@pitchfork-ui/react 0.2.0 → 0.7.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 (70) hide show
  1. package/dist/components/Accordion/Accordion.css +85 -0
  2. package/dist/components/Accordion/Accordion2.js +96 -0
  3. package/dist/components/Alert/Alert.css +29 -1
  4. package/dist/components/Alert/Alert2.js +4 -2
  5. package/dist/components/Avatar/Avatar.css +1 -1
  6. package/dist/components/BadgeGroup/BadgeGroup.css +4 -4
  7. package/dist/components/Button/Button.css +4 -4
  8. package/dist/components/ButtonGroup/ButtonGroup.css +2 -2
  9. package/dist/components/Carousel/Carousel.css +4 -2
  10. package/dist/components/Carousel/Carousel2.js +89 -76
  11. package/dist/components/CodeSnippet/CodeSnippet.css +2 -2
  12. package/dist/components/ContentDivider/ContentDivider.css +2 -2
  13. package/dist/components/DatePicker/DatePicker.css +1 -1
  14. package/dist/components/DatePicker/DatePicker2.js +3 -3
  15. package/dist/components/Dropdown/Dropdown.css +19 -2
  16. package/dist/components/Dropdown/Dropdown2.js +2 -3
  17. package/dist/components/GaugeChart/GaugeChart.css +18 -1
  18. package/dist/components/GaugeChart/GaugeChart2.js +5 -4
  19. package/dist/components/Heatmap/Heatmap.css +104 -0
  20. package/dist/components/Heatmap/Heatmap2.js +160 -0
  21. package/dist/components/InlineCTA/InlineCTA.css +58 -0
  22. package/dist/components/InlineCTA/InlineCTA2.js +14 -2
  23. package/dist/components/Modal/Modal.css +62 -0
  24. package/dist/components/Modal/Modal2.js +8 -6
  25. package/dist/components/MultiSelect/MultiSelect.css +19 -2
  26. package/dist/components/MultiSelect/MultiSelect2.js +3 -4
  27. package/dist/components/Notification/Notification.css +59 -4
  28. package/dist/components/Notification/Notification2.js +4 -2
  29. package/dist/components/Pagination/Pagination.css +5 -2
  30. package/dist/components/PieChart/PieChart.css +34 -0
  31. package/dist/components/PieChart/PieChart2.js +1 -1
  32. package/dist/components/ProgressIndicators/ProgressIndicators.css +20 -2
  33. package/dist/components/ProgressIndicators/ProgressIndicators2.js +4 -1
  34. package/dist/components/ProgressSteps/ProgressSteps.css +20 -3
  35. package/dist/components/RadarChart/RadarChart.css +22 -0
  36. package/dist/components/RadarChart/RadarChart2.js +19 -13
  37. package/dist/components/RichTextEditor/RichTextEditor.css +1 -1
  38. package/dist/components/Select/Select.css +21 -2
  39. package/dist/components/Select/Select2.js +3 -4
  40. package/dist/components/SidebarNavigation/SidebarNavigation.css +1 -1
  41. package/dist/components/SlideoutMenu/SlideoutMenu.css +2 -2
  42. package/dist/components/Sparkline/Sparkline.css +48 -0
  43. package/dist/components/Sparkline/Sparkline2.js +3 -2
  44. package/dist/components/Table/Table.css +4 -4
  45. package/dist/components/Tabs/Tabs.css +31 -5
  46. package/dist/components/Tabs/Tabs2.js +51 -4
  47. package/dist/components/Tag/Tag.css +1 -1
  48. package/dist/components/Tooltip/Tooltip.css +35 -0
  49. package/dist/components/Tooltip/Tooltip2.js +4 -4
  50. package/dist/components/TreeView/TreeView.css +2 -2
  51. package/dist/hooks/useExitAnimation.js +25 -0
  52. package/dist/hooks/usePresence.js +31 -0
  53. package/dist/index.cjs +834 -454
  54. package/dist/index.js +12 -8
  55. package/dist/src/components/Accordion/Accordion.d.ts +20 -0
  56. package/dist/src/components/Accordion/Accordion.test.d.ts +1 -0
  57. package/dist/src/components/Accordion/index.d.ts +1 -0
  58. package/dist/src/components/Heatmap/Heatmap.d.ts +28 -0
  59. package/dist/src/components/Heatmap/Heatmap.test.d.ts +1 -0
  60. package/dist/src/components/Heatmap/index.d.ts +1 -0
  61. package/dist/src/components/InlineCTA/InlineCTA.d.ts +2 -0
  62. package/dist/src/components/Sparkline/Sparkline.d.ts +2 -0
  63. package/dist/src/hooks/index.d.ts +2 -0
  64. package/dist/src/hooks/useExitAnimation.d.ts +18 -0
  65. package/dist/src/hooks/usePresence.d.ts +13 -0
  66. package/dist/src/index.d.ts +2 -0
  67. package/dist/styles/theme.css +47 -13
  68. package/dist/styles.css +767 -66
  69. package/package.json +1 -1
  70. package/theme.starter.css +4 -3
package/dist/index.cjs CHANGED
@@ -59,6 +59,267 @@ var getFocusableElements = (container) => {
59
59
  });
60
60
  };
61
61
  //#endregion
