@haklex/rich-ext-excalidraw 0.0.79 → 0.0.81

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.
@@ -0,0 +1,226 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
+ import { D as excalidrawStaticContainer, S as excalidrawFullscreenPopup, T as excalidrawLoading, _ as excalidrawDialogTitle, c as excalidrawActionGroup, g as excalidrawDialogMeta, h as excalidrawDialogHeaderTitle, k as readonlyUIOptions, m as excalidrawDialogHeader, p as excalidrawDialogCanvas, s as excalidrawActionButton, t as useExcalidrawData, w as excalidrawHeaderClose, x as excalidrawError } from "./useExcalidrawData-DcXa8vqV.js";
3
+ import { Component, useCallback, useEffect, useRef, useState } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { useColorScheme } from "@haklex/rich-editor";
6
+ import { presentDialog } from "@haklex/rich-editor-ui";
7
+ import { usePortalTheme } from "@haklex/rich-style-token";
8
+ import { Maximize2, ScanSearch, X, ZoomIn, ZoomOut } from "lucide-react";
9
+ //#region \0@oxc-project+runtime@0.115.0/helpers/typeof.js
10
+ function _typeof(o) {
11
+ "@babel/helpers - typeof";
12
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
13
+ return typeof o;
14
+ } : function(o) {
15
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
16
+ }, _typeof(o);
17
+ }
18
+ //#endregion
19
+ //#region \0@oxc-project+runtime@0.115.0/helpers/toPrimitive.js
20
+ function toPrimitive(t, r) {
21
+ if ("object" != _typeof(t) || !t) return t;
22
+ var e = t[Symbol.toPrimitive];
23
+ if (void 0 !== e) {
24
+ var i = e.call(t, r || "default");
25
+ if ("object" != _typeof(i)) return i;
26
+ throw new TypeError("@@toPrimitive must return a primitive value.");
27
+ }
28
+ return ("string" === r ? String : Number)(t);
29
+ }
30
+ //#endregion
31
+ //#region \0@oxc-project+runtime@0.115.0/helpers/toPropertyKey.js
32
+ function toPropertyKey(t) {
33
+ var i = toPrimitive(t, "string");
34
+ return "symbol" == _typeof(i) ? i : i + "";
35
+ }
36
+ //#endregion
37
+ //#region \0@oxc-project+runtime@0.115.0/helpers/defineProperty.js
38
+ function _defineProperty(e, r, t) {
39
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
40
+ value: t,
41
+ enumerable: !0,
42
+ configurable: !0,
43
+ writable: !0
44
+ }) : e[r] = t, e;
45
+ }
46
+ //#endregion
47
+ //#region src/ExcalidrawDisplayRenderer.tsx
48
+ var ExcalidrawDisplayRenderer_exports = /* @__PURE__ */ __exportAll({ ExcalidrawDisplayRenderer: () => ExcalidrawDisplayRenderer });
49
+ var ExcalidrawDisplayRenderer = ({ snapshot }) => {
50
+ return /* @__PURE__ */ jsx(ExcalidrawStaticCanvas, {
51
+ snapshot,
52
+ theme: useColorScheme()
53
+ });
54
+ };
55
+ var ExcalidrawExpandContent = ({ dismiss, ExcalidrawComponent, data, theme }) => {
56
+ const apiRef = useRef(null);
57
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
58
+ className: excalidrawDialogHeader,
59
+ children: [/* @__PURE__ */ jsxs("div", {
60
+ className: excalidrawDialogHeaderTitle,
61
+ children: [/* @__PURE__ */ jsx("span", {
62
+ className: excalidrawDialogTitle,
63
+ children: "Whiteboard"
64
+ }), /* @__PURE__ */ jsx("span", {
65
+ className: excalidrawDialogMeta,
66
+ children: "excalidraw"
67
+ })]
68
+ }), /* @__PURE__ */ jsx("button", {
69
+ className: excalidrawHeaderClose,
70
+ type: "button",
71
+ onClick: dismiss,
72
+ children: /* @__PURE__ */ jsx(X, { size: 18 })
73
+ })]
74
+ }), /* @__PURE__ */ jsx("div", {
75
+ className: excalidrawDialogCanvas,
76
+ children: /* @__PURE__ */ jsx(ExcalidrawComponent, {
77
+ viewModeEnabled: true,
78
+ zenModeEnabled: true,
79
+ UIOptions: readonlyUIOptions,
80
+ initialData: data,
81
+ theme,
82
+ excalidrawAPI: (api) => {
83
+ apiRef.current = api;
84
+ setTimeout(() => api.scrollToContent(), 100);
85
+ }
86
+ })
87
+ })] });
88
+ };
89
+ var ExcalidrawStaticCanvas = ({ snapshot, theme }) => {
90
+ const { snapshot: data, loading: dataLoading, error: dataError } = useExcalidrawData(snapshot);
91
+ const [ExcalidrawComponent, setExcalidrawComponent] = useState(null);
92
+ const [libLoading, setLibLoading] = useState(true);
93
+ const apiRef = useRef(null);
94
+ const { className: portalClassName } = usePortalTheme();
95
+ useEffect(() => {
96
+ import("@excalidraw/excalidraw").then((mod) => {
97
+ const Comp = mod.Excalidraw;
98
+ if (Comp) setExcalidrawComponent(() => Comp);
99
+ setLibLoading(false);
100
+ }).catch((error) => {
101
+ console.error("Error loading excalidraw", error);
102
+ setLibLoading(false);
103
+ });
104
+ }, []);
105
+ const handleExpand = useCallback(() => {
106
+ if (!ExcalidrawComponent || !data) return;
107
+ presentDialog({
108
+ content: ({ dismiss }) => /* @__PURE__ */ jsx(ExcalidrawExpandContent, {
109
+ ExcalidrawComponent,
110
+ data,
111
+ dismiss,
112
+ theme
113
+ }),
114
+ className: excalidrawFullscreenPopup,
115
+ portalClassName,
116
+ theme,
117
+ showCloseButton: false,
118
+ clickOutsideToDismiss: true
119
+ });
120
+ }, [
121
+ ExcalidrawComponent,
122
+ data,
123
+ theme,
124
+ portalClassName
125
+ ]);
126
+ if (dataLoading || libLoading) return /* @__PURE__ */ jsx("div", {
127
+ className: excalidrawStaticContainer,
128
+ children: /* @__PURE__ */ jsx("div", {
129
+ className: excalidrawLoading,
130
+ children: "Loading excalidraw..."
131
+ })
132
+ });
133
+ if (dataError || !data) return /* @__PURE__ */ jsx("div", {
134
+ className: excalidrawStaticContainer,
135
+ children: /* @__PURE__ */ jsx("div", {
136
+ className: excalidrawError,
137
+ children: dataError || "No data"
138
+ })
139
+ });
140
+ if (!ExcalidrawComponent) return /* @__PURE__ */ jsx("div", {
141
+ className: excalidrawStaticContainer,
142
+ children: /* @__PURE__ */ jsx("div", {
143
+ className: excalidrawError,
144
+ children: "Failed to load excalidraw"
145
+ })
146
+ });
147
+ return /* @__PURE__ */ jsxs("div", {
148
+ suppressHydrationWarning: true,
149
+ className: excalidrawStaticContainer,
150
+ "data-color-scheme": theme,
151
+ "data-theme": theme,
152
+ children: [/* @__PURE__ */ jsx(ExcalidrawErrorBoundary, {
153
+ fallback: /* @__PURE__ */ jsx("div", {
154
+ className: excalidrawError,
155
+ children: "Failed to render excalidraw"
156
+ }),
157
+ children: /* @__PURE__ */ jsx(ExcalidrawComponent, {
158
+ viewModeEnabled: true,
159
+ zenModeEnabled: true,
160
+ UIOptions: readonlyUIOptions,
161
+ initialData: data,
162
+ theme,
163
+ excalidrawAPI: (api) => {
164
+ apiRef.current = api;
165
+ setTimeout(() => api.scrollToContent(), 100);
166
+ }
167
+ })
168
+ }), /* @__PURE__ */ jsxs("div", {
169
+ className: excalidrawActionGroup,
170
+ children: [
171
+ /* @__PURE__ */ jsx("button", {
172
+ className: excalidrawActionButton,
173
+ title: "Zoom In",
174
+ type: "button",
175
+ onClick: () => {
176
+ const api = apiRef.current;
177
+ if (!api) return;
178
+ const zoom = api.getAppState().zoom.value;
179
+ api.updateScene({ appState: { zoom: { value: zoom * 1.25 } } });
180
+ },
181
+ children: /* @__PURE__ */ jsx(ZoomIn, { size: 20 })
182
+ }),
183
+ /* @__PURE__ */ jsx("button", {
184
+ className: excalidrawActionButton,
185
+ title: "Zoom Out",
186
+ type: "button",
187
+ onClick: () => {
188
+ const api = apiRef.current;
189
+ if (!api) return;
190
+ const zoom = api.getAppState().zoom.value;
191
+ api.updateScene({ appState: { zoom: { value: zoom / 1.25 } } });
192
+ },
193
+ children: /* @__PURE__ */ jsx(ZoomOut, { size: 20 })
194
+ }),
195
+ /* @__PURE__ */ jsx("button", {
196
+ className: excalidrawActionButton,
197
+ title: "Fit to Content",
198
+ type: "button",
199
+ onClick: () => apiRef.current?.scrollToContent(),
200
+ children: /* @__PURE__ */ jsx(ScanSearch, { size: 20 })
201
+ }),
202
+ /* @__PURE__ */ jsx("button", {
203
+ className: excalidrawActionButton,
204
+ title: "Expand",
205
+ type: "button",
206
+ onClick: handleExpand,
207
+ children: /* @__PURE__ */ jsx(Maximize2, { size: 20 })
208
+ })
209
+ ]
210
+ })]
211
+ });
212
+ };
213
+ var ExcalidrawErrorBoundary = class extends Component {
214
+ constructor(..._args) {
215
+ super(..._args);
216
+ _defineProperty(this, "state", { hasError: false });
217
+ }
218
+ static getDerivedStateFromError() {
219
+ return { hasError: true };
220
+ }
221
+ render() {
222
+ return this.state.hasError ? this.props.fallback : this.props.children;
223
+ }
224
+ };
225
+ //#endregion
226
+ export { ExcalidrawDisplayRenderer_exports as n, _defineProperty as r, ExcalidrawDisplayRenderer as t };
@@ -0,0 +1,475 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-CiIaOW0V.js";
2
+ import { C as excalidrawHeaderActions, O as excalidrawStatusDot, S as excalidrawFullscreenPopup, T as excalidrawLoading, _ as excalidrawDialogTitle, b as excalidrawEditorContainer, d as excalidrawConfirmBtnDanger, f as excalidrawConfirmBtnPrimary, g as excalidrawDialogMeta, i as excalidrawActionBarBtn, j as useExcalidrawConfig, k as readonlyUIOptions, l as excalidrawConfirmActions, m as excalidrawDialogHeader, p as excalidrawDialogCanvas, t as useExcalidrawData, u as excalidrawConfirmBtn, v as excalidrawEditLabel, w as excalidrawHeaderClose, x as excalidrawError, y as excalidrawEditOverlay } from "./useExcalidrawData-DcXa8vqV.js";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import { useColorScheme } from "@haklex/rich-editor";
6
+ import { SegmentedControl, dismissTopDialog, presentDialog } from "@haklex/rich-editor-ui";
7
+ import { usePortalTheme } from "@haklex/rich-style-token";
8
+ import { Clipboard, Download, Pencil, Save, X } from "lucide-react";
9
+ //#region src/ExcalidrawEditRenderer.tsx
10
+ var ExcalidrawEditRenderer_exports = /* @__PURE__ */ __exportAll({ ExcalidrawEditRenderer: () => ExcalidrawEditRenderer });
11
+ var SAVE_DEBOUNCE_MS = 2e3;
12
+ var ExcalidrawEditorDialogContent = ({ dismiss, ExcalidrawComponent, initialData, initialSnapshot, theme, onSave, saveSnapshot, onClose, baseRef, baseData }) => {
13
+ const { className: portalClassName } = usePortalTheme();
14
+ const apiRef = useRef(null);
15
+ const saveTimerRef = useRef(void 0);
16
+ const [isDirty, setIsDirty] = useState(false);
17
+ const isDirtyRef = useRef(false);
18
+ const confirmDialogOpenRef = useRef(false);
19
+ const initializedRef = useRef(false);
20
+ const baseRefRef = useRef(baseRef);
21
+ const baseDataRef = useRef(baseData);
22
+ const [storageMode, setStorageMode] = useState(() => {
23
+ if (!saveSnapshot || !initialSnapshot) return "inline";
24
+ return initialSnapshot.type === "delta" ? "delta" : initialSnapshot.type === "remote" ? "remote" : "inline";
25
+ });
26
+ const storageModeRef = useRef(storageMode);
27
+ const [savedRef, setSavedRef] = useState(() => {
28
+ if (!saveSnapshot || !initialSnapshot) return "";
29
+ if (initialSnapshot.type === "remote") return initialSnapshot.url;
30
+ if (initialSnapshot.type === "delta") return initialSnapshot.baseUrl;
31
+ return "";
32
+ });
33
+ const [isSaving, setIsSaving] = useState(false);
34
+ useEffect(() => {
35
+ return () => {
36
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
37
+ };
38
+ }, []);
39
+ const getSnapshot = useCallback(() => {
40
+ const api = apiRef.current;
41
+ if (!api) return;
42
+ const appState = api.getAppState();
43
+ return {
44
+ elements: api.getSceneElements(),
45
+ appState: {
46
+ viewBackgroundColor: appState.viewBackgroundColor,
47
+ gridSize: appState.gridSize
48
+ },
49
+ files: api.getFiles()
50
+ };
51
+ }, []);
52
+ const performSave = useCallback(() => {
53
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
54
+ const doc = getSnapshot();
55
+ if (!doc) return Promise.resolve();
56
+ const mode = storageModeRef.current;
57
+ if (mode === "delta" && saveSnapshot) {
58
+ setIsSaving(true);
59
+ return (async () => {
60
+ try {
61
+ const currentBaseUrl = baseRefRef.current;
62
+ const currentBaseData = baseDataRef.current;
63
+ if (!currentBaseUrl || !currentBaseData) {
64
+ const ref = await saveSnapshot(doc, baseRefRef.current || void 0);
65
+ baseRefRef.current = ref;
66
+ baseDataRef.current = doc;
67
+ setSavedRef(ref);
68
+ }
69
+ isDirtyRef.current = false;
70
+ setIsDirty(false);
71
+ } finally {
72
+ setIsSaving(false);
73
+ }
74
+ })();
75
+ }
76
+ if (mode === "remote" && saveSnapshot) {
77
+ if (baseRefRef.current && baseDataRef.current && JSON.stringify(doc) === JSON.stringify(baseDataRef.current)) {
78
+ isDirtyRef.current = false;
79
+ setIsDirty(false);
80
+ return Promise.resolve();
81
+ }
82
+ setIsSaving(true);
83
+ return saveSnapshot(doc, baseRefRef.current || void 0).then((ref) => {
84
+ baseRefRef.current = ref;
85
+ baseDataRef.current = doc;
86
+ isDirtyRef.current = false;
87
+ setIsDirty(false);
88
+ setIsSaving(false);
89
+ setSavedRef(ref);
90
+ }, () => {
91
+ setIsSaving(false);
92
+ });
93
+ }
94
+ isDirtyRef.current = false;
95
+ setIsDirty(false);
96
+ return Promise.resolve();
97
+ }, [saveSnapshot, getSnapshot]);
98
+ const emitSnapshot = useCallback(async () => {
99
+ const doc = getSnapshot();
100
+ if (!doc) return;
101
+ const mode = storageModeRef.current;
102
+ if (mode === "delta" && saveSnapshot) {
103
+ const currentBaseUrl = baseRefRef.current;
104
+ const currentBaseData = baseDataRef.current;
105
+ if (currentBaseUrl && currentBaseData) {
106
+ const { diff } = await import("jsondiffpatch");
107
+ const delta = diff(currentBaseData, structuredClone(doc));
108
+ onSave(delta ? {
109
+ type: "delta",
110
+ baseUrl: currentBaseUrl,
111
+ delta
112
+ } : {
113
+ type: "remote",
114
+ url: currentBaseUrl
115
+ });
116
+ } else onSave({
117
+ type: "remote",
118
+ url: await saveSnapshot(doc, baseRefRef.current || void 0)
119
+ });
120
+ return;
121
+ }
122
+ if (mode === "remote") {
123
+ const ref = baseRefRef.current;
124
+ if (ref) onSave({
125
+ type: "remote",
126
+ url: ref
127
+ });
128
+ else if (saveSnapshot) onSave({
129
+ type: "remote",
130
+ url: await saveSnapshot(doc)
131
+ });
132
+ return;
133
+ }
134
+ onSave({
135
+ type: "inline",
136
+ data: doc
137
+ });
138
+ }, [
139
+ onSave,
140
+ saveSnapshot,
141
+ getSnapshot
142
+ ]);
143
+ const handleChange = useCallback((elements) => {
144
+ if (!initializedRef.current) {
145
+ initializedRef.current = true;
146
+ return;
147
+ }
148
+ if (elements.length === 0) return;
149
+ if (!isDirtyRef.current) {
150
+ isDirtyRef.current = true;
151
+ setIsDirty(true);
152
+ }
153
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
154
+ saveTimerRef.current = setTimeout(() => performSave(), SAVE_DEBOUNCE_MS);
155
+ }, [performSave]);
156
+ const handleSaveAndClose = useCallback(() => {
157
+ performSave().then(async () => {
158
+ await emitSnapshot();
159
+ onClose(getSnapshot());
160
+ dismiss();
161
+ });
162
+ }, [
163
+ performSave,
164
+ emitSnapshot,
165
+ getSnapshot,
166
+ onClose,
167
+ dismiss
168
+ ]);
169
+ const handleDiscard = useCallback(() => {
170
+ if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
171
+ dismiss();
172
+ }, [dismiss]);
173
+ const showConfirmDialog = useCallback(() => {
174
+ if (confirmDialogOpenRef.current) return;
175
+ confirmDialogOpenRef.current = true;
176
+ presentDialog({
177
+ title: "Unsaved Changes",
178
+ description: "You have unsaved changes that will be lost if you close now.",
179
+ content: ({ dismiss: dismissConfirm }) => {
180
+ const wrappedDismiss = () => {
181
+ confirmDialogOpenRef.current = false;
182
+ dismissConfirm();
183
+ };
184
+ return /* @__PURE__ */ jsxs("div", {
185
+ className: excalidrawConfirmActions,
186
+ children: [
187
+ /* @__PURE__ */ jsx("button", {
188
+ className: excalidrawConfirmBtn,
189
+ type: "button",
190
+ onClick: wrappedDismiss,
191
+ children: "Continue Editing"
192
+ }),
193
+ /* @__PURE__ */ jsx("button", {
194
+ className: excalidrawConfirmBtnDanger,
195
+ type: "button",
196
+ onClick: () => {
197
+ wrappedDismiss();
198
+ handleDiscard();
199
+ },
200
+ children: "Discard"
201
+ }),
202
+ /* @__PURE__ */ jsx("button", {
203
+ className: excalidrawConfirmBtnPrimary,
204
+ type: "button",
205
+ onClick: () => {
206
+ wrappedDismiss();
207
+ handleSaveAndClose();
208
+ },
209
+ children: "Save & Close"
210
+ })
211
+ ]
212
+ });
213
+ },
214
+ portalClassName,
215
+ theme,
216
+ showCloseButton: false,
217
+ clickOutsideToDismiss: false
218
+ });
219
+ }, [
220
+ handleDiscard,
221
+ handleSaveAndClose,
222
+ portalClassName,
223
+ theme
224
+ ]);
225
+ const attemptClose = useCallback(() => {
226
+ if (isDirtyRef.current) showConfirmDialog();
227
+ else emitSnapshot().then(() => {
228
+ onClose(getSnapshot());
229
+ dismiss();
230
+ });
231
+ }, [
232
+ dismiss,
233
+ showConfirmDialog,
234
+ emitSnapshot,
235
+ getSnapshot,
236
+ onClose
237
+ ]);
238
+ useEffect(() => {
239
+ const handleKeyDown = (e) => {
240
+ if (e.key === "Escape") {
241
+ e.preventDefault();
242
+ e.stopImmediatePropagation();
243
+ if (confirmDialogOpenRef.current) {
244
+ confirmDialogOpenRef.current = false;
245
+ dismissTopDialog();
246
+ } else attemptClose();
247
+ }
248
+ };
249
+ document.addEventListener("keydown", handleKeyDown, true);
250
+ return () => document.removeEventListener("keydown", handleKeyDown, true);
251
+ }, [attemptClose]);
252
+ const handleManualUpload = useCallback(() => {
253
+ performSave();
254
+ }, [performSave]);
255
+ const handleExportJson = useCallback(() => {
256
+ const doc = getSnapshot();
257
+ if (!doc) return;
258
+ const blob = new Blob([JSON.stringify(doc, null, 2)], { type: "application/json" });
259
+ const url = URL.createObjectURL(blob);
260
+ const a = document.createElement("a");
261
+ a.href = url;
262
+ a.download = "excalidraw-snapshot.json";
263
+ a.click();
264
+ URL.revokeObjectURL(url);
265
+ }, [getSnapshot]);
266
+ const handleCopyJson = useCallback(() => {
267
+ const doc = getSnapshot();
268
+ if (!doc) return;
269
+ navigator.clipboard.writeText(JSON.stringify(doc));
270
+ }, [getSnapshot]);
271
+ const handleRefChange = useCallback((e) => {
272
+ const { value } = e.target;
273
+ setSavedRef(value);
274
+ baseRefRef.current = value;
275
+ baseDataRef.current = void 0;
276
+ }, []);
277
+ const handleStorageModeChange = useCallback((newMode) => {
278
+ setStorageMode(newMode);
279
+ storageModeRef.current = newMode;
280
+ if (newMode === "inline") setSavedRef("");
281
+ performSave();
282
+ }, [performSave]);
283
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
284
+ className: excalidrawDialogHeader,
285
+ children: [
286
+ /* @__PURE__ */ jsx("span", {
287
+ className: excalidrawStatusDot,
288
+ style: { backgroundColor: isDirty ? "#f59e0b" : "#22c55e" }
289
+ }),
290
+ /* @__PURE__ */ jsx("span", {
291
+ className: excalidrawDialogTitle,
292
+ children: "Canvas Editor"
293
+ }),
294
+ /* @__PURE__ */ jsx("span", {
295
+ className: excalidrawDialogMeta,
296
+ children: "excalidraw"
297
+ }),
298
+ /* @__PURE__ */ jsxs("div", {
299
+ className: excalidrawHeaderActions,
300
+ children: [
301
+ saveSnapshot && /* @__PURE__ */ jsxs(Fragment, { children: [
302
+ /* @__PURE__ */ jsx(SegmentedControl, {
303
+ value: storageMode,
304
+ items: [
305
+ {
306
+ value: "inline",
307
+ label: "Inline"
308
+ },
309
+ {
310
+ value: "remote",
311
+ label: "Remote"
312
+ },
313
+ {
314
+ value: "delta",
315
+ label: "Delta"
316
+ }
317
+ ],
318
+ onChange: handleStorageModeChange
319
+ }),
320
+ /* @__PURE__ */ jsx("div", { className: "_1c3wdzlh" }),
321
+ /* @__PURE__ */ jsxs("button", {
322
+ className: "_1c3wdzlg",
323
+ disabled: isSaving,
324
+ type: "button",
325
+ onClick: handleManualUpload,
326
+ children: [/* @__PURE__ */ jsx(Save, { size: 14 }), /* @__PURE__ */ jsx("span", { children: isSaving ? "Saving..." : "Save" })]
327
+ }),
328
+ /* @__PURE__ */ jsx("div", { className: "_1c3wdzlh" })
329
+ ] }),
330
+ /* @__PURE__ */ jsxs("button", {
331
+ className: excalidrawActionBarBtn,
332
+ type: "button",
333
+ onClick: handleExportJson,
334
+ children: [/* @__PURE__ */ jsx(Download, { size: 14 }), "JSON"]
335
+ }),
336
+ /* @__PURE__ */ jsxs("button", {
337
+ className: excalidrawActionBarBtn,
338
+ type: "button",
339
+ onClick: handleCopyJson,
340
+ children: [/* @__PURE__ */ jsx(Clipboard, { size: 14 }), "Copy"]
341
+ }),
342
+ storageMode !== "inline" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", { className: "_1c3wdzlh" }), /* @__PURE__ */ jsx("input", {
343
+ className: "_1c3wdzli",
344
+ placeholder: "base URL / ref",
345
+ spellCheck: false,
346
+ type: "text",
347
+ value: savedRef,
348
+ onChange: handleRefChange
349
+ })] })
350
+ ]
351
+ }),
352
+ /* @__PURE__ */ jsx("button", {
353
+ className: excalidrawHeaderClose,
354
+ type: "button",
355
+ onClick: attemptClose,
356
+ children: /* @__PURE__ */ jsx(X, { size: 18 })
357
+ })
358
+ ]
359
+ }), /* @__PURE__ */ jsx("div", {
360
+ className: excalidrawDialogCanvas,
361
+ children: /* @__PURE__ */ jsx(ExcalidrawComponent, {
362
+ initialData,
363
+ theme,
364
+ excalidrawAPI: (api) => {
365
+ apiRef.current = api;
366
+ },
367
+ onChange: handleChange
368
+ })
369
+ })] });
370
+ };
371
+ var ExcalidrawEditRenderer = ({ snapshot, onSnapshotChange }) => {
372
+ const theme = useColorScheme();
373
+ const { saveSnapshot } = useExcalidrawConfig();
374
+ const { snapshot: initialData, loading: dataLoading, error: dataError, baseRef, baseData } = useExcalidrawData(snapshot);
375
+ const [ExcalidrawComponent, setExcalidrawComponent] = useState(null);
376
+ const [libLoading, setLibLoading] = useState(true);
377
+ const previewApiRef = useRef(null);
378
+ const initialDataRef = useRef(void 0);
379
+ const [previewKey, setPreviewKey] = useState(0);
380
+ const onSnapshotChangeRef = useRef(onSnapshotChange);
381
+ onSnapshotChangeRef.current = onSnapshotChange;
382
+ const saveSnapshotRef = useRef(saveSnapshot);
383
+ saveSnapshotRef.current = saveSnapshot;
384
+ const snapshotRef = useRef(snapshot);
385
+ snapshotRef.current = snapshot;
386
+ const { className: portalClassName } = usePortalTheme();
387
+ useEffect(() => {
388
+ if (initialData && !initialDataRef.current) initialDataRef.current = initialData;
389
+ }, [initialData]);
390
+ useEffect(() => {
391
+ import("@excalidraw/excalidraw").then((mod) => {
392
+ const Comp = mod.Excalidraw || mod.default?.Excalidraw;
393
+ if (Comp) setExcalidrawComponent(() => Comp);
394
+ setLibLoading(false);
395
+ }).catch(() => setLibLoading(false));
396
+ }, []);
397
+ const baseRefRef = useRef(baseRef);
398
+ const baseDataRefOuter = useRef(baseData);
399
+ useEffect(() => {
400
+ if (baseRef) baseRefRef.current = baseRef;
401
+ }, [baseRef]);
402
+ useEffect(() => {
403
+ if (baseData) baseDataRefOuter.current = baseData;
404
+ }, [baseData]);
405
+ const handleOpenEditor = useCallback(() => {
406
+ if (!ExcalidrawComponent || dataLoading) return;
407
+ presentDialog({
408
+ content: ({ dismiss }) => /* @__PURE__ */ jsx(ExcalidrawEditorDialogContent, {
409
+ ExcalidrawComponent,
410
+ baseData: baseDataRefOuter.current,
411
+ baseRef: baseRefRef.current,
412
+ dismiss,
413
+ initialData: initialDataRef.current,
414
+ initialSnapshot: snapshotRef.current,
415
+ saveSnapshot: saveSnapshotRef.current,
416
+ theme,
417
+ onSave: (ref) => onSnapshotChangeRef.current(ref),
418
+ onClose: (doc) => {
419
+ if (doc) {
420
+ initialDataRef.current = doc;
421
+ setPreviewKey((k) => k + 1);
422
+ }
423
+ }
424
+ }),
425
+ className: excalidrawFullscreenPopup,
426
+ portalClassName,
427
+ theme,
428
+ showCloseButton: false,
429
+ clickOutsideToDismiss: false
430
+ });
431
+ }, [
432
+ ExcalidrawComponent,
433
+ dataLoading,
434
+ theme,
435
+ portalClassName
436
+ ]);
437
+ if (dataLoading || libLoading || !ExcalidrawComponent) return /* @__PURE__ */ jsx("div", {
438
+ className: excalidrawEditorContainer,
439
+ children: /* @__PURE__ */ jsx("div", {
440
+ className: excalidrawLoading,
441
+ children: "Loading excalidraw editor..."
442
+ })
443
+ });
444
+ if (dataError) return /* @__PURE__ */ jsx("div", {
445
+ className: excalidrawEditorContainer,
446
+ children: /* @__PURE__ */ jsx("div", {
447
+ className: excalidrawError,
448
+ children: dataError
449
+ })
450
+ });
451
+ return /* @__PURE__ */ jsxs("div", {
452
+ className: excalidrawEditorContainer,
453
+ children: [/* @__PURE__ */ jsx(ExcalidrawComponent, {
454
+ viewModeEnabled: true,
455
+ zenModeEnabled: true,
456
+ UIOptions: readonlyUIOptions,
457
+ initialData: initialDataRef.current,
458
+ theme,
459
+ excalidrawAPI: (api) => {
460
+ previewApiRef.current = api;
461
+ setTimeout(() => api.scrollToContent(), 100);
462
+ }
463
+ }, previewKey), /* @__PURE__ */ jsx("button", {
464
+ className: excalidrawEditOverlay,
465
+ type: "button",
466
+ onClick: handleOpenEditor,
467
+ children: /* @__PURE__ */ jsxs("span", {
468
+ className: excalidrawEditLabel,
469
+ children: [/* @__PURE__ */ jsx(Pencil, { size: 16 }), "Edit Whiteboard"]
470
+ })
471
+ })]
472
+ });
473
+ };
474
+ //#endregion
475
+ export { ExcalidrawEditRenderer_exports as n, ExcalidrawEditRenderer as t };