@haklex/rich-ext-tldraw 0.0.41 → 0.0.43

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,421 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { jsx, jsxs, Fragment } 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 { ZoomIn, ZoomOut, ScanSearch, Maximize2, X } from "lucide-react";
9
+ import { createContext, use, useMemo, useState, useEffect, useRef, useCallback, Component, createElement } from "react";
10
+ import { DecoratorNode } from "lexical";
11
+ const TldrawConfigContext = createContext({});
12
+ function TldrawConfigProvider({
13
+ apiUrl,
14
+ saveSnapshot,
15
+ children
16
+ }) {
17
+ const value = useMemo(
18
+ () => ({ apiUrl, saveSnapshot }),
19
+ [apiUrl, saveSnapshot]
20
+ );
21
+ return /* @__PURE__ */ jsx(TldrawConfigContext.Provider, { value, children });
22
+ }
23
+ function useTldrawConfig() {
24
+ return use(TldrawConfigContext);
25
+ }
26
+ var tldrawStaticContainer = "_1vqtdre0";
27
+ var tldrawEditorContainer = "_1vqtdre1";
28
+ var tldrawLoading = "_1vqtdre2";
29
+ var tldrawError = "_1vqtdre4";
30
+ var tldrawActionGroup = "_1vqtdre5";
31
+ var tldrawActionButton = "_1vqtdre6";
32
+ var tldrawFullscreenPopup = "_1vqtdre7";
33
+ var tldrawDialogHeader = "_1vqtdre8";
34
+ var tldrawStatusDot = "_1vqtdre9";
35
+ var tldrawDialogTitle = "_1vqtdrea";
36
+ var tldrawDialogMeta = "_1vqtdreb";
37
+ var tldrawHeaderActions = "_1vqtdrec";
38
+ var tldrawHeaderClose = "_1vqtdred";
39
+ var tldrawActionBarBtn = "_1vqtdree";
40
+ var tldrawActionBarSep = "_1vqtdref";
41
+ var tldrawActionBarUrl = "_1vqtdreg";
42
+ var tldrawDialogCanvas = "_1vqtdreh";
43
+ var tldrawConfirmActions = "_1vqtdrei";
44
+ var tldrawConfirmBtn = "_1vqtdrej";
45
+ var tldrawConfirmBtnPrimary = "_1vqtdrek";
46
+ var tldrawConfirmBtnDanger = "_1vqtdrel";
47
+ var tldrawEditOverlay = "_1vqtdrem";
48
+ var tldrawEditLabel = "_1vqtdren";
49
+ function useTldrawData(data) {
50
+ const { apiUrl } = useTldrawConfig();
51
+ const parsed = useMemo(() => {
52
+ if (!data) return { type: "empty" };
53
+ try {
54
+ const json = JSON.parse(data);
55
+ if (json && typeof json === "object") {
56
+ return {
57
+ type: "inline",
58
+ snapshot: json
59
+ };
60
+ }
61
+ } catch {
62
+ }
63
+ const firstLine = data.split("\n")[0].trim();
64
+ let fetchUrl2;
65
+ if (firstLine.startsWith("http")) {
66
+ fetchUrl2 = firstLine;
67
+ } else if (firstLine.startsWith("ref:") && apiUrl) {
68
+ fetchUrl2 = `${apiUrl}/objects/${firstLine.slice(4)}`;
69
+ }
70
+ if (fetchUrl2) {
71
+ return { type: "remote", fetchUrl: fetchUrl2 };
72
+ }
73
+ return {
74
+ type: "error",
75
+ error: firstLine.startsWith("ref:") ? "Missing apiUrl for ref resolution" : "Unrecognized snapshot format"
76
+ };
77
+ }, [data, apiUrl]);
78
+ const fetchUrl = parsed.type === "remote" ? parsed.fetchUrl : void 0;
79
+ const [remoteSnapshot, setRemoteSnapshot] = useState();
80
+ const [loading, setLoading] = useState(!!fetchUrl);
81
+ const [error, setError] = useState("");
82
+ useEffect(() => {
83
+ if (!fetchUrl) return;
84
+ let cancelled = false;
85
+ setLoading(true);
86
+ setError("");
87
+ fetch(fetchUrl).then((res) => {
88
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
89
+ return res.json();
90
+ }).then((json) => {
91
+ if (!cancelled) {
92
+ setRemoteSnapshot(json);
93
+ setLoading(false);
94
+ }
95
+ }).catch((err) => {
96
+ if (!cancelled) {
97
+ setError(err instanceof Error ? err.message : "Failed to load");
98
+ setLoading(false);
99
+ }
100
+ });
101
+ return () => {
102
+ cancelled = true;
103
+ };
104
+ }, [fetchUrl]);
105
+ if (parsed.type === "inline") {
106
+ return { snapshot: parsed.snapshot, loading: false, error: "" };
107
+ }
108
+ if (parsed.type === "remote") {
109
+ return { snapshot: remoteSnapshot, loading, error };
110
+ }
111
+ if (parsed.type === "error") {
112
+ return { snapshot: void 0, loading: false, error: parsed.error };
113
+ }
114
+ return { snapshot: void 0, loading: false, error: "" };
115
+ }
116
+ const TldrawDisplayRenderer = ({
117
+ snapshot
118
+ }) => {
119
+ const theme = useColorScheme();
120
+ const containerRef = useRef(null);
121
+ const [hasEnteredView, setHasEnteredView] = useState(false);
122
+ useEffect(() => {
123
+ if (hasEnteredView) return;
124
+ const target = containerRef.current;
125
+ if (!target) return;
126
+ const observer = new IntersectionObserver(
127
+ (entries) => {
128
+ if (entries.some((e) => e.isIntersecting)) {
129
+ setHasEnteredView(true);
130
+ observer.disconnect();
131
+ }
132
+ },
133
+ { rootMargin: "200px 0px", threshold: 0.1 }
134
+ );
135
+ observer.observe(target);
136
+ return () => observer.disconnect();
137
+ }, [hasEnteredView]);
138
+ if (!hasEnteredView) {
139
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawLoading, children: "Loading tldraw..." }) });
140
+ }
141
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, children: /* @__PURE__ */ jsx(TldrawStaticCanvas, { snapshot, theme }) });
142
+ };
143
+ const TldrawExpandContent = ({ dismiss, TldrawComponent, data, theme }) => /* @__PURE__ */ jsxs(Fragment, { children: [
144
+ /* @__PURE__ */ jsxs("div", { className: tldrawDialogHeader, children: [
145
+ /* @__PURE__ */ jsx("span", { className: tldrawDialogTitle, children: "Whiteboard" }),
146
+ /* @__PURE__ */ jsx("span", { className: tldrawDialogMeta, children: "tldraw" }),
147
+ /* @__PURE__ */ jsx("button", { type: "button", className: tldrawHeaderClose, onClick: dismiss, children: /* @__PURE__ */ jsx(X, { size: 18 }) })
148
+ ] }),
149
+ /* @__PURE__ */ jsx("div", { className: tldrawDialogCanvas, children: /* @__PURE__ */ jsx(
150
+ TldrawComponent,
151
+ {
152
+ snapshot: data,
153
+ hideUi: true,
154
+ onMount: (editor) => {
155
+ editor.updateInstanceState({ isReadonly: true });
156
+ editor.setCurrentTool("hand");
157
+ editor.user.updateUserPreferences({ colorScheme: theme });
158
+ setTimeout(() => editor.zoomToFit({ animate: false }), 100);
159
+ }
160
+ }
161
+ ) })
162
+ ] });
163
+ const TldrawStaticCanvas = ({ snapshot, theme }) => {
164
+ const {
165
+ snapshot: data,
166
+ loading: dataLoading,
167
+ error: dataError
168
+ } = useTldrawData(snapshot);
169
+ const [TldrawComponent, setTldrawComponent] = useState(null);
170
+ const [libLoading, setLibLoading] = useState(true);
171
+ const editorRef = useRef(null);
172
+ const { className: portalClassName } = usePortalTheme();
173
+ useEffect(() => {
174
+ import("tldraw").then((mod) => {
175
+ setTldrawComponent(() => mod.Tldraw);
176
+ setLibLoading(false);
177
+ }).catch(() => setLibLoading(false));
178
+ }, []);
179
+ useEffect(() => {
180
+ if (editorRef.current?.user?.updateUserPreferences) {
181
+ editorRef.current.user.updateUserPreferences({ colorScheme: theme });
182
+ }
183
+ }, [theme]);
184
+ const handleMount = useCallback(
185
+ (editor) => {
186
+ editorRef.current = editor;
187
+ editor.updateInstanceState({ isReadonly: true });
188
+ editor.setCurrentTool("hand");
189
+ editor.user.updateUserPreferences({ colorScheme: theme });
190
+ setTimeout(() => {
191
+ editor.zoomToFit({ animate: false });
192
+ }, 100);
193
+ },
194
+ [theme]
195
+ );
196
+ const handleExpand = useCallback(() => {
197
+ if (!TldrawComponent || !data) return;
198
+ presentDialog({
199
+ content: ({ dismiss }) => /* @__PURE__ */ jsx(
200
+ TldrawExpandContent,
201
+ {
202
+ dismiss,
203
+ TldrawComponent,
204
+ data,
205
+ theme
206
+ }
207
+ ),
208
+ className: tldrawFullscreenPopup,
209
+ portalClassName,
210
+ theme,
211
+ showCloseButton: false,
212
+ clickOutsideToDismiss: true
213
+ });
214
+ }, [TldrawComponent, data, theme, portalClassName]);
215
+ const loading = dataLoading || libLoading;
216
+ if (loading) {
217
+ return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawLoading, children: "Loading tldraw..." }) });
218
+ }
219
+ if (dataError || !data) {
220
+ return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawError, children: dataError || "No data" }) });
221
+ }
222
+ if (!TldrawComponent) {
223
+ return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawError, children: "Failed to load tldraw" }) });
224
+ }
225
+ return /* @__PURE__ */ jsxs(
226
+ "div",
227
+ {
228
+ className: tldrawStaticContainer,
229
+ "data-theme": theme,
230
+ "data-color-scheme": theme,
231
+ suppressHydrationWarning: true,
232
+ children: [
233
+ /* @__PURE__ */ jsx(
234
+ TldrawErrorBoundary,
235
+ {
236
+ fallback: /* @__PURE__ */ jsx("div", { className: tldrawError, children: "Failed to render tldraw" }),
237
+ children: /* @__PURE__ */ jsx(TldrawComponent, { snapshot: data, hideUi: true, onMount: handleMount })
238
+ }
239
+ ),
240
+ /* @__PURE__ */ jsxs("div", { className: tldrawActionGroup, children: [
241
+ /* @__PURE__ */ jsx(
242
+ "button",
243
+ {
244
+ type: "button",
245
+ className: tldrawActionButton,
246
+ title: "Zoom In",
247
+ onClick: () => editorRef.current?.zoomIn(),
248
+ children: /* @__PURE__ */ jsx(ZoomIn, { size: 20 })
249
+ }
250
+ ),
251
+ /* @__PURE__ */ jsx(
252
+ "button",
253
+ {
254
+ type: "button",
255
+ className: tldrawActionButton,
256
+ title: "Zoom Out",
257
+ onClick: () => editorRef.current?.zoomOut(),
258
+ children: /* @__PURE__ */ jsx(ZoomOut, { size: 20 })
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsx(
262
+ "button",
263
+ {
264
+ type: "button",
265
+ className: tldrawActionButton,
266
+ title: "Fit to Content",
267
+ onClick: () => editorRef.current?.zoomToFit(),
268
+ children: /* @__PURE__ */ jsx(ScanSearch, { size: 20 })
269
+ }
270
+ ),
271
+ /* @__PURE__ */ jsx(
272
+ "button",
273
+ {
274
+ type: "button",
275
+ className: tldrawActionButton,
276
+ title: "Expand",
277
+ onClick: handleExpand,
278
+ children: /* @__PURE__ */ jsx(Maximize2, { size: 20 })
279
+ }
280
+ )
281
+ ] })
282
+ ]
283
+ }
284
+ );
285
+ };
286
+ class TldrawErrorBoundary extends Component {
287
+ constructor() {
288
+ super(...arguments);
289
+ __publicField(this, "state", { hasError: false });
290
+ }
291
+ static getDerivedStateFromError() {
292
+ return { hasError: true };
293
+ }
294
+ render() {
295
+ return this.state.hasError ? this.props.fallback : this.props.children;
296
+ }
297
+ }
298
+ const TldrawDisplayRenderer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
299
+ __proto__: null,
300
+ TldrawDisplayRenderer
301
+ }, Symbol.toStringTag, { value: "Module" }));
302
+ const TldrawSSRRenderer = ({ snapshot }) => {
303
+ let label = "Tldraw Whiteboard";
304
+ try {
305
+ const data = JSON.parse(snapshot);
306
+ if (data && typeof data === "object") {
307
+ const shapeCount = Object.keys(data).filter(
308
+ (k) => k.startsWith("shape:")
309
+ ).length;
310
+ if (shapeCount > 0) {
311
+ label = `Tldraw Whiteboard (${shapeCount} shapes)`;
312
+ }
313
+ }
314
+ } catch {
315
+ }
316
+ return /* @__PURE__ */ jsx(
317
+ "div",
318
+ {
319
+ className: "rich-tldraw-ssr-placeholder",
320
+ style: {
321
+ position: "relative",
322
+ width: "100%",
323
+ aspectRatio: "16 / 10",
324
+ display: "flex",
325
+ alignItems: "center",
326
+ justifyContent: "center",
327
+ backgroundColor: "var(--rich-tldraw-bg, #f5f5f5)",
328
+ borderRadius: "8px",
329
+ border: "1px solid var(--rich-tldraw-border, #e5e5e5)",
330
+ color: "var(--rich-tldraw-fg, #737373)",
331
+ fontSize: "14px"
332
+ },
333
+ "aria-label": label,
334
+ children: /* @__PURE__ */ jsx("span", { children: label })
335
+ }
336
+ );
337
+ };
338
+ class TldrawNode extends DecoratorNode {
339
+ constructor(snapshot, key) {
340
+ super(key);
341
+ __publicField(this, "__snapshot");
342
+ this.__snapshot = snapshot;
343
+ }
344
+ static getType() {
345
+ return "tldraw";
346
+ }
347
+ static clone(node) {
348
+ return new TldrawNode(node.__snapshot, node.__key);
349
+ }
350
+ createDOM(_config) {
351
+ const div = document.createElement("div");
352
+ div.className = "rich-tldraw-wrapper";
353
+ return div;
354
+ }
355
+ updateDOM() {
356
+ return false;
357
+ }
358
+ isInline() {
359
+ return false;
360
+ }
361
+ static importJSON(serializedNode) {
362
+ return $createTldrawNode(serializedNode.snapshot);
363
+ }
364
+ exportJSON() {
365
+ return {
366
+ ...super.exportJSON(),
367
+ type: "tldraw",
368
+ snapshot: this.__snapshot,
369
+ version: 1
370
+ };
371
+ }
372
+ getSnapshot() {
373
+ return this.__snapshot;
374
+ }
375
+ setSnapshot(snapshot) {
376
+ const writable = this.getWritable();
377
+ writable.__snapshot = snapshot;
378
+ }
379
+ decorate(_editor, _config) {
380
+ return createElement(TldrawSSRRenderer, {
381
+ snapshot: this.__snapshot
382
+ });
383
+ }
384
+ }
385
+ function $createTldrawNode(snapshot) {
386
+ return new TldrawNode(snapshot);
387
+ }
388
+ function $isTldrawNode(node) {
389
+ return node instanceof TldrawNode;
390
+ }
391
+ export {
392
+ $createTldrawNode as $,
393
+ TldrawDisplayRenderer$1 as A,
394
+ TldrawConfigProvider as T,
395
+ $isTldrawNode as a,
396
+ TldrawDisplayRenderer as b,
397
+ TldrawNode as c,
398
+ TldrawSSRRenderer as d,
399
+ useTldrawData as e,
400
+ tldrawEditorContainer as f,
401
+ tldrawLoading as g,
402
+ tldrawError as h,
403
+ tldrawEditOverlay as i,
404
+ tldrawEditLabel as j,
405
+ tldrawConfirmActions as k,
406
+ tldrawConfirmBtn as l,
407
+ tldrawConfirmBtnDanger as m,
408
+ tldrawConfirmBtnPrimary as n,
409
+ tldrawDialogHeader as o,
410
+ tldrawStatusDot as p,
411
+ tldrawDialogTitle as q,
412
+ tldrawDialogMeta as r,
413
+ tldrawHeaderActions as s,
414
+ tldrawFullscreenPopup as t,
415
+ useTldrawConfig as u,
416
+ tldrawActionBarSep as v,
417
+ tldrawActionBarBtn as w,
418
+ tldrawActionBarUrl as x,
419
+ tldrawHeaderClose as y,
420
+ tldrawDialogCanvas as z
421
+ };
package/dist/index.mjs CHANGED
@@ -1,396 +1,19 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { c as TldrawNode, u as useTldrawConfig, e as useTldrawData, t as tldrawFullscreenPopup, f as tldrawEditorContainer, g as tldrawLoading, h as tldrawError, i as tldrawEditOverlay, j as tldrawEditLabel, k as tldrawConfirmActions, l as tldrawConfirmBtn, m as tldrawConfirmBtnDanger, n as tldrawConfirmBtnPrimary, o as tldrawDialogHeader, p as tldrawStatusDot, q as tldrawDialogTitle, r as tldrawDialogMeta, s as tldrawHeaderActions, v as tldrawActionBarSep, w as tldrawActionBarBtn, x as tldrawActionBarUrl, y as tldrawHeaderClose, z as tldrawDialogCanvas } from "./TldrawNode-DarV5KWA.js";
5
+ import { $, a, T, b, b as b2, d, b as b3 } from "./TldrawNode-DarV5KWA.js";
6
+ import { $insertNodes, $getNodeByKey, createCommand, COMMAND_PRIORITY_EDITOR } from "lexical";
7
+ import { PenTool, Pencil, Upload, Download, Clipboard, X } from "lucide-react";
8
+ import { lazy, createElement, Suspense, useState, useRef, useEffect, useCallback } from "react";
4
9
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
- import { createContext, use, useMemo, useState, useEffect, useRef, useCallback, Component, createElement, lazy, Suspense } from "react";
6
10
  import { useColorScheme } from "@haklex/rich-editor";
