@enact-ui/backgrounds 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.
package/dist/index.js ADDED
@@ -0,0 +1,338 @@
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
+ BackgroundPaths: () => BackgroundPaths,
24
+ LightRays: () => LightRays,
25
+ LiquidGlassBackground: () => LiquidGlassBackground
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/components/background-paths.tsx
30
+ var import_animate = require("@enact-ui/animate");
31
+ var import_react = require("motion/react");
32
+ var import_react2 = require("react");
33
+ var import_jsx_runtime = require("react/jsx-runtime");
34
+ function FloatingPaths({ position, baseDuration, opacity, ease, durationVariation, prefersReducedMotion }) {
35
+ const paths = (0, import_react2.useMemo)(
36
+ () => Array.from({ length: 36 }, (_, i) => {
37
+ const durationRandom = Math.random();
38
+ return {
39
+ id: i,
40
+ d: `M-${380 - i * 5 * position} -${189 + i * 6}C-${380 - i * 5 * position} -${189 + i * 6} -${312 - i * 5 * position} ${216 - i * 6} ${152 - i * 5 * position} ${343 - i * 6}C${616 - i * 5 * position} ${470 - i * 6} ${684 - i * 5 * position} ${875 - i * 6} ${684 - i * 5 * position} ${875 - i * 6}`,
41
+ color: `rgba(15,23,42,${0.1 + i * 0.03})`,
42
+ width: 0.5 + i * 0.03,
43
+ durationRandom
44
+ };
45
+ }),
46
+ [position]
47
+ );
48
+ if (prefersReducedMotion) {
49
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pointer-events-none absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "text-muted h-full w-full", viewBox: "0 0 696 316", fill: "none", "aria-hidden": "true", children: [
50
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("title", { children: "Background Paths" }),
51
+ paths.map((path) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: path.d, stroke: "currentColor", strokeWidth: path.width, strokeOpacity: opacity[1] }, path.id))
52
+ ] }) });
53
+ }
54
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pointer-events-none absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className: "text-muted h-full w-full", viewBox: "0 0 696 316", fill: "none", "aria-hidden": "true", children: [
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("title", { children: "Background Paths" }),
56
+ paths.map((path) => {
57
+ const duration = baseDuration + baseDuration * durationVariation * path.durationRandom;
58
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
59
+ import_react.motion.path,
60
+ {
61
+ d: path.d,
62
+ stroke: "currentColor",
63
+ strokeWidth: path.width,
64
+ strokeOpacity: 0.1 + path.id * 0.03,
65
+ initial: { pathLength: 0.3, opacity: opacity[0] },
66
+ animate: {
67
+ pathLength: 1,
68
+ opacity,
69
+ pathOffset: [0, 1, 0]
70
+ },
71
+ transition: {
72
+ duration,
73
+ repeat: Number.POSITIVE_INFINITY,
74
+ ease
75
+ }
76
+ },
77
+ path.id
78
+ );
79
+ })
80
+ ] }) });
81
+ }
82
+ var BackgroundPaths = ({ preset }) => {
83
+ const motionConfig = (0, import_animate.useMotionPreset)("paths", preset);
84
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pointer-events-none relative flex h-full w-full items-center justify-center overflow-hidden", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "absolute inset-0", children: [
85
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
86
+ FloatingPaths,
87
+ {
88
+ position: 1,
89
+ baseDuration: motionConfig.baseDuration,
90
+ opacity: motionConfig.opacity,
91
+ ease: motionConfig.ease,
92
+ durationVariation: motionConfig.durationVariation,
93
+ prefersReducedMotion: motionConfig.prefersReducedMotion
94
+ }
95
+ ),
96
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
97
+ FloatingPaths,
98
+ {
99
+ position: -1,
100
+ baseDuration: motionConfig.baseDuration,
101
+ opacity: motionConfig.opacity,
102
+ ease: motionConfig.ease,
103
+ durationVariation: motionConfig.durationVariation,
104
+ prefersReducedMotion: motionConfig.prefersReducedMotion
105
+ }
106
+ )
107
+ ] }) });
108
+ };
109
+
110
+ // src/components/light-rays.tsx
111
+ var import_animate2 = require("@enact-ui/animate");
112
+ var import_react3 = require("@enact-ui/react");
113
+ var import_react4 = require("motion/react");
114
+ var import_react5 = require("react");
115
+ var import_jsx_runtime2 = require("react/jsx-runtime");
116
+ var createRays = (count, swingVariation) => {
117
+ if (count <= 0) return [];
118
+ return Array.from({ length: count }, (_, index) => {
119
+ const left = 8 + Math.random() * 84;
120
+ const rotate = -28 + Math.random() * 56;
121
+ const width = 160 + Math.random() * 160;
122
+ const swing = 0.8 + Math.random() * swingVariation;
123
+ const delay = Math.random();
124
+ const durationMultiplier = 0.75 + Math.random() * 0.5;
125
+ const intensityMultiplier = 0.6 + Math.random() * 0.5;
126
+ return {
127
+ id: `${index}-${Math.round(left * 10)}`,
128
+ left,
129
+ rotate,
130
+ width,
131
+ swing,
132
+ delay,
133
+ durationMultiplier,
134
+ intensityMultiplier
135
+ };
136
+ });
137
+ };
138
+ var Ray = ({ left, rotate, width, swing, delay, durationMultiplier, intensityMultiplier, cycleDuration, intensity, prefersReducedMotion }) => {
139
+ const computedIntensity = intensity * intensityMultiplier;
140
+ const computedDuration = cycleDuration * durationMultiplier;
141
+ const computedDelay = delay * cycleDuration;
142
+ if (prefersReducedMotion) {
143
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
144
+ "div",
145
+ {
146
+ className: "pointer-events-none absolute -top-[12%] left-[var(--ray-left)] h-[var(--light-rays-length)] w-[var(--ray-width)] origin-top -translate-x-1/2 rounded-full bg-gradient-to-b from-[color-mix(in_srgb,var(--light-rays-color)_70%,transparent)] to-transparent opacity-[var(--ray-opacity)] mix-blend-screen blur-[var(--light-rays-blur)]",
147
+ style: {
148
+ "--ray-left": `${left}%`,
149
+ "--ray-width": `${width}px`,
150
+ "--ray-opacity": computedIntensity * 0.5,
151
+ transform: `rotate(${rotate}deg)`
152
+ },
153
+ "aria-hidden": "true"
154
+ }
155
+ );
156
+ }
157
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
158
+ import_react4.motion.div,
159
+ {
160
+ className: "pointer-events-none absolute -top-[12%] left-[var(--ray-left)] h-[var(--light-rays-length)] w-[var(--ray-width)] origin-top -translate-x-1/2 rounded-full bg-gradient-to-b from-[color-mix(in_srgb,var(--light-rays-color)_70%,transparent)] to-transparent opacity-0 mix-blend-screen blur-[var(--light-rays-blur)]",
161
+ style: {
162
+ "--ray-left": `${left}%`,
163
+ "--ray-width": `${width}px`
164
+ },
165
+ initial: { rotate },
166
+ animate: {
167
+ opacity: [0, computedIntensity, 0],
168
+ rotate: [rotate - swing, rotate + swing, rotate - swing]
169
+ },
170
+ transition: {
171
+ duration: computedDuration,
172
+ repeat: Number.POSITIVE_INFINITY,
173
+ ease: "easeInOut",
174
+ delay: computedDelay,
175
+ repeatDelay: computedDuration * 0.1
176
+ },
177
+ "aria-hidden": "true"
178
+ }
179
+ );
180
+ };
181
+ var LightRays = ({
182
+ className,
183
+ style,
184
+ preset,
185
+ count = 7,
186
+ color = "rgba(160, 210, 255, 0.2)",
187
+ blur = 36,
188
+ length = "70vh",
189
+ ref,
190
+ ...props
191
+ }) => {
192
+ const motionConfig = (0, import_animate2.useMotionPreset)("rays", preset);
193
+ const rays = (0, import_react5.useMemo)(() => createRays(count, motionConfig.swingVariation), [count, motionConfig.swingVariation]);
194
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
195
+ "div",
196
+ {
197
+ ref,
198
+ className: (0, import_react3.cx)("pointer-events-none absolute inset-0 isolate overflow-hidden rounded-[inherit]", className),
199
+ style: {
200
+ "--light-rays-color": color,
201
+ "--light-rays-blur": `${blur}px`,
202
+ "--light-rays-length": length,
203
+ ...style
204
+ },
205
+ "aria-hidden": "true",
206
+ ...props,
207
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "absolute inset-0 overflow-hidden", children: [
208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
209
+ "div",
210
+ {
211
+ "aria-hidden": "true",
212
+ className: "absolute inset-0 opacity-60",
213
+ style: {
214
+ background: "radial-gradient(circle at 20% 15%, color-mix(in srgb, var(--light-rays-color) 45%, transparent), transparent 70%)"
215
+ }
216
+ }
217
+ ),
218
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
219
+ "div",
220
+ {
221
+ "aria-hidden": "true",
222
+ className: "absolute inset-0 opacity-60",
223
+ style: {
224
+ background: "radial-gradient(circle at 80% 10%, color-mix(in srgb, var(--light-rays-color) 35%, transparent), transparent 75%)"
225
+ }
226
+ }
227
+ ),
228
+ rays.map((ray) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
229
+ Ray,
230
+ {
231
+ ...ray,
232
+ cycleDuration: motionConfig.cycleDuration,
233
+ intensity: motionConfig.intensity,
234
+ prefersReducedMotion: motionConfig.prefersReducedMotion
235
+ },
236
+ ray.id
237
+ ))
238
+ ] })
239
+ }
240
+ );
241
+ };
242
+
243
+ // src/components/liquid-glass-background.tsx
244
+ var import_react6 = require("motion/react");
245
+ var import_react7 = require("react");
246
+ var import_jsx_runtime3 = require("react/jsx-runtime");
247
+ var LiquidGlassBackground = () => {
248
+ const [isDarkMode, setIsDarkMode] = (0, import_react7.useState)(false);
249
+ (0, import_react7.useEffect)(() => {
250
+ const checkDarkMode = () => {
251
+ setIsDarkMode(document.documentElement.classList.contains("dark-mode"));
252
+ };
253
+ checkDarkMode();
254
+ const observer = new MutationObserver(checkDarkMode);
255
+ observer.observe(document.documentElement, {
256
+ attributes: true,
257
+ attributeFilter: ["class"]
258
+ });
259
+ return () => observer.disconnect();
260
+ }, []);
261
+ const lightModeColors = [
262
+ "rgba(0, 212, 255, 0.15)",
263
+ // Bright cyan
264
+ "rgba(173, 230, 255, 0.12)",
265
+ // Light cyan
266
+ "rgba(102, 178, 255, 0.1)",
267
+ // Soft blue
268
+ "rgba(0, 153, 204, 0.08)"
269
+ // Deeper cyan
270
+ ];
271
+ const darkModeColors = [
272
+ "rgba(0, 102, 255, 0.2)",
273
+ // Deep blue
274
+ "rgba(51, 153, 255, 0.15)",
275
+ // Bright blue
276
+ "rgba(102, 178, 255, 0.12)",
277
+ // Light blue
278
+ "rgba(0, 51, 204, 0.1)"
279
+ // Dark blue
280
+ ];
281
+ const colors = isDarkMode ? darkModeColors : lightModeColors;
282
+ const prefersReducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
283
+ const orbVariants = {
284
+ animate: {
285
+ x: prefersReducedMotion ? 0 : [0, 100, -80, 60, -40, 0],
286
+ y: prefersReducedMotion ? 0 : [0, -80, 60, -50, 40, 0],
287
+ scale: prefersReducedMotion ? 1 : [1, 1.3, 0.8, 1.2, 0.9, 1]
288
+ }
289
+ };
290
+ const transition = {
291
+ duration: prefersReducedMotion ? 0 : 12,
292
+ repeat: Infinity,
293
+ ease: "easeInOut"
294
+ };
295
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "pointer-events-none fixed inset-0 -z-10 overflow-hidden", "aria-hidden": "true", children: [
296
+ colors.map((color, index) => {
297
+ const size = 400 + index * 120;
298
+ const initialX = 10 + index * 30;
299
+ const initialY = 20 + index * 25;
300
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
301
+ import_react6.motion.div,
302
+ {
303
+ className: "absolute rounded-full blur-3xl",
304
+ style: {
305
+ width: `${size}px`,
306
+ height: `${size}px`,
307
+ background: `radial-gradient(circle, ${color} 0%, transparent 70%)`,
308
+ left: `${initialX}%`,
309
+ top: `${initialY}%`
310
+ },
311
+ variants: orbVariants,
312
+ animate: "animate",
313
+ transition: {
314
+ ...transition,
315
+ delay: index * 1.5
316
+ }
317
+ },
318
+ color
319
+ );
320
+ }),
321
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
322
+ "div",
323
+ {
324
+ className: "absolute inset-0 opacity-30",
325
+ style: {
326
+ background: isDarkMode ? "radial-gradient(circle at 50% 50%, rgba(0, 102, 255, 0.1) 0%, transparent 70%)" : "radial-gradient(circle at 50% 50%, rgba(0, 212, 255, 0.08) 0%, transparent 70%)"
327
+ }
328
+ }
329
+ )
330
+ ] });
331
+ };
332
+ // Annotate the CommonJS export names for ESM import in node:
333
+ 0 && (module.exports = {
334
+ BackgroundPaths,
335
+ LightRays,
336
+ LiquidGlassBackground
337
+ });
338
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/background-paths.tsx","../src/components/light-rays.tsx","../src/components/liquid-glass-background.tsx"],"sourcesContent":["// Copyright (c) 2025 Amsterdam Data Labs\n// @enact-ui/backgrounds - Decorative background effects\n\n/**\n * @enact-ui/backgrounds\n *\n * Decorative background effects for ENACT UI.\n * Purely cosmetic - can be removed without functional impact.\n *\n * Requires: @enact-ui/react (for cx utility)\n * Requires: @enact-ui/animate (for motion presets)\n * Requires: motion/react (for animations)\n *\n * @packageDocumentation\n */\n\n// =============================================================================\n// Background Components\n// =============================================================================\nexport { BackgroundPaths, type BackgroundPathsProps } from \"./components/background-paths\";\nexport { LightRays, type LightRaysProps } from \"./components/light-rays\";\nexport { LiquidGlassBackground } from \"./components/liquid-glass-background\";\n","// Copyright (c) 2025 Amsterdam Data Labs\n\"use client\";\n\nimport { type MotionPreset, useMotionPreset } from \"@enact-ui/animate\";\nimport { motion } from \"motion/react\";\nimport { type FC, useMemo } from \"react\";\n\ninterface FloatingPathsProps {\n position: number;\n baseDuration: number;\n opacity: [number, number, number];\n ease: \"linear\" | \"easeInOut\";\n durationVariation: number;\n prefersReducedMotion: boolean;\n}\n\nfunction FloatingPaths({ position, baseDuration, opacity, ease, durationVariation, prefersReducedMotion }: FloatingPathsProps) {\n // Memoize path calculations and random values to prevent regeneration on re-render\n const paths = useMemo(\n () =>\n Array.from({ length: 36 }, (_, i) => {\n // Generate stable random variations per path\n const durationRandom = Math.random();\n return {\n id: i,\n d: `M-${380 - i * 5 * position} -${189 + i * 6}C-${380 - i * 5 * position} -${189 + i * 6} -${312 - i * 5 * position} ${216 - i * 6} ${\n 152 - i * 5 * position\n } ${343 - i * 6}C${616 - i * 5 * position} ${470 - i * 6} ${\n 684 - i * 5 * position\n } ${875 - i * 6} ${684 - i * 5 * position} ${875 - i * 6}`,\n color: `rgba(15,23,42,${0.1 + i * 0.03})`,\n width: 0.5 + i * 0.03,\n durationRandom,\n };\n }),\n [position],\n );\n\n // If reduced motion is preferred, render static paths\n if (prefersReducedMotion) {\n return (\n <div className=\"pointer-events-none absolute inset-0\">\n <svg className=\"text-muted h-full w-full\" viewBox=\"0 0 696 316\" fill=\"none\" aria-hidden=\"true\">\n <title>Background Paths</title>\n {paths.map((path) => (\n <path key={path.id} d={path.d} stroke=\"currentColor\" strokeWidth={path.width} strokeOpacity={opacity[1]} />\n ))}\n </svg>\n </div>\n );\n }\n\n return (\n <div className=\"pointer-events-none absolute inset-0\">\n <svg className=\"text-muted h-full w-full\" viewBox=\"0 0 696 316\" fill=\"none\" aria-hidden=\"true\">\n <title>Background Paths</title>\n {paths.map((path) => {\n // Calculate duration with preset-based variation\n const duration = baseDuration + baseDuration * durationVariation * path.durationRandom;\n\n return (\n <motion.path\n key={path.id}\n d={path.d}\n stroke=\"currentColor\"\n strokeWidth={path.width}\n strokeOpacity={0.1 + path.id * 0.03}\n initial={{ pathLength: 0.3, opacity: opacity[0] }}\n animate={{\n pathLength: 1,\n opacity: opacity,\n pathOffset: [0, 1, 0],\n }}\n transition={{\n duration,\n repeat: Number.POSITIVE_INFINITY,\n ease,\n }}\n />\n );\n })}\n </svg>\n </div>\n );\n}\n\nexport interface BackgroundPathsProps {\n /** Motion preset - controls animation speed and intensity (required) */\n preset: MotionPreset;\n}\n\n/**\n * BackgroundPaths Component\n *\n * Renders animated SVG paths for ambient background effects.\n * Uses the motion preset system for theme-aware, configurable animations.\n *\n * @example\n * ```tsx\n * <BackgroundPaths preset=\"medium\" />\n * <BackgroundPaths preset=\"slow\" />\n * <BackgroundPaths preset=\"fast\" />\n * ```\n */\nexport const BackgroundPaths: FC<BackgroundPathsProps> = ({ preset }) => {\n const motionConfig = useMotionPreset(\"paths\", preset);\n\n return (\n <div className=\"pointer-events-none relative flex h-full w-full items-center justify-center overflow-hidden\" aria-hidden=\"true\">\n <div className=\"absolute inset-0\">\n <FloatingPaths\n position={1}\n baseDuration={motionConfig.baseDuration}\n opacity={motionConfig.opacity}\n ease={motionConfig.ease}\n durationVariation={motionConfig.durationVariation}\n prefersReducedMotion={motionConfig.prefersReducedMotion}\n />\n <FloatingPaths\n position={-1}\n baseDuration={motionConfig.baseDuration}\n opacity={motionConfig.opacity}\n ease={motionConfig.ease}\n durationVariation={motionConfig.durationVariation}\n prefersReducedMotion={motionConfig.prefersReducedMotion}\n />\n </div>\n </div>\n );\n};\n","// Copyright (c) 2025 Amsterdam Data Labs\n\"use client\";\n\nimport { type MotionPreset, useMotionPreset } from \"@enact-ui/animate\";\nimport { cx } from \"@enact-ui/react\";\nimport { type MotionStyle, motion } from \"motion/react\";\nimport { type CSSProperties, type FC, useMemo } from \"react\";\n\n/**\n * LightRays Component\n *\n * Adapted from MagicUI (MIT Licensed)\n * Original source: https://github.com/magicuidesign/magicui/blob/main/apps/www/registry/magicui/light-rays.tsx\n * Reference files: references/magicui-lightrays/\n *\n * Creates animated light rays that shine from above, perfect for ambient background effects.\n * Uses CSS gradients and motion animations - no Three.js dependencies required.\n *\n * Uses the motion preset system for theme-aware, configurable animations.\n */\nexport interface LightRaysProps extends React.HTMLAttributes<HTMLDivElement> {\n ref?: React.Ref<HTMLDivElement>;\n /** Motion preset - controls animation speed and intensity (required) */\n preset: MotionPreset;\n /** Number of light rays to render */\n count?: number;\n /** Color of the light rays (CSS color value) */\n color?: string;\n /** Blur amount in pixels */\n blur?: number;\n /** Length of the rays (CSS length value) */\n length?: string;\n}\n\ntype LightRay = {\n id: string;\n left: number;\n rotate: number;\n width: number;\n swing: number;\n delay: number;\n durationMultiplier: number;\n intensityMultiplier: number;\n};\n\nconst createRays = (count: number, swingVariation: number): LightRay[] => {\n if (count <= 0) return [];\n\n return Array.from({ length: count }, (_, index) => {\n const left = 8 + Math.random() * 84;\n const rotate = -28 + Math.random() * 56;\n const width = 160 + Math.random() * 160;\n const swing = 0.8 + Math.random() * swingVariation;\n const delay = Math.random();\n const durationMultiplier = 0.75 + Math.random() * 0.5;\n const intensityMultiplier = 0.6 + Math.random() * 0.5;\n\n return {\n id: `${index}-${Math.round(left * 10)}`,\n left,\n rotate,\n width,\n swing,\n delay,\n durationMultiplier,\n intensityMultiplier,\n };\n });\n};\n\ninterface RayProps extends LightRay {\n cycleDuration: number;\n intensity: number;\n prefersReducedMotion: boolean;\n}\n\nconst Ray: FC<RayProps> = ({ left, rotate, width, swing, delay, durationMultiplier, intensityMultiplier, cycleDuration, intensity, prefersReducedMotion }) => {\n const computedIntensity = intensity * intensityMultiplier;\n const computedDuration = cycleDuration * durationMultiplier;\n const computedDelay = delay * cycleDuration;\n\n // If reduced motion is preferred, render static ray\n if (prefersReducedMotion) {\n return (\n <div\n className=\"pointer-events-none absolute -top-[12%] left-[var(--ray-left)] h-[var(--light-rays-length)] w-[var(--ray-width)] origin-top -translate-x-1/2 rounded-full bg-gradient-to-b from-[color-mix(in_srgb,var(--light-rays-color)_70%,transparent)] to-transparent opacity-[var(--ray-opacity)] mix-blend-screen blur-[var(--light-rays-blur)]\"\n style={\n {\n \"--ray-left\": `${left}%`,\n \"--ray-width\": `${width}px`,\n \"--ray-opacity\": computedIntensity * 0.5,\n transform: `rotate(${rotate}deg)`,\n } as CSSProperties\n }\n aria-hidden=\"true\"\n />\n );\n }\n\n return (\n <motion.div\n className=\"pointer-events-none absolute -top-[12%] left-[var(--ray-left)] h-[var(--light-rays-length)] w-[var(--ray-width)] origin-top -translate-x-1/2 rounded-full bg-gradient-to-b from-[color-mix(in_srgb,var(--light-rays-color)_70%,transparent)] to-transparent opacity-0 mix-blend-screen blur-[var(--light-rays-blur)]\"\n style={\n {\n \"--ray-left\": `${left}%`,\n \"--ray-width\": `${width}px`,\n } as MotionStyle\n }\n initial={{ rotate: rotate }}\n animate={{\n opacity: [0, computedIntensity, 0],\n rotate: [rotate - swing, rotate + swing, rotate - swing],\n }}\n transition={{\n duration: computedDuration,\n repeat: Number.POSITIVE_INFINITY,\n ease: \"easeInOut\",\n delay: computedDelay,\n repeatDelay: computedDuration * 0.1,\n }}\n aria-hidden=\"true\"\n />\n );\n};\n\n/**\n * LightRays Component\n *\n * Creates animated light rays that shine from above, perfect for ambient background effects.\n * Uses the motion preset system for theme-aware, configurable animations.\n *\n * @example\n * ```tsx\n * <LightRays preset=\"medium\" />\n * <LightRays preset=\"slow\" count={5} color=\"rgba(160, 210, 255, 0.3)\" />\n * <LightRays preset=\"fast\" blur={48} length=\"80vh\" />\n * ```\n */\nexport const LightRays: FC<LightRaysProps> = ({\n className,\n style,\n preset,\n count = 7,\n color = \"rgba(160, 210, 255, 0.2)\",\n blur = 36,\n length = \"70vh\",\n ref,\n ...props\n}) => {\n const motionConfig = useMotionPreset(\"rays\", preset);\n\n // Memoize rays creation based on count and swingVariation\n const rays = useMemo(() => createRays(count, motionConfig.swingVariation), [count, motionConfig.swingVariation]);\n\n return (\n <div\n ref={ref}\n className={cx(\"pointer-events-none absolute inset-0 isolate overflow-hidden rounded-[inherit]\", className)}\n style={\n {\n \"--light-rays-color\": color,\n \"--light-rays-blur\": `${blur}px`,\n \"--light-rays-length\": length,\n ...style,\n } as CSSProperties\n }\n aria-hidden=\"true\"\n {...props}\n >\n <div className=\"absolute inset-0 overflow-hidden\">\n <div\n aria-hidden=\"true\"\n className=\"absolute inset-0 opacity-60\"\n style={\n {\n background: \"radial-gradient(circle at 20% 15%, color-mix(in srgb, var(--light-rays-color) 45%, transparent), transparent 70%)\",\n } as CSSProperties\n }\n />\n <div\n aria-hidden=\"true\"\n className=\"absolute inset-0 opacity-60\"\n style={\n {\n background: \"radial-gradient(circle at 80% 10%, color-mix(in srgb, var(--light-rays-color) 35%, transparent), transparent 75%)\",\n } as CSSProperties\n }\n />\n {rays.map((ray) => (\n <Ray\n key={ray.id}\n {...ray}\n cycleDuration={motionConfig.cycleDuration}\n intensity={motionConfig.intensity}\n prefersReducedMotion={motionConfig.prefersReducedMotion}\n />\n ))}\n </div>\n </div>\n );\n};\n","// Copyright (c) 2025 Amsterdam Data Labs\n\"use client\";\n\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\nimport { useEffect, useState } from \"react\";\n\n/**\n * LiquidGlassBackground Component\n *\n * Provides a subtle animated background for the liquid glass theme.\n * Features floating gradient orbs with gentle movements that showcase\n * glassmorphism effects without being distracting.\n */\nexport const LiquidGlassBackground: React.FC = () => {\n const [isDarkMode, setIsDarkMode] = useState(false);\n\n useEffect(() => {\n // Check for dark mode class on document element\n const checkDarkMode = () => {\n setIsDarkMode(document.documentElement.classList.contains(\"dark-mode\"));\n };\n\n checkDarkMode();\n\n // Watch for dark mode changes\n const observer = new MutationObserver(checkDarkMode);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n\n return () => observer.disconnect();\n }, []);\n\n // Color gradients for light and dark modes\n const lightModeColors = [\n \"rgba(0, 212, 255, 0.15)\", // Bright cyan\n \"rgba(173, 230, 255, 0.12)\", // Light cyan\n \"rgba(102, 178, 255, 0.1)\", // Soft blue\n \"rgba(0, 153, 204, 0.08)\", // Deeper cyan\n ];\n\n const darkModeColors = [\n \"rgba(0, 102, 255, 0.2)\", // Deep blue\n \"rgba(51, 153, 255, 0.15)\", // Bright blue\n \"rgba(102, 178, 255, 0.12)\", // Light blue\n \"rgba(0, 51, 204, 0.1)\", // Dark blue\n ];\n\n const colors = isDarkMode ? darkModeColors : lightModeColors;\n\n // Check for reduced motion preference\n const prefersReducedMotion = typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n // Animation variants - more pronounced movement for visible distortion\n const orbVariants = {\n animate: {\n x: prefersReducedMotion ? 0 : [0, 100, -80, 60, -40, 0],\n y: prefersReducedMotion ? 0 : [0, -80, 60, -50, 40, 0],\n scale: prefersReducedMotion ? 1 : [1, 1.3, 0.8, 1.2, 0.9, 1],\n },\n };\n\n const transition = {\n duration: prefersReducedMotion ? 0 : 12,\n repeat: Infinity,\n ease: \"easeInOut\" as const,\n };\n\n return (\n <div className=\"pointer-events-none fixed inset-0 -z-10 overflow-hidden\" aria-hidden=\"true\">\n {/* Floating Orbs */}\n {colors.map((color, index) => {\n const size = 400 + index * 120;\n const initialX = 10 + index * 30;\n const initialY = 20 + index * 25;\n\n return (\n <motion.div\n key={color}\n className=\"absolute rounded-full blur-3xl\"\n style={{\n width: `${size}px`,\n height: `${size}px`,\n background: `radial-gradient(circle, ${color} 0%, transparent 70%)`,\n left: `${initialX}%`,\n top: `${initialY}%`,\n }}\n variants={orbVariants}\n animate=\"animate\"\n transition={{\n ...transition,\n delay: index * 1.5,\n }}\n />\n );\n })}\n\n {/* Subtle gradient overlay for depth */}\n <div\n className=\"absolute inset-0 opacity-30\"\n style={{\n background: isDarkMode\n ? \"radial-gradient(circle at 50% 50%, rgba(0, 102, 255, 0.1) 0%, transparent 70%)\"\n : \"radial-gradient(circle at 50% 50%, rgba(0, 212, 255, 0.08) 0%, transparent 70%)\",\n }}\n />\n </div>\n );\n};\n\nexport default LiquidGlassBackground;\n"],"mappings":"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","names":["import_react","import_animate","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}