@novely/core 0.40.2 → 0.41.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
@@ -1,11 +1,11 @@
1
- interface LocalStorageStorageSettings {
1
+ type LocalStorageStorageSettings = {
2
2
  key: string;
3
- }
4
- interface Storage {
3
+ };
4
+ type NovelyStorage = {
5
5
  get: () => Promise<StorageData>;
6
6
  set: (data: StorageData) => Promise<void>;
7
- }
8
- declare const localStorageStorage: (options: LocalStorageStorageSettings) => Storage;
7
+ };
8
+ declare const localStorageStorage: (options: LocalStorageStorageSettings) => NovelyStorage;
9
9
 
10
10
  type PluralType = Intl.LDMLPluralRule;
11
11
  type Pluralization = Partial<Record<PluralType, string>>;
@@ -328,6 +328,7 @@ type CharactersData<$Characters extends Record<string, Character<Lang>>> = {
328
328
  };
329
329
  };
330
330
  type AssetsPreloading = 'lazy' | 'blocking' | 'automatic';
331
+ type CloneFN = <T>(value: T) => T;
331
332
  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>> {
332
333
  /**
333
334
  * An object containing the characters in the game.
@@ -406,7 +407,7 @@ interface NovelyInit<$Language extends Lang, $Characters extends Record<string,
406
407
  * An object that provides access to the game's storage system.
407
408
  * @default localStorage // at key `novely-game-storage`
408
409
  */
409
- storage?: Storage;
410
+ storage?: NovelyStorage;
410
411
  /**
411
412
  * Delay loading data until Promise is resolved
412
413
  */
@@ -509,6 +510,10 @@ interface NovelyInit<$Language extends Lang, $Characters extends Record<string,
509
510
  * Fetching function
510
511
  */
511
512
  fetch?: typeof fetch;
513
+ /**
514
+ * Function for clonning operations
515
+ */
516
+ cloneFunction?: CloneFN;
512
517
  /**
513
518
  * When page is going to be unloaded will call `storage.set` method
514
519
  * If 'prod' is passed enable only in production env.
@@ -796,7 +801,7 @@ type ChoiceParams<T> = T extends TypeEssentials<infer $Lang, infer $State, any,
796
801
  type FunctionParams<T> = T extends TypeEssentials<infer $Lang, infer $State, any, any> ? FunctionActionProps<$Lang, $State> : never;
797
802
  type InputHandler<T> = T extends TypeEssentials<infer $Lang, infer $State, any, any> ? ActionInputOnInputMeta<$Lang, $State> : never;
798
803
 
799
- 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, saveOnUnload, startKey }: NovelyInit<$Language, $Characters, $State, $Data, $Actions>) => {
804
+ 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, }: NovelyInit<$Language, $Characters, $State, $Data, $Actions>) => {
800
805
  /**
801
806
  * Function to set game script
802
807
  *
@@ -858,7 +863,7 @@ declare const novely: <$Language extends string, $Characters extends Record<stri
858
863
  */
859
864
  typeEssentials: TypeEssentials<$Language, $State, $Data, $Characters>;
860
865
  /**
861
- * Replaces content inside {{braces}} with using global data
866
+ * Replaces content inside {{braces}} using global data
862
867
  * @example
863
868
  * ```ts
864
869
  * data({ name: 'Alexei' })
@@ -870,6 +875,10 @@ declare const novely: <$Language extends string, $Characters extends Record<stri
870
875
  * ```
871
876
  */
872
877
  templateReplace(content: TextContent<$Language, $Data>): string;
878
+ /**
879
+ * Same as `templateReplace` but uses state and requires explicitly providing it
880
+ */
881
+ templateReplaceState(content: TextContent<$Language, $State>, state: State): string;
873
882
  /**
874
883
  * Cancel data loading, hide UI, ignore page change events
875
884
  * Data updates still will work in case Novely already was loaded
@@ -944,4 +953,4 @@ declare const extendAction: <Part0 extends Record<string, (...args: any[]) => Va
944
953
  */
945
954
  declare const asset: (...variants: string[]) => NovelyAsset;
946
955
 
947
- export { 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 ChoiceParams, type ConditionParams, type Context, type CoreData, type CustomActionHandle, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type Data, type DeepPartial, type DefaultActionProxy, EN, type Emotions, type FunctionParams, type FunctionableValue, type GetActionParameters, type InputHandler, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type RendererInitPreviewReturn, type Save, type Stack, type StackHolder, type State, type StateFunction, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypeEssentials, type TypewriterSpeed, type ValidAction, asset, extendAction, localStorageStorage, novely };
956
+ export { 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 ChoiceParams, type ConditionParams, type Context, type CoreData, type CustomActionHandle, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type Data, type DeepPartial, type DefaultActionProxy, EN, type Emotions, type FunctionParams, type FunctionableValue, type GetActionParameters, type InputHandler, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type NovelyStorage, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type RendererInitPreviewReturn, type Save, type Stack, type StackHolder, type State, type StateFunction, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypeEssentials, type TypewriterSpeed, type ValidAction, asset, extendAction, localStorageStorage, novely };
@@ -87,33 +87,6 @@ var Novely = (() => {
87
87
  // ../../node_modules/.pnpm/esm-env@1.0.0/node_modules/esm-env/prod-ssr.js
88
88
  var DEV = false;
89
89
 
90
- // ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/json/index.mjs
91
- function klona(val) {
92
- var k, out, tmp;
93
- if (Array.isArray(val)) {
94
- out = Array(k = val.length);
95
- while (k--) out[k] = (tmp = val[k]) && typeof tmp === "object" ? klona(tmp) : tmp;
96
- return out;
97
- }
98
- if (Object.prototype.toString.call(val) === "[object Object]") {
99
- out = {};
100
- for (k in val) {
101
- if (k === "__proto__") {
102
- Object.defineProperty(out, k, {
103
- value: klona(val[k]),
104
- configurable: true,
105
- enumerable: true,
106
- writable: true
107
- });
108
- } else {
109
- out[k] = (tmp = val[k]) && typeof tmp === "object" ? klona(tmp) : tmp;
110
- }
111
- }
112
- return out;
113
- }
114
- return val;
115
- }
116
-
117
90
  // ../../node_modules/.pnpm/es-toolkit@1.16.0/node_modules/es-toolkit/dist/function/once.mjs
118
91
  function once(func) {
119
92
  let called = false;
@@ -630,8 +603,8 @@ var Novely = (() => {
630
603
  };
631
604
  return useStack;
632
605
  };
633
- var mapSet = (set, fn) => {
634
- return [...set].map(fn);
606
+ var mapSet = (set2, fn) => {
607
+ return [...set2].map(fn);
635
608
  };
636
609
  var isImageAsset = (asset2) => {
637
610
  return isString(asset2) && isCSSImage(asset2);
@@ -783,7 +756,7 @@ var Novely = (() => {
783
756
  var isBlockingAction = (action) => {
784
757
  return isUserRequiredAction(action) || isSkippedDuringRestore(action[0]) && action[0] !== "vibrate";
785
758
  };
786
- var collectActionsBeforeBlockingAction = ({ path, refer }) => {
759
+ var collectActionsBeforeBlockingAction = ({ path, refer, clone }) => {
787
760
  const collection = [];
788
761
  let action = refer(path);
789
762
  while (true) {
@@ -806,11 +779,12 @@ var Novely = (() => {
806
779
  for (let i = 0; i < choiceProps.length; i++) {
807
780
  const branchContent = choiceProps[i];
808
781
  if (!Array.isArray(branchContent)) continue;
809
- const virtualPath = klona(path);
782
+ const virtualPath = clone(path);
810
783
  virtualPath.push(["choice", i], [null, 0]);
811
784
  const innerActions = collectActionsBeforeBlockingAction({
812
785
  path: virtualPath,
813
- refer
786
+ refer,
787
+ clone
814
788
  });
815
789
  collection.push(...innerActions);
816
790
  }
@@ -818,11 +792,12 @@ var Novely = (() => {
818
792
  const conditionProps = props;
819
793
  const conditions = Object.keys(conditionProps[1]);
820
794
  for (const condition of conditions) {
821
- const virtualPath = klona(path);
795
+ const virtualPath = clone(path);
822
796
  virtualPath.push(["condition", condition], [null, 0]);
823
797
  const innerActions = collectActionsBeforeBlockingAction({
824
798
  path: virtualPath,
825
- refer
799
+ refer,
800
+ clone
826
801
  });
827
802
  collection.push(...innerActions);
828
803
  }
@@ -939,15 +914,62 @@ var Novely = (() => {
939
914
  const update = (fn) => {
940
915
  push(current = fn(current));
941
916
  };
942
- const set = (val) => {
917
+ const set2 = (val) => {
943
918
  update(() => val);
944
919
  };
945
920
  const get = () => {
946
921
  return current;
947
922
  };
948
- return { subscribe, update, set, get };
923
+ return { subscribe, update, set: set2, get };
949
924
  };
950
925
 
926
+ // ../../node_modules/.pnpm/klona@2.0.6/node_modules/klona/full/index.mjs
927
+ function set(obj, key, val) {
928
+ if (typeof val.value === "object") val.value = klona(val.value);
929
+ if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") {
930
+ Object.defineProperty(obj, key, val);
931
+ } else obj[key] = val.value;
932
+ }
933
+ function klona(x) {
934
+ if (typeof x !== "object") return x;
935
+ var i = 0, k, list, tmp, str2 = Object.prototype.toString.call(x);
936
+ if (str2 === "[object Object]") {
937
+ tmp = Object.create(x.__proto__ || null);
938
+ } else if (str2 === "[object Array]") {
939
+ tmp = Array(x.length);
940
+ } else if (str2 === "[object Set]") {
941
+ tmp = /* @__PURE__ */ new Set();
942
+ x.forEach(function(val) {
943
+ tmp.add(klona(val));
944
+ });
945
+ } else if (str2 === "[object Map]") {
946
+ tmp = /* @__PURE__ */ new Map();
947
+ x.forEach(function(val, key) {
948
+ tmp.set(klona(key), klona(val));
949
+ });
950
+ } else if (str2 === "[object Date]") {
951
+ tmp = /* @__PURE__ */ new Date(+x);
952
+ } else if (str2 === "[object RegExp]") {
953
+ tmp = new RegExp(x.source, x.flags);
954
+ } else if (str2 === "[object DataView]") {
955
+ tmp = new x.constructor(klona(x.buffer));
956
+ } else if (str2 === "[object ArrayBuffer]") {
957
+ tmp = x.slice(0);
958
+ } else if (str2.slice(-6) === "Array]") {
959
+ tmp = new x.constructor(x);
960
+ }
961
+ if (tmp) {
962
+ for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) {
963
+ set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
964
+ }
965
+ for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
966
+ if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
967
+ set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
968
+ }
969
+ }
970
+ return tmp || x;
971
+ }
972
+
951
973
  // src/translation.ts
952
974
  var RGX = /{{(.*?)}}/g;
953
975
  var split = (input, delimeters) => {
@@ -1347,6 +1369,7 @@ var Novely = (() => {
1347
1369
  preloadAssets = "lazy",
1348
1370
  parallelAssetsDownloadLimit = 15,
1349
1371
  fetch: request = fetch,
1372
+ cloneFunction: clone = klona,
1350
1373
  saveOnUnload = true,
1351
1374
  startKey = "start"
1352
1375
  }) => {
@@ -1414,7 +1437,7 @@ var Novely = (() => {
1414
1437
  };
1415
1438
  }
1416
1439
  });
1417
- const getDefaultSave = (state = {}) => {
1440
+ const getDefaultSave = (state) => {
1418
1441
  return [
1419
1442
  [
1420
1443
  ["jump", startKey],
@@ -1436,7 +1459,7 @@ var Novely = (() => {
1436
1459
  };
1437
1460
  const initialData = {
1438
1461
  saves: [],
1439
- data: klona(defaultData),
1462
+ data: clone(defaultData),
1440
1463
  meta: [getLanguageWithoutParameters(), DEFAULT_TYPEWRITER_SPEED, 1, 1, 1]
1441
1464
  };
1442
1465
  const storageData = store(initialData);
@@ -1486,7 +1509,7 @@ var Novely = (() => {
1486
1509
  storageData.set(stored);
1487
1510
  };
1488
1511
  storageDelay.then(getStoredData);
1489
- const initial = getDefaultSave(klona(defaultState));
1512
+ const initial = getDefaultSave(clone(defaultState));
1490
1513
  const unsubscribeFromBrowserVisibilityChange = setupBrowserVisibilityChangeListeners({
1491
1514
  onChange: throttledEmergencyOnStorageDataChange
1492
1515
  });
@@ -1494,7 +1517,7 @@ var Novely = (() => {
1494
1517
  if (!coreData.get().dataLoaded) return;
1495
1518
  if (!autosaves && type === "auto") return;
1496
1519
  const stack = useStack(MAIN_CONTEXT_KEY);
1497
- const current = klona(stack.value);
1520
+ const current = clone(stack.value);
1498
1521
  storageData.update((prev) => {
1499
1522
  const replace2 = () => {
1500
1523
  prev.saves[prev.saves.length - 1] = current;
@@ -1524,7 +1547,7 @@ var Novely = (() => {
1524
1547
  };
1525
1548
  const newGame = () => {
1526
1549
  if (!coreData.get().dataLoaded) return;
1527
- const save2 = getDefaultSave(klona(defaultState));
1550
+ const save2 = getDefaultSave(clone(defaultState));
1528
1551
  if (autosaves) {
1529
1552
  storageData.update((prev) => {
1530
1553
  return prev.saves.push(save2), prev;
@@ -1537,7 +1560,7 @@ var Novely = (() => {
1537
1560
  renderer.ui.showScreen("game");
1538
1561
  render(context);
1539
1562
  };
1540
- const set = (save2, ctx) => {
1563
+ const set2 = (save2, ctx) => {
1541
1564
  const stack = useStack(ctx || MAIN_CONTEXT_KEY);
1542
1565
  stack.value = save2;
1543
1566
  return restore(save2);
@@ -1553,7 +1576,7 @@ var Novely = (() => {
1553
1576
  if (!coreData.get().dataLoaded) return;
1554
1577
  let latest = save2 || storageData.get().saves.at(-1);
1555
1578
  if (!latest) {
1556
- latest = klona(initial);
1579
+ latest = clone(initial);
1557
1580
  storageData.update((prev) => {
1558
1581
  prev.saves.push(latest);
1559
1582
  return prev;
@@ -1665,7 +1688,7 @@ var Novely = (() => {
1665
1688
  const processor = createQueueProcessor(queue, {
1666
1689
  skip: EMPTY_SET
1667
1690
  });
1668
- useStack(ctx).push(klona(save2));
1691
+ useStack(ctx).push(clone(save2));
1669
1692
  const assets = [];
1670
1693
  await processor.run(([action2, ...props]) => {
1671
1694
  if (isAudioAction(action2)) return;
@@ -1735,7 +1758,7 @@ var Novely = (() => {
1735
1758
  mainContextKey: MAIN_CONTEXT_KEY,
1736
1759
  characters: getCharactersData(characters),
1737
1760
  characterAssetSizes,
1738
- set,
1761
+ set: set2,
1739
1762
  restore,
1740
1763
  save,
1741
1764
  newGame,
@@ -1760,7 +1783,7 @@ var Novely = (() => {
1760
1783
  const enmemory = (ctx) => {
1761
1784
  if (ctx.meta.restoring) return;
1762
1785
  const stack = useStack(ctx);
1763
- const current = klona(stack.value);
1786
+ const current = clone(stack.value);
1764
1787
  current[2][1] = "auto";
1765
1788
  stack.push(current);
1766
1789
  save("auto");
@@ -1788,8 +1811,9 @@ var Novely = (() => {
1788
1811
  if (!isBlockingAction([action2, ...props])) return;
1789
1812
  try {
1790
1813
  const collection = collectActionsBeforeBlockingAction({
1791
- path: nextPath(klona(useStack(ctx).value[0])),
1792
- refer
1814
+ path: nextPath(clone(useStack(ctx).value[0])),
1815
+ refer,
1816
+ clone
1793
1817
  });
1794
1818
  for (const [action3, ...props2] of collection) {
1795
1819
  huntAssets({
@@ -2171,7 +2195,7 @@ var Novely = (() => {
2171
2195
  c: null
2172
2196
  };
2173
2197
  const getCurrentStorageData = () => {
2174
- return coreData.get().dataLoaded ? klona(storageData.get()) : null;
2198
+ return coreData.get().dataLoaded ? clone(storageData.get()) : null;
2175
2199
  };
2176
2200
  const setStorageData = (data2) => {
2177
2201
  if (destroyed) {
@@ -2244,7 +2268,7 @@ var Novely = (() => {
2244
2268
  */
2245
2269
  typeEssentials,
2246
2270
  /**
2247
- * Replaces content inside {{braces}} with using global data
2271
+ * Replaces content inside {{braces}} using global data
2248
2272
  * @example
2249
2273
  * ```ts
2250
2274
  * data({ name: 'Alexei' })
@@ -2258,6 +2282,12 @@ var Novely = (() => {
2258
2282
  templateReplace(content) {
2259
2283
  return templateReplace(content);
2260
2284
  },
2285
+ /**
2286
+ * Same as `templateReplace` but uses state and requires explicitly providing it
2287
+ */
2288
+ templateReplaceState(content, state) {
2289
+ return templateReplace(content, state);
2290
+ },
2261
2291
  /**
2262
2292
  * Cancel data loading, hide UI, ignore page change events
2263
2293
  * Data updates still will work in case Novely already was loaded