@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
@@ -0,0 +1,1627 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo, forwardRef, createElement, createContext, useRef, useId, useState, useContext, useEffect, useCallback } from 'react';
3
+ import { C as Chip } from './Chip-D2k5X_wX.js';
4
+ import { d as ToolbarItemWrapper, u as useToolbarSize, T as ToolbarButtonToggle } from './ToolbarButtonToggle-BPu81Wuv.js';
5
+ import { S as SvgKeyboardArrowDown } from './keyboard_arrow_down-C8WQ38p1.js';
6
+ import { S as SvgEvent } from './TimezoneMessage-BrKB_psP.js';
7
+ import { c as cx } from './index-De1g9FRV.js';
8
+ import { B as Button } from './Button-C_V2xQAs.js';
9
+ import { M as MultiSelectField, a as MultiSelectFieldSync } from './MultiSelectFieldSync-CXX2F0ru.js';
10
+ import { M as MultiSelectMenu, u as useConfirmationDraft, a as MultiSelectMenuSync } from './MultiSelectMenuSync-EKtvlL62.js';
11
+ import { S as SelectField, a as SelectFieldSync } from './SelectFieldSync-DykGkR_w.js';
12
+ import { S as SelectMenu, a as SelectMenuSync } from './SelectMenuSync-DTQ8Ofoz.js';
13
+ import { C as Checkbox } from './Checkbox-BeIzx_ZX.js';
14
+ import { f as OptionsPopover } from './syncFilterUtils-BEKek64h.js';
15
+ import { M as MenuFooter } from './useMenuInteraction-CpAOHSJu.js';
16
+ import { D as DateTime } from './luxon-wpz4A-OQ.js';
17
+ import { u as useDateFieldSingleConversion, a as useDateFieldSingleState, M as MaskedDateInput, b as DateFieldSingleCalendar, D as DateFieldSingle } from './DateFieldSingle-h3YkdwPo.js';
18
+ import { F as Flex } from './Flex-_orhvoxS.js';
19
+ import { D as Dialog } from './Dialog-CvYSMvfD.js';
20
+ import { u as useDateFieldRangeConversion, a as useDateFieldRangeState, M as MaskedDateRangeInput, b as DateFieldRangeCalendar, D as DateFieldRange } from './DateFieldRange-BN_uIvHI.js';
21
+ import { w as warnOnce } from './warnOnce-Y9PRHcU4.js';
22
+ import { F as FieldLabel } from './FieldLabel-D1qPAGtB.js';
23
+ import { G as Grid } from './Grid-BAN8WD_V.js';
24
+ import { N as NumberField } from './NumberField-BymFZhIJ.js';
25
+ import { T as Text } from './Text-BTzgTpqu.js';
26
+ import { R as Radio } from './Radio-BcHMk8dD.js';
27
+
28
+ import './filter-state.css';const FilterItemWrapper = ({ children }) => {
29
+ const props = useMemo(
30
+ () => ({
31
+ item: {
32
+ itemType: "button",
33
+ itemProps: {
34
+ children: null,
35
+ "aria-hidden": true
36
+ }
37
+ },
38
+ children
39
+ }),
40
+ [children]
41
+ );
42
+ return /* @__PURE__ */ jsx(ToolbarItemWrapper, { ...props });
43
+ };
44
+
45
+ const styles = {
46
+ "filter-button-trigger": "_filter-button-trigger_1kmgt_1",
47
+ "filter-button-trigger--selected": "_filter-button-trigger--selected_1kmgt_5",
48
+ "filter-drawer-trigger": "_filter-drawer-trigger_1kmgt_25",
49
+ "filter-drawer-trigger--chipped": "_filter-drawer-trigger--chipped_1kmgt_31",
50
+ "filter-numeric-range-separator": "_filter-numeric-range-separator_1kmgt_63"
51
+ };
52
+
53
+ const FilterTriggerButton = forwardRef(function FilterTriggerButton2({ filterId, label, isSelected, icon = "dropdown", className, ...rest }, ref) {
54
+ const toolbarSize = useToolbarSize();
55
+ const iconOptions = icon === "calendar" ? { before: SvgEvent } : { after: SvgKeyboardArrowDown };
56
+ const buttonClass = cx(
57
+ styles["filter-button-trigger"],
58
+ {
59
+ [styles["filter-button-trigger--selected"]]: isSelected
60
+ },
61
+ className
62
+ );
63
+ return /* @__PURE__ */ jsx(
64
+ Button,
65
+ {
66
+ ref,
67
+ appearance: "ghost",
68
+ size: toolbarSize,
69
+ icon: iconOptions,
70
+ "data-id": filterId,
71
+ "data-anv": "toolbar-button",
72
+ className: buttonClass,
73
+ ...rest,
74
+ children: label
75
+ }
76
+ );
77
+ });
78
+
79
+ const isSelected$6 = (filter) => !!filter.selectedOptions && filter.selectedOptions.length > 0;
80
+ const formatLabel$8 = (filter) => {
81
+ const count = filter.selectedOptions?.length ?? 0;
82
+ if (count === 0) return filter.label;
83
+ const countLabel = count.toString();
84
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
85
+ filter.label,
86
+ /* @__PURE__ */ jsx(
87
+ Chip,
88
+ {
89
+ label: countLabel,
90
+ color: "#0265DC",
91
+ size: "small",
92
+ "aria-label": `${countLabel} selected items`
93
+ }
94
+ )
95
+ ] });
96
+ };
97
+ const passThroughMenuProps$3 = (filter) => {
98
+ const {
99
+ id: _id,
100
+ label: _label,
101
+ type: _type,
102
+ selectedOptions: _selectedOptions,
103
+ drawerOnly: _drawerOnly,
104
+ ...rest
105
+ } = filter;
106
+ return rest;
107
+ };
108
+ const asyncMultiSelectAdapter = {
109
+ getValue: (filter) => filter.selectedOptions ?? [],
110
+ setValue: (filter, value) => ({ ...filter, selectedOptions: value }),
111
+ reset: (filter) => ({ ...filter, selectedOptions: [] }),
112
+ isActive: isSelected$6,
113
+ preserveState: (newFilter, existingFilter) => ({
114
+ ...newFilter,
115
+ selectedOptions: existingFilter.selectedOptions
116
+ }),
117
+ // No items array to rebind against — the selectedOptions are canonical.
118
+ cloneWithItemRefs: (filter) => ({ ...filter }),
119
+ renderBarControl: ({ filter, updateFilter, controlledFiltering }) => /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
120
+ MultiSelectMenu,
121
+ {
122
+ ...passThroughMenuProps$3(filter),
123
+ id: filter.id,
124
+ label: filter.label,
125
+ value: filter.selectedOptions ?? [],
126
+ onSelectedOptionsChange: (options) => updateFilter(filter.id, options, true),
127
+ confirmation: controlledFiltering,
128
+ clear: {
129
+ onClick: () => updateFilter(filter.id, [], true)
130
+ },
131
+ trigger: (triggerProps) => /* @__PURE__ */ jsx(
132
+ FilterTriggerButton,
133
+ {
134
+ ...triggerProps,
135
+ filterId: filter.id,
136
+ label: formatLabel$8(filter),
137
+ isSelected: isSelected$6(filter)
138
+ }
139
+ )
140
+ }
141
+ ) }, filter.id),
142
+ renderDrawer: ({ originalFilter, draftFilter, onDraftChange }) => /* @__PURE__ */ createElement(
143
+ MultiSelectField,
144
+ {
145
+ ...passThroughMenuProps$3(originalFilter),
146
+ key: draftFilter.id,
147
+ label: originalFilter.label,
148
+ value: draftFilter.selectedOptions ?? [],
149
+ onSelectedOptionsChange: (options) => onDraftChange(draftFilter.id, options)
150
+ }
151
+ ),
152
+ formatLabel: formatLabel$8,
153
+ isSelected: isSelected$6
154
+ };
155
+
156
+ const formatLabel$7 = (filter) => {
157
+ if (filter.selectedOption) {
158
+ return `${filter.label}: ${filter.selectedOption.label}`;
159
+ }
160
+ return filter.label;
161
+ };
162
+ const isSelected$5 = (filter) => filter.selectedOption !== void 0;
163
+ const passThroughMenuProps$2 = (filter) => {
164
+ const {
165
+ id: _id,
166
+ label: _label,
167
+ type: _type,
168
+ selectedOption: _selectedOption,
169
+ drawerOnly: _drawerOnly,
170
+ ...rest
171
+ } = filter;
172
+ return rest;
173
+ };
174
+ const asyncSelectAdapter = {
175
+ getValue: (filter) => filter.selectedOption,
176
+ setValue: (filter, value) => ({ ...filter, selectedOption: value }),
177
+ reset: (filter) => ({ ...filter, selectedOption: void 0 }),
178
+ isActive: isSelected$5,
179
+ preserveState: (newFilter, existingFilter) => ({
180
+ ...newFilter,
181
+ selectedOption: existingFilter.selectedOption
182
+ }),
183
+ // No items array to rebind against — the selectedOption is canonical.
184
+ cloneWithItemRefs: (filter) => ({ ...filter }),
185
+ renderBarControl: ({ filter, updateFilter }) => /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
186
+ SelectMenu,
187
+ {
188
+ ...passThroughMenuProps$2(filter),
189
+ id: filter.id,
190
+ label: filter.label,
191
+ value: filter.selectedOption ?? null,
192
+ onSelectedOptionChange: (option) => updateFilter(filter.id, option ?? void 0, true),
193
+ clear: {
194
+ onClick: () => updateFilter(filter.id, void 0, true)
195
+ },
196
+ trigger: (triggerProps) => /* @__PURE__ */ jsx(
197
+ FilterTriggerButton,
198
+ {
199
+ ...triggerProps,
200
+ filterId: filter.id,
201
+ label: formatLabel$7(filter),
202
+ isSelected: isSelected$5(filter)
203
+ }
204
+ )
205
+ }
206
+ ) }, filter.id),
207
+ renderDrawer: ({ originalFilter, draftFilter, onDraftChange }) => /* @__PURE__ */ createElement(
208
+ SelectField,
209
+ {
210
+ ...passThroughMenuProps$2(originalFilter),
211
+ key: draftFilter.id,
212
+ label: originalFilter.label,
213
+ value: draftFilter.selectedOption ?? null,
214
+ onSelectedOptionChange: (option) => onDraftChange(draftFilter.id, option ?? void 0)
215
+ }
216
+ ),
217
+ formatLabel: formatLabel$7,
218
+ isSelected: isSelected$5
219
+ };
220
+
221
+ const FilterToggleButton = ({
222
+ id,
223
+ checked,
224
+ children,
225
+ ...props
226
+ }) => {
227
+ return /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
228
+ ToolbarButtonToggle,
229
+ {
230
+ id,
231
+ checked,
232
+ isFilter: true,
233
+ ...props,
234
+ className: styles["filter-button-trigger"],
235
+ "data-anv": "toolbar-boolean-filter",
236
+ children
237
+ }
238
+ ) });
239
+ };
240
+
241
+ const booleanAdapter = {
242
+ getValue: (filter) => filter.checked,
243
+ setValue: (filter, value) => ({ ...filter, checked: value }),
244
+ reset: (filter) => ({ ...filter, checked: false }),
245
+ isActive: (filter) => filter.checked,
246
+ preserveState: (newFilter, existingFilter) => ({
247
+ ...newFilter,
248
+ checked: existingFilter.checked
249
+ }),
250
+ cloneWithItemRefs: (filter) => ({ ...filter }),
251
+ renderBarControl: ({ filter, updateFilter }) => /* @__PURE__ */ jsx(
252
+ FilterToggleButton,
253
+ {
254
+ id: filter.id,
255
+ checked: filter.checked,
256
+ onClick: () => updateFilter(filter.id, !filter.checked, true),
257
+ children: filter.label
258
+ },
259
+ filter.id
260
+ ),
261
+ renderDrawer: ({ draftFilter, onDraftChange }) => /* @__PURE__ */ jsx(
262
+ Checkbox,
263
+ {
264
+ label: draftFilter.label,
265
+ checked: draftFilter.checked,
266
+ onChange: (e) => onDraftChange(draftFilter.id, e?.target.checked ?? false)
267
+ },
268
+ draftFilter.id
269
+ ),
270
+ formatLabel: (filter) => filter.label,
271
+ isSelected: (filter) => filter.checked
272
+ };
273
+
274
+ const FilterGroupContext = createContext({
275
+ filterGroupRef: { current: null },
276
+ filters: [],
277
+ updateFilter: () => {
278
+ },
279
+ onFilterChange: () => {
280
+ },
281
+ controlledFiltering: false,
282
+ associatedContent: "",
283
+ showInlineFilters: false,
284
+ drawerOnlyFilters: []
285
+ });
286
+
287
+ const hasChangedFilter = (a, b) => {
288
+ if (Array.isArray(a) && Array.isArray(b)) {
289
+ if (a.length !== b.length) return true;
290
+ if (a.length === 0) return false;
291
+ const aItems = a;
292
+ const bItems = b;
293
+ if (aItems[0] && "id" in aItems[0]) {
294
+ const aIds = new Set(aItems.map((item) => item.id));
295
+ return bItems.some(
296
+ (item) => !aIds.has(item.id)
297
+ );
298
+ }
299
+ return JSON.stringify(a) !== JSON.stringify(b);
300
+ }
301
+ if (a && b && typeof a === "object" && typeof b === "object" && "id" in a && "id" in b) {
302
+ if (a.id !== b.id) return true;
303
+ if ("value" in a && "value" in b) {
304
+ return JSON.stringify(a.value) !== JSON.stringify(b.value);
305
+ }
306
+ return false;
307
+ }
308
+ return a !== b;
309
+ };
310
+
311
+ const FilterPopoverButton = (props) => {
312
+ const { filter, label, isSelected, committedValue, children } = props;
313
+ const commitOnSelect = props.commitOnSelect === true;
314
+ const initialValue = commitOnSelect ? void 0 : props.initialValue;
315
+ const keepOpenOnUncontrolledChange = !commitOnSelect && (props.keepOpenOnUncontrolledChange ?? false);
316
+ const triggerRef = useRef(null);
317
+ const popoverId = useId();
318
+ const [isOpen, setIsOpen] = useState(false);
319
+ const { updateFilter, controlledFiltering } = useContext(FilterGroupContext);
320
+ const [draftValue, setDraftValue] = useState(initialValue);
321
+ const draftValueRef = useRef(draftValue);
322
+ useEffect(() => {
323
+ draftValueRef.current = draftValue;
324
+ }, [draftValue]);
325
+ const prevIsOpenRef = useRef(isOpen);
326
+ const prevCommittedValueRef = useRef(committedValue);
327
+ useEffect(() => {
328
+ if (commitOnSelect) return;
329
+ const justOpened = isOpen && !prevIsOpenRef.current;
330
+ prevIsOpenRef.current = isOpen;
331
+ if (isOpen) {
332
+ const shouldSync = justOpened || prevCommittedValueRef.current !== committedValue;
333
+ if (shouldSync) {
334
+ setDraftValue(committedValue);
335
+ }
336
+ prevCommittedValueRef.current = committedValue;
337
+ }
338
+ }, [isOpen, committedValue, commitOnSelect]);
339
+ const closeAndRestoreFocus = useCallback(() => {
340
+ setIsOpen(false);
341
+ triggerRef.current?.focus();
342
+ }, []);
343
+ const handleDraftChange = useCallback(
344
+ (value) => {
345
+ if (commitOnSelect) {
346
+ if (hasChangedFilter(value, committedValue)) {
347
+ updateFilter(filter.id, value, true);
348
+ }
349
+ closeAndRestoreFocus();
350
+ return;
351
+ }
352
+ if (!hasChangedFilter(value, draftValueRef.current)) return;
353
+ draftValueRef.current = value;
354
+ setDraftValue(value);
355
+ if (!controlledFiltering) {
356
+ updateFilter(filter.id, value, true);
357
+ if (!keepOpenOnUncontrolledChange) {
358
+ closeAndRestoreFocus();
359
+ }
360
+ }
361
+ },
362
+ [
363
+ commitOnSelect,
364
+ committedValue,
365
+ controlledFiltering,
366
+ filter.id,
367
+ keepOpenOnUncontrolledChange,
368
+ updateFilter,
369
+ closeAndRestoreFocus
370
+ ]
371
+ );
372
+ const handleApply = useCallback(() => {
373
+ if (hasChangedFilter(draftValue, committedValue)) {
374
+ updateFilter(filter.id, draftValue, true);
375
+ }
376
+ closeAndRestoreFocus();
377
+ }, [
378
+ draftValue,
379
+ committedValue,
380
+ filter.id,
381
+ updateFilter,
382
+ closeAndRestoreFocus
383
+ ]);
384
+ const handleCancel = useCallback(() => {
385
+ if (!controlledFiltering) {
386
+ closeAndRestoreFocus();
387
+ return;
388
+ }
389
+ setDraftValue(committedValue);
390
+ closeAndRestoreFocus();
391
+ }, [controlledFiltering, committedValue, closeAndRestoreFocus]);
392
+ const handlePopoverClose = useCallback(() => {
393
+ if (commitOnSelect) {
394
+ setIsOpen(false);
395
+ return;
396
+ }
397
+ if (controlledFiltering) {
398
+ setDraftValue(committedValue);
399
+ setIsOpen(false);
400
+ } else if (keepOpenOnUncontrolledChange) {
401
+ setIsOpen(false);
402
+ } else {
403
+ if (hasChangedFilter(draftValueRef.current, committedValue)) {
404
+ updateFilter(filter.id, draftValueRef.current, true);
405
+ }
406
+ setIsOpen(false);
407
+ }
408
+ }, [
409
+ commitOnSelect,
410
+ controlledFiltering,
411
+ keepOpenOnUncontrolledChange,
412
+ committedValue,
413
+ filter.id,
414
+ updateFilter
415
+ ]);
416
+ const bodyValue = commitOnSelect ? committedValue : draftValue;
417
+ const showConfirmationFooter = controlledFiltering && !commitOnSelect;
418
+ useEffect(() => {
419
+ if (!isOpen || !showConfirmationFooter) return;
420
+ const popoverEl = document.getElementById(popoverId);
421
+ if (!popoverEl) return;
422
+ const handler = (e) => {
423
+ if (e.key !== "Enter" || e.defaultPrevented) return;
424
+ handleApply();
425
+ };
426
+ popoverEl.addEventListener("keydown", handler);
427
+ return () => popoverEl.removeEventListener("keydown", handler);
428
+ }, [isOpen, showConfirmationFooter, popoverId, handleApply]);
429
+ return /* @__PURE__ */ jsxs(FilterItemWrapper, { children: [
430
+ /* @__PURE__ */ jsx(
431
+ FilterTriggerButton,
432
+ {
433
+ ref: triggerRef,
434
+ filterId: filter.id,
435
+ label,
436
+ isSelected,
437
+ "aria-haspopup": "dialog",
438
+ "aria-expanded": isOpen,
439
+ "aria-controls": popoverId,
440
+ onClick: () => setIsOpen((prev) => !prev),
441
+ onKeyDown: (e) => {
442
+ if (e.key === "Escape" && isOpen) {
443
+ e.preventDefault();
444
+ handlePopoverClose();
445
+ }
446
+ }
447
+ }
448
+ ),
449
+ /* @__PURE__ */ jsx(
450
+ OptionsPopover,
451
+ {
452
+ id: popoverId,
453
+ referenceElement: triggerRef,
454
+ open: isOpen,
455
+ onClose: handlePopoverClose,
456
+ footer: showConfirmationFooter ? /* @__PURE__ */ jsx(
457
+ MenuFooter,
458
+ {
459
+ confirmation: {
460
+ onApply: handleApply,
461
+ onCancel: handleCancel
462
+ }
463
+ }
464
+ ) : void 0,
465
+ children: children({ value: bodyValue, onChange: handleDraftChange })
466
+ }
467
+ )
468
+ ] });
469
+ };
470
+
471
+ const formatLabel$6 = (filter) => {
472
+ if (filter.labelChipCount) {
473
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
474
+ filter.label,
475
+ /* @__PURE__ */ jsx(
476
+ Chip,
477
+ {
478
+ label: filter.labelChipCount.toString(),
479
+ color: "#0265DC",
480
+ size: "small",
481
+ "aria-label": `${filter.labelChipCount} selected items`
482
+ }
483
+ )
484
+ ] });
485
+ }
486
+ return filter.label;
487
+ };
488
+ const customAdapter = {
489
+ getValue: (filter) => filter.value,
490
+ setValue: (filter, value) => ({ ...filter, value }),
491
+ reset: (filter) => ({ ...filter, value: void 0 }),
492
+ isActive: (filter) => filter.value !== void 0,
493
+ preserveState: (newFilter, existingFilter) => ({
494
+ ...newFilter,
495
+ value: existingFilter.value
496
+ }),
497
+ cloneWithItemRefs: (filter) => {
498
+ const { value } = filter;
499
+ if (value === void 0) return { ...filter, value: void 0 };
500
+ if (Array.isArray(value)) return { ...filter, value: [...value] };
501
+ if (typeof value === "object" && value !== null) {
502
+ return { ...filter, value: { ...value } };
503
+ }
504
+ return { ...filter, value };
505
+ },
506
+ renderBarControl: ({ filter }) => /* @__PURE__ */ jsx(
507
+ FilterPopoverButton,
508
+ {
509
+ filter,
510
+ label: formatLabel$6(filter),
511
+ isSelected: filter.value !== void 0,
512
+ committedValue: filter.value,
513
+ initialValue: void 0,
514
+ children: ({ value, onChange }) => (
515
+ // drawer-only customs are filtered out before reaching
516
+ // renderBarControl, so this guard is purely for TS narrowing across
517
+ // the CustomFilter union (buttonRender is `never` when drawerOnly).
518
+ filter.drawerOnly ? null : filter.buttonRender({ value, onChange })
519
+ )
520
+ },
521
+ filter.id
522
+ ),
523
+ renderDrawer: ({ originalFilter, draftFilter, onDraftChange }) => /* @__PURE__ */ jsx("div", { children: originalFilter.drawerRender?.({
524
+ value: draftFilter.value,
525
+ onChange: (value) => onDraftChange(draftFilter.id, value)
526
+ }) }, draftFilter.id),
527
+ formatLabel: formatLabel$6,
528
+ isSelected: (filter) => filter.value !== void 0
529
+ };
530
+
531
+ const FilterDateSingle = (props) => {
532
+ if (props.variant === "inline") {
533
+ return /* @__PURE__ */ jsx(
534
+ Body$1,
535
+ {
536
+ filter: props.filter,
537
+ value: props.draftValue,
538
+ onChange: props.onDraftChange
539
+ }
540
+ );
541
+ }
542
+ return /* @__PURE__ */ jsx(PopoverShell$1, { ...props });
543
+ };
544
+ const Body$1 = ({
545
+ filter,
546
+ value: draftValue,
547
+ onChange: onDraftChange
548
+ }) => {
549
+ const maskedDateInputRef = useRef(null);
550
+ const handleChange = (change) => {
551
+ onDraftChange(change.date);
552
+ };
553
+ const { value, onChange } = useDateFieldSingleConversion({
554
+ value: draftValue,
555
+ onChange: handleChange
556
+ });
557
+ const { handleInputChange, handleCalendarSelection } = useDateFieldSingleState({
558
+ valueProp: value,
559
+ onChange: (change) => onChange({ ...change, isDateValid: true })
560
+ });
561
+ return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
562
+ /* @__PURE__ */ jsx(
563
+ MaskedDateInput,
564
+ {
565
+ mode: filter.mode,
566
+ ref: maskedDateInputRef,
567
+ onChange: handleInputChange,
568
+ lastValidDate: value ?? null,
569
+ autoComplete: "off"
570
+ }
571
+ ),
572
+ /* @__PURE__ */ jsx(
573
+ DateFieldSingleCalendar,
574
+ {
575
+ value: value ?? null,
576
+ onSelection: handleCalendarSelection
577
+ }
578
+ )
579
+ ] });
580
+ };
581
+ const PopoverShell$1 = ({
582
+ filter,
583
+ committedValue,
584
+ onCommit,
585
+ controlledFiltering,
586
+ label,
587
+ isSelected,
588
+ clear
589
+ }) => {
590
+ const triggerRef = useRef(null);
591
+ const popoverId = useId();
592
+ const [isOpen, setIsOpen] = useState(false);
593
+ const isEqual = useCallback(
594
+ (a, b) => !hasChangedFilter(a, b),
595
+ []
596
+ );
597
+ const { displayValue, setDraft, apply, cancel } = useConfirmationDraft(
598
+ {
599
+ value: committedValue,
600
+ onCommit,
601
+ isOpen,
602
+ enabled: controlledFiltering,
603
+ isEqual
604
+ }
605
+ );
606
+ const handleClose = useCallback(() => {
607
+ if (controlledFiltering) {
608
+ cancel();
609
+ }
610
+ setIsOpen(false);
611
+ }, [controlledFiltering, cancel]);
612
+ const handleApply = useCallback(() => {
613
+ apply();
614
+ setIsOpen(false);
615
+ }, [apply]);
616
+ return /* @__PURE__ */ jsxs(FilterItemWrapper, { children: [
617
+ /* @__PURE__ */ jsx(
618
+ FilterTriggerButton,
619
+ {
620
+ ref: triggerRef,
621
+ filterId: filter.id,
622
+ label,
623
+ isSelected,
624
+ icon: "calendar",
625
+ "aria-haspopup": "dialog",
626
+ "aria-expanded": isOpen,
627
+ onClick: () => setIsOpen((prev) => !prev)
628
+ }
629
+ ),
630
+ /* @__PURE__ */ jsx(
631
+ OptionsPopover,
632
+ {
633
+ id: popoverId,
634
+ referenceElement: triggerRef,
635
+ open: isOpen,
636
+ onClose: handleClose,
637
+ footer: clear || controlledFiltering ? /* @__PURE__ */ jsx(
638
+ MenuFooter,
639
+ {
640
+ clear: clear ? {
641
+ ...clear,
642
+ onClick: () => {
643
+ clear.onClick();
644
+ setIsOpen(false);
645
+ triggerRef.current?.focus();
646
+ }
647
+ } : void 0,
648
+ confirmation: controlledFiltering ? {
649
+ onApply: handleApply,
650
+ onCancel: handleClose
651
+ } : void 0
652
+ }
653
+ ) : void 0,
654
+ children: /* @__PURE__ */ jsx(Body$1, { filter, value: displayValue, onChange: setDraft })
655
+ }
656
+ )
657
+ ] });
658
+ };
659
+
660
+ const formatLabel$5 = (filter) => {
661
+ if (filter.value) {
662
+ const date = DateTime.fromISO(filter.value, { zone: "local" });
663
+ return `${filter.label}: ${date.monthShort} ${date.day}, ${date.year}`;
664
+ }
665
+ return filter.label;
666
+ };
667
+ const dateAdapter = {
668
+ getValue: (filter) => filter.value ?? null,
669
+ setValue: (filter, value) => ({ ...filter, value }),
670
+ reset: (filter) => ({ ...filter, value: null }),
671
+ isActive: (filter) => filter.value !== null && filter.value !== void 0,
672
+ preserveState: (newFilter, existingFilter) => ({
673
+ ...newFilter,
674
+ value: existingFilter.value
675
+ }),
676
+ cloneWithItemRefs: (filter) => ({ ...filter, value: filter.value ?? null }),
677
+ renderBarControl: ({ filter, updateFilter, controlledFiltering }) => /* @__PURE__ */ jsx(
678
+ FilterDateSingle,
679
+ {
680
+ filter,
681
+ committedValue: filter.value ?? null,
682
+ onCommit: (value) => updateFilter(filter.id, value, true),
683
+ controlledFiltering,
684
+ label: formatLabel$5(filter),
685
+ isSelected: !!filter.value,
686
+ clear: {
687
+ onClick: () => updateFilter(filter.id, null, true)
688
+ }
689
+ },
690
+ filter.id
691
+ ),
692
+ renderDrawer: ({ draftFilter, onDraftChange }) => /* @__PURE__ */ jsx(
693
+ DateFieldSingle,
694
+ {
695
+ label: draftFilter.label,
696
+ value: draftFilter.value ?? null,
697
+ onChange: (change) => onDraftChange(draftFilter.id, change.date),
698
+ mode: draftFilter.mode
699
+ },
700
+ draftFilter.id
701
+ ),
702
+ formatLabel: formatLabel$5,
703
+ isSelected: (filter) => !!filter.value
704
+ };
705
+
706
+ const FilterDateRange = (props) => {
707
+ if (props.variant === "inline") {
708
+ return /* @__PURE__ */ jsx(
709
+ Body,
710
+ {
711
+ filter: props.filter,
712
+ value: props.draftValue,
713
+ onChange: props.onDraftChange
714
+ }
715
+ );
716
+ }
717
+ return /* @__PURE__ */ jsx(PopoverShell, { ...props });
718
+ };
719
+ const Body = ({
720
+ filter,
721
+ value: draftValue,
722
+ onChange: onDraftChange
723
+ }) => {
724
+ const maskedDateRangeInputRef = useRef(null);
725
+ const handleChange = (change) => {
726
+ const hasCompleteRange = change.startDate && change.endDate;
727
+ const isClearingRange = !change.startDate && !change.endDate;
728
+ if (hasCompleteRange || isClearingRange) {
729
+ onDraftChange({
730
+ startDate: change.startDate,
731
+ endDate: change.endDate
732
+ });
733
+ }
734
+ };
735
+ const { value, onChange } = useDateFieldRangeConversion({
736
+ value: draftValue,
737
+ onChange: handleChange
738
+ });
739
+ const { handleInputChange, handleCalendarSelection } = useDateFieldRangeState(
740
+ {
741
+ valueProp: value,
742
+ onChange: (change) => {
743
+ const hasCompleteRange = change.startDate && change.endDate;
744
+ const isClearingRange = change.isInputEmpty;
745
+ if (change.isInputValid && hasCompleteRange || isClearingRange) {
746
+ onChange({ ...change, isDateRangeValid: true });
747
+ }
748
+ }
749
+ }
750
+ );
751
+ return /* @__PURE__ */ jsxs(Flex, { gap: 4, direction: "column", children: [
752
+ /* @__PURE__ */ jsx(
753
+ MaskedDateRangeInput,
754
+ {
755
+ mode: filter.mode,
756
+ ref: maskedDateRangeInputRef,
757
+ onChange: handleInputChange,
758
+ startDate: value?.startDate ?? null,
759
+ endDate: value?.endDate ?? null,
760
+ autoComplete: "off"
761
+ }
762
+ ),
763
+ /* @__PURE__ */ jsx(
764
+ DateFieldRangeCalendar,
765
+ {
766
+ startDate: value?.startDate ?? null,
767
+ endDate: value?.endDate ?? null,
768
+ onSelection: handleCalendarSelection
769
+ }
770
+ )
771
+ ] });
772
+ };
773
+ const PopoverShell = ({
774
+ filter,
775
+ committedValue,
776
+ onCommit,
777
+ controlledFiltering,
778
+ label,
779
+ isSelected,
780
+ clear
781
+ }) => {
782
+ const triggerRef = useRef(null);
783
+ const popoverId = useId();
784
+ const [isOpen, setIsOpen] = useState(false);
785
+ const isEqual = useCallback(
786
+ (a, b) => !hasChangedFilter(a, b),
787
+ []
788
+ );
789
+ const { displayValue, setDraft, apply, cancel } = useConfirmationDraft(
790
+ {
791
+ value: committedValue,
792
+ onCommit,
793
+ isOpen,
794
+ enabled: controlledFiltering,
795
+ isEqual
796
+ }
797
+ );
798
+ const handleClose = useCallback(() => {
799
+ if (controlledFiltering) {
800
+ cancel();
801
+ }
802
+ setIsOpen(false);
803
+ }, [controlledFiltering, cancel]);
804
+ const handleApply = useCallback(() => {
805
+ apply();
806
+ setIsOpen(false);
807
+ }, [apply]);
808
+ return /* @__PURE__ */ jsxs(FilterItemWrapper, { children: [
809
+ /* @__PURE__ */ jsx(
810
+ FilterTriggerButton,
811
+ {
812
+ ref: triggerRef,
813
+ filterId: filter.id,
814
+ label,
815
+ isSelected,
816
+ icon: "calendar",
817
+ "aria-haspopup": "dialog",
818
+ "aria-expanded": isOpen,
819
+ onClick: () => setIsOpen((prev) => !prev)
820
+ }
821
+ ),
822
+ /* @__PURE__ */ jsx(
823
+ OptionsPopover,
824
+ {
825
+ id: popoverId,
826
+ referenceElement: triggerRef,
827
+ open: isOpen,
828
+ onClose: handleClose,
829
+ footer: clear || controlledFiltering ? /* @__PURE__ */ jsx(
830
+ MenuFooter,
831
+ {
832
+ clear: clear ? {
833
+ ...clear,
834
+ onClick: () => {
835
+ clear.onClick();
836
+ setIsOpen(false);
837
+ triggerRef.current?.focus();
838
+ }
839
+ } : void 0,
840
+ confirmation: controlledFiltering ? {
841
+ onApply: handleApply,
842
+ onCancel: handleClose
843
+ } : void 0
844
+ }
845
+ ) : void 0,
846
+ children: /* @__PURE__ */ jsx(Body, { filter, value: displayValue, onChange: setDraft })
847
+ }
848
+ )
849
+ ] });
850
+ };
851
+
852
+ const LIBRARY_OPTION_LABELS = {
853
+ on: "On",
854
+ before: "Before",
855
+ after: "After",
856
+ customRange: "Custom Range"
857
+ };
858
+ const LIBRARY_OPTION_IDS_ORDERED = [
859
+ "on",
860
+ "before",
861
+ "after",
862
+ "customRange"
863
+ ];
864
+ const LIBRARY_OPTION_ID_SET = new Set(LIBRARY_OPTION_IDS_ORDERED);
865
+ const isDateListLibraryOptionId = (id) => LIBRARY_OPTION_ID_SET.has(id);
866
+ const getDateListLibraryOptionLabel = (id) => LIBRARY_OPTION_LABELS[id];
867
+ const dateListLibraryOptions = LIBRARY_OPTION_IDS_ORDERED.map((id) => ({
868
+ id,
869
+ label: `${LIBRARY_OPTION_LABELS[id]}…`
870
+ }));
871
+ const isDateListRangeLibraryId = (id) => id === "customRange";
872
+ const formatDateForLabel = (iso) => {
873
+ const d = DateTime.fromISO(iso, { zone: "local" });
874
+ return `${d.monthShort} ${d.day}, ${d.year}`;
875
+ };
876
+ const formatRangeForLabel = (range) => {
877
+ const start = DateTime.fromISO(range.startDate, { zone: "local" });
878
+ const end = DateTime.fromISO(range.endDate, { zone: "local" });
879
+ const sameYear = start.year === end.year;
880
+ const formattedStart = sameYear ? `${start.monthShort} ${start.day}` : `${start.monthShort} ${start.day}, ${start.year}`;
881
+ return `${formattedStart} – ${end.monthShort} ${end.day}, ${end.year}`;
882
+ };
883
+ const formatDateListSelectionLabel = (selection) => {
884
+ if (selection.value === null) return selection.label;
885
+ const formatted = typeof selection.value === "string" ? formatDateForLabel(selection.value) : formatRangeForLabel(selection.value);
886
+ if (selection.id === "customRange") return formatted;
887
+ return `${selection.label}: ${formatted}`;
888
+ };
889
+
890
+ const DateListDialog = ({
891
+ libraryId,
892
+ parentFilterId,
893
+ initialValue,
894
+ mode,
895
+ dialogCtaLabel,
896
+ onCommit,
897
+ onCancel
898
+ }) => {
899
+ const [dateDraft, setDateDraft] = useState(null);
900
+ const [rangeDraft, setRangeDraft] = useState(null);
901
+ useEffect(() => {
902
+ if (!libraryId) return;
903
+ if (isDateListRangeLibraryId(libraryId)) {
904
+ setRangeDraft(
905
+ initialValue && typeof initialValue === "object" ? {
906
+ startDate: initialValue.startDate,
907
+ endDate: initialValue.endDate
908
+ } : null
909
+ );
910
+ setDateDraft(null);
911
+ } else {
912
+ setDateDraft(typeof initialValue === "string" ? initialValue : null);
913
+ setRangeDraft(null);
914
+ }
915
+ }, [libraryId, initialValue]);
916
+ const dialogOpen = libraryId !== null;
917
+ const dialogLabel = libraryId ? getDateListLibraryOptionLabel(libraryId) : "";
918
+ const isRange = libraryId ? isDateListRangeLibraryId(libraryId) : false;
919
+ const canCommit = isRange ? Boolean(rangeDraft?.startDate && rangeDraft?.endDate) : Boolean(dateDraft);
920
+ const handleCommit = () => {
921
+ if (!libraryId) return;
922
+ if (isRange) {
923
+ if (!rangeDraft?.startDate || !rangeDraft?.endDate) return;
924
+ onCommit({
925
+ id: libraryId,
926
+ label: dialogLabel,
927
+ value: {
928
+ startDate: rangeDraft.startDate,
929
+ endDate: rangeDraft.endDate
930
+ }
931
+ });
932
+ } else {
933
+ if (!dateDraft) return;
934
+ onCommit({ id: libraryId, label: dialogLabel, value: dateDraft });
935
+ }
936
+ };
937
+ return /* @__PURE__ */ jsx(Dialog, { open: dialogOpen, onClose: onCancel, children: libraryId && /* @__PURE__ */ jsxs(Fragment, { children: [
938
+ /* @__PURE__ */ jsx(Dialog.Header, { children: dialogLabel }),
939
+ /* @__PURE__ */ jsx(Dialog.Content, { children: isRange ? /* @__PURE__ */ jsx(
940
+ FilterDateRange,
941
+ {
942
+ variant: "inline",
943
+ filter: {
944
+ id: `${parentFilterId}--date-list-dialog-range`,
945
+ label: dialogLabel,
946
+ type: "dateRange",
947
+ value: rangeDraft,
948
+ mode
949
+ },
950
+ draftValue: rangeDraft,
951
+ onDraftChange: setRangeDraft
952
+ }
953
+ ) : /* @__PURE__ */ jsx(
954
+ FilterDateSingle,
955
+ {
956
+ variant: "inline",
957
+ filter: {
958
+ id: `${parentFilterId}--date-list-dialog-date`,
959
+ label: dialogLabel,
960
+ type: "date",
961
+ value: dateDraft,
962
+ mode
963
+ },
964
+ draftValue: dateDraft,
965
+ onDraftChange: setDateDraft
966
+ }
967
+ ) }),
968
+ /* @__PURE__ */ jsx(Dialog.Footer, { children: /* @__PURE__ */ jsxs(Flex, { gap: 2, justifyContent: "flex-end", children: [
969
+ /* @__PURE__ */ jsx(Dialog.CancelButton, { appearance: "ghost", "aria-label": "Cancel", children: "Cancel" }),
970
+ /* @__PURE__ */ jsx(
971
+ Button,
972
+ {
973
+ appearance: "primary",
974
+ disabled: !canCommit,
975
+ onClick: handleCommit,
976
+ children: dialogCtaLabel
977
+ }
978
+ )
979
+ ] }) })
980
+ ] }) });
981
+ };
982
+ const FilterDateList = ({
983
+ filter,
984
+ committedValue,
985
+ onCommit,
986
+ label,
987
+ isSelected,
988
+ dialogCtaLabel,
989
+ clear
990
+ }) => {
991
+ const [openLibraryId, setOpenLibraryId] = useState(null);
992
+ useEffect(() => {
993
+ const libraryLabels = new Set(dateListLibraryOptions.map((o) => o.label));
994
+ filter.options.forEach((opt) => {
995
+ if (isDateListLibraryOptionId(opt.id)) {
996
+ warnOnce(
997
+ `[FilterDateList] Consumer option id "${opt.id}" is reserved for a library option ("on", "before", "after", "customRange"). Use a different id.`
998
+ );
999
+ }
1000
+ if (libraryLabels.has(opt.label)) {
1001
+ warnOnce(
1002
+ `[FilterDateList] Consumer option label "${opt.label}" collides with a library option label ("On…", "Before…", "After…", "Custom Range…"). Use a different label.`
1003
+ );
1004
+ }
1005
+ });
1006
+ }, [filter.options]);
1007
+ const options = useMemo(
1008
+ () => [
1009
+ ...filter.options.map(
1010
+ (opt) => ({ id: opt.id, label: opt.label })
1011
+ ),
1012
+ ...dateListLibraryOptions.map(
1013
+ (opt) => ({ id: opt.id, label: opt.label })
1014
+ )
1015
+ ],
1016
+ [filter.options]
1017
+ );
1018
+ const selectedOption = useMemo(
1019
+ () => committedValue ? options.find((opt) => opt.id === committedValue.id) ?? null : null,
1020
+ [options, committedValue]
1021
+ );
1022
+ const handleSelectedOptionChange = (option) => {
1023
+ if (!option) {
1024
+ onCommit(void 0);
1025
+ return;
1026
+ }
1027
+ const id = String(option.id);
1028
+ if (isDateListLibraryOptionId(id)) {
1029
+ setOpenLibraryId(id);
1030
+ return;
1031
+ }
1032
+ const consumerOption = filter.options.find((opt) => opt.id === id);
1033
+ if (!consumerOption) return;
1034
+ onCommit({
1035
+ id: consumerOption.id,
1036
+ label: consumerOption.label,
1037
+ value: consumerOption.value
1038
+ });
1039
+ };
1040
+ const dialogInitialValue = openLibraryId && committedValue?.id === openLibraryId && committedValue.value !== null ? committedValue.value : void 0;
1041
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1042
+ /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
1043
+ SelectMenuSync,
1044
+ {
1045
+ id: filter.id,
1046
+ label: filter.label,
1047
+ options,
1048
+ value: selectedOption,
1049
+ onSelectedOptionChange: handleSelectedOptionChange,
1050
+ disableSearch: true,
1051
+ clear,
1052
+ trigger: (triggerProps) => /* @__PURE__ */ jsx(
1053
+ FilterTriggerButton,
1054
+ {
1055
+ ...triggerProps,
1056
+ filterId: filter.id,
1057
+ label,
1058
+ isSelected,
1059
+ icon: "calendar"
1060
+ }
1061
+ )
1062
+ }
1063
+ ) }),
1064
+ /* @__PURE__ */ jsx(
1065
+ DateListDialog,
1066
+ {
1067
+ libraryId: openLibraryId,
1068
+ parentFilterId: filter.id,
1069
+ initialValue: dialogInitialValue,
1070
+ mode: filter.mode,
1071
+ dialogCtaLabel,
1072
+ onCommit: (option) => {
1073
+ onCommit(option);
1074
+ setOpenLibraryId(null);
1075
+ },
1076
+ onCancel: () => setOpenLibraryId(null)
1077
+ }
1078
+ )
1079
+ ] });
1080
+ };
1081
+
1082
+ const isSelected$4 = (filter) => filter.selectedOption !== void 0 && filter.selectedOption.value !== null;
1083
+ const formatLabel$4 = (filter) => {
1084
+ const selected = filter.selectedOption;
1085
+ if (!selected || selected.value === null) return filter.label;
1086
+ return formatDateListSelectionLabel(selected);
1087
+ };
1088
+ const dateListAdapter = {
1089
+ getValue: (filter) => filter.selectedOption,
1090
+ setValue: (filter, value) => ({ ...filter, selectedOption: value }),
1091
+ reset: (filter) => ({ ...filter, selectedOption: void 0 }),
1092
+ isActive: isSelected$4,
1093
+ preserveState: (newFilter, existingFilter) => ({
1094
+ ...newFilter,
1095
+ selectedOption: existingFilter.selectedOption
1096
+ }),
1097
+ cloneWithItemRefs: (filter) => ({ ...filter }),
1098
+ renderBarControl: ({ filter, updateFilter }) => /* @__PURE__ */ jsx(
1099
+ FilterDateList,
1100
+ {
1101
+ filter,
1102
+ committedValue: filter.selectedOption,
1103
+ onCommit: (value) => updateFilter(filter.id, value, true),
1104
+ label: formatLabel$4(filter),
1105
+ isSelected: isSelected$4(filter),
1106
+ dialogCtaLabel: "Apply",
1107
+ clear: {
1108
+ onClick: () => updateFilter(filter.id, void 0, true)
1109
+ }
1110
+ },
1111
+ filter.id
1112
+ ),
1113
+ renderDrawer: ({
1114
+ originalFilter,
1115
+ draftFilter,
1116
+ onDraftChange,
1117
+ requestDateListDialog
1118
+ }) => {
1119
+ const consumerSelectOptions = originalFilter.options.map((opt) => ({
1120
+ id: opt.id,
1121
+ label: opt.label,
1122
+ extra: { value: opt.value }
1123
+ }));
1124
+ const librarySelectOptions = dateListLibraryOptions.map((opt) => ({
1125
+ id: opt.id,
1126
+ label: opt.label,
1127
+ extra: { value: null }
1128
+ }));
1129
+ const allSelectOptions = [
1130
+ ...consumerSelectOptions,
1131
+ ...librarySelectOptions
1132
+ ];
1133
+ const selectedSelectOption = draftFilter.selectedOption ? {
1134
+ id: draftFilter.selectedOption.id,
1135
+ label: formatDateListSelectionLabel(draftFilter.selectedOption),
1136
+ extra: {
1137
+ value: draftFilter.selectedOption.value
1138
+ }
1139
+ } : null;
1140
+ return /* @__PURE__ */ jsx(
1141
+ SelectFieldSync,
1142
+ {
1143
+ label: originalFilter.label,
1144
+ placeholder: "Select an option...",
1145
+ disableSearch: true,
1146
+ options: allSelectOptions,
1147
+ value: selectedSelectOption,
1148
+ onSelectedOptionChange: (option) => {
1149
+ if (!option) {
1150
+ onDraftChange(draftFilter.id, void 0);
1151
+ return;
1152
+ }
1153
+ const id = String(option.id);
1154
+ if (isDateListLibraryOptionId(id)) {
1155
+ requestDateListDialog(draftFilter.id, id);
1156
+ return;
1157
+ }
1158
+ onDraftChange(draftFilter.id, {
1159
+ id,
1160
+ label: option.label,
1161
+ value: option.extra?.value ?? null
1162
+ });
1163
+ }
1164
+ },
1165
+ draftFilter.id
1166
+ );
1167
+ },
1168
+ formatLabel: formatLabel$4,
1169
+ isSelected: isSelected$4
1170
+ };
1171
+
1172
+ const formatLabel$3 = (filter) => {
1173
+ if (filter.value?.startDate && filter.value?.endDate) {
1174
+ const start = DateTime.fromISO(filter.value.startDate, {
1175
+ zone: "local"
1176
+ });
1177
+ const end = DateTime.fromISO(filter.value.endDate, {
1178
+ zone: "local"
1179
+ });
1180
+ const isSameYear = start.year === end.year;
1181
+ const formattedStart = isSameYear ? `${start.monthShort} ${start.day}` : `${start.monthShort} ${start.day}, ${start.year}`;
1182
+ return `${filter.label}: ${formattedStart} – ${end.monthShort} ${end.day}, ${end.year}`;
1183
+ }
1184
+ return filter.label;
1185
+ };
1186
+ const isSelected$3 = (filter) => !!(filter.value?.startDate && filter.value?.endDate);
1187
+ const dateRangeAdapter = {
1188
+ getValue: (filter) => filter.value ?? null,
1189
+ setValue: (filter, value) => ({ ...filter, value }),
1190
+ reset: (filter) => ({ ...filter, value: null }),
1191
+ isActive: (filter) => filter.value !== null && filter.value !== void 0 && filter.value.startDate !== null && filter.value.endDate !== null,
1192
+ preserveState: (newFilter, existingFilter) => ({
1193
+ ...newFilter,
1194
+ value: existingFilter.value
1195
+ }),
1196
+ cloneWithItemRefs: (filter) => ({
1197
+ ...filter,
1198
+ value: filter.value ?? null
1199
+ }),
1200
+ renderBarControl: ({ filter, updateFilter, controlledFiltering }) => /* @__PURE__ */ jsx(
1201
+ FilterDateRange,
1202
+ {
1203
+ filter,
1204
+ committedValue: filter.value ?? null,
1205
+ onCommit: (value) => updateFilter(filter.id, value, true),
1206
+ controlledFiltering,
1207
+ label: formatLabel$3(filter),
1208
+ isSelected: isSelected$3(filter),
1209
+ clear: {
1210
+ onClick: () => updateFilter(filter.id, null, true)
1211
+ }
1212
+ },
1213
+ filter.id
1214
+ ),
1215
+ renderDrawer: ({ draftFilter, onDraftChange }) => /* @__PURE__ */ jsx(
1216
+ DateFieldRange,
1217
+ {
1218
+ label: draftFilter.label,
1219
+ value: draftFilter.value ?? null,
1220
+ onChange: (change) => onDraftChange(draftFilter.id, {
1221
+ startDate: change.startDate,
1222
+ endDate: change.endDate
1223
+ }),
1224
+ mode: draftFilter.mode
1225
+ },
1226
+ draftFilter.id
1227
+ ),
1228
+ formatLabel: formatLabel$3,
1229
+ isSelected: isSelected$3
1230
+ };
1231
+
1232
+ const isSelected$2 = (filter) => !!filter.selectedOptions && filter.selectedOptions.length > 0;
1233
+ const formatLabel$2 = (filter) => {
1234
+ const count = filter.selectedOptions?.length ?? 0;
1235
+ if (count === 0) return filter.label;
1236
+ const countLabel = count.toString();
1237
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1238
+ filter.label,
1239
+ /* @__PURE__ */ jsx(
1240
+ Chip,
1241
+ {
1242
+ label: countLabel,
1243
+ color: "#0265DC",
1244
+ size: "small",
1245
+ "aria-label": `${countLabel} selected items`
1246
+ }
1247
+ )
1248
+ ] });
1249
+ };
1250
+ const passThroughMenuProps$1 = (filter) => {
1251
+ const {
1252
+ id: _id,
1253
+ label: _label,
1254
+ type: _type,
1255
+ selectedOptions: _selectedOptions,
1256
+ simpleDrawerVariant: _simpleDrawerVariant,
1257
+ drawerOnly: _drawerOnly,
1258
+ ...rest
1259
+ } = filter;
1260
+ return rest;
1261
+ };
1262
+ const multiSelectAdapter = {
1263
+ getValue: (filter) => filter.selectedOptions ?? [],
1264
+ setValue: (filter, value) => ({ ...filter, selectedOptions: value }),
1265
+ reset: (filter) => ({ ...filter, selectedOptions: [] }),
1266
+ isActive: isSelected$2,
1267
+ preserveState: (newFilter, existingFilter) => ({
1268
+ ...newFilter,
1269
+ selectedOptions: existingFilter.selectedOptions
1270
+ }),
1271
+ // Options are owned by the consumer; MultiSelectMenuSync handles identity
1272
+ // internally — no rebinding needed.
1273
+ cloneWithItemRefs: (filter) => ({ ...filter }),
1274
+ renderBarControl: ({ filter, updateFilter, controlledFiltering }) => /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
1275
+ MultiSelectMenuSync,
1276
+ {
1277
+ ...passThroughMenuProps$1(filter),
1278
+ id: filter.id,
1279
+ label: filter.label,
1280
+ value: filter.selectedOptions ?? [],
1281
+ onSelectedOptionsChange: (options) => updateFilter(filter.id, options, true),
1282
+ confirmation: controlledFiltering,
1283
+ clear: {
1284
+ onClick: () => updateFilter(filter.id, [], true)
1285
+ },
1286
+ trigger: (triggerProps) => /* @__PURE__ */ jsx(
1287
+ FilterTriggerButton,
1288
+ {
1289
+ ...triggerProps,
1290
+ filterId: filter.id,
1291
+ label: formatLabel$2(filter),
1292
+ isSelected: isSelected$2(filter)
1293
+ }
1294
+ )
1295
+ }
1296
+ ) }, filter.id),
1297
+ renderDrawer: ({ originalFilter, draftFilter, onDraftChange }) => {
1298
+ if (originalFilter.simpleDrawerVariant) {
1299
+ return /* @__PURE__ */ jsx(Checkbox.Group, { legend: originalFilter.label, children: originalFilter.options.map((option) => /* @__PURE__ */ jsx(
1300
+ Checkbox,
1301
+ {
1302
+ label: option.label,
1303
+ checked: draftFilter.selectedOptions?.some(
1304
+ (selected) => selected.id === option.id
1305
+ ) ?? false,
1306
+ onChange: (e) => {
1307
+ const currentSelected = draftFilter.selectedOptions ?? [];
1308
+ if (e?.target.checked) {
1309
+ onDraftChange(draftFilter.id, [...currentSelected, option]);
1310
+ } else {
1311
+ onDraftChange(
1312
+ draftFilter.id,
1313
+ currentSelected.filter(
1314
+ (selected) => selected.id !== option.id
1315
+ )
1316
+ );
1317
+ }
1318
+ }
1319
+ },
1320
+ option.id
1321
+ )) }, draftFilter.id);
1322
+ }
1323
+ return /* @__PURE__ */ createElement(
1324
+ MultiSelectFieldSync,
1325
+ {
1326
+ ...passThroughMenuProps$1(originalFilter),
1327
+ key: draftFilter.id,
1328
+ label: originalFilter.label,
1329
+ value: draftFilter.selectedOptions ?? [],
1330
+ onSelectedOptionsChange: (options) => onDraftChange(draftFilter.id, options)
1331
+ }
1332
+ );
1333
+ },
1334
+ formatLabel: formatLabel$2,
1335
+ isSelected: isSelected$2
1336
+ };
1337
+
1338
+ const clampToBounds = (n, minValue, maxValue) => {
1339
+ if (n === void 0) return void 0;
1340
+ let result = n;
1341
+ if (minValue !== void 0) result = Math.max(result, minValue);
1342
+ if (maxValue !== void 0) result = Math.min(result, maxValue);
1343
+ return result;
1344
+ };
1345
+ const FilterNumericRange = ({
1346
+ filter,
1347
+ value,
1348
+ onChange,
1349
+ layout
1350
+ }) => {
1351
+ const inclusive = filter.inclusiveBounds === true;
1352
+ const minFieldLabel = inclusive ? "Min" : "Above";
1353
+ const maxFieldLabel = inclusive ? "Max" : "Below";
1354
+ const minimumFractionDigits = filter.minimumFractionDigits ?? (filter.mode === "currency" ? 2 : filter.mode === "percentage" ? 0 : void 0);
1355
+ const maximumFractionDigits = filter.maximumFractionDigits ?? (filter.mode === "currency" ? 2 : filter.mode === "percentage" ? 3 : void 0);
1356
+ const decoratorProps = {
1357
+ ...filter.mode === "currency" && { prefix: "$" },
1358
+ ...filter.mode === "percentage" && { suffix: "%" },
1359
+ ...minimumFractionDigits !== void 0 && { minimumFractionDigits },
1360
+ ...maximumFractionDigits !== void 0 && { maximumFractionDigits }
1361
+ };
1362
+ const update = (next) => {
1363
+ const min = clampToBounds(next.min, filter.minValue, filter.maxValue);
1364
+ const max = clampToBounds(next.max, filter.minValue, filter.maxValue);
1365
+ onChange(min === void 0 && max === void 0 ? null : { min, max });
1366
+ };
1367
+ const sharedNumberFieldProps = {
1368
+ hideControls: filter.hideControls ?? true,
1369
+ step: filter.step,
1370
+ minValue: filter.minValue,
1371
+ maxValue: filter.maxValue,
1372
+ ...decoratorProps
1373
+ };
1374
+ const minField = /* @__PURE__ */ jsx(
1375
+ NumberField,
1376
+ {
1377
+ label: minFieldLabel,
1378
+ value: value?.min ?? null,
1379
+ onChange: (n) => update({ min: n ?? void 0, max: value?.max }),
1380
+ ...sharedNumberFieldProps
1381
+ }
1382
+ );
1383
+ const maxField = /* @__PURE__ */ jsx(
1384
+ NumberField,
1385
+ {
1386
+ label: maxFieldLabel,
1387
+ value: value?.max ?? null,
1388
+ onChange: (n) => update({ min: value?.min, max: n ?? void 0 }),
1389
+ ...sharedNumberFieldProps
1390
+ }
1391
+ );
1392
+ if (layout === "compact") {
1393
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", grow: 1, children: [
1394
+ minField,
1395
+ maxField
1396
+ ] });
1397
+ }
1398
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", grow: 1, children: [
1399
+ /* @__PURE__ */ jsx(FieldLabel, { children: filter.label }),
1400
+ /* @__PURE__ */ jsxs(Grid, { templateColumns: "1fr auto 1fr", gap: "2", children: [
1401
+ minField,
1402
+ /* @__PURE__ */ jsx(
1403
+ Flex,
1404
+ {
1405
+ alignItems: "center",
1406
+ justifyContent: "center",
1407
+ className: styles["filter-numeric-range-separator"],
1408
+ children: /* @__PURE__ */ jsx(Text, { children: "to" })
1409
+ }
1410
+ ),
1411
+ maxField
1412
+ ] })
1413
+ ] });
1414
+ };
1415
+
1416
+ const formatBound = (n, filter) => {
1417
+ const minimumFractionDigits = filter.minimumFractionDigits ?? (filter.mode === "currency" ? 2 : filter.mode === "percentage" ? 0 : void 0);
1418
+ const maximumFractionDigits = filter.maximumFractionDigits ?? (filter.mode === "currency" ? 2 : filter.mode === "percentage" ? 3 : void 0);
1419
+ const formatOptions = {};
1420
+ if (minimumFractionDigits !== void 0) {
1421
+ formatOptions.minimumFractionDigits = minimumFractionDigits;
1422
+ }
1423
+ if (maximumFractionDigits !== void 0) {
1424
+ formatOptions.maximumFractionDigits = maximumFractionDigits;
1425
+ }
1426
+ const formatted = n.toLocaleString("en-US", formatOptions);
1427
+ if (filter.mode === "currency") return `$${formatted}`;
1428
+ if (filter.mode === "percentage") return `${formatted}%`;
1429
+ return formatted;
1430
+ };
1431
+ const formatLabel$1 = (filter) => {
1432
+ const hasMin = filter.value?.min !== void 0;
1433
+ const hasMax = filter.value?.max !== void 0;
1434
+ if (!hasMin && !hasMax) return filter.label;
1435
+ const inclusive = filter.inclusiveBounds === true;
1436
+ const minSymbol = inclusive ? "≥" : ">";
1437
+ const maxSymbol = inclusive ? "≤" : "<";
1438
+ if (hasMin && hasMax) {
1439
+ return `${filter.label}: ${formatBound(filter.value.min, filter)} to ${formatBound(filter.value.max, filter)}`;
1440
+ }
1441
+ if (hasMin) {
1442
+ return `${filter.label}: ${minSymbol} ${formatBound(filter.value.min, filter)}`;
1443
+ }
1444
+ return `${filter.label}: ${maxSymbol} ${formatBound(filter.value.max, filter)}`;
1445
+ };
1446
+ const isSelected$1 = (filter) => filter.value !== null && filter.value !== void 0 && (filter.value.min !== void 0 || filter.value.max !== void 0);
1447
+ const numericRangeAdapter = {
1448
+ getValue: (filter) => filter.value ?? null,
1449
+ setValue: (filter, value) => ({ ...filter, value }),
1450
+ reset: (filter) => ({ ...filter, value: null }),
1451
+ isActive: isSelected$1,
1452
+ preserveState: (newFilter, existingFilter) => ({
1453
+ ...newFilter,
1454
+ value: existingFilter.value
1455
+ }),
1456
+ cloneWithItemRefs: (filter) => ({
1457
+ ...filter,
1458
+ value: filter.value ? { ...filter.value } : null
1459
+ }),
1460
+ renderBarControl: ({ filter }) => /* @__PURE__ */ jsx(
1461
+ FilterPopoverButton,
1462
+ {
1463
+ filter,
1464
+ label: formatLabel$1(filter),
1465
+ isSelected: isSelected$1(filter),
1466
+ committedValue: filter.value ?? null,
1467
+ initialValue: null,
1468
+ children: ({ value, onChange }) => /* @__PURE__ */ jsx(
1469
+ FilterNumericRange,
1470
+ {
1471
+ filter,
1472
+ value,
1473
+ onChange,
1474
+ layout: "compact"
1475
+ }
1476
+ )
1477
+ },
1478
+ filter.id
1479
+ ),
1480
+ renderDrawer: ({ draftFilter, onDraftChange }) => /* @__PURE__ */ jsx(
1481
+ FilterNumericRange,
1482
+ {
1483
+ filter: draftFilter,
1484
+ value: draftFilter.value ?? null,
1485
+ onChange: (value) => onDraftChange(draftFilter.id, value),
1486
+ layout: "grid"
1487
+ },
1488
+ draftFilter.id
1489
+ ),
1490
+ formatLabel: formatLabel$1,
1491
+ isSelected: isSelected$1
1492
+ };
1493
+
1494
+ const formatLabel = (filter) => {
1495
+ if (filter.selectedOption) {
1496
+ return `${filter.label}: ${filter.selectedOption.label}`;
1497
+ }
1498
+ return filter.label;
1499
+ };
1500
+ const isSelected = (filter) => filter.selectedOption !== void 0;
1501
+ const passThroughMenuProps = (filter) => {
1502
+ const {
1503
+ id: _id,
1504
+ label: _label,
1505
+ type: _type,
1506
+ selectedOption: _selectedOption,
1507
+ simpleDrawerVariant: _simpleDrawerVariant,
1508
+ drawerOnly: _drawerOnly,
1509
+ ...rest
1510
+ } = filter;
1511
+ return rest;
1512
+ };
1513
+ const singleSelectAdapter = {
1514
+ getValue: (filter) => filter.selectedOption,
1515
+ setValue: (filter, value) => ({ ...filter, selectedOption: value }),
1516
+ reset: (filter) => ({ ...filter, selectedOption: void 0 }),
1517
+ isActive: isSelected,
1518
+ preserveState: (newFilter, existingFilter) => ({
1519
+ ...newFilter,
1520
+ selectedOption: existingFilter.selectedOption
1521
+ }),
1522
+ // Options are owned by the consumer; SelectMenuSync handles option identity
1523
+ // internally — no rebinding needed here.
1524
+ cloneWithItemRefs: (filter) => ({ ...filter }),
1525
+ renderBarControl: ({ filter, updateFilter }) => /* @__PURE__ */ jsx(FilterItemWrapper, { children: /* @__PURE__ */ jsx(
1526
+ SelectMenuSync,
1527
+ {
1528
+ ...passThroughMenuProps(filter),
1529
+ id: filter.id,
1530
+ label: filter.label,
1531
+ value: filter.selectedOption ?? null,
1532
+ onSelectedOptionChange: (option) => updateFilter(filter.id, option ?? void 0, true),
1533
+ clear: {
1534
+ onClick: () => updateFilter(filter.id, void 0, true)
1535
+ },
1536
+ trigger: (triggerProps) => /* @__PURE__ */ jsx(
1537
+ FilterTriggerButton,
1538
+ {
1539
+ ...triggerProps,
1540
+ filterId: filter.id,
1541
+ label: formatLabel(filter),
1542
+ isSelected: isSelected(filter)
1543
+ }
1544
+ )
1545
+ }
1546
+ ) }, filter.id),
1547
+ renderDrawer: ({ originalFilter, draftFilter, onDraftChange }) => {
1548
+ if (originalFilter.simpleDrawerVariant) {
1549
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Radio.Group, { legend: originalFilter.label, children: originalFilter.options.map((option) => /* @__PURE__ */ jsx(
1550
+ Radio,
1551
+ {
1552
+ name: `${originalFilter.id}-radio`,
1553
+ value: String(option.id),
1554
+ label: option.label,
1555
+ checked: draftFilter.selectedOption?.id === option.id,
1556
+ onChange: (e) => {
1557
+ if (e?.target.checked) {
1558
+ const selected = originalFilter.options.find(
1559
+ (opt) => String(opt.id) === e.target.value
1560
+ );
1561
+ onDraftChange(draftFilter.id, selected);
1562
+ }
1563
+ }
1564
+ },
1565
+ option.id
1566
+ )) }) }, draftFilter.id);
1567
+ }
1568
+ return /* @__PURE__ */ createElement(
1569
+ SelectFieldSync,
1570
+ {
1571
+ ...passThroughMenuProps(originalFilter),
1572
+ key: draftFilter.id,
1573
+ label: originalFilter.label,
1574
+ value: draftFilter.selectedOption ?? null,
1575
+ onSelectedOptionChange: (option) => onDraftChange(draftFilter.id, option ?? void 0)
1576
+ }
1577
+ );
1578
+ },
1579
+ formatLabel,
1580
+ isSelected
1581
+ };
1582
+
1583
+ const filterAdapters = {
1584
+ boolean: booleanAdapter,
1585
+ custom: customAdapter,
1586
+ singleSelect: singleSelectAdapter,
1587
+ multiSelect: multiSelectAdapter,
1588
+ date: dateAdapter,
1589
+ dateRange: dateRangeAdapter,
1590
+ dateList: dateListAdapter,
1591
+ asyncSelect: asyncSelectAdapter,
1592
+ asyncMultiSelect: asyncMultiSelectAdapter,
1593
+ numericRange: numericRangeAdapter
1594
+ };
1595
+ const unknownAdapter = {
1596
+ getValue: () => void 0,
1597
+ setValue: (filter) => filter,
1598
+ reset: (filter) => filter,
1599
+ isActive: () => false,
1600
+ preserveState: (newFilter) => newFilter,
1601
+ cloneWithItemRefs: (filter) => filter,
1602
+ renderBarControl: () => null,
1603
+ renderDrawer: () => null,
1604
+ formatLabel: (filter) => filter.label,
1605
+ isSelected: () => false
1606
+ };
1607
+ const getAdapter = (filter) => filterAdapters[filter.type] ?? unknownAdapter;
1608
+
1609
+ const getActiveFilters = (filters) => filters.filter((filter) => getAdapter(filter).isActive(filter));
1610
+ const checkActiveFilters = (filters) => getActiveFilters(filters).length > 0;
1611
+ const resetFilters = (filters) => filters.map((filter) => getAdapter(filter).reset(filter));
1612
+ const updateSingleFilter = (filters, filterId, value) => filters.map((filter) => {
1613
+ if (filter.id !== filterId) return filter;
1614
+ return getAdapter(filter).setValue(filter, value);
1615
+ });
1616
+ const hasFilterSelectionChanged = (existingFilter, newFilter) => {
1617
+ const existingValue = getAdapter(existingFilter).getValue(existingFilter);
1618
+ const newValue = getAdapter(newFilter).getValue(newFilter);
1619
+ return existingValue !== newValue;
1620
+ };
1621
+ const preserveFilterState = (newFilter, existingFilter) => getAdapter(newFilter).preserveState(newFilter, existingFilter);
1622
+ const cloneFiltersWithItemRefs = (filters) => filters.map(
1623
+ (filter) => getAdapter(filter).cloneWithItemRefs(filter)
1624
+ );
1625
+
1626
+ export { DateListDialog as D, FilterGroupContext as F, checkActiveFilters as a, getAdapter as b, cloneFiltersWithItemRefs as c, FilterItemWrapper as d, FilterTriggerButton as e, getActiveFilters as g, hasFilterSelectionChanged as h, preserveFilterState as p, resetFilters as r, styles as s, updateSingleFilter as u };
1627
+ //# sourceMappingURL=filter-state-Bx3aYS1r.js.map