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,53 @@
1
+ import type { EffectSpec } from './types.js';
2
+ import type { Registry } from './registry.js';
3
+ /**
4
+ * Owned by phase 9b — catching the classic `target:` typo: `pop target:.a, .b` reads as three
5
+ * effect segments (`pop`, `.a`, `.b`), not one effect with a two-part selector, because a comma
6
+ * separates *segments* everywhere else in the grammar and `target:` is the one place a selector
7
+ * can legitimately contain one. An author who forgets the quotes (`target:'.a, .b'`) gets a stray
8
+ * segment named `.a` that is not a registered effect and looks exactly like a selector — this
9
+ * module finds that shape and 9b's diagnostics surface it via `data-kui-unmatched`.
10
+ */
11
+ /** One stray segment that looks like a continuation of the previous segment's `target:` selector. */
12
+ export interface UnquotedSelector {
13
+ /** The previous segment's `target:` value, as authored. */
14
+ previous: string;
15
+ /** The stray segment's name — the text between commas that isn't a registered effect. */
16
+ segment: string;
17
+ }
18
+ /**
19
+ * Find segments whose first token is not a registered effect name, that look like a selector
20
+ * fragment (start with `.`, `#`, `[`, `*`, `:`, or contain `>`, `~`, `+`), and whose *previous*
21
+ * segment carries a `target:` token — the shape an unquoted, comma-containing selector leaves
22
+ * behind once `parse.ts` has already split it on the comma.
23
+ *
24
+ * Pure: it only reads `specs` and `registry`, and never changes how anything is parsed or
25
+ * compiled — the fix is a warning, not a silent re-join, because re-joining would have to guess
26
+ * where the selector was supposed to end.
27
+ *
28
+ * Known limitation: only catches a stray segment whose *first token* looks like a selector.
29
+ * `pop target:.a, li > a` splits into a stray segment `li > a` whose first token is `li` — a
30
+ * plausible effect name — so it is not flagged, even though `>` later in the segment is still a
31
+ * combinator. Detecting that shape would mean scanning every segment for a `target:`-less
32
+ * combinator, not just the one right after a `target:`-bearing segment, which is out of scope
33
+ * here: this pass only looks at the segment immediately following one that carries `target:`.
34
+ *
35
+ * @param specs - The document's parsed effect segments, in authored order. Pre-lift: `target:`
36
+ * still lives in `spec.params.target` rather than having been pulled onto a separate field.
37
+ * @param registry - Where a segment's first token is looked up to decide if it names a real
38
+ * effect.
39
+ * @returns Every suspect segment found, in authored order.
40
+ * @complexity O(n) time in `specs.length`, each iteration doing an O(1) registry lookup; O(f)
41
+ * space in the number of findings.
42
+ * @overallScore 100
43
+ */
44
+ export declare function findUnquotedSelectors(specs: EffectSpec[], registry: Registry): UnquotedSelector[];
45
+ /**
46
+ * Render one {@link UnquotedSelector} finding as a warning string, naming both halves of the fix:
47
+ * quote the previous segment's selector so the whole comma list is one `target:` value.
48
+ *
49
+ * @param found - One finding from {@link findUnquotedSelectors}.
50
+ * @complexity O(1) time and space.
51
+ * @overallScore 100
52
+ */
53
+ export declare function unquotedSelectorWarning(found: UnquotedSelector): string;
@@ -0,0 +1,80 @@
1
+ import type { PrepareContext } from '../../core/effect-context.js';
2
+ import type { Cleanup } from '../../core/types.js';
3
+ export interface RingDragRequest {
4
+ el: Element;
5
+ ctx: PrepareContext;
6
+ /** `grab:false` still installs the keyboard half — that is accessibility, not decoration. */
7
+ enabled: boolean;
8
+ /** Pointer pixels per place on the ring. */
9
+ travelPx: number;
10
+ /** How many places the ring has *now*; asked per gesture, never captured. */
11
+ total(): number;
12
+ /** The ring's current continuous position, in places. */
13
+ positionOf(): number;
14
+ /** Move the ring to a continuous position and re-render. */
15
+ moveTo(position: number): void;
16
+ /** Publish or clear the dragging state the stylesheet suspends its transition on. */
17
+ setDragging(dragging: boolean): void;
18
+ }
19
+ /**
20
+ * Where a release coasts to, before snapping.
21
+ *
22
+ * Velocity is in pixels per second and the ring is measured in places, so the projection is
23
+ * `velocity / travel * seconds` — one conversion, in one place, in the unit the index uses.
24
+ *
25
+ * Capped, and the cap is not politeness. Uncapped, a hard flick on a phone (velocities of several
26
+ * thousand pixels per second are ordinary) projects a dozen places, and a ring that spins a dozen
27
+ * cards from one flick has stopped being a control and become a slot machine: the visitor cannot
28
+ * predict where it lands, so they cannot aim, so they flick again. Four places is far enough that a
29
+ * deliberate throw clearly differs from a nudge and close enough that the destination stays
30
+ * legible.
31
+ *
32
+ * Pure and exported so both halves — the conversion and the cap — are assertable without a pointer.
33
+ *
34
+ * @param position - Where the ring is at release, in places.
35
+ * @param velocityPxPerSec - Signed pointer velocity along the drag axis.
36
+ * @param travelPx - Pixels per place.
37
+ * @returns The un-snapped position the ring is heading for.
38
+ * @complexity O(1) time and space.
39
+ */
40
+ export declare function projectRelease(position: number, velocityPxPerSec: number, travelPx: number): number;
41
+ /**
42
+ * Which place a released ring settles on.
43
+ *
44
+ * Separate from {@link projectRelease} because they answer different questions and only one of them
45
+ * has an opinion: projection is physics, snapping is the contract that a ring always comes to rest
46
+ * facing a card. Splitting them is also what makes "a flick of exactly half a place still commits"
47
+ * testable without synthesising a gesture.
48
+ *
49
+ * `+ 0` is not decoration. `Math.round(-0.4)` is `-0`, and a ring settled at "minus place zero" is
50
+ * not a place — it is the same place spelled in a way that half of JavaScript disagrees with
51
+ * itself about. `-0 === 0` is true, so most arithmetic hides it; `Object.is(-0, 0)` is false, which
52
+ * is what `toBe` compares with, and `[-0].toString()` and `JSON.stringify(-0)` disagree with each
53
+ * other too. Adding zero normalises the sign at the one place a negative zero can be produced,
54
+ * rather than leaving every caller and every serialisation to find out for itself.
55
+ *
56
+ * @param projected - The coasting destination, in places.
57
+ * @returns The nearest whole place, never negative zero.
58
+ * @complexity O(1) time and space.
59
+ */
60
+ export declare function snapTo(projected: number): number;
61
+ /**
62
+ * Bring a settled position onto `[0, total)`.
63
+ *
64
+ * A ring has no ends, so nothing about the geometry needs this — `--kui-offset` is computed modulo
65
+ * the count and `render` rebases the published position on the live step every time. What needs it
66
+ * is arithmetic hygiene over a long session: `position` accumulates every drag ever made, and a
67
+ * number in the millions loses the fractional precision the sub-step rotation is carried in. Doing
68
+ * it at rest rather than mid-drag keeps the drag itself monotonic, so a gesture never jumps because
69
+ * it happened to cross the seam.
70
+ *
71
+ * @complexity O(1) time and space.
72
+ */
73
+ export declare function wrapPlace(place: number, total: number): number;
74
+ /**
75
+ * Install the grab and the keyboard on a ring.
76
+ *
77
+ * @returns Teardown for every listener and attribute this installs.
78
+ * @complexity O(1) per pointer event and per key; O(1) space.
79
+ */
80
+ export declare function createRingDrag(request: RingDragRequest): Cleanup;
@@ -0,0 +1,149 @@
1
+ import type { Preset, Primitive } from '../../core/types.js';
2
+ import type { Registry } from '../../core/registry.js';
3
+ /**
4
+ * Whether a slot at this ring angle has its own plane turned away from the camera.
5
+ *
6
+ * Pure and exported so the rule is assertable without a DOM or a layout. The angle is the slot's
7
+ * signed place on the ring in degrees, already including the live-step drift.
8
+ *
9
+ * `>=` rather than `>` at exactly a quarter turn: a slot edge-on to the camera has zero projected
10
+ * width, so it can only ever swallow a click that was aimed at something else. Calling it "back" is
11
+ * the answer that costs nothing and removes the boundary case from the hit-testing question.
12
+ *
13
+ * @param angleDeg - Signed degrees from the camera-facing position.
14
+ * @returns `'back'` when the slot's face points away, `'front'` otherwise.
15
+ * @complexity O(1) time and space.
16
+ */
17
+ export declare function faceAt(angleDeg: number): 'front' | 'back';
18
+ /**
19
+ * Bring an angle onto `(-180, 180]`, the range where "how far from facing me" is a magnitude.
20
+ *
21
+ * Without it a slot at `+350deg` — which is 10 degrees from front — reads as further from the
22
+ * camera than one at `+100deg`, and the whole back half of a large ring is mislabelled.
23
+ *
24
+ * @complexity O(1) time and space.
25
+ */
26
+ export declare function normaliseDegrees(angleDeg: number): number;
27
+ /**
28
+ * Where the ring's continuous position rounds to, and how far past it the ring currently sits.
29
+ *
30
+ * The pair the stylesheet needs and the reason both tokens are published rather than one: the
31
+ * integer decides which slot is *live* (and therefore what `--kui-offset` means for every other
32
+ * slot), and the remainder is the sub-step rotation on top of it. Re-snapping the integer whenever
33
+ * the remainder passes a half step is what keeps the remainder inside ±0.5, so the ring never has
34
+ * to travel back across the whole strip to wrap from the last slide to the first — the same
35
+ * property `circularOffset` gives the discrete case.
36
+ *
37
+ * @param position - Continuous ring position, in places. May be negative or beyond the count.
38
+ * @param total - How many places the ring has.
39
+ * @returns The live integer step, wrapped into range, and the signed remainder in `[-0.5, 0.5)`.
40
+ * @complexity O(1) time and space.
41
+ */
42
+ export declare function snapPosition(position: number, total: number): {
43
+ step: number;
44
+ drift: number;
45
+ };
46
+ /**
47
+ * An authored `<angle>` as a number of degrees.
48
+ *
49
+ * `params.ts` accepts every CSS angle unit and normalises only the bare/`d` spellings to `deg`, so
50
+ * a value reaching here can legitimately be `0.05turn` or `1.2rad`. The stylesheet does not care —
51
+ * it hands the token straight to `rotateY()` — but this file computes with it (to decide which
52
+ * slots face away), and a `Number('0.05turn')` is `NaN`.
53
+ *
54
+ * Falls back rather than throwing on an unrecognised unit for the reason every reader in this
55
+ * library does: the value has already been validated, so an unfamiliar spelling here means this
56
+ * function is behind `params.ts`, and a ring that spreads over the default arc is a better answer
57
+ * than one that throws during `prepare`.
58
+ *
59
+ * @param value - A validated CSS angle.
60
+ * @param fallbackDeg - Used when the unit is not one this function converts.
61
+ * @returns Degrees.
62
+ * @complexity O(n) time in value length; O(1) space.
63
+ */
64
+ export declare function degreesOf(value: string, fallbackDeg: number): number;
65
+ /**
66
+ * The ring primitive.
67
+ *
68
+ * `renderer: 'javascript'` and two channels together are the honest declaration: this file paints
69
+ * nothing itself — it publishes numbers — but `carousel.css` does, and both of the things it writes
70
+ * have to be declared or the conflict detector waves through a composition that silently loses one
71
+ * effect's output.
72
+ *
73
+ * `skew` is this catalog's name for "claims the whole `transform` shorthand" (see `CHANNEL.skew` in
74
+ * `core/types.ts`), which `carousel.css` writes on the elements this effect drives. The shorthand is
75
+ * unavoidable here: three-dimensional placement needs `rotateX`/`rotateY`/`translateZ` composed in a
76
+ * fixed order, and `rotate:`/`translate:` as individual properties are applied in the order the spec
77
+ * fixes, which is the reverse of the one this geometry needs.
78
+ *
79
+ * `discrete` is `display`, and it is here for exactly the reason `card-toggle` declares it
80
+ * (`effects/three-d/index.ts`): the unconditional host rule pins `display: grid` so every slot
81
+ * starts from the same cell instead of flowing down the page as block siblings. That has nothing to
82
+ * do with `catalog/discrete.ts`'s show/hide use of the same property, but `display` is tracked as
83
+ * one channel whatever value is written into it — the point of the channel model is the physical
84
+ * property, not the intent — so a ring composed with an `@starting-style` open/close effect is now
85
+ * correctly reported as a collision rather than quietly letting one of the two win.
86
+ *
87
+ * `reducedMotion: 'shorten'`, not `'disable'`, for exactly the reason `step-progress` carries the
88
+ * same note: under `disable` the animator never activates the instance, so no index is published,
89
+ * no slot is marked, and the arrows do nothing. A visitor who asked for less motion would get a
90
+ * dead widget rather than a calm one. Reduced motion suppresses the *travel* between places — which
91
+ * `base.css`'s policy layer already does to the transition `carousel.css` declares — never the
92
+ * function.
93
+ */
94
+ export declare const SPATIAL_RING_PRIMITIVE: Primitive;
95
+ export declare const CAROUSEL_PRIMITIVES: Primitive[];
96
+ /**
97
+ * Convex and concave are two names, not one parameter with two values.
98
+ *
99
+ * They are one sign in the maths — `translateZ(+r)` puts the camera outside the ring,
100
+ * `translateZ(-r)` puts it at the centre — and everything else about them differs. Outside, the far
101
+ * half of the ring is content: smaller, dimmer, and part of the composition, and a full 360-degree
102
+ * spread is right. Inside, the far half is *behind your head*, so a full spread hides most of the
103
+ * deck and the sensible default is a slice; the cards nearest the edges of that slice are the ones
104
+ * that need culling; and "next" moves the world past a fixed viewer rather than turning an object
105
+ * in front of one.
106
+ *
107
+ * A `curve:` keyword would have made all of that one name's problem to explain, with half its
108
+ * documentation prefixed by "unless". Two names each get their own defaults, their own rules in
109
+ * `carousel.css`, and their own paragraph.
110
+ *
111
+ * `requiresOwnSubtree` on all of them: every rule in `carousel.css` past the host rule reaches the
112
+ * slots, so a `target:` that relocated `data-kui-fx` onto one slot would leave those selectors
113
+ * looking for grandchildren nobody authored. (The primitive declares a `target` parameter of its
114
+ * own, so `compile.ts` never consults the flag — but `test/css-requires-own-subtree.test.ts`
115
+ * re-derives the reaching set from the stylesheet and does, and the fact it records is true.)
116
+ *
117
+ * `phase: 'idle'` on all of them too, and for the same reason `target` does not change the answer:
118
+ * `channelsFor`/`findConflicts` (`core/channels.ts`) reason about the channels *this preset
119
+ * declares* on the host it is authored on (`CHANNEL.skew` and `'discrete'`, from
120
+ * `SPATIAL_RING_PRIMITIVE`), not about which element in the subtree physically paints them — the
121
+ * compiler has no notion of "the primitive's own target moved the real work three nodes down," and
122
+ * does not need one here, because `requiresOwnSubtree` already keeps this preset off of anything
123
+ * `target:` could relocate.
124
+ *
125
+ * The phase question itself is the same one `scroll-mechanics/presets.ts` answers at length:
126
+ * `prepareSpatialRing` calls `render()` unconditionally during `prepare` — before any drag, before
127
+ * any control click — which stamps `data-kui-step`/`--kui-step-position`/the per-slot face
128
+ * attributes immediately, and the primitive's `defaultActivation` is `'load'`. So, like the scroll
129
+ * primitives and unlike `gestures/index.ts`'s `draggable` (silent until `pointerdown`), a ring never
130
+ * has a quiescent stretch for an entrance to release into — it claims `skew`/`discrete` from the
131
+ * first frame and holds them, drag or no drag, until `destroy()`. That is `EffectPhase`'s `idle`:
132
+ * "runs unbounded, so it never yields the channel at all." It buys nothing new by itself —
133
+ * `INDEPENDENT_PHASES` exempts only `entrance|state` and `exit|state`, so `idle` still collides with
134
+ * everything including another `idle`, which is correct: `carousel-3d, flip-in-x` really would fight
135
+ * over the `transform` shorthand (`CHANNEL.skew`) for the ring's whole lifetime, and there is no
136
+ * turn-taking to model. It replaces "nothing is known" with the actual, checked fact.
137
+ *
138
+ * None of the four declares `transitions`: nothing here renders through a CSS `transition:` on the
139
+ * host box for `phaseOf` to derive `state` from — the ring is `renderer: 'javascript'` throughout.
140
+ */
141
+ export declare const CAROUSEL_PRESETS: Preset[];
142
+ /**
143
+ * Register the spatial carousel.
144
+ *
145
+ * @param registry - Registry to populate.
146
+ * @returns The same registry, for chaining.
147
+ * @complexity O(n) time in the number of primitives and presets.
148
+ */
149
+ export declare function registerCarousel(registry: Registry): Registry;
@@ -0,0 +1,152 @@
1
+ import type { PrepareContext } from '../../core/effect-context.js';
2
+ import type { Cleanup } from '../../core/types.js';
3
+ /**
4
+ * Whether an authored `src` names a video platform's web page instead of a media file.
5
+ *
6
+ * @complexity O(n) time in value length; O(1) space.
7
+ * @overallScore 100
8
+ */
9
+ export declare function isVideoPageUrl(value: string): boolean;
10
+ /**
11
+ * Named focal points, as `object-position` percentage pairs.
12
+ *
13
+ * A `cover` fit crops, and which part it crops away is the whole editorial decision — the classic
14
+ * failure is a portrait cropped through the subject's chin. Percentages rather than the equivalent
15
+ * CSS keywords (`top`, `left top`) because the pair is written into one property from two halves,
16
+ * and `50% 0%` composes where `center top` would need its own keyword-order rules.
17
+ */
18
+ declare const FOCAL_POINTS: {
19
+ readonly center: "50% 50%";
20
+ readonly top: "50% 0%";
21
+ readonly bottom: "50% 100%";
22
+ readonly left: "0% 50%";
23
+ readonly right: "100% 50%";
24
+ readonly 'top-left': "0% 0%";
25
+ readonly 'top-right': "100% 0%";
26
+ readonly 'bottom-left': "0% 100%";
27
+ readonly 'bottom-right': "100% 100%";
28
+ };
29
+ export type FocalPoint = keyof typeof FOCAL_POINTS;
30
+ /** The nine named focal points, in the order the parameter schema declares them. */
31
+ export declare const FOCAL_POINT_NAMES: FocalPoint[];
32
+ /**
33
+ * Resolve a focal point name to an `object-position` value.
34
+ *
35
+ * @complexity O(1) time and space.
36
+ * @overallScore 100
37
+ */
38
+ export declare function focalPosition(focus: string): string;
39
+ /** How a background clip decides when to run. */
40
+ export type AutoplayMode = 'in-view' | 'always' | 'never';
41
+ export interface BackgroundMediaOptions {
42
+ /** URL or path to the image or video, already screened by `mediaSource`. */
43
+ src: string;
44
+ /** Still shown before a video's first frame; `''` for none. */
45
+ poster: string;
46
+ /** `object-fit` for the layer. */
47
+ fit: 'cover' | 'contain';
48
+ /** `object-position` for the layer, already resolved from a named focal point. */
49
+ position: string;
50
+ /** Scrim colour painted over the media and under the author's children. */
51
+ overlay: string;
52
+ /** Scrim opacity, `0`–`1`. */
53
+ overlayOpacity: number;
54
+ /** When a clip plays. Ignored for an image. */
55
+ autoplay: AutoplayMode;
56
+ /** `playbackRate` for a clip. Ignored for an image. */
57
+ rate: number;
58
+ /** Whether a clip restarts when it ends. Ignored for an image. */
59
+ loop: boolean;
60
+ /** Suppresses autoplay, leaving the poster frame standing. */
61
+ reducedMotion: boolean;
62
+ }
63
+ export interface BackgroundLayer {
64
+ /** Stop observing and delete every node this effect added, leaving the author's own as written. */
65
+ remove: Cleanup;
66
+ }
67
+ /**
68
+ * Whether a scrim colour is actually asking for a scrim.
69
+ *
70
+ * `transparent` is the default so that the parameter stays a real `type: 'color'` — validated by
71
+ * the same screen every other colour goes through — rather than an empty string that no colour
72
+ * grammar accepts. It also happens to be the honest spelling of "no scrim", so an author who
73
+ * writes it explicitly gets exactly what the default gives them.
74
+ *
75
+ * @complexity O(1) time and space.
76
+ * @overallScore 100
77
+ */
78
+ export declare function paintsOverlay(options: BackgroundMediaOptions): boolean;
79
+ /**
80
+ * Whether an authored `src` names a video rather than an image.
81
+ *
82
+ * @param src - Author-supplied path, already accepted as same-origin.
83
+ * @returns `true` when the path's final extension is a known video container.
84
+ * @complexity O(n) time in path length; O(1) space.
85
+ * @overallScore 100
86
+ */
87
+ export declare function isVideoSource(src: string): boolean;
88
+ /**
89
+ * Screen an authored media URL before it can reach `src`/`poster`.
90
+ *
91
+ * **Cross-origin URLs are allowed here, unlike `media-scrub`'s frame pattern, and that is a
92
+ * deliberate divergence rather than an oversight.** `isSameOriginPath` (`core/params.ts`) refuses
93
+ * every absolute URL on the grounds that `data-kui` is not always written by the site owner — a CMS
94
+ * field, a comment — so an unconstrained `src` turns the visitor's browser into an
95
+ * attacker-directed request tool. That reasoning still stands, and it is why the scheme allowlist
96
+ * above is kept tight.
97
+ *
98
+ * It is not the right trade for *this* parameter, though. A background is the one media case where
99
+ * the file routinely does not live on the page's own origin — an S3 bucket, a CDN, an asset host —
100
+ * and `media-scrub`'s `src:` is materially more dangerous than this one for a second reason: it is
101
+ * a `{i}` *template* that fires one request per frame, so a two-hundred-frame sequence is a
102
+ * two-hundred-request channel where this is a single fixed fetch. A site that does accept untrusted
103
+ * `data-kui` should set a `Content-Security-Policy` with `img-src`/`media-src`, which is the
104
+ * control actually designed for this and the one thing a library cannot do on the consumer's
105
+ * behalf.
106
+ *
107
+ * @param authored - Author-supplied value; `''` when none was written.
108
+ * @param name - Parameter name, for the diagnostic.
109
+ * @returns The URL, or `''` when it was rejected or absent.
110
+ * @complexity O(n) time in value length; O(1) space.
111
+ * @overallScore 100
112
+ */
113
+ export declare function mediaSource(authored: string, name: string, ctx: PrepareContext): string;
114
+ /**
115
+ * Apply the authored playback policy to a clip.
116
+ *
117
+ * `autoplay:` is the opt-out the three real cases need. `in-view` (default) pairs the clip with the
118
+ * viewport. `always` is for a short hero clip that must never be caught mid-stall by a visibility
119
+ * heuristic. `never` installs the clip and leaves it on its poster, which is also what any mode
120
+ * degrades to under a reduced-motion preference.
121
+ *
122
+ * @returns A teardown that stops any observer and leaves the clip paused.
123
+ * @complexity O(1) time and space.
124
+ * @overallScore 100
125
+ */
126
+ export declare function startPlayback(video: HTMLVideoElement, win: Window, options: BackgroundMediaOptions): Cleanup;
127
+ /**
128
+ * Play a background clip while any part of it is on screen, and pause it the rest of the time.
129
+ *
130
+ * This is the primitive's own observer rather than the animator's `on:enter` gate, because the two
131
+ * answer different questions: `on:enter` fires once and stays fired, which is right for a reveal
132
+ * and wrong for a clip that should stop costing decode budget the moment it scrolls away.
133
+ *
134
+ * `threshold: 0` — any intersection at all — rather than the `0.25` a card-sized video wants.
135
+ * `intersectionRatio` is measured against the *target*, and this target is usually a full section:
136
+ * one taller than four viewports can never reach a ratio of 0.25 no matter where it is scrolled,
137
+ * so a fractional threshold is a clip that silently never plays.
138
+ *
139
+ * @returns A teardown that disconnects the observer and leaves the clip paused.
140
+ * @complexity O(1) time and space.
141
+ * @overallScore 100
142
+ */
143
+ export declare function autoplayInView(video: HTMLVideoElement, win: Window): Cleanup;
144
+ /**
145
+ * Create the backdrop layer and hand back the handle that deletes it again.
146
+ *
147
+ * @param el - The host element, which keeps every child the author wrote.
148
+ * @complexity O(1) time and space.
149
+ * @overallScore 100
150
+ */
151
+ export declare function installBackgroundMedia(el: Element, ctx: PrepareContext, options: BackgroundMediaOptions): BackgroundLayer;
152
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { Preset, Primitive } from '../../core/types.js';
2
+ import type { Registry } from '../../core/registry.js';
3
+ export declare const DISCRETE_PRIMITIVES: Primitive[];
4
+ export declare const DISCRETE_PRESETS: Preset[];
5
+ /**
6
+ * Register the `@starting-style` discrete-open catalog (section J).
7
+ *
8
+ * @param registry - Registry to populate.
9
+ * @returns The same registry, for chaining.
10
+ * @complexity O(n) time in registered primitives and presets.
11
+ * @overallScore 100
12
+ */
13
+ export declare function registerDiscrete(registry: Registry): Registry;
@@ -0,0 +1,24 @@
1
+ import type { Preset, Primitive } from '../../core/types.js';
2
+ import type { Registry } from '../../core/registry.js';
3
+ export declare const PROXIMITY_FIELD_PRIMITIVES: Primitive[];
4
+ export declare const PROXIMITY_FIELD_PRESETS: Preset[];
5
+ export declare const PROXIMITY_GLOW_PRIMITIVES: Primitive[];
6
+ export declare const PROXIMITY_GLOW_PRESETS: Preset[];
7
+ /** Both halves of the family, for `registerInteractionProximity` below. */
8
+ export declare const INTERACTION_PROXIMITY_PRIMITIVES: Primitive[];
9
+ export declare const INTERACTION_PROXIMITY_PRESETS: Preset[];
10
+ /**
11
+ * Register the cross-element pointer-proximity family.
12
+ *
13
+ * A standalone top-level registration called directly from `catalog/index.ts`, the same shape
14
+ * `registerInteraction`'s own doc comment describes for `registerGestures`/`registerThreeD` —
15
+ * deliberately not folded into `interaction.ts`'s `INTERACTION_PRIMITIVES`/`_PRESETS`, which sits on
16
+ * that file's own 400-line lint ceiling and is being edited by another session concurrently with
17
+ * this one.
18
+ *
19
+ * @param registry - Registry to populate.
20
+ * @returns The same registry, for chaining.
21
+ * @complexity O(n) time in registered primitives and presets.
22
+ * @overallScore 100
23
+ */
24
+ export declare function registerInteractionProximity(registry: Registry): Registry;