@xom11/whiteboard 0.7.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -1
- package/dist/chunk-74VEEZBV.mjs +619 -0
- package/dist/chunk-74VEEZBV.mjs.map +1 -0
- package/dist/{chunk-BJX4YNA5.mjs → chunk-G7FR3AIV.mjs} +68 -12
- package/dist/chunk-G7FR3AIV.mjs.map +1 -0
- package/dist/{chunk-SHFOGORM.mjs → chunk-PDKKDZ4H.mjs} +4 -4
- package/dist/{chunk-SHFOGORM.mjs.map → chunk-PDKKDZ4H.mjs.map} +1 -1
- package/dist/chunk-PWIMZIB6.mjs +62 -0
- package/dist/chunk-PWIMZIB6.mjs.map +1 -0
- package/dist/{chunk-LPM4MM45.mjs → chunk-SBDMF4NQ.mjs} +3 -2
- package/dist/chunk-SBDMF4NQ.mjs.map +1 -0
- package/dist/chunk-WQOABS6N.mjs +197 -0
- package/dist/chunk-WQOABS6N.mjs.map +1 -0
- package/dist/{chunk-3SSQKRRO.mjs → chunk-ZVN356JZ.mjs} +4 -4
- package/dist/{chunk-3SSQKRRO.mjs.map → chunk-ZVN356JZ.mjs.map} +1 -1
- package/dist/geometry-2d.js +344 -228
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +2 -2
- package/dist/geometry-3d.d.mts +1 -1
- package/dist/geometry-3d.d.ts +1 -1
- package/dist/geometry-3d.js +3411 -1277
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +3 -2
- package/dist/graph-2d.js +360 -66
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +2 -2
- package/dist/{host-T2W6R6SO.mjs → host-DJETSFCG.mjs} +272 -223
- package/dist/host-DJETSFCG.mjs.map +1 -0
- package/dist/{host-2QGKMGCT.mjs → host-LZH2FZ2N.mjs} +3 -3
- package/dist/{host-2QGKMGCT.mjs.map → host-LZH2FZ2N.mjs.map} +1 -1
- package/dist/host-N6ACNJKI.mjs +3226 -0
- package/dist/host-N6ACNJKI.mjs.map +1 -0
- package/dist/index.d.mts +133 -6
- package/dist/index.d.ts +133 -6
- package/dist/index.js +5634 -1999
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1231 -146
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -6
- package/dist/chunk-BJX4YNA5.mjs.map +0 -1
- package/dist/chunk-DJTBZEAR.mjs +0 -25
- package/dist/chunk-DJTBZEAR.mjs.map +0 -1
- package/dist/chunk-HM7RIXJE.mjs +0 -331
- package/dist/chunk-HM7RIXJE.mjs.map +0 -1
- package/dist/chunk-HYXFHEDJ.mjs +0 -129
- package/dist/chunk-HYXFHEDJ.mjs.map +0 -1
- package/dist/chunk-LPM4MM45.mjs.map +0 -1
- package/dist/host-T2W6R6SO.mjs.map +0 -1
- package/dist/host-XUFON6CQ.mjs +0 -1422
- package/dist/host-XUFON6CQ.mjs.map +0 -1
package/dist/geometry-2d.js
CHANGED
|
@@ -116,7 +116,17 @@ function deserializeIntoBoard(board, serialized, options = {}) {
|
|
|
116
116
|
const palette = options.palette ?? paletteFor(false);
|
|
117
117
|
const idMap = /* @__PURE__ */ new Map();
|
|
118
118
|
const resolve = (a) => {
|
|
119
|
-
if (typeof a === "string"
|
|
119
|
+
if (typeof a === "string") {
|
|
120
|
+
if (idMap.has(a)) return idMap.get(a);
|
|
121
|
+
const m = /^(.+):border:(\d+)$/.exec(a);
|
|
122
|
+
if (m) {
|
|
123
|
+
const poly = idMap.get(m[1]);
|
|
124
|
+
const idx = parseInt(m[2], 10);
|
|
125
|
+
if (poly && Array.isArray(poly.borders) && poly.borders[idx]) {
|
|
126
|
+
return poly.borders[idx];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
120
130
|
if (Array.isArray(a)) return a.map(resolve);
|
|
121
131
|
return a;
|
|
122
132
|
};
|
|
@@ -139,12 +149,59 @@ var init_serialize = __esm({
|
|
|
139
149
|
}
|
|
140
150
|
});
|
|
141
151
|
|
|
152
|
+
// src/stamps/shared/safeJsx.ts
|
|
153
|
+
function safeJsx(label, fn, fallback) {
|
|
154
|
+
try {
|
|
155
|
+
return fn();
|
|
156
|
+
} catch (err) {
|
|
157
|
+
if (isDev) {
|
|
158
|
+
console.warn("[whiteboard:jsxgraph]", label, err);
|
|
159
|
+
}
|
|
160
|
+
return fallback;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
var isDev;
|
|
164
|
+
var init_safeJsx = __esm({
|
|
165
|
+
"src/stamps/shared/safeJsx.ts"() {
|
|
166
|
+
isDev = (() => {
|
|
167
|
+
try {
|
|
168
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
169
|
+
} catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
})();
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
142
176
|
// src/stamps/geometry-2d/render.ts
|
|
177
|
+
function containerDimsForBbox(bbox) {
|
|
178
|
+
const [xmin, ymax, xmax, ymin] = bbox;
|
|
179
|
+
const w = Math.abs(xmax - xmin);
|
|
180
|
+
const h = Math.abs(ymax - ymin);
|
|
181
|
+
if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {
|
|
182
|
+
return { width: FALLBACK_W, height: FALLBACK_H };
|
|
183
|
+
}
|
|
184
|
+
let width = w * PIXELS_PER_UNIT;
|
|
185
|
+
let height = h * PIXELS_PER_UNIT;
|
|
186
|
+
const maxAxis = Math.max(width, height);
|
|
187
|
+
if (maxAxis > MAX_DIM) {
|
|
188
|
+
const ratio = MAX_DIM / maxAxis;
|
|
189
|
+
width *= ratio;
|
|
190
|
+
height *= ratio;
|
|
191
|
+
}
|
|
192
|
+
const minAxis = Math.min(width, height);
|
|
193
|
+
if (minAxis < MIN_DIM) {
|
|
194
|
+
const ratio = MIN_DIM / minAxis;
|
|
195
|
+
width *= ratio;
|
|
196
|
+
height *= ratio;
|
|
197
|
+
}
|
|
198
|
+
return { width: Math.round(width), height: Math.round(height) };
|
|
199
|
+
}
|
|
143
200
|
async function renderGeometrySvgFromState(jsonState) {
|
|
144
201
|
const parsed = JSON.parse(jsonState);
|
|
145
202
|
const palette = paletteFor(false);
|
|
146
203
|
const JXG = (await import('jsxgraph')).default;
|
|
147
|
-
|
|
204
|
+
safeJsx("render.applyOptions", () => {
|
|
148
205
|
const opts = JXG.Options;
|
|
149
206
|
if (opts) {
|
|
150
207
|
opts.text = opts.text || {};
|
|
@@ -161,12 +218,12 @@ async function renderGeometrySvgFromState(jsonState) {
|
|
|
161
218
|
opts.grid = opts.grid || {};
|
|
162
219
|
opts.grid.strokeColor = palette.grid;
|
|
163
220
|
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
221
|
+
});
|
|
222
|
+
const { width, height } = containerDimsForBbox(parsed.bbox);
|
|
166
223
|
const container = document.createElement("div");
|
|
167
224
|
const containerId = "jxg_offscreen_" + Date.now() + "_" + Math.random().toString(36).slice(2, 8);
|
|
168
225
|
container.id = containerId;
|
|
169
|
-
container.style.cssText =
|
|
226
|
+
container.style.cssText = `position:absolute;top:-99999px;left:-99999px;width:${width}px;height:${height}px;visibility:hidden;pointer-events:none;`;
|
|
170
227
|
document.body.appendChild(container);
|
|
171
228
|
let board = null;
|
|
172
229
|
try {
|
|
@@ -176,24 +233,30 @@ async function renderGeometrySvgFromState(jsonState) {
|
|
|
176
233
|
grid: !!parsed.showGrid,
|
|
177
234
|
showCopyright: false,
|
|
178
235
|
showNavigation: false,
|
|
179
|
-
keepAspectRatio:
|
|
236
|
+
keepAspectRatio: true
|
|
180
237
|
});
|
|
181
238
|
deserializeIntoBoard(board, parsed, { palette });
|
|
182
239
|
board.update();
|
|
183
240
|
return renderGeometryToSvg(container);
|
|
184
241
|
} finally {
|
|
185
|
-
|
|
242
|
+
safeJsx("render.freeBoard", () => {
|
|
186
243
|
if (board) JXG.JSXGraph.freeBoard(board);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
244
|
+
});
|
|
189
245
|
if (container.parentNode) container.parentNode.removeChild(container);
|
|
190
246
|
}
|
|
191
247
|
}
|
|
248
|
+
var PIXELS_PER_UNIT, MIN_DIM, MAX_DIM, FALLBACK_W, FALLBACK_H;
|
|
192
249
|
var init_render = __esm({
|
|
193
250
|
"src/stamps/geometry-2d/render.ts"() {
|
|
194
251
|
init_renderInline();
|
|
195
252
|
init_serialize();
|
|
196
253
|
init_theme();
|
|
254
|
+
init_safeJsx();
|
|
255
|
+
PIXELS_PER_UNIT = 20;
|
|
256
|
+
MIN_DIM = 100;
|
|
257
|
+
MAX_DIM = 1200;
|
|
258
|
+
FALLBACK_W = 400;
|
|
259
|
+
FALLBACK_H = 300;
|
|
197
260
|
}
|
|
198
261
|
});
|
|
199
262
|
|
|
@@ -290,8 +353,12 @@ function letterForGroup(g) {
|
|
|
290
353
|
}
|
|
291
354
|
function objKind(obj) {
|
|
292
355
|
if (!obj) return "other";
|
|
356
|
+
const ec = typeof obj.elementClass === "number" ? obj.elementClass : null;
|
|
357
|
+
if (ec === 1) return "point";
|
|
358
|
+
if (ec === 2) return "line";
|
|
359
|
+
if (ec === 3) return "circle";
|
|
293
360
|
const e = (obj.elType || obj.type || "").toString().toLowerCase();
|
|
294
|
-
if (e === "point" || e === "glider" || e === "midpoint") return "point";
|
|
361
|
+
if (e === "point" || e === "glider" || e === "midpoint" || e === "intersection" || e === "otherintersection" || e === "reflection" || e === "mirrorpoint" || e === "mirrorelement" || e === "orthogonalprojection" || e === "parallelpoint") return "point";
|
|
295
362
|
if (e === "line" || e === "segment" || e === "arrow" || e === "axis" || e === "normal" || e === "parallel" || e === "perpendicular" || e === "tangent" || e === "bisector" || e === "perpendicularsegment") return "line";
|
|
296
363
|
if (e === "circle" || e === "circumcircle") return "circle";
|
|
297
364
|
return "other";
|
|
@@ -491,7 +558,7 @@ function handleDown(ctx, e) {
|
|
|
491
558
|
if (!sc) return;
|
|
492
559
|
const [sx, sy] = sc;
|
|
493
560
|
const hits2 = ctx.objectsAt(e).map(ctx.promoteLabel).filter((o) => o !== ctx.axisObjsRef.current.x && o !== ctx.axisObjsRef.current.y);
|
|
494
|
-
const obj = hits2.find((o) => objKind(o) === "point") ??
|
|
561
|
+
const obj = hits2.find((o) => objKind(o) === "point") ?? ctx.findNearestPoint(e, 12) ?? hits2[0];
|
|
495
562
|
if (obj) {
|
|
496
563
|
const shift = !!(e.shiftKey || e.altKey);
|
|
497
564
|
ctx.toggleSelect(obj, shift);
|
|
@@ -529,14 +596,8 @@ function handleDown(ctx, e) {
|
|
|
529
596
|
const tmp1 = ctx.boardRef.current.create("intersection", [a, b, 1], { visible: false, withLabel: false });
|
|
530
597
|
const d0 = Math.hypot((tmp0.X?.() ?? 0) - x, (tmp0.Y?.() ?? 0) - y);
|
|
531
598
|
const d1 = Math.hypot((tmp1.X?.() ?? 0) - x, (tmp1.Y?.() ?? 0) - y);
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
} catch {
|
|
535
|
-
}
|
|
536
|
-
try {
|
|
537
|
-
ctx.boardRef.current.removeObject(tmp1);
|
|
538
|
-
} catch {
|
|
539
|
-
}
|
|
599
|
+
safeJsx("handlers.removeObject(intersect.tmp0)", () => ctx.boardRef.current.removeObject(tmp0));
|
|
600
|
+
safeJsx("handlers.removeObject(intersect.tmp1)", () => ctx.boardRef.current.removeObject(tmp1));
|
|
540
601
|
const idx = d0 <= d1 ? 0 : 1;
|
|
541
602
|
ctx.create("intersection", [aId, bId, idx], attrs);
|
|
542
603
|
}
|
|
@@ -573,7 +634,7 @@ function handleDown(ctx, e) {
|
|
|
573
634
|
})();
|
|
574
635
|
if (ctx.pendingRef.current.length > 0 && ctx.boardRef.current) {
|
|
575
636
|
const prev = ctx.pendingRef.current[ctx.pendingRef.current.length - 1];
|
|
576
|
-
|
|
637
|
+
safeJsx("handlers.createPreviewSegment", () => {
|
|
577
638
|
const seg = ctx.boardRef.current.create("segment", [prev, pick2], {
|
|
578
639
|
strokeColor: "#3b82f6",
|
|
579
640
|
strokeWidth: 1.5,
|
|
@@ -583,8 +644,7 @@ function handleDown(ctx, e) {
|
|
|
583
644
|
withLabel: false
|
|
584
645
|
});
|
|
585
646
|
ctx.previewSegRef.current.push(seg);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
647
|
+
});
|
|
588
648
|
}
|
|
589
649
|
ctx.pendingRef.current.push(pick2);
|
|
590
650
|
ctx.setPendingCount(ctx.pendingRef.current.length);
|
|
@@ -695,10 +755,7 @@ function handleUp(ctx, e) {
|
|
|
695
755
|
if (!sc2) return;
|
|
696
756
|
const [ex, ey] = sc2;
|
|
697
757
|
if (mq.rect) {
|
|
698
|
-
|
|
699
|
-
ctx.boardRef.current?.removeObject(mq.rect);
|
|
700
|
-
} catch {
|
|
701
|
-
}
|
|
758
|
+
safeJsx("handlers.removeObject(marquee.rect)", () => ctx.boardRef.current?.removeObject(mq.rect));
|
|
702
759
|
}
|
|
703
760
|
if (Math.hypot(ex - mq.startSx, ey - mq.startSy) < 4) return;
|
|
704
761
|
const x1 = Math.min(mq.startSx, ex), x2 = Math.max(mq.startSx, ex);
|
|
@@ -731,10 +788,7 @@ function handleUp(ctx, e) {
|
|
|
731
788
|
}
|
|
732
789
|
}
|
|
733
790
|
ctx.setSelectionTick((tt) => tt + 1);
|
|
734
|
-
|
|
735
|
-
board.update();
|
|
736
|
-
} catch {
|
|
737
|
-
}
|
|
791
|
+
safeJsx("handlers.board.update(marquee)", () => board.update());
|
|
738
792
|
return;
|
|
739
793
|
}
|
|
740
794
|
if (t !== "move") return;
|
|
@@ -747,7 +801,7 @@ function handleUp(ctx, e) {
|
|
|
747
801
|
const moved = Math.hypot(sx - start.sx, sy - start.sy);
|
|
748
802
|
if (moved > 4) return;
|
|
749
803
|
const hits = ctx.objectsAt(e).map(ctx.promoteLabel).filter((o) => o !== ctx.axisObjsRef.current.x && o !== ctx.axisObjsRef.current.y);
|
|
750
|
-
const best = hits.find((o) => objKind(o) === "point") ??
|
|
804
|
+
const best = hits.find((o) => objKind(o) === "point") ?? ctx.findNearestPoint(e, 12) ?? hits[0];
|
|
751
805
|
if (!best) {
|
|
752
806
|
ctx.lastMoveClickRef.current = { obj: null, time: 0 };
|
|
753
807
|
return;
|
|
@@ -781,12 +835,9 @@ function handleMove(ctx, e) {
|
|
|
781
835
|
const [x2u, y2u] = ux2 && ux2.length >= 2 ? [ux2[0], ux2[1]] : toUsr(Math.max(startSx, sx), Math.max(startSy, sy));
|
|
782
836
|
const rect = ctx.marqueeRef.current.rect;
|
|
783
837
|
if (rect) {
|
|
784
|
-
|
|
785
|
-
ctx.boardRef.current.removeObject(rect);
|
|
786
|
-
} catch {
|
|
787
|
-
}
|
|
838
|
+
safeJsx("handlers.removeObject(marquee.prevRect)", () => ctx.boardRef.current.removeObject(rect));
|
|
788
839
|
}
|
|
789
|
-
|
|
840
|
+
safeJsx("handlers.createMarqueePolygon", () => {
|
|
790
841
|
ctx.marqueeRef.current.rect = ctx.boardRef.current.create("polygon", [
|
|
791
842
|
[x1u, y1u],
|
|
792
843
|
[x2u, y1u],
|
|
@@ -801,8 +852,7 @@ function handleMove(ctx, e) {
|
|
|
801
852
|
highlight: false,
|
|
802
853
|
withLabel: false
|
|
803
854
|
});
|
|
804
|
-
}
|
|
805
|
-
}
|
|
855
|
+
});
|
|
806
856
|
}
|
|
807
857
|
return;
|
|
808
858
|
}
|
|
@@ -812,20 +862,20 @@ function handleMove(ctx, e) {
|
|
|
812
862
|
ctx.previewRafRef.current = requestAnimationFrame(() => {
|
|
813
863
|
ctx.previewRafRef.current = null;
|
|
814
864
|
if (!ctx.boardRef.current || !ctx.phantomRef.current) return;
|
|
815
|
-
|
|
865
|
+
safeJsx("handlers.phantomMove", () => {
|
|
816
866
|
const coords = ctx.boardRef.current.getUsrCoordsOfMouse(e);
|
|
817
867
|
const JXG = ctx.jxgRef.current;
|
|
818
868
|
if (!JXG) return;
|
|
819
869
|
ctx.phantomRef.current.setPositionDirectly(JXG.COORDS_BY_USER, [coords[0], coords[1]]);
|
|
820
870
|
ctx.boardRef.current.update();
|
|
821
|
-
}
|
|
822
|
-
}
|
|
871
|
+
});
|
|
823
872
|
});
|
|
824
873
|
}
|
|
825
874
|
var init_handlers = __esm({
|
|
826
875
|
"src/stamps/geometry-2d/editor/handlers.ts"() {
|
|
827
876
|
init_tools();
|
|
828
877
|
init_transforms();
|
|
878
|
+
init_safeJsx();
|
|
829
879
|
}
|
|
830
880
|
});
|
|
831
881
|
var JSXGraphMiniBoard;
|
|
@@ -836,6 +886,7 @@ var init_MiniBoard = __esm({
|
|
|
836
886
|
init_tools();
|
|
837
887
|
init_theme();
|
|
838
888
|
init_handlers();
|
|
889
|
+
init_safeJsx();
|
|
839
890
|
JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
840
891
|
const isDarkRef = react.useRef(!!isDark);
|
|
841
892
|
isDarkRef.current = !!isDark;
|
|
@@ -845,6 +896,7 @@ var init_MiniBoard = __esm({
|
|
|
845
896
|
const jxgRef = react.useRef(null);
|
|
846
897
|
const axisObjsRef = react.useRef({});
|
|
847
898
|
const creationLogRef = react.useRef([]);
|
|
899
|
+
const redoStackRef = react.useRef([]);
|
|
848
900
|
const [tool, setTool] = react.useState("move");
|
|
849
901
|
const toolRef = react.useRef("move");
|
|
850
902
|
toolRef.current = tool;
|
|
@@ -888,19 +940,31 @@ var init_MiniBoard = __esm({
|
|
|
888
940
|
const nextLocalId = react.useCallback(() => "j" + creationLogRef.current.length, []);
|
|
889
941
|
const resolveArgs = react.useCallback((args) => {
|
|
890
942
|
return args.map((a) => {
|
|
891
|
-
if (typeof a === "string"
|
|
892
|
-
return objMapRef.current.get(a);
|
|
943
|
+
if (typeof a === "string") {
|
|
944
|
+
if (objMapRef.current.has(a)) return objMapRef.current.get(a);
|
|
945
|
+
const m = /^(.+):border:(\d+)$/.exec(a);
|
|
946
|
+
if (m) {
|
|
947
|
+
const poly = objMapRef.current.get(m[1]);
|
|
948
|
+
const idx = parseInt(m[2], 10);
|
|
949
|
+
if (poly && Array.isArray(poly.borders) && poly.borders[idx]) {
|
|
950
|
+
return poly.borders[idx];
|
|
951
|
+
}
|
|
952
|
+
}
|
|
893
953
|
}
|
|
894
954
|
return a;
|
|
895
955
|
});
|
|
896
956
|
}, []);
|
|
957
|
+
const pushCreationLog = react.useCallback((entry) => {
|
|
958
|
+
creationLogRef.current.push(entry);
|
|
959
|
+
redoStackRef.current = [];
|
|
960
|
+
}, []);
|
|
897
961
|
const pushLog = react.useCallback(
|
|
898
962
|
(id, type, args, attrs, obj) => {
|
|
899
|
-
|
|
963
|
+
pushCreationLog({ id, type, args, attrs });
|
|
900
964
|
objMapRef.current.set(id, obj);
|
|
901
965
|
setHistoryTick((t) => t + 1);
|
|
902
966
|
},
|
|
903
|
-
[]
|
|
967
|
+
[pushCreationLog]
|
|
904
968
|
);
|
|
905
969
|
const create = react.useCallback(
|
|
906
970
|
(type, args, attrs = {}) => {
|
|
@@ -915,15 +979,27 @@ var init_MiniBoard = __esm({
|
|
|
915
979
|
[nextLocalId, resolveArgs, pushLog]
|
|
916
980
|
);
|
|
917
981
|
const localIdOf = react.useCallback((obj) => {
|
|
982
|
+
if (!obj) return null;
|
|
918
983
|
for (const [id, o] of objMapRef.current.entries()) {
|
|
919
984
|
if (o === obj) return id;
|
|
920
985
|
}
|
|
986
|
+
for (const [id, o] of objMapRef.current.entries()) {
|
|
987
|
+
const borders = o?.borders;
|
|
988
|
+
if (Array.isArray(borders)) {
|
|
989
|
+
const idx = borders.indexOf(obj);
|
|
990
|
+
if (idx >= 0) return `${id}:border:${idx}`;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
921
993
|
return null;
|
|
922
994
|
}, []);
|
|
923
995
|
const snapshotObject = react.useCallback((obj, anchorScreen) => {
|
|
924
996
|
const o = obj;
|
|
925
997
|
const k = objKind(o);
|
|
926
998
|
if (k !== "point" && k !== "line" && k !== "circle") return null;
|
|
999
|
+
for (const owner of objMapRef.current.values()) {
|
|
1000
|
+
const borders = owner?.borders;
|
|
1001
|
+
if (Array.isArray(borders) && borders.indexOf(o) >= 0) return null;
|
|
1002
|
+
}
|
|
927
1003
|
const v = o.visProp ?? {};
|
|
928
1004
|
const showLabel = v.withlabel !== false;
|
|
929
1005
|
const showValue = valueLabelsRef.current.has(o);
|
|
@@ -983,16 +1059,10 @@ var init_MiniBoard = __esm({
|
|
|
983
1059
|
if (patch.remove) {
|
|
984
1060
|
const vl = valueLabelsRef.current.get(o);
|
|
985
1061
|
if (vl) {
|
|
986
|
-
|
|
987
|
-
boardRef.current.removeObject(vl);
|
|
988
|
-
} catch {
|
|
989
|
-
}
|
|
1062
|
+
safeJsx("MiniBoard.removeObject(valueLabel)", () => boardRef.current.removeObject(vl));
|
|
990
1063
|
valueLabelsRef.current.delete(o);
|
|
991
1064
|
}
|
|
992
|
-
|
|
993
|
-
boardRef.current.removeObject(o);
|
|
994
|
-
} catch {
|
|
995
|
-
}
|
|
1065
|
+
safeJsx("MiniBoard.removeObject(target)", () => boardRef.current.removeObject(o));
|
|
996
1066
|
const board = boardRef.current;
|
|
997
1067
|
const aliveIds = /* @__PURE__ */ new Set();
|
|
998
1068
|
for (const [id, obj2] of objMapRef.current.entries()) {
|
|
@@ -1017,7 +1087,7 @@ var init_MiniBoard = __esm({
|
|
|
1017
1087
|
const targetId = localIdOf(o);
|
|
1018
1088
|
if (targetId) {
|
|
1019
1089
|
const id = nextLocalId();
|
|
1020
|
-
|
|
1090
|
+
pushCreationLog({ id, type: "valueLabel", args: [targetId], attrs: {} });
|
|
1021
1091
|
objMapRef.current.set(id, txt);
|
|
1022
1092
|
setHistoryTick((t) => t + 1);
|
|
1023
1093
|
}
|
|
@@ -1026,10 +1096,7 @@ var init_MiniBoard = __esm({
|
|
|
1026
1096
|
const txt = valueLabelsRef.current.get(o);
|
|
1027
1097
|
valueLabelsRef.current.delete(o);
|
|
1028
1098
|
if (txt) {
|
|
1029
|
-
|
|
1030
|
-
boardRef.current.removeObject(txt);
|
|
1031
|
-
} catch {
|
|
1032
|
-
}
|
|
1099
|
+
safeJsx("MiniBoard.removeObject(valueLabel.text)", () => boardRef.current.removeObject(txt));
|
|
1033
1100
|
const txtId = localIdOf(txt);
|
|
1034
1101
|
if (txtId) {
|
|
1035
1102
|
creationLogRef.current = creationLogRef.current.filter((e) => e.id !== txtId);
|
|
@@ -1040,10 +1107,7 @@ var init_MiniBoard = __esm({
|
|
|
1040
1107
|
}
|
|
1041
1108
|
}
|
|
1042
1109
|
if (patch.attrs) {
|
|
1043
|
-
|
|
1044
|
-
o.setAttribute(patch.attrs);
|
|
1045
|
-
} catch {
|
|
1046
|
-
}
|
|
1110
|
+
safeJsx("MiniBoard.setAttribute", () => o.setAttribute(patch.attrs));
|
|
1047
1111
|
const id = localIdOf(o);
|
|
1048
1112
|
if (id) {
|
|
1049
1113
|
const entry = creationLogRef.current.find((e) => e.id === id);
|
|
@@ -1051,19 +1115,13 @@ var init_MiniBoard = __esm({
|
|
|
1051
1115
|
setHistoryTick((t) => t + 1);
|
|
1052
1116
|
}
|
|
1053
1117
|
}
|
|
1054
|
-
|
|
1055
|
-
boardRef.current.update();
|
|
1056
|
-
} catch {
|
|
1057
|
-
}
|
|
1118
|
+
safeJsx("MiniBoard.board.update(mutate)", () => boardRef.current.update());
|
|
1058
1119
|
}, [createValueLabelFor, localIdOf, nextLocalId]);
|
|
1059
1120
|
const clearPreviewSegs = react.useCallback(() => {
|
|
1060
1121
|
const b = boardRef.current;
|
|
1061
1122
|
if (!b) return;
|
|
1062
1123
|
for (const s of previewSegRef.current) {
|
|
1063
|
-
|
|
1064
|
-
b.removeObject(s);
|
|
1065
|
-
} catch {
|
|
1066
|
-
}
|
|
1124
|
+
safeJsx("MiniBoard.removeObject(previewSeg)", () => b.removeObject(s));
|
|
1067
1125
|
}
|
|
1068
1126
|
previewSegRef.current = [];
|
|
1069
1127
|
}, []);
|
|
@@ -1071,17 +1129,11 @@ var init_MiniBoard = __esm({
|
|
|
1071
1129
|
const b = boardRef.current;
|
|
1072
1130
|
if (!b) return;
|
|
1073
1131
|
if (previewShapeRef.current) {
|
|
1074
|
-
|
|
1075
|
-
b.removeObject(previewShapeRef.current);
|
|
1076
|
-
} catch {
|
|
1077
|
-
}
|
|
1132
|
+
safeJsx("MiniBoard.removeObject(previewShape)", () => b.removeObject(previewShapeRef.current));
|
|
1078
1133
|
previewShapeRef.current = null;
|
|
1079
1134
|
}
|
|
1080
1135
|
if (phantomRef.current) {
|
|
1081
|
-
|
|
1082
|
-
b.removeObject(phantomRef.current);
|
|
1083
|
-
} catch {
|
|
1084
|
-
}
|
|
1136
|
+
safeJsx("MiniBoard.removeObject(phantom)", () => b.removeObject(phantomRef.current));
|
|
1085
1137
|
phantomRef.current = null;
|
|
1086
1138
|
}
|
|
1087
1139
|
}, []);
|
|
@@ -1093,7 +1145,7 @@ var init_MiniBoard = __esm({
|
|
|
1093
1145
|
}, [clearPreviewSegs, removePhantom]);
|
|
1094
1146
|
const applySelectionStyle = react.useCallback((obj) => {
|
|
1095
1147
|
if (!obj || selOriginalRef.current.has(obj)) return;
|
|
1096
|
-
|
|
1148
|
+
safeJsx("MiniBoard.applySelectionStyle", () => {
|
|
1097
1149
|
const visProp = obj.visProp ?? {};
|
|
1098
1150
|
selOriginalRef.current.set(obj, {
|
|
1099
1151
|
strokeColor: visProp.strokecolor,
|
|
@@ -1105,19 +1157,17 @@ var init_MiniBoard = __esm({
|
|
|
1105
1157
|
} else {
|
|
1106
1158
|
obj.setAttribute({ strokeColor: "#06b6d4", strokeWidth: 3 });
|
|
1107
1159
|
}
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1160
|
+
});
|
|
1110
1161
|
}, []);
|
|
1111
1162
|
const restoreSelectionStyle = react.useCallback((obj) => {
|
|
1112
1163
|
const orig = selOriginalRef.current.get(obj);
|
|
1113
1164
|
if (!orig) return;
|
|
1114
|
-
|
|
1165
|
+
safeJsx("MiniBoard.restoreSelectionStyle", () => {
|
|
1115
1166
|
const attrs = {};
|
|
1116
1167
|
if (orig.strokeColor !== void 0) attrs.strokeColor = orig.strokeColor;
|
|
1117
1168
|
if (orig.strokeWidth !== void 0) attrs.strokeWidth = orig.strokeWidth;
|
|
1118
1169
|
obj.setAttribute(attrs);
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1170
|
+
});
|
|
1121
1171
|
selOriginalRef.current.delete(obj);
|
|
1122
1172
|
}, []);
|
|
1123
1173
|
const clearSelection = react.useCallback(() => {
|
|
@@ -1126,10 +1176,7 @@ var init_MiniBoard = __esm({
|
|
|
1126
1176
|
}
|
|
1127
1177
|
selectedSetRef.current.clear();
|
|
1128
1178
|
setSelectionTick((t) => t + 1);
|
|
1129
|
-
|
|
1130
|
-
boardRef.current?.update();
|
|
1131
|
-
} catch {
|
|
1132
|
-
}
|
|
1179
|
+
safeJsx("MiniBoard.board.update(clearSelection)", () => boardRef.current?.update());
|
|
1133
1180
|
}, [restoreSelectionStyle]);
|
|
1134
1181
|
const toggleSelect = react.useCallback((obj, additive) => {
|
|
1135
1182
|
if (!obj) return;
|
|
@@ -1149,10 +1196,7 @@ var init_MiniBoard = __esm({
|
|
|
1149
1196
|
}
|
|
1150
1197
|
}
|
|
1151
1198
|
setSelectionTick((t) => t + 1);
|
|
1152
|
-
|
|
1153
|
-
boardRef.current?.update();
|
|
1154
|
-
} catch {
|
|
1155
|
-
}
|
|
1199
|
+
safeJsx("MiniBoard.board.update(toggleSelect)", () => boardRef.current?.update());
|
|
1156
1200
|
}, [applySelectionStyle, restoreSelectionStyle]);
|
|
1157
1201
|
const deleteSelected = react.useCallback(() => {
|
|
1158
1202
|
const board = boardRef.current;
|
|
@@ -1160,10 +1204,7 @@ var init_MiniBoard = __esm({
|
|
|
1160
1204
|
if (selectedSetRef.current.size === 0) return;
|
|
1161
1205
|
for (const o of selectedSetRef.current) selOriginalRef.current.delete(o);
|
|
1162
1206
|
for (const o of selectedSetRef.current) {
|
|
1163
|
-
|
|
1164
|
-
board.removeObject(o);
|
|
1165
|
-
} catch {
|
|
1166
|
-
}
|
|
1207
|
+
safeJsx("MiniBoard.removeObject(selected)", () => board.removeObject(o));
|
|
1167
1208
|
}
|
|
1168
1209
|
selectedSetRef.current.clear();
|
|
1169
1210
|
const aliveIds = /* @__PURE__ */ new Set();
|
|
@@ -1236,10 +1277,7 @@ var init_MiniBoard = __esm({
|
|
|
1236
1277
|
const b = boardRef.current;
|
|
1237
1278
|
if (!b) return;
|
|
1238
1279
|
if (previewShapeRef.current) {
|
|
1239
|
-
|
|
1240
|
-
b.removeObject(previewShapeRef.current);
|
|
1241
|
-
} catch {
|
|
1242
|
-
}
|
|
1280
|
+
safeJsx("MiniBoard.removeObject(refreshPreview)", () => b.removeObject(previewShapeRef.current));
|
|
1243
1281
|
previewShapeRef.current = null;
|
|
1244
1282
|
}
|
|
1245
1283
|
const t = toolRef.current;
|
|
@@ -1358,7 +1396,7 @@ var init_MiniBoard = __esm({
|
|
|
1358
1396
|
}
|
|
1359
1397
|
case "toggleLabel": {
|
|
1360
1398
|
const obj = picks[0];
|
|
1361
|
-
|
|
1399
|
+
safeJsx("MiniBoard.toggleLabel", () => {
|
|
1362
1400
|
if (obj.label) {
|
|
1363
1401
|
const visible = obj.label.visProp.visible !== false;
|
|
1364
1402
|
obj.label.setAttribute({ visible: !visible });
|
|
@@ -1367,23 +1405,21 @@ var init_MiniBoard = __esm({
|
|
|
1367
1405
|
obj.setAttribute({ withLabel: !cur });
|
|
1368
1406
|
}
|
|
1369
1407
|
boardRef.current.update();
|
|
1370
|
-
}
|
|
1371
|
-
}
|
|
1408
|
+
});
|
|
1372
1409
|
break;
|
|
1373
1410
|
}
|
|
1374
1411
|
case "toggleVisible": {
|
|
1375
1412
|
const obj = picks[0];
|
|
1376
|
-
|
|
1413
|
+
safeJsx("MiniBoard.toggleVisible", () => {
|
|
1377
1414
|
const visible = obj.visProp.visible !== false;
|
|
1378
1415
|
obj.setAttribute({ visible: !visible });
|
|
1379
1416
|
boardRef.current.update();
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1417
|
+
});
|
|
1382
1418
|
break;
|
|
1383
1419
|
}
|
|
1384
1420
|
case "delete": {
|
|
1385
1421
|
const obj = picks[0];
|
|
1386
|
-
|
|
1422
|
+
safeJsx("MiniBoard.deleteOne", () => {
|
|
1387
1423
|
boardRef.current.removeObject(obj);
|
|
1388
1424
|
const board = boardRef.current;
|
|
1389
1425
|
const aliveIds = /* @__PURE__ */ new Set();
|
|
@@ -1398,8 +1434,7 @@ var init_MiniBoard = __esm({
|
|
|
1398
1434
|
if (!aliveIds.has(id)) objMapRef.current.delete(id);
|
|
1399
1435
|
}
|
|
1400
1436
|
setHistoryTick((t) => t + 1);
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1437
|
+
});
|
|
1403
1438
|
break;
|
|
1404
1439
|
}
|
|
1405
1440
|
}
|
|
@@ -1434,7 +1469,7 @@ var init_MiniBoard = __esm({
|
|
|
1434
1469
|
}
|
|
1435
1470
|
const stepId = nextLocalId();
|
|
1436
1471
|
const stepObj = boardRef.current.create("transform", step.params, step.attrs);
|
|
1437
|
-
|
|
1472
|
+
pushCreationLog({ id: stepId, type: "transform", args: stepLogArgs, attrs: step.attrs });
|
|
1438
1473
|
objMapRef.current.set(stepId, stepObj);
|
|
1439
1474
|
transformObjs.push(stepObj);
|
|
1440
1475
|
transformIds.push(stepId);
|
|
@@ -1448,7 +1483,7 @@ var init_MiniBoard = __esm({
|
|
|
1448
1483
|
const newName = srcName ? `${srcName}'` : nextLabel();
|
|
1449
1484
|
const attrs = { name: newName, size: 3, color: "#0ea5e9", strokeColor: "#0ea5e9", fillColor: "#0ea5e9" };
|
|
1450
1485
|
const obj = boardRef.current.create("point", [src, transformParent], attrs);
|
|
1451
|
-
|
|
1486
|
+
pushCreationLog({ id, type: "point", args: [srcId ?? src, transformLogRef], attrs });
|
|
1452
1487
|
objMapRef.current.set(id, obj);
|
|
1453
1488
|
return obj;
|
|
1454
1489
|
});
|
|
@@ -1479,6 +1514,45 @@ var init_MiniBoard = __esm({
|
|
|
1479
1514
|
}
|
|
1480
1515
|
setHistoryTick((t) => t + 1);
|
|
1481
1516
|
}, [create, flashWarn, localIdOf, nextLabel, nextLocalId]);
|
|
1517
|
+
const recreateFromLogEntry = react.useCallback((el) => {
|
|
1518
|
+
const board = boardRef.current;
|
|
1519
|
+
if (!board) return false;
|
|
1520
|
+
const idMap = objMapRef.current;
|
|
1521
|
+
const resolve = (a) => {
|
|
1522
|
+
if (typeof a === "string") {
|
|
1523
|
+
if (idMap.has(a)) return idMap.get(a);
|
|
1524
|
+
const m = /^(.+):border:(\d+)$/.exec(a);
|
|
1525
|
+
if (m) {
|
|
1526
|
+
const poly = idMap.get(m[1]);
|
|
1527
|
+
const idx = parseInt(m[2], 10);
|
|
1528
|
+
if (poly && Array.isArray(poly.borders) && poly.borders[idx]) {
|
|
1529
|
+
return poly.borders[idx];
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (Array.isArray(a)) return a.map(resolve);
|
|
1534
|
+
return a;
|
|
1535
|
+
};
|
|
1536
|
+
const resolved = el.args.map(resolve);
|
|
1537
|
+
try {
|
|
1538
|
+
if (el.type === "valueLabel") {
|
|
1539
|
+
const target = resolved[0];
|
|
1540
|
+
if (!target) return false;
|
|
1541
|
+
const txt = createValueLabelFor(target);
|
|
1542
|
+
if (!txt) return false;
|
|
1543
|
+
idMap.set(el.id, txt);
|
|
1544
|
+
valueLabelsRef.current.set(target, txt);
|
|
1545
|
+
return true;
|
|
1546
|
+
}
|
|
1547
|
+
const themedAttrs = resolveAttrColors({ ...el.attrs }, paletteFor(isDarkRef.current));
|
|
1548
|
+
const obj = board.create(el.type, resolved, themedAttrs);
|
|
1549
|
+
idMap.set(el.id, obj);
|
|
1550
|
+
return true;
|
|
1551
|
+
} catch (err) {
|
|
1552
|
+
console.warn("Recreate failed for", el.type, err);
|
|
1553
|
+
return false;
|
|
1554
|
+
}
|
|
1555
|
+
}, [createValueLabelFor]);
|
|
1482
1556
|
const undoLast = react.useCallback(() => {
|
|
1483
1557
|
const b = boardRef.current;
|
|
1484
1558
|
if (!b) return;
|
|
@@ -1488,21 +1562,31 @@ var init_MiniBoard = __esm({
|
|
|
1488
1562
|
const obj = objMapRef.current.get(last.id);
|
|
1489
1563
|
objMapRef.current.delete(last.id);
|
|
1490
1564
|
if (obj) {
|
|
1491
|
-
|
|
1492
|
-
b.removeObject(obj);
|
|
1493
|
-
} catch {
|
|
1494
|
-
}
|
|
1565
|
+
safeJsx("MiniBoard.removeObject(undo)", () => b.removeObject(obj));
|
|
1495
1566
|
clearPending();
|
|
1567
|
+
redoStackRef.current.push(last);
|
|
1496
1568
|
setHistoryTick((t) => t + 1);
|
|
1497
|
-
|
|
1498
|
-
b.update();
|
|
1499
|
-
} catch {
|
|
1500
|
-
}
|
|
1569
|
+
safeJsx("MiniBoard.board.update(undo)", () => b.update());
|
|
1501
1570
|
return;
|
|
1502
1571
|
}
|
|
1503
1572
|
}
|
|
1504
1573
|
setHistoryTick((t) => t + 1);
|
|
1505
1574
|
}, [clearPending]);
|
|
1575
|
+
const redoNext = react.useCallback(() => {
|
|
1576
|
+
const b = boardRef.current;
|
|
1577
|
+
if (!b) return;
|
|
1578
|
+
const entry = redoStackRef.current.pop();
|
|
1579
|
+
if (!entry) {
|
|
1580
|
+
setHistoryTick((t) => t + 1);
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
const ok = recreateFromLogEntry(entry);
|
|
1584
|
+
if (ok) {
|
|
1585
|
+
creationLogRef.current.push(entry);
|
|
1586
|
+
}
|
|
1587
|
+
setHistoryTick((t) => t + 1);
|
|
1588
|
+
safeJsx("MiniBoard.board.update(redo)", () => b.update());
|
|
1589
|
+
}, [recreateFromLogEntry]);
|
|
1506
1590
|
react.useEffect(() => {
|
|
1507
1591
|
const onKey = (e) => {
|
|
1508
1592
|
const ae = document.activeElement;
|
|
@@ -1514,6 +1598,13 @@ var init_MiniBoard = __esm({
|
|
|
1514
1598
|
undoLastRef.current();
|
|
1515
1599
|
return;
|
|
1516
1600
|
}
|
|
1601
|
+
if ((e.metaKey || e.ctrlKey) && (e.key.toLowerCase() === "z" && e.shiftKey || e.key.toLowerCase() === "y" && !e.shiftKey)) {
|
|
1602
|
+
if (inField) return;
|
|
1603
|
+
e.preventDefault();
|
|
1604
|
+
e.stopPropagation();
|
|
1605
|
+
redoNextRef.current();
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1517
1608
|
if (e.key === "Escape" && !inField) {
|
|
1518
1609
|
if (pendingRef.current.length > 0) {
|
|
1519
1610
|
e.preventDefault();
|
|
@@ -1560,16 +1651,14 @@ var init_MiniBoard = __esm({
|
|
|
1560
1651
|
if (!sc) return [];
|
|
1561
1652
|
const [sx, sy] = sc;
|
|
1562
1653
|
const list = [];
|
|
1563
|
-
|
|
1654
|
+
safeJsx("MiniBoard.objectsAt.loop", () => {
|
|
1564
1655
|
const objs = b.objectsList || [];
|
|
1565
1656
|
for (const o of objs) {
|
|
1566
|
-
|
|
1657
|
+
safeJsx("MiniBoard.objectsAt.hasPoint", () => {
|
|
1567
1658
|
if (o.hasPoint && o.hasPoint(sx, sy)) list.push(o);
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1659
|
+
});
|
|
1570
1660
|
}
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1661
|
+
});
|
|
1573
1662
|
return list;
|
|
1574
1663
|
}, [screenCoordsOf]);
|
|
1575
1664
|
const findNearestPoint = react.useCallback((evt, tolPx = 12) => {
|
|
@@ -1579,24 +1668,23 @@ var init_MiniBoard = __esm({
|
|
|
1579
1668
|
if (!sc) return null;
|
|
1580
1669
|
const [sx, sy] = sc;
|
|
1581
1670
|
const tol2 = tolPx * tolPx;
|
|
1582
|
-
|
|
1583
|
-
|
|
1671
|
+
const bestRef = { current: null };
|
|
1672
|
+
safeJsx("MiniBoard.findNearestPoint.loop", () => {
|
|
1584
1673
|
const objs = b.objectsList || [];
|
|
1585
1674
|
for (const o of objs) {
|
|
1586
|
-
|
|
1587
|
-
if (objKind(o) !== "point")
|
|
1675
|
+
safeJsx("MiniBoard.findNearestPoint.iter", () => {
|
|
1676
|
+
if (objKind(o) !== "point") return;
|
|
1588
1677
|
const pc = o.coords?.scrCoords;
|
|
1589
|
-
if (!pc)
|
|
1678
|
+
if (!pc) return;
|
|
1590
1679
|
const dx = pc[1] - sx;
|
|
1591
1680
|
const dy = pc[2] - sy;
|
|
1592
1681
|
const d2 = dx * dx + dy * dy;
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
}
|
|
1682
|
+
const cur = bestRef.current;
|
|
1683
|
+
if (d2 <= tol2 && (!cur || d2 < cur.d2)) bestRef.current = { obj: o, d2 };
|
|
1684
|
+
});
|
|
1596
1685
|
}
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
return best ? best.obj : null;
|
|
1686
|
+
});
|
|
1687
|
+
return bestRef.current ? bestRef.current.obj : null;
|
|
1600
1688
|
}, [screenCoordsOf]);
|
|
1601
1689
|
const promoteLabel = react.useCallback((o) => {
|
|
1602
1690
|
if (!o) return o;
|
|
@@ -1604,31 +1692,25 @@ var init_MiniBoard = __esm({
|
|
|
1604
1692
|
if (t !== "text") return o;
|
|
1605
1693
|
const b = boardRef.current;
|
|
1606
1694
|
if (!b) return o;
|
|
1607
|
-
|
|
1695
|
+
const promoted = safeJsx("MiniBoard.promoteLabel", () => {
|
|
1608
1696
|
for (const c of b.objectsList || []) {
|
|
1609
1697
|
if (c.label === o) return c;
|
|
1610
1698
|
}
|
|
1611
|
-
|
|
1612
|
-
}
|
|
1613
|
-
return o;
|
|
1699
|
+
return null;
|
|
1700
|
+
}, null);
|
|
1701
|
+
return promoted ?? o;
|
|
1614
1702
|
}, []);
|
|
1615
1703
|
const pendingTransformRef = react.useRef(null);
|
|
1616
1704
|
const transformSubsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
1617
1705
|
const emitTransform = react.useCallback((info) => {
|
|
1618
1706
|
transformSubsRef.current.forEach((cb) => {
|
|
1619
|
-
|
|
1620
|
-
cb(info);
|
|
1621
|
-
} catch {
|
|
1622
|
-
}
|
|
1707
|
+
safeJsx("MiniBoard.emitTransform.cb", () => cb(info));
|
|
1623
1708
|
});
|
|
1624
1709
|
}, []);
|
|
1625
1710
|
const selectSubsRef = react.useRef(/* @__PURE__ */ new Set());
|
|
1626
1711
|
const emitSelect = react.useCallback((snap) => {
|
|
1627
1712
|
selectSubsRef.current.forEach((cb) => {
|
|
1628
|
-
|
|
1629
|
-
cb(snap);
|
|
1630
|
-
} catch {
|
|
1631
|
-
}
|
|
1713
|
+
safeJsx("MiniBoard.emitSelect.cb", () => cb(snap));
|
|
1632
1714
|
});
|
|
1633
1715
|
}, []);
|
|
1634
1716
|
const moveDownRef = react.useRef(null);
|
|
@@ -1640,7 +1722,7 @@ var init_MiniBoard = __esm({
|
|
|
1640
1722
|
const JXG = (await import('jsxgraph')).default;
|
|
1641
1723
|
if (cancelled || !containerRef.current) return;
|
|
1642
1724
|
jxgRef.current = JXG;
|
|
1643
|
-
|
|
1725
|
+
safeJsx("MiniBoard.applyJxgOptions", () => {
|
|
1644
1726
|
const opts = JXG.Options;
|
|
1645
1727
|
if (opts) {
|
|
1646
1728
|
opts.text = opts.text || {};
|
|
@@ -1653,8 +1735,7 @@ var init_MiniBoard = __esm({
|
|
|
1653
1735
|
opts.label.strokeColor = themeLabel(isDarkRef.current);
|
|
1654
1736
|
opts.text.strokeColor = themeLabel(isDarkRef.current);
|
|
1655
1737
|
}
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1738
|
+
});
|
|
1658
1739
|
const board = JXG.JSXGraph.initBoard(containerId, {
|
|
1659
1740
|
boundingbox: initialState?.bbox ?? [-10, 10, 10, -10],
|
|
1660
1741
|
axis: false,
|
|
@@ -1675,43 +1756,20 @@ var init_MiniBoard = __esm({
|
|
|
1675
1756
|
});
|
|
1676
1757
|
boardRef.current = board;
|
|
1677
1758
|
if (initialState && initialState.elements.length > 0) {
|
|
1678
|
-
const idMap = objMapRef.current;
|
|
1679
1759
|
for (const el of initialState.elements) {
|
|
1680
|
-
|
|
1681
|
-
try {
|
|
1682
|
-
if (el.type === "valueLabel") {
|
|
1683
|
-
const target = resolved[0];
|
|
1684
|
-
if (target) {
|
|
1685
|
-
const txt = createValueLabelFor(target);
|
|
1686
|
-
if (txt) {
|
|
1687
|
-
idMap.set(el.id, txt);
|
|
1688
|
-
valueLabelsRef.current.set(target, txt);
|
|
1689
|
-
}
|
|
1690
|
-
}
|
|
1691
|
-
continue;
|
|
1692
|
-
}
|
|
1693
|
-
const themedAttrs = resolveAttrColors({ ...el.attrs }, paletteFor(isDarkRef.current));
|
|
1694
|
-
const obj = board.create(el.type, resolved, themedAttrs);
|
|
1695
|
-
idMap.set(el.id, obj);
|
|
1696
|
-
} catch (err) {
|
|
1697
|
-
console.warn("Replay failed for", el.type, err);
|
|
1698
|
-
}
|
|
1760
|
+
recreateFromLogEntry(el);
|
|
1699
1761
|
}
|
|
1700
1762
|
creationLogRef.current = [...initialState.elements];
|
|
1701
1763
|
labelIdxRef.current = initialState.elements.filter((e) => e.type === "point").length;
|
|
1702
1764
|
}
|
|
1703
1765
|
if (showAxisRef.current) {
|
|
1704
|
-
|
|
1766
|
+
safeJsx("MiniBoard.initAxes", () => {
|
|
1705
1767
|
axisObjsRef.current.x = board.create("axis", [[0, 0], [1, 0]], { strokeColor: themeAxis(isDarkRef.current), name: "", withLabel: false });
|
|
1706
1768
|
axisObjsRef.current.y = board.create("axis", [[0, 0], [0, 1]], { strokeColor: themeAxis(isDarkRef.current), name: "", withLabel: false });
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1769
|
+
});
|
|
1709
1770
|
}
|
|
1710
1771
|
if (showGridRef.current) {
|
|
1711
|
-
|
|
1712
|
-
board.create("grid", [], { strokeColor: themeGrid(isDarkRef.current), strokeOpacity: 1 });
|
|
1713
|
-
} catch {
|
|
1714
|
-
}
|
|
1772
|
+
safeJsx("MiniBoard.initGrid", () => board.create("grid", [], { strokeColor: themeGrid(isDarkRef.current), strokeOpacity: 1 }));
|
|
1715
1773
|
}
|
|
1716
1774
|
board.on("down", (e) => {
|
|
1717
1775
|
const ctx = {
|
|
@@ -1862,6 +1920,8 @@ var init_MiniBoard = __esm({
|
|
|
1862
1920
|
setShowGrid: (b) => setShowGridRef.current(b),
|
|
1863
1921
|
undo: () => undoLastRef.current(),
|
|
1864
1922
|
canUndo: () => creationLogRef.current.length > 0,
|
|
1923
|
+
redo: () => redoNextRef.current(),
|
|
1924
|
+
canRedo: () => redoStackRef.current.length > 0,
|
|
1865
1925
|
subscribe: (cb) => {
|
|
1866
1926
|
subscribersRef.current.add(cb);
|
|
1867
1927
|
return () => {
|
|
@@ -1874,15 +1934,14 @@ var init_MiniBoard = __esm({
|
|
|
1874
1934
|
const b = boardRef.current;
|
|
1875
1935
|
if (!b) return [];
|
|
1876
1936
|
const out = [];
|
|
1877
|
-
|
|
1937
|
+
safeJsx("MiniBoard.getAllPointNames", () => {
|
|
1878
1938
|
const objs = b.objectsList || [];
|
|
1879
1939
|
for (const o of objs) {
|
|
1880
1940
|
if (objKind(o) === "point" && typeof o.name === "string" && o.name) {
|
|
1881
1941
|
out.push(o.name);
|
|
1882
1942
|
}
|
|
1883
1943
|
}
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1944
|
+
});
|
|
1886
1945
|
return out;
|
|
1887
1946
|
},
|
|
1888
1947
|
onSelect: (cb) => {
|
|
@@ -1943,10 +2002,7 @@ var init_MiniBoard = __esm({
|
|
|
1943
2002
|
previewRafRef.current = null;
|
|
1944
2003
|
}
|
|
1945
2004
|
if (boardRef.current && jxgRef.current) {
|
|
1946
|
-
|
|
1947
|
-
jxgRef.current.JSXGraph.freeBoard(boardRef.current);
|
|
1948
|
-
} catch {
|
|
1949
|
-
}
|
|
2005
|
+
safeJsx("MiniBoard.freeBoard", () => jxgRef.current.JSXGraph.freeBoard(boardRef.current));
|
|
1950
2006
|
boardRef.current = null;
|
|
1951
2007
|
}
|
|
1952
2008
|
};
|
|
@@ -1954,19 +2010,13 @@ var init_MiniBoard = __esm({
|
|
|
1954
2010
|
react.useEffect(() => {
|
|
1955
2011
|
const b = boardRef.current;
|
|
1956
2012
|
if (!b) return;
|
|
1957
|
-
|
|
2013
|
+
safeJsx("MiniBoard.toggleAxis", () => {
|
|
1958
2014
|
if (axisObjsRef.current.x) {
|
|
1959
|
-
|
|
1960
|
-
b.removeObject(axisObjsRef.current.x);
|
|
1961
|
-
} catch {
|
|
1962
|
-
}
|
|
2015
|
+
safeJsx("MiniBoard.removeObject(axisX)", () => b.removeObject(axisObjsRef.current.x));
|
|
1963
2016
|
axisObjsRef.current.x = void 0;
|
|
1964
2017
|
}
|
|
1965
2018
|
if (axisObjsRef.current.y) {
|
|
1966
|
-
|
|
1967
|
-
b.removeObject(axisObjsRef.current.y);
|
|
1968
|
-
} catch {
|
|
1969
|
-
}
|
|
2019
|
+
safeJsx("MiniBoard.removeObject(axisY)", () => b.removeObject(axisObjsRef.current.y));
|
|
1970
2020
|
axisObjsRef.current.y = void 0;
|
|
1971
2021
|
}
|
|
1972
2022
|
if (showAxis) {
|
|
@@ -1974,28 +2024,23 @@ var init_MiniBoard = __esm({
|
|
|
1974
2024
|
axisObjsRef.current.y = b.create("axis", [[0, 0], [0, 1]], { strokeColor: themeAxis(isDarkRef.current), name: "", withLabel: false });
|
|
1975
2025
|
}
|
|
1976
2026
|
b.update();
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
2027
|
+
});
|
|
1979
2028
|
}, [showAxis]);
|
|
1980
2029
|
react.useEffect(() => {
|
|
1981
2030
|
const b = boardRef.current;
|
|
1982
2031
|
if (!b) return;
|
|
1983
|
-
|
|
2032
|
+
safeJsx("MiniBoard.toggleGrid", () => {
|
|
1984
2033
|
const objs = Object.values(b.objects || {});
|
|
1985
2034
|
for (const o of objs) {
|
|
1986
2035
|
if (o && (o.elType === "grid" || o.type === "grid" || o.visProp && o.visProp.type === "grid")) {
|
|
1987
|
-
|
|
1988
|
-
b.removeObject(o);
|
|
1989
|
-
} catch {
|
|
1990
|
-
}
|
|
2036
|
+
safeJsx("MiniBoard.removeObject(grid)", () => b.removeObject(o));
|
|
1991
2037
|
}
|
|
1992
2038
|
}
|
|
1993
2039
|
if (showGrid) {
|
|
1994
2040
|
b.create("grid", [], { strokeColor: themeGrid(isDarkRef.current), strokeOpacity: 1 });
|
|
1995
2041
|
}
|
|
1996
2042
|
b.update();
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
2043
|
+
});
|
|
1999
2044
|
}, [showGrid]);
|
|
2000
2045
|
const handleToolChange = react.useCallback((t) => {
|
|
2001
2046
|
clearPending();
|
|
@@ -2003,10 +2048,9 @@ var init_MiniBoard = __esm({
|
|
|
2003
2048
|
setTool(t);
|
|
2004
2049
|
const b = boardRef.current;
|
|
2005
2050
|
if (b) {
|
|
2006
|
-
|
|
2051
|
+
safeJsx("MiniBoard.setPanForTool", () => {
|
|
2007
2052
|
if (b.attr?.pan) b.attr.pan.enabled = t !== "select";
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2053
|
+
});
|
|
2010
2054
|
}
|
|
2011
2055
|
}, [clearPending]);
|
|
2012
2056
|
const handleToolChangeRef = react.useRef(handleToolChange);
|
|
@@ -2014,10 +2058,7 @@ var init_MiniBoard = __esm({
|
|
|
2014
2058
|
const subscribersRef = react.useRef(/* @__PURE__ */ new Set());
|
|
2015
2059
|
const notifySubscribers = react.useCallback(() => {
|
|
2016
2060
|
subscribersRef.current.forEach((cb) => {
|
|
2017
|
-
|
|
2018
|
-
cb();
|
|
2019
|
-
} catch {
|
|
2020
|
-
}
|
|
2061
|
+
safeJsx("MiniBoard.notifySubscriber.cb", () => cb());
|
|
2021
2062
|
});
|
|
2022
2063
|
}, []);
|
|
2023
2064
|
react.useEffect(() => {
|
|
@@ -2025,6 +2066,8 @@ var init_MiniBoard = __esm({
|
|
|
2025
2066
|
}, [tool, showAxis, showGrid, historyTick, notifySubscribers]);
|
|
2026
2067
|
const undoLastRef = react.useRef(undoLast);
|
|
2027
2068
|
undoLastRef.current = undoLast;
|
|
2069
|
+
const redoNextRef = react.useRef(redoNext);
|
|
2070
|
+
redoNextRef.current = redoNext;
|
|
2028
2071
|
const clearPendingRef = react.useRef(clearPending);
|
|
2029
2072
|
clearPendingRef.current = clearPending;
|
|
2030
2073
|
const finalizeTransformCreateRef = react.useRef(finalizeTransformCreate);
|
|
@@ -2135,6 +2178,7 @@ function MobileToolDrawer({
|
|
|
2135
2178
|
disabled: a.disabled,
|
|
2136
2179
|
"aria-label": a.label,
|
|
2137
2180
|
title: a.title ?? a.label,
|
|
2181
|
+
"data-testid": a.testId,
|
|
2138
2182
|
className: "inline-flex h-9 w-9 items-center justify-center rounded-full text-slate-600 transition hover:bg-slate-100 hover:text-slate-900 disabled:cursor-not-allowed disabled:text-slate-300 disabled:hover:bg-transparent",
|
|
2139
2183
|
children: a.icon
|
|
2140
2184
|
},
|
|
@@ -2240,6 +2284,12 @@ function UndoIcon() {
|
|
|
2240
2284
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.51 13a9 9 0 1 0 2.13-9.36L3 7" })
|
|
2241
2285
|
] });
|
|
2242
2286
|
}
|
|
2287
|
+
function RedoIcon() {
|
|
2288
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2289
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 7 21 13 15 13" }),
|
|
2290
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20.49 13a9 9 0 1 1-2.13-9.36L21 7" })
|
|
2291
|
+
] });
|
|
2292
|
+
}
|
|
2243
2293
|
function AxisIcon() {
|
|
2244
2294
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2245
2295
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4", y1: "20", x2: "20", y2: "20" }),
|
|
@@ -2284,7 +2334,7 @@ function useToolHoverTooltip() {
|
|
|
2284
2334
|
return { hover, portalReady, showHover, hideHover };
|
|
2285
2335
|
}
|
|
2286
2336
|
function DesktopGeometryPanel(props) {
|
|
2287
|
-
const { activeTool, onToolChange, showAxis, showGrid, onShowAxisChange, onShowGridChange, onUndo, canUndo, onClose, isDark, chordGroup } = props;
|
|
2337
|
+
const { activeTool, onToolChange, showAxis, showGrid, onShowAxisChange, onShowGridChange, onUndo, canUndo, onRedo, canRedo, onClose, isDark, chordGroup } = props;
|
|
2288
2338
|
const grouped = react.useMemo(() => {
|
|
2289
2339
|
return TOOLS.reduce((acc, t) => {
|
|
2290
2340
|
var _a;
|
|
@@ -2333,9 +2383,23 @@ function DesktopGeometryPanel(props) {
|
|
|
2333
2383
|
disabled: !canUndo,
|
|
2334
2384
|
title: "Ho\xE0n t\xE1c (Ctrl/Cmd+Z)",
|
|
2335
2385
|
"aria-label": "Ho\xE0n t\xE1c",
|
|
2386
|
+
"data-testid": "undo-btn",
|
|
2336
2387
|
className: "ml-auto inline-flex items-center justify-center rounded p-1 text-slate-600 transition hover:bg-slate-100 hover:text-slate-900 disabled:cursor-not-allowed disabled:text-slate-300 disabled:hover:bg-transparent",
|
|
2337
2388
|
children: /* @__PURE__ */ jsxRuntime.jsx(UndoIcon, {})
|
|
2338
2389
|
}
|
|
2390
|
+
),
|
|
2391
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2392
|
+
"button",
|
|
2393
|
+
{
|
|
2394
|
+
type: "button",
|
|
2395
|
+
onClick: onRedo,
|
|
2396
|
+
disabled: !canRedo,
|
|
2397
|
+
title: "L\xE0m l\u1EA1i (Ctrl/Cmd+Shift+Z)",
|
|
2398
|
+
"aria-label": "L\xE0m l\u1EA1i",
|
|
2399
|
+
"data-testid": "redo-btn",
|
|
2400
|
+
className: "inline-flex items-center justify-center rounded p-1 text-slate-600 transition hover:bg-slate-100 hover:text-slate-900 disabled:cursor-not-allowed disabled:text-slate-300 disabled:hover:bg-transparent",
|
|
2401
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RedoIcon, {})
|
|
2402
|
+
}
|
|
2339
2403
|
)
|
|
2340
2404
|
] }) }),
|
|
2341
2405
|
groupKeys.map((group) => {
|
|
@@ -2456,6 +2520,8 @@ function MobileGeometryPanel(props) {
|
|
|
2456
2520
|
onShowGridChange,
|
|
2457
2521
|
onUndo,
|
|
2458
2522
|
canUndo,
|
|
2523
|
+
onRedo,
|
|
2524
|
+
canRedo,
|
|
2459
2525
|
isDark,
|
|
2460
2526
|
drawerOpen,
|
|
2461
2527
|
onDrawerClose
|
|
@@ -2504,6 +2570,13 @@ function MobileGeometryPanel(props) {
|
|
|
2504
2570
|
icon: /* @__PURE__ */ jsxRuntime.jsx(UndoIcon, {}),
|
|
2505
2571
|
onClick: onUndo,
|
|
2506
2572
|
disabled: !canUndo
|
|
2573
|
+
},
|
|
2574
|
+
{
|
|
2575
|
+
label: "L\xE0m l\u1EA1i",
|
|
2576
|
+
title: "L\xE0m l\u1EA1i (Ctrl/Cmd+Shift+Z)",
|
|
2577
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(RedoIcon, {}),
|
|
2578
|
+
onClick: onRedo,
|
|
2579
|
+
disabled: !canRedo
|
|
2507
2580
|
}
|
|
2508
2581
|
],
|
|
2509
2582
|
groups,
|
|
@@ -2969,10 +3042,12 @@ var init_EditorPanel = __esm({
|
|
|
2969
3042
|
init_render();
|
|
2970
3043
|
init_PropertiesPopover();
|
|
2971
3044
|
init_TransformParamPopover();
|
|
3045
|
+
init_LeftPanel();
|
|
2972
3046
|
GeometryEditorPanel = react.forwardRef(
|
|
2973
|
-
function GeometryEditorPanel2({ initialState, onInsert, onClose, withLeftPanel = false, onStateChange, isDark, isMobile = false, onOpenDrawer }, ref) {
|
|
3047
|
+
function GeometryEditorPanel2({ initialState, onInsert, onClose, withLeftPanel = false, onStateChange, isDark, isMobile = false, onOpenDrawer, onUndo, onRedo, canUndo, canRedo }, ref) {
|
|
2974
3048
|
const handleRef = react.useRef(null);
|
|
2975
3049
|
const [ready, setReady] = react.useState(false);
|
|
3050
|
+
const [hasContent, setHasContent] = react.useState(false);
|
|
2976
3051
|
const [propsPopover, setPropsPopover] = react.useState(null);
|
|
2977
3052
|
const [transformPopover, setTransformPopover] = react.useState(null);
|
|
2978
3053
|
const onStateChangeRef = react.useRef(onStateChange);
|
|
@@ -2981,13 +3056,16 @@ var init_EditorPanel = __esm({
|
|
|
2981
3056
|
}, [onStateChange]);
|
|
2982
3057
|
const emitState = react.useCallback(() => {
|
|
2983
3058
|
const h = handleRef.current;
|
|
3059
|
+
if (!h) return;
|
|
3060
|
+
setHasContent(h.getCreationLog().length > 0);
|
|
2984
3061
|
const cb = onStateChangeRef.current;
|
|
2985
|
-
if (!
|
|
3062
|
+
if (!cb) return;
|
|
2986
3063
|
cb({
|
|
2987
3064
|
tool: h.getTool(),
|
|
2988
3065
|
showAxis: h.getShowAxis(),
|
|
2989
3066
|
showGrid: h.getShowGrid(),
|
|
2990
|
-
canUndo: h.canUndo()
|
|
3067
|
+
canUndo: h.canUndo(),
|
|
3068
|
+
canRedo: h.canRedo()
|
|
2991
3069
|
});
|
|
2992
3070
|
}, []);
|
|
2993
3071
|
const handleReady = react.useCallback((h) => {
|
|
@@ -3029,6 +3107,7 @@ var init_EditorPanel = __esm({
|
|
|
3029
3107
|
setShowAxis: (b) => handleRef.current?.setShowAxis(b),
|
|
3030
3108
|
setShowGrid: (b) => handleRef.current?.setShowGrid(b),
|
|
3031
3109
|
undo: () => handleRef.current?.undo(),
|
|
3110
|
+
redo: () => handleRef.current?.redo(),
|
|
3032
3111
|
insert: performInsert,
|
|
3033
3112
|
hasContent: () => (handleRef.current?.getCreationLog().length ?? 0) > 0
|
|
3034
3113
|
}), [performInsert]);
|
|
@@ -3078,17 +3157,46 @@ var init_EditorPanel = __esm({
|
|
|
3078
3157
|
] }),
|
|
3079
3158
|
"D\u1EF1ng h\xECnh h\u1ECDc"
|
|
3080
3159
|
] }),
|
|
3081
|
-
isMobile && /* @__PURE__ */ jsxRuntime.
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3160
|
+
isMobile && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3161
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3162
|
+
"button",
|
|
3163
|
+
{
|
|
3164
|
+
type: "button",
|
|
3165
|
+
onClick: onUndo,
|
|
3166
|
+
disabled: !canUndo,
|
|
3167
|
+
"aria-label": "Ho\xE0n t\xE1c",
|
|
3168
|
+
title: "Ho\xE0n t\xE1c (Ctrl/Cmd+Z)",
|
|
3169
|
+
"data-testid": "undo-btn-mobile",
|
|
3170
|
+
className: "inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15 disabled:opacity-40",
|
|
3171
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(UndoIcon, {})
|
|
3172
|
+
}
|
|
3173
|
+
),
|
|
3174
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3175
|
+
"button",
|
|
3176
|
+
{
|
|
3177
|
+
type: "button",
|
|
3178
|
+
onClick: onRedo,
|
|
3179
|
+
disabled: !canRedo,
|
|
3180
|
+
"aria-label": "L\xE0m l\u1EA1i",
|
|
3181
|
+
title: "L\xE0m l\u1EA1i (Ctrl/Cmd+Shift+Z)",
|
|
3182
|
+
"data-testid": "redo-btn-mobile",
|
|
3183
|
+
className: "inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15 disabled:opacity-40",
|
|
3184
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(RedoIcon, {})
|
|
3185
|
+
}
|
|
3186
|
+
),
|
|
3187
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3188
|
+
"button",
|
|
3189
|
+
{
|
|
3190
|
+
type: "button",
|
|
3191
|
+
onClick: handleInsert,
|
|
3192
|
+
disabled: !ready || !hasContent,
|
|
3193
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
3194
|
+
"data-testid": "geometry-insert-btn-mobile",
|
|
3195
|
+
className: "rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50",
|
|
3196
|
+
children: "Ch\xE8n"
|
|
3197
|
+
}
|
|
3198
|
+
)
|
|
3199
|
+
] }),
|
|
3092
3200
|
/* @__PURE__ */ jsxRuntime.jsx("button", { onClick: onClose, "aria-label": "\u0110\xF3ng", className: "inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3093
3201
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" }),
|
|
3094
3202
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" })
|
|
@@ -3182,7 +3290,8 @@ var init_EditorPanel = __esm({
|
|
|
3182
3290
|
"button",
|
|
3183
3291
|
{
|
|
3184
3292
|
onClick: handleInsert,
|
|
3185
|
-
disabled: !ready,
|
|
3293
|
+
disabled: !ready || !hasContent,
|
|
3294
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
3186
3295
|
"data-testid": "geometry-insert-btn",
|
|
3187
3296
|
className: "rounded bg-emerald-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-emerald-700 disabled:opacity-50",
|
|
3188
3297
|
children: "Ch\xE8n"
|
|
@@ -3410,7 +3519,8 @@ var init_host = __esm({
|
|
|
3410
3519
|
tool: "move",
|
|
3411
3520
|
showAxis: false,
|
|
3412
3521
|
showGrid: false,
|
|
3413
|
-
canUndo: false
|
|
3522
|
+
canUndo: false,
|
|
3523
|
+
canRedo: false
|
|
3414
3524
|
};
|
|
3415
3525
|
GeometryStampHost = react.forwardRef(
|
|
3416
3526
|
function GeometryStampHost2({ api, editingElement, onClose, isDark }, ref) {
|
|
@@ -3476,6 +3586,8 @@ var init_host = __esm({
|
|
|
3476
3586
|
onShowGridChange: (b) => panelRef.current?.setShowGrid(b),
|
|
3477
3587
|
onUndo: () => panelRef.current?.undo(),
|
|
3478
3588
|
canUndo: geomState.canUndo,
|
|
3589
|
+
onRedo: () => panelRef.current?.redo(),
|
|
3590
|
+
canRedo: geomState.canRedo,
|
|
3479
3591
|
onClose,
|
|
3480
3592
|
isDark,
|
|
3481
3593
|
isMobile,
|
|
@@ -3495,7 +3607,11 @@ var init_host = __esm({
|
|
|
3495
3607
|
withLeftPanel: !isMobile,
|
|
3496
3608
|
isDark,
|
|
3497
3609
|
isMobile,
|
|
3498
|
-
onOpenDrawer: () => setDrawerOpen(true)
|
|
3610
|
+
onOpenDrawer: () => setDrawerOpen(true),
|
|
3611
|
+
onUndo: () => panelRef.current?.undo(),
|
|
3612
|
+
onRedo: () => panelRef.current?.redo(),
|
|
3613
|
+
canUndo: geomState.canUndo,
|
|
3614
|
+
canRedo: geomState.canRedo
|
|
3499
3615
|
}
|
|
3500
3616
|
)
|
|
3501
3617
|
] });
|