kuinetic 0.1.3 → 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 (125) 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 +15218 -5595
  13. package/dist/kuinetic.all.min.js +2 -0
  14. package/dist/kuinetic.css +2900 -360
  15. package/dist/kuinetic.js +15217 -5593
  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 +705 -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/background-media.d.ts +152 -0
  83. package/dist/types/effects/catalog/discrete.d.ts +13 -0
  84. package/dist/types/effects/catalog/interaction-proximity.d.ts +24 -0
  85. package/dist/types/effects/catalog/interaction-reveal.d.ts +248 -0
  86. package/dist/types/effects/catalog/interaction-shared.d.ts +42 -0
  87. package/dist/types/effects/catalog/interaction-states.d.ts +68 -0
  88. package/dist/types/effects/catalog/materials.d.ts +67 -0
  89. package/dist/types/effects/catalog/media-shared.d.ts +3 -2
  90. package/dist/types/effects/catalog/numbers-shared.d.ts +8 -5
  91. package/dist/types/effects/catalog/shared.d.ts +2 -2
  92. package/dist/types/effects/catalog/text-shared.d.ts +92 -10
  93. package/dist/types/effects/catalog/transforms.d.ts +13 -0
  94. package/dist/types/effects/catalog/view-transitions.d.ts +13 -0
  95. package/dist/types/effects/forms/primitives.d.ts +15 -4
  96. package/dist/types/effects/gestures/index.d.ts +53 -0
  97. package/dist/types/effects/index.d.ts +5 -0
  98. package/dist/types/effects/layout/presets.d.ts +35 -0
  99. package/dist/types/effects/motion-path/index.d.ts +35 -0
  100. package/dist/types/effects/scroll-mechanics/params.d.ts +23 -0
  101. package/dist/types/effects/scroll-mechanics/presets.d.ts +51 -0
  102. package/dist/types/effects/scroll-mechanics/section-index.d.ts +47 -0
  103. package/dist/types/effects/shared.d.ts +162 -2
  104. package/dist/types/effects/step-index.d.ts +121 -0
  105. package/dist/types/effects/step-marking.d.ts +41 -33
  106. package/dist/types/effects/svg/icon-parts.d.ts +23 -0
  107. package/dist/types/effects/three-d/flip-parts.d.ts +46 -0
  108. package/dist/types/effects/tween/index.d.ts +57 -0
  109. package/dist/types/effects/tween/properties.d.ts +107 -0
  110. package/dist/types/effects/tween/waypoints.d.ts +106 -0
  111. package/dist/types/showcase/compare.d.ts +4 -0
  112. package/dist/types/showcase/device-frame.d.ts +3 -0
  113. package/dist/types/showcase/hotspots.d.ts +3 -0
  114. package/dist/types/showcase/index.d.ts +30 -0
  115. package/dist/types/showcase/lightbox.d.ts +3 -0
  116. package/dist/types/showcase/media-source.d.ts +13 -0
  117. package/dist/types/showcase/modal-shell.d.ts +22 -0
  118. package/dist/types/showcase/scroll-story.d.ts +4 -0
  119. package/dist/types/showcase/shared.d.ts +47 -0
  120. package/dist/types/showcase/slideshow.d.ts +3 -0
  121. package/dist/types/showcase/slow-mo.d.ts +5 -0
  122. package/package.json +14 -7
  123. package/dist/esm/chunk-5DON3UFQ.mjs +0 -4380
  124. package/dist/esm/chunk-JT4PZL3A.mjs +0 -773
  125. package/dist/esm/chunk-QUVFODSQ.mjs +0 -1278
