premium-react-loaders 4.0.0 → 4.1.1

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 (163) hide show
  1. package/README.md +21 -6
  2. package/dist/components/index.d.ts +1 -0
  3. package/dist/components/index.d.ts.map +1 -1
  4. package/dist/components/neon/NeonPulse.d.ts +12 -0
  5. package/dist/components/neon/NeonPulse.d.ts.map +1 -0
  6. package/dist/components/neon/NeonSpinner.d.ts +12 -0
  7. package/dist/components/neon/NeonSpinner.d.ts.map +1 -0
  8. package/dist/components/neon/NeonText.d.ts +12 -0
  9. package/dist/components/neon/NeonText.d.ts.map +1 -0
  10. package/dist/components/neon/index.d.ts +4 -0
  11. package/dist/components/neon/index.d.ts.map +1 -0
  12. package/dist/components/particle/ParticleField.d.ts +3 -0
  13. package/dist/components/particle/ParticleField.d.ts.map +1 -0
  14. package/dist/components/particle/ParticleTrail.d.ts +12 -0
  15. package/dist/components/particle/ParticleTrail.d.ts.map +1 -0
  16. package/dist/components/particle/index.d.ts +2 -0
  17. package/dist/components/particle/index.d.ts.map +1 -1
  18. package/dist/components/status/InfoIndicator.d.ts +29 -0
  19. package/dist/components/status/InfoIndicator.d.ts.map +1 -0
  20. package/dist/components/status/WarningIndicator.d.ts +29 -0
  21. package/dist/components/status/WarningIndicator.d.ts.map +1 -0
  22. package/dist/components/status/index.d.ts +2 -0
  23. package/dist/components/status/index.d.ts.map +1 -1
  24. package/dist/index.cjs +41 -27
  25. package/dist/index.js +41 -27
  26. package/dist/index10.cjs +1 -1
  27. package/dist/index10.js +1 -1
  28. package/dist/index11.cjs +1 -1
  29. package/dist/index11.js +1 -1
  30. package/dist/index12.cjs +1 -1
  31. package/dist/index12.js +1 -1
  32. package/dist/index13.cjs +1 -1
  33. package/dist/index13.js +1 -1
  34. package/dist/index14.cjs +1 -1
  35. package/dist/index14.js +1 -1
  36. package/dist/index15.cjs +1 -1
  37. package/dist/index15.js +1 -1
  38. package/dist/index17.cjs +1 -1
  39. package/dist/index17.js +1 -1
  40. package/dist/index18.cjs +1 -1
  41. package/dist/index18.js +1 -1
  42. package/dist/index19.cjs +1 -1
  43. package/dist/index19.js +1 -1
  44. package/dist/index20.cjs +1 -1
  45. package/dist/index20.js +1 -1
  46. package/dist/index21.cjs +1 -1
  47. package/dist/index21.js +1 -1
  48. package/dist/index22.cjs +1 -1
  49. package/dist/index22.js +1 -1
  50. package/dist/index23.cjs +1 -1
  51. package/dist/index23.js +1 -1
  52. package/dist/index24.cjs +1 -1
  53. package/dist/index24.js +1 -1
  54. package/dist/index25.cjs +1 -1
  55. package/dist/index25.js +1 -1
  56. package/dist/index26.cjs +1 -1
  57. package/dist/index26.js +1 -1
  58. package/dist/index27.cjs +1 -1
  59. package/dist/index27.js +1 -1
  60. package/dist/index28.cjs +1 -1
  61. package/dist/index28.js +1 -1
  62. package/dist/index29.cjs +1 -1
  63. package/dist/index29.js +1 -1
  64. package/dist/index30.cjs +1 -1
  65. package/dist/index30.js +1 -1
  66. package/dist/index31.cjs +1 -1
  67. package/dist/index31.js +1 -1
  68. package/dist/index32.cjs +1 -1
  69. package/dist/index32.js +1 -1
  70. package/dist/index33.cjs +1 -1
  71. package/dist/index33.js +1 -1
  72. package/dist/index34.cjs +1 -1
  73. package/dist/index34.js +1 -1
  74. package/dist/index35.cjs +1 -1
  75. package/dist/index35.js +1 -1
  76. package/dist/index36.cjs +1 -1
  77. package/dist/index36.js +1 -1
  78. package/dist/index37.cjs +59 -145
  79. package/dist/index37.js +61 -147
  80. package/dist/index38.cjs +32 -53
  81. package/dist/index38.js +33 -54
  82. package/dist/index39.cjs +138 -84
  83. package/dist/index39.js +140 -86
  84. package/dist/index40.cjs +33 -106
  85. package/dist/index40.js +34 -107
  86. package/dist/index41.cjs +66 -50
  87. package/dist/index41.js +66 -50
  88. package/dist/index42.cjs +123 -44
  89. package/dist/index42.js +124 -45
  90. package/dist/index43.cjs +43 -85
  91. package/dist/index43.js +44 -86
  92. package/dist/index44.cjs +35 -27
  93. package/dist/index44.js +35 -27
  94. package/dist/index45.cjs +87 -58
  95. package/dist/index45.js +87 -58
  96. package/dist/index46.cjs +35 -88
  97. package/dist/index46.js +36 -89
  98. package/dist/index47.cjs +62 -58
  99. package/dist/index47.js +63 -59
  100. package/dist/index48.cjs +87 -110
  101. package/dist/index48.js +88 -111
  102. package/dist/index49.cjs +48 -109
  103. package/dist/index49.js +49 -110
  104. package/dist/index50.cjs +110 -62
  105. package/dist/index50.js +111 -63
  106. package/dist/index51.cjs +104 -49
  107. package/dist/index51.js +104 -49
  108. package/dist/index52.cjs +43 -77
  109. package/dist/index52.js +44 -78
  110. package/dist/index53.cjs +56 -56
  111. package/dist/index53.js +56 -56
  112. package/dist/index54.cjs +104 -149
  113. package/dist/index54.js +106 -151
  114. package/dist/index55.cjs +97 -38
  115. package/dist/index55.js +99 -40
  116. package/dist/index56.cjs +161 -27
  117. package/dist/index56.js +162 -28
  118. package/dist/index57.cjs +36 -102
  119. package/dist/index57.js +38 -104
  120. package/dist/index58.cjs +19 -34
  121. package/dist/index58.js +20 -35
  122. package/dist/index59.cjs +87 -34
  123. package/dist/index59.js +89 -36
  124. package/dist/index60.cjs +25 -23
  125. package/dist/index60.js +25 -23
  126. package/dist/index61.cjs +32 -65
  127. package/dist/index61.js +34 -67
  128. package/dist/index62.cjs +29 -36
  129. package/dist/index62.js +30 -37
  130. package/dist/index63.cjs +66 -59
  131. package/dist/index63.js +69 -62
  132. package/dist/index64.cjs +71 -121
  133. package/dist/index64.js +72 -122
  134. package/dist/index65.cjs +92 -0
  135. package/dist/index65.js +92 -0
  136. package/dist/index66.cjs +76 -0
  137. package/dist/index66.js +76 -0
  138. package/dist/index67.cjs +76 -0
  139. package/dist/index67.js +76 -0
  140. package/dist/index68.cjs +64 -0
  141. package/dist/index68.js +64 -0
  142. package/dist/index69.cjs +60 -0
  143. package/dist/index69.js +60 -0
  144. package/dist/index7.cjs +1 -1
  145. package/dist/index7.js +1 -1
  146. package/dist/index70.cjs +57 -0
  147. package/dist/index70.js +57 -0
  148. package/dist/index71.cjs +125 -0
  149. package/dist/index71.js +125 -0
  150. package/dist/index8.cjs +1 -1
  151. package/dist/index8.js +1 -1
  152. package/dist/index9.cjs +1 -1
  153. package/dist/index9.js +1 -1
  154. package/dist/premium-react-loaders.css +85 -0
  155. package/dist/types/index.d.ts +1 -0
  156. package/dist/types/index.d.ts.map +1 -1
  157. package/dist/types/neon.d.ts +26 -0
  158. package/dist/types/neon.d.ts.map +1 -0
  159. package/dist/types/particle.d.ts +18 -0
  160. package/dist/types/particle.d.ts.map +1 -1
  161. package/dist/types/status.d.ts +30 -0
  162. package/dist/types/status.d.ts.map +1 -1
  163. package/package.json +1 -1
