@rohal12/spindle 0.37.0 → 0.37.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rohal12/spindle",
3
- "version": "0.37.0",
3
+ "version": "0.37.1",
4
4
  "type": "module",
5
5
  "description": "A Preact-based story format for Twine 2.",
6
6
  "license": "Unlicense",
package/src/index.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import { render } from 'preact';
2
2
  import { App } from './components/App';
3
3
  import { parseStoryData } from './parser';
4
- import { useStoryStore } from './store';
4
+ import { useStoryStore, fireStoryInit } from './store';
5
5
  import { installStoryAPI } from './story-api';
6
6
  import { resetIdCounters } from './action-registry';
7
7
  import { executeStoryInit } from './story-init';
@@ -101,7 +101,6 @@ function boot() {
101
101
 
102
102
  // Execute StoryInit passage if it exists
103
103
  executeStoryInit();
104
- useStoryStore.getState().bumpInitCount();
105
104
 
106
105
  // Restore session state if the page was refreshed
107
106
  const sessionPayload = loadSession(storyData.ifid);
@@ -109,6 +108,9 @@ function boot() {
109
108
  useStoryStore.getState().loadFromPayload(sessionPayload);
110
109
  }
111
110
 
111
+ // Fire storyinit after all state is settled (defaults + StoryInit + session)
112
+ fireStoryInit();
113
+
112
114
  // Pass 1: Pre-scan all widget passages to discover block widgets.
113
115
  // Register them as block macros BEFORE any tokenize/buildAST calls,
114
116
  // so that widget bodies using other block widgets parse correctly
package/src/store.ts CHANGED
@@ -176,6 +176,26 @@ function resetModuleState(base: Record<string, unknown>): void {
176
176
  serializedHistory = [];
177
177
  }
178
178
 
179
+ // ---------------------------------------------------------------------------
180
+ // storyinit callbacks (direct invocation — avoids Zustand subscription issues)
181
+ // ---------------------------------------------------------------------------
182
+
183
+ type StoryInitListener = () => void;
184
+ let storyInitListeners: StoryInitListener[] = [];
185
+
186
+ /** Register a callback to run after StoryInit completes (boot + every restart). */
187
+ export function onStoryInit(cb: StoryInitListener): () => void {
188
+ storyInitListeners.push(cb);
189
+ return () => {
190
+ storyInitListeners = storyInitListeners.filter((l) => l !== cb);
191
+ };
192
+ }
193
+
194
+ /** Fire all storyinit listeners. Called after all state resets are complete. */
195
+ export function fireStoryInit(): void {
196
+ for (const cb of storyInitListeners) cb();
197
+ }
198
+
179
199
  // ---------------------------------------------------------------------------
180
200
  // Store
181
201
  // ---------------------------------------------------------------------------
@@ -207,7 +227,6 @@ export interface StoryState {
207
227
  renderCounts: Record<string, number>;
208
228
  knownSaves: Record<string, true>;
209
229
  playthroughId: string;
210
- initCount: number;
211
230
  maxHistory: number;
212
231
  saveError: string | null;
213
232
  loadError: string | null;
@@ -215,7 +234,6 @@ export interface StoryState {
215
234
  nextTransition: TransitionConfig | null;
216
235
  nobr: boolean;
217
236
 
218
- bumpInitCount: () => void;
219
237
  setMaxHistory: (limit: number) => void;
220
238
  init: (
221
239
  storyData: StoryData,
@@ -260,7 +278,6 @@ export const useStoryStore = create<StoryState>()(
260
278
  renderCounts: {},
261
279
  knownSaves: {},
262
280
  playthroughId: '',
263
- initCount: 0,
264
281
  maxHistory: 40,
265
282
  saveError: null,
266
283
  loadError: null,
@@ -268,12 +285,6 @@ export const useStoryStore = create<StoryState>()(
268
285
  nextTransition: null,
269
286
  nobr: false,
270
287
 
271
- bumpInitCount: () => {
272
- set((state) => {
273
- state.initCount++;
274
- });
275
- },
276
-
277
288
  setMaxHistory: (limit: number) => {
278
289
  set((state) => {
279
290
  state.maxHistory = Math.max(1, Math.round(limit));
@@ -503,8 +514,8 @@ export const useStoryStore = create<StoryState>()(
503
514
 
504
515
  lastNavigationVars = get().variables;
505
516
  executeStoryInit();
506
- get().bumpInitCount();
507
517
  clearSession(storyData.ifid);
518
+ fireStoryInit();
508
519
 
509
520
  // Start a new playthrough on restart
510
521
  startNewPlaythrough(storyData.ifid)
package/src/story-api.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { useStoryStore } from './store';
1
+ import { useStoryStore, onStoryInit } from './store';
2
2
  import type { Passage } from './parser';
3
3
  import { settings } from './settings';
4
4
  import type {
@@ -359,13 +359,7 @@ function createStoryAPI(): StoryAPI {
359
359
  }
360
360
 
361
361
  if (event === 'storyinit') {
362
- let prevCount = useStoryStore.getState().initCount;
363
- return useStoryStore.subscribe((state) => {
364
- if (state.initCount !== prevCount) {
365
- prevCount = state.initCount;
366
- (callback as StoryInitCallback)();
367
- }
368
- });
362
+ return onStoryInit(callback as StoryInitCallback);
369
363
  }
370
364
 
371
365
  if (event === 'actionsChanged') {