@novely/core 0.34.0 → 0.35.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
@@ -75,6 +75,20 @@ interface CharacterHandle {
75
75
  animate: (timeout: number, classes: string[]) => void;
76
76
  emotions: Record<string, HTMLImageElement[]>;
77
77
  }
78
+ type CustomActionHandle = {
79
+ /**
80
+ * Function to remove custom action from screen (and from your state if any completely)
81
+ */
82
+ remove: () => void;
83
+ /**
84
+ * Function that will give action root (element which you should add to the screen because custom actions rendered into that element)
85
+ */
86
+ setMountElement: (mountElement: null | HTMLDivElement) => void;
87
+ /**
88
+ * Function that will give you clean function provided by custom action.
89
+ */
90
+ setClear: (clear: () => void) => void;
91
+ };
78
92
  type AudioHandle = {
79
93
  stop: () => void;
80
94
  pause: () => void;
@@ -93,8 +107,7 @@ type Context = {
93
107
  music: Set<string>;
94
108
  sounds: Set<string>;
95
109
  }, resolve: () => void) => void;
96
- custom: (fn: CustomHandler<Lang, State>, push: () => void) => Thenable<void>;
97
- clearCustom: (fn: CustomHandler<Lang, State>) => void;
110
+ custom: (fn: CustomHandler<Lang, State>) => CustomActionHandle;
98
111
  /**
99
112
  * Clears all mentioned actions except for preserved one
100
113
  * @param preserve Action that should not be cleared
@@ -213,6 +226,7 @@ type RendererInit<$Language extends Lang, $Characters extends Record<string, Cha
213
226
  preview: (save: Save<State>, name: string) => Promise<void>;
214
227
  removeContext: (name: string) => void;
215
228
  getStateFunction: (context: string) => StateFunction<State>;
229
+ clearCustomAction: (ctx: Context, customAction: CustomHandler) => void;
216
230
  getLanguageDisplayName: (lang: Lang) => string;
217
231
  };
218
232
 
@@ -499,36 +513,59 @@ type FunctionableValue<T> = T | (() => T);
499
513
  type CustomHandlerGetResultDataFunction = (data?: Record<string, unknown>) => Record<string, unknown>;
500
514
  type CustomHandlerGetResult<I extends boolean> = {
501
515
  /**
502
- * Remove's custom handler instance
516
+ * Element for the custom action to be rendered into
503
517
  */
504
- remove: () => void;
518
+ element: I extends true ? HTMLDivElement : null;
505
519
  /**
506
- * Данные
520
+ * Root node
507
521
  */
508
- data: CustomHandlerGetResultDataFunction;
522
+ root: HTMLElement;
523
+ };
524
+ type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
525
+ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
509
526
  /**
510
- * Элемент слоя
527
+ * Returns:
528
+ * - Root where entire novely is mounted
529
+ * - Element in which custom action could be mounted
530
+ *
531
+ * @example
532
+ * ```ts
533
+ * // pass `true` to insert element to the DOM
534
+ * const { root, element } = getDomNodes(true);
535
+ * ```
511
536
  */
512
- element: I extends true ? HTMLDivElement : null;
537
+ getDomNodes: CustomHandlerFunctionGetFn;
513
538
  /**
514
- * Корневой элемент Novely
539
+ * Renderer Context
515
540
  */
516
- root: HTMLElement;
541
+ rendererContext: Context;
517
542
  /**
518
- * Устанавливает обработчик очистки
543
+ * Function to work with custom action's state
544
+ */
545
+ data: CustomHandlerGetResultDataFunction;
546
+ /**
547
+ * Function to set cleanup handler
519
548
  */
520
549
  clear: (fn: () => void) => void;
521
- __internals: {
522
- ctx: Context;
523
- };
524
- };
525
- type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
526
- type CustomHandlerFunctionParameters<L extends string, S extends State> = {
527
- get: CustomHandlerFunctionGetFn;
550
+ /**
551
+ * Remove's custom handler instance
552
+ */
553
+ remove: () => void;
554
+ /**
555
+ * Context's state function
556
+ */
528
557
  state: StateFunction<S>;
529
- restoring: boolean;
530
- goingBack: boolean;
531
- preview: boolean;
558
+ /**
559
+ * Game flags (aka game states)
560
+ */
561
+ flags: {
562
+ restoring: boolean;
563
+ goingBack: boolean;
564
+ preview: boolean;
565
+ };
566
+ /**
567
+ * Game language
568
+ */
532
569
  lang: L;
533
570
  };
534
571
  type CustomHandlerFunction<L extends string, S extends State> = (parameters: CustomHandlerFunctionParameters<L, S>) => Thenable<void>;
@@ -799,4 +836,4 @@ declare const novely: <$Language extends string, $Characters extends Record<stri
799
836
  */
800
837
  declare const extendAction: <Part0 extends Record<string, (...args: any[]) => ValidAction>, Part1 extends Record<string, (...args: any[]) => ValidAction>>(base: Part0, extension: Part1) => Readonly<Assign<Part0, Part1>>;
801
838
 
