@fundamental-engine/react 0.4.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/LICENSE +21 -0
- package/README.md +139 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +96 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zach Shallbetter
|
|
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
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# @fundamental-engine/react
|
|
2
|
+
|
|
3
|
+
**The React adapter for [`@fundamental-engine/core`](../core)** — a reciprocal DOM-physics field as a React
|
|
4
|
+
component. Elements you mark with `data-body` become forces; the single background field reacts to
|
|
5
|
+
them, and its density reacts back. You author meaning in JSX (`data-*` in); the field returns
|
|
6
|
+
measurement (`--field-*` CSS variables out).
|
|
7
|
+
|
|
8
|
+
→ Live manual, Lab, and gallery at **[fundamental-engine.com](https://fundamental-engine.com)**.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm i @fundamental-engine/react
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
React (17, 18, or 19) is a **peer dependency** — the core engine itself stays zero-dependency.
|
|
17
|
+
|
|
18
|
+
## Use
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { FieldField } from '@fundamental-engine/react';
|
|
22
|
+
|
|
23
|
+
export function App() {
|
|
24
|
+
return (
|
|
25
|
+
<>
|
|
26
|
+
<FieldField accent="#4da3ff" />
|
|
27
|
+
<a data-body="attract" data-strength="0.9" data-range="320" data-feedback>
|
|
28
|
+
pull me
|
|
29
|
+
</a>
|
|
30
|
+
</>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`<FieldField>` mounts a fixed, full-viewport canvas behind your app and runs the engine on it — the
|
|
36
|
+
same field the `<field-root>` custom element and vanilla `mountField()` wrap. The field reacts to every
|
|
37
|
+
`[data-body]` element on the page (the *field-reacts* law), so the bodies do not need to be children of
|
|
38
|
+
`<FieldField>`.
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
`<FieldField>` accepts every [`FieldOptions`](../core) value plus React conveniences:
|
|
43
|
+
|
|
44
|
+
| Prop | Type | What it does |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `accent` | `string` | base hue for the field (any CSS color) |
|
|
47
|
+
| `density` | `number` | particle density multiplier |
|
|
48
|
+
| `render` | `'dots' \| 'trails' \| 'links' \| 'metaballs' \| 'voronoi' \| 'streamlines'` | underlay render method |
|
|
49
|
+
| `palette` | `string \| string[]` | named palette (`ours`, `heatmap`, `infrared`, `spectrum`) or explicit colors |
|
|
50
|
+
| `waves` | `boolean` | enable wave propagation |
|
|
51
|
+
| `mass` | `boolean` | first-class mass in the integrator |
|
|
52
|
+
| `attention` | `boolean` | attention/importance weighting |
|
|
53
|
+
| `causality` | `boolean` | causal-trail visualization |
|
|
54
|
+
| `heatmap` | `boolean` | density heatmap diagnostic |
|
|
55
|
+
| `className` / `style` | — | applied to the managed `<canvas>` |
|
|
56
|
+
| `onReady` | `(field: FieldHandle) => void` | called once the engine is live |
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
<FieldField
|
|
60
|
+
render="streamlines"
|
|
61
|
+
palette="infrared"
|
|
62
|
+
onReady={(field) => field.setFormation('wells')}
|
|
63
|
+
/>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Driving the field from code
|
|
67
|
+
|
|
68
|
+
`onReady` hands you the live `FieldHandle` — the full imperative surface:
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<FieldField onReady={(field) => {
|
|
72
|
+
field.scan(); // re-pick-up [data-body] elements after a render
|
|
73
|
+
field.setFormation('wells');
|
|
74
|
+
field.setRender('trails');
|
|
75
|
+
field.burst(window.innerWidth / 2, 200); // a one-off impulse
|
|
76
|
+
field.flowTo(x, y); // a movable focus the field bends toward
|
|
77
|
+
}} />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
| Method | Use |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `scan()` / `rescan()` | re-read `[data-body]` elements after the DOM changes |
|
|
83
|
+
| `setAccent(hex)` · `setPalette(p)` | recolor live |
|
|
84
|
+
| `setFormation(name)` | arrange particles into a named formation (e.g. `wells`) |
|
|
85
|
+
| `setRender(mode)` · `setOverlay(mode)` | change the underlay / overlay surface |
|
|
86
|
+
| `setAttention(on)` · `setCausality(on)` · `setHeatmap(on)` | toggle diagnostics |
|
|
87
|
+
| `burst(x, y, hex?)` · `flowTo(x, y)` · `clearFlow()` | impulses and a movable focus |
|
|
88
|
+
| `destroy()` | stop the loop and remove the managed canvas |
|
|
89
|
+
|
|
90
|
+
### The hook
|
|
91
|
+
|
|
92
|
+
For full control of the canvas element yourself, use `useFieldField()` instead of the component:
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
const { canvasRef, fieldRef } = useFieldField({ accent: '#4da3ff' });
|
|
96
|
+
return <canvas ref={canvasRef} className="my-field" />;
|
|
97
|
+
// fieldRef.current is the FieldHandle once mounted
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Marking bodies — the `data-body` vocabulary
|
|
101
|
+
|
|
102
|
+
Any element on the page becomes a *body* by carrying `data-body`. The common attributes:
|
|
103
|
+
|
|
104
|
+
| Attribute | Meaning |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `data-body="attract"` | the force token (`attract`, `gravity`, `charge`, `sink`, …) |
|
|
107
|
+
| `data-strength` | how hard it bends the field |
|
|
108
|
+
| `data-range` | radius of influence, in px |
|
|
109
|
+
| `data-feedback` | opt in to receiving `--field-*` variables back |
|
|
110
|
+
| `data-absorb` / `data-max` | for `sink` bodies: accretion load and capacity |
|
|
111
|
+
|
|
112
|
+
After rendering **new** bodies, call `field.scan()` (e.g. from `onReady` or via `fieldRef`) so the
|
|
113
|
+
engine picks them up.
|
|
114
|
+
|
|
115
|
+
## Server-side rendering (Next.js, Remix, Astro islands)
|
|
116
|
+
|
|
117
|
+
The field is a browser effect — the engine starts inside React effects, so `<FieldField>` is safe to
|
|
118
|
+
include in an app that server-renders, but it only comes alive on the client. In the Next.js App
|
|
119
|
+
Router, render it from a Client Component (`'use client'`).
|
|
120
|
+
|
|
121
|
+
## Recipes & data binding
|
|
122
|
+
|
|
123
|
+
To apply a named recipe or bind data to the field, use `applyRecipe()` / `bindData()` from
|
|
124
|
+
[`@fundamental-engine/platform`](../platform) against a ref'd container. Browse all 64 recipes at
|
|
125
|
+
[`/docs/gallery`](https://fundamental-engine.com/docs/gallery).
|
|
126
|
+
|
|
127
|
+
## Aliases
|
|
128
|
+
|
|
129
|
+
`ForcesField` / `useForcesField` and `ForcesFieldProps` are deprecated aliases of `FieldField` /
|
|
130
|
+
`useFieldField` / `FieldFieldProps`, kept for the `forces-ui` → `field-ui` rename.
|
|
131
|
+
|
|
132
|
+
## Related
|
|
133
|
+
|
|
134
|
+
[`@fundamental-engine/core`](../core) · [`@fundamental-engine/platform`](../platform) · [`@fundamental-engine/elements`](../elements)
|
|
135
|
+
· [`@fundamental-engine/vanilla`](../vanilla) · the [documentation map](../../docs/README.md).
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT © Zach Shallbetter
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The React adapter (Phase 7) — `<FieldField>` mounts the reciprocal field on a
|
|
3
|
+
* canvas via the core engine, the same field the custom element and `mountField`
|
|
4
|
+
* wrap. React is a peer dependency (the one framework dep; the core stays zero-dep).
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { FieldField } from '@fundamental-engine/react';
|
|
8
|
+
* <FieldField accent="#4da3ff" /> // a full-viewport reciprocal field
|
|
9
|
+
* <FieldField onReady={(f) => f.scan()} /> // grab the handle to drive it
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* The field reacts to `[data-body]` elements anywhere on the page (the field-reacts
|
|
13
|
+
* law); call `field.scan()` from `onReady` after you render new bodies.
|
|
14
|
+
*/
|
|
15
|
+
import type { CSSProperties, ReactElement, RefObject } from 'react';
|
|
16
|
+
import { type FieldHandle, type FieldOptions } from '@fundamental-engine/core';
|
|
17
|
+
export interface FieldFieldProps extends FieldOptions {
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: CSSProperties;
|
|
20
|
+
/** called once the field is created, with its handle (scan/burst/setAccent/…). */
|
|
21
|
+
onReady?: (field: FieldHandle) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function FieldField({ className, style, onReady, accent, density, waves, background, render, overlay, mass, palette, attention, causality, }: FieldFieldProps): ReactElement;
|
|
24
|
+
/**
|
|
25
|
+
* Hook form — returns a ref to attach to your own `<canvas>` and the live handle.
|
|
26
|
+
* Use when you need to own the canvas element (sizing, placement) yourself.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useFieldField(opts?: FieldOptions): {
|
|
29
|
+
canvasRef: RefObject<HTMLCanvasElement | null>;
|
|
30
|
+
fieldRef: RefObject<FieldHandle | null>;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,YAAY,EAAqB,MAAM,0BAA0B,CAAC;AAGtH,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,kFAAkF;IAClF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;CAGxC;AAKD,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,OAAO,EACP,IAAI,EACJ,OAAO,EACP,SAAS,EACT,SAAS,GACV,EAAE,eAAe,GAAG,YAAY,CAwChC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,GAAE,YAAiB,GAAG;IACtD,SAAS,EAAE,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC/C,QAAQ,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CACzC,CAmCA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* The React adapter (Phase 7) — `<FieldField>` mounts the reciprocal field on a
|
|
4
|
+
* canvas via the core engine, the same field the custom element and `mountField`
|
|
5
|
+
* wrap. React is a peer dependency (the one framework dep; the core stays zero-dep).
|
|
6
|
+
*
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import { FieldField } from '@fundamental-engine/react';
|
|
9
|
+
* <FieldField accent="#4da3ff" /> // a full-viewport reciprocal field
|
|
10
|
+
* <FieldField onReady={(f) => f.scan()} /> // grab the handle to drive it
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* The field reacts to `[data-body]` elements anywhere on the page (the field-reacts
|
|
14
|
+
* law); call `field.scan()` from `onReady` after you render new bodies.
|
|
15
|
+
*/
|
|
16
|
+
import { useEffect, useRef } from 'react';
|
|
17
|
+
import { FIELD_CANVAS_STYLE } from '@fundamental-engine/core';
|
|
18
|
+
import { createBrowserField } from '@fundamental-engine/platform';
|
|
19
|
+
// the fixed, click-through surface — shared with the vanilla mount via core/surface.ts.
|
|
20
|
+
const FIXED = FIELD_CANVAS_STYLE;
|
|
21
|
+
export function FieldField({ className, style, onReady, accent, density, waves, background, render, overlay, mass, palette, attention, causality, }) {
|
|
22
|
+
const canvasRef = useRef(null);
|
|
23
|
+
const onReadyRef = useRef(onReady);
|
|
24
|
+
onReadyRef.current = onReady;
|
|
25
|
+
/** Field Surfaces: the front overlay surface this component owns, lazily created. */
|
|
26
|
+
const overlayCanvasRef = useRef(null);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const canvas = canvasRef.current;
|
|
29
|
+
if (!canvas)
|
|
30
|
+
return;
|
|
31
|
+
// Field Surfaces: lazily create the overlay canvas the first time an overlay is set.
|
|
32
|
+
// Matches the element's pattern: fixed, full-viewport, click-through, above content.
|
|
33
|
+
if (overlay !== undefined && overlay !== 'off' && !overlayCanvasRef.current && typeof document !== 'undefined') {
|
|
34
|
+
const oc = document.createElement('canvas');
|
|
35
|
+
oc.setAttribute('aria-hidden', 'true');
|
|
36
|
+
oc.style.cssText =
|
|
37
|
+
'position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:5;mix-blend-mode:screen';
|
|
38
|
+
document.body.appendChild(oc);
|
|
39
|
+
overlayCanvasRef.current = oc;
|
|
40
|
+
}
|
|
41
|
+
const field = createBrowserField(canvas, {
|
|
42
|
+
accent, density, waves, background, render,
|
|
43
|
+
overlay, overlayCanvas: overlayCanvasRef.current ?? undefined,
|
|
44
|
+
mass, palette, attention, causality,
|
|
45
|
+
});
|
|
46
|
+
onReadyRef.current?.(field);
|
|
47
|
+
return () => {
|
|
48
|
+
field.destroy();
|
|
49
|
+
// Field Surfaces: remove the overlay canvas this component owns on teardown.
|
|
50
|
+
overlayCanvasRef.current?.remove();
|
|
51
|
+
overlayCanvasRef.current = null;
|
|
52
|
+
};
|
|
53
|
+
// re-create only when an engine option actually changes
|
|
54
|
+
}, [accent, density, waves, background, render, overlay, mass, palette, attention, causality]);
|
|
55
|
+
return (_jsx("canvas", { ref: canvasRef, "aria-hidden": "true", className: className, style: { ...FIXED, ...style } }));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Hook form — returns a ref to attach to your own `<canvas>` and the live handle.
|
|
59
|
+
* Use when you need to own the canvas element (sizing, placement) yourself.
|
|
60
|
+
*/
|
|
61
|
+
export function useFieldField(opts = {}) {
|
|
62
|
+
const canvasRef = useRef(null);
|
|
63
|
+
const fieldRef = useRef(null);
|
|
64
|
+
/** Field Surfaces: the front overlay surface this hook owns, lazily created. */
|
|
65
|
+
const overlayCanvasRef = useRef(null);
|
|
66
|
+
const { accent, density, waves, background, render, overlay, mass, palette, attention, causality } = opts;
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const canvas = canvasRef.current;
|
|
69
|
+
if (!canvas)
|
|
70
|
+
return;
|
|
71
|
+
// Field Surfaces: lazily create the overlay canvas when an overlay reading is requested.
|
|
72
|
+
if (overlay !== undefined && overlay !== 'off' && !overlayCanvasRef.current && typeof document !== 'undefined') {
|
|
73
|
+
const oc = document.createElement('canvas');
|
|
74
|
+
oc.setAttribute('aria-hidden', 'true');
|
|
75
|
+
oc.style.cssText =
|
|
76
|
+
'position:fixed;inset:0;width:100%;height:100%;pointer-events:none;z-index:5;mix-blend-mode:screen';
|
|
77
|
+
document.body.appendChild(oc);
|
|
78
|
+
overlayCanvasRef.current = oc;
|
|
79
|
+
}
|
|
80
|
+
const field = createBrowserField(canvas, {
|
|
81
|
+
accent, density, waves, background, render,
|
|
82
|
+
overlay, overlayCanvas: overlayCanvasRef.current ?? undefined,
|
|
83
|
+
mass, palette, attention, causality,
|
|
84
|
+
});
|
|
85
|
+
fieldRef.current = field;
|
|
86
|
+
return () => {
|
|
87
|
+
field.destroy();
|
|
88
|
+
fieldRef.current = null;
|
|
89
|
+
// Field Surfaces: remove the overlay canvas this hook owns on teardown.
|
|
90
|
+
overlayCanvasRef.current?.remove();
|
|
91
|
+
overlayCanvasRef.current = null;
|
|
92
|
+
};
|
|
93
|
+
}, [accent, density, waves, background, render, overlay, mass, palette, attention, causality]);
|
|
94
|
+
return { canvasRef, fieldRef };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fundamental-engine/react",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "React adapter for Fundamental — a reciprocal DOM-physics field as a <FieldField> component + useFieldField hook.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Zach Shallbetter <hi@zachshallbetter.com> (https://zachshallbetter.com)",
|
|
8
|
+
"homepage": "https://fundamental-engine.com",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/zachshallbetter/fundamental-engine.git",
|
|
12
|
+
"directory": "packages/react"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/zachshallbetter/fundamental-engine/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"Fundamental",
|
|
19
|
+
"react",
|
|
20
|
+
"particles",
|
|
21
|
+
"physics",
|
|
22
|
+
"canvas",
|
|
23
|
+
"field",
|
|
24
|
+
"react-component"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"main": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@fundamental-engine/platform": "0.4.0",
|
|
49
|
+
"@fundamental-engine/core": "0.4.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": ">=18"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/react": "^19.0.0",
|
|
56
|
+
"react": "^19.0.0",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc -p tsconfig.json",
|
|
61
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
62
|
+
"test": "node --test"
|
|
63
|
+
}
|
|
64
|
+
}
|