@glodon-aiot/dataset-annotation 3.13.0-alpha.29 → 3.14.0-alpha.31

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.
Files changed (33) hide show
  1. package/dist/es/components/DetectionAnnotation/components/LabelMaker/RectLabel.mjs +151 -135
  2. package/dist/es/components/DetectionAnnotation/components/LabelMaker/index.mjs +244 -218
  3. package/dist/es/components/VLMAnnotation/RegionItem.mjs +135 -59
  4. package/dist/es/components/VLMAnnotation/TextAnnotationPanel.mjs +73 -62
  5. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useDeleteRegion.mjs +55 -40
  6. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useDrawingMode.mjs +291 -162
  7. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useOCRControl.mjs +100 -0
  8. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useOCRRecognition.mjs +88 -55
  9. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionBoundaryCheck.mjs +103 -0
  10. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionLoader.mjs +123 -91
  11. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionSelection.mjs +42 -39
  12. package/dist/es/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionUpdate.mjs +55 -60
  13. package/dist/es/components/VLMAnnotation/VLMLabelMaker/icons/ai.svg.mjs +4 -0
  14. package/dist/es/components/VLMAnnotation/VLMLabelMaker/icons/error.svg.mjs +4 -0
  15. package/dist/es/components/VLMAnnotation/VLMLabelMaker/icons/loading.svg.mjs +4 -0
  16. package/dist/es/components/VLMAnnotation/VLMLabelMaker/icons/star.svg.mjs +4 -0
  17. package/dist/es/components/VLMAnnotation/VLMLabelMaker/index.mjs +512 -387
  18. package/dist/es/components/VLMAnnotation/constants.mjs +39 -32
  19. package/dist/es/components/VLMAnnotation/index.mjs +187 -150
  20. package/dist/es/index.mjs +1 -1
  21. package/dist/lib/index.js +4 -4
  22. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useDeleteRegion.d.ts +1 -0
  23. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useDrawingMode.d.ts +3 -1
  24. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useOCRControl.d.ts +16 -0
  25. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useOCRRecognition.d.ts +3 -2
  26. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionBoundaryCheck.d.ts +31 -0
  27. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionLoader.d.ts +5 -1
  28. package/dist/src/components/VLMAnnotation/VLMLabelMaker/hooks/useRegionSelection.d.ts +2 -1
  29. package/dist/src/components/VLMAnnotation/VLMLabelMaker/index.d.ts +2 -2
  30. package/dist/src/components/VLMAnnotation/constants.d.ts +19 -3
  31. package/dist/src/components/VLMAnnotation/index.d.ts +1 -1
  32. package/dist/src/components/VLMAnnotation/types.d.ts +15 -0
  33. package/package.json +2 -2
