@voidhash/mimic-react 0.0.1 → 0.0.3

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 (61) hide show
  1. package/.turbo/turbo-build.log +60 -26
  2. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/defineProperty.cjs +14 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/defineProperty.mjs +14 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.cjs +27 -0
  5. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs +27 -0
  6. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.cjs +16 -0
  7. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPrimitive.mjs +16 -0
  8. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPropertyKey.cjs +11 -0
  9. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/toPropertyKey.mjs +11 -0
  10. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/typeof.cjs +18 -0
  11. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/typeof.mjs +12 -0
  12. package/dist/zustand/index.cjs +2 -94
  13. package/dist/zustand/index.d.cts +3 -115
  14. package/dist/zustand/index.d.mts +3 -115
  15. package/dist/zustand/index.mjs +2 -95
  16. package/dist/zustand/middleware.cjs +95 -0
  17. package/dist/zustand/middleware.d.cts +47 -0
  18. package/dist/zustand/middleware.d.cts.map +1 -0
  19. package/dist/zustand/middleware.d.mts +47 -0
  20. package/dist/zustand/middleware.d.mts.map +1 -0
  21. package/dist/zustand/middleware.mjs +96 -0
  22. package/dist/zustand/middleware.mjs.map +1 -0
  23. package/dist/zustand/types.d.cts +75 -0
  24. package/dist/zustand/types.d.cts.map +1 -0
  25. package/dist/zustand/types.d.mts +75 -0
  26. package/dist/zustand/types.d.mts.map +1 -0
  27. package/dist/zustand-commander/commander.cjs +187 -0
  28. package/dist/zustand-commander/commander.d.cts +52 -0
  29. package/dist/zustand-commander/commander.d.cts.map +1 -0
  30. package/dist/zustand-commander/commander.d.mts +52 -0
  31. package/dist/zustand-commander/commander.d.mts.map +1 -0
  32. package/dist/zustand-commander/commander.mjs +185 -0
  33. package/dist/zustand-commander/commander.mjs.map +1 -0
  34. package/dist/zustand-commander/hooks.cjs +145 -0
  35. package/dist/zustand-commander/hooks.d.cts +78 -0
  36. package/dist/zustand-commander/hooks.d.cts.map +1 -0
  37. package/dist/zustand-commander/hooks.d.mts +78 -0
  38. package/dist/zustand-commander/hooks.d.mts.map +1 -0
  39. package/dist/zustand-commander/hooks.mjs +144 -0
  40. package/dist/zustand-commander/hooks.mjs.map +1 -0
  41. package/dist/zustand-commander/index.cjs +15 -354
  42. package/dist/zustand-commander/index.d.cts +4 -313
  43. package/dist/zustand-commander/index.d.mts +4 -313
  44. package/dist/zustand-commander/index.mjs +4 -344
  45. package/dist/zustand-commander/types.cjs +28 -0
  46. package/dist/zustand-commander/types.d.cts +195 -0
  47. package/dist/zustand-commander/types.d.cts.map +1 -0
  48. package/dist/zustand-commander/types.d.mts +195 -0
  49. package/dist/zustand-commander/types.d.mts.map +1 -0
  50. package/dist/zustand-commander/types.mjs +25 -0
  51. package/dist/zustand-commander/types.mjs.map +1 -0
  52. package/package.json +3 -3
  53. package/tsdown.config.ts +1 -1
  54. package/dist/objectSpread2-CIP_6jda.cjs +0 -73
  55. package/dist/objectSpread2-CxTyNSYl.mjs +0 -67
  56. package/dist/zustand/index.d.cts.map +0 -1
  57. package/dist/zustand/index.d.mts.map +0 -1
  58. package/dist/zustand/index.mjs.map +0 -1
  59. package/dist/zustand-commander/index.d.cts.map +0 -1
  60. package/dist/zustand-commander/index.d.mts.map +0 -1
  61. package/dist/zustand-commander/index.mjs.map +0 -1
