@giddaa-housing/ui 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/css/generated/shared.css +1 -1
  2. package/css/giddaa.css +12 -2
  3. package/dist/accordion.d.ts +9 -10
  4. package/dist/accordion.js +41 -87
  5. package/dist/activity-timeline.d.ts +12 -16
  6. package/dist/activity-timeline.js +83 -198
  7. package/dist/alert.d.ts +8 -9
  8. package/dist/alert.js +53 -111
  9. package/dist/auth-layout.d.ts +4 -4
  10. package/dist/auth-layout.js +143 -294
  11. package/dist/avatar.d.ts +6 -6
  12. package/dist/avatar.js +49 -19
  13. package/dist/badge.d.ts +12 -14
  14. package/dist/badge.js +71 -11
  15. package/dist/bar-chart.d.ts +65 -67
  16. package/dist/bar-chart.js +232 -207
  17. package/dist/breadcrumb.d.ts +5 -5
  18. package/dist/breadcrumb.js +56 -118
  19. package/dist/bullet-chart.d.ts +41 -37
  20. package/dist/bullet-chart.js +125 -148
  21. package/dist/button-BZIeyUw6.d.ts +17 -0
  22. package/dist/button-group.d.ts +13 -16
  23. package/dist/button-group.js +39 -88
  24. package/dist/button.d.ts +2 -19
  25. package/dist/button.js +94 -13
  26. package/dist/calendar.d.ts +6 -6
  27. package/dist/calendar.js +138 -17
  28. package/dist/card.d.ts +14 -16
  29. package/dist/card.js +59 -145
  30. package/dist/carousel.d.ts +34 -35
  31. package/dist/carousel.js +335 -20
  32. package/dist/chart.d.ts +90 -63
  33. package/dist/chart.js +573 -28
  34. package/dist/checkbox.d.ts +10 -12
  35. package/dist/checkbox.js +82 -47
  36. package/dist/cn-BI_4DMBf.js +23 -0
  37. package/dist/collapsible.d.ts +7 -8
  38. package/dist/collapsible.js +22 -47
  39. package/dist/combobox.d.ts +10 -10
  40. package/dist/combobox.js +236 -44
  41. package/dist/cta.d.ts +12 -14
  42. package/dist/cta.js +175 -341
  43. package/dist/currency-selector.d.ts +31 -32
  44. package/dist/currency-selector.js +106 -184
  45. package/dist/data-table.d.ts +168 -0
  46. package/dist/data-table.js +676 -0
  47. package/dist/date-picker.d.ts +22 -23
  48. package/dist/date-picker.js +119 -192
  49. package/dist/details-card.d.ts +7 -7
  50. package/dist/details-card.js +104 -253
  51. package/dist/dialog.d.ts +13 -14
  52. package/dist/dialog.js +116 -209
  53. package/dist/dropdown-menu.d.ts +13 -13
  54. package/dist/dropdown-menu.js +180 -37
  55. package/dist/dropzone.d.ts +55 -55
  56. package/dist/dropzone.js +327 -439
  57. package/dist/editorial-card.d.ts +23 -25
  58. package/dist/editorial-card.js +129 -296
  59. package/dist/empty-state.d.ts +8 -9
  60. package/dist/empty-state.js +48 -105
  61. package/dist/field.d.ts +23 -25
  62. package/dist/field.js +110 -221
  63. package/dist/filter.d.ts +118 -0
  64. package/dist/filter.js +775 -0
  65. package/dist/footer.d.ts +8 -15
  66. package/dist/footer.js +197 -400
  67. package/dist/funnel-chart.d.ts +49 -48
  68. package/dist/funnel-chart.js +170 -189
  69. package/dist/gallery-indicator.d.ts +11 -12
  70. package/dist/gallery-indicator.js +75 -12
  71. package/dist/heatmap-chart.d.ts +47 -50
  72. package/dist/heatmap-chart.js +186 -237
  73. package/dist/infotip.d.ts +8 -9
  74. package/dist/infotip.js +33 -59
  75. package/dist/input-CfoEJ8A6.d.ts +12 -0
  76. package/dist/input-group.d.ts +16 -20
  77. package/dist/input-group.js +99 -23
  78. package/dist/input-size-context-C-SFx9sx.d.ts +10 -0
  79. package/dist/input-size-context.d.ts +2 -11
  80. package/dist/input-size-context.js +17 -9
  81. package/dist/input.d.ts +2 -13
  82. package/dist/input.js +27 -11
  83. package/dist/item.d.ts +7 -8
  84. package/dist/item.js +22 -59
  85. package/dist/kpi-card.d.ts +18 -20
  86. package/dist/kpi-card.js +84 -192
  87. package/dist/label.d.ts +6 -6
  88. package/dist/label.js +40 -8
  89. package/dist/line-chart.d.ts +200 -129
  90. package/dist/line-chart.js +330 -105
  91. package/dist/list-item.d.ts +22 -0
  92. package/dist/list-item.js +84 -0
  93. package/dist/logo.d.ts +4 -4
  94. package/dist/logo.js +92 -9
  95. package/dist/map-indicator.d.ts +7 -7
  96. package/dist/map-indicator.js +80 -106
  97. package/dist/match.d.ts +10 -11
  98. package/dist/match.js +62 -107
  99. package/dist/media-gallery-hero.d.ts +40 -42
  100. package/dist/media-gallery-hero.js +182 -343
  101. package/dist/media-player.d.ts +17 -17
  102. package/dist/media-player.js +873 -1348
  103. package/dist/multi-step-form.d.ts +56 -0
  104. package/dist/multi-step-form.js +342 -0
  105. package/dist/number-input.d.ts +34 -34
  106. package/dist/number-input.js +64 -117
  107. package/dist/page-header.d.ts +10 -11
  108. package/dist/page-header.js +34 -79
  109. package/dist/pagination.d.ts +17 -21
  110. package/dist/pagination.js +132 -207
  111. package/dist/password-input.d.ts +5 -13
  112. package/dist/password-input.js +31 -55
  113. package/dist/phone-input.d.ts +19 -20
  114. package/dist/phone-input.js +226 -344
  115. package/dist/photo-gallery.d.ts +19 -19
  116. package/dist/photo-gallery.js +313 -449
  117. package/dist/picker-lzgmsNfG.js +32 -0
  118. package/dist/pie-chart.d.ts +121 -90
  119. package/dist/pie-chart.js +183 -149
  120. package/dist/popover.d.ts +9 -9
  121. package/dist/popover.js +72 -23
  122. package/dist/price-tag.d.ts +26 -27
  123. package/dist/price-tag.js +113 -173
  124. package/dist/progress.d.ts +16 -17
  125. package/dist/progress.js +169 -24
  126. package/dist/property-listing-card.d.ts +14 -17
  127. package/dist/property-listing-card.js +102 -220
  128. package/dist/purchase-option-card.d.ts +79 -0
  129. package/dist/purchase-option-card.js +176 -0
  130. package/dist/radar-chart.d.ts +29 -31
  131. package/dist/radar-chart.js +162 -137
  132. package/dist/radio-group.d.ts +11 -13
  133. package/dist/radio-group.js +46 -60
  134. package/dist/review-block.d.ts +14 -16
  135. package/dist/review-block.js +154 -10
  136. package/dist/rich-text-editor.d.ts +30 -14
  137. package/dist/rich-text-editor.js +592 -716
  138. package/dist/scatter-chart.d.ts +45 -47
  139. package/dist/scatter-chart.js +236 -240
  140. package/dist/search-input.d.ts +8 -16
  141. package/dist/search-input.js +57 -109
  142. package/dist/select.d.ts +8 -8
  143. package/dist/select.js +144 -27
  144. package/dist/separator.d.ts +8 -9
  145. package/dist/separator.js +32 -8
  146. package/dist/sheet.d.ts +11 -11
  147. package/dist/sheet.js +103 -24
  148. package/dist/sidebar.d.ts +32 -37
  149. package/dist/sidebar.js +364 -634
  150. package/dist/size-context-D4mYvcg8.d.ts +10 -0
  151. package/dist/size-context.d.ts +2 -11
  152. package/dist/size-context.js +17 -9
  153. package/dist/skeleton.d.ts +4 -5
  154. package/dist/skeleton.js +12 -8
  155. package/dist/slider.d.ts +8 -9
  156. package/dist/slider.js +64 -135
  157. package/dist/sparkline.d.ts +68 -58
  158. package/dist/sparkline.js +315 -251
  159. package/dist/stepper.d.ts +23 -24
  160. package/dist/stepper.js +149 -246
  161. package/dist/styles.css +1004 -116
  162. package/dist/switch.d.ts +10 -12
  163. package/dist/switch.js +48 -70
  164. package/dist/table-card.d.ts +35 -0
  165. package/dist/table-card.js +125 -0
  166. package/dist/table.d.ts +18 -14
  167. package/dist/table.js +117 -154
  168. package/dist/tabs.d.ts +33 -15
  169. package/dist/tabs.js +110 -18
  170. package/dist/tag.d.ts +21 -23
  171. package/dist/tag.js +103 -159
  172. package/dist/testimonial-block.d.ts +18 -19
  173. package/dist/testimonial-block.js +189 -358
  174. package/dist/textarea-IS_D8pXf.d.ts +11 -0
  175. package/dist/textarea.d.ts +2 -12
  176. package/dist/textarea.js +24 -11
  177. package/dist/time-picker.d.ts +11 -11
  178. package/dist/time-picker.js +245 -302
  179. package/dist/toast.d.ts +16 -18
  180. package/dist/toast.js +154 -205
  181. package/dist/tooltip.d.ts +8 -9
  182. package/dist/tooltip.js +37 -12
  183. package/dist/tree-map.d.ts +59 -62
  184. package/dist/tree-map.js +226 -269
  185. package/dist/use-uncontrolled-CLfM1XbB.js +21 -0
  186. package/dist/waterfall-chart.d.ts +94 -97
  187. package/dist/waterfall-chart.js +455 -552
  188. package/package.json +36 -9
  189. package/dist/accordion.js.map +0 -1
  190. package/dist/activity-timeline.js.map +0 -1
  191. package/dist/alert.js.map +0 -1
  192. package/dist/auth-layout.js.map +0 -1
  193. package/dist/avatar.js.map +0 -1
  194. package/dist/badge.js.map +0 -1
  195. package/dist/bar-chart.js.map +0 -1
  196. package/dist/breadcrumb.js.map +0 -1
  197. package/dist/bullet-chart.js.map +0 -1
  198. package/dist/button-group.js.map +0 -1
  199. package/dist/button.js.map +0 -1
  200. package/dist/calendar.js.map +0 -1
  201. package/dist/card.js.map +0 -1
  202. package/dist/carousel.js.map +0 -1
  203. package/dist/chart.js.map +0 -1
  204. package/dist/checkbox.js.map +0 -1
  205. package/dist/chunk-322YCNVL.js +0 -278
  206. package/dist/chunk-322YCNVL.js.map +0 -1
  207. package/dist/chunk-3ACQVT7A.js +0 -25
  208. package/dist/chunk-3ACQVT7A.js.map +0 -1
  209. package/dist/chunk-3T65TLJX.js +0 -334
  210. package/dist/chunk-3T65TLJX.js.map +0 -1
  211. package/dist/chunk-6ZSGQHH2.js +0 -192
  212. package/dist/chunk-6ZSGQHH2.js.map +0 -1
  213. package/dist/chunk-7TBMLFGW.js +0 -41
  214. package/dist/chunk-7TBMLFGW.js.map +0 -1
  215. package/dist/chunk-B4H6RNDH.js +0 -135
  216. package/dist/chunk-B4H6RNDH.js.map +0 -1
  217. package/dist/chunk-BUXCGZ6X.js +0 -219
  218. package/dist/chunk-BUXCGZ6X.js.map +0 -1
  219. package/dist/chunk-CHII2QHH.js +0 -58
  220. package/dist/chunk-CHII2QHH.js.map +0 -1
  221. package/dist/chunk-DMNOXRRW.js +0 -147
  222. package/dist/chunk-DMNOXRRW.js.map +0 -1
  223. package/dist/chunk-EFSOSSIC.js +0 -130
  224. package/dist/chunk-EFSOSSIC.js.map +0 -1
  225. package/dist/chunk-FZDSVMKY.js +0 -363
  226. package/dist/chunk-FZDSVMKY.js.map +0 -1
  227. package/dist/chunk-GJOFIJS3.js +0 -246
  228. package/dist/chunk-GJOFIJS3.js.map +0 -1
  229. package/dist/chunk-HL3ZSYES.js +0 -23
  230. package/dist/chunk-HL3ZSYES.js.map +0 -1
  231. package/dist/chunk-JVLUBAPB.js +0 -129
  232. package/dist/chunk-JVLUBAPB.js.map +0 -1
  233. package/dist/chunk-KDPYSOYZ.js +0 -64
  234. package/dist/chunk-KDPYSOYZ.js.map +0 -1
  235. package/dist/chunk-KSMDANKI.js +0 -43
  236. package/dist/chunk-KSMDANKI.js.map +0 -1
  237. package/dist/chunk-MEKCCOP5.js +0 -46
  238. package/dist/chunk-MEKCCOP5.js.map +0 -1
  239. package/dist/chunk-NOFXVRWL.js +0 -451
  240. package/dist/chunk-NOFXVRWL.js.map +0 -1
  241. package/dist/chunk-PC5MHNVA.js +0 -171
  242. package/dist/chunk-PC5MHNVA.js.map +0 -1
  243. package/dist/chunk-QKAQZ2GU.js +0 -122
  244. package/dist/chunk-QKAQZ2GU.js.map +0 -1
  245. package/dist/chunk-QZHSHSVV.js +0 -26
  246. package/dist/chunk-QZHSHSVV.js.map +0 -1
  247. package/dist/chunk-RBMK26XD.js +0 -19
  248. package/dist/chunk-RBMK26XD.js.map +0 -1
  249. package/dist/chunk-SFNJGF6M.js +0 -262
  250. package/dist/chunk-SFNJGF6M.js.map +0 -1
  251. package/dist/chunk-UJJNLGTM.js +0 -112
  252. package/dist/chunk-UJJNLGTM.js.map +0 -1
  253. package/dist/chunk-VGR4ZWJ3.js +0 -418
  254. package/dist/chunk-VGR4ZWJ3.js.map +0 -1
  255. package/dist/chunk-XG47P6D4.js +0 -99
  256. package/dist/chunk-XG47P6D4.js.map +0 -1
  257. package/dist/chunk-XZZAHNVM.js +0 -21
  258. package/dist/chunk-XZZAHNVM.js.map +0 -1
  259. package/dist/chunk-Y4TTYVNE.js +0 -36
  260. package/dist/chunk-Y4TTYVNE.js.map +0 -1
  261. package/dist/chunk-YDWIHW6Q.js +0 -69
  262. package/dist/chunk-YDWIHW6Q.js.map +0 -1
  263. package/dist/collapsible.js.map +0 -1
  264. package/dist/combobox.js.map +0 -1
  265. package/dist/cta.js.map +0 -1
  266. package/dist/currency-selector.js.map +0 -1
  267. package/dist/date-picker.js.map +0 -1
  268. package/dist/details-card.js.map +0 -1
  269. package/dist/dialog.js.map +0 -1
  270. package/dist/dropdown-menu.js.map +0 -1
  271. package/dist/dropzone.js.map +0 -1
  272. package/dist/editorial-card.js.map +0 -1
  273. package/dist/empty-state.js.map +0 -1
  274. package/dist/field.js.map +0 -1
  275. package/dist/footer.js.map +0 -1
  276. package/dist/funnel-chart.js.map +0 -1
  277. package/dist/gallery-indicator.js.map +0 -1
  278. package/dist/heatmap-chart.js.map +0 -1
  279. package/dist/infotip.js.map +0 -1
  280. package/dist/input-group.js.map +0 -1
  281. package/dist/input-size-context.js.map +0 -1
  282. package/dist/input.js.map +0 -1
  283. package/dist/item.js.map +0 -1
  284. package/dist/kpi-card.js.map +0 -1
  285. package/dist/label.js.map +0 -1
  286. package/dist/line-chart.js.map +0 -1
  287. package/dist/logo.js.map +0 -1
  288. package/dist/map-indicator.js.map +0 -1
  289. package/dist/match.js.map +0 -1
  290. package/dist/media-gallery-hero.js.map +0 -1
  291. package/dist/media-player.js.map +0 -1
  292. package/dist/number-input.js.map +0 -1
  293. package/dist/page-header.js.map +0 -1
  294. package/dist/pagination.js.map +0 -1
  295. package/dist/password-input.js.map +0 -1
  296. package/dist/phone-input.js.map +0 -1
  297. package/dist/photo-gallery.js.map +0 -1
  298. package/dist/pie-chart.js.map +0 -1
  299. package/dist/popover.js.map +0 -1
  300. package/dist/price-tag.js.map +0 -1
  301. package/dist/progress.js.map +0 -1
  302. package/dist/property-listing-card.js.map +0 -1
  303. package/dist/radar-chart.js.map +0 -1
  304. package/dist/radio-group.js.map +0 -1
  305. package/dist/review-block.js.map +0 -1
  306. package/dist/rich-text-editor.js.map +0 -1
  307. package/dist/scatter-chart.js.map +0 -1
  308. package/dist/search-input.js.map +0 -1
  309. package/dist/select.js.map +0 -1
  310. package/dist/separator.js.map +0 -1
  311. package/dist/sheet.js.map +0 -1
  312. package/dist/sidebar.js.map +0 -1
  313. package/dist/size-context.js.map +0 -1
  314. package/dist/skeleton.js.map +0 -1
  315. package/dist/slider.js.map +0 -1
  316. package/dist/sparkline.js.map +0 -1
  317. package/dist/stepper.js.map +0 -1
  318. package/dist/switch.js.map +0 -1
  319. package/dist/tab-list.d.ts +0 -38
  320. package/dist/tab-list.js +0 -123
  321. package/dist/tab-list.js.map +0 -1
  322. package/dist/table.js.map +0 -1
  323. package/dist/tabs.js.map +0 -1
  324. package/dist/tag.js.map +0 -1
  325. package/dist/testimonial-block.js.map +0 -1
  326. package/dist/textarea.js.map +0 -1
  327. package/dist/time-picker.js.map +0 -1
  328. package/dist/toast.js.map +0 -1
  329. package/dist/tooltip.js.map +0 -1
  330. package/dist/tree-map.js.map +0 -1
  331. package/dist/waterfall-chart.js.map +0 -1
