@servicetitan/anvil2 3.0.6 → 3.0.7

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 (163) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/Combobox.js +1 -2
  3. package/dist/Combobox.js.map +1 -1
  4. package/dist/{DataTable-0kOuVgSB.js → DataTable-E8z0H8c7.js} +140 -13
  5. package/dist/{DataTable-0kOuVgSB.js.map → DataTable-E8z0H8c7.js.map} +1 -1
  6. package/dist/DataTable.css +47 -5
  7. package/dist/{DateFieldRange-Be_I9GTp.js → DateFieldRange-BN_uIvHI.js} +24 -12
  8. package/dist/DateFieldRange-BN_uIvHI.js.map +1 -0
  9. package/dist/DateFieldRange.js +1 -1
  10. package/dist/{DateFieldSingle-CsrsY9i8.js → DateFieldSingle-h3YkdwPo.js} +2 -2
  11. package/dist/{DateFieldSingle-CsrsY9i8.js.map → DateFieldSingle-h3YkdwPo.js.map} +1 -1
  12. package/dist/DateFieldSingle.js +1 -1
  13. package/dist/{Dialog-CD-SDfPT.js → Dialog-CvYSMvfD.js} +2 -2
  14. package/dist/{Dialog-CD-SDfPT.js.map → Dialog-CvYSMvfD.js.map} +1 -1
  15. package/dist/Dialog.js +1 -1
  16. package/dist/FilterBar-B4ZAs73g.js +412 -0
  17. package/dist/FilterBar-B4ZAs73g.js.map +1 -0
  18. package/dist/FilterBar.js +1 -1
  19. package/dist/{ListView-CcRRh1ap.js → ListView-DO5psxd4.js} +5 -5
  20. package/dist/{ListView-CcRRh1ap.js.map → ListView-DO5psxd4.js.map} +1 -1
  21. package/dist/ListView.js +1 -1
  22. package/dist/{ListView.module-CKUQP3kf.js → ListView.module-DfqtCL3Q.js} +3 -3
  23. package/dist/ListView.module-DfqtCL3Q.js.map +1 -0
  24. package/dist/MultiSelectField.js +1 -1
  25. package/dist/{MultiSelectFieldSync-BMVROOjy.js → MultiSelectFieldSync-CXX2F0ru.js} +59 -29
  26. package/dist/MultiSelectFieldSync-CXX2F0ru.js.map +1 -0
  27. package/dist/MultiSelectFieldSync.css +72 -69
  28. package/dist/MultiSelectMenu.js +1 -1
  29. package/dist/{MultiSelectMenuSync-BNPp_2Bm.js → MultiSelectMenuSync-EKtvlL62.js} +218 -47
  30. package/dist/MultiSelectMenuSync-EKtvlL62.js.map +1 -0
  31. package/dist/{Page-SBy27-Wv.js → Page-C2_Hm27h.js} +2 -2
  32. package/dist/{Page-SBy27-Wv.js.map → Page-C2_Hm27h.js.map} +1 -1
  33. package/dist/Page.js +1 -1
  34. package/dist/{Pagination-Cm8-K6VH.js → Pagination-Bmd4JORe.js} +2 -2
  35. package/dist/{Pagination-Cm8-K6VH.js.map → Pagination-Bmd4JORe.js.map} +1 -1
  36. package/dist/Pagination.js +1 -1
  37. package/dist/SavedFiltersButton-2qba2Cgu.js +650 -0
  38. package/dist/SavedFiltersButton-2qba2Cgu.js.map +1 -0
  39. package/dist/SavedFiltersButton.css +8 -0
  40. package/dist/SavedFiltersButton.d.ts +1 -0
  41. package/dist/SavedFiltersButton.js +2 -0
  42. package/dist/SavedFiltersButton.js.map +1 -0
  43. package/dist/{SearchField-3tUPU8hH.js → SearchField-BMHJCVFu.js} +2 -2
  44. package/dist/{SearchField-3tUPU8hH.js.map → SearchField-BMHJCVFu.js.map} +1 -1
  45. package/dist/{SearchField-BcQZ5e0x.js → SearchField-fXc_vWEr.js} +2 -2
  46. package/dist/{SearchField-BcQZ5e0x.js.map → SearchField-fXc_vWEr.js.map} +1 -1
  47. package/dist/SearchField.js +1 -1
  48. package/dist/SelectField.js +1 -1
  49. package/dist/{SelectFieldSync-BeDYbJ2M.js → SelectFieldSync-DykGkR_w.js} +3 -3
  50. package/dist/{SelectFieldSync-BeDYbJ2M.js.map → SelectFieldSync-DykGkR_w.js.map} +1 -1
  51. package/dist/SelectMenu.js +1 -1
  52. package/dist/{SelectMenuSync-C-PFemsQ.js → SelectMenuSync-DTQ8Ofoz.js} +21 -9
  53. package/dist/SelectMenuSync-DTQ8Ofoz.js.map +1 -0
  54. package/dist/{SelectOptions-Tr11Ckqw.js → SelectOptions-DVSOJwRy.js} +2 -2
  55. package/dist/{SelectOptions-Tr11Ckqw.js.map → SelectOptions-DVSOJwRy.js.map} +1 -1
  56. package/dist/{SelectTrigger-DTz7V-Xx.js → SelectTrigger-CHk0KO-P.js} +2 -2
  57. package/dist/{SelectTrigger-DTz7V-Xx.js.map → SelectTrigger-CHk0KO-P.js.map} +1 -1
  58. package/dist/SelectTrigger.js +1 -1
  59. package/dist/{SelectTriggerBase-Ds6I7Qbr.js → SelectTriggerBase-B2S5SOZr.js} +134 -38
  60. package/dist/SelectTriggerBase-B2S5SOZr.js.map +1 -0
  61. package/dist/Table.js +1 -1
  62. package/dist/{Toolbar-BUd9eNkq.js → Toolbar-DaUKbbsL.js} +3 -3
  63. package/dist/{Toolbar-BUd9eNkq.js.map → Toolbar-DaUKbbsL.js.map} +1 -1
  64. package/dist/Toolbar.js +2 -2
  65. package/dist/{ToolbarButtonToggle-C06cqJ6F.js → ToolbarButtonToggle-BPu81Wuv.js} +4 -3
  66. package/dist/ToolbarButtonToggle-BPu81Wuv.js.map +1 -0
  67. package/dist/beta.js +10 -9
  68. package/dist/beta.js.map +1 -1
  69. package/dist/filter-state-Bx3aYS1r.js +1627 -0
  70. package/dist/filter-state-Bx3aYS1r.js.map +1 -0
  71. package/dist/{FilterBar.css → filter-state.css} +19 -33
  72. package/dist/index.js +9 -10
  73. package/dist/index.js.map +1 -1
  74. package/dist/src/beta/components/FilterBar/FilterBar.d.ts +12 -10
  75. package/dist/src/beta/components/FilterBar/FilterDateList.d.ts +15 -5
  76. package/dist/src/beta/components/FilterBar/FilterDateRange.d.ts +34 -29
  77. package/dist/src/beta/components/FilterBar/FilterDateSingle.d.ts +31 -22
  78. package/dist/src/beta/components/FilterBar/FilterDrawer.d.ts +1 -1
  79. package/dist/src/beta/components/FilterBar/FilterItemWrapper.d.ts +4 -12
  80. package/dist/src/beta/components/FilterBar/FilterNumericRange.d.ts +29 -0
  81. package/dist/src/beta/components/FilterBar/FilterPopoverButton.d.ts +86 -0
  82. package/dist/src/beta/components/FilterBar/FilterToggleButton.d.ts +2 -2
  83. package/dist/src/beta/components/FilterBar/FilterTriggerButton.d.ts +50 -0
  84. package/dist/src/beta/components/FilterBar/index.d.ts +1 -1
  85. package/dist/src/beta/components/FilterBar/internal/FilterGroupContext.d.ts +5 -9
  86. package/dist/src/beta/components/FilterBar/internal/adapters/asyncMultiSelect.d.ts +6 -0
  87. package/dist/src/beta/components/FilterBar/internal/adapters/asyncSelect.d.ts +6 -0
  88. package/dist/src/beta/components/FilterBar/internal/adapters/boolean.d.ts +3 -0
  89. package/dist/src/beta/components/FilterBar/internal/adapters/custom.d.ts +3 -0
  90. package/dist/src/beta/components/FilterBar/internal/adapters/date.d.ts +5 -0
  91. package/dist/src/beta/components/FilterBar/internal/adapters/dateList.d.ts +5 -0
  92. package/dist/src/beta/components/FilterBar/internal/adapters/dateRange.d.ts +8 -0
  93. package/dist/src/beta/components/FilterBar/internal/adapters/index.d.ts +15 -0
  94. package/dist/src/beta/components/FilterBar/internal/adapters/multiSelect.d.ts +6 -0
  95. package/dist/src/beta/components/FilterBar/internal/adapters/numericRange.d.ts +3 -0
  96. package/dist/src/beta/components/FilterBar/internal/adapters/singleSelect.d.ts +6 -0
  97. package/dist/src/beta/components/FilterBar/internal/adapters/types.d.ts +78 -0
  98. package/dist/src/beta/components/FilterBar/internal/types.d.ts +166 -61
  99. package/dist/src/beta/components/FilterBar/internal/utils/dateListLibraryOptions.d.ts +2 -2
  100. package/dist/src/beta/components/FilterBar/internal/utils/filter-state.d.ts +2 -40
  101. package/dist/src/beta/components/FilterBar/internal/utils/test.d.ts +13 -28
  102. package/dist/src/beta/components/FilterBar/internal/utils/value-compare.d.ts +14 -0
  103. package/dist/src/beta/components/MultiSelectField/internal/MultiSelectFieldComboboxMode.d.ts +1 -1
  104. package/dist/src/beta/components/MultiSelectField/internal/MultiSelectFieldSelectMode.d.ts +1 -1
  105. package/dist/src/beta/components/MultiSelectField/internal/types.d.ts +4 -2
  106. package/dist/src/beta/components/MultiSelectField/internal/useComboMultiple.d.ts +7 -5
  107. package/dist/src/beta/components/MultiSelectField/internal/useSelectModeMultiple.d.ts +5 -2
  108. package/dist/src/beta/components/MultiSelectField/types.d.ts +21 -36
  109. package/dist/src/beta/components/MultiSelectMenu/MultiSelectMenu.d.ts +1 -0
  110. package/dist/src/beta/components/MultiSelectMenu/types.d.ts +52 -12
  111. package/dist/src/beta/components/SavedFiltersButton/SavedFiltersButton.d.ts +40 -0
  112. package/dist/src/beta/components/SavedFiltersButton/index.d.ts +2 -0
  113. package/dist/src/beta/components/SavedFiltersButton/internal/AddSavedFilterDrawer.d.ts +27 -0
  114. package/dist/src/beta/components/SavedFiltersButton/internal/EditSavedFiltersDrawer.d.ts +38 -0
  115. package/dist/src/beta/components/SavedFiltersButton/types.d.ts +147 -0
  116. package/dist/src/beta/components/SelectField/types.d.ts +7 -11
  117. package/dist/src/beta/components/SelectMenu/internal/useMenuInteraction.d.ts +8 -1
  118. package/dist/src/beta/components/SelectMenu/types.d.ts +21 -1
  119. package/dist/src/beta/components/Table/DataTable/internal/DataTablePagination.d.ts +6 -0
  120. package/dist/src/beta/components/Table/DataTable/types.d.ts +43 -10
  121. package/dist/src/beta/components/Toolbar/internal/ToolbarContext.d.ts +3 -2
  122. package/dist/src/beta/components/index.d.ts +1 -0
  123. package/dist/src/internal/components/MenuFooter/MenuFooter.d.ts +43 -0
  124. package/dist/src/internal/components/OptionCheckbox.d.ts +6 -0
  125. package/dist/src/internal/components/OptionContentArea.d.ts +8 -0
  126. package/dist/src/internal/components/OptionRow.d.ts +10 -0
  127. package/dist/src/internal/components/OptionsPopover/OptionsPopover.d.ts +4 -4
  128. package/dist/src/internal/hooks/index.d.ts +2 -0
  129. package/dist/src/internal/hooks/useBulkActionRunner.d.ts +41 -0
  130. package/dist/src/internal/hooks/useConfirmationDraft.d.ts +21 -0
  131. package/dist/src/internal/types/bulkActionTypes.d.ts +39 -0
  132. package/dist/src/internal/types/confirmationTypes.d.ts +19 -0
  133. package/dist/src/internal/types/optionContent.d.ts +19 -0
  134. package/dist/src/internal/types/selectFieldInternalTypes.d.ts +2 -0
  135. package/dist/{syncFilterUtils-COxBIkt6.js → syncFilterUtils-BEKek64h.js} +163 -124
  136. package/dist/syncFilterUtils-BEKek64h.js.map +1 -0
  137. package/dist/syncFilterUtils.css +96 -59
  138. package/dist/{Combobox-Cp7M4-4r.js → useInfiniteCombobox-CknXmqlQ.js} +185 -10
  139. package/dist/useInfiniteCombobox-CknXmqlQ.js.map +1 -0
  140. package/dist/{useMenuInteraction-C4RU5Fdq.js → useMenuInteraction-CpAOHSJu.js} +118 -5
  141. package/dist/useMenuInteraction-CpAOHSJu.js.map +1 -0
  142. package/dist/useMenuInteraction.css +28 -0
  143. package/dist/{useToggleSelection-B5PnTuT2.js → useToggleSelection-B-Z80gy2.js} +53 -4
  144. package/dist/useToggleSelection-B-Z80gy2.js.map +1 -0
  145. package/package.json +3 -3
  146. package/dist/Combobox-Cp7M4-4r.js.map +0 -1
  147. package/dist/DateFieldRange-Be_I9GTp.js.map +0 -1
  148. package/dist/FilterBar-yysyZ-t1.js +0 -1797
  149. package/dist/FilterBar-yysyZ-t1.js.map +0 -1
  150. package/dist/ListView.module-CKUQP3kf.js.map +0 -1
  151. package/dist/MultiSelectFieldSync-BMVROOjy.js.map +0 -1
  152. package/dist/MultiSelectMenuSync-BNPp_2Bm.js.map +0 -1
  153. package/dist/SelectMenuSync-C-PFemsQ.js.map +0 -1
  154. package/dist/SelectTriggerBase-Ds6I7Qbr.js.map +0 -1
  155. package/dist/ToolbarButtonToggle-C06cqJ6F.js.map +0 -1
  156. package/dist/src/beta/components/FilterBar/FilterButton.d.ts +0 -33
  157. package/dist/src/beta/components/FilterBar/FilterSelect.d.ts +0 -29
  158. package/dist/syncFilterUtils-COxBIkt6.js.map +0 -1
  159. package/dist/useInfiniteCombobox-WcRgC9p6.js +0 -179
  160. package/dist/useInfiniteCombobox-WcRgC9p6.js.map +0 -1
  161. package/dist/useMenuInteraction-C4RU5Fdq.js.map +0 -1
  162. package/dist/useToggleSelection-B5PnTuT2.js.map +0 -1
  163. /package/dist/{Combobox.css → useInfiniteCombobox.css} +0 -0