@@ -0,0 +1,78 @@
1
+ import { CommandDispatch, CommanderSlice } from "./types.cjs";
2
+ import { StoreApi, UseBoundStore } from "zustand";
3
+
4
+ //#region src/zustand-commander/hooks.d.ts
5
+
6
+ /**
7
+ * React hook to get a dispatch function for commands.
8
+ * The dispatch function executes commands and manages undo/redo state.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const dispatch = useCommander(useStore);
13
+ *
14
+ * const handleClick = () => {
15
+ * dispatch(addCard)({ columnId: "col-1", title: "New Card" });
16
+ * };
17
+ * ```
18
+ */
19
+ declare function useCommander<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>): CommandDispatch<TStore>;
20
+ /**
21
+ * State and actions for undo/redo functionality.
22
+ */
23
+ interface UndoRedoState {
24
+ /** Whether there are actions that can be undone */
25
+ readonly canUndo: boolean;
26
+ /** Whether there are actions that can be redone */
27
+ readonly canRedo: boolean;
28
+ /** Number of items in the undo stack */
29
+ readonly undoCount: number;
30
+ /** Number of items in the redo stack */
31
+ readonly redoCount: number;
32
+ /** Undo the last action */
33
+ readonly undo: () => boolean;
34
+ /** Redo the last undone action */
35
+ readonly redo: () => boolean;
36
+ /** Clear the undo/redo history */
37
+ readonly clear: () => void;
38
+ }
39
+ /**
40
+ * React hook for undo/redo functionality.
41
+ * Provides state (canUndo, canRedo) and actions (undo, redo, clear).
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * const { canUndo, canRedo, undo, redo } = useUndoRedo(useStore);
46
+ *
47
+ * return (
48
+ * <>
49
+ * <button onClick={undo} disabled={!canUndo}>Undo</button>
50
+ * <button onClick={redo} disabled={!canRedo}>Redo</button>
51
+ * </>
52
+ * );
53
+ * ```
54
+ */
55
+ declare function useUndoRedo<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>): UndoRedoState;
56
+ /**
57
+ * Options for the keyboard shortcut hook.
58
+ */
59
+ interface UseUndoRedoKeyboardOptions {
60
+ /** Enable Ctrl/Cmd+Z for undo (default: true) */
61
+ readonly enableUndo?: boolean;
62
+ /** Enable Ctrl/Cmd+Shift+Z or Ctrl+Y for redo (default: true) */
63
+ readonly enableRedo?: boolean;
64
+ }
65
+ /**
66
+ * React hook that adds keyboard shortcuts for undo/redo.
67
+ * Listens for Ctrl/Cmd+Z (undo) and Ctrl/Cmd+Shift+Z or Ctrl+Y (redo).
68
+ *
69
+ * @example
70
+ * ```tsx
71
+ * // In your app component
72
+ * useUndoRedoKeyboard(useStore);
73
+ * ```
74
+ */
75
+ declare function useUndoRedoKeyboard<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>, options?: UseUndoRedoKeyboardOptions): void;
76
+ //#endregion
77
+ export { UndoRedoState, UseUndoRedoKeyboardOptions, useCommander, useUndoRedo, useUndoRedoKeyboard };
78
+ //# sourceMappingURL=hooks.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.cts","names":[],"sources":["../../src/zustand-commander/hooks.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsHA;AAiCA;;;;;;;AAiDA;AAiBA;AAAmD,iBA5HnC,YA4HmC,CAAA,eA5HP,cA4HO,CAAA,CAAA,KAAA,EA3H1C,aA2H0C,CA3H5B,QA2H4B,CA3HnB,MA2HmB,CAAA,CAAA,CAAA,EA1HhD,eA0HgD,CA1HhC,MA0HgC,CAAA;;;;AAExC,UArGM,aAAA,CAqGN;EAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBApE1B,2BAA2B,uBAClC,cAAc,SAAS,WAC7B;;;;UA+Cc,0BAAA;;;;;;;;;;;;;;;;iBAiBD,mCAAmC,uBAC1C,cAAc,SAAS,oBACrB"}
@@ -0,0 +1,78 @@
1
+ import { CommandDispatch, CommanderSlice } from "./types.mjs";
2
+ import { StoreApi, UseBoundStore } from "zustand";
3
+
4
+ //#region src/zustand-commander/hooks.d.ts
5
+
6
+ /**
7
+ * React hook to get a dispatch function for commands.
8
+ * The dispatch function executes commands and manages undo/redo state.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const dispatch = useCommander(useStore);
13
+ *
14
+ * const handleClick = () => {
15
+ * dispatch(addCard)({ columnId: "col-1", title: "New Card" });
16
+ * };
17
+ * ```
18
+ */
19
+ declare function useCommander<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>): CommandDispatch<TStore>;
20
+ /**
21
+ * State and actions for undo/redo functionality.
22
+ */
23
+ interface UndoRedoState {
24
+ /** Whether there are actions that can be undone */
25
+ readonly canUndo: boolean;
26
+ /** Whether there are actions that can be redone */
27
+ readonly canRedo: boolean;
28
+ /** Number of items in the undo stack */
29
+ readonly undoCount: number;
30
+ /** Number of items in the redo stack */
31
+ readonly redoCount: number;
32
+ /** Undo the last action */
33
+ readonly undo: () => boolean;
34
+ /** Redo the last undone action */
35
+ readonly redo: () => boolean;
36
+ /** Clear the undo/redo history */
37
+ readonly clear: () => void;
38
+ }
39
+ /**
40
+ * React hook for undo/redo functionality.
41
+ * Provides state (canUndo, canRedo) and actions (undo, redo, clear).
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * const { canUndo, canRedo, undo, redo } = useUndoRedo(useStore);
46
+ *
47
+ * return (
48
+ * <>
49
+ * <button onClick={undo} disabled={!canUndo}>Undo</button>
50
+ * <button onClick={redo} disabled={!canRedo}>Redo</button>
51
+ * </>
52
+ * );
53
+ * ```
54
+ */
55
+ declare function useUndoRedo<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>): UndoRedoState;
56
+ /**
57
+ * Options for the keyboard shortcut hook.
58
+ */
59
+ interface UseUndoRedoKeyboardOptions {
60
+ /** Enable Ctrl/Cmd+Z for undo (default: true) */
61
+ readonly enableUndo?: boolean;
62
+ /** Enable Ctrl/Cmd+Shift+Z or Ctrl+Y for redo (default: true) */
63
+ readonly enableRedo?: boolean;
64
+ }
65
+ /**
66
+ * React hook that adds keyboard shortcuts for undo/redo.
67
+ * Listens for Ctrl/Cmd+Z (undo) and Ctrl/Cmd+Shift+Z or Ctrl+Y (redo).
68
+ *
69
+ * @example
70
+ * ```tsx
71
+ * // In your app component
72
+ * useUndoRedoKeyboard(useStore);
73
+ * ```
74
+ */
75
+ declare function useUndoRedoKeyboard<TStore extends CommanderSlice>(store: UseBoundStore<StoreApi<TStore>>, options?: UseUndoRedoKeyboardOptions): void;
76
+ //#endregion
77
+ export { UndoRedoState, UseUndoRedoKeyboardOptions, useCommander, useUndoRedo, useUndoRedoKeyboard };
78
+ //# sourceMappingURL=hooks.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.mts","names":[],"sources":["../../src/zustand-commander/hooks.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAsHA;AAiCA;;;;;;;AAiDA;AAiBA;AAAmD,iBA5HnC,YA4HmC,CAAA,eA5HP,cA4HO,CAAA,CAAA,KAAA,EA3H1C,aA2H0C,CA3H5B,QA2H4B,CA3HnB,MA2HmB,CAAA,CAAA,CAAA,EA1HhD,eA0HgD,CA1HhC,MA0HgC,CAAA;;;;AAExC,UArGM,aAAA,CAqGN;EAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBApE1B,2BAA2B,uBAClC,cAAc,SAAS,WAC7B;;;;UA+Cc,0BAAA;;;;;;;;;;;;;;;;iBAiBD,mCAAmC,uBAC1C,cAAc,SAAS,oBACrB"}
@@ -0,0 +1,144 @@
1
+ import { _objectSpread2 } from "../_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs";
2
+ import { isUndoableCommand } from "./types.mjs";
3
+ import { clearUndoHistory, performRedo, performUndo } from "./commander.mjs";
4
+ import { useCallback, useEffect, useMemo } from "react";
5
+ import { useStore } from "zustand";
6
+
7
+ //#region src/zustand-commander/hooks.ts
8
+ /**
9
+ * @voidhash/mimic-react/zustand-commander
10
+ *
11
+ * React hooks for zustand-commander.
12
+ *
13
+ * @since 0.0.1
14
+ */
15
+ /**
16
+ * Creates a dispatch function for commands.
17
+ * This is for use outside of React components (e.g., in command handlers).
18
+ */
19
+ function createDispatchFromApi(storeApi, maxUndoStackSize = 100) {
20
+ const dispatch = (command) => {
21
+ return (params) => {
22
+ const ctx = {
23
+ getState: () => storeApi.getState(),
24
+ setState: (partial) => storeApi.setState(partial),
25
+ dispatch
26
+ };
27
+ const result = command.fn(ctx, params);
28
+ if (isUndoableCommand(command)) storeApi.setState((state) => {
29
+ const { undoStack } = state._commander;
30
+ const newUndoStack = [...undoStack, {
31
+ command,
32
+ params,
33
+ result,
34
+ timestamp: Date.now()
35
+ }].slice(-maxUndoStackSize);
36
+ return _objectSpread2(_objectSpread2({}, state), {}, { _commander: {
37
+ undoStack: newUndoStack,
38
+ redoStack: []
39
+ } });
40
+ });
41
+ return result;
42
+ };
43
+ };
44
+ return dispatch;
45
+ }
46
+ /**
47
+ * React hook to get a dispatch function for commands.
48
+ * The dispatch function executes commands and manages undo/redo state.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * const dispatch = useCommander(useStore);
53
+ *
54
+ * const handleClick = () => {
55
+ * dispatch(addCard)({ columnId: "col-1", title: "New Card" });
56
+ * };
57
+ * ```
58
+ */
59
+ function useCommander(store) {
60
+ const storeApi = useMemo(() => {
61
+ return store;
62
+ }, [store]);
63
+ return useMemo(() => createDispatchFromApi(storeApi), [storeApi]);
64
+ }
65
+ /**
66
+ * React hook for undo/redo functionality.
67
+ * Provides state (canUndo, canRedo) and actions (undo, redo, clear).
68
+ *
69
+ * @example
70
+ * ```tsx
71
+ * const { canUndo, canRedo, undo, redo } = useUndoRedo(useStore);
72
+ *
73
+ * return (
74
+ * <>
75
+ * <button onClick={undo} disabled={!canUndo}>Undo</button>
76
+ * <button onClick={redo} disabled={!canRedo}>Redo</button>
77
+ * </>
78
+ * );
79
+ * ```
80
+ */
81
+ function useUndoRedo(store) {
82
+ const storeApi = useMemo(() => {
83
+ return store;
84
+ }, [store]);
85
+ const commanderState = useStore(store, (state) => state._commander);
86
+ return {
87
+ canUndo: commanderState.undoStack.length > 0,
88
+ canRedo: commanderState.redoStack.length > 0,
89
+ undoCount: commanderState.undoStack.length,
90
+ redoCount: commanderState.redoStack.length,
91
+ undo: useCallback(() => {
92
+ return performUndo(storeApi);
93
+ }, [storeApi]),
94
+ redo: useCallback(() => {
95
+ return performRedo(storeApi);
96
+ }, [storeApi]),
97
+ clear: useCallback(() => {
98
+ clearUndoHistory(storeApi);
99
+ }, [storeApi])
100
+ };
101
+ }
102
+ /**
103
+ * React hook that adds keyboard shortcuts for undo/redo.
104
+ * Listens for Ctrl/Cmd+Z (undo) and Ctrl/Cmd+Shift+Z or Ctrl+Y (redo).
105
+ *
106
+ * @example
107
+ * ```tsx
108
+ * // In your app component
109
+ * useUndoRedoKeyboard(useStore);
110
+ * ```
111
+ */
112
+ function useUndoRedoKeyboard(store, options = {}) {
113
+ const { enableUndo = true, enableRedo = true } = options;
114
+ const storeApi = useMemo(() => {
115
+ return store;
116
+ }, [store]);
117
+ useEffect(() => {
118
+ if (typeof window === "undefined") return;
119
+ const handleKeyDown = (event) => {
120
+ if (!(navigator.platform.toUpperCase().indexOf("MAC") >= 0 ? event.metaKey : event.ctrlKey)) return;
121
+ if (enableUndo && event.key === "z" && !event.shiftKey) {
122
+ event.preventDefault();
123
+ performUndo(storeApi);
124
+ return;
125
+ }
126
+ if (enableRedo) {
127
+ if (event.key === "z" && event.shiftKey || event.key === "y") {
128
+ event.preventDefault();
129
+ performRedo(storeApi);
130
+ }
131
+ }
132
+ };
133
+ window.addEventListener("keydown", handleKeyDown);
134
+ return () => window.removeEventListener("keydown", handleKeyDown);
135
+ }, [
136
+ storeApi,
137
+ enableUndo,
138
+ enableRedo
139
+ ]);
140
+ }
141
+
142
+ //#endregion
143
+ export { useCommander, useUndoRedo, useUndoRedoKeyboard };
144
+ //# sourceMappingURL=hooks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.mjs","names":["dispatch: CommandDispatch<TStore>","ctx: CommandContext<TStore>"],"sources":["../../src/zustand-commander/hooks.ts"],"sourcesContent":["/**\n * @voidhash/mimic-react/zustand-commander\n *\n * React hooks for zustand-commander.\n *\n * @since 0.0.1\n */\n\nimport { useCallback, useEffect, useMemo } from \"react\";\nimport { useStore, type StoreApi, type UseBoundStore } from \"zustand\";\nimport { performRedo, performUndo, clearUndoHistory } from \"./commander\";\nimport {\n isUndoableCommand,\n type Command,\n type CommandContext,\n type CommandDispatch,\n type CommanderSlice,\n type ExtractState,\n} from \"./types.js\";\n\n// =============================================================================\n// useCommander Hook\n// =============================================================================\n\n/**\n * Creates a dispatch function for commands.\n * This is for use outside of React components (e.g., in command handlers).\n */\nfunction createDispatchFromApi<TStore extends CommanderSlice>(\n storeApi: StoreApi<TStore>,\n maxUndoStackSize = 100\n): CommandDispatch<TStore> {\n const dispatch: CommandDispatch<TStore> = <TParams, TReturn>(\n command: Command<TStore, TParams, TReturn>\n ) => {\n return (params: TParams): TReturn => {\n // Create context for the command\n const ctx: CommandContext<TStore> = {\n getState: () => storeApi.getState(),\n setState: (partial) => storeApi.setState(partial as Partial<TStore>),\n dispatch,\n };\n\n // Execute the command\n const result = command.fn(ctx, params);\n\n // If it's an undoable command, add to undo stack\n if (isUndoableCommand(command)) {\n storeApi.setState((state: TStore) => {\n const { undoStack } = state._commander;\n\n // Add to undo stack, respecting max size\n const newUndoStack = [\n ...undoStack,\n {\n command,\n params,\n result,\n timestamp: Date.now(),\n },\n ].slice(-maxUndoStackSize);\n\n // Clear redo stack when a new command is executed\n return {\n ...state,\n _commander: {\n undoStack: newUndoStack,\n redoStack: [],\n },\n } as TStore;\n });\n }\n\n return result;\n };\n };\n\n return dispatch;\n}\n\n/**\n * React hook to get a dispatch function for commands.\n * The dispatch function executes commands and manages undo/redo state.\n *\n * @example\n * ```tsx\n * const dispatch = useCommander(useStore);\n *\n * const handleClick = () => {\n * dispatch(addCard)({ columnId: \"col-1\", title: \"New Card\" });\n * };\n * ```\n */\nexport function useCommander<TStore extends CommanderSlice>(\n store: UseBoundStore<StoreApi<TStore>>\n): CommandDispatch<TStore> {\n // Get the store API\n const storeApi = useMemo(() => {\n // UseBoundStore has the StoreApi attached\n return store as unknown as StoreApi<TStore>;\n }, [store]);\n\n // Create a stable dispatch function\n const dispatch = useMemo(\n () => createDispatchFromApi<TStore>(storeApi),\n [storeApi]\n );\n\n return dispatch as CommandDispatch<TStore>;\n}\n\n// =============================================================================\n// useUndoRedo Hook\n// =============================================================================\n\n/**\n * State and actions for undo/redo functionality.\n */\nexport interface UndoRedoState {\n /** Whether there are actions that can be undone */\n readonly canUndo: boolean;\n /** Whether there are actions that can be redone */\n readonly canRedo: boolean;\n /** Number of items in the undo stack */\n readonly undoCount: number;\n /** Number of items in the redo stack */\n readonly redoCount: number;\n /** Undo the last action */\n readonly undo: () => boolean;\n /** Redo the last undone action */\n readonly redo: () => boolean;\n /** Clear the undo/redo history */\n readonly clear: () => void;\n}\n\n/**\n * React hook for undo/redo functionality.\n * Provides state (canUndo, canRedo) and actions (undo, redo, clear).\n *\n * @example\n * ```tsx\n * const { canUndo, canRedo, undo, redo } = useUndoRedo(useStore);\n *\n * return (\n * <>\n * <button onClick={undo} disabled={!canUndo}>Undo</button>\n * <button onClick={redo} disabled={!canRedo}>Redo</button>\n * </>\n * );\n * ```\n */\nexport function useUndoRedo<TStore extends CommanderSlice>(\n store: UseBoundStore<StoreApi<TStore>>\n): UndoRedoState {\n // Get the store API\n const storeApi = useMemo(() => {\n return store as unknown as StoreApi<TStore>;\n }, [store]);\n\n // Subscribe to commander state\n const commanderState = useStore(\n store,\n (state: TStore) => state._commander\n );\n\n const canUndo = commanderState.undoStack.length > 0;\n const canRedo = commanderState.redoStack.length > 0;\n const undoCount = commanderState.undoStack.length;\n const redoCount = commanderState.redoStack.length;\n\n const undo = useCallback(() => {\n return performUndo(storeApi);\n }, [storeApi]);\n\n const redo = useCallback(() => {\n return performRedo(storeApi);\n }, [storeApi]);\n\n const clear = useCallback(() => {\n clearUndoHistory(storeApi);\n }, [storeApi]);\n\n return {\n canUndo,\n canRedo,\n undoCount,\n redoCount,\n undo,\n redo,\n clear,\n };\n}\n\n// =============================================================================\n// Keyboard Shortcut Hook\n// =============================================================================\n\n/**\n * Options for the keyboard shortcut hook.\n */\nexport interface UseUndoRedoKeyboardOptions {\n /** Enable Ctrl/Cmd+Z for undo (default: true) */\n readonly enableUndo?: boolean;\n /** Enable Ctrl/Cmd+Shift+Z or Ctrl+Y for redo (default: true) */\n readonly enableRedo?: boolean;\n}\n\n/**\n * React hook that adds keyboard shortcuts for undo/redo.\n * Listens for Ctrl/Cmd+Z (undo) and Ctrl/Cmd+Shift+Z or Ctrl+Y (redo).\n *\n * @example\n * ```tsx\n * // In your app component\n * useUndoRedoKeyboard(useStore);\n * ```\n */\nexport function useUndoRedoKeyboard<TStore extends CommanderSlice>(\n store: UseBoundStore<StoreApi<TStore>>,\n options: UseUndoRedoKeyboardOptions = {}\n): void {\n const { enableUndo = true, enableRedo = true } = options;\n\n const storeApi = useMemo(() => {\n return store as unknown as StoreApi<TStore>;\n }, [store]);\n\n // Set up keyboard listener\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const isMac = navigator.platform.toUpperCase().indexOf(\"MAC\") >= 0;\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return;\n\n // Undo: Ctrl/Cmd + Z (without Shift)\n if (enableUndo && event.key === \"z\" && !event.shiftKey) {\n event.preventDefault();\n performUndo(storeApi);\n return;\n }\n\n // Redo: Ctrl/Cmd + Shift + Z or Ctrl + Y\n if (enableRedo) {\n if ((event.key === \"z\" && event.shiftKey) || event.key === \"y\") {\n event.preventDefault();\n performRedo(storeApi);\n }\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [storeApi, enableUndo, enableRedo]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,SAAS,sBACP,UACA,mBAAmB,KACM;CACzB,MAAMA,YACJ,YACG;AACH,UAAQ,WAA6B;GAEnC,MAAMC,MAA8B;IAClC,gBAAgB,SAAS,UAAU;IACnC,WAAW,YAAY,SAAS,SAAS,QAA2B;IACpE;IACD;GAGD,MAAM,SAAS,QAAQ,GAAG,KAAK,OAAO;AAGtC,OAAI,kBAAkB,QAAQ,CAC5B,UAAS,UAAU,UAAkB;IACnC,MAAM,EAAE,cAAc,MAAM;IAG5B,MAAM,eAAe,CACnB,GAAG,WACH;KACE;KACA;KACA;KACA,WAAW,KAAK,KAAK;KACtB,CACF,CAAC,MAAM,CAAC,iBAAiB;AAG1B,6CACK,cACH,YAAY;KACV,WAAW;KACX,WAAW,EAAE;KACd;KAEH;AAGJ,UAAO;;;AAIX,QAAO;;;;;;;;;;;;;;;AAgBT,SAAgB,aACd,OACyB;CAEzB,MAAM,WAAW,cAAc;AAE7B,SAAO;IACN,CAAC,MAAM,CAAC;AAQX,QALiB,cACT,sBAA8B,SAAS,EAC7C,CAAC,SAAS,CACX;;;;;;;;;;;;;;;;;;AA6CH,SAAgB,YACd,OACe;CAEf,MAAM,WAAW,cAAc;AAC7B,SAAO;IACN,CAAC,MAAM,CAAC;CAGX,MAAM,iBAAiB,SACrB,QACC,UAAkB,MAAM,WAC1B;AAmBD,QAAO;EACL,SAlBc,eAAe,UAAU,SAAS;EAmBhD,SAlBc,eAAe,UAAU,SAAS;EAmBhD,WAlBgB,eAAe,UAAU;EAmBzC,WAlBgB,eAAe,UAAU;EAmBzC,MAjBW,kBAAkB;AAC7B,UAAO,YAAY,SAAS;KAC3B,CAAC,SAAS,CAAC;EAgBZ,MAdW,kBAAkB;AAC7B,UAAO,YAAY,SAAS;KAC3B,CAAC,SAAS,CAAC;EAaZ,OAXY,kBAAkB;AAC9B,oBAAiB,SAAS;KACzB,CAAC,SAAS,CAAC;EAUb;;;;;;;;;;;;AA2BH,SAAgB,oBACd,OACA,UAAsC,EAAE,EAClC;CACN,MAAM,EAAE,aAAa,MAAM,aAAa,SAAS;CAEjD,MAAM,WAAW,cAAc;AAC7B,SAAO;IACN,CAAC,MAAM,CAAC;AAGX,iBAAgB;AACd,MAAI,OAAO,WAAW,YACpB;EAGF,MAAM,iBAAiB,UAAyB;AAI9C,OAAI,EAHU,UAAU,SAAS,aAAa,CAAC,QAAQ,MAAM,IAAI,IAC1C,MAAM,UAAU,MAAM,SAEhC;AAGb,OAAI,cAAc,MAAM,QAAQ,OAAO,CAAC,MAAM,UAAU;AACtD,UAAM,gBAAgB;AACtB,gBAAY,SAAS;AACrB;;AAIF,OAAI,YACF;QAAK,MAAM,QAAQ,OAAO,MAAM,YAAa,MAAM,QAAQ,KAAK;AAC9D,WAAM,gBAAgB;AACtB,iBAAY,SAAS;;;;AAK3B,SAAO,iBAAiB,WAAW,cAAc;AACjD,eAAa,OAAO,oBAAoB,WAAW,cAAc;IAChE;EAAC;EAAU;EAAY;EAAW,CAAC"}
@@ -1,354 +1,15 @@
1
- const require_objectSpread2 = require('../objectSpread2-CIP_6jda.cjs');
2
- let react = require("react");
3
- let zustand = require("zustand");
4
-
5
- //#region src/zustand-commander/types.ts
6
- /**
7
- * Symbol used to identify Command objects at runtime.
8
- */
9
- const COMMAND_SYMBOL = Symbol.for("zustand-commander/command");
10
- /**
11
- * Symbol used to identify UndoableCommand objects at runtime.
12
- */
13
- const UNDOABLE_COMMAND_SYMBOL = Symbol.for("zustand-commander/undoable-command");
14
- /**
15
- * Type guard to check if a value is a Command.
16
- */
17
- function isCommand(value) {
18
- return typeof value === "object" && value !== null && COMMAND_SYMBOL in value && value[COMMAND_SYMBOL] === true;
19
- }
20
- /**
21
- * Type guard to check if a command is undoable.
22
- */
23
- function isUndoableCommand(value) {
24
- return isCommand(value) && UNDOABLE_COMMAND_SYMBOL in value && value[UNDOABLE_COMMAND_SYMBOL] === true;
25
- }
26
-
27
- //#endregion
28
- //#region src/zustand-commander/commander.ts
29
- const DEFAULT_OPTIONS = { maxUndoStackSize: 100 };
30
- /**
31
- * Creates a commander instance bound to a specific store type.
32
- *
33
- * @example
34
- * ```ts
35
- * // Create commander for your store type
36
- * const commander = createCommander<StoreState>();
37
- *
38
- * // Define commands
39
- * const addItem = commander.action(
40
- * Schema.Struct({ name: Schema.String }),
41
- * (ctx, params) => {
42
- * const { mimic } = ctx.getState();
43
- * mimic.document.transaction(root => {
44
- * // add item
45
- * });
46
- * }
47
- * );
48
- *
49
- * // Create store with middleware
50
- * const useStore = create(
51
- * commander.middleware(
52
- * mimic(document, (set, get) => ({
53
- * // your state
54
- * }))
55
- * )
56
- * );
57
- * ```
58
- */
59
- function createCommander(options = {}) {
60
- const { maxUndoStackSize } = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, DEFAULT_OPTIONS), options);
61
- let _storeApi = null;
62
- /**
63
- * Creates the dispatch function for use within command handlers.
64
- */
65
- const createDispatch = () => {
66
- return (command) => {
67
- return (params) => {
68
- if (!_storeApi) throw new Error("Commander: Store not initialized. Make sure to use the commander middleware.");
69
- const ctx = {
70
- getState: () => _storeApi.getState(),
71
- setState: (partial) => _storeApi.setState(partial),
72
- dispatch: createDispatch()
73
- };
74
- const result = command.fn(ctx, params);
75
- if (isUndoableCommand(command)) {
76
- const entry = {
77
- command,
78
- params,
79
- result,
80
- timestamp: Date.now()
81
- };
82
- _storeApi.setState((state) => {
83
- const { undoStack, redoStack } = state._commander;
84
- const newUndoStack = [...undoStack, entry].slice(-maxUndoStackSize);
85
- return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, state), {}, { _commander: {
86
- undoStack: newUndoStack,
87
- redoStack: []
88
- } });
89
- });
90
- }
91
- return result;
92
- };
93
- };
94
- };
95
- /**
96
- * Create a regular command (no undo support).
97
- */
98
- function action(fn) {
99
- return {
100
- [COMMAND_SYMBOL]: true,
101
- fn
102
- };
103
- }
104
- /**
105
- * Create an undoable command with undo/redo support.
106
- */
107
- function undoableAction(fn, revert) {
108
- return {
109
- [COMMAND_SYMBOL]: true,
110
- [UNDOABLE_COMMAND_SYMBOL]: true,
111
- fn,
112
- revert
113
- };
114
- }
115
- /**
116
- * Zustand middleware that adds commander functionality.
117
- */
118
- const middleware = (config) => {
119
- return (set, get, api) => {
120
- _storeApi = api;
121
- return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, config(set, get, api)), {}, { _commander: {
122
- undoStack: [],
123
- redoStack: []
124
- } });
125
- };
126
- };
127
- return {
128
- action,
129
- undoableAction,
130
- middleware
131
- };
132
- }
133
- /**
134
- * Perform an undo operation on the store.
135
- * Returns true if an undo was performed, false if undo stack was empty.
136
- */
137
- function performUndo(storeApi) {
138
- const { undoStack, redoStack } = storeApi.getState()._commander;
139
- const entry = undoStack[undoStack.length - 1];
140
- if (!entry) return false;
141
- const newUndoStack = undoStack.slice(0, -1);
142
- const ctx = {
143
- getState: () => storeApi.getState(),
144
- setState: (partial) => storeApi.setState(partial),
145
- dispatch: createDispatchForUndo(storeApi)
146
- };
147
- entry.command.revert(ctx, entry.params, entry.result);
148
- storeApi.setState((state) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, state), {}, { _commander: {
149
- undoStack: newUndoStack,
150
- redoStack: [...redoStack, entry]
151
- } }));
152
- return true;
153
- }
154
- /**
155
- * Perform a redo operation on the store.
156
- * Returns true if a redo was performed, false if redo stack was empty.
157
- */
158
- function performRedo(storeApi) {
159
- const { undoStack, redoStack } = storeApi.getState()._commander;
160
- const entry = redoStack[redoStack.length - 1];
161
- if (!entry) return false;
162
- const newRedoStack = redoStack.slice(0, -1);
163
- const ctx = {
164
- getState: () => storeApi.getState(),
165
- setState: (partial) => storeApi.setState(partial),
166
- dispatch: createDispatchForUndo(storeApi)
167
- };
168
- const result = entry.command.fn(ctx, entry.params);
169
- const newEntry = {
170
- command: entry.command,
171
- params: entry.params,
172
- result,
173
- timestamp: Date.now()
174
- };
175
- storeApi.setState((state) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, state), {}, { _commander: {
176
- undoStack: [...undoStack, newEntry],
177
- redoStack: newRedoStack
178
- } }));
179
- return true;
180
- }
181
- /**
182
- * Creates a dispatch function for use during undo/redo operations.
183
- * This dispatch does NOT add to undo stack (to avoid infinite loops).
184
- */
185
- function createDispatchForUndo(storeApi) {
186
- return (command) => {
187
- return (params) => {
188
- const ctx = {
189
- getState: () => storeApi.getState(),
190
- setState: (partial) => storeApi.setState(partial),
191
- dispatch: createDispatchForUndo(storeApi)
192
- };
193
- return command.fn(ctx, params);
194
- };
195
- };
196
- }
197
- /**
198
- * Clear the undo and redo stacks.
199
- */
200
- function clearUndoHistory(storeApi) {
201
- storeApi.setState((state) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, state), {}, { _commander: {
202
- undoStack: [],
203
- redoStack: []
204
- } }));
205
- }
206
-
207
- //#endregion
208
- //#region src/zustand-commander/hooks.ts
209
- /**
210
- * @voidhash/mimic-react/zustand-commander
211
- *
212
- * React hooks for zustand-commander.
213
- *
214
- * @since 0.0.1
215
- */
216
- /**
217
- * Creates a dispatch function for commands.
218
- * This is for use outside of React components (e.g., in command handlers).
219
- */
220
- function createDispatchFromApi(storeApi, maxUndoStackSize = 100) {
221
- const dispatch = (command) => {
222
- return (params) => {
223
- const ctx = {
224
- getState: () => storeApi.getState(),
225
- setState: (partial) => storeApi.setState(partial),
226
- dispatch
227
- };
228
- const result = command.fn(ctx, params);
229
- if (isUndoableCommand(command)) storeApi.setState((state) => {
230
- const { undoStack } = state._commander;
231
- const newUndoStack = [...undoStack, {
232
- command,
233
- params,
234
- result,
235
- timestamp: Date.now()
236
- }].slice(-maxUndoStackSize);
237
- return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, state), {}, { _commander: {
238
- undoStack: newUndoStack,
239
- redoStack: []
240
- } });
241
- });
242
- return result;
243
- };
244
- };
245
- return dispatch;
246
- }
247
- /**
248
- * React hook to get a dispatch function for commands.
249
- * The dispatch function executes commands and manages undo/redo state.
250
- *
251
- * @example
252
- * ```tsx
253
- * const dispatch = useCommander(useStore);
254
- *
255
- * const handleClick = () => {
256
- * dispatch(addCard)({ columnId: "col-1", title: "New Card" });
257
- * };
258
- * ```
259
- */
260
- function useCommander(store) {
261
- const storeApi = (0, react.useMemo)(() => {
262
- return store;
263
- }, [store]);
264
- return (0, react.useMemo)(() => createDispatchFromApi(storeApi), [storeApi]);
265
- }
266
- /**
267
- * React hook for undo/redo functionality.
268
- * Provides state (canUndo, canRedo) and actions (undo, redo, clear).
269
- *
270
- * @example
271
- * ```tsx
272
- * const { canUndo, canRedo, undo, redo } = useUndoRedo(useStore);
273
- *
274
- * return (
275
- * <>
276
- * <button onClick={undo} disabled={!canUndo}>Undo</button>
277
- * <button onClick={redo} disabled={!canRedo}>Redo</button>
278
- * </>
279
- * );
280
- * ```
281
- */
282
- function useUndoRedo(store) {
283
- const storeApi = (0, react.useMemo)(() => {
284
- return store;
285
- }, [store]);
286
- const commanderState = (0, zustand.useStore)(store, (state) => state._commander);
287
- return {
288
- canUndo: commanderState.undoStack.length > 0,
289
- canRedo: commanderState.redoStack.length > 0,
290
- undoCount: commanderState.undoStack.length,
291
- redoCount: commanderState.redoStack.length,
292
- undo: (0, react.useCallback)(() => {
293
- return performUndo(storeApi);
294
- }, [storeApi]),
295
- redo: (0, react.useCallback)(() => {
296
- return performRedo(storeApi);
297
- }, [storeApi]),
298
- clear: (0, react.useCallback)(() => {
299
- clearUndoHistory(storeApi);
300
- }, [storeApi])
301
- };
302
- }
303
- /**
304
- * React hook that adds keyboard shortcuts for undo/redo.
305
- * Listens for Ctrl/Cmd+Z (undo) and Ctrl/Cmd+Shift+Z or Ctrl+Y (redo).
306
- *
307
- * @example
308
- * ```tsx
309
- * // In your app component
310
- * useUndoRedoKeyboard(useStore);
311
- * ```
312
- */
313
- function useUndoRedoKeyboard(store, options = {}) {
314
- const { enableUndo = true, enableRedo = true } = options;
315
- const storeApi = (0, react.useMemo)(() => {
316
- return store;
317
- }, [store]);
318
- (0, react.useEffect)(() => {
319
- if (typeof window === "undefined") return;
320
- const handleKeyDown = (event) => {
321
- if (!(navigator.platform.toUpperCase().indexOf("MAC") >= 0 ? event.metaKey : event.ctrlKey)) return;
322
- if (enableUndo && event.key === "z" && !event.shiftKey) {
323
- event.preventDefault();
324
- performUndo(storeApi);
325
- return;
326
- }
327
- if (enableRedo) {
328
- if (event.key === "z" && event.shiftKey || event.key === "y") {
329
- event.preventDefault();
330
- performRedo(storeApi);
331
- }
332
- }
333
- };
334
- window.addEventListener("keydown", handleKeyDown);
335
- return () => window.removeEventListener("keydown", handleKeyDown);
336
- }, [
337
- storeApi,
338
- enableUndo,
339
- enableRedo
340
- ]);
341
- }
342
-
343
- //#endregion
344
- exports.COMMAND_SYMBOL = COMMAND_SYMBOL;
345
- exports.UNDOABLE_COMMAND_SYMBOL = UNDOABLE_COMMAND_SYMBOL;
346
- exports.clearUndoHistory = clearUndoHistory;
347
- exports.createCommander = createCommander;
348
- exports.isCommand = isCommand;
349
- exports.isUndoableCommand = isUndoableCommand;
350
- exports.performRedo = performRedo;
351
- exports.performUndo = performUndo;
352
- exports.useCommander = useCommander;
353
- exports.useUndoRedo = useUndoRedo;
354
- exports.useUndoRedoKeyboard = useUndoRedoKeyboard;
1
+ const require_types = require('./types.cjs');
2
+ const require_commander = require('./commander.cjs');
3
+ const require_hooks = require('./hooks.cjs');
4
+
5
+ exports.COMMAND_SYMBOL = require_types.COMMAND_SYMBOL;
6
+ exports.UNDOABLE_COMMAND_SYMBOL = require_types.UNDOABLE_COMMAND_SYMBOL;
7
+ exports.clearUndoHistory = require_commander.clearUndoHistory;
8
+ exports.createCommander = require_commander.createCommander;
9
+ exports.isCommand = require_types.isCommand;
10
+ exports.isUndoableCommand = require_types.isUndoableCommand;
11
+ exports.performRedo = require_commander.performRedo;
12
+ exports.performUndo = require_commander.performUndo;
13
+ exports.useCommander = require_hooks.useCommander;
14
+ exports.useUndoRedo = require_hooks.useUndoRedo;
15
+ exports.useUndoRedoKeyboard = require_hooks.useUndoRedoKeyboard;