premium-react-loaders 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +203 -3
  2. package/dist/components/pulse/TypingIndicator.d.ts.map +1 -1
  3. package/dist/context/ThemeContext.d.ts +84 -0
  4. package/dist/context/ThemeContext.d.ts.map +1 -0
  5. package/dist/context/index.d.ts +3 -0
  6. package/dist/context/index.d.ts.map +1 -0
  7. package/dist/hooks/index.d.ts +3 -0
  8. package/dist/hooks/index.d.ts.map +1 -0
  9. package/dist/hooks/useLoader.d.ts +56 -0
  10. package/dist/hooks/useLoader.d.ts.map +1 -0
  11. package/dist/index.cjs +31 -26
  12. package/dist/index.d.ts +5 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +31 -26
  15. package/dist/index10.cjs +20 -31
  16. package/dist/index10.js +20 -31
  17. package/dist/index11.cjs +47 -25
  18. package/dist/index11.js +47 -25
  19. package/dist/index12.cjs +30 -126
  20. package/dist/index12.js +31 -127
  21. package/dist/index13.cjs +30 -53
  22. package/dist/index13.js +30 -53
  23. package/dist/index14.cjs +127 -43
  24. package/dist/index14.js +128 -44
  25. package/dist/index15.cjs +58 -37
  26. package/dist/index15.js +59 -38
  27. package/dist/index16.cjs +24 -36
  28. package/dist/index16.js +24 -36
  29. package/dist/index17.cjs +19 -21
  30. package/dist/index17.js +19 -21
  31. package/dist/index18.cjs +25 -20
  32. package/dist/index18.js +25 -20
  33. package/dist/index19.cjs +22 -32
  34. package/dist/index19.js +22 -32
  35. package/dist/index20.cjs +26 -35
  36. package/dist/index20.js +28 -37
  37. package/dist/index21.cjs +40 -76
  38. package/dist/index21.js +42 -78
  39. package/dist/index22.cjs +53 -102
  40. package/dist/index22.js +54 -103
  41. package/dist/index23.cjs +46 -80
  42. package/dist/index23.js +47 -81
  43. package/dist/index24.cjs +105 -103
  44. package/dist/index24.js +107 -105
  45. package/dist/index25.cjs +108 -27
  46. package/dist/index25.js +111 -30
  47. package/dist/index26.cjs +104 -36
  48. package/dist/index26.js +106 -38
  49. package/dist/index27.cjs +22 -30
  50. package/dist/index27.js +23 -31
  51. package/dist/index28.cjs +30 -29
  52. package/dist/index28.js +31 -30
  53. package/dist/index29.cjs +49 -52
  54. package/dist/index29.js +50 -53
  55. package/dist/index30.cjs +74 -121
  56. package/dist/index30.js +75 -122
  57. package/dist/index31.cjs +82 -0
  58. package/dist/index31.js +82 -0
  59. package/dist/index32.cjs +125 -0
  60. package/dist/index32.js +125 -0
  61. package/dist/index5.cjs +11 -72
  62. package/dist/index5.js +12 -73
  63. package/dist/index6.cjs +86 -65
  64. package/dist/index6.js +87 -66
  65. package/dist/index7.cjs +40 -20
  66. package/dist/index7.js +40 -20
  67. package/dist/index8.cjs +34 -21
  68. package/dist/index8.js +34 -21
  69. package/dist/index9.cjs +21 -55
  70. package/dist/index9.js +22 -56
  71. package/dist/premium-react-loaders.css +38 -6
  72. package/package.json +1 -1
