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/CHANGELOG.md
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **prop-for-that** are recorded here. Format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/). While the package is `0.x`, a
|
|
5
|
+
**minor** bump signals a breaking change and a **patch** bump signals a
|
|
6
|
+
backwards-compatible change (semver's `1.0.0`+ rules kick in at v1).
|
|
7
|
+
|
|
8
|
+
Only the published library (`dist/`) is versioned here; the demo and docs site
|
|
9
|
+
are repo-only and not part of the npm package.
|
|
10
|
+
|
|
11
|
+
## [0.6.4]
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- **`nav-type` plugin** — `--const-nav-type`: how the user arrived at the page,
|
|
15
|
+
written once as a string (`navigate` / `reload` / `back_forward` / `prerender`)
|
|
16
|
+
from `performance.getEntriesByType('navigation')[0].type`. Pairs with style
|
|
17
|
+
queries — `@container style(--const-nav-type: reload) { … }`. Global scope,
|
|
18
|
+
`const` cadence; typed mode registers it as a `<custom-ident>`. Import as
|
|
19
|
+
`navType` from `prop-for-that/plugins`. (Rides the batched writer, so it lands
|
|
20
|
+
the frame after bind — read the same value in a `<head>` script if you need it
|
|
21
|
+
before first paint.)
|
|
22
|
+
|
|
23
|
+
## [0.6.3]
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **`page-visible` plugin** — `--live-page-visible` (1/0): whether the tab is in
|
|
27
|
+
the foreground vs hidden (backgrounded, minimized, switched away). The companion
|
|
28
|
+
to `page-focused` — a *visible* tab can still be *unfocused* — for pausing video,
|
|
29
|
+
polling, or expensive effects when the page is truly hidden. Global scope, seeded
|
|
30
|
+
from `document.visibilityState` and driven by `visibilitychange`. Import as
|
|
31
|
+
`pageVisible` from `prop-for-that/plugins`.
|
|
32
|
+
- Internal: `onDocument` — a shared, ref-counted passive `document`-listener helper
|
|
33
|
+
(the document-target twin of `onWindow`), so sources can subscribe to
|
|
34
|
+
`document`-only events (`visibilitychange`, Page Lifecycle `freeze`/`resume`)
|
|
35
|
+
without a raw `addEventListener`.
|
|
36
|
+
|
|
37
|
+
## [0.6.2]
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
- **`page-focused` plugin** — `--live-page-focused` (1/0): whether the document
|
|
41
|
+
has focus (tab frontmost *and* window focused). Goes `0` when the user switches
|
|
42
|
+
to another tab, window, or app, and `1` on return. Global scope, seeded from
|
|
43
|
+
`document.hasFocus()` and driven by window `focus`/`blur`. Import as
|
|
44
|
+
`pageFocused` from `prop-for-that/plugins`.
|
|
45
|
+
|
|
46
|
+
## [0.6.1]
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- **`--const-mem` head constant** — `prop-for-that/head` now writes
|
|
50
|
+
`navigator.deviceMemory` (approximate device RAM in GiB) alongside the existing
|
|
51
|
+
scrollbar/DPR/core constants. Chromium-only and deliberately coarse (`0.25`–`8`,
|
|
52
|
+
capped for fingerprinting resistance); falls back to `0` where unsupported,
|
|
53
|
+
matching the `--const-cores` pattern.
|
|
54
|
+
|
|
55
|
+
## [0.6.0]
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- **`pointer-local` plugin — renamed its emitted properties (breaking).**
|
|
59
|
+
`--live-px` → `--live-local-pointer-x-ratio`, `--live-py` →
|
|
60
|
+
`--live-local-pointer-y-ratio`, `--live-pointer-inside` →
|
|
61
|
+
`--live-local-pointer-inside`. The element-scoped pointer now shares the
|
|
62
|
+
`pointer` namespace with a `local-` qualifier, so the two are distinguishable
|
|
63
|
+
at a glance, and the `-ratio` suffix keeps units honest against the viewport
|
|
64
|
+
`pointer` source (`--live-pointer-x` is pixels; `*-ratio` is 0–1). The global
|
|
65
|
+
`pointer` source's properties are unchanged. Update any CSS reading the old
|
|
66
|
+
names.
|
|
67
|
+
|
|
68
|
+
## [0.5.2]
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
- **`select` plugin** (`prop-for-that/plugins`) — a native `<select>`'s state as
|
|
72
|
+
numbers CSS can't reach: `--live-index` (`selectedIndex`, `-1` if none),
|
|
73
|
+
`--live-option-count`, `--live-index-pct` (0–1), `--live-value-num`
|
|
74
|
+
(`Number(value)`, only when the value is numeric), `--live-selected-count` and
|
|
75
|
+
`--live-selected-pct` (0–1) — the multi-select tally `:checked` can't count.
|
|
76
|
+
Turns a `<select>` into a discrete CSS state machine (slide a segmented
|
|
77
|
+
indicator off `--live-index`) or drives layout off the chosen value. Bind the
|
|
78
|
+
`<select>` or a container.
|
|
79
|
+
- **`color-input` plugin** (`prop-for-that/plugins`) — `--live-color`, the colour
|
|
80
|
+
chosen in an `<input type="color">` as one sRGB hex string (CSS otherwise can't
|
|
81
|
+
read it); extract channels with relative colour syntax / `color-mix()`. Typed
|
|
82
|
+
mode registers it `<color>` so a picker can live-theme + interpolate a region
|
|
83
|
+
with zero consumer JS. Bind the input or a container.
|
|
84
|
+
- **`field` plugin extended** — the per-reason `ValidityState` flags `:invalid`
|
|
85
|
+
can't distinguish (each 1/0): `--live-value-missing`, `--live-type-mismatch`,
|
|
86
|
+
`--live-pattern-mismatch`, `--live-too-long`, `--live-too-short`,
|
|
87
|
+
`--live-range-underflow`, `--live-range-overflow`, `--live-step-mismatch`,
|
|
88
|
+
`--live-bad-input`, `--live-custom-error`; plus a `maxlength` budget when one is
|
|
89
|
+
set: `--live-remaining` (chars left) and `--live-fill-pct` (0–1) for a pure-CSS
|
|
90
|
+
character counter. The budget props aren't written without a `maxlength`, so
|
|
91
|
+
keep a `var()` fallback.
|
|
92
|
+
|
|
93
|
+
## [0.5.1]
|
|
94
|
+
|
|
95
|
+
### Added
|
|
96
|
+
- **`data-props-typed` on the root `<html>`** — the markup equivalent of
|
|
97
|
+
`configure({ typed: true })` for the `auto` entry. Read once on load, it
|
|
98
|
+
registers every written `--live-*` as an interpolatable `@property`, so
|
|
99
|
+
HTML-only (`data-props-for`) pages can opt into typed values without touching
|
|
100
|
+
JS. It's a boolean: `@property` is registered per name for the whole document,
|
|
101
|
+
so typing is all-or-nothing and any attribute value is ignored (there's no
|
|
102
|
+
per-key subset, matching the JS API). For per-property initial values, use the
|
|
103
|
+
JS `configure({ defaults })`.
|
|
104
|
+
|
|
105
|
+
## [0.5.0]
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
- **BREAKING: `imgColor` and `videoColor` now emit single `#rrggbb` colours, not
|
|
109
|
+
RGB channels.** The canvas pixels are sRGB, so a hex colour is sufficient — and
|
|
110
|
+
CSS already extracts whatever channels you need from a colour with relative
|
|
111
|
+
colour syntax (`oklch(from var(--live-img) l c h)`) or `color-mix()`, so sharing
|
|
112
|
+
separate channel props was redundant. This replaces the per-channel `r` / `g` /
|
|
113
|
+
`b` props and the `l` luminance prop:
|
|
114
|
+
- `imgColor`: `--live-img`, `--live-img-accent`, `--live-img-dark`,
|
|
115
|
+
`--live-img-light`, `--live-img-avg` (each was `…-r` / `-g` / `-b` / `-l`).
|
|
116
|
+
`--live-img-temp` is unchanged.
|
|
117
|
+
- `videoColor`: `--live-video`, `--live-video-accent` (each was `…-r/g/b/l`).
|
|
118
|
+
- To pick legible text, derive it from the colour's own lightness instead of a
|
|
119
|
+
luminance prop, e.g. `color: oklch(from var(--live-img) clamp(0, (0.6 - l) * 9, 1) 0 0)`.
|
|
120
|
+
- Both sources now declare `@property` specs (`<color>`), so the live colours
|
|
121
|
+
interpolate smoothly under `configure({ typed: true })`.
|
|
122
|
+
|
|
123
|
+
## [0.4.6]
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
- **`videoColor` now also writes a live accent colour** — `--live-video-accent-r`
|
|
127
|
+
/ `-g` / `-b` / `-l`, the most vibrant colour of the current frame (reuses the
|
|
128
|
+
dominant when a frame is essentially grayscale). It reuses the same `palette()`
|
|
129
|
+
pass as `imgColor`, so the accent is free beyond a few ops per sample; the plugin
|
|
130
|
+
stays dominant + accent only (no full palette) since a six-swatch extraction
|
|
131
|
+
isn't worth running 4×/second for an ambient glow. The existing
|
|
132
|
+
`--live-video-r/g/b/l` dominant props are unchanged.
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
- Removed the now-unused internal `dominantColor()` from `_color.ts`; `videoColor`
|
|
136
|
+
reads the dominant from `palette()` instead. Internal only — no public API or
|
|
137
|
+
behaviour change.
|
|
138
|
+
|
|
139
|
+
## [0.4.5]
|
|
140
|
+
|
|
141
|
+
### Added
|
|
142
|
+
- **`imgColor` now extracts a small palette**, not just the dominant colour. Four
|
|
143
|
+
new swatches, each in the same `r` / `g` / `b` (`0`–`255`) + `l` (luminance
|
|
144
|
+
`0`–`1`) shape as the dominant: `--live-img-accent-*` (the most vibrant colour —
|
|
145
|
+
reuses the dominant for a grayscale image), `--live-img-dark-*` (darkest
|
|
146
|
+
non-black), `--live-img-light-*` (lightest non-white), and `--live-img-avg-*`
|
|
147
|
+
(the mean of every pixel, vs the dominant's mode). Plus a scalar
|
|
148
|
+
`--live-img-temp` (`−1` cool … `+1` warm) from the image's red-vs-blue balance.
|
|
149
|
+
All of it falls out of the **same single 16×16 bucketing pass** — no extra image
|
|
150
|
+
reads — so it's barely dearer than before. The existing `--live-img-r/g/b/l`
|
|
151
|
+
dominant props are unchanged.
|
|
152
|
+
|
|
153
|
+
### Changed
|
|
154
|
+
- `_color.ts` gains a shared `buildBuckets()` helper and a `palette()` extractor;
|
|
155
|
+
`dominantColor()` (used by `videoColor`) is refactored onto it with no behaviour
|
|
156
|
+
change, so `videoColor` stays dominant-only and pays nothing for the new palette.
|
|
157
|
+
|
|
158
|
+
## [0.4.4]
|
|
159
|
+
|
|
160
|
+
### Added
|
|
161
|
+
- **`videoColor` plugin** (`prop-for-that/plugins`, key `video-color`, element).
|
|
162
|
+
The dominant colour of a playing `<video>` — `--live-video-r` / `-g` / `-b`
|
|
163
|
+
(`0`–`255`) plus `--live-video-l` (relative luminance `0`–`1`) — for an ambient
|
|
164
|
+
glow, scrim, or chrome that tracks the picture. Sampling rides
|
|
165
|
+
`requestVideoFrameCallback` (so it stops when the video is paused, offscreen, or
|
|
166
|
+
backgrounded) and is throttled to ~4 Hz on top; it seeds a paused/poster frame
|
|
167
|
+
on attach and falls back to the `timeupdate` event where
|
|
168
|
+
`requestVideoFrameCallback` is unavailable. The current frame is read 16×16 from
|
|
169
|
+
a canvas, reusing `img-color`'s dominant-colour path. Cross-origin video needs
|
|
170
|
+
`crossorigin="anonymous"` + permissive CORS headers, else the canvas is tainted
|
|
171
|
+
and the plugin writes nothing (`var()` fallbacks stay safe). Bind the `<video>`
|
|
172
|
+
or a container holding one.
|
|
173
|
+
|
|
174
|
+
### Changed
|
|
175
|
+
- The shared pixel-sampling + dominant-colour logic now lives in
|
|
176
|
+
`src/plugins/_color.ts`, reused by both `imgColor` and `videoColor`. No
|
|
177
|
+
behaviour change to `imgColor`.
|
|
178
|
+
|
|
179
|
+
## [0.4.3]
|
|
180
|
+
|
|
181
|
+
### Added
|
|
182
|
+
- **`formState` plugin** (`prop-for-that/plugins`, key `form-state`, element).
|
|
183
|
+
Form-level **validity & completion** that CSS can't compute — `:invalid` matches
|
|
184
|
+
one control, but CSS can't count across a form or gate on "all valid." Bind it to
|
|
185
|
+
a `<form>` (or wrapper) for `--live-field-count` (controls subject to constraint
|
|
186
|
+
validation), `--live-valid-count` / `--live-invalid-count`, `--live-all-valid`
|
|
187
|
+
(`1`/`0` — the submit gate), and `--live-completion` (`0`–`1`: valid required
|
|
188
|
+
controls ÷ required controls). Recomputes on `input`/`change`, and on the frame
|
|
189
|
+
after a `reset`. Pairs with `field-state` (interaction history) and `field`
|
|
190
|
+
(per-field `--live-valid`).
|
|
191
|
+
- **`imgColor` plugin** (`prop-for-that/plugins`, key `img-color`, element). The
|
|
192
|
+
**dominant colour** of an `<img>` (CSS can't read pixels): `--live-img-r` /
|
|
193
|
+
`--live-img-g` / `--live-img-b` (`0`–`255`) plus `--live-img-l` (relative
|
|
194
|
+
luminance `0`–`1`, to pick legible text). Sampled 16×16 via `createImageBitmap`
|
|
195
|
+
+ `OffscreenCanvas` (decode/downscale off the main thread, ~256 px read back),
|
|
196
|
+
with a `<canvas>` fallback; recomputed on load so a `src` swap updates it. Bind
|
|
197
|
+
the `<img>` or a container holding one. Cross-origin images need
|
|
198
|
+
`crossorigin="anonymous"` + CORS, else the canvas is tainted and the plugin
|
|
199
|
+
writes nothing — so keep a `var()` fallback. Kept separate from `img` so the
|
|
200
|
+
pixel-reading cost is opt-in.
|
|
201
|
+
|
|
202
|
+
## [0.4.2]
|
|
203
|
+
|
|
204
|
+
### Fixed
|
|
205
|
+
- **`fieldState`**: `--live-changed` now clears correctly after a form `reset`.
|
|
206
|
+
It's recomputed against each control's *default* value synchronously, instead
|
|
207
|
+
of re-read in a microtask — Chromium runs that microtask checkpoint *before* the
|
|
208
|
+
reset event reverts the control values, so `--live-changed` stayed stuck on after
|
|
209
|
+
a reset. `dirty` / `touched` / `submitted` already reset correctly; now `changed`
|
|
210
|
+
does too (handles text inputs, `<textarea>`, `<select>`, and checkbox/radio).
|
|
211
|
+
|
|
212
|
+
## [0.4.1]
|
|
213
|
+
|
|
214
|
+
### Added
|
|
215
|
+
- **`fieldState` plugin** (`prop-for-that/plugins`, key `field-state`, element).
|
|
216
|
+
The form interaction-history states libraries like Angular, Formik, and React
|
|
217
|
+
Hook Form track but CSS pseudo-classes can't express — all `1`/`0`:
|
|
218
|
+
`--live-dirty` / `--live-pristine` (has the user edited the field at all —
|
|
219
|
+
latches on first `input`/`change`), `--live-touched` / `--live-untouched`
|
|
220
|
+
(blurred at least once — latches on first `blur`), `--live-changed` (current
|
|
221
|
+
value differs from the value at mount — un-latches when typed back), and
|
|
222
|
+
`--live-submitted` (the owning `<form>` has been submitted — latches on
|
|
223
|
+
`submit`, clears on `reset`). Both latch pairs reset when the form is reset.
|
|
224
|
+
Bind a **single field** for that field's state, or a **`<form>` / wrapper** for
|
|
225
|
+
the *aggregate* over every field inside it (dirty/touched/changed if *any*
|
|
226
|
+
field is — like a framework form-group). Props land on the bound element, so a
|
|
227
|
+
label, hint, or submit button can reveal an error or enable only once
|
|
228
|
+
`--live-touched`/`--live-submitted`/`--live-dirty`. Validity stays in the
|
|
229
|
+
`field` plugin; focus stays in `:focus`.
|
|
230
|
+
|
|
231
|
+
## [0.4.0]
|
|
232
|
+
|
|
233
|
+
### Added
|
|
234
|
+
- **`--const-scrollbar-thin-w`** from the `head` entry: the scrollbar width when
|
|
235
|
+
`scrollbar-width: thin` is applied, measured alongside `--const-scrollbar-w`.
|
|
236
|
+
Falls back to the classic width where `scrollbar-width: thin` isn't supported.
|
|
237
|
+
- **`img` plugin** (`prop-for-that/plugins`, key `img`, element). For `<img>`:
|
|
238
|
+
`--live-natural-w` / `--live-natural-h` (intrinsic pixel size), `--live-loaded`
|
|
239
|
+
(`1`/`0`), `--live-broken` (`1`/`0`). Bind the image or a container holding one
|
|
240
|
+
(props land on the container, so a wrapper can show a skeleton while loading, a
|
|
241
|
+
fallback when broken, or set `aspect-ratio` from the natural size). Seeds from
|
|
242
|
+
`complete`/`naturalWidth` so already-cached images report correctly.
|
|
243
|
+
- **`cpuPressure` plugin** (`prop-for-that/plugins`, key `cpu-pressure`, global).
|
|
244
|
+
Exposes the CPU's [Compute Pressure](https://developer.mozilla.org/en-US/docs/Web/API/Compute_Pressure_API)
|
|
245
|
+
state as `--live-cpu-pressure`, an ordered tier (nominal=0, fair=1, serious=2,
|
|
246
|
+
critical=3) — use it to back off expensive CSS work as the CPU gets busy.
|
|
247
|
+
Chromium-only, secure-context, and gated by the `compute-pressure` Permissions
|
|
248
|
+
Policy; feature-detects and no-ops (seeding `0` where supported, writing nothing
|
|
249
|
+
where not) so `var(--live-cpu-pressure, 0)` is safe everywhere.
|
|
250
|
+
|
|
251
|
+
### Changed (breaking)
|
|
252
|
+
- **The auto-mode attribute is renamed `data-prop` → `data-props-for`.** The
|
|
253
|
+
zero-config `prop-for-that/auto` entry now scans for, observes, and binds
|
|
254
|
+
`[data-props-for="key1 key2"]` (was `[data-prop]`). Rename the attribute on every
|
|
255
|
+
element: `<div data-prop="size">` → `<div data-props-for="size">`. The value
|
|
256
|
+
syntax is unchanged — one or more space-separated source keys. The imperative
|
|
257
|
+
`propsFor()` API is unaffected.
|
|
258
|
+
- **`visibility` is now full-element, and its latch moved off the `live`
|
|
259
|
+
cadence.** Both signals key off *entire-element* containment instead of
|
|
260
|
+
first-pixel overlap, and the write-once latch is renamed:
|
|
261
|
+
- `--live-visible` (1/0) now flips only while the element is **entirely**
|
|
262
|
+
within the viewport (previously: any part overlapping). Still reactive.
|
|
263
|
+
- `--live-has-entered` → **`--const-has-entered`**. It's written once (latches
|
|
264
|
+
to 1 the first time the element is entirely in view, never resets), so it now
|
|
265
|
+
lives on the `const` cadence. Update CSS to read `var(--const-has-entered)`.
|
|
266
|
+
- The shared `IntersectionObserver` gains `threshold: [0, 1]` to detect full
|
|
267
|
+
containment. An element larger than the viewport can never be entirely
|
|
268
|
+
visible, so neither signal ever turns on for it.
|
|
269
|
+
|
|
270
|
+
## [0.3.0]
|
|
271
|
+
|
|
272
|
+
### Changed (breaking)
|
|
273
|
+
- **Global `--live-*` writes go to an adopted stylesheet, not `<html>` inline
|
|
274
|
+
style.** Values written to the document root through the rAF writer now land in
|
|
275
|
+
a single constructable, adopted stylesheet rule (`:root {}`) instead of the
|
|
276
|
+
`<html>` element's inline `style`. This stops the per-frame churn from making
|
|
277
|
+
the DevTools Styles panel unusable and from flashing the Elements tree.
|
|
278
|
+
**Consumption is unchanged** — the rule targets `:root`, so `var()` / `calc()`
|
|
279
|
+
still inherit and resolve identically. What changes: reading
|
|
280
|
+
`document.documentElement.style.getPropertyValue('--live-*')` directly no longer
|
|
281
|
+
reflects these values (read computed style instead), and their cascade origin
|
|
282
|
+
moves from inline to an author rule (so author CSS / `!important` can now win).
|
|
283
|
+
Falls back to inline style where constructable stylesheets aren't supported
|
|
284
|
+
(older engines, SSR). **Element-scoped** writes are unchanged (still inline), and
|
|
285
|
+
the synchronous `head` entry still writes its `--const-*` constants inline by
|
|
286
|
+
design (first paint).
|
|
287
|
+
|
|
288
|
+
### Added
|
|
289
|
+
- **`pause()` / `resume()`**: freeze the shared frame loop (no sampling, no
|
|
290
|
+
flushing) so live values hold steady — handy for inspecting them in DevTools
|
|
291
|
+
without churn, or halting work in a backgrounded tab — then pick back up.
|
|
292
|
+
Bindings stay attached; both are idempotent.
|
|
293
|
+
- **`configure({ liveHz })`**: optional cap (in Hz) on how often the loop samples
|
|
294
|
+
and flushes. Unset (default) runs every animation frame; e.g. `30` coalesces
|
|
295
|
+
writes to ≤30/sec for fewer style recalcs and a calmer DevTools panel, at the
|
|
296
|
+
cost of update smoothness. Throttles the whole loop, so per-frame samplers
|
|
297
|
+
(`fps`, `scroll-velocity`) measure at this rate too.
|
|
298
|
+
|
|
299
|
+
## [0.2.0]
|
|
300
|
+
|
|
301
|
+
### Changed (breaking)
|
|
302
|
+
- **Unified `global()` and `bind()` into a single `propsFor()`**. It is global
|
|
303
|
+
(writes to the configured root) unless the first argument is a `Node`,
|
|
304
|
+
`NodeList`, or array of elements, in which case it attaches per element. Its
|
|
305
|
+
disposer tears down exactly what that call started and removes the custom
|
|
306
|
+
properties it wrote. The old `global` and `bind` exports are **removed**.
|
|
307
|
+
- **The `config` object is no longer exported.** Read or change the prefixes and
|
|
308
|
+
root through `configure()`.
|
|
309
|
+
- **`visibility`** now writes binary, scroll-*triggered* state: `--live-visible`
|
|
310
|
+
(`1`/`0`) plus `--live-has-entered` (`1`/`0`, latches on first entry and never
|
|
311
|
+
resets). The continuous `--live-visible-ratio` is **removed**; use native
|
|
312
|
+
`animation-timeline: view()` for continuous scroll-driven effects.
|
|
313
|
+
- **`range`** is now container-aware: attach it to a wrapper and it finds the inner
|
|
314
|
+
`<input>`, writing `--live-value` / `--live-value-pct` on the **container** so
|
|
315
|
+
the input and sibling elements (gauges, readouts) can all read the value.
|
|
316
|
+
|
|
317
|
+
### Removed (breaking)
|
|
318
|
+
- **Global `scroll` source** (`--live-scroll-x` / `-y` / `-progress`): superseded
|
|
319
|
+
by native CSS scroll-driven animations (`animation-timeline: scroll()` /
|
|
320
|
+
`view()`), which run on the compositor.
|
|
321
|
+
- **`el-scroll` plugin**: superseded by native `scroll(self)` / `scroll(nearest)`
|
|
322
|
+
scroll timelines.
|
|
323
|
+
|
|
324
|
+
### Added
|
|
325
|
+
- **`propsFor()`**: one entry point for attaching sources, global or per element
|
|
326
|
+
(a single element, a `NodeList`, or an array). Returns a scoped disposer.
|
|
327
|
+
- **`reset()`**: tears down every active binding plus the shared observers and
|
|
328
|
+
listeners, for a clean slate (handy in tests and before hot reloads).
|
|
329
|
+
- **`unregister(key)`**: removes a source from the registry by key.
|
|
330
|
+
- **`SourceKey`** type export for the registry key.
|
|
331
|
+
- **Typed properties** via `configure({ typed: true })`: opt-in `@property`
|
|
332
|
+
registration of written `--live-*` values, so they interpolate (consumers add
|
|
333
|
+
`transition` / `@keyframes`) and resolve to a guaranteed `0` initial. It is
|
|
334
|
+
feature-detected, idempotent, and uses `inherits: true`; sources may declare
|
|
335
|
+
per-property `props` typings (default `<number>` / `0`), and consumers may set
|
|
336
|
+
initial values in the same call with `configure({ typed: true, defaults: {…} })`.
|
|
337
|
+
- `llms.txt`: a dense, agent-oriented reference, now included in the published package.
|
|
338
|
+
- **`field`** is now container-aware: attach it to a wrapper and it finds the inner
|
|
339
|
+
`input` / `textarea` / `select`, writing `--live-length` / `--live-empty` /
|
|
340
|
+
`--live-valid` on the **container** so sibling readers (a counter, a meter, a
|
|
341
|
+
status word) inherit them. Attaching directly to the field still works.
|
|
342
|
+
- **`media`** is now container-aware too: attach it to a wrapper and it finds the
|
|
343
|
+
inner `video` / `audio`, writing `--live-progress` / `--live-current-time` /
|
|
344
|
+
`--live-duration` / `--live-paused` / `--live-volume` on the **container** so
|
|
345
|
+
sibling readers (a progress ring, a scrubber) inherit them.
|
|
346
|
+
|
|
347
|
+
### Fixed
|
|
348
|
+
- Single shared `requestAnimationFrame` loop now drives the writer and every
|
|
349
|
+
sampler, instead of each source running its own.
|
|
350
|
+
- `scroll-velocity` idles when the page isn't scrolling, instead of polling every
|
|
351
|
+
frame.
|
|
352
|
+
- `fps` now reports a smoothed average rather than a jittery per-frame value.
|
|
353
|
+
- `clock` no longer drifts: it's anchored to wall-clock time each tick.
|
|
354
|
+
- One shared `pointermove` listener now feeds both `pointer` and `pointer-local`.
|
|
355
|
+
- A failing source is isolated: it no longer takes down other sources or the loop.
|
|
356
|
+
- Written custom properties are removed on teardown.
|
|
357
|
+
- Disposers tear down only what their call started, leaving other bindings intact.
|
|
358
|
+
|
|
359
|
+
## [0.1.0]
|
|
360
|
+
|
|
361
|
+
### Added
|
|
362
|
+
- Initial release. Batched, diffed `requestAnimationFrame` writer.
|
|
363
|
+
- Core sources: `viewport`, `scroll`, `pointer`, `size`, `visibility`, `range`.
|
|
364
|
+
- Entries: `prop-for-that` (API), `prop-for-that/auto` (`[data-prop]` scanning),
|
|
365
|
+
`prop-for-that/head` (sync FOUC-safe `--const-*`).
|
|
366
|
+
- 14 opt-in plugins under `prop-for-that/plugins` (`scroll-velocity`, `online`,
|
|
367
|
+
`network`, `battery`, `clock`, `fps`, `visual-viewport`, `el-scroll`,
|
|
368
|
+
`pointer-local`, `media`, `field`, `orientation`, `motion`, `geo`).
|
|
369
|
+
- Build: ESM + CJS + `.d.ts` via tsup; tree-shakeable; zero runtime deps.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Adam Argyle
|
|
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,76 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# prop-for-that
|
|
4
|
+
|
|
5
|
+
**Expose what JavaScript knows but CSS can't see — as live CSS custom properties.**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/prop-for-that)
|
|
8
|
+
[](https://bundlephobia.com/package/prop-for-that)
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
[**Docs**](https://prop-for-that.netlify.app/docsite/) · [**Demos**](https://prop-for-that.netlify.app/) · [**Changelog**](./CHANGELOG.md) · [**llms.txt**](https://prop-for-that.netlify.app/llms.txt)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
Sliders, pointer position, element visibility, viewport size, battery, network, sensors — JavaScript can read all of it; CSS can't. **prop-for-that** writes that runtime state into `--live-*` and `--const-*` custom properties — batched and diffed down to one `setProperty` per frame — so your CSS can compose and react to it with plain `calc()` and `var()`.
|
|
19
|
+
|
|
20
|
+
Zero dependencies. TypeScript. ESM + CJS. SSR-safe.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm i prop-for-that
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick start
|
|
27
|
+
|
|
28
|
+
```html
|
|
29
|
+
<script type="module">import 'prop-for-that/auto'</script>
|
|
30
|
+
|
|
31
|
+
<input type="range" data-props-for="range" />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```css
|
|
35
|
+
/* the slider paints itself from its own value — no event listeners, no render loop */
|
|
36
|
+
input {
|
|
37
|
+
background: hsl(calc(var(--live-value-pct) * 120) 80% 50%);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Bind any element with `data-props-for="key …"` and read its `--live-*` properties in CSS. That's the whole idea.
|
|
42
|
+
|
|
43
|
+
## Why
|
|
44
|
+
|
|
45
|
+
- **CSS does the work.** No per-element event handlers or render loops — bind once, compose in stylesheets.
|
|
46
|
+
- **Fast by design.** One `requestAnimationFrame` flush per frame, write-on-change diffing, and a single shared `ResizeObserver` / `IntersectionObserver` for the whole page.
|
|
47
|
+
- **Ship only what you use.** Five core sources are built in; everything else is an opt-in, tree-shakeable plugin.
|
|
48
|
+
- **Plays with the platform.** Opt into typed [`@property`](https://prop-for-that.netlify.app/docsite/concepts/typed-properties/) values for interpolation, or FOUC-safe constants written before first paint.
|
|
49
|
+
- **Tiny and dependency-free**, in every bundle format.
|
|
50
|
+
|
|
51
|
+
## What it can read
|
|
52
|
+
|
|
53
|
+
**Core** (always on): viewport, pointer, element size, visibility, and `<input type="range">` values.
|
|
54
|
+
|
|
55
|
+
**Plugins** (opt-in): battery, network, online status, page focus & visibility, navigation type, FPS, clock, scroll velocity, device orientation / motion, geolocation, CPU pressure, media playback, form & field state, select & color-picker values, and dominant + accent colors extracted from images and video — 20+ in all.
|
|
56
|
+
|
|
57
|
+
→ Every source, every property, and live demos are in the **[docs](https://prop-for-that.netlify.app/docsite/reference/plugins/)**.
|
|
58
|
+
|
|
59
|
+
## Three entry points
|
|
60
|
+
|
|
61
|
+
| Import | What it does |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `prop-for-that/auto` | Zero-config: attaches global state and binds every `data-props-for` element, kept in sync with the DOM. |
|
|
64
|
+
| `prop-for-that` | Imperative API — `propsFor()`, `register()`, `configure()` — for explicit control and teardown. |
|
|
65
|
+
| `prop-for-that/head` | Synchronous, FOUC-safe constants (scrollbar width, DPR, core count, device memory) before first paint. |
|
|
66
|
+
| `prop-for-that/plugins` | The opt-in plugin catalog. |
|
|
67
|
+
|
|
68
|
+
Full API and concepts: **[prop-for-that.netlify.app/docsite](https://prop-for-that.netlify.app/docsite/)**.
|
|
69
|
+
|
|
70
|
+
## For LLMs / AI tools
|
|
71
|
+
|
|
72
|
+
A condensed, single-file reference — entry points, the full variable catalog, recipes, and gotchas — lives at **[llms.txt](./llms.txt)**, hosted at [prop-for-that.netlify.app/llms.txt](https://prop-for-that.netlify.app/llms.txt) and shipped in the npm package (`node_modules/prop-for-that/llms.txt`).
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
MIT © [Adam Argyle](https://github.com/argyleink)
|
package/dist/auto.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var c={livePrefix:"--live-",constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0,typed:false};var h=new Set,z=null,l=0,w=false,D=false,F=0,E=()=>typeof requestAnimationFrame=="function";function b(e){if(l=0,D);let t=c.liveHz;if(E()&&t&&t>0&&e-F<1e3/t){l=requestAnimationFrame(b);return}if(F=e,w=true,h.size)for(let r of [...h])r(e);z?.(),w=false,h.size&&E()&&A();}function A(){l||w||D||(E()?l=requestAnimationFrame(b):b(0));}function R(){A();}function O(e){z=e;}var f;function Q(){if(f!==void 0||(f=null,typeof document>"u"||typeof CSSStyleSheet!="function"||!("adoptedStyleSheets"in document)))return f;try{let e=new CSSStyleSheet;e.replaceSync(":root{}"),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],f=e.cssRules[0].style;}catch{f=null;}return f}function a(e){if(typeof document<"u"&&e===document.documentElement){let t=Q();if(t)return t}return e.style}var M=class{pending=new Map;last=new WeakMap;set(t,r,n){let o=this.pending.get(t);if(o?.has(r)){o.set(r,n);return}this.last.get(t)?.get(r)!==n&&(o?o.set(r,n):this.pending.set(t,new Map([[r,n]])),R());}forget(t,r){this.last.get(t)?.delete(r),this.pending.get(t)?.delete(r);}flush=()=>{if(this.pending.size!==0){for(let[t,r]of this.pending){let n=this.last.get(t);n||this.last.set(t,n=new Map);let o=a(t);for(let[i,s]of r)n.get(i)!==s&&(o.setProperty(i,s),n.set(i,s));}this.pending.clear();}}},m=new M;O(m.flush);var P=new Set;function q(e,t,r){if(P.has(e)||typeof CSS>"u"||typeof CSS.registerProperty!="function")return;P.add(e);let n=t?r?.[t]:void 0,o=t?c.defaults?.[t]:void 0;try{CSS.registerProperty({name:e,syntax:n?.syntax??"<number>",inherits:n?.inherits??!0,initialValue:o!=null?String(o):n?.initial??"0"});}catch{}}var L=new Map;function y(e,t){let r=L.get(e);if(!r){let n=new Set,o=i=>{for(let s of [...n])s(i);};r={handlers:n,dispatch:o},L.set(e,r),window.addEventListener(e,o,{passive:true});}return r.handlers.add(t),()=>{r.handlers.delete(t),r.handlers.size===0&&(window.removeEventListener(e,r.dispatch),L.delete(e));}}var I={key:"viewport",scope:"global",start(e){let t=()=>{e.write("vw",window.innerWidth),e.write("vh",window.innerHeight);};return t(),y("resize",t)}};function p(e){return Math.round(e*1e4)/1e4}var W={key:"pointer",scope:"global",start(e){return y("pointermove",r=>{let n=r;e.write("pointer-x",n.clientX),e.write("pointer-y",n.clientY),e.write("pointer-x-ratio",p(n.clientX/window.innerWidth)),e.write("pointer-y-ratio",p(n.clientY/window.innerHeight));})}};var g,T=new WeakMap;function K(e,t){return g||(g=new ResizeObserver(r=>{for(let n of r)T.get(n.target)?.(n);})),T.set(e,t),g.observe(e),()=>{g.unobserve(e),T.delete(e);}}var v,x=new WeakMap;function N(e,t){return v||(v=new IntersectionObserver(r=>{for(let n of r)x.get(n.target)?.(n);},{threshold:[0,1]})),x.set(e,t),v.observe(e),()=>{v.unobserve(e),x.delete(e);}}var B={key:"size",scope:"element",start(e){return K(e.target,t=>{let r=t.borderBoxSize?.[0],n=r?r.inlineSize:t.contentRect.width,o=r?r.blockSize:t.contentRect.height;e.write("w",p(n)),e.write("h",p(o)),e.write("aspect",o>0?p(n/o):0);})}};var X={key:"visibility",scope:"element",start(e){let t=false;return e.write("visible",0),e.write("has-entered",0,"const"),N(e.target,r=>{let n=r.intersectionRatio>=1;e.write("visible",n?1:0),n&&!t&&(t=true,e.write("has-entered",1,"const"));})}};function Y(e,t){return e.matches(t)?e:e.querySelector(t)}var $={key:"range",scope:"element",start(e){let t=Y(e.target,'input[type="range"], input[type="number"]');if(!t)return ()=>{};let r=()=>{let n=t.min===""?0:Number(t.min),o=t.max===""?100:Number(t.max),i=Number(t.value);e.write("value",i),e.write("value-pct",o>n?p((i-n)/(o-n)):0);};return r(),t.addEventListener("input",r,{passive:true}),()=>t.removeEventListener("input",r)}};var j={viewport:I,pointer:W,size:B,visibility:X,range:$};var Z=()=>{},u=new Map,ee={...j};function G(e){Object.assign(c,e);}function te(e,t,r){return {target:e,config:c,write(n,o,i="live"){let s=(i==="const"?c.constPrefix:c.livePrefix)+n;t.add(s),c.typed&&q(s,n,r),m.set(e,s,String(o));}}}function U(e,t,r){let n=r.get(t);if(!n)return;n.dispose();let o=a(e);for(let i of n.written)o.removeProperty(i),m.forget(e,i);r.delete(t);}function re(e,t){let r=u.get(e);r||u.set(e,r=new Map);let n=[];for(let o of t){if(r.has(o))continue;let i=ee[o];if(!i){console.warn(`[prop-for-that] unknown source "${o}"`);continue}let s=new Set,C;try{C=i.start(te(e,s,i.props));}catch(J){console.error(`[prop-for-that] source "${o}" failed to start`,J);continue}r.set(o,{dispose:C,written:s}),n.push(o);}return ()=>{let o=u.get(e);if(o){for(let i of n)U(e,i,o);o.size===0&&u.delete(e);}}}function ne(e){return e instanceof Element?[e]:typeof NodeList<"u"&&e instanceof NodeList||typeof HTMLCollection<"u"&&e instanceof HTMLCollection||Array.isArray(e)?Array.from(e).filter(t=>t instanceof Element):[]}function oe(e){return Array.isArray(e)&&(e.length===0||typeof e[0]=="string")}function H(e,t){let r,n;if(t===void 0&&oe(e)?(r=c.root?[c.root]:[],n=e):(r=ne(e),n=t??[]),!r.length||!n.length)return Z;let o=r.map(i=>re(i,n));return ()=>{for(let i of o)i();}}function k(e,t){let r=u.get(e);if(r){for(let n of t??[...r.keys()])U(e,n,r);r.size===0&&u.delete(e);}}var ie=["viewport","pointer"],d=new WeakMap;function se(e){return (e.dataset.propsFor??"").split(/\s+/).filter(Boolean)}function S(e){let t=se(e),r=d.get(e)??[],n=r.filter(i=>!t.includes(i)),o=t.filter(i=>!r.includes(i));n.length&&k(e,n),o.length&&H(e,o),t.length?d.set(e,t):d.delete(e);}function V(e){let t=d.get(e);t&&(k(e,t),d.delete(e));}function ce(e){e instanceof HTMLElement&&(e.hasAttribute("data-props-for")&&S(e),e.querySelectorAll("[data-props-for]").forEach(S));}function pe(e){e instanceof HTMLElement&&(V(e),e.querySelectorAll("[data-props-for]").forEach(V));}function _(){document.documentElement.hasAttribute("data-props-typed")&&G({typed:true}),H(ie),document.querySelectorAll("[data-props-for]").forEach(S),new MutationObserver(e=>{for(let t of e){if(t.type==="attributes"&&t.target instanceof HTMLElement){S(t.target);continue}t.removedNodes.forEach(pe),t.addedNodes.forEach(ce);}}).observe(document.documentElement,{subtree:true,childList:true,attributes:true,attributeFilter:["data-props-for"]});}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",_,{once:true}):_());
|
package/dist/auto.d.cts
ADDED
package/dist/auto.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){'use strict';var c={livePrefix:"--live-",constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0,typed:false};var h=new Set,z=null,l=0,w=false,D=false,F=0,E=()=>typeof requestAnimationFrame=="function";function b(e){if(l=0,D);let t=c.liveHz;if(E()&&t&&t>0&&e-F<1e3/t){l=requestAnimationFrame(b);return}if(F=e,w=true,h.size)for(let r of [...h])r(e);z?.(),w=false,h.size&&E()&&A();}function A(){l||w||D||(E()?l=requestAnimationFrame(b):b(0));}function R(){A();}function O(e){z=e;}var f;function Q(){if(f!==void 0||(f=null,typeof document>"u"||typeof CSSStyleSheet!="function"||!("adoptedStyleSheets"in document)))return f;try{let e=new CSSStyleSheet;e.replaceSync(":root{}"),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],f=e.cssRules[0].style;}catch{f=null;}return f}function a(e){if(typeof document<"u"&&e===document.documentElement){let t=Q();if(t)return t}return e.style}var M=class{pending=new Map;last=new WeakMap;set(t,r,n){let o=this.pending.get(t);if(o?.has(r)){o.set(r,n);return}this.last.get(t)?.get(r)!==n&&(o?o.set(r,n):this.pending.set(t,new Map([[r,n]])),R());}forget(t,r){this.last.get(t)?.delete(r),this.pending.get(t)?.delete(r);}flush=()=>{if(this.pending.size!==0){for(let[t,r]of this.pending){let n=this.last.get(t);n||this.last.set(t,n=new Map);let o=a(t);for(let[i,s]of r)n.get(i)!==s&&(o.setProperty(i,s),n.set(i,s));}this.pending.clear();}}},m=new M;O(m.flush);var P=new Set;function q(e,t,r){if(P.has(e)||typeof CSS>"u"||typeof CSS.registerProperty!="function")return;P.add(e);let n=t?r?.[t]:void 0,o=t?c.defaults?.[t]:void 0;try{CSS.registerProperty({name:e,syntax:n?.syntax??"<number>",inherits:n?.inherits??!0,initialValue:o!=null?String(o):n?.initial??"0"});}catch{}}var L=new Map;function y(e,t){let r=L.get(e);if(!r){let n=new Set,o=i=>{for(let s of [...n])s(i);};r={handlers:n,dispatch:o},L.set(e,r),window.addEventListener(e,o,{passive:true});}return r.handlers.add(t),()=>{r.handlers.delete(t),r.handlers.size===0&&(window.removeEventListener(e,r.dispatch),L.delete(e));}}var I={key:"viewport",scope:"global",start(e){let t=()=>{e.write("vw",window.innerWidth),e.write("vh",window.innerHeight);};return t(),y("resize",t)}};function p(e){return Math.round(e*1e4)/1e4}var W={key:"pointer",scope:"global",start(e){return y("pointermove",r=>{let n=r;e.write("pointer-x",n.clientX),e.write("pointer-y",n.clientY),e.write("pointer-x-ratio",p(n.clientX/window.innerWidth)),e.write("pointer-y-ratio",p(n.clientY/window.innerHeight));})}};var g,T=new WeakMap;function K(e,t){return g||(g=new ResizeObserver(r=>{for(let n of r)T.get(n.target)?.(n);})),T.set(e,t),g.observe(e),()=>{g.unobserve(e),T.delete(e);}}var v,x=new WeakMap;function N(e,t){return v||(v=new IntersectionObserver(r=>{for(let n of r)x.get(n.target)?.(n);},{threshold:[0,1]})),x.set(e,t),v.observe(e),()=>{v.unobserve(e),x.delete(e);}}var B={key:"size",scope:"element",start(e){return K(e.target,t=>{let r=t.borderBoxSize?.[0],n=r?r.inlineSize:t.contentRect.width,o=r?r.blockSize:t.contentRect.height;e.write("w",p(n)),e.write("h",p(o)),e.write("aspect",o>0?p(n/o):0);})}};var X={key:"visibility",scope:"element",start(e){let t=false;return e.write("visible",0),e.write("has-entered",0,"const"),N(e.target,r=>{let n=r.intersectionRatio>=1;e.write("visible",n?1:0),n&&!t&&(t=true,e.write("has-entered",1,"const"));})}};function Y(e,t){return e.matches(t)?e:e.querySelector(t)}var $={key:"range",scope:"element",start(e){let t=Y(e.target,'input[type="range"], input[type="number"]');if(!t)return ()=>{};let r=()=>{let n=t.min===""?0:Number(t.min),o=t.max===""?100:Number(t.max),i=Number(t.value);e.write("value",i),e.write("value-pct",o>n?p((i-n)/(o-n)):0);};return r(),t.addEventListener("input",r,{passive:true}),()=>t.removeEventListener("input",r)}};var j={viewport:I,pointer:W,size:B,visibility:X,range:$};var Z=()=>{},u=new Map,ee={...j};function G(e){Object.assign(c,e);}function te(e,t,r){return {target:e,config:c,write(n,o,i="live"){let s=(i==="const"?c.constPrefix:c.livePrefix)+n;t.add(s),c.typed&&q(s,n,r),m.set(e,s,String(o));}}}function U(e,t,r){let n=r.get(t);if(!n)return;n.dispose();let o=a(e);for(let i of n.written)o.removeProperty(i),m.forget(e,i);r.delete(t);}function re(e,t){let r=u.get(e);r||u.set(e,r=new Map);let n=[];for(let o of t){if(r.has(o))continue;let i=ee[o];if(!i){console.warn(`[prop-for-that] unknown source "${o}"`);continue}let s=new Set,C;try{C=i.start(te(e,s,i.props));}catch(J){console.error(`[prop-for-that] source "${o}" failed to start`,J);continue}r.set(o,{dispose:C,written:s}),n.push(o);}return ()=>{let o=u.get(e);if(o){for(let i of n)U(e,i,o);o.size===0&&u.delete(e);}}}function ne(e){return e instanceof Element?[e]:typeof NodeList<"u"&&e instanceof NodeList||typeof HTMLCollection<"u"&&e instanceof HTMLCollection||Array.isArray(e)?Array.from(e).filter(t=>t instanceof Element):[]}function oe(e){return Array.isArray(e)&&(e.length===0||typeof e[0]=="string")}function H(e,t){let r,n;if(t===void 0&&oe(e)?(r=c.root?[c.root]:[],n=e):(r=ne(e),n=t??[]),!r.length||!n.length)return Z;let o=r.map(i=>re(i,n));return ()=>{for(let i of o)i();}}function k(e,t){let r=u.get(e);if(r){for(let n of t??[...r.keys()])U(e,n,r);r.size===0&&u.delete(e);}}var ie=["viewport","pointer"],d=new WeakMap;function se(e){return (e.dataset.propsFor??"").split(/\s+/).filter(Boolean)}function S(e){let t=se(e),r=d.get(e)??[],n=r.filter(i=>!t.includes(i)),o=t.filter(i=>!r.includes(i));n.length&&k(e,n),o.length&&H(e,o),t.length?d.set(e,t):d.delete(e);}function V(e){let t=d.get(e);t&&(k(e,t),d.delete(e));}function ce(e){e instanceof HTMLElement&&(e.hasAttribute("data-props-for")&&S(e),e.querySelectorAll("[data-props-for]").forEach(S));}function pe(e){e instanceof HTMLElement&&(V(e),e.querySelectorAll("[data-props-for]").forEach(V));}function _(){document.documentElement.hasAttribute("data-props-typed")&&G({typed:true}),H(ie),document.querySelectorAll("[data-props-for]").forEach(S),new MutationObserver(e=>{for(let t of e){if(t.type==="attributes"&&t.target instanceof HTMLElement){S(t.target);continue}t.removedNodes.forEach(pe),t.addedNodes.forEach(ce);}}).observe(document.documentElement,{subtree:true,childList:true,attributes:true,attributeFilter:["data-props-for"]});}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",_,{once:true}):_());})();
|
package/dist/auto.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {i,j,k}from'./chunk-6DXNWAGS.js';import'./chunk-LWKH66VY.js';var p=["viewport","pointer"],n=new WeakMap;function m(e){return (e.dataset.propsFor??"").split(/\s+/).filter(Boolean)}function o(e){let t=m(e),d=n.get(e)??[],s=d.filter(r=>!t.includes(r)),a=t.filter(r=>!d.includes(r));s.length&&k(e,s),a.length&&j(e,a),t.length?n.set(e,t):n.delete(e);}function u(e){let t=n.get(e);t&&(k(e,t),n.delete(e));}function E(e){e instanceof HTMLElement&&(e.hasAttribute("data-props-for")&&o(e),e.querySelectorAll("[data-props-for]").forEach(o));}function L(e){e instanceof HTMLElement&&(u(e),e.querySelectorAll("[data-props-for]").forEach(u));}function l(){document.documentElement.hasAttribute("data-props-typed")&&i({typed:true}),j(p),document.querySelectorAll("[data-props-for]").forEach(o),new MutationObserver(e=>{for(let t of e){if(t.type==="attributes"&&t.target instanceof HTMLElement){o(t.target);continue}t.removedNodes.forEach(L),t.addedNodes.forEach(E);}}).observe(document.documentElement,{subtree:true,childList:true,attributes:true,attributeFilter:["data-props-for"]});}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",l,{once:true}):l());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a as a$1}from'./chunk-LWKH66VY.js';var a=new Set,z=null,f=0,h=false,d=false,F=0,E=()=>typeof requestAnimationFrame=="function";function b(e){if(f=0,d)return;let t=a$1.liveHz;if(E()&&t&&t>0&&e-F<1e3/t){f=requestAnimationFrame(b);return}if(F=e,h=true,a.size)for(let r of [...a])r(e);z?.(),h=false,a.size&&E()&&m();}function m(){f||h||d||(E()?f=requestAnimationFrame(b):b(0));}function D(){m();}function R(e){z=e;}function te(e){return a.add(e),m(),()=>{a.delete(e);}}function B(){d||(d=true,f&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(f),f=0);}function V(){d&&(d=false,m());}var l;function G(){if(l!==void 0||(l=null,typeof document>"u"||typeof CSSStyleSheet!="function"||!("adoptedStyleSheets"in document)))return l;try{let e=new CSSStyleSheet;e.replaceSync(":root{}"),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],l=e.cssRules[0].style;}catch{l=null;}return l}function y(e){if(typeof document<"u"&&e===document.documentElement){let t=G();if(t)return t}return e.style}var M=class{pending=new Map;last=new WeakMap;set(t,r,n){let o=this.pending.get(t);if(o?.has(r)){o.set(r,n);return}this.last.get(t)?.get(r)!==n&&(o?o.set(r,n):this.pending.set(t,new Map([[r,n]])),D());}forget(t,r){this.last.get(t)?.delete(r),this.pending.get(t)?.delete(r);}flush=()=>{if(this.pending.size!==0){for(let[t,r]of this.pending){let n=this.last.get(t);n||this.last.set(t,n=new Map);let o=y(t);for(let[i,s]of r)n.get(i)!==s&&(o.setProperty(i,s),n.set(i,s));}this.pending.clear();}}},g=new M;R(g.flush);var P=new Set;function A(e,t,r){if(P.has(e)||typeof CSS>"u"||typeof CSS.registerProperty!="function")return;P.add(e);let n=t?r?.[t]:void 0,o=t?a$1.defaults?.[t]:void 0;try{CSS.registerProperty({name:e,syntax:n?.syntax??"<number>",inherits:n?.inherits??!0,initialValue:o!=null?String(o):n?.initial??"0"});}catch{}}var x=new Map;function v(e,t){let r=x.get(e);if(!r){let n=new Set,o=i=>{for(let s of [...n])s(i);};r={handlers:n,dispatch:o},x.set(e,r),window.addEventListener(e,o,{passive:true});}return r.handlers.add(t),()=>{r.handlers.delete(t),r.handlers.size===0&&(window.removeEventListener(e,r.dispatch),x.delete(e));}}var O={key:"viewport",scope:"global",start(e){let t=()=>{e.write("vw",window.innerWidth),e.write("vh",window.innerHeight);};return t(),v("resize",t)}};function c(e){return Math.round(e*1e4)/1e4}var I={key:"pointer",scope:"global",start(e){return v("pointermove",r=>{let n=r;e.write("pointer-x",n.clientX),e.write("pointer-y",n.clientY),e.write("pointer-x-ratio",c(n.clientX/window.innerWidth)),e.write("pointer-y-ratio",c(n.clientY/window.innerHeight));})}};var S,k=new WeakMap;function K(e,t){return S||(S=new ResizeObserver(r=>{for(let n of r)k.get(n.target)?.(n);})),k.set(e,t),S.observe(e),()=>{S.unobserve(e),k.delete(e);}}var w,T=new WeakMap;function W(e,t){return w||(w=new IntersectionObserver(r=>{for(let n of r)T.get(n.target)?.(n);},{threshold:[0,1]})),T.set(e,t),w.observe(e),()=>{w.unobserve(e),T.delete(e);}}var q={key:"size",scope:"element",start(e){return K(e.target,t=>{let r=t.borderBoxSize?.[0],n=r?r.inlineSize:t.contentRect.width,o=r?r.blockSize:t.contentRect.height;e.write("w",c(n)),e.write("h",c(o)),e.write("aspect",o>0?c(n/o):0);})}};var N={key:"visibility",scope:"element",start(e){let t=false;return e.write("visible",0),e.write("has-entered",0,"const"),W(e.target,r=>{let n=r.intersectionRatio>=1;e.write("visible",n?1:0),n&&!t&&(t=true,e.write("has-entered",1,"const"));})}};function X(e,t){return e.matches(t)?e:e.querySelector(t)}var Y={key:"range",scope:"element",start(e){let t=X(e.target,'input[type="range"], input[type="number"]');if(!t)return ()=>{};let r=()=>{let n=t.min===""?0:Number(t.min),o=t.max===""?100:Number(t.max),i=Number(t.value);e.write("value",i),e.write("value-pct",o>n?c((i-n)/(o-n)):0);};return r(),t.addEventListener("input",r,{passive:true}),()=>t.removeEventListener("input",r)}};var $={viewport:O,pointer:I,size:q,visibility:N,range:Y};var J=()=>{},u=new Map,L={...$};function Ke(e){L[e.key]=e;}function We(e){delete L[e];}function qe(e){Object.assign(a$1,e);}function Q(e,t,r){return {target:e,config:a$1,write(n,o,i="live"){let s=(i==="const"?a$1.constPrefix:a$1.livePrefix)+n;t.add(s),a$1.typed&&A(s,n,r),g.set(e,s,String(o));}}}function C(e,t,r){let n=r.get(t);if(!n)return;n.dispose();let o=y(e);for(let i of n.written)o.removeProperty(i),g.forget(e,i);r.delete(t);}function U(e,t){let r=u.get(e);r||u.set(e,r=new Map);let n=[];for(let o of t){if(r.has(o))continue;let i=L[o];if(!i){console.warn(`[prop-for-that] unknown source "${o}"`);continue}let s=new Set,H;try{H=i.start(Q(e,s,i.props));}catch(j){console.error(`[prop-for-that] source "${o}" failed to start`,j);continue}r.set(o,{dispose:H,written:s}),n.push(o);}return ()=>{let o=u.get(e);if(o){for(let i of n)C(e,i,o);o.size===0&&u.delete(e);}}}function Z(e){return e instanceof Element?[e]:typeof NodeList<"u"&&e instanceof NodeList||typeof HTMLCollection<"u"&&e instanceof HTMLCollection||Array.isArray(e)?Array.from(e).filter(t=>t instanceof Element):[]}function _(e){return Array.isArray(e)&&(e.length===0||typeof e[0]=="string")}function Ne(e,t){let r,n;if(t===void 0&&_(e)?(r=a$1.root?[a$1.root]:[],n=e):(r=Z(e),n=t??[]),!r.length||!n.length)return J;let o=r.map(i=>U(i,n));return ()=>{for(let i of o)i();}}function Xe(e,t){let r=u.get(e);if(r){for(let n of t??[...r.keys()])C(e,n,r);r.size===0&&u.delete(e);}}function Ye(){for(let[e,t]of u)for(let r of [...t.keys()])C(e,r,t);u.clear();}export{te as a,B as b,V as c,v as d,c as e,X as f,Ke as g,We as h,qe as i,Ne as j,Xe as k,Ye as l};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={livePrefix:"--live-",constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0,typed:false};export{e as a};
|
package/dist/head.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var o={constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0};function s(){let i=o.root,t=(n,r)=>i.style.setProperty(o.constPrefix+n,String(r)),e=document.createElement("div");e.style.cssText="position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden",(document.body??i).appendChild(e),t("scrollbar-w",e.offsetWidth-e.clientWidth),e.style.scrollbarWidth="thin",t("scrollbar-thin-w",e.offsetWidth-e.clientWidth),e.remove(),t("dpr",window.devicePixelRatio||1),t("cores",navigator.hardwareConcurrency||0),t("mem",navigator.deviceMemory||0);}typeof document<"u"&&s();
|
package/dist/head.d.cts
ADDED
package/dist/head.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){'use strict';var o={constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0};function s(){let i=o.root,t=(n,r)=>i.style.setProperty(o.constPrefix+n,String(r)),e=document.createElement("div");e.style.cssText="position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden",(document.body??i).appendChild(e),t("scrollbar-w",e.offsetWidth-e.clientWidth),e.style.scrollbarWidth="thin",t("scrollbar-thin-w",e.offsetWidth-e.clientWidth),e.remove(),t("dpr",window.devicePixelRatio||1),t("cores",navigator.hardwareConcurrency||0),t("mem",navigator.deviceMemory||0);}typeof document<"u"&&s();})();
|
package/dist/head.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a}from'./chunk-LWKH66VY.js';function s(){let i=a.root,e=(r,n)=>i.style.setProperty(a.constPrefix+r,String(n)),t=document.createElement("div");t.style.cssText="position:absolute;top:-9999px;width:100px;height:100px;overflow:scroll;visibility:hidden",(document.body??i).appendChild(t),e("scrollbar-w",t.offsetWidth-t.clientWidth),t.style.scrollbarWidth="thin",e("scrollbar-thin-w",t.offsetWidth-t.clientWidth),t.remove(),e("dpr",window.devicePixelRatio||1),e("cores",navigator.hardwareConcurrency||0),e("mem",navigator.deviceMemory||0);}typeof document<"u"&&s();
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var p={livePrefix:"--live-",constPrefix:"--const-",root:typeof document<"u"?document.documentElement:void 0,typed:false};var S=new Set,z=null,f=0,w=false,d=false,F=0,h=()=>typeof requestAnimationFrame=="function";function E(e){if(f=0,d)return;let t=p.liveHz;if(h()&&t&&t>0&&e-F<1e3/t){f=requestAnimationFrame(E);return}if(F=e,w=true,S.size)for(let r of [...S])r(e);z?.(),w=false,S.size&&h()&&b();}function b(){f||w||d||(h()?f=requestAnimationFrame(E):E(0));}function D(){b();}function R(e){z=e;}function B(){d||(d=true,f&&typeof cancelAnimationFrame=="function"&&cancelAnimationFrame(f),f=0);}function V(){d&&(d=false,b());}var l;function G(){if(l!==void 0||(l=null,typeof document>"u"||typeof CSSStyleSheet!="function"||!("adoptedStyleSheets"in document)))return l;try{let e=new CSSStyleSheet;e.replaceSync(":root{}"),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],l=e.cssRules[0].style;}catch{l=null;}return l}function a(e){if(typeof document<"u"&&e===document.documentElement){let t=G();if(t)return t}return e.style}var x=class{pending=new Map;last=new WeakMap;set(t,r,n){let o=this.pending.get(t);if(o?.has(r)){o.set(r,n);return}this.last.get(t)?.get(r)!==n&&(o?o.set(r,n):this.pending.set(t,new Map([[r,n]])),D());}forget(t,r){this.last.get(t)?.delete(r),this.pending.get(t)?.delete(r);}flush=()=>{if(this.pending.size!==0){for(let[t,r]of this.pending){let n=this.last.get(t);n||this.last.set(t,n=new Map);let o=a(t);for(let[i,s]of r)n.get(i)!==s&&(o.setProperty(i,s),n.set(i,s));}this.pending.clear();}}},m=new x;R(m.flush);var P=new Set;function A(e,t,r){if(P.has(e)||typeof CSS>"u"||typeof CSS.registerProperty!="function")return;P.add(e);let n=t?r?.[t]:void 0,o=t?p.defaults?.[t]:void 0;try{CSS.registerProperty({name:e,syntax:n?.syntax??"<number>",inherits:n?.inherits??!0,initialValue:o!=null?String(o):n?.initial??"0"});}catch{}}var M=new Map;function y(e,t){let r=M.get(e);if(!r){let n=new Set,o=i=>{for(let s of [...n])s(i);};r={handlers:n,dispatch:o},M.set(e,r),window.addEventListener(e,o,{passive:true});}return r.handlers.add(t),()=>{r.handlers.delete(t),r.handlers.size===0&&(window.removeEventListener(e,r.dispatch),M.delete(e));}}var O={key:"viewport",scope:"global",start(e){let t=()=>{e.write("vw",window.innerWidth),e.write("vh",window.innerHeight);};return t(),y("resize",t)}};function c(e){return Math.round(e*1e4)/1e4}var I={key:"pointer",scope:"global",start(e){return y("pointermove",r=>{let n=r;e.write("pointer-x",n.clientX),e.write("pointer-y",n.clientY),e.write("pointer-x-ratio",c(n.clientX/window.innerWidth)),e.write("pointer-y-ratio",c(n.clientY/window.innerHeight));})}};var g,T=new WeakMap;function K(e,t){return g||(g=new ResizeObserver(r=>{for(let n of r)T.get(n.target)?.(n);})),T.set(e,t),g.observe(e),()=>{g.unobserve(e),T.delete(e);}}var v,k=new WeakMap;function W(e,t){return v||(v=new IntersectionObserver(r=>{for(let n of r)k.get(n.target)?.(n);},{threshold:[0,1]})),k.set(e,t),v.observe(e),()=>{v.unobserve(e),k.delete(e);}}var q={key:"size",scope:"element",start(e){return K(e.target,t=>{let r=t.borderBoxSize?.[0],n=r?r.inlineSize:t.contentRect.width,o=r?r.blockSize:t.contentRect.height;e.write("w",c(n)),e.write("h",c(o)),e.write("aspect",o>0?c(n/o):0);})}};var N={key:"visibility",scope:"element",start(e){let t=false;return e.write("visible",0),e.write("has-entered",0,"const"),W(e.target,r=>{let n=r.intersectionRatio>=1;e.write("visible",n?1:0),n&&!t&&(t=true,e.write("has-entered",1,"const"));})}};function X(e,t){return e.matches(t)?e:e.querySelector(t)}var Y={key:"range",scope:"element",start(e){let t=X(e.target,'input[type="range"], input[type="number"]');if(!t)return ()=>{};let r=()=>{let n=t.min===""?0:Number(t.min),o=t.max===""?100:Number(t.max),i=Number(t.value);e.write("value",i),e.write("value-pct",o>n?c((i-n)/(o-n)):0);};return r(),t.addEventListener("input",r,{passive:true}),()=>t.removeEventListener("input",r)}};var $={viewport:O,pointer:I,size:q,visibility:N,range:Y};var J=()=>{},u=new Map,C={...$};function Ke(e){C[e.key]=e;}function We(e){delete C[e];}function qe(e){Object.assign(p,e);}function Q(e,t,r){return {target:e,config:p,write(n,o,i="live"){let s=(i==="const"?p.constPrefix:p.livePrefix)+n;t.add(s),p.typed&&A(s,n,r),m.set(e,s,String(o));}}}function L(e,t,r){let n=r.get(t);if(!n)return;n.dispose();let o=a(e);for(let i of n.written)o.removeProperty(i),m.forget(e,i);r.delete(t);}function U(e,t){let r=u.get(e);r||u.set(e,r=new Map);let n=[];for(let o of t){if(r.has(o))continue;let i=C[o];if(!i){console.warn(`[prop-for-that] unknown source "${o}"`);continue}let s=new Set,H;try{H=i.start(Q(e,s,i.props));}catch(j){console.error(`[prop-for-that] source "${o}" failed to start`,j);continue}r.set(o,{dispose:H,written:s}),n.push(o);}return ()=>{let o=u.get(e);if(o){for(let i of n)L(e,i,o);o.size===0&&u.delete(e);}}}function Z(e){return e instanceof Element?[e]:typeof NodeList<"u"&&e instanceof NodeList||typeof HTMLCollection<"u"&&e instanceof HTMLCollection||Array.isArray(e)?Array.from(e).filter(t=>t instanceof Element):[]}function _(e){return Array.isArray(e)&&(e.length===0||typeof e[0]=="string")}function Ne(e,t){let r,n;if(t===void 0&&_(e)?(r=p.root?[p.root]:[],n=e):(r=Z(e),n=t??[]),!r.length||!n.length)return J;let o=r.map(i=>U(i,n));return ()=>{for(let i of o)i();}}function Xe(e,t){let r=u.get(e);if(r){for(let n of t??[...r.keys()])L(e,n,r);r.size===0&&u.delete(e);}}function Ye(){for(let[e,t]of u)for(let r of [...t.keys()])L(e,r,t);u.clear();}exports.configure=qe;exports.pause=B;exports.propsFor=Ne;exports.register=Ke;exports.reset=Ye;exports.resume=V;exports.unbind=Xe;exports.unregister=We;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { a as Config, D as Disposer, S as Source } from './types-BYVnuPvd.cjs';
|
|
2
|
+
export { C as Cadence, P as PropSpec, b as SourceContext } from './types-BYVnuPvd.cjs';
|
|
3
|
+
|
|
4
|
+
/** Freeze the loop: no sampling, no flushing, until `resume()`. Idempotent. */
|
|
5
|
+
declare function pause(): void;
|
|
6
|
+
/** Unfreeze the loop and pick up sampling / queued writes again. Idempotent. */
|
|
7
|
+
declare function resume(): void;
|
|
8
|
+
|
|
9
|
+
type CoreKey = 'viewport' | 'pointer' | 'size' | 'visibility' | 'range';
|
|
10
|
+
/** Built-in keys autocomplete; any registered/plugin key (a string) is allowed. */
|
|
11
|
+
type SourceKey = CoreKey | (string & {});
|
|
12
|
+
/** Register a custom or plugin source so it can be used by key. */
|
|
13
|
+
declare function register(source: Source): void;
|
|
14
|
+
/** Remove a previously registered source key. */
|
|
15
|
+
declare function unregister(key: string): void;
|
|
16
|
+
/** Override prefixes or the global root target. Call before attaching sources. */
|
|
17
|
+
declare function configure(opts: Partial<Config>): void;
|
|
18
|
+
/**
|
|
19
|
+
* Attach sources by key. Global by default (writes to `:root`); pass a Node,
|
|
20
|
+
* NodeList, or array of elements as the first argument to attach to elements.
|
|
21
|
+
*
|
|
22
|
+
* propsFor(['pointer']) // → :root
|
|
23
|
+
* propsFor(el, ['size']) // → el
|
|
24
|
+
* propsFor(els, ['visibility']) // → each element in a NodeList / array
|
|
25
|
+
*
|
|
26
|
+
* Returns a disposer that tears down exactly what this call started and removes
|
|
27
|
+
* the custom properties it wrote.
|
|
28
|
+
*/
|
|
29
|
+
declare function propsFor(keys: SourceKey[]): Disposer;
|
|
30
|
+
declare function propsFor(target: Element | NodeList | HTMLCollection | Element[], keys: SourceKey[]): Disposer;
|
|
31
|
+
/** Detach specific keys from an element, or all of them. Removes written props. */
|
|
32
|
+
declare function unbind(target: HTMLElement, keys?: string[]): void;
|
|
33
|
+
/** Tear down every active binding (and, via ref-counting, the shared observers
|
|
34
|
+
* and listeners they used). Useful for SPA route changes, HMR, and tests. */
|
|
35
|
+
declare function reset(): void;
|
|
36
|
+
|
|
37
|
+
export { Config, Disposer, Source, type SourceKey, configure, pause, propsFor, register, reset, resume, unbind, unregister };
|