kuinetic 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -10
- package/dist/esm/advanced/index.mjs +4727 -0
- package/dist/esm/chunk-AEQGC2KM.mjs +189 -0
- package/dist/esm/chunk-MQSNMYRP.mjs +9332 -0
- package/dist/esm/chunk-RVTYN6NZ.mjs +3446 -0
- package/dist/esm/chunk-U43BX5O2.mjs +2984 -0
- package/dist/esm/core/index.mjs +16 -9
- package/dist/esm/effects/index.mjs +19 -4
- package/dist/esm/index.mjs +17 -10
- package/dist/kuinetic.advanced.js +5070 -0
- package/dist/kuinetic.advanced.min.js +749 -0
- package/dist/kuinetic.all.js +15147 -6039
- package/dist/kuinetic.all.min.js +2 -0
- package/dist/kuinetic.css +2801 -318
- package/dist/kuinetic.js +15147 -6038
- package/dist/kuinetic.min.css +1 -0
- package/dist/kuinetic.min.js +7 -0
- package/dist/types/3d/angles.d.ts +30 -0
- package/dist/types/3d/flattening.d.ts +49 -0
- package/dist/types/3d/index.d.ts +36 -0
- package/dist/types/3d/model-3d.d.ts +115 -0
- package/dist/types/3d/register.d.ts +26 -0
- package/dist/types/3d/webgl.d.ts +24 -0
- package/dist/types/advanced/audio.d.ts +322 -0
- package/dist/types/advanced/base.d.ts +233 -0
- package/dist/types/advanced/camera-3d.d.ts +236 -0
- package/dist/types/advanced/fluid-cursor.d.ts +149 -0
- package/dist/types/advanced/gl-utils.d.ts +52 -0
- package/dist/types/advanced/glsl.d.ts +60 -0
- package/dist/types/advanced/index.d.ts +23 -0
- package/dist/types/advanced/particles.d.ts +108 -0
- package/dist/types/advanced/scenes.d.ts +207 -0
- package/dist/types/advanced/shaders.d.ts +972 -0
- package/dist/types/browser/boot.d.ts +72 -0
- package/dist/types/core/activation.d.ts +227 -2
- package/dist/types/core/animator.d.ts +446 -11
- package/dist/types/core/attrs.d.ts +9 -0
- package/dist/types/core/breakpoints.d.ts +260 -0
- package/dist/types/core/bundles.d.ts +71 -0
- package/dist/types/core/callback.d.ts +64 -0
- package/dist/types/core/capabilities.d.ts +47 -0
- package/dist/types/core/channels.d.ts +120 -2
- package/dist/types/core/cloak-selectors.d.ts +47 -0
- package/dist/types/core/compile.d.ts +207 -2
- package/dist/types/core/control.d.ts +218 -0
- package/dist/types/core/declarations.d.ts +128 -0
- package/dist/types/core/derived/aggregate.d.ts +43 -0
- package/dist/types/core/derived/book.d.ts +30 -0
- package/dist/types/core/derived/diagnostics.d.ts +51 -0
- package/dist/types/core/derived/group-gate.d.ts +62 -0
- package/dist/types/core/derived/install.d.ts +110 -0
- package/dist/types/core/derived/late-matches.d.ts +19 -0
- package/dist/types/core/derived/types.d.ts +108 -0
- package/dist/types/core/easing.d.ts +57 -0
- package/dist/types/core/element-config.d.ts +47 -6
- package/dist/types/core/element-size.d.ts +23 -0
- package/dist/types/core/event-sources.d.ts +39 -0
- package/dist/types/core/flip.d.ts +34 -1
- package/dist/types/core/gesture.d.ts +12 -0
- package/dist/types/core/host-facts.d.ts +155 -0
- package/dist/types/core/index.d.ts +7 -3
- package/dist/types/core/owned-styles.d.ts +129 -2
- package/dist/types/core/params.d.ts +48 -0
- package/dist/types/core/parse.d.ts +28 -1
- package/dist/types/core/register-into.d.ts +29 -0
- package/dist/types/core/registry.d.ts +10 -3
- package/dist/types/core/repeat.d.ts +91 -0
- package/dist/types/core/sequence.d.ts +126 -0
- package/dist/types/core/stagger-config.d.ts +199 -0
- package/dist/types/core/stagger-keys.d.ts +63 -0
- package/dist/types/core/stagger.d.ts +187 -6
- package/dist/types/core/style-plan.d.ts +21 -16
- package/dist/types/core/target.d.ts +128 -0
- package/dist/types/core/threshold-reachability.d.ts +45 -0
- package/dist/types/core/time-scale.d.ts +9 -0
- package/dist/types/core/toggle-actions.d.ts +141 -0
- package/dist/types/core/travel.d.ts +59 -0
- package/dist/types/core/types.d.ts +699 -13
- package/dist/types/core/unquoted-selectors.d.ts +53 -0
- package/dist/types/effects/carousel/drag.d.ts +80 -0
- package/dist/types/effects/carousel/index.d.ts +149 -0
- package/dist/types/effects/catalog/discrete.d.ts +13 -0
- package/dist/types/effects/catalog/interaction-proximity.d.ts +24 -0
- package/dist/types/effects/catalog/interaction-reveal.d.ts +248 -0
- package/dist/types/effects/catalog/interaction-shared.d.ts +42 -0
- package/dist/types/effects/catalog/interaction-states.d.ts +68 -0
- package/dist/types/effects/catalog/materials.d.ts +67 -0
- package/dist/types/effects/catalog/media-shared.d.ts +3 -2
- package/dist/types/effects/catalog/numbers-shared.d.ts +8 -5
- package/dist/types/effects/catalog/shared.d.ts +1 -1
- package/dist/types/effects/catalog/text-shared.d.ts +86 -10
- package/dist/types/effects/catalog/transforms.d.ts +13 -0
- package/dist/types/effects/catalog/view-transitions.d.ts +13 -0
- package/dist/types/effects/forms/primitives.d.ts +15 -4
- package/dist/types/effects/gestures/index.d.ts +53 -0
- package/dist/types/effects/index.d.ts +5 -0
- package/dist/types/effects/layout/presets.d.ts +35 -0
- package/dist/types/effects/motion-path/index.d.ts +35 -0
- package/dist/types/effects/scroll-mechanics/params.d.ts +23 -0
- package/dist/types/effects/scroll-mechanics/presets.d.ts +51 -0
- package/dist/types/effects/scroll-mechanics/section-index.d.ts +47 -0
- package/dist/types/effects/shared.d.ts +124 -4
- package/dist/types/effects/step-index.d.ts +121 -0
- package/dist/types/effects/step-marking.d.ts +41 -33
- package/dist/types/effects/svg/icon-parts.d.ts +23 -0
- package/dist/types/effects/three-d/flip-parts.d.ts +46 -0
- package/dist/types/effects/tween/index.d.ts +57 -0
- package/dist/types/effects/tween/properties.d.ts +107 -0
- package/dist/types/effects/tween/waypoints.d.ts +106 -0
- package/dist/types/showcase/compare.d.ts +4 -0
- package/dist/types/showcase/device-frame.d.ts +3 -0
- package/dist/types/showcase/hotspots.d.ts +3 -0
- package/dist/types/showcase/index.d.ts +30 -0
- package/dist/types/showcase/lightbox.d.ts +3 -0
- package/dist/types/showcase/media-source.d.ts +13 -0
- package/dist/types/showcase/modal-shell.d.ts +22 -0
- package/dist/types/showcase/scroll-story.d.ts +4 -0
- package/dist/types/showcase/shared.d.ts +47 -0
- package/dist/types/showcase/slideshow.d.ts +3 -0
- package/dist/types/showcase/slow-mo.d.ts +5 -0
- package/package.json +14 -7
- package/dist/esm/chunk-7WMNPIOZ.mjs +0 -4883
- package/dist/esm/chunk-JT4PZL3A.mjs +0 -773
- package/dist/esm/chunk-TJDDIQRG.mjs +0 -1290
|
@@ -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[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kuinetic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Declarative web animation from HTML attributes. Native CSS where possible, JS only where necessary.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"main": "./dist/esm/index.mjs",
|
|
11
11
|
"module": "./dist/esm/index.mjs",
|
|
12
12
|
"types": "./dist/types/index.d.ts",
|
|
13
|
-
"unpkg": "dist/kuinetic.js",
|
|
14
|
-
"jsdelivr": "dist/kuinetic.js",
|
|
13
|
+
"unpkg": "dist/kuinetic.min.js",
|
|
14
|
+
"jsdelivr": "dist/kuinetic.min.js",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"types": "./dist/types/effects/index.d.ts",
|
|
29
29
|
"default": "./dist/esm/effects/index.mjs"
|
|
30
30
|
},
|
|
31
|
+
"./advanced": {
|
|
32
|
+
"types": "./dist/types/advanced/index.d.ts",
|
|
33
|
+
"default": "./dist/esm/advanced/index.mjs"
|
|
34
|
+
},
|
|
31
35
|
"./css": "./dist/kuinetic.css",
|
|
32
36
|
"./package.json": "./package.json"
|
|
33
37
|
},
|
|
@@ -39,11 +43,12 @@
|
|
|
39
43
|
"lint": "eslint src test scripts",
|
|
40
44
|
"lint:deps": "depcruise src --config .dependency-cruiser.cjs",
|
|
41
45
|
"lint:dead": "knip",
|
|
42
|
-
"ci": "npm run build:dist && npm run typecheck && npm run lint && npm run lint:deps && npm run lint:dead && npm run check:css-coverage && npm run test:coverage && npm run test:browser",
|
|
46
|
+
"ci": "npm run build:dist && node scripts/verify-tiers.mjs && npm run typecheck && npm run lint && npm run lint:deps && npm run lint:dead && npm run check:css-coverage && npm run test:coverage && npm run test:browser",
|
|
43
47
|
"size": "npm run build:dist && size-limit",
|
|
44
|
-
"build": "npm run generate:css && esbuild src/index.ts --bundle --format=iife --global-name=kuinetic --outfile=demo/kuinetic.js && esbuild src/css/index.css --bundle --outfile=demo/kuinetic.css && npx @tailwindcss/cli -i demo/tailwind-entry.css -o demo/tailwind.css && node scripts/build-standalone.mjs demo",
|
|
45
|
-
"build:dist": "npm run clean:dist && npm run generate:css && esbuild src/index.ts src/core/index.ts src/effects/index.ts --bundle --format=esm --splitting --outdir=dist/esm --out-extension:.js=.mjs && esbuild src/index.ts --bundle --format=iife --global-name=kuinetic --outfile=dist/kuinetic.js && esbuild src/css/index.css --bundle --outfile=dist/kuinetic.css && tsc -p tsconfig.build.json && node scripts/build-standalone.mjs",
|
|
48
|
+
"build": "npm run generate:css && esbuild src/index.ts --bundle --format=iife --global-name=kuinetic --minify --sourcemap=linked --outfile=demo/kuinetic.js && esbuild src/css/index.css --bundle --outfile=demo/kuinetic.css && npx @tailwindcss/cli -i demo/tailwind-entry.css -o demo/tailwind.css && node scripts/build-tiers.mjs demo && node scripts/build-standalone.mjs demo && npm run sync:docs",
|
|
49
|
+
"build:dist": "npm run clean:dist && npm run generate:css && esbuild src/index.ts src/core/index.ts src/effects/index.ts src/advanced/index.ts --bundle --format=esm --splitting --outdir=dist/esm --out-extension:.js=.mjs && esbuild src/index.ts --bundle --format=iife --global-name=kuinetic --outfile=dist/kuinetic.js && esbuild src/css/index.css --bundle --outfile=dist/kuinetic.css && esbuild src/index.ts --bundle --format=iife --global-name=kuinetic --minify --outfile=dist/kuinetic.min.js && esbuild src/css/index.css --bundle --minify --outfile=dist/kuinetic.min.css && tsc -p tsconfig.build.json && node scripts/build-tiers.mjs && node scripts/build-standalone.mjs",
|
|
46
50
|
"verify:standalone": "npm run build:dist && node scripts/verify-standalone.mjs",
|
|
51
|
+
"verify:tiers": "npm run build:dist && node scripts/verify-tiers.mjs",
|
|
47
52
|
"verify:pack": "npm run build:dist && node scripts/verify-pack.mjs",
|
|
48
53
|
"clean:dist": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
49
54
|
"prepack": "npm run build:dist",
|
|
@@ -57,7 +62,8 @@
|
|
|
57
62
|
"generate:nav": "node scripts/generate-nav-header.mjs",
|
|
58
63
|
"record": "npm run build && node scripts/verify-browser.mjs --record",
|
|
59
64
|
"check:showcase": "npm run build && node scripts/check-showcase.mjs",
|
|
60
|
-
"check:css-coverage": "npm run build && node scripts/check-css-coverage.mjs"
|
|
65
|
+
"check:css-coverage": "npm run build && node scripts/check-css-coverage.mjs",
|
|
66
|
+
"sync:docs": "node scripts/sync-demo-docs.mjs"
|
|
61
67
|
},
|
|
62
68
|
"devDependencies": {
|
|
63
69
|
"@eslint/js": "^9.39.5",
|
|
@@ -78,6 +84,7 @@
|
|
|
78
84
|
"pngjs": "^7.0.0",
|
|
79
85
|
"size-limit": "^13.0.3",
|
|
80
86
|
"tailwindcss": "^4.3.3",
|
|
87
|
+
"three": "^0.186.0",
|
|
81
88
|
"typescript": "^5.9.3",
|
|
82
89
|
"typescript-eslint": "^8.66.0",
|
|
83
90
|
"vitest": "^2.1.9"
|