package/dist/index30.js CHANGED
@@ -1,125 +1,78 @@
1
- import { useState, useRef, useEffect } from "react";
2
- function useReducedMotion() {
3
- const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
4
- useEffect(() => {
5
- if (typeof window === "undefined" || !window.matchMedia) {
6
- return;
7
- }
8
- const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
9
- setPrefersReducedMotion(mediaQuery.matches);
10
- const handleChange = (event) => {
11
- setPrefersReducedMotion(event.matches);
12
- };
13
- if (mediaQuery.addEventListener) {
14
- mediaQuery.addEventListener("change", handleChange);
15
- return () => mediaQuery.removeEventListener("change", handleChange);
16
- } else {
17
- mediaQuery.addListener(handleChange);
18
- return () => mediaQuery.removeListener(handleChange);
19
- }
20
- }, []);
21
- return prefersReducedMotion;
22
- }
23
- function getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion) {
24
- if (respectMotionPreference && prefersReducedMotion) {
25
- return "0.01ms";
26
- }
27
- if (typeof speed === "number") {
28
- const validSpeed = !isNaN(speed) && speed > 0 ? Math.max(50, Math.min(1e4, speed)) : 1e3;
29
- return `${validSpeed}ms`;
30
- }
31
- const speedMap = {
32
- slow: "2s",
33
- normal: "1s",
34
- fast: "0.5s"
35
- };
36
- return speedMap[speed] || speedMap.normal;
37
- }
38
- function useLoaderVisibility(visible = true, delay = 0, minDuration = 0, transition) {
39
- const transitionDuration = transition === true ? 150 : typeof transition === "number" ? transition : 0;
40
- const hasTransition = transitionDuration > 0;
41
- const [shouldRender, setShouldRender] = useState(visible && delay === 0);
42
- const [isTransitioning, setIsTransitioning] = useState(visible && delay === 0 && hasTransition);
43
- const showTimeRef = useRef(visible && delay === 0 ? Date.now() : null);
44
- const delayTimerRef = useRef(null);
45
- const minDurationTimerRef = useRef(null);
46
- const transitionTimerRef = useRef(null);
47
- useEffect(() => {
48
- if (delayTimerRef.current) {
49
- clearTimeout(delayTimerRef.current);
50
- delayTimerRef.current = null;
51
- }
52
- if (minDurationTimerRef.current) {
53
- clearTimeout(minDurationTimerRef.current);
54
- minDurationTimerRef.current = null;
55
- }
56
- if (transitionTimerRef.current) {
57
- clearTimeout(transitionTimerRef.current);
58
- transitionTimerRef.current = null;
59
- }
60
- if (visible) {
61
- if (delay > 0) {
62
- delayTimerRef.current = setTimeout(() => {
63
- setShouldRender(true);
64
- showTimeRef.current = Date.now();
65
- if (hasTransition) {
66
- setIsTransitioning(true);
67
- }
68
- }, delay);
69
- } else {
70
- setShouldRender(true);
71
- showTimeRef.current = Date.now();
72
- if (hasTransition) {
73
- setIsTransitioning(true);
74
- }
75
- }
76
- } else {
77
- const hideLoader = () => {
78
- if (hasTransition) {
79
- setIsTransitioning(false);
80
- transitionTimerRef.current = setTimeout(() => {
81
- setShouldRender(false);
82
- showTimeRef.current = null;
83
- }, transitionDuration);
84
- } else {
85
- setShouldRender(false);
86
- showTimeRef.current = null;
87
- }
88
- };
89
- if (showTimeRef.current !== null && minDuration > 0) {
90
- const elapsedTime = Date.now() - showTimeRef.current;
91
- const remainingTime = minDuration - elapsedTime;
92
- if (remainingTime > 0) {
93
- minDurationTimerRef.current = setTimeout(hideLoader, remainingTime);
94
- } else {
95
- hideLoader();
96
- }
97
- } else {
98
- hideLoader();
99
- }
100
- }
101
- return () => {
102
- if (delayTimerRef.current) {
103
- clearTimeout(delayTimerRef.current);
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useReducedMotion, useLoaderVisibility, getEffectiveDuration } from "./index32.js";
4
+ import { normalizeSize } from "./index4.js";
5
+ import { cn } from "./index3.js";
6
+ const TypingIndicator = forwardRef(
7
+ ({
8
+ size,
9
+ color = "#3b82f6",
10
+ dotCount = 3,
11
+ dotSize = 8,
12
+ gap = 4,
13
+ variant = "bounce",
14
+ speed = "normal",
15
+ reverse = false,
16
+ respectMotionPreference = true,
17
+ delay = 0,
18
+ minDuration = 0,
19
+ transition,
20
+ className,
21
+ style,
22
+ testId = "typing-indicator",
23
+ visible = true,
24
+ ariaLabel = "Typing...",
25
+ ...rest
26
+ }, ref) => {
27
+ const prefersReducedMotion = useReducedMotion();
28
+ const effectiveDuration = getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion);
29
+ const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(
30
+ visible,
31
+ delay,
32
+ minDuration,
33
+ transition
34
+ );
35
+ if (!shouldRender) return null;
36
+ const gapValue = normalizeSize(gap);
37
+ const durationMs = typeof effectiveDuration === "string" ? parseFloat(effectiveDuration) * 1e3 : effectiveDuration;
38
+ const delayBetweenDots = durationMs * 0.15 / 1e3;
39
+ return /* @__PURE__ */ jsx(
40
+ "div",
41
+ {
42
+ ref,
43
+ "data-testid": testId,
44
+ className: cn("inline-flex items-center", className),
45
+ style: {
46
+ gap: gapValue,
47
+ height: size ? normalizeSize(size) : "auto",
48
+ ...style,
49
+ opacity,
50
+ transition: transitionStyle
51
+ },
52
+ role: "status",
53
+ "aria-label": ariaLabel,
54
+ "aria-busy": "true",
55
+ ...rest,
56
+ children: Array.from({ length: dotCount }).map((_, index) => /* @__PURE__ */ jsx(
57
+ "div",
58
+ {
59
+ className: "rounded-full",
60
+ style: {
61
+ width: normalizeSize(dotSize),
62
+ height: normalizeSize(dotSize),
63
+ backgroundColor: color,
64
+ animation: `typing-${variant} ${effectiveDuration} ease-in-out infinite`,
65
+ animationDelay: reverse ? `${(dotCount - index - 1) * delayBetweenDots}s` : `${index * delayBetweenDots}s`,
66
+ willChange: "transform, opacity"
67
+ }
68
+ },
69
+ index
70
+ ))
104
71
  }
105
- if (minDurationTimerRef.current) {
106
- clearTimeout(minDurationTimerRef.current);
107
- }
108
- if (transitionTimerRef.current) {
109
- clearTimeout(transitionTimerRef.current);
110
- }
111
- };
112
- }, [visible, delay, minDuration, hasTransition, transitionDuration]);
113
- const opacity = hasTransition ? isTransitioning ? 1 : 0 : 1;
114
- const transitionStyle = hasTransition ? `opacity ${transitionDuration}ms ease-in-out` : "none";
115
- return {
116
- shouldRender,
117
- opacity,
118
- transitionStyle
119
- };
120
- }
72
+ );
73
+ }
74
+ );
75
+ TypingIndicator.displayName = "TypingIndicator";
121
76
  export {
122
- getEffectiveDuration,
123
- useLoaderVisibility,
124
- useReducedMotion
77
+ TypingIndicator
125
78
  };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const hooks = require("./index32.cjs");
