@react-text-game/core 0.1.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.
Files changed (178) hide show
  1. package/README.md +744 -0
  2. package/dist/baseGameObject.d.ts +90 -0
  3. package/dist/baseGameObject.d.ts.map +1 -0
  4. package/dist/baseGameObject.js +109 -0
  5. package/dist/baseGameObject.js.map +1 -0
  6. package/dist/constants.d.ts +12 -0
  7. package/dist/constants.d.ts.map +1 -0
  8. package/dist/constants.js +12 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/game.d.ts +294 -0
  11. package/dist/game.d.ts.map +1 -0
  12. package/dist/game.js +489 -0
  13. package/dist/game.js.map +1 -0
  14. package/dist/helpers.d.ts +2 -0
  15. package/dist/helpers.d.ts.map +1 -0
  16. package/dist/helpers.js +6 -0
  17. package/dist/helpers.js.map +1 -0
  18. package/dist/hooks/index.d.ts +4 -0
  19. package/dist/hooks/index.d.ts.map +1 -0
  20. package/dist/hooks/index.js +4 -0
  21. package/dist/hooks/index.js.map +1 -0
  22. package/dist/hooks/useCurrentPassage.d.ts +10 -0
  23. package/dist/hooks/useCurrentPassage.d.ts.map +1 -0
  24. package/dist/hooks/useCurrentPassage.js +17 -0
  25. package/dist/hooks/useCurrentPassage.js.map +1 -0
  26. package/dist/hooks/useGameEntity.d.ts +21 -0
  27. package/dist/hooks/useGameEntity.d.ts.map +1 -0
  28. package/dist/hooks/useGameEntity.js +70 -0
  29. package/dist/hooks/useGameEntity.js.map +1 -0
  30. package/dist/hooks/useGameIsStarted.d.ts +12 -0
  31. package/dist/hooks/useGameIsStarted.d.ts.map +1 -0
  32. package/dist/hooks/useGameIsStarted.js +18 -0
  33. package/dist/hooks/useGameIsStarted.js.map +1 -0
  34. package/dist/index.d.ts +12 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +10 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/logger.d.ts +8 -0
  39. package/dist/logger.d.ts.map +1 -0
  40. package/dist/logger.js +36 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/options.d.ts +13 -0
  43. package/dist/options.d.ts.map +1 -0
  44. package/dist/options.js +15 -0
  45. package/dist/options.js.map +1 -0
  46. package/dist/passages/interactiveMap/fabric.d.ts +4 -0
  47. package/dist/passages/interactiveMap/fabric.d.ts.map +1 -0
  48. package/dist/passages/interactiveMap/fabric.js +3 -0
  49. package/dist/passages/interactiveMap/fabric.js.map +1 -0
  50. package/dist/passages/interactiveMap/index.d.ts +4 -0
  51. package/dist/passages/interactiveMap/index.d.ts.map +1 -0
  52. package/dist/passages/interactiveMap/index.js +4 -0
  53. package/dist/passages/interactiveMap/index.js.map +1 -0
  54. package/dist/passages/interactiveMap/interactiveMap.d.ts +89 -0
  55. package/dist/passages/interactiveMap/interactiveMap.d.ts.map +1 -0
  56. package/dist/passages/interactiveMap/interactiveMap.js +103 -0
  57. package/dist/passages/interactiveMap/interactiveMap.js.map +1 -0
  58. package/dist/passages/interactiveMap/types.d.ts +822 -0
  59. package/dist/passages/interactiveMap/types.d.ts.map +1 -0
  60. package/dist/passages/interactiveMap/types.js +2 -0
  61. package/dist/passages/interactiveMap/types.js.map +1 -0
  62. package/dist/passages/passage.d.ts +57 -0
  63. package/dist/passages/passage.d.ts.map +1 -0
  64. package/dist/passages/passage.js +64 -0
  65. package/dist/passages/passage.js.map +1 -0
  66. package/dist/passages/story/fabric.d.ts +4 -0
  67. package/dist/passages/story/fabric.d.ts.map +1 -0
  68. package/dist/passages/story/fabric.js +3 -0
  69. package/dist/passages/story/fabric.js.map +1 -0
  70. package/dist/passages/story/index.d.ts +5 -0
  71. package/dist/passages/story/index.d.ts.map +1 -0
  72. package/dist/passages/story/index.js +5 -0
  73. package/dist/passages/story/index.js.map +1 -0
  74. package/dist/passages/story/start.d.ts +14 -0
  75. package/dist/passages/story/start.d.ts.map +1 -0
  76. package/dist/passages/story/start.js +22 -0
  77. package/dist/passages/story/start.js.map +1 -0
  78. package/dist/passages/story/story.d.ts +84 -0
  79. package/dist/passages/story/story.d.ts.map +1 -0
  80. package/dist/passages/story/story.js +88 -0
  81. package/dist/passages/story/story.js.map +1 -0
  82. package/dist/passages/story/types.d.ts +911 -0
  83. package/dist/passages/story/types.d.ts.map +1 -0
  84. package/dist/passages/story/types.js +2 -0
  85. package/dist/passages/story/types.js.map +1 -0
  86. package/dist/passages/types/index.d.ts +3 -0
  87. package/dist/passages/types/index.d.ts.map +1 -0
  88. package/dist/passages/types/index.js +2 -0
  89. package/dist/passages/types/index.js.map +1 -0
  90. package/dist/passages/widget.d.ts +62 -0
  91. package/dist/passages/widget.d.ts.map +1 -0
  92. package/dist/passages/widget.js +66 -0
  93. package/dist/passages/widget.js.map +1 -0
  94. package/dist/saves/constants.d.ts +17 -0
  95. package/dist/saves/constants.d.ts.map +1 -0
  96. package/dist/saves/constants.js +17 -0
  97. package/dist/saves/constants.js.map +1 -0
  98. package/dist/saves/db.d.ts +119 -0
  99. package/dist/saves/db.d.ts.map +1 -0
  100. package/dist/saves/db.js +231 -0
  101. package/dist/saves/db.js.map +1 -0
  102. package/dist/saves/helpers.d.ts +28 -0
  103. package/dist/saves/helpers.d.ts.map +1 -0
  104. package/dist/saves/helpers.js +84 -0
  105. package/dist/saves/helpers.js.map +1 -0
  106. package/dist/saves/hooks/index.d.ts +10 -0
  107. package/dist/saves/hooks/index.d.ts.map +1 -0
  108. package/dist/saves/hooks/index.js +10 -0
  109. package/dist/saves/hooks/index.js.map +1 -0
  110. package/dist/saves/hooks/useDeleteAllSlots.d.ts +18 -0
  111. package/dist/saves/hooks/useDeleteAllSlots.d.ts.map +1 -0
  112. package/dist/saves/hooks/useDeleteAllSlots.js +18 -0
  113. package/dist/saves/hooks/useDeleteAllSlots.js.map +1 -0
  114. package/dist/saves/hooks/useDeleteGame.d.ts +22 -0
  115. package/dist/saves/hooks/useDeleteGame.d.ts.map +1 -0
  116. package/dist/saves/hooks/useDeleteGame.js +33 -0
  117. package/dist/saves/hooks/useDeleteGame.js.map +1 -0
  118. package/dist/saves/hooks/useExportSaves.d.ts +27 -0
  119. package/dist/saves/hooks/useExportSaves.d.ts.map +1 -0
  120. package/dist/saves/hooks/useExportSaves.js +54 -0
  121. package/dist/saves/hooks/useExportSaves.js.map +1 -0
  122. package/dist/saves/hooks/useImportSaves.d.ts +29 -0
  123. package/dist/saves/hooks/useImportSaves.d.ts.map +1 -0
  124. package/dist/saves/hooks/useImportSaves.js +108 -0
  125. package/dist/saves/hooks/useImportSaves.js.map +1 -0
  126. package/dist/saves/hooks/useLastLoadGame.d.ts +39 -0
  127. package/dist/saves/hooks/useLastLoadGame.d.ts.map +1 -0
  128. package/dist/saves/hooks/useLastLoadGame.js +72 -0
  129. package/dist/saves/hooks/useLastLoadGame.js.map +1 -0
  130. package/dist/saves/hooks/useLoadGame.d.ts +22 -0
  131. package/dist/saves/hooks/useLoadGame.d.ts.map +1 -0
  132. package/dist/saves/hooks/useLoadGame.js +40 -0
  133. package/dist/saves/hooks/useLoadGame.js.map +1 -0
  134. package/dist/saves/hooks/useRestartGame.d.ts +20 -0
  135. package/dist/saves/hooks/useRestartGame.d.ts.map +1 -0
  136. package/dist/saves/hooks/useRestartGame.js +29 -0
  137. package/dist/saves/hooks/useRestartGame.js.map +1 -0
  138. package/dist/saves/hooks/useSaveGame.d.ts +22 -0
  139. package/dist/saves/hooks/useSaveGame.d.ts.map +1 -0
  140. package/dist/saves/hooks/useSaveGame.js +34 -0
  141. package/dist/saves/hooks/useSaveGame.js.map +1 -0
  142. package/dist/saves/hooks/useSaveSlots.d.ts +45 -0
  143. package/dist/saves/hooks/useSaveSlots.d.ts.map +1 -0
  144. package/dist/saves/hooks/useSaveSlots.js +42 -0
  145. package/dist/saves/hooks/useSaveSlots.js.map +1 -0
  146. package/dist/saves/index.d.ts +4 -0
  147. package/dist/saves/index.d.ts.map +1 -0
  148. package/dist/saves/index.js +3 -0
  149. package/dist/saves/index.js.map +1 -0
  150. package/dist/saves/types.d.ts +52 -0
  151. package/dist/saves/types.d.ts.map +1 -0
  152. package/dist/saves/types.js +2 -0
  153. package/dist/saves/types.js.map +1 -0
  154. package/dist/storage.d.ts +124 -0
  155. package/dist/storage.d.ts.map +1 -0
  156. package/dist/storage.js +229 -0
  157. package/dist/storage.js.map +1 -0
  158. package/dist/tests/game.test.d.ts +2 -0
  159. package/dist/tests/game.test.d.ts.map +1 -0
  160. package/dist/tests/game.test.js +602 -0
  161. package/dist/tests/game.test.js.map +1 -0
  162. package/dist/tests/interactiveMap.test.d.ts +2 -0
  163. package/dist/tests/interactiveMap.test.d.ts.map +1 -0
  164. package/dist/tests/interactiveMap.test.js +1003 -0
  165. package/dist/tests/interactiveMap.test.js.map +1 -0
  166. package/dist/tests/storage.test.d.ts +2 -0
  167. package/dist/tests/storage.test.d.ts.map +1 -0
  168. package/dist/tests/storage.test.js +328 -0
  169. package/dist/tests/storage.test.js.map +1 -0
  170. package/dist/tests/story.test.d.ts +2 -0
  171. package/dist/tests/story.test.d.ts.map +1 -0
  172. package/dist/tests/story.test.js +698 -0
  173. package/dist/tests/story.test.js.map +1 -0
  174. package/dist/types.d.ts +19 -0
  175. package/dist/types.d.ts.map +1 -0
  176. package/dist/types.js +2 -0
  177. package/dist/types.js.map +1 -0
  178. package/package.json +60 -0
