@novely/core 0.52.0-next → 0.52.0-next.2
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 +71 -20
- package/dist/index.js +77 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/index.d.ts.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -66,10 +66,6 @@ type CustomActionHandle = {
|
|
|
66
66
|
* Function that will give action root (element which you should add to the screen because custom actions rendered into that element)
|
|
67
67
|
*/
|
|
68
68
|
setMountElement: (mountElement: null | HTMLDivElement) => void;
|
|
69
|
-
/**
|
|
70
|
-
* Function that will give you clean function provided by custom action.
|
|
71
|
-
*/
|
|
72
|
-
setClear: (clear: () => void) => void;
|
|
73
69
|
};
|
|
74
70
|
type AudioHandle = {
|
|
75
71
|
stop: () => void;
|
|
@@ -222,7 +218,7 @@ type RendererInit<$Language extends Lang, $Characters extends Record<string, Cha
|
|
|
222
218
|
preview: (save: Save<State>, name: string) => Promise<RendererInitPreviewReturn>;
|
|
223
219
|
removeContext: (name: string) => void;
|
|
224
220
|
getStateFunction: (context: string) => StateFunction<State>;
|
|
225
|
-
|
|
221
|
+
clearCustomActionsAtContext: (ctx: Context) => void;
|
|
226
222
|
getLanguageDisplayName: (lang: Lang) => string;
|
|
227
223
|
getCharacterColor: (character: string) => string;
|
|
228
224
|
getCharacterAssets: (character: string, emotion: string) => string[];
|
|
@@ -685,13 +681,9 @@ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
|
|
|
685
681
|
*/
|
|
686
682
|
getDomNodes: CustomHandlerFunctionGetFn;
|
|
687
683
|
/**
|
|
688
|
-
*
|
|
689
|
-
*/
|
|
690
|
-
getPath: () => Path;
|
|
691
|
-
/**
|
|
692
|
-
* Function to get current Save. It can be mutated.
|
|
684
|
+
* Function to get current Save. It can be mutated. Only use it when you know what you do
|
|
693
685
|
*
|
|
694
|
-
*
|
|
686
|
+
* @deprecated
|
|
695
687
|
*/
|
|
696
688
|
getSave: () => Save<S>;
|
|
697
689
|
/**
|
|
@@ -704,22 +696,68 @@ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
|
|
|
704
696
|
contextKey: string;
|
|
705
697
|
/**
|
|
706
698
|
* Function to work with custom action's state
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* ```ts
|
|
702
|
+
* type Data = { name: string };
|
|
703
|
+
*
|
|
704
|
+
* const handler: CustomHandler = async ({ data }) => {
|
|
705
|
+
* const _data = data<Data>();
|
|
706
|
+
*
|
|
707
|
+
* if (!_data.name) {
|
|
708
|
+
* _data.name = 'Mr. Crabs'
|
|
709
|
+
* }
|
|
710
|
+
*
|
|
711
|
+
* data<Data>().name // 'Mr. Crabs'
|
|
712
|
+
*
|
|
713
|
+
* data<Data>() == _data // true
|
|
714
|
+
*
|
|
715
|
+
* // passing object will replace object
|
|
716
|
+
* data<Data>({ name: 'Mr. Crabs' })
|
|
717
|
+
* data<Data>() == _data // false
|
|
718
|
+
* }
|
|
719
|
+
* ```
|
|
707
720
|
*/
|
|
708
721
|
data: CustomHandlerGetResultDataFunction;
|
|
709
722
|
/**
|
|
710
|
-
* Function to
|
|
723
|
+
* Function to access data stored at specific key.
|
|
724
|
+
* @example
|
|
725
|
+
* ```ts
|
|
726
|
+
* const handler: CustomHandler = async ({ dataAtKey }) => {
|
|
727
|
+
* // peek at data at action with key 'action-2'
|
|
728
|
+
* console.log(dataAtKey('action-2'))
|
|
729
|
+
* }
|
|
730
|
+
*
|
|
731
|
+
* handler.key = 'action-1'
|
|
732
|
+
* ```
|
|
733
|
+
* @deprecated
|
|
734
|
+
*/
|
|
735
|
+
dataAtKey: <T extends Record<string, unknown>>(key: string) => T | null;
|
|
736
|
+
/**
|
|
737
|
+
* Function to set cleanup functions.
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```ts
|
|
741
|
+
* const handler: CustomHandler = async ({ clear, paused }) => {
|
|
742
|
+
* const unsubscribe = paused.subscribe((paused) => {
|
|
743
|
+
*
|
|
744
|
+
* })
|
|
745
|
+
*
|
|
746
|
+
* clear(paused);
|
|
747
|
+
* }
|
|
748
|
+
* ```
|
|
711
749
|
*/
|
|
712
750
|
clear: (fn: () => void) => void;
|
|
713
751
|
/**
|
|
714
|
-
*
|
|
752
|
+
* It will call all clear actions and remove HTML element from `getDomNodes` function
|
|
715
753
|
*/
|
|
716
754
|
remove: () => void;
|
|
717
755
|
/**
|
|
718
|
-
*
|
|
756
|
+
* State function
|
|
719
757
|
*/
|
|
720
758
|
state: StateFunction<S>;
|
|
721
759
|
/**
|
|
722
|
-
* Game
|
|
760
|
+
* Game state
|
|
723
761
|
*/
|
|
724
762
|
flags: {
|
|
725
763
|
restoring: boolean;
|
|
@@ -732,10 +770,27 @@ type CustomHandlerFunctionParameters<L extends string, S extends State> = {
|
|
|
732
770
|
lang: L;
|
|
733
771
|
/**
|
|
734
772
|
* Function to replace template content
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```ts
|
|
776
|
+
* const handler: CustomHandler = async ({ state, templateReplace }) => {
|
|
777
|
+
* const text = templateReplace({ en: '' }, state())
|
|
778
|
+
* }
|
|
779
|
+
* ```
|
|
735
780
|
*/
|
|
736
781
|
templateReplace: (content: TextContent<L, State>, values?: State) => string;
|
|
737
782
|
/**
|
|
738
783
|
* Is game currently paused
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```ts
|
|
787
|
+
* const handler: CustomHandler = async ({ clear, paused }) => {
|
|
788
|
+
* const unsubscribe = paused.subscribe((paused) => {
|
|
789
|
+
* // Here you can pause/resume animations, sounds, etc, etc
|
|
790
|
+
* })
|
|
791
|
+
*
|
|
792
|
+
* clear(paused);
|
|
793
|
+
* }
|
|
739
794
|
*/
|
|
740
795
|
paused: Derived<boolean>;
|
|
741
796
|
};
|
|
@@ -766,16 +821,12 @@ type CustomHandlerInfo = CustomHandlerCalling & {
|
|
|
766
821
|
* When true interacting with it will be saved in history
|
|
767
822
|
*/
|
|
768
823
|
requireUserAction?: boolean;
|
|
769
|
-
/**
|
|
770
|
-
* When player is going back we clear every custom action. But we can ignore clearing that.
|
|
771
|
-
*/
|
|
772
|
-
skipClearOnGoingBack?: boolean;
|
|
773
824
|
/**
|
|
774
825
|
* Id by which we will determine what action is which
|
|
775
826
|
*/
|
|
776
827
|
id: string | symbol;
|
|
777
828
|
/**
|
|
778
|
-
* Key by which we will save the data
|
|
829
|
+
* Key by which we will save the custom action's data. It includes cleanup function's provided by `clear` and data in `data` function
|
|
779
830
|
*
|
|
780
831
|
* It can be a name of action or more specific thing. In example for custom `showCharacter` it may be `show-character-${character}
|
|
781
832
|
*/
|
package/dist/index.js
CHANGED
|
@@ -122,6 +122,7 @@ var MAIN_CONTEXT_KEY = "$MAIN";
|
|
|
122
122
|
// src/shared.ts
|
|
123
123
|
var STACK_MAP = /* @__PURE__ */ new Map();
|
|
124
124
|
var CUSTOM_ACTION_MAP = /* @__PURE__ */ new Map();
|
|
125
|
+
var CUSTOM_ACTION_CLEANUP_MAP = /* @__PURE__ */ new Map();
|
|
125
126
|
var PRELOADED_ASSETS = /* @__PURE__ */ new Set();
|
|
126
127
|
var ASSETS_TO_PRELOAD = /* @__PURE__ */ new Set();
|
|
127
128
|
|
|
@@ -674,7 +675,7 @@ var createQueueProcessor = (queue, options) => {
|
|
|
674
675
|
if (action === "function" || action === "custom") {
|
|
675
676
|
if (action === "custom") {
|
|
676
677
|
const fn = params[0];
|
|
677
|
-
if (
|
|
678
|
+
if (fn.callOnlyLatest) {
|
|
678
679
|
const notLatest = next(i).some(([name, func]) => {
|
|
679
680
|
if (name !== "custom") return;
|
|
680
681
|
const isIdenticalId = Boolean(func.id && fn.id && func.id === fn.id);
|
|
@@ -683,7 +684,7 @@ var createQueueProcessor = (queue, options) => {
|
|
|
683
684
|
return isIdenticalId || isIdenticalByReference || isIdenticalByCode;
|
|
684
685
|
});
|
|
685
686
|
if (notLatest) continue;
|
|
686
|
-
} else if (
|
|
687
|
+
} else if (fn.skipOnRestore) {
|
|
687
688
|
if (fn.skipOnRestore(next(i))) {
|
|
688
689
|
continue;
|
|
689
690
|
}
|
|
@@ -922,7 +923,7 @@ var capitalize = (str) => {
|
|
|
922
923
|
return str[0].toUpperCase() + str.slice(1);
|
|
923
924
|
};
|
|
924
925
|
|
|
925
|
-
// src/utilities/
|
|
926
|
+
// src/utilities/noop.ts
|
|
926
927
|
var noop = () => {
|
|
927
928
|
};
|
|
928
929
|
|
|
@@ -997,6 +998,7 @@ var immutable = (value) => {
|
|
|
997
998
|
};
|
|
998
999
|
|
|
999
1000
|
// src/custom-action.ts
|
|
1001
|
+
import { once as once2 } from "es-toolkit/function";
|
|
1000
1002
|
var createCustomActionNode = (id) => {
|
|
1001
1003
|
const div = document.createElement("div");
|
|
1002
1004
|
div.setAttribute("data-id", id);
|
|
@@ -1008,7 +1010,6 @@ var getCustomActionHolder = (ctx, fn) => {
|
|
|
1008
1010
|
return cached;
|
|
1009
1011
|
}
|
|
1010
1012
|
const holder = {
|
|
1011
|
-
cleanup: noop,
|
|
1012
1013
|
node: null,
|
|
1013
1014
|
fn,
|
|
1014
1015
|
localData: {}
|
|
@@ -1016,17 +1017,38 @@ var getCustomActionHolder = (ctx, fn) => {
|
|
|
1016
1017
|
CUSTOM_ACTION_MAP.set(ctx.id + fn.key, holder);
|
|
1017
1018
|
return holder;
|
|
1018
1019
|
};
|
|
1020
|
+
var getCustomActionCleanupHolder = (ctx) => {
|
|
1021
|
+
const existing = CUSTOM_ACTION_CLEANUP_MAP.get(ctx.id);
|
|
1022
|
+
if (existing) {
|
|
1023
|
+
return existing;
|
|
1024
|
+
}
|
|
1025
|
+
const holder = [];
|
|
1026
|
+
CUSTOM_ACTION_CLEANUP_MAP.set(ctx.id, holder);
|
|
1027
|
+
return holder;
|
|
1028
|
+
};
|
|
1019
1029
|
var handleCustomAction = (ctx, fn, {
|
|
1020
1030
|
lang,
|
|
1021
1031
|
state,
|
|
1022
1032
|
setMountElement,
|
|
1023
|
-
setClear,
|
|
1024
1033
|
remove: renderersRemove,
|
|
1025
1034
|
getStack: getStack2,
|
|
1026
1035
|
templateReplace,
|
|
1027
1036
|
paused
|
|
1028
1037
|
}) => {
|
|
1029
1038
|
const holder = getCustomActionHolder(ctx, fn);
|
|
1039
|
+
const cleanupHolder = getCustomActionCleanupHolder(ctx);
|
|
1040
|
+
const cleanupNode = () => {
|
|
1041
|
+
if (!cleanupHolder.some((item) => item.fn.id === fn.id && item.fn.key === fn.key)) {
|
|
1042
|
+
holder.node = null;
|
|
1043
|
+
setMountElement(null);
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
const cleanupSource = {
|
|
1047
|
+
fn,
|
|
1048
|
+
list: /* @__PURE__ */ new Set(),
|
|
1049
|
+
dom: cleanupNode
|
|
1050
|
+
};
|
|
1051
|
+
cleanupHolder.push(cleanupSource);
|
|
1030
1052
|
const flags = {
|
|
1031
1053
|
...ctx.meta
|
|
1032
1054
|
};
|
|
@@ -1045,15 +1067,7 @@ var handleCustomAction = (ctx, fn, {
|
|
|
1045
1067
|
};
|
|
1046
1068
|
};
|
|
1047
1069
|
const clear = (func) => {
|
|
1048
|
-
|
|
1049
|
-
holder.cleanup = () => {
|
|
1050
|
-
func();
|
|
1051
|
-
holder.node = null;
|
|
1052
|
-
holder.cleanup = noop;
|
|
1053
|
-
setMountElement(null);
|
|
1054
|
-
setClear(noop);
|
|
1055
|
-
}
|
|
1056
|
-
);
|
|
1070
|
+
cleanupSource.list.add(once2(func));
|
|
1057
1071
|
};
|
|
1058
1072
|
const data = (updatedData) => {
|
|
1059
1073
|
if (updatedData) {
|
|
@@ -1062,13 +1076,12 @@ var handleCustomAction = (ctx, fn, {
|
|
|
1062
1076
|
return holder.localData;
|
|
1063
1077
|
};
|
|
1064
1078
|
const remove = () => {
|
|
1065
|
-
|
|
1079
|
+
cleanupSource.list.forEach((fn2) => fn2());
|
|
1080
|
+
cleanupSource.list.clear();
|
|
1081
|
+
cleanupSource.dom();
|
|
1066
1082
|
renderersRemove();
|
|
1067
1083
|
};
|
|
1068
1084
|
const stack = getStack2(ctx);
|
|
1069
|
-
const getPath = () => {
|
|
1070
|
-
return stack.value[0];
|
|
1071
|
-
};
|
|
1072
1085
|
const getSave = () => {
|
|
1073
1086
|
return stack.value;
|
|
1074
1087
|
};
|
|
@@ -1077,13 +1090,13 @@ var handleCustomAction = (ctx, fn, {
|
|
|
1077
1090
|
lang,
|
|
1078
1091
|
state,
|
|
1079
1092
|
data,
|
|
1093
|
+
dataAtKey: (key) => CUSTOM_ACTION_MAP.get(ctx.id + key)?.localData || null,
|
|
1080
1094
|
templateReplace,
|
|
1081
1095
|
clear,
|
|
1082
1096
|
remove,
|
|
1083
1097
|
rendererContext: ctx,
|
|
1084
1098
|
getDomNodes,
|
|
1085
1099
|
getSave,
|
|
1086
|
-
getPath,
|
|
1087
1100
|
contextKey: ctx.id,
|
|
1088
1101
|
paused: flags.preview ? immutable(false) : paused
|
|
1089
1102
|
});
|
|
@@ -1610,13 +1623,7 @@ var novely = ({
|
|
|
1610
1623
|
filter: false,
|
|
1611
1624
|
referGuarded
|
|
1612
1625
|
});
|
|
1613
|
-
const
|
|
1614
|
-
run,
|
|
1615
|
-
keep: { keep, characters: characters2, audio: audio2 }
|
|
1616
|
-
} = createQueueProcessor(queue, {
|
|
1617
|
-
skip,
|
|
1618
|
-
skipPreserve
|
|
1619
|
-
});
|
|
1626
|
+
const cleanupHolder = getCustomActionCleanupHolder(context);
|
|
1620
1627
|
if (previous) {
|
|
1621
1628
|
const { queue: prevQueue } = await getActionsFromPath({
|
|
1622
1629
|
story,
|
|
@@ -1624,17 +1631,38 @@ var novely = ({
|
|
|
1624
1631
|
filter: false,
|
|
1625
1632
|
referGuarded
|
|
1626
1633
|
});
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
const [action2, fn] = element;
|
|
1634
|
+
const futures = [];
|
|
1635
|
+
const isFromDifferentBranches = previous[0][0][1] !== path[0][1];
|
|
1636
|
+
const end = isFromDifferentBranches ? 0 : queue.length - 1;
|
|
1637
|
+
for (let i = prevQueue.length - 1; i >= end; i--) {
|
|
1638
|
+
const [action2, fn] = prevQueue[i];
|
|
1633
1639
|
if (action2 === "custom") {
|
|
1634
|
-
|
|
1640
|
+
futures.push(fn);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
futures.reverse();
|
|
1644
|
+
const dom = /* @__PURE__ */ new Set();
|
|
1645
|
+
for (const future of futures) {
|
|
1646
|
+
inner: for (let i = cleanupHolder.length - 1; i >= 0; i--) {
|
|
1647
|
+
const item = cleanupHolder[i];
|
|
1648
|
+
if (future === item.fn) {
|
|
1649
|
+
item.list.forEach((fn) => fn());
|
|
1650
|
+
item.list.clear();
|
|
1651
|
+
cleanupHolder.splice(i, 1);
|
|
1652
|
+
dom.add(item.dom);
|
|
1653
|
+
break inner;
|
|
1654
|
+
}
|
|
1635
1655
|
}
|
|
1636
1656
|
}
|
|
1657
|
+
dom.forEach((f) => f());
|
|
1637
1658
|
}
|
|
1659
|
+
const {
|
|
1660
|
+
run,
|
|
1661
|
+
keep: { keep, characters: characters2, audio: audio2 }
|
|
1662
|
+
} = createQueueProcessor(queue, {
|
|
1663
|
+
skip,
|
|
1664
|
+
skipPreserve
|
|
1665
|
+
});
|
|
1638
1666
|
if (context.meta.goingBack) {
|
|
1639
1667
|
match("clear", [keep, characters2, audio2], {
|
|
1640
1668
|
ctx: context,
|
|
@@ -1650,6 +1678,11 @@ var novely = ({
|
|
|
1650
1678
|
return;
|
|
1651
1679
|
}
|
|
1652
1680
|
const [action2, ...props] = item;
|
|
1681
|
+
if (action2 === "custom") {
|
|
1682
|
+
if (cleanupHolder.some((holder) => holder.fn === props[0])) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1653
1686
|
return match(action2, props, {
|
|
1654
1687
|
ctx: context,
|
|
1655
1688
|
data: latest[1]
|
|
@@ -1783,8 +1816,16 @@ var novely = ({
|
|
|
1783
1816
|
}
|
|
1784
1817
|
return capitalize(language.nameOverride || getIntlLanguageDisplayName(lang));
|
|
1785
1818
|
};
|
|
1786
|
-
const
|
|
1787
|
-
|
|
1819
|
+
const clearCustomActionsAtContext = (ctx) => {
|
|
1820
|
+
const cleanupHolder = getCustomActionCleanupHolder(ctx);
|
|
1821
|
+
const dom = /* @__PURE__ */ new Set();
|
|
1822
|
+
for (const item of cleanupHolder) {
|
|
1823
|
+
item.list.forEach((fn) => fn());
|
|
1824
|
+
item.list.clear();
|
|
1825
|
+
dom.add(item.dom);
|
|
1826
|
+
}
|
|
1827
|
+
cleanupHolder.length = 0;
|
|
1828
|
+
dom.forEach((fn) => fn());
|
|
1788
1829
|
};
|
|
1789
1830
|
const getResourseTypeWrapper = (url) => {
|
|
1790
1831
|
return getResourseType({
|
|
@@ -1839,7 +1880,7 @@ var novely = ({
|
|
|
1839
1880
|
preview,
|
|
1840
1881
|
removeContext,
|
|
1841
1882
|
getStateFunction,
|
|
1842
|
-
|
|
1883
|
+
clearCustomActionsAtContext,
|
|
1843
1884
|
languages,
|
|
1844
1885
|
storageData,
|
|
1845
1886
|
coreData,
|