package/dist/index57.js CHANGED
@@ -1,119 +1,53 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { forwardRef, useRef, useEffect } from "react";
3
- import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index64.js";
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useState, useRef, useEffect } from "react";
4
3
  import { cn } from "./index3.js";
5
- const LiquidFill = forwardRef(
4
+ const LiveRegion = forwardRef(
6
5
  ({
7
- value,
8
- size = 80,
9
- color = "#3b82f6",
10
- waveAmplitude = 4,
11
- onComplete,
12
- speed = "normal",
13
- respectMotionPreference = true,
14
- delay = 0,
15
- minDuration = 0,
16
- transition,
17
- className,
18
- style,
19
- testId = "liquid-fill",
20
- visible = true,
21
- ariaLabel,
22
- ...rest
6
+ message,
7
+ politeness = "polite",
8
+ clearAfter,
9
+ atomic = true,
10
+ relevant = "additions",
11
+ className
23
12
  }, ref) => {
24
- const prefersReducedMotion = useReducedMotion();
25
- const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
- const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
27
- const onCompleteRef = useRef(onComplete);
28
- onCompleteRef.current = onComplete;
29
- const isIndeterminate = value === void 0;
30
- const clampedValue = isIndeterminate ? 50 : Math.min(100, Math.max(0, value));
13
+ const [displayMessage, setDisplayMessage] = useState(message);
14
+ const clearTimerRef = useRef(null);
31
15
  useEffect(() => {
32
- if (!isIndeterminate && clampedValue === 100 && onCompleteRef.current) {
33
- onCompleteRef.current();
16
+ setDisplayMessage(message);
17
+ if (clearTimerRef.current) {
18
+ clearTimeout(clearTimerRef.current);
19
+ clearTimerRef.current = null;
34
20
  }
35
- }, [clampedValue, isIndeterminate]);
36
- if (!shouldRender) return null;
37
- const progressLabel = ariaLabel || (isIndeterminate ? "Loading..." : `Loading ${clampedValue}%`);
38
- const fillBottom = `${clampedValue}%`;
21
+ if (clearAfter && message) {
22
+ clearTimerRef.current = setTimeout(() => {
23
+ setDisplayMessage("");
24
+ }, clearAfter);
25
+ }
26
+ return () => {
27
+ if (clearTimerRef.current) {
28
+ clearTimeout(clearTimerRef.current);
29
+ }
30
+ };
31
+ }, [message, clearAfter]);
39
32
  return /* @__PURE__ */ jsx(
40
33
  "div",
41
34
  {
42
35
  ref,
43
- "data-testid": testId,
44
- className: cn("inline-flex items-center justify-center", className),
45
- style: { opacity, transition: transitionStyle, ...style },
46
- role: "status",
47
- "aria-label": progressLabel,
48
- "aria-busy": "true",
49
- ...rest,
50
- children: /* @__PURE__ */ jsxs(
51
- "div",
52
- {
53
- className: "relative overflow-hidden rounded-full",
54
- style: { width: size, height: size },
55
- children: [
56
- /* @__PURE__ */ jsx(
57
- "div",
58
- {
59
- className: "absolute inset-0 rounded-full",
60
- style: { backgroundColor: `${color}20` }
61
- }
62
- ),
63
- /* @__PURE__ */ jsxs(
64
- "div",
65
- {
66
- className: "absolute left-0 right-0 bottom-0",
67
- style: {
68
- height: fillBottom,
69
- transition: isIndeterminate ? void 0 : "height 0.4s ease-in-out",
70
- overflow: "hidden"
71
- },
72
- children: [
73
- /* @__PURE__ */ jsx(
74
- "div",
75
- {
76
- style: {
77
- position: "absolute",
78
- top: -waveAmplitude * 2,
79
- left: 0,
80
- width: "200%",
81
- height: waveAmplitude * 4,
82
- backgroundColor: color,
83
- borderRadius: "40%",
84
- animation: `liquid-wave ${effectiveDuration} linear infinite`
85
- }
86
- }
87
- ),
88
- /* @__PURE__ */ jsx(
89
- "div",
90
- {
91
- className: "absolute bottom-0 left-0 right-0",
92
- style: { backgroundColor: color, top: waveAmplitude * 2 }
93
- }
94
- )
95
- ]
96
- }
97
- ),
98
- !isIndeterminate && /* @__PURE__ */ jsxs(
99
- "span",
100
- {
101
- className: "absolute inset-0 flex items-center justify-center text-xs font-bold",
102
- style: { color: clampedValue > 50 ? "#fff" : color },
103
- children: [
104
- clampedValue,
105
- "%"
106
- ]
107
- }
108
- )
109
- ]
110
- }
111
- )
36
+ className: cn(
37
+ // Visually hidden but accessible to screen readers
38
+ "sr-only absolute w-px h-px p-0 -m-px overflow-hidden whitespace-nowrap border-0",
39
+ className
40
+ ),
41
+ role: politeness === "assertive" ? "alert" : "status",
42
+ "aria-live": politeness,
43
+ "aria-atomic": atomic,
44
+ "aria-relevant": relevant,
45
+ children: displayMessage
112
46
  }
113
47
  );
114
48
  }
115
49
  );
