@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,650 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
3
+ import { S as SvgAdd } from './add-BcQkAUip.js';
4
+ import { S as SvgEdit } from './edit-DQOiktcu.js';
5
+ import { B as Button } from './Button-C_V2xQAs.js';
6
+ import { T as Text } from './Text-BTzgTpqu.js';
7
+ import { F as Flex } from './Flex-_orhvoxS.js';
8
+ import { f as OptionsPopover, O as OptionsPanel } from './syncFilterUtils-BEKek64h.js';
9
+ import { u as useMenuInteraction } from './useMenuInteraction-CpAOHSJu.js';
10
+ import { c as cloneFiltersWithItemRefs, u as updateSingleFilter, b as getAdapter, D as DateListDialog, e as FilterTriggerButton } from './filter-state-Bx3aYS1r.js';
11
+ import { D as Drawer } from './Drawer-s2y0xcgV.js';
12
+ import { T as TextField } from './TextField-WTYZJlX3.js';
13
+ import { A as Alert } from './Alert-BNH0UD2s.js';
14
+ import { D as Divider } from './Divider-CxtTyw8_.js';
15
+ import { DndSort } from './DndSort.js';
16
+ import { u as useDrillDown, D as DrillDown } from './useDrilldown-KZ9rRsXQ.js';
17
+
18
+ import './SavedFiltersButton.css';const footer = "_footer_1cnkf_7";
19
+ const styles = {
20
+ "empty-state": "_empty-state_1cnkf_1",
21
+ footer: footer
22
+ };
23
+
24
+ const AddSavedFilterDrawer = ({
25
+ open,
26
+ onClose,
27
+ filtersSnapshot,
28
+ onSave,
29
+ validateName
30
+ }) => {
31
+ const [name, setName] = useState("");
32
+ const [submitting, setSubmitting] = useState(false);
33
+ const [submitError, setSubmitError] = useState(void 0);
34
+ const [justSubmitted, setJustSubmitted] = useState(false);
35
+ useEffect(() => {
36
+ if (open) {
37
+ setName("");
38
+ setSubmitting(false);
39
+ setSubmitError(void 0);
40
+ setJustSubmitted(false);
41
+ }
42
+ }, [open]);
43
+ const trimmed = name.trim();
44
+ const validationError = !justSubmitted && validateName ? validateName(trimmed) : void 0;
45
+ const canSubmit = trimmed.length > 0 && !validationError && !submitting;
46
+ const handleAdd = async () => {
47
+ if (!canSubmit) return;
48
+ setSubmitting(true);
49
+ setSubmitError(void 0);
50
+ try {
51
+ await onSave({ name: trimmed, filters: filtersSnapshot });
52
+ setJustSubmitted(true);
53
+ onClose();
54
+ } catch (err) {
55
+ setSubmitError(
56
+ err instanceof Error && err.message ? err.message : "Failed to save filter."
57
+ );
58
+ setSubmitting(false);
59
+ }
60
+ };
61
+ const handleCancel = () => {
62
+ if (submitting) return;
63
+ onClose();
64
+ };
65
+ return /* @__PURE__ */ jsxs(Drawer, { open, onClose: handleCancel, children: [
66
+ /* @__PURE__ */ jsx(Drawer.Header, { children: "Save Current Filter" }),
67
+ /* @__PURE__ */ jsx(Drawer.Content, { children: /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "4", grow: 1, children: /* @__PURE__ */ jsx(
68
+ TextField,
69
+ {
70
+ label: "Filter Name",
71
+ placeholder: "Name this filter",
72
+ value: name,
73
+ onChange: (e) => setName(e?.target.value ?? ""),
74
+ disabled: submitting,
75
+ required: true,
76
+ error: submitError ?? validationError,
77
+ onKeyDown: (e) => {
78
+ if (e.key === "Enter" && canSubmit) {
79
+ e.preventDefault();
80
+ handleAdd();
81
+ }
82
+ }
83
+ }
84
+ ) }) }),
85
+ /* @__PURE__ */ jsx(Drawer.Footer, { children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "flex-end", gap: "3", grow: 1, children: [
86
+ /* @__PURE__ */ jsx(Button, { onClick: handleCancel, disabled: submitting, children: "Cancel" }),
87
+ /* @__PURE__ */ jsx(
88
+ Button,
89
+ {
90
+ appearance: "primary",
91
+ onClick: handleAdd,
92
+ disabled: !canSubmit,
93
+ loading: submitting,
94
+ children: "Add Saved Filter"
95
+ }
96
+ )
97
+ ] }) })
98
+ ] });
99
+ };
100
+
101
+ const DEFAULT_ALERT_TEXT = {
102
+ saveSuccess: "Filter saved.",
103
+ saveError: "Failed to save filter.",
104
+ updateSuccess: "Filter updated.",
105
+ updateError: "Failed to update filter.",
106
+ deleteSuccess: "Filter deleted.",
107
+ deleteError: "Failed to delete filter.",
108
+ reorderError: "Failed to reorder filters."
109
+ };
110
+ const EDIT_INDEX = 0;
111
+ const EditSavedFiltersDrawer = ({
112
+ open,
113
+ onClose,
114
+ savedFilters,
115
+ onUpdate,
116
+ onDelete,
117
+ onReorder,
118
+ validateName,
119
+ alertText
120
+ }) => {
121
+ const { setIndex, back, drillDownProps } = useDrillDown();
122
+ const [editingId, setEditingId] = useState(null);
123
+ const [drilldownName, setDrilldownName] = useState("");
124
+ const [drilldownDraft, setDrilldownDraft] = useState([]);
125
+ const [dateListDialogState, setDateListDialogState] = useState(null);
126
+ const [submitting, setSubmitting] = useState(
127
+ null
128
+ );
129
+ const [submitError, setSubmitError] = useState(null);
130
+ const seededForRef = useRef(null);
131
+ const [listAlert, setListAlert] = useState(null);
132
+ const [drilldownAlert, setDrilldownAlert] = useState(
133
+ null
134
+ );
135
+ useEffect(() => {
136
+ if (!open) {
137
+ setEditingId(null);
138
+ seededForRef.current = null;
139
+ setSubmitError(null);
140
+ setSubmitting(null);
141
+ setListAlert(null);
142
+ setDrilldownAlert(null);
143
+ setIndex(void 0);
144
+ }
145
+ }, [open, setIndex]);
146
+ const drilldownTarget = editingId ? savedFilters.find((s) => s.id === editingId) : void 0;
147
+ useEffect(() => {
148
+ if (!editingId || !drilldownTarget) return;
149
+ if (seededForRef.current === editingId) return;
150
+ seededForRef.current = editingId;
151
+ setDrilldownName(drilldownTarget.name);
152
+ setDrilldownDraft(cloneFiltersWithItemRefs(drilldownTarget.filters));
153
+ setSubmitError(null);
154
+ }, [editingId, drilldownTarget]);
155
+ const resolvedAlertText = useMemo(
156
+ () => ({ ...DEFAULT_ALERT_TEXT, ...alertText ?? {} }),
157
+ [alertText]
158
+ );
159
+ const handleEdit = useCallback(
160
+ (id) => {
161
+ setListAlert(null);
162
+ setEditingId(id);
163
+ setIndex(EDIT_INDEX);
164
+ },
165
+ [setIndex]
166
+ );
167
+ const handleDrop = useCallback(
168
+ (event) => {
169
+ if (!onReorder || !event.valid || !event.zoneSort) return;
170
+ Promise.resolve(onReorder(event.zoneSort.map((id) => String(id)))).catch(
171
+ (err) => {
172
+ console.error(
173
+ "SavedFiltersButton onReorderSavedFilters failed:",
174
+ err
175
+ );
176
+ setListAlert({
177
+ status: "danger",
178
+ title: err instanceof Error && err.message ? err.message : resolvedAlertText.reorderError
179
+ });
180
+ }
181
+ );
182
+ },
183
+ [onReorder, resolvedAlertText]
184
+ );
185
+ const sortedIds = useMemo(
186
+ () => savedFilters.map((s) => s.id),
187
+ [savedFilters]
188
+ );
189
+ const handleBackToList = useCallback(() => {
190
+ seededForRef.current = null;
191
+ setEditingId(null);
192
+ setSubmitError(null);
193
+ setDrilldownAlert(null);
194
+ back();
195
+ }, [back]);
196
+ const handleDraftChange = useCallback((filterId, value) => {
197
+ setDrilldownDraft((prev) => updateSingleFilter(prev, filterId, value));
198
+ }, []);
199
+ const requestDateListDialog = useCallback(
200
+ (filterId, libraryId) => {
201
+ setDateListDialogState({ filterId, libraryId });
202
+ },
203
+ []
204
+ );
205
+ const drilldownForm = useMemo(() => {
206
+ if (!drilldownTarget) return null;
207
+ return drilldownDraft.map((draftFilter) => {
208
+ const originalFilter = drilldownTarget.filters.find((f) => f.id === draftFilter.id) ?? draftFilter;
209
+ return getAdapter(draftFilter).renderDrawer({
210
+ originalFilter,
211
+ draftFilter,
212
+ onDraftChange: handleDraftChange,
213
+ requestDateListDialog
214
+ });
215
+ });
216
+ }, [
217
+ drilldownDraft,
218
+ drilldownTarget,
219
+ handleDraftChange,
220
+ requestDateListDialog
221
+ ]);
222
+ const trimmedName = drilldownName.trim();
223
+ const validationError = validateName && editingId ? validateName(trimmedName, editingId) : void 0;
224
+ const canSubmit = editingId !== null && trimmedName.length > 0 && !validationError && submitting === null;
225
+ const handleUpdate = useCallback(async () => {
226
+ if (!editingId || !onUpdate || !canSubmit) return;
227
+ setSubmitting("update");
228
+ setSubmitError(null);
229
+ setDrilldownAlert(null);
230
+ try {
231
+ await onUpdate(editingId, {
232
+ name: trimmedName,
233
+ filters: drilldownDraft
234
+ });
235
+ seededForRef.current = null;
236
+ setEditingId(null);
237
+ back();
238
+ setSubmitting(null);
239
+ setListAlert({
240
+ status: "success",
241
+ title: resolvedAlertText.updateSuccess
242
+ });
243
+ } catch (err) {
244
+ setDrilldownAlert({
245
+ status: "danger",
246
+ title: err instanceof Error && err.message ? err.message : resolvedAlertText.updateError
247
+ });
248
+ setSubmitting(null);
249
+ }
250
+ }, [
251
+ editingId,
252
+ onUpdate,
253
+ canSubmit,
254
+ trimmedName,
255
+ drilldownDraft,
256
+ resolvedAlertText,
257
+ back
258
+ ]);
259
+ const handleDelete = useCallback(async () => {
260
+ if (!editingId || !onDelete || submitting !== null) return;
261
+ if (drilldownTarget?.disableDelete) return;
262
+ setSubmitting("delete");
263
+ setSubmitError(null);
264
+ setDrilldownAlert(null);
265
+ try {
266
+ await onDelete(editingId);
267
+ seededForRef.current = null;
268
+ setEditingId(null);
269
+ back();
270
+ setSubmitting(null);
271
+ setListAlert({
272
+ status: "success",
273
+ title: resolvedAlertText.deleteSuccess
274
+ });
275
+ } catch (err) {
276
+ seededForRef.current = null;
277
+ setEditingId(null);
278
+ back();
279
+ setSubmitting(null);
280
+ setListAlert({
281
+ status: "danger",
282
+ title: err instanceof Error && err.message ? err.message : resolvedAlertText.deleteError
283
+ });
284
+ }
285
+ }, [
286
+ editingId,
287
+ onDelete,
288
+ submitting,
289
+ drilldownTarget,
290
+ resolvedAlertText,
291
+ back
292
+ ]);
293
+ const dateListDialogTarget = dateListDialogState ? drilldownDraft.find(
294
+ (f) => f.id === dateListDialogState.filterId && f.type === "dateList"
295
+ ) : void 0;
296
+ const dateListDialogSelected = dateListDialogTarget?.selectedOption;
297
+ const dateListDialogInitialValue = dateListDialogSelected && dateListDialogSelected.id === dateListDialogState?.libraryId && dateListDialogSelected.value !== null ? dateListDialogSelected.value : void 0;
298
+ const drilldownTitle = drilldownTarget?.name ?? "Edit Saved Filter";
299
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
300
+ /* @__PURE__ */ jsxs(Drawer, { open, onClose, ...drillDownProps, children: [
301
+ /* @__PURE__ */ jsx(Drawer.Header, { children: "Edit Saved Filters" }),
302
+ /* @__PURE__ */ jsx(Drawer.Content, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "4", grow: 1, children: [
303
+ listAlert && /* @__PURE__ */ jsx(Alert, { title: listAlert.title, status: listAlert.status }),
304
+ savedFilters.length === 0 ? /* @__PURE__ */ jsx(Text, { subdued: true, size: "small", children: "No saved filters to edit." }) : onReorder ? /* @__PURE__ */ jsx(DndSort, { onDrop: handleDrop, children: /* @__PURE__ */ jsx(
305
+ DndSort.Zone,
306
+ {
307
+ sortable: true,
308
+ id: "saved-filters-zone",
309
+ label: "Saved filters",
310
+ orientation: "vertical",
311
+ sortedIds,
312
+ gap: "2",
313
+ children: savedFilters.map((saved) => /* @__PURE__ */ jsx(
314
+ DndSort.Card,
315
+ {
316
+ id: saved.id,
317
+ label: saved.name,
318
+ dragOnlyWithHandle: true,
319
+ children: /* @__PURE__ */ jsxs(
320
+ Flex,
321
+ {
322
+ alignItems: "center",
323
+ justifyContent: "space-between",
324
+ gap: "2",
325
+ grow: 1,
326
+ children: [
327
+ /* @__PURE__ */ jsx(Text, { children: saved.name }),
328
+ !saved.disableEdit && /* @__PURE__ */ jsx(
329
+ Button,
330
+ {
331
+ appearance: "secondary",
332
+ size: "small",
333
+ icon: SvgEdit,
334
+ "aria-label": `Edit ${saved.name}`,
335
+ onClick: () => handleEdit(saved.id)
336
+ }
337
+ )
338
+ ]
339
+ }
340
+ )
341
+ },
342
+ saved.id
343
+ ))
344
+ }
345
+ ) }) : /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "2", children: savedFilters.map((saved) => /* @__PURE__ */ jsxs(
346
+ Flex,
347
+ {
348
+ alignItems: "center",
349
+ justifyContent: "space-between",
350
+ gap: "2",
351
+ children: [
352
+ /* @__PURE__ */ jsx(Text, { children: saved.name }),
353
+ !saved.disableEdit && /* @__PURE__ */ jsx(
354
+ Button,
355
+ {
356
+ appearance: "secondary",
357
+ size: "small",
358
+ icon: SvgEdit,
359
+ "aria-label": `Edit ${saved.name}`,
360
+ onClick: () => handleEdit(saved.id)
361
+ }
362
+ )
363
+ ]
364
+ },
365
+ saved.id
366
+ )) })
367
+ ] }) }),
368
+ /* @__PURE__ */ jsx(Drawer.Footer, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", grow: 1, children: /* @__PURE__ */ jsx(Button, { onClick: onClose, children: "Close" }) }) }),
369
+ /* @__PURE__ */ jsxs(DrillDown, { index: EDIT_INDEX, children: [
370
+ /* @__PURE__ */ jsx(DrillDown.Header, { children: drilldownTitle }),
371
+ /* @__PURE__ */ jsx(DrillDown.Content, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "4", grow: 1, children: [
372
+ drilldownAlert && /* @__PURE__ */ jsx(
373
+ Alert,
374
+ {
375
+ title: drilldownAlert.title,
376
+ status: drilldownAlert.status
377
+ }
378
+ ),
379
+ /* @__PURE__ */ jsx(
380
+ TextField,
381
+ {
382
+ label: "Filter Name",
383
+ placeholder: "Name this filter",
384
+ value: drilldownName,
385
+ onChange: (e) => setDrilldownName(e?.target.value ?? ""),
386
+ disabled: submitting !== null,
387
+ required: true,
388
+ error: submitError ?? validationError
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx(Divider, {}),
392
+ drilldownForm
393
+ ] }) }),
394
+ /* @__PURE__ */ jsx(DrillDown.Footer, { children: /* @__PURE__ */ jsxs(
395
+ Flex,
396
+ {
397
+ justifyContent: drilldownTarget?.disableDelete ? "flex-end" : "space-between",
398
+ gap: "3",
399
+ grow: 1,
400
+ children: [
401
+ !drilldownTarget?.disableDelete && /* @__PURE__ */ jsx(
402
+ Button,
403
+ {
404
+ appearance: "danger-secondary",
405
+ onClick: handleDelete,
406
+ loading: submitting === "delete",
407
+ disabled: submitting !== null,
408
+ children: "Delete Filter"
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsxs(Flex, { gap: "3", children: [
412
+ /* @__PURE__ */ jsx(
413
+ Button,
414
+ {
415
+ onClick: handleBackToList,
416
+ disabled: submitting !== null,
417
+ children: "Cancel"
418
+ }
419
+ ),
420
+ /* @__PURE__ */ jsx(
421
+ Button,
422
+ {
423
+ appearance: "primary",
424
+ onClick: handleUpdate,
425
+ disabled: !canSubmit,
426
+ loading: submitting === "update",
427
+ children: "Update Filter"
428
+ }
429
+ )
430
+ ] })
431
+ ]
432
+ }
433
+ ) })
434
+ ] })
435
+ ] }),
436
+ /* @__PURE__ */ jsx(
437
+ DateListDialog,
438
+ {
439
+ libraryId: dateListDialogState?.libraryId ?? null,
440
+ parentFilterId: dateListDialogState?.filterId ?? "",
441
+ initialValue: dateListDialogInitialValue,
442
+ mode: dateListDialogTarget?.mode,
443
+ dialogCtaLabel: "Save",
444
+ onCommit: (option) => {
445
+ if (dateListDialogState) {
446
+ handleDraftChange(dateListDialogState.filterId, option);
447
+ }
448
+ setDateListDialogState(null);
449
+ },
450
+ onCancel: () => setDateListDialogState(null)
451
+ }
452
+ )
453
+ ] });
454
+ };
455
+
456
+ const SavedFiltersButton = (props) => {
457
+ const {
458
+ savedFilters,
459
+ currentFilters,
460
+ onApplySavedFilter,
461
+ onSaveCurrentFilter,
462
+ onUpdateSavedFilter,
463
+ onDeleteSavedFilter,
464
+ onReorderSavedFilters,
465
+ validateName,
466
+ alertText,
467
+ activeSavedFilterId,
468
+ label: labelProp,
469
+ emptyState
470
+ } = props;
471
+ const DEFAULT_LABEL = "Saved Filters";
472
+ const label = labelProp ? labelProp : activeSavedFilterId ? savedFilters.find((sf) => sf.id === activeSavedFilterId)?.name || DEFAULT_LABEL : DEFAULT_LABEL;
473
+ const triggerRef = useRef(null);
474
+ const items = useMemo(
475
+ () => savedFilters.map((saved) => ({
476
+ id: saved.id,
477
+ type: "option",
478
+ original: { id: saved.id, label: saved.name }
479
+ })),
480
+ [savedFilters]
481
+ );
482
+ const selectedItemIds = useMemo(
483
+ () => activeSavedFilterId ? /* @__PURE__ */ new Set([activeSavedFilterId]) : /* @__PURE__ */ new Set(),
484
+ [activeSavedFilterId]
485
+ );
486
+ const getCheckedState = useCallback(
487
+ (item) => item.id === activeSavedFilterId ? "checked" : "unchecked",
488
+ [activeSavedFilterId]
489
+ );
490
+ const handleItemActivate = useCallback(
491
+ (item) => {
492
+ const saved = savedFilters.find((s) => s.id === item.id);
493
+ if (saved) onApplySavedFilter(saved);
494
+ },
495
+ [savedFilters, onApplySavedFilter]
496
+ );
497
+ const [isOpen, setIsOpen] = useState(false);
498
+ const {
499
+ closeMenu,
500
+ highlightedIndex,
501
+ getTriggerProps,
502
+ getMenuProps,
503
+ getItemProps
504
+ } = useMenuInteraction({
505
+ items,
506
+ sectionsMeta: [],
507
+ onItemActivate: handleItemActivate,
508
+ selectedItemIds,
509
+ displayAs: "popover",
510
+ closeOnActivate: true,
511
+ id: "saved-filters",
512
+ triggerRef,
513
+ label,
514
+ isOpen,
515
+ setIsOpen
516
+ });
517
+ const handleClickOutside = useCallback(() => {
518
+ closeMenu({ restoreFocus: false });
519
+ }, [closeMenu]);
520
+ const triggerProps = getTriggerProps();
521
+ const [addOpen, setAddOpen] = useState(false);
522
+ const [editOpen, setEditOpen] = useState(false);
523
+ const [filtersSnapshot, setFiltersSnapshot] = useState(
524
+ []
525
+ );
526
+ const handleSaveCurrentClick = useCallback(() => {
527
+ setFiltersSnapshot(currentFilters);
528
+ closeMenu({ restoreFocus: false });
529
+ setAddOpen(true);
530
+ }, [closeMenu, currentFilters]);
531
+ const handleEditClick = useCallback(() => {
532
+ closeMenu({ restoreFocus: false });
533
+ setEditOpen(true);
534
+ }, [closeMenu]);
535
+ const handleFooterKeyDown = (e) => {
536
+ if (e.key === "Escape") {
537
+ e.preventDefault();
538
+ closeMenu();
539
+ }
540
+ };
541
+ const footer = /* @__PURE__ */ jsxs(
542
+ Flex,
543
+ {
544
+ direction: "column",
545
+ gap: "2",
546
+ className: styles["footer"],
547
+ onKeyDown: handleFooterKeyDown,
548
+ children: [
549
+ /* @__PURE__ */ jsx(
550
+ Button,
551
+ {
552
+ appearance: "secondary",
553
+ size: "small",
554
+ icon: { before: SvgAdd },
555
+ style: { width: "100%" },
556
+ onClick: handleSaveCurrentClick,
557
+ children: "Save Current Filter"
558
+ }
559
+ ),
560
+ /* @__PURE__ */ jsx(
561
+ Button,
562
+ {
563
+ appearance: "secondary",
564
+ size: "small",
565
+ icon: { before: SvgEdit },
566
+ style: { width: "100%" },
567
+ onClick: handleEditClick,
568
+ disabled: savedFilters.length === 0,
569
+ children: "Edit Saved Filters"
570
+ }
571
+ )
572
+ ]
573
+ }
574
+ );
575
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
576
+ /* @__PURE__ */ jsx(
577
+ FilterTriggerButton,
578
+ {
579
+ ...triggerProps,
580
+ filterId: "saved-filters",
581
+ label,
582
+ isSelected: !!(activeSavedFilterId ?? false)
583
+ }
584
+ ),
585
+ /* @__PURE__ */ jsx(
586
+ OptionsPopover,
587
+ {
588
+ id: "saved-filters-popover",
589
+ referenceElement: triggerRef,
590
+ open: isOpen,
591
+ onClose: handleClickOutside,
592
+ width: 280,
593
+ footer,
594
+ children: items.length === 0 ? /* @__PURE__ */ jsx(
595
+ Flex,
596
+ {
597
+ direction: "column",
598
+ alignItems: "center",
599
+ justifyContent: "center",
600
+ className: styles["empty-state"],
601
+ children: typeof emptyState === "string" || emptyState == null ? /* @__PURE__ */ jsx(Text, { subdued: true, size: "small", children: emptyState ?? "No saved filters yet." }) : emptyState
602
+ }
603
+ ) : /* @__PURE__ */ jsx(
604
+ OptionsPanel,
605
+ {
606
+ isOpen,
607
+ items,
608
+ getMenuProps,
609
+ getItemProps,
610
+ highlightedIndex,
611
+ getCheckedState,
612
+ selectionType: "single",
613
+ hasMore: false,
614
+ onLoadMore: () => {
615
+ },
616
+ loading: false,
617
+ loadingMore: false
618
+ }
619
+ )
620
+ }
621
+ ),
622
+ /* @__PURE__ */ jsx(
623
+ AddSavedFilterDrawer,
624
+ {
625
+ open: addOpen,
626
+ onClose: () => setAddOpen(false),
627
+ filtersSnapshot,
628
+ onSave: onSaveCurrentFilter,
629
+ validateName: validateName ? (name) => validateName(name) : void 0
630
+ }
631
+ ),
632
+ /* @__PURE__ */ jsx(
633
+ EditSavedFiltersDrawer,
634
+ {
635
+ open: editOpen,
636
+ onClose: () => setEditOpen(false),
637
+ savedFilters,
638
+ onUpdate: onUpdateSavedFilter,
639
+ onDelete: onDeleteSavedFilter,
640
+ onReorder: onReorderSavedFilters,
641
+ validateName,
642
+ alertText
643
+ }
644
+ )
645
+ ] });
646
+ };
647
+ SavedFiltersButton.displayName = "SavedFiltersButton";
648
+
649
+ export { SavedFiltersButton as S };
650
+ //# sourceMappingURL=SavedFiltersButton-2qba2Cgu.js.map