7
11
  import { presentDialog, SegmentedControl } from "@haklex/rich-editor-ui";
8
12
  import { usePortalTheme } from "@haklex/rich-style-token";
9
- import { ZoomIn, ZoomOut, ScanSearch, Maximize2, X, PenTool, Pencil, Upload, Download, Clipboard } from "lucide-react";
10
- import { DecoratorNode, $insertNodes, $getNodeByKey, createCommand, COMMAND_PRIORITY_EDITOR } from "lexical";
11
13
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
12
14
  import { TLDRAW_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
13
- const TldrawConfigContext = createContext({});
14
- function TldrawConfigProvider({
15
- apiUrl,
16
- saveSnapshot,
17
- children
18
- }) {
19
- const value = useMemo(
20
- () => ({ apiUrl, saveSnapshot }),
21
- [apiUrl, saveSnapshot]
22
- );
23
- return /* @__PURE__ */ jsx(TldrawConfigContext.Provider, { value, children });
24
- }
25
- function useTldrawConfig() {
26
- return use(TldrawConfigContext);
27
- }
28
- var tldrawStaticContainer = "_1vqtdre0";
29
- var tldrawEditorContainer = "_1vqtdre1";
30
- var tldrawLoading = "_1vqtdre2";
31
- var tldrawError = "_1vqtdre4";
32
- var tldrawActionGroup = "_1vqtdre5";
33
- var tldrawActionButton = "_1vqtdre6";
34
- var tldrawFullscreenPopup = "_1vqtdre7";
35
- var tldrawDialogHeader = "_1vqtdre8";
36
- var tldrawStatusDot = "_1vqtdre9";
37
- var tldrawDialogTitle = "_1vqtdrea";
38
- var tldrawDialogMeta = "_1vqtdreb";
39
- var tldrawHeaderActions = "_1vqtdrec";
40
- var tldrawHeaderClose = "_1vqtdred";
41
- var tldrawActionBarBtn = "_1vqtdree";
42
- var tldrawActionBarSep = "_1vqtdref";
43
- var tldrawActionBarUrl = "_1vqtdreg";
44
- var tldrawDialogCanvas = "_1vqtdreh";
45
- var tldrawConfirmActions = "_1vqtdrei";
46
- var tldrawConfirmBtn = "_1vqtdrej";
47
- var tldrawConfirmBtnPrimary = "_1vqtdrek";
48
- var tldrawConfirmBtnDanger = "_1vqtdrel";
49
- var tldrawEditOverlay = "_1vqtdrem";
50
- var tldrawEditLabel = "_1vqtdren";
51
- function useTldrawData(data) {
52
- const { apiUrl } = useTldrawConfig();
53
- const parsed = useMemo(() => {
54
- if (!data) return { type: "empty" };
55
- try {
56
- const json = JSON.parse(data);
57
- if (json && typeof json === "object") {
58
- return {
59
- type: "inline",
60
- snapshot: json
61
- };
62
- }
63
- } catch {
64
- }
65
- const firstLine = data.split("\n")[0].trim();
66
- let fetchUrl2;
67
- if (firstLine.startsWith("http")) {
68
- fetchUrl2 = firstLine;
69
- } else if (firstLine.startsWith("ref:") && apiUrl) {
70
- fetchUrl2 = `${apiUrl}/objects/${firstLine.slice(4)}`;
71
- }
72
- if (fetchUrl2) {
73
- return { type: "remote", fetchUrl: fetchUrl2 };
74
- }
75
- return {
76
- type: "error",
77
- error: firstLine.startsWith("ref:") ? "Missing apiUrl for ref resolution" : "Unrecognized snapshot format"
78
- };
79
- }, [data, apiUrl]);
80
- const fetchUrl = parsed.type === "remote" ? parsed.fetchUrl : void 0;
81
- const [remoteSnapshot, setRemoteSnapshot] = useState();
82
- const [loading, setLoading] = useState(!!fetchUrl);
83
- const [error, setError] = useState("");
84
- useEffect(() => {
85
- if (!fetchUrl) return;
86
- let cancelled = false;
87
- setLoading(true);
88
- setError("");
89
- fetch(fetchUrl).then((res) => {
90
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
91
- return res.json();
92
- }).then((json) => {
93
- if (!cancelled) {
94
- setRemoteSnapshot(json);
95
- setLoading(false);
96
- }
97
- }).catch((err) => {
98
- if (!cancelled) {
99
- setError(err instanceof Error ? err.message : "Failed to load");
100
- setLoading(false);
101
- }
102
- });
103
- return () => {
104
- cancelled = true;
105
- };
106
- }, [fetchUrl]);
107
- if (parsed.type === "inline") {
108
- return { snapshot: parsed.snapshot, loading: false, error: "" };
109
- }
110
- if (parsed.type === "remote") {
111
- return { snapshot: remoteSnapshot, loading, error };
112
- }
113
- if (parsed.type === "error") {
114
- return { snapshot: void 0, loading: false, error: parsed.error };
115
- }
116
- return { snapshot: void 0, loading: false, error: "" };
117
- }
118
- const TldrawDisplayRenderer = ({
119
- snapshot
120
- }) => {
121
- const theme = useColorScheme();
122
- const containerRef = useRef(null);
123
- const [hasEnteredView, setHasEnteredView] = useState(false);
124
- useEffect(() => {
125
- if (hasEnteredView) return;
126
- const target = containerRef.current;
127
- if (!target) return;
128
- const observer = new IntersectionObserver(
129
- (entries) => {
130
- if (entries.some((e) => e.isIntersecting)) {
131
- setHasEnteredView(true);
132
- observer.disconnect();
133
- }
134
- },
135
- { rootMargin: "200px 0px", threshold: 0.1 }
136
- );
137
- observer.observe(target);
138
- return () => observer.disconnect();
139
- }, [hasEnteredView]);
140
- if (!hasEnteredView) {
141
- return /* @__PURE__ */ jsx("div", { ref: containerRef, className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawLoading, children: "Loading tldraw..." }) });
142
- }
143
- return /* @__PURE__ */ jsx("div", { ref: containerRef, children: /* @__PURE__ */ jsx(TldrawStaticCanvas, { snapshot, theme }) });
144
- };
145
- const TldrawExpandContent = ({ dismiss, TldrawComponent, data, theme }) => /* @__PURE__ */ jsxs(Fragment, { children: [
146
- /* @__PURE__ */ jsxs("div", { className: tldrawDialogHeader, children: [
147
- /* @__PURE__ */ jsx("span", { className: tldrawDialogTitle, children: "Whiteboard" }),
148
- /* @__PURE__ */ jsx("span", { className: tldrawDialogMeta, children: "tldraw" }),
149
- /* @__PURE__ */ jsx("button", { type: "button", className: tldrawHeaderClose, onClick: dismiss, children: /* @__PURE__ */ jsx(X, { size: 18 }) })
150
- ] }),
151
- /* @__PURE__ */ jsx("div", { className: tldrawDialogCanvas, children: /* @__PURE__ */ jsx(
152
- TldrawComponent,
153
- {
154
- snapshot: data,
155
- hideUi: true,
156
- onMount: (editor) => {
157
- editor.updateInstanceState({ isReadonly: true });
158
- editor.setCurrentTool("hand");
159
- editor.user.updateUserPreferences({ colorScheme: theme });
160
- setTimeout(() => editor.zoomToFit({ animate: false }), 100);
161
- }
162
- }
163
- ) })
164
- ] });
165
- const TldrawStaticCanvas = ({ snapshot, theme }) => {
166
- const {
167
- snapshot: data,
168
- loading: dataLoading,
169
- error: dataError
170
- } = useTldrawData(snapshot);
171
- const [TldrawComponent, setTldrawComponent] = useState(null);
172
- const [libLoading, setLibLoading] = useState(true);
173
- const editorRef = useRef(null);
174
- const { className: portalClassName } = usePortalTheme();
175
- useEffect(() => {
176
- import("tldraw").then((mod) => {
177
- setTldrawComponent(() => mod.Tldraw);
178
- setLibLoading(false);
179
- }).catch(() => setLibLoading(false));
180
- }, []);
181
- useEffect(() => {
182
- if (editorRef.current?.user?.updateUserPreferences) {
183
- editorRef.current.user.updateUserPreferences({ colorScheme: theme });
184
- }
185
- }, [theme]);
186
- const handleMount = useCallback(
187
- (editor) => {
188
- editorRef.current = editor;
189
- editor.updateInstanceState({ isReadonly: true });
190
- editor.setCurrentTool("hand");
191
- editor.user.updateUserPreferences({ colorScheme: theme });
192
- setTimeout(() => {
193
- editor.zoomToFit({ animate: false });
194
- }, 100);
195
- },
196
- [theme]
197
- );
198
- const handleExpand = useCallback(() => {
199
- if (!TldrawComponent || !data) return;
200
- presentDialog({
201
- content: ({ dismiss }) => /* @__PURE__ */ jsx(
202
- TldrawExpandContent,
203
- {
204
- dismiss,
205
- TldrawComponent,
206
- data,
207
- theme
208
- }
209
- ),
210
- className: tldrawFullscreenPopup,
211
- portalClassName,
212
- theme,
213
- showCloseButton: false,
214
- clickOutsideToDismiss: true
215
- });
216
- }, [TldrawComponent, data, theme, portalClassName]);
217
- const loading = dataLoading || libLoading;
218
- if (loading) {
219
- return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawLoading, children: "Loading tldraw..." }) });
220
- }
221
- if (dataError || !data) {
222
- return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawError, children: dataError || "No data" }) });
223
- }
224
- if (!TldrawComponent) {
225
- return /* @__PURE__ */ jsx("div", { className: tldrawStaticContainer, children: /* @__PURE__ */ jsx("div", { className: tldrawError, children: "Failed to load tldraw" }) });
226
- }
227
- return /* @__PURE__ */ jsxs(
228
- "div",
229
- {
230
- className: tldrawStaticContainer,
231
- "data-theme": theme,
232
- "data-color-scheme": theme,
233
- children: [
234
- /* @__PURE__ */ jsx(
235
- TldrawErrorBoundary,
236
- {
237
- fallback: /* @__PURE__ */ jsx("div", { className: tldrawError, children: "Failed to render tldraw" }),
238
- children: /* @__PURE__ */ jsx(TldrawComponent, { snapshot: data, hideUi: true, onMount: handleMount })
239
- }
240
- ),
241
- /* @__PURE__ */ jsxs("div", { className: tldrawActionGroup, children: [
242
- /* @__PURE__ */ jsx(
243
- "button",
244
- {
245
- type: "button",
246
- className: tldrawActionButton,
247
- title: "Zoom In",
248
- onClick: () => editorRef.current?.zoomIn(),
249
- children: /* @__PURE__ */ jsx(ZoomIn, { size: 20 })
250
- }
251
- ),
252
- /* @__PURE__ */ jsx(
253
- "button",
254
- {
255
- type: "button",
256
- className: tldrawActionButton,
257
- title: "Zoom Out",
258
- onClick: () => editorRef.current?.zoomOut(),
259
- children: /* @__PURE__ */ jsx(ZoomOut, { size: 20 })
260
- }
261
- ),
262
- /* @__PURE__ */ jsx(
263
- "button",
264
- {
265
- type: "button",
266
- className: tldrawActionButton,
267
- title: "Fit to Content",
268
- onClick: () => editorRef.current?.zoomToFit(),
269
- children: /* @__PURE__ */ jsx(ScanSearch, { size: 20 })
270
- }
271
- ),
272
- /* @__PURE__ */ jsx(
273
- "button",
274
- {
275
- type: "button",
276
- className: tldrawActionButton,
277
- title: "Expand",
278
- onClick: handleExpand,
279
- children: /* @__PURE__ */ jsx(Maximize2, { size: 20 })
280
- }
281
- )
282
- ] })
283
- ]
284
- }
285
- );
286
- };
287
- class TldrawErrorBoundary extends Component {
288
- constructor() {
289
- super(...arguments);
290
- __publicField(this, "state", { hasError: false });
291
- }
292
- static getDerivedStateFromError() {
293
- return { hasError: true };
294
- }
295
- render() {
296
- return this.state.hasError ? this.props.fallback : this.props.children;
297
- }
298
- }
299
- const TldrawDisplayRenderer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
300
- __proto__: null,
301
- TldrawDisplayRenderer
302
- }, Symbol.toStringTag, { value: "Module" }));
303
- const TldrawSSRRenderer = ({ snapshot }) => {
304
- let label = "Tldraw Whiteboard";
305
- try {
306
- const data = JSON.parse(snapshot);
307
- if (data && typeof data === "object") {
308
- const shapeCount = Object.keys(data).filter(
309
- (k) => k.startsWith("shape:")
310
- ).length;
311
- if (shapeCount > 0) {
312
- label = `Tldraw Whiteboard (${shapeCount} shapes)`;
313
- }
314
- }
315
- } catch {
316
- }
317
- return /* @__PURE__ */ jsx(
318
- "div",
319
- {
320
- className: "rich-tldraw-ssr-placeholder",
321
- style: {
322
- position: "relative",
323
- width: "100%",
324
- aspectRatio: "16 / 10",
325
- display: "flex",
326
- alignItems: "center",
327
- justifyContent: "center",
328
- backgroundColor: "var(--rich-tldraw-bg, #f5f5f5)",
329
- borderRadius: "8px",
330
- border: "1px solid var(--rich-tldraw-border, #e5e5e5)",
331
- color: "var(--rich-tldraw-fg, #737373)",
332
- fontSize: "14px"
333
- },
334
- "aria-label": label,
335
- children: /* @__PURE__ */ jsx("span", { children: label })
336
- }
337
- );
338
- };
339
- class TldrawNode extends DecoratorNode {
340
- constructor(snapshot, key) {
341
- super(key);
342
- __publicField(this, "__snapshot");
343
- this.__snapshot = snapshot;
344
- }
345
- static getType() {
346
- return "tldraw";
347
- }
348
- static clone(node) {
349
- return new TldrawNode(node.__snapshot, node.__key);
350
- }
351
- createDOM(_config) {
352
- const div = document.createElement("div");
353
- div.className = "rich-tldraw-wrapper";
354
- return div;
355
- }
356
- updateDOM() {
357
- return false;
358
- }
359
- isInline() {
360
- return false;
361
- }
362
- static importJSON(serializedNode) {
363
- return $createTldrawNode(serializedNode.snapshot);
364
- }
365
- exportJSON() {
366
- return {
367
- ...super.exportJSON(),
368
- type: "tldraw",
369
- snapshot: this.__snapshot,
370
- version: 1
371
- };
372
- }
373
- getSnapshot() {
374
- return this.__snapshot;
375
- }
376
- setSnapshot(snapshot) {
377
- const writable = this.getWritable();
378
- writable.__snapshot = snapshot;
379
- }
380
- decorate(_editor, _config) {
381
- return createElement(TldrawSSRRenderer, {
382
- snapshot: this.__snapshot
383
- });
384
- }
385
- }
386
- function $createTldrawNode(snapshot) {
387
- return new TldrawNode(snapshot);
388
- }
389
- function $isTldrawNode(node) {
390
- return node instanceof TldrawNode;
391
- }
392
15
  const LazyDisplayRenderer = lazy(
393
- () => Promise.resolve().then(() => TldrawDisplayRenderer$1).then((m) => ({
16
+ () => import("./TldrawNode-DarV5KWA.js").then((n) => n.A).then((m) => ({
394
17
  default: m.TldrawDisplayRenderer
395
18
  }))
396
19
  );
@@ -645,10 +268,10 @@ const TldrawEditorDialogContent = ({
645
268
  type: "application/json"
646
269
  });
647
270
  const url = URL.createObjectURL(blob);
648
- const a = document.createElement("a");
649
- a.href = url;
650
- a.download = "tldraw-snapshot.json";
651
- a.click();
271
+ const a2 = document.createElement("a");
272
+ a2.href = url;
273
+ a2.download = "tldraw-snapshot.json";
274
+ a2.click();
652
275
  URL.revokeObjectURL(url);
653
276
  }, []);
654
277
  const handleCopyJson = useCallback(() => {
@@ -887,19 +510,19 @@ function TldrawPlugin() {
887
510
  }
888
511
  export {
889
512
  $createTldrawEditNode,
890
- $createTldrawNode,
513
+ $ as $createTldrawNode,
891
514
  $isTldrawEditNode,
892
- $isTldrawNode,
515
+ a as $isTldrawNode,
893
516
  INSERT_TLDRAW_COMMAND,
894
517
  TLDRAW_BLOCK_TRANSFORMER,
895
- TldrawConfigProvider,
896
- TldrawDisplayRenderer,
518
+ T as TldrawConfigProvider,
519
+ b as TldrawDisplayRenderer,
897
520
  TldrawEditNode,
898
521
  TldrawEditRenderer,
899
522
  TldrawNode,
900
523
  TldrawPlugin,
901
- TldrawDisplayRenderer as TldrawRenderer,
902
- TldrawSSRRenderer,
903
- TldrawDisplayRenderer as TldrawStaticRenderer,
524
+ b2 as TldrawRenderer,
525
+ d as TldrawSSRRenderer,
526
+ b3 as TldrawStaticRenderer,
904
527
  useTldrawConfig
905
528
  };
@@ -0,0 +1,14 @@
1
+ import { $, a, T, b, c, b as b2, d, b as b3, u } from "./TldrawNode-DarV5KWA.js";
2
+ import { TLDRAW_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
3
+ export {
4
+ $ as $createTldrawNode,
5
+ a as $isTldrawNode,
6
+ TLDRAW_BLOCK_TRANSFORMER,
7
+ T as TldrawConfigProvider,
8
+ b as TldrawDisplayRenderer,
9
+ c as TldrawNode,
10
+ b2 as TldrawRenderer,
11
+ d as TldrawSSRRenderer,
12
+ b3 as TldrawStaticRenderer,
13
+ u as useTldrawConfig
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-ext-tldraw",
3
- "version": "0.0.41",
3
+ "version": "0.0.43",
4
4
  "description": "Tldraw whiteboard extension",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,10 +21,10 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "tldraw": "^3.15.6",
24
- "@haklex/rich-editor": "0.0.41",
25
- "@haklex/rich-editor-ui": "0.0.41",
26
- "@haklex/rich-headless": "0.0.41",
27
- "@haklex/rich-style-token": "0.0.41"
24
+ "@haklex/rich-editor-ui": "0.0.43",
25
+ "@haklex/rich-style-token": "0.0.43",
26
+ "@haklex/rich-editor": "0.0.43",
27
+ "@haklex/rich-headless": "0.0.43"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@lexical/react": "^0.41.0",