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.
- package/README.md +93 -10
- package/dist/esm/advanced/index.mjs +4727 -0
- package/dist/esm/chunk-AEQGC2KM.mjs +189 -0
- package/dist/esm/chunk-MQSNMYRP.mjs +9332 -0
- package/dist/esm/chunk-RVTYN6NZ.mjs +3446 -0
- package/dist/esm/chunk-U43BX5O2.mjs +2984 -0
- package/dist/esm/core/index.mjs +16 -9
- package/dist/esm/effects/index.mjs +19 -4
- package/dist/esm/index.mjs +17 -10
- package/dist/kuinetic.advanced.js +5070 -0
- package/dist/kuinetic.advanced.min.js +749 -0
- package/dist/kuinetic.all.js +15218 -5595
- package/dist/kuinetic.all.min.js +2 -0
- package/dist/kuinetic.css +2900 -360
- package/dist/kuinetic.js +15217 -5593
- package/dist/kuinetic.min.css +1 -0
- package/dist/kuinetic.min.js +7 -0
- package/dist/types/3d/angles.d.ts +30 -0
- package/dist/types/3d/flattening.d.ts +49 -0
- package/dist/types/3d/index.d.ts +36 -0
- package/dist/types/3d/model-3d.d.ts +115 -0
- package/dist/types/3d/register.d.ts +26 -0
- package/dist/types/3d/webgl.d.ts +24 -0
- package/dist/types/advanced/audio.d.ts +322 -0
- package/dist/types/advanced/base.d.ts +233 -0
- package/dist/types/advanced/camera-3d.d.ts +236 -0
- package/dist/types/advanced/fluid-cursor.d.ts +149 -0
- package/dist/types/advanced/gl-utils.d.ts +52 -0
- package/dist/types/advanced/glsl.d.ts +60 -0
- package/dist/types/advanced/index.d.ts +23 -0
- package/dist/types/advanced/particles.d.ts +108 -0
- package/dist/types/advanced/scenes.d.ts +207 -0
- package/dist/types/advanced/shaders.d.ts +972 -0
- package/dist/types/browser/boot.d.ts +72 -0
- package/dist/types/core/activation.d.ts +227 -2
- package/dist/types/core/animator.d.ts +446 -11
- package/dist/types/core/attrs.d.ts +9 -0
- package/dist/types/core/breakpoints.d.ts +260 -0
- package/dist/types/core/bundles.d.ts +71 -0
- package/dist/types/core/callback.d.ts +64 -0
- package/dist/types/core/capabilities.d.ts +47 -0
- package/dist/types/core/channels.d.ts +120 -2
- package/dist/types/core/cloak-selectors.d.ts +47 -0
- package/dist/types/core/compile.d.ts +207 -2
- package/dist/types/core/control.d.ts +218 -0
- package/dist/types/core/declarations.d.ts +128 -0
- package/dist/types/core/derived/aggregate.d.ts +43 -0
- package/dist/types/core/derived/book.d.ts +30 -0
- package/dist/types/core/derived/diagnostics.d.ts +51 -0
- package/dist/types/core/derived/group-gate.d.ts +62 -0
- package/dist/types/core/derived/install.d.ts +110 -0
- package/dist/types/core/derived/late-matches.d.ts +19 -0
- package/dist/types/core/derived/types.d.ts +108 -0
- package/dist/types/core/easing.d.ts +57 -0
- package/dist/types/core/element-config.d.ts +47 -6
- package/dist/types/core/element-size.d.ts +23 -0
- package/dist/types/core/event-sources.d.ts +39 -0
- package/dist/types/core/flip.d.ts +34 -1
- package/dist/types/core/gesture.d.ts +12 -0
- package/dist/types/core/host-facts.d.ts +155 -0
- package/dist/types/core/index.d.ts +7 -3
- package/dist/types/core/owned-styles.d.ts +129 -2
- package/dist/types/core/params.d.ts +48 -0
- package/dist/types/core/parse.d.ts +28 -1
- package/dist/types/core/register-into.d.ts +29 -0
- package/dist/types/core/registry.d.ts +10 -3
- package/dist/types/core/repeat.d.ts +91 -0
- package/dist/types/core/sequence.d.ts +126 -0
- package/dist/types/core/stagger-config.d.ts +199 -0
- package/dist/types/core/stagger-keys.d.ts +63 -0
- package/dist/types/core/stagger.d.ts +187 -6
- package/dist/types/core/style-plan.d.ts +21 -16
- package/dist/types/core/target.d.ts +128 -0
- package/dist/types/core/threshold-reachability.d.ts +45 -0
- package/dist/types/core/time-scale.d.ts +9 -0
- package/dist/types/core/toggle-actions.d.ts +141 -0
- package/dist/types/core/travel.d.ts +59 -0
- package/dist/types/core/types.d.ts +705 -13
- package/dist/types/core/unquoted-selectors.d.ts +53 -0
- package/dist/types/effects/carousel/drag.d.ts +80 -0
- package/dist/types/effects/carousel/index.d.ts +149 -0
- package/dist/types/effects/catalog/background-media.d.ts +152 -0
- package/dist/types/effects/catalog/discrete.d.ts +13 -0
- package/dist/types/effects/catalog/interaction-proximity.d.ts +24 -0
- package/dist/types/effects/catalog/interaction-reveal.d.ts +248 -0
- package/dist/types/effects/catalog/interaction-shared.d.ts +42 -0
- package/dist/types/effects/catalog/interaction-states.d.ts +68 -0
- package/dist/types/effects/catalog/materials.d.ts +67 -0
- package/dist/types/effects/catalog/media-shared.d.ts +3 -2
- package/dist/types/effects/catalog/numbers-shared.d.ts +8 -5
- package/dist/types/effects/catalog/shared.d.ts +2 -2
- package/dist/types/effects/catalog/text-shared.d.ts +92 -10
- package/dist/types/effects/catalog/transforms.d.ts +13 -0
- package/dist/types/effects/catalog/view-transitions.d.ts +13 -0
- package/dist/types/effects/forms/primitives.d.ts +15 -4
- package/dist/types/effects/gestures/index.d.ts +53 -0
- package/dist/types/effects/index.d.ts +5 -0
- package/dist/types/effects/layout/presets.d.ts +35 -0
- package/dist/types/effects/motion-path/index.d.ts +35 -0
- package/dist/types/effects/scroll-mechanics/params.d.ts +23 -0
- package/dist/types/effects/scroll-mechanics/presets.d.ts +51 -0
- package/dist/types/effects/scroll-mechanics/section-index.d.ts +47 -0
- package/dist/types/effects/shared.d.ts +162 -2
- package/dist/types/effects/step-index.d.ts +121 -0
- package/dist/types/effects/step-marking.d.ts +41 -33
- package/dist/types/effects/svg/icon-parts.d.ts +23 -0
- package/dist/types/effects/three-d/flip-parts.d.ts +46 -0
- package/dist/types/effects/tween/index.d.ts +57 -0
- package/dist/types/effects/tween/properties.d.ts +107 -0
- package/dist/types/effects/tween/waypoints.d.ts +106 -0
- package/dist/types/showcase/compare.d.ts +4 -0
- package/dist/types/showcase/device-frame.d.ts +3 -0
- package/dist/types/showcase/hotspots.d.ts +3 -0
- package/dist/types/showcase/index.d.ts +30 -0
- package/dist/types/showcase/lightbox.d.ts +3 -0
- package/dist/types/showcase/media-source.d.ts +13 -0
- package/dist/types/showcase/modal-shell.d.ts +22 -0
- package/dist/types/showcase/scroll-story.d.ts +4 -0
- package/dist/types/showcase/shared.d.ts +47 -0
- package/dist/types/showcase/slideshow.d.ts +3 -0
- package/dist/types/showcase/slow-mo.d.ts +5 -0
- package/package.json +14 -7
- package/dist/esm/chunk-5DON3UFQ.mjs +0 -4380
- package/dist/esm/chunk-JT4PZL3A.mjs +0 -773
- package/dist/esm/chunk-QUVFODSQ.mjs +0 -1278
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { PrepareContext } from '../core/effect-context.js';
|
|
2
1
|
import type { Cleanup } from '../core/types.js';
|
|
3
2
|
/**
|
|
4
3
|
* Marking the children of a stepped effect, shared by every primitive that has an index.
|
|
@@ -25,42 +24,23 @@ import type { Cleanup } from '../core/types.js';
|
|
|
25
24
|
*/
|
|
26
25
|
/** The attribute this module owns. Never write it from anywhere else. */
|
|
27
26
|
export declare const STEP_STATE_ATTR = "data-kui-step-state";
|
|
28
|
-
export type StepState = 'before' | 'active' | 'after';
|
|
29
27
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* `matches` against the two roots catches every selector that reaches the whole document — `*`,
|
|
33
|
-
* `html`, `body` and compounds like `*, a` with one rule and no bespoke parser — while leaving a
|
|
34
|
-
* deliberately scoped wildcard such as `.spy-nav > *` working, which a syntactic ban on `*` would
|
|
35
|
-
* not. `matches` throws on invalid syntax exactly as `querySelectorAll` does, so the same call
|
|
36
|
-
* still answers the validity question.
|
|
28
|
+
* The ring place, as a selectable attribute beside the `--kui-offset` custom property.
|
|
37
29
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
30
|
+
* Also owned here, and written to the same elements. See `createStepMarker` for why both forms
|
|
31
|
+
* exist: the number does arithmetic a selector cannot, the attribute selects what arithmetic
|
|
32
|
+
* cannot — and hiding a slide properly (`visibility`, not `opacity`) needs a keyword.
|
|
40
33
|
*/
|
|
41
|
-
export declare
|
|
34
|
+
export declare const STEP_OFFSET_ATTR = "data-kui-step-offset";
|
|
35
|
+
export type StepState = 'before' | 'active' | 'after';
|
|
42
36
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* every frame.
|
|
50
|
-
*
|
|
51
|
-
* Rejecting rather than silently narrowing is the honest response, because there is no narrower
|
|
52
|
-
* selector that could be meant. A selector reaching `<html>` or `<body>` is not naming a set of
|
|
53
|
-
* steps or a nav link, it is naming the page, and guessing which of its thousands of descendants
|
|
54
|
-
* the author meant would be worse than saying so.
|
|
55
|
-
*
|
|
56
|
-
* @param selector - The authored `target:` value; empty is the no-op default, not an error.
|
|
57
|
-
* @param ctx - Prepare context, for `doc` and the warning channel.
|
|
58
|
-
* @param effect - Effect name, so the warning says which attribute to go and fix.
|
|
59
|
-
* @returns The selector, or `''` when it must be ignored.
|
|
60
|
-
* @complexity O(1) time and space; `matches` walks the selector, not the document.
|
|
61
|
-
* @overallScore 100
|
|
37
|
+
* `target:`/`scope:` resolution — `resolveTarget`, `queryScoped`, `TargetScope`, `SCOPE_PARAM`,
|
|
38
|
+
* `scopeParam` — moved to `core/target.ts`. `core/compile.ts` and `core/animator.ts` need the same
|
|
39
|
+
* resolution for the *universal* `target:` (any effect, not just the handful of primitives that
|
|
40
|
+
* used to be the only place this grammar existed — see `compile.ts`'s `liftTarget` for who those
|
|
41
|
+
* are today), and `core` must not depend on `effects`. Import from `../core/target.js` here as
|
|
42
|
+
* everywhere else; this module keeps only the step-index-specific half.
|
|
62
43
|
*/
|
|
63
|
-
export declare function resolveTarget(selector: string, ctx: PrepareContext, effect: string): string;
|
|
64
44
|
/**
|
|
65
45
|
* A set of step elements plus the ledgers that let their original attributes survive teardown.
|
|
66
46
|
*
|
|
@@ -83,11 +63,39 @@ export interface StepMarker {
|
|
|
83
63
|
* the index actually changing — while frames are not.
|
|
84
64
|
*
|
|
85
65
|
* @param resolve - Produces the current step elements, in document order.
|
|
66
|
+
* @param warn - Optional diagnostic sink, called at most once per marker. Callers prefix their own
|
|
67
|
+
* effect name, the way every other warning in this library names the attribute to go and fix.
|
|
86
68
|
* @returns A marker; call `restore` from the primitive's teardown.
|
|
87
69
|
* @complexity O(n) per `mark` in the number of step elements; O(n) space in elements ever touched.
|
|
88
70
|
* @overallScore 100
|
|
89
71
|
*/
|
|
90
|
-
export declare function createStepMarker(resolve: () => Iterable<Element
|
|
72
|
+
export declare function createStepMarker(resolve: () => Iterable<Element>, warn?: (message: string) => void): StepMarker;
|
|
73
|
+
/**
|
|
74
|
+
* Where one step sits relative to the live one, as a signed number of places *around a ring*.
|
|
75
|
+
*
|
|
76
|
+
* `before`/`active`/`after` is a three-way split, which is all a progress bar needs and not enough
|
|
77
|
+
* for a deck: it says slide 5 is "before" slide 1 but not that it is one place behind it, and one
|
|
78
|
+
* place is the whole difference between a carousel that loops and one that rewinds. Driving the
|
|
79
|
+
* track off the container's single `--kui-step` means the wrap from the last slide to the first
|
|
80
|
+
* runs the track back across every slide in between — the snap-back that reads as "it jumped to
|
|
81
|
+
* the beginning" rather than "it carried on".
|
|
82
|
+
*
|
|
83
|
+
* Published per element instead, each slide can place itself: at index 0 of five, the last slide
|
|
84
|
+
* reads `-1` and sits to the *left* of the live one, so stepping onto it moves one place forward
|
|
85
|
+
* like every other step. Nothing is cloned and nothing is reordered — the ends of the strip simply
|
|
86
|
+
* stop existing, because there is no strip, only positions on a ring.
|
|
87
|
+
*
|
|
88
|
+
* Signed and shortest-path: the far half of the ring counts backwards, so `+3` of five becomes
|
|
89
|
+
* `-2`. An even count has no midpoint to split, and the exact half goes positive by convention.
|
|
90
|
+
*
|
|
91
|
+
* @param position - The element's index within its own parent group.
|
|
92
|
+
* @param index - The live step.
|
|
93
|
+
* @param size - How many steps are in that group.
|
|
94
|
+
* @returns Places from the live step, negative for behind it.
|
|
95
|
+
* @complexity O(1) time and space.
|
|
96
|
+
* @overallScore 100
|
|
97
|
+
*/
|
|
98
|
+
export declare function circularOffset(position: number, index: number, size: number): number;
|
|
91
99
|
/**
|
|
92
100
|
* Where one step sits relative to the live one.
|
|
93
101
|
*
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Primitive } from '../../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap an icon-toggle-family `prepare` so a host with no `.kui-bar` children gets
|
|
4
|
+
* `data-kui-part="bar"` on its positional bars.
|
|
5
|
+
*
|
|
6
|
+
* Stamps eagerly, before calling `inner`: `stylesheetTimingPrepare` (the only `inner` this ever
|
|
7
|
+
* wraps today) runs at install, not activation — only *its* inner mirroring is deferred — and the
|
|
8
|
+
* stamp has to be in place at the same moment, or `icon-parts.css`'s `[data-kui-part='bar']` rules
|
|
9
|
+
* have nothing to select yet when the browser's next paint reads them. Restored on `ctx.signal`
|
|
10
|
+
* abort, which fires when the instance releases (mirrors `flip-parts.ts`'s (7a) attribute-ledger
|
|
11
|
+
* cleanup one primitive over) — never on `reset()`/`destroy()` directly, since `PrepareContext`
|
|
12
|
+
* hands `prepare` nothing else that fires on every teardown path.
|
|
13
|
+
*
|
|
14
|
+
* A host that already wrote its own `.kui-bar` markup is untouched: `findBars` never runs, so
|
|
15
|
+
* nothing here can clash with class-based CSS an author is already relying on.
|
|
16
|
+
*
|
|
17
|
+
* @param inner - The primitive's own `prepare`, unwrapped.
|
|
18
|
+
* @returns A `prepare` of the same shape, with the part-stamping layered in.
|
|
19
|
+
* @complexity O(n) time in the host's children, beyond whatever `inner` itself costs; O(n)
|
|
20
|
+
* additional space held past `prepare` for the bars' ledgers, until `ctx.signal` aborts.
|
|
21
|
+
* @overallScore 100
|
|
22
|
+
*/
|
|
23
|
+
export declare function withIconParts(inner: NonNullable<Primitive['prepare']>): NonNullable<Primitive['prepare']>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Cleanup, EffectParams, PrepareContext } from '../../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Phase 7a — the flip card's structural parts (owner decision E): `data-kui-part="front"`/`"back"`
|
|
4
|
+
* on an unclassed card's two faces, and the toggle control — an authored `.kui-flip-control`, an
|
|
5
|
+
* authored `button[aria-pressed]` (stamped so `flip-card-parts.css` reaches it, but never wired,
|
|
6
|
+
* since the author already owns its click handler), or a control this module injects and wires
|
|
7
|
+
* itself: `<button type="button" class="kui-flip-control" data-kui-part="control injected"
|
|
8
|
+
* aria-pressed="false">Flip card</button>` (the `quiet` token joins it for a hover trigger, so
|
|
9
|
+
* `flip-card-parts.css` can hide it until `:focus-visible` — the pointer path already has one).
|
|
10
|
+
*
|
|
11
|
+
* Classes win throughout: a card the author already marked up with `.kui-face-front`/`-back`/
|
|
12
|
+
* `.kui-flip-control` gets no redundant attribute next to a class its own CSS may already select.
|
|
13
|
+
*/
|
|
14
|
+
/** What {@link prepareFlipParts} resolved for one flip card. */
|
|
15
|
+
export interface FlipParts {
|
|
16
|
+
/** The card's toggle control, whether authored or injected. `resolveControl`'s injected branch
|
|
17
|
+
* always succeeds, so this is never absent. */
|
|
18
|
+
control: Element;
|
|
19
|
+
/** Undo every attribute stamp and remove every injected node. */
|
|
20
|
+
cleanup: Cleanup;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Matches whichever control {@link prepareFlipParts} resolved for a card, whichever of the three
|
|
24
|
+
* branches produced it — an authored `.kui-flip-control`, an authored `button[aria-pressed]`
|
|
25
|
+
* (stamped `data-kui-part="control"`), or the injected fallback (both class and stamp). `three-d/
|
|
26
|
+
* index.ts`'s deferred `prepareCardToggle` re-finds the control through this selector rather than
|
|
27
|
+
* calling {@link prepareFlipParts} a second time — target:-everywhere reconcile R-7 moved the one
|
|
28
|
+
* call that stamps/injects to prepare time, before `prepareCardToggle` (deferred to activation)
|
|
29
|
+
* ever runs, so by the time it looks, the control this selector matches already exists.
|
|
30
|
+
*/
|
|
31
|
+
export declare const CONTROL_SELECTOR: string;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve (and stamp/inject) a flip card's structural parts.
|
|
34
|
+
*
|
|
35
|
+
* @param el - The flip card element.
|
|
36
|
+
* @param params - The effect's authored parameters; only `trigger` is read, to decide whether an
|
|
37
|
+
* injected control starts quiet (hidden until `:focus-visible`) — a hover trigger already has a
|
|
38
|
+
* pointer path, so the injected control is a keyboard fallback rather than the primary control.
|
|
39
|
+
* @param ctx - The prepare-time context; only `doc` is read, so an injected button is built
|
|
40
|
+
* through the same document the rest of this codebase's primitives use rather than a global.
|
|
41
|
+
* @returns The card's control and a cleanup that undoes every stamp and removes the injected node.
|
|
42
|
+
* @complexity O(c) time in the card's direct children; O(1) additional space per stamped/injected
|
|
43
|
+
* node.
|
|
44
|
+
* @overallScore 100
|
|
45
|
+
*/
|
|
46
|
+
export declare function prepareFlipParts(el: Element, params: EffectParams, ctx: PrepareContext): FlipParts;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Registry } from '../../core/registry.js';
|
|
2
|
+
import type { Preset, Primitive } from '../../core/types.js';
|
|
3
|
+
export declare const TWEEN_PRIMITIVES: Primitive[];
|
|
4
|
+
/**
|
|
5
|
+
* Two names, no parameter defaults of their own.
|
|
6
|
+
*
|
|
7
|
+
* `tween-from` cloaks and `tween` does not, which is the same rule every other name in the catalog
|
|
8
|
+
* follows: a `from` tween's start state is installed by the runtime, so between first paint and
|
|
9
|
+
* `start()` the element is painted at its *rest* state and then jumps back to animate — the flash
|
|
10
|
+
* `Preset.cloak` exists to remove. A `to` tween starts at the rest state by construction, so there
|
|
11
|
+
* is nothing to hide and cloaking it would blank an element that was always meant to be visible.
|
|
12
|
+
*
|
|
13
|
+
* **Neither declares `phase`, and that is deliberate — checked against the actual stylesheet, not
|
|
14
|
+
* assumed from "generic effect, therefore unknowable".**
|
|
15
|
+
*
|
|
16
|
+
* `tween` (the `to` direction) is knowable and the answer is still "no phase fits". Every block in
|
|
17
|
+
* `kui-tween-to-*` (`src/css/tween.css`) declares an explicit `to` — `translate: var(--kui-tween-x,
|
|
18
|
+
* 0) ...`, not a missing endpoint — so, per D1's correction #5, `animation-fill-mode: both` pins that
|
|
19
|
+
* exact authored value on the channel forever once the animation finishes; it never resolves against
|
|
20
|
+
* whatever the cascade underneath would otherwise say. That is precisely the shape `EffectPhase`'s
|
|
21
|
+
* own doc calls out as the trap: fifteen of the catalog's fifty-four `cloak: true` entrances close
|
|
22
|
+
* their block the same way and are *deliberately* left unphased rather than marked `entrance`,
|
|
23
|
+
* because `entrance` specifically means "plays once and releases the channel". `tween` is that same
|
|
24
|
+
* closed shape by construction — every property group's `to` block closes, with no exception — so it
|
|
25
|
+
* belongs in that same deliberately-unphased set on the same grounds, not because nothing is known.
|
|
26
|
+
* It is not `state` either (nothing gates it behind a visitor condition — it runs the moment it
|
|
27
|
+
* activates), not `idle` (it is a bounded, one-shot animation, not an unbounded loop), and not `exit`
|
|
28
|
+
* (it does not start at rest and depart; it moves *to* an arbitrary authored value).
|
|
29
|
+
*
|
|
30
|
+
* `tween-from` is where "cannot be known statically" is the literal, checked reason, not a hedge.
|
|
31
|
+
* Its two-point blocks (`kui-tween-from-*`) are the mirror of `tween`'s — `from` is explicit and `to`
|
|
32
|
+
* is missing, so a plain `tween-from y:40` *does* release: it is structurally identical to an open
|
|
33
|
+
* entrance like `fade-up`, and would be a defensible `phase: 'entrance'` on its own. But
|
|
34
|
+
* `waypoints.ts`'s `waypointKeyframes` compiles a **different, fully-explicit block** the moment any
|
|
35
|
+
* key in the group is authored as a list — `tween-from x:'0,100,40'` renders through
|
|
36
|
+
* `kui-tween-keys3-translate`, whose own comment in `tween.css` says it plainly: "unlike everything
|
|
37
|
+
* above they are fully explicit from 0% to 100%... there is no implicit half left for the browser to
|
|
38
|
+
* fill from computed style." That block does **not** release, for the same fill-forever reason
|
|
39
|
+
* `tween`'s `to` blocks do not. So whether this preset's one instance releases its channel depends on
|
|
40
|
+
* whether the *author* wrote a single value or a list for at least one key in the group — a fact
|
|
41
|
+
* about the spec, not about the preset, and exactly the shape D1 was killed over (`repeat:` turning
|
|
42
|
+
* a finite entrance into a loop at author time, invisible to a preset-level field). Declaring
|
|
43
|
+
* `phase: 'entrance'` here would be right for `tween-from y:40` and silently wrong for `tween-from
|
|
44
|
+
* y:'0,40'` on the very same element — the "wrong phase is worse than none" case this project was
|
|
45
|
+
* warned about, so it stays undeclared and collides with everything, exactly as before this field
|
|
46
|
+
* existed. See `test/catalog-phase-mechanics.test.ts` for what stays checked instead.
|
|
47
|
+
*/
|
|
48
|
+
export declare const TWEEN_PRESETS: Preset[];
|
|
49
|
+
/**
|
|
50
|
+
* Register the generic tween.
|
|
51
|
+
*
|
|
52
|
+
* @param registry - Registry to populate.
|
|
53
|
+
* @returns The same registry, for chaining.
|
|
54
|
+
* @complexity O(1) time and space — two primitives, two presets.
|
|
55
|
+
* @overallScore 100
|
|
56
|
+
*/
|
|
57
|
+
export declare function registerTween(registry: Registry): Registry;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Channel, ParamSpec, ParameterSchema } from '../../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The generic tween's vocabulary: which property names an author may put in a `key:value` slot,
|
|
4
|
+
* what each one means, and which keyframe block renders it.
|
|
5
|
+
*
|
|
6
|
+
* **Why this is an allowlist and not a passthrough.** `tween <name>:<value>` is the one place in
|
|
7
|
+
* the library where an author names a *CSS property* rather than choosing from a primitive's
|
|
8
|
+
* declared parameters, so the obvious implementation — write whatever they typed into whatever
|
|
9
|
+
* they typed — is also the one that breaks two invariants at once. It breaks composition, because
|
|
10
|
+
* `core/channels.ts` decides whether two effects may share an element from their declared channel
|
|
11
|
+
* sets and an open-ended property list has no channel; and it breaks the parameter contract in
|
|
12
|
+
* `core/params.ts`, which exists precisely because author strings end up in a stylesheet. An
|
|
13
|
+
* allowlist keeps every tweenable property on a known channel with a known value grammar, and
|
|
14
|
+
* costs only that a property nobody listed here cannot be tweened until someone adds a row.
|
|
15
|
+
*
|
|
16
|
+
* **Why the rows are grouped.** CSS writes `translate` as one property, not three; a keyframe that
|
|
17
|
+
* sets it sets every axis. So the unit of rendering is the *group* — one `@keyframes` block per
|
|
18
|
+
* group, one animation track per group the author actually touched — and not the individual key.
|
|
19
|
+
* See `src/css/tween.css`, where each group's block is written out, including what the identity
|
|
20
|
+
* fallbacks mean for an axis the author did not name.
|
|
21
|
+
*/
|
|
22
|
+
/** One rendering unit: a single CSS property (or filter list) written by one keyframe block. */
|
|
23
|
+
export type TweenGroup = 'translate' | 'rotate' | 'scale' | 'opacity' | 'filter' | 'color' | 'background';
|
|
24
|
+
/**
|
|
25
|
+
* Declared in rendering order rather than derived from `TWEEN_PROPERTIES`'s key order, so
|
|
26
|
+
* `tween opacity:0 x:100` and `tween x:100 opacity:0` compile to the same track order. Two
|
|
27
|
+
* spellings of one animation producing two different `animation-name` lists would make every
|
|
28
|
+
* assertion about a compiled plan depend on the order the author happened to type in.
|
|
29
|
+
*/
|
|
30
|
+
export declare const TWEEN_GROUP_ORDER: readonly TweenGroup[];
|
|
31
|
+
/**
|
|
32
|
+
* The channel each group claims — the honest answer to "what does this spec collide with".
|
|
33
|
+
*
|
|
34
|
+
* These are the existing catalog channels, not new ones: a tween writing `translate` must collide
|
|
35
|
+
* with `fade-up` for the same reason two entrances do, and giving the tween a private channel name
|
|
36
|
+
* would let exactly that pair compose into one effect silently overwriting the other.
|
|
37
|
+
*/
|
|
38
|
+
export declare const TWEEN_GROUP_CHANNELS: Record<TweenGroup, Channel>;
|
|
39
|
+
interface TweenProperty {
|
|
40
|
+
group: TweenGroup;
|
|
41
|
+
spec: ParamSpec;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Author key → what it animates.
|
|
45
|
+
*
|
|
46
|
+
* Deliberately absent, and each for a reason worth writing down rather than rediscovering:
|
|
47
|
+
*
|
|
48
|
+
* - **`rotate-x` / `rotate-y`.** The CSS `rotate` property takes one axis at a time, so they could
|
|
49
|
+
* not share the rotate group with `rotate` anyway; and rotating a flat box about x or y without a
|
|
50
|
+
* `perspective()` reads as a vertical squash, not a turn. Perspective only exists inside the
|
|
51
|
+
* `transform` shorthand, which is a different channel entirely (`CHANNEL.skew` — see
|
|
52
|
+
* `core/types.ts`) and already has an effect family of its own in `flip-in-x`/`flip-in-y`.
|
|
53
|
+
* - **`width` / `height` / `top` / `left`.** Animatable, and every one of them animates layout.
|
|
54
|
+
* The tween declares `perfClass: 'paint'`; admitting these would make that a lie for the whole
|
|
55
|
+
* effect rather than for the one attribute that used them, and the library has never offered a
|
|
56
|
+
* layout-animating primitive without saying so.
|
|
57
|
+
* - **`skew`.** Same `transform`-shorthand problem as 3D rotation, and skew has no property of its
|
|
58
|
+
* own to write — `CHANNEL.skew` documents exactly this.
|
|
59
|
+
*/
|
|
60
|
+
export declare const TWEEN_PROPERTIES: Readonly<Record<string, TweenProperty>>;
|
|
61
|
+
/**
|
|
62
|
+
* The tween's parameter schema, declared statically even though which keys *matter* varies per
|
|
63
|
+
* attribute.
|
|
64
|
+
*
|
|
65
|
+
* Every key is always declared, so an author who mistypes one gets `resolveParams`' ordinary
|
|
66
|
+
* `unknown parameter "opactiy" (known: ...)` warning listing the whole vocabulary, exactly as they
|
|
67
|
+
* would on any other effect. Declaring only the keys a given attribute used would have produced a
|
|
68
|
+
* "known:" list containing nothing but the author's own typo-free keys, which is the least useful
|
|
69
|
+
* form that message could take.
|
|
70
|
+
*/
|
|
71
|
+
export declare const TWEEN_SCHEMA: ParameterSchema;
|
|
72
|
+
/**
|
|
73
|
+
* `BARE_NUMBER` and {@link decimalNumber} used to live here. They moved to `core/params.ts` when
|
|
74
|
+
* the `'number|percentage'` union landed and the core needed the same lexical decimal shift to
|
|
75
|
+
* turn `opacity:80%` into `0.8` — one implementation, so the two paths cannot drift into
|
|
76
|
+
* disagreeing about what `50%` means.
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* Give a bare number the unit its property implies — `x:100` is `100px`, `rotate:45` is `45deg`.
|
|
80
|
+
*
|
|
81
|
+
* `core/params.ts` requires a unit on every `length`, and should keep doing so: a unitless
|
|
82
|
+
* `distance:24` on `fade-up` is a mistake worth naming, because the parameter is ambiguous between
|
|
83
|
+
* `px` and `%` and the author simply left the unit off. `angle` is not in that position and
|
|
84
|
+
* `params.ts` now coerces it there too, which makes this function's angle branch a no-op for
|
|
85
|
+
* anything that reaches validation — it is kept because it runs first and keeps the tween's own
|
|
86
|
+
* `rotate:45` identical to its `x:100`. A tween property is different for `length`. `x:100` is the
|
|
87
|
+
* syntax this feature was specified around, it is what every other animation library accepts, and
|
|
88
|
+
* "100 what" has exactly one sensible answer per property. So the coercion lives here, scoped to
|
|
89
|
+
* the tween's own keys, rather than loosening validation for the other 255 effects.
|
|
90
|
+
*
|
|
91
|
+
* Number-valued properties also accept percentages, expressed as decimal ratios for the core
|
|
92
|
+
* validator. Length percentages retain their units. Other values pass through unchanged: `2rem`
|
|
93
|
+
* and a quoted `calc(...)` still have to earn their acceptance in `params.ts`.
|
|
94
|
+
*
|
|
95
|
+
* @complexity O(n) time in value length; O(1) space.
|
|
96
|
+
* @overallScore 100
|
|
97
|
+
*/
|
|
98
|
+
export declare function withImpliedUnit(raw: string, type: ParamSpec['type']): string;
|
|
99
|
+
/**
|
|
100
|
+
* A shared param type is intentionally broader than some CSS slots: percentages are lengths for
|
|
101
|
+
* x/y, but not z or blur, and a negative blur invalidates the entire filter list. Check these
|
|
102
|
+
* slot-specific constraints on scalar values and waypoints alike. CSS-wide keywords are also
|
|
103
|
+
* unsafe here: `--kui-tween-color: inherit` inherits the custom property, not the element's color.
|
|
104
|
+
* All other values still go through the core validator; this never opens a second CSS escape path.
|
|
105
|
+
*/
|
|
106
|
+
export declare function tweenValue(key: string, raw: string, warn: (message: string) => void, label?: string): string | undefined;
|
|
107
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { ParameterSchema } from '../../core/types.js';
|
|
2
|
+
import type { TweenGroup } from './properties.js';
|
|
3
|
+
/**
|
|
4
|
+
* Multi-waypoint tweening — `tween x:'0,100,40'`, a value list instead of a value.
|
|
5
|
+
*
|
|
6
|
+
* `tween`/`tween-from` animate between exactly two states: wherever the element is, and where the
|
|
7
|
+
* author said. That is `gsap.to()`/`gsap.from()`, and it is where the catalog stopped — nothing in
|
|
8
|
+
* it smooths a property through *several* states, which is the shape of most real choreography (out,
|
|
9
|
+
* over, settle) and of every keyframe array in Motion, GSAP and WAAPI.
|
|
10
|
+
*
|
|
11
|
+
* **The whole feature is still static CSS.** A list of N values selects an N-step `@keyframes` block
|
|
12
|
+
* from `src/css/tween.css`, and each step reads its own custom property. Nothing is generated at
|
|
13
|
+
* runtime, nothing is interpolated in JavaScript, and the result is an ordinary compositor-run CSS
|
|
14
|
+
* animation exactly as the two-point tween already was — see the outline's §2.3, and `tween.css`'s
|
|
15
|
+
* own header for what the blocks look like.
|
|
16
|
+
*
|
|
17
|
+
* **Why a value list rather than a waypoint list.** The alternative shape is per-waypoint objects —
|
|
18
|
+
* `at:'x:0 y:0' at:'x:100 y:-60'` — and the grammar cannot hold it: a `key:value` slot appears once
|
|
19
|
+
* per spec, so repeating one is a duplicate-parameter warning. Property-major is also what Motion
|
|
20
|
+
* and WAAPI use (`animate(el, { x: [0, 100, 40] })`), and it keeps the vocabulary identical to the
|
|
21
|
+
* two-point tween's: an author who knows `x:100` knows `x:'0,100,40'`.
|
|
22
|
+
*
|
|
23
|
+
* **Even spacing across the duration.** Also GSAP's own default for a bare keyframe array. A
|
|
24
|
+
* per-step position would need the *percentage* in the keyframe selector to vary, and a keyframe
|
|
25
|
+
* selector cannot be a `var()` — it is the one part of a keyframe block that has to be literal. An
|
|
26
|
+
* author who wants an uneven rhythm can repeat a value to hold it for a step.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* The most waypoints one property may name.
|
|
30
|
+
*
|
|
31
|
+
* A budget rather than a limit of the technique: every count needs its own `@keyframes` block per
|
|
32
|
+
* property group, because the step percentages are literal, so the shipped stylesheet grows with
|
|
33
|
+
* this number. Five states keeps this static vocabulary bounded. Longer choreography needs another keyframe
|
|
34
|
+
* definition; two effects on the same property cannot bypass this budget by composing.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MAX_WAYPOINTS = 5;
|
|
37
|
+
/**
|
|
38
|
+
* One property group's waypoint shape, as read off the attribute.
|
|
39
|
+
*
|
|
40
|
+
* `count` is the group's, not the key's: a keyframe block has one step count, so every key in the
|
|
41
|
+
* group renders at the same steps whatever each of them individually wrote.
|
|
42
|
+
*/
|
|
43
|
+
export interface GroupWaypoints {
|
|
44
|
+
count: number;
|
|
45
|
+
/** Author key → its values, already padded to `count` and unit-normalised. */
|
|
46
|
+
keys: Map<string, string[]>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read one authored value as a waypoint list, or as the single value it is.
|
|
50
|
+
*
|
|
51
|
+
* Commas inside functions and strings are data. Unlike the core tokenizer, this scanner must
|
|
52
|
+
* retain empty items: dropping the middle of `0,,100` changes both the count and the rhythm,
|
|
53
|
+
* while dropping every item of `,,` used to make the first-value lookup throw. Empty values now
|
|
54
|
+
* reach ordinary parameter validation at their authored index and use the CSS fallback.
|
|
55
|
+
*
|
|
56
|
+
* @returns The values in order. One entry means the author wrote a plain value, and every caller
|
|
57
|
+
* treats that as the two-point tween it has always been.
|
|
58
|
+
* @complexity O(n) time and space in the value's length.
|
|
59
|
+
* @overallScore 100
|
|
60
|
+
*/
|
|
61
|
+
export declare function readWaypoints(raw: string): string[];
|
|
62
|
+
/**
|
|
63
|
+
* Collect the waypoint lists an attribute wrote, bucketed by the group that renders them.
|
|
64
|
+
*
|
|
65
|
+
* @param authored - Author key → raw value, for tween properties only.
|
|
66
|
+
* @returns One entry per group that named at least one list. Groups whose keys are all plain values
|
|
67
|
+
* are absent, and keep the two-point blocks they have always used.
|
|
68
|
+
* @complexity O(n) time and space in the number of values across the attribute.
|
|
69
|
+
* @overallScore 100
|
|
70
|
+
*/
|
|
71
|
+
export declare function collectWaypoints(authored: [string, string[]][], warn: (message: string) => void): Map<TweenGroup, GroupWaypoints>;
|
|
72
|
+
/**
|
|
73
|
+
* Expand a group's lists into one parameter per waypoint, with a spec for each.
|
|
74
|
+
*
|
|
75
|
+
* The key is `x[2]`, not `x-2`, and the brackets are load-bearing: these keys are synthesised by
|
|
76
|
+
* the library and can never be authored, so when one of them appears in a `resolveParams`
|
|
77
|
+
* diagnostic — `parameter "x[2]": expected a length` — the author can see both which key and which
|
|
78
|
+
* waypoint without the message having to explain itself, and can tell at a glance that it is not a
|
|
79
|
+
* name they were supposed to have written.
|
|
80
|
+
*
|
|
81
|
+
* The custom property is `--kui-tween-<key>-<n>`, which is what `tween.css`'s step reads, with the
|
|
82
|
+
* plain `--kui-tween-<key>` as its fallback. That fallback is the whole broadcast rule: a key that
|
|
83
|
+
* wrote a single value (`tween x:'0,100,40' y:20`) sets only the plain property, so every step of
|
|
84
|
+
* the block reads the same `y` and it holds — no JavaScript, no per-step duplication of a value the
|
|
85
|
+
* author wrote once.
|
|
86
|
+
*
|
|
87
|
+
* @param waypoints - One group's padded lists.
|
|
88
|
+
* @param params - Sink for the expanded values, keyed as above.
|
|
89
|
+
* @param schema - Sink for the specs those values are validated against.
|
|
90
|
+
* @complexity O(n) time and space in the group's total number of values.
|
|
91
|
+
* @overallScore 100
|
|
92
|
+
*/
|
|
93
|
+
export declare function expandWaypoints(waypoints: GroupWaypoints, params: Record<string, string>, schema: ParameterSchema, warn: (message: string) => void): void;
|
|
94
|
+
/**
|
|
95
|
+
* The keyframe block a group with waypoints renders through.
|
|
96
|
+
*
|
|
97
|
+
* One block per (group, count), all of them fully explicit from 0% to 100% — so unlike the
|
|
98
|
+
* two-point blocks there is no `to`-only and `from`-only pair, and `tween` and `tween-from` share
|
|
99
|
+
* them. That falls out of what a list *is*: an author who writes every state has written the first
|
|
100
|
+
* one too, so there is no implicit half left for the browser to fill from the element's computed
|
|
101
|
+
* style.
|
|
102
|
+
*
|
|
103
|
+
* @complexity O(1) time and space.
|
|
104
|
+
* @overallScore 100
|
|
105
|
+
*/
|
|
106
|
+
export declare function waypointKeyframes(group: TweenGroup, count: number): string;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Animator } from '../core/animator.js';
|
|
2
|
+
import type { Registry } from '../core/registry.js';
|
|
3
|
+
import type { Preset, Primitive } from '../core/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The showcase module: pre-built presentation widgets — a dialog, an ARIA carousel, image
|
|
6
|
+
* hotspots — the one part of this library that owns UI behaviour rather than only motion.
|
|
7
|
+
* `docs/design.md` §14's amendment is the boundary this module operates under; every widget's own
|
|
8
|
+
* file (`device-frame.ts`, `lightbox.ts`, …) argues its own case for why it needs the exception.
|
|
9
|
+
*
|
|
10
|
+
* This is the *only* file anything outside `src/showcase/` may import from — see
|
|
11
|
+
* `only-effects-barrel-imports-showcase` in `.dependency-cruiser.cjs`. That is what makes the
|
|
12
|
+
* later split into a standalone `kuinetic.showcase.js` a build-config change and not a source
|
|
13
|
+
* change: every showcase file keeps importing from inside `src/showcase/`, and the one line that
|
|
14
|
+
* moves is `src/effects/index.ts`'s call to {@link registerShowcase}.
|
|
15
|
+
*/
|
|
16
|
+
export declare const SHOWCASE_PRIMITIVES: Primitive[];
|
|
17
|
+
export declare const SHOWCASE_PRESETS: Preset[];
|
|
18
|
+
/**
|
|
19
|
+
* Register every showcase widget onto a `Registry`, an `Animator`, or anything shaped like either.
|
|
20
|
+
*
|
|
21
|
+
* The shape check — not `instanceof` — is what lets this same function serve as both the in-core
|
|
22
|
+
* call `src/effects/index.ts` makes today and the `boot({ register })` callback a split
|
|
23
|
+
* `kuinetic.showcase.js` tag will hand a page's existing animator tomorrow. See
|
|
24
|
+
* `src/core/register-into.ts`'s docblock for why identity cannot survive that split and shape can.
|
|
25
|
+
*
|
|
26
|
+
* @param target - The registry, the animator, or a host exposing one as `.registry`.
|
|
27
|
+
* @returns `target`, so callers can chain.
|
|
28
|
+
* @complexity O(n) time in showcase primitives plus presets; O(1) extra space.
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerShowcase(target: unknown): Registry | Animator;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** A safe, supported video URL and its preferred frame shape. */
|
|
2
|
+
export interface MediaSource {
|
|
3
|
+
kind: 'youtube' | 'vimeo' | 'file';
|
|
4
|
+
embedUrl: string;
|
|
5
|
+
aspect: 'wide' | 'tall';
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolve a real link into a supported player source. Unknown hosts and non-web schemes keep
|
|
9
|
+
* their normal link behavior; no attacker-controlled URL is handed to an iframe.
|
|
10
|
+
* @complexity O(n) in the URL length; O(1) extra space.
|
|
11
|
+
* @overallScore 100
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveMediaSource(href: string): MediaSource | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ModalContent {
|
|
2
|
+
node: HTMLElement;
|
|
3
|
+
label: string;
|
|
4
|
+
duration: number;
|
|
5
|
+
scale: string;
|
|
6
|
+
ease: string;
|
|
7
|
+
reducedMotion: boolean;
|
|
8
|
+
onKey?: (event: KeyboardEvent) => void;
|
|
9
|
+
onClose?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export interface ModalShell {
|
|
12
|
+
open(content: ModalContent): void;
|
|
13
|
+
dismiss(): void;
|
|
14
|
+
release(): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Share one lazily built modal per document across image and video widgets. The final live
|
|
18
|
+
* instance removes it, including an in-flight close timer and any scroll lock.
|
|
19
|
+
* @complexity O(1) per operation; O(1) shared DOM per document.
|
|
20
|
+
* @overallScore 100
|
|
21
|
+
*/
|
|
22
|
+
export declare function acquireModalShell(doc: Document): ModalShell;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Channel, ParameterSchema, PerfClass, Primitive } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The one shape every showcase widget shares.
|
|
4
|
+
*
|
|
5
|
+
* `src/showcase/` builds UI components the effect catalog deliberately stays out of (a dialog, an
|
|
6
|
+
* ARIA carousel, a native popover) — see `docs/design.md` §14's amendment. Every one of them is
|
|
7
|
+
* built the same way for the same reasons, so this bakes the shared answers in once rather than
|
|
8
|
+
* repeating them per widget:
|
|
9
|
+
*
|
|
10
|
+
* - `renderer: 'javascript'` — nothing here compiles to a `@keyframes` block; the DOM the widget
|
|
11
|
+
* builds and the states it toggles are the whole effect.
|
|
12
|
+
* - `supportedTimelines: ['time']` — a widget runs on a clock, never on scroll/view/pointer
|
|
13
|
+
* progress. Narrower than `TIMELINE_AGNOSTIC` (`effects/shared.ts`), which abstains for
|
|
14
|
+
* primitives that never read a `Timeline` at all; a widget primitive *could* be asked for one and
|
|
15
|
+
* the honest answer is "only time makes sense here".
|
|
16
|
+
* - `supportedActivations: ['load']`, `defaultActivation: 'load'` — a widget must be wired up
|
|
17
|
+
* before a keyboard user tabs to it or a crawler indexes it, not when it happens to scroll into
|
|
18
|
+
* view. `on:enter`'s lazy-install story is right for a decorative reveal and wrong for a control.
|
|
19
|
+
* - `reducedMotion: 'shorten'`, never `'disable'` — `'disable'` means the animator never calls
|
|
20
|
+
* `activate()` at all (`src/effects/forms/primitives.ts`'s doc on the same trap), which would
|
|
21
|
+
* leave the widget entirely unbuilt for a reduced-motion visitor. Motion is removed in CSS
|
|
22
|
+
* instead; the widget itself still has to exist.
|
|
23
|
+
* - `perfClass` is the one field every widget answers differently (a dialog's `backdrop-filter`
|
|
24
|
+
* is `'paint'`, a native-popover positioning read is `'layout'`, a synchronous attribute stamp is
|
|
25
|
+
* `'layout'` too), so it is a parameter rather than baked in.
|
|
26
|
+
*
|
|
27
|
+
* `prepare` is taken pre-built — already run through `deferPrepare` and, where the widget has
|
|
28
|
+
* nothing to time, `withTimingContract` — rather than assembled here, because the timing contract
|
|
29
|
+
* (which of `duration`/`delay`/`ease` a widget honours, and why not the rest) genuinely differs per
|
|
30
|
+
* widget and baking one reason in would misdescribe the others. Same division of labour
|
|
31
|
+
* `src/effects/navigation/index.ts`'s `navPrimitive` already uses for its own small family.
|
|
32
|
+
*
|
|
33
|
+
* @param id - Primitive id, also the preset name for every showcase widget shipped so far.
|
|
34
|
+
* @param spec - The three fields every widget answers differently: `channels` (CSS property
|
|
35
|
+
* groups this widget's CSS claims, see `core/channels.ts`), `parameters` (the widget's parameter
|
|
36
|
+
* schema), and `perfClass` (this widget's honest performance-budget class). Grouped into one
|
|
37
|
+
* object rather than three positional params so this factory stays under the four-parameter
|
|
38
|
+
* lint ceiling (`eslint.config.js`'s `max-params`) alongside `prepare`.
|
|
39
|
+
* @param prepare - Fully wrapped setup: `withTimingContract(...)`-and/or-`deferPrepare(...)`.
|
|
40
|
+
* @returns A complete `Primitive`.
|
|
41
|
+
* @complexity O(1) time and space.
|
|
42
|
+
*/
|
|
43
|
+
export declare function widgetPrimitive(id: string, spec: {
|
|
44
|
+
channels: Channel[];
|
|
45
|
+
parameters: ParameterSchema;
|
|
46
|
+
perfClass: PerfClass;
|
|
47
|
+
}, prepare: NonNullable<Primitive['prepare']>): Primitive;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Preset, Primitive } from '../core/types.js';
|
|
2
|
+
/** A host-only speed control for Web Animations and CSS motion in its subtree. */
|
|
3
|
+
export declare const SLOW_MO_PRIMITIVE: Primitive;
|
|
4
|
+
/** The showcase name for the speed-control primitive. */
|
|
5
|
+
export declare const SLOW_MO_PRESETS: Preset[];
|