@momoyu-ink/kit 0.4.2 → 0.5.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/dist/jsx-dev-runtime--ZXLAgUi.d.mts +600 -0
- package/dist/jsx-dev-runtime--ZXLAgUi.d.ts +600 -0
- package/dist/jsx-dev-runtime.cjs +27 -0
- package/dist/jsx-dev-runtime.d.mts +4 -0
- package/dist/jsx-dev-runtime.d.ts +4 -0
- package/dist/jsx-dev-runtime.mjs +6 -0
- package/dist/jsx-runtime.cjs +28 -0
- package/dist/jsx-runtime.d.mts +4 -0
- package/dist/jsx-runtime.d.ts +4 -0
- package/dist/jsx-runtime.mjs +7 -0
- package/dist/lib.cjs +1610 -0
- package/dist/lib.d.mts +668 -0
- package/dist/lib.d.ts +668 -15
- package/dist/lib.mjs +1641 -0
- package/package.json +29 -8
- package/dist/bindings/AnimationFormat.d.ts +0 -1
- package/dist/bindings/AnimationFormat.js +0 -3
- package/dist/bindings/AnimationFrameCallbackEvent.d.ts +0 -3
- package/dist/bindings/AnimationFrameCallbackEvent.js +0 -3
- package/dist/bindings/AnimationProps.d.ts +0 -6
- package/dist/bindings/AnimationProps.js +0 -2
- package/dist/bindings/AudioCommand.d.ts +0 -54
- package/dist/bindings/AudioCommand.js +0 -2
- package/dist/bindings/AudioSettings.d.ts +0 -42
- package/dist/bindings/AudioSettings.js +0 -3
- package/dist/bindings/BackdropProps.d.ts +0 -6
- package/dist/bindings/BackdropProps.js +0 -2
- package/dist/bindings/BeforeUnloadEvent.d.ts +0 -1
- package/dist/bindings/BeforeUnloadEvent.js +0 -3
- package/dist/bindings/ClipProps.d.ts +0 -4
- package/dist/bindings/ClipProps.js +0 -3
- package/dist/bindings/CustomEvent.d.ts +0 -18
- package/dist/bindings/CustomEvent.js +0 -3
- package/dist/bindings/EffectParams.d.ts +0 -6
- package/dist/bindings/EffectParams.js +0 -3
- package/dist/bindings/FilterKind.d.ts +0 -34
- package/dist/bindings/FilterKind.js +0 -3
- package/dist/bindings/FilterProps.d.ts +0 -4
- package/dist/bindings/FilterProps.js +0 -2
- package/dist/bindings/FocusEvent.d.ts +0 -5
- package/dist/bindings/FocusEvent.js +0 -2
- package/dist/bindings/FocusEventKind.d.ts +0 -1
- package/dist/bindings/FocusEventKind.js +0 -3
- package/dist/bindings/FullScreenEvent.d.ts +0 -4
- package/dist/bindings/FullScreenEvent.js +0 -2
- package/dist/bindings/FullscreenEventKind.d.ts +0 -1
- package/dist/bindings/FullscreenEventKind.js +0 -3
- package/dist/bindings/GameEvent.d.ts +0 -1
- package/dist/bindings/GameEvent.js +0 -3
- package/dist/bindings/Gamepad.d.ts +0 -44
- package/dist/bindings/Gamepad.js +0 -2
- package/dist/bindings/GamepadButton.d.ts +0 -20
- package/dist/bindings/GamepadButton.js +0 -3
- package/dist/bindings/GamepadCommand.d.ts +0 -9
- package/dist/bindings/GamepadCommand.js +0 -2
- package/dist/bindings/GamepadEvent.d.ts +0 -12
- package/dist/bindings/GamepadEvent.js +0 -2
- package/dist/bindings/GamepadHapticActuator.d.ts +0 -11
- package/dist/bindings/GamepadHapticActuator.js +0 -3
- package/dist/bindings/KeyboardEventKind.d.ts +0 -1
- package/dist/bindings/KeyboardEventKind.js +0 -3
- package/dist/bindings/KeyboardLocation.d.ts +0 -1
- package/dist/bindings/KeyboardLocation.js +0 -3
- package/dist/bindings/Literal.d.ts +0 -3
- package/dist/bindings/Literal.js +0 -3
- package/dist/bindings/MouseEventKind.d.ts +0 -1
- package/dist/bindings/MouseEventKind.js +0 -3
- package/dist/bindings/MoyuCursor.d.ts +0 -1
- package/dist/bindings/MoyuCursor.js +0 -3
- package/dist/bindings/NineSliceMode.d.ts +0 -1
- package/dist/bindings/NineSliceMode.js +0 -3
- package/dist/bindings/NodeEvent.d.ts +0 -4
- package/dist/bindings/NodeEvent.js +0 -3
- package/dist/bindings/NodeProps.d.ts +0 -20
- package/dist/bindings/NodeProps.js +0 -2
- package/dist/bindings/RawKeyboardEvent.d.ts +0 -16
- package/dist/bindings/RawKeyboardEvent.js +0 -2
- package/dist/bindings/RawMouseEvent.d.ts +0 -12
- package/dist/bindings/RawMouseEvent.js +0 -2
- package/dist/bindings/RawTouchEvent.d.ts +0 -13
- package/dist/bindings/RawTouchEvent.js +0 -2
- package/dist/bindings/RawWheelEvent.d.ts +0 -10
- package/dist/bindings/RawWheelEvent.js +0 -2
- package/dist/bindings/ResizeEvent.d.ts +0 -4
- package/dist/bindings/ResizeEvent.js +0 -3
- package/dist/bindings/ResolvedArgument.d.ts +0 -5
- package/dist/bindings/ResolvedArgument.js +0 -2
- package/dist/bindings/ResolvedCommandLine.d.ts +0 -5
- package/dist/bindings/ResolvedCommandLine.js +0 -2
- package/dist/bindings/ResolvedSystemCallLine.d.ts +0 -5
- package/dist/bindings/ResolvedSystemCallLine.js +0 -2
- package/dist/bindings/ScenarioCommand.d.ts +0 -103
- package/dist/bindings/ScenarioCommand.js +0 -2
- package/dist/bindings/ScenarioEvent.d.ts +0 -4
- package/dist/bindings/ScenarioEvent.js +0 -2
- package/dist/bindings/SpriteMode.d.ts +0 -1
- package/dist/bindings/SpriteMode.js +0 -3
- package/dist/bindings/SpriteProps.d.ts +0 -11
- package/dist/bindings/SpriteProps.js +0 -2
- package/dist/bindings/SystemCommand.d.ts +0 -30
- package/dist/bindings/SystemCommand.js +0 -2
- package/dist/bindings/TextCommand.d.ts +0 -9
- package/dist/bindings/TextCommand.js +0 -3
- package/dist/bindings/TextEvent.d.ts +0 -1
- package/dist/bindings/TextEvent.js +0 -3
- package/dist/bindings/TextLine.d.ts +0 -5
- package/dist/bindings/TextLine.js +0 -3
- package/dist/bindings/TextPrintMode.d.ts +0 -4
- package/dist/bindings/TextPrintMode.js +0 -3
- package/dist/bindings/TextProps.d.ts +0 -41
- package/dist/bindings/TextProps.js +0 -2
- package/dist/bindings/TouchEventKind.d.ts +0 -1
- package/dist/bindings/TouchEventKind.js +0 -3
- package/dist/bindings/VideoCommand.d.ts +0 -21
- package/dist/bindings/VideoCommand.js +0 -3
- package/dist/bindings/VideoEvent.d.ts +0 -1
- package/dist/bindings/VideoEvent.js +0 -3
- package/dist/bindings/VideoProps.d.ts +0 -7
- package/dist/bindings/VideoProps.js +0 -3
- package/dist/bindings/WheelEventDeltaMode.d.ts +0 -1
- package/dist/bindings/WheelEventDeltaMode.js +0 -3
- package/dist/bindings/WindowState.d.ts +0 -1
- package/dist/bindings/WindowState.js +0 -3
- package/dist/bindings/serde_json/JsonValue.d.ts +0 -3
- package/dist/bindings/serde_json/JsonValue.js +0 -3
- package/dist/commands.d.ts +0 -17
- package/dist/commands.js +0 -24
- package/dist/components/navigation.d.ts +0 -154
- package/dist/components/navigation.js +0 -252
- package/dist/declaration.d.ts +0 -80
- package/dist/declaration.js +0 -2
- package/dist/events/base.d.ts +0 -16
- package/dist/events/base.js +0 -19
- package/dist/events/globals.d.ts +0 -2
- package/dist/events/globals.js +0 -122
- package/dist/events/keyboard.d.ts +0 -37
- package/dist/events/keyboard.js +0 -2
- package/dist/events/listener.d.ts +0 -1
- package/dist/events/listener.js +0 -13
- package/dist/events/mouse.d.ts +0 -15
- package/dist/events/mouse.js +0 -2
- package/dist/events/touch.d.ts +0 -16
- package/dist/events/touch.js +0 -2
- package/dist/events/wheel.d.ts +0 -9
- package/dist/events/wheel.js +0 -2
- package/dist/events.d.ts +0 -33
- package/dist/events.js +0 -49
- package/dist/hooks/useFadeInOut.d.ts +0 -16
- package/dist/hooks/useFadeInOut.js +0 -62
- package/dist/hooks/useScenario.d.ts +0 -13
- package/dist/hooks/useScenario.js +0 -64
- package/dist/hooks/useSoundEffect.d.ts +0 -4
- package/dist/hooks/useSoundEffect.js +0 -63
- package/dist/hooks/useStage.d.ts +0 -126
- package/dist/hooks/useStage.js +0 -706
- package/dist/hooks.d.ts +0 -4
- package/dist/hooks.js +0 -20
- package/dist/lib.js +0 -54
- package/dist/moyu.d.ts +0 -19
- package/dist/moyu.js +0 -49
- package/dist/node.d.ts +0 -16
- package/dist/node.js +0 -105
- package/dist/react.d.ts +0 -20
- package/dist/react.js +0 -222
- package/dist/runtime-globals.d.ts +0 -65
- package/dist/runtime-globals.js +0 -2
- package/dist/sandbox.d.ts +0 -1
- package/dist/sandbox.js +0 -88
- package/dist/spring/animated.d.ts +0 -27
- package/dist/spring/animated.js +0 -2
- package/dist/spring/index.d.ts +0 -5
- package/dist/spring/index.js +0 -35
- package/dist/spring/primitives.d.ts +0 -3
- package/dist/spring/primitives.js +0 -13
- package/dist/state.d.ts +0 -6
- package/dist/state.js +0 -8
- package/dist/utils.d.ts +0 -10
- package/dist/utils.js +0 -10
- package/dist/zod-patch.d.ts +0 -10
- package/dist/zod-patch.js +0 -2
- package/jsx-runtime.d.ts +0 -1
package/dist/hooks/useStage.js
DELETED
|
@@ -1,706 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.autoState = exports.skipState = void 0;
|
|
4
|
-
exports.useIsSkipping = useIsSkipping;
|
|
5
|
-
exports.useIsAutoing = useIsAutoing;
|
|
6
|
-
exports.setDefaultAutoTailMs = setDefaultAutoTailMs;
|
|
7
|
-
exports.createStage = createStage;
|
|
8
|
-
exports.useStageContext = useStageContext;
|
|
9
|
-
exports.StageContextProvider = StageContextProvider;
|
|
10
|
-
exports.useSkipCallback = useSkipCallback;
|
|
11
|
-
exports.useInterruptCallback = useInterruptCallback;
|
|
12
|
-
exports.useSkipBlocker = useSkipBlocker;
|
|
13
|
-
exports.useAutoBlocker = useAutoBlocker;
|
|
14
|
-
exports.useAutoTicket = useAutoTicket;
|
|
15
|
-
exports.useBeforeHandleCommandCallback = useBeforeHandleCommandCallback;
|
|
16
|
-
const react_1 = require("react");
|
|
17
|
-
const valtio_1 = require("valtio");
|
|
18
|
-
const useScenario_1 = require("./useScenario");
|
|
19
|
-
const events_1 = require("../events");
|
|
20
|
-
const moyu_1 = require("../moyu");
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Skip state — independent valtio proxy (not serialized with game saves)
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
const SKIP_INTERVAL_MS = 80;
|
|
25
|
-
const autoRuntime = {
|
|
26
|
-
defaultTailMs: 0,
|
|
27
|
-
};
|
|
28
|
-
/** Reactive skip state. Actors read via useIsSkipping(). */
|
|
29
|
-
exports.skipState = (0, valtio_1.proxy)({ active: false });
|
|
30
|
-
/** Reactive auto state. Actors read via useIsAutoing(). */
|
|
31
|
-
exports.autoState = (0, valtio_1.proxy)({ active: false });
|
|
32
|
-
/** Reactively returns whether skip (Ctrl fast-forward) is active. */
|
|
33
|
-
function useIsSkipping() {
|
|
34
|
-
return (0, valtio_1.useSnapshot)(exports.skipState).active;
|
|
35
|
-
}
|
|
36
|
-
/** Reactively returns whether auto mode is active. */
|
|
37
|
-
function useIsAutoing() {
|
|
38
|
-
return (0, valtio_1.useSnapshot)(exports.autoState).active;
|
|
39
|
-
}
|
|
40
|
-
/** Set the default tail delay in milliseconds for newly created auto tickets. */
|
|
41
|
-
function setDefaultAutoTailMs(ms) {
|
|
42
|
-
if (!Number.isFinite(ms)) {
|
|
43
|
-
autoRuntime.defaultTailMs = 0;
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
autoRuntime.defaultTailMs = Math.max(0, ms);
|
|
47
|
-
}
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
// createStage — module-level infrastructure
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
function createStage() {
|
|
52
|
-
// --- registries ---
|
|
53
|
-
let commandSchema = null;
|
|
54
|
-
const commandHandlers = new Map();
|
|
55
|
-
const textLineHandlers = [];
|
|
56
|
-
const skipCallbacks = [];
|
|
57
|
-
const interruptCallbacks = [];
|
|
58
|
-
const skipBlockers = [];
|
|
59
|
-
const autoBlockers = [];
|
|
60
|
-
const beforeHandleCommandCallbacks = [];
|
|
61
|
-
// --- registration functions ---
|
|
62
|
-
/** Push `item` to `registry` and return a function that removes it. */
|
|
63
|
-
function addToRegistry(registry, item) {
|
|
64
|
-
registry.push(item);
|
|
65
|
-
return () => {
|
|
66
|
-
const idx = registry.indexOf(item);
|
|
67
|
-
if (idx !== -1)
|
|
68
|
-
registry.splice(idx, 1);
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Register command schema.
|
|
73
|
-
* Returns an unregister function.
|
|
74
|
-
*/
|
|
75
|
-
function registerCommandSchema(schema) {
|
|
76
|
-
if (commandSchema !== null) {
|
|
77
|
-
console.warn('[Stage] Command schema is already registered — overwriting.');
|
|
78
|
-
}
|
|
79
|
-
commandSchema = schema;
|
|
80
|
-
return () => {
|
|
81
|
-
if (commandSchema === schema) {
|
|
82
|
-
commandSchema = null;
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Register a command handler for one or more command names.
|
|
88
|
-
* Returns an unregister function.
|
|
89
|
-
*/
|
|
90
|
-
function registerCommand(commands, handler) {
|
|
91
|
-
const names = Array.isArray(commands) ? commands : [commands];
|
|
92
|
-
for (const name of names) {
|
|
93
|
-
if (commandHandlers.has(name)) {
|
|
94
|
-
console.warn(`[Stage] Command handler for "${name}" is already registered — overwriting.`);
|
|
95
|
-
}
|
|
96
|
-
commandHandlers.set(name, handler);
|
|
97
|
-
}
|
|
98
|
-
return () => {
|
|
99
|
-
for (const name of names) {
|
|
100
|
-
if (commandHandlers.get(name) === handler) {
|
|
101
|
-
commandHandlers.delete(name);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Register a text line handler.
|
|
108
|
-
* Returns an unregister function.
|
|
109
|
-
*/
|
|
110
|
-
function registerTextLine(handler) {
|
|
111
|
-
return addToRegistry(textLineHandlers, handler);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Add a skip callback (called when scenariowaitingcancelled fires).
|
|
115
|
-
* Returns a remove function.
|
|
116
|
-
*/
|
|
117
|
-
function addSkipCallback(cb) {
|
|
118
|
-
return addToRegistry(skipCallbacks, cb);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Add an interrupt callback (called on user click, in order).
|
|
122
|
-
* Return `true` from the callback to consume the click.
|
|
123
|
-
* Returns a remove function.
|
|
124
|
-
*/
|
|
125
|
-
function addInterruptCallback(cb) {
|
|
126
|
-
return addToRegistry(interruptCallbacks, cb);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Try to interrupt: iterate through interrupt callbacks until one returns true.
|
|
130
|
-
* Returns true if a callback consumed the event.
|
|
131
|
-
*/
|
|
132
|
-
function tryInterrupt() {
|
|
133
|
-
for (const cb of interruptCallbacks) {
|
|
134
|
-
try {
|
|
135
|
-
if (cb())
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
catch (err) {
|
|
139
|
-
console.error('Error in interrupt callback:', err);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
// --- skip blocker ---
|
|
145
|
-
/**
|
|
146
|
-
* Add a skip blocker callback. Return `true` from the callback to block skipping.
|
|
147
|
-
* Returns a remove function.
|
|
148
|
-
*/
|
|
149
|
-
function addSkipBlocker(cb) {
|
|
150
|
-
return addToRegistry(skipBlockers, cb);
|
|
151
|
-
}
|
|
152
|
-
/** Returns true if any registered skip blocker is active. */
|
|
153
|
-
function isAnyBlockerActive() {
|
|
154
|
-
for (const cb of skipBlockers) {
|
|
155
|
-
try {
|
|
156
|
-
if (cb())
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
catch (err) {
|
|
160
|
-
console.error('Error in skip blocker callback:', err);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Add an auto blocker callback. Return `true` from the callback to block auto mode.
|
|
167
|
-
* Returns a remove function.
|
|
168
|
-
*/
|
|
169
|
-
function addAutoBlocker(cb) {
|
|
170
|
-
return addToRegistry(autoBlockers, cb);
|
|
171
|
-
}
|
|
172
|
-
/** Returns true if any registered auto blocker is active. */
|
|
173
|
-
function isAnyAutoBlockerActive() {
|
|
174
|
-
for (const cb of autoBlockers) {
|
|
175
|
-
try {
|
|
176
|
-
if (cb())
|
|
177
|
-
return true;
|
|
178
|
-
}
|
|
179
|
-
catch (err) {
|
|
180
|
-
console.error('Error in auto blocker callback:', err);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
/** Add a callback to be invoked before handling each command. */
|
|
186
|
-
function addBeforeHandleCommandCallback(cb) {
|
|
187
|
-
return addToRegistry(beforeHandleCommandCallbacks, cb);
|
|
188
|
-
}
|
|
189
|
-
// --- skip (Ctrl fast-forward) management ---
|
|
190
|
-
let _skipTimer = null;
|
|
191
|
-
let _autoTimer = null;
|
|
192
|
-
let _autoBarrier = null;
|
|
193
|
-
let _autoResumeTimer = null;
|
|
194
|
-
let _autoCollectFrame = null;
|
|
195
|
-
let _autoBarrierSeq = 0;
|
|
196
|
-
let _autoTicketSeq = 0;
|
|
197
|
-
const _pendingAutoTickets = new Map();
|
|
198
|
-
function clearAutoResumeTimer() {
|
|
199
|
-
if (_autoResumeTimer !== null) {
|
|
200
|
-
clearTimeout(_autoResumeTimer);
|
|
201
|
-
_autoResumeTimer = null;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
function clearAutoCollectFrame() {
|
|
205
|
-
if (_autoCollectFrame !== null) {
|
|
206
|
-
cancelAnimationFrame(_autoCollectFrame);
|
|
207
|
-
_autoCollectFrame = null;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
function clearAutoBarrier() {
|
|
211
|
-
clearAutoCollectFrame();
|
|
212
|
-
clearAutoResumeTimer();
|
|
213
|
-
_autoBarrier = null;
|
|
214
|
-
}
|
|
215
|
-
function clearPendingAutoTickets() {
|
|
216
|
-
_pendingAutoTickets.clear();
|
|
217
|
-
}
|
|
218
|
-
function getActiveAutoBarrier(barrierId) {
|
|
219
|
-
if (_autoBarrier === null || _autoBarrier.id !== barrierId) {
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
return _autoBarrier;
|
|
223
|
-
}
|
|
224
|
-
function scheduleAutoResume(barrierId, delayMs) {
|
|
225
|
-
clearAutoResumeTimer();
|
|
226
|
-
const safeDelayMs = Number.isFinite(delayMs) ? Math.max(0, delayMs) : 0;
|
|
227
|
-
_autoResumeTimer = setTimeout(() => {
|
|
228
|
-
_autoResumeTimer = null;
|
|
229
|
-
if (!exports.autoState.active)
|
|
230
|
-
return;
|
|
231
|
-
if (_autoBarrier === null || _autoBarrier.id !== barrierId)
|
|
232
|
-
return;
|
|
233
|
-
_autoBarrier = null;
|
|
234
|
-
void (0, useScenario_1.nextLine)();
|
|
235
|
-
}, safeDelayMs);
|
|
236
|
-
}
|
|
237
|
-
function trySettleAutoBarrier(barrier) {
|
|
238
|
-
if (barrier.collecting || barrier.settled)
|
|
239
|
-
return;
|
|
240
|
-
const activeTickets = [...barrier.tickets.values()].filter((ticket) => !ticket.canceled);
|
|
241
|
-
const hasPending = activeTickets.some((ticket) => ticket.doneAt === null);
|
|
242
|
-
if (hasPending)
|
|
243
|
-
return;
|
|
244
|
-
const latestTicketReadyAt = activeTickets.reduce((maxReadyAt, ticket) => {
|
|
245
|
-
const ticketReadyAt = (ticket.doneAt ?? barrier.openedAt) + ticket.tailMs;
|
|
246
|
-
return Math.max(maxReadyAt, ticketReadyAt);
|
|
247
|
-
}, barrier.fallbackReadyAt);
|
|
248
|
-
barrier.settled = true;
|
|
249
|
-
scheduleAutoResume(barrier.id, latestTicketReadyAt - Date.now());
|
|
250
|
-
}
|
|
251
|
-
function closeAutoCollection(barrierId) {
|
|
252
|
-
const barrier = getActiveAutoBarrier(barrierId);
|
|
253
|
-
if (barrier === null || barrier.settled)
|
|
254
|
-
return;
|
|
255
|
-
barrier.collecting = false;
|
|
256
|
-
trySettleAutoBarrier(barrier);
|
|
257
|
-
}
|
|
258
|
-
function scheduleAutoCollectionClose(barrierId) {
|
|
259
|
-
queueMicrotask(() => {
|
|
260
|
-
const barrier = getActiveAutoBarrier(barrierId);
|
|
261
|
-
if (barrier === null || barrier.settled)
|
|
262
|
-
return;
|
|
263
|
-
_autoCollectFrame = requestAnimationFrame(() => {
|
|
264
|
-
_autoCollectFrame = null;
|
|
265
|
-
closeAutoCollection(barrierId);
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
function markAutoTicketDone(ticket) {
|
|
270
|
-
if (ticket.canceled || ticket.doneAt !== null)
|
|
271
|
-
return;
|
|
272
|
-
ticket.doneAt = Date.now();
|
|
273
|
-
if (ticket.barrierId === null)
|
|
274
|
-
return;
|
|
275
|
-
const barrier = getActiveAutoBarrier(ticket.barrierId);
|
|
276
|
-
if (barrier === null || barrier.settled)
|
|
277
|
-
return;
|
|
278
|
-
trySettleAutoBarrier(barrier);
|
|
279
|
-
}
|
|
280
|
-
function cancelAutoTicket(ticket) {
|
|
281
|
-
if (ticket.canceled)
|
|
282
|
-
return;
|
|
283
|
-
ticket.canceled = true;
|
|
284
|
-
if (ticket.barrierId === null) {
|
|
285
|
-
_pendingAutoTickets.delete(ticket.id);
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
const barrier = getActiveAutoBarrier(ticket.barrierId);
|
|
289
|
-
if (barrier === null || barrier.settled)
|
|
290
|
-
return;
|
|
291
|
-
trySettleAutoBarrier(barrier);
|
|
292
|
-
}
|
|
293
|
-
function createAutoTicketHandle(ticket) {
|
|
294
|
-
return {
|
|
295
|
-
done() {
|
|
296
|
-
markAutoTicketDone(ticket);
|
|
297
|
-
},
|
|
298
|
-
cancel() {
|
|
299
|
-
cancelAutoTicket(ticket);
|
|
300
|
-
},
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
function schedulePendingAutoTicketExpiry(ticketId) {
|
|
304
|
-
queueMicrotask(() => {
|
|
305
|
-
requestAnimationFrame(() => {
|
|
306
|
-
_pendingAutoTickets.delete(ticketId);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
function createPendingAutoTicket(options) {
|
|
311
|
-
const ticketId = ++_autoTicketSeq;
|
|
312
|
-
const ticket = {
|
|
313
|
-
id: ticketId,
|
|
314
|
-
label: options?.label,
|
|
315
|
-
tailMs: options?.tailMs ?? autoRuntime.defaultTailMs,
|
|
316
|
-
doneAt: null,
|
|
317
|
-
canceled: false,
|
|
318
|
-
barrierId: null,
|
|
319
|
-
};
|
|
320
|
-
_pendingAutoTickets.set(ticketId, ticket);
|
|
321
|
-
schedulePendingAutoTicketExpiry(ticketId);
|
|
322
|
-
return createAutoTicketHandle(ticket);
|
|
323
|
-
}
|
|
324
|
-
function adoptPendingAutoTickets(barrier) {
|
|
325
|
-
for (const [ticketId, ticket] of _pendingAutoTickets) {
|
|
326
|
-
_pendingAutoTickets.delete(ticketId);
|
|
327
|
-
if (ticket.canceled)
|
|
328
|
-
continue;
|
|
329
|
-
ticket.barrierId = barrier.id;
|
|
330
|
-
barrier.tickets.set(ticketId, ticket);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
function openAutoBarrier(reason, fallbackMs) {
|
|
334
|
-
const safeFallbackMs = Number.isFinite(fallbackMs) ? Math.max(0, fallbackMs) : 0;
|
|
335
|
-
clearAutoBarrier();
|
|
336
|
-
_autoBarrier = {
|
|
337
|
-
id: ++_autoBarrierSeq,
|
|
338
|
-
reason,
|
|
339
|
-
collecting: true,
|
|
340
|
-
openedAt: Date.now(),
|
|
341
|
-
fallbackReadyAt: Date.now() + safeFallbackMs,
|
|
342
|
-
tickets: new Map(),
|
|
343
|
-
settled: false,
|
|
344
|
-
};
|
|
345
|
-
adoptPendingAutoTickets(_autoBarrier);
|
|
346
|
-
scheduleAutoCollectionClose(_autoBarrier.id);
|
|
347
|
-
}
|
|
348
|
-
function issueAutoTicket(options) {
|
|
349
|
-
if (!exports.autoState.active) {
|
|
350
|
-
return null;
|
|
351
|
-
}
|
|
352
|
-
if (_autoBarrier === null) {
|
|
353
|
-
return createPendingAutoTicket(options);
|
|
354
|
-
}
|
|
355
|
-
if (!_autoBarrier.collecting || _autoBarrier.settled) {
|
|
356
|
-
return null;
|
|
357
|
-
}
|
|
358
|
-
const ticketId = ++_autoTicketSeq;
|
|
359
|
-
const ticket = {
|
|
360
|
-
id: ticketId,
|
|
361
|
-
label: options?.label,
|
|
362
|
-
tailMs: options?.tailMs ?? autoRuntime.defaultTailMs,
|
|
363
|
-
doneAt: null,
|
|
364
|
-
canceled: false,
|
|
365
|
-
barrierId: _autoBarrier.id,
|
|
366
|
-
};
|
|
367
|
-
_autoBarrier.tickets.set(ticketId, ticket);
|
|
368
|
-
return createAutoTicketHandle(ticket);
|
|
369
|
-
}
|
|
370
|
-
/** Schedule a delayed nextLine() call for the auto. */
|
|
371
|
-
function scheduleAutoNextLine() {
|
|
372
|
-
if (_autoTimer !== null)
|
|
373
|
-
clearTimeout(_autoTimer);
|
|
374
|
-
_autoTimer = setTimeout(() => {
|
|
375
|
-
_autoTimer = null;
|
|
376
|
-
if (!exports.autoState.active)
|
|
377
|
-
return;
|
|
378
|
-
if (isAnyAutoBlockerActive()) {
|
|
379
|
-
stopAuto();
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
if (_autoBarrier === null) {
|
|
383
|
-
void (0, useScenario_1.nextLine)();
|
|
384
|
-
}
|
|
385
|
-
}, autoRuntime.defaultTailMs);
|
|
386
|
-
}
|
|
387
|
-
/** Schedule a delayed nextLine() call for the skip chain. */
|
|
388
|
-
function scheduleSkipNextLine() {
|
|
389
|
-
if (_skipTimer !== null)
|
|
390
|
-
clearTimeout(_skipTimer);
|
|
391
|
-
_skipTimer = setTimeout(() => {
|
|
392
|
-
_skipTimer = null;
|
|
393
|
-
if (exports.skipState.active)
|
|
394
|
-
(0, useScenario_1.nextLine)();
|
|
395
|
-
}, SKIP_INTERVAL_MS);
|
|
396
|
-
}
|
|
397
|
-
/** Enter skip mode. Called when Ctrl is pressed. */
|
|
398
|
-
function startSkip() {
|
|
399
|
-
if (exports.skipState.active)
|
|
400
|
-
return;
|
|
401
|
-
if (isAnyBlockerActive())
|
|
402
|
-
return;
|
|
403
|
-
exports.skipState.active = true;
|
|
404
|
-
invokeSkipCallbacks(); // finish current animations
|
|
405
|
-
tryInterrupt(); // finish current printing
|
|
406
|
-
scheduleSkipNextLine(); // kick off the chain
|
|
407
|
-
}
|
|
408
|
-
/** Exit skip mode. Called when Ctrl is released, window blurs, or Stage unmounts. */
|
|
409
|
-
function stopSkip() {
|
|
410
|
-
exports.skipState.active = false;
|
|
411
|
-
if (_skipTimer !== null) {
|
|
412
|
-
clearTimeout(_skipTimer);
|
|
413
|
-
_skipTimer = null;
|
|
414
|
-
// ensure engine continues normally
|
|
415
|
-
(0, useScenario_1.nextLine)();
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
function isSkipping() {
|
|
419
|
-
return exports.skipState.active;
|
|
420
|
-
}
|
|
421
|
-
function startAuto() {
|
|
422
|
-
if (exports.autoState.active)
|
|
423
|
-
return;
|
|
424
|
-
if (isAnyAutoBlockerActive())
|
|
425
|
-
return;
|
|
426
|
-
exports.autoState.active = true;
|
|
427
|
-
tryInterrupt(); // finish current printing
|
|
428
|
-
scheduleAutoNextLine(); // kick off the chain
|
|
429
|
-
}
|
|
430
|
-
function stopAuto() {
|
|
431
|
-
exports.autoState.active = false;
|
|
432
|
-
if (_autoTimer !== null) {
|
|
433
|
-
clearTimeout(_autoTimer);
|
|
434
|
-
_autoTimer = null;
|
|
435
|
-
}
|
|
436
|
-
clearAutoBarrier();
|
|
437
|
-
clearPendingAutoTickets();
|
|
438
|
-
}
|
|
439
|
-
function isAutoing() {
|
|
440
|
-
return exports.autoState.active;
|
|
441
|
-
}
|
|
442
|
-
// --- internal helpers ---
|
|
443
|
-
/** Build a one-shot GameControl for a single dispatch cycle. */
|
|
444
|
-
function buildControl() {
|
|
445
|
-
let handled = false;
|
|
446
|
-
let unskippableFlag = false;
|
|
447
|
-
const control = {
|
|
448
|
-
setWaiting(time, skippable) {
|
|
449
|
-
handled = true;
|
|
450
|
-
if (exports.skipState.active) {
|
|
451
|
-
// Skip mode: finish residual animations and continue the chain
|
|
452
|
-
invokeSkipCallbacks();
|
|
453
|
-
scheduleSkipNextLine();
|
|
454
|
-
}
|
|
455
|
-
else if (exports.autoState.active) {
|
|
456
|
-
if (isAnyAutoBlockerActive()) {
|
|
457
|
-
stopAuto();
|
|
458
|
-
(0, useScenario_1.setWaiting)(time, skippable);
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
openAutoBarrier('wait', time);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
(0, useScenario_1.setWaiting)(time, skippable);
|
|
466
|
-
}
|
|
467
|
-
},
|
|
468
|
-
hold() {
|
|
469
|
-
handled = true;
|
|
470
|
-
if (exports.skipState.active && !unskippableFlag) {
|
|
471
|
-
if (isAnyBlockerActive()) {
|
|
472
|
-
stopSkip();
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
475
|
-
scheduleSkipNextLine();
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
else if (exports.skipState.active && unskippableFlag) {
|
|
479
|
-
stopSkip();
|
|
480
|
-
}
|
|
481
|
-
else if (exports.autoState.active) {
|
|
482
|
-
if (isAnyAutoBlockerActive()) {
|
|
483
|
-
stopAuto();
|
|
484
|
-
}
|
|
485
|
-
else {
|
|
486
|
-
openAutoBarrier('hold', 0);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
// When not skipping: do nothing (normal hold behavior)
|
|
490
|
-
},
|
|
491
|
-
nextLine() {
|
|
492
|
-
handled = true;
|
|
493
|
-
void (0, useScenario_1.nextLine)();
|
|
494
|
-
},
|
|
495
|
-
unskippable() {
|
|
496
|
-
unskippableFlag = true;
|
|
497
|
-
},
|
|
498
|
-
record(meta) {
|
|
499
|
-
const result = (0, moyu_1.executePluginCommand)('scenario', {
|
|
500
|
-
subCommand: 'record',
|
|
501
|
-
meta,
|
|
502
|
-
});
|
|
503
|
-
if (result && typeof result.then === 'function') {
|
|
504
|
-
throw new Error('Scenario record command unexpectedly returned a Promise');
|
|
505
|
-
}
|
|
506
|
-
return result;
|
|
507
|
-
},
|
|
508
|
-
};
|
|
509
|
-
return { control, wasHandled: () => handled };
|
|
510
|
-
}
|
|
511
|
-
// Transform actual command object to a more convenient format
|
|
512
|
-
function transformCommand(command) {
|
|
513
|
-
if (commandSchema === null) {
|
|
514
|
-
throw new Error('No command schema registered in Stage');
|
|
515
|
-
}
|
|
516
|
-
const parsed = commandSchema.safeParse({
|
|
517
|
-
command: command.command,
|
|
518
|
-
...Object.fromEntries(command.arguments.map((arg) => [arg.name, arg.value])),
|
|
519
|
-
});
|
|
520
|
-
if (!parsed.success) {
|
|
521
|
-
throw new Error(`Invalid command: ${command.command} with arguments ${JSON.stringify(command.arguments)}`);
|
|
522
|
-
}
|
|
523
|
-
return parsed.data;
|
|
524
|
-
}
|
|
525
|
-
/** Dispatch a scenariocommandline event. */
|
|
526
|
-
function dispatchCommand(e) {
|
|
527
|
-
for (const cb of beforeHandleCommandCallbacks) {
|
|
528
|
-
try {
|
|
529
|
-
cb(e);
|
|
530
|
-
}
|
|
531
|
-
catch (err) {
|
|
532
|
-
console.error('Error in beforeHandleCommand callback:', err);
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
let cmd;
|
|
536
|
-
try {
|
|
537
|
-
cmd = transformCommand(e);
|
|
538
|
-
}
|
|
539
|
-
catch (err) {
|
|
540
|
-
console.error('Failed to transform scenario command:', err);
|
|
541
|
-
void (0, useScenario_1.nextLine)();
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
const handler = commandHandlers.get(cmd.command);
|
|
545
|
-
if (!handler) {
|
|
546
|
-
console.warn(`[Stage] No handler registered for command "${cmd.command}". Auto-advancing.`);
|
|
547
|
-
void (0, useScenario_1.nextLine)();
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
const { control, wasHandled } = buildControl();
|
|
551
|
-
handler(cmd, control);
|
|
552
|
-
// Default: auto-advance if handler didn't explicitly control flow
|
|
553
|
-
if (!wasHandled()) {
|
|
554
|
-
void (0, useScenario_1.nextLine)();
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
/** Dispatch a scenariotext event. */
|
|
558
|
-
function dispatchTextLine(e) {
|
|
559
|
-
const { control, wasHandled } = buildControl();
|
|
560
|
-
for (const handler of textLineHandlers) {
|
|
561
|
-
handler(e, control);
|
|
562
|
-
}
|
|
563
|
-
if (!wasHandled()) {
|
|
564
|
-
void (0, useScenario_1.nextLine)();
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
/** Invoke all skip callbacks. */
|
|
568
|
-
function invokeSkipCallbacks() {
|
|
569
|
-
for (const cb of skipCallbacks) {
|
|
570
|
-
try {
|
|
571
|
-
cb();
|
|
572
|
-
}
|
|
573
|
-
catch (err) {
|
|
574
|
-
console.error('Error in skip callback:', err);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
// --- bind engine events (called inside StageContextProvider's useEffect) ---
|
|
579
|
-
function bindEvents() {
|
|
580
|
-
const cleanups = [
|
|
581
|
-
(0, events_1.addEventListener)('scenariocommandline', (e) => {
|
|
582
|
-
dispatchCommand(e);
|
|
583
|
-
}),
|
|
584
|
-
(0, events_1.addEventListener)('scenariotext', (e) => {
|
|
585
|
-
dispatchTextLine(e);
|
|
586
|
-
}),
|
|
587
|
-
(0, events_1.addEventListener)('scenariowaiting', () => {
|
|
588
|
-
console.log('still waiting...');
|
|
589
|
-
}),
|
|
590
|
-
(0, events_1.addEventListener)('scenariowaitingcancelled', () => {
|
|
591
|
-
invokeSkipCallbacks();
|
|
592
|
-
}),
|
|
593
|
-
];
|
|
594
|
-
return () => {
|
|
595
|
-
for (const cleanup of cleanups)
|
|
596
|
-
cleanup();
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
return {
|
|
600
|
-
registerCommandSchema,
|
|
601
|
-
registerCommand,
|
|
602
|
-
registerTextLine,
|
|
603
|
-
addSkipCallback,
|
|
604
|
-
addInterruptCallback,
|
|
605
|
-
addSkipBlocker,
|
|
606
|
-
addAutoBlocker,
|
|
607
|
-
addBeforeHandleCommandCallback,
|
|
608
|
-
issueAutoTicket,
|
|
609
|
-
tryInterrupt,
|
|
610
|
-
startSkip,
|
|
611
|
-
stopSkip,
|
|
612
|
-
isSkipping,
|
|
613
|
-
startAuto,
|
|
614
|
-
stopAuto,
|
|
615
|
-
isAutoing,
|
|
616
|
-
bindEvents,
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
const StageContext = (0, react_1.createContext)(null);
|
|
620
|
-
/** Access the stage instance from within StageContextProvider. */
|
|
621
|
-
function useStageContext() {
|
|
622
|
-
const ctx = (0, react_1.useContext)(StageContext);
|
|
623
|
-
if (!ctx)
|
|
624
|
-
throw new Error('useStageContext must be used within StageContextProvider');
|
|
625
|
-
return ctx;
|
|
626
|
-
}
|
|
627
|
-
// ---------------------------------------------------------------------------
|
|
628
|
-
// StageContextProvider — binds engine events within React lifecycle
|
|
629
|
-
// ---------------------------------------------------------------------------
|
|
630
|
-
function StageContextProvider({ stage, children }) {
|
|
631
|
-
// Bind engine events on mount, unbind on unmount
|
|
632
|
-
(0, react_1.useEffect)(() => {
|
|
633
|
-
return stage.bindEvents();
|
|
634
|
-
}, [stage]);
|
|
635
|
-
return (0, react_1.createElement)(StageContext.Provider, { value: stage }, children);
|
|
636
|
-
}
|
|
637
|
-
// ---------------------------------------------------------------------------
|
|
638
|
-
// Actor hooks — register skip / interrupt callbacks
|
|
639
|
-
// ---------------------------------------------------------------------------
|
|
640
|
-
/**
|
|
641
|
-
* Register a skip callback that fires when scenariowaitingcancelled is received.
|
|
642
|
-
* Automatically removed on unmount.
|
|
643
|
-
*/
|
|
644
|
-
function useSkipCallback(callback) {
|
|
645
|
-
const stage = useStageContext();
|
|
646
|
-
(0, react_1.useEffect)(() => {
|
|
647
|
-
return stage.addSkipCallback(callback);
|
|
648
|
-
}, [stage, callback]);
|
|
649
|
-
}
|
|
650
|
-
/**
|
|
651
|
-
* Register an interrupt callback for user click handling.
|
|
652
|
-
* Return `true` from the callback to consume the click.
|
|
653
|
-
* Automatically removed on unmount.
|
|
654
|
-
*/
|
|
655
|
-
function useInterruptCallback(callback) {
|
|
656
|
-
const stage = useStageContext();
|
|
657
|
-
(0, react_1.useEffect)(() => {
|
|
658
|
-
return stage.addInterruptCallback(callback);
|
|
659
|
-
}, [stage, callback]);
|
|
660
|
-
}
|
|
661
|
-
/**
|
|
662
|
-
* Register a skip blocker callback. Return `true` to block skipping.
|
|
663
|
-
* When any blocker is active, skip mode cannot start or will be stopped.
|
|
664
|
-
* Automatically removed on unmount.
|
|
665
|
-
*
|
|
666
|
-
* NOTE: `callback` must be a stable reference (wrap with `useCallback`).
|
|
667
|
-
*/
|
|
668
|
-
function useSkipBlocker(callback) {
|
|
669
|
-
const stage = useStageContext();
|
|
670
|
-
(0, react_1.useEffect)(() => {
|
|
671
|
-
return stage.addSkipBlocker(callback);
|
|
672
|
-
}, [stage, callback]);
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Register an auto blocker callback. Return `true` to block auto mode.
|
|
676
|
-
* Automatically removed on unmount.
|
|
677
|
-
*
|
|
678
|
-
* NOTE: `callback` must be a stable reference (wrap with `useCallback`).
|
|
679
|
-
*/
|
|
680
|
-
function useAutoBlocker(callback) {
|
|
681
|
-
const stage = useStageContext();
|
|
682
|
-
(0, react_1.useEffect)(() => {
|
|
683
|
-
return stage.addAutoBlocker(callback);
|
|
684
|
-
}, [stage, callback]);
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Get a function that issues an auto ticket for the current active barrier.
|
|
688
|
-
* Returns `null` when auto is inactive or the collection window has closed.
|
|
689
|
-
*/
|
|
690
|
-
function useAutoTicket() {
|
|
691
|
-
const stage = useStageContext();
|
|
692
|
-
return (0, react_1.useCallback)((options) => {
|
|
693
|
-
return stage.issueAutoTicket(options);
|
|
694
|
-
}, [stage]);
|
|
695
|
-
}
|
|
696
|
-
/**
|
|
697
|
-
* Register a callback to be invoked before handling each command.
|
|
698
|
-
* The callback receives the upcoming command object, allowing conditional logic.
|
|
699
|
-
* Automatically removed on unmount.
|
|
700
|
-
*/
|
|
701
|
-
function useBeforeHandleCommandCallback(callback) {
|
|
702
|
-
const stage = useStageContext();
|
|
703
|
-
(0, react_1.useEffect)(() => {
|
|
704
|
-
return stage.addBeforeHandleCommandCallback(callback);
|
|
705
|
-
}, [stage, callback]);
|
|
706
|
-
}
|
package/dist/hooks.d.ts
DELETED