@codefrydev/svg-engine 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -1
- package/dist/chunk-VCDC4W3X.js +3439 -0
- package/dist/editor.cjs +2910 -1630
- package/dist/editor.d.cts +2 -4
- package/dist/editor.d.ts +2 -4
- package/dist/editor.js +1068 -433
- package/dist/index.cjs +1864 -1219
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{types-BTYLCn9x.d.cts → types-BHUCCfQX.d.cts} +12 -2
- package/dist/{types-BTYLCn9x.d.ts → types-BHUCCfQX.d.ts} +12 -2
- package/dist/wc.cjs +1 -1
- package/dist/wc.d.cts +6 -3
- package/dist/wc.d.ts +6 -3
- package/dist/wc.iife.js +10 -299
- package/dist/wc.js +1 -1
- package/package.json +13 -5
- package/dist/chunk-KRCGD3CL.js +0 -2794
package/dist/editor.js
CHANGED
|
@@ -2,13 +2,64 @@ import {
|
|
|
2
2
|
Renderer,
|
|
3
3
|
getMouseCoords,
|
|
4
4
|
snap
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VCDC4W3X.js";
|
|
6
6
|
|
|
7
7
|
// src/editor/Editor.tsx
|
|
8
8
|
import { forwardRef, useEffect as useEffect2, useImperativeHandle, useMemo as useMemo2, useState as useState2 } from "react";
|
|
9
9
|
|
|
10
10
|
// src/editor/hooks/useDrawing.ts
|
|
11
11
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
12
|
+
var MIN_DRAW_DISTANCE = 10;
|
|
13
|
+
var snapshotOriginal = (element) => {
|
|
14
|
+
const base = {
|
|
15
|
+
x1: element.x1,
|
|
16
|
+
y1: element.y1,
|
|
17
|
+
x2: element.x2,
|
|
18
|
+
y2: element.y2
|
|
19
|
+
};
|
|
20
|
+
const raw = element.cps;
|
|
21
|
+
if (raw?.length) {
|
|
22
|
+
return { ...base, cps: raw.map((p) => ({ x: p.x, y: p.y })) };
|
|
23
|
+
}
|
|
24
|
+
return base;
|
|
25
|
+
};
|
|
26
|
+
var applyDragDelta = (prev, draggingId, dx, dy, orig) => {
|
|
27
|
+
const str = String(draggingId);
|
|
28
|
+
if (str.endsWith("-start")) {
|
|
29
|
+
const rawId = str.slice(0, -"-start".length);
|
|
30
|
+
return prev.map(
|
|
31
|
+
(el) => String(el.id) === rawId ? { ...el, x1: orig.x1 + dx, y1: orig.y1 + dy } : el
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
if (str.endsWith("-end")) {
|
|
35
|
+
const rawId = str.slice(0, -"-end".length);
|
|
36
|
+
return prev.map(
|
|
37
|
+
(el) => String(el.id) === rawId ? { ...el, x2: orig.x2 + dx, y2: orig.y2 + dy } : el
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const cpMatch = str.match(/^(.*)-cp-(\d+)$/);
|
|
41
|
+
if (cpMatch && orig.cps) {
|
|
42
|
+
const rawId = cpMatch[1];
|
|
43
|
+
const cpIndex = Number(cpMatch[2]);
|
|
44
|
+
return prev.map((el) => {
|
|
45
|
+
if (String(el.id) !== rawId) return el;
|
|
46
|
+
const newCps = orig.cps.map(
|
|
47
|
+
(p, i) => i === cpIndex ? { x: p.x + dx, y: p.y + dy } : { ...p }
|
|
48
|
+
);
|
|
49
|
+
return { ...el, cps: newCps };
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return prev.map(
|
|
53
|
+
(el) => el.id === draggingId || String(el.id) === str ? {
|
|
54
|
+
...el,
|
|
55
|
+
x1: orig.x1 + dx,
|
|
56
|
+
y1: orig.y1 + dy,
|
|
57
|
+
x2: orig.x2 + dx,
|
|
58
|
+
y2: orig.y2 + dy,
|
|
59
|
+
...orig.cps ? { cps: orig.cps.map((p) => ({ x: p.x + dx, y: p.y + dy })) } : {}
|
|
60
|
+
} : el
|
|
61
|
+
);
|
|
62
|
+
};
|
|
12
63
|
var waveOscillationDefaults = (tool) => {
|
|
13
64
|
let defaultColor = "#0f172a";
|
|
14
65
|
if (["spring", "sine_wave", "wavefronts", "shm_graph"].includes(tool)) defaultColor = "#3b82f6";
|
|
@@ -74,10 +125,10 @@ var toolCreateDefaults = (tool, presetKey) => {
|
|
|
74
125
|
case "ray":
|
|
75
126
|
case "photon":
|
|
76
127
|
if (presetKey === "graph") return { color: "#0f172a", strokeWidth: 2 };
|
|
77
|
-
if (presetKey === "mechanics"
|
|
128
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2 };
|
|
78
129
|
if (presetKey === "rotation") return { color: "#ef4444", strokeWidth: 2 };
|
|
79
|
-
if (presetKey === "
|
|
80
|
-
if (presetKey === "
|
|
130
|
+
if (presetKey === "light" && (tool === "ray" || tool === "photon")) return { color: "#ef4444", strokeWidth: 2 };
|
|
131
|
+
if (presetKey === "light") return { color: "#0f172a", strokeWidth: 2 };
|
|
81
132
|
return { color: "#ef4444", strokeWidth: 2 };
|
|
82
133
|
case "lens_convex":
|
|
83
134
|
case "lens_concave":
|
|
@@ -92,7 +143,7 @@ var toolCreateDefaults = (tool, presetKey) => {
|
|
|
92
143
|
case "slit_single":
|
|
93
144
|
return { color: "#0f172a", strokeWidth: 4 };
|
|
94
145
|
case "nucleus":
|
|
95
|
-
if (presetKey === "
|
|
146
|
+
if (presetKey === "light") return { color: "#3b82f6", strokeWidth: 2, fontSize: 18 };
|
|
96
147
|
return { color: "#0f172a", strokeWidth: 2, fontSize: 18 };
|
|
97
148
|
case "energy_level":
|
|
98
149
|
return { color: "#0f172a", strokeWidth: 2, label: "n=1", energy: "-13.6 eV" };
|
|
@@ -100,13 +151,13 @@ var toolCreateDefaults = (tool, presetKey) => {
|
|
|
100
151
|
return { color: "#0f172a", strokeWidth: 2, lineStyle: "dashed" };
|
|
101
152
|
case "point":
|
|
102
153
|
if (presetKey === "graph") return { color: "#0f172a", strokeWidth: 2, fontSize: 16, label: "P" };
|
|
103
|
-
if (presetKey === "light"
|
|
154
|
+
if (presetKey === "light") return { color: "#0f172a", strokeWidth: 2, fontSize: 18, label: "P" };
|
|
104
155
|
if (presetKey === "thermo") return { color: "#0f172a", strokeWidth: 2, fontSize: 18, label: "P" };
|
|
105
156
|
return {};
|
|
106
157
|
case "text":
|
|
107
158
|
if (presetKey === "graph") return { color: "#0f172a", strokeWidth: 2, fontSize: 18, label: "Label" };
|
|
108
|
-
if (presetKey === "light"
|
|
109
|
-
if (presetKey === "mechanics"
|
|
159
|
+
if (presetKey === "light") return { color: "#0f172a", strokeWidth: 2, fontSize: 18, label: "Text" };
|
|
160
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2, fontSize: 20, label: "Label" };
|
|
110
161
|
if (presetKey === "rotation") return { color: "#1e293b", strokeWidth: 2, fontSize: 20, label: "Label" };
|
|
111
162
|
if (presetKey === "thermo") return { color: "#1e293b", strokeWidth: 2, fontSize: 18, label: "Equation/Label" };
|
|
112
163
|
return {};
|
|
@@ -141,15 +192,15 @@ var toolCreateDefaults = (tool, presetKey) => {
|
|
|
141
192
|
return {};
|
|
142
193
|
case "spring":
|
|
143
194
|
if (presetKey === "rotation") return { color: "#0f172a", strokeWidth: 2, coils: 6, lineStyle: "solid" };
|
|
144
|
-
if (presetKey === "mechanics"
|
|
195
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2 };
|
|
145
196
|
return {};
|
|
146
197
|
case "pivot":
|
|
147
198
|
if (presetKey === "rotation") return { color: "#64748b", strokeWidth: 2, size: 20, fontSize: 18 };
|
|
148
|
-
if (presetKey === "mechanics"
|
|
199
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2 };
|
|
149
200
|
return {};
|
|
150
201
|
case "pulley":
|
|
151
202
|
if (presetKey === "rotation") return { color: "#64748b", strokeWidth: 2, fontSize: 18 };
|
|
152
|
-
if (presetKey === "mechanics"
|
|
203
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2 };
|
|
153
204
|
return {};
|
|
154
205
|
case "point_mass":
|
|
155
206
|
return { color: "#ef4444", strokeWidth: 2, size: 15, fontSize: 18 };
|
|
@@ -248,18 +299,18 @@ var toolCreateDefaults = (tool, presetKey) => {
|
|
|
248
299
|
case "disk":
|
|
249
300
|
case "particle":
|
|
250
301
|
case "com":
|
|
251
|
-
if (presetKey === "mechanics"
|
|
302
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2 };
|
|
252
303
|
return {};
|
|
253
304
|
case "block":
|
|
254
305
|
case "cart":
|
|
255
|
-
if (presetKey === "mechanics"
|
|
306
|
+
if (presetKey === "mechanics") return { color: "#0f172a", strokeWidth: 2, rotation: 0 };
|
|
256
307
|
return {};
|
|
257
308
|
default:
|
|
258
309
|
return {};
|
|
259
310
|
}
|
|
260
311
|
};
|
|
261
|
-
var useDrawing = (
|
|
262
|
-
const [elements, setElements] = useState(
|
|
312
|
+
var useDrawing = (initialElements, presetKey) => {
|
|
313
|
+
const [elements, setElements] = useState(initialElements);
|
|
263
314
|
const [tool, setTool] = useState("select");
|
|
264
315
|
const [drawing, setDrawing] = useState(null);
|
|
265
316
|
const [selectedId, setSelectedId] = useState(null);
|
|
@@ -272,10 +323,17 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
272
323
|
const dragStart = useRef({ x: 0, y: 0 });
|
|
273
324
|
const originalPos = useRef(null);
|
|
274
325
|
useEffect(() => {
|
|
275
|
-
setElements(
|
|
276
|
-
|
|
326
|
+
setElements(initialElements);
|
|
327
|
+
setSelectedId(null);
|
|
328
|
+
setShowProperties(false);
|
|
329
|
+
setDrawing(null);
|
|
330
|
+
}, [initialElements]);
|
|
277
331
|
useEffect(() => {
|
|
278
332
|
const handleKeyDown = (e) => {
|
|
333
|
+
const tgt = e.target;
|
|
334
|
+
if (tgt && (tgt.tagName === "INPUT" || tgt.tagName === "TEXTAREA" || tgt.isContentEditable)) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
279
337
|
if ((e.key === "Delete" || e.key === "Backspace") && selectedId) {
|
|
280
338
|
setElements((prev) => prev.filter((el) => el.id !== selectedId));
|
|
281
339
|
setSelectedId(null);
|
|
@@ -284,6 +342,7 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
284
342
|
if (e.key === "Escape") {
|
|
285
343
|
setDrawing(null);
|
|
286
344
|
setTool("select");
|
|
345
|
+
setShowProperties(false);
|
|
287
346
|
}
|
|
288
347
|
};
|
|
289
348
|
window.addEventListener("keydown", handleKeyDown);
|
|
@@ -301,18 +360,61 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
301
360
|
setSelectedId(element.id);
|
|
302
361
|
setDraggingId(element.id);
|
|
303
362
|
dragStart.current = m;
|
|
304
|
-
originalPos.current =
|
|
363
|
+
originalPos.current = snapshotOriginal(element);
|
|
364
|
+
};
|
|
365
|
+
const onHandlePointerDown = (e, element, kind, cpIndex) => {
|
|
366
|
+
if (tool !== "select") return;
|
|
367
|
+
e.stopPropagation();
|
|
368
|
+
if (!svgRef.current) return;
|
|
369
|
+
const m = getMouseCoords(svgRef.current, e);
|
|
370
|
+
setSelectedId(element.id);
|
|
371
|
+
dragStart.current = m;
|
|
372
|
+
if (kind === "start") {
|
|
373
|
+
setDraggingId(`${element.id}-start`);
|
|
374
|
+
originalPos.current = {
|
|
375
|
+
x1: element.x1,
|
|
376
|
+
y1: element.y1,
|
|
377
|
+
x2: element.x2,
|
|
378
|
+
y2: element.y2
|
|
379
|
+
};
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (kind === "end") {
|
|
383
|
+
setDraggingId(`${element.id}-end`);
|
|
384
|
+
originalPos.current = {
|
|
385
|
+
x1: element.x1,
|
|
386
|
+
y1: element.y1,
|
|
387
|
+
x2: element.x2,
|
|
388
|
+
y2: element.y2
|
|
389
|
+
};
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (kind === "cp" && cpIndex !== void 0) {
|
|
393
|
+
const raw = element.cps;
|
|
394
|
+
const cps = raw?.length && raw.length > 0 ? raw.map((p) => ({ x: p.x, y: p.y })) : [{ x: (element.x1 + element.x2) / 2, y: Math.min(element.y1, element.y2) - 50 }];
|
|
395
|
+
setDraggingId(`${element.id}-cp-${cpIndex}`);
|
|
396
|
+
originalPos.current = {
|
|
397
|
+
x1: element.x1,
|
|
398
|
+
y1: element.y1,
|
|
399
|
+
x2: element.x2,
|
|
400
|
+
y2: element.y2,
|
|
401
|
+
cps
|
|
402
|
+
};
|
|
403
|
+
}
|
|
305
404
|
};
|
|
306
405
|
const handleMouseDown = (e) => {
|
|
307
406
|
if (!svgRef.current) return;
|
|
308
407
|
if (tool === "select") {
|
|
309
|
-
|
|
408
|
+
if (e.target === svgRef.current) {
|
|
409
|
+
setSelectedId(null);
|
|
410
|
+
setShowProperties(false);
|
|
411
|
+
}
|
|
310
412
|
return;
|
|
311
413
|
}
|
|
312
414
|
const p = getMouseCoords(svgRef.current, e);
|
|
313
415
|
const x = snap(p.x);
|
|
314
416
|
const y = snap(p.y);
|
|
315
|
-
const mechanicsSingle =
|
|
417
|
+
const mechanicsSingle = presetKey === "mechanics" && ["pivot", "com", "axes"].includes(tool);
|
|
316
418
|
const rotationSingle = presetKey === "rotation" && ["point_mass", "com_indicator", "pivot"].includes(tool);
|
|
317
419
|
const waveOscSingle = presetKey === "waveOscillation" && ["tuning_fork", "speaker", "wavefronts", "mass_box"].includes(tool);
|
|
318
420
|
const single = mechanicsSingle || rotationSingle || waveOscSingle || [
|
|
@@ -354,7 +456,7 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
354
456
|
return;
|
|
355
457
|
}
|
|
356
458
|
const defaults = toolCreateDefaults(tool, presetKey);
|
|
357
|
-
const rotationExtra =
|
|
459
|
+
const rotationExtra = presetKey === "mechanics" && (tool === "block" || tool === "cart") ? { rotation: defaults.rotation ?? 0 } : {};
|
|
358
460
|
setDrawing({
|
|
359
461
|
...defaults,
|
|
360
462
|
...rotationExtra,
|
|
@@ -370,32 +472,24 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
370
472
|
const handleMouseMove = (e) => {
|
|
371
473
|
if (!svgRef.current) return;
|
|
372
474
|
const p = getMouseCoords(svgRef.current, e);
|
|
373
|
-
if (draggingId && originalPos.current) {
|
|
475
|
+
if (draggingId != null && originalPos.current) {
|
|
374
476
|
const dx = snap(p.x - dragStart.current.x);
|
|
375
477
|
const dy = snap(p.y - dragStart.current.y);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
(el) => el.id === draggingId ? {
|
|
379
|
-
...el,
|
|
380
|
-
x1: originalPos.current.x1 + dx,
|
|
381
|
-
y1: originalPos.current.y1 + dy,
|
|
382
|
-
x2: originalPos.current.x2 + dx,
|
|
383
|
-
y2: originalPos.current.y2 + dy
|
|
384
|
-
} : el
|
|
385
|
-
)
|
|
386
|
-
);
|
|
478
|
+
const orig = originalPos.current;
|
|
479
|
+
setElements((prev) => applyDragDelta(prev, draggingId, dx, dy, orig));
|
|
387
480
|
return;
|
|
388
481
|
}
|
|
389
482
|
if (!drawing) return;
|
|
390
483
|
setDrawing({ ...drawing, x2: snap(p.x), y2: snap(p.y) });
|
|
391
484
|
};
|
|
392
485
|
const handleMouseUp = () => {
|
|
393
|
-
if (draggingId) {
|
|
486
|
+
if (draggingId != null) {
|
|
394
487
|
setDraggingId(null);
|
|
488
|
+
originalPos.current = null;
|
|
395
489
|
return;
|
|
396
490
|
}
|
|
397
491
|
if (!drawing) return;
|
|
398
|
-
if (drawing.x1
|
|
492
|
+
if (Math.abs(drawing.x1 - drawing.x2) <= MIN_DRAW_DISTANCE && Math.abs(drawing.y1 - drawing.y2) <= MIN_DRAW_DISTANCE) {
|
|
399
493
|
setDrawing(null);
|
|
400
494
|
setTool("select");
|
|
401
495
|
return;
|
|
@@ -428,6 +522,7 @@ var useDrawing = (initialElements2, presetKey) => {
|
|
|
428
522
|
selectedElement,
|
|
429
523
|
svgRef,
|
|
430
524
|
onElementMouseDown,
|
|
525
|
+
onHandlePointerDown,
|
|
431
526
|
handleMouseDown,
|
|
432
527
|
handleMouseMove,
|
|
433
528
|
handleMouseUp
|
|
@@ -605,9 +700,10 @@ var Icons = {
|
|
|
605
700
|
/* @__PURE__ */ jsx("line", { x1: "8", y1: "16", x2: "16", y2: "16", stroke: "currentColor", strokeWidth: "2" })
|
|
606
701
|
] }),
|
|
607
702
|
torsion_pendulum: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
608
|
-
/* @__PURE__ */ jsx("
|
|
609
|
-
/* @__PURE__ */ jsx("
|
|
610
|
-
/* @__PURE__ */ jsx("
|
|
703
|
+
/* @__PURE__ */ jsx("rect", { x: "5", y: "2", width: "14", height: "4", rx: "1", fill: "currentColor", opacity: "0.35" }),
|
|
704
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "6", x2: "12", y2: "15", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
705
|
+
/* @__PURE__ */ jsx("rect", { x: "8", y: "15", width: "8", height: "6", rx: "2", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
706
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "15", x2: "14", y2: "13", stroke: "currentColor", strokeWidth: "1.2" })
|
|
611
707
|
] }),
|
|
612
708
|
standing_wave: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
613
709
|
/* @__PURE__ */ jsx("path", { d: "M 2 12 Q 7 2 12 12 T 22 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
@@ -730,7 +826,16 @@ var Icons = {
|
|
|
730
826
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3", fill: "#ef4444" })
|
|
731
827
|
] }),
|
|
732
828
|
orbit: /* @__PURE__ */ jsx("ellipse", { cx: "12", cy: "12", rx: "8", ry: "4.5", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
733
|
-
resistor: /* @__PURE__ */ jsx(
|
|
829
|
+
resistor: /* @__PURE__ */ jsx(
|
|
830
|
+
"path",
|
|
831
|
+
{
|
|
832
|
+
d: "M 2 12 L 6 12 L 8 6 L 12 18 L 16 6 L 18 12 L 22 12",
|
|
833
|
+
fill: "none",
|
|
834
|
+
stroke: "#b45309",
|
|
835
|
+
strokeWidth: "2.2",
|
|
836
|
+
strokeLinejoin: "round"
|
|
837
|
+
}
|
|
838
|
+
),
|
|
734
839
|
capacitor: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
735
840
|
/* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "9", y2: "12", stroke: "currentColor", strokeWidth: "2" }),
|
|
736
841
|
/* @__PURE__ */ jsx("line", { x1: "9", y1: "6", x2: "9", y2: "18", stroke: "currentColor", strokeWidth: "2.2" }),
|
|
@@ -740,22 +845,24 @@ var Icons = {
|
|
|
740
845
|
inductor: /* @__PURE__ */ jsx("path", { d: "M 3 12 C 5 8, 7 8, 9 12 C 11 8, 13 8, 15 12 C 17 8, 19 8, 21 12", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
741
846
|
diode: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
742
847
|
/* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "8", y2: "12", stroke: "currentColor", strokeWidth: "2" }),
|
|
743
|
-
/* @__PURE__ */ jsx("polygon", { points: "8,7 8,17 14,12", fill: "
|
|
848
|
+
/* @__PURE__ */ jsx("polygon", { points: "8,7 8,17 14,12", fill: "#fcd34d", fillOpacity: "0.85", stroke: "currentColor", strokeWidth: "2" }),
|
|
744
849
|
/* @__PURE__ */ jsx("line", { x1: "15.5", y1: "7", x2: "15.5", y2: "17", stroke: "currentColor", strokeWidth: "2" }),
|
|
745
850
|
/* @__PURE__ */ jsx("line", { x1: "15.5", y1: "12", x2: "21", y2: "12", stroke: "currentColor", strokeWidth: "2" })
|
|
746
851
|
] }),
|
|
747
852
|
battery: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
748
|
-
/* @__PURE__ */ jsx("path", { d: "M 2 12 L
|
|
749
|
-
/* @__PURE__ */ jsx("
|
|
853
|
+
/* @__PURE__ */ jsx("path", { d: "M 2 12 L 7 12", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
854
|
+
/* @__PURE__ */ jsx("rect", { x: "7", y: "4", width: "5", height: "16", rx: "0.5", fill: "#dc2626", stroke: "currentColor", strokeWidth: "1" }),
|
|
855
|
+
/* @__PURE__ */ jsx("rect", { x: "12", y: "7", width: "5", height: "10", rx: "0.5", fill: "#2563eb", stroke: "currentColor", strokeWidth: "1" }),
|
|
856
|
+
/* @__PURE__ */ jsx("path", { d: "M 17 12 L 22 12", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
750
857
|
] }),
|
|
751
858
|
ground: /* @__PURE__ */ jsx("path", { d: "M 12 4 L 12 12 M 6 12 L 18 12 M 8 16 L 16 16 M 10 20 L 14 20", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
752
859
|
meter_v: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
753
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "
|
|
754
|
-
/* @__PURE__ */ jsx("text", { x: "12", y: "15", fontSize: "
|
|
860
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "8", fill: "#e0f2fe", stroke: "#0369a1", strokeWidth: "2" }),
|
|
861
|
+
/* @__PURE__ */ jsx("text", { x: "12", y: "15", fontSize: "9", textAnchor: "middle", fill: "#0369a1", fontWeight: "bold", children: "V" })
|
|
755
862
|
] }),
|
|
756
863
|
meter_a: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
757
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "
|
|
758
|
-
/* @__PURE__ */ jsx("text", { x: "12", y: "15", fontSize: "
|
|
864
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "8", fill: "#fef3c7", stroke: "#b45309", strokeWidth: "2" }),
|
|
865
|
+
/* @__PURE__ */ jsx("text", { x: "12", y: "15", fontSize: "9", textAnchor: "middle", fill: "#b45309", fontWeight: "bold", children: "A" })
|
|
759
866
|
] }),
|
|
760
867
|
piston_cylinder: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
761
868
|
/* @__PURE__ */ jsx("path", { d: "M 4 4 L 4 20 L 20 20 L 20 4", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
@@ -837,7 +944,7 @@ var Icons = {
|
|
|
837
944
|
lens_convex: /* @__PURE__ */ jsx(
|
|
838
945
|
"path",
|
|
839
946
|
{
|
|
840
|
-
d: "M 12
|
|
947
|
+
d: "M 4 12 Q 12 4 20 12 Q 12 20 4 12 Z",
|
|
841
948
|
fill: "#38bdf8",
|
|
842
949
|
fillOpacity: "0.4",
|
|
843
950
|
stroke: "currentColor",
|
|
@@ -847,7 +954,7 @@ var Icons = {
|
|
|
847
954
|
lens_concave: /* @__PURE__ */ jsx(
|
|
848
955
|
"path",
|
|
849
956
|
{
|
|
850
|
-
d: "M 8
|
|
957
|
+
d: "M 4 8 L 4 16 Q 12 14 20 16 L 20 8 Q 12 10 4 8 Z",
|
|
851
958
|
fill: "#38bdf8",
|
|
852
959
|
fillOpacity: "0.4",
|
|
853
960
|
stroke: "currentColor",
|
|
@@ -855,16 +962,16 @@ var Icons = {
|
|
|
855
962
|
}
|
|
856
963
|
),
|
|
857
964
|
mirror_concave: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
858
|
-
/* @__PURE__ */ jsx("path", { d: "M
|
|
859
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
860
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
861
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
965
|
+
/* @__PURE__ */ jsx("path", { d: "M 4 12 Q 12 18 20 12", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
966
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "14", x2: "5", y2: "17", stroke: "currentColor" }),
|
|
967
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "15", x2: "9", y2: "18", stroke: "currentColor" }),
|
|
968
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "14", x2: "13", y2: "17", stroke: "currentColor" })
|
|
862
969
|
] }),
|
|
863
970
|
mirror_convex: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
864
|
-
/* @__PURE__ */ jsx("path", { d: "M
|
|
865
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
866
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
867
|
-
/* @__PURE__ */ jsx("line", { x1: "
|
|
971
|
+
/* @__PURE__ */ jsx("path", { d: "M 4 12 Q 12 6 20 12", fill: "none", stroke: "currentColor", strokeWidth: "2" }),
|
|
972
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "10", x2: "5", y2: "7", stroke: "currentColor" }),
|
|
973
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "9", y2: "6", stroke: "currentColor" }),
|
|
974
|
+
/* @__PURE__ */ jsx("line", { x1: "16", y1: "10", x2: "13", y2: "7", stroke: "currentColor" })
|
|
868
975
|
] }),
|
|
869
976
|
prism: /* @__PURE__ */ jsx("polygon", { points: "12,4 2,20 22,20", fill: "#38bdf8", fillOpacity: "0.4", stroke: "currentColor", strokeWidth: "2" }),
|
|
870
977
|
glass_slab: /* @__PURE__ */ jsx("rect", { x: "4", y: "6", width: "16", height: "12", fill: "#38bdf8", fillOpacity: "0.4", stroke: "currentColor", strokeWidth: "2" }),
|
|
@@ -1004,22 +1111,303 @@ var Icons = {
|
|
|
1004
1111
|
] })
|
|
1005
1112
|
};
|
|
1006
1113
|
|
|
1114
|
+
// src/editor/toolbarToolTheme.ts
|
|
1115
|
+
var tones = {
|
|
1116
|
+
teal: {
|
|
1117
|
+
idle: "text-teal-600 border-transparent hover:bg-teal-50 hover:border-teal-200",
|
|
1118
|
+
active: "bg-teal-50 text-teal-700 border-teal-200 shadow-sm ring-1 ring-teal-100"
|
|
1119
|
+
},
|
|
1120
|
+
indigo: {
|
|
1121
|
+
idle: "text-indigo-600 border-transparent hover:bg-indigo-50 hover:border-indigo-200",
|
|
1122
|
+
active: "bg-indigo-50 text-indigo-700 border-indigo-200 shadow-sm ring-1 ring-indigo-100"
|
|
1123
|
+
},
|
|
1124
|
+
violet: {
|
|
1125
|
+
idle: "text-violet-600 border-transparent hover:bg-violet-50 hover:border-violet-200",
|
|
1126
|
+
active: "bg-violet-50 text-violet-700 border-violet-200 shadow-sm ring-1 ring-violet-100"
|
|
1127
|
+
},
|
|
1128
|
+
purple: {
|
|
1129
|
+
idle: "text-purple-600 border-transparent hover:bg-purple-50 hover:border-purple-200",
|
|
1130
|
+
active: "bg-purple-50 text-purple-700 border-purple-200 shadow-sm ring-1 ring-purple-100"
|
|
1131
|
+
},
|
|
1132
|
+
amber: {
|
|
1133
|
+
idle: "text-amber-600 border-transparent hover:bg-amber-50 hover:border-amber-200",
|
|
1134
|
+
active: "bg-amber-50 text-amber-700 border-amber-200 shadow-sm ring-1 ring-amber-100"
|
|
1135
|
+
},
|
|
1136
|
+
orange: {
|
|
1137
|
+
idle: "text-orange-600 border-transparent hover:bg-orange-50 hover:border-orange-200",
|
|
1138
|
+
active: "bg-orange-50 text-orange-700 border-orange-200 shadow-sm ring-1 ring-orange-100"
|
|
1139
|
+
},
|
|
1140
|
+
rose: {
|
|
1141
|
+
idle: "text-rose-600 border-transparent hover:bg-rose-50 hover:border-rose-200",
|
|
1142
|
+
active: "bg-rose-50 text-rose-700 border-rose-200 shadow-sm ring-1 ring-rose-100"
|
|
1143
|
+
},
|
|
1144
|
+
sky: {
|
|
1145
|
+
idle: "text-sky-600 border-transparent hover:bg-sky-50 hover:border-sky-200",
|
|
1146
|
+
active: "bg-sky-50 text-sky-700 border-sky-200 shadow-sm ring-1 ring-sky-100"
|
|
1147
|
+
},
|
|
1148
|
+
cyan: {
|
|
1149
|
+
idle: "text-cyan-600 border-transparent hover:bg-cyan-50 hover:border-cyan-200",
|
|
1150
|
+
active: "bg-cyan-50 text-cyan-700 border-cyan-200 shadow-sm ring-1 ring-cyan-100"
|
|
1151
|
+
},
|
|
1152
|
+
fuchsia: {
|
|
1153
|
+
idle: "text-fuchsia-600 border-transparent hover:bg-fuchsia-50 hover:border-fuchsia-200",
|
|
1154
|
+
active: "bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200 shadow-sm ring-1 ring-fuchsia-100"
|
|
1155
|
+
},
|
|
1156
|
+
emerald: {
|
|
1157
|
+
idle: "text-emerald-600 border-transparent hover:bg-emerald-50 hover:border-emerald-200",
|
|
1158
|
+
active: "bg-emerald-50 text-emerald-700 border-emerald-200 shadow-sm ring-1 ring-emerald-100"
|
|
1159
|
+
},
|
|
1160
|
+
lime: {
|
|
1161
|
+
idle: "text-lime-600 border-transparent hover:bg-lime-50 hover:border-lime-200",
|
|
1162
|
+
active: "bg-lime-50 text-lime-700 border-lime-200 shadow-sm ring-1 ring-lime-100"
|
|
1163
|
+
},
|
|
1164
|
+
green: {
|
|
1165
|
+
idle: "text-green-600 border-transparent hover:bg-green-50 hover:border-green-200",
|
|
1166
|
+
active: "bg-green-50 text-green-700 border-green-200 shadow-sm ring-1 ring-green-100"
|
|
1167
|
+
},
|
|
1168
|
+
blue: {
|
|
1169
|
+
idle: "text-blue-600 border-transparent hover:bg-blue-50 hover:border-blue-200",
|
|
1170
|
+
active: "bg-blue-50 text-blue-700 border-blue-200 shadow-sm ring-1 ring-blue-100"
|
|
1171
|
+
},
|
|
1172
|
+
pink: {
|
|
1173
|
+
idle: "text-pink-600 border-transparent hover:bg-pink-50 hover:border-pink-200",
|
|
1174
|
+
active: "bg-pink-50 text-pink-700 border-pink-200 shadow-sm ring-1 ring-pink-100"
|
|
1175
|
+
},
|
|
1176
|
+
slate: {
|
|
1177
|
+
idle: "text-slate-600 border-transparent hover:bg-slate-100 hover:border-slate-200",
|
|
1178
|
+
active: "bg-slate-100 text-slate-800 border-slate-300 shadow-sm ring-1 ring-slate-200"
|
|
1179
|
+
},
|
|
1180
|
+
red: {
|
|
1181
|
+
idle: "text-red-600 border-transparent hover:bg-red-50 hover:border-red-200",
|
|
1182
|
+
active: "bg-red-50 text-red-700 border-red-200 shadow-sm ring-1 ring-red-100"
|
|
1183
|
+
},
|
|
1184
|
+
yellow: {
|
|
1185
|
+
idle: "text-yellow-600 border-transparent hover:bg-yellow-50 hover:border-yellow-200",
|
|
1186
|
+
active: "bg-yellow-50 text-yellow-800 border-yellow-200 shadow-sm ring-1 ring-yellow-100"
|
|
1187
|
+
},
|
|
1188
|
+
stone: {
|
|
1189
|
+
idle: "text-stone-600 border-transparent hover:bg-stone-50 hover:border-stone-200",
|
|
1190
|
+
active: "bg-stone-50 text-stone-800 border-stone-200 shadow-sm ring-1 ring-stone-100"
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
var bondCycle = ["indigo", "violet", "purple", "amber", "orange"];
|
|
1194
|
+
var arrowCycle = ["rose", "sky", "cyan", "fuchsia"];
|
|
1195
|
+
var fallbackCycle = [
|
|
1196
|
+
"indigo",
|
|
1197
|
+
"sky",
|
|
1198
|
+
"violet",
|
|
1199
|
+
"emerald",
|
|
1200
|
+
"rose",
|
|
1201
|
+
"amber",
|
|
1202
|
+
"cyan",
|
|
1203
|
+
"fuchsia",
|
|
1204
|
+
"lime",
|
|
1205
|
+
"orange",
|
|
1206
|
+
"blue",
|
|
1207
|
+
"pink"
|
|
1208
|
+
];
|
|
1209
|
+
function hashId(id) {
|
|
1210
|
+
let h = 2166136261;
|
|
1211
|
+
for (let i = 0; i < id.length; i++) {
|
|
1212
|
+
h ^= id.charCodeAt(i);
|
|
1213
|
+
h = Math.imul(h, 16777619);
|
|
1214
|
+
}
|
|
1215
|
+
return Math.abs(h);
|
|
1216
|
+
}
|
|
1217
|
+
var curated = {
|
|
1218
|
+
select: "teal",
|
|
1219
|
+
single_bond: "indigo",
|
|
1220
|
+
double_bond: "violet",
|
|
1221
|
+
triple_bond: "purple",
|
|
1222
|
+
wedge_bond: "amber",
|
|
1223
|
+
dash_bond: "orange",
|
|
1224
|
+
curved_arrow: "rose",
|
|
1225
|
+
reaction_arrow: "sky",
|
|
1226
|
+
equilibrium_arrow: "cyan",
|
|
1227
|
+
resonance_arrow: "fuchsia",
|
|
1228
|
+
benzene: "emerald",
|
|
1229
|
+
cyclohexane: "lime",
|
|
1230
|
+
cyclopentane: "green",
|
|
1231
|
+
cyclobutane: "teal",
|
|
1232
|
+
cyclopropane: "cyan",
|
|
1233
|
+
atom: "indigo",
|
|
1234
|
+
charge_plus: "rose",
|
|
1235
|
+
charge_minus: "sky",
|
|
1236
|
+
charge_pos: "rose",
|
|
1237
|
+
charge_neg: "sky",
|
|
1238
|
+
radical: "orange",
|
|
1239
|
+
lone_pair: "violet",
|
|
1240
|
+
text: "slate",
|
|
1241
|
+
point: "blue",
|
|
1242
|
+
line: "indigo",
|
|
1243
|
+
string: "indigo",
|
|
1244
|
+
dashed: "stone",
|
|
1245
|
+
dashed_line: "stone",
|
|
1246
|
+
vector: "sky",
|
|
1247
|
+
ray: "amber",
|
|
1248
|
+
axes: "slate",
|
|
1249
|
+
axes_3d: "slate",
|
|
1250
|
+
angle: "violet",
|
|
1251
|
+
arc: "violet",
|
|
1252
|
+
curve_arrow: "fuchsia",
|
|
1253
|
+
wire: "slate",
|
|
1254
|
+
resistor: "amber",
|
|
1255
|
+
capacitor: "blue",
|
|
1256
|
+
inductor: "violet",
|
|
1257
|
+
diode: "purple",
|
|
1258
|
+
battery: "green",
|
|
1259
|
+
meter_v: "cyan",
|
|
1260
|
+
meter_a: "cyan",
|
|
1261
|
+
meter: "cyan",
|
|
1262
|
+
ground: "stone",
|
|
1263
|
+
ac_source: "orange",
|
|
1264
|
+
spring: "lime",
|
|
1265
|
+
block: "amber",
|
|
1266
|
+
wedge: "amber",
|
|
1267
|
+
cart: "orange",
|
|
1268
|
+
particle: "blue",
|
|
1269
|
+
disk: "violet",
|
|
1270
|
+
rod: "stone",
|
|
1271
|
+
pulley: "slate",
|
|
1272
|
+
pivot: "red",
|
|
1273
|
+
com: "pink",
|
|
1274
|
+
surface: "stone",
|
|
1275
|
+
dimension: "cyan",
|
|
1276
|
+
point_mass: "blue",
|
|
1277
|
+
block_mass: "amber",
|
|
1278
|
+
com_indicator: "pink",
|
|
1279
|
+
system_boundary: "fuchsia",
|
|
1280
|
+
dashed_path: "stone",
|
|
1281
|
+
rocket: "orange",
|
|
1282
|
+
uniform_rod: "lime",
|
|
1283
|
+
solid_disk: "violet",
|
|
1284
|
+
hoop_ring: "purple",
|
|
1285
|
+
rolling_body: "rose",
|
|
1286
|
+
inclined_wedge: "amber",
|
|
1287
|
+
rectangle: "indigo",
|
|
1288
|
+
circle: "blue",
|
|
1289
|
+
ellipse: "violet",
|
|
1290
|
+
parabola_v: "emerald",
|
|
1291
|
+
parabola_h: "emerald",
|
|
1292
|
+
hyperbola: "purple",
|
|
1293
|
+
modulus: "orange",
|
|
1294
|
+
step_function: "stone",
|
|
1295
|
+
shaded_area: "cyan",
|
|
1296
|
+
exponential: "green",
|
|
1297
|
+
logarithmic: "teal",
|
|
1298
|
+
sine_wave: "sky",
|
|
1299
|
+
standing_wave: "cyan",
|
|
1300
|
+
wave_pulse: "blue",
|
|
1301
|
+
shm_graph: "violet",
|
|
1302
|
+
energy_graph: "amber",
|
|
1303
|
+
strobe_shm: "fuchsia",
|
|
1304
|
+
wall: "slate",
|
|
1305
|
+
speaker: "orange",
|
|
1306
|
+
tuning_fork: "amber",
|
|
1307
|
+
wavefronts: "sky",
|
|
1308
|
+
mach_cone: "purple",
|
|
1309
|
+
beats_graph: "pink",
|
|
1310
|
+
mass_box: "amber",
|
|
1311
|
+
pendulum: "indigo",
|
|
1312
|
+
torsion_pendulum: "violet",
|
|
1313
|
+
vane_liquid: "cyan",
|
|
1314
|
+
phasor: "fuchsia",
|
|
1315
|
+
damped_wave: "rose",
|
|
1316
|
+
dipole: "fuchsia",
|
|
1317
|
+
charged_plate_pos: "rose",
|
|
1318
|
+
charged_plate_neg: "sky",
|
|
1319
|
+
gaussian_sphere: "stone",
|
|
1320
|
+
gaussian_cylinder: "slate",
|
|
1321
|
+
lens_convex: "amber",
|
|
1322
|
+
lens_concave: "orange",
|
|
1323
|
+
mirror_plane: "sky",
|
|
1324
|
+
mirror_concave: "cyan",
|
|
1325
|
+
mirror_convex: "teal",
|
|
1326
|
+
prism: "violet",
|
|
1327
|
+
glass_slab: "blue",
|
|
1328
|
+
photon: "yellow",
|
|
1329
|
+
slit_double: "pink",
|
|
1330
|
+
slit_single: "rose",
|
|
1331
|
+
energy_level: "emerald",
|
|
1332
|
+
nucleus: "orange",
|
|
1333
|
+
b_field_line: "blue",
|
|
1334
|
+
b_field_curve: "indigo",
|
|
1335
|
+
bezier: "violet",
|
|
1336
|
+
pole_piece: "amber",
|
|
1337
|
+
b_region_in: "sky",
|
|
1338
|
+
b_region_out: "cyan",
|
|
1339
|
+
current_wire: "orange",
|
|
1340
|
+
bar_magnet: "red",
|
|
1341
|
+
coil: "purple",
|
|
1342
|
+
piston_cylinder: "sky",
|
|
1343
|
+
heat_engine: "orange",
|
|
1344
|
+
conduction_rod: "amber",
|
|
1345
|
+
pv_axes: "indigo",
|
|
1346
|
+
thermo_process: "violet",
|
|
1347
|
+
carnot_cycle: "fuchsia",
|
|
1348
|
+
maxwell_boltzmann: "emerald",
|
|
1349
|
+
diatomic_gas: "lime",
|
|
1350
|
+
random_walk: "stone"
|
|
1351
|
+
};
|
|
1352
|
+
var circuitIds = /* @__PURE__ */ new Set([
|
|
1353
|
+
"wire",
|
|
1354
|
+
"resistor",
|
|
1355
|
+
"capacitor",
|
|
1356
|
+
"inductor",
|
|
1357
|
+
"diode",
|
|
1358
|
+
"battery",
|
|
1359
|
+
"meter_v",
|
|
1360
|
+
"meter_a",
|
|
1361
|
+
"meter",
|
|
1362
|
+
"ground",
|
|
1363
|
+
"ac_source"
|
|
1364
|
+
]);
|
|
1365
|
+
function resolveToneKey(toolId) {
|
|
1366
|
+
const c = curated[toolId];
|
|
1367
|
+
if (c) return c;
|
|
1368
|
+
if (toolId.endsWith("_bond")) {
|
|
1369
|
+
return bondCycle[hashId(toolId) % bondCycle.length];
|
|
1370
|
+
}
|
|
1371
|
+
if (toolId.endsWith("_arrow")) {
|
|
1372
|
+
return arrowCycle[hashId(toolId) % arrowCycle.length];
|
|
1373
|
+
}
|
|
1374
|
+
const low = toolId.toLowerCase();
|
|
1375
|
+
if (low.includes("charge") && (low.includes("pos") || low.includes("plus") || low.includes("_p") || low.endsWith("pos"))) {
|
|
1376
|
+
return "rose";
|
|
1377
|
+
}
|
|
1378
|
+
if (low.includes("charge") && (low.includes("neg") || low.includes("minus"))) {
|
|
1379
|
+
return "sky";
|
|
1380
|
+
}
|
|
1381
|
+
if (toolId.startsWith("meter_")) return "violet";
|
|
1382
|
+
if (circuitIds.has(toolId)) {
|
|
1383
|
+
const circuitCycle = ["slate", "amber", "blue", "violet", "green"];
|
|
1384
|
+
return circuitCycle[hashId(toolId) % circuitCycle.length];
|
|
1385
|
+
}
|
|
1386
|
+
if (low.includes("lens") || low.includes("mirror") || low === "ray" || low.includes("photon")) {
|
|
1387
|
+
const opticsCycle = ["amber", "sky", "cyan", "violet", "yellow"];
|
|
1388
|
+
return opticsCycle[hashId(toolId) % opticsCycle.length];
|
|
1389
|
+
}
|
|
1390
|
+
return fallbackCycle[hashId(toolId) % fallbackCycle.length];
|
|
1391
|
+
}
|
|
1392
|
+
function getToolbarToolClasses(toolId, selected) {
|
|
1393
|
+
const key = resolveToneKey(toolId);
|
|
1394
|
+
return selected ? tones[key].active : tones[key].idle;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1007
1397
|
// src/editor/Toolbar.tsx
|
|
1008
1398
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1009
1399
|
var Toolbar = ({ categories, tool, onSelect }) => {
|
|
1010
|
-
const isChemistryCategory = (name) => ["chemistry", "arrows", "rings", "symbols"].includes(name.toLowerCase());
|
|
1011
1400
|
return /* @__PURE__ */ jsx2("aside", { className: "w-[108px] border-r border-slate-200 bg-gradient-to-b from-slate-50 to-white flex flex-col items-center py-3 gap-4 overflow-y-auto shrink-0", children: categories.map((category) => /* @__PURE__ */ jsxs2("section", { className: "flex flex-col items-center w-full px-2", children: [
|
|
1012
1401
|
/* @__PURE__ */ jsx2("div", { className: "text-[10px] font-semibold uppercase tracking-[0.20em] text-slate-400 mb-2 w-full text-center border-b border-slate-200 pb-1.5", children: category.name }),
|
|
1013
1402
|
/* @__PURE__ */ jsx2("div", { className: "flex flex-col gap-1.5 w-full items-center", children: category.tools.map((t) => {
|
|
1014
|
-
const
|
|
1015
|
-
const activeClass = chemistryTone ? "bg-teal-50 text-teal-700 border-teal-200 shadow-sm ring-1 ring-teal-100" : "bg-blue-50 text-blue-700 border-blue-200 shadow-sm ring-1 ring-blue-100";
|
|
1403
|
+
const toneClasses = getToolbarToolClasses(t.id, tool === t.id);
|
|
1016
1404
|
return /* @__PURE__ */ jsxs2(
|
|
1017
1405
|
"button",
|
|
1018
1406
|
{
|
|
1019
1407
|
type: "button",
|
|
1020
1408
|
onClick: () => onSelect(t.id),
|
|
1021
1409
|
title: t.name,
|
|
1022
|
-
className: `p-2 rounded-xl border flex flex-col items-center gap-1 transition-all w-full ${
|
|
1410
|
+
className: `p-2 rounded-xl border flex flex-col items-center gap-1 transition-all w-full ${toneClasses}`,
|
|
1023
1411
|
children: [
|
|
1024
1412
|
/* @__PURE__ */ jsx2("svg", { className: "w-5 h-5", viewBox: "0 0 24 24", children: Icons[t.id] ?? Icons.line }),
|
|
1025
1413
|
/* @__PURE__ */ jsx2("span", { className: "text-[11px] font-medium tracking-tight leading-tight text-center", children: t.name })
|
|
@@ -1034,6 +1422,7 @@ var Toolbar = ({ categories, tool, onSelect }) => {
|
|
|
1034
1422
|
// src/editor/PropertiesPanel.tsx
|
|
1035
1423
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1036
1424
|
var needsCurveHeight = (t) => ["gaussian_cylinder", "lens_convex", "lens_concave", "mirror_concave", "mirror_convex", "b_field_curve"].includes(t);
|
|
1425
|
+
var opticsCurveHeightAuto = (t) => ["lens_convex", "lens_concave", "mirror_concave", "mirror_convex"].includes(t);
|
|
1037
1426
|
var needsFontSize = (t) => ["text", "point", "charge_pos", "charge_neg", "point_mass", "com_indicator", "diatomic_gas", "mass_box"].includes(t);
|
|
1038
1427
|
var needsRotationSize = (t) => ["point_mass", "com_indicator", "pivot"].includes(t);
|
|
1039
1428
|
var needsWaveOscSize = (t) => ["pendulum", "mass_box"].includes(t);
|
|
@@ -1118,13 +1507,32 @@ var PropertiesPanel = ({ element, onChange, onDelete, onClose }) => {
|
|
|
1118
1507
|
] }),
|
|
1119
1508
|
needsCurveHeight(String(element.type)) && /* @__PURE__ */ jsxs3("label", { className: "block space-y-1", children: [
|
|
1120
1509
|
/* @__PURE__ */ jsx3("span", { className: "text-xs font-medium text-slate-600", children: element.type === "gaussian_cylinder" ? "Cylinder half-height (curveHeight)" : "Curve height" }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1510
|
+
opticsCurveHeightAuto(String(element.type)) ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1511
|
+
/* @__PURE__ */ jsx3(
|
|
1512
|
+
"input",
|
|
1513
|
+
{
|
|
1514
|
+
type: "number",
|
|
1515
|
+
className: "w-full px-3 py-2 border border-slate-300 rounded-lg text-sm",
|
|
1516
|
+
placeholder: "Auto",
|
|
1517
|
+
value: element.curveHeight === void 0 || element.curveHeight === null ? "" : Number(element.curveHeight),
|
|
1518
|
+
onChange: (e) => {
|
|
1519
|
+
const raw = e.target.value;
|
|
1520
|
+
if (raw === "") onChange("curveHeight", void 0);
|
|
1521
|
+
else {
|
|
1522
|
+
const n = Number(raw);
|
|
1523
|
+
onChange("curveHeight", Number.isFinite(n) ? n : void 0);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
),
|
|
1528
|
+
/* @__PURE__ */ jsx3("p", { className: "text-[11px] text-slate-500 leading-snug", children: "Empty = auto (scales with chord length: lenses ~15% / 4% sagitta, mirrors ~20%)." })
|
|
1529
|
+
] }) : /* @__PURE__ */ jsx3(
|
|
1122
1530
|
"input",
|
|
1123
1531
|
{
|
|
1124
1532
|
type: "number",
|
|
1125
1533
|
className: "w-full px-3 py-2 border border-slate-300 rounded-lg text-sm",
|
|
1126
1534
|
value: Number(
|
|
1127
|
-
element.curveHeight ?? (element.type === "b_field_curve" ? 50 : element.type === "gaussian_cylinder"
|
|
1535
|
+
element.curveHeight ?? (element.type === "b_field_curve" ? 50 : element.type === "gaussian_cylinder" ? 40 : 20)
|
|
1128
1536
|
),
|
|
1129
1537
|
onChange: (e) => onChange("curveHeight", Number(e.target.value))
|
|
1130
1538
|
}
|
|
@@ -1620,8 +2028,8 @@ var JsonModal = ({ open, jsonText, setJsonText, onClose, onLoad }) => {
|
|
|
1620
2028
|
};
|
|
1621
2029
|
|
|
1622
2030
|
// src/editor/presets/mechanics.ts
|
|
1623
|
-
var
|
|
1624
|
-
name: "
|
|
2031
|
+
var classicIncline = {
|
|
2032
|
+
name: "Classic incline FBD",
|
|
1625
2033
|
elements: [
|
|
1626
2034
|
{ id: 1, type: "wedge", x1: 100, y1: 400, x2: 500, y2: 100, label: "M", value: "", color: "#0f172a", strokeWidth: 2 },
|
|
1627
2035
|
{ id: 2, type: "block", x1: 220, y1: 260, x2: 300, y2: 300, label: "m", value: "", color: "#0f172a", strokeWidth: 2, rotation: -37 },
|
|
@@ -1633,7 +2041,60 @@ var mechanics = {
|
|
|
1633
2041
|
{ id: 8, type: "dashed", x1: 260, y1: 280, x2: 340, y2: 220, label: "", value: "", color: "#0f172a", strokeWidth: 2 },
|
|
1634
2042
|
{ id: 9, type: "dimension", x1: 100, y1: 440, x2: 500, y2: 440, label: "L", value: "", color: "#0f172a", strokeWidth: 2 },
|
|
1635
2043
|
{ id: 10, type: "axes", x1: 60, y1: 100, x2: 60, y2: 100, label: "", value: "", color: "#0f172a", strokeWidth: 2 }
|
|
1636
|
-
]
|
|
2044
|
+
]
|
|
2045
|
+
};
|
|
2046
|
+
var rigidBodiesShowcase = {
|
|
2047
|
+
name: "Rigid bodies & fluids showcase",
|
|
2048
|
+
elements: [
|
|
2049
|
+
{ id: 1, type: "text", x1: 200, y1: 40, x2: 200, y2: 40, label: "3D rigid bodies (moment of inertia)", color: "#64748b", fontSize: 18 },
|
|
2050
|
+
{ id: 2, type: "cylinder", x1: 60, y1: 140, x2: 220, y2: 180, color: "#38bdf8", strokeWidth: 2, fillOpacity: 0.4, curveHeight: 30, label: "M, R" },
|
|
2051
|
+
{ id: 3, type: "line", x1: 20, y1: 160, x2: 280, y2: 160, color: "#94a3b8", strokeWidth: 2, lineStyle: "dashed" },
|
|
2052
|
+
{ id: 4, type: "arc_arrow", x1: 260, y1: 160, x2: 300, y2: 160, color: "#0f172a", strokeWidth: 2, label: "\u03C9" },
|
|
2053
|
+
{ id: 5, type: "text", x1: 140, y1: 240, x2: 140, y2: 240, label: "I = MR\xB2/2", color: "#0f172a", fontSize: 16 },
|
|
2054
|
+
{ id: 6, type: "slab", x1: 340, y1: 120, x2: 500, y2: 180, color: "#38bdf8", strokeWidth: 2, fillOpacity: 0.4, curveHeight: 30, label: "M" },
|
|
2055
|
+
{ id: 7, type: "line", x1: 420, y1: 60, x2: 420, y2: 260, color: "#94a3b8", strokeWidth: 2, lineStyle: "dashed", label: "z" },
|
|
2056
|
+
{ id: 8, type: "arc_arrow", x1: 420, y1: 80, x2: 460, y2: 80, color: "#0f172a", strokeWidth: 2 },
|
|
2057
|
+
{ id: 9, type: "text", x1: 420, y1: 240, x2: 420, y2: 240, label: "I = M(l\xB2+b\xB2)/12", color: "#0f172a", fontSize: 16 },
|
|
2058
|
+
{ id: 10, type: "text", x1: 700, y1: 40, x2: 700, y2: 40, label: "Fluids & gravitation", color: "#64748b", fontSize: 18 },
|
|
2059
|
+
{ id: 11, type: "pipe", x1: 600, y1: 80, x2: 800, y2: 140, color: "#3b82f6", strokeWidth: 2, fillOpacity: 0.2, curveHeight: 20 },
|
|
2060
|
+
{ id: 12, type: "vector", x1: 620, y1: 110, x2: 680, y2: 110, color: "#0f172a", strokeWidth: 2, label: "v\u2081" },
|
|
2061
|
+
{ id: 13, type: "vector", x1: 720, y1: 110, x2: 780, y2: 110, color: "#0f172a", strokeWidth: 2, label: "v\u2082" },
|
|
2062
|
+
{ id: 14, type: "shell", x1: 700, y1: 240, x2: 760, y2: 240, color: "#8b5cf6", strokeWidth: 2, fillOpacity: 0.3, curveHeight: 15, label: "M" },
|
|
2063
|
+
{ id: 15, type: "point", x1: 700, y1: 240, x2: 700, y2: 240, color: "#0f172a", strokeWidth: 2, label: "O" },
|
|
2064
|
+
{ id: 16, type: "point", x1: 820, y1: 240, x2: 820, y2: 240, color: "#0f172a", strokeWidth: 2, label: "m" },
|
|
2065
|
+
{ id: 17, type: "vector", x1: 820, y1: 240, x2: 780, y2: 240, color: "#ef4444", strokeWidth: 2, label: "F" },
|
|
2066
|
+
{ id: 18, type: "text", x1: 220, y1: 320, x2: 220, y2: 320, label: "Ladders & pulleys", color: "#64748b", fontSize: 18 },
|
|
2067
|
+
{ id: 19, type: "table_edge", x1: 40, y1: 420, x2: 240, y2: 560, color: "#475569", strokeWidth: 2 },
|
|
2068
|
+
{ id: 20, type: "block", x1: 100, y1: 380, x2: 160, y2: 420, color: "#38bdf8", strokeWidth: 2, fillOpacity: 0.4, label: "m\u2081" },
|
|
2069
|
+
{ id: 21, type: "pulley", x1: 240, y1: 420, x2: 260, y2: 420, color: "#0f172a", strokeWidth: 2, fillOpacity: 0.2 },
|
|
2070
|
+
{ id: 22, type: "block", x1: 240, y1: 480, x2: 280, y2: 540, color: "#38bdf8", strokeWidth: 2, fillOpacity: 0.4, label: "m\u2082" },
|
|
2071
|
+
{ id: 23, type: "line", x1: 160, y1: 400, x2: 240, y2: 400, color: "#0f172a", strokeWidth: 2 },
|
|
2072
|
+
{ id: 24, type: "line", x1: 260, y1: 420, x2: 260, y2: 480, color: "#0f172a", strokeWidth: 2 },
|
|
2073
|
+
{ id: 25, type: "table_edge", x1: 400, y1: 360, x2: 560, y2: 560, color: "#475569", strokeWidth: 2 },
|
|
2074
|
+
{ id: 26, type: "ladder", x1: 460, y1: 560, x2: 560, y2: 420, color: "#f59e0b", strokeWidth: 2, curveHeight: 12 },
|
|
2075
|
+
{ id: 27, type: "vector", x1: 460, y1: 560, x2: 460, y2: 500, color: "#10b981", strokeWidth: 2, label: "N\u2081" },
|
|
2076
|
+
{ id: 28, type: "vector", x1: 560, y1: 420, x2: 500, y2: 420, color: "#10b981", strokeWidth: 2, label: "N\u2082" },
|
|
2077
|
+
{ id: 29, type: "vector", x1: 510, y1: 490, x2: 510, y2: 540, color: "#ef4444", strokeWidth: 2, label: "Mg" }
|
|
2078
|
+
]
|
|
2079
|
+
};
|
|
2080
|
+
var verticalSpringMass = {
|
|
2081
|
+
name: "Vertical spring\u2013mass",
|
|
2082
|
+
elements: [
|
|
2083
|
+
{ id: 1, type: "text", x1: 380, y1: 40, x2: 380, y2: 40, label: "Equilibrium along a vertical spring", color: "#64748b", fontSize: 18 },
|
|
2084
|
+
{ id: 2, type: "line", x1: 260, y1: 100, x2: 500, y2: 100, color: "#475569", strokeWidth: 3, label: "Ceiling" },
|
|
2085
|
+
{ id: 3, type: "spring", x1: 380, y1: 100, x2: 380, y2: 220, color: "#2563eb", strokeWidth: 2, coils: 8 },
|
|
2086
|
+
{ id: 4, type: "block", x1: 340, y1: 220, x2: 420, y2: 280, color: "#38bdf8", strokeWidth: 2, fillOpacity: 0.35, label: "m" },
|
|
2087
|
+
{ id: 5, type: "vector", x1: 380, y1: 280, x2: 380, y2: 380, color: "#ef4444", strokeWidth: 2.5, label: "mg" },
|
|
2088
|
+
{ id: 6, type: "vector", x1: 380, y1: 250, x2: 380, y2: 150, color: "#10b981", strokeWidth: 2.5, label: "F_s" },
|
|
2089
|
+
{ id: 7, type: "dashed", x1: 380, y1: 280, x2: 460, y2: 280, color: "#94a3b8", strokeWidth: 1.5, label: "x = 0" },
|
|
2090
|
+
{ id: 8, type: "text", x1: 480, y1: 260, x2: 480, y2: 260, label: "mg = kx\u2080", color: "#0f172a", fontSize: 16 }
|
|
2091
|
+
]
|
|
2092
|
+
};
|
|
2093
|
+
var mechanicsExamples = [classicIncline, rigidBodiesShowcase, verticalSpringMass];
|
|
2094
|
+
var mechanics = {
|
|
2095
|
+
name: "Mechanics",
|
|
2096
|
+
elements: mechanicsExamples[0].elements,
|
|
2097
|
+
examples: mechanicsExamples,
|
|
1637
2098
|
toolCategories: [
|
|
1638
2099
|
{
|
|
1639
2100
|
name: "Sketch and forces",
|
|
@@ -1673,24 +2134,59 @@ var mechanics = {
|
|
|
1673
2134
|
};
|
|
1674
2135
|
|
|
1675
2136
|
// src/editor/presets/circuit.ts
|
|
2137
|
+
var wheatstoneBridge = {
|
|
2138
|
+
name: "Wheatstone bridge",
|
|
2139
|
+
elements: [
|
|
2140
|
+
{ id: 1, type: "resistor", x1: 200, y1: 300, x2: 400, y2: 200, label: "R1", value: "60\u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2141
|
+
{ id: 2, type: "resistor", x1: 200, y1: 300, x2: 400, y2: 400, label: "R3", value: "300\u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2142
|
+
{ id: 3, type: "resistor", x1: 400, y1: 200, x2: 600, y2: 300, label: "R2", value: "100\u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2143
|
+
{ id: 4, type: "resistor", x1: 400, y1: 400, x2: 600, y2: 300, label: "R4", value: "500\u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2144
|
+
{ id: 5, type: "battery", x1: 400, y1: 400, x2: 400, y2: 200, label: "50V", value: "", color: "#1d4ed8", strokeWidth: 2.5 },
|
|
2145
|
+
{ id: 6, type: "wire", x1: 200, y1: 300, x2: 200, y2: 100, label: "", value: "", color: "#334155", strokeWidth: 3 },
|
|
2146
|
+
{ id: 7, type: "wire", x1: 200, y1: 100, x2: 340, y2: 100, label: "", value: "", color: "#334155", strokeWidth: 3 },
|
|
2147
|
+
{ id: 8, type: "meter_v", x1: 340, y1: 100, x2: 460, y2: 100, label: "", value: "", color: "#0369a1", strokeWidth: 2.5 },
|
|
2148
|
+
{ id: 9, type: "wire", x1: 460, y1: 100, x2: 600, y2: 100, label: "", value: "", color: "#334155", strokeWidth: 3 },
|
|
2149
|
+
{ id: 10, type: "wire", x1: 600, y1: 100, x2: 600, y2: 300, label: "", value: "", color: "#334155", strokeWidth: 3 },
|
|
2150
|
+
{ id: 11, type: "text", x1: 180, y1: 300, x2: 180, y2: 300, label: "S", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18, color: "#0f172a" },
|
|
2151
|
+
{ id: 12, type: "text", x1: 400, y1: 180, x2: 400, y2: 180, label: "P", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18, color: "#0f172a" },
|
|
2152
|
+
{ id: 13, type: "text", x1: 400, y1: 420, x2: 400, y2: 420, label: "Q", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18, color: "#0f172a" },
|
|
2153
|
+
{ id: 14, type: "text", x1: 620, y1: 300, x2: 620, y2: 300, label: "T", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18, color: "#0f172a" }
|
|
2154
|
+
]
|
|
2155
|
+
};
|
|
2156
|
+
var seriesRC = {
|
|
2157
|
+
name: "Series RC (charging)",
|
|
2158
|
+
elements: [
|
|
2159
|
+
{ id: 1, type: "text", x1: 320, y1: 40, x2: 320, y2: 40, label: "Single-loop RC after switch closes", color: "#475569", fontSize: 16 },
|
|
2160
|
+
{ id: 2, type: "battery", x1: 120, y1: 360, x2: 120, y2: 220, label: "\u03B5", value: "12 V", color: "#1d4ed8", strokeWidth: 2.5 },
|
|
2161
|
+
{ id: 3, type: "wire", x1: 120, y1: 220, x2: 220, y2: 220, color: "#334155", strokeWidth: 3 },
|
|
2162
|
+
{ id: 4, type: "resistor", x1: 220, y1: 220, x2: 380, y2: 220, label: "R", value: "2.2 k\u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2163
|
+
{ id: 5, type: "wire", x1: 380, y1: 220, x2: 480, y2: 220, color: "#334155", strokeWidth: 3 },
|
|
2164
|
+
{ id: 6, type: "capacitor", x1: 480, y1: 220, x2: 620, y2: 220, label: "C", value: "47 \u03BCF", color: "#0f172a", strokeWidth: 2.5 },
|
|
2165
|
+
{ id: 7, type: "wire", x1: 620, y1: 220, x2: 620, y2: 360, color: "#334155", strokeWidth: 3 },
|
|
2166
|
+
{ id: 8, type: "wire", x1: 620, y1: 360, x2: 120, y2: 360, color: "#334155", strokeWidth: 3 },
|
|
2167
|
+
{ id: 9, type: "text", x1: 360, y1: 120, x2: 360, y2: 120, label: "\u03C4 = RC", color: "#0f172a", fontSize: 18 }
|
|
2168
|
+
]
|
|
2169
|
+
};
|
|
2170
|
+
var parallelResistors = {
|
|
2171
|
+
name: "Parallel resistors",
|
|
2172
|
+
elements: [
|
|
2173
|
+
{ id: 1, type: "text", x1: 300, y1: 40, x2: 300, y2: 40, label: "Same voltage across each branch", color: "#475569", fontSize: 16 },
|
|
2174
|
+
{ id: 2, type: "battery", x1: 120, y1: 380, x2: 120, y2: 120, label: "V", value: "9 V", color: "#1d4ed8", strokeWidth: 2.5 },
|
|
2175
|
+
{ id: 3, type: "wire", x1: 120, y1: 120, x2: 520, y2: 120, color: "#334155", strokeWidth: 3 },
|
|
2176
|
+
{ id: 4, type: "resistor", x1: 260, y1: 120, x2: 260, y2: 300, label: "R\u2081", value: "300 \u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2177
|
+
{ id: 5, type: "resistor", x1: 400, y1: 120, x2: 400, y2: 300, label: "R\u2082", value: "600 \u03A9", color: "#b45309", strokeWidth: 2.5 },
|
|
2178
|
+
{ id: 6, type: "wire", x1: 260, y1: 300, x2: 400, y2: 300, color: "#334155", strokeWidth: 3 },
|
|
2179
|
+
{ id: 7, type: "wire", x1: 260, y1: 300, x2: 220, y2: 300, color: "#334155", strokeWidth: 3 },
|
|
2180
|
+
{ id: 8, type: "meter_a", x1: 220, y1: 300, x2: 120, y2: 300, label: "I", value: "", color: "#b45309", strokeWidth: 2.5 },
|
|
2181
|
+
{ id: 9, type: "wire", x1: 120, y1: 300, x2: 120, y2: 380, color: "#334155", strokeWidth: 3 },
|
|
2182
|
+
{ id: 10, type: "text", x1: 280, y1: 340, x2: 280, y2: 340, label: "1/R_eq = 1/R\u2081 + 1/R\u2082", color: "#0f172a", fontSize: 15 }
|
|
2183
|
+
]
|
|
2184
|
+
};
|
|
2185
|
+
var circuitExamples = [wheatstoneBridge, seriesRC, parallelResistors];
|
|
1676
2186
|
var circuit = {
|
|
1677
2187
|
name: "Circuit",
|
|
1678
|
-
elements: [
|
|
1679
|
-
|
|
1680
|
-
{ id: 2, type: "resistor", x1: 200, y1: 300, x2: 400, y2: 400, label: "R3", value: "300\u03A9" },
|
|
1681
|
-
{ id: 3, type: "resistor", x1: 400, y1: 200, x2: 600, y2: 300, label: "R2", value: "100\u03A9" },
|
|
1682
|
-
{ id: 4, type: "resistor", x1: 400, y1: 400, x2: 600, y2: 300, label: "R4", value: "500\u03A9" },
|
|
1683
|
-
{ id: 5, type: "battery", x1: 400, y1: 400, x2: 400, y2: 200, label: "50V", value: "" },
|
|
1684
|
-
{ id: 6, type: "wire", x1: 200, y1: 300, x2: 200, y2: 100, label: "", value: "" },
|
|
1685
|
-
{ id: 7, type: "wire", x1: 200, y1: 100, x2: 340, y2: 100, label: "", value: "" },
|
|
1686
|
-
{ id: 8, type: "meter_v", x1: 340, y1: 100, x2: 460, y2: 100, label: "", value: "" },
|
|
1687
|
-
{ id: 9, type: "wire", x1: 460, y1: 100, x2: 600, y2: 100, label: "", value: "" },
|
|
1688
|
-
{ id: 10, type: "wire", x1: 600, y1: 100, x2: 600, y2: 300, label: "", value: "" },
|
|
1689
|
-
{ id: 11, type: "text", x1: 180, y1: 300, x2: 180, y2: 300, label: "S", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18 },
|
|
1690
|
-
{ id: 12, type: "text", x1: 400, y1: 180, x2: 400, y2: 180, label: "P", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18 },
|
|
1691
|
-
{ id: 13, type: "text", x1: 400, y1: 420, x2: 400, y2: 420, label: "Q", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18 },
|
|
1692
|
-
{ id: 14, type: "text", x1: 620, y1: 300, x2: 620, y2: 300, label: "T", value: "", fontFamily: "sans-serif", fontWeight: "bold", fontSize: 18 }
|
|
1693
|
-
],
|
|
2188
|
+
elements: circuitExamples[0].elements,
|
|
2189
|
+
examples: circuitExamples,
|
|
1694
2190
|
toolCategories: [
|
|
1695
2191
|
{
|
|
1696
2192
|
name: "Circuit",
|
|
@@ -1712,91 +2208,130 @@ var circuit = {
|
|
|
1712
2208
|
};
|
|
1713
2209
|
|
|
1714
2210
|
// src/editor/presets/thermo.ts
|
|
1715
|
-
var
|
|
1716
|
-
name: "
|
|
2211
|
+
var pistonAndGas = {
|
|
2212
|
+
name: "Piston, heat & first law",
|
|
1717
2213
|
elements: [
|
|
1718
|
-
{ id:
|
|
2214
|
+
{ id: 1, type: "text", x1: 120, y1: 40, x2: 120, y2: 40, label: "Gas in a cylinder (work, heat, \u0394U)", color: "#475569", fontSize: 18 },
|
|
1719
2215
|
{
|
|
1720
|
-
id:
|
|
2216
|
+
id: 2,
|
|
1721
2217
|
type: "piston_cylinder",
|
|
1722
|
-
x1:
|
|
1723
|
-
y1:
|
|
1724
|
-
x2:
|
|
1725
|
-
y2:
|
|
1726
|
-
compression: 0.
|
|
2218
|
+
x1: 120,
|
|
2219
|
+
y1: 120,
|
|
2220
|
+
x2: 320,
|
|
2221
|
+
y2: 320,
|
|
2222
|
+
compression: 0.55,
|
|
1727
2223
|
showHeat: true,
|
|
1728
2224
|
color: "#0ea5e9",
|
|
1729
2225
|
strokeWidth: 2,
|
|
1730
|
-
label: "
|
|
2226
|
+
label: "Expansion stroke"
|
|
1731
2227
|
},
|
|
1732
|
-
{
|
|
2228
|
+
{
|
|
2229
|
+
id: 3,
|
|
2230
|
+
type: "thermo_process",
|
|
2231
|
+
x1: 400,
|
|
2232
|
+
y1: 200,
|
|
2233
|
+
x2: 560,
|
|
2234
|
+
y2: 120,
|
|
2235
|
+
processType: "isobaric",
|
|
2236
|
+
color: "#f59e0b",
|
|
2237
|
+
strokeWidth: 2,
|
|
2238
|
+
label: "Isobaric leg"
|
|
2239
|
+
},
|
|
2240
|
+
{ id: 4, type: "text", x1: 400, y1: 280, x2: 400, y2: 280, label: "Q = \u0394U + W", color: "#0f172a", fontSize: 18 }
|
|
2241
|
+
]
|
|
2242
|
+
};
|
|
2243
|
+
var engineAndPV = {
|
|
2244
|
+
name: "Heat engine & P\u2013V cycle",
|
|
2245
|
+
elements: [
|
|
2246
|
+
{ id: 1, type: "text", x1: 80, y1: 40, x2: 80, y2: 40, label: "Carnot engine between two reservoirs", color: "#475569", fontSize: 18 },
|
|
1733
2247
|
{
|
|
1734
2248
|
id: 2,
|
|
1735
2249
|
type: "heat_engine",
|
|
1736
|
-
x1:
|
|
1737
|
-
y1:
|
|
1738
|
-
x2:
|
|
1739
|
-
y2:
|
|
2250
|
+
x1: 120,
|
|
2251
|
+
y1: 100,
|
|
2252
|
+
x2: 260,
|
|
2253
|
+
y2: 300,
|
|
1740
2254
|
engineType: "engine",
|
|
1741
|
-
efficiency: 0.
|
|
2255
|
+
efficiency: 0.35,
|
|
1742
2256
|
color: "#10b981",
|
|
1743
2257
|
strokeWidth: 2,
|
|
1744
|
-
label: "
|
|
2258
|
+
label: "\u03B7 < 1"
|
|
1745
2259
|
},
|
|
1746
|
-
{ id: 103, type: "text", x1: 700, y1: 40, x2: 700, y2: 40, label: "3. P-V Diagrams", fontSize: 20, color: "#1e293b" },
|
|
1747
2260
|
{
|
|
1748
2261
|
id: 3,
|
|
1749
2262
|
type: "pv_axes",
|
|
1750
|
-
x1:
|
|
1751
|
-
y1:
|
|
1752
|
-
x2:
|
|
1753
|
-
y2:
|
|
2263
|
+
x1: 360,
|
|
2264
|
+
y1: 300,
|
|
2265
|
+
x2: 620,
|
|
2266
|
+
y2: 100,
|
|
1754
2267
|
color: "#1e293b",
|
|
1755
2268
|
strokeWidth: 2,
|
|
1756
|
-
label: "
|
|
2269
|
+
label: "State space",
|
|
1757
2270
|
xLabel: "V",
|
|
1758
2271
|
yLabel: "P"
|
|
1759
2272
|
},
|
|
1760
|
-
{ id: 4, type: "carnot_cycle", x1:
|
|
1761
|
-
{ id:
|
|
2273
|
+
{ id: 4, type: "carnot_cycle", x1: 400, y1: 140, x2: 560, y2: 240, color: "#ec4899", strokeWidth: 2 },
|
|
2274
|
+
{ id: 5, type: "text", x1: 640, y1: 180, x2: 640, y2: 180, label: "Isotherms + adiabats", color: "#64748b", fontSize: 15 }
|
|
2275
|
+
]
|
|
2276
|
+
};
|
|
2277
|
+
var kineticTheory = {
|
|
2278
|
+
name: "Kinetic theory & conduction",
|
|
2279
|
+
elements: [
|
|
2280
|
+
{ id: 1, type: "text", x1: 80, y1: 40, x2: 80, y2: 40, label: "Speed distribution & thermal transport", color: "#475569", fontSize: 18 },
|
|
1762
2281
|
{
|
|
1763
|
-
id:
|
|
2282
|
+
id: 2,
|
|
1764
2283
|
type: "maxwell_boltzmann",
|
|
1765
2284
|
x1: 80,
|
|
1766
|
-
y1:
|
|
1767
|
-
x2:
|
|
1768
|
-
y2:
|
|
2285
|
+
y1: 320,
|
|
2286
|
+
x2: 340,
|
|
2287
|
+
y2: 160,
|
|
1769
2288
|
t1: 300,
|
|
1770
2289
|
t2: 600,
|
|
1771
2290
|
color: "#8b5cf6",
|
|
1772
2291
|
strokeWidth: 2,
|
|
1773
|
-
label: "f(v)
|
|
2292
|
+
label: "f(v) at T\u2081, T\u2082"
|
|
1774
2293
|
},
|
|
1775
2294
|
{
|
|
1776
|
-
id:
|
|
2295
|
+
id: 3,
|
|
1777
2296
|
type: "diatomic_gas",
|
|
1778
|
-
x1:
|
|
1779
|
-
y1:
|
|
1780
|
-
x2:
|
|
1781
|
-
y2:
|
|
2297
|
+
x1: 420,
|
|
2298
|
+
y1: 220,
|
|
2299
|
+
x2: 520,
|
|
2300
|
+
y2: 220,
|
|
1782
2301
|
color: "#f59e0b",
|
|
1783
2302
|
strokeWidth: 2,
|
|
1784
|
-
label: "
|
|
2303
|
+
label: "5 DOF (trans + rot)",
|
|
1785
2304
|
showRotations: true
|
|
1786
2305
|
},
|
|
1787
|
-
{ id: 105, type: "text", x1: 700, y1: 340, x2: 700, y2: 340, label: "5. Thermal Conduction", fontSize: 20, color: "#1e293b" },
|
|
1788
2306
|
{
|
|
1789
|
-
id:
|
|
2307
|
+
id: 4,
|
|
1790
2308
|
type: "conduction_rod",
|
|
1791
|
-
x1:
|
|
1792
|
-
y1:
|
|
1793
|
-
x2:
|
|
1794
|
-
y2:
|
|
2309
|
+
x1: 420,
|
|
2310
|
+
y1: 320,
|
|
2311
|
+
x2: 720,
|
|
2312
|
+
y2: 360,
|
|
1795
2313
|
color: "#3b82f6",
|
|
1796
2314
|
strokeWidth: 2,
|
|
1797
|
-
label: "
|
|
2315
|
+
label: "Q\u0307 = kA\u0394T/L"
|
|
2316
|
+
},
|
|
2317
|
+
{
|
|
2318
|
+
id: 5,
|
|
2319
|
+
type: "random_walk",
|
|
2320
|
+
x1: 600,
|
|
2321
|
+
y1: 120,
|
|
2322
|
+
x2: 720,
|
|
2323
|
+
y2: 80,
|
|
2324
|
+
color: "#64748b",
|
|
2325
|
+
strokeWidth: 2,
|
|
2326
|
+
label: "Diffusion"
|
|
1798
2327
|
}
|
|
1799
|
-
]
|
|
2328
|
+
]
|
|
2329
|
+
};
|
|
2330
|
+
var thermoExamples = [pistonAndGas, engineAndPV, kineticTheory];
|
|
2331
|
+
var thermo = {
|
|
2332
|
+
name: "Thermodynamics",
|
|
2333
|
+
elements: thermoExamples[0].elements,
|
|
2334
|
+
examples: thermoExamples,
|
|
1800
2335
|
toolCategories: [
|
|
1801
2336
|
{
|
|
1802
2337
|
name: "Basics",
|
|
@@ -1834,81 +2369,55 @@ var thermo = {
|
|
|
1834
2369
|
]
|
|
1835
2370
|
};
|
|
1836
2371
|
|
|
1837
|
-
// src/editor/presets/
|
|
1838
|
-
var
|
|
1839
|
-
name: "
|
|
2372
|
+
// src/editor/presets/magnetism.ts
|
|
2373
|
+
var electromagnetGap = {
|
|
2374
|
+
name: "Electromagnet & uniform gap",
|
|
1840
2375
|
elements: [
|
|
1841
|
-
{ id: 1, type: "
|
|
1842
|
-
{ id: 2, type: "
|
|
1843
|
-
{ id: 3, type: "
|
|
1844
|
-
{ id: 4, type: "
|
|
1845
|
-
{ id: 5, type: "
|
|
1846
|
-
{ id: 6, type: "
|
|
1847
|
-
{ id: 7, type: "
|
|
1848
|
-
{ id: 8, type: "
|
|
1849
|
-
{ id: 9, type: "
|
|
1850
|
-
{ id: 10, type: "
|
|
1851
|
-
{ id: 11, type: "
|
|
1852
|
-
{ id: 12, type: "
|
|
1853
|
-
{ id: 13, type: "
|
|
1854
|
-
{ id: 14, type: "
|
|
1855
|
-
{ id: 15, type: "photon", x1: 510, y1: 520, x2: 590, y2: 520, label: "\u03BB", color: "#eab308", strokeWidth: 2 }
|
|
1856
|
-
],
|
|
1857
|
-
toolCategories: [
|
|
1858
|
-
{
|
|
1859
|
-
name: "Basics",
|
|
1860
|
-
tools: [
|
|
1861
|
-
{ id: "select", name: "Select/Move" },
|
|
1862
|
-
{ id: "point", name: "Point/Node" },
|
|
1863
|
-
{ id: "line", name: "Solid Line" },
|
|
1864
|
-
{ id: "vector", name: "Vector/Object" },
|
|
1865
|
-
{ id: "text", name: "Text Label" }
|
|
1866
|
-
]
|
|
1867
|
-
},
|
|
1868
|
-
{
|
|
1869
|
-
name: "Optics",
|
|
1870
|
-
tools: [
|
|
1871
|
-
{ id: "ray", name: "Light Ray" },
|
|
1872
|
-
{ id: "lens_convex", name: "Convex Lens" },
|
|
1873
|
-
{ id: "lens_concave", name: "Concave Lens" },
|
|
1874
|
-
{ id: "mirror_plane", name: "Plane Mirror" },
|
|
1875
|
-
{ id: "mirror_concave", name: "Concave Mirror" },
|
|
1876
|
-
{ id: "mirror_convex", name: "Convex Mirror" },
|
|
1877
|
-
{ id: "prism", name: "Glass Prism" },
|
|
1878
|
-
{ id: "glass_slab", name: "Glass Slab" }
|
|
1879
|
-
]
|
|
1880
|
-
},
|
|
1881
|
-
{
|
|
1882
|
-
name: "Modern Physics",
|
|
1883
|
-
tools: [
|
|
1884
|
-
{ id: "photon", name: "Photon (Wavy)" },
|
|
1885
|
-
{ id: "slit_double", name: "Double Slit" },
|
|
1886
|
-
{ id: "slit_single", name: "Single Slit" },
|
|
1887
|
-
{ id: "energy_level", name: "Energy Level" },
|
|
1888
|
-
{ id: "nucleus", name: "Atom/Nucleus" }
|
|
1889
|
-
]
|
|
1890
|
-
}
|
|
2376
|
+
{ id: 1, type: "text", x1: 280, y1: 36, x2: 280, y2: 36, label: "Iron pole pieces + straight B in the gap", color: "#475569", fontSize: 16 },
|
|
2377
|
+
{ id: 2, type: "pole_piece", x1: 100, y1: 80, x2: 200, y2: 300, label: "N", color: "#0f172a", strokeWidth: 2 },
|
|
2378
|
+
{ id: 3, type: "pole_piece", x1: 500, y1: 80, x2: 600, y2: 300, label: "S", color: "#0f172a", strokeWidth: 2 },
|
|
2379
|
+
{ id: 4, type: "b_field_line", x1: 200, y1: 120, x2: 500, y2: 120, label: "", color: "#10b981", strokeWidth: 2 },
|
|
2380
|
+
{ id: 5, type: "b_field_line", x1: 200, y1: 190, x2: 500, y2: 190, label: "B", color: "#10b981", strokeWidth: 2, fontSize: 18 },
|
|
2381
|
+
{ id: 6, type: "b_field_line", x1: 200, y1: 260, x2: 500, y2: 260, label: "", color: "#10b981", strokeWidth: 2 },
|
|
2382
|
+
{ id: 7, type: "b_field_curve", x1: 280, y1: 80, x2: 420, y2: 80, curveHeight: 50, label: "", color: "#10b981", strokeWidth: 2 },
|
|
2383
|
+
{ id: 8, type: "b_field_curve", x1: 250, y1: 80, x2: 450, y2: 80, curveHeight: 110, label: "", color: "#10b981", strokeWidth: 2 },
|
|
2384
|
+
{ id: 9, type: "axes_3d", x1: 200, y1: 540, x2: 300, y2: 540, label: "", color: "#64748b", strokeWidth: 2, fontSize: 16 },
|
|
2385
|
+
{ id: 10, type: "line", x1: 200, y1: 540, x2: 200, y2: 400, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
2386
|
+
{ id: 11, type: "line", x1: 200, y1: 400, x2: 320, y2: 400, label: "i", color: "#0ea5e9", strokeWidth: 3, fontSize: 16 },
|
|
2387
|
+
{ id: 12, type: "line", x1: 320, y1: 400, x2: 320, y2: 540, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
2388
|
+
{ id: 13, type: "line", x1: 320, y1: 540, x2: 200, y2: 540, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
2389
|
+
{ id: 14, type: "vector", x1: 200, y1: 540, x2: 320, y2: 620, label: "B", color: "#10b981", strokeWidth: 2.5, fontSize: 18 }
|
|
1891
2390
|
]
|
|
1892
2391
|
};
|
|
1893
|
-
|
|
1894
|
-
|
|
2392
|
+
var barMagnetField = {
|
|
2393
|
+
name: "Bar magnet & field lines",
|
|
2394
|
+
elements: [
|
|
2395
|
+
{ id: 1, type: "text", x1: 260, y1: 36, x2: 260, y2: 36, label: "Dipole field outside the magnet", color: "#475569", fontSize: 16 },
|
|
2396
|
+
{ id: 2, type: "bar_magnet", x1: 200, y1: 260, x2: 520, y2: 260, label: "Permanent magnet", color: "#0f172a", strokeWidth: 2 },
|
|
2397
|
+
{ id: 3, type: "b_field_curve", x1: 220, y1: 120, x2: 480, y2: 120, curveHeight: 80, color: "#10b981", strokeWidth: 2 },
|
|
2398
|
+
{ id: 4, type: "b_field_curve", x1: 200, y1: 400, x2: 500, y2: 400, curveHeight: -90, color: "#10b981", strokeWidth: 2 },
|
|
2399
|
+
{ id: 5, type: "b_field_line", x1: 360, y1: 140, x2: 360, y2: 220, color: "#10b981", strokeWidth: 2 },
|
|
2400
|
+
{ id: 6, type: "b_field_line", x1: 360, y1: 300, x2: 360, y2: 380, color: "#10b981", strokeWidth: 2 },
|
|
2401
|
+
{ id: 7, type: "text", x1: 600, y1: 240, x2: 600, y2: 240, label: "N \u2192 S outside", color: "#0f172a", fontSize: 15 }
|
|
2402
|
+
]
|
|
2403
|
+
};
|
|
2404
|
+
var longStraightWire = {
|
|
2405
|
+
name: "Long straight wire (Amp\xE8re)",
|
|
2406
|
+
elements: [
|
|
2407
|
+
{ id: 1, type: "text", x1: 240, y1: 36, x2: 240, y2: 36, label: "Current into page \u2297 \u2014 circular B around the wire", color: "#475569", fontSize: 15 },
|
|
2408
|
+
{ id: 2, type: "current_wire", x1: 400, y1: 120, x2: 400, y2: 420, label: "I", color: "#dc2626", strokeWidth: 3 },
|
|
2409
|
+
{ id: 3, type: "b_field_curve", x1: 520, y1: 200, x2: 280, y2: 200, curveHeight: 120, color: "#10b981", strokeWidth: 2 },
|
|
2410
|
+
{ id: 4, type: "b_field_curve", x1: 540, y1: 280, x2: 260, y2: 280, curveHeight: 140, color: "#10b981", strokeWidth: 2 },
|
|
2411
|
+
{ id: 5, type: "b_field_curve", x1: 500, y1: 360, x2: 300, y2: 360, curveHeight: 100, color: "#10b981", strokeWidth: 2 },
|
|
2412
|
+
{ id: 6, type: "b_region_in", x1: 360, y1: 240, x2: 440, y2: 320, color: "#6366f1", strokeWidth: 1.5 },
|
|
2413
|
+
{ id: 7, type: "text", x1: 400, y1: 460, x2: 400, y2: 460, label: "\u222E B\xB7dl = \u03BC\u2080I", color: "#0f172a", fontSize: 17 }
|
|
2414
|
+
]
|
|
2415
|
+
};
|
|
2416
|
+
var magnetismExamples = [electromagnetGap, barMagnetField, longStraightWire];
|
|
1895
2417
|
var magnetism = {
|
|
1896
2418
|
name: "Magnetism",
|
|
1897
|
-
elements: [
|
|
1898
|
-
|
|
1899
|
-
{ id: 2, type: "pole_piece", x1: 500, y1: 80, x2: 600, y2: 300, label: "S", color: "#0f172a", strokeWidth: 2 },
|
|
1900
|
-
{ id: 3, type: "b_field_line", x1: 200, y1: 120, x2: 500, y2: 120, label: "", color: "#10b981", strokeWidth: 2 },
|
|
1901
|
-
{ id: 4, type: "b_field_line", x1: 200, y1: 190, x2: 500, y2: 190, label: "B", color: "#10b981", strokeWidth: 2, fontSize: 18 },
|
|
1902
|
-
{ id: 5, type: "b_field_line", x1: 200, y1: 260, x2: 500, y2: 260, label: "", color: "#10b981", strokeWidth: 2 },
|
|
1903
|
-
{ id: 6, type: "b_field_curve", x1: 280, y1: 80, x2: 420, y2: 80, curveHeight: 50, label: "", color: "#10b981", strokeWidth: 2 },
|
|
1904
|
-
{ id: 7, type: "b_field_curve", x1: 250, y1: 80, x2: 450, y2: 80, curveHeight: 110, label: "", color: "#10b981", strokeWidth: 2 },
|
|
1905
|
-
{ id: 8, type: "axes_3d", x1: 200, y1: 540, x2: 300, y2: 540, label: "", color: "#64748b", strokeWidth: 2, fontSize: 16 },
|
|
1906
|
-
{ id: 9, type: "line", x1: 200, y1: 540, x2: 200, y2: 400, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
1907
|
-
{ id: 10, type: "line", x1: 200, y1: 400, x2: 320, y2: 400, label: "i", color: "#0ea5e9", strokeWidth: 3, fontSize: 16 },
|
|
1908
|
-
{ id: 11, type: "line", x1: 320, y1: 400, x2: 320, y2: 540, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
1909
|
-
{ id: 12, type: "line", x1: 320, y1: 540, x2: 200, y2: 540, label: "", color: "#0ea5e9", strokeWidth: 3 },
|
|
1910
|
-
{ id: 13, type: "vector", x1: 200, y1: 540, x2: 320, y2: 620, label: "B", color: "#10b981", strokeWidth: 2.5, fontSize: 18 }
|
|
1911
|
-
],
|
|
2419
|
+
elements: magnetismExamples[0].elements,
|
|
2420
|
+
examples: magnetismExamples,
|
|
1912
2421
|
toolCategories: [
|
|
1913
2422
|
{
|
|
1914
2423
|
name: "Basics",
|
|
@@ -1958,10 +2467,10 @@ var magnetism = {
|
|
|
1958
2467
|
]
|
|
1959
2468
|
};
|
|
1960
2469
|
|
|
1961
|
-
// src/editor/presets/
|
|
1962
|
-
var
|
|
2470
|
+
// src/editor/presets/light.ts
|
|
2471
|
+
var lightExamples = [
|
|
1963
2472
|
{
|
|
1964
|
-
name: "
|
|
2473
|
+
name: "Lens combination",
|
|
1965
2474
|
elements: [
|
|
1966
2475
|
{ id: 1, type: "line", x1: 50, y1: 300, x2: 850, y2: 300, lineStyle: "dashed", color: "#94a3b8", strokeWidth: 2 },
|
|
1967
2476
|
{ id: 2, type: "lens_convex", x1: 300, y1: 150, x2: 300, y2: 450, color: "#38bdf8", strokeWidth: 2, label: "f\u2081 = +30cm" },
|
|
@@ -1974,11 +2483,11 @@ var LIGHT_TOPICS = [
|
|
|
1974
2483
|
{ id: 9, type: "ray", x1: 500, y1: 334, x2: 800, y2: 334, color: "#ef4444", strokeWidth: 2 },
|
|
1975
2484
|
{ id: 10, type: "line", x1: 500, y1: 266, x2: 600, y2: 300, lineStyle: "dashed", color: "#ef4444", strokeWidth: 2 },
|
|
1976
2485
|
{ id: 11, type: "line", x1: 500, y1: 334, x2: 600, y2: 300, lineStyle: "dashed", color: "#ef4444", strokeWidth: 2 },
|
|
1977
|
-
{ id: 12, type: "point", x1: 600, y1: 300, x2: 600, y2: 300, label: "Virtual
|
|
2486
|
+
{ id: 12, type: "point", x1: 600, y1: 300, x2: 600, y2: 300, label: "Virtual object", color: "#64748b" }
|
|
1978
2487
|
]
|
|
1979
2488
|
},
|
|
1980
2489
|
{
|
|
1981
|
-
name: "
|
|
2490
|
+
name: "Concave mirror (real image)",
|
|
1982
2491
|
elements: [
|
|
1983
2492
|
{ id: 1, type: "line", x1: 50, y1: 300, x2: 700, y2: 300, lineStyle: "dashed", color: "#94a3b8", strokeWidth: 2 },
|
|
1984
2493
|
{ id: 2, type: "mirror_concave", x1: 600, y1: 150, x2: 600, y2: 450, curveHeight: 40, color: "#0f172a", strokeWidth: 2 },
|
|
@@ -1994,28 +2503,28 @@ var LIGHT_TOPICS = [
|
|
|
1994
2503
|
]
|
|
1995
2504
|
},
|
|
1996
2505
|
{
|
|
1997
|
-
name: "
|
|
2506
|
+
name: "Apparent depth (refraction)",
|
|
1998
2507
|
elements: [
|
|
1999
2508
|
{ id: 1, type: "glass_slab", x1: 50, y1: 300, x2: 850, y2: 600, color: "#38bdf8", label: "Water (\u03BC = 4/3)", strokeWidth: 2 },
|
|
2000
|
-
{ id: 2, type: "point", x1: 450, y1: 500, x2: 450, y2: 500, label: "Real
|
|
2509
|
+
{ id: 2, type: "point", x1: 450, y1: 500, x2: 450, y2: 500, label: "Real object", color: "#0f172a" },
|
|
2001
2510
|
{ id: 3, type: "ray", x1: 450, y1: 500, x2: 450, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
2002
2511
|
{ id: 4, type: "ray", x1: 450, y1: 300, x2: 450, y2: 100, color: "#ef4444", strokeWidth: 2 },
|
|
2003
2512
|
{ id: 5, type: "ray", x1: 450, y1: 500, x2: 550, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
2004
2513
|
{ id: 6, type: "ray", x1: 550, y1: 300, x2: 700, y2: 150, color: "#ef4444", strokeWidth: 2 },
|
|
2005
2514
|
{ id: 7, type: "line", x1: 550, y1: 300, x2: 450, y2: 400, lineStyle: "dashed", color: "#ef4444", strokeWidth: 2 },
|
|
2006
|
-
{ id: 8, type: "point", x1: 450, y1: 400, x2: 450, y2: 400, label: "Virtual
|
|
2515
|
+
{ id: 8, type: "point", x1: 450, y1: 400, x2: 450, y2: 400, label: "Virtual image", color: "#f59e0b" },
|
|
2007
2516
|
{ id: 9, type: "line", x1: 550, y1: 200, x2: 550, y2: 400, lineStyle: "dashed", color: "#94a3b8", strokeWidth: 1 }
|
|
2008
2517
|
]
|
|
2009
2518
|
},
|
|
2010
2519
|
{
|
|
2011
|
-
name: "
|
|
2520
|
+
name: "Double-slit interference",
|
|
2012
2521
|
elements: [
|
|
2013
2522
|
{ id: 1, type: "slit_double", x1: 200, y1: 200, x2: 200, y2: 400, color: "#0f172a", strokeWidth: 4 },
|
|
2014
2523
|
{ id: 2, type: "line", x1: 700, y1: 100, x2: 700, y2: 500, color: "#0f172a", strokeWidth: 4, label: "Screen" },
|
|
2015
2524
|
{ id: 3, type: "line", x1: 200, y1: 300, x2: 700, y2: 300, lineStyle: "dashed", color: "#94a3b8", strokeWidth: 2 },
|
|
2016
2525
|
{ id: 4, type: "point", x1: 200, y1: 250, x2: 200, y2: 250, label: "S\u2081", color: "#0f172a" },
|
|
2017
2526
|
{ id: 5, type: "point", x1: 200, y1: 350, x2: 200, y2: 350, label: "S\u2082", color: "#0f172a" },
|
|
2018
|
-
{ id: 6, type: "point", x1: 700, y1: 150, x2: 700, y2: 150, label: "P (
|
|
2527
|
+
{ id: 6, type: "point", x1: 700, y1: 150, x2: 700, y2: 150, label: "P (max/min)", color: "#0f172a" },
|
|
2019
2528
|
{ id: 7, type: "photon", x1: 200, y1: 250, x2: 700, y2: 150, color: "#eab308", strokeWidth: 2 },
|
|
2020
2529
|
{ id: 8, type: "photon", x1: 200, y1: 350, x2: 700, y2: 150, color: "#eab308", strokeWidth: 2 },
|
|
2021
2530
|
{ id: 9, type: "line", x1: 200, y1: 250, x2: 240, y2: 340, lineStyle: "dashed", color: "#ef4444", strokeWidth: 2 },
|
|
@@ -2026,7 +2535,7 @@ var LIGHT_TOPICS = [
|
|
|
2026
2535
|
]
|
|
2027
2536
|
},
|
|
2028
2537
|
{
|
|
2029
|
-
name: "
|
|
2538
|
+
name: "Single-slit diffraction",
|
|
2030
2539
|
elements: [
|
|
2031
2540
|
{ id: 1, type: "slit_single", x1: 300, y1: 200, x2: 300, y2: 400, color: "#0f172a", strokeWidth: 5, label: "Width a" },
|
|
2032
2541
|
{ id: 2, type: "line", x1: 700, y1: 100, x2: 700, y2: 500, color: "#0f172a", strokeWidth: 4 },
|
|
@@ -2037,89 +2546,77 @@ var LIGHT_TOPICS = [
|
|
|
2037
2546
|
{ id: 7, type: "ray", x1: 300, y1: 380, x2: 700, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
2038
2547
|
{ id: 8, type: "ray", x1: 300, y1: 220, x2: 700, y2: 150, color: "#3b82f6", strokeWidth: 2 },
|
|
2039
2548
|
{ id: 9, type: "ray", x1: 300, y1: 380, x2: 700, y2: 150, color: "#3b82f6", strokeWidth: 2 },
|
|
2040
|
-
{ id: 10, type: "point", x1: 700, y1: 300, x2: 700, y2: 300, label: "Central
|
|
2041
|
-
{ id: 11, type: "point", x1: 700, y1: 150, x2: 700, y2: 150, label: "1st
|
|
2549
|
+
{ id: 10, type: "point", x1: 700, y1: 300, x2: 700, y2: 300, label: "Central max", color: "#ef4444" },
|
|
2550
|
+
{ id: 11, type: "point", x1: 700, y1: 150, x2: 700, y2: 150, label: "1st min (a sin \u03B8 = \u03BB)", color: "#3b82f6" }
|
|
2042
2551
|
]
|
|
2043
2552
|
}
|
|
2044
2553
|
];
|
|
2045
|
-
|
|
2046
|
-
// src/editor/presets/light.ts
|
|
2047
2554
|
var light = {
|
|
2048
|
-
name: "Light",
|
|
2049
|
-
elements:
|
|
2555
|
+
name: "Light & optics",
|
|
2556
|
+
elements: lightExamples[0].elements,
|
|
2557
|
+
examples: lightExamples,
|
|
2050
2558
|
toolCategories: [
|
|
2051
2559
|
{
|
|
2052
2560
|
name: "Basics",
|
|
2053
2561
|
tools: [
|
|
2054
2562
|
{ id: "select", name: "Select/Move" },
|
|
2055
2563
|
{ id: "point", name: "Point/Node" },
|
|
2056
|
-
{ id: "line", name: "Solid
|
|
2564
|
+
{ id: "line", name: "Solid line" },
|
|
2057
2565
|
{ id: "vector", name: "Vector/Object" },
|
|
2058
|
-
{ id: "text", name: "Text
|
|
2566
|
+
{ id: "text", name: "Text label" }
|
|
2059
2567
|
]
|
|
2060
2568
|
},
|
|
2061
2569
|
{
|
|
2062
2570
|
name: "Optics",
|
|
2063
2571
|
tools: [
|
|
2064
|
-
{ id: "ray", name: "Light
|
|
2065
|
-
{ id: "lens_convex", name: "Convex
|
|
2066
|
-
{ id: "lens_concave", name: "Concave
|
|
2067
|
-
{ id: "mirror_plane", name: "Plane
|
|
2068
|
-
{ id: "mirror_concave", name: "Concave
|
|
2069
|
-
{ id: "mirror_convex", name: "Convex
|
|
2070
|
-
{ id: "prism", name: "Glass
|
|
2071
|
-
{ id: "glass_slab", name: "Glass
|
|
2572
|
+
{ id: "ray", name: "Light ray" },
|
|
2573
|
+
{ id: "lens_convex", name: "Convex lens" },
|
|
2574
|
+
{ id: "lens_concave", name: "Concave lens" },
|
|
2575
|
+
{ id: "mirror_plane", name: "Plane mirror" },
|
|
2576
|
+
{ id: "mirror_concave", name: "Concave mirror" },
|
|
2577
|
+
{ id: "mirror_convex", name: "Convex mirror" },
|
|
2578
|
+
{ id: "prism", name: "Glass prism" },
|
|
2579
|
+
{ id: "glass_slab", name: "Glass slab" }
|
|
2072
2580
|
]
|
|
2073
2581
|
},
|
|
2074
2582
|
{
|
|
2075
|
-
name: "Modern
|
|
2583
|
+
name: "Modern physics",
|
|
2076
2584
|
tools: [
|
|
2077
|
-
{ id: "photon", name: "Photon (
|
|
2078
|
-
{ id: "slit_double", name: "Double
|
|
2079
|
-
{ id: "slit_single", name: "Single
|
|
2080
|
-
{ id: "energy_level", name: "Energy
|
|
2585
|
+
{ id: "photon", name: "Photon (wavy)" },
|
|
2586
|
+
{ id: "slit_double", name: "Double slit" },
|
|
2587
|
+
{ id: "slit_single", name: "Single slit" },
|
|
2588
|
+
{ id: "energy_level", name: "Energy level" },
|
|
2081
2589
|
{ id: "nucleus", name: "Atom/Nucleus" }
|
|
2082
2590
|
]
|
|
2083
2591
|
}
|
|
2084
2592
|
]
|
|
2085
2593
|
};
|
|
2086
2594
|
|
|
2087
|
-
// src/editor/presets/waves.ts
|
|
2088
|
-
var waves = {
|
|
2089
|
-
name: "Waves",
|
|
2090
|
-
elements: [
|
|
2091
|
-
{ id: 1, type: "line", x1: 100, y1: 300, x2: 800, y2: 300, color: "#64748b", strokeWidth: 2 },
|
|
2092
|
-
{ id: 2, type: "slit_double", x1: 200, y1: 200, x2: 200, y2: 400, color: "#0f172a", strokeWidth: 4 },
|
|
2093
|
-
{ id: 3, type: "photon", x1: 200, y1: 250, x2: 700, y2: 150, color: "#eab308", strokeWidth: 2 }
|
|
2094
|
-
],
|
|
2095
|
-
toolCategories: [{ name: "Waves", tools: [{ id: "select", name: "Select" }, { id: "line", name: "Axis" }, { id: "slit_double", name: "Double Slit" }, { id: "photon", name: "Wave Ray" }, { id: "text", name: "Text" }] }]
|
|
2096
|
-
};
|
|
2097
|
-
|
|
2098
2595
|
// src/editor/presets/waveOscillation.ts
|
|
2099
|
-
var
|
|
2100
|
-
name: "
|
|
2596
|
+
var shmKinematics = {
|
|
2597
|
+
name: "SHM kinematics",
|
|
2101
2598
|
elements: [
|
|
2102
|
-
{ id:
|
|
2599
|
+
{ id: 1, type: "text", x1: 120, y1: 36, x2: 120, y2: 36, label: "Motion along x vs time graphs (x, v, a)", color: "#475569", fontSize: 17 },
|
|
2103
2600
|
{
|
|
2104
|
-
id:
|
|
2601
|
+
id: 2,
|
|
2105
2602
|
type: "strobe_shm",
|
|
2106
2603
|
x1: 120,
|
|
2107
|
-
y1:
|
|
2604
|
+
y1: 100,
|
|
2108
2605
|
x2: 120,
|
|
2109
|
-
y2:
|
|
2606
|
+
y2: 300,
|
|
2110
2607
|
amplitude: 60,
|
|
2111
2608
|
loops: 1,
|
|
2112
2609
|
color: "#f59e0b",
|
|
2113
2610
|
strokeWidth: 2,
|
|
2114
|
-
label: "
|
|
2611
|
+
label: "Mass on spring"
|
|
2115
2612
|
},
|
|
2116
2613
|
{
|
|
2117
|
-
id:
|
|
2614
|
+
id: 3,
|
|
2118
2615
|
type: "shm_graph",
|
|
2119
2616
|
x1: 260,
|
|
2120
|
-
y1:
|
|
2617
|
+
y1: 200,
|
|
2121
2618
|
x2: 460,
|
|
2122
|
-
y2:
|
|
2619
|
+
y2: 200,
|
|
2123
2620
|
amplitude: 60,
|
|
2124
2621
|
loops: 1,
|
|
2125
2622
|
graphType: "all",
|
|
@@ -2127,14 +2624,20 @@ var waveOscillation = {
|
|
|
2127
2624
|
strokeWidth: 2,
|
|
2128
2625
|
label: "x(t), v(t), a(t)"
|
|
2129
2626
|
},
|
|
2130
|
-
{ id:
|
|
2627
|
+
{ id: 4, type: "text", x1: 520, y1: 200, x2: 520, y2: 200, label: "\u03C9\xB2 = k/m", color: "#0f172a", fontSize: 16 }
|
|
2628
|
+
]
|
|
2629
|
+
};
|
|
2630
|
+
var pendulumAndPhasor = {
|
|
2631
|
+
name: "Pendulum & phasor",
|
|
2632
|
+
elements: [
|
|
2633
|
+
{ id: 1, type: "text", x1: 140, y1: 36, x2: 140, y2: 36, label: "Small oscillations + rotating phasor picture", color: "#475569", fontSize: 17 },
|
|
2131
2634
|
{
|
|
2132
|
-
id:
|
|
2635
|
+
id: 2,
|
|
2133
2636
|
type: "pendulum",
|
|
2134
|
-
x1:
|
|
2135
|
-
y1:
|
|
2136
|
-
x2:
|
|
2137
|
-
y2:
|
|
2637
|
+
x1: 200,
|
|
2638
|
+
y1: 100,
|
|
2639
|
+
x2: 260,
|
|
2640
|
+
y2: 240,
|
|
2138
2641
|
label: "m",
|
|
2139
2642
|
color: "#0ea5e9",
|
|
2140
2643
|
strokeWidth: 2,
|
|
@@ -2142,56 +2645,105 @@ var waveOscillation = {
|
|
|
2142
2645
|
showForces: true
|
|
2143
2646
|
},
|
|
2144
2647
|
{
|
|
2145
|
-
id:
|
|
2648
|
+
id: 3,
|
|
2146
2649
|
type: "phasor",
|
|
2147
|
-
x1:
|
|
2148
|
-
y1:
|
|
2149
|
-
x2:
|
|
2650
|
+
x1: 420,
|
|
2651
|
+
y1: 170,
|
|
2652
|
+
x2: 500,
|
|
2150
2653
|
y2: 90,
|
|
2151
2654
|
label: "\u03C9t",
|
|
2152
2655
|
color: "#8b5cf6",
|
|
2153
2656
|
strokeWidth: 2,
|
|
2154
2657
|
showProjection: true
|
|
2155
2658
|
},
|
|
2156
|
-
{
|
|
2659
|
+
{
|
|
2660
|
+
id: 4,
|
|
2661
|
+
type: "spring",
|
|
2662
|
+
x1: 620,
|
|
2663
|
+
y1: 120,
|
|
2664
|
+
x2: 620,
|
|
2665
|
+
y2: 240,
|
|
2666
|
+
color: "#3b82f6",
|
|
2667
|
+
strokeWidth: 2,
|
|
2668
|
+
coils: 7
|
|
2669
|
+
},
|
|
2157
2670
|
{
|
|
2158
2671
|
id: 5,
|
|
2672
|
+
type: "mass_box",
|
|
2673
|
+
x1: 600,
|
|
2674
|
+
y1: 240,
|
|
2675
|
+
x2: 640,
|
|
2676
|
+
y2: 280,
|
|
2677
|
+
color: "#ef4444",
|
|
2678
|
+
strokeWidth: 2,
|
|
2679
|
+
label: "m"
|
|
2680
|
+
},
|
|
2681
|
+
{ id: 6, type: "text", x1: 620, y1: 320, x2: 620, y2: 320, label: "Same \u03C9 for linear & torsional SHM", color: "#64748b", fontSize: 14 }
|
|
2682
|
+
]
|
|
2683
|
+
};
|
|
2684
|
+
var dampingAndEnergy = {
|
|
2685
|
+
name: "Damping & energy",
|
|
2686
|
+
elements: [
|
|
2687
|
+
{ id: 1, type: "text", x1: 120, y1: 36, x2: 120, y2: 36, label: "Lossy oscillator: energy swap + torsion mode", color: "#475569", fontSize: 17 },
|
|
2688
|
+
{
|
|
2689
|
+
id: 2,
|
|
2159
2690
|
type: "energy_graph",
|
|
2160
|
-
x1:
|
|
2161
|
-
y1:
|
|
2162
|
-
x2:
|
|
2163
|
-
y2:
|
|
2691
|
+
x1: 100,
|
|
2692
|
+
y1: 280,
|
|
2693
|
+
x2: 300,
|
|
2694
|
+
y2: 280,
|
|
2164
2695
|
amplitude: 80,
|
|
2165
2696
|
domain: "time",
|
|
2166
2697
|
color: "#1e293b",
|
|
2167
2698
|
strokeWidth: 2,
|
|
2168
|
-
label: "U(t)
|
|
2699
|
+
label: "U(t), K(t)"
|
|
2169
2700
|
},
|
|
2170
2701
|
{
|
|
2171
|
-
id:
|
|
2702
|
+
id: 3,
|
|
2172
2703
|
type: "vane_liquid",
|
|
2173
|
-
x1:
|
|
2174
|
-
y1:
|
|
2175
|
-
x2:
|
|
2176
|
-
y2:
|
|
2704
|
+
x1: 380,
|
|
2705
|
+
y1: 200,
|
|
2706
|
+
x2: 460,
|
|
2707
|
+
y2: 200,
|
|
2177
2708
|
color: "#64748b",
|
|
2178
2709
|
strokeWidth: 2,
|
|
2179
|
-
label: "
|
|
2710
|
+
label: "Drag \u221D v"
|
|
2711
|
+
},
|
|
2712
|
+
{ id: 4, type: "spring", x1: 420, y1: 80, x2: 420, y2: 200, color: "#3b82f6", strokeWidth: 2, coils: 6 },
|
|
2713
|
+
{
|
|
2714
|
+
id: 5,
|
|
2715
|
+
type: "damped_wave",
|
|
2716
|
+
x1: 520,
|
|
2717
|
+
y1: 240,
|
|
2718
|
+
x2: 720,
|
|
2719
|
+
y2: 240,
|
|
2720
|
+
amplitude: 45,
|
|
2721
|
+
damping: 0.02,
|
|
2722
|
+
frequency: 12,
|
|
2723
|
+
color: "#ec4899",
|
|
2724
|
+
strokeWidth: 2,
|
|
2725
|
+
label: "x(t) envelope"
|
|
2180
2726
|
},
|
|
2181
|
-
{ id: 7, type: "spring", x1: 440, y1: 260, x2: 440, y2: 380, color: "#3b82f6", strokeWidth: 2, coils: 6 },
|
|
2182
|
-
{ id: 104, type: "text", x1: 440, y1: 240, x2: 440, y2: 240, label: "Rigid Support", fontSize: 14, color: "#64748b" },
|
|
2183
2727
|
{
|
|
2184
|
-
id:
|
|
2728
|
+
id: 6,
|
|
2185
2729
|
type: "torsion_pendulum",
|
|
2186
|
-
x1:
|
|
2187
|
-
y1:
|
|
2188
|
-
x2:
|
|
2189
|
-
y2:
|
|
2730
|
+
x1: 320,
|
|
2731
|
+
y1: 380,
|
|
2732
|
+
x2: 320,
|
|
2733
|
+
y2: 520,
|
|
2190
2734
|
color: "#ec4899",
|
|
2191
2735
|
strokeWidth: 2,
|
|
2192
|
-
|
|
2736
|
+
size: 44,
|
|
2737
|
+
rotation: 22,
|
|
2738
|
+
label: "Disk + fiber"
|
|
2193
2739
|
}
|
|
2194
|
-
]
|
|
2740
|
+
]
|
|
2741
|
+
};
|
|
2742
|
+
var waveExamples = [shmKinematics, pendulumAndPhasor, dampingAndEnergy];
|
|
2743
|
+
var waveOscillation = {
|
|
2744
|
+
name: "Oscillations & Waves",
|
|
2745
|
+
elements: waveExamples[0].elements,
|
|
2746
|
+
examples: waveExamples,
|
|
2195
2747
|
toolCategories: [
|
|
2196
2748
|
{
|
|
2197
2749
|
name: "Basics",
|
|
@@ -2241,47 +2793,63 @@ var waveOscillation = {
|
|
|
2241
2793
|
};
|
|
2242
2794
|
|
|
2243
2795
|
// src/editor/presets/rotation.ts
|
|
2244
|
-
var
|
|
2245
|
-
name: "
|
|
2796
|
+
var collisionCom = {
|
|
2797
|
+
name: "Collision & center of mass",
|
|
2246
2798
|
elements: [
|
|
2247
|
-
{ id:
|
|
2248
|
-
{ id:
|
|
2249
|
-
{ id:
|
|
2250
|
-
{ id:
|
|
2251
|
-
{ id:
|
|
2252
|
-
{ id:
|
|
2253
|
-
{ id:
|
|
2254
|
-
{ id:
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
{ id:
|
|
2261
|
-
{ id:
|
|
2262
|
-
{
|
|
2263
|
-
|
|
2799
|
+
{ id: 1, type: "text", x1: 120, y1: 36, x2: 120, y2: 36, label: "Two bodies before/after contact \u2014 COM frame", color: "#475569", fontSize: 17 },
|
|
2800
|
+
{ id: 2, type: "point_mass", x1: 80, y1: 140, x2: 80, y2: 140, size: 25, color: "#ef4444", label: "m\u2081" },
|
|
2801
|
+
{ id: 3, type: "vector", x1: 80, y1: 140, x2: 180, y2: 140, color: "#ef4444", label: "u\u2081", strokeWidth: 2 },
|
|
2802
|
+
{ id: 4, type: "point_mass", x1: 240, y1: 100, x2: 240, y2: 100, size: 15, color: "#3b82f6", label: "m\u2082" },
|
|
2803
|
+
{ id: 5, type: "dashed_path", x1: 180, y1: 140, x2: 320, y2: 80, color: "#ef4444", strokeWidth: 1.5 },
|
|
2804
|
+
{ id: 6, type: "dashed_path", x1: 240, y1: 100, x2: 340, y2: 180, color: "#3b82f6", strokeWidth: 1.5 },
|
|
2805
|
+
{ id: 7, type: "com_indicator", x1: 160, y1: 120, x2: 160, y2: 120, color: "#10b981", size: 15, label: "COM" },
|
|
2806
|
+
{ id: 8, type: "system_boundary", x1: 40, y1: 60, x2: 360, y2: 220, color: "#94a3b8", strokeWidth: 1.5 }
|
|
2807
|
+
]
|
|
2808
|
+
};
|
|
2809
|
+
var rigidRodTorque = {
|
|
2810
|
+
name: "Rigid rod & torque",
|
|
2811
|
+
elements: [
|
|
2812
|
+
{ id: 1, type: "text", x1: 140, y1: 36, x2: 140, y2: 36, label: "Hinged rod: weight, pivot reaction, angular accel", color: "#475569", fontSize: 17 },
|
|
2813
|
+
{ id: 2, type: "pivot", x1: 120, y1: 160, x2: 120, y2: 160, color: "#64748b", size: 25 },
|
|
2814
|
+
{ id: 3, type: "uniform_rod", x1: 120, y1: 160, x2: 420, y2: 200, color: "#f59e0b", strokeWidth: 12, label: "L, M" },
|
|
2815
|
+
{ id: 4, type: "vector", x1: 420, y1: 200, x2: 420, y2: 300, color: "#ef4444", label: "mg", strokeWidth: 2 },
|
|
2816
|
+
{ id: 5, type: "curve_arrow", x1: 120, y1: 160, x2: 200, y2: 240, color: "#8b5cf6", strokeWidth: 2, label: "\u03B1" },
|
|
2817
|
+
{ id: 6, type: "text", x1: 480, y1: 200, x2: 480, y2: 200, label: "\u03C4 = I\u03B1 about pivot", color: "#0f172a", fontSize: 15 }
|
|
2818
|
+
]
|
|
2819
|
+
};
|
|
2820
|
+
var rollingPulleyRocket = {
|
|
2821
|
+
name: "Rolling, pulleys & rocket",
|
|
2822
|
+
elements: [
|
|
2823
|
+
{ id: 1, type: "text", x1: 100, y1: 36, x2: 100, y2: 36, label: "Rolling on incline \xB7 Atwood \xB7 variable-mass rocket", color: "#475569", fontSize: 16 },
|
|
2824
|
+
{ id: 2, type: "inclined_wedge", x1: 60, y1: 200, x2: 360, y2: 360, color: "#64748b", strokeWidth: 2, label: "\u03B8" },
|
|
2825
|
+
{
|
|
2826
|
+
id: 3,
|
|
2264
2827
|
type: "rolling_body",
|
|
2265
2828
|
x1: 160,
|
|
2266
|
-
y1:
|
|
2829
|
+
y1: 230,
|
|
2267
2830
|
x2: 200,
|
|
2268
|
-
y2:
|
|
2831
|
+
y2: 230,
|
|
2269
2832
|
color: "#3b82f6",
|
|
2270
2833
|
strokeWidth: 2,
|
|
2271
2834
|
label: "M, R",
|
|
2272
2835
|
showVelocity: true,
|
|
2273
2836
|
showOmega: true
|
|
2274
2837
|
},
|
|
2275
|
-
{ id:
|
|
2276
|
-
{ id:
|
|
2277
|
-
{ id:
|
|
2278
|
-
{ id:
|
|
2279
|
-
{ id:
|
|
2280
|
-
{ id:
|
|
2281
|
-
{ id:
|
|
2282
|
-
{ id:
|
|
2283
|
-
|
|
2284
|
-
|
|
2838
|
+
{ id: 4, type: "vector", x1: 160, y1: 250, x2: 110, y2: 225, color: "#ef4444", label: "f_s", strokeWidth: 2 },
|
|
2839
|
+
{ id: 5, type: "pulley", x1: 420, y1: 200, x2: 460, y2: 200, color: "#64748b", strokeWidth: 2 },
|
|
2840
|
+
{ id: 6, type: "block_mass", x1: 360, y1: 300, x2: 400, y2: 340, color: "#0ea5e9", label: "m\u2081" },
|
|
2841
|
+
{ id: 7, type: "block_mass", x1: 500, y1: 240, x2: 540, y2: 280, color: "#0ea5e9", label: "m\u2082" },
|
|
2842
|
+
{ id: 8, type: "line", x1: 380, y1: 300, x2: 380, y2: 200, color: "#1e293b", strokeWidth: 1.5 },
|
|
2843
|
+
{ id: 9, type: "line", x1: 520, y1: 260, x2: 520, y2: 200, color: "#1e293b", strokeWidth: 1.5 },
|
|
2844
|
+
{ id: 10, type: "rocket", x1: 620, y1: 340, x2: 620, y2: 220, color: "#3b82f6", strokeWidth: 2, label: "v(t)" },
|
|
2845
|
+
{ id: 11, type: "vector", x1: 620, y1: 340, x2: 620, y2: 400, color: "#f97316", strokeWidth: 2, label: "u_rel dm/dt" }
|
|
2846
|
+
]
|
|
2847
|
+
};
|
|
2848
|
+
var rotationExamples = [collisionCom, rigidRodTorque, rollingPulleyRocket];
|
|
2849
|
+
var rotation = {
|
|
2850
|
+
name: "Rotation",
|
|
2851
|
+
elements: rotationExamples[0].elements,
|
|
2852
|
+
examples: rotationExamples,
|
|
2285
2853
|
toolCategories: [
|
|
2286
2854
|
{
|
|
2287
2855
|
name: "Basics",
|
|
@@ -2326,57 +2894,83 @@ var rotation = {
|
|
|
2326
2894
|
};
|
|
2327
2895
|
|
|
2328
2896
|
// src/editor/presets/graph.ts
|
|
2329
|
-
var
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
id:
|
|
2339
|
-
type: "
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
id:
|
|
2366
|
-
type: "
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2897
|
+
var chargesAndRC = {
|
|
2898
|
+
name: "Charges, capacitor & field",
|
|
2899
|
+
elements: [
|
|
2900
|
+
{ id: 1, type: "text", x1: 320, y1: 24, x2: 320, y2: 24, label: "RC branch + point charges in an external E", color: "#475569", fontSize: 16 },
|
|
2901
|
+
{ id: 2, type: "capacitor", x1: 260, y1: 200, x2: 460, y2: 200, label: "C = 10\u03BCF", color: "#0f172a", strokeWidth: 3, fontSize: 18 },
|
|
2902
|
+
{ id: 3, type: "line", x1: 260, y1: 200, x2: 260, y2: 400, color: "#0f172a", strokeWidth: 2 },
|
|
2903
|
+
{ id: 4, type: "line", x1: 460, y1: 200, x2: 460, y2: 400, color: "#0f172a", strokeWidth: 2 },
|
|
2904
|
+
{ id: 5, type: "capacitor", x1: 260, y1: 400, x2: 460, y2: 400, label: "V = 12V", color: "#0f172a", strokeWidth: 3, fontSize: 18 },
|
|
2905
|
+
{ id: 6, type: "ground", x1: 460, y1: 400, x2: 460, y2: 460, label: "", color: "#0f172a", strokeWidth: 2 },
|
|
2906
|
+
{ id: 7, type: "charge_plus", x1: 340, y1: 180, x2: 340, y2: 180, label: "+Q", color: "#ef4444", strokeWidth: 2, fontSize: 16 },
|
|
2907
|
+
{ id: 8, type: "charge_minus", x1: 380, y1: 180, x2: 380, y2: 180, label: "-Q", color: "#3b82f6", strokeWidth: 2, fontSize: 16 },
|
|
2908
|
+
{
|
|
2909
|
+
id: 9,
|
|
2910
|
+
type: "vector",
|
|
2911
|
+
x1: 345,
|
|
2912
|
+
y1: 190,
|
|
2913
|
+
x2: 375,
|
|
2914
|
+
y2: 190,
|
|
2915
|
+
label: "",
|
|
2916
|
+
color: "#ef4444",
|
|
2917
|
+
strokeWidth: 1.5,
|
|
2918
|
+
lineStyle: "dashed"
|
|
2919
|
+
},
|
|
2920
|
+
{
|
|
2921
|
+
id: 10,
|
|
2922
|
+
type: "vector",
|
|
2923
|
+
x1: 345,
|
|
2924
|
+
y1: 210,
|
|
2925
|
+
x2: 375,
|
|
2926
|
+
y2: 210,
|
|
2927
|
+
label: "",
|
|
2928
|
+
color: "#ef4444",
|
|
2929
|
+
strokeWidth: 1.5,
|
|
2930
|
+
lineStyle: "dashed"
|
|
2931
|
+
},
|
|
2932
|
+
{ id: 11, type: "charge_plus", x1: 600, y1: 300, x2: 600, y2: 300, label: "+q", color: "#ef4444", strokeWidth: 2, fontSize: 18 },
|
|
2933
|
+
{ id: 12, type: "charge_minus", x1: 800, y1: 300, x2: 800, y2: 300, label: "-q", color: "#3b82f6", strokeWidth: 2, fontSize: 18 },
|
|
2934
|
+
{ id: 13, type: "vector", x1: 620, y1: 300, x2: 780, y2: 300, label: "E", color: "#94a3b8", strokeWidth: 2, fontSize: 18 },
|
|
2935
|
+
{
|
|
2936
|
+
id: 14,
|
|
2937
|
+
type: "circle",
|
|
2938
|
+
x1: 600,
|
|
2939
|
+
y1: 300,
|
|
2940
|
+
x2: 660,
|
|
2941
|
+
y2: 300,
|
|
2942
|
+
label: "",
|
|
2943
|
+
color: "#ef4444",
|
|
2944
|
+
strokeWidth: 1.5,
|
|
2945
|
+
lineStyle: "dashed"
|
|
2946
|
+
}
|
|
2947
|
+
]
|
|
2948
|
+
};
|
|
2949
|
+
var coordinateClassics = {
|
|
2950
|
+
name: "Coordinate plane: parabola & sine",
|
|
2951
|
+
elements: [
|
|
2952
|
+
{ id: 1, type: "text", x1: 280, y1: 24, x2: 280, y2: 24, label: "Standard graphs in x\u2013y", color: "#475569", fontSize: 16 },
|
|
2953
|
+
{ id: 2, type: "axes", x1: 120, y1: 380, x2: 520, y2: 80, color: "#0f172a", strokeWidth: 2 },
|
|
2954
|
+
{ id: 3, type: "parabola_v", x1: 200, y1: 200, x2: 440, y2: 340, color: "#2563eb", strokeWidth: 2.5, label: "y \u221D x\xB2" },
|
|
2955
|
+
{ id: 4, type: "sine_wave", x1: 140, y1: 260, x2: 500, y2: 260, color: "#db2777", strokeWidth: 2.5, label: "sin x", amplitude: 40, loops: 2 },
|
|
2956
|
+
{ id: 5, type: "text", x1: 560, y1: 120, x2: 560, y2: 120, label: "Use axes bbox for domain", color: "#64748b", fontSize: 14 }
|
|
2957
|
+
]
|
|
2958
|
+
};
|
|
2959
|
+
var hyperbolaAndModulus = {
|
|
2960
|
+
name: "Hyperbola & modulus",
|
|
2961
|
+
elements: [
|
|
2962
|
+
{ id: 1, type: "text", x1: 260, y1: 24, x2: 260, y2: 24, label: "Rational-style curves & piecewise linear", color: "#475569", fontSize: 16 },
|
|
2963
|
+
{ id: 2, type: "axes", x1: 100, y1: 400, x2: 540, y2: 60, color: "#0f172a", strokeWidth: 2 },
|
|
2964
|
+
{ id: 3, type: "hyperbola", x1: 320, y1: 100, x2: 480, y2: 360, color: "#7c3aed", strokeWidth: 2.5, label: "xy = const" },
|
|
2965
|
+
{ id: 4, type: "modulus", x1: 160, y1: 320, x2: 280, y2: 180, color: "#ea580c", strokeWidth: 2.5, label: "|x - a|" },
|
|
2966
|
+
{ id: 5, type: "text", x1: 560, y1: 280, x2: 560, y2: 280, label: "Asymptotes & kinks", color: "#64748b", fontSize: 14 }
|
|
2967
|
+
]
|
|
2968
|
+
};
|
|
2969
|
+
var graphExamples = [chargesAndRC, coordinateClassics, hyperbolaAndModulus];
|
|
2377
2970
|
var graph = {
|
|
2378
2971
|
name: "Graph",
|
|
2379
|
-
elements:
|
|
2972
|
+
elements: graphExamples[0].elements,
|
|
2973
|
+
examples: graphExamples,
|
|
2380
2974
|
toolCategories: [
|
|
2381
2975
|
{
|
|
2382
2976
|
name: "Basic",
|
|
@@ -2430,30 +3024,50 @@ var graph = {
|
|
|
2430
3024
|
};
|
|
2431
3025
|
|
|
2432
3026
|
// src/editor/presets/electrostatics.ts
|
|
3027
|
+
var pointChargeGauss = {
|
|
3028
|
+
name: "Point charge & Gaussian sphere",
|
|
3029
|
+
elements: [
|
|
3030
|
+
{ id: 1, type: "text", x1: 160, y1: 36, x2: 160, y2: 36, label: "Spherical symmetry: E \u221D 1/r\xB2 outside", color: "#475569", fontSize: 16 },
|
|
3031
|
+
{ id: 2, type: "charge_pos", x1: 160, y1: 180, x2: 160, y2: 180, label: "+q", color: "#ef4444", strokeWidth: 2, fontSize: 18 },
|
|
3032
|
+
{ id: 3, type: "gaussian_sphere", x1: 160, y1: 180, x2: 280, y2: 180, color: "#10b981", strokeWidth: 2, label: "Gaussian surface" },
|
|
3033
|
+
{ id: 4, type: "vector", x1: 160, y1: 180, x2: 300, y2: 180, color: "#ef4444", strokeWidth: 2, label: "E" },
|
|
3034
|
+
{ id: 5, type: "vector", x1: 160, y1: 180, x2: 160, y2: 60, color: "#ef4444", strokeWidth: 2 },
|
|
3035
|
+
{ id: 6, type: "vector", x1: 160, y1: 180, x2: 40, y2: 180, color: "#ef4444", strokeWidth: 2 },
|
|
3036
|
+
{ id: 7, type: "vector", x1: 160, y1: 180, x2: 160, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
3037
|
+
{ id: 8, type: "text", x1: 160, y1: 340, x2: 160, y2: 340, label: "\u222E E\xB7dA = Q/\u03B5\u2080", color: "#0f172a", fontSize: 17 }
|
|
3038
|
+
]
|
|
3039
|
+
};
|
|
3040
|
+
var lineChargeCylinder = {
|
|
3041
|
+
name: "Line charge & Gaussian cylinder",
|
|
3042
|
+
elements: [
|
|
3043
|
+
{ id: 1, type: "text", x1: 500, y1: 36, x2: 500, y2: 36, label: "Infinite line \u03BB \u2014 use a coaxial cylinder", color: "#475569", fontSize: 15 },
|
|
3044
|
+
{ id: 2, type: "charged_plate_pos", x1: 480, y1: 80, x2: 480, y2: 360, color: "#ef4444", strokeWidth: 2, label: "+\u03BB" },
|
|
3045
|
+
{ id: 3, type: "gaussian_cylinder", x1: 480, y1: 140, x2: 480, y2: 300, color: "#10b981", strokeWidth: 2, curveHeight: 60, label: "Coaxial S" },
|
|
3046
|
+
{ id: 4, type: "vector", x1: 480, y1: 210, x2: 600, y2: 210, color: "#ef4444", strokeWidth: 2, label: "E" },
|
|
3047
|
+
{ id: 5, type: "vector", x1: 480, y1: 210, x2: 360, y2: 210, color: "#ef4444", strokeWidth: 2 },
|
|
3048
|
+
{ id: 6, type: "text", x1: 480, y1: 400, x2: 480, y2: 400, label: "E = \u03BB / (2\u03C0\u03B5\u2080r)", color: "#0f172a", fontSize: 16 }
|
|
3049
|
+
]
|
|
3050
|
+
};
|
|
3051
|
+
var platesAndDipole = {
|
|
3052
|
+
name: "Parallel plates & dipole",
|
|
3053
|
+
elements: [
|
|
3054
|
+
{ id: 1, type: "text", x1: 720, y1: 36, x2: 720, y2: 36, label: "Uniform field + torque on p in E", color: "#475569", fontSize: 15 },
|
|
3055
|
+
{ id: 2, type: "charged_plate_pos", x1: 600, y1: 100, x2: 820, y2: 100, color: "#ef4444", strokeWidth: 2 },
|
|
3056
|
+
{ id: 3, type: "charged_plate_neg", x1: 600, y1: 300, x2: 820, y2: 300, color: "#3b82f6", strokeWidth: 2 },
|
|
3057
|
+
{ id: 4, type: "vector", x1: 640, y1: 100, x2: 640, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
3058
|
+
{ id: 5, type: "vector", x1: 700, y1: 100, x2: 700, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
3059
|
+
{ id: 6, type: "vector", x1: 780, y1: 100, x2: 780, y2: 300, color: "#ef4444", strokeWidth: 2, label: "E" },
|
|
3060
|
+
{ id: 7, type: "text", x1: 720, y1: 340, x2: 720, y2: 340, label: "\u0394V = E d (parallel)", color: "#0f172a", fontSize: 15 },
|
|
3061
|
+
{ id: 8, type: "dipole", x1: 120, y1: 480, x2: 280, y2: 480, color: "#64748b", strokeWidth: 2, label: "p" },
|
|
3062
|
+
{ id: 9, type: "vector", x1: 120, y1: 480, x2: 280, y2: 480, color: "#f59e0b", strokeWidth: 2, label: "p" },
|
|
3063
|
+
{ id: 10, type: "text", x1: 320, y1: 480, x2: 320, y2: 480, label: "\u03C4 = p \xD7 E", color: "#0f172a", fontSize: 16 }
|
|
3064
|
+
]
|
|
3065
|
+
};
|
|
3066
|
+
var electrostaticsExamples = [pointChargeGauss, lineChargeCylinder, platesAndDipole];
|
|
2433
3067
|
var electrostatics = {
|
|
2434
3068
|
name: "Electrostatics",
|
|
2435
|
-
elements: [
|
|
2436
|
-
|
|
2437
|
-
{ id: 2, type: "gaussian_sphere", x1: 160, y1: 160, x2: 260, y2: 160, color: "#10b981", strokeWidth: 2, label: "Gaussian Sphere" },
|
|
2438
|
-
{ id: 3, type: "vector", x1: 160, y1: 160, x2: 280, y2: 160, color: "#ef4444", strokeWidth: 2, label: "E" },
|
|
2439
|
-
{ id: 4, type: "vector", x1: 160, y1: 160, x2: 160, y2: 40, color: "#ef4444", strokeWidth: 2 },
|
|
2440
|
-
{ id: 5, type: "vector", x1: 160, y1: 160, x2: 40, y2: 160, color: "#ef4444", strokeWidth: 2 },
|
|
2441
|
-
{ id: 6, type: "vector", x1: 160, y1: 160, x2: 160, y2: 280, color: "#ef4444", strokeWidth: 2 },
|
|
2442
|
-
{ id: 7, type: "text", x1: 160, y1: 320, x2: 160, y2: 320, label: "Point Charge Field", color: "#334155", fontSize: 18 },
|
|
2443
|
-
{ id: 8, type: "charged_plate_pos", x1: 500, y1: 60, x2: 500, y2: 360, color: "#ef4444", strokeWidth: 2, label: "+\u03BB (Line Charge)" },
|
|
2444
|
-
{ id: 9, type: "gaussian_cylinder", x1: 500, y1: 120, x2: 500, y2: 300, color: "#10b981", strokeWidth: 2, curveHeight: 60, label: "Gaussian Cylinder" },
|
|
2445
|
-
{ id: 10, type: "vector", x1: 500, y1: 210, x2: 620, y2: 210, color: "#ef4444", strokeWidth: 2, label: "E" },
|
|
2446
|
-
{ id: 11, type: "vector", x1: 500, y1: 210, x2: 380, y2: 210, color: "#ef4444", strokeWidth: 2 },
|
|
2447
|
-
{ id: 12, type: "text", x1: 500, y1: 400, x2: 500, y2: 400, label: "Cylindrical Symmetry", color: "#334155", fontSize: 18 },
|
|
2448
|
-
{ id: 13, type: "charged_plate_pos", x1: 760, y1: 100, x2: 960, y2: 100, color: "#ef4444", strokeWidth: 2 },
|
|
2449
|
-
{ id: 14, type: "charged_plate_neg", x1: 760, y1: 300, x2: 960, y2: 300, color: "#3b82f6", strokeWidth: 2 },
|
|
2450
|
-
{ id: 15, type: "vector", x1: 800, y1: 100, x2: 800, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
2451
|
-
{ id: 16, type: "vector", x1: 860, y1: 100, x2: 860, y2: 300, color: "#ef4444", strokeWidth: 2, label: "Uniform E-Field" },
|
|
2452
|
-
{ id: 17, type: "vector", x1: 920, y1: 100, x2: 920, y2: 300, color: "#ef4444", strokeWidth: 2 },
|
|
2453
|
-
{ id: 18, type: "text", x1: 860, y1: 340, x2: 860, y2: 340, label: "Parallel Plates", color: "#334155", fontSize: 18 },
|
|
2454
|
-
{ id: 19, type: "dipole", x1: 100, y1: 500, x2: 260, y2: 500, color: "#64748b", strokeWidth: 2, label: "Electric Dipole (p)" },
|
|
2455
|
-
{ id: 20, type: "vector", x1: 100, y1: 500, x2: 260, y2: 500, color: "#f59e0b", strokeWidth: 2, label: "p" }
|
|
2456
|
-
],
|
|
3069
|
+
elements: electrostaticsExamples[0].elements,
|
|
3070
|
+
examples: electrostaticsExamples,
|
|
2457
3071
|
toolCategories: [
|
|
2458
3072
|
{
|
|
2459
3073
|
name: "Basics",
|
|
@@ -2498,21 +3112,51 @@ var electrostatics = {
|
|
|
2498
3112
|
};
|
|
2499
3113
|
|
|
2500
3114
|
// src/editor/presets/chemistry.ts
|
|
3115
|
+
var aromaticHalogenation = {
|
|
3116
|
+
name: "Aromatic halogenation",
|
|
3117
|
+
elements: [
|
|
3118
|
+
{ id: 1, type: "text", x1: 420, y1: 40, x2: 420, y2: 40, label: "Lewis acid catalyzed chlorination (schematic)", color: "#64748b", fontSize: 15 },
|
|
3119
|
+
{ id: 2, type: "benzene", x1: 150, y1: 210, x2: 150, y2: 210, label: "", value: "" },
|
|
3120
|
+
{ id: 3, type: "text", x1: 240, y1: 210, x2: 240, y2: 210, label: "+", value: "" },
|
|
3121
|
+
{ id: 4, type: "atom", x1: 285, y1: 210, x2: 285, y2: 210, label: "Cl", value: "" },
|
|
3122
|
+
{ id: 5, type: "single_bond", x1: 300, y1: 210, x2: 330, y2: 210, label: "", value: "" },
|
|
3123
|
+
{ id: 6, type: "atom", x1: 345, y1: 210, x2: 345, y2: 210, label: "Cl", value: "" },
|
|
3124
|
+
{ id: 7, type: "reaction_arrow", x1: 400, y1: 210, x2: 520, y2: 210, label: "FeCl\u2083", value: "cat." },
|
|
3125
|
+
{ id: 8, type: "benzene", x1: 600, y1: 210, x2: 600, y2: 210, label: "", value: "" },
|
|
3126
|
+
{ id: 9, type: "single_bond", x1: 600, y1: 180, x2: 600, y2: 120, label: "", value: "" },
|
|
3127
|
+
{ id: 10, type: "atom", x1: 600, y1: 105, x2: 600, y2: 105, label: "Cl", value: "" },
|
|
3128
|
+
{ id: 11, type: "text", x1: 690, y1: 210, x2: 690, y2: 210, label: "+", value: "" },
|
|
3129
|
+
{ id: 12, type: "atom", x1: 750, y1: 210, x2: 750, y2: 210, label: "HCl", value: "" }
|
|
3130
|
+
]
|
|
3131
|
+
};
|
|
3132
|
+
var ringEquilibrium = {
|
|
3133
|
+
name: "Ring conformers",
|
|
3134
|
+
elements: [
|
|
3135
|
+
{ id: 1, type: "text", x1: 400, y1: 50, x2: 400, y2: 50, label: "Six-membered ring: two low-energy chairs", color: "#64748b", fontSize: 15 },
|
|
3136
|
+
{ id: 2, type: "cyclohexane", x1: 220, y1: 240, x2: 220, y2: 240, label: "", value: "" },
|
|
3137
|
+
{ id: 3, type: "equilibrium_arrow", x1: 300, y1: 240, x2: 420, y2: 240, label: "", value: "" },
|
|
3138
|
+
{ id: 4, type: "cyclohexane", x1: 520, y1: 240, x2: 520, y2: 240, label: "", value: "" },
|
|
3139
|
+
{ id: 5, type: "text", x1: 400, y1: 360, x2: 400, y2: 360, label: "Flip interconverts axial / equatorial substituents", color: "#334155", fontSize: 14 },
|
|
3140
|
+
{ id: 6, type: "wedge_bond", x1: 220, y1: 200, x2: 200, y2: 170, label: "", value: "" },
|
|
3141
|
+
{ id: 7, type: "atom", x1: 188, y1: 158, x2: 188, y2: 158, label: "R", value: "" }
|
|
3142
|
+
]
|
|
3143
|
+
};
|
|
3144
|
+
var resonanceStructures = {
|
|
3145
|
+
name: "Benzene resonance",
|
|
3146
|
+
elements: [
|
|
3147
|
+
{ id: 1, type: "text", x1: 400, y1: 50, x2: 400, y2: 50, label: "\u03C0 system: two major Kekul\xE9 contributors", color: "#64748b", fontSize: 15 },
|
|
3148
|
+
{ id: 2, type: "benzene", x1: 200, y1: 220, x2: 200, y2: 220, label: "", value: "" },
|
|
3149
|
+
{ id: 3, type: "resonance_arrow", x1: 280, y1: 220, x2: 360, y2: 220, label: "", value: "" },
|
|
3150
|
+
{ id: 4, type: "benzene", x1: 440, y1: 220, x2: 440, y2: 220, label: "", value: "" },
|
|
3151
|
+
{ id: 5, type: "double_bond", x1: 440, y1: 200, x2: 470, y2: 180, label: "", value: "" },
|
|
3152
|
+
{ id: 6, type: "text", x1: 400, y1: 340, x2: 400, y2: 340, label: "Real molecule = hybrid (D\u2086h symmetry)", color: "#334155", fontSize: 14 }
|
|
3153
|
+
]
|
|
3154
|
+
};
|
|
3155
|
+
var chemistryExamples = [aromaticHalogenation, ringEquilibrium, resonanceStructures];
|
|
2501
3156
|
var chemistry = {
|
|
2502
3157
|
name: "Chemistry",
|
|
2503
|
-
elements: [
|
|
2504
|
-
|
|
2505
|
-
{ id: 2, type: "text", x1: 240, y1: 210, x2: 240, y2: 210, label: "+", value: "" },
|
|
2506
|
-
{ id: 3, type: "atom", x1: 285, y1: 210, x2: 285, y2: 210, label: "Cl", value: "" },
|
|
2507
|
-
{ id: 4, type: "single_bond", x1: 300, y1: 210, x2: 330, y2: 210, label: "", value: "" },
|
|
2508
|
-
{ id: 5, type: "atom", x1: 345, y1: 210, x2: 345, y2: 210, label: "Cl", value: "" },
|
|
2509
|
-
{ id: 6, type: "reaction_arrow", x1: 400, y1: 210, x2: 520, y2: 210, label: "FeCl3", value: "Dark" },
|
|
2510
|
-
{ id: 7, type: "benzene", x1: 600, y1: 210, x2: 600, y2: 210, label: "", value: "" },
|
|
2511
|
-
{ id: 8, type: "single_bond", x1: 600, y1: 180, x2: 600, y2: 120, label: "", value: "" },
|
|
2512
|
-
{ id: 9, type: "atom", x1: 600, y1: 105, x2: 600, y2: 105, label: "Cl", value: "" },
|
|
2513
|
-
{ id: 10, type: "text", x1: 690, y1: 210, x2: 690, y2: 210, label: "+", value: "" },
|
|
2514
|
-
{ id: 11, type: "atom", x1: 750, y1: 210, x2: 750, y2: 210, label: "HCl", value: "" }
|
|
2515
|
-
],
|
|
3158
|
+
elements: chemistryExamples[0].elements,
|
|
3159
|
+
examples: chemistryExamples,
|
|
2516
3160
|
toolCategories: [
|
|
2517
3161
|
{
|
|
2518
3162
|
name: "Chemistry",
|
|
@@ -2558,39 +3202,25 @@ var chemistry = {
|
|
|
2558
3202
|
]
|
|
2559
3203
|
};
|
|
2560
3204
|
|
|
2561
|
-
// src/editor/presets/mechanical.ts
|
|
2562
|
-
var mechanical = {
|
|
2563
|
-
name: "Mechanical",
|
|
2564
|
-
elements: [
|
|
2565
|
-
{ id: 1, type: "wedge", x1: 100, y1: 400, x2: 500, y2: 100, label: "M" },
|
|
2566
|
-
{ id: 2, type: "block", x1: 220, y1: 260, x2: 300, y2: 300, label: "m" },
|
|
2567
|
-
{ id: 3, type: "arc", x1: 100, y1: 400, x2: 260, y2: 280, label: "\u03B8" }
|
|
2568
|
-
],
|
|
2569
|
-
toolCategories: [{ name: "Mechanical", tools: [{ id: "select", name: "Select" }, { id: "wedge", name: "Wedge" }, { id: "block", name: "Block" }, { id: "vector", name: "Vector" }, { id: "arc", name: "Arc" }, { id: "dashed", name: "Dashed" }, { id: "dimension", name: "Dimension" }, { id: "axes", name: "Axes" }] }]
|
|
2570
|
-
};
|
|
2571
|
-
|
|
2572
3205
|
// src/editor/presets/index.ts
|
|
2573
3206
|
var presets = {
|
|
2574
3207
|
mechanics,
|
|
2575
3208
|
circuit,
|
|
2576
3209
|
thermo,
|
|
2577
|
-
optical,
|
|
2578
3210
|
magnetism,
|
|
2579
3211
|
light,
|
|
2580
|
-
waves,
|
|
2581
3212
|
waveOscillation,
|
|
2582
3213
|
rotation,
|
|
2583
3214
|
graph,
|
|
2584
3215
|
electrostatics,
|
|
2585
|
-
chemistry
|
|
2586
|
-
mechanical
|
|
3216
|
+
chemistry
|
|
2587
3217
|
};
|
|
2588
3218
|
|
|
2589
3219
|
// src/editor/Editor.tsx
|
|
2590
3220
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2591
3221
|
var defaultPreset = presets.mechanics;
|
|
2592
3222
|
var Editor = forwardRef(function Editor2({
|
|
2593
|
-
initialElements
|
|
3223
|
+
initialElements,
|
|
2594
3224
|
toolCategories,
|
|
2595
3225
|
preset,
|
|
2596
3226
|
enablePresetSwitch = true,
|
|
@@ -2603,6 +3233,7 @@ var Editor = forwardRef(function Editor2({
|
|
|
2603
3233
|
onExport
|
|
2604
3234
|
}, ref) {
|
|
2605
3235
|
const [selectedPreset, setSelectedPreset] = useState2(preset ?? "mechanics");
|
|
3236
|
+
const [exampleIndex, setExampleIndex] = useState2(0);
|
|
2606
3237
|
const isPresetExternallyControlled = preset !== void 0 && typeof onPresetChange === "function";
|
|
2607
3238
|
useEffect2(() => {
|
|
2608
3239
|
if (isPresetExternallyControlled && preset) {
|
|
@@ -2611,23 +3242,21 @@ var Editor = forwardRef(function Editor2({
|
|
|
2611
3242
|
}, [preset, isPresetExternallyControlled]);
|
|
2612
3243
|
const activePresetKey = isPresetExternallyControlled ? preset ?? selectedPreset : selectedPreset;
|
|
2613
3244
|
const activePreset = presets[activePresetKey] ?? defaultPreset;
|
|
2614
|
-
const [lightTopicIndex, setLightTopicIndex] = useState2(0);
|
|
2615
3245
|
useEffect2(() => {
|
|
2616
|
-
|
|
3246
|
+
setExampleIndex(0);
|
|
2617
3247
|
}, [activePresetKey]);
|
|
2618
3248
|
const resolvedInitialElements = useMemo2(() => {
|
|
2619
|
-
if (
|
|
2620
|
-
|
|
2621
|
-
return
|
|
2622
|
-
}, [
|
|
3249
|
+
if (initialElements != null) return initialElements;
|
|
3250
|
+
const source = activePreset.examples?.[exampleIndex]?.elements ?? activePreset.elements;
|
|
3251
|
+
return source.slice();
|
|
3252
|
+
}, [initialElements, activePreset, exampleIndex]);
|
|
2623
3253
|
const state = useDrawing(resolvedInitialElements, activePresetKey);
|
|
2624
|
-
const showLightTopicPicker = activePresetKey === "light" && initialElements2 == null;
|
|
2625
3254
|
useEffect2(() => {
|
|
2626
3255
|
onChange?.(state.elements);
|
|
2627
3256
|
}, [state.elements, onChange]);
|
|
2628
3257
|
useEffect2(() => {
|
|
2629
3258
|
if (typeof viewMode === "boolean") state.setIsViewMode(viewMode);
|
|
2630
|
-
}, [viewMode, state]);
|
|
3259
|
+
}, [viewMode, state.setIsViewMode]);
|
|
2631
3260
|
useEffect2(() => {
|
|
2632
3261
|
if (!state.selectedId) {
|
|
2633
3262
|
state.setShowProperties(false);
|
|
@@ -2642,6 +3271,7 @@ var Editor = forwardRef(function Editor2({
|
|
|
2642
3271
|
clear: () => state.setElements([])
|
|
2643
3272
|
}),
|
|
2644
3273
|
[state.elements, state.setElements]
|
|
3274
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
2645
3275
|
);
|
|
2646
3276
|
const displayTitle = documentTitle ?? `${activePreset.name} Editor`;
|
|
2647
3277
|
const handleCopyJson = () => {
|
|
@@ -2652,7 +3282,17 @@ var Editor = forwardRef(function Editor2({
|
|
|
2652
3282
|
}
|
|
2653
3283
|
};
|
|
2654
3284
|
const updateSelected = (key, value) => {
|
|
2655
|
-
state.setElements(
|
|
3285
|
+
state.setElements(
|
|
3286
|
+
(els) => els.map((el) => {
|
|
3287
|
+
if (el.id !== state.selectedId) return el;
|
|
3288
|
+
if (value === void 0) {
|
|
3289
|
+
const copy = { ...el };
|
|
3290
|
+
delete copy[key];
|
|
3291
|
+
return copy;
|
|
3292
|
+
}
|
|
3293
|
+
return { ...el, [key]: value };
|
|
3294
|
+
})
|
|
3295
|
+
);
|
|
2656
3296
|
};
|
|
2657
3297
|
const deleteSelected = () => {
|
|
2658
3298
|
if (!state.selectedId) return;
|
|
@@ -2684,24 +3324,18 @@ var Editor = forwardRef(function Editor2({
|
|
|
2684
3324
|
),
|
|
2685
3325
|
/* @__PURE__ */ jsx5("span", { className: "pointer-events-none absolute inset-y-0 right-2 flex items-center text-slate-500 text-xs", children: "\u25BC" })
|
|
2686
3326
|
] }),
|
|
2687
|
-
|
|
3327
|
+
initialElements == null && activePreset.examples && activePreset.examples.length > 0 && /* @__PURE__ */ jsxs5("div", { className: "relative shrink-0 max-w-[min(280px,46vw)]", children: [
|
|
2688
3328
|
/* @__PURE__ */ jsx5(
|
|
2689
3329
|
"select",
|
|
2690
3330
|
{
|
|
2691
|
-
value:
|
|
2692
|
-
onChange: (e) =>
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
state.setShowProperties(false);
|
|
2697
|
-
},
|
|
2698
|
-
className: "w-full appearance-none text-xs md:text-sm pl-3 pr-8 py-2 rounded-full border border-slate-200 bg-sky-50 text-slate-800 shadow-sm hover:bg-sky-100 focus:outline-none focus:ring-2 focus:ring-sky-200 truncate",
|
|
2699
|
-
title: "Load JEE/NEET topic scene",
|
|
2700
|
-
"aria-label": "Light syllabus topic",
|
|
2701
|
-
children: LIGHT_TOPICS.map((t, i) => /* @__PURE__ */ jsx5("option", { value: i, children: t.name }, t.name))
|
|
3331
|
+
value: exampleIndex,
|
|
3332
|
+
onChange: (e) => setExampleIndex(Number(e.target.value)),
|
|
3333
|
+
className: "appearance-none w-full text-xs md:text-sm pl-3 pr-8 py-2 rounded-full border border-violet-200 bg-violet-50/90 text-violet-900 shadow-sm hover:bg-violet-100 focus:outline-none focus:ring-2 focus:ring-violet-200 truncate",
|
|
3334
|
+
title: "Load example scene",
|
|
3335
|
+
children: activePreset.examples.map((ex, i) => /* @__PURE__ */ jsx5("option", { value: i, children: ex.name }, ex.name))
|
|
2702
3336
|
}
|
|
2703
3337
|
),
|
|
2704
|
-
/* @__PURE__ */ jsx5("span", { className: "pointer-events-none absolute inset-y-0 right-2 flex items-center text-
|
|
3338
|
+
/* @__PURE__ */ jsx5("span", { className: "pointer-events-none absolute inset-y-0 right-2 flex items-center text-violet-600 text-xs", children: "\u25BC" })
|
|
2705
3339
|
] }),
|
|
2706
3340
|
!hideDocumentTitle && /* @__PURE__ */ jsx5("h1", { className: "text-lg md:text-2xl font-semibold tracking-tight text-slate-800 truncate min-w-0", children: displayTitle })
|
|
2707
3341
|
] }),
|
|
@@ -2789,7 +3423,8 @@ var Editor = forwardRef(function Editor2({
|
|
|
2789
3423
|
onBackgroundMouseMove: state.isViewMode ? void 0 : state.handleMouseMove,
|
|
2790
3424
|
onBackgroundMouseUp: state.isViewMode ? void 0 : state.handleMouseUp,
|
|
2791
3425
|
onBackgroundMouseLeave: state.isViewMode ? void 0 : state.handleMouseUp,
|
|
2792
|
-
onElementMouseDown: state.onElementMouseDown
|
|
3426
|
+
onElementMouseDown: state.onElementMouseDown,
|
|
3427
|
+
onHandlePointerDown: state.isViewMode ? void 0 : state.onHandlePointerDown
|
|
2793
3428
|
}
|
|
2794
3429
|
),
|
|
2795
3430
|
state.showProperties && state.selectedId && !state.isViewMode && /* @__PURE__ */ jsx5(
|