beez-ui 2.7.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +43 -13
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/components/account-menu.d.ts +4 -3
  5. package/dist/components/account-menu.js +63 -54
  6. package/dist/components/alert.d.ts +15 -15
  7. package/dist/components/alert.js +289 -270
  8. package/dist/components/animated-theme-toggler.js +1 -1
  9. package/dist/components/avatar.d.ts +56 -31
  10. package/dist/components/avatar.js +394 -277
  11. package/dist/components/badge.d.ts +8 -28
  12. package/dist/components/badge.js +55 -108
  13. package/dist/components/calendar.d.ts +36 -26
  14. package/dist/components/calendar.js +132 -1227
  15. package/dist/components/card.d.ts +36 -25
  16. package/dist/components/card.js +895 -72
  17. package/dist/components/carousel.d.ts +63 -47
  18. package/dist/components/carousel.js +496 -777
  19. package/dist/components/data-table.d.ts +5 -4
  20. package/dist/components/data-table.js +7 -6
  21. package/dist/components/dialog-surface.d.ts +23 -1
  22. package/dist/components/dialog-surface.js +99 -3
  23. package/dist/components/dialog.d.ts +80 -45
  24. package/dist/components/dialog.js +258 -503
  25. package/dist/components/dropdown-menu.d.ts +56 -73
  26. package/dist/components/dropdown-menu.js +79 -714
  27. package/dist/components/field.d.ts +3 -1
  28. package/dist/components/field.js +49 -39
  29. package/dist/components/filter-presets-bar.js +2 -2
  30. package/dist/components/filter-query-bar.js +1 -1
  31. package/dist/components/hover-card.d.ts +42 -41
  32. package/dist/components/hover-card.js +57 -483
  33. package/dist/components/pagination.d.ts +53 -31
  34. package/dist/components/pagination.js +176 -412
  35. package/dist/components/popover.d.ts +11 -23
  36. package/dist/components/popover.js +19 -304
  37. package/dist/components/{alert-dialog.d.ts → primitives/alert-dialog.d.ts} +17 -5
  38. package/dist/components/{alert-dialog.js → primitives/alert-dialog.js} +102 -54
  39. package/dist/components/primitives/avatar.d.ts +46 -0
  40. package/dist/components/primitives/avatar.js +268 -0
  41. package/dist/components/primitives/calendar.d.ts +37 -0
  42. package/dist/components/primitives/calendar.js +1250 -0
  43. package/dist/components/primitives/carousel.d.ts +106 -0
  44. package/dist/components/primitives/carousel.js +928 -0
  45. package/dist/components/primitives/dialog.d.ts +62 -0
  46. package/dist/components/primitives/dialog.js +490 -0
  47. package/dist/components/primitives/dropdown-menu-items.d.ts +59 -0
  48. package/dist/components/primitives/dropdown-menu-items.js +265 -0
  49. package/dist/components/primitives/dropdown-menu.d.ts +64 -0
  50. package/dist/components/primitives/dropdown-menu.js +557 -0
  51. package/dist/components/primitives/hover-card.d.ts +50 -0
  52. package/dist/components/primitives/hover-card.js +507 -0
  53. package/dist/components/primitives/pagination.d.ts +65 -0
  54. package/dist/components/primitives/pagination.js +373 -0
  55. package/dist/components/primitives/popover.d.ts +22 -0
  56. package/dist/components/primitives/popover.js +213 -0
  57. package/dist/components/primitives/select.d.ts +36 -0
  58. package/dist/components/primitives/select.js +407 -0
  59. package/dist/components/primitives/tooltip.d.ts +30 -0
  60. package/dist/components/primitives/tooltip.js +277 -0
  61. package/dist/components/radio-group.d.ts +30 -17
  62. package/dist/components/radio-group.js +266 -315
  63. package/dist/components/rich-link-editor.js +1 -1
  64. package/dist/components/select.d.ts +51 -42
  65. package/dist/components/select.js +163 -495
  66. package/dist/components/skeleton.d.ts +16 -15
  67. package/dist/components/skeleton.js +99 -205
  68. package/dist/components/split-button.js +1 -1
  69. package/dist/components/switch.d.ts +3 -6
  70. package/dist/components/switch.js +163 -170
  71. package/dist/components/tabs.d.ts +3 -11
  72. package/dist/components/tabs.js +61 -75
  73. package/dist/components/themed-toaster.d.ts +1 -1
  74. package/dist/components/themed-toaster.js +1 -1
  75. package/dist/components/toaster.d.ts +1 -1
  76. package/dist/components/toaster.js +1 -1
  77. package/dist/components/tooltip.d.ts +36 -31
  78. package/dist/components/tooltip.js +44 -284
  79. package/dist/constants/alert.d.ts +5 -1
  80. package/dist/constants/alert.js +5 -1
  81. package/dist/constants/avatar.d.ts +29 -1
  82. package/dist/constants/avatar.js +25 -0
  83. package/dist/constants/calendar.d.ts +12 -0
  84. package/dist/constants/calendar.js +12 -0
  85. package/dist/constants/card.d.ts +23 -0
  86. package/dist/constants/card.js +20 -0
  87. package/dist/constants/carousel.d.ts +31 -13
  88. package/dist/constants/carousel.js +32 -11
  89. package/dist/constants/dialog.d.ts +6 -1
  90. package/dist/constants/dialog.js +5 -1
  91. package/dist/constants/dropdown-menu.d.ts +2 -2
  92. package/dist/constants/dropdown-menu.js +2 -2
  93. package/dist/constants/pagination.d.ts +13 -2
  94. package/dist/constants/pagination.js +13 -2
  95. package/dist/constants/select.d.ts +4 -2
  96. package/dist/constants/select.js +4 -2
  97. package/dist/constants/switch.d.ts +5 -16
  98. package/dist/constants/switch.js +6 -14
  99. package/dist/hooks/use-today.d.ts +7 -0
  100. package/dist/hooks/use-today.js +50 -0
  101. package/dist/hooks.d.ts +1 -0
  102. package/dist/hooks.js +1 -0
  103. package/dist/index.d.ts +0 -1
  104. package/dist/index.js +0 -1
  105. package/dist/motion/glide-indicator.d.ts +1 -1
  106. package/dist/motion/glide-indicator.js +1 -1
  107. package/dist/motion/presence.d.ts +0 -1
  108. package/dist/motion/presence.js +0 -1
  109. package/dist/styles.css +1 -1
  110. package/package.json +1 -6
@@ -1,298 +1,395 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  /**
4
- * Carousel on Embla with Arc's carousel design (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): round
5
- * outlined controls on the surface that answer hover on fine pointers and press in, a grab cursor while the track can
6
- * be dragged, Home and End to reach the edges, and optional Arc indicators whose pill stretches and travels with the
7
- * slides frame by frame. Embla keeps dragging, snapping, looping and plugins.
4
+ * Arc's Carousel (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md) as a closed component: one child per
5
+ * slide, a centered slide row that is dragged, flicked or arrowed through, and a control row under it with an optional
6
+ * rotation control, the indicator tab list and the arrows. Embla runs inside and is never exposed; the beez-ui
7
+ * extensions (`loop`, `duration`, `watchFocus`, `onSettle`, deferred re-initialization, labels and visibility of the
8
+ * controls) cover media viewers that used Embla's API directly.
8
9
  */
9
10
  import * as React from "react";