62
+ //#region src/hooks/useAnchoredPosition.ts
63
+ function useAnchoredPosition({ anchorRef, floatingRef, enabled = true, align = "start", offset = 8, viewportPadding = 8, minWidth, matchAnchorWidth = true, flip = false }) {
64
+ const [style, setStyle] = (0, react.useState)({});
65
+ (0, react.useEffect)(() => {
66
+ if (!enabled || typeof window === "undefined") return;
67
+ const updatePosition = () => {
68
+ const anchor = anchorRef.current;
69
+ if (!anchor) return;
70
+ const anchorRect = anchor.getBoundingClientRect();
71
+ const floatingRect = floatingRef?.current?.getBoundingClientRect();
72
+ const width = Math.max(matchAnchorWidth ? anchorRect.width : 0, minWidth ?? 0, floatingRect?.width ?? 0);
73
+ const maxLeft = window.innerWidth - viewportPadding - width;
74
+ const alignedLeft = align === "end" ? anchorRect.right - width : anchorRect.left;
75
+ const left = maxLeft >= viewportPadding ? Math.min(Math.max(alignedLeft, viewportPadding), maxLeft) : viewportPadding;
76
+ const floatingHeight = floatingRect?.height ?? 0;
77
+ const belowTop = anchorRect.bottom + offset;
78
+ const aboveTop = anchorRect.top - floatingHeight - offset;
79
+ const rawTop = flip && floatingHeight > 0 && window.innerHeight - anchorRect.bottom < floatingHeight + offset + viewportPadding ? aboveTop : belowTop;
80
+ const maxTop = window.innerHeight - viewportPadding - floatingHeight;
81
+ setStyle({
82
+ left,
83
+ top: floatingHeight > 0 && maxTop >= viewportPadding ? Math.min(Math.max(rawTop, viewportPadding), maxTop) : rawTop,
84
+ width: matchAnchorWidth ? width : void 0,
85
+ minWidth: matchAnchorWidth ? void 0 : width
86
+ });
87
+ };
88
+ updatePosition();
89
+ window.addEventListener("resize", updatePosition);
90
+ window.addEventListener("scroll", updatePosition, true);
91
+ return () => {
92
+ window.removeEventListener("resize", updatePosition);
93
+ window.removeEventListener("scroll", updatePosition, true);
94
+ };
95
+ }, [
96
+ align,
97
+ anchorRef,
98
+ enabled,
99
+ floatingRef,
100
+ flip,
101
+ matchAnchorWidth,
102
+ minWidth,
103
+ offset,
104
+ viewportPadding
105
+ ]);
106
+ return style;
107
+ }
108
+ //#endregion
109
+ //#region src/hooks/useComposedRefs.ts
110
+ function useComposedRefs(...refs) {
111
+ return (node) => {
112
+ refs.forEach((ref) => {
113
+ if (!ref) return;
114
+ if (typeof ref === "function") {
115
+ ref(node);
116
+ return;
117
+ }
118
+ ref.current = node;
119
+ });
120
+ };
121
+ }
122
+ //#endregion
123
+ //#region src/hooks/useControllableState.ts
124
+ function useControllableState({ value, defaultValue, onChange }) {
125
+ const [internalValue, setInternalValue] = (0, react.useState)(defaultValue);
126
+ const isControlled = value !== void 0;
127
+ const currentValue = isControlled ? value : internalValue;
128
+ return [
129
+ currentValue,
130
+ (0, react.useCallback)((nextValue) => {
131
+ const resolvedValue = typeof nextValue === "function" ? nextValue(currentValue) : nextValue;
132
+ if (!isControlled) setInternalValue(resolvedValue);
133
+ onChange?.(resolvedValue);
134
+ }, [
135
+ currentValue,
136
+ isControlled,
137
+ onChange
138
+ ]),
139
+ isControlled
140
+ ];
141
+ }
142
+ //#endregion
143
+ //#region src/hooks/useDisclosure.ts
144
+ function useDisclosure({ open, defaultOpen = false, onOpenChange, disabled = false } = {}) {
145
+ const [isOpen, setIsOpen] = useControllableState({
146
+ value: open,
147
+ defaultValue: defaultOpen,
148
+ onChange: onOpenChange
149
+ });
150
+ return {
151
+ isOpen,
152
+ setIsOpen,
153
+ open: (0, react.useCallback)(() => {
154
+ if (!disabled) setIsOpen(true);
155
+ }, [disabled, setIsOpen]),
156
+ close: (0, react.useCallback)(() => {
157
+ setIsOpen(false);
158
+ }, [setIsOpen]),
159
+ toggle: (0, react.useCallback)(() => {
160
+ if (!disabled) setIsOpen((current) => !current);
161
+ }, [disabled, setIsOpen])
162
+ };
163
+ }
164
+ //#endregion
165
+ //#region src/hooks/useExitAnimation.ts
166
+ var prefersReducedMotion$1 = () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
167
+ /**
168
+ * Plays an exit animation before signalling removal. Apply `isExiting` to a CSS
169
+ * class that runs the exit keyframes; `onExited` fires after `duration`. When the
170
+ * user prefers reduced motion, `onExited` fires immediately with no animation.
171
+ */
172
+ function useExitAnimation({ onExited, duration = 220 } = {}) {
173
+ const [isExiting, setIsExiting] = (0, react.useState)(false);
174
+ const startExit = () => {
175
+ if (prefersReducedMotion$1()) {
176
+ onExited?.();
177
+ return;
178
+ }
179
+ setIsExiting(true);
180
+ window.setTimeout(() => onExited?.(), duration);
181
+ };
182
+ return {
183
+ isExiting,
184
+ startExit
185
+ };
186
+ }
187
+ //#endregion
188
+ //#region src/hooks/useFocusTrap.ts
189
+ function useFocusTrap({ containerRef, enabled = true, onEscape, restoreFocus = true }) {
190
+ (0, react.useEffect)(() => {
191
+ if (!enabled || typeof document === "undefined") return;
192
+ const container = containerRef.current;
193
+ const previousActiveElement = document.activeElement;
194
+ const initialFocusable = container ? getFocusableElements(container)[0] : void 0;
195
+ if (initialFocusable) initialFocusable.focus();
196
+ else container?.focus();
197
+ const onKeyDown = (event) => {
198
+ if (event.key === Keys.Escape) {
199
+ onEscape?.();
200
+ return;
201
+ }
202
+ if (event.key !== Keys.Tab || !containerRef.current) return;
203
+ const focusableElements = getFocusableElements(containerRef.current);
204
+ if (focusableElements.length === 0) {
205
+ event.preventDefault();
206
+ containerRef.current.focus();
207
+ return;
208
+ }
209
+ const firstElement = focusableElements[0];
210
+ const lastElement = focusableElements[focusableElements.length - 1];
211
+ const activeElement = document.activeElement;
212
+ if (!(activeElement ? containerRef.current.contains(activeElement) : false)) {
213
+ event.preventDefault();
214
+ (event.shiftKey ? lastElement : firstElement).focus();
215
+ return;
216
+ }
217
+ if (event.shiftKey && activeElement === firstElement) {
218
+ event.preventDefault();
219
+ lastElement.focus();
220
+ return;
221
+ }
222
+ if (!event.shiftKey && activeElement === lastElement) {
223
+ event.preventDefault();
224
+ firstElement.focus();
225
+ }
226
+ };
227
+ document.addEventListener("keydown", onKeyDown);
228
+ return () => {
229
+ document.removeEventListener("keydown", onKeyDown);
230
+ if (restoreFocus) previousActiveElement?.focus?.();
231
+ };
232
+ }, [
233
+ containerRef,
234
+ enabled,
235
+ onEscape,
236
+ restoreFocus
237
+ ]);
238
+ }
239
+ //#endregion
240
+ //#region src/hooks/useListNavigation.ts
241
+ function useListNavigation({ items, isDisabled = () => false, initialIndex }) {
242
+ const enabledIndexes = (0, react.useMemo)(() => items.map((item, index) => ({
243
+ item,
244
+ index
245
+ })).filter(({ item, index }) => !isDisabled(item, index)).map(({ index }) => index), [isDisabled, items]);
246
+ const firstEnabledIndex = enabledIndexes[0] ?? -1;
247
+ const lastEnabledIndex = enabledIndexes[enabledIndexes.length - 1] ?? -1;
248
+ const [activeIndex, setActiveIndex] = (0, react.useState)(initialIndex ?? firstEnabledIndex);
249
+ const getNextEnabledIndex = (0, react.useCallback)((startIndex, direction) => {
250
+ if (enabledIndexes.length === 0) return -1;
251
+ const currentEnabledPosition = enabledIndexes.indexOf(startIndex);
252
+ return enabledIndexes[((currentEnabledPosition === -1 ? direction === 1 ? -1 : 0 : currentEnabledPosition) + direction + enabledIndexes.length) % enabledIndexes.length] ?? -1;
253
+ }, [enabledIndexes]);
254
+ return {
255
+ activeIndex,
256
+ enabledIndexes,
257
+ firstEnabledIndex,
258
+ lastEnabledIndex,
259
+ getNextEnabledIndex,
260
+ move: (0, react.useCallback)((action, currentIndex = activeIndex) => {
261
+ const nextIndex = action === "first" ? firstEnabledIndex : action === "last" ? lastEnabledIndex : getNextEnabledIndex(currentIndex, action === "next" ? 1 : -1);
262
+ if (nextIndex >= 0) setActiveIndex(nextIndex);
263
+ return nextIndex;
264
+ }, [
265
+ activeIndex,
266
+ firstEnabledIndex,
267
+ getNextEnabledIndex,
268
+ lastEnabledIndex
269
+ ]),
270
+ setActiveIndex
271
+ };
272
+ }
273
+ //#endregion
274
+ //#region src/hooks/useOutsideInteraction.ts
275
+ function useOutsideInteraction({ refs, enabled = true, onInteractOutside, eventName = "pointerdown" }) {
276
+ (0, react.useEffect)(() => {
277
+ if (!enabled || typeof document === "undefined") return;
278
+ const handleEvent = (event) => {
279
+ const target = event.target;
280
+ if (!refs.some((ref) => ref.current?.contains(target))) onInteractOutside(event);
281
+ };
282
+ document.addEventListener(eventName, handleEvent);
283
+ return () => {
284
+ document.removeEventListener(eventName, handleEvent);
285
+ };
286
+ }, [
287
+ enabled,
288
+ eventName,
289
+ onInteractOutside,
290
+ refs
291
+ ]);
292
+ }
293
+ //#endregion
294
+ //#region src/hooks/usePresence.ts
295
+ var prefersReducedMotion = () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
296
+ /**
297
+ * Keeps a conditionally-rendered element mounted long enough to play an exit
298
+ * animation. Drive it with the `present` prop (e.g. a Modal's `open`): when it
299
+ * flips to false, the element stays mounted with `isExiting` true for `duration`
300
+ * ms, then unmounts. Reduced motion unmounts immediately.
301
+ */
302
+ function usePresence(present, duration = 200) {
303
+ const [isExiting, setIsExiting] = (0, react.useState)(false);
304
+ const wasPresent = (0, react.useRef)(false);
305
+ (0, react.useEffect)(() => {
306
+ if (present) {
307
+ wasPresent.current = true;
308
+ return;
309
+ }
310
+ if (!wasPresent.current || prefersReducedMotion()) return;
311
+ wasPresent.current = false;
312
+ setIsExiting(true);
313
+ const timer = window.setTimeout(() => setIsExiting(false), duration);
314
+ return () => window.clearTimeout(timer);
315
+ }, [present, duration]);
316
+ const exiting = !present && isExiting;
317
+ return {
318
+ isMounted: present || exiting,
319
+ isExiting: exiting
320
+ };
321
+ }
322
+ //#endregion
62
323
  //#region src/utils/cx.ts
