@novely/core 0.54.0-next.3 → 0.55.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.
@@ -0,0 +1,1319 @@
1
+ //#region src/store.d.ts
2
+ type Stored<T> = {
3
+ subscribe: (cb: (value: T) => void) => () => void;
4
+ update: (fn: (prev: T) => T) => void;
5
+ set: (val: T) => void;
6
+ get: () => T;
7
+ };
8
+ type Derived<T> = {
9
+ subscribe: (cb: (value: T) => void) => () => void;
10
+ get: () => T;
11
+ };
12
+ //#endregion
13
+ //#region src/translations.d.ts
14
+ declare const RU: {
15
+ NewGame: string;
16
+ HomeScreen: string;
17
+ ToTheGame: string;
18
+ Language: string;
19
+ NoSaves: string;
20
+ LoadSave: string;
21
+ Saves: string;
22
+ Settings: string;
23
+ Sumbit: string;
24
+ GoBack: string;
25
+ DoSave: string;
26
+ Auto: string;
27
+ Stop: string;
28
+ Exit: string;
29
+ Automatic: string;
30
+ Manual: string;
31
+ Remove: string;
32
+ LoadASaveFrom: string;
33
+ DeleteASaveFrom: string;
34
+ TextSpeed: string;
35
+ TextSpeedSlow: string;
36
+ TextSpeedMedium: string;
37
+ TextSpeedFast: string;
38
+ TextSpeedAuto: string;
39
+ CompleteText: string;
40
+ GoForward: string;
41
+ ExitDialogWarning: string;
42
+ ExitDialogExit: string;
43
+ ExitDialogBack: string;
44
+ OpenMenu: string;
45
+ CloseMenu: string;
46
+ MusicVolume: string;
47
+ SoundVolume: string;
48
+ VoiceVolume: string;
49
+ Close: string;
50
+ DialogOverview: string;
51
+ };
52
+ type BaseTranslationStrings = keyof typeof RU;
53
+ declare const EN: Record<BaseTranslationStrings, string>;
54
+ //#endregion
55
+ //#region src/renderer.d.ts
56
+ type CharacterHandle = {
57
+ emotion: (emotion: string, render: boolean) => void;
58
+ append: (className?: string, style?: string, restoring?: boolean) => void;
59
+ remove: (className?: string, style?: string, duration?: number, restoring?: boolean) => Promise<void>;
60
+ animate: (classes: string[]) => void;
61
+ emotions: Record<string, HTMLImageElement[]>;
62
+ };
63
+ type CustomActionHandle = {
64
+ /**
65
+ * Function to remove custom action from screen (and from your state if any completely)
66
+ */
67
+ remove: () => void;
68
+ /**
69
+ * Function that will give action root (element which you should add to the screen because custom actions rendered into that element)
70
+ */
71
+ setMountElement: (mountElement: null | HTMLDivElement) => void;
72
+ };
73
+ type AudioHandle = {
74
+ stop: () => void;
75
+ pause: () => void;
76
+ play: (loop: boolean) => void;
77
+ };
78
+ type Context = {
79
+ id: string;
80
+ get root(): HTMLElement;
81
+ set root(value: HTMLElement);
82
+ character: (character: string) => CharacterHandle;
83
+ background: (background: Record<string, string>) => void;
84
+ dialog: (content: string, name: string, character: string | undefined, emotion: string | undefined, resolve: () => void) => void;
85
+ choices: (question: string, choices: [name: string, active: Stored<boolean>, visible: Stored<boolean>, onselect: () => void, image: string][], resolve: (selected: number) => void) => void;
86
+ input: (question: string, onInput: (meta: ActionInputOnInputMeta<Lang, State>) => void, setup: ActionInputSetup, resolve: () => void) => void;
87
+ clear: (keep: Set<keyof DefaultActionProxy>, keepCharacters: Set<string>, keepAudio: {
88
+ music: Set<string>;
89
+ sounds: Set<string>;
90
+ }, resolve: () => void) => void;
91
+ custom: (fn: CustomHandler<Lang, State>) => CustomActionHandle;
92
+ /**
93
+ * Clears all mentioned actions except for preserved one
94
+ * @param preserve Action that should not be cleared
95
+ */
96
+ clearBlockingActions: (preserve: 'dialog' | 'choice' | 'input' | 'text' | undefined) => void;
97
+ text: (str: string, resolve: () => void) => void;
98
+ vibrate: (pattern: VibratePattern) => void;
99
+ audio: {
100
+ voice: (source: string, paused: Derived<boolean>) => void;
101
+ voiceStop: () => void;
102
+ music: (source: string, paused: Derived<boolean>, method: 'music' | 'sound') => AudioHandle;
103
+ /**
104
+ * Stop all sounds
105
+ */
106
+ clear: () => void;
107
+ /**
108
+ * Destroy
109
+ */
110
+ destroy: () => void;
111
+ /**
112
+ * Initialize audio service, attach events, etc
113
+ */
114
+ start: () => void;
115
+ };
116
+ loading: (shown: boolean) => void;
117
+ meta: {
118
+ get restoring(): boolean;
119
+ set restoring(value: boolean);
120
+ get preview(): boolean;
121
+ set preview(value: boolean);
122
+ get goingBack(): boolean;
123
+ set goingBack(value: boolean);
124
+ };
125
+ };
126
+ type Renderer = {
127
+ misc: {
128
+ /**
129
+ * Function to preload image sync
130
+ * @param image Image URL
131
+ * @returns Image URL
132
+ */
133
+ preloadImage: <T extends string>(image: T) => T;
134
+ /**
135
+ * Function to preload image async
136
+ * @param image Image URL
137
+ * @returns Promise
138
+ */
139
+ preloadImageBlocking: (image: string) => Promise<void>;
140
+ /**
141
+ * Function to preload audio
142
+ * @param source <url> pointing to the audio
143
+ */
144
+ preloadAudioBlocking: (source: string) => Promise<void>;
145
+ };
146
+ ui: {
147
+ /**
148
+ * Shows the screen
149
+ */
150
+ showScreen(name: NovelyScreen): void;
151
+ /**
152
+ * Returns current screen
153
+ */
154
+ getScreen(): NovelyScreen | (string & Record<never, never>);
155
+ /**
156
+ * Shows loading
157
+ *
158
+ * Unline `showScreen('loading')` does not change screen
159
+ */
160
+ showLoading(): void;
161
+ /**
162
+ * Hides loading
163
+ */
164
+ hideLoading(): void;
165
+ /**
166
+ * Shows prompt to exit
167
+ */
168
+ showExitPrompt(): void;
169
+ /**
170
+ * Render the game
171
+ */
172
+ start(): {
173
+ /**
174
+ * Unmount
175
+ */
176
+ unmount(): void;
177
+ };
178
+ };
179
+ actions: Record<string, (...args: any[]) => ValidAction>;
180
+ getContext: (context: string) => Context;
181
+ removeContext: (context: string) => void;
182
+ };
183
+ type RendererInitPreviewReturn = {
184
+ /**
185
+ * Assets that was used in game preview
186
+ */
187
+ assets: string[];
188
+ };
189
+ type RendererInit<$Language extends Lang, $Characters extends Record<string, Character<$Language>>> = {
190
+ characters: CharactersData<$Characters>;
191
+ characterAssetSizes: CharacterAssetSizes<$Characters>;
192
+ set: (save: Save<State>) => Promise<void>;
193
+ restore: (save?: Save<State>) => Promise<void>;
194
+ save: (type: Save<State>[2][1]) => void;
195
+ newGame: () => void;
196
+ exit: (force?: boolean) => void;
197
+ back: () => Promise<void>;
198
+ languages: $Language[];
199
+ /**
200
+ * Translation function
201
+ */
202
+ t: (key: BaseTranslationStrings, lang: Lang) => string;
203
+ /**
204
+ * Store that tracks data updates
205
+ */
206
+ storageData: Stored<StorageData<Lang, Data>>;
207
+ /**
208
+ * Store that used to communicate between renderer and core
209
+ */
210
+ coreData: Stored<CoreData>;
211
+ /**
212
+ * There is different context, and the main one which is used for game
213
+ */
214
+ mainContextKey: string;
215
+ preview: (save: Save<State>, name: string) => Promise<RendererInitPreviewReturn>;
216
+ removeContext: (name: string) => void;
217
+ getStateFunction: (context: string) => StateFunction<State>;
218
+ clearCustomActionsAtContext: (ctx: Context) => void;
219
+ getLanguageDisplayName: (lang: Lang) => string;
220
+ getCharacterColor: (character: string) => string;
221
+ getCharacterAssets: (character: string, emotion: string) => string[];
222
+ getDialogOverview: () => Promise<DialogOverview>;
223
+ getResourseType: (url: string) => Promise<'image' | 'audio' | 'other'>;
224
+ setLanguage: (language: string) => void;
225
+ };
226
+ //#endregion
227
+ //#region src/storage.d.ts
228
+ type StorageAdapter = {
229
+ get: () => Promise<StorageData>;
230
+ set: (data: StorageData) => Promise<void>;
231
+ };
232
+ type StorageAdapterLocalOptions = {
233
+ key: string;
234
+ };
235
+ /**
236
+ * Stores data in localStorage
237
+ */
238
+ declare const storageAdapterLocal: ({
239
+ key
240
+ }: StorageAdapterLocalOptions) => StorageAdapter;
241
+ //#endregion
242
+ //#region src/translation.d.ts
243
+ type PluralType = Intl.LDMLPluralRule;
244
+ type Pluralization = Partial<Record<PluralType, string>>;
245
+ type AllowedContent = string | ((state: State | Data) => string | string[]) | string[] | (string | ((state: State | Data) => string | string[]))[];
246
+ type TranslationActions = Partial<Record<string, (str: string) => string>>;
247
+ /**
248
+ * Turns any allowed content into string
249
+ * @param c Content
250
+ */
251
+ //#endregion
252
+ //#region src/utilities/internationalization.d.ts
253
+ declare const getLanguage$1: (languages: string[]) => string;
254
+ //#endregion
255
+ //#region src/types.d.ts
256
+ type NovelyAsset = {
257
+ readonly source: string;
258
+ readonly id: string;
259
+ readonly type: 'audio' | 'image';
260
+ };
261
+ type Thenable<T> = T | Promise<T>;
262
+ type PathItem = [null, number] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
263
+ type Path = PathItem[];
264
+ type State = Record<string, any>;
265
+ type Data = Record<string, any>;
266
+ type SaveDate = number;
267
+ type SaveType = 'manual' | 'auto';
268
+ type SaveMeta = [date: SaveDate, type: SaveType];
269
+ type Save<S extends State = State> = [path: Path, state: S, meta: SaveMeta, state_snapshots: S[]];
270
+ type Lang = string;
271
+ type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto';
272
+ type SoundVolume = number;
273
+ type StorageMeta<L extends Lang = string> = [lang: L, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
274
+ type Migration = (save: unknown) => unknown;
275
+ type StorageData<L extends Lang = string, D extends Data = Data> = {
276
+ saves: Save[];
277
+ data: D;
278
+ meta: StorageMeta<L>;
279
+ };
280
+ type Stack = {
281
+ value: Save;
282
+ back(): void;
283
+ push(value: Save): void;
284
+ clear(): void;
285
+ };
286
+ type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
287
+ /**
288
+ * @see https://pendletonjones.com/deep-partial
289
+ */
290
+ type DeepPartial<T> = unknown extends T ? T : T extends object ? { [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]> } : T;
291
+ /**
292
+ *
293
+ */
294
+ type Assign<A extends object, B extends object> = Pick<A, Exclude<keyof A, keyof B>> & B;
295
+ type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
296
+ type CoreData = {
297
+ dataLoaded: boolean;
298
+ paused: boolean;
299
+ focused: boolean;
300
+ };
301
+ type StackHolder = Save[] & {
302
+ previous: Save | undefined;
303
+ };
304
+ type TranslationDescription = {
305
+ internal: Record<BaseTranslationStrings, string>;
306
+ /**
307
+ * IETF BCP 47 language tag
308
+ */
309
+ tag?: string;
310
+ /**
311
+ * Custom name
312
+ */
313
+ nameOverride?: string;
314
+ plural?: Record<string, Pluralization>;
315
+ actions?: TranslationActions;
316
+ };
317
+ type DefaultEmotions<$Characters extends Record<string, Character<Lang>>> = { [Character in keyof $Characters]?: keyof $Characters[Character]['emotions'] & string };
318
+ type CharacterAssetSizes<$Characters extends Record<string, Character<Lang>>> = { [Character in keyof $Characters]?: {
319
+ width: number;
320
+ height: number;
321
+ } };
322
+ type CharactersData<$Characters extends Record<string, Character<Lang>>> = { [Character in keyof $Characters]: {
323
+ name: $Characters[Character]['name'];
324
+ emotions: Array<keyof $Characters[Character]['emotions']>;
325
+ } };
326
+ type AssetsPreloading = 'lazy' | 'automatic';
327
+ type CloneFN = <T>(value: T) => T;
328
+ type StoryOptionsStatic = {
329
+ /**
330
+ * Static mode means that story is static
331
+ */
332
+ mode: 'static';
333
+ };
334
+ type StoryOptionsDynamic = {
335
+ /**
336
+ * Dynamic mode means that story parts can be loaded dynamically
337
+ */
338
+ mode: 'dynamic';
339
+ /**
340
+ * Number of saves to preload story for
341
+ * @default 4
342
+ */
343
+ preloadSaves?: number;
344
+ /**
345
+ * Function to dynamically load story parts.
346
+ *
347
+ * When engine find's unknown scene it will run this function.
348
+ * @example
349
+ * ```
350
+ * const load = async (scene: string): Promise<Story> => {
351
+ * if (['part_2__act_1', 'part_2__act_2', 'part_2__act_3'].includes(scene)) {
352
+ * const { getStory } = await import('./part-2.ts');
353
+ *
354
+ * return getStory(engine.action);
355
+ * }
356
+ *
357
+ * if (scene === 'end') {
358
+ * return {
359
+ * 'end': [
360
+ * engine.action.text('The End')
361
+ * ]
362
+ * }
363
+ * }
364
+ *
365
+ * throw new Error(`Unknown scene: ${scene}`);
366
+ * }
367
+ * ```
368
+ */
369
+ load: (scene: string) => Promise<Story>;
370
+ };
371
+ type StoryOptions = StoryOptionsStatic | StoryOptionsDynamic;
372
+ type OnLanguageChange<$Lang extends Lang> = (language: $Lang) => void;
373
+ interface NovelyInit<$Language extends Lang, $Characters extends Record<string, Character<NoInfer<$Language>>>, $State extends State, $Data extends Data, $Actions extends Record<string, (...args: any[]) => ValidAction>> {
374
+ /**
375
+ * An object containing the characters in the game.
376
+ * @example
377
+ * ```ts
378
+ * const engine = novely({
379
+ * characters: {
380
+ * // Character ID
381
+ * Alexei: {
382
+ * name: 'Alexei',
383
+ * color: '#f60002',
384
+ * emotions: {
385
+ * hopeful: './hopeful.png'
386
+ * }
387
+ * }
388
+ * }
389
+ * })
390
+ * ```
391
+ */
392
+ characters: $Characters;
393
+ /**
394
+ * Define default emotions for characters
395
+ * @example
396
+ * ```ts
397
+ * const engine = novely({
398
+ * characters: {
399
+ * Yuki: {
400
+ * name: 'Yuki',
401
+ * color: '#f595f6',
402
+ * emotions: {
403
+ * normal: './normal.png'
404
+ * }
405
+ * }
406
+ * },
407
+ * defaultEmotions: {
408
+ * Yuki: 'normal'
409
+ * }
410
+ * });
411
+ *
412
+ * engine.script({
413
+ * start: [
414
+ * // Without emotion!
415
+ * engine.action.showCharacter('Yuki')
416
+ * ]
417
+ * })
418
+ * ```
419
+ */
420
+ defaultEmotions?: DefaultEmotions<NoInfer<$Characters>>;
421
+ /**
422
+ * Character asset sizes. We need width-height pair to render character, but we get it only after the assets are loaded. However, using that option we can use width-height before load.
423
+ * @example
424
+ * ```
425
+ * import peter_the_great from './assets/peter_the_great.png?width=800&height=1200';
426
+ *
427
+ * const engine = novely({
428
+ * characters: {
429
+ * Peter: {
430
+ * name: 'Peter',
431
+ * color: '#c04931',
432
+ * emotions: {
433
+ * normal: peter_the_great
434
+ * }
435
+ * }
436
+ * },
437
+ * characterAssetSizes: {
438
+ * Peter: {
439
+ * width: 800,
440
+ * height: 1200
441
+ * }
442
+ * }
443
+ * })
444
+ * ```
445
+ */
446
+ characterAssetSizes?: CharacterAssetSizes<NoInfer<$Characters>>;
447
+ /**
448
+ * An object that provides access to the game's storage system.
449
+ * @default storageAdapterLocal({ key: 'novely-game-storage' })
450
+ */
451
+ storage?: StorageAdapter;
452
+ /**
453
+ * Delay loading data until Promise is resolved
454
+ */
455
+ storageDelay?: Promise<void>;
456
+ /**
457
+ * A function that returns a Renderer object used to display the game's content
458
+ */
459
+ renderer: (initializationData: RendererInit<NoInfer<$Language>, NoInfer<$Characters>>) => Renderer & {
460
+ actions: $Actions;
461
+ };
462
+ /**
463
+ * An optional property that specifies the initial screen to display when the game starts
464
+ */
465
+ initialScreen?: NovelyScreen;
466
+ /**
467
+ * An object containing the translation functions used in the game
468
+ * @see https://novely.pages.dev/guide/translation.html Docs
469
+ * @example
470
+ * ```ts
471
+ * import { novely, EN } from 'novely';
472
+ *
473
+ * const engine = novely({
474
+ * translation: {
475
+ * internal: EN,
476
+ * // Optional IETF BCP 47 language tag
477
+ * tag: 'en-US',
478
+ * plural: {
479
+ *
480
+ * },
481
+ * actions: {
482
+ *
483
+ * }
484
+ * }
485
+ * })
486
+ * ```
487
+ */
488
+ translation: Record<$Language, TranslationDescription>;
489
+ /**
490
+ * Initial state value
491
+ *
492
+ * State is a local value bound to one save
493
+ */
494
+ state?: $State;
495
+ /**
496
+ * Initial data value
497
+ *
498
+ * Data is a global value shared between saves
499
+ */
500
+ data?: $Data;
501
+ /**
502
+ * Enable autosaves or disable
503
+ * @default true
504
+ */
505
+ autosaves?: boolean;
506
+ /**
507
+ * Migration from old saves to newer
508
+ */
509
+ migrations?: Migration[];
510
+ /**
511
+ * For saves Novely uses `throttle` function. This might be needed if you want to control frequency of saves to the storage
512
+ * @default 850
513
+ */
514
+ throttleTimeout?: number;
515
+ /**
516
+ * Limits how many assets can be downloaded parallelly
517
+ * @default 15
518
+ */
519
+ parallelAssetsDownloadLimit?: number;
520
+ /**
521
+ * Custom language detector
522
+ * @param languages Supported languages
523
+ * @param original Original function that novely, could be used as fallback
524
+ * @example
525
+ * ```ts
526
+ * const engine = novely({
527
+ * getLanguage(languages, original) {
528
+ * if (!sdk) return original(languages);
529
+ *
530
+ * return sdk.environment.i18n.lang // i.e. custom language from some sdk
531
+ * }
532
+ * })
533
+ * ```
534
+ */
535
+ getLanguage?: (languages: NoInfer<$Language>[], original: typeof getLanguage$1) => $Language | (string & Record<never, never>);
536
+ /**
537
+ * Ignores saved language, and uses `getLanguage` to get it on every engine start
538
+ * @default false
539
+ */
540
+ overrideLanguage?: boolean;
541
+ /**
542
+ * Show a prompt before exiting a game
543
+ * @default true
544
+ */
545
+ askBeforeExit?: boolean;
546
+ /**
547
+ * "automatic" will try to preload assets when possible
548
+ *
549
+ * "lazy" will load assets only when they are shown
550
+ *
551
+ * @default "automatic"
552
+ */
553
+ preloadAssets?: AssetsPreloading;
554
+ /**
555
+ * Fetching function
556
+ */
557
+ fetch?: typeof fetch;
558
+ /**
559
+ * Function for clonning operations
560
+ */
561
+ cloneFunction?: CloneFN;
562
+ /**
563
+ * When page is going to be unloaded will call `storage.set` method
564
+ * If 'prod' is passed enable only in production env.
565
+ * @default true
566
+ */
567
+ saveOnUnload?: boolean | 'prod';
568
+ /**
569
+ * The key that signifies the start of the game. It is not recommended to override this parameter.
570
+ *
571
+ * @default 'start'
572
+ * @example
573
+ * ```ts
574
+ * const engine = novely({
575
+ * ...,
576
+ * startKey: 'PART_1'
577
+ * })
578
+ *
579
+ * engine.script({
580
+ * // now game will start from here
581
+ * PART_1: [
582
+ *
583
+ * ]
584
+ * })
585
+ * ```
586
+ */
587
+ startKey?: 'start' | (string & Record<never, never>);
588
+ /**
589
+ * Typewriter speed set by default
590
+ */
591
+ defaultTypewriterSpeed?: TypewriterSpeed;
592
+ /**
593
+ * Options to control story loading behaviour
594
+ */
595
+ storyOptions?: StoryOptions;
596
+ /**
597
+ * Will be called ONLY when language was changed by player
598
+ */
599
+ onLanguageChange?: OnLanguageChange<NoInfer<$Language>>;
600
+ }
601
+ type StateFunction<S extends State> = {
602
+ (value: DeepPartial<S> | ((prev: S) => S)): void;
603
+ (): S;
604
+ };
605
+ type EngineTypes<$Lang extends Lang = Lang, $State extends State = State, $Data extends Data = Data, $Characters extends Record<string, Character<$Lang>> = Record<string, Character<$Lang>>> = {
606
+ readonly l: $Lang;
607
+ readonly s: $State;
608
+ readonly d: $Data;
609
+ readonly c: $Characters;
610
+ };
611
+ type DialogOverviewEntry = {
612
+ /**
613
+ * Link to character voice
614
+ */
615
+ voice: string | undefined;
616
+ /**
617
+ * Character name
618
+ */
619
+ name: string;
620
+ /**
621
+ * Text that character says
622
+ */
623
+ text: string;
624
+ };
625
+ type DialogOverview = DialogOverviewEntry[];
626
+ //#endregion
627
+ //#region src/character.d.ts
628
+ type Name<$Lang extends Lang> = string | Record<$Lang, string>;
629
+ type Emotions<Emotion extends string = string> = Record<Emotion, string | NovelyAsset | (string | NovelyAsset)[]>;
630
+ type Character<$Lang extends Lang = string> = {
631
+ name: Name<$Lang>;
632
+ color: string;
633
+ emotions: Emotions;
634
+ };
635
+ //#endregion
636
+ //#region src/ticker.d.ts
637
+ type TickHandler = (ticker: Ticker) => void;
638
+ declare class Ticker {
639
+ listeners: Set<TickHandler>;
640
+ running: boolean;
641
+ private _factory;
642
+ constructor(factory: TickerFactory);
643
+ get deltaTime(): number;
644
+ get lastTime(): number;
645
+ add(cb: (ticker: Ticker) => void): () => void;
646
+ remove(cb: (ticker: Ticker) => void): void;
647
+ start: () => void;
648
+ stop: () => void;
649
+ detach: () => void;
650
+ }
651
+ declare class TickerFactory {
652
+ private _children;
653
+ private _raf;
654
+ private _running;
655
+ private _unsubscribe;
656
+ deltaTime: number;
657
+ lastTime: number;
658
+ constructor(paused: Derived<boolean>);
659
+ start(): void;
660
+ stop(): void;
661
+ fork(): Ticker;
662
+ check(positive: boolean): void;
663
+ destroy(): void;
664
+ detach(ticker: Ticker): void;
665
+ private update;
666
+ }
667
+ //#endregion
668
+ //#region src/action.d.ts
669
+ type ValidAction = ['choice', string | undefined, ...[string, unknown[], (() => boolean)?, (() => boolean)?, string?][]] | ['clear', Set<keyof DefaultActionProxy>?, Set<string>?, {
670
+ music: Set<string>;
671
+ sounds: Set<string>;
672
+ }?] | ['condition', (state: State) => boolean, Record<string, ValidAction[]>] | ['dialog', string | undefined, TextContent<string, State>, string | undefined] | ['end'] | ['showBackground', string | NovelyAsset | BackgroundImage] | ['playMusic', string | NovelyAsset] | ['stopMusic', string | NovelyAsset] | ['pauseMusic', string | NovelyAsset] | ['playSound', audio: string | NovelyAsset, loop?: boolean] | ['pauseSound', string | NovelyAsset] | ['stopSound', string | NovelyAsset] | ['voice', string | NovelyAsset | Record<string, string | NovelyAsset>] | ['stopVoice'] | ['jump', string] | ['showCharacter', string, keyof Character['emotions'], string?, string?] | ['hideCharacter', string, string?, string?, number?] | ['animateCharacter', string, number, ...string[]] | ['wait', number | ((state: State) => number)] | ['function', FunctionAction<string, State>] | ['input', string, (meta: ActionInputOnInputMeta<string, State>) => void, ActionInputSetup?] | ['custom', CustomHandler<string, State>] | ['vibrate', ...number[]] | ['next'] | ['text', ...TextContent<string, State>[]] | ['exit'] | ['preload', string | NovelyAsset] | ['block', string] | ValidAction[];
673
+ type Story = Record<string, ValidAction[]>;
674
+ type TextContent<L extends string, S extends State> = string | ((state: S) => string) | Record<L, string | ((state: S) => string)>;
675
+ type FunctionableValue<T> = T | (() => T);
676
+ type CustomHandlerGetResultDataFunction = <T = Record<string, unknown>>(data?: T) => T;
677
+ type CustomHandlerGetResult<I extends boolean> = {
678
+ /**
679
+ * Element for the custom action to be rendered into
680
+ */
681
+ element: I extends true ? HTMLDivElement : null;
682
+ /**
683
+ * Root node
684
+ */
685
+ root: HTMLElement;
686
+ };
687
+ type OnForwardFnParams = {
688
+ isUserRequiredAction: boolean;
689
+ isBlockingAction: boolean;
690
+ action: Exclude<ValidAction, ValidAction[]>;
691
+ };
692
+ type OnForwardFn = (params: OnForwardFnParams) => void;
693
+ type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
694
+ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
695
+ /**
696
+ * Returns:
697
+ * - Root where entire novely is mounted
698
+ * - Element in which custom action could be mounted
699
+ *
700
+ * @example
701
+ * ```ts
702
+ * // pass `true` to insert element to the DOM
703
+ * const { root, element } = getDomNodes(true);
704
+ * ```
705
+ */
706
+ getDomNodes: CustomHandlerFunctionGetFn;
707
+ /**
708
+ * Function to get current Save. It can be mutated. Only use it when you know what you do
709
+ *
710
+ * @deprecated
711
+ */
712
+ getSave: () => Save<S>;
713
+ /**
714
+ * Renderer Context
715
+ */
716
+ rendererContext: Context;
717
+ /**
718
+ * Context key in which action is running
719
+ */
720
+ contextKey: string;
721
+ /**
722
+ * Function to work with custom action's state
723
+ *
724
+ * @example
725
+ * ```ts
726
+ * type Data = { name: string };
727
+ *
728
+ * const handler: CustomHandler = async ({ data }) => {
729
+ * const _data = data<Data>();
730
+ *
731
+ * if (!_data.name) {
732
+ * _data.name = 'Mr. Crabs'
733
+ * }
734
+ *
735
+ * data<Data>().name // 'Mr. Crabs'
736
+ *
737
+ * data<Data>() == _data // true
738
+ *
739
+ * // passing object will replace object
740
+ * data<Data>({ name: 'Mr. Crabs' })
741
+ * data<Data>() == _data // false
742
+ * }
743
+ * ```
744
+ */
745
+ data: CustomHandlerGetResultDataFunction;
746
+ /**
747
+ * Function to access data stored at specific key.
748
+ * @example
749
+ * ```ts
750
+ * const handler: CustomHandler = async ({ dataAtKey }) => {
751
+ * // peek at data at action with key 'action-2'
752
+ * console.log(dataAtKey('action-2'))
753
+ * }
754
+ *
755
+ * handler.key = 'action-1'
756
+ * ```
757
+ * @deprecated
758
+ */
759
+ dataAtKey: <T extends Record<string, unknown>>(key: string) => T | null;
760
+ /**
761
+ * Function to register cleanup callbacks (executed in reverse order of registration).
762
+ *
763
+ * @example
764
+ * ```ts
765
+ * const handler: CustomHandler = async ({ clear, paused }) => {
766
+ * const unsubscribe = paused.subscribe((paused) => {
767
+ *
768
+ * })
769
+ *
770
+ * clear(paused);
771
+ * }
772
+ * ```
773
+ */
774
+ clear: (fn: () => void) => void;
775
+ /**
776
+ * Overwrites `onBack` callback. Callback will be called after clearing some actions, but before starting others.
777
+ *
778
+ * @example
779
+ * ```ts
780
+ * const handler: CustomHandler = ({ getDomNodes, state, onBack }) => {
781
+ * // some code
782
+ * const update = () => button.textContent = `Clicks: ${state().clicks}`;
783
+ *
784
+ * onBack(() => {
785
+ * console.log('Backing up');
786
+ * // sync state with UI
787
+ * update();
788
+ * })
789
+ * }
790
+ * ```
791
+ */
792
+ onBack: (fn: () => void) => void;
793
+ /**
794
+ * Overwrites `onForward` callback. Callback will be called before executing next action.
795
+ *
796
+ * @example
797
+ * ```ts
798
+ * const handler: CustomHandler = ({ getDomNodes, state, onForward }) => {
799
+ * onForward(({ action, isBlockingAction, isUserRequiredAction }) => {
800
+ * console.log(action)
801
+ * console.log({ isBlockingAction, isUserRequiredAction })
802
+ * })
803
+ * }
804
+ * ```
805
+ */
806
+ onForward: (fn: OnForwardFn) => void;
807
+ /**
808
+ * It will call all clear actions and remove HTML element from `getDomNodes` function
809
+ */
810
+ remove: () => void;
811
+ /**
812
+ * State function
813
+ */
814
+ state: StateFunction<S>;
815
+ /**
816
+ * Game state
817
+ */
818
+ flags: {
819
+ restoring: boolean;
820
+ goingBack: boolean;
821
+ preview: boolean;
822
+ };
823
+ /**
824
+ * Game language
825
+ */
826
+ lang: L;
827
+ /**
828
+ * Function to replace template content
829
+ *
830
+ * @example
831
+ * ```ts
832
+ * const handler: CustomHandler = async ({ state, templateReplace }) => {
833
+ * const text = templateReplace({ en: '' }, state())
834
+ * }
835
+ * ```
836
+ */
837
+ templateReplace: (content: TextContent<L, State>, values?: State) => string;
838
+ /**
839
+ * Is game currently paused
840
+ *
841
+ * @example
842
+ * ```ts
843
+ * const handler: CustomHandler = async ({ clear, paused }) => {
844
+ * const unsubscribe = paused.subscribe((paused) => {
845
+ * // Here you can pause/resume animations, sounds, etc, etc
846
+ * })
847
+ *
848
+ * clear(paused);
849
+ * }
850
+ */
851
+ paused: Derived<boolean>;
852
+ /**
853
+ * Ticker
854
+ *
855
+ * @example
856
+ * ```ts
857
+ * const handler: CustomHandler = async ({ clear, ticker }) => {
858
+ * const unsubscribe = ticker.add((ticker) => {
859
+ * console.log(ticker.deltaTime);
860
+ * })
861
+ *
862
+ * ticker.start();
863
+ *
864
+ * clear(unsubscribe);
865
+ * }
866
+ * ```
867
+ */
868
+ ticker: Ticker;
869
+ /**
870
+ * Fetching function.
871
+ * @default fetch
872
+ */
873
+ request: typeof fetch;
874
+ };
875
+ type CustomHandlerFunction<L extends string, S extends State> = (parameters: CustomHandlerFunctionParameters<L, S>) => Thenable<void>;
876
+ type CustomHandlerCalling = {
877
+ /**
878
+ * Call only the last custom action of this type or not. Does not affect other custom actions
879
+ * @example
880
+ * ```ts
881
+ * ['custom', customSomething1]
882
+ * ['custom', customSomething1]
883
+ * ['custom', customSomething1] <-- Run only that
884
+ * ```
885
+ */
886
+ callOnlyLatest?: boolean;
887
+ /**
888
+ * Manually check should be skipped or not during restore
889
+ * @param nextActions Next actions in the restoring queue
890
+ */
891
+ skipOnRestore?: (nextActions: Exclude<ValidAction, ValidAction[]>[]) => boolean;
892
+ };
893
+ /**
894
+ * Array of URL or NovelyAsset
895
+ */
896
+ type ResolvedAssets = (NovelyAsset | string)[];
897
+ type AssetsResolverArgs = {
898
+ /**
899
+ * Fetching function
900
+ */
901
+ request: typeof fetch;
902
+ };
903
+ /**
904
+ * Function to get assets
905
+ */
906
+ type AssetsResolver = (args: AssetsResolverArgs) => Thenable<ResolvedAssets>;
907
+ type CustomHandlerInfo = CustomHandlerCalling & {
908
+ /**
909
+ * Assets used by action. When preload is "automatic", will be preloaded before action runs.
910
+ *
911
+ * In case function is provided, execution time is limited to 250ms,
912
+ * then returned assets or empty array (when limited)
913
+ * will always be used with that action
914
+ *
915
+ * @example
916
+ * ```ts
917
+ * handler.assets = [url]
918
+ * handler.assets = async ({ request }) => {
919
+ * return [url]
920
+ * }
921
+ * ```
922
+ */
923
+ assets?: ResolvedAssets | AssetsResolver;
924
+ /**
925
+ * When true interacting with it will be saved in history
926
+ */
927
+ requireUserAction?: boolean;
928
+ /**
929
+ * Id by which we will determine what action is which
930
+ */
931
+ id: string | symbol;
932
+ /**
933
+ * Key by which we will save the custom action's data. It includes cleanup function's provided by `clear` and data in `data` function
934
+ *
935
+ * It can be a name of action or more specific thing. In example for custom `showCharacter` it may be `show-character-${character}
936
+ */
937
+ key: string;
938
+ };
939
+ type CustomHandler<L extends string = string, S extends State = State> = CustomHandlerFunction<L, S> & CustomHandlerInfo;
940
+ interface ActionInputOnInputMeta<L extends string, S extends State> {
941
+ /**
942
+ * Input Element itself
943
+ */
944
+ input: HTMLInputElement;
945
+ /**
946
+ * Function to show error message or hide it
947
+ * @param error Error message or empty string to remove it
948
+ */
949
+ error: (error: string) => void;
950
+ /**
951
+ * Input Event
952
+ */
953
+ event: InputEvent & {
954
+ currentTarget: HTMLInputElement;
955
+ };
956
+ /**
957
+ * Sanitized `input.value`
958
+ */
959
+ value: string;
960
+ /**
961
+ * Language
962
+ */
963
+ lang: L;
964
+ /**
965
+ * State function
966
+ */
967
+ state: StateFunction<S>;
968
+ }
969
+ type FunctionActionProps<L extends Lang, S extends State> = {
970
+ restoring: boolean;
971
+ goingBack: boolean;
972
+ preview: boolean;
973
+ /**
974
+ * Language
975
+ */
976
+ lang: L;
977
+ /**
978
+ * State function
979
+ */
980
+ state: StateFunction<S>;
981
+ };
982
+ type ChoiceCheckFunctionProps<L extends Lang, S extends State> = {
983
+ /**
984
+ * Language
985
+ */
986
+ lang: L;
987
+ /**
988
+ * State
989
+ */
990
+ state: S;
991
+ };
992
+ type ChoiceOnSelectFunctionProps = {
993
+ /**
994
+ * Triggers `active` and `visible` properties computation
995
+ */
996
+ recompute: () => void;
997
+ };
998
+ type ChoiceCheckFunction<L extends Lang, S extends State> = (props: ChoiceCheckFunctionProps<L, S>) => boolean;
999
+ type ChoiceOnSelectFunction = (props: ChoiceOnSelectFunctionProps) => void;
1000
+ type ConditionCheckFunction<S extends State, R extends string | true | false> = (state: S) => R;
1001
+ type FunctionAction<L extends string, S extends State> = (props: FunctionActionProps<L, S>) => Thenable<void>;
1002
+ type ActionInputSetupCleanup = () => void;
1003
+ type ActionInputSetup = (input: HTMLInputElement) => ActionInputSetupCleanup | void;
1004
+ type BackgroundImage = Record<string, string | NovelyAsset>;
1005
+ type VoiceAction<L extends Lang> = (params: string | NovelyAsset | Partial<Record<L, string | NovelyAsset>>) => ValidAction;
1006
+ type ActionChoiceChoiceObject<L extends Lang, S extends State> = {
1007
+ title: TextContent<L, S>;
1008
+ children: ValidAction[];
1009
+ active?: ChoiceCheckFunction<L, S>;
1010
+ visible?: ChoiceCheckFunction<L, S>;
1011
+ onSelect?: ChoiceOnSelectFunction;
1012
+ image?: string | NovelyAsset;
1013
+ };
1014
+ type ActionChoiceChoice<L extends Lang, S extends State> = [title: TextContent<L, S>, actions: ValidAction[], active?: ChoiceCheckFunction<L, S>, visible?: ChoiceCheckFunction<L, S>, onSelect?: ChoiceOnSelectFunction, image?: string | NovelyAsset];
1015
+ type ActionProxy<Characters extends Record<string, Character>, Languages extends Lang, S extends State> = {
1016
+ choice: {
1017
+ (...choices: ActionChoiceChoice<Languages, S>[]): ValidAction;
1018
+ (question: TextContent<Languages, S>, ...choices: ActionChoiceChoice<Languages, S>[]): ValidAction;
1019
+ };
1020
+ clear: (keep?: Set<keyof DefaultActionProxy>, keepCharacters?: Set<string>, keepAudio?: {
1021
+ music: Set<string>;
1022
+ sounds: Set<string>;
1023
+ }) => ValidAction;
1024
+ condition: <T extends string | true | false>(condition: ConditionCheckFunction<S, T>, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
1025
+ exit: () => ValidAction;
1026
+ dialog: {
1027
+ <C extends keyof Characters>(character: C, content: TextContent<Languages, S>, emotion?: keyof Characters[C]['emotions']): ValidAction;
1028
+ (character: undefined, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
1029
+ (character: string, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
1030
+ };
1031
+ end: () => ValidAction;
1032
+ showBackground: {
1033
+ (background: string | NovelyAsset): ValidAction;
1034
+ <T extends Record<string, string | NovelyAsset>>(background: NonEmptyRecord<T>): ValidAction;
1035
+ };
1036
+ playMusic: (audio: string | NovelyAsset) => ValidAction;
1037
+ pauseMusic: (audio: string | NovelyAsset) => ValidAction;
1038
+ stopMusic: (audio: string | NovelyAsset) => ValidAction;
1039
+ playSound: (audio: string | NovelyAsset, loop?: boolean) => ValidAction;
1040
+ pauseSound: (audio: string | NovelyAsset) => ValidAction;
1041
+ stopSound: (audio: string | NovelyAsset) => ValidAction;
1042
+ /**
1043
+ * Plays voice
1044
+ *
1045
+ * @example
1046
+ * ```
1047
+ * engine.script({
1048
+ * start: [
1049
+ * engine.action.voice('./rick-astley-never-gonna-give-you-up.mp3'),
1050
+ * engine.action.say('Rick', 'Never gonna give you up'),
1051
+ * ]
1052
+ * })
1053
+ * ```
1054
+ */
1055
+ voice: VoiceAction<Languages>;
1056
+ /**
1057
+ * Stops currently playing voice
1058
+ */
1059
+ stopVoice: () => ValidAction;
1060
+ jump: (scene: string) => ValidAction;
1061
+ showCharacter: <C extends keyof Characters>(character: C, emotion?: keyof Characters[C]['emotions'], className?: string, style?: string) => ValidAction;
1062
+ hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
1063
+ animateCharacter: (character: keyof Characters, classes: string) => ValidAction;
1064
+ wait: (time: number | ((state: State) => number)) => ValidAction;
1065
+ function: (fn: FunctionAction<Languages, S>) => ValidAction;
1066
+ input: (question: TextContent<Languages, S>, onInput: (meta: ActionInputOnInputMeta<Languages, S>) => void, setup?: ActionInputSetup) => ValidAction;
1067
+ custom: (handler: CustomHandler<Languages, S> | CustomHandler) => ValidAction;
1068
+ vibrate: (...pattern: number[]) => ValidAction;
1069
+ next: () => ValidAction;
1070
+ text: (...text: TextContent<Languages, S>[]) => ValidAction;
1071
+ preload: (source: string | NovelyAsset) => ValidAction;
1072
+ block: (scene: string) => ValidAction;
1073
+ };
1074
+ type DefaultActionProxy = ActionProxy<Record<string, Character>, Lang, State>;
1075
+ type GetActionParameters<T extends Capitalize<keyof DefaultActionProxy>> = Parameters<DefaultActionProxy[Uncapitalize<T>]>;
1076
+ type VirtualActions<$Characters extends Record<string, Character>, $Lang extends Lang, $State extends State> = {
1077
+ choice: (question: TextContent<$Lang, $State>, ...choices: ActionChoiceChoiceObject<$Lang, $State>[]) => ValidAction;
1078
+ say: (character: keyof $Characters, content: TextContent<$Lang, $State>) => ValidAction;
1079
+ };
1080
+ //#endregion
1081
+ //#region src/type-utils.d.ts
1082
+ type ConditionParams<T> = T extends EngineTypes<any, infer $State, any, any> ? $State : never;
1083
+ type ChoiceParams<T> = T extends EngineTypes<infer $Lang, infer $State, any, any> ? ChoiceCheckFunctionProps<$Lang, $State> : never;
1084
+ type FunctionParams<T> = T extends EngineTypes<infer $Lang, infer $State, any, any> ? FunctionActionProps<$Lang, $State> : never;
1085
+ type InputHandler<T> = T extends EngineTypes<infer $Lang, infer $State, any, any> ? ActionInputOnInputMeta<$Lang, $State> : never;
1086
+ /**
1087
+ * @example
1088
+ * ```ts
1089
+ * type Types = TypesFromEngine<typeof engine>;
1090
+ * ```
1091
+ */
1092
+ type TypesFromEngine<T> = T extends {
1093
+ types: EngineTypes<infer $Lang, infer $State, infer $Data, infer $Characters> | null;
1094
+ } ? EngineTypes<$Lang, $State, $Data, $Characters> : never;
1095
+ //#endregion
1096
+ //#region src/novely.d.ts
1097
+ declare const novely: <$Language extends string, $Characters extends Record<string, Character<$Language>>, $State extends State, $Data extends Data, $Actions extends Record<string, (...args: any[]) => ValidAction>>({
1098
+ characters,
1099
+ characterAssetSizes,
1100
+ defaultEmotions,
1101
+ storage,
1102
+ storageDelay,
1103
+ renderer: createRenderer,
1104
+ initialScreen,
1105
+ translation,
1106
+ state: defaultState,
1107
+ data: defaultData,
1108
+ autosaves,
1109
+ migrations,
1110
+ throttleTimeout,
1111
+ getLanguage,
1112
+ overrideLanguage,
1113
+ askBeforeExit,
1114
+ preloadAssets,
1115
+ parallelAssetsDownloadLimit,
1116
+ fetch: request,
1117
+ cloneFunction: clone,
1118
+ saveOnUnload,
1119
+ startKey,
1120
+ defaultTypewriterSpeed,
1121
+ storyOptions,
1122
+ onLanguageChange
1123
+ }: NovelyInit<$Language, $Characters, $State, $Data, $Actions>) => {
1124
+ /**
1125
+ * Function to set game script
1126
+ *
1127
+ * @example
1128
+ * ```ts
1129
+ * engine.script({
1130
+ * start: [
1131
+ * action.function(() => {})
1132
+ * ]
1133
+ * })
1134
+ * ```
1135
+ */
1136
+ script: (part: Story) => Promise<void>;
1137
+ /**
1138
+ * Get actions
1139
+ *
1140
+ * @example
1141
+ * ```ts
1142
+ * engine.script({
1143
+ * start: [
1144
+ * action.function(() => {})
1145
+ * ]
1146
+ * })
1147
+ * ```
1148
+ */
1149
+ action: $Actions & ActionProxy<$Characters, $Language, $State> & VirtualActions<$Characters, $Language, $State>;
1150
+ /**
1151
+ * State bound to `$MAIN` game context
1152
+ * @deprecated Use `state` function provided from action arguments
1153
+ */
1154
+ state: StateFunction<State>;
1155
+ /**
1156
+ * Store data between games
1157
+ *
1158
+ * @example
1159
+ * ```ts
1160
+ * engine.script({
1161
+ * start: [
1162
+ * action.function(() => {
1163
+ * // Paid content should be purchased only once
1164
+ * // So it will be available in any save
1165
+ * data({ paid_content_purchased: true })
1166
+ * })
1167
+ * ]
1168
+ * })
1169
+ * ```
1170
+ */
1171
+ data: StateFunction<$Data>;
1172
+ /**
1173
+ * Used in combination with type utilities
1174
+ * @example
1175
+ * ```ts
1176
+ * import type { TypesFromEngine, ConditionParams, StateFunction } from '@novely/core';
1177
+ *
1178
+ * type Types = TypesFromEngine<typeof engine>;
1179
+ *
1180
+ * const conditionCheck = (state: StateFunction<ConditionParams<Types>>) => {
1181
+ * return state.age >= 18;
1182
+ * }
1183
+ * ```
1184
+ */
1185
+ types: EngineTypes<$Language, $State, $Data, $Characters> | null;
1186
+ /**
1187
+ * Replaces content inside {{braces}} using global data
1188
+ * @example
1189
+ * ```ts
1190
+ * data({ name: 'Alexei' })
1191
+ *
1192
+ * templateReplace('{{name}} is our hero')
1193
+ * templateReplace({
1194
+ * en: (data) => 'Hello, ' + data.name
1195
+ * })
1196
+ * ```
1197
+ */
1198
+ templateReplace(content: TextContent<$Language, $Data>): string;
1199
+ /**
1200
+ * Same as `templateReplace` but uses state and requires explicitly providing it
1201
+ */
1202
+ templateReplaceState(content: TextContent<$Language, $State>, state: State): string;
1203
+ /**
1204
+ * Cancel data loading, hide UI, ignore page change events
1205
+ * Data updates still will work in case Novely already was loaded
1206
+ */
1207
+ destroy(): void;
1208
+ /**
1209
+ * Funtion to get current storage data
1210
+ *
1211
+ * @example
1212
+ * ```ts
1213
+ * const currentStorageData = engine.getCurrentStorageData();
1214
+ * ```
1215
+ */
1216
+ getCurrentStorageData: () => StorageData<$Language, $Data> | null;
1217
+ /**
1218
+ * Function to set storage data. Using this function is not recommended.
1219
+ *
1220
+ * @deprecated
1221
+ * @example
1222
+ * ```ts
1223
+ * const currentStorageData = engine.getCurrentStorageData();
1224
+ *
1225
+ * if (currentStorageData) {
1226
+ * // update music volume
1227
+ * currentStorageData.meta[2] = 1;
1228
+ *
1229
+ * setStorageData(currentStorageData)
1230
+ * }
1231
+ * ```
1232
+ */
1233
+ setStorageData: (data: StorageData<$Language, $Data>) => void;
1234
+ /**
1235
+ * Function to control paused state. Custom Actions are provided with `paused` store they can subscribe to.
1236
+ * This function will notify Custom Actions. Pause state can be used when showing ads.
1237
+ * @example
1238
+ * ```ts
1239
+ * sdk.on('pause' () => engine.setPaused(true));
1240
+ * sdk.on('resume', () => engine.setPaused(false));
1241
+ * ```
1242
+ */
1243
+ setPaused: (paused: boolean) => void;
1244
+ /**
1245
+ * Function to control focused state. It will affect `paused` store passed to Custom Actions.
1246
+ * This function can be used to pause game when it's not focused.
1247
+ * @example
1248
+ * ```ts
1249
+ * import { pauseOnBlur } from '@novely/core';
1250
+ *
1251
+ * // Will subscribe to blur/focus events and call `setFocused`
1252
+ * pauseOnBlur(engine);
1253
+ *
1254
+ * // OR
1255
+ *
1256
+ * sdk.on('focus' () => engine.setFocused(true));
1257
+ * sdk.on('blur', () => engine.setFocused(false));
1258
+ * ```
1259
+ */
1260
+ setFocused: (focused: boolean) => void;
1261
+ };
1262
+ //#endregion
1263
+ //#region src/extend-actions.d.ts
1264
+ type Part = Record<string, (...args: any[]) => ValidAction>;
1265
+ /**
1266
+ * Extens core action with custom actions
1267
+ * @param base Actions object you will extend, `engine.action`
1268
+ * @param extension Actions object you will extend with
1269
+ * @example
1270
+ * ```ts
1271
+ * const action = extendAction(engine.action, {
1272
+ * particles: (options: Parameters<typeof particles>[0]) => {
1273
+ * return ['custom', particles(options)]
1274
+ * }
1275
+ * })
1276
+ * ```
1277
+ */
1278
+ declare const extendAction: <Part0 extends Part, Part1 extends Part>(base: Part0, extension: Part1) => Readonly<Assign<Part0, Part1>>;
1279
+ //#endregion
1280
+ //#region src/asset.d.ts
1281
+ /**
1282
+ * Memoizes and returns an asset selection object based on provided file variants.
1283
+ * The selected asset depends on the client's support for various formats.
1284
+ *
1285
+ * @param {...string} variants - A variable number of strings, each representing a potential asset file URL.
1286
+ * @returns {NovelyAsset} An object representing the selected asset with `source` and `type` properties.
1287
+ *
1288
+ * @throws {Error} If in DEV mode and no arguments are provided.
1289
+ * @example
1290
+ * ```
1291
+ * import { asset } from 'novely';
1292
+ *
1293
+ * // Passed first have higher priority
1294
+ * const classroom = asset(
1295
+ * 'classroom.avif',
1296
+ * 'classroom.webp',
1297
+ * 'classroom.jpeg'
1298
+ * );
1299
+ *
1300
+ * setTimeout(() => {
1301
+ * console.log(classroom.source);
1302
+ * }, 100);
1303
+ * ```
1304
+ */
1305
+ declare const asset: {
1306
+ (...variants: string[]): NovelyAsset;
1307
+ image(source: string): NovelyAsset;
1308
+ audio(source: string): NovelyAsset;
1309
+ };
1310
+ //#endregion
1311
+ //#region src/browser-events.d.ts
1312
+ declare const pauseOnBlur: (engine: {
1313
+ setFocused: (focused: boolean) => void;
1314
+ }) => {
1315
+ unsubscribe: () => void;
1316
+ };
1317
+ //#endregion
1318
+ export { type ActionChoiceChoice, type ActionChoiceChoiceObject, type ActionInputOnInputMeta, type ActionInputSetup, type ActionInputSetupCleanup, type ActionProxy, type AllowedContent, type AudioHandle, type BackgroundImage, type BaseTranslationStrings, type Character, type CharacterAssetSizes, type CharacterHandle, type CharactersData, type ChoiceCheckFunction, type ChoiceCheckFunctionProps, type ChoiceOnSelectFunction, type ChoiceOnSelectFunctionProps, type ChoiceParams, type ConditionCheckFunction, type ConditionParams, type Context, type CoreData, type CustomActionHandle, type CustomHandler, type CustomHandlerFunction, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type CustomHandlerInfo, type Data, type DeepPartial, type DefaultActionProxy, type Derived, EN, type Emotions, type EngineTypes, type FunctionParams, type FunctionableValue, type GetActionParameters, type InputHandler, type Lang, type NovelyAsset, type NovelyInit, type NovelyScreen, type Path, type PathItem, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type RendererInitPreviewReturn, type Save, type Stack, type StackHolder, type State, type StateFunction, type StorageAdapter, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type Ticker, type TranslationActions, type TypesFromEngine, type TypewriterSpeed, type ValidAction, asset, extendAction, novely, pauseOnBlur, storageAdapterLocal };
1319
+ //# sourceMappingURL=index.d.mts.map