machina 7.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -60,17 +60,17 @@ light.dispose(); // tears down; all subsequent calls are silent no-ops
|
|
|
60
60
|
|
|
61
61
|
### Public API — `Fsm`
|
|
62
62
|
|
|
63
|
-
| Method | Description
|
|
64
|
-
| ---------------------------- |
|
|
65
|
-
| `handle(inputName, ...args)` | Dispatch an input to the current state's handler
|
|
66
|
-
| `canHandle(inputName)` | True if the current state
|
|
67
|
-
| `transition(toState)` | Directly transition; fires `_onExit`, `_onEnter`, lifecycle events
|
|
68
|
-
| `reset()` | Transition back to `initialState`
|
|
69
|
-
| `currentState()` | Returns the current state name
|
|
70
|
-
| `compositeState()` | Dot-delimited path including active child FSM states
|
|
71
|
-
| `on(eventName, callback)` | Subscribe to a lifecycle event (returns `{ off() }`)
|
|
72
|
-
| `emit(eventName, data?)` | Emit a custom event
|
|
73
|
-
| `dispose(options?)` | Permanently shut down; cascades to child FSMs by default
|
|
63
|
+
| Method | Description |
|
|
64
|
+
| ---------------------------- | ------------------------------------------------------------------------- |
|
|
65
|
+
| `handle(inputName, ...args)` | Dispatch an input to the current state's handler |
|
|
66
|
+
| `canHandle(inputName)` | True if the current state — or its `_child` chain — can handle this input |
|
|
67
|
+
| `transition(toState)` | Directly transition; fires `_onExit`, `_onEnter`, lifecycle events |
|
|
68
|
+
| `reset()` | Transition back to `initialState` |
|
|
69
|
+
| `currentState()` | Returns the current state name |
|
|
70
|
+
| `compositeState()` | Dot-delimited path including active child FSM states |
|
|
71
|
+
| `on(eventName, callback)` | Subscribe to a lifecycle event (returns `{ off() }`) |
|
|
72
|
+
| `emit(eventName, data?)` | Emit a custom event |
|
|
73
|
+
| `dispose(options?)` | Permanently shut down; cascades to child FSMs by default |
|
|
74
74
|
|
|
75
75
|
## `createBehavioralFsm`
|
|
76
76
|
|
|
@@ -188,6 +188,28 @@ uploader.compositeState(); // "idle"
|
|
|
188
188
|
|
|
189
189
|
The parent re-enters `initialState` of the child FSM whenever the parent transitions into the state that owns `_child`.
|
|
190
190
|
|
|
191
|
+
Delegation reaches any depth: `canHandle()` answers for the whole `_child` chain, so an input handled three levels down can be dispatched from the root. When both a descendant and an ancestor could handle an input, the descendant wins.
|
|
192
|
+
|
|
193
|
+
An FSM can also declare inputs it fires at itself but never handles — expecting whatever mounts it to catch them via bubbling:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
const phase = createFsm({
|
|
197
|
+
id: "phase",
|
|
198
|
+
initialState: "running",
|
|
199
|
+
context: {},
|
|
200
|
+
bubbles: ["phaseComplete"], // "I fire this; whoever mounts me must deal with it"
|
|
201
|
+
states: {
|
|
202
|
+
running: {
|
|
203
|
+
_onEnter() {
|
|
204
|
+
// ...later: phase.handle("phaseComplete") — typed, no handler here
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Declared bubbles join the FSM's typed input union, and they form a compile-time contract: a config that mounts `phase` via `_child` must handle `phaseComplete`, re-declare it in its own `bubbles`, or carry a `"*"` catch-all — otherwise it fails to compile, with the error naming what's missing. Standalone FSMs owe nothing; the contract only exists where FSMs get wired together. The engine never reads `bubbles` — it's purely type-level.
|
|
212
|
+
|
|
191
213
|
## Deferred input
|
|
192
214
|
|
|
193
215
|
Call `defer()` inside a handler to queue the current input for replay after the next transition. Pass `{ until: "stateName" }` to replay only on entry to a specific state.
|
package/package.json
CHANGED