63
324
  function cx(...classes) {
64
325
  return classes.filter(Boolean).join(" ");
@@ -240,28 +501,117 @@ function Icon({ name, label, className, style, ...props }) {
240
501
  }
241
502
  Icon.displayName = "Icon";
242
503
  //#endregion
243
- //#region src/components/Alert/Alert.tsx
244
- var variantIcon$1 = {
245
- info: "circle-info",
246
- success: "circle-check",
247
- warning: "triangle-exclamation",
248
- danger: "circle-xmark"
249
- };
250
- var variantRole = {
251
- info: "status",
252
- success: "status",
253
- warning: "alert",
254
- danger: "alert"
255
- };
256
- var Alert = (0, react.forwardRef)(({ className, variant = "info", heading, description, dismissible = false, onDismiss, icon, children, ...props }, ref) => {
257
- const resolvedIcon = icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
258
- name: variantIcon$1[variant],
259
- "aria-hidden": true
504
+ //#region src/components/Accordion/Accordion.tsx
505
+ var Accordion = (0, react.forwardRef)(function Accordion({ className, items, type = "single", value, defaultValue, onValueChange, headingLevel = 3, ...props }, ref) {
506
+ const baseId = (0, react.useId)();
507
+ const [expanded = [], setExpanded] = useControllableState({
508
+ value,
509
+ defaultValue: defaultValue ?? [],
510
+ onChange: onValueChange
260
511
  });
261
- const body = children ?? description;
262
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
512
+ const triggerRefs = (0, react.useRef)([]);
513
+ const toggle = (itemValue) => {
514
+ const isOpen = expanded.includes(itemValue);
515
+ if (type === "single") setExpanded(isOpen ? [] : [itemValue]);
516
+ else setExpanded(isOpen ? expanded.filter((v) => v !== itemValue) : [...expanded, itemValue]);
517
+ };
518
+ const enabledIndexes = items.map((item, index) => ({
519
+ item,
520
+ index
521
+ })).filter(({ item }) => !item.disabled).map(({ index }) => index);
522
+ const onTriggerKeyDown = (event, index) => {
523
+ if (enabledIndexes.length === 0) return;
524
+ const position = enabledIndexes.indexOf(index);
525
+ let target;
526
+ if (event.key === Keys.ArrowDown) target = enabledIndexes[(position + 1) % enabledIndexes.length];
527
+ else if (event.key === Keys.ArrowUp) target = enabledIndexes[(position - 1 + enabledIndexes.length) % enabledIndexes.length];
528
+ else if (event.key === Keys.Home) target = enabledIndexes[0];
529
+ else if (event.key === Keys.End) target = enabledIndexes[enabledIndexes.length - 1];
530
+ if (target !== void 0) {
531
+ event.preventDefault();
532
+ triggerRefs.current[target]?.focus();
533
+ }
534
+ };
535
+ const Heading = `h${headingLevel}`;
536
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
263
537
  ref,
264
- className: cx("pf-alert", `pf-alert--${variant}`, className),
538
+ className: cx("pf-accordion", className),
539
+ ...props,
540
+ children: items.map((item, index) => {
541
+ const isOpen = expanded.includes(item.value);
542
+ const triggerId = `${baseId}-trigger-${item.value}`;
543
+ const panelId = `${baseId}-panel-${item.value}`;
544
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
545
+ className: cx("pf-accordion__item", isOpen && "pf-accordion__item--open"),
546
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Heading, {
547
+ className: "pf-accordion__heading",
548
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
549
+ ref: (element) => {
550
+ triggerRefs.current[index] = element;
551
+ },
552
+ type: "button",
553
+ id: triggerId,
554
+ className: "pf-accordion__trigger",
555
+ "aria-expanded": isOpen,
556
+ "aria-controls": panelId,
557
+ disabled: item.disabled,
558
+ onClick: () => toggle(item.value),
559
+ onKeyDown: (event) => onTriggerKeyDown(event, index),
560
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
561
+ className: "pf-accordion__title",
562
+ children: item.title
563
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
564
+ className: "pf-accordion__icon",
565
+ "aria-hidden": true,
566
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
567
+ name: "chevron-down",
568
+ "aria-hidden": true
569
+ })
570
+ })]
571
+ })
572
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
573
+ className: cx("pf-accordion__panel", isOpen && "pf-accordion__panel--open"),
574
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
575
+ id: panelId,
576
+ role: "region",
577
+ "aria-labelledby": triggerId,
578
+ className: "pf-accordion__content",
579
+ ...isOpen ? {} : { inert: true },
580
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
581
+ className: "pf-accordion__content-inner",
582
+ children: item.content
583
+ })
584
+ })
585
+ })]
586
+ }, item.value);
587
+ })
588
+ });
589
+ });
590
+ Accordion.displayName = "Accordion";
591
+ //#endregion
592
+ //#region src/components/Alert/Alert.tsx
593
+ var variantIcon$1 = {
594
+ info: "circle-info",
595
+ success: "circle-check",
596
+ warning: "triangle-exclamation",
597
+ danger: "circle-xmark"
598
+ };
599
+ var variantRole = {
600
+ info: "status",
601
+ success: "status",
602
+ warning: "alert",
603
+ danger: "alert"
604
+ };
605
+ var Alert = (0, react.forwardRef)(({ className, variant = "info", heading, description, dismissible = false, onDismiss, icon, children, ...props }, ref) => {
606
+ const resolvedIcon = icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
607
+ name: variantIcon$1[variant],
608
+ "aria-hidden": true
609
+ });
610
+ const body = children ?? description;
611
+ const { isExiting, startExit } = useExitAnimation({ onExited: onDismiss });
612
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
613
+ ref,
614
+ className: cx("pf-alert", `pf-alert--${variant}`, isExiting && "pf-alert--exiting", className),
265
615
  role: variantRole[variant],
266
616
  ...props,
