@haklex/rich-ext-excalidraw 0.49.0 → 0.50.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.
- package/dist/ExcalidrawConfigContext.d.ts +3 -1
- package/dist/ExcalidrawConfigContext.d.ts.map +1 -1
- package/dist/ExcalidrawDisplayRenderer.d.ts +1 -0
- package/dist/ExcalidrawDisplayRenderer.d.ts.map +1 -1
- package/dist/ExcalidrawEditRenderer.d.ts.map +1 -1
- package/dist/ExcalidrawFrameStates.d.ts +11 -0
- package/dist/ExcalidrawFrameStates.d.ts.map +1 -0
- package/dist/ExcalidrawSSRRenderer.d.ts.map +1 -1
- package/dist/index.mjs +51 -55
- package/dist/rich-ext-excalidraw.css +1 -1
- package/dist/scene/InteractiveScene.d.ts +11 -0
- package/dist/scene/InteractiveScene.d.ts.map +1 -0
- package/dist/scene/Scene.d.ts +24 -0
- package/dist/scene/Scene.d.ts.map +1 -0
- package/dist/scene/fonts.d.ts +8 -0
- package/dist/scene/fonts.d.ts.map +1 -0
- package/dist/scene/normalize.d.ts +4 -0
- package/dist/scene/normalize.d.ts.map +1 -0
- package/dist/scene/rough.d.ts +19 -0
- package/dist/scene/rough.d.ts.map +1 -0
- package/dist/scene/scene.test.d.ts +2 -0
- package/dist/scene/scene.test.d.ts.map +1 -0
- package/dist/scene/styles.css.d.ts +7 -0
- package/dist/scene/styles.css.d.ts.map +1 -0
- package/dist/scene/types.d.ts +118 -0
- package/dist/scene/types.d.ts.map +1 -0
- package/dist/static.mjs +2 -2
- package/dist/styles.css.d.ts +5 -2
- package/dist/styles.css.d.ts.map +1 -1
- package/dist/transformer-C2e_qiIg.js +487 -0
- package/dist/useExcalidrawData.d.ts +2 -0
- package/dist/useExcalidrawData.d.ts.map +1 -1
- package/dist/useExcalidrawFont-DAmoYxvU.js +795 -0
- package/dist/useExcalidrawFont.d.ts +2 -0
- package/dist/useExcalidrawFont.d.ts.map +1 -0
- package/package.json +12 -6
- package/dist/constants.d.ts +0 -5
- package/dist/constants.d.ts.map +0 -1
- package/dist/transformer-BaQILRBF.js +0 -315
- package/dist/useExcalidrawData-ZN9PHFyy.js +0 -227
|
@@ -0,0 +1,795 @@
|
|
|
1
|
+
import { createContext, memo, use, useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { PenLine, TriangleAlert } from "lucide-react";
|
|
4
|
+
import { RoughGenerator } from "roughjs/bin/generator";
|
|
5
|
+
//#region src/ExcalidrawConfigContext.tsx
|
|
6
|
+
var ExcalidrawConfigContext = createContext({});
|
|
7
|
+
function ExcalidrawConfigProvider({ apiUrl, fontCssHref, saveSnapshot, children }) {
|
|
8
|
+
const value = useMemo(() => ({
|
|
9
|
+
apiUrl,
|
|
10
|
+
fontCssHref,
|
|
11
|
+
saveSnapshot
|
|
12
|
+
}), [
|
|
13
|
+
apiUrl,
|
|
14
|
+
fontCssHref,
|
|
15
|
+
saveSnapshot
|
|
16
|
+
]);
|
|
17
|
+
return /* @__PURE__ */ jsx(ExcalidrawConfigContext.Provider, {
|
|
18
|
+
value,
|
|
19
|
+
children
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function useExcalidrawConfig() {
|
|
23
|
+
return use(ExcalidrawConfigContext);
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/styles.css.ts
|
|
27
|
+
var excalidrawStaticContainer = "_1c3wdzl0";
|
|
28
|
+
var excalidrawEditorContainer = "_1c3wdzl1";
|
|
29
|
+
var excalidrawPlaceholder = "_1c3wdzl2";
|
|
30
|
+
var excalidrawStateLayer = "_1c3wdzl3";
|
|
31
|
+
var excalidrawStateIcon = "_1c3wdzl4";
|
|
32
|
+
var excalidrawLoading = "_1c3wdzl6";
|
|
33
|
+
var excalidrawEmpty = "_1c3wdzl7";
|
|
34
|
+
var excalidrawError = "_1c3wdzl8";
|
|
35
|
+
var excalidrawErrorIcon = "_1c3wdzl9";
|
|
36
|
+
var excalidrawFullscreenPopup = "_1c3wdzlb";
|
|
37
|
+
var excalidrawDialogHeader = "_1c3wdzlc";
|
|
38
|
+
var excalidrawDialogHeaderTitle = "_1c3wdzld";
|
|
39
|
+
var excalidrawStatusDot = "_1c3wdzle";
|
|
40
|
+
var excalidrawDialogTitle = "_1c3wdzlf";
|
|
41
|
+
var excalidrawDialogMeta = "_1c3wdzlg";
|
|
42
|
+
var excalidrawHeaderActions = "_1c3wdzlh";
|
|
43
|
+
var excalidrawHeaderClose = "_1c3wdzli";
|
|
44
|
+
var excalidrawActionBarBtn = "_1c3wdzlj";
|
|
45
|
+
var excalidrawActionBarSep = "_1c3wdzlk";
|
|
46
|
+
var excalidrawActionBarUrl = "_1c3wdzll";
|
|
47
|
+
var excalidrawDialogCanvas = "_1c3wdzlm";
|
|
48
|
+
var excalidrawConfirmActions = "_1c3wdzln";
|
|
49
|
+
var excalidrawConfirmBtn = "_1c3wdzlo";
|
|
50
|
+
var excalidrawConfirmBtnPrimary = "_1c3wdzlp";
|
|
51
|
+
var excalidrawConfirmBtnDanger = "_1c3wdzlq";
|
|
52
|
+
var excalidrawEditOverlay = "_1c3wdzlr";
|
|
53
|
+
var excalidrawEditLabel = "_1c3wdzls";
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/ExcalidrawFrameStates.tsx
|
|
56
|
+
var ExcalidrawPlaceholderState = ({ elementCount }) => {
|
|
57
|
+
const label = elementCount ? `Whiteboard · ${elementCount} elements` : "Whiteboard";
|
|
58
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
59
|
+
"aria-label": label,
|
|
60
|
+
className: excalidrawStateLayer,
|
|
61
|
+
children: [/* @__PURE__ */ jsx(PenLine, {
|
|
62
|
+
"aria-hidden": true,
|
|
63
|
+
className: excalidrawStateIcon
|
|
64
|
+
}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var ExcalidrawLoadingState = () => /* @__PURE__ */ jsx("div", {
|
|
68
|
+
"aria-busy": true,
|
|
69
|
+
className: excalidrawLoading,
|
|
70
|
+
children: /* @__PURE__ */ jsx("span", { children: "Loading whiteboard…" })
|
|
71
|
+
});
|
|
72
|
+
var ExcalidrawEmptyState = () => /* @__PURE__ */ jsx("div", {
|
|
73
|
+
className: excalidrawEmpty,
|
|
74
|
+
children: /* @__PURE__ */ jsx("span", { children: "Empty whiteboard" })
|
|
75
|
+
});
|
|
76
|
+
var ExcalidrawErrorState = ({ message, onRetry }) => /* @__PURE__ */ jsxs("div", {
|
|
77
|
+
className: excalidrawError,
|
|
78
|
+
role: "alert",
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsx(TriangleAlert, {
|
|
81
|
+
"aria-hidden": true,
|
|
82
|
+
className: excalidrawErrorIcon
|
|
83
|
+
}),
|
|
84
|
+
/* @__PURE__ */ jsx("span", { children: message }),
|
|
85
|
+
onRetry && /* @__PURE__ */ jsx("button", {
|
|
86
|
+
className: "_1c3wdzla",
|
|
87
|
+
type: "button",
|
|
88
|
+
onClick: onRetry,
|
|
89
|
+
children: "Retry"
|
|
90
|
+
})
|
|
91
|
+
]
|
|
92
|
+
});
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/scene/fonts.ts
|
|
95
|
+
var EXCALIDRAW_FONT_STACK = {
|
|
96
|
+
hand: "\"Excalifont\", \"LXGW WenKai Screen\", \"Virgil\", \"Comic Sans MS\", \"Segoe Print\", \"Bradley Hand\", cursive",
|
|
97
|
+
sans: "Helvetica, \"PingFang SC\", \"Microsoft YaHei\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", system-ui, sans-serif",
|
|
98
|
+
mono: "\"Cascadia Code\", \"Cascadia\", ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace"
|
|
99
|
+
};
|
|
100
|
+
function fontFamilyToCss(id) {
|
|
101
|
+
switch (id) {
|
|
102
|
+
case 3: return EXCALIDRAW_FONT_STACK.mono;
|
|
103
|
+
default: return EXCALIDRAW_FONT_STACK.hand;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/scene/rough.ts
|
|
108
|
+
var _gen = null;
|
|
109
|
+
function gen() {
|
|
110
|
+
if (!_gen) _gen = new RoughGenerator();
|
|
111
|
+
return _gen;
|
|
112
|
+
}
|
|
113
|
+
function roughOptionsForElement(el, override) {
|
|
114
|
+
const dashes = strokeDash(el.strokeStyle, el.strokeWidth);
|
|
115
|
+
const opts = {
|
|
116
|
+
seed: el.seed || 1,
|
|
117
|
+
stroke: el.strokeColor,
|
|
118
|
+
strokeWidth: el.strokeWidth,
|
|
119
|
+
roughness: el.roughness,
|
|
120
|
+
disableMultiStroke: el.strokeWidth < 2,
|
|
121
|
+
fill: el.backgroundColor === "transparent" ? void 0 : el.backgroundColor,
|
|
122
|
+
fillStyle: el.fillStyle,
|
|
123
|
+
fillWeight: el.strokeWidth / 2,
|
|
124
|
+
hachureGap: el.strokeWidth * 4,
|
|
125
|
+
preserveVertices: false
|
|
126
|
+
};
|
|
127
|
+
if (dashes) opts.strokeLineDash = dashes;
|
|
128
|
+
return {
|
|
129
|
+
...opts,
|
|
130
|
+
...override
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function strokeDash(style, w) {
|
|
134
|
+
if (style === "solid") return void 0;
|
|
135
|
+
if (style === "dashed") return [8, 8 + w];
|
|
136
|
+
if (style === "dotted") return [1.5, 6 + w];
|
|
137
|
+
}
|
|
138
|
+
function rectangle(el, override) {
|
|
139
|
+
return gen().rectangle(0, 0, el.width, el.height, roughOptionsForElement(el, override));
|
|
140
|
+
}
|
|
141
|
+
function ellipse(el, override) {
|
|
142
|
+
return gen().ellipse(el.width / 2, el.height / 2, el.width, el.height, roughOptionsForElement(el, override));
|
|
143
|
+
}
|
|
144
|
+
function diamond(el, override) {
|
|
145
|
+
const hw = el.width / 2;
|
|
146
|
+
const hh = el.height / 2;
|
|
147
|
+
return gen().polygon([
|
|
148
|
+
[hw, 0],
|
|
149
|
+
[el.width, hh],
|
|
150
|
+
[hw, el.height],
|
|
151
|
+
[0, hh]
|
|
152
|
+
], roughOptionsForElement(el, override));
|
|
153
|
+
}
|
|
154
|
+
function path(d, options) {
|
|
155
|
+
return gen().path(d, options);
|
|
156
|
+
}
|
|
157
|
+
function linearPath(points, options) {
|
|
158
|
+
return gen().linearPath(points, options);
|
|
159
|
+
}
|
|
160
|
+
function curve(points, options) {
|
|
161
|
+
return gen().curve(points, options);
|
|
162
|
+
}
|
|
163
|
+
function opsToPath(ops) {
|
|
164
|
+
let d = "";
|
|
165
|
+
for (const { op, data } of ops) switch (op) {
|
|
166
|
+
case "move":
|
|
167
|
+
d += `M${data[0]} ${data[1]} `;
|
|
168
|
+
break;
|
|
169
|
+
case "lineTo":
|
|
170
|
+
d += `L${data[0]} ${data[1]} `;
|
|
171
|
+
break;
|
|
172
|
+
case "bcurveTo": d += `C${data[0]} ${data[1]}, ${data[2]} ${data[3]}, ${data[4]} ${data[5]} `;
|
|
173
|
+
}
|
|
174
|
+
return d.trim();
|
|
175
|
+
}
|
|
176
|
+
function drawableToOpSets(drawable) {
|
|
177
|
+
return drawable.sets.map((set) => ({
|
|
178
|
+
type: set.type,
|
|
179
|
+
d: opsToPath(set.ops)
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
function roundedRectPath(width, height, radius) {
|
|
183
|
+
const r = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
184
|
+
return [
|
|
185
|
+
`M ${r} 0`,
|
|
186
|
+
`L ${width - r} 0`,
|
|
187
|
+
`Q ${width} 0 ${width} ${r}`,
|
|
188
|
+
`L ${width} ${height - r}`,
|
|
189
|
+
`Q ${width} ${height} ${width - r} ${height}`,
|
|
190
|
+
`L ${r} ${height}`,
|
|
191
|
+
`Q 0 ${height} 0 ${height - r}`,
|
|
192
|
+
`L 0 ${r}`,
|
|
193
|
+
`Q 0 0 ${r} 0`,
|
|
194
|
+
"Z"
|
|
195
|
+
].join(" ");
|
|
196
|
+
}
|
|
197
|
+
var PROPORTIONAL_RADIUS = .25;
|
|
198
|
+
var FIXED_RADIUS = 32;
|
|
199
|
+
function getCornerRadius(el) {
|
|
200
|
+
if (!el.roundness) return 0;
|
|
201
|
+
if (el.roundness.type === 3) {
|
|
202
|
+
const min = Math.min(el.width, el.height);
|
|
203
|
+
return Math.min(min * PROPORTIONAL_RADIUS, FIXED_RADIUS);
|
|
204
|
+
}
|
|
205
|
+
return el.roundness.value ?? 0;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/scene/Scene.tsx
|
|
209
|
+
var SVG_PADDING = 32;
|
|
210
|
+
function computeSceneBounds(elements) {
|
|
211
|
+
if (elements.length === 0) return {
|
|
212
|
+
minX: 0,
|
|
213
|
+
minY: 0,
|
|
214
|
+
width: 100,
|
|
215
|
+
height: 100
|
|
216
|
+
};
|
|
217
|
+
let minX = Infinity;
|
|
218
|
+
let minY = Infinity;
|
|
219
|
+
let maxX = -Infinity;
|
|
220
|
+
let maxY = -Infinity;
|
|
221
|
+
for (const el of elements) {
|
|
222
|
+
if (el.isDeleted) continue;
|
|
223
|
+
const x0 = el.x;
|
|
224
|
+
const y0 = el.y;
|
|
225
|
+
const x1 = el.x + el.width;
|
|
226
|
+
const y1 = el.y + el.height;
|
|
227
|
+
if (x0 < minX) minX = x0;
|
|
228
|
+
if (y0 < minY) minY = y0;
|
|
229
|
+
if (x1 > maxX) maxX = x1;
|
|
230
|
+
if (y1 > maxY) maxY = y1;
|
|
231
|
+
}
|
|
232
|
+
if (!Number.isFinite(minX)) return {
|
|
233
|
+
minX: 0,
|
|
234
|
+
minY: 0,
|
|
235
|
+
width: 100,
|
|
236
|
+
height: 100
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
minX: minX - SVG_PADDING,
|
|
240
|
+
minY: minY - SVG_PADDING,
|
|
241
|
+
width: maxX - minX + 64,
|
|
242
|
+
height: maxY - minY + 64
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
var DARK_SCENE_FILTER = "invert(93%) hue-rotate(180deg)";
|
|
246
|
+
var COUNTER_INVERT_FILTER_ID = "rich-excalidraw-counter-invert";
|
|
247
|
+
var SceneDarkContext = createContext(false);
|
|
248
|
+
var CounterInvertFilter = () => /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", {
|
|
249
|
+
colorInterpolationFilters: "sRGB",
|
|
250
|
+
id: COUNTER_INVERT_FILTER_ID,
|
|
251
|
+
children: [/* @__PURE__ */ jsx("feColorMatrix", {
|
|
252
|
+
type: "hueRotate",
|
|
253
|
+
values: "180"
|
|
254
|
+
}), /* @__PURE__ */ jsx("feColorMatrix", {
|
|
255
|
+
type: "matrix",
|
|
256
|
+
values: "-1.16279 0 0 0 1.081395 0 -1.16279 0 0 1.081395 0 0 -1.16279 0 1.081395 0 0 0 1 0"
|
|
257
|
+
})]
|
|
258
|
+
}) });
|
|
259
|
+
var SceneContent = memo(({ dark = false, files, scene }) => {
|
|
260
|
+
const elements = scene.elements.filter((el) => !el.isDeleted);
|
|
261
|
+
return /* @__PURE__ */ jsxs(SceneDarkContext, {
|
|
262
|
+
value: dark,
|
|
263
|
+
children: [dark && /* @__PURE__ */ jsx(CounterInvertFilter, {}), elements.map((el) => /* @__PURE__ */ jsx(ElementGroup, {
|
|
264
|
+
el,
|
|
265
|
+
files
|
|
266
|
+
}, el.id))]
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
SceneContent.displayName = "SceneContent";
|
|
270
|
+
var Scene = ({ className, files, scene, style, theme = "light" }) => {
|
|
271
|
+
const bounds = computeSceneBounds(scene.elements.filter((el) => !el.isDeleted));
|
|
272
|
+
const isDark = theme === "dark";
|
|
273
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
274
|
+
className,
|
|
275
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
276
|
+
role: "img",
|
|
277
|
+
viewBox: `${bounds.minX} ${bounds.minY} ${bounds.width} ${bounds.height}`,
|
|
278
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
279
|
+
style: {
|
|
280
|
+
width: "100%",
|
|
281
|
+
height: "100%",
|
|
282
|
+
display: "block",
|
|
283
|
+
...isDark ? { filter: DARK_SCENE_FILTER } : null,
|
|
284
|
+
...style
|
|
285
|
+
},
|
|
286
|
+
children: /* @__PURE__ */ jsx(SceneContent, {
|
|
287
|
+
dark: isDark,
|
|
288
|
+
files: files ?? scene.files,
|
|
289
|
+
scene
|
|
290
|
+
})
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
var ElementGroup = ({ el, files }) => {
|
|
294
|
+
const cx = el.x + el.width / 2;
|
|
295
|
+
const cy = el.y + el.height / 2;
|
|
296
|
+
const angleDeg = el.angle * 180 / Math.PI;
|
|
297
|
+
const transform = `translate(${el.x} ${el.y}) rotate(${angleDeg} ${el.width / 2} ${el.height / 2})`;
|
|
298
|
+
return /* @__PURE__ */ jsx("g", {
|
|
299
|
+
"data-cx": cx,
|
|
300
|
+
"data-cy": cy,
|
|
301
|
+
"data-id": el.id,
|
|
302
|
+
"data-type": el.type,
|
|
303
|
+
opacity: el.opacity != null ? el.opacity / 100 : 1,
|
|
304
|
+
transform,
|
|
305
|
+
children: /* @__PURE__ */ jsx(ElementContent, {
|
|
306
|
+
el,
|
|
307
|
+
files
|
|
308
|
+
})
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
var ElementContent = ({ el, files }) => {
|
|
312
|
+
switch (el.type) {
|
|
313
|
+
case "rectangle": return /* @__PURE__ */ jsx(RectangleRender, { el });
|
|
314
|
+
case "ellipse": return /* @__PURE__ */ jsx(EllipseRender, { el });
|
|
315
|
+
case "diamond": return /* @__PURE__ */ jsx(DiamondRender, { el });
|
|
316
|
+
case "line":
|
|
317
|
+
case "arrow": return /* @__PURE__ */ jsx(LinearRender, { el });
|
|
318
|
+
case "freedraw": return /* @__PURE__ */ jsx(FreedrawRender, { el });
|
|
319
|
+
case "text": return /* @__PURE__ */ jsx(TextRender, { el });
|
|
320
|
+
case "image": return /* @__PURE__ */ jsx(ImageRender, {
|
|
321
|
+
el,
|
|
322
|
+
files
|
|
323
|
+
});
|
|
324
|
+
case "frame":
|
|
325
|
+
case "magicframe": return /* @__PURE__ */ jsx(FrameRender, { el });
|
|
326
|
+
case "embeddable":
|
|
327
|
+
case "iframe": return /* @__PURE__ */ jsx(EmbedPlaceholder, { el });
|
|
328
|
+
default: return null;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
var PathSet = ({ drawable, fillColor, strokeColor, strokeWidth }) => {
|
|
332
|
+
const opSets = drawableToOpSets(drawable);
|
|
333
|
+
return /* @__PURE__ */ jsx(Fragment, { children: opSets.map((set, i) => {
|
|
334
|
+
if (set.type === "path") return /* @__PURE__ */ jsx("path", {
|
|
335
|
+
d: set.d,
|
|
336
|
+
fill: "none",
|
|
337
|
+
stroke: strokeColor,
|
|
338
|
+
strokeLinecap: "round",
|
|
339
|
+
strokeLinejoin: "round",
|
|
340
|
+
strokeWidth
|
|
341
|
+
}, i);
|
|
342
|
+
if (set.type === "fillPath") return /* @__PURE__ */ jsx("path", {
|
|
343
|
+
d: set.d,
|
|
344
|
+
fill: fillColor || "none",
|
|
345
|
+
fillRule: "evenodd",
|
|
346
|
+
stroke: "none"
|
|
347
|
+
}, i);
|
|
348
|
+
return /* @__PURE__ */ jsx("path", {
|
|
349
|
+
d: set.d,
|
|
350
|
+
fill: "none",
|
|
351
|
+
stroke: fillColor || strokeColor,
|
|
352
|
+
strokeLinecap: "round",
|
|
353
|
+
strokeLinejoin: "round",
|
|
354
|
+
strokeWidth: drawable.options.fillWeight ?? strokeWidth / 2
|
|
355
|
+
}, i);
|
|
356
|
+
}) });
|
|
357
|
+
};
|
|
358
|
+
var RectangleRender = ({ el }) => {
|
|
359
|
+
const radius = getCornerRadius(el);
|
|
360
|
+
const opts = roughOptionsForElement(el);
|
|
361
|
+
const drawable = radius > 0 ? path(roundedRectPath(el.width, el.height, radius), opts) : rectangle(el);
|
|
362
|
+
return /* @__PURE__ */ jsx(PathSet, {
|
|
363
|
+
drawable,
|
|
364
|
+
fillColor: el.backgroundColor !== "transparent" ? el.backgroundColor : void 0,
|
|
365
|
+
strokeColor: el.strokeColor,
|
|
366
|
+
strokeWidth: el.strokeWidth
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
var EllipseRender = ({ el }) => {
|
|
370
|
+
const drawable = ellipse(el);
|
|
371
|
+
return /* @__PURE__ */ jsx(PathSet, {
|
|
372
|
+
drawable,
|
|
373
|
+
fillColor: el.backgroundColor !== "transparent" ? el.backgroundColor : void 0,
|
|
374
|
+
strokeColor: el.strokeColor,
|
|
375
|
+
strokeWidth: el.strokeWidth
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
var DiamondRender = ({ el }) => {
|
|
379
|
+
const drawable = diamond(el);
|
|
380
|
+
return /* @__PURE__ */ jsx(PathSet, {
|
|
381
|
+
drawable,
|
|
382
|
+
fillColor: el.backgroundColor !== "transparent" ? el.backgroundColor : void 0,
|
|
383
|
+
strokeColor: el.strokeColor,
|
|
384
|
+
strokeWidth: el.strokeWidth
|
|
385
|
+
});
|
|
386
|
+
};
|
|
387
|
+
var ARROWHEAD_LENGTH = 18;
|
|
388
|
+
function arrowheadAngle(points, end) {
|
|
389
|
+
if (points.length < 2) return {
|
|
390
|
+
x: 0,
|
|
391
|
+
y: 0,
|
|
392
|
+
angle: 0
|
|
393
|
+
};
|
|
394
|
+
const idx = end === "end" ? points.length - 1 : 0;
|
|
395
|
+
const next = end === "end" ? points.length - 2 : 1;
|
|
396
|
+
const [x, y] = points[idx];
|
|
397
|
+
const [px, py] = points[next];
|
|
398
|
+
return {
|
|
399
|
+
x,
|
|
400
|
+
y,
|
|
401
|
+
angle: Math.atan2(y - py, x - px)
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
var Arrowhead = ({ angle, color, shape, strokeWidth, x, y }) => {
|
|
405
|
+
if (!shape) return null;
|
|
406
|
+
if (shape === "arrow" || shape === "triangle" || shape === "triangle_outline") {
|
|
407
|
+
const len = ARROWHEAD_LENGTH;
|
|
408
|
+
const a1 = angle + Math.PI - Math.PI / 7;
|
|
409
|
+
const a2 = angle + Math.PI + Math.PI / 7;
|
|
410
|
+
const x1 = x + Math.cos(a1) * len;
|
|
411
|
+
const y1 = y + Math.sin(a1) * len;
|
|
412
|
+
const x2 = x + Math.cos(a2) * len;
|
|
413
|
+
const y2 = y + Math.sin(a2) * len;
|
|
414
|
+
if (shape === "arrow") return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("line", {
|
|
415
|
+
stroke: color,
|
|
416
|
+
strokeLinecap: "round",
|
|
417
|
+
strokeWidth,
|
|
418
|
+
x1: x,
|
|
419
|
+
x2: x1,
|
|
420
|
+
y1: y,
|
|
421
|
+
y2: y1
|
|
422
|
+
}), /* @__PURE__ */ jsx("line", {
|
|
423
|
+
stroke: color,
|
|
424
|
+
strokeLinecap: "round",
|
|
425
|
+
strokeWidth,
|
|
426
|
+
x1: x,
|
|
427
|
+
x2,
|
|
428
|
+
y1: y,
|
|
429
|
+
y2
|
|
430
|
+
})] });
|
|
431
|
+
return /* @__PURE__ */ jsx("polygon", {
|
|
432
|
+
fill: shape === "triangle" ? color : "none",
|
|
433
|
+
points: `${x},${y} ${x1},${y1} ${x2},${y2}`,
|
|
434
|
+
stroke: color,
|
|
435
|
+
strokeLinejoin: "round",
|
|
436
|
+
strokeWidth
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
if (shape === "dot" || shape === "circle" || shape === "circle_outline") return /* @__PURE__ */ jsx("circle", {
|
|
440
|
+
cx: x,
|
|
441
|
+
cy: y,
|
|
442
|
+
fill: shape === "circle_outline" ? "none" : color,
|
|
443
|
+
r: ARROWHEAD_LENGTH / 3,
|
|
444
|
+
stroke: color,
|
|
445
|
+
strokeWidth
|
|
446
|
+
});
|
|
447
|
+
if (shape === "bar") {
|
|
448
|
+
const len = ARROWHEAD_LENGTH / 1.5;
|
|
449
|
+
const perp = angle + Math.PI / 2;
|
|
450
|
+
return /* @__PURE__ */ jsx("line", {
|
|
451
|
+
stroke: color,
|
|
452
|
+
strokeLinecap: "round",
|
|
453
|
+
strokeWidth,
|
|
454
|
+
x1: x + Math.cos(perp) * len,
|
|
455
|
+
x2: x - Math.cos(perp) * len,
|
|
456
|
+
y1: y + Math.sin(perp) * len,
|
|
457
|
+
y2: y - Math.sin(perp) * len
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
return null;
|
|
461
|
+
};
|
|
462
|
+
var LinearRender = ({ el }) => {
|
|
463
|
+
const points = el.points && el.points.length > 0 ? el.points : [[0, 0], [el.width, el.height]];
|
|
464
|
+
const isCurved = el.roundness?.type === 2;
|
|
465
|
+
const opts = roughOptionsForElement(el, {
|
|
466
|
+
fill: void 0,
|
|
467
|
+
fillStyle: void 0
|
|
468
|
+
});
|
|
469
|
+
const drawable = isCurved && points.length > 2 ? curve(points, opts) : linearPath(points, opts);
|
|
470
|
+
const startHead = el.startArrowhead;
|
|
471
|
+
const endHead = el.type === "arrow" ? el.endArrowhead ?? "arrow" : el.endArrowhead;
|
|
472
|
+
const startInfo = startHead ? arrowheadAngle(points, "start") : null;
|
|
473
|
+
const endInfo = endHead ? arrowheadAngle(points, "end") : null;
|
|
474
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
475
|
+
/* @__PURE__ */ jsx(PathSet, {
|
|
476
|
+
drawable,
|
|
477
|
+
strokeColor: el.strokeColor,
|
|
478
|
+
strokeWidth: el.strokeWidth
|
|
479
|
+
}),
|
|
480
|
+
startHead && startInfo && /* @__PURE__ */ jsx(Arrowhead, {
|
|
481
|
+
angle: startInfo.angle + Math.PI,
|
|
482
|
+
color: el.strokeColor,
|
|
483
|
+
shape: startHead,
|
|
484
|
+
strokeWidth: el.strokeWidth,
|
|
485
|
+
x: startInfo.x,
|
|
486
|
+
y: startInfo.y
|
|
487
|
+
}),
|
|
488
|
+
endHead && endInfo && /* @__PURE__ */ jsx(Arrowhead, {
|
|
489
|
+
angle: endInfo.angle,
|
|
490
|
+
color: el.strokeColor,
|
|
491
|
+
shape: endHead,
|
|
492
|
+
strokeWidth: el.strokeWidth,
|
|
493
|
+
x: endInfo.x,
|
|
494
|
+
y: endInfo.y
|
|
495
|
+
})
|
|
496
|
+
] });
|
|
497
|
+
};
|
|
498
|
+
var FreedrawRender = ({ el }) => {
|
|
499
|
+
if (!el.points || el.points.length === 0) return null;
|
|
500
|
+
if (el.points.length === 1) {
|
|
501
|
+
const [x, y] = el.points[0];
|
|
502
|
+
return /* @__PURE__ */ jsx("circle", {
|
|
503
|
+
cx: x,
|
|
504
|
+
cy: y,
|
|
505
|
+
fill: el.strokeColor,
|
|
506
|
+
r: el.strokeWidth
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
const d = el.points.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x} ${y}`).join(" ");
|
|
510
|
+
return /* @__PURE__ */ jsx("path", {
|
|
511
|
+
d,
|
|
512
|
+
fill: "none",
|
|
513
|
+
stroke: el.strokeColor,
|
|
514
|
+
strokeLinecap: "round",
|
|
515
|
+
strokeLinejoin: "round",
|
|
516
|
+
strokeWidth: el.strokeWidth
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
var DEFAULT_LINE_HEIGHT = 1.25;
|
|
520
|
+
var TextRender = ({ el }) => {
|
|
521
|
+
const lineHeight = el.lineHeight ?? DEFAULT_LINE_HEIGHT;
|
|
522
|
+
const lines = el.text.split("\n");
|
|
523
|
+
const fontSize = el.fontSize;
|
|
524
|
+
const family = fontFamilyToCss(el.fontFamily);
|
|
525
|
+
const anchor = el.textAlign === "center" ? "middle" : el.textAlign === "right" ? "end" : "start";
|
|
526
|
+
const ax = el.textAlign === "center" ? el.width / 2 : el.textAlign === "right" ? el.width : 0;
|
|
527
|
+
const dy = fontSize * lineHeight;
|
|
528
|
+
const baseline = fontSize * .82;
|
|
529
|
+
return /* @__PURE__ */ jsx("text", {
|
|
530
|
+
dominantBaseline: "alphabetic",
|
|
531
|
+
fill: el.strokeColor,
|
|
532
|
+
fontFamily: family,
|
|
533
|
+
fontSize,
|
|
534
|
+
style: { whiteSpace: "pre" },
|
|
535
|
+
textAnchor: anchor,
|
|
536
|
+
x: ax,
|
|
537
|
+
y: baseline,
|
|
538
|
+
children: lines.map((line, i) => /* @__PURE__ */ jsx("tspan", {
|
|
539
|
+
dy: i === 0 ? 0 : dy,
|
|
540
|
+
x: ax,
|
|
541
|
+
children: line || " "
|
|
542
|
+
}, i))
|
|
543
|
+
});
|
|
544
|
+
};
|
|
545
|
+
var ImageRender = ({ el, files }) => {
|
|
546
|
+
const dark = use(SceneDarkContext);
|
|
547
|
+
const file = el.fileId && files ? files[el.fileId] : void 0;
|
|
548
|
+
if (!file?.dataURL) return /* @__PURE__ */ jsx(ImagePlaceholder, {
|
|
549
|
+
el,
|
|
550
|
+
label: "Image"
|
|
551
|
+
});
|
|
552
|
+
const scaleX = el.scale?.[0] ?? 1;
|
|
553
|
+
const scaleY = el.scale?.[1] ?? 1;
|
|
554
|
+
return /* @__PURE__ */ jsx("image", {
|
|
555
|
+
filter: dark ? `url(#${COUNTER_INVERT_FILTER_ID})` : void 0,
|
|
556
|
+
height: el.height,
|
|
557
|
+
href: file.dataURL,
|
|
558
|
+
preserveAspectRatio: "none",
|
|
559
|
+
width: el.width,
|
|
560
|
+
transform: scaleX !== 1 || scaleY !== 1 ? `translate(${scaleX < 0 ? el.width : 0} ${scaleY < 0 ? el.height : 0}) scale(${scaleX} ${scaleY})` : void 0
|
|
561
|
+
});
|
|
562
|
+
};
|
|
563
|
+
var ImagePlaceholder = ({ el, label }) => {
|
|
564
|
+
return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("rect", {
|
|
565
|
+
fill: "none",
|
|
566
|
+
height: el.height,
|
|
567
|
+
stroke: el.strokeColor || "#888",
|
|
568
|
+
strokeDasharray: "4 4",
|
|
569
|
+
strokeWidth: 1,
|
|
570
|
+
width: el.width
|
|
571
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
572
|
+
dominantBaseline: "middle",
|
|
573
|
+
fill: el.strokeColor || "#888",
|
|
574
|
+
fontFamily: fontFamilyToCss(1),
|
|
575
|
+
fontSize: Math.min(16, el.height / 4),
|
|
576
|
+
textAnchor: "middle",
|
|
577
|
+
x: el.width / 2,
|
|
578
|
+
y: el.height / 2,
|
|
579
|
+
children: label
|
|
580
|
+
})] });
|
|
581
|
+
};
|
|
582
|
+
var FrameRender = ({ el }) => {
|
|
583
|
+
const name = el.name || (el.type === "magicframe" ? "Magic frame" : "Frame");
|
|
584
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("rect", {
|
|
585
|
+
fill: "none",
|
|
586
|
+
height: el.height,
|
|
587
|
+
rx: 4,
|
|
588
|
+
stroke: "#bbb",
|
|
589
|
+
strokeWidth: 1.5,
|
|
590
|
+
width: el.width
|
|
591
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
592
|
+
fill: "#999",
|
|
593
|
+
fontFamily: fontFamilyToCss(2),
|
|
594
|
+
fontSize: 12,
|
|
595
|
+
x: 4,
|
|
596
|
+
y: -4,
|
|
597
|
+
children: name
|
|
598
|
+
})] });
|
|
599
|
+
};
|
|
600
|
+
var EmbedPlaceholder = ({ el }) => /* @__PURE__ */ jsx(ImagePlaceholder, {
|
|
601
|
+
el,
|
|
602
|
+
label: "Embed"
|
|
603
|
+
});
|
|
604
|
+
//#endregion
|
|
605
|
+
//#region src/scene/normalize.ts
|
|
606
|
+
function toScene(data) {
|
|
607
|
+
if (!data) return null;
|
|
608
|
+
if (typeof data !== "object") return null;
|
|
609
|
+
if (!Array.isArray(data.elements) && data.data !== void 0) return toScene(data.data);
|
|
610
|
+
return {
|
|
611
|
+
type: "excalidraw",
|
|
612
|
+
elements: Array.isArray(data.elements) ? data.elements : [],
|
|
613
|
+
appState: data.appState ?? {},
|
|
614
|
+
files: data.files ?? {}
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
function countElements(scene) {
|
|
618
|
+
return scene.elements.filter((el) => !el.isDeleted).length;
|
|
619
|
+
}
|
|
620
|
+
//#endregion
|
|
621
|
+
//#region src/types.ts
|
|
622
|
+
var LOCAL_SCENE_PATH = /^(?:\.{1,2}\/)?[\w-][\w./-]*\.excalidraw$/;
|
|
623
|
+
function isLocalScenePath(ref) {
|
|
624
|
+
return LOCAL_SCENE_PATH.test(ref);
|
|
625
|
+
}
|
|
626
|
+
function parseSnapshot(raw) {
|
|
627
|
+
if (!raw || !raw.trim()) return null;
|
|
628
|
+
try {
|
|
629
|
+
const json = JSON.parse(raw);
|
|
630
|
+
if (json && typeof json === "object") return {
|
|
631
|
+
type: "inline",
|
|
632
|
+
data: json
|
|
633
|
+
};
|
|
634
|
+
} catch {}
|
|
635
|
+
const lines = raw.split("\n");
|
|
636
|
+
const firstLine = lines[0].trim();
|
|
637
|
+
if (!firstLine.startsWith("http") && !firstLine.startsWith("blob:") && !firstLine.startsWith("ref:") && !isLocalScenePath(firstLine)) return null;
|
|
638
|
+
const remaining = lines.slice(1).join("\n").trim();
|
|
639
|
+
if (remaining) try {
|
|
640
|
+
const delta = JSON.parse(remaining);
|
|
641
|
+
if (delta && typeof delta === "object") return {
|
|
642
|
+
type: "delta",
|
|
643
|
+
baseUrl: firstLine,
|
|
644
|
+
delta
|
|
645
|
+
};
|
|
646
|
+
} catch {}
|
|
647
|
+
return {
|
|
648
|
+
type: "remote",
|
|
649
|
+
url: firstLine
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function serializeSnapshot(snapshot) {
|
|
653
|
+
switch (snapshot.type) {
|
|
654
|
+
case "inline": return JSON.stringify(snapshot.data);
|
|
655
|
+
case "remote": return snapshot.url;
|
|
656
|
+
case "delta": return [snapshot.baseUrl, JSON.stringify(snapshot.delta)].join("\n");
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
//#endregion
|
|
660
|
+
//#region src/useExcalidrawData.ts
|
|
661
|
+
function resolveUrl(url, apiUrl) {
|
|
662
|
+
const refLine = url;
|
|
663
|
+
if (url.startsWith("http") || url.startsWith("blob:") || isLocalScenePath(url)) return {
|
|
664
|
+
fetchUrl: url,
|
|
665
|
+
refLine
|
|
666
|
+
};
|
|
667
|
+
if (url.startsWith("ref:") && apiUrl) return {
|
|
668
|
+
fetchUrl: `${apiUrl}/objects/${url.slice(4)}`,
|
|
669
|
+
refLine
|
|
670
|
+
};
|
|
671
|
+
return { error: url.startsWith("ref:") ? "Missing apiUrl for ref resolution" : "Unrecognized snapshot format" };
|
|
672
|
+
}
|
|
673
|
+
function typedToParsed(typed, apiUrl) {
|
|
674
|
+
switch (typed.type) {
|
|
675
|
+
case "inline": return {
|
|
676
|
+
type: "inline",
|
|
677
|
+
snapshot: typed.data
|
|
678
|
+
};
|
|
679
|
+
case "remote": {
|
|
680
|
+
const result = resolveUrl(typed.url, apiUrl);
|
|
681
|
+
if ("error" in result) return {
|
|
682
|
+
type: "error",
|
|
683
|
+
error: result.error
|
|
684
|
+
};
|
|
685
|
+
return {
|
|
686
|
+
type: "remote",
|
|
687
|
+
fetchUrl: result.fetchUrl,
|
|
688
|
+
refLine: result.refLine
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
case "delta": {
|
|
692
|
+
const result = resolveUrl(typed.baseUrl, apiUrl);
|
|
693
|
+
if ("error" in result) return {
|
|
694
|
+
type: "error",
|
|
695
|
+
error: result.error
|
|
696
|
+
};
|
|
697
|
+
return {
|
|
698
|
+
type: "incremental",
|
|
699
|
+
fetchUrl: result.fetchUrl,
|
|
700
|
+
refLine: result.refLine,
|
|
701
|
+
delta: typed.delta
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
function stringToParsed(data, apiUrl) {
|
|
707
|
+
const typed = parseSnapshot(data);
|
|
708
|
+
if (!typed) return { type: "empty" };
|
|
709
|
+
return typedToParsed(typed, apiUrl);
|
|
710
|
+
}
|
|
711
|
+
function useExcalidrawData(data) {
|
|
712
|
+
const { apiUrl } = useExcalidrawConfig();
|
|
713
|
+
const parsed = useMemo(() => {
|
|
714
|
+
if (data === null || data === void 0) return { type: "empty" };
|
|
715
|
+
if (typeof data === "string") return stringToParsed(data, apiUrl);
|
|
716
|
+
return typedToParsed(data, apiUrl);
|
|
717
|
+
}, [data, apiUrl]);
|
|
718
|
+
const [remoteSnapshot, setRemoteSnapshot] = useState();
|
|
719
|
+
const [baseData, setBaseData] = useState();
|
|
720
|
+
const [loading, setLoading] = useState(parsed.type === "remote" || parsed.type === "incremental");
|
|
721
|
+
const [error, setError] = useState("");
|
|
722
|
+
const [attempt, setAttempt] = useState(0);
|
|
723
|
+
const retry = useCallback(() => setAttempt((n) => n + 1), []);
|
|
724
|
+
useEffect(() => {
|
|
725
|
+
if (parsed.type !== "remote" && parsed.type !== "incremental") return;
|
|
726
|
+
const { fetchUrl } = parsed;
|
|
727
|
+
const delta = parsed.type === "incremental" ? parsed.delta : void 0;
|
|
728
|
+
let cancelled = false;
|
|
729
|
+
setLoading(true);
|
|
730
|
+
setError("");
|
|
731
|
+
fetch(fetchUrl).then((res) => {
|
|
732
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
733
|
+
return res.json();
|
|
734
|
+
}).then(async (json) => {
|
|
735
|
+
if (cancelled) return;
|
|
736
|
+
setBaseData(json);
|
|
737
|
+
if ((delta ? Object.keys(delta) : []).length > 0) {
|
|
738
|
+
const { patch } = await import("jsondiffpatch");
|
|
739
|
+
if (cancelled) return;
|
|
740
|
+
const patched = patch(structuredClone(json), delta);
|
|
741
|
+
setRemoteSnapshot(patched);
|
|
742
|
+
} else setRemoteSnapshot(json);
|
|
743
|
+
setLoading(false);
|
|
744
|
+
}).catch((err) => {
|
|
745
|
+
if (!cancelled) {
|
|
746
|
+
setError(err instanceof Error ? err.message : "Failed to load");
|
|
747
|
+
setLoading(false);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
return () => {
|
|
751
|
+
cancelled = true;
|
|
752
|
+
};
|
|
753
|
+
}, [parsed, attempt]);
|
|
754
|
+
if (parsed.type === "inline") return {
|
|
755
|
+
snapshot: parsed.snapshot,
|
|
756
|
+
loading: false,
|
|
757
|
+
error: "",
|
|
758
|
+
retry
|
|
759
|
+
};
|
|
760
|
+
if (parsed.type === "remote" || parsed.type === "incremental") return {
|
|
761
|
+
snapshot: remoteSnapshot,
|
|
762
|
+
loading,
|
|
763
|
+
error,
|
|
764
|
+
retry,
|
|
765
|
+
baseRef: parsed.refLine,
|
|
766
|
+
baseData
|
|
767
|
+
};
|
|
768
|
+
if (parsed.type === "error") return {
|
|
769
|
+
snapshot: void 0,
|
|
770
|
+
loading: false,
|
|
771
|
+
error: parsed.error,
|
|
772
|
+
retry
|
|
773
|
+
};
|
|
774
|
+
return {
|
|
775
|
+
snapshot: void 0,
|
|
776
|
+
loading: false,
|
|
777
|
+
error: "",
|
|
778
|
+
retry
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
//#endregion
|
|
782
|
+
//#region src/useExcalidrawFont.ts
|
|
783
|
+
function useExcalidrawFont() {
|
|
784
|
+
const { fontCssHref } = useExcalidrawConfig();
|
|
785
|
+
useEffect(() => {
|
|
786
|
+
if (!fontCssHref || typeof document === "undefined") return;
|
|
787
|
+
if (document.head.querySelector(`link[href="${CSS.escape(fontCssHref)}"]`)) return;
|
|
788
|
+
const link = document.createElement("link");
|
|
789
|
+
link.rel = "stylesheet";
|
|
790
|
+
link.href = fontCssHref;
|
|
791
|
+
document.head.append(link);
|
|
792
|
+
}, [fontCssHref]);
|
|
793
|
+
}
|
|
794
|
+
//#endregion
|
|
795
|
+
export { excalidrawEditorContainer as A, excalidrawDialogCanvas as C, excalidrawDialogTitle as D, excalidrawDialogMeta as E, excalidrawStaticContainer as F, excalidrawStatusDot as I, ExcalidrawConfigProvider as L, excalidrawHeaderActions as M, excalidrawHeaderClose as N, excalidrawEditLabel as O, excalidrawPlaceholder as P, useExcalidrawConfig as R, excalidrawConfirmBtnPrimary as S, excalidrawDialogHeaderTitle as T, excalidrawActionBarSep as _, serializeSnapshot as a, excalidrawConfirmBtn as b, DARK_SCENE_FILTER as c, computeSceneBounds as d, ExcalidrawEmptyState as f, excalidrawActionBarBtn as g, ExcalidrawPlaceholderState as h, parseSnapshot as i, excalidrawFullscreenPopup as j, excalidrawEditOverlay as k, Scene as l, ExcalidrawLoadingState as m, useExcalidrawData as n, countElements as o, ExcalidrawErrorState as p, isLocalScenePath as r, toScene as s, useExcalidrawFont as t, SceneContent as u, excalidrawActionBarUrl as v, excalidrawDialogHeader as w, excalidrawConfirmBtnDanger as x, excalidrawConfirmActions as y };
|