@servicetitan/anvil2 1.45.2 → 1.46.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 (109) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/{Calendar-BK861SAW.js → Calendar-BQ5F2ENO.js} +2 -2
  3. package/dist/{Calendar-BK861SAW.js.map → Calendar-BQ5F2ENO.js.map} +1 -1
  4. package/dist/Calendar.js +1 -1
  5. package/dist/{Checkbox-ZphVb1l0.js → Checkbox-DDrmVC-u.js} +2 -2
  6. package/dist/{Checkbox-ZphVb1l0.js.map → Checkbox-DDrmVC-u.js.map} +1 -1
  7. package/dist/{Checkbox-CYNjFdtO.js → Checkbox-Dl4KTwEJ.js} +2 -2
  8. package/dist/{Checkbox-CYNjFdtO.js.map → Checkbox-Dl4KTwEJ.js.map} +1 -1
  9. package/dist/Checkbox.js +2 -2
  10. package/dist/{useInfiniteCombobox-BaYWUxjg.js → Combobox-B9nesJuc.js} +18 -185
  11. package/dist/Combobox-B9nesJuc.js.map +1 -0
  12. package/dist/Combobox.js +2 -1
  13. package/dist/Combobox.js.map +1 -1
  14. package/dist/{DateField-DnasO2rB.js → DateField-DXxPsRtf.js} +2 -2
  15. package/dist/{DateField-DnasO2rB.js.map → DateField-DXxPsRtf.js.map} +1 -1
  16. package/dist/DateField.js +1 -1
  17. package/dist/{DateFieldRange-Ba-8T-Nz.js → DateFieldRange-Xauviu1w.js} +6 -6
  18. package/dist/DateFieldRange-Xauviu1w.js.map +1 -0
  19. package/dist/DateFieldRange.js +1 -1
  20. package/dist/{DateFieldSingle-BBu5Hi9c.js → DateFieldSingle-yLnwpVzd.js} +4 -4
  21. package/dist/{DateFieldSingle-BBu5Hi9c.js.map → DateFieldSingle-yLnwpVzd.js.map} +1 -1
  22. package/dist/DateFieldSingle.js +1 -1
  23. package/dist/Dnd.js +1 -1
  24. package/dist/DndSort.js +1 -1
  25. package/dist/{ListView-DEAMQopB.js → ListView-pb3rIcze.js} +2 -2
  26. package/dist/{ListView-DEAMQopB.js.map → ListView-pb3rIcze.js.map} +1 -1
  27. package/dist/ListView.js +1 -1
  28. package/dist/{Menu-C8we5CHP.js → Menu-DEVZz9xZ.js} +8 -3
  29. package/dist/Menu-DEVZz9xZ.js.map +1 -0
  30. package/dist/Menu.js +1 -1
  31. package/dist/{Page-cKXkjMmd.js → Page-BMDkbDcU.js} +2 -2
  32. package/dist/{Page-cKXkjMmd.js.map → Page-BMDkbDcU.js.map} +1 -1
  33. package/dist/Page.js +1 -1
  34. package/dist/{Pagination-ta8a2cJN.js → Pagination-BJsCppgW.js} +2 -2
  35. package/dist/{Pagination-ta8a2cJN.js.map → Pagination-BJsCppgW.js.map} +1 -1
  36. package/dist/Pagination.js +1 -1
  37. package/dist/{SearchField-BKXkoWPs.js → SearchField-Bb0uObwG.js} +2 -2
  38. package/dist/{SearchField-BKXkoWPs.js.map → SearchField-Bb0uObwG.js.map} +1 -1
  39. package/dist/SearchField.js +1 -1
  40. package/dist/{SelectCard-BWh8Yp7T.js → SelectCard-BTYZg9TG.js} +2 -2
  41. package/dist/{SelectCard-BWh8Yp7T.js.map → SelectCard-BTYZg9TG.js.map} +1 -1
  42. package/dist/SelectCard.js +1 -1
  43. package/dist/Toolbar-D4zuUFhb.js +2077 -0
  44. package/dist/Toolbar-D4zuUFhb.js.map +1 -0
  45. package/dist/Toolbar.css +139 -28
  46. package/dist/Toolbar.d.ts +3 -3
  47. package/dist/Toolbar.js +1 -1
  48. package/dist/assets/icons/st/gnav_legacy_search_filled.svg +1 -1
  49. package/dist/assets/icons/st/gnav_legacy_search_outline.svg +1 -1
  50. package/dist/beta/components/Toolbar/Filters/FilterButton.d.ts +30 -0
  51. package/dist/beta/components/Toolbar/Filters/FilterDateRange.d.ts +37 -0
  52. package/dist/beta/components/Toolbar/Filters/FilterDateSingle.d.ts +30 -0
  53. package/dist/beta/components/Toolbar/Filters/FilterDrawer.d.ts +15 -0
  54. package/dist/beta/components/Toolbar/Filters/FilterGroup.d.ts +25 -0
  55. package/dist/beta/components/Toolbar/Filters/FilterItemWrapper.d.ts +24 -0
  56. package/dist/beta/components/Toolbar/Filters/FilterSelect.d.ts +29 -0
  57. package/dist/beta/components/Toolbar/Filters/FilterToggleButton.d.ts +24 -0
  58. package/dist/beta/components/Toolbar/Filters/internal/FilterGroupContext.d.ts +40 -0
  59. package/dist/beta/components/Toolbar/Filters/internal/types.d.ts +130 -0
  60. package/dist/beta/components/Toolbar/Filters/internal/utils/filter-state.d.ts +40 -0
  61. package/dist/beta/components/Toolbar/Filters/internal/utils/test.d.ts +57 -0
  62. package/dist/beta/components/Toolbar/Toolbar.d.ts +302 -0
  63. package/dist/beta/components/Toolbar/ToolbarButton.d.ts +41 -0
  64. package/dist/beta/components/Toolbar/ToolbarButtonLink.d.ts +43 -0
  65. package/dist/beta/components/Toolbar/ToolbarButtonToggle.d.ts +42 -0
  66. package/dist/beta/components/Toolbar/ToolbarControlGroup.d.ts +20 -0
  67. package/dist/beta/components/Toolbar/ToolbarSearchField.d.ts +20 -0
  68. package/dist/beta/components/Toolbar/ToolbarSelect.d.ts +108 -0
  69. package/dist/beta/components/Toolbar/index.d.ts +9 -0
  70. package/dist/beta/components/Toolbar/internal/ToolbarItemOverflowContext.d.ts +19 -0
  71. package/dist/beta/components/Toolbar/internal/ToolbarItemWrapper.d.ts +40 -0
  72. package/dist/beta/components/Toolbar/internal/ToolbarOverflowContext.d.ts +35 -0
  73. package/dist/beta/components/Toolbar/internal/ToolbarOverflowMenu.d.ts +29 -0
  74. package/dist/beta/components/Toolbar/internal/utils/accessibility.d.ts +26 -0
  75. package/dist/beta/components/Toolbar/internal/utils/test.d.ts +29 -0
  76. package/dist/beta/components/Toolbar/types.d.ts +50 -0
  77. package/dist/beta/components/index.d.ts +1 -0
  78. package/dist/beta/index.d.ts +1 -0
  79. package/dist/beta.d.ts +2 -0
  80. package/dist/beta.js +2 -0
  81. package/dist/beta.js.map +1 -0
  82. package/dist/components/Combobox/ComboboxTypes.d.ts +8 -0
  83. package/dist/components/DateFieldRange/internal/DateFieldRangeCalendar.d.ts +1 -1
  84. package/dist/components/Dialog/index.d.ts +1 -1
  85. package/dist/{indeterminate_check_box-Bg24oeHy.js → indeterminate_check_box-RY9zr3xS.js} +17 -17
  86. package/dist/{indeterminate_check_box-Bg24oeHy.js.map → indeterminate_check_box-RY9zr3xS.js.map} +1 -1
  87. package/dist/indeterminate_check_box.css +72 -66
  88. package/dist/{index-CqdP5W00.js → index-V5Ez2gq_.js} +2 -2
  89. package/dist/{index-CqdP5W00.js.map → index-V5Ez2gq_.js.map} +1 -1
  90. package/dist/index.css +125 -26
  91. package/dist/index.js +759 -27
  92. package/dist/index.js.map +1 -1
  93. package/dist/index2.css +88 -105
  94. package/dist/internal/hooks/index.d.ts +1 -0
  95. package/dist/internal/hooks/useContainerQuery/index.d.ts +1 -0
  96. package/dist/internal/hooks/useContainerQuery/useContainerQuery.d.ts +46 -0
  97. package/dist/{useDateFieldOrchestration-DPLftOxu.js → useDateFieldOrchestration-BNJCsRkS.js} +2 -2
  98. package/dist/{useDateFieldOrchestration-DPLftOxu.js.map → useDateFieldOrchestration-BNJCsRkS.js.map} +1 -1
  99. package/dist/useInfiniteCombobox-WcRgC9p6.js +179 -0
  100. package/dist/useInfiniteCombobox-WcRgC9p6.js.map +1 -0
  101. package/dist/useIntersectionObserver-BEmMDO3P.js +70 -0
  102. package/dist/useIntersectionObserver-BEmMDO3P.js.map +1 -0
  103. package/package.json +2 -1
  104. package/dist/DateFieldRange-Ba-8T-Nz.js.map +0 -1
  105. package/dist/Menu-C8we5CHP.js.map +0 -1
  106. package/dist/Toolbar-DK7tXy_W.js +0 -807
  107. package/dist/Toolbar-DK7tXy_W.js.map +0 -1
  108. package/dist/useInfiniteCombobox-BaYWUxjg.js.map +0 -1
  109. /package/dist/{useInfiniteCombobox.css → Combobox.css} +0 -0
