@hkdigital/lib-core 0.4.25 → 0.4.26

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.
@@ -13,6 +13,19 @@ export default class AudioScene {
13
13
  loaded: boolean;
14
14
  muted: boolean;
15
15
  targetGain: number;
16
+ /**
17
+ * Get audio scene loading progress
18
+ */
19
+ get progress(): {
20
+ totalBytesLoaded: number;
21
+ totalSize: number;
22
+ sourcesLoaded: number;
23
+ numberOfSources: number;
24
+ };
25
+ /**
26
+ * Start loading all audio sources
27
+ */
28
+ load(): void;
16
29
  destroy(): void;
17
30
  /**
18
31
  * Add in-memory audio source
@@ -28,16 +41,6 @@ export default class AudioScene {
28
41
  url: string;
29
42
  config?: SourceConfig;
30
43
  }): void;
31
- /**
32
- * Start loading all audio sources
33
- */
34
- load(): void;
35
- /**
36
- * Set an audio context to use
37
- *
38
- * @param {AudioContext} [audioContext]
39
- */
40
- setAudioContext(audioContext?: AudioContext): void;
41
44
  /**
42
45
  * Get a source that can be used to play the audio once
43
46
  *
@@ -46,6 +49,12 @@ export default class AudioScene {
46
49
  * @returns {Promise<AudioBufferSourceNode>}
47
50
  */
48
51
  getSourceNode(label: string): Promise<AudioBufferSourceNode>;
52
+ /**
53
+ * Set an audio context to use
54
+ *
55
+ * @param {AudioContext} [audioContext]
56
+ */
57
+ setAudioContext(audioContext?: AudioContext): void;
49
58
  /**
50
59
  * Set target gain
51
60
  *
@@ -5,10 +5,7 @@ import { LoadingStateMachine } from '../../../state/machines.js';
5
5
  import {
6
6
  STATE_INITIAL,
7
7
  STATE_LOADING,
8
- STATE_UNLOADING,
9
8
  STATE_LOADED,
10
- STATE_CANCELLED,
11
- STATE_ERROR,
12
9
  LOAD,
13
10
  LOADED
14
11
  } from '../../../state/machines.js';
@@ -30,10 +27,9 @@ import AudioLoader from './AudioLoader.svelte.js';
30
27
  export default class AudioScene {
31
28
  #state = new LoadingStateMachine();
32
29
 
33
- // @note this exported state is set by $effect's
30
+ // @note this exported state is set by onenter
34
31
  state = $state(STATE_INITIAL);
35
32
 
36
- // @note this exported state is set by $effect's
37
33
  loaded = $derived.by(() => {
38
34
  return this.state === STATE_LOADED;
39
35
  });
@@ -109,47 +105,33 @@ export default class AudioScene {
109
105
  }
110
106
  });
111
107
 
112
- $effect(() => {
113
- switch (state.current) {
114
- case STATE_LOADING:
115
- {
116
- // console.log('AudioScene:loading');
117
- this.#startLoading();
118
- }
119
- break;
120
-
121
- case STATE_UNLOADING:
122
- {
123
- // console.log('AudioScene:unloading');
124
- // this.#startUnLoading();
125
- }
126
- break;
127
-
128
- case STATE_LOADED:
129
- {
130
- // console.log('AudioScene:loaded');
131
-
132
- // tODO
133
- // this.#abortLoading = null;
134
- }
135
- break;
136
-
137
- case STATE_CANCELLED:
138
- {
139
- // console.log('AudioScene:cancelled');
140
- // TODO
141
- }
142
- break;
143
-
144
- case STATE_ERROR:
145
- {
146
- console.error('AudioScene:error', state.error);
147
- }
148
- break;
149
- } // end switch
108
+ state.onenter = ( currentState ) => {
109
+ // console.log('onenter', currentState );
110
+
111
+ if(currentState === STATE_LOADING )
112
+ {
113
+ // console.log('AudioScene:loading');
114
+ this.#startLoading();
115
+ }
150
116
 
151
117
  this.state = state.current;
152
- });
118
+ };
119
+ }
120
+
121
+ /* ==== Common loader interface */
122
+
123
+ /**
124
+ * Get audio scene loading progress
125
+ */
126
+ get progress() {
127
+ return this.#progress;
128
+ }
129
+
130
+ /**
131
+ * Start loading all audio sources
132
+ */
133
+ load() {
134
+ this.#state.send(LOAD);
153
135
  }
154
136
 
155
137
  destroy() {
@@ -157,6 +139,8 @@ export default class AudioScene {
157
139
  // TODO: Unload AUdioLoaders?
158
140
  }
159
141
 
142
+ /* ==== Source definitions */
143
+
160
144
  /**
161
145
  * Add in-memory audio source
162
146
  * - Uses an AudioLoader instance to load audio data from network
@@ -175,36 +159,7 @@ export default class AudioScene {
175
159
  this.#memorySources.push({ label, audioLoader, config });
176
160
  }
177
161
 
178
- /**
179
- * Start loading all audio sources
180
- */
181
- load() {
182
- this.#state.send(LOAD);
183
-
184
- // FIXME: in unit test when moved to startloading it hangs!
185
-
186
- for (const { audioLoader } of this.#memorySources) {
187
- audioLoader.load();
188
- }
189
- }
190
-
191
- /**
192
- * Set an audio context to use
193
- *
194
- * @param {AudioContext} [audioContext]
195
- */
196
- setAudioContext( audioContext ) {
197
- this.#audioContext = audioContext;
198
- }
199
-
200
- async #startLoading() {
201
- // console.log('#startLoading');
202
-
203
- // FIXME: in unit test when moved to startloading it hangs!
204
- // for (const { audioLoader } of this.#memorySources) {
205
- // audioLoader.load();
206
- // }
207
- }
162
+ /* ==== Resource access */
208
163
 
209
164
  /**
210
165
  * Get a source that can be used to play the audio once
@@ -240,6 +195,25 @@ export default class AudioScene {
240
195
  return sourceNode;
241
196
  }
242
197
 
198
+ /**
199
+ * Set an audio context to use
200
+ *
201
+ * @param {AudioContext} [audioContext]
202
+ */
203
+ setAudioContext( audioContext ) {
204
+ this.#audioContext = audioContext;
205
+ }
206
+
207
+ async #startLoading() {
208
+ // console.log('#startLoading');
209
+
210
+ for (const { audioLoader } of this.#memorySources) {
211
+ audioLoader.load();
212
+ }
213
+ }
214
+
215
+ /* ==== Audio specific */
216
+
243
217
  /**
244
218
  * Set target gain
245
219
  *
@@ -281,6 +255,7 @@ export default class AudioScene {
281
255
  this.setTargetGain(this.#unmutedTargetGain);
282
256
  }
283
257
 
258
+ /* ==== Internals */
284
259
 
