All Projects → NullVoxPopuli → ember-statechart-component

NullVoxPopuli / ember-statechart-component

Licence: MIT license
Statecharts as components. No classes. Pure declarative state transitions.

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language
HTML
75241 projects

Projects that are alternatives of or similar to ember-statechart-component

ember-cli-string-helpers
Set of the String helpers extracted from DockYard's ember-composable-helpers.
Stars: ✭ 73 (+160.71%)
Mutual labels:  ember, emberjs
Guides Source
This repository contains the Ember.js Guides
Stars: ✭ 130 (+364.29%)
Mutual labels:  ember, emberjs
Ember Cli Foundation 6 Sass
Stars: ✭ 65 (+132.14%)
Mutual labels:  ember, emberjs
fire
An idiomatic micro-framework for building Ember.js compatible APIs with Go.
Stars: ✭ 56 (+100%)
Mutual labels:  ember, emberjs
Ember Cli Addon Docs
Easy, beautiful docs for your OSS Ember addons
Stars: ✭ 162 (+478.57%)
Mutual labels:  ember, emberjs
Ember Octane Vs Classic Cheat Sheet
A cheat sheet for converting classic Ember app to Octane
Stars: ✭ 48 (+71.43%)
Mutual labels:  ember, emberjs
Ember Cli Bundle Analyzer
Analyze the size and contents of your Ember app's bundles
Stars: ✭ 78 (+178.57%)
Mutual labels:  ember, emberjs
Ember Accessibility
An EmberJS addon to help identify accessibility violations during development
Stars: ✭ 29 (+3.57%)
Mutual labels:  ember, emberjs
Qunit Dom
High Level DOM Assertions for QUnit
Stars: ✭ 146 (+421.43%)
Mutual labels:  ember, emberjs
Awesome Ember
A curated list of awesome Ember.js stuff like addons, articles, videos, gists and more.
Stars: ✭ 140 (+400%)
Mutual labels:  ember, emberjs
vim-emberlayout
Open Ember files in a grid
Stars: ✭ 18 (-35.71%)
Mutual labels:  ember, emberjs
super-rentals-tutorial
No description or website provided.
Stars: ✭ 69 (+146.43%)
Mutual labels:  ember, emberjs
Docfy
Build fully personalized documentation sites; write content and demos in Markdown.
Stars: ✭ 48 (+71.43%)
Mutual labels:  ember, emberjs
Ember Api Docs
Ember API Docs viewer
Stars: ✭ 55 (+96.43%)
Mutual labels:  ember, emberjs
Mber
Fast and minimal Ember.js CLI alternative, without broccoli.
Stars: ✭ 30 (+7.14%)
Mutual labels:  ember, emberjs
Ember Styleguide
This is a UI addon that intends to help standardize the Ember family of websites and make it easier to make the Ember website an Ember app.
Stars: ✭ 69 (+146.43%)
Mutual labels:  ember, emberjs
Pretzel
Javascript full-stack framework for Big Data visualisation and analysis
Stars: ✭ 26 (-7.14%)
Mutual labels:  ember, emberjs
Ember Inspector
Adds an Ember tab to the browser's Developer Tools that allows you to inspect Ember objects in your application.
Stars: ✭ 936 (+3242.86%)
Mutual labels:  ember, emberjs
Super Rentals
Codebase for the Super Rentals official tutorial
Stars: ✭ 134 (+378.57%)
Mutual labels:  ember, emberjs
Library App
Detailed Ember.js Octane v3.21 tutorial for absolute beginners. https://yoember.com
Stars: ✭ 189 (+575%)
Mutual labels:  ember, emberjs

ember-statechart-component

CI npm version

Use XState Machines as components.

Installation

ember install ember-statechart-component
# or
npm install ember-statechart-component
# or
yarn add ember-statechart-component

To be able to use XState state.matches method in our templates, we will first need [email protected]+ or a HelperManager for handling vanilla functions. ember-functions-as-helper-polyfill provides one:

ember install ember-functions-as-helper-polyfill
# or
npm install ember-functions-as-helper-polyfill
# or
yarn add ember-functions-as-helper-polyfill

In app/app.js / app/app.ts, a one time setup function will need to be called so that the ComponentManager is registered.

import Application from '@ember/application';

import config from 'ember-app/config/environment';
import loadInitializers from 'ember-load-initializers';
import Resolver from 'ember-resolver';

import { setupComponentMachines } 'ember-statechart-component';

export default class App extends Application {
  modulePrefix = config.modulePrefix;
  podModulePrefix = config.podModulePrefix;
  Resolver = Resolver;
}

