@xom11/whiteboard 0.27.0 → 0.28.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/dist/ai.d.mts +1 -1
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +54 -23
- package/dist/ai.js.map +1 -1
- package/dist/ai.mjs +54 -23
- package/dist/ai.mjs.map +1 -1
- package/dist/catalog.json +4 -4
- package/dist/{chunk-D5JLJ3PT.mjs → chunk-5JM35CXV.mjs} +4 -4
- package/dist/{chunk-D5JLJ3PT.mjs.map → chunk-5JM35CXV.mjs.map} +1 -1
- package/dist/{chunk-KYMBUTPO.mjs → chunk-BU5KLO3P.mjs} +3 -3
- package/dist/{chunk-KYMBUTPO.mjs.map → chunk-BU5KLO3P.mjs.map} +1 -1
- package/dist/{chunk-AYJPOHCI.mjs → chunk-H22OZYTW.mjs} +3 -3
- package/dist/{chunk-AYJPOHCI.mjs.map → chunk-H22OZYTW.mjs.map} +1 -1
- package/dist/{chunk-I3L56GVH.mjs → chunk-OQIQNKPQ.mjs} +3 -3
- package/dist/{chunk-I3L56GVH.mjs.map → chunk-OQIQNKPQ.mjs.map} +1 -1
- package/dist/{chunk-KZGPSTZI.mjs → chunk-QCZVFEN4.mjs} +4 -4
- package/dist/{chunk-KZGPSTZI.mjs.map → chunk-QCZVFEN4.mjs.map} +1 -1
- package/dist/{chunk-4ETJ4CDY.mjs → chunk-QRUAEXLR.mjs} +4 -4
- package/dist/{chunk-4ETJ4CDY.mjs.map → chunk-QRUAEXLR.mjs.map} +1 -1
- package/dist/{chunk-HLAOGXEK.mjs → chunk-V3YJ6JFL.mjs} +3 -3
- package/dist/{chunk-HLAOGXEK.mjs.map → chunk-V3YJ6JFL.mjs.map} +1 -1
- package/dist/{chunk-D5LWSN2Y.mjs → chunk-ZTQBUKLJ.mjs} +30 -13
- package/dist/chunk-ZTQBUKLJ.mjs.map +1 -0
- package/dist/geometry-2d.d.mts +1 -1
- package/dist/geometry-2d.d.ts +1 -1
- package/dist/geometry-2d.js +143 -33
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +3 -3
- package/dist/geometry-3d.d.mts +1 -1
- package/dist/geometry-3d.d.ts +1 -1
- package/dist/geometry-3d.js +28 -11
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +3 -3
- package/dist/graph-2d.d.mts +1 -1
- package/dist/graph-2d.d.ts +1 -1
- package/dist/graph-2d.js +28 -11
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +3 -3
- package/dist/{host-M26FS244.mjs → host-2ISGVO7O.mjs} +5 -5
- package/dist/{host-M26FS244.mjs.map → host-2ISGVO7O.mjs.map} +1 -1
- package/dist/{host-HAYCJJ2T.mjs → host-4P766V4J.mjs} +110 -27
- package/dist/host-4P766V4J.mjs.map +1 -0
- package/dist/{host-LTJHAY5A.mjs → host-HOSJHQ5H.mjs} +6 -6
- package/dist/{host-LTJHAY5A.mjs.map → host-HOSJHQ5H.mjs.map} +1 -1
- package/dist/index.d.mts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +147 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -15
- package/dist/index.mjs.map +1 -1
- package/dist/latex.d.mts +1 -1
- package/dist/latex.d.ts +1 -1
- package/dist/serialize-N4G6RFBB.mjs +9 -0
- package/dist/{serialize-C3LSUMSA.mjs.map → serialize-N4G6RFBB.mjs.map} +1 -1
- package/dist/{types-zc_Pa0mp.d.mts → types-BHYC2Fiw.d.mts} +25 -1
- package/dist/{types-zc_Pa0mp.d.ts → types-BHYC2Fiw.d.ts} +25 -1
- package/package.json +1 -1
- package/dist/chunk-D5LWSN2Y.mjs.map +0 -1
- package/dist/host-HAYCJJ2T.mjs.map +0 -1
- package/dist/serialize-C3LSUMSA.mjs +0 -9
package/dist/geometry-2d.d.mts
CHANGED
package/dist/geometry-2d.d.ts
CHANGED
package/dist/geometry-2d.js
CHANGED
|
@@ -2293,9 +2293,11 @@ var init_circle = __esm({
|
|
|
2293
2293
|
},
|
|
2294
2294
|
render: (obj, ctx) => {
|
|
2295
2295
|
const board = ctx.jxg;
|
|
2296
|
+
const isCenterLabel = (l) => /^[A-Z]['′]?\d*$/u.test(l);
|
|
2297
|
+
const isCenter = isCenterLabel(obj.label);
|
|
2296
2298
|
const baseOpts = {
|
|
2297
2299
|
name: obj.label,
|
|
2298
|
-
withLabel: obj.attrs.showLabel ?? false,
|
|
2300
|
+
withLabel: isCenter ? obj.attrs.showLabel ?? false : true,
|
|
2299
2301
|
strokeColor: obj.attrs.color ?? "#0f172a",
|
|
2300
2302
|
strokeWidth: obj.attrs.width ?? 2,
|
|
2301
2303
|
dash: obj.attrs.dash ?? 0,
|
|
@@ -2308,22 +2310,37 @@ var init_circle = __esm({
|
|
|
2308
2310
|
const p1 = ctx.resolveRef(c.p1);
|
|
2309
2311
|
const p2 = ctx.resolveRef(c.p2);
|
|
2310
2312
|
const p3 = ctx.resolveRef(c.p3);
|
|
2313
|
+
if (isCenter) {
|
|
2314
|
+
const center2 = board.create("circumcenter", [p1, p2, p3], {
|
|
2315
|
+
visible: obj.visible,
|
|
2316
|
+
withLabel: true,
|
|
2317
|
+
fixed: true,
|
|
2318
|
+
name: obj.label
|
|
2319
|
+
});
|
|
2320
|
+
const circ = board.create("circumcircle", [p1, p2, p3], { ...baseOpts, withLabel: false });
|
|
2321
|
+
circ.center = circ.center ?? center2;
|
|
2322
|
+
circ._helpers = [center2];
|
|
2323
|
+
return circ;
|
|
2324
|
+
}
|
|
2311
2325
|
return board.create("circumcircle", [p1, p2, p3], baseOpts);
|
|
2312
2326
|
}
|
|
2313
2327
|
if (c?.kind === "incircle") {
|
|
2314
2328
|
const p1 = ctx.resolveRef(c.p1);
|
|
2315
2329
|
const p2 = ctx.resolveRef(c.p2);
|
|
2316
2330
|
const p3 = ctx.resolveRef(c.p3);
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2331
|
+
if (isCenter) {
|
|
2332
|
+
const center2 = board.create("incenter", [p1, p2, p3], {
|
|
2333
|
+
visible: obj.visible,
|
|
2334
|
+
withLabel: true,
|
|
2335
|
+
fixed: true,
|
|
2336
|
+
name: obj.label
|
|
2337
|
+
});
|
|
2338
|
+
const circ = board.create("incircle", [p1, p2, p3], { ...baseOpts, withLabel: false });
|
|
2339
|
+
circ.center = circ.center ?? center2;
|
|
2340
|
+
circ._helpers = [center2];
|
|
2341
|
+
return circ;
|
|
2342
|
+
}
|
|
2343
|
+
return board.create("incircle", [p1, p2, p3], baseOpts);
|
|
2327
2344
|
}
|
|
2328
2345
|
if (c?.kind === "excircle") {
|
|
2329
2346
|
const P = [ctx.resolveRef(c.p1), ctx.resolveRef(c.p2), ctx.resolveRef(c.p3)];
|
|
@@ -12549,6 +12566,94 @@ var init_AiFigurePrompt = __esm({
|
|
|
12549
12566
|
StopIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, ...props, children: /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) });
|
|
12550
12567
|
}
|
|
12551
12568
|
});
|
|
12569
|
+
|
|
12570
|
+
// src/stamps/geometry-2d/draft.ts
|
|
12571
|
+
function svgIntrinsicSize(svg) {
|
|
12572
|
+
const w = svg.match(/<svg[^>]*\swidth="([\d.]+)"/);
|
|
12573
|
+
const h = svg.match(/<svg[^>]*\sheight="([\d.]+)"/);
|
|
12574
|
+
if (w && h) return { width: parseFloat(w[1]), height: parseFloat(h[1]) };
|
|
12575
|
+
const vb = svg.match(/viewBox="0 0 ([\d.]+) ([\d.]+)"/);
|
|
12576
|
+
if (vb) return { width: parseFloat(vb[1]), height: parseFloat(vb[2]) };
|
|
12577
|
+
return { width: 300, height: 200 };
|
|
12578
|
+
}
|
|
12579
|
+
function draftFromViewport(svg, appState, seq) {
|
|
12580
|
+
const { width, height } = svgIntrinsicSize(svg);
|
|
12581
|
+
const zoom = appState.zoom?.value ?? 1;
|
|
12582
|
+
const vw = appState.width ?? 800;
|
|
12583
|
+
const vh = appState.height ?? 600;
|
|
12584
|
+
const cx = appState.scrollX + vw / 2 / zoom;
|
|
12585
|
+
const cy = appState.scrollY + vh / 2 / zoom;
|
|
12586
|
+
return { svg, width, height, x: cx - width / 2, y: cy - height / 2, seq };
|
|
12587
|
+
}
|
|
12588
|
+
function didStateChange(seen, jsonState) {
|
|
12589
|
+
if (seen.last === jsonState) return false;
|
|
12590
|
+
seen.last = jsonState;
|
|
12591
|
+
return true;
|
|
12592
|
+
}
|
|
12593
|
+
var init_draft = __esm({
|
|
12594
|
+
"src/stamps/geometry-2d/draft.ts"() {
|
|
12595
|
+
}
|
|
12596
|
+
});
|
|
12597
|
+
function useGeometryDraftEmit({
|
|
12598
|
+
store,
|
|
12599
|
+
handleRef,
|
|
12600
|
+
api,
|
|
12601
|
+
showAxis,
|
|
12602
|
+
showGrid,
|
|
12603
|
+
onGeometryDraft,
|
|
12604
|
+
debounceMs = 350
|
|
12605
|
+
}) {
|
|
12606
|
+
const seqRef = React2.useRef(0);
|
|
12607
|
+
const seenRef = React2.useRef({ last: null });
|
|
12608
|
+
const timerRef = React2.useRef(null);
|
|
12609
|
+
const cbRef = React2.useRef(onGeometryDraft);
|
|
12610
|
+
cbRef.current = onGeometryDraft;
|
|
12611
|
+
React2.useEffect(() => {
|
|
12612
|
+
if (!cbRef.current) return;
|
|
12613
|
+
const emit = () => {
|
|
12614
|
+
const h = handleRef.current;
|
|
12615
|
+
if (!h) return;
|
|
12616
|
+
const state = h.getState();
|
|
12617
|
+
if (Object.keys(state.objects).length === 0) {
|
|
12618
|
+
if (seenRef.current.last !== null) {
|
|
12619
|
+
seenRef.current.last = null;
|
|
12620
|
+
cbRef.current?.(null);
|
|
12621
|
+
}
|
|
12622
|
+
return;
|
|
12623
|
+
}
|
|
12624
|
+
const bbox = h.getBbox();
|
|
12625
|
+
const jsonState = serializeBoard(state, { bbox, showAxis, showGrid });
|
|
12626
|
+
if (!didStateChange(seenRef.current, jsonState)) return;
|
|
12627
|
+
void (async () => {
|
|
12628
|
+
try {
|
|
12629
|
+
const svg = await renderGeometrySvgFromState(jsonState);
|
|
12630
|
+
const appState = api?.getAppState?.() ?? { scrollX: 0, scrollY: 0, width: 800, height: 600, zoom: { value: 1 } };
|
|
12631
|
+
seqRef.current += 1;
|
|
12632
|
+
cbRef.current?.(draftFromViewport(svg, appState, seqRef.current));
|
|
12633
|
+
} catch (err) {
|
|
12634
|
+
console.warn("[geometry] draft render failed:", err);
|
|
12635
|
+
}
|
|
12636
|
+
})();
|
|
12637
|
+
};
|
|
12638
|
+
const schedule = () => {
|
|
12639
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
12640
|
+
timerRef.current = setTimeout(emit, debounceMs);
|
|
12641
|
+
};
|
|
12642
|
+
const unsub = store.subscribe(schedule);
|
|
12643
|
+
return () => {
|
|
12644
|
+
unsub();
|
|
12645
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
12646
|
+
cbRef.current?.(null);
|
|
12647
|
+
};
|
|
12648
|
+
}, [store, handleRef, api, showAxis, showGrid, debounceMs]);
|
|
12649
|
+
}
|
|
12650
|
+
var init_useGeometryDraftEmit = __esm({
|
|
12651
|
+
"src/stamps/geometry-2d/editor/useGeometryDraftEmit.ts"() {
|
|
12652
|
+
init_serialize();
|
|
12653
|
+
init_render();
|
|
12654
|
+
init_draft();
|
|
12655
|
+
}
|
|
12656
|
+
});
|
|
12552
12657
|
var GeometryEditorPanelInner, GeometryEditorPanel;
|
|
12553
12658
|
var init_EditorPanel = __esm({
|
|
12554
12659
|
"src/stamps/geometry-2d/editor/EditorPanel.tsx"() {
|
|
@@ -12565,6 +12670,7 @@ var init_EditorPanel = __esm({
|
|
|
12565
12670
|
init_constants();
|
|
12566
12671
|
init_Toast2();
|
|
12567
12672
|
init_AiFigurePrompt();
|
|
12673
|
+
init_useGeometryDraftEmit();
|
|
12568
12674
|
GeometryEditorPanelInner = React2.forwardRef(
|
|
12569
12675
|
function GeometryEditorPanelInner2({
|
|
12570
12676
|
store,
|
|
@@ -12583,7 +12689,9 @@ var init_EditorPanel = __esm({
|
|
|
12583
12689
|
canUndo,
|
|
12584
12690
|
canRedo,
|
|
12585
12691
|
onSelectionChange,
|
|
12586
|
-
generateGeometryFigure
|
|
12692
|
+
generateGeometryFigure,
|
|
12693
|
+
api,
|
|
12694
|
+
onGeometryDraft
|
|
12587
12695
|
}, ref) {
|
|
12588
12696
|
const { showToast } = useToast();
|
|
12589
12697
|
const handleRef = React2.useRef(null);
|
|
@@ -12596,12 +12704,14 @@ var init_EditorPanel = __esm({
|
|
|
12596
12704
|
React2.useEffect(() => {
|
|
12597
12705
|
onSelectionChangeRef.current = onSelectionChange;
|
|
12598
12706
|
}, [onSelectionChange]);
|
|
12707
|
+
const onGeometryDraftRef = React2.useRef(onGeometryDraft);
|
|
12708
|
+
React2.useEffect(() => {
|
|
12709
|
+
onGeometryDraftRef.current = onGeometryDraft;
|
|
12710
|
+
}, [onGeometryDraft]);
|
|
12599
12711
|
useEditorState({ store, onHistoryChange });
|
|
12600
|
-
|
|
12601
|
-
|
|
12602
|
-
|
|
12603
|
-
() => store.getState()
|
|
12604
|
-
);
|
|
12712
|
+
useGeometryDraftEmit({ store, handleRef, api, showAxis, showGrid, onGeometryDraft });
|
|
12713
|
+
const snap = () => store.getState();
|
|
12714
|
+
const currentSceneState = React2.useSyncExternalStore((cb) => store.subscribe(cb), snap, snap);
|
|
12605
12715
|
React2.useEffect(() => {
|
|
12606
12716
|
const sync = () => setHasContent(Object.keys(store.getState().objects).length > 0);
|
|
12607
12717
|
sync();
|
|
@@ -12611,22 +12721,22 @@ var init_EditorPanel = __esm({
|
|
|
12611
12721
|
const h = handleRef.current;
|
|
12612
12722
|
if (!h) return;
|
|
12613
12723
|
setReady(true);
|
|
12614
|
-
h.onSelect((
|
|
12615
|
-
setPropsPopover(
|
|
12724
|
+
h.onSelect((snap2) => {
|
|
12725
|
+
setPropsPopover(snap2);
|
|
12616
12726
|
setMultiSelection(null);
|
|
12617
|
-
onSelectionChangeRef.current?.(
|
|
12727
|
+
onSelectionChangeRef.current?.(snap2.id);
|
|
12618
12728
|
});
|
|
12619
12729
|
h.onTransformParam((info) => setTransformPopover(info));
|
|
12620
|
-
h.onSelectionState((
|
|
12621
|
-
if (!
|
|
12730
|
+
h.onSelectionState((snap2) => {
|
|
12731
|
+
if (!snap2 || snap2.ids.length === 0) {
|
|
12622
12732
|
setPropsPopover(null);
|
|
12623
12733
|
setMultiSelection(null);
|
|
12624
12734
|
onSelectionChangeRef.current?.(void 0);
|
|
12625
12735
|
return;
|
|
12626
12736
|
}
|
|
12627
|
-
if (
|
|
12628
|
-
const id =
|
|
12629
|
-
const single = buildObjectSnapshot(store.getState(), id,
|
|
12737
|
+
if (snap2.ids.length === 1) {
|
|
12738
|
+
const id = snap2.ids[0];
|
|
12739
|
+
const single = buildObjectSnapshot(store.getState(), id, snap2.anchor);
|
|
12630
12740
|
if (single) {
|
|
12631
12741
|
setPropsPopover(single);
|
|
12632
12742
|
setMultiSelection(null);
|
|
@@ -12634,7 +12744,7 @@ var init_EditorPanel = __esm({
|
|
|
12634
12744
|
}
|
|
12635
12745
|
return;
|
|
12636
12746
|
}
|
|
12637
|
-
setMultiSelection(
|
|
12747
|
+
setMultiSelection(snap2);
|
|
12638
12748
|
setPropsPopover(null);
|
|
12639
12749
|
onSelectionChangeRef.current?.(void 0);
|
|
12640
12750
|
});
|
|
@@ -12678,15 +12788,13 @@ var init_EditorPanel = __esm({
|
|
|
12678
12788
|
try {
|
|
12679
12789
|
const svgString = await renderGeometrySvgFromState(jsonState);
|
|
12680
12790
|
onInsert(jsonState, svgString);
|
|
12791
|
+
onGeometryDraftRef.current?.(null);
|
|
12681
12792
|
} catch (err) {
|
|
12682
12793
|
console.error("Geometry insert failed:", err);
|
|
12683
12794
|
}
|
|
12684
12795
|
})();
|
|
12685
12796
|
return true;
|
|
12686
12797
|
}, [onInsert, showAxis, showGrid]);
|
|
12687
|
-
const handleInsert = React2.useCallback(() => {
|
|
12688
|
-
performInsert();
|
|
12689
|
-
}, [performInsert]);
|
|
12690
12798
|
const loadAiFigure = React2.useCallback((generated) => {
|
|
12691
12799
|
handleRef.current?.clearSelection();
|
|
12692
12800
|
setPropsPopover(null);
|
|
@@ -12781,7 +12889,7 @@ var init_EditorPanel = __esm({
|
|
|
12781
12889
|
"button",
|
|
12782
12890
|
{
|
|
12783
12891
|
type: "button",
|
|
12784
|
-
onClick:
|
|
12892
|
+
onClick: performInsert,
|
|
12785
12893
|
disabled: !ready || !hasContent,
|
|
12786
12894
|
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
12787
12895
|
"data-testid": "geometry-insert-btn-mobile",
|
|
@@ -12899,7 +13007,7 @@ var init_EditorPanel = __esm({
|
|
|
12899
13007
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12900
13008
|
"button",
|
|
12901
13009
|
{
|
|
12902
|
-
onClick:
|
|
13010
|
+
onClick: performInsert,
|
|
12903
13011
|
disabled: !ready || !hasContent,
|
|
12904
13012
|
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
12905
13013
|
"data-testid": "geometry-insert-btn",
|
|
@@ -13260,7 +13368,7 @@ var init_host = __esm({
|
|
|
13260
13368
|
init_useStampStore();
|
|
13261
13369
|
init_dslRenderRow();
|
|
13262
13370
|
GeometryStampHost = React2.forwardRef(
|
|
13263
|
-
function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure }, ref) {
|
|
13371
|
+
function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure, onGeometryDraft }, ref) {
|
|
13264
13372
|
const panelRef = React2.useRef(null);
|
|
13265
13373
|
const { isMobile } = useIsMobile();
|
|
13266
13374
|
const [drawerOpen, setDrawerOpen] = React2.useState(false);
|
|
@@ -13375,7 +13483,9 @@ var init_host = __esm({
|
|
|
13375
13483
|
canUndo,
|
|
13376
13484
|
canRedo,
|
|
13377
13485
|
onSelectionChange: setSelectedObjectId,
|
|
13378
|
-
generateGeometryFigure
|
|
13486
|
+
generateGeometryFigure,
|
|
13487
|
+
api,
|
|
13488
|
+
onGeometryDraft
|
|
13379
13489
|
}
|
|
13380
13490
|
)
|
|
13381
13491
|
] });
|