285
260
  #getGainNode()
286
261
  {
@@ -322,4 +297,4 @@ export default class AudioScene {
322
297
 
323
298
  throw new Error(`Source [${label}] has not been defined`);
324
299
  }
325
- }
300
+ } // end class
@@ -10,6 +10,19 @@
10
10
  export default class ImageScene {
11
11
  state: string;
12
12
  loaded: boolean;
13
+ /**
14
+ * Get image scene loading progress
15
+ */
16
+ get progress(): {
17
+ totalBytesLoaded: number;
18
+ totalSize: number;
19
+ sourcesLoaded: number;
20
+ numberOfSources: number;
21
+ };
22
+ /**
23
+ * Start loading all image sources
24
+ */
25
+ load(): void;
13
26
  destroy(): void;
14
27
  /**
15
28
  * Add image source
@@ -23,19 +36,6 @@ export default class ImageScene {
23
36
  label: string;
24
37
  imageSource: import("../../../config/typedef.js").ImageSource;
25
38
  }): void;
26
- /**
27
- * Start loading all image sources
28
- */
29
- load(): void;
30
- /**
31
- * Get image scene loading progress
32
- */
33
- get progress(): {
34
- totalBytesLoaded: number;
35
- totalSize: number;
36
- sourcesLoaded: number;
37
- numberOfSources: number;
38
- };
39
39
  /**
40
40
  * Get an image loader
41
41
  *
@@ -7,10 +7,7 @@ import { LoadingStateMachine } from '../../../state/machines.js';
7
7
  import {
8
8
  STATE_INITIAL,
9
9
  STATE_LOADING,
10
- STATE_UNLOADING,
11
10
  STATE_LOADED,
12
- STATE_CANCELLED,
13
- STATE_ERROR,
14
11
  LOAD,
15
12
  LOADED
16
13
  } from '../../../state/machines.js';
@@ -31,10 +28,9 @@ import ImageLoader from './ImageLoader.svelte.js';
31
28
  export default class ImageScene {
32
29
  #state = new LoadingStateMachine();
33
30
 
34
- // @note this exported state is set by $effect's
31
+ // @note this exported state is set by onenter
35
32
  state = $state(STATE_INITIAL);
36
33
 
37
- // @note this exported state is set by $effect's
38
34
  loaded = $derived.by(() => {
39
35
  return this.state === STATE_LOADED;
40
36
  });
@@ -92,55 +88,42 @@ export default class ImageScene {
92
88
  }
93
89
  } );
94
90
 
95
- state.onenter = ( state ) => {
96
- // console.log('onenter', state );
97
-
98
- switch (state) {
99
- case STATE_LOADING:
100
- {
101
- // console.log('ImageScene:loading');
102
- this.#startLoading();
103
- }
104
- break;
105
-
106
- case STATE_UNLOADING:
107
- {
108
- // console.log('ImageScene:unloading');
109
- // this.#startUnLoading();
110
- }
111
- break;
112
-
113
- case STATE_LOADED:
114
- {
115
- // console.log('ImageScene:loaded');
116
- // TODO
117
- // this.#abortLoading = null;
118
- }
119
- break;
120
-
121
- case STATE_CANCELLED:
122
- {
123
- // console.log('ImageScene:cancelled');
124
- // TODO
125
- }
126
- break;
127
-
128
- case STATE_ERROR:
129
- {
130
- console.log('ImageScene:error', state);
131
- }
132
- break;
133
- } // end switch
134
-
135
- this.state = state;
91
+ state.onenter = ( currentState ) => {
92
+ // console.log('onenter', currentState );
93
+
94
+ if(currentState === STATE_LOADING )
95
+ {
96
+ // console.log('ImageScene:loading');
97
+ this.#startLoading();
98
+ }
99
+
100
+ this.state = currentState;
136
101
  };
137
102
  }
138
103
 
104
+ /* ==== Common loader interface */
105
+
106
+ /**
107
+ * Get image scene loading progress
108
+ */
109
+ get progress() {
110
+ return this.#progress;
111
+ }
112
+
113
+ /**
114
+ * Start loading all image sources
115
+ */
116
+ load() {
117
+ this.#state.send(LOAD);
118
+ }
119
+
139
120
  destroy() {
140
121
  // TODO: disconnect all image sources?
141
122
  // TODO: Unload ImageLoaders?
142
123
  }
143
124
 
125
+ /* ==== Source definitions */
126
+
144
127
  /**
145
128
  * Add image source
146
129
  * - Uses an ImageLoader instance to load image data from network
@@ -159,42 +142,7 @@ export default class ImageScene {
159
142
  this.#imageSources.push({ label, imageLoader });
160
143
  }
161
144
 
162
- /**
163
- * Start loading all image sources
164
- */
165
- load() {
166
- this.#state.send(LOAD);
167
- }
168
-
169
- async #startLoading() {
170
- for (const { imageLoader } of this.#imageSources) {
171
- imageLoader.load();
172
- }
173
- }
174
-
175
- /**
176
- * Get Image source
177
- *
178
- * @param {string} label
179
- *
180
- * @returns {ImageSceneSource}
181
- */
182
- #getImageSceneSource(label) {
183
- for (const source of this.#imageSources) {
184
- if (label === source.label) {
185
- return source;
186
- }
187
- }
188
-
189
- throw new Error(`Source [${label}] has not been defined`);
190
- }
191
-
192
- /**
193
- * Get image scene loading progress
194
- */
195
- get progress() {
196
- return this.#progress;
197
- }
145
+ /* ==== Resource access */
198
146
 
