@novely/core 0.23.0 → 0.24.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 CHANGED
@@ -6,153 +6,19 @@ type Character<LanguageKeys extends string = string> = {
6
6
  emotions: Emotions;
7
7
  };
8
8
 
9
- type Thenable<T> = T | Promise<T>;
10
- type PathItem = [null, number | string] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
11
- type Path = PathItem[];
12
- type State = Record<string, any>;
13
- type Data = Record<string, any>;
14
- type SaveDate = number;
15
- type SaveType = 'manual' | 'auto';
16
- type SaveMeta = [date: SaveDate, type: SaveType];
17
- type Save = [path: Path, state: State, meta: SaveMeta];
18
- type Lang = string;
19
- type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
20
- type SoundVolume = number;
21
- type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
22
- type Migration = (save: unknown) => unknown;
23
- type StorageData = {
24
- saves: Save[];
25
- data: Data;
26
- meta: StorageMeta;
27
- };
28
- type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
29
- /**
30
- * @see https://pendletonjones.com/deep-partial
31
- */
32
- type DeepPartial<T> = unknown extends T ? T : T extends object ? {
33
- [P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
34
- } : T;
35
- type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
36
- type CoreData = {
37
- dataLoaded: boolean;
38
- };
39
-
40
- type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta<string>) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
41
- type Story = Record<string, ValidAction[]>;
42
- type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
43
- type FunctionableValue<T> = T | (() => T);
44
- type CustomHandlerGetResultDataFunction = {
45
- (data?: Record<string, unknown>): Record<string, unknown>;
46
- };
47
- type CustomHandlerGetResult<I extends boolean> = {
48
- delete: () => void;
49
- /**
50
- * Данные
51
- */
52
- data: CustomHandlerGetResultDataFunction;
53
- /**
54
- * Элемент слоя
55
- */
56
- element: I extends true ? HTMLDivElement : null;
57
- /**
58
- * Корневой элемент Novely
59
- */
60
- root: HTMLElement;
61
- /**
62
- * Устанавливает обработчик очистки
63
- */
64
- clear: (fn: () => void) => void;
65
- };
66
- type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
67
- type CustomHandlerFunctionParameters = {
68
- get: CustomHandlerFunctionGetFn;
69
- goingBack: boolean;
70
- preview: boolean;
71
- lang: string;
72
- };
73
- type CustomHandlerFunction = (parameters: CustomHandlerFunctionParameters) => Thenable<void>;
74
- type CustomHandler = CustomHandlerFunction & {
75
- callOnlyLatest?: boolean;
76
- requireUserAction?: boolean;
77
- skipClearOnGoingBack?: boolean;
78
- id?: string | symbol;
9
+ interface LocalStorageStorageSettings {
79
10
  key: string;
80
- };
81
- interface ActionInputOnInputMeta<L extends string> {
82
- /**
83
- * Input Element itself
84
- */
85
- input: HTMLInputElement;
86
- /**
87
- * Function to show error message or hide it
88
- * @param error Error message or empty string to remove it
89
- */
90
- error: (error: string) => void;
91
- /**
92
- * Input Event
93
- */
94
- event: InputEvent & {
95
- currentTarget: HTMLInputElement;
96
- };
97
- /**
98
- * Sanitized `input.value`
99
- */
100
- value: string;
101
- /**
102
- * Language
103
- */
104
- lang: L;
105
11
  }
106
- type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
107
- type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
108
- type ActionProxyProvider<Characters extends Record<string, Character>, Languages extends string> = {
109
- choice: {
110
- (...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
111
- (question: Unwrappable<Languages>, ...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
112
- };
113
- clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>, keepAudio?: {
114
- music: Set<string>;
115
- sounds: Set<string>;
116
- }) => ValidAction;
117
- condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
118
- exit: () => ValidAction;
119
- dialog: {
120
- <C extends keyof Characters>(person: C, content: Unwrappable<Languages>, emotion?: keyof Characters[C]['emotions']): ValidAction;
121
- (person: undefined, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
122
- (person: string, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
123
- };
124
- end: () => ValidAction;
125
- showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
126
- playMusic: (audio: string) => ValidAction;
127
- stopMusic: (audio: string) => ValidAction;
128
- playSound: (audio: string, loop?: boolean) => ValidAction;
129
- stopSound: (audio: string) => ValidAction;
130
- /**
131
- * Plays voice
132
- */
133
- voice: (voice: string) => ValidAction;
134
- /**
135
- * Stops currently playing voice
136
- */
137
- stopVoice: () => ValidAction;
138
- jump: (scene: string) => ValidAction;
139
- showCharacter: {
140
- <C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
141
- };
142
- hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
143
- animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
144
- wait: (time: FunctionableValue<number>) => ValidAction;
145
- function: (fn: (restoring: boolean, goingBack: boolean, preview: boolean) => Thenable<void>) => ValidAction;
146
- input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta<Languages>) => void, setup?: ActionInputSetup) => ValidAction;
147
- custom: (handler: CustomHandler) => ValidAction;
148
- vibrate: (...pattern: number[]) => ValidAction;
149
- next: () => ValidAction;
150
- text: (...text: Unwrappable<Languages>[]) => ValidAction;
151
- preload: (source: string) => ValidAction;
152
- block: (scene: string) => ValidAction;
153
- };
154
- type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>, string>;
155
- type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
12
+ interface Storage {
13
+ get: () => Promise<StorageData>;
14
+ set: (data: StorageData) => Promise<void>;
15
+ }
16
+ declare const localStorageStorage: (options: LocalStorageStorageSettings) => Storage;
17
+
18
+ type PluralType = Intl.LDMLPluralRule;
19
+ type Pluralization = Partial<Record<PluralType, string>>;
20
+ type AllowedContent = string | (() => string | string[]) | string[] | (string | (() => string | string[]))[];
21
+ type TranslationActions = Partial<Record<string, (str: string) => string>>;
156
22
 
157
23
  declare const RU: {
158
24
  NewGame: string;
@@ -342,29 +208,74 @@ type RendererInit = {
342
208
  removeContext: (name: string) => void;
343
209
  };
344
210
 
345
- interface LocalStorageStorageSettings {
346
- key: string;
347
- }
348
- interface Storage {
349
- get: () => Promise<StorageData>;
350
- set: (data: StorageData) => Promise<void>;
351
- }
352
- declare const localStorageStorage: (options: LocalStorageStorageSettings) => Storage;
353
-
354
- type PluralType = Intl.LDMLPluralRule;
355
- type Pluralization = Partial<Record<PluralType, string>>;
356
- type AllowedContent = string | (() => string | string[]) | string[] | (string | (() => string | string[]))[];
357
- type TranslationActions = Partial<Record<string, (str: string) => string>>;
358
-
359
211
  declare const getLanguage: (languages: string[]) => string;
360
212
 
361
- interface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data> {
213
+ type Thenable<T> = T | Promise<T>;
214
+ type PathItem = [null, number | string] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
215
+ type Path = PathItem[];
216
+ type State = Record<string, any>;
217
+ type Data = Record<string, any>;
218
+ type SaveDate = number;
219
+ type SaveType = 'manual' | 'auto';
220
+ type SaveMeta = [date: SaveDate, type: SaveType];
221
+ type Save = [path: Path, state: State, meta: SaveMeta];
222
+ type Lang = string;
223
+ type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
224
+ type SoundVolume = number;
225
+ type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
226
+ type Migration = (save: unknown) => unknown;
227
+ type StorageData = {
228
+ saves: Save[];
229
+ data: Data;
230
+ meta: StorageMeta;
231
+ };
232
+ type Stack = {
233
+ value: Save;
234
+ back(): void;
235
+ push(value: Save): void;
236
+ clear(): void;
237
+ };
238
+ type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
239
+ /**
240
+ * @see https://pendletonjones.com/deep-partial
241
+ */
242
+ type DeepPartial<T> = unknown extends T ? T : T extends object ? {
243
+ [P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
244
+ } : T;
245
+ type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
246
+ type CoreData = {
247
+ dataLoaded: boolean;
248
+ };
249
+ type StackHolder = Save[] & {
250
+ previous: Save | undefined;
251
+ };
252
+ type TranslationDescription = {
253
+ internal: Record<BaseTranslationStrings, string>;
362
254
  /**
363
- * An array of languages supported by the game.
255
+ * IETF BCP 47 language tag
364
256
  */
365
- languages: Languages[];
257
+ tag?: string;
258
+ plural?: Record<string, Pluralization>;
259
+ actions?: TranslationActions;
260
+ };
261
+ interface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data> {
366
262
  /**
367
263
  * An object containing the characters in the game.
264
+ * @example
265
+ * ```ts
266
+ * const engine = novely({
267
+ * characters: {
268
+ * // Character ID
269
+ * Alexei: {
270
+ * name: 'Alexei',
271
+ * color: '#f60002',
272
+ * emotions: {
273
+ * hopeful: './hopeful.png'
274
+ * }
275
+ * }
276
+ * }
277
+ * })
278
+ * ```
368
279
  */
369
280
  characters: Characters;
370
281
  /**
@@ -386,22 +297,37 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
386
297
  initialScreen?: NovelyScreen;
387
298
  /**
388
299
  * An object containing the translation functions used in the game
300
+ * @see https://novely.pages.dev/guide/translation.html Docs
301
+ * @example
302
+ * ```ts
303
+ * import { novely, EN } from 'novely';
304
+ *
305
+ * const engine = novely({
306
+ * translation: {
307
+ * internal: EN,
308
+ * // Optional IETF BCP 47 language tag
309
+ * tag: 'en-US',
310
+ * plural: {
311
+ *
312
+ * },
313
+ * actions: {
314
+ *
315
+ * }
316
+ * }
317
+ * })
318
+ * ```
389
319
  */
390
- translation: Record<Languages, {
391
- internal: Record<BaseTranslationStrings, string>;
392
- /**
393
- * IETF BCP 47 language tag
394
- */
395
- tag?: string;
396
- plural?: Record<string, Pluralization>;
397
- actions?: TranslationActions;
398
- }>;
320
+ translation: Record<Languages, TranslationDescription>;
399
321
  /**
400
322
  * Initial state value
323
+ *
324
+ * State is a local value bound to one save
401
325
  */
402
326
  state?: StateScheme;
403
327
  /**
404
328
  * Initial data value
329
+ *
330
+ * Data is a global value shared between saves
405
331
  */
406
332
  data?: DataScheme;
407
333
  /**
@@ -425,13 +351,16 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
425
351
  parallelAssetsDownloadLimit?: number;
426
352
  /**
427
353
  * Custom language detector
428
- * @param languages Supported languages aka `languages: []` in the config
429
- * @example ```ts
430
- * novely({
431
- * getLanguage(languages, original) {
432
- * if (!sdk) return original(languages);
433
- * return sdk.environment.i18n.lang // i.e. custom language from some sdk
434
- * }
354
+ * @param languages Supported languages
355
+ * @param original Original function that novely, could be used as fallback
356
+ * @example
357
+ * ```ts
358
+ * const engine = novely({
359
+ * getLanguage(languages, original) {
360
+ * if (!sdk) return original(languages);
361
+ *
362
+ * return sdk.environment.i18n.lang // i.e. custom language from some sdk
363
+ * }
435
364
  * })
436
365
  * ```
437
366
  */
@@ -455,7 +384,125 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
455
384
  */
456
385
  fetch?: typeof fetch;
457
386
  }
458
- declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, translation, languages, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request }: NovelyInit<Languages, Characters, StateScheme, DataScheme>) => {
387
+
388
+ type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta<string>) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
389
+ type Story = Record<string, ValidAction[]>;
390
+ type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
391
+ type FunctionableValue<T> = T | (() => T);
392
+ type CustomHandlerGetResultDataFunction = {
393
+ (data?: Record<string, unknown>): Record<string, unknown>;
394
+ };
395
+ type CustomHandlerGetResult<I extends boolean> = {
396
+ delete: () => void;
397
+ /**
398
+ * Данные
399
+ */
400
+ data: CustomHandlerGetResultDataFunction;
401
+ /**
402
+ * Элемент слоя
403
+ */
404
+ element: I extends true ? HTMLDivElement : null;
405
+ /**
406
+ * Корневой элемент Novely
407
+ */
408
+ root: HTMLElement;
409
+ /**
410
+ * Устанавливает обработчик очистки
411
+ */
412
+ clear: (fn: () => void) => void;
413
+ };
414
+ type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
415
+ type CustomHandlerFunctionParameters = {
416
+ get: CustomHandlerFunctionGetFn;
417
+ goingBack: boolean;
418
+ preview: boolean;
419
+ lang: string;
420
+ };
421
+ type CustomHandlerFunction = (parameters: CustomHandlerFunctionParameters) => Thenable<void>;
422
+ type CustomHandler = CustomHandlerFunction & {
423
+ callOnlyLatest?: boolean;
424
+ requireUserAction?: boolean;
425
+ skipClearOnGoingBack?: boolean;
426
+ id?: string | symbol;
427
+ key: string;
428
+ };
429
+ interface ActionInputOnInputMeta<L extends string> {
430
+ /**
431
+ * Input Element itself
432
+ */
433
+ input: HTMLInputElement;
434
+ /**
435
+ * Function to show error message or hide it
436
+ * @param error Error message or empty string to remove it
437
+ */
438
+ error: (error: string) => void;
439
+ /**
440
+ * Input Event
441
+ */
442
+ event: InputEvent & {
443
+ currentTarget: HTMLInputElement;
444
+ };
445
+ /**
446
+ * Sanitized `input.value`
447
+ */
448
+ value: string;
449
+ /**
450
+ * Language
451
+ */
452
+ lang: L;
453
+ }
454
+ type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
455
+ type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
456
+ type ActionProxyProvider<Characters extends Record<string, Character>, Languages extends string> = {
457
+ choice: {
458
+ (...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
459
+ (question: Unwrappable<Languages>, ...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
460
+ };
461
+ clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>, keepAudio?: {
462
+ music: Set<string>;
463
+ sounds: Set<string>;
464
+ }) => ValidAction;
465
+ condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
466
+ exit: () => ValidAction;
467
+ dialog: {
468
+ <C extends keyof Characters>(person: C, content: Unwrappable<Languages>, emotion?: keyof Characters[C]['emotions']): ValidAction;
469
+ (person: undefined, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
470
+ (person: string, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
471
+ };
472
+ end: () => ValidAction;
473
+ showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
474
+ playMusic: (audio: string) => ValidAction;
475
+ stopMusic: (audio: string) => ValidAction;
476
+ playSound: (audio: string, loop?: boolean) => ValidAction;
477
+ stopSound: (audio: string) => ValidAction;
478
+ /**
479
+ * Plays voice
480
+ */
481
+ voice: (voice: string) => ValidAction;
482
+ /**
483
+ * Stops currently playing voice
484
+ */
485
+ stopVoice: () => ValidAction;
486
+ jump: (scene: string) => ValidAction;
487
+ showCharacter: {
488
+ <C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
489
+ };
490
+ hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
491
+ animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
492
+ wait: (time: FunctionableValue<number>) => ValidAction;
493
+ function: (fn: (restoring: boolean, goingBack: boolean, preview: boolean) => Thenable<void>) => ValidAction;
494
+ input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta<Languages>) => void, setup?: ActionInputSetup) => ValidAction;
495
+ custom: (handler: CustomHandler) => ValidAction;
496
+ vibrate: (...pattern: number[]) => ValidAction;
497
+ next: () => ValidAction;
498
+ text: (...text: Unwrappable<Languages>[]) => ValidAction;
499
+ preload: (source: string) => ValidAction;
500
+ block: (scene: string) => ValidAction;
501
+ };
502
+ type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>, string>;
503
+ type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
504
+
505
+ declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, translation, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request }: NovelyInit<Languages, Characters, StateScheme, DataScheme>) => {
459
506
  /**
460
507
  * Function to set game script
461
508
  */
@@ -489,4 +536,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
489
536
  destroy(): void;
490
537
  };
491
538
 
492
- export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
539
+ export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
@@ -810,7 +810,6 @@ var Novely = (() => {
810
810
  renderer: createRenderer,
811
811
  initialScreen = "mainmenu",
812
812
  translation,
813
- languages,
814
813
  state: defaultState,
815
814
  data: defaultData,
816
815
  autosaves = true,
@@ -823,6 +822,7 @@ var Novely = (() => {
823
822
  parallelAssetsDownloadLimit = 15,
824
823
  fetch: request = fetch
825
824
  }) => {
825
+ const languages = Object.keys(translation);
826
826
  const limitScript = (0, import_p_limit.default)(1);
827
827
  const limitAssetsDownload = (0, import_p_limit.default)(parallelAssetsDownloadLimit);
828
828
  const story = {};
@@ -955,12 +955,10 @@ var Novely = (() => {
955
955
  for (const migration of migrations) {
956
956
  stored = migration(stored);
957
957
  }
958
- stored.meta[1] ||= DEFAULT_TYPEWRITER_SPEED;
959
- if (overrideLanguage) {
958
+ if (overrideLanguage || !stored.meta[0]) {
960
959
  stored.meta[0] = getLanguageWithoutParameters();
961
- } else {
962
- stored.meta[0] ||= getLanguageWithoutParameters();
963
960
  }
961
+ stored.meta[1] ||= DEFAULT_TYPEWRITER_SPEED;
964
962
  stored.meta[2] ??= 1;
965
963
  stored.meta[3] ??= 1;
966
964
  stored.meta[4] ??= 1;