@rohal12/spindle 0.26.1 → 0.27.0
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,19 +1,38 @@
|
|
|
1
|
-
import { useState, useEffect, useCallback } from 'preact/hooks';
|
|
1
|
+
import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
|
2
2
|
import { PassageDialog } from './PassageDialog';
|
|
3
3
|
import {
|
|
4
4
|
subscribeTriggerDialogs,
|
|
5
5
|
shiftDialogQueue,
|
|
6
6
|
dialogQueueLength,
|
|
7
|
+
registerDialogHost,
|
|
7
8
|
} from '../triggers';
|
|
9
|
+
import type { QueuedDialog } from '../triggers';
|
|
8
10
|
|
|
9
11
|
export function TriggerDialogHost() {
|
|
10
|
-
const [current, setCurrent] = useState<
|
|
12
|
+
const [current, setCurrent] = useState<QueuedDialog | null>(null);
|
|
13
|
+
const currentRef = useRef(current);
|
|
14
|
+
currentRef.current = current;
|
|
11
15
|
|
|
12
16
|
const advance = useCallback(() => {
|
|
13
17
|
const next = shiftDialogQueue();
|
|
14
18
|
setCurrent(next ?? null);
|
|
15
19
|
}, []);
|
|
16
20
|
|
|
21
|
+
const handleClose = useCallback(() => {
|
|
22
|
+
setCurrent(null);
|
|
23
|
+
// Show next queued dialog after a tick
|
|
24
|
+
if (dialogQueueLength() > 0) {
|
|
25
|
+
requestAnimationFrame(advance);
|
|
26
|
+
}
|
|
27
|
+
}, [advance]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
return registerDialogHost({
|
|
31
|
+
close: handleClose,
|
|
32
|
+
isOpen: () => currentRef.current !== null,
|
|
33
|
+
});
|
|
34
|
+
}, [handleClose]);
|
|
35
|
+
|
|
17
36
|
useEffect(() => {
|
|
18
37
|
return subscribeTriggerDialogs(() => {
|
|
19
38
|
setCurrent((prev) => {
|
|
@@ -23,19 +42,12 @@ export function TriggerDialogHost() {
|
|
|
23
42
|
});
|
|
24
43
|
}, []);
|
|
25
44
|
|
|
26
|
-
const handleClose = useCallback(() => {
|
|
27
|
-
setCurrent(null);
|
|
28
|
-
// Show next queued dialog after a tick
|
|
29
|
-
if (dialogQueueLength() > 0) {
|
|
30
|
-
requestAnimationFrame(advance);
|
|
31
|
-
}
|
|
32
|
-
}, [advance]);
|
|
33
|
-
|
|
34
45
|
if (!current) return null;
|
|
35
46
|
|
|
36
47
|
return (
|
|
37
48
|
<PassageDialog
|
|
38
|
-
passageName={current}
|
|
49
|
+
passageName={current.passageName}
|
|
50
|
+
panelClass={current.panelClass}
|
|
39
51
|
onClose={handleClose}
|
|
40
52
|
/>
|
|
41
53
|
);
|
|
@@ -81,17 +81,19 @@ function WidgetBody({
|
|
|
81
81
|
ownKeys: Record<string, unknown>;
|
|
82
82
|
}) {
|
|
83
83
|
const nobr = useContext(NobrContext);
|
|
84
|
-
const [
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
const [localMutations, setLocalMutations] = useState<Record<string, unknown>>(
|
|
85
|
+
{},
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Recomputed every render — picks up new ownKeys from parent
|
|
89
|
+
const localState = { ...parentValues, ...ownKeys, ...localMutations };
|
|
88
90
|
|
|
89
91
|
const valuesRef = useRef(localState);
|
|
90
92
|
valuesRef.current = localState;
|
|
91
93
|
|
|
92
94
|
const getValues = useCallback(() => valuesRef.current, []);
|
|
93
95
|
const update = useCallback((key: string, value: unknown) => {
|
|
94
|
-
|
|
96
|
+
setLocalMutations((prev) => ({ ...prev, [key]: value }));
|
|
95
97
|
}, []);
|
|
96
98
|
const updater = useMemo(() => ({ update, getValues }), [update, getValues]);
|
|
97
99
|
|
package/src/story-api.ts
CHANGED
|
@@ -21,7 +21,14 @@ import {
|
|
|
21
21
|
randomInt,
|
|
22
22
|
snapshotPRNG,
|
|
23
23
|
} from './prng';
|
|
24
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
addTrigger,
|
|
26
|
+
removeTrigger,
|
|
27
|
+
pushDialog,
|
|
28
|
+
clearDialogQueue,
|
|
29
|
+
closeCurrentDialog,
|
|
30
|
+
isDialogShowing,
|
|
31
|
+
} from './triggers';
|
|
25
32
|
import type { WatchOptions } from './triggers';
|
|
26
33
|
import type { TransitionConfig } from './transition';
|
|
27
34
|
|
|
@@ -73,6 +80,10 @@ export interface StoryAPI {
|
|
|
73
80
|
callbackOrOptions: (() => void) | WatchOptions,
|
|
74
81
|
): () => void;
|
|
75
82
|
unwatch(name: string): void;
|
|
83
|
+
openDialog(passageName: string, options?: { panelClass?: string }): void;
|
|
84
|
+
closeDialog(): void;
|
|
85
|
+
closeAllDialogs(): void;
|
|
86
|
+
isDialogOpen(): boolean;
|
|
76
87
|
setNobr(enabled: boolean): void;
|
|
77
88
|
setCSS(enabled: boolean): void;
|
|
78
89
|
setTransition(config: TransitionConfig | null): void;
|
|
@@ -286,6 +297,23 @@ function createStoryAPI(): StoryAPI {
|
|
|
286
297
|
removeTrigger(name);
|
|
287
298
|
},
|
|
288
299
|
|
|
300
|
+
openDialog(passageName: string, options?: { panelClass?: string }): void {
|
|
301
|
+
pushDialog({ passageName, panelClass: options?.panelClass });
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
closeDialog(): void {
|
|
305
|
+
closeCurrentDialog();
|
|
306
|
+
},
|
|
307
|
+
|
|
308
|
+
closeAllDialogs(): void {
|
|
309
|
+
clearDialogQueue();
|
|
310
|
+
closeCurrentDialog();
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
isDialogOpen(): boolean {
|
|
314
|
+
return isDialogShowing();
|
|
315
|
+
},
|
|
316
|
+
|
|
289
317
|
setNobr(enabled: boolean): void {
|
|
290
318
|
useStoryStore.setState({ nobr: enabled });
|
|
291
319
|
},
|
package/src/triggers.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface WatchOptions {
|
|
|
10
10
|
priority?: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export interface QueuedDialog {
|
|
14
|
+
passageName: string;
|
|
15
|
+
panelClass?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
interface Trigger {
|
|
14
19
|
id: number;
|
|
15
20
|
name?: string;
|
|
@@ -25,9 +30,15 @@ let triggers: Trigger[] = [];
|
|
|
25
30
|
let checking = false;
|
|
26
31
|
|
|
27
32
|
type DialogCallback = () => void;
|
|
28
|
-
let dialogQueue:
|
|
33
|
+
let dialogQueue: QueuedDialog[] = [];
|
|
29
34
|
let dialogNotify: DialogCallback | null = null;
|
|
30
35
|
|
|
36
|
+
interface DialogHostCallbacks {
|
|
37
|
+
close: () => void;
|
|
38
|
+
isOpen: () => boolean;
|
|
39
|
+
}
|
|
40
|
+
let dialogHostCallbacks: DialogHostCallbacks | null = null;
|
|
41
|
+
|
|
31
42
|
function evalCondition(condition: string): boolean {
|
|
32
43
|
const state = useStoryStore.getState();
|
|
33
44
|
try {
|
|
@@ -84,7 +95,7 @@ function fireTrigger(trigger: Trigger): void {
|
|
|
84
95
|
}
|
|
85
96
|
|
|
86
97
|
if (options.dialog) {
|
|
87
|
-
dialogQueue.push(options.dialog);
|
|
98
|
+
dialogQueue.push({ passageName: options.dialog });
|
|
88
99
|
dialogNotify?.();
|
|
89
100
|
}
|
|
90
101
|
|
|
@@ -141,6 +152,7 @@ export function resetTriggers(): void {
|
|
|
141
152
|
triggers = [];
|
|
142
153
|
dialogQueue = [];
|
|
143
154
|
nextId = 0;
|
|
155
|
+
dialogHostCallbacks?.close();
|
|
144
156
|
}
|
|
145
157
|
|
|
146
158
|
export function subscribeTriggerDialogs(cb: () => void): () => void {
|
|
@@ -152,10 +164,34 @@ export function subscribeTriggerDialogs(cb: () => void): () => void {
|
|
|
152
164
|
};
|
|
153
165
|
}
|
|
154
166
|
|
|
155
|
-
export function shiftDialogQueue():
|
|
167
|
+
export function shiftDialogQueue(): QueuedDialog | undefined {
|
|
156
168
|
return dialogQueue.shift();
|
|
157
169
|
}
|
|
158
170
|
|
|
159
171
|
export function dialogQueueLength(): number {
|
|
160
172
|
return dialogQueue.length;
|
|
161
173
|
}
|
|
174
|
+
|
|
175
|
+
export function pushDialog(item: QueuedDialog): void {
|
|
176
|
+
dialogQueue.push(item);
|
|
177
|
+
dialogNotify?.();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function clearDialogQueue(): void {
|
|
181
|
+
dialogQueue = [];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function registerDialogHost(callbacks: DialogHostCallbacks): () => void {
|
|
185
|
+
dialogHostCallbacks = callbacks;
|
|
186
|
+
return () => {
|
|
187
|
+
if (dialogHostCallbacks === callbacks) dialogHostCallbacks = null;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function closeCurrentDialog(): void {
|
|
192
|
+
dialogHostCallbacks?.close();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function isDialogShowing(): boolean {
|
|
196
|
+
return dialogHostCallbacks?.isOpen() ?? false;
|
|
197
|
+
}
|