kuinetic 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -10
- package/dist/esm/advanced/index.mjs +4727 -0
- package/dist/esm/chunk-AEQGC2KM.mjs +189 -0
- package/dist/esm/chunk-MQSNMYRP.mjs +9332 -0
- package/dist/esm/chunk-RVTYN6NZ.mjs +3446 -0
- package/dist/esm/chunk-U43BX5O2.mjs +2984 -0
- package/dist/esm/core/index.mjs +16 -9
- package/dist/esm/effects/index.mjs +19 -4
- package/dist/esm/index.mjs +17 -10
- package/dist/kuinetic.advanced.js +5070 -0
- package/dist/kuinetic.advanced.min.js +749 -0
- package/dist/kuinetic.all.js +15147 -6039
- package/dist/kuinetic.all.min.js +2 -0
- package/dist/kuinetic.css +2801 -318
- package/dist/kuinetic.js +15147 -6038
- package/dist/kuinetic.min.css +1 -0
- package/dist/kuinetic.min.js +7 -0
- package/dist/types/3d/angles.d.ts +30 -0
- package/dist/types/3d/flattening.d.ts +49 -0
- package/dist/types/3d/index.d.ts +36 -0
- package/dist/types/3d/model-3d.d.ts +115 -0
- package/dist/types/3d/register.d.ts +26 -0
- package/dist/types/3d/webgl.d.ts +24 -0
- package/dist/types/advanced/audio.d.ts +322 -0
- package/dist/types/advanced/base.d.ts +233 -0
- package/dist/types/advanced/camera-3d.d.ts +236 -0
- package/dist/types/advanced/fluid-cursor.d.ts +149 -0
- package/dist/types/advanced/gl-utils.d.ts +52 -0
- package/dist/types/advanced/glsl.d.ts +60 -0
- package/dist/types/advanced/index.d.ts +23 -0
- package/dist/types/advanced/particles.d.ts +108 -0
- package/dist/types/advanced/scenes.d.ts +207 -0
- package/dist/types/advanced/shaders.d.ts +972 -0
- package/dist/types/browser/boot.d.ts +72 -0
- package/dist/types/core/activation.d.ts +227 -2
- package/dist/types/core/animator.d.ts +446 -11
- package/dist/types/core/attrs.d.ts +9 -0
- package/dist/types/core/breakpoints.d.ts +260 -0
- package/dist/types/core/bundles.d.ts +71 -0
- package/dist/types/core/callback.d.ts +64 -0
- package/dist/types/core/capabilities.d.ts +47 -0
- package/dist/types/core/channels.d.ts +120 -2
- package/dist/types/core/cloak-selectors.d.ts +47 -0
- package/dist/types/core/compile.d.ts +207 -2
- package/dist/types/core/control.d.ts +218 -0
- package/dist/types/core/declarations.d.ts +128 -0
- package/dist/types/core/derived/aggregate.d.ts +43 -0
- package/dist/types/core/derived/book.d.ts +30 -0
- package/dist/types/core/derived/diagnostics.d.ts +51 -0
- package/dist/types/core/derived/group-gate.d.ts +62 -0
- package/dist/types/core/derived/install.d.ts +110 -0
- package/dist/types/core/derived/late-matches.d.ts +19 -0
- package/dist/types/core/derived/types.d.ts +108 -0
- package/dist/types/core/easing.d.ts +57 -0
- package/dist/types/core/element-config.d.ts +47 -6
- package/dist/types/core/element-size.d.ts +23 -0
- package/dist/types/core/event-sources.d.ts +39 -0
- package/dist/types/core/flip.d.ts +34 -1
- package/dist/types/core/gesture.d.ts +12 -0
- package/dist/types/core/host-facts.d.ts +155 -0
- package/dist/types/core/index.d.ts +7 -3
- package/dist/types/core/owned-styles.d.ts +129 -2
- package/dist/types/core/params.d.ts +48 -0
- package/dist/types/core/parse.d.ts +28 -1
- package/dist/types/core/register-into.d.ts +29 -0
- package/dist/types/core/registry.d.ts +10 -3
- package/dist/types/core/repeat.d.ts +91 -0
- package/dist/types/core/sequence.d.ts +126 -0
- package/dist/types/core/stagger-config.d.ts +199 -0
- package/dist/types/core/stagger-keys.d.ts +63 -0
- package/dist/types/core/stagger.d.ts +187 -6
- package/dist/types/core/style-plan.d.ts +21 -16
- package/dist/types/core/target.d.ts +128 -0
- package/dist/types/core/threshold-reachability.d.ts +45 -0
- package/dist/types/core/time-scale.d.ts +9 -0
- package/dist/types/core/toggle-actions.d.ts +141 -0
- package/dist/types/core/travel.d.ts +59 -0
- package/dist/types/core/types.d.ts +699 -13
- package/dist/types/core/unquoted-selectors.d.ts +53 -0
- package/dist/types/effects/carousel/drag.d.ts +80 -0
- package/dist/types/effects/carousel/index.d.ts +149 -0
- package/dist/types/effects/catalog/discrete.d.ts +13 -0
- package/dist/types/effects/catalog/interaction-proximity.d.ts +24 -0
- package/dist/types/effects/catalog/interaction-reveal.d.ts +248 -0
- package/dist/types/effects/catalog/interaction-shared.d.ts +42 -0
- package/dist/types/effects/catalog/interaction-states.d.ts +68 -0
- package/dist/types/effects/catalog/materials.d.ts +67 -0
- package/dist/types/effects/catalog/media-shared.d.ts +3 -2
- package/dist/types/effects/catalog/numbers-shared.d.ts +8 -5
- package/dist/types/effects/catalog/shared.d.ts +1 -1
- package/dist/types/effects/catalog/text-shared.d.ts +86 -10
- package/dist/types/effects/catalog/transforms.d.ts +13 -0
- package/dist/types/effects/catalog/view-transitions.d.ts +13 -0
- package/dist/types/effects/forms/primitives.d.ts +15 -4
- package/dist/types/effects/gestures/index.d.ts +53 -0
- package/dist/types/effects/index.d.ts +5 -0
- package/dist/types/effects/layout/presets.d.ts +35 -0
- package/dist/types/effects/motion-path/index.d.ts +35 -0
- package/dist/types/effects/scroll-mechanics/params.d.ts +23 -0
- package/dist/types/effects/scroll-mechanics/presets.d.ts +51 -0
- package/dist/types/effects/scroll-mechanics/section-index.d.ts +47 -0
- package/dist/types/effects/shared.d.ts +124 -4
- package/dist/types/effects/step-index.d.ts +121 -0
- package/dist/types/effects/step-marking.d.ts +41 -33
- package/dist/types/effects/svg/icon-parts.d.ts +23 -0
- package/dist/types/effects/three-d/flip-parts.d.ts +46 -0
- package/dist/types/effects/tween/index.d.ts +57 -0
- package/dist/types/effects/tween/properties.d.ts +107 -0
- package/dist/types/effects/tween/waypoints.d.ts +106 -0
- package/dist/types/showcase/compare.d.ts +4 -0
- package/dist/types/showcase/device-frame.d.ts +3 -0
- package/dist/types/showcase/hotspots.d.ts +3 -0
- package/dist/types/showcase/index.d.ts +30 -0
- package/dist/types/showcase/lightbox.d.ts +3 -0
- package/dist/types/showcase/media-source.d.ts +13 -0
- package/dist/types/showcase/modal-shell.d.ts +22 -0
- package/dist/types/showcase/scroll-story.d.ts +4 -0
- package/dist/types/showcase/shared.d.ts +47 -0
- package/dist/types/showcase/slideshow.d.ts +3 -0
- package/dist/types/showcase/slow-mo.d.ts +5 -0
- package/package.json +14 -7
- package/dist/esm/chunk-7WMNPIOZ.mjs +0 -4883
- package/dist/esm/chunk-JT4PZL3A.mjs +0 -773
- package/dist/esm/chunk-TJDDIQRG.mjs +0 -1290
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ActivationBinder } from './activation.js';
|
|
2
2
|
import { ATTR } from './attrs.js';
|
|
3
3
|
import type { Capabilities } from './capabilities.js';
|
|
4
|
+
import type { ControlHandle } from './control.js';
|
|
4
5
|
import type { DomWatcher } from './dom-watcher.js';
|
|
5
6
|
import type { JsEffectPreparer } from './js-effect-preparer.js';
|
|
6
7
|
import type { ScrollRoot, ScrollScheduler } from './scroll-scheduler.js';
|
|
@@ -36,18 +37,22 @@ export interface AnimatorOptions {
|
|
|
36
37
|
/** Watch for DOM insertions and attribute changes. Off by default. */
|
|
37
38
|
observe?: boolean;
|
|
38
39
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Scans a document for authored effects and installs them.
|
|
41
|
-
*
|
|
42
|
-
* Every collaborator — registry, capabilities, reporter, activation binder — is injected, so no
|
|
43
|
-
* behaviour depends on module state or globals. The class itself only orchestrates: parsing,
|
|
44
|
-
* compilation, and style decisions all live in pure modules it calls.
|
|
45
|
-
*/
|
|
46
40
|
export declare class Animator {
|
|
47
41
|
readonly registry: Registry;
|
|
48
42
|
readonly capabilities: Capabilities;
|
|
43
|
+
/**
|
|
44
|
+
* Public alongside `registry` and `capabilities`, and for the same reason: `control()` is a free
|
|
45
|
+
* function in its own module (mirroring `play()`), and an author-facing diagnostic it emits has
|
|
46
|
+
* to reach the same sink every other diagnostic on this animator does. Routing it through a
|
|
47
|
+
* second, private channel would mean `consoleReporter()` silenced half the library's warnings.
|
|
48
|
+
*/
|
|
49
|
+
readonly reporter: Reporter;
|
|
49
50
|
private readonly root;
|
|
50
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Author-defined bundles found in this animator's root. Per-animator, not per-module: two
|
|
53
|
+
* animators on two roots must not see each other's definitions.
|
|
54
|
+
*/
|
|
55
|
+
private readonly bundles;
|
|
51
56
|
private readonly binder;
|
|
52
57
|
private readonly scheduler;
|
|
53
58
|
private readonly rootResolver;
|
|
@@ -58,9 +63,57 @@ export declare class Animator {
|
|
|
58
63
|
private readonly states;
|
|
59
64
|
/** Iterable lifecycle index; the WeakMap remains the fast state lookup. */
|
|
60
65
|
private readonly liveElements;
|
|
66
|
+
/**
|
|
67
|
+
* Which run is current for one element's `InstanceState`, so a completion that resolves after
|
|
68
|
+
* being superseded can tell it is stale even when `status` and `direction` do not say so.
|
|
69
|
+
*
|
|
70
|
+
* `state.direction` cannot serve as that identifier on its own — it only ever holds `'forward'`
|
|
71
|
+
* or `'reverse'`, so an element whose activation flips back and forth (a hover-driven card flip,
|
|
72
|
+
* `pointerenter`/`pointerleave` firing repeatedly) revisits the same direction many times over
|
|
73
|
+
* its life. A cancelled run's completion settling late would then match a much later run headed
|
|
74
|
+
* the same way, by coincidence rather than by being the same run. Keyed on `InstanceState` rather
|
|
75
|
+
* than `Element` so a `release()`-then-reinstall — a fresh state object — starts with no
|
|
76
|
+
* history, the same reason `settleWhen` already re-checks `this.states.get(el) !== state`.
|
|
77
|
+
*/
|
|
78
|
+
private readonly currentRun;
|
|
79
|
+
/**
|
|
80
|
+
* Whether the element's current run has a settle gate that will eventually write its final
|
|
81
|
+
* status, or whether nothing is ever going to report on it.
|
|
82
|
+
*
|
|
83
|
+
* `settleWhen` declines to arm a gate when every instance it was handed is `continuous` — see
|
|
84
|
+
* the reasoning there, which is right: a pin that is still pinned should read `running`. But
|
|
85
|
+
* "nobody will ever write this status" was left as an unrecorded fact known only inside that
|
|
86
|
+
* one early return, and `cancel()` had no way to ask. So a cancelled pin kept `status =
|
|
87
|
+
* 'running'` for the rest of the element's life and `activate()`'s own `running` guard locked it
|
|
88
|
+
* out of every future activation. Measured on `<div data-kui="pin-section">`, the documented
|
|
89
|
+
* form: cancel left `data-kui-state="running"`, and the next `activate()` emitted no `kui:start`
|
|
90
|
+
* at all.
|
|
91
|
+
*
|
|
92
|
+
* Recorded here rather than re-derived in `cancel()` from `state.instances`, because the two
|
|
93
|
+
* would not be asking the same question. `settleWhen` decides on the instances that actually
|
|
94
|
+
* *started* this run; an instance whose setup threw is excluded there, and by cancel time it is
|
|
95
|
+
* indistinguishable from a timed one (`continuous` reads from the setup result, which a failed
|
|
96
|
+
* or torn-down instance no longer has). The gate's own answer is the only one that matches the
|
|
97
|
+
* gate's own behaviour.
|
|
98
|
+
*
|
|
99
|
+
* Keyed on `InstanceState` for the same reason `currentRun` is: a `release()`-then-reinstall
|
|
100
|
+
* mints a fresh state object, which must start with no history.
|
|
101
|
+
*/
|
|
102
|
+
private readonly settleArmed;
|
|
61
103
|
/** Built lazily by `watch()` when not injected, so nothing observes until `start()` needs it. */
|
|
62
104
|
private domWatcher;
|
|
105
|
+
/**
|
|
106
|
+
* Built lazily by `watchGates()`, and only for an element carrying a viewport gate on a
|
|
107
|
+
* JavaScript-rendered effect — see `applyViewportGates` for why that is the only case that needs
|
|
108
|
+
* one. Stays `undefined` on a page whose gates are all on CSS-rendered effects, which binds no
|
|
109
|
+
* `MediaQueryList` listener anywhere.
|
|
110
|
+
*/
|
|
111
|
+
private gateWatcher;
|
|
63
112
|
private started;
|
|
113
|
+
/** This animator's derived-host bookkeeping — see `DerivedBook`. */
|
|
114
|
+
private readonly book;
|
|
115
|
+
/** The narrow window the `derived/*` modules get onto this animator — see `AnimatorPort`. */
|
|
116
|
+
private readonly port;
|
|
64
117
|
constructor(options?: AnimatorOptions);
|
|
65
118
|
/**
|
|
66
119
|
* Explicit entry point. Importing the library never touches the document, which keeps SSR,
|
|
@@ -76,11 +129,28 @@ export declare class Animator {
|
|
|
76
129
|
* `querySelectorAll` excludes the root, but an inserted subtree very often carries the
|
|
77
130
|
* attribute on its top node — skipping it silently drops those animations.
|
|
78
131
|
*
|
|
132
|
+
* Two passes, and the order is the feature. Every `data-kui-define` in the subtree is registered
|
|
133
|
+
* before any element in it is compiled, so a `<template>` at the bottom of the document is
|
|
134
|
+
* already known to the card at the top that names it. Making forward references work by
|
|
135
|
+
* construction rather than by handling is the point — see `core/bundles.ts`.
|
|
136
|
+
*
|
|
79
137
|
* @param root - Subtree to scan. Defaults to the animator's root.
|
|
80
138
|
* @complexity O(n) time in the subtree size; O(1) extra space.
|
|
81
139
|
* @overallScore 100
|
|
82
140
|
*/
|
|
83
141
|
scan(root?: ParentNode): this;
|
|
142
|
+
/**
|
|
143
|
+
* Recompile every element that stalled on a name the library did not know.
|
|
144
|
+
*
|
|
145
|
+
* `pending` is stamped for any unresolved name, not only an undefined bundle, so this can retry
|
|
146
|
+
* an element that will fail again. That is deliberate: the alternative is an index of which
|
|
147
|
+
* element is waiting on which name, and the cost of being wrong here is one wasted compile on a
|
|
148
|
+
* page that already has a warning about it.
|
|
149
|
+
*
|
|
150
|
+
* @complexity O(p) time in the number of pending elements.
|
|
151
|
+
* @overallScore 100
|
|
152
|
+
*/
|
|
153
|
+
private retryPending;
|
|
84
154
|
/**
|
|
85
155
|
* Compile and install one element's effects, recompiling if its attribute changed.
|
|
86
156
|
*
|
|
@@ -89,6 +159,19 @@ export declare class Animator {
|
|
|
89
159
|
* @overallScore 100
|
|
90
160
|
*/
|
|
91
161
|
process(el: Element): void;
|
|
162
|
+
/**
|
|
163
|
+
* Report everything a finished compile has to say about one element.
|
|
164
|
+
*
|
|
165
|
+
* Three sources, one place. The third is separate from the plan's own warnings because `compile`
|
|
166
|
+
* is pure and environment-free by design — it is handed a registry and a timeline, never the
|
|
167
|
+
* browser it is running in. "This browser cannot render that channel" is only answerable here,
|
|
168
|
+
* where the detected capabilities live, and `targets[0]`'s channel union is the merged one, so it
|
|
169
|
+
* runs once per element rather than once per `target:` group.
|
|
170
|
+
*
|
|
171
|
+
* @complexity O(w) time in the total warning count; O(1) space.
|
|
172
|
+
* @overallScore 100
|
|
173
|
+
*/
|
|
174
|
+
private reportCompiled;
|
|
92
175
|
/**
|
|
93
176
|
* Apply a compiled plan and bind its activation.
|
|
94
177
|
*
|
|
@@ -97,16 +180,148 @@ export declare class Animator {
|
|
|
97
180
|
*/
|
|
98
181
|
/**
|
|
99
182
|
* Choose the activation, letting a primitive's preference fill in only when the author named
|
|
100
|
-
* none, and
|
|
183
|
+
* none, and reporting whatever looks wrong about one the author did name.
|
|
101
184
|
*
|
|
102
185
|
* Declared capability metadata was previously never checked anywhere, which made
|
|
103
|
-
* `supportedActivations` documentation rather than a contract.
|
|
186
|
+
* `supportedActivations` documentation rather than a contract. The checks themselves live in
|
|
187
|
+
* `activation.ts`'s diagnostics half — they grew a good deal when the list opened, and they
|
|
188
|
+
* decide nothing, so keeping them here would have made this class the place where "which
|
|
189
|
+
* activation" and "is that a real event" were the same paragraph.
|
|
104
190
|
*
|
|
105
191
|
* @complexity O(a) time in supported activations; O(1) space.
|
|
106
192
|
* @overallScore 100
|
|
107
193
|
*/
|
|
108
194
|
private resolveActivation;
|
|
195
|
+
/**
|
|
196
|
+
* Resolve the viewport gates (`above:` / `below:`) on this element's JavaScript-rendered effects.
|
|
197
|
+
*
|
|
198
|
+
* CSS-rendered segments are deliberately absent from this method. Their gate is compiled into the
|
|
199
|
+
* `animation-name` declaration as a `var()` the browser re-resolves on every resize with no
|
|
200
|
+
* script involved (see `core/breakpoints.ts`), which is the entire reason this feature does not
|
|
201
|
+
* need the teardown machinery `gsap.matchMedia()` is built around. A JavaScript-rendered effect
|
|
202
|
+
* has no `animation-name` for a stylesheet to neutralise, so it is the one case that has to be
|
|
203
|
+
* decided here — and, having been decided once, has to be re-decided when the viewport crosses
|
|
204
|
+
* the breakpoint it was decided at.
|
|
205
|
+
*
|
|
206
|
+
* @complexity O(e) time in JS-rendered effects; O(b) space, bounded by the scale's five names.
|
|
207
|
+
* @overallScore 100
|
|
208
|
+
*/
|
|
209
|
+
private applyViewportGates;
|
|
210
|
+
/**
|
|
211
|
+
* Arm live re-evaluation for one element, building the watcher on first use.
|
|
212
|
+
*
|
|
213
|
+
* Lazy so that a page with no JavaScript-rendered gate — which is most pages, since the catalog
|
|
214
|
+
* is overwhelmingly `css-keyframes` — binds no `MediaQueryList` listener at all.
|
|
215
|
+
*
|
|
216
|
+
* @complexity O(b) time in the element's breakpoints; O(1) amortised space.
|
|
217
|
+
* @overallScore 100
|
|
218
|
+
*/
|
|
219
|
+
private watchGates;
|
|
220
|
+
/**
|
|
221
|
+
* Rebuild one element because the viewport crossed a breakpoint its JS effects depend on.
|
|
222
|
+
*
|
|
223
|
+
* `release` then `process`, rather than a partial update, and rather than `process` alone:
|
|
224
|
+
* `process` short-circuits on an unchanged fingerprint, and the fingerprint is a hash of
|
|
225
|
+
* *attributes*, which have not changed — the viewport has. Releasing first is also what makes the
|
|
226
|
+
* transition safe mid-animation: it aborts the activation binding, runs each JS effect's own
|
|
227
|
+
* `destroy()`, and unwinds both ledgers, so the element is back at the author's own markup before
|
|
228
|
+
* the new plan touches it. That is the same path an attribute edit takes, so there is one
|
|
229
|
+
* teardown implementation rather than two.
|
|
230
|
+
*
|
|
231
|
+
* There is deliberately no "is this element still live?" guard. Every path that stops tracking an
|
|
232
|
+
* element goes through `release`, and `release` unwatches — so an element that reaches here is
|
|
233
|
+
* one the watcher still holds, which is one `release` has not run on, which is one that is live.
|
|
234
|
+
* A guard would be unreachable code pretending to be caution, the same call `positioned()` in
|
|
235
|
+
* `compile.ts` makes about its own missing branch.
|
|
236
|
+
*
|
|
237
|
+
* @complexity O(e) time in the element's composed effects; O(1) space.
|
|
238
|
+
* @overallScore 100
|
|
239
|
+
*/
|
|
240
|
+
private regate;
|
|
241
|
+
/** Route a document with any non-empty-selector group through the derived-host path; `true`
|
|
242
|
+
* when it did (a derived install's own `document` never carries one, so this cannot recurse). */
|
|
243
|
+
private installedAsHost;
|
|
109
244
|
private install;
|
|
245
|
+
/**
|
|
246
|
+
* Install a zero-instance aggregate host: a `target:` host with no own (empty-selector) group,
|
|
247
|
+
* whose status mirrors its derived matches' instead of running any effect of its own
|
|
248
|
+
* (`syncAggregate`). Called by 2a's `installWithTargets` after every claimed match has already
|
|
249
|
+
* been installed, which is what D-E's stamping order requires — the host's own `data-kui-state`
|
|
250
|
+
* must never appear before its matches'.
|
|
251
|
+
*
|
|
252
|
+
* @complexity O(g) time in the document's group count; O(1) space.
|
|
253
|
+
* @overallScore 100
|
|
254
|
+
*/
|
|
255
|
+
private installAggregate;
|
|
256
|
+
/**
|
|
257
|
+
* Apply one `target:` group's compiled plan to every element its selector resolved to.
|
|
258
|
+
*
|
|
259
|
+
* Its own `planStyles` call, not the element-wide one `install` already made: `declarations` are
|
|
260
|
+
* per group, so `fade-up target:h2, pin` writes different properties to the `h2` than to the host
|
|
261
|
+
* even though both share one gate, one activation and one reduced-motion policy (which is exactly
|
|
262
|
+
* what `elementHasCssAnimation` carries in from the caller).
|
|
263
|
+
*
|
|
264
|
+
* `group.target.selector` is always `''` here — `installedAsHost` diverts any document carrying a
|
|
265
|
+
* real `target:` group to `installWithTargets` before `install` (this method's only caller) ever
|
|
266
|
+
* runs, so `matches` is always the host's own single-element `[el]` (target:-everywhere reconcile
|
|
267
|
+
* R-8 removed the in-place relocation path this method used to also handle, along with the
|
|
268
|
+
* `indexTargetGroup` call it made only for a real group — `restageTargets`, in
|
|
269
|
+
* `core/derived/install.ts`, is the one that indexes a real target group's stagger keys now).
|
|
270
|
+
*
|
|
271
|
+
* @complexity O(m * p) time in the group's matches and the plan's properties; O(p) space.
|
|
272
|
+
* @overallScore 100
|
|
273
|
+
*/
|
|
274
|
+
private installGroup;
|
|
275
|
+
/**
|
|
276
|
+
* Write one group's plan onto one of its matched elements, and register the instances that plan
|
|
277
|
+
* produced there.
|
|
278
|
+
*
|
|
279
|
+
* Every write goes through `context.ledgers`, never `match.style`/`match.setAttribute` directly:
|
|
280
|
+
* under `scope:page` a match need not be a descendant of the host at all, so the ledger set is
|
|
281
|
+
* the only thing that knows to unwind it on `release()`.
|
|
282
|
+
*
|
|
283
|
+
* @complexity O(p) time in the plan's property count; O(1) space beyond the instances pushed.
|
|
284
|
+
* @overallScore 100
|
|
285
|
+
*/
|
|
286
|
+
private installMatch;
|
|
287
|
+
/**
|
|
288
|
+
* Wire an authored `func:` to this element's completion.
|
|
289
|
+
*
|
|
290
|
+
* Registered as an ordinary `kui:finish` listener rather than called from a dispatch site, so it
|
|
291
|
+
* can never fire at a moment the event does not — the key is sugar for that listener, and is
|
|
292
|
+
* implemented as literally that listener. It detaches with every other binding on
|
|
293
|
+
* `controller.abort()`.
|
|
294
|
+
*
|
|
295
|
+
* Called from `install` *before* `openGate`, and the order is load-bearing: the one `kui:finish`
|
|
296
|
+
* an element can receive during install is the synchronous `reduced-motion` one, and the visitor
|
|
297
|
+
* who asked for reduced motion is the last one whose chained step should silently be dropped.
|
|
298
|
+
*
|
|
299
|
+
* See `callback.ts` for the lookup rules, and for why this key must never be built from
|
|
300
|
+
* untrusted input.
|
|
301
|
+
*
|
|
302
|
+
* @complexity O(1) time and space.
|
|
303
|
+
* @overallScore 100
|
|
304
|
+
*/
|
|
305
|
+
private bindAuthorCallback;
|
|
306
|
+
/**
|
|
307
|
+
* Validate and resolve one `CompiledTarget`'s selector against the live document.
|
|
308
|
+
*
|
|
309
|
+
* `resolveTarget`'s document-wide/invalid rejection — the same rule the six built-in
|
|
310
|
+
* `target:`-declaring primitives apply inside their own `prepare` — has to run again here for
|
|
311
|
+
* every *other* primitive: a CSS-rendered retargeted effect never calls `prepare` at all, so
|
|
312
|
+
* compile-to-install time is the only point at which this element has a real `Document` to
|
|
313
|
+
* validate the selector against. `compileTargets` itself is pure and DOM-free by design and
|
|
314
|
+
* cannot do this check.
|
|
315
|
+
*
|
|
316
|
+
* @param el - The host. The search root under `'self'`, and the only "match" for the host group
|
|
317
|
+
* (`target.selector === ''`), which is never queried at all.
|
|
318
|
+
* @returns The matches, in document order. Empty when the selector was invalid, too broad, or
|
|
319
|
+
* simply matched nothing — every case already warned by name.
|
|
320
|
+
* @complexity O(1) for the host group; O(n) in document size otherwise, the query itself being
|
|
321
|
+
* the DOM's.
|
|
322
|
+
* @overallScore 100
|
|
323
|
+
*/
|
|
324
|
+
private resolveGroupMatches;
|
|
110
325
|
/**
|
|
111
326
|
* Decide whether, and when, the effects on this element are allowed to start.
|
|
112
327
|
*
|
|
@@ -119,6 +334,41 @@ export declare class Animator {
|
|
|
119
334
|
* @overallScore 100
|
|
120
335
|
*/
|
|
121
336
|
private openGate;
|
|
337
|
+
/**
|
|
338
|
+
* Whether the visitor's own reduced-motion preference disables this plan outright, rather than
|
|
339
|
+
* merely shortening or crossfading it.
|
|
340
|
+
*
|
|
341
|
+
* Pulled out of `openGate` so that method's own branching stays about *what to do*, not about
|
|
342
|
+
* the two-part question of whether the policy applies at all.
|
|
343
|
+
*
|
|
344
|
+
* @complexity O(1) time and space.
|
|
345
|
+
* @overallScore 100
|
|
346
|
+
*/
|
|
347
|
+
private reducedMotionDisables;
|
|
348
|
+
/**
|
|
349
|
+
* Report every way an authored `actions:` cannot do what it says, once, at bind time.
|
|
350
|
+
*
|
|
351
|
+
* At bind time rather than per crossing, and that is the whole reason this is a separate method:
|
|
352
|
+
* a crossing fires on every scroll pass, and a diagnostic repeated on each one is a diagnostic
|
|
353
|
+
* nobody reads. It is the same discipline `control.ts` applies — warn once at construction, even
|
|
354
|
+
* for a caller who only meant to read.
|
|
355
|
+
*
|
|
356
|
+
* @complexity O(1) time and space.
|
|
357
|
+
* @overallScore 100
|
|
358
|
+
*/
|
|
359
|
+
private warnAboutCrossings;
|
|
360
|
+
/**
|
|
361
|
+
* Do whatever this element's `actions:` names for the crossing that just happened.
|
|
362
|
+
*
|
|
363
|
+
* A pure dispatch, and deliberately nothing more. `toggle-actions.ts` owns what each verb means,
|
|
364
|
+
* `activation.ts` owns which crossing it was, and this method's only contribution is the two
|
|
365
|
+
* things neither of them can reach: the element's own directional transitions, and its instances'
|
|
366
|
+
* playheads. If anything resembling animation logic ever appears here, it is in the wrong file.
|
|
367
|
+
*
|
|
368
|
+
* @complexity O(n) time in the element's instances; O(n) space.
|
|
369
|
+
* @overallScore 100
|
|
370
|
+
*/
|
|
371
|
+
private applyCrossing;
|
|
122
372
|
/**
|
|
123
373
|
* Start a deferred animation.
|
|
124
374
|
*
|
|
@@ -135,6 +385,180 @@ export declare class Animator {
|
|
|
135
385
|
* @overallScore 100
|
|
136
386
|
*/
|
|
137
387
|
activate(el: Element): void;
|
|
388
|
+
/** The per-element half of {@link activate} — see that method's own doc comment. */
|
|
389
|
+
private activateOne;
|
|
390
|
+
/**
|
|
391
|
+
* Play an element's effects back out.
|
|
392
|
+
*
|
|
393
|
+
* The exit half of a paired activation — `data-kui-on="pointerenter/pointerleave"`,
|
|
394
|
+
* `data-kui-on="enter/leave"` — routed through one method for the same reason `activate` is: it
|
|
395
|
+
* is the single place an effect ever runs backwards, so what an exit means does not have to be
|
|
396
|
+
* re-decided per activation.
|
|
397
|
+
*
|
|
398
|
+
* **CSS-rendered effects reverse; JS-rendered ones do not, and say so.** A CSS effect has a real
|
|
399
|
+
* `Animation` handle whose playback rate can simply be negated, landing on the from-state that
|
|
400
|
+
* `animation-fill-mode: both` is already holding. A JS-rendered effect has no playhead at all —
|
|
401
|
+
* `getAnimations()` returns `[]` for it (see `play.ts`) — and there is no honest general shim
|
|
402
|
+
* for "half a `split-flap`, backwards". Rather than invent one that misbehaves differently per
|
|
403
|
+
* primitive, an instance that cannot reverse is named in a warning; the author learns their
|
|
404
|
+
* pointerleave does nothing *here* instead of discovering it in a browser. On an element
|
|
405
|
+
* composing both renderers the CSS half still reverses and the warning names what did not.
|
|
406
|
+
*
|
|
407
|
+
* @param el - Element whose effects should play out.
|
|
408
|
+
* @complexity O(n) time in the number of instances; O(1) space.
|
|
409
|
+
* @overallScore 100
|
|
410
|
+
*/
|
|
411
|
+
deactivate(el: Element): void;
|
|
412
|
+
/**
|
|
413
|
+
* Turn an element's playhead around and settle it back at the from-state it started from.
|
|
414
|
+
*
|
|
415
|
+
* The single owner of `state.direction === 'reverse'`, and it exists as its own method because
|
|
416
|
+
* for a while there were two owners and neither knew about the other. `deactivate()` — the exit
|
|
417
|
+
* half of a paired activation — flipped the direction and re-armed the settle gate;
|
|
418
|
+
* `control(el).reverse()` reached straight past the state machine into the raw `Animation`
|
|
419
|
+
* handles through `InstanceControl.reverse`. Both moved the same playheads, only one of them said
|
|
420
|
+
* so, and an animator that believed a reversing element was still travelling forwards got three
|
|
421
|
+
* things wrong at once: a later `deactivate()` sailed through its "an exit already in flight must
|
|
422
|
+
* not restart" guard and began a *second* reverse; `activate()` could never turn the playhead
|
|
423
|
+
* around, because it looks for `'reverse'` and never saw it; and the forward `settleWhen` left
|
|
424
|
+
* over from the entrance stayed pending until it stamped `data-kui-state="finished"` onto an
|
|
425
|
+
* element sitting at its from-state.
|
|
426
|
+
*
|
|
427
|
+
* So the transition lives here and both entry points call it. What `deactivate()` keeps is only
|
|
428
|
+
* what is true of an *activation* exit specifically. A programmatic reverse is not one — an
|
|
429
|
+
* author calling `control().reverse()` has not had a pointer leave anything — so it inherits
|
|
430
|
+
* none of that, and in particular is not told that the effects it cannot reach make "the exit
|
|
431
|
+
* half of this activation" do nothing. `control.ts` has already named those for it.
|
|
432
|
+
*
|
|
433
|
+
* Resuming forward travel is `activate()`'s job, not a second method here: an element left in
|
|
434
|
+
* `'reverse'` is turned around by `turnAround`, which is reachable from every route that
|
|
435
|
+
* activates — a pointer coming back, `play()`, `kui.activate()`.
|
|
436
|
+
*
|
|
437
|
+
* @param el - Element whose effects should run backwards. Unknown elements are ignored, exactly
|
|
438
|
+
* as they are by `activate` and `deactivate`.
|
|
439
|
+
* @complexity O(n) time in the number of instances; O(1) space.
|
|
440
|
+
* @overallScore 100
|
|
441
|
+
*/
|
|
442
|
+
reverseFrom(el: Element): void;
|
|
443
|
+
/** The per-element half of {@link reverseFrom} — see that method's own doc comment. */
|
|
444
|
+
private reverseOne;
|
|
445
|
+
/**
|
|
446
|
+
* Resume forward playback on an element whose exit is still in flight.
|
|
447
|
+
*
|
|
448
|
+
* Separate from `activate`'s main path because none of that path applies: the instances are
|
|
449
|
+
* already started, the activation is already spent, and the state is already `running`. All that
|
|
450
|
+
* changes is the direction of travel.
|
|
451
|
+
*
|
|
452
|
+
* @complexity O(n) time in the number of instances; O(1) space.
|
|
453
|
+
* @overallScore 100
|
|
454
|
+
*/
|
|
455
|
+
private turnAround;
|
|
456
|
+
/**
|
|
457
|
+
* Write an element's final state once the instances driving it have finished.
|
|
458
|
+
*
|
|
459
|
+
* The reported state has to become truthful eventually, or `data-kui-state` codifies a lie that
|
|
460
|
+
* tests then assert against. It also has to stay truthful when a run is superseded mid-flight: a
|
|
461
|
+
* reverse that is turned around leaves its own `finished` promise pending, and letting that
|
|
462
|
+
* promise write `ready` over the forward run that replaced it is how an element ends up claiming
|
|
463
|
+
* it is back at its from-state while visibly finishing its entrance. Capturing the direction at
|
|
464
|
+
* the time of the call and re-checking it on resolution is what makes the stale promise a no-op
|
|
465
|
+
* in the ordinary case — turned-around and reversed-again runs, which is why that comment and
|
|
466
|
+
* check are kept even though `run` below also covers them.
|
|
467
|
+
*
|
|
468
|
+
* `run` is the check `direction` cannot be: `direction` only ever holds two values, so a run
|
|
469
|
+
* that flips back and forth several times (a hover-driven card flip, `pointerenter`/
|
|
470
|
+
* `pointerleave` firing repeatedly) revisits the same direction repeatedly, and a stale run's
|
|
471
|
+
* belated completion could otherwise be mistaken for a much later one simply travelling the same
|
|
472
|
+
* way. `beginRun` mints one identity per run; only the run that is still current when its own
|
|
473
|
+
* promise resolves gets to report anything.
|
|
474
|
+
*
|
|
475
|
+
* @param target - The element, its state, and this run's identity — see {@link SettleTarget}.
|
|
476
|
+
* @param instances - The instances this particular run started; a run only waits on its own.
|
|
477
|
+
* @param next - State to report when they are all done.
|
|
478
|
+
* @complexity O(n) time in the instances; O(n) space for the pending promises.
|
|
479
|
+
* @overallScore 100
|
|
480
|
+
*/
|
|
481
|
+
private settleWhen;
|
|
482
|
+
/**
|
|
483
|
+
* Mark the start of a new run — a forward activation, a reversal, or a turnaround out of one —
|
|
484
|
+
* and clear the mark a previous run's cancellation left behind.
|
|
485
|
+
*
|
|
486
|
+
* The two things a fresh run does are bound together deliberately: `cancelled` describes *this*
|
|
487
|
+
* run, not the element for life, so every place that begins one must also disown whatever the
|
|
488
|
+
* run before it was marked with, or that run's cancellation would silently apply to a completion
|
|
489
|
+
* it had nothing to do with — see `InstanceState.cancelled`'s own doc comment for the contract
|
|
490
|
+
* this keeps. Doing both here, in one call, is what stops a caller resetting one without the
|
|
491
|
+
* other; three call sites each remembering to write two lines in the right order was exactly
|
|
492
|
+
* this bug's shape the first time.
|
|
493
|
+
*
|
|
494
|
+
* @returns This run's identity, to be threaded through to the `settleWhen` call that will
|
|
495
|
+
* eventually report on it.
|
|
496
|
+
* @complexity O(1) time, O(1) space.
|
|
497
|
+
* @overallScore 100
|
|
498
|
+
*/
|
|
499
|
+
private beginRun;
|
|
500
|
+
/**
|
|
501
|
+
* Dispatch one lifecycle event for an element, filling in the identity every listener needs.
|
|
502
|
+
*
|
|
503
|
+
* Centralised here rather than inside each instance because the animator is the only place that
|
|
504
|
+
* knows the *element's* lifecycle — an element composing three effects starts once and finishes
|
|
505
|
+
* once, not three times, and only this class sees all three instances at the same moment.
|
|
506
|
+
*
|
|
507
|
+
* @complexity O(n) time in listeners on the propagation path; O(1) space.
|
|
508
|
+
* @overallScore 100
|
|
509
|
+
*/
|
|
510
|
+
private emit;
|
|
511
|
+
/**
|
|
512
|
+
* Write one element's status, through its own ledger, with no aggregate sync.
|
|
513
|
+
*
|
|
514
|
+
* The one place `status`/`data-kui-state` are written together, so every call site that used to
|
|
515
|
+
* write both fields by hand now shares one line to drift out of sync in. `el` is unused today —
|
|
516
|
+
* kept because 2b's tests and a future per-element hook both key on it, and because every other
|
|
517
|
+
* write in this file takes the element it writes to as its first argument.
|
|
518
|
+
*
|
|
519
|
+
* @complexity O(1) time and space.
|
|
520
|
+
* @overallScore 100
|
|
521
|
+
*/
|
|
522
|
+
private writeStatus;
|
|
523
|
+
/**
|
|
524
|
+
* Let a derived state's host re-derive its aggregate status (D-A).
|
|
525
|
+
*
|
|
526
|
+
* Called after the derived element's own event, so listeners see the match's event before the
|
|
527
|
+
* host's — the same order a nested DOM structure would deliver them in were the host merely
|
|
528
|
+
* listening for its children's events instead of deriving its own status from them.
|
|
529
|
+
*
|
|
530
|
+
* @complexity O(1) time and space, delegating to {@link syncAggregate}.
|
|
531
|
+
* @overallScore 100
|
|
532
|
+
*/
|
|
533
|
+
private syncHost;
|
|
534
|
+
/**
|
|
535
|
+
* Stop one element's effects where they are, leaving it mid-animation.
|
|
536
|
+
*
|
|
537
|
+
* The counterpart to `activate()`, and the reason it exists rather than callers reaching into
|
|
538
|
+
* `stateOf(el).instances` themselves (which is what `play()`'s handle used to do): cancellation
|
|
539
|
+
* has an observable consequence — `kui:cancel`, and the suppression of the `kui:finish` that
|
|
540
|
+
* would otherwise follow it — and that consequence has to be applied wherever cancellation
|
|
541
|
+
* happens, not only where it happens to be convenient.
|
|
542
|
+
*
|
|
543
|
+
* @param el - Element whose effects should stop.
|
|
544
|
+
* @complexity O(n) time in the element's instances; O(1) space.
|
|
545
|
+
* @overallScore 100
|
|
546
|
+
*/
|
|
547
|
+
cancel(el: Element): void;
|
|
548
|
+
/** The per-element half of {@link cancel} — see that method's own doc comment. */
|
|
549
|
+
private cancelOne;
|
|
550
|
+
/**
|
|
551
|
+
* Runtime control over a selection's playheads — pause, resume, reverse, seek, re-speed.
|
|
552
|
+
*
|
|
553
|
+
* Selection-shaped rather than single-element, so it matches `play()` and so one call covers a
|
|
554
|
+
* staggered group. `control.ts` builds a per-element handle underneath and the returned handle
|
|
555
|
+
* composes them.
|
|
556
|
+
*
|
|
557
|
+
* @param target - Selector, element, or iterable of elements.
|
|
558
|
+
* @complexity O(n) time in selected elements and their instances; O(n) space.
|
|
559
|
+
* @overallScore 100
|
|
560
|
+
*/
|
|
561
|
+
control(target: Target): ControlHandle;
|
|
138
562
|
/**
|
|
139
563
|
* Activate one instance, isolating a throw from its (possibly deferred) setup.
|
|
140
564
|
*
|
|
@@ -161,6 +585,10 @@ export declare class Animator {
|
|
|
161
585
|
*/
|
|
162
586
|
uncloak(): void;
|
|
163
587
|
stateOf(el: Element): InstanceState | undefined;
|
|
588
|
+
/** The derived matches a host's `target:` groups installed, in document order. `[]` otherwise. */
|
|
589
|
+
derivedOf(el: Element): Element[];
|
|
590
|
+
/** The host that installed a derived match, else `undefined`. */
|
|
591
|
+
hostOf(el: Element): Element | undefined;
|
|
164
592
|
/**
|
|
165
593
|
* Tear an element's effects down so the next `process()` reinstalls from scratch.
|
|
166
594
|
*
|
|
@@ -195,8 +623,15 @@ export declare class Animator {
|
|
|
195
623
|
* method's only caller — is itself typed `(el: Element) => void`, so there is no runtime case
|
|
196
624
|
* where `node` is a `Document`/`DocumentFragment` to guard against.
|
|
197
625
|
*
|
|
626
|
+
* `restageAfterRemoval` runs over every candidate visited, not only the ones actually released:
|
|
627
|
+
* a removed stagger member is exactly the case this closes, and whether it was "live" by
|
|
628
|
+
* `liveElements`' definition is a question `GROUP_OF_CHILD` (in `stagger.ts`) answers on its own
|
|
629
|
+
* terms. Without it, removing one item from a staggered group left every later sibling holding
|
|
630
|
+
* the rank an index computed for a group one element larger — the stale-after-*edit* half of the
|
|
631
|
+
* same defect `3d57ff7` already closed for an attribute change, left open for a removal.
|
|
632
|
+
*
|
|
198
633
|
* @complexity O(s) time in the removed subtree's element count; O(1) per candidate via the
|
|
199
|
-
* `liveElements` Set lookup.
|
|
634
|
+
* `liveElements` Set lookup, plus stagger re-ranking bounded by the surviving groups' own sizes.
|
|
200
635
|
* @overallScore 100
|
|
201
636
|
*/
|
|
202
637
|
private releaseTree;
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
export declare const ATTR: {
|
|
3
3
|
/** Authored. The rich grammar. */
|
|
4
4
|
readonly source: "data-kui";
|
|
5
|
+
/**
|
|
6
|
+
* Authored. Names the composition in this element's {@link source} so other elements can reuse
|
|
7
|
+
* it by name. An element carrying it is a definition — data, never animated. See `core/bundles.ts`.
|
|
8
|
+
*/
|
|
9
|
+
readonly define: "data-kui-define";
|
|
5
10
|
/** Library-owned and unstable: normalized effect names, for CSS hooks and debugging. */
|
|
6
11
|
readonly normalized: "data-kui-fx";
|
|
7
12
|
readonly state: "data-kui-state";
|
|
@@ -12,4 +17,8 @@ export declare const ATTR: {
|
|
|
12
17
|
readonly cloak: "data-kui-cloak";
|
|
13
18
|
/** Reduced-motion policy, stamped from the primitive so the CSS layer can act on it. */
|
|
14
19
|
readonly rm: "data-kui-rm";
|
|
20
|
+
/** Library-owned: comma list of `target:` selectors on this host that matched nothing (D). */
|
|
21
|
+
readonly unmatched: "data-kui-unmatched";
|
|
22
|
+
/** Library-owned: a structural role the library assigned to a child (`front`,`back`,`control`,`bar`). */
|
|
23
|
+
readonly part: "data-kui-part";
|
|
15
24
|
};
|