@novely/core 0.5.0 → 0.6.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/index.d.ts +26 -9
- package/dist/index.global.js +64 -44
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +47 -28
- package/dist/index.js.map +1 -1
- package/package.json +61 -61
package/dist/index.d.ts
CHANGED
|
@@ -19,11 +19,11 @@ type Path = PathItem[];
|
|
|
19
19
|
type State = Record<string, any>;
|
|
20
20
|
type Data = Record<string, any>;
|
|
21
21
|
type SaveDate = number;
|
|
22
|
-
type SaveType =
|
|
22
|
+
type SaveType = 'manual' | 'auto';
|
|
23
23
|
type SaveMeta = [SaveDate, SaveType];
|
|
24
24
|
type Save = [Path, State, SaveMeta];
|
|
25
25
|
type Lang = string;
|
|
26
|
-
type TypewriterSpeed =
|
|
26
|
+
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & {});
|
|
27
27
|
type StorageMeta = [Lang, TypewriterSpeed];
|
|
28
28
|
type Migration = (save: unknown) => unknown;
|
|
29
29
|
type StorageData = {
|
|
@@ -37,7 +37,7 @@ type Stack = {
|
|
|
37
37
|
push(value: Save): void;
|
|
38
38
|
clear(): void;
|
|
39
39
|
};
|
|
40
|
-
type NovelyScreen =
|
|
40
|
+
type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
41
41
|
/**
|
|
42
42
|
* @see https://pendletonjones.com/deep-partial
|
|
43
43
|
*/
|
|
@@ -47,7 +47,7 @@ type DeepPartial<T> = unknown extends T ? T : T extends object ? {
|
|
|
47
47
|
|
|
48
48
|
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['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'] | ValidAction[];
|
|
49
49
|
type Story = Record<string, ValidAction[]>;
|
|
50
|
-
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string>;
|
|
50
|
+
type Unwrappable = string | ((lang: string, obj: Record<string, unknown>) => string) | Record<string, string | (() => string)>;
|
|
51
51
|
type FunctionableValue<T> = T | (() => T);
|
|
52
52
|
type CustomHandlerGetResultDataFunction = {
|
|
53
53
|
(data?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -150,7 +150,7 @@ interface CharacterHandle {
|
|
|
150
150
|
withEmotion: (emotion: string) => () => void;
|
|
151
151
|
append: (className?: string, style?: string, restoring?: boolean) => void;
|
|
152
152
|
remove: (className?: string, style?: string, duration?: number) => (resolve: () => void, restoring: boolean) => void;
|
|
153
|
-
emotions: Record<string, HTMLImageElement | Record<
|
|
153
|
+
emotions: Record<string, HTMLImageElement | Record<'head' | 'left' | 'right', HTMLImageElement>>;
|
|
154
154
|
}
|
|
155
155
|
interface AudioHandle {
|
|
156
156
|
element: HTMLAudioElement;
|
|
@@ -160,7 +160,7 @@ interface AudioHandle {
|
|
|
160
160
|
}
|
|
161
161
|
interface RendererStore {
|
|
162
162
|
characters: Record<string, CharacterHandle>;
|
|
163
|
-
audio: Partial<Record<
|
|
163
|
+
audio: Partial<Record<'music', AudioHandle>>;
|
|
164
164
|
}
|
|
165
165
|
type Renderer = {
|
|
166
166
|
character: (character: string) => CharacterHandle;
|
|
@@ -177,7 +177,7 @@ type Renderer = {
|
|
|
177
177
|
/**
|
|
178
178
|
* Показывает экран, скрывает другие
|
|
179
179
|
*/
|
|
180
|
-
showScreen(name:
|
|
180
|
+
showScreen(name: 'mainmenu' | 'game' | 'saves' | 'settings' | 'loading'): void;
|
|
181
181
|
};
|
|
182
182
|
};
|
|
183
183
|
type RendererInit = {
|
|
@@ -255,8 +255,25 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
|
|
|
255
255
|
* Migration from old saves to newer
|
|
256
256
|
*/
|
|
257
257
|
migrations?: Migration[];
|
|
258
|
+
/**
|
|
259
|
+
* For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage
|
|
260
|
+
* @default 799
|
|
261
|
+
*/
|
|
262
|
+
throttleTimeout?: number;
|
|
263
|
+
/**
|
|
264
|
+
* Custom language detector
|
|
265
|
+
* @param languages Supported languages aka `languages: []` in the config
|
|
266
|
+
* @example ```ts
|
|
267
|
+
* novely({
|
|
268
|
+
* getLanguage(languages) {
|
|
269
|
+
* return sdk.environment.i18n.lang // i.e. custom language from some sdk
|
|
270
|
+
* }
|
|
271
|
+
* })
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
getLanguage?: (languages: string[]) => string;
|
|
258
275
|
}
|
|
259
|
-
declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends _novely_t9n.T9N<Languages, string>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, t9n, languages, state: defaultState, data: defaultData, autosaves, migrations }: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {
|
|
276
|
+
declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends _novely_t9n.T9N<Languages, string>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, t9n, languages, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage }: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {
|
|
260
277
|
/**
|
|
261
278
|
* Function to set story
|
|
262
279
|
*/
|
|
@@ -282,7 +299,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
282
299
|
/**
|
|
283
300
|
* Unwraps translatable content to a string value
|
|
284
301
|
*/
|
|
285
|
-
unwrap(content:
|
|
302
|
+
unwrap(content: Unwrappable | Record<Languages, string>): string;
|
|
286
303
|
/**
|
|
287
304
|
* Function that is used for translation
|
|
288
305
|
*/
|
package/dist/index.global.js
CHANGED
|
@@ -273,36 +273,31 @@ var Novely = (() => {
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
// src/constants.ts
|
|
276
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set([
|
|
277
|
-
"dialog",
|
|
278
|
-
"choice",
|
|
279
|
-
"input",
|
|
280
|
-
"vibrate",
|
|
281
|
-
"text"
|
|
282
|
-
]);
|
|
276
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
283
277
|
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
284
278
|
|
|
285
279
|
// ../t9n/dist/index.js
|
|
286
|
-
var
|
|
280
|
+
var d = (e, o) => {
|
|
287
281
|
let r = [];
|
|
288
|
-
for (let a of
|
|
282
|
+
for (let a of o) {
|
|
289
283
|
if (!e)
|
|
290
284
|
break;
|
|
291
|
-
let [t,
|
|
292
|
-
r.push(t), e =
|
|
285
|
+
let [t, i] = e.split(a, 2);
|
|
286
|
+
r.push(t), e = i;
|
|
293
287
|
}
|
|
294
288
|
return r.push(e), r;
|
|
295
289
|
};
|
|
296
|
-
var
|
|
297
|
-
var
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
290
|
+
var m = /{{(.*?)}}/g;
|
|
291
|
+
var l = (e) => Array.isArray(e) ? e.map((o) => l(o)).join("<br>") : typeof e == "function" ? l(e()) : e;
|
|
292
|
+
var T = (e, o, r, a, t) => l(e).replace(m, (i, s, n) => {
|
|
293
|
+
i = 0, n = o;
|
|
294
|
+
let [c, g, u] = d(s.trim(), ["@", "%"]), S = c.split(".");
|
|
295
|
+
for (; n && i < S.length; )
|
|
296
|
+
n = n[S[i++]];
|
|
302
297
|
g && r && n && t && (n = r[g][t.select(n)]);
|
|
303
|
-
let
|
|
304
|
-
return
|
|
305
|
-
})
|
|
298
|
+
let p = a && u && a[u];
|
|
299
|
+
return p && (n = p(n)), n ?? "";
|
|
300
|
+
});
|
|
306
301
|
|
|
307
302
|
// src/novely.ts
|
|
308
303
|
var novely = ({
|
|
@@ -316,7 +311,9 @@ var Novely = (() => {
|
|
|
316
311
|
state: defaultState,
|
|
317
312
|
data: defaultData,
|
|
318
313
|
autosaves = true,
|
|
319
|
-
migrations = []
|
|
314
|
+
migrations = [],
|
|
315
|
+
throttleTimeout = 799,
|
|
316
|
+
getLanguage: getLanguage2 = getLanguage
|
|
320
317
|
}) => {
|
|
321
318
|
let story;
|
|
322
319
|
let times = /* @__PURE__ */ new Set();
|
|
@@ -326,17 +323,19 @@ var Novely = (() => {
|
|
|
326
323
|
return times.add(value), value;
|
|
327
324
|
};
|
|
328
325
|
const withStory = (s) => {
|
|
329
|
-
story = Object.fromEntries(
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
326
|
+
story = Object.fromEntries(
|
|
327
|
+
Object.entries(s).map(([name, items]) => {
|
|
328
|
+
const flat = (item) => {
|
|
329
|
+
return item.flatMap((data2) => {
|
|
330
|
+
const type = data2[0];
|
|
331
|
+
if (Array.isArray(type))
|
|
332
|
+
return flat(data2);
|
|
333
|
+
return [data2];
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
return [name, flat(items)];
|
|
337
|
+
})
|
|
338
|
+
);
|
|
340
339
|
if (initialScreen !== "game")
|
|
341
340
|
renderer.ui.showScreen(initialScreen);
|
|
342
341
|
};
|
|
@@ -355,7 +354,14 @@ var Novely = (() => {
|
|
|
355
354
|
stack.value[1] = val;
|
|
356
355
|
}
|
|
357
356
|
const getDefaultSave = (state2 = {}) => {
|
|
358
|
-
return [
|
|
357
|
+
return [
|
|
358
|
+
[
|
|
359
|
+
[null, "start"],
|
|
360
|
+
[null, 0]
|
|
361
|
+
],
|
|
362
|
+
state2,
|
|
363
|
+
[intime(Date.now()), "auto"]
|
|
364
|
+
];
|
|
359
365
|
};
|
|
360
366
|
const createStack = (current, stack2 = [current]) => {
|
|
361
367
|
return {
|
|
@@ -380,7 +386,7 @@ var Novely = (() => {
|
|
|
380
386
|
const initialData = {
|
|
381
387
|
saves: [],
|
|
382
388
|
data: klona(defaultData),
|
|
383
|
-
meta: [
|
|
389
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
384
390
|
};
|
|
385
391
|
const $ = store(initialData);
|
|
386
392
|
let initialDataLoaded = false;
|
|
@@ -388,14 +394,14 @@ var Novely = (() => {
|
|
|
388
394
|
if (initialDataLoaded)
|
|
389
395
|
storage.set(value);
|
|
390
396
|
};
|
|
391
|
-
const throttledOnStorageDataChange = throttle(onStorageDataChange,
|
|
397
|
+
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
392
398
|
$.subscribe(throttledOnStorageDataChange);
|
|
393
399
|
const getStoredData = () => {
|
|
394
400
|
storage.get().then((stored) => {
|
|
395
401
|
for (const migration of migrations) {
|
|
396
402
|
stored = migration(stored);
|
|
397
403
|
}
|
|
398
|
-
stored.meta[0] ||=
|
|
404
|
+
stored.meta[0] ||= getLanguage2(languages);
|
|
399
405
|
stored.meta[1] ||= getTypewriterSpeed();
|
|
400
406
|
if (isEmpty(stored.data)) {
|
|
401
407
|
stored.data = defaultData;
|
|
@@ -455,7 +461,11 @@ var Novely = (() => {
|
|
|
455
461
|
return;
|
|
456
462
|
let latest = save2 ? save2 : $.get().saves.at(-1);
|
|
457
463
|
if (!latest) {
|
|
458
|
-
$.update(() => ({
|
|
464
|
+
$.update(() => ({
|
|
465
|
+
saves: [initial],
|
|
466
|
+
data: klona(defaultData),
|
|
467
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
468
|
+
}));
|
|
459
469
|
latest = klona(initial);
|
|
460
470
|
}
|
|
461
471
|
restoring = true, stack.value = latest;
|
|
@@ -620,9 +630,9 @@ var Novely = (() => {
|
|
|
620
630
|
},
|
|
621
631
|
dialog([character, content, emotion]) {
|
|
622
632
|
const name = (() => {
|
|
623
|
-
const
|
|
633
|
+
const c = character, cs = characters;
|
|
624
634
|
const lang = $.get().meta[0];
|
|
625
|
-
return
|
|
635
|
+
return c ? c in cs ? typeof cs[c].name === "string" ? cs[c].name : cs[c].name[lang] : c : "";
|
|
626
636
|
})();
|
|
627
637
|
renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);
|
|
628
638
|
},
|
|
@@ -641,7 +651,10 @@ var Novely = (() => {
|
|
|
641
651
|
const unwrapped = choices.map(([content, action2, visible]) => {
|
|
642
652
|
return [unwrap(content), action2, visible];
|
|
643
653
|
});
|
|
644
|
-
renderer.choices(
|
|
654
|
+
renderer.choices(
|
|
655
|
+
unwrap(question),
|
|
656
|
+
unwrapped
|
|
657
|
+
)((selected) => {
|
|
645
658
|
enmemory();
|
|
646
659
|
const offset = isWithoutQuestion ? 0 : 1;
|
|
647
660
|
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
@@ -650,7 +663,10 @@ var Novely = (() => {
|
|
|
650
663
|
});
|
|
651
664
|
},
|
|
652
665
|
jump([scene]) {
|
|
653
|
-
stack.value[0] = [
|
|
666
|
+
stack.value[0] = [
|
|
667
|
+
[null, scene],
|
|
668
|
+
[null, -1]
|
|
669
|
+
];
|
|
654
670
|
match("clear", []);
|
|
655
671
|
},
|
|
656
672
|
clear([keep, characters2]) {
|
|
@@ -760,10 +776,14 @@ var Novely = (() => {
|
|
|
760
776
|
interacted = value;
|
|
761
777
|
};
|
|
762
778
|
const unwrap = (content, global = false) => {
|
|
763
|
-
const {
|
|
779
|
+
const {
|
|
780
|
+
data: data2,
|
|
781
|
+
meta: [lang]
|
|
782
|
+
} = $.get();
|
|
764
783
|
const obj = global ? data2 : state();
|
|
765
|
-
const
|
|
766
|
-
|
|
784
|
+
const cnt = isFunction(content) ? content(lang, obj) : typeof content === "string" ? content : content[lang];
|
|
785
|
+
const str2 = isFunction(cnt) ? cnt() : cnt;
|
|
786
|
+
return T(str2, obj);
|
|
767
787
|
};
|
|
768
788
|
function data(value) {
|
|
769
789
|
if (!value)
|
package/dist/index.global.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js","../src/index.ts","../src/utils.ts","../src/store.ts","../src/novely.ts","../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/json/index.mjs","../src/constants.ts","../../t9n/src/lib.ts","../../t9n/src/translation.ts","../../t9n/src/translations.ts","../src/storage.ts"],"sourcesContent":["'use strict';\n\nvar isMergeableObject = function isMergeableObject(value) {\n\treturn isNonNullObject(value)\n\t\t&& !isSpecial(value)\n};\n\nfunction isNonNullObject(value) {\n\treturn !!value && typeof value === 'object'\n}\n\nfunction isSpecial(value) {\n\tvar stringValue = Object.prototype.toString.call(value);\n\n\treturn stringValue === '[object RegExp]'\n\t\t|| stringValue === '[object Date]'\n\t\t|| isReactElement(value)\n}\n\n// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25\nvar canUseSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;\n\nfunction isReactElement(value) {\n\treturn value.$$typeof === REACT_ELEMENT_TYPE\n}\n\nfunction emptyTarget(val) {\n\treturn Array.isArray(val) ? [] : {}\n}\n\nfunction cloneUnlessOtherwiseSpecified(value, options) {\n\treturn (options.clone !== false && options.isMergeableObject(value))\n\t\t? deepmerge(emptyTarget(value), value, options)\n\t\t: value\n}\n\nfunction defaultArrayMerge(target, source, options) {\n\treturn target.concat(source).map(function(element) {\n\t\treturn cloneUnlessOtherwiseSpecified(element, options)\n\t})\n}\n\nfunction getMergeFunction(key, options) {\n\tif (!options.customMerge) {\n\t\treturn deepmerge\n\t}\n\tvar customMerge = options.customMerge(key);\n\treturn typeof customMerge === 'function' ? customMerge : deepmerge\n}\n\nfunction getEnumerableOwnPropertySymbols(target) {\n\treturn Object.getOwnPropertySymbols\n\t\t? Object.getOwnPropertySymbols(target).filter(function(symbol) {\n\t\t\treturn Object.propertyIsEnumerable.call(target, symbol)\n\t\t})\n\t\t: []\n}\n\nfunction getKeys(target) {\n\treturn Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))\n}\n\nfunction propertyIsOnObject(object, property) {\n\ttry {\n\t\treturn property in object\n\t} catch(_) {\n\t\treturn false\n\t}\n}\n\n// Protects from prototype poisoning and unexpected merging up the prototype chain.\nfunction propertyIsUnsafe(target, key) {\n\treturn propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,\n\t\t&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,\n\t\t\t&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.\n}\n\nfunction mergeObject(target, source, options) {\n\tvar destination = {};\n\tif (options.isMergeableObject(target)) {\n\t\tgetKeys(target).forEach(function(key) {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n\t\t});\n\t}\n\tgetKeys(source).forEach(function(key) {\n\t\tif (propertyIsUnsafe(target, key)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {\n\t\t\tdestination[key] = getMergeFunction(key, options)(target[key], source[key], options);\n\t\t} else {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(source[key], options);\n\t\t}\n\t});\n\treturn destination\n}\n\nfunction deepmerge(target, source, options) {\n\toptions = options || {};\n\toptions.arrayMerge = options.arrayMerge || defaultArrayMerge;\n\toptions.isMergeableObject = options.isMergeableObject || isMergeableObject;\n\t// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n\t// implementations can use it. The caller may not replace it.\n\toptions.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;\n\n\tvar sourceIsArray = Array.isArray(source);\n\tvar targetIsArray = Array.isArray(target);\n\tvar sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n\tif (!sourceAndTargetTypesMatch) {\n\t\treturn cloneUnlessOtherwiseSpecified(source, options)\n\t} else if (sourceIsArray) {\n\t\treturn options.arrayMerge(target, source, options)\n\t} else {\n\t\treturn mergeObject(target, source, options)\n\t}\n}\n\ndeepmerge.all = function deepmergeAll(array, options) {\n\tif (!Array.isArray(array)) {\n\t\tthrow new Error('first argument should be an array')\n\t}\n\n\treturn array.reduce(function(prev, next) {\n\t\treturn deepmerge(prev, next, options)\n\t}, {})\n};\n\nvar deepmerge_1 = deepmerge;\n\nmodule.exports = deepmerge_1;\n","export type { ValidAction, Story, ActionProxyProvider, DefaultActionProxyProvider, GetActionParameters, Unwrappable, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, FunctionableValue } from './action'\nexport type { Emotions, Character } from './character'\nexport type { CharacterHandle, AudioHandle, RendererStore, Renderer, RendererInit } from './renderer'\nexport type { Storage } from './storage'\nexport type { Thenable, Path, StorageData, StorageMeta, TypewriterSpeed, Lang, NovelyScreen } from './types'\nexport type { Stored } from './store'\nexport type { BaseTranslationStrings } from '@novely/t9n';\n\nexport { novely } from './novely'\nexport { localStorageStorage } from './storage'","import type { ActionProxyProvider, CustomHandler } from './action'\nimport type { Character } from './character'\nimport type { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n return Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then)\n}\n\nconst isEmpty = (val: unknown): val is {} => {\n return typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Prevent `undefined`\n */\n defaultData ||= {} as DataScheme;\n defaultState ||= {} as StateScheme;\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: klona(defaultData) as Data,\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * When data is empty replace it with `defaultData`\n * It also might be empty (default to empty)\n */\n if (isEmpty(stored.data)) {\n stored.data = defaultData as Data;\n }\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: klona(defaultData) as Data, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n const keep = new Set();\n const characters = new Set();\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n */\n for (let i = 0; i <= val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Add item to queue and action to keep\n */\n const push = () => {\n keep.add(action);\n queue.push([action, meta]);\n }\n\n /**\n * Do not remove characters that will be here anyways\n */\n if (action === 'showCharacter') characters.add(meta[0]);\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n push();\n } else {\n continue;\n }\n }\n\n push();\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n queue.forEach((value, index) => {\n /**\n * Mutate the queue item\n */\n value.push(index);\n });\n\n /**\n * This is basically made for TypeScript.\n */\n const indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n /**\n * Run these exactly before the main loop.\n */\n renderer.ui.showScreen('game');\n /**\n * Provide the `keep` in there\n */\n match('clear', [keep, characters]);\n\n /**\n * Get the next actions array.\n */\n const next = (i: number) => indexedQueue.slice(i + 1);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * When `callOnlyLatest` is `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * We'll calculate it is `latest` or not\n */\n const notLatest = next(i).some(([_action, _meta]) => {\n if (!_meta || !meta) return false;\n\n const c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n const c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n /**\n * Also check for `undefined`\n */\n const isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n \n /**\n * Equal by id or equal by `toString()`\n */\n return isIdenticalID || (str(c0) === str(c1));\n });\n\n if (notLatest) continue;\n }\n\n /**\n * Action can return Promise. \n */\n const result = match(action, meta);\n\n /**\n * Should wait until it resolved\n */\n if (isPromise(result)) {\n /**\n * Await it!\n */\n await result;\n }\n } else if (action === 'showCharacter') {\n const skip = next(i).some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground' || action === 'animateCharacter') {\n /**\n * Такая же оптимизация применяется к фонам и анимированию персонажей.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next(i).some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Person name\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * If there is a question, then `index` should be shifted by `1`\n */\n const offset = isWithoutQuestion ? 0 : 1;\n\n stack.value[0].push(['choice', selected + offset], [null, 0]);\n render();\n interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear([keep, characters]) {\n /**\n * Remove vibration\n */\n vibrate(0);\n /**\n * Call the actual `clear`\n */\n renderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n target.classList.remove(...classNames);\n \n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n /**\n * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n */\n match('custom', [handler]);\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n function data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n function data(): DataScheme;\n function data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n if (!value) return $.get().data as DataScheme | void;\n\n const prev = $.get().data;\n const val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n $.update((prev) => {\n prev.data = val;\n\n return prev;\n });\n }\n\n return {\n /**\n * Function to set story\n */\n withStory,\n /**\n * Function to get actions\n */\n action,\n /**\n * State that belongs to games\n */\n state,\n /**\n * Unlike `state`, stored at global scope instead and shared between games\n */\n data,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n /**\n * Function that is used for translation\n */\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","export function klona(val) {\n\tvar k, out, tmp;\n\n\tif (Array.isArray(val)) {\n\t\tout = Array(k=val.length);\n\t\twhile (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\treturn out;\n\t}\n\n\tif (Object.prototype.toString.call(val) === '[object Object]') {\n\t\tout = {}; // null\n\t\tfor (k in val) {\n\t\t\tif (k === '__proto__') {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tvalue: klona(val[k]),\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tout[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn val;\n}\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET }","const split = (input: string, delimeters: string[]) => {\n const output: (string | undefined)[] = [];\n\n for (const delimeter of delimeters) {\n if (!input) break;\n\n const [start, end] = input.split(delimeter, 2);\n\n output.push(start); input = end;\n }\n\n output.push(input);\n\n return output;\n}\n\nexport { split }","import type { BaseTranslationStrings } from './translations';\nimport { split } from './lib';\n\ntype PluralType = Intl.LDMLPluralRule;\ntype FunctionalSetupT9N = <LanguageKey extends string, PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\ntype SetupT9N<LanguageKey extends string> = <PluralKey extends string, StringKey extends string, Actions extends string>(parameters: { [Lang in LanguageKey]: { pluralization: { [Plural in PluralKey]: Partial<Record<PluralType, string>> }; internal: { [Key in BaseTranslationStrings]: string }; strings: { [Str in StringKey]: string }; actions?: { [Action in Actions]?: (value: string) => string; } } }) => T9N<LanguageKey, StringKey>\n\ntype T9N<LanguageKey extends string, StringKey extends string> = {\n t(key: StringKey | Record<LanguageKey, string>): (lang: LanguageKey | (string & {}), obj: Record<string, unknown>) => string;\n i(key: StringKey, lang: LanguageKey | (string & {})): string;\n}\n\nconst RGX = /{{(.*?)}}/g;\n\nconst replace = (str: string | string[], obj: Record<string, unknown>, pluralization?: Record<string, Record<string, PluralType>>, actions?: Partial<Record<string, (str: string) => string>>, pr?: Intl.PluralRules) => {\n if (Array.isArray(str)) str = str.join('');\n\n return str.replace(RGX, (x: any, key: string, y: any) => {\n x = 0;\n y = obj;\n\n const [pathstr, plural, action] = split(key.trim(), ['@', '%']);\n\n let path = pathstr!.split('.');\n\n while (y && x < path.length) y = y[path[x++]];\n\n if (plural && pluralization && y && pr) {\n y = pluralization[plural][pr.select(y)];\n }\n\n const actionHandler = actions && action && actions[action];\n\n if (actionHandler) y = actionHandler(y);\n\n return y != null ? y : '';\n });\n}\n\nconst createT9N: FunctionalSetupT9N = (parameters) => {\n let locale: string | undefined;\n let pr: Intl.PluralRules | undefined;\n\n return {\n t(key) {\n return (lang, obj) => {\n /**\n * At first run `locale` and `pr` are not defined.\n * When `locale` changes, `pr` should be updated`\n */\n if (!locale || !pr || lang != locale) {\n pr = new Intl.PluralRules(locale = lang);\n }\n\n // @ts-ignore\n const str: string | string[] = typeof key === 'object' ? key[lang] : parameters[lang]['strings'][key];\n\n if (!str) return '';\n\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return replace(str, obj, parameters[lang]['pluralization'], parameters[lang]['actions'], pr);\n }\n },\n i(key, lang) {\n // @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n return parameters[lang]['internal'][key] as string;\n }\n }\n}\n\nexport { createT9N, replace }\nexport type { SetupT9N, T9N, FunctionalSetupT9N } ","const RU = {\n 'NewGame': 'Новая игра',\n 'HomeScreen': 'Главный экран',\n 'ToTheGame': 'К игре',\n 'Language': 'Язык',\n 'NoSaves': 'Сохранений нет',\n 'LoadSave': 'Загрузить',\n 'Saves': 'Сохранения',\n 'Settings': 'Настройки',\n 'Sumbit': 'Подтвердить',\n 'GoBack': 'Назад',\n 'DoSave': 'Сохранение',\n 'Auto': 'Авто',\n 'Stop': 'Стоп',\n 'Exit': 'Выход',\n 'Automatic': 'Автоматическое',\n 'Manual': 'Ручное',\n 'Remove': 'Удалить',\n 'LoadASaveFrom': 'Загрузить сохранение от',\n 'DeleteASaveFrom': 'Удалить сохранение от',\n 'TextSpeed': 'Скорость Текста',\n 'TextSpeedSlow': 'Медленная',\n 'TextSpeedMedium': 'Средняя',\n 'TextSpeedFast': 'Быстрая',\n 'TextSpeedAuto': 'Автоматическая'\n};\n\ntype BaseTranslationStrings = keyof typeof RU;\n\nconst EN: Record<BaseTranslationStrings, string> = {\n 'NewGame': 'New Game',\n 'HomeScreen': 'Home Screen',\n 'ToTheGame': 'To the Game',\n 'Language': 'Language',\n 'NoSaves': 'No saves',\n 'LoadSave': 'Load',\n 'Saves': 'Saves',\n 'Settings': 'Settings',\n 'Sumbit': 'Submit',\n 'GoBack': 'Go back',\n 'DoSave': 'Save',\n 'Auto': 'Auto',\n 'Stop': 'Stop',\n 'Exit': 'Exit',\n 'Automatic': 'Automatic',\n 'Manual': 'Manual',\n 'Remove': 'Remove',\n 'LoadASaveFrom': 'Load a save from',\n 'DeleteASaveFrom': 'Delete a save from',\n 'TextSpeed': 'Text Speed',\n 'TextSpeedSlow': 'Slow',\n 'TextSpeedMedium': 'Medium',\n 'TextSpeedFast': 'Fast',\n 'TextSpeedAuto': 'Auto'\n};\n\nexport { RU, EN }\nexport type { BaseTranslationStrings }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":"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","names":["isMergeableObject","deepmerge","split","input","delimeters","output","delimeter","start","end","RGX","replace","str","obj","pluralization","actions","pr","x","key","y","pathstr","plural","action","path","actionHandler","data","deepmerge","state","stack","save","characters","action","push","index","next","c","str","prev"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js","../src/index.ts","../src/utils.ts","../src/store.ts","../src/novely.ts","../../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/json/index.mjs","../src/constants.ts","../../t9n/src/lib.ts","../../t9n/src/translation.ts","../../t9n/src/translations.ts","../src/storage.ts"],"sourcesContent":["'use strict';\n\nvar isMergeableObject = function isMergeableObject(value) {\n\treturn isNonNullObject(value)\n\t\t&& !isSpecial(value)\n};\n\nfunction isNonNullObject(value) {\n\treturn !!value && typeof value === 'object'\n}\n\nfunction isSpecial(value) {\n\tvar stringValue = Object.prototype.toString.call(value);\n\n\treturn stringValue === '[object RegExp]'\n\t\t|| stringValue === '[object Date]'\n\t\t|| isReactElement(value)\n}\n\n// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25\nvar canUseSymbol = typeof Symbol === 'function' && Symbol.for;\nvar REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;\n\nfunction isReactElement(value) {\n\treturn value.$$typeof === REACT_ELEMENT_TYPE\n}\n\nfunction emptyTarget(val) {\n\treturn Array.isArray(val) ? [] : {}\n}\n\nfunction cloneUnlessOtherwiseSpecified(value, options) {\n\treturn (options.clone !== false && options.isMergeableObject(value))\n\t\t? deepmerge(emptyTarget(value), value, options)\n\t\t: value\n}\n\nfunction defaultArrayMerge(target, source, options) {\n\treturn target.concat(source).map(function(element) {\n\t\treturn cloneUnlessOtherwiseSpecified(element, options)\n\t})\n}\n\nfunction getMergeFunction(key, options) {\n\tif (!options.customMerge) {\n\t\treturn deepmerge\n\t}\n\tvar customMerge = options.customMerge(key);\n\treturn typeof customMerge === 'function' ? customMerge : deepmerge\n}\n\nfunction getEnumerableOwnPropertySymbols(target) {\n\treturn Object.getOwnPropertySymbols\n\t\t? Object.getOwnPropertySymbols(target).filter(function(symbol) {\n\t\t\treturn Object.propertyIsEnumerable.call(target, symbol)\n\t\t})\n\t\t: []\n}\n\nfunction getKeys(target) {\n\treturn Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))\n}\n\nfunction propertyIsOnObject(object, property) {\n\ttry {\n\t\treturn property in object\n\t} catch(_) {\n\t\treturn false\n\t}\n}\n\n// Protects from prototype poisoning and unexpected merging up the prototype chain.\nfunction propertyIsUnsafe(target, key) {\n\treturn propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet,\n\t\t&& !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain,\n\t\t\t&& Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable.\n}\n\nfunction mergeObject(target, source, options) {\n\tvar destination = {};\n\tif (options.isMergeableObject(target)) {\n\t\tgetKeys(target).forEach(function(key) {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n\t\t});\n\t}\n\tgetKeys(source).forEach(function(key) {\n\t\tif (propertyIsUnsafe(target, key)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) {\n\t\t\tdestination[key] = getMergeFunction(key, options)(target[key], source[key], options);\n\t\t} else {\n\t\t\tdestination[key] = cloneUnlessOtherwiseSpecified(source[key], options);\n\t\t}\n\t});\n\treturn destination\n}\n\nfunction deepmerge(target, source, options) {\n\toptions = options || {};\n\toptions.arrayMerge = options.arrayMerge || defaultArrayMerge;\n\toptions.isMergeableObject = options.isMergeableObject || isMergeableObject;\n\t// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n\t// implementations can use it. The caller may not replace it.\n\toptions.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;\n\n\tvar sourceIsArray = Array.isArray(source);\n\tvar targetIsArray = Array.isArray(target);\n\tvar sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n\tif (!sourceAndTargetTypesMatch) {\n\t\treturn cloneUnlessOtherwiseSpecified(source, options)\n\t} else if (sourceIsArray) {\n\t\treturn options.arrayMerge(target, source, options)\n\t} else {\n\t\treturn mergeObject(target, source, options)\n\t}\n}\n\ndeepmerge.all = function deepmergeAll(array, options) {\n\tif (!Array.isArray(array)) {\n\t\tthrow new Error('first argument should be an array')\n\t}\n\n\treturn array.reduce(function(prev, next) {\n\t\treturn deepmerge(prev, next, options)\n\t}, {})\n};\n\nvar deepmerge_1 = deepmerge;\n\nmodule.exports = deepmerge_1;\n","export type {\n\tValidAction,\n\tStory,\n\tActionProxyProvider,\n\tDefaultActionProxyProvider,\n\tGetActionParameters,\n\tUnwrappable,\n\tCustomHandler,\n\tCustomHandlerGetResult,\n\tCustomHandlerGetResultDataFunction,\n\tFunctionableValue,\n} from './action';\nexport type { Emotions, Character } from './character';\nexport type { CharacterHandle, AudioHandle, RendererStore, Renderer, RendererInit } from './renderer';\nexport type { Storage } from './storage';\nexport type { Thenable, Path, StorageData, StorageMeta, TypewriterSpeed, Lang, NovelyScreen } from './types';\nexport type { Stored } from './store';\nexport type { BaseTranslationStrings } from '@novely/t9n';\n\nexport { novely } from './novely';\nexport { localStorageStorage } from './storage';\n","import type { ActionProxyProvider, CustomHandler } from './action';\nimport type { Character } from './character';\nimport type { TypewriterSpeed, Thenable } from './types';\n\ntype MatchActionMap = {\n\t[Key in keyof ActionProxyProvider<Record<string, Character>>]: (\n\t\tdata: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>,\n\t) => void;\n};\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n\tcustom: (value: [handler: CustomHandler]) => Thenable<void>;\n};\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n\treturn (action: keyof MatchActionMap, props: any) => {\n\t\treturn values[action](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 {} => {\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 = (value: unknown) => {\n\treturn String(value);\n};\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 getTypewriterSpeed = (): TypewriterSpeed => {\n\treturn 'Medium';\n};\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n\tif (languages.includes(language)) {\n\t\treturn language;\n\t} else if (languages.includes((language = language.substring(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) {\n\t\tif (throttled) {\n\t\t\tsavedArgs = arguments;\n\t\t\tsavedThis = this;\n\t\t\treturn;\n\t\t}\n\n\t\tfn.apply(this, arguments 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 vibrate = (pattern: VibratePattern) => {\n\ttry {\n\t\tif ('vibrate' in navigator) {\n\t\t\tnavigator.vibrate(pattern);\n\t\t}\n\t} catch {}\n};\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n\tfor (let i = array.length - 1; i > 0; i--) {\n\t\tif (fn(array[i])) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n};\n\nexport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetTypewriterSpeed,\n\tgetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n};\n","type Stored<T> = {\n\tsubscribe: (cb: (value: T) => void) => () => void;\n\tupdate: (fn: (prev: T) => T) => void;\n\tget: () => T;\n};\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n\tconst subscribe = (cb: (value: T) => void) => {\n\t\tsubscribers.add(cb), cb(current);\n\n\t\treturn () => {\n\t\t\tsubscribers.delete(cb);\n\t\t};\n\t};\n\n\tconst push = (value: T) => {\n\t\tsubscribers.forEach((cb) => cb(value));\n\t};\n\n\tconst update = (fn: (prev: T) => T) => {\n\t\tpush((current = fn(current)));\n\t};\n\n\tconst get = () => {\n\t\treturn current;\n\t};\n\n\treturn { subscribe, update, get } as const;\n};\n\nexport { store };\nexport type { Stored };\n","import type { Character } from './character';\nimport type {\n\tActionProxyProvider,\n\tGetActionParameters,\n\tStory,\n\tValidAction,\n\tUnwrappable,\n\tCustomHandler,\n} from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types';\nimport type { Renderer, RendererInit } from './renderer';\nimport type { SetupT9N } from '@novely/t9n';\nimport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tstr,\n\tisUserRequiredAction,\n\tgetTypewriterSpeed,\n\tgetLanguage as defaultGetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n} from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge';\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n> {\n\t/**\n\t * An array of languages supported by the game.\n\t */\n\tlanguages: Languages[];\n\t/**\n\t * An object containing the characters in the game.\n\t */\n\tcharacters: Characters;\n\t/**\n\t * An object that provides access to the game's storage system.\n\t */\n\tstorage: Storage;\n\t/**\n\t * Delay loading data until Promise is resolved\n\t */\n\tstorageDelay?: Promise<void>;\n\t/**\n\t * A function that returns a Renderer object used to display the game's content\n\t */\n\trenderer: (characters: RendererInit) => Renderer;\n\t/**\n\t * An optional property that specifies the initial screen to display when the game starts\n\t */\n\tinitialScreen?: NovelyScreen;\n\t/**\n\t * An object containing the translation functions used in the game\n\t */\n\tt9n: Inter;\n\t/**\n\t * Initial state value\n\t */\n\tstate?: StateScheme;\n\t/**\n\t * Initial data value\n\t */\n\tdata?: DataScheme;\n\t/**\n\t * Enable autosaves or disable\n\t * @default true\n\t */\n\tautosaves?: boolean;\n\t/**\n\t * Migration from old saves to newer\n\t */\n\tmigrations?: Migration[];\n\t/**\n\t * For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage\n\t * @default 799\n\t */\n\tthrottleTimeout?: number;\n\t/**\n\t * Custom language detector\n\t * @param languages Supported languages aka `languages: []` in the config\n\t * @example ```ts\n\t * novely({\n\t * \t\tgetLanguage(languages) {\n\t * \t\t\t\treturn sdk.environment.i18n.lang // i.e. custom language from some sdk\n\t * \t\t}\n\t * })\n\t * ```\n\t */\n\tgetLanguage?: (languages: string[]) => string;\n}\n\nconst novely = <\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n>({\n\tcharacters,\n\tstorage,\n\tstorageDelay = Promise.resolve(),\n\trenderer: createRenderer,\n\tinitialScreen = 'mainmenu',\n\tt9n,\n\tlanguages,\n\tstate: defaultState,\n\tdata: defaultData,\n\tautosaves = true,\n\tmigrations = [],\n\tthrottleTimeout = 799,\n\tgetLanguage = defaultGetLanguage\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n\tlet story: Story;\n\tlet times = new Set<number>();\n\n\t/**\n\t * Prevent `undefined`\n\t */\n\tdefaultData ||= {} as DataScheme;\n\tdefaultState ||= {} as StateScheme;\n\n\t/**\n\t * Saves timestamps created in this session\n\t */\n\tconst intime = (value: number) => {\n\t\treturn times.add(value), value;\n\t};\n\n\tconst withStory = (s: Story) => {\n\t\t/**\n\t\t * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n\t\t */\n\t\tstory = Object.fromEntries(\n\t\t\tObject.entries(s).map(([name, items]) => {\n\t\t\t\tconst flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n\t\t\t\t\treturn item.flatMap((data) => {\n\t\t\t\t\t\tconst type = data[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This is not just an action like `['name', ...arguments]`, but an array of actions\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (Array.isArray(type)) return flat(data as ValidAction[]);\n\n\t\t\t\t\t\treturn [data as ValidAction];\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\treturn [name, flat(items)];\n\t\t\t}),\n\t\t);\n\n\t\t/**\n\t\t * When `initialScreen` is not a game, we can safely show it\n\t\t */\n\t\tif (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n\t};\n\n\tconst action = new Proxy({} as ActionProxyProvider<Characters>, {\n\t\tget(_, prop) {\n\t\t\treturn (\n\t\t\t\t...props: Parameters<\n\t\t\t\t\tActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]\n\t\t\t\t>\n\t\t\t) => {\n\t\t\t\treturn [prop, ...props];\n\t\t\t};\n\t\t},\n\t});\n\n\tfunction state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n\tfunction state(): StateScheme;\n\tfunction state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n\t\tif (!value) return stack.value[1] as StateScheme | void;\n\n\t\tconst prev = stack.value[1];\n\t\tconst val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n\t\tstack.value[1] = val as StateScheme;\n\t}\n\n\tconst getDefaultSave = (state = {}) => {\n\t\treturn [\n\t\t\t[\n\t\t\t\t[null, 'start'],\n\t\t\t\t[null, 0],\n\t\t\t],\n\t\t\tstate,\n\t\t\t[intime(Date.now()), 'auto'],\n\t\t] as Save;\n\t};\n\n\tconst createStack = (current: Save, stack = [current]) => {\n\t\treturn {\n\t\t\tget value() {\n\t\t\t\treturn stack.at(-1)!;\n\t\t\t},\n\t\t\tset value(value: Save) {\n\t\t\t\tstack[stack.length - 1] = value;\n\t\t\t},\n\t\t\tback() {\n\t\t\t\tif (stack.length > 1) stack.pop(), (goingBack = true);\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 = [getDefaultSave(klona(defaultState))];\n\t\t\t},\n\t\t};\n\t};\n\n\t/**\n\t * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n\t * 2) Actual stored data is loaded, language and etc is changed\n\t */\n\tconst initialData: StorageData = {\n\t\tsaves: [],\n\t\tdata: klona(defaultData) as Data,\n\t\tmeta: [getLanguage(languages), getTypewriterSpeed()],\n\t};\n\n\tconst $ = store(initialData);\n\n\tlet initialDataLoaded = false;\n\n\tconst onStorageDataChange = (value: StorageData) => {\n\t\tif (initialDataLoaded) storage.set(value);\n\t};\n\n\tconst throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);\n\n\t$.subscribe(throttledOnStorageDataChange);\n\n\tconst getStoredData = () => {\n\t\tstorage.get().then((stored) => {\n\t\t\t/**\n\t\t\t * Migration is done only once (when game loads it's data), and then it saves the updated format\n\t\t\t */\n\t\t\tfor (const migration of migrations) {\n\t\t\t\t// @ts-expect-error Types does not match between versions\n\t\t\t\tstored = migration(stored);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n\t\t\t */\n\t\t\tstored.meta[0] ||= getLanguage(languages);\n\t\t\tstored.meta[1] ||= getTypewriterSpeed();\n\n\t\t\t/**\n\t\t\t * When data is empty replace it with `defaultData`\n\t\t\t * It also might be empty (default to empty)\n\t\t\t */\n\t\t\tif (isEmpty(stored.data)) {\n\t\t\t\tstored.data = defaultData as Data;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Now the next store updates will entail saving via storage.set\n\t\t\t */\n\t\t\tinitialDataLoaded = true;\n\n\t\t\t$.update(() => stored);\n\n\t\t\t/**\n\t\t\t * When initialScreen is game, then we will load it, but after the data is loaded\n\t\t\t */\n\t\t\tif (initialScreen === 'game') restore();\n\t\t});\n\t};\n\n\t/**\n\t * By default this is resolved immediately, but also can be delayed.\n\t * I.e. storage has not loaded yet\n\t */\n\tstorageDelay.then(getStoredData);\n\n\tconst initial = getDefaultSave(klona(defaultState));\n\tconst stack = createStack(initial);\n\n\tconst save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n\t\tif (!initialDataLoaded) return;\n\n\t\t/**\n\t\t * When autosaves diabled just return\n\t\t */\n\t\tif (!autosaves && type === 'auto') return;\n\n\t\tconst current = klona(stack.value);\n\n\t\t$.update((prev) => {\n\t\t\t/**\n\t\t\t * Find latest save that were created in current session, and check if it is latest in an array\n\t\t\t *\n\t\t\t * We check if save was created in current session and it is latest in array\n\t\t\t * When it is not then replacing it will break logical chain\n\t\t\t *\n\t\t\t * [auto save 1]\n\t\t\t * [manual save 1]\n\t\t\t * [auto save 2] <- should not replace first auto save\n\t\t\t */\n\t\t\tconst isLatest = findLastIndex(prev.saves, (value) => times.has(value[2][0])) === prev.saves.length - 1;\n\n\t\t\t/**\n\t\t\t * Update type and time information\n\t\t\t */\n\t\t\tcurrent[2][0] = intime(Date.now());\n\t\t\tcurrent[2][1] = type;\n\n\t\t\tif (!override || !isLatest) {\n\t\t\t\tprev.saves.push(current);\n\n\t\t\t\treturn prev;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Get latest\n\t\t\t */\n\t\t\tconst latest = prev.saves.at(-1);\n\n\t\t\t/**\n\t\t\t * When that save is the same type, replace it\n\t\t\t */\n\t\t\tif (latest && latest[2][1] === type) {\n\t\t\t\tprev.saves[prev.saves.length - 1] = current;\n\t\t\t} else {\n\t\t\t\tprev.saves.push(current);\n\t\t\t}\n\n\t\t\treturn prev;\n\t\t});\n\t};\n\n\tconst newGame = () => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tconst save = getDefaultSave(klona(defaultState));\n\n\t\t/**\n\t\t * Initial save is automatic, and should be ignored when autosaves is turned off\n\t\t */\n\t\tif (autosaves) {\n\t\t\t$.update((prev) => {\n\t\t\t\treturn prev.saves.push(save), prev;\n\t\t\t});\n\t\t}\n\n\t\trestore(save);\n\t};\n\n\t/**\n\t * Set's the save\n\t */\n\tconst set = (save: Save) => {\n\t\tstack.value = save;\n\n\t\treturn restore(save);\n\t};\n\n\tlet restoring = false;\n\tlet goingBack = false;\n\tlet interacted = false;\n\n\t/**\n\t * Restore\n\t */\n\tconst restore = async (save?: Save) => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tlet latest = save ? save : $.get().saves.at(-1);\n\n\t\t/**\n\t\t * When there is no game, then make a new game\n\t\t */\n\t\tif (!latest) {\n\t\t\t$.update(() => ({\n\t\t\t\tsaves: [initial],\n\t\t\t\tdata: klona(defaultData) as Data,\n\t\t\t\tmeta: [getLanguage(languages), getTypewriterSpeed()],\n\t\t\t}));\n\n\t\t\tlatest = klona(initial);\n\t\t}\n\n\t\t(restoring = true), (stack.value = latest);\n\n\t\t/**\n\t\t * Текущий элемент в истории\n\t\t */\n\t\tlet current: any = story;\n\t\t/**\n\t\t * Текущий элемент `[null, int]`\n\t\t */\n\t\tlet index = 0;\n\n\t\t/**\n\t\t * Число элементов `[null, int]`\n\t\t */\n\t\tconst max = stack.value[0].reduce((acc, [type, val]) => {\n\t\t\tif (isNull(type) && isNumber(val)) return acc + 1;\n\n\t\t\treturn acc;\n\t\t}, 0);\n\n\t\tconst queue = [] as [any, any][];\n\t\tconst keep = new Set();\n\t\tconst characters = new Set();\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tif (isString(val)) {\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t} else if (isNumber(val)) {\n\t\t\t\t\tindex++;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n\t\t\t\t\t * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n\t\t\t\t\t */\n\t\t\t\t\tfor (let i = 0; i <= val; i++) {\n\t\t\t\t\t\tconst [action, ...meta] = current[i];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Add item to queue and action to keep\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst push = () => {\n\t\t\t\t\t\t\tkeep.add(action);\n\t\t\t\t\t\t\tqueue.push([action, meta]);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Do not remove characters that will be here anyways\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (action === 'showCharacter') characters.add(meta[0]);\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n\t\t\t\t\t\t * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n\t\t\t\t\t\t\tif (index === max && i === val) {\n\t\t\t\t\t\t\t\tpush();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpush();\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t}\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\tqueue.forEach((value, index) => {\n\t\t\t/**\n\t\t\t * Mutate the queue item\n\t\t\t */\n\t\t\tvalue.push(index);\n\t\t});\n\n\t\t/**\n\t\t * This is basically made for TypeScript.\n\t\t */\n\t\tconst indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n\t\t/**\n\t\t * Run these exactly before the main loop.\n\t\t */\n\t\trenderer.ui.showScreen('game');\n\t\t/**\n\t\t * Provide the `keep` in there\n\t\t */\n\t\tmatch('clear', [keep, characters]);\n\n\t\t/**\n\t\t * Get the next actions array.\n\t\t */\n\t\tconst next = (i: number) => indexedQueue.slice(i + 1);\n\n\t\tfor await (const [action, meta, i] of indexedQueue) {\n\t\t\tif (action === 'function' || action === 'custom') {\n\t\t\t\t/**\n\t\t\t\t * When `callOnlyLatest` is `true`\n\t\t\t\t */\n\t\t\t\tif (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We'll calculate it is `latest` or not\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t\tconst c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\t\t\t\t\t\tconst c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Also check for `undefined`\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Equal by id or equal by `toString()`\n\t\t\t\t\t\t */\n\t\t\t\t\t\treturn isIdenticalID || str(c0) === str(c1);\n\t\t\t\t\t});\n\n\t\t\t\t\tif (notLatest) continue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Action can return Promise.\n\t\t\t\t */\n\t\t\t\tconst result = match(action, meta);\n\n\t\t\t\t/**\n\t\t\t\t * Should wait until it resolved\n\t\t\t\t */\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Await it!\n\t\t\t\t\t */\n\t\t\t\t\tawait result;\n\t\t\t\t}\n\t\t\t} else if (action === 'showCharacter') {\n\t\t\t\tconst skip = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Проверка на возможный `undefined`\n\t\t\t\t\t */\n\t\t\t\t\tif (!_meta || !meta) return false;\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\tconst hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\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\tconst notLatest = _action === action && _meta[0] === meta[0];\n\n\t\t\t\t\treturn hidden || notLatest;\n\t\t\t\t});\n\n\t\t\t\tif (skip) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else if (action === 'showBackground' || action === 'animateCharacter') {\n\t\t\t\t/**\n\t\t\t\t * Такая же оптимизация применяется к фонам и анимированию персонажей.\n\t\t\t\t * Если фон изменится, то нет смысла устанавливать текущий\n\t\t\t\t */\n\t\t\t\tconst notLatest = next(i).some(([_action]) => action === _action);\n\n\t\t\t\tif (notLatest) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else {\n\t\t\t\tmatch(action, meta);\n\t\t\t}\n\t\t}\n\n\t\t(restoring = goingBack = false), render();\n\t};\n\n\tconst refer = () => {\n\t\tlet current: any = story;\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tcurrent = current[val];\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\treturn current;\n\t};\n\n\tconst exit = () => {\n\t\tconst current = stack.value;\n\n\t\tstack.clear();\n\t\trenderer.ui.showScreen('mainmenu');\n\n\t\t/**\n\t\t * First two save elements and it's type\n\t\t */\n\t\tconst [[first, second], , [time, type]] = current;\n\n\t\tif (type === 'auto' && first && second) {\n\t\t\t/**\n\t\t\t * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n\t\t\t */\n\t\t\tif (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n\t\t\t\t$.update((prev) => {\n\t\t\t\t\tprev.saves = prev.saves.filter((save) => save !== current);\n\n\t\t\t\t\treturn prev;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Reset interactive value\n\t\t */\n\t\tinteractivity(false);\n\t\t/**\n\t\t * Reset session times\n\t\t */\n\t\ttimes.clear();\n\t};\n\n\tconst back = () => {\n\t\treturn stack.back(), restore(stack.value);\n\t};\n\n\tconst renderer = createRenderer({\n\t\tcharacters,\n\t\tset,\n\t\trestore,\n\t\tsave,\n\t\tnewGame,\n\t\texit,\n\t\tback,\n\t\tstack,\n\t\tlanguages,\n\t\tt: t9n.i,\n\t\t$,\n\t});\n\n\tconst match = matchAction({\n\t\twait([time]) {\n\t\t\tif (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n\t\t},\n\t\tshowBackground([background]) {\n\t\t\trenderer.background(background);\n\t\t\tpush();\n\t\t},\n\t\tplayMusic([source]) {\n\t\t\trenderer.music(source, 'music').play();\n\t\t\tpush();\n\t\t},\n\t\tstopMusic([source]) {\n\t\t\trenderer.music(source, 'music').stop();\n\t\t\tpush();\n\t\t},\n\t\tshowCharacter([character, emotion, className, style]) {\n\t\t\tconst handle = renderer.character(character);\n\n\t\t\thandle.append(className, style, restoring);\n\t\t\thandle.withEmotion(emotion)();\n\n\t\t\tpush();\n\t\t},\n\t\thideCharacter([character, className, style, duration]) {\n\t\t\trenderer.character(character).remove(className, style, duration)(push, restoring);\n\t\t},\n\t\tdialog([character, content, emotion]) {\n\t\t\t/**\n\t\t\t * Person name\n\t\t\t */\n\t\t\tconst name = (() => {\n\t\t\t\tconst c = character,\n\t\t\t\t\tcs = characters;\n\t\t\t\tconst lang = $.get().meta[0];\n\n\t\t\t\treturn c\n\t\t\t\t\t? c in cs\n\t\t\t\t\t\t? typeof cs[c].name === 'string'\n\t\t\t\t\t\t\t? (cs[c].name as string)\n\t\t\t\t\t\t\t: (cs[c].name as Record<string, string>)[lang]\n\t\t\t\t\t\t: c\n\t\t\t\t\t: '';\n\t\t\t})();\n\n\t\t\trenderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n\t\t},\n\t\tfunction([fn]) {\n\t\t\tconst result = fn(restoring, goingBack);\n\n\t\t\tif (!restoring) result ? result.then(push) : push();\n\n\t\t\treturn result;\n\t\t},\n\t\tchoice([question, ...choices]) {\n\t\t\tconst isWithoutQuestion = Array.isArray(question);\n\n\t\t\tif (isWithoutQuestion) {\n\t\t\t\t/**\n\t\t\t\t * Первый элемент может быть как строкой, так и элементов выбора\n\t\t\t\t */\n\t\t\t\tchoices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n\t\t\t\t/**\n\t\t\t\t * Значит, текст не требуется\n\t\t\t\t */\n\t\t\t\tquestion = '';\n\t\t\t}\n\n\t\t\tconst unwrapped = choices.map(([content, action, visible]) => {\n\t\t\t\treturn [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n\t\t\t});\n\n\t\t\trenderer.choices(\n\t\t\t\tunwrap(question),\n\t\t\t\tunwrapped,\n\t\t\t)((selected) => {\n\t\t\t\tenmemory();\n\n\t\t\t\t/**\n\t\t\t\t * If there is a question, then `index` should be shifted by `1`\n\t\t\t\t */\n\t\t\t\tconst offset = isWithoutQuestion ? 0 : 1;\n\n\t\t\t\tstack.value[0].push(['choice', selected + offset], [null, 0]);\n\t\t\t\trender();\n\t\t\t\tinteractivity(true);\n\t\t\t});\n\t\t},\n\t\tjump([scene]) {\n\t\t\t/**\n\t\t\t * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n\t\t\t */\n\t\t\tstack.value[0] = [\n\t\t\t\t[null, scene],\n\t\t\t\t[null, -1],\n\t\t\t];\n\n\t\t\tmatch('clear', []);\n\t\t},\n\t\tclear([keep, characters]) {\n\t\t\t/**\n\t\t\t * Remove vibration\n\t\t\t */\n\t\t\tvibrate(0);\n\t\t\t/**\n\t\t\t * Call the actual `clear`\n\t\t\t */\n\t\t\trenderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n\t\t},\n\t\tcondition([condition]) {\n\t\t\tconst value = condition();\n\n\t\t\tif (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n\t\t},\n\t\tend() {\n\t\t\t/**\n\t\t\t * Clear the Scene\n\t\t\t */\n\t\t\tmatch('clear', []);\n\t\t\t/**\n\t\t\t * Go to the main menu\n\t\t\t */\n\t\t\trenderer.ui.showScreen('mainmenu');\n\t\t\t/**\n\t\t\t * Reset interactive value\n\t\t\t */\n\t\t\tinteractivity(false);\n\t\t\t/**\n\t\t\t * Reset session times\n\t\t\t */\n\t\t\ttimes.clear();\n\t\t},\n\t\tinput([question, onInput, setup]) {\n\t\t\trenderer.input(unwrap(question), onInput, setup)(forward);\n\t\t},\n\t\tcustom([handler]) {\n\t\t\tconst result = renderer.custom(handler, goingBack, () => {\n\t\t\t\tif (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n\t\t\t\tif (!restoring) push();\n\t\t\t});\n\n\t\t\treturn result;\n\t\t},\n\t\tvibrate(pattern) {\n\t\t\tvibrate(pattern);\n\t\t\tpush();\n\t\t},\n\t\tnext() {\n\t\t\tpush();\n\t\t},\n\t\tanimateCharacter([character, timeout, ...classes]) {\n\t\t\tconst handler: CustomHandler = (get) => {\n\t\t\t\tconst { clear } = get('@@internal-animate-character', false);\n\t\t\t\tconst char = renderer.store.characters[character];\n\n\t\t\t\t/**\n\t\t\t\t * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n\t\t\t\t */\n\t\t\t\tif (!char) return;\n\n\t\t\t\tconst target = char.canvas;\n\n\t\t\t\t/**\n\t\t\t\t * Character is not found\n\t\t\t\t */\n\t\t\t\tif (!target) return;\n\n\t\t\t\tconst classNames = classes.filter((className) => !target.classList.contains(className));\n\n\t\t\t\ttarget.classList.add(...classNames);\n\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\t\t\t\t}, timeout);\n\n\t\t\t\tclear(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Clear timeout, because when you will game re-runs some callback might remove classes from character\n\t\t\t\t\t */\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n\t\t\t */\n\t\t\tmatch('custom', [handler]);\n\t\t},\n\t\ttext(text) {\n\t\t\trenderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n\t\t},\n\t\texit() {\n\t\t\tconst path = stack.value[0];\n\n\t\t\tfor (let i = path.length - 1; i > 0; i--) {\n\t\t\t\tif (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n\t\t\t\tstack.value[0] = path.slice(0, i);\n\t\t\t\tnext();\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\trender();\n\t\t},\n\t});\n\n\tconst enmemory = () => {\n\t\tif (restoring) return;\n\n\t\tconst current = klona(stack.value);\n\n\t\tcurrent[2][1] = 'auto';\n\n\t\tstack.push(current);\n\n\t\tsave(true, 'auto');\n\t};\n\n\tconst next = () => {\n\t\tconst path = stack.value[0];\n\t\t/**\n\t\t * Последний элемент пути\n\t\t */\n\t\tconst last = path[path.length - 1]!;\n\n\t\t/**\n\t\t * Если он вида `[null, int]` - увеличивает `int`\n\t\t */\n\t\tif (isNull(last[0]) && isNumber(last[1])) {\n\t\t\tlast[1] = last[1] + 1;\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Иначе добавляет новое `[null int]`\n\t\t */\n\t\tpath.push([null, 0]);\n\t};\n\n\tconst render = () => {\n\t\tconst referred = refer();\n\n\t\tif (!Array.isArray(referred)) return;\n\n\t\tconst [action, ...props] = referred;\n\n\t\tmatch(action, props);\n\t};\n\n\tconst push = () => {\n\t\tif (!restoring) next(), render();\n\t};\n\n\tconst forward = () => {\n\t\tenmemory();\n\t\tpush();\n\t\tinteractivity(true);\n\t};\n\n\tconst interactivity = (value = false) => {\n\t\tinteracted = value;\n\t};\n\n\t/**\n\t * Unwraps translatable content to string\n\t *\n\t * @example ```\n\t * unwrap(t('Hello'));\n\t * unwrap({ en: 'Hello', ru: 'Привет' });\n\t * unwrap({ en: () => data().ad_viewed ? 'Diamond Hat' : 'Diamond Hat (Watch Adv)' })\n\t * unwrap('Hello, {{name}}');\n\t * ```\n\t */\n\tconst unwrap = (content: Unwrappable, global = false) => {\n\t\tconst {\n\t\t\tdata,\n\t\t\tmeta: [lang],\n\t\t} = $.get();\n\n\t\tconst obj = global ? data : state();\n\t\tconst cnt = isFunction(content) ? content(lang, obj) : typeof content === 'string' ? content : content[lang];\n\n\t\tconst str = isFunction(cnt) ? cnt() : cnt;\n\n\t\treturn replaceT9N(str, obj);\n\t};\n\n\tfunction data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n\tfunction data(): DataScheme;\n\tfunction data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n\t\tif (!value) return $.get().data as DataScheme | void;\n\n\t\tconst prev = $.get().data;\n\t\tconst val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n\t\t$.update((prev) => {\n\t\t\tprev.data = val;\n\n\t\t\treturn prev;\n\t\t});\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Function to set story\n\t\t */\n\t\twithStory,\n\t\t/**\n\t\t * Function to get actions\n\t\t */\n\t\taction,\n\t\t/**\n\t\t * State that belongs to games\n\t\t */\n\t\tstate,\n\t\t/**\n\t\t * Unlike `state`, stored at global scope instead and shared between games\n\t\t */\n\t\tdata,\n\t\t/**\n\t\t * Unwraps translatable content to a string value\n\t\t */\n\t\tunwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n\t\t\treturn unwrap(content, true);\n\t\t},\n\t\t/**\n\t\t * Function that is used for translation\n\t\t */\n\t\tt: t9n.t as Inter['t'],\n\t};\n};\n\nexport { novely };\n","export function klona(val) {\n\tvar k, out, tmp;\n\n\tif (Array.isArray(val)) {\n\t\tout = Array(k=val.length);\n\t\twhile (k--) out[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\treturn out;\n\t}\n\n\tif (Object.prototype.toString.call(val) === '[object Object]') {\n\t\tout = {}; // null\n\t\tfor (k in val) {\n\t\t\tif (k === '__proto__') {\n\t\t\t\tObject.defineProperty(out, k, {\n\t\t\t\t\tvalue: klona(val[k]),\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tout[k] = (tmp=val[k]) && typeof tmp === 'object' ? klona(tmp) : tmp;\n\t\t\t}\n\t\t}\n\t\treturn out;\n\t}\n\n\treturn val;\n}\n","const SKIPPED_DURING_RESTORE = new Set(['dialog', 'choice', 'input', 'vibrate', 'text'] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET };\n","const split = (input: string, delimeters: string[]) => {\n\tconst output: (string | undefined)[] = [];\n\n\tfor (const delimeter of delimeters) {\n\t\tif (!input) break;\n\n\t\tconst [start, end] = input.split(delimeter, 2);\n\n\t\toutput.push(start);\n\t\tinput = end;\n\t}\n\n\toutput.push(input);\n\n\treturn output;\n};\n\nexport { split };\n","import type { BaseTranslationStrings } from './translations';\nimport { split } from './lib';\n\ntype PluralType = Intl.LDMLPluralRule;\ntype FunctionalSetupT9N = <\n\tLanguageKey extends string,\n\tPluralKey extends string,\n\tStringKey extends string,\n\tActions extends string,\n>(parameters: {\n\t[Lang in LanguageKey]: {\n\t\tpluralization: {\n\t\t\t[Plural in PluralKey]: Partial<Record<PluralType, string>>;\n\t\t};\n\t\tinternal: { [Key in BaseTranslationStrings]: string };\n\t\tstrings: { [Str in StringKey]: string };\n\t\tactions?: { [Action in Actions]?: (value: string) => string };\n\t};\n}) => T9N<LanguageKey, StringKey>;\ntype SetupT9N<LanguageKey extends string> = <\n\tPluralKey extends string,\n\tStringKey extends string,\n\tActions extends string,\n>(parameters: {\n\t[Lang in LanguageKey]: {\n\t\tpluralization: {\n\t\t\t[Plural in PluralKey]: Partial<Record<PluralType, string>>;\n\t\t};\n\t\tinternal: { [Key in BaseTranslationStrings]: string };\n\t\tstrings: { [Str in StringKey]: string };\n\t\tactions?: { [Action in Actions]?: (value: string) => string };\n\t};\n}) => T9N<LanguageKey, StringKey>;\n\ntype T9N<LanguageKey extends string, StringKey extends string> = {\n\tt(\n\t\tkey: StringKey | Record<LanguageKey, AllowedContent>,\n\t): (lang: LanguageKey | (string & {}), obj: Record<string, unknown>) => string;\n\ti(key: StringKey, lang: LanguageKey | (string & {})): string;\n};\n\nconst RGX = /{{(.*?)}}/g;\n\ntype AllowedContent = string | (() => string | string[]) | string[] | (string | (() => string | string[]))[];\n\n/**\n * Unwraps any allowed content into string\n * @param c Content\n */\nconst unwrap = (c: AllowedContent): string => {\n\tif (Array.isArray(c)) {\n\t\treturn c.map((item) => unwrap(item)).join('<br>');\n\t}\n\n\tif (typeof c === 'function') {\n\t\treturn unwrap(c());\n\t}\n\n\treturn c;\n};\n\nconst replace = (\n\tstr: AllowedContent,\n\tobj: Record<string, unknown>,\n\tpluralization?: Record<string, Record<string, PluralType>>,\n\tactions?: Partial<Record<string, (str: string) => string>>,\n\tpr?: Intl.PluralRules,\n) => {\n\treturn unwrap(str).replace(RGX, (x: any, key: string, y: any) => {\n\t\tx = 0;\n\t\ty = obj;\n\n\t\tconst [pathstr, plural, action] = split(key.trim(), ['@', '%']);\n\n\t\tlet path = pathstr!.split('.');\n\n\t\twhile (y && x < path.length) y = y[path[x++]];\n\n\t\tif (plural && pluralization && y && pr) {\n\t\t\ty = pluralization[plural][pr.select(y)];\n\t\t}\n\n\t\tconst actionHandler = actions && action && actions[action];\n\n\t\tif (actionHandler) y = actionHandler(y);\n\n\t\treturn y != null ? y : '';\n\t});\n};\n\nconst createT9N: FunctionalSetupT9N = (parameters) => {\n\tlet locale: string | undefined;\n\tlet pr: Intl.PluralRules | undefined;\n\n\treturn {\n\t\tt(key) {\n\t\t\treturn (lang, obj) => {\n\t\t\t\t/**\n\t\t\t\t * At first run `locale` and `pr` are not defined.\n\t\t\t\t * When `locale` changes, `pr` should be updated`\n\t\t\t\t */\n\t\t\t\tif (!locale || !pr || lang != locale) {\n\t\t\t\t\tpr = new Intl.PluralRules((locale = lang));\n\t\t\t\t}\n\n\t\t\t\t// @ts-ignore\n\t\t\t\tconst str: string | string[] = typeof key === 'object' ? key[lang] : parameters[lang]['strings'][key];\n\n\t\t\t\tif (!str) return '';\n\n\t\t\t\t// @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n\t\t\t\treturn replace(str, obj, parameters[lang]['pluralization'], parameters[lang]['actions'], pr);\n\t\t\t};\n\t\t},\n\t\ti(key, lang) {\n\t\t\t// @ts-ignore `(string & {})` cannot be used to index type `LanguageKey`.\n\t\t\treturn parameters[lang]['internal'][key] as string;\n\t\t},\n\t};\n};\n\nexport { createT9N, replace };\nexport type { SetupT9N, T9N, AllowedContent, FunctionalSetupT9N };\n","const RU = {\n\tNewGame: 'Новая игра',\n\tHomeScreen: 'Главный экран',\n\tToTheGame: 'К игре',\n\tLanguage: 'Язык',\n\tNoSaves: 'Сохранений нет',\n\tLoadSave: 'Загрузить',\n\tSaves: 'Сохранения',\n\tSettings: 'Настройки',\n\tSumbit: 'Подтвердить',\n\tGoBack: 'Назад',\n\tDoSave: 'Сохранение',\n\tAuto: 'Авто',\n\tStop: 'Стоп',\n\tExit: 'Выход',\n\tAutomatic: 'Автоматическое',\n\tManual: 'Ручное',\n\tRemove: 'Удалить',\n\tLoadASaveFrom: 'Загрузить сохранение от',\n\tDeleteASaveFrom: 'Удалить сохранение от',\n\tTextSpeed: 'Скорость Текста',\n\tTextSpeedSlow: 'Медленная',\n\tTextSpeedMedium: 'Средняя',\n\tTextSpeedFast: 'Быстрая',\n\tTextSpeedAuto: 'Автоматическая',\n\tCompleteText: 'Завершить текст',\n\tGoForward: 'Перейти вперёд',\n};\n\ntype BaseTranslationStrings = keyof typeof RU;\n\nconst EN: Record<BaseTranslationStrings, string> = {\n\tNewGame: 'New Game',\n\tHomeScreen: 'Home Screen',\n\tToTheGame: 'To the Game',\n\tLanguage: 'Language',\n\tNoSaves: 'No saves',\n\tLoadSave: 'Load',\n\tSaves: 'Saves',\n\tSettings: 'Settings',\n\tSumbit: 'Submit',\n\tGoBack: 'Go back',\n\tDoSave: 'Save',\n\tAuto: 'Auto',\n\tStop: 'Stop',\n\tExit: 'Exit',\n\tAutomatic: 'Automatic',\n\tManual: 'Manual',\n\tRemove: 'Remove',\n\tLoadASaveFrom: 'Load a save from',\n\tDeleteASaveFrom: 'Delete a save from',\n\tTextSpeed: 'Text Speed',\n\tTextSpeedSlow: 'Slow',\n\tTextSpeedMedium: 'Medium',\n\tTextSpeedFast: 'Fast',\n\tTextSpeedAuto: 'Auto',\n\tCompleteText: 'Complete text',\n\tGoForward: 'Go forward',\n};\n\n/**\n * Translated automatically\n */\nconst KK: Record<BaseTranslationStrings, string> = {\n\tNewGame: 'Жаңа ойын',\n\tHomeScreen: 'Негізгі экран',\n\tToTheGame: 'Ойынға',\n\tLanguage: 'Тіл',\n\tNoSaves: 'Сақтау жоқ',\n\tLoadSave: 'Жүктеу',\n\tSaves: 'Сақтау',\n\tSettings: 'Параметрлер',\n\tSumbit: 'Растау',\n\tGoBack: 'Артқа',\n\tDoSave: 'Сақтау',\n\tAuto: 'Авто',\n\tStop: 'Тоқта',\n\tExit: 'Шығу',\n\tAutomatic: 'Автоматты',\n\tManual: 'Қолмен',\n\tRemove: 'Жою',\n\tLoadASaveFrom: 'Сақтауды жүктеу',\n\tDeleteASaveFrom: 'Сақтауды жою',\n\tTextSpeed: 'Мәтін Жылдамдығы',\n\tTextSpeedSlow: 'Баяу',\n\tTextSpeedMedium: 'Орташа',\n\tTextSpeedFast: 'Жылдам',\n\tTextSpeedAuto: 'Автоматты',\n\tCompleteText: 'Мәтінді аяқтау',\n\tGoForward: 'Алға жылжу',\n};\n\n/**\n * Translated automatically\n */\nconst JP: Record<BaseTranslationStrings, string> = {\n\tNewGame: '「新しいゲーム」',\n\tHomeScreen: 'ホーム画面',\n\tToTheGame: '「ゲームに戻る」',\n\tLanguage: '言語',\n\tNoSaves: 'ノーセーブ',\n\tLoadSave: 'ダウンロード',\n\tSaves: '保存',\n\tSettings: '設定',\n\tSumbit: '確認',\n\tGoBack: '「戻る」',\n\tDoSave: '保存',\n\tAuto: 'オート',\n\tStop: '止まれ',\n\tExit: '出口',\n\tAutomatic: '自動',\n\tManual: 'マニュアル',\n\tRemove: '削除',\n\tLoadASaveFrom: 'ロードセーブから',\n\tDeleteASaveFrom: 'から保存を削除',\n\tTextSpeed: 'テキストスピード',\n\tTextSpeedSlow: '「遅い」',\n\tTextSpeedMedium: 'ミディアム',\n\tTextSpeedFast: '「速い」',\n\tTextSpeedAuto: '自動',\n\tCompleteText: 'テキストを完成させる',\n\tGoForward: '先に行く',\n};\n\nexport { RU, EN, KK, JP };\nexport type { BaseTranslationStrings };\n","import type { StorageData } from './types';\n\ninterface LocalStorageStorageSettings {\n\tkey: string;\n}\n\ninterface Storage {\n\tget: () => Promise<StorageData>;\n\tset: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n\treturn {\n\t\tasync get() {\n\t\t\tconst value = localStorage.getItem(options.key);\n\n\t\t\treturn value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n\t\t},\n\t\tasync set(data) {\n\t\t\tlocalStorage.setItem(options.key, JSON.stringify(data));\n\t\t},\n\t};\n};\n\nexport type { Storage };\nexport { localStorageStorage };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAEA,UAAI,oBAAoB,SAASA,mBAAkB,OAAO;AACzD,eAAO,gBAAgB,KAAK,KACxB,CAAC,UAAU,KAAK;AAAA,MACrB;AAEA,eAAS,gBAAgB,OAAO;AAC/B,eAAO,CAAC,CAAC,SAAS,OAAO,UAAU;AAAA,MACpC;AAEA,eAAS,UAAU,OAAO;AACzB,YAAI,cAAc,OAAO,UAAU,SAAS,KAAK,KAAK;AAEtD,eAAO,gBAAgB,qBACnB,gBAAgB,mBAChB,eAAe,KAAK;AAAA,MACzB;AAGA,UAAI,eAAe,OAAO,WAAW,cAAc,OAAO;AAC1D,UAAI,qBAAqB,eAAe,OAAO,IAAI,eAAe,IAAI;AAEtE,eAAS,eAAe,OAAO;AAC9B,eAAO,MAAM,aAAa;AAAA,MAC3B;AAEA,eAAS,YAAY,KAAK;AACzB,eAAO,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;AAAA,MACnC;AAEA,eAAS,8BAA8B,OAAO,SAAS;AACtD,eAAQ,QAAQ,UAAU,SAAS,QAAQ,kBAAkB,KAAK,IAC/DC,WAAU,YAAY,KAAK,GAAG,OAAO,OAAO,IAC5C;AAAA,MACJ;AAEA,eAAS,kBAAkB,QAAQ,QAAQ,SAAS;AACnD,eAAO,OAAO,OAAO,MAAM,EAAE,IAAI,SAAS,SAAS;AAClD,iBAAO,8BAA8B,SAAS,OAAO;AAAA,QACtD,CAAC;AAAA,MACF;AAEA,eAAS,iBAAiB,KAAK,SAAS;AACvC,YAAI,CAAC,QAAQ,aAAa;AACzB,iBAAOA;AAAA,QACR;AACA,YAAI,cAAc,QAAQ,YAAY,GAAG;AACzC,eAAO,OAAO,gBAAgB,aAAa,cAAcA;AAAA,MAC1D;AAEA,eAAS,gCAAgC,QAAQ;AAChD,eAAO,OAAO,wBACX,OAAO,sBAAsB,MAAM,EAAE,OAAO,SAAS,QAAQ;AAC9D,iBAAO,OAAO,qBAAqB,KAAK,QAAQ,MAAM;AAAA,QACvD,CAAC,IACC,CAAC;AAAA,MACL;AAEA,eAAS,QAAQ,QAAQ;AACxB,eAAO,OAAO,KAAK,MAAM,EAAE,OAAO,gCAAgC,MAAM,CAAC;AAAA,MAC1E;AAEA,eAAS,mBAAmB,QAAQ,UAAU;AAC7C,YAAI;AACH,iBAAO,YAAY;AAAA,QACpB,SAAQ,GAAN;AACD,iBAAO;AAAA,QACR;AAAA,MACD;AAGA,eAAS,iBAAiB,QAAQ,KAAK;AACtC,eAAO,mBAAmB,QAAQ,GAAG,KACjC,EAAE,OAAO,eAAe,KAAK,QAAQ,GAAG,KACvC,OAAO,qBAAqB,KAAK,QAAQ,GAAG;AAAA,MAClD;AAEA,eAAS,YAAY,QAAQ,QAAQ,SAAS;AAC7C,YAAI,cAAc,CAAC;AACnB,YAAI,QAAQ,kBAAkB,MAAM,GAAG;AACtC,kBAAQ,MAAM,EAAE,QAAQ,SAAS,KAAK;AACrC,wBAAY,GAAG,IAAI,8BAA8B,OAAO,GAAG,GAAG,OAAO;AAAA,UACtE,CAAC;AAAA,QACF;AACA,gBAAQ,MAAM,EAAE,QAAQ,SAAS,KAAK;AACrC,cAAI,iBAAiB,QAAQ,GAAG,GAAG;AAClC;AAAA,UACD;AAEA,cAAI,mBAAmB,QAAQ,GAAG,KAAK,QAAQ,kBAAkB,OAAO,GAAG,CAAC,GAAG;AAC9E,wBAAY,GAAG,IAAI,iBAAiB,KAAK,OAAO,EAAE,OAAO,GAAG,GAAG,OAAO,GAAG,GAAG,OAAO;AAAA,UACpF,OAAO;AACN,wBAAY,GAAG,IAAI,8BAA8B,OAAO,GAAG,GAAG,OAAO;AAAA,UACtE;AAAA,QACD,CAAC;AACD,eAAO;AAAA,MACR;AAEA,eAASA,WAAU,QAAQ,QAAQ,SAAS;AAC3C,kBAAU,WAAW,CAAC;AACtB,gBAAQ,aAAa,QAAQ,cAAc;AAC3C,gBAAQ,oBAAoB,QAAQ,qBAAqB;AAGzD,gBAAQ,gCAAgC;AAExC,YAAI,gBAAgB,MAAM,QAAQ,MAAM;AACxC,YAAI,gBAAgB,MAAM,QAAQ,MAAM;AACxC,YAAI,4BAA4B,kBAAkB;AAElD,YAAI,CAAC,2BAA2B;AAC/B,iBAAO,8BAA8B,QAAQ,OAAO;AAAA,QACrD,WAAW,eAAe;AACzB,iBAAO,QAAQ,WAAW,QAAQ,QAAQ,OAAO;AAAA,QAClD,OAAO;AACN,iBAAO,YAAY,QAAQ,QAAQ,OAAO;AAAA,QAC3C;AAAA,MACD;AAEA,MAAAA,WAAU,MAAM,SAAS,aAAa,OAAO,SAAS;AACrD,YAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AAC1B,gBAAM,IAAI,MAAM,mCAAmC;AAAA,QACpD;AAEA,eAAO,MAAM,OAAO,SAAS,MAAM,MAAM;AACxC,iBAAOA,WAAU,MAAM,MAAM,OAAO;AAAA,QACrC,GAAG,CAAC,CAAC;AAAA,MACN;AAEA,UAAI,cAAcA;AAElB,aAAO,UAAU;AAAA;AAAA;;;ACpIjB;AAAA;AAAA;AAAA;AAAA;;;ACcA,MAAM,cAAc,CAAmC,WAAc;AACpE,WAAO,CAAC,QAA8B,UAAe;AACpD,aAAO,OAAO,MAAM,EAAE,KAAK;AAAA,IAC5B;AAAA,EACD;AAEA,MAAM,WAAW,CAAC,QAAgC;AACjD,WAAO,OAAO,QAAQ;AAAA,EACvB;AAEA,MAAM,SAAS,CAAC,QAA8B;AAC7C,WAAO,QAAQ;AAAA,EAChB;AAEA,MAAM,WAAW,CAAC,QAAgC;AACjD,WAAO,OAAO,QAAQ;AAAA,EACvB;AAEA,MAAM,aAAa,CAAC,QAAuD;AAC1E,WAAO,OAAO,QAAQ;AAAA,EACvB;AAEA,MAAM,YAAY,CAAC,QAAsC;AACxD,WAAO,QAAQ,GAAG,MAAM,OAAO,QAAQ,YAAY,WAAW,GAAG,MAAM,WAAY,IAAY,IAAI;AAAA,EACpG;AAEA,MAAM,UAAU,CAAC,QAA4B;AAC5C,WAAO,OAAO,QAAQ,YAAY,CAAC,OAAO,GAAG,KAAK,OAAO,KAAK,GAAG,EAAE,WAAW;AAAA,EAC/E;AAQA,MAAM,MAAM,CAAC,UAAmB;AAC/B,WAAO,OAAO,KAAK;AAAA,EACpB;AAEA,MAAM,uBAAuB,CAC5B,QACA,SACI;AACJ,WAAO,WAAW,YAAY,KAAK,CAAC,KAAM,KAAK,CAAC,EAA+B;AAAA,EAChF;AAEA,MAAM,qBAAqB,MAAuB;AACjD,WAAO;AAAA,EACR;AAEA,MAAM,cAAc,CAAC,WAAqB,WAAW,UAAU,aAAa;AAC3E,QAAI,UAAU,SAAS,QAAQ,GAAG;AACjC,aAAO;AAAA,IACR,WAAW,UAAU,SAAU,WAAW,SAAS,UAAU,GAAG,CAAC,CAAE,GAAG;AACrE,aAAO;AAAA,IACR,WAAY,WAAW,UAAU,KAAK,CAAC,UAAU,UAAU,UAAU,SAAS,KAAK,CAAC,GAAK;AACxF,aAAO;AAAA,IACR;AAKA,WAAO,UAAU,CAAC;AAAA,EACnB;AAMA,MAAM,WAAW,CAAqC,IAAQ,OAAe;AAC5E,QAAI,YAAY,OACf,WACA;AAED,aAAS,UAAmB;AAC3B,UAAI,WAAW;AACd,oBAAY;AACZ,oBAAY;AACZ;AAAA,MACD;AAEA,SAAG,MAAM,MAAM,SAA6B;AAE5C,kBAAY;AAEZ,iBAAW,WAAY;AACtB,oBAAY;AAEZ,YAAI,WAAW;AACd,kBAAQ,MAAM,WAAW,SAAS;AAClC,sBAAY,YAAY;AAAA,QACzB;AAAA,MACD,GAAG,EAAE;AAAA,IACN;AAEA,WAAO;AAAA,EACR;AAEA,MAAM,UAAU,CAAC,YAA4B;AAC5C,QAAI;AACH,UAAI,aAAa,WAAW;AAC3B,kBAAU,QAAQ,OAAO;AAAA,MAC1B;AAAA,IACD,QAAE;AAAA,IAAO;AAAA,EACV;AAEA,MAAM,gBAAgB,CAAI,OAAY,OAA6B;AAClE,aAAS,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;AAC1C,UAAI,GAAG,MAAM,CAAC,CAAC,GAAG;AACjB,eAAO;AAAA,MACR;AAAA,IACD;AAEA,WAAO;AAAA,EACR;;;AC3HA,MAAM,QAAQ,CAAI,SAAY,cAAc,oBAAI,IAAwB,MAAiB;AACxF,UAAM,YAAY,CAAC,OAA2B;AAC7C,kBAAY,IAAI,EAAE,GAAG,GAAG,OAAO;AAE/B,aAAO,MAAM;AACZ,oBAAY,OAAO,EAAE;AAAA,MACtB;AAAA,IACD;AAEA,UAAM,OAAO,CAAC,UAAa;AAC1B,kBAAY,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;AAAA,IACtC;AAEA,UAAM,SAAS,CAAC,OAAuB;AACtC,WAAM,UAAU,GAAG,OAAO,CAAE;AAAA,IAC7B;AAEA,UAAM,MAAM,MAAM;AACjB,aAAO;AAAA,IACR;AAEA,WAAO,EAAE,WAAW,QAAQ,IAAI;AAAA,EACjC;;;ACEA,yBAAiC;;;AC9B1B,WAAS,MAAM,KAAK;AAC1B,QAAI,GAAG,KAAK;AAEZ,QAAI,MAAM,QAAQ,GAAG,GAAG;AACvB,YAAM,MAAM,IAAE,IAAI,MAAM;AACxB,aAAO;AAAK,YAAI,CAAC,KAAK,MAAI,IAAI,CAAC,MAAM,OAAO,QAAQ,WAAW,MAAM,GAAG,IAAI;AAC5E,aAAO;AAAA,IACR;AAEA,QAAI,OAAO,UAAU,SAAS,KAAK,GAAG,MAAM,mBAAmB;AAC9D,YAAM,CAAC;AACP,WAAK,KAAK,KAAK;AACd,YAAI,MAAM,aAAa;AACtB,iBAAO,eAAe,KAAK,GAAG;AAAA,YAC7B,OAAO,MAAM,IAAI,CAAC,CAAC;AAAA,YACnB,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,UAAU;AAAA,UACX,CAAC;AAAA,QACF,OAAO;AACN,cAAI,CAAC,KAAK,MAAI,IAAI,CAAC,MAAM,OAAO,QAAQ,WAAW,MAAM,GAAG,IAAI;AAAA,QACjE;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,EACR;;;AC3BA,MAAM,yBAAyB,oBAAI,IAAI,CAAC,UAAU,UAAU,SAAS,WAAW,MAAM,CAAU;AAEhG,MAAM,YAAY,oBAAI,IAAS;;;ACF/B,MAAMC,IAAQ,CAACC,GAAeC,MAAyB;AACtD,QAAMC,IAAiC,CAAC;AAExC,aAAWC,KAAaF,GAAY;AACnC,UAAI,CAACD;AAAO;AAEZ,UAAM,CAACI,GAAOC,CAAG,IAAIL,EAAM,MAAMG,GAAW,CAAC;AAE7CD,QAAO,KAAKE,CAAK,GACjBJ,IAAQK;IACT;AAEA,WAAAH,EAAO,KAAKF,CAAK,GAEVE;EACR;AC0BA,MAAMI,IAAM;AAAZ,MAQMC,IAAUC,OACX,MAAM,QAAQA,CAAC,IACXA,EAAE,IAAKC,OAASF,EAAOE,CAAI,CAAC,EAAE,KAAK,MAAM,IAG7C,OAAOD,KAAM,aACTD,EAAOC,EAAE,CAAC,IAGXA;AAjBR,MAoBME,IAAU,CACfC,GACAC,GACAC,GACAC,GACAC,MAEOR,EAAOI,CAAG,EAAE,QAAQL,GAAK,CAACU,GAAQC,GAAaC,MAAW;AAChEF,QAAI,GACJE,IAAIN;AAEJ,QAAM,CAACO,GAASC,GAAQC,CAAM,IAAItB,EAAMkB,EAAI,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,GAE1DK,IAAOH,EAAS,MAAM,GAAG;AAE7B,WAAOD,KAAKF,IAAIM,EAAK;AAAQJ,UAAIA,EAAEI,EAAKN,GAAG,CAAC;AAExCI,SAAUP,KAAiBK,KAAKH,MACnCG,IAAIL,EAAcO,CAAM,EAAEL,EAAG,OAAOG,CAAC,CAAC;AAGvC,QAAMK,IAAgBT,KAAWO,KAAUP,EAAQO,CAAM;AAEzD,WAAIE,MAAeL,IAAIK,EAAcL,CAAC,IAE/BA,KAAgB;EACxB,CAAC;;;AJmBF,MAAM,SAAS,CAMb;AAAA,IACD;AAAA,IACA;AAAA,IACA,eAAe,QAAQ,QAAQ;AAAA,IAC/B,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,aAAa,CAAC;AAAA,IACd,kBAAkB;AAAA,IAClB,aAAAM,eAAc;AAAA,EACf,MAAyE;AACxE,QAAI;AACJ,QAAI,QAAQ,oBAAI,IAAY;AAK5B,oBAAgB,CAAC;AACjB,qBAAiB,CAAC;AAKlB,UAAM,SAAS,CAAC,UAAkB;AACjC,aAAO,MAAM,IAAI,KAAK,GAAG;AAAA,IAC1B;AAEA,UAAM,YAAY,CAAC,MAAa;AAI/B,cAAQ,OAAO;AAAA,QACd,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AACxC,gBAAM,OAAO,CAAC,SAAyD;AACtE,mBAAO,KAAK,QAAQ,CAACC,UAAS;AAC7B,oBAAM,OAAOA,MAAK,CAAC;AAKnB,kBAAI,MAAM,QAAQ,IAAI;AAAG,uBAAO,KAAKA,KAAqB;AAE1D,qBAAO,CAACA,KAAmB;AAAA,YAC5B,CAAC;AAAA,UACF;AAEA,iBAAO,CAAC,MAAM,KAAK,KAAK,CAAC;AAAA,QAC1B,CAAC;AAAA,MACF;AAKA,UAAI,kBAAkB;AAAQ,iBAAS,GAAG,WAAW,aAAa;AAAA,IACnE;AAEA,UAAM,SAAS,IAAI,MAAM,CAAC,GAAsC;AAAA,MAC/D,IAAI,GAAG,MAAM;AACZ,eAAO,IACH,UAGC;AACJ,iBAAO,CAAC,MAAM,GAAG,KAAK;AAAA,QACvB;AAAA,MACD;AAAA,IACD,CAAC;AAID,aAAS,MAAM,OAA6F;AAC3G,UAAI,CAAC;AAAO,eAAO,MAAM,MAAM,CAAC;AAEhC,YAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,YAAM,MAAM,WAAW,KAAK,IAAI,MAAM,IAAmB,QAAI,iBAAAC,KAAU,CAAC,MAAM,KAAK,CAAC;AAEpF,YAAM,MAAM,CAAC,IAAI;AAAA,IAClB;AAEA,UAAM,iBAAiB,CAACC,SAAQ,CAAC,MAAM;AACtC,aAAO;AAAA,QACN;AAAA,UACC,CAAC,MAAM,OAAO;AAAA,UACd,CAAC,MAAM,CAAC;AAAA,QACT;AAAA,QACAA;AAAA,QACA,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,MAAM;AAAA,MAC5B;AAAA,IACD;AAEA,UAAM,cAAc,CAAC,SAAeC,SAAQ,CAAC,OAAO,MAAM;AACzD,aAAO;AAAA,QACN,IAAI,QAAQ;AACX,iBAAOA,OAAM,GAAG,EAAE;AAAA,QACnB;AAAA,QACA,IAAI,MAAM,OAAa;AACtB,UAAAA,OAAMA,OAAM,SAAS,CAAC,IAAI;AAAA,QAC3B;AAAA,QACA,OAAO;AACN,cAAIA,OAAM,SAAS;AAAG,YAAAA,OAAM,IAAI,GAAI,YAAY;AAAA,QACjD;AAAA,QACA,KAAK,OAAa;AACjB,UAAAA,OAAM,KAAK,KAAK;AAAA,QACjB;AAAA,QACA,QAAQ;AACP,UAAAA,SAAQ,CAAC,eAAe,MAAM,YAAY,CAAC,CAAC;AAAA,QAC7C;AAAA,MACD;AAAA,IACD;AAMA,UAAM,cAA2B;AAAA,MAChC,OAAO,CAAC;AAAA,MACR,MAAM,MAAM,WAAW;AAAA,MACvB,MAAM,CAACJ,aAAY,SAAS,GAAG,mBAAmB,CAAC;AAAA,IACpD;AAEA,UAAM,IAAI,MAAM,WAAW;AAE3B,QAAI,oBAAoB;AAExB,UAAM,sBAAsB,CAAC,UAAuB;AACnD,UAAI;AAAmB,gBAAQ,IAAI,KAAK;AAAA,IACzC;AAEA,UAAM,+BAA+B,SAAS,qBAAqB,eAAe;AAElF,MAAE,UAAU,4BAA4B;AAExC,UAAM,gBAAgB,MAAM;AAC3B,cAAQ,IAAI,EAAE,KAAK,CAAC,WAAW;AAI9B,mBAAW,aAAa,YAAY;AAEnC,mBAAS,UAAU,MAAM;AAAA,QAC1B;AAKA,eAAO,KAAK,CAAC,MAAMA,aAAY,SAAS;AACxC,eAAO,KAAK,CAAC,MAAM,mBAAmB;AAMtC,YAAI,QAAQ,OAAO,IAAI,GAAG;AACzB,iBAAO,OAAO;AAAA,QACf;AAKA,4BAAoB;AAEpB,UAAE,OAAO,MAAM,MAAM;AAKrB,YAAI,kBAAkB;AAAQ,kBAAQ;AAAA,MACvC,CAAC;AAAA,IACF;AAMA,iBAAa,KAAK,aAAa;AAE/B,UAAM,UAAU,eAAe,MAAM,YAAY,CAAC;AAClD,UAAM,QAAQ,YAAY,OAAO;AAEjC,UAAM,OAAO,CAAC,WAAW,OAAO,OAAmB,WAAW,SAAS,aAAa;AACnF,UAAI,CAAC;AAAmB;AAKxB,UAAI,CAAC,aAAa,SAAS;AAAQ;AAEnC,YAAM,UAAU,MAAM,MAAM,KAAK;AAEjC,QAAE,OAAO,CAAC,SAAS;AAWlB,cAAM,WAAW,cAAc,KAAK,OAAO,CAAC,UAAU,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,SAAS;AAKtG,gBAAQ,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,IAAI,CAAC;AACjC,gBAAQ,CAAC,EAAE,CAAC,IAAI;AAEhB,YAAI,CAAC,YAAY,CAAC,UAAU;AAC3B,eAAK,MAAM,KAAK,OAAO;AAEvB,iBAAO;AAAA,QACR;AAKA,cAAM,SAAS,KAAK,MAAM,GAAG,EAAE;AAK/B,YAAI,UAAU,OAAO,CAAC,EAAE,CAAC,MAAM,MAAM;AACpC,eAAK,MAAM,KAAK,MAAM,SAAS,CAAC,IAAI;AAAA,QACrC,OAAO;AACN,eAAK,MAAM,KAAK,OAAO;AAAA,QACxB;AAEA,eAAO;AAAA,MACR,CAAC;AAAA,IACF;AAEA,UAAM,UAAU,MAAM;AACrB,UAAI,CAAC;AAAmB;AAExB,YAAMK,QAAO,eAAe,MAAM,YAAY,CAAC;AAK/C,UAAI,WAAW;AACd,UAAE,OAAO,CAAC,SAAS;AAClB,iBAAO,KAAK,MAAM,KAAKA,KAAI,GAAG;AAAA,QAC/B,CAAC;AAAA,MACF;AAEA,cAAQA,KAAI;AAAA,IACb;AAKA,UAAM,MAAM,CAACA,UAAe;AAC3B,YAAM,QAAQA;AAEd,aAAO,QAAQA,KAAI;AAAA,IACpB;AAEA,QAAI,YAAY;AAChB,QAAI,YAAY;AAChB,QAAI,aAAa;AAKjB,UAAM,UAAU,OAAOA,UAAgB;AACtC,UAAI,CAAC;AAAmB;AAExB,UAAI,SAASA,QAAOA,QAAO,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE;AAK9C,UAAI,CAAC,QAAQ;AACZ,UAAE,OAAO,OAAO;AAAA,UACf,OAAO,CAAC,OAAO;AAAA,UACf,MAAM,MAAM,WAAW;AAAA,UACvB,MAAM,CAACL,aAAY,SAAS,GAAG,mBAAmB,CAAC;AAAA,QACpD,EAAE;AAEF,iBAAS,MAAM,OAAO;AAAA,MACvB;AAEA,MAAC,YAAY,MAAQ,MAAM,QAAQ;AAKnC,UAAI,UAAe;AAInB,UAAI,QAAQ;AAKZ,YAAM,MAAM,MAAM,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;AACvD,YAAI,OAAO,IAAI,KAAK,SAAS,GAAG;AAAG,iBAAO,MAAM;AAEhD,eAAO;AAAA,MACR,GAAG,CAAC;AAEJ,YAAM,QAAQ,CAAC;AACf,YAAM,OAAO,oBAAI,IAAI;AACrB,YAAMM,cAAa,oBAAI,IAAI;AAE3B,iBAAW,CAAC,MAAM,GAAG,KAAK,MAAM,MAAM,CAAC,GAAG;AACzC,YAAI,SAAS,MAAM;AAClB,cAAI,SAAS,GAAG,GAAG;AAClB,sBAAU,QAAQ,GAAG;AAAA,UACtB,WAAW,SAAS,GAAG,GAAG;AACzB;AAMA,qBAAS,IAAI,GAAG,KAAK,KAAK,KAAK;AAC9B,oBAAM,CAACC,SAAQ,GAAG,IAAI,IAAI,QAAQ,CAAC;AAKnC,oBAAMC,QAAO,MAAM;AAClB,qBAAK,IAAID,OAAM;AACf,sBAAM,KAAK,CAACA,SAAQ,IAAI,CAAC;AAAA,cAC1B;AAKA,kBAAIA,YAAW;AAAiB,gBAAAD,YAAW,IAAI,KAAK,CAAC,CAAC;AAMtD,kBAAI,uBAAuB,IAAIC,OAAM,KAAK,qBAAqBA,SAAQ,IAAI,GAAG;AAC7E,oBAAI,UAAU,OAAO,MAAM,KAAK;AAC/B,kBAAAC,MAAK;AAAA,gBACN,OAAO;AACN;AAAA,gBACD;AAAA,cACD;AAEA,cAAAA,MAAK;AAAA,YACN;AAEA,sBAAU,QAAQ,GAAG;AAAA,UACtB;AAAA,QACD,WAAW,SAAS,UAAU;AAC7B,oBAAU,QAAS,MAAiB,CAAC,EAAE,CAAC;AAAA,QACzC,WAAW,SAAS,aAAa;AAChC,oBAAU,QAAQ,CAAC,EAAE,GAAG;AAAA,QACzB;AAAA,MACD;AAEA,YAAM,QAAQ,CAAC,OAAOC,WAAU;AAI/B,cAAM,KAAKA,MAAK;AAAA,MACjB,CAAC;AAKD,YAAM,eAAe;AAKrB,eAAS,GAAG,WAAW,MAAM;AAI7B,YAAM,SAAS,CAAC,MAAMH,WAAU,CAAC;AAKjC,YAAMI,QAAO,CAAC,MAAc,aAAa,MAAM,IAAI,CAAC;AAEpD,uBAAiB,CAACH,SAAQ,MAAM,CAAC,KAAK,cAAc;AACnD,YAAIA,YAAW,cAAcA,YAAW,UAAU;AAIjD,cAAIA,YAAW,YAAa,KAAuC,CAAC,EAAE,gBAAgB;AAIrF,kBAAM,YAAYG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,KAAK,MAAM;AACpD,kBAAI,CAAC,SAAS,CAAC;AAAM,uBAAO;AAE5B,oBAAM,KAAK,MAAM,CAAC;AAClB,oBAAM,KAAK,KAAK,CAAC;AAKjB,oBAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG;AAKrD,qBAAO,iBAAiB,IAAI,EAAE,MAAM,IAAI,EAAE;AAAA,YAC3C,CAAC;AAED,gBAAI;AAAW;AAAA,UAChB;AAKA,gBAAM,SAAS,MAAMH,SAAQ,IAAI;AAKjC,cAAI,UAAU,MAAM,GAAG;AAItB,kBAAM;AAAA,UACP;AAAA,QACD,WAAWA,YAAW,iBAAiB;AACtC,gBAAM,OAAOG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,KAAK,MAAM;AAI/C,gBAAI,CAAC,SAAS,CAAC;AAAM,qBAAO;AAM5B,kBAAM,SAAS,YAAY,mBAAmB,MAAM,CAAC,MAAM,KAAK,CAAC;AAKjE,kBAAM,YAAY,YAAYH,WAAU,MAAM,CAAC,MAAM,KAAK,CAAC;AAE3D,mBAAO,UAAU;AAAA,UAClB,CAAC;AAED,cAAI;AAAM;AAEV,gBAAMA,SAAQ,IAAI;AAAA,QACnB,WAAWA,YAAW,oBAAoBA,YAAW,oBAAoB;AAKxE,gBAAM,YAAYG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,MAAMH,YAAW,OAAO;AAEhE,cAAI;AAAW;AAEf,gBAAMA,SAAQ,IAAI;AAAA,QACnB,OAAO;AACN,gBAAMA,SAAQ,IAAI;AAAA,QACnB;AAAA,MACD;AAEA,MAAC,YAAY,YAAY,OAAQ,OAAO;AAAA,IACzC;AAEA,UAAM,QAAQ,MAAM;AACnB,UAAI,UAAe;AAEnB,iBAAW,CAAC,MAAM,GAAG,KAAK,MAAM,MAAM,CAAC,GAAG;AACzC,YAAI,SAAS,MAAM;AAClB,oBAAU,QAAQ,GAAG;AAAA,QACtB,WAAW,SAAS,UAAU;AAC7B,oBAAU,QAAS,MAAiB,CAAC,EAAE,CAAC;AAAA,QACzC,WAAW,SAAS,aAAa;AAChC,oBAAU,QAAQ,CAAC,EAAE,GAAG;AAAA,QACzB;AAAA,MACD;AAEA,aAAO;AAAA,IACR;AAEA,UAAM,OAAO,MAAM;AAClB,YAAM,UAAU,MAAM;AAEtB,YAAM,MAAM;AACZ,eAAS,GAAG,WAAW,UAAU;AAKjC,YAAM,CAAC,CAAC,OAAO,MAAM,GAAG,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI;AAE1C,UAAI,SAAS,UAAU,SAAS,QAAQ;AAIvC,YAAI,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,WAAW,OAAO,CAAC,MAAM,QAAQ,CAAC,cAAc,MAAM,IAAI,IAAI,GAAG;AACtG,YAAE,OAAO,CAAC,SAAS;AAClB,iBAAK,QAAQ,KAAK,MAAM,OAAO,CAACF,UAASA,UAAS,OAAO;AAEzD,mBAAO;AAAA,UACR,CAAC;AAAA,QACF;AAAA,MACD;AAKA,oBAAc,KAAK;AAInB,YAAM,MAAM;AAAA,IACb;AAEA,UAAM,OAAO,MAAM;AAClB,aAAO,MAAM,KAAK,GAAG,QAAQ,MAAM,KAAK;AAAA,IACzC;AAEA,UAAM,WAAW,eAAe;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,IAAI;AAAA,MACP;AAAA,IACD,CAAC;AAED,UAAM,QAAQ,YAAY;AAAA,MACzB,KAAK,CAAC,IAAI,GAAG;AACZ,YAAI,CAAC;AAAW,qBAAW,MAAM,WAAW,IAAI,IAAI,KAAK,IAAI,IAAI;AAAA,MAClE;AAAA,MACA,eAAe,CAAC,UAAU,GAAG;AAC5B,iBAAS,WAAW,UAAU;AAC9B,aAAK;AAAA,MACN;AAAA,MACA,UAAU,CAAC,MAAM,GAAG;AACnB,iBAAS,MAAM,QAAQ,OAAO,EAAE,KAAK;AACrC,aAAK;AAAA,MACN;AAAA,MACA,UAAU,CAAC,MAAM,GAAG;AACnB,iBAAS,MAAM,QAAQ,OAAO,EAAE,KAAK;AACrC,aAAK;AAAA,MACN;AAAA,MACA,cAAc,CAAC,WAAW,SAAS,WAAW,KAAK,GAAG;AACrD,cAAM,SAAS,SAAS,UAAU,SAAS;AAE3C,eAAO,OAAO,WAAW,OAAO,SAAS;AACzC,eAAO,YAAY,OAAO,EAAE;AAE5B,aAAK;AAAA,MACN;AAAA,MACA,cAAc,CAAC,WAAW,WAAW,OAAO,QAAQ,GAAG;AACtD,iBAAS,UAAU,SAAS,EAAE,OAAO,WAAW,OAAO,QAAQ,EAAE,MAAM,SAAS;AAAA,MACjF;AAAA,MACA,OAAO,CAAC,WAAW,SAAS,OAAO,GAAG;AAIrC,cAAM,QAAQ,MAAM;AACnB,gBAAM,IAAI,WACT,KAAK;AACN,gBAAM,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;AAE3B,iBAAO,IACJ,KAAK,KACJ,OAAO,GAAG,CAAC,EAAE,SAAS,WACpB,GAAG,CAAC,EAAE,OACN,GAAG,CAAC,EAAE,KAAgC,IAAI,IAC5C,IACD;AAAA,QACJ,GAAG;AAEH,iBAAS,OAAO,OAAO,OAAO,GAAG,OAAO,IAAI,GAAG,WAAW,OAAO,EAAE,OAAO;AAAA,MAC3E;AAAA,MACA,SAAS,CAAC,EAAE,GAAG;AACd,cAAM,SAAS,GAAG,WAAW,SAAS;AAEtC,YAAI,CAAC;AAAW,mBAAS,OAAO,KAAK,IAAI,IAAI,KAAK;AAElD,eAAO;AAAA,MACR;AAAA,MACA,OAAO,CAAC,UAAU,GAAG,OAAO,GAAG;AAC9B,cAAM,oBAAoB,MAAM,QAAQ,QAAQ;AAEhD,YAAI,mBAAmB;AAItB,kBAAQ,QAAQ,QAAkE;AAIlF,qBAAW;AAAA,QACZ;AAEA,cAAM,YAAY,QAAQ,IAAI,CAAC,CAAC,SAASE,SAAQ,OAAO,MAAM;AAC7D,iBAAO,CAAC,OAAO,OAAO,GAAGA,SAAQ,OAAO;AAAA,QACzC,CAAC;AAED,iBAAS;AAAA,UACR,OAAO,QAAQ;AAAA,UACf;AAAA,QACD,EAAE,CAAC,aAAa;AACf,mBAAS;AAKT,gBAAM,SAAS,oBAAoB,IAAI;AAEvC,gBAAM,MAAM,CAAC,EAAE,KAAK,CAAC,UAAU,WAAW,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5D,iBAAO;AACP,wBAAc,IAAI;AAAA,QACnB,CAAC;AAAA,MACF;AAAA,MACA,KAAK,CAAC,KAAK,GAAG;AAIb,cAAM,MAAM,CAAC,IAAI;AAAA,UAChB,CAAC,MAAM,KAAK;AAAA,UACZ,CAAC,MAAM,EAAE;AAAA,QACV;AAEA,cAAM,SAAS,CAAC,CAAC;AAAA,MAClB;AAAA,MACA,MAAM,CAAC,MAAMD,WAAU,GAAG;AAIzB,gBAAQ,CAAC;AAIT,iBAAS,MAAM,WAAW,QAAQ,WAAWA,eAAc,SAAS,EAAE,IAAI;AAAA,MAC3E;AAAA,MACA,UAAU,CAAC,SAAS,GAAG;AACtB,cAAM,QAAQ,UAAU;AAExB,YAAI,CAAC;AAAW,gBAAM,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO;AAAA,MACtF;AAAA,MACA,MAAM;AAIL,cAAM,SAAS,CAAC,CAAC;AAIjB,iBAAS,GAAG,WAAW,UAAU;AAIjC,sBAAc,KAAK;AAInB,cAAM,MAAM;AAAA,MACb;AAAA,MACA,MAAM,CAAC,UAAU,SAAS,KAAK,GAAG;AACjC,iBAAS,MAAM,OAAO,QAAQ,GAAG,SAAS,KAAK,EAAE,OAAO;AAAA,MACzD;AAAA,MACA,OAAO,CAAC,OAAO,GAAG;AACjB,cAAM,SAAS,SAAS,OAAO,SAAS,WAAW,MAAM;AACxD,cAAI,CAAC,aAAa,QAAQ;AAAmB,qBAAS,GAAG,cAAc,IAAI;AAC3E,cAAI,CAAC;AAAW,iBAAK;AAAA,QACtB,CAAC;AAED,eAAO;AAAA,MACR;AAAA,MACA,QAAQ,SAAS;AAChB,gBAAQ,OAAO;AACf,aAAK;AAAA,MACN;AAAA,MACA,OAAO;AACN,aAAK;AAAA,MACN;AAAA,MACA,iBAAiB,CAAC,WAAW,SAAS,GAAG,OAAO,GAAG;AAClD,cAAM,UAAyB,CAAC,QAAQ;AACvC,gBAAM,EAAE,MAAM,IAAI,IAAI,gCAAgC,KAAK;AAC3D,gBAAM,OAAO,SAAS,MAAM,WAAW,SAAS;AAKhD,cAAI,CAAC;AAAM;AAEX,gBAAM,SAAS,KAAK;AAKpB,cAAI,CAAC;AAAQ;AAEb,gBAAM,aAAa,QAAQ,OAAO,CAAC,cAAc,CAAC,OAAO,UAAU,SAAS,SAAS,CAAC;AAEtF,iBAAO,UAAU,IAAI,GAAG,UAAU;AAElC,gBAAM,YAAY,WAAW,MAAM;AAClC,mBAAO,UAAU,OAAO,GAAG,UAAU;AAAA,UACtC,GAAG,OAAO;AAEV,gBAAM,MAAM;AACX,mBAAO,UAAU,OAAO,GAAG,UAAU;AAKrC,yBAAa,SAAS;AAAA,UACvB,CAAC;AAAA,QACF;AAKA,cAAM,UAAU,CAAC,OAAO,CAAC;AAAA,MAC1B;AAAA,MACA,KAAK,MAAM;AACV,iBAAS,KAAK,KAAK,IAAI,CAAC,YAAY,OAAO,OAAO,CAAC,EAAE,KAAK,GAAG,GAAG,OAAO;AAAA,MACxE;AAAA,MACA,OAAO;AACN,cAAM,OAAO,MAAM,MAAM,CAAC;AAE1B,iBAAS,IAAI,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK;AACzC,cAAI,KAAK,CAAC,EAAE,CAAC,MAAM,YAAY,KAAK,CAAC,EAAE,CAAC,MAAM;AAAa;AAE3D,gBAAM,MAAM,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC;AAChC,eAAK;AAEL;AAAA,QACD;AAEA,eAAO;AAAA,MACR;AAAA,IACD,CAAC;AAED,UAAM,WAAW,MAAM;AACtB,UAAI;AAAW;AAEf,YAAM,UAAU,MAAM,MAAM,KAAK;AAEjC,cAAQ,CAAC,EAAE,CAAC,IAAI;AAEhB,YAAM,KAAK,OAAO;AAElB,WAAK,MAAM,MAAM;AAAA,IAClB;AAEA,UAAM,OAAO,MAAM;AAClB,YAAM,OAAO,MAAM,MAAM,CAAC;AAI1B,YAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AAKjC,UAAI,OAAO,KAAK,CAAC,CAAC,KAAK,SAAS,KAAK,CAAC,CAAC,GAAG;AACzC,aAAK,CAAC,IAAI,KAAK,CAAC,IAAI;AACpB;AAAA,MACD;AAKA,WAAK,KAAK,CAAC,MAAM,CAAC,CAAC;AAAA,IACpB;AAEA,UAAM,SAAS,MAAM;AACpB,YAAM,WAAW,MAAM;AAEvB,UAAI,CAAC,MAAM,QAAQ,QAAQ;AAAG;AAE9B,YAAM,CAACC,SAAQ,GAAG,KAAK,IAAI;AAE3B,YAAMA,SAAQ,KAAK;AAAA,IACpB;AAEA,UAAM,OAAO,MAAM;AAClB,UAAI,CAAC;AAAW,aAAK,GAAG,OAAO;AAAA,IAChC;AAEA,UAAM,UAAU,MAAM;AACrB,eAAS;AACT,WAAK;AACL,oBAAc,IAAI;AAAA,IACnB;AAEA,UAAM,gBAAgB,CAAC,QAAQ,UAAU;AACxC,mBAAa;AAAA,IACd;AAYA,UAAM,SAAS,CAAC,SAAsB,SAAS,UAAU;AACxD,YAAM;AAAA,QACL,MAAAN;AAAA,QACA,MAAM,CAAC,IAAI;AAAA,MACZ,IAAI,EAAE,IAAI;AAEV,YAAM,MAAM,SAASA,QAAO,MAAM;AAClC,YAAM,MAAM,WAAW,OAAO,IAAI,QAAQ,MAAM,GAAG,IAAI,OAAO,YAAY,WAAW,UAAU,QAAQ,IAAI;AAE3G,YAAMU,OAAM,WAAW,GAAG,IAAI,IAAI,IAAI;AAEtC,aAAO,EAAWA,MAAK,GAAG;AAAA,IAC3B;AAIA,aAAS,KAAK,OAAyF;AACtG,UAAI,CAAC;AAAO,eAAO,EAAE,IAAI,EAAE;AAE3B,YAAM,OAAO,EAAE,IAAI,EAAE;AACrB,YAAM,MAAM,WAAW,KAAK,IAAI,MAAM,IAAkB,QAAI,iBAAAT,KAAU,CAAC,MAAM,KAAK,CAAC;AAEnF,QAAE,OAAO,CAACU,UAAS;AAClB,QAAAA,MAAK,OAAO;AAEZ,eAAOA;AAAA,MACR,CAAC;AAAA,IACF;AAEA,WAAO;AAAA;AAAA;AAAA;AAAA,MAIN;AAAA;AAAA;AAAA;AAAA,MAIA;AAAA;AAAA;AAAA;AAAA,MAIA;AAAA;AAAA;AAAA;AAAA,MAIA;AAAA;AAAA;AAAA;AAAA,MAIA,OAAO,SAAmF;AACzF,eAAO,OAAO,SAAS,IAAI;AAAA,MAC5B;AAAA;AAAA;AAAA;AAAA,MAIA,GAAG,IAAI;AAAA,IACR;AAAA,EACD;;;AM/8BA,MAAM,sBAAsB,CAAC,YAAkD;AAC9E,WAAO;AAAA,MACN,MAAM,MAAM;AACX,cAAM,QAAQ,aAAa,QAAQ,QAAQ,GAAG;AAE9C,eAAO,QAAQ,KAAK,MAAM,KAAK,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,MAAM,IAAI,MAAM;AACf,qBAAa,QAAQ,QAAQ,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,MACvD;AAAA,IACD;AAAA,EACD;","names":["isMergeableObject","deepmerge","split","input","delimeters","output","delimeter","start","end","RGX","unwrap","c","item","replace","str","obj","pluralization","actions","pr","x","key","y","pathstr","plural","action","path","actionHandler","getLanguage","data","deepmerge","state","stack","save","characters","action","push","index","next","str","prev"]}
|
package/dist/index.js
CHANGED
|
@@ -103,13 +103,7 @@ import { all as deepmerge } from "deepmerge";
|
|
|
103
103
|
import { klona } from "klona/json";
|
|
104
104
|
|
|
105
105
|
// src/constants.ts
|
|
106
|
-
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set([
|
|
107
|
-
"dialog",
|
|
108
|
-
"choice",
|
|
109
|
-
"input",
|
|
110
|
-
"vibrate",
|
|
111
|
-
"text"
|
|
112
|
-
]);
|
|
106
|
+
var SKIPPED_DURING_RESTORE = /* @__PURE__ */ new Set(["dialog", "choice", "input", "vibrate", "text"]);
|
|
113
107
|
var EMPTY_SET = /* @__PURE__ */ new Set();
|
|
114
108
|
|
|
115
109
|
// src/novely.ts
|
|
@@ -125,7 +119,9 @@ var novely = ({
|
|
|
125
119
|
state: defaultState,
|
|
126
120
|
data: defaultData,
|
|
127
121
|
autosaves = true,
|
|
128
|
-
migrations = []
|
|
122
|
+
migrations = [],
|
|
123
|
+
throttleTimeout = 799,
|
|
124
|
+
getLanguage: getLanguage2 = getLanguage
|
|
129
125
|
}) => {
|
|
130
126
|
let story;
|
|
131
127
|
let times = /* @__PURE__ */ new Set();
|
|
@@ -135,17 +131,19 @@ var novely = ({
|
|
|
135
131
|
return times.add(value), value;
|
|
136
132
|
};
|
|
137
133
|
const withStory = (s) => {
|
|
138
|
-
story = Object.fromEntries(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
134
|
+
story = Object.fromEntries(
|
|
135
|
+
Object.entries(s).map(([name, items]) => {
|
|
136
|
+
const flat = (item) => {
|
|
137
|
+
return item.flatMap((data2) => {
|
|
138
|
+
const type = data2[0];
|
|
139
|
+
if (Array.isArray(type))
|
|
140
|
+
return flat(data2);
|
|
141
|
+
return [data2];
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
return [name, flat(items)];
|
|
145
|
+
})
|
|
146
|
+
);
|
|
149
147
|
if (initialScreen !== "game")
|
|
150
148
|
renderer.ui.showScreen(initialScreen);
|
|
151
149
|
};
|
|
@@ -164,7 +162,14 @@ var novely = ({
|
|
|
164
162
|
stack.value[1] = val;
|
|
165
163
|
}
|
|
166
164
|
const getDefaultSave = (state2 = {}) => {
|
|
167
|
-
return [
|
|
165
|
+
return [
|
|
166
|
+
[
|
|
167
|
+
[null, "start"],
|
|
168
|
+
[null, 0]
|
|
169
|
+
],
|
|
170
|
+
state2,
|
|
171
|
+
[intime(Date.now()), "auto"]
|
|
172
|
+
];
|
|
168
173
|
};
|
|
169
174
|
const createStack = (current, stack2 = [current]) => {
|
|
170
175
|
return {
|
|
@@ -189,7 +194,7 @@ var novely = ({
|
|
|
189
194
|
const initialData = {
|
|
190
195
|
saves: [],
|
|
191
196
|
data: klona(defaultData),
|
|
192
|
-
meta: [
|
|
197
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
193
198
|
};
|
|
194
199
|
const $ = store(initialData);
|
|
195
200
|
let initialDataLoaded = false;
|
|
@@ -197,14 +202,14 @@ var novely = ({
|
|
|
197
202
|
if (initialDataLoaded)
|
|
198
203
|
storage.set(value);
|
|
199
204
|
};
|
|
200
|
-
const throttledOnStorageDataChange = throttle(onStorageDataChange,
|
|
205
|
+
const throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);
|
|
201
206
|
$.subscribe(throttledOnStorageDataChange);
|
|
202
207
|
const getStoredData = () => {
|
|
203
208
|
storage.get().then((stored) => {
|
|
204
209
|
for (const migration of migrations) {
|
|
205
210
|
stored = migration(stored);
|
|
206
211
|
}
|
|
207
|
-
stored.meta[0] ||=
|
|
212
|
+
stored.meta[0] ||= getLanguage2(languages);
|
|
208
213
|
stored.meta[1] ||= getTypewriterSpeed();
|
|
209
214
|
if (isEmpty(stored.data)) {
|
|
210
215
|
stored.data = defaultData;
|
|
@@ -264,7 +269,11 @@ var novely = ({
|
|
|
264
269
|
return;
|
|
265
270
|
let latest = save2 ? save2 : $.get().saves.at(-1);
|
|
266
271
|
if (!latest) {
|
|
267
|
-
$.update(() => ({
|
|
272
|
+
$.update(() => ({
|
|
273
|
+
saves: [initial],
|
|
274
|
+
data: klona(defaultData),
|
|
275
|
+
meta: [getLanguage2(languages), getTypewriterSpeed()]
|
|
276
|
+
}));
|
|
268
277
|
latest = klona(initial);
|
|
269
278
|
}
|
|
270
279
|
restoring = true, stack.value = latest;
|
|
@@ -450,7 +459,10 @@ var novely = ({
|
|
|
450
459
|
const unwrapped = choices.map(([content, action2, visible]) => {
|
|
451
460
|
return [unwrap(content), action2, visible];
|
|
452
461
|
});
|
|
453
|
-
renderer.choices(
|
|
462
|
+
renderer.choices(
|
|
463
|
+
unwrap(question),
|
|
464
|
+
unwrapped
|
|
465
|
+
)((selected) => {
|
|
454
466
|
enmemory();
|
|
455
467
|
const offset = isWithoutQuestion ? 0 : 1;
|
|
456
468
|
stack.value[0].push(["choice", selected + offset], [null, 0]);
|
|
@@ -459,7 +471,10 @@ var novely = ({
|
|
|
459
471
|
});
|
|
460
472
|
},
|
|
461
473
|
jump([scene]) {
|
|
462
|
-
stack.value[0] = [
|
|
474
|
+
stack.value[0] = [
|
|
475
|
+
[null, scene],
|
|
476
|
+
[null, -1]
|
|
477
|
+
];
|
|
463
478
|
match("clear", []);
|
|
464
479
|
},
|
|
465
480
|
clear([keep, characters2]) {
|
|
@@ -569,9 +584,13 @@ var novely = ({
|
|
|
569
584
|
interacted = value;
|
|
570
585
|
};
|
|
571
586
|
const unwrap = (content, global = false) => {
|
|
572
|
-
const {
|
|
587
|
+
const {
|
|
588
|
+
data: data2,
|
|
589
|
+
meta: [lang]
|
|
590
|
+
} = $.get();
|
|
573
591
|
const obj = global ? data2 : state();
|
|
574
|
-
const
|
|
592
|
+
const cnt = isFunction(content) ? content(lang, obj) : typeof content === "string" ? content : content[lang];
|
|
593
|
+
const str2 = isFunction(cnt) ? cnt() : cnt;
|
|
575
594
|
return replaceT9N(str2, obj);
|
|
576
595
|
};
|
|
577
596
|
function data(value) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/store.ts","../src/novely.ts","../src/constants.ts","../src/storage.ts"],"sourcesContent":["import type { ActionProxyProvider, CustomHandler } from './action'\nimport type { Character } from './character'\nimport type { TypewriterSpeed, Thenable } from './types'\n\ntype MatchActionMap = {\n [Key in keyof ActionProxyProvider<Record<string, Character>>]: (data: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>) => void;\n}\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n custom: (value: [handler: CustomHandler]) => Thenable<void>;\n}\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n return (action: keyof MatchActionMap, props: any) => {\n return values[action](props);\n }\n}\n\nconst isNumber = (val: unknown): val is number => {\n return typeof val === 'number';\n}\n\nconst isNull = (val: unknown): val is null => {\n return val === null;\n}\n\nconst isString = (val: unknown): val is string => {\n return typeof val === 'string';\n}\n\nconst isFunction = (val: unknown): val is ((...parameters: any[]) => any) => {\n return typeof val === 'function';\n}\n\nconst isPromise = (val: unknown): val is Promise<any> => {\n return Boolean(val) && (typeof val === 'object' || isFunction(val)) && isFunction((val as any).then)\n}\n\nconst isEmpty = (val: unknown): val is {} => {\n return typeof val === 'object' && !isNull(val) && Object.keys(val).length === 0;\n}\n\nconst isCSSImage = (str: string) => {\n const startsWith = String.prototype.startsWith.bind(str);\n\n return startsWith('http') || startsWith('/') || startsWith('.') || startsWith('data');\n}\n\nconst str = (value: unknown) => {\n return String(value);\n}\n\nconst isUserRequiredAction = (action: keyof MatchActionMapComplete, meta: Parameters<MatchActionMapComplete[keyof MatchActionMapComplete]>) => {\n return action === 'custom' && meta[0] && (meta[0] as unknown as CustomHandler).requireUserAction;\n}\n\nconst getTypewriterSpeed = (): TypewriterSpeed => {\n return 'Medium'\n}\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n if (languages.includes(language)) {\n return language;\n } else if (languages.includes((language = language.substring(0, 2)))) {\n return language;\n } else if ((language = languages.find((value) => navigator.languages.includes(value))!)) {\n return language\n }\n\n /**\n * We'v checked the `en-GB` format, `en` format, and maybe any second languages, but there were no matches\n */\n return 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 let throttled = false, savedArgs: any, savedThis: any;\n\n function wrapper(this: any) {\n if (throttled) {\n savedArgs = arguments;\n savedThis = this;\n return;\n }\n\n fn.apply(this, arguments as unknown as any[]);\n\n throttled = true;\n\n setTimeout(function () {\n throttled = false;\n\n if (savedArgs) {\n wrapper.apply(savedThis, savedArgs);\n savedArgs = savedThis = null;\n }\n }, ms);\n }\n\n return wrapper as unknown as (...args: Parameters<Fn>) => void;\n}\n\nconst vibrate = (pattern: VibratePattern) => {\n try {\n if ('vibrate' in navigator) {\n navigator.vibrate(pattern);\n }\n } catch { }\n}\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n for (let i = array.length - 1; i > 0; i--) {\n if (fn(array[i])) {\n return i;\n }\n }\n\n return -1;\n}\n\nexport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, isCSSImage, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex }","type Stored<T> = {\n subscribe: (cb: (value: T) => void) => () => void;\n update: (fn: (prev: T) => T) => void;\n get: () => T;\n}\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n const subscribe = (cb: (value: T) => void) => {\n subscribers.add(cb), cb(current);\n\n return () => {\n subscribers.delete(cb);\n }\n };\n\n const push = (value: T) => {\n subscribers.forEach((cb) => cb(value))\n };\n\n const update = (fn: (prev: T) => T) => {\n push((current = fn(current)));\n };\n\n const get = () => {\n return current;\n };\n\n return { subscribe, update, get } as const;\n};\n\nexport { store }\nexport type { Stored }","import type { Character } from './character';\nimport type { ActionProxyProvider, GetActionParameters, Story, ValidAction, Unwrappable, CustomHandler } from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types'\nimport type { Renderer, RendererInit } from './renderer'\nimport type { SetupT9N } from '@novely/t9n'\nimport { matchAction, isNumber, isNull, isString, isPromise, isEmpty, str, isUserRequiredAction, getTypewriterSpeed, getLanguage, throttle, isFunction, vibrate, findLastIndex } from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge'\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, Inter extends ReturnType<SetupT9N<Languages>>, StateScheme extends State, DataScheme extends Data> {\n /**\n * An array of languages supported by the game.\n */\n languages: Languages[];\n /**\n * An object containing the characters in the game.\n */\n characters: Characters;\n /**\n * An object that provides access to the game's storage system.\n */\n storage: Storage;\n /**\n * Delay loading data until Promise is resolved\n */\n storageDelay?: Promise<void>;\n /**\n * A function that returns a Renderer object used to display the game's content\n */\n renderer: (characters: RendererInit) => Renderer;\n /**\n * An optional property that specifies the initial screen to display when the game starts\n */\n initialScreen?: NovelyScreen;\n /**\n * An object containing the translation functions used in the game\n */\n t9n: Inter;\n /**\n * Initial state value\n */\n state?: StateScheme;\n /**\n * Initial data value\n */\n data?: DataScheme;\n /**\n * Enable autosaves or disable\n * @default true\n */\n autosaves?: boolean;\n /**\n * Migration from old saves to newer\n */\n migrations?: Migration[]\n}\n\nconst novely = <\n Languages extends string,\n Characters extends Record<string, Character<Languages>>,\n Inter extends ReturnType<SetupT9N<Languages>>,\n StateScheme extends State,\n DataScheme extends Data\n>({\n characters,\n storage,\n storageDelay = Promise.resolve(),\n renderer: createRenderer,\n initialScreen = \"mainmenu\",\n t9n,\n languages,\n state: defaultState,\n data: defaultData,\n autosaves = true,\n migrations = []\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n let story: Story;\n let times = new Set<number>();\n\n /**\n * Prevent `undefined`\n */\n defaultData ||= {} as DataScheme;\n defaultState ||= {} as StateScheme;\n\n /**\n * Saves timestamps created in this session\n */\n const intime = (value: number) => {\n return times.add(value), value;\n }\n\n const withStory = (s: Story) => {\n /**\n * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n */\n story = Object.fromEntries(Object.entries(s).map(([name, items]) => {\n const flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n return item.flatMap((data) => {\n const type = data[0];\n\n /**\n * This is not just an action like `['name', ...arguments]`, but an array of actions\n */\n if (Array.isArray(type)) return flat(data as ValidAction[]);\n\n return [data as ValidAction];\n });\n };\n\n return [name, flat(items)];\n }));\n\n /**\n * When `initialScreen` is not a game, we can safely show it\n */\n if (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n }\n\n const action = new Proxy({} as ActionProxyProvider<Characters>, {\n get(_, prop) {\n return (...props: Parameters<ActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]>) => {\n return [prop, ...props];\n }\n }\n });\n\n function state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n function state(): StateScheme;\n function state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n if (!value) return stack.value[1] as StateScheme | void;\n\n const prev = stack.value[1];\n const val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n stack.value[1] = val as StateScheme;\n }\n\n const getDefaultSave = (state = {}) => {\n return [[[null, 'start'], [null, 0]], state, [intime(Date.now()), 'auto']] as Save;\n }\n\n const createStack = (current: Save, stack = [current]) => {\n return {\n get value() {\n return stack.at(-1)!;\n },\n set value(value: Save) {\n stack[stack.length - 1] = value;\n },\n back() {\n if (stack.length > 1) stack.pop(), goingBack = true;\n },\n push(value: Save) {\n stack.push(value);\n },\n clear() {\n stack = [getDefaultSave(klona(defaultState))];\n }\n }\n }\n\n /**\n * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n * 2) Actual stored data is loaded, language and etc is changed \n */\n const initialData: StorageData = {\n saves: [],\n data: klona(defaultData) as Data,\n meta: [getLanguage(languages), getTypewriterSpeed()],\n };\n\n const $ = store(initialData);\n\n let initialDataLoaded = false;\n\n const onStorageDataChange = (value: StorageData) => {\n if (initialDataLoaded) storage.set(value);\n };\n\n const throttledOnStorageDataChange = throttle(onStorageDataChange, 120);\n\n $.subscribe(throttledOnStorageDataChange);\n\n const getStoredData = () => {\n storage.get().then(stored => {\n /**\n * Migration is done only once (when game loads it's data), and then it saves the updated format\n */\n for (const migration of migrations) {\n // @ts-expect-error Types does not match between versions\n stored = migration(stored);\n }\n\n /**\n * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n */\n stored.meta[0] ||= getLanguage(languages);\n stored.meta[1] ||= getTypewriterSpeed();\n\n /**\n * When data is empty replace it with `defaultData`\n * It also might be empty (default to empty)\n */\n if (isEmpty(stored.data)) {\n stored.data = defaultData as Data;\n }\n\n /**\n * Now the next store updates will entail saving via storage.set\n */\n initialDataLoaded = true;\n\n $.update(() => stored);\n\n /**\n * When initialScreen is game, then we will load it, but after the data is loaded\n */\n if (initialScreen === 'game') restore();\n });\n }\n\n /**\n * By default this is resolved immediately, but also can be delayed.\n * I.e. storage has not loaded yet\n */\n storageDelay.then(getStoredData)\n\n const initial = getDefaultSave(klona(defaultState));\n const stack = createStack(initial);\n\n const save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n if (!initialDataLoaded) return;\n\n /**\n * When autosaves diabled just return\n */\n if (!autosaves && type === 'auto') return;\n\n const current = klona(stack.value);\n\n $.update(prev => {\n /**\n * Find latest save that were created in current session, and check if it is latest in an array\n * \n * We check if save was created in current session and it is latest in array\n * When it is not then replacing it will break logical chain\n * \n * [auto save 1]\n * [manual save 1]\n * [auto save 2] <- should not replace first auto save \n */\n const isLatest = findLastIndex(prev.saves, value => times.has(value[2][0])) === prev.saves.length - 1;\n\n /**\n * Update type and time information\n */\n current[2][0] = intime(Date.now());\n current[2][1] = type;\n\n if (!override || !isLatest) {\n prev.saves.push(current);\n\n return prev;\n }\n\n /**\n * Get latest\n */\n const latest = prev.saves.at(-1);\n\n /**\n * When that save is the same type, replace it\n */\n if (latest && latest[2][1] === type) {\n prev.saves[prev.saves.length - 1] = current;\n } else {\n prev.saves.push(current);\n }\n\n return prev;\n });\n }\n\n const newGame = () => {\n if (!initialDataLoaded) return;\n\n const save = getDefaultSave(klona(defaultState));\n\n /**\n * Initial save is automatic, and should be ignored when autosaves is turned off\n */\n if (autosaves) {\n $.update(prev => {\n return prev.saves.push(save), prev;\n });\n }\n\n restore(save);\n }\n\n /**\n * Set's the save\n */\n const set = (save: Save) => {\n stack.value = save;\n\n return restore(save);\n }\n\n let restoring = false;\n let goingBack = false;\n let interacted = false;\n\n /**\n * Restore\n */\n const restore = async (save?: Save) => {\n if (!initialDataLoaded) return;\n\n let latest = save ? save : $.get().saves.at(-1);\n\n /**\n * When there is no game, then make a new game\n */\n if (!latest) {\n $.update(() => ({ saves: [initial], data: klona(defaultData) as Data, meta: [getLanguage(languages), getTypewriterSpeed()] }));\n\n latest = klona(initial);\n }\n\n restoring = true, stack.value = latest;\n\n /**\n * Текущий элемент в истории\n */\n let current: any = story;\n /**\n * Текущий элемент `[null, int]`\n */\n let index = 0;\n\n /**\n * Число элементов `[null, int]`\n */\n const max = stack.value[0].reduce((acc, [type, val]) => {\n if (isNull(type) && isNumber(val)) return acc + 1;\n\n return acc;\n }, 0);\n\n const queue = [] as [any, any][];\n const keep = new Set();\n const characters = new Set();\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n if (isString(val)) {\n current = current[val];\n } else if (isNumber(val)) {\n index++;\n\n /**\n * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n */\n for (let i = 0; i <= val; i++) {\n const [action, ...meta] = current[i];\n\n /**\n * Add item to queue and action to keep\n */\n const push = () => {\n keep.add(action);\n queue.push([action, meta]);\n }\n\n /**\n * Do not remove characters that will be here anyways\n */\n if (action === 'showCharacter') characters.add(meta[0]);\n\n /**\n * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n */\n if (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n if (index === max && i === val) {\n push();\n } else {\n continue;\n }\n }\n\n push();\n }\n\n current = current[val];\n }\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n queue.forEach((value, index) => {\n /**\n * Mutate the queue item\n */\n value.push(index);\n });\n\n /**\n * This is basically made for TypeScript.\n */\n const indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n /**\n * Run these exactly before the main loop.\n */\n renderer.ui.showScreen('game');\n /**\n * Provide the `keep` in there\n */\n match('clear', [keep, characters]);\n\n /**\n * Get the next actions array.\n */\n const next = (i: number) => indexedQueue.slice(i + 1);\n\n for await (const [action, meta, i] of indexedQueue) {\n if (action === 'function' || action === 'custom') {\n /**\n * When `callOnlyLatest` is `true`\n */\n if (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n /**\n * We'll calculate it is `latest` or not\n */\n const notLatest = next(i).some(([_action, _meta]) => {\n if (!_meta || !meta) return false;\n\n const c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n const c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n /**\n * Also check for `undefined`\n */\n const isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n \n /**\n * Equal by id or equal by `toString()`\n */\n return isIdenticalID || (str(c0) === str(c1));\n });\n\n if (notLatest) continue;\n }\n\n /**\n * Action can return Promise. \n */\n const result = match(action, meta);\n\n /**\n * Should wait until it resolved\n */\n if (isPromise(result)) {\n /**\n * Await it!\n */\n await result;\n }\n } else if (action === 'showCharacter') {\n const skip = next(i).some(([_action, _meta]) => {\n /**\n * Проверка на возможный `undefined`\n */\n if (!_meta || !meta) return false;\n\n /**\n * Будет ли персонаж скрыт в будущем\n * Нет смысла при загрузке сохранения загружать и отрисовывать персонажа, который будет скрыт\n */\n const hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\n /**\n * Не нужно запускать рендер персонажа, если после этого будет ещё один рендер этого персонажа\n * Таким образом избегаем ситуации, когда при загрузке вследствие гонки при загрузки изображений отрисовывается не последняя эмоция\n */\n const notLatest = _action === action && _meta[0] === meta[0];\n\n return hidden || notLatest;\n })\n\n if (skip) continue;\n\n match(action, meta);\n } else if (action === 'showBackground' || action === 'animateCharacter') {\n /**\n * Такая же оптимизация применяется к фонам и анимированию персонажей.\n * Если фон изменится, то нет смысла устанавливать текущий\n */\n const notLatest = next(i).some(([_action]) => action === _action);\n\n if (notLatest) continue;\n\n match(action, meta);\n } else {\n match(action, meta);\n }\n }\n\n restoring = goingBack = false, render();\n }\n\n const refer = () => {\n let current: any = story;\n\n for (const [type, val] of stack.value[0]) {\n if (type === null) {\n current = current[val];\n } else if (type === 'choice') {\n current = current[val as number + 1][1];\n } else if (type === 'condition') {\n current = current[2][val];\n }\n }\n\n return current;\n }\n\n const exit = () => {\n const current = stack.value;\n\n stack.clear();\n renderer.ui.showScreen('mainmenu');\n\n /**\n * First two save elements and it's type\n */\n const [[first, second], , [time, type]] = current;\n\n if (type === 'auto' && first && second) {\n /**\n * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n */\n if (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n $.update((prev) => {\n prev.saves = prev.saves.filter(save => save !== current);\n\n return prev;\n })\n }\n }\n\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n }\n\n const back = () => {\n return stack.back(), restore(stack.value);\n }\n\n const renderer = createRenderer({\n characters,\n set,\n restore,\n save,\n newGame,\n exit,\n back,\n stack,\n languages,\n t: t9n.i,\n $\n });\n\n const match = matchAction({\n wait([time]) {\n if (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n },\n showBackground([background]) {\n renderer.background(background);\n push()\n },\n playMusic([source]) {\n renderer.music(source, 'music').play();\n push()\n },\n stopMusic([source]) {\n renderer.music(source, 'music').stop();\n push()\n },\n showCharacter([character, emotion, className, style]) {\n const handle = renderer.character(character);\n\n handle.append(className, style, restoring);\n handle.withEmotion(emotion)();\n\n push()\n },\n hideCharacter([character, className, style, duration]) {\n renderer.character(character).remove(className, style, duration)(push, restoring);\n },\n dialog([character, content, emotion]) {\n /**\n * Person name\n */\n const name = (() => {\n const c = character, cs = characters;\n const lang = $.get().meta[0];\n\n return c ? c in cs ? typeof cs[c].name === 'string' ? cs[c].name as string : (cs[c].name as Record<string, string>)[lang] : c : '';\n })();\n\n renderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n },\n function([fn]) {\n const result = fn(restoring, goingBack);\n\n if (!restoring) result ? result.then(push) : push();\n\n return result;\n },\n choice([question, ...choices]) {\n const isWithoutQuestion = Array.isArray(question);\n\n if (isWithoutQuestion) {\n /**\n * Первый элемент может быть как строкой, так и элементов выбора\n */\n choices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n /**\n * Значит, текст не требуется\n */\n question = '';\n }\n\n const unwrapped = choices.map(([content, action, visible]) => {\n return [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n });\n\n renderer.choices(unwrap(question), unwrapped)((selected) => {\n enmemory();\n\n /**\n * If there is a question, then `index` should be shifted by `1`\n */\n const offset = isWithoutQuestion ? 0 : 1;\n\n stack.value[0].push(['choice', selected + offset], [null, 0]);\n render();\n interactivity(true);\n });\n },\n jump([scene]) {\n /**\n * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n */\n stack.value[0] = [[null, scene], [null, -1]];\n\n match('clear', []);\n },\n clear([keep, characters]) {\n /**\n * Remove vibration\n */\n vibrate(0);\n /**\n * Call the actual `clear`\n */\n renderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n },\n condition([condition]) {\n const value = condition();\n\n if (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n },\n end() {\n /**\n * Clear the Scene\n */\n match('clear', []);\n /**\n * Go to the main menu\n */\n renderer.ui.showScreen('mainmenu');\n /**\n * Reset interactive value\n */\n interactivity(false);\n /**\n * Reset session times\n */\n times.clear();\n },\n input([question, onInput, setup]) {\n renderer.input(unwrap(question), onInput, setup)(forward);\n },\n custom([handler]) {\n const result = renderer.custom(handler, goingBack, () => {\n if (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n if (!restoring) push();\n });\n\n return result;\n },\n vibrate(pattern) {\n vibrate(pattern);\n push()\n },\n next() {\n push();\n },\n animateCharacter([character, timeout, ...classes]) {\n const handler: CustomHandler = (get) => {\n const { clear } = get('@@internal-animate-character', false);\n const char = renderer.store.characters[character];\n\n /**\n * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n */\n if (!char) return;\n\n const target = char.canvas;\n\n /**\n * Character is not found\n */\n if (!target) return;\n\n const classNames = classes.filter(className => !target.classList.contains(className));\n\n target.classList.add(...classNames);\n\n const timeoutId = setTimeout(() => {\n target.classList.remove(...classNames);\n }, timeout);\n\n clear(() => {\n target.classList.remove(...classNames);\n \n /**\n * Clear timeout, because when you will game re-runs some callback might remove classes from character\n */\n clearTimeout(timeoutId);\n });\n }\n\n /**\n * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n */\n match('custom', [handler]);\n },\n text(text) {\n renderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n },\n exit() {\n const path = stack.value[0];\n\n for (let i = path.length - 1; i > 0; i--) {\n if (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n stack.value[0] = path.slice(0, i);\n next();\n\n break;\n }\n\n render();\n }\n });\n\n const enmemory = () => {\n if (restoring) return;\n\n const current = klona(stack.value);\n\n current[2][1] = 'auto';\n\n stack.push(current);\n\n save(true, 'auto');\n }\n\n const next = () => {\n const path = stack.value[0];\n /**\n * Последний элемент пути\n */\n const last = path[path.length - 1]!;\n\n /**\n * Если он вида `[null, int]` - увеличивает `int`\n */\n if (isNull(last[0]) && isNumber(last[1])) {\n last[1] = last[1] + 1;\n return;\n }\n\n /**\n * Иначе добавляет новое `[null int]`\n */\n path.push([null, 0]);\n }\n\n const render = () => {\n const referred = refer();\n\n if (!Array.isArray(referred)) return;\n\n const [action, ...props] = referred;\n\n match(action, props);\n }\n\n const push = () => {\n if (!restoring) next(), render();\n }\n\n const forward = () => {\n enmemory();\n push();\n interactivity(true)\n }\n\n const interactivity = (value = false) => {\n interacted = value;\n }\n\n /**\n * Unwraps translatable content to string\n * \n * @example ```\n * unwrap(t('Hello'));\n * unwrap({ en: 'Hello', ru: 'Привет' });\n * unwrap('Hello, {{name}}');\n * ```\n */\n const unwrap = (content: Unwrappable, global = false) => {\n const { data, meta: [lang] } = $.get();\n\n const obj = global ? data : state();\n const str = isFunction(content)\n ? content(lang, obj)\n : typeof content === 'object'\n ? content[lang]\n : content;\n \n return replaceT9N(str, obj);\n }\n\n function data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n function data(): DataScheme;\n function data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n if (!value) return $.get().data as DataScheme | void;\n\n const prev = $.get().data;\n const val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n $.update((prev) => {\n prev.data = val;\n\n return prev;\n });\n }\n\n return {\n /**\n * Function to set story\n */\n withStory,\n /**\n * Function to get actions\n */\n action,\n /**\n * State that belongs to games\n */\n state,\n /**\n * Unlike `state`, stored at global scope instead and shared between games\n */\n data,\n /**\n * Unwraps translatable content to a string value\n */\n unwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n return unwrap(content, true);\n },\n /**\n * Function that is used for translation\n */\n t: t9n.t as Inter['t'],\n }\n}\n\nexport { novely }\n","const SKIPPED_DURING_RESTORE = new Set([\n 'dialog',\n 'choice',\n 'input',\n 'vibrate',\n 'text'\n] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET }","import type { StorageData } from './types'\n\ninterface LocalStorageStorageSettings {\n key: string\n}\n\ninterface Storage {\n get: () => Promise<StorageData>;\n set: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n return {\n async get() {\n const value = localStorage.getItem(options.key);\n\n return value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n },\n async set(data) {\n localStorage.setItem(options.key, JSON.stringify(data));\n }\n }\n}\n\nexport type { Storage }\nexport { localStorageStorage }"],"mappings":";AAYA,IAAM,cAAc,CAAmC,WAAc;AACnE,SAAO,CAAC,QAA8B,UAAe;AACnD,WAAO,OAAO,MAAM,EAAE,KAAK;AAAA,EAC7B;AACF;AAEA,IAAM,WAAW,CAAC,QAAgC;AAChD,SAAO,OAAO,QAAQ;AACxB;AAEA,IAAM,SAAS,CAAC,QAA8B;AAC5C,SAAO,QAAQ;AACjB;AAEA,IAAM,WAAW,CAAC,QAAgC;AAChD,SAAO,OAAO,QAAQ;AACxB;AAEA,IAAM,aAAa,CAAC,QAAyD;AAC3E,SAAO,OAAO,QAAQ;AACxB;AAEA,IAAM,YAAY,CAAC,QAAsC;AACvD,SAAO,QAAQ,GAAG,MAAM,OAAO,QAAQ,YAAY,WAAW,GAAG,MAAM,WAAY,IAAY,IAAI;AACrG;AAEA,IAAM,UAAU,CAAC,QAA4B;AAC3C,SAAO,OAAO,QAAQ,YAAY,CAAC,OAAO,GAAG,KAAK,OAAO,KAAK,GAAG,EAAE,WAAW;AAChF;AAQA,IAAM,MAAM,CAAC,UAAmB;AAC9B,SAAO,OAAO,KAAK;AACrB;AAEA,IAAM,uBAAuB,CAAC,QAAsC,SAA2E;AAC7I,SAAO,WAAW,YAAY,KAAK,CAAC,KAAM,KAAK,CAAC,EAA+B;AACjF;AAEA,IAAM,qBAAqB,MAAuB;AAChD,SAAO;AACT;AAEA,IAAM,cAAc,CAAC,WAAqB,WAAW,UAAU,aAAa;AAC1E,MAAI,UAAU,SAAS,QAAQ,GAAG;AAChC,WAAO;AAAA,EACT,WAAW,UAAU,SAAU,WAAW,SAAS,UAAU,GAAG,CAAC,CAAE,GAAG;AACpE,WAAO;AAAA,EACT,WAAY,WAAW,UAAU,KAAK,CAAC,UAAU,UAAU,UAAU,SAAS,KAAK,CAAC,GAAK;AACvF,WAAO;AAAA,EACT;AAKA,SAAO,UAAU,CAAC;AACpB;AAMA,IAAM,WAAW,CAAuC,IAAQ,OAAe;AAC7E,MAAI,YAAY,OAAO,WAAgB;AAEvC,WAAS,UAAmB;AAC1B,QAAI,WAAW;AACb,kBAAY;AACZ,kBAAY;AACZ;AAAA,IACF;AAEA,OAAG,MAAM,MAAM,SAA6B;AAE5C,gBAAY;AAEZ,eAAW,WAAY;AACrB,kBAAY;AAEZ,UAAI,WAAW;AACb,gBAAQ,MAAM,WAAW,SAAS;AAClC,oBAAY,YAAY;AAAA,MAC1B;AAAA,IACF,GAAG,EAAE;AAAA,EACP;AAEA,SAAO;AACT;AAEA,IAAM,UAAU,CAAC,YAA4B;AAC3C,MAAI;AACF,QAAI,aAAa,WAAW;AAC1B,gBAAU,QAAQ,OAAO;AAAA,IAC3B;AAAA,EACF,QAAE;AAAA,EAAQ;AACZ;AAEA,IAAM,gBAAgB,CAAI,OAAY,OAA6B;AACjE,WAAS,IAAI,MAAM,SAAS,GAAG,IAAI,GAAG,KAAK;AACzC,QAAI,GAAG,MAAM,CAAC,CAAC,GAAG;AAChB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;ACpHA,IAAM,QAAQ,CAAI,SAAY,cAAc,oBAAI,IAAwB,MAAiB;AACvF,QAAM,YAAY,CAAC,OAA2B;AAC5C,gBAAY,IAAI,EAAE,GAAG,GAAG,OAAO;AAE/B,WAAO,MAAM;AACX,kBAAY,OAAO,EAAE;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,OAAO,CAAC,UAAa;AACzB,gBAAY,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;AAAA,EACvC;AAEA,QAAM,SAAS,CAAC,OAAuB;AACrC,SAAM,UAAU,GAAG,OAAO,CAAE;AAAA,EAC9B;AAEA,QAAM,MAAM,MAAM;AAChB,WAAO;AAAA,EACT;AAEA,SAAO,EAAE,WAAW,QAAQ,IAAI;AAClC;;;ACpBA,SAAS,OAAO,iBAAiB;AACjC,SAAS,aAAa;;;ACTtB,IAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAU;AAEV,IAAM,YAAY,oBAAI,IAAS;;;ADG/B,SAAS,WAAW,kBAAkB;AAkDtC,IAAM,SAAS,CAMb;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe,QAAQ,QAAQ;AAAA,EAC/B,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,aAAa,CAAC;AAChB,MAAyE;AACvE,MAAI;AACJ,MAAI,QAAQ,oBAAI,IAAY;AAK5B,kBAAgB,CAAC;AACjB,mBAAiB,CAAC;AAKlB,QAAM,SAAS,CAAC,UAAkB;AAChC,WAAO,MAAM,IAAI,KAAK,GAAG;AAAA,EAC3B;AAEA,QAAM,YAAY,CAAC,MAAa;AAI9B,YAAQ,OAAO,YAAY,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AAClE,YAAM,OAAO,CAAC,SAAyD;AACrE,eAAO,KAAK,QAAQ,CAACA,UAAS;AAC5B,gBAAM,OAAOA,MAAK,CAAC;AAKnB,cAAI,MAAM,QAAQ,IAAI;AAAG,mBAAO,KAAKA,KAAqB;AAE1D,iBAAO,CAACA,KAAmB;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,aAAO,CAAC,MAAM,KAAK,KAAK,CAAC;AAAA,IAC3B,CAAC,CAAC;AAKF,QAAI,kBAAkB;AAAQ,eAAS,GAAG,WAAW,aAAa;AAAA,EACpE;AAEA,QAAM,SAAS,IAAI,MAAM,CAAC,GAAsC;AAAA,IAC9D,IAAI,GAAG,MAAM;AACX,aAAO,IAAI,UAA4H;AACrI,eAAO,CAAC,MAAM,GAAG,KAAK;AAAA,MACxB;AAAA,IACF;AAAA,EACF,CAAC;AAID,WAAS,MAAM,OAA6F;AAC1G,QAAI,CAAC;AAAO,aAAO,MAAM,MAAM,CAAC;AAEhC,UAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,UAAM,MAAM,WAAW,KAAK,IAAI,MAAM,IAAmB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;AAEpF,UAAM,MAAM,CAAC,IAAI;AAAA,EACnB;AAEA,QAAM,iBAAiB,CAACC,SAAQ,CAAC,MAAM;AACrC,WAAO,CAAC,CAAC,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,GAAGA,QAAO,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC;AAAA,EAC3E;AAEA,QAAM,cAAc,CAAC,SAAeC,SAAQ,CAAC,OAAO,MAAM;AACxD,WAAO;AAAA,MACL,IAAI,QAAQ;AACV,eAAOA,OAAM,GAAG,EAAE;AAAA,MACpB;AAAA,MACA,IAAI,MAAM,OAAa;AACrB,QAAAA,OAAMA,OAAM,SAAS,CAAC,IAAI;AAAA,MAC5B;AAAA,MACA,OAAO;AACL,YAAIA,OAAM,SAAS;AAAG,UAAAA,OAAM,IAAI,GAAG,YAAY;AAAA,MACjD;AAAA,MACA,KAAK,OAAa;AAChB,QAAAA,OAAM,KAAK,KAAK;AAAA,MAClB;AAAA,MACA,QAAQ;AACN,QAAAA,SAAQ,CAAC,eAAe,MAAM,YAAY,CAAC,CAAC;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAMA,QAAM,cAA2B;AAAA,IAC/B,OAAO,CAAC;AAAA,IACR,MAAM,MAAM,WAAW;AAAA,IACvB,MAAM,CAAC,YAAY,SAAS,GAAG,mBAAmB,CAAC;AAAA,EACrD;AAEA,QAAM,IAAI,MAAM,WAAW;AAE3B,MAAI,oBAAoB;AAExB,QAAM,sBAAsB,CAAC,UAAuB;AAClD,QAAI;AAAmB,cAAQ,IAAI,KAAK;AAAA,EAC1C;AAEA,QAAM,+BAA+B,SAAS,qBAAqB,GAAG;AAEtE,IAAE,UAAU,4BAA4B;AAExC,QAAM,gBAAgB,MAAM;AAC1B,YAAQ,IAAI,EAAE,KAAK,YAAU;AAI3B,iBAAW,aAAa,YAAY;AAElC,iBAAS,UAAU,MAAM;AAAA,MAC3B;AAKA,aAAO,KAAK,CAAC,MAAM,YAAY,SAAS;AACxC,aAAO,KAAK,CAAC,MAAM,mBAAmB;AAMtC,UAAI,QAAQ,OAAO,IAAI,GAAG;AACxB,eAAO,OAAO;AAAA,MAChB;AAKA,0BAAoB;AAEpB,QAAE,OAAO,MAAM,MAAM;AAKrB,UAAI,kBAAkB;AAAQ,gBAAQ;AAAA,IACxC,CAAC;AAAA,EACH;AAMA,eAAa,KAAK,aAAa;AAE/B,QAAM,UAAU,eAAe,MAAM,YAAY,CAAC;AAClD,QAAM,QAAQ,YAAY,OAAO;AAEjC,QAAM,OAAO,CAAC,WAAW,OAAO,OAAmB,WAAW,SAAS,aAAa;AAClF,QAAI,CAAC;AAAmB;AAKxB,QAAI,CAAC,aAAa,SAAS;AAAQ;AAEnC,UAAM,UAAU,MAAM,MAAM,KAAK;AAEjC,MAAE,OAAO,UAAQ;AAWf,YAAM,WAAW,cAAc,KAAK,OAAO,WAAS,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,SAAS;AAKpG,cAAQ,CAAC,EAAE,CAAC,IAAI,OAAO,KAAK,IAAI,CAAC;AACjC,cAAQ,CAAC,EAAE,CAAC,IAAI;AAEhB,UAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,aAAK,MAAM,KAAK,OAAO;AAEvB,eAAO;AAAA,MACT;AAKA,YAAM,SAAS,KAAK,MAAM,GAAG,EAAE;AAK/B,UAAI,UAAU,OAAO,CAAC,EAAE,CAAC,MAAM,MAAM;AACnC,aAAK,MAAM,KAAK,MAAM,SAAS,CAAC,IAAI;AAAA,MACtC,OAAO;AACL,aAAK,MAAM,KAAK,OAAO;AAAA,MACzB;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC;AAAmB;AAExB,UAAMC,QAAO,eAAe,MAAM,YAAY,CAAC;AAK/C,QAAI,WAAW;AACb,QAAE,OAAO,UAAQ;AACf,eAAO,KAAK,MAAM,KAAKA,KAAI,GAAG;AAAA,MAChC,CAAC;AAAA,IACH;AAEA,YAAQA,KAAI;AAAA,EACd;AAKA,QAAM,MAAM,CAACA,UAAe;AAC1B,UAAM,QAAQA;AAEd,WAAO,QAAQA,KAAI;AAAA,EACrB;AAEA,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,aAAa;AAKjB,QAAM,UAAU,OAAOA,UAAgB;AACrC,QAAI,CAAC;AAAmB;AAExB,QAAI,SAASA,QAAOA,QAAO,EAAE,IAAI,EAAE,MAAM,GAAG,EAAE;AAK9C,QAAI,CAAC,QAAQ;AACX,QAAE,OAAO,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,MAAM,MAAM,WAAW,GAAW,MAAM,CAAC,YAAY,SAAS,GAAG,mBAAmB,CAAC,EAAE,EAAE;AAE7H,eAAS,MAAM,OAAO;AAAA,IACxB;AAEA,gBAAY,MAAM,MAAM,QAAQ;AAKhC,QAAI,UAAe;AAInB,QAAI,QAAQ;AAKZ,UAAM,MAAM,MAAM,MAAM,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM;AACtD,UAAI,OAAO,IAAI,KAAK,SAAS,GAAG;AAAG,eAAO,MAAM;AAEhD,aAAO;AAAA,IACT,GAAG,CAAC;AAEJ,UAAM,QAAQ,CAAC;AACf,UAAM,OAAO,oBAAI,IAAI;AACrB,UAAMC,cAAa,oBAAI,IAAI;AAE3B,eAAW,CAAC,MAAM,GAAG,KAAK,MAAM,MAAM,CAAC,GAAG;AACxC,UAAI,SAAS,MAAM;AACjB,YAAI,SAAS,GAAG,GAAG;AACjB,oBAAU,QAAQ,GAAG;AAAA,QACvB,WAAW,SAAS,GAAG,GAAG;AACxB;AAMA,mBAAS,IAAI,GAAG,KAAK,KAAK,KAAK;AAC7B,kBAAM,CAACC,SAAQ,GAAG,IAAI,IAAI,QAAQ,CAAC;AAKnC,kBAAMC,QAAO,MAAM;AACjB,mBAAK,IAAID,OAAM;AACf,oBAAM,KAAK,CAACA,SAAQ,IAAI,CAAC;AAAA,YAC3B;AAKA,gBAAIA,YAAW;AAAiB,cAAAD,YAAW,IAAI,KAAK,CAAC,CAAC;AAMtD,gBAAI,uBAAuB,IAAIC,OAAM,KAAK,qBAAqBA,SAAQ,IAAI,GAAG;AAC5E,kBAAI,UAAU,OAAO,MAAM,KAAK;AAC9B,gBAAAC,MAAK;AAAA,cACP,OAAO;AACL;AAAA,cACF;AAAA,YACF;AAEA,YAAAA,MAAK;AAAA,UACP;AAEA,oBAAU,QAAQ,GAAG;AAAA,QACvB;AAAA,MACF,WAAW,SAAS,UAAU;AAC5B,kBAAU,QAAQ,MAAgB,CAAC,EAAE,CAAC;AAAA,MACxC,WAAW,SAAS,aAAa;AAC/B,kBAAU,QAAQ,CAAC,EAAE,GAAG;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,QAAQ,CAAC,OAAOC,WAAU;AAI9B,YAAM,KAAKA,MAAK;AAAA,IAClB,CAAC;AAKD,UAAM,eAAe;AAKrB,aAAS,GAAG,WAAW,MAAM;AAI7B,UAAM,SAAS,CAAC,MAAMH,WAAU,CAAC;AAKjC,UAAMI,QAAO,CAAC,MAAc,aAAa,MAAM,IAAI,CAAC;AAEpD,qBAAiB,CAACH,SAAQ,MAAM,CAAC,KAAK,cAAc;AAClD,UAAIA,YAAW,cAAcA,YAAW,UAAU;AAIhD,YAAIA,YAAW,YAAa,KAAuC,CAAC,EAAE,gBAAgB;AAIpF,gBAAM,YAAYG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,KAAK,MAAM;AACnD,gBAAI,CAAC,SAAS,CAAC;AAAM,qBAAO;AAE5B,kBAAM,KAAK,MAAM,CAAC;AAClB,kBAAM,KAAM,KAAK,CAAC;AAKlB,kBAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG;AAKrD,mBAAO,iBAAkB,IAAI,EAAE,MAAM,IAAI,EAAE;AAAA,UAC7C,CAAC;AAED,cAAI;AAAW;AAAA,QACjB;AAKA,cAAM,SAAS,MAAMH,SAAQ,IAAI;AAKjC,YAAI,UAAU,MAAM,GAAG;AAIrB,gBAAM;AAAA,QACR;AAAA,MACF,WAAWA,YAAW,iBAAiB;AACrC,cAAM,OAAOG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,KAAK,MAAM;AAI9C,cAAI,CAAC,SAAS,CAAC;AAAM,mBAAO;AAM5B,gBAAM,SAAS,YAAY,mBAAmB,MAAM,CAAC,MAAM,KAAK,CAAC;AAKjE,gBAAM,YAAY,YAAYH,WAAU,MAAM,CAAC,MAAM,KAAK,CAAC;AAE3D,iBAAO,UAAU;AAAA,QACnB,CAAC;AAED,YAAI;AAAM;AAEV,cAAMA,SAAQ,IAAI;AAAA,MACpB,WAAWA,YAAW,oBAAoBA,YAAW,oBAAoB;AAKvE,cAAM,YAAYG,MAAK,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,MAAMH,YAAW,OAAO;AAEhE,YAAI;AAAW;AAEf,cAAMA,SAAQ,IAAI;AAAA,MACpB,OAAO;AACL,cAAMA,SAAQ,IAAI;AAAA,MACpB;AAAA,IACF;AAEA,gBAAY,YAAY,OAAO,OAAO;AAAA,EACxC;AAEA,QAAM,QAAQ,MAAM;AAClB,QAAI,UAAe;AAEnB,eAAW,CAAC,MAAM,GAAG,KAAK,MAAM,MAAM,CAAC,GAAG;AACxC,UAAI,SAAS,MAAM;AACjB,kBAAU,QAAQ,GAAG;AAAA,MACvB,WAAW,SAAS,UAAU;AAC5B,kBAAU,QAAQ,MAAgB,CAAC,EAAE,CAAC;AAAA,MACxC,WAAW,SAAS,aAAa;AAC/B,kBAAU,QAAQ,CAAC,EAAE,GAAG;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,MAAM;AACjB,UAAM,UAAU,MAAM;AAEtB,UAAM,MAAM;AACZ,aAAS,GAAG,WAAW,UAAU;AAKjC,UAAM,CAAC,CAAC,OAAO,MAAM,GAAG,EAAE,CAAC,MAAM,IAAI,CAAC,IAAI;AAE1C,QAAI,SAAS,UAAU,SAAS,QAAQ;AAItC,UAAI,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,WAAW,OAAO,CAAC,MAAM,QAAQ,CAAC,cAAc,MAAM,IAAI,IAAI,GAAG;AACrG,UAAE,OAAO,CAAC,SAAS;AACjB,eAAK,QAAQ,KAAK,MAAM,OAAO,CAAAF,UAAQA,UAAS,OAAO;AAEvD,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAKA,kBAAc,KAAK;AAInB,UAAM,MAAM;AAAA,EACd;AAEA,QAAM,OAAO,MAAM;AACjB,WAAO,MAAM,KAAK,GAAG,QAAQ,MAAM,KAAK;AAAA,EAC1C;AAEA,QAAM,WAAW,eAAe;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,IAAI;AAAA,IACP;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,YAAY;AAAA,IACxB,KAAK,CAAC,IAAI,GAAG;AACX,UAAI,CAAC;AAAW,mBAAW,MAAM,WAAW,IAAI,IAAI,KAAK,IAAI,IAAI;AAAA,IACnE;AAAA,IACA,eAAe,CAAC,UAAU,GAAG;AAC3B,eAAS,WAAW,UAAU;AAC9B,WAAK;AAAA,IACP;AAAA,IACA,UAAU,CAAC,MAAM,GAAG;AAClB,eAAS,MAAM,QAAQ,OAAO,EAAE,KAAK;AACrC,WAAK;AAAA,IACP;AAAA,IACA,UAAU,CAAC,MAAM,GAAG;AAClB,eAAS,MAAM,QAAQ,OAAO,EAAE,KAAK;AACrC,WAAK;AAAA,IACP;AAAA,IACA,cAAc,CAAC,WAAW,SAAS,WAAW,KAAK,GAAG;AACpD,YAAM,SAAS,SAAS,UAAU,SAAS;AAE3C,aAAO,OAAO,WAAW,OAAO,SAAS;AACzC,aAAO,YAAY,OAAO,EAAE;AAE5B,WAAK;AAAA,IACP;AAAA,IACA,cAAc,CAAC,WAAW,WAAW,OAAO,QAAQ,GAAG;AACrD,eAAS,UAAU,SAAS,EAAE,OAAO,WAAW,OAAO,QAAQ,EAAE,MAAM,SAAS;AAAA,IAClF;AAAA,IACA,OAAO,CAAC,WAAW,SAAS,OAAO,GAAG;AAIpC,YAAM,QAAQ,MAAM;AAClB,cAAM,IAAI,WAAW,KAAK;AAC1B,cAAM,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;AAE3B,eAAO,IAAI,KAAK,KAAK,OAAO,GAAG,CAAC,EAAE,SAAS,WAAW,GAAG,CAAC,EAAE,OAAkB,GAAG,CAAC,EAAE,KAAgC,IAAI,IAAI,IAAI;AAAA,MAClI,GAAG;AAEH,eAAS,OAAO,OAAO,OAAO,GAAG,OAAO,IAAI,GAAG,WAAW,OAAO,EAAE,OAAO;AAAA,IAC5E;AAAA,IACA,SAAS,CAAC,EAAE,GAAG;AACb,YAAM,SAAS,GAAG,WAAW,SAAS;AAEtC,UAAI,CAAC;AAAW,iBAAS,OAAO,KAAK,IAAI,IAAI,KAAK;AAElD,aAAO;AAAA,IACT;AAAA,IACA,OAAO,CAAC,UAAU,GAAG,OAAO,GAAG;AAC7B,YAAM,oBAAoB,MAAM,QAAQ,QAAQ;AAEhD,UAAI,mBAAmB;AAIrB,gBAAQ,QAAQ,QAAkE;AAIlF,mBAAW;AAAA,MACb;AAEA,YAAM,YAAY,QAAQ,IAAI,CAAC,CAAC,SAASE,SAAQ,OAAO,MAAM;AAC5D,eAAO,CAAC,OAAO,OAAO,GAAGA,SAAQ,OAAO;AAAA,MAC1C,CAAC;AAED,eAAS,QAAQ,OAAO,QAAQ,GAAG,SAAS,EAAE,CAAC,aAAa;AAC1D,iBAAS;AAKT,cAAM,SAAS,oBAAoB,IAAI;AAEvC,cAAM,MAAM,CAAC,EAAE,KAAK,CAAC,UAAU,WAAW,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5D,eAAO;AACP,sBAAc,IAAI;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IACA,KAAK,CAAC,KAAK,GAAG;AAIZ,YAAM,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;AAE3C,YAAM,SAAS,CAAC,CAAC;AAAA,IACnB;AAAA,IACA,MAAM,CAAC,MAAMD,WAAU,GAAG;AAIxB,cAAQ,CAAC;AAIT,eAAS,MAAM,WAAW,QAAQ,WAAWA,eAAc,SAAS,EAAE,IAAI;AAAA,IAC5E;AAAA,IACA,UAAU,CAAC,SAAS,GAAG;AACrB,YAAM,QAAQ,UAAU;AAExB,UAAI,CAAC;AAAW,cAAM,MAAM,CAAC,EAAE,KAAK,CAAC,aAAa,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO;AAAA,IACvF;AAAA,IACA,MAAM;AAIJ,YAAM,SAAS,CAAC,CAAC;AAIjB,eAAS,GAAG,WAAW,UAAU;AAIjC,oBAAc,KAAK;AAInB,YAAM,MAAM;AAAA,IACd;AAAA,IACA,MAAM,CAAC,UAAU,SAAS,KAAK,GAAG;AAChC,eAAS,MAAM,OAAO,QAAQ,GAAG,SAAS,KAAK,EAAE,OAAO;AAAA,IAC1D;AAAA,IACA,OAAO,CAAC,OAAO,GAAG;AAChB,YAAM,SAAS,SAAS,OAAO,SAAS,WAAW,MAAM;AACvD,YAAI,CAAC,aAAa,QAAQ;AAAmB,mBAAS,GAAG,cAAc,IAAI;AAC3E,YAAI,CAAC;AAAW,eAAK;AAAA,MACvB,CAAC;AAED,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,SAAS;AACf,cAAQ,OAAO;AACf,WAAK;AAAA,IACP;AAAA,IACA,OAAO;AACL,WAAK;AAAA,IACP;AAAA,IACA,iBAAiB,CAAC,WAAW,SAAS,GAAG,OAAO,GAAG;AACjD,YAAM,UAAyB,CAAC,QAAQ;AACtC,cAAM,EAAE,MAAM,IAAI,IAAI,gCAAgC,KAAK;AAC3D,cAAM,OAAO,SAAS,MAAM,WAAW,SAAS;AAKhD,YAAI,CAAC;AAAM;AAEX,cAAM,SAAS,KAAK;AAKpB,YAAI,CAAC;AAAQ;AAEb,cAAM,aAAa,QAAQ,OAAO,eAAa,CAAC,OAAO,UAAU,SAAS,SAAS,CAAC;AAEpF,eAAO,UAAU,IAAI,GAAG,UAAU;AAElC,cAAM,YAAY,WAAW,MAAM;AACjC,iBAAO,UAAU,OAAO,GAAG,UAAU;AAAA,QACvC,GAAG,OAAO;AAEV,cAAM,MAAM;AACV,iBAAO,UAAU,OAAO,GAAG,UAAU;AAKrC,uBAAa,SAAS;AAAA,QACxB,CAAC;AAAA,MACH;AAKA,YAAM,UAAU,CAAC,OAAO,CAAC;AAAA,IAC3B;AAAA,IACA,KAAK,MAAM;AACT,eAAS,KAAK,KAAK,IAAI,CAAC,YAAY,OAAO,OAAO,CAAC,EAAE,KAAK,GAAG,GAAG,OAAO;AAAA,IACzE;AAAA,IACA,OAAO;AACL,YAAM,OAAO,MAAM,MAAM,CAAC;AAE1B,eAAS,IAAI,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK;AACxC,YAAI,KAAK,CAAC,EAAE,CAAC,MAAM,YAAY,KAAK,CAAC,EAAE,CAAC,MAAM;AAAa;AAE3D,cAAM,MAAM,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC;AAChC,aAAK;AAEL;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,QAAM,WAAW,MAAM;AACrB,QAAI;AAAW;AAEf,UAAM,UAAU,MAAM,MAAM,KAAK;AAEjC,YAAQ,CAAC,EAAE,CAAC,IAAI;AAEhB,UAAM,KAAK,OAAO;AAElB,SAAK,MAAM,MAAM;AAAA,EACnB;AAEA,QAAM,OAAO,MAAM;AACjB,UAAM,OAAO,MAAM,MAAM,CAAC;AAI1B,UAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AAKjC,QAAI,OAAO,KAAK,CAAC,CAAC,KAAK,SAAS,KAAK,CAAC,CAAC,GAAG;AACxC,WAAK,CAAC,IAAI,KAAK,CAAC,IAAI;AACpB;AAAA,IACF;AAKA,SAAK,KAAK,CAAC,MAAM,CAAC,CAAC;AAAA,EACrB;AAEA,QAAM,SAAS,MAAM;AACnB,UAAM,WAAW,MAAM;AAEvB,QAAI,CAAC,MAAM,QAAQ,QAAQ;AAAG;AAE9B,UAAM,CAACC,SAAQ,GAAG,KAAK,IAAI;AAE3B,UAAMA,SAAQ,KAAK;AAAA,EACrB;AAEA,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC;AAAW,WAAK,GAAG,OAAO;AAAA,EACjC;AAEA,QAAM,UAAU,MAAM;AACpB,aAAS;AACT,SAAK;AACL,kBAAc,IAAI;AAAA,EACpB;AAEA,QAAM,gBAAgB,CAAC,QAAQ,UAAU;AACvC,iBAAa;AAAA,EACf;AAWA,QAAM,SAAS,CAAC,SAAsB,SAAS,UAAU;AACvD,UAAM,EAAE,MAAAL,OAAM,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI;AAErC,UAAM,MAAM,SAASA,QAAO,MAAM;AAClC,UAAMS,OAAM,WAAW,OAAO,IAC1B,QAAQ,MAAM,GAAG,IACjB,OAAO,YAAY,WACjB,QAAQ,IAAI,IACZ;AAEN,WAAO,WAAWA,MAAK,GAAG;AAAA,EAC5B;AAIA,WAAS,KAAK,OAAyF;AACrG,QAAI,CAAC;AAAO,aAAO,EAAE,IAAI,EAAE;AAE3B,UAAM,OAAO,EAAE,IAAI,EAAE;AACrB,UAAM,MAAM,WAAW,KAAK,IAAI,MAAM,IAAkB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;AAEnF,MAAE,OAAO,CAACC,UAAS;AACjB,MAAAA,MAAK,OAAO;AAEZ,aAAOA;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA;AAAA;AAAA;AAAA,IAIA,OAAO,SAAmF;AACxF,aAAO,OAAO,SAAS,IAAI;AAAA,IAC7B;AAAA;AAAA;AAAA;AAAA,IAIA,GAAG,IAAI;AAAA,EACT;AACF;;;AEh4BA,IAAM,sBAAsB,CAAC,YAAkD;AAC7E,SAAO;AAAA,IACL,MAAM,MAAM;AACV,YAAM,QAAQ,aAAa,QAAQ,QAAQ,GAAG;AAE9C,aAAO,QAAQ,KAAK,MAAM,KAAK,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE;AAAA,IACrE;AAAA,IACA,MAAM,IAAI,MAAM;AACd,mBAAa,QAAQ,QAAQ,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,IACxD;AAAA,EACF;AACF;","names":["data","state","stack","save","characters","action","push","index","next","str","prev"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/store.ts","../src/novely.ts","../src/constants.ts","../src/storage.ts"],"sourcesContent":["import type { ActionProxyProvider, CustomHandler } from './action';\nimport type { Character } from './character';\nimport type { TypewriterSpeed, Thenable } from './types';\n\ntype MatchActionMap = {\n\t[Key in keyof ActionProxyProvider<Record<string, Character>>]: (\n\t\tdata: Parameters<ActionProxyProvider<Record<string, Character>>[Key]>,\n\t) => void;\n};\n\ntype MatchActionMapComplete = Omit<MatchActionMap, 'custom'> & {\n\tcustom: (value: [handler: CustomHandler]) => Thenable<void>;\n};\n\nconst matchAction = <M extends MatchActionMapComplete>(values: M) => {\n\treturn (action: keyof MatchActionMap, props: any) => {\n\t\treturn values[action](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 {} => {\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 = (value: unknown) => {\n\treturn String(value);\n};\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 getTypewriterSpeed = (): TypewriterSpeed => {\n\treturn 'Medium';\n};\n\nconst getLanguage = (languages: string[], language = navigator.language) => {\n\tif (languages.includes(language)) {\n\t\treturn language;\n\t} else if (languages.includes((language = language.substring(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) {\n\t\tif (throttled) {\n\t\t\tsavedArgs = arguments;\n\t\t\tsavedThis = this;\n\t\t\treturn;\n\t\t}\n\n\t\tfn.apply(this, arguments 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 vibrate = (pattern: VibratePattern) => {\n\ttry {\n\t\tif ('vibrate' in navigator) {\n\t\t\tnavigator.vibrate(pattern);\n\t\t}\n\t} catch {}\n};\n\nconst findLastIndex = <T>(array: T[], fn: (item: T) => boolean) => {\n\tfor (let i = array.length - 1; i > 0; i--) {\n\t\tif (fn(array[i])) {\n\t\t\treturn i;\n\t\t}\n\t}\n\n\treturn -1;\n};\n\nexport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tisCSSImage,\n\tstr,\n\tisUserRequiredAction,\n\tgetTypewriterSpeed,\n\tgetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n};\n","type Stored<T> = {\n\tsubscribe: (cb: (value: T) => void) => () => void;\n\tupdate: (fn: (prev: T) => T) => void;\n\tget: () => T;\n};\n\nconst store = <T>(current: T, subscribers = new Set<(value: T) => void>()): Stored<T> => {\n\tconst subscribe = (cb: (value: T) => void) => {\n\t\tsubscribers.add(cb), cb(current);\n\n\t\treturn () => {\n\t\t\tsubscribers.delete(cb);\n\t\t};\n\t};\n\n\tconst push = (value: T) => {\n\t\tsubscribers.forEach((cb) => cb(value));\n\t};\n\n\tconst update = (fn: (prev: T) => T) => {\n\t\tpush((current = fn(current)));\n\t};\n\n\tconst get = () => {\n\t\treturn current;\n\t};\n\n\treturn { subscribe, update, get } as const;\n};\n\nexport { store };\nexport type { Stored };\n","import type { Character } from './character';\nimport type {\n\tActionProxyProvider,\n\tGetActionParameters,\n\tStory,\n\tValidAction,\n\tUnwrappable,\n\tCustomHandler,\n} from './action';\nimport type { Storage } from './storage';\nimport type { Save, State, Data, StorageData, DeepPartial, NovelyScreen, Migration } from './types';\nimport type { Renderer, RendererInit } from './renderer';\nimport type { SetupT9N } from '@novely/t9n';\nimport {\n\tmatchAction,\n\tisNumber,\n\tisNull,\n\tisString,\n\tisPromise,\n\tisEmpty,\n\tstr,\n\tisUserRequiredAction,\n\tgetTypewriterSpeed,\n\tgetLanguage as defaultGetLanguage,\n\tthrottle,\n\tisFunction,\n\tvibrate,\n\tfindLastIndex,\n} from './utils';\nimport { store } from './store';\nimport { all as deepmerge } from 'deepmerge';\nimport { klona } from 'klona/json';\nimport { SKIPPED_DURING_RESTORE, EMPTY_SET } from './constants';\nimport { replace as replaceT9N } from '@novely/t9n';\n\ninterface NovelyInit<\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n> {\n\t/**\n\t * An array of languages supported by the game.\n\t */\n\tlanguages: Languages[];\n\t/**\n\t * An object containing the characters in the game.\n\t */\n\tcharacters: Characters;\n\t/**\n\t * An object that provides access to the game's storage system.\n\t */\n\tstorage: Storage;\n\t/**\n\t * Delay loading data until Promise is resolved\n\t */\n\tstorageDelay?: Promise<void>;\n\t/**\n\t * A function that returns a Renderer object used to display the game's content\n\t */\n\trenderer: (characters: RendererInit) => Renderer;\n\t/**\n\t * An optional property that specifies the initial screen to display when the game starts\n\t */\n\tinitialScreen?: NovelyScreen;\n\t/**\n\t * An object containing the translation functions used in the game\n\t */\n\tt9n: Inter;\n\t/**\n\t * Initial state value\n\t */\n\tstate?: StateScheme;\n\t/**\n\t * Initial data value\n\t */\n\tdata?: DataScheme;\n\t/**\n\t * Enable autosaves or disable\n\t * @default true\n\t */\n\tautosaves?: boolean;\n\t/**\n\t * Migration from old saves to newer\n\t */\n\tmigrations?: Migration[];\n\t/**\n\t * For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage\n\t * @default 799\n\t */\n\tthrottleTimeout?: number;\n\t/**\n\t * Custom language detector\n\t * @param languages Supported languages aka `languages: []` in the config\n\t * @example ```ts\n\t * novely({\n\t * \t\tgetLanguage(languages) {\n\t * \t\t\t\treturn sdk.environment.i18n.lang // i.e. custom language from some sdk\n\t * \t\t}\n\t * })\n\t * ```\n\t */\n\tgetLanguage?: (languages: string[]) => string;\n}\n\nconst novely = <\n\tLanguages extends string,\n\tCharacters extends Record<string, Character<Languages>>,\n\tInter extends ReturnType<SetupT9N<Languages>>,\n\tStateScheme extends State,\n\tDataScheme extends Data,\n>({\n\tcharacters,\n\tstorage,\n\tstorageDelay = Promise.resolve(),\n\trenderer: createRenderer,\n\tinitialScreen = 'mainmenu',\n\tt9n,\n\tlanguages,\n\tstate: defaultState,\n\tdata: defaultData,\n\tautosaves = true,\n\tmigrations = [],\n\tthrottleTimeout = 799,\n\tgetLanguage = defaultGetLanguage\n}: NovelyInit<Languages, Characters, Inter, StateScheme, DataScheme>) => {\n\tlet story: Story;\n\tlet times = new Set<number>();\n\n\t/**\n\t * Prevent `undefined`\n\t */\n\tdefaultData ||= {} as DataScheme;\n\tdefaultState ||= {} as StateScheme;\n\n\t/**\n\t * Saves timestamps created in this session\n\t */\n\tconst intime = (value: number) => {\n\t\treturn times.add(value), value;\n\t};\n\n\tconst withStory = (s: Story) => {\n\t\t/**\n\t\t * Transforms `(ValidAction | ValidAction[])[]` to `ValidAction[]`\n\t\t */\n\t\tstory = Object.fromEntries(\n\t\t\tObject.entries(s).map(([name, items]) => {\n\t\t\t\tconst flat = (item: (ValidAction | ValidAction[])[]): ValidAction[] => {\n\t\t\t\t\treturn item.flatMap((data) => {\n\t\t\t\t\t\tconst type = data[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * This is not just an action like `['name', ...arguments]`, but an array of actions\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (Array.isArray(type)) return flat(data as ValidAction[]);\n\n\t\t\t\t\t\treturn [data as ValidAction];\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\treturn [name, flat(items)];\n\t\t\t}),\n\t\t);\n\n\t\t/**\n\t\t * When `initialScreen` is not a game, we can safely show it\n\t\t */\n\t\tif (initialScreen !== 'game') renderer.ui.showScreen(initialScreen);\n\t};\n\n\tconst action = new Proxy({} as ActionProxyProvider<Characters>, {\n\t\tget(_, prop) {\n\t\t\treturn (\n\t\t\t\t...props: Parameters<\n\t\t\t\t\tActionProxyProvider<Record<string, Character>>[keyof ActionProxyProvider<Record<string, Character>>]\n\t\t\t\t>\n\t\t\t) => {\n\t\t\t\treturn [prop, ...props];\n\t\t\t};\n\t\t},\n\t});\n\n\tfunction state(value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;\n\tfunction state(): StateScheme;\n\tfunction state(value?: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): StateScheme | void {\n\t\tif (!value) return stack.value[1] as StateScheme | void;\n\n\t\tconst prev = stack.value[1];\n\t\tconst val = isFunction(value) ? value(prev as StateScheme) : deepmerge([prev, value]);\n\n\t\tstack.value[1] = val as StateScheme;\n\t}\n\n\tconst getDefaultSave = (state = {}) => {\n\t\treturn [\n\t\t\t[\n\t\t\t\t[null, 'start'],\n\t\t\t\t[null, 0],\n\t\t\t],\n\t\t\tstate,\n\t\t\t[intime(Date.now()), 'auto'],\n\t\t] as Save;\n\t};\n\n\tconst createStack = (current: Save, stack = [current]) => {\n\t\treturn {\n\t\t\tget value() {\n\t\t\t\treturn stack.at(-1)!;\n\t\t\t},\n\t\t\tset value(value: Save) {\n\t\t\t\tstack[stack.length - 1] = value;\n\t\t\t},\n\t\t\tback() {\n\t\t\t\tif (stack.length > 1) stack.pop(), (goingBack = true);\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 = [getDefaultSave(klona(defaultState))];\n\t\t\t},\n\t\t};\n\t};\n\n\t/**\n\t * 1) Novely rendered using the `initialData`, but you can't start new game or `load` an empty one - this is scary, imagine losing your progress\n\t * 2) Actual stored data is loaded, language and etc is changed\n\t */\n\tconst initialData: StorageData = {\n\t\tsaves: [],\n\t\tdata: klona(defaultData) as Data,\n\t\tmeta: [getLanguage(languages), getTypewriterSpeed()],\n\t};\n\n\tconst $ = store(initialData);\n\n\tlet initialDataLoaded = false;\n\n\tconst onStorageDataChange = (value: StorageData) => {\n\t\tif (initialDataLoaded) storage.set(value);\n\t};\n\n\tconst throttledOnStorageDataChange = throttle(onStorageDataChange, throttleTimeout);\n\n\t$.subscribe(throttledOnStorageDataChange);\n\n\tconst getStoredData = () => {\n\t\tstorage.get().then((stored) => {\n\t\t\t/**\n\t\t\t * Migration is done only once (when game loads it's data), and then it saves the updated format\n\t\t\t */\n\t\t\tfor (const migration of migrations) {\n\t\t\t\t// @ts-expect-error Types does not match between versions\n\t\t\t\tstored = migration(stored);\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Default `localStorageStorage` cannot determine preferred language, and returns empty array\n\t\t\t */\n\t\t\tstored.meta[0] ||= getLanguage(languages);\n\t\t\tstored.meta[1] ||= getTypewriterSpeed();\n\n\t\t\t/**\n\t\t\t * When data is empty replace it with `defaultData`\n\t\t\t * It also might be empty (default to empty)\n\t\t\t */\n\t\t\tif (isEmpty(stored.data)) {\n\t\t\t\tstored.data = defaultData as Data;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Now the next store updates will entail saving via storage.set\n\t\t\t */\n\t\t\tinitialDataLoaded = true;\n\n\t\t\t$.update(() => stored);\n\n\t\t\t/**\n\t\t\t * When initialScreen is game, then we will load it, but after the data is loaded\n\t\t\t */\n\t\t\tif (initialScreen === 'game') restore();\n\t\t});\n\t};\n\n\t/**\n\t * By default this is resolved immediately, but also can be delayed.\n\t * I.e. storage has not loaded yet\n\t */\n\tstorageDelay.then(getStoredData);\n\n\tconst initial = getDefaultSave(klona(defaultState));\n\tconst stack = createStack(initial);\n\n\tconst save = (override = false, type: Save[2][1] = override ? 'auto' : 'manual') => {\n\t\tif (!initialDataLoaded) return;\n\n\t\t/**\n\t\t * When autosaves diabled just return\n\t\t */\n\t\tif (!autosaves && type === 'auto') return;\n\n\t\tconst current = klona(stack.value);\n\n\t\t$.update((prev) => {\n\t\t\t/**\n\t\t\t * Find latest save that were created in current session, and check if it is latest in an array\n\t\t\t *\n\t\t\t * We check if save was created in current session and it is latest in array\n\t\t\t * When it is not then replacing it will break logical chain\n\t\t\t *\n\t\t\t * [auto save 1]\n\t\t\t * [manual save 1]\n\t\t\t * [auto save 2] <- should not replace first auto save\n\t\t\t */\n\t\t\tconst isLatest = findLastIndex(prev.saves, (value) => times.has(value[2][0])) === prev.saves.length - 1;\n\n\t\t\t/**\n\t\t\t * Update type and time information\n\t\t\t */\n\t\t\tcurrent[2][0] = intime(Date.now());\n\t\t\tcurrent[2][1] = type;\n\n\t\t\tif (!override || !isLatest) {\n\t\t\t\tprev.saves.push(current);\n\n\t\t\t\treturn prev;\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Get latest\n\t\t\t */\n\t\t\tconst latest = prev.saves.at(-1);\n\n\t\t\t/**\n\t\t\t * When that save is the same type, replace it\n\t\t\t */\n\t\t\tif (latest && latest[2][1] === type) {\n\t\t\t\tprev.saves[prev.saves.length - 1] = current;\n\t\t\t} else {\n\t\t\t\tprev.saves.push(current);\n\t\t\t}\n\n\t\t\treturn prev;\n\t\t});\n\t};\n\n\tconst newGame = () => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tconst save = getDefaultSave(klona(defaultState));\n\n\t\t/**\n\t\t * Initial save is automatic, and should be ignored when autosaves is turned off\n\t\t */\n\t\tif (autosaves) {\n\t\t\t$.update((prev) => {\n\t\t\t\treturn prev.saves.push(save), prev;\n\t\t\t});\n\t\t}\n\n\t\trestore(save);\n\t};\n\n\t/**\n\t * Set's the save\n\t */\n\tconst set = (save: Save) => {\n\t\tstack.value = save;\n\n\t\treturn restore(save);\n\t};\n\n\tlet restoring = false;\n\tlet goingBack = false;\n\tlet interacted = false;\n\n\t/**\n\t * Restore\n\t */\n\tconst restore = async (save?: Save) => {\n\t\tif (!initialDataLoaded) return;\n\n\t\tlet latest = save ? save : $.get().saves.at(-1);\n\n\t\t/**\n\t\t * When there is no game, then make a new game\n\t\t */\n\t\tif (!latest) {\n\t\t\t$.update(() => ({\n\t\t\t\tsaves: [initial],\n\t\t\t\tdata: klona(defaultData) as Data,\n\t\t\t\tmeta: [getLanguage(languages), getTypewriterSpeed()],\n\t\t\t}));\n\n\t\t\tlatest = klona(initial);\n\t\t}\n\n\t\t(restoring = true), (stack.value = latest);\n\n\t\t/**\n\t\t * Текущий элемент в истории\n\t\t */\n\t\tlet current: any = story;\n\t\t/**\n\t\t * Текущий элемент `[null, int]`\n\t\t */\n\t\tlet index = 0;\n\n\t\t/**\n\t\t * Число элементов `[null, int]`\n\t\t */\n\t\tconst max = stack.value[0].reduce((acc, [type, val]) => {\n\t\t\tif (isNull(type) && isNumber(val)) return acc + 1;\n\n\t\t\treturn acc;\n\t\t}, 0);\n\n\t\tconst queue = [] as [any, any][];\n\t\tconst keep = new Set();\n\t\tconst characters = new Set();\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tif (isString(val)) {\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t} else if (isNumber(val)) {\n\t\t\t\t\tindex++;\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Запустим все экшены которые идут в `[null, int]` от `0` до `int`\n\t\t\t\t\t * Почему-то потребовалось изменить `<` на `<=`, чтобы последний action попадал сюда\n\t\t\t\t\t */\n\t\t\t\t\tfor (let i = 0; i <= val; i++) {\n\t\t\t\t\t\tconst [action, ...meta] = current[i];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Add item to queue and action to keep\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst push = () => {\n\t\t\t\t\t\t\tkeep.add(action);\n\t\t\t\t\t\t\tqueue.push([action, meta]);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Do not remove characters that will be here anyways\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (action === 'showCharacter') characters.add(meta[0]);\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Экшены, для закрытия которых пользователь должен с ними взаимодействовать\n\t\t\t\t\t\t * Также в эту группу входят экшены, которые не должны быть вызваны при восстановлении\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (SKIPPED_DURING_RESTORE.has(action) || isUserRequiredAction(action, meta)) {\n\t\t\t\t\t\t\tif (index === max && i === val) {\n\t\t\t\t\t\t\t\tpush();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpush();\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrent = current[val];\n\t\t\t\t}\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\tqueue.forEach((value, index) => {\n\t\t\t/**\n\t\t\t * Mutate the queue item\n\t\t\t */\n\t\t\tvalue.push(index);\n\t\t});\n\n\t\t/**\n\t\t * This is basically made for TypeScript.\n\t\t */\n\t\tconst indexedQueue = queue as unknown as [Exclude<ValidAction[0], ValidAction>, ValidAction[1], number][];\n\n\t\t/**\n\t\t * Run these exactly before the main loop.\n\t\t */\n\t\trenderer.ui.showScreen('game');\n\t\t/**\n\t\t * Provide the `keep` in there\n\t\t */\n\t\tmatch('clear', [keep, characters]);\n\n\t\t/**\n\t\t * Get the next actions array.\n\t\t */\n\t\tconst next = (i: number) => indexedQueue.slice(i + 1);\n\n\t\tfor await (const [action, meta, i] of indexedQueue) {\n\t\t\tif (action === 'function' || action === 'custom') {\n\t\t\t\t/**\n\t\t\t\t * When `callOnlyLatest` is `true`\n\t\t\t\t */\n\t\t\t\tif (action === 'custom' && (meta as GetActionParameters<'Custom'>)[0].callOnlyLatest) {\n\t\t\t\t\t/**\n\t\t\t\t\t * We'll calculate it is `latest` or not\n\t\t\t\t\t */\n\t\t\t\t\tconst notLatest = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t\tif (!_meta || !meta) return false;\n\n\t\t\t\t\t\tconst c0 = _meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\t\t\t\t\t\tconst c1 = meta[0] as unknown as GetActionParameters<'Custom'>[0];\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Also check for `undefined`\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst isIdenticalID = c0.id && c1.id && c0.id === c1.id;\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Equal by id or equal by `toString()`\n\t\t\t\t\t\t */\n\t\t\t\t\t\treturn isIdenticalID || str(c0) === str(c1);\n\t\t\t\t\t});\n\n\t\t\t\t\tif (notLatest) continue;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Action can return Promise.\n\t\t\t\t */\n\t\t\t\tconst result = match(action, meta);\n\n\t\t\t\t/**\n\t\t\t\t * Should wait until it resolved\n\t\t\t\t */\n\t\t\t\tif (isPromise(result)) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Await it!\n\t\t\t\t\t */\n\t\t\t\t\tawait result;\n\t\t\t\t}\n\t\t\t} else if (action === 'showCharacter') {\n\t\t\t\tconst skip = next(i).some(([_action, _meta]) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Проверка на возможный `undefined`\n\t\t\t\t\t */\n\t\t\t\t\tif (!_meta || !meta) return false;\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\tconst hidden = _action === 'hideCharacter' && _meta[0] === meta[0];\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\tconst notLatest = _action === action && _meta[0] === meta[0];\n\n\t\t\t\t\treturn hidden || notLatest;\n\t\t\t\t});\n\n\t\t\t\tif (skip) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else if (action === 'showBackground' || action === 'animateCharacter') {\n\t\t\t\t/**\n\t\t\t\t * Такая же оптимизация применяется к фонам и анимированию персонажей.\n\t\t\t\t * Если фон изменится, то нет смысла устанавливать текущий\n\t\t\t\t */\n\t\t\t\tconst notLatest = next(i).some(([_action]) => action === _action);\n\n\t\t\t\tif (notLatest) continue;\n\n\t\t\t\tmatch(action, meta);\n\t\t\t} else {\n\t\t\t\tmatch(action, meta);\n\t\t\t}\n\t\t}\n\n\t\t(restoring = goingBack = false), render();\n\t};\n\n\tconst refer = () => {\n\t\tlet current: any = story;\n\n\t\tfor (const [type, val] of stack.value[0]) {\n\t\t\tif (type === null) {\n\t\t\t\tcurrent = current[val];\n\t\t\t} else if (type === 'choice') {\n\t\t\t\tcurrent = current[(val as number) + 1][1];\n\t\t\t} else if (type === 'condition') {\n\t\t\t\tcurrent = current[2][val];\n\t\t\t}\n\t\t}\n\n\t\treturn current;\n\t};\n\n\tconst exit = () => {\n\t\tconst current = stack.value;\n\n\t\tstack.clear();\n\t\trenderer.ui.showScreen('mainmenu');\n\n\t\t/**\n\t\t * First two save elements and it's type\n\t\t */\n\t\tconst [[first, second], , [time, type]] = current;\n\n\t\tif (type === 'auto' && first && second) {\n\t\t\t/**\n\t\t\t * Если сохранение похоже на начальное, и при этом игрок не взаимодействовал с игрой, и оно было создано в текущей сессии, то удаляем его\n\t\t\t */\n\t\t\tif (first[0] === null && first[1] === 'start' && second[0] === null && !interacted && times.has(time)) {\n\t\t\t\t$.update((prev) => {\n\t\t\t\t\tprev.saves = prev.saves.filter((save) => save !== current);\n\n\t\t\t\t\treturn prev;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Reset interactive value\n\t\t */\n\t\tinteractivity(false);\n\t\t/**\n\t\t * Reset session times\n\t\t */\n\t\ttimes.clear();\n\t};\n\n\tconst back = () => {\n\t\treturn stack.back(), restore(stack.value);\n\t};\n\n\tconst renderer = createRenderer({\n\t\tcharacters,\n\t\tset,\n\t\trestore,\n\t\tsave,\n\t\tnewGame,\n\t\texit,\n\t\tback,\n\t\tstack,\n\t\tlanguages,\n\t\tt: t9n.i,\n\t\t$,\n\t});\n\n\tconst match = matchAction({\n\t\twait([time]) {\n\t\t\tif (!restoring) setTimeout(push, isFunction(time) ? time() : time);\n\t\t},\n\t\tshowBackground([background]) {\n\t\t\trenderer.background(background);\n\t\t\tpush();\n\t\t},\n\t\tplayMusic([source]) {\n\t\t\trenderer.music(source, 'music').play();\n\t\t\tpush();\n\t\t},\n\t\tstopMusic([source]) {\n\t\t\trenderer.music(source, 'music').stop();\n\t\t\tpush();\n\t\t},\n\t\tshowCharacter([character, emotion, className, style]) {\n\t\t\tconst handle = renderer.character(character);\n\n\t\t\thandle.append(className, style, restoring);\n\t\t\thandle.withEmotion(emotion)();\n\n\t\t\tpush();\n\t\t},\n\t\thideCharacter([character, className, style, duration]) {\n\t\t\trenderer.character(character).remove(className, style, duration)(push, restoring);\n\t\t},\n\t\tdialog([character, content, emotion]) {\n\t\t\t/**\n\t\t\t * Person name\n\t\t\t */\n\t\t\tconst name = (() => {\n\t\t\t\tconst c = character,\n\t\t\t\t\tcs = characters;\n\t\t\t\tconst lang = $.get().meta[0];\n\n\t\t\t\treturn c\n\t\t\t\t\t? c in cs\n\t\t\t\t\t\t? typeof cs[c].name === 'string'\n\t\t\t\t\t\t\t? (cs[c].name as string)\n\t\t\t\t\t\t\t: (cs[c].name as Record<string, string>)[lang]\n\t\t\t\t\t\t: c\n\t\t\t\t\t: '';\n\t\t\t})();\n\n\t\t\trenderer.dialog(unwrap(content), unwrap(name), character, emotion)(forward);\n\t\t},\n\t\tfunction([fn]) {\n\t\t\tconst result = fn(restoring, goingBack);\n\n\t\t\tif (!restoring) result ? result.then(push) : push();\n\n\t\t\treturn result;\n\t\t},\n\t\tchoice([question, ...choices]) {\n\t\t\tconst isWithoutQuestion = Array.isArray(question);\n\n\t\t\tif (isWithoutQuestion) {\n\t\t\t\t/**\n\t\t\t\t * Первый элемент может быть как строкой, так и элементов выбора\n\t\t\t\t */\n\t\t\t\tchoices.unshift(question as unknown as [Unwrappable, ValidAction[], () => boolean]);\n\t\t\t\t/**\n\t\t\t\t * Значит, текст не требуется\n\t\t\t\t */\n\t\t\t\tquestion = '';\n\t\t\t}\n\n\t\t\tconst unwrapped = choices.map(([content, action, visible]) => {\n\t\t\t\treturn [unwrap(content), action, visible] as [string, ValidAction[], () => boolean];\n\t\t\t});\n\n\t\t\trenderer.choices(\n\t\t\t\tunwrap(question),\n\t\t\t\tunwrapped,\n\t\t\t)((selected) => {\n\t\t\t\tenmemory();\n\n\t\t\t\t/**\n\t\t\t\t * If there is a question, then `index` should be shifted by `1`\n\t\t\t\t */\n\t\t\t\tconst offset = isWithoutQuestion ? 0 : 1;\n\n\t\t\t\tstack.value[0].push(['choice', selected + offset], [null, 0]);\n\t\t\t\trender();\n\t\t\t\tinteractivity(true);\n\t\t\t});\n\t\t},\n\t\tjump([scene]) {\n\t\t\t/**\n\t\t\t * `-1` index is used here because `clear` will run `next` that will increase index to `0`\n\t\t\t */\n\t\t\tstack.value[0] = [\n\t\t\t\t[null, scene],\n\t\t\t\t[null, -1],\n\t\t\t];\n\n\t\t\tmatch('clear', []);\n\t\t},\n\t\tclear([keep, characters]) {\n\t\t\t/**\n\t\t\t * Remove vibration\n\t\t\t */\n\t\t\tvibrate(0);\n\t\t\t/**\n\t\t\t * Call the actual `clear`\n\t\t\t */\n\t\t\trenderer.clear(goingBack, keep || EMPTY_SET, characters || EMPTY_SET)(push);\n\t\t},\n\t\tcondition([condition]) {\n\t\t\tconst value = condition();\n\n\t\t\tif (!restoring) stack.value[0].push(['condition', String(value)], [null, 0]), render();\n\t\t},\n\t\tend() {\n\t\t\t/**\n\t\t\t * Clear the Scene\n\t\t\t */\n\t\t\tmatch('clear', []);\n\t\t\t/**\n\t\t\t * Go to the main menu\n\t\t\t */\n\t\t\trenderer.ui.showScreen('mainmenu');\n\t\t\t/**\n\t\t\t * Reset interactive value\n\t\t\t */\n\t\t\tinteractivity(false);\n\t\t\t/**\n\t\t\t * Reset session times\n\t\t\t */\n\t\t\ttimes.clear();\n\t\t},\n\t\tinput([question, onInput, setup]) {\n\t\t\trenderer.input(unwrap(question), onInput, setup)(forward);\n\t\t},\n\t\tcustom([handler]) {\n\t\t\tconst result = renderer.custom(handler, goingBack, () => {\n\t\t\t\tif (!restoring && handler.requireUserAction) enmemory(), interactivity(true);\n\t\t\t\tif (!restoring) push();\n\t\t\t});\n\n\t\t\treturn result;\n\t\t},\n\t\tvibrate(pattern) {\n\t\t\tvibrate(pattern);\n\t\t\tpush();\n\t\t},\n\t\tnext() {\n\t\t\tpush();\n\t\t},\n\t\tanimateCharacter([character, timeout, ...classes]) {\n\t\t\tconst handler: CustomHandler = (get) => {\n\t\t\t\tconst { clear } = get('@@internal-animate-character', false);\n\t\t\t\tconst char = renderer.store.characters[character];\n\n\t\t\t\t/**\n\t\t\t\t * Character is not defined, maybe, `animateCharacter` was called before `showCharacter`\n\t\t\t\t */\n\t\t\t\tif (!char) return;\n\n\t\t\t\tconst target = char.canvas;\n\n\t\t\t\t/**\n\t\t\t\t * Character is not found\n\t\t\t\t */\n\t\t\t\tif (!target) return;\n\n\t\t\t\tconst classNames = classes.filter((className) => !target.classList.contains(className));\n\n\t\t\t\ttarget.classList.add(...classNames);\n\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\t\t\t\t}, timeout);\n\n\t\t\t\tclear(() => {\n\t\t\t\t\ttarget.classList.remove(...classNames);\n\n\t\t\t\t\t/**\n\t\t\t\t\t * Clear timeout, because when you will game re-runs some callback might remove classes from character\n\t\t\t\t\t */\n\t\t\t\t\tclearTimeout(timeoutId);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\t/**\n\t\t\t * `callOnlyLatest` property will not have any effect, because `custom` is called directly\n\t\t\t */\n\t\t\tmatch('custom', [handler]);\n\t\t},\n\t\ttext(text) {\n\t\t\trenderer.text(text.map((content) => unwrap(content)).join(' '), forward);\n\t\t},\n\t\texit() {\n\t\t\tconst path = stack.value[0];\n\n\t\t\tfor (let i = path.length - 1; i > 0; i--) {\n\t\t\t\tif (path[i][0] !== 'choice' && path[i][0] !== 'condition') continue;\n\n\t\t\t\tstack.value[0] = path.slice(0, i);\n\t\t\t\tnext();\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\trender();\n\t\t},\n\t});\n\n\tconst enmemory = () => {\n\t\tif (restoring) return;\n\n\t\tconst current = klona(stack.value);\n\n\t\tcurrent[2][1] = 'auto';\n\n\t\tstack.push(current);\n\n\t\tsave(true, 'auto');\n\t};\n\n\tconst next = () => {\n\t\tconst path = stack.value[0];\n\t\t/**\n\t\t * Последний элемент пути\n\t\t */\n\t\tconst last = path[path.length - 1]!;\n\n\t\t/**\n\t\t * Если он вида `[null, int]` - увеличивает `int`\n\t\t */\n\t\tif (isNull(last[0]) && isNumber(last[1])) {\n\t\t\tlast[1] = last[1] + 1;\n\t\t\treturn;\n\t\t}\n\n\t\t/**\n\t\t * Иначе добавляет новое `[null int]`\n\t\t */\n\t\tpath.push([null, 0]);\n\t};\n\n\tconst render = () => {\n\t\tconst referred = refer();\n\n\t\tif (!Array.isArray(referred)) return;\n\n\t\tconst [action, ...props] = referred;\n\n\t\tmatch(action, props);\n\t};\n\n\tconst push = () => {\n\t\tif (!restoring) next(), render();\n\t};\n\n\tconst forward = () => {\n\t\tenmemory();\n\t\tpush();\n\t\tinteractivity(true);\n\t};\n\n\tconst interactivity = (value = false) => {\n\t\tinteracted = value;\n\t};\n\n\t/**\n\t * Unwraps translatable content to string\n\t *\n\t * @example ```\n\t * unwrap(t('Hello'));\n\t * unwrap({ en: 'Hello', ru: 'Привет' });\n\t * unwrap({ en: () => data().ad_viewed ? 'Diamond Hat' : 'Diamond Hat (Watch Adv)' })\n\t * unwrap('Hello, {{name}}');\n\t * ```\n\t */\n\tconst unwrap = (content: Unwrappable, global = false) => {\n\t\tconst {\n\t\t\tdata,\n\t\t\tmeta: [lang],\n\t\t} = $.get();\n\n\t\tconst obj = global ? data : state();\n\t\tconst cnt = isFunction(content) ? content(lang, obj) : typeof content === 'string' ? content : content[lang];\n\n\t\tconst str = isFunction(cnt) ? cnt() : cnt;\n\n\t\treturn replaceT9N(str, obj);\n\t};\n\n\tfunction data(value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;\n\tfunction data(): DataScheme;\n\tfunction data(value?: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): DataScheme | void {\n\t\tif (!value) return $.get().data as DataScheme | void;\n\n\t\tconst prev = $.get().data;\n\t\tconst val = isFunction(value) ? value(prev as DataScheme) : deepmerge([prev, value]);\n\n\t\t$.update((prev) => {\n\t\t\tprev.data = val;\n\n\t\t\treturn prev;\n\t\t});\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Function to set story\n\t\t */\n\t\twithStory,\n\t\t/**\n\t\t * Function to get actions\n\t\t */\n\t\taction,\n\t\t/**\n\t\t * State that belongs to games\n\t\t */\n\t\tstate,\n\t\t/**\n\t\t * Unlike `state`, stored at global scope instead and shared between games\n\t\t */\n\t\tdata,\n\t\t/**\n\t\t * Unwraps translatable content to a string value\n\t\t */\n\t\tunwrap(content: Exclude<Unwrappable, Record<string, string>> | Record<Languages, string>) {\n\t\t\treturn unwrap(content, true);\n\t\t},\n\t\t/**\n\t\t * Function that is used for translation\n\t\t */\n\t\tt: t9n.t as Inter['t'],\n\t};\n};\n\nexport { novely };\n","const SKIPPED_DURING_RESTORE = new Set(['dialog', 'choice', 'input', 'vibrate', 'text'] as const);\n\nconst EMPTY_SET = new Set<any>();\n\nexport { SKIPPED_DURING_RESTORE, EMPTY_SET };\n","import type { StorageData } from './types';\n\ninterface LocalStorageStorageSettings {\n\tkey: string;\n}\n\ninterface Storage {\n\tget: () => Promise<StorageData>;\n\tset: (data: StorageData) => Promise<void>;\n}\n\nconst localStorageStorage = (options: LocalStorageStorageSettings): Storage => {\n\treturn {\n\t\tasync get() {\n\t\t\tconst value = localStorage.getItem(options.key);\n\n\t\t\treturn value ? JSON.parse(value) : { saves: [], data: {}, meta: [] };\n\t\t},\n\t\tasync set(data) {\n\t\t\tlocalStorage.setItem(options.key, JSON.stringify(data));\n\t\t},\n\t};\n};\n\nexport type { Storage };\nexport { localStorageStorage };\n"],"mappings":"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","names":["getLanguage","data","state","stack","save","characters","action","push","index","next","str","prev"]}
|
package/package.json
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
2
|
+
"name": "@novely/core",
|
|
3
|
+
"description": "Novely - powerful visual novel engine for creating interactive stories and games with branching narratives and rich multimedia content.",
|
|
4
|
+
"version": "0.6.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"cdn": "./dist/index.global.js",
|
|
12
|
+
"unpkg": "./dist/index.global.js",
|
|
13
|
+
"jsdelivr": "./dist/index.global.js",
|
|
14
|
+
"browser": "./dist/index.global.js",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./*": "./dist/*",
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"build": "tsup --dts"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"tsup": "^7.1.0",
|
|
29
|
+
"typescript": "^5.1.6"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@novely/t9n": "latest",
|
|
33
|
+
"deepmerge": "^4.3.1",
|
|
34
|
+
"klona": "^2.0.6"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"deepmerge": "^4.3.0",
|
|
38
|
+
"klona": "^2.0.6"
|
|
39
|
+
},
|
|
40
|
+
"license": "ISC",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/yhdgms1/novely/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/yhdgms1/novely/tree/main/packages/core",
|
|
45
|
+
"keywords": [
|
|
46
|
+
"novely",
|
|
47
|
+
"novel",
|
|
48
|
+
"engine",
|
|
49
|
+
"renpy"
|
|
50
|
+
],
|
|
51
|
+
"author": {
|
|
52
|
+
"name": "Artemiy Schukin",
|
|
53
|
+
"url": "https://github.com/yhdgms1"
|
|
54
|
+
},
|
|
55
|
+
"contributors": [],
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/yhdgms1/novely.git"
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"dist/*"
|
|
62
|
+
]
|
|
63
63
|
}
|