@@ -0,0 +1,51 @@
1
+ import type { AnimatorPort } from './types.js';
2
+ import type { CompiledTarget } from '../compile.js';
3
+ import type { AttributeLedger } from '../owned-styles.js';
4
+ /**
5
+ * D(a): write `data-kui-unmatched="<sel>, <sel>"` on `host`, listing every `target:` group selector
6
+ * that matched nothing (plus 9b's suspect segments) — the one host-visible signal that a `target:`
7
+ * declaration silently found nothing to animate. Through `attributes` when given, so the write is
8
+ * unwound on release like every other library-owned attribute; a plain `setAttribute`/
9
+ * `removeAttribute` when the host has no ledger at all (it failed outright and was never given
10
+ * one).
11
+ *
12
+ * An empty `selectors` removes the attribute rather than writing an empty string. `AttributeLedger`
13
+ * has no `remove`, so that branch always goes straight through `host.removeAttribute` even when a
14
+ * ledger is given — safe, because a ledger only ever records an attribute's original value on its
15
+ * first `set`; if this call never calls `set`, `restore()` has nothing of ours to unwind here.
16
+ *
17
+ * @param host - The element to stamp.
18
+ * @param selectors - Every selector that matched nothing, in authored order. `[]` removes the
19
+ * attribute rather than writing an empty one.
20
+ * @param attributes - The host's own attribute ledger, when it has one.
21
+ * @complexity O(n) time in `selectors.length` (the join); O(1) space beyond the joined string.
22
+ * @overallScore 100
23
+ */
24
+ export declare function markUnmatched(host: Element, selectors: string[], attributes?: AttributeLedger): void;
25
+ /**
26
+ * Warn when a derived match whose effects establish a 3D rendering context (`Preset.establishes3d`)
27
+ * sits inside an element — the host, or a live-state ancestor — that is also running one
28
+ * (memory: no-nested-3d). `preserve-3d`/`perspective` contexts do not compose when nested, so this
29
+ * is surfaced as early as possible rather than left to look like a broken effect.
30
+ *
31
+ * @param port - The animator's narrow window.
32
+ * @param host - The `target:` host installing `match`.
33
+ * @param match - The derived match being installed.
34
+ * @param target - The compiled group `match` was claimed by (its own group, or 2b's union).
35
+ * @complexity O(d) time in DOM depth, bounded by `ANCESTOR_WALK_BOUND`; O(1) space.
36
+ * @overallScore 100
37
+ */
38
+ export declare function warnNested3d(port: AnimatorPort, host: Element, match: Element, target: CompiledTarget): void;
39
+ /**
40
+ * Warn when a `cloak: true` preset is retargeted with `scope:page` while `<html data-kui-cloak>`
41
+ * is present — a page-scope match can sit anywhere in the document, including outside the host's
42
+ * own subtree, so the pre-JS cloak selector (9a) cannot reach it and it will flash unstyled before
43
+ * the animator ever runs.
44
+ *
45
+ * @param port - The animator's narrow window.
46
+ * @param host - The `target:` host.
47
+ * @param target - The compiled `scope:page` group carrying a `cloak: true` preset.
48
+ * @complexity O(n) time in the group's effect count; O(1) space.
49
+ * @overallScore 100
50
+ */
51
+ export declare function warnPageScopeCloak(port: AnimatorPort, host: Element, target: CompiledTarget): void;
@@ -0,0 +1,62 @@
1
+ import type { AnimatorPort, DerivedInstallContext } from './types.js';
2
+ import type { CompiledTarget } from '../compile.js';
3
+ import type { InstanceState } from '../types.js';
4
+ /**
5
+ * Owned by phase 3b — B-a's "one host binding when grouped" rule. A `target:` group whose
6
+ * effective stagger keys carry `cascade:`/`spread:`/`order:` is read across the whole group at
7
+ * once, so it gets one activation binding on the *host* that fans out to every member in document
8
+ * order, instead of each member independently binding its own gate the way an ordinary derived
9
+ * match does.
10
+ */
11
+ /**
12
+ * The gate owner for one derived group: the host itself, when the group's effective stagger keys
13
+ * are grouped (`isGroupedKeys`); `undefined` otherwise, meaning each member binds its own gate as
14
+ * an ordinary derived install would.
15
+ *
16
+ * The effective keys follow the same "each key decided on its own" rule the rest of `target:`
17
+ * uses: the group's own scoped hoists (`target.hoists`) override the host's element-wide keys
18
+ * per key, via {@link staggerKeysFor}/{@link elementStaggerKeys} — the identical recipe
19
+ * `restageTargets` uses to index the group, so a group that reads as "grouped" for stagger
20
+ * indexing reads as "grouped" for gating too.
21
+ *
22
+ * @param port - The animator's narrow window. Unused: the decision only needs the group's own
23
+ * keys, not anything the animator itself knows — kept in the signature for parity with every
24
+ * other derived-host module function, all of which take it.
25
+ * @param context - The host's derived-install context.
26
+ * @param target - The group being installed.
27
+ * @complexity O(1) time and space.
28
+ * @overallScore 100
29
+ */
30
+ export declare function groupGateOwner(port: AnimatorPort, context: DerivedInstallContext, target: CompiledTarget): Element | undefined;
31
+ /**
32
+ * Whether `Animator.openGate` must skip binding this (deferred-gate) element's own activation,
33
+ * because a grouped derived match's gate is owned by its host instead (`groupGateOwner`) —
34
+ * `state.gateOwner` names that host.
35
+ *
36
+ * `openGate` only ever reaches this check once it has already established `stylePlan.gate ===
37
+ * 'deferred'` (see `animator.ts`), so this needs no gate check of its own: `gateOwner` being set
38
+ * at all is sufficient.
39
+ *
40
+ * @param state - The element's instance state.
41
+ * @complexity O(1) time and space.
42
+ * @overallScore 100
43
+ */
44
+ export declare function skipsOwnBinding(state: InstanceState): boolean;
45
+ /**
46
+ * Install one activation binding on `host` per grouped live `target:` group, activating (and, for
47
+ * a paired exit, deactivating) every member in document order through `port.activateOne`/
48
+ * `port.deactivateOne` rather than each member's own gate. Registers its own release in
49
+ * `port.book.cleanups` so the binding is torn down when the host is released.
50
+ *
51
+ * Only groups `groupGateOwner` (via 2a) named `host` as the owner of are candidates — `host`'s
52
+ * other live groups, if any, are ungrouped and already bind per-member through the ordinary
53
+ * `openGate` path.
54
+ *
55
+ * @param port - The animator's narrow window.
56
+ * @param host - The `target:` host whose live groups may need a group binding.
57
+ * @complexity O(g) time in the host's live group count (each binding's own fan-out is amortized
58
+ * into its later `activate`/`deactivate` calls, not this call); O(1) space beyond what each
59
+ * binding retains.
60
+ * @overallScore 100
61
+ */
62
+ export declare function bindGroups(port: AnimatorPort, host: Element): void;
@@ -0,0 +1,110 @@
1
+ import type { CompiledTarget } from '../compile.js';
2
+ import type { ElementConfig } from '../element-config.js';
3
+ import type { AnimatorPort, DerivedInstallContext, InstallRequest, ResolvedGroup } from './types.js';
4
+ /**
5
+ * Install `request.el` the derived-host way: resolve every `target:` group's matches, apply the
6
+ * collision rules (D-D) to decide what this host may actually claim, install every claimed match as
7
+ * its own derived state, then the host's own group (or a zero-instance aggregate).
8
+ *
9
+ * A host with no own (untargeted) segment and nothing claimed has real compiled effects — `process`
10
+ * already ruled out zero effects entirely — but nowhere for any of them to run, so this is the
11
+ * `'failed'` outcome below.
12
+ *
13
+ * @param port - The animator's narrow window (see `AnimatorPort`).
14
+ * @param request - The would-be host's install request.
15
+ * Returns nothing: every non-empty-selector document is fully handled here, whether that means a
16
+ * real install or the `'failed'` outcome above, so `Animator.install` never falls through to its own
17
+ * body for a request it routed here.
18
+ * @complexity O(g * m) time in group count and matches per group (the resolve + claim passes); O(g +
19
+ * m) space.
20
+ * @overallScore 100
21
+ */
22
+ export declare function installWithTargets(port: AnimatorPort, request: InstallRequest): void;
23
+ /**
24
+ * Release a derived-host's bookkeeping, called at the very start of `Animator.release(el)`, before
25
+ * `el`'s own teardown runs. A host and a match are mutually exclusive — a match is never itself
26
+ * claimable as a `target:` host, because `claimMatches` refuses any candidate that already carries
27
+ * its own `data-kui` — so at most one of the two branches below ever does anything.
28
+ *
29
+ * @param port - The animator's narrow window.
30
+ * @param el - The element being released — a host, a derived match, or neither.
31
+ * @complexity O(1) time and space for a match; O(c) for a host, in its claimed-match and cleanup
32
+ * counts.
33
+ * @overallScore 100
34
+ */
35
+ export declare function releaseDerived(port: AnimatorPort, el: Element): void;
36
+ /**
37
+ * Called once at the end of `Animator.releaseTree`, after every removed candidate in the batch has
38
+ * had its own teardown run (and so its own `releaseDerived` match-branch, recording its former host
39
+ * via {@link rememberFormerHost}). Re-indexes every surviving host that lost one or more derived
40
+ * matches in this removal — the derived-host analogue of `restageAfterRemoval` for ordinary stagger
41
+ * groups — and lets it re-derive its aggregate status now that its membership has changed.
42
+ *
43
+ * @param port - The animator's narrow window.
44
+ * @param removed - Every element `releaseTree` visited while tearing down one removal batch.
45
+ * @complexity O(r) time in the removed-candidate count, plus each surviving host's own restage;
46
+ * O(h) space in the distinct former-host count.
47
+ * @overallScore 100
48
+ */
49
+ export declare function restageAfterTreeRelease(port: AnimatorPort, removed: Element[]): void;
50
+ /**
51
+ * Apply the collision rules (D-D) over one host's resolved `target:` groups, deciding which matched
52
+ * elements this host is actually allowed to claim.
53
+ *
54
+ * A match is skipped, with an aggregated warning naming the selector and the group's effects, when
55
+ * it is the host itself, when it already carries its own `data-kui` (an authored element animates
56
+ * itself, never a host's group), or when another host has already claimed it (first wins — whichever
57
+ * host's `scan()` reached it first). A match this same host has already claimed under an earlier
58
+ * group in the same resolution is joined into that claim silently — that is the ordinary "one
59
+ * element, several groups" case `compileUnion` exists for, not a collision.
60
+ *
61
+ * @param port - The animator's narrow window.
62
+ * @param host - The element whose `target:` groups are being resolved.
63
+ * @param groups - Every non-empty-selector group's `CompiledTarget` and its resolved matches.
64
+ * @returns Each claimed match mapped to every group of *this* host that claims it, in authored
65
+ * group order; the map's own iteration order is document order.
66
+ * @complexity O(g * m) time in groups and matches per group; O(m) space.
67
+ * @overallScore 100
68
+ */
69
+ export declare function claimMatches(port: AnimatorPort, host: Element, groups: ResolvedGroup[]): Map<Element, CompiledTarget[]>;
70
+ /**
71
+ * Install every claimed match as its own derived host — a single group installs directly, two or
72
+ * more recompile through `compileUnion` first — and record the result in `port.book` (the host's
73
+ * `derived` set, each match's `hosts` entry, and the owning group's `members`).
74
+ *
75
+ * Used both by `installWithTargets` (the initial install) and by phase 6's `adoptLateMatches` (a
76
+ * late-inserted match joining an already-live group).
77
+ *
78
+ * @param port - The animator's narrow window.
79
+ * @param context - The host's derived-install context (fingerprint, parsed value, base config).
80
+ * @param claims - `claimMatches`'s output: each match to install, and which of the host's groups
81
+ * claim it.
82
+ * @param cache - Group-config memoization, shared with `installWithTargets`'s own group resolution
83
+ * pass when one is available; a caller with no group-level pass of its own (a late adoption
84
+ * joining an already-live group) may omit it and get a fresh one, since there is nothing else in
85
+ * that case to share it with.
86
+ * @returns The matches actually installed, in claim order.
87
+ * @complexity O(m) time in the claimed-match count, plus each union's own compile on a cache miss;
88
+ * O(m) space.
89
+ * @overallScore 100
90
+ */
91
+ export declare function installDerivedMatches(port: AnimatorPort, context: DerivedInstallContext, claims: Map<Element, CompiledTarget[]>, cache?: Map<CompiledTarget, ElementConfig>): Element[];
92
+ /**
93
+ * Re-run `indexTargetGroup` for every one of a host's live `target:` groups, over its *current*
94
+ * members — each match's own `--kui-i` through its own ledger, the host's `--kui-stagger`/`-count`
95
+ * through the host's. Called whenever a group's membership changes after its initial install: a late
96
+ * adoption (phase 6) or a removal (`restageAfterTreeRelease`), as well as once at the end of the
97
+ * initial install itself.
98
+ *
99
+ * A group with no members is skipped outright — nothing to number, and nothing for `indexTargetGroup`
100
+ * to derive a step from. Two live groups on one host both write the host's `--kui-stagger`/`-count`;
101
+ * the second's write wins, matching HEAD's own single-group behaviour (there was never more than one
102
+ * write to race against before `target:` existed).
103
+ *
104
+ * @param port - The animator's narrow window.
105
+ * @param host - The `target:` host to re-index.
106
+ * @complexity O(g * m) time in the host's live groups and their member counts; O(1) space beyond
107
+ * `indexTargetGroup`'s own.
108
+ * @overallScore 100
109
+ */
110
+ export declare function restageTargets(port: AnimatorPort, host: Element): void;
@@ -0,0 +1,19 @@
1
+ import type { AnimatorPort } from './types.js';
2
+ /**
3
+ * C(a): a node was inserted under `observe:true`. Walk its ancestors (bounded) for a live
4
+ * `target:` host with `scope:'self'` groups, and for each, claim and install only matches it did
5
+ * not already have, then restage. Never re-processes a host: one straight-line ancestor walk from
6
+ * `node.parentElement` visits each ancestor at most once.
7
+ *
8
+ * `node` itself is skipped outright when it carries `ATTR.part`: 7a's injected flip-card control
9
+ * (and any other library-injected part) must never itself be adopted as a `target:` match, no
10
+ * matter what selector it happens to satisfy.
11
+ *
12
+ * @param port - The animator's narrow window.
13
+ * @param node - The newly inserted element.
14
+ * @complexity O(d * g * m) time in the walk depth (bounded by `ANCESTOR_WALK_BOUND`), each
15
+ * ancestor's live group count, and each group's match count; O(1) space beyond what each host's
16
+ * own reindex retains.
17
+ * @overallScore 100
18
+ */
19
+ export declare function adoptLateMatches(port: AnimatorPort, node: Element): void;
@@ -0,0 +1,108 @@
1
+ import type { ActivationBinder } from '../activation.js';
2
+ import type { Capabilities } from '../capabilities.js';
3
+ import type { CompiledDocument, CompiledPlan, CompiledTarget } from '../compile.js';
4
+ import type { LifecycleEventType, LifecycleReason } from '../control.js';
5
+ import type { ElementConfig } from '../element-config.js';
6
+ import type { Registry } from '../registry.js';
7
+ import type { Reporter } from '../reporter.js';
8
+ import type { Activation, InstanceState, ParsedValue, Timeline } from '../types.js';
9
+ export type { StaggerGroupKeys } from '../stagger-config.js';
10
+ /** Everything `Animator.install` needs. Moved here verbatim from `animator.ts`'s own
11
+ * `InstallRequest`, plus three optional fields that are absent for every HEAD code path. */
12
+ export interface InstallRequest {
13
+ el: Element;
14
+ fingerprint: string;
15
+ parsed: ParsedValue;
16
+ /** The element's config with its activation already resolved against its own group. */
17
+ config: ElementConfig;
18
+ document: CompiledDocument;
19
+ /** `resolveConfig`'s output BEFORE `resolveActivation` mutated `activation` — what each derived
20
+ * group's config is built from (`resolveGroupConfig(baseConfig, target.hoists)`). Set by
21
+ * `process()`; absent on a derived install. */
22
+ baseConfig?: ElementConfig;
23
+ /** Set only on a derived install: the authored element whose `target:` group installed `el`.
24
+ * `install` copies it to `InstanceState.host`. */
25
+ host?: Element;
26
+ /** Set only on a derived install of a *grouped* target (`cascade:`/`spread:`/`order:`): the
27
+ * element that owns the activation binding for it (always the host). `install` copies it to
28
+ * `InstanceState.gateOwner`; `openGate` then skips binding `el` itself. */
29
+ gateOwner?: Element;
30
+ }
31
+ /** One `CompiledTarget` and the live elements its selector resolved to. Moved from `animator.ts`'s
32
+ * own `ResolvedGroup`. */
33
+ export interface ResolvedGroup {
34
+ target: CompiledTarget;
35
+ matches: Element[];
36
+ }
37
+ /** Everything needed to install (more) derived matches for one host later — recorded by 2a at
38
+ * install, read by 2b (`compileUnion`), 3b (`bindGroups`), 6 (`adoptLateMatches`). */
39
+ export interface DerivedInstallContext {
40
+ host: Element;
41
+ /** The host's own fingerprint; a derived match's is `${fingerprint}\u0000${scope} ${selector}`. */
42
+ fingerprint: string;
43
+ /** The host's parsed value (after `scopeHoists`): element-wide `rm`, stagger keys. */
44
+ parsed: ParsedValue;
45
+ /** The host's un-resolved config (see `InstallRequest.baseConfig`). */
46
+ baseConfig: ElementConfig;
47
+ /** `baseConfig.timeline` — what `compileUnion` recompiles against. */
48
+ timeline: Timeline;
49
+ }
50
+ /** One `target:` group as installed on one host. */
51
+ export interface LiveTargetGroup {
52
+ /** As the host compiled it (non-empty `selector`, its `scope`, `hoists`, `specs`, `plan`). */
53
+ target: CompiledTarget;
54
+ /** `resolveGroupConfig(baseConfig, target.hoists)` with `activation` resolved for this group. */
55
+ config: ElementConfig;
56
+ /** The host when this group is grouped (Phase 3b), else undefined. */
57
+ gateOwner?: Element;
58
+ /** Derived matches currently installed from this group, in document order. Mutated by 2a on
59
+ * release and by 6 on adoption. */
60
+ members: Element[];
61
+ }
62
+ /** The animator's derived-host bookkeeping. One instance per Animator; all WeakMaps so a removed
63
+ * element takes its entries with it. Written ONLY through the 2a/2b/3b/6 module functions. */
64
+ export interface DerivedBook {
65
+ /** host → its derived matches (insertion order = document order at install). */
66
+ readonly derived: WeakMap<Element, Set<Element>>;
67
+ /** derived match → its host. Presence means "claimed" (collision rule D-D). */
68
+ readonly hosts: WeakMap<Element, Element>;
69
+ /** host → its live target groups. */
70
+ readonly groups: WeakMap<Element, LiveTargetGroup[]>;
71
+ /** host → what `installWithTargets` installed it with. */
72
+ readonly contexts: WeakMap<Element, DerivedInstallContext>;
73
+ /** host → union-compile cache keyed by sorted `${scope} ${selector}` list joined with `\u0001`. */
74
+ readonly unions: WeakMap<Element, Map<string, CompiledTarget>>;
75
+ /** host → cleanups to run when the host is released (group bindings, target-group-host claim). */
76
+ readonly cleanups: WeakMap<Element, Array<() => void>>;
77
+ }
78
+ /**
79
+ * The narrow window a derived-host module gets onto one Animator. Built once in the Animator
80
+ * constructor; every member delegates to the existing private method of the same name. Modules take
81
+ * this, never `Animator`, so each is unit-testable with a hand-built fake.
82
+ */
83
+ export interface AnimatorPort {
84
+ readonly registry: Registry;
85
+ readonly reporter: Reporter;
86
+ readonly binder: ActivationBinder;
87
+ readonly capabilities: Capabilities;
88
+ readonly respectReducedMotion: boolean;
89
+ readonly book: DerivedBook;
90
+ stateOf(el: Element): InstanceState | undefined;
91
+ /** `Animator.install` — installs `request.el` from a document. Re-enters `installWithTargets` only
92
+ * when the document has a non-empty selector; a derived install's document never does. */
93
+ install(request: InstallRequest): void;
94
+ /** `Animator.installAggregate` — a zero-instance host state (no own group). */
95
+ installAggregate(request: InstallRequest): void;
96
+ /** `Animator.resolveGroupMatches` — validate + query + warn "matched nothing"/too broad. */
97
+ resolveGroupMatches(host: Element, target: CompiledTarget): Element[];
98
+ /** `Animator.resolveActivation`. */
99
+ resolveActivation(el: Element, config: ElementConfig, plan: CompiledPlan): Activation;
100
+ release(el: Element): void;
101
+ /** Start ONE element (no fan-out). */
102
+ activateOne(el: Element): void;
103
+ /** The per-element exit half (`Animator.deactivate`). */
104
+ deactivateOne(el: Element): void;
105
+ /** `state.status = next` + `data-kui-state` through the state's own ledger. No aggregate sync. */
106
+ writeStatus(el: Element, state: InstanceState, next: InstanceState['status']): void;
107
+ emit(el: Element, state: InstanceState, type: LifecycleEventType, reason: LifecycleReason): void;
108
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Resolve one authored easing token to the value a stylesheet can hold.
3
+ *
4
+ * @param easing - A native keyword, a kUInetic keyword, a CSS easing function, or `spring(...)`.
5
+ * @returns A valid `animation-timing-function` / `transition-timing-function` value. Never the
6
+ * author's own text for a `spring(...)`: that path emits digits generated from clamped numbers,
7
+ * so nothing authored survives into the declaration.
8
+ * @complexity O(1) amortised — a `spring(...)` curve is built once per distinct damping ratio and
9
+ * cached; every other form is a set lookup. O(1) space beyond the cache.
10
+ * @overallScore 100
11
+ */
12
+ export declare function cssEasingValue(easing: string): string;
13
+ /**
14
+ * Resolve one authored easing token to a value `Element.animate` will actually accept.
15
+ *
16
+ * The Web Animations sibling of {@link cssEasingValue}, and it exists because the two APIs screen
17
+ * easings at different moments. A stylesheet resolves `var(--kui-ease-back-out, ease-out)` through
18
+ * the cascade at computed-value time; `KeyframeEffect`'s `easing` option is parsed as a bare
19
+ * `<easing-function>` the instant it is handed over, with no cascade to consult — so `var(...)` is
20
+ * as invalid there as `back-out` itself. Neither one degrades: Chrome throws
21
+ * `TypeError: 'back-out' is not a valid value for easing` out of `animate()`, which took the whole
22
+ * FLIP with it and left the layout change to happen instantly and silently.
23
+ *
24
+ * So the custom property is read here instead of deferred to the browser. Reading it — rather than
25
+ * mirroring `base.css`'s ten definitions into a table here — is what keeps the open half of the
26
+ * vocabulary working: `params.ts`'s `EASING_KEYWORD` accepts any `[a-z]+-(in|out|in-out)`, so an
27
+ * author may define `--kui-ease-swift-out` and write `ease:swift-out`, and a table could only ever
28
+ * know the names this repo happens to ship. It also cannot drift from `base.css`, because it *is*
29
+ * `base.css`. The cost is that it only answers correctly once the library's stylesheet has been
30
+ * applied, which is why the three callers resolve at prepare time rather than at module load.
31
+ *
32
+ * @param easing - A native keyword, a kUInetic keyword, a CSS easing function, or `spring(...)`.
33
+ * @param el - Element the token is resolved against, so a `--kui-ease-*` scoped to a subtree wins
34
+ * exactly as it would in the cascade.
35
+ * @param warn - Called once when a named token resolves to nothing.
36
+ * @returns A literal easing value, or `undefined` when the author named none — which leaves each
37
+ * caller's own default standing rather than substituting a house one for it.
38
+ * @complexity O(1) amortised; a bare keyword costs one `getComputedStyle` read.
39
+ * @overallScore 100
40
+ */
41
+ export declare function waapiEasingValue(easing: string, el: Element, warn: (message: string) => void): string | undefined;
42
+ /**
43
+ * Everything wrong with a `spring(...)` token, named one problem at a time.
44
+ *
45
+ * Separate from {@link cssEasingValue} because the two answer different questions and have
46
+ * different callers: `parse.ts` has the author's text and a warnings sink at the moment the
47
+ * attribute is read, which is where every other grammar diagnostic in this library is raised.
48
+ * Nothing here is fatal — a refused value is clamped or dropped and a curve is always produced —
49
+ * so this is a warning list, never a rejection.
50
+ *
51
+ * @param token - Any easing token. A token that is not a `spring(...)` has no problems by
52
+ * definition, so callers need no guard of their own.
53
+ * @returns One message per malformed, unknown, duplicated, or out-of-range argument.
54
+ * @complexity O(a) time and space in the argument count.
55
+ * @overallScore 100
56
+ */
57
+ export declare function springTokenProblems(token: string): string[];
@@ -1,4 +1,5 @@
1
- import type { Activation, ParsedValue, Timeline } from './types.js';
1
+ import type { ToggleActions } from './toggle-actions.js';
2
+ import type { Activation, ParsedValue, SegmentHoists, Timeline } from './types.js';
2
3
  /** The subset of an element's attributes this module needs. Keeps resolution DOM-free. */
3
4
  export interface ElementAttributes {
4
5
  source: string;
@@ -10,6 +11,16 @@ export interface ElementConfig {
10
11
  activation: Activation;
11
12
  /** Whether the author named an activation, so a primitive default may fill in when not. */
12
13
  activationAuthored: boolean;
14
+ /** Optional selector for the event source named by `data-kui-on`'s `from:` refinement. */
15
+ activationSource?: string;
16
+ /**
17
+ * What to do at each of the observer's four crossings, when the author wrote `actions:`.
18
+ *
19
+ * Absent — not a defaulted four-way table — because absent and "the default four-way table" are
20
+ * genuinely different bindings: without this the observer keeps its two-way delivery and its
21
+ * one-shot release, which is what every piece of existing markup depends on.
22
+ */
23
+ actions?: ToggleActions;
13
24
  timeline: Timeline;
14
25
  /** Trailing tokens of `data-kui-timeline`, e.g. `entry 0% cover 60%`. */
15
26
  range: string;
@@ -42,11 +53,41 @@ export declare function readAttributes(el: Element): ElementAttributes;
42
53
  */
43
54
  export declare function resolveConfig(attributes: ElementAttributes, parsed: ParsedValue): ElementConfig;
44
55
  /**
45
- * Convert an IntersectionObserver threshold from `"30%"` or `"0.3"` into a clamped ratio.
56
+ * Keep a source selector only when its longhand activation won the precedence decision.
46
57
  *
47
- * @param raw - Authored threshold value.
48
- * @returns A ratio in [0, 1]; unparseable input yields 0 rather than throwing.
49
- * @complexity O(1) time, O(1) space.
58
+ * Applying `from:` after an inline `on:` wins would pair two independently authored activations.
59
+ *
60
+ * @param input - Parsed inline and longhand activation settings.
61
+ * @returns The optional source field for the resolved element configuration.
62
+ * @complexity O(1) time and space.
63
+ */
64
+ /**
65
+ * Read only the head keyword off a raw `timeline:` value, falling back when it is absent or not a
66
+ * recognised timeline — the same extraction `resolveConfig` does inline for the element-wide
67
+ * attribute, duplicated here (against the same {@link TIMELINES} set) rather than refactored into
68
+ * it, so a per-group caller (`compile.ts`'s `scopeHoists`/`compileTargets`) can reuse the logic
69
+ * without touching `resolveConfig`'s own body and risking its passing tests.
70
+ *
71
+ * @param raw - A group's scoped `timeline:` hoist, or `undefined` when it scoped none.
72
+ * @param fallback - The element-wide timeline to use when `raw` is absent or unrecognised.
73
+ * @complexity O(k) time in the value's length; O(1) space.
74
+ * @overallScore 100
75
+ */
76
+ export declare function resolveTimelineHead(raw: string | undefined, fallback: Timeline): Timeline;
77
+ /**
78
+ * Build a derived host's own `ElementConfig` from the element-wide base plus its `target:` group's
79
+ * scoped hoists — not yet wired into `animator.ts` (that is Phase 2's job, once each group installs
80
+ * as its own host); landed now so `CompiledTarget.hoists` has a documented consumer shape.
81
+ *
82
+ * Each field the group scoped a value for overrides the base; anything the group left unscoped
83
+ * inherits the element-wide answer unchanged, matching D-B's "hoists written in an untargeted
84
+ * segment stay element-wide and are inherited by every target group unless the group overrides
85
+ * them".
86
+ *
87
+ * @param base - The host element's own resolved config, from `resolveConfig`.
88
+ * @param hoists - The group's merged scoped hoists (`CompiledTarget.hoists`), or absent when the
89
+ * group scoped none — the identity path, returning `base` unchanged.
90
+ * @complexity O(1) time and space.
50
91
  * @overallScore 100
51
92
  */
52
- export declare function toThresholdRatio(raw: string): number;
93
+ export declare function resolveGroupConfig(base: ElementConfig, hoists: SegmentHoists | undefined): ElementConfig;
@@ -0,0 +1,23 @@
1
+ import type { Cleanup } from './types.js';
2
+ /** A resize subscription whose observed elements can change as an effect changes targets. */
3
+ export interface SizeWatch {
4
+ observe(element: Element): void;
5
+ unobserve(element: Element): void;
6
+ disconnect: Cleanup;
7
+ }
8
+ /**
9
+ * Watch element boxes, including the window-resize fallback for browsers without ResizeObserver.
10
+ *
11
+ * @complexity O(1) per observed element and notification; O(n) space in observed elements.
12
+ * @overallScore 100
13
+ */
14
+ export declare function watchElementSize(win: Window, onChange: () => void): SizeWatch;
15
+ /**
16
+ * Coalesce notifications into one callback in the next animation frame; cancel on teardown.
17
+ * @complexity O(1) time and space per request.
18
+ * @overallScore 100
19
+ */
20
+ export declare function frameScheduler(win: Window, callback: () => void): {
21
+ request(): void;
22
+ cancel: Cleanup;
23
+ };
@@ -0,0 +1,39 @@
1
+ import type { Reporter } from './reporter.js';
2
+ import type { Cleanup } from './types.js';
3
+ /** Everything needed to retain callbacks for a group of source elements and event types. */
4
+ export interface EventSourceBindingRequest {
5
+ sources: readonly Element[];
6
+ types: readonly string[];
7
+ run(): void;
8
+ }
9
+ /** Owns shared foreign-event listeners and releases all of them on destruction. */
10
+ export interface EventSourceBindings {
11
+ bind(request: EventSourceBindingRequest): Cleanup;
12
+ destroy(): void;
13
+ }
14
+ /**
15
+ * Create a registry that shares one native listener per source/event pair.
16
+ *
17
+ * @returns A registry for binding callbacks and releasing every foreign listener it owns.
18
+ * @complexity O(1) to build; retained listener costs are documented on the nested functions.
19
+ */
20
+ export declare function createEventSourceBindings(): EventSourceBindings;
21
+ /** Everything needed to resolve an optional foreign event source against the animated element's document. */
22
+ export interface EventSourceResolutionRequest {
23
+ el: Element;
24
+ from?: string;
25
+ reporter?: Reporter;
26
+ }
27
+ /**
28
+ * Resolve an event source selector once while an animation is installed.
29
+ *
30
+ * `from:` deliberately resolves only at install time. The existing `observe: true` watcher tracks
31
+ * animated elements, not arbitrary potential source nodes, so pretending that a missing source
32
+ * would bind later would create a silent and unbounded document-wide observer. A named warning is
33
+ * the established selector convention and gives the author an immediate correction path.
34
+ *
35
+ * @param request - Animated element, optional selector, and diagnostic sink.
36
+ * @returns The event source elements, or an empty list when the selector is unusable or unmatched.
37
+ * @complexity O(n) in document size for a selector query; O(s) space for s matching sources.
38
+ */
39
+ export declare function resolveEventSources({ el, from, reporter }: EventSourceResolutionRequest): Element[];
@@ -21,6 +21,17 @@ export interface FlipSnapshot {
21
21
  }
22
22
  export interface FlipOptions {
23
23
  durationMs?: number;
24
+ /**
25
+ * Hold the inverted (pre-move) position this long before playing the move.
26
+ *
27
+ * `fill: 'backwards'` comes with it and is what makes it a delay rather than a glitch: by the
28
+ * time a FLIP runs the browser has *already* laid the elements out at their destination, so an
29
+ * unfilled delay would show them there for the wait and then snap back to animate. Filling
30
+ * backwards holds the first keyframe — the invert — for exactly the delay, which is what
31
+ * `animation-fill-mode: both` does for a delayed CSS effect. The end is unaffected either way:
32
+ * `backwards` does not fill forwards, so the stylesheet still owns the resting position.
33
+ */
34
+ delayMs?: number;
24
35
  easing?: string;
25
36
  /** Animate width/height differences as a scale. Off for elements with visible borders. */
26
37
  scale?: boolean;
@@ -56,6 +67,28 @@ export declare function domMeasure(el: Element): Box;
56
67
  * @overallScore 100
57
68
  */
58
69
  export declare function createFlipEngine(deps?: Partial<FlipDeps>): FlipEngine;
70
+ /**
71
+ * Hold every FLIP run that is still playing, so teardown can stop all of them.
72
+ *
73
+ * A `FlipRun` outlives the call that started it: `engine.play` hands back live Web Animations and
74
+ * returns immediately. Dropping that handle means teardown has nothing to cancel, and the moves
75
+ * keep playing on elements the animator has already released — with `duration:10s` that is ten
76
+ * seconds of motion after `destroy()`.
77
+ *
78
+ * A single "latest run" slot is not enough. FLIP durations are author-controlled and mutations
79
+ * arrive whenever the page says so, so a second reorder can easily land while the first is still
80
+ * mid-flight; keeping only the newest would leave the older one running past teardown, which is
81
+ * the same bug one step removed. Each run drops itself on completion, so the set holds only what
82
+ * is genuinely in flight rather than growing with the page's history.
83
+ *
84
+ * @returns `track` to register a run, and `cancelAll` for teardown.
85
+ * @complexity O(1) per run tracked; O(k) space in runs currently playing.
86
+ * @overallScore 100
87
+ */
88
+ export declare function trackFlipRuns(): {
89
+ track(run: FlipRun): void;
90
+ cancelAll(): void;
91
+ };
59
92
  /**
60
93
  * Watch a container and FLIP its children whenever its child list changes.
61
94
  *
@@ -66,7 +99,7 @@ export declare function createFlipEngine(deps?: Partial<FlipDeps>): FlipEngine;
66
99
  * @param engine - FLIP engine to use.
67
100
  * @param options - Timing and scaling.
68
101
  * @param observe - MutationObserver factory, injected for tests.
69
- * @returns Teardown that disconnects the observer.
102
+ * @returns Teardown that disconnects the observer and cancels any move still playing.
70
103
  * @complexity O(n) per mutation batch in the number of children.
71
104
  * @overallScore 100
72
105
  */
@@ -39,6 +39,18 @@ export interface GestureOptions {
39
39
  swipeVelocity?: number;
40
40
  /** Hold duration in ms before `onLongPress`. Zero disables it. */
41
41
  longPressMs?: number;
42
+ /**
43
+ * Whether to take pointer capture on `pointerdown`. Default `true`, which is right for every
44
+ * gesture that *moves* the element (see `onDown`), and wrong for every gesture that does not.
45
+ *
46
+ * Capture redirects the whole pointer sequence to this element, and the browser then targets the
47
+ * resulting `click` at the capturing element rather than the node actually under the cursor. On a
48
+ * container with interactive children that silently kills all of them: a `swipe-x` on a carousel
49
+ * shell swallowed every click on its own dots and buttons, because the click was delivered to the
50
+ * shell. `swipeable` recognises and publishes an attribute — it never moves anything — so it has
51
+ * nothing to stay under the cursor for and opts out.
52
+ */
53
+ capturePointer?: boolean;
42
54
  }
43
55
  export interface GestureDeps {
44
56
  now(): number;