@@ -1,42 +1,57 @@
1
- import { useCallback as Q, useEffect as te } from "react";
2
- import { fabric as j } from "fabric";
3
- import { TEMP_RECT_FILL_COLOR as V, RECT_STROKE_COLOR as U, TEMP_RECT_STROKE_DASH_ARRAY as v, TRANSPARENT_FILL as oe, REGION_NAME_PREFIX as re, BASE_STROKE_WIDTH as a } from "../../constants.mjs";
4
- const ne = ({
1
+ import { useCallback as ue, useRef as fe, useEffect as he } from "react";
2
+ import { fabric as b } from "fabric";
3
+ import { CROSSHAIR_LINE_COLOR as me, CROSSHAIR_LINE_DASH_ARRAY as ge, CROSSHAIR_LINE_WIDTH as ke, TEMP_RECT_FILL_COLOR as be, RECT_STROKE_COLOR as G, TEMP_RECT_STROKE_DASH_ARRAY as pe, TRANSPARENT_FILL as Ee, REGION_NAME_PREFIX as xe, BASE_STROKE_WIDTH as K } from "../../constants.mjs";
4
+ const Te = ({
5
5
  canvas: e,
6
- drawingMode: x,
7
- draggable: H,
8
- setDrawingMode: $,
9
- canvasToImageCoords: G,
10
- labelDefinitions: y,
11
- onChange: T,
12
- cropRegionImage: K,
13
- updateRegionShapeAndImage: L,
14
- performOCRIfNeeded: B,
15
- createDeleteControl: D,
16
- updateRegionNameText: N,
17
- onRegionChange: S,
18
- onRegionSelect: w,
6
+ drawingMode: C,
7
+ draggable: q,
8
+ setDrawingMode: J,
9
+ canvasToImageCoords: Q,
10
+ labelDefinitions: X,
11
+ onChange: a,
12
+ cropRegionImage: V,
13
+ updateRegionShapeAndImage: P,
14
+ performOCRIfNeeded: v,
15
+ createDeleteControl: ee,
16
+ createOCRControl: te,
17
+ updateRegionNameText: oe,
18
+ onRegionChange: U,
19
+ onRegionSelect: M,
19
20
  rectMapRef: h,
20
- textLayersMapRef: z
21
+ textLayersMapRef: re,
22
+ setupBoundaryCheck: ie
21
23
  }) => {
22
- const X = Q(() => {
23
- const Y = /* @__PURE__ */ new Set();
24
- return z.current.forEach((r) => {
25
- r.forEach((l) => {
26
- Y.add(l);
24
+ const D = ue(() => {
25
+ const R = /* @__PURE__ */ new Set();
26
+ return re.current.forEach((T) => {
27
+ T.forEach((W) => {
28
+ R.add(W);
27
29
  });
28
- }), Y;
29
- }, [z]), R = Q(() => {
30
+ }), R;
31
+ }, [re]), l = fe({
32
+ horizontal: null,
33
+ vertical: null
34
+ }), Le = fe({
35
+ dleft: -1,
36
+ dtop: -1,
37
+ dw: 0,
38
+ dh: 0,
39
+ rect: null
40
+ }), Z = ue(() => {
30
41
  e && (e.skipTargetFind = !1);
31
42
  }, [e]);
32
- return te(() => {
33
- if (!e || !x || H) {
34
- if (R(), e && !x) {
43
+ return he(() => {
44
+ if (!e || !C || q) {
45
+ if (Z(), e && !C) {
46
+ l.current.horizontal && e.getObjects().includes(l.current.horizontal) && e.remove(l.current.horizontal), l.current.vertical && e.getObjects().includes(l.current.vertical) && e.remove(l.current.vertical), l.current = {
47
+ horizontal: null,
48
+ vertical: null
49
+ };
35
50
  const o = e.getActiveObject();
36
51
  e.selection = !1, e.skipTargetFind = !1;
37
- const n = X();
38
- e.getObjects().forEach((t) => {
39
- t instanceof j.Rect && n.has(t) ? t.set({
52
+ const r = D();
53
+ e.getObjects().forEach((i) => {
54
+ i instanceof b.Rect && r.has(i) ? i.set({
40
55
  evented: !0,
41
56
  selectable: !1,
42
57
  lockMovementX: !0,
@@ -44,69 +59,131 @@ const ne = ({
44
59
  lockScalingX: !0,
45
60
  lockScalingY: !0,
46
61
  lockRotation: !0
47
- }) : (t.set("evented", !0), t.set("selectable", !0));
62
+ }) : (i.set("evented", !0), i.set("selectable", !0), i instanceof b.Rect && i.set("hasControls", !0));
48
63
  }), o && e.getObjects().includes(o) && (e.setActiveObject(o), e.renderAll()), e.defaultCursor = "default", e.setCursor("default");
49
64
  }
50
65
  return;
51
66
  }
52
- R(), e.selection = !1, e.skipTargetFind = !0, e.getActiveObject() && (e.discardActiveObject(), e.renderAll()), e.getObjects().forEach((o) => {
53
- o.set("evented", !1), o.set("selectable", !1);
54
- }), e.defaultCursor = "crosshair", e.setCursor("crosshair");
55
- let r = -1, l = -1, d = 0, m = 0, f = null;
56
- const q = (o) => {
57
- e.getActiveObject() && (e.discardActiveObject(), e.renderAll()), r = -1, l = -1, d = 0, m = 0;
58
- const t = e.getPointer(o.e);
59
- l = t.x, r = t.y, e.skipTargetFind = !0;
60
- }, P = (o) => {
61
- if (l === -1 || r === -1)
67
+ Z(), e.selection = !1, e.skipTargetFind = !0, e.getActiveObject() && (e.discardActiveObject(), e.renderAll()), e.getObjects().forEach((o) => {
68
+ o.set("evented", !1), o.set("selectable", !1), o instanceof b.Rect && o.hasControls && o.set("hasControls", !1);
69
+ }), e.defaultCursor = "crosshair", e.setCursor("crosshair"), l.current.horizontal && e.getObjects().includes(l.current.horizontal) && e.remove(l.current.horizontal), l.current.vertical && e.getObjects().includes(l.current.vertical) && e.remove(l.current.vertical), l.current = {
70
+ horizontal: null,
71
+ vertical: null
72
+ };
73
+ const T = e.getWidth(), W = e.getHeight(), m = e.getZoom(), L = T / m, A = W / m, O = Math.max(L, A) * 3, F = ke / m, S = new b.Line([-O, 0, O, 0], {
74
+ stroke: me,
75
+ strokeWidth: F,
76
+ strokeDashArray: ge,
77
+ selectable: !1,
78
+ evented: !1,
79
+ excludeFromExport: !0,
80
+ // 导出时不包含此线
81
+ strokeUniform: !0,
82
+ // 设置为 true,使线宽随缩放调整以保持视觉一致
83
+ visible: !1
84
+ // 初始状态隐藏,只有鼠标进入画布时才显示
85
+ }), _ = new b.Line([0, -O, 0, O], {
86
+ stroke: me,
87
+ strokeWidth: F,
88
+ strokeDashArray: ge,
89
+ selectable: !1,
90
+ evented: !1,
91
+ excludeFromExport: !0,
92
+ // 导出时不包含此线
93
+ strokeUniform: !0,
94
+ // 设置为 true,使线宽随缩放调整以保持视觉一致
95
+ visible: !1
96
+ // 初始状态隐藏,只有鼠标进入画布时才显示
97
+ });
98
+ l.current = {
99
+ horizontal: S,
100
+ vertical: _
101
+ }, e.add(S), e.add(_), S.sendToBack(), _.sendToBack();
102
+ const z = (o, r) => {
103
+ const i = l.current.horizontal, d = l.current.vertical;
104
+ if (!i || !d)
105
+ return;
106
+ const u = e.getZoom(), g = e.getWidth(), c = e.getHeight(), k = g / u, p = c / u, f = Math.max(k, p) * 3;
107
+ i.set({
108
+ x1: o - f,
109
+ y1: r,
110
+ x2: o + f,
111
+ y2: r,
112
+ visible: !0
113
+ // 显示辅助线
114
+ }), d.set({
115
+ x1: o,
116
+ y1: r - f,
117
+ x2: o,
118
+ y2: r + f,
119
+ visible: !0
120
+ // 显示辅助线
121
+ }), i.sendToBack(), d.sendToBack(), e.renderAll();
122
+ }, E = () => {
123
+ const o = l.current.horizontal, r = l.current.vertical;
124
+ !o || !r || (o.set({
125
+ visible: !1
126
+ }), r.set({
127
+ visible: !1
128
+ }), e.renderAll());
129
+ }, t = Le.current, H = (o) => {
130
+ if (e.skipTargetFind && (t.dleft === -1 || t.dtop === -1)) {
131
+ const r = e.getPointer(o.e);
132
+ t.dleft = r.x, t.dtop = r.y;
133
+ }
134
+ }, Ae = (o) => {
135
+ const r = e.getPointer(o.e);
136
+ z(r.x, r.y);
137
+ }, B = (o) => {
138
+ if (Ae(o), t.dleft === -1 || t.dtop === -1)
62
139
  return;
63
- const n = e.getPointer(o.e);
64
- let t = n.x, c = n.y;
65
- if (d = Math.abs(t - l), m = Math.abs(c - r), d === 0 || m === 0)
140
+ const r = e.getPointer(o.e);
141
+ let i = r.x, d = r.y;
142
+ if (t.dw = Math.abs(i - t.dleft), t.dh = Math.abs(d - t.dtop), t.dw === 0 || t.dh === 0)
66
143
  return;
67
- let g = r > c ? c : r, C = l > t ? t : l, u = d, k = m;
68
- f && e.remove(f);
69
- const A = e.getZoom(), p = a / A;
70
- f = new j.Rect({
71
- left: C,
72
- top: g,
73
- width: u,
144
+ let u = t.dtop > d ? d : t.dtop, g = t.dleft > i ? i : t.dleft, c = t.dw, k = t.dh;
145
+ t.rect && e.remove(t.rect);
146
+ const p = e.getZoom(), f = K / p;
147
+ t.rect = new b.Rect({
148
+ left: g,
149
+ top: u,
150
+ width: c,
74
151
  height: k,
75
- fill: V,
76
- stroke: U,
77
- strokeWidth: p,
152
+ fill: be,
153
+ stroke: G,
154
+ strokeWidth: f,
78
155
  strokeUniform: !0,
79
156
  // 边框宽度不受缩放影响
80
- strokeDashArray: v,
157
+ strokeDashArray: pe,
81
158
  selectable: !1,
82
159
  evented: !1,
83
160
  objectCaching: !1,
84
161
  // 禁用缓存,避免缩放时边框变虚
85
162
  statefullCache: !1,
86
163
  noScaleCache: !1
87
- }), e.add(f), e.renderAll();
88
- }, W = (o) => {
89
- if (l === -1 || r === -1) {
90
- r = -1, l = -1;
164
+ }), e.add(t.rect), e.renderAll();
165
+ }, I = (o) => {
166
+ if (t.dleft === -1 || t.dtop === -1) {
167
+ t.dtop = -1, t.dleft = -1;
91
168
  return;
92
169
  }
93
- const n = e.getPointer(o.e);
94
- let t = n.x, c = n.y;
95
- if (d = Math.abs(t - l), m = Math.abs(c - r), d === 0 || m === 0) {
96
- f && (e.remove(f), e.renderAll()), r = -1, l = -1;
170
+ const r = e.getPointer(o.e);
171
+ let i = r.x, d = r.y;
172
+ if (t.dw = Math.abs(i - t.dleft), t.dh = Math.abs(d - t.dtop), t.dw === 0 || t.dh === 0) {
173
+ t.rect && (e.remove(t.rect), e.renderAll()), t.dtop = -1, t.dleft = -1;
97
174
  return;
98
175
  }
99
- let g = r > c ? c : r, C = l > t ? t : l, u = d, k = m;
100
- f && (e.remove(f), f = null);
101
- const A = G(C, g), p = u, F = k, E = e.getZoom(), b = a / E, s = new j.Rect({
102
- left: C,
103
- top: g,
104
- width: u,
176
+ let u = t.dtop > d ? d : t.dtop, g = t.dleft > i ? i : t.dleft, c = t.dw, k = t.dh;
177
+ t.rect && (e.remove(t.rect), t.rect = null);
178
+ const p = Q(g, u), f = c, N = k, x = e.getZoom(), w = K / x, n = new b.Rect({
179
+ left: g,
180
+ top: u,
181
+ width: c,
105
182
  height: k,
106
- fill: oe,
183
+ fill: Ee,
107
184
  // 无填充色
108
- stroke: U,
109
- strokeWidth: b,
185
+ stroke: G,
186
+ strokeWidth: w,
110
187
  strokeUniform: !0,
111
188
  // 边框宽度不受缩放影响
112
189
  selectable: !0,
@@ -117,118 +194,140 @@ const ne = ({
117
194
  // 锁定旋转
118
195
  lockUniScaling: !1,
119
196
  // 允许非等比缩放,控制点跟随鼠标
197
+ lockScalingFlip: !0,
198
+ // 禁止缩放时翻转
120
199
  objectCaching: !1,
121
200
  // 禁用缓存,避免缩放时边框变虚
122
201
  statefullCache: !1,
123
- noScaleCache: !1
202
+ noScaleCache: !1,
203
+ hasControls: !0
204
+ // 启用控件
124
205
  });
125
- e.add(s), s.controls.deleteControl = D();
126
- const Z = h.current.size, _ = {};
127
- y == null || y.forEach((i) => {
128
- _[i.id] = "";
206
+ e.add(n), n.controls.deleteControl = ee(), n.controls.ocrControl = te(), n.set("hasControls", !1);
207
+ const $ = h.current.size, Y = {};
208
+ X == null || X.forEach((s) => {
209
+ Y[s.id] = "";
129
210
  });
130
- const M = {
211
+ const j = {
131
212
  id: `region-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
132
- name: `${re}${Z + 1}`,
213
+ name: `${xe}${$ + 1}`,
133
214
  // 设置名称:区域+(索引+1)
134
215
  shape: {
135
216
  name: "rect",
136
- x: Math.max(0, A.x),
137
- y: Math.max(0, A.y),
138
- width: p,
139
- height: F
217
+ x: Math.max(0, p.x),
218
+ y: Math.max(0, p.y),
219
+ width: f,
220
+ height: N
140
221
  },
141
- content: _
222
+ content: Y
142
223
  };
143
- if (h.current.set(s, M), N(s, M), L(s), S) {
144
- const i = h.current.get(s);
145
- i && S(i, "create");
224
+ if (h.current.set(n, j), oe(n, j), P(n), U) {
225
+ const s = h.current.get(n);
226
+ s && U(s, "create");
146
227
  }
147
- K(M).then((i) => {
148
- if (i) {
149
- const O = h.current.get(s);
150
- if (O) {
151
- if (O.image = i, delete O.textLayouts, T) {
152
- const ee = Array.from(h.current.values());
153
- T(ee);
228
+ V(j).then((s) => {
229
+ if (s) {
230
+ const y = h.current.get(n);
231
+ if (y) {
232
+ if (y.image = s, delete y.textLayouts, a) {
233
+ const Oe = Array.from(h.current.values());
234
+ a(Oe);
154
235
  }
155
- B(O, "create");
236
+ v(y, "create");
156
237
  }
157
238
  }
158
- }).catch((i) => {
159
- console.error("Failed to crop region image:", i);
160
- }), e.setActiveObject(s), e.renderAll(), setTimeout(() => {
161
- if (w) {
162
- const i = h.current.get(s);
163
- i && w(i);
239
+ }).catch((s) => {
240
+ console.error("Failed to crop region image:", s);
241
+ }), e.setActiveObject(n), e.renderAll(), setTimeout(() => {
242
+ if (M) {
243
+ const s = h.current.get(n);
244
+ s && M(s);
164
245
  }
165
246
  setTimeout(() => {
166
- if (e && s && e.getObjects().includes(s) && (e.setActiveObject(s), e.renderAll(), w)) {
167
- const i = h.current.get(s);
168
- i && w(i);
247
+ if (e && n && e.getObjects().includes(n) && (e.setActiveObject(n), e.renderAll(), M)) {
248
+ const s = h.current.get(n);
249
+ s && M(s);
169
250
  }
170
251
  }, 0);
171
- }, 0), s.on("modified", () => {
172
- L(s);
173
- }), s.on("moved", () => {
174
- L(s);
252
+ }, 0), ie(n), n.on("modified", () => {
253
+ P(n);
254
+ }), n.on("moved", () => {
255
+ P(n);
175
256
  }), setTimeout(() => {
176
- if (T) {
177
- const i = Array.from(h.current.values());
178
- T(i);
257
+ if (a) {
258
+ const s = Array.from(h.current.values());
259
+ a(s);
179
260
  }
180
- }, 0), r = -1, l = -1, e.selection = !1, $(!1);
181
- }, I = (o) => {
182
- if (l === -1 || r === -1)
261
+ }, 0), t.dtop = -1, t.dleft = -1, e.selection = !1, J(!1);
262
+ }, le = (o) => {
263
+ const i = e.getElement().getBoundingClientRect(), d = o.clientX, u = o.clientY, g = d >= i.left && d <= i.right && u >= i.top && u <= i.bottom;
264
+ if (g) {
265
+ const c = e.getPointer(o);
266
+ z(c.x, c.y);
267
+ } else
268
+ E();
269
+ if (!(t.dleft === -1 || t.dtop === -1))
270
+ if (g) {
271
+ const c = e.getPointer(o);
272
+ B({
273
+ e: o,
274
+ pointer: c
275
+ });
276
+ } else {
277
+ const c = e.getZoom(), k = e.viewportTransform ? e.viewportTransform[4] / c : 0, p = e.viewportTransform ? e.viewportTransform[5] / c : 0, f = e.getWidth() / c, N = e.getHeight() / c;
278
+ let x = (d - i.left) / c - k, w = (u - i.top) / c - p;
279
+ if (x = Math.max(0, Math.min(x, f)), w = Math.max(0, Math.min(w, N)), t.dw = Math.abs(x - t.dleft), t.dh = Math.abs(w - t.dtop), t.dw === 0 || t.dh === 0)
280
+ return;
281
+ let n = t.dtop > w ? w : t.dtop, $ = t.dleft > x ? x : t.dleft, Y = t.dw, j = t.dh;
282
+ t.rect && e.remove(t.rect);
283
+ const s = e.getZoom(), y = K / s;
284
+ t.rect = new b.Rect({
285
+ left: $,
286
+ top: n,
287
+ width: Y,
288
+ height: j,
289
+ fill: be,
290
+ stroke: G,
291
+ strokeWidth: y,
292
+ strokeUniform: !0,
293
+ strokeDashArray: pe,
294
+ selectable: !1,
295
+ evented: !1,
296
+ objectCaching: !1,
297
+ statefullCache: !1,
298
+ noScaleCache: !1
299
+ }), e.add(t.rect), e.renderAll();
300
+ }
301
+ }, ne = () => {
302
+ E();
303
+ }, se = (o) => {
304
+ const r = e.getPointer(o.e);
305
+ z(r.x, r.y);
306
+ }, ce = (o) => {
307
+ if (!C)
183
308
  return;
184
- const t = e.getElement().getBoundingClientRect(), c = o.clientX, g = o.clientY;
185
- if (c >= t.left && c <= t.right && g >= t.top && g <= t.bottom) {
186
- const u = e.getPointer(o);
187
- P({
188
- e: o,
189
- pointer: u
190
- });
191
- } else {
192
- const u = e.getZoom(), k = e.viewportTransform ? e.viewportTransform[4] / u : 0, A = e.viewportTransform ? e.viewportTransform[5] / u : 0, p = e.getWidth() / u, F = e.getHeight() / u;
193
- let E = (c - t.left) / u - k, b = (g - t.top) / u - A;
194
- if (E = Math.max(0, Math.min(E, p)), b = Math.max(0, Math.min(b, F)), d = Math.abs(E - l), m = Math.abs(b - r), d === 0 || m === 0)
195
- return;
196
- let s = r > b ? b : r, Z = l > E ? E : l, _ = d, M = m;
197
- f && e.remove(f);
198
- const i = e.getZoom(), O = a / i;
199
- f = new j.Rect({
200
- left: Z,
201
- top: s,
202
- width: _,
203
- height: M,
204
- fill: V,
205
- stroke: U,
206
- strokeWidth: O,
207
- strokeUniform: !0,
208
- strokeDashArray: v,
209
- selectable: !1,
210
- evented: !1,
211
- objectCaching: !1,
212
- statefullCache: !1,
213
- noScaleCache: !1
214
- }), e.add(f), e.renderAll();
215
- }
309
+ e.skipTargetFind = !0, e.getActiveObject() && (e.discardActiveObject(), e.renderAll()), t.dtop = -1, t.dleft = -1, t.dw = 0, t.dh = 0;
310
+ const i = e.getPointer(o.e);
311
+ t.dleft = i.x, t.dtop = i.y;
216
312
  };
217
- e.on("mouse:down", q), e.on("mouse:move", P), e.on("mouse:up", W), document.addEventListener("mousemove", I);
218
- const J = (o) => {
219
- if (l === -1 || r === -1)
313
+ e.on("mouse:down:before", ce), e.on("mouse:down", H), e.on("mouse:move", B), e.on("mouse:up", I), e.on("mouse:out", ne), e.on("mouse:over", se), document.addEventListener("mousemove", le);
314
+ const de = (o) => {
315
+ if (t.dleft === -1 || t.dtop === -1)
220
316
  return;
221
- const n = e.getPointer(o);
222
- W({
317
+ const r = e.getPointer(o);
318
+ I({
223
319
  e: o,
224
- pointer: n
320
+ pointer: r
225
321
  });
226
322
  };
227
- return document.addEventListener("mouseup", J), () => {
228
- e.off("mouse:down", q), e.off("mouse:move", P), e.off("mouse:up", W), document.removeEventListener("mousemove", I), document.removeEventListener("mouseup", J), f && (e.remove(f), e.renderAll()), e.skipTargetFind = !1;
229
- const o = X();
230
- e.getObjects().forEach((n) => {
231
- n instanceof j.Rect && o.has(n) ? n.set({
323
+ return document.addEventListener("mouseup", de), () => {
324
+ e.off("mouse:down:before", ce), e.off("mouse:down", H), e.off("mouse:move", B), e.off("mouse:up", I), e.off("mouse:out", ne), e.off("mouse:over", se), document.removeEventListener("mousemove", le), document.removeEventListener("mouseup", de), t.rect && (e.remove(t.rect), e.renderAll()), l.current.horizontal && e.getObjects().includes(l.current.horizontal) && e.remove(l.current.horizontal), l.current.vertical && e.getObjects().includes(l.current.vertical) && e.remove(l.current.vertical), l.current = {
325
+ horizontal: null,
326
+ vertical: null
327
+ }, e.skipTargetFind = !1;
328
+ const o = D();
329
+ e.getObjects().forEach((r) => {
330
+ r instanceof b.Rect && o.has(r) ? r.set({
232
331
  evented: !0,
233
332
  selectable: !1,
234
333
  lockMovementX: !0,
@@ -236,13 +335,43 @@ const ne = ({
236
335
  lockScalingX: !0,
237
336
  lockScalingY: !0,
238
337
  lockRotation: !0
239
- }) : (n.set("evented", !0), n.set("selectable", !0));
338
+ }) : (r.set("evented", !0), r.set("selectable", !0));
240
339
  });
241
340
  };
242
- }, [e, x, H, R, G, T, K, L, B, D, N, S, w, $, h, X]), {
243
- stopDraw: R
341
+ }, [e, C, q, Z, Q, a, V, P, v, ee, te, oe, U, M, J, h, D, ie]), he(() => {
342
+ if (!e || !C)
343
+ return;
344
+ let R = e.getZoom();
345
+ const T = () => {
346
+ const m = l.current.horizontal, L = l.current.vertical;
347
+ if (!m || !L)
348
+ return;
349
+ const A = e.getZoom();
350
+ if (Math.abs(A - R) < 1e-3)
351
+ return;
352
+ R = A;
353
+ const O = ke / A, F = e.getWidth(), S = e.getHeight(), _ = F / A, z = S / A, E = Math.max(_, z) * 3, t = (m.x1 + m.x2) / 2;
354
+ m.y1, L.x1;
355
+ const H = (L.y1 + L.y2) / 2;
356
+ m.set({
357
+ strokeWidth: O,
358
+ x1: t - E,
359
+ x2: t + E
360
+ }), L.set({
361
+ strokeWidth: O,
362
+ y1: H - E,
363
+ y2: H + E
364
+ }), e.renderAll();
365
+ }, W = () => {
366
+ T();
367
+ };
368
+ return e.on("after:render", W), T(), () => {
369
+ e.off("after:render", W);
370
+ };
371
+ }, [e, C]), {
372
+ stopDraw: Z
244
373
  };
245
374
  };
246
375
  export {
247
- ne as useDrawingMode
376
+ Te as useDrawingMode
248
377
  };
@@ -0,0 +1,100 @@
1
+ import { useRef as a, useEffect as X, useCallback as H } from "react";
2
+ import { fabric as Y } from "fabric";
3
+ import { AI_CONTROL_OFFSET_X as P, AI_CONTROL_OFFSET_Y as U, AI_ICON_SIZE as y } from "../../constants.mjs";
4
+ import W from "../icons/ai.svg.mjs";
5
+ import Z from "../icons/star.svg.mjs";
6
+ import B from "../icons/error.svg.mjs";
7
+ import G from "../icons/loading.svg.mjs";
8
+ const nr = ({
9
+ performOCR: O,
10
+ ocrRecognizingRef: s,
11
+ ocrErrorRef: S,
12
+ rectMapRef: w
13
+ }) => {
14
+ const f = (r) => !(!r.complete || r.naturalWidth === 0), g = a(null), A = a(null), v = a(null), h = a(null), d = a(/* @__PURE__ */ new Set()), t = a(null), C = a(null);
15
+ return X(() => {
16
+ if (!g.current) {
17
+ const r = document.createElement("img");
18
+ r.src = W, g.current = r;
19
+ }
20
+ if (!A.current) {
21
+ const r = document.createElement("img");
22
+ r.src = Z, A.current = r;
23
+ }
24
+ if (!v.current) {
25
+ const r = document.createElement("img");
26
+ r.src = B, v.current = r;
27
+ }
28
+ if (!h.current) {
29
+ const r = document.createElement("img");
30
+ r.src = G, h.current = r;
31
+ }
32
+ }, []), X(() => {
33
+ const r = () => {
34
+ s.current.size > 0 ? (d.current.forEach((o) => {
35
+ o.renderAll();
36
+ }), t.current = requestAnimationFrame(r)) : t.current = null;
37
+ };
38
+ C.current = r, s.current.size > 0 && (t.current = requestAnimationFrame(r));
39
+ const m = setInterval(() => {
40
+ const c = s.current.size > 0, o = t.current !== null;
41
+ c && !o && (t.current = requestAnimationFrame(r));
42
+ }, 100);
43
+ return () => {
44
+ t.current !== null && cancelAnimationFrame(t.current), clearInterval(m);
45
+ };
46
+ }, [s]), {
47
+ createOCRControl: H(() => {
48
+ const r = y, l = g.current, m = A.current, c = v.current, o = h.current, n = 14, N = (e, p, F, M, I) => {
49
+ if (!l)
50
+ return;
51
+ const D = I, _ = w.current.get(D);
52
+ if (!_)
53
+ return;
54
+ const z = _.id, T = s.current.has(z), k = S.current.has(z), q = () => {
55
+ e.save(), e.translate(p, F), e.rotate(Y.util.degreesToRadians(I.angle || 0)), e.drawImage(l, -r / 2, -r / 2, r, r);
56
+ const u = r / 2 - n / 2 + 8, E = -r / 2 + n / 2 - 8;
57
+ if (T) {
58
+ if (o && f(o)) {
59
+ e.save(), e.translate(u, E);
60
+ const L = Date.now() / 500 % (Math.PI * 2);
61
+ e.rotate(L), e.drawImage(o, -n / 2, -n / 2, n, n), e.restore();
62
+ }
63
+ const i = I.canvas;
64
+ i && (d.current.has(i), d.current.add(i), s.current.size > 0 && !t.current && C.current && (t.current = requestAnimationFrame(C.current)));
65
+ } else {
66
+ const i = I.canvas;
67
+ i && s.current.size === 0 && d.current.delete(i), k && c && f(c) ? e.drawImage(c, u - n / 2, E - n / 2, n, n) : !T && !k && m && f(m) && e.drawImage(m, u - n / 2, E - n / 2, n, n);
68
+ }
69
+ e.restore();
70
+ };
71
+ f(l) ? q() : l.onload = () => {
72
+ q();
73
+ const u = I.canvas;
74
+ u && u.renderAll();
75
+ };
76
+ }, R = (e, p) => {
77
+ const F = p.target;
78
+ return O(F), !1;
79
+ };
80
+ return new Y.Control({
81
+ x: 0.5,
82
+ // 右侧(0 = 左边,0.5 = 中间,1 = 右边)
83
+ y: -0.5,
84
+ // 顶部(0 = 顶部,0.5 = 中间,1 = 底部)
85
+ offsetX: P,
86
+ // 与删除按钮相同的X偏移
87
+ offsetY: U + y + 4,
88
+ // 向下偏移,放在删除按钮下方(删除按钮的offsetY + 删除按钮大小 + 间距)
89
+ cursorStyle: "pointer",
90
+ mouseUpHandler: R,
91
+ render: N,
92
+ sizeX: r,
93
+ sizeY: r
94
+ });
95
+ }, [O, s, S, w])
96
+ };
97
+ };
98
+ export {
99
+ nr as useOCRControl
100
+ };