@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.
Files changed (40) hide show
  1. package/dist/{chunk-ZVN356JZ.mjs → chunk-D257NCQW.mjs} +3 -3
  2. package/dist/{chunk-ZVN356JZ.mjs.map → chunk-D257NCQW.mjs.map} +1 -1
  3. package/dist/{chunk-KEYZ5EZT.mjs → chunk-G7FR3AIV.mjs} +44 -5
  4. package/dist/chunk-G7FR3AIV.mjs.map +1 -0
  5. package/dist/chunk-PWIMZIB6.mjs +62 -0
  6. package/dist/chunk-PWIMZIB6.mjs.map +1 -0
  7. package/dist/chunk-WQOABS6N.mjs +197 -0
  8. package/dist/chunk-WQOABS6N.mjs.map +1 -0
  9. package/dist/{chunk-DU3RHKT5.mjs → chunk-YVJP7NRG.mjs} +4 -4
  10. package/dist/{chunk-DU3RHKT5.mjs.map → chunk-YVJP7NRG.mjs.map} +1 -1
  11. package/dist/geometry-2d.js +102 -18
  12. package/dist/geometry-2d.js.map +1 -1
  13. package/dist/geometry-2d.mjs +2 -2
  14. package/dist/geometry-3d.js +152 -93
  15. package/dist/geometry-3d.js.map +1 -1
  16. package/dist/geometry-3d.mjs +2 -2
  17. package/dist/graph-2d.js +88 -20
  18. package/dist/graph-2d.js.map +1 -1
  19. package/dist/graph-2d.mjs +1 -1
  20. package/dist/{host-PIIDSMVE.mjs → host-N6ACNJKI.mjs} +51 -12
  21. package/dist/host-N6ACNJKI.mjs.map +1 -0
  22. package/dist/{host-LZH2FZ2N.mjs → host-NKGV6RF2.mjs} +91 -23
  23. package/dist/host-NKGV6RF2.mjs.map +1 -0
  24. package/dist/{host-VDNAJMLC.mjs → host-XVK7UCRE.mjs} +62 -18
  25. package/dist/host-XVK7UCRE.mjs.map +1 -0
  26. package/dist/index.d.mts +127 -1
  27. package/dist/index.d.ts +127 -1
  28. package/dist/index.js +1336 -177
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +993 -52
  31. package/dist/index.mjs.map +1 -1
  32. package/package.json +4 -1
  33. package/dist/chunk-DU2NFHRR.mjs +0 -103
  34. package/dist/chunk-DU2NFHRR.mjs.map +0 -1
  35. package/dist/chunk-IUVV52HO.mjs +0 -144
  36. package/dist/chunk-IUVV52HO.mjs.map +0 -1
  37. package/dist/chunk-KEYZ5EZT.mjs.map +0 -1
  38. package/dist/host-LZH2FZ2N.mjs.map +0 -1
  39. package/dist/host-PIIDSMVE.mjs.map +0 -1
  40. package/dist/host-VDNAJMLC.mjs.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xom11/whiteboard",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
4
4
  "private": false,
5
5
  "description": "Excalidraw + JSXGraph + KaTeX whiteboard component (drawing, geometry stamps, LaTeX stamps).",
6
6
  "license": "MIT",
@@ -85,5 +85,8 @@
85
85
  "tsup": "^8.3.5",
86
86
  "typescript": "^5.6.0",
87
87
  "vite": "^8.0.13"
88
+ },
89
+ "dependencies": {
90
+ "pdfjs-dist": "^5.7.284"
88
91
  }
89
92
  }