116
- LiquidFill.displayName = "LiquidFill";
50
+ LiveRegion.displayName = "LiveRegion";
117
51
  export {
118
- LiquidFill
52
+ LiveRegion
119
53
  };
package/dist/index58.cjs CHANGED
@@ -2,14 +2,12 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
- const colors = require("./index4.cjs");
6
- const hooks = require("./index64.cjs");
5
+ const hooks = require("./index71.cjs");
7
6
  const classNames = require("./index3.cjs");
8
- const WaveCircle = react.forwardRef(
7
+ const MorphBlob = react.forwardRef(
9
8
  ({
10
9
  size = 80,
11
10
  color = "#3b82f6",
12
- ringCount = 3,
13
11
  speed = "normal",
14
12
  respectMotionPreference = true,
15
13
  delay = 0,
@@ -17,7 +15,7 @@ const WaveCircle = react.forwardRef(
17
15
  transition,
18
16
  className,
19
17
  style,
20
- testId = "wave-circle",
18
+ testId = "morph-blob",
21
19
  visible = true,
22
20
  ariaLabel = "Loading...",
23
21
  ...rest
@@ -26,45 +24,32 @@ const WaveCircle = react.forwardRef(
26
24
  const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
27
25
  const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(visible, delay, minDuration, transition);
28
26
  if (!shouldRender) return null;
29
- const clampedCount = Math.min(5, Math.max(2, ringCount));
30
- const durationMs = colors.parseDurationMs(effectiveDuration);
31
- return /* @__PURE__ */ jsxRuntime.jsxs(
27
+ return /* @__PURE__ */ jsxRuntime.jsx(
32
28
  "div",
33
29
  {
34
30
  ref,
35
31
  "data-testid": testId,
36
- className: classNames.cn("relative inline-flex items-center justify-center", className),
37
- style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
32
+ className: classNames.cn("inline-flex items-center justify-center", className),
33
+ style: { opacity, transition: transitionStyle, ...style },
38
34
  role: "status",
39
35
  "aria-label": ariaLabel,
40
36
  "aria-busy": "true",
41
37
  ...rest,
42
- children: [
43
- /* @__PURE__ */ jsxRuntime.jsx(
44
- "div",
45
- {
46
- className: "absolute rounded-full z-10",
47
- style: { width: size * 0.15, height: size * 0.15, backgroundColor: color }
38
+ children: /* @__PURE__ */ jsxRuntime.jsx(
39
+ "div",
40
+ {
41
+ style: {
42
+ width: size,
43
+ height: size,
44
+ backgroundColor: color,
45
+ borderRadius: "60% 40% 30% 70% / 60% 30% 70% 40%",
46
+ animation: `morph-blob ${effectiveDuration} ease-in-out infinite`
48
47
  }
49
- ),
50
- Array.from({ length: clampedCount }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx(
51
- "div",
52
- {
53
- className: "absolute rounded-full border-2",
54
- style: {
55
- width: size,
56
- height: size,
57
- borderColor: color,
58
- animation: `wave-circle-expand ${effectiveDuration} ease-out infinite`,
59
- animationDelay: `${i / clampedCount * durationMs}ms`
60
- }
61
- },
62
- i
63
- ))
64
- ]
48
+ }
49
+ )
65
50
  }
66
51
  );
67
52
  }
68
53
  );
69
- WaveCircle.displayName = "WaveCircle";
70
- exports.WaveCircle = WaveCircle;
54
+ MorphBlob.displayName = "MorphBlob";
55
+ exports.MorphBlob = MorphBlob;
package/dist/index58.js CHANGED
@@ -1,13 +1,11 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
1
+ import { jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { parseDurationMs } from "./index4.js";
4
- import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index64.js";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index71.js";
5
4
  import { cn } from "./index3.js";
6
- const WaveCircle = forwardRef(
5
+ const MorphBlob = forwardRef(
7
6
  ({
8
7
  size = 80,
9
8
  color = "#3b82f6",
10
- ringCount = 3,
11
9
  speed = "normal",
12
10
  respectMotionPreference = true,
13
11
  delay = 0,
@@ -15,7 +13,7 @@ const WaveCircle = forwardRef(
15
13
  transition,
16
14
  className,
17
15
  style,
18
- testId = "wave-circle",
16
+ testId = "morph-blob",
19
17
  visible = true,
20
18
  ariaLabel = "Loading...",
21
19
  ...rest
@@ -24,47 +22,34 @@ const WaveCircle = forwardRef(
24
22
  const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
25
23
  const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
26
24
  if (!shouldRender) return null;
27
- const clampedCount = Math.min(5, Math.max(2, ringCount));
28
- const durationMs = parseDurationMs(effectiveDuration);
29
- return /* @__PURE__ */ jsxs(
25
+ return /* @__PURE__ */ jsx(
30
26
  "div",
31
27
  {
32
28
  ref,
33
29
  "data-testid": testId,
34
- className: cn("relative inline-flex items-center justify-center", className),
35
- style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
30
+ className: cn("inline-flex items-center justify-center", className),
31
+ style: { opacity, transition: transitionStyle, ...style },
36
32
  role: "status",
37
33
  "aria-label": ariaLabel,
38
34
  "aria-busy": "true",
39
35
  ...rest,
40
- children: [
41
- /* @__PURE__ */ jsx(
42
- "div",
43
- {
44
- className: "absolute rounded-full z-10",
45
- style: { width: size * 0.15, height: size * 0.15, backgroundColor: color }
36
+ children: /* @__PURE__ */ jsx(
37
+ "div",
38
+ {
39
+ style: {
40
+ width: size,
41
+ height: size,
42
+ backgroundColor: color,
43
+ borderRadius: "60% 40% 30% 70% / 60% 30% 70% 40%",
44
+ animation: `morph-blob ${effectiveDuration} ease-in-out infinite`
46
45
  }
47
- ),
48
- Array.from({ length: clampedCount }, (_, i) => /* @__PURE__ */ jsx(
49
- "div",
50
- {
51
- className: "absolute rounded-full border-2",
52
- style: {
53
- width: size,
54
- height: size,
55
- borderColor: color,
56
- animation: `wave-circle-expand ${effectiveDuration} ease-out infinite`,
57
- animationDelay: `${i / clampedCount * durationMs}ms`
58
- }
59
- },
60
- i
61
- ))
62
- ]
46
+ }
47
+ )
63
48
  }
64
49
  );
65
50
  }
66
51
  );
67
- WaveCircle.displayName = "WaveCircle";
52
+ MorphBlob.displayName = "MorphBlob";
68
53
  export {
69
- WaveCircle
54
+ MorphBlob
70
55
  };
package/dist/index59.cjs CHANGED
@@ -2,15 +2,15 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
- const hooks = require("./index64.cjs");
5
+ const hooks = require("./index71.cjs");
6
6
  const classNames = require("./index3.cjs");
7
- const GradientSpinner = react.forwardRef(
7
+ const LiquidFill = react.forwardRef(
8
8
  ({
9
- size = 48,
9
+ value,
10
+ size = 80,
10
11
  color = "#3b82f6",
11
- secondaryColor = "#8b5cf6",
12
- thickness = 4,
13
- backgroundColor = "white",
12
+ waveAmplitude = 4,
13
+ onComplete,
14
14
  speed = "normal",
15
15
  respectMotionPreference = true,
16
16
  delay = 0,
@@ -18,49 +18,102 @@ const GradientSpinner = react.forwardRef(
18
18
  transition,
19
19
  className,
20
20
  style,
21
- testId = "gradient-spinner",
21
+ testId = "liquid-fill",
22
22
  visible = true,
23
- ariaLabel = "Loading...",
23
+ ariaLabel,
24
24
  ...rest
25
25
  }, ref) => {
26
26
  const prefersReducedMotion = hooks.useReducedMotion();
27
27
  const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
28
28
  const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(visible, delay, minDuration, transition);
29
+ const onCompleteRef = react.useRef(onComplete);
30
+ onCompleteRef.current = onComplete;
31
+ const isIndeterminate = value === void 0;
32
+ const clampedValue = isIndeterminate ? 50 : Math.min(100, Math.max(0, value));
33
+ react.useEffect(() => {
34
+ if (!isIndeterminate && clampedValue === 100 && onCompleteRef.current) {
35
+ onCompleteRef.current();
36
+ }
37
+ }, [clampedValue, isIndeterminate]);
29
38
  if (!shouldRender) return null;
30
- const inner = size - thickness * 2;
31
- return /* @__PURE__ */ jsxRuntime.jsxs(
39
+ const progressLabel = ariaLabel || (isIndeterminate ? "Loading..." : `Loading ${clampedValue}%`);
40
+ const fillBottom = `${clampedValue}%`;
41
+ return /* @__PURE__ */ jsxRuntime.jsx(
32
42
  "div",
33
43
  {
34
44
  ref,
35
45
  "data-testid": testId,
36
- className: classNames.cn("relative inline-flex items-center justify-center", className),
37
- style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
46
+ className: classNames.cn("inline-flex items-center justify-center", className),
47
+ style: { opacity, transition: transitionStyle, ...style },
38
48
  role: "status",
39
- "aria-label": ariaLabel,
49
+ "aria-label": progressLabel,
40
50
  "aria-busy": "true",
41
51
  ...rest,
42
- children: [
43
- /* @__PURE__ */ jsxRuntime.jsx(
44
- "div",
45
- {
46
- className: "absolute inset-0 rounded-full",
47
- style: {
48
- background: `conic-gradient(from 0deg, ${color}, ${secondaryColor}, transparent)`,
49
- animation: `gradient-spin ${effectiveDuration} linear infinite`
50
- }
51
- }
52
- ),
53
- /* @__PURE__ */ jsxRuntime.jsx(
54
- "div",
55
- {
56
- className: "absolute rounded-full",
57
- style: { width: inner, height: inner, backgroundColor }
58
- }
59
- )
60
- ]
52
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
53
+ "div",
54
+ {
55
+ className: "relative overflow-hidden rounded-full",
56
+ style: { width: size, height: size },
57
+ children: [
58
+ /* @__PURE__ */ jsxRuntime.jsx(
59
+ "div",
60
+ {
61
+ className: "absolute inset-0 rounded-full",
62
+ style: { backgroundColor: `${color}20` }
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsxRuntime.jsxs(
66
+ "div",
67
+ {
68
+ className: "absolute left-0 right-0 bottom-0",
69
+ style: {
70
+ height: fillBottom,
71
+ transition: isIndeterminate ? void 0 : "height 0.4s ease-in-out",
72
+ overflow: "hidden"
73
+ },
74
+ children: [
75
+ /* @__PURE__ */ jsxRuntime.jsx(
76
+ "div",
77
+ {
78
+ style: {
79
+ position: "absolute",
80
+ top: -waveAmplitude * 2,
81
+ left: 0,
82
+ width: "200%",
83
+ height: waveAmplitude * 4,
84
+ backgroundColor: color,
85
+ borderRadius: "40%",
86
+ animation: `liquid-wave ${effectiveDuration} linear infinite`
87
+ }
88
+ }
89
+ ),
90
+ /* @__PURE__ */ jsxRuntime.jsx(
91
+ "div",
92
+ {
93
+ className: "absolute bottom-0 left-0 right-0",
94
+ style: { backgroundColor: color, top: waveAmplitude * 2 }
95
+ }
96
+ )
97
+ ]
98
+ }
99
+ ),
100
+ !isIndeterminate && /* @__PURE__ */ jsxRuntime.jsxs(
101
+ "span",
102
+ {
103
+ className: "absolute inset-0 flex items-center justify-center text-xs font-bold",
104
+ style: { color: clampedValue > 50 ? "#fff" : color },
105
+ children: [
106
+ clampedValue,
107
+ "%"
108
+ ]
109
+ }
110
+ )
111
+ ]
112
+ }
113
+ )
61
114
  }
62
115
  );
63
116
  }
64
117
  );
65
- GradientSpinner.displayName = "GradientSpinner";
66
- exports.GradientSpinner = GradientSpinner;
118
+ LiquidFill.displayName = "LiquidFill";
119
+ exports.LiquidFill = LiquidFill;
package/dist/index59.js CHANGED
@@ -1,14 +1,14 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { forwardRef } from "react";
3
- import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index64.js";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useRef, useEffect } from "react";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index71.js";
4
4
  import { cn } from "./index3.js";
5
- const GradientSpinner = forwardRef(
5
+ const LiquidFill = forwardRef(
6
6
  ({
7
- size = 48,
7
+ value,
8
+ size = 80,
8
9
  color = "#3b82f6",
9
- secondaryColor = "#8b5cf6",
10
- thickness = 4,
11
- backgroundColor = "white",
10
+ waveAmplitude = 4,
11
+ onComplete,
12
12
  speed = "normal",
13
13
  respectMotionPreference = true,
14
14
  delay = 0,
@@ -16,51 +16,104 @@ const GradientSpinner = forwardRef(
16
16
  transition,
17
17
  className,
18
18
  style,
19
- testId = "gradient-spinner",
19
+ testId = "liquid-fill",
20
20
  visible = true,
21
- ariaLabel = "Loading...",
21
+ ariaLabel,
22
22
  ...rest
23
23
  }, ref) => {
24
24
  const prefersReducedMotion = useReducedMotion();
25
25
  const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
26
  const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(visible, delay, minDuration, transition);
27
+ const onCompleteRef = useRef(onComplete);
28
+ onCompleteRef.current = onComplete;
29
+ const isIndeterminate = value === void 0;
30
+ const clampedValue = isIndeterminate ? 50 : Math.min(100, Math.max(0, value));
31
+ useEffect(() => {
32
+ if (!isIndeterminate && clampedValue === 100 && onCompleteRef.current) {
33
+ onCompleteRef.current();
34
+ }
35
+ }, [clampedValue, isIndeterminate]);
27
36
  if (!shouldRender) return null;
28
- const inner = size - thickness * 2;
29
- return /* @__PURE__ */ jsxs(
37
+ const progressLabel = ariaLabel || (isIndeterminate ? "Loading..." : `Loading ${clampedValue}%`);
38
+ const fillBottom = `${clampedValue}%`;
39
+ return /* @__PURE__ */ jsx(
30
40
  "div",
31
41
  {
32
42
  ref,
33
43
  "data-testid": testId,
34
- className: cn("relative inline-flex items-center justify-center", className),
35
- style: { width: size, height: size, opacity, transition: transitionStyle, ...style },
44
+ className: cn("inline-flex items-center justify-center", className),
45
+ style: { opacity, transition: transitionStyle, ...style },
36
46
  role: "status",
37
- "aria-label": ariaLabel,
47
+ "aria-label": progressLabel,
38
48
  "aria-busy": "true",
39
49
  ...rest,
40
- children: [
41
- /* @__PURE__ */ jsx(
42
- "div",
43
- {
44
- className: "absolute inset-0 rounded-full",
45
- style: {
46
- background: `conic-gradient(from 0deg, ${color}, ${secondaryColor}, transparent)`,
47
- animation: `gradient-spin ${effectiveDuration} linear infinite`
48
- }
49
- }
50
- ),
51
- /* @__PURE__ */ jsx(
52
- "div",
53
- {
54
- className: "absolute rounded-full",
55
- style: { width: inner, height: inner, backgroundColor }
56
- }
57
- )
58
- ]
50
+ children: /* @__PURE__ */ jsxs(
51
+ "div",
52
+ {
53
+ className: "relative overflow-hidden rounded-full",
54
+ style: { width: size, height: size },
55
+ children: [
56
+ /* @__PURE__ */ jsx(
57
+ "div",
58
+ {
59
+ className: "absolute inset-0 rounded-full",
60
+ style: { backgroundColor: `${color}20` }
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ className: "absolute left-0 right-0 bottom-0",
67
+ style: {
68
+ height: fillBottom,
69
+ transition: isIndeterminate ? void 0 : "height 0.4s ease-in-out",
70
+ overflow: "hidden"
71
+ },
72
+ children: [
73
+ /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ style: {
77
+ position: "absolute",
78
+ top: -waveAmplitude * 2,
79
+ left: 0,
80
+ width: "200%",
81
+ height: waveAmplitude * 4,
82
+ backgroundColor: color,
83
+ borderRadius: "40%",
84
+ animation: `liquid-wave ${effectiveDuration} linear infinite`
85
+ }
86
+ }
87
+ ),
88
+ /* @__PURE__ */ jsx(
89
+ "div",
90
+ {
91
+ className: "absolute bottom-0 left-0 right-0",
92
+ style: { backgroundColor: color, top: waveAmplitude * 2 }
93
+ }
94
+ )
95
+ ]
96
+ }
97
+ ),
98
+ !isIndeterminate && /* @__PURE__ */ jsxs(
99
+ "span",
100
+ {
101
+ className: "absolute inset-0 flex items-center justify-center text-xs font-bold",
102
+ style: { color: clampedValue > 50 ? "#fff" : color },
103
+ children: [
104
+ clampedValue,
105
+ "%"
106
+ ]
107
+ }
108
+ )
109
+ ]
110
+ }
111
+ )
59
112
  }
60
113
  );
61
114
  }
62
115
  );
63
- GradientSpinner.displayName = "GradientSpinner";
116
+ LiquidFill.displayName = "LiquidFill";
64
117
  export {
65
- GradientSpinner
118
+ LiquidFill
66
119
  };