@zag-js/core
Version:
A minimal implementation of xstate fsm for UI machines
154 lines (113 loc) • 5.3 kB
Markdown
# @zag-js/core
This package contains a minimal implementation of [XState FSM](https://github.com/statelyai/xstate) for **finite state
machines** with addition of extra features we need for our components.
## Features
- Finite states (non-nested)
- Initial state
- Transitions (object or strings)
- Context
- Entry actions
- Exit actions
- Delayed timeout actions (basically `setTimeout`)
- Delayed interval actions (basically `setInterval`)
- Transition actions
- Boolean guard helpers (`and`, `or`, `not`)
- Basic spawn helpers
- Activities (for state nodes)
> To better understand the state machines, we strongly recommend going though the
> [xstate docs](https://xstate.js.org/docs/) and videos. It'll give you the foundations you need.
## Quick start
**Installation**
```bash
npm i @zag-js/core
# or
yarn add @zag-js/core
```
**Usage (machine):**
```js
import { createMachine } from "@zag-js/core"
const toggleMachine = createMachine({
id: "toggle",
initialState() {
return "inactive"
},
states: {
inactive: { on: { TOGGLE: "active" } },
active: { on: { TOGGLE: "inactive" } },
},
})
toggleMachine.start()
console.log(toggleMachine.state.value) // => "inactive"
toggleMachine.send("TOGGLE")
console.log(toggleMachine.state.value) // => "active"
toggleMachine.send("TOGGLE")
console.log(toggleMachine.state.value) // => "inactive"
```
**Usage (service):**
```js
import { createMachine } from "@zag-js/core"
const toggleMachine = createMachine({...})
toggleMachine.start()
toggleService.subscribe((state) => {
console.log(state.value)
})
toggleService.send("TOGGLE")
toggleService.send("TOGGLE")
toggleService.stop()
```
## API
### `createMachine(config, options)`
Creates a new finite state machine from the config.
| Argument | Type | Description |
| --------- | ------------------ | ------------------------------------------- |
| `config` | object (see below) | The config object for creating the machine. |
| `options` | object (see below) | The optional options object. |
**Returns:**
A `Machine`, which provides:
- `machine.initialState`: the machine's resolved initial state
- `machine.start()`: the function to start the machine in the specified initial state.
- `machine.stop()`: the function to stop the machine completely. It also cleans up all scheduled actions and timeouts.
- `machine.transition(state, event)`: a transition function that returns the next state given the current `state` and
`event`. It also performs any delayed, entry or exit side-effects.
- `machine.send(event)`: a transition function instructs the machine to execute a transition based on the event.
- `machine.onTransition(fn)`: a function that gets called when the machine transition function instructs the machine to
execute a transition based on the event.
- `machine.onChange(fn)`: a function that gets called when the machine's context value changes.
- `machine.state`: the state object that describes the machine at a specific point in time. It contains the following
properties:
- `value`: the current state value
- `previousValue`: the previous state value
- `event`: the event that triggered the transition to the current state
- `nextEvents`: the list of events the machine can respond to at its current state
- `tags`: the tags associated with this state
- `done`: whether the machine that reached its final state
- `context`: the current context value
- `matches(...)`: a function used to test whether the current state matches one or more state values
The machine config has this schema:
### Machine config
- `id` (string) - an identifier for the type of machine this is. Useful for debugging.
- `context` (object) - the extended state data that represents quantitative data (string, number, objects, etc) that can
be modified in the machine.
- `initial` (string) - the key of the initial state.
- `states` (object) - an object mapping state names (keys) to states
- `on` (object) - an global mapping of event types to transitions. If specified, this event will called if the state
node doesn't handle the emitted event.
### State config
- `on` (object) - an object mapping event types (keys) to [transitions](#transition-config)
### Transition config
String syntax:
- (string) - the state name to transition to.
- Same as `{ target: stateName }`
Object syntax:
- `target` (string) - the state name to transition to.
- `actions` (Action | Action[]) - the [action(s)](#action-config) to execute when this transition is taken.
- `guard` (Guard) - the condition (predicate function) to test. If it returns `true`, the transition will be taken.
### Machine options
- `actions?` (object) - a lookup object for your string actions.
- `guards?` (object) - a lookup object for your string guards specified as `guard` in the machine.
- `activities?` (object) - a lookup object for your string activities.
- `delays?` (object) - a lookup object for your string delays used in `after` and `every` config.
### Action config
The action function to execute while transitioning from one state to another. It takes the following arguments:
- `context` (any) - the machine's current `context`.
- `event` (object) - the event that caused the action to be executed.