267
617
  children: [
@@ -284,7 +634,7 @@ var Alert = (0, react.forwardRef)(({ className, variant = "info", heading, descr
284
634
  type: "button",
285
635
  className: "pf-alert__dismiss",
286
636
  "aria-label": "Dismiss alert",
287
- onClick: () => onDismiss?.(),
637
+ onClick: startExit,
288
638
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
289
639
  name: "circle-xmark",
290
640
  "aria-hidden": true
@@ -547,325 +897,116 @@ function Card({ className, ref, ...props }) {
547
897
  ref,
548
898
  className: cx("pf-card", className),
549
899
  ...props
550
- });
551
- }
552
- Card.displayName = "Card";
553
- function CardHeader({ className, ref, ...props }) {
554
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
555
- ref,
556
- className: cx("pf-card__header", className),
557
- ...props
558
- });
559
- }
560
- CardHeader.displayName = "CardHeader";
561
- function CardContent({ className, ref, ...props }) {
562
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
563
- ref,
564
- className: cx("pf-card__content", className),
565
- ...props
566
- });
567
- }
568
- CardContent.displayName = "CardContent";
569
- function CardFooter({ className, ref, ...props }) {
570
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
571
- ref,
572
- className: cx("pf-card__footer", className),
573
- ...props
574
- });
575
- }
576
- CardFooter.displayName = "CardFooter";
577
- //#endregion
578
- //#region src/components/CreditCard/CreditCard.tsx
579
- var maskCardNumber = (value) => {
580
- const digits = value.replace(/\D+/g, "");
581
- if (digits.length <= 4) return digits;
582
- const visible = digits.slice(-4);
583
- const hiddenLength = digits.length - 4;
584
- return `${"*".repeat(hiddenLength)}${visible}`.replace(/(.{4})/g, "$1 ").trim();
585
- };
586
- var formatCardNumber = (value) => {
587
- return value.replace(/\D+/g, "").replace(/(.{4})/g, "$1 ").trim();
588
- };
589
- var CreditCard = (0, react.forwardRef)(({ brand = "generic", cardNumber, cardholderName, expiry, cvc, masked = true, className, ...props }, ref) => {
590
- const displayNumber = masked ? maskCardNumber(cardNumber) : formatCardNumber(cardNumber);
591
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
592
- ref,
593
- className: cx("pf-credit-card", `is-${brand}`, className),
594
- ...props,
595
- children: [
596
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
597
- className: "top-row",
598
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
599
- className: "chip",
600
- "aria-hidden": true
601
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
602
- className: "brand",
603
- children: brand.toUpperCase()
604
- })]
605
- }),
606
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
607
- className: "number",
608
- children: displayNumber
609
- }),
610
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
611
- className: "meta",
612
- children: [
613
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
614
- className: "label",
615
- children: "Card holder"
616
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
617
- className: "value",
618
- children: cardholderName
619
- })] }),
620
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
621
- className: "label",
622
- children: "Expires"
623
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
624
- className: "value",
625
- children: expiry
626
- })] }),
627
- cvc ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
628
- className: "label",
629
- children: "CVC"
630
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
631
- className: "value",
632
- children: masked ? "***" : cvc
633
- })] }) : null
634
- ]
635
- })
636
- ]
637
- });
638
- });
639
- CreditCard.displayName = "CreditCard";
640
- //#endregion
641
- //#region src/components/Checkbox/Checkbox.tsx
642
- var Checkbox = (0, react.forwardRef)(({ id, label, className, ...props }, ref) => {
643
- const generatedId = (0, react.useId)();
644
- const checkboxId = id ?? generatedId;
645
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
646
- className: "pf-checkbox-field",
647
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
648
- ref,
649
- id: checkboxId,
650
- type: "checkbox",
651
- className: cx("pf-checkbox", className),
652
- ...props
653
- }), label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
654
- htmlFor: checkboxId,
655
- children: label
656
- }) : null]
657
- });
658
- });
659
- Checkbox.displayName = "Checkbox";
660
- //#endregion
661
- //#region src/hooks/useAnchoredPosition.ts
662
- function useAnchoredPosition({ anchorRef, floatingRef, enabled = true, align = "start", offset = 8, viewportPadding = 8, minWidth, matchAnchorWidth = true, flip = false }) {
663
- const [style, setStyle] = (0, react.useState)({});
664
- (0, react.useEffect)(() => {
665
- if (!enabled || typeof window === "undefined") return;
666
- const updatePosition = () => {
667
- const anchor = anchorRef.current;
668
- if (!anchor) return;
669
- const anchorRect = anchor.getBoundingClientRect();
670
- const floatingRect = floatingRef?.current?.getBoundingClientRect();
671
- const width = Math.max(matchAnchorWidth ? anchorRect.width : 0, minWidth ?? 0, floatingRect?.width ?? 0);
672
- const maxLeft = window.innerWidth - viewportPadding - width;
673
- const alignedLeft = align === "end" ? anchorRect.right - width : anchorRect.left;
674
- const left = maxLeft >= viewportPadding ? Math.min(Math.max(alignedLeft, viewportPadding), maxLeft) : viewportPadding;
675
- const floatingHeight = floatingRect?.height ?? 0;
676
- const belowTop = anchorRect.bottom + offset;
677
- const aboveTop = anchorRect.top - floatingHeight - offset;
678
- const rawTop = flip && floatingHeight > 0 && window.innerHeight - anchorRect.bottom < floatingHeight + offset + viewportPadding ? aboveTop : belowTop;
679
- const maxTop = window.innerHeight - viewportPadding - floatingHeight;
680
- setStyle({
681
- left,
682
- top: floatingHeight > 0 && maxTop >= viewportPadding ? Math.min(Math.max(rawTop, viewportPadding), maxTop) : rawTop,
683
- width: matchAnchorWidth ? width : void 0,
684
- minWidth: matchAnchorWidth ? void 0 : width
685
- });
686
- };
687
- updatePosition();
688
- window.addEventListener("resize", updatePosition);
689
- window.addEventListener("scroll", updatePosition, true);
690
- return () => {
691
- window.removeEventListener("resize", updatePosition);
692
- window.removeEventListener("scroll", updatePosition, true);
693
- };
694
- }, [
695
- align,
696
- anchorRef,
697
- enabled,
698
- floatingRef,
699
- flip,
700
- matchAnchorWidth,
701
- minWidth,
702
- offset,
703
- viewportPadding
704
- ]);
705
- return style;
706
- }
707
- //#endregion
708
- //#region src/hooks/useComposedRefs.ts
709
- function useComposedRefs(...refs) {
710
- return (node) => {
711
- refs.forEach((ref) => {
712
- if (!ref) return;
713
- if (typeof ref === "function") {
714
- ref(node);
715
- return;
716
- }
717
- ref.current = node;
718
- });
719
- };
720
- }
721
- //#endregion
722
- //#region src/hooks/useControllableState.ts
723
- function useControllableState({ value, defaultValue, onChange }) {
724
- const [internalValue, setInternalValue] = (0, react.useState)(defaultValue);
725
- const isControlled = value !== void 0;
726
- const currentValue = isControlled ? value : internalValue;
727
- return [
728
- currentValue,
729
- (0, react.useCallback)((nextValue) => {
730
- const resolvedValue = typeof nextValue === "function" ? nextValue(currentValue) : nextValue;
731
- if (!isControlled) setInternalValue(resolvedValue);
732
- onChange?.(resolvedValue);
733
- }, [
734
- currentValue,
735
- isControlled,
736
- onChange
737
- ]),
738
- isControlled
739
- ];
740
- }
741
- //#endregion
742
- //#region src/hooks/useDisclosure.ts
743
- function useDisclosure({ open, defaultOpen = false, onOpenChange, disabled = false } = {}) {
744
- const [isOpen, setIsOpen] = useControllableState({
745
- value: open,
746
- defaultValue: defaultOpen,
747
- onChange: onOpenChange
748
- });
749
- return {
750
- isOpen,
751
- setIsOpen,
752
- open: (0, react.useCallback)(() => {
753
- if (!disabled) setIsOpen(true);
754
- }, [disabled, setIsOpen]),
755
- close: (0, react.useCallback)(() => {
756
- setIsOpen(false);
757
- }, [setIsOpen]),
758
- toggle: (0, react.useCallback)(() => {
759
- if (!disabled) setIsOpen((current) => !current);
760
- }, [disabled, setIsOpen])
761
- };
762
- }
763
- //#endregion
764
- //#region src/hooks/useFocusTrap.ts
765
- function useFocusTrap({ containerRef, enabled = true, onEscape, restoreFocus = true }) {
766
- (0, react.useEffect)(() => {
767
- if (!enabled || typeof document === "undefined") return;
768
- const container = containerRef.current;
769
- const previousActiveElement = document.activeElement;
770
- const initialFocusable = container ? getFocusableElements(container)[0] : void 0;
771
- if (initialFocusable) initialFocusable.focus();
772
- else container?.focus();
773
- const onKeyDown = (event) => {
774
- if (event.key === Keys.Escape) {
775
- onEscape?.();
776
- return;
777
- }
778
- if (event.key !== Keys.Tab || !containerRef.current) return;
779
- const focusableElements = getFocusableElements(containerRef.current);
780
- if (focusableElements.length === 0) {
781
- event.preventDefault();
782
- containerRef.current.focus();
783
- return;
784
- }
785
- const firstElement = focusableElements[0];
786
- const lastElement = focusableElements[focusableElements.length - 1];
787
- const activeElement = document.activeElement;
788
- if (!(activeElement ? containerRef.current.contains(activeElement) : false)) {
789
- event.preventDefault();
790
- (event.shiftKey ? lastElement : firstElement).focus();
791
- return;
792
- }
793
- if (event.shiftKey && activeElement === firstElement) {
794
- event.preventDefault();
795
- lastElement.focus();
796
- return;
797
- }
798
- if (!event.shiftKey && activeElement === lastElement) {
799
- event.preventDefault();
800
- firstElement.focus();
801
- }
802
- };
803
- document.addEventListener("keydown", onKeyDown);
804
- return () => {
805
- document.removeEventListener("keydown", onKeyDown);
806
- if (restoreFocus) previousActiveElement?.focus?.();
807
- };
808
- }, [
809
- containerRef,
810
- enabled,
811
- onEscape,
812
- restoreFocus
813
- ]);
814
- }
815
- //#endregion
816
- //#region src/hooks/useListNavigation.ts
817
- function useListNavigation({ items, isDisabled = () => false, initialIndex }) {
818
- const enabledIndexes = (0, react.useMemo)(() => items.map((item, index) => ({
819
- item,
820
- index
821
- })).filter(({ item, index }) => !isDisabled(item, index)).map(({ index }) => index), [isDisabled, items]);
822
- const firstEnabledIndex = enabledIndexes[0] ?? -1;
823
- const lastEnabledIndex = enabledIndexes[enabledIndexes.length - 1] ?? -1;
824
- const [activeIndex, setActiveIndex] = (0, react.useState)(initialIndex ?? firstEnabledIndex);
825
- const getNextEnabledIndex = (0, react.useCallback)((startIndex, direction) => {
826
- if (enabledIndexes.length === 0) return -1;
827
- const currentEnabledPosition = enabledIndexes.indexOf(startIndex);
828
- return enabledIndexes[((currentEnabledPosition === -1 ? direction === 1 ? -1 : 0 : currentEnabledPosition) + direction + enabledIndexes.length) % enabledIndexes.length] ?? -1;
829
- }, [enabledIndexes]);
830
- return {
831
- activeIndex,
832
- enabledIndexes,
833
- firstEnabledIndex,
834
- lastEnabledIndex,
835
- getNextEnabledIndex,
836
- move: (0, react.useCallback)((action, currentIndex = activeIndex) => {
837
- const nextIndex = action === "first" ? firstEnabledIndex : action === "last" ? lastEnabledIndex : getNextEnabledIndex(currentIndex, action === "next" ? 1 : -1);
838
- if (nextIndex >= 0) setActiveIndex(nextIndex);
839
- return nextIndex;
840
- }, [
841
- activeIndex,
842
- firstEnabledIndex,
843
- getNextEnabledIndex,
844
- lastEnabledIndex
845
- ]),
846
- setActiveIndex
847
- };
900
+ });
848
901
  }
849
- //#endregion
850
- //#region src/hooks/useOutsideInteraction.ts
851
- function useOutsideInteraction({ refs, enabled = true, onInteractOutside, eventName = "pointerdown" }) {
852
- (0, react.useEffect)(() => {
853
- if (!enabled || typeof document === "undefined") return;
854
- const handleEvent = (event) => {
855
- const target = event.target;
856
- if (!refs.some((ref) => ref.current?.contains(target))) onInteractOutside(event);
857
- };
858
- document.addEventListener(eventName, handleEvent);
859
- return () => {
860
- document.removeEventListener(eventName, handleEvent);
861
- };
862
- }, [
863
- enabled,
864
- eventName,
865
- onInteractOutside,
866
- refs
867
- ]);
902
+ Card.displayName = "Card";
903
+ function CardHeader({ className, ref, ...props }) {
904
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
905
+ ref,
906
+ className: cx("pf-card__header", className),
907
+ ...props
908
+ });
909
+ }
910
+ CardHeader.displayName = "CardHeader";
911
+ function CardContent({ className, ref, ...props }) {
912
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
913
+ ref,
914
+ className: cx("pf-card__content", className),
915
+ ...props
916
+ });
917
+ }
918
+ CardContent.displayName = "CardContent";
919
+ function CardFooter({ className, ref, ...props }) {
920
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
921
+ ref,
922
+ className: cx("pf-card__footer", className),
923
+ ...props
924
+ });
868
925
  }