6
+ const classNames = require("./index3.cjs");
7
+ const LoaderOverlay = react.forwardRef(
8
+ ({
9
+ loading = false,
10
+ loader,
11
+ children,
12
+ position = "fixed",
13
+ backdropOpacity = 0.5,
14
+ backdropColor = "#000000",
15
+ blur = false,
16
+ delay = 0,
17
+ minDuration = 0,
18
+ transition,
19
+ className,
20
+ style,
21
+ testId = "loader-overlay",
22
+ ariaLabel = "Loading content...",
23
+ zIndex = 9999,
24
+ ...rest
25
+ }, ref) => {
26
+ const { shouldRender, opacity, transitionStyle } = hooks.useLoaderVisibility(
27
+ loading,
28
+ delay,
29
+ minDuration,
30
+ transition
31
+ );
32
+ const backdropStyles = {
33
+ backgroundColor: backdropColor,
34
+ opacity: backdropOpacity,
35
+ backdropFilter: blur ? "blur(4px)" : void 0,
36
+ WebkitBackdropFilter: blur ? "blur(4px)" : void 0
37
+ };
38
+ return /* @__PURE__ */ jsxRuntime.jsxs(
39
+ "div",
40
+ {
41
+ ref,
42
+ "data-testid": testId,
43
+ className: classNames.cn("relative", className),
44
+ style,
45
+ ...rest,
46
+ children: [
47
+ children,
48
+ shouldRender && /* @__PURE__ */ jsxRuntime.jsxs(
49
+ "div",
50
+ {
51
+ className: classNames.cn(
52
+ "inset-0 flex items-center justify-center",
53
+ position === "fixed" ? "fixed" : "absolute"
54
+ ),
55
+ style: {
56
+ zIndex,
57
+ opacity,
58
+ transition: transitionStyle
59
+ },
60
+ role: "status",
61
+ "aria-label": ariaLabel,
62
+ "aria-busy": "true",
63
+ children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx(
65
+ "div",
66
+ {
67
+ className: "absolute inset-0",
68
+ style: backdropStyles,
69
+ "aria-hidden": "true"
70
+ }
71
+ ),
72
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10", children: loader })
73
+ ]
74
+ }
75
+ )
76
+ ]
77
+ }
78
+ );
79
+ }
80
+ );
81
+ LoaderOverlay.displayName = "LoaderOverlay";
82
+ exports.LoaderOverlay = LoaderOverlay;
@@ -0,0 +1,82 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from "react";
3
+ import { useLoaderVisibility } from "./index32.js";
4
+ import { cn } from "./index3.js";
5
+ const LoaderOverlay = forwardRef(
6
+ ({
7
+ loading = false,
8
+ loader,
9
+ children,
10
+ position = "fixed",
11
+ backdropOpacity = 0.5,
12
+ backdropColor = "#000000",
13
+ blur = false,
14
+ delay = 0,
15
+ minDuration = 0,
16
+ transition,
17
+ className,
18
+ style,
19
+ testId = "loader-overlay",
20
+ ariaLabel = "Loading content...",
21
+ zIndex = 9999,
22
+ ...rest
23
+ }, ref) => {
24
+ const { shouldRender, opacity, transitionStyle } = useLoaderVisibility(
25
+ loading,
26
+ delay,
27
+ minDuration,
28
+ transition
29
+ );
30
+ const backdropStyles = {
31
+ backgroundColor: backdropColor,
32
+ opacity: backdropOpacity,
33
+ backdropFilter: blur ? "blur(4px)" : void 0,
34
+ WebkitBackdropFilter: blur ? "blur(4px)" : void 0
35
+ };
36
+ return /* @__PURE__ */ jsxs(
37
+ "div",
38
+ {
39
+ ref,
40
+ "data-testid": testId,
41
+ className: cn("relative", className),
42
+ style,
43
+ ...rest,
44
+ children: [
45
+ children,
46
+ shouldRender && /* @__PURE__ */ jsxs(
47
+ "div",
48
+ {
49
+ className: cn(
50
+ "inset-0 flex items-center justify-center",
51
+ position === "fixed" ? "fixed" : "absolute"
52
+ ),
53
+ style: {
54
+ zIndex,
55
+ opacity,
56
+ transition: transitionStyle
57
+ },
58
+ role: "status",
59
+ "aria-label": ariaLabel,
60
+ "aria-busy": "true",
61
+ children: [
62
+ /* @__PURE__ */ jsx(
63
+ "div",
64
+ {
65
+ className: "absolute inset-0",
66
+ style: backdropStyles,
67
+ "aria-hidden": "true"
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx("div", { className: "relative z-10", children: loader })
71
+ ]
72
+ }
73
+ )
74
+ ]
75
+ }
76
+ );
77
+ }
78
+ );
79
+ LoaderOverlay.displayName = "LoaderOverlay";
80
+ export {
81
+ LoaderOverlay
82
+ };
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ function useReducedMotion() {
5
+ const [prefersReducedMotion, setPrefersReducedMotion] = react.useState(false);
6
+ react.useEffect(() => {
7
+ if (typeof window === "undefined" || !window.matchMedia) {
8
+ return;
9
+ }
10
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
11
+ setPrefersReducedMotion(mediaQuery.matches);
12
+ const handleChange = (event) => {
13
+ setPrefersReducedMotion(event.matches);
14
+ };
15
+ if (mediaQuery.addEventListener) {
16
+ mediaQuery.addEventListener("change", handleChange);
17
+ return () => mediaQuery.removeEventListener("change", handleChange);
18
+ } else {
19
+ mediaQuery.addListener(handleChange);
20
+ return () => mediaQuery.removeListener(handleChange);
21
+ }
22
+ }, []);
23
+ return prefersReducedMotion;
24
+ }
25
+ function getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion) {
26
+ if (respectMotionPreference && prefersReducedMotion) {
27
+ return "0.01ms";
28
+ }
29
+ if (typeof speed === "number") {
30
+ const validSpeed = !isNaN(speed) && speed > 0 ? Math.max(50, Math.min(1e4, speed)) : 1e3;
31
+ return `${validSpeed}ms`;
32
+ }
33
+ const speedMap = {
34
+ slow: "2s",
35
+ normal: "1s",
36
+ fast: "0.5s"
37
+ };
38
+ return speedMap[speed] || speedMap.normal;
39
+ }
40
+ function useLoaderVisibility(visible = true, delay = 0, minDuration = 0, transition) {
41
+ const transitionDuration = transition === true ? 150 : typeof transition === "number" ? transition : 0;
42
+ const hasTransition = transitionDuration > 0;
43
+ const [shouldRender, setShouldRender] = react.useState(visible && delay === 0);
44
+ const [isTransitioning, setIsTransitioning] = react.useState(visible && delay === 0 && hasTransition);
45
+ const showTimeRef = react.useRef(visible && delay === 0 ? Date.now() : null);
46
+ const delayTimerRef = react.useRef(null);
47
+ const minDurationTimerRef = react.useRef(null);
48
+ const transitionTimerRef = react.useRef(null);
49
+ react.useEffect(() => {
50
+ if (delayTimerRef.current) {
51
+ clearTimeout(delayTimerRef.current);
52
+ delayTimerRef.current = null;
53
+ }
54
+ if (minDurationTimerRef.current) {
55
+ clearTimeout(minDurationTimerRef.current);
56
+ minDurationTimerRef.current = null;
57
+ }
58
+ if (transitionTimerRef.current) {
59
+ clearTimeout(transitionTimerRef.current);
60
+ transitionTimerRef.current = null;
61
+ }
62
+ if (visible) {
63
+ if (delay > 0) {
64
+ delayTimerRef.current = setTimeout(() => {
65
+ setShouldRender(true);
66
+ showTimeRef.current = Date.now();
67
+ if (hasTransition) {
68
+ setIsTransitioning(true);
69
+ }
70
+ }, delay);
71
+ } else {
72
+ setShouldRender(true);
73
+ showTimeRef.current = Date.now();
74
+ if (hasTransition) {
75
+ setIsTransitioning(true);
76
+ }
77
+ }
78
+ } else {
79
+ const hideLoader = () => {
80
+ if (hasTransition) {
81
+ setIsTransitioning(false);
82
+ transitionTimerRef.current = setTimeout(() => {
83
+ setShouldRender(false);
84
+ showTimeRef.current = null;
85
+ }, transitionDuration);
86
+ } else {
87
+ setShouldRender(false);
88
+ showTimeRef.current = null;
89
+ }
90
+ };
91
+ if (showTimeRef.current !== null && minDuration > 0) {
92
+ const elapsedTime = Date.now() - showTimeRef.current;
93
+ const remainingTime = minDuration - elapsedTime;
94
+ if (remainingTime > 0) {
95
+ minDurationTimerRef.current = setTimeout(hideLoader, remainingTime);
96
+ } else {
97
+ hideLoader();
98
+ }
99
+ } else {
100
+ hideLoader();
101
+ }
102
+ }
103
+ return () => {
104
+ if (delayTimerRef.current) {
105
+ clearTimeout(delayTimerRef.current);
106
+ }
107
+ if (minDurationTimerRef.current) {
108
+ clearTimeout(minDurationTimerRef.current);
109
+ }
110
+ if (transitionTimerRef.current) {
111
+ clearTimeout(transitionTimerRef.current);
112
+ }
113
+ };
114
+ }, [visible, delay, minDuration, hasTransition, transitionDuration]);
115
+ const opacity = hasTransition ? isTransitioning ? 1 : 0 : 1;
116
+ const transitionStyle = hasTransition ? `opacity ${transitionDuration}ms ease-in-out` : "none";
117
+ return {
118
+ shouldRender,
119
+ opacity,
120
+ transitionStyle
121
+ };
122
+ }
123
+ exports.getEffectiveDuration = getEffectiveDuration;
124
+ exports.useLoaderVisibility = useLoaderVisibility;
125
+ exports.useReducedMotion = useReducedMotion;
@@ -0,0 +1,125 @@
1
+ import { useState, useRef, useEffect } from "react";
2
+ function useReducedMotion() {
3
+ const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
4
+ useEffect(() => {
5
+ if (typeof window === "undefined" || !window.matchMedia) {
6
+ return;
7
+ }
8
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
9
+ setPrefersReducedMotion(mediaQuery.matches);
10
+ const handleChange = (event) => {
11
+ setPrefersReducedMotion(event.matches);
12
+ };
13
+ if (mediaQuery.addEventListener) {
14
+ mediaQuery.addEventListener("change", handleChange);
15
+ return () => mediaQuery.removeEventListener("change", handleChange);
16
+ } else {
17
+ mediaQuery.addListener(handleChange);
18
+ return () => mediaQuery.removeListener(handleChange);
19
+ }
20
+ }, []);
21
+ return prefersReducedMotion;
22
+ }
23
+ function getEffectiveDuration(speed, respectMotionPreference, prefersReducedMotion) {
24
+ if (respectMotionPreference && prefersReducedMotion) {
25
+ return "0.01ms";
26
+ }
27
+ if (typeof speed === "number") {
28
+ const validSpeed = !isNaN(speed) && speed > 0 ? Math.max(50, Math.min(1e4, speed)) : 1e3;
29
+ return `${validSpeed}ms`;
30
+ }
31
+ const speedMap = {
32
+ slow: "2s",
33
+ normal: "1s",
34
+ fast: "0.5s"
35
+ };
36
+ return speedMap[speed] || speedMap.normal;
37
+ }
38
+ function useLoaderVisibility(visible = true, delay = 0, minDuration = 0, transition) {
39
+ const transitionDuration = transition === true ? 150 : typeof transition === "number" ? transition : 0;
40
+ const hasTransition = transitionDuration > 0;
41
+ const [shouldRender, setShouldRender] = useState(visible && delay === 0);
42
+ const [isTransitioning, setIsTransitioning] = useState(visible && delay === 0 && hasTransition);
43
+ const showTimeRef = useRef(visible && delay === 0 ? Date.now() : null);
44
+ const delayTimerRef = useRef(null);
45
+ const minDurationTimerRef = useRef(null);
46
+ const transitionTimerRef = useRef(null);
47
+ useEffect(() => {
48
+ if (delayTimerRef.current) {
49
+ clearTimeout(delayTimerRef.current);
50
+ delayTimerRef.current = null;
51
+ }
52
+ if (minDurationTimerRef.current) {
53
+ clearTimeout(minDurationTimerRef.current);
54
+ minDurationTimerRef.current = null;
55
+ }
56
+ if (transitionTimerRef.current) {
57
+ clearTimeout(transitionTimerRef.current);
58
+ transitionTimerRef.current = null;
59
+ }
60
+ if (visible) {
61
+ if (delay > 0) {
62
+ delayTimerRef.current = setTimeout(() => {
63
+ setShouldRender(true);
64
+ showTimeRef.current = Date.now();
65
+ if (hasTransition) {
66
+ setIsTransitioning(true);
67
+ }
68
+ }, delay);
69
+ } else {
70
+ setShouldRender(true);
71
+ showTimeRef.current = Date.now();
72
+ if (hasTransition) {
73
+ setIsTransitioning(true);
74
+ }
75
+ }
76
+ } else {
77
+ const hideLoader = () => {
78
+ if (hasTransition) {
79
+ setIsTransitioning(false);
80
+ transitionTimerRef.current = setTimeout(() => {
81
+ setShouldRender(false);
82
+ showTimeRef.current = null;
83
+ }, transitionDuration);
84
+ } else {
85
+ setShouldRender(false);
86
+ showTimeRef.current = null;
87
+ }
88
+ };
89
+ if (showTimeRef.current !== null && minDuration > 0) {
90
+ const elapsedTime = Date.now() - showTimeRef.current;
91
+ const remainingTime = minDuration - elapsedTime;
92
+ if (remainingTime > 0) {
93
+ minDurationTimerRef.current = setTimeout(hideLoader, remainingTime);
94
+ } else {
95
+ hideLoader();
96
+ }
97
+ } else {
98
+ hideLoader();
99
+ }
100
+ }
101
+ return () => {
102
+ if (delayTimerRef.current) {
103
+ clearTimeout(delayTimerRef.current);
104
+ }
105
+ if (minDurationTimerRef.current) {
106
+ clearTimeout(minDurationTimerRef.current);
107
+ }
108
+ if (transitionTimerRef.current) {
109
+ clearTimeout(transitionTimerRef.current);
110
+ }
111
+ };
112
+ }, [visible, delay, minDuration, hasTransition, transitionDuration]);
113
+ const opacity = hasTransition ? isTransitioning ? 1 : 0 : 1;
114
+ const transitionStyle = hasTransition ? `opacity ${transitionDuration}ms ease-in-out` : "none";
115
+ return {
116
+ shouldRender,
117
+ opacity,
118
+ transitionStyle
119
+ };
120
+ }
121
+ export {
122
+ getEffectiveDuration,
123
+ useLoaderVisibility,
124
+ useReducedMotion
125
+ };