199
147
  /**
200
148
  * Get an image loader
@@ -236,4 +184,29 @@ export default class ImageScene {
236
184
 
237
185
  return source.imageLoader.getObjectURL();
238
186
  }
239
- }
187
+
188
+ async #startLoading() {
189
+ for (const { imageLoader } of this.#imageSources) {
190
+ imageLoader.load();
191
+ }
192
+ }
193
+
194
+ /* ==== Internals */
195
+
196
+ /**
197
+ * Get Image source
198
+ *
199
+ * @param {string} label
200
+ *
201
+ * @returns {ImageSceneSource}
202
+ */
203
+ #getImageSceneSource(label) {
204
+ for (const source of this.#imageSources) {
205
+ if (label === source.label) {
206
+ return source;
207
+ }
208
+ }
209
+
210
+ throw new Error(`Source [${label}] has not been defined`);
211
+ }
212
+ } // end class
@@ -90,10 +90,6 @@ export default class NetworkLoader {
90
90
  const state = this._state;
91
91
  // const progress = this.progress;
92
92
 
93
- //
94
- // ISSUE: $effect is not triggered by this._state changes,
95
- // using onenter instead
96
- //
97
93
  this._state.onenter = () => {
98
94
  switch (state.current) {
99
95
  case STATE_LOADING:
@@ -1,4 +1,4 @@
1
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
1
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
2
2
  /** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
3
3
  /** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
4
4
  /**
@@ -50,7 +50,7 @@ export default class FiniteStateMachine extends EventEmitter {
50
50
  get current(): any;
51
51
  #private;
52
52
  }
53
- export type StateTransitionMetadata = import("./typedef.js").StateTransitionMetadata;
53
+ export type TransitionData = import("./typedef.js").TransitionData;
54
54
  export type OnEnterCallback = import("./typedef.js").OnEnterCallback;
55
55
  export type OnExitCallback = import("./typedef.js").OnExitCallback;
56
56
  import EventEmitter from '../../../generic/events/classes/EventEmitter.js';
@@ -8,7 +8,7 @@ import { isTestEnv } from '../../../util/env.js';
8
8
  import EventEmitter from '../../../generic/events/classes/EventEmitter.js';
9
9
  import { ENTER, EXIT } from './constants.js';
10
10
 
11
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
11
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
12
12
  /** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
13
13
  /** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
14
14
 
@@ -57,17 +57,17 @@ export default class FiniteStateMachine extends EventEmitter {
57
57
  this.states = states;
58
58
 
59
59
  // synthetically trigger _enter for the initial state.
60
- const initialMetadata = {
60
+ const initialTransitionData = {
61
61
  from: null,
62
62
  to: initial,
63
63
  event: null,
64
64
  args: []
65
65
  };
66
66
 
67
- this.#executeAction('_enter', initialMetadata);
67
+ this.#executeAction('_enter', initialTransitionData);
68
68
 
69
69
  // Emit ENTER event for external listeners for initial state
70
- this.emit(ENTER, { state: initial, metadata: initialMetadata });
70
+ this.emit(ENTER, { state: initial, transition: initialTransitionData });
71
71
  }
72
72
 
73
73
  /**
@@ -78,24 +78,24 @@ export default class FiniteStateMachine extends EventEmitter {
78
78
  * @param {any[]} [args]
79
79
  */
80
80
  #transition(newState, event, args) {
81
- /** @type {StateTransitionMetadata} */
82
- const metadata = { from: this.#current, to: newState, event, args };
81
+ /** @type {TransitionData} */
82
+ const transition = { from: this.#current, to: newState, event, args };
83
83
 
84
84
  // Call onexit callback before leaving current state
85
- this.onexit?.(this.#current, metadata);
85
+ this.onexit?.(this.#current, transition);
86
86
 
87
87
  // Emit EXIT event for external listeners
88
- this.emit(EXIT, { state: this.#current, metadata });
88
+ this.emit(EXIT, { state: this.#current, transition });
89
89
 
90
- this.#executeAction('_exit', metadata);
90
+ this.#executeAction('_exit', transition);
91
91
  this.#current = newState;
92
- this.#executeAction('_enter', metadata);
92
+ this.#executeAction('_enter', transition);
93
93
 
94
94
  // Emit ENTER event for external listeners
95
- this.emit(ENTER, { state: newState, metadata });
95
+ this.emit(ENTER, { state: newState, transition });
96
96
 
97
97
  // Call onenter callback after state change
98
- this.onenter?.(newState, metadata);
98
+ this.onenter?.(newState, transition);
99
99
  }
100
100
 
101
101
  /**
@@ -116,7 +116,7 @@ export default class FiniteStateMachine extends EventEmitter {
116
116
  if (isLifecycleFnMeta(args[0])) {
117
117
  return action(args[0]);
118
118
  } else {
119
- throw new Error(`Invalid metadata passed to lifecycle function`);
119
+ throw new Error(`Invalid transition data passed to lifecycle function`);
120
120
  }
121
121
 
122
122
  // Normal state events
@@ -56,16 +56,16 @@ Each state can define:
56
56
  ```javascript
57
57
  const machine = new FiniteStateMachine('idle', {
58
58
  idle: {
59
- _enter: (metadata) => {
59
+ _enter: (transition) => {
60
60
  console.log('Entered idle state');
61
61
  },
62
- _exit: (metadata) => {
62
+ _exit: (transition) => {
63
63
  console.log('Leaving idle state');
64
64
  },
65
65
  start: 'running'
66
66
  },
67
67
  running: {
68
- _enter: (metadata) => {
68
+ _enter: (transition) => {
69
69
  console.log('Started running');
70
70
  },
71
71
  stop: 'idle'
@@ -73,14 +73,14 @@ const machine = new FiniteStateMachine('idle', {
73
73
  });
74
74
  ```
75
75
 
76
- ## Callback Metadata
76
+ ## Callback TransitionData
77
77
 
78
- Enter and exit callbacks receive metadata about the transition:
78
+ Enter and exit callbacks receive transition data about the state change:
79
79
 
80
80
  ```javascript
81
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
81
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
82
82
 
83
- // Metadata structure:
83
+ // TransitionData structure:
84
84
  {
85
85
  from: 'previousState', // State being exited
86
86
  to: 'newState', // State being entered
@@ -94,18 +94,18 @@ Enter and exit callbacks receive metadata about the transition:
94
94
  For better type safety, import the type definitions:
95
95
 
96
96
  ```javascript
97
- /** @typedef {import('./typedef.js').StateTransitionMetadata} StateTransitionMetadata */
97
+ /** @typedef {import('./typedef.js').TransitionData} TransitionData */
98
98
  /** @typedef {import('./typedef.js').OnEnterCallback} OnEnterCallback */
99
99
  /** @typedef {import('./typedef.js').OnExitCallback} OnExitCallback */
100
100
 
101
101
  /** @type {OnEnterCallback} */
102
- const handleEnter = (state, metadata) => {
103
- console.log(`Entering ${state} from ${metadata.from}`);
102
+ const handleEnter = (currentState, transition) => {
103
+ console.log(`Entering ${currentState} from ${transition.from}`);
104
104
  };
105
105
 
106
106
  /** @type {OnExitCallback} */
107
- const handleExit = (state, metadata) => {
108
- console.log(`Leaving ${state} to ${metadata.to}`);
107
+ const handleExit = (currentState, transition) => {
108
+ console.log(`Leaving ${currentState} to ${transition.to}`);
109
109
  };
110
110
 
111
111
  machine.onenter = handleEnter;
@@ -209,8 +209,8 @@ const machine = new FiniteStateMachine('idle', {
209
209
  error: { retry: 'loading', reset: 'idle' }
210
210
  });
211
211
 
212
- machine.onexit = (state, metadata) => {
213
- switch (state) {
212
+ machine.onexit = (currentState, transition) => {
213
+ switch (currentState) {
214
214
  case 'loading':
215
215
  console.log('Leaving loading state...');
216
216
  // Cancel ongoing requests
@@ -224,8 +224,8 @@ machine.onexit = (state, metadata) => {
224
224
  }
225
225
  };
226
226
 
227
- machine.onenter = (state, metadata) => {
228
- switch (state) {
227
+ machine.onenter = (currentState, transition) => {
228
+ switch (currentState) {
229
229
  case 'loading':
230
230
  console.log('Started loading...');
231
231
  showSpinner();
@@ -236,7 +236,7 @@ machine.onenter = (state, metadata) => {
236
236
  break;
237
237
  case 'error':
238
238
  console.log('Loading failed');
239
- showError(metadata.args[0]);
239
+ showError(transition.args[0]);
240
240
  break;
241
241
  }
242
242
  };
@@ -264,8 +264,8 @@ const machine = new FiniteStateMachine('idle', {
264
264
  }
265
265
  });
266
266
 
267
- machine.onexit = (state) => console.log(`3. onexit ${state}`);
268
- machine.onenter = (state) => console.log(`6. onenter ${state}`);
267
+ machine.onexit = (currentState) => console.log(`3. onexit ${currentState}`);
268
+ machine.onenter = (currentState) => console.log(`6. onenter ${currentState}`);
269
269
 
270
270
  // Initial state triggers _enter and onenter
271
271
  // Output:
@@ -313,8 +313,8 @@ machine.onexit = (state) => {
313
313
  }
314
314
  };
315
315
 
316
- machine.onenter = (state) => {
317
- switch (state) {
316
+ machine.onenter = (label) => {
317
+ switch (label) {
318
318
  case 'loading':
319
319
  this.#startProcess(); // Start async process immediately
320
320
  break;
@@ -381,8 +381,8 @@ export default class TaskProcessor {
381
381
 
382
382
  constructor() {
383
383
  // onexit: Handle cleanup when leaving states
384
- this.#machine.onexit = (state) => {
385
- switch (state) {
384
+ this.#machine.onexit = (currentState) => {
385
+ switch (currentState) {
386
386
  case 'processing':
387
387
  this.#cancelTasks(); // Cancel ongoing tasks if interrupted
388
388
  break;
@@ -390,8 +390,8 @@ export default class TaskProcessor {
390
390
  };
391
391
 
392
392
  // onenter: Handle immediate state actions
393
- this.#machine.onenter = (state) => {
394
- switch (state) {
393
+ this.#machine.onenter = (currentState) => {
394
+ switch (currentState) {
395
395
  case 'processing':
396
396
  this.#startAllTasks(); // Start processing immediately
397
397
  break;
@@ -399,7 +399,7 @@ export default class TaskProcessor {
399
399
  this.#notifyComplete(); // Cleanup/notify when done
400
400
  break;
401
401
  }
402
- this.state = state;
402
+ this.state = currentState;
403
403
  };
404
404
 
405
405
  // $effect: Monitor reactive completion
@@ -435,8 +435,8 @@ export default class TaskProcessor {
435
435
  });
436
436
 
437
437
  // Handle state-specific actions
438
- machine.onexit = (state) => {
439
- switch (state) {
438
+ machine.onexit = (currentState) => {
439
+ switch (currentState) {
440
440
  case 'loading':
441
441
  // Cancel any ongoing requests
442
442
  cancelRequests();
@@ -444,8 +444,8 @@ export default class TaskProcessor {
444
444
  }
445
445
  };
446
446
 
447
- machine.onenter = (state) => {
448
- switch (state) {
447
+ machine.onenter = (currentState) => {
448
+ switch (currentState) {
449
449
  case 'loading':
450
450
  loadData();
451
451
  break;
@@ -526,7 +526,7 @@ const auth = new FiniteStateMachine('anonymous', {
526
526
  failure: 'anonymous'
527
527
  },
528
528
  authenticated: {
529
- _enter: (meta) => console.log('Welcome!'),
529
+ _enter: (transition) => console.log('Welcome!'),
530
530
  logout: 'anonymous',
531
531
  expire: 'anonymous'
532
532
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Metadata object passed to state transition callbacks
3
3
  */
4
- export type StateTransitionMetadata = {
4
+ export type TransitionData = {
5
5
  /**
6
6
  * - The state being exited
7
7
  */
@@ -22,8 +22,8 @@ export type StateTransitionMetadata = {
22
22
  /**
23
23
  * Callback function called when entering a state
24
24
  */
25
- export type OnEnterCallback = (arg0: string, arg1: StateTransitionMetadata) => void;
25
+ export type OnEnterCallback = (currentState: string, transition: TransitionData) => void;
26
26
  /**
27
27
  * Callback function called when exiting a state
28
28
  */
29
- export type OnExitCallback = (arg0: string, arg1: StateTransitionMetadata) => void;
29
+ export type OnExitCallback = (currentState: string, transition: TransitionData) => void;
@@ -5,24 +5,30 @@
5
5
  /**
6
6
  * Metadata object passed to state transition callbacks
7
7
  *
8
- * @typedef {object} StateTransitionMetadata
8
+ * @typedef {object} TransitionData
9
9
  * @property {string} from - The state being exited
10
10
  * @property {string} to - The state being entered
11
11
  * @property {string} event - The event that triggered the transition
12
12
  * @property {any[]} args - Arguments passed to the send() method
13
13
  */
14
14
 
15
- /**
16
- * Callback function called when entering a state
17
- *
18
- * @typedef {function(string, StateTransitionMetadata): void} OnEnterCallback
19
- */
15
+ /**
16
+ * Callback function called when entering a state
17
+ *
18
+ * @callback OnEnterCallback
19
+ * @param {string} currentState - The state being entered
20
+ * @param {TransitionData} transition - Details about the transition
21
+ * @returns {void}
22
+ */
20
23
 
21
- /**
22
- * Callback function called when exiting a state
23
- *
24
- * @typedef {function(string, StateTransitionMetadata): void} OnExitCallback
25
- */
24
+ /**
25
+ * Callback function called when exiting a state
26
+ *
27
+ * @callback OnExitCallback
28
+ * @param {string} currentState - The state being exited
29
+ * @param {TransitionData} transition - Details about the transition
30
+ * @returns {void}
31
+ */
26
32
 
27
- // Export types for external use (this is just for JSDoc, no actual exports needed)
33
+ // Export types for JSdoc
28
34
  export {};
@@ -108,8 +108,8 @@ The `onenter` callback provides a reliable way to react to state changes, design
108
108
  ```javascript
109
109
  const loader = new LoadingStateMachine();
110
110
 
111
- loader.onenter = (state) => {
112
- switch (state) {
111
+ loader.onenter = (currentState) => {
112
+ switch (currentState) {
113
113
  case STATE_LOADING:
114
114
  console.log('Started loading...');
115
115
  showSpinner();
@@ -141,8 +141,8 @@ $effect(() => {
141
141
  });
142
142
 
143
143
  // onenter catches every transition
144
- loader.onenter = (state) => {
145
- console.log(state); // Sees every state change
144
+ loader.onenter = (currentState) => {
145
+ console.log(currentState); // Sees every state change
146
146
  };
147
147
  ```
148
148
 
@@ -188,8 +188,8 @@ const timeoutId = setTimeout(() => {
188
188
  }
189
189
  }, 10000); // 10 second timeout
190
190
 
191
- loader.onenter = (state) => {
192
- switch (state) {
191
+ loader.onenter = (currentState) => {
192
+ switch (currentState) {
193
193
  case STATE_TIMEOUT:
194
194
  console.log('Loading timed out');
195
195
  showRetryButton();
@@ -220,8 +220,8 @@ LoadingStateMachine inherits the `onenter` callback and Svelte reactivity integr
220
220
  ```javascript
221
221
  const loader = new LoadingStateMachine();
222
222
 
223
- loader.onenter = (state) => {
224
- switch (state) {
223
+ loader.onenter = (currentState) => {
224
+ switch (currentState) {
225
225
  case STATE_LOADING:
226
226
  this.#startLoading(); // Start async process immediately
227
227
  break;
@@ -267,8 +267,8 @@ export default class MultiSourceLoader {
267
267
 
268
268
  constructor() {
269
269
  // Handle immediate loading state actions
270
- this.#loader.onenter = (state) => {
271
- switch (state) {
270
+ this.#loader.onenter = (currentState) => {
271
+ switch (currentState) {
272
272
  case STATE_LOADING:
273
273
  this.#startAllSources();
274
274
  break;
@@ -282,7 +282,7 @@ export default class MultiSourceLoader {
282
282
  this.#handleTimeout();
283
283
  break;
284
284
  }
285
- this.state = state;
285
+ this.state = currentState;
286
286
  };
287
287
 
288
288
  // Monitor reactive completion
@@ -319,8 +319,8 @@ export default class MultiSourceLoader {
319
319
  const loader = new LoadingStateMachine();
320
320
  let data = $state(null);
321
321
 
322
- loader.onenter = (state) => {
323
- if (state === STATE_LOADING) {
322
+ loader.onenter = (currentState) => {
323
+ if (currentState === STATE_LOADING) {
324
324
  loadData();
325
325
  }
326
326
  };
@@ -371,8 +371,8 @@ export default class MultiSourceLoader {
371
371
  const loader = new LoadingStateMachine();
372
372
  let abortController = null;
373
373
 
374
- loader.onenter = (state) => {
375
- switch (state) {
374
+ loader.onenter = (currentState) => {
375
+ switch (currentState) {
376
376
  case STATE_LOADING:
377
377
  startLoad();
378
378
  break;
@@ -426,8 +426,8 @@ export default class MultiSourceLoader {
426
426
 
427
427
  ```javascript
428
428
  // ✅ Good - use onenter for reliable side effects
429
- loader.onenter = (state) => {
430
- if (state === STATE_LOADING) {
429
+ loader.onenter = (currentState) => {
430
+ if (currentState === STATE_LOADING) {
431
431
  analytics.track('loading_started');
432
432
  }
433
433
  };
@@ -443,8 +443,8 @@ $effect(() => {
443
443
  ### 2. Handle All Error States
444
444
 
445
445
  ```javascript
446
- loader.onenter = (state) => {
447
- switch (state) {
446
+ loader.onenter = (currentState) => {
447
+ switch (currentState) {
448
448
  case STATE_ERROR:
449
449
  showErrorToast(loader.error.message);
450
450
  logError(loader.error);
@@ -459,8 +459,8 @@ loader.onenter = (state) => {
459
459
  ### 3. Implement Proper Cleanup
460
460
 
461
461
  ```javascript
462
- loader.onenter = (state) => {
463
- switch (state) {
462
+ loader.onenter = (currentState) => {
463
+ switch (currentState) {
464
464
  case STATE_LOADING:
465
465
  showProgressBar();
466
466
  break;
@@ -500,8 +500,8 @@ loader.send('load');
500
500
  const resourceLoader = new LoadingStateMachine();
501
501
  let resource = null;
502
502
 
503
- resourceLoader.onenter = async (state) => {
504
- switch (state) {
503
+ resourceLoader.onenter = async (currentState) => {
504
+ switch (currentState) {
505
505
  case STATE_LOADING:
506
506
  try {
507
507
  resource = await loadResource();
@@ -529,8 +529,8 @@ const retryLoader = new LoadingStateMachine();
529
529
  let retryCount = 0;
530
530
  const maxRetries = 3;
531
531
 
532
- retryLoader.onenter = async (state) => {
533
- switch (state) {
532
+ retryLoader.onenter = async (currentState) => {
533
+ switch (currentState) {
534
534
  case STATE_LOADING:
535
535
  try {
536
536
  await performLoad();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-core",
3
- "version": "0.4.25",
3
+ "version": "0.4.26",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"