@xom11/whiteboard 0.6.1 → 0.6.2
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/index.js +140 -130
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -126
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import './index.css';
|
|
2
3
|
import dynamic from 'next/dynamic';
|
|
3
4
|
import { forwardRef, useRef, useState, useEffect, useCallback, useImperativeHandle, useMemo, useId } from 'react';
|
|
4
5
|
import { createPortal } from 'react-dom';
|
|
5
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import JXG from 'jsxgraph';
|
|
7
7
|
import '@excalidraw/excalidraw/index.css';
|
|
8
8
|
|
|
9
9
|
// src/Whiteboard.tsx
|
|
@@ -637,9 +637,9 @@ function handleMove(ctx, e) {
|
|
|
637
637
|
if (!ctx.boardRef.current || !ctx.phantomRef.current) return;
|
|
638
638
|
try {
|
|
639
639
|
const coords = ctx.boardRef.current.getUsrCoordsOfMouse(e);
|
|
640
|
-
const
|
|
641
|
-
if (!
|
|
642
|
-
ctx.phantomRef.current.setPositionDirectly(
|
|
640
|
+
const JXG = ctx.jxgRef.current;
|
|
641
|
+
if (!JXG) return;
|
|
642
|
+
ctx.phantomRef.current.setPositionDirectly(JXG.COORDS_BY_USER, [coords[0], coords[1]]);
|
|
643
643
|
ctx.boardRef.current.update();
|
|
644
644
|
} catch {
|
|
645
645
|
}
|
|
@@ -1446,11 +1446,11 @@ var JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
|
1446
1446
|
if (typeof window === "undefined" || !containerRef.current) return;
|
|
1447
1447
|
let cancelled = false;
|
|
1448
1448
|
(async () => {
|
|
1449
|
-
const
|
|
1449
|
+
const JXG = (await import('jsxgraph')).default;
|
|
1450
1450
|
if (cancelled || !containerRef.current) return;
|
|
1451
|
-
jxgRef.current =
|
|
1451
|
+
jxgRef.current = JXG;
|
|
1452
1452
|
try {
|
|
1453
|
-
const opts =
|
|
1453
|
+
const opts = JXG.Options;
|
|
1454
1454
|
if (opts) {
|
|
1455
1455
|
opts.text = opts.text || {};
|
|
1456
1456
|
opts.text.display = "internal";
|
|
@@ -1464,7 +1464,7 @@ var JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
|
1464
1464
|
}
|
|
1465
1465
|
} catch {
|
|
1466
1466
|
}
|
|
1467
|
-
const board =
|
|
1467
|
+
const board = JXG.JSXGraph.initBoard(containerId, {
|
|
1468
1468
|
boundingbox: initialState?.bbox ?? [-10, 10, 10, -10],
|
|
1469
1469
|
axis: false,
|
|
1470
1470
|
// We manage axis manually via toggle for clean default
|
|
@@ -2096,9 +2096,9 @@ function renderGeometryToSvg(boardContainer) {
|
|
|
2096
2096
|
async function renderGeometrySvgFromState(jsonState) {
|
|
2097
2097
|
const parsed = JSON.parse(jsonState);
|
|
2098
2098
|
const palette = paletteFor(false);
|
|
2099
|
-
const
|
|
2099
|
+
const JXG = (await import('jsxgraph')).default;
|
|
2100
2100
|
try {
|
|
2101
|
-
const opts =
|
|
2101
|
+
const opts = JXG.Options;
|
|
2102
2102
|
if (opts) {
|
|
2103
2103
|
opts.text = opts.text || {};
|
|
2104
2104
|
opts.text.display = "internal";
|
|
@@ -2123,7 +2123,7 @@ async function renderGeometrySvgFromState(jsonState) {
|
|
|
2123
2123
|
document.body.appendChild(container);
|
|
2124
2124
|
let board = null;
|
|
2125
2125
|
try {
|
|
2126
|
-
board =
|
|
2126
|
+
board = JXG.JSXGraph.initBoard(containerId, {
|
|
2127
2127
|
boundingbox: parsed.bbox,
|
|
2128
2128
|
axis: !!parsed.showAxis,
|
|
2129
2129
|
grid: !!parsed.showGrid,
|
|
@@ -2136,7 +2136,7 @@ async function renderGeometrySvgFromState(jsonState) {
|
|
|
2136
2136
|
return renderGeometryToSvg(container);
|
|
2137
2137
|
} finally {
|
|
2138
2138
|
try {
|
|
2139
|
-
if (board)
|
|
2139
|
+
if (board) JXG.JSXGraph.freeBoard(board);
|
|
2140
2140
|
} catch {
|
|
2141
2141
|
}
|
|
2142
2142
|
if (container.parentNode) container.parentNode.removeChild(container);
|
|
@@ -3808,126 +3808,134 @@ var MiniBoard3D = forwardRef(function MiniBoard3D2({ isDark, initialState }, ref
|
|
|
3808
3808
|
useEffect(() => {
|
|
3809
3809
|
const div = containerRef.current;
|
|
3810
3810
|
if (!div) return;
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3811
|
+
let cancelled = false;
|
|
3812
|
+
let JXG = null;
|
|
3813
|
+
let board = null;
|
|
3814
|
+
void (async () => {
|
|
3815
|
+
JXG = (await import('jsxgraph')).default;
|
|
3816
|
+
if (cancelled || !containerRef.current) return;
|
|
3817
|
+
JXG.Options.text.display = "internal";
|
|
3818
|
+
board = JXG.JSXGraph.initBoard(div, {
|
|
3819
|
+
boundingbox: [-6, 6, 6, -6],
|
|
3820
|
+
axis: false,
|
|
3821
|
+
showCopyright: false,
|
|
3822
|
+
showNavigation: false,
|
|
3823
|
+
renderer: "svg"
|
|
3824
|
+
});
|
|
3825
|
+
boardRef.current = board;
|
|
3826
|
+
const initView = initialState?.view ?? DEFAULT_VIEW3D;
|
|
3827
|
+
const baseAttrs = VIEW3D_ATTRS(isDark);
|
|
3828
|
+
const view = board.create(
|
|
3829
|
+
"view3d",
|
|
3827
3830
|
[
|
|
3828
|
-
[
|
|
3829
|
-
[
|
|
3830
|
-
[
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
view
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3831
|
+
[-5, -5],
|
|
3832
|
+
[10, 10],
|
|
3833
|
+
[
|
|
3834
|
+
[initView.bbox3D[0], initView.bbox3D[3]],
|
|
3835
|
+
[initView.bbox3D[1], initView.bbox3D[4]],
|
|
3836
|
+
[initView.bbox3D[2], initView.bbox3D[5]]
|
|
3837
|
+
]
|
|
3838
|
+
],
|
|
3839
|
+
{
|
|
3840
|
+
...baseAttrs,
|
|
3841
|
+
az: { ...baseAttrs.az, value: initView.azimuth },
|
|
3842
|
+
el: { ...baseAttrs.el, value: initView.elevation }
|
|
3843
|
+
}
|
|
3844
|
+
);
|
|
3845
|
+
viewRef.current = view;
|
|
3846
|
+
let idCounter = 1;
|
|
3847
|
+
const ctx = createHandlerContext({
|
|
3848
|
+
view,
|
|
3849
|
+
pushLog: (e) => {
|
|
3850
|
+
logRef.current.push(e);
|
|
3851
|
+
notify();
|
|
3852
|
+
},
|
|
3853
|
+
objMap: objMapRef.current,
|
|
3854
|
+
nextId: () => `obj_${Date.now().toString(36)}_${(idCounter++).toString(36)}`,
|
|
3855
|
+
isDark,
|
|
3856
|
+
promptCoords: (label) => {
|
|
3857
|
+
const raw = window.prompt(`${label}
|
|
3852
3858
|
(\u0111\u1ECBnh d\u1EA1ng "x,y,z")`, "0,0,0");
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3859
|
+
if (!raw) return null;
|
|
3860
|
+
const parts = raw.split(",").map((s) => Number(s.trim()));
|
|
3861
|
+
if (parts.length !== 3 || parts.some((n) => !isFinite(n))) return null;
|
|
3862
|
+
return { x: parts[0], y: parts[1], z: parts[2] };
|
|
3863
|
+
},
|
|
3864
|
+
promptNumber: (label) => {
|
|
3865
|
+
const raw = window.prompt(label, "1");
|
|
3866
|
+
if (raw == null) return null;
|
|
3867
|
+
const n = Number(raw);
|
|
3868
|
+
return isFinite(n) ? n : null;
|
|
3869
|
+
},
|
|
3870
|
+
promptText: (label) => {
|
|
3871
|
+
const raw = window.prompt(label, "");
|
|
3872
|
+
return raw == null ? null : raw;
|
|
3873
|
+
},
|
|
3874
|
+
notify
|
|
3875
|
+
});
|
|
3876
|
+
ctxRef.current = ctx;
|
|
3877
|
+
function findExistingPointAt(clientX, clientY) {
|
|
3878
|
+
const containerRect = div.getBoundingClientRect();
|
|
3879
|
+
const localX = clientX - containerRect.left;
|
|
3880
|
+
const localY = clientY - containerRect.top;
|
|
3881
|
+
const PICK = 18;
|
|
3882
|
+
const svg = div.querySelector("svg");
|
|
3883
|
+
if (!svg) return void 0;
|
|
3884
|
+
for (const [id, obj] of objMapRef.current) {
|
|
3885
|
+
const entry = obj;
|
|
3886
|
+
if (entry?.elType !== "point3d") continue;
|
|
3887
|
+
const sc = entry.element2D?.coords?.scrCoords;
|
|
3888
|
+
if (!sc || sc.length < 3) continue;
|
|
3889
|
+
const dx = sc[1] - localX;
|
|
3890
|
+
const dy = sc[2] - localY;
|
|
3891
|
+
if (dx * dx + dy * dy <= PICK * PICK) return id;
|
|
3892
|
+
}
|
|
3893
|
+
return void 0;
|
|
3886
3894
|
}
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
y3 = uc[1];
|
|
3895
|
+
const handlePointerDown = (e) => {
|
|
3896
|
+
const tool = toolRef.current;
|
|
3897
|
+
if (tool === "move") return;
|
|
3898
|
+
const existingPointId = findExistingPointAt(e.clientX, e.clientY);
|
|
3899
|
+
let x3 = 0;
|
|
3900
|
+
let y3 = 0;
|
|
3901
|
+
const z3 = 0;
|
|
3902
|
+
try {
|
|
3903
|
+
const board2d = boardRef.current;
|
|
3904
|
+
if (board2d?.getUsrCoordsOfMouse) {
|
|
3905
|
+
const uc = board2d.getUsrCoordsOfMouse(e);
|
|
3906
|
+
if (Array.isArray(uc) && uc.length >= 2) {
|
|
3907
|
+
x3 = uc[0];
|
|
3908
|
+
y3 = uc[1];
|
|
3909
|
+
}
|
|
3903
3910
|
}
|
|
3911
|
+
} catch {
|
|
3912
|
+
}
|
|
3913
|
+
const hit = { x3, y3, z3, existingPointId };
|
|
3914
|
+
handleToolStep(ctx, tool, hit);
|
|
3915
|
+
};
|
|
3916
|
+
const svgEl = div.querySelector("svg");
|
|
3917
|
+
const targetEl = svgEl ?? div;
|
|
3918
|
+
const handlePointerDownEv = (e) => handlePointerDown(e);
|
|
3919
|
+
targetEl.addEventListener("pointerdown", handlePointerDownEv);
|
|
3920
|
+
pointerHandlerRef.current = { el: targetEl, fn: handlePointerDownEv };
|
|
3921
|
+
if (initialState?.elements?.length) {
|
|
3922
|
+
const map = objMapRef.current;
|
|
3923
|
+
for (const el of initialState.elements) {
|
|
3924
|
+
const parents = el.parents.map(
|
|
3925
|
+
(p2) => typeof p2 === "string" && p2.startsWith("@id:") ? map.get(p2.slice(4)) : p2
|
|
3926
|
+
);
|
|
3927
|
+
const obj = view.create(el.type, parents, {
|
|
3928
|
+
...el.attributes,
|
|
3929
|
+
id: el.id,
|
|
3930
|
+
name: el.label
|
|
3931
|
+
});
|
|
3932
|
+
map.set(el.id, obj);
|
|
3933
|
+
logRef.current.push(el);
|
|
3904
3934
|
}
|
|
3905
|
-
} catch {
|
|
3906
|
-
}
|
|
3907
|
-
const hit = { x3, y3, z3, existingPointId };
|
|
3908
|
-
handleToolStep(ctx, tool, hit);
|
|
3909
|
-
};
|
|
3910
|
-
const svgEl = div.querySelector("svg");
|
|
3911
|
-
const targetEl = svgEl ?? div;
|
|
3912
|
-
const handlePointerDownEv = (e) => handlePointerDown(e);
|
|
3913
|
-
targetEl.addEventListener("pointerdown", handlePointerDownEv);
|
|
3914
|
-
pointerHandlerRef.current = { el: targetEl, fn: handlePointerDownEv };
|
|
3915
|
-
if (initialState?.elements?.length) {
|
|
3916
|
-
const map = objMapRef.current;
|
|
3917
|
-
for (const el of initialState.elements) {
|
|
3918
|
-
const parents = el.parents.map(
|
|
3919
|
-
(p2) => typeof p2 === "string" && p2.startsWith("@id:") ? map.get(p2.slice(4)) : p2
|
|
3920
|
-
);
|
|
3921
|
-
const obj = view.create(el.type, parents, {
|
|
3922
|
-
...el.attributes,
|
|
3923
|
-
id: el.id,
|
|
3924
|
-
name: el.label
|
|
3925
|
-
});
|
|
3926
|
-
map.set(el.id, obj);
|
|
3927
|
-
logRef.current.push(el);
|
|
3928
3935
|
}
|
|
3929
|
-
}
|
|
3936
|
+
})();
|
|
3930
3937
|
return () => {
|
|
3938
|
+
cancelled = true;
|
|
3931
3939
|
if (pointerHandlerRef.current) {
|
|
3932
3940
|
pointerHandlerRef.current.el.removeEventListener(
|
|
3933
3941
|
"pointerdown",
|
|
@@ -3936,7 +3944,7 @@ var MiniBoard3D = forwardRef(function MiniBoard3D2({ isDark, initialState }, ref
|
|
|
3936
3944
|
pointerHandlerRef.current = null;
|
|
3937
3945
|
}
|
|
3938
3946
|
try {
|
|
3939
|
-
JXG.JSXGraph.freeBoard(board);
|
|
3947
|
+
if (board && JXG) JXG.JSXGraph.freeBoard(board);
|
|
3940
3948
|
} catch {
|
|
3941
3949
|
}
|
|
3942
3950
|
boardRef.current = null;
|
|
@@ -4460,10 +4468,13 @@ function parseSerializedBoard3D(json) {
|
|
|
4460
4468
|
}
|
|
4461
4469
|
return parsed;
|
|
4462
4470
|
}
|
|
4471
|
+
|
|
4472
|
+
// src/stamps/geometry-3d/render.ts
|
|
4463
4473
|
var OUTPUT_WIDTH = 1024;
|
|
4464
4474
|
var OUTPUT_HEIGHT = 768;
|
|
4465
4475
|
async function renderGeometry3DSvgFromState(jsonState) {
|
|
4466
4476
|
const state = parseSerializedBoard3D(jsonState);
|
|
4477
|
+
const JXG = (await import('jsxgraph')).default;
|
|
4467
4478
|
const div = document.createElement("div");
|
|
4468
4479
|
div.style.cssText = `position:absolute;left:-9999px;top:-9999px;width:${OUTPUT_WIDTH}px;height:${OUTPUT_HEIGHT}px;`;
|
|
4469
4480
|
document.body.appendChild(div);
|