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