premium-react-loaders 1.1.0 → 1.2.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 (99) hide show
  1. package/README.md +55 -6
  2. package/dist/components/progress/ProgressBar.d.ts.map +1 -1
  3. package/dist/components/progress/ProgressCircle.d.ts.map +1 -1
  4. package/dist/components/progress/ProgressRing.d.ts.map +1 -1
  5. package/dist/components/pulse/PulseBars.d.ts +2 -2
  6. package/dist/components/pulse/PulseBars.d.ts.map +1 -1
  7. package/dist/components/pulse/PulseDots.d.ts +2 -2
  8. package/dist/components/pulse/PulseDots.d.ts.map +1 -1
  9. package/dist/components/pulse/PulseWave.d.ts +2 -2
  10. package/dist/components/pulse/PulseWave.d.ts.map +1 -1
  11. package/dist/components/pulse/TypingIndicator.d.ts.map +1 -1
  12. package/dist/components/spinner/SpinnerBars.d.ts +2 -2
  13. package/dist/components/spinner/SpinnerBars.d.ts.map +1 -1
  14. package/dist/components/spinner/SpinnerCircle.d.ts +2 -1
  15. package/dist/components/spinner/SpinnerCircle.d.ts.map +1 -1
  16. package/dist/components/spinner/SpinnerDots.d.ts +2 -2
  17. package/dist/components/spinner/SpinnerDots.d.ts.map +1 -1
  18. package/dist/components/spinner/SpinnerGrid.d.ts +2 -2
  19. package/dist/components/spinner/SpinnerGrid.d.ts.map +1 -1
  20. package/dist/components/spinner/SpinnerPulse.d.ts +3 -3
  21. package/dist/components/spinner/SpinnerPulse.d.ts.map +1 -1
  22. package/dist/components/spinner/SpinnerRing.d.ts +3 -3
  23. package/dist/components/spinner/SpinnerRing.d.ts.map +1 -1
  24. package/dist/components/spinner/SpinnerWave.d.ts +3 -3
  25. package/dist/components/spinner/SpinnerWave.d.ts.map +1 -1
  26. package/dist/index14.cjs +9 -3
  27. package/dist/index14.cjs.map +1 -1
  28. package/dist/index14.js +9 -3
  29. package/dist/index14.js.map +1 -1
  30. package/dist/index15.cjs +8 -2
  31. package/dist/index15.cjs.map +1 -1
  32. package/dist/index15.js +9 -3
  33. package/dist/index15.js.map +1 -1
  34. package/dist/index16.cjs +8 -2
  35. package/dist/index16.cjs.map +1 -1
  36. package/dist/index16.js +9 -3
  37. package/dist/index16.js.map +1 -1
  38. package/dist/index17.cjs +8 -4
  39. package/dist/index17.cjs.map +1 -1
  40. package/dist/index17.js +9 -5
  41. package/dist/index17.js.map +1 -1
  42. package/dist/index18.cjs +9 -4
  43. package/dist/index18.cjs.map +1 -1
  44. package/dist/index18.js +10 -5
  45. package/dist/index18.js.map +1 -1
  46. package/dist/index19.cjs +9 -4
  47. package/dist/index19.cjs.map +1 -1
  48. package/dist/index19.js +10 -5
  49. package/dist/index19.js.map +1 -1
  50. package/dist/index20.cjs +9 -4
  51. package/dist/index20.cjs.map +1 -1
  52. package/dist/index20.js +10 -5
  53. package/dist/index20.js.map +1 -1
  54. package/dist/index21.cjs +7 -2
  55. package/dist/index21.cjs.map +1 -1
  56. package/dist/index21.js +8 -3
  57. package/dist/index21.js.map +1 -1
  58. package/dist/index22.cjs +11 -4
  59. package/dist/index22.cjs.map +1 -1
  60. package/dist/index22.js +12 -5
  61. package/dist/index22.js.map +1 -1
  62. package/dist/index23.cjs +11 -4
  63. package/dist/index23.cjs.map +1 -1
  64. package/dist/index23.js +12 -5
  65. package/dist/index23.js.map +1 -1
  66. package/dist/index25.cjs +8 -4
  67. package/dist/index25.cjs.map +1 -1
  68. package/dist/index25.js +9 -5
  69. package/dist/index25.js.map +1 -1
  70. package/dist/index26.cjs +8 -4
  71. package/dist/index26.cjs.map +1 -1
  72. package/dist/index26.js +9 -5
  73. package/dist/index26.js.map +1 -1
  74. package/dist/index27.cjs +9 -4
  75. package/dist/index27.cjs.map +1 -1
  76. package/dist/index27.js +10 -5
  77. package/dist/index27.js.map +1 -1
  78. package/dist/index28.cjs +7 -3
  79. package/dist/index28.cjs.map +1 -1
  80. package/dist/index28.js +8 -4
  81. package/dist/index28.js.map +1 -1
  82. package/dist/index31.cjs +42 -0
  83. package/dist/index31.cjs.map +1 -0
  84. package/dist/index31.js +42 -0
  85. package/dist/index31.js.map +1 -0
  86. package/dist/index4.cjs +10 -0
  87. package/dist/index4.cjs.map +1 -1
  88. package/dist/index4.js +10 -0
  89. package/dist/index4.js.map +1 -1
  90. package/dist/premium-react-loaders.css +270 -3
  91. package/dist/types/common.d.ts +14 -2
  92. package/dist/types/common.d.ts.map +1 -1
  93. package/dist/utils/colors.d.ts +2 -1
  94. package/dist/utils/colors.d.ts.map +1 -1
  95. package/dist/utils/hooks.d.ts +10 -0
  96. package/dist/utils/hooks.d.ts.map +1 -0
  97. package/dist/utils/index.d.ts +1 -0
  98. package/dist/utils/index.d.ts.map +1 -1
  99. package/package.json +1 -1
package/dist/index21.cjs CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
5
  const colors = require("./index4.cjs");
6
+ const hooks = require("./index31.cjs");
6
7
  const classNames = require("./index3.cjs");
