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.
Files changed (124) hide show
  1. package/README.md +93 -10
  2. package/dist/esm/advanced/index.mjs +4727 -0
  3. package/dist/esm/chunk-AEQGC2KM.mjs +189 -0
  4. package/dist/esm/chunk-MQSNMYRP.mjs +9332 -0
  5. package/dist/esm/chunk-RVTYN6NZ.mjs +3446 -0
  6. package/dist/esm/chunk-U43BX5O2.mjs +2984 -0
  7. package/dist/esm/core/index.mjs +16 -9
  8. package/dist/esm/effects/index.mjs +19 -4
  9. package/dist/esm/index.mjs +17 -10
  10. package/dist/kuinetic.advanced.js +5070 -0
  11. package/dist/kuinetic.advanced.min.js +749 -0
  12. package/dist/kuinetic.all.js +15147 -6039
  13. package/dist/kuinetic.all.min.js +2 -0
  14. package/dist/kuinetic.css +2801 -318
  15. package/dist/kuinetic.js +15147 -6038
  16. package/dist/kuinetic.min.css +1 -0
  17. package/dist/kuinetic.min.js +7 -0
  18. package/dist/types/3d/angles.d.ts +30 -0
  19. package/dist/types/3d/flattening.d.ts +49 -0
  20. package/dist/types/3d/index.d.ts +36 -0
  21. package/dist/types/3d/model-3d.d.ts +115 -0
  22. package/dist/types/3d/register.d.ts +26 -0
  23. package/dist/types/3d/webgl.d.ts +24 -0
  24. package/dist/types/advanced/audio.d.ts +322 -0
  25. package/dist/types/advanced/base.d.ts +233 -0
  26. package/dist/types/advanced/camera-3d.d.ts +236 -0
  27. package/dist/types/advanced/fluid-cursor.d.ts +149 -0
  28. package/dist/types/advanced/gl-utils.d.ts +52 -0
  29. package/dist/types/advanced/glsl.d.ts +60 -0
  30. package/dist/types/advanced/index.d.ts +23 -0
  31. package/dist/types/advanced/particles.d.ts +108 -0
  32. package/dist/types/advanced/scenes.d.ts +207 -0
  33. package/dist/types/advanced/shaders.d.ts +972 -0
  34. package/dist/types/browser/boot.d.ts +72 -0
  35. package/dist/types/core/activation.d.ts +227 -2
  36. package/dist/types/core/animator.d.ts +446 -11
  37. package/dist/types/core/attrs.d.ts +9 -0
  38. package/dist/types/core/breakpoints.d.ts +260 -0
  39. package/dist/types/core/bundles.d.ts +71 -0
  40. package/dist/types/core/callback.d.ts +64 -0
  41. package/dist/types/core/capabilities.d.ts +47 -0
  42. package/dist/types/core/channels.d.ts +120 -2
  43. package/dist/types/core/cloak-selectors.d.ts +47 -0
  44. package/dist/types/core/compile.d.ts +207 -2
  45. package/dist/types/core/control.d.ts +218 -0
  46. package/dist/types/core/declarations.d.ts +128 -0
  47. package/dist/types/core/derived/aggregate.d.ts +43 -0
  48. package/dist/types/core/derived/book.d.ts +30 -0
  49. package/dist/types/core/derived/diagnostics.d.ts +51 -0
  50. package/dist/types/core/derived/group-gate.d.ts +62 -0
  51. package/dist/types/core/derived/install.d.ts +110 -0
  52. package/dist/types/core/derived/late-matches.d.ts +19 -0
  53. package/dist/types/core/derived/types.d.ts +108 -0
  54. package/dist/types/core/easing.d.ts +57 -0
  55. package/dist/types/core/element-config.d.ts +47 -6
  56. package/dist/types/core/element-size.d.ts +23 -0
  57. package/dist/types/core/event-sources.d.ts +39 -0
  58. package/dist/types/core/flip.d.ts +34 -1
  59. package/dist/types/core/gesture.d.ts +12 -0
  60. package/dist/types/core/host-facts.d.ts +155 -0
  61. package/dist/types/core/index.d.ts +7 -3
  62. package/dist/types/core/owned-styles.d.ts +129 -2
  63. package/dist/types/core/params.d.ts +48 -0
  64. package/dist/types/core/parse.d.ts +28 -1
  65. package/dist/types/core/register-into.d.ts +29 -0
  66. package/dist/types/core/registry.d.ts +10 -3
  67. package/dist/types/core/repeat.d.ts +91 -0
  68. package/dist/types/core/sequence.d.ts +126 -0
  69. package/dist/types/core/stagger-config.d.ts +199 -0
  70. package/dist/types/core/stagger-keys.d.ts +63 -0
  71. package/dist/types/core/stagger.d.ts +187 -6
  72. package/dist/types/core/style-plan.d.ts +21 -16
  73. package/dist/types/core/target.d.ts +128 -0
  74. package/dist/types/core/threshold-reachability.d.ts +45 -0
  75. package/dist/types/core/time-scale.d.ts +9 -0
  76. package/dist/types/core/toggle-actions.d.ts +141 -0
  77. package/dist/types/core/travel.d.ts +59 -0
  78. package/dist/types/core/types.d.ts +699 -13
  79. package/dist/types/core/unquoted-selectors.d.ts +53 -0
  80. package/dist/types/effects/carousel/drag.d.ts +80 -0
  81. package/dist/types/effects/carousel/index.d.ts +149 -0
  82. package/dist/types/effects/catalog/discrete.d.ts +13 -0
  83. package/dist/types/effects/catalog/interaction-proximity.d.ts +24 -0
  84. package/dist/types/effects/catalog/interaction-reveal.d.ts +248 -0
  85. package/dist/types/effects/catalog/interaction-shared.d.ts +42 -0
  86. package/dist/types/effects/catalog/interaction-states.d.ts +68 -0
  87. package/dist/types/effects/catalog/materials.d.ts +67 -0
  88. package/dist/types/effects/catalog/media-shared.d.ts +3 -2
  89. package/dist/types/effects/catalog/numbers-shared.d.ts +8 -5
  90. package/dist/types/effects/catalog/shared.d.ts +1 -1
  91. package/dist/types/effects/catalog/text-shared.d.ts +86 -10
  92. package/dist/types/effects/catalog/transforms.d.ts +13 -0
  93. package/dist/types/effects/catalog/view-transitions.d.ts +13 -0
  94. package/dist/types/effects/forms/primitives.d.ts +15 -4
  95. package/dist/types/effects/gestures/index.d.ts +53 -0
  96. package/dist/types/effects/index.d.ts +5 -0
  97. package/dist/types/effects/layout/presets.d.ts +35 -0
  98. package/dist/types/effects/motion-path/index.d.ts +35 -0
  99. package/dist/types/effects/scroll-mechanics/params.d.ts +23 -0
  100. package/dist/types/effects/scroll-mechanics/presets.d.ts +51 -0
  101. package/dist/types/effects/scroll-mechanics/section-index.d.ts +47 -0
  102. package/dist/types/effects/shared.d.ts +124 -4
  103. package/dist/types/effects/step-index.d.ts +121 -0
  104. package/dist/types/effects/step-marking.d.ts +41 -33
  105. package/dist/types/effects/svg/icon-parts.d.ts +23 -0
  106. package/dist/types/effects/three-d/flip-parts.d.ts +46 -0
  107. package/dist/types/effects/tween/index.d.ts +57 -0
  108. package/dist/types/effects/tween/properties.d.ts +107 -0
  109. package/dist/types/effects/tween/waypoints.d.ts +106 -0
  110. package/dist/types/showcase/compare.d.ts +4 -0
  111. package/dist/types/showcase/device-frame.d.ts +3 -0
  112. package/dist/types/showcase/hotspots.d.ts +3 -0
  113. package/dist/types/showcase/index.d.ts +30 -0
  114. package/dist/types/showcase/lightbox.d.ts +3 -0
  115. package/dist/types/showcase/media-source.d.ts +13 -0
  116. package/dist/types/showcase/modal-shell.d.ts +22 -0
  117. package/dist/types/showcase/scroll-story.d.ts +4 -0
  118. package/dist/types/showcase/shared.d.ts +47 -0
  119. package/dist/types/showcase/slideshow.d.ts +3 -0
  120. package/dist/types/showcase/slow-mo.d.ts +5 -0
  121. package/package.json +14 -7
  122. package/dist/esm/chunk-7WMNPIOZ.mjs +0 -4883
  123. package/dist/esm/chunk-JT4PZL3A.mjs +0 -773
  124. 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
- private readonly reporter;
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 warning when an authored activation is not one the effect supports.
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
  };