@@ -0,0 +1,2077 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { useState, useEffect, useContext, createContext, useId, useRef, useCallback, forwardRef, useMemo } from 'react';
4
+ import { B as Button } from './Button-BxFXQ0-n.js';
5
+ import { T as Tooltip } from './Tooltip-BI3Xs75X.js';
6
+ import { g as getKeyboardFocusableElements } from './getKeyboardFocusableElements-QqcABz0D.js';
7
+ import { c as cx } from './index-tZvMCc77.js';
8
+ import { u as useIntersectionObserver } from './useIntersectionObserver-BEmMDO3P.js';
9
+ import { useTrackingId } from './useTrackingId.js';
10
+ import { B as ButtonToggle } from './ButtonToggle-pSwg7NvT.js';
11
+ import { B as ButtonLink } from './ButtonLink-CXv65WVV.js';
12
+ import { S as SvgArrowDropDown } from './arrow_drop_down-ChAdBDux.js';
13
+ import { L as Listbox } from './Listbox-CUhMbFm2.js';
14
+ import { P as Popover } from './Popover-r26xMIfm.js';
15
+ import { F as Flex } from './Flex-BdQMekvA.js';
16
+ import { S as SvgMoreHoriz } from './more_horiz-DJgdQiy0.js';
17
+ import { S as SvgMoreVert } from './more_vert-C_lJSyxt.js';
18
+ import { I as Icon } from './Icon-D8SPKeO4.js';
19
+ import { S as SvgClose } from './close-DZj38AEh.js';
20
+ import { S as SvgKeyboardArrowDown } from './keyboard_arrow_down-C8WQ38p1.js';
21
+ import { S as SvgEvent } from './event-BEJFimi3.js';
22
+ import { D as DateTime } from './Calendar-BQ5F2ENO.js';
23
+ import { C as Chip } from './Chip-Bz-vlQ4D.js';
24
+ import { L as ListView } from './ListView-pb3rIcze.js';
25
+ import { S as SearchField, a as SvgSearch } from './SearchField-Bb0uObwG.js';
26
+ import { u as useDateFieldSingleConversion, a as useDateFieldSingleState, M as MaskedDateInput, b as DateFieldSingleCalendar, D as DateFieldSingle } from './DateFieldSingle-yLnwpVzd.js';
27
+ import { u as useDateFieldRangeConversion, a as useDateFieldRangeState, M as MaskedDateRangeInput, b as DateFieldRangeCalendar, D as DateFieldRange } from './DateFieldRange-Xauviu1w.js';
28
+ import { C as Checkbox } from './Checkbox-DDrmVC-u.js';
29
+ import { R as Radio } from './Radio-C89VCMXd.js';
30
+ import { C as Combobox } from './Combobox-B9nesJuc.js';
31
+ import { D as Drawer } from './Drawer-CM4ZbAro.js';
32
+ import { B as BreakpointSm, a as BreakpointMd, b as BreakpointLg, c as BreakpointXl, d as BreakpointXxl } from './primitive-BoyEHaOo.js';
33
+ import { u as useMergeRefs } from './useMergeRefs-Bde85AWI.js';
34
+ import { u as useLayoutPropsUtil } from './useLayoutPropsUtil-DjD5IMh0.js';
35
+
36
+ import './Toolbar.css';function containerBreakpoint(containerWidth, name, min, max) {
37
+ if ((min == null || containerWidth >= min) && (max == null || containerWidth < max)) {
38
+ return {
39
+ name,
40
+ min,
41
+ max,
42
+ containerWidth,
43
+ containerHeight: 0
44
+ // Will be updated with actual height
45
+ };
46
+ }
47
+ return void 0;
48
+ }
49
+ const getContainerBreakpoint = (containerWidth, containerHeight) => {
50
+ if (!BreakpointSm) return;
51
+ if (!BreakpointMd) return;
52
+ if (!BreakpointLg) return;
53
+ if (!BreakpointXl) return;
54
+ if (!BreakpointXxl) return;
55
+ const sm = parseInt(BreakpointSm.value);
56
+ const md = parseInt(BreakpointMd.value);
57
+ const lg = parseInt(BreakpointLg.value);
58
+ const xl = parseInt(BreakpointXl.value);
59
+ const xxl = parseInt(BreakpointXxl.value);
60
+ const result = containerBreakpoint(containerWidth, "xs", void 0, sm) ?? containerBreakpoint(containerWidth, "sm", sm, md) ?? containerBreakpoint(containerWidth, "md", md, lg) ?? containerBreakpoint(containerWidth, "lg", lg, xl) ?? containerBreakpoint(containerWidth, "xl", xl, xxl) ?? containerBreakpoint(containerWidth, "xxl", xxl, void 0);
61
+ return result ? { ...result, containerHeight } : void 0;
62
+ };
63
+ const useContainerQuery = (containerRef, props) => {
64
+ const [size, setSize] = useState(
65
+ void 0
66
+ );
67
+ useEffect(() => {
68
+ if (!containerRef.current) return;
69
+ const resizeObserver = new ResizeObserver((entries) => {
70
+ for (const entry of entries) {
71
+ const { width, height } = entry.contentRect;
72
+ const breakpoint = getContainerBreakpoint(width, height);
73
+ setSize(breakpoint);
74
+ }
75
+ });
76
+ resizeObserver.observe(containerRef.current);
77
+ const rect = containerRef.current.getBoundingClientRect();
78
+ setSize(getContainerBreakpoint(rect.width, rect.height));
79
+ return () => {
80
+ resizeObserver.disconnect();
81
+ };
82
+ }, [containerRef, props?.disable]);
83
+ return size;
84
+ };
85
+
86
+ const OverflowItemContext = createContext({
87
+ isInOverflowMenu: false
88
+ });
89
+ const useOverFlowItemContext = () => useContext(OverflowItemContext);
90
+
91
+ const ToolbarOverflowContext = createContext({
92
+ overflowItems: [],
93
+ addItem: () => {
94
+ return;
95
+ },
96
+ removeItem: () => {
97
+ return;
98
+ },
99
+ toolbarRef: { current: null },
100
+ orderedIds: [],
101
+ overflow: "wrap"
102
+ });
103
+
104
+ function getToolbarElements(toolbarElement) {
105
+ const toolbarContent = toolbarElement.querySelector(
106
+ '[data-anv="toolbar-content"]'
107
+ );
108
+ const mainItems = getKeyboardFocusableElements(toolbarContent).filter(
109
+ (item) => {
110
+ const isHidden = !item.closest('[aria-hidden="true"]');
111
+ const isInDrawer = !item.closest('[data-anv="filter-group-drawer"]');
112
+ const isInPopover = !item.closest('[data-anv="popover-content"]');
113
+ return isHidden && isInDrawer && isInPopover;
114
+ }
115
+ );
116
+ const overflowTrigger = toolbarElement.querySelector(
117
+ '[data-anv="toolbar-overflow-trigger"]'
118
+ );
119
+ return overflowTrigger ? [...mainItems, overflowTrigger] : mainItems;
120
+ }
121
+ function updateToolbarItemsTabIndex(toolbarElement, activeItem) {
122
+ if (!toolbarElement) return;
123
+ const items = getToolbarElements(toolbarElement);
124
+ if (!items.length) return;
125
+ let activeIndex = 0;
126
+ if (typeof activeItem === "number") {
127
+ activeIndex = Math.max(0, Math.min(activeItem, items.length - 1));
128
+ } else if (activeItem instanceof Element) {
129
+ const foundIndex = items.indexOf(activeItem);
130
+ if (foundIndex !== -1) {
131
+ activeIndex = foundIndex;
132
+ }
133
+ }
134
+ items.forEach((item, index) => {
135
+ item.setAttribute("tabindex", index === activeIndex ? "0" : "-1");
136
+ });
137
+ return items[activeIndex];
138
+ }
139
+ function handleToolbarKeyDown(event, toolbarElement) {
140
+ if (!toolbarElement || event.altKey || event.ctrlKey || event.metaKey) return;
141
+ const items = getToolbarElements(toolbarElement);
142
+ if (!items.length) return;
143
+ const activeElement = event.target;
144
+ if (!toolbarElement.contains(activeElement)) return;
145
+ const activeItem = items.find(
146
+ (item) => item === activeElement || Array.from(item.children).some((child) => child === activeElement)
147
+ );
148
+ const activeIndex = activeItem ? items.indexOf(activeItem) : -1;
149
+ if (activeIndex === -1) return;
150
+ let nextIndex = activeIndex;
151
+ const isVertical = toolbarElement.getAttribute("aria-orientation") === "vertical";
152
+ switch (event.key) {
153
+ case "ArrowLeft":
154
+ case "ArrowUp":
155
+ event.preventDefault();
156
+ if (isVertical && event.key === "ArrowUp" || !isVertical && event.key === "ArrowLeft") {
157
+ nextIndex = activeIndex <= 0 ? items.length - 1 : activeIndex - 1;
158
+ }
159
+ break;
160
+ case "ArrowRight":
161
+ case "ArrowDown":
162
+ event.preventDefault();
163
+ if (isVertical && event.key === "ArrowDown" || !isVertical && event.key === "ArrowRight") {
164
+ nextIndex = activeIndex >= items.length - 1 ? 0 : activeIndex + 1;
165
+ }
166
+ break;
167
+ case "Home":
168
+ event.preventDefault();
169
+ nextIndex = 0;
170
+ break;
171
+ case "End":
172
+ event.preventDefault();
173
+ nextIndex = items.length - 1;
174
+ break;
175
+ default:
176
+ return;
177
+ }
178
+ updateToolbarItemsTabIndex(toolbarElement, nextIndex);
179
+ items[nextIndex]?.focus();
180
+ }
181
+ const handleMenuKeyboardNavigation = (event) => {
182
+ const menuItems = Array.from(
183
+ event.currentTarget.querySelectorAll('[role="menuitem"]')
184
+ ).map((menuItem) => {
185
+ return getKeyboardFocusableElements(menuItem)[0] || menuItem;
186
+ });
187
+ if (!menuItems.length) return;
188
+ const currentIndex = menuItems.indexOf(document.activeElement);
189
+ if (currentIndex === -1) return;
190
+ let nextIndex = currentIndex;
191
+ const isModifierKey = event.altKey || event.ctrlKey || event.metaKey;
192
+ if (isModifierKey) return;
193
+ switch (event.key) {
194
+ case "ArrowDown":
195
+ case "ArrowUp": {
196
+ event.preventDefault();
197
+ const direction = event.key === "ArrowDown" ? 1 : -1;
198
+ nextIndex = (currentIndex + direction + menuItems.length) % menuItems.length;
199
+ break;
200
+ }
201
+ case "Home":
202
+ event.preventDefault();
203
+ nextIndex = 0;
204
+ break;
205
+ case "End":
206
+ event.preventDefault();
207
+ nextIndex = menuItems.length - 1;
208
+ break;
209
+ default:
210
+ return;
211
+ }
212
+ menuItems[nextIndex]?.focus();
213
+ };
214
+
215
+ const toolbar = "_toolbar_bslcr_13";
216
+ const styles$3 = {
217
+ toolbar: toolbar,
218
+ "toolbar-outline-spacer": "_toolbar-outline-spacer_bslcr_17",
219
+ "toolbar-content": "_toolbar-content_bslcr_20",
220
+ "overflow-wrap": "_overflow-wrap_bslcr_24",
221
+ "overflow-collapse": "_overflow-collapse_bslcr_27",
222
+ "toolbar-overflow-content": "_toolbar-overflow-content_bslcr_30",
223
+ "toolbar-button-item": "_toolbar-button-item_bslcr_38",
224
+ "toolbar-item": "_toolbar-item_bslcr_44",
225
+ "toolbar-button-toggle-item": "_toolbar-button-toggle-item_bslcr_63",
226
+ "toolbar-overflow-trigger": "_toolbar-overflow-trigger_bslcr_69"
227
+ };
228
+
229
+ const ToolbarItemWrapper = ({
230
+ item,
231
+ children,
232
+ observerRoot,
233
+ onVisibilityChange,
234
+ rootMargin,
235
+ className
236
+ }) => {
237
+ const { addItem, removeItem, toolbarRef, overflow } = useContext(
238
+ ToolbarOverflowContext
239
+ );
240
+ const itemId = useId();
241
+ const elementRef = useRef(null);
242
+ const isCollapseMode = overflow === "collapse";
243
+ const prevIntersectingRef = useRef(true);
244
+ const handleVisibilityChange = useCallback(
245
+ (isVisible) => {
246
+ if (!isCollapseMode || prevIntersectingRef.current === isVisible) return;
247
+ if (onVisibilityChange) {
248
+ onVisibilityChange(isVisible);
249
+ } else if (item) {
250
+ const itemWithId = { ...item, id: itemId };
251
+ if (isVisible) {
252
+ removeItem(itemWithId);
253
+ } else {
254
+ addItem(itemWithId);
255
+ }
256
+ }
257
+ prevIntersectingRef.current = isVisible;
258
+ },
259
+ [isCollapseMode, onVisibilityChange, item, itemId, addItem, removeItem]
260
+ );
261
+ const { isIntersecting, ref } = useIntersectionObserver({
262
+ root: isCollapseMode ? observerRoot ?? toolbarRef.current : null,
263
+ threshold: 1,
264
+ initialIsIntersecting: true,
265
+ // Start as visible
266
+ onChange: handleVisibilityChange,
267
+ rootMargin
268
+ });
269
+ const setRefCallback = useCallback(
270
+ (node) => {
271
+ elementRef.current = node;
272
+ if (isCollapseMode) {
273
+ ref(node);
274
+ }
275
+ },
276
+ [ref, isCollapseMode]
277
+ );
278
+ const handleFocusOrClick = useCallback(() => {
279
+ if (!toolbarRef.current || !elementRef.current) return;
280
+ const currentElement = elementRef.current.querySelector("button, a, input");
281
+ if (!currentElement) return;
282
+ updateToolbarItemsTabIndex(toolbarRef.current, currentElement);
283
+ }, [toolbarRef]);
284
+ useEffect(() => {
285
+ const interactiveEl = elementRef.current?.querySelector("button, a, input");
286
+ if (!interactiveEl) return;
287
+ interactiveEl.addEventListener("focus", handleFocusOrClick);
288
+ interactiveEl.addEventListener("click", handleFocusOrClick);
289
+ return () => {
290
+ interactiveEl.removeEventListener("focus", handleFocusOrClick);
291
+ interactiveEl.removeEventListener("click", handleFocusOrClick);
292
+ };
293
+ }, [handleFocusOrClick]);
294
+ const toolbarItemClassName = cx(styles$3["toolbar-item"], className);
295
+ const isHidden = isCollapseMode && !isIntersecting;
296
+ return /* @__PURE__ */ jsx(
297
+ "div",
298
+ {
299
+ ref: setRefCallback,
300
+ className: toolbarItemClassName,
301
+ style: { visibility: isHidden ? "hidden" : "visible" },
302
+ "aria-hidden": isHidden,
303
+ ...{ inert: isHidden ? "" : void 0 },
304
+ "data-id": itemId,
305
+ "data-anv": "toolbar-item",
306
+ children
307
+ }
308
+ );
309
+ };
310
+
311
+ const ToolbarButton = forwardRef(
312
+ (props, _ref) => {
313
+ const { appearance = "ghost", className, children, ...rest } = props;
314
+ const { isInOverflowMenu = false } = useOverFlowItemContext?.() || {};
315
+ const trackingId = useTrackingId({
316
+ name: "ToolbarButton",
317
+ data: {
318
+ disabled: props.disabled,
319
+ "aria-label": props["aria-label"],
320
+ children: props.children
321
+ },
322
+ hasOverride: !!props["data-tracking-id"]
323
+ });
324
+ const buttonClassNames = cx(className, styles$3["toolbar-button-item"]);
325
+ const item = children ? /* @__PURE__ */ jsx(
326
+ Button,
327
+ {
328
+ "data-tracking-id": trackingId,
329
+ appearance,
330
+ size: "small",
331
+ "data-anv": "toolbar-button",
332
+ className: buttonClassNames,
333
+ ...rest,
334
+ children
335
+ }
336
+ ) : /* @__PURE__ */ jsxs(Tooltip, { children: [
337
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { children: /* @__PURE__ */ jsx(
338
+ Button,
339
+ {
340
+ "data-tracking-id": trackingId,
341
+ appearance,
342
+ size: "small",
343
+ "data-anv": "toolbar-button",
344
+ className: buttonClassNames,
345
+ ...rest
346
+ }
347
+ ) }),
348
+ /* @__PURE__ */ jsx(Tooltip.Content, { children: rest["aria-label"] })
349
+ ] });
350
+ if (isInOverflowMenu) {
351
+ return item;
352
+ }
353
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { item: { itemProps: props, itemType: "button" }, children: item });
354
+ }
355
+ );
356
+ ToolbarButton.displayName = "ToolbarButton";
357
+
358
+ const ToolbarButtonToggle = forwardRef((props, _ref) => {
359
+ const { className, children, isFilter, ...rest } = props;
360
+ const { isInOverflowMenu = false } = useOverFlowItemContext?.() || {};
361
+ const trackingId = useTrackingId({
362
+ name: "ToolbarButtonToggle",
363
+ data: {
364
+ checked: props.checked,
365
+ disabled: props.disabled,
366
+ "aria-label": props["aria-label"],
367
+ children: props.children
368
+ },
369
+ hasOverride: !!props["data-tracking-id"]
370
+ });
371
+ const buttonToggleClassNames = cx(
372
+ className,
373
+ styles$3["toolbar-button-item"],
374
+ styles$3["toolbar-button-toggle-item"]
375
+ );
376
+ const item = children ? /* @__PURE__ */ jsx(
377
+ ButtonToggle,
378
+ {
379
+ "data-tracking-id": trackingId,
380
+ size: "small",
381
+ "data-anv": "toolbar-button-toggle",
382
+ className: buttonToggleClassNames,
383
+ ...rest,
384
+ children
385
+ }
386
+ ) : /* @__PURE__ */ jsxs(Tooltip, { children: [
387
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { children: /* @__PURE__ */ jsx(
388
+ ButtonToggle,
389
+ {
390
+ "data-tracking-id": trackingId,
391
+ size: "small",
392
+ "data-anv": "toolbar-button-toggle",
393
+ className: buttonToggleClassNames,
394
+ ...rest
395
+ }
396
+ ) }),
397
+ /* @__PURE__ */ jsx(Tooltip.Content, { children: rest["aria-label"] })
398
+ ] });
399
+ if (isInOverflowMenu || isFilter) {
400
+ return item;
401
+ }
402
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { item: { itemProps: props, itemType: "buttonToggle" }, children: item });
403
+ });
404
+ ToolbarButtonToggle.displayName = "ToolbarButtonToggle";
405
+
406
+ const ToolbarButtonLink = forwardRef((props, _ref) => {
407
+ const { appearance = "ghost", className, children, ...rest } = props;
408
+ const { isInOverflowMenu = false } = useOverFlowItemContext?.() || {};
409
+ const trackingId = useTrackingId({
410
+ name: "ToolbarButtonLink",
411
+ data: {
412
+ href: props.href,
413
+ disabled: props.disabled,
414
+ "aria-label": props["aria-label"],
415
+ children: props.children,
416
+ target: props.target
417
+ },
418
+ hasOverride: !!props["data-tracking-id"]
419
+ });
420
+ const buttonLinkClassNames = cx(className, styles$3["toolbar-button-item"]);
421
+ const item = children ? /* @__PURE__ */ jsx(
422
+ ButtonLink,
423
+ {
424
+ "data-tracking-id": trackingId,
425
+ appearance,
426
+ size: "small",
427
+ "data-anv": "toolbar-button-link",
428
+ className: buttonLinkClassNames,
429
+ ...rest,
430
+ children
431
+ }
432
+ ) : /* @__PURE__ */ jsxs(Tooltip, { children: [
433
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { children: /* @__PURE__ */ jsx(
434
+ ButtonLink,
435
+ {
436
+ "data-tracking-id": trackingId,
437
+ appearance,
438
+ size: "small",
439
+ "data-anv": "toolbar-button-link",
440
+ className: buttonLinkClassNames,
441
+ ...rest
442
+ }
443
+ ) }),
444
+ /* @__PURE__ */ jsx(Tooltip.Content, { children: rest["aria-label"] })
445
+ ] });
446
+ if (isInOverflowMenu) {
447
+ return item;
448
+ }
449
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { item: { itemProps: props, itemType: "buttonLink" }, children: item });
450
+ });
451
+ ToolbarButtonLink.displayName = "ToolbarButtonLink";
452
+
453
+ const ToolbarSelect = forwardRef(
454
+ (props, _ref) => {
455
+ const {
456
+ appearance = "ghost",
457
+ onChange,
458
+ selected: selectedItemId,
459
+ accessibleLabel,
460
+ className,
461
+ items,
462
+ ...rest
463
+ } = props;
464
+ const selectId = useId();
465
+ const defaultId = items.length > 0 ? items[0].id : "";
466
+ const [internalSelectedId, setInternalSelectedId] = useState(defaultId);
467
+ const selectedId = selectedItemId ?? internalSelectedId;
468
+ const selectedItem = items.find((item2) => item2.id === selectedId) || items.find((item2) => item2.id === defaultId);
469
+ useEffect(() => {
470
+ if (!selectedItemId && items.length > 0 && !items.some((item2) => item2.id === internalSelectedId)) {
471
+ setInternalSelectedId(items[0].id);
472
+ }
473
+ }, [items, selectedItemId, internalSelectedId]);
474
+ const handleSelectionChange = (selected) => {
475
+ if (selected?.id) {
476
+ if (selectedItemId === void 0) {
477
+ setInternalSelectedId(selected.id);
478
+ }
479
+ onChange?.(selected.id);
480
+ }
481
+ };
482
+ const { isInOverflowMenu = false } = useOverFlowItemContext?.() || {};
483
+ const trackingId = useTrackingId({
484
+ name: "ToolbarSelect",
485
+ data: {
486
+ selected: props.selected,
487
+ disabled: props.disabled,
488
+ "aria-label": props["aria-label"],
489
+ items: props.items
490
+ },
491
+ hasOverride: !!props["data-tracking-id"]
492
+ });
493
+ const buttonClassNames = cx(className, styles$3["toolbar-button-item"]);
494
+ const item = /* @__PURE__ */ jsxs(Popover, { noPadding: true, children: [
495
+ /* @__PURE__ */ jsx(
496
+ Popover.Button,
497
+ {
498
+ "data-tracking-id": trackingId,
499
+ appearance,
500
+ size: "small",
501
+ icon: { after: SvgArrowDropDown },
502
+ className: buttonClassNames,
503
+ id: selectId,
504
+ "data-anv": "toolbar-select",
505
+ ...rest,
506
+ children: selectedItem?.label
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(
510
+ Popover.Content,
511
+ {
512
+ className: styles$3["toolbar-select-content"],
513
+ "aria-label": `${accessibleLabel} options`,
514
+ children: /* @__PURE__ */ jsx(
515
+ Listbox,
516
+ {
517
+ selected: selectedItem,
518
+ onSelectionChange: handleSelectionChange,
519
+ items,
520
+ "aria-labelledby": selectId,
521
+ children: ({ items: items2 }) => items2.map((item2) => /* @__PURE__ */ jsx(Listbox.Option, { item: item2, children: item2.label }, item2.label))
522
+ }
523
+ )
524
+ }
525
+ )
526
+ ] });
527
+ if (isInOverflowMenu) {
528
+ return item;
529
+ }
530
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { item: { itemProps: props, itemType: "select" }, children: item });
531
+ }
532
+ );
533
+ ToolbarSelect.displayName = "ToolbarSelect";
534
+
535
+ const OverflowItem = ({ itemType, itemProps }) => {
536
+ switch (itemType) {
537
+ case "button":
538
+ return /* @__PURE__ */ jsx(ToolbarButton, { ...itemProps });
539
+ case "buttonToggle":
540
+ return /* @__PURE__ */ jsx(ToolbarButtonToggle, { ...itemProps });
541
+ case "buttonLink":
542
+ return /* @__PURE__ */ jsx(ToolbarButtonLink, { ...itemProps });
543
+ case "select":
544
+ return /* @__PURE__ */ jsx(ToolbarSelect, { ...itemProps });
545
+ default:
546
+ return null;
547
+ }
548
+ };
549
+ const ToolbarOverflowMenu = ({
550
+ additionalItems,
551
+ direction
552
+ }) => {
553
+ const { overflowItems, orderedIds } = useContext(ToolbarOverflowContext);
554
+ const menuTriggerId = useId();
555
+ const orderedItems = useMemo(() => {
556
+ const allElements = orderedIds?.map((id) => {
557
+ return overflowItems.find((item) => item.id === id);
558
+ });
559
+ return allElements?.filter((item) => item !== void 0) || [];
560
+ }, [orderedIds, overflowItems]);
561
+ const popoverButtonClassNames = cx(
562
+ styles$3["toolbar-button-item"],
563
+ styles$3["toolbar-overflow-trigger"]
564
+ );
565
+ const overflowIcon = direction === "horizontal" ? SvgMoreHoriz : SvgMoreVert;
566
+ return /* @__PURE__ */ jsxs(Popover, { noPadding: true, children: [
567
+ /* @__PURE__ */ jsx(
568
+ Popover.Button,
569
+ {
570
+ size: "small",
571
+ appearance: "ghost",
572
+ id: menuTriggerId,
573
+ className: popoverButtonClassNames,
574
+ "data-anv": "toolbar-overflow-trigger",
575
+ "aria-label": "Additional toolbar options",
576
+ children: /* @__PURE__ */ jsx(Icon, { svg: overflowIcon, size: "small" })
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsx(Popover.Content, { children: /* @__PURE__ */ jsx(OverflowItemContext.Provider, { value: { isInOverflowMenu: true }, children: /* @__PURE__ */ jsxs(
580
+ "ul",
581
+ {
582
+ role: "menu",
583
+ className: styles$3["toolbar-overflow-content"],
584
+ "data-anv": "toolbar-overflow-menu",
585
+ "aria-labelledby": menuTriggerId,
586
+ onKeyDown: handleMenuKeyboardNavigation,
587
+ children: [
588
+ orderedItems.map((item) => {
589
+ const { itemType, itemProps, id } = item;
590
+ return /* @__PURE__ */ jsx(
591
+ "li",
592
+ {
593
+ role: "menuitem",
594
+ "data-anv": "toolbar-overflow-item",
595
+ children: /* @__PURE__ */ jsx(
596
+ OverflowItem,
597
+ {
598
+ itemType,
599
+ itemProps,
600
+ id
601
+ }
602
+ )
603
+ },
604
+ `${itemType}-${id}`
605
+ );
606
+ }),
607
+ additionalItems?.map((item, index) => /* @__PURE__ */ jsx(
608
+ "li",
609
+ {
610
+ role: "menuitem",
611
+ "data-anv": "toolbar-overflow-item",
612
+ children: item
613
+ },
614
+ `additional-item-${index}`
615
+ ))
616
+ ]
617
+ }
618
+ ) }) })
619
+ ] });
620
+ };
621
+
622
+ const FilterGroupContext = createContext({
623
+ filterGroupRef: { current: null },
624
+ filters: [],
625
+ updateFilter: () => {
626
+ },
627
+ controlledFiltering: false,
628
+ hiddenFilters: [],
629
+ addHiddenFilter: () => {
630
+ },
631
+ removeHiddenFilter: () => {
632
+ }
633
+ });
634
+
635
+ const styles$2 = {
636
+ "filter-button-trigger": "_filter-button-trigger_320zf_18",
637
+ "filter-button-content": "_filter-button-content_320zf_22",
638
+ "filter-drawer-trigger": "_filter-drawer-trigger_320zf_26",
639
+ "filter-button-buttons": "_filter-button-buttons_320zf_31",
640
+ "filter-item": "_filter-item_320zf_37",
641
+ "filter-select-search": "_filter-select-search_320zf_45",
642
+ "filter-button-trigger--selected": "_filter-button-trigger--selected_320zf_54",
643
+ "filter-drawer-trigger--chipped": "_filter-drawer-trigger--chipped_320zf_64"
644
+ };
645
+
646
+ const FilterItemWrapper = ({
647
+ filter,
648
+ children
649
+ }) => {
650
+ const { addHiddenFilter, removeHiddenFilter, filterGroupRef } = useContext(FilterGroupContext);
651
+ const props = {
652
+ item: {
653
+ itemType: "button",
654
+ itemProps: {
655
+ children: null,
656
+ "aria-hidden": true
657
+ }
658
+ },
659
+ children,
660
+ className: styles$2["filter-item"],
661
+ observerRoot: filterGroupRef.current,
662
+ onVisibilityChange: (isVisible) => {
663
+ if (filter) {
664
+ if (isVisible) {
665
+ removeHiddenFilter?.(filter);
666
+ } else {
667
+ addHiddenFilter?.(filter);
668
+ }
669
+ }
670
+ },
671
+ rootMargin: "0px -80px 0px 0px"
672
+ };
673
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { ...props });
674
+ };
675
+
676
+ const getActiveFilters = (filters) => {
677
+ return filters.filter((filter) => {
678
+ switch (filter.type) {
679
+ case "boolean":
680
+ return filter.checked;
681
+ case "custom":
682
+ return filter.value !== void 0;
683
+ case "singleSelect":
684
+ return filter.selectedItem !== void 0;
685
+ case "multiSelect":
686
+ return filter.selectedItems && filter.selectedItems.length > 0;
687
+ case "date":
688
+ case "dateRange":
689
+ return filter.value !== null && filter.value !== void 0;
690
+ default:
691
+ return false;
692
+ }
693
+ });
694
+ };
695
+ const checkActiveFilters = (filters) => {
696
+ return getActiveFilters(filters).length > 0;
697
+ };
698
+ const resetFilters = (filters) => {
699
+ return filters.map((filter) => {
700
+ switch (filter.type) {
701
+ case "boolean":
702
+ return {
703
+ ...filter,
704
+ checked: false
705
+ };
706
+ case "custom":
707
+ return {
708
+ ...filter,
709
+ value: void 0
710
+ };
711
+ case "singleSelect":
712
+ return {
713
+ ...filter,
714
+ selectedItem: void 0
715
+ };
716
+ case "multiSelect":
717
+ return {
718
+ ...filter,
719
+ selectedItems: []
720
+ };
721
+ case "date":
722
+ case "dateRange":
723
+ return {
724
+ ...filter,
725
+ value: null
726
+ };
727
+ default:
728
+ return filter;
729
+ }
730
+ });
731
+ };
732
+ const updateSingleFilter = (filters, filterId, value) => {
733
+ return filters.map((filter) => {
734
+ if (filter.id !== filterId) return filter;
735
+ switch (filter.type) {
736
+ case "boolean":
737
+ return {
738
+ ...filter,
739
+ checked: value
740
+ };
741
+ case "singleSelect":
742
+ return {
743
+ ...filter,
744
+ selectedItem: value
745
+ };
746
+ case "multiSelect":
747
+ return {
748
+ ...filter,
749
+ selectedItems: value
750
+ };
751
+ case "date":
752
+ return {
753
+ ...filter,
754
+ value
755
+ };
756
+ case "dateRange":
757
+ return {
758
+ ...filter,
759
+ value
760
+ };
761
+ case "custom":
762
+ return {
763
+ ...filter,
764
+ value
765
+ };
766
+ default:
767
+ return filter;
768
+ }
769
+ });
770
+ };
771
+ const hasChangedFilter = (a, b) => {
772
+ if (a && b && typeof a === "object" && typeof b === "object" && "id" in a && "id" in b) {
773
+ return a.id !== b.id;
774
+ }
775
+ return a !== b;
776
+ };
777
+
778
+ const FilterToggleButton = ({
779
+ id,
780
+ checked,
781
+ children,
782
+ ...props
783
+ }) => {
784
+ const filter = {
785
+ id,
786
+ type: "boolean",
787
+ checked,
788
+ label: typeof children === "string" ? children : id
789
+ };
790
+ return /* @__PURE__ */ jsx(FilterItemWrapper, { filter, children: /* @__PURE__ */ jsx(
791
+ ToolbarButtonToggle,
792
+ {
793
+ checked,
794
+ isFilter: true,
795
+ ...props,
796
+ className: styles$2["filter-button-trigger"],
797
+ "data-anv": "toolbar-boolean-filter",
798
+ children
799
+ }
800
+ ) });
801
+ };
802
+
803
+ const FilterSelect = ({
804
+ filter,
805
+ draftValue,
806
+ onDraftChange
807
+ }) => {
808
+ const isMultiSelect = filter.type === "multiSelect";
809
+ const singleSelectList = useMemo(
810
+ () => /* @__PURE__ */ jsx(
811
+ Listbox,
812
+ {
813
+ items: filter.items,
814
+ selected: draftValue,
815
+ onSelectionChange: (selected) => {
816
+ onDraftChange(selected);
817
+ },
818
+ disableAutoSelectOnFocus: true,
819
+ style: { padding: 0 },
820
+ children: ({ items }) => items.map((item) => /* @__PURE__ */ jsx(Listbox.Option, { item, disabled: item.disabled, children: item.label }, item.id))
821
+ },
822
+ filter.id
823
+ ),
824
+ [filter.id, filter.items, draftValue, onDraftChange]
825
+ );
826
+ const multiSelectList = useMemo(
827
+ () => /* @__PURE__ */ jsx(
828
+ ListView,
829
+ {
830
+ items: filter.items,
831
+ selected: Array.isArray(draftValue) ? draftValue : [],
832
+ onSelectionChange: (selectedItems) => {
833
+ const items = selectedItems;
834
+ onDraftChange(items);
835
+ },
836
+ style: { padding: 0 },
837
+ children: ({ items }) => items.map((item) => /* @__PURE__ */ jsx(ListView.Option, { item, children: item.label }, item.id))
838
+ },
839
+ filter.id
840
+ ),
841
+ [filter.id, filter.items, draftValue, onDraftChange]
842
+ );
843
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
844
+ filter.hasSearch && /* @__PURE__ */ jsx(
845
+ SearchField,
846
+ {
847
+ size: "small",
848
+ className: styles$2["filter-select-search"],
849
+ onChange: (e) => {
850
+ filter.onSearch?.(e.target.value);
851
+ },
852
+ onClear: () => {
853
+ filter.onSearchClear?.();
854
+ },
855
+ "data-anv": "filter-select-search"
856
+ }
857
+ ),
858
+ isMultiSelect ? multiSelectList : singleSelectList
859
+ ] });
860
+ };
861
+
862
+ const FilterDateSingle = ({
863
+ filter,
864
+ draftValue,
865
+ onDraftChange
866
+ }) => {
867
+ const maskedDateInputRef = useRef(null);
868
+ const handleChange = (change) => {
869
+ onDraftChange(change.date);
870
+ };
871
+ const { value, onChange } = useDateFieldSingleConversion({
872
+ value: draftValue,
873
+ onChange: handleChange
874
+ });
875
+ const { handleInputChange, handleCalendarSelection } = useDateFieldSingleState({
876
+ valueProp: value,
877
+ onChange: (change) => onChange({ ...change, isDateValid: true })
878
+ });
879
+ return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
880
+ /* @__PURE__ */ jsx(
881
+ MaskedDateInput,
882
+ {
883
+ mode: filter.mode,
884
+ ref: maskedDateInputRef,
885
+ onChange: handleInputChange,
886
+ lastValidDate: value ?? null,
887
+ autoComplete: "off"
888
+ }
889
+ ),
890
+ /* @__PURE__ */ jsx(
891
+ DateFieldSingleCalendar,
892
+ {
893
+ value: value ?? null,
894
+ onSelection: handleCalendarSelection
895
+ }
896
+ )
897
+ ] });
898
+ };
899
+
900
+ const FilterDateRange = ({
901
+ filter,
902
+ draftValue,
903
+ onDraftChange
904
+ }) => {
905
+ const maskedDateRangeInputRef = useRef(null);
906
+ const handleChange = (change) => {
907
+ const hasCompleteRange = change.startDate && change.endDate;
908
+ const isClearingRange = !change.startDate && !change.endDate;
909
+ if (hasCompleteRange || isClearingRange) {
910
+ onDraftChange({
911
+ startDate: change.startDate,
912
+ endDate: change.endDate
913
+ });
914
+ }
915
+ };
916
+ const { value, onChange } = useDateFieldRangeConversion({
917
+ value: draftValue,
918
+ onChange: handleChange
919
+ });
920
+ const { handleInputChange, handleCalendarSelection } = useDateFieldRangeState(
921
+ {
922
+ valueProp: value,
923
+ onChange: (change) => {
924
+ const hasCompleteRange = change.startDate && change.endDate;
925
+ const isClearingRange = change.isInputEmpty;
926
+ if (change.isInputValid && (hasCompleteRange || isClearingRange)) {
927
+ onChange({ ...change, isDateRangeValid: true });
928
+ }
929
+ }
930
+ }
931
+ );
932
+ return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
933
+ /* @__PURE__ */ jsx(
934
+ MaskedDateRangeInput,
935
+ {
936
+ mode: filter.mode,
937
+ ref: maskedDateRangeInputRef,
938
+ onChange: handleInputChange,
939
+ startDate: value?.startDate ?? null,
940
+ endDate: value?.endDate ?? null,
941
+ autoComplete: "off"
942
+ }
943
+ ),
944
+ /* @__PURE__ */ jsx(
945
+ DateFieldRangeCalendar,
946
+ {
947
+ startDate: value?.startDate ?? null,
948
+ endDate: value?.endDate ?? null,
949
+ onSelection: handleCalendarSelection
950
+ }
951
+ )
952
+ ] });
953
+ };
954
+
955
+ const FilterButton = ({
956
+ filter,
957
+ children,
958
+ className
959
+ }) => {
960
+ const [isOpen, setIsOpen] = useState(false);
961
+ const { updateFilter, controlledFiltering } = useContext(FilterGroupContext);
962
+ const [draftValue, setDraftValue] = useState(
963
+ filter.type === "multiSelect" ? [] : void 0
964
+ );
965
+ const getCurrentFilterValue = () => {
966
+ switch (filter.type) {
967
+ case "singleSelect":
968
+ return filter.selectedItem;
969
+ case "multiSelect":
970
+ return filter.selectedItems || [];
971
+ case "date":
972
+ case "dateRange":
973
+ return filter.value;
974
+ case "custom":
975
+ return filter.value;
976
+ default:
977
+ return void 0;
978
+ }
979
+ };
980
+ useEffect(() => {
981
+ if (isOpen) {
982
+ const initialValue = getCurrentFilterValue();
983
+ setDraftValue(initialValue);
984
+ }
985
+ }, [isOpen]);
986
+ const handleChange = useCallback(
987
+ (value) => {
988
+ if (hasChangedFilter(value, draftValue)) {
989
+ setDraftValue(value);
990
+ if (!controlledFiltering) {
991
+ updateFilter(filter.id, value, true);
992
+ if (filter.type !== "multiSelect") {
993
+ setIsOpen(false);
994
+ }
995
+ }
996
+ }
997
+ },
998
+ [filter.id, filter.type, controlledFiltering, updateFilter, draftValue]
999
+ );
1000
+ const handleSubmit = () => {
1001
+ const stateValue = getCurrentFilterValue();
1002
+ if (hasChangedFilter(draftValue, stateValue)) {
1003
+ updateFilter(filter.id, draftValue, true);
1004
+ }
1005
+ setIsOpen(false);
1006
+ };
1007
+ const handleCancel = () => {
1008
+ if (!controlledFiltering) {
1009
+ setIsOpen(false);
1010
+ return;
1011
+ }
1012
+ const originalValue = getCurrentFilterValue();
1013
+ setDraftValue(originalValue);
1014
+ setIsOpen(false);
1015
+ };
1016
+ const getButtonLabel = useMemo(() => {
1017
+ switch (filter.type) {
1018
+ case "singleSelect": {
1019
+ const singleSelectFilter = filter;
1020
+ if (singleSelectFilter.selectedItem) {
1021
+ return `${filter.label}: ${singleSelectFilter.selectedItem.label}`;
1022
+ }
1023
+ return filter.label;
1024
+ }
1025
+ case "multiSelect": {
1026
+ const multiSelectFilter = filter;
1027
+ if (multiSelectFilter.selectedItems && multiSelectFilter.selectedItems.length > 0) {
1028
+ const selectionCount = multiSelectFilter.selectedItems.length.toString();
1029
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1030
+ filter.label,
1031
+ /* @__PURE__ */ jsx(
1032
+ Chip,
1033
+ {
1034
+ label: selectionCount,
1035
+ color: "#0265DC",
1036
+ size: "small",
1037
+ "aria-label": `${selectionCount} selected items`
1038
+ }
1039
+ )
1040
+ ] });
1041
+ }
1042
+ return filter.label;
1043
+ }
1044
+ case "date":
1045
+ if (filter.value) {
1046
+ const date = DateTime.fromISO(filter.value, { zone: "local" });
1047
+ return `${filter.label}: ${date.monthShort} ${date.day}, ${date.year}`;
1048
+ }
1049
+ return filter.label;
1050
+ case "dateRange":
1051
+ if (filter.value) {
1052
+ const start = DateTime.fromISO(filter.value.startDate, {
1053
+ zone: "local"
1054
+ });
1055
+ const end = DateTime.fromISO(filter.value.endDate, {
1056
+ zone: "local"
1057
+ });
1058
+ const isSameYear = start.year === end.year;
1059
+ const formattedStart = isSameYear ? `${start.monthShort} ${start.day}` : `${start.monthShort} ${start.day}, ${start.year}`;
1060
+ return `${filter.label}: ${formattedStart} – ${end.monthShort} ${end.day}, ${end.year}`;
1061
+ }
1062
+ return filter.label;
1063
+ case "custom":
1064
+ if (filter.labelChipCount) {
1065
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1066
+ filter.label,
1067
+ /* @__PURE__ */ jsx(
1068
+ Chip,
1069
+ {
1070
+ label: filter.labelChipCount.toString(),
1071
+ color: "#0265DC",
1072
+ size: "small",
1073
+ "aria-label": `${filter.labelChipCount} selected items`
1074
+ }
1075
+ )
1076
+ ] });
1077
+ }
1078
+ return filter.label;
1079
+ default:
1080
+ return filter.label;
1081
+ }
1082
+ }, [filter]);
1083
+ const getContent = useMemo(() => {
1084
+ switch (filter.type) {
1085
+ case "custom":
1086
+ return filter.buttonRender({
1087
+ value: draftValue,
1088
+ onChange: handleChange
1089
+ });
1090
+ case "singleSelect":
1091
+ return /* @__PURE__ */ jsx(
1092
+ FilterSelect,
1093
+ {
1094
+ filter,
1095
+ draftValue,
1096
+ onDraftChange: handleChange
1097
+ }
1098
+ );
1099
+ case "multiSelect":
1100
+ return /* @__PURE__ */ jsx(
1101
+ FilterSelect,
1102
+ {
1103
+ filter,
1104
+ draftValue,
1105
+ onDraftChange: handleChange
1106
+ }
1107
+ );
1108
+ case "date":
1109
+ return /* @__PURE__ */ jsx(
1110
+ FilterDateSingle,
1111
+ {
1112
+ filter,
1113
+ draftValue,
1114
+ onDraftChange: handleChange
1115
+ }
1116
+ );
1117
+ case "dateRange":
1118
+ return /* @__PURE__ */ jsx(
1119
+ FilterDateRange,
1120
+ {
1121
+ filter,
1122
+ draftValue,
1123
+ onDraftChange: handleChange
1124
+ }
1125
+ );
1126
+ default:
1127
+ return children;
1128
+ }
1129
+ }, [filter, draftValue, handleChange, children]);
1130
+ const handleOutsidePress = () => {
1131
+ if (controlledFiltering) {
1132
+ handleCancel();
1133
+ } else {
1134
+ if (filter.type === "multiSelect") {
1135
+ updateFilter(filter.id, draftValue, true);
1136
+ }
1137
+ handleSubmit();
1138
+ }
1139
+ };
1140
+ const handleKeyDown = (e) => {
1141
+ if (e.key === "Enter") {
1142
+ if (!controlledFiltering) {
1143
+ handleSubmit();
1144
+ }
1145
+ }
1146
+ if (e.key === "Escape") {
1147
+ handleOutsidePress();
1148
+ }
1149
+ };
1150
+ const triggerClasses = cx(styles$2["filter-button-trigger"], {
1151
+ [styles$2["filter-button-trigger--selected"]]: filter.type === "custom" && filter.value || filter.type === "singleSelect" && filter.selectedItem || filter.type === "multiSelect" && filter.selectedItems && filter.selectedItems.length > 0 || filter.type === "date" && filter.value || filter.type === "dateRange" && filter.value
1152
+ });
1153
+ const contentClasses = cx(styles$2["filter-button-content"], className);
1154
+ const iconOptions = filter.type === "date" || filter.type === "dateRange" ? { before: SvgEvent } : { after: SvgKeyboardArrowDown };
1155
+ return /* @__PURE__ */ jsx(FilterItemWrapper, { filter, children: /* @__PURE__ */ jsxs(
1156
+ Popover,
1157
+ {
1158
+ open: isOpen,
1159
+ onClickOutside: isOpen ? handleOutsidePress : void 0,
1160
+ placement: "bottom-start",
1161
+ children: [
1162
+ /* @__PURE__ */ jsx(
1163
+ Popover.Button,
1164
+ {
1165
+ appearance: "ghost",
1166
+ size: "small",
1167
+ icon: iconOptions,
1168
+ "data-id": filter.id,
1169
+ "data-anv": "toolbar-button",
1170
+ className: triggerClasses,
1171
+ onClick: () => {
1172
+ setIsOpen(!isOpen);
1173
+ },
1174
+ children: getButtonLabel
1175
+ }
1176
+ ),
1177
+ /* @__PURE__ */ jsxs(Popover.Content, { onKeyDown: handleKeyDown, className: contentClasses, children: [
1178
+ getContent,
1179
+ controlledFiltering && /* @__PURE__ */ jsxs(
1180
+ Flex,
1181
+ {
1182
+ gap: 2,
1183
+ justifyContent: "flex-end",
1184
+ className: styles$2["filter-button-buttons"],
1185
+ children: [
1186
+ /* @__PURE__ */ jsx(Popover.Close, { size: "small", onClick: handleCancel, children: "Cancel" }),
1187
+ /* @__PURE__ */ jsx(Button, { appearance: "primary", size: "small", onClick: handleSubmit, children: "Apply" })
1188
+ ]
1189
+ }
1190
+ )
1191
+ ] })
1192
+ ]
1193
+ }
1194
+ ) });
1195
+ };
1196
+
1197
+ const styles$1 = {
1198
+ "toolbar-control-group": "_toolbar-control-group_13h8p_2"
1199
+ };
1200
+
1201
+ const ToolbarControlGroupElement = forwardRef((props, ref) => {
1202
+ const { children, "aria-label": ariaLabel, ...rest } = props;
1203
+ const { overflow } = useContext(ToolbarOverflowContext);
1204
+ return /* @__PURE__ */ jsx(
1205
+ Flex,
1206
+ {
1207
+ ref,
1208
+ alignItems: "center",
1209
+ gap: 1,
1210
+ wrap: overflow === "collapse" ? "nowrap" : "wrap",
1211
+ "data-anv": "toolbar-control-group",
1212
+ role: "group",
1213
+ "aria-label": ariaLabel ? ariaLabel : "Toolbar controls",
1214
+ className: styles$1["toolbar-control-group"],
1215
+ ...rest,
1216
+ children
1217
+ }
1218
+ );
1219
+ });
1220
+ ToolbarControlGroupElement.displayName = "ToolbarControlGroup";
1221
+ const ToolbarControlGroup = ToolbarControlGroupElement;
1222
+
1223
+ const SvgTune = (props) => /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", ...props }, /* @__PURE__ */ React.createElement("path", { d: "M3 18c0 .55.45 1 1 1h5v-2H4c-.55 0-1 .45-1 1zM3 6c0 .55.45 1 1 1h9V5H4c-.55 0-1 .45-1 1zm10 14v-1h7c.55 0 1-.45 1-1s-.45-1-1-1h-7v-1c0-.55-.45-1-1-1s-1 .45-1 1v4c0 .55.45 1 1 1s1-.45 1-1zM7 10v1H4c-.55 0-1 .45-1 1s.45 1 1 1h3v1c0 .55.45 1 1 1s1-.45 1-1v-4c0-.55-.45-1-1-1s-1 .45-1 1zm14 2c0-.55-.45-1-1-1h-9v2h9c.55 0 1-.45 1-1zm-5-3c.55 0 1-.45 1-1V7h3c.55 0 1-.45 1-1s-.45-1-1-1h-3V4c0-.55-.45-1-1-1s-1 .45-1 1v4c0 .55.45 1 1 1z" }));
1224
+
1225
+ const FilterDrawer = () => {
1226
+ const [open, setOpen] = useState(false);
1227
+ const {
1228
+ filters,
1229
+ updateFilter,
1230
+ onFilterChange,
1231
+ hiddenFilters,
1232
+ filterGroupRef
1233
+ } = useContext(FilterGroupContext);
1234
+ const containerQuery = useContainerQuery(filterGroupRef);
1235
+ const showInlineFilters = containerQuery && containerQuery.name !== "xs" && containerQuery.name !== "sm";
1236
+ const [draftFilters, setDraftFilters] = useState(filters);
1237
+ const [searchValues, setSearchValues] = useState({});
1238
+ const activeFiltersCount = getActiveFilters(
1239
+ !showInlineFilters ? filters : hiddenFilters
1240
+ ).length;
1241
+ useEffect(() => {
1242
+ if (open) {
1243
+ setDraftFilters(
1244
+ filters.map((filter) => {
1245
+ switch (filter.type) {
1246
+ case "singleSelect":
1247
+ return {
1248
+ ...filter,
1249
+ selectedItem: filter.selectedItem ? filter.items.find(
1250
+ (item) => item.id === filter.selectedItem?.id
1251
+ ) || filter.selectedItem : void 0
1252
+ };
1253
+ case "multiSelect":
1254
+ return {
1255
+ ...filter,
1256
+ selectedItems: filter.selectedItems ? filter.selectedItems.map((selectedItem) => {
1257
+ const matchingItem = filter.items.find(
1258
+ (item) => item.id === selectedItem.id
1259
+ );
1260
+ return matchingItem || selectedItem;
1261
+ }) : []
1262
+ };
1263
+ case "date":
1264
+ return {
1265
+ ...filter,
1266
+ value: filter.value
1267
+ };
1268
+ case "dateRange":
1269
+ return {
1270
+ ...filter,
1271
+ value: filter.value
1272
+ };
1273
+ case "custom":
1274
+ return {
1275
+ ...filter,
1276
+ value: filter.value ? { ...filter.value } : void 0
1277
+ };
1278
+ default:
1279
+ return { ...filter };
1280
+ }
1281
+ })
1282
+ );
1283
+ }
1284
+ }, [open]);
1285
+ const handleDraftChange = useCallback(
1286
+ (filterId, value) => {
1287
+ setDraftFilters((draft) => updateSingleFilter(draft, filterId, value));
1288
+ const filter = filters.find((f) => f.id === filterId);
1289
+ if ((filter?.type === "singleSelect" || filter?.type === "multiSelect") && filter.hasSearch && value) {
1290
+ setSearchValues((prev) => ({ ...prev, [filterId]: "" }));
1291
+ requestAnimationFrame(() => {
1292
+ filter.onSearch?.("");
1293
+ });
1294
+ }
1295
+ },
1296
+ [filters]
1297
+ );
1298
+ const clearDraftFilters = () => {
1299
+ setDraftFilters(resetFilters(draftFilters));
1300
+ };
1301
+ const hasActiveDraftFilters = checkActiveFilters(draftFilters);
1302
+ const filterForm = useMemo(
1303
+ () => draftFilters.map((draftFilter) => {
1304
+ const originalFilter = filters.find((f) => f.id === draftFilter.id);
1305
+ if (!originalFilter) return null;
1306
+ switch (draftFilter.type) {
1307
+ case "boolean":
1308
+ return /* @__PURE__ */ jsx(
1309
+ Checkbox,
1310
+ {
1311
+ label: draftFilter.label,
1312
+ checked: draftFilter.checked,
1313
+ onChange: (e) => handleDraftChange(draftFilter.id, e?.target.checked ?? false)
1314
+ },
1315
+ draftFilter.id
1316
+ );
1317
+ case "custom": {
1318
+ const customFilter = originalFilter;
1319
+ return /* @__PURE__ */ jsx("div", { children: customFilter.drawerRender?.({
1320
+ value: draftFilter.value,
1321
+ onChange: (value) => handleDraftChange(draftFilter.id, value)
1322
+ }) }, draftFilter.id);
1323
+ }
1324
+ case "singleSelect": {
1325
+ const singleSelectFilter = originalFilter;
1326
+ const draftSingleSelectFilter = draftFilter;
1327
+ if (singleSelectFilter.simpleDrawerVariant) {
1328
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Radio.Group, { legend: singleSelectFilter.label, children: singleSelectFilter.items.map((item) => /* @__PURE__ */ jsx(
1329
+ Radio,
1330
+ {
1331
+ name: `${singleSelectFilter.id}-radio`,
1332
+ value: item.id,
1333
+ label: item.label,
1334
+ checked: draftSingleSelectFilter.selectedItem?.id === item.id,
1335
+ onChange: (e) => {
1336
+ if (e?.target.checked) {
1337
+ const selected = singleSelectFilter.items.find(
1338
+ (opt) => opt.id === e.target.value
1339
+ );
1340
+ handleDraftChange(draftFilter.id, selected);
1341
+ }
1342
+ }
1343
+ },
1344
+ item.id
1345
+ )) }) }, draftFilter.id);
1346
+ } else {
1347
+ const selectedItem = draftSingleSelectFilter.selectedItem ? singleSelectFilter.items?.find(
1348
+ (item) => item.id === draftSingleSelectFilter.selectedItem?.id
1349
+ ) ?? null : null;
1350
+ return /* @__PURE__ */ jsxs(
1351
+ Combobox,
1352
+ {
1353
+ items: singleSelectFilter.items,
1354
+ selectedItem,
1355
+ onChange: (selectedItem2) => {
1356
+ handleDraftChange(draftFilter.id, selectedItem2);
1357
+ },
1358
+ itemToString: (item) => item?.label ?? "",
1359
+ disableFilter: singleSelectFilter.hasSearch,
1360
+ children: [
1361
+ singleSelectFilter.hasSearch ? /* @__PURE__ */ jsx(
1362
+ Combobox.SearchField,
1363
+ {
1364
+ label: draftSingleSelectFilter.label,
1365
+ prefix: { icon: { svg: SvgSearch } },
1366
+ placeholder: "Search...",
1367
+ size: "small",
1368
+ value: draftSingleSelectFilter.selectedItem?.label || searchValues[draftFilter.id] || "",
1369
+ onChange: (e) => {
1370
+ const searchValue = e.target.value;
1371
+ setSearchValues((prev) => ({
1372
+ ...prev,
1373
+ [draftFilter.id]: searchValue
1374
+ }));
1375
+ singleSelectFilter.onSearch?.(searchValue);
1376
+ },
1377
+ onClear: () => {
1378
+ setSearchValues((prev) => ({
1379
+ ...prev,
1380
+ [draftFilter.id]: ""
1381
+ }));
1382
+ handleDraftChange(draftFilter.id, void 0);
1383
+ singleSelectFilter.onSearchClear?.();
1384
+ },
1385
+ "data-anv": "filter-drawer-combobox-search"
1386
+ }
1387
+ ) : /* @__PURE__ */ jsx(
1388
+ Combobox.SelectTrigger,
1389
+ {
1390
+ label: singleSelectFilter.label,
1391
+ placeholder: "Select an option...",
1392
+ size: "small"
1393
+ }
1394
+ ),
1395
+ /* @__PURE__ */ jsx(Combobox.Content, { children: ({ items }) => /* @__PURE__ */ jsx(Combobox.List, { style: { padding: 0 }, children: items.map((item, i) => /* @__PURE__ */ jsx(Combobox.Item, { item, index: i, children: item.label }, item.id)) }) })
1396
+ ]
1397
+ },
1398
+ draftFilter.id
1399
+ );
1400
+ }
1401
+ }
1402
+ case "multiSelect": {
1403
+ const multiSelectFilter = originalFilter;
1404
+ const draftMultiSelectFilter = draftFilter;
1405
+ if (multiSelectFilter.simpleDrawerVariant) {
1406
+ return /* @__PURE__ */ jsx(
1407
+ Checkbox.Group,
1408
+ {
1409
+ legend: multiSelectFilter.label,
1410
+ children: multiSelectFilter.items.map((item) => /* @__PURE__ */ jsx(
1411
+ Checkbox,
1412
+ {
1413
+ label: item.label,
1414
+ checked: draftMultiSelectFilter.selectedItems?.some(
1415
+ (selected) => selected.id === item.id
1416
+ ) ?? false,
1417
+ onChange: (e) => {
1418
+ const currentSelected = draftMultiSelectFilter.selectedItems || [];
1419
+ if (e?.target.checked) {
1420
+ handleDraftChange(draftFilter.id, [
1421
+ ...currentSelected,
1422
+ item
1423
+ ]);
1424
+ } else {
1425
+ handleDraftChange(
1426
+ draftFilter.id,
1427
+ currentSelected.filter(
1428
+ (selected) => selected.id !== item.id
1429
+ )
1430
+ );
1431
+ }
1432
+ }
1433
+ },
1434
+ item.id
1435
+ ))
1436
+ },
1437
+ draftFilter.id
1438
+ );
1439
+ } else {
1440
+ const hasActiveSearch = searchValues[draftFilter.id] && searchValues[draftFilter.id].length > 0;
1441
+ return /* @__PURE__ */ jsxs(
1442
+ Combobox,
1443
+ {
1444
+ items: multiSelectFilter.items,
1445
+ selectedItems: draftMultiSelectFilter.selectedItems || [],
1446
+ onChange: (selectedItems) => handleDraftChange(draftFilter.id, selectedItems),
1447
+ itemToString: (item) => item?.label ?? "",
1448
+ itemToKey: (item) => item?.id ?? "",
1449
+ disableFilter: multiSelectFilter.hasSearch,
1450
+ multiple: true,
1451
+ disableCloseOnSelectItem: !hasActiveSearch,
1452
+ children: [
1453
+ multiSelectFilter.hasSearch ? /* @__PURE__ */ jsx(
1454
+ Combobox.SearchField,
1455
+ {
1456
+ label: multiSelectFilter.label,
1457
+ prefix: { icon: { svg: SvgSearch } },
1458
+ placeholder: "Search...",
1459
+ size: "small",
1460
+ value: searchValues[draftFilter.id] || "",
1461
+ onChange: (e) => {
1462
+ const searchValue = e.target.value;
1463
+ setSearchValues((prev) => ({
1464
+ ...prev,
1465
+ [draftFilter.id]: searchValue
1466
+ }));
1467
+ multiSelectFilter.onSearch?.(searchValue);
1468
+ },
1469
+ onClear: () => {
1470
+ setSearchValues((prev) => ({
1471
+ ...prev,
1472
+ [draftFilter.id]: ""
1473
+ }));
1474
+ handleDraftChange(draftFilter.id, []);
1475
+ multiSelectFilter.onSearchClear?.();
1476
+ },
1477
+ "data-anv": "filter-drawer-combobox-search"
1478
+ }
1479
+ ) : /* @__PURE__ */ jsx(
1480
+ Combobox.SelectTrigger,
1481
+ {
1482
+ label: multiSelectFilter.label,
1483
+ placeholder: "Select options...",
1484
+ size: "small"
1485
+ }
1486
+ ),
1487
+ /* @__PURE__ */ jsx(Combobox.Content, { children: ({ items }) => /* @__PURE__ */ jsx(Combobox.List, { style: { padding: 0 }, children: items.map((item, i) => /* @__PURE__ */ jsx(Combobox.Item, { item, index: i, children: item.label }, item.id)) }) })
1488
+ ]
1489
+ },
1490
+ draftFilter.id
1491
+ );
1492
+ }
1493
+ }
1494
+ case "date": {
1495
+ return /* @__PURE__ */ jsx(
1496
+ DateFieldSingle,
1497
+ {
1498
+ label: draftFilter.label,
1499
+ value: draftFilter.value,
1500
+ onChange: (change) => {
1501
+ handleDraftChange(draftFilter.id, change.date);
1502
+ },
1503
+ mode: draftFilter.mode
1504
+ },
1505
+ draftFilter.id
1506
+ );
1507
+ }
1508
+ case "dateRange": {
1509
+ return /* @__PURE__ */ jsx(
1510
+ DateFieldRange,
1511
+ {
1512
+ label: draftFilter.label,
1513
+ value: draftFilter.value,
1514
+ onChange: (change) => {
1515
+ handleDraftChange(draftFilter.id, {
1516
+ startDate: change.startDate,
1517
+ endDate: change.endDate
1518
+ });
1519
+ },
1520
+ mode: draftFilter.mode
1521
+ },
1522
+ draftFilter.id
1523
+ );
1524
+ }
1525
+ default:
1526
+ return null;
1527
+ }
1528
+ }),
1529
+ [draftFilters, filters, searchValues, handleDraftChange]
1530
+ );
1531
+ const applyFiltering = () => {
1532
+ draftFilters.forEach((draftFilter) => {
1533
+ switch (draftFilter.type) {
1534
+ case "boolean":
1535
+ updateFilter(draftFilter.id, draftFilter.checked, false);
1536
+ break;
1537
+ case "singleSelect":
1538
+ updateFilter(
1539
+ draftFilter.id,
1540
+ draftFilter.selectedItem,
1541
+ false
1542
+ );
1543
+ break;
1544
+ case "multiSelect":
1545
+ updateFilter(
1546
+ draftFilter.id,
1547
+ draftFilter.selectedItems,
1548
+ false
1549
+ );
1550
+ break;
1551
+ case "date":
1552
+ case "dateRange":
1553
+ case "custom":
1554
+ updateFilter(draftFilter.id, draftFilter.value, false);
1555
+ break;
1556
+ }
1557
+ });
1558
+ onFilterChange?.(draftFilters);
1559
+ setOpen(false);
1560
+ };
1561
+ const handleCancel = () => {
1562
+ setOpen(false);
1563
+ };
1564
+ const hasHiddenActiveFilters = activeFiltersCount > 0;
1565
+ const triggerClasses = cx(
1566
+ styles$2["filter-button-trigger"],
1567
+ styles$2["filter-drawer-trigger"],
1568
+ {
1569
+ [styles$2["filter-drawer-trigger--chipped"]]: hasHiddenActiveFilters
1570
+ }
1571
+ );
1572
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1573
+ /* @__PURE__ */ jsxs(
1574
+ ButtonToggle,
1575
+ {
1576
+ "data-anv": "filter-group-drawer-trigger",
1577
+ icon: { before: SvgTune },
1578
+ onClick: () => setOpen(true),
1579
+ className: triggerClasses,
1580
+ checked: open,
1581
+ children: [
1582
+ "Filters",
1583
+ hasHiddenActiveFilters && /* @__PURE__ */ jsx(
1584
+ Chip,
1585
+ {
1586
+ size: "small",
1587
+ color: "#0265DC",
1588
+ label: activeFiltersCount.toString()
1589
+ }
1590
+ )
1591
+ ]
1592
+ }
1593
+ ),
1594
+ /* @__PURE__ */ jsxs(
1595
+ Drawer,
1596
+ {
1597
+ "data-anv": "filter-group-drawer",
1598
+ "data-testid": "filter-group-drawer",
1599
+ open,
1600
+ onClose: () => setOpen(false),
1601
+ children: [
1602
+ /* @__PURE__ */ jsx(Drawer.Content, { children: /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 6, grow: 1, children: filterForm }) }),
1603
+ /* @__PURE__ */ jsx(Drawer.Footer, { children: /* @__PURE__ */ jsxs(
1604
+ Flex,
1605
+ {
1606
+ justifyContent: hasActiveDraftFilters ? "space-between" : "flex-end",
1607
+ grow: 1,
1608
+ children: [
1609
+ hasActiveDraftFilters && /* @__PURE__ */ jsx(
1610
+ Button,
1611
+ {
1612
+ appearance: "ghost",
1613
+ icon: { before: SvgClose },
1614
+ onClick: clearDraftFilters,
1615
+ children: "Clear All Filters"
1616
+ }
1617
+ ),
1618
+ /* @__PURE__ */ jsxs(Flex, { gap: "3", children: [
1619
+ /* @__PURE__ */ jsx(Button, { onClick: handleCancel, children: "Cancel" }),
1620
+ /* @__PURE__ */ jsx(Button, { appearance: "primary", onClick: applyFiltering, children: "Apply" })
1621
+ ] })
1622
+ ]
1623
+ }
1624
+ ) })
1625
+ ]
1626
+ }
1627
+ )
1628
+ ] });
1629
+ };
1630
+
1631
+ const FilterGroupElement = forwardRef(
1632
+ (props, ref) => {
1633
+ const {
1634
+ filters: initialFilters,
1635
+ onFilterChange,
1636
+ controlledFiltering = false,
1637
+ ...rest
1638
+ } = props;
1639
+ const [filters, setFilters] = useState(initialFilters);
1640
+ const [hiddenFilters, setHiddenFilters] = useState([]);
1641
+ const filterGroupRef = useRef(null);
1642
+ const containerQuery = useContainerQuery(filterGroupRef);
1643
+ const showInlineFilters = containerQuery && containerQuery.name !== "xs" && containerQuery.name !== "sm";
1644
+ useEffect(() => {
1645
+ setFilters((prevFilters) => {
1646
+ return initialFilters.map((newFilter) => {
1647
+ const existingFilter = prevFilters.find((f) => f.id === newFilter.id);
1648
+ if (existingFilter) {
1649
+ switch (newFilter.type) {
1650
+ case "boolean":
1651
+ return {
1652
+ ...newFilter,
1653
+ checked: existingFilter.checked
1654
+ };
1655
+ case "singleSelect":
1656
+ return {
1657
+ ...newFilter,
1658
+ selectedItem: existingFilter.selectedItem
1659
+ };
1660
+ case "multiSelect":
1661
+ return {
1662
+ ...newFilter,
1663
+ selectedItems: existingFilter.selectedItems
1664
+ };
1665
+ case "date":
1666
+ return {
1667
+ ...newFilter,
1668
+ value: existingFilter.value
1669
+ };
1670
+ case "dateRange":
1671
+ return {
1672
+ ...newFilter,
1673
+ value: existingFilter.value
1674
+ };
1675
+ case "custom":
1676
+ return {
1677
+ ...newFilter,
1678
+ value: existingFilter.value
1679
+ };
1680
+ default:
1681
+ return newFilter;
1682
+ }
1683
+ }
1684
+ return newFilter;
1685
+ });
1686
+ });
1687
+ }, [initialFilters]);
1688
+ const updateFilter = useCallback(
1689
+ (filterId, value2, submit) => {
1690
+ setFilters((prevFilters) => {
1691
+ const updatedFilters = updateSingleFilter(
1692
+ prevFilters,
1693
+ filterId,
1694
+ value2
1695
+ );
1696
+ if (submit) {
1697
+ onFilterChange?.(updatedFilters);
1698
+ }
1699
+ return updatedFilters;
1700
+ });
1701
+ },
1702
+ [onFilterChange]
1703
+ );
1704
+ const addHiddenFilter = useCallback((filter) => {
1705
+ setHiddenFilters((prev) => [...prev, filter]);
1706
+ }, []);
1707
+ const removeHiddenFilter = useCallback((filter) => {
1708
+ setHiddenFilters((prev) => prev.filter((f) => f.id !== filter.id));
1709
+ }, []);
1710
+ const clearAllFilters = () => {
1711
+ const resetAllFilters = resetFilters(filters);
1712
+ setFilters(resetAllFilters);
1713
+ onFilterChange?.(resetAllFilters);
1714
+ setTimeout(() => {
1715
+ if (filterGroupRef.current) {
1716
+ const firstFocusable = filterGroupRef.current.querySelector(
1717
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1718
+ );
1719
+ if (firstFocusable) {
1720
+ firstFocusable.focus();
1721
+ }
1722
+ }
1723
+ }, 0);
1724
+ };
1725
+ const hasActiveFilters = checkActiveFilters(filters);
1726
+ const filterGroupControls = filters.map((filter) => {
1727
+ switch (filter.type) {
1728
+ case "boolean":
1729
+ return /* @__PURE__ */ jsx(
1730
+ FilterToggleButton,
1731
+ {
1732
+ id: filter.id,
1733
+ checked: filter.checked,
1734
+ onClick: () => {
1735
+ updateFilter(filter.id, !filter.checked, true);
1736
+ },
1737
+ children: filter.label
1738
+ },
1739
+ filter.id
1740
+ );
1741
+ case "custom":
1742
+ case "singleSelect":
1743
+ case "multiSelect":
1744
+ case "date":
1745
+ case "dateRange":
1746
+ return /* @__PURE__ */ jsx(FilterButton, { filter }, filter.id);
1747
+ // TODO: Add cases for other filter types here as needed
1748
+ default:
1749
+ return null;
1750
+ }
1751
+ });
1752
+ const value = useMemo(
1753
+ () => ({
1754
+ filterGroupRef,
1755
+ filters,
1756
+ updateFilter,
1757
+ onFilterChange,
1758
+ controlledFiltering,
1759
+ hiddenFilters,
1760
+ addHiddenFilter,
1761
+ removeHiddenFilter
1762
+ }),
1763
+ [
1764
+ filterGroupRef,
1765
+ filters,
1766
+ updateFilter,
1767
+ onFilterChange,
1768
+ controlledFiltering,
1769
+ hiddenFilters,
1770
+ addHiddenFilter,
1771
+ removeHiddenFilter
1772
+ ]
1773
+ );
1774
+ return /* @__PURE__ */ jsx(FilterGroupContext.Provider, { value, children: /* @__PURE__ */ jsxs(
1775
+ ToolbarControlGroup,
1776
+ {
1777
+ ref: useMergeRefs([filterGroupRef, ref]),
1778
+ "data-anv": "toolbar-filter-group",
1779
+ "aria-label": "Filter controls",
1780
+ ...rest,
1781
+ children: [
1782
+ showInlineFilters && filterGroupControls,
1783
+ /* @__PURE__ */ jsx(FilterDrawer, {}),
1784
+ showInlineFilters && hasActiveFilters && /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
1785
+ Button,
1786
+ {
1787
+ appearance: "ghost",
1788
+ size: "small",
1789
+ className: styles$2["filter-button-trigger"],
1790
+ icon: {
1791
+ before: SvgClose
1792
+ },
1793
+ onClick: clearAllFilters,
1794
+ children: "Clear Filters"
1795
+ }
1796
+ ) })
1797
+ ]
1798
+ }
1799
+ ) });
1800
+ }
1801
+ );
1802
+ FilterGroupElement.displayName = "FilterGroup";
1803
+ const FilterGroup = FilterGroupElement;
1804
+
1805
+ const styles = {
1806
+ "toolbar-search-field-container": "_toolbar-search-field-container_9jh3s_2",
1807
+ "toolbar-search-field": "_toolbar-search-field_9jh3s_2"
1808
+ };
1809
+
1810
+ const ToolbarSearchField = forwardRef(
1811
+ (props, ref) => {
1812
+ const { className, ...rest } = props;
1813
+ const searchFieldStyles = cx(styles["toolbar-search-field"], className);
1814
+ return /* @__PURE__ */ jsx("div", { className: styles["toolbar-search-field-container"], children: /* @__PURE__ */ jsx(
1815
+ SearchField,
1816
+ {
1817
+ ref,
1818
+ className: searchFieldStyles,
1819
+ size: "small",
1820
+ "data-anv": "toolbar-search-field",
1821
+ ...rest
1822
+ }
1823
+ ) });
1824
+ }
1825
+ );
1826
+ ToolbarSearchField.displayName = "ToolbarSearchField";
1827
+
1828
+ const ToolbarElement = forwardRef(
1829
+ (props, ref) => {
1830
+ const { layoutStyles, componentProps } = useLayoutPropsUtil(props);
1831
+ const {
1832
+ associatedContent,
1833
+ className,
1834
+ children,
1835
+ style,
1836
+ direction = "horizontal",
1837
+ overflow = "wrap",
1838
+ onKeyDown,
1839
+ additionalItems,
1840
+ ...rest
1841
+ } = componentProps;
1842
+ const [overflowItems, setOverflowItems] = useState([]);
1843
+ const toolbarItemsRef = useRef(null);
1844
+ const toolbarRef = useRef(null);
1845
+ const [orderedIds, setOrderedIds] = useState([]);
1846
+ useEffect(() => {
1847
+ const newOrderedIds = Array.from(
1848
+ toolbarItemsRef.current?.querySelectorAll("[data-id]") || []
1849
+ ).map((el) => {
1850
+ return el.getAttribute("data-id");
1851
+ });
1852
+ setOrderedIds(newOrderedIds);
1853
+ }, [children]);
1854
+ const addItem = useCallback((item) => {
1855
+ setOverflowItems((prev) => [...prev, item]);
1856
+ }, []);
1857
+ const removeItem = useCallback((item) => {
1858
+ setOverflowItems(
1859
+ (prev) => prev.filter((component) => component.id !== item.id)
1860
+ );
1861
+ }, []);
1862
+ useEffect(() => {
1863
+ if (toolbarRef.current) {
1864
+ updateToolbarItemsTabIndex(toolbarRef.current);
1865
+ }
1866
+ }, [children]);
1867
+ const handleKeyDown = useCallback(
1868
+ (event) => {
1869
+ if (toolbarRef.current) {
1870
+ handleToolbarKeyDown(event, toolbarRef.current);
1871
+ }
1872
+ onKeyDown?.(event);
1873
+ },
1874
+ [onKeyDown]
1875
+ );
1876
+ const showOverflowMenu = overflow === "collapse" && overflowItems.length > 0 || !!additionalItems;
1877
+ const value = useMemo(
1878
+ () => ({
1879
+ overflowItems,
1880
+ addItem,
1881
+ removeItem,
1882
+ toolbarRef,
1883
+ orderedIds,
1884
+ overflow
1885
+ }),
1886
+ [overflowItems, addItem, removeItem, toolbarRef, orderedIds, overflow]
1887
+ );
1888
+ const styleCombined = {
1889
+ ...style,
1890
+ ...layoutStyles
1891
+ };
1892
+ const toolbarClassNames = cx(styles$3["toolbar"], className);
1893
+ const toolbarContentClassNames = cx(styles$3["toolbar-content"], {
1894
+ [styles$3[`overflow-${overflow}`]]: overflow
1895
+ });
1896
+ return /* @__PURE__ */ jsx(ToolbarOverflowContext.Provider, { value, children: /* @__PURE__ */ jsxs(
1897
+ Flex,
1898
+ {
1899
+ direction: direction === "horizontal" ? "row" : "column",
1900
+ wrap: overflow === "wrap" ? "wrap" : "nowrap",
1901
+ alignItems: "center",
1902
+ className: toolbarClassNames,
1903
+ style: styleCombined,
1904
+ ref: useMergeRefs([toolbarRef, ref]),
1905
+ role: "toolbar",
1906
+ "data-anv": "toolbar",
1907
+ "aria-orientation": direction,
1908
+ "aria-label": `Toolbar for ${associatedContent}. Use arrow keys to navigate through toolbar controls.`,
1909
+ onKeyDown: handleKeyDown,
1910
+ ...rest,
1911
+ children: [
1912
+ /* @__PURE__ */ jsx(
1913
+ Flex,
1914
+ {
1915
+ ref: useMergeRefs([toolbarItemsRef, ref]),
1916
+ className: toolbarContentClassNames,
1917
+ direction: direction === "horizontal" ? "row" : "column",
1918
+ wrap: overflow === "wrap" ? "wrap" : "nowrap",
1919
+ alignItems: "center",
1920
+ grow: 1,
1921
+ "data-anv": "toolbar-content",
1922
+ "data-overflow": overflow,
1923
+ children
1924
+ }
1925
+ ),
1926
+ showOverflowMenu && /* @__PURE__ */ jsx(
1927
+ ToolbarOverflowMenu,
1928
+ {
1929
+ direction,
1930
+ additionalItems
1931
+ }
1932
+ )
1933
+ ]
1934
+ }
1935
+ ) });
1936
+ }
1937
+ );
1938
+ ToolbarElement.displayName = "Toolbar";
1939
+ const Toolbar = Object.assign(ToolbarElement, {
1940
+ /**
1941
+ * ToolbarButton component for standard clickable actions within a toolbar with anvil2 tracking.
1942
+ *
1943
+ * Features:
1944
+ * - Designed specifically for toolbar integration
1945
+ * - Consistent styling with other toolbar items
1946
+ * - Automatic tooltip for icon-only buttons
1947
+ * - Overflow menu support
1948
+ * - Accessibility enforcement for aria-labels
1949
+ * - Small size optimized for toolbar layout
1950
+ * - Ghost and primary appearance options
1951
+ * - Automatic tracking ID generation for analytics
1952
+ *
1953
+ * @example
1954
+ * <Toolbar.Button icon={BoldIcon} aria-label="Bold text" />
1955
+ *
1956
+ * @example
1957
+ * <Toolbar.Button appearance="primary">
1958
+ * Save
1959
+ * </Toolbar.Button>
1960
+ */
1961
+ Button: ToolbarButton,
1962
+ /**
1963
+ * ToolbarButtonToggle component for toggleable actions within a toolbar with anvil2 tracking.
1964
+ *
1965
+ * Features:
1966
+ * - Toggle state management
1967
+ * - Designed specifically for toolbar integration
1968
+ * - Consistent styling with other toolbar items
1969
+ * - Overflow menu support
1970
+ * - Accessibility enforcement for aria-labels
1971
+ * - Small size optimized for toolbar layout
1972
+ * - Ghost and primary appearance options
1973
+ * - Automatic tracking ID generation for analytics
1974
+ *
1975
+ * @example
1976
+ * <Toolbar.ButtonToggle icon={BoldIcon} aria-label="Bold" checked={isBold} />
1977
+ */
1978
+ ButtonToggle: ToolbarButtonToggle,
1979
+ /**
1980
+ * ToolbarButtonLink component for link actions within a toolbar with anvil2 tracking.
1981
+ *
1982
+ * Features:
1983
+ * - Link functionality with href support
1984
+ * - Designed specifically for toolbar integration
1985
+ * - Consistent styling with other toolbar items
1986
+ * - Overflow menu support
1987
+ * - Accessibility enforcement for aria-labels
1988
+ * - Small size optimized for toolbar layout
1989
+ * - Ghost and primary appearance options
1990
+ * - Automatic tracking ID generation for analytics
1991
+ *
1992
+ * @example
1993
+ * <Toolbar.ButtonLink href="/help">
1994
+ * Help
1995
+ * </Toolbar.ButtonLink>
1996
+ */
1997
+ ButtonLink: ToolbarButtonLink,
1998
+ /**
1999
+ * ToolbarSelect component provides a dropdown selector within a toolbar with anvil2 tracking.
2000
+ *
2001
+ * Features:
2002
+ * - Dropdown menu with selectable options
2003
+ * - Controlled and uncontrolled usage patterns
2004
+ * - Automatic overflow menu integration
2005
+ * - Accessibility support with proper ARIA labels
2006
+ * - Small size optimized for toolbar layout
2007
+ * - Ghost and primary appearance options
2008
+ * - Dropdown arrow icon indicator
2009
+ * - Listbox integration for keyboard navigation
2010
+ * - Automatic tracking ID generation for analytics
2011
+ *
2012
+ * @example
2013
+ * <Toolbar.Select
2014
+ * items={fontOptions}
2015
+ * selected="arial"
2016
+ * accessibleLabel="Font family"
2017
+ * onChange={(id) => setFont(id)}
2018
+ * />
2019
+ */
2020
+ Select: ToolbarSelect,
2021
+ /**
2022
+ * FilterGroup component displays a group of filters with toggles and a clear button.
2023
+ * Also contains the FilterDrawer for additional filter options.
2024
+ *
2025
+ * Features:
2026
+ * - Renders filter toggles and popovers for all filter types
2027
+ * - Supports controlled and uncontrolled filtering
2028
+ * - Integrates with FilterDrawer for batch filter editing
2029
+ * - Provides a clear all filters button
2030
+ * - Handles overflow and hidden filters
2031
+ * - Shares filter state via context for child components
2032
+ * - Supports boolean, custom, single-select, multi-select, date, and date range filter types
2033
+ * - Date filters include calendar popup for easy selection
2034
+ * - Date range filters support start and end date selection
2035
+ *
2036
+ * @example
2037
+ * <Toolbar.Filters
2038
+ * filters={filters}
2039
+ * onFilterChange={handleFilter}
2040
+ * controlledFiltering={true}
2041
+ * />
2042
+ */
2043
+ Filters: FilterGroup,
2044
+ /**
2045
+ * ToolbarControlGroup component provides a flex container for grouping related toolbar controls.
2046
+ * Can be used for filters, buttons, or other toolbar items.
2047
+ *
2048
+ * Features:
2049
+ * - Groups related toolbar controls in a flex container
2050
+ * - Supports accessibility with aria-label
2051
+ * - Handles overflow and wrapping based on toolbar context
2052
+ * - Integrates with layout utilities for spacing and alignment
2053
+ *
2054
+ * @example
2055
+ * <Toolbar.ControlGroup aria-label="Formatting controls">
2056
+ * <Toolbar.Button icon={BoldIcon} aria-label="Bold" />
2057
+ * <Toolbar.Button icon={ItalicIcon} aria-label="Italic" />
2058
+ * </Toolbar.ControlGroup>
2059
+ */
2060
+ ControlGroup: ToolbarControlGroup,
2061
+ /**
2062
+ * ToolbarSearchField component renders a small-sized search field for use in toolbars.
2063
+ *
2064
+ * Features:
2065
+ * - Renders a search field styled for toolbar usage
2066
+ * - Always uses small size for compact layout
2067
+ * - Supports all SearchField props except size
2068
+ * - Integrates with toolbar layouts and accessibility
2069
+ *
2070
+ * @example
2071
+ * <Toolbar.Search placeholder="Search..." />
2072
+ */
2073
+ Search: ToolbarSearchField
2074
+ });
2075
+
2076
+ export { Toolbar as T, ToolbarButton as a, ToolbarButtonToggle as b, ToolbarButtonLink as c, ToolbarSelect as d, ToolbarControlGroup as e, ToolbarSearchField as f, ToolbarElement as g };
2077
+ //# sourceMappingURL=Toolbar-D4zuUFhb.js.map