kuinetic 0.2.1 → 0.2.3
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 +15 -8
- package/dist/esm/advanced/index.mjs +5 -5
- package/dist/esm/{chunk-U43BX5O2.mjs → chunk-FASAEQDR.mjs} +54 -7
- package/dist/esm/{chunk-BN2Y4UKB.mjs → chunk-FYMZW5N2.mjs} +2373 -541
- package/dist/esm/{chunk-RVTYN6NZ.mjs → chunk-MZQG2VMG.mjs} +208 -2
- package/dist/esm/core/index.mjs +21 -3
- package/dist/esm/effects/index.mjs +2 -2
- package/dist/esm/index.mjs +35 -4
- package/dist/esm/notes/index.mjs +1075 -0
- package/dist/kuinetic.advanced.js +63 -25
- package/dist/kuinetic.advanced.min.js +3 -3
- package/dist/kuinetic.all.js +2658 -538
- package/dist/kuinetic.all.min.js +2 -2
- package/dist/kuinetic.css +238 -65
- package/dist/kuinetic.js +2657 -537
- package/dist/kuinetic.min.css +1 -1
- package/dist/kuinetic.min.js +2 -2
- package/dist/kuinetic.notes.js +1 -0
- package/dist/types/3d/flattening.d.ts +8 -7
- package/dist/types/advanced/camera-3d.d.ts +0 -4
- package/dist/types/advanced/fluid-cursor.d.ts +0 -4
- package/dist/types/advanced/particles.d.ts +0 -4
- package/dist/types/advanced/scenes.d.ts +0 -4
- package/dist/types/browser/boot.d.ts +9 -4
- package/dist/types/core/activation.d.ts +11 -0
- package/dist/types/core/compile.d.ts +7 -0
- package/dist/types/core/deck-viewer.d.ts +87 -0
- package/dist/types/core/derived/types.d.ts +0 -1
- package/dist/types/core/describe.d.ts +174 -0
- package/dist/types/core/gesture.d.ts +16 -1
- package/dist/types/core/index.d.ts +6 -2
- package/dist/types/core/stagger.d.ts +1 -1
- package/dist/types/core/target.d.ts +28 -0
- package/dist/types/core/timing-contract.d.ts +61 -0
- package/dist/types/core/types.d.ts +59 -0
- package/dist/types/effects/auto-motion.d.ts +169 -0
- package/dist/types/effects/carousel/deck.d.ts +170 -0
- package/dist/types/effects/carousel/drag.d.ts +6 -0
- package/dist/types/effects/carousel/fit.d.ts +130 -0
- package/dist/types/effects/carousel/index.d.ts +6 -23
- package/dist/types/effects/carousel/stack.d.ts +77 -0
- package/dist/types/effects/catalog/interaction-reveal.d.ts +69 -9
- package/dist/types/effects/forms/primitives.d.ts +1 -2
- package/dist/types/effects/gestures/index.d.ts +3 -4
- package/dist/types/effects/shared.d.ts +3 -30
- package/dist/types/effects/step-index.d.ts +48 -10
- package/dist/types/effects/swipe-event.d.ts +75 -0
- package/dist/types/index.d.ts +26 -0
- package/dist/types/notes/catalog-core.d.ts +3 -0
- package/dist/types/notes/catalog.d.ts +3 -0
- package/dist/types/notes/index.d.ts +13 -0
- package/dist/types/notes/interaction-reveal.d.ts +3 -0
- package/dist/types/notes/interaction.d.ts +6 -0
- package/dist/types/notes/keys.d.ts +7 -0
- package/dist/types/notes/mechanics.d.ts +7 -0
- package/dist/types/notes/scroll-nav-forms.d.ts +6 -0
- package/dist/types/notes/shared.d.ts +6 -0
- package/dist/types/notes/showcase.d.ts +7 -0
- package/dist/types/notes/text.d.ts +3 -0
- package/dist/types/showcase/compare.d.ts +9 -0
- package/dist/types/showcase/index.d.ts +3 -0
- package/dist/types/showcase/lightbox.d.ts +23 -1
- package/dist/types/showcase/modal-shell.d.ts +11 -0
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ wherever CSS can do it. Standalone, MIT, npm + CDN, framework-agnostic. No produ
|
|
|
10
10
|
<h1 data-kui="fade-up">Hello.</h1>
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
305 named effects across scroll reveals, hover/interaction, text, numbers, layout, SVG, 3D, and
|
|
14
14
|
gesture-driven motion. 3,800+ unit tests. The jsdom suite holds `src/` at 100%
|
|
15
15
|
line/branch/function/statement coverage with two carve-outs: the WebGL tier in `src/advanced/`
|
|
16
16
|
(`shaders.ts`, `gl-utils.ts`, `fluid-cursor.ts`, `particles.ts`), whose GPU paths cannot execute
|
|
@@ -123,16 +123,23 @@ its readable, unminified twin, about twice the transfer size; use it only for de
|
|
|
123
123
|
`kuinetic.advanced.min.js` is a tier: it needs core on the page, in either order, and never carries
|
|
124
124
|
a copy of it.
|
|
125
125
|
|
|
126
|
-
Every one of those browser bundles starts itself once the document is ready.
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
Every one of those browser bundles starts itself once the document is ready. Importing from npm does
|
|
127
|
+
**not** start anything — a module import stays side-effect-free, which is the guarantee the bundler
|
|
128
|
+
path is built on.
|
|
129
|
+
|
|
130
|
+
To drive it by hand, put `data-kui-manual` on the tag. On `kuinetic.js` that turns off the
|
|
131
|
+
*auto-start* only: nothing is created or started until you call `kuinetic.kuinetic({ ... }).start()`,
|
|
132
|
+
and any tier bundle you load (`kuinetic.advanced.js`, ...) still registers into the animator you
|
|
133
|
+
build, in either tag order. On a tier's own tag it takes that tier out entirely.
|
|
129
134
|
|
|
130
135
|
> **Changed in 0.2.** These bundles used to do nothing until you called
|
|
131
136
|
> `kuinetic.kuinetic({ observe: true }).start()` yourself, and `kuinetic.all.js` started itself the
|
|
132
137
|
> instant it parsed rather than at `DOMContentLoaded`. If you already write that call, it keeps
|
|
133
|
-
> working and your animator is still the one the page uses
|
|
134
|
-
>
|
|
135
|
-
>
|
|
138
|
+
> working and your animator is still the one the page uses. A call that names its own options — a
|
|
139
|
+
> `reporter`, a scoped `root`, a `registry` — is how you configure the auto-started animator, and it
|
|
140
|
+
> is adopted without comment. A call with no options, or only `{ observe: true }`, does nothing the
|
|
141
|
+
> script tag has not already done, so you will see one console line saying it is now redundant. Delete
|
|
142
|
+
> it, or add `data-kui-manual` to the tag to go back to driving everything by hand.
|
|
136
143
|
|
|
137
144
|
## Your first animation
|
|
138
145
|
|
|
@@ -179,7 +186,7 @@ untrusted input — see Getting Started for the full note.
|
|
|
179
186
|
## Docs
|
|
180
187
|
|
|
181
188
|
- **Getting Started** — install, first animation, timing, composition, common mistakes.
|
|
182
|
-
- **Catalog** — all
|
|
189
|
+
- **Catalog** — all 305 named effects, grouped by category, with renderer and channel metadata.
|
|
183
190
|
- **Architecture** — the attribute grammar, the composition model, and why the library is built
|
|
184
191
|
the way it is (`docs/design.md` in this repo).
|
|
185
192
|
|
|
@@ -1836,7 +1836,7 @@ function parseAngleRadians(raw) {
|
|
|
1836
1836
|
if (!match) return 0;
|
|
1837
1837
|
const value = parseFloat(match[1]);
|
|
1838
1838
|
if (!Number.isFinite(value)) return 0;
|
|
1839
|
-
return value *
|
|
1839
|
+
return value * ANGLE_UNITS[(match[2] ?? "deg").toLowerCase()];
|
|
1840
1840
|
}
|
|
1841
1841
|
var PALETTE_SIZE = 5;
|
|
1842
1842
|
var DEFAULT_PALETTE = [
|
|
@@ -2067,7 +2067,7 @@ function paintBoxOf(content, natural, cs) {
|
|
|
2067
2067
|
if (bw <= 0 || bh <= 0) return content;
|
|
2068
2068
|
const [dw, dh] = fittedSize(cs.objectFit || "fill", bw, bh, natural);
|
|
2069
2069
|
const tokens = (cs.objectPosition || "50% 50%").trim().split(/\s+/);
|
|
2070
|
-
const left = content.left + positionOffset(tokens[0]
|
|
2070
|
+
const left = content.left + positionOffset(tokens[0], bw - dw);
|
|
2071
2071
|
const top = content.top + positionOffset(tokens[1] ?? "50%", bh - dh);
|
|
2072
2072
|
return { left, top, right: left + dw, bottom: top + dh };
|
|
2073
2073
|
}
|
|
@@ -2333,7 +2333,7 @@ function extractShaderOptions(params, createCanvas) {
|
|
|
2333
2333
|
...readDuotoneColors(c1Text, c2Text, createCanvas),
|
|
2334
2334
|
blendMode: blendMap[params.text("blend", "normal")] ?? 0,
|
|
2335
2335
|
to: params.text("to", ""),
|
|
2336
|
-
progress: params.num
|
|
2336
|
+
progress: params.num("progress", -1),
|
|
2337
2337
|
// Compared against the one enabling word rather than "not `off`", so — exactly as with
|
|
2338
2338
|
// `audioBand` below — a caller passing an unvalidated accessor, or an author who typed
|
|
2339
2339
|
// `scrub: scrol`, cannot turn the bridge on by accident.
|
|
@@ -2770,7 +2770,7 @@ function restoreInstanceOpacity(el, state) {
|
|
|
2770
2770
|
if (!state.hiddenByRenderer) return;
|
|
2771
2771
|
state.hiddenByRenderer = false;
|
|
2772
2772
|
const style = styleOf(state.ledgers, el);
|
|
2773
|
-
if (style) style.set("opacity", style.peek("opacity")
|
|
2773
|
+
if (style) style.set("opacity", style.peek("opacity"));
|
|
2774
2774
|
}
|
|
2775
2775
|
var SHADER_TEXTURE_GRACE_MS = 5e3;
|
|
2776
2776
|
function acquireRenderer(info, held) {
|
|
@@ -3938,7 +3938,7 @@ function prepareCameraScene(el, params, ctx) {
|
|
|
3938
3938
|
const controller = new CameraController(htmlEl, options, resolvedEnv);
|
|
3939
3939
|
const layerEls = ownedDescendants(htmlEl, "camera-scene", "camera-layer");
|
|
3940
3940
|
for (const layer of layerEls) {
|
|
3941
|
-
const kui = layer.getAttribute("data-kui")
|
|
3941
|
+
const kui = layer.getAttribute("data-kui");
|
|
3942
3942
|
const zMatch = /z:([+-]?[0-9.]+)(?:px)?/.exec(kui);
|
|
3943
3943
|
const depthZ = zMatch ? parseDepth(zMatch[1]) : 0;
|
|
3944
3944
|
controller.addLayer(layer, depthZ);
|
|
@@ -36,6 +36,10 @@ function scopeParam(params, fallback) {
|
|
|
36
36
|
function queryScoped(el, ctx, selector, scope) {
|
|
37
37
|
return [...(scope === "page" ? ctx.doc : el).querySelectorAll(selector)];
|
|
38
38
|
}
|
|
39
|
+
function queryControls(el, ctx, selector) {
|
|
40
|
+
const inside = [...el.querySelectorAll(selector)];
|
|
41
|
+
return inside.length > 0 ? inside : [...ctx.doc.querySelectorAll(selector)];
|
|
42
|
+
}
|
|
39
43
|
|
|
40
44
|
// src/core/event-sources.ts
|
|
41
45
|
function createEventSourceBindings() {
|
|
@@ -541,18 +545,25 @@ function defaultObserverFactory() {
|
|
|
541
545
|
if (typeof IntersectionObserver === "undefined") return void 0;
|
|
542
546
|
return (callback, init) => new IntersectionObserver(callback, init);
|
|
543
547
|
}
|
|
548
|
+
function onlyBoundLate(name, claims) {
|
|
549
|
+
const authorising = authorisingActivations(name);
|
|
550
|
+
if (!authorising.includes("enter")) return false;
|
|
551
|
+
const suits = (claim) => authorising.some((named) => claim.supported.includes(named));
|
|
552
|
+
if (!claims.some((claim) => claim.entrance && suits(claim))) return false;
|
|
553
|
+
return claims.every((claim) => suits(claim) || claim.supported.includes("load"));
|
|
554
|
+
}
|
|
544
555
|
function warnAboutActivation(request) {
|
|
545
556
|
warnUnsupported(request);
|
|
546
557
|
warnUnknownEvents(request);
|
|
547
558
|
}
|
|
548
|
-
function warnUnsupported({ el, spec, supported, reporter }) {
|
|
549
|
-
|
|
559
|
+
function warnUnsupported({ el, spec, supported, claims, reporter }) {
|
|
560
|
+
const declaredAny = supported.length > 0 || (claims?.some((claim) => claim.supported.length > 0) ?? false);
|
|
561
|
+
if (!declaredAny) return;
|
|
562
|
+
const shared = supported.length > 0 ? supported.join(", ") : "none in common across the composed effects";
|
|
550
563
|
for (const name of spec.names) {
|
|
551
564
|
if (authorisingActivations(name).some((named) => supported.includes(named))) continue;
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
el
|
|
555
|
-
);
|
|
565
|
+
if (claims && onlyBoundLate(name, claims)) continue;
|
|
566
|
+
reporter.warn(`activation "${name}" is not supported by this effect (supports: ${shared})`, el);
|
|
556
567
|
}
|
|
557
568
|
}
|
|
558
569
|
function warnUnknownEvents({ el, spec, reporter }) {
|
|
@@ -615,6 +626,10 @@ var CHANNEL = {
|
|
|
615
626
|
*/
|
|
616
627
|
skew: "skew"
|
|
617
628
|
};
|
|
629
|
+
function attributeChannel(attribute) {
|
|
630
|
+
return `attr:${attribute}`;
|
|
631
|
+
}
|
|
632
|
+
var SUBTREE_CHANNEL = "subtree";
|
|
618
633
|
function inertInstance(destroy = () => {
|
|
619
634
|
}) {
|
|
620
635
|
return {
|
|
@@ -2055,6 +2070,21 @@ function emitLifecycle(el, type, detail) {
|
|
|
2055
2070
|
el.dispatchEvent(new Ctor(type, { detail, bubbles: true, composed: true }));
|
|
2056
2071
|
}
|
|
2057
2072
|
|
|
2073
|
+
// src/core/timing-contract.ts
|
|
2074
|
+
var ALL_TIMING_TOKENS = ["duration", "delay", "ease"];
|
|
2075
|
+
var CONTRACTS = /* @__PURE__ */ new WeakMap();
|
|
2076
|
+
function declareTimingContract(prepare, contract) {
|
|
2077
|
+
CONTRACTS.set(prepare, contract);
|
|
2078
|
+
return prepare;
|
|
2079
|
+
}
|
|
2080
|
+
function inheritTimingContract(inner, outer) {
|
|
2081
|
+
const contract = CONTRACTS.get(inner);
|
|
2082
|
+
return contract ? declareTimingContract(outer, contract) : outer;
|
|
2083
|
+
}
|
|
2084
|
+
function timingContractOf(primitive) {
|
|
2085
|
+
return primitive.prepare ? CONTRACTS.get(primitive.prepare) : void 0;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2058
2088
|
// src/core/params.ts
|
|
2059
2089
|
var DANGEROUS = /[;<]|\/\*|url\s*\(|expression\s*\(|@import|image-set\s*\(/i;
|
|
2060
2090
|
var ABSOLUTE_OR_PROTOCOL_RELATIVE = /^(?:[a-z][a-z0-9+.-]*:|[/\\]{2})/i;
|
|
@@ -2682,11 +2712,20 @@ function createRootResolver(options) {
|
|
|
2682
2712
|
const windowRoot = windowScrollRoot(win);
|
|
2683
2713
|
return (el) => {
|
|
2684
2714
|
for (let node = el.parentElement; node; node = node.parentElement) {
|
|
2715
|
+
if (scrollsTheViewport(node, win)) return windowRoot;
|
|
2685
2716
|
if (isScrollable(node)) return elementScrollRoot(node, win);
|
|
2686
2717
|
}
|
|
2687
2718
|
return windowRoot;
|
|
2688
2719
|
};
|
|
2689
2720
|
}
|
|
2721
|
+
function scrollsTheViewport(node, win) {
|
|
2722
|
+
const root = win.document.documentElement;
|
|
2723
|
+
if (node === root) return true;
|
|
2724
|
+
if (node !== win.document.body) return false;
|
|
2725
|
+
const rootStyle = win.getComputedStyle(root);
|
|
2726
|
+
return !CLIPPING_OVERFLOW.has(rootStyle.overflowX) && !CLIPPING_OVERFLOW.has(rootStyle.overflowY);
|
|
2727
|
+
}
|
|
2728
|
+
var CLIPPING_OVERFLOW = /* @__PURE__ */ new Set(["auto", "scroll", "overlay", "hidden", "clip"]);
|
|
2690
2729
|
var SCROLLABLE_OVERFLOW = /* @__PURE__ */ new Set(["auto", "scroll", "overlay"]);
|
|
2691
2730
|
function defaultIsScrollable(win) {
|
|
2692
2731
|
return (el) => {
|
|
@@ -2920,12 +2959,14 @@ export {
|
|
|
2920
2959
|
SCOPE_PARAM,
|
|
2921
2960
|
scopeParam,
|
|
2922
2961
|
queryScoped,
|
|
2962
|
+
queryControls,
|
|
2923
2963
|
resolveActivationSpec,
|
|
2924
2964
|
startKindOf,
|
|
2925
2965
|
isOneShot,
|
|
2926
2966
|
createActivationBinder,
|
|
2927
2967
|
warnAboutActivation,
|
|
2928
2968
|
ATTR,
|
|
2969
|
+
BREAKPOINT_NAMES,
|
|
2929
2970
|
gatedAnimationName,
|
|
2930
2971
|
gateMatches,
|
|
2931
2972
|
gatesOverlap,
|
|
@@ -2945,6 +2986,8 @@ export {
|
|
|
2945
2986
|
warnAboutToggleActions,
|
|
2946
2987
|
applyToggleVerb,
|
|
2947
2988
|
CHANNEL,
|
|
2989
|
+
attributeChannel,
|
|
2990
|
+
SUBTREE_CHANNEL,
|
|
2948
2991
|
inertInstance,
|
|
2949
2992
|
SEGMENT_HOIST_KEYS,
|
|
2950
2993
|
splitTopLevel,
|
|
@@ -2980,5 +3023,9 @@ export {
|
|
|
2980
3023
|
createCssInstance,
|
|
2981
3024
|
continuousSetup,
|
|
2982
3025
|
deferredInstance,
|
|
2983
|
-
deferPrepare
|
|
3026
|
+
deferPrepare,
|
|
3027
|
+
ALL_TIMING_TOKENS,
|
|
3028
|
+
declareTimingContract,
|
|
3029
|
+
inheritTimingContract,
|
|
3030
|
+
timingContractOf
|
|
2984
3031
|
};
|