premium-react-loaders 4.0.0 → 4.1.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.
Files changed (162) hide show
  1. package/dist/components/index.d.ts +1 -0
  2. package/dist/components/index.d.ts.map +1 -1
  3. package/dist/components/neon/NeonPulse.d.ts +12 -0
  4. package/dist/components/neon/NeonPulse.d.ts.map +1 -0
  5. package/dist/components/neon/NeonSpinner.d.ts +12 -0
  6. package/dist/components/neon/NeonSpinner.d.ts.map +1 -0
  7. package/dist/components/neon/NeonText.d.ts +12 -0
  8. package/dist/components/neon/NeonText.d.ts.map +1 -0
  9. package/dist/components/neon/index.d.ts +4 -0
  10. package/dist/components/neon/index.d.ts.map +1 -0
  11. package/dist/components/particle/ParticleField.d.ts +3 -0
  12. package/dist/components/particle/ParticleField.d.ts.map +1 -0
  13. package/dist/components/particle/ParticleTrail.d.ts +12 -0
  14. package/dist/components/particle/ParticleTrail.d.ts.map +1 -0
  15. package/dist/components/particle/index.d.ts +2 -0
  16. package/dist/components/particle/index.d.ts.map +1 -1
  17. package/dist/components/status/InfoIndicator.d.ts +29 -0
  18. package/dist/components/status/InfoIndicator.d.ts.map +1 -0
  19. package/dist/components/status/WarningIndicator.d.ts +29 -0
  20. package/dist/components/status/WarningIndicator.d.ts.map +1 -0
  21. package/dist/components/status/index.d.ts +2 -0
  22. package/dist/components/status/index.d.ts.map +1 -1
  23. package/dist/index.cjs +41 -27
  24. package/dist/index.js +41 -27
  25. package/dist/index10.cjs +1 -1
  26. package/dist/index10.js +1 -1
  27. package/dist/index11.cjs +1 -1
  28. package/dist/index11.js +1 -1
  29. package/dist/index12.cjs +1 -1
  30. package/dist/index12.js +1 -1
  31. package/dist/index13.cjs +1 -1
  32. package/dist/index13.js +1 -1
  33. package/dist/index14.cjs +1 -1
  34. package/dist/index14.js +1 -1
  35. package/dist/index15.cjs +1 -1
  36. package/dist/index15.js +1 -1
  37. package/dist/index17.cjs +1 -1
  38. package/dist/index17.js +1 -1
  39. package/dist/index18.cjs +1 -1
  40. package/dist/index18.js +1 -1
  41. package/dist/index19.cjs +1 -1
  42. package/dist/index19.js +1 -1
  43. package/dist/index20.cjs +1 -1
  44. package/dist/index20.js +1 -1
  45. package/dist/index21.cjs +1 -1
  46. package/dist/index21.js +1 -1
  47. package/dist/index22.cjs +1 -1
  48. package/dist/index22.js +1 -1
  49. package/dist/index23.cjs +1 -1
  50. package/dist/index23.js +1 -1
  51. package/dist/index24.cjs +1 -1
  52. package/dist/index24.js +1 -1
  53. package/dist/index25.cjs +1 -1
  54. package/dist/index25.js +1 -1
  55. package/dist/index26.cjs +1 -1
  56. package/dist/index26.js +1 -1
  57. package/dist/index27.cjs +1 -1
  58. package/dist/index27.js +1 -1
  59. package/dist/index28.cjs +1 -1
  60. package/dist/index28.js +1 -1
  61. package/dist/index29.cjs +1 -1
  62. package/dist/index29.js +1 -1
  63. package/dist/index30.cjs +1 -1
  64. package/dist/index30.js +1 -1
  65. package/dist/index31.cjs +1 -1
  66. package/dist/index31.js +1 -1
  67. package/dist/index32.cjs +1 -1
  68. package/dist/index32.js +1 -1
  69. package/dist/index33.cjs +1 -1
  70. package/dist/index33.js +1 -1
  71. package/dist/index34.cjs +1 -1
  72. package/dist/index34.js +1 -1
  73. package/dist/index35.cjs +1 -1
  74. package/dist/index35.js +1 -1
  75. package/dist/index36.cjs +1 -1
  76. package/dist/index36.js +1 -1
  77. package/dist/index37.cjs +59 -145
  78. package/dist/index37.js +61 -147
  79. package/dist/index38.cjs +32 -53
  80. package/dist/index38.js +33 -54
  81. package/dist/index39.cjs +138 -84
  82. package/dist/index39.js +140 -86
  83. package/dist/index40.cjs +33 -106
  84. package/dist/index40.js +34 -107
  85. package/dist/index41.cjs +66 -50
  86. package/dist/index41.js +66 -50
  87. package/dist/index42.cjs +123 -44
  88. package/dist/index42.js +124 -45
  89. package/dist/index43.cjs +43 -85
  90. package/dist/index43.js +44 -86
  91. package/dist/index44.cjs +35 -27
  92. package/dist/index44.js +35 -27
  93. package/dist/index45.cjs +87 -58
  94. package/dist/index45.js +87 -58
  95. package/dist/index46.cjs +35 -88
  96. package/dist/index46.js +36 -89
  97. package/dist/index47.cjs +62 -58
  98. package/dist/index47.js +63 -59
  99. package/dist/index48.cjs +87 -110
  100. package/dist/index48.js +88 -111
  101. package/dist/index49.cjs +48 -109
  102. package/dist/index49.js +49 -110
  103. package/dist/index50.cjs +110 -62
  104. package/dist/index50.js +111 -63
  105. package/dist/index51.cjs +104 -49
  106. package/dist/index51.js +104 -49
  107. package/dist/index52.cjs +43 -77
  108. package/dist/index52.js +44 -78
  109. package/dist/index53.cjs +56 -56
  110. package/dist/index53.js +56 -56
  111. package/dist/index54.cjs +104 -149
  112. package/dist/index54.js +106 -151
  113. package/dist/index55.cjs +97 -38
  114. package/dist/index55.js +99 -40
  115. package/dist/index56.cjs +161 -27
  116. package/dist/index56.js +162 -28
  117. package/dist/index57.cjs +36 -102
  118. package/dist/index57.js +38 -104
  119. package/dist/index58.cjs +19 -34
  120. package/dist/index58.js +20 -35
  121. package/dist/index59.cjs +87 -34
  122. package/dist/index59.js +89 -36
  123. package/dist/index60.cjs +25 -23
  124. package/dist/index60.js +25 -23
  125. package/dist/index61.cjs +32 -65
  126. package/dist/index61.js +34 -67
  127. package/dist/index62.cjs +29 -36
  128. package/dist/index62.js +30 -37
  129. package/dist/index63.cjs +66 -59
  130. package/dist/index63.js +69 -62
  131. package/dist/index64.cjs +71 -121
  132. package/dist/index64.js +72 -122
  133. package/dist/index65.cjs +92 -0
  134. package/dist/index65.js +92 -0
  135. package/dist/index66.cjs +76 -0
  136. package/dist/index66.js +76 -0
  137. package/dist/index67.cjs +76 -0
  138. package/dist/index67.js +76 -0
  139. package/dist/index68.cjs +64 -0
  140. package/dist/index68.js +64 -0
  141. package/dist/index69.cjs +60 -0
  142. package/dist/index69.js +60 -0
  143. package/dist/index7.cjs +1 -1
  144. package/dist/index7.js +1 -1
  145. package/dist/index70.cjs +57 -0
  146. package/dist/index70.js +57 -0
  147. package/dist/index71.cjs +125 -0
  148. package/dist/index71.js +125 -0
  149. package/dist/index8.cjs +1 -1
  150. package/dist/index8.js +1 -1
  151. package/dist/index9.cjs +1 -1
  152. package/dist/index9.js +1 -1
  153. package/dist/premium-react-loaders.css +85 -0
  154. package/dist/types/index.d.ts +1 -0
  155. package/dist/types/index.d.ts.map +1 -1
  156. package/dist/types/neon.d.ts +26 -0
  157. package/dist/types/neon.d.ts.map +1 -0
  158. package/dist/types/particle.d.ts +18 -0
  159. package/dist/types/particle.d.ts.map +1 -1
  160. package/dist/types/status.d.ts +30 -0
  161. package/dist/types/status.d.ts.map +1 -1
  162. package/package.json +1 -1
