Skip to content

Commit

Permalink
Update Node event handler to support multiple events (#8)
Browse files Browse the repository at this point in the history
* Update Node event handler to support multiple events

* update method parameters to use variadic tuple type
  • Loading branch information
brendantruleo authored Apr 1, 2024
1 parent 66f0646 commit c066edb
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export default class Node<C, E extends Event> {

/**
* Define an event handler for this state. The given `type` string must match
* a `type` from your statechart's [[Event]] type. The given [[EventHandler]]
* a `type`(s) from your statechart's [[Event]] type(s). The given [[EventHandler]]
* function can return an object with the following keys to control the
* behavior of the statechart:
*
Expand All @@ -211,13 +211,20 @@ export default class Node<C, E extends Event> {
* ```
*/
on<T extends E['type']>(
type: T,
handler: EventHandler<C, E, T> | string | string[],
...args: [T, ...T[], handler: EventHandler<C, E, T> | string | string[]]
): this {
this.handlers[type] =
typeof handler === 'string' || Array.isArray(handler)
? () => ({goto: handler})
: handler;
const types = args.slice(0, -1) as T[];
const handler = args[args.length - 1] as
| EventHandler<C, E, T>
| string
| string[];

for (const type of types) {
this.handlers[type] =
typeof handler === 'string' || Array.isArray(handler)
? () => ({ goto: handler })
: handler;
}
return this;
}

Expand Down
17 changes: 17 additions & 0 deletions src/Statechart.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,23 @@ describe('Statechart#send', () => {
});
});

it('allows multiple events to use the same handler', () => {
type Ctx = { fromEvt: string };
type Evt = {type: 'x'} | { type: 'y'};

const sc = new Statechart<Ctx, Evt>({ fromEvt: '' }, s => {
s.state('a', s => {
s.on('x', 'y', (ctx, evt) => ({ context: { ...ctx, fromEvt: evt.type }}));
});
});

let state = sc.send(sc.initialState, {type: 'x'});
expect(state.context.fromEvt).toEqual('x');

state = sc.send(state, {type: 'y'});
expect(state.context.fromEvt).toEqual('y');
})

it('handles concurrent states with the same child state names', () => {
type Ctx = {};
type Evt = {type: 'TOGGLE_X'};
Expand Down

0 comments on commit c066edb

Please sign in to comment.