7
8
  const ProgressBar = react.forwardRef(
8
9
  ({
@@ -15,6 +16,8 @@ const ProgressBar = react.forwardRef(
15
16
  gradient = false,
16
17
  buffer,
17
18
  speed = "normal",
19
+ reverse = false,
20
+ respectMotionPreference = true,
18
21
  className,
19
22
  style,
20
23
  testId = "progress-bar",
@@ -23,10 +26,11 @@ const ProgressBar = react.forwardRef(
23
26
  ...rest
24
27
  }, ref) => {
25
28
  if (!visible) return null;
29
+ const prefersReducedMotion = hooks.useReducedMotion();
30
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
31
  const clampedValue = Math.min(100, Math.max(0, value));
27
32
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
28
33
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
29
- const animationDuration = colors.getAnimationDuration(speed);
30
34
  const gradientId = react.useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);
31
35
  return /* @__PURE__ */ jsxRuntime.jsxs(
32
36
  "div",
@@ -66,7 +70,8 @@ const ProgressBar = react.forwardRef(
66
70
  className: "absolute h-full rounded-full",
67
71
  style: {
68
72
  backgroundColor: gradient ? `url(#${gradientId})` : color,
69
- animation: `progress-indeterminate ${animationDuration} ease-in-out infinite`,
73
+ animation: `progress-indeterminate ${effectiveDuration} ease-in-out infinite`,
74
+ animationDirection: reverse ? "reverse" : "normal",
70
75
  width: "40%"
71
76
  }
72
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index21.cjs","sources":["../src/components/progress/ProgressBar.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressBarProps } from '../../types';\nimport { cn, normalizeSize, getContrastColor, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressBar - Linear progress bar\n *\n * A horizontal progress bar that can be determinate (showing specific progress) or indeterminate (loading animation).\n *\n * @example\n * ```tsx\n * <ProgressBar value={75} showValue />\n * <ProgressBar indeterminate />\n * <ProgressBar value={50} height={8} color=\"#8b5cf6\" />\n * <ProgressBar value={50} buffer={75} /> // YouTube-style buffering\n * <ProgressBar value={60} gradient /> // Gradient progress\n * ```\n */\nexport const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n height = '0.5rem',\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-bar',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n\n // Generate gradient ID for SVG-based gradient\n const gradientId = useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('relative w-full overflow-hidden rounded-full', className)}\n style={{\n height: normalizeSize(height),\n backgroundColor: secondaryColor,\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n {/* Gradient SVG definition */}\n {gradient && !indeterminate && (\n <svg width=\"0\" height=\"0\" style={{ position: 'absolute' }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor || '#8b5cf6'} />\n </linearGradient>\n </defs>\n </svg>\n )}\n\n {/* Buffer indicator (shows behind main progress) */}\n {clampedBuffer !== undefined && !indeterminate && (\n <div\n className=\"absolute h-full rounded-full opacity-30\"\n style={{\n width: `${clampedBuffer}%`,\n backgroundColor: color,\n }}\n />\n )}\n\n {indeterminate ? (\n <div\n className=\"absolute h-full rounded-full\"\n style={{\n backgroundColor: gradient ? `url(#${gradientId})` : color,\n animation: `progress-indeterminate ${animationDuration} ease-in-out infinite`,\n width: '40%',\n }}\n />\n ) : (\n <div\n className=\"h-full rounded-full transition-all duration-300 ease-in-out\"\n style={{\n width: `${clampedValue}%`,\n background: gradient ? `url(#${gradientId})` : color,\n }}\n />\n )}\n\n {showValue && !indeterminate && (\n <span\n className=\"absolute inset-0 flex items-center justify-center text-xs font-medium\"\n style={{\n color: clampedValue > 50 ? getContrastColor(color) : secondaryColor === '#e0e0e0' ? '#000000' : getContrastColor(secondaryColor)\n }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressBar.displayName = 'ProgressBar';\n"],"names":["forwardRef","getAnimationDuration","useMemo","jsxs","cn","normalizeSize","jsx","getContrastColor"],"mappings":";;;;;;AAkBO,MAAM,cAAcA,MAAAA;AAAAA,EACzB,CACE;AAAA,IACE,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,eAAe,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AACrD,UAAM,gBAAgB,WAAW,SAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AAClF,UAAM,gBAAgB,aAAa,WAAW,YAAY;AAC1D,UAAM,oBAAoBC,OAAAA,qBAAqB,KAAK;AAGpD,UAAM,aAAaC,MAAAA,QAAQ,MAAM,yBAAyB,KAAK,SAAS,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE;AAEvG,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAa;AAAA,QACb,WAAWC,WAAAA,GAAG,gDAAgD,SAAS;AAAA,QACvE,OAAO;AAAA,UACL,QAAQC,OAAAA,cAAc,MAAM;AAAA,UAC5B,iBAAiB;AAAA,UACjB,GAAG;AAAA,QAAA;AAAA,QAEL,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,iBAAe,gBAAgB,SAAY;AAAA,QAC3C,iBAAe;AAAA,QACf,iBAAe;AAAA,QACd,GAAG;AAAA,QAGH,UAAA;AAAA,UAAA,YAAY,CAAC,iBACZC,2BAAAA,IAAC,OAAA,EAAI,OAAM,KAAI,QAAO,KAAI,OAAO,EAAE,UAAU,WAAA,GAC3C,yCAAC,QAAA,EACC,UAAAH,2BAAAA,KAAC,kBAAA,EAAe,IAAI,YAAY,IAAG,MAAK,IAAG,MAAK,IAAG,QAAO,IAAG,MAC3D,UAAA;AAAA,YAAAG,2BAAAA,IAAC,QAAA,EAAK,QAAO,MAAK,WAAW,OAAO;AAAA,2CACnC,QAAA,EAAK,QAAO,QAAO,WAAW,kBAAkB,UAAA,CAAW;AAAA,UAAA,EAAA,CAC9D,GACF,GACF;AAAA,UAID,kBAAkB,UAAa,CAAC,iBAC/BA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,aAAa;AAAA,gBACvB,iBAAiB;AAAA,cAAA;AAAA,YACnB;AAAA,UAAA;AAAA,UAIH,gBACCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,iBAAiB,WAAW,QAAQ,UAAU,MAAM;AAAA,gBACpD,WAAW,0BAA0B,iBAAiB;AAAA,gBACtD,OAAO;AAAA,cAAA;AAAA,YACT;AAAA,UAAA,IAGFA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,YAAY;AAAA,gBACtB,YAAY,WAAW,QAAQ,UAAU,MAAM;AAAA,cAAA;AAAA,YACjD;AAAA,UAAA;AAAA,UAIH,aAAa,CAAC,iBACbH,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,eAAe,KAAKI,wBAAiB,KAAK,IAAI,mBAAmB,YAAY,YAAYA,OAAAA,iBAAiB,cAAc;AAAA,cAAA;AAAA,cAGhI,UAAA;AAAA,gBAAA;AAAA,gBAAa;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAChB;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,YAAY,cAAc;;"}
1
+ {"version":3,"file":"index21.cjs","sources":["../src/components/progress/ProgressBar.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressBarProps } from '../../types';\nimport { cn, normalizeSize, getContrastColor, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressBar - Linear progress bar\n *\n * A horizontal progress bar that can be determinate (showing specific progress) or indeterminate (loading animation).\n *\n * @example\n * ```tsx\n * <ProgressBar value={75} showValue />\n * <ProgressBar indeterminate />\n * <ProgressBar value={50} height={8} color=\"#8b5cf6\" />\n * <ProgressBar value={50} buffer={75} /> // YouTube-style buffering\n * <ProgressBar value={60} gradient /> // Gradient progress\n * ```\n */\nexport const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n height = '0.5rem',\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-bar',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n\n // Generate gradient ID for SVG-based gradient\n const gradientId = useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('relative w-full overflow-hidden rounded-full', className)}\n style={{\n height: normalizeSize(height),\n backgroundColor: secondaryColor,\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n {/* Gradient SVG definition */}\n {gradient && !indeterminate && (\n <svg width=\"0\" height=\"0\" style={{ position: 'absolute' }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor || '#8b5cf6'} />\n </linearGradient>\n </defs>\n </svg>\n )}\n\n {/* Buffer indicator (shows behind main progress) */}\n {clampedBuffer !== undefined && !indeterminate && (\n <div\n className=\"absolute h-full rounded-full opacity-30\"\n style={{\n width: `${clampedBuffer}%`,\n backgroundColor: color,\n }}\n />\n )}\n\n {indeterminate ? (\n <div\n className=\"absolute h-full rounded-full\"\n style={{\n backgroundColor: gradient ? `url(#${gradientId})` : color,\n animation: `progress-indeterminate ${effectiveDuration} ease-in-out infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n width: '40%',\n }}\n />\n ) : (\n <div\n className=\"h-full rounded-full transition-all duration-300 ease-in-out\"\n style={{\n width: `${clampedValue}%`,\n background: gradient ? `url(#${gradientId})` : color,\n }}\n />\n )}\n\n {showValue && !indeterminate && (\n <span\n className=\"absolute inset-0 flex items-center justify-center text-xs font-medium\"\n style={{\n color: clampedValue > 50 ? getContrastColor(color) : secondaryColor === '#e0e0e0' ? '#000000' : getContrastColor(secondaryColor)\n }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressBar.displayName = 'ProgressBar';\n"],"names":["forwardRef","useReducedMotion","getEffectiveDuration","useMemo","jsxs","cn","normalizeSize","jsx","getContrastColor"],"mappings":"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"}
package/dist/index21.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useMemo } from "react";
3
- import { normalizeSize, getAnimationDuration, getContrastColor } from "./index4.js";
3
+ import { normalizeSize, getContrastColor } from "./index4.js";
4
+ import { useReducedMotion, getEffectiveDuration } from "./index31.js";
4
5
  import { cn } from "./index3.js";
5
6
  const ProgressBar = forwardRef(
6
7
  ({
@@ -13,6 +14,8 @@ const ProgressBar = forwardRef(
13
14
  gradient = false,
14
15
  buffer,
15
16
  speed = "normal",
17
+ reverse = false,
18
+ respectMotionPreference = true,
16
19
  className,
17
20
  style,
18
21
  testId = "progress-bar",
@@ -21,10 +24,11 @@ const ProgressBar = forwardRef(
21
24
  ...rest
22
25
  }, ref) => {
23
26
  if (!visible) return null;
27
+ const prefersReducedMotion = useReducedMotion();
28
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
24
29
  const clampedValue = Math.min(100, Math.max(0, value));
25
30
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
26
31
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
27
- const animationDuration = getAnimationDuration(speed);
28
32
  const gradientId = useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);
29
33
  return /* @__PURE__ */ jsxs(
30
34
  "div",
@@ -64,7 +68,8 @@ const ProgressBar = forwardRef(
64
68
  className: "absolute h-full rounded-full",
65
69
  style: {
66
70
  backgroundColor: gradient ? `url(#${gradientId})` : color,
67
- animation: `progress-indeterminate ${animationDuration} ease-in-out infinite`,
71
+ animation: `progress-indeterminate ${effectiveDuration} ease-in-out infinite`,
72
+ animationDirection: reverse ? "reverse" : "normal",
68
73
  width: "40%"
69
74
  }
70
75
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index21.js","sources":["../src/components/progress/ProgressBar.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressBarProps } from '../../types';\nimport { cn, normalizeSize, getContrastColor, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressBar - Linear progress bar\n *\n * A horizontal progress bar that can be determinate (showing specific progress) or indeterminate (loading animation).\n *\n * @example\n * ```tsx\n * <ProgressBar value={75} showValue />\n * <ProgressBar indeterminate />\n * <ProgressBar value={50} height={8} color=\"#8b5cf6\" />\n * <ProgressBar value={50} buffer={75} /> // YouTube-style buffering\n * <ProgressBar value={60} gradient /> // Gradient progress\n * ```\n */\nexport const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n height = '0.5rem',\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-bar',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n\n // Generate gradient ID for SVG-based gradient\n const gradientId = useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('relative w-full overflow-hidden rounded-full', className)}\n style={{\n height: normalizeSize(height),\n backgroundColor: secondaryColor,\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n {/* Gradient SVG definition */}\n {gradient && !indeterminate && (\n <svg width=\"0\" height=\"0\" style={{ position: 'absolute' }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor || '#8b5cf6'} />\n </linearGradient>\n </defs>\n </svg>\n )}\n\n {/* Buffer indicator (shows behind main progress) */}\n {clampedBuffer !== undefined && !indeterminate && (\n <div\n className=\"absolute h-full rounded-full opacity-30\"\n style={{\n width: `${clampedBuffer}%`,\n backgroundColor: color,\n }}\n />\n )}\n\n {indeterminate ? (\n <div\n className=\"absolute h-full rounded-full\"\n style={{\n backgroundColor: gradient ? `url(#${gradientId})` : color,\n animation: `progress-indeterminate ${animationDuration} ease-in-out infinite`,\n width: '40%',\n }}\n />\n ) : (\n <div\n className=\"h-full rounded-full transition-all duration-300 ease-in-out\"\n style={{\n width: `${clampedValue}%`,\n background: gradient ? `url(#${gradientId})` : color,\n }}\n />\n )}\n\n {showValue && !indeterminate && (\n <span\n className=\"absolute inset-0 flex items-center justify-center text-xs font-medium\"\n style={{\n color: clampedValue > 50 ? getContrastColor(color) : secondaryColor === '#e0e0e0' ? '#000000' : getContrastColor(secondaryColor)\n }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressBar.displayName = 'ProgressBar';\n"],"names":[],"mappings":";;;;AAkBO,MAAM,cAAc;AAAA,EACzB,CACE;AAAA,IACE,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,eAAe,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AACrD,UAAM,gBAAgB,WAAW,SAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AAClF,UAAM,gBAAgB,aAAa,WAAW,YAAY;AAC1D,UAAM,oBAAoB,qBAAqB,KAAK;AAGpD,UAAM,aAAa,QAAQ,MAAM,yBAAyB,KAAK,SAAS,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE;AAEvG,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAa;AAAA,QACb,WAAW,GAAG,gDAAgD,SAAS;AAAA,QACvE,OAAO;AAAA,UACL,QAAQ,cAAc,MAAM;AAAA,UAC5B,iBAAiB;AAAA,UACjB,GAAG;AAAA,QAAA;AAAA,QAEL,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,iBAAe,gBAAgB,SAAY;AAAA,QAC3C,iBAAe;AAAA,QACf,iBAAe;AAAA,QACd,GAAG;AAAA,QAGH,UAAA;AAAA,UAAA,YAAY,CAAC,iBACZ,oBAAC,OAAA,EAAI,OAAM,KAAI,QAAO,KAAI,OAAO,EAAE,UAAU,WAAA,GAC3C,8BAAC,QAAA,EACC,UAAA,qBAAC,kBAAA,EAAe,IAAI,YAAY,IAAG,MAAK,IAAG,MAAK,IAAG,QAAO,IAAG,MAC3D,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,QAAO,MAAK,WAAW,OAAO;AAAA,gCACnC,QAAA,EAAK,QAAO,QAAO,WAAW,kBAAkB,UAAA,CAAW;AAAA,UAAA,EAAA,CAC9D,GACF,GACF;AAAA,UAID,kBAAkB,UAAa,CAAC,iBAC/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,aAAa;AAAA,gBACvB,iBAAiB;AAAA,cAAA;AAAA,YACnB;AAAA,UAAA;AAAA,UAIH,gBACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,iBAAiB,WAAW,QAAQ,UAAU,MAAM;AAAA,gBACpD,WAAW,0BAA0B,iBAAiB;AAAA,gBACtD,OAAO;AAAA,cAAA;AAAA,YACT;AAAA,UAAA,IAGF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,YAAY;AAAA,gBACtB,YAAY,WAAW,QAAQ,UAAU,MAAM;AAAA,cAAA;AAAA,YACjD;AAAA,UAAA;AAAA,UAIH,aAAa,CAAC,iBACb;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,eAAe,KAAK,iBAAiB,KAAK,IAAI,mBAAmB,YAAY,YAAY,iBAAiB,cAAc;AAAA,cAAA;AAAA,cAGhI,UAAA;AAAA,gBAAA;AAAA,gBAAa;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAChB;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,YAAY,cAAc;"}
1
+ {"version":3,"file":"index21.js","sources":["../src/components/progress/ProgressBar.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressBarProps } from '../../types';\nimport { cn, normalizeSize, getContrastColor, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressBar - Linear progress bar\n *\n * A horizontal progress bar that can be determinate (showing specific progress) or indeterminate (loading animation).\n *\n * @example\n * ```tsx\n * <ProgressBar value={75} showValue />\n * <ProgressBar indeterminate />\n * <ProgressBar value={50} height={8} color=\"#8b5cf6\" />\n * <ProgressBar value={50} buffer={75} /> // YouTube-style buffering\n * <ProgressBar value={60} gradient /> // Gradient progress\n * ```\n */\nexport const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n height = '0.5rem',\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-bar',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n\n // Generate gradient ID for SVG-based gradient\n const gradientId = useMemo(() => `progress-bar-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('relative w-full overflow-hidden rounded-full', className)}\n style={{\n height: normalizeSize(height),\n backgroundColor: secondaryColor,\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n {/* Gradient SVG definition */}\n {gradient && !indeterminate && (\n <svg width=\"0\" height=\"0\" style={{ position: 'absolute' }}>\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"0%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor || '#8b5cf6'} />\n </linearGradient>\n </defs>\n </svg>\n )}\n\n {/* Buffer indicator (shows behind main progress) */}\n {clampedBuffer !== undefined && !indeterminate && (\n <div\n className=\"absolute h-full rounded-full opacity-30\"\n style={{\n width: `${clampedBuffer}%`,\n backgroundColor: color,\n }}\n />\n )}\n\n {indeterminate ? (\n <div\n className=\"absolute h-full rounded-full\"\n style={{\n backgroundColor: gradient ? `url(#${gradientId})` : color,\n animation: `progress-indeterminate ${effectiveDuration} ease-in-out infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n width: '40%',\n }}\n />\n ) : (\n <div\n className=\"h-full rounded-full transition-all duration-300 ease-in-out\"\n style={{\n width: `${clampedValue}%`,\n background: gradient ? `url(#${gradientId})` : color,\n }}\n />\n )}\n\n {showValue && !indeterminate && (\n <span\n className=\"absolute inset-0 flex items-center justify-center text-xs font-medium\"\n style={{\n color: clampedValue > 50 ? getContrastColor(color) : secondaryColor === '#e0e0e0' ? '#000000' : getContrastColor(secondaryColor)\n }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressBar.displayName = 'ProgressBar';\n"],"names":[],"mappings":";;;;;AAkBO,MAAM,cAAc;AAAA,EACzB,CACE;AAAA,IACE,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,uBAAuB,iBAAA;AAC7B,UAAM,oBAAoB,qBAAqB,OAAO,yBAAyB,oBAAoB;AAEnG,UAAM,eAAe,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AACrD,UAAM,gBAAgB,WAAW,SAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI;AAClF,UAAM,gBAAgB,aAAa,WAAW,YAAY;AAG1D,UAAM,aAAa,QAAQ,MAAM,yBAAyB,KAAK,SAAS,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE;AAEvG,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAa;AAAA,QACb,WAAW,GAAG,gDAAgD,SAAS;AAAA,QACvE,OAAO;AAAA,UACL,QAAQ,cAAc,MAAM;AAAA,UAC5B,iBAAiB;AAAA,UACjB,GAAG;AAAA,QAAA;AAAA,QAEL,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,iBAAe,gBAAgB,SAAY;AAAA,QAC3C,iBAAe;AAAA,QACf,iBAAe;AAAA,QACd,GAAG;AAAA,QAGH,UAAA;AAAA,UAAA,YAAY,CAAC,iBACZ,oBAAC,OAAA,EAAI,OAAM,KAAI,QAAO,KAAI,OAAO,EAAE,UAAU,WAAA,GAC3C,8BAAC,QAAA,EACC,UAAA,qBAAC,kBAAA,EAAe,IAAI,YAAY,IAAG,MAAK,IAAG,MAAK,IAAG,QAAO,IAAG,MAC3D,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,QAAO,MAAK,WAAW,OAAO;AAAA,gCACnC,QAAA,EAAK,QAAO,QAAO,WAAW,kBAAkB,UAAA,CAAW;AAAA,UAAA,EAAA,CAC9D,GACF,GACF;AAAA,UAID,kBAAkB,UAAa,CAAC,iBAC/B;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,aAAa;AAAA,gBACvB,iBAAiB;AAAA,cAAA;AAAA,YACnB;AAAA,UAAA;AAAA,UAIH,gBACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,iBAAiB,WAAW,QAAQ,UAAU,MAAM;AAAA,gBACpD,WAAW,0BAA0B,iBAAiB;AAAA,gBACtD,oBAAoB,UAAU,YAAY;AAAA,gBAC1C,OAAO;AAAA,cAAA;AAAA,YACT;AAAA,UAAA,IAGF;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,GAAG,YAAY;AAAA,gBACtB,YAAY,WAAW,QAAQ,UAAU,MAAM;AAAA,cAAA;AAAA,YACjD;AAAA,UAAA;AAAA,UAIH,aAAa,CAAC,iBACb;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,OAAO,eAAe,KAAK,iBAAiB,KAAK,IAAI,mBAAmB,YAAY,YAAY,iBAAiB,cAAc;AAAA,cAAA;AAAA,cAGhI,UAAA;AAAA,gBAAA;AAAA,gBAAa;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QAChB;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,YAAY,cAAc;"}
package/dist/index22.cjs CHANGED
@@ -2,6 +2,7 @@
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("./index31.cjs");
5
6
  const colors = require("./index4.cjs");
6
7
  const classNames = require("./index3.cjs");
7
8
  const ProgressCircle = react.forwardRef(
@@ -9,12 +10,14 @@ const ProgressCircle = react.forwardRef(
9
10
  value = 0,
10
11
  indeterminate = false,
11
12
  showValue = false,
12
- size = 60,
13
+ size = "lg",
13
14
  thickness = 4,
14
15
  color = "#3b82f6",
15
16
  secondaryColor = "#e0e0e0",
16
17
  buffer,
17
18
  speed = "normal",
19
+ reverse = false,
20
+ respectMotionPreference = true,
18
21
  className,
19
22
  style,
20
23
  testId = "progress-circle",
@@ -23,16 +26,17 @@ const ProgressCircle = react.forwardRef(
23
26
  ...rest
24
27
  }, ref) => {
25
28
  if (!visible) return null;
29
+ const prefersReducedMotion = hooks.useReducedMotion();
30
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
26
31
  const clampedValue = Math.min(100, Math.max(0, value));
27
32
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
28
- const sizeValue = colors.parseSizeToNumber(size, 60);
33
+ const sizeValue = colors.parseSizeToNumber(size, 56);
29
34
  const thicknessValue = colors.parseSizeToNumber(thickness, 4);
30
35
  const radius = (sizeValue - thicknessValue * 2) / 2;
31
36
  const circumference = 2 * Math.PI * radius;
32
37
  const strokeDashoffset = circumference - clampedValue / 100 * circumference;
33
38
  const bufferDashoffset = clampedBuffer !== void 0 ? circumference - clampedBuffer / 100 * circumference : void 0;
34
39
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
35
- const animationDuration = colors.getAnimationDuration(speed);
36
40
  return /* @__PURE__ */ jsxRuntime.jsxs(
37
41
  "div",
38
42
  {
@@ -58,7 +62,10 @@ const ProgressCircle = react.forwardRef(
58
62
  width: sizeValue,
59
63
  height: sizeValue,
60
64
  viewBox: `0 0 ${sizeValue} ${sizeValue}`,
61
- style: indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : void 0,
65
+ style: indeterminate ? {
66
+ animation: `spinner-rotate ${effectiveDuration} linear infinite`,
67
+ animationDirection: reverse ? "reverse" : "normal"
68
+ } : void 0,
62
69
  children: [
63
70
  /* @__PURE__ */ jsxRuntime.jsx(
64
71
  "circle",
@@ -1 +1 @@
1
- {"version":3,"file":"index22.cjs","sources":["../src/components/progress/ProgressCircle.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { ProgressCircleProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressCircle - SVG-based circular progress indicator\n *\n * A circular progress indicator that shows progress as a partial circle.\n *\n * @example\n * ```tsx\n * <ProgressCircle value={75} showValue />\n * <ProgressCircle value={50} size={80} thickness={6} />\n * <ProgressCircle indeterminate speed=\"fast\" />\n * <ProgressCircle value={50} buffer={75} />\n * ```\n */\nexport const ProgressCircle = forwardRef<HTMLDivElement, ProgressCircleProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 60,\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-circle',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 60);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : undefined}\n >\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-medium\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressCircle.displayName = 'ProgressCircle';\n"],"names":["forwardRef","parseSizeToNumber","getAnimationDuration","jsxs","cn","normalizeSize","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"index22.cjs","sources":["../src/components/progress/ProgressCircle.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { ProgressCircleProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressCircle - SVG-based circular progress indicator\n *\n * A circular progress indicator that shows progress as a partial circle.\n *\n * @example\n * ```tsx\n * <ProgressCircle value={75} showValue />\n * <ProgressCircle value={50} size={80} thickness={6} />\n * <ProgressCircle indeterminate speed=\"fast\" />\n * <ProgressCircle value={50} buffer={75} />\n * ```\n */\nexport const ProgressCircle = forwardRef<HTMLDivElement, ProgressCircleProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 'lg',\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-circle',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 56);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? {\n animation: `spinner-rotate ${effectiveDuration} linear infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n } : undefined}\n >\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-medium\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressCircle.displayName = 'ProgressCircle';\n"],"names":["forwardRef","useReducedMotion","getEffectiveDuration","parseSizeToNumber","jsxs","cn","normalizeSize","jsx"],"mappings":"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"}
package/dist/index22.js CHANGED
@@ -1,18 +1,21 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
- import { normalizeSize, getAnimationDuration, parseSizeToNumber } from "./index4.js";
3
+ import { useReducedMotion, getEffectiveDuration } from "./index31.js";
4
+ import { normalizeSize, parseSizeToNumber } from "./index4.js";
4
5
  import { cn } from "./index3.js";
5
6
  const ProgressCircle = forwardRef(
6
7
  ({
7
8
  value = 0,
8
9
  indeterminate = false,
9
10
  showValue = false,
10
- size = 60,
11
+ size = "lg",
11
12
  thickness = 4,
12
13
  color = "#3b82f6",
13
14
  secondaryColor = "#e0e0e0",
14
15
  buffer,
15
16
  speed = "normal",
17
+ reverse = false,
18
+ respectMotionPreference = true,
16
19
  className,
17
20
  style,
18
21
  testId = "progress-circle",
@@ -21,16 +24,17 @@ const ProgressCircle = forwardRef(
21
24
  ...rest
22
25
  }, ref) => {
23
26
  if (!visible) return null;
27
+ const prefersReducedMotion = useReducedMotion();
28
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
24
29
  const clampedValue = Math.min(100, Math.max(0, value));
25
30
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
26
- const sizeValue = parseSizeToNumber(size, 60);
31
+ const sizeValue = parseSizeToNumber(size, 56);
27
32
  const thicknessValue = parseSizeToNumber(thickness, 4);
28
33
  const radius = (sizeValue - thicknessValue * 2) / 2;
29
34
  const circumference = 2 * Math.PI * radius;
30
35
  const strokeDashoffset = circumference - clampedValue / 100 * circumference;
31
36
  const bufferDashoffset = clampedBuffer !== void 0 ? circumference - clampedBuffer / 100 * circumference : void 0;
32
37
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
33
- const animationDuration = getAnimationDuration(speed);
34
38
  return /* @__PURE__ */ jsxs(
35
39
  "div",
36
40
  {
@@ -56,7 +60,10 @@ const ProgressCircle = forwardRef(
56
60
  width: sizeValue,
57
61
  height: sizeValue,
58
62
  viewBox: `0 0 ${sizeValue} ${sizeValue}`,
59
- style: indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : void 0,
63
+ style: indeterminate ? {
64
+ animation: `spinner-rotate ${effectiveDuration} linear infinite`,
65
+ animationDirection: reverse ? "reverse" : "normal"
66
+ } : void 0,
60
67
  children: [
61
68
  /* @__PURE__ */ jsx(
62
69
  "circle",
@@ -1 +1 @@
1
- {"version":3,"file":"index22.js","sources":["../src/components/progress/ProgressCircle.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { ProgressCircleProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressCircle - SVG-based circular progress indicator\n *\n * A circular progress indicator that shows progress as a partial circle.\n *\n * @example\n * ```tsx\n * <ProgressCircle value={75} showValue />\n * <ProgressCircle value={50} size={80} thickness={6} />\n * <ProgressCircle indeterminate speed=\"fast\" />\n * <ProgressCircle value={50} buffer={75} />\n * ```\n */\nexport const ProgressCircle = forwardRef<HTMLDivElement, ProgressCircleProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 60,\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-circle',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 60);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : undefined}\n >\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-medium\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressCircle.displayName = 'ProgressCircle';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index22.js","sources":["../src/components/progress/ProgressCircle.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { ProgressCircleProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressCircle - SVG-based circular progress indicator\n *\n * A circular progress indicator that shows progress as a partial circle.\n *\n * @example\n * ```tsx\n * <ProgressCircle value={75} showValue />\n * <ProgressCircle value={50} size={80} thickness={6} />\n * <ProgressCircle indeterminate speed=\"fast\" />\n * <ProgressCircle value={50} buffer={75} />\n * ```\n */\nexport const ProgressCircle = forwardRef<HTMLDivElement, ProgressCircleProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 'lg',\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-circle',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 56);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? {\n animation: `spinner-rotate ${effectiveDuration} linear infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n } : undefined}\n >\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-medium\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressCircle.displayName = 'ProgressCircle';\n"],"names":[],"mappings":"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"}
package/dist/index23.cjs CHANGED
@@ -2,6 +2,7 @@
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("./index31.cjs");
5
6
  const colors = require("./index4.cjs");
6
7
  const classNames = require("./index3.cjs");
7
8
  const ProgressRing = react.forwardRef(
@@ -9,13 +10,15 @@ const ProgressRing = react.forwardRef(
9
10
  value = 0,
10
11
  indeterminate = false,
11
12
  showValue = false,
12
- size = 60,
13
+ size = "lg",
13
14
  thickness = 4,
14
15
  color = "#3b82f6",
15
16
  secondaryColor = "#e0e0e0",
16
17
  gradient = false,
17
18
  buffer,
18
19
  speed = "normal",
20
+ reverse = false,
21
+ respectMotionPreference = true,
19
22
  className,
20
23
  style,
21
24
  testId = "progress-ring",
@@ -24,16 +27,17 @@ const ProgressRing = react.forwardRef(
24
27
  ...rest
25
28
  }, ref) => {
26
29
  if (!visible) return null;
30
+ const prefersReducedMotion = hooks.useReducedMotion();
31
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
27
32
  const clampedValue = Math.min(100, Math.max(0, value));
28
33
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
29
- const sizeValue = colors.parseSizeToNumber(size, 60);
34
+ const sizeValue = colors.parseSizeToNumber(size, 56);
30
35
  const thicknessValue = colors.parseSizeToNumber(thickness, 4);
31
36
  const radius = (sizeValue - thicknessValue * 2) / 2;
32
37
  const circumference = 2 * Math.PI * radius;
33
38
  const strokeDashoffset = circumference - clampedValue / 100 * circumference;
34
39
  const bufferDashoffset = clampedBuffer !== void 0 ? circumference - clampedBuffer / 100 * circumference : void 0;
35
40
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
36
- const animationDuration = colors.getAnimationDuration(speed);
37
41
  const gradientId = react.useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);
38
42
  return /* @__PURE__ */ jsxRuntime.jsxs(
39
43
  "div",
@@ -60,7 +64,10 @@ const ProgressRing = react.forwardRef(
60
64
  width: sizeValue,
61
65
  height: sizeValue,
62
66
  viewBox: `0 0 ${sizeValue} ${sizeValue}`,
63
- style: indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : void 0,
67
+ style: indeterminate ? {
68
+ animation: `spinner-rotate ${effectiveDuration} linear infinite`,
69
+ animationDirection: reverse ? "reverse" : "normal"
70
+ } : void 0,
64
71
  children: [
65
72
  gradient && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
66
73
  /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: color }),
@@ -1 +1 @@
1
- {"version":3,"file":"index23.cjs","sources":["../src/components/progress/ProgressRing.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressRingProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressRing - Ring-style progress with gradient option\n *\n * A circular progress ring with optional gradient colors.\n *\n * @example\n * ```tsx\n * <ProgressRing value={75} showValue />\n * <ProgressRing value={60} gradient secondaryColor=\"#8b5cf6\" />\n * <ProgressRing indeterminate speed=\"fast\" />\n * <ProgressRing value={50} buffer={75} />\n * ```\n */\nexport const ProgressRing = forwardRef<HTMLDivElement, ProgressRingProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 60,\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-ring',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 60);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n const gradientId = useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : undefined}\n >\n {gradient && (\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor === '#e0e0e0' ? '#8b5cf6' : secondaryColor} />\n </linearGradient>\n </defs>\n )}\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? '#e0e0e0' : secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-semibold\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressRing.displayName = 'ProgressRing';\n"],"names":["forwardRef","parseSizeToNumber","getAnimationDuration","useMemo","jsxs","cn","normalizeSize","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"index23.cjs","sources":["../src/components/progress/ProgressRing.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressRingProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressRing - Ring-style progress with gradient option\n *\n * A circular progress ring with optional gradient colors.\n *\n * @example\n * ```tsx\n * <ProgressRing value={75} showValue />\n * <ProgressRing value={60} gradient secondaryColor=\"#8b5cf6\" />\n * <ProgressRing indeterminate speed=\"fast\" />\n * <ProgressRing value={50} buffer={75} />\n * ```\n */\nexport const ProgressRing = forwardRef<HTMLDivElement, ProgressRingProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 'lg',\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-ring',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 56);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const gradientId = useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? {\n animation: `spinner-rotate ${effectiveDuration} linear infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n } : undefined}\n >\n {gradient && (\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor === '#e0e0e0' ? '#8b5cf6' : secondaryColor} />\n </linearGradient>\n </defs>\n )}\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? '#e0e0e0' : secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-semibold\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressRing.displayName = 'ProgressRing';\n"],"names":["forwardRef","useReducedMotion","getEffectiveDuration","parseSizeToNumber","useMemo","jsxs","cn","normalizeSize","jsx"],"mappings":"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"}
package/dist/index23.js CHANGED
@@ -1,19 +1,22 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useMemo } from "react";
3
- import { normalizeSize, getAnimationDuration, parseSizeToNumber } from "./index4.js";
3
+ import { useReducedMotion, getEffectiveDuration } from "./index31.js";
4
+ import { normalizeSize, parseSizeToNumber } from "./index4.js";
4
5
  import { cn } from "./index3.js";
5
6
  const ProgressRing = forwardRef(
6
7
  ({
7
8
  value = 0,
8
9
  indeterminate = false,
9
10
  showValue = false,
10
- size = 60,
11
+ size = "lg",
11
12
  thickness = 4,
12
13
  color = "#3b82f6",
13
14
  secondaryColor = "#e0e0e0",
14
15
  gradient = false,
15
16
  buffer,
16
17
  speed = "normal",
18
+ reverse = false,
19
+ respectMotionPreference = true,
17
20
  className,
18
21
  style,
19
22
  testId = "progress-ring",
@@ -22,16 +25,17 @@ const ProgressRing = forwardRef(
22
25
  ...rest
23
26
  }, ref) => {
24
27
  if (!visible) return null;
28
+ const prefersReducedMotion = useReducedMotion();
29
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
25
30
  const clampedValue = Math.min(100, Math.max(0, value));
26
31
  const clampedBuffer = buffer !== void 0 ? Math.min(100, Math.max(0, buffer)) : void 0;
27
- const sizeValue = parseSizeToNumber(size, 60);
32
+ const sizeValue = parseSizeToNumber(size, 56);
28
33
  const thicknessValue = parseSizeToNumber(thickness, 4);
29
34
  const radius = (sizeValue - thicknessValue * 2) / 2;
30
35
  const circumference = 2 * Math.PI * radius;
31
36
  const strokeDashoffset = circumference - clampedValue / 100 * circumference;
32
37
  const bufferDashoffset = clampedBuffer !== void 0 ? circumference - clampedBuffer / 100 * circumference : void 0;
33
38
  const progressLabel = ariaLabel || `Loading ${clampedValue}%`;
34
- const animationDuration = getAnimationDuration(speed);
35
39
  const gradientId = useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);
36
40
  return /* @__PURE__ */ jsxs(
37
41
  "div",
@@ -58,7 +62,10 @@ const ProgressRing = forwardRef(
58
62
  width: sizeValue,
59
63
  height: sizeValue,
60
64
  viewBox: `0 0 ${sizeValue} ${sizeValue}`,
61
- style: indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : void 0,
65
+ style: indeterminate ? {
66
+ animation: `spinner-rotate ${effectiveDuration} linear infinite`,
67
+ animationDirection: reverse ? "reverse" : "normal"
68
+ } : void 0,
62
69
  children: [
63
70
  gradient && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [
64
71
  /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: color }),
@@ -1 +1 @@
1
- {"version":3,"file":"index23.js","sources":["../src/components/progress/ProgressRing.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressRingProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, getAnimationDuration } from '../../utils';\n\n/**\n * ProgressRing - Ring-style progress with gradient option\n *\n * A circular progress ring with optional gradient colors.\n *\n * @example\n * ```tsx\n * <ProgressRing value={75} showValue />\n * <ProgressRing value={60} gradient secondaryColor=\"#8b5cf6\" />\n * <ProgressRing indeterminate speed=\"fast\" />\n * <ProgressRing value={50} buffer={75} />\n * ```\n */\nexport const ProgressRing = forwardRef<HTMLDivElement, ProgressRingProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 60,\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n className,\n style,\n testId = 'progress-ring',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 60);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const animationDuration = getAnimationDuration(speed);\n const gradientId = useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? { animation: `spinner-rotate ${animationDuration} linear infinite` } : undefined}\n >\n {gradient && (\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor === '#e0e0e0' ? '#8b5cf6' : secondaryColor} />\n </linearGradient>\n </defs>\n )}\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? '#e0e0e0' : secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-semibold\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressRing.displayName = 'ProgressRing';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index23.js","sources":["../src/components/progress/ProgressRing.tsx"],"sourcesContent":["import { forwardRef, useMemo } from 'react';\nimport { ProgressRingProps } from '../../types';\nimport { cn, normalizeSize, parseSizeToNumber, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * ProgressRing - Ring-style progress with gradient option\n *\n * A circular progress ring with optional gradient colors.\n *\n * @example\n * ```tsx\n * <ProgressRing value={75} showValue />\n * <ProgressRing value={60} gradient secondaryColor=\"#8b5cf6\" />\n * <ProgressRing indeterminate speed=\"fast\" />\n * <ProgressRing value={50} buffer={75} />\n * ```\n */\nexport const ProgressRing = forwardRef<HTMLDivElement, ProgressRingProps>(\n (\n {\n value = 0,\n indeterminate = false,\n showValue = false,\n size = 'lg',\n thickness = 4,\n color = '#3b82f6',\n secondaryColor = '#e0e0e0',\n gradient = false,\n buffer,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'progress-ring',\n visible = true,\n ariaLabel,\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n const clampedValue = Math.min(100, Math.max(0, value));\n const clampedBuffer = buffer !== undefined ? Math.min(100, Math.max(0, buffer)) : undefined;\n const sizeValue = parseSizeToNumber(size, 56);\n const thicknessValue = parseSizeToNumber(thickness, 4);\n const radius = (sizeValue - thicknessValue * 2) / 2;\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (clampedValue / 100) * circumference;\n const bufferDashoffset = clampedBuffer !== undefined ? circumference - (clampedBuffer / 100) * circumference : undefined;\n const progressLabel = ariaLabel || `Loading ${clampedValue}%`;\n const gradientId = useMemo(() => `progress-gradient-${Math.random().toString(36).substr(2, 9)}`, []);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center relative', className)}\n style={{\n width: normalizeSize(size),\n height: normalizeSize(size),\n ...style,\n }}\n role=\"progressbar\"\n aria-label={progressLabel}\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={100}\n {...rest}\n >\n <svg\n className={cn(indeterminate && 'animate-spinner-rotate')}\n width={sizeValue}\n height={sizeValue}\n viewBox={`0 0 ${sizeValue} ${sizeValue}`}\n style={indeterminate ? {\n animation: `spinner-rotate ${effectiveDuration} linear infinite`,\n animationDirection: reverse ? 'reverse' : 'normal',\n } : undefined}\n >\n {gradient && (\n <defs>\n <linearGradient id={gradientId} x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n <stop offset=\"0%\" stopColor={color} />\n <stop offset=\"100%\" stopColor={secondaryColor === '#e0e0e0' ? '#8b5cf6' : secondaryColor} />\n </linearGradient>\n </defs>\n )}\n {/* Background circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? '#e0e0e0' : secondaryColor}\n strokeWidth={thicknessValue}\n />\n {/* Buffer circle (behind progress) */}\n {bufferDashoffset !== undefined && !indeterminate && (\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={bufferDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n opacity={0.3}\n />\n )}\n {/* Progress circle */}\n <circle\n cx={sizeValue / 2}\n cy={sizeValue / 2}\n r={radius}\n fill=\"none\"\n stroke={gradient ? `url(#${gradientId})` : color}\n strokeWidth={thicknessValue}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={indeterminate ? circumference * 0.75 : strokeDashoffset}\n transform={`rotate(-90 ${sizeValue / 2} ${sizeValue / 2})`}\n style={{\n transition: indeterminate ? 'none' : 'stroke-dashoffset 0.3s ease-in-out',\n }}\n />\n </svg>\n {showValue && !indeterminate && (\n <span\n className=\"absolute text-sm font-semibold\"\n style={{ color }}\n >\n {clampedValue}%\n </span>\n )}\n </div>\n );\n }\n);\n\nProgressRing.displayName = 'ProgressRing';\n"],"names":[],"mappings":"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"}
package/dist/index25.cjs CHANGED
@@ -2,15 +2,18 @@
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("./index31.cjs");
5
6
  const colors = require("./index4.cjs");
6
7
  const classNames = require("./index3.cjs");
7
8
  const PulseDots = react.forwardRef(
8
9
  ({
9
- size = 40,
10
+ size = "md",
10
11
  color = "#3b82f6",
11
12
  dotCount = 3,
12
13
  dotSize = 10,
13
14
  speed = "normal",
15
+ reverse = false,
16
+ respectMotionPreference = true,
14
17
  className,
15
18
  style,
16
19
  testId = "pulse-dots",
@@ -19,7 +22,8 @@ const PulseDots = react.forwardRef(
19
22
  ...rest
20
23
  }, ref) => {
21
24
  if (!visible) return null;
22
- const animationDuration = colors.getAnimationDuration(speed);
25
+ const prefersReducedMotion = hooks.useReducedMotion();
26
+ const effectiveDuration = hooks.getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
23
27
  return /* @__PURE__ */ jsxRuntime.jsx(
24
28
  "div",
25
29
  {
@@ -42,8 +46,8 @@ const PulseDots = react.forwardRef(
42
46
  width: colors.normalizeSize(dotSize),
43
47
  height: colors.normalizeSize(dotSize),
44
48
  backgroundColor: color,
45
- animation: `pulse-bounce ${animationDuration} ease-in-out infinite`,
46
- animationDelay: `${index * 0.15}s`
49
+ animation: `pulse-bounce ${effectiveDuration} ease-in-out infinite`,
50
+ animationDelay: reverse ? `${(dotCount - index - 1) * 0.15}s` : `${index * 0.15}s`
47
51
  }
48
52
  },
49
53
  index
@@ -1 +1 @@
1
- {"version":3,"file":"index25.cjs","sources":["../src/components/pulse/PulseDots.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { PulseDotsProps } from '../../types';\nimport { cn, normalizeSize, getAnimationDuration } from '../../utils';\n\n/**\n * PulseDots - Bouncing dots loader\n *\n * A loader with bouncing dots that scale and fade in a sequence.\n *\n * @example\n * ```tsx\n * <PulseDots size={40} color=\"#3b82f6\" />\n * <PulseDots size={32} dotCount={5} speed=\"fast\" />\n * ```\n */\nexport const PulseDots = forwardRef<HTMLDivElement, PulseDotsProps>(\n (\n {\n size = 40,\n color = '#3b82f6',\n dotCount = 3,\n dotSize = 10,\n speed = 'normal',\n className,\n style,\n testId = 'pulse-dots',\n visible = true,\n ariaLabel = 'Loading...',\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const animationDuration = getAnimationDuration(speed);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center gap-2', className)}\n style={{\n height: normalizeSize(size),\n ...style,\n }}\n role=\"status\"\n aria-label={ariaLabel}\n aria-busy=\"true\"\n {...rest}\n >\n {Array.from({ length: dotCount }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-full\"\n style={{\n width: normalizeSize(dotSize),\n height: normalizeSize(dotSize),\n backgroundColor: color,\n animation: `pulse-bounce ${animationDuration} ease-in-out infinite`,\n animationDelay: `${index * 0.15}s`,\n }}\n />\n ))}\n </div>\n );\n }\n);\n\nPulseDots.displayName = 'PulseDots';\n"],"names":["forwardRef","getAnimationDuration","jsx","cn","normalizeSize"],"mappings":";;;;;;AAeO,MAAM,YAAYA,MAAAA;AAAAA,EACvB,CACE;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,GAAG;AAAA,EAAA,GAEL,QACG;AACH,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,oBAAoBC,OAAAA,qBAAqB,KAAK;AAEpD,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAa;AAAA,QACb,WAAWC,WAAAA,GAAG,iDAAiD,SAAS;AAAA,QACxE,OAAO;AAAA,UACL,QAAQC,OAAAA,cAAc,IAAI;AAAA,UAC1B,GAAG;AAAA,QAAA;AAAA,QAEL,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,aAAU;AAAA,QACT,GAAG;AAAA,QAEH,UAAA,MAAM,KAAK,EAAE,QAAQ,UAAU,EAAE,IAAI,CAAC,GAAG,UACxCF,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAOE,OAAAA,cAAc,OAAO;AAAA,cAC5B,QAAQA,OAAAA,cAAc,OAAO;AAAA,cAC7B,iBAAiB;AAAA,cACjB,WAAW,gBAAgB,iBAAiB;AAAA,cAC5C,gBAAgB,GAAG,QAAQ,IAAI;AAAA,YAAA;AAAA,UACjC;AAAA,UARK;AAAA,QAAA,CAUR;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,UAAU,cAAc;;"}
1
+ {"version":3,"file":"index25.cjs","sources":["../src/components/pulse/PulseDots.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport { PulseDotsProps } from '../../types';\nimport { cn, normalizeSize, useReducedMotion, getEffectiveDuration } from '../../utils';\n\n/**\n * PulseDots - Bouncing dots loader\n *\n * A loader with bouncing dots that scale and fade in a sequence.\n *\n * @example\n * ```tsx\n * <PulseDots size=\"lg\" color=\"#3b82f6\" />\n * <PulseDots size=\"sm\" dotCount={5} speed=\"fast\" reverse />\n * ```\n */\nexport const PulseDots = forwardRef<HTMLDivElement, PulseDotsProps>(\n (\n {\n size = 'md',\n color = '#3b82f6',\n dotCount = 3,\n dotSize = 10,\n speed = 'normal',\n reverse = false,\n respectMotionPreference = true,\n className,\n style,\n testId = 'pulse-dots',\n visible = true,\n ariaLabel = 'Loading...',\n ...rest\n },\n ref\n ) => {\n if (!visible) return null;\n\n const prefersReducedMotion = useReducedMotion();\n const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);\n\n return (\n <div\n ref={ref}\n data-testid={testId}\n className={cn('inline-flex items-center justify-center gap-2', className)}\n style={{\n height: normalizeSize(size),\n ...style,\n }}\n role=\"status\"\n aria-label={ariaLabel}\n aria-busy=\"true\"\n {...rest}\n >\n {Array.from({ length: dotCount }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-full\"\n style={{\n width: normalizeSize(dotSize),\n height: normalizeSize(dotSize),\n backgroundColor: color,\n animation: `pulse-bounce ${effectiveDuration} ease-in-out infinite`,\n animationDelay: reverse ? `${(dotCount - index - 1) * 0.15}s` : `${index * 0.15}s`,\n }}\n />\n ))}\n </div>\n );\n }\n);\n\nPulseDots.displayName = 'PulseDots';\n"],"names":["forwardRef","useReducedMotion","getEffectiveDuration","jsx","cn","normalizeSize"],"mappings":";;;;;;;AAeO,MAAM,YAAYA,MAAAA;AAAAA,EACvB,CACE;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,GAAG;AAAA,EAAA,GAEL,QACG;AACH,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,uBAAuBC,MAAAA,iBAAA;AAC7B,UAAM,oBAAoBC,MAAAA,qBAAqB,OAAO,yBAAyB,oBAAoB;AAEnG,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,eAAa;AAAA,QACb,WAAWC,WAAAA,GAAG,iDAAiD,SAAS;AAAA,QACxE,OAAO;AAAA,UACL,QAAQC,OAAAA,cAAc,IAAI;AAAA,UAC1B,GAAG;AAAA,QAAA;AAAA,QAEL,MAAK;AAAA,QACL,cAAY;AAAA,QACZ,aAAU;AAAA,QACT,GAAG;AAAA,QAEH,UAAA,MAAM,KAAK,EAAE,QAAQ,UAAU,EAAE,IAAI,CAAC,GAAG,UACxCF,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YACV,OAAO;AAAA,cACL,OAAOE,OAAAA,cAAc,OAAO;AAAA,cAC5B,QAAQA,OAAAA,cAAc,OAAO;AAAA,cAC7B,iBAAiB;AAAA,cACjB,WAAW,gBAAgB,iBAAiB;AAAA,cAC5C,gBAAgB,UAAU,IAAI,WAAW,QAAQ,KAAK,IAAI,MAAM,GAAG,QAAQ,IAAI;AAAA,YAAA;AAAA,UACjF;AAAA,UARK;AAAA,QAAA,CAUR;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,UAAU,cAAc;;"}