@xom11/whiteboard 0.9.1 → 0.10.1
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-ZVN356JZ.mjs → chunk-D257NCQW.mjs} +3 -3
- package/dist/{chunk-ZVN356JZ.mjs.map → chunk-D257NCQW.mjs.map} +1 -1
- package/dist/{chunk-KEYZ5EZT.mjs → chunk-G7FR3AIV.mjs} +44 -5
- package/dist/chunk-G7FR3AIV.mjs.map +1 -0
- 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/{chunk-DU3RHKT5.mjs → chunk-YVJP7NRG.mjs} +4 -4
- package/dist/{chunk-DU3RHKT5.mjs.map → chunk-YVJP7NRG.mjs.map} +1 -1
- package/dist/geometry-2d.js +102 -18
- 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/graph-2d.js +88 -20
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +1 -1
- package/dist/{host-PIIDSMVE.mjs → host-N6ACNJKI.mjs} +51 -12
- package/dist/host-N6ACNJKI.mjs.map +1 -0
- package/dist/{host-LZH2FZ2N.mjs → host-NKGV6RF2.mjs} +91 -23
- package/dist/host-NKGV6RF2.mjs.map +1 -0
- package/dist/{host-VDNAJMLC.mjs → host-XVK7UCRE.mjs} +62 -18
- package/dist/host-XVK7UCRE.mjs.map +1 -0
- package/dist/index.d.mts +127 -1
- package/dist/index.d.ts +127 -1
- package/dist/index.js +1336 -177
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +993 -52
- 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-LZH2FZ2N.mjs.map +0 -1
- package/dist/host-PIIDSMVE.mjs.map +0 -1
- package/dist/host-VDNAJMLC.mjs.map +0 -1
|
@@ -3,7 +3,7 @@ import { EMPTY_GRAPH, addPointOnCurve, addIntersection, validate, stringifySeria
|
|
|
3
3
|
import { useIsMobile } from './chunk-P2AOIF7S.mjs';
|
|
4
4
|
import { insertStampImage } from './chunk-C6SCVOMC.mjs';
|
|
5
5
|
import { __require } from './chunk-BJTO5JO5.mjs';
|
|
6
|
-
import { forwardRef, useRef, useState, useCallback,
|
|
6
|
+
import { forwardRef, useRef, useState, useCallback, useEffect, useImperativeHandle, useMemo } from 'react';
|
|
7
7
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
|
|
9
9
|
// src/stamps/graph-2d/editor/tools.ts
|
|
@@ -218,9 +218,15 @@ function CloseIcon() {
|
|
|
218
218
|
] });
|
|
219
219
|
}
|
|
220
220
|
function UndoIcon() {
|
|
221
|
-
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "
|
|
222
|
-
/* @__PURE__ */ jsx("
|
|
223
|
-
/* @__PURE__ */ jsx("path", { d: "M3
|
|
221
|
+
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
222
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10 L8 5 L8 8 L15 8 A5 5 0 0 1 20 13 L20 16" }),
|
|
223
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10 L8 15 L8 12" })
|
|
224
|
+
] });
|
|
225
|
+
}
|
|
226
|
+
function RedoIcon() {
|
|
227
|
+
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
228
|
+
/* @__PURE__ */ jsx("path", { d: "M21 10 L16 5 L16 8 L9 8 A5 5 0 0 0 4 13 L4 16" }),
|
|
229
|
+
/* @__PURE__ */ jsx("path", { d: "M21 10 L16 15 L16 12" })
|
|
224
230
|
] });
|
|
225
231
|
}
|
|
226
232
|
function ResetViewIcon() {
|
|
@@ -311,9 +317,23 @@ function PanelBody(props) {
|
|
|
311
317
|
disabled: !props.canUndo,
|
|
312
318
|
title: "Ho\xE0n t\xE1c (Ctrl/Cmd+Z)",
|
|
313
319
|
"aria-label": "Ho\xE0n t\xE1c",
|
|
320
|
+
"data-testid": "undo-btn",
|
|
314
321
|
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",
|
|
315
322
|
children: /* @__PURE__ */ jsx(UndoIcon, {})
|
|
316
323
|
}
|
|
324
|
+
),
|
|
325
|
+
/* @__PURE__ */ jsx(
|
|
326
|
+
"button",
|
|
327
|
+
{
|
|
328
|
+
type: "button",
|
|
329
|
+
onClick: props.onRedo,
|
|
330
|
+
disabled: !props.canRedo,
|
|
331
|
+
title: "L\xE0m l\u1EA1i (Ctrl/Cmd+Shift+Z)",
|
|
332
|
+
"aria-label": "L\xE0m l\u1EA1i",
|
|
333
|
+
"data-testid": "redo-btn",
|
|
334
|
+
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",
|
|
335
|
+
children: /* @__PURE__ */ jsx(RedoIcon, {})
|
|
336
|
+
}
|
|
317
337
|
)
|
|
318
338
|
] }) }),
|
|
319
339
|
/* @__PURE__ */ jsx(Section, { label: "C\xF4ng c\u1EE5", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-1", children: GRAPH_TOOLS.map((t) => {
|
|
@@ -628,6 +648,7 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
628
648
|
const [errors, setErrors] = useState({});
|
|
629
649
|
const [tool, setToolState] = useState("move");
|
|
630
650
|
const undoStackRef = useRef([]);
|
|
651
|
+
const redoStackRef = useRef([]);
|
|
631
652
|
const idCounterRef = useRef(1);
|
|
632
653
|
const toolRef = useRef(tool);
|
|
633
654
|
toolRef.current = tool;
|
|
@@ -638,6 +659,7 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
638
659
|
const pushUndo = useCallback((g) => {
|
|
639
660
|
undoStackRef.current.push(g);
|
|
640
661
|
if (undoStackRef.current.length > 30) undoStackRef.current.shift();
|
|
662
|
+
redoStackRef.current = [];
|
|
641
663
|
}, []);
|
|
642
664
|
const setErrorsWithNotify = useCallback(
|
|
643
665
|
(updater) => {
|
|
@@ -654,7 +676,8 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
654
676
|
tool: t,
|
|
655
677
|
showAxis: g.view.showAxis,
|
|
656
678
|
showGrid: g.view.showGrid,
|
|
657
|
-
canUndo: undoStackRef.current.length > 0
|
|
679
|
+
canUndo: undoStackRef.current.length > 0,
|
|
680
|
+
canRedo: redoStackRef.current.length > 0
|
|
658
681
|
});
|
|
659
682
|
}, []);
|
|
660
683
|
const updateGraph = useCallback(
|
|
@@ -669,6 +692,58 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
669
692
|
},
|
|
670
693
|
[pushUndo, notifyStateChange]
|
|
671
694
|
);
|
|
695
|
+
const doUndo = useCallback(() => {
|
|
696
|
+
const prev = undoStackRef.current.pop();
|
|
697
|
+
if (!prev) return;
|
|
698
|
+
redoStackRef.current.push(graphRef.current);
|
|
699
|
+
if (redoStackRef.current.length > 30) redoStackRef.current.shift();
|
|
700
|
+
graphRef.current = prev;
|
|
701
|
+
forceUpdate((n) => n + 1);
|
|
702
|
+
propsRef.current.onStateChange({
|
|
703
|
+
tool: toolRef.current,
|
|
704
|
+
showAxis: prev.view.showAxis,
|
|
705
|
+
showGrid: prev.view.showGrid,
|
|
706
|
+
canUndo: undoStackRef.current.length > 0,
|
|
707
|
+
canRedo: redoStackRef.current.length > 0
|
|
708
|
+
});
|
|
709
|
+
propsRef.current.onGraphChange?.(prev);
|
|
710
|
+
}, []);
|
|
711
|
+
const doRedo = useCallback(() => {
|
|
712
|
+
const next = redoStackRef.current.pop();
|
|
713
|
+
if (!next) return;
|
|
714
|
+
undoStackRef.current.push(graphRef.current);
|
|
715
|
+
if (undoStackRef.current.length > 30) undoStackRef.current.shift();
|
|
716
|
+
graphRef.current = next;
|
|
717
|
+
forceUpdate((n) => n + 1);
|
|
718
|
+
propsRef.current.onStateChange({
|
|
719
|
+
tool: toolRef.current,
|
|
720
|
+
showAxis: next.view.showAxis,
|
|
721
|
+
showGrid: next.view.showGrid,
|
|
722
|
+
canUndo: undoStackRef.current.length > 0,
|
|
723
|
+
canRedo: redoStackRef.current.length > 0
|
|
724
|
+
});
|
|
725
|
+
propsRef.current.onGraphChange?.(next);
|
|
726
|
+
}, []);
|
|
727
|
+
useEffect(() => {
|
|
728
|
+
const onKey = (e) => {
|
|
729
|
+
const ae = document.activeElement;
|
|
730
|
+
const inField = !!(ae && (ae.tagName === "INPUT" || ae.tagName === "TEXTAREA" || ae.isContentEditable));
|
|
731
|
+
if (inField) return;
|
|
732
|
+
if (!(e.metaKey || e.ctrlKey)) return;
|
|
733
|
+
const key = e.key.toLowerCase();
|
|
734
|
+
if (key === "z" && !e.shiftKey) {
|
|
735
|
+
e.preventDefault();
|
|
736
|
+
e.stopPropagation();
|
|
737
|
+
doUndo();
|
|
738
|
+
} else if (key === "z" && e.shiftKey || key === "y" && !e.shiftKey) {
|
|
739
|
+
e.preventDefault();
|
|
740
|
+
e.stopPropagation();
|
|
741
|
+
doRedo();
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
window.addEventListener("keydown", onKey, { capture: true });
|
|
745
|
+
return () => window.removeEventListener("keydown", onKey, { capture: true });
|
|
746
|
+
}, [doUndo, doRedo]);
|
|
672
747
|
const onBoardEvent = useCallback((ev) => {
|
|
673
748
|
const currentTool = toolRef.current;
|
|
674
749
|
if (currentTool === "point-on-curve" && ev.type === "click-curve" && ev.functionId && ev.x !== void 0) {
|
|
@@ -721,7 +796,8 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
721
796
|
tool: t,
|
|
722
797
|
showAxis: g.view.showAxis,
|
|
723
798
|
showGrid: g.view.showGrid,
|
|
724
|
-
canUndo: undoStackRef.current.length > 0
|
|
799
|
+
canUndo: undoStackRef.current.length > 0,
|
|
800
|
+
canRedo: redoStackRef.current.length > 0
|
|
725
801
|
});
|
|
726
802
|
},
|
|
727
803
|
setShowAxis: (b) => updateGraph((g) => ({ ...g, view: { ...g.view, showAxis: b } })),
|
|
@@ -730,19 +806,8 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
730
806
|
...g,
|
|
731
807
|
view: { ...g.view, xMin: -10, xMax: 10, yMin: -10, yMax: 10 }
|
|
732
808
|
})),
|
|
733
|
-
undo:
|
|
734
|
-
|
|
735
|
-
if (!prev) return;
|
|
736
|
-
graphRef.current = prev;
|
|
737
|
-
forceUpdate((n) => n + 1);
|
|
738
|
-
propsRef.current.onStateChange({
|
|
739
|
-
tool: toolRef.current,
|
|
740
|
-
showAxis: prev.view.showAxis,
|
|
741
|
-
showGrid: prev.view.showGrid,
|
|
742
|
-
canUndo: undoStackRef.current.length > 0
|
|
743
|
-
});
|
|
744
|
-
propsRef.current.onGraphChange?.(prev);
|
|
745
|
-
},
|
|
809
|
+
undo: doUndo,
|
|
810
|
+
redo: doRedo,
|
|
746
811
|
addFunction: (expr) => {
|
|
747
812
|
const g = graphRef.current;
|
|
748
813
|
if (g.functions.length >= MAX_FUNCTIONS) {
|
|
@@ -835,7 +900,7 @@ var GraphEditorPanel = forwardRef(function GraphEditorPanel2(props, ref) {
|
|
|
835
900
|
}),
|
|
836
901
|
// deps: updateGraph stable; errors changes when function errors change; setErrorsWithNotify stable
|
|
837
902
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
838
|
-
[updateGraph, errors, setErrorsWithNotify]
|
|
903
|
+
[updateGraph, errors, setErrorsWithNotify, doUndo, doRedo]
|
|
839
904
|
);
|
|
840
905
|
useEffect(() => {
|
|
841
906
|
if (!initialGraphNotifiedRef.current) {
|
|
@@ -962,7 +1027,8 @@ var INITIAL_GRAPH_STATE = {
|
|
|
962
1027
|
tool: "move",
|
|
963
1028
|
showAxis: true,
|
|
964
1029
|
showGrid: true,
|
|
965
|
-
canUndo: false
|
|
1030
|
+
canUndo: false,
|
|
1031
|
+
canRedo: false
|
|
966
1032
|
};
|
|
967
1033
|
var Graph2DStampHost = forwardRef(
|
|
968
1034
|
function Graph2DStampHost2({ api, editingElement, onClose, isDark }, ref) {
|
|
@@ -1022,6 +1088,8 @@ var Graph2DStampHost = forwardRef(
|
|
|
1022
1088
|
onResetView: () => panelRef.current?.resetView(),
|
|
1023
1089
|
onUndo: () => panelRef.current?.undo(),
|
|
1024
1090
|
canUndo: graphUIState.canUndo,
|
|
1091
|
+
onRedo: () => panelRef.current?.redo(),
|
|
1092
|
+
canRedo: graphUIState.canRedo,
|
|
1025
1093
|
onClose,
|
|
1026
1094
|
isDark,
|
|
1027
1095
|
isMobile,
|
|
@@ -1062,5 +1130,5 @@ var Graph2DStampHost = forwardRef(
|
|
|
1062
1130
|
);
|
|
1063
1131
|
|
|
1064
1132
|
export { Graph2DStampHost };
|
|
1065
|
-
//# sourceMappingURL=host-
|
|
1066
|
-
//# sourceMappingURL=host-
|
|
1133
|
+
//# sourceMappingURL=host-NKGV6RF2.mjs.map
|
|
1134
|
+
//# sourceMappingURL=host-NKGV6RF2.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stamps/graph-2d/editor/tools.ts","../src/stamps/graph-2d/editor/FunctionRow.tsx","../src/stamps/graph-2d/editor/SliderRow.tsx","../src/stamps/graph-2d/colors.ts","../src/stamps/graph-2d/editor/AlgebraView.tsx","../src/stamps/graph-2d/editor/LeftPanel.tsx","../src/stamps/graph-2d/editor/MiniBoard.tsx","../src/stamps/graph-2d/editor/EditorPanel.tsx","../src/stamps/graph-2d/host.tsx"],"names":["jsxs","jsx","useEffect","GraphEditorPanel","useRef","useState","forwardRef","Graph2DStampHost","useCallback","useImperativeHandle","Fragment"],"mappings":"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","file":"host-NKGV6RF2.mjs","sourcesContent":["// src/stamps/graph-2d/editor/tools.ts\nexport type GraphTool = 'move' | 'point-on-curve' | 'intersect' | 'tangent';\n\nexport interface GraphToolMeta {\n id: GraphTool;\n label: string;\n title: string;\n shortcutKey?: string;\n}\n\nexport const GRAPH_TOOLS: GraphToolMeta[] = [\n { id: 'move', label: 'Di chuyển', title: 'Di chuyển / chọn' },\n { id: 'point-on-curve', label: 'Điểm trên curve', title: 'Tạo điểm cố định trên đồ thị' },\n { id: 'intersect', label: 'Giao điểm', title: 'Đánh dấu giao điểm 2 đồ thị' },\n { id: 'tangent', label: 'Tiếp tuyến', title: 'Vẽ tiếp tuyến tại điểm trên đồ thị' },\n];\n","'use client';\n\nimport { useEffect, useState, type KeyboardEvent, type FocusEvent } from 'react';\n\nexport interface FunctionRowProps {\n id: string;\n name: string;\n expression: string;\n color: string;\n visible: boolean;\n error: string | null;\n onExpressionCommit: (expr: string) => void;\n onToggleVisible: () => void;\n onRemove: () => void;\n}\n\nexport function FunctionRow(props: FunctionRowProps) {\n const { id, name, expression, color, visible, error } = props;\n const [draft, setDraft] = useState(expression);\n\n useEffect(() => {\n setDraft(expression);\n }, [expression]);\n\n const commit = () => {\n if (draft !== expression) props.onExpressionCommit(draft);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n commit();\n (e.target as HTMLInputElement).blur();\n } else if (e.key === 'Escape') {\n setDraft(expression);\n (e.target as HTMLInputElement).blur();\n }\n };\n\n const handleBlur = (_: FocusEvent<HTMLInputElement>) => commit();\n\n return (\n <div className={`graph-function-row${error ? ' is-error' : ''}`} data-testid={`graph-function-row-${id}`}>\n <span\n className=\"graph-function-color\"\n style={{ backgroundColor: color }}\n aria-hidden=\"true\"\n />\n <span className=\"graph-function-name\" data-testid={`graph-function-name-${id}`}>\n {name}(x) =\n </span>\n <input\n aria-label=\"Biểu thức\"\n className=\"graph-function-input\"\n type=\"text\"\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n spellCheck={false}\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n />\n <button\n type=\"button\"\n aria-label=\"Ẩn/hiện đồ thị\"\n className={`graph-function-eye${visible ? '' : ' is-hidden'}`}\n onClick={props.onToggleVisible}\n >\n {visible ? '👁' : '⊘'}\n </button>\n <button\n type=\"button\"\n aria-label=\"Xoá đồ thị\"\n className=\"graph-function-remove\"\n onClick={props.onRemove}\n >\n ✕\n </button>\n {error ? <div className=\"graph-function-error\">{error}</div> : null}\n </div>\n );\n}\n","'use client';\n\nexport interface SliderRowProps {\n name: string;\n value: number;\n min: number;\n max: number;\n step: number;\n onChange: (value: number) => void;\n onRemove: () => void;\n onRangeChange: (min: number, max: number, step: number) => void;\n}\n\nexport function SliderRow(props: SliderRowProps) {\n const { name, value, min, max, step } = props;\n return (\n <div className=\"graph-slider-row\" data-testid={`graph-slider-row-${name}`}>\n <div className=\"graph-slider-header\">\n <span className=\"graph-slider-name\">{name}</span>\n <span className=\"graph-slider-value\">= {value.toFixed(2)}</span>\n <button\n type=\"button\"\n aria-label={`Xoá tham số ${name}`}\n className=\"graph-slider-remove\"\n onClick={props.onRemove}\n >\n ✕\n </button>\n </div>\n <input\n type=\"range\"\n aria-label={`Slider ${name}`}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={(e) => props.onChange(parseFloat(e.target.value))}\n className=\"graph-slider-input\"\n />\n <div className=\"graph-slider-range\">\n <span>{min}</span>\n <span>{max}</span>\n </div>\n </div>\n );\n}\n","export const GRAPH_PALETTE = [\n '#2563eb', // blue\n '#dc2626', // red\n '#16a34a', // green\n '#9333ea', // purple\n '#ea580c', // orange\n '#0891b2', // cyan\n '#db2777', // pink\n '#65a30d', // lime\n] as const;\n\nexport const FUNCTION_NAMES = ['f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'] as const;\n\nexport const MAX_FUNCTIONS = 8;\nexport const MAX_PARAMETERS = 8;\n\nexport function nextColor(usedColors: readonly string[]): string {\n for (const c of GRAPH_PALETTE) {\n if (!usedColors.includes(c)) return c;\n }\n return GRAPH_PALETTE[usedColors.length % GRAPH_PALETTE.length];\n}\n\nexport function nextFunctionName(usedNames: readonly string[]): string {\n for (const n of FUNCTION_NAMES) {\n if (!usedNames.includes(n)) return n;\n }\n return FUNCTION_NAMES[usedNames.length % FUNCTION_NAMES.length];\n}\n","'use client';\n\nimport { FunctionRow } from './FunctionRow';\nimport { SliderRow } from './SliderRow';\nimport type { SerializedGraph } from '../serialize';\nimport { MAX_FUNCTIONS } from '../colors';\n\nexport interface AlgebraViewProps {\n graph: SerializedGraph;\n errors: Record<string, string | null>;\n onAddFunctionDraft: () => void;\n onCommitFunctionExpr: (id: string, expr: string) => void;\n onToggleFunctionVisible: (id: string) => void;\n onRemoveFunction: (id: string) => void;\n onParameterChange: (name: string, value: number) => void;\n onParameterRangeChange: (name: string, min: number, max: number, step: number) => void;\n onRemoveParameter: (name: string) => void;\n}\n\nexport function AlgebraView(props: AlgebraViewProps) {\n const { graph, errors } = props;\n const atMax = graph.functions.length >= MAX_FUNCTIONS;\n\n return (\n <div className=\"graph-algebra-view\">\n <div className=\"graph-algebra-section\">\n {graph.functions.map((f) => (\n <FunctionRow\n key={f.id}\n id={f.id}\n name={f.name}\n expression={f.expression}\n color={f.color}\n visible={f.visible}\n error={errors[f.id] ?? null}\n onExpressionCommit={(expr) => props.onCommitFunctionExpr(f.id, expr)}\n onToggleVisible={() => props.onToggleFunctionVisible(f.id)}\n onRemove={() => props.onRemoveFunction(f.id)}\n />\n ))}\n <button\n type=\"button\"\n aria-label=\"Thêm hàm số\"\n className=\"graph-algebra-add\"\n onClick={props.onAddFunctionDraft}\n disabled={atMax}\n >\n + Thêm hàm\n </button>\n </div>\n\n {graph.parameters.length > 0 ? (\n <div className=\"graph-algebra-section graph-algebra-parameters\">\n {graph.parameters.map((p) => (\n <SliderRow\n key={p.name}\n name={p.name}\n value={p.value}\n min={p.min}\n max={p.max}\n step={p.step}\n onChange={(v) => props.onParameterChange(p.name, v)}\n onRangeChange={(min, max, step) =>\n props.onParameterRangeChange(p.name, min, max, step)\n }\n onRemove={() => props.onRemoveParameter(p.name)}\n />\n ))}\n </div>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport { GRAPH_TOOLS, type GraphTool } from './tools';\nimport { AlgebraView, type AlgebraViewProps } from './AlgebraView';\n\n// ---------- Icons ----------\n\nconst GraphIconHeader = (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 21 V3\" />\n <path d=\"M3 21 H21\" />\n <path d=\"M5 19 C8 5, 14 5, 19 17\" />\n </svg>\n);\n\nfunction CloseIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n );\n}\n\nfunction UndoIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M3 10 L8 5 L8 8 L15 8 A5 5 0 0 1 20 13 L20 16\" />\n <path d=\"M3 10 L8 15 L8 12\" />\n </svg>\n );\n}\n\nfunction RedoIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 10 L16 5 L16 8 L9 8 A5 5 0 0 0 4 13 L4 16\" />\n <path d=\"M21 10 L16 15 L16 12\" />\n </svg>\n );\n}\n\nfunction ResetViewIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\" />\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n </svg>\n );\n}\n\n// Tool icons\nfunction MoveIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 4 L9 4 L9 9 L4 9 Z\" />\n </svg>\n );\n}\nfunction PointOnCurveIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 17 C7 8, 14 8, 21 14\" />\n <circle cx=\"12\" cy=\"11\" r=\"2.2\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\nfunction IntersectIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 17 C8 5, 14 5, 21 17\" />\n <path d=\"M3 5 C8 17, 14 17, 21 5\" />\n <circle cx=\"12\" cy=\"11\" r=\"1.6\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\nfunction TangentIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 17 C8 7, 14 7, 21 16\" />\n <line x1=\"4\" y1=\"14\" x2=\"20\" y2=\"6\" />\n <circle cx=\"12\" cy=\"10\" r=\"1.8\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n}\n\nconst TOOL_ICONS: Record<GraphTool, React.ReactNode> = {\n move: <MoveIcon />,\n 'point-on-curve': <PointOnCurveIcon />,\n intersect: <IntersectIcon />,\n tangent: <TangentIcon />,\n};\n\n// ---------- Props ----------\n\nexport interface GraphLeftPanelProps extends AlgebraViewProps {\n activeTool: GraphTool;\n onToolChange: (t: GraphTool) => void;\n showAxis: boolean;\n showGrid: boolean;\n onShowAxisChange: (b: boolean) => void;\n onShowGridChange: (b: boolean) => void;\n onResetView: () => void;\n onUndo: () => void;\n canUndo: boolean;\n onRedo: () => void;\n canRedo: boolean;\n onClose: () => void;\n isDark: boolean;\n isMobile: boolean;\n drawerOpen: boolean;\n onDrawerClose: () => void;\n}\n\n// ---------- Section ----------\n\nfunction Section({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <section>\n <h4 className=\"mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-slate-500\">\n {label}\n </h4>\n {children}\n </section>\n );\n}\n\n// ---------- Body ----------\n\nfunction PanelBody(props: GraphLeftPanelProps) {\n return (\n <>\n <Section label=\"Bố cục\">\n <div className=\"flex items-center gap-2 flex-wrap text-[11px] text-slate-700\">\n <label className=\"inline-flex select-none items-center gap-1.5\">\n <input\n type=\"checkbox\"\n checked={props.showAxis}\n onChange={(e) => props.onShowAxisChange(e.target.checked)}\n data-testid=\"toggle-axis\"\n />\n Trục\n </label>\n <label className=\"inline-flex select-none items-center gap-1.5\">\n <input\n type=\"checkbox\"\n checked={props.showGrid}\n onChange={(e) => props.onShowGridChange(e.target.checked)}\n data-testid=\"toggle-grid\"\n />\n Lưới\n </label>\n <button\n type=\"button\"\n onClick={props.onResetView}\n title=\"Đặt lại tầm nhìn\"\n aria-label=\"Đặt lại tầm nhìn\"\n className=\"ml-auto inline-flex items-center justify-center rounded p-1 text-slate-600 transition hover:bg-slate-100 hover:text-slate-900\"\n >\n <ResetViewIcon />\n </button>\n <button\n type=\"button\"\n onClick={props.onUndo}\n disabled={!props.canUndo}\n title=\"Hoàn tác (Ctrl/Cmd+Z)\"\n aria-label=\"Hoàn tác\"\n data-testid=\"undo-btn\"\n 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\"\n >\n <UndoIcon />\n </button>\n <button\n type=\"button\"\n onClick={props.onRedo}\n disabled={!props.canRedo}\n title=\"Làm lại (Ctrl/Cmd+Shift+Z)\"\n aria-label=\"Làm lại\"\n data-testid=\"redo-btn\"\n 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\"\n >\n <RedoIcon />\n </button>\n </div>\n </Section>\n\n <Section label=\"Công cụ\">\n <div className=\"grid grid-cols-4 gap-1\">\n {GRAPH_TOOLS.map((t) => {\n const isActive = props.activeTool === t.id;\n return (\n <button\n key={t.id}\n type=\"button\"\n aria-label={t.title}\n title={t.title}\n aria-pressed={isActive}\n onClick={() => props.onToolChange(t.id)}\n data-testid={`graph-tool-${t.id}`}\n className={[\n 'flex h-8 items-center justify-center rounded-md transition',\n isActive\n ? 'bg-orange-600 text-white shadow-sm'\n : 'text-slate-700 hover:bg-slate-100 hover:text-slate-900',\n ].join(' ')}\n >\n {TOOL_ICONS[t.id]}\n </button>\n );\n })}\n </div>\n </Section>\n\n <Section label=\"Hàm số\">\n <AlgebraView\n graph={props.graph}\n errors={props.errors}\n onAddFunctionDraft={props.onAddFunctionDraft}\n onCommitFunctionExpr={props.onCommitFunctionExpr}\n onToggleFunctionVisible={props.onToggleFunctionVisible}\n onRemoveFunction={props.onRemoveFunction}\n onParameterChange={props.onParameterChange}\n onParameterRangeChange={props.onParameterRangeChange}\n onRemoveParameter={props.onRemoveParameter}\n />\n </Section>\n </>\n );\n}\n\n// ---------- Public ----------\n\nexport function GraphLeftPanel(props: GraphLeftPanelProps) {\n const { isMobile, drawerOpen, isDark, onClose, onDrawerClose } = props;\n if (isMobile && !drawerOpen) return null;\n const handleClose = isMobile ? onDrawerClose : onClose;\n return (\n <aside\n role=\"complementary\"\n aria-label=\"Đồ thị 2D\"\n data-testid=\"graph-left-panel\"\n data-stamp-area=\"true\"\n className={[\n isDark ? 'theme--dark ' : '',\n isMobile\n ? 'fixed inset-y-0 left-0 z-50 flex w-72 max-w-[85vw] flex-col bg-white shadow-2xl animate-in slide-in-from-left duration-200'\n : 'absolute left-0 top-0 z-30 flex h-full w-60 flex-col border-r border-slate-200 bg-white shadow-md animate-in slide-in-from-left duration-200',\n ].join(' ')}\n >\n <header className=\"flex items-center justify-between border-b border-slate-200 bg-gradient-to-r from-slate-50 to-white px-3 py-2\">\n <h3 className=\"flex items-center gap-2 text-sm font-semibold text-slate-800\">\n <span className=\"text-base leading-none\">{GraphIconHeader}</span>\n Đồ thị 2D\n </h3>\n <button\n onClick={handleClose}\n aria-label=\"Đóng\"\n className=\"rounded p-1 text-slate-500 transition hover:bg-slate-100 hover:text-slate-800\"\n >\n <CloseIcon />\n </button>\n </header>\n <div className=\"min-h-0 flex-1 overflow-y-auto p-3 space-y-4\">\n <PanelBody {...props} />\n </div>\n </aside>\n );\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\nimport type { SerializedGraph } from '../serialize';\nimport { compile } from '../parser';\nimport { graphPaletteFor } from './theme';\nimport type { GraphTool } from './tools';\nimport { numericalDerivative } from './handlers';\n\nexport interface BoardEvent {\n type: 'click-curve' | 'click-empty' | 'view-change';\n functionId?: string;\n x?: number;\n y?: number;\n view?: SerializedGraph['view'];\n}\n\nexport interface MiniBoardProps {\n graph: SerializedGraph;\n activeTool: GraphTool;\n isDark: boolean;\n onBoardEvent: (e: BoardEvent) => void;\n}\n\ninterface CurveRef {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n obj: any;\n expression: string;\n color: string;\n visible: boolean;\n paramSignature: string;\n}\n\nexport function MiniBoard({ graph, activeTool, isDark, onBoardEvent }: MiniBoardProps) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const boardRef = useRef<any>(null);\n const curvesRef = useRef<Map<string, CurveRef>>(new Map());\n const palette = graphPaletteFor(isDark);\n\n // Init board on mount\n useEffect(() => {\n let cancelled = false;\n let createdBoard: unknown = null;\n const containerEl = containerRef.current;\n if (!containerEl) return;\n const containerId = `jxg_graph2d_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n containerEl.id = containerId;\n\n (async () => {\n const JXG = (await import('jsxgraph')).default;\n if (cancelled) return;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const opts = (JXG as any).Options;\n if (opts) {\n opts.text = opts.text || {};\n opts.text.display = 'internal';\n opts.label = opts.label || {};\n opts.label.display = 'internal';\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const board = (JXG as any).JSXGraph.initBoard(containerId, {\n boundingbox: [graph.view.xMin, graph.view.yMax, graph.view.xMax, graph.view.yMin],\n axis: graph.view.showAxis,\n grid: graph.view.showGrid,\n showCopyright: false,\n showNavigation: true,\n pan: { enabled: true, needShift: false },\n zoom: { wheel: true, needShift: false },\n keepAspectRatio: false,\n });\n boardRef.current = board;\n createdBoard = board;\n syncObjects(board, graph, curvesRef.current);\n board.on('boundingbox', () => {\n const bb = board.getBoundingBox();\n onBoardEvent({\n type: 'view-change',\n view: {\n xMin: bb[0],\n xMax: bb[2],\n yMax: bb[1],\n yMin: bb[3],\n showAxis: graph.view.showAxis,\n showGrid: graph.view.showGrid,\n },\n });\n });\n board.on('down', (ev: { clientX?: number; clientY?: number }) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const usrCoords = (board as any).getUsrCoordsOfMouse?.(ev as unknown as MouseEvent);\n const x = usrCoords?.[0] ?? 0;\n const y = usrCoords?.[1] ?? 0;\n // Tìm curve dưới chuột (best-effort)\n let functionId: string | undefined;\n for (const [id, ref] of curvesRef.current) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const obj = ref.obj as any;\n if (obj?.hasPoint && obj.hasPoint(ev.clientX ?? 0, ev.clientY ?? 0)) {\n functionId = id;\n break;\n }\n }\n if (functionId) onBoardEvent({ type: 'click-curve', functionId, x, y });\n else onBoardEvent({ type: 'click-empty', x, y });\n });\n })().catch((err) => console.error('MiniBoard init failed:', err));\n\n return () => {\n cancelled = true;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (createdBoard) (require('jsxgraph') as any).default.JSXGraph.freeBoard(createdBoard);\n } catch { /* ignore */ }\n boardRef.current = null;\n curvesRef.current.clear();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Sync objects khi graph thay đổi\n useEffect(() => {\n if (!boardRef.current) return;\n syncObjects(boardRef.current, graph, curvesRef.current);\n }, [graph]);\n\n // Suppress unused palette warning - consumed by syncObjects via isDark\n void palette;\n\n // Cursor visual feedback theo activeTool\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n el.style.cursor = activeTool === 'move' ? '' : 'crosshair';\n }, [activeTool]);\n\n return (\n <div\n ref={containerRef}\n className=\"graph-miniboard\"\n style={{ width: '100%', height: '100%', minHeight: '300px' }}\n data-testid=\"graph-miniboard\"\n />\n );\n}\n\nfunction paramSig(graph: SerializedGraph): string {\n return graph.parameters.map((p) => `${p.name}=${p.value}`).join(',');\n}\n\nfunction syncObjects(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n board: any,\n graph: SerializedGraph,\n curves: Map<string, CurveRef>,\n): void {\n const sig = paramSig(graph);\n const paramMap: Record<string, number> = {};\n for (const p of graph.parameters) paramMap[p.name] = p.value;\n\n const wantedIds = new Set(graph.functions.map((f) => f.id));\n // Remove stale curves\n for (const [id, ref] of curves) {\n if (!wantedIds.has(id)) {\n try { board.removeObject(ref.obj); } catch { /* ignore */ }\n curves.delete(id);\n }\n }\n for (const f of graph.functions) {\n const existing = curves.get(f.id);\n const needsRecreate =\n !existing ||\n existing.expression !== f.expression ||\n existing.color !== f.color ||\n existing.visible !== f.visible ||\n existing.paramSignature !== sig;\n if (!needsRecreate) continue;\n if (existing) {\n try { board.removeObject(existing.obj); } catch { /* ignore */ }\n }\n if (!f.visible) {\n curves.delete(f.id);\n continue;\n }\n const compiled = compile(f.expression, paramMap);\n if (typeof compiled !== 'function') continue;\n const domain = f.domain ?? { min: graph.view.xMin, max: graph.view.xMax };\n const obj = board.create('functiongraph', [compiled, domain.min, domain.max], {\n strokeColor: f.color,\n strokeWidth: 2,\n name: f.name,\n withLabel: false,\n highlight: false,\n });\n curves.set(f.id, {\n obj,\n expression: f.expression,\n color: f.color,\n visible: f.visible,\n paramSignature: sig,\n });\n }\n\n // Render points\n for (const point of graph.points) {\n const fn = graph.functions.find((f) => f.id === point.functionId);\n if (!fn || !fn.visible) continue;\n const compiled = compile(fn.expression, paramMap);\n if (typeof compiled !== 'function') continue;\n const y = compiled(point.x);\n board.create('point', [point.x, y], {\n name: point.label ?? '',\n size: 3,\n fillColor: fn.color,\n strokeColor: fn.color,\n withLabel: !!point.label,\n });\n }\n\n // Render intersections\n for (const inter of graph.intersections) {\n const fa = graph.functions.find((f) => f.id === inter.functionIdA);\n const fb = graph.functions.find((f) => f.id === inter.functionIdB);\n if (!fa || !fb || !fa.visible || !fb.visible) continue;\n const cfa = compile(fa.expression, paramMap);\n const cfb = compile(fb.expression, paramMap);\n if (typeof cfa !== 'function' || typeof cfb !== 'function') continue;\n const roots = scanRoots((x: number) => cfa(x) - cfb(x), graph.view.xMin, graph.view.xMax);\n for (const x of roots) {\n board.create('point', [x, cfa(x)], {\n size: 3,\n fillColor: '#000',\n strokeColor: '#000',\n });\n }\n }\n\n // Render tangents\n for (const tan of graph.tangents) {\n const pt = graph.points.find((p) => p.id === tan.pointId);\n if (!pt) continue;\n const fn = graph.functions.find((f) => f.id === pt.functionId);\n if (!fn || !fn.visible) continue;\n const slope = numericalDerivative(fn.expression, paramMap, pt.x);\n const cfn = compile(fn.expression, paramMap);\n if (typeof cfn !== 'function' || !Number.isFinite(slope)) continue;\n const y0 = cfn(pt.x);\n const x1 = graph.view.xMin;\n const x2 = graph.view.xMax;\n board.create(\n 'line',\n [\n [x1, slope * (x1 - pt.x) + y0],\n [x2, slope * (x2 - pt.x) + y0],\n ],\n {\n strokeColor: fn.color,\n strokeWidth: 1,\n dash: 2,\n straightFirst: false,\n straightLast: false,\n },\n );\n }\n\n board.update();\n}\n\nfunction scanRoots(\n fn: (x: number) => number,\n xMin: number,\n xMax: number,\n samples = 200,\n): number[] {\n const roots: number[] = [];\n const step = (xMax - xMin) / samples;\n let prevX = xMin;\n let prevY = fn(prevX);\n for (let i = 1; i <= samples; i++) {\n const x = xMin + i * step;\n const y = fn(x);\n if (Number.isFinite(prevY) && Number.isFinite(y) && prevY * y < 0) {\n // bisection\n let a = prevX;\n let b = x;\n let ya = prevY;\n for (let j = 0; j < 30; j++) {\n const m = (a + b) / 2;\n const ym = fn(m);\n if (Math.abs(ym) < 1e-6) {\n a = b = m;\n break;\n }\n if (ya * ym < 0) {\n b = m;\n } else {\n a = m;\n ya = ym;\n }\n }\n roots.push((a + b) / 2);\n }\n prevX = x;\n prevY = y;\n }\n return roots;\n}\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type Ref,\n} from 'react';\nimport { MiniBoard } from './MiniBoard';\nimport type { BoardEvent } from './MiniBoard';\nimport {\n EMPTY_GRAPH,\n stringifySerializedGraph,\n type SerializedFunction,\n type SerializedGraph,\n type SerializedParameter,\n} from '../serialize';\nimport { validate } from '../parser';\nimport { renderGraph2dSvgFromState } from '../render';\nimport { nextColor, nextFunctionName, MAX_FUNCTIONS, MAX_PARAMETERS } from '../colors';\nimport type { GraphTool } from './tools';\nimport { addPointOnCurve, addIntersection } from './handlers';\n\nexport interface GraphState {\n tool: GraphTool;\n showAxis: boolean;\n showGrid: boolean;\n canUndo: boolean;\n canRedo: boolean;\n}\n\nexport interface GraphEditorPanelHandle {\n insert(): boolean;\n hasContent(): boolean;\n setTool(t: GraphTool): void;\n setShowAxis(b: boolean): void;\n setShowGrid(b: boolean): void;\n resetView(): void;\n undo(): void;\n redo(): void;\n\n addFunction(expr: string): { ok: true; id: string } | { ok: false; error: string };\n commitFunctionExpression(id: string, expr: string): void;\n toggleFunctionVisible(id: string): void;\n removeFunction(id: string): void;\n\n setParameter(name: string, value: number): void;\n setParameterRange(name: string, min: number, max: number, step: number): void;\n removeParameter(name: string): void;\n\n getGraph(): SerializedGraph;\n getErrors(): Record<string, string | null>;\n}\n\nexport interface GraphEditorPanelProps {\n initialState: SerializedGraph | null;\n onInsert: (jsonState: string, svgString: string) => void;\n onClose: () => void;\n onStateChange: (state: GraphState) => void;\n withLeftPanel: boolean;\n isDark: boolean;\n isMobile: boolean;\n onOpenDrawer: () => void;\n // Lift state up so Host can render AlgebraView with current graph + errors\n onGraphChange?: (g: SerializedGraph) => void;\n onErrorsChange?: (errors: Record<string, string | null>) => void;\n}\n\nexport const GraphEditorPanel = forwardRef(function GraphEditorPanel(\n props: GraphEditorPanelProps,\n ref: Ref<GraphEditorPanelHandle>,\n) {\n // graphRef is the single source of truth for imperative reads (hasContent, getGraph, etc.)\n // setGraph triggers re-render to sync JSXGraph MiniBoard\n const initialGraph = props.initialState ?? EMPTY_GRAPH;\n const graphRef = useRef<SerializedGraph>(initialGraph);\n const [, forceUpdate] = useState(0);\n\n const [errors, setErrors] = useState<Record<string, string | null>>({});\n const [tool, setToolState] = useState<GraphTool>('move');\n const undoStackRef = useRef<SerializedGraph[]>([]);\n const redoStackRef = useRef<SerializedGraph[]>([]);\n const idCounterRef = useRef(1);\n\n const toolRef = useRef<GraphTool>(tool);\n toolRef.current = tool;\n\n const intersectFirstRef = useRef<string | null>(null);\n\n const propsRef = useRef(props);\n propsRef.current = props;\n\n // Notify initial graph state to Host on mount\n const initialGraphNotifiedRef = useRef(false);\n\n const pushUndo = useCallback((g: SerializedGraph) => {\n undoStackRef.current.push(g);\n if (undoStackRef.current.length > 30) undoStackRef.current.shift();\n // Bất kỳ thao tác mới nào cũng làm rớt nhánh redo\n redoStackRef.current = [];\n }, []);\n\n const setErrorsWithNotify = useCallback(\n (updater: (prev: Record<string, string | null>) => Record<string, string | null>) => {\n setErrors((prev) => {\n const next = updater(prev);\n propsRef.current.onErrorsChange?.(next);\n return next;\n });\n },\n [],\n );\n\n const notifyStateChange = useCallback((g: SerializedGraph, t: GraphTool) => {\n propsRef.current.onStateChange({\n tool: t,\n showAxis: g.view.showAxis,\n showGrid: g.view.showGrid,\n canUndo: undoStackRef.current.length > 0,\n canRedo: redoStackRef.current.length > 0,\n });\n }, []);\n\n const updateGraph = useCallback(\n (mutator: (prev: SerializedGraph) => SerializedGraph) => {\n const prev = graphRef.current;\n pushUndo(prev);\n const next = mutator(prev);\n graphRef.current = next;\n notifyStateChange(next, toolRef.current);\n forceUpdate((n) => n + 1);\n propsRef.current.onGraphChange?.(next);\n },\n [pushUndo, notifyStateChange],\n );\n\n const doUndo = useCallback(() => {\n const prev = undoStackRef.current.pop();\n if (!prev) return;\n redoStackRef.current.push(graphRef.current);\n if (redoStackRef.current.length > 30) redoStackRef.current.shift();\n graphRef.current = prev;\n forceUpdate((n) => n + 1);\n propsRef.current.onStateChange({\n tool: toolRef.current,\n showAxis: prev.view.showAxis,\n showGrid: prev.view.showGrid,\n canUndo: undoStackRef.current.length > 0,\n canRedo: redoStackRef.current.length > 0,\n });\n propsRef.current.onGraphChange?.(prev);\n }, []);\n\n const doRedo = useCallback(() => {\n const next = redoStackRef.current.pop();\n if (!next) return;\n undoStackRef.current.push(graphRef.current);\n if (undoStackRef.current.length > 30) undoStackRef.current.shift();\n graphRef.current = next;\n forceUpdate((n) => n + 1);\n propsRef.current.onStateChange({\n tool: toolRef.current,\n showAxis: next.view.showAxis,\n showGrid: next.view.showGrid,\n canUndo: undoStackRef.current.length > 0,\n canRedo: redoStackRef.current.length > 0,\n });\n propsRef.current.onGraphChange?.(next);\n }, []);\n\n // Global keyboard shortcuts: Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, Ctrl+Y\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const ae = document.activeElement as HTMLElement | null;\n const inField = !!(\n ae &&\n (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA' || ae.isContentEditable)\n );\n if (inField) return;\n if (!(e.metaKey || e.ctrlKey)) return;\n const key = e.key.toLowerCase();\n if (key === 'z' && !e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n doUndo();\n } else if ((key === 'z' && e.shiftKey) || (key === 'y' && !e.shiftKey)) {\n e.preventDefault();\n e.stopPropagation();\n doRedo();\n }\n };\n window.addEventListener('keydown', onKey, { capture: true });\n return () => window.removeEventListener('keydown', onKey, { capture: true });\n }, [doUndo, doRedo]);\n\n const onBoardEvent = useCallback((ev: BoardEvent) => {\n const currentTool = toolRef.current;\n if (currentTool === 'point-on-curve' && ev.type === 'click-curve' && ev.functionId && ev.x !== undefined) {\n updateGraph((g) =>\n addPointOnCurve(\n g,\n { x: ev.x!, y: ev.y ?? 0, functionId: ev.functionId },\n () => `p${idCounterRef.current++}`,\n ),\n );\n setToolState('move');\n } else if (currentTool === 'intersect' && ev.type === 'click-curve' && ev.functionId) {\n if (!intersectFirstRef.current) {\n intersectFirstRef.current = ev.functionId;\n } else {\n const a = intersectFirstRef.current;\n const b = ev.functionId;\n intersectFirstRef.current = null;\n updateGraph((g) =>\n addIntersection(g, a, b, () => `i${idCounterRef.current++}`),\n );\n setToolState('move');\n }\n } else if (currentTool === 'tangent' && ev.type === 'click-curve' && ev.functionId && ev.x !== undefined) {\n const pointId = `p${idCounterRef.current++}`;\n const tangentId = `t${idCounterRef.current++}`;\n updateGraph((g) => ({\n ...g,\n points: [...g.points, { id: pointId, functionId: ev.functionId!, x: ev.x! }],\n tangents: [...g.tangents, { id: tangentId, pointId }],\n }));\n setToolState('move');\n }\n }, [updateGraph]);\n\n useImperativeHandle(\n ref,\n () => ({\n insert: () => {\n const g = graphRef.current;\n if (g.functions.length === 0) return false;\n const jsonState = stringifySerializedGraph(g);\n renderGraph2dSvgFromState(jsonState)\n .then((svg) => propsRef.current.onInsert(jsonState, svg))\n .catch((err) => console.error('Graph2D insert render failed:', err));\n return true;\n },\n\n hasContent: () => graphRef.current.functions.length > 0,\n\n setTool: (t: GraphTool) => {\n setToolState(t);\n const g = graphRef.current;\n propsRef.current.onStateChange({\n tool: t,\n showAxis: g.view.showAxis,\n showGrid: g.view.showGrid,\n canUndo: undoStackRef.current.length > 0,\n canRedo: redoStackRef.current.length > 0,\n });\n },\n\n setShowAxis: (b: boolean) =>\n updateGraph((g) => ({ ...g, view: { ...g.view, showAxis: b } })),\n\n setShowGrid: (b: boolean) =>\n updateGraph((g) => ({ ...g, view: { ...g.view, showGrid: b } })),\n\n resetView: () =>\n updateGraph((g) => ({\n ...g,\n view: { ...g.view, xMin: -10, xMax: 10, yMin: -10, yMax: 10 },\n })),\n\n undo: doUndo,\n redo: doRedo,\n\n addFunction: (expr: string) => {\n const g = graphRef.current;\n if (g.functions.length >= MAX_FUNCTIONS) {\n return { ok: false as const, error: `Tối đa ${MAX_FUNCTIONS} hàm` };\n }\n const v = validate(expr);\n if (!v.ok) return { ok: false as const, error: v.error ?? 'Invalid' };\n\n const id = `f${idCounterRef.current++}`;\n const usedNames = g.functions.map((f) => f.name);\n const usedColors = g.functions.map((f) => f.color);\n const newFn: SerializedFunction = {\n id,\n name: nextFunctionName(usedNames),\n expression: expr,\n color: nextColor(usedColors),\n visible: true,\n };\n\n const usedParamNames = new Set(g.parameters.map((p) => p.name));\n const newParams: SerializedParameter[] = [];\n for (const varName of v.freeVars) {\n if (usedParamNames.has(varName)) continue;\n if (g.parameters.length + newParams.length >= MAX_PARAMETERS) break;\n newParams.push({ name: varName, value: 1, min: -5, max: 5, step: 0.1 });\n }\n\n updateGraph((prev) => ({\n ...prev,\n functions: [...prev.functions, newFn],\n parameters: [...prev.parameters, ...newParams],\n }));\n setErrorsWithNotify((e) => ({ ...e, [id]: null }));\n return { ok: true as const, id };\n },\n\n commitFunctionExpression: (id: string, expr: string) => {\n const g = graphRef.current;\n const v = validate(expr);\n if (!v.ok) {\n setErrorsWithNotify((e) => ({ ...e, [id]: v.error ?? 'Invalid' }));\n return;\n }\n const usedParamNames = new Set(g.parameters.map((p) => p.name));\n const newParams: SerializedParameter[] = [];\n for (const varName of v.freeVars) {\n if (usedParamNames.has(varName)) continue;\n if (g.parameters.length + newParams.length >= MAX_PARAMETERS) break;\n newParams.push({ name: varName, value: 1, min: -5, max: 5, step: 0.1 });\n }\n updateGraph((prev) => ({\n ...prev,\n functions: prev.functions.map((f) =>\n f.id === id ? { ...f, expression: expr } : f,\n ),\n parameters: [...prev.parameters, ...newParams],\n }));\n setErrorsWithNotify((e) => ({ ...e, [id]: null }));\n },\n\n toggleFunctionVisible: (id: string) =>\n updateGraph((g) => ({\n ...g,\n functions: g.functions.map((f) =>\n f.id === id ? { ...f, visible: !f.visible } : f,\n ),\n })),\n\n removeFunction: (id: string) =>\n updateGraph((g) => ({\n ...g,\n functions: g.functions.filter((f) => f.id !== id),\n })),\n\n // setParameter does NOT push undo — would flood the stack (slider drag)\n setParameter: (name: string, value: number) => {\n const next = {\n ...graphRef.current,\n parameters: graphRef.current.parameters.map((p) =>\n p.name === name ? { ...p, value } : p,\n ),\n };\n graphRef.current = next;\n forceUpdate((n) => n + 1);\n propsRef.current.onGraphChange?.(next);\n },\n\n setParameterRange: (name: string, min: number, max: number, step: number) =>\n updateGraph((g) => ({\n ...g,\n parameters: g.parameters.map((p) =>\n p.name === name\n ? { ...p, min, max, step, value: Math.min(max, Math.max(min, p.value)) }\n : p,\n ),\n })),\n\n removeParameter: (name: string) =>\n updateGraph((g) => ({\n ...g,\n parameters: g.parameters.filter((p) => p.name !== name),\n })),\n\n getGraph: () => graphRef.current,\n getErrors: () => errors,\n }),\n // deps: updateGraph stable; errors changes when function errors change; setErrorsWithNotify stable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [updateGraph, errors, setErrorsWithNotify, doUndo, doRedo],\n );\n\n // Notify Host of initial graph on mount (so AlgebraView renders correctly for re-edit)\n useEffect(() => {\n if (!initialGraphNotifiedRef.current) {\n initialGraphNotifiedRef.current = true;\n propsRef.current.onGraphChange?.(graphRef.current);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const graph = graphRef.current;\n const hasContent = graph.functions.length > 0;\n\n const handleInsert = () => {\n const g = graphRef.current;\n if (g.functions.length === 0) return;\n const jsonState = stringifySerializedGraph(g);\n renderGraph2dSvgFromState(jsonState)\n .then((svg) => propsRef.current.onInsert(jsonState, svg))\n .catch((err) => console.error('Graph2D insert render failed:', err));\n };\n\n const { isMobile, isDark, withLeftPanel } = props;\n const wrapperStyle: CSSProperties = isMobile\n ? { position: 'fixed', inset: 0, zIndex: 40 }\n : {\n position: 'absolute',\n top: '50%',\n left: withLeftPanel ? 'calc(50% + 120px)' : '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 40,\n };\n\n return (\n <div\n role=\"dialog\"\n aria-label=\"Đồ thị 2D\"\n data-testid=\"graph-editor-panel\"\n data-stamp-area=\"true\"\n data-mobile-editor={isMobile ? 'true' : undefined}\n style={wrapperStyle}\n className={[\n isDark ? 'theme--dark ' : '',\n 'flex flex-col overflow-hidden bg-white',\n isMobile\n ? 'h-full w-full'\n : 'h-[540px] max-h-[85vh] w-[640px] max-w-[calc(100vw-280px)] rounded-lg border border-slate-300 shadow-2xl ring-1 ring-black/5',\n ].join(' ')}\n >\n <header className=\"flex items-center gap-2 border-b border-slate-200 bg-gradient-to-r from-orange-500 to-amber-600 px-3 py-2 text-white\">\n {isMobile && (\n <button\n type=\"button\"\n onClick={props.onOpenDrawer}\n aria-label=\"Mở bảng đại số\"\n data-testid=\"graph-drawer-toggle\"\n className=\"-ml-1 inline-flex h-10 w-10 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"4\" y1=\"6\" x2=\"20\" y2=\"6\" />\n <line x1=\"4\" y1=\"12\" x2=\"20\" y2=\"12\" />\n <line x1=\"4\" y1=\"18\" x2=\"20\" y2=\"18\" />\n </svg>\n </button>\n )}\n <h3 className=\"flex flex-1 items-center gap-2 text-sm font-semibold\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 21 V3\" />\n <path d=\"M3 21 H21\" />\n <path d=\"M5 19 C8 5, 14 5, 19 17\" />\n </svg>\n Đồ thị 2D\n </h3>\n {isMobile && (\n <button\n type=\"button\"\n onClick={handleInsert}\n disabled={!hasContent}\n data-testid=\"graph-insert-btn-mobile\"\n className=\"rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50\"\n >\n Chèn\n </button>\n )}\n <button\n onClick={props.onClose}\n aria-label=\"Đóng\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded transition hover:bg-white/15\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n </svg>\n </button>\n </header>\n\n <div className=\"min-h-0 flex-1\">\n <MiniBoard\n graph={graph}\n activeTool={tool}\n isDark={isDark}\n onBoardEvent={onBoardEvent}\n />\n </div>\n\n {!isMobile && (\n <footer className=\"flex items-center justify-between border-t border-slate-200 bg-slate-50 px-3 py-2\">\n <span className=\"text-xs text-slate-500\">Nhập biểu thức trong bảng đại số bên trái.</span>\n <div className=\"flex gap-2\">\n <button\n onClick={props.onClose}\n className=\"rounded border border-slate-300 bg-white px-3 py-1 text-xs font-medium text-slate-700 transition hover:bg-slate-100\"\n >\n Huỷ\n </button>\n <button\n onClick={handleInsert}\n disabled={!hasContent}\n data-testid=\"graph-insert-btn\"\n className=\"rounded bg-orange-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-orange-700 disabled:opacity-50\"\n >\n Chèn\n </button>\n </div>\n </footer>\n )}\n </div>\n );\n});\n","'use client';\n\nimport {\n forwardRef,\n useCallback,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { GraphLeftPanel } from './editor/LeftPanel';\nimport {\n GraphEditorPanel,\n type GraphEditorPanelHandle,\n type GraphState,\n} from './editor/EditorPanel';\nimport { insertStampImage } from '../shared/insertImage';\nimport {\n parseSerializedGraph,\n EMPTY_GRAPH,\n type SerializedGraph,\n} from './serialize';\nimport type {\n StampHostProps,\n StampHostHandle,\n} from '../shared/types';\nimport { useIsMobile } from '../shared/useIsMobile';\nimport { isGraph2DCustomData, type Graph2DCustomData } from './types';\n\n// ============== Host component ==============\n\nconst INITIAL_GRAPH_STATE: GraphState = {\n tool: 'move',\n showAxis: true,\n showGrid: true,\n canUndo: false,\n canRedo: false,\n};\n\nexport const Graph2DStampHost = forwardRef<StampHostHandle, StampHostProps>(\n function Graph2DStampHost({ api, editingElement, onClose, isDark }, ref) {\n const panelRef = useRef<GraphEditorPanelHandle | null>(null);\n const [graphUIState, setGraphUIState] = useState<GraphState>(INITIAL_GRAPH_STATE);\n const { isMobile } = useIsMobile();\n const [drawerOpen, setDrawerOpen] = useState(false);\n\n const initialState = useMemo<SerializedGraph | null>(() => {\n if (!editingElement) return null;\n if (!isGraph2DCustomData(editingElement.customData)) return null;\n return parseSerializedGraph(editingElement.customData.jsonState);\n }, [editingElement]);\n\n // State lifted from EditorPanel so LeftPanel/AlgebraView renders current graph + errors\n const [graphSnapshot, setGraphSnapshot] = useState<SerializedGraph>(\n initialState ?? EMPTY_GRAPH,\n );\n const [errorsSnapshot, setErrorsSnapshot] = useState<Record<string, string | null>>({});\n\n const handleInsert = useCallback(\n async (jsonState: string, svgString: string) => {\n if (!api) return;\n try {\n await insertStampImage(api, {\n svgString,\n makeCustomData: (width, height): Graph2DCustomData => ({\n kind: 'graph2d',\n version: 1,\n jsonState,\n svgWidth: width,\n svgHeight: height,\n }),\n editingElementId: editingElement?.id ?? null,\n });\n } catch (err) {\n console.error('Graph2D insert failed:', err);\n }\n onClose();\n },\n [api, editingElement?.id, onClose],\n );\n\n useImperativeHandle(\n ref,\n () => ({\n tryInsert: () => panelRef.current?.insert() ?? false,\n hasContent: () => panelRef.current?.hasContent() ?? false,\n }),\n [],\n );\n\n return (\n <>\n <GraphLeftPanel\n activeTool={graphUIState.tool}\n onToolChange={(t) => panelRef.current?.setTool(t)}\n showAxis={graphUIState.showAxis}\n showGrid={graphUIState.showGrid}\n onShowAxisChange={(b) => panelRef.current?.setShowAxis(b)}\n onShowGridChange={(b) => panelRef.current?.setShowGrid(b)}\n onResetView={() => panelRef.current?.resetView()}\n onUndo={() => panelRef.current?.undo()}\n canUndo={graphUIState.canUndo}\n onRedo={() => panelRef.current?.redo()}\n canRedo={graphUIState.canRedo}\n onClose={onClose}\n isDark={isDark}\n isMobile={isMobile}\n drawerOpen={drawerOpen}\n onDrawerClose={() => setDrawerOpen(false)}\n graph={graphSnapshot}\n errors={errorsSnapshot}\n onAddFunctionDraft={() => {\n const result = panelRef.current?.addFunction('x');\n if (result && !result.ok) console.warn('addFunction failed:', result.error);\n }}\n onCommitFunctionExpr={(id, expr) =>\n panelRef.current?.commitFunctionExpression(id, expr)\n }\n onToggleFunctionVisible={(id) => panelRef.current?.toggleFunctionVisible(id)}\n onRemoveFunction={(id) => panelRef.current?.removeFunction(id)}\n onParameterChange={(name, v) => panelRef.current?.setParameter(name, v)}\n onParameterRangeChange={(name, min, max, step) =>\n panelRef.current?.setParameterRange(name, min, max, step)\n }\n onRemoveParameter={(name) => panelRef.current?.removeParameter(name)}\n />\n <GraphEditorPanel\n ref={panelRef}\n initialState={initialState}\n onInsert={handleInsert}\n onClose={onClose}\n onStateChange={setGraphUIState}\n onGraphChange={setGraphSnapshot}\n onErrorsChange={setErrorsSnapshot}\n withLeftPanel={!isMobile}\n isDark={isDark}\n isMobile={isMobile}\n onOpenDrawer={() => setDrawerOpen(true)}\n />\n </>\n );\n },\n);\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, safeJsx } from './chunk-
|
|
2
|
+
import { serializeBoard, renderGeometrySvgFromState, isGeometryCustomData, safeJsx } from './chunk-G7FR3AIV.mjs';
|
|
3
3
|
import { useChordShortcut, MobileToolDrawer } from './chunk-SBDMF4NQ.mjs';
|
|
4
4
|
import { resolveAttrColors, paletteFor, themeLabel, themeAxis, themeGrid } from './chunk-HTBLO5JO.mjs';
|
|
5
5
|
import { useIsMobile } from './chunk-P2AOIF7S.mjs';
|
|
@@ -259,8 +259,12 @@ function letterForGroup(g) {
|
|
|
259
259
|
}
|
|
260
260
|
function objKind(obj) {
|
|
261
261
|
if (!obj) return "other";
|
|
262
|
+
const ec = typeof obj.elementClass === "number" ? obj.elementClass : null;
|
|
263
|
+
if (ec === 1) return "point";
|
|
264
|
+
if (ec === 2) return "line";
|
|
265
|
+
if (ec === 3) return "circle";
|
|
262
266
|
const e = (obj.elType || obj.type || "").toString().toLowerCase();
|
|
263
|
-
if (e === "point" || e === "glider" || e === "midpoint") return "point";
|
|
267
|
+
if (e === "point" || e === "glider" || e === "midpoint" || e === "intersection" || e === "otherintersection" || e === "reflection" || e === "mirrorpoint" || e === "mirrorelement" || e === "orthogonalprojection" || e === "parallelpoint") return "point";
|
|
264
268
|
if (e === "line" || e === "segment" || e === "arrow" || e === "axis" || e === "normal" || e === "parallel" || e === "perpendicular" || e === "tangent" || e === "bisector" || e === "perpendicularsegment") return "line";
|
|
265
269
|
if (e === "circle" || e === "circumcircle") return "circle";
|
|
266
270
|
return "other";
|
|
@@ -282,7 +286,7 @@ function handleDown(ctx, e) {
|
|
|
282
286
|
if (!sc) return;
|
|
283
287
|
const [sx, sy] = sc;
|
|
284
288
|
const hits2 = ctx.objectsAt(e).map(ctx.promoteLabel).filter((o) => o !== ctx.axisObjsRef.current.x && o !== ctx.axisObjsRef.current.y);
|
|
285
|
-
const obj = hits2.find((o) => objKind(o) === "point") ??
|
|
289
|
+
const obj = hits2.find((o) => objKind(o) === "point") ?? ctx.findNearestPoint(e, 12) ?? hits2[0];
|
|
286
290
|
if (obj) {
|
|
287
291
|
const shift = !!(e.shiftKey || e.altKey);
|
|
288
292
|
ctx.toggleSelect(obj, shift);
|
|
@@ -525,7 +529,7 @@ function handleUp(ctx, e) {
|
|
|
525
529
|
const moved = Math.hypot(sx - start.sx, sy - start.sy);
|
|
526
530
|
if (moved > 4) return;
|
|
527
531
|
const hits = ctx.objectsAt(e).map(ctx.promoteLabel).filter((o) => o !== ctx.axisObjsRef.current.x && o !== ctx.axisObjsRef.current.y);
|
|
528
|
-
const best = hits.find((o) => objKind(o) === "point") ??
|
|
532
|
+
const best = hits.find((o) => objKind(o) === "point") ?? ctx.findNearestPoint(e, 12) ?? hits[0];
|
|
529
533
|
if (!best) {
|
|
530
534
|
ctx.lastMoveClickRef.current = { obj: null, time: 0 };
|
|
531
535
|
return;
|
|
@@ -648,8 +652,16 @@ var JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
|
648
652
|
const nextLocalId = useCallback(() => "j" + creationLogRef.current.length, []);
|
|
649
653
|
const resolveArgs = useCallback((args) => {
|
|
650
654
|
return args.map((a) => {
|
|
651
|
-
if (typeof a === "string"
|
|
652
|
-
return objMapRef.current.get(a);
|
|
655
|
+
if (typeof a === "string") {
|
|
656
|
+
if (objMapRef.current.has(a)) return objMapRef.current.get(a);
|
|
657
|
+
const m = /^(.+):border:(\d+)$/.exec(a);
|
|
658
|
+
if (m) {
|
|
659
|
+
const poly = objMapRef.current.get(m[1]);
|
|
660
|
+
const idx = parseInt(m[2], 10);
|
|
661
|
+
if (poly && Array.isArray(poly.borders) && poly.borders[idx]) {
|
|
662
|
+
return poly.borders[idx];
|
|
663
|
+
}
|
|
664
|
+
}
|
|
653
665
|
}
|
|
654
666
|
return a;
|
|
655
667
|
});
|
|
@@ -679,15 +691,27 @@ var JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
|
679
691
|
[nextLocalId, resolveArgs, pushLog]
|
|
680
692
|
);
|
|
681
693
|
const localIdOf = useCallback((obj) => {
|
|
694
|
+
if (!obj) return null;
|
|
682
695
|
for (const [id, o] of objMapRef.current.entries()) {
|
|
683
696
|
if (o === obj) return id;
|
|
684
697
|
}
|
|
698
|
+
for (const [id, o] of objMapRef.current.entries()) {
|
|
699
|
+
const borders = o?.borders;
|
|
700
|
+
if (Array.isArray(borders)) {
|
|
701
|
+
const idx = borders.indexOf(obj);
|
|
702
|
+
if (idx >= 0) return `${id}:border:${idx}`;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
685
705
|
return null;
|
|
686
706
|
}, []);
|
|
687
707
|
const snapshotObject = useCallback((obj, anchorScreen) => {
|
|
688
708
|
const o = obj;
|
|
689
709
|
const k = objKind(o);
|
|
690
710
|
if (k !== "point" && k !== "line" && k !== "circle") return null;
|
|
711
|
+
for (const owner of objMapRef.current.values()) {
|
|
712
|
+
const borders = owner?.borders;
|
|
713
|
+
if (Array.isArray(borders) && borders.indexOf(o) >= 0) return null;
|
|
714
|
+
}
|
|
691
715
|
const v = o.visProp ?? {};
|
|
692
716
|
const showLabel = v.withlabel !== false;
|
|
693
717
|
const showValue = valueLabelsRef.current.has(o);
|
|
@@ -1206,7 +1230,22 @@ var JSXGraphMiniBoard = ({ onReady, initialState, isDark }) => {
|
|
|
1206
1230
|
const board = boardRef.current;
|
|
1207
1231
|
if (!board) return false;
|
|
1208
1232
|
const idMap = objMapRef.current;
|
|
1209
|
-
const
|
|
1233
|
+
const resolve = (a) => {
|
|
1234
|
+
if (typeof a === "string") {
|
|
1235
|
+
if (idMap.has(a)) return idMap.get(a);
|
|
1236
|
+
const m = /^(.+):border:(\d+)$/.exec(a);
|
|
1237
|
+
if (m) {
|
|
1238
|
+
const poly = idMap.get(m[1]);
|
|
1239
|
+
const idx = parseInt(m[2], 10);
|
|
1240
|
+
if (poly && Array.isArray(poly.borders) && poly.borders[idx]) {
|
|
1241
|
+
return poly.borders[idx];
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
if (Array.isArray(a)) return a.map(resolve);
|
|
1246
|
+
return a;
|
|
1247
|
+
};
|
|
1248
|
+
const resolved = el.args.map(resolve);
|
|
1210
1249
|
try {
|
|
1211
1250
|
if (el.type === "valueLabel") {
|
|
1212
1251
|
const target = resolved[0];
|
|
@@ -1819,15 +1858,15 @@ function CloseIcon() {
|
|
|
1819
1858
|
] });
|
|
1820
1859
|
}
|
|
1821
1860
|
function UndoIcon() {
|
|
1822
|
-
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "
|
|
1823
|
-
/* @__PURE__ */ jsx("
|
|
1824
|
-
/* @__PURE__ */ jsx("path", { d: "M3
|
|
1861
|
+
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1862
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10 L8 5 L8 8 L15 8 A5 5 0 0 1 20 13 L20 16" }),
|
|
1863
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10 L8 15 L8 12" })
|
|
1825
1864
|
] });
|
|
1826
1865
|
}
|
|
1827
1866
|
function RedoIcon() {
|
|
1828
|
-
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "
|
|
1829
|
-
/* @__PURE__ */ jsx("
|
|
1830
|
-
/* @__PURE__ */ jsx("path", { d: "
|
|
1867
|
+
return /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1868
|
+
/* @__PURE__ */ jsx("path", { d: "M21 10 L16 5 L16 8 L9 8 A5 5 0 0 0 4 13 L4 16" }),
|
|
1869
|
+
/* @__PURE__ */ jsx("path", { d: "M21 10 L16 15 L16 12" })
|
|
1831
1870
|
] });
|
|
1832
1871
|
}
|
|
1833
1872
|
function AxisIcon() {
|
|
@@ -2504,6 +2543,7 @@ var GeometryEditorPanel = forwardRef(
|
|
|
2504
2543
|
function GeometryEditorPanel2({ initialState, onInsert, onClose, withLeftPanel = false, onStateChange, isDark, isMobile = false, onOpenDrawer, onUndo, onRedo, canUndo, canRedo }, ref) {
|
|
2505
2544
|
const handleRef = useRef(null);
|
|
2506
2545
|
const [ready, setReady] = useState(false);
|
|
2546
|
+
const [hasContent, setHasContent] = useState(false);
|
|
2507
2547
|
const [propsPopover, setPropsPopover] = useState(null);
|
|
2508
2548
|
const [transformPopover, setTransformPopover] = useState(null);
|
|
2509
2549
|
const onStateChangeRef = useRef(onStateChange);
|
|
@@ -2512,8 +2552,10 @@ var GeometryEditorPanel = forwardRef(
|
|
|
2512
2552
|
}, [onStateChange]);
|
|
2513
2553
|
const emitState = useCallback(() => {
|
|
2514
2554
|
const h = handleRef.current;
|
|
2555
|
+
if (!h) return;
|
|
2556
|
+
setHasContent(h.getCreationLog().length > 0);
|
|
2515
2557
|
const cb = onStateChangeRef.current;
|
|
2516
|
-
if (!
|
|
2558
|
+
if (!cb) return;
|
|
2517
2559
|
cb({
|
|
2518
2560
|
tool: h.getTool(),
|
|
2519
2561
|
showAxis: h.getShowAxis(),
|
|
@@ -2643,7 +2685,8 @@ var GeometryEditorPanel = forwardRef(
|
|
|
2643
2685
|
{
|
|
2644
2686
|
type: "button",
|
|
2645
2687
|
onClick: handleInsert,
|
|
2646
|
-
disabled: !ready,
|
|
2688
|
+
disabled: !ready || !hasContent,
|
|
2689
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
2647
2690
|
"data-testid": "geometry-insert-btn-mobile",
|
|
2648
2691
|
className: "rounded bg-white/15 px-3 py-1.5 text-xs font-semibold transition hover:bg-white/25 disabled:opacity-50",
|
|
2649
2692
|
children: "Ch\xE8n"
|
|
@@ -2743,7 +2786,8 @@ var GeometryEditorPanel = forwardRef(
|
|
|
2743
2786
|
"button",
|
|
2744
2787
|
{
|
|
2745
2788
|
onClick: handleInsert,
|
|
2746
|
-
disabled: !ready,
|
|
2789
|
+
disabled: !ready || !hasContent,
|
|
2790
|
+
title: !hasContent ? "V\u1EBD \xEDt nh\u1EA5t m\u1ED9t \u0111\u1ED1i t\u01B0\u1EE3ng tr\u01B0\u1EDBc khi ch\xE8n" : void 0,
|
|
2747
2791
|
"data-testid": "geometry-insert-btn",
|
|
2748
2792
|
className: "rounded bg-emerald-600 px-3 py-1 text-xs font-medium text-white transition hover:bg-emerald-700 disabled:opacity-50",
|
|
2749
2793
|
children: "Ch\xE8n"
|
|
@@ -2860,5 +2904,5 @@ var GeometryStampHost = forwardRef(
|
|
|
2860
2904
|
);
|
|
2861
2905
|
|
|
2862
2906
|
export { GeometryStampHost };
|
|
2863
|
-
//# sourceMappingURL=host-
|
|
2864
|
-
//# sourceMappingURL=host-
|
|
2907
|
+
//# sourceMappingURL=host-XVK7UCRE.mjs.map
|
|
2908
|
+
//# sourceMappingURL=host-XVK7UCRE.mjs.map
|