@xom11/whiteboard 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ExcalidrawWithMenus-WENZRYYE.mjs → ExcalidrawWithMenus-2QPPTXJM.mjs} +3 -2
- package/dist/ExcalidrawWithMenus-2QPPTXJM.mjs.map +1 -0
- package/dist/ai.d.mts +3035 -108
- package/dist/ai.d.ts +3035 -108
- package/dist/ai.js +6736 -775
- package/dist/ai.js.map +1 -1
- package/dist/ai.mjs +5110 -578
- package/dist/ai.mjs.map +1 -1
- package/dist/catalog.json +5 -5
- package/dist/{chunk-ESVPQWHX.mjs → chunk-4ETJ4CDY.mjs} +5 -5
- package/dist/{chunk-ESVPQWHX.mjs.map → chunk-4ETJ4CDY.mjs.map} +1 -1
- package/dist/{chunk-VNCCIV6O.mjs → chunk-AJAHD35N.mjs} +779 -9
- package/dist/chunk-AJAHD35N.mjs.map +1 -0
- package/dist/chunk-AYJPOHCI.mjs +265 -0
- package/dist/chunk-AYJPOHCI.mjs.map +1 -0
- package/dist/{chunk-M42TGYT6.mjs → chunk-BNBOIDO5.mjs} +3 -3
- package/dist/{chunk-M42TGYT6.mjs.map → chunk-BNBOIDO5.mjs.map} +1 -1
- package/dist/{chunk-CJBLJUWG.mjs → chunk-CXHNVYMD.mjs} +4 -4
- package/dist/{chunk-CJBLJUWG.mjs.map → chunk-CXHNVYMD.mjs.map} +1 -1
- package/dist/{chunk-NDEZJKNY.mjs → chunk-D5JLJ3PT.mjs} +4 -4
- package/dist/{chunk-NDEZJKNY.mjs.map → chunk-D5JLJ3PT.mjs.map} +1 -1
- package/dist/{chunk-REIJZDVZ.mjs → chunk-D5LWSN2Y.mjs} +942 -195
- package/dist/chunk-D5LWSN2Y.mjs.map +1 -0
- package/dist/{chunk-I24QOHPU.mjs → chunk-HLAOGXEK.mjs} +3 -3
- package/dist/{chunk-I24QOHPU.mjs.map → chunk-HLAOGXEK.mjs.map} +1 -1
- package/dist/{chunk-TB4CL25L.mjs → chunk-I3L56GVH.mjs} +206 -66
- package/dist/chunk-I3L56GVH.mjs.map +1 -0
- package/dist/chunk-J5LGTIGS.mjs +10 -0
- package/dist/chunk-J5LGTIGS.mjs.map +1 -0
- package/dist/{chunk-ONBCUWVI.mjs → chunk-KYMBUTPO.mjs} +3 -3
- package/dist/{chunk-ONBCUWVI.mjs.map → chunk-KYMBUTPO.mjs.map} +1 -1
- package/dist/{chunk-YSJOVBCD.mjs → chunk-KZGPSTZI.mjs} +4 -4
- package/dist/{chunk-YSJOVBCD.mjs.map → chunk-KZGPSTZI.mjs.map} +1 -1
- package/dist/{chunk-SGFJLHHG.mjs → chunk-PPKHCRRE.mjs} +3 -3
- package/dist/{chunk-SGFJLHHG.mjs.map → chunk-PPKHCRRE.mjs.map} +1 -1
- package/dist/{chunk-AYSFWUPK.mjs → chunk-SZDAS7LK.mjs} +79 -2
- package/dist/chunk-SZDAS7LK.mjs.map +1 -0
- package/dist/chunk-T3SOHYB2.mjs +851 -0
- package/dist/chunk-T3SOHYB2.mjs.map +1 -0
- package/dist/geometry-2d.d.mts +1 -1
- package/dist/geometry-2d.d.ts +1 -1
- package/dist/geometry-2d.js +5389 -1362
- package/dist/geometry-2d.js.map +1 -1
- package/dist/geometry-2d.mjs +5 -4
- package/dist/geometry-3d.d.mts +1 -1
- package/dist/geometry-3d.d.ts +1 -1
- package/dist/geometry-3d.js +1333 -251
- package/dist/geometry-3d.js.map +1 -1
- package/dist/geometry-3d.mjs +4 -3
- package/dist/graph-2d.d.mts +1 -1
- package/dist/graph-2d.d.ts +1 -1
- package/dist/graph-2d.js +1499 -340
- package/dist/graph-2d.js.map +1 -1
- package/dist/graph-2d.mjs +7 -6
- package/dist/handleExtractProblem-C-U5KluK.d.mts +158 -0
- package/dist/handleExtractProblem-C-U5KluK.d.ts +158 -0
- package/dist/{host-L7FMFZUW.mjs → host-HAYCJJ2T.mjs} +1258 -441
- package/dist/host-HAYCJJ2T.mjs.map +1 -0
- package/dist/{host-QK53UYMD.mjs → host-LTJHAY5A.mjs} +10 -9
- package/dist/host-LTJHAY5A.mjs.map +1 -0
- package/dist/{host-A64ITWVX.mjs → host-M26FS244.mjs} +6 -5
- package/dist/host-M26FS244.mjs.map +1 -0
- package/dist/{host-QS2EOTRJ.mjs → host-ZQCDAT6O.mjs} +3 -2
- package/dist/host-ZQCDAT6O.mjs.map +1 -0
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5621 -1590
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +22 -20
- package/dist/index.mjs.map +1 -1
- package/dist/latex.d.mts +1 -1
- package/dist/latex.d.ts +1 -1
- package/dist/latex.mjs +2 -1
- package/dist/render-ZX2O2IK7.mjs +10 -0
- package/dist/{render-3WTY7NZB.mjs.map → render-ZX2O2IK7.mjs.map} +1 -1
- package/dist/serialize-C3LSUMSA.mjs +9 -0
- package/dist/{serialize-SRJVKYUG.mjs.map → serialize-C3LSUMSA.mjs.map} +1 -1
- package/dist/{types-DWRyCa2m.d.ts → types-zc_Pa0mp.d.mts} +105 -0
- package/dist/{types-DWRyCa2m.d.mts → types-zc_Pa0mp.d.ts} +105 -0
- package/package.json +10 -1
- package/dist/ExcalidrawWithMenus-WENZRYYE.mjs.map +0 -1
- package/dist/chunk-AYSFWUPK.mjs.map +0 -1
- package/dist/chunk-REIJZDVZ.mjs.map +0 -1
- package/dist/chunk-TB4CL25L.mjs.map +0 -1
- package/dist/chunk-VNCCIV6O.mjs.map +0 -1
- package/dist/chunk-VRHWDZ66.mjs +0 -96
- package/dist/chunk-VRHWDZ66.mjs.map +0 -1
- package/dist/host-A64ITWVX.mjs.map +0 -1
- package/dist/host-L7FMFZUW.mjs.map +0 -1
- package/dist/host-QK53UYMD.mjs.map +0 -1
- package/dist/host-QS2EOTRJ.mjs.map +0 -1
- package/dist/render-3WTY7NZB.mjs +0 -9
- package/dist/serialize-SRJVKYUG.mjs +0 -8
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { paletteFor } from './chunk-R5FL6S7L.mjs';
|
|
3
|
+
import { JxgRenderer } from './chunk-SZDAS7LK.mjs';
|
|
4
|
+
import { renderJsxgOffscreen } from './chunk-ICR4CVOE.mjs';
|
|
5
|
+
import { serializeScene, deserializeScene } from './chunk-D5LWSN2Y.mjs';
|
|
6
|
+
import { createStore } from './chunk-IHUFOV7L.mjs';
|
|
7
|
+
import { DEFAULT_VIEW_2D } from './chunk-73Q7ADVL.mjs';
|
|
8
|
+
|
|
9
|
+
// src/stamps/geometry-2d/serialize.ts
|
|
10
|
+
function serializeBoard(state, view) {
|
|
11
|
+
const withView = {
|
|
12
|
+
...state,
|
|
13
|
+
meta: { domain: "2d", version: state.meta.version, view }
|
|
14
|
+
};
|
|
15
|
+
return serializeScene(withView);
|
|
16
|
+
}
|
|
17
|
+
function deserializeBoard(raw) {
|
|
18
|
+
return deserializeScene("2d", raw);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/stamps/geometry-2d/autoFitBbox.ts
|
|
22
|
+
function robustRange(values, k = 1.5) {
|
|
23
|
+
const n = values.length;
|
|
24
|
+
if (n === 0) return [0, 0];
|
|
25
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
26
|
+
if (n < 4) return [sorted[0], sorted[n - 1]];
|
|
27
|
+
const quantile = (p) => {
|
|
28
|
+
const idx = (n - 1) * p;
|
|
29
|
+
const lo = Math.floor(idx);
|
|
30
|
+
const hi = Math.ceil(idx);
|
|
31
|
+
if (lo === hi) return sorted[lo];
|
|
32
|
+
return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);
|
|
33
|
+
};
|
|
34
|
+
const q1 = quantile(0.25);
|
|
35
|
+
const q3 = quantile(0.75);
|
|
36
|
+
const iqr = q3 - q1;
|
|
37
|
+
const fenceLo = q1 - k * iqr;
|
|
38
|
+
const fenceHi = q3 + k * iqr;
|
|
39
|
+
let min = Infinity;
|
|
40
|
+
let max = -Infinity;
|
|
41
|
+
for (const v of sorted) {
|
|
42
|
+
if (v < fenceLo || v > fenceHi) continue;
|
|
43
|
+
if (v < min) min = v;
|
|
44
|
+
if (v > max) max = v;
|
|
45
|
+
}
|
|
46
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return [sorted[0], sorted[n - 1]];
|
|
47
|
+
return [min, max];
|
|
48
|
+
}
|
|
49
|
+
var CIRCLE_MAX_FACTOR = 1;
|
|
50
|
+
function computeAutoFitBbox(points, circles, aspect, padPct = 0.12) {
|
|
51
|
+
const xs = points.map((p) => p[0]).filter(Number.isFinite);
|
|
52
|
+
const ys = points.map((p) => p[1]).filter(Number.isFinite);
|
|
53
|
+
let xmin = Infinity, xmax = -Infinity, ymin = Infinity, ymax = -Infinity;
|
|
54
|
+
let clusterDiag = 0;
|
|
55
|
+
if (xs.length >= 2 && ys.length >= 2) {
|
|
56
|
+
[xmin, xmax] = robustRange(xs);
|
|
57
|
+
[ymin, ymax] = robustRange(ys);
|
|
58
|
+
clusterDiag = Math.hypot(xmax - xmin, ymax - ymin);
|
|
59
|
+
}
|
|
60
|
+
for (const c of circles) {
|
|
61
|
+
if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy) || !Number.isFinite(c.r)) continue;
|
|
62
|
+
if (clusterDiag > 0 && c.r > CIRCLE_MAX_FACTOR * clusterDiag) continue;
|
|
63
|
+
xmin = Math.min(xmin, c.cx - c.r);
|
|
64
|
+
xmax = Math.max(xmax, c.cx + c.r);
|
|
65
|
+
ymin = Math.min(ymin, c.cy - c.r);
|
|
66
|
+
ymax = Math.max(ymax, c.cy + c.r);
|
|
67
|
+
}
|
|
68
|
+
if (!Number.isFinite(xmin) || !Number.isFinite(xmax) || !Number.isFinite(ymin) || !Number.isFinite(ymax)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
let w = xmax - xmin;
|
|
72
|
+
let h = ymax - ymin;
|
|
73
|
+
if (w < 0.5) {
|
|
74
|
+
const cx = (xmin + xmax) / 2;
|
|
75
|
+
xmin = cx - 0.5;
|
|
76
|
+
xmax = cx + 0.5;
|
|
77
|
+
w = 1;
|
|
78
|
+
}
|
|
79
|
+
if (h < 0.5) {
|
|
80
|
+
const cy = (ymin + ymax) / 2;
|
|
81
|
+
ymin = cy - 0.5;
|
|
82
|
+
ymax = cy + 0.5;
|
|
83
|
+
h = 1;
|
|
84
|
+
}
|
|
85
|
+
const padX = w * padPct;
|
|
86
|
+
const padY = h * padPct;
|
|
87
|
+
xmin -= padX;
|
|
88
|
+
xmax += padX;
|
|
89
|
+
ymin -= padY;
|
|
90
|
+
ymax += padY;
|
|
91
|
+
w = xmax - xmin;
|
|
92
|
+
h = ymax - ymin;
|
|
93
|
+
const curAspect = w / h;
|
|
94
|
+
if (curAspect < aspect) {
|
|
95
|
+
const newW = h * aspect;
|
|
96
|
+
const cx = (xmin + xmax) / 2;
|
|
97
|
+
xmin = cx - newW / 2;
|
|
98
|
+
xmax = cx + newW / 2;
|
|
99
|
+
} else if (curAspect > aspect) {
|
|
100
|
+
const newH = w / aspect;
|
|
101
|
+
const cy = (ymin + ymax) / 2;
|
|
102
|
+
ymin = cy - newH / 2;
|
|
103
|
+
ymax = cy + newH / 2;
|
|
104
|
+
}
|
|
105
|
+
return [xmin, ymax, xmax, ymin];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/stamps/geometry-2d/labelLayout.ts
|
|
109
|
+
function radialLabelOffsets(points, R = 14) {
|
|
110
|
+
const out = /* @__PURE__ */ new Map();
|
|
111
|
+
if (points.length < 2) return out;
|
|
112
|
+
const cx = points.reduce((s, p) => s + p.x, 0) / points.length;
|
|
113
|
+
const cy = points.reduce((s, p) => s + p.y, 0) / points.length;
|
|
114
|
+
for (const p of points) {
|
|
115
|
+
let dx = p.x - cx;
|
|
116
|
+
let dy = p.y - cy;
|
|
117
|
+
const len = Math.hypot(dx, dy);
|
|
118
|
+
if (len < 1e-9) {
|
|
119
|
+
dx = 0;
|
|
120
|
+
dy = 1;
|
|
121
|
+
} else {
|
|
122
|
+
dx /= len;
|
|
123
|
+
dy /= len;
|
|
124
|
+
}
|
|
125
|
+
out.set(p.id, [Math.round(dx * R), Math.round(dy * R)]);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/stamps/geometry-2d/render.ts
|
|
131
|
+
var PIXELS_PER_UNIT = 20;
|
|
132
|
+
var MIN_DIM = 100;
|
|
133
|
+
var MAX_DIM = 1200;
|
|
134
|
+
var FALLBACK_W = 400;
|
|
135
|
+
var FALLBACK_H = 300;
|
|
136
|
+
function containerDimsForBbox(bbox) {
|
|
137
|
+
const [xmin, ymax, xmax, ymin] = bbox;
|
|
138
|
+
const w = Math.abs(xmax - xmin);
|
|
139
|
+
const h = Math.abs(ymax - ymin);
|
|
140
|
+
if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {
|
|
141
|
+
return { width: FALLBACK_W, height: FALLBACK_H };
|
|
142
|
+
}
|
|
143
|
+
let width = w * PIXELS_PER_UNIT;
|
|
144
|
+
let height = h * PIXELS_PER_UNIT;
|
|
145
|
+
const maxAxis = Math.max(width, height);
|
|
146
|
+
if (maxAxis > MAX_DIM) {
|
|
147
|
+
const ratio = MAX_DIM / maxAxis;
|
|
148
|
+
width *= ratio;
|
|
149
|
+
height *= ratio;
|
|
150
|
+
}
|
|
151
|
+
const minAxis = Math.min(width, height);
|
|
152
|
+
if (minAxis < MIN_DIM) {
|
|
153
|
+
const ratio = MIN_DIM / minAxis;
|
|
154
|
+
width *= ratio;
|
|
155
|
+
height *= ratio;
|
|
156
|
+
}
|
|
157
|
+
return { width: Math.round(width), height: Math.round(height) };
|
|
158
|
+
}
|
|
159
|
+
function autoFitBboxFromBoard(board, aspect) {
|
|
160
|
+
const objs = board?.objectsList;
|
|
161
|
+
if (!Array.isArray(objs)) return;
|
|
162
|
+
const points = [];
|
|
163
|
+
const circles = [];
|
|
164
|
+
for (const o of objs) {
|
|
165
|
+
if (o?.elementClass === 1 && typeof o.X === "function" && typeof o.Y === "function") {
|
|
166
|
+
const x = o.X(), y = o.Y();
|
|
167
|
+
if (Number.isFinite(x) && Number.isFinite(y)) points.push([x, y]);
|
|
168
|
+
} else if (o?.elementClass === 3 && o.center?.X && typeof o.Radius === "function") {
|
|
169
|
+
const cx = o.center.X(), cy = o.center.Y(), r = o.Radius();
|
|
170
|
+
if (Number.isFinite(cx) && Number.isFinite(cy) && Number.isFinite(r)) {
|
|
171
|
+
circles.push({ cx, cy, r });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const bbox = computeAutoFitBbox(points, circles, aspect);
|
|
176
|
+
if (!bbox) return;
|
|
177
|
+
try {
|
|
178
|
+
board.setBoundingBox(bbox);
|
|
179
|
+
if (typeof board.update === "function") board.update();
|
|
180
|
+
if (typeof board.fullUpdate === "function") board.fullUpdate();
|
|
181
|
+
} catch {
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function applyRadialLabelOffsets(board) {
|
|
185
|
+
const objs = board?.objectsList;
|
|
186
|
+
if (!Array.isArray(objs)) return;
|
|
187
|
+
const pts = [];
|
|
188
|
+
for (const o of objs) {
|
|
189
|
+
if (o?.elementClass === 1 && typeof o.X === "function" && o.label) {
|
|
190
|
+
const x = o.X(), y = o.Y();
|
|
191
|
+
if (Number.isFinite(x) && Number.isFinite(y)) pts.push({ id: o.id, x, y, el: o });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const offsets = radialLabelOffsets(pts.map((p) => ({ id: p.id, x: p.x, y: p.y })));
|
|
195
|
+
if (offsets.size === 0) return;
|
|
196
|
+
for (const p of pts) {
|
|
197
|
+
const off = offsets.get(p.id);
|
|
198
|
+
if (!off) continue;
|
|
199
|
+
try {
|
|
200
|
+
p.el.setAttribute({ label: { offset: off } });
|
|
201
|
+
} catch {
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
if (typeof board.update === "function") board.update();
|
|
206
|
+
} catch {
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function isDefaultBbox(bbox) {
|
|
210
|
+
const d = DEFAULT_VIEW_2D.bbox;
|
|
211
|
+
return bbox.length === 4 && bbox[0] === d[0] && bbox[1] === d[1] && bbox[2] === d[2] && bbox[3] === d[3];
|
|
212
|
+
}
|
|
213
|
+
async function renderGeometrySvgFromState(jsonState) {
|
|
214
|
+
const state = deserializeBoard(jsonState);
|
|
215
|
+
const view = state.meta.domain === "2d" ? state.meta.view : DEFAULT_VIEW_2D;
|
|
216
|
+
const bbox = view.bbox;
|
|
217
|
+
const shouldAutoFit = isDefaultBbox(bbox);
|
|
218
|
+
const palette = paletteFor(false);
|
|
219
|
+
const dims = containerDimsForBbox(bbox);
|
|
220
|
+
const { svgString } = await renderJsxgOffscreen({
|
|
221
|
+
bbox,
|
|
222
|
+
dims,
|
|
223
|
+
axis: view.showAxis,
|
|
224
|
+
grid: view.showGrid,
|
|
225
|
+
keepAspectRatio: true,
|
|
226
|
+
applyOptions: (JXG) => {
|
|
227
|
+
const opts = JXG.Options;
|
|
228
|
+
if (!opts) return;
|
|
229
|
+
opts.text = opts.text || {};
|
|
230
|
+
opts.text.display = "internal";
|
|
231
|
+
opts.text.useASCIIMathML = false;
|
|
232
|
+
opts.text.useMathJax = false;
|
|
233
|
+
opts.text.useKatex = false;
|
|
234
|
+
opts.text.strokeColor = palette.label;
|
|
235
|
+
opts.label = opts.label || {};
|
|
236
|
+
opts.label.display = "internal";
|
|
237
|
+
opts.label.strokeColor = palette.label;
|
|
238
|
+
opts.axis = opts.axis || {};
|
|
239
|
+
opts.axis.strokeColor = palette.axis;
|
|
240
|
+
opts.grid = opts.grid || {};
|
|
241
|
+
opts.grid.strokeColor = palette.grid;
|
|
242
|
+
},
|
|
243
|
+
setup: (board) => {
|
|
244
|
+
const store = createStore(state);
|
|
245
|
+
const renderer = new JxgRenderer(store, board);
|
|
246
|
+
if (shouldAutoFit) {
|
|
247
|
+
autoFitBboxFromBoard(board, dims.width / dims.height);
|
|
248
|
+
applyRadialLabelOffsets(board);
|
|
249
|
+
}
|
|
250
|
+
return renderer;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return svgString;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/stamps/geometry-2d/types.ts
|
|
257
|
+
function isGeometryCustomData(data) {
|
|
258
|
+
if (!data || typeof data !== "object") return false;
|
|
259
|
+
const d = data;
|
|
260
|
+
return d.kind === "geometry" && d.version === 1 && typeof d.jsonState === "string";
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export { deserializeBoard, isGeometryCustomData, renderGeometrySvgFromState, serializeBoard };
|
|
264
|
+
//# sourceMappingURL=chunk-AYJPOHCI.mjs.map
|
|
265
|
+
//# sourceMappingURL=chunk-AYJPOHCI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/stamps/geometry-2d/serialize.ts","../src/stamps/geometry-2d/autoFitBbox.ts","../src/stamps/geometry-2d/labelLayout.ts","../src/stamps/geometry-2d/render.ts","../src/stamps/geometry-2d/types.ts"],"names":[],"mappings":"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","file":"chunk-AYJPOHCI.mjs","sourcesContent":["// src/stamps/geometry-2d/serialize.ts\n//\n// Sau Tier D PR 3: customData.jsonState chỉ chứa `JSON.stringify(state)`\n// (không còn envelope `{version, bbox, state, showAxis, showGrid}`).\n// View info (bbox/axis/grid) nằm trong `state.meta.view` (View2D shape).\n\nimport { serializeScene, deserializeScene } from '../shared/serializeScene';\nimport type { State, View2D } from '../../core/scene';\n\nexport function serializeBoard(state: State, view: View2D): string {\n const withView: State = {\n ...state,\n meta: { domain: '2d', version: state.meta.version, view },\n };\n return serializeScene(withView);\n}\n\nexport function deserializeBoard(raw: string): State {\n return deserializeScene('2d', raw);\n}\n","// Pure geometry helpers for auto-fitting an AI-generated figure into a viewport.\n//\n// Two concerns, both visual-quality fixes:\n// 1. Outlier-robust extent — a single far-flung point or an oversized circle\n// must not compress the main cluster into a sliver (eval cau-13, cau-04).\n// We use Tukey IQR fences per axis to trim statistical outliers.\n// 2. Aspect correction — the offscreen container is sized from the DEFAULT\n// square bbox, so the fitted bbox must be expanded to the same aspect or\n// JSXGraph's setBoundingBox stretches the units → circles become ellipses\n// (eval cau-08). We grow the shorter axis (never shrink) so everything in\n// the robust extent stays visible.\n\n/**\n * Robust [min, max] of a sample using Tukey fences (Q1 - k·IQR, Q3 + k·IQR).\n * Values outside the fence are dropped before taking min/max. With no outliers\n * this returns the raw [min, max]. For < 4 samples IQR is meaningless → raw range.\n */\nexport function robustRange(values: number[], k = 1.5): [number, number] {\n const n = values.length;\n if (n === 0) return [0, 0];\n const sorted = [...values].sort((a, b) => a - b);\n if (n < 4) return [sorted[0], sorted[n - 1]];\n const quantile = (p: number): number => {\n const idx = (n - 1) * p;\n const lo = Math.floor(idx);\n const hi = Math.ceil(idx);\n if (lo === hi) return sorted[lo];\n return sorted[lo] + (sorted[hi] - sorted[lo]) * (idx - lo);\n };\n const q1 = quantile(0.25);\n const q3 = quantile(0.75);\n const iqr = q3 - q1;\n const fenceLo = q1 - k * iqr;\n const fenceHi = q3 + k * iqr;\n let min = Infinity;\n let max = -Infinity;\n for (const v of sorted) {\n if (v < fenceLo || v > fenceHi) continue;\n if (v < min) min = v;\n if (v > max) max = v;\n }\n if (!Number.isFinite(min) || !Number.isFinite(max)) return [sorted[0], sorted[n - 1]];\n return [min, max];\n}\n\nexport interface CircleExtent {\n cx: number;\n cy: number;\n r: number;\n}\n\n// A circle whose radius exceeds this multiple of the point-cluster diagonal is\n// treated as an oversized outlier and excluded from the fit (it still draws,\n// just clipped). Keeps a normal circumcircle in-frame while preventing a single\n// degenerate giant circle from compressing the whole figure (eval cau-13).\nconst CIRCLE_MAX_FACTOR = 1.0;\n\n/**\n * Compute a JSXGraph bbox `[xmin, ymax, xmax, ymin]` fitted to the figure.\n *\n * Points are reduced to a robust extent via Tukey IQR fences (trims stray\n * intersection points that fly off to huge coords). Circles are included WHOLE\n * (never per-edge trimmed — a clipped circle looks broken) unless a circle is\n * egregiously larger than the point cluster, in which case it is excluded. The\n * result is padded and expanded to `aspect` (= container width / height) so\n * units stay square (round circles). Returns null when there is no geometry.\n */\nexport function computeAutoFitBbox(\n points: ReadonlyArray<readonly [number, number]>,\n circles: ReadonlyArray<CircleExtent>,\n aspect: number,\n padPct = 0.12,\n): [number, number, number, number] | null {\n const xs = points.map((p) => p[0]).filter(Number.isFinite);\n const ys = points.map((p) => p[1]).filter(Number.isFinite);\n\n let xmin = Infinity, xmax = -Infinity, ymin = Infinity, ymax = -Infinity;\n let clusterDiag = 0;\n if (xs.length >= 2 && ys.length >= 2) {\n [xmin, xmax] = robustRange(xs);\n [ymin, ymax] = robustRange(ys);\n clusterDiag = Math.hypot(xmax - xmin, ymax - ymin);\n }\n\n for (const c of circles) {\n if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy) || !Number.isFinite(c.r)) continue;\n // Exclude an oversized circle only when we have a point cluster to compare to.\n if (clusterDiag > 0 && c.r > CIRCLE_MAX_FACTOR * clusterDiag) continue;\n xmin = Math.min(xmin, c.cx - c.r); xmax = Math.max(xmax, c.cx + c.r);\n ymin = Math.min(ymin, c.cy - c.r); ymax = Math.max(ymax, c.cy + c.r);\n }\n\n if (!Number.isFinite(xmin) || !Number.isFinite(xmax) || !Number.isFinite(ymin) || !Number.isFinite(ymax)) {\n return null;\n }\n let w = xmax - xmin;\n let h = ymax - ymin;\n\n // Degenerate (all coincident / fully collinear on one axis): floor to 1 unit.\n if (w < 0.5) { const cx = (xmin + xmax) / 2; xmin = cx - 0.5; xmax = cx + 0.5; w = 1; }\n if (h < 0.5) { const cy = (ymin + ymax) / 2; ymin = cy - 0.5; ymax = cy + 0.5; h = 1; }\n\n const padX = w * padPct;\n const padY = h * padPct;\n xmin -= padX; xmax += padX; ymin -= padY; ymax += padY;\n w = xmax - xmin; h = ymax - ymin;\n\n // Expand the shorter axis so width/height matches the container aspect.\n const curAspect = w / h;\n if (curAspect < aspect) {\n const newW = h * aspect;\n const cx = (xmin + xmax) / 2;\n xmin = cx - newW / 2; xmax = cx + newW / 2;\n } else if (curAspect > aspect) {\n const newH = w / aspect;\n const cy = (ymin + ymax) / 2;\n ymin = cy - newH / 2; ymax = cy + newH / 2;\n }\n\n return [xmin, ymax, xmax, ymin];\n}\n","// Anti-collision label placement for AI-generated figures.\n//\n// JSXGraph places every point label at a fixed [10,10] pixel offset (up-right).\n// When points cluster, labels overlap and overlap interior lines. We push each\n// label radially OUTWARD from the figure centroid: points on the left get a\n// left offset, points on the right get a right offset, etc. Offsets are in the\n// SAME sign convention as JSXGraph's label `offset` attribute (it negates the\n// y internally for screen space), so [dirX·R, dirY·R] in math coords maps\n// directly to a screen offset away from the centroid.\n\nexport interface LabeledPoint {\n id: string;\n x: number;\n y: number;\n}\n\nexport function radialLabelOffsets(\n points: LabeledPoint[],\n R = 14,\n): Map<string, [number, number]> {\n const out = new Map<string, [number, number]>();\n if (points.length < 2) return out;\n\n const cx = points.reduce((s, p) => s + p.x, 0) / points.length;\n const cy = points.reduce((s, p) => s + p.y, 0) / points.length;\n\n for (const p of points) {\n let dx = p.x - cx;\n let dy = p.y - cy;\n const len = Math.hypot(dx, dy);\n if (len < 1e-9) {\n // Point sits on the centroid → no meaningful direction; push up.\n dx = 0;\n dy = 1;\n } else {\n dx /= len;\n dy /= len;\n }\n out.set(p.id, [Math.round(dx * R), Math.round(dy * R)]);\n }\n return out;\n}\n","import { deserializeBoard } from './serialize';\nimport { paletteFor } from './editor/theme';\nimport { createStore } from '../../core/scene';\nimport { DEFAULT_VIEW_2D } from '../../core/scene/types';\nimport { JxgRenderer } from '../../core/scene/render/JxgRenderer';\nimport { renderJsxgOffscreen } from '../shared/jxgOffscreenRender';\nimport { computeAutoFitBbox } from './autoFitBbox';\nimport { radialLabelOffsets } from './labelLayout';\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 * Container dimensions phải MATCH aspect ratio của bbox (đã được editor lưu\n * sau khi JSXGraph adjust với keepAspectRatio:true). Trước đây hardcode\n * 400×300 + keepAspectRatio:false làm shape bị kéo dãn (circle thành ellipse,\n * góc vuông lệch) khi bbox không 4:3 → ảnh hiển thị khác với editor lúc\n * double-click. Fix: tính container W/H từ bbox + keepAspectRatio:true để\n * SVG output khớp với view trong editor.\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 */\n\nconst PIXELS_PER_UNIT = 20;\nconst MIN_DIM = 100;\nconst MAX_DIM = 1200;\nconst FALLBACK_W = 400;\nconst FALLBACK_H = 300;\n\nexport function containerDimsForBbox(bbox: [number, number, number, number]): { width: number; height: number } {\n const [xmin, ymax, xmax, ymin] = bbox;\n const w = Math.abs(xmax - xmin);\n const h = Math.abs(ymax - ymin);\n if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {\n return { width: FALLBACK_W, height: FALLBACK_H };\n }\n let width = w * PIXELS_PER_UNIT;\n let height = h * PIXELS_PER_UNIT;\n const maxAxis = Math.max(width, height);\n if (maxAxis > MAX_DIM) {\n const ratio = MAX_DIM / maxAxis;\n width *= ratio;\n height *= ratio;\n }\n const minAxis = Math.min(width, height);\n if (minAxis < MIN_DIM) {\n const ratio = MIN_DIM / minAxis;\n width *= ratio;\n height *= ratio;\n }\n return { width: Math.round(width), height: Math.round(height) };\n}\n\n/**\n * Auto-fit board bbox sau khi entities đã render. Thu thập toạ độ point + 4\n * điểm biên của mỗi circle, đưa qua `computeAutoFitBbox` (Tukey IQR trim\n * outlier + expand theo aspect container) rồi gọi setBoundingBox.\n *\n * Áp dụng khi state.meta.view.bbox còn là DEFAULT_VIEW_2D — i.e. AI-generated\n * figure chưa được editor zoom/pan. Stamp đã edit có bbox riêng của user, giữ\n * nguyên (consumer expectation: re-render khớp với view editor lúc save).\n *\n * `aspect` = container width/height. computeAutoFitBbox expand bbox về đúng\n * aspect này nên setBoundingBox (keepAspectRatio mặc định) cho units vuông →\n * circle tròn (không méo thành ellipse).\n */\nfunction autoFitBboxFromBoard(board: any, aspect: number): void {\n const objs = board?.objectsList;\n if (!Array.isArray(objs)) return;\n const points: [number, number][] = [];\n const circles: { cx: number; cy: number; r: number }[] = [];\n for (const o of objs) {\n // OBJECT_CLASS_POINT = 1\n if (o?.elementClass === 1 && typeof o.X === 'function' && typeof o.Y === 'function') {\n const x = o.X(), y = o.Y();\n if (Number.isFinite(x) && Number.isFinite(y)) points.push([x, y]);\n } else if (o?.elementClass === 3 && o.center?.X && typeof o.Radius === 'function') {\n // OBJECT_CLASS_CIRCLE\n const cx = o.center.X(), cy = o.center.Y(), r = o.Radius();\n if (Number.isFinite(cx) && Number.isFinite(cy) && Number.isFinite(r)) {\n circles.push({ cx, cy, r });\n }\n }\n }\n const bbox = computeAutoFitBbox(points, circles, aspect);\n if (!bbox) return;\n try {\n board.setBoundingBox(bbox);\n if (typeof board.update === 'function') board.update();\n if (typeof board.fullUpdate === 'function') board.fullUpdate();\n } catch { /* ignore */ }\n}\n\n/**\n * Đẩy label điểm ra xa centroid (radial) để giảm chồng nhãn. Chỉ chạy cho\n * AI-generated figure (shouldAutoFit) — stamp user-edit giữ layout nhãn mặc định.\n */\nfunction applyRadialLabelOffsets(board: any): void {\n const objs = board?.objectsList;\n if (!Array.isArray(objs)) return;\n const pts: { id: string; x: number; y: number; el: any }[] = [];\n for (const o of objs) {\n if (o?.elementClass === 1 && typeof o.X === 'function' && o.label) {\n const x = o.X(), y = o.Y();\n if (Number.isFinite(x) && Number.isFinite(y)) pts.push({ id: o.id, x, y, el: o });\n }\n }\n const offsets = radialLabelOffsets(pts.map((p) => ({ id: p.id, x: p.x, y: p.y })));\n if (offsets.size === 0) return;\n for (const p of pts) {\n const off = offsets.get(p.id);\n if (!off) continue;\n try { p.el.setAttribute({ label: { offset: off } }); } catch { /* ignore */ }\n }\n try {\n if (typeof board.update === 'function') board.update();\n } catch { /* ignore */ }\n}\n\nfunction isDefaultBbox(bbox: readonly number[]): boolean {\n const d = DEFAULT_VIEW_2D.bbox;\n return bbox.length === 4 && bbox[0] === d[0] && bbox[1] === d[1] && bbox[2] === d[2] && bbox[3] === d[3];\n}\n\nexport async function renderGeometrySvgFromState(jsonState: string): Promise<string> {\n const state = deserializeBoard(jsonState);\n const view = state.meta.domain === '2d' ? state.meta.view : DEFAULT_VIEW_2D;\n const bbox = view.bbox as [number, number, number, number];\n const shouldAutoFit = isDefaultBbox(bbox);\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 dims = containerDimsForBbox(bbox);\n const { svgString } = await renderJsxgOffscreen({\n bbox,\n dims,\n axis: view.showAxis,\n grid: view.showGrid,\n keepAspectRatio: true,\n applyOptions: (JXG) => {\n \n const opts = (JXG as any).Options;\n if (!opts) return;\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 setup: (board) => {\n const store = createStore(state);\n const renderer = new JxgRenderer(store, board);\n if (shouldAutoFit) {\n autoFitBboxFromBoard(board, dims.width / dims.height);\n applyRadialLabelOffsets(board);\n }\n return renderer;\n },\n });\n return svgString;\n}\n","import type { BaseStampCustomData } from '../shared/types';\n\nexport interface GeometryCustomData extends BaseStampCustomData {\n kind: 'geometry';\n version: 1;\n jsonState: string;\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,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { DEFAULT_THEME_2D } from './chunk-
|
|
2
|
+
import { DEFAULT_THEME_2D } from './chunk-SZDAS7LK.mjs';
|
|
3
3
|
|
|
4
4
|
// src/stamps/graph-2d/editor/theme.ts
|
|
5
5
|
var GRAPH_THEME_LIGHT = {
|
|
@@ -19,5 +19,5 @@ function paletteFor(isDark) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export { paletteFor };
|
|
22
|
-
//# sourceMappingURL=chunk-
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
22
|
+
//# sourceMappingURL=chunk-BNBOIDO5.mjs.map
|
|
23
|
+
//# sourceMappingURL=chunk-BNBOIDO5.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stamps/graph-2d/editor/theme.ts"],"names":[],"mappings":";;;AAIO,IAAM,iBAAA,GAA6B;AAAA,EACxC,GAAG;AACL,CAAA;AAEO,IAAM,gBAAA,GAA4B;AAAA,EACvC,GAAG,gBAAA;AAAA,EACH,MAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAM,SAAA;AAAA,EACN,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,SAAA;AAAA,EACN,SAAA,EAAW;AACb,CAAA;AAEO,SAAS,WAAW,MAAA,EAA0B;AACnD,EAAA,OAAO,SAAS,gBAAA,GAAmB,iBAAA;AACrC","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/stamps/graph-2d/editor/theme.ts"],"names":[],"mappings":";;;AAIO,IAAM,iBAAA,GAA6B;AAAA,EACxC,GAAG;AACL,CAAA;AAEO,IAAM,gBAAA,GAA4B;AAAA,EACvC,GAAG,gBAAA;AAAA,EACH,MAAA,EAAQ,SAAA;AAAA,EACR,IAAA,EAAM,SAAA;AAAA,EACN,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,IAAA,EAAM,SAAA;AAAA,EACN,SAAA,EAAW;AACb,CAAA;AAEO,SAAS,WAAW,MAAA,EAA0B;AACnD,EAAA,OAAO,SAAS,gBAAA,GAAmB,iBAAA;AACrC","file":"chunk-BNBOIDO5.mjs","sourcesContent":["// src/stamps/graph-2d/editor/theme.ts\nimport type { Theme2D } from '../../../core/scene/render/types2d';\nimport { DEFAULT_THEME_2D } from '../../../core/scene/render/types2d';\n\nexport const GRAPH_THEME_LIGHT: Theme2D = {\n ...DEFAULT_THEME_2D,\n};\n\nexport const GRAPH_THEME_DARK: Theme2D = {\n ...DEFAULT_THEME_2D,\n stroke: '#f1f5f9',\n fill: '#3b82f6',\n label: '#f1f5f9',\n axis: '#475569',\n grid: '#334155',\n pointFill: '#93c5fd',\n};\n\nexport function paletteFor(isDark: boolean): Theme2D {\n return isDark ? GRAPH_THEME_DARK : GRAPH_THEME_LIGHT;\n}\n\nexport const FUNCTION_COLORS = [\n '#2563eb', '#dc2626', '#16a34a', '#9333ea',\n '#ea580c', '#0891b2', '#db2777', '#65a30d',\n] as const;\n\nexport const FUNCTION_NAMES = ['f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'] as const;\nexport const PARAMETER_NAMES = ['a', 'b', 'c', 'd', 'k', 't', 'm', 'n'] as const;\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { paletteFor } from './chunk-
|
|
3
|
-
import { JxgRenderer } from './chunk-
|
|
2
|
+
import { paletteFor } from './chunk-BNBOIDO5.mjs';
|
|
3
|
+
import { JxgRenderer } from './chunk-SZDAS7LK.mjs';
|
|
4
4
|
import { renderJsxgOffscreen } from './chunk-ICR4CVOE.mjs';
|
|
5
5
|
import { createStore } from './chunk-IHUFOV7L.mjs';
|
|
6
6
|
|
|
@@ -53,5 +53,5 @@ async function renderGraphSvgFromState(state, _isDark, width = DEFAULT_WIDTH, he
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export { renderGraphSvgFromState };
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
57
|
-
//# sourceMappingURL=chunk-
|
|
56
|
+
//# sourceMappingURL=chunk-CXHNVYMD.mjs.map
|
|
57
|
+
//# sourceMappingURL=chunk-CXHNVYMD.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stamps/graph-2d/render.ts"],"names":[],"mappings":";;;;;;AAUA,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,cAAA,GAAiB,GAAA;AAEvB,eAAsB,wBACpB,KAAA,EACA,OAAA,EACA,KAAA,GAAQ,aAAA,EACR,SAAS,cAAA,EACQ;AACjB,EAAA,MAAM,OAAA,GAAU,WAAW,KAAK,CAAA;AAChC,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,MAAA,KAAW,SAAA,GAAY,KAAK,IAAA,GAAO,IAAA;AACrD,EAAA,MAAM,IAAA,GAAyC;AAAA,IAC7C,MAAM,IAAA,IAAQ,GAAA;AAAA,IACd,MAAM,IAAA,IAAQ,EAAA;AAAA,IACd,MAAM,IAAA,IAAQ,EAAA;AAAA,IACd,MAAM,IAAA,IAAQ;AAAA,GAChB;AACA,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,mBAAA,CAAoB;AAAA,MAC9C,IAAA;AAAA,MACA,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,MACtB,IAAA,EAAM,MAAM,QAAA,IAAY,IAAA;AAAA,MACxB,IAAA,EAAM,MAAM,QAAA,IAAY,IAAA;AAAA,MACxB,eAAA,EAAiB,KAAA;AAAA,MACjB,YAAA,EAAc,CAAC,GAAA,KAAQ;AAErB,QAAA,MAAM,OAAQ,GAAA,CAAY,OAAA;AAC1B,QAAA,IAAI,CAAC,IAAA,EAAM;AACX,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,KAAK,OAAA,GAAU,UAAA;AACpB,QAAA,IAAA,CAAK,KAAK,cAAA,GAAiB,KAAA;AAC3B,QAAA,IAAA,CAAK,KAAK,UAAA,GAAa,KAAA;AACvB,QAAA,IAAA,CAAK,KAAK,QAAA,GAAW,KAAA;AACrB,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,KAAA;AAChC,QAAA,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAC5B,QAAA,IAAA,CAAK,MAAM,OAAA,GAAU,UAAA;AACrB,QAAA,IAAA,CAAK,KAAA,CAAM,cAAc,OAAA,CAAQ,KAAA;AACjC,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,IAAA;AAChC,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,IAAA;AAAA,MAClC,CAAA;AAAA,MACA,KAAA,EAAO,CAAC,KAAA,KAAU;AAChB,QAAA,MAAM,KAAA,GAAQ,YAAY,KAAK,CAAA;AAC/B,QAAA,OAAO,IAAI,WAAA,CAAY,KAAA,EAAO,KAAK,CAAA;AAAA,MACrC;AAAA,KACD,CAAA;AACD,IAAA,OAAO,SAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,EAAA;AAAA,EACT;AACF","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/stamps/graph-2d/render.ts"],"names":[],"mappings":";;;;;;AAUA,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,cAAA,GAAiB,GAAA;AAEvB,eAAsB,wBACpB,KAAA,EACA,OAAA,EACA,KAAA,GAAQ,aAAA,EACR,SAAS,cAAA,EACQ;AACjB,EAAA,MAAM,OAAA,GAAU,WAAW,KAAK,CAAA;AAChC,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,MAAA,KAAW,SAAA,GAAY,KAAK,IAAA,GAAO,IAAA;AACrD,EAAA,MAAM,IAAA,GAAyC;AAAA,IAC7C,MAAM,IAAA,IAAQ,GAAA;AAAA,IACd,MAAM,IAAA,IAAQ,EAAA;AAAA,IACd,MAAM,IAAA,IAAQ,EAAA;AAAA,IACd,MAAM,IAAA,IAAQ;AAAA,GAChB;AACA,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,mBAAA,CAAoB;AAAA,MAC9C,IAAA;AAAA,MACA,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,MACtB,IAAA,EAAM,MAAM,QAAA,IAAY,IAAA;AAAA,MACxB,IAAA,EAAM,MAAM,QAAA,IAAY,IAAA;AAAA,MACxB,eAAA,EAAiB,KAAA;AAAA,MACjB,YAAA,EAAc,CAAC,GAAA,KAAQ;AAErB,QAAA,MAAM,OAAQ,GAAA,CAAY,OAAA;AAC1B,QAAA,IAAI,CAAC,IAAA,EAAM;AACX,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,KAAK,OAAA,GAAU,UAAA;AACpB,QAAA,IAAA,CAAK,KAAK,cAAA,GAAiB,KAAA;AAC3B,QAAA,IAAA,CAAK,KAAK,UAAA,GAAa,KAAA;AACvB,QAAA,IAAA,CAAK,KAAK,QAAA,GAAW,KAAA;AACrB,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,KAAA;AAChC,QAAA,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAC5B,QAAA,IAAA,CAAK,MAAM,OAAA,GAAU,UAAA;AACrB,QAAA,IAAA,CAAK,KAAA,CAAM,cAAc,OAAA,CAAQ,KAAA;AACjC,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,IAAA;AAChC,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC1B,QAAA,IAAA,CAAK,IAAA,CAAK,cAAc,OAAA,CAAQ,IAAA;AAAA,MAClC,CAAA;AAAA,MACA,KAAA,EAAO,CAAC,KAAA,KAAU;AAChB,QAAA,MAAM,KAAA,GAAQ,YAAY,KAAK,CAAA;AAC/B,QAAA,OAAO,IAAI,WAAA,CAAY,KAAA,EAAO,KAAK,CAAA;AAAA,MACrC;AAAA,KACD,CAAA;AACD,IAAA,OAAO,SAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,EAAA;AAAA,EACT;AACF","file":"chunk-CXHNVYMD.mjs","sourcesContent":["// src/stamps/graph-2d/render.ts\n// Offscreen SVG export từ graph2d State. Dùng cho insert/restore stamp.\n//\n// LƯU Ý: Luôn dùng light palette — Excalidraw tự invert trong dark mode.\nimport type { State } from '../../core/scene/types';\nimport { createStore } from '../../core/scene/store';\nimport { JxgRenderer } from '../../core/scene/render/JxgRenderer';\nimport { paletteFor } from './editor/theme';\nimport { renderJsxgOffscreen } from '../shared/jxgOffscreenRender';\n\nconst DEFAULT_WIDTH = 600;\nconst DEFAULT_HEIGHT = 400;\n\nexport async function renderGraphSvgFromState(\n state: State,\n _isDark: boolean,\n width = DEFAULT_WIDTH,\n height = DEFAULT_HEIGHT,\n): Promise<string> {\n const palette = paletteFor(false);\n const meta = state.meta;\n const view = meta.domain === 'graph2d' ? meta.view : null;\n const bbox: [number, number, number, number] = [\n view?.xMin ?? -10,\n view?.yMax ?? 10,\n view?.xMax ?? 10,\n view?.yMin ?? -10,\n ];\n try {\n const { svgString } = await renderJsxgOffscreen({\n bbox,\n dims: { width, height },\n axis: view?.showAxis ?? true,\n grid: view?.showGrid ?? true,\n keepAspectRatio: false,\n applyOptions: (JXG) => {\n \n const opts = (JXG as any).Options;\n if (!opts) return;\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 setup: (board) => {\n const store = createStore(state);\n return new JxgRenderer(store, board);\n },\n });\n return svgString;\n } catch {\n // Match old contract: callers expect '' when no SVG produced.\n return '';\n }\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { isGeometry3DCustomData, renderGeometry3DSvgFromState } from './chunk-
|
|
2
|
+
import { isGeometry3DCustomData, renderGeometry3DSvgFromState } from './chunk-KYMBUTPO.mjs';
|
|
3
3
|
import { svgToStampFile } from './chunk-5UTGXHLJ.mjs';
|
|
4
4
|
import { lazy } from 'react';
|
|
5
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
var Geometry3DStampHost = lazy(
|
|
8
|
-
() => import('./host-
|
|
8
|
+
() => import('./host-M26FS244.mjs').then((m) => ({ default: m.Geometry3DStampHost }))
|
|
9
9
|
);
|
|
10
10
|
var Geometry3DIcon = /* @__PURE__ */ jsxs(
|
|
11
11
|
"svg",
|
|
@@ -57,5 +57,5 @@ var geometry3dStamp = {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
export { geometry3dStamp };
|
|
60
|
-
//# sourceMappingURL=chunk-
|
|
61
|
-
//# sourceMappingURL=chunk-
|
|
60
|
+
//# sourceMappingURL=chunk-D5JLJ3PT.mjs.map
|
|
61
|
+
//# sourceMappingURL=chunk-D5JLJ3PT.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stamps/geometry-3d/index.tsx"],"names":[],"mappings":";;;;;AAgBA,IAAM,mBAAA,GAAsB,IAAA;AAAA,EAAK,MAC/B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,mBAAA,EAAoB,CAAE;AACnE,CAAA;AAEA,IAAM,cAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAGZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,2BAAA,EAA4B,CAAA;AAAA,sBAEpC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,sBAEnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA;AAAA;AACxC,CAAA;AAGK,IAAM,eAAA,GAAmD;AAAA,EAC9D,IAAA,EAAM,YAAA;AAAA,EACN,YAAA,EAAc,IAAA;AAAA,EACd,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,YAAA,EAAc,gBAAA;AAAA,EACd,WAAA,EAAa,cAAA;AAAA,EACb,aAAA,EAAe,0BAAA;AAAA,EACf,iBAAA,EAAmB,sBAAA;AAAA,EACnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAI,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,MAAM,mFAA2E,CAAA;AAAA,IAC7F;AACA,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAAA,EACA,yBAAA,EAA2B,OAAO,OAAA,KAA+C;AAC/E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,QAAQ,CAAC,MAAA,IAAU,CAAC,sBAAA,CAAuB,IAAI,GAAG,OAAO,IAAA;AAC9D,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,MAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,IAAA,EAAM;AACR","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/stamps/geometry-3d/index.tsx"],"names":[],"mappings":";;;;;AAgBA,IAAM,mBAAA,GAAsB,IAAA;AAAA,EAAK,MAC/B,OAAO,qBAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,mBAAA,EAAoB,CAAE;AACnE,CAAA;AAEA,IAAM,cAAA,mBACJ,IAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,KAAA,EAAM,IAAA;AAAA,IACN,MAAA,EAAO,IAAA;AAAA,IACP,OAAA,EAAQ,WAAA;AAAA,IACR,IAAA,EAAK,MAAA;AAAA,IACL,MAAA,EAAO,cAAA;AAAA,IACP,WAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAc,OAAA;AAAA,IACd,cAAA,EAAe,OAAA;AAAA,IACf,aAAA,EAAY,MAAA;AAAA,IAGZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,2BAAA,EAA4B,CAAA;AAAA,sBAEpC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,sBAEnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA;AAAA;AACxC,CAAA;AAGK,IAAM,eAAA,GAAmD;AAAA,EAC9D,IAAA,EAAM,YAAA;AAAA,EACN,YAAA,EAAc,IAAA;AAAA,EACd,WAAA,EAAa,GAAA;AAAA,EACb,YAAA,EAAc,GAAA;AAAA,EACd,YAAA,EAAc,gBAAA;AAAA,EACd,WAAA,EAAa,cAAA;AAAA,EACb,aAAA,EAAe,0BAAA;AAAA,EACf,iBAAA,EAAmB,sBAAA;AAAA,EACnB,MAAM,wBAAwB,IAAA,EAAgC;AAC5D,IAAA,IAAI,CAAC,sBAAA,CAAuB,IAAI,CAAA,EAAG;AACjC,MAAA,MAAM,IAAI,MAAM,mFAA2E,CAAA;AAAA,IAC7F;AACA,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAAA,EACA,yBAAA,EAA2B,OAAO,OAAA,KAA+C;AAC/E,IAAA,MAAM,OAAO,OAAA,CAAQ,UAAA;AACrB,IAAA,MAAM,SAAU,OAAA,CAAuC,MAAA;AACvD,IAAA,IAAI,CAAC,QAAQ,CAAC,MAAA,IAAU,CAAC,sBAAA,CAAuB,IAAI,GAAG,OAAO,IAAA;AAC9D,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,4BAAA,CAA6B,KAAK,SAAS,CAAA;AACvE,MAAA,OAAO,cAAA,CAAe,WAAW,MAAM,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AAAA,EACA,IAAA,EAAM;AACR","file":"chunk-D5JLJ3PT.mjs","sourcesContent":["'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';\nimport { svgToStampFile } from '../shared/svgToStampFile';\n\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<Geometry3DCustomData> = {\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 || !isGeometry3DCustomData(data)) return null;\n try {\n const { svgString } = await renderGeometry3DSvgFromState(data.jsonState);\n return svgToStampFile(svgString, fileId);\n } catch {\n return null;\n }\n },\n Host: Geometry3DStampHost,\n};\n"]}
|