@xom11/whiteboard 0.9.1 → 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/dist/{chunk-KEYZ5EZT.mjs → chunk-G7FR3AIV.mjs} +44 -5
- package/dist/chunk-G7FR3AIV.mjs.map +1 -0
- package/dist/{chunk-DU3RHKT5.mjs → chunk-PDKKDZ4H.mjs} +4 -4
- package/dist/{chunk-DU3RHKT5.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-WQOABS6N.mjs +197 -0
- package/dist/chunk-WQOABS6N.mjs.map +1 -0
- package/dist/geometry-2d.js +96 -12
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +2 -2
- package/dist/geometry-3d.js +152 -93
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +2 -2
- package/dist/{host-VDNAJMLC.mjs → host-DJETSFCG.mjs} +56 -12
- package/dist/host-DJETSFCG.mjs.map +1 -0
- package/dist/{host-PIIDSMVE.mjs → host-N6ACNJKI.mjs} +51 -12
- package/dist/host-N6ACNJKI.mjs.map +1 -0
- package/dist/index.d.mts +127 -1
- package/dist/index.d.ts +127 -1
- package/dist/index.js +1265 -174
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +991 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -1
- package/dist/chunk-DU2NFHRR.mjs +0 -103
- package/dist/chunk-DU2NFHRR.mjs.map +0 -1
- package/dist/chunk-IUVV52HO.mjs +0 -144
- package/dist/chunk-IUVV52HO.mjs.map +0 -1
- package/dist/chunk-KEYZ5EZT.mjs.map +0 -1
- package/dist/host-PIIDSMVE.mjs.map +0 -1
- package/dist/host-VDNAJMLC.mjs.map +0 -1
package/dist/geometry-2d.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { geometryStamp } from './chunk-
|
|
3
|
-
export { isGeometryCustomData } from './chunk-
|
|
2
|
+
export { geometryStamp } from './chunk-PDKKDZ4H.mjs';
|
|
3
|
+
export { isGeometryCustomData } from './chunk-G7FR3AIV.mjs';
|
|
4
4
|
import './chunk-HTBLO5JO.mjs';
|
|
5
5
|
import './chunk-BJTO5JO5.mjs';
|
|
6
6
|
//# sourceMappingURL=geometry-2d.mjs.map
|
package/dist/geometry-3d.js
CHANGED
|
@@ -161,6 +161,108 @@ var init_theme2 = __esm({
|
|
|
161
161
|
}
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
+
// src/stamps/geometry-3d/render.ts
|
|
165
|
+
async function renderGeometry3DSvgFromState(jsonState) {
|
|
166
|
+
const state = parseSerializedBoard3D(jsonState);
|
|
167
|
+
const JXG = (await import('jsxgraph')).default;
|
|
168
|
+
const div = document.createElement("div");
|
|
169
|
+
div.style.cssText = `position:absolute;left:-9999px;top:-9999px;width:${OUTPUT_WIDTH}px;height:${OUTPUT_HEIGHT}px;`;
|
|
170
|
+
document.body.appendChild(div);
|
|
171
|
+
try {
|
|
172
|
+
JXG.Options.text.display = "internal";
|
|
173
|
+
const board = JXG.JSXGraph.initBoard(div, {
|
|
174
|
+
boundingbox: state.bbox,
|
|
175
|
+
keepaspectratio: true,
|
|
176
|
+
axis: false,
|
|
177
|
+
showCopyright: false,
|
|
178
|
+
showNavigation: false,
|
|
179
|
+
renderer: "svg"
|
|
180
|
+
});
|
|
181
|
+
const baseAttrs = VIEW3D_ATTRS(false);
|
|
182
|
+
const view = board.create(
|
|
183
|
+
"view3d",
|
|
184
|
+
[
|
|
185
|
+
[-5, -5],
|
|
186
|
+
[10, 10],
|
|
187
|
+
[
|
|
188
|
+
[state.view.bbox3D[0], state.view.bbox3D[3]],
|
|
189
|
+
[state.view.bbox3D[1], state.view.bbox3D[4]],
|
|
190
|
+
[state.view.bbox3D[2], state.view.bbox3D[5]]
|
|
191
|
+
]
|
|
192
|
+
],
|
|
193
|
+
{
|
|
194
|
+
...baseAttrs,
|
|
195
|
+
// JSXGraph view3d đọc azimuth/elevation từ az.slider.start (không phải
|
|
196
|
+
// az.value). Nếu pass `value` → JSXGraph bỏ qua → render rơi về default
|
|
197
|
+
// (1.0 rad / 0.3 rad), không khớp góc user xoay trong editor.
|
|
198
|
+
az: { ...baseAttrs.az, slider: { ...baseAttrs.az.slider, start: state.view.azimuth } },
|
|
199
|
+
el: { ...baseAttrs.el, slider: { ...baseAttrs.el.slider, start: state.view.elevation } }
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
try {
|
|
203
|
+
const v = view;
|
|
204
|
+
v?.az_slide?.setValue?.(state.view.azimuth);
|
|
205
|
+
v?.el_slide?.setValue?.(state.view.elevation);
|
|
206
|
+
v?.board?.update?.();
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
if (!state.showAxes) {
|
|
210
|
+
view.defaultAxes = [];
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
view.create(
|
|
214
|
+
"plane3d",
|
|
215
|
+
[
|
|
216
|
+
[0, 0, 0],
|
|
217
|
+
[1, 0, 0],
|
|
218
|
+
[0, 1, 0],
|
|
219
|
+
GROUND_PLANE_RANGE,
|
|
220
|
+
GROUND_PLANE_RANGE
|
|
221
|
+
],
|
|
222
|
+
GROUND_PLANE_ATTRS(false)
|
|
223
|
+
);
|
|
224
|
+
} catch {
|
|
225
|
+
}
|
|
226
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
227
|
+
for (const el of state.elements) {
|
|
228
|
+
const parents = el.parents.map(
|
|
229
|
+
(p) => typeof p === "string" && p.startsWith("@id:") ? idMap.get(p.slice(4)) : p
|
|
230
|
+
);
|
|
231
|
+
const obj = view.create(el.type, parents, {
|
|
232
|
+
...el.attributes,
|
|
233
|
+
id: el.id,
|
|
234
|
+
name: el.label
|
|
235
|
+
});
|
|
236
|
+
idMap.set(el.id, obj);
|
|
237
|
+
}
|
|
238
|
+
const svg = div.querySelector("svg");
|
|
239
|
+
if (!svg) {
|
|
240
|
+
throw new Error("renderGeometry3DSvgFromState: SVG not produced");
|
|
241
|
+
}
|
|
242
|
+
const clone = svg.cloneNode(true);
|
|
243
|
+
clone.setAttribute("width", String(OUTPUT_WIDTH));
|
|
244
|
+
clone.setAttribute("height", String(OUTPUT_HEIGHT));
|
|
245
|
+
const svgString = new XMLSerializer().serializeToString(clone);
|
|
246
|
+
try {
|
|
247
|
+
JXG.JSXGraph.freeBoard(board);
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
return { svgString, width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT };
|
|
251
|
+
} finally {
|
|
252
|
+
document.body.removeChild(div);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
var OUTPUT_WIDTH, OUTPUT_HEIGHT;
|
|
256
|
+
var init_render = __esm({
|
|
257
|
+
"src/stamps/geometry-3d/render.ts"() {
|
|
258
|
+
"use client";
|
|
259
|
+
init_serialize();
|
|
260
|
+
init_theme2();
|
|
261
|
+
OUTPUT_WIDTH = 1024;
|
|
262
|
+
OUTPUT_HEIGHT = 768;
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
164
266
|
// src/stamps/geometry-3d/editor/tools/handlers/_ensurePoint.ts
|
|
165
267
|
function hitToConstraint(hit) {
|
|
166
268
|
switch (hit.kind) {
|
|
@@ -1562,8 +1664,11 @@ var init_MiniBoard3D = __esm({
|
|
|
1562
1664
|
],
|
|
1563
1665
|
{
|
|
1564
1666
|
...baseAttrs,
|
|
1565
|
-
|
|
1566
|
-
|
|
1667
|
+
// JSXGraph view3d đọc giá trị khởi tạo từ az.slider.start (không
|
|
1668
|
+
// phải az.value). Pass nhầm `value` → JSXGraph dùng default
|
|
1669
|
+
// 1.0/0.3, khiến DEFAULT_VIEW3D bị bỏ qua.
|
|
1670
|
+
az: { ...baseAttrs.az, slider: { ...baseAttrs.az.slider, start: DEFAULT_VIEW3D.azimuth } },
|
|
1671
|
+
el: { ...baseAttrs.el, slider: { ...baseAttrs.el.slider, start: DEFAULT_VIEW3D.elevation } }
|
|
1567
1672
|
}
|
|
1568
1673
|
);
|
|
1569
1674
|
} catch {
|
|
@@ -2200,6 +2305,7 @@ var init_EditorPanel = __esm({
|
|
|
2200
2305
|
init_ensurePoint();
|
|
2201
2306
|
init_MiniBoard3D();
|
|
2202
2307
|
init_StatusHint();
|
|
2308
|
+
init_theme2();
|
|
2203
2309
|
init_persistence();
|
|
2204
2310
|
EditorPanel = React2__namespace.forwardRef(
|
|
2205
2311
|
function EditorPanel2(props, ref) {
|
|
@@ -2305,8 +2411,17 @@ var init_EditorPanel = __esm({
|
|
|
2305
2411
|
}, [showAxis, showGrid]);
|
|
2306
2412
|
const handleView3DReady = React2__namespace.useCallback((view) => {
|
|
2307
2413
|
rendererRef.current = new JxgRenderer(scene, view);
|
|
2414
|
+
if (initialState) {
|
|
2415
|
+
try {
|
|
2416
|
+
const v = view;
|
|
2417
|
+
v?.az_slide?.setValue?.(initialState.view.azimuth);
|
|
2418
|
+
v?.el_slide?.setValue?.(initialState.view.elevation);
|
|
2419
|
+
v?.board?.update?.();
|
|
2420
|
+
} catch {
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2308
2423
|
onReadyChange?.(true);
|
|
2309
|
-
}, [onReadyChange, scene]);
|
|
2424
|
+
}, [onReadyChange, scene, initialState]);
|
|
2310
2425
|
const handleClick = React2__namespace.useCallback((screen) => {
|
|
2311
2426
|
const board = boardRef.current;
|
|
2312
2427
|
if (!board) return;
|
|
@@ -2444,8 +2559,10 @@ var init_EditorPanel = __esm({
|
|
|
2444
2559
|
const elevation = typeof elSlider?.Value === "function" ? elSlider.Value() : 0;
|
|
2445
2560
|
return sceneToBoard(
|
|
2446
2561
|
scene,
|
|
2447
|
-
{ azimuth, elevation, bbox3D: [
|
|
2448
|
-
[
|
|
2562
|
+
{ azimuth, elevation, bbox3D: [...DEFAULT_VIEW3D.bbox3D] },
|
|
2563
|
+
// JSXGraph boundingbox order: [xmin, ymax, xmax, ymin]. Must match
|
|
2564
|
+
// MiniBoard3D.initBoard so render reproduces the editor's view.
|
|
2565
|
+
[-6, 6, 6, -6]
|
|
2449
2566
|
);
|
|
2450
2567
|
},
|
|
2451
2568
|
setTool: (k) => controllerRef.current.selectTool(k),
|
|
@@ -3722,6 +3839,7 @@ var init_host = __esm({
|
|
|
3722
3839
|
init_useChordShortcut();
|
|
3723
3840
|
init_insertImage();
|
|
3724
3841
|
init_useIsMobile();
|
|
3842
|
+
init_render();
|
|
3725
3843
|
init_serialize();
|
|
3726
3844
|
Geometry3DStampHost = React2.forwardRef(
|
|
3727
3845
|
function Geometry3DStampHost2({ api, editingElement, onClose, isDark }, ref) {
|
|
@@ -3736,10 +3854,25 @@ var init_host = __esm({
|
|
|
3736
3854
|
const [showGrid, setShowGrid] = React2.useState(true);
|
|
3737
3855
|
const [canUndo, setCanUndo] = React2.useState(false);
|
|
3738
3856
|
const [canRedo, setCanRedo] = React2.useState(false);
|
|
3857
|
+
const [hasContent, setHasContent] = React2.useState(false);
|
|
3739
3858
|
const handleHistoryChange = React2.useCallback((u, r) => {
|
|
3740
3859
|
setCanUndo(u);
|
|
3741
3860
|
setCanRedo(r);
|
|
3742
3861
|
}, []);
|
|
3862
|
+
React2.useEffect(() => {
|
|
3863
|
+
const scene = sceneRef.current;
|
|
3864
|
+
if (!scene) return;
|
|
3865
|
+
const sync = () => setHasContent(scene.list().length > 0);
|
|
3866
|
+
sync();
|
|
3867
|
+
const unsubs = [
|
|
3868
|
+
scene.on("add", sync),
|
|
3869
|
+
scene.on("delete", sync),
|
|
3870
|
+
scene.on("reset", sync)
|
|
3871
|
+
];
|
|
3872
|
+
return () => {
|
|
3873
|
+
for (const u of unsubs) u();
|
|
3874
|
+
};
|
|
3875
|
+
}, []);
|
|
3743
3876
|
const handleUndo = React2.useCallback(() => {
|
|
3744
3877
|
editorRef.current?.undo();
|
|
3745
3878
|
}, []);
|
|
@@ -3787,7 +3920,15 @@ var init_host = __esm({
|
|
|
3787
3920
|
if (!editorRef.current.hasContent()) return false;
|
|
3788
3921
|
const board = editorRef.current.serialize();
|
|
3789
3922
|
if (board.elements.length === 0) return false;
|
|
3790
|
-
void
|
|
3923
|
+
void (async () => {
|
|
3924
|
+
try {
|
|
3925
|
+
const jsonState = serializeBoard3D(board);
|
|
3926
|
+
const { svgString, width, height } = await renderGeometry3DSvgFromState(jsonState);
|
|
3927
|
+
await performInsert(board, width, height, svgString);
|
|
3928
|
+
} catch (err) {
|
|
3929
|
+
console.error("Geometry3D insert failed:", err);
|
|
3930
|
+
}
|
|
3931
|
+
})();
|
|
3791
3932
|
return true;
|
|
3792
3933
|
}, [performInsert]);
|
|
3793
3934
|
React2.useImperativeHandle(
|
|
@@ -3869,7 +4010,8 @@ var init_host = __esm({
|
|
|
3869
4010
|
{
|
|
3870
4011
|
type: "button",
|
|
3871
4012
|
onClick: tryInsert,
|
|
3872
|
-
disabled: !ready,
|
|
4013
|
+
disabled: !ready || !hasContent,
|
|
4014
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
3873
4015
|
"data-testid": "geom3d-insert-btn-mobile",
|
|
3874
4016
|
className: "rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50",
|
|
3875
4017
|
children: "Ch\xE8n"
|
|
@@ -3919,7 +4061,8 @@ var init_host = __esm({
|
|
|
3919
4061
|
"button",
|
|
3920
4062
|
{
|
|
3921
4063
|
onClick: tryInsert,
|
|
3922
|
-
disabled: !ready,
|
|
4064
|
+
disabled: !ready || !hasContent,
|
|
4065
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
3923
4066
|
"data-testid": "geom3d-insert-btn",
|
|
3924
4067
|
className: "rounded bg-emerald-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-emerald-700 disabled:opacity-50",
|
|
3925
4068
|
children: "Ch\xE8n"
|
|
@@ -3960,91 +4103,7 @@ var init_host = __esm({
|
|
|
3960
4103
|
|
|
3961
4104
|
// src/stamps/geometry-3d/index.tsx
|
|
3962
4105
|
init_serialize();
|
|
3963
|
-
|
|
3964
|
-
// src/stamps/geometry-3d/render.ts
|
|
3965
|
-
init_serialize();
|
|
3966
|
-
init_theme2();
|
|
3967
|
-
var OUTPUT_WIDTH = 1024;
|
|
3968
|
-
var OUTPUT_HEIGHT = 768;
|
|
3969
|
-
async function renderGeometry3DSvgFromState(jsonState) {
|
|
3970
|
-
const state = parseSerializedBoard3D(jsonState);
|
|
3971
|
-
const JXG = (await import('jsxgraph')).default;
|
|
3972
|
-
const div = document.createElement("div");
|
|
3973
|
-
div.style.cssText = `position:absolute;left:-9999px;top:-9999px;width:${OUTPUT_WIDTH}px;height:${OUTPUT_HEIGHT}px;`;
|
|
3974
|
-
document.body.appendChild(div);
|
|
3975
|
-
try {
|
|
3976
|
-
JXG.Options.text.display = "internal";
|
|
3977
|
-
const board = JXG.JSXGraph.initBoard(div, {
|
|
3978
|
-
boundingbox: state.bbox,
|
|
3979
|
-
axis: false,
|
|
3980
|
-
showCopyright: false,
|
|
3981
|
-
showNavigation: false,
|
|
3982
|
-
renderer: "svg"
|
|
3983
|
-
});
|
|
3984
|
-
const baseAttrs = VIEW3D_ATTRS(false);
|
|
3985
|
-
const view = board.create(
|
|
3986
|
-
"view3d",
|
|
3987
|
-
[
|
|
3988
|
-
[-5, -5],
|
|
3989
|
-
[10, 10],
|
|
3990
|
-
[
|
|
3991
|
-
[state.view.bbox3D[0], state.view.bbox3D[3]],
|
|
3992
|
-
[state.view.bbox3D[1], state.view.bbox3D[4]],
|
|
3993
|
-
[state.view.bbox3D[2], state.view.bbox3D[5]]
|
|
3994
|
-
]
|
|
3995
|
-
],
|
|
3996
|
-
{
|
|
3997
|
-
...baseAttrs,
|
|
3998
|
-
az: { ...baseAttrs.az, value: state.view.azimuth },
|
|
3999
|
-
el: { ...baseAttrs.el, value: state.view.elevation }
|
|
4000
|
-
}
|
|
4001
|
-
);
|
|
4002
|
-
if (!state.showAxes) {
|
|
4003
|
-
view.defaultAxes = [];
|
|
4004
|
-
}
|
|
4005
|
-
try {
|
|
4006
|
-
view.create(
|
|
4007
|
-
"plane3d",
|
|
4008
|
-
[
|
|
4009
|
-
[0, 0, 0],
|
|
4010
|
-
[1, 0, 0],
|
|
4011
|
-
[0, 1, 0],
|
|
4012
|
-
GROUND_PLANE_RANGE,
|
|
4013
|
-
GROUND_PLANE_RANGE
|
|
4014
|
-
],
|
|
4015
|
-
GROUND_PLANE_ATTRS(false)
|
|
4016
|
-
);
|
|
4017
|
-
} catch {
|
|
4018
|
-
}
|
|
4019
|
-
const idMap = /* @__PURE__ */ new Map();
|
|
4020
|
-
for (const el of state.elements) {
|
|
4021
|
-
const parents = el.parents.map(
|
|
4022
|
-
(p) => typeof p === "string" && p.startsWith("@id:") ? idMap.get(p.slice(4)) : p
|
|
4023
|
-
);
|
|
4024
|
-
const obj = view.create(el.type, parents, {
|
|
4025
|
-
...el.attributes,
|
|
4026
|
-
id: el.id,
|
|
4027
|
-
name: el.label
|
|
4028
|
-
});
|
|
4029
|
-
idMap.set(el.id, obj);
|
|
4030
|
-
}
|
|
4031
|
-
const svg = div.querySelector("svg");
|
|
4032
|
-
if (!svg) {
|
|
4033
|
-
throw new Error("renderGeometry3DSvgFromState: SVG not produced");
|
|
4034
|
-
}
|
|
4035
|
-
const clone = svg.cloneNode(true);
|
|
4036
|
-
clone.setAttribute("width", String(OUTPUT_WIDTH));
|
|
4037
|
-
clone.setAttribute("height", String(OUTPUT_HEIGHT));
|
|
4038
|
-
const svgString = new XMLSerializer().serializeToString(clone);
|
|
4039
|
-
try {
|
|
4040
|
-
JXG.JSXGraph.freeBoard(board);
|
|
4041
|
-
} catch {
|
|
4042
|
-
}
|
|
4043
|
-
return { svgString, width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT };
|
|
4044
|
-
} finally {
|
|
4045
|
-
document.body.removeChild(div);
|
|
4046
|
-
}
|
|
4047
|
-
}
|
|
4106
|
+
init_render();
|
|
4048
4107
|
var Geometry3DStampHost3 = React2.lazy(
|
|
4049
4108
|
() => Promise.resolve().then(() => (init_host(), host_exports)).then((m) => ({ default: m.Geometry3DStampHost }))
|
|
4050
4109
|
);
|