@@ -1,103 +0,0 @@
1
- "use client";
2
- import { paletteFor } from './chunk-HTBLO5JO.mjs';
3
-
4
- // src/stamps/geometry-3d/serialize.ts
5
- function isGeometry3DCustomData(data) {
6
- if (!data || typeof data !== "object") return false;
7
- const d = data;
8
- return d.kind === "geometry3d" && (d.version === 1 || d.version === 2) && typeof d.jsonState === "string";
9
- }
10
- function serializeBoard3D(state) {
11
- return JSON.stringify(state);
12
- }
13
- function parseSerializedBoard3D(json) {
14
- const parsed = JSON.parse(json);
15
- if (!parsed || typeof parsed !== "object") {
16
- throw new Error("parseSerializedBoard3D: not an object");
17
- }
18
- const p = parsed;
19
- if (p.version !== 1 && p.version !== 2) {
20
- throw new Error(`parseSerializedBoard3D: unsupported version ${String(p.version)}`);
21
- }
22
- if (!Array.isArray(p.elements)) {
23
- throw new Error("parseSerializedBoard3D: elements missing");
24
- }
25
- return parsed;
26
- }
27
-
28
- // src/stamps/geometry-3d/editor/theme.ts
29
- function paletteFor2(isDark) {
30
- const base = paletteFor(isDark);
31
- return {
32
- ...base,
33
- view3dBg: isDark ? "#1a1a1a" : "#ffffff",
34
- axisX: "#d63b3b",
35
- axisY: "#2d8a2d",
36
- axisZ: "#2d6dd6"
37
- };
38
- }
39
- var DEFAULT_VIEW3D = {
40
- azimuth: 0.7,
41
- elevation: 0.4,
42
- bbox3D: [-3, -3, -3, 3, 3, 3]
43
- };
44
- var VIEW3D_ATTRS = (isDark) => {
45
- const p = paletteFor2(isDark);
46
- const axisLabel = (color) => ({
47
- strokeColor: color,
48
- fontSize: 14,
49
- offset: [10, 0]
50
- });
51
- return {
52
- az: { slider: { visible: false }, point2: { visible: false } },
53
- el: { slider: { visible: false } },
54
- projection: "central",
55
- // GeoGebra-style: axes pass through origin (0,0,0) instead of bbox border.
56
- axesPosition: "center",
57
- xAxis: {
58
- strokeColor: p.axisX,
59
- strokeWidth: 2,
60
- lastArrow: { type: 2, size: 8 },
61
- name: "x",
62
- withLabel: true,
63
- label: axisLabel(p.axisX)
64
- },
65
- yAxis: {
66
- strokeColor: p.axisY,
67
- strokeWidth: 2,
68
- lastArrow: { type: 2, size: 8 },
69
- name: "y",
70
- withLabel: true,
71
- label: axisLabel(p.axisY)
72
- },
73
- zAxis: {
74
- strokeColor: p.axisZ,
75
- strokeWidth: 2,
76
- lastArrow: { type: 2, size: 8 },
77
- name: "z",
78
- withLabel: true,
79
- label: axisLabel(p.axisZ)
80
- },
81
- // GeoGebra-style: hide ALL bbox wall planes; the XY ground plane is drawn
82
- // explicitly at z=0 via the helper below (so it coincides with Ox/Oy).
83
- xPlaneRear: { visible: false, mesh3d: { visible: false } },
84
- yPlaneRear: { visible: false, mesh3d: { visible: false } },
85
- zPlaneRear: { visible: false, mesh3d: { visible: false } }
86
- };
87
- };
88
- var GROUND_PLANE_ATTRS = (isDark) => ({
89
- fillColor: isDark ? "#2a2a2a" : "#e6e6e6",
90
- fillOpacity: isDark ? 0.5 : 0.55,
91
- strokeColor: isDark ? "#3a3a3a" : "#cfcfcf",
92
- strokeOpacity: 0.7,
93
- strokeWidth: 1,
94
- fixed: true,
95
- highlight: false,
96
- withLabel: false,
97
- layer: 0
98
- });
99
- var GROUND_PLANE_RANGE = [-3, 3];
100
-
101
- export { DEFAULT_VIEW3D, GROUND_PLANE_ATTRS, GROUND_PLANE_RANGE, VIEW3D_ATTRS, isGeometry3DCustomData, paletteFor2 as paletteFor, parseSerializedBoard3D, serializeBoard3D };
102
- //# sourceMappingURL=chunk-DU2NFHRR.mjs.map
103
- //# sourceMappingURL=chunk-DU2NFHRR.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stamps/geometry-3d/serialize.ts","../src/stamps/geometry-3d/editor/theme.ts"],"names":["paletteFor"],"mappings":"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","file":"chunk-DU2NFHRR.mjs","sourcesContent":["import type { BaseStampCustomData } from '../shared/types';\nimport type { Constraint } from './editor/scene/types';\n\nexport interface Geometry3DCustomData extends BaseStampCustomData {\n kind: 'geometry3d';\n version: 1 | 2;\n jsonState: string;\n svgWidth: number;\n svgHeight: number;\n}\n\nexport function isGeometry3DCustomData(data: unknown): data is Geometry3DCustomData {\n if (!data || typeof data !== 'object') return false;\n const d = data as Partial<Geometry3DCustomData>;\n return (\n d.kind === 'geometry3d' &&\n (d.version === 1 || d.version === 2) &&\n typeof d.jsonState === 'string'\n );\n}\n\nexport type Element3DType =\n | 'point3d'\n | 'line3d'\n | 'plane3d'\n | 'polygon3d'\n | 'sphere3d'\n | 'text3d';\n\nexport interface SerializedElement3D {\n type: Element3DType;\n /**\n * Parents passed to JSXGraph view.create. Either literal values (numbers,\n * strings) or `\"@id:<id>\"` placeholder strings referencing earlier created\n * objects in the log (resolved at deserialize time).\n */\n parents: unknown[];\n attributes: Record<string, unknown>;\n id: string;\n label?: string;\n /** v2 only — present on point3d elements to encode the surface constraint. */\n constraint?: Constraint;\n}\n\nexport interface SerializedBoard3D {\n version: 1 | 2;\n bbox: [number, number, number, number];\n view: {\n azimuth: number;\n elevation: number;\n bbox3D: [number, number, number, number, number, number];\n };\n showAxes: boolean;\n showMesh: boolean;\n elements: SerializedElement3D[];\n}\n\nexport function serializeBoard3D(state: SerializedBoard3D): string {\n return JSON.stringify(state);\n}\n\nexport function parseSerializedBoard3D(json: string): SerializedBoard3D {\n const parsed = JSON.parse(json) as unknown;\n if (!parsed || typeof parsed !== 'object') {\n throw new Error('parseSerializedBoard3D: not an object');\n }\n const p = parsed as Partial<SerializedBoard3D>;\n if (p.version !== 1 && p.version !== 2) {\n throw new Error(`parseSerializedBoard3D: unsupported version ${String(p.version)}`);\n }\n if (!Array.isArray(p.elements)) {\n throw new Error('parseSerializedBoard3D: elements missing');\n }\n return parsed as SerializedBoard3D;\n}\n","import {\n paletteFor as palette2D,\n type GeomPalette,\n} from '../../geometry-2d/editor/theme';\n\nexport type Geom3DPalette = GeomPalette & {\n view3dBg: string;\n axisX: string;\n axisY: string;\n axisZ: string;\n};\n\nexport function paletteFor(isDark: boolean): Geom3DPalette {\n const base = palette2D(isDark);\n return {\n ...base,\n view3dBg: isDark ? '#1a1a1a' : '#ffffff',\n axisX: '#d63b3b',\n axisY: '#2d8a2d',\n axisZ: '#2d6dd6',\n };\n}\n\nexport const DEFAULT_VIEW3D: {\n azimuth: number;\n elevation: number;\n bbox3D: [number, number, number, number, number, number];\n} = {\n azimuth: 0.7,\n elevation: 0.4,\n bbox3D: [-3, -3, -3, 3, 3, 3],\n};\n\nexport const VIEW3D_ATTRS = (isDark: boolean) => {\n const p = paletteFor(isDark);\n const axisLabel = (color: string) => ({\n strokeColor: color,\n fontSize: 14,\n offset: [10, 0] as [number, number],\n });\n return {\n az: { slider: { visible: false }, point2: { visible: false } },\n el: { slider: { visible: false } },\n projection: 'central' as const,\n // GeoGebra-style: axes pass through origin (0,0,0) instead of bbox border.\n axesPosition: 'center' as const,\n xAxis: {\n strokeColor: p.axisX,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'x',\n withLabel: true,\n label: axisLabel(p.axisX),\n },\n yAxis: {\n strokeColor: p.axisY,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'y',\n withLabel: true,\n label: axisLabel(p.axisY),\n },\n zAxis: {\n strokeColor: p.axisZ,\n strokeWidth: 2,\n lastArrow: { type: 2, size: 8 },\n name: 'z',\n withLabel: true,\n label: axisLabel(p.axisZ),\n },\n // GeoGebra-style: hide ALL bbox wall planes; the XY ground plane is drawn\n // explicitly at z=0 via the helper below (so it coincides with Ox/Oy).\n xPlaneRear: { visible: false, mesh3d: { visible: false } },\n yPlaneRear: { visible: false, mesh3d: { visible: false } },\n zPlaneRear: { visible: false, mesh3d: { visible: false } },\n };\n};\n\nexport const GROUND_PLANE_ATTRS = (isDark: boolean) => ({\n fillColor: isDark ? '#2a2a2a' : '#e6e6e6',\n fillOpacity: isDark ? 0.5 : 0.55,\n strokeColor: isDark ? '#3a3a3a' : '#cfcfcf',\n strokeOpacity: 0.7,\n strokeWidth: 1,\n fixed: true,\n highlight: false,\n withLabel: false,\n layer: 0,\n});\n\n/** XY ground plane extent (square around origin in user units). */\nexport const GROUND_PLANE_RANGE: [number, number] = [-3, 3];\n"]}
@@ -1,144 +0,0 @@
1
- "use client";
2
- import { isGeometry3DCustomData, parseSerializedBoard3D, VIEW3D_ATTRS, GROUND_PLANE_RANGE, GROUND_PLANE_ATTRS } from './chunk-DU2NFHRR.mjs';
3
- import { lazy } from 'react';
4
- import { jsxs, jsx } from 'react/jsx-runtime';
5
-
6
- // src/stamps/geometry-3d/render.ts
7
- var OUTPUT_WIDTH = 1024;
8
- var OUTPUT_HEIGHT = 768;
9
- async function renderGeometry3DSvgFromState(jsonState) {
10
- const state = parseSerializedBoard3D(jsonState);
11
- const JXG = (await import('jsxgraph')).default;
12
- const div = document.createElement("div");
13
- div.style.cssText = `position:absolute;left:-9999px;top:-9999px;width:${OUTPUT_WIDTH}px;height:${OUTPUT_HEIGHT}px;`;
14
- document.body.appendChild(div);
15
- try {
16
- JXG.Options.text.display = "internal";
17
- const board = JXG.JSXGraph.initBoard(div, {
18
- boundingbox: state.bbox,
19
- axis: false,
20
- showCopyright: false,
21
- showNavigation: false,
22
- renderer: "svg"
23
- });
24
- const baseAttrs = VIEW3D_ATTRS(false);
25
- const view = board.create(
26
- "view3d",
27
- [
28
- [-5, -5],
29
- [10, 10],
30
- [
31
- [state.view.bbox3D[0], state.view.bbox3D[3]],
32
- [state.view.bbox3D[1], state.view.bbox3D[4]],
33
- [state.view.bbox3D[2], state.view.bbox3D[5]]
34
- ]
35
- ],
36
- {
37
- ...baseAttrs,
38
- az: { ...baseAttrs.az, value: state.view.azimuth },
39
- el: { ...baseAttrs.el, value: state.view.elevation }
40
- }
41
- );
42
- if (!state.showAxes) {
43
- view.defaultAxes = [];
44
- }
45
- try {
46
- view.create(
47
- "plane3d",
48
- [
49
- [0, 0, 0],
50
- [1, 0, 0],
51
- [0, 1, 0],
52
- GROUND_PLANE_RANGE,
53
- GROUND_PLANE_RANGE
54
- ],
55
- GROUND_PLANE_ATTRS(false)
56
- );
57
- } catch {
58
- }
59
- const idMap = /* @__PURE__ */ new Map();
60
- for (const el of state.elements) {
61
- const parents = el.parents.map(
62
- (p) => typeof p === "string" && p.startsWith("@id:") ? idMap.get(p.slice(4)) : p
63
- );
64
- const obj = view.create(el.type, parents, {
65
- ...el.attributes,
66
- id: el.id,
67
- name: el.label
68
- });
69
- idMap.set(el.id, obj);
70
- }
71
- const svg = div.querySelector("svg");
72
- if (!svg) {
73
- throw new Error("renderGeometry3DSvgFromState: SVG not produced");
74
- }
75
- const clone = svg.cloneNode(true);
76
- clone.setAttribute("width", String(OUTPUT_WIDTH));
77
- clone.setAttribute("height", String(OUTPUT_HEIGHT));
78
- const svgString = new XMLSerializer().serializeToString(clone);
79
- try {
80
- JXG.JSXGraph.freeBoard(board);
81
- } catch {
82
- }
83
- return { svgString, width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT };
84
- } finally {
85
- document.body.removeChild(div);
86
- }
87
- }
88
- var Geometry3DStampHost = lazy(
89
- () => import('./host-PIIDSMVE.mjs').then((m) => ({ default: m.Geometry3DStampHost }))
90
- );
91
- var Geometry3DIcon = /* @__PURE__ */ jsxs(
92
- "svg",
93
- {
94
- width: "20",
95
- height: "20",
96
- viewBox: "0 0 24 24",
97
- fill: "none",
98
- stroke: "currentColor",
99
- strokeWidth: "1.6",
100
- strokeLinecap: "round",
101
- strokeLinejoin: "round",
102
- "aria-hidden": "true",
103
- children: [
104
- /* @__PURE__ */ jsx("path", { d: "M4 9 L4 20 L14 20 L14 9 Z" }),
105
- /* @__PURE__ */ jsx("path", { d: "M4 9 L10 4 L20 4 L14 9 Z" }),
106
- /* @__PURE__ */ jsx("path", { d: "M14 9 L20 4 L20 15 L14 20 Z" })
107
- ]
108
- }
109
- );
110
- var geometry3dStamp = {
111
- kind: "geometry3d",
112
- experimental: true,
113
- shortcutKey: "d",
114
- toolbarLabel: "D",
115
- toolbarTitle: "H\xECnh 3D (D)",
116
- toolbarIcon: Geometry3DIcon,
117
- toolbarTestId: "stamp-toolbar-geometry3d",
118
- matchesCustomData: isGeometry3DCustomData,
119
- async renderSvgFromCustomData(data) {
120
- if (!isGeometry3DCustomData(data)) {
121
- throw new Error("geometry3dStamp.renderSvgFromCustomData: customData kh\xF4ng ph\u1EA3i geometry3d");
122
- }
123
- const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);
124
- return svgString;
125
- },
126
- restoreFileFromCustomData: async (element) => {
127
- const data = element.customData;
128
- const fileId = element.fileId;
129
- if (!data || !fileId) return null;
130
- if (!isGeometry3DCustomData(data)) return null;
131
- try {
132
- const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);
133
- const dataURL = `data:image/svg+xml;base64,${typeof btoa !== "undefined" ? btoa(unescape(encodeURIComponent(svgString))) : Buffer.from(svgString).toString("base64")}`;
134
- return { fileId, dataURL, mimeType: "image/svg+xml" };
135
- } catch {
136
- return null;
137
- }
138
- },
139
- Host: Geometry3DStampHost
140
- };
141
-
142
- export { geometry3dStamp };
143
- //# sourceMappingURL=chunk-IUVV52HO.mjs.map
144
- //# sourceMappingURL=chunk-IUVV52HO.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stamps/geometry-3d/render.ts","../src/stamps/geometry-3d/index.tsx"],"names":[],"mappings":"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","file":"chunk-IUVV52HO.mjs","sourcesContent":["\"use client\";\n\nimport { parseSerializedBoard3D } from './serialize';\nimport { GROUND_PLANE_ATTRS, GROUND_PLANE_RANGE, VIEW3D_ATTRS } from './editor/theme';\n\nexport interface RenderResult {\n svgString: string;\n width: number;\n height: number;\n}\n\nconst OUTPUT_WIDTH = 1024;\nconst OUTPUT_HEIGHT = 768;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JxgObj = any;\n\nexport async function renderGeometry3DSvgFromState(\n jsonState: string,\n): Promise<RenderResult> {\n const state = parseSerializedBoard3D(jsonState);\n const JXG = (await import('jsxgraph')).default;\n\n const div = document.createElement('div');\n div.style.cssText = `position:absolute;left:-9999px;top:-9999px;width:${OUTPUT_WIDTH}px;height:${OUTPUT_HEIGHT}px;`;\n document.body.appendChild(div);\n\n try {\n JXG.Options.text.display = 'internal';\n\n const board = JXG.JSXGraph.initBoard(div, {\n boundingbox: state.bbox,\n axis: false,\n showCopyright: false,\n showNavigation: false,\n renderer: 'svg',\n }) as { create: (k: string, p: unknown[], a: unknown) => JxgObj };\n\n const baseAttrs = VIEW3D_ATTRS(false);\n const view: JxgObj = board.create(\n 'view3d',\n [\n [-5, -5],\n [10, 10],\n [\n [state.view.bbox3D[0], state.view.bbox3D[3]],\n [state.view.bbox3D[1], state.view.bbox3D[4]],\n [state.view.bbox3D[2], state.view.bbox3D[5]],\n ],\n ],\n {\n ...baseAttrs,\n az: { ...baseAttrs.az, value: state.view.azimuth },\n el: { ...baseAttrs.el, value: state.view.elevation },\n },\n );\n\n if (!state.showAxes) {\n (view as { defaultAxes?: unknown[] }).defaultAxes = [];\n }\n\n // XY ground plane through origin (matches editor's MiniBoard3D).\n try {\n (view as { create: (k: string, p: unknown[], a: unknown) => JxgObj }).create(\n 'plane3d',\n [\n [0, 0, 0],\n [1, 0, 0],\n [0, 1, 0],\n GROUND_PLANE_RANGE,\n GROUND_PLANE_RANGE,\n ],\n GROUND_PLANE_ATTRS(false),\n );\n } catch {\n /* swallow */\n }\n\n const idMap = new Map<string, JxgObj>();\n for (const el of state.elements) {\n const parents = el.parents.map((p) =>\n typeof p === 'string' && p.startsWith('@id:')\n ? idMap.get(p.slice(4))\n : p,\n );\n const obj = (\n view as { create: (k: string, p: unknown[], a: unknown) => JxgObj }\n ).create(el.type, parents, {\n ...el.attributes,\n id: el.id,\n name: el.label,\n });\n idMap.set(el.id, obj);\n }\n\n const svg = div.querySelector('svg');\n if (!svg) {\n throw new Error('renderGeometry3DSvgFromState: SVG not produced');\n }\n const clone = svg.cloneNode(true) as SVGElement;\n clone.setAttribute('width', String(OUTPUT_WIDTH));\n clone.setAttribute('height', String(OUTPUT_HEIGHT));\n const svgString = new XMLSerializer().serializeToString(clone);\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n JXG.JSXGraph.freeBoard(board as any);\n } catch {\n /* ignore teardown */\n }\n\n return { svgString, width: OUTPUT_WIDTH, height: OUTPUT_HEIGHT };\n } finally {\n document.body.removeChild(div);\n }\n}\n","'use client';\n\nimport { lazy, type ReactNode } from 'react';\nimport {\n isGeometry3DCustomData,\n type Geometry3DCustomData,\n} from './serialize';\nimport { renderGeometry3DSvgFromState } from './render';\nimport type {\n RestoredStampFile,\n StampType,\n} from '../shared/types';\n\nexport { isGeometry3DCustomData };\nexport type { Geometry3DCustomData };\n\nconst Geometry3DStampHost = lazy(() =>\n import('./host').then((m) => ({ default: m.Geometry3DStampHost })),\n);\n\nconst Geometry3DIcon: ReactNode = (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {/* Mặt trước */}\n <path d=\"M4 9 L4 20 L14 20 L14 9 Z\" />\n {/* Mặt trên */}\n <path d=\"M4 9 L10 4 L20 4 L14 9 Z\" />\n {/* Mặt phải */}\n <path d=\"M14 9 L20 4 L20 15 L14 20 Z\" />\n </svg>\n);\n\nexport const geometry3dStamp: StampType = {\n kind: 'geometry3d',\n experimental: true,\n shortcutKey: 'd',\n toolbarLabel: 'D',\n toolbarTitle: 'Hình 3D (D)',\n toolbarIcon: Geometry3DIcon,\n toolbarTestId: 'stamp-toolbar-geometry3d',\n matchesCustomData: isGeometry3DCustomData,\n async renderSvgFromCustomData(data: unknown): Promise<string> {\n if (!isGeometry3DCustomData(data)) {\n throw new Error('geometry3dStamp.renderSvgFromCustomData: customData không phải geometry3d');\n }\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgString;\n },\n restoreFileFromCustomData: async (element): Promise<RestoredStampFile | null> => {\n const data = element.customData as Geometry3DCustomData | undefined;\n const fileId = (element as { fileId?: string | null }).fileId;\n if (!data || !fileId) return null;\n if (!isGeometry3DCustomData(data)) return null;\n try {\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n const dataURL = `data:image/svg+xml;base64,${\n typeof btoa !== 'undefined'\n ? btoa(unescape(encodeURIComponent(svgString)))\n : Buffer.from(svgString).toString('base64')\n }`;\n return { fileId, dataURL, mimeType: 'image/svg+xml' };\n } catch {\n return null;\n }\n },\n Host: Geometry3DStampHost,\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stamps/geometry-2d/renderInline.ts","../src/stamps/geometry-2d/serialize.ts","../src/stamps/shared/safeJsx.ts","../src/stamps/geometry-2d/render.ts","../src/stamps/geometry-2d/types.ts"],"names":[],"mappings":"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","file":"chunk-KEYZ5EZT.mjs","sourcesContent":["export function renderGeometryToSvg(boardContainer: HTMLElement): string {\n const svgEl = boardContainer.querySelector('svg');\n if (!svgEl) throw new Error('renderGeometryToSvg: no SVG found in board container');\n const clone = svgEl.cloneNode(true) as SVGElement;\n if (!clone.getAttribute('xmlns')) {\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n }\n return new XMLSerializer().serializeToString(clone);\n}\n","// JSXGraph không có built-in getJSON. Component giữ MỘT LOG riêng của các create() call\n// do user trigger, pass log đó vào serializeBoard. Replay = gọi board.create() theo thứ tự log.\n//\n// type === 'transform': args là [refs đến điểm/đường/scalar], attrs là { type: 'translate'|'rotate'|'reflect'|'scale', ... }.\n// Object trả về (kết quả board.create('transform', ...)) được đăng ký vào idMap như mọi element khác\n// để point/line phụ thuộc reference được bằng id ('j5' → JSXGraph transform object).\n//\n// Log lưu màu dưới dạng sentinel ('@stroke', '@axis', '@grid', '@label') để\n// theme-neutral. Khi replay, palette resolve thành màu thực theo `isDark` hiện\n// tại (truyền qua options.palette).\n\nimport { paletteFor, resolveAttrColors, type GeomPalette } from './editor/theme';\n\nexport interface SerializedElement {\n type: string;\n args: unknown[];\n attrs: Record<string, unknown>;\n id: string;\n}\n\nexport interface SerializedBoard {\n bbox: [number, number, number, number];\n elements: SerializedElement[];\n showAxis?: boolean;\n showGrid?: boolean;\n}\n\ninterface BoardLike {\n getBoundingBox(): [number, number, number, number];\n create(type: string, args: unknown[], attrs: Record<string, unknown>): unknown;\n}\n\nexport function serializeBoard(\n board: BoardLike,\n log: SerializedElement[],\n options: { showAxis?: boolean; showGrid?: boolean } = {},\n): SerializedBoard {\n return {\n bbox: board.getBoundingBox(),\n elements: log.map(e => ({ type: e.type, args: e.args, attrs: e.attrs, id: e.id })),\n showAxis: !!options.showAxis,\n showGrid: !!options.showGrid,\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction createValueLabel(board: any, target: any): unknown {\n if (!board || !target) return null;\n const e = (target.elType ?? target.type ?? '').toString().toLowerCase();\n if (e === 'segment' || e === 'line' || e === 'arrow') {\n const p1 = target.point1, p2 = target.point2;\n if (!p1 || !p2) return null;\n return board.create('text', [\n () => (p1.X() + p2.X()) / 2 + 0.15,\n () => (p1.Y() + p2.Y()) / 2 + 0.25,\n () => {\n const len = Math.hypot(p2.X() - p1.X(), p2.Y() - p1.Y());\n const name = typeof target.name === 'string' && target.name ? target.name : 'd';\n return `${name} = ${len.toFixed(2)}`;\n },\n ], { fontSize: 12, color: '#dc2626', fixed: true, highlight: false });\n }\n if (e === 'circle' || e === 'circumcircle') {\n const center = target.center ?? target.midpoint ?? target.point1;\n if (!center) return null;\n return board.create('text', [\n () => center.X() + 0.3,\n () => center.Y() + 0.3,\n () => {\n const r = typeof target.Radius === 'function' ? target.Radius() : 0;\n const name = typeof target.name === 'string' && target.name ? target.name : 'r';\n return `${name} = ${r.toFixed(2)}`;\n },\n ], { fontSize: 12, color: '#dc2626', fixed: true, highlight: false });\n }\n return null;\n}\n\nexport interface DeserializeOptions {\n /** Theme-aware palette để resolve sentinel attrs. Mặc định = light. */\n palette?: GeomPalette;\n}\n\nexport function deserializeIntoBoard(\n board: BoardLike,\n serialized: SerializedBoard,\n options: DeserializeOptions = {},\n): void {\n // Replay: args may contain references to earlier elements by our serialized id (\"j0\", \"j1\"…).\n // We resolve those to actual JSXGraph objects via a local id→object map. Nested\n // arrays are also resolved recursively — needed for dilate, which logs the\n // transform parent of a transformed point as [\"j2\",\"j3\",\"j4\"] (a chain of 3\n // transforms passed to `board.create('point', [src, [t1,t2,t3]])`).\n const palette = options.palette ?? paletteFor(false);\n const idMap = new Map<string, unknown>();\n const resolve = (a: unknown): unknown => {\n if (typeof a === 'string' && idMap.has(a)) return idMap.get(a);\n if (Array.isArray(a)) return a.map(resolve);\n return a;\n };\n for (const el of serialized.elements) {\n const resolvedArgs = el.args.map(resolve);\n if (el.type === 'valueLabel') {\n const target = resolvedArgs[0];\n const txt = createValueLabel(board, target);\n if (txt) idMap.set(el.id, txt);\n continue;\n }\n const themedAttrs = resolveAttrColors({ ...el.attrs }, palette);\n const created = board.create(el.type, resolvedArgs, themedAttrs);\n idMap.set(el.id, created);\n }\n}\n","const isDev = (() => {\n try {\n return typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n } catch {\n return false;\n }\n})();\n\n/**\n * Wrap JSXGraph operations that can throw on stale/missing state.\n * In dev mode: log to console. In prod: silent swallow + return fallback.\n *\n * @param label Short tag for grep-ability (vd \"removeObject\", \"board.update\").\n * @param fn Operation to execute.\n * @param fallback Value to return if fn throws (default: undefined).\n */\nexport function safeJsx<T>(label: string, fn: () => T): T | undefined;\nexport function safeJsx<T>(label: string, fn: () => T, fallback: T): T;\nexport function safeJsx<T>(label: string, fn: () => T, fallback?: T): T | undefined {\n try {\n return fn();\n } catch (err) {\n if (isDev) {\n // eslint-disable-next-line no-console\n console.warn('[whiteboard:jsxgraph]', label, err);\n }\n return fallback;\n }\n}\n","import { renderGeometryToSvg } from './renderInline';\nimport { deserializeIntoBoard, type SerializedBoard } from './serialize';\nimport { paletteFor } from './editor/theme';\nimport { safeJsx } from '../shared/safeJsx';\n\n/**\n * Re-render geometry SVG từ jsonState đã serialize. Dùng cho:\n * 1. Restore math-stamp file sau khi reload page (Excalidraw mất binary files).\n * 2. Generate SVG lúc INSERT (thay vì clone DOM với màu theo theme editor).\n *\n * LƯU Ý quan trọng — luôn dùng LIGHT palette (nét đậm). Excalidraw apply CSS\n * `filter: invert(93%) hue-rotate(180deg)` lên canvas trong dark mode → nét\n * đậm tự đảo thành sáng. Nếu ta bake nét sáng vào SVG cho dark mode, filter\n * sẽ đảo thành đậm → chìm vào nền tối. Giải pháp: luôn dùng nét đậm + để\n * Excalidraw tự lo invert.\n *\n * Implementation: tạo 1 div ẩn (off-screen, real dimensions để JSXGraph render\n * chuẩn), initBoard, replay creation log từ jsonState, dump SVG, dọn dẹp.\n *\n * Lý do JXG.Options.text.display = 'internal': JSXGraph mặc định render\n * label bằng HTML <div> overlay → clone SVG export sẽ thiếu label.\n */\nexport async function renderGeometrySvgFromState(jsonState: string): Promise<string> {\n const parsed = JSON.parse(jsonState) as SerializedBoard;\n // Stamps inserted vào Excalidraw canvas → luôn dùng light palette.\n // Excalidraw's THEME_FILTER tự đảo nét trong dark mode.\n const palette = paletteFor(false);\n const JXG = (await import('jsxgraph')).default;\n safeJsx('render.applyOptions', () => {\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.text.useASCIIMathML = false;\n opts.text.useMathJax = false;\n opts.text.useKatex = false;\n opts.text.strokeColor = palette.label;\n opts.label = opts.label || {};\n opts.label.display = 'internal';\n opts.label.strokeColor = palette.label;\n opts.axis = opts.axis || {};\n opts.axis.strokeColor = palette.axis;\n opts.grid = opts.grid || {};\n opts.grid.strokeColor = palette.grid;\n }\n });\n const container = document.createElement('div');\n const containerId = 'jxg_offscreen_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8);\n container.id = containerId;\n container.style.cssText = 'position:absolute;top:-99999px;left:-99999px;width:400px;height:300px;visibility:hidden;pointer-events:none;';\n document.body.appendChild(container);\n let board: unknown = null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n board = (JXG as any).JSXGraph.initBoard(containerId, {\n boundingbox: parsed.bbox,\n axis: !!parsed.showAxis,\n grid: !!parsed.showGrid,\n showCopyright: false,\n showNavigation: false,\n keepAspectRatio: false,\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n deserializeIntoBoard(board as any, parsed, { palette });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (board as any).update();\n return renderGeometryToSvg(container);\n } finally {\n safeJsx('render.freeBoard', () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (board) (JXG as any).JSXGraph.freeBoard(board);\n });\n if (container.parentNode) container.parentNode.removeChild(container);\n }\n}\n","import type { BaseStampCustomData } from '../shared/types';\n\nexport interface GeometryCustomData extends BaseStampCustomData {\n kind: 'geometry';\n version: 1;\n jsonState: string;\n svgWidth: number;\n svgHeight: number;\n}\n\nexport function isGeometryCustomData(data: unknown): data is GeometryCustomData {\n if (!data || typeof data !== 'object') return false;\n const d = data as Partial<GeometryCustomData>;\n return d.kind === 'geometry' && d.version === 1 && typeof d.jsonState === 'string';\n}\n"]}
@@ -1 +0,0 @@
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-LZH2FZ2N.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=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"3 7 3 13 9 13\" />\n <path d=\"M3.51 13a9 9 0 1 0 2.13-9.36L3 7\" />\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 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 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 </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}\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\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 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 }, []);\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 });\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 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 });\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: () => {\n const prev = undoStackRef.current.pop();\n if (!prev) return;\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 });\n propsRef.current.onGraphChange?.(prev);\n },\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],\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};\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 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"]}