@8btc/whiteboard 0.0.20-alpha.39 → 0.0.20-alpha.40

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.
@@ -2,6 +2,36 @@ export * from '../app/adapter/maze'
2
2
  export {}
3
3
 
4
4
 
5
+ declare module "@tiptap/core" {
6
+ interface Commands<ReturnType> {
7
+ fontSize: {
8
+ setFontSize: (size: string) => ReturnType;
9
+ unsetFontSize: () => ReturnType;
10
+ };
11
+ }
12
+ }
13
+
14
+
15
+ declare module "@tiptap/core" {
16
+ interface Commands<ReturnType> {
17
+ lineHeight: {
18
+ setLineHeight: (lineHeight: string) => ReturnType;
19
+ unsetLineHeight: () => ReturnType;
20
+ };
21
+ }
22
+ }
23
+
24
+
25
+ declare module "@tiptap/core" {
26
+ interface Commands<ReturnType> {
27
+ letterSpacing: {
28
+ setLetterSpacing: (spacing: string) => ReturnType;
29
+ unsetLetterSpacing: () => ReturnType;
30
+ };
31
+ }
32
+ }
33
+
34
+
5
35
  declare module "@tiptap/core" {
6
36
  interface Commands<ReturnType> {
7
37
  nodeBackground: {
@@ -1,12 +1,12 @@
1
- import { v4 as _ } from "uuid";
2
- import { N as M } from "../const-YEx1e3IJ.js";
1
+ import { v4 as w } from "uuid";
2
+ import { N as B } from "../const-B6DtCQRi.js";
3
3
  async function N(t) {
4
- return new Promise((r, n) => {
4
+ return new Promise((n, o) => {
5
5
  const e = new Image();
6
6
  e.onload = () => {
7
- r({ width: e.naturalWidth, height: e.naturalHeight });
7
+ n({ width: e.naturalWidth, height: e.naturalHeight });
8
8
  }, e.onerror = () => {
9
- n(new Error(`Failed to load image: ${t}`));
9
+ o(new Error(`Failed to load image: ${t}`));
10
10
  }, e.src = t;
11
11
  });
12
12
  }
@@ -14,198 +14,289 @@ function v(t) {
14
14
  if (!t) return { x: 0, y: 0 };
15
15
  if ((t.getState().nodes || []).length > 0) {
16
16
  const e = t.getMainLayer();
17
- let i = 1 / 0, o = -1 / 0;
17
+ let r = 1 / 0, i = -1 / 0;
18
18
  if (e.children.forEach((s) => {
19
- if (s.visible() && s.getClassName() !== "Transformer" && s.hasName(M.selectable)) {
20
- const a = s.getAttrs(), c = a.x || 0, d = a.y || 0, l = a.height || 0;
21
- i = Math.min(i, c), o = Math.max(o, d + l);
19
+ if (s.visible() && s.getClassName() !== "Transformer" && s.hasName(B.selectable)) {
20
+ const l = s.getAttrs(), a = l.x || 0, d = l.y || 0, c = l.height || 0;
21
+ r = Math.min(r, a), i = Math.max(i, d + c);
22
22
  }
23
- }), i !== 1 / 0 && o !== -1 / 0)
24
- return { x: i, y: o };
23
+ }), r !== 1 / 0 && i !== -1 / 0)
24
+ return { x: r, y: i };
25
25
  }
26
- const n = t.getState().viewport;
26
+ const o = t.getState().viewport;
27
27
  return {
28
- x: n.x,
29
- y: n.y
28
+ x: o.x,
29
+ y: o.y
30
30
  };
31
31
  }
32
- async function E(t, r, n, e) {
32
+ async function S(t, n, o, e) {
33
33
  if (!t) return;
34
- const i = Array.isArray(r) ? r : [r];
35
- if (i.length === 0) return;
36
- const o = e?.spacing ?? 20, s = e?.scrollToView ?? !0, a = e?.direction ?? "horizontal", c = e?.reuseExisting ?? !0, d = /* @__PURE__ */ new Map();
37
- c && (t.getState().nodes || []).forEach((m) => {
34
+ const r = Array.isArray(n) ? n : [n];
35
+ if (r.length === 0) return;
36
+ const i = e?.spacing ?? 20, s = e?.scrollToView ?? !0, l = e?.direction ?? "horizontal", a = e?.reuseExisting ?? !0, d = /* @__PURE__ */ new Map();
37
+ a && (t.getState().nodes || []).forEach((m) => {
38
38
  m.$_type === "image" && m.$_imageUrl && d.set(m.$_imageUrl, m.id);
39
39
  });
40
- const l = await Promise.all(i.map((f) => N(f))), h = [], u = [];
41
- let g = n.x, y = n.y;
42
- return i.forEach((f, m) => {
43
- if (c && d.has(f)) {
44
- const w = d.get(f);
45
- u.push(w);
40
+ const c = await Promise.all(r.map((f) => N(f))), h = [], g = [];
41
+ let u = o.x, y = o.y;
42
+ return r.forEach((f, m) => {
43
+ if (a && d.has(f)) {
44
+ const _ = d.get(f);
45
+ g.push(_);
46
46
  return;
47
47
  }
48
- const { width: $, height: x } = l[m], I = _();
48
+ const { width: x, height: $ } = c[m], I = w();
49
49
  h.push({
50
50
  id: I,
51
51
  $_type: "image",
52
- x: g,
52
+ x: u,
53
53
  y,
54
- width: $,
55
- height: x,
54
+ width: x,
55
+ height: $,
56
56
  $_imageUrl: f
57
- }), u.push(I), a === "horizontal" ? g += $ + o : y += x + o;
58
- }), h.length > 0 && t.createNodes(h, !0), s && t.scrollToContent({ scale: !1, nodeIds: u }), u;
57
+ }), g.push(I), l === "horizontal" ? u += x + i : y += $ + i;
58
+ }), h.length > 0 && t.createNodes(h, !0), s && t.scrollToContent({ scale: !1, nodeIds: g }), g;
59
59
  }
60
- async function B(t, r) {
60
+ async function H(t, n) {
61
61
  if (!t) return;
62
- const n = v(t);
63
- return E(t, r, {
64
- x: n.x,
65
- y: n.y + 20
62
+ const o = v(t);
63
+ return S(t, n, {
64
+ x: o.x,
65
+ y: o.y + 20
66
66
  });
67
67
  }
68
- function L(t, r) {
68
+ function L(t, n) {
69
69
  if (!t) return;
70
- const n = t.getState().selectedNodeIds || [];
71
- if (n.length === 0) return;
72
- let e = 1 / 0, i = 1 / 0, o = -1 / 0, s = -1 / 0;
73
- if (t.getMainLayer().children.forEach((l) => {
74
- if (l.visible() && l.getClassName() !== "Transformer" && n.includes(l.id())) {
75
- const h = l.getAttrs(), u = h.x || 0, g = h.y || 0, y = h.width || 0, f = h.height || 0;
76
- e = Math.min(e, u), i = Math.min(i, g), o = Math.max(o, u + y), s = Math.max(s, g + f);
70
+ const o = t.getState().selectedNodeIds || [];
71
+ if (o.length === 0) return;
72
+ let e = 1 / 0, r = 1 / 0, i = -1 / 0, s = -1 / 0;
73
+ if (t.getMainLayer().children.forEach((c) => {
74
+ if (c.visible() && c.getClassName() !== "Transformer" && o.includes(c.id())) {
75
+ const h = c.getAttrs(), g = h.x || 0, u = h.y || 0, y = h.width || 0, f = h.height || 0;
76
+ e = Math.min(e, g), r = Math.min(r, u), i = Math.max(i, g + y), s = Math.max(s, u + f);
77
77
  }
78
- }), e === 1 / 0 || i === 1 / 0 || o === -1 / 0 || s === -1 / 0)
78
+ }), e === 1 / 0 || r === 1 / 0 || i === -1 / 0 || s === -1 / 0)
79
79
  return;
80
- const c = {
81
- x: o + 20,
82
- y: i,
83
- width: o - e,
84
- height: s - i
80
+ const a = {
81
+ x: i + 20,
82
+ y: r,
83
+ width: i - e,
84
+ height: s - r
85
85
  }, d = {
86
- id: _(),
86
+ id: w(),
87
87
  $_type: "html",
88
88
  $_actualType: "loading",
89
- x: c.x,
90
- y: c.y,
91
- width: c.width,
92
- height: c.height,
93
- $_imageUrl: r,
89
+ x: a.x,
90
+ y: a.y,
91
+ width: a.width,
92
+ height: a.height,
93
+ $_imageUrl: n,
94
94
  // 示例 loading 图片 URL
95
95
  $_htmlContent: `
96
- <img alt="loading" src="${r}" style="width: 100%; height: 100%; object-fit: contain;" />
96
+ <img alt="loading" src="${n}" style="width: 100%; height: 100%; object-fit: contain;" />
97
97
  `
98
98
  };
99
99
  return t.createNodes([d], !0), d.id;
100
100
  }
101
- function X(t, r, n) {
101
+ function R(t, n, o) {
102
102
  if (!t) return;
103
- const e = t.getCanvasNodeById(r);
103
+ const e = t.getCanvasNodeById(n);
104
104
  if (!e) return;
105
- const i = e.getConfig();
106
- if (i.$_type !== "html") return;
107
- const o = Array.isArray(n) ? n : [n];
108
- if (o.length === 0) return;
109
- const s = i.x, a = i.y;
110
- E(t, o, { x: s, y: a }, { scrollToView: !1 }), t.deleteNodes([r]);
105
+ const r = e.getConfig();
106
+ if (r.$_type !== "html") return;
107
+ const i = Array.isArray(o) ? o : [o];
108
+ if (i.length === 0) return;
109
+ const s = r.x, l = r.y;
110
+ S(t, i, { x: s, y: l }, { scrollToView: !1 }), t.deleteNodes([n]);
111
111
  }
112
- async function p(t, r, n, e, i) {
112
+ async function T(t, n, o, e, r) {
113
113
  if (!t) return;
114
- const o = i?.scrollToView ?? !0;
115
- if (i?.reuseExisting ?? !0) {
114
+ const i = r?.scrollToView ?? !0;
115
+ if (r?.reuseExisting ?? !0) {
116
116
  const d = t.getState().nodes || [];
117
- for (const l of d)
118
- if (l.$_type === "video" && l.$_videoUrl === r)
119
- return o && t.scrollToContent({ scale: !1, nodeIds: [l.id] }), l.id;
117
+ for (const c of d)
118
+ if (c.$_type === "video" && c.$_videoUrl === n)
119
+ return i && t.scrollToContent({ scale: !1, nodeIds: [c.id] }), c.id;
120
120
  }
121
- let a = { width: 320, height: 180 };
121
+ let l = { width: 320, height: 180 };
122
122
  try {
123
- a = await N(n);
123
+ l = await N(o);
124
124
  } catch (d) {
125
125
  console.warn("Failed to load cover image, using default size:", d);
126
126
  }
127
- const c = {
128
- id: _(),
127
+ const a = {
128
+ id: w(),
129
129
  $_type: "video",
130
130
  x: e.x,
131
131
  y: e.y,
132
- width: a.width,
132
+ width: l.width,
133
133
  // 使用封面图片的宽度
134
- height: a.height,
134
+ height: l.height,
135
135
  // 使用封面图片的高度
136
- $_videoUrl: r,
137
- $_coverUrl: n
136
+ $_videoUrl: n,
137
+ $_coverUrl: o
138
138
  };
139
- return t.createNodes([c], !0), o && t.scrollToContent({ scale: !1, nodeIds: [c.id] }), c.id;
139
+ return t.createNodes([a], !0), i && t.scrollToContent({ scale: !1, nodeIds: [a.id] }), a.id;
140
140
  }
141
- async function Y(t, r, n) {
141
+ async function k(t, n, o) {
142
142
  if (!t) return;
143
143
  const e = v(t);
144
- return p(t, r, n, {
144
+ return T(t, n, o, {
145
145
  x: e.x,
146
146
  y: e.y + 20
147
147
  });
148
148
  }
149
- async function V(t, r) {
149
+ async function F(t, n) {
150
150
  if (!t) return null;
151
- const n = t.getCanvasNodeById(r);
152
- if (!n) return null;
153
- const e = n.getConfig();
151
+ const o = t.getCanvasNodeById(n);
152
+ if (!o) return null;
153
+ const e = o.getConfig();
154
154
  if (e.$_type !== "image-marker" || !e.$_relativeBox)
155
155
  return null;
156
- const i = e.$_parentId;
157
- if (!i) return null;
158
- const o = t.getNodeConfigById(i);
159
- if (!o || o.$_type !== "image" || !o.$_imageUrl) return null;
160
- const { start: s, end: a } = e.$_relativeBox, c = s.ratioX, d = s.ratioY, l = a.ratioX - s.ratioX, h = a.ratioY - s.ratioY;
161
- return new Promise((u) => {
162
- const g = new Image();
163
- g.crossOrigin = "anonymous", g.onload = () => {
164
- const y = g.naturalWidth, f = g.naturalHeight, m = c * y, $ = d * f, x = l * y, I = h * f, w = document.createElement("canvas");
165
- w.width = x, w.height = I;
166
- const C = w.getContext("2d");
167
- if (!C) {
168
- u(null);
156
+ const r = e.$_parentId;
157
+ if (!r) return null;
158
+ const i = t.getNodeConfigById(r);
159
+ if (!i || i.$_type !== "image" || !i.$_imageUrl) return null;
160
+ const { start: s, end: l } = e.$_relativeBox, a = s.ratioX, d = s.ratioY, c = l.ratioX - s.ratioX, h = l.ratioY - s.ratioY;
161
+ return new Promise((g) => {
162
+ const u = new Image();
163
+ u.crossOrigin = "anonymous", u.onload = () => {
164
+ const y = u.naturalWidth, f = u.naturalHeight, m = a * y, x = d * f, $ = c * y, I = h * f, _ = document.createElement("canvas");
165
+ _.width = $, _.height = I;
166
+ const p = _.getContext("2d");
167
+ if (!p) {
168
+ g(null);
169
169
  return;
170
170
  }
171
- C.drawImage(
172
- g,
171
+ p.drawImage(
172
+ u,
173
173
  m,
174
- $,
175
174
  x,
175
+ $,
176
176
  I,
177
177
  0,
178
178
  0,
179
- x,
179
+ $,
180
180
  I
181
181
  );
182
- const S = w.toDataURL("image/png");
183
- u(S);
184
- }, g.onerror = () => {
185
- console.error("Failed to load image:", o.$_imageUrl), u(null);
186
- }, g.src = o.$_imageUrl;
182
+ const E = _.toDataURL("image/png");
183
+ g(E);
184
+ }, u.onerror = () => {
185
+ console.error("Failed to load image:", i.$_imageUrl), g(null);
186
+ }, u.src = i.$_imageUrl;
187
187
  });
188
188
  }
189
- function z(t, r) {
189
+ function W(t, n) {
190
190
  if (!t) return null;
191
- const n = t.getState().selectedNodeIds || [];
192
- if (n.length === 0) return null;
193
- if (n.length === 1) {
194
- const e = t.getCanvasNodeById(n[0]);
191
+ const o = t.getState().selectedNodeIds || [];
192
+ if (o.length === 0) return null;
193
+ if (o.length === 1) {
194
+ const e = t.getCanvasNodeById(o[0]);
195
195
  if (!e) return null;
196
196
  if (e.getConfig().$_type === "image")
197
197
  return e.getConfig().$_imageUrl || null;
198
198
  }
199
- return t.exportSelectionAsImage(r);
199
+ return t.exportSelectionAsImage(n);
200
+ }
201
+ function U(t) {
202
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
203
+ }
204
+ function M(t, n, o, e, r, i, s) {
205
+ return `<p><span style="${[
206
+ `font-family: ${n}`,
207
+ `font-size: ${o}px`,
208
+ `letter-spacing: ${e}px`,
209
+ `font-weight: ${r}`,
210
+ `color: ${i}`,
211
+ `line-height: ${s}`
212
+ ].join("; ")}">${U(t)}</span></p>`;
213
+ }
214
+ const C = /* @__PURE__ */ new Set();
215
+ function X(t, n, o) {
216
+ const e = `${n}-${o || "all"}`;
217
+ if (C.has(e)) return;
218
+ C.add(e);
219
+ const r = o ? `:wght@${o}` : "", i = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(t)}${r}&display=swap`, s = document.createElement("link");
220
+ s.rel = "stylesheet", s.href = i, s.onerror = () => {
221
+ const l = `https://cdn.jsdelivr.net/fontsource/fonts/${n}@latest/index.css`, a = document.createElement("link");
222
+ a.rel = "stylesheet", a.href = l, document.head.appendChild(a);
223
+ }, document.head.appendChild(s);
224
+ }
225
+ function b(t, n) {
226
+ if (!t) return;
227
+ X(n.fontFamily, n.fontId, n.fontWeight);
228
+ const o = w(), e = M(
229
+ n.text,
230
+ n.fontFamily,
231
+ n.fontSize,
232
+ n.letterSpacing,
233
+ n.fontWeight,
234
+ n.fontColor,
235
+ n.lineHeight
236
+ ), r = {
237
+ id: o,
238
+ $_type: "rich-text",
239
+ x: n.position.x,
240
+ y: n.position.y,
241
+ $_htmlContent: e,
242
+ scaleWhenCreate: 1,
243
+ image: void 0
244
+ };
245
+ return t.createNodes([r], !0), o;
246
+ }
247
+ function z(t, n, o) {
248
+ t && t.updateNodes([n], { $_imageUrl: o });
249
+ }
250
+ async function P(t, n) {
251
+ if (!t) return null;
252
+ const o = t.getCanvasNodeById(n);
253
+ if (!o) return null;
254
+ const e = o.getConfig();
255
+ if (e.$_type !== "font-replace" || !e.$_relativeBox) return null;
256
+ const r = e.$_parentId;
257
+ if (!r) return null;
258
+ const i = t.getNodeConfigById(r);
259
+ if (!i || i.$_type !== "image" || !i.$_imageUrl)
260
+ return null;
261
+ const { start: s, end: l } = e.$_relativeBox, a = await new Promise((d) => {
262
+ const c = new window.Image();
263
+ c.crossOrigin = "anonymous", c.onload = () => {
264
+ const h = c.naturalWidth, g = c.naturalHeight, u = s.ratioX * h, y = s.ratioY * g, f = (l.ratioX - s.ratioX) * h, m = (l.ratioY - s.ratioY) * g, x = document.createElement("canvas");
265
+ x.width = f, x.height = m;
266
+ const $ = x.getContext("2d");
267
+ if (!$) {
268
+ d(null);
269
+ return;
270
+ }
271
+ $.drawImage(c, u, y, f, m, 0, 0, f, m), d({
272
+ regionImage: x.toDataURL("image/png"),
273
+ naturalWidth: h,
274
+ naturalHeight: g
275
+ });
276
+ }, c.onerror = () => d(null), c.src = i.$_imageUrl;
277
+ });
278
+ return a ? {
279
+ region_image: a.regionImage,
280
+ edit_urls: [i.$_imageUrl],
281
+ prompt: "去掉选区内的文字,保持背景完整",
282
+ relative_box: { start: s, end: l },
283
+ image_node_id: r,
284
+ font_replace_node_id: n,
285
+ natural_width: a.naturalWidth,
286
+ natural_height: a.naturalHeight
287
+ } : null;
200
288
  }
201
289
  export {
202
290
  v as calculateBottomLeftOfCanvasContent,
203
- V as exportMarkedRegion,
204
- z as exportSelectionAsImage,
205
- B as insertImageBesideContent,
206
- E as insertImagesAtPosition,
291
+ b as createRichTextFromFontReplace,
292
+ P as exportFontReplaceRegion,
293
+ F as exportMarkedRegion,
294
+ W as exportSelectionAsImage,
295
+ H as insertImageBesideContent,
296
+ S as insertImagesAtPosition,
207
297
  L as insertLoadingImageBesideSelection,
208
- p as insertVideoAtPosition,
209
- Y as insertVideoBesideContent,
210
- X as replaceLoadingImageNode
298
+ T as insertVideoAtPosition,
299
+ k as insertVideoBesideContent,
300
+ z as replaceImageUrl,
301
+ R as replaceLoadingImageNode
211
302
  };
@@ -13,7 +13,8 @@ const i = {
13
13
  polygon: "polygon_intrinsic",
14
14
  arrow: "arrow_intrinsic",
15
15
  brush: "brush_intrinsic",
16
- imageBrush: "image_brush_intrinsic"
16
+ imageBrush: "image_brush_intrinsic",
17
+ fontReplace: "font_replace_intrinsic"
17
18
  }, n = {
18
19
  CORNER_RADIUS: 6,
19
20
  MIN_SIZE: 10