@pixerate/editor-react 0.15.0 → 0.17.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 (54) hide show
  1. package/README.md +6 -2
  2. package/dist/canvas/index.cjs +484 -119
  3. package/dist/canvas/index.cjs.map +1 -1
  4. package/dist/canvas/index.d.cts +122 -3
  5. package/dist/canvas/index.d.ts +122 -3
  6. package/dist/canvas/index.js +380 -0
  7. package/dist/canvas/index.js.map +1 -1
  8. package/dist/chunk-I3E4KSA2.js +515 -0
  9. package/dist/chunk-I3E4KSA2.js.map +1 -0
  10. package/dist/chunk-JR5ZBDR7.js +2012 -0
  11. package/dist/chunk-JR5ZBDR7.js.map +1 -0
  12. package/dist/chunk-XWFU2CSG.js +167 -0
  13. package/dist/chunk-XWFU2CSG.js.map +1 -0
  14. package/dist/chunk-ZU54BMDC.js +2128 -0
  15. package/dist/chunk-ZU54BMDC.js.map +1 -0
  16. package/dist/generation/index.cjs +525 -0
  17. package/dist/generation/index.cjs.map +1 -0
  18. package/dist/generation/index.d.cts +124 -0
  19. package/dist/generation/index.d.ts +124 -0
  20. package/dist/generation/index.js +19 -0
  21. package/dist/generation/index.js.map +1 -0
  22. package/dist/image-editor/index.cjs +988 -337
  23. package/dist/image-editor/index.cjs.map +1 -1
  24. package/dist/image-editor/index.d.cts +92 -2
  25. package/dist/image-editor/index.d.ts +92 -2
  26. package/dist/image-editor/index.js +17 -3
  27. package/dist/index.cjs +3628 -754
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +226 -5
  30. package/dist/index.d.ts +226 -5
  31. package/dist/index.js +868 -77
  32. package/dist/index.js.map +1 -1
  33. package/dist/persistence/index.cjs +191 -0
  34. package/dist/persistence/index.cjs.map +1 -0
  35. package/dist/persistence/index.d.cts +77 -0
  36. package/dist/persistence/index.d.ts +77 -0
  37. package/dist/persistence/index.js +9 -0
  38. package/dist/persistence/index.js.map +1 -0
  39. package/dist/spreadsheet/index.cjs +949 -111
  40. package/dist/spreadsheet/index.cjs.map +1 -1
  41. package/dist/spreadsheet/index.d.cts +121 -7
  42. package/dist/spreadsheet/index.d.ts +121 -7
  43. package/dist/spreadsheet/index.js +11 -1
  44. package/dist/tokens/index.cjs +395 -0
  45. package/dist/tokens/index.cjs.map +1 -0
  46. package/dist/tokens/index.d.cts +54 -0
  47. package/dist/tokens/index.d.ts +54 -0
  48. package/dist/tokens/index.js +375 -0
  49. package/dist/tokens/index.js.map +1 -0
  50. package/package.json +26 -2
  51. package/dist/chunk-LPFZMZ3L.js +0 -1461
  52. package/dist/chunk-LPFZMZ3L.js.map +0 -1
  53. package/dist/chunk-QVQYYHJ5.js +0 -1161
  54. package/dist/chunk-QVQYYHJ5.js.map +0 -1
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/persistence/index.ts
21
+ var persistence_exports = {};
22
+ __export(persistence_exports, {
23
+ RecoveryPrompt: () => RecoveryPrompt,
24
+ useAutosave: () => useAutosave
25
+ });
26
+ module.exports = __toCommonJS(persistence_exports);
27
+
28
+ // src/persistence/useAutosave.ts
29
+ var import_react = require("react");
30
+ var import_persistence = require("@pixerate/editor/persistence");
31
+ var IDLE = {
32
+ status: "idle",
33
+ error: null,
34
+ failures: 0,
35
+ nextAttemptAt: null,
36
+ lastSavedAt: null,
37
+ ready: false
38
+ };
39
+ function useAutosave(options) {
40
+ const optionsRef = (0, import_react.useRef)(options);
41
+ optionsRef.current = options;
42
+ const { storage, key, history, dirty } = options;
43
+ const recover = options.recover !== false;
44
+ const flushOnHide = options.flushOnHide !== false;
45
+ const ready = options.ready !== false;
46
+ const [controller, setController] = (0, import_react.useState)(null);
47
+ const [status, setStatus] = (0, import_react.useState)(IDLE);
48
+ const [recovery, setRecovery] = (0, import_react.useState)(null);
49
+ const [pendingRecovery, setPendingRecovery] = (0, import_react.useState)(recover);
50
+ const revisionsRef = (0, import_react.useRef)(null);
51
+ (0, import_react.useEffect)(() => {
52
+ const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
53
+ const o = optionsRef.current;
54
+ const instance = (0, import_persistence.createAutosaveController)({
55
+ storage,
56
+ key,
57
+ getSnapshot: () => optionsRef.current.getSnapshot(),
58
+ serialize: o.serialize,
59
+ deserialize: o.deserialize,
60
+ name: () => optionsRef.current.name,
61
+ revision: revisions.revision,
62
+ savedRevision: revisions.savedRevision,
63
+ interval: o.interval,
64
+ debounceMs: o.debounceMs,
65
+ retryBaseMs: o.retryBaseMs,
66
+ retryMaxMs: o.retryMaxMs
67
+ });
68
+ const unsubscribeStatus = instance.subscribe(setStatus);
69
+ const unsubscribeRevisions = revisions.subscribe(() => instance.notify());
70
+ revisionsRef.current = revisions;
71
+ setController(instance);
72
+ setStatus(instance.getStatus());
73
+ let active = true;
74
+ if (recover) {
75
+ setPendingRecovery(true);
76
+ instance.checkRecovery().catch(() => null).then((found) => {
77
+ if (!active) return;
78
+ setRecovery(found);
79
+ setPendingRecovery(found !== null);
80
+ });
81
+ } else {
82
+ setRecovery(null);
83
+ setPendingRecovery(false);
84
+ }
85
+ return () => {
86
+ active = false;
87
+ unsubscribeStatus();
88
+ unsubscribeRevisions();
89
+ revisions.destroy();
90
+ instance.destroy();
91
+ if (revisionsRef.current === revisions) revisionsRef.current = null;
92
+ };
93
+ }, [storage, key, history, dirty, recover]);
94
+ (0, import_react.useEffect)(() => {
95
+ if (controller && ready && !pendingRecovery) controller.ready();
96
+ }, [controller, ready, pendingRecovery]);
97
+ (0, import_react.useEffect)(() => {
98
+ if (!controller || !flushOnHide || typeof window === "undefined") return;
99
+ const flush = () => void controller.flushNow();
100
+ const onVisibility = () => {
101
+ if (document.visibilityState === "hidden") flush();
102
+ };
103
+ window.addEventListener("pagehide", flush);
104
+ document.addEventListener("visibilitychange", onVisibility);
105
+ return () => {
106
+ window.removeEventListener("pagehide", flush);
107
+ document.removeEventListener("visibilitychange", onVisibility);
108
+ };
109
+ }, [controller, flushOnHide]);
110
+ const restore = (0, import_react.useCallback)(() => {
111
+ const snapshot = recovery?.snapshot;
112
+ setRecovery(null);
113
+ setPendingRecovery(false);
114
+ return snapshot;
115
+ }, [recovery]);
116
+ const discard = (0, import_react.useCallback)(async () => {
117
+ if (controller) await controller.discardRecovery();
118
+ setRecovery(null);
119
+ setPendingRecovery(false);
120
+ }, [controller]);
121
+ const flushNow = (0, import_react.useCallback)(async () => {
122
+ await controller?.flushNow();
123
+ }, [controller]);
124
+ const markClean = (0, import_react.useCallback)(async () => {
125
+ revisionsRef.current?.markSaved();
126
+ await controller?.markClean();
127
+ }, [controller]);
128
+ const notifyChange = (0, import_react.useCallback)(() => revisionsRef.current?.bump(), []);
129
+ return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
130
+ }
131
+
132
+ // src/persistence/RecoveryPrompt.tsx
133
+ var import_persistence2 = require("@pixerate/editor/persistence");
134
+ var import_jsx_runtime = require("react/jsx-runtime");
135
+ var RecoveryPrompt = ({
136
+ recovery,
137
+ onRestore,
138
+ onDiscard,
139
+ formatTime,
140
+ restoreLabel = "Restore",
141
+ discardLabel = "Discard",
142
+ className = ""
143
+ }) => {
144
+ if (!recovery) return null;
145
+ const { name } = recovery.meta;
146
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
147
+ "div",
148
+ {
149
+ role: "alertdialog",
150
+ "aria-label": "Unsaved changes found",
151
+ "data-recovery-prompt": "",
152
+ className: `flex flex-wrap items-center gap-3 rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm ${className}`,
153
+ children: [
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0 flex-1", children: [
155
+ (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
156
+ name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
157
+ "(",
158
+ name,
159
+ ")"
160
+ ] }) : null
161
+ ] }),
162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
163
+ "button",
164
+ {
165
+ type: "button",
166
+ "data-recovery-restore": "",
167
+ onClick: onRestore,
168
+ className: "rounded-md bg-primary px-3 py-1 text-xs font-medium text-primary-foreground hover:opacity-90",
169
+ children: restoreLabel
170
+ }
171
+ ),
172
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
173
+ "button",
174
+ {
175
+ type: "button",
176
+ "data-recovery-discard": "",
177
+ onClick: onDiscard,
178
+ className: "rounded-md border border-border px-3 py-1 text-xs font-medium hover:bg-muted",
179
+ children: discardLabel
180
+ }
181
+ )
182
+ ]
183
+ }
184
+ );
185
+ };
186
+ // Annotate the CommonJS export names for ESM import in node:
187
+ 0 && (module.exports = {
188
+ RecoveryPrompt,
189
+ useAutosave
190
+ });
191
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/persistence/index.ts","../../src/persistence/useAutosave.ts","../../src/persistence/RecoveryPrompt.tsx"],"sourcesContent":["export * from './useAutosave';\nexport * from './RecoveryPrompt';\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n createAutosaveController,\n createRevisionTracker,\n type AutosaveController,\n type AutosaveRecovery,\n type AutosaveStatusInfo,\n type DirtyFlagSource,\n type RevisionChangeSource,\n type RevisionTracker,\n type StorageAdapter,\n} from '@pixerate/editor/persistence';\n\nexport interface UseAutosaveOptions<T> {\n storage: StorageAdapter;\n /** Snapshot key (the meta lives at `<key>:meta`). */\n key: string;\n /** Reads the current document (the latest function is always used). */\n getSnapshot: () => T;\n serialize?: (snapshot: T) => string;\n deserialize?: (text: string) => T;\n /** Document name stored with the snapshot. */\n name?: string;\n /** Change notifications, e.g. a `HistoryManager`. */\n history?: RevisionChangeSource;\n /** Saved-vs-current flag, e.g. `useHistoryDirty().tracker` or a `bindDirtyToHistory` binding. */\n dirty?: DirtyFlagSource;\n interval?: number;\n debounceMs?: number;\n retryBaseMs?: number;\n retryMaxMs?: number;\n /**\n * Whether the document has finished loading (default `true`). Snapshots start\n * once this is true and any recovered snapshot was restored or discarded.\n */\n ready?: boolean;\n /** Look for an earlier session's snapshot on mount (default `true`). */\n recover?: boolean;\n /** Write pending changes on `pagehide` and when the tab is hidden (default `true`). */\n flushOnHide?: boolean;\n}\n\nexport interface UseAutosaveResult<T> {\n status: AutosaveStatusInfo;\n /** An earlier session's unsaved snapshot, until restored or discarded. */\n recovery: AutosaveRecovery<T> | null;\n /** True while the recovery check runs or a recovered snapshot awaits a decision. */\n pendingRecovery: boolean;\n /** Takes the recovered snapshot (apply it to the editor) and starts autosaving. */\n restore: () => T | undefined;\n /** Deletes the recovered snapshot and starts autosaving. */\n discard: () => Promise<void>;\n /** Writes pending changes now. */\n flushNow: () => Promise<void>;\n /** Call after an explicit save: marks the current revision saved and retires this session's snapshot. */\n markClean: () => Promise<void>;\n /** Records a change made outside `history`. */\n notifyChange: () => void;\n controller: AutosaveController<T> | null;\n}\n\nconst IDLE: AutosaveStatusInfo = {\n status: 'idle',\n error: null,\n failures: 0,\n nextAttemptAt: null,\n lastSavedAt: null,\n ready: false,\n};\n\n/**\n * Crash-recovery autosave bound to a history and dirty flag, with page\n * lifecycle flushing and a recovery check on mount (see\n * `createAutosaveController` in `@pixerate/editor/persistence`). Render\n * `<RecoveryPrompt>` with `recovery`, `restore` and `discard`.\n */\nexport function useAutosave<T>(options: UseAutosaveOptions<T>): UseAutosaveResult<T> {\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const { storage, key, history, dirty } = options;\n const recover = options.recover !== false;\n const flushOnHide = options.flushOnHide !== false;\n const ready = options.ready !== false;\n\n const [controller, setController] = useState<AutosaveController<T> | null>(null);\n const [status, setStatus] = useState<AutosaveStatusInfo>(IDLE);\n const [recovery, setRecovery] = useState<AutosaveRecovery<T> | null>(null);\n const [pendingRecovery, setPendingRecovery] = useState(recover);\n const revisionsRef = useRef<RevisionTracker | null>(null);\n\n useEffect(() => {\n const revisions = createRevisionTracker({ history, dirty });\n const o = optionsRef.current;\n const instance = createAutosaveController<T>({\n storage,\n key,\n getSnapshot: () => optionsRef.current.getSnapshot(),\n serialize: o.serialize,\n deserialize: o.deserialize,\n name: () => optionsRef.current.name,\n revision: revisions.revision,\n savedRevision: revisions.savedRevision,\n interval: o.interval,\n debounceMs: o.debounceMs,\n retryBaseMs: o.retryBaseMs,\n retryMaxMs: o.retryMaxMs,\n });\n const unsubscribeStatus = instance.subscribe(setStatus);\n const unsubscribeRevisions = revisions.subscribe(() => instance.notify());\n revisionsRef.current = revisions;\n setController(instance);\n setStatus(instance.getStatus());\n\n let active = true;\n if (recover) {\n setPendingRecovery(true);\n instance\n .checkRecovery()\n .catch(() => null)\n .then((found) => {\n if (!active) return;\n setRecovery(found);\n setPendingRecovery(found !== null);\n });\n } else {\n setRecovery(null);\n setPendingRecovery(false);\n }\n\n return () => {\n active = false;\n unsubscribeStatus();\n unsubscribeRevisions();\n revisions.destroy();\n instance.destroy();\n if (revisionsRef.current === revisions) revisionsRef.current = null;\n };\n }, [storage, key, history, dirty, recover]);\n\n useEffect(() => {\n if (controller && ready && !pendingRecovery) controller.ready();\n }, [controller, ready, pendingRecovery]);\n\n useEffect(() => {\n if (!controller || !flushOnHide || typeof window === 'undefined') return;\n const flush = () => void controller.flushNow();\n const onVisibility = () => {\n if (document.visibilityState === 'hidden') flush();\n };\n window.addEventListener('pagehide', flush);\n document.addEventListener('visibilitychange', onVisibility);\n return () => {\n window.removeEventListener('pagehide', flush);\n document.removeEventListener('visibilitychange', onVisibility);\n };\n }, [controller, flushOnHide]);\n\n const restore = useCallback(() => {\n const snapshot = recovery?.snapshot;\n setRecovery(null);\n setPendingRecovery(false);\n return snapshot;\n }, [recovery]);\n\n const discard = useCallback(async () => {\n if (controller) await controller.discardRecovery();\n setRecovery(null);\n setPendingRecovery(false);\n }, [controller]);\n\n const flushNow = useCallback(async () => {\n await controller?.flushNow();\n }, [controller]);\n\n const markClean = useCallback(async () => {\n revisionsRef.current?.markSaved();\n await controller?.markClean();\n }, [controller]);\n\n const notifyChange = useCallback(() => revisionsRef.current?.bump(), []);\n\n return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };\n}\n","import React from 'react';\nimport { formatRecoveryMessage, type RecoveryMeta } from '@pixerate/editor/persistence';\n\nexport interface RecoveryPromptProps {\n /** `useAutosave().recovery`; nothing renders while it is `null`. */\n recovery: { meta: RecoveryMeta } | null;\n onRestore: () => void;\n onDiscard: () => void;\n /** Formats the snapshot time (default `toLocaleString`). */\n formatTime?: (time: number) => string;\n restoreLabel?: string;\n discardLabel?: string;\n className?: string;\n}\n\n/**\n * \"Restore unsaved changes from <time>?\" banner with Restore / Discard buttons\n * (Tailwind + theme tokens).\n */\nexport const RecoveryPrompt: React.FC<RecoveryPromptProps> = ({\n recovery,\n onRestore,\n onDiscard,\n formatTime,\n restoreLabel = 'Restore',\n discardLabel = 'Discard',\n className = '',\n}) => {\n if (!recovery) return null;\n const { name } = recovery.meta;\n return (\n <div\n role=\"alertdialog\"\n aria-label=\"Unsaved changes found\"\n data-recovery-prompt=\"\"\n className={`flex flex-wrap items-center gap-3 rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm ${className}`}\n >\n <span className=\"min-w-0 flex-1\">\n {formatRecoveryMessage(recovery.meta, formatTime)}\n {name ? <span className=\"ml-1 text-xs text-muted-foreground\">({name})</span> : null}\n </span>\n <button\n type=\"button\"\n data-recovery-restore=\"\"\n onClick={onRestore}\n className=\"rounded-md bg-primary px-3 py-1 text-xs font-medium text-primary-foreground hover:opacity-90\"\n >\n {restoreLabel}\n </button>\n <button\n type=\"button\"\n data-recovery-discard=\"\"\n onClick={onDiscard}\n className=\"rounded-md border border-border px-3 py-1 text-xs font-medium hover:bg-muted\"\n >\n {discardLabel}\n </button>\n </div>\n );\n};\n"],"mappings":"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","names":["import_persistence"]}
@@ -0,0 +1,77 @@
1
+ import { StorageAdapter, RevisionChangeSource, DirtyFlagSource, AutosaveStatusInfo, AutosaveRecovery, AutosaveController, RecoveryMeta } from '@pixerate/editor/persistence';
2
+ import React__default from 'react';
3
+
4
+ interface UseAutosaveOptions<T> {
5
+ storage: StorageAdapter;
6
+ /** Snapshot key (the meta lives at `<key>:meta`). */
7
+ key: string;
8
+ /** Reads the current document (the latest function is always used). */
9
+ getSnapshot: () => T;
10
+ serialize?: (snapshot: T) => string;
11
+ deserialize?: (text: string) => T;
12
+ /** Document name stored with the snapshot. */
13
+ name?: string;
14
+ /** Change notifications, e.g. a `HistoryManager`. */
15
+ history?: RevisionChangeSource;
16
+ /** Saved-vs-current flag, e.g. `useHistoryDirty().tracker` or a `bindDirtyToHistory` binding. */
17
+ dirty?: DirtyFlagSource;
18
+ interval?: number;
19
+ debounceMs?: number;
20
+ retryBaseMs?: number;
21
+ retryMaxMs?: number;
22
+ /**
23
+ * Whether the document has finished loading (default `true`). Snapshots start
24
+ * once this is true and any recovered snapshot was restored or discarded.
25
+ */
26
+ ready?: boolean;
27
+ /** Look for an earlier session's snapshot on mount (default `true`). */
28
+ recover?: boolean;
29
+ /** Write pending changes on `pagehide` and when the tab is hidden (default `true`). */
30
+ flushOnHide?: boolean;
31
+ }
32
+ interface UseAutosaveResult<T> {
33
+ status: AutosaveStatusInfo;
34
+ /** An earlier session's unsaved snapshot, until restored or discarded. */
35
+ recovery: AutosaveRecovery<T> | null;
36
+ /** True while the recovery check runs or a recovered snapshot awaits a decision. */
37
+ pendingRecovery: boolean;
38
+ /** Takes the recovered snapshot (apply it to the editor) and starts autosaving. */
39
+ restore: () => T | undefined;
40
+ /** Deletes the recovered snapshot and starts autosaving. */
41
+ discard: () => Promise<void>;
42
+ /** Writes pending changes now. */
43
+ flushNow: () => Promise<void>;
44
+ /** Call after an explicit save: marks the current revision saved and retires this session's snapshot. */
45
+ markClean: () => Promise<void>;
46
+ /** Records a change made outside `history`. */
47
+ notifyChange: () => void;
48
+ controller: AutosaveController<T> | null;
49
+ }
50
+ /**
51
+ * Crash-recovery autosave bound to a history and dirty flag, with page
52
+ * lifecycle flushing and a recovery check on mount (see
53
+ * `createAutosaveController` in `@pixerate/editor/persistence`). Render
54
+ * `<RecoveryPrompt>` with `recovery`, `restore` and `discard`.
55
+ */
56
+ declare function useAutosave<T>(options: UseAutosaveOptions<T>): UseAutosaveResult<T>;
57
+
58
+ interface RecoveryPromptProps {
59
+ /** `useAutosave().recovery`; nothing renders while it is `null`. */
60
+ recovery: {
61
+ meta: RecoveryMeta;
62
+ } | null;
63
+ onRestore: () => void;
64
+ onDiscard: () => void;
65
+ /** Formats the snapshot time (default `toLocaleString`). */
66
+ formatTime?: (time: number) => string;
67
+ restoreLabel?: string;
68
+ discardLabel?: string;
69
+ className?: string;
70
+ }
71
+ /**
72
+ * "Restore unsaved changes from <time>?" banner with Restore / Discard buttons
73
+ * (Tailwind + theme tokens).
74
+ */
75
+ declare const RecoveryPrompt: React__default.FC<RecoveryPromptProps>;
76
+
77
+ export { RecoveryPrompt, type RecoveryPromptProps, type UseAutosaveOptions, type UseAutosaveResult, useAutosave };
@@ -0,0 +1,77 @@
1
+ import { StorageAdapter, RevisionChangeSource, DirtyFlagSource, AutosaveStatusInfo, AutosaveRecovery, AutosaveController, RecoveryMeta } from '@pixerate/editor/persistence';
2
+ import React__default from 'react';
3
+
4
+ interface UseAutosaveOptions<T> {
5
+ storage: StorageAdapter;
6
+ /** Snapshot key (the meta lives at `<key>:meta`). */
7
+ key: string;
8
+ /** Reads the current document (the latest function is always used). */
9
+ getSnapshot: () => T;
10
+ serialize?: (snapshot: T) => string;
11
+ deserialize?: (text: string) => T;
12
+ /** Document name stored with the snapshot. */
13
+ name?: string;
14
+ /** Change notifications, e.g. a `HistoryManager`. */
15
+ history?: RevisionChangeSource;
16
+ /** Saved-vs-current flag, e.g. `useHistoryDirty().tracker` or a `bindDirtyToHistory` binding. */
17
+ dirty?: DirtyFlagSource;
18
+ interval?: number;
19
+ debounceMs?: number;
20
+ retryBaseMs?: number;
21
+ retryMaxMs?: number;
22
+ /**
23
+ * Whether the document has finished loading (default `true`). Snapshots start
24
+ * once this is true and any recovered snapshot was restored or discarded.
25
+ */
26
+ ready?: boolean;
27
+ /** Look for an earlier session's snapshot on mount (default `true`). */
28
+ recover?: boolean;
29
+ /** Write pending changes on `pagehide` and when the tab is hidden (default `true`). */
30
+ flushOnHide?: boolean;
31
+ }
32
+ interface UseAutosaveResult<T> {
33
+ status: AutosaveStatusInfo;
34
+ /** An earlier session's unsaved snapshot, until restored or discarded. */
35
+ recovery: AutosaveRecovery<T> | null;
36
+ /** True while the recovery check runs or a recovered snapshot awaits a decision. */
37
+ pendingRecovery: boolean;
38
+ /** Takes the recovered snapshot (apply it to the editor) and starts autosaving. */
39
+ restore: () => T | undefined;
40
+ /** Deletes the recovered snapshot and starts autosaving. */
41
+ discard: () => Promise<void>;
42
+ /** Writes pending changes now. */
43
+ flushNow: () => Promise<void>;
44
+ /** Call after an explicit save: marks the current revision saved and retires this session's snapshot. */
45
+ markClean: () => Promise<void>;
46
+ /** Records a change made outside `history`. */
47
+ notifyChange: () => void;
48
+ controller: AutosaveController<T> | null;
49
+ }
50
+ /**
51
+ * Crash-recovery autosave bound to a history and dirty flag, with page
52
+ * lifecycle flushing and a recovery check on mount (see
53
+ * `createAutosaveController` in `@pixerate/editor/persistence`). Render
54
+ * `<RecoveryPrompt>` with `recovery`, `restore` and `discard`.
55
+ */
56
+ declare function useAutosave<T>(options: UseAutosaveOptions<T>): UseAutosaveResult<T>;
57
+
58
+ interface RecoveryPromptProps {
59
+ /** `useAutosave().recovery`; nothing renders while it is `null`. */
60
+ recovery: {
61
+ meta: RecoveryMeta;
62
+ } | null;
63
+ onRestore: () => void;
64
+ onDiscard: () => void;
65
+ /** Formats the snapshot time (default `toLocaleString`). */
66
+ formatTime?: (time: number) => string;
67
+ restoreLabel?: string;
68
+ discardLabel?: string;
69
+ className?: string;
70
+ }
71
+ /**
72
+ * "Restore unsaved changes from <time>?" banner with Restore / Discard buttons
73
+ * (Tailwind + theme tokens).
74
+ */
75
+ declare const RecoveryPrompt: React__default.FC<RecoveryPromptProps>;
76
+
77
+ export { RecoveryPrompt, type RecoveryPromptProps, type UseAutosaveOptions, type UseAutosaveResult, useAutosave };
@@ -0,0 +1,9 @@
1
+ import {
2
+ RecoveryPrompt,
3
+ useAutosave
4
+ } from "../chunk-XWFU2CSG.js";
5
+ export {
6
+ RecoveryPrompt,
7
+ useAutosave
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}