@@ -1,1797 +0,0 @@
1
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import * as React from 'react';
3
- import { useState, useEffect, createContext, useContext, useCallback, useMemo, useRef, forwardRef } from 'react';
4
- import { S as SvgClose } from './close-DZj38AEh.js';
5
- import { b as ToolbarItemWrapper, T as ToolbarButtonToggle, a as useToolbarSize, d as updateToolbarItemsTabIndex, e as handleToolbarKeyDown, c as ToolbarContext } from './ToolbarButtonToggle-C06cqJ6F.js';
6
- import { B as Button } from './Button-C_V2xQAs.js';
7
- import { S as SvgKeyboardArrowDown } from './keyboard_arrow_down-C8WQ38p1.js';
8
- import { S as SvgEvent } from './TimezoneMessage-BrKB_psP.js';
9
- import { D as DateTime } from './luxon-wpz4A-OQ.js';
10
- import { C as Chip } from './Chip-D2k5X_wX.js';
11
- import { t as tabbable } from './usePopoverTransitionStates-CDXCdyKa.js';
12
- import { L as Listbox } from './Listbox-CvQHBFWb.js';
13
- import { L as ListView } from './ListView-CcRRh1ap.js';
14
- import { S as SearchField } from './SearchField-3tUPU8hH.js';
15
- import { F as Flex } from './Flex-_orhvoxS.js';
16
- import { u as useDateFieldSingleConversion, a as useDateFieldSingleState, M as MaskedDateInput, b as DateFieldSingleCalendar, D as DateFieldSingle } from './DateFieldSingle-CsrsY9i8.js';
17
- import { u as useDateFieldRangeConversion, a as useDateFieldRangeState, M as MaskedDateRangeInput, b as DateFieldRangeCalendar, D as DateFieldRange } from './DateFieldRange-Be_I9GTp.js';
18
- import { D as Dialog } from './Dialog-CD-SDfPT.js';
19
- import { w as warnOnce } from './warnOnce-Y9PRHcU4.js';
20
- import { c as cx } from './index-De1g9FRV.js';
21
- import { P as Popover } from './AiMark-BXL0sWIV.js';
22
- import { a as SvgSearch } from './SearchField-BcQZ5e0x.js';
23
- import { C as Checkbox } from './Checkbox-BeIzx_ZX.js';
24
- import { R as Radio } from './Radio-BcHMk8dD.js';
25
- import { C as Combobox } from './Combobox-Cp7M4-4r.js';
26
- import { a as SelectFieldSync } from './SelectFieldSync-BeDYbJ2M.js';
27
- import { B as ButtonToggle } from './ButtonToggle-jnDMPSyK.js';
28
- import { D as Drawer } from './Drawer-s2y0xcgV.js';
29
- import { d as BreakpointSm, c as BreakpointMd, b as BreakpointLg, a as BreakpointXl, B as BreakpointXxl } from './primitive-DXlHdTFb.js';
30
- import { u as useLayoutPropsUtil } from './useLayoutPropsUtil-CB_zHDbW.js';
31
- import { u as useMergeRefs } from './useMergeRefs-Dfmtq9cI.js';
32
-
33
- import './FilterBar.css';function containerBreakpoint(containerWidth, name, min, max) {
34
- if ((min == null || containerWidth >= min) && (max == null || containerWidth < max)) {
35
- return {
36
- name,
37
- min,
38
- max,
39
- containerWidth,
40
- containerHeight: 0
41
- // Will be updated with actual height
42
- };
43
- }
44
- return void 0;
45
- }
46
- const getContainerBreakpoint = (containerWidth, containerHeight) => {
47
- if (!BreakpointSm) return;
48
- if (!BreakpointMd) return;
49
- if (!BreakpointLg) return;
50
- if (!BreakpointXl) return;
51
- if (!BreakpointXxl) return;
52
- const sm = parseInt(BreakpointSm.value);
53
- const md = parseInt(BreakpointMd.value);
54
- const lg = parseInt(BreakpointLg.value);
55
- const xl = parseInt(BreakpointXl.value);
56
- const xxl = parseInt(BreakpointXxl.value);
57
- 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);
58
- return result ? { ...result, containerHeight } : void 0;
59
- };
60
- const useContainerQuery = (containerRef, props) => {
61
- const [size, setSize] = useState(
62
- void 0
63
- );
64
- useEffect(() => {
65
- if (!containerRef.current) return;
66
- const resizeObserver = new ResizeObserver((entries) => {
67
- for (const entry of entries) {
68
- const { width, height } = entry.contentRect;
69
- const breakpoint = getContainerBreakpoint(width, height);
70
- setSize(breakpoint);
71
- }
72
- });
73
- resizeObserver.observe(containerRef.current);
74
- const rect = containerRef.current.getBoundingClientRect();
75
- setSize(getContainerBreakpoint(rect.width, rect.height));
76
- return () => {
77
- resizeObserver.disconnect();
78
- };
79
- }, [containerRef, props?.disable]);
80
- return size;
81
- };
82
-
83
- const FilterGroupContext = createContext({
84
- filterGroupRef: { current: null },
85
- filters: [],
86
- updateFilter: () => {
87
- },
88
- onFilterChange: () => {
89
- },
90
- controlledFiltering: false,
91
- associatedContent: "",
92
- hiddenFilters: [],
93
- addHiddenFilter: () => {
94
- },
95
- removeHiddenFilter: () => {
96
- }
97
- });
98
-
99
- const styles = {
100
- "filter-button-trigger": "_filter-button-trigger_1ky9m_1",
101
- "filter-button-trigger--selected": "_filter-button-trigger--selected_1ky9m_5",
102
- "filter-button-content": "_filter-button-content_1ky9m_14",
103
- "filter-select-content": "_filter-select-content_1ky9m_19",
104
- "filter-button-buttons": "_filter-button-buttons_1ky9m_25",
105
- "filter-drawer-trigger": "_filter-drawer-trigger_1ky9m_29",
106
- "filter-drawer-trigger--chipped": "_filter-drawer-trigger--chipped_1ky9m_41",
107
- "filter-item": "_filter-item_1ky9m_65",
108
- "filter-select-search": "_filter-select-search_1ky9m_70"
109
- };
110
-
111
- const FilterItemWrapper = ({
112
- filter,
113
- children
114
- }) => {
115
- const { addHiddenFilter, removeHiddenFilter, filterGroupRef } = useContext(FilterGroupContext);
116
- const handleVisibilityChange = useCallback(
117
- (isVisible) => {
118
- if (filter) {
119
- if (isVisible) {
120
- removeHiddenFilter?.(filter);
121
- } else {
122
- addHiddenFilter?.(filter);
123
- }
124
- }
125
- },
126
- [filter, addHiddenFilter, removeHiddenFilter]
127
- );
128
- const props = useMemo(
129
- () => ({
130
- item: {
131
- itemType: "button",
132
- itemProps: {
133
- children: null,
134
- "aria-hidden": true
135
- }
136
- },
137
- children,
138
- className: styles["filter-item"],
139
- observerRoot: filterGroupRef.current,
140
- onVisibilityChange: handleVisibilityChange,
141
- rootMargin: "0px -80px 0px 0px"
142
- }),
143
- [children, filterGroupRef, handleVisibilityChange]
144
- );
145
- return /* @__PURE__ */ jsx(ToolbarItemWrapper, { ...props });
146
- };
147
-
148
- const getActiveFilters = (filters) => {
149
- return filters.filter((filter) => {
150
- switch (filter.type) {
151
- case "boolean":
152
- return filter.checked;
153
- case "custom":
154
- return filter.value !== void 0;
155
- case "singleSelect":
156
- return filter.selectedItem !== void 0;
157
- case "multiSelect":
158
- return filter.selectedItems && filter.selectedItems.length > 0;
159
- case "date":
160
- return filter.value !== null && filter.value !== void 0;
161
- case "dateRange":
162
- return filter.value !== null && filter.value !== void 0 && filter.value.startDate !== null && filter.value.endDate !== null;
163
- case "dateList":
164
- return filter.selectedOption !== void 0 && filter.selectedOption.value !== null;
165
- default:
166
- return false;
167
- }
168
- });
169
- };
170
- const checkActiveFilters = (filters) => {
171
- return getActiveFilters(filters).length > 0;
172
- };
173
- const resetFilters = (filters) => {
174
- return filters.map((filter) => {
175
- switch (filter.type) {
176
- case "boolean":
177
- return {
178
- ...filter,
179
- checked: false
180
- };
181
- case "custom":
182
- return {
183
- ...filter,
184
- value: void 0
185
- };
186
- case "singleSelect":
187
- return {
188
- ...filter,
189
- selectedItem: void 0
190
- };
191
- case "multiSelect":
192
- return {
193
- ...filter,
194
- selectedItems: []
195
- };
196
- case "date":
197
- case "dateRange":
198
- return {
199
- ...filter,
200
- value: null
201
- };
202
- case "dateList":
203
- return {
204
- ...filter,
205
- selectedOption: void 0
206
- };
207
- default:
208
- return filter;
209
- }
210
- });
211
- };
212
- const updateSingleFilter = (filters, filterId, value) => {
213
- return filters.map((filter) => {
214
- if (filter.id !== filterId) return filter;
215
- switch (filter.type) {
216
- case "boolean":
217
- return {
218
- ...filter,
219
- checked: value
220
- };
221
- case "singleSelect":
222
- return {
223
- ...filter,
224
- selectedItem: value
225
- };
226
- case "multiSelect":
227
- return {
228
- ...filter,
229
- selectedItems: value
230
- };
231
- case "date":
232
- return {
233
- ...filter,
234
- value
235
- };
236
- case "dateRange":
237
- return {
238
- ...filter,
239
- value
240
- };
241
- case "dateList":
242
- return {
243
- ...filter,
244
- selectedOption: value
245
- };
246
- case "custom":
247
- return {
248
- ...filter,
249
- value
250
- };
251
- default:
252
- return filter;
253
- }
254
- });
255
- };
256
- const hasChangedFilter = (a, b) => {
257
- if (Array.isArray(a) && Array.isArray(b)) {
258
- if (a.length !== b.length) return true;
259
- if (a.length === 0) return false;
260
- const aItems = a;
261
- const bItems = b;
262
- if (aItems[0] && "id" in aItems[0]) {
263
- const aIds = new Set(aItems.map((item) => item.id));
264
- return bItems.some(
265
- (item) => !aIds.has(item.id)
266
- );
267
- }
268
- return JSON.stringify(a) !== JSON.stringify(b);
269
- }
270
- if (a && b && typeof a === "object" && typeof b === "object" && "id" in a && "id" in b) {
271
- if (a.id !== b.id) return true;
272
- if ("value" in a && "value" in b) {
273
- return JSON.stringify(a.value) !== JSON.stringify(b.value);
274
- }
275
- return false;
276
- }
277
- return a !== b;
278
- };
279
- const getFilterSelectionValue = (filter) => {
280
- switch (filter.type) {
281
- case "boolean":
282
- return filter.checked;
283
- case "singleSelect":
284
- return filter.selectedItem;
285
- case "multiSelect":
286
- return filter.selectedItems;
287
- case "date":
288
- case "dateRange":
289
- case "custom":
290
- return filter.value;
291
- case "dateList":
292
- return filter.selectedOption;
293
- default:
294
- return void 0;
295
- }
296
- };
297
- const hasFilterSelectionChanged = (existingFilter, newFilter) => {
298
- const existingValue = getFilterSelectionValue(existingFilter);
299
- const newValue = getFilterSelectionValue(newFilter);
300
- return existingValue !== newValue;
301
- };
302
- const preserveFilterState = (newFilter, existingFilter) => {
303
- switch (newFilter.type) {
304
- case "boolean":
305
- return {
306
- ...newFilter,
307
- checked: existingFilter.checked
308
- };
309
- case "singleSelect":
310
- return {
311
- ...newFilter,
312
- selectedItem: existingFilter.selectedItem
313
- };
314
- case "multiSelect":
315
- return {
316
- ...newFilter,
317
- selectedItems: existingFilter.selectedItems
318
- };
319
- case "date":
320
- return {
321
- ...newFilter,
322
- value: existingFilter.value
323
- };
324
- case "dateRange":
325
- return {
326
- ...newFilter,
327
- value: existingFilter.value
328
- };
329
- case "custom":
330
- return {
331
- ...newFilter,
332
- value: existingFilter.value
333
- };
334
- case "dateList":
335
- return {
336
- ...newFilter,
337
- selectedOption: existingFilter.selectedOption
338
- };
339
- default:
340
- return newFilter;
341
- }
342
- };
343
- const cloneFiltersWithItemRefs = (filters) => {
344
- return filters.map((filter) => {
345
- switch (filter.type) {
346
- case "singleSelect":
347
- return {
348
- ...filter,
349
- selectedItem: filter.selectedItem ? filter.items.find(
350
- (item) => item.id === filter.selectedItem?.id
351
- ) || filter.selectedItem : void 0
352
- };
353
- case "multiSelect":
354
- return {
355
- ...filter,
356
- selectedItems: filter.selectedItems ? filter.selectedItems.map(
357
- (selectedItem) => filter.items.find((item) => item.id === selectedItem.id) || selectedItem
358
- ) : []
359
- };
360
- case "date":
361
- return {
362
- ...filter,
363
- value: filter.value
364
- };
365
- case "dateRange":
366
- return {
367
- ...filter,
368
- value: filter.value
369
- };
370
- case "dateList":
371
- return { ...filter };
372
- case "custom": {
373
- const { value } = filter;
374
- if (value === void 0) {
375
- return { ...filter, value: void 0 };
376
- }
377
- if (Array.isArray(value)) {
378
- return { ...filter, value: [...value] };
379
- }
380
- if (typeof value === "object" && value !== null) {
381
- return { ...filter, value: { ...value } };
382
- }
383
- return { ...filter, value };
384
- }
385
- default:
386
- return { ...filter };
387
- }
388
- });
389
- };
390
-
391
- const FilterToggleButton = ({
392
- id,
393
- checked,
394
- children,
395
- ...props
396
- }) => {
397
- const filter = {
398
- id,
399
- type: "boolean",
400
- checked,
401
- label: typeof children === "string" ? children : id
402
- };
403
- return /* @__PURE__ */ jsx(FilterItemWrapper, { filter, children: /* @__PURE__ */ jsx(
404
- ToolbarButtonToggle,
405
- {
406
- checked,
407
- isFilter: true,
408
- ...props,
409
- className: styles["filter-button-trigger"],
410
- "data-anv": "toolbar-boolean-filter",
411
- children
412
- }
413
- ) });
414
- };
415
-
416
- const LIBRARY_OPTION_LABELS = {
417
- on: "On",
418
- before: "Before",
419
- after: "After",
420
- customRange: "Custom Range"
421
- };
422
- const LIBRARY_OPTION_IDS_ORDERED = [
423
- "on",
424
- "before",
425
- "after",
426
- "customRange"
427
- ];
428
- const LIBRARY_OPTION_ID_SET = new Set(LIBRARY_OPTION_IDS_ORDERED);
429
- const isDateListLibraryOptionId = (id) => LIBRARY_OPTION_ID_SET.has(id);
430
- const getDateListLibraryOptionLabel = (id) => LIBRARY_OPTION_LABELS[id];
431
- const dateListLibraryOptions = LIBRARY_OPTION_IDS_ORDERED.map((id) => ({
432
- id,
433
- label: `${LIBRARY_OPTION_LABELS[id]}…`
434
- }));
435
- const isDateListRangeLibraryId = (id) => id === "customRange";
436
- const formatDateForLabel = (iso) => {
437
- const d = DateTime.fromISO(iso, { zone: "local" });
438
- return `${d.monthShort} ${d.day}, ${d.year}`;
439
- };
440
- const formatRangeForLabel = (range) => {
441
- const start = DateTime.fromISO(range.startDate, { zone: "local" });
442
- const end = DateTime.fromISO(range.endDate, { zone: "local" });
443
- const sameYear = start.year === end.year;
444
- const formattedStart = sameYear ? `${start.monthShort} ${start.day}` : `${start.monthShort} ${start.day}, ${start.year}`;
445
- return `${formattedStart} – ${end.monthShort} ${end.day}, ${end.year}`;
446
- };
447
- const formatDateListSelectionLabel = (selection) => {
448
- if (selection.value === null) return selection.label;
449
- const formatted = typeof selection.value === "string" ? formatDateForLabel(selection.value) : formatRangeForLabel(selection.value);
450
- if (selection.id === "customRange") return formatted;
451
- return `${selection.label}: ${formatted}`;
452
- };
453
-
454
- const FilterSelect = ({
455
- filter,
456
- draftValue,
457
- onDraftChange
458
- }) => {
459
- const isMultiSelect = filter.type === "multiSelect";
460
- const listRef = useRef(null);
461
- const shouldStabilizeItems = isMultiSelect && filter.hasSearch;
462
- const [stableItems, setStableItems] = useState(filter.items);
463
- const isSearchActiveRef = useRef(false);
464
- const expectingSearchUpdate = useRef(false);
465
- const displayItems = shouldStabilizeItems ? stableItems : filter.items;
466
- useEffect(() => {
467
- if (!shouldStabilizeItems) return;
468
- if (expectingSearchUpdate.current) {
469
- setStableItems(filter.items);
470
- expectingSearchUpdate.current = false;
471
- } else if (!isSearchActiveRef.current) {
472
- setStableItems(filter.items);
473
- }
474
- }, [filter.items, shouldStabilizeItems]);
475
- const handleSearch = useCallback(
476
- (e) => {
477
- const { value } = e.target;
478
- filter.onSearch?.(value);
479
- if (shouldStabilizeItems) {
480
- if (value.length > 0) {
481
- isSearchActiveRef.current = true;
482
- expectingSearchUpdate.current = true;
483
- } else {
484
- isSearchActiveRef.current = false;
485
- }
486
- }
487
- },
488
- [filter, shouldStabilizeItems]
489
- );
490
- const handleSearchClear = useCallback(() => {
491
- filter.onSearchClear?.();
492
- if (shouldStabilizeItems) {
493
- isSearchActiveRef.current = false;
494
- }
495
- }, [filter, shouldStabilizeItems]);
496
- const handleSearchKeyDown = useCallback(
497
- (e) => {
498
- if (e.key === "ArrowDown" && listRef.current) {
499
- e.preventDefault();
500
- const focusableElements = tabbable(listRef.current);
501
- if (focusableElements.length > 0) {
502
- focusableElements[0].focus();
503
- }
504
- }
505
- },
506
- []
507
- );
508
- const singleSelectList = useMemo(
509
- () => /* @__PURE__ */ jsx("div", { ref: listRef, children: /* @__PURE__ */ jsx(
510
- Listbox,
511
- {
512
- items: filter.items,
513
- selected: draftValue,
514
- onSelectionChange: (selected) => {
515
- onDraftChange(selected);
516
- },
517
- disableAutoSelectOnFocus: true,
518
- style: { paddingInline: "1rem", paddingBlockStart: "1rem" },
519
- children: ({ items }) => items.map((item) => /* @__PURE__ */ jsx(
520
- Listbox.Option,
521
- {
522
- item,
523
- disabled: item.disabled,
524
- children: item.label
525
- },
526
- item.id
527
- ))
528
- },
529
- filter.id
530
- ) }),
531
- [filter.id, filter.items, draftValue, onDraftChange]
532
- );
533
- const multiSelectList = useMemo(
534
- () => /* @__PURE__ */ jsx("div", { ref: listRef, children: /* @__PURE__ */ jsx(
535
- ListView,
536
- {
537
- items: displayItems,
538
- selected: Array.isArray(draftValue) ? draftValue : [],
539
- onSelectionChange: (selectedItems) => {
540
- const items = selectedItems;
541
- onDraftChange(items);
542
- },
543
- style: { paddingInline: "1rem", paddingBlockStart: "1rem" },
544
- children: ({ items }) => items.map((item) => /* @__PURE__ */ jsx(ListView.Option, { item, children: item.label }, item.id))
545
- },
546
- filter.id
547
- ) }),
548
- [filter.id, displayItems, draftValue, onDraftChange]
549
- );
550
- return /* @__PURE__ */ jsxs(Fragment, { children: [
551
- filter.hasSearch && /* @__PURE__ */ jsx(
552
- SearchField,
553
- {
554
- size: "small",
555
- className: styles["filter-select-search"],
556
- onChange: handleSearch,
557
- onClear: handleSearchClear,
558
- onKeyDown: handleSearchKeyDown,
559
- "data-anv": "filter-select-search"
560
- }
561
- ),
562
- isMultiSelect ? multiSelectList : singleSelectList
563
- ] });
564
- };
565
-
566
- const FilterDateSingle = ({
567
- filter,
568
- draftValue,
569
- onDraftChange
570
- }) => {
571
- const maskedDateInputRef = useRef(null);
572
- const handleChange = (change) => {
573
- onDraftChange(change.date);
574
- };
575
- const { value, onChange } = useDateFieldSingleConversion({
576
- value: draftValue,
577
- onChange: handleChange
578
- });
579
- const { handleInputChange, handleCalendarSelection } = useDateFieldSingleState({
580
- valueProp: value,
581
- onChange: (change) => onChange({ ...change, isDateValid: true })
582
- });
583
- return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
584
- /* @__PURE__ */ jsx(
585
- MaskedDateInput,
586
- {
587
- mode: filter.mode,
588
- ref: maskedDateInputRef,
589
- onChange: handleInputChange,
590
- lastValidDate: value ?? null,
591
- autoComplete: "off"
592
- }
593
- ),
594
- /* @__PURE__ */ jsx(
595
- DateFieldSingleCalendar,
596
- {
597
- value: value ?? null,
598
- onSelection: handleCalendarSelection
599
- }
600
- )
601
- ] });
602
- };
603
-
604
- const FilterDateRange = ({
605
- filter,
606
- draftValue,
607
- onDraftChange
608
- }) => {
609
- const maskedDateRangeInputRef = useRef(null);
610
- const handleChange = (change) => {
611
- const hasCompleteRange = change.startDate && change.endDate;
612
- const isClearingRange = !change.startDate && !change.endDate;
613
- if (hasCompleteRange || isClearingRange) {
614
- onDraftChange({
615
- startDate: change.startDate,
616
- endDate: change.endDate
617
- });
618
- }
619
- };
620
- const { value, onChange } = useDateFieldRangeConversion({
621
- value: draftValue,
622
- onChange: handleChange
623
- });
624
- const { handleInputChange, handleCalendarSelection } = useDateFieldRangeState(
625
- {
626
- valueProp: value,
627
- onChange: (change) => {
628
- const hasCompleteRange = change.startDate && change.endDate;
629
- const isClearingRange = change.isInputEmpty;
630
- if (change.isInputValid && hasCompleteRange || isClearingRange) {
631
- onChange({ ...change, isDateRangeValid: true });
632
- }
633
- }
634
- }
635
- );
636
- return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
637
- /* @__PURE__ */ jsx(
638
- MaskedDateRangeInput,
639
- {
640
- mode: filter.mode,
641
- ref: maskedDateRangeInputRef,
642
- onChange: handleInputChange,
643
- startDate: value?.startDate ?? null,
644
- endDate: value?.endDate ?? null,
645
- autoComplete: "off"
646
- }
647
- ),
648
- /* @__PURE__ */ jsx(
649
- DateFieldRangeCalendar,
650
- {
651
- startDate: value?.startDate ?? null,
652
- endDate: value?.endDate ?? null,
653
- onSelection: handleCalendarSelection
654
- }
655
- )
656
- ] });
657
- };
658
-
659
- const DateListDialog = ({
660
- libraryId,
661
- parentFilterId,
662
- initialValue,
663
- mode,
664
- dialogCtaLabel,
665
- onCommit,
666
- onCancel
667
- }) => {
668
- const [dateDraft, setDateDraft] = useState(null);
669
- const [rangeDraft, setRangeDraft] = useState(null);
670
- useEffect(() => {
671
- if (!libraryId) return;
672
- if (isDateListRangeLibraryId(libraryId)) {
673
- setRangeDraft(
674
- initialValue && typeof initialValue === "object" ? {
675
- startDate: initialValue.startDate,
676
- endDate: initialValue.endDate
677
- } : null
678
- );
679
- setDateDraft(null);
680
- } else {
681
- setDateDraft(typeof initialValue === "string" ? initialValue : null);
682
- setRangeDraft(null);
683
- }
684
- }, [libraryId, initialValue]);
685
- const dialogOpen = libraryId !== null;
686
- const dialogLabel = libraryId ? getDateListLibraryOptionLabel(libraryId) : "";
687
- const isRange = libraryId ? isDateListRangeLibraryId(libraryId) : false;
688
- const canCommit = isRange ? Boolean(rangeDraft?.startDate && rangeDraft?.endDate) : Boolean(dateDraft);
689
- const handleCommit = () => {
690
- if (!libraryId) return;
691
- if (isRange) {
692
- if (!rangeDraft?.startDate || !rangeDraft?.endDate) return;
693
- onCommit({
694
- id: libraryId,
695
- label: dialogLabel,
696
- value: {
697
- startDate: rangeDraft.startDate,
698
- endDate: rangeDraft.endDate
699
- }
700
- });
701
- } else {
702
- if (!dateDraft) return;
703
- onCommit({ id: libraryId, label: dialogLabel, value: dateDraft });
704
- }
705
- };
706
- return /* @__PURE__ */ jsx(Dialog, { open: dialogOpen, onClose: onCancel, children: libraryId && /* @__PURE__ */ jsxs(Fragment, { children: [
707
- /* @__PURE__ */ jsx(Dialog.Header, { children: dialogLabel }),
708
- /* @__PURE__ */ jsx(Dialog.Content, { children: isRange ? /* @__PURE__ */ jsx(
709
- FilterDateRange,
710
- {
711
- filter: {
712
- id: `${parentFilterId}--date-list-dialog-range`,
713
- label: dialogLabel,
714
- type: "dateRange",
715
- value: rangeDraft,
716
- mode
717
- },
718
- draftValue: rangeDraft,
719
- onDraftChange: setRangeDraft
720
- }
721
- ) : /* @__PURE__ */ jsx(
722
- FilterDateSingle,
723
- {
724
- filter: {
725
- id: `${parentFilterId}--date-list-dialog-date`,
726
- label: dialogLabel,
727
- type: "date",
728
- value: dateDraft,
729
- mode
730
- },
731
- draftValue: dateDraft,
732
- onDraftChange: setDateDraft
733
- }
734
- ) }),
735
- /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, justifyContent: "flex-end", children: [
736
- /* @__PURE__ */ jsx(Dialog.CancelButton, { appearance: "ghost", "aria-label": "Cancel", children: "Cancel" }),
737
- /* @__PURE__ */ jsx(
738
- Button,
739
- {
740
- appearance: "primary",
741
- disabled: !canCommit,
742
- onClick: handleCommit,
743
- children: dialogCtaLabel
744
- }
745
- )
746
- ] }) })
747
- ] }) });
748
- };
749
- const FilterDateList = ({
750
- filter,
751
- draftValue,
752
- onDraftChange,
753
- dialogCtaLabel
754
- }) => {
755
- const [openLibraryId, setOpenLibraryId] = useState(null);
756
- useEffect(() => {
757
- const libraryLabels = new Set(dateListLibraryOptions.map((o) => o.label));
758
- filter.options.forEach((opt) => {
759
- if (isDateListLibraryOptionId(opt.id)) {
760
- warnOnce(
761
- `[FilterDateList] Consumer option id "${opt.id}" is reserved for a library option ("on", "before", "after", "customRange"). Use a different id.`
762
- );
763
- }
764
- if (libraryLabels.has(opt.label)) {
765
- warnOnce(
766
- `[FilterDateList] Consumer option label "${opt.label}" collides with a library option label ("On…", "Before…", "After…", "Custom Range…"). Use a different label.`
767
- );
768
- }
769
- });
770
- }, [filter.options]);
771
- const items = useMemo(
772
- () => [
773
- ...filter.options.map(
774
- (opt) => ({ ...opt, _kind: "consumer" })
775
- ),
776
- ...dateListLibraryOptions.map(
777
- (opt) => ({
778
- id: opt.id,
779
- label: opt.label,
780
- _kind: "library"
781
- })
782
- )
783
- ],
784
- [filter.options]
785
- );
786
- const selectedItem = useMemo(
787
- () => draftValue ? items.find((item) => item.id === draftValue.id) : void 0,
788
- [items, draftValue]
789
- );
790
- const handleSelectionChange = (selected) => {
791
- if (!selected) {
792
- if (draftValue && isDateListLibraryOptionId(draftValue.id)) {
793
- setOpenLibraryId(draftValue.id);
794
- }
795
- return;
796
- }
797
- if (selected._kind === "library") {
798
- setOpenLibraryId(selected.id);
799
- return;
800
- }
801
- onDraftChange({
802
- id: selected.id,
803
- label: selected.label,
804
- value: selected.value
805
- });
806
- };
807
- const dialogInitialValue = openLibraryId && draftValue?.id === openLibraryId && draftValue.value !== null ? draftValue.value : void 0;
808
- return /* @__PURE__ */ jsxs(Fragment, { children: [
809
- /* @__PURE__ */ jsx(
810
- Listbox,
811
- {
812
- items,
813
- selected: selectedItem,
814
- onSelectionChange: handleSelectionChange,
815
- disableAutoSelectOnFocus: true,
816
- style: { paddingInline: "1rem", paddingBlockStart: "1rem" },
817
- children: ({ items: items2 }) => items2.map((item) => /* @__PURE__ */ jsx(Listbox.Option, { item, children: item.label }, item.id))
818
- }
819
- ),
820
- /* @__PURE__ */ jsx(
821
- DateListDialog,
822
- {
823
- libraryId: openLibraryId,
824
- parentFilterId: filter.id,
825
- initialValue: dialogInitialValue,
826
- mode: filter.mode,
827
- dialogCtaLabel,
828
- onCommit: (option) => {
829
- onDraftChange(option);
830
- setOpenLibraryId(null);
831
- },
832
- onCancel: () => setOpenLibraryId(null)
833
- }
834
- )
835
- ] });
836
- };
837
-
838
- const FilterButton = ({
839
- filter,
840
- children,
841
- className
842
- }) => {
843
- const [isOpen, setIsOpen] = useState(false);
844
- const { updateFilter, controlledFiltering } = useContext(FilterGroupContext);
845
- const toolbarSize = useToolbarSize();
846
- const [draftValue, setDraftValue] = useState(
847
- filter.type === "multiSelect" ? [] : void 0
848
- );
849
- const draftValueRef = useRef(draftValue);
850
- useEffect(() => {
851
- draftValueRef.current = draftValue;
852
- }, [draftValue]);
853
- const getCurrentFilterValue = useCallback(() => {
854
- switch (filter.type) {
855
- case "singleSelect":
856
- return filter.selectedItem;
857
- case "multiSelect":
858
- return filter.selectedItems || [];
859
- case "date":
860
- case "dateRange":
861
- return filter.value;
862
- case "dateList":
863
- return filter.selectedOption;
864
- case "custom":
865
- return filter.value;
866
- default:
867
- return void 0;
868
- }
869
- }, [filter]);
870
- const prevIsOpenRef = useRef(isOpen);
871
- const prevFilterRef = useRef(filter);
872
- useEffect(() => {
873
- const justOpened = isOpen && !prevIsOpenRef.current;
874
- prevIsOpenRef.current = isOpen;
875
- if (isOpen) {
876
- const shouldSync = justOpened || prevFilterRef.current && hasFilterSelectionChanged(prevFilterRef.current, filter);
877
- if (shouldSync) {
878
- const currentValue = getCurrentFilterValue();
879
- setDraftValue(currentValue);
880
- }
881
- prevFilterRef.current = filter;
882
- }
883
- }, [isOpen, filter]);
884
- const handleChange = useCallback(
885
- (value) => {
886
- if (hasChangedFilter(value, draftValueRef.current)) {
887
- draftValueRef.current = value;
888
- setDraftValue(value);
889
- if (filter.type === "dateList") {
890
- updateFilter(filter.id, value, true);
891
- setIsOpen(false);
892
- return;
893
- }
894
- if (!controlledFiltering) {
895
- updateFilter(filter.id, value, true);
896
- if (filter.type !== "multiSelect") {
897
- setIsOpen(false);
898
- }
899
- }
900
- }
901
- },
902
- [filter.id, filter.type, controlledFiltering, updateFilter]
903
- );
904
- const handleSubmit = useCallback(() => {
905
- const stateValue = getCurrentFilterValue();
906
- if (hasChangedFilter(draftValue, stateValue)) {
907
- updateFilter(filter.id, draftValue, true);
908
- }
909
- setIsOpen(false);
910
- }, [draftValue, getCurrentFilterValue, filter.id, updateFilter]);
911
- const handleCancel = useCallback(() => {
912
- if (!controlledFiltering) {
913
- setIsOpen(false);
914
- return;
915
- }
916
- const originalValue = getCurrentFilterValue();
917
- setDraftValue(originalValue);
918
- setIsOpen(false);
919
- }, [controlledFiltering, getCurrentFilterValue]);
920
- const getButtonLabel = useMemo(() => {
921
- switch (filter.type) {
922
- case "singleSelect": {
923
- const singleSelectFilter = filter;
924
- if (singleSelectFilter.selectedItem) {
925
- return `${filter.label}: ${singleSelectFilter.selectedItem.label}`;
926
- }
927
- return filter.label;
928
- }
929
- case "multiSelect": {
930
- const multiSelectFilter = filter;
931
- if (multiSelectFilter.selectedItems && multiSelectFilter.selectedItems.length > 0) {
932
- const selectionCount = multiSelectFilter.selectedItems.length.toString();
933
- return /* @__PURE__ */ jsxs(Fragment, { children: [
934
- filter.label,
935
- /* @__PURE__ */ jsx(
936
- Chip,
937
- {
938
- label: selectionCount,
939
- color: "#0265DC",
940
- size: "small",
941
- "aria-label": `${selectionCount} selected items`
942
- }
943
- )
944
- ] });
945
- }
946
- return filter.label;
947
- }
948
- case "date":
949
- if (filter.value) {
950
- const date = DateTime.fromISO(filter.value, { zone: "local" });
951
- return `${filter.label}: ${date.monthShort} ${date.day}, ${date.year}`;
952
- }
953
- return filter.label;
954
- case "dateRange":
955
- if (filter.value?.startDate && filter.value?.endDate) {
956
- const start = DateTime.fromISO(filter.value.startDate, {
957
- zone: "local"
958
- });
959
- const end = DateTime.fromISO(filter.value.endDate, {
960
- zone: "local"
961
- });
962
- const isSameYear = start.year === end.year;
963
- const formattedStart = isSameYear ? `${start.monthShort} ${start.day}` : `${start.monthShort} ${start.day}, ${start.year}`;
964
- return `${filter.label}: ${formattedStart} – ${end.monthShort} ${end.day}, ${end.year}`;
965
- }
966
- return filter.label;
967
- case "custom":
968
- if (filter.labelChipCount) {
969
- return /* @__PURE__ */ jsxs(Fragment, { children: [
970
- filter.label,
971
- /* @__PURE__ */ jsx(
972
- Chip,
973
- {
974
- label: filter.labelChipCount.toString(),
975
- color: "#0265DC",
976
- size: "small",
977
- "aria-label": `${filter.labelChipCount} selected items`
978
- }
979
- )
980
- ] });
981
- }
982
- return filter.label;
983
- case "dateList": {
984
- const selected = filter.selectedOption;
985
- if (!selected || selected.value === null) return filter.label;
986
- return formatDateListSelectionLabel(selected);
987
- }
988
- default:
989
- return filter.label;
990
- }
991
- }, [filter]);
992
- const getContent = useMemo(() => {
993
- switch (filter.type) {
994
- case "custom":
995
- return filter.buttonRender({
996
- value: draftValue,
997
- onChange: handleChange
998
- });
999
- case "singleSelect":
1000
- return /* @__PURE__ */ jsx(
1001
- FilterSelect,
1002
- {
1003
- filter,
1004
- draftValue,
1005
- onDraftChange: handleChange
1006
- }
1007
- );
1008
- case "multiSelect":
1009
- return /* @__PURE__ */ jsx(
1010
- FilterSelect,
1011
- {
1012
- filter,
1013
- draftValue,
1014
- onDraftChange: handleChange
1015
- }
1016
- );
1017
- case "date":
1018
- return /* @__PURE__ */ jsx(
1019
- FilterDateSingle,
1020
- {
1021
- filter,
1022
- draftValue,
1023
- onDraftChange: handleChange
1024
- }
1025
- );
1026
- case "dateRange":
1027
- return /* @__PURE__ */ jsx(
1028
- FilterDateRange,
1029
- {
1030
- filter,
1031
- draftValue,
1032
- onDraftChange: handleChange
1033
- }
1034
- );
1035
- case "dateList":
1036
- return /* @__PURE__ */ jsx(
1037
- FilterDateList,
1038
- {
1039
- filter,
1040
- draftValue,
1041
- onDraftChange: handleChange,
1042
- dialogCtaLabel: "Apply"
1043
- }
1044
- );
1045
- default:
1046
- return children;
1047
- }
1048
- }, [filter, draftValue, handleChange, children]);
1049
- const handleOutsidePress = () => {
1050
- if (controlledFiltering) {
1051
- handleCancel();
1052
- } else if (filter.type === "multiSelect") {
1053
- setIsOpen(false);
1054
- } else {
1055
- handleSubmit();
1056
- }
1057
- };
1058
- const handleKeyDown = (e) => {
1059
- if (e.key === "Enter") {
1060
- if (!controlledFiltering && filter.type !== "multiSelect") {
1061
- handleSubmit();
1062
- }
1063
- }
1064
- };
1065
- const triggerClasses = cx(styles["filter-button-trigger"], {
1066
- [styles["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?.startDate && filter.value?.endDate || filter.type === "dateList" && filter.selectedOption !== void 0 && filter.selectedOption.value !== null
1067
- });
1068
- const contentClasses = cx(styles["filter-button-content"], className);
1069
- const iconOptions = filter.type === "date" || filter.type === "dateRange" || filter.type === "dateList" ? { before: SvgEvent } : { after: SvgKeyboardArrowDown };
1070
- return /* @__PURE__ */ jsx(FilterItemWrapper, { filter, children: /* @__PURE__ */ jsxs(
1071
- Popover,
1072
- {
1073
- open: isOpen,
1074
- onClose: handleOutsidePress,
1075
- placement: "bottom-start",
1076
- modal: true,
1077
- noPadding: filter.type === "multiSelect" || filter.type === "singleSelect" || filter.type === "dateList",
1078
- children: [
1079
- /* @__PURE__ */ jsx(
1080
- Popover.Button,
1081
- {
1082
- appearance: "ghost",
1083
- size: toolbarSize,
1084
- icon: iconOptions,
1085
- "data-id": filter.id,
1086
- "data-anv": "toolbar-button",
1087
- className: triggerClasses,
1088
- onClick: () => {
1089
- setIsOpen(!isOpen);
1090
- },
1091
- children: getButtonLabel
1092
- }
1093
- ),
1094
- /* @__PURE__ */ jsxs(Popover.Content, { onKeyDown: handleKeyDown, className: contentClasses, children: [
1095
- getContent,
1096
- controlledFiltering && filter.type !== "dateList" && /* @__PURE__ */ jsxs(
1097
- Flex,
1098
- {
1099
- gap: 2,
1100
- justifyContent: "flex-end",
1101
- className: styles["filter-button-buttons"],
1102
- children: [
1103
- /* @__PURE__ */ jsx(Popover.Close, { size: "small", children: "Cancel" }),
1104
- /* @__PURE__ */ jsx(Button, { appearance: "primary", size: "small", onClick: handleSubmit, children: "Apply" })
1105
- ]
1106
- }
1107
- )
1108
- ] })
1109
- ]
1110
- }
1111
- ) });
1112
- };
1113
-
1114
- 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" }));
1115
-
1116
- const FilterDrawer = () => {
1117
- const [open, setOpen] = useState(false);
1118
- const {
1119
- filters,
1120
- updateFilter,
1121
- onFilterChange,
1122
- hiddenFilters,
1123
- filterGroupRef
1124
- } = useContext(FilterGroupContext);
1125
- const toolbarSize = useToolbarSize();
1126
- const containerQuery = useContainerQuery(filterGroupRef);
1127
- const showInlineFilters = containerQuery && containerQuery.name !== "xs" && containerQuery.name !== "sm";
1128
- const [draftFilters, setDraftFilters] = useState(filters);
1129
- const [searchValues, setSearchValues] = useState({});
1130
- const [dateListDialogState, setDateListDialogState] = useState(null);
1131
- const activeFiltersCount = getActiveFilters(
1132
- !showInlineFilters ? filters : hiddenFilters
1133
- ).length;
1134
- const prevOpenRef = useRef(open);
1135
- const prevFiltersRef = useRef(filters);
1136
- useEffect(() => {
1137
- const justOpened = open && !prevOpenRef.current;
1138
- prevOpenRef.current = open;
1139
- if (open) {
1140
- const anySelectionChanged = prevFiltersRef.current.some(
1141
- (prevFilter, index) => {
1142
- const newFilter = filters[index];
1143
- return newFilter && hasFilterSelectionChanged(prevFilter, newFilter);
1144
- }
1145
- );
1146
- const shouldSync = justOpened || anySelectionChanged;
1147
- if (shouldSync) {
1148
- setDraftFilters(cloneFiltersWithItemRefs(filters));
1149
- }
1150
- prevFiltersRef.current = filters;
1151
- }
1152
- }, [open, filters]);
1153
- const handleDraftChange = useCallback(
1154
- (filterId, value) => {
1155
- setDraftFilters((draft) => updateSingleFilter(draft, filterId, value));
1156
- const filter = filters.find((f) => f.id === filterId);
1157
- if ((filter?.type === "singleSelect" || filter?.type === "multiSelect") && filter.hasSearch && value) {
1158
- setSearchValues((prev) => ({ ...prev, [filterId]: "" }));
1159
- requestAnimationFrame(() => {
1160
- filter.onSearch?.("");
1161
- });
1162
- }
1163
- },
1164
- [filters]
1165
- );
1166
- const clearDraftFilters = () => {
1167
- setDraftFilters(resetFilters(draftFilters));
1168
- };
1169
- const hasActiveDraftFilters = checkActiveFilters(draftFilters);
1170
- const filterForm = useMemo(
1171
- () => draftFilters.map((draftFilter) => {
1172
- const originalFilter = filters.find((f) => f.id === draftFilter.id);
1173
- if (!originalFilter) return null;
1174
- switch (draftFilter.type) {
1175
- case "boolean":
1176
- return /* @__PURE__ */ jsx(
1177
- Checkbox,
1178
- {
1179
- label: draftFilter.label,
1180
- checked: draftFilter.checked,
1181
- onChange: (e) => handleDraftChange(draftFilter.id, e?.target.checked ?? false)
1182
- },
1183
- draftFilter.id
1184
- );
1185
- case "custom": {
1186
- const customFilter = originalFilter;
1187
- return /* @__PURE__ */ jsx("div", { children: customFilter.drawerRender?.({
1188
- value: draftFilter.value,
1189
- onChange: (value) => handleDraftChange(draftFilter.id, value)
1190
- }) }, draftFilter.id);
1191
- }
1192
- case "singleSelect": {
1193
- const singleSelectFilter = originalFilter;
1194
- const draftSingleSelectFilter = draftFilter;
1195
- if (singleSelectFilter.simpleDrawerVariant) {
1196
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Radio.Group, { legend: singleSelectFilter.label, children: singleSelectFilter.items.map((item) => /* @__PURE__ */ jsx(
1197
- Radio,
1198
- {
1199
- name: `${singleSelectFilter.id}-radio`,
1200
- value: item.id,
1201
- label: item.label,
1202
- checked: draftSingleSelectFilter.selectedItem?.id === item.id,
1203
- onChange: (e) => {
1204
- if (e?.target.checked) {
1205
- const selected = singleSelectFilter.items.find(
1206
- (opt) => opt.id === e.target.value
1207
- );
1208
- handleDraftChange(draftFilter.id, selected);
1209
- }
1210
- }
1211
- },
1212
- item.id
1213
- )) }) }, draftFilter.id);
1214
- } else {
1215
- const selectedItem = draftSingleSelectFilter.selectedItem ? singleSelectFilter.items?.find(
1216
- (item) => item.id === draftSingleSelectFilter.selectedItem?.id
1217
- ) ?? null : null;
1218
- return /* @__PURE__ */ jsxs(
1219
- Combobox,
1220
- {
1221
- items: singleSelectFilter.items,
1222
- selectedItem,
1223
- onChange: (selectedItem2) => {
1224
- handleDraftChange(draftFilter.id, selectedItem2);
1225
- },
1226
- itemToString: (item) => item?.label ?? "",
1227
- disableFilter: singleSelectFilter.hasSearch,
1228
- children: [
1229
- singleSelectFilter.hasSearch ? /* @__PURE__ */ jsx(
1230
- Combobox.SearchField,
1231
- {
1232
- label: draftSingleSelectFilter.label,
1233
- prefix: { icon: { svg: SvgSearch } },
1234
- placeholder: "Search...",
1235
- size: "medium",
1236
- value: draftSingleSelectFilter.selectedItem?.label || searchValues[draftFilter.id] || "",
1237
- onChange: (e) => {
1238
- const searchValue = e.target.value;
1239
- setSearchValues((prev) => ({
1240
- ...prev,
1241
- [draftFilter.id]: searchValue
1242
- }));
1243
- singleSelectFilter.onSearch?.(searchValue);
1244
- },
1245
- onClear: () => {
1246
- setSearchValues((prev) => ({
1247
- ...prev,
1248
- [draftFilter.id]: ""
1249
- }));
1250
- handleDraftChange(draftFilter.id, void 0);
1251
- singleSelectFilter.onSearchClear?.();
1252
- },
1253
- "data-anv": "filter-drawer-combobox-search"
1254
- }
1255
- ) : /* @__PURE__ */ jsx(
1256
- Combobox.SelectTrigger,
1257
- {
1258
- label: singleSelectFilter.label,
1259
- placeholder: "Select an option...",
1260
- size: "medium"
1261
- }
1262
- ),
1263
- /* @__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)) }) })
1264
- ]
1265
- },
1266
- draftFilter.id
1267
- );
1268
- }
1269
- }
1270
- case "multiSelect": {
1271
- const multiSelectFilter = originalFilter;
1272
- const draftMultiSelectFilter = draftFilter;
1273
- if (multiSelectFilter.simpleDrawerVariant) {
1274
- return /* @__PURE__ */ jsx(
1275
- Checkbox.Group,
1276
- {
1277
- legend: multiSelectFilter.label,
1278
- children: multiSelectFilter.items.map((item) => /* @__PURE__ */ jsx(
1279
- Checkbox,
1280
- {
1281
- label: item.label,
1282
- checked: draftMultiSelectFilter.selectedItems?.some(
1283
- (selected) => selected.id === item.id
1284
- ) ?? false,
1285
- onChange: (e) => {
1286
- const currentSelected = draftMultiSelectFilter.selectedItems || [];
1287
- if (e?.target.checked) {
1288
- handleDraftChange(draftFilter.id, [
1289
- ...currentSelected,
1290
- item
1291
- ]);
1292
- } else {
1293
- handleDraftChange(
1294
- draftFilter.id,
1295
- currentSelected.filter(
1296
- (selected) => selected.id !== item.id
1297
- )
1298
- );
1299
- }
1300
- }
1301
- },
1302
- item.id
1303
- ))
1304
- },
1305
- draftFilter.id
1306
- );
1307
- } else {
1308
- const hasActiveSearch = searchValues[draftFilter.id] && searchValues[draftFilter.id].length > 0;
1309
- return /* @__PURE__ */ jsxs(
1310
- Combobox,
1311
- {
1312
- items: multiSelectFilter.items,
1313
- selectedItems: draftMultiSelectFilter.selectedItems || [],
1314
- onChange: (selectedItems) => handleDraftChange(draftFilter.id, selectedItems),
1315
- itemToString: (item) => item?.label ?? "",
1316
- itemToKey: (item) => item?.id ?? "",
1317
- disableFilter: multiSelectFilter.hasSearch,
1318
- multiple: true,
1319
- disableCloseOnSelectItem: !hasActiveSearch,
1320
- children: [
1321
- multiSelectFilter.hasSearch ? /* @__PURE__ */ jsx(
1322
- Combobox.SearchField,
1323
- {
1324
- label: multiSelectFilter.label,
1325
- prefix: { icon: { svg: SvgSearch } },
1326
- placeholder: "Search...",
1327
- size: "medium",
1328
- value: searchValues[draftFilter.id] || "",
1329
- onChange: (e) => {
1330
- const searchValue = e.target.value;
1331
- setSearchValues((prev) => ({
1332
- ...prev,
1333
- [draftFilter.id]: searchValue
1334
- }));
1335
- multiSelectFilter.onSearch?.(searchValue);
1336
- },
1337
- onClear: () => {
1338
- setSearchValues((prev) => ({
1339
- ...prev,
1340
- [draftFilter.id]: ""
1341
- }));
1342
- handleDraftChange(draftFilter.id, []);
1343
- multiSelectFilter.onSearchClear?.();
1344
- },
1345
- "data-anv": "filter-drawer-combobox-search"
1346
- }
1347
- ) : /* @__PURE__ */ jsx(
1348
- Combobox.SelectTrigger,
1349
- {
1350
- label: multiSelectFilter.label,
1351
- placeholder: "Select options...",
1352
- size: "medium"
1353
- }
1354
- ),
1355
- /* @__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)) }) })
1356
- ]
1357
- },
1358
- draftFilter.id
1359
- );
1360
- }
1361
- }
1362
- case "date": {
1363
- return /* @__PURE__ */ jsx(
1364
- DateFieldSingle,
1365
- {
1366
- label: draftFilter.label,
1367
- value: draftFilter.value,
1368
- onChange: (change) => {
1369
- handleDraftChange(draftFilter.id, change.date);
1370
- },
1371
- mode: draftFilter.mode
1372
- },
1373
- draftFilter.id
1374
- );
1375
- }
1376
- case "dateRange": {
1377
- return /* @__PURE__ */ jsx(
1378
- DateFieldRange,
1379
- {
1380
- label: draftFilter.label,
1381
- value: draftFilter.value,
1382
- onChange: (change) => {
1383
- handleDraftChange(draftFilter.id, {
1384
- startDate: change.startDate,
1385
- endDate: change.endDate
1386
- });
1387
- },
1388
- mode: draftFilter.mode
1389
- },
1390
- draftFilter.id
1391
- );
1392
- }
1393
- case "dateList": {
1394
- const dateListFilter = originalFilter;
1395
- const draftDateListFilter = draftFilter;
1396
- const consumerSelectOptions = dateListFilter.options.map((opt) => ({
1397
- id: opt.id,
1398
- label: opt.label,
1399
- extra: { value: opt.value }
1400
- }));
1401
- const librarySelectOptions = dateListLibraryOptions.map((opt) => ({
1402
- id: opt.id,
1403
- label: opt.label,
1404
- extra: { value: null }
1405
- }));
1406
- const allSelectOptions = [
1407
- ...consumerSelectOptions,
1408
- ...librarySelectOptions
1409
- ];
1410
- const selectedSelectOption = draftDateListFilter.selectedOption ? {
1411
- id: draftDateListFilter.selectedOption.id,
1412
- label: formatDateListSelectionLabel(
1413
- draftDateListFilter.selectedOption
1414
- ),
1415
- extra: {
1416
- value: draftDateListFilter.selectedOption.value
1417
- }
1418
- } : null;
1419
- return /* @__PURE__ */ jsx(
1420
- SelectFieldSync,
1421
- {
1422
- label: dateListFilter.label,
1423
- placeholder: "Select an option...",
1424
- disableSearch: true,
1425
- options: allSelectOptions,
1426
- value: selectedSelectOption,
1427
- onSelectedOptionChange: (option) => {
1428
- if (!option) {
1429
- handleDraftChange(draftFilter.id, void 0);
1430
- return;
1431
- }
1432
- const id = String(option.id);
1433
- if (isDateListLibraryOptionId(id)) {
1434
- setDateListDialogState({
1435
- filterId: draftFilter.id,
1436
- libraryId: id
1437
- });
1438
- return;
1439
- }
1440
- handleDraftChange(draftFilter.id, {
1441
- id,
1442
- label: option.label,
1443
- value: option.extra?.value ?? null
1444
- });
1445
- }
1446
- },
1447
- draftFilter.id
1448
- );
1449
- }
1450
- default:
1451
- return null;
1452
- }
1453
- }),
1454
- [draftFilters, filters, searchValues, handleDraftChange]
1455
- );
1456
- const applyFiltering = () => {
1457
- draftFilters.forEach((draftFilter) => {
1458
- switch (draftFilter.type) {
1459
- case "boolean":
1460
- updateFilter(draftFilter.id, draftFilter.checked, false);
1461
- break;
1462
- case "singleSelect":
1463
- updateFilter(
1464
- draftFilter.id,
1465
- draftFilter.selectedItem,
1466
- false
1467
- );
1468
- break;
1469
- case "multiSelect":
1470
- updateFilter(
1471
- draftFilter.id,
1472
- draftFilter.selectedItems,
1473
- false
1474
- );
1475
- break;
1476
- case "date":
1477
- case "dateRange":
1478
- case "custom":
1479
- updateFilter(draftFilter.id, draftFilter.value, false);
1480
- break;
1481
- case "dateList":
1482
- updateFilter(
1483
- draftFilter.id,
1484
- draftFilter.selectedOption,
1485
- false
1486
- );
1487
- break;
1488
- }
1489
- });
1490
- onFilterChange?.(draftFilters);
1491
- setOpen(false);
1492
- };
1493
- const handleCancel = () => {
1494
- setOpen(false);
1495
- };
1496
- const hasHiddenActiveFilters = activeFiltersCount > 0;
1497
- const triggerClasses = cx(
1498
- styles["filter-button-trigger"],
1499
- styles["filter-drawer-trigger"],
1500
- {
1501
- [styles["filter-drawer-trigger--chipped"]]: hasHiddenActiveFilters
1502
- }
1503
- );
1504
- const dateListDialogTarget = dateListDialogState ? draftFilters.find(
1505
- (f) => f.id === dateListDialogState.filterId && f.type === "dateList"
1506
- ) : void 0;
1507
- const dateListDialogSelected = dateListDialogTarget?.selectedOption;
1508
- const dateListDialogInitialValue = dateListDialogSelected && dateListDialogSelected.id === dateListDialogState?.libraryId && dateListDialogSelected.value !== null ? dateListDialogSelected.value : void 0;
1509
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1510
- /* @__PURE__ */ jsxs(
1511
- ButtonToggle,
1512
- {
1513
- "data-anv": "filter-group-drawer-trigger",
1514
- icon: { before: SvgTune },
1515
- onClick: () => setOpen(true),
1516
- className: triggerClasses,
1517
- checked: open,
1518
- size: toolbarSize,
1519
- children: [
1520
- "Filters",
1521
- hasHiddenActiveFilters && /* @__PURE__ */ jsx(
1522
- Chip,
1523
- {
1524
- size: "small",
1525
- color: "#0265DC",
1526
- label: activeFiltersCount.toString()
1527
- }
1528
- )
1529
- ]
1530
- }
1531
- ),
1532
- /* @__PURE__ */ jsxs(
1533
- Drawer,
1534
- {
1535
- "data-anv": "filter-group-drawer",
1536
- "data-testid": "filter-group-drawer",
1537
- open,
1538
- onClose: () => setOpen(false),
1539
- children: [
1540
- /* @__PURE__ */ jsx(Drawer.Content, { children: /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 6, grow: 1, children: filterForm }) }),
1541
- /* @__PURE__ */ jsx(Drawer.Footer, { children: /* @__PURE__ */ jsxs(
1542
- Flex,
1543
- {
1544
- justifyContent: hasActiveDraftFilters ? "space-between" : "flex-end",
1545
- grow: 1,
1546
- children: [
1547
- hasActiveDraftFilters && /* @__PURE__ */ jsx(
1548
- Button,
1549
- {
1550
- appearance: "ghost",
1551
- icon: { before: SvgClose },
1552
- onClick: clearDraftFilters,
1553
- children: "Clear All Filters"
1554
- }
1555
- ),
1556
- /* @__PURE__ */ jsxs(Flex, { gap: "3", children: [
1557
- /* @__PURE__ */ jsx(Button, { onClick: handleCancel, children: "Cancel" }),
1558
- /* @__PURE__ */ jsx(Button, { appearance: "primary", onClick: applyFiltering, children: "Apply" })
1559
- ] })
1560
- ]
1561
- }
1562
- ) })
1563
- ]
1564
- }
1565
- ),
1566
- /* @__PURE__ */ jsx(
1567
- DateListDialog,
1568
- {
1569
- libraryId: dateListDialogState?.libraryId ?? null,
1570
- parentFilterId: dateListDialogState?.filterId ?? "",
1571
- initialValue: dateListDialogInitialValue,
1572
- mode: dateListDialogTarget?.mode,
1573
- dialogCtaLabel: "Save",
1574
- onCommit: (option) => {
1575
- if (dateListDialogState) {
1576
- handleDraftChange(dateListDialogState.filterId, option);
1577
- }
1578
- setDateListDialogState(null);
1579
- },
1580
- onCancel: () => setDateListDialogState(null)
1581
- }
1582
- )
1583
- ] });
1584
- };
1585
-
1586
- const FilterBar = forwardRef(
1587
- function FilterBarInner(props, ref) {
1588
- const { layoutStyles, componentProps } = useLayoutPropsUtil(props);
1589
- const {
1590
- filters: initialFilters,
1591
- onFilterChange,
1592
- controlledFiltering = false,
1593
- associatedContent,
1594
- size = "xsmall",
1595
- overflow = "wrap",
1596
- className,
1597
- style,
1598
- onKeyDown,
1599
- ...rest
1600
- } = componentProps;
1601
- const [filters, setFilters] = useState(initialFilters);
1602
- const [hiddenFilters, setHiddenFilters] = useState([]);
1603
- const filterBarRef = useRef(null);
1604
- const containerQuery = useContainerQuery(filterBarRef);
1605
- const showInlineFilters = containerQuery && containerQuery.name !== "xs" && containerQuery.name !== "sm";
1606
- useEffect(() => {
1607
- setFilters((prevFilters) => {
1608
- const existingFiltersMap = new Map(prevFilters.map((f) => [f.id, f]));
1609
- return initialFilters.map((newFilter) => {
1610
- const existingFilter = existingFiltersMap.get(newFilter.id);
1611
- if (!existingFilter) {
1612
- return newFilter;
1613
- }
1614
- if (!hasFilterSelectionChanged(existingFilter, newFilter)) {
1615
- return preserveFilterState(newFilter, existingFilter);
1616
- }
1617
- return newFilter;
1618
- });
1619
- });
1620
- }, [initialFilters]);
1621
- const updateFilter = useCallback(
1622
- (filterId, value, submit) => {
1623
- setFilters((prevFilters) => {
1624
- const updatedFilters = updateSingleFilter(
1625
- prevFilters,
1626
- filterId,
1627
- value
1628
- );
1629
- if (submit) {
1630
- onFilterChange?.(updatedFilters);
1631
- }
1632
- return updatedFilters;
1633
- });
1634
- },
1635
- [onFilterChange]
1636
- );
1637
- const addHiddenFilter = useCallback((filter) => {
1638
- setHiddenFilters((prev) => [...prev, filter]);
1639
- }, []);
1640
- const removeHiddenFilter = useCallback((filter) => {
1641
- setHiddenFilters((prev) => prev.filter((f) => f.id !== filter.id));
1642
- }, []);
1643
- const clearAllFilters = () => {
1644
- const resetAllFilters = resetFilters(filters);
1645
- setFilters(resetAllFilters);
1646
- onFilterChange?.(resetAllFilters);
1647
- requestAnimationFrame(() => {
1648
- if (filterBarRef.current) {
1649
- const firstFocusable = filterBarRef.current.querySelector(
1650
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1651
- );
1652
- if (firstFocusable) {
1653
- firstFocusable.focus();
1654
- }
1655
- }
1656
- });
1657
- };
1658
- const hasActiveFilters = checkActiveFilters(filters);
1659
- const filterGroupControls = filters.map((filter) => {
1660
- switch (filter.type) {
1661
- case "boolean":
1662
- return /* @__PURE__ */ jsx(
1663
- FilterToggleButton,
1664
- {
1665
- id: filter.id,
1666
- checked: filter.checked,
1667
- onClick: () => {
1668
- updateFilter(filter.id, !filter.checked, true);
1669
- },
1670
- children: filter.label
1671
- },
1672
- filter.id
1673
- );
1674
- case "singleSelect":
1675
- case "multiSelect":
1676
- return /* @__PURE__ */ jsx(
1677
- FilterButton,
1678
- {
1679
- filter,
1680
- className: styles["filter-select-content"]
1681
- },
1682
- filter.id
1683
- );
1684
- case "custom":
1685
- case "date":
1686
- case "dateRange":
1687
- case "dateList":
1688
- return /* @__PURE__ */ jsx(FilterButton, { filter }, filter.id);
1689
- default:
1690
- return null;
1691
- }
1692
- });
1693
- const toolbarContextValue = useMemo(
1694
- () => ({
1695
- overflowItems: [],
1696
- addItem: () => {
1697
- },
1698
- removeItem: () => {
1699
- },
1700
- toolbarRef: filterBarRef,
1701
- overflow,
1702
- size
1703
- }),
1704
- [overflow, size]
1705
- );
1706
- const filterGroupContextValue = useMemo(
1707
- () => ({
1708
- filterGroupRef: filterBarRef,
1709
- filters,
1710
- updateFilter,
1711
- onFilterChange,
1712
- controlledFiltering,
1713
- associatedContent,
1714
- hiddenFilters,
1715
- addHiddenFilter,
1716
- removeHiddenFilter
1717
- }),
1718
- [
1719
- filterBarRef,
1720
- filters,
1721
- updateFilter,
1722
- onFilterChange,
1723
- controlledFiltering,
1724
- associatedContent,
1725
- hiddenFilters,
1726
- addHiddenFilter,
1727
- removeHiddenFilter
1728
- ]
1729
- );
1730
- useEffect(() => {
1731
- if (filterBarRef.current) {
1732
- updateToolbarItemsTabIndex(filterBarRef.current);
1733
- }
1734
- }, [filters]);
1735
- const handleKeyDown = useCallback(
1736
- (event) => {
1737
- if (filterBarRef.current) {
1738
- handleToolbarKeyDown(event, filterBarRef.current);
1739
- }
1740
- onKeyDown?.(event);
1741
- },
1742
- [onKeyDown]
1743
- );
1744
- const styleCombined = {
1745
- ...style,
1746
- ...layoutStyles
1747
- };
1748
- return /* @__PURE__ */ jsx(ToolbarContext.Provider, { value: toolbarContextValue, children: /* @__PURE__ */ jsx(FilterGroupContext.Provider, { value: filterGroupContextValue, children: /* @__PURE__ */ jsx(
1749
- Flex,
1750
- {
1751
- ref: useMergeRefs([filterBarRef, ref]),
1752
- role: "toolbar",
1753
- "aria-label": `Filters for ${associatedContent}. Use arrow keys to navigate through filter controls.`,
1754
- "aria-orientation": "horizontal",
1755
- onKeyDown: handleKeyDown,
1756
- alignItems: "center",
1757
- gap: 1,
1758
- wrap: overflow === "collapse" ? "nowrap" : "wrap",
1759
- className,
1760
- style: styleCombined,
1761
- "data-anv": "filter-bar",
1762
- ...rest,
1763
- children: /* @__PURE__ */ jsxs(
1764
- Flex,
1765
- {
1766
- alignItems: "center",
1767
- gap: 1,
1768
- wrap: overflow === "collapse" ? "nowrap" : "wrap",
1769
- grow: 1,
1770
- "data-anv": "toolbar-content",
1771
- children: [
1772
- showInlineFilters && filterGroupControls,
1773
- /* @__PURE__ */ jsx(FilterDrawer, {}),
1774
- showInlineFilters && hasActiveFilters && /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
1775
- Button,
1776
- {
1777
- appearance: "ghost",
1778
- size,
1779
- className: styles["filter-button-trigger"],
1780
- icon: {
1781
- before: SvgClose
1782
- },
1783
- onClick: clearAllFilters,
1784
- children: "Clear Filters"
1785
- }
1786
- ) })
1787
- ]
1788
- }
1789
- )
1790
- }
1791
- ) }) });
1792
- }
1793
- );
1794
- FilterBar.displayName = "FilterBar";
1795
-
1796
- export { FilterBar as F };
1797
- //# sourceMappingURL=FilterBar-yysyZ-t1.js.map