loadInitializers(App, config.modulePrefix);

setupComponentMachines();

Usage

Example with Ember Octane

// app/components/toggle.js
import { createMachine } from 'xstate';

export default createMachine({
  initial: 'inactive',
  states: {
    inactive: { on: { TOGGLE: 'active' } },
    active: { on: { TOGGLE: 'inactive' } },
  },
});

Usage:

<Toggle as |state send|>
  {{state.value}}

  <button {{on 'click' (fn send 'TOGGLE')}}>
    Toggle
  </button>
</Toggle>

The default template for every createMachine(..) is

{{yield this.state this.send}}

but that can be overriden to suit your needs by defining your own template. The this is an instance of the XState Interpreter

Accessing EmberJS Services

// app/components/authenticated-toggle.js
import { getService } from 'ember-statechart-component';
import { createMachine } from 'xstate';

export default createMachine({
  initial: 'inactive',
  states: {
    inactive: {
      on: {
        TOGGLE: [
          {
            target: 'active',
            cond: 'isAuthenticated',
          },
          { actions: ['notify'] },
        ],
      },
    },
    active: { on: { TOGGLE: 'inactive' } },
  },
}, {
  actions: {
    notify: (ctx) => {
      getService(ctx, 'toasts').notify('You must be logged in');
    },
  },
  guards: {
    isAuthenticated: (ctx) => getService(ctx, 'session').isAuthenticated,
  },
});

Usage:

<AuthenticatedToggle as |state send|>
  {{state.value}}

  <button {{on 'click' (fn send 'TOGGLE')}}>
    Toggle
  </button>
</AuthenticatedToggle>

Matching States

<Toggle as |state send|>
  {{#if (state.matches 'inactive')}}
    The inactive state
  {{else if (state.matches 'active')}}
    The active state
  {{else}}
    Unknown state
  {{/if}}

  <button {{on 'click' (fn send 'TOGGLE')}}>
    Toggle
  </button>
</Toggle>

Glint

Having type checking with these state machines can be done automatically after importing the /glint file in your types/<app-name>/glint-registry.d.ts.

import "@glint/environment-ember-loose";
import "@glint/environment-ember-loose/native-integration";
import "ember-page-title/glint";

// This import extends the type of `StateMachine` to be glint-compatible
import 'ember-statechart-component/glint';

declare module "@glint/environment-ember-loose/registry" {
  export default interface Registry {
    // How to define globals from external addons
  }
}

API

@config

This argument allows you to pass a MachineOptions for actions, services, guards, etc.

Usage:

Toggle machine that needs a config
// app/components/toggle.js
import { createMachine, assign } from 'xstate';

export default createMachine({
  initial: 'inactive',
  states: {
    inactive: { on: { TOGGLE: 'active' } },
    active: {
      on: {
        TOGGLE: {
          target: 'inactive',
          actions: ['toggleIsOn']
        }
      }
    },
  },
});
<Toggle
  @config={{hash
    actions=(hash
      toggleIsOn=@onRoomIlluminated
    )
  }}
as |state send|>
  <button {{on 'click' (fn send 'TOGGLE')}}>
    Toggle
  </button>
</Toggle>

@context

Sets the initial context. The current value of the context can then be accessed via state.context.

Usage:

Toggle machine that interacts with context
// app/components/toggle.js
import { createMachine, assign } from 'xstate';

export default createMachine({
  initial: 'inactive',
  states: {
    inactive: {
      on: {
        TOGGLE: {
          target: 'active',
          actions: ['increaseCounter']
        }
      }
    },
    active: {
      on: {
        TOGGLE: {
          target: 'inactive',
          actions: ['increaseCounter']
        }
      }
    },
  },
}, {
  actions: {
    increaseCounter: assign({
      counter: (context) => context.counter + 1
    })
  }
});
<Toggle @context=(hash counter=0) as |state send|>
  <button {{on 'click' (fn send 'TOGGLE')}}>
    Toggle
  </button>

  <p>
    Toggled: {{state.context.counter}} times.
  </p>
</Toggle>

@state

The machine will use @state as the initial state. Any changes to this argument are not automatically propagated to the machine. An ARGS_UPDATE event (see details below) is sent instead.

What happens if any of the passed args change?

An event will be sent to the machine for you, ARGS_UPDATE, along with all named arguments used to invoke the component.

Compatibility

  • ember-source v3.28+
  • typescript v4.5+
  • ember-auto-import v2+
  • A browser that supports Proxy
  • Glint 0.8.3+
    • Note that updates to glint support will not be covered by this library's adherance to SemVer. All glint-related updates will be bugfixes until Glint is declared stable.

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].