@llui/transitions 0.0.11 → 0.0.14
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/dist/flip.js +2 -1
- package/dist/flip.js.map +1 -0
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -0
- package/dist/presets.js +3 -2
- package/dist/presets.js.map +1 -0
- package/dist/route-transition.js +4 -3
- package/dist/route-transition.js.map +1 -0
- package/dist/spring.js +2 -1
- package/dist/spring.js.map +1 -0
- package/dist/stagger.js +1 -0
- package/dist/stagger.js.map +1 -0
- package/dist/style-utils.d.ts +1 -1
- package/dist/style-utils.d.ts.map +1 -1
- package/dist/style-utils.js +1 -0
- package/dist/style-utils.js.map +1 -0
- package/dist/transition.d.ts +1 -1
- package/dist/transition.d.ts.map +1 -1
- package/dist/transition.js +2 -1
- package/dist/transition.js.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/package.json +12 -12
package/dist/flip.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asElements } from './style-utils';
|
|
1
|
+
import { asElements } from './style-utils.js';
|
|
2
2
|
/**
|
|
3
3
|
* FLIP (First-Last-Invert-Play) reorder animation for `each()` lists.
|
|
4
4
|
*
|
|
@@ -118,3 +118,4 @@ export function mergeTransitions(...parts) {
|
|
|
118
118
|
}
|
|
119
119
|
return out;
|
|
120
120
|
}
|
|
121
|
+
//# sourceMappingURL=flip.js.map
|
package/dist/flip.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flip.js","sourceRoot":"","sources":["../src/flip.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\nimport { asElements } from './style-utils.js'\n\nexport interface FlipOptions {\n duration?: number\n easing?: string\n}\n\n/**\n * FLIP (First-Last-Invert-Play) reorder animation for `each()` lists.\n *\n * Attach to an `each()` alongside item enter/leave transitions. After each\n * reconcile, items whose positions changed animate smoothly from their\n * previous position to the new one.\n *\n * ```ts\n * each({\n * items: s => s.items,\n * key: i => i.id,\n * render,\n * ...fade(), // animates appear/disappear\n * ...flip(), // animates reorders\n * })\n * ```\n *\n * Spreading two transition helpers merges their hooks: `fade()` provides\n * `enter`/`leave`, `flip()` provides `enter` (position capture) and\n * `onTransition` (apply inverse + play). The `enter` from `flip()` overrides\n * `fade()`'s only if spread after — put `flip()` last.\n *\n * Actually, to combine both, use `mergeTransitions(fade(), flip())` which\n * chains `enter` handlers.\n *\n * Requires WAAPI (`element.animate()`). In environments without it (old\n * browsers, minimal jsdom) the transforms are applied without animation.\n */\nexport function flip(opts: FlipOptions = {}): TransitionOptions {\n const duration = opts.duration ?? 300\n const easing = opts.easing ?? 'ease-out'\n const positions = new WeakMap<Element, DOMRect>()\n const tracked = new Set<Element>()\n\n const captureAfterFrame = (els: HTMLElement[]): void => {\n const run = (): void => {\n for (const el of els) {\n if (el.isConnected) positions.set(el, el.getBoundingClientRect())\n }\n }\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(run)\n } else {\n run()\n }\n }\n\n return {\n enter: (nodes: Node[]) => {\n const els = asElements(nodes)\n for (const el of els) tracked.add(el)\n captureAfterFrame(els)\n },\n leave: (nodes: Node[]) => {\n for (const el of asElements(nodes)) tracked.delete(el)\n },\n onTransition: () => {\n // Snapshot current set (tracked may mutate during iteration).\n const current = Array.from(tracked)\n for (const el of current) {\n if (!el.isConnected) {\n tracked.delete(el)\n continue\n }\n const prev = positions.get(el)\n const next = el.getBoundingClientRect()\n if (prev && (prev.left !== next.left || prev.top !== next.top)) {\n const dx = prev.left - next.left\n const dy = prev.top - next.top\n if (typeof el.animate === 'function') {\n el.animate(\n [{ transform: `translate(${dx}px, ${dy}px)` }, { transform: 'translate(0, 0)' }],\n { duration, easing, fill: 'backwards' },\n )\n }\n }\n positions.set(el, next)\n }\n },\n }\n}\n\n/**\n * Merge multiple TransitionOptions into one, chaining their `enter`,\n * `leave`, and `onTransition` handlers in order.\n *\n * Useful for combining an item-level animation (fade/slide/...) with flip():\n *\n * ```ts\n * each({ items, key, render, ...mergeTransitions(fade(), flip()) })\n * ```\n */\nexport function mergeTransitions(...parts: TransitionOptions[]): TransitionOptions {\n const enters = parts.map((p) => p.enter).filter((f): f is NonNullable<typeof f> => !!f)\n const leaves = parts.map((p) => p.leave).filter((f): f is NonNullable<typeof f> => !!f)\n const onTs = parts.map((p) => p.onTransition).filter((f): f is NonNullable<typeof f> => !!f)\n\n const out: TransitionOptions = {}\n if (enters.length > 0) {\n out.enter = (nodes: Node[]) => {\n for (const fn of enters) void fn(nodes)\n }\n }\n if (leaves.length > 0) {\n out.leave = (nodes: Node[]) => {\n // Wait for all leaves to resolve.\n const results = leaves.map((fn) => fn(nodes))\n const promises = results.filter(\n (r): r is Promise<void> => !!r && typeof (r as Promise<void>).then === 'function',\n )\n if (promises.length === 0) return\n return Promise.all(promises).then(() => undefined)\n }\n }\n if (onTs.length > 0) {\n out.onTransition = (ctx) => {\n for (const fn of onTs) void fn(ctx)\n }\n }\n return out\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export { transition } from './transition';
|
|
2
|
-
export { fade, slide, scale, collapse } from './presets';
|
|
3
|
-
export type { FadeOptions, SlideOptions, SlideDirection, ScaleOptions, CollapseOptions, } from './presets';
|
|
4
|
-
export { spring } from './spring';
|
|
5
|
-
export type { SpringOptions } from './spring';
|
|
6
|
-
export { flip, mergeTransitions } from './flip';
|
|
7
|
-
export type { FlipOptions } from './flip';
|
|
8
|
-
export { routeTransition } from './route-transition';
|
|
9
|
-
export type { RouteTransitionOptions } from './route-transition';
|
|
10
|
-
export { stagger } from './stagger';
|
|
11
|
-
export type { StaggerOptions } from './stagger';
|
|
12
|
-
export type { TransitionSpec, TransitionValue, Styles } from './types';
|
|
1
|
+
export { transition } from './transition.js';
|
|
2
|
+
export { fade, slide, scale, collapse } from './presets.js';
|
|
3
|
+
export type { FadeOptions, SlideOptions, SlideDirection, ScaleOptions, CollapseOptions, } from './presets.js';
|
|
4
|
+
export { spring } from './spring.js';
|
|
5
|
+
export type { SpringOptions } from './spring.js';
|
|
6
|
+
export { flip, mergeTransitions } from './flip.js';
|
|
7
|
+
export type { FlipOptions } from './flip.js';
|
|
8
|
+
export { routeTransition } from './route-transition.js';
|
|
9
|
+
export type { RouteTransitionOptions } from './route-transition.js';
|
|
10
|
+
export { stagger } from './stagger.js';
|
|
11
|
+
export type { StaggerOptions } from './stagger.js';
|
|
12
|
+
export type { TransitionSpec, TransitionValue, Styles } from './types.js';
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC3D,YAAY,EACV,WAAW,EACX,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAClD,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAG5C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAGnE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGlD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
// Core primitive
|
|
2
|
-
export { transition } from './transition';
|
|
2
|
+
export { transition } from './transition.js';
|
|
3
3
|
// Presets
|
|
4
|
-
export { fade, slide, scale, collapse } from './presets';
|
|
4
|
+
export { fade, slide, scale, collapse } from './presets.js';
|
|
5
5
|
// Spring physics
|
|
6
|
-
export { spring } from './spring';
|
|
6
|
+
export { spring } from './spring.js';
|
|
7
7
|
// Reorder animation + composition
|
|
8
|
-
export { flip, mergeTransitions } from './flip';
|
|
8
|
+
export { flip, mergeTransitions } from './flip.js';
|
|
9
9
|
// Route transitions
|
|
10
|
-
export { routeTransition } from './route-transition';
|
|
10
|
+
export { routeTransition } from './route-transition.js';
|
|
11
11
|
// Stagger
|
|
12
|
-
export { stagger } from './stagger';
|
|
12
|
+
export { stagger } from './stagger.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,UAAU;AACV,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAS3D,iBAAiB;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC,kCAAkC;AAClC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAGlD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAGvD,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA","sourcesContent":["// Core primitive\nexport { transition } from './transition.js'\n\n// Presets\nexport { fade, slide, scale, collapse } from './presets.js'\nexport type {\n FadeOptions,\n SlideOptions,\n SlideDirection,\n ScaleOptions,\n CollapseOptions,\n} from './presets.js'\n\n// Spring physics\nexport { spring } from './spring.js'\nexport type { SpringOptions } from './spring.js'\n\n// Reorder animation + composition\nexport { flip, mergeTransitions } from './flip.js'\nexport type { FlipOptions } from './flip.js'\n\n// Route transitions\nexport { routeTransition } from './route-transition.js'\nexport type { RouteTransitionOptions } from './route-transition.js'\n\n// Stagger\nexport { stagger } from './stagger.js'\nexport type { StaggerOptions } from './stagger.js'\n\n// Types\nexport type { TransitionSpec, TransitionValue, Styles } from './types.js'\n"]}
|
package/dist/presets.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { transition } from './transition';
|
|
2
|
-
import { asElements, forceReflow } from './style-utils';
|
|
1
|
+
import { transition } from './transition.js';
|
|
2
|
+
import { asElements, forceReflow } from './style-utils.js';
|
|
3
3
|
export function fade(opts = {}) {
|
|
4
4
|
const duration = opts.duration ?? 200;
|
|
5
5
|
const easing = opts.easing ?? 'ease-out';
|
|
@@ -144,3 +144,4 @@ function wait(ms) {
|
|
|
144
144
|
return Promise.resolve();
|
|
145
145
|
return new Promise((resolve) => setTimeout(resolve, ms + 16));
|
|
146
146
|
}
|
|
147
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAQ1D,MAAM,UAAU,IAAI,CAAC,OAAoB,EAAE;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAA;IACxC,MAAM,MAAM,GAAW,EAAE,UAAU,EAAE,WAAW,QAAQ,MAAM,MAAM,EAAE,EAAE,CAAA;IACxE,OAAO,UAAU,CAAC;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ;QACR,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;QACzB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;QACvB,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;QACzB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;KACxB,CAAC,CAAA;AACJ,CAAC;AAgBD,MAAM,UAAU,KAAK,CAAC,OAAqB,EAAE;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAA;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAA;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAA;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,KAAK,CAAA;IAEpC,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAA;IAC3D,MAAM,MAAM,GAAW,EAAE,UAAU,EAAE,GAAG,KAAK,IAAI,QAAQ,MAAM,MAAM,EAAE,EAAE,CAAA;IAEzE,MAAM,MAAM,GAAW,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;IAC5C,MAAM,OAAO,GAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAA;IACxD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;QAClB,OAAO,CAAC,OAAO,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,OAAO,UAAU,CAAC;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ;QACR,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,MAAM;KAChB,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,SAAyB,EAAE,QAAgB;IAC9D,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,MAAM;YACT,OAAO,iBAAiB,QAAQ,KAAK,CAAA;QACvC,KAAK,IAAI;YACP,OAAO,gBAAgB,QAAQ,KAAK,CAAA;QACtC,KAAK,OAAO;YACV,OAAO,cAAc,QAAQ,QAAQ,CAAA;QACvC,KAAK,MAAM;YACT,OAAO,aAAa,QAAQ,QAAQ,CAAA;IACxC,CAAC;AACH,CAAC;AAcD,MAAM,UAAU,KAAK,CAAC,OAAqB,EAAE;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAA;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAA;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,KAAK,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAA;IAEtC,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAA;IAC3D,MAAM,MAAM,GAAW;QACrB,UAAU,EAAE,GAAG,KAAK,IAAI,QAAQ,MAAM,MAAM,EAAE;QAC9C,eAAe,EAAE,MAAM;KACxB,CAAA;IAED,MAAM,MAAM,GAAW,EAAE,SAAS,EAAE,SAAS,IAAI,GAAG,EAAE,CAAA;IACtD,MAAM,OAAO,GAAW,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA;IACjD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,OAAO,GAAG,CAAC,CAAA;QAClB,OAAO,CAAC,OAAO,GAAG,CAAC,CAAA;IACrB,CAAC;IAED,OAAO,UAAU,CAAC;QAChB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ;QACR,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,MAAM;QACjB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,MAAM;KAChB,CAAC,CAAA;AACJ,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAwB,EAAE;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,CAAA;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,UAAU,CAAA;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,KAAK,CAAA;IACpC,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAA;IAElD,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAiB,EAAE;QAChD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC9C,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAA;QAElB,6CAA6C;QAC7C,MAAM,WAAW,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAA;QACnE,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAA;QAEtB,0BAA0B;QAC1B,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAA;QACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;QAChC,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CAAA;QAEvC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACzB,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAA;QACvB,KAAK,CAAC,UAAU,GAAG,GAAG,QAAQ,IAAI,QAAQ,MAAM,MAAM,EAAE,CAAA;QACxD,WAAW,CAAC,EAAE,CAAC,CAAA;QACf,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,WAAW,IAAI,CAAA;QAEpC,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC9B,KAAK,CAAC,QAAQ,GAAG,YAAY,CAAA;YAC7B,KAAK,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAA;YAC1B,KAAK,CAAC,UAAU,GAAG,cAAc,CAAA;QACnC,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAiB,EAAE;QAChD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;QAC9C,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAE,CAAA;QAElB,MAAM,WAAW,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAA;QACnE,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAA;QACtB,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACzB,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,WAAW,IAAI,CAAA;QACpC,KAAK,CAAC,UAAU,GAAG,GAAG,QAAQ,IAAI,QAAQ,MAAM,MAAM,EAAE,CAAA;QACxD,WAAW,CAAC,EAAE,CAAC,CAAA;QACf,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAA;QAEvB,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAA;IACvB,CAAC,CAAA;IAED,MAAM,GAAG,GAAsB,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;IAClD,IAAI,MAAM,EAAE,CAAC;QACX,GAAG,CAAC,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YAC5B,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAA;QACtB,CAAC,CAAA;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,IAAI,CAAC,EAAU;IACtB,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;AAC/D,CAAC","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\nimport type { Styles } from './types.js'\nimport { transition } from './transition.js'\nimport { asElements, forceReflow } from './style-utils.js'\n\nexport interface FadeOptions {\n duration?: number\n easing?: string\n appear?: boolean\n}\n\nexport function fade(opts: FadeOptions = {}): TransitionOptions {\n const duration = opts.duration ?? 200\n const easing = opts.easing ?? 'ease-out'\n const active: Styles = { transition: `opacity ${duration}ms ${easing}` }\n return transition({\n appear: opts.appear,\n duration,\n enterActive: active,\n enterFrom: { opacity: 0 },\n enterTo: { opacity: 1 },\n leaveActive: active,\n leaveFrom: { opacity: 1 },\n leaveTo: { opacity: 0 },\n })\n}\n\nexport type SlideDirection = 'up' | 'down' | 'left' | 'right'\n\nexport interface SlideOptions {\n /** The direction the element slides IN from (default: 'down' — enters from below). */\n direction?: SlideDirection\n /** Pixel distance to slide (default: 20). */\n distance?: number\n duration?: number\n easing?: string\n /** Also animate opacity (default: true). */\n fade?: boolean\n appear?: boolean\n}\n\nexport function slide(opts: SlideOptions = {}): TransitionOptions {\n const direction = opts.direction ?? 'down'\n const distance = opts.distance ?? 20\n const duration = opts.duration ?? 250\n const easing = opts.easing ?? 'ease-out'\n const withFade = opts.fade !== false\n\n const offset = slideOffset(direction, distance)\n const props = withFade ? 'transform, opacity' : 'transform'\n const active: Styles = { transition: `${props} ${duration}ms ${easing}` }\n\n const hidden: Styles = { transform: offset }\n const visible: Styles = { transform: 'translate(0, 0)' }\n if (withFade) {\n hidden.opacity = 0\n visible.opacity = 1\n }\n\n return transition({\n appear: opts.appear,\n duration,\n enterActive: active,\n enterFrom: hidden,\n enterTo: visible,\n leaveActive: active,\n leaveFrom: visible,\n leaveTo: hidden,\n })\n}\n\nfunction slideOffset(direction: SlideDirection, distance: number): string {\n switch (direction) {\n case 'down':\n return `translate(0, -${distance}px)`\n case 'up':\n return `translate(0, ${distance}px)`\n case 'right':\n return `translate(-${distance}px, 0)`\n case 'left':\n return `translate(${distance}px, 0)`\n }\n}\n\nexport interface ScaleOptions {\n /** Starting scale factor (default: 0.95). */\n from?: number\n duration?: number\n easing?: string\n /** Also animate opacity (default: true). */\n fade?: boolean\n /** Transform origin (default: 'center'). */\n origin?: string\n appear?: boolean\n}\n\nexport function scale(opts: ScaleOptions = {}): TransitionOptions {\n const from = opts.from ?? 0.95\n const duration = opts.duration ?? 200\n const easing = opts.easing ?? 'ease-out'\n const withFade = opts.fade !== false\n const origin = opts.origin ?? 'center'\n\n const props = withFade ? 'transform, opacity' : 'transform'\n const active: Styles = {\n transition: `${props} ${duration}ms ${easing}`,\n transformOrigin: origin,\n }\n\n const hidden: Styles = { transform: `scale(${from})` }\n const visible: Styles = { transform: 'scale(1)' }\n if (withFade) {\n hidden.opacity = 0\n visible.opacity = 1\n }\n\n return transition({\n appear: opts.appear,\n duration,\n enterActive: active,\n enterFrom: hidden,\n enterTo: visible,\n leaveActive: active,\n leaveFrom: visible,\n leaveTo: hidden,\n })\n}\n\nexport interface CollapseOptions {\n /** Axis to collapse: 'y' = height, 'x' = width (default: 'y'). */\n axis?: 'x' | 'y'\n duration?: number\n easing?: string\n appear?: boolean\n}\n\n/**\n * Animate an element open/closed along the y-axis (height) or x-axis (width).\n *\n * Unlike CSS-only presets, `collapse()` measures the element's natural size\n * at runtime — the animation works regardless of content size. Only the\n * first element in each `nodes` group is animated.\n */\nexport function collapse(opts: CollapseOptions = {}): TransitionOptions {\n const axis = opts.axis ?? 'y'\n const duration = opts.duration ?? 250\n const easing = opts.easing ?? 'ease-out'\n const appear = opts.appear !== false\n const sizeProp = axis === 'y' ? 'height' : 'width'\n\n const runEnter = (nodes: Node[]): Promise<void> => {\n const els = asElements(nodes)\n if (els.length === 0) return Promise.resolve()\n const el = els[0]!\n\n // Measure natural size with content visible.\n const naturalSize = axis === 'y' ? el.scrollHeight : el.scrollWidth\n const style = el.style\n\n // Save values to restore.\n const prevOverflow = style.overflow\n const prevSize = style[sizeProp]\n const prevTransition = style.transition\n\n style.overflow = 'hidden'\n style[sizeProp] = '0px'\n style.transition = `${sizeProp} ${duration}ms ${easing}`\n forceReflow(el)\n style[sizeProp] = `${naturalSize}px`\n\n return wait(duration).then(() => {\n style.overflow = prevOverflow\n style[sizeProp] = prevSize\n style.transition = prevTransition\n })\n }\n\n const runLeave = (nodes: Node[]): Promise<void> => {\n const els = asElements(nodes)\n if (els.length === 0) return Promise.resolve()\n const el = els[0]!\n\n const naturalSize = axis === 'y' ? el.scrollHeight : el.scrollWidth\n const style = el.style\n style.overflow = 'hidden'\n style[sizeProp] = `${naturalSize}px`\n style.transition = `${sizeProp} ${duration}ms ${easing}`\n forceReflow(el)\n style[sizeProp] = '0px'\n\n return wait(duration)\n }\n\n const out: TransitionOptions = { leave: runLeave }\n if (appear) {\n out.enter = (nodes: Node[]) => {\n void runEnter(nodes)\n }\n }\n return out\n}\n\nfunction wait(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => setTimeout(resolve, ms + 16))\n}\n"]}
|
package/dist/route-transition.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { fade } from './presets';
|
|
2
|
-
import { slide } from './presets';
|
|
3
|
-
import { mergeTransitions } from './flip';
|
|
1
|
+
import { fade } from './presets.js';
|
|
2
|
+
import { slide } from './presets.js';
|
|
3
|
+
import { mergeTransitions } from './flip.js';
|
|
4
4
|
/**
|
|
5
5
|
* Convenience wrapper that returns `{ enter, leave }` hooks suitable for
|
|
6
6
|
* spreading into a `branch()` call to animate page transitions.
|
|
@@ -39,3 +39,4 @@ export function routeTransition(opts) {
|
|
|
39
39
|
});
|
|
40
40
|
return mergeTransitions(fadeT, slideT);
|
|
41
41
|
}
|
|
42
|
+
//# sourceMappingURL=route-transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-transition.js","sourceRoot":"","sources":["../src/route-transition.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAa5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAiD;IAEjD,8EAA8E;IAC9E,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC,EAAE,CAAC;QACjD,OAAO,IAAyB,CAAA;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,IAAI,IAAI,EAAE,CAA2B,CAAA;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAA;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,UAAU,CAAA;IAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,KAAK,KAAK,CAAA;IACxC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,EAAE,CAAA;IAEhD,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAA;IAExC,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAA;IAE5B,MAAM,MAAM,GAAG,KAAK,CAAC;QACnB,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,aAAa;QACvB,QAAQ;QACR,MAAM;QACN,IAAI,EAAE,KAAK;KACZ,CAAC,CAAA;IAEF,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;AACxC,CAAC","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\nimport { fade } from './presets.js'\nimport { slide } from './presets.js'\nimport { mergeTransitions } from './flip.js'\n\nexport interface RouteTransitionOptions {\n /** Duration in milliseconds (default: 250). */\n duration?: number\n /** Easing function (default: 'ease-out'). */\n easing?: string\n /** Enable a slight vertical slide alongside the fade (default: true). */\n slide?: boolean\n /** Slide distance in pixels (default: 12). */\n slideDistance?: number\n}\n\n/**\n * Convenience wrapper that returns `{ enter, leave }` hooks suitable for\n * spreading into a `branch()` call to animate page transitions.\n *\n * Can be called two ways:\n *\n * 1. With route-specific options (produces a fade + optional slide):\n * ```ts\n * branch({ on, cases, ...routeTransition({ duration: 200 }) })\n * ```\n *\n * 2. With a pre-built `TransitionOptions` (e.g. from any preset):\n * ```ts\n * branch({ on, cases, ...routeTransition(fade({ duration: 200 })) })\n * ```\n */\nexport function routeTransition(\n opts?: RouteTransitionOptions | TransitionOptions,\n): TransitionOptions {\n // If opts already has enter/leave, treat it as a pre-built TransitionOptions.\n if (opts && ('enter' in opts || 'leave' in opts)) {\n return opts as TransitionOptions\n }\n\n const config = (opts ?? {}) as RouteTransitionOptions\n const duration = config.duration ?? 250\n const easing = config.easing ?? 'ease-out'\n const withSlide = config.slide !== false\n const slideDistance = config.slideDistance ?? 12\n\n const fadeT = fade({ duration, easing })\n\n if (!withSlide) return fadeT\n\n const slideT = slide({\n direction: 'up',\n distance: slideDistance,\n duration,\n easing,\n fade: false,\n })\n\n return mergeTransitions(fadeT, slideT)\n}\n"]}
|
package/dist/spring.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asElements } from './style-utils';
|
|
1
|
+
import { asElements } from './style-utils.js';
|
|
2
2
|
function simulateSpring(state, target, stiffness, damping, mass, dt) {
|
|
3
3
|
const acceleration = (-stiffness * (state.position - target) - damping * state.velocity) / mass;
|
|
4
4
|
state.velocity += acceleration * dt;
|
|
@@ -68,3 +68,4 @@ export function spring(opts = {}) {
|
|
|
68
68
|
};
|
|
69
69
|
return { enter, leave };
|
|
70
70
|
}
|
|
71
|
+
//# sourceMappingURL=spring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spring.js","sourceRoot":"","sources":["../src/spring.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\nimport { asElements } from './style-utils.js'\n\nexport interface SpringOptions {\n /** Spring stiffness (default: 170). */\n stiffness?: number\n /** Damping coefficient (default: 26). */\n damping?: number\n /** Mass (default: 1). */\n mass?: number\n /** Stop threshold for velocity and position (default: 0.01). */\n precision?: number\n /** CSS property to animate (default: 'opacity'). */\n property?: string\n /** Start value (default: 0). */\n from?: number\n /** End value (default: 1). */\n to?: number\n}\n\ninterface SpringState {\n position: number\n velocity: number\n}\n\nfunction simulateSpring(\n state: SpringState,\n target: number,\n stiffness: number,\n damping: number,\n mass: number,\n dt: number,\n): void {\n const acceleration = (-stiffness * (state.position - target) - damping * state.velocity) / mass\n state.velocity += acceleration * dt\n state.position += state.velocity * dt\n}\n\nfunction isSettled(state: SpringState, target: number, precision: number): boolean {\n return Math.abs(state.velocity) < precision && Math.abs(state.position - target) < precision\n}\n\nfunction animateSpring(\n els: HTMLElement[],\n from: number,\n to: number,\n property: string,\n stiffness: number,\n damping: number,\n mass: number,\n precision: number,\n): Promise<void> {\n if (els.length === 0) return Promise.resolve()\n\n return new Promise<void>((resolve) => {\n const state: SpringState = { position: from, velocity: 0 }\n let lastTime: number | null = null\n\n function step(time: number) {\n if (lastTime === null) {\n lastTime = time\n }\n\n // dt in seconds, clamped to avoid spiral on tab-switch\n const dt = Math.min((time - lastTime) / 1000, 0.064)\n lastTime = time\n\n simulateSpring(state, to, stiffness, damping, mass, dt)\n\n for (const el of els) {\n el.style.setProperty(property, String(state.position))\n }\n\n if (isSettled(state, to, precision)) {\n // Snap to exact target\n for (const el of els) {\n el.style.setProperty(property, String(to))\n }\n resolve()\n return\n }\n\n requestAnimationFrame(step)\n }\n\n // Apply initial value\n for (const el of els) {\n el.style.setProperty(property, String(from))\n }\n\n requestAnimationFrame(step)\n })\n}\n\n/**\n * Spring-physics transition. Returns `{ enter, leave }` that animate a CSS\n * property using a damped spring simulation driven by `requestAnimationFrame`.\n *\n * ```ts\n * show({ when: (s) => s.open, render: () => content(), ...spring() })\n * show({ ...spring({ property: 'transform', from: 0, to: 1 }) })\n * ```\n */\nexport function spring(opts: SpringOptions = {}): TransitionOptions {\n const stiffness = opts.stiffness ?? 170\n const damping = opts.damping ?? 26\n const mass = opts.mass ?? 1\n const precision = opts.precision ?? 0.01\n const property = opts.property ?? 'opacity'\n const from = opts.from ?? 0\n const to = opts.to ?? 1\n\n const enter = (nodes: Node[]): void => {\n const els = asElements(nodes)\n void animateSpring(els, from, to, property, stiffness, damping, mass, precision)\n }\n\n const leave = (nodes: Node[]): Promise<void> => {\n const els = asElements(nodes)\n return animateSpring(els, to, from, property, stiffness, damping, mass, precision)\n }\n\n return { enter, leave }\n}\n"]}
|
package/dist/stagger.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stagger.js","sourceRoot":"","sources":["../src/stagger.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,OAAO,CAAC,IAAuB,EAAE,IAAqB;IACpE,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,EAAE,CAAA;IAC7C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,cAAc,CAAA;IAErD,kEAAkE;IAClE,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,mBAAmB,GAAG,KAAK,CAAA;IAE/B,SAAS,eAAe;QACtB,UAAU,GAAG,CAAC,CAAA;QACd,mBAAmB,GAAG,KAAK,CAAA;IAC7B,CAAC;IAED,iEAAiE;IACjE,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,mBAAmB,GAAG,KAAK,CAAA;IAC/B,IAAI,cAAc,GAAG,CAAC,CAAA;IAEtB,SAAS,eAAe;QACtB,UAAU,GAAG,CAAC,CAAA;QACd,cAAc,GAAG,CAAC,CAAA;QAClB,mBAAmB,GAAG,KAAK,CAAA;IAC7B,CAAC;IAED,MAAM,GAAG,GAAsB,EAAE,CAAA;IAEjC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAA;QAC5B,GAAG,CAAC,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YAC5B,MAAM,GAAG,GAAG,UAAU,EAAE,CAAA;YACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,mBAAmB,GAAG,IAAI,CAAA;gBAC1B,cAAc,CAAC,eAAe,CAAC,CAAA;YACjC,CAAC;YACD,MAAM,KAAK,GAAG,GAAG,GAAG,YAAY,CAAA;YAChC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;YACzB,CAAC;YACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,UAAU,CAAC,GAAG,EAAE;oBACd,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;oBAC/B,IAAI,MAAM,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBACnE,CAAC;wBAAC,MAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBACnD,CAAC;yBAAM,CAAC;wBACN,OAAO,EAAE,CAAA;oBACX,CAAC;gBACH,CAAC,EAAE,KAAK,CAAC,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;IACH,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAA;QAC5B,GAAG,CAAC,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;YAC5B,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;gBAClC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;YACzB,CAAC;YAED,MAAM,GAAG,GAAG,UAAU,EAAE,CAAA;YACxB,cAAc,GAAG,UAAU,CAAA;YAC3B,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,mBAAmB,GAAG,IAAI,CAAA;gBAC1B,cAAc,CAAC,eAAe,CAAC,CAAA;YACjC,CAAC;YAED,2EAA2E;YAC3E,uEAAuE;YACvE,wEAAwE;YACxE,mEAAmE;YACnE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC7B,MAAM,WAAW,GAAG,GAAG,CAAA;gBACvB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBACnC,2EAA2E;oBAC3E,cAAc,CAAC,GAAG,EAAE;wBAClB,MAAM,UAAU,GAAG,cAAc,GAAG,CAAC,GAAG,WAAW,CAAA;wBACnD,MAAM,KAAK,GAAG,UAAU,GAAG,YAAY,CAAA;wBACvC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;4BAChB,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;4BAC/B,IAAI,MAAM,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gCACnE,CAAC;gCAAC,MAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;4BACnD,CAAC;iCAAM,CAAC;gCACN,OAAO,EAAE,CAAA;4BACX,CAAC;wBACH,CAAC;6BAAM,CAAC;4BACN,UAAU,CAAC,GAAG,EAAE;gCACd,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;gCAC/B,IAAI,MAAM,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oCACnE,CAAC;oCAAC,MAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;gCACnD,CAAC;qCAAM,CAAC;oCACN,OAAO,EAAE,CAAA;gCACX,CAAC;4BACH,CAAC,EAAE,KAAK,CAAC,CAAA;wBACX,CAAC;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC,CAAC,CAAA;YACJ,CAAC;YAED,aAAa;YACb,MAAM,KAAK,GAAG,GAAG,GAAG,YAAY,CAAA;YAChC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;gBAChB,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;YACzB,CAAC;YACD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACnC,UAAU,CAAC,GAAG,EAAE;oBACd,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;oBAC/B,IAAI,MAAM,IAAI,OAAQ,MAAwB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBACnE,CAAC;wBAAC,MAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;oBACnD,CAAC;yBAAM,CAAC;wBACN,OAAO,EAAE,CAAA;oBACX,CAAC;gBACH,CAAC,EAAE,KAAK,CAAC,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;IACH,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAA;IACtC,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\n\nexport interface StaggerOptions {\n /** Delay between each item in milliseconds (default: 30). */\n delayPerItem?: number\n /** How to stagger leave animations: 'sequential' (same order as enter),\n * 'reverse', or 'simultaneous' (no stagger). Default: 'simultaneous'. */\n leaveOrder?: 'sequential' | 'reverse' | 'simultaneous'\n}\n\n/**\n * Wrap any transition preset so that batch-entered items get staggered delays.\n *\n * Items entering within the same microtask are considered a \"batch\" and get\n * sequential delays (`index * delayPerItem`). The counter resets after the\n * microtask, so the next batch starts from 0.\n *\n * ```ts\n * each({\n * items: s => s.items,\n * key: i => i.id,\n * render: ({ item }) => [...],\n * ...stagger(fade({ duration: 150 }), { delayPerItem: 30 }),\n * })\n * ```\n */\nexport function stagger(spec: TransitionOptions, opts?: StaggerOptions): TransitionOptions {\n const delayPerItem = opts?.delayPerItem ?? 30\n const leaveOrder = opts?.leaveOrder ?? 'simultaneous'\n\n // ── Enter stagger ──────────────────────────────────────────────\n let enterIndex = 0\n let enterResetScheduled = false\n\n function resetEnterIndex(): void {\n enterIndex = 0\n enterResetScheduled = false\n }\n\n // ── Leave stagger ─────────────────────────────────────────────\n let leaveIndex = 0\n let leaveResetScheduled = false\n let leaveBatchSize = 0\n\n function resetLeaveIndex(): void {\n leaveIndex = 0\n leaveBatchSize = 0\n leaveResetScheduled = false\n }\n\n const out: TransitionOptions = {}\n\n if (spec.enter) {\n const baseEnter = spec.enter\n out.enter = (nodes: Node[]) => {\n const idx = enterIndex++\n if (!enterResetScheduled) {\n enterResetScheduled = true\n queueMicrotask(resetEnterIndex)\n }\n const delay = idx * delayPerItem\n if (delay === 0) {\n return baseEnter(nodes)\n }\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n const result = baseEnter(nodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(resolve, resolve)\n } else {\n resolve()\n }\n }, delay)\n })\n }\n }\n\n if (spec.leave) {\n const baseLeave = spec.leave\n out.leave = (nodes: Node[]) => {\n if (leaveOrder === 'simultaneous') {\n return baseLeave(nodes)\n }\n\n const idx = leaveIndex++\n leaveBatchSize = leaveIndex\n if (!leaveResetScheduled) {\n leaveResetScheduled = true\n queueMicrotask(resetLeaveIndex)\n }\n\n // For reverse order, compute delay after all items in the batch are known.\n // Since we can't know the batch size ahead of time, we use a microtask\n // to capture it, but the delay must be applied now. For reverse, we use\n // a deferred approach: schedule the animation after the microtask.\n if (leaveOrder === 'reverse') {\n const capturedIdx = idx\n return new Promise<void>((resolve) => {\n // Wait for microtask to know batch size, then schedule with reverse delay.\n queueMicrotask(() => {\n const reverseIdx = leaveBatchSize - 1 - capturedIdx\n const delay = reverseIdx * delayPerItem\n if (delay === 0) {\n const result = baseLeave(nodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(resolve, resolve)\n } else {\n resolve()\n }\n } else {\n setTimeout(() => {\n const result = baseLeave(nodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(resolve, resolve)\n } else {\n resolve()\n }\n }, delay)\n }\n })\n })\n }\n\n // sequential\n const delay = idx * delayPerItem\n if (delay === 0) {\n return baseLeave(nodes)\n }\n return new Promise<void>((resolve) => {\n setTimeout(() => {\n const result = baseLeave(nodes)\n if (result && typeof (result as Promise<void>).then === 'function') {\n ;(result as Promise<void>).then(resolve, resolve)\n } else {\n resolve()\n }\n }, delay)\n })\n }\n }\n\n if (spec.onTransition) {\n out.onTransition = spec.onTransition\n }\n\n return out\n}\n"]}
|
package/dist/style-utils.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-utils.d.ts","sourceRoot":"","sources":["../src/style-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"style-utils.d.ts","sourceRoot":"","sources":["../src/style-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,YAAY,CAAA;AA0CzD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,CAMvD;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAcpF;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAcrF;AA0BD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAKtD;AAiBD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAGjD"}
|
package/dist/style-utils.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"style-utils.js","sourceRoot":"","sources":["../src/style-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Styles, TransitionValue } from './types.js'\n\n// CSS properties that are unitless when given a numeric value.\n// All other numeric values are suffixed with `px`.\nconst UNITLESS = new Set([\n 'opacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'flexNegative',\n 'order',\n 'zIndex',\n 'fontWeight',\n 'lineHeight',\n 'zoom',\n 'gridRow',\n 'gridRowStart',\n 'gridRowEnd',\n 'gridColumn',\n 'gridColumnStart',\n 'gridColumnEnd',\n 'columnCount',\n 'tabSize',\n 'scale',\n 'aspectRatio',\n])\n\nfunction formatStyleValue(prop: string, value: string | number): string {\n if (typeof value === 'string') return value\n if (UNITLESS.has(prop)) return String(value)\n return `${value}px`\n}\n\nfunction splitClasses(raw: string): string[] {\n const out: string[] = []\n const parts = raw.split(/\\s+/)\n for (const p of parts) {\n if (p.length > 0) out.push(p)\n }\n return out\n}\n\n/**\n * Filter an array of nodes down to HTMLElements — transition animations\n * only apply to elements, not comment anchors or text nodes.\n */\nexport function asElements(nodes: Node[]): HTMLElement[] {\n const out: HTMLElement[] = []\n for (const n of nodes) {\n if (n.nodeType === 1) out.push(n as HTMLElement)\n }\n return out\n}\n\n/** Apply a TransitionValue (classes, styles, or a mix) to an element. */\nexport function applyValue(el: HTMLElement, value: TransitionValue | undefined): void {\n if (value == null) return\n if (typeof value === 'string') {\n applyClasses(el, value)\n return\n }\n if (Array.isArray(value)) {\n for (const part of value) {\n if (typeof part === 'string') applyClasses(el, part)\n else applyStyles(el, part)\n }\n return\n }\n applyStyles(el, value)\n}\n\n/** Remove a TransitionValue from an element. */\nexport function removeValue(el: HTMLElement, value: TransitionValue | undefined): void {\n if (value == null) return\n if (typeof value === 'string') {\n removeClasses(el, value)\n return\n }\n if (Array.isArray(value)) {\n for (const part of value) {\n if (typeof part === 'string') removeClasses(el, part)\n else removeStyles(el, part)\n }\n return\n }\n removeStyles(el, value)\n}\n\nfunction applyClasses(el: HTMLElement, raw: string): void {\n const classes = splitClasses(raw)\n if (classes.length > 0) el.classList.add(...classes)\n}\n\nfunction removeClasses(el: HTMLElement, raw: string): void {\n const classes = splitClasses(raw)\n if (classes.length > 0) el.classList.remove(...classes)\n}\n\nfunction applyStyles(el: HTMLElement, styles: Styles): void {\n const decl = el.style as unknown as Record<string, string>\n for (const key in styles) {\n decl[key] = formatStyleValue(key, styles[key]!)\n }\n}\n\nfunction removeStyles(el: HTMLElement, styles: Styles): void {\n const decl = el.style as unknown as Record<string, string>\n for (const key in styles) {\n decl[key] = ''\n }\n}\n\n/**\n * Detect total transition duration from computed styles.\n * Returns the maximum of (transition-duration + transition-delay) and\n * (animation-duration + animation-delay), in milliseconds.\n */\nexport function detectDuration(el: HTMLElement): number {\n const cs = getComputedStyle(el)\n const t = parseTime(cs.transitionDuration) + parseTime(cs.transitionDelay)\n const a = parseTime(cs.animationDuration) + parseTime(cs.animationDelay)\n return Math.max(t, a)\n}\n\nfunction parseTime(raw: string): number {\n if (!raw) return 0\n let max = 0\n const parts = raw.split(',')\n for (const part of parts) {\n const trimmed = part.trim()\n const m = trimmed.match(/^([\\d.]+)(m?s)$/)\n if (!m) continue\n const n = parseFloat(m[1]!)\n const ms = m[2] === 's' ? n * 1000 : n\n if (ms > max) max = ms\n }\n return max\n}\n\n/** Force a style recalculation so subsequent class/style changes animate. */\nexport function forceReflow(el: HTMLElement): void {\n // Reading an offset property forces synchronous layout.\n void el.offsetHeight\n}\n"]}
|
package/dist/transition.d.ts
CHANGED
package/dist/transition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition.d.ts","sourceRoot":"","sources":["../src/transition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"transition.d.ts","sourceRoot":"","sources":["../src/transition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAMhD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,iBAAiB,CA+DlE"}
|
package/dist/transition.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyValue, removeValue, asElements, detectDuration, forceReflow } from './style-utils';
|
|
1
|
+
import { applyValue, removeValue, asElements, detectDuration, forceReflow } from './style-utils.js';
|
|
2
2
|
// Buffer added to setTimeout so styles have settled before resolution.
|
|
3
3
|
const TIMING_BUFFER_MS = 16;
|
|
4
4
|
/**
|
|
@@ -77,3 +77,4 @@ function wait(ms) {
|
|
|
77
77
|
setTimeout(resolve, ms + TIMING_BUFFER_MS);
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
|
+
//# sourceMappingURL=transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition.js","sourceRoot":"","sources":["../src/transition.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TransitionOptions } from '@llui/dom'\nimport type { TransitionSpec } from './types.js'\nimport { applyValue, removeValue, asElements, detectDuration, forceReflow } from './style-utils.js'\n\n// Buffer added to setTimeout so styles have settled before resolution.\nconst TIMING_BUFFER_MS = 16\n\n/**\n * Build a `TransitionOptions` bundle ({ enter, leave }) from a spec.\n *\n * Pass the result into `branch`, `show`, or `each` to animate the enter/leave\n * of that structural block.\n *\n * Lifecycle:\n * - **enter**: apply `enterFrom` + `enterActive` → reflow → swap `enterFrom` → `enterTo`\n * → wait for duration → remove all transient values (element rests on its base styles).\n * - **leave**: apply `leaveFrom` + `leaveActive` → reflow → swap `leaveFrom` → `leaveTo`\n * → wait for duration (Promise-resolved so DOM removal is deferred).\n *\n * Duration:\n * - If `duration` is given, it is used verbatim.\n * - Otherwise, computed `transition-duration + transition-delay` is read after\n * the active/from classes are applied, taking the max across properties.\n */\nexport function transition(spec: TransitionSpec): TransitionOptions {\n const appear = spec.appear !== false\n\n const runEnter = (nodes: Node[]): Promise<void> => {\n const els = asElements(nodes)\n if (els.length === 0) return Promise.resolve()\n\n // Apply from + active\n for (const el of els) {\n applyValue(el, spec.enterFrom)\n applyValue(el, spec.enterActive)\n }\n\n // Force reflow so the next class change triggers a transition.\n forceReflow(els[0]!)\n\n // Move to target state\n for (const el of els) {\n removeValue(el, spec.enterFrom)\n applyValue(el, spec.enterTo)\n }\n\n const duration = spec.duration ?? detectDuration(els[0]!)\n\n return wait(duration).then(() => {\n for (const el of els) {\n removeValue(el, spec.enterActive)\n removeValue(el, spec.enterTo)\n }\n })\n }\n\n const runLeave = (nodes: Node[]): Promise<void> => {\n const els = asElements(nodes)\n if (els.length === 0) return Promise.resolve()\n\n for (const el of els) {\n applyValue(el, spec.leaveFrom)\n applyValue(el, spec.leaveActive)\n }\n\n forceReflow(els[0]!)\n\n for (const el of els) {\n removeValue(el, spec.leaveFrom)\n applyValue(el, spec.leaveTo)\n }\n\n const duration = spec.duration ?? detectDuration(els[0]!)\n return wait(duration)\n }\n\n const out: TransitionOptions = {\n leave: runLeave,\n }\n\n if (appear) {\n out.enter = (nodes: Node[]) => {\n void runEnter(nodes)\n }\n }\n\n return out\n}\n\nfunction wait(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve()\n return new Promise((resolve) => {\n setTimeout(resolve, ms + TIMING_BUFFER_MS)\n })\n}\n"]}
|
package/dist/types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * CSS style properties as a plain object. Numeric values are automatically\n * suffixed with `px` for known dimensional properties.\n *\n * Example: `{ opacity: 0, transform: 'scale(0.95)', width: 200 }`\n */\nexport type Styles = Record<string, string | number>\n\n/**\n * One \"state\" in a transition.\n *\n * - `string` — space-separated class names (applied via classList)\n * - `Styles` — inline style object (applied via element.style)\n * - `Array<string | Styles>` — mix both (useful for utility classes + dynamic styles)\n */\nexport type TransitionValue = string | Styles | Array<string | Styles>\n\nexport interface TransitionSpec {\n /** Initial state before enter animation (removed once enter completes). */\n enterFrom?: TransitionValue\n /** Final state during enter animation (removed once enter completes). */\n enterTo?: TransitionValue\n /** Applied throughout enter (typically the `transition-*` / `animation` properties). */\n enterActive?: TransitionValue\n /** Initial state before leave animation. */\n leaveFrom?: TransitionValue\n /** Final state during leave animation. */\n leaveTo?: TransitionValue\n /** Applied throughout leave. */\n leaveActive?: TransitionValue\n /**\n * Explicit duration in milliseconds. When omitted, the duration is read from\n * the element's computed `transition-duration` / `transition-delay` after the\n * active classes are applied.\n */\n duration?: number\n /** If true, run the enter transition on initial mount (default: true). */\n appear?: boolean\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llui/transitions",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,19 +10,13 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts"
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsc -p tsconfig.build.json",
|
|
15
|
-
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
16
|
-
"lint": "eslint src",
|
|
17
|
-
"test": "vitest run"
|
|
18
|
-
},
|
|
19
13
|
"peerDependencies": {
|
|
20
|
-
"@llui/dom": "^0.0.
|
|
14
|
+
"@llui/dom": "^0.0.14"
|
|
21
15
|
},
|
|
22
16
|
"devDependencies": {
|
|
23
|
-
"@llui/dom": "workspace:*",
|
|
24
17
|
"typescript": "^6.0.0",
|
|
25
|
-
"vitest": "^4.1.2"
|
|
18
|
+
"vitest": "^4.1.2",
|
|
19
|
+
"@llui/dom": "0.0.14"
|
|
26
20
|
},
|
|
27
21
|
"sideEffects": false,
|
|
28
22
|
"description": "LLui animation helpers — transition(), fade, slide, scale, collapse for branch/show/each",
|
|
@@ -46,5 +40,11 @@
|
|
|
46
40
|
"homepage": "https://github.com/fponticelli/llui/tree/main/packages/transitions#readme",
|
|
47
41
|
"files": [
|
|
48
42
|
"dist"
|
|
49
|
-
]
|
|
50
|
-
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc -p tsconfig.build.json",
|
|
46
|
+
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
47
|
+
"lint": "eslint src",
|
|
48
|
+
"test": "vitest run"
|
|
49
|
+
}
|
|
50
|
+
}
|