926
+ CardFooter.displayName = "CardFooter";
927
+ //#endregion
928
+ //#region src/components/CreditCard/CreditCard.tsx
929
+ var maskCardNumber = (value) => {
930
+ const digits = value.replace(/\D+/g, "");
931
+ if (digits.length <= 4) return digits;
932
+ const visible = digits.slice(-4);
933
+ const hiddenLength = digits.length - 4;
934
+ return `${"*".repeat(hiddenLength)}${visible}`.replace(/(.{4})/g, "$1 ").trim();
935
+ };
936
+ var formatCardNumber = (value) => {
937
+ return value.replace(/\D+/g, "").replace(/(.{4})/g, "$1 ").trim();
938
+ };
939
+ var CreditCard = (0, react.forwardRef)(({ brand = "generic", cardNumber, cardholderName, expiry, cvc, masked = true, className, ...props }, ref) => {
940
+ const displayNumber = masked ? maskCardNumber(cardNumber) : formatCardNumber(cardNumber);
941
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
942
+ ref,
943
+ className: cx("pf-credit-card", `is-${brand}`, className),
944
+ ...props,
945
+ children: [
946
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
947
+ className: "top-row",
948
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
949
+ className: "chip",
950
+ "aria-hidden": true
951
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
952
+ className: "brand",
953
+ children: brand.toUpperCase()
954
+ })]
955
+ }),
956
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
957
+ className: "number",
958
+ children: displayNumber
959
+ }),
960
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
961
+ className: "meta",
962
+ children: [
963
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
964
+ className: "label",
965
+ children: "Card holder"
966
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
967
+ className: "value",
968
+ children: cardholderName
969
+ })] }),
970
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
971
+ className: "label",
972
+ children: "Expires"
973
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
974
+ className: "value",
975
+ children: expiry
976
+ })] }),
977
+ cvc ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
978
+ className: "label",
979
+ children: "CVC"
980
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
981
+ className: "value",
982
+ children: masked ? "***" : cvc
983
+ })] }) : null
984
+ ]
985
+ })
986
+ ]
987
+ });
988
+ });
989
+ CreditCard.displayName = "CreditCard";
990
+ //#endregion
991
+ //#region src/components/Checkbox/Checkbox.tsx
992
+ var Checkbox = (0, react.forwardRef)(({ id, label, className, ...props }, ref) => {
993
+ const generatedId = (0, react.useId)();
994
+ const checkboxId = id ?? generatedId;
995
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
996
+ className: "pf-checkbox-field",
997
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
998
+ ref,
999
+ id: checkboxId,
1000
+ type: "checkbox",
1001
+ className: cx("pf-checkbox", className),
1002
+ ...props
1003
+ }), label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
1004
+ htmlFor: checkboxId,
1005
+ children: label
1006
+ }) : null]
1007
+ });
1008
+ });
1009
+ Checkbox.displayName = "Checkbox";
869
1010
  //#endregion
870
1011
  //#region src/components/Dropdown/Dropdown.tsx
871
1012
  var Dropdown = (0, react.forwardRef)(({ label = "Actions", items, align = "start", disabled, className, maxVisibleItems, ...props }, ref) => {
@@ -943,7 +1084,6 @@ var Dropdown = (0, react.forwardRef)(({ label = "Actions", items, align = "start
943
1084
  className: "pf-dropdown__trigger",
944
1085
  "aria-haspopup": "menu",
945
1086
  "aria-expanded": isOpen,
946
- "aria-controls": isOpen ? menuId : void 0,
947
1087
  onClick: () => {
948
1088
  disclosure.toggle();
949
1089
  },
@@ -1294,88 +1434,101 @@ var Carousel = (0, react.forwardRef)(function Carousel({ className, slides, init
1294
1434
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1295
1435
  ref,
1296
1436
  className: cx("pf-carousel", className),
1437
+ role: "region",
1438
+ "aria-roledescription": "carousel",
1297
1439
  "aria-label": ariaLabel,
1298
1440
  ...props,
1299
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1300
- className: "pf-carousel__viewport",
1301
- role: "region",
1302
- "aria-roledescription": "carousel",
1303
- "aria-label": slideLabel,
1304
- children: totalSlides === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1305
- className: "pf-carousel__empty",
1306
- role: "status",
1307
- children: "Add at least one slide."
1308
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1309
- className: "pf-carousel__track",
1310
- style: { transform: `translateX(-${resolvedActiveIndex * 100}%)` },
1311
- children: slides.map((slide, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1312
- className: "pf-carousel__slide",
1313
- role: "group",
1314
- "aria-roledescription": "slide",
1315
- "aria-label": `Slide ${index + 1} of ${totalSlides}`,
1316
- "aria-hidden": index !== resolvedActiveIndex,
1317
- children: slide
1318
- }, `slide-${index}`))
1319
- })
1320
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1321
- className: "pf-carousel__controls",
1322
- onKeyDown: (event) => {
1323
- if (event.key === "ArrowLeft") {
1324
- event.preventDefault();
1325
- goToIndex(resolvedActiveIndex - 1);
1326
- } else if (event.key === "ArrowRight") {
1327
- event.preventDefault();
1328
- goToIndex(resolvedActiveIndex + 1);
1329
- }
1330
- },
1331
- children: [
1332
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1333
- type: "button",
1334
- className: "pf-carousel__nav",
1335
- "aria-label": "Previous slide",
1336
- disabled: isPrevDisabled || totalSlides < 2,
1337
- onClick: () => {
1338
- goToIndex(resolvedActiveIndex - 1);
1339
- },
1340
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1341
- name: "square-caret-left",
1342
- "aria-hidden": true
1343
- })
1344
- }),
1345
- showIndicators && totalSlides > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1346
- className: "pf-carousel__indicators",
1347
- "aria-label": "Slide indicators",
1348
- children: slides.map((_, index) => {
1349
- const isActive = index === resolvedActiveIndex;
1350
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1351
- type: "button",
1352
- className: cx("pf-carousel__indicator", isActive && "pf-carousel__indicator--active"),
1353
- "aria-label": `Go to slide ${index + 1}`,
1354
- "aria-current": isActive ? "true" : void 0,
1355
- onClick: () => {
1356
- goToIndex(index);
1357
- }
1358
- }, `indicator-${index}`);
1441
+ children: [
1442
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1443
+ className: "pf-carousel__viewport",
1444
+ children: totalSlides === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1445
+ className: "pf-carousel__empty",
1446
+ role: "status",
1447
+ children: "Add at least one slide."
1448
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1449
+ className: "pf-carousel__track",
1450
+ style: { transform: `translateX(-${resolvedActiveIndex * 100}%)` },
1451
+ children: slides.map((slide, index) => {
1452
+ const isInactive = index !== resolvedActiveIndex;
1453
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1454
+ className: "pf-carousel__slide",
1455
+ role: "group",
1456
+ "aria-roledescription": "slide",
1457
+ "aria-label": `Slide ${index + 1} of ${totalSlides}`,
1458
+ "aria-hidden": isInactive,
1459
+ ...isInactive ? { inert: true } : {},
1460
+ children: slide
1461
+ }, `slide-${index}`);
1359
1462
  })
1360
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1361
- className: "pf-carousel__indicator-spacer",
1362
- "aria-hidden": true
1363
- }),
1364
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1365
- type: "button",
1366
- className: "pf-carousel__nav",
1367
- "aria-label": "Next slide",
1368
- disabled: isNextDisabled || totalSlides < 2,
1369
- onClick: () => {
1463
+ })
1464
+ }),
1465
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1466
+ className: "pf-sr-only",
1467
+ "aria-live": "polite",
1468
+ "aria-atomic": "true",
1469
+ children: totalSlides > 0 ? slideLabel : ""
1470
+ }),
1471
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1472
+ className: "pf-carousel__controls",
1473
+ onKeyDown: (event) => {
1474
+ if (event.key === "ArrowLeft") {
1475
+ event.preventDefault();
1476
+ goToIndex(resolvedActiveIndex - 1);
1477
+ } else if (event.key === "ArrowRight") {
1478
+ event.preventDefault();
1370
1479
  goToIndex(resolvedActiveIndex + 1);
1371
- },
1372
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1373
- name: "square-caret-right",
1480
+ }
1481
+ },
1482
+ children: [
1483
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1484
+ type: "button",
1485
+ className: "pf-carousel__nav",
1486
+ "aria-label": "Previous slide",
1487
+ disabled: isPrevDisabled || totalSlides < 2,
1488
+ onClick: () => {
1489
+ goToIndex(resolvedActiveIndex - 1);
1490
+ },
1491
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1492
+ name: "square-caret-left",
1493
+ "aria-hidden": true
1494
+ })
1495
+ }),
1496
+ showIndicators && totalSlides > 1 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1497
+ className: "pf-carousel__indicators",
1498
+ role: "group",
1499
+ "aria-label": "Slide indicators",
1500
+ children: slides.map((_, index) => {
1501
+ const isActive = index === resolvedActiveIndex;
1502
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1503
+ type: "button",
1504
+ className: cx("pf-carousel__indicator", isActive && "pf-carousel__indicator--active"),
1505
+ "aria-label": `Go to slide ${index + 1}`,
1506
+ "aria-current": isActive ? "true" : void 0,
1507
+ onClick: () => {
1508
+ goToIndex(index);
1509
+ }
1510
+ }, `indicator-${index}`);
1511
+ })
1512
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1513
+ className: "pf-carousel__indicator-spacer",
1374
1514
  "aria-hidden": true
