@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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useChordShortcut } from './chunk-HNQLZIEP.mjs';
|
|
3
3
|
import { useToolStateMachine } from './chunk-NVJ7K3DK.mjs';
|
|
4
|
-
import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-
|
|
5
|
-
import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-
|
|
4
|
+
import { safeJsx, initJxgBoard, attachJxgWheelZoom, useToast, ToastHost, STAMP_PANEL_DESKTOP, ToastProvider, useStampStore, StampLeftPanel, ObjectRow } from './chunk-OQIQNKPQ.mjs';
|
|
5
|
+
import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, deserializeBoard } from './chunk-H22OZYTW.mjs';
|
|
6
6
|
import { themeLabel, paletteFor, themeAxis, themeGrid } from './chunk-R5FL6S7L.mjs';
|
|
7
7
|
import { JxgRenderer } from './chunk-SZDAS7LK.mjs';
|
|
8
8
|
import './chunk-ICR4CVOE.mjs';
|
|
9
|
-
import { nextLabel, useEditorState, listObjects } from './chunk-
|
|
9
|
+
import { nextLabel, useEditorState, listObjects } from './chunk-ZTQBUKLJ.mjs';
|
|
10
10
|
import './chunk-IHUFOV7L.mjs';
|
|
11
11
|
import { validateFile, fileToImagePart, describeDsl, serializeState } from './chunk-AJAHD35N.mjs';
|
|
12
12
|
import { handleExtractProblem } from './chunk-T3SOHYB2.mjs';
|
|
@@ -3697,6 +3697,85 @@ function AiFigurePrompt({
|
|
|
3697
3697
|
ocrWarning && /* @__PURE__ */ jsx("p", { className: "mt-1 rounded bg-amber-50 px-2 py-1 text-[11px] text-amber-700", children: ocrWarning })
|
|
3698
3698
|
] });
|
|
3699
3699
|
}
|
|
3700
|
+
|
|
3701
|
+
// src/stamps/geometry-2d/draft.ts
|
|
3702
|
+
function svgIntrinsicSize(svg) {
|
|
3703
|
+
const w = svg.match(/<svg[^>]*\swidth="([\d.]+)"/);
|
|
3704
|
+
const h = svg.match(/<svg[^>]*\sheight="([\d.]+)"/);
|
|
3705
|
+
if (w && h) return { width: parseFloat(w[1]), height: parseFloat(h[1]) };
|
|
3706
|
+
const vb = svg.match(/viewBox="0 0 ([\d.]+) ([\d.]+)"/);
|
|
3707
|
+
if (vb) return { width: parseFloat(vb[1]), height: parseFloat(vb[2]) };
|
|
3708
|
+
return { width: 300, height: 200 };
|
|
3709
|
+
}
|
|
3710
|
+
function draftFromViewport(svg, appState, seq) {
|
|
3711
|
+
const { width, height } = svgIntrinsicSize(svg);
|
|
3712
|
+
const zoom = appState.zoom?.value ?? 1;
|
|
3713
|
+
const vw = appState.width ?? 800;
|
|
3714
|
+
const vh = appState.height ?? 600;
|
|
3715
|
+
const cx = appState.scrollX + vw / 2 / zoom;
|
|
3716
|
+
const cy = appState.scrollY + vh / 2 / zoom;
|
|
3717
|
+
return { svg, width, height, x: cx - width / 2, y: cy - height / 2, seq };
|
|
3718
|
+
}
|
|
3719
|
+
function didStateChange(seen, jsonState) {
|
|
3720
|
+
if (seen.last === jsonState) return false;
|
|
3721
|
+
seen.last = jsonState;
|
|
3722
|
+
return true;
|
|
3723
|
+
}
|
|
3724
|
+
|
|
3725
|
+
// src/stamps/geometry-2d/editor/useGeometryDraftEmit.ts
|
|
3726
|
+
function useGeometryDraftEmit({
|
|
3727
|
+
store,
|
|
3728
|
+
handleRef,
|
|
3729
|
+
api,
|
|
3730
|
+
showAxis,
|
|
3731
|
+
showGrid,
|
|
3732
|
+
onGeometryDraft,
|
|
3733
|
+
debounceMs = 350
|
|
3734
|
+
}) {
|
|
3735
|
+
const seqRef = useRef(0);
|
|
3736
|
+
const seenRef = useRef({ last: null });
|
|
3737
|
+
const timerRef = useRef(null);
|
|
3738
|
+
const cbRef = useRef(onGeometryDraft);
|
|
3739
|
+
cbRef.current = onGeometryDraft;
|
|
3740
|
+
useEffect(() => {
|
|
3741
|
+
if (!cbRef.current) return;
|
|
3742
|
+
const emit = () => {
|
|
3743
|
+
const h = handleRef.current;
|
|
3744
|
+
if (!h) return;
|
|
3745
|
+
const state = h.getState();
|
|
3746
|
+
if (Object.keys(state.objects).length === 0) {
|
|
3747
|
+
if (seenRef.current.last !== null) {
|
|
3748
|
+
seenRef.current.last = null;
|
|
3749
|
+
cbRef.current?.(null);
|
|
3750
|
+
}
|
|
3751
|
+
return;
|
|
3752
|
+
}
|
|
3753
|
+
const bbox = h.getBbox();
|
|
3754
|
+
const jsonState = serializeBoard(state, { bbox, showAxis, showGrid });
|
|
3755
|
+
if (!didStateChange(seenRef.current, jsonState)) return;
|
|
3756
|
+
void (async () => {
|
|
3757
|
+
try {
|
|
3758
|
+
const svg = await renderGeometrySvgFromState(jsonState);
|
|
3759
|
+
const appState = api?.getAppState?.() ?? { scrollX: 0, scrollY: 0, width: 800, height: 600, zoom: { value: 1 } };
|
|
3760
|
+
seqRef.current += 1;
|
|
3761
|
+
cbRef.current?.(draftFromViewport(svg, appState, seqRef.current));
|
|
3762
|
+
} catch (err) {
|
|
3763
|
+
console.warn("[geometry] draft render failed:", err);
|
|
3764
|
+
}
|
|
3765
|
+
})();
|
|
3766
|
+
};
|
|
3767
|
+
const schedule = () => {
|
|
3768
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
3769
|
+
timerRef.current = setTimeout(emit, debounceMs);
|
|
3770
|
+
};
|
|
3771
|
+
const unsub = store.subscribe(schedule);
|
|
3772
|
+
return () => {
|
|
3773
|
+
unsub();
|
|
3774
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
3775
|
+
cbRef.current?.(null);
|
|
3776
|
+
};
|
|
3777
|
+
}, [store, handleRef, api, showAxis, showGrid, debounceMs]);
|
|
3778
|
+
}
|
|
3700
3779
|
var GeometryEditorPanelInner = forwardRef(
|
|
3701
3780
|
function GeometryEditorPanelInner2({
|
|
3702
3781
|
store,
|
|
@@ -3715,7 +3794,9 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3715
3794
|
canUndo,
|
|
3716
3795
|
canRedo,
|
|
3717
3796
|
onSelectionChange,
|
|
3718
|
-
generateGeometryFigure
|
|
3797
|
+
generateGeometryFigure,
|
|
3798
|
+
api,
|
|
3799
|
+
onGeometryDraft
|
|
3719
3800
|
}, ref) {
|
|
3720
3801
|
const { showToast } = useToast();
|
|
3721
3802
|
const handleRef = useRef(null);
|
|
@@ -3728,12 +3809,14 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3728
3809
|
useEffect(() => {
|
|
3729
3810
|
onSelectionChangeRef.current = onSelectionChange;
|
|
3730
3811
|
}, [onSelectionChange]);
|
|
3812
|
+
const onGeometryDraftRef = useRef(onGeometryDraft);
|
|
3813
|
+
useEffect(() => {
|
|
3814
|
+
onGeometryDraftRef.current = onGeometryDraft;
|
|
3815
|
+
}, [onGeometryDraft]);
|
|
3731
3816
|
useEditorState({ store, onHistoryChange });
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
() => store.getState()
|
|
3736
|
-
);
|
|
3817
|
+
useGeometryDraftEmit({ store, handleRef, api, showAxis, showGrid, onGeometryDraft });
|
|
3818
|
+
const snap = () => store.getState();
|
|
3819
|
+
const currentSceneState = useSyncExternalStore((cb) => store.subscribe(cb), snap, snap);
|
|
3737
3820
|
useEffect(() => {
|
|
3738
3821
|
const sync = () => setHasContent(Object.keys(store.getState().objects).length > 0);
|
|
3739
3822
|
sync();
|
|
@@ -3743,22 +3826,22 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3743
3826
|
const h = handleRef.current;
|
|
3744
3827
|
if (!h) return;
|
|
3745
3828
|
setReady(true);
|
|
3746
|
-
h.onSelect((
|
|
3747
|
-
setPropsPopover(
|
|
3829
|
+
h.onSelect((snap2) => {
|
|
3830
|
+
setPropsPopover(snap2);
|
|
3748
3831
|
setMultiSelection(null);
|
|
3749
|
-
onSelectionChangeRef.current?.(
|
|
3832
|
+
onSelectionChangeRef.current?.(snap2.id);
|
|
3750
3833
|
});
|
|
3751
3834
|
h.onTransformParam((info) => setTransformPopover(info));
|
|
3752
|
-
h.onSelectionState((
|
|
3753
|
-
if (!
|
|
3835
|
+
h.onSelectionState((snap2) => {
|
|
3836
|
+
if (!snap2 || snap2.ids.length === 0) {
|
|
3754
3837
|
setPropsPopover(null);
|
|
3755
3838
|
setMultiSelection(null);
|
|
3756
3839
|
onSelectionChangeRef.current?.(void 0);
|
|
3757
3840
|
return;
|
|
3758
3841
|
}
|
|
3759
|
-
if (
|
|
3760
|
-
const id =
|
|
3761
|
-
const single = buildObjectSnapshot(store.getState(), id,
|
|
3842
|
+
if (snap2.ids.length === 1) {
|
|
3843
|
+
const id = snap2.ids[0];
|
|
3844
|
+
const single = buildObjectSnapshot(store.getState(), id, snap2.anchor);
|
|
3762
3845
|
if (single) {
|
|
3763
3846
|
setPropsPopover(single);
|
|
3764
3847
|
setMultiSelection(null);
|
|
@@ -3766,7 +3849,7 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3766
3849
|
}
|
|
3767
3850
|
return;
|
|
3768
3851
|
}
|
|
3769
|
-
setMultiSelection(
|
|
3852
|
+
setMultiSelection(snap2);
|
|
3770
3853
|
setPropsPopover(null);
|
|
3771
3854
|
onSelectionChangeRef.current?.(void 0);
|
|
3772
3855
|
});
|
|
@@ -3810,15 +3893,13 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3810
3893
|
try {
|
|
3811
3894
|
const svgString = await renderGeometrySvgFromState(jsonState);
|
|
3812
3895
|
onInsert(jsonState, svgString);
|
|
3896
|
+
onGeometryDraftRef.current?.(null);
|
|
3813
3897
|
} catch (err) {
|
|
3814
3898
|
console.error("Geometry insert failed:", err);
|
|
3815
3899
|
}
|
|
3816
3900
|
})();
|
|
3817
3901
|
return true;
|
|
3818
3902
|
}, [onInsert, showAxis, showGrid]);
|
|
3819
|
-
const handleInsert = useCallback(() => {
|
|
3820
|
-
performInsert();
|
|
3821
|
-
}, [performInsert]);
|
|
3822
3903
|
const loadAiFigure = useCallback((generated) => {
|
|
3823
3904
|
handleRef.current?.clearSelection();
|
|
3824
3905
|
setPropsPopover(null);
|
|
@@ -3913,7 +3994,7 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
3913
3994
|
"button",
|
|
3914
3995
|
{
|
|
3915
3996
|
type: "button",
|
|
3916
|
-
onClick:
|
|
3997
|
+
onClick: performInsert,
|
|
3917
3998
|
disabled: !ready || !hasContent,
|
|
3918
3999
|
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
3919
4000
|
"data-testid": "geometry-insert-btn-mobile",
|
|
@@ -4031,7 +4112,7 @@ var GeometryEditorPanelInner = forwardRef(
|
|
|
4031
4112
|
/* @__PURE__ */ jsx(
|
|
4032
4113
|
"button",
|
|
4033
4114
|
{
|
|
4034
|
-
onClick:
|
|
4115
|
+
onClick: performInsert,
|
|
4035
4116
|
disabled: !ready || !hasContent,
|
|
4036
4117
|
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
4037
4118
|
"data-testid": "geometry-insert-btn",
|
|
@@ -4087,7 +4168,7 @@ function parseInitialState(data) {
|
|
|
4087
4168
|
return deserializeBoard(data.jsonState);
|
|
4088
4169
|
}
|
|
4089
4170
|
var GeometryStampHost = forwardRef(
|
|
4090
|
-
function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure }, ref) {
|
|
4171
|
+
function GeometryStampHost2({ api, editingElement, onClose, isDark, generateGeometryFigure, onGeometryDraft }, ref) {
|
|
4091
4172
|
const panelRef = useRef(null);
|
|
4092
4173
|
const { isMobile } = useIsMobile();
|
|
4093
4174
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
@@ -4202,7 +4283,9 @@ var GeometryStampHost = forwardRef(
|
|
|
4202
4283
|
canUndo,
|
|
4203
4284
|
canRedo,
|
|
4204
4285
|
onSelectionChange: setSelectedObjectId,
|
|
4205
|
-
generateGeometryFigure
|
|
4286
|
+
generateGeometryFigure,
|
|
4287
|
+
api,
|
|
4288
|
+
onGeometryDraft
|
|
4206
4289
|
}
|
|
4207
4290
|
)
|
|
4208
4291
|
] });
|
|
@@ -4210,5 +4293,5 @@ var GeometryStampHost = forwardRef(
|
|
|
4210
4293
|
);
|
|
4211
4294
|
|
|
4212
4295
|
export { GeometryStampHost };
|
|
4213
|
-
//# sourceMappingURL=host-
|
|
4214
|
-
//# sourceMappingURL=host-
|
|
4296
|
+
//# sourceMappingURL=host-4P766V4J.mjs.map
|
|
4297
|
+
//# sourceMappingURL=host-4P766V4J.mjs.map
|