@novely/core 0.13.0 → 0.14.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
@@ -10,7 +10,7 @@ type Character<LanguageKeys extends string = string> = {
10
10
  };
11
11
 
12
12
  type Thenable<T> = T | Promise<T>;
13
- type PathItem = [null, number | string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
13
+ type PathItem = [null, number | string] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
14
14
  type Path = PathItem[];
15
15
  type State = Record<string, any>;
16
16
  type Data = Record<string, any>;
@@ -45,9 +45,9 @@ type CoreData = {
45
45
  dataLoaded: boolean;
46
46
  };
47
47
 
48
- type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
48
+ 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]] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
49
49
  type Story = Record<string, ValidAction[]>;
50
- type Unwrappable = string | Record<string, string | (() => string)>;
50
+ type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
51
51
  type FunctionableValue<T> = T | (() => T);
52
52
  type CustomHandlerGetResultDataFunction = {
53
53
  (data?: Record<string, unknown>): Record<string, unknown>;
@@ -101,18 +101,18 @@ interface ActionInputOnInputMeta {
101
101
  }
102
102
  type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
103
103
  type BackgroundImage = Partial<Record<"portrait" | "landscape" | "all", string>> & Record<(string), string>;
104
- type ActionProxyProvider<Characters extends Record<string, Character>> = {
104
+ type ActionProxyProvider<Characters extends Record<string, Character>, Languages extends string> = {
105
105
  choice: {
106
- (...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
107
- (question: Unwrappable, ...choices: ([Unwrappable, ValidAction[]] | [Unwrappable, ValidAction[], () => boolean])[]): ValidAction;
106
+ (...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
107
+ (question: Unwrappable<Languages>, ...choices: ([Unwrappable<Languages>, ValidAction[]] | [Unwrappable<Languages>, ValidAction[], () => boolean])[]): ValidAction;
108
108
  };
109
109
  clear: (keep?: Set<keyof DefaultActionProxyProvider>, keepCharacters?: Set<string>) => ValidAction;
110
110
  condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
111
111
  exit: () => ValidAction;
112
112
  dialog: {
113
- <C extends keyof Characters>(person: C, content: Unwrappable, emotion?: keyof Characters[C]['emotions']): ValidAction;
114
- (person: undefined, content: Unwrappable, emotion?: undefined): ValidAction;
115
- (person: string, content: Unwrappable, emotion?: undefined): ValidAction;
113
+ <C extends keyof Characters>(person: C, content: Unwrappable<Languages>, emotion?: keyof Characters[C]['emotions']): ValidAction;
114
+ (person: undefined, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
115
+ (person: string, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
116
116
  };
117
117
  end: () => ValidAction;
118
118
  showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
@@ -126,15 +126,15 @@ type ActionProxyProvider<Characters extends Record<string, Character>> = {
126
126
  animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
127
127
  wait: (time: FunctionableValue<number>) => ValidAction;
128
128
  function: (fn: (restoring: boolean, goingBack: boolean) => Thenable<void>) => ValidAction;
129
- input: (question: Unwrappable, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
129
+ input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta) => void, setup?: ActionInputSetup) => ValidAction;
130
130
  custom: (handler: CustomHandler) => ValidAction;
131
131
  vibrate: (...pattern: number[]) => ValidAction;
132
132
  next: () => ValidAction;
133
- text: (...text: Unwrappable[]) => ValidAction;
133
+ text: (...text: Unwrappable<Languages>[]) => ValidAction;
134
134
  preload: (source: string) => ValidAction;
135
135
  block: (scene: string) => ValidAction;
136
136
  };
137
- type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>>;
137
+ type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>, string>;
138
138
  type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
139
139
 
140
140
  declare const RU: {
@@ -234,7 +234,11 @@ type Renderer = {
234
234
  /**
235
235
  * Shows the screen
236
236
  */
237
- showScreen(name: 'mainmenu' | 'game' | 'saves' | 'settings' | 'loading'): void;
237
+ showScreen(name: NovelyScreen | 'loading'): void;
238
+ /**
239
+ * Returns current screen
240
+ */
241
+ getScreen(): NovelyScreen | 'loading' | (string & Record<never, never>);
238
242
  /**
239
243
  * Shows prompt to exit
240
244
  */
@@ -382,11 +386,11 @@ declare const novely: <Languages extends string, Characters extends Record<strin
382
386
  /**
383
387
  * Function to set story
384
388
  */
385
- withStory: (s: Story) => Promise<void>;
389
+ withStory: (story: Story) => Promise<void>;
386
390
  /**
387
391
  * Function to get actions
388
392
  */
389
- action: ActionProxyProvider<Characters>;
393
+ action: ActionProxyProvider<Characters, Languages>;
390
394
  /**
391
395
  * State that belongs to games
392
396
  */
@@ -404,7 +408,7 @@ declare const novely: <Languages extends string, Characters extends Record<strin
404
408
  /**
405
409
  * Unwraps translatable content to a string value
406
410
  */
407
- unwrap(content: Unwrappable | Record<Languages, string>): string;
411
+ unwrap(content: string | (() => string) | Record<Languages, string> | Exclude<Record<Languages, string | (() => string)>, Record<string, string>>): string;
408
412
  };
409
413
 
410
- export { ActionProxyProvider, AllowedContent, AudioHandle, BaseTranslationStrings, Character, CharacterHandle, CoreData, CustomHandler, CustomHandlerGetResult, CustomHandlerGetResultDataFunction, DefaultActionProxyProvider, EN, Emotions, FunctionableValue, GetActionParameters, JP, KK, Lang, NovelyScreen, Path, PluralType, Pluralization, RU, Renderer, RendererInit, RendererStore, Storage, StorageData, StorageMeta, Stored, Story, Thenable, TranslationActions, TypewriterSpeed, Unwrappable, ValidAction, localStorageStorage, novely };
414
+ export { type ActionProxyProvider, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type CoreData, type CustomHandler, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxyProvider, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type RendererStore, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type Thenable, type TranslationActions, type TypewriterSpeed, type Unwrappable, type ValidAction, localStorageStorage, novely };
@@ -107,13 +107,20 @@ var Novely = (() => {
107
107
  }
108
108
  return -1;
109
109
  };
110
- var createDeferredPromise = () => {
110
+ var createControlledPromise = () => {
111
111
  let resolve, reject;
112
112
  const promise = new Promise((res, rej) => {
113
113
  resolve = res;
114
114
  reject = rej;
115
115
  });
116
- return { resolve, reject, promise };
116
+ return {
117
+ resolve,
118
+ reject,
119
+ promise,
120
+ reset() {
121
+ Object.assign(this, createControlledPromise());
122
+ }
123
+ };
117
124
  };
118
125
  var findLastPathItemBeforeItemOfType = (path, name) => {
119
126
  const index = findLastIndex(path, ([_name, _value], next) => {
@@ -135,6 +142,20 @@ var Novely = (() => {
135
142
  var isAction = (element) => {
136
143
  return Array.isArray(element) && isString(element[0]);
137
144
  };
145
+ var flattenStory = (story) => {
146
+ const entries = Object.entries(story).map(([name, items]) => {
147
+ const flat = (item) => {
148
+ return item.flatMap((data) => {
149
+ const type = data[0];
150
+ if (Array.isArray(type))
151
+ return flat(data);
152
+ return [data];
153
+ });
154
+ };
155
+ return [name, flat(items)];
156
+ });
157
+ return Object.fromEntries(entries);
158
+ };
138
159
 
139
160
  // src/global.ts
140
161
  var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
@@ -344,29 +365,20 @@ var Novely = (() => {
344
365
  askBeforeExit = true,
345
366
  preloadAssets = "lazy"
346
367
  }) => {
347
- let story;
368
+ const story = {};
348
369
  const times = /* @__PURE__ */ new Set();
349
370
  const ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
350
- const assetsLoaded = createDeferredPromise();
371
+ const assetsLoaded = createControlledPromise();
351
372
  defaultData ||= {};
352
373
  defaultState ||= {};
353
374
  const intime = (value) => {
354
375
  return times.add(value), value;
355
376
  };
356
- const withStory = async (s) => {
357
- story = Object.fromEntries(
358
- Object.entries(s).map(([name, items]) => {
359
- const flat = (item) => {
360
- return item.flatMap((data2) => {
361
- const type = data2[0];
362
- if (Array.isArray(type))
363
- return flat(data2);
364
- return [data2];
365
- });
366
- };
367
- return [name, flat(items)];
368
- })
369
- );
377
+ const script = (part) => {
378
+ Object.assign(story, flattenStory(part));
379
+ };
380
+ const withStory = async (story2) => {
381
+ script(story2);
370
382
  if (preloadAssets === "blocking" && ASSETS_TO_PRELOAD.size > 0) {
371
383
  renderer.ui.showScreen("loading");
372
384
  await renderer.misc.preloadImagesBlocking(ASSETS_TO_PRELOAD);
@@ -408,7 +420,7 @@ var Novely = (() => {
408
420
  const getDefaultSave = (state2 = {}) => {
409
421
  return [
410
422
  [
411
- [null, "start"],
423
+ ["jump", "start"],
412
424
  [null, 0]
413
425
  ],
414
426
  state2,
@@ -557,7 +569,10 @@ var Novely = (() => {
557
569
  const characters2 = /* @__PURE__ */ new Set();
558
570
  const blocks = [];
559
571
  for (const [type, val] of path) {
560
- if (type === null) {
572
+ if (type === "jump") {
573
+ precurrent = story;
574
+ current = current[val];
575
+ } else if (type === null) {
561
576
  precurrent = current;
562
577
  if (isNumber(val)) {
563
578
  index++;
@@ -654,7 +669,11 @@ var Novely = (() => {
654
669
  let precurrent = story;
655
670
  const blocks = [];
656
671
  for (const [type, val] of path) {
657
- if (type === null) {
672
+ console.log(type, val);
673
+ if (type === "jump") {
674
+ precurrent = story;
675
+ current = current[val];
676
+ } else if (type === null) {
658
677
  precurrent = current;
659
678
  current = current[val];
660
679
  } else if (type === "choice") {
@@ -785,7 +804,7 @@ var Novely = (() => {
785
804
  },
786
805
  jump([scene]) {
787
806
  stack.value[0] = [
788
- [null, scene],
807
+ ["jump", scene],
789
808
  [null, -1]
790
809
  ];
791
810
  match("clear", []);
@@ -916,7 +935,7 @@ var Novely = (() => {
916
935
  const next = () => {
917
936
  const path = stack.value[0];
918
937
  const last = path.at(-1);
919
- if (last && isNull(last[0]) && isNumber(last[1])) {
938
+ if (last && (isNull(last[0]) || last[0] === "jump") && isNumber(last[1])) {
920
939
  last[1]++;
921
940
  } else {
922
941
  path.push([null, 0]);
@@ -949,7 +968,7 @@ var Novely = (() => {
949
968
  meta: [lang]
950
969
  } = $.get();
951
970
  const obj = global ? data2 : state();
952
- const cnt = isFunction(content) ? content(lang, obj) : typeof content === "string" ? content : content[lang];
971
+ const cnt = isFunction(content) ? content() : typeof content === "string" ? content : content[lang];
953
972
  const str2 = isFunction(cnt) ? cnt() : cnt;
954
973
  const trans = translation[lang];
955
974
  if (trans.actions || trans.plural) {