@rohal12/spindle 0.51.1 → 0.51.2
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/dist/pkg/headless.js
CHANGED
|
@@ -4825,16 +4825,17 @@ function defineMacro(config, source = "builtin") {
|
|
|
4825
4825
|
//#endregion
|
|
4826
4826
|
//#region src/passage-render-state.ts
|
|
4827
4827
|
/**
|
|
4828
|
-
*
|
|
4829
|
-
* first render, e.g. when the story
|
|
4830
|
-
* Lets Story.waitForActions() tell whether the
|
|
4828
|
+
* Navigation id (the store's `navigationId`) of the passage most recently
|
|
4829
|
+
* mounted by <Passage> (null until the first render, e.g. when the story
|
|
4830
|
+
* interface has no {passage}). Lets Story.waitForActions() tell whether the
|
|
4831
|
+
* current navigation is on screen, also when it revisits the passage shown.
|
|
4831
4832
|
*/
|
|
4832
|
-
var
|
|
4833
|
-
function markPassageRendered(
|
|
4834
|
-
|
|
4833
|
+
var renderedNavigationId = null;
|
|
4834
|
+
function markPassageRendered(navigationId) {
|
|
4835
|
+
renderedNavigationId = navigationId;
|
|
4835
4836
|
}
|
|
4836
|
-
function
|
|
4837
|
-
return
|
|
4837
|
+
function getRenderedNavigationId() {
|
|
4838
|
+
return renderedNavigationId;
|
|
4838
4839
|
}
|
|
4839
4840
|
//#endregion
|
|
4840
4841
|
//#region src/story-api.ts
|
|
@@ -5128,11 +5129,10 @@ function createStoryAPI() {
|
|
|
5128
5129
|
await new Promise((resolve) => {
|
|
5129
5130
|
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
5130
5131
|
});
|
|
5131
|
-
const
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
if (name === useStoryStore.getState().currentPassage) {
|
|
5132
|
+
const isRendered = () => getRenderedNavigationId() === useStoryStore.getState().navigationId;
|
|
5133
|
+
if (getRenderedNavigationId() !== null && !isRendered() && !useStoryStore.getState().renderDeferred) await new Promise((resolve) => {
|
|
5134
|
+
const off = on("passagerender", () => {
|
|
5135
|
+
if (isRendered()) {
|
|
5136
5136
|
off();
|
|
5137
5137
|
resolve();
|
|
5138
5138
|
}
|
|
@@ -7152,7 +7152,7 @@ var CODE_PASSAGES = new Set([
|
|
|
7152
7152
|
"PassageFooter",
|
|
7153
7153
|
"PassageDone"
|
|
7154
7154
|
]);
|
|
7155
|
-
function Passage({ passage, dataTransition }) {
|
|
7155
|
+
function Passage({ passage, dataTransition, navigationId }) {
|
|
7156
7156
|
const storyData = useStoryStore((s) => s.storyData);
|
|
7157
7157
|
const isCodePassage = CODE_PASSAGES.has(passage.name);
|
|
7158
7158
|
const [doneReady, setDoneReady] = useState(false);
|
|
@@ -7210,9 +7210,9 @@ function Passage({ passage, dataTransition }) {
|
|
|
7210
7210
|
}, [doneReady, donePassage?.content]);
|
|
7211
7211
|
const elRef = useRef(null);
|
|
7212
7212
|
useLayoutEffect(() => {
|
|
7213
|
-
markPassageRendered(
|
|
7213
|
+
if (navigationId !== void 0) markPassageRendered(navigationId);
|
|
7214
7214
|
if (elRef.current) emitFromRender("passagerender", passage.name, elRef.current);
|
|
7215
|
-
}, [passage.name]);
|
|
7215
|
+
}, [passage.name, navigationId]);
|
|
7216
7216
|
const nobr = passage.tags.includes("nobr");
|
|
7217
7217
|
const inner = /* @__PURE__ */ jsxs("div", {
|
|
7218
7218
|
ref: elRef,
|
|
@@ -7458,7 +7458,8 @@ defineMacro({
|
|
|
7458
7458
|
ref: containerRef,
|
|
7459
7459
|
children: effectivePassage && /* @__PURE__ */ jsx(Passage, {
|
|
7460
7460
|
passage: effectivePassage,
|
|
7461
|
-
dataTransition: renderDeferred ? "none" : resolvedTypeRef.current
|
|
7461
|
+
dataTransition: renderDeferred ? "none" : resolvedTypeRef.current,
|
|
7462
|
+
navigationId: renderDeferred ? void 0 : displayed.id
|
|
7462
7463
|
}, renderDeferred ? "loading" : `nav-${displayed.id}`)
|
|
7463
7464
|
})]
|
|
7464
7465
|
});
|
package/package.json
CHANGED
|
@@ -42,6 +42,8 @@ export function renderPassageContent(passage: PassageData) {
|
|
|
42
42
|
interface PassageProps {
|
|
43
43
|
passage: PassageData;
|
|
44
44
|
dataTransition?: string;
|
|
45
|
+
/** The navigation this passage displays; omitted for placeholders. */
|
|
46
|
+
navigationId?: number;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
const CODE_PASSAGES = new Set([
|
|
@@ -51,7 +53,11 @@ const CODE_PASSAGES = new Set([
|
|
|
51
53
|
'PassageDone',
|
|
52
54
|
]);
|
|
53
55
|
|
|
54
|
-
export function Passage({
|
|
56
|
+
export function Passage({
|
|
57
|
+
passage,
|
|
58
|
+
dataTransition,
|
|
59
|
+
navigationId,
|
|
60
|
+
}: PassageProps) {
|
|
55
61
|
const storyData = useStoryStore((s) => s.storyData);
|
|
56
62
|
const isCodePassage = CODE_PASSAGES.has(passage.name);
|
|
57
63
|
const [doneReady, setDoneReady] = useState(false);
|
|
@@ -121,11 +127,11 @@ export function Passage({ passage, dataTransition }: PassageProps) {
|
|
|
121
127
|
// Passage so every navigation that shows a passage mounts a new one.
|
|
122
128
|
const elRef = useRef<HTMLDivElement>(null);
|
|
123
129
|
useLayoutEffect(() => {
|
|
124
|
-
markPassageRendered(
|
|
130
|
+
if (navigationId !== undefined) markPassageRendered(navigationId);
|
|
125
131
|
if (elRef.current) {
|
|
126
132
|
emitFromRender('passagerender', passage.name, elRef.current);
|
|
127
133
|
}
|
|
128
|
-
}, [passage.name]);
|
|
134
|
+
}, [passage.name, navigationId]);
|
|
129
135
|
|
|
130
136
|
const nobr = passage.tags.includes('nobr');
|
|
131
137
|
|
|
@@ -292,6 +292,7 @@ defineMacro({
|
|
|
292
292
|
passage={effectivePassage}
|
|
293
293
|
key={renderDeferred ? 'loading' : `nav-${displayed.id}`}
|
|
294
294
|
dataTransition={renderDeferred ? 'none' : resolvedTypeRef.current}
|
|
295
|
+
navigationId={renderDeferred ? undefined : displayed.id}
|
|
295
296
|
/>
|
|
296
297
|
)}
|
|
297
298
|
</div>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* first render, e.g. when the story
|
|
4
|
-
* Lets Story.waitForActions() tell whether the
|
|
2
|
+
* Navigation id (the store's `navigationId`) of the passage most recently
|
|
3
|
+
* mounted by <Passage> (null until the first render, e.g. when the story
|
|
4
|
+
* interface has no {passage}). Lets Story.waitForActions() tell whether the
|
|
5
|
+
* current navigation is on screen, also when it revisits the passage shown.
|
|
5
6
|
*/
|
|
6
|
-
let
|
|
7
|
+
let renderedNavigationId: number | null = null;
|
|
7
8
|
|
|
8
|
-
export function markPassageRendered(
|
|
9
|
-
|
|
9
|
+
export function markPassageRendered(navigationId: number): void {
|
|
10
|
+
renderedNavigationId = navigationId;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
export function
|
|
13
|
-
return
|
|
13
|
+
export function getRenderedNavigationId(): number | null {
|
|
14
|
+
return renderedNavigationId;
|
|
14
15
|
}
|
package/src/story-api.ts
CHANGED
|
@@ -30,7 +30,7 @@ import type { MacroDefinition } from './define-macro';
|
|
|
30
30
|
import { getMacroRegistry as _getMacroRegistry } from './registry';
|
|
31
31
|
import type { MacroMetadata } from './registry';
|
|
32
32
|
import { getActions, getAction, type StoryAction } from './action-registry';
|
|
33
|
-
import {
|
|
33
|
+
import { getRenderedNavigationId } from './passage-render-state';
|
|
34
34
|
import {
|
|
35
35
|
initPRNG,
|
|
36
36
|
isPRNGEnabled,
|
|
@@ -548,13 +548,19 @@ function createStoryAPI(): StoryAPI {
|
|
|
548
548
|
});
|
|
549
549
|
// A navigation can still be rendering: the passage display mounts the
|
|
550
550
|
// new passage from an effect, after a fade-through's outgoing phase.
|
|
551
|
-
// Its actions exist only once it is mounted, so wait for that.
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
551
|
+
// Its actions exist only once it is mounted, so wait for that. Compare
|
|
552
|
+
// navigations, not passage names: revisiting the passage shown mounts
|
|
553
|
+
// it anew (#228).
|
|
554
|
+
const isRendered = () =>
|
|
555
|
+
getRenderedNavigationId() === useStoryStore.getState().navigationId;
|
|
556
|
+
if (
|
|
557
|
+
getRenderedNavigationId() !== null &&
|
|
558
|
+
!isRendered() &&
|
|
559
|
+
!useStoryStore.getState().renderDeferred
|
|
560
|
+
) {
|
|
555
561
|
await new Promise<void>((resolve) => {
|
|
556
|
-
const off = emitterOn('passagerender', (
|
|
557
|
-
if (
|
|
562
|
+
const off = emitterOn('passagerender', () => {
|
|
563
|
+
if (isRendered()) {
|
|
558
564
|
off();
|
|
559
565
|
resolve();
|
|
560
566
|
}
|