@enact-ui/animate 1.0.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.
@@ -0,0 +1,53 @@
1
+ import { type MotionPreset } from "../presets/motion-presets";
2
+ /** Computed motion configuration for paths component */
3
+ export interface ComputedPathsMotion {
4
+ /** Computed base duration (preset * CSS multiplier) */
5
+ baseDuration: number;
6
+ /** Computed opacity keyframes respecting CSS bounds */
7
+ opacity: [number, number, number];
8
+ /** Easing function from preset */
9
+ ease: "linear" | "easeInOut";
10
+ /** Delay variation factor from preset */
11
+ delayVariation: number;
12
+ /** Duration variation factor from preset */
13
+ durationVariation: number;
14
+ /** Whether reduced motion is preferred */
15
+ prefersReducedMotion: boolean;
16
+ }
17
+ /** Computed motion configuration for rays component */
18
+ export interface ComputedRaysMotion {
19
+ /** Computed cycle duration (preset speed * CSS multiplier) */
20
+ cycleDuration: number;
21
+ /** Base intensity from preset */
22
+ intensity: number;
23
+ /** Swing variation from preset */
24
+ swingVariation: number;
25
+ /** Whether reduced motion is preferred */
26
+ prefersReducedMotion: boolean;
27
+ }
28
+ /**
29
+ * Hook for using motion presets with theme-aware CSS variables.
30
+ *
31
+ * Provides computed motion configuration that:
32
+ * - Respects `prefers-reduced-motion` preference
33
+ * - Reads and applies CSS motion variables from the theme
34
+ * - Memoizes calculations to prevent unnecessary re-renders
35
+ *
36
+ * @param component - The component type ("paths" | "rays")
37
+ * @param preset - The motion preset ("slow" | "medium" | "fast")
38
+ * @returns Computed motion configuration for the component
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * // In BackgroundPaths component
43
+ * const motion = useMotionPreset("paths", "medium");
44
+ * // Returns: { baseDuration: 20, opacity: [...], ... }
45
+ *
46
+ * // In LightRays component
47
+ * const motion = useMotionPreset("rays", "fast");
48
+ * // Returns: { cycleDuration: 8, intensity: 0.7, ... }
49
+ * ```
50
+ */
51
+ export declare function useMotionPreset(component: "paths", preset: MotionPreset): ComputedPathsMotion;
52
+ export declare function useMotionPreset(component: "rays", preset: MotionPreset): ComputedRaysMotion;
53
+ //# sourceMappingURL=use-motion-preset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-motion-preset.d.ts","sourceRoot":"","sources":["../../src/hooks/use-motion-preset.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgF,KAAK,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAY5I,wDAAwD;AACxD,MAAM,WAAW,mBAAmB;IAChC,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,kCAAkC;IAClC,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,yCAAyC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,oBAAoB,EAAE,OAAO,CAAC;CACjC;AAED,uDAAuD;AACvD,MAAM,WAAW,kBAAkB;IAC/B,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,oBAAoB,EAAE,OAAO,CAAC;CACjC;AAmFD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,mBAAmB,CAAC;AAC/F,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,kBAAkB,CAAC"}
@@ -0,0 +1,117 @@
1
+ // Copyright (c) 2025 Amsterdam Data Labs
2
+ "use client";
3
+ import { useEffect, useMemo, useState } from "react";
4
+ import { getPreset } from "../presets/motion-presets";
5
+ /** Default CSS variable values (fallback if not in browser) */
6
+ const DEFAULT_CSS_VARS = {
7
+ durationMultiplier: 1,
8
+ opacityMin: 0.35,
9
+ opacityMax: 0.6,
10
+ };
11
+ /**
12
+ * Reads motion CSS variables from the document root.
13
+ * Returns default values if not in browser environment.
14
+ */
15
+ function readCSSVariables() {
16
+ if (typeof window === "undefined") {
17
+ return DEFAULT_CSS_VARS;
18
+ }
19
+ const root = document.documentElement;
20
+ const styles = getComputedStyle(root);
21
+ const parseFloat_ = (value, fallback) => {
22
+ const parsed = parseFloat(value);
23
+ return Number.isNaN(parsed) ? fallback : parsed;
24
+ };
25
+ return {
26
+ durationMultiplier: parseFloat_(styles.getPropertyValue("--motion-duration-multiplier"), DEFAULT_CSS_VARS.durationMultiplier),
27
+ opacityMin: parseFloat_(styles.getPropertyValue("--motion-opacity-min"), DEFAULT_CSS_VARS.opacityMin),
28
+ opacityMax: parseFloat_(styles.getPropertyValue("--motion-opacity-max"), DEFAULT_CSS_VARS.opacityMax),
29
+ };
30
+ }
31
+ /**
32
+ * Computes paths motion configuration from preset and CSS variables.
33
+ */
34
+ function computePathsMotion(preset, cssVars, prefersReducedMotion) {
35
+ if (prefersReducedMotion) {
36
+ return {
37
+ baseDuration: 0,
38
+ opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],
39
+ ease: preset.ease,
40
+ delayVariation: 0,
41
+ durationVariation: 0,
42
+ prefersReducedMotion: true,
43
+ };
44
+ }
45
+ return {
46
+ baseDuration: preset.duration * cssVars.durationMultiplier,
47
+ opacity: [
48
+ Math.max(preset.opacity[0], cssVars.opacityMin),
49
+ Math.min(preset.opacity[1], cssVars.opacityMax),
50
+ Math.max(preset.opacity[2], cssVars.opacityMin),
51
+ ],
52
+ ease: preset.ease,
53
+ delayVariation: preset.delayVariation,
54
+ durationVariation: preset.durationVariation,
55
+ prefersReducedMotion: false,
56
+ };
57
+ }
58
+ /**
59
+ * Computes rays motion configuration from preset and CSS variables.
60
+ */
61
+ function computeRaysMotion(preset, cssVars, prefersReducedMotion) {
62
+ if (prefersReducedMotion) {
63
+ return {
64
+ cycleDuration: 0,
65
+ intensity: 0,
66
+ swingVariation: 0,
67
+ prefersReducedMotion: true,
68
+ };
69
+ }
70
+ return {
71
+ cycleDuration: Math.max(preset.speed * cssVars.durationMultiplier, 0.1),
72
+ intensity: preset.intensity,
73
+ swingVariation: preset.swingVariation,
74
+ prefersReducedMotion: false,
75
+ };
76
+ }
77
+ export function useMotionPreset(component, preset) {
78
+ // Track reduced motion preference with state for reactivity
79
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {
80
+ if (typeof window === "undefined")
81
+ return false;
82
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
83
+ });
84
+ // Track CSS variables (may change with theme)
85
+ const [cssVars, setCssVars] = useState(DEFAULT_CSS_VARS);
86
+ // Listen for reduced motion preference changes
87
+ useEffect(() => {
88
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
89
+ setPrefersReducedMotion(mediaQuery.matches);
90
+ const handler = (e) => setPrefersReducedMotion(e.matches);
91
+ mediaQuery.addEventListener("change", handler);
92
+ return () => mediaQuery.removeEventListener("change", handler);
93
+ }, []);
94
+ // Read CSS variables on mount and when theme might change
95
+ useEffect(() => {
96
+ setCssVars(readCSSVariables());
97
+ // Listen for theme changes via attribute mutations on document
98
+ const observer = new MutationObserver(() => {
99
+ setCssVars(readCSSVariables());
100
+ });
101
+ observer.observe(document.documentElement, {
102
+ attributes: true,
103
+ attributeFilter: ["class", "data-theme"],
104
+ });
105
+ return () => observer.disconnect();
106
+ }, []);
107
+ // Compute and memoize the motion configuration
108
+ return useMemo(() => {
109
+ if (component === "paths") {
110
+ const presetConfig = getPreset(preset, "paths");
111
+ return computePathsMotion(presetConfig, cssVars, prefersReducedMotion);
112
+ }
113
+ const presetConfig = getPreset(preset, "rays");
114
+ return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);
115
+ }, [component, preset, cssVars, prefersReducedMotion]);
116
+ }
117
+ //# sourceMappingURL=use-motion-preset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-motion-preset.js","sourceRoot":"","sources":["../../src/hooks/use-motion-preset.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAA+C,SAAS,EAA2C,MAAM,2BAA2B,CAAC;AAwC5I,+DAA+D;AAC/D,MAAM,gBAAgB,GAAuB;IACzC,kBAAkB,EAAE,CAAC;IACrB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,GAAG;CAClB,CAAC;AAEF;;;GAGG;AACH,SAAS,gBAAgB;IACrB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;IACtC,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAEtC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,QAAgB,EAAU,EAAE;QAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IACpD,CAAC,CAAC;IAEF,OAAO;QACH,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC,8BAA8B,CAAC,EAAE,gBAAgB,CAAC,kBAAkB,CAAC;QAC7H,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,gBAAgB,CAAC,UAAU,CAAC;QACrG,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,EAAE,gBAAgB,CAAC,UAAU,CAAC;KACxG,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,MAA0B,EAAE,OAA2B,EAAE,oBAA6B;IAC9G,IAAI,oBAAoB,EAAE,CAAC;QACvB,OAAO;YACH,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC;YACrE,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,cAAc,EAAE,CAAC;YACjB,iBAAiB,EAAE,CAAC;YACpB,oBAAoB,EAAE,IAAI;SAC7B,CAAC;IACN,CAAC;IAED,OAAO;QACH,YAAY,EAAE,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,kBAAkB;QAC1D,OAAO,EAAE;YACL,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;SAClD;QACD,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,oBAAoB,EAAE,KAAK;KAC9B,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,MAAuB,EAAE,OAA2B,EAAE,oBAA6B;IAC1G,IAAI,oBAAoB,EAAE,CAAC;QACvB,OAAO;YACH,aAAa,EAAE,CAAC;YAChB,SAAS,EAAE,CAAC;YACZ,cAAc,EAAE,CAAC;YACjB,oBAAoB,EAAE,IAAI;SAC7B,CAAC;IACN,CAAC;IAED,OAAO;QACH,aAAa,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;QACvE,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,oBAAoB,EAAE,KAAK;KAC9B,CAAC;AACN,CAAC;AA2BD,MAAM,UAAU,eAAe,CAAC,SAAwB,EAAE,MAAoB;IAC1E,4DAA4D;IAC5D,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QAClE,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAChD,OAAO,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,8CAA8C;IAC9C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAqB,gBAAgB,CAAC,CAAC;IAE7E,+CAA+C;IAC/C,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC;QACzE,uBAAuB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,CAAC,CAAsB,EAAE,EAAE,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC/E,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,0DAA0D;IAC1D,SAAS,CAAC,GAAG,EAAE;QACX,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAE/B,+DAA+D;QAC/D,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE;YACvC,UAAU,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE;YACvC,UAAU,EAAE,IAAI;YAChB,eAAe,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;SAC3C,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,+CAA+C;IAC/C,OAAO,OAAO,CAAC,GAAG,EAAE;QAChB,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChD,OAAO,kBAAkB,CAAC,YAAY,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,iBAAiB,CAAC,YAAY,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC;IAC1E,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @enact-ui/animate
3
+ *
4
+ * Animation utilities and motion presets for ENACT UI.
5
+ * Only install if you need animation capabilities.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { type ComputedPathsMotion, type ComputedRaysMotion, useMotionPreset, } from "./hooks/use-motion-preset";
10
+ export { type AmbientPathsConfig, ambientPaths, applyMotionPreset, type ComponentType, getPreset, type LightRaysConfig, lightRays, type MotionPreset, type PresetConfig, } from "./presets/motion-presets";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAKH,OAAO,EACH,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,eAAe,GAClB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACH,KAAK,kBAAkB,EAEvB,YAAY,EACZ,iBAAiB,EACjB,KAAK,aAAa,EAElB,SAAS,EACT,KAAK,eAAe,EACpB,SAAS,EAET,KAAK,YAAY,EACjB,KAAK,YAAY,GACpB,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ambientPaths: () => ambientPaths,
24
+ applyMotionPreset: () => applyMotionPreset,
25
+ getPreset: () => getPreset,
26
+ lightRays: () => lightRays,
27
+ useMotionPreset: () => useMotionPreset
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/hooks/use-motion-preset.ts
32
+ var import_react = require("react");
33
+
34
+ // src/presets/motion-presets.ts
35
+ var ambientPaths = {
36
+ slow: {
37
+ duration: 30,
38
+ opacity: [0.2, 0.4, 0.2],
39
+ ease: "easeInOut",
40
+ delayVariation: 0.3,
41
+ durationVariation: 0.5
42
+ },
43
+ medium: {
44
+ duration: 20,
45
+ opacity: [0.3, 0.6, 0.3],
46
+ ease: "easeInOut",
47
+ delayVariation: 0.25,
48
+ durationVariation: 0.5
49
+ },
50
+ fast: {
51
+ duration: 12,
52
+ opacity: [0.4, 0.8, 0.4],
53
+ ease: "linear",
54
+ delayVariation: 0.2,
55
+ durationVariation: 0.4
56
+ }
57
+ };
58
+ var lightRays = {
59
+ slow: {
60
+ speed: 20,
61
+ intensity: 0.3,
62
+ swingVariation: 1.8
63
+ },
64
+ medium: {
65
+ speed: 14,
66
+ intensity: 0.5,
67
+ swingVariation: 1.5
68
+ },
69
+ fast: {
70
+ speed: 8,
71
+ intensity: 0.7,
72
+ swingVariation: 1.2
73
+ }
74
+ };
75
+ function getPreset(preset, component) {
76
+ if (component === "paths") {
77
+ return ambientPaths[preset];
78
+ }
79
+ return lightRays[preset];
80
+ }
81
+ function applyMotionPreset(preset, baseConfig) {
82
+ return { ...baseConfig, ...preset };
83
+ }
84
+
85
+ // src/hooks/use-motion-preset.ts
86
+ var DEFAULT_CSS_VARS = {
87
+ durationMultiplier: 1,
88
+ opacityMin: 0.35,
89
+ opacityMax: 0.6
90
+ };
91
+ function readCSSVariables() {
92
+ if (typeof window === "undefined") {
93
+ return DEFAULT_CSS_VARS;
94
+ }
95
+ const root = document.documentElement;
96
+ const styles = getComputedStyle(root);
97
+ const parseFloat_ = (value, fallback) => {
98
+ const parsed = parseFloat(value);
99
+ return Number.isNaN(parsed) ? fallback : parsed;
100
+ };
101
+ return {
102
+ durationMultiplier: parseFloat_(styles.getPropertyValue("--motion-duration-multiplier"), DEFAULT_CSS_VARS.durationMultiplier),
103
+ opacityMin: parseFloat_(styles.getPropertyValue("--motion-opacity-min"), DEFAULT_CSS_VARS.opacityMin),
104
+ opacityMax: parseFloat_(styles.getPropertyValue("--motion-opacity-max"), DEFAULT_CSS_VARS.opacityMax)
105
+ };
106
+ }
107
+ function computePathsMotion(preset, cssVars, prefersReducedMotion) {
108
+ if (prefersReducedMotion) {
109
+ return {
110
+ baseDuration: 0,
111
+ opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],
112
+ ease: preset.ease,
113
+ delayVariation: 0,
114
+ durationVariation: 0,
115
+ prefersReducedMotion: true
116
+ };
117
+ }
118
+ return {
119
+ baseDuration: preset.duration * cssVars.durationMultiplier,
120
+ opacity: [
121
+ Math.max(preset.opacity[0], cssVars.opacityMin),
122
+ Math.min(preset.opacity[1], cssVars.opacityMax),
123
+ Math.max(preset.opacity[2], cssVars.opacityMin)
124
+ ],
125
+ ease: preset.ease,
126
+ delayVariation: preset.delayVariation,
127
+ durationVariation: preset.durationVariation,
128
+ prefersReducedMotion: false
129
+ };
130
+ }
131
+ function computeRaysMotion(preset, cssVars, prefersReducedMotion) {
132
+ if (prefersReducedMotion) {
133
+ return {
134
+ cycleDuration: 0,
135
+ intensity: 0,
136
+ swingVariation: 0,
137
+ prefersReducedMotion: true
138
+ };
139
+ }
140
+ return {
141
+ cycleDuration: Math.max(preset.speed * cssVars.durationMultiplier, 0.1),
142
+ intensity: preset.intensity,
143
+ swingVariation: preset.swingVariation,
144
+ prefersReducedMotion: false
145
+ };
146
+ }
147
+ function useMotionPreset(component, preset) {
148
+ const [prefersReducedMotion, setPrefersReducedMotion] = (0, import_react.useState)(() => {
149
+ if (typeof window === "undefined") return false;
150
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
151
+ });
152
+ const [cssVars, setCssVars] = (0, import_react.useState)(DEFAULT_CSS_VARS);
153
+ (0, import_react.useEffect)(() => {
154
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
155
+ setPrefersReducedMotion(mediaQuery.matches);
156
+ const handler = (e) => setPrefersReducedMotion(e.matches);
157
+ mediaQuery.addEventListener("change", handler);
158
+ return () => mediaQuery.removeEventListener("change", handler);
159
+ }, []);
160
+ (0, import_react.useEffect)(() => {
161
+ setCssVars(readCSSVariables());
162
+ const observer = new MutationObserver(() => {
163
+ setCssVars(readCSSVariables());
164
+ });
165
+ observer.observe(document.documentElement, {
166
+ attributes: true,
167
+ attributeFilter: ["class", "data-theme"]
168
+ });
169
+ return () => observer.disconnect();
170
+ }, []);
171
+ return (0, import_react.useMemo)(() => {
172
+ if (component === "paths") {
173
+ const presetConfig2 = getPreset(preset, "paths");
174
+ return computePathsMotion(presetConfig2, cssVars, prefersReducedMotion);
175
+ }
176
+ const presetConfig = getPreset(preset, "rays");
177
+ return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);
178
+ }, [component, preset, cssVars, prefersReducedMotion]);
179
+ }
180
+ // Annotate the CommonJS export names for ESM import in node:
181
+ 0 && (module.exports = {
182
+ ambientPaths,
183
+ applyMotionPreset,
184
+ getPreset,
185
+ lightRays,
186
+ useMotionPreset
187
+ });
188
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/hooks/use-motion-preset.ts","../src/presets/motion-presets.ts"],"sourcesContent":["// Copyright (c) 2025 Amsterdam Data Labs\n// @enact-ui/animate - Animation utilities and motion presets\n\n/**\n * @enact-ui/animate\n *\n * Animation utilities and motion presets for ENACT UI.\n * Only install if you need animation capabilities.\n *\n * @packageDocumentation\n */\n\n// =============================================================================\n// Hooks\n// =============================================================================\nexport {\n type ComputedPathsMotion,\n type ComputedRaysMotion,\n useMotionPreset,\n} from \"./hooks/use-motion-preset\";\n\n// =============================================================================\n// Motion Presets\n// =============================================================================\nexport {\n type AmbientPathsConfig,\n // Preset configurations\n ambientPaths,\n applyMotionPreset,\n type ComponentType,\n // Utility functions\n getPreset,\n type LightRaysConfig,\n lightRays,\n // Types\n type MotionPreset,\n type PresetConfig,\n} from \"./presets/motion-presets\";\n","// Copyright (c) 2025 Amsterdam Data Labs\n\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { type AmbientPathsConfig, type ComponentType, getPreset, type LightRaysConfig, type MotionPreset } from \"../presets/motion-presets\";\n\n/** CSS motion variables read from the theme */\ninterface MotionCSSVariables {\n /** Speed/duration multiplier (0 = no motion, 1 = normal) */\n durationMultiplier: number;\n /** Minimum opacity for motion animations */\n opacityMin: number;\n /** Maximum opacity for motion animations */\n opacityMax: number;\n}\n\n/** Computed motion configuration for paths component */\nexport interface ComputedPathsMotion {\n /** Computed base duration (preset * CSS multiplier) */\n baseDuration: number;\n /** Computed opacity keyframes respecting CSS bounds */\n opacity: [number, number, number];\n /** Easing function from preset */\n ease: \"linear\" | \"easeInOut\";\n /** Delay variation factor from preset */\n delayVariation: number;\n /** Duration variation factor from preset */\n durationVariation: number;\n /** Whether reduced motion is preferred */\n prefersReducedMotion: boolean;\n}\n\n/** Computed motion configuration for rays component */\nexport interface ComputedRaysMotion {\n /** Computed cycle duration (preset speed * CSS multiplier) */\n cycleDuration: number;\n /** Base intensity from preset */\n intensity: number;\n /** Swing variation from preset */\n swingVariation: number;\n /** Whether reduced motion is preferred */\n prefersReducedMotion: boolean;\n}\n\n/** Default CSS variable values (fallback if not in browser) */\nconst DEFAULT_CSS_VARS: MotionCSSVariables = {\n durationMultiplier: 1,\n opacityMin: 0.35,\n opacityMax: 0.6,\n};\n\n/**\n * Reads motion CSS variables from the document root.\n * Returns default values if not in browser environment.\n */\nfunction readCSSVariables(): MotionCSSVariables {\n if (typeof window === \"undefined\") {\n return DEFAULT_CSS_VARS;\n }\n\n const root = document.documentElement;\n const styles = getComputedStyle(root);\n\n const parseFloat_ = (value: string, fallback: number): number => {\n const parsed = parseFloat(value);\n return Number.isNaN(parsed) ? fallback : parsed;\n };\n\n return {\n durationMultiplier: parseFloat_(styles.getPropertyValue(\"--motion-duration-multiplier\"), DEFAULT_CSS_VARS.durationMultiplier),\n opacityMin: parseFloat_(styles.getPropertyValue(\"--motion-opacity-min\"), DEFAULT_CSS_VARS.opacityMin),\n opacityMax: parseFloat_(styles.getPropertyValue(\"--motion-opacity-max\"), DEFAULT_CSS_VARS.opacityMax),\n };\n}\n\n/**\n * Computes paths motion configuration from preset and CSS variables.\n */\nfunction computePathsMotion(preset: AmbientPathsConfig, cssVars: MotionCSSVariables, prefersReducedMotion: boolean): ComputedPathsMotion {\n if (prefersReducedMotion) {\n return {\n baseDuration: 0,\n opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],\n ease: preset.ease,\n delayVariation: 0,\n durationVariation: 0,\n prefersReducedMotion: true,\n };\n }\n\n return {\n baseDuration: preset.duration * cssVars.durationMultiplier,\n opacity: [\n Math.max(preset.opacity[0], cssVars.opacityMin),\n Math.min(preset.opacity[1], cssVars.opacityMax),\n Math.max(preset.opacity[2], cssVars.opacityMin),\n ],\n ease: preset.ease,\n delayVariation: preset.delayVariation,\n durationVariation: preset.durationVariation,\n prefersReducedMotion: false,\n };\n}\n\n/**\n * Computes rays motion configuration from preset and CSS variables.\n */\nfunction computeRaysMotion(preset: LightRaysConfig, cssVars: MotionCSSVariables, prefersReducedMotion: boolean): ComputedRaysMotion {\n if (prefersReducedMotion) {\n return {\n cycleDuration: 0,\n intensity: 0,\n swingVariation: 0,\n prefersReducedMotion: true,\n };\n }\n\n return {\n cycleDuration: Math.max(preset.speed * cssVars.durationMultiplier, 0.1),\n intensity: preset.intensity,\n swingVariation: preset.swingVariation,\n prefersReducedMotion: false,\n };\n}\n\n/**\n * Hook for using motion presets with theme-aware CSS variables.\n *\n * Provides computed motion configuration that:\n * - Respects `prefers-reduced-motion` preference\n * - Reads and applies CSS motion variables from the theme\n * - Memoizes calculations to prevent unnecessary re-renders\n *\n * @param component - The component type (\"paths\" | \"rays\")\n * @param preset - The motion preset (\"slow\" | \"medium\" | \"fast\")\n * @returns Computed motion configuration for the component\n *\n * @example\n * ```tsx\n * // In BackgroundPaths component\n * const motion = useMotionPreset(\"paths\", \"medium\");\n * // Returns: { baseDuration: 20, opacity: [...], ... }\n *\n * // In LightRays component\n * const motion = useMotionPreset(\"rays\", \"fast\");\n * // Returns: { cycleDuration: 8, intensity: 0.7, ... }\n * ```\n */\nexport function useMotionPreset(component: \"paths\", preset: MotionPreset): ComputedPathsMotion;\nexport function useMotionPreset(component: \"rays\", preset: MotionPreset): ComputedRaysMotion;\nexport function useMotionPreset(component: ComponentType, preset: MotionPreset): ComputedPathsMotion | ComputedRaysMotion {\n // Track reduced motion preference with state for reactivity\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n });\n\n // Track CSS variables (may change with theme)\n const [cssVars, setCssVars] = useState<MotionCSSVariables>(DEFAULT_CSS_VARS);\n\n // Listen for reduced motion preference changes\n useEffect(() => {\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setPrefersReducedMotion(mediaQuery.matches);\n\n const handler = (e: MediaQueryListEvent) => setPrefersReducedMotion(e.matches);\n mediaQuery.addEventListener(\"change\", handler);\n return () => mediaQuery.removeEventListener(\"change\", handler);\n }, []);\n\n // Read CSS variables on mount and when theme might change\n useEffect(() => {\n setCssVars(readCSSVariables());\n\n // Listen for theme changes via attribute mutations on document\n const observer = new MutationObserver(() => {\n setCssVars(readCSSVariables());\n });\n\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\"],\n });\n\n return () => observer.disconnect();\n }, []);\n\n // Compute and memoize the motion configuration\n return useMemo(() => {\n if (component === \"paths\") {\n const presetConfig = getPreset(preset, \"paths\");\n return computePathsMotion(presetConfig, cssVars, prefersReducedMotion);\n }\n const presetConfig = getPreset(preset, \"rays\");\n return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);\n }, [component, preset, cssVars, prefersReducedMotion]);\n}\n","// Copyright (c) 2025 Amsterdam Data Labs\n/**\n * Motion Presets Utility\n *\n * Defines motion preset configurations for ambient animation components.\n * These presets provide consistent, theme-aware motion settings.\n */\n\n/** Available motion speed presets */\nexport type MotionPreset = \"slow\" | \"medium\" | \"fast\";\n\n/** Component types that support motion presets */\nexport type ComponentType = \"paths\" | \"rays\";\n\n/** Configuration for ambient paths animations */\nexport interface AmbientPathsConfig {\n /** Base duration in seconds */\n duration: number;\n /** Opacity keyframes [start, peak, end] */\n opacity: [number, number, number];\n /** Easing function */\n ease: \"linear\" | \"easeInOut\";\n /** Random delay variation factor (0-1) */\n delayVariation: number;\n /** Random duration variation factor (0-1) */\n durationVariation: number;\n}\n\n/** Configuration for light rays animations */\nexport interface LightRaysConfig {\n /** Base speed/cycle duration in seconds */\n speed: number;\n /** Base intensity multiplier (0-1) */\n intensity: number;\n /** Swing angle variation factor */\n swingVariation: number;\n}\n\n/** Union type for all preset configurations */\nexport type PresetConfig = AmbientPathsConfig | LightRaysConfig;\n\n/**\n * Preset configurations for BackgroundPaths component.\n * Each preset defines duration, opacity, and variation settings.\n */\nexport const ambientPaths: Record<MotionPreset, AmbientPathsConfig> = {\n slow: {\n duration: 30,\n opacity: [0.2, 0.4, 0.2],\n ease: \"easeInOut\",\n delayVariation: 0.3,\n durationVariation: 0.5,\n },\n medium: {\n duration: 20,\n opacity: [0.3, 0.6, 0.3],\n ease: \"easeInOut\",\n delayVariation: 0.25,\n durationVariation: 0.5,\n },\n fast: {\n duration: 12,\n opacity: [0.4, 0.8, 0.4],\n ease: \"linear\",\n delayVariation: 0.2,\n durationVariation: 0.4,\n },\n};\n\n/**\n * Preset configurations for LightRays component.\n * Each preset defines speed, intensity, and swing settings.\n */\nexport const lightRays: Record<MotionPreset, LightRaysConfig> = {\n slow: {\n speed: 20,\n intensity: 0.3,\n swingVariation: 1.8,\n },\n medium: {\n speed: 14,\n intensity: 0.5,\n swingVariation: 1.5,\n },\n fast: {\n speed: 8,\n intensity: 0.7,\n swingVariation: 1.2,\n },\n};\n\n/**\n * Retrieves a preset configuration for a specific component type.\n *\n * @param preset - The motion preset name (\"slow\" | \"medium\" | \"fast\")\n * @param component - The component type (\"paths\" | \"rays\")\n * @returns The preset configuration for the specified component\n *\n * @example\n * ```ts\n * const pathsPreset = getPreset(\"medium\", \"paths\");\n * // Returns: { duration: 20, opacity: [0.3, 0.6, 0.3], ... }\n *\n * const raysPreset = getPreset(\"fast\", \"rays\");\n * // Returns: { speed: 8, intensity: 0.7, swingVariation: 1.2 }\n * ```\n */\nexport function getPreset(preset: MotionPreset, component: \"paths\"): AmbientPathsConfig;\nexport function getPreset(preset: MotionPreset, component: \"rays\"): LightRaysConfig;\nexport function getPreset(preset: MotionPreset, component: ComponentType): PresetConfig {\n if (component === \"paths\") {\n return ambientPaths[preset];\n }\n return lightRays[preset];\n}\n\n/**\n * Merges a preset configuration with a base configuration.\n * Useful for combining preset values with component-specific overrides.\n *\n * @param preset - The preset configuration to apply\n * @param baseConfig - The base configuration to merge with\n * @returns Merged configuration with preset values taking precedence\n *\n * @example\n * ```ts\n * const preset = getPreset(\"medium\", \"paths\");\n * const result = applyMotionPreset(preset, { count: 36 });\n * // Returns: { duration: 20, opacity: [...], count: 36, ... }\n * ```\n */\nexport function applyMotionPreset<T extends Record<string, unknown>>(preset: PresetConfig, baseConfig: T): PresetConfig & T {\n return { ...baseConfig, ...preset };\n}\n"],"mappings":"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","names":["presetConfig"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,157 @@
1
+ // src/hooks/use-motion-preset.ts
2
+ import { useEffect, useMemo, useState } from "react";
3
+
4
+ // src/presets/motion-presets.ts
5
+ var ambientPaths = {
6
+ slow: {
7
+ duration: 30,
8
+ opacity: [0.2, 0.4, 0.2],
9
+ ease: "easeInOut",
10
+ delayVariation: 0.3,
11
+ durationVariation: 0.5
12
+ },
13
+ medium: {
14
+ duration: 20,
15
+ opacity: [0.3, 0.6, 0.3],
16
+ ease: "easeInOut",
17
+ delayVariation: 0.25,
18
+ durationVariation: 0.5
19
+ },
20
+ fast: {
21
+ duration: 12,
22
+ opacity: [0.4, 0.8, 0.4],
23
+ ease: "linear",
24
+ delayVariation: 0.2,
25
+ durationVariation: 0.4
26
+ }
27
+ };
28
+ var lightRays = {
29
+ slow: {
30
+ speed: 20,
31
+ intensity: 0.3,
32
+ swingVariation: 1.8
33
+ },
34
+ medium: {
35
+ speed: 14,
36
+ intensity: 0.5,
37
+ swingVariation: 1.5
38
+ },
39
+ fast: {
40
+ speed: 8,
41
+ intensity: 0.7,
42
+ swingVariation: 1.2
43
+ }
44
+ };
45
+ function getPreset(preset, component) {
46
+ if (component === "paths") {
47
+ return ambientPaths[preset];
48
+ }
49
+ return lightRays[preset];
50
+ }
51
+ function applyMotionPreset(preset, baseConfig) {
52
+ return { ...baseConfig, ...preset };
53
+ }
54
+
55
+ // src/hooks/use-motion-preset.ts
56
+ var DEFAULT_CSS_VARS = {
57
+ durationMultiplier: 1,
58
+ opacityMin: 0.35,
59
+ opacityMax: 0.6
60
+ };
61
+ function readCSSVariables() {
62
+ if (typeof window === "undefined") {
63
+ return DEFAULT_CSS_VARS;
64
+ }
65
+ const root = document.documentElement;
66
+ const styles = getComputedStyle(root);
67
+ const parseFloat_ = (value, fallback) => {
68
+ const parsed = parseFloat(value);
69
+ return Number.isNaN(parsed) ? fallback : parsed;
70
+ };
71
+ return {
72
+ durationMultiplier: parseFloat_(styles.getPropertyValue("--motion-duration-multiplier"), DEFAULT_CSS_VARS.durationMultiplier),
73
+ opacityMin: parseFloat_(styles.getPropertyValue("--motion-opacity-min"), DEFAULT_CSS_VARS.opacityMin),
74
+ opacityMax: parseFloat_(styles.getPropertyValue("--motion-opacity-max"), DEFAULT_CSS_VARS.opacityMax)
75
+ };
76
+ }
77
+ function computePathsMotion(preset, cssVars, prefersReducedMotion) {
78
+ if (prefersReducedMotion) {
79
+ return {
80
+ baseDuration: 0,
81
+ opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],
82
+ ease: preset.ease,
83
+ delayVariation: 0,
84
+ durationVariation: 0,
85
+ prefersReducedMotion: true
86
+ };
87
+ }
88
+ return {
89
+ baseDuration: preset.duration * cssVars.durationMultiplier,
90
+ opacity: [
91
+ Math.max(preset.opacity[0], cssVars.opacityMin),
92
+ Math.min(preset.opacity[1], cssVars.opacityMax),
93
+ Math.max(preset.opacity[2], cssVars.opacityMin)
94
+ ],
95
+ ease: preset.ease,
96
+ delayVariation: preset.delayVariation,
97
+ durationVariation: preset.durationVariation,
98
+ prefersReducedMotion: false
99
+ };
100
+ }
101
+ function computeRaysMotion(preset, cssVars, prefersReducedMotion) {
102
+ if (prefersReducedMotion) {
103
+ return {
104
+ cycleDuration: 0,
105
+ intensity: 0,
106
+ swingVariation: 0,
107
+ prefersReducedMotion: true
108
+ };
109
+ }
110
+ return {
111
+ cycleDuration: Math.max(preset.speed * cssVars.durationMultiplier, 0.1),
112
+ intensity: preset.intensity,
113
+ swingVariation: preset.swingVariation,
114
+ prefersReducedMotion: false
115
+ };
116
+ }
117
+ function useMotionPreset(component, preset) {
118
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {
119
+ if (typeof window === "undefined") return false;
120
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
121
+ });
122
+ const [cssVars, setCssVars] = useState(DEFAULT_CSS_VARS);
123
+ useEffect(() => {
124
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
125
+ setPrefersReducedMotion(mediaQuery.matches);
126
+ const handler = (e) => setPrefersReducedMotion(e.matches);
127
+ mediaQuery.addEventListener("change", handler);
128
+ return () => mediaQuery.removeEventListener("change", handler);
129
+ }, []);
130
+ useEffect(() => {
131
+ setCssVars(readCSSVariables());
132
+ const observer = new MutationObserver(() => {
133
+ setCssVars(readCSSVariables());
134
+ });
135
+ observer.observe(document.documentElement, {
136
+ attributes: true,
137
+ attributeFilter: ["class", "data-theme"]
138
+ });
139
+ return () => observer.disconnect();
140
+ }, []);
141
+ return useMemo(() => {
142
+ if (component === "paths") {
143
+ const presetConfig2 = getPreset(preset, "paths");
144
+ return computePathsMotion(presetConfig2, cssVars, prefersReducedMotion);
145
+ }
146
+ const presetConfig = getPreset(preset, "rays");
147
+ return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);
148
+ }, [component, preset, cssVars, prefersReducedMotion]);
149
+ }
150
+ export {
151
+ ambientPaths,
152
+ applyMotionPreset,
153
+ getPreset,
154
+ lightRays,
155
+ useMotionPreset
156
+ };
157
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-motion-preset.ts","../src/presets/motion-presets.ts"],"sourcesContent":["// Copyright (c) 2025 Amsterdam Data Labs\n\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { type AmbientPathsConfig, type ComponentType, getPreset, type LightRaysConfig, type MotionPreset } from \"../presets/motion-presets\";\n\n/** CSS motion variables read from the theme */\ninterface MotionCSSVariables {\n /** Speed/duration multiplier (0 = no motion, 1 = normal) */\n durationMultiplier: number;\n /** Minimum opacity for motion animations */\n opacityMin: number;\n /** Maximum opacity for motion animations */\n opacityMax: number;\n}\n\n/** Computed motion configuration for paths component */\nexport interface ComputedPathsMotion {\n /** Computed base duration (preset * CSS multiplier) */\n baseDuration: number;\n /** Computed opacity keyframes respecting CSS bounds */\n opacity: [number, number, number];\n /** Easing function from preset */\n ease: \"linear\" | \"easeInOut\";\n /** Delay variation factor from preset */\n delayVariation: number;\n /** Duration variation factor from preset */\n durationVariation: number;\n /** Whether reduced motion is preferred */\n prefersReducedMotion: boolean;\n}\n\n/** Computed motion configuration for rays component */\nexport interface ComputedRaysMotion {\n /** Computed cycle duration (preset speed * CSS multiplier) */\n cycleDuration: number;\n /** Base intensity from preset */\n intensity: number;\n /** Swing variation from preset */\n swingVariation: number;\n /** Whether reduced motion is preferred */\n prefersReducedMotion: boolean;\n}\n\n/** Default CSS variable values (fallback if not in browser) */\nconst DEFAULT_CSS_VARS: MotionCSSVariables = {\n durationMultiplier: 1,\n opacityMin: 0.35,\n opacityMax: 0.6,\n};\n\n/**\n * Reads motion CSS variables from the document root.\n * Returns default values if not in browser environment.\n */\nfunction readCSSVariables(): MotionCSSVariables {\n if (typeof window === \"undefined\") {\n return DEFAULT_CSS_VARS;\n }\n\n const root = document.documentElement;\n const styles = getComputedStyle(root);\n\n const parseFloat_ = (value: string, fallback: number): number => {\n const parsed = parseFloat(value);\n return Number.isNaN(parsed) ? fallback : parsed;\n };\n\n return {\n durationMultiplier: parseFloat_(styles.getPropertyValue(\"--motion-duration-multiplier\"), DEFAULT_CSS_VARS.durationMultiplier),\n opacityMin: parseFloat_(styles.getPropertyValue(\"--motion-opacity-min\"), DEFAULT_CSS_VARS.opacityMin),\n opacityMax: parseFloat_(styles.getPropertyValue(\"--motion-opacity-max\"), DEFAULT_CSS_VARS.opacityMax),\n };\n}\n\n/**\n * Computes paths motion configuration from preset and CSS variables.\n */\nfunction computePathsMotion(preset: AmbientPathsConfig, cssVars: MotionCSSVariables, prefersReducedMotion: boolean): ComputedPathsMotion {\n if (prefersReducedMotion) {\n return {\n baseDuration: 0,\n opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],\n ease: preset.ease,\n delayVariation: 0,\n durationVariation: 0,\n prefersReducedMotion: true,\n };\n }\n\n return {\n baseDuration: preset.duration * cssVars.durationMultiplier,\n opacity: [\n Math.max(preset.opacity[0], cssVars.opacityMin),\n Math.min(preset.opacity[1], cssVars.opacityMax),\n Math.max(preset.opacity[2], cssVars.opacityMin),\n ],\n ease: preset.ease,\n delayVariation: preset.delayVariation,\n durationVariation: preset.durationVariation,\n prefersReducedMotion: false,\n };\n}\n\n/**\n * Computes rays motion configuration from preset and CSS variables.\n */\nfunction computeRaysMotion(preset: LightRaysConfig, cssVars: MotionCSSVariables, prefersReducedMotion: boolean): ComputedRaysMotion {\n if (prefersReducedMotion) {\n return {\n cycleDuration: 0,\n intensity: 0,\n swingVariation: 0,\n prefersReducedMotion: true,\n };\n }\n\n return {\n cycleDuration: Math.max(preset.speed * cssVars.durationMultiplier, 0.1),\n intensity: preset.intensity,\n swingVariation: preset.swingVariation,\n prefersReducedMotion: false,\n };\n}\n\n/**\n * Hook for using motion presets with theme-aware CSS variables.\n *\n * Provides computed motion configuration that:\n * - Respects `prefers-reduced-motion` preference\n * - Reads and applies CSS motion variables from the theme\n * - Memoizes calculations to prevent unnecessary re-renders\n *\n * @param component - The component type (\"paths\" | \"rays\")\n * @param preset - The motion preset (\"slow\" | \"medium\" | \"fast\")\n * @returns Computed motion configuration for the component\n *\n * @example\n * ```tsx\n * // In BackgroundPaths component\n * const motion = useMotionPreset(\"paths\", \"medium\");\n * // Returns: { baseDuration: 20, opacity: [...], ... }\n *\n * // In LightRays component\n * const motion = useMotionPreset(\"rays\", \"fast\");\n * // Returns: { cycleDuration: 8, intensity: 0.7, ... }\n * ```\n */\nexport function useMotionPreset(component: \"paths\", preset: MotionPreset): ComputedPathsMotion;\nexport function useMotionPreset(component: \"rays\", preset: MotionPreset): ComputedRaysMotion;\nexport function useMotionPreset(component: ComponentType, preset: MotionPreset): ComputedPathsMotion | ComputedRaysMotion {\n // Track reduced motion preference with state for reactivity\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n });\n\n // Track CSS variables (may change with theme)\n const [cssVars, setCssVars] = useState<MotionCSSVariables>(DEFAULT_CSS_VARS);\n\n // Listen for reduced motion preference changes\n useEffect(() => {\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setPrefersReducedMotion(mediaQuery.matches);\n\n const handler = (e: MediaQueryListEvent) => setPrefersReducedMotion(e.matches);\n mediaQuery.addEventListener(\"change\", handler);\n return () => mediaQuery.removeEventListener(\"change\", handler);\n }, []);\n\n // Read CSS variables on mount and when theme might change\n useEffect(() => {\n setCssVars(readCSSVariables());\n\n // Listen for theme changes via attribute mutations on document\n const observer = new MutationObserver(() => {\n setCssVars(readCSSVariables());\n });\n\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\", \"data-theme\"],\n });\n\n return () => observer.disconnect();\n }, []);\n\n // Compute and memoize the motion configuration\n return useMemo(() => {\n if (component === \"paths\") {\n const presetConfig = getPreset(preset, \"paths\");\n return computePathsMotion(presetConfig, cssVars, prefersReducedMotion);\n }\n const presetConfig = getPreset(preset, \"rays\");\n return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);\n }, [component, preset, cssVars, prefersReducedMotion]);\n}\n","// Copyright (c) 2025 Amsterdam Data Labs\n/**\n * Motion Presets Utility\n *\n * Defines motion preset configurations for ambient animation components.\n * These presets provide consistent, theme-aware motion settings.\n */\n\n/** Available motion speed presets */\nexport type MotionPreset = \"slow\" | \"medium\" | \"fast\";\n\n/** Component types that support motion presets */\nexport type ComponentType = \"paths\" | \"rays\";\n\n/** Configuration for ambient paths animations */\nexport interface AmbientPathsConfig {\n /** Base duration in seconds */\n duration: number;\n /** Opacity keyframes [start, peak, end] */\n opacity: [number, number, number];\n /** Easing function */\n ease: \"linear\" | \"easeInOut\";\n /** Random delay variation factor (0-1) */\n delayVariation: number;\n /** Random duration variation factor (0-1) */\n durationVariation: number;\n}\n\n/** Configuration for light rays animations */\nexport interface LightRaysConfig {\n /** Base speed/cycle duration in seconds */\n speed: number;\n /** Base intensity multiplier (0-1) */\n intensity: number;\n /** Swing angle variation factor */\n swingVariation: number;\n}\n\n/** Union type for all preset configurations */\nexport type PresetConfig = AmbientPathsConfig | LightRaysConfig;\n\n/**\n * Preset configurations for BackgroundPaths component.\n * Each preset defines duration, opacity, and variation settings.\n */\nexport const ambientPaths: Record<MotionPreset, AmbientPathsConfig> = {\n slow: {\n duration: 30,\n opacity: [0.2, 0.4, 0.2],\n ease: \"easeInOut\",\n delayVariation: 0.3,\n durationVariation: 0.5,\n },\n medium: {\n duration: 20,\n opacity: [0.3, 0.6, 0.3],\n ease: \"easeInOut\",\n delayVariation: 0.25,\n durationVariation: 0.5,\n },\n fast: {\n duration: 12,\n opacity: [0.4, 0.8, 0.4],\n ease: \"linear\",\n delayVariation: 0.2,\n durationVariation: 0.4,\n },\n};\n\n/**\n * Preset configurations for LightRays component.\n * Each preset defines speed, intensity, and swing settings.\n */\nexport const lightRays: Record<MotionPreset, LightRaysConfig> = {\n slow: {\n speed: 20,\n intensity: 0.3,\n swingVariation: 1.8,\n },\n medium: {\n speed: 14,\n intensity: 0.5,\n swingVariation: 1.5,\n },\n fast: {\n speed: 8,\n intensity: 0.7,\n swingVariation: 1.2,\n },\n};\n\n/**\n * Retrieves a preset configuration for a specific component type.\n *\n * @param preset - The motion preset name (\"slow\" | \"medium\" | \"fast\")\n * @param component - The component type (\"paths\" | \"rays\")\n * @returns The preset configuration for the specified component\n *\n * @example\n * ```ts\n * const pathsPreset = getPreset(\"medium\", \"paths\");\n * // Returns: { duration: 20, opacity: [0.3, 0.6, 0.3], ... }\n *\n * const raysPreset = getPreset(\"fast\", \"rays\");\n * // Returns: { speed: 8, intensity: 0.7, swingVariation: 1.2 }\n * ```\n */\nexport function getPreset(preset: MotionPreset, component: \"paths\"): AmbientPathsConfig;\nexport function getPreset(preset: MotionPreset, component: \"rays\"): LightRaysConfig;\nexport function getPreset(preset: MotionPreset, component: ComponentType): PresetConfig {\n if (component === \"paths\") {\n return ambientPaths[preset];\n }\n return lightRays[preset];\n}\n\n/**\n * Merges a preset configuration with a base configuration.\n * Useful for combining preset values with component-specific overrides.\n *\n * @param preset - The preset configuration to apply\n * @param baseConfig - The base configuration to merge with\n * @returns Merged configuration with preset values taking precedence\n *\n * @example\n * ```ts\n * const preset = getPreset(\"medium\", \"paths\");\n * const result = applyMotionPreset(preset, { count: 36 });\n * // Returns: { duration: 20, opacity: [...], count: 36, ... }\n * ```\n */\nexport function applyMotionPreset<T extends Record<string, unknown>>(preset: PresetConfig, baseConfig: T): PresetConfig & T {\n return { ...baseConfig, ...preset };\n}\n"],"mappings":"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","names":["presetConfig"]}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Motion Presets Utility
3
+ *
4
+ * Defines motion preset configurations for ambient animation components.
5
+ * These presets provide consistent, theme-aware motion settings.
6
+ */
7
+ /** Available motion speed presets */
8
+ export type MotionPreset = "slow" | "medium" | "fast";
9
+ /** Component types that support motion presets */
10
+ export type ComponentType = "paths" | "rays";
11
+ /** Configuration for ambient paths animations */
12
+ export interface AmbientPathsConfig {
13
+ /** Base duration in seconds */
14
+ duration: number;
15
+ /** Opacity keyframes [start, peak, end] */
16
+ opacity: [number, number, number];
17
+ /** Easing function */
18
+ ease: "linear" | "easeInOut";
19
+ /** Random delay variation factor (0-1) */
20
+ delayVariation: number;
21
+ /** Random duration variation factor (0-1) */
22
+ durationVariation: number;
23
+ }
24
+ /** Configuration for light rays animations */
25
+ export interface LightRaysConfig {
26
+ /** Base speed/cycle duration in seconds */
27
+ speed: number;
28
+ /** Base intensity multiplier (0-1) */
29
+ intensity: number;
30
+ /** Swing angle variation factor */
31
+ swingVariation: number;
32
+ }
33
+ /** Union type for all preset configurations */
34
+ export type PresetConfig = AmbientPathsConfig | LightRaysConfig;
35
+ /**
36
+ * Preset configurations for BackgroundPaths component.
37
+ * Each preset defines duration, opacity, and variation settings.
38
+ */
39
+ export declare const ambientPaths: Record<MotionPreset, AmbientPathsConfig>;
40
+ /**
41
+ * Preset configurations for LightRays component.
42
+ * Each preset defines speed, intensity, and swing settings.
43
+ */
44
+ export declare const lightRays: Record<MotionPreset, LightRaysConfig>;
45
+ /**
46
+ * Retrieves a preset configuration for a specific component type.
47
+ *
48
+ * @param preset - The motion preset name ("slow" | "medium" | "fast")
49
+ * @param component - The component type ("paths" | "rays")
50
+ * @returns The preset configuration for the specified component
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const pathsPreset = getPreset("medium", "paths");
55
+ * // Returns: { duration: 20, opacity: [0.3, 0.6, 0.3], ... }
56
+ *
57
+ * const raysPreset = getPreset("fast", "rays");
58
+ * // Returns: { speed: 8, intensity: 0.7, swingVariation: 1.2 }
59
+ * ```
60
+ */
61
+ export declare function getPreset(preset: MotionPreset, component: "paths"): AmbientPathsConfig;
62
+ export declare function getPreset(preset: MotionPreset, component: "rays"): LightRaysConfig;
63
+ /**
64
+ * Merges a preset configuration with a base configuration.
65
+ * Useful for combining preset values with component-specific overrides.
66
+ *
67
+ * @param preset - The preset configuration to apply
68
+ * @param baseConfig - The base configuration to merge with
69
+ * @returns Merged configuration with preset values taking precedence
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * const preset = getPreset("medium", "paths");
74
+ * const result = applyMotionPreset(preset, { count: 36 });
75
+ * // Returns: { duration: 20, opacity: [...], count: 36, ... }
76
+ * ```
77
+ */
78
+ export declare function applyMotionPreset<T extends Record<string, unknown>>(preset: PresetConfig, baseConfig: T): PresetConfig & T;
79
+ //# sourceMappingURL=motion-presets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion-presets.d.ts","sourceRoot":"","sources":["../../src/presets/motion-presets.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,qCAAqC;AACrC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IAC/B,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,sBAAsB;IACtB,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAC;IAC7B,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;CAC7B;AAED,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC5B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,+CAA+C;AAC/C,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEhE;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,kBAAkB,CAsBjE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE,eAAe,CAgB3D,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,kBAAkB,CAAC;AACxF,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAAC;AAQpF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,GAAG,YAAY,GAAG,CAAC,CAE1H"}
@@ -0,0 +1,80 @@
1
+ // Copyright (c) 2025 Amsterdam Data Labs
2
+ /**
3
+ * Motion Presets Utility
4
+ *
5
+ * Defines motion preset configurations for ambient animation components.
6
+ * These presets provide consistent, theme-aware motion settings.
7
+ */
8
+ /**
9
+ * Preset configurations for BackgroundPaths component.
10
+ * Each preset defines duration, opacity, and variation settings.
11
+ */
12
+ export const ambientPaths = {
13
+ slow: {
14
+ duration: 30,
15
+ opacity: [0.2, 0.4, 0.2],
16
+ ease: "easeInOut",
17
+ delayVariation: 0.3,
18
+ durationVariation: 0.5,
19
+ },
20
+ medium: {
21
+ duration: 20,
22
+ opacity: [0.3, 0.6, 0.3],
23
+ ease: "easeInOut",
24
+ delayVariation: 0.25,
25
+ durationVariation: 0.5,
26
+ },
27
+ fast: {
28
+ duration: 12,
29
+ opacity: [0.4, 0.8, 0.4],
30
+ ease: "linear",
31
+ delayVariation: 0.2,
32
+ durationVariation: 0.4,
33
+ },
34
+ };
35
+ /**
36
+ * Preset configurations for LightRays component.
37
+ * Each preset defines speed, intensity, and swing settings.
38
+ */
39
+ export const lightRays = {
40
+ slow: {
41
+ speed: 20,
42
+ intensity: 0.3,
43
+ swingVariation: 1.8,
44
+ },
45
+ medium: {
46
+ speed: 14,
47
+ intensity: 0.5,
48
+ swingVariation: 1.5,
49
+ },
50
+ fast: {
51
+ speed: 8,
52
+ intensity: 0.7,
53
+ swingVariation: 1.2,
54
+ },
55
+ };
56
+ export function getPreset(preset, component) {
57
+ if (component === "paths") {
58
+ return ambientPaths[preset];
59
+ }
60
+ return lightRays[preset];
61
+ }
62
+ /**
63
+ * Merges a preset configuration with a base configuration.
64
+ * Useful for combining preset values with component-specific overrides.
65
+ *
66
+ * @param preset - The preset configuration to apply
67
+ * @param baseConfig - The base configuration to merge with
68
+ * @returns Merged configuration with preset values taking precedence
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const preset = getPreset("medium", "paths");
73
+ * const result = applyMotionPreset(preset, { count: 36 });
74
+ * // Returns: { duration: 20, opacity: [...], count: 36, ... }
75
+ * ```
76
+ */
77
+ export function applyMotionPreset(preset, baseConfig) {
78
+ return { ...baseConfig, ...preset };
79
+ }
80
+ //# sourceMappingURL=motion-presets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion-presets.js","sourceRoot":"","sources":["../../src/presets/motion-presets.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC;;;;;GAKG;AAmCH;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAA6C;IAClE,IAAI,EAAE;QACF,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;QACxB,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,GAAG;QACnB,iBAAiB,EAAE,GAAG;KACzB;IACD,MAAM,EAAE;QACJ,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;QACxB,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,IAAI;QACpB,iBAAiB,EAAE,GAAG;KACzB;IACD,IAAI,EAAE;QACF,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;QACxB,IAAI,EAAE,QAAQ;QACd,cAAc,EAAE,GAAG;QACnB,iBAAiB,EAAE,GAAG;KACzB;CACJ,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAA0C;IAC5D,IAAI,EAAE;QACF,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;KACtB;IACD,MAAM,EAAE;QACJ,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;KACtB;IACD,IAAI,EAAE;QACF,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;KACtB;CACJ,CAAC;AAoBF,MAAM,UAAU,SAAS,CAAC,MAAoB,EAAE,SAAwB;IACpE,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAoC,MAAoB,EAAE,UAAa;IACpG,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC;AACxC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@enact-ui/animate",
3
+ "version": "1.0.0",
4
+ "description": "Animation utilities and motion presets for ENACT UI. Only install if you need animation.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "sideEffects": false,
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc --build && tsup",
22
+ "dev": "tsup --watch",
23
+ "type-check": "tsc --noEmit",
24
+ "lint": "biome check --write .",
25
+ "lint:check": "biome check .",
26
+ "clean": "rm -rf dist tsconfig.tsbuildinfo"
27
+ },
28
+ "peerDependencies": {
29
+ "@enact-ui/react": "^0.0.0",
30
+ "motion": "^12.0.0",
31
+ "react": "^18.0.0 || ^19.0.0",
32
+ "react-dom": "^18.0.0 || ^19.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^19.1.9",
36
+ "@types/react-dom": "^19.1.7",
37
+ "typescript": "^5.9.2"
38
+ },
39
+ "keywords": [
40
+ "react",
41
+ "animation",
42
+ "motion",
43
+ "framer-motion",
44
+ "enact-ui"
45
+ ],
46
+ "engines": {
47
+ "node": ">=24.0.0",
48
+ "npm": ">=10.0.0"
49
+ },
50
+ "author": "Enact UI",
51
+ "license": "MIT",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/enact-ui/enact-ui.git",
55
+ "directory": "packages/animate"
56
+ },
57
+ "bugs": {
58
+ "url": "https://github.com/enact-ui/enact-ui/issues"
59
+ },
60
+ "homepage": "https://enact-ui.com"
61
+ }