@nice2dev/ui-math 1.0.10

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/index.mjs ADDED
@@ -0,0 +1,3491 @@
1
+ var T = Object.defineProperty;
2
+ var R = (e, t, r) => t in e ? T(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
+ var M = (e, t, r) => R(e, typeof t != "symbol" ? t + "" : t, r);
4
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
+ import { createContext, useContext, useState, useRef, useCallback, useEffect } from "react";
6
+ const MATH_SYMBOLS = [
7
+ // Greek lowercase
8
+ { name: "alpha", latex: "\\alpha", category: "greek", preview: "α" },
9
+ { name: "beta", latex: "\\beta", category: "greek", preview: "β" },
10
+ { name: "gamma", latex: "\\gamma", category: "greek", preview: "γ" },
11
+ { name: "delta", latex: "\\delta", category: "greek", preview: "δ" },
12
+ { name: "epsilon", latex: "\\epsilon", category: "greek", preview: "ε" },
13
+ { name: "zeta", latex: "\\zeta", category: "greek", preview: "ζ" },
14
+ { name: "eta", latex: "\\eta", category: "greek", preview: "η" },
15
+ { name: "theta", latex: "\\theta", category: "greek", preview: "θ" },
16
+ { name: "iota", latex: "\\iota", category: "greek", preview: "ι" },
17
+ { name: "kappa", latex: "\\kappa", category: "greek", preview: "κ" },
18
+ { name: "lambda", latex: "\\lambda", category: "greek", preview: "λ" },
19
+ { name: "mu", latex: "\\mu", category: "greek", preview: "μ" },
20
+ { name: "nu", latex: "\\nu", category: "greek", preview: "ν" },
21
+ { name: "xi", latex: "\\xi", category: "greek", preview: "ξ" },
22
+ { name: "pi", latex: "\\pi", category: "greek", preview: "π" },
23
+ { name: "rho", latex: "\\rho", category: "greek", preview: "ρ" },
24
+ { name: "sigma", latex: "\\sigma", category: "greek", preview: "σ" },
25
+ { name: "tau", latex: "\\tau", category: "greek", preview: "τ" },
26
+ { name: "upsilon", latex: "\\upsilon", category: "greek", preview: "υ" },
27
+ { name: "phi", latex: "\\phi", category: "greek", preview: "φ" },
28
+ { name: "chi", latex: "\\chi", category: "greek", preview: "χ" },
29
+ { name: "psi", latex: "\\psi", category: "greek", preview: "ψ" },
30
+ { name: "omega", latex: "\\omega", category: "greek", preview: "ω" },
31
+ // Greek uppercase
32
+ { name: "Gamma", latex: "\\Gamma", category: "greek", preview: "Γ" },
33
+ { name: "Delta", latex: "\\Delta", category: "greek", preview: "Δ" },
34
+ { name: "Theta", latex: "\\Theta", category: "greek", preview: "Θ" },
35
+ { name: "Lambda", latex: "\\Lambda", category: "greek", preview: "Λ" },
36
+ { name: "Xi", latex: "\\Xi", category: "greek", preview: "Ξ" },
37
+ { name: "Pi", latex: "\\Pi", category: "greek", preview: "Π" },
38
+ { name: "Sigma", latex: "\\Sigma", category: "greek", preview: "Σ" },
39
+ { name: "Phi", latex: "\\Phi", category: "greek", preview: "Φ" },
40
+ { name: "Psi", latex: "\\Psi", category: "greek", preview: "Ψ" },
41
+ { name: "Omega", latex: "\\Omega", category: "greek", preview: "Ω" },
42
+ // Operators
43
+ { name: "plus/minus", latex: "\\pm", category: "operators", preview: "±" },
44
+ { name: "minus/plus", latex: "\\mp", category: "operators", preview: "∓" },
45
+ { name: "times", latex: "\\times", category: "operators", preview: "×" },
46
+ { name: "divide", latex: "\\div", category: "operators", preview: "÷" },
47
+ { name: "cdot", latex: "\\cdot", category: "operators", preview: "·" },
48
+ { name: "star", latex: "\\star", category: "operators", preview: "⋆" },
49
+ { name: "circle", latex: "\\circ", category: "operators", preview: "∘" },
50
+ { name: "bullet", latex: "\\bullet", category: "operators", preview: "•" },
51
+ { name: "oplus", latex: "\\oplus", category: "operators", preview: "⊕" },
52
+ { name: "otimes", latex: "\\otimes", category: "operators", preview: "⊗" },
53
+ { name: "odot", latex: "\\odot", category: "operators", preview: "⊙" },
54
+ // Relations
55
+ { name: "less than", latex: "<", category: "relations", preview: "<" },
56
+ { name: "greater than", latex: ">", category: "relations", preview: ">" },
57
+ { name: "less or equal", latex: "\\leq", category: "relations", preview: "≤" },
58
+ { name: "greater or equal", latex: "\\geq", category: "relations", preview: "≥" },
59
+ { name: "not equal", latex: "\\neq", category: "relations", preview: "≠" },
60
+ { name: "approximately", latex: "\\approx", category: "relations", preview: "≈" },
61
+ { name: "equivalent", latex: "\\equiv", category: "relations", preview: "≡" },
62
+ { name: "similar", latex: "\\sim", category: "relations", preview: "∼" },
63
+ { name: "proportional", latex: "\\propto", category: "relations", preview: "∝" },
64
+ { name: "perpendicular", latex: "\\perp", category: "relations", preview: "⊥" },
65
+ { name: "parallel", latex: "\\parallel", category: "relations", preview: "∥" },
66
+ // Arrows
67
+ { name: "right arrow", latex: "\\rightarrow", category: "arrows", preview: "→" },
68
+ { name: "left arrow", latex: "\\leftarrow", category: "arrows", preview: "←" },
69
+ { name: "double right", latex: "\\Rightarrow", category: "arrows", preview: "⇒" },
70
+ { name: "double left", latex: "\\Leftarrow", category: "arrows", preview: "⇐" },
71
+ { name: "iff", latex: "\\Leftrightarrow", category: "arrows", preview: "⇔" },
72
+ { name: "up arrow", latex: "\\uparrow", category: "arrows", preview: "↑" },
73
+ { name: "down arrow", latex: "\\downarrow", category: "arrows", preview: "↓" },
74
+ { name: "maps to", latex: "\\mapsto", category: "arrows", preview: "↦" },
75
+ // Functions
76
+ { name: "sine", latex: "\\sin", category: "functions", preview: "sin" },
77
+ { name: "cosine", latex: "\\cos", category: "functions", preview: "cos" },
78
+ { name: "tangent", latex: "\\tan", category: "functions", preview: "tan" },
79
+ { name: "cotangent", latex: "\\cot", category: "functions", preview: "cot" },
80
+ { name: "arcsine", latex: "\\arcsin", category: "functions", preview: "arcsin" },
81
+ { name: "arccosine", latex: "\\arccos", category: "functions", preview: "arccos" },
82
+ { name: "arctangent", latex: "\\arctan", category: "functions", preview: "arctan" },
83
+ { name: "logarithm", latex: "\\log", category: "functions", preview: "log" },
84
+ { name: "natural log", latex: "\\ln", category: "functions", preview: "ln" },
85
+ { name: "exponential", latex: "\\exp", category: "functions", preview: "exp" },
86
+ { name: "limit", latex: "\\lim", category: "functions", preview: "lim" },
87
+ { name: "supremum", latex: "\\sup", category: "functions", preview: "sup" },
88
+ { name: "infimum", latex: "\\inf", category: "functions", preview: "inf" },
89
+ { name: "maximum", latex: "\\max", category: "functions", preview: "max" },
90
+ { name: "minimum", latex: "\\min", category: "functions", preview: "min" },
91
+ // Accents
92
+ { name: "hat", latex: "\\hat{x}", category: "accents", preview: "x̂" },
93
+ { name: "bar", latex: "\\bar{x}", category: "accents", preview: "x̄" },
94
+ { name: "vector", latex: "\\vec{x}", category: "accents", preview: "x⃗" },
95
+ { name: "dot", latex: "\\dot{x}", category: "accents", preview: "ẋ" },
96
+ { name: "double dot", latex: "\\ddot{x}", category: "accents", preview: "ẍ" },
97
+ { name: "tilde", latex: "\\tilde{x}", category: "accents", preview: "x̃" },
98
+ // Delimiters
99
+ { name: "parentheses", latex: "\\left( \\right)", category: "delimiters", preview: "( )" },
100
+ { name: "brackets", latex: "\\left[ \\right]", category: "delimiters", preview: "[ ]" },
101
+ { name: "braces", latex: "\\left\\{ \\right\\}", category: "delimiters", preview: "{ }" },
102
+ {
103
+ name: "angle brackets",
104
+ latex: "\\left\\langle \\right\\rangle",
105
+ category: "delimiters",
106
+ preview: "⟨ ⟩"
107
+ },
108
+ {
109
+ name: "ceiling",
110
+ latex: "\\left\\lceil \\right\\rceil",
111
+ category: "delimiters",
112
+ preview: "⌈ ⌉"
113
+ },
114
+ {
115
+ name: "floor",
116
+ latex: "\\left\\lfloor \\right\\rfloor",
117
+ category: "delimiters",
118
+ preview: "⌊ ⌋"
119
+ },
120
+ { name: "absolute", latex: "\\left| \\right|", category: "delimiters", preview: "| |" },
121
+ { name: "norm", latex: "\\left\\| \\right\\|", category: "delimiters", preview: "‖ ‖" },
122
+ // Sets
123
+ { name: "element of", latex: "\\in", category: "sets", preview: "∈" },
124
+ { name: "not element", latex: "\\notin", category: "sets", preview: "∉" },
125
+ { name: "contains", latex: "\\ni", category: "sets", preview: "∋" },
126
+ { name: "subset", latex: "\\subset", category: "sets", preview: "⊂" },
127
+ { name: "superset", latex: "\\supset", category: "sets", preview: "⊃" },
128
+ { name: "subset or equal", latex: "\\subseteq", category: "sets", preview: "⊆" },
129
+ { name: "union", latex: "\\cup", category: "sets", preview: "∪" },
130
+ { name: "intersection", latex: "\\cap", category: "sets", preview: "∩" },
131
+ { name: "set minus", latex: "\\setminus", category: "sets", preview: "∖" },
132
+ { name: "empty set", latex: "\\emptyset", category: "sets", preview: "∅" },
133
+ { name: "naturals", latex: "\\mathbb{N}", category: "sets", preview: "ℕ" },
134
+ { name: "integers", latex: "\\mathbb{Z}", category: "sets", preview: "ℤ" },
135
+ { name: "rationals", latex: "\\mathbb{Q}", category: "sets", preview: "ℚ" },
136
+ { name: "reals", latex: "\\mathbb{R}", category: "sets", preview: "ℝ" },
137
+ { name: "complex", latex: "\\mathbb{C}", category: "sets", preview: "ℂ" },
138
+ // Logic
139
+ { name: "for all", latex: "\\forall", category: "logic", preview: "∀" },
140
+ { name: "exists", latex: "\\exists", category: "logic", preview: "∃" },
141
+ { name: "not exists", latex: "\\nexists", category: "logic", preview: "∄" },
142
+ { name: "and", latex: "\\land", category: "logic", preview: "∧" },
143
+ { name: "or", latex: "\\lor", category: "logic", preview: "∨" },
144
+ { name: "not", latex: "\\neg", category: "logic", preview: "¬" },
145
+ { name: "therefore", latex: "\\therefore", category: "logic", preview: "∴" },
146
+ { name: "because", latex: "\\because", category: "logic", preview: "∵" },
147
+ // Calculus
148
+ { name: "integral", latex: "\\int", category: "calculus", preview: "∫" },
149
+ { name: "double integral", latex: "\\iint", category: "calculus", preview: "∬" },
150
+ { name: "triple integral", latex: "\\iiint", category: "calculus", preview: "∭" },
151
+ { name: "contour integral", latex: "\\oint", category: "calculus", preview: "∮" },
152
+ { name: "partial", latex: "\\partial", category: "calculus", preview: "∂" },
153
+ { name: "nabla/gradient", latex: "\\nabla", category: "calculus", preview: "∇" },
154
+ { name: "summation", latex: "\\sum", category: "calculus", preview: "Σ" },
155
+ { name: "product", latex: "\\prod", category: "calculus", preview: "Π" },
156
+ { name: "infinity", latex: "\\infty", category: "calculus", preview: "∞" },
157
+ // Matrices
158
+ {
159
+ name: "matrix",
160
+ latex: "\\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}",
161
+ category: "matrices",
162
+ preview: "[ ]"
163
+ },
164
+ {
165
+ name: "determinant",
166
+ latex: "\\begin{vmatrix} a & b \\\\ c & d \\end{vmatrix}",
167
+ category: "matrices",
168
+ preview: "| |"
169
+ },
170
+ {
171
+ name: "bracket matrix",
172
+ latex: "\\begin{bmatrix} a & b \\\\ c & d \\end{bmatrix}",
173
+ category: "matrices",
174
+ preview: "[[ ]]"
175
+ },
176
+ {
177
+ name: "cases",
178
+ latex: "\\begin{cases} a & \\text{if } x > 0 \\\\ b & \\text{otherwise} \\end{cases}",
179
+ category: "matrices",
180
+ preview: "{ }"
181
+ }
182
+ ];
183
+ function getSymbolsByCategory(e) {
184
+ return MATH_SYMBOLS.filter((t) => t.category === e);
185
+ }
186
+ const EQUATION_TEMPLATES = [
187
+ // Basic
188
+ { name: "Fraction", latex: "\\frac{a}{b}", category: "basic" },
189
+ { name: "Square root", latex: "\\sqrt{x}", category: "basic" },
190
+ { name: "Nth root", latex: "\\sqrt[n]{x}", category: "basic" },
191
+ { name: "Power", latex: "x^{n}", category: "basic" },
192
+ { name: "Subscript", latex: "x_{n}", category: "basic" },
193
+ { name: "Both", latex: "x_{i}^{n}", category: "basic" },
194
+ // Calculus
195
+ { name: "Derivative", latex: "\\frac{d}{dx}f(x)", category: "calculus" },
196
+ { name: "Partial derivative", latex: "\\frac{\\partial f}{\\partial x}", category: "calculus" },
197
+ { name: "Definite integral", latex: "\\int_{a}^{b} f(x)\\,dx", category: "calculus" },
198
+ { name: "Indefinite integral", latex: "\\int f(x)\\,dx", category: "calculus" },
199
+ { name: "Limit", latex: "\\lim_{x \\to a} f(x)", category: "calculus" },
200
+ { name: "Summation", latex: "\\sum_{i=1}^{n} a_i", category: "calculus" },
201
+ { name: "Product", latex: "\\prod_{i=1}^{n} a_i", category: "calculus" },
202
+ // Algebra
203
+ {
204
+ name: "Quadratic formula",
205
+ latex: "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}",
206
+ category: "algebra"
207
+ },
208
+ { name: "Binomial", latex: "\\binom{n}{k} = \\frac{n!}{k!(n-k)!}", category: "algebra" },
209
+ {
210
+ name: "System of equations",
211
+ latex: "\\begin{cases} ax + by = c \\\\ dx + ey = f \\end{cases}",
212
+ category: "algebra"
213
+ },
214
+ // Geometry/Trigonometry
215
+ { name: "Pythagorean", latex: "a^2 + b^2 = c^2", category: "geometry" },
216
+ { name: "Circle area", latex: "A = \\pi r^2", category: "geometry" },
217
+ { name: "Sphere volume", latex: "V = \\frac{4}{3}\\pi r^3", category: "geometry" },
218
+ { name: "Euler's identity", latex: "e^{i\\pi} + 1 = 0", category: "geometry" },
219
+ // Statistics
220
+ { name: "Mean", latex: "\\bar{x} = \\frac{1}{n}\\sum_{i=1}^{n} x_i", category: "statistics" },
221
+ {
222
+ name: "Variance",
223
+ latex: "\\sigma^2 = \\frac{1}{n}\\sum_{i=1}^{n}(x_i - \\bar{x})^2",
224
+ category: "statistics"
225
+ },
226
+ {
227
+ name: "Normal distribution",
228
+ latex: "f(x) = \\frac{1}{\\sigma\\sqrt{2\\pi}}e^{-\\frac{(x-\\mu)^2}{2\\sigma^2}}",
229
+ category: "statistics"
230
+ },
231
+ // Physics
232
+ { name: "Einstein mass-energy", latex: "E = mc^2", category: "physics" },
233
+ { name: "Newton's second law", latex: "F = ma", category: "physics" },
234
+ {
235
+ name: "Schrödinger equation",
236
+ latex: "i\\hbar\\frac{\\partial}{\\partial t}\\Psi = \\hat{H}\\Psi",
237
+ category: "physics"
238
+ },
239
+ {
240
+ name: "Maxwell's equations",
241
+ latex: "\\nabla \\cdot \\vec{E} = \\frac{\\rho}{\\epsilon_0}",
242
+ category: "physics"
243
+ }
244
+ ];
245
+ class MathEditorService {
246
+ constructor(t = {}) {
247
+ M(this, "equations", /* @__PURE__ */ new Map());
248
+ M(this, "config");
249
+ M(this, "nextNumber");
250
+ this.config = {
251
+ enableNumbering: t.enableNumbering ?? !0,
252
+ startNumber: t.startNumber ?? 1,
253
+ renderDelay: t.renderDelay ?? 100
254
+ }, this.nextNumber = this.config.startNumber;
255
+ }
256
+ /** Create new equation */
257
+ createEquation(t, r) {
258
+ const a = {
259
+ id: this.generateId(),
260
+ latex: t,
261
+ label: r,
262
+ number: this.config.enableNumbering ? this.nextNumber++ : void 0,
263
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
264
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
265
+ };
266
+ return this.equations.set(a.id, a), a;
267
+ }
268
+ /** Update equation */
269
+ updateEquation(t, r, a) {
270
+ const o = this.equations.get(t);
271
+ if (!o)
272
+ throw new Error(`Equation not found: ${t}`);
273
+ const n = {
274
+ ...o,
275
+ latex: r,
276
+ label: a ?? o.label,
277
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
278
+ };
279
+ return this.equations.set(t, n), n;
280
+ }
281
+ /** Delete equation */
282
+ deleteEquation(t) {
283
+ this.equations.delete(t);
284
+ }
285
+ /** Get equation */
286
+ getEquation(t) {
287
+ return this.equations.get(t);
288
+ }
289
+ /** List all equations */
290
+ listEquations() {
291
+ return Array.from(this.equations.values()).sort(
292
+ (t, r) => new Date(t.createdAt).getTime() - new Date(r.createdAt).getTime()
293
+ );
294
+ }
295
+ /** Export to LaTeX document */
296
+ exportToLatex() {
297
+ const t = [
298
+ "\\documentclass{article}",
299
+ "\\usepackage{amsmath}",
300
+ "\\usepackage{amssymb}",
301
+ "",
302
+ "\\begin{document}",
303
+ ""
304
+ ];
305
+ for (const r of this.listEquations())
306
+ r.number !== void 0 ? (t.push("\\begin{equation}"), r.label && t.push(`\\label{${r.label}}`), t.push(r.latex), t.push("\\end{equation}")) : (t.push("\\["), t.push(r.latex), t.push("\\]")), t.push("");
307
+ return t.push("\\end{document}"), t.join(`
308
+ `);
309
+ }
310
+ /** Parse LaTeX and extract equations */
311
+ parseLatex(t) {
312
+ const r = [], a = /\\\[([\s\S]*?)\\\]/g;
313
+ let o;
314
+ for (; (o = a.exec(t)) !== null; )
315
+ r.push(this.createEquation(o[1].trim()));
316
+ const n = /\\begin\{equation\}([\s\S]*?)\\end\{equation\}/g;
317
+ for (; (o = n.exec(t)) !== null; ) {
318
+ const s = o[1].match(/\\label\{([^}]+)\}/), c = o[1].replace(/\\label\{[^}]+\}/, "").trim();
319
+ r.push(this.createEquation(c, s == null ? void 0 : s[1]));
320
+ }
321
+ return r;
322
+ }
323
+ generateId() {
324
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
325
+ }
326
+ }
327
+ function createMathEditorService(e) {
328
+ return new MathEditorService(e);
329
+ }
330
+ async function recognizeHandwriting(e) {
331
+ return await new Promise((r) => setTimeout(r, 500)), {
332
+ latex: e.reduce((r, a) => r + a.points.length, 0) > 50 ? "\\sqrt{x^2 + y^2}" : "x",
333
+ confidence: 0.85,
334
+ alternatives: ["x", "X", "\\times"]
335
+ };
336
+ }
337
+ const MathEditorContext = createContext(null);
338
+ function useMathEditor() {
339
+ const e = useContext(MathEditorContext);
340
+ if (!e)
341
+ throw new Error("useMathEditor must be used within MathEditorProvider");
342
+ return e;
343
+ }
344
+ const styles$3 = {
345
+ container: {
346
+ display: "flex",
347
+ flexDirection: "column",
348
+ height: "100%",
349
+ fontFamily: "'Inter', sans-serif",
350
+ fontSize: "14px"
351
+ },
352
+ toolbar: {
353
+ display: "flex",
354
+ gap: "8px",
355
+ padding: "8px",
356
+ borderBottom: "1px solid #e0e0e0",
357
+ backgroundColor: "#fafafa",
358
+ flexWrap: "wrap",
359
+ alignItems: "center"
360
+ },
361
+ main: {
362
+ display: "flex",
363
+ flex: 1,
364
+ overflow: "hidden"
365
+ },
366
+ sidebar: {
367
+ width: "200px",
368
+ borderRight: "1px solid #e0e0e0",
369
+ overflow: "auto",
370
+ backgroundColor: "#f5f5f5"
371
+ },
372
+ editor: {
373
+ flex: 1,
374
+ display: "flex",
375
+ flexDirection: "column",
376
+ padding: "16px",
377
+ overflow: "auto"
378
+ },
379
+ input: {
380
+ width: "100%",
381
+ minHeight: "100px",
382
+ padding: "12px",
383
+ fontFamily: "'JetBrains Mono', monospace",
384
+ fontSize: "14px",
385
+ border: "1px solid #ddd",
386
+ borderRadius: "4px",
387
+ resize: "vertical"
388
+ },
389
+ preview: {
390
+ marginTop: "16px",
391
+ padding: "20px",
392
+ backgroundColor: "#fff",
393
+ border: "1px solid #e0e0e0",
394
+ borderRadius: "4px",
395
+ minHeight: "60px",
396
+ fontSize: "20px",
397
+ textAlign: "center"
398
+ },
399
+ button: {
400
+ padding: "6px 12px",
401
+ backgroundColor: "#1976d2",
402
+ color: "white",
403
+ border: "none",
404
+ borderRadius: "4px",
405
+ cursor: "pointer",
406
+ fontSize: "13px"
407
+ },
408
+ symbolGrid: {
409
+ display: "grid",
410
+ gridTemplateColumns: "repeat(5, 1fr)",
411
+ gap: "4px",
412
+ padding: "8px"
413
+ },
414
+ symbolButton: {
415
+ padding: "8px",
416
+ border: "1px solid #ddd",
417
+ borderRadius: "4px",
418
+ backgroundColor: "#fff",
419
+ cursor: "pointer",
420
+ fontSize: "16px",
421
+ textAlign: "center"
422
+ },
423
+ categoryHeader: {
424
+ padding: "8px 12px",
425
+ backgroundColor: "#e0e0e0",
426
+ fontWeight: 600,
427
+ fontSize: "12px",
428
+ textTransform: "uppercase"
429
+ },
430
+ canvas: {
431
+ width: "100%",
432
+ height: "200px",
433
+ border: "1px solid #ddd",
434
+ borderRadius: "4px",
435
+ backgroundColor: "#fff",
436
+ cursor: "crosshair"
437
+ }
438
+ };
439
+ function NiceMathEditor({
440
+ service: e,
441
+ initialLatex: t = "",
442
+ onChange: r,
443
+ className: a,
444
+ style: o
445
+ }) {
446
+ const [n, s] = useState(t), [c, l] = useState("input"), i = useRef(null), d = useCallback(
447
+ (y) => {
448
+ s(y), r == null || r(y);
449
+ },
450
+ [r]
451
+ ), u = useCallback(
452
+ (y) => {
453
+ const g = i.current;
454
+ if (!g) {
455
+ d(n + y);
456
+ return;
457
+ }
458
+ const m = g.selectionStart, p = g.selectionEnd, x = n.slice(0, m) + y + n.slice(p);
459
+ d(x), setTimeout(() => {
460
+ g.focus(), g.selectionStart = g.selectionEnd = m + y.length;
461
+ }, 0);
462
+ },
463
+ [n, d]
464
+ ), h = useCallback(
465
+ (y) => {
466
+ u(y.latex);
467
+ },
468
+ [u]
469
+ ), b = {
470
+ service: e,
471
+ latex: n,
472
+ setLatex: d,
473
+ insertSymbol: u,
474
+ insertTemplate: h,
475
+ mode: c,
476
+ setMode: l
477
+ };
478
+ return /* @__PURE__ */ jsx(MathEditorContext.Provider, { value: b, children: /* @__PURE__ */ jsxs("div", { className: a, style: { ...styles$3.container, ...o }, children: [
479
+ /* @__PURE__ */ jsx(Toolbar$1, {}),
480
+ /* @__PURE__ */ jsxs("div", { style: styles$3.main, children: [
481
+ /* @__PURE__ */ jsx(SymbolPalette, {}),
482
+ /* @__PURE__ */ jsx("div", { style: styles$3.editor, children: c === "input" ? /* @__PURE__ */ jsxs(Fragment, { children: [
483
+ /* @__PURE__ */ jsx(
484
+ "textarea",
485
+ {
486
+ ref: i,
487
+ value: n,
488
+ onChange: (y) => d(y.target.value),
489
+ placeholder: "Enter LaTeX equation...",
490
+ style: styles$3.input
491
+ }
492
+ ),
493
+ /* @__PURE__ */ jsx(LatexPreview, { latex: n })
494
+ ] }) : /* @__PURE__ */ jsx(HandwritingCanvas, {}) })
495
+ ] })
496
+ ] }) });
497
+ }
498
+ function Toolbar$1() {
499
+ const { mode: e, setMode: t, latex: r, insertTemplate: a } = useMathEditor(), [o, n] = useState(!1);
500
+ return /* @__PURE__ */ jsxs("div", { style: styles$3.toolbar, children: [
501
+ /* @__PURE__ */ jsx(
502
+ "button",
503
+ {
504
+ onClick: () => t("input"),
505
+ style: {
506
+ ...styles$3.button,
507
+ backgroundColor: e === "input" ? "#1976d2" : "#9e9e9e"
508
+ },
509
+ children: "⌨️ LaTeX Input"
510
+ }
511
+ ),
512
+ /* @__PURE__ */ jsx(
513
+ "button",
514
+ {
515
+ onClick: () => t("handwriting"),
516
+ style: {
517
+ ...styles$3.button,
518
+ backgroundColor: e === "handwriting" ? "#1976d2" : "#9e9e9e"
519
+ },
520
+ children: "✏️ Handwriting"
521
+ }
522
+ ),
523
+ /* @__PURE__ */ jsx("div", { style: { borderLeft: "1px solid #ccc", height: "24px", margin: "0 8px" } }),
524
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
525
+ /* @__PURE__ */ jsx("button", { onClick: () => n(!o), style: styles$3.button, children: "📐 Templates ▾" }),
526
+ o && /* @__PURE__ */ jsx(
527
+ "div",
528
+ {
529
+ style: {
530
+ position: "absolute",
531
+ top: "100%",
532
+ left: 0,
533
+ backgroundColor: "#fff",
534
+ border: "1px solid #ddd",
535
+ borderRadius: "4px",
536
+ boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
537
+ zIndex: 100,
538
+ width: "300px",
539
+ maxHeight: "400px",
540
+ overflow: "auto"
541
+ },
542
+ children: ["basic", "calculus", "algebra", "geometry", "statistics", "physics"].map(
543
+ (s) => /* @__PURE__ */ jsxs("div", { children: [
544
+ /* @__PURE__ */ jsx("div", { style: styles$3.categoryHeader, children: s }),
545
+ EQUATION_TEMPLATES.filter((c) => c.category === s).map((c) => /* @__PURE__ */ jsxs(
546
+ "div",
547
+ {
548
+ onClick: () => {
549
+ a(c), n(!1);
550
+ },
551
+ style: {
552
+ padding: "8px 12px",
553
+ cursor: "pointer",
554
+ borderBottom: "1px solid #eee"
555
+ },
556
+ onMouseOver: (l) => l.target.style.backgroundColor = "#f5f5f5",
557
+ onMouseOut: (l) => l.target.style.backgroundColor = "transparent",
558
+ children: [
559
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 500 }, children: c.name }),
560
+ /* @__PURE__ */ jsxs("div", { style: { fontSize: "12px", color: "#666", fontFamily: "monospace" }, children: [
561
+ c.latex.substring(0, 40),
562
+ c.latex.length > 40 ? "..." : ""
563
+ ] })
564
+ ]
565
+ },
566
+ c.name
567
+ ))
568
+ ] }, s)
569
+ )
570
+ }
571
+ )
572
+ ] }),
573
+ /* @__PURE__ */ jsx("div", { style: { flex: 1 } }),
574
+ /* @__PURE__ */ jsx(
575
+ "button",
576
+ {
577
+ onClick: () => navigator.clipboard.writeText(r),
578
+ style: { ...styles$3.button, backgroundColor: "#4caf50" },
579
+ children: "📋 Copy LaTeX"
580
+ }
581
+ )
582
+ ] });
583
+ }
584
+ function SymbolPalette() {
585
+ const { insertSymbol: e } = useMathEditor(), [t, r] = useState("greek"), a = [
586
+ "greek",
587
+ "operators",
588
+ "relations",
589
+ "arrows",
590
+ "functions",
591
+ "accents",
592
+ "delimiters",
593
+ "sets",
594
+ "logic",
595
+ "calculus",
596
+ "matrices"
597
+ ], o = getSymbolsByCategory(t);
598
+ return /* @__PURE__ */ jsxs("div", { style: styles$3.sidebar, children: [
599
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", padding: "8px", gap: "4px" }, children: a.map((n) => /* @__PURE__ */ jsx(
600
+ "button",
601
+ {
602
+ onClick: () => r(n),
603
+ style: {
604
+ padding: "4px 8px",
605
+ fontSize: "11px",
606
+ border: "1px solid #ddd",
607
+ borderRadius: "4px",
608
+ backgroundColor: t === n ? "#1976d2" : "#fff",
609
+ color: t === n ? "#fff" : "#333",
610
+ cursor: "pointer"
611
+ },
612
+ children: n
613
+ },
614
+ n
615
+ )) }),
616
+ /* @__PURE__ */ jsx("div", { style: styles$3.symbolGrid, children: o.map((n) => /* @__PURE__ */ jsx(
617
+ "button",
618
+ {
619
+ onClick: () => e(n.latex),
620
+ style: styles$3.symbolButton,
621
+ title: `${n.name}: ${n.latex}`,
622
+ children: n.preview || n.latex
623
+ },
624
+ n.name
625
+ )) })
626
+ ] });
627
+ }
628
+ function LatexPreview({ latex: e }) {
629
+ return /* @__PURE__ */ jsxs("div", { style: styles$3.preview, children: [
630
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "12px", color: "#666", marginBottom: "8px" }, children: "Preview (requires KaTeX/MathJax integration):" }),
631
+ /* @__PURE__ */ jsx("code", { style: { fontSize: "16px" }, children: e || "(empty)" })
632
+ ] });
633
+ }
634
+ function HandwritingCanvas() {
635
+ const { setLatex: e, setMode: t } = useMathEditor(), r = useRef(null), [a, o] = useState([]), [n, s] = useState([]), [c, l] = useState(!1), [i, d] = useState(!1), u = (m) => {
636
+ const p = r.current;
637
+ if (!p)
638
+ return;
639
+ l(!0);
640
+ const x = p.getBoundingClientRect();
641
+ s([
642
+ {
643
+ x: m.clientX - x.left,
644
+ y: m.clientY - x.top,
645
+ pressure: m.pressure,
646
+ timestamp: Date.now()
647
+ }
648
+ ]);
649
+ }, h = (m) => {
650
+ if (!c)
651
+ return;
652
+ const p = r.current, x = p == null ? void 0 : p.getContext("2d");
653
+ if (!p || !x)
654
+ return;
655
+ const w = p.getBoundingClientRect(), k = {
656
+ x: m.clientX - w.left,
657
+ y: m.clientY - w.top,
658
+ pressure: m.pressure,
659
+ timestamp: Date.now()
660
+ };
661
+ if (s((f) => [...f, k]), n.length > 0) {
662
+ const f = n[n.length - 1];
663
+ x.beginPath(), x.moveTo(f.x, f.y), x.lineTo(k.x, k.y), x.strokeStyle = "#000", x.lineWidth = 2, x.lineCap = "round", x.stroke();
664
+ }
665
+ }, b = () => {
666
+ if (c) {
667
+ if (l(!1), n.length > 1) {
668
+ const m = {
669
+ id: Date.now().toString(),
670
+ points: [...n]
671
+ };
672
+ o((p) => [...p, m]);
673
+ }
674
+ s([]);
675
+ }
676
+ }, y = () => {
677
+ const m = r.current, p = m == null ? void 0 : m.getContext("2d");
678
+ p && m && p.clearRect(0, 0, m.width, m.height), o([]);
679
+ }, g = async () => {
680
+ if (a.length !== 0) {
681
+ d(!0);
682
+ try {
683
+ const m = await recognizeHandwriting(a);
684
+ e(m.latex), t("input");
685
+ } finally {
686
+ d(!1);
687
+ }
688
+ }
689
+ };
690
+ return useEffect(() => {
691
+ const m = r.current;
692
+ m && (m.width = m.offsetWidth, m.height = 200);
693
+ }, []), /* @__PURE__ */ jsxs("div", { children: [
694
+ /* @__PURE__ */ jsx(
695
+ "canvas",
696
+ {
697
+ ref: r,
698
+ style: styles$3.canvas,
699
+ onPointerDown: u,
700
+ onPointerMove: h,
701
+ onPointerUp: b,
702
+ onPointerLeave: b
703
+ }
704
+ ),
705
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", marginTop: "12px" }, children: [
706
+ /* @__PURE__ */ jsx("button", { onClick: y, style: { ...styles$3.button, backgroundColor: "#f44336" }, children: "Clear" }),
707
+ /* @__PURE__ */ jsx(
708
+ "button",
709
+ {
710
+ onClick: g,
711
+ disabled: a.length === 0 || i,
712
+ style: styles$3.button,
713
+ children: i ? "Recognizing..." : "Recognize"
714
+ }
715
+ )
716
+ ] }),
717
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: "#666", marginTop: "8px" }, children: "Draw your equation above. Handwriting recognition requires external API integration." })
718
+ ] });
719
+ }
720
+ const mathConstants = {
721
+ pi: Math.PI,
722
+ PI: Math.PI,
723
+ e: Math.E,
724
+ E: Math.E,
725
+ phi: (1 + Math.sqrt(5)) / 2,
726
+ tau: Math.PI * 2
727
+ }, mathFunctions = {
728
+ sin: Math.sin,
729
+ cos: Math.cos,
730
+ tan: Math.tan,
731
+ asin: Math.asin,
732
+ acos: Math.acos,
733
+ atan: Math.atan,
734
+ atan2: Math.atan2,
735
+ sinh: Math.sinh,
736
+ cosh: Math.cosh,
737
+ tanh: Math.tanh,
738
+ sqrt: Math.sqrt,
739
+ cbrt: Math.cbrt,
740
+ abs: Math.abs,
741
+ floor: Math.floor,
742
+ ceil: Math.ceil,
743
+ round: Math.round,
744
+ exp: Math.exp,
745
+ log: Math.log,
746
+ log10: Math.log10,
747
+ log2: Math.log2,
748
+ pow: Math.pow,
749
+ min: Math.min,
750
+ max: Math.max,
751
+ sign: Math.sign,
752
+ hypot: Math.hypot,
753
+ // Custom
754
+ sec: (e) => 1 / Math.cos(e),
755
+ csc: (e) => 1 / Math.sin(e),
756
+ cot: (e) => 1 / Math.tan(e),
757
+ ln: Math.log
758
+ };
759
+ class ExpressionParser {
760
+ constructor() {
761
+ M(this, "pos", 0);
762
+ M(this, "expr", "");
763
+ }
764
+ parse(t) {
765
+ this.expr = t.replace(/\s+/g, ""), this.pos = 0;
766
+ const r = this.parseAddSub();
767
+ return (a) => this.evaluate(r, { ...mathConstants, ...a });
768
+ }
769
+ parseAddSub() {
770
+ let t = this.parseMulDiv();
771
+ for (; this.pos < this.expr.length; ) {
772
+ const r = this.expr[this.pos];
773
+ if (r !== "+" && r !== "-")
774
+ break;
775
+ this.pos++;
776
+ const a = this.parseMulDiv();
777
+ t = { type: "binary", op: r, left: t, right: a };
778
+ }
779
+ return t;
780
+ }
781
+ parseMulDiv() {
782
+ let t = this.parsePower();
783
+ for (; this.pos < this.expr.length; ) {
784
+ const r = this.expr[this.pos];
785
+ if (r !== "*" && r !== "/")
786
+ break;
787
+ this.pos++;
788
+ const a = this.parsePower();
789
+ t = { type: "binary", op: r, left: t, right: a };
790
+ }
791
+ return t;
792
+ }
793
+ parsePower() {
794
+ let t = this.parseUnary();
795
+ for (; this.pos < this.expr.length && this.expr[this.pos] === "^"; ) {
796
+ this.pos++;
797
+ const r = this.parseUnary();
798
+ t = { type: "binary", op: "^", left: t, right: r };
799
+ }
800
+ return t;
801
+ }
802
+ parseUnary() {
803
+ return this.expr[this.pos] === "-" ? (this.pos++, { type: "unary", op: "-", arg: this.parseUnary() }) : (this.expr[this.pos] === "+" && this.pos++, this.parsePrimary());
804
+ }
805
+ parsePrimary() {
806
+ if (this.expr[this.pos] === "(") {
807
+ this.pos++;
808
+ const a = this.parseAddSub();
809
+ return this.expr[this.pos] === ")" && this.pos++, a;
810
+ }
811
+ const t = this.expr.slice(this.pos).match(/^(\d+\.?\d*)/);
812
+ if (t)
813
+ return this.pos += t[1].length, { type: "number", value: parseFloat(t[1]) };
814
+ const r = this.expr.slice(this.pos).match(/^([a-zA-Z_][a-zA-Z0-9_]*)/);
815
+ if (r) {
816
+ const a = r[1];
817
+ if (this.pos += a.length, this.expr[this.pos] === "(") {
818
+ this.pos++;
819
+ const o = [];
820
+ for (; this.expr[this.pos] !== ")" && this.pos < this.expr.length; )
821
+ o.push(this.parseAddSub()), this.expr[this.pos] === "," && this.pos++;
822
+ return this.expr[this.pos] === ")" && this.pos++, { type: "call", name: a, args: o };
823
+ }
824
+ return { type: "variable", name: a };
825
+ }
826
+ return { type: "number", value: 0 };
827
+ }
828
+ evaluate(t, r) {
829
+ switch (t.type) {
830
+ case "number":
831
+ return t.value;
832
+ case "variable":
833
+ if (t.name in r)
834
+ return r[t.name];
835
+ throw new Error(`Unknown variable: ${t.name}`);
836
+ case "unary":
837
+ return t.op === "-" ? -this.evaluate(t.arg, r) : this.evaluate(t.arg, r);
838
+ case "binary": {
839
+ const a = this.evaluate(t.left, r), o = this.evaluate(t.right, r);
840
+ switch (t.op) {
841
+ case "+":
842
+ return a + o;
843
+ case "-":
844
+ return a - o;
845
+ case "*":
846
+ return a * o;
847
+ case "/":
848
+ return a / o;
849
+ case "^":
850
+ return Math.pow(a, o);
851
+ default:
852
+ return 0;
853
+ }
854
+ }
855
+ case "call": {
856
+ const a = mathFunctions[t.name];
857
+ if (!a)
858
+ throw new Error(`Unknown function: ${t.name}`);
859
+ const o = t.args.map((n) => this.evaluate(n, r));
860
+ return a(...o);
861
+ }
862
+ default:
863
+ return 0;
864
+ }
865
+ }
866
+ }
867
+ class GraphService {
868
+ constructor(t = {}) {
869
+ M(this, "plots", /* @__PURE__ */ new Map());
870
+ M(this, "parser", new ExpressionParser());
871
+ M(this, "config");
872
+ this.config = {
873
+ defaultResolution: t.defaultResolution ?? 200,
874
+ maxResolution: t.maxResolution ?? 1e3
875
+ };
876
+ }
877
+ /** Add a plot */
878
+ addPlot(t) {
879
+ const r = {
880
+ id: this.generateId(),
881
+ type: t.type,
882
+ expression: t.expression,
883
+ expressionY: t.expressionY,
884
+ expressionZ: t.expressionZ,
885
+ label: t.label,
886
+ color: t.color ?? { r: 66, g: 133, b: 244 },
887
+ lineWidth: t.lineWidth ?? 2,
888
+ visible: t.visible ?? !0,
889
+ parameterRange: t.parameterRange ?? { min: -Math.PI, max: Math.PI },
890
+ parameterRange2: t.parameterRange2 ?? { min: -Math.PI, max: Math.PI },
891
+ resolution: t.resolution ?? this.config.defaultResolution
892
+ };
893
+ return this.plots.set(r.id, r), r;
894
+ }
895
+ /** Update a plot */
896
+ updatePlot(t, r) {
897
+ const a = this.plots.get(t);
898
+ if (!a)
899
+ throw new Error(`Plot not found: ${t}`);
900
+ const o = { ...a, ...r, id: a.id };
901
+ return this.plots.set(t, o), o;
902
+ }
903
+ /** Remove a plot */
904
+ removePlot(t) {
905
+ this.plots.delete(t);
906
+ }
907
+ /** Get all plots */
908
+ getPlots() {
909
+ return Array.from(this.plots.values());
910
+ }
911
+ /** Get plot by ID */
912
+ getPlot(t) {
913
+ return this.plots.get(t);
914
+ }
915
+ /** Compute 2D function points */
916
+ compute2DFunction(t, r, a, o) {
917
+ const n = this.parser.parse(t), s = [], c = (r.max - r.min) / a;
918
+ for (let l = 0; l <= a; l++) {
919
+ const i = r.min + l * c;
920
+ try {
921
+ const d = n({ x: i, ...o });
922
+ Number.isFinite(d) && s.push({ x: i, y: d });
923
+ } catch {
924
+ }
925
+ }
926
+ return s;
927
+ }
928
+ /** Compute 2D parametric curve */
929
+ compute2DParametric(t, r, a, o, n) {
930
+ const s = this.parser.parse(t), c = this.parser.parse(r), l = [], i = (a.max - a.min) / o;
931
+ for (let d = 0; d <= o; d++) {
932
+ const u = a.min + d * i;
933
+ try {
934
+ const h = s({ t: u, ...n }), b = c({ t: u, ...n });
935
+ Number.isFinite(h) && Number.isFinite(b) && l.push({ x: h, y: b });
936
+ } catch {
937
+ }
938
+ }
939
+ return l;
940
+ }
941
+ /** Compute 2D polar curve */
942
+ compute2DPolar(t, r, a, o) {
943
+ const n = this.parser.parse(t), s = [], c = (r.max - r.min) / a;
944
+ for (let l = 0; l <= a; l++) {
945
+ const i = r.min + l * c;
946
+ try {
947
+ const d = n({ theta: i, t: i, ...o });
948
+ if (Number.isFinite(d)) {
949
+ const u = d * Math.cos(i), h = d * Math.sin(i);
950
+ s.push({ x: u, y: h });
951
+ }
952
+ } catch {
953
+ }
954
+ }
955
+ return s;
956
+ }
957
+ /** Compute 3D surface points */
958
+ compute3DSurface(t, r, a, o, n) {
959
+ const s = this.parser.parse(t), c = [], l = (r.max - r.min) / o, i = (a.max - a.min) / o;
960
+ for (let d = 0; d <= o; d++) {
961
+ const u = [], h = r.min + d * l;
962
+ for (let b = 0; b <= o; b++) {
963
+ const y = a.min + b * i;
964
+ try {
965
+ const g = s({ x: h, y, ...n });
966
+ Number.isFinite(g) ? u.push({ x: h, y, z: g }) : u.push({ x: h, y, z: 0 });
967
+ } catch {
968
+ u.push({ x: h, y, z: 0 });
969
+ }
970
+ }
971
+ c.push(u);
972
+ }
973
+ return c;
974
+ }
975
+ /** Export plot data as SVG */
976
+ exportSVG(t, r, a, o) {
977
+ const s = a - 80, c = o - 40 * 2, l = (u) => 40 + (u - r.xRange.min) / (r.xRange.max - r.xRange.min) * s, i = (u) => o - 40 - (u - r.yRange.min) / (r.yRange.max - r.yRange.min) * c, d = [
978
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${o}">`,
979
+ `<rect width="100%" height="100%" fill="rgb(${r.backgroundColor.r},${r.backgroundColor.g},${r.backgroundColor.b})"/>`
980
+ ];
981
+ if (r.showGrid) {
982
+ d.push('<g stroke="#ddd" stroke-width="0.5">');
983
+ for (let u = Math.ceil(r.xRange.min); u <= r.xRange.max; u++) {
984
+ const h = l(u);
985
+ d.push(`<line x1="${h}" y1="40" x2="${h}" y2="${o - 40}"/>`);
986
+ }
987
+ for (let u = Math.ceil(r.yRange.min); u <= r.yRange.max; u++) {
988
+ const h = i(u);
989
+ d.push(`<line x1="40" y1="${h}" x2="${a - 40}" y2="${h}"/>`);
990
+ }
991
+ d.push("</g>");
992
+ }
993
+ if (r.showAxes) {
994
+ d.push('<g stroke="#333" stroke-width="1">');
995
+ const u = i(0), h = l(0);
996
+ d.push(`<line x1="40" y1="${u}" x2="${a - 40}" y2="${u}"/>`), d.push(`<line x1="${h}" y1="40" x2="${h}" y2="${o - 40}"/>`), d.push("</g>");
997
+ }
998
+ for (const u of t.filter((h) => h.visible))
999
+ if (u.type === "2d-function") {
1000
+ const h = this.compute2DFunction(u.expression, r.xRange, u.resolution || 200);
1001
+ if (h.length > 0) {
1002
+ const b = h.map((y, g) => `${g === 0 ? "M" : "L"}${l(y.x)},${i(y.y)}`).join(" ");
1003
+ d.push(
1004
+ `<path d="${b}" fill="none" stroke="rgb(${u.color.r},${u.color.g},${u.color.b})" stroke-width="${u.lineWidth}"/>`
1005
+ );
1006
+ }
1007
+ }
1008
+ return r.showLabels && (d.push(
1009
+ `<text x="${a / 2}" y="${o - 10}" text-anchor="middle" font-size="12">x</text>`
1010
+ ), d.push(
1011
+ `<text x="10" y="${o / 2}" text-anchor="middle" font-size="12" transform="rotate(-90,10,${o / 2})">y</text>`
1012
+ )), d.push("</svg>"), d.join(`
1013
+ `);
1014
+ }
1015
+ /** Export as PNG (data URL) */
1016
+ async exportPNG(t, r, a, o) {
1017
+ const n = this.exportSVG(t, r, a, o);
1018
+ return new Promise((s, c) => {
1019
+ const l = new Image();
1020
+ l.onload = () => {
1021
+ const i = document.createElement("canvas");
1022
+ i.width = a, i.height = o;
1023
+ const d = i.getContext("2d");
1024
+ if (!d) {
1025
+ c(new Error("Could not get canvas context"));
1026
+ return;
1027
+ }
1028
+ d.drawImage(l, 0, 0), s(i.toDataURL("image/png"));
1029
+ }, l.onerror = c, l.src = "data:image/svg+xml;base64," + btoa(n);
1030
+ });
1031
+ }
1032
+ generateId() {
1033
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
1034
+ }
1035
+ }
1036
+ function createGraphService(e) {
1037
+ return new GraphService(e);
1038
+ }
1039
+ const FUNCTION_PRESETS = [
1040
+ // Basic
1041
+ { name: "Linear", expression: "x", type: "2d-function", category: "basic" },
1042
+ { name: "Quadratic", expression: "x^2", type: "2d-function", category: "basic" },
1043
+ { name: "Cubic", expression: "x^3", type: "2d-function", category: "basic" },
1044
+ { name: "Square root", expression: "sqrt(x)", type: "2d-function", category: "basic" },
1045
+ { name: "Absolute", expression: "abs(x)", type: "2d-function", category: "basic" },
1046
+ { name: "Reciprocal", expression: "1/x", type: "2d-function", category: "basic" },
1047
+ // Trigonometric
1048
+ { name: "Sine", expression: "sin(x)", type: "2d-function", category: "trigonometric" },
1049
+ { name: "Cosine", expression: "cos(x)", type: "2d-function", category: "trigonometric" },
1050
+ { name: "Tangent", expression: "tan(x)", type: "2d-function", category: "trigonometric" },
1051
+ { name: "Sine wave", expression: "sin(2*x)", type: "2d-function", category: "trigonometric" },
1052
+ {
1053
+ name: "Damped oscillation",
1054
+ expression: "exp(-x/5)*sin(x*3)",
1055
+ type: "2d-function",
1056
+ category: "trigonometric"
1057
+ },
1058
+ // Exponential/Logarithmic
1059
+ { name: "Exponential", expression: "exp(x)", type: "2d-function", category: "exponential" },
1060
+ { name: "Natural log", expression: "ln(x)", type: "2d-function", category: "exponential" },
1061
+ { name: "Gaussian", expression: "exp(-x^2)", type: "2d-function", category: "exponential" },
1062
+ { name: "Sigmoid", expression: "1/(1+exp(-x))", type: "2d-function", category: "exponential" },
1063
+ // Parametric
1064
+ {
1065
+ name: "Circle",
1066
+ expression: "cos(t)",
1067
+ expressionY: "sin(t)",
1068
+ type: "2d-parametric",
1069
+ category: "parametric"
1070
+ },
1071
+ {
1072
+ name: "Ellipse",
1073
+ expression: "2*cos(t)",
1074
+ expressionY: "sin(t)",
1075
+ type: "2d-parametric",
1076
+ category: "parametric"
1077
+ },
1078
+ {
1079
+ name: "Lissajous",
1080
+ expression: "sin(3*t)",
1081
+ expressionY: "sin(2*t)",
1082
+ type: "2d-parametric",
1083
+ category: "parametric"
1084
+ },
1085
+ {
1086
+ name: "Spiral",
1087
+ expression: "t*cos(t)",
1088
+ expressionY: "t*sin(t)",
1089
+ type: "2d-parametric",
1090
+ category: "parametric"
1091
+ },
1092
+ {
1093
+ name: "Cardioid",
1094
+ expression: "(1-cos(t))*cos(t)",
1095
+ expressionY: "(1-cos(t))*sin(t)",
1096
+ type: "2d-parametric",
1097
+ category: "parametric"
1098
+ },
1099
+ {
1100
+ name: "Rose curve",
1101
+ expression: "cos(3*t)*cos(t)",
1102
+ expressionY: "cos(3*t)*sin(t)",
1103
+ type: "2d-parametric",
1104
+ category: "parametric"
1105
+ },
1106
+ // Polar
1107
+ { name: "Polar rose 3", expression: "cos(3*theta)", type: "2d-polar", category: "polar" },
1108
+ { name: "Polar rose 5", expression: "cos(5*theta)", type: "2d-polar", category: "polar" },
1109
+ { name: "Archimedean spiral", expression: "theta", type: "2d-polar", category: "polar" },
1110
+ { name: "Logarithmic spiral", expression: "exp(theta/10)", type: "2d-polar", category: "polar" },
1111
+ // 3D Surfaces
1112
+ { name: "Paraboloid", expression: "x^2 + y^2", type: "3d-surface", category: "3d" },
1113
+ { name: "Saddle", expression: "x^2 - y^2", type: "3d-surface", category: "3d" },
1114
+ { name: "Ripple", expression: "sin(sqrt(x^2 + y^2))", type: "3d-surface", category: "3d" },
1115
+ { name: "Torus slice", expression: "cos(x)*sin(y)", type: "3d-surface", category: "3d" },
1116
+ {
1117
+ name: "Peaks",
1118
+ expression: "3*(1-x)^2*exp(-x^2-(y+1)^2) - 10*(x/5-x^3-y^5)*exp(-x^2-y^2) - 1/3*exp(-(x+1)^2-y^2)",
1119
+ type: "3d-surface",
1120
+ category: "3d"
1121
+ }
1122
+ ], GraphContext = createContext(null);
1123
+ function useGraph() {
1124
+ const e = useContext(GraphContext);
1125
+ if (!e)
1126
+ throw new Error("useGraph must be used within GraphProvider");
1127
+ return e;
1128
+ }
1129
+ const styles$2 = {
1130
+ container: {
1131
+ display: "flex",
1132
+ height: "100%",
1133
+ fontFamily: "'Inter', sans-serif",
1134
+ fontSize: "14px"
1135
+ },
1136
+ sidebar: {
1137
+ width: "280px",
1138
+ borderRight: "1px solid #e0e0e0",
1139
+ display: "flex",
1140
+ flexDirection: "column",
1141
+ overflow: "hidden"
1142
+ },
1143
+ plotList: {
1144
+ flex: 1,
1145
+ overflow: "auto",
1146
+ padding: "8px"
1147
+ },
1148
+ main: {
1149
+ flex: 1,
1150
+ display: "flex",
1151
+ flexDirection: "column",
1152
+ backgroundColor: "#fff"
1153
+ },
1154
+ canvas: {
1155
+ flex: 1,
1156
+ backgroundColor: "#fff"
1157
+ },
1158
+ toolbar: {
1159
+ display: "flex",
1160
+ gap: "8px",
1161
+ padding: "8px",
1162
+ borderBottom: "1px solid #e0e0e0",
1163
+ alignItems: "center"
1164
+ },
1165
+ button: {
1166
+ padding: "6px 12px",
1167
+ backgroundColor: "#1976d2",
1168
+ color: "white",
1169
+ border: "none",
1170
+ borderRadius: "4px",
1171
+ cursor: "pointer",
1172
+ fontSize: "13px"
1173
+ },
1174
+ input: {
1175
+ padding: "6px 8px",
1176
+ border: "1px solid #ddd",
1177
+ borderRadius: "4px",
1178
+ fontSize: "13px"
1179
+ },
1180
+ plotItem: {
1181
+ padding: "8px",
1182
+ marginBottom: "8px",
1183
+ border: "1px solid #e0e0e0",
1184
+ borderRadius: "4px",
1185
+ backgroundColor: "#fafafa"
1186
+ }
1187
+ };
1188
+ function NiceGraphPlotter({
1189
+ service: e,
1190
+ width: t = 800,
1191
+ height: r = 600,
1192
+ className: a,
1193
+ style: o
1194
+ }) {
1195
+ const [n, s] = useState([]), [c, l] = useState({
1196
+ xRange: { min: -10, max: 10 },
1197
+ yRange: { min: -10, max: 10 },
1198
+ zRange: { min: -5, max: 5 },
1199
+ showGrid: !0,
1200
+ showAxes: !0,
1201
+ showLabels: !0,
1202
+ backgroundColor: { r: 255, g: 255, b: 255 },
1203
+ cameraRotationX: 30,
1204
+ cameraRotationY: 45,
1205
+ cameraDistance: 5
1206
+ }), [i, d] = useState({
1207
+ isPlaying: !1,
1208
+ parameter: "a",
1209
+ currentValue: 0,
1210
+ minValue: -5,
1211
+ maxValue: 5,
1212
+ speed: 1
1213
+ }), u = useCallback(() => {
1214
+ s(e.getPlots());
1215
+ }, [e]), h = useCallback((x) => {
1216
+ l((w) => ({ ...w, ...x }));
1217
+ }, []), b = useCallback((x) => {
1218
+ d((w) => ({ ...w, ...x }));
1219
+ }, []), y = useCallback(
1220
+ (x) => {
1221
+ e.addPlot(x), u();
1222
+ },
1223
+ [e, u]
1224
+ ), g = useCallback(
1225
+ (x) => {
1226
+ e.removePlot(x), u();
1227
+ },
1228
+ [e, u]
1229
+ ), m = useCallback(
1230
+ (x, w) => {
1231
+ e.updatePlot(x, w), u();
1232
+ },
1233
+ [e, u]
1234
+ ), p = {
1235
+ service: e,
1236
+ plots: n,
1237
+ view: c,
1238
+ setView: h,
1239
+ addPlot: y,
1240
+ removePlot: g,
1241
+ updatePlot: m,
1242
+ animation: i,
1243
+ setAnimation: b,
1244
+ refresh: u
1245
+ };
1246
+ return /* @__PURE__ */ jsx(GraphContext.Provider, { value: p, children: /* @__PURE__ */ jsxs("div", { className: a, style: { ...styles$2.container, ...o }, children: [
1247
+ /* @__PURE__ */ jsxs("div", { style: styles$2.sidebar, children: [
1248
+ /* @__PURE__ */ jsx(PlotControls, {}),
1249
+ /* @__PURE__ */ jsx(PlotList, {})
1250
+ ] }),
1251
+ /* @__PURE__ */ jsxs("div", { style: styles$2.main, children: [
1252
+ /* @__PURE__ */ jsx(GraphToolbar, { width: t, height: r }),
1253
+ /* @__PURE__ */ jsx(Canvas2D, { width: t, height: r })
1254
+ ] })
1255
+ ] }) });
1256
+ }
1257
+ function PlotControls() {
1258
+ const { addPlot: e } = useGraph(), [t, r] = useState("sin(x)"), [a, o] = useState("2d-function"), [n, s] = useState("cos(x)"), c = () => {
1259
+ e({
1260
+ type: a,
1261
+ expression: t,
1262
+ expressionY: a === "2d-parametric" ? n : void 0,
1263
+ color: {
1264
+ r: Math.floor(Math.random() * 200),
1265
+ g: Math.floor(Math.random() * 200),
1266
+ b: Math.floor(Math.random() * 200)
1267
+ }
1268
+ });
1269
+ };
1270
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", borderBottom: "1px solid #e0e0e0" }, children: [
1271
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px" }, children: /* @__PURE__ */ jsxs(
1272
+ "select",
1273
+ {
1274
+ value: a,
1275
+ onChange: (l) => o(l.target.value),
1276
+ style: { ...styles$2.input, width: "100%" },
1277
+ children: [
1278
+ /* @__PURE__ */ jsx("option", { value: "2d-function", children: "y = f(x)" }),
1279
+ /* @__PURE__ */ jsx("option", { value: "2d-parametric", children: "Parametric (x(t), y(t))" }),
1280
+ /* @__PURE__ */ jsx("option", { value: "2d-polar", children: "Polar r = f(θ)" }),
1281
+ /* @__PURE__ */ jsx("option", { value: "3d-surface", children: "3D Surface z = f(x,y)" })
1282
+ ]
1283
+ }
1284
+ ) }),
1285
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px" }, children: /* @__PURE__ */ jsx(
1286
+ "input",
1287
+ {
1288
+ type: "text",
1289
+ value: t,
1290
+ onChange: (l) => r(l.target.value),
1291
+ placeholder: a === "2d-parametric" ? "x(t) = ..." : "Expression...",
1292
+ style: { ...styles$2.input, width: "100%" }
1293
+ }
1294
+ ) }),
1295
+ a === "2d-parametric" && /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px" }, children: /* @__PURE__ */ jsx(
1296
+ "input",
1297
+ {
1298
+ type: "text",
1299
+ value: n,
1300
+ onChange: (l) => s(l.target.value),
1301
+ placeholder: "y(t) = ...",
1302
+ style: { ...styles$2.input, width: "100%" }
1303
+ }
1304
+ ) }),
1305
+ /* @__PURE__ */ jsx("button", { onClick: c, style: { ...styles$2.button, width: "100%" }, children: "+ Add Plot" }),
1306
+ /* @__PURE__ */ jsxs(
1307
+ "select",
1308
+ {
1309
+ onChange: (l) => {
1310
+ const i = FUNCTION_PRESETS.find((d) => d.name === l.target.value);
1311
+ i && e({
1312
+ type: i.type,
1313
+ expression: i.expression,
1314
+ expressionY: i.expressionY,
1315
+ label: i.name,
1316
+ color: {
1317
+ r: Math.floor(Math.random() * 200),
1318
+ g: Math.floor(Math.random() * 200),
1319
+ b: Math.floor(Math.random() * 200)
1320
+ }
1321
+ });
1322
+ },
1323
+ style: { ...styles$2.input, width: "100%", marginTop: "8px" },
1324
+ value: "",
1325
+ children: [
1326
+ /* @__PURE__ */ jsx("option", { value: "", disabled: !0, children: "Quick add preset..." }),
1327
+ ["basic", "trigonometric", "exponential", "parametric", "polar", "3d"].map((l) => /* @__PURE__ */ jsx("optgroup", { label: l.charAt(0).toUpperCase() + l.slice(1), children: FUNCTION_PRESETS.filter((i) => i.category === l).map((i) => /* @__PURE__ */ jsxs("option", { value: i.name, children: [
1328
+ i.name,
1329
+ ": ",
1330
+ i.expression
1331
+ ] }, i.name)) }, l))
1332
+ ]
1333
+ }
1334
+ )
1335
+ ] });
1336
+ }
1337
+ function PlotList() {
1338
+ const { plots: e, removePlot: t, updatePlot: r } = useGraph();
1339
+ return /* @__PURE__ */ jsxs("div", { style: styles$2.plotList, children: [
1340
+ e.length === 0 && /* @__PURE__ */ jsx("div", { style: { color: "#666", textAlign: "center", padding: "16px" }, children: "No plots added yet" }),
1341
+ e.map((a) => /* @__PURE__ */ jsxs("div", { style: styles$2.plotItem, children: [
1342
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "8px" }, children: [
1343
+ /* @__PURE__ */ jsx(
1344
+ "input",
1345
+ {
1346
+ type: "checkbox",
1347
+ checked: a.visible,
1348
+ onChange: (o) => r(a.id, { visible: o.target.checked })
1349
+ }
1350
+ ),
1351
+ /* @__PURE__ */ jsx(
1352
+ "div",
1353
+ {
1354
+ style: {
1355
+ width: "16px",
1356
+ height: "16px",
1357
+ borderRadius: "3px",
1358
+ backgroundColor: `rgb(${a.color.r},${a.color.g},${a.color.b})`
1359
+ }
1360
+ }
1361
+ ),
1362
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, fontWeight: 500 }, children: a.label || a.expression }),
1363
+ /* @__PURE__ */ jsx(
1364
+ "button",
1365
+ {
1366
+ onClick: () => t(a.id),
1367
+ style: {
1368
+ padding: "2px 6px",
1369
+ backgroundColor: "#f44336",
1370
+ color: "white",
1371
+ border: "none",
1372
+ borderRadius: "3px",
1373
+ cursor: "pointer",
1374
+ fontSize: "12px"
1375
+ },
1376
+ children: "×"
1377
+ }
1378
+ )
1379
+ ] }),
1380
+ /* @__PURE__ */ jsx("div", { style: { fontSize: "12px", color: "#666", fontFamily: "monospace" }, children: a.type === "2d-parametric" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1381
+ "x(t) = ",
1382
+ a.expression,
1383
+ /* @__PURE__ */ jsx("br", {}),
1384
+ "y(t) = ",
1385
+ a.expressionY
1386
+ ] }) : a.expression })
1387
+ ] }, a.id))
1388
+ ] });
1389
+ }
1390
+ function GraphToolbar({ width: e, height: t }) {
1391
+ const { service: r, plots: a, view: o, setView: n } = useGraph(), s = () => {
1392
+ const l = r.exportSVG(a, o, e, t), i = new Blob([l], { type: "image/svg+xml" }), d = URL.createObjectURL(i), u = document.createElement("a");
1393
+ u.href = d, u.download = "graph.svg", u.click(), URL.revokeObjectURL(d);
1394
+ }, c = async () => {
1395
+ const l = await r.exportPNG(a, o, e, t), i = document.createElement("a");
1396
+ i.href = l, i.download = "graph.png", i.click();
1397
+ };
1398
+ return /* @__PURE__ */ jsxs("div", { style: styles$2.toolbar, children: [
1399
+ /* @__PURE__ */ jsxs("label", { style: { fontSize: "12px" }, children: [
1400
+ "X: [",
1401
+ " ",
1402
+ /* @__PURE__ */ jsx(
1403
+ "input",
1404
+ {
1405
+ type: "number",
1406
+ value: o.xRange.min,
1407
+ onChange: (l) => n({ xRange: { ...o.xRange, min: Number(l.target.value) } }),
1408
+ style: { ...styles$2.input, width: "50px" }
1409
+ }
1410
+ ),
1411
+ ",",
1412
+ " ",
1413
+ /* @__PURE__ */ jsx(
1414
+ "input",
1415
+ {
1416
+ type: "number",
1417
+ value: o.xRange.max,
1418
+ onChange: (l) => n({ xRange: { ...o.xRange, max: Number(l.target.value) } }),
1419
+ style: { ...styles$2.input, width: "50px" }
1420
+ }
1421
+ ),
1422
+ "]"
1423
+ ] }),
1424
+ /* @__PURE__ */ jsxs("label", { style: { fontSize: "12px" }, children: [
1425
+ "Y: [",
1426
+ " ",
1427
+ /* @__PURE__ */ jsx(
1428
+ "input",
1429
+ {
1430
+ type: "number",
1431
+ value: o.yRange.min,
1432
+ onChange: (l) => n({ yRange: { ...o.yRange, min: Number(l.target.value) } }),
1433
+ style: { ...styles$2.input, width: "50px" }
1434
+ }
1435
+ ),
1436
+ ",",
1437
+ " ",
1438
+ /* @__PURE__ */ jsx(
1439
+ "input",
1440
+ {
1441
+ type: "number",
1442
+ value: o.yRange.max,
1443
+ onChange: (l) => n({ yRange: { ...o.yRange, max: Number(l.target.value) } }),
1444
+ style: { ...styles$2.input, width: "50px" }
1445
+ }
1446
+ ),
1447
+ "]"
1448
+ ] }),
1449
+ /* @__PURE__ */ jsxs("label", { style: { fontSize: "12px" }, children: [
1450
+ /* @__PURE__ */ jsx(
1451
+ "input",
1452
+ {
1453
+ type: "checkbox",
1454
+ checked: o.showGrid,
1455
+ onChange: (l) => n({ showGrid: l.target.checked })
1456
+ }
1457
+ ),
1458
+ "Grid"
1459
+ ] }),
1460
+ /* @__PURE__ */ jsxs("label", { style: { fontSize: "12px" }, children: [
1461
+ /* @__PURE__ */ jsx(
1462
+ "input",
1463
+ {
1464
+ type: "checkbox",
1465
+ checked: o.showAxes,
1466
+ onChange: (l) => n({ showAxes: l.target.checked })
1467
+ }
1468
+ ),
1469
+ "Axes"
1470
+ ] }),
1471
+ /* @__PURE__ */ jsx("div", { style: { flex: 1 } }),
1472
+ /* @__PURE__ */ jsx("button", { onClick: s, style: { ...styles$2.button, backgroundColor: "#4caf50" }, children: "📥 SVG" }),
1473
+ /* @__PURE__ */ jsx("button", { onClick: c, style: { ...styles$2.button, backgroundColor: "#ff9800" }, children: "📥 PNG" })
1474
+ ] });
1475
+ }
1476
+ function Canvas2D({ width: e, height: t }) {
1477
+ const r = useRef(null), { service: a, plots: o, view: n, animation: s } = useGraph(), c = 40;
1478
+ return useEffect(() => {
1479
+ const l = r.current, i = l == null ? void 0 : l.getContext("2d");
1480
+ if (!l || !i)
1481
+ return;
1482
+ i.fillStyle = `rgb(${n.backgroundColor.r},${n.backgroundColor.g},${n.backgroundColor.b})`, i.fillRect(0, 0, e, t);
1483
+ const d = e - c * 2, u = t - c * 2, h = (g) => c + (g - n.xRange.min) / (n.xRange.max - n.xRange.min) * d, b = (g) => t - c - (g - n.yRange.min) / (n.yRange.max - n.yRange.min) * u;
1484
+ if (n.showGrid) {
1485
+ i.strokeStyle = "#e0e0e0", i.lineWidth = 0.5;
1486
+ for (let g = Math.ceil(n.xRange.min); g <= n.xRange.max; g++) {
1487
+ const m = h(g);
1488
+ i.beginPath(), i.moveTo(m, c), i.lineTo(m, t - c), i.stroke();
1489
+ }
1490
+ for (let g = Math.ceil(n.yRange.min); g <= n.yRange.max; g++) {
1491
+ const m = b(g);
1492
+ i.beginPath(), i.moveTo(c, m), i.lineTo(e - c, m), i.stroke();
1493
+ }
1494
+ }
1495
+ if (n.showAxes) {
1496
+ i.strokeStyle = "#333", i.lineWidth = 1;
1497
+ const g = b(0);
1498
+ i.beginPath(), i.moveTo(c, g), i.lineTo(e - c, g), i.stroke();
1499
+ const m = h(0);
1500
+ if (i.beginPath(), i.moveTo(m, c), i.lineTo(m, t - c), i.stroke(), n.showLabels) {
1501
+ i.fillStyle = "#333", i.font = "12px sans-serif", i.textAlign = "center", i.fillText("x", e - c + 15, g + 4), i.fillText("y", m, c - 10), i.font = "10px sans-serif";
1502
+ for (let p = Math.ceil(n.xRange.min); p <= n.xRange.max; p++)
1503
+ p !== 0 && i.fillText(String(p), h(p), g + 15);
1504
+ for (let p = Math.ceil(n.yRange.min); p <= n.yRange.max; p++)
1505
+ p !== 0 && (i.textAlign = "right", i.fillText(String(p), m - 5, b(p) + 4));
1506
+ }
1507
+ }
1508
+ const y = s.isPlaying ? { [s.parameter]: s.currentValue } : {};
1509
+ for (const g of o.filter((m) => m.visible)) {
1510
+ const m = `rgb(${g.color.r},${g.color.g},${g.color.b})`;
1511
+ i.strokeStyle = m, i.lineWidth = g.lineWidth || 2;
1512
+ let p = [];
1513
+ switch (g.type) {
1514
+ case "2d-function":
1515
+ p = a.compute2DFunction(
1516
+ g.expression,
1517
+ n.xRange,
1518
+ g.resolution || 200,
1519
+ y
1520
+ );
1521
+ break;
1522
+ case "2d-parametric":
1523
+ p = a.compute2DParametric(
1524
+ g.expression,
1525
+ g.expressionY || "sin(t)",
1526
+ g.parameterRange || { min: 0, max: 2 * Math.PI },
1527
+ g.resolution || 200,
1528
+ y
1529
+ );
1530
+ break;
1531
+ case "2d-polar":
1532
+ p = a.compute2DPolar(
1533
+ g.expression,
1534
+ g.parameterRange || { min: 0, max: 2 * Math.PI },
1535
+ g.resolution || 200,
1536
+ y
1537
+ );
1538
+ break;
1539
+ }
1540
+ if (p.length > 0) {
1541
+ i.beginPath();
1542
+ let x = !1;
1543
+ for (const w of p) {
1544
+ const k = h(w.x), f = b(w.y);
1545
+ if (f < 0 || f > t) {
1546
+ x = !1;
1547
+ continue;
1548
+ }
1549
+ x ? i.lineTo(k, f) : (i.moveTo(k, f), x = !0);
1550
+ }
1551
+ i.stroke();
1552
+ }
1553
+ }
1554
+ }, [o, n, s, a, e, t]), /* @__PURE__ */ jsx("canvas", { ref: r, width: e, height: t, style: styles$2.canvas });
1555
+ }
1556
+ const UNITS = [
1557
+ // Length
1558
+ { name: "Meter", symbol: "m", category: "Length", toBase: (e) => e, fromBase: (e) => e },
1559
+ {
1560
+ name: "Kilometer",
1561
+ symbol: "km",
1562
+ category: "Length",
1563
+ toBase: (e) => e * 1e3,
1564
+ fromBase: (e) => e / 1e3
1565
+ },
1566
+ {
1567
+ name: "Centimeter",
1568
+ symbol: "cm",
1569
+ category: "Length",
1570
+ toBase: (e) => e / 100,
1571
+ fromBase: (e) => e * 100
1572
+ },
1573
+ {
1574
+ name: "Millimeter",
1575
+ symbol: "mm",
1576
+ category: "Length",
1577
+ toBase: (e) => e / 1e3,
1578
+ fromBase: (e) => e * 1e3
1579
+ },
1580
+ {
1581
+ name: "Mile",
1582
+ symbol: "mi",
1583
+ category: "Length",
1584
+ toBase: (e) => e * 1609.344,
1585
+ fromBase: (e) => e / 1609.344
1586
+ },
1587
+ {
1588
+ name: "Yard",
1589
+ symbol: "yd",
1590
+ category: "Length",
1591
+ toBase: (e) => e * 0.9144,
1592
+ fromBase: (e) => e / 0.9144
1593
+ },
1594
+ {
1595
+ name: "Foot",
1596
+ symbol: "ft",
1597
+ category: "Length",
1598
+ toBase: (e) => e * 0.3048,
1599
+ fromBase: (e) => e / 0.3048
1600
+ },
1601
+ {
1602
+ name: "Inch",
1603
+ symbol: "in",
1604
+ category: "Length",
1605
+ toBase: (e) => e * 0.0254,
1606
+ fromBase: (e) => e / 0.0254
1607
+ },
1608
+ // Mass
1609
+ { name: "Kilogram", symbol: "kg", category: "Mass", toBase: (e) => e, fromBase: (e) => e },
1610
+ {
1611
+ name: "Gram",
1612
+ symbol: "g",
1613
+ category: "Mass",
1614
+ toBase: (e) => e / 1e3,
1615
+ fromBase: (e) => e * 1e3
1616
+ },
1617
+ {
1618
+ name: "Milligram",
1619
+ symbol: "mg",
1620
+ category: "Mass",
1621
+ toBase: (e) => e / 1e6,
1622
+ fromBase: (e) => e * 1e6
1623
+ },
1624
+ {
1625
+ name: "Pound",
1626
+ symbol: "lb",
1627
+ category: "Mass",
1628
+ toBase: (e) => e * 0.453592,
1629
+ fromBase: (e) => e / 0.453592
1630
+ },
1631
+ {
1632
+ name: "Ounce",
1633
+ symbol: "oz",
1634
+ category: "Mass",
1635
+ toBase: (e) => e * 0.0283495,
1636
+ fromBase: (e) => e / 0.0283495
1637
+ },
1638
+ {
1639
+ name: "Ton",
1640
+ symbol: "t",
1641
+ category: "Mass",
1642
+ toBase: (e) => e * 1e3,
1643
+ fromBase: (e) => e / 1e3
1644
+ },
1645
+ // Temperature
1646
+ { name: "Celsius", symbol: "°C", category: "Temperature", toBase: (e) => e, fromBase: (e) => e },
1647
+ {
1648
+ name: "Fahrenheit",
1649
+ symbol: "°F",
1650
+ category: "Temperature",
1651
+ toBase: (e) => (e - 32) * 5 / 9,
1652
+ fromBase: (e) => e * 9 / 5 + 32
1653
+ },
1654
+ {
1655
+ name: "Kelvin",
1656
+ symbol: "K",
1657
+ category: "Temperature",
1658
+ toBase: (e) => e - 273.15,
1659
+ fromBase: (e) => e + 273.15
1660
+ },
1661
+ // Time
1662
+ { name: "Second", symbol: "s", category: "Time", toBase: (e) => e, fromBase: (e) => e },
1663
+ {
1664
+ name: "Millisecond",
1665
+ symbol: "ms",
1666
+ category: "Time",
1667
+ toBase: (e) => e / 1e3,
1668
+ fromBase: (e) => e * 1e3
1669
+ },
1670
+ {
1671
+ name: "Minute",
1672
+ symbol: "min",
1673
+ category: "Time",
1674
+ toBase: (e) => e * 60,
1675
+ fromBase: (e) => e / 60
1676
+ },
1677
+ {
1678
+ name: "Hour",
1679
+ symbol: "hr",
1680
+ category: "Time",
1681
+ toBase: (e) => e * 3600,
1682
+ fromBase: (e) => e / 3600
1683
+ },
1684
+ {
1685
+ name: "Day",
1686
+ symbol: "d",
1687
+ category: "Time",
1688
+ toBase: (e) => e * 86400,
1689
+ fromBase: (e) => e / 86400
1690
+ },
1691
+ {
1692
+ name: "Week",
1693
+ symbol: "wk",
1694
+ category: "Time",
1695
+ toBase: (e) => e * 604800,
1696
+ fromBase: (e) => e / 604800
1697
+ },
1698
+ // Area
1699
+ { name: "Square meter", symbol: "m²", category: "Area", toBase: (e) => e, fromBase: (e) => e },
1700
+ {
1701
+ name: "Square kilometer",
1702
+ symbol: "km²",
1703
+ category: "Area",
1704
+ toBase: (e) => e * 1e6,
1705
+ fromBase: (e) => e / 1e6
1706
+ },
1707
+ {
1708
+ name: "Hectare",
1709
+ symbol: "ha",
1710
+ category: "Area",
1711
+ toBase: (e) => e * 1e4,
1712
+ fromBase: (e) => e / 1e4
1713
+ },
1714
+ {
1715
+ name: "Acre",
1716
+ symbol: "ac",
1717
+ category: "Area",
1718
+ toBase: (e) => e * 4046.86,
1719
+ fromBase: (e) => e / 4046.86
1720
+ },
1721
+ {
1722
+ name: "Square foot",
1723
+ symbol: "ft²",
1724
+ category: "Area",
1725
+ toBase: (e) => e * 0.092903,
1726
+ fromBase: (e) => e / 0.092903
1727
+ },
1728
+ // Volume
1729
+ { name: "Liter", symbol: "L", category: "Volume", toBase: (e) => e, fromBase: (e) => e },
1730
+ {
1731
+ name: "Milliliter",
1732
+ symbol: "mL",
1733
+ category: "Volume",
1734
+ toBase: (e) => e / 1e3,
1735
+ fromBase: (e) => e * 1e3
1736
+ },
1737
+ {
1738
+ name: "Cubic meter",
1739
+ symbol: "m³",
1740
+ category: "Volume",
1741
+ toBase: (e) => e * 1e3,
1742
+ fromBase: (e) => e / 1e3
1743
+ },
1744
+ {
1745
+ name: "Gallon (US)",
1746
+ symbol: "gal",
1747
+ category: "Volume",
1748
+ toBase: (e) => e * 3.78541,
1749
+ fromBase: (e) => e / 3.78541
1750
+ },
1751
+ {
1752
+ name: "Quart",
1753
+ symbol: "qt",
1754
+ category: "Volume",
1755
+ toBase: (e) => e * 0.946353,
1756
+ fromBase: (e) => e / 0.946353
1757
+ },
1758
+ {
1759
+ name: "Pint",
1760
+ symbol: "pt",
1761
+ category: "Volume",
1762
+ toBase: (e) => e * 0.473176,
1763
+ fromBase: (e) => e / 0.473176
1764
+ },
1765
+ {
1766
+ name: "Cup",
1767
+ symbol: "cup",
1768
+ category: "Volume",
1769
+ toBase: (e) => e * 0.236588,
1770
+ fromBase: (e) => e / 0.236588
1771
+ },
1772
+ // Speed
1773
+ { name: "Meters/second", symbol: "m/s", category: "Speed", toBase: (e) => e, fromBase: (e) => e },
1774
+ {
1775
+ name: "Kilometers/hour",
1776
+ symbol: "km/h",
1777
+ category: "Speed",
1778
+ toBase: (e) => e / 3.6,
1779
+ fromBase: (e) => e * 3.6
1780
+ },
1781
+ {
1782
+ name: "Miles/hour",
1783
+ symbol: "mph",
1784
+ category: "Speed",
1785
+ toBase: (e) => e * 0.44704,
1786
+ fromBase: (e) => e / 0.44704
1787
+ },
1788
+ {
1789
+ name: "Knots",
1790
+ symbol: "kn",
1791
+ category: "Speed",
1792
+ toBase: (e) => e * 0.514444,
1793
+ fromBase: (e) => e / 0.514444
1794
+ },
1795
+ // Data
1796
+ { name: "Byte", symbol: "B", category: "Data", toBase: (e) => e, fromBase: (e) => e },
1797
+ {
1798
+ name: "Kilobyte",
1799
+ symbol: "KB",
1800
+ category: "Data",
1801
+ toBase: (e) => e * 1024,
1802
+ fromBase: (e) => e / 1024
1803
+ },
1804
+ {
1805
+ name: "Megabyte",
1806
+ symbol: "MB",
1807
+ category: "Data",
1808
+ toBase: (e) => e * 1048576,
1809
+ fromBase: (e) => e / 1048576
1810
+ },
1811
+ {
1812
+ name: "Gigabyte",
1813
+ symbol: "GB",
1814
+ category: "Data",
1815
+ toBase: (e) => e * 1073741824,
1816
+ fromBase: (e) => e / 1073741824
1817
+ },
1818
+ {
1819
+ name: "Terabyte",
1820
+ symbol: "TB",
1821
+ category: "Data",
1822
+ toBase: (e) => e * 1099511627776,
1823
+ fromBase: (e) => e / 1099511627776
1824
+ },
1825
+ { name: "Bit", symbol: "bit", category: "Data", toBase: (e) => e / 8, fromBase: (e) => e * 8 }
1826
+ ], MatrixOps = {
1827
+ create(e, t, r = 0) {
1828
+ const a = [];
1829
+ for (let o = 0; o < e; o++)
1830
+ a.push(new Array(t).fill(r));
1831
+ return { rows: e, cols: t, data: a };
1832
+ },
1833
+ identity(e) {
1834
+ const t = this.create(e, e);
1835
+ for (let r = 0; r < e; r++)
1836
+ t.data[r][r] = 1;
1837
+ return t;
1838
+ },
1839
+ add(e, t) {
1840
+ if (e.rows !== t.rows || e.cols !== t.cols)
1841
+ throw new Error("Matrix dimensions must match for addition");
1842
+ const r = this.create(e.rows, e.cols);
1843
+ for (let a = 0; a < e.rows; a++)
1844
+ for (let o = 0; o < e.cols; o++)
1845
+ r.data[a][o] = e.data[a][o] + t.data[a][o];
1846
+ return r;
1847
+ },
1848
+ subtract(e, t) {
1849
+ if (e.rows !== t.rows || e.cols !== t.cols)
1850
+ throw new Error("Matrix dimensions must match for subtraction");
1851
+ const r = this.create(e.rows, e.cols);
1852
+ for (let a = 0; a < e.rows; a++)
1853
+ for (let o = 0; o < e.cols; o++)
1854
+ r.data[a][o] = e.data[a][o] - t.data[a][o];
1855
+ return r;
1856
+ },
1857
+ multiply(e, t) {
1858
+ if (e.cols !== t.rows)
1859
+ throw new Error("Matrix A columns must equal Matrix B rows for multiplication");
1860
+ const r = this.create(e.rows, t.cols);
1861
+ for (let a = 0; a < e.rows; a++)
1862
+ for (let o = 0; o < t.cols; o++) {
1863
+ let n = 0;
1864
+ for (let s = 0; s < e.cols; s++)
1865
+ n += e.data[a][s] * t.data[s][o];
1866
+ r.data[a][o] = n;
1867
+ }
1868
+ return r;
1869
+ },
1870
+ scalar(e, t) {
1871
+ const r = this.create(e.rows, e.cols);
1872
+ for (let a = 0; a < e.rows; a++)
1873
+ for (let o = 0; o < e.cols; o++)
1874
+ r.data[a][o] = e.data[a][o] * t;
1875
+ return r;
1876
+ },
1877
+ transpose(e) {
1878
+ const t = this.create(e.cols, e.rows);
1879
+ for (let r = 0; r < e.rows; r++)
1880
+ for (let a = 0; a < e.cols; a++)
1881
+ t.data[a][r] = e.data[r][a];
1882
+ return t;
1883
+ },
1884
+ determinant(e) {
1885
+ if (e.rows !== e.cols)
1886
+ throw new Error("Determinant requires square matrix");
1887
+ if (e.rows === 1)
1888
+ return e.data[0][0];
1889
+ if (e.rows === 2)
1890
+ return e.data[0][0] * e.data[1][1] - e.data[0][1] * e.data[1][0];
1891
+ let t = 0;
1892
+ for (let r = 0; r < e.cols; r++)
1893
+ t += Math.pow(-1, r) * e.data[0][r] * this.determinant(this.minor(e, 0, r));
1894
+ return t;
1895
+ },
1896
+ minor(e, t, r) {
1897
+ const a = this.create(e.rows - 1, e.cols - 1);
1898
+ let o = 0;
1899
+ for (let n = 0; n < e.rows; n++) {
1900
+ if (n === t)
1901
+ continue;
1902
+ let s = 0;
1903
+ for (let c = 0; c < e.cols; c++)
1904
+ c !== r && (a.data[o][s] = e.data[n][c], s++);
1905
+ o++;
1906
+ }
1907
+ return a;
1908
+ },
1909
+ inverse(e) {
1910
+ const t = this.determinant(e);
1911
+ if (t === 0)
1912
+ throw new Error("Matrix is singular, cannot compute inverse");
1913
+ const r = e.rows, a = this.create(r, r);
1914
+ for (let o = 0; o < r; o++)
1915
+ for (let n = 0; n < r; n++) {
1916
+ const s = Math.pow(-1, o + n), c = this.determinant(this.minor(e, o, n));
1917
+ a.data[n][o] = s * c;
1918
+ }
1919
+ return this.scalar(a, 1 / t);
1920
+ },
1921
+ trace(e) {
1922
+ if (e.rows !== e.cols)
1923
+ throw new Error("Trace requires square matrix");
1924
+ let t = 0;
1925
+ for (let r = 0; r < e.rows; r++)
1926
+ t += e.data[r][r];
1927
+ return t;
1928
+ },
1929
+ eigenvalues2x2(e) {
1930
+ if (e.rows !== 2 || e.cols !== 2)
1931
+ throw new Error("Only 2x2 matrices supported for eigenvalues");
1932
+ const t = e.data[0][0], r = e.data[0][1], a = e.data[1][0], o = e.data[1][1], n = t + o, s = t * o - r * a, c = n * n - 4 * s;
1933
+ if (c < 0)
1934
+ throw new Error("Complex eigenvalues not supported");
1935
+ const l = Math.sqrt(c);
1936
+ return [(n + l) / 2, (n - l) / 2];
1937
+ },
1938
+ toString(e, t = 4) {
1939
+ return e.data.map((r) => "[ " + r.map((a) => a.toFixed(t).padStart(10)).join(" ") + " ]").join(`
1940
+ `);
1941
+ }
1942
+ }, CalculusOps = {
1943
+ /** Numerical derivative at a point */
1944
+ derivative(e, t, r = 1e-7) {
1945
+ return (e(t + r) - e(t - r)) / (2 * r);
1946
+ },
1947
+ /** Second derivative at a point */
1948
+ secondDerivative(e, t, r = 1e-5) {
1949
+ return (e(t + r) - 2 * e(t) + e(t - r)) / (r * r);
1950
+ },
1951
+ /** Numerical integration using Simpson's rule */
1952
+ integrate(e, t, r, a = 1e3) {
1953
+ a % 2 !== 0 && a++;
1954
+ const o = (r - t) / a;
1955
+ let n = e(t) + e(r);
1956
+ for (let s = 1; s < a; s++) {
1957
+ const c = t + s * o;
1958
+ n += s % 2 === 0 ? 2 * e(c) : 4 * e(c);
1959
+ }
1960
+ return o / 3 * n;
1961
+ },
1962
+ /** Find root using Newton-Raphson method */
1963
+ findRoot(e, t, r = 1e-10, a = 100) {
1964
+ let o = t;
1965
+ for (let n = 0; n < a; n++) {
1966
+ const s = e(o);
1967
+ if (Math.abs(s) < r)
1968
+ return o;
1969
+ const c = this.derivative(e, o);
1970
+ if (c === 0)
1971
+ throw new Error("Derivative is zero, Newton-Raphson failed");
1972
+ o = o - s / c;
1973
+ }
1974
+ throw new Error("Newton-Raphson did not converge");
1975
+ },
1976
+ /** Symbolic differentiation (simple cases) */
1977
+ symbolicDerivative(e) {
1978
+ if (e = e.trim(), /^-?\d+\.?\d*$/.test(e))
1979
+ return "0";
1980
+ if (e === "x")
1981
+ return "1";
1982
+ const t = e.match(/^x\^(\d+)$/);
1983
+ if (t) {
1984
+ const a = parseInt(t[1], 10);
1985
+ return a === 1 ? "1" : a === 2 ? "2*x" : `${a}*x^${a - 1}`;
1986
+ }
1987
+ const r = e.match(/^(-?\d+\.?\d*)\*x\^(\d+)$/);
1988
+ if (r) {
1989
+ const a = parseFloat(r[1]), o = parseInt(r[2], 10), n = a * o;
1990
+ return o === 1 ? String(n) : o === 2 ? `${n}*x` : `${n}*x^${o - 1}`;
1991
+ }
1992
+ return e === "sin(x)" ? "cos(x)" : e === "cos(x)" ? "-sin(x)" : e === "e^x" || e === "exp(x)" ? "e^x" : e === "ln(x)" ? "1/x" : `d/dx(${e})`;
1993
+ },
1994
+ /** Symbolic integration (simple cases) */
1995
+ symbolicIntegral(e) {
1996
+ if (e = e.trim(), /^-?\d+\.?\d*$/.test(e))
1997
+ return `${e}*x + C`;
1998
+ if (e === "x")
1999
+ return "x^2/2 + C";
2000
+ const t = e.match(/^x\^(\d+)$/);
2001
+ if (t) {
2002
+ const r = parseInt(t[1], 10);
2003
+ return `x^${r + 1}/${r + 1} + C`;
2004
+ }
2005
+ return e === "sin(x)" ? "-cos(x) + C" : e === "cos(x)" ? "sin(x) + C" : e === "e^x" || e === "exp(x)" ? "e^x + C" : e === "1/x" ? "ln|x| + C" : `∫(${e})dx + C`;
2006
+ },
2007
+ /** Solve quadratic equation ax² + bx + c = 0 */
2008
+ solveQuadratic(e, t, r) {
2009
+ const a = t * t - 4 * e * r;
2010
+ if (a < 0)
2011
+ throw new Error("No real solutions (complex roots)");
2012
+ if (a === 0)
2013
+ return [-t / (2 * e)];
2014
+ const o = Math.sqrt(a);
2015
+ return [(-t + o) / (2 * e), (-t - o) / (2 * e)];
2016
+ }
2017
+ };
2018
+ class CalculatorService {
2019
+ constructor(e = {}) {
2020
+ M(this, "history", []);
2021
+ M(this, "memory", 0);
2022
+ M(this, "variables", /* @__PURE__ */ new Map());
2023
+ M(this, "config");
2024
+ this.config = {
2025
+ precision: e.precision ?? 12,
2026
+ angleUnit: e.angleUnit ?? "rad"
2027
+ };
2028
+ }
2029
+ /** Evaluate expression */
2030
+ evaluate(expression) {
2031
+ let expr = expression.replace(/π|pi/gi, String(Math.PI)).replace(/e(?![xp])/gi, String(Math.E)).replace(/\^/g, "**").replace(/√/g, "Math.sqrt").replace(/sin/gi, "Math.sin").replace(/cos/gi, "Math.cos").replace(/tan/gi, "Math.tan").replace(/asin/gi, "Math.asin").replace(/acos/gi, "Math.acos").replace(/atan/gi, "Math.atan").replace(/sinh/gi, "Math.sinh").replace(/cosh/gi, "Math.cosh").replace(/tanh/gi, "Math.tanh").replace(/log10/gi, "Math.log10").replace(/log2/gi, "Math.log2").replace(/ln/gi, "Math.log").replace(/log\b/gi, "Math.log10").replace(/exp/gi, "Math.exp").replace(/sqrt/gi, "Math.sqrt").replace(/cbrt/gi, "Math.cbrt").replace(/abs/gi, "Math.abs").replace(/floor/gi, "Math.floor").replace(/ceil/gi, "Math.ceil").replace(/round/gi, "Math.round").replace(/pow/gi, "Math.pow").replace(/min/gi, "Math.min").replace(/max/gi, "Math.max");
2032
+ for (const [e, t] of this.variables)
2033
+ expr = expr.replace(new RegExp(`\\b${e}\\b`, "g"), String(t));
2034
+ try {
2035
+ const result = eval(expr);
2036
+ if (typeof result != "number" || !Number.isFinite(result))
2037
+ throw new Error("Invalid result");
2038
+ return result;
2039
+ } catch (e) {
2040
+ throw new Error(`Invalid expression: ${e.message}`);
2041
+ }
2042
+ }
2043
+ /** Add to history */
2044
+ addHistory(e, t, r) {
2045
+ this.history.unshift({
2046
+ id: Date.now().toString(36),
2047
+ expression: e,
2048
+ result: t,
2049
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2050
+ mode: r
2051
+ }), this.history.length > 100 && this.history.pop();
2052
+ }
2053
+ /** Get history */
2054
+ getHistory() {
2055
+ return this.history;
2056
+ }
2057
+ /** Clear history */
2058
+ clearHistory() {
2059
+ this.history = [];
2060
+ }
2061
+ /** Memory operations */
2062
+ memoryStore(e) {
2063
+ this.memory = e;
2064
+ }
2065
+ memoryRecall() {
2066
+ return this.memory;
2067
+ }
2068
+ memoryAdd(e) {
2069
+ this.memory += e;
2070
+ }
2071
+ memoryClear() {
2072
+ this.memory = 0;
2073
+ }
2074
+ /** Variable operations */
2075
+ setVariable(e, t) {
2076
+ this.variables.set(e, t);
2077
+ }
2078
+ getVariable(e) {
2079
+ return this.variables.get(e);
2080
+ }
2081
+ /** Convert between number bases */
2082
+ convertBase(e, t, r) {
2083
+ const a = { BIN: 2, OCT: 8, DEC: 10, HEX: 16 }, o = parseInt(e, a[t]);
2084
+ if (isNaN(o))
2085
+ throw new Error("Invalid number for base conversion");
2086
+ return o.toString(a[r]).toUpperCase();
2087
+ }
2088
+ /** Convert units */
2089
+ convertUnits(e, t, r) {
2090
+ const a = UNITS.find((s) => s.symbol === t), o = UNITS.find((s) => s.symbol === r);
2091
+ if (!a || !o)
2092
+ throw new Error("Unknown unit");
2093
+ if (a.category !== o.category)
2094
+ throw new Error("Cannot convert between different unit categories");
2095
+ const n = a.toBase(e);
2096
+ return o.fromBase(n);
2097
+ }
2098
+ /** Get units by category */
2099
+ getUnitsByCategory(e) {
2100
+ return UNITS.filter((t) => t.category === e);
2101
+ }
2102
+ /** Get all unit categories */
2103
+ getUnitCategories() {
2104
+ return [...new Set(UNITS.map((e) => e.category))];
2105
+ }
2106
+ /** Format number with precision */
2107
+ format(e) {
2108
+ const t = this.config.precision;
2109
+ return Math.abs(e) < 1e-10 ? "0" : Math.abs(e) > 1e10 || Math.abs(e) < 1e-6 ? e.toExponential(t) : parseFloat(e.toPrecision(t)).toString();
2110
+ }
2111
+ }
2112
+ function createCalculatorService(e) {
2113
+ return new CalculatorService(e);
2114
+ }
2115
+ const CalculatorContext = createContext(null);
2116
+ function useCalculator() {
2117
+ const e = useContext(CalculatorContext);
2118
+ if (!e)
2119
+ throw new Error("useCalculator must be used within CalculatorProvider");
2120
+ return e;
2121
+ }
2122
+ const styles$1 = {
2123
+ container: {
2124
+ width: "400px",
2125
+ fontFamily: "'Inter', sans-serif",
2126
+ backgroundColor: "#1e1e1e",
2127
+ borderRadius: "12px",
2128
+ overflow: "hidden",
2129
+ boxShadow: "0 4px 20px rgba(0,0,0,0.3)"
2130
+ },
2131
+ modeSelector: {
2132
+ display: "flex",
2133
+ backgroundColor: "#2d2d2d"
2134
+ },
2135
+ modeButton: {
2136
+ flex: 1,
2137
+ padding: "8px",
2138
+ border: "none",
2139
+ backgroundColor: "transparent",
2140
+ color: "#888",
2141
+ fontSize: "11px",
2142
+ cursor: "pointer"
2143
+ },
2144
+ display: {
2145
+ padding: "20px",
2146
+ backgroundColor: "#252525",
2147
+ minHeight: "80px"
2148
+ },
2149
+ displayText: {
2150
+ color: "#fff",
2151
+ fontSize: "32px",
2152
+ fontFamily: "'JetBrains Mono', monospace",
2153
+ textAlign: "right",
2154
+ wordBreak: "break-all"
2155
+ },
2156
+ keypad: {
2157
+ display: "grid",
2158
+ gridTemplateColumns: "repeat(4, 1fr)",
2159
+ gap: "1px",
2160
+ backgroundColor: "#333",
2161
+ padding: "1px"
2162
+ },
2163
+ key: {
2164
+ padding: "20px",
2165
+ border: "none",
2166
+ backgroundColor: "#3c3c3c",
2167
+ color: "#fff",
2168
+ fontSize: "18px",
2169
+ cursor: "pointer",
2170
+ transition: "background-color 0.1s"
2171
+ },
2172
+ keyOperator: {
2173
+ backgroundColor: "#ff9f0a",
2174
+ color: "#000"
2175
+ },
2176
+ keyFunction: {
2177
+ backgroundColor: "#505050"
2178
+ }
2179
+ };
2180
+ function NiceCalculator({
2181
+ service: e,
2182
+ className: t,
2183
+ style: r
2184
+ }) {
2185
+ const [a, o] = useState("0"), [n, s] = useState("standard"), [c, l] = useState([]), [i, d] = useState(!1), u = useCallback(
2186
+ (g) => {
2187
+ i && /[0-9.]/.test(g) ? (o(g), d(!1)) : (o((m) => m === "0" && g !== "." ? g : m + g), d(!1));
2188
+ },
2189
+ [i]
2190
+ ), h = useCallback(() => {
2191
+ o("0"), d(!1);
2192
+ }, []), b = useCallback(() => {
2193
+ try {
2194
+ const g = e.evaluate(a), m = e.format(g);
2195
+ e.addHistory(a, m, n), l(e.getHistory()), o(m), d(!0);
2196
+ } catch {
2197
+ o("Error"), d(!0);
2198
+ }
2199
+ }, [a, n, e]), y = {
2200
+ service: e,
2201
+ display: a,
2202
+ setDisplay: o,
2203
+ mode: n,
2204
+ setMode: s,
2205
+ history: c,
2206
+ calculate: b,
2207
+ appendDigit: u,
2208
+ clear: h
2209
+ };
2210
+ return /* @__PURE__ */ jsx(CalculatorContext.Provider, { value: y, children: /* @__PURE__ */ jsxs("div", { className: t, style: { ...styles$1.container, ...r }, children: [
2211
+ /* @__PURE__ */ jsx(ModeSelector, {}),
2212
+ /* @__PURE__ */ jsx(Display, {}),
2213
+ n === "standard" && /* @__PURE__ */ jsx(StandardKeypad, {}),
2214
+ n === "scientific" && /* @__PURE__ */ jsx(ScientificKeypad, {}),
2215
+ n === "programmer" && /* @__PURE__ */ jsx(ProgrammerKeypad, {}),
2216
+ n === "matrix" && /* @__PURE__ */ jsx(MatrixMode, {}),
2217
+ n === "calculus" && /* @__PURE__ */ jsx(CalculusMode, {}),
2218
+ n === "units" && /* @__PURE__ */ jsx(UnitsMode, {})
2219
+ ] }) });
2220
+ }
2221
+ function ModeSelector() {
2222
+ const { mode: e, setMode: t } = useCalculator(), r = [
2223
+ { id: "standard", label: "Standard" },
2224
+ { id: "scientific", label: "Scientific" },
2225
+ { id: "programmer", label: "Programmer" },
2226
+ { id: "matrix", label: "Matrix" },
2227
+ { id: "calculus", label: "Calculus" },
2228
+ { id: "units", label: "Units" }
2229
+ ];
2230
+ return /* @__PURE__ */ jsx("div", { style: styles$1.modeSelector, children: r.map((a) => /* @__PURE__ */ jsx(
2231
+ "button",
2232
+ {
2233
+ onClick: () => t(a.id),
2234
+ style: {
2235
+ ...styles$1.modeButton,
2236
+ backgroundColor: e === a.id ? "#1976d2" : "transparent",
2237
+ color: e === a.id ? "#fff" : "#888"
2238
+ },
2239
+ children: a.label
2240
+ },
2241
+ a.id
2242
+ )) });
2243
+ }
2244
+ function Display() {
2245
+ const { display: e } = useCalculator();
2246
+ return /* @__PURE__ */ jsx("div", { style: styles$1.display, children: /* @__PURE__ */ jsx("div", { style: styles$1.displayText, children: e }) });
2247
+ }
2248
+ function StandardKeypad() {
2249
+ const { appendDigit: e, clear: t, calculate: r, setDisplay: a, display: o } = useCalculator(), n = [
2250
+ { label: "AC", action: t, style: styles$1.keyFunction },
2251
+ {
2252
+ label: "±",
2253
+ action: () => a(o.startsWith("-") ? o.slice(1) : "-" + o),
2254
+ style: styles$1.keyFunction
2255
+ },
2256
+ { label: "%", action: () => e("/100"), style: styles$1.keyFunction },
2257
+ { label: "÷", action: () => e("/"), style: styles$1.keyOperator },
2258
+ { label: "7", action: () => e("7") },
2259
+ { label: "8", action: () => e("8") },
2260
+ { label: "9", action: () => e("9") },
2261
+ { label: "×", action: () => e("*"), style: styles$1.keyOperator },
2262
+ { label: "4", action: () => e("4") },
2263
+ { label: "5", action: () => e("5") },
2264
+ { label: "6", action: () => e("6") },
2265
+ { label: "−", action: () => e("-"), style: styles$1.keyOperator },
2266
+ { label: "1", action: () => e("1") },
2267
+ { label: "2", action: () => e("2") },
2268
+ { label: "3", action: () => e("3") },
2269
+ { label: "+", action: () => e("+"), style: styles$1.keyOperator },
2270
+ { label: "0", action: () => e("0") },
2271
+ { label: ".", action: () => e(".") },
2272
+ { label: "⌫", action: () => a(o.length > 1 ? o.slice(0, -1) : "0") },
2273
+ { label: "=", action: r, style: styles$1.keyOperator }
2274
+ ];
2275
+ return /* @__PURE__ */ jsx("div", { style: styles$1.keypad, children: n.map((s, c) => /* @__PURE__ */ jsx("button", { onClick: s.action, style: { ...styles$1.key, ...s.style || {} }, children: s.label }, c)) });
2276
+ }
2277
+ function ScientificKeypad() {
2278
+ const { appendDigit: e, clear: t, calculate: r, setDisplay: a, display: o } = useCalculator(), n = [
2279
+ { label: "sin", action: () => e("sin(") },
2280
+ { label: "cos", action: () => e("cos(") },
2281
+ { label: "tan", action: () => e("tan(") },
2282
+ { label: "ln", action: () => e("ln(") },
2283
+ { label: "log", action: () => e("log10(") }
2284
+ ], s = [
2285
+ { label: "x²", action: () => e("^2") },
2286
+ { label: "x³", action: () => e("^3") },
2287
+ { label: "xʸ", action: () => e("^") },
2288
+ { label: "√", action: () => e("sqrt(") },
2289
+ { label: "eˣ", action: () => e("exp(") }
2290
+ ], c = [
2291
+ { label: "(", action: () => e("(") },
2292
+ { label: ")", action: () => e(")") },
2293
+ { label: "π", action: () => e("π") },
2294
+ { label: "e", action: () => e("e") },
2295
+ { label: "AC", action: t }
2296
+ ];
2297
+ return /* @__PURE__ */ jsxs("div", { children: [
2298
+ /* @__PURE__ */ jsx("div", { style: { ...styles$1.keypad, gridTemplateColumns: "repeat(5, 1fr)" }, children: [...n, ...s, ...c].map((l, i) => /* @__PURE__ */ jsx(
2299
+ "button",
2300
+ {
2301
+ onClick: l.action,
2302
+ style: { ...styles$1.key, ...styles$1.keyFunction, padding: "12px" },
2303
+ children: l.label
2304
+ },
2305
+ i
2306
+ )) }),
2307
+ /* @__PURE__ */ jsx(StandardKeypad, {})
2308
+ ] });
2309
+ }
2310
+ function ProgrammerKeypad() {
2311
+ const { display: e, setDisplay: t, service: r } = useCalculator(), [a, o] = useState("DEC"), n = (c) => {
2312
+ try {
2313
+ const l = r.convertBase(e, a, c);
2314
+ t(l), o(c);
2315
+ } catch {
2316
+ t("Error");
2317
+ }
2318
+ }, s = a === "HEX" ? ["A", "B", "C", "D", "E", "F"] : [];
2319
+ return /* @__PURE__ */ jsxs("div", { children: [
2320
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "4px", padding: "8px", backgroundColor: "#252525" }, children: ["BIN", "OCT", "DEC", "HEX"].map((c) => /* @__PURE__ */ jsx(
2321
+ "button",
2322
+ {
2323
+ onClick: () => n(c),
2324
+ style: {
2325
+ flex: 1,
2326
+ padding: "8px",
2327
+ border: "none",
2328
+ borderRadius: "4px",
2329
+ backgroundColor: a === c ? "#1976d2" : "#3c3c3c",
2330
+ color: "#fff",
2331
+ cursor: "pointer"
2332
+ },
2333
+ children: c
2334
+ },
2335
+ c
2336
+ )) }),
2337
+ s.length > 0 && /* @__PURE__ */ jsx("div", { style: { ...styles$1.keypad, gridTemplateColumns: "repeat(6, 1fr)" }, children: s.map((c) => /* @__PURE__ */ jsx(
2338
+ "button",
2339
+ {
2340
+ onClick: () => t(e === "0" ? c : e + c),
2341
+ style: styles$1.key,
2342
+ children: c
2343
+ },
2344
+ c
2345
+ )) }),
2346
+ /* @__PURE__ */ jsx("div", { style: { ...styles$1.keypad, gridTemplateColumns: "repeat(4, 1fr)" }, children: [
2347
+ "7",
2348
+ "8",
2349
+ "9",
2350
+ "AND",
2351
+ "4",
2352
+ "5",
2353
+ "6",
2354
+ "OR",
2355
+ "1",
2356
+ "2",
2357
+ "3",
2358
+ "XOR",
2359
+ "0",
2360
+ "NOT",
2361
+ "<<",
2362
+ ">>"
2363
+ ].map((c) => {
2364
+ const l = ["AND", "OR", "XOR", "NOT", "<<", ">>"].includes(c);
2365
+ return /* @__PURE__ */ jsx(
2366
+ "button",
2367
+ {
2368
+ onClick: () => t(e === "0" ? c : e + c),
2369
+ style: { ...styles$1.key, ...l ? styles$1.keyFunction : {} },
2370
+ children: c
2371
+ },
2372
+ c
2373
+ );
2374
+ }) })
2375
+ ] });
2376
+ }
2377
+ function MatrixMode() {
2378
+ const [e, t] = useState(MatrixOps.create(2, 2)), [r, a] = useState(MatrixOps.create(2, 2)), [o, n] = useState(""), s = (l, i, d, u, h) => {
2379
+ const b = { ...l, data: l.data.map((y) => [...y]) };
2380
+ b.data[d][u] = parseFloat(h) || 0, i(b);
2381
+ };
2382
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", backgroundColor: "#252525" }, children: [
2383
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px", marginBottom: "12px" }, children: [
2384
+ /* @__PURE__ */ jsxs("div", { children: [
2385
+ /* @__PURE__ */ jsx("div", { style: { color: "#888", marginBottom: "4px" }, children: "Matrix A" }),
2386
+ /* @__PURE__ */ jsx(
2387
+ MatrixInput,
2388
+ {
2389
+ matrix: e,
2390
+ onChange: (l, i, d) => s(e, t, l, i, d)
2391
+ }
2392
+ )
2393
+ ] }),
2394
+ /* @__PURE__ */ jsxs("div", { children: [
2395
+ /* @__PURE__ */ jsx("div", { style: { color: "#888", marginBottom: "4px" }, children: "Matrix B" }),
2396
+ /* @__PURE__ */ jsx(
2397
+ MatrixInput,
2398
+ {
2399
+ matrix: r,
2400
+ onChange: (l, i, d) => s(r, a, l, i, d)
2401
+ }
2402
+ )
2403
+ ] })
2404
+ ] }),
2405
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "4px", flexWrap: "wrap", marginBottom: "12px" }, children: [
2406
+ { label: "A + B", fn: () => MatrixOps.toString(MatrixOps.add(e, r)) },
2407
+ { label: "A - B", fn: () => MatrixOps.toString(MatrixOps.subtract(e, r)) },
2408
+ { label: "A × B", fn: () => MatrixOps.toString(MatrixOps.multiply(e, r)) },
2409
+ { label: "det(A)", fn: () => MatrixOps.determinant(e).toFixed(4) },
2410
+ { label: "Aᵀ", fn: () => MatrixOps.toString(MatrixOps.transpose(e)) },
2411
+ { label: "A⁻¹", fn: () => MatrixOps.toString(MatrixOps.inverse(e)) }
2412
+ ].map((l) => /* @__PURE__ */ jsx(
2413
+ "button",
2414
+ {
2415
+ onClick: () => {
2416
+ try {
2417
+ n(l.fn());
2418
+ } catch (i) {
2419
+ n(i.message);
2420
+ }
2421
+ },
2422
+ style: {
2423
+ padding: "8px 12px",
2424
+ backgroundColor: "#1976d2",
2425
+ color: "#fff",
2426
+ border: "none",
2427
+ borderRadius: "4px",
2428
+ cursor: "pointer"
2429
+ },
2430
+ children: l.label
2431
+ },
2432
+ l.label
2433
+ )) }),
2434
+ o && /* @__PURE__ */ jsx("pre", { style: { color: "#fff", fontFamily: "monospace", whiteSpace: "pre-wrap" }, children: o })
2435
+ ] });
2436
+ }
2437
+ function MatrixInput({
2438
+ matrix: e,
2439
+ onChange: t
2440
+ }) {
2441
+ return /* @__PURE__ */ jsx(
2442
+ "div",
2443
+ {
2444
+ style: { display: "grid", gridTemplateColumns: `repeat(${e.cols}, 50px)`, gap: "4px" },
2445
+ children: e.data.map(
2446
+ (r, a) => r.map((o, n) => /* @__PURE__ */ jsx(
2447
+ "input",
2448
+ {
2449
+ type: "number",
2450
+ value: o,
2451
+ onChange: (s) => t(a, n, s.target.value),
2452
+ style: {
2453
+ width: "100%",
2454
+ padding: "4px",
2455
+ textAlign: "center",
2456
+ backgroundColor: "#3c3c3c",
2457
+ color: "#fff",
2458
+ border: "1px solid #555",
2459
+ borderRadius: "4px"
2460
+ }
2461
+ },
2462
+ `${a}-${n}`
2463
+ ))
2464
+ )
2465
+ }
2466
+ );
2467
+ }
2468
+ function CalculusMode() {
2469
+ const [e, t] = useState("x^2"), [r, a] = useState("");
2470
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", backgroundColor: "#252525" }, children: [
2471
+ /* @__PURE__ */ jsx(
2472
+ "input",
2473
+ {
2474
+ type: "text",
2475
+ value: e,
2476
+ onChange: (o) => t(o.target.value),
2477
+ placeholder: "Enter expression (e.g., x^2, sin(x))",
2478
+ style: {
2479
+ width: "100%",
2480
+ padding: "8px",
2481
+ marginBottom: "12px",
2482
+ backgroundColor: "#3c3c3c",
2483
+ color: "#fff",
2484
+ border: "1px solid #555",
2485
+ borderRadius: "4px"
2486
+ }
2487
+ }
2488
+ ),
2489
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "4px", flexWrap: "wrap", marginBottom: "12px" }, children: [
2490
+ /* @__PURE__ */ jsx(
2491
+ "button",
2492
+ {
2493
+ onClick: () => a(`d/dx(${e}) = ${CalculusOps.symbolicDerivative(e)}`),
2494
+ style: {
2495
+ padding: "8px 12px",
2496
+ backgroundColor: "#4caf50",
2497
+ color: "#fff",
2498
+ border: "none",
2499
+ borderRadius: "4px",
2500
+ cursor: "pointer"
2501
+ },
2502
+ children: "Differentiate"
2503
+ }
2504
+ ),
2505
+ /* @__PURE__ */ jsx(
2506
+ "button",
2507
+ {
2508
+ onClick: () => a(`∫(${e})dx = ${CalculusOps.symbolicIntegral(e)}`),
2509
+ style: {
2510
+ padding: "8px 12px",
2511
+ backgroundColor: "#2196f3",
2512
+ color: "#fff",
2513
+ border: "none",
2514
+ borderRadius: "4px",
2515
+ cursor: "pointer"
2516
+ },
2517
+ children: "Integrate"
2518
+ }
2519
+ )
2520
+ ] }),
2521
+ r && /* @__PURE__ */ jsx(
2522
+ "div",
2523
+ {
2524
+ style: {
2525
+ color: "#fff",
2526
+ fontFamily: "monospace",
2527
+ padding: "8px",
2528
+ backgroundColor: "#1e1e1e",
2529
+ borderRadius: "4px"
2530
+ },
2531
+ children: r
2532
+ }
2533
+ )
2534
+ ] });
2535
+ }
2536
+ function UnitsMode() {
2537
+ const { service: e } = useCalculator(), [t, r] = useState("1"), [a, o] = useState("m"), [n, s] = useState("ft"), [c, l] = useState("Length"), [i, d] = useState(""), u = e.getUnitCategories(), h = e.getUnitsByCategory(c), b = () => {
2538
+ try {
2539
+ const y = e.convertUnits(parseFloat(t), a, n);
2540
+ d(`${t} ${a} = ${e.format(y)} ${n}`);
2541
+ } catch (y) {
2542
+ d(y.message);
2543
+ }
2544
+ };
2545
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", backgroundColor: "#252525" }, children: [
2546
+ /* @__PURE__ */ jsx(
2547
+ "select",
2548
+ {
2549
+ value: c,
2550
+ onChange: (y) => {
2551
+ l(y.target.value);
2552
+ const g = e.getUnitsByCategory(y.target.value);
2553
+ g.length >= 2 && (o(g[0].symbol), s(g[1].symbol));
2554
+ },
2555
+ style: {
2556
+ width: "100%",
2557
+ padding: "8px",
2558
+ marginBottom: "12px",
2559
+ backgroundColor: "#3c3c3c",
2560
+ color: "#fff",
2561
+ border: "1px solid #555",
2562
+ borderRadius: "4px"
2563
+ },
2564
+ children: u.map((y) => /* @__PURE__ */ jsx("option", { value: y, children: y }, y))
2565
+ }
2566
+ ),
2567
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center", marginBottom: "12px" }, children: [
2568
+ /* @__PURE__ */ jsx(
2569
+ "input",
2570
+ {
2571
+ type: "number",
2572
+ value: t,
2573
+ onChange: (y) => r(y.target.value),
2574
+ style: {
2575
+ flex: 1,
2576
+ padding: "8px",
2577
+ backgroundColor: "#3c3c3c",
2578
+ color: "#fff",
2579
+ border: "1px solid #555",
2580
+ borderRadius: "4px"
2581
+ }
2582
+ }
2583
+ ),
2584
+ /* @__PURE__ */ jsx(
2585
+ "select",
2586
+ {
2587
+ value: a,
2588
+ onChange: (y) => o(y.target.value),
2589
+ style: {
2590
+ padding: "8px",
2591
+ backgroundColor: "#3c3c3c",
2592
+ color: "#fff",
2593
+ border: "1px solid #555",
2594
+ borderRadius: "4px"
2595
+ },
2596
+ children: h.map((y) => /* @__PURE__ */ jsxs("option", { value: y.symbol, children: [
2597
+ y.name,
2598
+ " (",
2599
+ y.symbol,
2600
+ ")"
2601
+ ] }, y.symbol))
2602
+ }
2603
+ )
2604
+ ] }),
2605
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", alignItems: "center", marginBottom: "12px" }, children: [
2606
+ /* @__PURE__ */ jsx("span", { style: { color: "#888" }, children: "→" }),
2607
+ /* @__PURE__ */ jsx(
2608
+ "select",
2609
+ {
2610
+ value: n,
2611
+ onChange: (y) => s(y.target.value),
2612
+ style: {
2613
+ flex: 1,
2614
+ padding: "8px",
2615
+ backgroundColor: "#3c3c3c",
2616
+ color: "#fff",
2617
+ border: "1px solid #555",
2618
+ borderRadius: "4px"
2619
+ },
2620
+ children: h.map((y) => /* @__PURE__ */ jsxs("option", { value: y.symbol, children: [
2621
+ y.name,
2622
+ " (",
2623
+ y.symbol,
2624
+ ")"
2625
+ ] }, y.symbol))
2626
+ }
2627
+ )
2628
+ ] }),
2629
+ /* @__PURE__ */ jsx(
2630
+ "button",
2631
+ {
2632
+ onClick: b,
2633
+ style: {
2634
+ width: "100%",
2635
+ padding: "12px",
2636
+ backgroundColor: "#ff9f0a",
2637
+ color: "#000",
2638
+ border: "none",
2639
+ borderRadius: "4px",
2640
+ fontSize: "16px",
2641
+ cursor: "pointer"
2642
+ },
2643
+ children: "Convert"
2644
+ }
2645
+ ),
2646
+ i && /* @__PURE__ */ jsx("div", { style: { marginTop: "12px", color: "#fff", fontSize: "18px", textAlign: "center" }, children: i })
2647
+ ] });
2648
+ }
2649
+ const GeoMath = {
2650
+ /** Distance between two points */
2651
+ distance(e, t) {
2652
+ return Math.sqrt((t.x - e.x) ** 2 + (t.y - e.y) ** 2);
2653
+ },
2654
+ /** Midpoint of two points */
2655
+ midpoint(e, t) {
2656
+ return { x: (e.x + t.x) / 2, y: (e.y + t.y) / 2 };
2657
+ },
2658
+ /** Angle between three points (vertex at p2) */
2659
+ angle(e, t, r) {
2660
+ const a = Math.atan2(e.y - t.y, e.x - t.x);
2661
+ let n = Math.atan2(r.y - t.y, r.x - t.x) - a;
2662
+ return n < 0 && (n += 2 * Math.PI), n;
2663
+ },
2664
+ /** Angle in degrees */
2665
+ angleDegrees(e, t, r) {
2666
+ return this.angle(e, t, r) * 180 / Math.PI;
2667
+ },
2668
+ /** Point on line closest to given point */
2669
+ closestPointOnLine(e, t, r) {
2670
+ const a = t.x - e.x, o = t.y - e.y, n = ((r.x - e.x) * a + (r.y - e.y) * o) / (a * a + o * o);
2671
+ return { x: e.x + n * a, y: e.y + n * o };
2672
+ },
2673
+ /** Line-line intersection */
2674
+ lineIntersection(e, t, r, a) {
2675
+ const o = (e.x - t.x) * (r.y - a.y) - (e.y - t.y) * (r.x - a.x);
2676
+ if (Math.abs(o) < 1e-10)
2677
+ return null;
2678
+ const n = ((e.x - r.x) * (r.y - a.y) - (e.y - r.y) * (r.x - a.x)) / o;
2679
+ return {
2680
+ x: e.x + n * (t.x - e.x),
2681
+ y: e.y + n * (t.y - e.y)
2682
+ };
2683
+ },
2684
+ /** Circle-line intersection */
2685
+ circleLineIntersection(e, t, r, a) {
2686
+ const o = a.x - r.x, n = a.y - r.y, s = r.x - e.x, c = r.y - e.y, l = o * o + n * n, i = 2 * (s * o + c * n), d = s * s + c * c - t * t, u = i * i - 4 * l * d;
2687
+ if (u < 0)
2688
+ return [];
2689
+ const h = Math.sqrt(u), b = (-i - h) / (2 * l), y = (-i + h) / (2 * l), g = [];
2690
+ return b >= 0 && b <= 1 && g.push({ x: r.x + b * o, y: r.y + b * n }), y >= 0 && y <= 1 && Math.abs(y - b) > 1e-10 && g.push({ x: r.x + y * o, y: r.y + y * n }), g;
2691
+ },
2692
+ /** Circle-circle intersection */
2693
+ circleCircleIntersection(e, t, r, a) {
2694
+ const o = this.distance(e, r);
2695
+ if (o > t + a || o < Math.abs(t - a) || o === 0)
2696
+ return [];
2697
+ const n = (t * t - a * a + o * o) / (2 * o), s = Math.sqrt(t * t - n * n), c = e.x + n * (r.x - e.x) / o, l = e.y + n * (r.y - e.y) / o;
2698
+ return [
2699
+ { x: c + s * (r.y - e.y) / o, y: l - s * (r.x - e.x) / o },
2700
+ { x: c - s * (r.y - e.y) / o, y: l + s * (r.x - e.x) / o }
2701
+ ];
2702
+ },
2703
+ /** Perpendicular line through point */
2704
+ perpendicularThrough(e, t, r) {
2705
+ this.closestPointOnLine(e, t, r);
2706
+ const a = t.x - e.x, o = t.y - e.y;
2707
+ return {
2708
+ p1: r,
2709
+ p2: { x: r.x - o, y: r.y + a }
2710
+ };
2711
+ },
2712
+ /** Parallel line through point */
2713
+ parallelThrough(e, t, r) {
2714
+ const a = t.x - e.x, o = t.y - e.y;
2715
+ return {
2716
+ p1: r,
2717
+ p2: { x: r.x + a, y: r.y + o }
2718
+ };
2719
+ },
2720
+ /** Angle bisector */
2721
+ angleBisector(e, t, r) {
2722
+ const a = Math.atan2(e.y - t.y, e.x - t.x), o = Math.atan2(r.y - t.y, r.x - t.x);
2723
+ let n = (a + o) / 2;
2724
+ return Math.abs(o - a) > Math.PI && (n += Math.PI), {
2725
+ x: t.x + Math.cos(n),
2726
+ y: t.y + Math.sin(n)
2727
+ };
2728
+ },
2729
+ /** Reflect point over line */
2730
+ reflect(e, t, r) {
2731
+ const a = this.closestPointOnLine(t, r, e);
2732
+ return {
2733
+ x: 2 * a.x - e.x,
2734
+ y: 2 * a.y - e.y
2735
+ };
2736
+ },
2737
+ /** Rotate point around center */
2738
+ rotate(e, t, r) {
2739
+ const a = Math.cos(r), o = Math.sin(r), n = e.x - t.x, s = e.y - t.y;
2740
+ return {
2741
+ x: t.x + n * a - s * o,
2742
+ y: t.y + n * o + s * a
2743
+ };
2744
+ },
2745
+ /** Translate point */
2746
+ translate(e, t, r) {
2747
+ return { x: e.x + t, y: e.y + r };
2748
+ },
2749
+ /** Dilate point from center */
2750
+ dilate(e, t, r) {
2751
+ return {
2752
+ x: t.x + r * (e.x - t.x),
2753
+ y: t.y + r * (e.y - t.y)
2754
+ };
2755
+ },
2756
+ /** Polygon area (shoelace formula) */
2757
+ polygonArea(e) {
2758
+ let t = 0;
2759
+ const r = e.length;
2760
+ for (let a = 0; a < r; a++) {
2761
+ const o = (a + 1) % r;
2762
+ t += e[a].x * e[o].y, t -= e[o].x * e[a].y;
2763
+ }
2764
+ return Math.abs(t) / 2;
2765
+ },
2766
+ /** Polygon perimeter */
2767
+ polygonPerimeter(e) {
2768
+ let t = 0;
2769
+ const r = e.length;
2770
+ for (let a = 0; a < r; a++) {
2771
+ const o = (a + 1) % r;
2772
+ t += this.distance(e[a], e[o]);
2773
+ }
2774
+ return t;
2775
+ },
2776
+ /** Triangle circumcenter */
2777
+ circumcenter(e, t, r) {
2778
+ const a = 2 * (e.x * (t.y - r.y) + t.x * (r.y - e.y) + r.x * (e.y - t.y)), o = ((e.x ** 2 + e.y ** 2) * (t.y - r.y) + (t.x ** 2 + t.y ** 2) * (r.y - e.y) + (r.x ** 2 + r.y ** 2) * (e.y - t.y)) / a, n = ((e.x ** 2 + e.y ** 2) * (r.x - t.x) + (t.x ** 2 + t.y ** 2) * (e.x - r.x) + (r.x ** 2 + r.y ** 2) * (t.x - e.x)) / a;
2779
+ return { x: o, y: n };
2780
+ },
2781
+ /** Triangle incenter */
2782
+ incenter(e, t, r) {
2783
+ const a = this.distance(e, t), o = this.distance(t, r), n = this.distance(r, e), s = a + o + n;
2784
+ return {
2785
+ x: (o * e.x + n * t.x + a * r.x) / s,
2786
+ y: (o * e.y + n * t.y + a * r.y) / s
2787
+ };
2788
+ },
2789
+ /** Triangle centroid */
2790
+ centroid(e, t, r) {
2791
+ return {
2792
+ x: (e.x + t.x + r.x) / 3,
2793
+ y: (e.y + t.y + r.y) / 3
2794
+ };
2795
+ }
2796
+ };
2797
+ class GeometryService {
2798
+ constructor() {
2799
+ M(this, "elements", /* @__PURE__ */ new Map());
2800
+ M(this, "nextLabel", 1);
2801
+ }
2802
+ /** Add element */
2803
+ addElement(t) {
2804
+ const r = this.generateId(), a = { ...t, id: r };
2805
+ return this.elements.set(r, a), a;
2806
+ }
2807
+ /** Get element */
2808
+ getElement(t) {
2809
+ return this.elements.get(t);
2810
+ }
2811
+ /** Get point */
2812
+ getPoint(t) {
2813
+ const r = this.elements.get(t);
2814
+ return (r == null ? void 0 : r.type) === "point" ? r : void 0;
2815
+ }
2816
+ /** Update element */
2817
+ updateElement(t, r) {
2818
+ const a = this.elements.get(t);
2819
+ a && this.elements.set(t, { ...a, ...r, id: t, type: a.type });
2820
+ }
2821
+ /** Delete element */
2822
+ deleteElement(t) {
2823
+ var r;
2824
+ this.elements.delete(t);
2825
+ for (const [a, o] of this.elements)
2826
+ (r = o.dependencies) != null && r.includes(t) && this.deleteElement(a);
2827
+ }
2828
+ /** Get all elements */
2829
+ getAllElements() {
2830
+ return Array.from(this.elements.values());
2831
+ }
2832
+ /** Get elements by type */
2833
+ getElementsByType(t) {
2834
+ return Array.from(this.elements.values()).filter((r) => r.type === t);
2835
+ }
2836
+ /** Clear all */
2837
+ clear() {
2838
+ this.elements.clear(), this.nextLabel = 1;
2839
+ }
2840
+ /** Create point */
2841
+ createPoint(t, r, a) {
2842
+ return this.addElement({
2843
+ type: "point",
2844
+ x: t,
2845
+ y: r,
2846
+ label: a ?? this.getNextLabel(),
2847
+ color: { r: 0, g: 0, b: 0 },
2848
+ visible: !0,
2849
+ selected: !1,
2850
+ locked: !1,
2851
+ size: 6
2852
+ });
2853
+ }
2854
+ /** Create segment */
2855
+ createSegment(t, r) {
2856
+ return this.addElement({
2857
+ type: "segment",
2858
+ point1Id: t,
2859
+ point2Id: r,
2860
+ label: void 0,
2861
+ color: { r: 50, g: 50, b: 50 },
2862
+ visible: !0,
2863
+ selected: !1,
2864
+ locked: !1,
2865
+ width: 2,
2866
+ dependencies: [t, r]
2867
+ });
2868
+ }
2869
+ /** Create line */
2870
+ createLine(t, r) {
2871
+ return this.addElement({
2872
+ type: "line",
2873
+ point1Id: t,
2874
+ point2Id: r,
2875
+ label: void 0,
2876
+ color: { r: 50, g: 50, b: 200 },
2877
+ visible: !0,
2878
+ selected: !1,
2879
+ locked: !1,
2880
+ width: 1,
2881
+ dependencies: [t, r]
2882
+ });
2883
+ }
2884
+ /** Create ray */
2885
+ createRay(t, r) {
2886
+ return this.addElement({
2887
+ type: "ray",
2888
+ originId: t,
2889
+ throughId: r,
2890
+ label: void 0,
2891
+ color: { r: 50, g: 150, b: 50 },
2892
+ visible: !0,
2893
+ selected: !1,
2894
+ locked: !1,
2895
+ width: 1,
2896
+ dependencies: [t, r]
2897
+ });
2898
+ }
2899
+ /** Create circle */
2900
+ createCircle(t, r) {
2901
+ return this.addElement({
2902
+ type: "circle",
2903
+ centerId: t,
2904
+ radius: r,
2905
+ label: void 0,
2906
+ color: { r: 200, g: 50, b: 50 },
2907
+ visible: !0,
2908
+ selected: !1,
2909
+ locked: !1,
2910
+ width: 2,
2911
+ dependencies: [t]
2912
+ });
2913
+ }
2914
+ /** Create polygon */
2915
+ createPolygon(t) {
2916
+ return this.addElement({
2917
+ type: "polygon",
2918
+ pointIds: t,
2919
+ label: void 0,
2920
+ color: { r: 100, g: 100, b: 200 },
2921
+ visible: !0,
2922
+ selected: !1,
2923
+ locked: !1,
2924
+ width: 2,
2925
+ fill: { r: 100, g: 100, b: 200, a: 0.2 },
2926
+ dependencies: t
2927
+ });
2928
+ }
2929
+ /** Create midpoint */
2930
+ createMidpoint(t, r) {
2931
+ const a = this.getPoint(t), o = this.getPoint(r);
2932
+ if (!a || !o)
2933
+ return null;
2934
+ const n = GeoMath.midpoint(a, o), s = this.createPoint(n.x, n.y);
2935
+ return s.dependencies = [t, r], s.color = { r: 0, g: 150, b: 0 }, s;
2936
+ }
2937
+ /** Create perpendicular */
2938
+ createPerpendicular(t, r, a) {
2939
+ const o = this.getPoint(t), n = this.getPoint(r), s = this.getPoint(a);
2940
+ if (!o || !n || !s)
2941
+ return null;
2942
+ const c = GeoMath.perpendicularThrough(o, n, s), l = this.createPoint(c.p2.x, c.p2.y), i = this.createLine(a, l.id);
2943
+ return i.dependencies = [t, r, a], i;
2944
+ }
2945
+ /** Create parallel */
2946
+ createParallel(t, r, a) {
2947
+ const o = this.getPoint(t), n = this.getPoint(r), s = this.getPoint(a);
2948
+ if (!o || !n || !s)
2949
+ return null;
2950
+ const c = GeoMath.parallelThrough(o, n, s), l = this.createPoint(c.p2.x, c.p2.y), i = this.createLine(a, l.id);
2951
+ return i.dependencies = [t, r, a], i;
2952
+ }
2953
+ /** Create intersection point */
2954
+ createIntersection(t, r) {
2955
+ const a = this.elements.get(t), o = this.elements.get(r);
2956
+ if (!a || !o)
2957
+ return [];
2958
+ const n = [], s = (i) => {
2959
+ if (i.type === "line" || i.type === "segment" || i.type === "ray") {
2960
+ const d = i, u = this.getPoint(d.point1Id ?? d.originId), h = this.getPoint(d.point2Id ?? d.throughId);
2961
+ if (u && h)
2962
+ return [u, h];
2963
+ }
2964
+ return null;
2965
+ }, c = s(a), l = s(o);
2966
+ if (c && l) {
2967
+ const i = GeoMath.lineIntersection(c[0], c[1], l[0], l[1]);
2968
+ if (i) {
2969
+ const d = this.createPoint(i.x, i.y);
2970
+ d.dependencies = [t, r], d.color = { r: 255, g: 0, b: 0 }, n.push(d);
2971
+ }
2972
+ }
2973
+ if (a.type === "circle" && l) {
2974
+ const i = a, d = this.getPoint(i.centerId);
2975
+ if (d) {
2976
+ const u = GeoMath.circleLineIntersection(d, i.radius, l[0], l[1]);
2977
+ for (const h of u) {
2978
+ const b = this.createPoint(h.x, h.y);
2979
+ b.dependencies = [t, r], b.color = { r: 255, g: 0, b: 0 }, n.push(b);
2980
+ }
2981
+ }
2982
+ }
2983
+ if (a.type === "circle" && o.type === "circle") {
2984
+ const i = a, d = o, u = this.getPoint(i.centerId), h = this.getPoint(d.centerId);
2985
+ if (u && h) {
2986
+ const b = GeoMath.circleCircleIntersection(u, i.radius, h, d.radius);
2987
+ for (const y of b) {
2988
+ const g = this.createPoint(y.x, y.y);
2989
+ g.dependencies = [t, r], g.color = { r: 255, g: 0, b: 0 }, n.push(g);
2990
+ }
2991
+ }
2992
+ }
2993
+ return n;
2994
+ }
2995
+ /** Calculate measurement */
2996
+ calculateMeasurement(t, r) {
2997
+ switch (t) {
2998
+ case "distance": {
2999
+ const a = this.getPoint(r[0]), o = this.getPoint(r[1]);
3000
+ if (a && o)
3001
+ return GeoMath.distance(a, o);
3002
+ break;
3003
+ }
3004
+ case "angle": {
3005
+ const a = this.getPoint(r[0]), o = this.getPoint(r[1]), n = this.getPoint(r[2]);
3006
+ if (a && o && n)
3007
+ return GeoMath.angleDegrees(a, o, n);
3008
+ break;
3009
+ }
3010
+ case "area":
3011
+ case "perimeter": {
3012
+ const a = this.elements.get(r[0]);
3013
+ if ((a == null ? void 0 : a.type) === "polygon") {
3014
+ const o = a.pointIds.map((n) => this.getPoint(n)).filter(Boolean);
3015
+ return t === "area" ? GeoMath.polygonArea(o) : GeoMath.polygonPerimeter(o);
3016
+ }
3017
+ break;
3018
+ }
3019
+ }
3020
+ return 0;
3021
+ }
3022
+ /** Export to SVG */
3023
+ exportSVG(t, r, a) {
3024
+ const o = [
3025
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${r}" viewBox="0 0 ${t} ${r}">`
3026
+ ];
3027
+ o.push(
3028
+ `<rect width="100%" height="100%" fill="rgb(${a.backgroundColor.r},${a.backgroundColor.g},${a.backgroundColor.b})"/>`
3029
+ );
3030
+ const n = (s, c) => ({
3031
+ x: t / 2 + (s - a.centerX) * a.scale,
3032
+ y: r / 2 - (c - a.centerY) * a.scale
3033
+ });
3034
+ if (a.showGrid) {
3035
+ o.push('<g stroke="#ddd" stroke-width="0.5">');
3036
+ for (let s = Math.floor(-t / 2 / a.scale + a.centerX); s <= t / 2 / a.scale + a.centerX; s += a.gridSpacing) {
3037
+ const c = n(s, 0);
3038
+ o.push(`<line x1="${c.x}" y1="0" x2="${c.x}" y2="${r}"/>`);
3039
+ }
3040
+ for (let s = Math.floor(-r / 2 / a.scale + a.centerY); s <= r / 2 / a.scale + a.centerY; s += a.gridSpacing) {
3041
+ const c = n(0, s);
3042
+ o.push(`<line x1="0" y1="${c.y}" x2="${t}" y2="${c.y}"/>`);
3043
+ }
3044
+ o.push("</g>");
3045
+ }
3046
+ if (a.showAxes) {
3047
+ const s = n(0, 0);
3048
+ o.push('<g stroke="#333" stroke-width="1">'), o.push(`<line x1="0" y1="${s.y}" x2="${t}" y2="${s.y}"/>`), o.push(`<line x1="${s.x}" y1="0" x2="${s.x}" y2="${r}"/>`), o.push("</g>");
3049
+ }
3050
+ for (const s of this.getAllElements()) {
3051
+ if (!s.visible)
3052
+ continue;
3053
+ const c = `rgb(${s.color.r},${s.color.g},${s.color.b})`;
3054
+ switch (s.type) {
3055
+ case "point": {
3056
+ const l = n(s.x, s.y);
3057
+ o.push(`<circle cx="${l.x}" cy="${l.y}" r="${s.size}" fill="${c}"/>`), s.label && o.push(`<text x="${l.x + 8}" y="${l.y - 8}" font-size="12">${s.label}</text>`);
3058
+ break;
3059
+ }
3060
+ case "segment": {
3061
+ const l = this.getPoint(s.point1Id), i = this.getPoint(s.point2Id);
3062
+ if (l && i) {
3063
+ const d = n(l.x, l.y), u = n(i.x, i.y);
3064
+ o.push(
3065
+ `<line x1="${d.x}" y1="${d.y}" x2="${u.x}" y2="${u.y}" stroke="${c}" stroke-width="${s.width}"/>`
3066
+ );
3067
+ }
3068
+ break;
3069
+ }
3070
+ case "circle": {
3071
+ const l = this.getPoint(s.centerId);
3072
+ if (l) {
3073
+ const i = n(l.x, l.y), d = s.radius * a.scale, u = s.fill ? `rgba(${s.fill.r},${s.fill.g},${s.fill.b},${s.fill.a ?? 0.2})` : "none";
3074
+ o.push(
3075
+ `<circle cx="${i.x}" cy="${i.y}" r="${d}" fill="${u}" stroke="${c}" stroke-width="${s.width}"/>`
3076
+ );
3077
+ }
3078
+ break;
3079
+ }
3080
+ case "polygon": {
3081
+ const l = s.pointIds.map((i) => this.getPoint(i)).filter(Boolean);
3082
+ if (l.length > 0) {
3083
+ const d = l.map((h) => n(h.x, h.y)).map((h, b) => `${b === 0 ? "M" : "L"}${h.x},${h.y}`).join(" ") + " Z", u = s.fill ? `rgba(${s.fill.r},${s.fill.g},${s.fill.b},${s.fill.a ?? 0.2})` : "none";
3084
+ o.push(
3085
+ `<path d="${d}" fill="${u}" stroke="${c}" stroke-width="${s.width}"/>`
3086
+ );
3087
+ }
3088
+ break;
3089
+ }
3090
+ }
3091
+ }
3092
+ return o.push("</svg>"), o.join(`
3093
+ `);
3094
+ }
3095
+ generateId() {
3096
+ return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
3097
+ }
3098
+ getNextLabel() {
3099
+ const t = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", r = this.nextLabel - 1;
3100
+ return this.nextLabel++, r < 26 ? t[r] : t[r % 26] + Math.floor(r / 26);
3101
+ }
3102
+ }
3103
+ function createGeometryService() {
3104
+ return new GeometryService();
3105
+ }
3106
+ const GeometryContext = createContext(null);
3107
+ function useGeometry() {
3108
+ const e = useContext(GeometryContext);
3109
+ if (!e)
3110
+ throw new Error("useGeometry must be used within GeometryProvider");
3111
+ return e;
3112
+ }
3113
+ const styles = {
3114
+ container: {
3115
+ display: "flex",
3116
+ height: "100%",
3117
+ fontFamily: "'Inter', sans-serif",
3118
+ fontSize: "14px"
3119
+ },
3120
+ toolbar: {
3121
+ width: "50px",
3122
+ backgroundColor: "#f5f5f5",
3123
+ borderRight: "1px solid #e0e0e0",
3124
+ display: "flex",
3125
+ flexDirection: "column",
3126
+ padding: "8px 4px",
3127
+ gap: "4px"
3128
+ },
3129
+ toolButton: {
3130
+ width: "40px",
3131
+ height: "40px",
3132
+ border: "none",
3133
+ borderRadius: "4px",
3134
+ backgroundColor: "transparent",
3135
+ cursor: "pointer",
3136
+ display: "flex",
3137
+ alignItems: "center",
3138
+ justifyContent: "center",
3139
+ fontSize: "18px"
3140
+ },
3141
+ main: {
3142
+ flex: 1,
3143
+ display: "flex",
3144
+ flexDirection: "column",
3145
+ overflow: "hidden"
3146
+ },
3147
+ canvas: {
3148
+ flex: 1,
3149
+ cursor: "crosshair"
3150
+ },
3151
+ statusBar: {
3152
+ height: "30px",
3153
+ backgroundColor: "#f5f5f5",
3154
+ borderTop: "1px solid #e0e0e0",
3155
+ padding: "0 12px",
3156
+ display: "flex",
3157
+ alignItems: "center",
3158
+ fontSize: "12px",
3159
+ color: "#666"
3160
+ }
3161
+ };
3162
+ function NiceGeometry({
3163
+ service: e,
3164
+ width: t = 800,
3165
+ height: r = 600,
3166
+ className: a,
3167
+ style: o
3168
+ }) {
3169
+ const [n, s] = useState([]), [c, l] = useState("point"), [i, d] = useState([]), [u, h] = useState({
3170
+ centerX: 0,
3171
+ centerY: 0,
3172
+ scale: 40,
3173
+ showGrid: !0,
3174
+ showAxes: !0,
3175
+ gridSpacing: 1,
3176
+ snapToGrid: !0,
3177
+ snapToPoints: !0,
3178
+ backgroundColor: { r: 255, g: 255, b: 255 }
3179
+ }), b = useCallback(() => {
3180
+ s(e.getAllElements());
3181
+ }, [e]), y = useCallback((m) => {
3182
+ h((p) => ({ ...p, ...m }));
3183
+ }, []);
3184
+ useEffect(() => {
3185
+ b();
3186
+ }, [b]);
3187
+ const g = {
3188
+ service: e,
3189
+ elements: n,
3190
+ tool: c,
3191
+ setTool: l,
3192
+ view: u,
3193
+ setView: y,
3194
+ selectedIds: i,
3195
+ setSelectedIds: d,
3196
+ refresh: b
3197
+ };
3198
+ return /* @__PURE__ */ jsx(GeometryContext.Provider, { value: g, children: /* @__PURE__ */ jsxs("div", { className: a, style: { ...styles.container, ...o }, children: [
3199
+ /* @__PURE__ */ jsx(Toolbar, {}),
3200
+ /* @__PURE__ */ jsxs("div", { style: styles.main, children: [
3201
+ /* @__PURE__ */ jsx(Canvas, { width: t, height: r }),
3202
+ /* @__PURE__ */ jsx(StatusBar, { width: t, height: r })
3203
+ ] })
3204
+ ] }) });
3205
+ }
3206
+ function Toolbar() {
3207
+ const { tool: e, setTool: t } = useGeometry(), r = [
3208
+ { id: "select", icon: "⬚", title: "Select" },
3209
+ { id: "point", icon: "•", title: "Point" },
3210
+ { id: "segment", icon: "—", title: "Segment" },
3211
+ { id: "line", icon: "↔", title: "Line" },
3212
+ { id: "ray", icon: "→", title: "Ray" },
3213
+ { id: "circle", icon: "○", title: "Circle" },
3214
+ { id: "polygon", icon: "△", title: "Polygon" },
3215
+ { id: "perpendicular", icon: "⊥", title: "Perpendicular" },
3216
+ { id: "parallel", icon: "∥", title: "Parallel" },
3217
+ { id: "midpoint", icon: "⊙", title: "Midpoint" },
3218
+ { id: "bisector", icon: "∠", title: "Angle Bisector" },
3219
+ { id: "intersection", icon: "✕", title: "Intersection" },
3220
+ { id: "reflect", icon: "⇄", title: "Reflect" },
3221
+ { id: "rotate", icon: "↻", title: "Rotate" },
3222
+ { id: "measure", icon: "📏", title: "Measure" }
3223
+ ];
3224
+ return /* @__PURE__ */ jsx("div", { style: styles.toolbar, children: r.map((a) => /* @__PURE__ */ jsx(
3225
+ "button",
3226
+ {
3227
+ onClick: () => t(a.id),
3228
+ title: a.title,
3229
+ style: {
3230
+ ...styles.toolButton,
3231
+ backgroundColor: e === a.id ? "#1976d2" : "transparent",
3232
+ color: e === a.id ? "#fff" : "#333"
3233
+ },
3234
+ children: a.icon
3235
+ },
3236
+ a.id
3237
+ )) });
3238
+ }
3239
+ function Canvas({ width: e, height: t }) {
3240
+ const r = useRef(null), { service: a, elements: o, tool: n, view: s, selectedIds: c, setSelectedIds: l, refresh: i } = useGeometry(), [d, u] = useState([]), h = useCallback(
3241
+ (m, p) => {
3242
+ const x = (m - e / 2) / s.scale + s.centerX, w = -(p - t / 2) / s.scale + s.centerY;
3243
+ return s.snapToGrid ? {
3244
+ x: Math.round(x / s.gridSpacing) * s.gridSpacing,
3245
+ y: Math.round(w / s.gridSpacing) * s.gridSpacing
3246
+ } : { x, y: w };
3247
+ },
3248
+ [e, t, s]
3249
+ ), b = useCallback(
3250
+ (m, p) => ({
3251
+ x: e / 2 + (m - s.centerX) * s.scale,
3252
+ y: t / 2 - (p - s.centerY) * s.scale
3253
+ }),
3254
+ [e, t, s]
3255
+ ), y = useCallback(
3256
+ (m) => {
3257
+ var w;
3258
+ const p = (w = r.current) == null ? void 0 : w.getBoundingClientRect();
3259
+ if (!p)
3260
+ return;
3261
+ const x = h(m.clientX - p.left, m.clientY - p.top);
3262
+ switch (n) {
3263
+ case "point": {
3264
+ a.createPoint(x.x, x.y), i();
3265
+ break;
3266
+ }
3267
+ case "segment":
3268
+ case "line":
3269
+ case "ray": {
3270
+ const k = g(x);
3271
+ if (k)
3272
+ u((f) => {
3273
+ const v = [...f, k.id];
3274
+ return v.length === 2 ? (n === "segment" ? a.createSegment(v[0], v[1]) : n === "line" ? a.createLine(v[0], v[1]) : n === "ray" && a.createRay(v[0], v[1]), i(), []) : v;
3275
+ });
3276
+ else {
3277
+ const f = a.createPoint(x.x, x.y);
3278
+ u((v) => {
3279
+ const C = [...v, f.id];
3280
+ return C.length === 2 ? (n === "segment" ? a.createSegment(C[0], C[1]) : n === "line" ? a.createLine(C[0], C[1]) : n === "ray" && a.createRay(C[0], C[1]), i(), []) : C;
3281
+ }), i();
3282
+ }
3283
+ break;
3284
+ }
3285
+ case "circle": {
3286
+ const k = g(x);
3287
+ if (k)
3288
+ u((f) => {
3289
+ if (f.length === 0)
3290
+ return [k.id];
3291
+ const v = a.getPoint(f[0]);
3292
+ if (v) {
3293
+ const C = GeoMath.distance(v, x);
3294
+ a.createCircle(f[0], C), i();
3295
+ }
3296
+ return [];
3297
+ });
3298
+ else if (d.length === 1) {
3299
+ const f = a.getPoint(d[0]);
3300
+ if (f) {
3301
+ const v = GeoMath.distance(f, x);
3302
+ a.createCircle(d[0], v), i(), u([]);
3303
+ }
3304
+ } else {
3305
+ const f = a.createPoint(x.x, x.y);
3306
+ u([f.id]), i();
3307
+ }
3308
+ break;
3309
+ }
3310
+ case "midpoint": {
3311
+ const k = g(x);
3312
+ k && u((f) => {
3313
+ const v = [...f, k.id];
3314
+ return v.length === 2 ? (a.createMidpoint(v[0], v[1]), i(), []) : v;
3315
+ });
3316
+ break;
3317
+ }
3318
+ case "select": {
3319
+ const k = g(x);
3320
+ l(k ? [k.id] : []);
3321
+ break;
3322
+ }
3323
+ }
3324
+ },
3325
+ [n, a, i, h, d, l]
3326
+ ), g = (m) => {
3327
+ for (const x of o)
3328
+ if (x.type === "point" && GeoMath.distance(x, m) < 0.5)
3329
+ return x;
3330
+ };
3331
+ return useEffect(() => {
3332
+ const m = r.current, p = m == null ? void 0 : m.getContext("2d");
3333
+ if (!(!m || !p)) {
3334
+ if (p.fillStyle = `rgb(${s.backgroundColor.r},${s.backgroundColor.g},${s.backgroundColor.b})`, p.fillRect(0, 0, e, t), s.showGrid) {
3335
+ p.strokeStyle = "#e0e0e0", p.lineWidth = 0.5;
3336
+ const x = s.gridSpacing * s.scale, w = (e / 2 - s.centerX * s.scale) % x, k = (t / 2 + s.centerY * s.scale) % x;
3337
+ for (let f = w; f < e; f += x)
3338
+ p.beginPath(), p.moveTo(f, 0), p.lineTo(f, t), p.stroke();
3339
+ for (let f = k; f < t; f += x)
3340
+ p.beginPath(), p.moveTo(0, f), p.lineTo(e, f), p.stroke();
3341
+ }
3342
+ if (s.showAxes) {
3343
+ const x = b(0, 0);
3344
+ p.strokeStyle = "#333", p.lineWidth = 1, p.beginPath(), p.moveTo(0, x.y), p.lineTo(e, x.y), p.stroke(), p.beginPath(), p.moveTo(x.x, 0), p.lineTo(x.x, t), p.stroke();
3345
+ }
3346
+ for (const x of o) {
3347
+ if (!x.visible)
3348
+ continue;
3349
+ const w = `rgb(${x.color.r},${x.color.g},${x.color.b})`, k = c.includes(x.id);
3350
+ switch (x.type) {
3351
+ case "point": {
3352
+ const f = b(x.x, x.y);
3353
+ p.beginPath(), p.arc(f.x, f.y, k ? x.size + 2 : x.size, 0, 2 * Math.PI), p.fillStyle = k ? "#1976d2" : w, p.fill(), x.label && (p.fillStyle = "#333", p.font = "12px sans-serif", p.fillText(x.label, f.x + 8, f.y - 8));
3354
+ break;
3355
+ }
3356
+ case "segment": {
3357
+ const f = a.getPoint(x.point1Id), v = a.getPoint(x.point2Id);
3358
+ if (f && v) {
3359
+ const C = b(f.x, f.y), S = b(v.x, v.y);
3360
+ p.strokeStyle = w, p.lineWidth = x.width, p.beginPath(), p.moveTo(C.x, C.y), p.lineTo(S.x, S.y), p.stroke();
3361
+ }
3362
+ break;
3363
+ }
3364
+ case "line": {
3365
+ const f = a.getPoint(x.point1Id), v = a.getPoint(x.point2Id);
3366
+ if (f && v) {
3367
+ const C = v.x - f.x, S = v.y - f.y, $ = -1e3, j = 1e3, P = b(f.x + $ * C, f.y + $ * S), B = b(f.x + j * C, f.y + j * S);
3368
+ p.strokeStyle = w, p.lineWidth = x.width, p.beginPath(), p.moveTo(P.x, P.y), p.lineTo(B.x, B.y), p.stroke();
3369
+ }
3370
+ break;
3371
+ }
3372
+ case "circle": {
3373
+ const f = a.getPoint(x.centerId);
3374
+ if (f) {
3375
+ const v = b(f.x, f.y), C = x.radius * s.scale;
3376
+ p.beginPath(), p.arc(v.x, v.y, C, 0, 2 * Math.PI), x.fill && (p.fillStyle = `rgba(${x.fill.r},${x.fill.g},${x.fill.b},${x.fill.a ?? 0.2})`, p.fill()), p.strokeStyle = w, p.lineWidth = x.width, p.stroke();
3377
+ }
3378
+ break;
3379
+ }
3380
+ case "polygon": {
3381
+ const f = x.pointIds.map((v) => a.getPoint(v)).filter(Boolean);
3382
+ if (f.length > 0) {
3383
+ p.beginPath();
3384
+ const v = b(f[0].x, f[0].y);
3385
+ p.moveTo(v.x, v.y);
3386
+ for (let C = 1; C < f.length; C++) {
3387
+ const S = b(f[C].x, f[C].y);
3388
+ p.lineTo(S.x, S.y);
3389
+ }
3390
+ p.closePath(), x.fill && (p.fillStyle = `rgba(${x.fill.r},${x.fill.g},${x.fill.b},${x.fill.a ?? 0.2})`, p.fill()), p.strokeStyle = w, p.lineWidth = x.width, p.stroke();
3391
+ }
3392
+ break;
3393
+ }
3394
+ }
3395
+ }
3396
+ if (d.length > 0) {
3397
+ p.fillStyle = "rgba(25, 118, 210, 0.3)";
3398
+ for (const x of d) {
3399
+ const w = a.getPoint(x);
3400
+ if (w) {
3401
+ const k = b(w.x, w.y);
3402
+ p.beginPath(), p.arc(k.x, k.y, 12, 0, 2 * Math.PI), p.fill();
3403
+ }
3404
+ }
3405
+ }
3406
+ }
3407
+ }, [o, s, e, t, c, d, a, b]), /* @__PURE__ */ jsx(
3408
+ "canvas",
3409
+ {
3410
+ ref: r,
3411
+ width: e,
3412
+ height: t,
3413
+ style: styles.canvas,
3414
+ onClick: y
3415
+ }
3416
+ );
3417
+ }
3418
+ function StatusBar({ width: e, height: t }) {
3419
+ const { tool: r, elements: a, view: o, service: n } = useGeometry(), [s, c] = useState(null), l = {
3420
+ select: "Select",
3421
+ point: "Point",
3422
+ line: "Line",
3423
+ ray: "Ray",
3424
+ segment: "Segment",
3425
+ circle: "Circle",
3426
+ arc: "Arc",
3427
+ polygon: "Polygon",
3428
+ angle: "Angle",
3429
+ perpendicular: "Perpendicular",
3430
+ parallel: "Parallel",
3431
+ bisector: "Angle Bisector",
3432
+ midpoint: "Midpoint",
3433
+ tangent: "Tangent",
3434
+ intersection: "Intersection",
3435
+ reflect: "Reflect",
3436
+ rotate: "Rotate",
3437
+ translate: "Translate",
3438
+ dilate: "Dilate",
3439
+ measure: "Measure",
3440
+ text: "Text"
3441
+ }, i = a.filter((d) => d.type === "point").length;
3442
+ return /* @__PURE__ */ jsxs("div", { style: styles.statusBar, children: [
3443
+ /* @__PURE__ */ jsxs("span", { children: [
3444
+ "Tool: ",
3445
+ l[r]
3446
+ ] }),
3447
+ /* @__PURE__ */ jsx("span", { style: { margin: "0 16px" }, children: "|" }),
3448
+ /* @__PURE__ */ jsxs("span", { children: [
3449
+ "Objects: ",
3450
+ a.length
3451
+ ] }),
3452
+ /* @__PURE__ */ jsx("span", { style: { margin: "0 16px" }, children: "|" }),
3453
+ /* @__PURE__ */ jsxs("span", { children: [
3454
+ "Points: ",
3455
+ i
3456
+ ] }),
3457
+ /* @__PURE__ */ jsx("span", { style: { margin: "0 16px" }, children: "|" }),
3458
+ /* @__PURE__ */ jsxs("span", { children: [
3459
+ "Scale: ",
3460
+ o.scale.toFixed(1),
3461
+ "x"
3462
+ ] })
3463
+ ] });
3464
+ }
3465
+ export {
3466
+ CalculatorService,
3467
+ CalculusOps,
3468
+ EQUATION_TEMPLATES,
3469
+ ExpressionParser,
3470
+ FUNCTION_PRESETS,
3471
+ GeoMath,
3472
+ GeometryService,
3473
+ GraphService,
3474
+ MATH_SYMBOLS,
3475
+ MathEditorService,
3476
+ MatrixOps,
3477
+ NiceCalculator,
3478
+ NiceGeometry,
3479
+ NiceGraphPlotter,
3480
+ NiceMathEditor,
3481
+ createCalculatorService,
3482
+ createGeometryService,
3483
+ createGraphService,
3484
+ createMathEditorService,
3485
+ getSymbolsByCategory,
3486
+ recognizeHandwriting,
3487
+ useCalculator,
3488
+ useGeometry,
3489
+ useGraph,
3490
+ useMathEditor
3491
+ };