prop-for-that 0.6.4
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/CHANGELOG.md +369 -0
- package/LICENSE +21 -0
- package/README.md +76 -0
- package/dist/auto.cjs +1 -0
- package/dist/auto.d.cts +2 -0
- package/dist/auto.d.ts +2 -0
- package/dist/auto.global.js +1 -0
- package/dist/auto.js +1 -0
- package/dist/chunk-6DXNWAGS.js +1 -0
- package/dist/chunk-LWKH66VY.js +1 -0
- package/dist/head.cjs +1 -0
- package/dist/head.d.cts +2 -0
- package/dist/head.d.ts +2 -0
- package/dist/head.global.js +1 -0
- package/dist/head.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.global.js +1 -0
- package/dist/index.js +1 -0
- package/dist/plugins.cjs +1 -0
- package/dist/plugins.d.cts +328 -0
- package/dist/plugins.d.ts +328 -0
- package/dist/plugins.js +1 -0
- package/dist/types-BYVnuPvd.d.cts +64 -0
- package/dist/types-BYVnuPvd.d.ts +64 -0
- package/llms.txt +204 -0
- package/package.json +83 -0
package/llms.txt
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# prop-for-that
|
|
2
|
+
|
|
3
|
+
> Expose runtime state that JavaScript knows but CSS can't see, as batched, diffed
|
|
4
|
+
> CSS custom properties. CSS then computes and reacts to it via `var()` (continuous
|
|
5
|
+
> values) or `@container style()` (discrete values), with no JS in the animation path.
|
|
6
|
+
|
|
7
|
+
prop-for-that reads browser/runtime state (pointer, viewport, element size,
|
|
8
|
+
visibility, slider values, network, battery, sensors, and more) and writes it into
|
|
9
|
+
`--live-*` (reactive) and `--const-*` (write-once) custom properties. A single
|
|
10
|
+
`requestAnimationFrame` writer coalesces all updates and only calls `setProperty`
|
|
11
|
+
when a value actually changed. Zero runtime dependencies, tree-shakeable, TypeScript.
|
|
12
|
+
|
|
13
|
+
## Entry points
|
|
14
|
+
|
|
15
|
+
- `prop-for-that`: the core API (`configure`, `register`, `unregister`, `propsFor`, `unbind`, `reset`).
|
|
16
|
+
- `prop-for-that/auto`: side-effecting. On load it attaches the default globals (`viewport`, `pointer`) to `:root`, scans the DOM for `[data-props-for="key1 key2"]` and binds those sources, and watches the DOM with a `MutationObserver`. If the root `<html>` has the boolean attribute `data-props-typed`, it calls `configure({ typed: true })` first (markup equivalent; read once on load; global, no per-key subset).
|
|
17
|
+
- `prop-for-that/head`: side-effecting. Synchronously writes FOUC-safe constants before first paint. Inline it in `<head>`.
|
|
18
|
+
- `prop-for-that/plugins`: opt-in plugin sources, plus `registerPlugins` and `allPlugins`.
|
|
19
|
+
|
|
20
|
+
Build outputs: ESM + CJS + `.d.ts`. Browser-only; entries guard `typeof document`, so importing is SSR-safe (sources attach client-side).
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm i prop-for-that
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Mental model
|
|
29
|
+
|
|
30
|
+
1. A **source** reads one group of state. It has a `key` (used in `propsFor`/`data-props-for`), a `scope` (`global` → writes to `:root`; `element` → writes to the bound element), and a `start(ctx)` that attaches listeners/observers and returns a disposer.
|
|
31
|
+
2. Sources call `ctx.write(localName, value, cadence?)`, never `setProperty` directly. The **Writer** queues writes and flushes once per `requestAnimationFrame`, diffing against the last value written.
|
|
32
|
+
3. CSS consumes the resulting custom properties:
|
|
33
|
+
- **`var()`** for continuous values (ratios, dimensions), composed with `calc()`.
|
|
34
|
+
- **`@container style()`** for discrete/boolean/integer values (equality match). Every element is a style-query container by default; no `container-type` needed.
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { configure, register, unregister, propsFor, unbind, reset, pause, resume } from 'prop-for-that'
|
|
40
|
+
|
|
41
|
+
configure(opts: Partial<Config>): void // call once, before any propsFor()
|
|
42
|
+
register(source: Source): void // add a custom/plugin source by key
|
|
43
|
+
unregister(key: SourceKey): void // remove a source from the registry
|
|
44
|
+
propsFor(keys: string[]): Disposer // global: attach sources to config.root (:root)
|
|
45
|
+
propsFor(target: Element | NodeList | Element[], keys: string[]): Disposer // per element(s)
|
|
46
|
+
unbind(target: HTMLElement, keys?: string[]): void // detach some/all
|
|
47
|
+
reset(): void // tear down every binding + shared observers/listeners
|
|
48
|
+
pause(): void // freeze the loop (no sampling/flushing); idempotent
|
|
49
|
+
resume(): void // unfreeze; flushes anything queued while paused
|
|
50
|
+
|
|
51
|
+
// propsFor is global unless the first arg is a Node, NodeList, or array of elements.
|
|
52
|
+
// Its disposer tears down only what that call started and removes the properties it wrote.
|
|
53
|
+
|
|
54
|
+
interface Config { livePrefix: string; constPrefix: string; root: HTMLElement; typed: boolean; defaults?: Record<string, string|number>; liveHz?: number }
|
|
55
|
+
// defaults: livePrefix '--live-', constPrefix '--const-', root document.documentElement, typed false, liveHz unset (every frame)
|
|
56
|
+
// config.defaults are typed @property initial values, keyed by a source's local name
|
|
57
|
+
// liveHz caps loop sampling+flushing rate (e.g. 30); fewer writes = less style recalc + calmer DevTools
|
|
58
|
+
|
|
59
|
+
interface Source {
|
|
60
|
+
key: SourceKey
|
|
61
|
+
scope: 'global' | 'element'
|
|
62
|
+
start(ctx: SourceContext): Disposer
|
|
63
|
+
}
|
|
64
|
+
interface SourceContext {
|
|
65
|
+
target: HTMLElement
|
|
66
|
+
config: Config
|
|
67
|
+
write(localName: string, value: string | number, cadence?: 'live' | 'const'): void
|
|
68
|
+
}
|
|
69
|
+
type Disposer = () => void
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Plugins:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { registerPlugins, allPlugins, battery /* …named exports */ } from 'prop-for-that/plugins'
|
|
76
|
+
|
|
77
|
+
registerPlugins() // register every plugin
|
|
78
|
+
registerPlugins(battery, clock) // register a subset
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`propsFor()` returns a disposer; re-attaching an already-active key on the same target is a no-op.
|
|
82
|
+
|
|
83
|
+
## Variable catalog (canonical)
|
|
84
|
+
|
|
85
|
+
All names below are the full property names. Reactive values use the `--live-`
|
|
86
|
+
prefix; constants use `--const-`. Values are unitless numbers unless noted.
|
|
87
|
+
|
|
88
|
+
### Core sources (in the main bundle)
|
|
89
|
+
|
|
90
|
+
| key | scope | properties |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `viewport` | global | `--live-vw`, `--live-vh` |
|
|
93
|
+
| `pointer` | global | `--live-pointer-x`, `--live-pointer-y`, `--live-pointer-x-ratio` (0–1), `--live-pointer-y-ratio` (0–1) |
|
|
94
|
+
| `size` | element | `--live-w`, `--live-h`, `--live-aspect` (w/h) |
|
|
95
|
+
| `visibility` | element | `--live-visible` (1/0, whole element in viewport), `--const-has-entered` (1/0, latches once entirely in viewport, never resets) |
|
|
96
|
+
| `range` | element | `--live-value`, `--live-value-pct` (0–1). Bind the `<input>` or a container holding one. |
|
|
97
|
+
|
|
98
|
+
### Head constants (`prop-for-that/head`)
|
|
99
|
+
|
|
100
|
+
| property | value |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `--const-scrollbar-w` | scrollbar width in px |
|
|
103
|
+
| `--const-scrollbar-thin-w` | scrollbar width in px with `scrollbar-width: thin` (= `--const-scrollbar-w` where unsupported) |
|
|
104
|
+
| `--const-dpr` | `devicePixelRatio` |
|
|
105
|
+
| `--const-cores` | `navigator.hardwareConcurrency` |
|
|
106
|
+
| `--const-mem` | `navigator.deviceMemory` in GiB (Chromium-only, coarse; `0` elsewhere) |
|
|
107
|
+
|
|
108
|
+
### Plugins (`prop-for-that/plugins`)
|
|
109
|
+
|
|
110
|
+
Import name is camelCase; the key for `propsFor`/`data-props-for` is the dashed form.
|
|
111
|
+
|
|
112
|
+
| import | key | scope | properties |
|
|
113
|
+
| --- | --- | --- | --- |
|
|
114
|
+
| `scrollVelocity` | `scroll-velocity` | global | `--live-scroll-velocity` (signed px/frame), `--live-scroll-direction` (1/-1/0) |
|
|
115
|
+
| `online` | `online` | global | `--live-online` (1/0) |
|
|
116
|
+
| `pageFocused` | `page-focused` | global | `--live-page-focused` (1/0 — tab frontmost and window focused; `0` when switched away) |
|
|
117
|
+
| `pageVisible` | `page-visible` | global | `--live-page-visible` (1/0 — tab foreground vs hidden/backgrounded; `document.visibilityState`. A visible tab can still be unfocused) |
|
|
118
|
+
| `navType` | `nav-type` | global | `--const-nav-type` (write-once string — how the user arrived: `navigate` / `reload` / `back_forward` / `prerender`, from `performance.getEntriesByType('navigation')[0].type`. Pairs with `@container style(--const-nav-type: reload)`) |
|
|
119
|
+
| `network` | `network` | global | `--live-net-downlink`, `--live-net-rtt`, `--live-net-save-data` (1/0), `--live-net-type` (slow-2g=1…4g=4, else 0) |
|
|
120
|
+
| `battery` | `battery` | global | `--live-battery-level` (0–1), `--live-battery-charging` (1/0) |
|
|
121
|
+
| `clock` | `clock` | global | `--live-now` (epoch seconds), `--live-hours`, `--live-minutes`, `--live-seconds` |
|
|
122
|
+
| `fps` | `fps` | global | `--live-fps` |
|
|
123
|
+
| `visualViewport` | `visual-viewport` | global | `--live-vvp-scale`, `--live-vvp-offset-top`, `--live-vvp-height` |
|
|
124
|
+
| `orientation` | `orientation` | global | `--live-orient-alpha`, `--live-orient-beta`, `--live-orient-gamma` (deg) |
|
|
125
|
+
| `motion` | `motion` | global | `--live-accel-x`, `--live-accel-y`, `--live-accel-z` (m/s²) |
|
|
126
|
+
| `geo` | `geo` | global | `--live-geo-lat`, `--live-geo-lng`, `--live-geo-accuracy` (m) |
|
|
127
|
+
| `cpuPressure` | `cpu-pressure` | global | `--live-cpu-pressure` (Compute Pressure tier: nominal=0, fair=1, serious=2, critical=3) |
|
|
128
|
+
| `pointerLocal` | `pointer-local` | element | `--live-local-pointer-x-ratio`, `--live-local-pointer-y-ratio` (0–1 within the element), `--live-local-pointer-inside` (1/0) |
|
|
129
|
+
| `media` | `media` | element | `--live-current-time`, `--live-duration`, `--live-progress` (0–1), `--live-paused` (1/0), `--live-volume` (0–1) |
|
|
130
|
+
| `field` | `field` | element | `--live-length`, `--live-empty` (1/0), `--live-valid` (1/0); per-reason validity flags (each 1/0) `--live-value-missing`, `--live-type-mismatch`, `--live-pattern-mismatch`, `--live-too-long`, `--live-too-short`, `--live-range-underflow`, `--live-range-overflow`, `--live-step-mismatch`, `--live-bad-input`, `--live-custom-error`; and with `maxlength`: `--live-remaining`, `--live-fill-pct` (0–1) |
|
|
131
|
+
| `select` | `select` | element | `--live-index` (selectedIndex, -1 if none), `--live-option-count`, `--live-index-pct` (0–1), `--live-value-num` (numeric value only), `--live-selected-count`, `--live-selected-pct` (0–1, counts a `<select multiple>` CSS can't tally). Bind the `<select>` or a container. |
|
|
132
|
+
| `colorInput` | `color-input` | element | `--live-color` (the `<input type="color">` value as sRGB hex; typed mode registers it `<color>`). Bind the input or a container. |
|
|
133
|
+
| `fieldState` | `field-state` | element | form interaction history (all 1/0): `--live-dirty`/`--live-pristine` (user has edited it; latches), `--live-touched`/`--live-untouched` (blurred at least once; latches), `--live-changed` (current value ≠ mount value; un-latches), `--live-submitted` (owning `<form>` submitted). Bind a single field for its state, or a `<form>`/wrapper for the aggregate over all its fields. |
|
|
134
|
+
| `formState` | `form-state` | element | form-level validity/completion CSS can't count: `--live-field-count`, `--live-valid-count`, `--live-invalid-count`, `--live-all-valid` (1/0 submit gate), `--live-completion` (0–1, valid required ÷ required). Bind a `<form>`/wrapper. |
|
|
135
|
+
| `img` | `img` | element | `--live-natural-w`, `--live-natural-h` (intrinsic px), `--live-loaded` (1/0), `--live-broken` (1/0). Bind the `<img>` or a container holding one. |
|
|
136
|
+
| `imgColor` | `img-color` | element | a palette from an `<img>`, all from one 16×16 bucketing pass (createImageBitmap+OffscreenCanvas). Each swatch is a single sRGB hex colour (no channel props — use relative colour syntax / color-mix to extract): `--live-img` (dominant), `--live-img-accent` (most vibrant), `--live-img-dark` (darkest non-black), `--live-img-light` (lightest non-white), `--live-img-avg` (mean). Plus `--live-img-temp` (−1 cool…+1 warm). Accent reuses the dominant for grayscale. Cross-origin needs `crossorigin` + CORS, else no-ops. Bind the `<img>` or a container. |
|
|
137
|
+
| `videoColor` | `video-color` | element | live colours of a playing `<video>`, each a single sRGB hex colour: `--live-video` (dominant) + `--live-video-accent` (most vibrant; reuses the dominant for a grayscale frame). Both from one 16×16 read on `requestVideoFrameCallback` (stops when paused/offscreen/backgrounded), throttled to ~4 Hz; seeds a paused/poster frame; falls back to `timeupdate`. Cross-origin needs `crossorigin` + CORS, else no-ops. Bind the `<video>` or a container. |
|
|
138
|
+
|
|
139
|
+
## Recipes
|
|
140
|
+
|
|
141
|
+
Zero-config (attributes):
|
|
142
|
+
|
|
143
|
+
```html
|
|
144
|
+
<script type="module">import 'prop-for-that/auto'</script>
|
|
145
|
+
<input type="range" data-props-for="range">
|
|
146
|
+
<section data-props-for="size visibility">…</section>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Imperative:
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
import { propsFor } from 'prop-for-that'
|
|
153
|
+
propsFor(['pointer']) // writes pointer vars to :root
|
|
154
|
+
propsFor(el, ['size', 'visibility']) // writes element vars to el
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
A plugin:
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
import { register, propsFor } from 'prop-for-that'
|
|
161
|
+
import { battery } from 'prop-for-that/plugins'
|
|
162
|
+
register(battery)
|
|
163
|
+
propsFor(['battery'])
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Container-bound range (so siblings can read the value):
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
// the source finds the inner <input> but writes the vars on the wrapper
|
|
170
|
+
propsFor(document.querySelector('.meter'), ['range'])
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Continuous reaction with `var()`:
|
|
174
|
+
|
|
175
|
+
```css
|
|
176
|
+
.card { transform: rotateY(calc((var(--live-pointer-x-ratio) - 0.5) * 16deg)); }
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Discrete reaction with a style query:
|
|
180
|
+
|
|
181
|
+
```css
|
|
182
|
+
@container style(--live-online: 0) { .banner { display: block; } }
|
|
183
|
+
@container style(--live-value: 100) { .badge { color: var(--accent); } }
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Gotchas (read before writing CSS)
|
|
187
|
+
|
|
188
|
+
- **Custom properties inherit downward only.** An `element`-scoped source writes its vars on the bound element. To let *sibling* elements react, bind a common ancestor. `range` and `field` help here: bind them to a container and they find the inner `<input>`, writing the vars on the container.
|
|
189
|
+
- **Pick the right consumer.** Continuous numbers go through `var()` + `calc()`. Discrete/boolean/integer values use `@container style()`, which matches on **equality only** (range comparisons like `style(--x < 5)` are not stable yet). Emit booleans/tiers when you need thresholds.
|
|
190
|
+
- **`visibility` is binary + latched, not a ratio.** It writes `--live-visible` and `--const-has-entered`. There is no continuous visible-ratio and no scroll-position source: use native `animation-timeline: scroll()` / `view()` for continuous scroll-driven effects.
|
|
191
|
+
- **Values are unitless.** Multiply by `1px`, `1deg`, `100%`, etc. in CSS.
|
|
192
|
+
- **Configure prefixes before attaching.** `configure({ livePrefix, constPrefix })` must run before any `propsFor()`.
|
|
193
|
+
- **Typed properties are opt-in.** `configure({ typed: true })` (before attaching) registers each written `--live-*` with `@property` so it interpolates (consumers add `transition`/`@keyframes`) and resolves to `0` before a value arrives. With the `auto` entry, `<html data-props-typed>` is the markup equivalent (boolean, read once on load; typing is global per `@property` name, so no per-key subset). It is a one-way door (no unregister), uses `inherits: true`, is feature-detected, and skips names already registered. Sources can declare per-property `props: { name: { syntax, initial, inherits } }` (default `<number>` / `0` / inherited); consumers can set initials with `configure({ typed: true, defaults: { 'pointer-x-ratio': 0.5 } })` (keyed by local name).
|
|
194
|
+
- **Permission-gated plugins** (`orientation`, `motion`, `geo`) and unsupported APIs feature-detect and no-op; registering them is always safe. On iOS some need a user-gesture permission grant before values arrive. `cpuPressure` is Chromium-only and needs a secure context + the `compute-pressure` Permissions Policy; it seeds `--live-cpu-pressure: 0` where supported, writes nothing where not.
|
|
195
|
+
- **Global writes land in an adopted stylesheet, not `<html>` inline style.** Root `--live-*` go into one constructable, adopted `:root {}` rule (element-scoped writes stay inline; the `head` entry still writes `--const-*` inline for first paint). Keeps the DevTools Styles panel usable under per-frame churn; `var()`/`calc()` consumption is identical (still inherits). Reading `documentElement.style` directly won't show them — read computed style. Falls back to inline where constructable stylesheets are unsupported.
|
|
196
|
+
- **Freeze or throttle the loop.** `pause()` / `resume()` stop and restart sampling+flushing (values hold steady; bindings stay attached). `configure({ liveHz: 30 })` caps the rate to reduce mutations/recalc, throttling samplers (`fps`, `scroll-velocity`) too.
|
|
197
|
+
|
|
198
|
+
## Links
|
|
199
|
+
|
|
200
|
+
- [Documentation](https://prop-for-that.netlify.app/docsite/): full guides, concepts, and API.
|
|
201
|
+
- [Plugin & source reference](https://prop-for-that.netlify.app/docsite/reference/plugins/): every source, key, and property.
|
|
202
|
+
- [Live demos](https://prop-for-that.netlify.app/): interactive examples of each source.
|
|
203
|
+
- [Under consideration](https://prop-for-that.netlify.app/docsite/considered/): deferred/proposed sources and voting.
|
|
204
|
+
- [Repository](https://github.com/argyleink/prop-for-that): source, issues, changelog, contributing.
|
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prop-for-that",
|
|
3
|
+
"version": "0.6.4",
|
|
4
|
+
"description": "Expose what JavaScript knows but CSS can't see, as batched, diffed CSS custom properties.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/argyleink/prop-for-that.git"
|
|
10
|
+
},
|
|
11
|
+
"author": "Adam Argyle (https://github.com/argyleink)",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"css",
|
|
14
|
+
"custom-properties",
|
|
15
|
+
"css-variables",
|
|
16
|
+
"reactive",
|
|
17
|
+
"state",
|
|
18
|
+
"dom",
|
|
19
|
+
"battery",
|
|
20
|
+
"network",
|
|
21
|
+
"geolocation",
|
|
22
|
+
"device-orientation",
|
|
23
|
+
"scroll-velocity",
|
|
24
|
+
"fps"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": [
|
|
27
|
+
"./dist/auto.js",
|
|
28
|
+
"./dist/auto.cjs",
|
|
29
|
+
"./dist/head.js",
|
|
30
|
+
"./dist/head.cjs"
|
|
31
|
+
],
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
},
|
|
38
|
+
"./auto": {
|
|
39
|
+
"types": "./dist/auto.d.ts",
|
|
40
|
+
"import": "./dist/auto.js",
|
|
41
|
+
"require": "./dist/auto.cjs"
|
|
42
|
+
},
|
|
43
|
+
"./head": {
|
|
44
|
+
"types": "./dist/head.d.ts",
|
|
45
|
+
"import": "./dist/head.js",
|
|
46
|
+
"require": "./dist/head.cjs"
|
|
47
|
+
},
|
|
48
|
+
"./plugins": {
|
|
49
|
+
"types": "./dist/plugins.d.ts",
|
|
50
|
+
"import": "./dist/plugins.js",
|
|
51
|
+
"require": "./dist/plugins.cjs"
|
|
52
|
+
},
|
|
53
|
+
"./package.json": "./package.json"
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"llms.txt",
|
|
58
|
+
"CHANGELOG.md"
|
|
59
|
+
],
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public",
|
|
62
|
+
"provenance": true
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "tsup",
|
|
66
|
+
"build:demos": "cd demos && npm install && npm run build",
|
|
67
|
+
"build:docs": "cd docs && npm install && DOCS_BASE=/docsite npm run build",
|
|
68
|
+
"build:site": "npm run build:demos && npm run build:docs && node scripts/assemble-site.mjs",
|
|
69
|
+
"dev": "tsup --watch",
|
|
70
|
+
"typecheck": "tsc --noEmit",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"test:watch": "vitest",
|
|
73
|
+
"test:e2e": "playwright test",
|
|
74
|
+
"prepublishOnly": "npm run build"
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"@playwright/test": "^1.49.1",
|
|
78
|
+
"jsdom": "^25.0.1",
|
|
79
|
+
"tsup": "^8.3.5",
|
|
80
|
+
"typescript": "^5.7.2",
|
|
81
|
+
"vitest": "^2.1.8"
|
|
82
|
+
}
|
|
83
|
+
}
|