10
- import useEmblaCarousel from "embla-carousel-react";
11
- import { animate, motion, useMotionValue, useTransform } from "motion/react";
12
- import { CAROUSEL_COPY, CAROUSEL_EDGE_KEYS, CAROUSEL_INDICATOR_LENGTH_PX, CAROUSEL_KEYS, CAROUSEL_OWN_KEYBOARD_SELECTOR, CAROUSEL_ROOT_SELECTOR } from "../constants/carousel.js";
11
+ import { AnimatePresence, animate, motion, useMotionValue } from "motion/react";
12
+ import { Pause, Play } from "lucide-react";
13
+ import { CAROUSEL_COPY, CAROUSEL_DEFAULT_SLIDE_SIZE, CAROUSEL_ROTATION_ICON_ENTER_SCALE, CAROUSEL_ROTATION_ICON_SIZE_PX, CAROUSEL_SLIDE_SIZE_PROPERTY } from "../constants/carousel.js";
14
+ import { useIsHydrated } from "../hooks/use-is-hydrated.js";
13
15
  import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
14
- import { ARC_SPRING_SMOOTH } from "../motion/arc-tokens.js";
16
+ import { ARC_BLUR, ARC_DURATION, ARC_EASE, ARC_SPRING_SNAPPY } from "../motion/arc-tokens.js";
15
17
  import { cn } from "../lib/utils.js";
16
18
  import { ControlButton } from "./control-button.js";
