@8btc/whiteboard 0.0.18 → 0.0.19-beta.1

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/index.js CHANGED
@@ -1,595 +1,518 @@
1
- var __defProp = Object.defineProperty;
2
- var __typeError = (msg) => {
3
- throw TypeError(msg);
1
+ var xe = Object.defineProperty;
2
+ var jt = (o) => {
3
+ throw TypeError(o);
4
4
  };
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
8
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
9
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
- var _core, _stage, _viewport, _handleWheel, _handlePointerDown, _handlePointerMove, _handlePointerUp, _handleDragStart, _handleDragMove, _handleDragEnd, _CanvasStage_instances, setupEventListeners_fn, _core2, _transformer, _handleTransformStart, _handleTransform, _handleTransformEnd, _handleDragStart2, _handleDragMove2, _handleDragEnd2, _CanvasTransformer_instances, setupEventListeners_fn2, _toolTypeChangeHandler, _RectNode_instances, setupEventHandlers_fn, _ImageNode_instances, loadImage_fn, _toolTypeChangeHandler2, setupEventHandlers_fn2, syncImageMarkers_fn, syncImageMarkersToState_fn, _rect, _markerGroup, _circle, _text, _handleViewportChange, _handleNodesSelected, _ImageMarkerNode_instances, changeVisulStyle_fn, setupEventHandlers_fn3, _canvasStage, _mainLayer, _canvasTransformer, _draftNode, _container, _handleKeyDown, _CanvasCore_instances, setupKeyboardEvents_fn;
13
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
14
- import { useState, useEffect, useRef } from "react";
15
- import Konva from "konva";
16
- import mitt from "mitt";
17
- import { v4 } from "uuid";
18
- import { Slot } from "@radix-ui/react-slot";
19
- import { cva } from "class-variance-authority";
20
- import { clsx } from "clsx";
21
- import { twMerge } from "tailwind-merge";
22
- import { Minus, Plus, Undo2, Redo2 } from "lucide-react";
23
- class CanvasStage {
24
- constructor(core, config) {
25
- __privateAdd(this, _CanvasStage_instances);
26
- __privateAdd(this, _core);
27
- __privateAdd(this, _stage);
28
- __privateAdd(this, _viewport, { x: 0, y: 0, scale: 1 });
5
+ var we = (o, s, t) => s in o ? xe(o, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[s] = t;
6
+ var z = (o, s, t) => we(o, typeof s != "symbol" ? s + "" : s, t), Ot = (o, s, t) => s.has(o) || jt("Cannot " + t);
7
+ var e = (o, s, t) => (Ot(o, s, "read from private field"), t ? t.call(o) : s.get(o)), d = (o, s, t) => s.has(o) ? jt("Cannot add the same private member more than once") : s instanceof WeakSet ? s.add(o) : s.set(o, t), l = (o, s, t, i) => (Ot(o, s, "write to private field"), i ? i.call(o, t) : s.set(o, t), t), b = (o, s, t) => (Ot(o, s, "access private method"), t);
8
+ import { jsxs as it, jsx as N, Fragment as ve } from "react/jsx-runtime";
9
+ import { useState as ht, useEffect as Wt, useRef as Se } from "react";
10
+ import D from "konva";
11
+ import Ne from "mitt";
12
+ import { R as w, N as A, I as tt } from "./const-Das6lRi-.js";
13
+ import { v4 as pt } from "uuid";
14
+ import { Slot as _e } from "@radix-ui/react-slot";
15
+ import { cva as be } from "class-variance-authority";
16
+ import { clsx as Me } from "clsx";
17
+ import { twMerge as Ie } from "tailwind-merge";
18
+ import { Minus as Ce, Plus as Ee, Undo2 as ke, Redo2 as Te } from "lucide-react";
19
+ var y, p, V, yt, xt, wt, vt, St, Nt, _t, bt, ie;
20
+ class $e {
21
+ constructor(s, t) {
22
+ d(this, bt);
23
+ d(this, y);
24
+ d(this, p);
25
+ d(this, V, { x: 0, y: 0, scale: 1 });
29
26
  /**
30
27
  * 处理滚轮缩放和平移
31
28
  */
32
- __privateAdd(this, _handleWheel, (e) => {
33
- e.evt.preventDefault();
34
- const stage = __privateGet(this, _stage);
35
- const pointer = stage.getPointerPosition();
36
- if (!pointer) return;
37
- if (e.evt.ctrlKey) {
38
- const oldScale = __privateGet(this, _viewport).scale;
39
- const mousePointTo = {
40
- x: (pointer.x - __privateGet(this, _viewport).x) / oldScale,
41
- y: (pointer.y - __privateGet(this, _viewport).y) / oldScale
42
- };
43
- const scaleBy = 1.01;
44
- const direction = e.evt.deltaY > 0 ? -1 : 1;
45
- const steps = Math.min(Math.abs(e.evt.deltaY), 10);
46
- let newScale = oldScale;
47
- for (let i = 0; i < steps; i++) {
48
- newScale = direction > 0 ? newScale * scaleBy : newScale / scaleBy;
29
+ d(this, yt, (s) => {
30
+ s.evt.preventDefault();
31
+ const i = e(this, p).getPointerPosition();
32
+ if (i)
33
+ if (s.evt.ctrlKey) {
34
+ const n = e(this, V).scale, r = {
35
+ x: (i.x - e(this, V).x) / n,
36
+ y: (i.y - e(this, V).y) / n
37
+ }, a = 1.01, h = s.evt.deltaY > 0 ? -1 : 1, c = Math.min(Math.abs(s.evt.deltaY), 10);
38
+ let g = n;
39
+ for (let u = 0; u < c; u++)
40
+ g = h > 0 ? g * a : g / a;
41
+ const m = Math.max(0.1, Math.min(5, g)), f = {
42
+ x: i.x - r.x * m,
43
+ y: i.y - r.y * m
44
+ };
45
+ e(this, y)._updateViewport({ x: f.x, y: f.y, scale: m });
46
+ } else {
47
+ const n = s.evt.shiftKey ? s.evt.deltaY : s.evt.deltaX, r = s.evt.shiftKey ? 0 : s.evt.deltaY;
48
+ e(this, y)._updateViewport({
49
+ x: e(this, V).x - n,
50
+ y: e(this, V).y - r
51
+ });
49
52
  }
50
- const scale = Math.max(0.1, Math.min(5, newScale));
51
- const newPos = {
52
- x: pointer.x - mousePointTo.x * scale,
53
- y: pointer.y - mousePointTo.y * scale
54
- };
55
- __privateGet(this, _core).updateViewport({ x: newPos.x, y: newPos.y, scale });
56
- } else {
57
- const deltaX = e.evt.shiftKey ? e.evt.deltaY : e.evt.deltaX;
58
- const deltaY = e.evt.shiftKey ? 0 : e.evt.deltaY;
59
- __privateGet(this, _core).updateViewport({
60
- x: __privateGet(this, _viewport).x - deltaX,
61
- y: __privateGet(this, _viewport).y - deltaY
62
- });
63
- }
64
53
  });
65
- __privateAdd(this, _handlePointerDown, (event) => {
66
- const toolType = __privateGet(this, _core).getState().toolType;
67
- if (event.evt.button !== 0 || toolType === "hand") {
54
+ d(this, xt, (s) => {
55
+ const t = e(this, y).getState().toolType;
56
+ if (s.evt.button !== 0 || t === "hand")
68
57
  return;
69
- }
70
- const clickedOnEmpty = event.target === __privateGet(this, _stage);
71
- const pointerPos = __privateGet(this, _stage).getRelativePointerPosition();
72
- if (toolType === "select" && !clickedOnEmpty) {
73
- const nodeId = event.target.id();
74
- if (nodeId) {
75
- __privateGet(this, _core).selectNode(nodeId, event.evt.shiftKey);
58
+ const i = e(this, p).getRelativePointerPosition();
59
+ if (e(this, y)._setDrawingPosition(i || { x: 0, y: 0 }), t === "select")
60
+ if (s.target === e(this, p)) {
61
+ e(this, y)._selectNodes(), e(this, y)._createSelectRect();
62
+ return;
63
+ } else {
64
+ const r = s.target.id();
65
+ r && e(this, y)._selectNodes([r], s.evt.shiftKey);
66
+ return;
76
67
  }
77
- return;
78
- }
79
- if (toolType === "rectangle" && pointerPos) {
80
- __privateGet(this, _core).createDraftNode(toolType, pointerPos);
81
- }
82
- if (toolType === "image-marker" && pointerPos) {
83
- const imageShape = __privateGet(this, _core).findImageAtPosition(pointerPos);
84
- if (imageShape) {
85
- const width = imageShape.width();
86
- const height = imageShape.height();
87
- if (width && height) {
88
- const imageBounds = {
89
- x: imageShape.x(),
90
- y: imageShape.y(),
91
- width,
92
- height
68
+ if (t === "rectangle" && i && e(this, y)._createDraftNode(t), t === "image-marker" && i) {
69
+ const n = e(this, y)._findImageAtPosition(i);
70
+ if (n) {
71
+ const r = n.width(), a = n.height();
72
+ if (r && a) {
73
+ const h = {
74
+ x: n.x(),
75
+ y: n.y(),
76
+ width: r,
77
+ height: a
93
78
  };
94
- __privateGet(this, _core).createDraftNode(toolType, pointerPos, {
95
- parent: imageShape.id(),
96
- bounds: imageBounds,
97
- startPosition: pointerPos
79
+ e(this, y)._createDraftNode(t, {
80
+ $_parentId: n.id(),
81
+ $_bounds: h
98
82
  });
99
83
  }
100
84
  }
101
85
  }
102
- __privateGet(this, _core).selectNode();
86
+ e(this, y)._selectNodes();
103
87
  });
104
- __privateAdd(this, _handlePointerMove, () => {
105
- const toolType = __privateGet(this, _core).getState().toolType;
106
- if (toolType === "hand") {
88
+ d(this, wt, () => {
89
+ const s = e(this, y).getState().toolType;
90
+ if (s === "hand")
107
91
  return;
108
- }
109
- const pointerPos = __privateGet(this, _stage).getRelativePointerPosition();
110
- if ((toolType === "rectangle" || toolType === "image-marker") && pointerPos) {
111
- __privateGet(this, _core).updateDraftNode(pointerPos);
112
- }
113
- });
114
- __privateAdd(this, _handlePointerUp, () => {
115
- const toolType = __privateGet(this, _core).getState().toolType;
116
- if (toolType === "hand") {
92
+ const t = e(this, p).getRelativePointerPosition();
93
+ if (e(this, y)._updateDrawingPosition(t || { x: 0, y: 0 }), s === "select") {
94
+ e(this, y)._updateSelectRect();
117
95
  return;
118
96
  }
119
- if (toolType === "rectangle" || toolType === "image-marker") {
120
- __privateGet(this, _core).finalizeDraftNode();
121
- }
97
+ (s === "rectangle" || s === "image-marker") && e(this, y)._updateDraftNode();
122
98
  });
123
- __privateAdd(this, _handleDragStart, (event) => {
124
- if (event.target !== __privateGet(this, _stage)) {
125
- return;
126
- }
127
- const toolType = __privateGet(this, _core).getState().toolType;
128
- if (toolType === "hand") {
129
- this.setCursor("grabbing");
130
- } else if (toolType === "select") {
131
- this.setCursor("all-scroll");
99
+ d(this, vt, () => {
100
+ const s = e(this, y).getState().toolType;
101
+ if (s !== "hand") {
102
+ if (s === "select") {
103
+ e(this, y)._finalizeSelectRect();
104
+ return;
105
+ }
106
+ (s === "rectangle" || s === "image-marker") && e(this, y)._finalizeDraftNode();
132
107
  }
133
108
  });
134
- __privateAdd(this, _handleDragMove, (event) => {
135
- if (event.target !== __privateGet(this, _stage)) {
109
+ d(this, St, (s) => {
110
+ if (s.target !== e(this, p))
136
111
  return;
137
- }
138
- __privateGet(this, _core).updateViewport({
139
- x: __privateGet(this, _stage).x(),
140
- y: __privateGet(this, _stage).y()
141
- });
112
+ const t = e(this, y).getState().toolType;
113
+ t === "hand" ? this.setCursor("grabbing") : t === "select" && this.setCursor("all-scroll");
142
114
  });
143
- __privateAdd(this, _handleDragEnd, (event) => {
144
- if (event.target !== __privateGet(this, _stage)) {
145
- return;
146
- }
147
- __privateGet(this, _core).updateViewport({
148
- x: __privateGet(this, _stage).x(),
149
- y: __privateGet(this, _stage).y()
115
+ d(this, Nt, (s) => {
116
+ s.target === e(this, p) && e(this, y)._updateViewport({
117
+ x: e(this, p).x(),
118
+ y: e(this, p).y()
150
119
  });
151
- this.resetCursor();
152
120
  });
153
- __privateSet(this, _core, core);
154
- __privateSet(this, _stage, new Konva.Stage({
155
- container: config.container,
156
- width: config.width,
157
- height: config.height,
121
+ d(this, _t, (s) => {
122
+ s.target === e(this, p) && (e(this, y)._updateViewport({
123
+ x: e(this, p).x(),
124
+ y: e(this, p).y()
125
+ }), this.resetCursor());
126
+ });
127
+ l(this, y, s), l(this, p, new D.Stage({
128
+ container: t.container,
129
+ width: t.width,
130
+ height: t.height,
158
131
  x: 0,
159
132
  y: 0,
160
133
  scaleX: 1,
161
134
  scaleY: 1,
162
- draggable: config.draggable ?? false,
163
- className: config.className
164
- }));
165
- __privateMethod(this, _CanvasStage_instances, setupEventListeners_fn).call(this);
135
+ draggable: t.draggable ?? !1,
136
+ className: t.className
137
+ })), b(this, bt, ie).call(this);
166
138
  }
167
139
  /**
168
140
  * 获取原生 Konva.Stage 实例
169
141
  */
170
142
  getStage() {
171
- return __privateGet(this, _stage);
143
+ return e(this, p);
172
144
  }
173
145
  /**
174
146
  * 获取当前视口状态
175
147
  */
176
148
  getViewport() {
177
- return { ...__privateGet(this, _viewport) };
149
+ return { ...e(this, V) };
178
150
  }
179
151
  /**
180
152
  * 设置视口(包括位置、缩放和尺寸)
181
153
  */
182
- setViewport(viewport) {
183
- const newViewport = { ...__privateGet(this, _viewport), ...viewport };
184
- __privateSet(this, _viewport, newViewport);
185
- if (viewport.x !== void 0) {
186
- __privateGet(this, _stage).x(viewport.x);
187
- }
188
- if (viewport.y !== void 0) {
189
- __privateGet(this, _stage).y(viewport.y);
190
- }
191
- if (viewport.scale !== void 0) {
192
- __privateGet(this, _stage).scaleX(viewport.scale);
193
- __privateGet(this, _stage).scaleY(viewport.scale);
194
- }
195
- if (viewport.width !== void 0) {
196
- __privateGet(this, _stage).width(viewport.width);
197
- }
198
- if (viewport.height !== void 0) {
199
- __privateGet(this, _stage).height(viewport.height);
200
- }
154
+ setViewport(s) {
155
+ const t = { ...e(this, V), ...s };
156
+ l(this, V, t), s.x !== void 0 && e(this, p).x(s.x), s.y !== void 0 && e(this, p).y(s.y), s.scale !== void 0 && (e(this, p).scaleX(s.scale), e(this, p).scaleY(s.scale));
201
157
  }
202
158
  /**
203
159
  * 设置是否可拖拽
204
160
  */
205
- setDraggable(draggable) {
206
- __privateGet(this, _stage).draggable(draggable);
161
+ setDraggable(s) {
162
+ e(this, p).draggable(s);
207
163
  }
208
164
  /**
209
165
  * 设置光标样式
210
166
  */
211
- setCursor(cursor) {
212
- const container = __privateGet(this, _stage).container();
213
- container.style.cursor = cursor;
167
+ setCursor(s) {
168
+ const t = e(this, p).container();
169
+ t.style.cursor = s;
214
170
  }
215
171
  /**
216
172
  * 重置光标样式
217
173
  */
218
174
  resetCursor() {
219
- const container = __privateGet(this, _stage).container();
220
- const toolType = __privateGet(this, _core).getState().toolType;
221
- if (toolType === "hand") {
222
- container.style.cursor = "grab";
175
+ const s = e(this, p).container();
176
+ if (e(this, y).getState().toolType === "hand") {
177
+ s.style.cursor = "grab";
223
178
  return;
224
179
  }
225
- container.style.cursor = "default";
180
+ s.style.cursor = "default";
226
181
  }
227
182
  /**
228
183
  * 销毁 Stage
229
184
  */
230
185
  destroy() {
231
- __privateGet(this, _stage).destroy();
186
+ e(this, p).destroy();
232
187
  }
233
188
  }
234
- _core = new WeakMap();
235
- _stage = new WeakMap();
236
- _viewport = new WeakMap();
237
- _handleWheel = new WeakMap();
238
- _handlePointerDown = new WeakMap();
239
- _handlePointerMove = new WeakMap();
240
- _handlePointerUp = new WeakMap();
241
- _handleDragStart = new WeakMap();
242
- _handleDragMove = new WeakMap();
243
- _handleDragEnd = new WeakMap();
244
- _CanvasStage_instances = new WeakSet();
245
- /**
189
+ y = new WeakMap(), p = new WeakMap(), V = new WeakMap(), yt = new WeakMap(), xt = new WeakMap(), wt = new WeakMap(), vt = new WeakMap(), St = new WeakMap(), Nt = new WeakMap(), _t = new WeakMap(), bt = new WeakSet(), /**
246
190
  * 设置事件监听器
247
191
  */
248
- setupEventListeners_fn = function() {
249
- __privateGet(this, _stage).on("wheel", __privateGet(this, _handleWheel));
250
- __privateGet(this, _stage).on("pointerdown", __privateGet(this, _handlePointerDown));
251
- __privateGet(this, _stage).on("pointermove", __privateGet(this, _handlePointerMove));
252
- __privateGet(this, _stage).on("pointerup", __privateGet(this, _handlePointerUp));
253
- __privateGet(this, _stage).on("dragstart", __privateGet(this, _handleDragStart));
254
- __privateGet(this, _stage).on("dragmove", __privateGet(this, _handleDragMove));
255
- __privateGet(this, _stage).on("dragend", __privateGet(this, _handleDragEnd));
192
+ ie = function() {
193
+ e(this, p).on("wheel", e(this, yt)), e(this, p).on("pointerdown", e(this, xt)), e(this, p).on("pointermove", e(this, wt)), e(this, p).on("pointerup", e(this, vt)), e(this, p).on("dragstart", e(this, St)), e(this, p).on("dragmove", e(this, Nt)), e(this, p).on("dragend", e(this, _t));
256
194
  };
257
- class CanvasTransformer {
258
- constructor(core, config) {
259
- __privateAdd(this, _CanvasTransformer_instances);
260
- __privateAdd(this, _core2);
261
- __privateAdd(this, _transformer);
195
+ var ct, S, Mt, It, Ct, Et, kt, Tt, $t, ne;
196
+ class Re {
197
+ constructor(s, t) {
198
+ d(this, $t);
199
+ d(this, ct);
200
+ d(this, S);
262
201
  /**
263
202
  * 处理 transformstart 事件
264
203
  */
265
- __privateAdd(this, _handleTransformStart, () => {
204
+ d(this, Mt, () => {
266
205
  this.emitPositionChange();
267
206
  });
268
207
  /**
269
208
  * 处理 transform 事件
270
209
  */
271
- __privateAdd(this, _handleTransform, () => {
210
+ d(this, It, () => {
272
211
  this.emitPositionChange();
273
212
  });
274
213
  /**
275
214
  * 处理 transformend 事件
276
215
  */
277
- __privateAdd(this, _handleTransformEnd, () => {
216
+ d(this, Ct, () => {
278
217
  this.emitPositionChange();
279
218
  });
280
219
  /**
281
220
  * 处理 dragstart 事件
282
221
  */
283
- __privateAdd(this, _handleDragStart2, () => {
222
+ d(this, Et, () => {
284
223
  this.emitPositionChange();
285
224
  });
286
225
  /**
287
226
  * 处理 dragmove 事件
288
227
  */
289
- __privateAdd(this, _handleDragMove2, () => {
228
+ d(this, kt, () => {
290
229
  this.emitPositionChange();
291
230
  });
292
231
  /**
293
232
  * 处理 dragend 事件
294
233
  */
295
- __privateAdd(this, _handleDragEnd2, () => {
234
+ d(this, Tt, () => {
296
235
  this.emitPositionChange();
297
236
  });
298
- __privateSet(this, _core2, core);
299
- __privateSet(this, _transformer, new Konva.Transformer({
300
- rotateEnabled: config?.rotateEnabled ?? true,
301
- ignoreStroke: config?.ignoreStroke ?? true,
302
- anchorSize: config?.anchorSize ?? 8,
303
- borderDash: config?.borderDash ?? [4, 4],
304
- anchorCornerRadius: config?.anchorCornerRadius ?? 4,
305
- padding: config?.padding ?? 6
306
- }));
307
- __privateMethod(this, _CanvasTransformer_instances, setupEventListeners_fn2).call(this);
237
+ l(this, ct, s), l(this, S, new D.Transformer({
238
+ rotateEnabled: t?.rotateEnabled ?? !0,
239
+ ignoreStroke: t?.ignoreStroke ?? !0,
240
+ anchorSize: t?.anchorSize ?? 8,
241
+ borderDash: t?.borderDash ?? [4, 4],
242
+ anchorCornerRadius: t?.anchorCornerRadius ?? 4,
243
+ padding: t?.padding ?? 6,
244
+ shouldOverdrawWholeArea: !0
245
+ })), b(this, $t, ne).call(this);
308
246
  }
309
247
  /**
310
248
  * 获取原生 Konva.Transformer 实例
311
249
  */
312
250
  getTransformer() {
313
- return __privateGet(this, _transformer);
251
+ return e(this, S);
314
252
  }
315
253
  /**
316
254
  * 获取 Transformer 的位置信息
317
255
  */
318
256
  getPosition() {
319
- const nodes = __privateGet(this, _transformer).nodes();
320
- if (nodes.length === 0) {
257
+ if (e(this, S).nodes().length === 0)
321
258
  return null;
322
- }
323
- const box = __privateGet(this, _transformer).getClientRect();
259
+ const t = e(this, S).getClientRect();
324
260
  return {
325
- x: box.x,
326
- y: box.y,
327
- width: box.width,
328
- height: box.height,
329
- rotation: __privateGet(this, _transformer).rotation()
261
+ x: t.x,
262
+ y: t.y,
263
+ width: t.width,
264
+ height: t.height,
265
+ rotation: e(this, S).rotation()
330
266
  };
331
267
  }
332
268
  /**
333
269
  * 设置要变换的节点
334
270
  */
335
- setNodes(nodes) {
336
- if (nodes.length === 0) {
271
+ setNodes(s) {
272
+ if (s.length === 0) {
337
273
  this.clearNodes();
338
274
  return;
339
275
  }
340
- __privateGet(this, _transformer).nodes(nodes);
341
- __privateGet(this, _transformer).moveToTop();
342
- this.emitPositionChange();
276
+ e(this, S).nodes(s), e(this, S).moveToTop(), this.emitPositionChange();
343
277
  }
344
278
  /**
345
279
  * 获取当前变换的节点
346
280
  */
347
281
  getNodes() {
348
- return __privateGet(this, _transformer).nodes();
282
+ return e(this, S).nodes();
349
283
  }
350
284
  /**
351
285
  * 清除所有节点
352
286
  */
353
287
  clearNodes() {
354
- __privateGet(this, _transformer).nodes([]);
355
- __privateGet(this, _transformer).moveToBottom();
356
- this.emitPositionChange();
288
+ e(this, S).nodes([]), e(this, S).moveToBottom(), this.emitPositionChange();
357
289
  }
358
290
  /**
359
291
  * emit Transformer 位置
360
292
  */
361
293
  emitPositionChange() {
362
- const position = this.getPosition();
363
- __privateGet(this, _core2).emitEvent("transformer:positionChange", position);
294
+ const s = this.getPosition();
295
+ e(this, ct)._emit("transformer:positionChange", s);
364
296
  }
365
297
  /**
366
298
  * 销毁 Transformer
367
299
  */
368
300
  destroy() {
369
- __privateGet(this, _transformer).destroy();
301
+ e(this, S).destroy();
370
302
  }
371
303
  }
372
- _core2 = new WeakMap();
373
- _transformer = new WeakMap();
374
- _handleTransformStart = new WeakMap();
375
- _handleTransform = new WeakMap();
376
- _handleTransformEnd = new WeakMap();
377
- _handleDragStart2 = new WeakMap();
378
- _handleDragMove2 = new WeakMap();
379
- _handleDragEnd2 = new WeakMap();
380
- _CanvasTransformer_instances = new WeakSet();
381
- /**
304
+ ct = new WeakMap(), S = new WeakMap(), Mt = new WeakMap(), It = new WeakMap(), Ct = new WeakMap(), Et = new WeakMap(), kt = new WeakMap(), Tt = new WeakMap(), $t = new WeakSet(), /**
382
305
  * 设置事件监听器
383
306
  */
384
- setupEventListeners_fn2 = function() {
385
- __privateGet(this, _transformer).on("transformstart", __privateGet(this, _handleTransformStart));
386
- __privateGet(this, _transformer).on("transform", __privateGet(this, _handleTransform));
387
- __privateGet(this, _transformer).on("transformend", __privateGet(this, _handleTransformEnd));
388
- __privateGet(this, _transformer).on("dragstart", __privateGet(this, _handleDragStart2));
389
- __privateGet(this, _transformer).on("dragmove", __privateGet(this, _handleDragMove2));
390
- __privateGet(this, _transformer).on("dragend", __privateGet(this, _handleDragEnd2));
307
+ ne = function() {
308
+ e(this, S).on("transformstart", e(this, Mt)), e(this, S).on("transform", e(this, It)), e(this, S).on("transformend", e(this, Ct)), e(this, S).on("dragstart", e(this, Et)), e(this, S).on("dragmove", e(this, kt)), e(this, S).on("dragend", e(this, Tt));
391
309
  };
392
- class CanvasState {
393
- constructor(initialState) {
394
- __publicField(this, "_past", []);
395
- __publicField(this, "_present");
396
- __publicField(this, "_future", []);
397
- __publicField(this, "_emitter");
398
- this._present = initialState;
399
- this._emitter = mitt();
310
+ var k, T, X, $;
311
+ class De {
312
+ // todo: 优化 selectedNodeIds 的存储和查询性能
313
+ // private _selectedNodeIds: Set<string> = new Set();
314
+ constructor(s) {
315
+ d(this, k, []);
316
+ d(this, T);
317
+ d(this, X, []);
318
+ d(this, $);
319
+ l(this, T, s), l(this, $, Ne());
400
320
  }
401
321
  /**
402
322
  * 获取当前状态
403
323
  */
404
324
  getState() {
405
- return { ...this._present };
325
+ return { ...e(this, T) };
406
326
  }
407
327
  /**
408
328
  * 获取完整历史状态
409
329
  */
410
330
  getHistory() {
411
331
  return {
412
- past: [...this._past],
413
- present: { ...this._present },
414
- future: [...this._future]
332
+ past: [...e(this, k)],
333
+ present: { ...e(this, T) },
334
+ future: [...e(this, X)]
415
335
  };
416
336
  }
417
337
  /**
418
338
  * 是否可以撤销
419
339
  */
420
340
  canUndo() {
421
- return this._past.length > 0;
341
+ return e(this, k).length > 0;
422
342
  }
423
343
  /**
424
344
  * 是否可以重做
425
345
  */
426
346
  canRedo() {
427
- return this._future.length > 0;
347
+ return e(this, X).length > 0;
428
348
  }
429
349
  /**
430
350
  * 订阅状态事件
431
351
  */
432
- on(event, handler) {
433
- this._emitter.on(event, handler);
352
+ on(s, t) {
353
+ e(this, $).on(s, t);
434
354
  }
435
355
  /**
436
356
  * 取消订阅状态事件
437
357
  */
438
- off(event, handler) {
439
- this._emitter.off(event, handler);
358
+ off(s, t) {
359
+ e(this, $).off(s, t);
440
360
  }
441
361
  /**
362
+ * @internal
442
363
  * 发送事件
443
364
  */
444
- emit(event, data) {
445
- this._emitter.emit(event, data);
365
+ _emit(s, t) {
366
+ e(this, $).emit(s, t);
446
367
  }
447
368
  /**
448
369
  * 撤销操作
449
370
  */
450
371
  undo() {
451
- if (this._past.length === 0) return;
452
- const previous = this._past[this._past.length - 1];
453
- const newPast = this._past.slice(0, this._past.length - 1);
454
- this._past = newPast;
455
- this._future = [this._present, ...this._future];
456
- this._present = previous;
457
- this._syncState(previous);
458
- this._emitter.emit("state:undo", previous);
459
- this._emitter.emit("state:change", previous);
372
+ if (e(this, k).length === 0) return;
373
+ const s = e(this, k)[e(this, k).length - 1], t = e(this, k).slice(0, e(this, k).length - 1);
374
+ l(this, k, t), l(this, X, [e(this, T), ...e(this, X)]), l(this, T, s), this._renderCanvas(s), e(this, $).emit("state:undo", s), e(this, $).emit("state:change", s);
460
375
  }
461
376
  /**
462
377
  * 重做操作
463
378
  */
464
379
  redo() {
465
- if (this._future.length === 0) return;
466
- const next = this._future[0];
467
- const newFuture = this._future.slice(1);
468
- this._past = [...this._past, this._present];
469
- this._future = newFuture;
470
- this._present = next;
471
- this._syncState(next);
472
- this._emitter.emit("state:redo", next);
473
- this._emitter.emit("state:change", next);
380
+ if (e(this, X).length === 0) return;
381
+ const s = e(this, X)[0], t = e(this, X).slice(1);
382
+ l(this, k, [...e(this, k), e(this, T)]), l(this, X, t), l(this, T, s), this._renderCanvas(s), e(this, $).emit("state:redo", s), e(this, $).emit("state:change", s);
474
383
  }
475
384
  /**
476
385
  * 重置历史记录
477
386
  */
478
387
  resetHistory() {
479
- this._past = [];
480
- this._future = [];
481
- this._emitter.emit("state:reset", this._present);
482
- this._emitter.emit("state:change", this._present);
388
+ l(this, k, []), l(this, X, []), e(this, $).emit("state:reset", e(this, T)), e(this, $).emit("state:change", e(this, T));
483
389
  }
484
390
  /**
485
391
  * 更新状态
486
392
  * @param partial - 部分状态更新
487
393
  * @param addToHistory - 是否添加到历史记录
488
394
  */
489
- _updateState(partial, addToHistory = true) {
490
- const newState = { ...this._present, ...partial };
491
- if (addToHistory) {
492
- this._past = [...this._past, this._present];
493
- this._future = [];
494
- }
495
- this._present = newState;
496
- this._emitter.emit("state:change", newState);
497
- }
498
- /**
499
- * 同步状态到外部系统(由子类实现)
500
- * @param _state - 要同步的状态
501
- */
502
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
503
- _syncState(_state) {
395
+ _updateState(s, t) {
396
+ const i = { ...e(this, T), ...s };
397
+ t && (l(this, k, [...e(this, k), e(this, T)]), l(this, X, [])), l(this, T, i), e(this, $).emit("state:change", i);
504
398
  }
505
399
  /**
506
400
  * 清理资源
507
401
  */
508
402
  _dispose() {
509
- this._emitter.all.clear();
403
+ e(this, $).all.clear();
510
404
  }
511
405
  }
512
- const NODE_NAMES = {
513
- nodeRoot: "nodeRoot_intrinsic",
514
- selectable: "selectable_intrinsic",
515
- rect: "rect_intrinsic",
516
- image: "image_intrinsic",
517
- imageMarker: "image_marker_intrinsic"
518
- };
519
- const RECT = {
520
- CORNER_RADIUS: 6,
521
- MIN_SIZE: 10
522
- };
523
- const IMAGE = {
524
- MIN_SIZE: 10
406
+ k = new WeakMap(), T = new WeakMap(), X = new WeakMap(), $ = new WeakMap();
407
+ class Vt {
408
+ }
409
+ const Ae = {
410
+ // used by RectNode
411
+ stroke: "$_strokeColor"
412
+ }, Oe = {
413
+ "theme.select-rect-border": "rgb(33, 150, 243)",
414
+ "theme.select-rect-fill": "rgba(33, 150, 243, 0.2)",
415
+ "theme.image-marker-color": "#F44336",
416
+ "theme.stroke-color.1": "#000000",
417
+ // Material Blue
418
+ "theme.stroke-color.2": "#F44336",
419
+ // Material Green
420
+ "theme.stroke-color.3": "#FF9800",
421
+ // Material Orange
422
+ "theme.fill-color.1": "#E3F2FD",
423
+ // Light Blue
424
+ "theme.fill-color.2": "#E8F5E9",
425
+ // Light Green
426
+ "theme.fill-color.3": "#FFF3E0"
427
+ // Light Orange
428
+ }, Ye = {
429
+ $_strokeColor: "theme.stroke-color.1"
525
430
  };
526
- class BaseCanvasNode {
527
- constructor(core, node, isDraft = false) {
528
- __publicField(this, "core");
529
- __publicField(this, "node");
530
- __publicField(this, "element");
531
- __publicField(this, "isDraft");
532
- this.core = core;
533
- this.node = node;
534
- this.isDraft = isDraft;
535
- this.element = this.createElement();
536
- }
537
- /**
538
- * 获取 Konva 元素
539
- */
540
- getElement() {
541
- return this.element;
542
- }
543
- /**
544
- * 获取节点数据
545
- */
546
- getNode() {
547
- return this.node;
431
+ function Lt(o, s) {
432
+ const t = {};
433
+ return Object.entries(Ae).forEach(([i, n]) => {
434
+ if (n in o) {
435
+ const r = o[n];
436
+ let a = r;
437
+ r.startsWith("theme.") && (a = s[r]), a && (t[i] = a);
438
+ }
439
+ }), t;
440
+ }
441
+ function Jt(o, s) {
442
+ const t = Math.max(o.width ?? w.MIN_SIZE, w.MIN_SIZE), i = Math.max(o.height ?? w.MIN_SIZE, w.MIN_SIZE), n = Lt(
443
+ {
444
+ ...Ye,
445
+ ...o
446
+ },
447
+ s
448
+ );
449
+ return {
450
+ ...o,
451
+ ...n,
452
+ cornerRadius: w.CORNER_RADIUS,
453
+ strokeWidth: 2,
454
+ width: t,
455
+ height: i,
456
+ name: `${A.nodeRoot} ${A.selectable} ${A.rect}`,
457
+ draggable: !0
458
+ };
459
+ }
460
+ function ze(o, s) {
461
+ const t = o.width ?? tt.MIN_SIZE, i = o.height ?? tt.MIN_SIZE, n = Lt(o, s);
462
+ if (!o.image) {
463
+ const a = document.createElement("canvas");
464
+ a.width = t, a.height = i, o.image = a;
548
465
  }
466
+ return {
467
+ ...o,
468
+ ...n,
469
+ name: `${A.nodeRoot} ${A.selectable} ${A.image}`,
470
+ draggable: !0
471
+ };
472
+ }
473
+ function Qt(o, s) {
474
+ const t = Math.max(o.width ?? w.MIN_SIZE, w.MIN_SIZE), i = Math.max(o.height ?? w.MIN_SIZE, w.MIN_SIZE), n = Lt(o, s);
475
+ return n.markerColor = s["theme.image-marker-color"], {
476
+ ...o,
477
+ ...n,
478
+ width: t,
479
+ height: i,
480
+ name: `${A.nodeRoot} ${A.imageMarker} ${o.$_parentId}`
481
+ };
549
482
  }
550
- function getRectSize(rect) {
483
+ function Xe(o) {
551
484
  return {
552
- width: Math.max(RECT.MIN_SIZE, rect.width() * rect.scaleX()),
553
- height: Math.max(RECT.MIN_SIZE, rect.height() * rect.scaleY())
485
+ width: Math.max(w.MIN_SIZE, o.width() * o.scaleX()),
486
+ height: Math.max(w.MIN_SIZE, o.height() * o.scaleY())
554
487
  };
555
488
  }
556
- class RectNode extends BaseCanvasNode {
557
- constructor(core, node, isDraft = false) {
558
- super(core, node, isDraft);
559
- __privateAdd(this, _RectNode_instances);
560
- __privateAdd(this, _toolTypeChangeHandler, (toolType) => {
561
- const isSelect = toolType === "select";
562
- this.element.listening(isSelect);
489
+ var dt, Rt, re;
490
+ class Ze extends Vt {
491
+ constructor(t, i, n = !1) {
492
+ super();
493
+ d(this, Rt);
494
+ z(this, "core");
495
+ z(this, "config");
496
+ z(this, "element");
497
+ z(this, "isDraft");
498
+ d(this, dt, (t) => {
499
+ const i = t === "select";
500
+ this.element.listening(i);
563
501
  });
564
- __privateMethod(this, _RectNode_instances, setupEventHandlers_fn).call(this, this.getElement());
502
+ this.core = t, this.config = Jt(i, this.core.getTheme()), this.element = this.createElement(), this.element.setAttr("$$_canvasNode", this), this.isDraft = n, b(this, Rt, re).call(this, this.getElement());
503
+ }
504
+ getID() {
505
+ return this.config.id;
506
+ }
507
+ getConfig() {
508
+ return this.config;
509
+ }
510
+ updateConfigBasedOnElement() {
511
+ const i = { ...this.getElement().getAttrs(), $$_canvasNode: void 0 };
512
+ this.config = i;
565
513
  }
566
514
  createElement() {
567
- const width = Math.max(
568
- this.node.props.width ?? RECT.MIN_SIZE,
569
- RECT.MIN_SIZE
570
- );
571
- const height = Math.max(
572
- this.node.props.height ?? RECT.MIN_SIZE,
573
- RECT.MIN_SIZE
574
- );
575
- const config = {
576
- id: this.node.id,
577
- ...this.node.props,
578
- ...this.node.style,
579
- width,
580
- height,
581
- cornerRadius: RECT.CORNER_RADIUS,
582
- name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.rect}`,
583
- draggable: true,
584
- stroke: "black",
585
- strokeWidth: 2
586
- };
587
- const rect = new Konva.Rect(config);
588
- rect.setAttrs({
589
- width,
590
- height
591
- });
592
- return rect;
515
+ return new D.Rect(this.config);
593
516
  }
594
517
  /**
595
518
  * 获取 Konva.Rect 实例
@@ -600,114 +523,80 @@ class RectNode extends BaseCanvasNode {
600
523
  /**
601
524
  * 更新节点数据
602
525
  */
603
- updateNode(node) {
604
- this.node = {
605
- ...this.node,
606
- ...node,
607
- props: {
608
- ...this.node.props,
609
- ...node.props
526
+ updateNode(t) {
527
+ this.config = Jt(
528
+ {
529
+ ...this.config,
530
+ ...t
610
531
  },
611
- style: {
612
- ...this.node.style,
613
- ...node.style
614
- }
615
- };
616
- const rect = this.getElement();
617
- rect.x(this.node.props.x);
618
- rect.y(this.node.props.y);
619
- const width = Math.max(
620
- this.node.props.width ?? RECT.MIN_SIZE,
621
- RECT.MIN_SIZE
622
- );
623
- const height = Math.max(
624
- this.node.props.height ?? RECT.MIN_SIZE,
625
- RECT.MIN_SIZE
626
- );
627
- rect.width(width);
628
- rect.height(height);
532
+ this.core.getTheme()
533
+ ), this.getElement().setAttrs(t);
629
534
  }
630
535
  /**
631
536
  * 销毁
632
537
  */
633
538
  destroy() {
634
- this.core.off("toolType:change", __privateGet(this, _toolTypeChangeHandler));
635
- this.element.destroy();
539
+ this.core.off("toolType:change", e(this, dt)), this.element.destroy();
636
540
  }
637
541
  }
638
- _toolTypeChangeHandler = new WeakMap();
639
- _RectNode_instances = new WeakSet();
640
- /**
542
+ dt = new WeakMap(), Rt = new WeakSet(), /**
641
543
  * 设置事件处理器
642
544
  */
643
- setupEventHandlers_fn = function(rect) {
644
- const element = rect;
645
- this.core.on("toolType:change", __privateGet(this, _toolTypeChangeHandler));
646
- element.on("transform", (event) => {
647
- const rect2 = event.target;
648
- const { width, height } = getRectSize(rect2);
649
- rect2.scale({ x: 1, y: 1 });
650
- rect2.width(width);
651
- rect2.height(height);
652
- });
653
- element.on("transformend", (event) => {
654
- const rect2 = event.target;
655
- const { width, height } = getRectSize(rect2);
656
- const newProps = {
657
- ...this.node.props,
658
- x: rect2.x(),
659
- y: rect2.y(),
660
- width,
661
- height,
662
- rotation: rect2.rotation()
663
- };
664
- this.node.props = newProps;
665
- this.core._syncNodeFromElement(this.node.id, {
666
- props: newProps
667
- });
668
- });
669
- element.on("dragend", (event) => {
670
- const rect2 = event.target;
671
- const newProps = {
672
- ...this.node.props,
673
- x: rect2.x(),
674
- y: rect2.y()
675
- };
676
- this.node.props = newProps;
677
- this.core._syncNodeFromElement(this.node.id, {
678
- props: newProps
679
- });
545
+ re = function(t) {
546
+ const i = t;
547
+ this.core.on("toolType:change", e(this, dt)), i.on("transform", (n) => {
548
+ const r = n.target, { width: a, height: h } = Xe(r);
549
+ r.scale({ x: 1, y: 1 }), r.width(a), r.height(h);
550
+ }), i.on("transformend", (n) => {
551
+ this.updateConfigBasedOnElement(), this.core._rebuildStateAfterNodeChange(this, !0);
552
+ }), i.on("dragend", (n) => {
553
+ this.updateConfigBasedOnElement(), this.core._rebuildStateAfterNodeChange(this, !0);
680
554
  });
681
555
  };
682
- class ImageNode extends BaseCanvasNode {
683
- constructor(core, node, isDraft = false) {
684
- super(core, node, isDraft);
685
- __privateAdd(this, _ImageNode_instances);
686
- __privateAdd(this, _toolTypeChangeHandler2, (toolType) => {
687
- const isSelect = toolType === "select";
688
- this.element.listening(isSelect);
556
+ var H, Yt, lt, gt, oe, zt;
557
+ class Pe extends Vt {
558
+ constructor(t, i, n = !1) {
559
+ super();
560
+ d(this, H);
561
+ z(this, "core");
562
+ z(this, "config");
563
+ z(this, "element");
564
+ z(this, "isDraft");
565
+ d(this, lt, (t) => {
566
+ const i = t === "select";
567
+ this.element.listening(i);
689
568
  });
690
- __privateMethod(this, _ImageNode_instances, loadImage_fn).call(this);
691
- __privateMethod(this, _ImageNode_instances, setupEventHandlers_fn2).call(this, this.getElement());
569
+ d(this, gt, () => {
570
+ const t = this.getElement().getLayer();
571
+ if (!t) return;
572
+ const i = t.find(
573
+ (n) => n.hasName(this.config.id)
574
+ );
575
+ this.core._rebuildStateAfterNodeChange(
576
+ [
577
+ this,
578
+ ...i.map(
579
+ (n) => n.getAttr("$$_canvasNode")
580
+ )
581
+ ],
582
+ !0
583
+ );
584
+ });
585
+ this.core = t, this.config = ze(i, this.core.getTheme()), this.element = this.createElement(), this.element.setAttr("$$_canvasNode", this), this.isDraft = n, b(this, H, Yt).call(this), b(this, H, oe).call(this, this.getElement());
586
+ }
587
+ getID() {
588
+ return this.config.id;
589
+ }
590
+ updateConfigBasedOnElement() {
591
+ const i = {
592
+ ...this.getElement().getAttrs(),
593
+ $$_canvasNode: void 0,
594
+ image: void 0
595
+ };
596
+ this.config = i;
692
597
  }
693
598
  createElement() {
694
- const width = this.node.props.width || IMAGE.MIN_SIZE;
695
- const height = this.node.props.height || IMAGE.MIN_SIZE;
696
- const placeholder = document.createElement("canvas");
697
- placeholder.width = width;
698
- placeholder.height = height;
699
- const img = new Konva.Image({
700
- id: this.node.id,
701
- x: this.node.props.x,
702
- y: this.node.props.y,
703
- width,
704
- height,
705
- rotation: this.node.props.rotation || 0,
706
- name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.selectable} ${NODE_NAMES.image}`,
707
- draggable: true,
708
- image: placeholder
709
- });
710
- return img;
599
+ return new D.Image(this.config);
711
600
  }
712
601
  /**
713
602
  * 获取 Konva.Image 实例
@@ -718,271 +607,155 @@ class ImageNode extends BaseCanvasNode {
718
607
  /**
719
608
  * 更新节点数据
720
609
  */
721
- updateNode(node) {
722
- this.node = {
723
- ...this.node,
724
- ...node,
725
- props: {
726
- ...this.node.props,
727
- ...node.props
728
- },
729
- style: {
730
- ...this.node.style,
731
- ...node.style
732
- },
733
- meta: {
734
- ...this.node.meta,
735
- ...node.meta
736
- }
737
- };
738
- const img = this.getElement();
739
- img.x(this.node.props.x);
740
- img.y(this.node.props.y);
741
- if (this.node.props.width && this.node.props.height) {
742
- const width = Math.max(this.node.props.width, IMAGE.MIN_SIZE);
743
- const height = Math.max(this.node.props.height, IMAGE.MIN_SIZE);
744
- img.width(width);
745
- img.height(height);
746
- }
747
- if (this.node.props.rotation !== void 0) {
748
- img.rotation(this.node.props.rotation);
749
- }
750
- if (node.meta?.imageUrl && node.meta.imageUrl !== this.node.meta.imageUrl) {
751
- __privateMethod(this, _ImageNode_instances, loadImage_fn).call(this);
752
- }
610
+ updateNode(t) {
611
+ const i = this.config;
612
+ this.config = {
613
+ ...this.config,
614
+ ...t,
615
+ id: this.config.id
616
+ }, this.getElement().setAttrs(t), t.$_imageUrl && t.$_imageUrl !== i.$_imageUrl && b(this, H, Yt).call(this);
753
617
  }
754
618
  /**
755
619
  * 销毁
756
620
  */
757
621
  destroy() {
758
- this.core.off("toolType:change", __privateGet(this, _toolTypeChangeHandler2));
759
- this.element.destroy();
622
+ this.core.off("toolType:change", e(this, lt)), this.element.destroy();
623
+ }
624
+ getConfig() {
625
+ const t = {
626
+ ...this.config,
627
+ $$_canvasNode: void 0,
628
+ image: void 0
629
+ };
630
+ return structuredClone(t);
760
631
  }
761
632
  }
762
- _ImageNode_instances = new WeakSet();
763
- /**
633
+ H = new WeakSet(), /**
764
634
  * 加载图片
765
635
  */
766
- loadImage_fn = function() {
767
- const imageUrl = this.node.meta.imageUrl;
768
- if (!imageUrl) {
636
+ Yt = function() {
637
+ const t = this.config.$_imageUrl;
638
+ if (!t) {
769
639
  console.warn("Image URL is missing");
770
640
  return;
771
641
  }
772
- const img = new window.Image();
773
- img.crossOrigin = "anonymous";
774
- img.src = imageUrl;
775
- img.onload = () => {
776
- this.getElement().image(img);
777
- const width = this.node.props.width ?? img.width;
778
- const height = this.node.props.height ?? img.height;
779
- this.getElement().width(Math.max(width, IMAGE.MIN_SIZE));
780
- this.getElement().height(Math.max(height, IMAGE.MIN_SIZE));
642
+ const i = new window.Image();
643
+ i.crossOrigin = "anonymous", i.src = t, i.onload = () => {
644
+ this.getElement().image(i);
645
+ const n = this.config.width ?? i.width, r = this.config.height ?? i.height;
646
+ this.getElement().width(Math.max(n, tt.MIN_SIZE)), this.getElement().height(Math.max(r, tt.MIN_SIZE));
647
+ }, i.onerror = () => {
648
+ console.error("Failed to load image:", t);
781
649
  };
782
- img.onerror = () => {
783
- console.error("Failed to load image:", imageUrl);
784
- };
785
- };
786
- _toolTypeChangeHandler2 = new WeakMap();
787
- /**
650
+ }, lt = new WeakMap(), gt = new WeakMap(), /**
788
651
  * 设置事件处理器
789
652
  */
790
- setupEventHandlers_fn2 = function(img) {
791
- this.core.on("toolType:change", __privateGet(this, _toolTypeChangeHandler2));
792
- img.on("transform", (event) => {
793
- const img2 = event.target;
794
- const width = Math.max(IMAGE.MIN_SIZE, img2.width() * img2.scaleX());
795
- const height = Math.max(IMAGE.MIN_SIZE, img2.height() * img2.scaleY());
796
- img2.scale({ x: 1, y: 1 });
797
- img2.width(width);
798
- img2.height(height);
799
- __privateMethod(this, _ImageNode_instances, syncImageMarkers_fn).call(this);
653
+ oe = function(t) {
654
+ this.core.on("toolType:change", e(this, lt)), t.on("transform", (i) => {
655
+ const n = i.target, r = Math.max(tt.MIN_SIZE, n.width() * n.scaleX()), a = Math.max(tt.MIN_SIZE, n.height() * n.scaleY());
656
+ n.scale({ x: 1, y: 1 }), n.width(r), n.height(a), b(this, H, zt).call(this);
657
+ }), t.on("transformend", (i) => {
658
+ this.updateConfigBasedOnElement(), e(this, gt).call(this);
659
+ }), t.on("dragmove", () => {
660
+ b(this, H, zt).call(this);
661
+ }), t.on("dragend", (i) => {
662
+ this.updateConfigBasedOnElement(), e(this, gt).call(this);
800
663
  });
801
- img.on("transformend", (event) => {
802
- const img2 = event.target;
803
- const newProps = {
804
- ...this.node.props,
805
- x: img2.x(),
806
- y: img2.y(),
807
- width: img2.width(),
808
- height: img2.height(),
809
- rotation: img2.rotation()
810
- };
811
- this.node.props = newProps;
812
- this.core._syncNodeFromElement(this.node.id, {
813
- props: newProps
814
- });
815
- __privateMethod(this, _ImageNode_instances, syncImageMarkersToState_fn).call(this);
816
- });
817
- img.on("dragmove", () => {
818
- __privateMethod(this, _ImageNode_instances, syncImageMarkers_fn).call(this);
819
- });
820
- img.on("dragend", (event) => {
821
- const img2 = event.target;
822
- const newProps = {
823
- ...this.node.props,
824
- x: img2.x(),
825
- y: img2.y()
826
- };
827
- this.node.props = newProps;
828
- this.core._syncNodeFromElement(this.node.id, {
829
- props: newProps
830
- });
831
- __privateMethod(this, _ImageNode_instances, syncImageMarkersToState_fn).call(this);
832
- });
833
- };
834
- /**
664
+ }, /**
835
665
  * 同步 image-marker 节点的位置(实时更新 Konva 元素)
836
666
  */
837
- syncImageMarkers_fn = function() {
838
- const img = this.getElement();
839
- const layer = img.getLayer();
840
- if (!layer) return;
841
- const imgX = img.x();
842
- const imgY = img.y();
843
- const imgWidth = img.width();
844
- const imgHeight = img.height();
845
- const imageMarkerElements = layer.find(
846
- (node) => node.hasName(this.node.id)
847
- );
848
- const nodes = this.core.getState().nodes || [];
849
- imageMarkerElements.forEach((nodeElement) => {
850
- const nodeData = nodes.find((n) => n.id === nodeElement.id());
851
- if (nodeData?.type === "image-marker" && nodeData.meta.relativePosition) {
852
- const { start, end } = nodeData.meta.relativePosition;
853
- const startX = imgX + start.percentX / 100 * imgWidth;
854
- const startY = imgY + start.percentY / 100 * imgHeight;
855
- const endX = imgX + end.percentX / 100 * imgWidth;
856
- const endY = imgY + end.percentY / 100 * imgHeight;
857
- const newX = Math.min(startX, endX);
858
- const newY = Math.min(startY, endY);
859
- const newWidth = Math.abs(endX - startX);
860
- const newHeight = Math.abs(endY - startY);
861
- nodeElement.position({ x: newX, y: newY });
862
- nodeElement.setAttrs({ width: newWidth, height: newHeight });
863
- const children = nodeElement.getChildren();
864
- children.forEach((child) => {
865
- if (child.getClassName() === "Rect") {
866
- child.setAttrs({ width: newWidth, height: newHeight });
867
- } else if (child.getClassName() === "Group") {
868
- child.setAttrs({ x: newWidth, y: newHeight });
869
- }
870
- });
667
+ zt = function() {
668
+ const t = this.getElement(), i = t.getLayer();
669
+ if (!i) return;
670
+ const n = t.x(), r = t.y(), a = t.width(), h = t.height(), c = i.find(
671
+ (m) => m.hasName(this.config.id)
672
+ ), g = this.core.getState().nodes || [];
673
+ c.forEach((m) => {
674
+ const f = g.find((u) => u.id === m.id());
675
+ if (f?.$_type === "image-marker" && f.$_relativeBox) {
676
+ const { start: u, end: x } = f.$_relativeBox, v = n + u.ratioX * a, M = r + u.ratioY * h, _ = n + x.ratioX * a, E = r + x.ratioY * h, Dt = Math.min(v, _), Bt = Math.min(M, E), G = Math.abs(_ - v), rt = Math.abs(E - M);
677
+ m.setAttrs({
678
+ x: Dt,
679
+ y: Bt,
680
+ width: G,
681
+ height: rt
682
+ }), m.getChildren().forEach((Y) => {
683
+ Y.getClassName() === "Rect" ? Y.setAttrs({ width: G, height: rt }) : Y.getClassName() === "Group" && Y.setAttrs({ x: G, y: rt });
684
+ }), m.getAttr("$$_canvasNode")?.updateConfigBasedOnElement();
871
685
  }
872
686
  });
873
687
  };
874
- /**
875
- * 同步 image-marker 节点到状态
876
- */
877
- syncImageMarkersToState_fn = function() {
878
- const img = this.getElement();
879
- const layer = img.getLayer();
880
- if (!layer) return;
881
- const imageMarkerElements = layer.find(
882
- (node) => node.hasName(this.node.id)
883
- );
884
- imageMarkerElements.forEach((nodeElement) => {
885
- this.core._syncNodeFromElement(nodeElement.id(), {
886
- props: {
887
- x: nodeElement.x(),
888
- y: nodeElement.y(),
889
- width: nodeElement.width(),
890
- height: nodeElement.height()
891
- }
892
- });
893
- });
894
- };
895
- class ImageMarkerNode extends BaseCanvasNode {
896
- constructor(core, node, isDraft = false) {
897
- super(core, node, isDraft);
898
- __privateAdd(this, _ImageMarkerNode_instances);
899
- __privateAdd(this, _rect);
900
- __privateAdd(this, _markerGroup);
901
- __privateAdd(this, _circle);
902
- __privateAdd(this, _text);
903
- __privateAdd(this, _handleViewportChange);
904
- __privateAdd(this, _handleNodesSelected);
905
- const group = this.getElement();
906
- __privateSet(this, _rect, group.findOne(".rect"));
907
- __privateSet(this, _markerGroup, group.findOne(".marker-group"));
908
- __privateSet(this, _circle, __privateGet(this, _markerGroup).findOne("Circle"));
909
- __privateSet(this, _text, __privateGet(this, _markerGroup).findOne("Text"));
910
- __privateMethod(this, _ImageMarkerNode_instances, setupEventHandlers_fn3).call(this);
911
- __privateSet(this, _handleViewportChange, () => {
912
- __privateMethod(this, _ImageMarkerNode_instances, changeVisulStyle_fn).call(this);
913
- });
914
- this.core.on("viewport:scale:change", __privateGet(this, _handleViewportChange));
915
- __privateSet(this, _handleNodesSelected, (selectedIds) => {
916
- const isSelected = selectedIds.includes(this.node.id);
917
- this.setFocusState(isSelected);
918
- });
919
- this.core.on("nodes:selected", __privateGet(this, _handleNodesSelected));
688
+ var L, R, q, B, et, st, nt, ae, he;
689
+ class Ue extends Vt {
690
+ constructor(t, i, n = !1) {
691
+ super();
692
+ d(this, nt);
693
+ z(this, "core");
694
+ z(this, "config");
695
+ z(this, "element");
696
+ z(this, "isDraft");
697
+ d(this, L);
698
+ d(this, R);
699
+ d(this, q);
700
+ d(this, B);
701
+ d(this, et);
702
+ d(this, st);
703
+ this.core = t, this.config = Qt(i, this.core.getTheme()), this.isDraft = n, this.element = this.createElement(), this.element.setAttr("$$_canvasNode", this);
704
+ const r = this.getElement();
705
+ l(this, L, r.findOne(".rect")), l(this, R, r.findOne(".marker-group")), l(this, q, e(this, R).findOne("Circle")), l(this, B, e(this, R).findOne("Text")), b(this, nt, he).call(this), l(this, et, () => {
706
+ b(this, nt, ae).call(this);
707
+ }), this.core.on("viewport:scale:change", e(this, et)), l(this, st, (a) => {
708
+ const h = a.includes(this.config.id);
709
+ this.setFocusState(h);
710
+ }), this.core.on("nodes:selected", e(this, st));
711
+ }
712
+ getID() {
713
+ return this.config.id;
714
+ }
715
+ getConfig() {
716
+ return this.config;
920
717
  }
921
718
  createElement() {
922
- const width = Math.max(
923
- this.node.props.width ?? RECT.MIN_SIZE,
924
- RECT.MIN_SIZE
925
- );
926
- const height = Math.max(
927
- this.node.props.height ?? RECT.MIN_SIZE,
928
- RECT.MIN_SIZE
929
- );
930
- const group = new Konva.Group({
931
- id: this.node.id,
932
- name: `${NODE_NAMES.nodeRoot} ${NODE_NAMES.imageMarker} ${this.node.meta.parent}`,
933
- x: this.node.props.x,
934
- y: this.node.props.y,
935
- width,
936
- height
937
- });
938
- const stageScale = this.core.getStageScale();
939
- const rectStrokeWidth = 2 / stageScale;
940
- const rectDash = [5 / stageScale, 5 / stageScale];
941
- const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
942
- const rect = new Konva.Rect({
719
+ const t = Math.max(this.config.width ?? w.MIN_SIZE, w.MIN_SIZE), i = Math.max(this.config.height ?? w.MIN_SIZE, w.MIN_SIZE), n = new D.Group({
720
+ id: this.config.id,
721
+ name: `${A.nodeRoot} ${A.imageMarker} ${this.config.$_parentId}`,
722
+ x: this.config.x,
723
+ y: this.config.y,
724
+ width: t,
725
+ height: i
726
+ }), r = this.core.getStageScale(), a = 2 / r, h = [5 / r, 5 / r], c = w.CORNER_RADIUS / r, g = new D.Rect({
943
727
  name: "rect",
944
728
  x: 0,
945
729
  y: 0,
946
- width,
947
- height,
948
- stroke: "#F44336",
949
- strokeWidth: rectStrokeWidth,
950
- dash: rectDash,
951
- fill: "transparent",
952
- cornerRadius: rectCornerRadius,
953
- listening: false
954
- });
955
- const markerGroup = new Konva.Group({
730
+ width: t,
731
+ height: i,
732
+ stroke: this.config.markerColor,
733
+ strokeWidth: a,
734
+ dash: h,
735
+ cornerRadius: c,
736
+ listening: !1
737
+ }), m = new D.Group({
956
738
  name: "marker-group",
957
- x: width,
958
- y: height,
959
- visible: this.isDraft ? false : true
960
- });
961
- const radius = 14 / stageScale;
962
- const strokeWidth = 3 / stageScale;
963
- const fontSize = 16 / stageScale;
964
- const circle = new Konva.Circle({
965
- radius,
966
- fill: "#F44336",
739
+ x: t,
740
+ y: i,
741
+ visible: !this.isDraft
742
+ }), f = 14 / r, u = 3 / r, x = 16 / r, v = new D.Circle({
743
+ radius: f,
744
+ fill: this.config.markerColor,
967
745
  stroke: "white",
968
- strokeWidth
969
- });
970
- const text = new Konva.Text({
971
- x: -radius,
972
- y: -radius,
973
- width: radius * 2,
974
- height: radius * 2,
975
- text: String(this.node.meta.markerNumber || ""),
746
+ strokeWidth: u
747
+ }), M = new D.Text({
748
+ x: -f,
749
+ y: -f,
750
+ width: f * 2,
751
+ height: f * 2,
752
+ text: String(this.config.$_markerNumber || ""),
976
753
  align: "center",
977
754
  verticalAlign: "middle",
978
- fontSize,
755
+ fontSize: x,
979
756
  fill: "white"
980
757
  });
981
- markerGroup.add(circle);
982
- markerGroup.add(text);
983
- group.add(rect);
984
- group.add(markerGroup);
985
- return group;
758
+ return m.add(v), m.add(M), n.add(g), n.add(m), n;
986
759
  }
987
760
  /**
988
761
  * 获取 Konva.Group 实例
@@ -993,292 +766,197 @@ class ImageMarkerNode extends BaseCanvasNode {
993
766
  /**
994
767
  * 更新节点数据
995
768
  */
996
- updateNode(node) {
997
- this.node = {
998
- ...this.node,
999
- ...node,
1000
- props: {
1001
- ...this.node.props,
1002
- ...node.props
1003
- },
1004
- style: {
1005
- ...this.node.style,
1006
- ...node.style
769
+ updateNode(t) {
770
+ this.config = Qt(
771
+ {
772
+ ...this.config,
773
+ ...t
1007
774
  },
1008
- meta: {
1009
- ...this.node.meta,
1010
- ...node.meta
1011
- }
1012
- };
1013
- const group = this.getElement();
1014
- group.x(this.node.props.x);
1015
- group.y(this.node.props.y);
1016
- const width = Math.max(
1017
- this.node.props.width ?? RECT.MIN_SIZE,
1018
- RECT.MIN_SIZE
1019
- );
1020
- const height = Math.max(
1021
- this.node.props.height ?? RECT.MIN_SIZE,
1022
- RECT.MIN_SIZE
775
+ this.core.getTheme()
1023
776
  );
1024
- group.width(width);
1025
- group.height(height);
1026
- __privateGet(this, _rect).width(width);
1027
- __privateGet(this, _rect).height(height);
1028
- __privateGet(this, _markerGroup).x(width);
1029
- __privateGet(this, _markerGroup).y(height);
1030
- if (node.style?.color) {
1031
- __privateGet(this, _rect).stroke(node.style.color);
1032
- }
1033
- if (node.meta?.markerNumber !== void 0) {
1034
- __privateGet(this, _text).text(String(node.meta.markerNumber));
1035
- }
777
+ const i = this.getElement();
778
+ i.x(this.config.x), i.y(this.config.y);
779
+ const n = Math.max(this.config.width ?? w.MIN_SIZE, w.MIN_SIZE), r = Math.max(this.config.height ?? w.MIN_SIZE, w.MIN_SIZE);
780
+ i.width(n), i.height(r), e(this, L).width(n), e(this, L).height(r), e(this, R).x(n), e(this, R).y(r), t.markerColor && (e(this, L).stroke(t.markerColor), e(this, q).fill(t.markerColor)), t.$_markerNumber !== void 0 && e(this, B).text(String(t.$_markerNumber));
1036
781
  }
1037
782
  /**
1038
783
  * 销毁
1039
784
  */
1040
785
  destroy() {
1041
- this.core.off("viewport:scale:change", __privateGet(this, _handleViewportChange));
1042
- this.core.off("nodes:selected", __privateGet(this, _handleNodesSelected));
1043
- this.element.destroy();
786
+ this.core.off("viewport:scale:change", e(this, et)), this.core.off("nodes:selected", e(this, st)), this.element.destroy();
1044
787
  }
1045
788
  /**
1046
789
  * 更新焦点状态(hover 或 selected)
1047
790
  */
1048
- setFocusState(isFocus) {
1049
- const stageScale = this.core.getStageScale();
1050
- const strokeWidth = isFocus ? 4 / stageScale : 3 / stageScale;
1051
- const scale = isFocus ? 1.2 : 1;
1052
- __privateGet(this, _rect).strokeWidth(strokeWidth);
1053
- __privateGet(this, _circle).strokeWidth(strokeWidth);
1054
- __privateGet(this, _markerGroup).scaleX(scale);
1055
- __privateGet(this, _markerGroup).scaleY(scale);
791
+ setFocusState(t) {
792
+ const i = this.core.getStageScale(), n = t ? 4 / i : 3 / i, r = t ? 1.2 : 1;
793
+ e(this, L).strokeWidth(n), e(this, q).strokeWidth(n), e(this, R).scaleX(r), e(this, R).scaleY(r);
794
+ }
795
+ updateConfigBasedOnElement() {
796
+ const t = this.getElement();
797
+ this.config = {
798
+ ...this.config,
799
+ width: t.width(),
800
+ height: t.height(),
801
+ x: t.x(),
802
+ y: t.y()
803
+ };
1056
804
  }
1057
805
  }
1058
- _rect = new WeakMap();
1059
- _markerGroup = new WeakMap();
1060
- _circle = new WeakMap();
1061
- _text = new WeakMap();
1062
- _handleViewportChange = new WeakMap();
1063
- _handleNodesSelected = new WeakMap();
1064
- _ImageMarkerNode_instances = new WeakSet();
1065
- /**
806
+ L = new WeakMap(), R = new WeakMap(), q = new WeakMap(), B = new WeakMap(), et = new WeakMap(), st = new WeakMap(), nt = new WeakSet(), /**
1066
807
  * 更新标记点的缩放以保持视觉大小不变
1067
808
  */
1068
- changeVisulStyle_fn = function() {
1069
- const stageScale = this.core.getStageScale();
1070
- const radius = 14 / stageScale;
1071
- const strokeWidth = 3 / stageScale;
1072
- const fontSize = 16 / stageScale;
1073
- const rectStrokeWidth = 3 / stageScale;
1074
- const rectDash = [5 / stageScale, 5 / stageScale];
1075
- const rectCornerRadius = RECT.CORNER_RADIUS / stageScale;
1076
- __privateGet(this, _rect).strokeWidth(rectStrokeWidth);
1077
- __privateGet(this, _rect).dash(rectDash);
1078
- __privateGet(this, _rect).cornerRadius(rectCornerRadius);
1079
- __privateGet(this, _circle).radius(radius);
1080
- __privateGet(this, _circle).strokeWidth(strokeWidth);
1081
- __privateGet(this, _text).x(-radius);
1082
- __privateGet(this, _text).y(-radius);
1083
- __privateGet(this, _text).width(radius * 2);
1084
- __privateGet(this, _text).height(radius * 2);
1085
- __privateGet(this, _text).fontSize(fontSize);
1086
- };
1087
- /**
809
+ ae = function() {
810
+ const t = this.core.getStageScale(), i = 14 / t, n = 3 / t, r = 16 / t, a = 3 / t, h = [5 / t, 5 / t], c = w.CORNER_RADIUS / t;
811
+ e(this, L).strokeWidth(a), e(this, L).dash(h), e(this, L).cornerRadius(c), e(this, q).radius(i), e(this, q).strokeWidth(n), e(this, B).x(-i), e(this, B).y(-i), e(this, B).width(i * 2), e(this, B).height(i * 2), e(this, B).fontSize(r);
812
+ }, /**
1088
813
  * 设置事件处理器
1089
814
  */
1090
- setupEventHandlers_fn3 = function() {
1091
- __privateGet(this, _markerGroup).on("pointerover", () => {
1092
- this.setFocusState(true);
1093
- this.core.setCursor("pointer");
1094
- });
1095
- __privateGet(this, _markerGroup).on("pointerout", () => {
1096
- const selectedIds = this.core.getState().selectedNodeIds || [];
1097
- const isSelected = selectedIds.includes(this.node.id);
1098
- this.setFocusState(isSelected);
1099
- this.core.resetCursor();
1100
- });
1101
- __privateGet(this, _markerGroup).on("pointerdown", () => {
1102
- this.core.selectNode(this.node.id);
1103
- });
1104
- __privateGet(this, _markerGroup).on("transform", () => {
815
+ he = function() {
816
+ e(this, R).on("pointerover", () => {
817
+ this.setFocusState(!0), this.core._setCursor("pointer");
818
+ }), e(this, R).on("pointerout", () => {
819
+ const i = (this.core.getState().selectedNodeIds || []).includes(this.config.id);
820
+ this.setFocusState(i), this.core._resetCursor();
821
+ }), e(this, R).on("pointerdown", () => {
822
+ this.core._selectNodes([this.config.id]);
823
+ }), e(this, R).on("transform", () => {
1105
824
  console.log("image marker group on transform called");
1106
825
  });
1107
826
  };
1108
- function createCanvasNodeByType(core, type, config, isDraft = false) {
1109
- switch (type) {
827
+ function te(o, s, t, i = !1) {
828
+ switch (s) {
1110
829
  case "rectangle":
1111
- return new RectNode(core, config, isDraft);
830
+ return new Ze(o, t, i);
1112
831
  case "image":
1113
- return new ImageNode(core, config, isDraft);
832
+ return new Pe(o, t, i);
1114
833
  case "image-marker":
1115
- return new ImageMarkerNode(core, config, isDraft);
834
+ return new Ue(o, t, i);
1116
835
  default:
1117
836
  return null;
1118
837
  }
1119
838
  }
1120
- function clamp(value, range) {
1121
- return Math.min(Math.max(value, range[0]), range[1]);
839
+ function ee(o, s) {
840
+ return Math.min(Math.max(o, s[0]), s[1]);
1122
841
  }
1123
- const createNodeByType = (type, position, style, meta) => {
1124
- const baseNode = {
1125
- type,
1126
- id: v4(),
1127
- text: null,
1128
- style: {
1129
- opacity: 1,
1130
- line: "solid",
1131
- color: "black",
1132
- size: "medium",
1133
- animated: false
1134
- },
1135
- props: {
1136
- x: position.x,
1137
- y: position.y,
1138
- rotation: 0,
1139
- visible: true
1140
- },
1141
- meta: {
1142
- ...meta,
1143
- startPoint: position
1144
- }
1145
- };
1146
- if (type === "image-marker") {
1147
- return {
1148
- ...baseNode,
1149
- style: {
1150
- ...baseNode.style,
1151
- color: "#F44336"
1152
- }
842
+ const We = (o, s, t) => ({
843
+ ...t,
844
+ $_type: o,
845
+ id: pt(),
846
+ x: s.x,
847
+ y: s.y
848
+ });
849
+ function Ve(o, s, t) {
850
+ let i = s;
851
+ if (o.$_type === "image-marker" && o.$_bounds) {
852
+ const n = o.$_bounds;
853
+ i = {
854
+ x: ee(s.x, [n.x, n.x + n.width]),
855
+ y: ee(s.y, [n.y, n.y + n.height])
1153
856
  };
1154
857
  }
1155
- return baseNode;
1156
- };
1157
- function updateNodeByType(node, position) {
1158
- let finalPosition = position;
1159
- if (node.type === "image-marker" && node.meta.bounds) {
1160
- const bounds = node.meta.bounds;
1161
- finalPosition = {
1162
- x: clamp(position.x, [bounds.x, bounds.x + bounds.width]),
1163
- y: clamp(position.y, [bounds.y, bounds.y + bounds.height])
1164
- };
1165
- }
1166
- if (node.type === "rectangle" || node.type === "image-marker") {
1167
- const startPoint = node.meta.startPoint ?? {
1168
- x: node.props.x,
1169
- y: node.props.y
1170
- };
1171
- const [p1, p2] = normalizePoints(startPoint, finalPosition);
858
+ if (o.$_type === "rectangle" || o.$_type === "image-marker") {
859
+ const [n, r] = Xt(t, i);
1172
860
  return {
1173
- ...node,
1174
- props: {
1175
- ...node.props,
1176
- x: p1.x,
1177
- y: p1.y,
1178
- width: Math.max(p2.x - p1.x, RECT.MIN_SIZE),
1179
- height: Math.max(p2.y - p1.y, RECT.MIN_SIZE)
1180
- },
1181
- meta: {
1182
- ...node.meta,
1183
- // 保存初始起点,以便后续更新使用
1184
- startPoint
1185
- }
861
+ ...o,
862
+ x: n.x,
863
+ y: n.y,
864
+ width: Math.max(r.x - n.x, w.MIN_SIZE),
865
+ height: Math.max(r.y - n.y, w.MIN_SIZE)
1186
866
  };
1187
867
  }
1188
- return node;
868
+ return o;
1189
869
  }
1190
- function normalizePoints(p1, p2) {
1191
- let p1x = p1.x, p1y = p1.y, p2x = p2.x, p2y = p2.y, d;
1192
- if (p1x > p2x) {
1193
- d = Math.abs(p1x - p2x);
1194
- p1x = p2x;
1195
- p2x = p1x + d;
1196
- }
1197
- if (p1y > p2y) {
1198
- d = Math.abs(p1y - p2y);
1199
- p1y = p2y;
1200
- p2y = p1y + d;
1201
- }
1202
- return [
1203
- { x: p1x, y: p1y },
1204
- { x: p2x, y: p2y }
870
+ function Xt(o, s) {
871
+ let t = o.x, i = o.y, n = s.x, r = s.y, a;
872
+ return t > n && (a = Math.abs(t - n), t = n, n = t + a), i > r && (a = Math.abs(i - r), i = r, r = i + a), [
873
+ { x: t, y: i },
874
+ { x: n, y: r }
1205
875
  ];
1206
876
  }
1207
- class CanvasCore extends CanvasState {
1208
- constructor(el) {
1209
- super({
877
+ const Le = (o, s) => {
878
+ if (o.length !== s.length) return !1;
879
+ const t = new Set(o);
880
+ return s.every((i) => t.has(i));
881
+ };
882
+ var mt, I, U, W, C, j, Z, P, F, J, ut, O, ce, de, Pt, Ut, le;
883
+ const at = class at extends De {
884
+ constructor(t, i) {
885
+ const n = {
886
+ toolType: "select",
887
+ nodes: [],
888
+ ...i,
1210
889
  viewport: {
1211
890
  x: 0,
1212
891
  y: 0,
1213
- width: el.clientWidth,
1214
- height: el.clientHeight,
1215
- scale: 1
1216
- },
1217
- toolType: "select",
1218
- nodes: []
1219
- });
1220
- __privateAdd(this, _CanvasCore_instances);
1221
- __privateAdd(this, _canvasStage);
1222
- __privateAdd(this, _mainLayer);
1223
- __privateAdd(this, _canvasTransformer);
1224
- __privateAdd(this, _draftNode, null);
1225
- __privateAdd(this, _container);
1226
- __privateAdd(this, _handleKeyDown, (e) => {
1227
- if (e.key === "Delete" || e.key === "Backspace") {
1228
- e.preventDefault();
1229
- this.deleteSelectedNodes();
892
+ scale: 1,
893
+ ...i?.viewport
1230
894
  }
895
+ };
896
+ super(n);
897
+ d(this, O);
898
+ d(this, I);
899
+ d(this, U);
900
+ d(this, W);
901
+ d(this, C, null);
902
+ d(this, j);
903
+ d(this, Z, null);
904
+ d(this, P, null);
905
+ /** 节点映射,方便快速查找 */
906
+ d(this, F, /* @__PURE__ */ new Map());
907
+ d(this, J, null);
908
+ d(this, ut, (t) => {
909
+ (t.key === "Delete" || t.key === "Backspace") && (t.preventDefault(), this.deleteSelectedNodes());
1231
910
  });
1232
- __privateSet(this, _container, el);
1233
- __privateSet(this, _canvasStage, new CanvasStage(this, {
1234
- container: el,
1235
- width: el.clientWidth,
1236
- height: el.clientHeight,
1237
- draggable: false,
911
+ l(this, j, t), l(this, I, new $e(this, {
912
+ container: t,
913
+ width: t.clientWidth,
914
+ height: t.clientHeight,
915
+ draggable: !1,
1238
916
  className: "touch-none"
1239
- }));
1240
- __privateSet(this, _mainLayer, new Konva.Layer());
1241
- __privateSet(this, _canvasTransformer, new CanvasTransformer(this));
1242
- __privateGet(this, _canvasStage).getStage().add(__privateGet(this, _mainLayer));
1243
- __privateGet(this, _mainLayer).add(__privateGet(this, _canvasTransformer).getTransformer());
1244
- this.updateViewport(this.getState().viewport, false);
1245
- __privateMethod(this, _CanvasCore_instances, setupKeyboardEvents_fn).call(this);
917
+ })), l(this, U, new D.Layer()), l(this, W, new Re(this)), e(this, I).getStage().add(e(this, U)), e(this, U).add(e(this, W).getTransformer()), this._renderCanvas(n), b(this, O, ce).call(this), b(this, O, de).call(this);
918
+ }
919
+ /**
920
+ * 注册全局主题
921
+ */
922
+ static registerTheme(t) {
923
+ l(at, mt, t);
924
+ }
925
+ /**
926
+ * 获取主题,如果没有注册过返回默认主题
927
+ */
928
+ getTheme() {
929
+ return e(at, mt) ?? Oe;
1246
930
  }
1247
931
  /**
1248
932
  * 获取 CanvasStage 实例
1249
933
  */
1250
934
  getCanvasStage() {
1251
- return __privateGet(this, _canvasStage);
935
+ return e(this, I);
1252
936
  }
1253
937
  /**
1254
938
  * 获取 CanvasTransformer 实例
1255
939
  */
1256
940
  getCanvasTransformer() {
1257
- return __privateGet(this, _canvasTransformer);
1258
- }
1259
- /**
1260
- * 发射事件(供内部类使用)
1261
- */
1262
- emitEvent(event, data) {
1263
- this.emit(event, data);
941
+ return e(this, W);
1264
942
  }
1265
943
  /**
1266
944
  * 获取 Konva.Stage 实例
1267
945
  */
1268
946
  getStage() {
1269
- return __privateGet(this, _canvasStage).getStage();
947
+ return e(this, I).getStage();
1270
948
  }
1271
949
  /**
1272
950
  * 获取 Stage 容器元素
1273
951
  */
1274
952
  getContainer() {
1275
- return __privateGet(this, _canvasStage).getStage().container();
953
+ return e(this, I).getStage().container();
1276
954
  }
1277
955
  /**
1278
956
  * 获取主图层
1279
957
  */
1280
958
  getMainLayer() {
1281
- return __privateGet(this, _mainLayer);
959
+ return e(this, U);
1282
960
  }
1283
961
  /**
1284
962
  * 获取当前工具类型
@@ -1289,283 +967,246 @@ class CanvasCore extends CanvasState {
1289
967
  /**
1290
968
  * 设置当前工具类型(内部使用)
1291
969
  */
1292
- setToolType(type) {
1293
- this.selectNode();
1294
- this._updateState(
970
+ setToolType(t) {
971
+ this._selectNodes(), this._updateState(
1295
972
  {
1296
- toolType: type
973
+ toolType: t
1297
974
  },
1298
- false
1299
- );
1300
- this.emit("toolType:change", type);
1301
- if (type === "hand") {
1302
- __privateGet(this, _canvasStage).setDraggable(true);
1303
- __privateGet(this, _canvasStage).setCursor("grab");
1304
- } else {
1305
- __privateGet(this, _canvasStage).setDraggable(false);
1306
- __privateGet(this, _canvasStage).resetCursor();
1307
- }
975
+ !1
976
+ ), this._emit("toolType:change", t), t === "hand" ? (e(this, I).setDraggable(!0), e(this, I).setCursor("grab")) : (e(this, I).setDraggable(!1), e(this, I).resetCursor());
977
+ }
978
+ /**
979
+ * 根据 ID 获取 Canvas 节点实例
980
+ */
981
+ getCanvasNodeById(t) {
982
+ return e(this, F).get(t) || null;
1308
983
  }
1309
984
  /**
1310
985
  * 设置是否可拖拽(内部使用)
1311
986
  */
1312
- setDraggable(draggable) {
1313
- __privateGet(this, _canvasStage).setDraggable(draggable);
987
+ setDraggable(t) {
988
+ e(this, I).setDraggable(t);
1314
989
  }
1315
990
  /**
1316
991
  * 设置光标
1317
992
  * @internal 仅供内部使用
1318
993
  */
1319
- setCursor(cursor) {
1320
- __privateGet(this, _canvasStage).setCursor(cursor);
994
+ _setCursor(t) {
995
+ e(this, I).setCursor(t);
1321
996
  }
1322
997
  /**
1323
998
  * 重置光标
1324
999
  * @internal 仅供内部使用
1325
1000
  */
1326
- resetCursor() {
1327
- __privateGet(this, _canvasStage).resetCursor();
1001
+ _resetCursor() {
1002
+ e(this, I).resetCursor();
1328
1003
  }
1329
1004
  /**
1330
1005
  * 获取当前 Stage 缩放比例
1331
1006
  */
1332
1007
  getStageScale() {
1333
- return __privateGet(this, _canvasStage).getStage().scaleX();
1008
+ return e(this, I).getStage().scaleX();
1334
1009
  }
1335
1010
  /**
1336
1011
  * 更新视口位置
1337
1012
  * @internal 仅供内部使用,外部请使用 CanvasApi
1338
1013
  */
1339
- updateViewport(viewport, addToHistory = false) {
1340
- __privateGet(this, _canvasStage).setViewport(viewport);
1341
- const oldViewport = this.getState().viewport;
1342
- const newViewport = {
1343
- ...oldViewport,
1344
- ...viewport
1014
+ _updateViewport(t, i = !1) {
1015
+ e(this, I).setViewport(t);
1016
+ const n = this.getState().viewport, r = {
1017
+ ...n,
1018
+ ...t
1345
1019
  };
1346
1020
  this._updateState(
1347
1021
  {
1348
- viewport: newViewport
1022
+ viewport: r
1349
1023
  },
1350
- addToHistory
1351
- );
1352
- this.emit("viewport:change", newViewport);
1353
- if (oldViewport.scale !== newViewport.scale) {
1354
- this.emit("viewport:scale:change", newViewport.scale);
1355
- }
1356
- __privateGet(this, _canvasTransformer).emitPositionChange();
1024
+ i
1025
+ ), this._emit("viewport:change", r), n.scale !== r.scale && this._emit("viewport:scale:change", r.scale), e(this, W).emitPositionChange();
1357
1026
  }
1358
- createNodes(nodes) {
1359
- const canvasNodes = nodes.map((node) => createCanvasNodeByType(this, node.type, node, false)).filter((node) => node !== null);
1360
- canvasNodes.forEach((node) => {
1361
- __privateGet(this, _mainLayer).add(node.getElement());
1362
- });
1363
- const newNodes = [...this.getState().nodes || [], ...nodes];
1364
- this._updateState(
1365
- {
1366
- nodes: newNodes
1367
- },
1368
- true
1369
- );
1370
- this.emit("nodes:created", nodes);
1027
+ createNodes(t, i) {
1028
+ const n = t.map((r) => te(this, r.$_type, r, !1)).filter((r) => r !== null);
1029
+ n.forEach((r) => {
1030
+ e(this, U).add(r.getElement());
1031
+ }), b(this, O, Ut).call(this, n, i), this._emit("nodes:created", t);
1371
1032
  }
1372
1033
  /**
1373
1034
  * 创建图片标注节点(内部使用)
1374
1035
  */
1375
- createImageMarkerNode(parentImageId, startPosition, endPosition, imageBounds) {
1376
- const nodes = this.getState().nodes || [];
1377
- let maxMarkerNumber = 0;
1378
- nodes.forEach((node) => {
1379
- if (node.type === "image-marker" && node.meta.parent === parentImageId && typeof node.meta.markerNumber === "number") {
1380
- maxMarkerNumber = Math.max(maxMarkerNumber, node.meta.markerNumber);
1381
- }
1036
+ createImageMarkerNode(t, i, n, r) {
1037
+ const a = this.getState().nodes || [];
1038
+ let h = 0;
1039
+ a.forEach((E) => {
1040
+ E.$_type === "image-marker" && typeof E.$_markerNumber == "number" && (h = Math.max(h, E.$_markerNumber));
1382
1041
  });
1383
- const startPercentX = (startPosition.x - imageBounds.x) / imageBounds.width * 100;
1384
- const startPercentY = (startPosition.y - imageBounds.y) / imageBounds.height * 100;
1385
- const endPercentX = (endPosition.x - imageBounds.x) / imageBounds.width * 100;
1386
- const endPercentY = (endPosition.y - imageBounds.y) / imageBounds.height * 100;
1387
- const x = Math.min(startPosition.x, endPosition.x);
1388
- const y = Math.min(startPosition.y, endPosition.y);
1389
- const width = Math.abs(endPosition.x - startPosition.x);
1390
- const height = Math.abs(endPosition.y - startPosition.y);
1391
- const markerNode = {
1392
- id: v4(),
1393
- type: "image-marker",
1394
- props: {
1395
- x,
1396
- y,
1397
- width,
1398
- height,
1399
- rotation: 0,
1400
- visible: true
1401
- },
1402
- style: {
1403
- color: "#F44336",
1404
- line: "dashed",
1405
- size: "medium",
1406
- opacity: 1
1407
- },
1408
- meta: {
1409
- parent: parentImageId,
1410
- markerNumber: maxMarkerNumber + 1,
1411
- relativePosition: {
1412
- start: {
1413
- percentX: Math.max(0, Math.min(100, startPercentX)),
1414
- percentY: Math.max(0, Math.min(100, startPercentY))
1415
- },
1416
- end: {
1417
- percentX: Math.max(0, Math.min(100, endPercentX)),
1418
- percentY: Math.max(0, Math.min(100, endPercentY))
1419
- }
1042
+ const c = (i.x - r.x) / r.width, g = (i.y - r.y) / r.height, m = (n.x - r.x) / r.width, f = (n.y - r.y) / r.height, u = Math.min(i.x, n.x), x = Math.min(i.y, n.y), v = Math.abs(n.x - i.x), M = Math.abs(n.y - i.y), _ = {
1043
+ id: pt(),
1044
+ $_type: "image-marker",
1045
+ x: u,
1046
+ y: x,
1047
+ width: v,
1048
+ height: M,
1049
+ visible: !0,
1050
+ line: "dashed",
1051
+ $_parentId: t,
1052
+ $_markerNumber: h + 1,
1053
+ $_relativeBox: {
1054
+ start: {
1055
+ ratioX: Math.max(0, Math.min(1, c)),
1056
+ ratioY: Math.max(0, Math.min(1, g))
1057
+ },
1058
+ end: {
1059
+ ratioX: Math.max(0, Math.min(1, m)),
1060
+ ratioY: Math.max(0, Math.min(1, f))
1420
1061
  }
1421
1062
  }
1422
1063
  };
1423
- this.createNodes([markerNode]);
1064
+ this.createNodes([_], !0);
1424
1065
  }
1425
1066
  /**
1426
1067
  * 在指定位置查找图片节点
1427
1068
  * @internal 仅供内部使用
1428
1069
  */
1429
- findImageAtPosition(position) {
1430
- const layer = __privateGet(this, _mainLayer);
1431
- const shapes = layer.getChildren();
1432
- const filteredShapes = shapes.filter(
1433
- (shape) => !shape.name().includes("imageMarker")
1434
- );
1435
- const sortedShapes = filteredShapes.slice().sort((a, b) => b.zIndex() - a.zIndex());
1436
- for (const shape of sortedShapes) {
1437
- const x = shape.x();
1438
- const y = shape.y();
1439
- const width = shape.width();
1440
- const height = shape.height();
1441
- if (position.x >= x && position.x <= x + width && position.y >= y && position.y <= y + height) {
1442
- if (shape.getClassName() === "Image") {
1443
- return shape;
1444
- }
1445
- return null;
1446
- }
1070
+ _findImageAtPosition(t) {
1071
+ const a = e(this, U).getChildren().filter(
1072
+ (h) => !h.name().includes("imageMarker")
1073
+ ).slice().sort((h, c) => c.zIndex() - h.zIndex());
1074
+ for (const h of a) {
1075
+ const c = h.x(), g = h.y(), m = h.width(), f = h.height();
1076
+ if (t.x >= c && t.x <= c + m && t.y >= g && t.y <= g + f)
1077
+ return h.getClassName() === "Image" ? h : null;
1447
1078
  }
1448
1079
  return null;
1449
1080
  }
1450
1081
  /**
1451
1082
  * @internal 仅供内部使用
1452
1083
  */
1453
- createDraftNode(type, position, meta) {
1454
- if (__privateGet(this, _draftNode)) {
1455
- __privateGet(this, _draftNode).destroy();
1456
- }
1457
- const node = createNodeByType(type, position, void 0, meta);
1458
- __privateSet(this, _draftNode, createCanvasNodeByType(this, type, node, true));
1459
- if (!__privateGet(this, _draftNode)) return;
1460
- __privateGet(this, _mainLayer).add(__privateGet(this, _draftNode).getElement());
1084
+ _setDrawingPosition(t) {
1085
+ l(this, P, [t, t]);
1461
1086
  }
1462
1087
  /**
1463
1088
  * @internal 仅供内部使用
1464
1089
  */
1465
- updateDraftNode(position) {
1466
- if (!__privateGet(this, _draftNode)) return;
1467
- const node = __privateGet(this, _draftNode).getNode();
1468
- const updatedNode = updateNodeByType(node, position);
1469
- __privateGet(this, _draftNode).updateNode(updatedNode);
1090
+ _updateDrawingPosition(t) {
1091
+ e(this, P) && (e(this, P)[1] = t);
1470
1092
  }
1471
1093
  /**
1472
1094
  * @internal 仅供内部使用
1473
1095
  */
1474
- finalizeDraftNode() {
1475
- if (!__privateGet(this, _draftNode)) return;
1476
- const id = v4();
1477
- const draftNode = __privateGet(this, _draftNode).getNode();
1478
- if (draftNode.type === "image-marker" && draftNode.meta.parent) {
1479
- const bounds = draftNode.meta.bounds;
1480
- const startPosition = draftNode.meta.startPosition;
1481
- const endPosition = {
1482
- x: draftNode.props.x + (draftNode.props.width || 0),
1483
- y: draftNode.props.y + (draftNode.props.height || 0)
1484
- };
1485
- const nodes = this.getState().nodes || [];
1486
- let maxMarkerNumber = 0;
1487
- nodes.forEach((node3) => {
1488
- if (node3.type === "image-marker" && node3.meta.parent === draftNode.meta.parent && typeof node3.meta.markerNumber === "number") {
1489
- maxMarkerNumber = Math.max(maxMarkerNumber, node3.meta.markerNumber);
1490
- }
1096
+ _createDraftNode(t, i) {
1097
+ e(this, C) && e(this, C).destroy();
1098
+ const n = We(t, e(this, P)[0], i);
1099
+ l(this, C, te(this, t, n, !0)), e(this, C) && e(this, U).add(e(this, C).getElement());
1100
+ }
1101
+ /**
1102
+ * @internal 仅供内部使用
1103
+ */
1104
+ _updateDraftNode() {
1105
+ if (!e(this, C)) return;
1106
+ const t = e(this, C).getConfig(), i = Ve(
1107
+ t,
1108
+ e(this, P)[1],
1109
+ e(this, P)[0]
1110
+ );
1111
+ e(this, C).updateNode(i);
1112
+ }
1113
+ /**
1114
+ * @internal 仅供内部使用
1115
+ */
1116
+ _finalizeDraftNode() {
1117
+ if (!e(this, C)) return;
1118
+ const t = pt(), i = e(this, C).getConfig();
1119
+ if (i.$_type === "image-marker" && i.$_parentId) {
1120
+ const r = i.$_bounds, a = e(this, P)[0], h = {
1121
+ x: i.x + (i.width || 0),
1122
+ y: i.y + (i.height || 0)
1123
+ }, [c, g] = Xt(a, h), m = this.getState().nodes || [];
1124
+ let f = 0;
1125
+ m.forEach((E) => {
1126
+ E.$_type === "image-marker" && E.$_parentId === i.$_parentId && typeof E.$_markerNumber == "number" && (f = Math.max(f, E.$_markerNumber));
1491
1127
  });
1492
- const startPercentX = (startPosition.x - bounds.x) / bounds.width * 100;
1493
- const startPercentY = (startPosition.y - bounds.y) / bounds.height * 100;
1494
- const endPercentX = (endPosition.x - bounds.x) / bounds.width * 100;
1495
- const endPercentY = (endPosition.y - bounds.y) / bounds.height * 100;
1496
- const node2 = {
1497
- ...draftNode,
1498
- props: {
1499
- ...draftNode.props
1500
- },
1501
- style: {
1502
- ...draftNode.style
1503
- },
1504
- meta: {
1505
- parent: draftNode.meta.parent,
1506
- markerNumber: maxMarkerNumber + 1,
1507
- relativePosition: {
1508
- start: {
1509
- percentX: Math.max(0, Math.min(100, startPercentX)),
1510
- percentY: Math.max(0, Math.min(100, startPercentY))
1511
- },
1512
- end: {
1513
- percentX: Math.max(0, Math.min(100, endPercentX)),
1514
- percentY: Math.max(0, Math.min(100, endPercentY))
1515
- }
1128
+ const u = (c.x - r.x) / r.width, x = (c.y - r.y) / r.height, v = (g.x - r.x) / r.width, M = (g.y - r.y) / r.height, _ = {
1129
+ ...i,
1130
+ $_markerNumber: f + 1,
1131
+ $_relativeBox: {
1132
+ start: {
1133
+ ratioX: Math.max(0, Math.min(1, u)),
1134
+ ratioY: Math.max(0, Math.min(1, x))
1135
+ },
1136
+ end: {
1137
+ ratioX: Math.max(0, Math.min(1, v)),
1138
+ ratioY: Math.max(0, Math.min(1, M))
1516
1139
  }
1517
1140
  },
1518
- id,
1519
- type: "image-marker"
1141
+ $_type: "image-marker",
1142
+ id: t
1520
1143
  };
1521
- this.createNodes([node2]);
1522
- __privateGet(this, _draftNode).destroy();
1523
- __privateSet(this, _draftNode, null);
1524
- this.setToolType("select");
1144
+ this.createNodes([_], !0), e(this, C).destroy(), l(this, C, null), this.setToolType("select");
1525
1145
  return;
1526
1146
  }
1527
- const node = {
1528
- ...draftNode,
1529
- props: {
1530
- ...draftNode.props
1531
- },
1532
- style: {
1533
- ...draftNode.style
1534
- },
1535
- meta: {
1536
- ...draftNode.meta
1537
- },
1538
- id
1147
+ const n = {
1148
+ ...i,
1149
+ id: t
1539
1150
  };
1540
- this.createNodes([node]);
1541
- __privateGet(this, _draftNode).destroy();
1542
- __privateSet(this, _draftNode, null);
1543
- this.setToolType("select");
1151
+ this.createNodes([n], !0), e(this, C).destroy(), l(this, C, null), this.setToolType("select");
1152
+ }
1153
+ /**
1154
+ * @internal 仅供内部使用
1155
+ */
1156
+ _createSelectRect() {
1157
+ e(this, Z) && e(this, Z).destroy(), l(this, Z, new D.Rect({
1158
+ x: e(this, P)[0].x,
1159
+ y: e(this, P)[0].y,
1160
+ width: 0,
1161
+ height: 0,
1162
+ stroke: this.getTheme()["theme.select-rect-border"],
1163
+ strokeWidth: 1,
1164
+ fill: this.getTheme()["theme.select-rect-fill"]
1165
+ })), e(this, U).add(e(this, Z));
1166
+ }
1167
+ /*
1168
+ * @internal 仅供内部使用
1169
+ */
1170
+ _updateSelectRect() {
1171
+ if (!e(this, Z)) return;
1172
+ const [t, i] = Xt(...e(this, P));
1173
+ e(this, Z).setAttrs({
1174
+ x: t.x,
1175
+ y: t.y,
1176
+ width: i.x - t.x,
1177
+ height: i.y - t.y
1178
+ });
1179
+ const n = e(this, Z).getClientRect(), a = e(this, U).find(`.${A.selectable}`).filter((h) => {
1180
+ const c = h.getClientRect();
1181
+ return D.Util.haveIntersection(n, c);
1182
+ });
1183
+ this._selectNodes(
1184
+ a.length > 0 ? a.map((h) => h.id()) : void 0,
1185
+ !1
1186
+ );
1187
+ }
1188
+ /**
1189
+ * @internal 仅供内部使用
1190
+ */
1191
+ _finalizeSelectRect() {
1192
+ e(this, Z) && (e(this, Z).destroy(), l(this, Z, null));
1544
1193
  }
1545
1194
  /**
1546
1195
  * 选择节点
1547
1196
  * @internal 仅供内部使用,外部请使用 CanvasApi
1548
1197
  */
1549
- selectNode(nodeId, multiSelect = false) {
1550
- const curSelectedNodeIds = this.getState().selectedNodeIds ?? [];
1551
- let selectedNodeIds = [];
1552
- if (nodeId) {
1553
- if (multiSelect && curSelectedNodeIds.length > 0) {
1554
- selectedNodeIds = [...curSelectedNodeIds, nodeId];
1555
- } else {
1556
- selectedNodeIds = [nodeId];
1198
+ _selectNodes(t, i = !1) {
1199
+ const n = this.getState().selectedNodeIds ?? [];
1200
+ let r = [];
1201
+ if (t?.length && (i && n.length > 0 ? r = [...n, ...t] : r = [...t]), !Le(n, r)) {
1202
+ if (r.length === 0)
1203
+ e(this, W).clearNodes();
1204
+ else {
1205
+ const a = this.getStage().find(`.${A.selectable}`).filter((h) => r.includes(h.id()));
1206
+ e(this, W).setNodes(a);
1557
1207
  }
1558
- } else if (curSelectedNodeIds.length === 0) {
1559
- return;
1560
- }
1561
- if (selectedNodeIds.length === 0) {
1562
- __privateGet(this, _canvasTransformer).clearNodes();
1563
- } else {
1564
- const nodes = this.getStage().find(`.${NODE_NAMES.selectable}`).filter((node) => selectedNodeIds.includes(node.id()));
1565
- __privateGet(this, _canvasTransformer).setNodes(nodes);
1208
+ this._updateState({ selectedNodeIds: r }, !1), this._emit("nodes:selected", r);
1566
1209
  }
1567
- this._updateState({ selectedNodeIds }, false);
1568
- this.emit("nodes:selected", selectedNodeIds);
1569
1210
  }
1570
1211
  /**
1571
1212
  * 删除指定的节点(内部使用)
@@ -1574,119 +1215,117 @@ class CanvasCore extends CanvasState {
1574
1215
  * @param nodeIds - 要删除的节点 ID 数组
1575
1216
  * @returns 被删除的节点数据数组
1576
1217
  */
1577
- deleteNodes(nodeIds) {
1578
- if (nodeIds.length === 0) return [];
1579
- const nodes = this.getState().nodes || [];
1580
- const idsToDelete = new Set(nodeIds);
1581
- nodeIds.forEach((id) => {
1582
- const node = nodes.find((n) => n.id === id);
1583
- if (node?.type === "image") {
1584
- nodes.forEach((n) => {
1585
- if (n.type === "image-marker" && n.meta.parent === id) {
1586
- idsToDelete.add(n.id);
1587
- }
1588
- });
1589
- }
1590
- });
1591
- const deletedNodes = nodes.filter((n) => idsToDelete.has(n.id));
1592
- idsToDelete.forEach((id) => {
1593
- const shape = this.getStage().findOne(`#${id}`);
1594
- if (shape) {
1595
- shape.destroy();
1596
- }
1218
+ deleteNodes(t) {
1219
+ if (t.length === 0) return [];
1220
+ const i = this.getState().nodes || [], n = new Set(t);
1221
+ t.forEach((a) => {
1222
+ i.find((c) => c.id === a)?.$_type === "image" && i.forEach((c) => {
1223
+ c.$_type === "image-marker" && c.$_parentId === a && n.add(c.id);
1224
+ });
1597
1225
  });
1598
- const newNodes = nodes.filter((n) => !idsToDelete.has(n.id));
1599
- __privateGet(this, _canvasTransformer).clearNodes();
1600
- this._updateState(
1226
+ const r = i.filter((a) => n.has(a.id));
1227
+ return n.forEach((a) => {
1228
+ const h = this.getStage().findOne(`#${a}`);
1229
+ h && h.destroy();
1230
+ }), b(this, O, le).call(this, Array.from(n), !0), e(this, W).clearNodes(), this._updateState(
1601
1231
  {
1602
- nodes: newNodes,
1603
1232
  selectedNodeIds: []
1604
1233
  },
1605
- true
1606
- );
1607
- this.emit("nodes:deleted", deletedNodes);
1608
- return deletedNodes;
1234
+ !0
1235
+ ), this._emit("nodes:deleted", r), r;
1609
1236
  }
1610
1237
  /**
1611
1238
  * 删除选中的节点(内部使用)
1612
1239
  * @internal 仅供内部使用,外部请使用 CanvasApi
1613
1240
  */
1614
1241
  deleteSelectedNodes() {
1615
- const selectedNodeIds = this.getState().selectedNodeIds || [];
1616
- if (selectedNodeIds.length === 0) return;
1617
- this.deleteNodes(selectedNodeIds);
1242
+ const t = this.getState().selectedNodeIds || [];
1243
+ t.length !== 0 && this.deleteNodes(t);
1618
1244
  }
1619
1245
  /**
1620
1246
  * 销毁 canvas
1621
1247
  */
1622
1248
  dispose() {
1623
- __privateGet(this, _container).removeEventListener("keydown", __privateGet(this, _handleKeyDown));
1624
- this.getCanvasTransformer().destroy();
1625
- this.getMainLayer().destroy();
1626
- this.getCanvasStage().destroy();
1627
- this._dispose();
1628
- }
1629
- /**
1630
- * 从元素同步节点数据(供节点类内部使用)
1631
- */
1632
- _syncNodeFromElement(nodeId, updates) {
1633
- const nodes = this.getState().nodes || [];
1634
- const nodeIndex = nodes.findIndex((n) => n.id === nodeId);
1635
- if (nodeIndex === -1) return;
1636
- const updatedNode = {
1637
- ...nodes[nodeIndex],
1638
- ...updates,
1639
- props: {
1640
- ...nodes[nodeIndex].props,
1641
- ...updates.props
1642
- },
1643
- style: {
1644
- ...nodes[nodeIndex].style,
1645
- ...updates.style
1646
- },
1647
- meta: {
1648
- ...nodes[nodeIndex].meta,
1649
- ...updates.meta
1650
- }
1651
- };
1652
- const newNodes = [...nodes];
1653
- newNodes[nodeIndex] = updatedNode;
1654
- this._updateState(
1655
- {
1656
- nodes: newNodes
1657
- },
1658
- true
1659
- );
1249
+ e(this, j).removeEventListener("keydown", e(this, ut)), e(this, J) && (e(this, J).disconnect(), l(this, J, null)), this.getCanvasTransformer().destroy(), this.getMainLayer().destroy(), this.getCanvasStage().destroy(), this._dispose();
1250
+ }
1251
+ /**
1252
+ * @internal 仅供内部使用
1253
+ * 在元素节点改变后(例如 tranfromEnd dragEnd)重建 state.nodes
1254
+ */
1255
+ _rebuildStateAfterNodeChange(t, i) {
1256
+ b(this, O, Ut).call(this, Array.isArray(t) ? t : [t], i);
1660
1257
  }
1661
1258
  /**
1662
1259
  * 实现父类的状态同步方法
1663
1260
  * 当 undo/redo 时被调用
1664
1261
  */
1665
- _syncState(state) {
1666
- __privateGet(this, _canvasStage).setViewport({
1667
- x: state.viewport.x,
1668
- y: state.viewport.y,
1669
- scale: state.viewport.scale,
1670
- width: state.viewport.width,
1671
- height: state.viewport.height
1672
- });
1262
+ _renderCanvas(t) {
1263
+ this._updateViewport(
1264
+ {
1265
+ x: t.viewport.x,
1266
+ y: t.viewport.y,
1267
+ scale: t.viewport.scale
1268
+ },
1269
+ !1
1270
+ ), e(this, F).forEach((n, r) => {
1271
+ n.destroy();
1272
+ }), e(this, F).clear(), this.createNodes(t.nodes || [], !1);
1273
+ const i = t.selectedNodeIds || [];
1274
+ if (i.length === 0)
1275
+ e(this, W).clearNodes();
1276
+ else {
1277
+ const n = this.getStage().find(`.${A.selectable}`).filter((r) => i.includes(r.id()));
1278
+ e(this, W).setNodes(n);
1279
+ }
1673
1280
  }
1674
- }
1675
- _canvasStage = new WeakMap();
1676
- _mainLayer = new WeakMap();
1677
- _canvasTransformer = new WeakMap();
1678
- _draftNode = new WeakMap();
1679
- _container = new WeakMap();
1680
- _handleKeyDown = new WeakMap();
1681
- _CanvasCore_instances = new WeakSet();
1682
- /**
1281
+ };
1282
+ mt = new WeakMap(), I = new WeakMap(), U = new WeakMap(), W = new WeakMap(), C = new WeakMap(), j = new WeakMap(), Z = new WeakMap(), P = new WeakMap(), F = new WeakMap(), J = new WeakMap(), ut = new WeakMap(), O = new WeakSet(), /**
1683
1283
  * 设置键盘事件监听
1684
1284
  */
1685
- setupKeyboardEvents_fn = function() {
1686
- __privateGet(this, _container).tabIndex = 0;
1687
- __privateGet(this, _container).addEventListener("keydown", __privateGet(this, _handleKeyDown));
1688
- };
1689
- class CanvasApi extends CanvasCore {
1285
+ ce = function() {
1286
+ e(this, j).tabIndex = 0, e(this, j).addEventListener("keydown", e(this, ut));
1287
+ }, /**
1288
+ * 设置尺寸变化监听
1289
+ */
1290
+ de = function() {
1291
+ l(this, J, new ResizeObserver((t) => {
1292
+ for (const i of t) {
1293
+ const { width: n, height: r } = i.contentRect, a = this.getStage(), h = this.getState().viewport, c = a.width(), g = a.height(), m = h.x + c / 2, f = h.y + g / 2;
1294
+ a.width(n), a.height(r);
1295
+ const u = m - n / 2, x = f - r / 2;
1296
+ this._updateViewport(
1297
+ {
1298
+ x: u,
1299
+ y: x
1300
+ },
1301
+ !1
1302
+ );
1303
+ }
1304
+ })), e(this, J).observe(e(this, j));
1305
+ }, /**
1306
+ * 根据canvas节点映射重建 state.nodes
1307
+ */
1308
+ Pt = function(t) {
1309
+ const i = {
1310
+ nodes: Array.from(e(this, F).values()).map((n) => n.getConfig())
1311
+ };
1312
+ this._updateState(i, t);
1313
+ }, /**
1314
+ * 更新 state.nodes
1315
+ */
1316
+ Ut = function(t, i) {
1317
+ t.forEach((n) => {
1318
+ e(this, F).set(n.getID(), n);
1319
+ }), t.length !== 0 && b(this, O, Pt).call(this, i);
1320
+ }, le = function(t, i = !1) {
1321
+ t.forEach((n) => {
1322
+ const r = e(this, F).get(n);
1323
+ r && r.destroy(), e(this, F).delete(n);
1324
+ }), t.length !== 0 && b(this, O, Pt).call(this, i);
1325
+ }, /** 全局注册的主题 */
1326
+ d(at, mt, null);
1327
+ let Zt = at;
1328
+ class Be extends Zt {
1690
1329
  /**
1691
1330
  * 获取所有可用的工具类型
1692
1331
  */
@@ -1696,76 +1335,57 @@ class CanvasApi extends CanvasCore {
1696
1335
  /**
1697
1336
  * 设置当前工具类型
1698
1337
  */
1699
- setToolType(type) {
1700
- super.setToolType(type);
1338
+ setToolType(s) {
1339
+ super.setToolType(s);
1701
1340
  }
1702
1341
  /**
1703
1342
  * 手动创建多个节点
1704
1343
  * 如果你不知道自己在干什么,请使用更高层的封装方法,如 createImageNode
1705
1344
  */
1706
- createNodes(nodes) {
1707
- super.createNodes(nodes);
1345
+ createNodes(s, t) {
1346
+ super.createNodes(s, t);
1708
1347
  }
1709
1348
  /**
1710
1349
  * 根据 ID 获取节点
1711
1350
  */
1712
- getNodeById(id) {
1713
- const nodes = this.getState().nodes || [];
1714
- const node = nodes.find((n) => n.id === id);
1715
- return node || null;
1351
+ getNodeById(s) {
1352
+ return (this.getState().nodes || []).find((n) => n.id === s) || null;
1716
1353
  }
1717
1354
  /**
1718
1355
  * 更新视口位置
1719
1356
  */
1720
- updateViewport(viewport, addToHistory = false) {
1721
- super.updateViewport(viewport, addToHistory);
1357
+ updateViewport(s, t = !1) {
1358
+ super._updateViewport(s, t);
1722
1359
  }
1723
1360
  /**
1724
1361
  * 创建图片节点
1725
1362
  */
1726
- createImageNode(imageUrl, position) {
1727
- const pos = position ?? { x: 100, y: 100 };
1728
- const imageNode = {
1729
- id: v4(),
1730
- type: "image",
1731
- props: {
1732
- x: pos.x,
1733
- y: pos.y,
1734
- width: void 0,
1735
- height: void 0,
1736
- rotation: 0,
1737
- visible: true
1738
- },
1739
- style: {
1740
- color: "#000000",
1741
- line: "solid",
1742
- size: "medium",
1743
- opacity: 1
1744
- },
1745
- meta: {
1746
- imageUrl
1747
- }
1363
+ createImageNode(s, t) {
1364
+ const i = t ?? { x: 100, y: 100 }, n = {
1365
+ id: pt(),
1366
+ $_type: "image",
1367
+ x: i.x,
1368
+ y: i.y,
1369
+ $_imageUrl: s
1748
1370
  };
1749
- this.createNodes([imageNode]);
1371
+ this.createNodes([n], !0);
1750
1372
  }
1751
1373
  /**
1752
1374
  * 导出全部图形为图片
1753
1375
  * @param options - 导出配置
1754
1376
  * @returns DataURL 格式的图片数据
1755
1377
  */
1756
- exportAsImage(options) {
1757
- const stage = this.getStage();
1758
- const transformer = this.getCanvasTransformer().getTransformer();
1759
- const transformerVisible = transformer.visible();
1760
- transformer.visible(false);
1378
+ exportAsImage(s) {
1379
+ const t = this.getStage(), i = this.getCanvasTransformer().getTransformer(), n = i.visible();
1380
+ i.visible(!1);
1761
1381
  try {
1762
- return stage.toDataURL({
1763
- pixelRatio: options?.pixelRatio ?? 2,
1764
- mimeType: options?.mimeType ?? "image/png",
1765
- quality: options?.quality ?? 1
1382
+ return t.toDataURL({
1383
+ pixelRatio: s?.pixelRatio ?? 2,
1384
+ mimeType: s?.mimeType ?? "image/png",
1385
+ quality: s?.quality ?? 1
1766
1386
  });
1767
1387
  } finally {
1768
- transformer.visible(transformerVisible);
1388
+ i.visible(n);
1769
1389
  }
1770
1390
  }
1771
1391
  /**
@@ -1773,107 +1393,75 @@ class CanvasApi extends CanvasCore {
1773
1393
  * @param options - 导出配置
1774
1394
  * @returns DataURL 格式的图片数据,如果没有选区则返回 null
1775
1395
  */
1776
- exportSelectionAsImage(options) {
1777
- const selectedNodeIds = this.getState().selectedNodeIds || [];
1778
- if (selectedNodeIds.length === 0) {
1779
- console.warn("No selection to export");
1780
- return null;
1781
- }
1782
- const padding = options?.padding ?? 0;
1783
- const tempGroup = new Konva.Group();
1784
- selectedNodeIds.forEach((id) => {
1785
- const shape = this.getStage().findOne(`#${id}`);
1786
- if (shape) {
1787
- const clone = shape.clone();
1788
- tempGroup.add(clone);
1396
+ exportSelectionAsImage(s) {
1397
+ const t = this.getState().selectedNodeIds || [];
1398
+ if (t.length === 0)
1399
+ return console.warn("No selection to export"), null;
1400
+ const i = s?.padding ?? 0, n = new D.Group();
1401
+ t.forEach((h) => {
1402
+ const c = this.getStage().findOne(`#${h}`);
1403
+ if (c) {
1404
+ const g = c.clone();
1405
+ n.add(g);
1789
1406
  }
1790
1407
  });
1791
- const box = tempGroup.getClientRect();
1792
- const dataURL = tempGroup.toDataURL({
1793
- x: box.x - padding,
1794
- y: box.y - padding,
1795
- width: box.width + padding * 2,
1796
- height: box.height + padding * 2,
1797
- pixelRatio: options?.pixelRatio ?? 2,
1798
- mimeType: options?.mimeType ?? "image/png",
1799
- quality: options?.quality ?? 1
1408
+ const r = n.getClientRect(), a = n.toDataURL({
1409
+ x: r.x - i,
1410
+ y: r.y - i,
1411
+ width: r.width + i * 2,
1412
+ height: r.height + i * 2,
1413
+ pixelRatio: s?.pixelRatio ?? 2,
1414
+ mimeType: s?.mimeType ?? "image/png",
1415
+ quality: s?.quality ?? 1
1800
1416
  });
1801
- tempGroup.destroy();
1802
- return dataURL;
1417
+ return n.destroy(), a;
1803
1418
  }
1804
1419
  /**
1805
1420
  * 导出带有标注的图片节点为图片
1806
1421
  * @param id - 图片节点 ID
1807
1422
  * @returns DataURL 格式的图片数据,如果节点或者 marker 不存在则返回 null
1808
1423
  */
1809
- exportImageWithMarker(id, options) {
1810
- const imageShape = this.getStage().findOne(`#${id}`);
1811
- if (!imageShape) {
1812
- console.warn("Image shape not found on stage");
1813
- return null;
1814
- }
1815
- const nodes = this.getState().nodes || [];
1816
- const markerNodes = nodes.filter(
1817
- (n) => n.type === "image-marker" && n.meta.parent === id
1424
+ exportImageWithMarker(s, t) {
1425
+ const i = this.getStage().findOne(`#${s}`);
1426
+ if (!i)
1427
+ return console.warn("Image shape not found on stage"), null;
1428
+ const r = (this.getState().nodes || []).filter(
1429
+ (m) => m.$_type === "image-marker" && m.$_parentId === s
1818
1430
  );
1819
- if (markerNodes.length === 0) {
1820
- console.warn("No image-marker nodes found for the given image ID");
1821
- return null;
1822
- }
1823
- const tempGroup = new Konva.Group();
1824
- const imageClone = imageShape.clone();
1825
- tempGroup.add(imageClone);
1826
- markerNodes.forEach((markerNode) => {
1827
- const markerShape = this.getStage().findOne(`#${markerNode.id}`);
1828
- if (markerShape) {
1829
- const markerClone = markerShape.clone();
1830
- const rect = markerClone.findOne(".rect");
1831
- const markerGroup = markerClone.findOne(".marker-group");
1832
- if (rect) {
1833
- rect.strokeWidth(3);
1834
- rect.dash([5, 5]);
1835
- rect.cornerRadius(6);
1431
+ if (r.length === 0)
1432
+ return console.warn("No image-marker nodes found for the given image ID"), null;
1433
+ const a = new D.Group(), h = i.clone();
1434
+ a.add(h), r.forEach((m) => {
1435
+ const f = this.getStage().findOne(`#${m.id}`);
1436
+ if (f) {
1437
+ const u = f.clone(), x = u.findOne(".rect"), v = u.findOne(".marker-group");
1438
+ if (x && (x.strokeWidth(3), x.dash([5, 5]), x.cornerRadius(6)), v) {
1439
+ const M = v.findOne("Circle"), _ = v.findOne("Text");
1440
+ M && (M.radius(14), M.strokeWidth(3)), _ && (_.x(-14), _.y(-14), _.width(28), _.height(28), _.fontSize(16));
1836
1441
  }
1837
- if (markerGroup) {
1838
- const circle = markerGroup.findOne("Circle");
1839
- const text = markerGroup.findOne("Text");
1840
- if (circle) {
1841
- circle.radius(14);
1842
- circle.strokeWidth(3);
1843
- }
1844
- if (text) {
1845
- const radius = 14;
1846
- text.x(-radius);
1847
- text.y(-radius);
1848
- text.width(radius * 2);
1849
- text.height(radius * 2);
1850
- text.fontSize(16);
1851
- }
1852
- }
1853
- tempGroup.add(markerClone);
1442
+ a.add(u);
1854
1443
  }
1855
1444
  });
1856
- const box = tempGroup.getClientRect();
1857
- console.log("Exporting image with markers, bounding box:", box);
1858
- const dataURL = tempGroup.toDataURL({
1859
- x: box.x,
1860
- y: box.y,
1861
- width: box.width,
1862
- height: box.height,
1863
- pixelRatio: options?.pixelRatio ?? 2,
1864
- mimeType: options?.mimeType ?? "image/png",
1865
- quality: options?.quality ?? 1
1445
+ const c = a.getClientRect();
1446
+ console.log("Exporting image with markers, bounding box:", c);
1447
+ const g = a.toDataURL({
1448
+ x: c.x,
1449
+ y: c.y,
1450
+ width: c.width,
1451
+ height: c.height,
1452
+ pixelRatio: t?.pixelRatio ?? 2,
1453
+ mimeType: t?.mimeType ?? "image/png",
1454
+ quality: t?.quality ?? 1
1866
1455
  });
1867
- tempGroup.destroy();
1868
- return dataURL;
1456
+ return a.destroy(), g;
1869
1457
  }
1870
1458
  /**
1871
1459
  * 删除当前选中的节点
1872
1460
  * 如果删除的是 image 节点,会同步删除所有关联的 image-marker
1873
1461
  */
1874
1462
  deleteSelectedNodes() {
1875
- const selectedNodeIds = this.getState().selectedNodeIds || [];
1876
- this.deleteNodes(selectedNodeIds);
1463
+ const s = this.getState().selectedNodeIds || [];
1464
+ this.deleteNodes(s);
1877
1465
  }
1878
1466
  /**
1879
1467
  * 删除指定的节点
@@ -1881,31 +1469,25 @@ class CanvasApi extends CanvasCore {
1881
1469
  * @param nodeIds - 要删除的节点 ID 数组
1882
1470
  * @returns 被删除的节点数据数组
1883
1471
  */
1884
- deleteNodes(nodeIds) {
1885
- return super.deleteNodes(nodeIds);
1472
+ deleteNodes(s) {
1473
+ return super.deleteNodes(s);
1886
1474
  }
1887
1475
  /**
1888
1476
  * 将节点移动到最上层
1889
1477
  */
1890
- moveNodesToTop(nodeIds) {
1891
- if (nodeIds.length === 0) return;
1892
- nodeIds.forEach((id) => {
1893
- const shape = this.getStage().findOne(`#${id}`);
1894
- if (shape) {
1895
- shape.moveToTop();
1896
- }
1478
+ moveNodesToTop(s) {
1479
+ s.length !== 0 && s.forEach((t) => {
1480
+ const i = this.getStage().findOne(`#${t}`);
1481
+ i && i.moveToTop();
1897
1482
  });
1898
1483
  }
1899
1484
  /**
1900
1485
  * 将节点移动到最下层
1901
1486
  */
1902
- moveNodesToBottom(nodeIds) {
1903
- if (nodeIds.length === 0) return;
1904
- nodeIds.forEach((id) => {
1905
- const shape = this.getStage().findOne(`#${id}`);
1906
- if (shape) {
1907
- shape.moveToBottom();
1908
- }
1487
+ moveNodesToBottom(s) {
1488
+ s.length !== 0 && s.forEach((t) => {
1489
+ const i = this.getStage().findOne(`#${t}`);
1490
+ i && i.moveToBottom();
1909
1491
  });
1910
1492
  }
1911
1493
  /**
@@ -1918,79 +1500,52 @@ class CanvasApi extends CanvasCore {
1918
1500
  * @param options.scale - 是否自动调整缩放以适应内容,默认 false
1919
1501
  * @param options.nodeIds - 要滚动到的节点 ID 数组
1920
1502
  */
1921
- scrollToContent(options) {
1922
- const nodes = this.getState().nodes || [];
1923
- if (nodes.length === 0) return;
1924
- const padding = options?.padding ?? 50;
1925
- const shouldScale = options?.scale === true;
1926
- const targetNodeIds = options?.nodeIds;
1927
- let minX = Infinity;
1928
- let minY = Infinity;
1929
- let maxX = -Infinity;
1930
- let maxY = -Infinity;
1931
- const mainLayer = this.getMainLayer();
1932
- const selectedNodeIds = this.getState().selectedNodeIds || [];
1933
- const hasTargetIds = targetNodeIds && targetNodeIds.length > 0;
1934
- const hasSelection = !hasTargetIds && selectedNodeIds.length > 0;
1935
- const idsToShow = hasTargetIds ? targetNodeIds : hasSelection ? selectedNodeIds : null;
1936
- mainLayer.children.forEach((child) => {
1937
- if (child.visible() && child.getClassName() !== "Transformer" && child.hasName(NODE_NAMES.selectable)) {
1938
- if (idsToShow) {
1939
- const id = child.id();
1940
- if (!idsToShow.includes(id)) return;
1941
- }
1942
- const attrs = child.getAttrs();
1943
- const x2 = attrs.x || 0;
1944
- const y2 = attrs.y || 0;
1945
- const width = attrs.width || 0;
1946
- const height = attrs.height || 0;
1947
- const rotation = attrs.rotation || 0;
1948
- if (rotation) {
1949
- const box = child.getClientRect({ skipTransform: false });
1950
- const stage = this.getStage();
1951
- const currentScale = stage.scaleX();
1952
- const currentX = stage.x();
1953
- const currentY = stage.y();
1954
- const worldMinX = (box.x - currentX) / currentScale;
1955
- const worldMinY = (box.y - currentY) / currentScale;
1956
- const worldMaxX = (box.x + box.width - currentX) / currentScale;
1957
- const worldMaxY = (box.y + box.height - currentY) / currentScale;
1958
- minX = Math.min(minX, worldMinX);
1959
- minY = Math.min(minY, worldMinY);
1960
- maxX = Math.max(maxX, worldMaxX);
1961
- maxY = Math.max(maxY, worldMaxY);
1962
- } else {
1963
- minX = Math.min(minX, x2);
1964
- minY = Math.min(minY, y2);
1965
- maxX = Math.max(maxX, x2 + width);
1966
- maxY = Math.max(maxY, y2 + height);
1503
+ scrollToContent(s) {
1504
+ if ((this.getState().nodes || []).length === 0) return;
1505
+ const i = s?.padding ?? 50, n = s?.scale === !0, r = s?.nodeIds;
1506
+ let a = 1 / 0, h = 1 / 0, c = -1 / 0, g = -1 / 0;
1507
+ const m = this.getMainLayer(), f = this.getState().selectedNodeIds || [], u = r && r.length > 0, x = !u && f.length > 0, v = u ? r : x ? f : null;
1508
+ if (m.children.forEach((Y) => {
1509
+ if (Y.visible() && Y.getClassName() !== "Transformer" && Y.hasName(A.selectable)) {
1510
+ if (v) {
1511
+ const K = Y.id();
1512
+ if (!v.includes(K)) return;
1967
1513
  }
1514
+ const Q = Y.getAttrs(), Ht = Q.x || 0, Gt = Q.y || 0, ge = Q.width || 0, me = Q.height || 0;
1515
+ if (Q.rotation || 0) {
1516
+ const K = Y.getClientRect({ skipTransform: !1 }), At = this.getStage(), ft = At.scaleX(), Kt = At.x(), qt = At.y(), ue = (K.x - Kt) / ft, fe = (K.y - qt) / ft, pe = (K.x + K.width - Kt) / ft, ye = (K.y + K.height - qt) / ft;
1517
+ a = Math.min(a, ue), h = Math.min(h, fe), c = Math.max(c, pe), g = Math.max(g, ye);
1518
+ } else
1519
+ a = Math.min(a, Ht), h = Math.min(h, Gt), c = Math.max(c, Ht + ge), g = Math.max(g, Gt + me);
1968
1520
  }
1969
- });
1970
- if (minX === Infinity || minY === Infinity) return;
1971
- const contentWidth = maxX - minX;
1972
- const contentHeight = maxY - minY;
1973
- const contentCenterX = minX + contentWidth / 2;
1974
- const contentCenterY = minY + contentHeight / 2;
1975
- const viewport = this.getState().viewport;
1976
- let newScale = viewport.scale;
1977
- if (shouldScale) {
1978
- const scaleX = (viewport.width - padding * 2) / contentWidth;
1979
- const scaleY = (viewport.height - padding * 2) / contentHeight;
1980
- newScale = Math.min(scaleX, scaleY, 1);
1521
+ }), a === 1 / 0 || h === 1 / 0) return;
1522
+ const M = c - a, _ = g - h, E = a + M / 2, Dt = h + _ / 2;
1523
+ let G = this.getState().viewport.scale;
1524
+ if (n) {
1525
+ const Y = (this.getStage().width() - i * 2) / M, Q = (this.getStage().height() - i * 2) / _;
1526
+ G = Math.min(Y, Q, 1);
1981
1527
  }
1982
- const x = viewport.width / 2 - contentCenterX * newScale;
1983
- const y = viewport.height / 2 - contentCenterY * newScale;
1984
- this.updateViewport({ x, y, scale: newScale }, true);
1528
+ const rt = this.getStage().width() / 2 - E * G, Ft = this.getStage().height() / 2 - Dt * G;
1529
+ this.updateViewport({ x: rt, y: Ft, scale: G }, !0);
1530
+ }
1531
+ /**
1532
+ * 导出当前状态
1533
+ */
1534
+ save() {
1535
+ return this.getState();
1536
+ }
1537
+ /**
1538
+ * 从状态中恢复画布
1539
+ */
1540
+ restore(s) {
1541
+ this._renderCanvas(s);
1985
1542
  }
1986
1543
  }
1987
- function modulate(value, rangeA, rangeB, clamp2 = false) {
1988
- const [fromLow, fromHigh] = rangeA;
1989
- const [v0, v1] = rangeB;
1990
- const result = v0 + (value - fromLow) / (fromHigh - fromLow) * (v1 - v0);
1991
- return clamp2 ? v0 < v1 ? Math.max(Math.min(result, v1), v0) : Math.max(Math.min(result, v0), v1) : result;
1544
+ function Fe(o, s, t, i = !1) {
1545
+ const [n, r] = s, [a, h] = t, c = a + (o - n) / (r - n) * (h - a);
1546
+ return i ? a < h ? Math.max(Math.min(c, h), a) : Math.max(Math.min(c, a), h) : c;
1992
1547
  }
1993
- const gridSteps = [
1548
+ const se = [
1994
1549
  {
1995
1550
  min: -1,
1996
1551
  mid: 0.15,
@@ -2012,20 +1567,15 @@ const gridSteps = [
2012
1567
  step: 1
2013
1568
  }
2014
1569
  ];
2015
- function GridBackground({
2016
- viewportX,
2017
- viewportY,
2018
- scale,
2019
- size = 20,
2020
- showGrid = true
1570
+ function He({
1571
+ viewportX: o,
1572
+ viewportY: s,
1573
+ scale: t,
1574
+ size: i = 20,
1575
+ showGrid: n = !0
2021
1576
  }) {
2022
- const x = viewportX / scale;
2023
- const y = viewportY / scale;
2024
- const z = scale;
2025
- if (!showGrid) {
2026
- return null;
2027
- }
2028
- return /* @__PURE__ */ jsxs(
1577
+ const r = o / t, a = s / t, h = t;
1578
+ return n ? /* @__PURE__ */ it(
2029
1579
  "svg",
2030
1580
  {
2031
1581
  className: "canvas-grid w-full h-full absolute top-0 left-0",
@@ -2033,43 +1583,38 @@ function GridBackground({
2033
1583
  xmlns: "http://www.w3.org/2000/svg",
2034
1584
  "aria-hidden": "true",
2035
1585
  children: [
2036
- /* @__PURE__ */ jsx("defs", { children: gridSteps.map(({ min, mid, step }, i) => {
2037
- const s = step * size * z;
2038
- const xo = 0.5 + x * z;
2039
- const yo = 0.5 + y * z;
2040
- const gxo = xo > 0 ? xo % s : s + xo % s;
2041
- const gyo = yo > 0 ? yo % s : s + yo % s;
2042
- const opacity = z < mid ? modulate(z, [min, mid], [0, 1]) : 1;
2043
- return /* @__PURE__ */ jsx(
1586
+ /* @__PURE__ */ N("defs", { children: se.map(({ min: c, mid: g, step: m }, f) => {
1587
+ const u = m * i * h, x = 0.5 + r * h, v = 0.5 + a * h, M = x > 0 ? x % u : u + x % u, _ = v > 0 ? v % u : u + v % u, E = h < g ? Fe(h, [c, g], [0, 1]) : 1;
1588
+ return /* @__PURE__ */ N(
2044
1589
  "pattern",
2045
1590
  {
2046
- id: `grid_${step}`,
2047
- width: s,
2048
- height: s,
1591
+ id: `grid_${m}`,
1592
+ width: u,
1593
+ height: u,
2049
1594
  patternUnits: "userSpaceOnUse",
2050
- children: /* @__PURE__ */ jsx(
1595
+ children: /* @__PURE__ */ N(
2051
1596
  "circle",
2052
1597
  {
2053
- className: "tl-grid-dot",
2054
- cx: gxo,
2055
- cy: gyo,
1598
+ className: "grid-dot",
1599
+ cx: M,
1600
+ cy: _,
2056
1601
  r: 1,
2057
- opacity
1602
+ opacity: E
2058
1603
  }
2059
1604
  )
2060
1605
  },
2061
- i
1606
+ f
2062
1607
  );
2063
1608
  }) }),
2064
- gridSteps.map(({ step }, i) => /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#grid_${step})` }, i))
1609
+ se.map(({ step: c }, g) => /* @__PURE__ */ N("rect", { width: "100%", height: "100%", fill: `url(#grid_${c})` }, g))
2065
1610
  ]
2066
1611
  }
2067
- );
1612
+ ) : null;
2068
1613
  }
2069
- function cn(...inputs) {
2070
- return twMerge(clsx(inputs));
1614
+ function Ge(...o) {
1615
+ return Ie(Me(o));
2071
1616
  }
2072
- const buttonVariants = cva(
1617
+ const Ke = be(
2073
1618
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
2074
1619
  {
2075
1620
  variants: {
@@ -2096,162 +1641,148 @@ const buttonVariants = cva(
2096
1641
  }
2097
1642
  }
2098
1643
  );
2099
- function Button({
2100
- className,
2101
- variant = "default",
2102
- size = "default",
2103
- asChild = false,
2104
- ...props
1644
+ function ot({
1645
+ className: o,
1646
+ variant: s = "default",
1647
+ size: t = "default",
1648
+ asChild: i = !1,
1649
+ ...n
2105
1650
  }) {
2106
- const Comp = asChild ? Slot : "button";
2107
- return /* @__PURE__ */ jsx(
2108
- Comp,
1651
+ return /* @__PURE__ */ N(
1652
+ i ? _e : "button",
2109
1653
  {
2110
1654
  "data-slot": "button",
2111
- "data-variant": variant,
2112
- "data-size": size,
2113
- className: cn(buttonVariants({ variant, size, className })),
2114
- ...props
1655
+ "data-variant": s,
1656
+ "data-size": t,
1657
+ className: Ge(Ke({ variant: s, size: t, className: o })),
1658
+ ...n
2115
1659
  }
2116
1660
  );
2117
1661
  }
2118
- function ZoomPanel({ api }) {
2119
- const [viewport, setViewport] = useState(api.getState().viewport);
2120
- useEffect(() => {
2121
- api.on("viewport:change", (newViewport) => {
2122
- setViewport(newViewport);
1662
+ function qe({ api: o }) {
1663
+ const [s, t] = ht(o.getState().viewport);
1664
+ Wt(() => {
1665
+ o.on("viewport:change", (c) => {
1666
+ t(c);
2123
1667
  });
2124
- }, [setViewport, api]);
2125
- const updateScale = (scale) => {
2126
- const halfWidth = viewport.width / 2;
2127
- const halfHeight = viewport.height / 2;
2128
- const worldCenterX = (halfWidth - viewport.x) / viewport.scale;
2129
- const worldCenterY = (halfHeight - viewport.y) / viewport.scale;
2130
- const x = halfWidth - worldCenterX * scale;
2131
- const y = halfHeight - worldCenterY * scale;
2132
- api.updateViewport({ x, y, scale });
2133
- };
2134
- const handleZoomIn = () => {
2135
- const scale = Math.min(viewport.scale * 1.2, 5);
2136
- updateScale(scale);
2137
- };
2138
- const handleZoomOut = () => {
2139
- const scale = Math.max(viewport.scale / 1.2, 0.1);
2140
- updateScale(scale);
2141
- };
2142
- const handleReset = () => {
2143
- updateScale(1);
2144
- };
2145
- const percent = Math.round(viewport.scale * 100);
2146
- return /* @__PURE__ */ jsxs("div", { className: "zoom-panel flex items-center gap-2", children: [
2147
- /* @__PURE__ */ jsx(
2148
- Button,
1668
+ }, [t, o]);
1669
+ const i = (c) => {
1670
+ const g = o.getStage().width() / 2, m = o.getStage().height() / 2, f = (g - s.x) / s.scale, u = (m - s.y) / s.scale, x = g - f * c, v = m - u * c;
1671
+ o.updateViewport({ x, y: v, scale: c });
1672
+ }, n = () => {
1673
+ const c = Math.min(s.scale * 1.2, 5);
1674
+ i(c);
1675
+ }, r = () => {
1676
+ const c = Math.max(s.scale / 1.2, 0.1);
1677
+ i(c);
1678
+ }, a = () => {
1679
+ i(1);
1680
+ }, h = Math.round(s.scale * 100);
1681
+ return /* @__PURE__ */ it("div", { className: "zoom-panel flex items-center gap-2", children: [
1682
+ /* @__PURE__ */ N(
1683
+ ot,
2149
1684
  {
2150
1685
  size: "sm",
2151
1686
  variant: "secondary",
2152
- onClick: handleZoomOut,
1687
+ onClick: r,
2153
1688
  title: "缩小",
2154
- children: /* @__PURE__ */ jsx(Minus, {})
1689
+ children: /* @__PURE__ */ N(Ce, {})
2155
1690
  }
2156
1691
  ),
2157
- /* @__PURE__ */ jsxs(
2158
- Button,
1692
+ /* @__PURE__ */ it(
1693
+ ot,
2159
1694
  {
2160
1695
  size: "sm",
2161
1696
  variant: "secondary",
2162
- onClick: handleReset,
2163
- title: `${percent}%`,
1697
+ onClick: a,
1698
+ title: `${h}%`,
2164
1699
  className: "min-w-16",
2165
1700
  children: [
2166
- percent,
1701
+ h,
2167
1702
  "%"
2168
1703
  ]
2169
1704
  }
2170
1705
  ),
2171
- /* @__PURE__ */ jsx(
2172
- Button,
1706
+ /* @__PURE__ */ N(
1707
+ ot,
2173
1708
  {
2174
1709
  size: "sm",
2175
1710
  variant: "secondary",
2176
- onClick: handleZoomIn,
1711
+ onClick: n,
2177
1712
  title: "放大",
2178
- children: /* @__PURE__ */ jsx(Plus, {})
1713
+ children: /* @__PURE__ */ N(Ee, {})
2179
1714
  }
2180
1715
  )
2181
1716
  ] });
2182
1717
  }
2183
- function HistoryPanel({ api }) {
2184
- const [canUndo, setCanUndo] = useState(api.canUndo());
2185
- const [canRedo, setCanRedo] = useState(api.canRedo());
2186
- useEffect(() => {
2187
- const handleStateChange = () => {
2188
- setCanUndo(api.canUndo());
2189
- setCanRedo(api.canRedo());
1718
+ function je({ api: o }) {
1719
+ const [s, t] = ht(o.canUndo()), [i, n] = ht(o.canRedo());
1720
+ return Wt(() => {
1721
+ const r = () => {
1722
+ t(o.canUndo()), n(o.canRedo());
2190
1723
  };
2191
- api.on("state:change", handleStateChange);
2192
- return () => {
2193
- api.off("state:change", handleStateChange);
1724
+ return o.on("state:change", r), () => {
1725
+ o.off("state:change", r);
2194
1726
  };
2195
- }, [api]);
2196
- return /* @__PURE__ */ jsxs("div", { className: "history-panel flex items-center gap-2", children: [
2197
- /* @__PURE__ */ jsx(
2198
- Button,
1727
+ }, [o]), /* @__PURE__ */ it("div", { className: "history-panel flex items-center gap-2", children: [
1728
+ /* @__PURE__ */ N(
1729
+ ot,
2199
1730
  {
2200
1731
  size: "sm",
2201
1732
  variant: "secondary",
2202
- disabled: !canUndo,
2203
- onClick: () => api.undo(),
1733
+ disabled: !s,
1734
+ onClick: () => o.undo(),
2204
1735
  title: "撤销",
2205
- children: /* @__PURE__ */ jsx(Undo2, {})
1736
+ children: /* @__PURE__ */ N(ke, {})
2206
1737
  }
2207
1738
  ),
2208
- /* @__PURE__ */ jsx(
2209
- Button,
1739
+ /* @__PURE__ */ N(
1740
+ ot,
2210
1741
  {
2211
1742
  size: "sm",
2212
1743
  variant: "secondary",
2213
- disabled: !canRedo,
2214
- onClick: () => api.redo(),
1744
+ disabled: !i,
1745
+ onClick: () => o.redo(),
2215
1746
  title: "重做",
2216
- children: /* @__PURE__ */ jsx(Redo2, {})
1747
+ children: /* @__PURE__ */ N(Te, {})
2217
1748
  }
2218
1749
  )
2219
1750
  ] });
2220
1751
  }
2221
- function PureCanvas({ setApi }) {
2222
- const containerRef = useRef(null);
2223
- const [_api, _setApi] = useState(null);
2224
- const [viewport, setViewport] = useState({ x: 0, y: 0, scale: 1 });
2225
- useEffect(() => {
2226
- if (!containerRef.current) return;
2227
- const core = new CanvasApi(containerRef.current);
2228
- _setApi(core);
2229
- setApi?.(core);
2230
- core.on("viewport:change", (newViewport) => {
2231
- setViewport(newViewport);
2232
- });
2233
- return () => {
2234
- core.dispose();
1752
+ function ls({ setApi: o }) {
1753
+ const s = Se(null), [t, i] = ht(null), [n, r] = ht({ x: 0, y: 0, scale: 1 });
1754
+ return Wt(() => {
1755
+ if (!s.current) return;
1756
+ const a = new Be(s.current);
1757
+ return i(a), o?.(a), a.on("viewport:change", (h) => {
1758
+ r(h);
1759
+ }), () => {
1760
+ a.dispose();
2235
1761
  };
2236
- }, [setApi]);
2237
- return /* @__PURE__ */ jsxs("div", { className: "pure-canvas relative size-full", children: [
2238
- /* @__PURE__ */ jsx(
2239
- GridBackground,
1762
+ }, [o]), /* @__PURE__ */ it("div", { className: "whiteboard relative size-full", children: [
1763
+ /* @__PURE__ */ N(
1764
+ He,
1765
+ {
1766
+ viewportX: n.x,
1767
+ viewportY: n.y,
1768
+ scale: n.scale
1769
+ }
1770
+ ),
1771
+ /* @__PURE__ */ N(
1772
+ "div",
2240
1773
  {
2241
- viewportX: viewport.x,
2242
- viewportY: viewport.y,
2243
- scale: viewport.scale
1774
+ ref: s,
1775
+ className: "whiteboard-container size-full outline-none"
2244
1776
  }
2245
1777
  ),
2246
- /* @__PURE__ */ jsx("div", { ref: containerRef, className: "size-full" }),
2247
- _api && /* @__PURE__ */ jsxs(Fragment, { children: [
2248
- /* @__PURE__ */ jsx("div", { className: "history-panel-wrapper absolute bottom-4 left-4 z-10", children: /* @__PURE__ */ jsx(HistoryPanel, { api: _api }) }),
2249
- /* @__PURE__ */ jsx("div", { className: "zoom-panel-wrapper absolute bottom-4 right-4 z-10", children: /* @__PURE__ */ jsx(ZoomPanel, { api: _api }) })
1778
+ t && /* @__PURE__ */ it(ve, { children: [
1779
+ /* @__PURE__ */ N("div", { className: "history-panel-wrapper absolute bottom-4 left-4 z-10", children: /* @__PURE__ */ N(je, { api: t }) }),
1780
+ /* @__PURE__ */ N("div", { className: "zoom-panel-wrapper absolute bottom-4 right-4 z-10", children: /* @__PURE__ */ N(qe, { api: t }) })
2250
1781
  ] })
2251
1782
  ] });
2252
1783
  }
2253
1784
  export {
2254
- CanvasApi,
2255
- NODE_NAMES,
2256
- PureCanvas
1785
+ Be as CanvasApi,
1786
+ A as NODE_NAMES,
1787
+ ls as Whiteboard
2257
1788
  };