1515
+ }),
1516
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1517
+ type: "button",
1518
+ className: "pf-carousel__nav",
1519
+ "aria-label": "Next slide",
1520
+ disabled: isNextDisabled || totalSlides < 2,
1521
+ onClick: () => {
1522
+ goToIndex(resolvedActiveIndex + 1);
1523
+ },
1524
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1525
+ name: "square-caret-right",
1526
+ "aria-hidden": true
1527
+ })
1375
1528
  })
1376
- })
1377
- ]
1378
- })]
1529
+ ]
1530
+ })
1531
+ ]
1379
1532
  });
1380
1533
  });
1381
1534
  Carousel.displayName = "Carousel";
@@ -1925,14 +2078,15 @@ var HeaderNavigation = (0, react.forwardRef)(function HeaderNavigation({ classNa
1925
2078
  HeaderNavigation.displayName = "HeaderNavigation";
1926
2079
  //#endregion
1927
2080
  //#region src/components/InlineCTA/InlineCTA.tsx
1928
- var InlineCTA = (0, react.forwardRef)(function InlineCTA({ className, heading, description, action, icon, iconName = "circle-question", tone = "default", children, ...props }, ref) {
2081
+ var InlineCTA = (0, react.forwardRef)(function InlineCTA({ className, heading, description, action, icon, iconName = "circle-question", tone = "default", dismissible = false, onDismiss, children, ...props }, ref) {
1929
2082
  const resolvedIcon = icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1930
2083
  name: iconName,
1931
2084
  "aria-hidden": true
1932
2085
  });
2086
+ const { isExiting, startExit } = useExitAnimation({ onExited: onDismiss });
1933
2087
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1934
2088
  ref,
1935
- className: cx("pf-inline-cta", `pf-inline-cta--${tone}`, className),
2089
+ className: cx("pf-inline-cta", `pf-inline-cta--${tone}`, dismissible && "pf-inline-cta--dismissible", isExiting && "pf-inline-cta--exiting", className),
1936
2090
  ...props,
1937
2091
  children: [
1938
2092
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -1957,6 +2111,16 @@ var InlineCTA = (0, react.forwardRef)(function InlineCTA({ className, heading, d
1957
2111
  action ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1958
2112
  className: "pf-inline-cta__action",
1959
2113
  children: action
2114
+ }) : null,
2115
+ dismissible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2116
+ type: "button",
2117
+ className: "pf-inline-cta__dismiss",
2118
+ "aria-label": "Dismiss",
2119
+ onClick: startExit,
2120
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
2121
+ name: "circle-xmark",
2122
+ "aria-hidden": true
2123
+ })
1960
2124
  }) : null
1961
2125
  ]
1962
2126
  });
@@ -1968,8 +2132,7 @@ var GaugeChart = (0, react.forwardRef)(function GaugeChart({ className, value, m
1968
2132
  const progress = max > 0 ? Math.min(Math.max(value, 0), max) / max : 0;
1969
2133
  const radius = (size - strokeWidth) / 2;
1970
2134
  const circumference = 2 * Math.PI * radius;
1971
- const filled = progress * circumference;
1972
- const gap = circumference - filled;
2135
+ const offset = circumference - progress * circumference;
1973
2136
  const center = size / 2;
1974
2137
  const pct = Math.round(progress * 100);
1975
2138
  const defaultLabel = `${pct}%`;
@@ -2009,10 +2172,12 @@ var GaugeChart = (0, react.forwardRef)(function GaugeChart({ className, value, m
2009
2172
  stroke: colorVar,
2010
2173
  strokeWidth,
2011
2174
  strokeLinecap: "round",
2012
- strokeDasharray: `${filled} ${gap}`,
2175
+ strokeDasharray: circumference,
2013
2176
  style: {
2014
2177
  transform: "rotate(-90deg)",
2015
- transformOrigin: `${center}px ${center}px`
2178
+ transformOrigin: `${center}px ${center}px`,
2179
+ "--pf-gauge-circumference": circumference,
2180
+ "--pf-gauge-offset": offset
2016
2181
  },
2017
2182
  className: "pf-gauge__fill"
2018
2183
  })]
@@ -2031,6 +2196,161 @@ var GaugeChart = (0, react.forwardRef)(function GaugeChart({ className, value, m
2031
2196
  });
2032
2197
  GaugeChart.displayName = "GaugeChart";
2033
2198
  //#endregion
2199
+ //#region src/components/Heatmap/Heatmap.tsx
2200
+ var MONTHS = [
2201
+ "Jan",
2202
+ "Feb",
2203
+ "Mar",
2204
+ "Apr",
2205
+ "May",
2206
+ "Jun",
2207
+ "Jul",
2208
+ "Aug",
2209
+ "Sep",
2210
+ "Oct",
2211
+ "Nov",
2212
+ "Dec"
2213
+ ];
2214
+ var WEEKDAYS = [
2215
+ "Sun",
2216
+ "Mon",
2217
+ "Tue",
2218
+ "Wed",
2219
+ "Thu",
2220
+ "Fri",
2221
+ "Sat"
2222
+ ];
2223
+ function parseISO(s) {
2224
+ const [y, m, d] = s.split("-").map(Number);
2225
+ return new Date(y, m - 1, d);
2226
+ }
2227
+ function toISO(d) {
2228
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
2229
+ }
2230
+ function addDays(d, n) {
2231
+ const r = new Date(d);
2232
+ r.setDate(r.getDate() + n);
2233
+ return r;
2234
+ }
2235
+ var Heatmap = (0, react.forwardRef)(function Heatmap({ className, data, startDate, endDate, levels = 5, weekStartsOn = 0, cellSize = 12, cellGap = 3, showWeekdayLabels = true, showMonthLabels = true, valueFormatter, label, emptyLabel = "No data", style, ...props }, ref) {
2236
+ const sortedDates = data.map((d) => d.date).sort();
2237
+ if (!Boolean(startDate || endDate || data.length)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2238
+ ref,
2239
+ className: cx("pf-heatmap", className),
2240
+ ...props,
2241
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2242
+ className: "pf-heatmap__empty",
2243
+ children: emptyLabel
2244
+ })
2245
+ });
2246
+ const valueByDate = new Map(data.map((d) => [d.date, d.value]));
2247
+ const maxValue = data.reduce((max, d) => Math.max(max, d.value), 0);
2248
+ const total = data.reduce((sum, d) => sum + d.value, 0);
2249
+ const levelCount = Math.max(2, levels);
2250
+ const start = parseISO(startDate ?? sortedDates[0]);
2251
+ const end = parseISO(endDate ?? sortedDates[sortedDates.length - 1]);
2252
+ const gridStart = addDays(start, -((start.getDay() - weekStartsOn + 7) % 7));
2253
+ const weeks = [];
2254
+ let cursor = gridStart;
2255
+ while (cursor <= end) {
2256
+ const week = [];
2257
+ for (let i = 0; i < 7; i++) {
2258
+ week.push({
2259
+ iso: toISO(cursor),
2260
+ date: new Date(cursor),
2261
+ inRange: cursor >= start && cursor <= end
2262
+ });
2263
+ cursor = addDays(cursor, 1);
2264
+ }
2265
+ weeks.push(week);
2266
+ }
2267
+ function levelFor(value) {
2268
+ if (value <= 0 || maxValue <= 0) return 0;
2269
+ return Math.min(levelCount - 1, Math.max(1, Math.ceil(value / maxValue * (levelCount - 1))));
2270
+ }
2271
+ function cellColor(level) {
2272
+ if (level === 0) return "var(--pf-heatmap-empty)";
2273
+ return `color-mix(in srgb, var(--pf-heatmap-color) ${Math.round(level / (levelCount - 1) * 100)}%, var(--pf-heatmap-empty))`;
2274
+ }
2275
+ const monthLabels = [];
2276
+ let lastMonth = -1;
2277
+ weeks.forEach((week, col) => {
2278
+ const firstInRange = week.find((c) => c.inRange);
2279
+ if (!firstInRange) return;
2280
+ const month = firstInRange.date.getMonth();
2281
+ if (month !== lastMonth) {
2282
+ monthLabels.push({
2283
+ col: col + 1,
2284
+ label: MONTHS[month]
2285
+ });
2286
+ lastMonth = month;
2287
+ }
2288
+ });
2289
+ const styleVars = {
2290
+ "--pf-heatmap-cell-size": `${cellSize}px`,
2291
+ "--pf-heatmap-cell-gap": `${cellGap}px`,
2292
+ ...style
2293
+ };
2294
+ const ariaLabel = label ?? `Activity heatmap from ${toISO(start)} to ${toISO(end)}, ${total} total`;
2295
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2296
+ ref,
2297
+ className: cx("pf-heatmap", className),
2298
+ style: styleVars,
2299
+ role: "img",
2300
+ "aria-label": ariaLabel,
2301
+ ...props,
2302
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2303
+ className: "pf-heatmap__body",
2304
+ children: [showWeekdayLabels ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2305
+ className: "pf-heatmap__weekdays",
2306
+ children: [showMonthLabels ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2307
+ className: "pf-heatmap__weekday-spacer",
2308
+ "aria-hidden": "true"
2309
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2310
+ className: "pf-heatmap__weekday-grid",
2311
+ children: Array.from({ length: 7 }, (_, i) => {
2312
+ const dow = (weekStartsOn + i) % 7;
2313
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2314
+ className: "pf-heatmap__weekday",
2315
+ children: i % 2 === 1 ? WEEKDAYS[dow] : ""
2316
+ }, i);
2317
+ })
2318
+ })]
2319
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2320
+ className: "pf-heatmap__main",
2321
+ children: [showMonthLabels ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2322
+ className: "pf-heatmap__months",
2323
+ style: { gridTemplateColumns: `repeat(${weeks.length}, var(--pf-heatmap-cell-size))` },
2324
+ "aria-hidden": "true",
2325
+ children: monthLabels.map((m) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2326
+ className: "pf-heatmap__month",
2327
+ style: { gridColumnStart: m.col },
2328
+ children: m.label
2329
+ }, `${m.label}-${m.col}`))
2330
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2331
+ className: "pf-heatmap__grid",
2332
+ children: weeks.flatMap((week, wi) => week.map((cell, di) => {
2333
+ if (!cell.inRange) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "pf-heatmap__cell pf-heatmap__cell--empty" }, `${wi}-${di}`);
2334
+ const value = valueByDate.get(cell.iso) ?? 0;
2335
+ const level = levelFor(value);
2336
+ const title = valueFormatter ? valueFormatter(value, cell.iso) : `${cell.iso}: ${value}`;
2337
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2338
+ className: "pf-heatmap__cell",
2339
+ style: {
2340
+ background: cellColor(level),
2341
+ animationDelay: `${wi * 8}ms`
2342
+ },
2343
+ title,
2344
+ "data-level": level
2345
+ }, `${wi}-${di}`);
2346
+ }))
2347
+ })]
2348
+ })]
2349
+ })
2350
+ });
2351
+ });
2352
+ Heatmap.displayName = "Heatmap";
2353
+ //#endregion
2034
2354
  //#region src/components/LineBarCharts/LineBarChart.tsx
