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
|
@@ -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;
|