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