2035
2355
  var CHART_COLORS = [
2036
2356
  "var(--pf-chart-color-1)",
@@ -2447,25 +2767,26 @@ var Modal = (0, react.forwardRef)(function Modal({ className, open, onOpenChange
2447
2767
  const titleId = (0, react.useId)();
2448
2768
  const descriptionId = (0, react.useId)();
2449
2769
  const dialogRef = (0, react.useRef)(null);
2770
+ const { isMounted, isExiting } = usePresence(open);
2450
2771
  (0, react.useImperativeHandle)(ref, () => dialogRef.current, []);
2451
2772
  (0, react.useEffect)(() => {
2452
- if (!open || typeof document === "undefined") return;
2773
+ if (!isMounted || typeof document === "undefined") return;
2453
2774
  const originalOverflow = document.body.style.overflow;
2454
2775
  document.body.style.overflow = "hidden";
2455
2776
  return () => {
2456
2777
  document.body.style.overflow = originalOverflow;
2457
2778
  };
2458
- }, [open]);
2779
+ }, [isMounted]);
2459
2780
  useFocusTrap({
2460
2781
  containerRef: dialogRef,
2461
2782
  enabled: open,
2462
2783
  onEscape: () => onOpenChange?.(false)
2463
2784
  });
2464
- if (!open || typeof document === "undefined") return null;
2785
+ if (!isMounted || typeof document === "undefined") return null;
2465
2786
  return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2466
2787
  className: "pf-modal__portal",
2467
2788
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2468
- className: "pf-modal__overlay",
2789
+ className: cx("pf-modal__overlay", isExiting && "pf-modal__overlay--exiting"),
2469
2790
  onClick: () => {
2470
2791
  if (closeOnOverlayClick) onOpenChange?.(false);
2471
2792
  }
@@ -2473,7 +2794,7 @@ var Modal = (0, react.forwardRef)(function Modal({ className, open, onOpenChange
2473
2794
  className: "pf-modal__viewport",
2474
2795
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2475
2796
  ref: dialogRef,
2476
- className: cx("pf-modal", `pf-modal--${size}`, className),
2797
+ className: cx("pf-modal", `pf-modal--${size}`, isExiting && "pf-modal--exiting", className),
2477
2798
  role: "dialog",
2478
2799
  "aria-modal": "true",
2479
2800
  "aria-labelledby": title ? titleId : void 0,
@@ -2624,7 +2945,6 @@ var MultiSelect = (0, react.forwardRef)(({ id, options, value, defaultValue, onV
2624
2945
  "aria-haspopup": "listbox",
2625
2946
  "aria-expanded": isOpen,
2626
2947
  "aria-required": required || void 0,
2627
- "aria-controls": isOpen ? listboxId : void 0,
2628
2948
  "aria-describedby": describedBy,
2629
2949
  onClick: () => {
2630
2950
  disclosure.toggle();
@@ -2717,9 +3037,10 @@ var Notification = (0, react.forwardRef)(({ className, variant = "info", heading
2717
3037
  "aria-hidden": true
2718
3038
  });
2719
3039
  const body = children ?? description;
3040
+ const { isExiting, startExit } = useExitAnimation({ onExited: onDismiss });
2720
3041
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2721
3042
  ref,
2722
- className: cx("pf-notification", `pf-notification--${variant}`, className),
3043
+ className: cx("pf-notification", `pf-notification--${variant}`, isExiting && "pf-notification--exiting", className),
2723
3044
  role: "status",
2724
3045
  ...props,
2725
3046
  children: [
@@ -2749,7 +3070,7 @@ var Notification = (0, react.forwardRef)(({ className, variant = "info", heading
2749
3070
  type: "button",
2750
3071
  className: "pf-notification__dismiss",
2751
3072
  "aria-label": "Dismiss notification",
2752
- onClick: () => onDismiss?.(),
3073
+ onClick: startExit,
2753
3074
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
2754
3075
  name: "circle-xmark",
2755
3076
  "aria-hidden": true
@@ -2937,7 +3258,7 @@ var PieChart = (0, react.forwardRef)(function PieChart({ className, data, size =
2937
3258
  style: {
2938
3259
  width: chartSize,
2939
3260
  height: chartSize,
2940
- backgroundImage: conicGradient
3261
+ "--pf-pie-gradient": conicGradient
2941
3262
  },
2942
3263
  role: "img",
2943
3264
  "aria-label": "Pie chart",
@@ -3035,7 +3356,10 @@ var ProgressCircle = (0, react.forwardRef)(function ProgressCircle({ value, max
3035
3356
  r: radius,
3036
3357
  strokeWidth,
3037
3358
  strokeDasharray: circumference,
3038
- strokeDashoffset: dashOffset
3359
+ style: {
3360
+ "--pf-progress-dashoffset": dashOffset,
3361
+ "--pf-progress-circ": circumference
3362
+ }
3039
3363
  })]
3040
3364
  }), showValue ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3041
3365
  className: "pf-progress-circle__value",
@@ -3151,21 +3475,27 @@ var RadarChart = (0, react.forwardRef)(function RadarChart({ className, data, si
3151
3475
  x2: axis.end.x,
3152
3476
  y2: axis.end.y
3153
3477
  }, `axis-${index}`)) : null,
3154
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
3155
- className: "pf-radar-chart__area",
3156
- points: valuePolygon,
3478
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
3479
+ className: "pf-radar-chart__value",
3157
3480
  style: {
3158
- fill: fillColor,
3159
- stroke: strokeColor
3160
- }
3481
+ transformBox: "view-box",
3482
+ transformOrigin: `${center}px ${center}px`
3483
+ },
3484
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
3485
+ className: "pf-radar-chart__area",
3486
+ points: valuePolygon,
3487
+ style: {
3488
+ fill: fillColor,
3489
+ stroke: strokeColor
3490
+ }
3491
+ }), valuePoints.map((point, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
3492
+ className: "pf-radar-chart__point",
3493
+ cx: point.x,
3494
+ cy: point.y,
3495
+ r: 3,
3496
+ style: { fill: strokeColor }
3497
+ }, `point-${index}`))]
3161
3498
  }),
3162
- valuePoints.map((point, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
3163
- className: "pf-radar-chart__point",
3164
- cx: point.x,
3165
- cy: point.y,
3166
- r: 3,
3167
- style: { fill: strokeColor }
3168
- }, `point-${index}`)),
3169
3499
  axes.map((axis, index) => {
3170
3500
  const labelPoint = polarToCartesian(center, center, outerRadius + 18, axis.angle);
3171
3501
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
@@ -3677,7 +4007,7 @@ function normalizePoints(data, width, height, padding) {
3677
4007
  return [padding + i / (data.length - 1) * innerW, padding + (1 - (value - min) / range) * innerH];
3678
4008
  });
3679
4009
  }
3680
- var Sparkline = (0, react.forwardRef)(function Sparkline({ className, data = [], width = 120, height = 36, variant = "line", strokeWidth = 1.5, color, endDot = false, label, style, ...props }, ref) {
4010
+ var Sparkline = (0, react.forwardRef)(function Sparkline({ className, data = [], width = 120, height = 36, variant = "line", strokeWidth = 1.5, color, endDot = false, animate = false, label, style, ...props }, ref) {
3681
4011
  const padding = strokeWidth + 2;
3682
4012
  const points = (0, react.useMemo)(() => normalizePoints(data, width, height, padding), [
3683
4013
  data,
@@ -3711,7 +4041,7 @@ var Sparkline = (0, react.forwardRef)(function Sparkline({ className, data = [],
3711
4041
  width,
3712
4042
  height,
3713
4043
  viewBox: `0 0 ${width} ${height}`,
3714
- className: cx("pf-sparkline", `pf-sparkline--${variant}`, className),
4044
+ className: cx("pf-sparkline", `pf-sparkline--${variant}`, animate && "pf-sparkline--animated", className),
3715
4045
  "aria-label": label,
3716
4046
  role: label ? "img" : "presentation",
3717
4047
  style: {
@@ -3732,6 +4062,7 @@ var Sparkline = (0, react.forwardRef)(function Sparkline({ className, data = [],
3732
4062
  strokeWidth,
3733
4063
  strokeLinecap: "round",
3734
4064
  strokeLinejoin: "round",
4065
+ pathLength: animate ? 1 : void 0,
3735
4066
  className: "pf-sparkline__line"
3736
4067
  }),
3737
4068
  endDot && lastPoint && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
@@ -4052,7 +4383,6 @@ var Select = (0, react.forwardRef)(({ id, options, value, defaultValue, onValueC
4052
4383
  disabled,
4053
4384
  "aria-haspopup": "listbox",
4054
4385
  "aria-expanded": isOpen,
4055
- "aria-controls": isOpen ? listboxId : void 0,
4056
4386
  "aria-required": required || void 0,
4057
4387
  "aria-describedby": describedBy,
4058
4388
  onClick: () => {
@@ -4313,6 +4643,7 @@ function Table({ className, columns, rows, caption, dense = false, striped = fal
4313
4643
  Table.displayName = "Table";
4314
4644
  //#endregion
4315
4645
  //#region src/components/Tabs/Tabs.tsx
4646
+ var useIsomorphicLayoutEffect = typeof document !== "undefined" ? react.useLayoutEffect : react.useEffect;
4316
4647
  function getFirstEnabledValue(items) {
4317
4648
  return items.find((item) => !item.disabled)?.value;
4318
4649
  }
@@ -4323,6 +4654,39 @@ var Tabs = (0, react.forwardRef)(function Tabs({ className, items, value, defaul
4323
4654
  const selectedValue = isControlled ? value : internalValue;
4324
4655
  const selectedItem = (0, react.useMemo)(() => items.find((item) => item.value === selectedValue && !item.disabled) ?? items.find((item) => !item.disabled), [items, selectedValue]);
4325
4656
  const buttonRefs = (0, react.useRef)([]);
4657
+ const listRef = (0, react.useRef)(null);
4658
+ const [indicator, setIndicator] = (0, react.useState)(null);
4659
+ useIsomorphicLayoutEffect(() => {
4660
+ const list = listRef.current;
4661
+ const activeIndex = items.findIndex((item) => item.value === selectedItem?.value);
4662
+ const activeButton = buttonRefs.current[activeIndex];
4663
+ if (!list || !activeButton) {
4664
+ setIndicator(null);
4665
+ return;
4666
+ }
4667
+ const measure = () => {
4668
+ const listRect = list.getBoundingClientRect();
4669
+ const tabRect = activeButton.getBoundingClientRect();
4670
+ setIndicator({
4671
+ left: tabRect.left - listRect.left + list.scrollLeft,
4672
+ width: tabRect.width,
4673
+ top: tabRect.top - listRect.top,
4674
+ height: tabRect.height
4675
+ });
4676
+ };
4677
+ measure();
4678
+ if (typeof ResizeObserver === "undefined") return;
4679
+ const observer = new ResizeObserver(measure);
4680
+ observer.observe(list);
4681
+ observer.observe(activeButton);
4682
+ return () => observer.disconnect();
4683
+ }, [
4684
+ items,
4685
+ selectedItem?.value,
4686
+ variant,
4687
+ size,
4688
+ fullWidth
4689
+ ]);
4326
4690
  const setSelectedValue = (nextValue) => {
4327
4691
  if (!isControlled) setInternalValue(nextValue);
4328
4692
  onValueChange?.(nextValue);
@@ -4347,11 +4711,24 @@ var Tabs = (0, react.forwardRef)(function Tabs({ className, items, value, defaul
4347
4711
  ref,
4348
4712
  className: cx("pf-tabs", className),
4349
4713
  ...props,
4350
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4714
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4715
+ ref: listRef,
4351
4716
  className: cx("pf-tabs__list", `pf-tabs__list--${variant}`, `pf-tabs__list--${size}`, fullWidth && "pf-tabs__list--full-width"),
4352
4717
  role: "tablist",
4353
4718
  "aria-orientation": "horizontal",
4354
- children: items.map((item, index) => {
4719
+ children: [indicator ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4720
+ "aria-hidden": true,
4721
+ className: cx("pf-tabs__indicator", `pf-tabs__indicator--${variant}`),
4722
+ style: variant === "pills" ? {
4723
+ left: indicator.left,
4724
+ width: indicator.width,
4725
+ top: indicator.top,
4726
+ height: indicator.height
4727
+ } : {
4728
+ left: indicator.left,
4729
+ width: indicator.width
4730
+ }
4731
+ }) : null, items.map((item, index) => {
4355
4732
  const isSelected = item.value === selectedItem?.value;
4356
4733
  const tabId = `${baseId}-tab-${item.value}`;
4357
4734
  const panelId = `${baseId}-panel-${item.value}`;
@@ -4390,7 +4767,7 @@ var Tabs = (0, react.forwardRef)(function Tabs({ className, items, value, defaul
4390
4767
  },
4391
4768
  children: item.label
4392
4769
  }, item.value);
4393
- })
4770
+ })]
4394
4771
  }), selectedItem ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4395
4772
  id: `${baseId}-panel-${selectedItem.value}`,
4396
4773
  className: "pf-tabs__panel",
@@ -4519,6 +4896,7 @@ var Tooltip = (0, react.forwardRef)(function Tooltip({ content, children, open,
4519
4896
  const [resolvedPlacement, setResolvedPlacement] = (0, react.useState)(placement);
4520
4897
  const isControlled = open !== void 0;
4521
4898
  const isVisible = !disabled && (isControlled ? open : isOpen);
4899
+ const { isMounted, isExiting } = usePresence(Boolean(isVisible), 160);
4522
4900
  const clearShowTimer = () => {
4523
4901
  if (showTimerRef.current !== void 0) {
4524
4902
  window.clearTimeout(showTimerRef.current);
@@ -4537,8 +4915,6 @@ var Tooltip = (0, react.forwardRef)(function Tooltip({ content, children, open,
4537
4915
  clearShowTimer();
4538
4916
  if (isControlled) return;
4539
4917
  setIsOpen(false);
4540
- setStyle({ visibility: "hidden" });
4541
- setResolvedPlacement(placement);
4542
4918
  };
4543
4919
  (0, react.useEffect)(() => {
4544
4920
  return () => {
@@ -4573,11 +4949,11 @@ var Tooltip = (0, react.forwardRef)(function Tooltip({ content, children, open,
4573
4949
  },
4574
4950
  "aria-describedby": isVisible ? tooltipId : void 0,
4575
4951
  children: children ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {})
4576
- }), isVisible && typeof document !== "undefined" ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4952
+ }), isMounted && typeof document !== "undefined" ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4577
4953
  id: tooltipId,
4578
4954
  ref: tooltipRef,
4579
4955
  role: "tooltip",
4580
- className: cx("pf-tooltip", `pf-tooltip--${resolvedPlacement}`, className),
4956
+ className: cx("pf-tooltip", `pf-tooltip--${resolvedPlacement}`, isExiting && "pf-tooltip--exiting", className),
4581
4957
  style,
4582
4958
  children: content
4583
4959
  }), document.body) : null] });
@@ -4855,6 +5231,7 @@ var VideoPlayer = (0, react.forwardRef)(({ id, label, description, error, aspect
4855
5231
  });
4856
5232
  VideoPlayer.displayName = "VideoPlayer";
4857
5233
  //#endregion
5234
+ exports.Accordion = Accordion;
4858
5235
  exports.Alert = Alert;
4859
5236
  exports.AreaChart = AreaChart;
4860
5237
  exports.Avatar = Avatar;
@@ -4880,6 +5257,7 @@ exports.EmptyState = EmptyState;
4880
5257
  exports.FileUploader = FileUploader;
4881
5258
  exports.GaugeChart = GaugeChart;
4882
5259
  exports.HeaderNavigation = HeaderNavigation;
5260
+ exports.Heatmap = Heatmap;
4883
5261
  exports.Icon = Icon;
4884
5262
  exports.InlineCTA = InlineCTA;
4885
5263
  exports.Input = Input;
@@ -4935,6 +5313,8 @@ exports.useAnchoredPosition = useAnchoredPosition;
4935
5313
  exports.useComposedRefs = useComposedRefs;
4936
5314
  exports.useControllableState = useControllableState;
4937
5315
  exports.useDisclosure = useDisclosure;
5316
+ exports.useExitAnimation = useExitAnimation;
4938
5317
  exports.useFocusTrap = useFocusTrap;
4939
5318
  exports.useListNavigation = useListNavigation;
4940
5319
  exports.useOutsideInteraction = useOutsideInteraction;
5320
+ exports.usePresence = usePresence;