@elucim/dsl 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +245 -245
  3. package/package.json +10 -10
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Seth Juarez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,245 +1,245 @@
1
- # @elucim/dsl
2
-
3
- > Declarative JSON DSL for animated visualizations — perfect for AI agents.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@elucim/dsl)](https://www.npmjs.com/package/@elucim/dsl)
6
- [![license](https://img.shields.io/npm/l/@elucim/dsl)](https://github.com/sethjuarez/elucim/blob/main/LICENSE)
7
-
8
- `@elucim/dsl` lets you describe animated diagrams as JSON documents. An AI agent (or any code) produces a JSON object conforming to the schema, and the `<DslRenderer>` component renders it as a fully interactive [Elucim](https://www.npmjs.com/package/@elucim/core) visualization — no React knowledge required.
9
-
10
- ## Install
11
-
12
- ```bash
13
- npm install @elucim/dsl @elucim/core react react-dom
14
- # or
15
- pnpm add @elucim/dsl @elucim/core react react-dom
16
- ```
17
-
18
- ## Quick Start
19
-
20
- ```tsx
21
- import { DslRenderer } from '@elucim/dsl';
22
- import type { ElucimDocument } from '@elucim/dsl';
23
-
24
- const myDiagram: ElucimDocument = {
25
- version: '1.0',
26
- root: {
27
- type: 'player',
28
- width: 800,
29
- height: 600,
30
- fps: 30,
31
- durationInFrames: 90,
32
- background: '#0d0d1a',
33
- children: [
34
- {
35
- type: 'circle',
36
- cx: 400,
37
- cy: 300,
38
- r: 100,
39
- stroke: '#3b82f6',
40
- strokeWidth: 3,
41
- draw: 60,
42
- },
43
- ],
44
- },
45
- };
46
-
47
- function App() {
48
- return <DslRenderer dsl={myDiagram} />;
49
- }
50
- ```
51
-
52
- ## API
53
-
54
- ### `<DslRenderer dsl={doc} />`
55
-
56
- Validates the DSL document and renders it as React components. If validation fails, displays error messages.
57
-
58
- **Props:**
59
- - `dsl: ElucimDocument` — The DSL document to render
60
- - `className?: string` — CSS class for the wrapper div
61
- - `style?: CSSProperties` — Inline styles for the wrapper div
62
-
63
- ### `validate(doc: unknown): ValidationResult`
64
-
65
- Validates a DSL document without rendering it.
66
-
67
- ```ts
68
- import { validate } from '@elucim/dsl';
69
-
70
- const result = validate(myDoc);
71
- if (!result.valid) {
72
- console.log(result.errors);
73
- // [{ path: 'root.children[0].cx', message: 'Required numeric field "cx"...', severity: 'error' }]
74
- }
75
- ```
76
-
77
- ### `compileExpression(expr: string)`
78
-
79
- Compile a math expression string into a callable function.
80
-
81
- ```ts
82
- import { compileExpression } from '@elucim/dsl';
83
-
84
- const fn = compileExpression('sin(x) * 2');
85
- fn({ x: Math.PI / 2 }); // → 2
86
- ```
87
-
88
- ### `compileVectorExpression(expr: string)`
89
-
90
- Compile a vector field expression returning `[number, number]`.
91
-
92
- ```ts
93
- import { compileVectorExpression } from '@elucim/dsl';
94
-
95
- const fn = compileVectorExpression('[-y, x]');
96
- fn({ x: 1, y: 2 }); // → [-2, 1]
97
- ```
98
-
99
- ## Document Schema
100
-
101
- Every document has this structure:
102
-
103
- ```json
104
- {
105
- "version": "1.0",
106
- "root": { "type": "scene|player|presentation", ... }
107
- }
108
- ```
109
-
110
- ### Root Types
111
-
112
- | Type | Description |
113
- |------|-------------|
114
- | `scene` | Raw SVG scene (needs external frame control) |
115
- | `player` | Interactive player with controls, scrub bar, play/pause |
116
- | `presentation` | Slide-based presentation with transitions |
117
-
118
- ### Element Types
119
-
120
- #### Primitives
121
- | Type | Required Props | Description |
122
- |------|---------------|-------------|
123
- | `circle` | `cx`, `cy`, `r` | SVG circle |
124
- | `line` | `x1`, `y1`, `x2`, `y2` | SVG line |
125
- | `arrow` | `x1`, `y1`, `x2`, `y2` | Line with arrowhead |
126
- | `rect` | `x`, `y`, `width`, `height` | Rectangle |
127
- | `polygon` | `points` (array of [x,y]) | Polygon/polyline |
128
- | `text` | `x`, `y`, `content` | Text element |
129
-
130
- #### Math Visualizations
131
- | Type | Required Props | Description |
132
- |------|---------------|-------------|
133
- | `axes` | — | Coordinate axes with grid/ticks |
134
- | `functionPlot` | `fn` (expression) | Plot a function like `"sin(x)"` |
135
- | `vector` | `to` ([x,y]) | Mathematical vector with label |
136
- | `vectorField` | `fn` (vector expr) | Grid of arrows like `"[-y, x]"` |
137
- | `matrix` | `values` (2D array) | Matrix with brackets |
138
- | `graph` | `nodes`, `edges` | Graph theory visualization |
139
- | `latex` | `expression`, `x`, `y` | LaTeX rendered via KaTeX |
140
-
141
- #### Animation Wrappers
142
- | Type | Key Props | Description |
143
- |------|----------|-------------|
144
- | `fadeIn` | `duration`, `easing` | Fade children in |
145
- | `fadeOut` | `duration`, `easing` | Fade children out |
146
- | `draw` | `duration`, `easing` | Progressive stroke drawing |
147
- | `write` | `duration`, `easing` | Stroke draw + fill fade |
148
- | `transform` | `translate`, `scale`, `rotate`, `opacity` | Animate position/scale/rotation |
149
- | `morph` | `fromColor`, `toColor`, `fromScale`, `toScale` | Color/scale morphing |
150
- | `stagger` | `staggerDelay` | Sequential delayed children |
151
- | `parallel` | — | Children animate simultaneously |
152
-
153
- #### Structural
154
- | Type | Key Props | Description |
155
- |------|----------|-------------|
156
- | `sequence` | `from`, `durationInFrames` | Time-offset wrapper |
157
- | `group` | `children` | Logical grouping |
158
-
159
- ### Inline Animation Props
160
-
161
- All primitives support these optional animation props directly:
162
- - `fadeIn?: number` — Fade in over N frames
163
- - `fadeOut?: number` — Fade out over N frames
164
- - `draw?: number` — Progressive stroke draw over N frames
165
- - `easing?: string | { type, ... }` — Easing function
166
-
167
- ### Easing
168
-
169
- **Named easings:** `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeInOutQuart`, `easeInSine`, `easeOutSine`, `easeInOutSine`, `easeInExpo`, `easeOutExpo`, `easeInOutExpo`, `easeInBack`, `easeOutBack`, `easeOutElastic`, `easeOutBounce`
170
-
171
- **Spring:** `{ "type": "spring", "stiffness": 100, "damping": 10, "mass": 1 }`
172
-
173
- **Cubic Bezier:** `{ "type": "cubicBezier", "x1": 0.25, "y1": 0.1, "x2": 0.25, "y2": 1 }`
174
-
175
- ### Math Expressions
176
-
177
- Used in `functionPlot.fn` and `vectorField.fn`. Safe evaluation — no `eval()`.
178
-
179
- **Operators:** `+`, `-`, `*`, `/`, `^` (power), unary `-`
180
-
181
- **Functions:** `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sqrt`, `abs`, `log`, `ln`, `exp`, `floor`, `ceil`, `round`, `min`, `max`, `sign`, `pow`
182
-
183
- **Constants:** `PI`, `E`, `TAU`
184
-
185
- **Variables:** `x` (FunctionPlot), `x` and `y` (VectorField)
186
-
187
- **Examples:**
188
- - `"sin(x)"` — Sine wave
189
- - `"x^2 - 1"` — Parabola
190
- - `"exp(-(x^2) / 2)"` — Gaussian
191
- - `"[-y, x]"` — Rotation vector field
192
- - `"[sin(y), cos(x)]"` — Wave vector field
193
-
194
- ## Examples
195
-
196
- See the [`examples/`](./examples/) directory:
197
- - `hello-circle.json` — Minimal animated circle
198
- - `math-demo.json` — Axes, function plot, vector, LaTeX
199
- - `animated-scene.json` — FadeIn, Draw, Transform, Stagger, Morph
200
- - `presentation.json` — Multi-slide presentation
201
- - `full-showcase.json` — Every feature in one document
202
-
203
- ## For AI Agents
204
-
205
- When instructing an LLM to create Elucim diagrams:
206
-
207
- 1. **Ask it to produce JSON** matching the `ElucimDocument` schema
208
- 2. **Set `version: "1.0"`** as the first field
209
- 3. **Choose a root type**: `player` for interactive, `scene` for embedded, `presentation` for slides
210
- 4. **Use `sequence` nodes** to control timing (offsets in frames)
211
- 5. **Wrap elements in animation nodes** (`fadeIn`, `draw`, `stagger`) for entrance effects
212
- 6. **Use math expression strings** for function plots and vector fields
213
-
214
- Example prompt:
215
- > "Create an Elucim DSL JSON document that shows a coordinate system with sin(x) and cos(x) plotted,
216
- > with the sin curve drawing first, then the cos curve drawing 30 frames later,
217
- > and a LaTeX label fading in at the end."
218
-
219
- ## Fluent Builder API
220
-
221
- Build presentations programmatically with a chainable TypeScript API:
222
-
223
- ```tsx
224
- import { presentation, darkTheme } from '@elucim/dsl';
225
-
226
- const doc = presentation(darkTheme)
227
- .size(1920, 1080)
228
- .transition('fade', 500)
229
- .slide('Welcome', (s) => {
230
- s.title('Hello World');
231
- })
232
- .slide('Math', (s) => {
233
- s.latex('e^{i\\pi} + 1 = 0', { x: 960, y: 500, fontSize: 48, color: '#fdcb6e' });
234
- })
235
- .build();
236
- ```
237
-
238
- ## Related
239
-
240
- - **[@elucim/core](https://www.npmjs.com/package/@elucim/core)** — The React rendering engine (peer dependency)
241
- - **[Elucim on GitHub](https://github.com/sethjuarez/elucim)** — Full docs with live interactive examples
242
-
243
- ## License
244
-
245
- [MIT](https://github.com/sethjuarez/elucim/blob/main/LICENSE)
1
+ # @elucim/dsl
2
+
3
+ > Declarative JSON DSL for animated visualizations — perfect for AI agents.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@elucim/dsl)](https://www.npmjs.com/package/@elucim/dsl)
6
+ [![license](https://img.shields.io/npm/l/@elucim/dsl)](https://github.com/sethjuarez/elucim/blob/main/LICENSE)
7
+
8
+ `@elucim/dsl` lets you describe animated diagrams as JSON documents. An AI agent (or any code) produces a JSON object conforming to the schema, and the `<DslRenderer>` component renders it as a fully interactive [Elucim](https://www.npmjs.com/package/@elucim/core) visualization — no React knowledge required.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @elucim/dsl @elucim/core react react-dom
14
+ # or
15
+ pnpm add @elucim/dsl @elucim/core react react-dom
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```tsx
21
+ import { DslRenderer } from '@elucim/dsl';
22
+ import type { ElucimDocument } from '@elucim/dsl';
23
+
24
+ const myDiagram: ElucimDocument = {
25
+ version: '1.0',
26
+ root: {
27
+ type: 'player',
28
+ width: 800,
29
+ height: 600,
30
+ fps: 30,
31
+ durationInFrames: 90,
32
+ background: '#0d0d1a',
33
+ children: [
34
+ {
35
+ type: 'circle',
36
+ cx: 400,
37
+ cy: 300,
38
+ r: 100,
39
+ stroke: '#3b82f6',
40
+ strokeWidth: 3,
41
+ draw: 60,
42
+ },
43
+ ],
44
+ },
45
+ };
46
+
47
+ function App() {
48
+ return <DslRenderer dsl={myDiagram} />;
49
+ }
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### `<DslRenderer dsl={doc} />`
55
+
56
+ Validates the DSL document and renders it as React components. If validation fails, displays error messages.
57
+
58
+ **Props:**
59
+ - `dsl: ElucimDocument` — The DSL document to render
60
+ - `className?: string` — CSS class for the wrapper div
61
+ - `style?: CSSProperties` — Inline styles for the wrapper div
62
+
63
+ ### `validate(doc: unknown): ValidationResult`
64
+
65
+ Validates a DSL document without rendering it.
66
+
67
+ ```ts
68
+ import { validate } from '@elucim/dsl';
69
+
70
+ const result = validate(myDoc);
71
+ if (!result.valid) {
72
+ console.log(result.errors);
73
+ // [{ path: 'root.children[0].cx', message: 'Required numeric field "cx"...', severity: 'error' }]
74
+ }
75
+ ```
76
+
77
+ ### `compileExpression(expr: string)`
78
+
79
+ Compile a math expression string into a callable function.
80
+
81
+ ```ts
82
+ import { compileExpression } from '@elucim/dsl';
83
+
84
+ const fn = compileExpression('sin(x) * 2');
85
+ fn({ x: Math.PI / 2 }); // → 2
86
+ ```
87
+
88
+ ### `compileVectorExpression(expr: string)`
89
+
90
+ Compile a vector field expression returning `[number, number]`.
91
+
92
+ ```ts
93
+ import { compileVectorExpression } from '@elucim/dsl';
94
+
95
+ const fn = compileVectorExpression('[-y, x]');
96
+ fn({ x: 1, y: 2 }); // → [-2, 1]
97
+ ```
98
+
99
+ ## Document Schema
100
+
101
+ Every document has this structure:
102
+
103
+ ```json
104
+ {
105
+ "version": "1.0",
106
+ "root": { "type": "scene|player|presentation", ... }
107
+ }
108
+ ```
109
+
110
+ ### Root Types
111
+
112
+ | Type | Description |
113
+ |------|-------------|
114
+ | `scene` | Raw SVG scene (needs external frame control) |
115
+ | `player` | Interactive player with controls, scrub bar, play/pause |
116
+ | `presentation` | Slide-based presentation with transitions |
117
+
118
+ ### Element Types
119
+
120
+ #### Primitives
121
+ | Type | Required Props | Description |
122
+ |------|---------------|-------------|
123
+ | `circle` | `cx`, `cy`, `r` | SVG circle |
124
+ | `line` | `x1`, `y1`, `x2`, `y2` | SVG line |
125
+ | `arrow` | `x1`, `y1`, `x2`, `y2` | Line with arrowhead |
126
+ | `rect` | `x`, `y`, `width`, `height` | Rectangle |
127
+ | `polygon` | `points` (array of [x,y]) | Polygon/polyline |
128
+ | `text` | `x`, `y`, `content` | Text element |
129
+
130
+ #### Math Visualizations
131
+ | Type | Required Props | Description |
132
+ |------|---------------|-------------|
133
+ | `axes` | — | Coordinate axes with grid/ticks |
134
+ | `functionPlot` | `fn` (expression) | Plot a function like `"sin(x)"` |
135
+ | `vector` | `to` ([x,y]) | Mathematical vector with label |
136
+ | `vectorField` | `fn` (vector expr) | Grid of arrows like `"[-y, x]"` |
137
+ | `matrix` | `values` (2D array) | Matrix with brackets |
138
+ | `graph` | `nodes`, `edges` | Graph theory visualization |
139
+ | `latex` | `expression`, `x`, `y` | LaTeX rendered via KaTeX |
140
+
141
+ #### Animation Wrappers
142
+ | Type | Key Props | Description |
143
+ |------|----------|-------------|
144
+ | `fadeIn` | `duration`, `easing` | Fade children in |
145
+ | `fadeOut` | `duration`, `easing` | Fade children out |
146
+ | `draw` | `duration`, `easing` | Progressive stroke drawing |
147
+ | `write` | `duration`, `easing` | Stroke draw + fill fade |
148
+ | `transform` | `translate`, `scale`, `rotate`, `opacity` | Animate position/scale/rotation |
149
+ | `morph` | `fromColor`, `toColor`, `fromScale`, `toScale` | Color/scale morphing |
150
+ | `stagger` | `staggerDelay` | Sequential delayed children |
151
+ | `parallel` | — | Children animate simultaneously |
152
+
153
+ #### Structural
154
+ | Type | Key Props | Description |
155
+ |------|----------|-------------|
156
+ | `sequence` | `from`, `durationInFrames` | Time-offset wrapper |
157
+ | `group` | `children` | Logical grouping |
158
+
159
+ ### Inline Animation Props
160
+
161
+ All primitives support these optional animation props directly:
162
+ - `fadeIn?: number` — Fade in over N frames
163
+ - `fadeOut?: number` — Fade out over N frames
164
+ - `draw?: number` — Progressive stroke draw over N frames
165
+ - `easing?: string | { type, ... }` — Easing function
166
+
167
+ ### Easing
168
+
169
+ **Named easings:** `linear`, `easeInQuad`, `easeOutQuad`, `easeInOutQuad`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`, `easeInQuart`, `easeOutQuart`, `easeInOutQuart`, `easeInSine`, `easeOutSine`, `easeInOutSine`, `easeInExpo`, `easeOutExpo`, `easeInOutExpo`, `easeInBack`, `easeOutBack`, `easeOutElastic`, `easeOutBounce`
170
+
171
+ **Spring:** `{ "type": "spring", "stiffness": 100, "damping": 10, "mass": 1 }`
172
+
173
+ **Cubic Bezier:** `{ "type": "cubicBezier", "x1": 0.25, "y1": 0.1, "x2": 0.25, "y2": 1 }`
174
+
175
+ ### Math Expressions
176
+
177
+ Used in `functionPlot.fn` and `vectorField.fn`. Safe evaluation — no `eval()`.
178
+
179
+ **Operators:** `+`, `-`, `*`, `/`, `^` (power), unary `-`
180
+
181
+ **Functions:** `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sqrt`, `abs`, `log`, `ln`, `exp`, `floor`, `ceil`, `round`, `min`, `max`, `sign`, `pow`
182
+
183
+ **Constants:** `PI`, `E`, `TAU`
184
+
185
+ **Variables:** `x` (FunctionPlot), `x` and `y` (VectorField)
186
+
187
+ **Examples:**
188
+ - `"sin(x)"` — Sine wave
189
+ - `"x^2 - 1"` — Parabola
190
+ - `"exp(-(x^2) / 2)"` — Gaussian
191
+ - `"[-y, x]"` — Rotation vector field
192
+ - `"[sin(y), cos(x)]"` — Wave vector field
193
+
194
+ ## Examples
195
+
196
+ See the [`examples/`](./examples/) directory:
197
+ - `hello-circle.json` — Minimal animated circle
198
+ - `math-demo.json` — Axes, function plot, vector, LaTeX
199
+ - `animated-scene.json` — FadeIn, Draw, Transform, Stagger, Morph
200
+ - `presentation.json` — Multi-slide presentation
201
+ - `full-showcase.json` — Every feature in one document
202
+
203
+ ## For AI Agents
204
+
205
+ When instructing an LLM to create Elucim diagrams:
206
+
207
+ 1. **Ask it to produce JSON** matching the `ElucimDocument` schema
208
+ 2. **Set `version: "1.0"`** as the first field
209
+ 3. **Choose a root type**: `player` for interactive, `scene` for embedded, `presentation` for slides
210
+ 4. **Use `sequence` nodes** to control timing (offsets in frames)
211
+ 5. **Wrap elements in animation nodes** (`fadeIn`, `draw`, `stagger`) for entrance effects
212
+ 6. **Use math expression strings** for function plots and vector fields
213
+
214
+ Example prompt:
215
+ > "Create an Elucim DSL JSON document that shows a coordinate system with sin(x) and cos(x) plotted,
216
+ > with the sin curve drawing first, then the cos curve drawing 30 frames later,
217
+ > and a LaTeX label fading in at the end."
218
+
219
+ ## Fluent Builder API
220
+
221
+ Build presentations programmatically with a chainable TypeScript API:
222
+
223
+ ```tsx
224
+ import { presentation, darkTheme } from '@elucim/dsl';
225
+
226
+ const doc = presentation(darkTheme)
227
+ .size(1920, 1080)
228
+ .transition('fade', 500)
229
+ .slide('Welcome', (s) => {
230
+ s.title('Hello World');
231
+ })
232
+ .slide('Math', (s) => {
233
+ s.latex('e^{i\\pi} + 1 = 0', { x: 960, y: 500, fontSize: 48, color: '#fdcb6e' });
234
+ })
235
+ .build();
236
+ ```
237
+
238
+ ## Related
239
+
240
+ - **[@elucim/core](https://www.npmjs.com/package/@elucim/core)** — The React rendering engine (peer dependency)
241
+ - **[Elucim on GitHub](https://github.com/sethjuarez/elucim)** — Full docs with live interactive examples
242
+
243
+ ## License
244
+
245
+ [MIT](https://github.com/sethjuarez/elucim/blob/main/LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elucim/dsl",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "JSON/YAML DSL for declarative Elucim animations — define visualizations without writing React code",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -37,19 +37,12 @@
37
37
  "dist",
38
38
  "elucim.schema.json"
39
39
  ],
40
- "scripts": {
41
- "dev": "vite build --watch",
42
- "build": "tsc && vite build",
43
- "test": "vitest run",
44
- "test:watch": "vitest",
45
- "lint": "tsc --noEmit"
46
- },
47
40
  "peerDependencies": {
48
41
  "react": "^18.0.0 || ^19.0.0",
49
42
  "react-dom": "^18.0.0 || ^19.0.0"
50
43
  },
51
44
  "dependencies": {
52
- "@elucim/core": "^0.1.1"
45
+ "@elucim/core": "0.1.2"
53
46
  },
54
47
  "devDependencies": {
55
48
  "@types/react": "^18.3.0",
@@ -62,5 +55,12 @@
62
55
  "vite": "^5.4.0",
63
56
  "vite-plugin-dts": "^4.0.0",
64
57
  "vitest": "^2.0.0"
58
+ },
59
+ "scripts": {
60
+ "dev": "vite build --watch",
61
+ "build": "tsc && vite build",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest",
64
+ "lint": "tsc --noEmit"
65
65
  }
66
- }
66
+ }