@elixpo/lixsketch 5.4.7 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/AIRenderer-M4LMJ66J.js +1105 -0
- package/dist/react/AIRenderer-M4LMJ66J.js.map +7 -0
- package/dist/react/Arrow-BJDAXPMH.js +8 -0
- package/dist/react/Arrow-BJDAXPMH.js.map +7 -0
- package/dist/react/Circle-KPG7TKIX.js +8 -0
- package/dist/react/Circle-KPG7TKIX.js.map +7 -0
- package/dist/react/CodeShape-K4DIZAIV.js +8 -0
- package/dist/react/CodeShape-K4DIZAIV.js.map +7 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js +569 -0
- package/dist/react/CopyPaste-4CKJRHJ3.js.map +7 -0
- package/dist/react/EraserTrail-PA6IQLQN.js +20 -0
- package/dist/react/EraserTrail-PA6IQLQN.js.map +7 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js +463 -0
- package/dist/react/EventDispatcher-SRFH6LQZ.js.map +7 -0
- package/dist/react/Frame-6UR5XPAX.js +10 -0
- package/dist/react/Frame-6UR5XPAX.js.map +7 -0
- package/dist/react/FreehandStroke-CK24NUT3.js +8 -0
- package/dist/react/FreehandStroke-CK24NUT3.js.map +7 -0
- package/dist/react/GraphEngine-QE5B2PMR.js +340 -0
- package/dist/react/GraphEngine-QE5B2PMR.js.map +7 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js +10 -0
- package/dist/react/GraphMathParser-2WMTY4IE.js.map +7 -0
- package/dist/react/IconShape-KMIA6T2H.js +10 -0
- package/dist/react/IconShape-KMIA6T2H.js.map +7 -0
- package/dist/react/ImageShape-CHHGBXUQ.js +10 -0
- package/dist/react/ImageShape-CHHGBXUQ.js.map +7 -0
- package/dist/react/LayerOrder-XCHF4MSS.js +66 -0
- package/dist/react/LayerOrder-XCHF4MSS.js.map +7 -0
- package/dist/react/Line-2KOQEEGA.js +10 -0
- package/dist/react/Line-2KOQEEGA.js.map +7 -0
- package/dist/react/LixScriptParser-JYWJX375.js +1033 -0
- package/dist/react/LixScriptParser-JYWJX375.js.map +7 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js +412 -0
- package/dist/react/MermaidFlowchartRenderer-4QBAZ5MB.js.map +7 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js +8 -0
- package/dist/react/MermaidSequenceParser-UKG2NSZY.js.map +7 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js +387 -0
- package/dist/react/MermaidSequenceRenderer-HPLHY5II.js.map +7 -0
- package/dist/react/Rectangle-6FE7RN6W.js +8 -0
- package/dist/react/Rectangle-6FE7RN6W.js.map +7 -0
- package/dist/react/ResizeCode-WAMDTKSW.js +2 -0
- package/dist/react/ResizeCode-WAMDTKSW.js.map +7 -0
- package/dist/react/ResizeShapes-LKEQTITP.js +250 -0
- package/dist/react/ResizeShapes-LKEQTITP.js.map +7 -0
- package/dist/react/SceneSerializer-4U4B24JM.js +739 -0
- package/dist/react/SceneSerializer-4U4B24JM.js.map +7 -0
- package/dist/react/Selection-VVUHY5YJ.js +34 -0
- package/dist/react/Selection-VVUHY5YJ.js.map +7 -0
- package/dist/react/SketchEngine-YA4RG3KX.js +413 -0
- package/dist/react/SketchEngine-YA4RG3KX.js.map +7 -0
- package/dist/react/TextShape-54ZJ66E3.js +8 -0
- package/dist/react/TextShape-54ZJ66E3.js.map +7 -0
- package/dist/react/UndoRedo-M2JZUBKN.js +30 -0
- package/dist/react/UndoRedo-M2JZUBKN.js.map +7 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js +186 -0
- package/dist/react/ZoomPan-U3TXC5AJ.js.map +7 -0
- package/dist/react/arrowTool-CWEMIRXK.js +17 -0
- package/dist/react/arrowTool-CWEMIRXK.js.map +7 -0
- package/dist/react/boxicons-5JNJQPUP.woff +0 -0
- package/dist/react/boxicons-6NVWQSCQ.eot +0 -0
- package/dist/react/boxicons-AQ5N6WP7.woff2 +0 -0
- package/dist/react/boxicons-GDR4JU3X.ttf +0 -0
- package/dist/react/boxicons-NNFHLMOR.svg +1660 -0
- package/dist/react/chunk-2OQXI7QB.js +564 -0
- package/dist/react/chunk-2OQXI7QB.js.map +7 -0
- package/dist/react/chunk-5OUBTHHO.js +187 -0
- package/dist/react/chunk-5OUBTHHO.js.map +7 -0
- package/dist/react/chunk-6PFXZKL2.js +628 -0
- package/dist/react/chunk-6PFXZKL2.js.map +7 -0
- package/dist/react/chunk-6SFNWGGZ.js +453 -0
- package/dist/react/chunk-6SFNWGGZ.js.map +7 -0
- package/dist/react/chunk-7TZSIR6V.js +210 -0
- package/dist/react/chunk-7TZSIR6V.js.map +7 -0
- package/dist/react/chunk-AJAZC37E.js +662 -0
- package/dist/react/chunk-AJAZC37E.js.map +7 -0
- package/dist/react/chunk-BU4D2WYQ.js +1213 -0
- package/dist/react/chunk-BU4D2WYQ.js.map +7 -0
- package/dist/react/chunk-BZE4CEBG.js +747 -0
- package/dist/react/chunk-BZE4CEBG.js.map +7 -0
- package/dist/react/chunk-CB2RANCB.js +212 -0
- package/dist/react/chunk-CB2RANCB.js.map +7 -0
- package/dist/react/chunk-DNAG7ML6.js +128 -0
- package/dist/react/chunk-DNAG7ML6.js.map +7 -0
- package/dist/react/chunk-HZWLPXFN.js +198 -0
- package/dist/react/chunk-HZWLPXFN.js.map +7 -0
- package/dist/react/chunk-I6HCCIXB.js +572 -0
- package/dist/react/chunk-I6HCCIXB.js.map +7 -0
- package/dist/react/chunk-IZ5OGWGW.js +235 -0
- package/dist/react/chunk-IZ5OGWGW.js.map +7 -0
- package/dist/react/chunk-JJCJNLNN.js +1490 -0
- package/dist/react/chunk-JJCJNLNN.js.map +7 -0
- package/dist/react/chunk-JQ3IRFDP.js +222 -0
- package/dist/react/chunk-JQ3IRFDP.js.map +7 -0
- package/dist/react/chunk-L5OARZJ7.js +1134 -0
- package/dist/react/chunk-L5OARZJ7.js.map +7 -0
- package/dist/react/chunk-LHRTXNVE.js +1600 -0
- package/dist/react/chunk-LHRTXNVE.js.map +7 -0
- package/dist/react/chunk-Q2GA4MBZ.js +1653 -0
- package/dist/react/chunk-Q2GA4MBZ.js.map +7 -0
- package/dist/react/chunk-QNSE5BAY.js +519 -0
- package/dist/react/chunk-QNSE5BAY.js.map +7 -0
- package/dist/react/chunk-QXFBG7OM.js +191 -0
- package/dist/react/chunk-QXFBG7OM.js.map +7 -0
- package/dist/react/chunk-T6ZVV5ZO.js +714 -0
- package/dist/react/chunk-T6ZVV5ZO.js.map +7 -0
- package/dist/react/chunk-URB6MY46.js +974 -0
- package/dist/react/chunk-URB6MY46.js.map +7 -0
- package/dist/react/chunk-VN62KLOC.js +931 -0
- package/dist/react/chunk-VN62KLOC.js.map +7 -0
- package/dist/react/chunk-VQVEPJSA.js +158 -0
- package/dist/react/chunk-VQVEPJSA.js.map +7 -0
- package/dist/react/chunk-XISEAGBV.js +1632 -0
- package/dist/react/chunk-XISEAGBV.js.map +7 -0
- package/dist/react/chunk-YKJUBFHE.js +575 -0
- package/dist/react/chunk-YKJUBFHE.js.map +7 -0
- package/dist/react/circleTool-NUATSEI2.js +14 -0
- package/dist/react/circleTool-NUATSEI2.js.map +7 -0
- package/dist/react/codeTool-MHCB2FNB.js +38 -0
- package/dist/react/codeTool-MHCB2FNB.js.map +7 -0
- package/dist/react/eraserTool-2GS2LQCS.js +103 -0
- package/dist/react/eraserTool-2GS2LQCS.js.map +7 -0
- package/dist/react/frameTool-PWVKKXSP.js +14 -0
- package/dist/react/frameTool-PWVKKXSP.js.map +7 -0
- package/dist/react/freehandTool-SLYGASVP.js +14 -0
- package/dist/react/freehandTool-SLYGASVP.js.map +7 -0
- package/dist/react/iconTool-GPZ7O7NH.js +18 -0
- package/dist/react/iconTool-GPZ7O7NH.js.map +7 -0
- package/dist/react/imageTool-D5R4XGEU.js +15 -0
- package/dist/react/imageTool-D5R4XGEU.js.map +7 -0
- package/dist/react/index.js +5342 -0
- package/dist/react/index.js.map +7 -0
- package/dist/react/laserTool-XVMV63AV.js +239 -0
- package/dist/react/laserTool-XVMV63AV.js.map +7 -0
- package/dist/react/lineTool-WNI5EMZ5.js +14 -0
- package/dist/react/lineTool-WNI5EMZ5.js.map +7 -0
- package/dist/react/lixCode-OJMVUXXI.ttf +0 -0
- package/dist/react/lixDefault-JEAPAUJL.ttf +0 -0
- package/dist/react/lixFancy-BPXYM5CQ.ttf +0 -0
- package/dist/react/lixFont-CPKEUDVM.woff2 +0 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js +14 -0
- package/dist/react/rectangleTool-U7DZ6ZTA.js.map +7 -0
- package/dist/react/styles.css +6627 -0
- package/dist/react/textTool-M7S6F3VC.js +21 -0
- package/dist/react/textTool-M7S6F3VC.js.map +7 -0
- package/package.json +39 -5
- package/src/EngineShortcuts.js +83 -27
- package/src/core/AIRenderer.js +30 -18
- package/src/core/GraphEngine.js +64 -41
- package/src/core/MermaidFlowchartRenderer.js +153 -88
- package/src/core/MermaidSequenceRenderer.js +168 -93
- package/src/core/SceneSerializer.js +86 -2
- package/src/core/Selection.js +119 -19
- package/src/core/UndoRedo.js +82 -15
- package/src/core/ZoomPan.js +15 -5
- package/src/index.js +14 -1
- package/src/react/LixSketchCanvas.jsx +347 -0
- package/src/react/components/AppMenu.jsx +475 -0
- package/src/react/components/Footer.jsx +85 -0
- package/src/react/components/Toolbar.jsx +140 -0
- package/src/react/components/canvas/CanvasLoadingOverlay.jsx +76 -0
- package/src/react/components/canvas/ContextMenu.jsx +466 -0
- package/src/react/components/canvas/FindBar.jsx +177 -0
- package/src/react/components/canvas/ImageSourcePicker.jsx +133 -0
- package/src/react/components/canvas/MultiSelectActions.jsx +120 -0
- package/src/react/components/canvas/SVGCanvas.jsx +145 -0
- package/src/react/components/canvas/SaveStatusIndicator.jsx +29 -0
- package/src/react/components/modals/CanvasPropertiesModal.jsx +358 -0
- package/src/react/components/modals/CommandPalette.jsx +307 -0
- package/src/react/components/modals/ExportImageModal.jsx +287 -0
- package/src/react/components/modals/GraphModal.jsx +174 -0
- package/src/react/components/modals/HelpModal.jsx +208 -0
- package/src/react/components/modals/LixScriptModal.jsx +130 -0
- package/src/react/components/modals/ShortcutsModal.jsx +125 -0
- package/src/react/components/sidebars/ArrowSidebar.jsx +173 -0
- package/src/react/components/sidebars/CircleSidebar.jsx +134 -0
- package/src/react/components/sidebars/FrameSidebar.jsx +263 -0
- package/src/react/components/sidebars/IconSidebar.jsx +279 -0
- package/src/react/components/sidebars/ImageSidebar.jsx +69 -0
- package/src/react/components/sidebars/LineSidebar.jsx +109 -0
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +119 -0
- package/src/react/components/sidebars/RectangleSidebar.jsx +165 -0
- package/src/react/components/sidebars/ShapeSidebar.jsx +130 -0
- package/src/react/components/sidebars/TextSidebar.jsx +174 -0
- package/src/react/hooks/inertStores.js +58 -0
- package/src/react/hooks/useSketchEngine.js +76 -0
- package/src/react/hooks/useTranslation.js +92 -0
- package/src/react/index.js +41 -0
- package/src/react/store/useSketchStore.js +234 -0
- package/src/react/store/useUIStore.js +196 -0
- package/src/react/styles/arrowSidebar.css +263 -0
- package/src/react/styles/canvasStroke.css +47 -0
- package/src/react/styles/canvasTools.css +769 -0
- package/src/react/styles/circleSidebar.css +206 -0
- package/src/react/styles/fonts/fonts.css +29 -0
- package/src/react/styles/fonts/lixCode.ttf +0 -0
- package/src/react/styles/fonts/lixDefault.ttf +0 -0
- package/src/react/styles/fonts/lixDocs.ttf +0 -0
- package/src/react/styles/fonts/lixFancy.ttf +0 -0
- package/src/react/styles/fonts/lixFont.woff2 +0 -0
- package/src/react/styles/lineSidebar.css +207 -0
- package/src/react/styles/paintbrushSidebar.css +247 -0
- package/src/react/styles/squareSidebar.css +206 -0
- package/src/react/styles/writeText.css +149 -0
- package/src/react/styles.css +175 -0
- package/src/react/toolsEnum.js +20 -0
- package/src/react/utils/toast.js +18 -0
- package/src/shapes/Frame.js +7 -1
- package/src/shapes/Line.js +11 -5
- package/src/tools/arrowTool.js +30 -4
- package/src/tools/circleTool.js +33 -9
- package/src/tools/codeTool.js +5 -3
- package/src/tools/frameTool.js +47 -7
- package/src/tools/freehandTool.js +12 -4
- package/src/tools/iconTool.js +7 -1
- package/src/tools/imageTool.js +7 -1
- package/src/tools/lineTool.js +27 -3
- package/src/tools/rectangleTool.js +45 -8
- package/src/tools/textTool.js +23 -6
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/core/GraphMathParser.js
|
|
4
|
+
var FUNCTIONS = {
|
|
5
|
+
sin: Math.sin,
|
|
6
|
+
cos: Math.cos,
|
|
7
|
+
tan: Math.tan,
|
|
8
|
+
asin: Math.asin,
|
|
9
|
+
acos: Math.acos,
|
|
10
|
+
atan: Math.atan,
|
|
11
|
+
sqrt: Math.sqrt,
|
|
12
|
+
abs: Math.abs,
|
|
13
|
+
log: Math.log10,
|
|
14
|
+
ln: Math.log,
|
|
15
|
+
exp: Math.exp,
|
|
16
|
+
floor: Math.floor,
|
|
17
|
+
ceil: Math.ceil
|
|
18
|
+
};
|
|
19
|
+
var CONSTANTS = { pi: Math.PI, e: Math.E };
|
|
20
|
+
function tokenize(expr) {
|
|
21
|
+
const tokens = [];
|
|
22
|
+
let i = 0;
|
|
23
|
+
while (i < expr.length) {
|
|
24
|
+
const ch = expr[i];
|
|
25
|
+
if (/\s/.test(ch)) {
|
|
26
|
+
i++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if ("+-*/^(),".includes(ch)) {
|
|
30
|
+
tokens.push({ type: "op", value: ch });
|
|
31
|
+
i++;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (/[0-9.]/.test(ch)) {
|
|
35
|
+
let num = "";
|
|
36
|
+
while (i < expr.length && /[0-9.]/.test(expr[i])) {
|
|
37
|
+
num += expr[i];
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
tokens.push({ type: "num", value: parseFloat(num) });
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (/[a-zA-Z_]/.test(ch)) {
|
|
44
|
+
let name = "";
|
|
45
|
+
while (i < expr.length && /[a-zA-Z_0-9]/.test(expr[i])) {
|
|
46
|
+
name += expr[i];
|
|
47
|
+
i++;
|
|
48
|
+
}
|
|
49
|
+
tokens.push({ type: "id", value: name });
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
i++;
|
|
53
|
+
}
|
|
54
|
+
return tokens;
|
|
55
|
+
}
|
|
56
|
+
function insertImplicitMul(tokens) {
|
|
57
|
+
const result = [];
|
|
58
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
59
|
+
const t = tokens[i];
|
|
60
|
+
result.push(t);
|
|
61
|
+
if (i + 1 < tokens.length) {
|
|
62
|
+
const next = tokens[i + 1];
|
|
63
|
+
const needsMul = (
|
|
64
|
+
// num followed by id or ( → 2x, 2(x), 2sin(x)
|
|
65
|
+
t.type === "num" && (next.type === "id" || next.value === "(") || // ) followed by ( or id or num → (x)(y), (x)2
|
|
66
|
+
t.value === ")" && (next.type === "num" || next.type === "id" || next.value === "(") || // id followed by ( when id is NOT a function → x(2) means x*2
|
|
67
|
+
t.type === "id" && next.value === "(" && !FUNCTIONS[t.value] || // id/num followed by id → xy means x*y
|
|
68
|
+
t.type === "id" && !FUNCTIONS[t.value] && next.type === "id" || // num followed by num after implicit patterns (rare)
|
|
69
|
+
t.type === "id" && !FUNCTIONS[t.value] && next.type === "num"
|
|
70
|
+
);
|
|
71
|
+
if (needsMul) {
|
|
72
|
+
result.push({ type: "op", value: "*" });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
function parse(tokens) {
|
|
79
|
+
let pos = 0;
|
|
80
|
+
function peek() {
|
|
81
|
+
return tokens[pos];
|
|
82
|
+
}
|
|
83
|
+
function consume(expected) {
|
|
84
|
+
const t = tokens[pos];
|
|
85
|
+
if (expected && (!t || t.value !== expected)) return null;
|
|
86
|
+
pos++;
|
|
87
|
+
return t;
|
|
88
|
+
}
|
|
89
|
+
function parseExpr() {
|
|
90
|
+
let left = parseTerm();
|
|
91
|
+
while (peek() && (peek().value === "+" || peek().value === "-")) {
|
|
92
|
+
const op = consume().value;
|
|
93
|
+
const right = parseTerm();
|
|
94
|
+
const l = left, r = right;
|
|
95
|
+
if (op === "+") left = (x) => l(x) + r(x);
|
|
96
|
+
else left = (x) => l(x) - r(x);
|
|
97
|
+
}
|
|
98
|
+
return left;
|
|
99
|
+
}
|
|
100
|
+
function parseTerm() {
|
|
101
|
+
let left = parsePower();
|
|
102
|
+
while (peek() && (peek().value === "*" || peek().value === "/")) {
|
|
103
|
+
const op = consume().value;
|
|
104
|
+
const right = parsePower();
|
|
105
|
+
const l = left, r = right;
|
|
106
|
+
if (op === "*") left = (x) => l(x) * r(x);
|
|
107
|
+
else left = (x) => {
|
|
108
|
+
const d = r(x);
|
|
109
|
+
return d === 0 ? NaN : l(x) / d;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return left;
|
|
113
|
+
}
|
|
114
|
+
function parsePower() {
|
|
115
|
+
let base = parseUnary();
|
|
116
|
+
if (peek() && peek().value === "^") {
|
|
117
|
+
consume();
|
|
118
|
+
const exp = parsePower();
|
|
119
|
+
const b = base;
|
|
120
|
+
base = (x) => Math.pow(b(x), exp(x));
|
|
121
|
+
}
|
|
122
|
+
return base;
|
|
123
|
+
}
|
|
124
|
+
function parseUnary() {
|
|
125
|
+
if (peek() && peek().value === "-") {
|
|
126
|
+
consume();
|
|
127
|
+
const val = parsePrimary();
|
|
128
|
+
return (x) => -val(x);
|
|
129
|
+
}
|
|
130
|
+
if (peek() && peek().value === "+") {
|
|
131
|
+
consume();
|
|
132
|
+
}
|
|
133
|
+
return parsePrimary();
|
|
134
|
+
}
|
|
135
|
+
function parsePrimary() {
|
|
136
|
+
const t = peek();
|
|
137
|
+
if (!t) return () => NaN;
|
|
138
|
+
if (t.type === "num") {
|
|
139
|
+
consume();
|
|
140
|
+
const v = t.value;
|
|
141
|
+
return () => v;
|
|
142
|
+
}
|
|
143
|
+
if (t.value === "(") {
|
|
144
|
+
consume("(");
|
|
145
|
+
const inner = parseExpr();
|
|
146
|
+
consume(")");
|
|
147
|
+
return inner;
|
|
148
|
+
}
|
|
149
|
+
if (t.type === "id") {
|
|
150
|
+
consume();
|
|
151
|
+
const name = t.value.toLowerCase();
|
|
152
|
+
if (CONSTANTS[name] !== void 0) {
|
|
153
|
+
const v = CONSTANTS[name];
|
|
154
|
+
return () => v;
|
|
155
|
+
}
|
|
156
|
+
if (FUNCTIONS[name] && peek() && peek().value === "(") {
|
|
157
|
+
consume("(");
|
|
158
|
+
const arg = parseExpr();
|
|
159
|
+
consume(")");
|
|
160
|
+
const fn2 = FUNCTIONS[name];
|
|
161
|
+
return (x) => fn2(arg(x));
|
|
162
|
+
}
|
|
163
|
+
if (name === "x") return (x) => x;
|
|
164
|
+
return (x) => x;
|
|
165
|
+
}
|
|
166
|
+
consume();
|
|
167
|
+
return () => NaN;
|
|
168
|
+
}
|
|
169
|
+
const fn = parseExpr();
|
|
170
|
+
return fn;
|
|
171
|
+
}
|
|
172
|
+
function parseExpression(input) {
|
|
173
|
+
if (!input || typeof input !== "string") return null;
|
|
174
|
+
try {
|
|
175
|
+
let expr = input.trim();
|
|
176
|
+
expr = expr.replace(/^[yf]\s*\(?\s*x?\s*\)?\s*=\s*/i, "");
|
|
177
|
+
if (!expr) return null;
|
|
178
|
+
const tokens = tokenize(expr);
|
|
179
|
+
if (tokens.length === 0) return null;
|
|
180
|
+
const withMul = insertImplicitMul(tokens);
|
|
181
|
+
const fn = parse(withMul);
|
|
182
|
+
const test1 = fn(0);
|
|
183
|
+
const test2 = fn(1);
|
|
184
|
+
if (typeof test1 !== "number" && typeof test2 !== "number") return null;
|
|
185
|
+
return fn;
|
|
186
|
+
} catch (e) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function isValidExpression(input) {
|
|
191
|
+
return parseExpression(input) !== null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export {
|
|
195
|
+
parseExpression,
|
|
196
|
+
isValidExpression
|
|
197
|
+
};
|
|
198
|
+
//# sourceMappingURL=chunk-HZWLPXFN.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/core/GraphMathParser.js"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable */\n/**\n * GraphMathParser - Parses math expressions into evaluable functions.\n * Supports: +, -, *, /, ^ (power), implicit multiplication (2x, 3sin(x))\n * Functions: sin, cos, tan, asin, acos, atan, sqrt, abs, log, ln, exp, floor, ceil\n * Constants: pi, e\n * Forms: \"y = expr\", \"f(x) = expr\", or just \"expr\"\n */\n\nconst FUNCTIONS = {\n sin: Math.sin, cos: Math.cos, tan: Math.tan,\n asin: Math.asin, acos: Math.acos, atan: Math.atan,\n sqrt: Math.sqrt, abs: Math.abs,\n log: Math.log10, ln: Math.log, exp: Math.exp,\n floor: Math.floor, ceil: Math.ceil,\n};\n\nconst CONSTANTS = { pi: Math.PI, e: Math.E };\n\n// Tokenizer\nfunction tokenize(expr) {\n const tokens = [];\n let i = 0;\n while (i < expr.length) {\n const ch = expr[i];\n if (/\\s/.test(ch)) { i++; continue; }\n if ('+-*/^(),'.includes(ch)) {\n tokens.push({ type: 'op', value: ch });\n i++;\n continue;\n }\n // Number (including decimals)\n if (/[0-9.]/.test(ch)) {\n let num = '';\n while (i < expr.length && /[0-9.]/.test(expr[i])) { num += expr[i]; i++; }\n tokens.push({ type: 'num', value: parseFloat(num) });\n continue;\n }\n // Identifier (variable, function, or constant)\n if (/[a-zA-Z_]/.test(ch)) {\n let name = '';\n while (i < expr.length && /[a-zA-Z_0-9]/.test(expr[i])) { name += expr[i]; i++; }\n tokens.push({ type: 'id', value: name });\n continue;\n }\n i++; // skip unknown chars\n }\n return tokens;\n}\n\n// Insert implicit multiplication tokens\nfunction insertImplicitMul(tokens) {\n const result = [];\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n result.push(t);\n if (i + 1 < tokens.length) {\n const next = tokens[i + 1];\n const needsMul =\n // num followed by id or ( \u2192 2x, 2(x), 2sin(x)\n (t.type === 'num' && (next.type === 'id' || next.value === '(')) ||\n // ) followed by ( or id or num \u2192 (x)(y), (x)2\n (t.value === ')' && (next.type === 'num' || next.type === 'id' || next.value === '(')) ||\n // id followed by ( when id is NOT a function \u2192 x(2) means x*2\n (t.type === 'id' && next.value === '(' && !FUNCTIONS[t.value]) ||\n // id/num followed by id \u2192 xy means x*y\n (t.type === 'id' && !FUNCTIONS[t.value] && next.type === 'id') ||\n // num followed by num after implicit patterns (rare)\n (t.type === 'id' && !FUNCTIONS[t.value] && next.type === 'num');\n if (needsMul) {\n result.push({ type: 'op', value: '*' });\n }\n }\n }\n return result;\n}\n\n// Recursive descent parser \u2192 builds evaluable function tree\nfunction parse(tokens) {\n let pos = 0;\n\n function peek() { return tokens[pos]; }\n function consume(expected) {\n const t = tokens[pos];\n if (expected && (!t || t.value !== expected)) return null;\n pos++;\n return t;\n }\n\n // Expression: term ((+|-) term)*\n function parseExpr() {\n let left = parseTerm();\n while (peek() && (peek().value === '+' || peek().value === '-')) {\n const op = consume().value;\n const right = parseTerm();\n const l = left, r = right;\n if (op === '+') left = (x) => l(x) + r(x);\n else left = (x) => l(x) - r(x);\n }\n return left;\n }\n\n // Term: power ((*|/) power)*\n function parseTerm() {\n let left = parsePower();\n while (peek() && (peek().value === '*' || peek().value === '/')) {\n const op = consume().value;\n const right = parsePower();\n const l = left, r = right;\n if (op === '*') left = (x) => l(x) * r(x);\n else left = (x) => { const d = r(x); return d === 0 ? NaN : l(x) / d; };\n }\n return left;\n }\n\n // Power: unary (^ unary)* (right-associative)\n function parsePower() {\n let base = parseUnary();\n if (peek() && peek().value === '^') {\n consume();\n const exp = parsePower(); // right-associative\n const b = base;\n base = (x) => Math.pow(b(x), exp(x));\n }\n return base;\n }\n\n // Unary: (+|-) primary\n function parseUnary() {\n if (peek() && peek().value === '-') {\n consume();\n const val = parsePrimary();\n return (x) => -val(x);\n }\n if (peek() && peek().value === '+') { consume(); }\n return parsePrimary();\n }\n\n // Primary: number | variable | function(expr) | (expr)\n function parsePrimary() {\n const t = peek();\n if (!t) return () => NaN;\n\n // Number\n if (t.type === 'num') {\n consume();\n const v = t.value;\n return () => v;\n }\n\n // Parenthesized expression\n if (t.value === '(') {\n consume('(');\n const inner = parseExpr();\n consume(')');\n return inner;\n }\n\n // Identifier\n if (t.type === 'id') {\n consume();\n const name = t.value.toLowerCase();\n\n // Constant\n if (CONSTANTS[name] !== undefined) {\n const v = CONSTANTS[name];\n return () => v;\n }\n\n // Function call\n if (FUNCTIONS[name] && peek() && peek().value === '(') {\n consume('(');\n const arg = parseExpr();\n consume(')');\n const fn = FUNCTIONS[name];\n return (x) => fn(arg(x));\n }\n\n // Variable 'x'\n if (name === 'x') return (x) => x;\n\n // Unknown identifier \u2014 treat as x\n return (x) => x;\n }\n\n // Fallback\n consume();\n return () => NaN;\n }\n\n const fn = parseExpr();\n return fn;\n}\n\n/**\n * Parse a math expression string into a callable (x) => y function.\n * Returns null if parsing fails.\n */\nexport function parseExpression(input) {\n if (!input || typeof input !== 'string') return null;\n\n try {\n let expr = input.trim();\n\n // Strip \"y =\" or \"f(x) =\" prefix\n expr = expr.replace(/^[yf]\\s*\\(?\\s*x?\\s*\\)?\\s*=\\s*/i, '');\n if (!expr) return null;\n\n const tokens = tokenize(expr);\n if (tokens.length === 0) return null;\n\n const withMul = insertImplicitMul(tokens);\n const fn = parse(withMul);\n\n // Validate: test with a few x values\n const test1 = fn(0);\n const test2 = fn(1);\n if (typeof test1 !== 'number' && typeof test2 !== 'number') return null;\n\n return fn;\n } catch (e) {\n return null;\n }\n}\n\n/**\n * Validate an expression string \u2014 returns true if parseable.\n */\nexport function isValidExpression(input) {\n return parseExpression(input) !== null;\n}\n"],
|
|
5
|
+
"mappings": ";;;AASA,IAAM,YAAY;AAAA,EACd,KAAK,KAAK;AAAA,EAAK,KAAK,KAAK;AAAA,EAAK,KAAK,KAAK;AAAA,EACxC,MAAM,KAAK;AAAA,EAAM,MAAM,KAAK;AAAA,EAAM,MAAM,KAAK;AAAA,EAC7C,MAAM,KAAK;AAAA,EAAM,KAAK,KAAK;AAAA,EAC3B,KAAK,KAAK;AAAA,EAAO,IAAI,KAAK;AAAA,EAAK,KAAK,KAAK;AAAA,EACzC,OAAO,KAAK;AAAA,EAAO,MAAM,KAAK;AAClC;AAEA,IAAM,YAAY,EAAE,IAAI,KAAK,IAAI,GAAG,KAAK,EAAE;AAG3C,SAAS,SAAS,MAAM;AACpB,QAAM,SAAS,CAAC;AAChB,MAAI,IAAI;AACR,SAAO,IAAI,KAAK,QAAQ;AACpB,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,KAAK,KAAK,EAAE,GAAG;AAAE;AAAK;AAAA,IAAU;AACpC,QAAI,WAAW,SAAS,EAAE,GAAG;AACzB,aAAO,KAAK,EAAE,MAAM,MAAM,OAAO,GAAG,CAAC;AACrC;AACA;AAAA,IACJ;AAEA,QAAI,SAAS,KAAK,EAAE,GAAG;AACnB,UAAI,MAAM;AACV,aAAO,IAAI,KAAK,UAAU,SAAS,KAAK,KAAK,CAAC,CAAC,GAAG;AAAE,eAAO,KAAK,CAAC;AAAG;AAAA,MAAK;AACzE,aAAO,KAAK,EAAE,MAAM,OAAO,OAAO,WAAW,GAAG,EAAE,CAAC;AACnD;AAAA,IACJ;AAEA,QAAI,YAAY,KAAK,EAAE,GAAG;AACtB,UAAI,OAAO;AACX,aAAO,IAAI,KAAK,UAAU,eAAe,KAAK,KAAK,CAAC,CAAC,GAAG;AAAE,gBAAQ,KAAK,CAAC;AAAG;AAAA,MAAK;AAChF,aAAO,KAAK,EAAE,MAAM,MAAM,OAAO,KAAK,CAAC;AACvC;AAAA,IACJ;AACA;AAAA,EACJ;AACA,SAAO;AACX;AAGA,SAAS,kBAAkB,QAAQ;AAC/B,QAAM,SAAS,CAAC;AAChB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACpC,UAAM,IAAI,OAAO,CAAC;AAClB,WAAO,KAAK,CAAC;AACb,QAAI,IAAI,IAAI,OAAO,QAAQ;AACvB,YAAM,OAAO,OAAO,IAAI,CAAC;AACzB,YAAM;AAAA;AAAA,QAED,EAAE,SAAS,UAAU,KAAK,SAAS,QAAQ,KAAK,UAAU;AAAA,QAE1D,EAAE,UAAU,QAAQ,KAAK,SAAS,SAAS,KAAK,SAAS,QAAQ,KAAK,UAAU;AAAA,QAEhF,EAAE,SAAS,QAAQ,KAAK,UAAU,OAAO,CAAC,UAAU,EAAE,KAAK;AAAA,QAE3D,EAAE,SAAS,QAAQ,CAAC,UAAU,EAAE,KAAK,KAAK,KAAK,SAAS;AAAA,QAExD,EAAE,SAAS,QAAQ,CAAC,UAAU,EAAE,KAAK,KAAK,KAAK,SAAS;AAAA;AAC7D,UAAI,UAAU;AACV,eAAO,KAAK,EAAE,MAAM,MAAM,OAAO,IAAI,CAAC;AAAA,MAC1C;AAAA,IACJ;AAAA,EACJ;AACA,SAAO;AACX;AAGA,SAAS,MAAM,QAAQ;AACnB,MAAI,MAAM;AAEV,WAAS,OAAO;AAAE,WAAO,OAAO,GAAG;AAAA,EAAG;AACtC,WAAS,QAAQ,UAAU;AACvB,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,aAAa,CAAC,KAAK,EAAE,UAAU,UAAW,QAAO;AACrD;AACA,WAAO;AAAA,EACX;AAGA,WAAS,YAAY;AACjB,QAAI,OAAO,UAAU;AACrB,WAAO,KAAK,MAAM,KAAK,EAAE,UAAU,OAAO,KAAK,EAAE,UAAU,MAAM;AAC7D,YAAM,KAAK,QAAQ,EAAE;AACrB,YAAM,QAAQ,UAAU;AACxB,YAAM,IAAI,MAAM,IAAI;AACpB,UAAI,OAAO,IAAK,QAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,UACnC,QAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,IACjC;AACA,WAAO;AAAA,EACX;AAGA,WAAS,YAAY;AACjB,QAAI,OAAO,WAAW;AACtB,WAAO,KAAK,MAAM,KAAK,EAAE,UAAU,OAAO,KAAK,EAAE,UAAU,MAAM;AAC7D,YAAM,KAAK,QAAQ,EAAE;AACrB,YAAM,QAAQ,WAAW;AACzB,YAAM,IAAI,MAAM,IAAI;AACpB,UAAI,OAAO,IAAK,QAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,UACnC,QAAO,CAAC,MAAM;AAAE,cAAM,IAAI,EAAE,CAAC;AAAG,eAAO,MAAM,IAAI,MAAM,EAAE,CAAC,IAAI;AAAA,MAAG;AAAA,IAC1E;AACA,WAAO;AAAA,EACX;AAGA,WAAS,aAAa;AAClB,QAAI,OAAO,WAAW;AACtB,QAAI,KAAK,KAAK,KAAK,EAAE,UAAU,KAAK;AAChC,cAAQ;AACR,YAAM,MAAM,WAAW;AACvB,YAAM,IAAI;AACV,aAAO,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;AAAA,IACvC;AACA,WAAO;AAAA,EACX;AAGA,WAAS,aAAa;AAClB,QAAI,KAAK,KAAK,KAAK,EAAE,UAAU,KAAK;AAChC,cAAQ;AACR,YAAM,MAAM,aAAa;AACzB,aAAO,CAAC,MAAM,CAAC,IAAI,CAAC;AAAA,IACxB;AACA,QAAI,KAAK,KAAK,KAAK,EAAE,UAAU,KAAK;AAAE,cAAQ;AAAA,IAAG;AACjD,WAAO,aAAa;AAAA,EACxB;AAGA,WAAS,eAAe;AACpB,UAAM,IAAI,KAAK;AACf,QAAI,CAAC,EAAG,QAAO,MAAM;AAGrB,QAAI,EAAE,SAAS,OAAO;AAClB,cAAQ;AACR,YAAM,IAAI,EAAE;AACZ,aAAO,MAAM;AAAA,IACjB;AAGA,QAAI,EAAE,UAAU,KAAK;AACjB,cAAQ,GAAG;AACX,YAAM,QAAQ,UAAU;AACxB,cAAQ,GAAG;AACX,aAAO;AAAA,IACX;AAGA,QAAI,EAAE,SAAS,MAAM;AACjB,cAAQ;AACR,YAAM,OAAO,EAAE,MAAM,YAAY;AAGjC,UAAI,UAAU,IAAI,MAAM,QAAW;AAC/B,cAAM,IAAI,UAAU,IAAI;AACxB,eAAO,MAAM;AAAA,MACjB;AAGA,UAAI,UAAU,IAAI,KAAK,KAAK,KAAK,KAAK,EAAE,UAAU,KAAK;AACnD,gBAAQ,GAAG;AACX,cAAM,MAAM,UAAU;AACtB,gBAAQ,GAAG;AACX,cAAMA,MAAK,UAAU,IAAI;AACzB,eAAO,CAAC,MAAMA,IAAG,IAAI,CAAC,CAAC;AAAA,MAC3B;AAGA,UAAI,SAAS,IAAK,QAAO,CAAC,MAAM;AAGhC,aAAO,CAAC,MAAM;AAAA,IAClB;AAGA,YAAQ;AACR,WAAO,MAAM;AAAA,EACjB;AAEA,QAAM,KAAK,UAAU;AACrB,SAAO;AACX;AAMO,SAAS,gBAAgB,OAAO;AACnC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAEhD,MAAI;AACA,QAAI,OAAO,MAAM,KAAK;AAGtB,WAAO,KAAK,QAAQ,kCAAkC,EAAE;AACxD,QAAI,CAAC,KAAM,QAAO;AAElB,UAAM,SAAS,SAAS,IAAI;AAC5B,QAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,UAAM,UAAU,kBAAkB,MAAM;AACxC,UAAM,KAAK,MAAM,OAAO;AAGxB,UAAM,QAAQ,GAAG,CAAC;AAClB,UAAM,QAAQ,GAAG,CAAC;AAClB,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AAEnE,WAAO;AAAA,EACX,SAAS,GAAG;AACR,WAAO;AAAA,EACX;AACJ;AAKO,SAAS,kBAAkB,OAAO;AACrC,SAAO,gBAAgB,KAAK,MAAM;AACtC;",
|
|
6
|
+
"names": ["fn"]
|
|
7
|
+
}
|