@nice2dev/ui-math 1.1.9 → 1.2.0

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