802
- export { type ActionInputOnInputMeta, type ActionInputSetup, type ActionInputSetupCleanup, type ActionProxy, type AllowedContent, type AudioHandle, type BackgroundImage, type BaseTranslationStrings, type Character, type CharacterHandle, type ConditionParams, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type Data, type DeepPartial, type DefaultActionProxy, EN, type Emotions, 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 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, extendAction, localStorageStorage, novely };
839
+ export { type ActionInputOnInputMeta, type ActionInputSetup, type ActionInputSetupCleanup, type ActionProxy, type AllowedContent, type AudioHandle, type BackgroundImage, type BaseTranslationStrings, type Character, type CharacterHandle, 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 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 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, extendAction, localStorageStorage, novely };
@@ -210,6 +210,7 @@ var Novely = (() => {
210
210
 
211
211
  // src/shared.ts
212
212
  var STACK_MAP = /* @__PURE__ */ new Map();
213
+ var CUSTOM_ACTION_MAP = /* @__PURE__ */ new Map();
213
214
  var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
214
215
 
215
216
  // ../../node_modules/.pnpm/esm-env@1.0.0/node_modules/esm-env/prod-ssr.js
@@ -943,6 +944,76 @@ var Novely = (() => {
943
944
  });
944
945
  };
945
946
 
947
+ // src/custom-action.ts
948
+ var createCustomActionNode = (id) => {
949
+ const div = document.createElement("div");
950
+ div.setAttribute("data-id", id);
951
+ return div;
952
+ };
953
+ var getCustomActionHolder = (ctx, fn) => {
954
+ const cached = CUSTOM_ACTION_MAP.get(ctx.id + fn.key);
955
+ if (cached) {
956
+ return cached;
957
+ }
958
+ const holder = {
959
+ cleanup: noop,
960
+ node: null,
961
+ fn,
962
+ localData: {}
963
+ };
964
+ CUSTOM_ACTION_MAP.set(ctx.id + fn.key, holder);
965
+ return holder;
966
+ };
967
+ var handleCustomAction = (ctx, fn, { lang, state, setMountElement, setClear, remove: renderersRemove }) => {
968
+ const holder = getCustomActionHolder(ctx, fn);
969
+ const flags = {
970
+ ...ctx.meta
971
+ };
972
+ const getDomNodes = (insert = true) => {
973
+ if (holder.node || !insert) {
974
+ return {
975
+ element: holder.node,
976
+ root: ctx.root
977
+ };
978
+ }
979
+ holder.node = insert ? createCustomActionNode(fn.key) : null;
980
+ setMountElement(holder.node);
981
+ return {
982
+ element: holder.node,
983
+ root: ctx.root
984
+ };
985
+ };
986
+ const clear = (func) => {
987
+ setClear(holder.cleanup = () => {
988
+ func();
989
+ holder.node = null;
990
+ holder.cleanup = noop;
991
+ setMountElement(null);
992
+ setClear(noop);
993
+ });
994
+ };
995
+ const data = (updatedData) => {
996
+ if (updatedData) {
997
+ return holder.localData = updatedData;
998
+ }
999
+ return holder.localData;
1000
+ };
1001
+ const remove = () => {
1002
+ holder.cleanup();
1003
+ renderersRemove();
1004
+ };
1005
+ return fn({
1006
+ flags,
1007
+ lang,
1008
+ state,
1009
+ data,
1010
+ clear,
1011
+ remove,
1012
+ rendererContext: ctx,
1013
+ getDomNodes
1014
+ });
1015
+ };
1016
+
946
1017
  // src/storage.ts
947
1018
  var localStorageStorage = (options) => {
948
1019
  return {
@@ -1263,7 +1334,7 @@ var Novely = (() => {
1263
1334
  }
1264
1335
  const [action2, fn] = element;
1265
1336
  if (action2 === "custom") {
1266
- context.clearCustom(fn);
1337
+ getCustomActionHolder(context, fn).cleanup();
1267
1338
  }
1268
1339
  }
1269
1340
  }
@@ -1388,6 +1459,9 @@ var Novely = (() => {
1388
1459
  }
1389
1460
  return capitalize(language.nameOverride || getIntlLanguageDisplayName(lang));
1390
1461
  };
1462
+ const clearCustomAction = (ctx, fn) => {
1463
+ getCustomActionHolder(ctx, fn).cleanup();
1464
+ };
1391
1465
  const renderer = createRenderer({
1392
1466
  mainContextKey: MAIN_CONTEXT_KEY,
1393
1467
  characters,
@@ -1401,6 +1475,7 @@ var Novely = (() => {
1401
1475
  preview,
1402
1476
  removeContext,
1403
1477
  getStateFunction,
1478
+ clearCustomAction,
1404
1479
  languages,
1405
1480
  storageData,
1406
1481
  coreData,
@@ -1644,19 +1719,31 @@ var Novely = (() => {
1644
1719
  forward
1645
1720
  );
1646
1721
  },
1647
- custom({ ctx, push }, [handler]) {
1648
- if (handler.requireUserAction) {
1722
+ custom({ ctx, push }, [fn]) {
1723
+ if (fn.requireUserAction) {
1649
1724
  ctx.clearBlockingActions(void 0);
1650
1725
  }
1651
- const result = ctx.custom(handler, () => {
1652
- if (ctx.meta.restoring)
1653
- return;
1654
- if (handler.requireUserAction && !ctx.meta.preview) {
1726
+ const state = getStateFunction(ctx);
1727
+ const lang = storageData.get().meta[0];
1728
+ const result = handleCustomAction(ctx, fn, {
1729
+ ...ctx.custom(fn),
1730
+ state,
1731
+ lang
1732
+ });
1733
+ const next2 = () => {
1734
+ if (fn.requireUserAction && !ctx.meta.preview) {
1655
1735
  enmemory(ctx);
1656
1736
  interactivity(true);
1657
1737
  }
1658
1738
  push();
1659
- });
1739
+ };
1740
+ if (!ctx.meta.restoring) {
1741
+ if (isPromise(result)) {
1742
+ result.then(next2);
1743
+ } else {
1744
+ next2();
1745
+ }
1746
+ }
1660
1747
  return result;
1661
1748
  },
1662
1749
  vibrate({ ctx, push }, pattern) {