package/dist/filter.js ADDED
@@ -0,0 +1,775 @@
1
+ "use client";
2
+ import { t as cn } from "./cn-BI_4DMBf.js";
3
+ import { Button } from "./button.js";
4
+ import { Input } from "./input.js";
5
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
6
+ import { Field, FieldError } from "./field.js";
7
+ import { Plus, X } from "lucide-react";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ import * as React from "react";
10
+ //#region src/filter.tsx
11
+ const emptyFilterState = {
12
+ appliedCount: 0,
13
+ errors: {},
14
+ ids: [],
15
+ rows: {}
16
+ };
17
+ const conditionsByType = {
18
+ boolean: [{
19
+ id: "equals",
20
+ name: "Equals"
21
+ }],
22
+ date: [
23
+ {
24
+ id: "equals",
25
+ name: "Equals"
26
+ },
27
+ {
28
+ id: "lessThan",
29
+ name: "Less Than"
30
+ },
31
+ {
32
+ id: "greaterThan",
33
+ name: "Greater Than"
34
+ }
35
+ ],
36
+ multiSelect: [{
37
+ id: "equals",
38
+ name: "Equals"
39
+ }],
40
+ number: [
41
+ {
42
+ id: "equals",
43
+ name: "Equals"
44
+ },
45
+ {
46
+ id: "lessThan",
47
+ name: "Less Than"
48
+ },
49
+ {
50
+ id: "greaterThan",
51
+ name: "Greater Than"
52
+ }
53
+ ],
54
+ select: [{
55
+ id: "equals",
56
+ name: "Equals"
57
+ }],
58
+ text: [{
59
+ id: "contains",
60
+ name: "Contains"
61
+ }, {
62
+ id: "equals",
63
+ name: "Equals"
64
+ }]
65
+ };
66
+ const RANGE_CONDITION = "range";
67
+ function getValueError(value) {
68
+ if (typeof value === "undefined") return "Value is required";
69
+ if (Array.isArray(value) && value.length === 0) return "Value is required";
70
+ if (typeof value === "string" && value.trim() === "") return "Value is required";
71
+ if (typeof value === "object" && !Array.isArray(value) && value !== null) {
72
+ const rangeValue = getRangeValue(value);
73
+ if (!rangeValue) return "Value is required";
74
+ if (typeof rangeValue.min === "number" && typeof rangeValue.max === "number" && rangeValue.min > rangeValue.max) return "Min cannot be greater than max";
75
+ }
76
+ }
77
+ function getRowItemError(item, row) {
78
+ if (item === "field") return row.field ? void 0 : "Field is required";
79
+ if (item === "condition") return row.condition ? void 0 : "Condition is required";
80
+ return getValueError(row.value);
81
+ }
82
+ function getRowErrors(row) {
83
+ const errors = {};
84
+ for (const item of [
85
+ "field",
86
+ "condition",
87
+ "value"
88
+ ]) {
89
+ const error = getRowItemError(item, row);
90
+ if (error) errors[item] = error;
91
+ }
92
+ return errors;
93
+ }
94
+ function withRowItemError(errors, id, item, row, clearItems = []) {
95
+ const rowErrors = { ...errors[id] };
96
+ for (const clearItem of clearItems) delete rowErrors[clearItem];
97
+ const itemError = getRowItemError(item, row);
98
+ if (itemError) rowErrors[item] = itemError;
99
+ else delete rowErrors[item];
100
+ const nextErrors = { ...errors };
101
+ if (Object.keys(rowErrors).length) nextErrors[id] = rowErrors;
102
+ else delete nextErrors[id];
103
+ return nextErrors;
104
+ }
105
+ function filterReducer(state, action) {
106
+ switch (action.type) {
107
+ case "replace-state": return action.state;
108
+ case "add-row":
109
+ if (state.ids.includes(action.id)) return state;
110
+ return {
111
+ ...state,
112
+ ids: [...state.ids, action.id],
113
+ rows: {
114
+ ...state.rows,
115
+ [action.id]: action.row
116
+ }
117
+ };
118
+ case "remove-row": {
119
+ const rows = { ...state.rows };
120
+ const errors = { ...state.errors };
121
+ delete rows[action.id];
122
+ delete errors[action.id];
123
+ return {
124
+ ...state,
125
+ errors,
126
+ ids: state.ids.filter((id) => id !== action.id),
127
+ rows
128
+ };
129
+ }
130
+ case "set-row-field": {
131
+ if (!state.rows[action.id]) return state;
132
+ const row = {
133
+ field: action.field,
134
+ condition: action.condition,
135
+ value: void 0
136
+ };
137
+ return {
138
+ ...state,
139
+ errors: withRowItemError(state.errors, action.id, "field", row, ["condition", "value"]),
140
+ rows: {
141
+ ...state.rows,
142
+ [action.id]: row
143
+ }
144
+ };
145
+ }
146
+ case "set-row-condition": {
147
+ const currentRow = state.rows[action.id];
148
+ if (!currentRow) return state;
149
+ const row = {
150
+ ...currentRow,
151
+ condition: action.condition
152
+ };
153
+ return {
154
+ ...state,
155
+ errors: withRowItemError(state.errors, action.id, "condition", row),
156
+ rows: {
157
+ ...state.rows,
158
+ [action.id]: row
159
+ }
160
+ };
161
+ }
162
+ case "set-row-value": {
163
+ const currentRow = state.rows[action.id];
164
+ if (!currentRow) return state;
165
+ const row = {
166
+ ...currentRow,
167
+ value: action.value
168
+ };
169
+ return {
170
+ ...state,
171
+ errors: withRowItemError(state.errors, action.id, "value", row),
172
+ rows: {
173
+ ...state.rows,
174
+ [action.id]: row
175
+ }
176
+ };
177
+ }
178
+ case "apply": {
179
+ const hasErrors = Object.keys(action.errors).length > 0;
180
+ return {
181
+ ...state,
182
+ appliedCount: hasErrors ? state.appliedCount : state.ids.length,
183
+ errors: action.errors
184
+ };
185
+ }
186
+ case "reset": return emptyFilterState;
187
+ }
188
+ }
189
+ const FilterContext = React.createContext(null);
190
+ function useFilterContext() {
191
+ const context = React.useContext(FilterContext);
192
+ if (!context) throw new Error("Filter components must be rendered inside <Filter />.");
193
+ return context;
194
+ }
195
+ function Filter({ children, defaultJoin = "AND", fields, onApply, defaultValue = "" }) {
196
+ const [state, dispatch] = React.useReducer(filterReducer, void 0, () => buildStateFromSerializedFilters(defaultValue, fields));
197
+ const contentRef = React.useRef(null);
198
+ const loadedOptionsCache = React.useRef(/* @__PURE__ */ new Map());
199
+ const fieldsRef = React.useRef(fields);
200
+ fieldsRef.current = fields;
201
+ const fieldSignature = fields.map((field) => `${field.field}:${field.type}`).join("");
202
+ const lastDefaultValueRef = React.useRef(defaultValue);
203
+ const lastFieldSignatureRef = React.useRef(fieldSignature);
204
+ React.useEffect(() => {
205
+ if (lastDefaultValueRef.current === defaultValue && lastFieldSignatureRef.current === fieldSignature) return;
206
+ lastDefaultValueRef.current = defaultValue;
207
+ lastFieldSignatureRef.current = fieldSignature;
208
+ loadedOptionsCache.current.clear();
209
+ dispatch({
210
+ type: "replace-state",
211
+ state: buildStateFromSerializedFilters(defaultValue, fieldsRef.current)
212
+ });
213
+ }, [defaultValue, fieldSignature]);
214
+ const value = React.useMemo(() => ({
215
+ contentRef,
216
+ defaultJoin,
217
+ dispatch,
218
+ fields,
219
+ loadedOptionsCache,
220
+ onApply,
221
+ state
222
+ }), [
223
+ defaultJoin,
224
+ fields,
225
+ onApply,
226
+ state
227
+ ]);
228
+ return /* @__PURE__ */ jsx(FilterContext.Provider, {
229
+ value,
230
+ children
231
+ });
232
+ }
233
+ function FilterTrigger({ children, className, countClassName, hideCountWhenZero = true, render }) {
234
+ const { state } = useFilterContext();
235
+ const appliedCount = state.appliedCount;
236
+ if (render) return /* @__PURE__ */ jsx(Fragment, { children: render({ count: appliedCount }) });
237
+ return /* @__PURE__ */ jsxs("div", {
238
+ className: cn("relative", className),
239
+ children: [children, (appliedCount > 0 || !hideCountWhenZero) && /* @__PURE__ */ jsx("span", {
240
+ className: cn("absolute left-0 top-0 inline-flex size-5 translate-y-[-40%] items-center justify-center rounded-full bg-action-primary text-xs font-bold leading-none text-fg-on-brand", countClassName),
241
+ children: appliedCount
242
+ })]
243
+ });
244
+ }
245
+ let rowIdCounter = 0;
246
+ function createRow(fieldConfig) {
247
+ return {
248
+ field: fieldConfig?.field ?? "",
249
+ condition: fieldConfig?.type === "range" ? RANGE_CONDITION : ""
250
+ };
251
+ }
252
+ function FilterContent({ addFilterLabel = "Add Filter", className, label = "Where" }) {
253
+ const { contentRef, dispatch, fields, state } = useFilterContext();
254
+ return /* @__PURE__ */ jsx("div", {
255
+ ref: contentRef,
256
+ className: cn("max-h-80 space-y-4 overflow-y-auto pb-6", className),
257
+ children: /* @__PURE__ */ jsxs("div", {
258
+ className: "flex flex-col gap-y-4",
259
+ children: [
260
+ /* @__PURE__ */ jsx("p", {
261
+ className: "text-sm font-bold uppercase",
262
+ children: label
263
+ }),
264
+ !!state.ids.length && /* @__PURE__ */ jsx("div", {
265
+ className: "flex w-full flex-col gap-y-4",
266
+ children: state.ids.map((rowId) => /* @__PURE__ */ jsx(FilterRow, { id: rowId }, rowId))
267
+ }),
268
+ /* @__PURE__ */ jsxs(Button, {
269
+ type: "button",
270
+ variant: "ghost",
271
+ className: "w-fit gap-1.5 px-0 text-fg-brand hover:bg-transparent hover:text-action-secondary active:bg-transparent",
272
+ onClick: () => {
273
+ rowIdCounter += 1;
274
+ dispatch({
275
+ type: "add-row",
276
+ id: `filter-row-${rowIdCounter}`,
277
+ row: createRow(fields[0])
278
+ });
279
+ },
280
+ children: [/* @__PURE__ */ jsx(Plus, {}), addFilterLabel]
281
+ })
282
+ ]
283
+ })
284
+ });
285
+ }
286
+ function FilterRow({ id }) {
287
+ const { dispatch, fields, state } = useFilterContext();
288
+ const row = state.rows[id];
289
+ const fieldConfig = fields.find((config) => config.field === row?.field);
290
+ if (!row || !fieldConfig) return null;
291
+ return /* @__PURE__ */ jsxs("div", {
292
+ className: "flex items-start gap-4 md:gap-2",
293
+ children: [/* @__PURE__ */ jsxs("div", {
294
+ className: "grid flex-1 grid-cols-1 gap-4 md:grid-cols-3",
295
+ children: [
296
+ /* @__PURE__ */ jsx(FilterRowField, {
297
+ id,
298
+ row
299
+ }),
300
+ fieldConfig.type !== "range" && /* @__PURE__ */ jsx(FilterRowCondition, {
301
+ id,
302
+ row,
303
+ fieldType: fieldConfig.type
304
+ }),
305
+ /* @__PURE__ */ jsx(FilterRowValue, {
306
+ id,
307
+ row,
308
+ fieldConfig
309
+ })
310
+ ]
311
+ }), /* @__PURE__ */ jsx(Button, {
312
+ type: "button",
313
+ variant: "ghost",
314
+ size: "icon-sm",
315
+ onClick: () => dispatch({
316
+ type: "remove-row",
317
+ id
318
+ }),
319
+ children: /* @__PURE__ */ jsx(X, {})
320
+ })]
321
+ });
322
+ }
323
+ function FilterRowField({ id, row }) {
324
+ const { dispatch, fields, state } = useFilterContext();
325
+ const error = state.errors[id]?.field;
326
+ const options = fields.map((config) => ({
327
+ label: config.label,
328
+ value: config.field
329
+ }));
330
+ return /* @__PURE__ */ jsxs(Field, {
331
+ className: "w-full flex-1",
332
+ children: [/* @__PURE__ */ jsxs(Select, {
333
+ value: row.field,
334
+ onValueChange: (nextValue) => {
335
+ const nextField = typeof nextValue === "string" ? nextValue : "";
336
+ const nextConfig = fields.find((config) => config.field === nextField);
337
+ dispatch({
338
+ type: "set-row-field",
339
+ id,
340
+ field: nextField,
341
+ condition: nextConfig?.type === "range" ? RANGE_CONDITION : ""
342
+ });
343
+ },
344
+ items: options,
345
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
346
+ className: "w-full",
347
+ "aria-invalid": !!error,
348
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select field" })
349
+ }), /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
350
+ value: option.value,
351
+ children: option.label
352
+ }, option.value)) })]
353
+ }), error && /* @__PURE__ */ jsx(FieldError, { children: error })]
354
+ });
355
+ }
356
+ function FilterRowCondition({ id, row, fieldType }) {
357
+ const { dispatch, state } = useFilterContext();
358
+ const error = state.errors[id]?.condition;
359
+ const conditions = fieldType === "range" ? [] : conditionsByType[fieldType] ?? [];
360
+ return /* @__PURE__ */ jsxs(Field, {
361
+ className: "w-full flex-1",
362
+ children: [/* @__PURE__ */ jsxs(Select, {
363
+ value: row.condition,
364
+ onValueChange: (nextValue) => dispatch({
365
+ type: "set-row-condition",
366
+ id,
367
+ condition: typeof nextValue === "string" ? nextValue : ""
368
+ }),
369
+ items: conditions.map((condition) => ({
370
+ value: condition.id,
371
+ label: condition.name
372
+ })),
373
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
374
+ className: "w-full",
375
+ "aria-invalid": !!error,
376
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select condition" })
377
+ }), /* @__PURE__ */ jsx(SelectContent, { children: conditions.map((condition) => /* @__PURE__ */ jsx(SelectItem, {
378
+ value: condition.id,
379
+ children: condition.name
380
+ }, condition.id)) })]
381
+ }), error && /* @__PURE__ */ jsx(FieldError, { children: error })]
382
+ });
383
+ }
384
+ function FilterRowValue({ id, row, fieldConfig }) {
385
+ const { dispatch, state } = useFilterContext();
386
+ const error = state.errors[id]?.value;
387
+ const valueProps = {
388
+ field: fieldConfig,
389
+ value: row.value,
390
+ onChange: (value) => dispatch({
391
+ type: "set-row-value",
392
+ id,
393
+ value
394
+ }),
395
+ invalid: !!error,
396
+ error
397
+ };
398
+ return /* @__PURE__ */ jsxs(Field, {
399
+ className: cn("w-full flex-1", { "md:col-span-2": fieldConfig.type === "range" }),
400
+ children: [fieldConfig.renderValue ? fieldConfig.renderValue(valueProps) : /* @__PURE__ */ jsx(FilterBuiltInValue, { ...valueProps }), error && /* @__PURE__ */ jsx(FieldError, { children: error })]
401
+ });
402
+ }
403
+ function FilterBuiltInValue(props) {
404
+ const { field } = props;
405
+ switch (field.type) {
406
+ case "text": return /* @__PURE__ */ jsx(FilterValueText, {
407
+ ...props,
408
+ placeholder: `Enter ${field.label} value`
409
+ });
410
+ case "number": return /* @__PURE__ */ jsx(FilterValueNumber, {
411
+ ...props,
412
+ placeholder: `Enter ${field.label} value`
413
+ });
414
+ case "date": return /* @__PURE__ */ jsx(FilterValueDate, { ...props });
415
+ case "boolean": return /* @__PURE__ */ jsx(FilterValueBoolean, {
416
+ ...props,
417
+ placeholder: `Select ${field.label}`
418
+ });
419
+ case "range": return /* @__PURE__ */ jsx(FilterValueRange, { ...props });
420
+ case "select":
421
+ case "multiSelect": {
422
+ const multiple = field.type === "multiSelect";
423
+ const placeholder = `Select ${field.label}`;
424
+ if (field.loadOptions) return /* @__PURE__ */ jsx(FilterLoadedValueSelect, {
425
+ ...props,
426
+ multiple,
427
+ placeholder
428
+ });
429
+ return /* @__PURE__ */ jsx(FilterValueSelect, {
430
+ ...props,
431
+ multiple,
432
+ options: field.options ?? [],
433
+ placeholder
434
+ });
435
+ }
436
+ }
437
+ }
438
+ function FilterValueText({ value, onChange, invalid, placeholder }) {
439
+ return /* @__PURE__ */ jsx(Input, {
440
+ type: "text",
441
+ placeholder,
442
+ value: typeof value === "string" ? value : "",
443
+ onChange: (event) => onChange(event.target.value),
444
+ "aria-invalid": !!invalid
445
+ });
446
+ }
447
+ function FilterValueNumber({ value, onChange, invalid, placeholder }) {
448
+ return /* @__PURE__ */ jsx(Input, {
449
+ type: "number",
450
+ placeholder,
451
+ value: typeof value === "number" ? String(value) : "",
452
+ onChange: (event) => onChange(event.target.value === "" ? void 0 : Number(event.target.value)),
453
+ "aria-invalid": !!invalid
454
+ });
455
+ }
456
+ function FilterValueDate({ value, onChange, invalid }) {
457
+ return /* @__PURE__ */ jsx(Input, {
458
+ type: "date",
459
+ value: typeof value === "string" ? value : "",
460
+ onChange: (event) => onChange(event.target.value),
461
+ "aria-invalid": !!invalid
462
+ });
463
+ }
464
+ function FilterValueBoolean({ value, onChange, invalid, placeholder, trueLabel = "Yes", falseLabel = "No" }) {
465
+ const items = [{
466
+ label: trueLabel,
467
+ value: "true"
468
+ }, {
469
+ label: falseLabel,
470
+ value: "false"
471
+ }];
472
+ return /* @__PURE__ */ jsxs(Select, {
473
+ value: typeof value === "boolean" ? String(value) : "",
474
+ onValueChange: (nextValue) => onChange(nextValue === "true"),
475
+ items,
476
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
477
+ className: "w-full",
478
+ "aria-invalid": !!invalid,
479
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
480
+ }), /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, {
481
+ value: item.value,
482
+ children: item.label
483
+ }, item.value)) })]
484
+ });
485
+ }
486
+ function FilterValueRange({ value, onChange, invalid }) {
487
+ const rangeValue = getRangeValue(value);
488
+ return /* @__PURE__ */ jsxs("div", {
489
+ className: "flex items-center gap-2",
490
+ children: [
491
+ /* @__PURE__ */ jsx(Input, {
492
+ type: "number",
493
+ placeholder: "Min",
494
+ value: typeof rangeValue?.min === "number" ? rangeValue.min : "",
495
+ onChange: (event) => onChange(mergeRangeValue(rangeValue, "min", event.target.value)),
496
+ className: "flex-1",
497
+ "aria-invalid": !!invalid
498
+ }),
499
+ /* @__PURE__ */ jsx("span", {
500
+ className: "text-sm text-fg-secondary",
501
+ children: "to"
502
+ }),
503
+ /* @__PURE__ */ jsx(Input, {
504
+ type: "number",
505
+ placeholder: "Max",
506
+ value: typeof rangeValue?.max === "number" ? rangeValue.max : "",
507
+ onChange: (event) => onChange(mergeRangeValue(rangeValue, "max", event.target.value)),
508
+ className: "flex-1",
509
+ "aria-invalid": !!invalid
510
+ })
511
+ ]
512
+ });
513
+ }
514
+ function FilterValueSelect({ value, onChange, invalid, placeholder, options, multiple = false, loading = false, emptyMessage = "No options available", open, onOpenChange }) {
515
+ const toOptionValue = (itemValue) => {
516
+ return options.find((entry) => String(entry.value) === itemValue)?.value ?? itemValue;
517
+ };
518
+ return /* @__PURE__ */ jsxs(Select, {
519
+ multiple,
520
+ open,
521
+ onOpenChange,
522
+ value: multiple ? Array.isArray(value) ? value.map(String) : [] : typeof value === "string" || typeof value === "number" ? String(value) : "",
523
+ onValueChange: (nextValue) => {
524
+ if (Array.isArray(nextValue)) {
525
+ onChange(nextValue.map(toOptionValue));
526
+ return;
527
+ }
528
+ onChange(typeof nextValue === "string" ? toOptionValue(nextValue) : void 0);
529
+ },
530
+ items: options.map((option) => ({
531
+ label: option.label,
532
+ value: String(option.value)
533
+ })),
534
+ children: [/* @__PURE__ */ jsx(SelectTrigger, {
535
+ className: "w-full",
536
+ "aria-invalid": !!invalid,
537
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
538
+ }), /* @__PURE__ */ jsx(SelectContent, { children: loading ? /* @__PURE__ */ jsx("div", {
539
+ className: "px-3 py-2 text-sm text-fg-secondary",
540
+ children: "Loading..."
541
+ }) : options.length === 0 ? /* @__PURE__ */ jsx("div", {
542
+ className: "px-3 py-2 text-sm text-fg-secondary",
543
+ children: emptyMessage
544
+ }) : options.map((option) => /* @__PURE__ */ jsx(SelectItem, {
545
+ value: String(option.value),
546
+ children: option.label
547
+ }, option.value)) })]
548
+ });
549
+ }
550
+ /**
551
+ * Select whose options come from `field.loadOptions`. Nothing is fetched
552
+ * until the dropdown opens; results are cached per field on the nearest
553
+ * <Filter /> so other rows using the same field reuse them.
554
+ */
555
+ function FilterLoadedValueSelect({ field, multiple, placeholder, ...props }) {
556
+ const { loadedOptionsCache } = useFilterContext();
557
+ const [open, setOpen] = React.useState(false);
558
+ const [loading, setLoading] = React.useState(false);
559
+ const [loadedOptions, setLoadedOptions] = React.useState(null);
560
+ const mountedRef = React.useRef(true);
561
+ const fieldRef = React.useRef(field.field);
562
+ React.useEffect(() => {
563
+ return () => {
564
+ mountedRef.current = false;
565
+ };
566
+ }, []);
567
+ React.useEffect(() => {
568
+ fieldRef.current = field.field;
569
+ setOpen(false);
570
+ setLoading(false);
571
+ setLoadedOptions(null);
572
+ }, [field.field]);
573
+ const handleOpenChange = (nextOpen) => {
574
+ setOpen(nextOpen);
575
+ if (!nextOpen || loadedOptions || !field.loadOptions) return;
576
+ const cache = loadedOptionsCache.current;
577
+ const pending = cache.get(field.field) ?? field.loadOptions();
578
+ cache.set(field.field, pending);
579
+ setLoading(true);
580
+ pending.then((options) => {
581
+ if (mountedRef.current && fieldRef.current === field.field) setLoadedOptions(options);
582
+ }).catch(() => {
583
+ if (cache.get(field.field) === pending) cache.delete(field.field);
584
+ }).finally(() => {
585
+ if (mountedRef.current && fieldRef.current === field.field) setLoading(false);
586
+ });
587
+ };
588
+ return /* @__PURE__ */ jsx(FilterValueSelect, {
589
+ ...props,
590
+ multiple,
591
+ placeholder,
592
+ options: loadedOptions ?? field.options ?? [],
593
+ loading: loading && !loadedOptions,
594
+ open,
595
+ onOpenChange: handleOpenChange
596
+ });
597
+ }
598
+ function FilterApplyButton({ children = "Apply Filter", className, onApplySuccess }) {
599
+ const { contentRef, defaultJoin, dispatch, fields, onApply, state } = useFilterContext();
600
+ return /* @__PURE__ */ jsx(Button, {
601
+ className,
602
+ onClick: () => {
603
+ const errors = {};
604
+ for (const id of state.ids) {
605
+ const row = state.rows[id];
606
+ if (!row) continue;
607
+ const rowErrors = getRowErrors(row);
608
+ if (Object.keys(rowErrors).length) errors[id] = rowErrors;
609
+ }
610
+ dispatch({
611
+ type: "apply",
612
+ errors
613
+ });
614
+ if (Object.keys(errors).length) {
615
+ focusFirstInvalidFilterItem(contentRef.current);
616
+ return;
617
+ }
618
+ const filters = serializeFilters({
619
+ defaultJoin,
620
+ fields,
621
+ ids: state.ids,
622
+ rows: state.rows
623
+ });
624
+ onApply(filters.length ? JSON.stringify(filters) : "", filters);
625
+ onApplySuccess?.();
626
+ },
627
+ children
628
+ });
629
+ }
630
+ function FilterResetButton({ children = "Reset Filter", className, onReset }) {
631
+ const { dispatch, onApply } = useFilterContext();
632
+ return /* @__PURE__ */ jsx(Button, {
633
+ variant: "tertiary-outline",
634
+ className,
635
+ onClick: () => {
636
+ dispatch({ type: "reset" });
637
+ onApply("", []);
638
+ onReset?.();
639
+ },
640
+ children
641
+ });
642
+ }
643
+ function focusFirstInvalidFilterItem(root) {
644
+ setTimeout(() => {
645
+ const invalidItem = (root ?? document).querySelector("[aria-invalid=true]");
646
+ if (invalidItem instanceof HTMLButtonElement) {
647
+ invalidItem.click();
648
+ return;
649
+ }
650
+ if (invalidItem instanceof HTMLInputElement) invalidItem.focus();
651
+ }, 0);
652
+ }
653
+ function serializeFilters({ defaultJoin, fields, ids, rows }) {
654
+ return ids.flatMap((id) => {
655
+ const row = rows[id];
656
+ if (!row) return [];
657
+ const fieldConfig = fields.find((config) => config.field === row.field);
658
+ if (!fieldConfig) return [];
659
+ return serializeRow(defaultJoin, fieldConfig, row);
660
+ });
661
+ }
662
+ function serializeRow(defaultJoin, fieldConfig, row) {
663
+ if (fieldConfig.type === "range") {
664
+ const rangeValue = getRangeValue(row.value);
665
+ if (!rangeValue) return [];
666
+ return [...typeof rangeValue.min === "number" ? [{
667
+ connector: defaultJoin,
668
+ field: row.field,
669
+ action: "greaterThan",
670
+ value: rangeValue.min
671
+ }] : [], ...typeof rangeValue.max === "number" ? [{
672
+ connector: defaultJoin,
673
+ field: row.field,
674
+ action: "lessThan",
675
+ value: rangeValue.max
676
+ }] : []];
677
+ }
678
+ if (!isFilterCondition(row.condition) || typeof row.value === "undefined") return [];
679
+ return [{
680
+ connector: defaultJoin,
681
+ field: row.field,
682
+ action: row.condition,
683
+ value: row.value
684
+ }];
685
+ }
686
+ /**
687
+ * Parse a serialized filter string (as produced by `onApply`) back into
688
+ * structured filters. Invalid or malformed entries are dropped.
689
+ */
690
+ function parseSerializedFilters(value) {
691
+ if (!value.trim()) return [];
692
+ try {
693
+ const parsed = JSON.parse(value);
694
+ if (!Array.isArray(parsed)) return [];
695
+ return parsed.filter(isSerializedFilter);
696
+ } catch {
697
+ return [];
698
+ }
699
+ }
700
+ function buildStateFromSerializedFilters(value, fields) {
701
+ const parsedFilters = parseSerializedFilters(value);
702
+ if (!parsedFilters.length) return emptyFilterState;
703
+ const ids = [];
704
+ const rows = {};
705
+ for (let index = 0; index < parsedFilters.length; index += 1) {
706
+ const currentFilter = parsedFilters[index];
707
+ const fieldConfig = fields.find((config) => config.field === currentFilter.field);
708
+ if (!fieldConfig) continue;
709
+ const rowId = `${currentFilter.field}-${index}`;
710
+ if (fieldConfig.type === "range") {
711
+ const rangeValue = {};
712
+ if (currentFilter.action === "greaterThan" && typeof currentFilter.value === "number") rangeValue.min = currentFilter.value;
713
+ if (currentFilter.action === "lessThan" && typeof currentFilter.value === "number") rangeValue.max = currentFilter.value;
714
+ const nextFilter = parsedFilters[index + 1];
715
+ if (nextFilter && nextFilter.field === currentFilter.field && nextFilter.connector === currentFilter.connector) {
716
+ if (nextFilter.action === "greaterThan" && typeof nextFilter.value === "number") {
717
+ rangeValue.min = nextFilter.value;
718
+ index += 1;
719
+ } else if (nextFilter.action === "lessThan" && typeof nextFilter.value === "number") {
720
+ rangeValue.max = nextFilter.value;
721
+ index += 1;
722
+ }
723
+ }
724
+ ids.push(rowId);
725
+ rows[rowId] = {
726
+ field: currentFilter.field,
727
+ condition: RANGE_CONDITION,
728
+ value: rangeValue
729
+ };
730
+ continue;
731
+ }
732
+ ids.push(rowId);
733
+ rows[rowId] = {
734
+ field: currentFilter.field,
735
+ condition: currentFilter.action,
736
+ value: currentFilter.value
737
+ };
738
+ }
739
+ return {
740
+ appliedCount: ids.length,
741
+ errors: {},
742
+ ids,
743
+ rows
744
+ };
745
+ }
746
+ function isSerializedFilter(value) {
747
+ if (typeof value !== "object" || value === null) return false;
748
+ const filter = value;
749
+ return (filter.connector === "AND" || filter.connector === "OR") && typeof filter.field === "string" && isFilterCondition(filter.action) && isSerializedFilterValue(filter.value);
750
+ }
751
+ function isFilterCondition(action) {
752
+ return action === "equals" || action === "greaterThan" || action === "lessThan" || action === "contains";
753
+ }
754
+ function isSerializedFilterValue(value) {
755
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every((item) => typeof item === "string" || typeof item === "number");
756
+ }
757
+ function getRangeValue(value) {
758
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return;
759
+ const rangeValue = value;
760
+ const min = typeof rangeValue.min === "number" && Number.isFinite(rangeValue.min) ? rangeValue.min : void 0;
761
+ const max = typeof rangeValue.max === "number" && Number.isFinite(rangeValue.max) ? rangeValue.max : void 0;
762
+ if (typeof min === "undefined" && typeof max === "undefined") return;
763
+ return {
764
+ min,
765
+ max
766
+ };
767
+ }
768
+ function mergeRangeValue(currentValue, boundary, rawValue) {
769
+ return getRangeValue({
770
+ ...currentValue,
771
+ [boundary]: rawValue === "" ? void 0 : Number(rawValue)
772
+ });
773
+ }
774
+ //#endregion
775
+ export { Filter, FilterApplyButton, FilterContent, FilterResetButton, FilterTrigger, FilterValueBoolean, FilterValueDate, FilterValueNumber, FilterValueRange, FilterValueSelect, FilterValueText, parseSerializedFilters };