17
- import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
19
+ import { Carousel as CarouselRoot, CarouselContent, CarouselIndicators, CarouselItem, CarouselNext, CarouselPrevious, defaultCarouselSlideLabel } from "./primitives/carousel.js";
18
20
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
- const CarouselContext = React.createContext(null);
20
- function useCarousel() {
21
- const context = React.useContext(CarouselContext);
22
- if (!context) {
23
- throw new Error("useCarousel must be used within a <Carousel />");
24
- }
25
- return context;
21
+ /**
22
+ * Clamps a slide index to the slides that exist.
23
+ * @param index - Requested index.
24
+ * @param count - Number of slides.
25
+ * @returns An index between 0 and the last slide.
26
+ */
27
+ function clampSlideIndex(index, count) {
28
+ return Math.min(Math.max(0, count - 1), Math.max(0, index));
26
29
  }
27
- /** Arc's round control on the surface: outlined, a fill on hover-capable pointers and a dimmed disabled state. */
28
- const carouselControlClassName = "absolute touch-manipulation rounded-full border-border bg-surface text-foreground hover-fine:not-disabled:bg-surface-muted disabled:bg-surface disabled:text-text-muted disabled:opacity-50 [&_svg:not([class*='size-'])]:size-[18px]";
29
- function Carousel(t0) {
30
- const $ = _c(50);
31
- let children;
32
- let className;
33
- let opts;
34
- let plugins;
35
- let props;
36
- let setApi;
37
- let t1;
38
- if ($[0] !== t0) {
39
- ({orientation: t1, opts, setApi, plugins, className, children, ...props} = t0);
40
- $[0] = t0;
41
- $[1] = children;
42
- $[2] = className;
43
- $[3] = opts;
44
- $[4] = plugins;
45
- $[5] = props;
46
- $[6] = setApi;
47
- $[7] = t1;
48
- } else {
49
- children = $[1];
50
- className = $[2];
51
- opts = $[3];
52
- plugins = $[4];
53
- props = $[5];
54
- setApi = $[6];
55
- t1 = $[7];
56
- }
57
- const orientation = t1 === undefined ? "horizontal" : t1;
58
- const shouldReduceMotion = usePrefersReducedMotion();
59
- const t2 = orientation === "horizontal" ? "x" : "y";
60
- let t3;
61
- if ($[8] !== opts || $[9] !== t2) {
62
- t3 = {
63
- ...opts,
64
- axis: t2
65
- };
66
- $[8] = opts;
67
- $[9] = t2;
68
- $[10] = t3;
69
- } else {
70
- t3 = $[10];
71
- }
72
- const [carouselRef, api] = useEmblaCarousel(t3, plugins);
73
- const [canScrollPrev, setCanScrollPrev] = React.useState(false);
74
- const [canScrollNext, setCanScrollNext] = React.useState(false);
75
- let t4;
76
- if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
77
- t4 = (api_0) => {
78
- if (!api_0) {
79
- return;
30
+ /** Rotation icon entering from a small, blurred state, as in Arc. */
31
+ const rotationIconHidden = {
32
+ opacity: 0,
33
+ scale: CAROUSEL_ROTATION_ICON_ENTER_SCALE,
34
+ filter: `blur(${ARC_BLUR.subtle}px)`
35
+ };
36
+ const rotationIconRest = {
37
+ opacity: 1,
38
+ scale: 1,
39
+ filter: "blur(0px)"
40
+ };
41
+ const rotationIconEnter = {
42
+ ...ARC_SPRING_SNAPPY,
43
+ opacity: {
44
+ duration: ARC_DURATION.fast,
45
+ ease: [...ARC_EASE.enter]
46
+ },
47
+ filter: {
48
+ duration: ARC_DURATION.fast,
49
+ ease: [...ARC_EASE.enter]
50
+ }
51
+ };
52
+ const rotationIconExit = {
53
+ ...rotationIconHidden,
54
+ transition: {
55
+ duration: ARC_DURATION.fast,
56
+ ease: [...ARC_EASE.standard]
57
+ }
58
+ };
59
+ /**
60
+ * Keeps Embla in step with its slides without ever cutting a scroll short. Embla re-initializes when a slide is added,
61
+ * removed or resized; a re-initialization recreates the engine and aborts a running scroll, so while a scroll or a
62
+ * drag is in progress the request is parked and runs once the carousel comes to rest.
63
+ * @returns Embla's `watchResize` and `watchSlides` callbacks, stable across renders, plus the handle to bind them.
64
+ */
65
+ function useDeferredReInit() {
66
+ const $ = _c(5);
67
+ const apiRef = React.useRef(undefined);
68
+ const isPointerDownRef = React.useRef(false);
69
+ const isPendingRef = React.useRef(false);
70
+ let t0;
71
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
72
+ t0 = () => {
73
+ const api = apiRef.current;
74
+ if (!api || api.slideNodes().length === 0) {
75
+ return false;
80
76
  }
81
- setCanScrollPrev(api_0.canScrollPrev());
82
- setCanScrollNext(api_0.canScrollNext());
83
- };
84
- $[11] = t4;
85
- } else {
86
- t4 = $[11];
87
- }
88
- const onSelect = t4;
89
- let t5;
90
- if ($[12] !== api || $[13] !== shouldReduceMotion) {
91
- t5 = () => {
92
- api?.scrollPrev(shouldReduceMotion);
93
- };
94
- $[12] = api;
95
- $[13] = shouldReduceMotion;
96
- $[14] = t5;
97
- } else {
98
- t5 = $[14];
99
- }
100
- const scrollPrev = t5;
101
- let t6;
102
- if ($[15] !== api || $[16] !== shouldReduceMotion) {
103
- t6 = () => {
104
- api?.scrollNext(shouldReduceMotion);
77
+ return isPointerDownRef.current || !api.internalEngine().scrollBody.settled();
105
78
  };
106
- $[15] = api;
107
- $[16] = shouldReduceMotion;
108
- $[17] = t6;
79
+ $[0] = t0;
109
80
  } else {
110
- t6 = $[17];
81
+ t0 = $[0];
111
82
  }
112
- const scrollNext = t6;
113
- let t7;
114
- if ($[18] !== api || $[19] !== orientation || $[20] !== scrollNext || $[21] !== scrollPrev || $[22] !== shouldReduceMotion) {
115
- t7 = (event) => {
116
- if (event.altKey || event.ctrlKey || event.metaKey) {
117
- return;
118
- }
119
- const keyboardOwner = event.target instanceof Element ? event.target.closest(CAROUSEL_OWN_KEYBOARD_SELECTOR) : null;
120
- if (keyboardOwner && event.currentTarget.contains(keyboardOwner)) {
121
- return;
122
- }
123
- const closestCarousel = event.target instanceof Element ? event.target.closest(CAROUSEL_ROOT_SELECTOR) : null;
124
- if (closestCarousel && closestCarousel !== event.currentTarget) {
125
- return;
126
- }
127
- const keys = CAROUSEL_KEYS[orientation];
128
- if (event.key === keys.previous) {
129
- event.preventDefault();
130
- scrollPrev();
131
- } else {
132
- if (event.key === keys.next) {
133
- event.preventDefault();
134
- scrollNext();
135
- } else {
136
- if (api && event.key === CAROUSEL_EDGE_KEYS.first) {
137
- event.preventDefault();
138
- api.scrollTo(0, shouldReduceMotion);
139
- } else {
140
- if (api && event.key === CAROUSEL_EDGE_KEYS.last) {
141
- event.preventDefault();
142
- api.scrollTo(api.scrollSnapList().length - 1, shouldReduceMotion);
143
- }
144
- }
145
- }
83
+ const isBusy = t0;
84
+ let t1;
85
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
86
+ t1 = () => {
87
+ if (!isBusy()) {
88
+ return true;
146
89
  }
90
+ isPendingRef.current = true;
91
+ return false;
147
92
  };
148
- $[18] = api;
149
- $[19] = orientation;
150
- $[20] = scrollNext;
151
- $[21] = scrollPrev;
152
- $[22] = shouldReduceMotion;
153
- $[23] = t7;
93
+ $[1] = t1;
154
94
  } else {
155
- t7 = $[23];
95
+ t1 = $[1];
156
96
  }
157
- const handleKeyDown = t7;
158
- let t8;
159
- let t9;
160
- if ($[24] !== api || $[25] !== setApi) {
161
- t8 = () => {
162
- if (!api || !setApi) {
97
+ const deferWhileBusy = t1;
98
+ let t2;
99
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
100
+ t2 = () => {
101
+ const api_0 = apiRef.current;
102
+ if (!api_0 || !isPendingRef.current || isBusy()) {
163
103
  return;
164
104
  }
165
- setApi(api);
105
+ isPendingRef.current = false;
106
+ api_0.reInit();
166
107
  };
167
- t9 = [api, setApi];
168
- $[24] = api;
169
- $[25] = setApi;
170
- $[26] = t8;
171
- $[27] = t9;
108
+ $[2] = t2;
172
109
  } else {
173
- t8 = $[26];
174
- t9 = $[27];
110
+ t2 = $[2];
175
111
  }
176
- React.useEffect(t8, t9);
177
- let t10;
178
- let t11;
179
- if ($[28] !== api) {
180
- t10 = () => {
181
- if (!api) {
112
+ const flush = t2;
113
+ let t3;
114
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
115
+ t3 = (api_1) => {
116
+ apiRef.current = api_1;
117
+ if (!api_1) {
182
118
  return;
183
119
  }
184
- let isMounted = true;
185
- queueMicrotask(() => {
186
- if (isMounted) {
187
- onSelect(api);
188
- }
189
- });
190
- api.on("reInit", onSelect);
191
- api.on("select", onSelect);
120
+ const handlePointerDown = () => {
121
+ isPointerDownRef.current = true;
122
+ };
123
+ const handlePointerUp = () => {
124
+ isPointerDownRef.current = false;
125
+ flush();
126
+ };
127
+ const handleSettle = () => queueMicrotask(flush);
128
+ api_1.on("pointerDown", handlePointerDown);
129
+ api_1.on("pointerUp", handlePointerUp);
130
+ api_1.on("settle", handleSettle);
192
131
  return () => {
193
- isMounted = false;
194
- api?.off("reInit", onSelect);
195
- api?.off("select", onSelect);
132
+ api_1.off("pointerDown", handlePointerDown);
133
+ api_1.off("pointerUp", handlePointerUp);
134
+ api_1.off("settle", handleSettle);
135
+ isPointerDownRef.current = false;
136
+ isPendingRef.current = false;
196
137
  };
197
138
  };
198
- t11 = [api, onSelect];
199
- $[28] = api;
200
- $[29] = t10;
201
- $[30] = t11;
139
+ $[3] = t3;
202
140
  } else {
203
- t10 = $[29];
204
- t11 = $[30];
141
+ t3 = $[3];
205
142
  }
206
- React.useEffect(t10, t11);
207
- const t12 = orientation || (opts?.axis === "y" ? "vertical" : "horizontal");
208
- let t13;
209
- if ($[31] !== api || $[32] !== canScrollNext || $[33] !== canScrollPrev || $[34] !== carouselRef || $[35] !== opts || $[36] !== scrollNext || $[37] !== scrollPrev || $[38] !== t12) {
210
- t13 = {
211
- carouselRef,
212
- api,
213
- opts,
214
- orientation: t12,
215
- scrollPrev,
216
- scrollNext,
217
- canScrollPrev,
218
- canScrollNext
143
+ const bind = t3;
144
+ let t4;
145
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
146
+ t4 = {
147
+ watch: deferWhileBusy,
148
+ bind
219
149
  };
220
- $[31] = api;
221
- $[32] = canScrollNext;
222
- $[33] = canScrollPrev;
223
- $[34] = carouselRef;
224
- $[35] = opts;
225
- $[36] = scrollNext;
226
- $[37] = scrollPrev;
227
- $[38] = t12;
228
- $[39] = t13;
229
- } else {
230
- t13 = $[39];
231
- }
232
- let t14;
233
- if ($[40] !== className) {
234
- t14 = cn("relative", className);
235
- $[40] = className;
236
- $[41] = t14;
237
- } else {
238
- t14 = $[41];
239
- }
240
- let t15;
241
- if ($[42] !== children || $[43] !== handleKeyDown || $[44] !== props || $[45] !== t14) {
242
- t15 = /* @__PURE__ */ _jsx("div", {
243
- onKeyDownCapture: handleKeyDown,
244
- className: t14,
245
- role: "region",
246
- "aria-roledescription": "carousel",
247
- "data-slot": "carousel",
248
- ...props,
249
- children
250
- });
251
- $[42] = children;
252
- $[43] = handleKeyDown;
253
- $[44] = props;
254
- $[45] = t14;
255
- $[46] = t15;
256
- } else {
257
- t15 = $[46];
258
- }
259
- let t16;
260
- if ($[47] !== t13 || $[48] !== t15) {
261
- t16 = /* @__PURE__ */ _jsx(CarouselContext.Provider, {
262
- value: t13,
263
- children: t15
264
- });
265
- $[47] = t13;
266
- $[48] = t15;
267
- $[49] = t16;
150
+ $[4] = t4;
268
151
  } else {
269
- t16 = $[49];
152
+ t4 = $[4];
270
153
  }
271
- return t16;
154
+ return t4;
272
155
  }
273
156
  /**
274
- * The clipped viewport and the slide track. While the track can be dragged it shows Arc's grab cursor on fine
275
- * pointers, and a grabbing cursor while a drag is held.
157
+ * A centered row of slides browsed by drag, flick, the arrow keys, Home and End, the arrows or the indicator tabs, with
158
+ * optional rotation. Neighbouring slides stay in view as a hint that there is more, and are inert until selected.
159
+ * @param props - Arc's carousel props plus the beez-ui extensions.
160
+ * @returns The carousel section.
276
161
  */
277
- function CarouselContent(t0) {
278
- const $ = _c(19);
279
- let className;
280
- let props;
281
- if ($[0] !== t0) {
282
- ({className, ...props} = t0);
283
- $[0] = t0;
284
- $[1] = className;
285
- $[2] = props;
286
- } else {
287
- className = $[1];
288
- props = $[2];
289
- }
290
- const { carouselRef, api, opts, orientation, canScrollPrev, canScrollNext } = useCarousel();
162
+ function Carousel({ label, children, index: controlledIndex, defaultIndex = 0, onIndexChange, slideSize = CAROUSEL_DEFAULT_SLIDE_SIZE, slideLabel = defaultCarouselSlideLabel, interval, autoplay = false, className, loop = false, duration, watchFocus = true, onSettle, previousLabel = CAROUSEL_COPY.previous, nextLabel = CAROUSEL_COPY.next, showControls = true, showIndicators = true, slideClassName, viewportClassName, trackClassName }) {
163
+ const slides = React.Children.toArray(children);
164
+ const count = slides.length;
165
+ const baseId = React.useId();
166
+ const getSlideId = React.useCallback((slideIndex) => `${baseId}-slide-${slideIndex}`, [baseId]);
167
+ const reduceMotion = usePrefersReducedMotion();
168
+ const isHydrated = useIsHydrated();
169
+ const [startIndex] = React.useState(() => clampSlideIndex(controlledIndex ?? defaultIndex, count));
170
+ const [selectedIndex, setSelectedIndex] = React.useState(startIndex);
171
+ const [api, setApi] = React.useState();
172
+ const [announcement, setAnnouncement] = React.useState("");
173
+ const [engineSlideCount, setEngineSlideCount] = React.useState(0);
174
+ const { watch, bind } = useDeferredReInit();
175
+ const callbacksRef = React.useRef({
176
+ onIndexChange,
177
+ onSettle,
178
+ slideLabel
179
+ });
180
+ React.useLayoutEffect(() => {
181
+ callbacksRef.current = {
182
+ onIndexChange,
183
+ onSettle,
184
+ slideLabel
185
+ };
186
+ });
187
+ const reportedIndexRef = React.useRef(startIndex);
188
+ const settledIndexRef = React.useRef(startIndex);
189
+ const isRotatingRef = React.useRef(false);
190
+ const pendingDefaultIndexRef = React.useRef(controlledIndex === undefined && defaultIndex > startIndex ? defaultIndex : undefined);
191
+ const options = {
192
+ align: "center",
193
+ containScroll: false,
194
+ loop,
195
+ watchFocus,
196
+ watchResize: watch,
197
+ watchSlides: watch,
198
+ ...duration === undefined ? {} : { duration }
199
+ };
200
+ React.useEffect(() => bind(api), [api, bind]);
201
+ React.useLayoutEffect(() => {
202
+ if (!api) return;
203
+ api.scrollTo(reportedIndexRef.current, true);
204
+ }, [api]);
205
+ React.useEffect(() => {
206
+ if (!api) return;
207
+ const handleSettle = () => {
208
+ const settledIndex = api.selectedScrollSnap();
209
+ if (settledIndex === settledIndexRef.current) return;
210
+ settledIndexRef.current = settledIndex;
211
+ callbacksRef.current.onSettle?.(settledIndex);
212
+ };
213
+ const handleSelect = () => {
214
+ const nextIndex = api.selectedScrollSnap();
215
+ setSelectedIndex(nextIndex);
216
+ if (nextIndex !== reportedIndexRef.current) {
217
+ pendingDefaultIndexRef.current = undefined;
218
+ reportedIndexRef.current = nextIndex;
219
+ const { onIndexChange: reportIndex, slideLabel: nameSlide } = callbacksRef.current;
220
+ reportIndex?.(nextIndex);
221
+ if (!isRotatingRef.current) setAnnouncement(nameSlide(nextIndex, api.slideNodes().length));
222
+ }
223
+ isRotatingRef.current = false;
224
+ if (api.internalEngine().scrollBody.settled() && !api.internalEngine().dragHandler.pointerDown()) handleSettle();
225
+ };
226
+ const handleReInit = () => {
227
+ setEngineSlideCount(api.slideNodes().length);
228
+ handleSelect();
229
+ handleSettle();
230
+ };
231
+ api.on("select", handleSelect);
232
+ api.on("settle", handleSettle);
233
+ api.on("reInit", handleReInit);
234
+ return () => {
235
+ api.off("select", handleSelect);
236
+ api.off("settle", handleSettle);
237
+ api.off("reInit", handleReInit);
238
+ };
239
+ }, [api]);
240
+ React.useEffect(() => {
241
+ if (!api || controlledIndex === undefined) return;
242
+ const nextIndex = clampSlideIndex(controlledIndex, api.slideNodes().length);
243
+ if (nextIndex === api.selectedScrollSnap()) return;
244
+ reportedIndexRef.current = nextIndex;
245
+ api.scrollTo(nextIndex, reduceMotion);
246
+ }, [
247
+ api,
248
+ controlledIndex,
249
+ engineSlideCount,
250
+ reduceMotion,
251
+ selectedIndex
252
+ ]);
253
+ React.useEffect(() => {
254
+ const pendingIndex = pendingDefaultIndexRef.current;
255
+ if (!api || pendingIndex === undefined || api.slideNodes().length <= pendingIndex) return;
256
+ pendingDefaultIndexRef.current = undefined;
257
+ reportedIndexRef.current = pendingIndex;
258
+ settledIndexRef.current = pendingIndex;
259
+ api.scrollTo(pendingIndex, true);
260
+ }, [api, engineSlideCount]);
261
+ const rotation = useRotation({
262
+ api,
263
+ count,
264
+ interval,
265
+ autoplay,
266
+ reduceMotion,
267
+ isHydrated,
268
+ selectedIndex,
269
+ loop,
270
+ isRotatingRef
271
+ });
272
+ const visibleIndex = clampSlideIndex(selectedIndex, count);
273
+ const hasControlRow = count > 1 && (showControls || showIndicators || rotation.hasControl);
274
+ const hasIndicators = count > 1 && showIndicators;
275
+ const rootStyle = { [CAROUSEL_SLIDE_SIZE_PROPERTY]: slideSize };
276
+ return /* @__PURE__ */ _jsxs(CarouselRoot, {
277
+ opts: options,
278
+ setApi,
279
+ "aria-label": label,
280
+ className: cn("@container/carousel grid w-full min-w-0 grid-cols-[minmax(0,1fr)] gap-4", className),
281
+ style: rootStyle,
282
+ onPointerEnter: (event) => {
283
+ if (event.pointerType === "mouse") rotation.setIsHovered(true);
284
+ },
285
+ onPointerLeave: () => rotation.setIsHovered(false),
286
+ onFocus: (event) => rotation.handleFocus(event.target),
287
+ onBlur: (event) => {
288
+ if (!event.currentTarget.contains(event.relatedTarget)) rotation.handleFocus(null);
289
+ },
290
+ ref: rotation.rootRef,
291
+ children: [
292
+ /* @__PURE__ */ _jsx(CarouselContent, {
293
+ viewportClassName,
294
+ className: cn("select-none [&_img]:[-webkit-user-drag:none]", trackClassName),
295
+ children: slides.map((slide, slideIndex) => /* @__PURE__ */ _jsx(CarouselItem, {
296
+ id: getSlideId(slideIndex),
297
+ role: hasIndicators ? "tabpanel" : "group",
298
+ "aria-label": slideLabel(slideIndex, count),
299
+ inert: slideIndex !== visibleIndex || undefined,
300
+ className: cn("basis-(--carousel-slide)", slideClassName),
301
+ children: slide
302
+ }, React.isValidElement(slide) && slide.key != null ? slide.key : slideIndex))
303
+ }),
304
+ hasControlRow ? /* @__PURE__ */ _jsxs("div", {
305
+ "data-slot": "carousel-controls",
306
+ className: "flex min-w-0 items-center gap-2 px-[calc((100cqw_-_var(--carousel-slide))/2)] @max-[340px]/carousel:gap-1 @max-[340px]/carousel:px-[max(0px,calc((100cqw_-_var(--carousel-slide))/2_-_var(--spacing)*2))]",
307
+ children: [
308
+ rotation.hasControl ? /* @__PURE__ */ _jsx(ControlButton, {
309
+ ref: rotation.playRef,
310
+ "data-slot": "carousel-rotation",
311
+ variant: "outline",
312
+ size: "icon",
313
+ className: "size-(--control-height-sm) rounded-full border-border bg-surface text-foreground hover-fine:bg-surface-muted",
314
+ "aria-label": rotation.isPlaying ? CAROUSEL_COPY.pauseRotation : CAROUSEL_COPY.startRotation,
315
+ disabled: !rotation.canRotate,
316
+ onClick: rotation.toggle,
317
+ children: /* @__PURE__ */ _jsx("span", {
318
+ className: "grid size-4 place-items-center",
319
+ children: /* @__PURE__ */ _jsx(AnimatePresence, {
320
+ initial: false,
321
+ children: /* @__PURE__ */ _jsx(motion.span, {
322
+ className: "col-start-1 row-start-1 grid place-items-center",
323
+ initial: reduceMotion ? { opacity: 0 } : rotationIconHidden,
324
+ animate: rotationIconRest,
325
+ exit: reduceMotion ? {
326
+ opacity: 0,
327
+ transition: { duration: 0 }
328
+ } : rotationIconExit,
329
+ transition: reduceMotion ? { duration: 0 } : rotationIconEnter,
330
+ children: rotation.isPlaying ? /* @__PURE__ */ _jsx(Pause, {
331
+ size: CAROUSEL_ROTATION_ICON_SIZE_PX,
332
+ strokeWidth: 1.75,
333
+ fill: "currentColor",
334
+ "aria-hidden": "true"
335
+ }) : /* @__PURE__ */ _jsx(Play, {
336
+ size: CAROUSEL_ROTATION_ICON_SIZE_PX,
337
+ strokeWidth: 1.75,
338
+ fill: "currentColor",
339
+ "aria-hidden": "true"
340
+ })
341
+ }, rotation.isPlaying ? "pause" : "play")
342
+ })
343
+ })
344
+ }) : null,
345
+ showIndicators ? /* @__PURE__ */ _jsx(CarouselIndicators, {
346
+ slideLabel,
347
+ getSlideId,
348
+ drain: rotation.drain,
349
+ initialCount: count,
350
+ initialIndex: startIndex
351
+ }) : null,
352
+ showControls ? /* @__PURE__ */ _jsxs("div", {
353
+ className: "ms-auto flex flex-none gap-2 @max-[340px]/carousel:gap-1",
354
+ children: [/* @__PURE__ */ _jsx(CarouselPrevious, { "aria-label": previousLabel }), /* @__PURE__ */ _jsx(CarouselNext, { "aria-label": nextLabel })]
355
+ }) : null
356
+ ]
357
+ }) : null,
358
+ /* @__PURE__ */ _jsx("span", {
359
+ className: "sr-only",
360
+ "aria-live": "polite",
361
+ "aria-atomic": "true",
362
+ children: announcement
363
+ })
364
+ ]
365
+ });
366
+ }
367
+ /**
368
+ * Arc's slide rotation: each slide stays for `interval` while its pill drains, then the carousel moves on, wrapping to
369
+ * the first slide at the end. Rotation pauses on hover, keyboard focus, drag, offscreen and in hidden tabs; pausing it
370
+ * with the control refills the pill. Reduced motion, once hydrated, makes rotation unavailable and disables the control,
371
+ * which stays in place so the control row keeps its layout after hydration.
372
+ * @param settings - Carousel state the rotation reads.
373
+ * @returns Rotation state and the handlers the carousel binds.
374
+ */
375
+ function useRotation(t0) {
376
+ const $ = _c(37);
377
+ const { api, count, interval, autoplay, reduceMotion, isHydrated, selectedIndex, loop, isRotatingRef } = t0;
378
+ const [isPlaying, setIsPlaying] = React.useState(autoplay);
379
+ const [isHovered, setIsHovered] = React.useState(false);
380
+ const [isFocusPaused, setIsFocusPaused] = React.useState(false);
291
381
  const [isDragging, setIsDragging] = React.useState(false);
292
- const isDraggable = opts?.watchDrag !== false && (canScrollPrev || canScrollNext);
382
+ const [isInView, setIsInView] = React.useState(true);
383
+ const [isPageVisible, setIsPageVisible] = React.useState(true);
384
+ const drain = useMotionValue(0);
385
+ const rootRef = React.useRef(null);
386
+ const playRef = React.useRef(null);
387
+ const hasControl = Boolean(interval) && count > 1;
388
+ const canRotate = hasControl && !(isHydrated && reduceMotion);
389
+ const isRunning = canRotate && isPlaying && !isHovered && !isFocusPaused && !isDragging && isInView && isPageVisible;
293
390
  let t1;
294
391
  let t2;
295
- if ($[3] !== api) {
392
+ if ($[0] !== api) {
296
393
  t1 = () => {
297
394
  if (!api) {
298
395
  return;
@@ -307,560 +404,182 @@ function CarouselContent(t0) {
307
404
  };
308
405
  };
309
406
  t2 = [api];
310
- $[3] = api;
311
- $[4] = t1;
312
- $[5] = t2;
407
+ $[0] = api;
408
+ $[1] = t1;
409
+ $[2] = t2;
313
410
  } else {
314
- t1 = $[4];
315
- t2 = $[5];
411
+ t1 = $[1];
412
+ t2 = $[2];
316
413
  }
317
414
  React.useEffect(t1, t2);
318
- const t3 = isDraggable && "pointer-fine:cursor-grab pointer-fine:data-dragging:cursor-grabbing";
319
- let t4;
320
- if ($[6] !== t3) {
321
- t4 = cn("overflow-hidden", t3);
322
- $[6] = t3;
323
- $[7] = t4;
324
- } else {
325
- t4 = $[7];
326
- }
327
- const t5 = isDraggable && isDragging || undefined;
328
- const t6 = orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col";
329
- let t7;
330
- if ($[8] !== className || $[9] !== t6) {
331
- t7 = cn("flex", t6, className);
332
- $[8] = className;
333
- $[9] = t6;
334
- $[10] = t7;
335
- } else {
336
- t7 = $[10];
337
- }
338
- let t8;
339
- if ($[11] !== props || $[12] !== t7) {
340
- t8 = /* @__PURE__ */ _jsx("div", {
341
- className: t7,
342
- ...props
343
- });
344
- $[11] = props;
345
- $[12] = t7;
346
- $[13] = t8;
347
- } else {
348
- t8 = $[13];
349
- }
350
- let t9;
351
- if ($[14] !== carouselRef || $[15] !== t4 || $[16] !== t5 || $[17] !== t8) {
352
- t9 = /* @__PURE__ */ _jsx("div", {
353
- ref: carouselRef,
354
- className: t4,
355
- "data-slot": "carousel-content",
356
- "data-dragging": t5,
357
- children: t8
358
- });
359
- $[14] = carouselRef;
360
- $[15] = t4;
361
- $[16] = t5;
362
- $[17] = t8;
363
- $[18] = t9;
364
- } else {
365
- t9 = $[18];
366
- }
367
- return t9;
368
- }
369
- function CarouselItem(t0) {
370
- const $ = _c(9);
371
- let className;
372
- let props;
373
- if ($[0] !== t0) {
374
- ({className, ...props} = t0);
375
- $[0] = t0;
376
- $[1] = className;
377
- $[2] = props;
378
- } else {
379
- className = $[1];
380
- props = $[2];
381
- }
382
- const { orientation } = useCarousel();
383
- const t1 = orientation === "horizontal" ? "pl-4" : "pt-4";
384
- let t2;
385
- if ($[3] !== className || $[4] !== t1) {
386
- t2 = cn("min-w-0 shrink-0 grow-0 basis-full", t1, className);
387
- $[3] = className;
388
- $[4] = t1;
389
- $[5] = t2;
390
- } else {
391
- t2 = $[5];
392
- }
393
415
  let t3;
394
- if ($[6] !== props || $[7] !== t2) {
395
- t3 = /* @__PURE__ */ _jsx("div", {
396
- role: "group",
397
- "aria-roledescription": "slide",
398
- "data-slot": "carousel-item",
399
- className: t2,
400
- ...props
401
- });
402
- $[6] = props;
403
- $[7] = t2;
404
- $[8] = t3;
405
- } else {
406
- t3 = $[8];
407
- }
408
- return t3;
409
- }
410
- function CarouselPrevious(t0) {
411
- const $ = _c(17);
412
- let className;
413
- let props;
414
- let t1;
415
- let t2;
416
- if ($[0] !== t0) {
417
- ({className, variant: t1, size: t2, ...props} = t0);
418
- $[0] = t0;
419
- $[1] = className;
420
- $[2] = props;
421
- $[3] = t1;
422
- $[4] = t2;
416
+ if ($[3] !== drain) {
417
+ t3 = () => {
418
+ drain.jump(0);
419
+ };
420
+ $[3] = drain;
421
+ $[4] = t3;
423
422
  } else {
424
- className = $[1];
425
- props = $[2];
426
- t1 = $[3];
427
- t2 = $[4];
423
+ t3 = $[4];
428
424
  }
429
- const variant = t1 === undefined ? "outline" : t1;
430
- const size = t2 === undefined ? "icon-lg" : t2;
431
- const { orientation, scrollPrev, canScrollPrev } = useCarousel();
432
- const t3 = orientation === "horizontal" ? "top-1/2 -left-12 -translate-y-1/2" : "-top-12 left-1/2 -translate-x-1/2 rotate-90";
433
425
  let t4;
434
- if ($[5] !== className || $[6] !== t3) {
435
- t4 = cn(carouselControlClassName, t3, className);
436
- $[5] = className;
437
- $[6] = t3;
426
+ if ($[5] !== drain || $[6] !== selectedIndex) {
427
+ t4 = [drain, selectedIndex];
428
+ $[5] = drain;
429
+ $[6] = selectedIndex;
438
430
  $[7] = t4;
439
431
  } else {
440
432
  t4 = $[7];
441
433
  }
442
- const t5 = !canScrollPrev;
443
- let t6;
444
- let t7;
445
- if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
446
- t6 = /* @__PURE__ */ _jsx(ChevronLeftIcon, { strokeWidth: 1.75 });
447
- t7 = /* @__PURE__ */ _jsx("span", {
448
- className: "sr-only",
449
- children: "Previous slide"
450
- });
451
- $[8] = t6;
452
- $[9] = t7;
453
- } else {
454
- t6 = $[8];
455
- t7 = $[9];
456
- }
457
- let t8;
458
- if ($[10] !== props || $[11] !== scrollPrev || $[12] !== size || $[13] !== t4 || $[14] !== t5 || $[15] !== variant) {
459
- t8 = /* @__PURE__ */ _jsxs(ControlButton, {
460
- "data-slot": "carousel-previous",
461
- variant,
462
- size,
463
- className: t4,
464
- disabled: t5,
465
- onClick: scrollPrev,
466
- ...props,
467
- children: [t6, t7]
468
- });
469
- $[10] = props;
470
- $[11] = scrollPrev;
471
- $[12] = size;
472
- $[13] = t4;
434
+ React.useEffect(t3, t4);
435
+ let t5;
436
+ if ($[8] !== api || $[9] !== drain || $[10] !== interval || $[11] !== isRotatingRef || $[12] !== isRunning || $[13] !== loop) {
437
+ t5 = () => {
438
+ if (!isRunning || !interval || !api) {
439
+ return;
440
+ }
441
+ const controls = animate(drain, 1, {
442
+ duration: (1 - drain.get()) * interval / 1e3,
443
+ ease: "linear",
444
+ onComplete: () => {
445
+ isRotatingRef.current = true;
446
+ if (loop || api.canScrollNext()) {
447
+ api.scrollNext();
448
+ } else {
449
+ api.scrollTo(0);
450
+ }
451
+ }
452
+ });
453
+ return () => controls.stop();
454
+ };
455
+ $[8] = api;
456
+ $[9] = drain;
457
+ $[10] = interval;
458
+ $[11] = isRotatingRef;
459
+ $[12] = isRunning;
460
+ $[13] = loop;
473
461
  $[14] = t5;
474
- $[15] = variant;
475
- $[16] = t8;
476
462
  } else {
477
- t8 = $[16];
478
- }
479
- return t8;
480
- }
481
- function CarouselNext(t0) {
482
- const $ = _c(17);
483
- let className;
484
- let props;
485
- let t1;
486
- let t2;
487
- if ($[0] !== t0) {
488
- ({className, variant: t1, size: t2, ...props} = t0);
489
- $[0] = t0;
490
- $[1] = className;
491
- $[2] = props;
492
- $[3] = t1;
493
- $[4] = t2;
494
- } else {
495
- className = $[1];
496
- props = $[2];
497
- t1 = $[3];
498
- t2 = $[4];
499
- }
500
- const variant = t1 === undefined ? "outline" : t1;
501
- const size = t2 === undefined ? "icon-lg" : t2;
502
- const { orientation, scrollNext, canScrollNext } = useCarousel();
503
- const t3 = orientation === "horizontal" ? "top-1/2 -right-12 -translate-y-1/2" : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90";
504
- let t4;
505
- if ($[5] !== className || $[6] !== t3) {
506
- t4 = cn(carouselControlClassName, t3, className);
507
- $[5] = className;
508
- $[6] = t3;
509
- $[7] = t4;
510
- } else {
511
- t4 = $[7];
463
+ t5 = $[14];
512
464
  }
513
- const t5 = !canScrollNext;
514
465
  let t6;
515
- let t7;
516
- if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
517
- t6 = /* @__PURE__ */ _jsx(ChevronRightIcon, { strokeWidth: 1.75 });
518
- t7 = /* @__PURE__ */ _jsx("span", {
519
- className: "sr-only",
520
- children: "Next slide"
521
- });
522
- $[8] = t6;
523
- $[9] = t7;
466
+ if ($[15] !== api || $[16] !== drain || $[17] !== interval || $[18] !== isRotatingRef || $[19] !== isRunning || $[20] !== loop || $[21] !== selectedIndex) {
467
+ t6 = [
468
+ api,
469
+ drain,
470
+ interval,
471
+ isRotatingRef,
472
+ isRunning,
473
+ loop,
474
+ selectedIndex
475
+ ];
476
+ $[15] = api;
477
+ $[16] = drain;
478
+ $[17] = interval;
479
+ $[18] = isRotatingRef;
480
+ $[19] = isRunning;
481
+ $[20] = loop;
482
+ $[21] = selectedIndex;
483
+ $[22] = t6;
524
484
  } else {
525
- t6 = $[8];
526
- t7 = $[9];
485
+ t6 = $[22];
527
486
  }
487
+ React.useEffect(t5, t6);
488
+ let t7;
528
489
  let t8;
529
- if ($[10] !== props || $[11] !== scrollNext || $[12] !== size || $[13] !== t4 || $[14] !== t5 || $[15] !== variant) {
530
- t8 = /* @__PURE__ */ _jsxs(ControlButton, {
531
- "data-slot": "carousel-next",
532
- variant,
533
- size,
534
- className: t4,
535
- disabled: t5,
536
- onClick: scrollNext,
537
- ...props,
538
- children: [t6, t7]
539
- });
540
- $[10] = props;
541
- $[11] = scrollNext;
542
- $[12] = size;
543
- $[13] = t4;
544
- $[14] = t5;
545
- $[15] = variant;
546
- $[16] = t8;
547
- } else {
548
- t8 = $[16];
549
- }
550
- return t8;
551
- }
552
- /**
553
- * Default accessible name of one indicator, for example "Diapositiva 2 de 5".
554
- * @param index - Zero-based slide position.
555
- * @param count - Number of slides.
556
- * @returns The Spanish slide label.
557
- */
558
- function defaultCarouselSlideLabel(index, count) {
559
- return `${CAROUSEL_COPY.slideLabelPrefix} ${index + 1} ${CAROUSEL_COPY.slideLabelSeparator} ${count}`;
560
- }
561
- /**
562
- * Continuous slide position, in slides, of a scroll progress between Embla's snap points. Snaps are progress values,
563
- * so trimmed edges and slides of different sizes still map to whole slides at rest.
564
- * @param progress - Embla's scroll progress, from 0 to 1.
565
- * @param snaps - Embla's snap points, as scroll progress values.
566
- * @returns The fractional index of the slide in view.
567
- */
568
- function toSlidePosition(progress, snaps) {
569
- const lastIndex = snaps.length - 1;
570
- if (lastIndex < 1) return 0;
571
- const first = snaps[0] ?? 0;
572
- const last = snaps[lastIndex] ?? 1;
573
- if (progress <= first) return 0;
574
- if (progress >= last) return lastIndex;
575
- for (let index = 0; index < lastIndex; index += 1) {
576
- const start = snaps[index] ?? 0;
577
- const end = snaps[index + 1] ?? 1;
578
- if (progress <= end) return end > start ? index + (progress - start) / (end - start) : index;
579
- }
580
- return lastIndex;
581
- }
582
- /**
583
- * Arc's page indicator for a carousel: one dot per snap point, where the current one stretches into a pill that
584
- * follows the track frame by frame while it is dragged or scrolled. The dots are buttons in a named group and the
585
- * current one carries `aria-current`; activating a dot scrolls to its slide, and when a dot has focus the carousel's
586
- * arrow, Home and End keys move the focus to the dot of the new slide. It renders
587
- * once Embla has measured the slides. Place it inside `Carousel`.
588
- * @param props - Optional accessible copy plus native attributes of the list.
589
- * @returns The indicator list, or nothing until there is more than one snap point.
590
- */
591
- function CarouselIndicators(t0) {
592
- const $ = _c(28);
593
- let className;
594
- let props;
595
- let t1;
596
- let t2;
597
- if ($[0] !== t0) {
598
- ({className, label: t1, slideLabel: t2, ...props} = t0);
599
- $[0] = t0;
600
- $[1] = className;
601
- $[2] = props;
602
- $[3] = t1;
603
- $[4] = t2;
604
- } else {
605
- className = $[1];
606
- props = $[2];
607
- t1 = $[3];
608
- t2 = $[4];
609
- }
610
- const label = t1 === undefined ? CAROUSEL_COPY.indicatorsLabel : t1;
611
- const slideLabel = t2 === undefined ? defaultCarouselSlideLabel : t2;
612
- const { api, orientation } = useCarousel();
613
- const reduceMotion = usePrefersReducedMotion();
614
- const [snapCount, setSnapCount] = React.useState(0);
615
- const [selectedIndex, setSelectedIndex] = React.useState(0);
616
- const [isLooping, setIsLooping] = React.useState(false);
617
- const position = useMotionValue(0);
618
- let t3;
619
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
620
- t3 = [];
621
- $[5] = t3;
622
- } else {
623
- t3 = $[5];
624
- }
625
- const indicatorRefs = React.useRef(t3);
626
- let t4;
627
- let t5;
628
- if ($[6] !== api || $[7] !== position || $[8] !== reduceMotion) {
629
- t4 = () => {
630
- if (!api) {
490
+ if ($[23] !== interval) {
491
+ t7 = () => {
492
+ const root = rootRef.current;
493
+ if (!interval || !root) {
631
494
  return;
632
495
  }
633
- let positionAnimation = null;
634
- const isLoop = () => api.internalEngine().options.loop;
635
- const trackScroll = () => {
636
- if (isLoop()) {
637
- return;
638
- }
639
- positionAnimation?.stop();
640
- position.set(toSlidePosition(api.scrollProgress(), api.scrollSnapList()));
641
- };
642
- const syncSelection = () => {
643
- const nextIndex = api.selectedScrollSnap();
644
- const count = api.scrollSnapList().length;
645
- setSnapCount(count);
646
- setSelectedIndex(nextIndex);
647
- setIsLooping(isLoop());
648
- if (isLoop()) {
649
- positionAnimation?.stop();
650
- const turns = Math.round((position.get() - nextIndex) / count);
651
- const destination = nextIndex + turns * count;
652
- positionAnimation = reduceMotion ? null : animate(position, destination, {
653
- ...ARC_SPRING_SMOOTH,
654
- onComplete: () => position.jump(nextIndex)
655
- });
656
- if (reduceMotion) {
657
- position.set(nextIndex);
658
- }
659
- }
660
- if (indicatorRefs.current.some(_temp)) {
661
- indicatorRefs.current[nextIndex]?.focus({ preventScroll: true });
496
+ const observer = typeof IntersectionObserver === "undefined" ? null : new IntersectionObserver((t9) => {
497
+ const [entry] = t9;
498
+ if (entry) {
499
+ setIsInView(entry.isIntersecting);
662
500
  }
663
- };
664
- const syncAll = () => {
665
- syncSelection();
666
- if (isLoop()) {
667
- positionAnimation?.stop();
668
- position.set(api.selectedScrollSnap());
669
- } else {
670
- trackScroll();
671
- }
672
- };
673
- syncAll();
674
- api.on("reInit", syncAll);
675
- api.on("select", syncSelection);
676
- api.on("scroll", trackScroll);
501
+ });
502
+ observer?.observe(root);
503
+ const handleVisibilityChange = () => setIsPageVisible(document.visibilityState !== "hidden");
504
+ handleVisibilityChange();
505
+ document.addEventListener("visibilitychange", handleVisibilityChange);
677
506
  return () => {
678
- positionAnimation?.stop();
679
- api.off("reInit", syncAll);
680
- api.off("select", syncSelection);
681
- api.off("scroll", trackScroll);
507
+ observer?.disconnect();
508
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
682
509
  };
683
510
  };
684
- t5 = [
685
- api,
686
- position,
687
- reduceMotion
688
- ];
689
- $[6] = api;
690
- $[7] = position;
691
- $[8] = reduceMotion;
692
- $[9] = t4;
693
- $[10] = t5;
511
+ t8 = [interval];
512
+ $[23] = interval;
513
+ $[24] = t7;
514
+ $[25] = t8;
694
515
  } else {
695
- t4 = $[9];
696
- t5 = $[10];
697
- }
698
- React.useEffect(t4, t5);
699
- if (snapCount < 2) {
700
- return null;
701
- }
702
- const t6 = orientation === "vertical" && "flex-col";
703
- let t7;
704
- if ($[11] !== className || $[12] !== t6) {
705
- t7 = cn("flex min-w-0 items-center justify-center", t6, className);
706
- $[11] = className;
707
- $[12] = t6;
708
- $[13] = t7;
709
- } else {
710
- t7 = $[13];
711
- }
712
- let t8;
713
- if ($[14] !== api || $[15] !== isLooping || $[16] !== orientation || $[17] !== position || $[18] !== reduceMotion || $[19] !== selectedIndex || $[20] !== slideLabel || $[21] !== snapCount) {
714
- t8 = Array.from({ length: snapCount }, (_, index) => /* @__PURE__ */ _jsx(CarouselIndicator, {
715
- index,
716
- lastIndex: snapCount - 1,
717
- isLooping,
718
- position,
719
- isSelected: index === selectedIndex,
720
- orientation: orientation ?? "horizontal",
721
- label: slideLabel(index, snapCount),
722
- indicatorRef: (node) => {
723
- indicatorRefs.current[index] = node;
724
- },
725
- onSelect: () => api?.scrollTo(index, reduceMotion)
726
- }, index));
727
- $[14] = api;
728
- $[15] = isLooping;
729
- $[16] = orientation;
730
- $[17] = position;
731
- $[18] = reduceMotion;
732
- $[19] = selectedIndex;
733
- $[20] = slideLabel;
734
- $[21] = snapCount;
735
- $[22] = t8;
736
- } else {
737
- t8 = $[22];
516
+ t7 = $[24];
517
+ t8 = $[25];
738
518
  }
519
+ React.useEffect(t7, t8);
739
520
  let t9;
740
- if ($[23] !== label || $[24] !== props || $[25] !== t7 || $[26] !== t8) {
741
- t9 = /* @__PURE__ */ _jsx("div", {
742
- role: "group",
743
- "aria-label": label,
744
- "data-slot": "carousel-indicators",
745
- className: t7,
746
- ...props,
747
- children: t8
748
- });
749
- $[23] = label;
750
- $[24] = props;
751
- $[25] = t7;
752
- $[26] = t8;
753
- $[27] = t9;
754
- } else {
755
- t9 = $[27];
756
- }
757
- return t9;
758
- }
759
- function _temp(indicator) {
760
- return indicator !== null && indicator === document.activeElement;
761
- }
762
- /** One dot that grows toward the pill as the track nears its slide, so the pill hands over continuously. */
763
- function CarouselIndicator(t0) {
764
- const $ = _c(24);
765
- const { index, lastIndex, isLooping, position, isSelected, orientation, label, indicatorRef, onSelect } = t0;
766
- let t1;
767
- if ($[0] !== index || $[1] !== isLooping || $[2] !== lastIndex) {
768
- t1 = (value) => {
769
- if (!isLooping) {
770
- return Math.max(0, 1 - Math.abs(Math.min(lastIndex, Math.max(0, value)) - index));
521
+ if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
522
+ t9 = (target) => {
523
+ if (!(target instanceof Element) || target === playRef.current) {
524
+ setIsFocusPaused(false);
525
+ return;
771
526
  }
772
- const count = lastIndex + 1;
773
- const distance = Math.abs(value - index) % count;
774
- return Math.max(0, 1 - Math.min(distance, count - distance));
527
+ setIsFocusPaused(target.matches(":focus-visible"));
775
528
  };
776
- $[0] = index;
777
- $[1] = isLooping;
778
- $[2] = lastIndex;
779
- $[3] = t1;
529
+ $[26] = t9;
780
530
  } else {
781
- t1 = $[3];
531
+ t9 = $[26];
782
532
  }
783
- const emphasis = useTransform(position, t1);
784
- const length = useTransform(emphasis, _temp2);
785
- const t2 = isSelected || undefined;
786
- const t3 = orientation === "horizontal" ? "h-(--control-height-sm) px-[5px]" : "w-(--control-height-sm) py-[5px]";
787
- let t4;
788
- if ($[4] !== t3) {
789
- t4 = cn("group/indicator grid shrink-0 cursor-pointer place-items-center rounded-full border-0 bg-transparent p-0 outline-none [-webkit-tap-highlight-color:transparent] focus-visible:ring-3 focus-visible:ring-ring/50", t3);
790
- $[4] = t3;
791
- $[5] = t4;
792
- } else {
793
- t4 = $[5];
794
- }
795
- const t5 = orientation === "horizontal" ? "h-1.5" : "w-1.5";
796
- let t6;
797
- if ($[6] !== t5) {
798
- t6 = cn("relative block overflow-hidden rounded-full bg-border-strong transition-colors duration-(--duration-fast) ease-(--ease-standard) motion-reduce:transition-none group-hover/indicator:bg-text-muted", t5);
799
- $[6] = t5;
800
- $[7] = t6;
801
- } else {
802
- t6 = $[7];
803
- }
804
- let t7;
805
- if ($[8] !== length || $[9] !== orientation) {
806
- t7 = orientation === "horizontal" ? { width: length } : { height: length };
807
- $[8] = length;
808
- $[9] = orientation;
809
- $[10] = t7;
810
- } else {
811
- t7 = $[10];
812
- }
813
- let t8;
814
- if ($[11] !== emphasis) {
815
- t8 = /* @__PURE__ */ _jsx(motion.span, {
816
- className: "absolute inset-0 bg-foreground",
817
- style: { opacity: emphasis }
818
- });
819
- $[11] = emphasis;
820
- $[12] = t8;
821
- } else {
822
- t8 = $[12];
823
- }
824
- let t9;
825
- if ($[13] !== t6 || $[14] !== t7 || $[15] !== t8) {
826
- t9 = /* @__PURE__ */ _jsx(motion.span, {
827
- "aria-hidden": "true",
828
- className: t6,
829
- style: t7,
830
- children: t8
831
- });
832
- $[13] = t6;
833
- $[14] = t7;
834
- $[15] = t8;
835
- $[16] = t9;
533
+ const handleFocus = t9;
534
+ let t10;
535
+ if ($[27] !== drain || $[28] !== isPlaying || $[29] !== reduceMotion) {
536
+ t10 = () => {
537
+ if (!isPlaying) {
538
+ setIsPlaying(true);
539
+ return;
540
+ }
541
+ setIsPlaying(false);
542
+ if (reduceMotion) {
543
+ drain.jump(0);
544
+ } else {
545
+ animate(drain, 0, {
546
+ duration: ARC_DURATION.standard,
547
+ ease: [...ARC_EASE.standard]
548
+ });
549
+ }
550
+ };
551
+ $[27] = drain;
552
+ $[28] = isPlaying;
553
+ $[29] = reduceMotion;
554
+ $[30] = t10;
836
555
  } else {
837
- t9 = $[16];
556
+ t10 = $[30];
838
557
  }
839
- let t10;
840
- if ($[17] !== indicatorRef || $[18] !== label || $[19] !== onSelect || $[20] !== t2 || $[21] !== t4 || $[22] !== t9) {
841
- t10 = /* @__PURE__ */ _jsx("button", {
842
- ref: indicatorRef,
843
- type: "button",
844
- "aria-current": t2,
845
- "aria-label": label,
846
- "data-slot": "carousel-indicator",
847
- className: t4,
848
- onClick: onSelect,
849
- children: t9
850
- });
851
- $[17] = indicatorRef;
852
- $[18] = label;
853
- $[19] = onSelect;
854
- $[20] = t2;
855
- $[21] = t4;
856
- $[22] = t9;
857
- $[23] = t10;
558
+ const toggle = t10;
559
+ const t11 = canRotate && isPlaying;
560
+ const t12 = canRotate ? drain : undefined;
561
+ let t13;
562
+ if ($[31] !== canRotate || $[32] !== hasControl || $[33] !== t11 || $[34] !== t12 || $[35] !== toggle) {
563
+ t13 = {
564
+ hasControl,
565
+ canRotate,
566
+ isPlaying: t11,
567
+ drain: t12,
568
+ rootRef,
569
+ playRef,
570
+ setIsHovered,
571
+ handleFocus,
572
+ toggle
573
+ };
574
+ $[31] = canRotate;
575
+ $[32] = hasControl;
576
+ $[33] = t11;
577
+ $[34] = t12;
578
+ $[35] = toggle;
579
+ $[36] = t13;
858
580
  } else {
859
- t10 = $[23];
581
+ t13 = $[36];
860
582
  }
861
- return t10;
862
- }
863
- function _temp2(value_0) {
864
- return CAROUSEL_INDICATOR_LENGTH_PX.dot + (CAROUSEL_INDICATOR_LENGTH_PX.pill - CAROUSEL_INDICATOR_LENGTH_PX.dot) * value_0;
583
+ return t13;
865
584
  }
866
- export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselIndicators, useCarousel };
585
+ export { Carousel };