@novely/core 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@ declare const localStorageStorage: (options: LocalStorageStorageSettings) => Sto
17
17
 
18
18
  type PluralType = Intl.LDMLPluralRule;
19
19
  type Pluralization = Partial<Record<PluralType, string>>;
20
- type AllowedContent = string | (() => string | string[]) | string[] | (string | (() => string | string[]))[];
20
+ type AllowedContent = string | ((state: State) => string | string[]) | string[] | (string | ((state: State) => string | string[]))[];
21
21
  type TranslationActions = Partial<Record<string, (str: string) => string>>;
22
22
 
23
23
  declare const RU: {
@@ -138,14 +138,14 @@ type Renderer = {
138
138
  character: (character: string) => CharacterHandle;
139
139
  background: (background: string | BackgroundImage) => void;
140
140
  dialog: (content: string, name: string, character: string | undefined, emotion: string | undefined, resolve: () => void) => void;
141
- choices: (question: string, choices: ([string, ValidAction[]] | [string, ValidAction[], () => boolean])[], resolve: (selected: number) => void) => void;
142
- input: (question: string, onInput: (meta: ActionInputOnInputMeta<string>) => void, setup: ActionInputSetup, resolve: () => void) => void;
143
- clear: (keep: Set<keyof DefaultActionProxyProvider>, keepCharacters: Set<string>, keepAudio: {
141
+ choices: (question: string, choices: [name: string, actions: ValidAction[], active?: boolean][], resolve: (selected: number) => void) => void;
142
+ input: (question: string, onInput: (meta: ActionInputOnInputMeta<string, State>) => void, setup: ActionInputSetup, resolve: () => void) => void;
143
+ clear: (keep: Set<keyof DefaultActionProxy>, keepCharacters: Set<string>, keepAudio: {
144
144
  music: Set<string>;
145
145
  sounds: Set<string>;
146
146
  }, resolve: () => void) => void;
147
- custom: (fn: Parameters<DefaultActionProxyProvider['custom']>[0], push: () => void) => Thenable<void>;
148
- clearCustom: (fn: Parameters<DefaultActionProxyProvider['custom']>[0]) => void;
147
+ custom: (fn: Parameters<DefaultActionProxy['custom']>[0], push: () => void) => Thenable<void>;
148
+ clearCustom: (fn: Parameters<DefaultActionProxy['custom']>[0]) => void;
149
149
  text: (str: string, resolve: () => void) => void;
150
150
  vibrate: (pattern: VibratePattern) => void;
151
151
  audio: {
@@ -206,6 +206,7 @@ type RendererInit = {
206
206
  mainContextKey: string;
207
207
  preview: (save: Save, name: string) => Promise<void>;
208
208
  removeContext: (name: string) => void;
209
+ getStateFunction: (context: string) => StateFunction<State>;
209
210
  };
210
211
 
211
212
  declare const getLanguage: (languages: string[]) => string;
@@ -218,16 +219,26 @@ type Data = Record<string, any>;
218
219
  type SaveDate = number;
219
220
  type SaveType = 'manual' | 'auto';
220
221
  type SaveMeta = [date: SaveDate, type: SaveType];
221
- type Save = [path: Path, state: State, meta: SaveMeta];
222
+ type Save<S extends State = State> = [
223
+ path: Path,
224
+ state: S,
225
+ meta: SaveMeta
226
+ ];
222
227
  type Lang = string;
223
228
  type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
224
229
  type SoundVolume = number;
225
- type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
230
+ type StorageMeta<L extends string = string> = [
231
+ lang: L,
232
+ typewriter_speed: TypewriterSpeed,
233
+ music_volume: SoundVolume,
234
+ sound_volume: SoundVolume,
235
+ voice_volume: SoundVolume
236
+ ];
226
237
  type Migration = (save: unknown) => unknown;
227
- type StorageData = {
238
+ type StorageData<L extends string = string, D extends Data = Data> = {
228
239
  saves: Save[];
229
- data: Data;
230
- meta: StorageMeta;
240
+ data: D;
241
+ meta: StorageMeta<L>;
231
242
  };
232
243
  type Stack = {
233
244
  value: Save;
@@ -383,11 +394,24 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
383
394
  * Fetching function
384
395
  */
385
396
  fetch?: typeof fetch;
397
+ /**
398
+ * When page is going to be unloaded will call `storage.set` method
399
+ * If 'prod' is passed enable only in production env.
400
+ * @default true
401
+ */
402
+ saveOnUnload?: boolean | 'prod';
386
403
  }
404
+ type StateFunction<S extends State> = {
405
+ (value: DeepPartial<S> | ((prev: S) => S)): void;
406
+ (): S;
407
+ };
387
408
 
388
- type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta<string>) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
409
+ type ValidAction = ['choice', number] | ['clear', Set<keyof DefaultActionProxy>?, Set<string>?, {
410
+ music: Set<string>;
411
+ sounds: Set<string>;
412
+ }?] | ['condition', (state: State) => boolean, Record<string, ValidAction[]>] | ['dialog', string | undefined, TextContent<string, State>, string | undefined] | ['say', string, TextContent<string, State>] | ['end'] | ['showBackground', string | NonEmptyRecord<BackgroundImage>] | ['playMusic', string] | ['stopMusic', string] | ['playSound', audio: string, loop?: boolean] | ['voice', string] | ['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] | ['block', string] | ValidAction[];
389
413
  type Story = Record<string, ValidAction[]>;
390
- type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
414
+ type TextContent<L extends string, S extends State> = string | ((state: S) => string) | Record<L, string | ((state: S) => string)>;
391
415
  type FunctionableValue<T> = T | (() => T);
392
416
  type CustomHandlerGetResultDataFunction = {
393
417
  (data?: Record<string, unknown>): Record<string, unknown>;
@@ -412,21 +436,22 @@ type CustomHandlerGetResult<I extends boolean> = {
412
436
  clear: (fn: () => void) => void;
413
437
  };
414
438
  type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
415
- type CustomHandlerFunctionParameters = {
439
+ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
416
440
  get: CustomHandlerFunctionGetFn;
441
+ state: StateFunction<S>;
417
442
  goingBack: boolean;
418
443
  preview: boolean;
419
- lang: string;
444
+ lang: L;
420
445
  };
421
- type CustomHandlerFunction = (parameters: CustomHandlerFunctionParameters) => Thenable<void>;
422
- type CustomHandler = CustomHandlerFunction & {
446
+ type CustomHandlerFunction<L extends string, S extends State> = (parameters: CustomHandlerFunctionParameters<L, S>) => Thenable<void>;
447
+ type CustomHandler<L extends string = string, S extends State = State> = CustomHandlerFunction<L, S> & {
423
448
  callOnlyLatest?: boolean;
424
449
  requireUserAction?: boolean;
425
450
  skipClearOnGoingBack?: boolean;
426
451
  id?: string | symbol;
427
452
  key: string;
428
453
  };
429
- interface ActionInputOnInputMeta<L extends string> {
454
+ interface ActionInputOnInputMeta<L extends string, S extends State> {
430
455
  /**
431
456
  * Input Element itself
432
457
  */
@@ -450,25 +475,57 @@ interface ActionInputOnInputMeta<L extends string> {
450
475
  * Language
451
476
  */
452
477
  lang: L;
478
+ /**
479
+ * State function
480
+ */
481
+ state: StateFunction<S>;
453
482
  }
483
+ type FunctionActionProps<L extends string, S extends State> = {
484
+ restoring: boolean;
485
+ goingBack: boolean;
486
+ preview: boolean;
487
+ /**
488
+ * Language
489
+ */
490
+ lang: L;
491
+ /**
492
+ * State function
493
+ */
494
+ state: StateFunction<S>;
495
+ };
496
+ type ChoiceCheckFunctionProps<L extends string, S extends State> = {
497
+ /**
498
+ * Language
499
+ */
500
+ lang: L;
501
+ /**
502
+ * State
503
+ */
504
+ state: S;
505
+ };
506
+ type ChoiceCheckFunction<L extends string, S extends State> = {
507
+ (props: ChoiceCheckFunctionProps<L, S>): boolean;
508
+ };
509
+ type FunctionAction<L extends string, S extends State> = (props: FunctionActionProps<L, S>) => Thenable<void>;
454
510
  type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
455
511
  type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
456
- type ActionProxyProvider<Characters extends Record<string, Character>, Languages extends string> = {
512
+ type ActionProxy<Characters extends Record<string, Character>, Languages extends string, S extends State> = {
457
513
  choice: {
458
- (...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
459
- (question: Unwrappable<Languages>, ...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
514
+ (...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
515
+ (question: TextContent<Languages, S>, ...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
460
516
  };
461
- clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>, keepAudio?: {
517
+ clear: (keep?: Set<keyof DefaultActionProxy>, keepCharacters?: Set<string>, keepAudio?: {
462
518
  music: Set<string>;
463
519
  sounds: Set<string>;
464
520
  }) => ValidAction;
465
- condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
521
+ condition: <T extends string | true | false>(condition: (state: S) => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
466
522
  exit: () => ValidAction;
467
523
  dialog: {
468
- <C extends keyof Characters>(person: C, content: Unwrappable<Languages>, emotion?: keyof Characters[C]['emotions']): ValidAction;
469
- (person: undefined, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
470
- (person: string, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
524
+ <C extends keyof Characters>(character: C, content: TextContent<Languages, S>, emotion?: keyof Characters[C]['emotions']): ValidAction;
525
+ (character: undefined, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
526
+ (character: string, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
471
527
  };
528
+ say: (character: keyof Characters, content: TextContent<Languages, S>) => ValidAction;
472
529
  end: () => ValidAction;
473
530
  showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
474
531
  playMusic: (audio: string) => ValidAction;
@@ -489,46 +546,84 @@ type ActionProxyProvider<Characters extends Record<string, Character>, Languages
489
546
  };
490
547
  hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
491
548
  animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
492
- wait: (time: FunctionableValue<number>) => ValidAction;
493
- function: (fn: (restoring: boolean, goingBack: boolean, preview: boolean) => Thenable<void>) => ValidAction;
494
- input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta<Languages>) => void, setup?: ActionInputSetup) => ValidAction;
495
- custom: (handler: CustomHandler) => ValidAction;
549
+ wait: (time: number | ((state: State) => number)) => ValidAction;
550
+ function: (fn: FunctionAction<Languages, S>) => ValidAction;
551
+ input: (question: TextContent<Languages, S>, onInput: (meta: ActionInputOnInputMeta<Languages, S>) => void, setup?: ActionInputSetup) => ValidAction;
552
+ custom: (handler: CustomHandler<Languages, S> | CustomHandler) => ValidAction;
496
553
  vibrate: (...pattern: number[]) => ValidAction;
497
554
  next: () => ValidAction;
498
- text: (...text: Unwrappable<Languages>[]) => ValidAction;
555
+ text: (...text: TextContent<Languages, S>[]) => ValidAction;
499
556
  preload: (source: string) => ValidAction;
500
557
  block: (scene: string) => ValidAction;
501
558
  };
502
- type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>, string>;
503
- type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
559
+ type DefaultActionProxy = ActionProxy<Record<string, Character>, string, State>;
560
+ type GetActionParameters<T extends Capitalize<keyof DefaultActionProxy>> = Parameters<DefaultActionProxy[Uncapitalize<T>]>;
504
561
 
505
- declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, translation, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request }: NovelyInit<Languages, Characters, StateScheme, DataScheme>) => {
562
+ declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, translation, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request, saveOnUnload }: NovelyInit<Languages, Characters, StateScheme, DataScheme>) => {
506
563
  /**
507
564
  * Function to set game script
565
+ *
566
+ * @example
567
+ * ```ts
568
+ * engine.script({
569
+ * start: [
570
+ * action.function(() => {})
571
+ * ]
572
+ * })
573
+ * ```
508
574
  */
509
575
  script: (part: Story) => Promise<void>;
510
576
  /**
511
- * Function to get actions
577
+ * Get actions
578
+ *
579
+ * @example
580
+ * ```ts
581
+ * engine.script({
582
+ * start: [
583
+ * action.function(() => {})
584
+ * ]
585
+ * })
586
+ * ```
512
587
  */
513
- action: ActionProxyProvider<Characters, Languages>;
588
+ action: ActionProxy<Characters, Languages, StateScheme>;
514
589
  /**
515
- * State that belongs to games
590
+ * @deprecated Will be removed BUT replaced with state passed into actions as a parameter
516
591
  */
517
- state: {
518
- (value: DeepPartial<StateScheme> | ((prev: StateScheme) => StateScheme)): void;
519
- (): StateScheme;
520
- };
592
+ state: StateFunction<State>;
593
+ /**
594
+ * Store data between games
595
+ *
596
+ * @example
597
+ * ```ts
598
+ * engine.script({
599
+ * start: [
600
+ * action.function(() => {
601
+ * // Paid content should be purchased only once
602
+ * // So it will be available in any save
603
+ * data({ paid_content_purchased: true })
604
+ * })
605
+ * ]
606
+ * })
607
+ * ```
608
+ */
609
+ data: StateFunction<DataScheme>;
521
610
  /**
522
- * Unlike `state`, stored at global scope instead and shared between games
611
+ * @deprecated Renamed into `templateReplace`
523
612
  */
524
- data: {
525
- (value: DeepPartial<DataScheme> | ((prev: DataScheme) => DataScheme)): void;
526
- (): DataScheme;
527
- };
613
+ unwrap(content: TextContent<Languages, DataScheme>): string;
528
614
  /**
529
- * Unwraps translatable content to a string value
615
+ * Replaces content inside {{braces}} with using global data
616
+ * @example
617
+ * ```ts
618
+ * data({ name: 'Alexei' })
619
+ *
620
+ * templateReplace('{{name}} is our hero')
621
+ * templateReplace({
622
+ * en: (data) => 'Hello, ' + data.name
623
+ * })
624
+ * ```
530
625
  */
531
- unwrap(content: string | (() => string) | Exclude<Record<Languages, string | (() => string)>, Record<string, string>> | Record<Languages, string>): string;
626
+ templateReplace(content: TextContent<Languages, DataScheme>): string;
532
627
  /**
533
628
  * Cancel data loading, hide UI, ignore page change events
534
629
  * Data updates still will work in case Novely already was loaded
@@ -536,4 +631,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
536
631
  destroy(): void;
537
632
  };
538
633
 
539
- export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
634
+ export { type ActionProxy, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxy, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypewriterSpeed, type ValidAction, localStorageStorage, novely };