package/dist/index64.js CHANGED
@@ -1,125 +1,75 @@
1
- import { useState, useRef, useEffect } from "react";
2
- function useReducedMotion() {
3
- const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
4
- useEffect(() => {
5
- if (typeof window === "undefined" || !window.matchMedia) {
6
- return;
7
- }
8
- const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
9
- setPrefersReducedMotion(mediaQuery.matches);
10
- const handleChange = (event) => {
11
- setPrefersReducedMotion(event.matches);
12
- };
13
- if (mediaQuery.addEventListener) {
14
- mediaQuery.addEventListener("change", handleChange);
15
- return () => mediaQuery.removeEventListener("change", handleChange);
16
- } else {
17
- mediaQuery.addListener(handleChange);
18
- return () => mediaQuery.removeListener(handleChange);
19
- }
20
- }, []);
21
- return prefersReducedMotion;
22
- }
23
- function getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion) {
24
- if (respectMotionPreference && prefersReducedMotion) {
25
- return "0.01ms";
26
- }
27
- if (typeof speed === "number") {
28
- const validSpeed = !isNaN(speed) && speed > 0 ? Math.max(50, Math.min(1e4, speed)) : 1e3;
29
- return `${validSpeed}ms`;
30
- }
31
- const speedMap = {
32
- slow: "2s",
33
- normal: "1s",
34
- fast: "0.5s"
35
- };
36
- return speedMap[speed] || speedMap.normal;
37
- }
38
- function useLoaderVisibility(visible = true, delay = 0, minDuration = 0, transition) {
39
- const transitionDuration = transition === true ? 150 : typeof transition === "number" ? transition : 0;
40
- const hasTransition = transitionDuration > 0;
41
- const [shouldRender, setShouldRender] = useState(visible && delay === 0);
42
- const [isTransitioning, setIsTransitioning] = useState(visible && delay === 0 && hasTransition);
43
- const showTimeRef = useRef(visible && delay === 0 ? Date.now() : null);
44
- const delayTimerRef = useRef(null);
45
- const minDurationTimerRef = useRef(null);
46
- const transitionTimerRef = useRef(null);
47
- useEffect(() => {
48
- if (delayTimerRef.current) {
49
- clearTimeout(delayTimerRef.current);
50
- delayTimerRef.current = null;
51
- }
52
- if (minDurationTimerRef.current) {
53
- clearTimeout(minDurationTimerRef.current);
54
- minDurationTimerRef.current = null;
55
- }
56
- if (transitionTimerRef.current) {
57
- clearTimeout(transitionTimerRef.current);
58
- transitionTimerRef.current = null;
59
- }
60
- if (visible) {
61
- if (delay > 0) {
62
- delayTimerRef.current = setTimeout(() => {
63
- setShouldRender(true);
64
- showTimeRef.current = Date.now();
65
- if (hasTransition) {
66
- setIsTransitioning(true);
67
- }
68
- }, delay);
69
- } else {
70
- setShouldRender(true);
71
- showTimeRef.current = Date.now();
72
- if (hasTransition) {
73
- setIsTransitioning(true);
74
- }
75
- }
76
- } else {
77
- const hideLoader = () => {
78
- if (hasTransition) {
79
- setIsTransitioning(false);
80
- transitionTimerRef.current = setTimeout(() => {
81
- setShouldRender(false);
82
- showTimeRef.current = null;
83
- }, transitionDuration);
84
- } else {
85
- setShouldRender(false);
86
- showTimeRef.current = null;
87
- }
88
- };
89
- if (showTimeRef.current !== null && minDuration > 0) {
90
- const elapsedTime = Date.now() - showTimeRef.current;
91
- const remainingTime = minDuration - elapsedTime;
92
- if (remainingTime > 0) {
93
- minDurationTimerRef.current = setTimeout(hideLoader, remainingTime);
94
- } else {
95
- hideLoader();
96
- }
97
- } else {
98
- hideLoader();
99
- }
100
- }
101
- return () => {
102
- if (delayTimerRef.current) {
103
- clearTimeout(delayTimerRef.current);
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index71.js";
4
+ import { parseDurationMs } from "./index4.js";
5
+ import { cn } from "./index3.js";
6
+ const ParticleBurst = forwardRef(
7
+ ({
8
+ size = 60,
9
+ count = 8,
10
+ color = "#3b82f6",
11
+ particleSize = 6,
12
+ speed = "normal",
13
+ respectMotionPreference = true,
14
+ delay = 0,
15
+ minDuration = 0,
16
+ transition,
17
+ className,
18
+ style,
19
+ testId = "particle-burst",
20
+ visible = true,
21
+ ariaLabel = "Loading...",
22
+ ...rest
23
+ }, ref) => {
24
+ const prefersReducedMotion = useReducedMotion();
25
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
+ const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
27
+ if (!shouldRender) return null;
28
+ const clampedCount = Math.min(20, Math.max(4, count));
29
+ const radius = size / 2;
30
+ const durationMs = parseDurationMs(effectiveDuration);
31
+ return /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ ref,
35
+ "data-testid": testId,
36
+ className: cn("relative inline-flex items-center justify-center", className),
37
+ style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
38
+ role: "status",
39
+ "aria-label": ariaLabel,
40
+ "aria-busy": "true",
41
+ ...rest,
42
+ children: Array.from({ length: clampedCount }, (_, i) => {
43
+ const angle = i / clampedCount * 2 * Math.PI;
44
+ const tx = Math.cos(angle) * radius;
45
+ const ty = Math.sin(angle) * radius;
46
+ const animationDelay = `${i / clampedCount * durationMs}ms`;
47
+ return /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ className: "absolute rounded-full",
51
+ style: {
52
+ width: particleSize,
53
+ height: particleSize,
54
+ backgroundColor: color,
55
+ top: "50%",
56
+ left: "50%",
57
+ marginTop: -particleSize / 2,
58
+ marginLeft: -particleSize / 2,
59
+ animation: `particle-burst ${effectiveDuration} ease-out infinite`,
60
+ animationDelay,
61
+ ["--tx"]: `${tx}px`,
62
+ ["--ty"]: `${ty}px`
63
+ }
64
+ },
65
+ i
66
+ );
67
+ })
104
68
  }
105
- if (minDurationTimerRef.current) {
106
- clearTimeout(minDurationTimerRef.current);
107
- }
108
- if (transitionTimerRef.current) {
109
- clearTimeout(transitionTimerRef.current);
110
- }
111
- };
112
- }, [visible, delay, minDuration, hasTransition, transitionDuration]);
113
- const opacity = hasTransition ? isTransitioning ? 1 : 0 : 1;
114
- const transitionStyle = hasTransition ? `opacity ${transitionDuration}ms ease-in-out` : "none";
115
- return {
116
- shouldRender,
117
- opacity,
118
- transitionStyle
119
- };
120
- }
69
+ );
70
+ }
71
+ );
72
+ ParticleBurst.displayName = "ParticleBurst";
121
73
  export {
122
- getEffectiveDuration,
123
- useLoaderVisibility,
124
- useReducedMotion
74
+ ParticleBurst
125
75
  };
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const hooks = require("./index71.cjs");
6
+ const colors = require("./index4.cjs");
7
+ const classNames = require("./index3.cjs");
8
+ const ParticleOrbit = react.forwardRef(
9
+ ({
10
+ size = 80,
11
+ count = 5,
12
+ color = "#3b82f6",
13
+ centerColor,
14
+ speed = "normal",
15
+ respectMotionPreference = true,
16
+ delay = 0,
17
+ minDuration = 0,
18
+ transition,
19
+ className,
20
+ style,
21
+ testId = "particle-orbit",
22
+ visible = true,
23
+ ariaLabel = "Loading...",
24
+ ...rest
25
+ }, ref) => {
26
+ const prefersReducedMotion = hooks.useReducedMotion();
27
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
28
+ const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(visible, delay, minDuration, transition);
29
+ if (!shouldRender) return null;
30
+ const clampedCount = Math.min(8, Math.max(3, count));
31
+ const orbitRadius = size * 0.35;
32
+ const particleSize = size * 0.1;
33
+ const centerSize = size * 0.15;
34
+ const dotColor = centerColor || color;
35
+ const durationMs = colors.parseDurationMs(effectiveDuration);
36
+ return /* @__PURE__ */ jsxRuntime.jsxs(
37
+ "div",
38
+ {
39
+ ref,
40
+ "data-testid": testId,
41
+ className: classNames.cn("relative inline-flex items-center justify-center", className),
42
+ style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
43
+ role: "status",
44
+ "aria-label": ariaLabel,
45
+ "aria-busy": "true",
46
+ ...rest,
47
+ children: [
48
+ /* @__PURE__ */ jsxRuntime.jsx(
49
+ "div",
50
+ {
51
+ className: "absolute rounded-full z-10",
52
+ style: {
53
+ width: centerSize,
54
+ height: centerSize,
55
+ backgroundColor: dotColor,
56
+ top: "50%",
57
+ left: "50%",
58
+ transform: "translate(-50%, -50%)"
59
+ }
60
+ }
61
+ ),
62
+ Array.from({ length: clampedCount }, (_, i) => {
63
+ const startAngle = `${i / clampedCount * 360}deg`;
64
+ const staggerDelay = `-${i / clampedCount * durationMs}ms`;
65
+ return /* @__PURE__ */ jsxRuntime.jsx(
66
+ "div",
67
+ {
68
+ className: "absolute rounded-full",
69
+ style: {
70
+ width: particleSize,
71
+ height: particleSize,
72
+ backgroundColor: color,
73
+ top: "50%",
74
+ left: "50%",
75
+ marginTop: -particleSize / 2,
76
+ marginLeft: -particleSize / 2,
77
+ animation: `particle-orbit ${effectiveDuration} linear infinite`,
78
+ animationDelay: staggerDelay,
79
+ ["--start-angle"]: startAngle,
80
+ ["--orbit-radius"]: `${orbitRadius}px`
81
+ }
82
+ },
83
+ i
84
+ );
85
+ })
86
+ ]
87
+ }
88
+ );
89
+ }
90
+ );
91
+ ParticleOrbit.displayName = "ParticleOrbit";
92
+ exports.ParticleOrbit = ParticleOrbit;
@@ -0,0 +1,92 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index71.js";
4
+ import { parseDurationMs } from "./index4.js";
5
+ import { cn } from "./index3.js";
6
+ const ParticleOrbit = forwardRef(
7
+ ({
8
+ size = 80,
9
+ count = 5,
10
+ color = "#3b82f6",
11
+ centerColor,
12
+ speed = "normal",
13
+ respectMotionPreference = true,
14
+ delay = 0,
15
+ minDuration = 0,
16
+ transition,
17
+ className,
18
+ style,
19
+ testId = "particle-orbit",
20
+ visible = true,
21
+ ariaLabel = "Loading...",
22
+ ...rest
23
+ }, ref) => {
24
+ const prefersReducedMotion = useReducedMotion();
25
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
+ const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
27
+ if (!shouldRender) return null;
28
+ const clampedCount = Math.min(8, Math.max(3, count));
29
+ const orbitRadius = size * 0.35;
30
+ const particleSize = size * 0.1;
31
+ const centerSize = size * 0.15;
32
+ const dotColor = centerColor || color;
33
+ const durationMs = parseDurationMs(effectiveDuration);
34
+ return /* @__PURE__ */ jsxs(
35
+ "div",
36
+ {
37
+ ref,
38
+ "data-testid": testId,
39
+ className: cn("relative inline-flex items-center justify-center", className),
40
+ style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
41
+ role: "status",
42
+ "aria-label": ariaLabel,
43
+ "aria-busy": "true",
44
+ ...rest,
45
+ children: [
46
+ /* @__PURE__ */ jsx(
47
+ "div",
48
+ {
49
+ className: "absolute rounded-full z-10",
50
+ style: {
51
+ width: centerSize,
52
+ height: centerSize,
53
+ backgroundColor: dotColor,
54
+ top: "50%",
55
+ left: "50%",
56
+ transform: "translate(-50%, -50%)"
57
+ }
58
+ }
59
+ ),
60
+ Array.from({ length: clampedCount }, (_, i) => {
61
+ const startAngle = `${i / clampedCount * 360}deg`;
62
+ const staggerDelay = `-${i / clampedCount * durationMs}ms`;
63
+ return /* @__PURE__ */ jsx(
64
+ "div",
65
+ {
66
+ className: "absolute rounded-full",
67
+ style: {
68
+ width: particleSize,
69
+ height: particleSize,
70
+ backgroundColor: color,
71
+ top: "50%",
72
+ left: "50%",
73
+ marginTop: -particleSize / 2,
74
+ marginLeft: -particleSize / 2,
75
+ animation: `particle-orbit ${effectiveDuration} linear infinite`,
76
+ animationDelay: staggerDelay,
77
+ ["--start-angle"]: startAngle,
78
+ ["--orbit-radius"]: `${orbitRadius}px`
79
+ }
80
+ },
81
+ i
82
+ );
83
+ })
84
+ ]
85
+ }
86
+ );
87
+ }
88
+ );
89
+ ParticleOrbit.displayName = "ParticleOrbit";
90
+ export {
91
+ ParticleOrbit
92
+ };
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const hooks = require("./index71.cjs");
6
+ const colors = require("./index4.cjs");
7
+ const classNames = require("./index3.cjs");
8
+ const ParticleTrail = react.forwardRef(
9
+ ({
10
+ size = 60,
11
+ count = 6,
12
+ color = "#3b82f6",
13
+ speed = "normal",
14
+ respectMotionPreference = true,
15
+ delay = 0,
16
+ minDuration = 0,
17
+ transition,
18
+ className,
19
+ style,
20
+ testId = "particle-trail",
21
+ visible = true,
22
+ ariaLabel = "Loading...",
23
+ ...rest
24
+ }, ref) => {
25
+ const prefersReducedMotion = hooks.useReducedMotion();
26
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
27
+ const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(visible, delay, minDuration, transition);
28
+ if (!shouldRender) return null;
29
+ const clampedCount = Math.min(10, Math.max(3, count));
30
+ const orbitRadius = size * 0.35;
31
+ const particleSize = Math.max(3, size * 0.08);
32
+ const durationMs = colors.parseDurationMs(effectiveDuration);
33
+ return /* @__PURE__ */ jsxRuntime.jsx(
34
+ "div",
35
+ {
36
+ ref,
37
+ "data-testid": testId,
38
+ className: classNames.cn("relative inline-flex items-center justify-center", className),
39
+ style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
40
+ role: "status",
41
+ "aria-label": ariaLabel,
42
+ "aria-busy": "true",
43
+ ...rest,
44
+ children: Array.from({ length: clampedCount }, (_, i) => {
45
+ const trailOpacity = 1 - i / clampedCount * 0.85;
46
+ const trailScale = 1 - i / clampedCount * 0.6;
47
+ const startAngle = `${i / clampedCount * 360}deg`;
48
+ const staggerDelay = `-${i / clampedCount * durationMs}ms`;
49
+ return /* @__PURE__ */ jsxRuntime.jsx(
50
+ "div",
51
+ {
52
+ className: "absolute rounded-full animate-particle-trail",
53
+ style: {
54
+ width: particleSize * trailScale,
55
+ height: particleSize * trailScale,
56
+ backgroundColor: color,
57
+ top: "50%",
58
+ left: "50%",
59
+ marginTop: -(particleSize * trailScale) / 2,
60
+ marginLeft: -(particleSize * trailScale) / 2,
61
+ opacity: trailOpacity,
62
+ animationDuration: effectiveDuration,
63
+ animationDelay: staggerDelay,
64
+ ["--start-angle"]: startAngle,
65
+ ["--orbit-radius"]: `${orbitRadius}px`
66
+ }
67
+ },
68
+ i
69
+ );
70
+ })
71
+ }
72
+ );
73
+ }
74
+ );
75
+ ParticleTrail.displayName = "ParticleTrail";
76
+ exports.ParticleTrail = ParticleTrail;
@@ -0,0 +1,76 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index71.js";
4
+ import { parseDurationMs } from "./index4.js";
5
+ import { cn } from "./index3.js";
6
+ const ParticleTrail = forwardRef(
7
+ ({
8
+ size = 60,
9
+ count = 6,
10
+ color = "#3b82f6",
11
+ speed = "normal",
12
+ respectMotionPreference = true,
13
+ delay = 0,
14
+ minDuration = 0,
15
+ transition,
16
+ className,
17
+ style,
18
+ testId = "particle-trail",
19
+ visible = true,
20
+ ariaLabel = "Loading...",
21
+ ...rest
22
+ }, ref) => {
23
+ const prefersReducedMotion = useReducedMotion();
24
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
25
+ const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
26
+ if (!shouldRender) return null;
27
+ const clampedCount = Math.min(10, Math.max(3, count));
28
+ const orbitRadius = size * 0.35;
29
+ const particleSize = Math.max(3, size * 0.08);
30
+ const durationMs = parseDurationMs(effectiveDuration);
31
+ return /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ ref,
35
+ "data-testid": testId,
36
+ className: cn("relative inline-flex items-center justify-center", className),
37
+ style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
38
+ role: "status",
39
+ "aria-label": ariaLabel,
40
+ "aria-busy": "true",
41
+ ...rest,
42
+ children: Array.from({ length: clampedCount }, (_, i) => {
43
+ const trailOpacity = 1 - i / clampedCount * 0.85;
44
+ const trailScale = 1 - i / clampedCount * 0.6;
45
+ const startAngle = `${i / clampedCount * 360}deg`;
46
+ const staggerDelay = `-${i / clampedCount * durationMs}ms`;
47
+ return /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ className: "absolute rounded-full animate-particle-trail",
51
+ style: {
52
+ width: particleSize * trailScale,
53
+ height: particleSize * trailScale,
54
+ backgroundColor: color,
55
+ top: "50%",
56
+ left: "50%",
57
+ marginTop: -(particleSize * trailScale) / 2,
58
+ marginLeft: -(particleSize * trailScale) / 2,
59
+ opacity: trailOpacity,
60
+ animationDuration: effectiveDuration,
61
+ animationDelay: staggerDelay,
62
+ ["--start-angle"]: startAngle,
63
+ ["--orbit-radius"]: `${orbitRadius}px`
64
+ }
65
+ },
66
+ i
67
+ );
68
+ })
69
+ }
70
+ );
71
+ }
72
+ );
73
+ ParticleTrail.displayName = "ParticleTrail";
74
+ export {
75
+ ParticleTrail
76
+ };
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const hooks = require("./index71.cjs");
6
+ const classNames = require("./index3.cjs");
7
+ const ParticleField = react.forwardRef(
8
+ ({
9
+ width = 120,
10
+ height = 120,
11
+ count = 12,
12
+ color = "#3b82f6",
13
+ speed = "normal",
14
+ respectMotionPreference = true,
15
+ delay = 0,
16
+ minDuration = 0,
17
+ transition,
18
+ className,
19
+ style,
20
+ testId = "particle-field",
21
+ visible = true,
22
+ ariaLabel = "Loading...",
23
+ ...rest
24
+ }, ref) => {
25
+ const prefersReducedMotion = hooks.useReducedMotion();
26
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
27
+ const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(visible, delay, minDuration, transition);
28
+ if (!shouldRender) return null;
29
+ const clampedCount = Math.min(30, Math.max(5, count));
30
+ const particles = Array.from({ length: clampedCount }, (_, i) => {
31
+ const seed = i * 137.508;
32
+ const x = seed * 7.3 % width;
33
+ const drift = seed * 3.1 % 20 - 10;
34
+ const size = 2 + seed % 4;
35
+ const particleOpacity = 0.4 + seed % 0.6;
36
+ const durationMultiplier = 0.6 + i / clampedCount * 0.8;
37
+ const delayMs = -(i / clampedCount * 3e3);
38
+ return { x, drift, size, particleOpacity, durationMultiplier, delayMs };
39
+ });
40
+ return /* @__PURE__ */ jsxRuntime.jsx(
41
+ "div",
42
+ {
43
+ ref,
44
+ "data-testid": testId,
45
+ className: classNames.cn("relative inline-block overflow-hidden", className),
46
+ style: { width, height, opacity, transition: transitionStyle, ...style },
47
+ role: "status",
48
+ "aria-label": ariaLabel,
49
+ "aria-busy": "true",
50
+ ...rest,
51
+ children: particles.map(({ x, drift, size: pSize, particleOpacity, durationMultiplier, delayMs }, i) => /* @__PURE__ */ jsxRuntime.jsx(
52
+ "div",
53
+ {
54
+ className: "absolute rounded-full animate-particle-field-float",
55
+ style: {
56
+ width: pSize,
57
+ height: pSize,
58
+ backgroundColor: color,
59
+ left: x,
60
+ bottom: 0,
61
+ animationDuration: `calc(${effectiveDuration} * ${durationMultiplier})`,
62
+ animationDelay: `${delayMs}ms`,
63
+ ["--tx-start"]: `${drift}px`,
64
+ ["--tx-end"]: `${drift * 1.5}px`,
65
+ ["--field-height"]: `${height}px`,
66
+ ["--particle-opacity"]: `${particleOpacity}`
67
+ }
68
+ },
69
+ i
70
+ ))
71
+ }
72
+ );
73
+ }
74
+ );
75
+ ParticleField.displayName = "ParticleField";
76
+ exports.ParticleField = ParticleField;