@@ -0,0 +1,40 @@
1
+ import { Game } from "../../game";
2
+ import { loadGame } from "../../saves";
3
+ /**
4
+ * React hook that provides a function to load a saved game by its ID.
5
+ * Restores the game state from the specified save.
6
+ *
7
+ * @returns Function that accepts an optional save ID and loads the game, returning a result object on failure
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const loadGame = useLoadGame();
12
+ * const handleLoad = async () => {
13
+ * const result = await loadGame(saveId);
14
+ * if (result?.success === false) {
15
+ * console.error('Load failed:', result.message);
16
+ * }
17
+ * };
18
+ * ```
19
+ */
20
+ export const useLoadGame = () => async (id) => {
21
+ try {
22
+ const data = await loadGame(id);
23
+ if (!data) {
24
+ return {
25
+ success: false,
26
+ message: "The requested game save does not exist",
27
+ };
28
+ }
29
+ Game.setState(data.gameData);
30
+ }
31
+ catch (e) {
32
+ console.error("Failed to load game:", e);
33
+ return {
34
+ success: false,
35
+ message: e.message ||
36
+ "Failed to load game. Check console for more info.",
37
+ };
38
+ }
39
+ };
40
+ //# sourceMappingURL=useLoadGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useLoadGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;IAClD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,wCAAwC;aACpD,CAAC;QACN,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EACF,CAAW,CAAC,OAAO;gBACpB,mDAAmD;SAC1D,CAAC;IACN,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * React hook that provides a function to restart the game from the initial state.
3
+ * Loads the system save (initial game state), clears auto-save, and navigates to start passage.
4
+ *
5
+ * @returns Callback function that restarts the game
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const restartGame = useRestartGame();
10
+ * <button onClick={restartGame}>Restart Game</button>
11
+ * ```
12
+ */
13
+ export declare const useRestartGame: () => () => Promise<{
14
+ success: boolean;
15
+ error: string;
16
+ } | {
17
+ success: boolean;
18
+ error: null;
19
+ }>;
20
+ //# sourceMappingURL=useRestartGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRestartGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useRestartGame.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc;;;;;;EAe1B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { useCallback } from "react";
2
+ import { SYSTEM_PASSAGE_NAMES } from "../../constants";
3
+ import { Game } from "../../game";
4
+ import { getSystemSave } from "../../saves";
5
+ /**
6
+ * React hook that provides a function to restart the game from the initial state.
7
+ * Loads the system save (initial game state), clears auto-save, and navigates to start passage.
8
+ *
9
+ * @returns Callback function that restarts the game
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const restartGame = useRestartGame();
14
+ * <button onClick={restartGame}>Restart Game</button>
15
+ * ```
16
+ */
17
+ export const useRestartGame = () => {
18
+ return useCallback(async () => {
19
+ const systemSave = await getSystemSave();
20
+ if (!systemSave) {
21
+ return { success: false, error: "System save not found. Cannot restart game." };
22
+ }
23
+ Game.clearAutoSave();
24
+ Game.setState(systemSave.gameData);
25
+ Game.jumpTo(SYSTEM_PASSAGE_NAMES.START_MENU);
26
+ return { success: true, error: null };
27
+ }, []);
28
+ };
29
+ //# sourceMappingURL=useRestartGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRestartGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useRestartGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,EAAE;IAC/B,OAAO,WAAW,CAAC,KAAK,IAAI,EAAE;QAC1B,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE,CAAC;QAEzC,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAA;QACnF,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAEnC,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAE7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC1C,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * React hook that provides a function to save the current game state to a specific slot.
3
+ * The save is stored in IndexedDB with the slot number as the save name.
4
+ *
5
+ * @returns Function that accepts a slot number and saves the game, returning a result object on failure
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * const saveGame = useSaveGame();
10
+ * const handleSave = async () => {
11
+ * const result = await saveGame(1);
12
+ * if (result?.success === false) {
13
+ * console.error('Save failed:', result.message);
14
+ * }
15
+ * };
16
+ * ```
17
+ */
18
+ export declare const useSaveGame: () => (id: number) => Promise<{
19
+ success: boolean;
20
+ message: string;
21
+ } | undefined>;
22
+ //# sourceMappingURL=useSaveGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveGame.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveGame.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,WAAW,SAAgB,IAAI,MAAM;;;cAcjD,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { Game } from "../../game";
2
+ import { saveGame } from "../../saves";
3
+ /**
4
+ * React hook that provides a function to save the current game state to a specific slot.
5
+ * The save is stored in IndexedDB with the slot number as the save name.
6
+ *
7
+ * @returns Function that accepts a slot number and saves the game, returning a result object on failure
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const saveGame = useSaveGame();
12
+ * const handleSave = async () => {
13
+ * const result = await saveGame(1);
14
+ * if (result?.success === false) {
15
+ * console.error('Save failed:', result.message);
16
+ * }
17
+ * };
18
+ * ```
19
+ */
20
+ export const useSaveGame = () => async (id) => {
21
+ const data = Game.getState();
22
+ try {
23
+ await saveGame(id, data);
24
+ }
25
+ catch (e) {
26
+ console.error("Failed to save game:", e);
27
+ return {
28
+ success: false,
29
+ message: e.message ||
30
+ "Failed to save game. Check console for more info.",
31
+ };
32
+ }
33
+ };
34
+ //# sourceMappingURL=useSaveGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveGame.js","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;IAE7B,IAAI,CAAC;QACD,MAAM,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO;YACH,OAAO,EAAE,KAAK;YACd,OAAO,EACF,CAAW,CAAC,OAAO;gBACpB,mDAAmD;SAC1D,CAAC;IACN,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { GameSave } from "../../saves";
2
+ /**
3
+ * React hook that provides an array of save slots with live updates from IndexedDB.
4
+ * Each slot includes the save data and methods to save, load, and delete.
5
+ *
6
+ * @param config - Configuration object
7
+ * @param config.count - Number of save slots to create (defaults to 1)
8
+ * @returns Array of save slot objects, each containing data and action methods
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const slots = useSaveSlots({ count: 5 });
13
+ *
14
+ * return (
15
+ * <div>
16
+ * {slots.map((slot, index) => (
17
+ * <div key={index}>
18
+ * <p>Slot {index}: {slot.data ? 'Saved' : 'Empty'}</p>
19
+ * <button onClick={() => slot.save()}>Save</button>
20
+ * <button onClick={() => slot.load()} disabled={!slot.data}>Load</button>
21
+ * <button onClick={() => slot.delete()} disabled={!slot.data}>Delete</button>
22
+ * </div>
23
+ * ))}
24
+ * </div>
25
+ * );
26
+ * ```
27
+ */
28
+ export declare const useSaveSlots: ({ count }?: {
29
+ count: number;
30
+ }) => {
31
+ data: GameSave | null;
32
+ save: () => Promise<{
33
+ success: boolean;
34
+ message: string;
35
+ } | undefined>;
36
+ load: () => Promise<{
37
+ success: boolean;
38
+ message: string;
39
+ } | undefined>;
40
+ delete: () => Promise<{
41
+ success: boolean;
42
+ message: string;
43
+ } | undefined>;
44
+ }[];
45
+ //# sourceMappingURL=useSaveSlots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveSlots.d.ts","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveSlots.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAwD,MAAM,QAAQ,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,GAAI;;CAAwB;;;;;;;;;;;;;;GAkBpD,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { useLiveQuery } from "dexie-react-hooks";
2
+ import { useMemo } from "react";
3
+ import { getAllSaves, useDeleteGame, useLoadGame, useSaveGame } from "../../saves";
4
+ /**
5
+ * React hook that provides an array of save slots with live updates from IndexedDB.
6
+ * Each slot includes the save data and methods to save, load, and delete.
7
+ *
8
+ * @param config - Configuration object
9
+ * @param config.count - Number of save slots to create (defaults to 1)
10
+ * @returns Array of save slot objects, each containing data and action methods
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const slots = useSaveSlots({ count: 5 });
15
+ *
16
+ * return (
17
+ * <div>
18
+ * {slots.map((slot, index) => (
19
+ * <div key={index}>
20
+ * <p>Slot {index}: {slot.data ? 'Saved' : 'Empty'}</p>
21
+ * <button onClick={() => slot.save()}>Save</button>
22
+ * <button onClick={() => slot.load()} disabled={!slot.data}>Load</button>
23
+ * <button onClick={() => slot.delete()} disabled={!slot.data}>Delete</button>
24
+ * </div>
25
+ * ))}
26
+ * </div>
27
+ * );
28
+ * ```
29
+ */
30
+ export const useSaveSlots = ({ count } = { count: 1 }) => {
31
+ const data = useLiveQuery(() => getAllSaves(), [], []);
32
+ const deleteGameHandler = useDeleteGame();
33
+ const saveGameHandler = useSaveGame();
34
+ const loadGameHandler = useLoadGame();
35
+ return useMemo(() => Array.from({ length: count }).map((_, index) => ({
36
+ data: data?.find((slot) => slot.name === `${index}`) || null,
37
+ save: async () => saveGameHandler(index),
38
+ load: async () => loadGameHandler(index),
39
+ delete: async () => deleteGameHandler(index),
40
+ })), [data, count, deleteGameHandler, loadGameHandler, saveGameHandler]);
41
+ };
42
+ //# sourceMappingURL=useSaveSlots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSaveSlots.js","sourceRoot":"","sources":["../../../src/saves/hooks/useSaveSlots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAY,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;IACrD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,EAAgB,CAAC,CAAC;IACrE,MAAM,iBAAiB,GAAG,aAAa,EAAE,CAAC;IAC1C,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;IACtC,MAAM,eAAe,GAAG,WAAW,EAAE,CAAC;IAEtC,OAAO,OAAO,CACV,GAAG,EAAE,CACD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAC7B,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACX,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK,EAAE,CAAC,IAAI,IAAI;QAC5D,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;QACxC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;QACxC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC;KAC/C,CAAC,CACL,EACL,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,CAAC,CACrE,CAAC;AACN,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './db';
2
+ export * from './hooks';
3
+ export type * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/saves/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC;AACxB,mBAAmB,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './db';
2
+ export * from './hooks';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/saves/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,SAAS,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Represents a saved game state
3
+ */
4
+ export interface GameSave {
5
+ /** Database auto-generated ID */
6
+ id?: number;
7
+ /** User-defined name for the save */
8
+ name: string;
9
+ /** Serialized game state data */
10
+ gameData: Record<string, unknown>;
11
+ /** When the save was created */
12
+ timestamp: Date;
13
+ /** Game version when the save was created */
14
+ version: string;
15
+ /** Base64 encoded screenshot (optional) */
16
+ screenshot?: string;
17
+ /** User-provided description (optional) */
18
+ description?: string;
19
+ /** Mark as system save (won't be shown in UI) */
20
+ isSystemSave?: boolean;
21
+ }
22
+ /**
23
+ * Represents a game setting stored in the database
24
+ */
25
+ export interface GameSettings {
26
+ /** Database auto-generated ID */
27
+ id?: number;
28
+ /** Unique key for the setting */
29
+ key: string;
30
+ /** Setting value (can be string, number, boolean, or object) */
31
+ value: string | number | boolean | object;
32
+ /** When the setting was last updated */
33
+ timestamp: Date;
34
+ /** Game version when the setting was created/updated */
35
+ version: string;
36
+ }
37
+ /**
38
+ * Represents the state of save slots, used by React hooks
39
+ */
40
+ export type SaveSlotsData = {
41
+ /** Whether there are no saves */
42
+ isEmpty: boolean;
43
+ /** Whether saves are currently being loaded */
44
+ isLoading: boolean;
45
+ /** Whether there was an error loading saves */
46
+ isError: boolean;
47
+ /** Error object if an error occurred */
48
+ error: Error | null;
49
+ /** Array of game saves */
50
+ data: GameSave[];
51
+ };
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/saves/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,gCAAgC;IAChC,SAAS,EAAE,IAAI,CAAC;IAChB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IACzB,iCAAiC;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC1C,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IACxB,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,0BAA0B;IAC1B,IAAI,EAAE,QAAQ,EAAE,CAAC;CACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/saves/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,124 @@
1
+ import { GameSaveState, JsonPath } from "./types";
2
+ /**
3
+ * JSONPath-based storage system for game state persistence.
4
+ *
5
+ * The Storage class provides a flexible way to store and retrieve game state using
6
+ * JSONPath queries. It supports nested data structures and protects system paths
7
+ * from accidental modification.
8
+ *
9
+ * @see https://www.npmjs.com/package/jsonpath-plus - JSONPath Plus library documentation
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Set values
14
+ * Storage.setValue('$.player.health', 100);
15
+ * Storage.setValue('$.inventory.items', ['sword', 'shield']);
16
+ *
17
+ * // Get values
18
+ * const health = Storage.getValue<number>('$.player.health');
19
+ * const items = Storage.getValue<string[]>('$.inventory.items');
20
+ *
21
+ * // Full state
22
+ * const state = Storage.getState();
23
+ * Storage.setState(state);
24
+ * ```
25
+ */
26
+ export declare class Storage {
27
+ /**
28
+ * Retrieves values from storage using a JSONPath query.
29
+ *
30
+ * Returns an array of matching values. If no matches are found, returns an empty array.
31
+ * The JSONPath Plus library supports complex queries including wildcards, filters, and deep scanning.
32
+ *
33
+ * @template T - The expected type of values to retrieve
34
+ * @param jsonPath - The JSONPath query string (e.g., '$.player.health', '$.inventory.items[*]')
35
+ * @returns Array of values matching the JSONPath query
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // Get a single value (returns array with one element)
40
+ * const health = Storage.getValue<number>('$.player.health');
41
+ * if (health.length > 0) {
42
+ * console.log(health[0]); // 100
43
+ * }
44
+ *
45
+ * // Get multiple values with wildcard
46
+ * const allItems = Storage.getValue<string>('$.inventory.*.name');
47
+ * ```
48
+ */
49
+ static getValue<T>(jsonPath: JsonPath): Array<T>;
50
+ /**
51
+ * Sets a value in storage at the specified JSONPath.
52
+ *
53
+ * If the path exists, updates the value. If the path doesn't exist, creates it.
54
+ * System paths (prefixed with STORAGE_SYSTEM_PATH) are protected from external modification.
55
+ *
56
+ * @template T - The type of value to set
57
+ * @param jsonPath - The JSONPath where the value should be set
58
+ * @param value - The value to set at the specified JSONPath
59
+ * @param _isSystem - Internal flag to allow system path modification (default: false)
60
+ * @throws Error if attempting to modify a system path without _isSystem flag
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * // Set a simple value
65
+ * Storage.setValue('$.player.health', 75);
66
+ *
67
+ * // Set a complex object
68
+ * Storage.setValue('$.player.stats', { str: 10, dex: 8 });
69
+ *
70
+ * // System paths are protected
71
+ * Storage.setValue('$._system.game', {}); // Throws error
72
+ * ```
73
+ */
74
+ static setValue<T>(jsonPath: JsonPath, value: T, _isSystem?: boolean): void;
75
+ /**
76
+ * Retrieves the entire storage state as a plain object.
77
+ *
78
+ * @returns The complete storage state, ready for serialization
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const state = Storage.getState();
83
+ * localStorage.setItem('save', JSON.stringify(state));
84
+ * ```
85
+ */
86
+ static getState(): GameSaveState;
87
+ /**
88
+ * Replaces the entire storage state with a new state object.
89
+ *
90
+ * Clears all existing storage data and replaces it with the provided state.
91
+ * Useful for loading saved games or resetting to a specific state.
92
+ *
93
+ * @param state - The new state to set for the storage
94
+ * @throws Error if state is not a valid object
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const savedState = JSON.parse(localStorage.getItem('save'));
99
+ * Storage.setState(savedState);
100
+ * ```
101
+ */
102
+ static setState(state: GameSaveState): void;
103
+ /**
104
+ * Creates a nested path in storage and assigns a value.
105
+ *
106
+ * Parses the JSONPath and creates all necessary intermediate objects/arrays
107
+ * to build the path if it doesn't exist. Supports both object properties and array indices.
108
+ *
109
+ * @private - Used internally by setValue when creating new paths
110
+ * @template T - The type of value to set at the path
111
+ * @param obj - The target object where the path will be created
112
+ * @param jsonPath - The JSONPath string specifying the location
113
+ * @param value - The value to set at the specified location
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * // Creates $.player.inventory.items[0] = 'sword'
118
+ * // Will create player object, inventory object, items array automatically
119
+ * Storage.createPath(storage, '$.player.inventory.items[0]', 'sword');
120
+ * ```
121
+ */
122
+ private static createPath;
123
+ }
124
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,OAAO;IAChB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;IAIhD;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EACb,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,CAAC,EACR,SAAS,GAAE,OAAe,GAC3B,IAAI;IAkCP;;;;;;;;;;OAUG;IACH,MAAM,CAAC,QAAQ,IAAI,aAAa;IAIhC;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAY3C;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CA8E5B"}