@novely/core 0.21.0 → 0.22.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/dist/chunk-YQR6UQKB.js +403 -0
- package/dist/chunk-YQR6UQKB.js.map +1 -0
- package/dist/index.d.ts +17 -6
- package/dist/index.global.js +4 -3
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/utils-RKG56tcx.d.ts +448 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.global.js +411 -0
- package/dist/utils.global.js.map +1 -0
- package/dist/utils.js +63 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
3
|
+
var BLOCK_EXIT_STATEMENTS = /* @__PURE__ */ new Set(["choice:exit", "condition:exit", "block:exit"]);
|
|
4
|
+
var BLOCK_STATEMENTS = /* @__PURE__ */ new Set(["choice", "condition", "block"]);
|
|
5
|
+
var AUDIO_ACTIONS = /* @__PURE__ */ new Set([
|
|
6
|
+
"playMusic",
|
|
7
|
+
"stopMusic",
|
|
8
|
+
"playSound",
|
|
9
|
+
"stopSound",
|
|
10
|
+
"voice",
|
|
11
|
+
"stopVoice"
|
|
12
|
+
]);
|
|
13
|
+
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
14
|
+
var DEFAULT_TYPEWRITER_SPEED = "Medium";
|
|
15
|
+
var MAIN_CONTEXT_KEY = "$MAIN";
|
|
16
|
+
|
|
17
|
+
// src/shared.ts
|
|
18
|
+
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
19
|
+
|
|
20
|
+
// src/utils.ts
|
|
21
|
+
var matchAction = (getContext, values) => {
|
|
22
|
+
return (action, props, { ctx, data }) => {
|
|
23
|
+
const context = typeof ctx === "string" ? getContext(ctx) : ctx;
|
|
24
|
+
return values[action]({
|
|
25
|
+
ctx: context,
|
|
26
|
+
data
|
|
27
|
+
}, props);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
var isNumber = (val) => {
|
|
31
|
+
return typeof val === "number";
|
|
32
|
+
};
|
|
33
|
+
var isNull = (val) => {
|
|
34
|
+
return val === null;
|
|
35
|
+
};
|
|
36
|
+
var isString = (val) => {
|
|
37
|
+
return typeof val === "string";
|
|
38
|
+
};
|
|
39
|
+
var isFunction = (val) => {
|
|
40
|
+
return typeof val === "function";
|
|
41
|
+
};
|
|
42
|
+
var isPromise = (val) => {
|
|
43
|
+
return Boolean(val) && (typeof val === "object" || isFunction(val)) && isFunction(val.then);
|
|
44
|
+
};
|
|
45
|
+
var isEmpty = (val) => {
|
|
46
|
+
return typeof val === "object" && !isNull(val) && Object.keys(val).length === 0;
|
|
47
|
+
};
|
|
48
|
+
var isCSSImage = (str2) => {
|
|
49
|
+
const startsWith = String.prototype.startsWith.bind(str2);
|
|
50
|
+
return startsWith("http") || startsWith("/") || startsWith(".") || startsWith("data");
|
|
51
|
+
};
|
|
52
|
+
var str = String;
|
|
53
|
+
var isUserRequiredAction = (action, meta) => {
|
|
54
|
+
return action === "custom" && meta[0] && meta[0].requireUserAction;
|
|
55
|
+
};
|
|
56
|
+
var getLanguage = (languages) => {
|
|
57
|
+
let { language } = navigator;
|
|
58
|
+
if (languages.includes(language)) {
|
|
59
|
+
return language;
|
|
60
|
+
} else if (languages.includes(language = language.slice(0, 2))) {
|
|
61
|
+
return language;
|
|
62
|
+
} else if (language = languages.find((value) => navigator.languages.includes(value))) {
|
|
63
|
+
return language;
|
|
64
|
+
}
|
|
65
|
+
return languages[0];
|
|
66
|
+
};
|
|
67
|
+
var throttle = (fn, ms) => {
|
|
68
|
+
let throttled = false, savedArgs, savedThis;
|
|
69
|
+
function wrapper(...args) {
|
|
70
|
+
if (throttled) {
|
|
71
|
+
savedArgs = args;
|
|
72
|
+
savedThis = this;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
fn.apply(this, args);
|
|
76
|
+
throttled = true;
|
|
77
|
+
setTimeout(function() {
|
|
78
|
+
throttled = false;
|
|
79
|
+
if (savedArgs) {
|
|
80
|
+
wrapper.apply(savedThis, savedArgs);
|
|
81
|
+
savedArgs = savedThis = null;
|
|
82
|
+
}
|
|
83
|
+
}, ms);
|
|
84
|
+
}
|
|
85
|
+
return wrapper;
|
|
86
|
+
};
|
|
87
|
+
var findLastIndex = (array, fn) => {
|
|
88
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
89
|
+
if (fn(array[i], array[i + 1])) {
|
|
90
|
+
return i;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return -1;
|
|
94
|
+
};
|
|
95
|
+
var findLast = (array, fn) => {
|
|
96
|
+
return array[findLastIndex(array, fn)];
|
|
97
|
+
};
|
|
98
|
+
var createControlledPromise = () => {
|
|
99
|
+
const object = {
|
|
100
|
+
resolve: null,
|
|
101
|
+
reject: null,
|
|
102
|
+
promise: null,
|
|
103
|
+
cancel: null
|
|
104
|
+
};
|
|
105
|
+
const init = () => {
|
|
106
|
+
const promise = new Promise((resolve, reject) => {
|
|
107
|
+
object.reject = reject;
|
|
108
|
+
object.resolve = (value) => {
|
|
109
|
+
resolve({ cancelled: false, value });
|
|
110
|
+
};
|
|
111
|
+
object.cancel = () => {
|
|
112
|
+
resolve({ cancelled: true, value: null });
|
|
113
|
+
init();
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
object.promise = promise;
|
|
117
|
+
};
|
|
118
|
+
return init(), object;
|
|
119
|
+
};
|
|
120
|
+
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
121
|
+
const index = findLastIndex(path, ([_name, _value], next) => {
|
|
122
|
+
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
123
|
+
});
|
|
124
|
+
return path[index];
|
|
125
|
+
};
|
|
126
|
+
var isBlockStatement = (statement) => {
|
|
127
|
+
return BLOCK_STATEMENTS.has(statement);
|
|
128
|
+
};
|
|
129
|
+
var isBlockExitStatement = (statement) => {
|
|
130
|
+
return BLOCK_EXIT_STATEMENTS.has(statement);
|
|
131
|
+
};
|
|
132
|
+
var isSkippedDuringRestore = (item) => {
|
|
133
|
+
return SKIPPED_DURING_RESTORE.has(item);
|
|
134
|
+
};
|
|
135
|
+
var noop = () => {
|
|
136
|
+
};
|
|
137
|
+
var isAction = (element) => {
|
|
138
|
+
return Array.isArray(element) && isString(element[0]);
|
|
139
|
+
};
|
|
140
|
+
var flattenStory = (story) => {
|
|
141
|
+
const entries = Object.entries(story).map(([name, items]) => {
|
|
142
|
+
const flat = (item) => {
|
|
143
|
+
return item.flatMap((data) => {
|
|
144
|
+
const type = data[0];
|
|
145
|
+
if (Array.isArray(type))
|
|
146
|
+
return flat(data);
|
|
147
|
+
return [data];
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
return [name, flat(items)];
|
|
151
|
+
});
|
|
152
|
+
return Object.fromEntries(entries);
|
|
153
|
+
};
|
|
154
|
+
var once = (fn) => {
|
|
155
|
+
let ran = false;
|
|
156
|
+
return () => {
|
|
157
|
+
if (ran)
|
|
158
|
+
return;
|
|
159
|
+
ran = true;
|
|
160
|
+
fn();
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
var isExitImpossible = (path) => {
|
|
164
|
+
const blockStatements = path.filter(([item]) => isBlockStatement(item));
|
|
165
|
+
const blockExitStatements = path.filter(([item]) => isBlockExitStatement(item));
|
|
166
|
+
if (blockStatements.length === 0 && blockExitStatements.length === 0) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
if (blockStatements.length > blockExitStatements.length) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return !blockExitStatements.every(([name], i) => name && name.startsWith(blockStatements[i][0]));
|
|
173
|
+
};
|
|
174
|
+
var getOppositeAction = (action) => {
|
|
175
|
+
const MAP = {
|
|
176
|
+
"showCharacter": "hideCharacter",
|
|
177
|
+
"playSound": "stopSound",
|
|
178
|
+
"playMusic": "stopMusic",
|
|
179
|
+
"voice": "stopVoice"
|
|
180
|
+
};
|
|
181
|
+
return MAP[action];
|
|
182
|
+
};
|
|
183
|
+
var getActionsFromPath = (story, path, raw = false) => {
|
|
184
|
+
let current = story;
|
|
185
|
+
let precurrent;
|
|
186
|
+
let ignoreNested = false;
|
|
187
|
+
let index = 0;
|
|
188
|
+
const max = path.reduce((acc, [type, val]) => {
|
|
189
|
+
if (isNull(type) && isNumber(val)) {
|
|
190
|
+
return acc + 1;
|
|
191
|
+
}
|
|
192
|
+
return acc;
|
|
193
|
+
}, 0);
|
|
194
|
+
const queue = [];
|
|
195
|
+
const blocks = [];
|
|
196
|
+
for (const [type, val] of path) {
|
|
197
|
+
if (type === "jump") {
|
|
198
|
+
precurrent = story;
|
|
199
|
+
current = current[val];
|
|
200
|
+
} else if (type === null) {
|
|
201
|
+
precurrent = current;
|
|
202
|
+
if (isNumber(val)) {
|
|
203
|
+
index++;
|
|
204
|
+
let startIndex = 0;
|
|
205
|
+
if (ignoreNested) {
|
|
206
|
+
const prev = findLastPathItemBeforeItemOfType(path.slice(0, index), "block");
|
|
207
|
+
if (prev) {
|
|
208
|
+
startIndex = prev[1];
|
|
209
|
+
ignoreNested = false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (let i = startIndex; i <= val; i++) {
|
|
213
|
+
const item = current[i];
|
|
214
|
+
if (!isAction(item))
|
|
215
|
+
continue;
|
|
216
|
+
const [action, ...meta] = item;
|
|
217
|
+
const push = () => {
|
|
218
|
+
queue.push([action, meta]);
|
|
219
|
+
};
|
|
220
|
+
if (raw) {
|
|
221
|
+
push();
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (isSkippedDuringRestore(action) || isUserRequiredAction(action, meta)) {
|
|
225
|
+
if (index === max && i === val) {
|
|
226
|
+
push();
|
|
227
|
+
}
|
|
228
|
+
continue;
|
|
229
|
+
} else {
|
|
230
|
+
push();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
current = current[val];
|
|
235
|
+
} else if (type === "choice") {
|
|
236
|
+
blocks.push(precurrent);
|
|
237
|
+
current = current[val + 1][1];
|
|
238
|
+
} else if (type === "condition") {
|
|
239
|
+
blocks.push(precurrent);
|
|
240
|
+
current = current[2][val];
|
|
241
|
+
} else if (type === "block") {
|
|
242
|
+
blocks.push(precurrent);
|
|
243
|
+
current = story[val];
|
|
244
|
+
} else if (type === "block:exit" || type === "choice:exit" || type === "condition:exit") {
|
|
245
|
+
current = blocks.pop();
|
|
246
|
+
ignoreNested = true;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return queue;
|
|
250
|
+
};
|
|
251
|
+
var createQueueProcessor = (queue) => {
|
|
252
|
+
const processedQueue = [];
|
|
253
|
+
const keep = /* @__PURE__ */ new Set();
|
|
254
|
+
const characters = /* @__PURE__ */ new Set();
|
|
255
|
+
const audio = {
|
|
256
|
+
music: /* @__PURE__ */ new Set(),
|
|
257
|
+
sound: /* @__PURE__ */ new Set()
|
|
258
|
+
};
|
|
259
|
+
const next = (i) => queue.slice(i + 1);
|
|
260
|
+
for (const [i, [action, meta]] of queue.entries()) {
|
|
261
|
+
keep.add(action);
|
|
262
|
+
if (action === "function" || action === "custom") {
|
|
263
|
+
if (action === "custom" && meta[0].callOnlyLatest) {
|
|
264
|
+
const notLatest = next(i).some(([, _meta]) => {
|
|
265
|
+
if (!_meta || !meta)
|
|
266
|
+
return false;
|
|
267
|
+
const c0 = _meta[0];
|
|
268
|
+
const c1 = meta[0];
|
|
269
|
+
const isIdenticalID = c0.id && c1.id && c0.id === c1.id;
|
|
270
|
+
const isIdenticalByReference = c0 === c1;
|
|
271
|
+
return isIdenticalID || isIdenticalByReference || str(c0) === str(c1);
|
|
272
|
+
});
|
|
273
|
+
if (notLatest)
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
processedQueue.push([action, meta]);
|
|
277
|
+
} else if (action === "showCharacter" || action === "playSound" || action === "playMusic" || action === "voice") {
|
|
278
|
+
const closing = getOppositeAction(action);
|
|
279
|
+
const skip = next(i).some(([_action, _meta]) => {
|
|
280
|
+
if (!_meta || !meta)
|
|
281
|
+
return false;
|
|
282
|
+
if (_meta[0] !== meta[0])
|
|
283
|
+
return false;
|
|
284
|
+
return _action === closing || _action === action;
|
|
285
|
+
});
|
|
286
|
+
if (skip)
|
|
287
|
+
continue;
|
|
288
|
+
if (action === "showCharacter") {
|
|
289
|
+
characters.add(meta[0]);
|
|
290
|
+
} else if (action === "playMusic") {
|
|
291
|
+
audio.music.add(meta[0]);
|
|
292
|
+
} else if (action === "playSound") {
|
|
293
|
+
audio.sound.add(meta[0]);
|
|
294
|
+
}
|
|
295
|
+
processedQueue.push([action, meta]);
|
|
296
|
+
} else if (action === "showBackground" || action === "animateCharacter" || action === "preload") {
|
|
297
|
+
const skip = next(i).some(([_action], i2, array) => action === _action);
|
|
298
|
+
if (skip)
|
|
299
|
+
continue;
|
|
300
|
+
processedQueue.push([action, meta]);
|
|
301
|
+
} else {
|
|
302
|
+
processedQueue.push([action, meta]);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const run = async (match) => {
|
|
306
|
+
for await (const [action, meta] of processedQueue) {
|
|
307
|
+
const result = match(action, meta);
|
|
308
|
+
if (isPromise(result)) {
|
|
309
|
+
await result;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
processedQueue.length = 0;
|
|
313
|
+
};
|
|
314
|
+
const getKeep = () => {
|
|
315
|
+
return {
|
|
316
|
+
keep,
|
|
317
|
+
characters,
|
|
318
|
+
audio
|
|
319
|
+
};
|
|
320
|
+
};
|
|
321
|
+
return {
|
|
322
|
+
run,
|
|
323
|
+
getKeep
|
|
324
|
+
};
|
|
325
|
+
};
|
|
326
|
+
var getStack = (ctx) => {
|
|
327
|
+
const { id } = ctx;
|
|
328
|
+
const cached = STACK_MAP.get(id);
|
|
329
|
+
if (cached)
|
|
330
|
+
return cached;
|
|
331
|
+
const stack = [];
|
|
332
|
+
STACK_MAP.set(id, stack);
|
|
333
|
+
return stack;
|
|
334
|
+
};
|
|
335
|
+
var createUseStackFunction = (renderer) => {
|
|
336
|
+
const useStack = (context) => {
|
|
337
|
+
const ctx = typeof context === "string" ? renderer.getContext(context) : context;
|
|
338
|
+
const stack = getStack(ctx);
|
|
339
|
+
return {
|
|
340
|
+
get previous() {
|
|
341
|
+
return stack.previous;
|
|
342
|
+
},
|
|
343
|
+
get value() {
|
|
344
|
+
return stack.at(-1);
|
|
345
|
+
},
|
|
346
|
+
set value(value) {
|
|
347
|
+
stack[stack.length - 1] = value;
|
|
348
|
+
},
|
|
349
|
+
back() {
|
|
350
|
+
if (stack.length > 1) {
|
|
351
|
+
stack.previous = stack.pop();
|
|
352
|
+
ctx.meta.goingBack = true;
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
push(value) {
|
|
356
|
+
stack.push(value);
|
|
357
|
+
},
|
|
358
|
+
clear() {
|
|
359
|
+
stack.length = 0;
|
|
360
|
+
stack.length = 1;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
return useStack;
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
export {
|
|
368
|
+
AUDIO_ACTIONS,
|
|
369
|
+
EMPTY_SET,
|
|
370
|
+
DEFAULT_TYPEWRITER_SPEED,
|
|
371
|
+
MAIN_CONTEXT_KEY,
|
|
372
|
+
STACK_MAP,
|
|
373
|
+
matchAction,
|
|
374
|
+
isNumber,
|
|
375
|
+
isNull,
|
|
376
|
+
isString,
|
|
377
|
+
isFunction,
|
|
378
|
+
isPromise,
|
|
379
|
+
isEmpty,
|
|
380
|
+
isCSSImage,
|
|
381
|
+
str,
|
|
382
|
+
isUserRequiredAction,
|
|
383
|
+
getLanguage,
|
|
384
|
+
throttle,
|
|
385
|
+
findLastIndex,
|
|
386
|
+
findLast,
|
|
387
|
+
createControlledPromise,
|
|
388
|
+
findLastPathItemBeforeItemOfType,
|
|
389
|
+
isBlockStatement,
|
|
390
|
+
isBlockExitStatement,
|
|
391
|
+
isSkippedDuringRestore,
|
|
392
|
+
noop,
|
|
393
|
+
isAction,
|
|
394
|
+
flattenStory,
|
|
395
|
+
once,
|
|
396
|
+
isExitImpossible,
|
|
397
|
+
getOppositeAction,
|
|
398
|
+
getActionsFromPath,
|
|
399
|
+
createQueueProcessor,
|
|
400
|
+
getStack,
|
|
401
|
+
createUseStackFunction
|
|
402
|
+
};
|
|
403
|
+
//# sourceMappingURL=chunk-YQR6UQKB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/shared.ts","../src/utils.ts"],"sourcesContent":["import type { TypewriterSpeed } from './types';\n\nconst SKIPPED_DURING_RESTORE = new Set(['dialog', 'choice', 'input', 'vibrate', 'text'] as const);\n\nconst BLOCK_EXIT_STATEMENTS = new Set(['choice:exit', 'condition:exit', 'block:exit'] as const);\n\nconst BLOCK_STATEMENTS = new Set(['choice', 'condition', 'block'] as const);\n\nconst AUDIO_ACTIONS = new Set([\n 'playMusic',\n 'stopMusic',\n 'playSound',\n 'stopSound',\n 'voice',\n 'stopVoice'\n] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nconst DEFAULT_TYPEWRITER_SPEED: TypewriterSpeed = 'Medium';\n\n/**\n * @internal\n */\nconst MAIN_CONTEXT_KEY = '$MAIN';\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET, DEFAULT_TYPEWRITER_SPEED, BLOCK_EXIT_STATEMENTS, BLOCK_STATEMENTS, MAIN_CONTEXT_KEY, AUDIO_ACTIONS };\n","import type { StackHolder } from './types';\n\n/**\n * @internal\n */\nconst STACK_MAP = new Map<string, StackHolder>();\n\nexport { STACK_MAP }\n","import type { ActionProxyProvider, DefaultActionProxyProvider, CustomHandler, Story, ValidAction, GetActionParameters } from './action';\nimport type { Character } from './character';\nimport type { Thenable, Path, PathItem, Save, UseStackFunctionReturnType, StackHolder } from './types';\nimport type { Context, Renderer } from './renderer';\nimport { BLOCK_STATEMENTS, BLOCK_EXIT_STATEMENTS, SKIPPED_DURING_RESTORE } from './constants';\nimport { STACK_MAP } from './shared';\n\ntype MatchActionParams = {\n\tdata: Record<string, unknown>\n\tctx: Context\n}\n\ntype MatchActionMap = {\n\t[Key in keyof DefaultActionProxyProvider]: (params: MatchActionParams, data: Parameters<DefaultActionProxyProvider[Key]>) => void;\n};\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n\tcustom: (params: MatchActionParams, value: [handler: CustomHandler]) => Thenable<void>;\n};\n\ntype MatchActionParameters = {\n\t/**\n\t * Name of context or context\n\t */\n\tctx: string | Context;\n\t/**\n\t * Data from the save\n\t */\n\tdata: Record<string, unknown>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(getContext: (name: string) => Context, values: M) => {\n\treturn (action: keyof MatchActionMapComplete, props: any, { ctx, data }: MatchActionParameters) => {\n\t\tconst context = typeof ctx === 'string' ? getContext(ctx) : ctx;\n\n\t\treturn values[action]({\n\t\t\tctx: context,\n\t\t\tdata,\n\t\t}, props);\n\t};\n};\n\nconst isNumber = (val: unknown): val is number => {\n\treturn typeof val === 'number';\n};\n\nconst isNull = (val: unknown): val is null => {\n\treturn val === null;\n};\n\nconst isString = (val: unknown): val is string => {\n\treturn typeof val === 'string';\n};\n\nconst isFunction = (val: unknown): val is (...parameters: any[]) => any => {\n\treturn typeof val === 'function';\n};\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n\treturn Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then);\n};\n\nconst isEmpty = (val: unknown): val is Record<PropertyKey, never> => {\n\treturn typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n};\n\nconst isCSSImage = (str: string) => {\n\tconst startsWith = String.prototype.startsWith.bind(str);\n\n\treturn startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n};\n\nconst str = String;\n\nconst isUserRequiredAction = (\n\taction: keyof MatchActionMapComplete,\n\tmeta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>,\n) => {\n\treturn action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n};\n\nconst getLanguage = (languages: string[]) => {\n\tlet { language } = navigator;\n\n\tif (languages.includes(language)) {\n\t\treturn language;\n\t} else if (languages.includes((language = language.slice(0, 2)))) {\n\t\treturn language;\n\t} else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n\t\treturn language;\n\t}\n\n\t/**\n\t * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n\t */\n\treturn languages[0];\n};\n\n/**\n * @copyright Techlead LLC\n * @see https://learn.javascript.ru/task/throttle\n */\nconst throttle = <Fn extends (...args: any[]) => any>(fn: Fn, ms: number) => {\n\tlet throttled = false,\n\t\tsavedArgs: any,\n\t\tsavedThis: any;\n\n\tfunction wrapper(this: any, ...args: any[]) {\n\t\tif (throttled) {\n\t\t\tsavedArgs = args;\n\t\t\t/* eslint-disable @typescript-eslint/no-this-alias */\n\t\t\tsavedThis = this;\n\t\t\treturn;\n\t\t}\n\n\t\tfn.apply(this, args as unknown as any[]);\n\n\t\tthrottled = true;\n\n\t\tsetTimeout(function () {\n\t\t\tthrottled = false;\n\n\t\t\tif (savedArgs) {\n\t\t\t\twrapper.apply(savedThis, savedArgs);\n\t\t\t\tsavedArgs = savedThis = null;\n\t\t\t}\n\t\t}, ms);\n\t}\n\n\treturn wrapper as unknown as (...args: Parameters<Fn>) => void;\n};\n\nconst findLastIndex = <T>(array: T[], fn: (item: T, next?: T) => boolean) => {\n\tfor (let i = array.length - 1; i >= 0; i--) {\n\t\tif (fn(array[i], array[i + 1])) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n};\n\nconst findLast = <T>(array: T[], fn: (item: T, next?: T) => boolean) => {\n\treturn array[findLastIndex(array, fn)];\n}\n\ntype ControlledPromise<T> = Promise<\n\t| {\n\t\t\tvalue: T;\n\t\t\tcancelled: false;\n\t }\n\t| {\n\t\t\tvalue: null;\n\t\t\tcancelled: true;\n\t }\n>;\n\ntype ControlledPromiseObj<T> = {\n\tresolve: (value: T | PromiseLike<T>) => void;\n\treject: (reason?: any) => void;\n\n\tpromise: ControlledPromise<T>;\n\n\tcancel: () => void;\n};\n\nconst createControlledPromise = <T = void>() => {\n\tconst object = {\n\t\tresolve: null,\n\t\treject: null,\n\n\t\tpromise: null,\n\n\t\tcancel: null,\n\t} as unknown as ControlledPromiseObj<T>;\n\n\tconst init = () => {\n\t\tconst promise = new Promise((resolve, reject) => {\n\t\t\tobject.reject = reject;\n\t\t\tobject.resolve = (value) => {\n\t\t\t\tresolve({ cancelled: false, value });\n\t\t\t};\n\n\t\t\tobject.cancel = () => {\n\t\t\t\tresolve({ cancelled: true, value: null });\n\t\t\t\tinit();\n\t\t\t};\n\t\t});\n\n\t\t// @ts-expect-error Types does not match and this is expected\n\t\tobject.promise = promise;\n\t};\n\n\treturn init(), object;\n};\n\nconst findLastPathItemBeforeItemOfType = (path: Path, name: PathItem[0]) => {\n\tconst index = findLastIndex(path, ([_name, _value], next) => {\n\t\treturn isNull(_name) && isNumber(_value) && next != null && next[0] === name;\n\t});\n\n\treturn path[index] as undefined | [null, number];\n};\n\nconst isBlockStatement = (statement: unknown): statement is 'choice' | 'condition' | 'block' => {\n\treturn BLOCK_STATEMENTS.has(statement as any);\n};\n\nconst isBlockExitStatement = (\n\tstatement: unknown,\n): statement is 'choice:exit' | 'condition:exit' | 'block:exit' => {\n\treturn BLOCK_EXIT_STATEMENTS.has(statement as any);\n};\n\nconst isSkippedDuringRestore = (item: unknown): item is 'vibrate' | 'dialog' | 'input' | 'choice' | 'text' => {\n\treturn SKIPPED_DURING_RESTORE.has(item as any);\n};\n\nconst noop = () => {};\n\nconst isAction = (\n\telement: unknown,\n): element is [\n\tkeyof MatchActionMapComplete,\n\t...Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>,\n] => {\n\treturn Array.isArray(element) && isString(element[0]);\n};\n\n/**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\nconst flattenStory = (story: Story) => {\n\tconst entries = Object.entries(story).map(([name, items]) => {\n\t\tconst flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n\t\t\treturn item.flatMap((data) => {\n\t\t\t\tconst type = data[0];\n\n\t\t\t\t/**\n\t\t\t\t * This is not just an action like `['name', ...arguments]`, but an array of actions\n\t\t\t\t */\n\t\t\t\tif (Array.isArray(type)) return flat(data as ValidAction[]);\n\n\t\t\t\treturn [data as ValidAction];\n\t\t\t});\n\t\t};\n\n\t\treturn [name, flat(items)];\n\t});\n\n\treturn Object.fromEntries(entries);\n};\n\n/**\n * A wrapper on `fn` to make it run only once!\n * @param fn Function that needed to run no more than one time\n */\nconst once = (fn: () => void) => {\n\tlet ran = false;\n\n\treturn () => {\n\t\tif (ran) return;\n\n\t\tran = true;\n\t\tfn();\n\t};\n};\n\nconst isExitImpossible = (path: Path) => {\n\tconst blockStatements = path.filter(([item]) => isBlockStatement(item));\n\tconst blockExitStatements = path.filter(([item]) => isBlockExitStatement(item));\n\n\t/**\n\t * There were no blocks nor exits from blocks\n\t */\n\tif (blockStatements.length === 0 && blockExitStatements.length === 0) {\n\t\treturn true;\n\t}\n\n\t/**\n\t * There is block that can be exited\n\t */\n\tif (blockStatements.length > blockExitStatements.length) {\n\t\treturn false;\n\t}\n\n\treturn !blockExitStatements.every(([name], i) => name && name.startsWith(blockStatements[i][0]!))\n}\n\nconst getOppositeAction = (action: 'showCharacter' | 'playSound' | 'playMusic' | 'voice' | any) => {\n\tconst MAP = {\n\t\t'showCharacter': 'hideCharacter',\n\t\t'playSound': 'stopSound',\n\t\t'playMusic': 'stopMusic',\n\t\t'voice': 'stopVoice'\n\t} as const;\n\n\treturn MAP[action as keyof typeof MAP];\n}\n\nconst getActionsFromPath = (story: Story, path: Path, raw: boolean = false) => {\n\t/**\n\t * Current item in the story\n\t */\n\tlet current: any = story;\n\t/**\n\t * Previous `current` value\n\t */\n\tlet precurrent: any;\n\t/**\n\t * Should we ignore some actions\n\t */\n\tlet ignoreNested = false;\n\t/**\n\t * Current item of type `[null, int]`\n\t */\n\tlet index = 0;\n\n\t/**\n\t * Cound of items of type `[null, int]`\n\t */\n\tconst max = path.reduce((acc, [type, val]) => {\n\t\tif (isNull(type) && isNumber(val)) {\n\t\t\treturn acc + 1;\n\t\t}\n\n\t\treturn acc;\n\t}, 0);\n\n\tconst queue = [] as [any, any][];\n\tconst blocks = [];\n\n\tfor (const [type, val] of path) {\n\t\tif (type === 'jump') {\n\t\t\tprecurrent = story;\n\t\t\tcurrent = current[val];\n\t\t} else if (type === null) {\n\t\t\tprecurrent = current;\n\n\t\t\tif (isNumber(val)) {\n\t\t\t\tindex++;\n\n\t\t\t\tlet startIndex = 0;\n\n\t\t\t\tif (ignoreNested) {\n\t\t\t\t\tconst prev = findLastPathItemBeforeItemOfType(path.slice(0, index), 'block');\n\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tstartIndex = prev[1];\n\t\t\t\t\t\tignoreNested = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n\t\t\t\t * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n\t\t\t\t */\n\t\t\t\tfor (let i = startIndex; i <= val; i++) {\n\t\t\t\t\tconst item = current[i];\n\n\t\t\t\t\t/**\n\t\t\t\t\t * In case of broken save at least not throw\n\t\t\t\t\t * But is should not happen\n\t\t\t\t\t */\n\t\t\t\t\tif (!isAction(item)) continue;\n\n\t\t\t\t\tconst [action, ...meta] = item;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Add item to queue and action to keep\n\t\t\t\t\t */\n\t\t\t\t\tconst push = () => {\n\t\t\t\t\t\tqueue.push([action, meta]);\n\t\t\t\t\t};\n\n\t\t\t\t\t/**\n\t\t\t\t\t * In case we want pure data then just add it\n\t\t\t\t\t */\n\t\t\t\t\tif (raw) {\n\t\t\t\t\t\tpush();\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n\t\t\t\t\t * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n\t\t\t\t\t */\n\t\t\t\t\tif (isSkippedDuringRestore(action) || isUserRequiredAction(action, meta)) {\n\t\t\t\t\t\tif (index === max && i === val) {\n\t\t\t\t\t\t\tpush();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpush();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrent = current[val];\n\t\t} else if (type === 'choice') {\n\t\t\tblocks.push(precurrent);\n\t\t\tcurrent = current[val + 1][1];\n\t\t} else if (type === 'condition') {\n\t\t\tblocks.push(precurrent);\n\t\t\tcurrent = current[2][val];\n\t\t} else if (type === 'block') {\n\t\t\tblocks.push(precurrent);\n\t\t\tcurrent = story[val];\n\t\t} else if (type === 'block:exit' || type === 'choice:exit' || type === 'condition:exit') {\n\t\t\tcurrent = blocks.pop();\n\t\t\tignoreNested = true;\n\t\t}\n\t}\n\n\treturn queue;\n}\n\nconst createQueueProcessor = (queue: [any, any][]) => {\n\tconst processedQueue: [any, any][] = [];\n\n\tconst keep = new Set();\n\tconst characters = new Set();\n\tconst audio = {\n\t\tmusic: new Set(),\n\t\tsound: new Set()\n\t};\n\n\t/**\n\t * Get the next actions array.\n\t */\n\tconst next = (i: number) => queue.slice(i + 1);\n\n\tfor (const [i, [action, meta]] of queue.entries()) {\n\t\t/**\n\t\t * Keep actually does not keep any actions, clear method only works with things like `dialog` which can blink and etc\n\t\t * So it's just easies to add everything in there\n\t\t */\n\t\tkeep.add(action);\n\n\t\tif (action === 'function' || action === 'custom') {\n\t\t\t/**\n\t\t\t * When `callOnlyLatest` is `true`\n\t\t\t */\n\t\t\tif (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n\t\t\t\t/**\n\t\t\t\t * We'll calculate it is `latest` or not\n\t\t\t\t */\n\t\t\t\tconst notLatest = next(i).some(([, _meta]) => {\n\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\tconst c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\t\t\t\t\tconst c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Also check for `undefined`\n\t\t\t\t\t */\n\t\t\t\t\tconst isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n\t\t\t\t\tconst isIdenticalByReference = c0 === c1;\n\n\t\t\t\t\treturn isIdenticalID || isIdenticalByReference || str(c0) === str(c1);\n\t\t\t\t});\n\n\t\t\t\tif (notLatest) continue;\n\t\t\t}\n\n\t\t\tprocessedQueue.push([action, meta]);\n\t\t} else if (action === 'showCharacter' || action === 'playSound' || action === 'playMusic' || action === 'voice') {\n\t\t\tconst closing = getOppositeAction(action);\n\n\t\t\tconst skip = next(i).some(([_action, _meta]) => {\n\t\t\t\tif (!_meta || !meta) return false;\n\t\t\t\tif (_meta[0] !== meta[0]) return false;\n\n\t\t\t\t/**\n\t\t\t\t * It either will be closed OR same action will be ran again\n\t\t\t\t */\n\t\t\t\treturn _action === closing || _action === action;\n\t\t\t});\n\n\t\t\tif (skip) continue;\n\n\t\t\t/**\n\t\t\t * Actually, we do not need check above to add there things to keep because if something was hidden already we could not keep it visible\n\t\t\t */\n\t\t\tif (action === 'showCharacter') {\n\t\t\t\tcharacters.add(meta[0])\n\t\t\t} else if (action === 'playMusic') {\n\t\t\t\taudio.music.add(meta[0])\n\t\t\t} else if (action === 'playSound') {\n\t\t\t\taudio.sound.add(meta[0])\n\t\t\t}\n\n\t\t\tprocessedQueue.push([action, meta]);\n\t\t} else if (action === 'showBackground' || action === 'animateCharacter' || action === 'preload') {\n\t\t\t/**\n\t\t\t * @todo: Также сравнивать персонажей в animateCharacter. Чтобы не просто последний запускался, а последний для персонажа.\n\t\t\t * Тем не менее таким образом могут быть лишнии анимации.\n\t\t\t * Можно проверить, что одна анимация идёт сразу за другой, а не через, например, dialog\n\t\t\t */\n\n\t\t\t/**\n\t\t\t * Такая же оптимизация применяется к фонам и анимированию персонажей, и `preload`.\n\t\t\t * Если фон изменится, то нет смысла устанавливать или предзагружать текущий\n\t\t\t */\n\t\t\tconst skip = next(i).some(([_action], i, array) => action === _action);\n\n\t\t\tif (skip) continue;\n\n\t\t\tprocessedQueue.push([action, meta]);\n\t\t} else {\n\t\t\tprocessedQueue.push([action, meta]);\n\t\t}\n\t}\n\n\tconst run = async (match: (action: keyof ActionProxyProvider<Record<string, Character>, string>, props: any) => Thenable<void>) => {\n\t\tfor await (const [action, meta] of processedQueue) {\n\t\t\tconst result = match(action, meta);\n\n\t\t\tif (isPromise(result)) {\n\t\t\t\tawait result;\n\t\t\t}\n\t\t}\n\n\t\tprocessedQueue.length = 0;\n\t}\n\n\tconst getKeep = () => {\n\t\treturn {\n\t\t\tkeep,\n\t\t\tcharacters,\n\t\t\taudio\n\t\t}\n\t}\n\n\treturn {\n\t\trun,\n\t\tgetKeep\n\t}\n}\n\nconst getStack = (ctx: Context) => {\n\tconst { id } = ctx;\n\tconst cached = STACK_MAP.get(id);\n\n\tif (cached) return cached;\n\n\tconst stack = [] as unknown as StackHolder;\n\n\tSTACK_MAP.set(id, stack);\n\n\treturn stack;\n}\n\nconst createUseStackFunction = (renderer: Renderer) => {\n\tconst useStack = (context: Context | string): UseStackFunctionReturnType => {\n\t\tconst ctx = typeof context === 'string' ? renderer.getContext(context) : context;\n\t\tconst stack = getStack(ctx);\n\n\t\treturn {\n\t\t\tget previous() {\n\t\t\t\treturn stack.previous;\n\t\t\t},\n\t\t\tget value() {\n\t\t\t\treturn stack.at(-1)!;\n\t\t\t},\n\t\t\tset value(value) {\n\t\t\t\tstack[stack.length - 1] = value;\n\t\t\t},\n\n\t\t\tback() {\n\t\t\t\tif (stack.length > 1) {\n\t\t\t\t\tstack.previous = stack.pop();\n\t\t\t\t\tctx.meta.goingBack = true;\n\t\t\t\t}\n\t\t\t},\n\t\t\tpush(value: Save) {\n\t\t\t\tstack.push(value);\n\t\t\t},\n\t\t\tclear() {\n\t\t\t\tstack.length = 0;\n\t\t\t\tstack.length = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn useStack;\n}\n\nexport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetLanguage,\n\tthrottle,\n\tisFunction,\n\tfindLastIndex,\n\tfindLast,\n\tcreateControlledPromise,\n\tfindLastPathItemBeforeItemOfType,\n\tisBlockStatement,\n\tisBlockExitStatement,\n\tisSkippedDuringRestore,\n\tnoop,\n\tisAction,\n\tflattenStory,\n\tonce,\n\tisExitImpossible,\n\tgetOppositeAction,\n\tgetActionsFromPath,\n\tcreateQueueProcessor,\n\tgetStack,\n\tcreateUseStackFunction\n};\n"],"mappings":"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","names":["str","i"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ type CoreData = {
|
|
|
37
37
|
dataLoaded: boolean;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
|
|
40
|
+
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta<string>) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
|
|
41
41
|
type Story = Record<string, ValidAction[]>;
|
|
42
42
|
type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
|
|
43
43
|
type FunctionableValue<T> = T | (() => T);
|
|
@@ -63,7 +63,14 @@ type CustomHandlerGetResult<I extends boolean> = {
|
|
|
63
63
|
*/
|
|
64
64
|
clear: (fn: () => void) => void;
|
|
65
65
|
};
|
|
66
|
-
type
|
|
66
|
+
type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
|
|
67
|
+
type CustomHandlerFunctionParameters = {
|
|
68
|
+
get: CustomHandlerFunctionGetFn;
|
|
69
|
+
goingBack: boolean;
|
|
70
|
+
preview: boolean;
|
|
71
|
+
lang: string;
|
|
72
|
+
};
|
|
73
|
+
type CustomHandlerFunction = (parameters: CustomHandlerFunctionParameters) => Thenable<void>;
|
|
67
74
|
type CustomHandler = CustomHandlerFunction & {
|
|
68
75
|
callOnlyLatest?: boolean;
|
|
69
76
|
requireUserAction?: boolean;
|
|
@@ -71,7 +78,7 @@ type CustomHandler = CustomHandlerFunction & {
|
|
|
71
78
|
id?: string | symbol;
|
|
72
79
|
key: string;
|
|
73
80
|
};
|
|
74
|
-
interface ActionInputOnInputMeta {
|
|
81
|
+
interface ActionInputOnInputMeta<L extends string> {
|
|
75
82
|
/**
|
|
76
83
|
* Input Element itself
|
|
77
84
|
*/
|
|
@@ -91,6 +98,10 @@ interface ActionInputOnInputMeta {
|
|
|
91
98
|
* Sanitized `input.value`
|
|
92
99
|
*/
|
|
93
100
|
value: string;
|
|
101
|
+
/**
|
|
102
|
+
* Language
|
|
103
|
+
*/
|
|
104
|
+
lang: L;
|
|
94
105
|
}
|
|
95
106
|
type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
|
|
96
107
|
type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
|
|
@@ -132,7 +143,7 @@ type ActionProxyProvider<Characters extends Record<string, Character>, Languages
|
|
|
132
143
|
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
133
144
|
wait: (time: FunctionableValue<number>) => ValidAction;
|
|
134
145
|
function: (fn: (restoring: boolean, goingBack: boolean, preview: boolean) => Thenable<void>) => ValidAction;
|
|
135
|
-
input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
|
|
146
|
+
input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta<Languages>) => void, setup?: ActionInputSetup) => ValidAction;
|
|
136
147
|
custom: (handler: CustomHandler) => ValidAction;
|
|
137
148
|
vibrate: (...pattern: number[]) => ValidAction;
|
|
138
149
|
next: () => ValidAction;
|
|
@@ -261,7 +272,7 @@ type Renderer = {
|
|
|
261
272
|
background: (background: string | BackgroundImage) => void;
|
|
262
273
|
dialog: (content: string, name: string, character: string | undefined, emotion: string | undefined, resolve: () => void) => void;
|
|
263
274
|
choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[], resolve: (selected: number) => void) => void;
|
|
264
|
-
input: (question: string, onInput: (meta: ActionInputOnInputMeta) => void, setup: ActionInputSetup, resolve: () => void) => void;
|
|
275
|
+
input: (question: string, onInput: (meta: ActionInputOnInputMeta<string>) => void, setup: ActionInputSetup, resolve: () => void) => void;
|
|
265
276
|
clear: (keep: Set<keyof DefaultActionProxyProvider>, keepCharacters: Set<string>, keepAudio: {
|
|
266
277
|
music: Set<string>;
|
|
267
278
|
sounds: Set<string>;
|
|
@@ -464,4 +475,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
464
475
|
unwrap(content: string | (() => string) | Record<Languages, string> | Exclude<Record<Languages, string | (() => string)>, Record<string, string>>): string;
|
|
465
476
|
};
|
|
466
477
|
|
|
467
|
-
export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
|
|
478
|
+
export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
|
package/dist/index.global.js
CHANGED
|
@@ -248,7 +248,7 @@ var Novely = (() => {
|
|
|
248
248
|
};
|
|
249
249
|
var findLastIndex = (array, fn) => {
|
|
250
250
|
for (let i = array.length - 1; i >= 0; i--) {
|
|
251
|
-
if (fn(array[i],
|
|
251
|
+
if (fn.call(array, array[i], i, array)) {
|
|
252
252
|
return i;
|
|
253
253
|
}
|
|
254
254
|
}
|
|
@@ -277,7 +277,8 @@ var Novely = (() => {
|
|
|
277
277
|
return init(), object;
|
|
278
278
|
};
|
|
279
279
|
var findLastPathItemBeforeItemOfType = (path, name) => {
|
|
280
|
-
const index = findLastIndex(path, ([_name, _value],
|
|
280
|
+
const index = findLastIndex(path, ([_name, _value], i, array) => {
|
|
281
|
+
const next = array[i + 1];
|
|
281
282
|
return isNull(_name) && isNumber(_value) && next != null && next[0] === name;
|
|
282
283
|
});
|
|
283
284
|
return path[index];
|
|
@@ -1242,7 +1243,7 @@ var Novely = (() => {
|
|
|
1242
1243
|
}
|
|
1243
1244
|
if (ctx.meta.preview)
|
|
1244
1245
|
return;
|
|
1245
|
-
const handler = (get) => {
|
|
1246
|
+
const handler = ({ get }) => {
|
|
1246
1247
|
const { clear } = get(false);
|
|
1247
1248
|
const char = ctx.getCharacter(character);
|
|
1248
1249
|
if (!char)
|