themelia-react-ui 2.0.5 → 3.0.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 (968) hide show
  1. package/CHANGELOG.md +326 -0
  2. package/MIGRATION.md +858 -0
  3. package/README.md +35 -24
  4. package/dist/{accordion-B9MHG0cT.js → accordion-DNVqwEIC.js} +37 -37
  5. package/dist/accordion-DNVqwEIC.js.map +1 -0
  6. package/dist/action-menu-D5343RwT.js +286 -0
  7. package/dist/action-menu-D5343RwT.js.map +1 -0
  8. package/dist/ai-artifact-otrz9ZwS.js +1214 -0
  9. package/dist/ai-artifact-otrz9ZwS.js.map +1 -0
  10. package/dist/anchored-positioning-1U_eBFNx.js +9 -0
  11. package/dist/anchored-positioning-1U_eBFNx.js.map +1 -0
  12. package/dist/app-shell-CPN30Nb1.js +372 -0
  13. package/dist/app-shell-CPN30Nb1.js.map +1 -0
  14. package/dist/{attachment-Dg_69lPS.js → attachment-D2-fpfmv.js} +15 -15
  15. package/dist/{attachment-Dg_69lPS.js.map → attachment-D2-fpfmv.js.map} +1 -1
  16. package/dist/{auth-DTkkshS8.js → auth-g_oUTDDC.js} +236 -243
  17. package/dist/auth-g_oUTDDC.js.map +1 -0
  18. package/dist/{avatar-CeZaFmNH.js → avatar-Ca3Ihrq4.js} +4 -4
  19. package/dist/{avatar-CeZaFmNH.js.map → avatar-Ca3Ihrq4.js.map} +1 -1
  20. package/dist/{badge-xIiV_E7f.js → badge-oGiXblW7.js} +8 -9
  21. package/dist/badge-oGiXblW7.js.map +1 -0
  22. package/dist/base/accordion.js +1 -1
  23. package/dist/base/action-menu.js +1 -1
  24. package/dist/base/attachment.js +1 -1
  25. package/dist/base/avatar.js +1 -1
  26. package/dist/base/badge.js +1 -1
  27. package/dist/base/batch-action-bar.js +1 -1
  28. package/dist/base/buttons.js +2 -2
  29. package/dist/base/cards.js +3 -3
  30. package/dist/base/carousel.js +11 -11
  31. package/dist/base/carousel.js.map +1 -1
  32. package/dist/base/cascader.js +1 -1
  33. package/dist/base/chart.js +1 -1
  34. package/dist/base/choice-inputs.js +2 -2
  35. package/dist/base/code-block.js +1 -1
  36. package/dist/base/combobox.js +1 -1
  37. package/dist/base/command.js +1 -1
  38. package/dist/base/copyable.js +1 -1
  39. package/dist/base/date-pickers.js +2 -2
  40. package/dist/base/display.js +7 -7
  41. package/dist/base/feedback.js +4 -4
  42. package/dist/base/forms-numeric.js +2 -2
  43. package/dist/base/forms.js +2 -2
  44. package/dist/base/inline-edit.js +13 -13
  45. package/dist/base/inline-edit.js.map +1 -1
  46. package/dist/base/item.js +1 -1
  47. package/dist/base/media-gallery.js +203 -2
  48. package/dist/base/media-gallery.js.map +1 -0
  49. package/dist/base/metadata-list.js +1 -1
  50. package/dist/base/navigation.js +7 -7
  51. package/dist/base/popover-menu.js +1 -1
  52. package/dist/base/popover.js +1 -1
  53. package/dist/base/qr-code.js +32 -22
  54. package/dist/base/qr-code.js.map +1 -1
  55. package/dist/base/repeaters.js +208 -198
  56. package/dist/base/repeaters.js.map +1 -1
  57. package/dist/base/sidebar.js +2 -2
  58. package/dist/base/signature-pad.js +14 -14
  59. package/dist/base/signature-pad.js.map +1 -1
  60. package/dist/base/skeleton.js +1 -1
  61. package/dist/base/spinner.js +8 -14
  62. package/dist/base/spinner.js.map +1 -1
  63. package/dist/base/structure.js +1 -1
  64. package/dist/base/table.js +1 -1
  65. package/dist/base/text-inputs.js +3 -3
  66. package/dist/base/toaster.js +2 -2
  67. package/dist/base/tree.js +2 -2
  68. package/dist/base/upload-queue.js +303 -2
  69. package/dist/base/upload-queue.js.map +1 -0
  70. package/dist/base/upload.js +3 -4
  71. package/dist/base/value-inputs.js +1 -1
  72. package/dist/{batch-action-bar-Cb8cuvyy.js → batch-action-bar-D6MZQNnC.js} +10 -10
  73. package/dist/{batch-action-bar-Cb8cuvyy.js.map → batch-action-bar-D6MZQNnC.js.map} +1 -1
  74. package/dist/blocks/admin.js +242 -228
  75. package/dist/blocks/admin.js.map +1 -1
  76. package/dist/blocks/ai.js +398 -354
  77. package/dist/blocks/ai.js.map +1 -1
  78. package/dist/blocks/analytics/charts.js +1022 -0
  79. package/dist/blocks/analytics/charts.js.map +1 -0
  80. package/dist/blocks/analytics/usage-card.js +1 -1
  81. package/dist/blocks/analytics.js +173 -1392
  82. package/dist/blocks/analytics.js.map +1 -1
  83. package/dist/blocks/collaboration.js +1 -1
  84. package/dist/blocks/commerce/receipt.js +1 -1
  85. package/dist/blocks/commerce.js +1533 -1399
  86. package/dist/blocks/commerce.js.map +1 -1
  87. package/dist/blocks/data-display.js +2 -3
  88. package/dist/blocks/onboarding.js +91 -82
  89. package/dist/blocks/onboarding.js.map +1 -1
  90. package/dist/blocks/planning.js +25 -25
  91. package/dist/blocks/planning.js.map +1 -1
  92. package/dist/blocks/timelines.js +2 -2
  93. package/dist/breadcrumbs-CQ9JSlez.js +136 -0
  94. package/dist/breadcrumbs-CQ9JSlez.js.map +1 -0
  95. package/dist/{button-S2Cubiiz.js → button-rd6FiHfQ.js} +12 -8
  96. package/dist/button-rd6FiHfQ.js.map +1 -0
  97. package/dist/{buttons-BedGfygC.js → buttons-pZVgPTZn.js} +230 -246
  98. package/dist/buttons-pZVgPTZn.js.map +1 -0
  99. package/dist/{cards-rNX1M4Xn.js → cards-CgWyqvgZ.js} +25 -22
  100. package/dist/{cards-rNX1M4Xn.js.map → cards-CgWyqvgZ.js.map} +1 -1
  101. package/dist/cascader-Cf05pwaq.js +444 -0
  102. package/dist/cascader-Cf05pwaq.js.map +1 -0
  103. package/dist/{chart-Darg_0Kv.js → chart-CygRCyIZ.js} +5 -5
  104. package/dist/{chart-Darg_0Kv.js.map → chart-CygRCyIZ.js.map} +1 -1
  105. package/dist/{checkbox-fflqmODR.js → checkbox-Dy5_XBMZ.js} +4 -4
  106. package/dist/{checkbox-fflqmODR.js.map → checkbox-Dy5_XBMZ.js.map} +1 -1
  107. package/dist/{choice-inputs-zUgBZfE4.js → choice-inputs-oJEsrb5Y.js} +195 -184
  108. package/dist/choice-inputs-oJEsrb5Y.js.map +1 -0
  109. package/dist/{code-block-BzmM9Eig.js → code-block-BrLD7mCi.js} +44 -60
  110. package/dist/code-block-BrLD7mCi.js.map +1 -0
  111. package/dist/collapsible-CRCCg_bO.js +80 -0
  112. package/dist/collapsible-CRCCg_bO.js.map +1 -0
  113. package/dist/{collection-content-gDh1v6O4.js → collection-content-D7SoDlYd.js} +3 -3
  114. package/dist/{collection-content-gDh1v6O4.js.map → collection-content-D7SoDlYd.js.map} +1 -1
  115. package/dist/combobox-Dl6f6kHz.js +362 -0
  116. package/dist/combobox-Dl6f6kHz.js.map +1 -0
  117. package/dist/combobox-DrDXtSSt.js +929 -0
  118. package/dist/combobox-DrDXtSSt.js.map +1 -0
  119. package/dist/command-CjZ2VzKC.js +432 -0
  120. package/dist/command-CjZ2VzKC.js.map +1 -0
  121. package/dist/comments-C2MZyRmh.js +1214 -0
  122. package/dist/comments-C2MZyRmh.js.map +1 -0
  123. package/dist/components/base/accordion/accordion.d.ts +11 -3
  124. package/dist/components/base/action-menu/action-menu.d.ts +11 -3
  125. package/dist/components/base/buttons/button.d.ts +2 -2
  126. package/dist/components/base/buttons/index.d.ts +1 -1
  127. package/dist/components/base/buttons/loader-button.d.ts +6 -15
  128. package/dist/components/base/cards/index.d.ts +1 -1
  129. package/dist/components/base/cards/partials/card-body-context.d.ts +6 -0
  130. package/dist/components/base/cards/smart-card.d.ts +0 -2
  131. package/dist/components/base/cards/smart-card.types.d.ts +12 -10
  132. package/dist/components/base/cascader/cascader.d.ts +8 -2
  133. package/dist/components/base/cascader/cascader.types.d.ts +24 -2
  134. package/dist/components/base/cascader/index.d.ts +1 -1
  135. package/dist/components/base/choice-inputs/choice-types.d.ts +4 -0
  136. package/dist/components/base/choice-inputs/pill-radio-group.d.ts +7 -6
  137. package/dist/components/base/choice-inputs/switch.d.ts +1 -1
  138. package/dist/components/base/code-block/use-code-copy.d.ts +2 -6
  139. package/dist/components/base/combobox/combobox-field.d.ts +2 -2
  140. package/dist/components/base/command/command.d.ts +1 -1
  141. package/dist/components/base/date-pickers/date-picker-internals.d.ts +3 -1
  142. package/dist/components/base/date-pickers/datepicker.types.d.ts +11 -7
  143. package/dist/components/base/date-pickers/time-picker.d.ts +17 -3
  144. package/dist/components/base/display/dialog.d.ts +3 -9
  145. package/dist/components/base/display/index.d.ts +2 -3
  146. package/dist/components/base/display/separator.d.ts +1 -1
  147. package/dist/components/base/feedback/alert.d.ts +2 -1
  148. package/dist/components/base/feedback/empty.d.ts +10 -2
  149. package/dist/components/base/feedback/state-display.d.ts +5 -1
  150. package/dist/components/base/feedback/state-display.strings.d.ts +9 -0
  151. package/dist/components/base/forms/form-field.d.ts +7 -2
  152. package/dist/components/base/forms/workflow.d.ts +2 -2
  153. package/dist/components/base/forms-numeric/coordinates-input.d.ts +4 -1
  154. package/dist/components/base/forms-numeric/decimal-input.d.ts +2 -2
  155. package/dist/components/base/forms-numeric/dimensions-input.d.ts +13 -18
  156. package/dist/components/base/forms-numeric/index.d.ts +3 -3
  157. package/dist/components/base/forms-numeric/numeric-composite-field.d.ts +12 -0
  158. package/dist/components/base/forms-numeric/weight-input.d.ts +6 -1
  159. package/dist/components/base/item/item.types.d.ts +6 -2
  160. package/dist/components/base/metadata-list/index.d.ts +1 -3
  161. package/dist/components/base/metadata-list/metadata-list.d.ts +4 -1
  162. package/dist/components/base/navigation/index.d.ts +2 -2
  163. package/dist/components/base/navigation/language-switcher.d.ts +17 -8
  164. package/dist/components/base/navigation/navigation-tabs.d.ts +8 -1
  165. package/dist/components/base/navigation/page-header/index.d.ts +1 -1
  166. package/dist/components/base/navigation/page-header/page-header.d.ts +13 -17
  167. package/dist/components/base/navigation/pagination.d.ts +5 -5
  168. package/dist/components/base/popover/popover.recipes.d.ts +0 -1
  169. package/dist/components/base/qr-code/qr-code.d.ts +4 -0
  170. package/dist/components/base/repeaters/index.d.ts +1 -1
  171. package/dist/components/base/repeaters/key-value-editor.d.ts +6 -1
  172. package/dist/components/base/sheet/sheet.d.ts +6 -15
  173. package/dist/components/base/sidebar/index.d.ts +1 -6
  174. package/dist/components/base/sidebar/sidebar.d.ts +40 -10
  175. package/dist/components/base/skeleton/skeleton.d.ts +1 -1
  176. package/dist/components/base/structure/structure.types.d.ts +11 -2
  177. package/dist/components/base/text-inputs/index.d.ts +1 -1
  178. package/dist/components/base/tree/index.d.ts +1 -0
  179. package/dist/components/base/tree/tree.d.ts +2 -2
  180. package/dist/components/base/tree/tree.types.d.ts +7 -1
  181. package/dist/components/base/upload/avatar-upload.d.ts +2 -1
  182. package/dist/components/base/upload/file-upload.validation.d.ts +37 -1
  183. package/dist/components/base/upload/image-upload.d.ts +4 -1
  184. package/dist/components/base/upload/index.d.ts +3 -9
  185. package/dist/components/base/value-inputs/date-time-input.d.ts +4 -0
  186. package/dist/components/base/value-inputs/slider.d.ts +5 -2
  187. package/dist/components/blocks/admin/action-surfaces/index.d.ts +17 -4
  188. package/dist/components/blocks/admin/api-key-list/api-key-list.types.d.ts +9 -3
  189. package/dist/components/blocks/admin/index.d.ts +1 -1
  190. package/dist/components/blocks/ai/ai-artifact/ai-artifact.d.ts +1 -1
  191. package/dist/components/blocks/ai/ai-artifact/types.d.ts +9 -4
  192. package/dist/components/blocks/ai/ai-chain-of-thought/ai-chain-of-thought.d.ts +1 -1
  193. package/dist/components/blocks/ai/ai-chain-of-thought/types.d.ts +11 -1
  194. package/dist/components/blocks/ai/ai-citation/ai-citation.d.ts +1 -1
  195. package/dist/components/blocks/ai/ai-citation/types.d.ts +8 -0
  196. package/dist/components/blocks/ai/ai-confirmation/ai-confirmation.d.ts +1 -1
  197. package/dist/components/blocks/ai/ai-confirmation/types.d.ts +21 -5
  198. package/dist/components/blocks/ai/ai-feedback/types.d.ts +7 -2
  199. package/dist/components/blocks/ai/ai-inline-citation/types.d.ts +9 -3
  200. package/dist/components/blocks/ai/ai-package-info/ai-package-info.d.ts +1 -1
  201. package/dist/components/blocks/ai/ai-package-info/types.d.ts +6 -0
  202. package/dist/components/blocks/ai/ai-reasoning/types.d.ts +2 -0
  203. package/dist/components/blocks/ai/ai-sources/ai-sources.d.ts +1 -1
  204. package/dist/components/blocks/ai/ai-sources/types.d.ts +10 -2
  205. package/dist/components/blocks/ai/ai-task/ai-task.d.ts +1 -1
  206. package/dist/components/blocks/ai/ai-task/types.d.ts +10 -1
  207. package/dist/components/blocks/ai/ai-tool-call/ai-tool-call.d.ts +1 -1
  208. package/dist/components/blocks/ai/ai-tool-call/types.d.ts +8 -0
  209. package/dist/components/blocks/ai/ai.strings.d.ts +2 -0
  210. package/dist/components/blocks/analytics/activity-heatmap/types.d.ts +1 -1
  211. package/dist/components/blocks/analytics/analytics.strings.d.ts +2 -0
  212. package/dist/components/blocks/analytics/atoms/metric-trend-chip.d.ts +11 -1
  213. package/dist/components/blocks/analytics/chart-card/chart-card.d.ts +7 -5
  214. package/dist/components/blocks/analytics/charts/index.d.ts +27 -0
  215. package/dist/components/blocks/analytics/index.d.ts +17 -24
  216. package/dist/components/blocks/analytics/metric/metric.d.ts +7 -3
  217. package/dist/components/blocks/analytics/metric-comparison/metric-comparison.d.ts +2 -0
  218. package/dist/components/blocks/analytics/metric-grid/metric-grid.d.ts +4 -5
  219. package/dist/components/blocks/analytics/types.d.ts +13 -4
  220. package/dist/components/blocks/analytics/usage-card/usage-card.strings.d.ts +2 -0
  221. package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
  222. package/dist/components/blocks/commerce/address-card/types.d.ts +5 -16
  223. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.d.ts +2 -2
  224. package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.types.d.ts +6 -4
  225. package/dist/components/blocks/commerce/cart-summary/cart-summary.d.ts +0 -2
  226. package/dist/components/blocks/commerce/cart-summary/index.d.ts +2 -2
  227. package/dist/components/blocks/commerce/cart-summary/types.d.ts +9 -11
  228. package/dist/components/blocks/commerce/coupon-input/coupon-input.d.ts +1 -1
  229. package/dist/components/blocks/commerce/coupon-input/types.d.ts +7 -3
  230. package/dist/components/blocks/commerce/discount-stack/discount-stack.d.ts +0 -2
  231. package/dist/components/blocks/commerce/discount-stack/index.d.ts +2 -2
  232. package/dist/components/blocks/commerce/discount-stack/types.d.ts +4 -6
  233. package/dist/components/blocks/commerce/fulfillment-group/fulfillment-group.d.ts +1 -1
  234. package/dist/components/blocks/commerce/fulfillment-group/types.d.ts +2 -0
  235. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-balance.d.ts +18 -0
  236. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-compact.d.ts +1 -1
  237. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-copy-button.d.ts +0 -1
  238. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-dark.d.ts +1 -1
  239. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-full.d.ts +1 -1
  240. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-illustrated.d.ts +1 -1
  241. package/dist/components/blocks/commerce/giftcard-card/partials/giftcard-minimal.d.ts +1 -1
  242. package/dist/components/blocks/commerce/giftcard-card/types.d.ts +16 -5
  243. package/dist/components/blocks/commerce/index.d.ts +8 -8
  244. package/dist/components/blocks/commerce/inventory-level/inventory-level.strings.d.ts +2 -0
  245. package/dist/components/blocks/commerce/inventory-level/types.d.ts +1 -1
  246. package/dist/components/blocks/commerce/inventory-section/types.d.ts +0 -5
  247. package/dist/components/blocks/commerce/invoice-line-items/types.d.ts +6 -3
  248. package/dist/components/blocks/commerce/loyalty-points/loyalty-points.d.ts +1 -1
  249. package/dist/components/blocks/commerce/loyalty-points/types.d.ts +11 -5
  250. package/dist/components/blocks/commerce/order-status/order-status.d.ts +1 -1
  251. package/dist/components/blocks/commerce/order-status/types.d.ts +12 -8
  252. package/dist/components/blocks/commerce/order-timeline/order-timeline.d.ts +1 -1
  253. package/dist/components/blocks/commerce/order-timeline/types.d.ts +3 -1
  254. package/dist/components/blocks/commerce/payment-method/index.d.ts +2 -2
  255. package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +0 -8
  256. package/dist/components/blocks/commerce/payment-method/types.d.ts +0 -2
  257. package/dist/components/blocks/commerce/receipt/index.d.ts +1 -1
  258. package/dist/components/blocks/commerce/receipt/receipt-items.d.ts +1 -1
  259. package/dist/components/blocks/commerce/receipt/types.d.ts +10 -0
  260. package/dist/components/blocks/commerce/refund-status/index.d.ts +2 -2
  261. package/dist/components/blocks/commerce/refund-status/refund-status.d.ts +0 -2
  262. package/dist/components/blocks/commerce/refund-status/types.d.ts +0 -2
  263. package/dist/components/blocks/commerce/seo-listing/types.d.ts +7 -0
  264. package/dist/components/blocks/commerce/shared/code-entry.d.ts +39 -0
  265. package/dist/components/blocks/commerce/shared/order-status.d.ts +1 -1
  266. package/dist/components/blocks/commerce/subscription-summary/subscription-summary.d.ts +1 -1
  267. package/dist/components/blocks/commerce/subscription-summary/types.d.ts +10 -1
  268. package/dist/components/blocks/commerce/upcoming-booking/index.d.ts +2 -1
  269. package/dist/components/blocks/commerce/upcoming-booking/types.d.ts +8 -0
  270. package/dist/components/blocks/commerce/upcoming-booking/upcoming-booking.d.ts +2 -2
  271. package/dist/components/blocks/commerce/vendor-profile/types.d.ts +4 -5
  272. package/dist/components/blocks/commerce/voucher-entry/types.d.ts +6 -3
  273. package/dist/components/blocks/commerce/voucher-entry/voucher-entry.d.ts +1 -1
  274. package/dist/components/blocks/content-block-hooks.d.ts +22 -0
  275. package/dist/components/blocks/data-display/dense-info-card/dense-info.strings.d.ts +5 -1
  276. package/dist/components/blocks/data-display/dense-info-card/helpers.d.ts +3 -1
  277. package/dist/components/blocks/data-display/dense-info-card/index.d.ts +1 -1
  278. package/dist/components/blocks/data-display/dense-info-card/partials/dense-info-classification.d.ts +1 -1
  279. package/dist/components/blocks/data-display/dense-info-card/partials/dense-info-dashboard.d.ts +1 -1
  280. package/dist/components/blocks/data-display/dense-info-card/partials/dense-info-financial.d.ts +1 -1
  281. package/dist/components/blocks/data-display/dense-info-card/partials/dense-info-project.d.ts +1 -1
  282. package/dist/components/blocks/data-display/dense-info-card/partials/dense-info-score.d.ts +1 -1
  283. package/dist/components/blocks/data-display/dense-info-card/types.d.ts +12 -5
  284. package/dist/components/blocks/data-display/empty-state/empty-state.types.d.ts +10 -3
  285. package/dist/components/blocks/data-display/index.d.ts +0 -1
  286. package/dist/components/blocks/data-display/relationship-card-frame.d.ts +1 -1
  287. package/dist/components/blocks/onboarding/checklist/checklist.types.d.ts +5 -3
  288. package/dist/components/blocks/planning/task-card.types.d.ts +7 -3
  289. package/dist/components/blocks/timelines/changelog/types.d.ts +2 -2
  290. package/dist/components/blocks/timelines/index.d.ts +2 -2
  291. package/dist/components/blocks/timelines/milestones/types.d.ts +2 -2
  292. package/dist/components/blocks/timelines/shared/timeline.d.ts +6 -0
  293. package/dist/components/blocks/timelines/steps-card/index.d.ts +2 -1
  294. package/dist/components/blocks/timelines/steps-card/steps-card.d.ts +2 -2
  295. package/dist/components/blocks/timelines/steps-card/types.d.ts +13 -1
  296. package/dist/components/features/activities/activities.strings.d.ts +5 -3
  297. package/dist/components/features/activities/activities.types.d.ts +46 -22
  298. package/dist/components/features/activities/hooks/use-activity-feed.d.ts +6 -0
  299. package/dist/components/features/activities/hooks/use-activity-resources.d.ts +2 -1
  300. package/dist/components/features/activities/index.d.ts +1 -1
  301. package/dist/components/features/activities/partials/activity-headline.d.ts +5 -0
  302. package/dist/components/features/activities/partials/activity-row.d.ts +12 -13
  303. package/dist/components/features/activities/partials/row-layers.d.ts +7 -0
  304. package/dist/components/features/activities/relative-time.d.ts +18 -0
  305. package/dist/components/features/ai-chat/ai-chat.d.ts +6 -2
  306. package/dist/components/features/ai-chat/ai-chat.strings.d.ts +41 -2
  307. package/dist/components/features/ai-chat/ai-chat.types.d.ts +6 -0
  308. package/dist/components/features/ai-chat/hooks/use-ai-chat-scroll.d.ts +1 -1
  309. package/dist/components/features/ai-chat/partials/ai-chat-attachments-strip.d.ts +5 -1
  310. package/dist/components/features/ai-chat/partials/ai-chat-prompt-input.d.ts +2 -2
  311. package/dist/components/features/ai-chat/partials/ai-chat-queue.d.ts +3 -1
  312. package/dist/components/features/ai-chat/partials/ai-chat-suggestions-row.d.ts +6 -1
  313. package/dist/components/features/appointment-calendar/appointment-calendar.d.ts +1 -1
  314. package/dist/components/features/appointment-calendar/appointment-calendar.types.d.ts +20 -4
  315. package/dist/components/features/appointment-calendar/index.d.ts +1 -1
  316. package/dist/components/features/appointment-calendar/partials/appointment-agenda.d.ts +18 -10
  317. package/dist/components/features/async-preview/async-preview.d.ts +2 -2
  318. package/dist/components/features/async-preview/async-preview.types.d.ts +30 -1
  319. package/dist/components/features/async-preview/preview-trigger-cell.d.ts +7 -2
  320. package/dist/components/features/combobox/async-resource-combobox.d.ts +2 -2
  321. package/dist/components/features/combobox/combobox.d.ts +12 -3
  322. package/dist/components/features/combobox/components/error-message.d.ts +3 -1
  323. package/dist/components/features/combobox/hooks/use-combobox-core.d.ts +4 -3
  324. package/dist/components/features/combobox/hooks/use-combobox-state.d.ts +1 -0
  325. package/dist/components/features/combobox/hooks/use-load-more.d.ts +1 -0
  326. package/dist/components/features/combobox/index.d.ts +1 -1
  327. package/dist/components/features/combobox/types.d.ts +68 -37
  328. package/dist/components/features/comments/comments.strings.d.ts +6 -5
  329. package/dist/components/features/comments/comments.types.d.ts +40 -26
  330. package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -1
  331. package/dist/components/features/comments/hooks/use-comments.d.ts +8 -1
  332. package/dist/components/features/data-view/data-view.strings.d.ts +9 -2
  333. package/dist/components/features/data-view/data-view.types.d.ts +15 -2
  334. package/dist/components/features/email-composer/email-html.d.ts +5 -0
  335. package/dist/components/features/email-composer/http.d.ts +2 -0
  336. package/dist/components/features/email-composer/strings.d.ts +17 -2
  337. package/dist/components/features/email-composer/types.d.ts +19 -2
  338. package/dist/components/features/email-composer/use-composer.d.ts +2 -78
  339. package/dist/components/features/event-calendar/event-calendar-day-cell.d.ts +1 -1
  340. package/dist/components/features/event-calendar/event-calendar-event-badge.d.ts +1 -1
  341. package/dist/components/features/event-calendar/event-calendar-header.d.ts +1 -1
  342. package/dist/components/features/event-calendar/event-calendar-legend.d.ts +2 -2
  343. package/dist/components/features/event-calendar/event-calendar.d.ts +1 -1
  344. package/dist/components/features/event-calendar/event-calendar.types.d.ts +126 -21
  345. package/dist/components/features/filters/facets/date-facet.d.ts +4 -2
  346. package/dist/components/features/filters/facets/range-facet.d.ts +24 -7
  347. package/dist/components/features/filters/filter-context.d.ts +9 -0
  348. package/dist/components/features/filters/filters.strings.d.ts +36 -3
  349. package/dist/components/features/filters/filters.types.d.ts +75 -8
  350. package/dist/components/features/filters/hooks/use-filter-draft.d.ts +1 -0
  351. package/dist/components/features/filters/index.d.ts +2 -2
  352. package/dist/components/features/filters/operator-options.d.ts +25 -2
  353. package/dist/components/features/filters/partials/active-filter-item.d.ts +0 -13
  354. package/dist/components/features/filters/partials/async-options-status.d.ts +32 -0
  355. package/dist/components/features/filters/partials/date-filter-content.d.ts +3 -2
  356. package/dist/components/features/filters/partials/filter-draft-footer.d.ts +11 -0
  357. package/dist/components/features/filters/partials/filter-operator-select.d.ts +4 -2
  358. package/dist/components/features/filters/partials/filter-pill.d.ts +5 -1
  359. package/dist/components/features/filters/partials/filter-popover-content.d.ts +4 -2
  360. package/dist/components/features/filters/partials/filter-tabs.d.ts +2 -1
  361. package/dist/components/features/filters/partials/range-filter-content.d.ts +12 -0
  362. package/dist/components/features/filters/partials/regular-filter-content.d.ts +1 -1
  363. package/dist/components/features/filters/utils/filter-utils.d.ts +34 -5
  364. package/dist/components/features/global-search/global-search-dialog.d.ts +7 -1
  365. package/dist/components/features/global-search/global-search.d.ts +7 -1
  366. package/dist/components/features/global-search/global-search.strings.d.ts +19 -3
  367. package/dist/components/features/global-search/global-search.types.d.ts +30 -6
  368. package/dist/components/features/global-search/index.d.ts +1 -1
  369. package/dist/components/features/global-search/partials/global-search-idle-state.d.ts +6 -1
  370. package/dist/components/features/global-search/partials/global-search-input.d.ts +2 -0
  371. package/dist/components/features/kanban/index.d.ts +2 -2
  372. package/dist/components/features/kanban/kanban-context.d.ts +4 -0
  373. package/dist/components/features/kanban/kanban-keyboard.d.ts +7 -2
  374. package/dist/components/features/kanban/kanban.d.ts +10 -1
  375. package/dist/components/features/kanban/kanban.strings.d.ts +11 -2
  376. package/dist/components/features/kanban/kanban.types.d.ts +26 -0
  377. package/dist/components/features/map/map.d.ts +4 -0
  378. package/dist/components/features/map/place-autocomplete.d.ts +10 -1
  379. package/dist/components/features/media-library/hooks/use-media-library.d.ts +3 -1
  380. package/dist/components/features/media-library/media-library.d.ts +1 -1
  381. package/dist/components/features/media-library/media-library.strings.d.ts +39 -3
  382. package/dist/components/features/media-library/media-library.types.d.ts +82 -9
  383. package/dist/components/features/media-library/partials/media-library-partials.d.ts +3 -3
  384. package/dist/components/features/mentions/hooks/use-mentions-search.d.ts +7 -0
  385. package/dist/components/features/mentions/hooks/use-mentions.d.ts +16 -1
  386. package/dist/components/features/mentions/index.d.ts +1 -1
  387. package/dist/components/features/mentions/mentions.strings.d.ts +10 -2
  388. package/dist/components/features/mentions/partials/mention-chip.d.ts +1 -0
  389. package/dist/components/features/mentions/partials/mention-inline-suggestions.d.ts +12 -1
  390. package/dist/components/features/mentions/partials/mention-picker.d.ts +8 -1
  391. package/dist/components/features/mentions/partials/mention-search-error.d.ts +6 -0
  392. package/dist/components/features/mentions/utils/index.d.ts +0 -1
  393. package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
  394. package/dist/components/features/overlays/dialog.d.ts +1 -1
  395. package/dist/components/features/overlays/drawer.d.ts +1 -1
  396. package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +2 -2
  397. package/dist/components/features/overlays/index.d.ts +2 -2
  398. package/dist/components/features/overlays/overlays.strings.d.ts +2 -1
  399. package/dist/components/features/overlays/overlays.types.d.ts +27 -10
  400. package/dist/components/features/products/components/index.d.ts +0 -10
  401. package/dist/components/features/products/components/product-contract-overview.d.ts +1 -1
  402. package/dist/components/features/products/components/product-details-card.d.ts +1 -1
  403. package/dist/components/features/products/components/product-operations-card.d.ts +1 -1
  404. package/dist/components/features/products/components/product-option-action-menu.d.ts +1 -1
  405. package/dist/components/features/products/components/product-options-summary.d.ts +1 -1
  406. package/dist/components/features/products/components/product-policies-card.d.ts +1 -1
  407. package/dist/components/features/products/components/product-quote-preview-card.d.ts +1 -1
  408. package/dist/components/features/products/components/product-readiness-card.d.ts +1 -1
  409. package/dist/components/features/products/components/product-structure-card.d.ts +1 -1
  410. package/dist/components/features/products/components/product-variant-action-menu.d.ts +1 -1
  411. package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
  412. package/dist/components/features/products/components/product-variants-table.d.ts +1 -1
  413. package/dist/components/features/products/partials/product-surface.d.ts +15 -0
  414. package/dist/components/features/products/products.strings.d.ts +8 -0
  415. package/dist/components/features/products/products.types.d.ts +26 -8
  416. package/dist/components/features/questionnaire/questionnaire.types.d.ts +7 -2
  417. package/dist/components/features/resource/index.d.ts +2 -3
  418. package/dist/components/features/resource/resource.d.ts +2 -10
  419. package/dist/components/features/resource/resource.types.d.ts +7 -147
  420. package/dist/components/features/resource-assignment/partials/assignment-surface.d.ts +15 -0
  421. package/dist/components/features/resource-assignment/resource-assignment.strings.d.ts +6 -1
  422. package/dist/components/features/resource-assignment/resource-assignment.types.d.ts +6 -0
  423. package/dist/components/features/rich-text-editor/form-rich-text-editor.d.ts +1 -1
  424. package/dist/components/features/rich-text-editor/partials/caret-helpers.d.ts +5 -7
  425. package/dist/components/features/rich-text-editor/partials/editor-field-aria.d.ts +14 -0
  426. package/dist/components/features/rich-text-editor/partials/html-helpers.d.ts +2 -3
  427. package/dist/components/features/rich-text-editor/partials/image-uploads.d.ts +6 -2
  428. package/dist/components/features/rich-text-editor/partials/index.d.ts +2 -3
  429. package/dist/components/features/rich-text-editor/partials/rich-text-editor-tiptap.d.ts +0 -1
  430. package/dist/components/features/rich-text-editor/partials/rich-text-editor-toolbar.d.ts +5 -4
  431. package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +1 -1
  432. package/dist/components/features/rich-text-editor/rich-text-editor.types.d.ts +30 -4
  433. package/dist/components/features/schema-form/hooks/use-schema-form.d.ts +10 -1
  434. package/dist/components/features/schema-form/partials/schema-form-field.d.ts +3 -1
  435. package/dist/components/features/schema-form/schema-form.d.ts +1 -1
  436. package/dist/components/features/schema-form/schema-form.types.d.ts +13 -5
  437. package/dist/components/features/schema-form/schema-form.utils.d.ts +1 -1
  438. package/dist/components/features/suggestions/suggestions.strings.d.ts +14 -0
  439. package/dist/components/features/suggestions/suggestions.types.d.ts +13 -5
  440. package/dist/components/features/table/data-table.d.ts +1 -1
  441. package/dist/components/features/table/filter-bar.d.ts +1 -1
  442. package/dist/components/features/table/index.d.ts +1 -0
  443. package/dist/components/features/table/pagination.d.ts +1 -1
  444. package/dist/components/features/table/partials/cell-value.d.ts +1 -1
  445. package/dist/components/features/table/table-body.d.ts +1 -1
  446. package/dist/components/features/table/table-header.d.ts +1 -1
  447. package/dist/components/features/table/table-helpers.d.ts +37 -12
  448. package/dist/components/features/table/table-region.recipes.d.ts +11 -0
  449. package/dist/components/features/table/table-toolbar.d.ts +1 -1
  450. package/dist/components/features/table/table.strings.d.ts +4 -0
  451. package/dist/components/features/table/table.types.d.ts +91 -49
  452. package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +4 -0
  453. package/dist/components/features/theme-tweaker/theme-tweaker.strings.d.ts +10 -7
  454. package/dist/components/features/theme-tweaker/theme-tweaker.utils.d.ts +17 -0
  455. package/dist/components/layout/app-shell/app-shell.types.d.ts +46 -49
  456. package/dist/components/layout/app-shell/index.d.ts +2 -2
  457. package/dist/components/layout/app-shell/shell-regions.d.ts +9 -0
  458. package/dist/components/layout/app-shell/shell-skip-link.d.ts +9 -0
  459. package/dist/components/layout/app-shell/sidebar-inset-layout.d.ts +1 -1
  460. package/dist/components/layout/app-shell/stacked-layout.d.ts +1 -1
  461. package/dist/components/layout/app-shell/topbar-sidebar-layout.d.ts +1 -1
  462. package/dist/components/layout/auth/auth-shell.d.ts +1 -1
  463. package/dist/components/layout/auth/auth.types.d.ts +0 -5
  464. package/dist/components/layout/containers/inline-gutter-context.d.ts +7 -0
  465. package/dist/components/layout/containers/main-landmark-context.d.ts +6 -0
  466. package/dist/components/layout/header/header.types.d.ts +19 -8
  467. package/dist/components/layout/header/partials/header-global-search-trigger.d.ts +1 -1
  468. package/dist/components/layout/header/partials/header-notifications.d.ts +1 -1
  469. package/dist/components/layout/header/partials/header-search.d.ts +1 -1
  470. package/dist/components/layout/hooks/use-command-shortcut.d.ts +10 -1
  471. package/dist/components/layout/layout.types.d.ts +6 -4
  472. package/dist/components/layout/navigation/breadcrumb-progress/breadcrumb-progress.d.ts +1 -1
  473. package/dist/components/layout/navigation/breadcrumb-progress/types.d.ts +9 -0
  474. package/dist/components/layout/navigation/section-nav/section-nav.d.ts +8 -1
  475. package/dist/components/layout/navigation/side-nav.d.ts +3 -2
  476. package/dist/components/layout/normalize-layout-path.d.ts +1 -0
  477. package/dist/components/layout/page/index.d.ts +2 -3
  478. package/dist/components/layout/page/page.strings.d.ts +12 -0
  479. package/dist/components/layout/page/page.types.d.ts +7 -110
  480. package/dist/components/layout/page/partials/page-header.d.ts +1 -1
  481. package/dist/components/layout/settings/index.d.ts +1 -1
  482. package/dist/components/layout/settings/settings.d.ts +4 -6
  483. package/dist/components/layout/sidebar/app-sidebar.d.ts +1 -1
  484. package/dist/components/layout/sidebar/components/sidebar-grouped-navigation.d.ts +1 -1
  485. package/dist/components/layout/sidebar/components/sidebar-navigation-footer.d.ts +1 -1
  486. package/dist/components/layout/sidebar/components/sidebar-navigation.d.ts +1 -1
  487. package/dist/components/layout/sidebar/index.d.ts +1 -1
  488. package/dist/components/layout/sidebar/sidebar-navigation-rail.d.ts +17 -7
  489. package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -0
  490. package/dist/components/layout/sidebar/sidebar.types.d.ts +12 -12
  491. package/dist/components/layout/sidebar/sidebar.utils.d.ts +4 -0
  492. package/dist/components/layout/workspace/workspace.strings.d.ts +2 -2
  493. package/dist/components/layout/workspace/workspace.types.d.ts +13 -7
  494. package/dist/components/primitives/date.d.ts +22 -3
  495. package/dist/components/primitives/file-size.d.ts +8 -2
  496. package/dist/components/primitives/index.d.ts +1 -1
  497. package/dist/components/primitives/initials.d.ts +3 -1
  498. package/dist/components/primitives/link.d.ts +11 -3
  499. package/dist/components/primitives/money.d.ts +2 -2
  500. package/dist/components/primitives/number.d.ts +3 -2
  501. package/dist/components/typography/heading.d.ts +9 -3
  502. package/dist/components/typography/index.d.ts +1 -1
  503. package/dist/components/typography/rich-text/rich-text-tree.d.ts +7 -5
  504. package/dist/components/typography/text-link.d.ts +10 -3
  505. package/dist/components/ui/badge.d.ts +2 -4
  506. package/dist/components/ui/breadcrumb.d.ts +2 -3
  507. package/dist/components/ui/button.d.ts +8 -2
  508. package/dist/components/ui/collapsible.d.ts +1 -4
  509. package/dist/components/ui/command.d.ts +20 -18
  510. package/dist/components/ui/dialog.d.ts +3 -9
  511. package/dist/components/ui/empty.d.ts +2 -2
  512. package/dist/components/ui/input-group.d.ts +3 -3
  513. package/dist/components/ui/item.d.ts +3 -3
  514. package/dist/components/ui/popover.d.ts +3 -7
  515. package/dist/components/ui/sheet.d.ts +4 -12
  516. package/dist/components/ui/sidebar-state.d.ts +6 -1
  517. package/dist/components/ui/sidebar.d.ts +7 -4
  518. package/dist/components/ui/tabs.d.ts +2 -2
  519. package/dist/components/ui/toggle-group.d.ts +3 -3
  520. package/dist/components/ui/toggle.d.ts +2 -2
  521. package/dist/components/ui/tooltip.d.ts +1 -3
  522. package/dist/{containers-CIxwbZt5.js → containers-BdfLTP4w.js} +37 -32
  523. package/dist/containers-BdfLTP4w.js.map +1 -0
  524. package/dist/content-block-hooks-Z3iKjqd1.js +17 -0
  525. package/dist/content-block-hooks-Z3iKjqd1.js.map +1 -0
  526. package/dist/{copyable-DIznBqiT.js → copyable-Bmr14W0d.js} +6 -6
  527. package/dist/{copyable-DIznBqiT.js.map → copyable-Bmr14W0d.js.map} +1 -1
  528. package/dist/{data-display-BdgCAw8T.js → data-display-CWe9SOYh.js} +264 -250
  529. package/dist/data-display-CWe9SOYh.js.map +1 -0
  530. package/dist/date-3qsCE1ID.js +209 -0
  531. package/dist/date-3qsCE1ID.js.map +1 -0
  532. package/dist/date-picker-D1keJQIG.js +1617 -0
  533. package/dist/date-picker-D1keJQIG.js.map +1 -0
  534. package/dist/date-pickers-D8aJoeHc.js +185 -0
  535. package/dist/date-pickers-D8aJoeHc.js.map +1 -0
  536. package/dist/disclosure-panel-B0HFNZ9x.js.map +1 -1
  537. package/dist/{display-KsZLw9Ov.js → display-VlmP1I0i.js} +23 -46
  538. package/dist/display-VlmP1I0i.js.map +1 -0
  539. package/dist/{dropdown-menu-CLs8Lihj.js → dropdown-menu-B8hjvbkS.js} +9 -9
  540. package/dist/{dropdown-menu-CLs8Lihj.js.map → dropdown-menu-B8hjvbkS.js.map} +1 -1
  541. package/dist/dropzone-CHBNK3de.js +116 -0
  542. package/dist/dropzone-CHBNK3de.js.map +1 -0
  543. package/dist/features/activities.js +767 -700
  544. package/dist/features/activities.js.map +1 -1
  545. package/dist/features/ai-chat.js +280 -235
  546. package/dist/features/ai-chat.js.map +1 -1
  547. package/dist/features/appointment-calendar.js +430 -334
  548. package/dist/features/appointment-calendar.js.map +1 -1
  549. package/dist/features/async-preview.js +351 -265
  550. package/dist/features/async-preview.js.map +1 -1
  551. package/dist/features/combobox.js +2 -2
  552. package/dist/features/comments.js +1 -1
  553. package/dist/features/data-view.js +212 -151
  554. package/dist/features/data-view.js.map +1 -1
  555. package/dist/features/email-composer/engine.js +1 -1
  556. package/dist/features/email-composer.js +347 -313
  557. package/dist/features/email-composer.js.map +1 -1
  558. package/dist/features/event-calendar.js +501 -348
  559. package/dist/features/event-calendar.js.map +1 -1
  560. package/dist/features/filters.js +2 -2
  561. package/dist/features/global-search.js +250 -210
  562. package/dist/features/global-search.js.map +1 -1
  563. package/dist/features/kanban.js +280 -210
  564. package/dist/features/kanban.js.map +1 -1
  565. package/dist/features/map/style.css +15 -0
  566. package/dist/features/map.js +435 -404
  567. package/dist/features/map.js.map +1 -1
  568. package/dist/features/media-library.js +1745 -1195
  569. package/dist/features/media-library.js.map +1 -1
  570. package/dist/features/mentions.js +2 -2
  571. package/dist/features/overlays.js +2 -2
  572. package/dist/features/products.js +1862 -1759
  573. package/dist/features/products.js.map +1 -1
  574. package/dist/features/questionnaire.js +188 -168
  575. package/dist/features/questionnaire.js.map +1 -1
  576. package/dist/features/resource-assignment.js +223 -191
  577. package/dist/features/resource-assignment.js.map +1 -1
  578. package/dist/features/resource.js +55 -217
  579. package/dist/features/resource.js.map +1 -1
  580. package/dist/features/rich-text-editor.js +28 -19
  581. package/dist/features/rich-text-editor.js.map +1 -1
  582. package/dist/features/schema-form.js +380 -287
  583. package/dist/features/schema-form.js.map +1 -1
  584. package/dist/features/suggestions.js +90 -74
  585. package/dist/features/suggestions.js.map +1 -1
  586. package/dist/features/table.js +2 -2
  587. package/dist/features/theme-tweaker.js +718 -627
  588. package/dist/features/theme-tweaker.js.map +1 -1
  589. package/dist/feedback-DmqmXKLn.js +254 -0
  590. package/dist/feedback-DmqmXKLn.js.map +1 -0
  591. package/dist/{field-affordance-recipes-DWcNcOjh.js → field-affordance-recipes-DfbMadot.js} +13 -9
  592. package/dist/field-affordance-recipes-DfbMadot.js.map +1 -0
  593. package/dist/field-control-attributes-B6i335wr.js +18 -0
  594. package/dist/field-control-attributes-B6i335wr.js.map +1 -0
  595. package/dist/field-state-recipes-EtCxpEy3.js +18 -0
  596. package/dist/field-state-recipes-EtCxpEy3.js.map +1 -0
  597. package/dist/filters-BviMRMLS.js +2692 -0
  598. package/dist/filters-BviMRMLS.js.map +1 -0
  599. package/dist/{focus-recipes-B653VaLq.js → focus-recipes-DSkiUvUp.js} +3 -3
  600. package/dist/focus-recipes-DSkiUvUp.js.map +1 -0
  601. package/dist/form-field-BdfCwSoQ.js +74 -0
  602. package/dist/form-field-BdfCwSoQ.js.map +1 -0
  603. package/dist/{form-sizing-Bs2qFUeE.js → form-sizing-DE_dZw32.js} +3 -3
  604. package/dist/{form-sizing-Bs2qFUeE.js.map → form-sizing-DE_dZw32.js.map} +1 -1
  605. package/dist/{forms-C0RGnJTe.js → forms-B8DzJnBN.js} +35 -35
  606. package/dist/forms-B8DzJnBN.js.map +1 -0
  607. package/dist/forms-numeric-DOBswjKj.js +992 -0
  608. package/dist/forms-numeric-DOBswjKj.js.map +1 -0
  609. package/dist/{header-DMMxG__r.js → header-Cq3G0ZRP.js} +163 -158
  610. package/dist/header-Cq3G0ZRP.js.map +1 -0
  611. package/dist/hooks/use-files.d.ts +2 -0
  612. package/dist/{hooks-DB6CJ4MR.js → hooks-DHfeSMAO.js} +34 -14
  613. package/dist/hooks-DHfeSMAO.js.map +1 -0
  614. package/dist/{http-D_6rOnzU.js → http-Cu-GPpss.js} +61 -35
  615. package/dist/http-Cu-GPpss.js.map +1 -0
  616. package/dist/{icon-badge-DZF-YjQp.js → icon-badge-B0Kq7wom.js} +3 -3
  617. package/dist/{icon-badge-DZF-YjQp.js.map → icon-badge-B0Kq7wom.js.map} +1 -1
  618. package/dist/index.js +6 -6
  619. package/dist/inline-gutter-context-CSqmrMFZ.js +11 -0
  620. package/dist/inline-gutter-context-CSqmrMFZ.js.map +1 -0
  621. package/dist/{input-DMBwAZmr.js → input-2YrgTUrz.js} +3 -3
  622. package/dist/{input-DMBwAZmr.js.map → input-2YrgTUrz.js.map} +1 -1
  623. package/dist/{input-CvyDQlY7.js → input-DfJyrjoR.js} +7 -7
  624. package/dist/{input-CvyDQlY7.js.map → input-DfJyrjoR.js.map} +1 -1
  625. package/dist/{interaction-recipes-XR9ZpVYL.js → interaction-recipes-DmuS1ase.js} +2 -2
  626. package/dist/{interaction-recipes-XR9ZpVYL.js.map → interaction-recipes-DmuS1ase.js.map} +1 -1
  627. package/dist/item-GJ9mvCcg.js +279 -0
  628. package/dist/item-GJ9mvCcg.js.map +1 -0
  629. package/dist/layout/app-shell.js +1 -1
  630. package/dist/layout/auth.js +1 -1
  631. package/dist/layout/containers.js +1 -1
  632. package/dist/layout/header.js +1 -1
  633. package/dist/layout/hooks.js +1 -1
  634. package/dist/layout/navigation.js +1 -1
  635. package/dist/layout/page.js +2 -2
  636. package/dist/layout/settings.js +2 -2
  637. package/dist/layout/sidebar.js +3 -3
  638. package/dist/layout/workspace.js +1 -1
  639. package/dist/layout.js +12 -12
  640. package/dist/layout.types-DbtnyAtd.js +33 -0
  641. package/dist/layout.types-DbtnyAtd.js.map +1 -0
  642. package/dist/lib/anchored-positioning.d.ts +11 -0
  643. package/dist/lib/field-affordance-recipes.d.ts +10 -0
  644. package/dist/lib/field-control-attributes.d.ts +11 -0
  645. package/dist/lib/field-state-recipes.d.ts +8 -0
  646. package/dist/lib/focus-recipes.d.ts +7 -0
  647. package/dist/lib/format.d.ts +26 -0
  648. package/dist/lib/money-format.d.ts +6 -0
  649. package/dist/lib/motion-recipes.d.ts +6 -0
  650. package/dist/lib/surface-recipes.d.ts +33 -3
  651. package/dist/lib/theme-scope.d.ts +17 -1
  652. package/dist/lib/token-merge.generated.d.ts +19 -25
  653. package/dist/lib/ui-provider/index.d.ts +1 -1
  654. package/dist/lib/ui-provider/types.d.ts +5 -0
  655. package/dist/lib/use-controllable-state.d.ts +16 -0
  656. package/dist/lib/use-copy-feedback.d.ts +15 -0
  657. package/dist/lib/utils.js +1 -1
  658. package/dist/lib/variant-props.d.ts +9 -0
  659. package/dist/main-landmark-context-BAsyqp2I.js +11 -0
  660. package/dist/main-landmark-context-BAsyqp2I.js.map +1 -0
  661. package/dist/mentions-zz0ewNIq.js +670 -0
  662. package/dist/mentions-zz0ewNIq.js.map +1 -0
  663. package/dist/message-BiiVrRrm.js +138 -0
  664. package/dist/message-BiiVrRrm.js.map +1 -0
  665. package/dist/{metadata-list-C3MkU-Om.js → metadata-list-G85roWjS.js} +13 -12
  666. package/dist/metadata-list-G85roWjS.js.map +1 -0
  667. package/dist/{motion-recipes-DitYv6P2.js → motion-recipes-CUc_aHuG.js} +7 -4
  668. package/dist/motion-recipes-CUc_aHuG.js.map +1 -0
  669. package/dist/navigation-C0Be5C3i.js +304 -0
  670. package/dist/navigation-C0Be5C3i.js.map +1 -0
  671. package/dist/navigation-CmqaQR_G.js +257 -0
  672. package/dist/navigation-CmqaQR_G.js.map +1 -0
  673. package/dist/normalize-layout-path-BmEgg6fu.js +14 -0
  674. package/dist/normalize-layout-path-BmEgg6fu.js.map +1 -0
  675. package/dist/number-NFWKIoiK.js +340 -0
  676. package/dist/number-NFWKIoiK.js.map +1 -0
  677. package/dist/{overflow-tab-bar-IVFVQFV6.js → overflow-tab-bar-DV7HE_3t.js} +8 -8
  678. package/dist/{overflow-tab-bar-IVFVQFV6.js.map → overflow-tab-bar-DV7HE_3t.js.map} +1 -1
  679. package/dist/{overlays-BSgCtM2v.js → overlays-D-gAIfPF.js} +369 -364
  680. package/dist/overlays-D-gAIfPF.js.map +1 -0
  681. package/dist/page-D4pQhgSq.js +216 -0
  682. package/dist/page-D4pQhgSq.js.map +1 -0
  683. package/dist/{page-header-commands-7P3sfE9u.js → page-header-commands-elelNOfd.js} +29 -29
  684. package/dist/{page-header-commands-7P3sfE9u.js.map → page-header-commands-elelNOfd.js.map} +1 -1
  685. package/dist/{pagination-CgCjElfu.js → pagination-BuSWw1US.js} +22 -23
  686. package/dist/pagination-BuSWw1US.js.map +1 -0
  687. package/dist/popover-BpMxbqEK.js +205 -0
  688. package/dist/popover-BpMxbqEK.js.map +1 -0
  689. package/dist/{popover-menu-DlnQ2zlR.js → popover-menu-CO-_iiuz.js} +7 -7
  690. package/dist/{popover-menu-DlnQ2zlR.js.map → popover-menu-CO-_iiuz.js.map} +1 -1
  691. package/dist/{popover.recipes-DdiEp0rd.js → popover.recipes-BqkdvlZn.js} +3 -4
  692. package/dist/{popover.recipes-DdiEp0rd.js.map → popover.recipes-BqkdvlZn.js.map} +1 -1
  693. package/dist/{portal-recipes-BpsV_iRw.js → portal-recipes-BPeS4rGB.js} +2 -2
  694. package/dist/{portal-recipes-BpsV_iRw.js.map → portal-recipes-BPeS4rGB.js.map} +1 -1
  695. package/dist/primitives-BlC1lXBr.js +447 -0
  696. package/dist/primitives-BlC1lXBr.js.map +1 -0
  697. package/dist/primitives.js +4 -4
  698. package/dist/{progress-BJhQP9WX.js → progress-RARK8AjB.js} +5 -5
  699. package/dist/{progress-BJhQP9WX.js.map → progress-RARK8AjB.js.map} +1 -1
  700. package/dist/receipt-CUf2Vegp.js +114 -0
  701. package/dist/receipt-CUf2Vegp.js.map +1 -0
  702. package/dist/rich-text-Cypm9__d.js +44 -0
  703. package/dist/rich-text-Cypm9__d.js.map +1 -0
  704. package/dist/rich-text-editor-Z6cQepsA.js +919 -0
  705. package/dist/rich-text-editor-Z6cQepsA.js.map +1 -0
  706. package/dist/rich-text-editor-toolbar-DYbRJARB.js +100 -0
  707. package/dist/rich-text-editor-toolbar-DYbRJARB.js.map +1 -0
  708. package/dist/rich-text-tree-DdKHIJx4.js +154 -0
  709. package/dist/rich-text-tree-DdKHIJx4.js.map +1 -0
  710. package/dist/{scroll-area-B0dB2cBi.js → scroll-area-B9HKbji0.js} +3 -3
  711. package/dist/{scroll-area-B0dB2cBi.js.map → scroll-area-B9HKbji0.js.map} +1 -1
  712. package/dist/{separator-Ct_WSWTJ.js → separator-DaDe26sf.js} +3 -3
  713. package/dist/separator-DaDe26sf.js.map +1 -0
  714. package/dist/{separator-Bb17I4pu.js → separator-KGsNXt2J.js} +2 -2
  715. package/dist/{separator-Bb17I4pu.js.map → separator-KGsNXt2J.js.map} +1 -1
  716. package/dist/services/actions/action-adapters.d.ts +5 -2
  717. package/dist/services/actions/index.d.ts +1 -1
  718. package/dist/services/actions.js +2 -2
  719. package/dist/services/actions.js.map +1 -1
  720. package/dist/settings-D5j_RJvT.js +160 -0
  721. package/dist/settings-D5j_RJvT.js.map +1 -0
  722. package/dist/sheet-B6j_BE9O.js +241 -0
  723. package/dist/sheet-B6j_BE9O.js.map +1 -0
  724. package/dist/{sidebar-f9gRWXIR.js → sidebar-C-iQ_TJP.js} +379 -350
  725. package/dist/sidebar-C-iQ_TJP.js.map +1 -0
  726. package/dist/sidebar-D5VO2W8S.js +715 -0
  727. package/dist/sidebar-D5VO2W8S.js.map +1 -0
  728. package/dist/{skeleton-BapcJd9C.js → skeleton-Cab_KgVo.js} +13 -13
  729. package/dist/skeleton-Cab_KgVo.js.map +1 -0
  730. package/dist/{smart-card-CW0hjetE.js → smart-card-C59z6KFO.js} +217 -210
  731. package/dist/smart-card-C59z6KFO.js.map +1 -0
  732. package/dist/{structure-DuxKl954.js → structure-DElaQwwN.js} +2 -2
  733. package/dist/{structure-DuxKl954.js.map → structure-DElaQwwN.js.map} +1 -1
  734. package/dist/style.css +1 -1
  735. package/dist/{surface-recipes-BKRVW8Os.js → surface-recipes-DV6rrOFq.js} +11 -3
  736. package/dist/surface-recipes-DV6rrOFq.js.map +1 -0
  737. package/dist/table-CSRUgpdK.js +180 -0
  738. package/dist/table-CSRUgpdK.js.map +1 -0
  739. package/dist/table-DdXDBsR_.js +1657 -0
  740. package/dist/table-DdXDBsR_.js.map +1 -0
  741. package/dist/tabs-WnHfV2pM.js +192 -0
  742. package/dist/tabs-WnHfV2pM.js.map +1 -0
  743. package/dist/{text-inputs-B1culiSK.js → text-inputs-ljyBYaCd.js} +112 -112
  744. package/dist/text-inputs-ljyBYaCd.js.map +1 -0
  745. package/dist/theme.css +21 -5
  746. package/dist/timelines-mOmS9Eh3.js +479 -0
  747. package/dist/timelines-mOmS9Eh3.js.map +1 -0
  748. package/dist/tooltip-yjX-Uv-p.js +112 -0
  749. package/dist/tooltip-yjX-Uv-p.js.map +1 -0
  750. package/dist/{tree-CzUJHnFs.js → tree-YpkxUG2Z.js} +80 -72
  751. package/dist/tree-YpkxUG2Z.js.map +1 -0
  752. package/dist/typography/rich-text.js +1 -1
  753. package/dist/{typography-BQnine1k.js → typography-C0dELqYV.js} +46 -40
  754. package/dist/typography-C0dELqYV.js.map +1 -0
  755. package/dist/typography.js +1 -1
  756. package/dist/{ui-provider-C-74NVLc.js → ui-provider-Bu1S-o96.js} +4 -3
  757. package/dist/ui-provider-Bu1S-o96.js.map +1 -0
  758. package/dist/ui-provider.js +2 -2
  759. package/dist/upload-DMuMYJFT.js +875 -0
  760. package/dist/upload-DMuMYJFT.js.map +1 -0
  761. package/dist/{usage-card-BeSLY0i0.js → usage-card-DDPki5P1.js} +57 -54
  762. package/dist/usage-card-DDPki5P1.js.map +1 -0
  763. package/dist/use-controllable-state-BlP8SyBI.js +13 -0
  764. package/dist/use-controllable-state-BlP8SyBI.js.map +1 -0
  765. package/dist/use-copy-feedback-CzcaqlLf.js +28 -0
  766. package/dist/use-copy-feedback-CzcaqlLf.js.map +1 -0
  767. package/dist/use-metric-format-options-Dk4rC1NO.js +251 -0
  768. package/dist/use-metric-format-options-Dk4rC1NO.js.map +1 -0
  769. package/dist/{utils-B6kKb8jB.js → utils-BVbAG2J6.js} +128 -112
  770. package/dist/utils-BVbAG2J6.js.map +1 -0
  771. package/dist/value-inputs-h5MwjGCo.js +982 -0
  772. package/dist/value-inputs-h5MwjGCo.js.map +1 -0
  773. package/dist/value-typography-D15uwfj-.js +154 -0
  774. package/dist/value-typography-D15uwfj-.js.map +1 -0
  775. package/dist/workspace-DIryPqBt.js +400 -0
  776. package/dist/workspace-DIryPqBt.js.map +1 -0
  777. package/docs/consumer-skill/SKILL.md +7 -0
  778. package/docs/consumer-skill/agents/themelia-ui-designer.md +11 -2
  779. package/docs/consumer-skill/examples/analytics.tsx +1 -1
  780. package/docs/consumer-skill/examples/app-layout.tsx +3 -3
  781. package/docs/consumer-skill/examples/commerce-lines.tsx +7 -5
  782. package/docs/consumer-skill/examples/detail.tsx +3 -2
  783. package/docs/consumer-skill/examples/edit.tsx +3 -3
  784. package/docs/consumer-skill/examples/email-composer.tsx +1 -1
  785. package/docs/consumer-skill/examples/index-table.tsx +2 -2
  786. package/docs/consumer-skill/examples/scoped-directory.tsx +7 -6
  787. package/docs/consumer-skill/references/agents-md.md +27 -23
  788. package/docs/consumer-skill/references/analytics.md +33 -4
  789. package/docs/consumer-skill/references/building-views.md +213 -0
  790. package/docs/consumer-skill/references/catalogue.md +617 -0
  791. package/docs/consumer-skill/references/component-contracts.json +25852 -32067
  792. package/docs/consumer-skill/references/composition.md +42 -21
  793. package/docs/consumer-skill/references/design-contract.md +1 -0
  794. package/docs/consumer-skill/references/discovery.md +8 -5
  795. package/docs/consumer-skill/references/installation.md +59 -10
  796. package/docs/consumer-skill/references/integration.md +28 -5
  797. package/docs/consumer-skill/references/product-composition.md +2 -2
  798. package/docs/consumer-skill/references/public-api.json +726 -641
  799. package/docs/consumer-skill/references/review.md +57 -15
  800. package/docs/consumer-skill/references/rhf-workflows.md +72 -0
  801. package/docs/consumer-skill/references/screen-archetypes.md +2 -2
  802. package/docs/consumer-skill/references/theming.md +8 -3
  803. package/docs/consumer-skill/references/tokens.json +4 -4
  804. package/docs/consumer-skill/references/workflows.md +7 -7
  805. package/docs/consumer-skill/scripts/composition-policy.mjs +178 -44
  806. package/docs/consumer-skill/scripts/composition.mjs +4 -1
  807. package/docs/consumer-skill/scripts/discovery.mjs +3 -1
  808. package/docs/consumer-skill/scripts/setup-skills.mjs +74 -10
  809. package/docs/consumer-skills/themelia-components/SKILL.md +8 -4
  810. package/docs/consumer-skills/themelia-composition/SKILL.md +7 -3
  811. package/docs/consumer-skills/themelia-design/SKILL.md +7 -1
  812. package/docs/consumer-skills/themelia-tokenization/SKILL.md +1 -1
  813. package/package.json +12 -13
  814. package/templates/README.md +3 -2
  815. package/templates/admin-shell-template.tsx +50 -11
  816. package/templates/analytics-operations-template.tsx +20 -24
  817. package/templates/customers-template.tsx +30 -25
  818. package/templates/index.ts +2 -8
  819. package/templates/orders-template.tsx +28 -24
  820. package/templates/products-template.tsx +14 -4
  821. package/templates/user-permissions-template.tsx +11 -14
  822. package/dist/accordion-B9MHG0cT.js.map +0 -1
  823. package/dist/action-menu-Dr8K-ghE.js +0 -284
  824. package/dist/action-menu-Dr8K-ghE.js.map +0 -1
  825. package/dist/ai-artifact-C58tQcBy.js +0 -1185
  826. package/dist/ai-artifact-C58tQcBy.js.map +0 -1
  827. package/dist/anchored-positioning-DPnKTvNs.js +0 -6
  828. package/dist/anchored-positioning-DPnKTvNs.js.map +0 -1
  829. package/dist/app-shell-B_IuNWOo.js +0 -321
  830. package/dist/app-shell-B_IuNWOo.js.map +0 -1
  831. package/dist/auth-DTkkshS8.js.map +0 -1
  832. package/dist/badge-xIiV_E7f.js.map +0 -1
  833. package/dist/base/sheet.js +0 -3
  834. package/dist/breadcrumbs-J-K2kl4c.js +0 -129
  835. package/dist/breadcrumbs-J-K2kl4c.js.map +0 -1
  836. package/dist/button-S2Cubiiz.js.map +0 -1
  837. package/dist/buttons-BedGfygC.js.map +0 -1
  838. package/dist/cascader-B1MiqkBq.js +0 -439
  839. package/dist/cascader-B1MiqkBq.js.map +0 -1
  840. package/dist/choice-inputs-zUgBZfE4.js.map +0 -1
  841. package/dist/code-block-BzmM9Eig.js.map +0 -1
  842. package/dist/collapsible-BkAI_XD4.js +0 -81
  843. package/dist/collapsible-BkAI_XD4.js.map +0 -1
  844. package/dist/combobox-BEx0vJgF.js +0 -362
  845. package/dist/combobox-BEx0vJgF.js.map +0 -1
  846. package/dist/combobox-BwzoXFSG.js +0 -884
  847. package/dist/combobox-BwzoXFSG.js.map +0 -1
  848. package/dist/command-CrlPIL6m.js +0 -425
  849. package/dist/command-CrlPIL6m.js.map +0 -1
  850. package/dist/comments-Dmpp0YIc.js +0 -1169
  851. package/dist/comments-Dmpp0YIc.js.map +0 -1
  852. package/dist/components/base/buttons/tooltip-button.d.ts +0 -7
  853. package/dist/components/base/display/content-block.d.ts +0 -75
  854. package/dist/components/base/display/content-block.strings.d.ts +0 -5
  855. package/dist/components/base/sheet/index.d.ts +0 -29
  856. package/dist/components/blocks/ai/use-copy-feedback.d.ts +0 -6
  857. package/dist/components/blocks/data-display/metadata/index.d.ts +0 -30
  858. package/dist/components/features/mentions/utils/split-html-by-mentions.d.ts +0 -16
  859. package/dist/components/features/resource/resource.strings.d.ts +0 -12
  860. package/dist/components/features/rich-text-editor/partials/rich-text-editor-fallback.d.ts +0 -8
  861. package/dist/components/features/sync/index.d.ts +0 -26
  862. package/dist/components/features/sync/sync-range-dialog-form.d.ts +0 -5
  863. package/dist/components/features/sync/sync.strings.d.ts +0 -18
  864. package/dist/components/features/sync/sync.types.d.ts +0 -44
  865. package/dist/components/layout/page/partials/page-actions.d.ts +0 -3
  866. package/dist/components/ui/slot.d.ts +0 -6
  867. package/dist/containers-CIxwbZt5.js.map +0 -1
  868. package/dist/data-display-BdgCAw8T.js.map +0 -1
  869. package/dist/date-Cq8ioE4o.js +0 -144
  870. package/dist/date-Cq8ioE4o.js.map +0 -1
  871. package/dist/date-picker-RlIzKom_.js +0 -1551
  872. package/dist/date-picker-RlIzKom_.js.map +0 -1
  873. package/dist/date-pickers-DY-CpXS1.js +0 -179
  874. package/dist/date-pickers-DY-CpXS1.js.map +0 -1
  875. package/dist/display-KsZLw9Ov.js.map +0 -1
  876. package/dist/features/sync.js +0 -142
  877. package/dist/features/sync.js.map +0 -1
  878. package/dist/feedback-Dm4izqFn.js +0 -240
  879. package/dist/feedback-Dm4izqFn.js.map +0 -1
  880. package/dist/field-affordance-recipes-DWcNcOjh.js.map +0 -1
  881. package/dist/field-state-recipes-BVA2CWHo.js +0 -12
  882. package/dist/field-state-recipes-BVA2CWHo.js.map +0 -1
  883. package/dist/filters-DzgSJpMK.js +0 -2257
  884. package/dist/filters-DzgSJpMK.js.map +0 -1
  885. package/dist/focus-recipes-B653VaLq.js.map +0 -1
  886. package/dist/form-field-BriWAXyg.js +0 -63
  887. package/dist/form-field-BriWAXyg.js.map +0 -1
  888. package/dist/forms-C0RGnJTe.js.map +0 -1
  889. package/dist/forms-numeric-DIhghX1Q.js +0 -910
  890. package/dist/forms-numeric-DIhghX1Q.js.map +0 -1
  891. package/dist/header-DMMxG__r.js.map +0 -1
  892. package/dist/hooks-DB6CJ4MR.js.map +0 -1
  893. package/dist/http-D_6rOnzU.js.map +0 -1
  894. package/dist/item-DjCcM18E.js +0 -277
  895. package/dist/item-DjCcM18E.js.map +0 -1
  896. package/dist/layout.types-Cn7aUzJp.js +0 -20
  897. package/dist/layout.types-Cn7aUzJp.js.map +0 -1
  898. package/dist/media-gallery-C-vChPmE.js +0 -203
  899. package/dist/media-gallery-C-vChPmE.js.map +0 -1
  900. package/dist/mentions-0_4nWuI-.js +0 -570
  901. package/dist/mentions-0_4nWuI-.js.map +0 -1
  902. package/dist/message-g8p7eVtN.js +0 -128
  903. package/dist/message-g8p7eVtN.js.map +0 -1
  904. package/dist/metadata-list-C3MkU-Om.js.map +0 -1
  905. package/dist/motion-recipes-DitYv6P2.js.map +0 -1
  906. package/dist/navigation-C90-oQFq.js +0 -255
  907. package/dist/navigation-C90-oQFq.js.map +0 -1
  908. package/dist/navigation-DaRjthVk.js +0 -288
  909. package/dist/navigation-DaRjthVk.js.map +0 -1
  910. package/dist/number-CRU3kGuk.js +0 -354
  911. package/dist/number-CRU3kGuk.js.map +0 -1
  912. package/dist/overlays-BSgCtM2v.js.map +0 -1
  913. package/dist/page-DUUKDAjo.js +0 -331
  914. package/dist/page-DUUKDAjo.js.map +0 -1
  915. package/dist/pagination-CgCjElfu.js.map +0 -1
  916. package/dist/popover-B85RenIl.js +0 -201
  917. package/dist/popover-B85RenIl.js.map +0 -1
  918. package/dist/primitives-ByWgGUgt.js +0 -380
  919. package/dist/primitives-ByWgGUgt.js.map +0 -1
  920. package/dist/receipt-tOc7B3hw.js +0 -116
  921. package/dist/receipt-tOc7B3hw.js.map +0 -1
  922. package/dist/rich-text-Dth5E882.js +0 -78
  923. package/dist/rich-text-Dth5E882.js.map +0 -1
  924. package/dist/rich-text-editor-C1fOjBTd.js +0 -1195
  925. package/dist/rich-text-editor-C1fOjBTd.js.map +0 -1
  926. package/dist/rich-text-editor-toolbar-laT3tpBT.js +0 -98
  927. package/dist/rich-text-editor-toolbar-laT3tpBT.js.map +0 -1
  928. package/dist/sanitize-html-DsQmI48u.js +0 -92
  929. package/dist/sanitize-html-DsQmI48u.js.map +0 -1
  930. package/dist/separator-Ct_WSWTJ.js.map +0 -1
  931. package/dist/settings-Bar5wiSo.js +0 -167
  932. package/dist/settings-Bar5wiSo.js.map +0 -1
  933. package/dist/sheet-BGPERY55.js +0 -250
  934. package/dist/sheet-BGPERY55.js.map +0 -1
  935. package/dist/sidebar-D-JYMMbY.js +0 -686
  936. package/dist/sidebar-D-JYMMbY.js.map +0 -1
  937. package/dist/sidebar-f9gRWXIR.js.map +0 -1
  938. package/dist/skeleton-BapcJd9C.js.map +0 -1
  939. package/dist/slot-CLF9kLrS.js +0 -16
  940. package/dist/slot-CLF9kLrS.js.map +0 -1
  941. package/dist/smart-card-CW0hjetE.js.map +0 -1
  942. package/dist/surface-recipes-BKRVW8Os.js.map +0 -1
  943. package/dist/table-B4TE7iOV.js +0 -175
  944. package/dist/table-B4TE7iOV.js.map +0 -1
  945. package/dist/table-CFOWY9pQ.js +0 -1536
  946. package/dist/table-CFOWY9pQ.js.map +0 -1
  947. package/dist/tabs-e7ko9S2o.js +0 -191
  948. package/dist/tabs-e7ko9S2o.js.map +0 -1
  949. package/dist/text-inputs-B1culiSK.js.map +0 -1
  950. package/dist/timelines-D3Sl9ueq.js +0 -458
  951. package/dist/timelines-D3Sl9ueq.js.map +0 -1
  952. package/dist/tooltip-8wz5S_Zr.js +0 -113
  953. package/dist/tooltip-8wz5S_Zr.js.map +0 -1
  954. package/dist/tree-CzUJHnFs.js.map +0 -1
  955. package/dist/typography-BQnine1k.js.map +0 -1
  956. package/dist/ui-provider-C-74NVLc.js.map +0 -1
  957. package/dist/upload-BOW6U2tI.js +0 -855
  958. package/dist/upload-BOW6U2tI.js.map +0 -1
  959. package/dist/upload-queue-qUXn1ykN.js +0 -409
  960. package/dist/upload-queue-qUXn1ykN.js.map +0 -1
  961. package/dist/usage-card-BeSLY0i0.js.map +0 -1
  962. package/dist/utils-B6kKb8jB.js.map +0 -1
  963. package/dist/value-inputs-skdVB2zh.js +0 -980
  964. package/dist/value-inputs-skdVB2zh.js.map +0 -1
  965. package/dist/value-typography-uAmWUAL1.js +0 -116
  966. package/dist/value-typography-uAmWUAL1.js.map +0 -1
  967. package/dist/workspace-DHeHv0qw.js +0 -411
  968. package/dist/workspace-DHeHv0qw.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters-BviMRMLS.js","names":["NumberValue","DateValue","_Fragment","_Fragment","_Fragment","parseBound","_Fragment","_Fragment","resolveComponentScale","useDatesConfig","useDensityConfig","cn","Text","DisplayLabel","focusRecipes","Button","Grid","Stack","toneRecipes","neutralFillRecipes","regionRecipes","LoadingState","ErrorState","popoverWidthRecipes","popoverRecipes","Value","Number$1","DateRange","parseDateInput","DatePrimitive","Badge","layerRecipes","fieldAffordanceRecipes","CommandItem","CommandInput","CommandEmpty","CommandList","CommandGroup","CommandSeparator","Command","formControlSizeClasses","formFieldTriggerClasses","resolveFormControlSize","Input","defaultDatePickerStrings","DatePicker","PopoverTitle","PopoverTrigger","PopoverHeader","PopoverDescription","Popover","PopoverFooter","PopoverContent","FormField","controlGroupSquareClasses","segmentedControlRecipes","controlGroupHeightClasses","TabsTrigger","TabsList","Tabs","PopoverMenu","useDebouncedCallback","useDebounce","useCascaderController","CascaderPanel","defaultCascaderStrings","Cascader","React","Fragment$1","defaultFilterStrings","count","interpolateFilterString","template","params","key","match","formatFilterCount","getFilterString","keys","path","result","strings","FilterType","FilterOperatorEnum","defineAsyncSelectConfig","config","getTextOperators","getSelectOperators","getNumberOperators","getDateOperators","getMultiSelectOperators","getMembershipOperators","getBooleanOperators","getOperatorsForType","type","getDefaultOperatorForType","usesMembershipOperators","resolveDefaultOperator","getOperatorsForFilter","getOperatorLabel","operator","getRangeBounds","first","value","isCompleteDateRange","endpoint","parseFilterDate","pattern","parsed","parse","isValid","findFilterOptionPath","option","options","labelInRunningText","label","word","hasNestedFilterOptions","toCascaderNodes","getFilterOptionLabel","filter","separator","validateFilterValue","validation","entries","isEmpty","entry","t","numeric","customValidation","getFilterValidationMessage","isMultiValueFilter","isSameFilterValue","a","b","left","right","index","FilterContext","createContext","EMPTY_FILTER_VALUE","reconcileAsyncLabels","next","filters","fetcher","mapToOption","limit","previous","sameSource","normalizeFilterValue","bound","FilterProvider","isNavigatingProp","stringsProp","filtersRef","useRef","onFilterChangeRef","onFilterChange","onErrorRef","onError","operatorDrafts","setOperatorDrafts","useState","operatorDraftsRef","writeOperatorDrafts","useCallback","setOperatorDraft","clearOperatorDraft","asyncCacheVersion","setAsyncCacheVersion","keptAsyncLabels","setKeptAsyncLabels","asyncLabels","useMemo","activeFiltersRef","activeFilters","proposalRef","readLatestFilters","proposal","proposeFilters","activeAsyncValues","useStrings","useEffect","useLayoutEffect","addFilter","removeFilter","latest","id","f","updateFilter","updates","clearFilters","replaceFilters","newFilters","getFilterByKey","getFilterValue","getFilterOperator","applied","setFilterValue","rawValue","existingFilter","draftOperator","isFilterActive","setFilterOperator","validateFilter","getDependentFilters","dep","cacheAsyncOptions","filterMap","filterKey","changed","version","getAsyncOptionLabel","optionValue","reportError","error","context","controller","reportPreloadError","selectedValues","cache","active","unresolved","resolveOptions","request","items","useFilters","useContext","useFilterGroups","processedFilters","dynamicFilterOptions","dyn","searchFilters","visibleFilters","activeRegularFilters","alwaysVisibleFilters","popoverFilters","activeFilterKeys","FilterOperatorSelect","open","setOpen","currentOperatorLabel","operators","op","disabled","segmentResetClassName","onOperatorChange","item","FilterValueDisplay","min","max","summary","renderAsyncValueText","val","renderValueText","CalendarIcon","renderDateValue","renderSingleDateValue","renderDateRangeValue","_filter","date","dateFormat","from","start","to","end","Divider","ActiveFilterItem","size","defaultScale","labelId","valueId","SEGMENT_RESET","isNavigating","triggerRef","popoverOpen","onFilterClick","ChevronDown","onFilterClear","X","readCacheEntry","gcTime","cacheKey","useAsyncOptions","asyncConfig","debounceMs","normalisedQuery","searchInput","minQueryLength","preload","staleTime","isPreload","meetsMinLength","canFetch","isActive","isBelowMinQuery","queryFn","state","setState","cached","reloadTick","setReloadTick","refetch","consumedReloadRef","force","isFresh","prev","cancelled","err","useFilterDraft","draft","setDraft","current","AsyncOptionsStatus","fetching","Loader2","event","onRetry","AsyncOptionsAnnouncer","formatCount","message","hasRows","FilterDraftFooter","caption","onConfirm","FilterEditorHeader","onBack","ChevronLeft","title","description","AsyncFilterContent","setSearchInput","tempValue","setTempValue","isMulti","maxSelected","showBackButton","triggerSource","isDirty","validationMessage","sortedOptions","selectedSet","optionValueSet","o","missingSelected","handleValueSelect","v","onClose","handleDone","emptyContent","isLoading","isFetching","isError","showsEmptyStatus","onBackToFilterList","EMPTY_PRESETS","shortcutRanges","now","addDays","startOfWeek","endOfWeek","startOfMonth","endOfMonth","subMonths","startOfYear","endOfYear","subYears","buildShortcutPresets","shortcuts","shortcut","calendar","weekStartsOn","DateFacet","isRangeMode","readableFormat","placeholder","withConfirm","closeOnSelect","showShortcuts","rangeValue","singleValue","configStrings","commonProps","className","handleSingleChange","output","handleRangeChange","presetsProp","DateFilterContent","setValidationMessage","startDate","endDate","formatOutputDate","format","handleDateChange","formattedStart","formattedEnd","facetValue","FilterErrorBoundaryBase","Component","fallback","labels","FilterErrorBoundary","props","FilterListItem","subtitle","FilterListContent","handleFilterSelect","availableFilters","BOUND_INPUT","parseBound$1","text","RangeFacet","minValue","setMinValue","maxValue","setMaxValue","focused","setFocused","emitted","setEmitted","seen","setSeen","valueChanged","differsFromInput","differsFromEmitted","inputSettled","emitRange","onValueChange","RangeFacetFields","instanceId","useId","errorId","onFocusChange","Label","onMinChange","invalid","onMaxChange","parseBound","trimmed","RangeFilterContent","appliedMin","appliedMax","setMin","setMax","nextMin","nextMax","malformed","dirty","confirm","NestedFilterOptions","onChange","RegularFilterContent","isMultiSelect","atMaxSelected","isSelected","newValue","handleNestedChange","nextValue","header","TagsFacetComponent","inputValue","setInputValue","handleAddTag","trimmedValue","handleRemoveTag","tag","tagToRemove","handleKeyDown","handleClearAll","hasTags","tagCountLabel","tagSummary","Plus","TagsFacet","TagsFilterContent","EDITOR_CONTROL","focusFilterEditorControl","popup","controls","element","FilterPopoverContent","popupRef","editorKey","activeFilterInPopover","shownEditorKey","view","frame","popoverWidth","handleSetFilterValue","FilterPill","operatorChangeTimer","opensSuppressed","operatorChangeRef","labelRef","editorFocusRef","isOpen","onClear","FiltersButton","setIsOpen","setActiveFilterInPopover","Filter","FilterTabs","nonSearchFilters","fc","activeTabId","tab","tabs","preset","sortedPreset","sortedActive","i","handleTabClick","presetFilters","filterConfig","SearchLoadingIcon","SearchFacetComponent","inputValueRef","lastEmittedValue","isUserTypingRef","currentInput","emitValue","getValidationMessage","term","debouncedUpdate","generic","genericWord","SearchFacet","SearchFiltersList","layoutGap","controlRowGap","FilterLayout","activeFilterKey","setActiveFilterKey","addFilterRef","removedFilterRef","handlePillValueChange","getFilterOperators","handleOperatorChange","variant","loadingFilters","filterLabel","showClearFilters","hasActive","DEFAULT_OPERATOR_SUFFIX","DEFAULT_RESET_PAGE_KEYS","filterOperators","normalizeQuery","record","input","normalized","toPublicRecord","out","values","readValues","arrayFormat","normalizeValues","formatValues","transformed","formatted","getDefaultOperator","readOperator","operatorSuffix","shouldEncodeOperator","mode","defaultOperator","parseFiltersFromQuery","query","filterConfigs","rawValues","dateRange","serializeFiltersToQuery","preserveUnrelated","includeOperators","resetPageKeys","nextRecord","currentQuery","configByKey","activeFilter","mergeFilterQuery","nextFilterQuery","SelectFacet","hasSelection","handleSelect","selectedValue","getOptionLabel","nestedNodes","placeholderInterpolated","selectedText","ChevronsUpDown","AsyncSelectFacet","labelCache","opt","initialOptions","initial","fromOptions","fromInitialOptions","emptyMessage","Check","zodValidator","schema","predicateValidator","predicate"],"sources":["../src/components/features/filters/filters.strings.ts","../src/components/features/filters/filters.types.ts","../src/components/features/filters/operator-options.ts","../src/components/features/filters/utils/filter-utils.ts","../src/components/features/filters/filter-context.tsx","../src/components/features/filters/hooks/use-filter-groups.ts","../src/components/features/filters/partials/filter-operator-select.tsx","../src/components/features/filters/partials/filter-value-display.tsx","../src/components/features/filters/partials/active-filter-item.tsx","../src/components/features/filters/hooks/use-async-options.ts","../src/components/features/filters/hooks/use-filter-draft.ts","../src/components/features/filters/partials/async-options-status.tsx","../src/components/features/filters/partials/filter-draft-footer.tsx","../src/components/features/filters/partials/filter-editor-header.tsx","../src/components/features/filters/partials/async-filter-content.tsx","../src/components/features/filters/facets/date-facet.tsx","../src/components/features/filters/partials/date-filter-content.tsx","../src/components/features/filters/partials/filter-error-boundary.tsx","../src/components/features/filters/partials/filter-list-item.tsx","../src/components/features/filters/partials/filter-list-content.tsx","../src/components/features/filters/facets/range-facet.tsx","../src/components/features/filters/partials/range-filter-content.tsx","../src/components/features/filters/partials/nested-filter-options.tsx","../src/components/features/filters/partials/regular-filter-content.tsx","../src/components/features/filters/facets/tags-facet.tsx","../src/components/features/filters/partials/tags-filter-content.tsx","../src/components/features/filters/partials/filter-popover-content.tsx","../src/components/features/filters/partials/filter-pill.tsx","../src/components/features/filters/partials/filters-button.tsx","../src/components/features/filters/partials/filter-tabs.tsx","../src/components/features/filters/facets/search-facet.tsx","../src/components/features/filters/partials/search-filters-list.tsx","../src/components/features/filters/filter-layout.tsx","../src/components/features/filters/filter-query.ts","../src/components/features/filters/facets/select-facet.tsx","../src/components/features/filters/facets/async-select-facet.tsx","../src/components/features/filters/validators.ts"],"sourcesContent":["/**\n * Filter strings — default copy and nested override contract.\n *\n * Consumers localize filters by passing `strings` to `<FilterProvider>`.\n * No routing, framework i18n hook, or backend shared-props contract belongs in\n * this default feature path.\n */\n\nexport interface FilterOperatorStrings {\n\tcontains: string;\n\tequals: string;\n\tnotContains: string;\n\tis: string;\n\tisNot: string;\n\tgreaterThan: string;\n\tlessThan: string;\n\tbefore: string;\n\tafter: string;\n\tbetween: string;\n\thas: string;\n\thasAny: string;\n\thasAll: string;\n\t/** Set membership, the `in` operator. Optional so existing complete overrides keep compiling. */\n\tin?: string;\n\t/** Set exclusion, the `not_in` operator. Optional so existing complete overrides keep compiling. */\n\tnotIn?: string;\n}\n\nexport interface FilterStrings {\n\t// Filter loading states\n\tloading: string;\n\tloadingOptions: string; // \"Loading {filterLabel} options...\"\n\n\t// Action buttons\n\taddFilter: string;\n\tclear: string;\n\tconfirm: string;\n\tclearFilters: string;\n\tclearAll: string;\n\n\t// Date selection\n\tselectDate: string;\n\tselectDateRange: string;\n\tcalendar: {\n\t\tnotDateSelected: string;\n\t\tnotDateRangeSelected: string;\n\t\t/** Shortcut labels. `today`, `thisMonth` and `lastThirtyDays` name the default set; the rest are offered through `datePickerConfig.shortcuts`. */\n\t\ttoday: string;\n\t\tyesterday: string;\n\t\tlastSevenDays: string;\n\t\tlastThirtyDays: string;\n\t\tthisMonth: string;\n\t\tlastMonth: string;\n\t\tthisYear: string;\n\t\tlastYear: string;\n\t\t/** \"This week\" shortcut in the range editor. Falls back to the date picker's copy. */\n\t\tthisWeek?: string;\n\t\t/** Label before the start of the range summary. Falls back to the date picker's copy. */\n\t\tfrom?: string;\n\t\t/** Label before the end of the range summary. Falls back to the date picker's copy. */\n\t\tto?: string;\n\t};\n\n\t// Value selection\n\tselectValues: string;\n\tsearchPlaceholder: string; // \"Search {filterLabel}...\"\n\tnoOptionsFound: string;\n\t/** Whether the entry is selected. */\n\tselected: string; // \"{count} {filterLabel} selected\"\n\tnothingSelected: string; // pill value text when nothing has been picked yet\n\n\t// Tags\n\tenterTag: string;\n\taddTag: string;\n\tremoveTag: string;\n\ttag: string;\n\ttags: string;\n\tenterTags: string;\n\t/**\n\t * Tag count above the chosen tags. A template with `{count}` and `{label}`\n\t * (the `tag` or `tags` string), or a function for languages with more\n\t * plural forms or a different order. Defaults to \"{count} {label}\".\n\t */\n\ttagCount?: string | ((count: number) => string);\n\n\t// Filter list\n\tsearchFilters: string;\n\tnoFiltersAvailable: string;\n\tavailableFilters: string;\n\tactiveFilters: string;\n\tclearSearch: string;\n\tbackToFilters: string;\n\t/** Returns from a nested option level to its parent level. */\n\tpreviousLevel: string;\n\t/** Chooses the nested option level being viewed, when branches are selectable. */\n\tselectCurrentLevel: string;\n\tselect: string;\n\toptions: string;\n\t/**\n\t * Option count under a filter in the Add filter list. A template with\n\t * `{count}` and `{label}` (the `options` string), or a function for other\n\t * plural rules. Defaults to \"{count} {label}\".\n\t */\n\toptionCount?: string | ((count: number) => string);\n\n\t// Operator selector (active-filter pill dropdown)\n\toperator: string;\n\toperators: FilterOperatorStrings;\n\n\t// Range filters\n\tmin: string;\n\tmax: string;\n\n\t// Async select filters\n\tfetchError: string;\n\tretryFetch: string;\n\tminQueryHint: string; // \"Type at least {min} characters...\"\n\tsearching: string;\n\t/**\n\t * Result count announced to assistive technology when an async search\n\t * settles. A function, so each locale applies its own plural rules.\n\t * Defaults to \"1 option found\" / \"{count} options found\".\n\t */\n\toptionsFound?: (count: number) => string;\n\n\t// Error boundary\n\terror: {\n\t\ttitle: string;\n\t\tdescriptionWithKey: string;\n\t\tgeneric: string;\n\t\tunknown: string;\n\t\t/** Name of the button that dismisses a failed filter. Falls back to `clear`. */\n\t\tdismiss?: string;\n\t};\n\n\t// Value validation\n\tvalidation: {\n\t\trequired: string;\n\t\tminValue: string;\n\t\tmaxValue: string;\n\t\tinvalidFormat: string;\n\t};\n}\n\n/**\n * Default English strings for the filter system.\n * These serve as fallbacks when no strings are provided.\n */\nexport const defaultFilterStrings: FilterStrings = {\n\t// Filter loading states\n\tloading: 'Loading',\n\tloadingOptions: 'Loading {filterLabel} options...',\n\n\t// Action buttons\n\taddFilter: 'Add filter',\n\tclear: 'Clear',\n\tconfirm: 'Confirm',\n\tclearFilters: 'Clear filters',\n\tclearAll: 'Clear all',\n\n\t// Date selection\n\tselectDate: 'Select date',\n\tselectDateRange: 'Select date range',\n\tcalendar: {\n\t\tnotDateSelected: 'No date selected',\n\t\tnotDateRangeSelected: 'No date range selected',\n\t\ttoday: 'Today',\n\t\tyesterday: 'Yesterday',\n\t\tlastSevenDays: 'Last 7 days',\n\t\tlastThirtyDays: 'Last 30 days',\n\t\tthisMonth: 'This month',\n\t\tlastMonth: 'Last month',\n\t\tthisYear: 'This year',\n\t\tlastYear: 'Last year',\n\t},\n\n\t// Value selection\n\tselectValues: 'Select values',\n\tsearchPlaceholder: 'Search {filterLabel}...',\n\tnoOptionsFound: 'No options found',\n\tselected: '{count} {filterLabel} selected',\n\tnothingSelected: 'Nothing selected',\n\n\t// Tags\n\tenterTag: 'Enter tag',\n\taddTag: 'Add tag',\n\tremoveTag: 'Remove',\n\ttag: 'tag',\n\ttags: 'tags',\n\tenterTags: 'Enter tags',\n\ttagCount: '{count} {label}',\n\n\t// Filter list\n\tsearchFilters: 'Search filters...',\n\tnoFiltersAvailable: 'No filters available',\n\tavailableFilters: 'Available filters',\n\tactiveFilters: 'Active filters',\n\tclearSearch: 'Clear search',\n\tbackToFilters: 'Back to filters',\n\tpreviousLevel: 'Back',\n\tselectCurrentLevel: 'Select this level',\n\tselect: 'Select',\n\toptions: 'options',\n\toptionCount: '{count} {label}',\n\n\t// Operator selector (active-filter pill dropdown)\n\toperator: 'Operator',\n\toperators: {\n\t\tcontains: 'contains',\n\t\tequals: 'is',\n\t\tnotContains: 'does not contain',\n\t\tis: 'is',\n\t\tisNot: 'is not',\n\t\tgreaterThan: 'greater than',\n\t\tlessThan: 'less than',\n\t\tbefore: 'before',\n\t\tafter: 'after',\n\t\tbetween: 'between',\n\t\thas: 'has',\n\t\thasAny: 'has any',\n\t\thasAll: 'has all',\n\t\tin: 'is any of',\n\t\tnotIn: 'is none of',\n\t},\n\n\t// Range filters\n\tmin: 'Min',\n\tmax: 'Max',\n\n\t// Async select filters\n\tfetchError: 'Failed to load options',\n\tretryFetch: 'Retry',\n\tminQueryHint: 'Type at least {min} characters...',\n\tsearching: 'Searching...',\n\toptionsFound: (count) => (count === 1 ? '1 option found' : `${count} options found`),\n\n\t// Error boundary\n\terror: {\n\t\ttitle: 'Filter error',\n\t\tdescriptionWithKey: 'There was a problem with \"{filterKey}\" filter.',\n\t\tgeneric: 'There was a problem loading this filter.',\n\t\tunknown: 'Unknown error',\n\t},\n\n\t// Value validation\n\tvalidation: {\n\t\trequired: 'This filter is required',\n\t\tminValue: 'Value must be at least {min}',\n\t\tmaxValue: 'Value must be at most {max}',\n\t\tinvalidFormat: 'Invalid format',\n\t},\n};\n\n/**\n * Helper function to interpolate values in strings.\n * Replaces {key} with the corresponding value from the params object.\n */\nexport function interpolateFilterString(\n\ttemplate: string,\n\tparams: Record<string, string | number>,\n): string {\n\tconst withCurlyPlaceholders = template.replace(/{(\\w+)}/g, (match, key) => {\n\t\treturn String(params[key] ?? match);\n\t});\n\n\tconst withColonPlaceholdersReplaced = withCurlyPlaceholders.replace(\n\t\t/:(\\w+)/g,\n\t\t(match, key) => {\n\t\t\treturn params[key] !== undefined ? String(params[key]) : match;\n\t\t},\n\t);\n\n\treturn withColonPlaceholdersReplaced;\n}\n\n/**\n * A count string that is either a `{count} {label}` template or a function,\n * so a locale can reorder the words or apply its own plural rules.\n */\nexport function formatFilterCount(\n\ttemplate: string | ((count: number) => string) | undefined,\n\tcount: number,\n\tlabel: string,\n): string {\n\tif (typeof template === 'function') return template(count);\n\treturn interpolateFilterString(template ?? '{count} {label}', { count, label }).trim();\n}\n\n/**\n * Helper function to get a string from a strings object\n * with dot notation support.\n */\nexport function getFilterString(\n\tstrings: FilterStrings,\n\tpath: string,\n\tparams?: Record<string, string | number>,\n): string {\n\tconst keys = path.split('.');\n\tlet result: unknown = strings;\n\n\tfor (const key of keys) {\n\t\tif (result == null || typeof result !== 'object') {\n\t\t\treturn path; // Return the path if the string is not found\n\t\t}\n\t\tresult = (result as Record<string, unknown>)[key];\n\t}\n\n\tif (typeof result === 'string') {\n\t\treturn params ? interpolateFilterString(result, params) : result;\n\t}\n\n\treturn path; // Return the path if the string is not found\n}\n","import type { ReactNode } from 'react';\nimport type { DatePickerProps, PresetDateRange } from '../../base/date-pickers';\n\n/** Shared height class for all filter control elements. */\nexport const FILTER_ELEMENT_HEIGHT = 'h-control';\n\n/**\n * Core type definitions and interfaces for the filters feature.\n *\n * This file defines:\n * - Filter types (SELECT, MULTI_SELECT, SEARCH, RANGE, DATE)\n * - Filter operators (equals, contains, in, etc.)\n * - Configuration interfaces for filters\n * - Context value types for filter state management\n * - Validation and display configuration types\n *\n * These types are used throughout the filters feature to ensure type safety\n * and consistent data structures.\n */\n\nexport const FilterType = {\n\tSELECT: 'select',\n\tMULTI_SELECT: 'multi_select',\n\tASYNC_SELECT: 'async_select',\n\tSEARCH: 'search',\n\tRANGE: 'range',\n\tDATE: 'date',\n\tTAGS: 'tags',\n} as const;\n\nexport type FilterType = (typeof FilterType)[keyof typeof FilterType];\n\n// Convert string union to enum for better type safety and autocompletion\n// Note: All enum values are used via the FilterOperator type below, even if not directly referenced\nexport const FilterOperatorEnum = {\n\tEQUALS: 'equals',\n\tCONTAINS: 'contains',\n\tIN: 'in',\n\tNOT_IN: 'not_in',\n\tNOT: 'not',\n\tBEFORE: 'before',\n\tAFTER: 'after',\n\tBETWEEN: 'between',\n\tGT: 'gt',\n\tLT: 'lt',\n\tGTE: 'gte',\n\tLTE: 'lte',\n\tHAS: 'has',\n\tHAS_ANY: 'has_any',\n\tHAS_ALL: 'has_all',\n} as const;\n\n// Strict type for better type safety - using enum values to match backend\nexport type FilterOperator = (typeof FilterOperatorEnum)[keyof typeof FilterOperatorEnum];\n\nexport interface OperatorOption {\n\t/** Display label. */\n\tlabel: string;\n\t/** Current value of the filter. */\n\tvalue: FilterOperator;\n}\n\n// Filter display types\n// Accept both 'drawer' and 'collapsed' as synonyms for the collapsed UI\nexport type FilterDisplay = 'always' | 'drawer' | 'collapsed' | 'hidden';\n\n/** Origin of a filter editor, used to decide whether a back action is available. */\nexport type FilterTriggerSource = 'toolbar' | 'chip';\n\nexport const FilterCategory = {\n\tFILTER: 'filter',\n\tSORT: 'sort',\n\tGROUP: 'group',\n} as const;\n\nexport type FilterCategory = (typeof FilterCategory)[keyof typeof FilterCategory];\n\nexport interface FilterOption {\n\t/** Display label. */\n\tlabel: string;\n\t/** Current value of the filter. */\n\tvalue: string;\n\t/** Leading glyph. */\n\ticon: ReactNode;\n\t/** Nested options. SELECT and MULTI_SELECT editors show them level by level, and a chosen option reads as its path. */\n\tchildren?: FilterOption[];\n\t/** Renders the entry as unselectable. */\n\tdisabled?: boolean;\n\t/** Supporting copy shown under the label. */\n\tdescription?: string;\n\t/** Layout metadata only: the built-in editors and pills do not read it. */\n\tcolor?: string;\n}\n\nexport interface DisplayConfig {\n\t/** Layout metadata only: for custom layouts. FilterLayout does not read it. */\n\trenderConfig?: {\n\t\tdesktop: string;\n\t\tmobile?: string;\n\t\ttablet?: string;\n\t};\n\tdisplay?: FilterDisplay;\n\t/** Layout metadata only: for custom layouts. FilterLayout does not read it. */\n\tcategory?: FilterCategory;\n\t/** Layout metadata only: for custom layouts. FilterLayout keeps the order of `filters`. */\n\tpriority?: number;\n\thidden?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string; // Simplified config for basic styling needs\n}\n\n/**\n * Checked by `validateFilter` and by the built-in editors before a draft is\n * applied; an invalid draft shows its message and cannot be confirmed.\n */\nexport interface ValidationConfig {\n\t/** Lowest number allowed. Applies to numbers and to each RANGE bound. */\n\tmin?: number;\n\t/** Highest number allowed. Applies to numbers and to each RANGE bound. */\n\tmax?: number;\n\t/** Tested against a string, or against every entry of an array value. */\n\tpattern?: RegExp;\n\t/** Rejects an empty value. */\n\trequired?: boolean;\n\t/** Receives the whole value. Return `true`, or `false` or a message to reject it. */\n\tcustom?: (value: unknown) => boolean | string;\n}\n\nexport interface FilterDependency {\n\tkey: string;\n\t/** Comparison currently chosen. */\n\toperator: FilterOperator;\n\t/** Current value of the filter. */\n\tvalue: string | string[];\n}\n\nexport interface FilterErrorContext {\n\tphase: 'fetch-options' | 'apply' | 'validate' | 'render';\n\tfilterKey?: string;\n}\n\nexport type FilterErrorHandler = (\n\terror: unknown,\n\tcontext: FilterErrorContext,\n) => void;\n\n/**\n * Configuration for ASYNC_SELECT filters that load options asynchronously.\n *\n * The single async channel owns search, caching, abort, and preload control.\n * Static SELECT and MULTI_SELECT filters use `FilterConfig.options` instead.\n */\nexport interface AsyncSelectConfig<TItem = unknown> {\n\t/** Cache key factory — receives { query, limit } and returns a stable key. */\n\tqueryKey: (args: { query: string; limit: number }) => readonly unknown[];\n\t/** Fetcher function — receives { query, limit, signal } and returns items */\n\tfetcher: (args: {\n\t\tquery: string;\n\t\tlimit: number;\n\t\tsignal?: AbortSignal;\n\t}) => Promise<TItem[]>;\n\t/** Maps a fetched item to a FilterOption for display. */\n\tmapToOption: {\n\t\tbivarianceHack(item: TItem): FilterOption;\n\t}['bivarianceHack'];\n\t/**\n\t * Loads the items for values that are already applied, such as ids restored\n\t * from a URL, so their pill and editor show labels even when they fall\n\t * outside the first page. Without it the provider preloads the first page\n\t * and an unresolved value is listed by its raw value.\n\t */\n\tresolveOptions?: (args: {\n\t\tvalues: string[];\n\t\tsignal?: AbortSignal;\n\t}) => Promise<TItem[]>;\n\t/** Max items to fetch per request (default: 10) */\n\tlimit?: number;\n\t/** Minimum characters before fetching (default: 0) */\n\tminQueryLength?: number;\n\t/** Whether to fetch with empty query on open (default: true) */\n\tpreload?: boolean;\n\t/** Debounce delay in ms (default: 300) */\n\tdebounceMs?: number;\n\t/** Freshness window in ms for cached results within one mounted editor (default: 60_000). */\n\tstaleTime?: number;\n\t/** Retention window in ms within one mounted editor (default: 300_000). Closing the editor discards its cache. */\n\tgcTime?: number;\n}\n\n/**\n * Infers the fetched item shape once and preserves it across `fetcher` and\n * `mapToOption`, while remaining assignable to heterogeneous filter arrays.\n */\nexport function defineAsyncSelectConfig<TItem>(\n\tconfig: AsyncSelectConfig<TItem>,\n): AsyncSelectConfig<TItem> {\n\treturn config;\n}\n\nexport interface FilterConfig {\n\tkey: string;\n\t/** Display label. */\n\tlabel: string;\n\t/** Plural form of the label, used in \"{count} {label} selected\" when count > 1 */\n\tpluralLabel?: string;\n\ttype: FilterType;\n\t/** Supporting copy under an inline SEARCH field. Pills and popover editors do not show it. */\n\tdescription?: string;\n\t/** Operator the filter starts with. Wins over `operators[0]` and the type default. */\n\toperator?: FilterOperator;\n\t/** Comparisons this filter offers. The first one is the default when `operator` is not set. */\n\toperators?: OperatorOption[];\n\t/**\n\t * MULTI_SELECT only. Compares by set membership: the filter starts with\n\t * `in` (\"is any of\") and its pill offers `in` and `not_in`, instead of\n\t * starting with `equals` and offering is / is not / is any of / is none of.\n\t * `operator` and `operators` still win. Defaults to `false`.\n\t *\n\t * Migration, before turning it on for a filter that already has stored\n\t * state:\n\t * - The default operator is not written to the query string, so a link\n\t * saved as `?status=paid` used to parse as `equals` and now parses as\n\t * `in`. Have the backend read a missing operator for this key as `in`,\n\t * or re-serialize stored links first with `includeOperators: 'always'`\n\t * so they carry `status__op=equals`.\n\t * - A stored `ActiveFilter` or saved view with `operator: 'equals'` keeps\n\t * it. Its pill reads \"is\", the query now carries `status__op=equals`\n\t * because it is no longer the default, and the user can switch it to\n\t * `in` or `not_in` but not back. Map stored `equals` to `in` when the\n\t * two mean the same to the backend.\n\t * - Filter tab presets without an `operator` apply `in`.\n\t */\n\tmembershipOperators?: boolean;\n\toptions?: FilterOption[];\n\tplaceholder?: string;\n\tdelay?: number;\n\t/** Leading glyph. */\n\ticon: ReactNode;\n\tdisplayConfig: DisplayConfig;\n\t/** Layout metadata only: for the consumer's initial state. The provider is controlled and does not apply it. */\n\tdefaultValue?: string | string[];\n\tvalidation?: ValidationConfig;\n\t/**\n\t * Layout metadata only: for custom layouts, read through\n\t * `getDependentFilters`. FilterLayout does not hide or clear dependent filters.\n\t */\n\tdependencies?: FilterDependency[];\n\tmultiple?: boolean;\n\t/** For nested options: only leaves can be chosen (default), or any option, including a branch. */\n\tselectableOptions?: 'leaf' | 'any';\n\tcloseOnSelect?: boolean;\n\t/** Most values a multi-value select may hold; further options are disabled once it is reached. */\n\tmaxSelected?: number;\n\t/** Async option loading config for ASYNC_SELECT filters. */\n\tasyncConfig?: AsyncSelectConfig;\n\tdateFormat?: {\n\t\tdisplay?: string; // Format for display (e.g., 'MMM d, yyyy')\n\t\tparam?: string; // Format for URL parameters (e.g., 'yyyy-MM-dd')\n\t};\n\t// Date picker specific options\n\tdatePickerConfig?: {\n\t\tshowConfirmButton?: boolean;\n\t\tshowShortcuts?: boolean;\n\t\tnoDatePlaceholder?: string;\n\t\tnoRangePlaceholder?: string;\n\t\tautoApply?: boolean; // Whether to automatically apply date selections\n\t\t/** Copy passed to the date picker, over the provider's `calendar` strings. */\n\t\tstrings?: DatePickerProps['strings'];\n\t\t/** Replaces the range shortcuts. `showShortcuts: false` still hides them. */\n\t\tpresets?: PresetDateRange[];\n\t\t/**\n\t\t * Range shortcuts to offer, in order, labelled from the provider's\n\t\t * `calendar` strings. Omit to keep the date picker's default set\n\t\t * (today, this week, this month, last 30 days). `presets` wins when both\n\t\t * are passed, and `showShortcuts: false` hides either.\n\t\t */\n\t\tshortcuts?: FilterDateShortcut[];\n\t\t/**\n\t\t * date-fns locale for weekday and month names and the trigger text.\n\t\t * Falls back to `UIProvider` `dates.locale`.\n\t\t */\n\t\tlocale?: DatePickerProps['locale'];\n\t};\n\t// Optional formatting functions\n\tformat?: (value: unknown) => string;\n\tparse?: (value: string) => unknown;\n\ttransform?: (value: unknown) => unknown;\n}\n\n/** A built-in range shortcut of the DATE editor. Each one is labelled by the `calendar` string of the same name. */\nexport type FilterDateShortcut =\n\t| 'today'\n\t| 'yesterday'\n\t| 'thisWeek'\n\t| 'lastSevenDays'\n\t| 'lastThirtyDays'\n\t| 'thisMonth'\n\t| 'lastMonth'\n\t| 'thisYear'\n\t| 'lastYear';\n\nexport interface ActiveFilter {\n\t/** Stable identity for this entry. */\n\tid: string;\n\tkey: string;\n\t/** Comparison currently chosen. */\n\toperator: FilterOperator;\n\t/** Current value of the filter. RANGE uses [min, max], with an empty string for an open bound. */\n\tvalue: string[];\n}\n\nexport interface FilterGroup {\n\t/** Display label. */\n\tlabel: string;\n\t/** Filter definitions available to the surface. */\n\tfilters: FilterConfig[];\n}\n\nexport interface FilterState {\n\t[key: string]: string[];\n}\n\nexport interface FilterTabPreset {\n\tkey: string;\n\t/** Current value of the filter. */\n\tvalue: string[];\n\t/** Comparison currently chosen. */\n\toperator?: FilterOperator;\n}\n\nexport interface FilterTab {\n\t/** Stable identity for this entry. */\n\tid: string;\n\t/** Display label. */\n\tlabel: string;\n\tpresets: FilterTabPreset[];\n\tcount?: number;\n}\n","import {\n\tFilterOperatorEnum,\n\ttype FilterConfig,\n\ttype FilterOperator,\n\ttype OperatorOption,\n\tFilterType,\n} from './filters.types';\nimport { defaultFilterStrings, type FilterOperatorStrings } from './filters.strings';\n\nexport function getTextOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [\n\t\t{ label: strings.contains, value: FilterOperatorEnum.CONTAINS },\n\t\t{ label: strings.equals, value: FilterOperatorEnum.EQUALS },\n\t\t{ label: strings.notContains, value: FilterOperatorEnum.NOT },\n\t];\n}\n\nexport function getSelectOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [\n\t\t{ label: strings.is, value: FilterOperatorEnum.EQUALS },\n\t\t{ label: strings.isNot, value: FilterOperatorEnum.NOT },\n\t];\n}\n\nexport function getNumberOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [\n\t\t{ label: strings.equals, value: FilterOperatorEnum.EQUALS },\n\t\t{ label: strings.greaterThan, value: FilterOperatorEnum.GT },\n\t\t{ label: strings.lessThan, value: FilterOperatorEnum.LT },\n\t];\n}\n\nexport function getDateOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [\n\t\t{ label: strings.before, value: FilterOperatorEnum.BEFORE },\n\t\t{ label: strings.after, value: FilterOperatorEnum.AFTER },\n\t\t{ label: strings.between, value: FilterOperatorEnum.BETWEEN },\n\t];\n}\n\n/**\n * Operators for a MULTI_SELECT filter. `equals` and `not` stay first because\n * `equals` is the stored default; `in` and `not_in` name the set comparison.\n */\nexport function getMultiSelectOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [...getSelectOperators(strings), ...getMembershipOperators(strings)];\n}\n\n/** The set-membership pair, `in` and `not_in`. */\nfunction getMembershipOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [\n\t\t{ label: strings.in ?? defaultFilterStrings.operators.in!, value: FilterOperatorEnum.IN },\n\t\t{ label: strings.notIn ?? defaultFilterStrings.operators.notIn!, value: FilterOperatorEnum.NOT_IN },\n\t];\n}\n\nexport function getBooleanOperators(strings: FilterOperatorStrings): OperatorOption[] {\n\treturn [{ label: strings.equals, value: FilterOperatorEnum.EQUALS }];\n}\n\nexport function getOperatorsForType(\n\ttype: FilterType,\n\tstrings: FilterOperatorStrings,\n): OperatorOption[] {\n\tswitch (type) {\n\t\tcase FilterType.SEARCH:\n\t\t\treturn getTextOperators(strings);\n\t\tcase FilterType.TAGS:\n\t\t\treturn [\n\t\t\t\t{ label: strings.has, value: FilterOperatorEnum.HAS },\n\t\t\t\t{ label: strings.hasAny, value: FilterOperatorEnum.HAS_ANY },\n\t\t\t\t{ label: strings.hasAll, value: FilterOperatorEnum.HAS_ALL },\n\t\t\t];\n\t\tcase FilterType.SELECT:\n\t\tcase FilterType.ASYNC_SELECT:\n\t\t\treturn getSelectOperators(strings);\n\t\tcase FilterType.MULTI_SELECT:\n\t\t\treturn getMultiSelectOperators(strings);\n\t\tcase FilterType.RANGE:\n\t\t\treturn [{ label: strings.between, value: FilterOperatorEnum.BETWEEN }];\n\t\tcase FilterType.DATE:\n\t\t\treturn getDateOperators(strings);\n\t\tdefault:\n\t\t\treturn getTextOperators(strings);\n\t}\n}\n\nexport function getDefaultOperatorForType(\n\ttype: FilterType,\n): FilterOperator {\n\tswitch (type) {\n\t\tcase FilterType.SEARCH:\n\t\t\treturn FilterOperatorEnum.CONTAINS;\n\t\tcase FilterType.TAGS:\n\t\t\t// Tags default to array containment semantics\n\t\t\treturn FilterOperatorEnum.HAS;\n\t\tcase FilterType.SELECT:\n\t\tcase FilterType.ASYNC_SELECT:\n\t\t\treturn FilterOperatorEnum.EQUALS;\n\t\tcase FilterType.RANGE:\n\t\t\treturn FilterOperatorEnum.BETWEEN;\n\t\tcase FilterType.DATE:\n\t\t\treturn FilterOperatorEnum.BEFORE;\n\t\tdefault:\n\t\t\treturn FilterOperatorEnum.EQUALS;\n\t}\n}\n\n/** Whether a filter opted in to set-membership operators: MULTI_SELECT with `membershipOperators`. */\nfunction usesMembershipOperators(\n\tconfig: Pick<FilterConfig, 'type' | 'membershipOperators'>,\n): boolean {\n\treturn config.type === FilterType.MULTI_SELECT && config.membershipOperators === true;\n}\n\n/**\n * The operator a filter starts with: its configured `operator`, then the\n * first of its `operators`, then `in` for a MULTI_SELECT that set\n * `membershipOperators`, then the default for its type. The provider, the\n * query helpers and filter tabs all resolve the default through this.\n */\nexport function resolveDefaultOperator(\n\tconfig: Pick<FilterConfig, 'type' | 'operator' | 'operators' | 'membershipOperators'> | undefined,\n): FilterOperator {\n\tif (!config) return FilterOperatorEnum.EQUALS;\n\treturn config.operator\n\t\t?? config.operators?.[0]?.value\n\t\t?? (usesMembershipOperators(config) ? FilterOperatorEnum.IN : getDefaultOperatorForType(config.type));\n}\n\n/**\n * The operators a filter's pill offers: its own `operators`, then `in` and\n * `not_in` for a MULTI_SELECT that set `membershipOperators`, then the list\n * for its type.\n */\nexport function getOperatorsForFilter(\n\tconfig: Pick<FilterConfig, 'type' | 'operators' | 'membershipOperators'>,\n\tstrings: FilterOperatorStrings,\n): OperatorOption[] {\n\tif (config.operators && config.operators.length > 0) return config.operators;\n\tif (usesMembershipOperators(config)) return getMembershipOperators(strings);\n\treturn getOperatorsForType(config.type, strings);\n}\n\n/**\n * Localised label for an operator that is not in the list a pill offers, such\n * as one restored from a URL. `gte` and `lte` have no copy and return undefined.\n */\nexport function getOperatorLabel(\n\toperator: FilterOperator,\n\tstrings: FilterOperatorStrings,\n): string | undefined {\n\tswitch (operator) {\n\t\tcase FilterOperatorEnum.EQUALS: return strings.is;\n\t\tcase FilterOperatorEnum.NOT: return strings.isNot;\n\t\tcase FilterOperatorEnum.CONTAINS: return strings.contains;\n\t\tcase FilterOperatorEnum.IN: return strings.in ?? defaultFilterStrings.operators.in;\n\t\tcase FilterOperatorEnum.NOT_IN: return strings.notIn ?? defaultFilterStrings.operators.notIn;\n\t\tcase FilterOperatorEnum.BEFORE: return strings.before;\n\t\tcase FilterOperatorEnum.AFTER: return strings.after;\n\t\tcase FilterOperatorEnum.BETWEEN: return strings.between;\n\t\tcase FilterOperatorEnum.GT: return strings.greaterThan;\n\t\tcase FilterOperatorEnum.LT: return strings.lessThan;\n\t\tcase FilterOperatorEnum.HAS: return strings.has;\n\t\tcase FilterOperatorEnum.HAS_ANY: return strings.hasAny;\n\t\tcase FilterOperatorEnum.HAS_ALL: return strings.hasAll;\n\t\tdefault: return undefined;\n\t}\n}\n","import type { ReactNode } from 'react';\nimport { isValid, parse } from 'date-fns';\nimport type { CascaderNode } from '../../../base/cascader';\nimport { parseDateInput } from '../../../primitives';\nimport type { FilterConfig, FilterDependency, FilterOperator, FilterOption } from '../filters.types';\n\nexport function getRangeBounds(value: readonly string[], operator?: FilterOperator): [min: string, max: string] {\n\tconst first = value[0] ?? '';\n\tif (value.length > 1) return [first, value[1] ?? ''];\n\tif (operator === 'lt') return ['', first];\n\tif (operator === 'equals') return [first, first];\n\treturn [first, ''];\n}\n\nexport function isCompleteDateRange(value: readonly string[]): boolean {\n\treturn value.length === 2 && value.every((endpoint) => endpoint.trim().length > 0);\n}\n\n/** Filter dates use local calendar days or the app's explicit parameter format. */\nexport function parseFilterDate(value: string | undefined, pattern?: string): Date | undefined {\n\tif (!value) return undefined;\n\tif (pattern) {\n\t\tconst parsed = parse(value, pattern, new Date());\n\t\tif (isValid(parsed)) return parsed;\n\t}\n\treturn parseDateInput(value) ?? undefined;\n}\n\n/**\n * The option for a value and its ancestors, searching nested options.\n */\nexport function findFilterOptionPath(\n\toptions: readonly FilterOption[] | undefined,\n\tvalue: string,\n): FilterOption[] {\n\tfor (const option of options ?? []) {\n\t\tif (option.value === value) return [option];\n\t\tconst path = findFilterOptionPath(option.children, value);\n\t\tif (path.length) return [option, ...path];\n\t}\n\treturn [];\n}\n\n/**\n * A sentence-case label inside running text, such as a footer count:\n * \"Created date\" reads \"created date\", while acronyms such as \"SKU\" stay.\n */\nexport function labelInRunningText(label: string): string {\n\treturn label.replace(/\\S+/g, (word) => (/^\\p{Lu}{2,}/u.test(word) ? word : word.toLowerCase()));\n}\n\n/**\n * Whether any option nests children, so the editor shows them level by level.\n */\nexport function hasNestedFilterOptions(options?: readonly FilterOption[]): boolean {\n\treturn !!options?.some((option) => !!option.children?.length);\n}\n\n/**\n * Nested filter options as cascader nodes.\n */\nexport function toCascaderNodes(options: readonly FilterOption[]): CascaderNode[] {\n\treturn options.map((option) => ({\n\t\tvalue: option.value,\n\t\tlabel: option.label,\n\t\tdescription: option.description,\n\t\ticon: option.icon ?? undefined,\n\t\tdisabled: option.disabled,\n\t\t...(option.children?.length ? { children: toCascaderNodes(option.children) } : {}),\n\t}));\n}\n\n/**\n * Gets the label for a filter option; a nested option reads as its path, such as \"Europe / Greece\".\n */\nexport function getFilterOptionLabel(\n\tfilter: FilterConfig,\n\tvalue: string,\n\tseparator = ' / ',\n): string | undefined {\n\tconst path = findFilterOptionPath(filter.options, value);\n\treturn path.length ? path.map((option) => option.label).join(separator) : undefined;\n}\n\n/**\n * Gets the icon for a filter option\n */\nexport function getFilterOptionIcon(\n\tfilter: FilterConfig,\n\tvalue: string,\n): ReactNode | undefined {\n\treturn findFilterOptionPath(filter.options, value).at(-1)?.icon;\n}\n\n/**\n * Validates a filter value against the filter configuration.\n *\n * The provider holds every value as a string array, so an array is checked\n * entry by entry: `required` rejects an empty array, `pattern` tests each\n * non-empty entry, and `min`/`max` test each bound of a RANGE filter. A scalar\n * number or string is checked directly, as before. `custom` receives the\n * whole value.\n *\n * @param filter - The filter configuration to validate against\n * @param value - The value to validate\n * @param t - Resolves a `validation.*` string path to its copy\n * @returns true if valid, or an error message string if invalid\n */\nexport function validateFilterValue(\n\tfilter: FilterConfig,\n\tvalue: unknown,\n\tt: (key: string) => string,\n): boolean | string {\n\tconst validation = filter.validation;\n\tconst entries: unknown[] = Array.isArray(value) ? value : [value];\n\tconst isEmpty = value == null || value === '' ||\n\t\t(Array.isArray(value) && value.every((entry) => entry == null || String(entry).trim() === ''));\n\n\tif (validation?.required && isEmpty) {\n\t\treturn t('validation.required');\n\t}\n\n\tconst checksNumbers = validation?.min !== undefined || validation?.max !== undefined;\n\tif (checksNumbers) {\n\t\tfor (const entry of entries) {\n\t\t\t// Strings are only read as numbers for RANGE bounds; an open bound is skipped.\n\t\t\tconst numeric = typeof entry === 'number'\n\t\t\t\t? entry\n\t\t\t\t: filter.type === 'range' && typeof entry === 'string' && entry.trim() !== ''\n\t\t\t\t\t? Number(entry)\n\t\t\t\t\t: undefined;\n\t\t\tif (numeric === undefined) continue;\n\t\t\tif (Number.isNaN(numeric)) return t('validation.invalidFormat');\n\t\t\tif (validation?.min !== undefined && numeric < validation.min) {\n\t\t\t\treturn t('validation.minValue').replace('{min}', String(validation.min));\n\t\t\t}\n\t\t\tif (validation?.max !== undefined && numeric > validation.max) {\n\t\t\t\treturn t('validation.maxValue').replace('{max}', String(validation.max));\n\t\t\t}\n\t\t}\n\t}\n\n\tif (validation?.pattern) {\n\t\t// A fresh expression, so a global or sticky flag keeps no position between entries.\n\t\tconst pattern = new RegExp(validation.pattern.source, validation.pattern.flags.replace(/[gy]/g, ''));\n\t\tfor (const entry of entries) {\n\t\t\tif (typeof entry !== 'string' || entry === '') continue;\n\t\t\tif (!pattern.test(entry)) return t('validation.invalidFormat');\n\t\t}\n\t}\n\n\tif (validation?.custom) {\n\t\tconst customValidation = validation.custom(value);\n\t\tif (typeof customValidation === 'string' || !customValidation) {\n\t\t\treturn customValidation;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * The message to show for a draft that fails its filter's `validation`, or\n * undefined when it may be applied. A bare `false` reads as an invalid format.\n */\nexport function getFilterValidationMessage(\n\tfilter: FilterConfig,\n\tvalue: unknown,\n\tstrings: { validation: { required: string; minValue: string; maxValue: string; invalidFormat: string } },\n): string | undefined {\n\tif (!filter.validation) return undefined;\n\tconst result = validateFilterValue(filter, value, (path) => {\n\t\tconst key = path.replace('validation.', '') as keyof typeof strings.validation;\n\t\treturn strings.validation[key] ?? path;\n\t});\n\tif (result === true) return undefined;\n\treturn typeof result === 'string' && result ? result : strings.validation.invalidFormat;\n}\n\n/** Whether a filter holds several values: MULTI_SELECT, TAGS, or any filter with `multiple`. */\nexport function isMultiValueFilter(config: Pick<FilterConfig, 'type' | 'multiple'>): boolean {\n\treturn (\n\t\tconfig.type === 'multi_select' ||\n\t\tconfig.type === 'tags' ||\n\t\tconfig.multiple === true\n\t);\n}\n\n/** Whether two filter values hold the same entries in the same order. */\nexport function isSameFilterValue(a: readonly string[] | undefined, b: readonly string[] | undefined): boolean {\n\tif (a === b) return true;\n\tconst left = a ?? [];\n\tconst right = b ?? [];\n\treturn left.length === right.length && left.every((entry, index) => entry === right[index]);\n}\n\n/**\n * Formats a filter value for display using either the format function provided\n * in the filter config, or by looking up option labels\n *\n * @param filter - The filter configuration\n * @param value - The value to format\n * @returns Formatted string representation of the value\n */\nexport function formatFilterValue(\n\tfilter: FilterConfig,\n\tvalue: unknown,\n): string {\n\t// Use custom format function if provided in filter config\n\tif (filter.format && typeof filter.format === 'function') {\n\t\ttry {\n\t\t\treturn filter.format(value);\n\t\t} catch (error) {\n\t\t\tif (import.meta.env?.DEV) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`Error using custom format function for filter ${filter.key}:`,\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Fall back to default formatting\n\t\t}\n\t}\n\n\t// Default formatting behavior\n\tif (Array.isArray(value)) {\n\t\treturn value\n\t\t\t.map((v) => getFilterOptionLabel(filter, String(v)) ?? String(v))\n\t\t\t.join(', ');\n\t}\n\n\treturn getFilterOptionLabel(filter, String(value)) ?? String(value);\n}\n\n/**\n * Gets the values of dependent filters. A headless helper for\n * `FilterConfig.dependencies`; FilterLayout does not call it.\n */\nexport function getDependentFilterValues(\n\tdependencies: FilterDependency[],\n\tfilterState: Record<string, string[]>,\n): Record<string, string[]> {\n\treturn dependencies.reduce(\n\t\t(acc, dep) => {\n\t\t\tconst values = filterState[dep.key] || [];\n\t\t\tif (values.length > 0) {\n\t\t\t\tacc[dep.key] = values;\n\t\t\t}\n\t\t\treturn acc;\n\t\t},\n\t\t{} as Record<string, string[]>,\n\t);\n}\n\n/**\n * Determines if a filter should be shown based on its dependencies. A\n * headless helper for `FilterConfig.dependencies`; FilterLayout does not call it.\n */\nexport function shouldShowFilter(\n\tfilter: FilterConfig,\n\tfilterState: Record<string, string[]>,\n): boolean {\n\tif (!filter.dependencies || filter.dependencies.length === 0) {\n\t\treturn true;\n\t}\n\n\treturn filter.dependencies.every((dep) => {\n\t\tconst values = filterState[dep.key] || [];\n\t\tif (values.length === 0) return false;\n\n\t\tswitch (dep.operator) {\n\t\t\tcase 'equals':\n\t\t\t\treturn values.includes(dep.value as string);\n\t\t\tcase 'contains':\n\t\t\t\treturn values.some((v) => (dep.value as string).includes(v));\n\t\t\tcase 'in':\n\t\t\t\treturn Array.isArray(dep.value)\n\t\t\t\t\t? values.some((v) => (dep.value as string[]).includes(v))\n\t\t\t\t\t: values.includes(dep.value);\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t});\n}\n\n/** Reads `FilterConfig.defaultValue` per key. A headless helper; the provider does not call it. */\nexport function extractFilterDefaults<T extends string = string>(\n\tfilters: FilterConfig[],\n): Record<T, string> {\n\treturn filters.reduce(\n\t\t(acc, filter) => {\n\t\t\t// Force the default value to be treated as a string\n\t\t\tacc[filter.key as T] = (filter.defaultValue as string) || '';\n\t\t\treturn acc;\n\t\t},\n\t\t{} as Record<T, string>,\n\t);\n}\n","/**\n * bem-exempt: FilterProvider renders only <FilterContext.Provider>, which is\n * not a DOM node. CONVENTIONS.md §8 requires the {name}--component hook to land\n * on a real rendered element and explicitly forbids putting it on a context\n * provider. Filter chrome carries its own hooks in `partials/`.\n */\nimport {\n\tcreateContext,\n\tuseContext,\n\tuseMemo,\n\tuseCallback,\n\ttype ReactNode,\n\tuseRef,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseState,\n} from 'react';\nimport { useStrings, type StringsProp } from '../../../lib/strings';\nimport {\n\tdefaultFilterStrings,\n\tgetFilterString,\n\ttype FilterStrings,\n} from './filters.strings';\nimport {\n\tFilterType,\n\ttype FilterConfig,\n\ttype ActiveFilter,\n\ttype FilterOperator,\n\ttype FilterOption,\n\ttype FilterErrorContext,\n\ttype FilterErrorHandler,\n} from './filters.types';\nimport { resolveDefaultOperator } from './operator-options';\nimport { isCompleteDateRange, validateFilterValue } from './utils/filter-utils';\n\nexport interface FilterProviderProps {\n\tchildren: ReactNode;\n\t/** Filter definitions available to the surface. */\n\tfilters: FilterConfig[];\n\t/** Filters currently applied. */\n\tactiveFilters: ActiveFilter[];\n\t/** Fired when the change filters change. */\n\tonFilterChange: (filters: ActiveFilter[]) => void;\n\t/** Whether a filter change is still being applied. */\n\tnavigating?: boolean;\n\t/** Overrides this surface's own copy. */\n\tstrings?: StringsProp<FilterStrings>;\n\t/** Called when an async fetch, validation, apply, or render step throws.\n\t * Library DEV-logs the error; consumer wires telemetry here. */\n\tonError?: FilterErrorHandler;\n}\n\nexport interface FilterContextValue {\n\t/** Filters currently applied. */\n\tactiveFilters: ActiveFilter[];\n\t/** Filter definitions available to the surface. */\n\tfilters: FilterConfig[];\n\taddFilter: (filter: ActiveFilter) => void;\n\tremoveFilter: (id: string) => void;\n\tupdateFilter: (id: string, updates: Partial<ActiveFilter>) => void;\n\tclearFilters: () => void;\n\treplaceFilters: (filters: ActiveFilter[]) => void;\n\tgetFilterByKey: (key: string) => FilterConfig | undefined;\n\tgetFilterValue: (key: string) => string[];\n\tsetFilterValue: (key: string, value: string[]) => void;\n\tisFilterActive: (key: string) => boolean;\n\tgetFilterOperator: (key: string) => FilterOperator | undefined;\n\tsetFilterOperator: (key: string, operator: FilterOperator) => void;\n\t/**\n\t * Checks a value against the filter's `validation`: `true`, or the message\n\t * to show. Array values are checked entry by entry. The built-in editors\n\t * call this before applying a draft.\n\t */\n\tvalidateFilter: (key: string, value: unknown) => boolean | string;\n\t/**\n\t * Filters whose `dependencies` name this key. A headless helper for custom\n\t * layouts: FilterLayout does not hide or clear dependent filters itself.\n\t */\n\tgetDependentFilters: (key: string) => FilterConfig[];\n\t/** Whether a filter change is still being applied. */\n\tisNavigating: boolean;\n\t/** Overrides this surface's own copy. */\n\tstrings: FilterStrings;\n\t/** Cache resolved options for async filters (keyed by filter key → option value → FilterOption) */\n\tcacheAsyncOptions: (filterKey: string, options: FilterOption[]) => void;\n\t/** Resolve a cached label for an async filter value */\n\tgetAsyncOptionLabel: (filterKey: string, optionValue: string) => string | undefined;\n\t/** Report feature-level errors through the provider callback. */\n\treportError: FilterErrorHandler;\n}\n\nconst FilterContext = createContext<FilterContextValue | undefined>(undefined);\n\ninterface AsyncLabelCache {\n\tfetcher: NonNullable<FilterConfig['asyncConfig']>['fetcher'] | undefined;\n\tmapToOption: NonNullable<FilterConfig['asyncConfig']>['mapToOption'] | undefined;\n\tlimit: number;\n\toptions: Map<string, FilterOption>;\n}\n\ntype AsyncLabelCaches = Map<string, AsyncLabelCache>;\n\n/** One shared empty value, so an inactive filter reads the same array on every render. */\nconst EMPTY_FILTER_VALUE: string[] = [];\n\n/**\n * Label caches for the current ASYNC_SELECT filters. An entry survives a\n * recreated definition with the same fetcher and mapper, and the previous map\n * is returned when nothing changed, so an in-flight preload is not restarted.\n */\nfunction reconcileAsyncLabels(filters: FilterConfig[], previous: AsyncLabelCaches): AsyncLabelCaches {\n\tconst next: AsyncLabelCaches = new Map();\n\tfor (const filter of filters) {\n\t\tif (filter.type !== FilterType.ASYNC_SELECT) continue;\n\t\tconst fetcher = filter.asyncConfig?.fetcher;\n\t\tconst mapToOption = filter.asyncConfig?.mapToOption;\n\t\tconst limit = filter.asyncConfig?.limit ?? 10;\n\t\tconst entry = previous.get(filter.key);\n\t\tconst sameSource = entry && entry.fetcher === fetcher && entry.mapToOption === mapToOption;\n\t\tnext.set(filter.key, sameSource && entry.limit === limit\n\t\t\t? entry\n\t\t\t: { fetcher, mapToOption, limit, options: sameSource ? entry.options : new Map() });\n\t}\n\tif (next.size === previous.size && [...next].every(([key, entry]) => previous.get(key) === entry)) {\n\t\treturn previous;\n\t}\n\treturn next;\n}\n\n/** A SEARCH term of spaces, or a RANGE with both bounds open, is no filter at all. */\nfunction normalizeFilterValue(config: FilterConfig | undefined, value: string[]): string[] {\n\tif (config?.type === FilterType.RANGE) {\n\t\treturn value.some((bound) => bound.trim().length > 0) ? value : EMPTY_FILTER_VALUE;\n\t}\n\tif (value.every((entry) => entry.trim().length > 0)) return value;\n\treturn value.filter((entry) => entry.trim().length > 0);\n}\n\n/**\n * Framework-agnostic filter provider.\n * State, strings, and async option fetchers are passed by the consumer.\n */\nexport function FilterProvider({\n\tchildren,\n\tfilters,\n\tactiveFilters,\n\tonFilterChange,\n\tnavigating: isNavigatingProp = false,\n\tstrings: stringsProp,\n\tonError,\n}: FilterProviderProps) {\n\tconst filtersRef = useRef(filters);\n\tconst onFilterChangeRef = useRef(onFilterChange);\n\tconst onErrorRef = useRef(onError);\n\tonErrorRef.current = onError;\n\t// An operator chosen before its filter has a value, or a DATE `between`\n\t// that still lacks an endpoint. It is applied with the next value.\n\tconst [operatorDrafts, setOperatorDrafts] = useState(() => new Map<string, FilterOperator>());\n\t// Mirrors the drafts for handlers, so an operator and a value set in the\n\t// same handler agree before the next render.\n\tconst operatorDraftsRef = useRef(operatorDrafts);\n\tconst writeOperatorDrafts = useCallback((next: Map<string, FilterOperator>) => {\n\t\toperatorDraftsRef.current = next;\n\t\tsetOperatorDrafts(next);\n\t}, []);\n\tconst setOperatorDraft = useCallback((key: string, operator: FilterOperator) => {\n\t\twriteOperatorDrafts(new Map(operatorDraftsRef.current).set(key, operator));\n\t}, [writeOperatorDrafts]);\n\tconst clearOperatorDraft = useCallback((key: string) => {\n\t\tif (!operatorDraftsRef.current.has(key)) return;\n\t\tconst next = new Map(operatorDraftsRef.current);\n\t\tnext.delete(key);\n\t\twriteOperatorDrafts(next);\n\t}, [writeOperatorDrafts]);\n\n\t// Trigger re-render when async labels are resolved\n\tconst [asyncCacheVersion, setAsyncCacheVersion] = useState(0);\n\t// Reconciled against the caches kept in state, so the memo stays pure; the\n\t// state follows only when a definition's source or limit really changed.\n\tconst [keptAsyncLabels, setKeptAsyncLabels] = useState<AsyncLabelCaches>(() => reconcileAsyncLabels(filters, new Map()));\n\tconst asyncLabels = useMemo(() => reconcileAsyncLabels(filters, keptAsyncLabels), [filters, keptAsyncLabels]);\n\tif (asyncLabels !== keptAsyncLabels) setKeptAsyncLabels(asyncLabels);\n\n\t// The filters the consumer last received, plus the proposal made from them\n\t// in the current handler. Two writes in one handler build on each other; a\n\t// proposal the consumer refuses is dropped before the next handler runs.\n\tconst activeFiltersRef = useRef(activeFilters);\n\tconst proposalRef = useRef<{ base: ActiveFilter[]; next: ActiveFilter[] } | null>(null);\n\tconst readLatestFilters = useCallback((): ActiveFilter[] => {\n\t\tconst proposal = proposalRef.current;\n\t\treturn proposal && proposal.base === activeFiltersRef.current ? proposal.next : activeFiltersRef.current;\n\t}, []);\n\tconst proposeFilters = useCallback((next: ActiveFilter[]) => {\n\t\tconst proposal = { base: activeFiltersRef.current, next };\n\t\tproposalRef.current = proposal;\n\t\tqueueMicrotask(() => {\n\t\t\tif (proposalRef.current === proposal) proposalRef.current = null;\n\t\t});\n\t\tonFilterChangeRef.current(next);\n\t}, []);\n\tconst activeAsyncValues = JSON.stringify(activeFilters\n\t\t.filter((filter) => asyncLabels.has(filter.key))\n\t\t.map(({ key, value }) => [key, value]));\n\n\tconst strings = useStrings(defaultFilterStrings, stringsProp);\n\n\t// Update refs when prop change\n\tuseEffect(() => {\n\t\tfiltersRef.current = filters;\n\t}, [filters]);\n\n\tuseLayoutEffect(() => {\n\t\tactiveFiltersRef.current = activeFilters;\n\t\tproposalRef.current = null;\n\t}, [activeFilters]);\n\n\tuseEffect(() => {\n\t\tonFilterChangeRef.current = onFilterChange;\n\t}, [onFilterChange]);\n\n\tconst addFilter = useCallback(\n\t\t(filter: ActiveFilter) => {\n\t\t\tproposeFilters([...readLatestFilters(), filter]);\n\t\t},\n\t\t[proposeFilters, readLatestFilters],\n\t);\n\n\tconst removeFilter = useCallback(\n\t\t(id: string) => {\n\t\t\tconst latest = readLatestFilters();\n\t\t\tclearOperatorDraft(latest.find(filter => filter.id === id)?.key ?? id);\n\t\t\tproposeFilters(latest.filter(\n\t\t\t\t(f: ActiveFilter) => f.id !== id && f.key !== id,\n\t\t\t));\n\t\t},\n\t\t[clearOperatorDraft, proposeFilters, readLatestFilters],\n\t);\n\n\tconst updateFilter = useCallback(\n\t\t(id: string, updates: Partial<ActiveFilter>) => {\n\t\t\tproposeFilters(readLatestFilters().map((f: ActiveFilter) =>\n\t\t\t\tf.id === id || f.key === id ? { ...f, ...updates } : f,\n\t\t\t));\n\t\t},\n\t\t[proposeFilters, readLatestFilters],\n\t);\n\n\tconst clearFilters = useCallback(() => {\n\t\twriteOperatorDrafts(new Map());\n\t\tproposeFilters([]);\n\t}, [proposeFilters, writeOperatorDrafts]);\n\n\tconst replaceFilters = useCallback((newFilters: ActiveFilter[]) => {\n\t\twriteOperatorDrafts(new Map());\n\t\tproposeFilters(newFilters);\n\t}, [proposeFilters, writeOperatorDrafts]);\n\n\tconst getFilterByKey = useCallback(\n\t\t(key: string): FilterConfig | undefined => {\n\t\t\treturn filtersRef.current.find((f: FilterConfig) => f.key === key);\n\t\t},\n\t\t[],\n\t);\n\n\tconst getFilterValue = useCallback(\n\t\t(key: string): string[] => {\n\t\t\tconst filter = activeFilters.find(\n\t\t\t\t(f: ActiveFilter) => f.key === key,\n\t\t\t);\n\t\t\treturn filter?.value ?? EMPTY_FILTER_VALUE;\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst getFilterOperator = useCallback(\n\t\t(key: string): FilterOperator | undefined => {\n\t\t\tconst applied = activeFilters.find((filter) => filter.key === key);\n\t\t\tconst config = filters.find(filter => filter.key === key);\n\t\t\treturn operatorDrafts.get(key) ?? applied?.operator ?? resolveDefaultOperator(config);\n\t\t},\n\t\t[activeFilters, operatorDrafts, filters],\n\t);\n\n\tconst setFilterValue = useCallback(\n\t\t(key: string, rawValue: string[]) => {\n\t\t\tconst config = getFilterByKey(key);\n\t\t\tconst value = normalizeFilterValue(config, rawValue);\n\t\t\tconst existingFilter = readLatestFilters().find(\n\t\t\t\t(f: ActiveFilter) => f.key === key,\n\t\t\t);\n\t\t\tconst draftOperator = operatorDraftsRef.current.get(key);\n\t\t\tconst operator = draftOperator ?? existingFilter?.operator ?? resolveDefaultOperator(config);\n\t\t\tif (config?.type === FilterType.DATE && operator === 'between' && value.length > 0 && !isCompleteDateRange(value)) return;\n\n\t\t\tclearOperatorDraft(key);\n\t\t\tif (value.length === 0) {\n\t\t\t\t// Remove filter if the value is empty\n\t\t\t\tif (existingFilter) {\n\t\t\t\t\tremoveFilter(key);\n\t\t\t\t}\n\t\t\t} else if (existingFilter) {\n\t\t\t\tupdateFilter(key, draftOperator ? { value, operator: draftOperator } : { value });\n\t\t\t} else {\n\t\t\t\taddFilter({\n\t\t\t\t\tid: key,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue,\n\t\t\t\t\toperator,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[addFilter, clearOperatorDraft, getFilterByKey, readLatestFilters, removeFilter, updateFilter],\n\t);\n\n\tconst isFilterActive = useCallback(\n\t\t(key: string): boolean => {\n\t\t\treturn activeFilters.some(\n\t\t\t\t(f: ActiveFilter) => f.key === key && f.value.length > 0,\n\t\t\t);\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst setFilterOperator = useCallback(\n\t\t(key: string, operator: FilterOperator) => {\n\t\t\tconst existingFilter = readLatestFilters().find(\n\t\t\t\t(f: ActiveFilter) => f.key === key,\n\t\t\t);\n\t\t\tif (!existingFilter) {\n\t\t\t\t// Remembered on the pill and applied with its first value.\n\t\t\t\tsetOperatorDraft(key, operator);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (getFilterByKey(key)?.type === FilterType.DATE) {\n\t\t\t\t// Keep the applied query valid until there are two endpoints.\n\t\t\t\tif (operator === 'between' && !isCompleteDateRange(existingFilter.value)) {\n\t\t\t\t\tsetOperatorDraft(key, operator);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tclearOperatorDraft(key);\n\t\t\t\tconst value = operator === 'between' ? existingFilter.value : existingFilter.value.slice(0, 1);\n\t\t\t\tupdateFilter(key, { operator, value });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tupdateFilter(key, { operator });\n\t\t},\n\t\t[clearOperatorDraft, getFilterByKey, readLatestFilters, setOperatorDraft, updateFilter],\n\t);\n\n\tconst validateFilter = useCallback(\n\t\t(key: string, value: unknown): boolean | string => {\n\t\t\tconst filter = filtersRef.current.find(\n\t\t\t\t(f: FilterConfig) => f.key === key,\n\t\t\t);\n\t\t\tif (!filter) return false;\n\t\t\treturn validateFilterValue(filter, value, (path) =>\n\t\t\t\tgetFilterString(strings, path),\n\t\t\t);\n\t\t},\n\t\t[strings],\n\t);\n\n\tconst getDependentFilters = useCallback((key: string): FilterConfig[] => {\n\t\treturn filtersRef.current.filter((f: FilterConfig) =>\n\t\t\tf.dependencies?.some((dep: { key: string }) => dep.key === key),\n\t\t);\n\t}, []);\n\n\tconst cacheAsyncOptions = useCallback(\n\t\t(filterKey: string, options: FilterOption[]) => {\n\t\t\tconst filterMap = asyncLabels.get(filterKey)?.options;\n\t\t\tif (!filterMap) return;\n\t\t\tlet changed = false;\n\t\t\tfor (const option of options) {\n\t\t\t\tif (filterMap.get(option.value)?.label !== option.label) changed = true;\n\t\t\t\tfilterMap.set(option.value, option);\n\t\t\t}\n\t\t\tif (changed) setAsyncCacheVersion((version) => version + 1);\n\t\t},\n\t\t[asyncLabels],\n\t);\n\n\tconst getAsyncOptionLabel = useCallback(\n\t\t(filterKey: string, optionValue: string): string | undefined => {\n\t\t\treturn asyncLabels.get(filterKey)?.options.get(optionValue)?.label;\n\t\t},\n\t\t// Label consumers also memoize selected options using this callback.\n\t\t// oxlint-disable-next-line react-hooks/exhaustive-deps -- The cache version changes this identity so memoized label consumers refresh.\n\t\t[asyncLabels, asyncCacheVersion],\n\t);\n\n\tconst reportError = useCallback(\n\t\t(error: unknown, context: FilterErrorContext) => {\n\t\t\tonErrorRef.current?.(error, context);\n\t\t},\n\t\t[],\n\t);\n\n\t// Preload unresolved active ASYNC_SELECT labels, including replacement configs, so that\n\t// filter pills can display resolved labels instead of raw UUIDs.\n\tuseEffect(() => {\n\t\tconst controller = new AbortController();\n\t\tconst reportPreloadError = (error: unknown, filterKey: string) => {\n\t\t\tif (controller.signal.aborted) return;\n\t\t\tif (error && (error as { name?: string }).name === 'AbortError') return;\n\t\t\tonErrorRef.current?.(error, {\n\t\t\t\tphase: 'fetch-options',\n\t\t\t\tfilterKey,\n\t\t\t});\n\t\t};\n\n\t\tconst selectedValues = new Map<string, string[]>(JSON.parse(activeAsyncValues));\n\t\tfor (const [filterKey, cache] of asyncLabels) {\n\t\t\tconst active = selectedValues.get(filterKey);\n\t\t\tif (!active || active.length === 0) continue;\n\t\t\tconst unresolved = active.filter((value) => !cache.options.has(value));\n\t\t\tif (unresolved.length === 0) continue;\n\n\t\t\tconst { fetcher, mapToOption, limit } = cache;\n\t\t\tif (!mapToOption) continue;\n\t\t\t// Read at request time, so an inline resolver does not restart the preload.\n\t\t\tconst resolveOptions = filtersRef.current.find((filter) => filter.key === filterKey)?.asyncConfig?.resolveOptions;\n\t\t\tconst request = resolveOptions\n\t\t\t\t? resolveOptions({ values: unresolved, signal: controller.signal })\n\t\t\t\t: fetcher?.({ query: '', limit, signal: controller.signal });\n\t\t\tif (!request) continue;\n\t\t\tvoid request\n\t\t\t\t.then((items) => {\n\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\tcacheAsyncOptions(filterKey, items.map(mapToOption));\n\t\t\t\t})\n\t\t\t\t.catch((error) => reportPreloadError(error, filterKey));\n\t\t}\n\n\t\treturn () => controller.abort();\n\t}, [activeAsyncValues, asyncLabels, cacheAsyncOptions]);\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tactiveFilters,\n\t\t\tfilters,\n\t\t\taddFilter,\n\t\t\tremoveFilter,\n\t\t\tupdateFilter,\n\t\t\tclearFilters,\n\t\t\treplaceFilters,\n\t\t\tgetFilterByKey,\n\t\t\tgetFilterValue,\n\t\t\tsetFilterValue,\n\t\t\tisFilterActive,\n\t\t\tgetFilterOperator,\n\t\t\tsetFilterOperator,\n\t\t\tvalidateFilter,\n\t\t\tgetDependentFilters,\n\t\t\tisNavigating: isNavigatingProp,\n\t\t\tstrings,\n\t\t\tcacheAsyncOptions,\n\t\t\tgetAsyncOptionLabel,\n\t\t\treportError,\n\t\t}),\n\t\t[\n\t\t\tactiveFilters,\n\t\t\tfilters,\n\t\t\taddFilter,\n\t\t\tremoveFilter,\n\t\t\tupdateFilter,\n\t\t\tclearFilters,\n\t\t\treplaceFilters,\n\t\t\tgetFilterByKey,\n\t\t\tgetFilterValue,\n\t\t\tsetFilterValue,\n\t\t\tisFilterActive,\n\t\t\tgetFilterOperator,\n\t\t\tsetFilterOperator,\n\t\t\tvalidateFilter,\n\t\t\tgetDependentFilters,\n\t\t\tisNavigatingProp,\n\t\t\tstrings,\n\t\t\tcacheAsyncOptions,\n\t\t\tgetAsyncOptionLabel,\n\t\t\treportError,\n\t\t],\n\t);\n\n\treturn (\n\t\t<FilterContext.Provider value={value}>\n\t\t\t{children}\n\t\t</FilterContext.Provider>\n\t);\n}\n\nexport function useFilters() {\n\tconst context = useContext(FilterContext);\n\tif (!context) {\n\t\tthrow new Error('useFilters must be used within a FilterProvider');\n\t}\n\treturn context;\n}\n","/**\n * useFilterGroups — headless partitioning of the filter list into the four\n * groups `FilterLayout` (and any custom layout) renders distinctly:\n *\n * - `searchFilters` — `FilterType.SEARCH`, always inline\n * - `alwaysVisibleFilters` — `displayConfig.display === 'always'` and inactive\n * - `activeRegularFilters` — non-search filters that are currently active\n * - `popoverFilters` — non-search, inactive, non-always (live in \"+\" popover)\n *\n * Plus `activeFilterKeys` and `hasActive` helpers. Consumers building a\n * custom strip layout against `<FilterProvider>` can call this and place\n * each group wherever they want without re-implementing the partition\n * logic.\n *\n * `dynamicFilterOptions` (optional) lets consumers swap a filter's option\n * list at render time (e.g. async-loaded options from a parent component)\n * without mutating the provider state.\n */\nimport { useMemo } from 'react';\n\nimport { useFilters } from '../filter-context';\nimport { type FilterConfig, FilterType } from '../filters.types';\n\nexport interface UseFilterGroupsOptions {\n\t/** Override `filter.options` per-key at render time. */\n\tdynamicFilterOptions?: Record<string, FilterConfig['options']>;\n}\n\nexport interface UseFilterGroupsResult {\n\t/** Filters merged with `dynamicFilterOptions`. */\n\tprocessedFilters: FilterConfig[];\n\tsearchFilters: FilterConfig[];\n\talwaysVisibleFilters: FilterConfig[];\n\tactiveRegularFilters: FilterConfig[];\n\tpopoverFilters: FilterConfig[];\n\tactiveFilterKeys: string[];\n\thasActive: boolean;\n}\n\nexport function useFilterGroups(options: UseFilterGroupsOptions = {}): UseFilterGroupsResult {\n\tconst { dynamicFilterOptions } = options;\n\tconst { filters, isFilterActive } = useFilters();\n\n\tconst processedFilters = useMemo(() => {\n\t\tif (!dynamicFilterOptions) return filters;\n\t\treturn filters.map((filter) => {\n\t\t\tconst dyn = dynamicFilterOptions[filter.key];\n\t\t\tif (Array.isArray(dyn)) return { ...filter, options: dyn };\n\t\t\treturn filter;\n\t\t});\n\t}, [filters, dynamicFilterOptions]);\n\n\treturn useMemo(() => {\n\t\tconst searchFilters = processedFilters.filter((f) => f.type === FilterType.SEARCH);\n\t\tconst visibleFilters = processedFilters.filter(\n\t\t\t(f) => !f.displayConfig?.hidden && f.displayConfig?.display !== 'hidden',\n\t\t);\n\t\tconst activeRegularFilters = processedFilters.filter(\n\t\t\t(f) =>\n\t\t\t\tf.type !== FilterType.SEARCH\n\t\t\t\t&& !f.displayConfig?.hidden\n\t\t\t\t&& f.displayConfig?.display !== 'hidden'\n\t\t\t\t&& isFilterActive(f.key),\n\t\t);\n\t\tconst alwaysVisibleFilters = visibleFilters.filter(\n\t\t\t(f) =>\n\t\t\t\tf.type !== FilterType.SEARCH\n\t\t\t\t&& !isFilterActive(f.key)\n\t\t\t\t&& f.displayConfig?.display === 'always',\n\t\t);\n\t\tconst popoverFilters = visibleFilters.filter(\n\t\t\t(f) =>\n\t\t\t\tf.type !== FilterType.SEARCH\n\t\t\t\t&& !isFilterActive(f.key)\n\t\t\t\t&& f.displayConfig?.display !== 'always',\n\t\t);\n\t\tconst activeFilterKeys = activeRegularFilters.map((f) => f.key);\n\n\t\treturn {\n\t\t\tprocessedFilters,\n\t\t\tsearchFilters,\n\t\t\talwaysVisibleFilters,\n\t\t\tactiveRegularFilters,\n\t\t\tpopoverFilters,\n\t\t\tactiveFilterKeys,\n\t\t\thasActive: activeFilterKeys.length > 0,\n\t\t};\n\t}, [processedFilters, isFilterActive]);\n}\n","import React, { useState } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { PopoverMenu } from '../../../base/popover-menu';\nimport { DisplayLabel, Text } from '../../../typography';\nimport { cn } from '../../../../lib/utils';\n\nimport { useFilters } from '../filter-context';\nimport type { FilterOperator, OperatorOption } from '../filters.types';\nimport { getOperatorLabel } from '../operator-options';\nimport { popoverWidthRecipes } from '../../../base/popover/popover.recipes';\n\nexport interface FilterOperatorSelectProps {\n\t/** Comparison currently chosen. */\n\toperator: FilterOperator;\n\t/** Comparisons this filter offers. */\n\toperators: OperatorOption[];\n\tonOperatorChange: (operator: FilterOperator) => void;\n\t/** Keeps the menu closed, for example while a filter change is applying. */\n\tdisabled?: boolean;\n\t/** Segment-reset classes forwarded by the parent pill so the trigger\n\t * drops its base border + focus ring (it lives inside a segmented\n\t * pill, not as a standalone button). */\n\tsegmentResetClassName?: string;\n}\n\n/**\n * FilterOperatorSelect — operator dropdown for an active filter pill.\n *\n * Now delegates the trigger + popover + command-list pattern entirely to\n * `PopoverMenu`. The trigger is rendered in the pill's inline strip, the\n * `header` slot supplies the \"Operator\" display label, and item rendering\n * keeps density-tokenized padding while primary labels follow Typography.\n */\nexport function FilterOperatorSelect({\n\toperator,\n\toperators,\n\tonOperatorChange,\n\tdisabled = false,\n\tsegmentResetClassName,\n}: FilterOperatorSelectProps) {\n\tconst [open, setOpen] = useState(false);\n\tconst { strings } = useFilters();\n\n\t// An operator outside the offered list, such as one restored from a URL,\n\t// still reads as its localised name rather than its raw id.\n\tconst currentOperatorLabel =\n\t\toperators.find((op) => op.value === operator)?.label\n\t\t|| getOperatorLabel(operator, strings.operators)\n\t\t|| operator;\n\n\tconst handleTriggerClick = (e: React.MouseEvent) => {\n\t\te.stopPropagation();\n\t};\n\n\treturn (\n\t\t<PopoverMenu\n\t\t\topen={open && !disabled}\n\t\t\tonOpenChange={(next) => setOpen(next && !disabled)}\n\t\t\tsearch={false}\n\t\t\tcontentLabel={strings.operator}\n\t\t\ttrigger={\n\t\t\t\t<Button\n\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'filter-operator-select--component',\n\t\t\t\t\t\tsegmentResetClassName,\n\t\t\t\t\t\t'h-full min-h-0 px-control text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n\t\t\t\t\t)}\n\t\t\t\t\tonClick={handleTriggerClick}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t<Text tag=\"span\" type=\"inherit\">\n\t\t\t\t\t\t{currentOperatorLabel}\n\t\t\t\t\t</Text>\n\t\t\t\t</Button>\n\t\t\t}\n\t\t\theader={\n\t\t\t\t<DisplayLabel tag=\"span\">\n\t\t\t\t\t{strings.operator}\n\t\t\t\t</DisplayLabel>\n\t\t\t}\n\t\t\tcontentClassName={popoverWidthRecipes.xs}\n\t\t\titems={operators.map((op) => ({\n\t\t\t\tvalue: op.value,\n\t\t\t\tlabel: op.label,\n\t\t\t\tselected: op.value === operator,\n\t\t\t}))}\n\t\t\tonSelect={(item) => {\n\t\t\t\tonOperatorChange(item.value as FilterOperator);\n\t\t\t\tsetOpen(false);\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { CalendarIcon } from 'lucide-react';\nimport { Stack } from '../../../base/structure';\nimport { Date as DateValue, DateRange, Number as NumberValue, Value } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { layerRecipes } from '../../../../lib/layer-recipes';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport type { FilterStrings } from '../filters.strings';\nimport { interpolateFilterString } from '../filters.strings';\nimport { FilterType, type FilterConfig } from '../filters.types';\nimport { findFilterOptionPath, getFilterOptionLabel, getRangeBounds, labelInRunningText, parseFilterDate } from '../utils/filter-utils';\n\nexport interface FilterValueDisplayProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n}\n\n/**\n * Filter Value Display Component\n *\n * This component provides the UI for displaying filter values.\n * It handles:\n * - Displaying filter values with appropriate formatting\n * - Showing icons for filter options\n * - Handling date formatting\n * - Supporting internationalization\n *\n * The component is used to show users the current value of a filter\n * in a consistent and informative way.\n */\n\nexport function FilterValueDisplay({ filter, value }: FilterValueDisplayProps) {\n\tconst { strings, getFilterOperator } = useFilters();\n\n\t// Empty state — render the localized \"Nothing selected\" instead of an\n\t// empty cell so the pill never collapses to no-value text.\n\tif (value.length === 0 && filter.type !== FilterType.DATE) {\n\t\treturn (\n\t\t\t<Text tag=\"span\" type=\"secondary\" lineHeight=\"none\" className=\"filter-value-display--component\">\n\t\t\t\t{strings.nothingSelected}\n\t\t\t</Text>\n\t\t);\n\t}\n\n\tif (filter.type === FilterType.RANGE) {\n\t\tconst [min, max] = getRangeBounds(value, getFilterOperator(filter.key));\n\t\tconst summary = min && max ? `${min} – ${max}` : min ? `${strings.min} ${min}` : max ? `${strings.max} ${max}` : strings.nothingSelected;\n\t\treturn <Text tag=\"span\" type=\"inherit\" weight=\"semibold\" lineHeight=\"none\" className=\"filter-value-display--component\">{summary}</Text>;\n\t}\n\n\t// For ASYNC_SELECT — always show \"N selected\"\n\tif (filter.type === FilterType.ASYNC_SELECT && !filter.options?.length) {\n\t\treturn (\n\t\t\t<Text tag=\"span\" type=\"inherit\" weight=\"semibold\" lineHeight=\"none\" className=\"filter-value-display--component\">\n\t\t\t\t{renderAsyncValueText(filter, value, strings)}\n\t\t\t</Text>\n\t\t);\n\t}\n\n\tif (filter.options && filter.type !== FilterType.DATE) {\n\t\treturn (\n\t\t\t<Stack direction=\"horizontal\" gap=\"xs\" wrap={false} className=\"filter-value-display--component\">\n\t\t\t\t{/* Option icons - shown for both single and multi-select cases. The\n\t\t\t\t group is its own stacking context; earlier icons overlap later ones. */}\n\t\t\t\t<div className=\"relative isolate flex\">\n\t\t\t\t\t{value.slice(0, 2).map((val, index) => {\n\t\t\t\t\t\tconst option = findFilterOptionPath(filter.options, val).at(-1);\n\t\t\t\t\t\tif (!option?.icon) return null;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tkey={val}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'border-background bg-background relative rounded-full border',\n\t\t\t\t\t\t\t\t\tindex > 0 ? '-ml-space-sm z-[1]' : layerRecipes.raised,\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t\t{value.length > 2 && (\n\t\t\t\t\t\t<div className=\"bg-muted border-background relative z-0 -ml-space-sm flex size-icon items-center justify-center rounded-full border\">\n\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" weight=\"medium\">\n\t\t\t\t\t\t\t\t+<NumberValue value={value.length - 2} size=\"inherit\" align=\"center\" />\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Value text */}\n\t\t\t\t<Text tag=\"span\" type=\"inherit\" weight=\"semibold\" lineHeight=\"none\" className=\"truncate\">\n\t\t\t\t\t{renderValueText(filter, value, strings)}\n\t\t\t\t</Text>\n\t\t\t</Stack>\n\t\t);\n\t}\n\n\t// For date filters\n\tif (filter.type === FilterType.DATE) {\n\t\treturn (\n\t\t\t<Stack direction=\"horizontal\" gap=\"xs\" wrap={false} className=\"filter-value-display--component\">\n\t\t\t\t<CalendarIcon className=\"text-muted-foreground size-icon-sm\" />\n\t\t\t\t{/* One typography owner: the date primitives inside inherit its weight and leading. */}\n\t\t\t\t<Text tag=\"span\" type=\"inherit\" weight=\"semibold\" lineHeight=\"none\" className=\"min-w-0 truncate\">\n\t\t\t\t\t{renderDateValue(filter, value, strings)}\n\t\t\t\t</Text>\n\t\t\t</Stack>\n\t\t);\n\t}\n\n\t// For other filters\n\treturn (\n\t\t<Text tag=\"span\" type=\"inherit\" weight=\"semibold\" lineHeight=\"none\" className=\"filter-value-display--component truncate\">\n\t\t\t{renderValueText(filter, value, strings)}\n\t\t</Text>\n\t);\n}\n\n// Helper function to render date values\nfunction renderDateValue(\n\tfilter: FilterConfig,\n\tvalue: string[],\n\tstrings: FilterStrings,\n) {\n\tif (value.length === 1) {\n\t\treturn renderSingleDateValue(value[0], filter.dateFormat);\n\t}\n\n\tif (value.length === 2) {\n\t\treturn renderDateRangeValue(value[0], value[1], filter.dateFormat);\n\t}\n\n\treturn (\n\t\t<Value>\n\t\t\t{filter.datePickerConfig?.noDatePlaceholder || strings.calendar.notDateSelected}\n\t\t</Value>\n\t);\n}\n\n// Helper function to render text values for async filters — always \"N selected\"\nfunction renderAsyncValueText(\n\t_filter: FilterConfig,\n\tvalue: string[],\n\tstrings: FilterStrings,\n) {\n\tif (value.length === 0) return '';\n\treturn interpolateFilterString(strings.selected, { count: value.length, filterLabel: labelInRunningText((value.length > 1 ? _filter.pluralLabel : _filter.label) ?? _filter.label) });\n}\n\n// Helper function to render text values\nfunction renderValueText(\n\tfilter: FilterConfig,\n\tvalue: string[],\n\tstrings: FilterStrings,\n) {\n\tif (value.length > 1) {\n\t\treturn interpolateFilterString(strings.selected, {\n\t\t\tcount: value.length,\n\t\t\tfilterLabel: labelInRunningText(filter.pluralLabel ?? filter.label),\n\t\t});\n\t}\n\n\treturn value\n\t\t// A nested option reads as its path, such as \"Europe / Greece\".\n\t\t.map((val) => getFilterOptionLabel(filter, val) || val)\n\t\t.join(', ');\n}\n\nfunction renderSingleDateValue(rawValue: string, dateFormat?: FilterConfig['dateFormat']) {\n\tconst date = parseFilterDate(rawValue, dateFormat?.param);\n\treturn date ? <DateValue value={date} format={dateFormat?.display} /> : <Value>{rawValue}</Value>;\n}\n\nfunction renderDateRangeValue(start: string, end: string, dateFormat?: FilterConfig['dateFormat']) {\n\tconst from = parseFilterDate(start, dateFormat?.param);\n\tconst to = parseFilterDate(end, dateFormat?.param);\n\tif (from && to) {\n\t\treturn <DateRange from={from} to={to} format={dateFormat?.display} />;\n\t}\n\n\treturn (\n\t\t<span className=\"inline-flex min-w-0 items-center gap-space-xs\">\n\t\t\t{renderSingleDateValue(start, dateFormat)}\n\t\t\t<Value>–</Value>\n\t\t\t{renderSingleDateValue(end, dateFormat)}\n\t\t</span>\n\t);\n}\n","import { ChevronDown, X } from 'lucide-react';\nimport React from 'react';\nimport { Button } from '../../../base/buttons';\nimport { Text } from '../../../typography';\nimport { cn } from '../../../../lib/utils';\nimport { controlGroupHeightClasses, segmentedControlRecipes } from '../../../../lib/control-group-recipes';\nimport { focusRecipes } from '../../../../lib/focus-recipes';\nimport { useDensityConfig } from '../../../../lib/ui-provider';\nimport { resolveComponentScale } from '../../../../lib/ui-provider/scale';\nimport { regionRecipes } from '../../../../lib/surface-recipes';\nimport { useFilters } from '../filter-context';\nimport {\n\ttype FilterConfig,\n\ttype FilterOperator,\n\ttype OperatorOption,\n} from '../filters.types';\nimport { FilterOperatorSelect } from './filter-operator-select';\nimport { FilterValueDisplay } from './filter-value-display';\n\nexport interface ActiveFilterItemProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Whether the filter is currently applied. */\n\tactive: boolean;\n\t/** Whether the filter editor is open. */\n\tpopoverOpen?: boolean;\n\t/** Ref to the visible editor trigger for focus restoration. */\n\ttriggerRef?: React.Ref<HTMLButtonElement>;\n\t/** Comparisons this filter offers. */\n\toperators: OperatorOption[];\n\t/** Comparison currently chosen. */\n\toperator: FilterOperator;\n\tonOperatorChange: (operator: FilterOperator) => void;\n\t/** Fired when the clear filters change. */\n\tonFilterClear: () => void;\n\t/** Opens the value editor from either segment; the optional event identifies its focus origin. */\n\tonFilterClick: (event?: React.MouseEvent<HTMLButtonElement>) => void;\n}\n\n/**\n * Active Filter Item Component\n *\n * This component displays a single active filter in the filter list.\n * It provides:\n * - Display of filter label and value\n * - Remove filter functionality\n * - Visual feedback for active state\n * - Support for different filter types\n *\n * The component is used in the filter list to show currently active filters\n * and allow users to remove them.\n */\n\nfunction Divider() {\n\treturn <div aria-hidden className={cn('w-px self-stretch', regionRecipes.segmentDivider)} />;\n}\n\nexport function ActiveFilterItem({\n\tfilter,\n\tvalue,\n\tactive,\n\tpopoverOpen,\n\ttriggerRef,\n\toperators,\n\toperator,\n\tonOperatorChange,\n\tonFilterClear,\n\tonFilterClick,\n}: ActiveFilterItemProps) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveComponentScale(undefined, defaultScale);\n\tconst { strings, isNavigating } = useFilters();\n\tconst labelId = React.useId();\n\tconst valueId = React.useId();\n\n\t// Inside the pill, segment buttons must not paint their own border — the\n\t// pill itself is the visual container. The global `<Button>` primitive\n\t// bakes in `border border-transparent`, so without the reset every segment\n\t// paints a full 1px box (a double border just inside the pill chrome).\n\t// The pill clips its segments, so focus is the inset recipe: the shared\n\t// edge and halo drawn inside the segment, where the clip cannot cut them.\n\tconst SEGMENT_RESET =\n\t\t`${segmentedControlRecipes.joinedItem} !border-0 !rounded-none !shadow-none ${focusRecipes.inset}`;\n\n\t// Explicit 1px divider — the segment buttons use `!border-0` (so they\n\t// don't paint an inner full-box decoration) which would also wipe a\n\t// `divide-x` border. A standalone separator div is unambiguous and\n\t// doesn't fight with the buttons' baseline chrome.\n\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={filter.label}\n\t\t\taria-busy={isNavigating || undefined}\n\t\t\tdata-active={active || undefined}\n\t\t\tclassName={cn(\n\t\t\t\t'active-filter-item--component',\n\t\t\t\tsegmentedControlRecipes.joinedFrame, controlGroupHeightClasses[size], 'bg-background',\n\t\t\t\t// One dim on the chip's own box while a change is applying; its\n\t\t\t\t// segments are guarded, not disabled, so they do not dim a second time.\n\t\t\t\tisNavigating && 'pointer-events-none opacity-50',\n\t\t\t\tfilter.displayConfig?.className,\n\t\t\t)}\n\t\t>\n\t\t\t{/* Filter icon, label and dropdown button grouped together */}\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\ttone=\"secondary\"\n\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\tSEGMENT_RESET,\n\t\t\t\t\t'flex h-full min-h-0 items-center gap-space-sm px-control hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n\t\t\t\t)}\n\t\t\t\tref={triggerRef}\n\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\taria-expanded={popoverOpen}\n\t\t\t\tonClick={isNavigating ? undefined : onFilterClick}\n\t\t\t>\n\t\t\t\t{!!filter.icon && (\n\t\t\t\t\t<span className=\"flex items-center text-muted-foreground\">\n\t\t\t\t\t\t{filter.icon}\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t\t<Text id={labelId} tag=\"span\" type=\"inherit\" weight=\"semibold\">{filter.label}</Text>\n\t\t\t\t<ChevronDown className=\"size-icon-sm\" />\n\t\t\t</Button>\n\n\t\t\t<Divider />\n\n\t\t\t{/* Operator dropdown */}\n\t\t\t<FilterOperatorSelect\n\t\t\t\toperator={operator}\n\t\t\t\toperators={operators}\n\t\t\t\tonOperatorChange={onOperatorChange}\n\t\t\t\tdisabled={isNavigating}\n\t\t\t\tsegmentResetClassName={SEGMENT_RESET}\n\t\t\t/>\n\n\t\t\t<Divider />\n\n\t\t\t{/* Selected, counted and empty summaries all open the same editor. */}\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\ttone=\"secondary\"\n\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\taria-labelledby={`${labelId} ${valueId}`}\n\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\taria-expanded={popoverOpen}\n\t\t\t\tonClick={isNavigating ? undefined : onFilterClick}\n\t\t\t\tclassName={cn(SEGMENT_RESET, 'flex h-full min-h-0 min-w-0 flex-1 items-center justify-start px-control hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground')}\n\t\t\t>\n\t\t\t\t<span id={valueId} className=\"min-w-0\">\n\t\t\t\t\t<FilterValueDisplay filter={filter} value={value} />\n\t\t\t\t</span>\n\t\t\t</Button>\n\n\t\t\t{!!active && (\n\t\t\t\t<>\n\t\t\t\t\t<Divider />\n\n\t\t\t\t\t{/* Clear button */}\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\tSEGMENT_RESET,\n\t\t\t\t\t\t\t'flex h-full min-h-0 shrink-0 items-center justify-center px-space-sm text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tif (!isNavigating) onFilterClear();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X aria-hidden=\"true\" className=\"size-icon\" />\n\t\t\t\t\t\t<Text tag=\"span\" className=\"sr-only\">\n\t\t\t\t\t\t\t{strings.clear}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Button>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","/**\n * useAsyncOptions — peer-dep-free async fetcher for filter facets.\n *\n * Replaces the previous external query-client integration so the feature\n * stays framework-agnostic. Behaviour preserved:\n * - Debounced search input\n * - Min-query-length gating with an `isBelowMinQuery` flag\n * - Optional preload (empty query) with an `enabled` toggle\n * - AbortController on each new request\n * - Per-hook cache isolated by fetcher/mapper identity to avoid refetching\n * identical queries within the cache window (`staleTime`)\n * - `refetch()` for the consumer's retry button\n *\n * Consumers that want react-query semantics can compose `asyncConfig.fetcher`\n * with their own `useQuery` and pass the resulting `FilterOption[]` through\n * a controlled `options` prop on the facet — no integration code needed in\n * this library.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useDebounce } from '../../../../hooks/use-debounce';\n\nimport type {\n\tFilterConfig,\n\tFilterErrorHandler,\n\tFilterOption,\n} from '../filters.types';\n\ninterface CacheEntry {\n\t/** Formatted time for the entry. */\n\ttimestamp: number;\n\t/** Records to render. */\n\tdata: FilterOption[];\n}\n\nfunction readCacheEntry(cache: Map<string, CacheEntry>, cacheKey: string, gcTime: number): CacheEntry | undefined {\n\tfor (const [key, entry] of cache) {\n\t\tif (Date.now() - entry.timestamp > gcTime) cache.delete(key);\n\t}\n\treturn cache.get(cacheKey);\n}\n\nexport interface UseAsyncOptionsResult {\n\toptions: FilterOption[];\n\t/** Replaces the content with the loading state. */\n\tisLoading: boolean;\n\tisFetching: boolean;\n\tisError: boolean;\n\trefetch: () => void;\n\tisBelowMinQuery: boolean;\n\tminQueryLength: number;\n}\n\nexport interface UseAsyncOptionsOptions {\n\t/** Receives non-abort fetch failures after stale requests have been discarded. */\n\tonError?: FilterErrorHandler;\n}\n\nexport function useAsyncOptions(\n\tfilter: FilterConfig,\n\tsearchInput: string,\n\tisActive: boolean,\n\toptions: UseAsyncOptionsOptions = {},\n): UseAsyncOptionsResult {\n\tconst { asyncConfig } = filter;\n\tconst fetcher = asyncConfig?.fetcher;\n\tconst mapToOption = asyncConfig?.mapToOption;\n\t// oxlint-disable-next-line react-hooks/exhaustive-deps -- The key, fetcher and mapper reset the cache; the factory reads none of them.\n\tconst cache = useMemo(() => new Map<string, CacheEntry>(), [filter.key, fetcher, mapToOption]);\n\tconst onErrorRef = useRef(options.onError);\n\tonErrorRef.current = options.onError;\n\tconst debounceMs = asyncConfig?.debounceMs ?? filter.delay ?? 300;\n\tconst debouncedSearch = useDebounce(searchInput, debounceMs);\n\tconst normalisedQuery = (debouncedSearch ?? '').trim();\n\n\tconst limit = asyncConfig?.limit ?? 10;\n\tconst minQueryLength = asyncConfig?.minQueryLength ?? 0;\n\tconst preload = asyncConfig?.preload ?? true;\n\tconst staleTime = asyncConfig?.staleTime ?? 60_000;\n\tconst gcTime = asyncConfig?.gcTime ?? 300_000;\n\n\tconst isPreload = normalisedQuery.length === 0 && preload;\n\tconst meetsMinLength = normalisedQuery.length >= minQueryLength;\n\tconst hasFetcher = Boolean(asyncConfig?.fetcher);\n\tconst canFetch =\n\t\thasFetcher &&\n\t\tisActive &&\n\t\t(isPreload || (normalisedQuery.length > 0 && meetsMinLength));\n\tconst isBelowMinQuery =\n\t\tisActive &&\n\t\t!isPreload &&\n\t\tnormalisedQuery.length > 0 &&\n\t\tnormalisedQuery.length < minQueryLength;\n\n\tconst cacheKey = useMemo(() => {\n\t\tif (asyncConfig?.queryKey) {\n\t\t\treturn JSON.stringify(\n\t\t\t\tasyncConfig.queryKey({ query: normalisedQuery, limit }),\n\t\t\t);\n\t\t}\n\t\treturn JSON.stringify(['filter', filter.key, normalisedQuery, limit]);\n\t}, [asyncConfig, filter.key, normalisedQuery, limit]);\n\n\tconst queryFn = useCallback(\n\t\tasync (signal: AbortSignal): Promise<FilterOption[]> => {\n\t\t\tif (fetcher && mapToOption) {\n\t\t\t\tconst items = await fetcher({\n\t\t\t\t\tquery: normalisedQuery,\n\t\t\t\t\tlimit,\n\t\t\t\t\tsignal,\n\t\t\t\t});\n\t\t\t\treturn items.map(mapToOption);\n\t\t\t}\n\t\t\treturn [];\n\t\t},\n\t\t[fetcher, mapToOption, normalisedQuery, limit],\n\t);\n\n\tconst [state, setState] = useState<{\n\t\tcache: Map<string, CacheEntry>;\n\t\tdata: FilterOption[];\n\t\tloading: boolean;\n\t\tfetching: boolean;\n\t\terror: boolean;\n\t}>(() => {\n\t\tconst cached = readCacheEntry(cache, cacheKey, gcTime);\n\t\treturn {\n\t\t\tcache,\n\t\t\tdata: cached?.data ?? [],\n\t\t\tloading: false,\n\t\t\tfetching: false,\n\t\t\terror: false,\n\t\t};\n\t});\n\n\tconst [reloadTick, setReloadTick] = useState(0);\n\tconst refetch = useCallback(() => setReloadTick((t) => t + 1), []);\n\tconst consumedReloadRef = useRef(0);\n\n\tuseEffect(() => {\n\t\tconst force = consumedReloadRef.current !== reloadTick;\n\t\tconsumedReloadRef.current = reloadTick;\n\t\tif (!canFetch) return;\n\n\t\tconst cached = readCacheEntry(cache, cacheKey, gcTime);\n\t\tconst isFresh =\n\t\t\tcached !== undefined && Date.now() - cached.timestamp < staleTime;\n\n\t\tconst controller = new AbortController();\n\n\t\tif (isFresh && !force) {\n\t\t\tsetState({\n\t\t\t\tcache,\n\t\t\t\tdata: cached.data,\n\t\t\t\tloading: false,\n\t\t\t\tfetching: false,\n\t\t\t\terror: false,\n\t\t\t});\n\t\t\treturn () => controller.abort();\n\t\t}\n\n\t\tsetState((prev) => ({\n\t\t\tcache,\n\t\t\tdata: cached?.data ?? (prev.cache === cache ? prev.data : []),\n\t\t\tloading: cached === undefined,\n\t\t\tfetching: true,\n\t\t\terror: false,\n\t\t}));\n\n\t\tlet cancelled = false;\n\t\tqueryFn(controller.signal)\n\t\t\t.then((data) => {\n\t\t\t\tif (cancelled) return;\n\t\t\t\tcache.set(cacheKey, { timestamp: Date.now(), data });\n\t\t\t\tsetState({\n\t\t\t\t\tcache,\n\t\t\t\t\tdata,\n\t\t\t\t\tloading: false,\n\t\t\t\t\tfetching: false,\n\t\t\t\t\terror: false,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tif (cancelled || controller.signal.aborted) return;\n\t\t\t\tif (err && (err as { name?: string }).name === 'AbortError') return;\n\t\t\t\tsetState((prev) => ({\n\t\t\t\t\tcache,\n\t\t\t\t\tdata: prev.cache === cache ? prev.data : [],\n\t\t\t\t\tloading: false,\n\t\t\t\t\tfetching: false,\n\t\t\t\t\terror: true,\n\t\t\t\t}));\n\t\t\t\tonErrorRef.current?.(err, {\n\t\t\t\t\tphase: 'fetch-options',\n\t\t\t\t\tfilterKey: filter.key,\n\t\t\t\t});\n\t\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [cache, cacheKey, queryFn, canFetch, staleTime, gcTime, reloadTick, filter.key]);\n\n\treturn {\n\t\toptions: canFetch && state.cache === cache ? state.data : [],\n\t\tisLoading: canFetch && state.cache === cache && state.loading,\n\t\tisFetching: canFetch && state.cache === cache && state.fetching,\n\t\tisError: canFetch && state.cache === cache && state.error,\n\t\trefetch,\n\t\tisBelowMinQuery,\n\t\tminQueryLength,\n\t};\n}\n","/**\n * useFilterDraft — the unconfirmed value of a filter editor.\n *\n * The draft follows the applied value only when its entries change. A parent\n * that re-renders with an equal array, as polling or live data does, keeps\n * the user's unconfirmed selection.\n */\nimport { useCallback, useState } from 'react';\n\nimport { isSameFilterValue } from '../utils/filter-utils';\n\nexport function useFilterDraft(value: string[] | undefined): [draft: string[], setDraft: (next: string[]) => void] {\n\tconst [state, setState] = useState(() => ({ applied: value, draft: value ?? [] }));\n\tlet draft = state.draft;\n\tif (state.applied !== value) {\n\t\tif (!isSameFilterValue(state.applied, value)) draft = value ?? [];\n\t\tsetState({ applied: value, draft });\n\t}\n\tconst setDraft = useCallback((next: string[]) => {\n\t\tsetState((current) => ({ ...current, draft: next }));\n\t}, []);\n\treturn [draft, setDraft];\n}\n","import { Loader2 } from 'lucide-react';\n\nimport { Button } from '../../../base/buttons';\nimport { ErrorState } from '../../../base/feedback';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { useFilters } from '../filter-context';\nimport { defaultFilterStrings } from '../filters.strings';\n\ninterface AsyncOptionsStatusProps {\n\t/** A request for the current query is in flight. */\n\tfetching: boolean;\n\t/** The last request for the current query failed. */\n\terror: boolean;\n\tonRetry: () => void;\n}\n\n/**\n * Status above an async option list that still shows rows: the rows may be\n * from the previous query, so a pending search is announced and a failed one\n * offers Retry. The editor and the standalone facet share it. The pending\n * search is announced by AsyncOptionsAnnouncer, so this row carries no role.\n */\nexport function AsyncOptionsStatus({ fetching, error, onRetry }: AsyncOptionsStatusProps) {\n\tconst { strings } = useFilters();\n\tif (fetching) {\n\t\treturn (\n\t\t\t<Stack direction=\"horizontal\" gap=\"sm\" wrap={false} className=\"px-control-sm py-space-xs\">\n\t\t\t\t<Loader2 aria-hidden=\"true\" className=\"text-muted-foreground size-icon-sm animate-spin\" />\n\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">\n\t\t\t\t\t{strings.searching}\n\t\t\t\t</Text>\n\t\t\t</Stack>\n\t\t);\n\t}\n\tif (error) {\n\t\treturn (\n\t\t\t<ErrorState\n\t\t\t\tvariant=\"inline\"\n\t\t\t\ttitle={strings.fetchError}\n\t\t\t\taction={\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\tonRetry();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{strings.retryFetch}\n\t\t\t\t\t</Button>\n\t\t\t\t}\n\t\t\t/>\n\t\t);\n\t}\n\treturn null;\n}\n\ninterface AsyncOptionsAnnouncerProps {\n\t/** A request for the current query is in flight. */\n\tfetching: boolean;\n\t/** The last request for the current query failed. */\n\terror: boolean;\n\t/** Options the current query returned. */\n\tcount: number;\n\t/** The list shows rows, so its own empty status is not on screen. */\n\thasRows: boolean;\n}\n\n/**\n * One persistent polite live region for an async option list: it says a\n * search is pending while rows from the previous query are still shown, then\n * how many options the settled query found. The empty and failed states\n * announce themselves, so the region stays silent for them.\n */\nexport function AsyncOptionsAnnouncer({ fetching, error, count, hasRows }: AsyncOptionsAnnouncerProps) {\n\tconst { strings } = useFilters();\n\tconst formatCount = strings.optionsFound ?? defaultFilterStrings.optionsFound;\n\tconst message = fetching\n\t\t? (hasRows ? strings.searching : '')\n\t\t: !error && count > 0 ? formatCount?.(count) ?? '' : '';\n\treturn (\n\t\t<Text tag=\"span\" role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n\t\t\t{message}\n\t\t</Text>\n\t);\n}\n","import type { ReactNode } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { PopoverFooter } from '../../../base/popover';\nimport { Text } from '../../../typography';\nimport { useFilters } from '../filter-context';\n\ninterface FilterDraftFooterProps {\n\t/** Supporting copy on the leading edge, such as the selected count. */\n\tcaption?: ReactNode;\n\t/** Why the draft cannot be applied. Replaces the caption and disables Confirm. */\n\terror?: string;\n\tonConfirm: () => void;\n}\n\n/** Confirm footer shared by the editors that apply a draft. */\nexport function FilterDraftFooter({ caption, error, onConfirm }: FilterDraftFooterProps) {\n\tconst { strings } = useFilters();\n\treturn (\n\t\t<PopoverFooter\n\t\t\tcaption={error ? <Text tag=\"span\" size=\"xs\" type=\"error\" role=\"alert\">{error}</Text> : caption}\n\t\t>\n\t\t\t<Button tone=\"primary\" size=\"sm\" onClick={onConfirm} disabled={Boolean(error)}>\n\t\t\t\t{strings.confirm}\n\t\t\t</Button>\n\t\t</PopoverFooter>\n\t);\n}\n","import { ChevronLeft } from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { PopoverDescription, PopoverHeader, PopoverTitle } from '../../../base/popover';\nimport { useFilters } from '../filter-context';\n\ninterface FilterEditorHeaderProps {\n\t/** The filter label shown as the editor title. */\n\ttitle: ReactNode;\n\t/** Optional supporting line under the title. */\n\tdescription?: ReactNode;\n\t/** Returns to the filter list; the back button shows only when this is set. */\n\tonBack?: () => void;\n}\n\n/**\n * The one header every value editor uses — list, date and tag editors alike:\n * an optional back button and the filter label as the popover title, set in\n * the compact editor surface so every editor starts on the same band.\n */\nexport function FilterEditorHeader({ title, description, onBack }: FilterEditorHeaderProps) {\n\tconst { strings } = useFilters();\n\treturn (\n\t\t<PopoverHeader\n\t\t\tstart={onBack ? (\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\ticonOnly\n\t\t\t\t\tonClick={onBack}\n\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\taria-label={strings.backToFilters}\n\t\t\t\t>\n\t\t\t\t\t<ChevronLeft aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />\n\t\t\t\t</Button>\n\t\t\t) : undefined}\n\t\t>\n\t\t\t<PopoverTitle>{title}</PopoverTitle>\n\t\t\t{description != null && <PopoverDescription>{description}</PopoverDescription>}\n\t\t</PopoverHeader>\n\t);\n}\n","import { useEffect, useMemo, useState } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from '../../../base/command';\nimport { ErrorState, LoadingState } from '../../../base/feedback';\nimport { Text } from '../../../typography';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig, FilterOption, FilterTriggerSource } from '../filters.types';\nimport { useAsyncOptions } from '../hooks';\nimport { useFilterDraft } from '../hooks/use-filter-draft';\nimport { getFilterValidationMessage, labelInRunningText } from '../utils/filter-utils';\nimport { AsyncOptionsAnnouncer, AsyncOptionsStatus } from './async-options-status';\nimport { FilterDraftFooter } from './filter-draft-footer';\nimport { FilterEditorHeader } from './filter-editor-header';\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface AsyncFilterContentProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired when the change filters change. */\n\tonFilterChange: (value: string[]) => void;\n\tonBackToFilterList: () => void;\n\tonClose: () => void;\n\t/** Origin of the editor, which determines back-button behavior. */\n\ttriggerSource?: FilterTriggerSource;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Async Filter Content – renders inside the popover pipeline.\n *\n * Matches the layout of RegularFilterContent (header + command list + footer)\n * but fetches options asynchronously through the framework-agnostic hook.\n */\nexport function AsyncFilterContent({\n\tfilter,\n\tvalue,\n\tonFilterChange,\n\tonBackToFilterList,\n\tonClose,\n\ttriggerSource = 'chip',\n}: AsyncFilterContentProps) {\n\tconst { strings, cacheAsyncOptions, getAsyncOptionLabel, reportError } = useFilters();\n\tconst [searchInput, setSearchInput] = useState('');\n\t// The draft follows the applied value only when its entries change.\n\tconst [tempValue, setTempValue] = useFilterDraft(value);\n\n\tconst {\n\t\toptions,\n\t\tisLoading,\n\t\tisFetching,\n\t\tisError,\n\t\trefetch,\n\t\tisBelowMinQuery,\n\t\tminQueryLength,\n\t} = useAsyncOptions(filter, searchInput, true, {\n\t\tonError: reportError,\n\t});\n\n\t// Populate the shared async options cache for label resolution in FilterValueDisplay.\n\t// This updates provider state, so it must run after render.\n\tuseEffect(() => {\n\t\tif (options.length > 0) {\n\t\t\tcacheAsyncOptions(filter.key, options);\n\t\t}\n\t}, [cacheAsyncOptions, filter.key, options]);\n\n\tconst isMulti = filter.multiple !== false;\n\tconst maxSelected = filter.maxSelected;\n\tconst showBackButton = triggerSource === 'toolbar';\n\tconst isDirty = tempValue.length !== value.length || tempValue.some((item) => !value.includes(item));\n\tconst validationMessage = isDirty ? getFilterValidationMessage(filter, tempValue, strings) : undefined;\n\n\t// Sort options: selected items first, then the rest.\n\t// Also include cached selected items that may not be in current search results.\n\tconst sortedOptions = useMemo(() => {\n\t\tconst selectedSet = new Set(tempValue);\n\t\tconst optionValueSet = new Set(options.map((o) => o.value));\n\n\t\t// Selected items missing from the current results stay listed, so they\n\t\t// can be deselected: by their cached label, or by their raw value until\n\t\t// `asyncConfig.resolveOptions` or a search resolves one.\n\t\tconst missingSelected: FilterOption[] = [];\n\t\tfor (const val of tempValue) {\n\t\t\tif (!optionValueSet.has(val)) {\n\t\t\t\tconst label = getAsyncOptionLabel(filter.key, val) ?? val;\n\t\t\t\tmissingSelected.push({ value: val, label, icon: filter.icon });\n\t\t\t}\n\t\t}\n\n\t\tconst all = [...missingSelected, ...options];\n\t\treturn all.sort((a, b) => {\n\t\t\tconst aSelected = selectedSet.has(a.value) ? 0 : 1;\n\t\t\tconst bSelected = selectedSet.has(b.value) ? 0 : 1;\n\t\t\treturn aSelected - bSelected;\n\t\t});\n\t}, [options, tempValue, filter.key, filter.icon, getAsyncOptionLabel]);\n\n\tconst handleValueSelect = (optionValue: string) => {\n\t\tif (isMulti) {\n\t\t\tif (tempValue.includes(optionValue)) {\n\t\t\t\tsetTempValue(tempValue.filter((v) => v !== optionValue));\n\t\t\t} else {\n\t\t\t\tif (maxSelected && tempValue.length >= maxSelected) return;\n\t\t\t\tsetTempValue([...tempValue, optionValue]);\n\t\t\t}\n\t\t} else {\n\t\t\tsetTempValue([optionValue]);\n\t\t\tif (filter.closeOnSelect === true) {\n\t\t\t\tonFilterChange([optionValue]);\n\t\t\t\tonClose();\n\t\t\t}\n\t\t}\n\t};\n\n\tconst handleDone = () => {\n\t\tif (validationMessage) return;\n\t\tonFilterChange(tempValue);\n\t\tonClose();\n\t};\n\n\t// Render the status area inside CommandEmpty\n\tconst emptyContent = useMemo(() => {\n\t\tif (isLoading || isFetching) {\n\t\t\treturn (\n\t\t\t\t<LoadingState label={strings.searching} />\n\t\t\t);\n\t\t}\n\n\t\tif (isError) {\n\t\t\treturn (\n\t\t\t\t<ErrorState\n\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t\ttitle={strings.fetchError}\n\t\t\t\t\taction={\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\tvoid refetch();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{strings.retryFetch}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\tif (isBelowMinQuery) {\n\t\t\treturn (\n\t\t\t\t<div className=\"text-muted-foreground flex items-center justify-center py-space-xl\">\n\t\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t{interpolateFilterString(strings.minQueryHint, {\n\t\t\t\t\t\t\tmin: minQueryLength,\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Text>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\treturn strings.noOptionsFound;\n\t}, [\n\t\tisLoading,\n\t\tisFetching,\n\t\tisError,\n\t\tisBelowMinQuery,\n\t\tminQueryLength,\n\t\tstrings,\n\t\trefetch,\n\t]);\n\n\t// With no rows at all, the status takes the whole list.\n\tconst showsEmptyStatus = sortedOptions.length === 0;\n\n\treturn (\n\t\t<>\n\t\t\t{/* Header – matches RegularFilterContent */}\n\t\t\t<FilterEditorHeader title={filter.label} description={strings.selectValues} onBack={showBackButton ? onBackToFilterList : undefined} />\n\n\t\t\t{/* Command list with async search */}\n\t\t\t<Command shouldFilter={false} inset=\"flush\" className=\"rounded-none\">\n\t\t\t\t<CommandInput\n\t\t\t\t\tplaceholder={interpolateFilterString(\n\t\t\t\t\t\tstrings.searchPlaceholder,\n\t\t\t\t\t\t{ filterLabel: labelInRunningText(filter.label) },\n\t\t\t\t\t)}\n\t\t\t\t\tvalue={searchInput}\n\t\t\t\t\tonValueChange={setSearchInput}\n\t\t\t\t/>\n\t\t\t\t<CommandList aria-busy={isFetching || undefined}>\n\t\t\t\t\t{showsEmptyStatus ? (\n\t\t\t\t\t\t<CommandEmpty>{emptyContent}</CommandEmpty>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<CommandGroup>\n\t\t\t\t\t\t\t<AsyncOptionsStatus fetching={isFetching} error={isError} onRetry={refetch} />\n\t\t\t\t\t\t\t{sortedOptions.map((option) => (\n\t\t\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\t\t\t\tonSelect={() => handleValueSelect(option.value)}\n\t\t\t\t\t\t\t\t\tdata-checked={tempValue.includes(option.value) || undefined}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\toption.disabled ||\n\t\t\t\t\t\t\t\t\t\t(!!maxSelected &&\n\t\t\t\t\t\t\t\t\t\t\ttempValue.length >= maxSelected &&\n\t\t\t\t\t\t\t\t\t\t\t!tempValue.includes(option.value))\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName=\"flex items-center gap-space-sm\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t\t\t<Text tag=\"span\" type=\"inherit\" lineHeight=\"tight\">\n\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</CommandGroup>\n\t\t\t\t\t)}\n\t\t\t\t</CommandList>\n\t\t\t</Command>\n\n\t\t\t<AsyncOptionsAnnouncer fetching={isFetching} error={isError} count={options.length} hasRows={!showsEmptyStatus} />\n\n\t\t\t{/* Like static selections, confirmation only appears for a changed draft. */}\n\t\t\t{isDirty && (\n\t\t\t\t<FilterDraftFooter\n\t\t\t\t\tcaption={interpolateFilterString(strings.selected, {\n\t\t\t\t\t\tcount: tempValue.length,\n\t\t\t\t\t\tfilterLabel: labelInRunningText((tempValue.length > 1 ? filter.pluralLabel : filter.label) ?? filter.label),\n\t\t\t\t\t})}\n\t\t\t\t\terror={validationMessage}\n\t\t\t\t\tonConfirm={handleDone}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import { addDays, endOfMonth, endOfWeek, endOfYear, isValid, startOfMonth, startOfWeek, startOfYear, subMonths, subYears } from 'date-fns';\nimport { useMemo } from 'react';\nimport type { DateRange } from 'react-day-picker';\nimport {\n\t\tDatePicker,\n\t\ttype DateOutput,\n\t\ttype DateRangeOutput,\n\t\ttype PresetDateRange,\n} from '../../../base/date-pickers';\nimport { defaultDatePickerStrings } from '../../../base/date-pickers';\nimport { useDatesConfig } from '../../../../lib/ui-provider';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport type { FilterStrings } from '../filters.strings';\nimport type { FilterConfig, FilterDateShortcut, FilterOperator } from '../filters.types';\n\nconst EMPTY_PRESETS: PresetDateRange[] = [];\n\ntype WeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6;\n\n/** The range each built-in shortcut selects, relative to now. */\nconst shortcutRanges: Record<FilterDateShortcut, (now: Date, weekStartsOn: WeekStartsOn) => { from: Date; to: Date }> = {\n\ttoday: (now) => ({ from: now, to: now }),\n\tyesterday: (now) => ({ from: addDays(now, -1), to: addDays(now, -1) }),\n\tthisWeek: (now, weekStartsOn) => ({ from: startOfWeek(now, { weekStartsOn }), to: endOfWeek(now, { weekStartsOn }) }),\n\tlastSevenDays: (now) => ({ from: addDays(now, -6), to: now }),\n\tlastThirtyDays: (now) => ({ from: addDays(now, -30), to: now }),\n\tthisMonth: (now) => ({ from: startOfMonth(now), to: endOfMonth(now) }),\n\tlastMonth: (now) => ({ from: startOfMonth(subMonths(now, 1)), to: endOfMonth(subMonths(now, 1)) }),\n\tthisYear: (now) => ({ from: startOfYear(now), to: endOfYear(now) }),\n\tlastYear: (now) => ({ from: startOfYear(subYears(now, 1)), to: endOfYear(subYears(now, 1)) }),\n};\n\n/** Shortcuts labelled from the filter strings owner, in the order the filter lists them. */\nfunction buildShortcutPresets(\n\tshortcuts: readonly FilterDateShortcut[],\n\tcalendar: FilterStrings['calendar'],\n\tweekStartsOn: WeekStartsOn,\n): PresetDateRange[] {\n\treturn shortcuts.map((shortcut) => ({\n\t\tlabel: shortcut === 'thisWeek' ? calendar.thisWeek ?? defaultDatePickerStrings.thisWeek : calendar[shortcut],\n\t\tgetValue: () => shortcutRanges[shortcut](new Date(), weekStartsOn),\n\t}));\n}\n\nexport interface DateFacetProps {\n\t\t/** Definition of the filter this control edits. */\n\t\tfilter: FilterConfig;\n\t\t/** Active operator. When omitted, the standalone facet uses the filter configuration. */\n\t\toperator?: FilterOperator;\n\t\t/** Current value. */\n\t\tvalue: { start?: Date; end?: Date };\n\t\t/** Fired with the next value. */\n\t\tonValueChange: (value: { start?: Date; end?: Date }) => void;\n\t\t/** Merged onto the outermost node. */\n\t\tclassName?: string;\n}\n\nexport function DateFacet({\n\t\tfilter,\n\t\toperator,\n\t\tvalue,\n\t\tonValueChange,\n\t\tclassName,\n}: DateFacetProps) {\n\t\tconst { strings } = useFilters();\n\t\tconst { weekStartsOn } = useDatesConfig();\n\n\t\tconst isRangeMode = operator === undefined ? (\n\t\t\t\tfilter.operators?.some((op) => op.value === 'between') ||\n\t\t\t\tfilter.operator === 'between' ||\n\t\t\t\tfilter.key.toLowerCase().includes('range') ||\n\t\t\t\tfilter.key.toLowerCase().includes('between')\n\t\t) : operator === 'between';\n\n\t\tconst dateFormat = filter.dateFormat?.param ?? 'yyyy-MM-dd';\n\t\tconst readableFormat = filter.dateFormat?.display ?? 'PPP';\n\t\tconst placeholder = isRangeMode\n\t\t\t\t? (filter.datePickerConfig?.noRangePlaceholder ??\n\t\t\t\t\tfilter.placeholder ??\n\t\t\t\t\tstrings.calendar.notDateRangeSelected)\n\t\t\t\t: (filter.datePickerConfig?.noDatePlaceholder ??\n\t\t\t\t\tfilter.placeholder ??\n\t\t\t\t\tstrings.calendar.notDateSelected);\n\t\tconst withConfirm = Boolean(filter.datePickerConfig?.showConfirmButton);\n\t\tconst closeOnSelect = filter.datePickerConfig?.autoApply ?? !withConfirm;\n\t\tconst showShortcuts = filter.datePickerConfig?.showShortcuts ?? true;\n\n\t\tconst rangeValue: DateRange | undefined =\n\t\t\t\tisRangeMode && (value.start || value.end)\n\t\t\t\t\t\t? { from: value.start, to: value.end }\n\t\t\t\t\t\t: undefined;\n\n\t\tconst singleValue =\n\t\t\t\t!isRangeMode && value.start && isValid(value.start)\n\t\t\t\t\t\t? value.start\n\t\t\t\t\t\t: undefined;\n\n\t\t// The filter strings owner names the picker; `datePickerConfig.strings`\n\t\t// reaches the rest of the picker's copy for one filter.\n\t\tconst calendar = strings.calendar;\n\t\tconst configStrings = filter.datePickerConfig?.strings;\n\t\tconst pickerStrings = useMemo(() => ({\n\t\t\t\ttoday: calendar.today,\n\t\t\t\tthisMonth: calendar.thisMonth,\n\t\t\t\tlastMonth: calendar.lastMonth,\n\t\t\t\tlastYear: calendar.lastYear,\n\t\t\t\tlast30Days: calendar.lastThirtyDays,\n\t\t\t\t...(calendar.thisWeek ? { thisWeek: calendar.thisWeek } : null),\n\t\t\t\t...(calendar.from ? { from: calendar.from } : null),\n\t\t\t\t...(calendar.to ? { to: calendar.to } : null),\n\t\t\t\tselectDate: strings.selectDate,\n\t\t\t\tselectDateRange: strings.selectDateRange,\n\t\t\t\tconfirm: strings.confirm,\n\t\t\t\tclear: strings.clear,\n\t\t\t\t...configStrings,\n\t\t}), [calendar, configStrings, strings.selectDate, strings.selectDateRange, strings.confirm, strings.clear]);\n\n\t\tconst commonProps = {\n\t\t\t\tformat: dateFormat,\n\t\t\t\treadableFormat,\n\t\t\t\tplaceholder,\n\t\t\t\tstrings: pickerStrings,\n\t\t\t\tlocale: filter.datePickerConfig?.locale,\n\t\t\t\tdisablePortal: true,\n\t\t\t\tnumberOfMonths: 1,\n\t\t\t\tclassName: cn('date-facet--component', 'w-full', className),\n\t\t};\n\n\t\tconst handleSingleChange = (output: DateOutput) => {\n\t\t\t\tonValueChange({ start: output.date ?? undefined, end: undefined });\n\t\t};\n\n\t\tconst handleRangeChange = (output: DateRangeOutput) => {\n\t\t\t\tonValueChange({\n\t\t\t\t\t\tstart: output.range?.from ?? undefined,\n\t\t\t\t\t\tend: output.range?.to ?? undefined,\n\t\t\t\t});\n\t\t};\n\n\t\tif (isRangeMode) {\n\t\t\t\tconst shortcuts = filter.datePickerConfig?.shortcuts;\n\t\t\t\tconst presetsProp = !showShortcuts\n\t\t\t\t\t\t? EMPTY_PRESETS\n\t\t\t\t\t\t: filter.datePickerConfig?.presets\n\t\t\t\t\t\t\t?? (shortcuts ? buildShortcutPresets(shortcuts, calendar, weekStartsOn ?? 1) : undefined);\n\t\t\t\treturn (\n\t\t\t\t\t\t<DatePicker\n\t\t\t\t\t\t\t\tmode=\"range\"\n\t\t\t\t\t\t\t\tvalue={rangeValue}\n\t\t\t\t\t\t\t\tonValueChange={handleRangeChange}\n\t\t\t\t\t\t\t\twithConfirm={withConfirm}\n\t\t\t\t\t\t\t\tcloseOnSelect={closeOnSelect}\n\t\t\t\t\t\t\t\tpresets={presetsProp}\n\t\t\t\t\t\t\t\t{...commonProps}\n\t\t\t\t\t\t/>\n\t\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t\t<DatePicker\n\t\t\t\t\t\tmode=\"single\"\n\t\t\t\t\t\tvalue={singleValue}\n\t\t\t\t\t\tonValueChange={handleSingleChange}\n\t\t\t\t\t\tcloseOnSelect={closeOnSelect}\n\t\t\t\t\t\t{...commonProps}\n\t\t\t\t/>\n\t\t);\n}\n","import { format, isValid } from 'date-fns';\nimport { useState } from 'react';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { popoverRecipes } from '../../../base/popover/popover.recipes';\nimport { DateFacet } from '../facets/date-facet';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig, FilterOperator, FilterTriggerSource } from '../filters.types';\nimport { getFilterValidationMessage, parseFilterDate } from '../utils/filter-utils';\nimport { FilterEditorHeader } from './filter-editor-header';\n\ninterface DateFilterContentProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\toperator?: FilterOperator;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired when the change filters change. */\n\tonFilterChange: (value: string[]) => void;\n\tonBackToFilterList: () => void;\n\t/** Origin of the editor, which determines back-button behavior. */\n\ttriggerSource?: FilterTriggerSource;\n}\n\nexport function DateFilterContent({\n\tfilter,\n\toperator,\n\tvalue,\n\tonFilterChange,\n\tonBackToFilterList,\n\ttriggerSource = 'chip',\n}: DateFilterContentProps) {\n\tconst { strings } = useFilters();\n\t// The date editor applies as it is picked, so a rejected pick stays here.\n\tconst [validationMessage, setValidationMessage] = useState<string>();\n\tconst startDate = parseFilterDate(value[0], filter.dateFormat?.param);\n\tconst endDate = parseFilterDate(value[1], filter.dateFormat?.param);\n\n\t// Default date format for filter params - matches backend expectations\n\tconst defaultDateFormat = 'yyyy-MM-dd';\n\n\tconst formatOutputDate = (date?: Date) => {\n\t\tif (!date || !isValid(date)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn format(date, filter.dateFormat?.param ?? defaultDateFormat);\n\t};\n\n\tconst handleDateChange = ({ start, end }: { start?: Date; end?: Date }) => {\n\t\tconst next: string[] = [];\n\t\tconst formattedStart = formatOutputDate(start);\n\t\tconst formattedEnd = formatOutputDate(end);\n\n\t\tif (formattedStart) {\n\t\t\tnext.push(formattedStart);\n\t\t}\n\n\t\tif (formattedEnd) {\n\t\t\tnext.push(formattedEnd);\n\t\t}\n\n\t\tconst message = getFilterValidationMessage(filter, next, strings);\n\t\tsetValidationMessage(message);\n\t\tif (!message) onFilterChange(next);\n\t};\n\n\tconst showBackButton = triggerSource === 'toolbar';\n\n\tconst facetValue = { start: startDate, end: endDate };\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t<FilterEditorHeader title={filter.label} onBack={showBackButton ? onBackToFilterList : undefined} />\n\n\t\t\t<Stack gap=\"sm\" className={popoverRecipes.menuRegion}>\n\t\t\t\t<DateFacet\n\t\t\t\t\tfilter={filter}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\tvalue={facetValue}\n\t\t\t\t\tonValueChange={handleDateChange}\n\t\t\t\t/>\n\t\t\t\t{!!validationMessage && (\n\t\t\t\t\t<Text size=\"xs\" type=\"error\" role=\"alert\">\n\t\t\t\t\t\t{validationMessage}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</Stack>\n\t\t</div>\n\t);\n}\n","import { X } from 'lucide-react';\nimport { Component, type ErrorInfo, type ReactNode, useMemo } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { MonoValue } from '../../../primitives';\nimport { Text } from '../../../typography';\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport { toneRecipes } from '../../../../lib/tone-recipes';\nimport { cn } from '../../../../lib/utils';\n\nexport interface FilterErrorBoundaryProps {\n\t\tchildren: ReactNode;\n\t\t/** Key identifying which filter this content edits. */\n\t\tfilterKey?: string;\n\t\t/** Shown when the primary content is unavailable. */\n\t\tfallback?: ReactNode;\n}\n\ninterface State {\n\t\thasError: boolean;\n\t\terror: Error | null;\n}\n\ninterface FilterErrorBoundaryLabels {\n\t\t/** Surface title. */\n\t\ttitle: string;\n\t\treset: string;\n\t\tgetDescription: (filterKey?: string) => string;\n\t\tunknownError: string;\n}\n\nclass FilterErrorBoundaryBase extends Component<\n\tFilterErrorBoundaryProps & {\n\t\tlabels: FilterErrorBoundaryLabels;\n\t\tonError: (error: unknown, context: { phase: 'render'; filterKey?: string }) => void;\n\t},\n\t\tState\n> {\n\t\tpublic state: State = {\n\t\t\t\thasError: false,\n\t\t\t\terror: null,\n\t\t};\n\n\t\t/**\n\t\t * Update state when an error occurs\n\t\t */\n\t\tpublic static getDerivedStateFromError(error: Error): State {\n\t\t\t\treturn { hasError: true, error };\n\t\t}\n\n\t\t/**\n\t\t * Log the error to the console and to an error tracking service if available\n\t\t */\n\t\tpublic componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n\t\t\t\tif (import.meta.env?.DEV) {\n\t console.error('Filter error:', error, errorInfo);\n\t\t\t\t}\n\n\t\tthis.props.onError(error, {\n\t\t\tphase: 'render',\n\t\t\tfilterKey: this.props.filterKey,\n\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Reset the error state\n\t\t */\n\t\tprivate handleReset = () => {\n\t\t\t\tthis.setState({ hasError: false, error: null });\n\t\t};\n\n\t\tpublic render() {\n\t\t\t\tif (this.state.hasError) {\n\t\t\t\t\t\tconst { fallback, filterKey, labels } = this.props;\n\t\t\t\t\t\tif (fallback) {\n\t\t\t\treturn <div className=\"filter-error-boundary--component contents\">{fallback}</div>;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t<div className={cn('filter-error-boundary--component rounded-radius border p-surface-xs', toneRecipes.destructive.edge, toneRecipes.destructive.wash, toneRecipes.destructive.ink)}>\n\t\t\t\t\t\t\t\t\t\t<div className=\"mb-space-xs flex items-center justify-between\">\n\t\t\t\t\t\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"semibold\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{labels.title}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttone=\"destructive\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={this.handleReset}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label={labels.reset}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<X className=\"size-icon-sm\" />\n\t\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t<Text>{labels.getDescription(filterKey)}</Text>\n\t\t\t\t\t\t\t\t\t\t{/* Exception text is for the developer; production users see the localised copy above. */}\n\t\t\t\t\t\t\t\t\t\t{Boolean(import.meta.env?.DEV) && (\n\t\t\t\t\t\t\t\t\t\t\t\t<MonoValue size=\"xs\" className=\"mt-space-xs text-destructive\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{this.state.error?.message || labels.unknownError}\n\t\t\t\t\t\t\t\t\t\t\t\t</MonoValue>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t);\n\t\t\t\t}\n\n\t\treturn <div className=\"filter-error-boundary--component contents\">{this.props.children}</div>;\n\t\t}\n}\n\nexport function FilterErrorBoundary(props: FilterErrorBoundaryProps) {\n\t\tconst { strings, reportError } = useFilters();\n\n\t\tconst labels = useMemo<FilterErrorBoundaryLabels>(\n\t\t\t\t() => ({\n\t\t\t\t\t\ttitle: strings.error.title,\n\t\t\t\t\t\treset: strings.error.dismiss ?? strings.clear,\n\t\t\t\t\t\tgetDescription: (filterKey?: string) =>\n\t\t\t\t\t\t\t\tfilterKey\n\t\t\t\t\t\t\t\t\t\t? interpolateFilterString(strings.error.descriptionWithKey, {\n\t\t\t\t\t\t\t\t\t\t\t\t\tfilterKey,\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t: strings.error.generic,\n\t\t\t\t\t\tunknownError: strings.error.unknown,\n\t\t\t\t}),\n\t\t\t\t[strings],\n\t\t);\n\n\treturn <FilterErrorBoundaryBase {...props} labels={labels} onError={reportError} />;\n}\n","import { CommandItem } from '../../../base/command';\nimport { Text } from '../../../typography';\nimport { useFilters } from '../filter-context';\nimport { formatFilterCount } from '../filters.strings';\nimport { FilterType, type FilterConfig } from '../filters.types';\n\ninterface FilterListItemProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Fired when an entry is activated. */\n\tonSelect: () => void;\n}\n\n/**\n * FilterListItem — single row inside the Filters-button menu.\n *\n * Shows a leading icon (rendered as-is so its native colour comes through),\n * the filter label as the primary line, and a secondary \"{n} options\" line\n * for SELECT-style filters or the \"select date range\" hint for DATE filters.\n *\n * All typography flows through the base Text component so the global\n * scale + theming applies consistently.\n */\nexport function FilterListItem({ filter, onSelect }: FilterListItemProps) {\n\tconst { strings } = useFilters();\n\n\tconst subtitle =\n\t\tfilter.type === FilterType.DATE\n\t\t\t? filter.operator === 'between'\n\t\t\t\t? strings?.selectDateRange\n\t\t\t\t: strings?.selectDate\n\t\t\t: filter.options\n\t\t\t\t? formatFilterCount(strings.optionCount, filter.options.length, strings.options)\n\t\t\t\t: null;\n\n\treturn (\n\t\t<CommandItem\n\t\t\tkey={filter.key}\n\t\t\tonSelect={onSelect}\n\t\t>\n\t\t\t{!!filter.icon && (\n\t\t\t\t<span className=\"shrink-0 text-muted-foreground [&_svg]:size-icon\">{filter.icon}</span>\n\t\t\t)}\n\t\t\t<div className=\"flex min-w-0 flex-col gap-dense leading-tight\">\n\t\t\t\t<Text tag=\"span\" type=\"inherit\" lineHeight=\"tight\" weight=\"medium\" className=\"truncate\">\n\t\t\t\t\t{filter.label}\n\t\t\t\t</Text>\n\t\t\t\t{!!subtitle && (\n\t\t\t\t\t<Text tag=\"span\" lineHeight=\"tight\" size=\"xs\" type=\"secondary\" className=\"truncate\">\n\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t</Text>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</CommandItem>\n\t);\n}\n","import {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandList,\n\tCommandSeparator,\n} from '../../../base/command';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig } from '../filters.types';\nimport { FilterListItem } from './filter-list-item';\n\ninterface FilterListContentProps {\n\t/** Filters the user may add. */\n\tavailableFilters: FilterConfig[];\n\t/** Filters currently applied. */\n\tactiveFilters: FilterConfig[];\n\t/** Fired when the select filters change. */\n\tonFilterSelect: (filter: FilterConfig) => void;\n}\n\n/**\n * Filter Popover Content Component\n *\n * This component provides the content wrapper for filter popovers.\n * It handles:\n * - Consistent popover styling\n * - Content layout and spacing\n * - Responsive behavior\n * - Animation and transitions\n *\n * The component is used to wrap filter content in a consistent\n * popover interface across different filter types.\n */\n\nexport function FilterListContent({\n\tavailableFilters,\n\tactiveFilters,\n\tonFilterSelect,\n}: FilterListContentProps) {\n\tconst { strings } = useFilters();\n\n\t// Handle filter selection with explicit closing of popover\n\tconst handleFilterSelect = (filter: FilterConfig) => {\n\t\t// Call the passed onFilterSelect with the filter\n\t\tonFilterSelect(filter);\n\t};\n\n\treturn (\n\t\t<Command inset=\"compact\" className=\"rounded-none\">\n\t\t\t<CommandInput placeholder={strings.searchFilters} />\n\t\t\t<CommandList>\n\t\t\t\t<CommandEmpty>\n\t\t\t\t\t{strings.noFiltersAvailable}\n\t\t\t\t</CommandEmpty>\n\n\t\t\t\t{availableFilters.length > 0 && (\n\t\t\t\t\t<CommandGroup heading={strings.availableFilters}>\n\t\t\t\t\t\t{availableFilters.map((filter) => (\n\t\t\t\t\t\t\t<FilterListItem\n\t\t\t\t\t\t\t\tkey={filter.key}\n\t\t\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\t\t\tonSelect={() => handleFilterSelect(filter)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</CommandGroup>\n\t\t\t\t)}\n\n\t\t\t\t{activeFilters.length > 0 && (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<CommandSeparator />\n\t\t\t\t\t\t<CommandGroup heading={strings.activeFilters}>\n\t\t\t\t\t\t\t{activeFilters.map((filter) => (\n\t\t\t\t\t\t\t\t<FilterListItem\n\t\t\t\t\t\t\t\t\tkey={filter.key}\n\t\t\t\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\t\t\t\tonSelect={() => handleFilterSelect(filter)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</CommandGroup>\n\t\t\t\t\t</>\n\t\t\t\t)}\n\t\t\t</CommandList>\n\t\t</Command>\n\t);\n}\n","import { useState, useEffect, useId, type ChangeEvent } from 'react';\nimport { Input } from '../../../base/text-inputs';\nimport { Grid, Stack } from '../../../base/structure';\nimport { Label, Text } from '../../../typography';\nimport { DEFAULT_DEBOUNCE_MS, useDebouncedCallback } from '../../../../hooks/use-debounced-callback';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig } from '../filters.types';\nimport { getFilterValidationMessage } from '../utils/filter-utils';\n\nexport interface RangeFacetProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: { min?: number; max?: number };\n\t/** Fired with the next value. */\n\tonValueChange: (value: { min?: number; max?: number }) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\n/** A bound while it is being typed: digits with an optional sign and decimal point. */\nconst BOUND_INPUT = /^-?\\d*\\.?\\d*$/;\n\n/** The number a typed bound stands for; an empty or unfinished bound such as \"-\" or \".\" is open. */\nfunction parseBound(text: string): number | undefined {\n\tif (text.trim() === '') return undefined;\n\tconst bound = Number(text);\n\treturn Number.isFinite(bound) ? bound : undefined;\n}\n\n/**\n * Range Filter Facet\n *\n * A numeric range with a minimum and a maximum bound. Either bound may be\n * left open, and negative and decimal numbers are accepted. The facet emits\n * `{ min, max }` after the filter's `delay`, with `undefined` for an open\n * bound, and follows external changes to `value` while it is not focused\n * and the provider is not navigating.\n *\n * A range whose minimum exceeds its maximum, or that falls outside\n * `filter.validation.min`/`max`, is marked invalid with its message and is\n * not emitted.\n */\n\nexport function RangeFacet({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: RangeFacetProps) {\n\tconst { strings, isNavigating } = useFilters();\n\tconst [minValue, setMinValue] = useState<string>(\n\t\tvalue.min?.toString() ?? '',\n\t);\n\tconst [maxValue, setMaxValue] = useState<string>(\n\t\tvalue.max?.toString() ?? '',\n\t);\n\tconst [focused, setFocused] = useState(false);\n\tconst min = parseBound(minValue);\n\tconst max = parseBound(maxValue);\n\n\t// The range last reconciled with the parent, and the `value` last rendered.\n\tconst [emitted, setEmitted] = useState<{ min?: number; max?: number }>({ min: value.min, max: value.max });\n\tconst [seen, setSeen] = useState({ min: value.min, max: value.max });\n\tconst valueChanged = seen.min !== value.min || seen.max !== value.max;\n\tif (valueChanged) setSeen({ min: value.min, max: value.max });\n\n\t// Follow an external value, such as Clear filters, once the user is not\n\t// typing. An echo of this facet's own emission never replaces newer input,\n\t// and input that has not been emitted yet yields only to a real change.\n\tconst differsFromInput = min !== value.min || max !== value.max;\n\tconst differsFromEmitted = emitted.min !== value.min || emitted.max !== value.max;\n\tconst inputSettled = min === emitted.min && max === emitted.max;\n\tif (!focused && !isNavigating && differsFromInput && differsFromEmitted && (inputSettled || valueChanged)) {\n\t\tsetMinValue(value.min?.toString() ?? '');\n\t\tsetMaxValue(value.max?.toString() ?? '');\n\t\tsetEmitted({ min: value.min, max: value.max });\n\t}\n\n\tconst reversed = min !== undefined && max !== undefined && min > max;\n\tconst error = reversed\n\t\t? strings.validation.invalidFormat\n\t\t: min === undefined && max === undefined\n\t\t\t? undefined\n\t\t\t: getFilterValidationMessage(filter, [min === undefined ? '' : String(min), max === undefined ? '' : String(max)], strings);\n\n\t// `useDebouncedCallback` reads `value` and `onValueChange` at fire time, so\n\t// the effect below stays dep-light and never re-runs on an inline callback's\n\t// changing identity.\n\tconst emitRange = useDebouncedCallback(\n\t\t(next: { min?: number; max?: number }) => {\n\t\t\tsetEmitted(next);\n\t\t\tif (next.min !== value.min || next.max !== value.max) {\n\t\t\t\tonValueChange(next);\n\t\t\t}\n\t\t},\n\t\tfilter.delay ?? DEFAULT_DEBOUNCE_MS,\n\t);\n\n\tuseEffect(() => {\n\t\tif (error) return emitRange.cancel;\n\t\temitRange({ min, max });\n\n\t\treturn emitRange.cancel;\n\t}, [min, max, error, emitRange]);\n\n\tconst handleMinChange = (e: ChangeEvent<HTMLInputElement>) => {\n\t\tif (BOUND_INPUT.test(e.target.value)) setMinValue(e.target.value);\n\t};\n\n\tconst handleMaxChange = (e: ChangeEvent<HTMLInputElement>) => {\n\t\tif (BOUND_INPUT.test(e.target.value)) setMaxValue(e.target.value);\n\t};\n\n\treturn (\n\t\t<RangeFacetFields\n\t\t\tmin={minValue}\n\t\t\tmax={maxValue}\n\t\t\tonMinChange={handleMinChange}\n\t\t\tonMaxChange={handleMaxChange}\n\t\t\tonFocusChange={setFocused}\n\t\t\tclassName={className}\n\t\t\tinvalid={Boolean(error)}\n\t\t\terror={error}\n\t\t/>\n\t);\n}\n\ninterface RangeFacetFieldsProps {\n\tmin: string;\n\tmax: string;\n\tonMinChange: (event: ChangeEvent<HTMLInputElement>) => void;\n\tonMaxChange: (event: ChangeEvent<HTMLInputElement>) => void;\n\tclassName?: string;\n\tinvalid?: boolean;\n\t/** Message for an invalid range, announced under the fields and tied to both inputs. */\n\terror?: string;\n\t/** Reports whether focus is inside the fields. */\n\tonFocusChange?: (focused: boolean) => void;\n}\n\n/** The public facet and the Confirm editor share the same field anatomy. */\nexport function RangeFacetFields({ min, max, onMinChange, onMaxChange, className, invalid, error, onFocusChange }: RangeFacetFieldsProps) {\n\tconst { strings } = useFilters();\n\tconst instanceId = useId();\n\tconst errorId = error ? `${instanceId}-error` : undefined;\n\treturn (\n\t\t<Stack\n\t\t\tgap=\"md\"\n\t\t\tclassName={cn('range-facet--component', className)}\n\t\t\tonFocus={onFocusChange ? () => onFocusChange(true) : undefined}\n\t\t\tonBlur={onFocusChange ? (event) => {\n\t\t\t\tif (!event.currentTarget.contains(event.relatedTarget)) onFocusChange(false);\n\t\t\t} : undefined}\n\t\t>\n\t\t\t<Grid columns={{ base: 1, sm: 2 }} gap=\"md\">\n\t\t\t\t<Stack gap=\"xs\">\n\t\t\t\t\t<Label htmlFor={`${instanceId}-min`} className=\"text-inherit\">\n\t\t\t\t\t\t{strings.min}\n\t\t\t\t\t</Label>\n\t\t\t\t\t<Input\n\t\t\t\t\t\tid={`${instanceId}-min`}\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tinputMode=\"decimal\"\n\t\t\t\t\t\tvalue={min}\n\t\t\t\t\t\tonChange={onMinChange}\n\t\t\t\t\t\taria-invalid={invalid || undefined}\n\t\t\t\t\t\taria-describedby={errorId}\n\t\t\t\t\t\tplaceholder={strings.min}\n\t\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\t/>\n\t\t\t\t</Stack>\n\t\t\t\t<Stack gap=\"xs\">\n\t\t\t\t\t<Label htmlFor={`${instanceId}-max`} className=\"text-inherit\">\n\t\t\t\t\t\t{strings.max}\n\t\t\t\t\t</Label>\n\t\t\t\t\t<Input\n\t\t\t\t\t\tid={`${instanceId}-max`}\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tinputMode=\"decimal\"\n\t\t\t\t\t\tvalue={max}\n\t\t\t\t\t\tonChange={onMaxChange}\n\t\t\t\t\t\taria-invalid={invalid || undefined}\n\t\t\t\t\t\taria-describedby={errorId}\n\t\t\t\t\t\tplaceholder={strings.max}\n\t\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\t/>\n\t\t\t\t</Stack>\n\t\t\t</Grid>\n\t\t\t{!!error && (\n\t\t\t\t<Text id={errorId} size=\"xs\" type=\"error\" role=\"alert\">\n\t\t\t\t\t{error}\n\t\t\t\t</Text>\n\t\t\t)}\n\t\t</Stack>\n\t);\n}\n","import { useEffect, useState } from 'react';\nimport { popoverRecipes } from '../../../base/popover/popover.recipes';\nimport { RangeFacetFields } from '../facets/range-facet';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig, FilterOperator, FilterTriggerSource } from '../filters.types';\nimport { getFilterValidationMessage, getRangeBounds } from '../utils/filter-utils';\nimport { FilterDraftFooter } from './filter-draft-footer';\nimport { FilterEditorHeader } from './filter-editor-header';\n\ninterface RangeFilterContentProps {\n\tfilter: FilterConfig;\n\toperator: FilterOperator;\n\tvalue: string[];\n\tonFilterChange: (value: string[]) => void;\n\tonBackToFilterList: () => void;\n\tonClose: () => void;\n\ttriggerSource: FilterTriggerSource;\n}\n\nfunction parseBound(value: string): string | undefined {\n\tconst trimmed = value.trim();\n\tif (!trimmed) return '';\n\tif (!/^-?(?:\\d+\\.?\\d*|\\.\\d+)$/.test(trimmed)) return undefined;\n\tconst bound = Number(trimmed);\n\treturn Number.isFinite(bound) ? trimmed : undefined;\n}\n\nexport function RangeFilterContent({ filter, operator, value, onFilterChange, onBackToFilterList, onClose, triggerSource }: RangeFilterContentProps) {\n\tconst { strings, reportError } = useFilters();\n\tconst [appliedMin, appliedMax] = getRangeBounds(value, operator);\n\tconst [min, setMin] = useState(appliedMin);\n\tconst [max, setMax] = useState(appliedMax);\n\n\tuseEffect(() => {\n\t\tsetMin(appliedMin);\n\t\tsetMax(appliedMax);\n\t}, [appliedMin, appliedMax]);\n\n\tconst nextMin = parseBound(min);\n\tconst nextMax = parseBound(max);\n\tconst malformed = nextMin === undefined || nextMax === undefined ||\n\t\t(Boolean(nextMin && nextMax) && Number(nextMin) > Number(nextMax));\n\tconst dirty = min !== appliedMin || max !== appliedMax;\n\tconst validationMessage = malformed\n\t\t? strings.validation.invalidFormat\n\t\t: dirty ? getFilterValidationMessage(filter, nextMin || nextMax ? [nextMin, nextMax] : [], strings) : undefined;\n\tconst invalid = Boolean(validationMessage);\n\n\tfunction confirm() {\n\t\tif (invalid || nextMin === undefined || nextMax === undefined) return;\n\t\ttry {\n\t\t\tonFilterChange(nextMin || nextMax ? [nextMin, nextMax] : []);\n\t\t\tonClose();\n\t\t} catch (error) {\n\t\t\treportError(error, { phase: 'apply', filterKey: filter.key });\n\t\t}\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t<FilterEditorHeader title={filter.label} onBack={triggerSource === 'toolbar' ? onBackToFilterList : undefined} />\n\t\t\t<div className={popoverRecipes.menuRegion}>\n\t\t\t\t<RangeFacetFields\n\t\t\t\t\tmin={min}\n\t\t\t\t\tmax={max}\n\t\t\t\t\tonMinChange={(event) => setMin(event.target.value)}\n\t\t\t\t\tonMaxChange={(event) => setMax(event.target.value)}\n\t\t\t\t\tinvalid={invalid}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t\t{dirty && (\n\t\t\t\t<FilterDraftFooter error={validationMessage} onConfirm={confirm} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useMemo, type ReactNode } from 'react';\n\nimport { CascaderPanel, defaultCascaderStrings, useCascaderController } from '../../../base/cascader/cascader-panel';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig } from '../filters.types';\nimport { labelInRunningText, toCascaderNodes } from '../utils/filter-utils';\n\ninterface NestedFilterOptionsProps {\n\t/** Definition of the filter this control edits; its options nest `children`. */\n\tfilter: FilterConfig;\n\t/** Current draft value. */\n\tvalue: string[];\n\t/** Whether several options can be chosen. */\n\tmultiple: boolean;\n\t/** Receives the next draft value. */\n\tonChange: (value: string[]) => void;\n\t/** The editor's header, shown at the root level; a drilled level shows its own header and path instead. */\n\theader: ReactNode;\n}\n\n/**\n * NestedFilterOptions — the SELECT / MULTI_SELECT editor body for options with\n * `children`. It shows one level at a time through the shared cascader panel,\n * with path search across every level, inside the filter's own popover.\n */\nexport function NestedFilterOptions({ filter, value, multiple, onChange, header }: NestedFilterOptionsProps) {\n\tconst { strings } = useFilters();\n\tconst items = useMemo(() => toCascaderNodes(filter.options ?? []), [filter.options]);\n\tconst controller = useCascaderController({\n\t\titems,\n\t\tselected: value,\n\t\topen: true,\n\t\tmultiple,\n\t\tselectable: filter.selectableOptions ?? 'leaf',\n\t\tstrings: {\n\t\t\t...defaultCascaderStrings,\n\t\t\troot: filter.label,\n\t\t\tsearch: interpolateFilterString(strings.searchPlaceholder, { filterLabel: labelInRunningText(filter.label) }),\n\t\t\tempty: strings.noOptionsFound,\n\t\t\tback: strings.previousLevel,\n\t\t\tselectCurrent: strings.selectCurrentLevel,\n\t\t},\n\t\tonChange: (next) => onChange(next == null ? [] : typeof next === 'string' ? [next] : [...next]),\n\t});\n\treturn <CascaderPanel controller={controller} header={header} rootInPath className=\"nested-filter-options--component\" />;\n}\n","import { Stack } from '../../../base/structure';\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from '../../../base/command';\nimport { Text } from '../../../typography';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig, FilterTriggerSource } from '../filters.types';\nimport { useFilterDraft } from '../hooks/use-filter-draft';\nimport { getFilterValidationMessage, hasNestedFilterOptions, isMultiValueFilter, labelInRunningText } from '../utils/filter-utils';\nimport { FilterDraftFooter } from './filter-draft-footer';\nimport { NestedFilterOptions } from './nested-filter-options';\nimport { FilterEditorHeader } from './filter-editor-header';\n\ninterface RegularFilterContentProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired when the change filters change. */\n\tonFilterChange: (value: string[]) => void;\n\tonBackToFilterList: () => void;\n\tonClose: () => void;\n\t/** Origin of the editor, which determines back-button behavior. */\n\ttriggerSource?: FilterTriggerSource;\n}\n\n/**\n * RegularFilterContent — popover body for SELECT / MULTI_SELECT filters.\n *\n * Layout:\n * - Compact header: optional back-arrow and shared primary title.\n * - Inline search input (only if the filter has more than 5 options).\n * - Tight list of options whose primary labels inherit the Typography default.\n * - Compact footer: selected count on the leading edge, Confirm button on\n * the trailing edge — only rendered when the user has changed selection.\n *\n * Sizes are tuned to feel like a native menu, not a card. Popover width\n * stays at ~260-300px so labels read at one glance. Options with `children`\n * replace the flat list with one level at a time (NestedFilterOptions).\n */\nexport function RegularFilterContent({\n\tfilter,\n\tvalue,\n\tonFilterChange,\n\tonBackToFilterList,\n\tonClose,\n\ttriggerSource = 'chip',\n}: RegularFilterContentProps) {\n\tconst { strings, reportError } = useFilters();\n\n\tconst isMultiSelect = isMultiValueFilter(filter);\n\tconst showBackButton = triggerSource === 'toolbar';\n\n\tconst [tempValue, setTempValue] = useFilterDraft(value);\n\tconst atMaxSelected = isMultiSelect && !!filter.maxSelected && tempValue.length >= filter.maxSelected;\n\n\tconst handleValueSelect = (optionValue: string) => {\n\t\tif (isMultiSelect) {\n\t\t\tconst isSelected = tempValue.includes(optionValue);\n\t\t\tif (!isSelected && atMaxSelected) return;\n\t\t\tconst newValue = isSelected\n\t\t\t\t? tempValue.filter((v) => v !== optionValue)\n\t\t\t\t: [...tempValue, optionValue];\n\t\t\tsetTempValue(newValue);\n\t\t} else {\n\t\t\tsetTempValue([optionValue]);\n\n\t\t\tif (filter.closeOnSelect === true) {\n\t\t\t\tonFilterChange([optionValue]);\n\t\t\t\tonClose();\n\t\t\t}\n\t\t}\n\t};\n\n\t// A nested editor reports the complete next value rather than one toggled option.\n\tconst handleNestedChange = (nextValue: string[]) => {\n\t\tsetTempValue(nextValue);\n\t\tif (!isMultiSelect && filter.closeOnSelect === true && nextValue.length) {\n\t\t\tonFilterChange(nextValue);\n\t\t\tonClose();\n\t\t}\n\t};\n\n\tconst handleDone = () => {\n\t\tif (validationMessage) return;\n\t\ttry {\n\t\t\tonFilterChange(tempValue);\n\t\t\tonClose();\n\t\t} catch (error) {\n\t\t\tif (import.meta.env?.DEV) {\n\t console.error('Error applying filter:', error);\n\t\t\t}\n\t\t\treportError(error, { phase: 'apply', filterKey: filter.key });\n\t\t}\n\t};\n\n\t// SECTION 1 — Label header. Nested options show it at their root level only.\n\tconst header = (\n\t\t<FilterEditorHeader title={filter.label} onBack={showBackButton ? onBackToFilterList : undefined} />\n\t);\n\n\tconst isDirty = JSON.stringify(tempValue.slice().sort()) !== JSON.stringify((value ?? []).slice().sort());\n\tconst validationMessage = isDirty ? getFilterValidationMessage(filter, tempValue, strings) : undefined;\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\n\t\t\t{hasNestedFilterOptions(filter.options) ? (\n\t\t\t\t<NestedFilterOptions filter={filter} value={tempValue} multiple={isMultiSelect} onChange={handleNestedChange} header={header} />\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t{header}\n\t\t\t\t<Command inset=\"flush\" className=\"rounded-none\">\n\t\t\t\t\t{/* SECTION 2 — Search. The search row owns its inset; the\n\t\t\t\t\t\tcollection below owns the compact surface inset. */}\n\t\t\t\t\t<CommandInput\n\t\t\t\t\t\tplaceholder={interpolateFilterString(\n\t\t\t\t\t\t\tstrings.searchPlaceholder,\n\t\t\t\t\t\t\t{ filterLabel: labelInRunningText(filter.label) },\n\t\t\t\t\t\t)}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{/* SECTION 3 — Values list.\n\t\t\t\t\t\tSame tokenized outer padding as the other two sections.\n\t\t\t\t\t\tItems inside have additional inner padding so option\n\t\t\t\t\t\tlabels are slightly more indented than the section frame —\n\t\t\t\t\t\tthat's what tells the eye \"these are list rows, not header text\". */}\n\t\t\t\t\t<CommandList>\n\t\t\t\t\t\t<CommandEmpty>\n\t\t\t\t\t\t\t<Text type=\"secondary\" align=\"center\" className=\"py-space-xl\">\n\t\t\t\t\t\t\t\t{strings.noOptionsFound}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t</CommandEmpty>\n\t\t\t\t\t\t<CommandGroup>\n\t\t\t\t\t\t\t{filter.options?.map((option) => {\n\t\t\t\t\t\t\t\tconst isSelected = tempValue.includes(option.value);\n\t\t\t\t\t\t\t\t// data-checked toggles the CommandItem's built-in\n\t\t\t\t\t\t\t\t// CheckIcon (rendered after children with ml-auto).\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\t\t\t\t\tonSelect={() => handleValueSelect(option.value)}\n\t\t\t\t\t\t\t\t\t\tdata-checked={isSelected || undefined}\n\t\t\t\t\t\t\t\t\t\tdisabled={option.disabled || (atMaxSelected && !isSelected)}\n\t\t\t\t\t\t\t\t\t\tclassName=\"data-[checked=true]:**:[svg]:text-primary-accent\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{!!option.icon && (\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 text-muted-foreground [&_svg]:size-icon\">\n\t\t\t\t\t\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t<Stack gap=\"dense\" className=\"flex min-w-0 flex-1 flex-col leading-tight\">\n\t\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"inherit\"\n\t\t\t\t\t\t\t\t\t\t\t\tlineHeight=\"tight\"\n\t\t\t\t\t\t\t\t\t\t\t\tweight={isSelected ? 'medium' : 'regular'}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t{!!option.description && (\n\t\t\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tlineHeight=\"tight\"\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{option.description}\n\t\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</CommandGroup>\n\t\t\t\t\t</CommandList>\n\t\t\t\t</Command>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t{/* Compact footer — only shows when dirty */}\n\t\t\t{!!isDirty && (\n\t\t\t\t<FilterDraftFooter\n\t\t\t\t\tcaption={interpolateFilterString(strings.selected, {\n\t\t\t\t\t\tcount: tempValue.length,\n\t\t\t\t\t\tfilterLabel: labelInRunningText((tempValue.length > 1 ? filter.pluralLabel : filter.label) ?? filter.label),\n\t\t\t\t\t})}\n\t\t\t\t\terror={validationMessage}\n\t\t\t\t\tonConfirm={handleDone}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { X, Plus } from 'lucide-react';\nimport React, { useState, useCallback, type KeyboardEvent } from 'react';\nimport { Badge } from '../../../base/badge';\nimport { Button } from '../../../base/buttons';\nimport { Input } from '../../../base/text-inputs';\nimport { formControlSizeClasses, resolveFormControlSize } from '../../../base/forms/form-sizing';\nimport { controlGroupSquareClasses } from '../../../../lib/control-group-recipes';\nimport { fieldAffordanceRecipes } from '../../../../lib/field-affordance-recipes';\nimport { useDensityConfig } from '../../../../lib/ui-provider';\nimport { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport { formatFilterCount } from '../filters.strings';\nimport type { FilterConfig } from '../filters.types';\n\nexport interface TagsFacetProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired with the next value. */\n\tonValueChange: (value: string[]) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\n/**\n * Tags Filter Facet\n *\n * This component implements a tags input filter that allows users to:\n * - Enter tags through an input field\n * - Add tags by pressing Enter or clicking the add button\n * - View all selected tags as removable badges\n * - Remove individual tags by clicking the X on each badge\n *\n * The component is ideal for filtering by multiple tags or keywords\n * where users need to see all selected values at once.\n */\n\nfunction TagsFacetComponent({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: TagsFacetProps) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveFormControlSize(undefined, defaultScale);\n\tconst { strings } = useFilters();\n\tconst [inputValue, setInputValue] = useState('');\n\t// Handle adding a new tag\n\tconst handleAddTag = useCallback(() => {\n\t\tconst trimmedValue = inputValue.trim();\n\n\t\t// Don't add empty tags or duplicates\n\t\tif (!trimmedValue || value.includes(trimmedValue)) {\n\t\t\treturn;\n\t\t}\n\n\t\tonValueChange([...value, trimmedValue]);\n\t\tsetInputValue('');\n\t}, [inputValue, value, onValueChange]);\n\n\t// Handle removing a tag\n\tconst handleRemoveTag = useCallback(\n\t\t(tagToRemove: string) => {\n\t\t\tonValueChange(value.filter((tag) => tag !== tagToRemove));\n\t\t},\n\t\t[value, onValueChange],\n\t);\n\n\t// Handle keyboard events\n\tconst handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n\t\t// Enter that confirms an IME composition belongs to the composition, not the tag.\n\t\tif (e.key === 'Enter' && !e.nativeEvent.isComposing) {\n\t\t\te.preventDefault();\n\t\t\thandleAddTag();\n\t\t}\n\t};\n\n\t// Clear all tags\n\tconst handleClearAll = useCallback(() => {\n\t\tonValueChange([]);\n\t\tsetInputValue('');\n\t}, [onValueChange]);\n\n\tconst hasTags = value.length > 0;\n\tconst tagCountLabel =\n\t\tvalue.length === 1 ? strings.tag : strings.tags;\n\tconst tagSummary = hasTags ? (\n\t\t<Stack gap=\"md\" className=\"tags-facet--summary\">\n\t\t\t<Stack direction=\"horizontal\" gap=\"sm\" justify=\"between\" wrap={false}>\n\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">\n\t\t\t\t\t{formatFilterCount(strings.tagCount, value.length, tagCountLabel)}\n\t\t\t\t</Text>\n\t\t\t\t<Button\n\t\t\t\t\tonClick={handleClearAll}\n\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tclassName=\"text-muted-foreground hover:text-foreground\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\taria-label={strings.clearAll}\n\t\t\t\t>\n\t\t\t\t\t{strings.clearAll}\n\t\t\t\t</Button>\n\t\t\t</Stack>\n\t\t\t<Stack direction=\"horizontal\" gap=\"md\">\n\t\t\t\t{value.map((tag) => (\n\t\t\t\t\t<Badge\n\t\t\t\t\t\tkey={tag}\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tclassName=\"flex items-center gap-space-sm py-space-2xs pl-space-md pr-space-sm\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\">{tag}</Text>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tonClick={() => handleRemoveTag(tag)}\n\t\t\t\t\t\t\tclassName={cn(fieldAffordanceRecipes.target, fieldAffordanceRecipes.focus, fieldAffordanceRecipes.toggle)}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-label={`${strings.removeTag} ${tag}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<X className={fieldAffordanceRecipes.icon} aria-hidden=\"true\" />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</Badge>\n\t\t\t\t))}\n\t\t\t</Stack>\n\t\t</Stack>\n\t) : null;\n\n\treturn (\n\t\t<Stack gap=\"lg\" className={cn('tags-facet--component', className)}>\n\t\t\t{/* Input section */}\n\t\t\t<Stack direction=\"horizontal\" gap=\"md\" wrap={false}>\n\t\t\t\t<div className=\"relative flex-1\">\n\t\t\t\t\t<Input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\taria-label={filter.label}\n\t\t\t\t\t\tvalue={inputValue}\n\t\t\t\t\t\tonChange={(e) => setInputValue(e.target.value)}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tplaceholder={\n\t\t\t\t\t\t\tfilter.placeholder ?? strings.enterTag\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<Button tone=\"primary\"\n\t\t\t\t\tonClick={handleAddTag}\n\t\t\t\t\tdisabled={!inputValue.trim()}\n\t\t\t\t\tsize={size}\n\t\t\t\t\ticonOnly\n\t\t\t\t\tclassName={cn(formControlSizeClasses[size], controlGroupSquareClasses[size])}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t<Plus className=\"size-icon\" />\n\t\t\t\t\t<Text tag=\"span\" size=\"pxs\" className=\"sr-only\">\n\t\t\t\t\t\t{strings.addTag}\n\t\t\t\t\t</Text>\n\t\t\t\t</Button>\n\t\t\t</Stack>\n\n\t\t\t{/* Tags display section */}\n\t\t\t{tagSummary}\n\t\t</Stack>\n\t);\n}\n\nexport const TagsFacet = React.memo(TagsFacetComponent);\nTagsFacet.displayName = 'TagsFacet';\n","import { popoverRecipes } from '../../../base/popover/popover.recipes';\nimport { TagsFacet } from '../facets/tags-facet';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig, FilterTriggerSource } from '../filters.types';\nimport { useFilterDraft } from '../hooks/use-filter-draft';\nimport { getFilterValidationMessage } from '../utils/filter-utils';\nimport { FilterDraftFooter } from './filter-draft-footer';\nimport { FilterEditorHeader } from './filter-editor-header';\n\ninterface TagsFilterContentProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired when the change filters change. */\n\tonFilterChange: (value: string[]) => void;\n\tonBackToFilterList: () => void;\n\tonClose: () => void;\n\t/** Origin of the editor, which determines back-button behavior. */\n\ttriggerSource?: FilterTriggerSource;\n}\n\n/**\n * Tags Filter Content Component\n *\n * This component provides the content for tags filter popovers.\n * It handles:\n * - Tag input and management\n * - Multiple tag selection\n * - Displaying and removing tags\n * - Applying filter changes\n *\n * The component wraps the TagsFacet component and provides\n * the popover-specific UI elements like header and action buttons.\n */\n\nexport function TagsFilterContent({\n\tfilter,\n\tvalue,\n\tonFilterChange,\n\tonBackToFilterList,\n\tonClose,\n\ttriggerSource = 'chip',\n}: TagsFilterContentProps) {\n\tconst { strings, reportError } = useFilters();\n\n\t// The draft follows the applied value only when its entries change.\n\tconst [tempValue, setTempValue] = useFilterDraft(value);\n\tconst showBackButton = triggerSource === 'toolbar';\n\n\t// Apply changes when Done is clicked\n\tconst handleDone = () => {\n\t\tif (validationMessage) return;\n\t\ttry {\n\t\t\tonFilterChange(tempValue);\n\t\t\tonClose();\n\t\t} catch (error) {\n\t\t\tif (import.meta.env?.DEV) {\n\t console.error('Error applying filter:', error);\n\t\t\t}\n\t\t\treportError(error, { phase: 'apply', filterKey: filter.key });\n\t\t}\n\t};\n\n\tconst isDirty = JSON.stringify(tempValue.slice().sort()) !== JSON.stringify((value ?? []).slice().sort());\n\tconst validationMessage = isDirty ? getFilterValidationMessage(filter, tempValue, strings) : undefined;\n\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t<FilterEditorHeader title={filter.label} onBack={showBackButton ? onBackToFilterList : undefined} />\n\n\t\t\t<div className={popoverRecipes.menuRegion}>\n\t\t\t\t<TagsFacet\n\t\t\t\t\tfilter={filter}\n\t\t\t\t\tvalue={tempValue}\n\t\t\t\t\tonValueChange={setTempValue}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{!!isDirty && (\n\t\t\t\t// The facet already counts the tags above, so the footer holds only the command.\n\t\t\t\t<FilterDraftFooter error={validationMessage} onConfirm={handleDone} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useEffect, useRef, type ComponentProps } from 'react';\nimport { useFilters } from '../filter-context';\nimport { PopoverContent } from '../../../base/popover';\nimport { cn } from '../../../../lib/utils';\nimport { FilterType, type FilterConfig, type FilterOperator, type FilterTriggerSource } from '../filters.types';\nimport { AsyncFilterContent } from './async-filter-content';\nimport { DateFilterContent } from './date-filter-content';\nimport { FilterListContent } from './filter-list-content';\nimport { RangeFilterContent } from './range-filter-content';\nimport { RegularFilterContent } from './regular-filter-content';\nimport { TagsFilterContent } from './tags-filter-content';\nimport { popoverWidthRecipes } from '../../../base/popover/popover.recipes';\n\n// Focusable controls an editor body may lead with, in document order.\nconst EDITOR_CONTROL = 'input:not([type=hidden]):not(:disabled), textarea:not(:disabled), button:not(:disabled), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Moves focus to the primary control of the view that just replaced the\n * previous one: an editor's search, text or tag input (or its first date\n * field), or the filter list's search when the user goes back. The header's\n * back button is skipped, so typing continues in the new view.\n */\nfunction focusFilterEditorControl(popup: HTMLElement | null) {\n\t\tif (!popup) return;\n\t\tconst controls = [...popup.querySelectorAll<HTMLElement>(EDITOR_CONTROL)].filter((element) => !element.closest('.popover-header--component'));\n\t\tconst target = controls.find((element) => element.matches('input, textarea')) ?? controls[0];\n\t\ttarget?.focus({ preventScroll: true });\n}\n\nexport interface FilterPopoverContentProps {\n\t\t/** Which filter the popover is currently editing. */\n\t\tactiveFilterInPopover: FilterConfig | null;\n\t\t/** Active operator when the caller already owns the displayed selection. */\n\t\toperator?: FilterOperator;\n\t\t/** Filters the user may add. */\n\t\tavailableFilters: FilterConfig[];\n\t\t/** Filters currently applied. */\n\t\tactiveFilters: FilterConfig[];\n\t\t/** Reads the current value of a filter. */\n\t\tgetFilterValue: (key: string) => string[];\n\t\t/** Writes the next value of a filter. */\n\t\tsetFilterValue: (key: string, value: string[]) => void;\n\t\t/** Fired when the select filters change. */\n\t\tonFilterSelect: (filter: FilterConfig) => void;\n\t\tonBackToFilterList: () => void;\n\t\tonClose: () => void;\n\t\t/** Origin of the editor, which determines back-button behavior. */\n\t\ttriggerSource?: FilterTriggerSource;\n\t\tfinalFocus?: ComponentProps<typeof PopoverContent>['finalFocus'];\n}\n\n/**\n * Filter Popover Content Component\n *\n * This component provides the content wrapper for filter popovers.\n * It handles:\n * - Consistent popover styling\n * - Content layout and spacing\n * - Responsive behavior\n * - Animation and transitions\n *\n * The component is used to wrap filter content in a consistent\n * popover interface across different filter types.\n */\n\nexport function FilterPopoverContent({\n\t\tactiveFilterInPopover,\n\t\toperator,\n\t\tavailableFilters,\n\t\tactiveFilters,\n\t\tgetFilterValue,\n\t\tsetFilterValue,\n\t\tonFilterSelect,\n\t\tonBackToFilterList,\n\t\tonClose,\n\t\ttriggerSource = 'chip',\n\t\tfinalFocus,\n}: FilterPopoverContentProps) {\n\t\tconst { strings, getFilterOperator } = useFilters();\n\t\tconst popupRef = useRef<HTMLDivElement>(null);\n\t\tconst editorKey = activeFilterInPopover?.key ?? null;\n\t\tconst shownEditorKey = useRef(editorKey);\n\t\t// Opening the popover is Base UI's initial focus; switching views inside\n\t\t// an open popover removes the focused control, so the new view takes it.\n\t\tuseEffect(() => {\n\t\t\t\tif (shownEditorKey.current === editorKey) return;\n\t\t\t\tshownEditorKey.current = editorKey;\n\t\t\t\tconst popup = popupRef.current;\n\t\t\t\t// A closing popover resets its view too; its focus returns to the trigger.\n\t\t\t\tif (!popup?.hasAttribute('data-open')) return;\n\t\t\t\tfocusFilterEditorControl(popup);\n\t\t\t\t// Base UI recovers lost focus to the popup on the next frame; keep the\n\t\t\t\t// new view's control when that recovery lands on the container.\n\t\t\t\tconst view = popup.ownerDocument.defaultView;\n\t\t\t\tconst frame = view?.requestAnimationFrame(() => {\n\t\t\t\t\t\tif (popup.ownerDocument.activeElement === popup) focusFilterEditorControl(popup);\n\t\t\t\t});\n\t\t\t\treturn () => { if (frame != null) view?.cancelAnimationFrame(frame); };\n\t\t}, [editorKey]);\n\t\tconst popoverWidth =\n\t\t\t\tactiveFilterInPopover?.type === FilterType.DATE ||\n\t\t\t\tactiveFilterInPopover?.type === FilterType.TAGS\n\t\t\t\t\t\t? 'w-auto min-w-80 gap-0 overflow-hidden'\n\t\t\t\t\t\t: activeFilterInPopover?.type === FilterType.ASYNC_SELECT\n\t\t\t\t\t\t\t? cn(popoverWidthRecipes.md, 'gap-0 overflow-hidden')\n\t\t\t\t\t\t\t: cn(popoverWidthRecipes.md, 'gap-0 overflow-hidden');\n\n\t\t// Forward values directly so upstream can decide whether to add or clear the filter\n\t\tconst handleSetFilterValue = (key: string, value: string[]) => {\n\t\t\t\tsetFilterValue(key, value);\n\t\t};\n\n\t\treturn (\n\t\t<PopoverContent ref={popupRef} finalFocus={finalFocus} type=\"menu\" aria-label={activeFilterInPopover?.label ?? strings.addFilter} inset=\"flush\" className={cn('filter-popover-content--component', popoverWidth)} align=\"start\">\n\t\t\t\t\t\t{activeFilterInPopover ? (\n\t\t\t\t\t\t\t\t// Render specific filter content based on type\n\t\t\t\t\t\t\t\tactiveFilterInPopover.type === FilterType.DATE ? (\n\t\t\t\t\t\t\t\t\t\t<DateFilterContent\n\t\t\t\t\t\t\t\t\t\t\t\tfilter={activeFilterInPopover}\n\t\t\t\t\t\t\t\t\t\t\t\toperator={operator ?? getFilterOperator(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={getFilterValue(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tonFilterChange={(value) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleSetFilterValue(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tactiveFilterInPopover.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tonBackToFilterList={onBackToFilterList}\n\t\t\t\t\t\t\t\t\t\t\t\ttriggerSource={triggerSource}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : activeFilterInPopover.type === FilterType.RANGE ? (\n\t\t\t\t\t\t\t\t\t\t<RangeFilterContent\n\t\t\t\t\t\t\t\t\t\t\t\tfilter={activeFilterInPopover}\n\t\t\t\t\t\t\t\t\t\t\t\toperator={operator ?? getFilterOperator(activeFilterInPopover.key) ?? 'between'}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={getFilterValue(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tonFilterChange={(value) => handleSetFilterValue(activeFilterInPopover.key, value)}\n\t\t\t\t\t\t\t\t\t\t\t\tonBackToFilterList={onBackToFilterList}\n\t\t\t\t\t\t\t\t\t\t\t\tonClose={onClose}\n\t\t\t\t\t\t\t\t\t\t\t\ttriggerSource={triggerSource}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : activeFilterInPopover.type === FilterType.TAGS ? (\n\t\t\t\t\t\t\t\t\t\t<TagsFilterContent\n\t\t\t\t\t\t\t\t\t\t\t\tfilter={activeFilterInPopover}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={getFilterValue(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tonFilterChange={(value) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleSetFilterValue(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tactiveFilterInPopover.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tonBackToFilterList={onBackToFilterList}\n\t\t\t\t\t\t\t\t\t\t\t\tonClose={onClose}\n\t\t\t\t\t\t\t\t\t\t\t\ttriggerSource={triggerSource}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : activeFilterInPopover.type === FilterType.ASYNC_SELECT ? (\n\t\t\t\t\t\t\t\t\t\t<AsyncFilterContent\n\t\t\t\t\t\t\t\t\t\t\t\tfilter={activeFilterInPopover}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={getFilterValue(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tonFilterChange={(value) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleSetFilterValue(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tactiveFilterInPopover.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tonBackToFilterList={onBackToFilterList}\n\t\t\t\t\t\t\t\t\t\t\t\tonClose={onClose}\n\t\t\t\t\t\t\t\t\t\t\t\ttriggerSource={triggerSource}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<RegularFilterContent\n\t\t\t\t\t\t\t\t\t\t\t\tfilter={activeFilterInPopover}\n\t\t\t\t\t\t\t\t\t\t\t\tvalue={getFilterValue(activeFilterInPopover.key)}\n\t\t\t\t\t\t\t\t\t\t\t\tonFilterChange={(value) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleSetFilterValue(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tactiveFilterInPopover.key,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\tonBackToFilterList={onBackToFilterList}\n\t\t\t\t\t\t\t\t\t\t\t\tonClose={onClose}\n\t\t\t\t\t\t\t\t\t\t\t\ttriggerSource={triggerSource}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t// Render the list of available filters\n\t\t\t\t\t\t\t\t<FilterListContent\n\t\t\t\t\t\t\t\t\t\tavailableFilters={availableFilters}\n\t\t\t\t\t\t\t\t\t\tactiveFilters={activeFilters}\n\t\t\t\t\t\t\t\t\t\tonFilterSelect={onFilterSelect}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t</PopoverContent>\n\t\t);\n}\n","/**\n * FilterPill — internal partial that wraps a single `ActiveFilterItem` with\n * its popover. Used by `FilterLayout` for both `display: 'always'` filters\n * and `active` regular filters since the rendering is identical except for\n * the `availableFilters` / `activeFilters` lists passed to the popover.\n *\n * Exported from `partials/index.ts` so consumers building a custom strip\n * around `<FilterProvider>` can re-use it without duplicating the popover\n * machinery.\n */\nimport { useEffect, useRef, useState } from 'react';\n\nimport { Popover, PopoverTrigger } from '../../../base/popover';\n\nimport type {\n\tFilterConfig,\n\tFilterOperator,\n\tOperatorOption,\n} from '../filters.types';\n\nimport { useFilters } from '../filter-context';\nimport { ActiveFilterItem } from './active-filter-item';\nimport { FilterErrorBoundary } from './filter-error-boundary';\nimport { FilterPopoverContent } from './filter-popover-content';\n\nexport interface FilterPillProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Whether the filter is currently applied. */\n\tactive: boolean;\n\t/** Comparison currently chosen. */\n\toperator: FilterOperator;\n\t/** Comparisons this filter offers. */\n\toperators: OperatorOption[];\n\tonOperatorChange: (operator: FilterOperator) => void;\n\tonValueChange: (value: string[]) => void;\n\tonClear: () => void;\n\t/** Filters to render in the \"+\" list inside the popover. */\n\tavailableFilters: FilterConfig[];\n\t/** Active regular filters list (for the popover header / context). */\n\tactiveFilters: FilterConfig[];\n\t/**\n\t * Optional flag a custom strip can read: it is true for 100 ms after an\n\t * operator change, and the pill does not open its editor while it is set.\n\t * Without it the editor opens as soon as it is asked to.\n\t */\n\toperatorChangeRef?: React.MutableRefObject<boolean>;\n}\n\nexport function FilterPill({\n\tfilter,\n\tvalue,\n\tactive,\n\toperator,\n\toperators,\n\tonOperatorChange,\n\tonValueChange,\n\tonClear,\n\tavailableFilters,\n\tactiveFilters,\n\toperatorChangeRef,\n}: FilterPillProps) {\n\tconst { isNavigating } = useFilters();\n\tconst operatorChangeTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\tuseEffect(() => () => clearTimeout(operatorChangeTimer.current), []);\n\tconst opensSuppressed = () => isNavigating || operatorChangeRef?.current === true;\n\n\tconst [open, setOpen] = useState(false);\n\n\tconst labelRef = useRef<HTMLButtonElement>(null);\n\tconst editorFocusRef = useRef<HTMLButtonElement>(null);\n\treturn (\n\t\t<FilterErrorBoundary filterKey={filter.key}>\n\t\t\t<Popover\n\t\t\t\topen={open}\n\t\t\t\tonOpenChange={(isOpen) => {\n\t\t\t\t\tif (isOpen && opensSuppressed()) return;\n\t\t\t\t\tsetOpen(isOpen);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"filter-pill--component filter-pill--anchor relative\">\n\t\t\t\t\t{/* Base UI positions against its trigger. This inert trigger mirrors\n\t\t\t\t\t\tthe pill bounds while the pill's own segmented controls retain all\n\t\t\t\t\t\tinteraction and focus behavior. */}\n\t\t\t\t\t<PopoverTrigger\n\t\t\t\t\t\trender={<span />}\n\t\t\t\t\t\tnativeButton={false}\n\t\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tclassName=\"pointer-events-none absolute inset-0\"\n\t\t\t\t\t/>\n\t\t\t\t\t<ActiveFilterItem\n\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\tpopoverOpen={open}\n\t\t\t\t\ttriggerRef={labelRef}\n\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\tactive={active}\n\t\t\t\t\t\toperators={operators}\n\t\t\t\t\t\toperator={operator}\n\t\t\t\t\t\tonOperatorChange={(next) => {\n\t\t\t\t\t\t\tif (isNavigating) return;\n\t\t\t\t\t\t\tif (operatorChangeRef) {\n\t\t\t\t\t\t\t\toperatorChangeRef.current = true;\n\t\t\t\t\t\t\t\tclearTimeout(operatorChangeTimer.current);\n\t\t\t\t\t\t\t\toperatorChangeTimer.current = setTimeout(() => {\n\t\t\t\t\t\t\t\t\toperatorChangeRef.current = false;\n\t\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonOperatorChange(next);\n\t\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFilterClear={() => {\n\t\t\t\t\t\t\tif (isNavigating) return;\n\t\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\t\tonClear();\n\t\t\t\t\t\tlabelRef.current?.focus();\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFilterClick={(event) => {\n\t\t\t\t\t\t\tif (!opensSuppressed()) {\n\t\t\t\t\t\t\t\teditorFocusRef.current = event?.currentTarget ?? labelRef.current;\n\t\t\t\t\t\t\t\tsetOpen(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<FilterPopoverContent\n\t\t\t\t\tfinalFocus={editorFocusRef}\n\t\t\t\t\tactiveFilterInPopover={filter}\n\t\t\t\t\toperator={operator}\n\t\t\t\t\tavailableFilters={availableFilters}\n\t\t\t\t\tactiveFilters={activeFilters}\n\t\t\t\t\tgetFilterValue={() => value}\n\t\t\t\t\tsetFilterValue={(_, next) => onValueChange(next)}\n\t\t\t\t\tonFilterSelect={() => {}}\n\t\t\t\t\tonBackToFilterList={() => {}}\n\t\t\t\t\tonClose={() => setOpen(false)}\n\t\t\t\t\ttriggerSource=\"chip\"\n\t\t\t\t/>\n\t\t\t</Popover>\n\t\t</FilterErrorBoundary>\n\t);\n}\n\nFilterPill.displayName = 'FilterPill';\n","import { Filter } from 'lucide-react';\nimport { useState, useEffect, type Ref } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { formControlSizeClasses, resolveFormControlSize } from '../../../base/forms/form-sizing';\nimport { controlGroupSquareClasses } from '../../../../lib/control-group-recipes';\nimport { useDensityConfig } from '../../../../lib/ui-provider';\nimport { cn } from '../../../../lib/utils';\nimport {\n\tPopover,\n\tPopoverTrigger,\n} from '../../../base/popover';\nimport type { FilterConfig } from '../filters.types';\nimport { useFilters } from '../filter-context';\nimport { FilterPopoverContent } from './filter-popover-content';\n\nexport interface FiltersButtonProps {\n\t/** Receives the Add filter trigger, for focus restoration in custom layouts. */\n\ttriggerRef?: Ref<HTMLButtonElement>;\n\t/** Filters the user may add. */\n\tavailableFilters: FilterConfig[];\n\t/** Filters currently applied. */\n\tactiveFilters: FilterConfig[];\n\t/** Which filter the popover is currently editing. */\n\tactiveFilterInPopover: FilterConfig | null;\n\t/** Reads the current value of a filter. */\n\tgetFilterValue: (key: string) => string[];\n\t/** Writes the next value of a filter. */\n\tsetFilterValue: (key: string, value: string[]) => void;\n\t/** Opens the popover on a particular filter. */\n\tsetActiveFilterInPopover: (filter: FilterConfig | null) => void;\n}\n\n/**\n * Filters Button Component\n *\n * This component provides the main button for adding and managing filters.\n * It handles:\n * - Opening the filter popover\n * - Managing filter selection state\n * - Handling filter actions (select, back, close)\n * - Supporting internationalization\n *\n * The component is used as the primary entry point for users to\n * add and configure filters in the application.\n */\n\nexport function FiltersButton({\n\ttriggerRef,\n\tavailableFilters,\n\tactiveFilters,\n\tactiveFilterInPopover,\n\tgetFilterValue,\n\tsetFilterValue,\n\tsetActiveFilterInPopover,\n}: FiltersButtonProps) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveFormControlSize(undefined, defaultScale);\n\t// Control popover state explicitly\n\tconst [isOpen, setIsOpen] = useState(false);\n\tconst { strings, isNavigating } = useFilters();\n\n\t// Handle filter selection - keep popover open\n\tconst handleFilterSelect = (filter: FilterConfig) => {\n\t\t// Set the selected filter without closing the popover\n\t\tsetActiveFilterInPopover(filter);\n\t};\n\n\t// Handle back to filter list action\n\tconst handleBackToFilterList = () => {\n\t\tsetActiveFilterInPopover(null);\n\t};\n\n\t// Handle complete close action - reset everything\n\tconst handleClose = () => {\n\t\tsetActiveFilterInPopover(null);\n\t\tsetIsOpen(false);\n\t};\n\n\t// Reset active filter when popover closes\n\tuseEffect(() => {\n\t\tif (!isOpen) {\n\t\t\t// Reset to filters view when popover is closed\n\t\t\tsetActiveFilterInPopover(null);\n\t\t}\n\t}, [isOpen, setActiveFilterInPopover]);\n\n\treturn (\n\t\t<Popover open={isOpen} onOpenChange={(next) => { if (!next || !isNavigating) setIsOpen(next); }}>\n\t\t\t<PopoverTrigger\n\t\t\t\trender={(\n\t\t\t\t\t<Button\n\t\t\t\t\t\tref={triggerRef}\n\t\t\t\t\t\ttone=\"secondary\" buttonStyle=\"outline\"\n\t\t\t\t\t\tsize={size} iconOnly\n\t\t\t\t\t\taria-label={strings.addFilter}\n\t\t\t\t\t\taria-disabled={isNavigating || undefined}\n\t\t\t\t\t\tclassName={cn('filters-button--component shrink-0', formControlSizeClasses[size], controlGroupSquareClasses[size])}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Filter className=\"size-icon-sm\" />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t/>\n\t\t\t<FilterPopoverContent\n\t\t\t\tactiveFilterInPopover={activeFilterInPopover}\n\t\t\t\tavailableFilters={availableFilters}\n\t\t\t\tactiveFilters={activeFilters}\n\t\t\t\tgetFilterValue={getFilterValue}\n\t\t\t\tsetFilterValue={setFilterValue}\n\t\t\t\tonFilterSelect={handleFilterSelect}\n\t\t\t\tonBackToFilterList={handleBackToFilterList}\n\t\t\t\tonClose={handleClose}\n\t\t\t\ttriggerSource=\"toolbar\"\n\t\t\t/>\n\t\t</Popover>\n\t);\n}\n","import { useMemo, useCallback } from 'react';\nimport { Tabs, TabsList, TabsTrigger } from '../../../base/navigation/tabs';\nimport { Text } from '../../../typography';\nimport { useFilters } from '../filter-context';\nimport { FilterType, type ActiveFilter, type FilterTab } from '../filters.types';\nimport { resolveDefaultOperator } from '../operator-options';\n\nexport interface FilterTabsProps {\n\t/** Tabs to offer, in display order. */\n\ttabs: FilterTab[];\n}\n\n/**\n * Single-selection filter preset buttons with Base UI roving keyboard navigation.\n * These change filters rather than switch associated tab panels, so arrow keys\n * only move focus; Enter, Space or a click applies a tab's presets.\n *\n * - \"All\" tab (empty presets): active when zero non-search active filters\n * - Named tabs: active when presets exactly match non-search active filters\n * - Search filters are preserved across tab switches\n */\nexport function FilterTabs({ tabs }: FilterTabsProps) {\n\tconst { activeFilters, filters, replaceFilters } = useFilters();\n\n\tconst nonSearchFilters = useMemo(\n\t\t() => activeFilters.filter((f) => {\n\t\t\tconst config = filters.find((fc) => fc.key === f.key);\n\t\t\treturn config?.type !== FilterType.SEARCH;\n\t\t}),\n\t\t[activeFilters, filters],\n\t);\n\n\tconst searchFilters = useMemo(\n\t\t() => activeFilters.filter((f) => {\n\t\t\tconst config = filters.find((fc) => fc.key === f.key);\n\t\t\treturn config?.type === FilterType.SEARCH;\n\t\t}),\n\t\t[activeFilters, filters],\n\t);\n\n\tconst activeTabId = useMemo(() => {\n\t\tfor (const tab of tabs) {\n\t\t\t// \"All\" tab: no presets → active when zero non-search filters\n\t\t\tif (tab.presets.length === 0) {\n\t\t\t\tif (nonSearchFilters.length === 0) return tab.id;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Named tab: bidirectional exact match\n\t\t\tif (tab.presets.length !== nonSearchFilters.length) continue;\n\n\t\t\tconst allMatch = tab.presets.every((preset) => {\n\t\t\t\tconst active = nonSearchFilters.find((f) => f.key === preset.key);\n\t\t\t\tif (!active) return false;\n\n\t\t\t\tconst sortedPreset = [...preset.value].sort();\n\t\t\t\tconst sortedActive = [...active.value].sort();\n\t\t\t\tif (sortedPreset.length !== sortedActive.length) return false;\n\t\t\t\tif (sortedPreset.some((v, i) => v !== sortedActive[i])) return false;\n\n\t\t\t\t// Check operator if specified in preset\n\t\t\t\tif (preset.operator && active.operator !== preset.operator) return false;\n\n\t\t\t\treturn true;\n\t\t\t});\n\n\t\t\tif (allMatch) return tab.id;\n\t\t}\n\n\t\treturn null;\n\t}, [tabs, nonSearchFilters]);\n\n\tconst handleTabClick = useCallback(\n\t\t(tab: FilterTab) => {\n\t\t\tif (tab.presets.length === 0) {\n\t\t\t\t// \"All\" tab — keep only search filters\n\t\t\t\treplaceFilters([...searchFilters]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst presetFilters: ActiveFilter[] = tab.presets.map((preset) => {\n\t\t\t\tconst filterConfig = filters.find((fc) => fc.key === preset.key);\n\t\t\t\tconst operator = preset.operator ?? resolveDefaultOperator(filterConfig);\n\n\t\t\t\treturn {\n\t\t\t\t\tid: preset.key,\n\t\t\t\t\tkey: preset.key,\n\t\t\t\t\tvalue: preset.value,\n\t\t\t\t\toperator,\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treplaceFilters([...searchFilters, ...presetFilters]);\n\t\t},\n\t\t[filters, searchFilters, replaceFilters],\n\t);\n\n\tif (tabs.length === 0) return null;\n\n\treturn (\n\t\t<Tabs value={activeTabId} onValueChange={value => {\n const tab = tabs.find(item => item.id === value);\n if (tab) handleTabClick(tab);\n }} className=\"filter-tabs--component\">\n {/* Manual activation: arrow keys move focus, and Enter, Space or a click applies the presets. */}\n <TabsList variant=\"chips\" role=\"group\" aria-orientation={undefined} className=\"gap-space-md\">\n\t\t\t{tabs.map((tab) => {\n\t\t\t\tconst isActive = activeTabId === tab.id;\n\n\t\t\t\treturn (\n\t\t\t\t\t<TabsTrigger\n\t\t\t\t\t\tkey={tab.id}\n value={tab.id}\n role=\"button\"\n aria-selected={undefined}\n aria-controls={undefined}\n aria-pressed={isActive}\n\n\t\t\t\t\t\tclassName=\"filter-tabs--tab\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\tweight=\"medium\"\n\t\t\t\t\t\t\tclassName=\"text-inherit\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{tab.label}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t{tab.count !== undefined && (\n\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\tclassName=\"tabular-nums\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{tab.count}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</TabsTrigger>\n\t\t\t\t);\n\t\t\t})}\n\t\t</TabsList>\n </Tabs>\n\t);\n}\n","import { Loader2, type LucideIcon } from 'lucide-react';\nimport React, {\n\t\ttype ChangeEvent,\n\t\tuseState,\n\t\tuseEffect,\n\t\tuseRef,\n} from 'react';\nimport { FormField } from '../../../base/forms/form-field';\nimport { Input } from '../../../base/text-inputs';\nimport {\n\t\tDEFAULT_DEBOUNCE_MS,\n\t\tuseDebouncedCallback,\n} from '../../../../hooks/use-debounced-callback';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig } from '../filters.types';\nimport { getFilterValidationMessage, labelInRunningText } from '../utils/filter-utils';\n\nexport interface SearchFacetProps {\n\t\t/** Definition of the filter this control edits. */\n\t\tfilter: FilterConfig;\n\t\t/** Current value. */\n\t\tvalue: string[];\n\t\t/** Fired with the next value. */\n\t\tonValueChange: (value: string[]) => void;\n\t\t/** Merged onto the outermost node. */\n\t\tclassName?: string;\n}\n\n/**\n * Search Filter Facet\n *\n * This component implements a text search filter that allows users to:\n * - Enter search terms\n * - Configure search behavior (contains, equals, etc.)\n * - Set debounce delay for performance\n * - Customize placeholder text and appearance\n *\n * The component integrates with the filter context to manage the search value\n * and provides a responsive search input interface.\n */\n\nconst SearchLoadingIcon: LucideIcon = React.forwardRef(function SearchLoadingIcon(props, ref) {\n return <Loader2 {...props} ref={ref} className={cn('animate-spin', props.className)} />;\n});\n\nfunction SearchFacetComponent({\n\t\tfilter,\n\t\tvalue,\n\t\tonValueChange,\n\t\tclassName,\n}: SearchFacetProps) {\n\t\tconst { strings, isNavigating } = useFilters();\n\n\t\t// Use local state for the input value - initialized from value prop\n\t\tconst [inputValue, setInputValue] = useState(value[0] || '');\n\t\t// Ref mirror of inputValue so the sync effect can read it without depending on it\n\t\tconst inputValueRef = useRef(inputValue);\n\t\tuseEffect(() => { inputValueRef.current = inputValue; }, [inputValue]);\n\t\t// Tracking the last value we emitted to prevent duplicate emissions\n\t\tconst lastEmittedValue = useRef(value[0] ?? '');\n\t\t// Track if we're currently handling user input to prevent interference\n\t\tconst isUserTypingRef = useRef(false);\n\n\t\t// Update input value when props change (for URL sync/refresh)\n\t\t// Guarded by isNavigating to prevent stale prop overwrites during the\n\t\t// gap between debounce-fire and Inertia response arriving.\n\t\tuseEffect(() => {\n\t\t\t\t// Skip if user is actively typing or navigation is in-flight\n\t\t\t\tif (isUserTypingRef.current || isNavigating) {\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst currentInput = inputValueRef.current;\n\n\t\t\t\t// Handle empty value array - this happens when filters are cleared\n\t\t\t\tif (!value.length || value[0] === '') {\n\t\t\t\t\t\tif (currentInput !== '') {\n\t\t\t\t\t\t\t\tsetInputValue('');\n\t\t\t\t\t\t\t\tlastEmittedValue.current = '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Only update if the value is different from what we have\n\t\t\t\t// and different from what we last emitted\n\t\t\t\tif (\n\t\t\t\t\t\tvalue[0] !== undefined &&\n\t\t\t\t\t\tvalue[0] !== currentInput &&\n\t\t\t\t\t\tvalue[0] !== lastEmittedValue.current\n\t\t\t\t) {\n\t\t\t\t\t\tsetInputValue(value[0]);\n\t\t\t\t\t\tlastEmittedValue.current = value[0];\n\t\t\t\t}\n\t\t}, [value, isNavigating]);\n\n\t\t// Debounced emit. `useDebouncedCallback` keeps `onValueChange` in a ref\n\t\t// and drops the pending call on unmount, so neither the callback's\n\t\t// changing identity nor a mounted flag has to be tracked here.\n\t\tconst emitValue = useDebouncedCallback((newValue: string) => {\n\t\t\t\tlastEmittedValue.current = newValue;\n\t\t\t\tisUserTypingRef.current = false;\n\t\t\t\tonValueChange([newValue]);\n\t\t}, filter.delay ?? DEFAULT_DEBOUNCE_MS);\n\n\t\t// A term that fails the filter's `validation` is shown with its message and\n\t\t// never applied. An empty input clears the search and is always allowed.\n\t\tconst getValidationMessage = (term: string) =>\n\t\t\t\tterm.trim() === '' ? undefined : getFilterValidationMessage(filter, [term], strings);\n\t\tconst validationMessage = getValidationMessage(inputValue);\n\n\t\t// Consistently handles ALL input changes\n\t\tconst debouncedUpdate = (newValue: string) => {\n\t\t\t\tif (getValidationMessage(newValue)) {\n\t\t\t\t\t\temitValue.cancel();\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Returning to the applied value supersedes any pending draft.\n\t\t\t\tif (lastEmittedValue.current === newValue) {\n\t\t\t\t\t\temitValue.cancel();\n\t\t\t\t\t\tisUserTypingRef.current = false;\n\t\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\temitValue(newValue);\n\t\t};\n\n\t\t// Handle input change - works for both typing and deleting characters\n\t\tconst handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {\n\t\t\t\tisUserTypingRef.current = true;\n\t\t\t\tconst newValue = e.target.value;\n\t\t\t\tsetInputValue(newValue);\n\t\t\t\tdebouncedUpdate(newValue);\n\t\t};\n\n\t\t// Handle focusing the input\n\t\tconst handleFocus = () => {\n\t\t\t\tisUserTypingRef.current = true;\n\t\t};\n\n\t\t// Handle blurring the input\n\t\tconst handleBlur = () => {\n\t\t\t\t// Set a small delay before clearing the typing flag\n\t\t\t\t// This prevents immediate sync which could cause issues\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tisUserTypingRef.current = false;\n\t\t\t\t}, 100);\n\t\t};\n\n\n\t\treturn (\n\t\t// FormField owns the message, its alert role and the input's invalid and\n\t\t// described-by wiring. With no label and no error it adds nothing.\n\t\t<FormField\n\t\t\t\terror={validationMessage}\n\t\t\t\tclassName={cn('search-facet--component', 'search-facet relative w-full min-w-0 rounded-radius bg-background', className)}\n\t\t>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\taria-label={filter.label}\n\t\t\t\t\t\t\t\tvalue={inputValue}\n\t\t\t\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\t\t\t\tonFocus={handleFocus}\n\t\t\t\t\t\t\t\tonBlur={handleBlur}\n\t\t\t\t\t\t\t\tplaceholder={\n\t\t\t\t\t\t\t\t\t\tfilter.placeholder ??\n\t\t\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst label = labelInRunningText(filter.label.trim());\n\t\t\t\t\t\t\t\t\t\t\t\t// The template with no label, such as \"Search...\".\n\t\t\t\t\t\t\t\t\t\t\t\tconst generic = interpolateFilterString(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstrings.searchPlaceholder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ filterLabel: '' },\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.replace(/\\s+([….?!])/g, '$1')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.replace(/\\s{2,}/g, ' ')\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t.trim();\n\t\t\t\t\t\t\t\t\t\t\t\t// A label that repeats the template's own word, in\n\t\t\t\t\t\t\t\t\t\t\t\t// whatever language the strings owner supplies,\n\t\t\t\t\t\t\t\t\t\t\t\t// collapses to it instead of reading \"Search search...\".\n\t\t\t\t\t\t\t\t\t\t\t\tconst genericWord = generic.replace(/[\\s….?!]+$/u, '').toLocaleLowerCase();\n\t\t\t\t\t\t\t\t\t\t\t\tif (!label || label.toLocaleLowerCase() === genericWord) return generic;\n\t\t\t\t\t\t\t\t\t\t\t\treturn interpolateFilterString(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tstrings.searchPlaceholder,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ filterLabel: label },\n\t\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t})()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tclearable={inputValue.trim() !== '' && !isNavigating}\n\t\t\t\t\t\t\t\tendIcon={isNavigating ? SearchLoadingIcon : undefined}\n\t\t\t\t\t\t\t\tstrings={{clear: strings.clearSearch}}\n\t\t\t/>\n\t\t</FormField>\n\t\t);\n}\n\nexport const SearchFacet = React.memo(SearchFacetComponent);\nSearchFacet.displayName = 'SearchFacet';\n","import { Text } from '../../../typography';\nimport { Stack } from '../../../base/structure';\nimport { cn } from '../../../../lib/utils';\nimport { SearchFacet } from '../facets/search-facet';\nimport type { FilterConfig } from '../filters.types';\n\nexport interface SearchFiltersListProps {\n\t/** Filter definitions available to the surface. */\n\tfilters: FilterConfig[];\n\t/** Reads the current value of a filter. */\n\tgetFilterValue: (key: string) => string[];\n\t/** Writes the next value of a filter. */\n\tsetFilterValue: (key: string, value: string[]) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\n/**\n * Search Filters List Component\n *\n * This component provides a list of search filters that are always visible.\n * It handles:\n * - Rendering multiple search filters\n * - Managing filter values\n * - Applying custom styling\n * - Supporting responsive layout\n *\n * The component is used to display search filters that should be\n * immediately accessible to users without requiring a popover.\n */\n\nexport function SearchFiltersList({\n\tfilters,\n\tgetFilterValue,\n\tsetFilterValue,\n\tclassName,\n}: SearchFiltersListProps) {\n\treturn (\n\t\t<>\n\t\t\t{filters.map((filter) => (\n\t\t\t\t<Stack\n\t\t\t\t\tgap=\"lg\"\n\t\t\t\t\tkey={filter.key}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'search-filters-list--component',\n\t\t\t\t\t\t'w-full min-w-0 sm:w-64 sm:flex-none',\n\t\t\t\t\t\tfilter.displayConfig.className,\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<SearchFacet\n\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\tvalue={getFilterValue(filter.key)}\n\t\t\t\t\t\tonValueChange={(newValue) =>\n\t\t\t\t\t\t\tsetFilterValue(filter.key, newValue)\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t\t{!!filter.description && (\n\t\t\t\t\t\t<Text size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t{filter.description}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Stack>\n\t\t\t))}\n\t\t</>\n\t);\n}\n","/**\n * FilterLayout — default strip layout: search inputs inline, then either\n * \"always-visible\" or active filter pills, then the \"+\" button for the\n * remaining inactive filters.\n *\n * The heavy lifting now lives in two reusable pieces:\n * - `useFilterGroups()` (hook) — partitions filters into search /\n * always-visible / active / popover groups so consumers building a\n * custom strip can call this and place each group themselves.\n * - `<FilterPill>` (partial) — wraps `<ActiveFilterItem>` + popover so\n * the duplicated rendering between always-visible and active filters\n * collapses to a single component.\n */\nimport { useCallback, useEffect, useState, useRef } from 'react';\n\nimport { Button } from '../../base/buttons';\nimport { Stack, type StructureGap } from '../../base/structure';\nimport { Text } from '../../typography';\nimport { neutralFillRecipes } from '../../../lib/surface-recipes';\nimport { cn } from '../../../lib/utils';\n\nimport { useFilters } from './filter-context';\nimport { interpolateFilterString } from './filters.strings';\nimport {\n\ttype FilterConfig,\n\ttype FilterTab,\n\ttype FilterOperator,\n} from './filters.types';\nimport { useFilterGroups } from './hooks/use-filter-groups';\nimport { getOperatorsForFilter } from './operator-options';\n\nimport {\n\tFilterErrorBoundary,\n\tFiltersButton,\n\tFilterPill,\n\tFilterTabs,\n\tSearchFiltersList,\n} from './partials';\n\nexport interface FilterLayoutProps {\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n\t/** Per-key dynamic options that override the provider's filter.options. */\n\tdynamicFilterOptions?: Record<string, FilterConfig['options']>;\n\t/** Per-key loading states; renders a small spinning chip. */\n\tloadingFilters?: Record<string, boolean>;\n\t/** The variant this surface represents. */\n\tvariant?: 'default' | 'compact';\n\t/** Renders the clear filters. */\n\tshowClearFilters?: boolean;\n\t/** Tabs to offer, in display order. */\n\ttabs?: FilterTab[];\n}\n\nconst layoutGap = {\n\tcompact: 'lg',\n\tdefault: 'xl',\n} satisfies Record<NonNullable<FilterLayoutProps['variant']>, StructureGap>;\n\nconst controlRowGap = {\n\tcompact: 'sm',\n\tdefault: 'md',\n} satisfies Record<NonNullable<FilterLayoutProps['variant']>, StructureGap>;\n\nexport function FilterLayout({\n\tclassName,\n\tdynamicFilterOptions = {},\n\tloadingFilters = {},\n\tvariant = 'default',\n\tshowClearFilters = false,\n\ttabs,\n}: FilterLayoutProps) {\n\tconst {\n\t\tgetFilterValue,\n\t\tsetFilterValue,\n\t\tisFilterActive,\n\t\tclearFilters,\n\t\tgetFilterOperator,\n\t\tsetFilterOperator,\n\t\tisNavigating,\n\t\tstrings,\n\t} = useFilters();\n\n\tconst groups = useFilterGroups({ dynamicFilterOptions });\n\tconst {\n\t\tprocessedFilters,\n\t\tsearchFilters,\n\t\talwaysVisibleFilters,\n\t\tactiveRegularFilters,\n\t\tpopoverFilters,\n\t\thasActive,\n\t} = groups;\n\n\tconst [activeFilterKey, setActiveFilterKey] = useState<string | null>(null);\n\tconst activeFilterInPopover = processedFilters.find((filter) => filter.key === activeFilterKey) ?? null;\n\tconst setActiveFilterInPopover = useCallback((filter: FilterConfig | null) => {\n\t\tsetActiveFilterKey(filter?.key ?? null);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (activeFilterKey !== null && activeFilterInPopover === null) setActiveFilterKey(null);\n\t}, [activeFilterKey, activeFilterInPopover]);\n\n\tconst addFilterRef = useRef<HTMLButtonElement>(null);\n\tconst removedFilterRef = useRef<string | null>(null);\n\tfunction handlePillValueChange(filter: FilterConfig, value: string[]) {\n\t\tif (value.length === 0 && filter.displayConfig?.display !== 'always') {\n\t\t\tremovedFilterRef.current = filter.key;\n\t\t}\n\t\tsetFilterValue(filter.key, value);\n\t}\n\tuseEffect(() => {\n\t\tconst key = removedFilterRef.current;\n\t\tif (key !== null && !isFilterActive(key)) {\n\t\t\taddFilterRef.current?.focus();\n\t\t\tremovedFilterRef.current = null;\n\t\t}\n\t}, [isFilterActive]);\n\n\tfunction getFilterOperators(filter: FilterConfig) {\n\t\treturn getOperatorsForFilter(filter, strings.operators);\n\t}\n\n\tfunction handleOperatorChange(filterKey: string, operator: FilterOperator) {\n\t\tsetFilterOperator(filterKey, operator);\n\t}\n\n\treturn (\n\t\t<Stack gap={layoutGap[variant]} className={cn('filter-layout--component', className)}>\n\t\t\t{!!tabs && tabs.length > 0 && <FilterTabs tabs={tabs} />}\n\n\t\t\t<Stack direction=\"horizontal\" align=\"center\" gap={controlRowGap[variant]} aria-busy={isNavigating || undefined}>\n\t\t\t\t<FilterErrorBoundary filterKey=\"search-filters\">\n\t\t\t\t\t<SearchFiltersList\n\t\t\t\t\t\tfilters={searchFilters}\n\t\t\t\t\t\tgetFilterValue={getFilterValue}\n\t\t\t\t\t\tsetFilterValue={setFilterValue}\n\t\t\t\t\t/>\n\t\t\t\t</FilterErrorBoundary>\n\n\t\t\t\t{/* A box-less wrapper cannot dim: each pill and button dims itself while navigating. */}\n\t\t\t\t<div className=\"contents\">\n\t\t\t\t\t{/* Loading chips for filters being updated */}\n\t\t\t\t\t{Object.entries(loadingFilters)\n\t\t\t\t\t\t.filter(([, isLoading]) => isLoading)\n\t\t\t\t\t\t.map(([key]) => {\n\t\t\t\t\t\t\tconst filterLabel =\n\t\t\t\t\t\t\t\tprocessedFilters.find((f) => f.key === key)?.label || key;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Stack\n\t\t\t\t\t\t\t\t\tkey={`loading-${key}`}\n\t\t\t\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\t\t\t\tdirection=\"horizontal\"\n\t\t\t\t\t\t\t\t\tgap=\"sm\"\n\t\t\t\t\t\t\t\t\twrap={false}\n\t\t\t\t\t\t\t\t\tclassName={cn('rounded-radius px-control-sm py-space-xs', neutralFillRecipes.band)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div aria-hidden=\"true\" className=\"border-muted-foreground/30 border-t-primary size-icon-sm animate-spin rounded-full border-2\"></div>\n\t\t\t\t\t\t\t\t\t<Text tag=\"span\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t{interpolateFilterString(strings.loadingOptions, { filterLabel })}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\n\t\t\t\t\t{/* One keyed sequence preserves trigger identity as a filter becomes active. */}\n\t\t\t\t\t{[...alwaysVisibleFilters, ...activeRegularFilters].map((filter) => (\n\t\t\t\t\t\t<FilterPill\n\t\t\t\t\t\t\tkey={filter.key}\n\t\t\t\t\t\t\tfilter={filter}\n\t\t\t\t\t\t\tvalue={getFilterValue(filter.key) ?? []}\n\t\t\t\t\t\t\tactive={isFilterActive(filter.key)}\n\t\t\t\t\t\t\toperator={getFilterOperator(filter.key) || 'equals'}\n\t\t\t\t\t\t\toperators={getFilterOperators(filter)}\n\t\t\t\t\t\t\tonOperatorChange={(operator) => handleOperatorChange(filter.key, operator)}\n\t\t\t\t\t\t\tonValueChange={(value) => handlePillValueChange(filter, value)}\n\t\t\t\t\t\t\tonClear={() => handlePillValueChange(filter, [])}\n\t\t\t\t\t\t\tavailableFilters={popoverFilters}\n\t\t\t\t\t\t\tactiveFilters={[...activeRegularFilters, ...alwaysVisibleFilters]}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\n\t\t\t\t\t{popoverFilters.length > 0 && (\n\t\t\t\t\t\t<FilterErrorBoundary filterKey=\"filters-button\">\n\t\t\t\t\t\t\t<FiltersButton\n\t\t\t\t\t\t\t\ttriggerRef={addFilterRef}\n\t\t\t\t\t\t\t\tavailableFilters={popoverFilters}\n\t\t\t\t\t\t\t\tactiveFilters={activeRegularFilters}\n\t\t\t\t\t\t\t\tactiveFilterInPopover={activeFilterInPopover}\n\t\t\t\t\t\t\t\tgetFilterValue={getFilterValue}\n\t\t\t\t\t\t\t\tsetFilterValue={setFilterValue}\n\t\t\t\t\t\t\t\tsetActiveFilterInPopover={setActiveFilterInPopover}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</FilterErrorBoundary>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{!!showClearFilters && hasActive && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tonClick={isNavigating ? undefined : clearFilters}\n\t\t\t\t\t\t\taria-disabled={isNavigating || undefined}\n\t\t\t\t\t\t\tclassName=\"text-muted-foreground ml-auto\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{strings.clearFilters}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</Stack>\n\t\t</Stack>\n\t);\n}\n","import { resolveDefaultOperator } from './operator-options';\nimport {\n\ttype ActiveFilter,\n\ttype FilterConfig,\n\ttype FilterOperator,\n\tFilterOperatorEnum,\n\tFilterType,\n} from './filters.types';\nimport { getRangeBounds, isCompleteDateRange, isMultiValueFilter } from './utils/filter-utils';\n\nexport type FilterQueryValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| undefined\n\t| readonly (string | number | boolean | null | undefined)[];\n\nexport type FilterQueryRecord = Record<string, string | string[] | undefined>;\n\nexport type FilterQueryInput =\n\t| URLSearchParams\n\t| Record<string, FilterQueryValue>;\n\nexport type FilterQueryArrayFormat = 'repeat' | 'comma';\nexport type FilterQueryOperatorMode = 'changed' | 'always' | 'never';\n\nexport interface FilterQueryOptions {\n\t/** Suffix for the companion operator query key. Default: `__op`. */\n\toperatorSuffix?: string;\n\t/** Array encoding for multi-value filters. Default: repeated keys/string arrays. */\n\tarrayFormat?: FilterQueryArrayFormat;\n\t/** Keep unrelated query keys while serializing filters. Default: true. */\n\tpreserveUnrelated?: boolean;\n\t/** Query keys to remove when filters change. Default: `['page']`. */\n\tresetPageKeys?: readonly string[];\n\t/** Include filter operator query keys. Default: only when not the configured default. */\n\tincludeOperators?: FilterQueryOperatorMode;\n}\n\nconst DEFAULT_OPERATOR_SUFFIX = '__op';\nconst DEFAULT_RESET_PAGE_KEYS = ['page'] as const;\n\nconst filterOperators = new Set<string>(Object.values(FilterOperatorEnum));\n\nfunction normalizeQuery(input?: FilterQueryInput): Record<string, string[]> {\n\tconst record: Record<string, string[]> = {};\n\tif (!input) return record;\n\n\tif (input instanceof URLSearchParams) {\n\t\tinput.forEach((value, key) => {\n\t\t\trecord[key] = [...(record[key] ?? []), value];\n\t\t});\n\t\treturn record;\n\t}\n\n\tfor (const [key, value] of Object.entries(input)) {\n\t\tconst values = Array.isArray(value) ? value : [value];\n\t\tconst normalized = values\n\t\t\t.filter((item): item is string | number | boolean => (\n\t\t\t\titem !== null &&\n\t\t\t\titem !== undefined\n\t\t\t))\n\t\t\t.map((item) => String(item));\n\n\t\tif (normalized.some(Boolean)) {\n\t\t\trecord[key] = normalized;\n\t\t}\n\t}\n\n\treturn record;\n}\n\nfunction toPublicRecord(record: Record<string, string[]>): FilterQueryRecord {\n\tconst out: FilterQueryRecord = {};\n\tfor (const [key, values] of Object.entries(record)) {\n\t\tif (values.length === 0) continue;\n\t\tout[key] = values.length === 1 ? values[0] : values;\n\t}\n\treturn out;\n}\n\nfunction readValues(\n\trecord: Record<string, string[]>,\n\tkey: string,\n\tarrayFormat: FilterQueryArrayFormat,\n): string[] {\n\tconst values = record[key] ?? [];\n\tif (arrayFormat === 'comma') {\n\t\treturn values.flatMap((value) => value.split(','));\n\t}\n\treturn values;\n}\n\nfunction normalizeValues(\n\tconfig: FilterConfig,\n\tvalues: readonly string[],\n): string[] {\n\treturn values\n\t\t.map((value) => value.trim())\n\t\t.filter((value) => value.length > 0)\n\t\t.map((value) => {\n\t\t\tif (!config.parse) return value;\n\t\t\tconst parsed = config.parse(value);\n\t\t\treturn parsed === null || parsed === undefined ? '' : String(parsed);\n\t\t})\n\t\t.filter((value) => value.length > 0);\n}\n\nfunction formatValues(config: FilterConfig, values: readonly string[]): string[] {\n\treturn values\n\t\t.map((value) => {\n\t\t\tconst transformed = config.transform ? config.transform(value) : value;\n\t\t\tconst formatted = config.format ? config.format(transformed) : transformed;\n\t\t\treturn formatted === null || formatted === undefined ? '' : String(formatted);\n\t\t})\n\t\t.filter((value) => value.length > 0);\n}\n\nconst getDefaultOperator = resolveDefaultOperator;\n\nfunction readOperator(\n\tconfig: FilterConfig,\n\trecord: Record<string, string[]>,\n\toperatorSuffix: string,\n): FilterOperator {\n\tconst [operator] = record[`${config.key}${operatorSuffix}`] ?? [];\n\tif (operator && filterOperators.has(operator)) {\n\t\treturn operator as FilterOperator;\n\t}\n\treturn getDefaultOperator(config);\n}\n\nfunction shouldEncodeOperator(\n\tmode: FilterQueryOperatorMode,\n\toperator: FilterOperator,\n\tdefaultOperator: FilterOperator,\n): boolean {\n\tif (mode === 'always') return true;\n\tif (mode === 'never') return false;\n\treturn operator !== defaultOperator;\n}\n\nexport function parseFiltersFromQuery(\n\tfilterConfigs: readonly FilterConfig[],\n\tquery: FilterQueryInput,\n\toptions: FilterQueryOptions = {},\n): ActiveFilter[] {\n\tconst operatorSuffix = options.operatorSuffix ?? DEFAULT_OPERATOR_SUFFIX;\n\tconst arrayFormat = options.arrayFormat ?? 'repeat';\n\tconst record = normalizeQuery(query);\n\n\treturn filterConfigs.flatMap((config) => {\n\t\tconst rawValues = readValues(record, config.key, arrayFormat);\n\t\tconst operator = readOperator(config, record, operatorSuffix);\n\t\tif (config.type === FilterType.RANGE) {\n\t\t\tconst value = getRangeBounds(rawValues, operator)\n\t\t\t\t.map((bound) => normalizeValues(config, [bound])[0] ?? '');\n\t\t\treturn value.some(Boolean) ? [{ id: config.key, key: config.key, operator, value }] : [];\n\t\t}\n\n\t\tconst values = normalizeValues(config, rawValues);\n\t\tif (values.length === 0) return [];\n\t\tconst dateRange = config.type === FilterType.DATE && operator === FilterOperatorEnum.BETWEEN;\n\t\tif (dateRange && !isCompleteDateRange(values)) return [];\n\n\t\treturn [{\n\t\t\tid: config.key,\n\t\t\tkey: config.key,\n\t\t\toperator,\n\t\t\tvalue: dateRange || isMultiValueFilter(config) ? values : [values[0]!],\n\t\t} satisfies ActiveFilter];\n\t});\n}\n\nexport function serializeFiltersToQuery(\n\tfilterConfigs: readonly FilterConfig[],\n\tactiveFilters: readonly ActiveFilter[],\n\tcurrentQuery?: FilterQueryInput,\n\toptions: FilterQueryOptions = {},\n): FilterQueryRecord {\n\tconst operatorSuffix = options.operatorSuffix ?? DEFAULT_OPERATOR_SUFFIX;\n\tconst arrayFormat = options.arrayFormat ?? 'repeat';\n\tconst preserveUnrelated = options.preserveUnrelated ?? true;\n\tconst includeOperators = options.includeOperators ?? 'changed';\n\tconst resetPageKeys = options.resetPageKeys ?? DEFAULT_RESET_PAGE_KEYS;\n\tconst nextRecord = preserveUnrelated ? normalizeQuery(currentQuery) : {};\n\tconst configByKey = new Map(filterConfigs.map((config) => [config.key, config]));\n\n\tfor (const config of filterConfigs) {\n\t\tdelete nextRecord[config.key];\n\t\tdelete nextRecord[`${config.key}${operatorSuffix}`];\n\t}\n\tfor (const key of resetPageKeys) {\n\t\tdelete nextRecord[key];\n\t}\n\n\tfor (const activeFilter of activeFilters) {\n\t\tconst config = configByKey.get(activeFilter.key);\n\t\tif (!config) continue;\n\n\t\tconst values = config.type === FilterType.RANGE\n\t\t\t? getRangeBounds(activeFilter.value, activeFilter.operator).map((bound) => bound ? formatValues(config, [bound])[0] ?? '' : '')\n\t\t\t: formatValues(config, activeFilter.value);\n\t\tif (!values.some(Boolean)) continue;\n\t\tif (config.type === FilterType.DATE && activeFilter.operator === FilterOperatorEnum.BETWEEN && !isCompleteDateRange(values)) continue;\n\n\t\tnextRecord[activeFilter.key] = arrayFormat === 'comma'\n\t\t\t? [values.join(',')]\n\t\t\t: values;\n\n\t\tconst defaultOperator = getDefaultOperator(config);\n\t\tif (shouldEncodeOperator(includeOperators, activeFilter.operator, defaultOperator)) {\n\t\t\tnextRecord[`${activeFilter.key}${operatorSuffix}`] = [activeFilter.operator];\n\t\t}\n\t}\n\n\treturn toPublicRecord(nextRecord);\n}\n\nexport function mergeFilterQuery(\n\tcurrentQuery: FilterQueryInput,\n\tnextFilterQuery: FilterQueryInput,\n\toptions: Pick<FilterQueryOptions, 'preserveUnrelated' | 'resetPageKeys'> = {},\n): FilterQueryRecord {\n\tconst preserveUnrelated = options.preserveUnrelated ?? true;\n\tconst resetPageKeys = options.resetPageKeys ?? DEFAULT_RESET_PAGE_KEYS;\n\tconst current = preserveUnrelated ? normalizeQuery(currentQuery) : {};\n\tconst next = normalizeQuery(nextFilterQuery);\n\n\tfor (const key of resetPageKeys) {\n\t\tdelete current[key];\n\t}\n\n\tfor (const [key, values] of Object.entries(next)) {\n\t\tif (values.length === 0) {\n\t\t\tdelete current[key];\n\t\t} else {\n\t\t\tcurrent[key] = values;\n\t\t}\n\t}\n\n\treturn toPublicRecord(current);\n}\n","import { ChevronsUpDown } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport { PopoverMenu, type PopoverMenuItem } from '../../../base/popover-menu';\nimport { Text } from '../../../typography';\nimport { Button } from '../../../base/buttons';\nimport { Cascader } from '../../../base/cascader';\nimport { formFieldTriggerClasses, resolveFormControlSize } from '../../../base/forms/form-sizing';\nimport { useDensityConfig } from '../../../../lib/ui-provider';\nimport { cn } from '../../../../lib/utils';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig } from '../filters.types';\nimport { getFilterOptionLabel, hasNestedFilterOptions, isMultiValueFilter, labelInRunningText, toCascaderNodes } from '../utils/filter-utils';\n\nexport interface SelectFacetProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired with the next value. */\n\tonValueChange: (value: string[]) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\n/**\n * SelectFacet — single/multi-select dropdown filter.\n *\n * Composes `PopoverMenu` for the popover + searchable list pattern.\n * Multi-select keeps the popover open after a tap; single-select closes\n * unless `closeOnSelect=false` is passed in the filter config. Options with\n * `children` use the Cascader field instead, one level at a time.\n */\nexport function SelectFacet({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: SelectFacetProps) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveFormControlSize(undefined, defaultScale);\n\tconst { strings } = useFilters();\n\tconst [open, setOpen] = useState(false);\n\tconst [searchInput, setSearchInput] = useState('');\n\tconst hasSelection = value.length > 0;\n\n\tconst options = filter.options;\n\t// The same rule as the popover editor and the query helpers.\n\tconst isMulti = isMultiValueFilter(filter);\n\tconst atMaxSelected = isMulti && !!filter.maxSelected && value.length >= filter.maxSelected;\n\n\tconst handleSelect = (selectedValue: string) => {\n\t\tif (isMulti) {\n\t\t\tif (value.includes(selectedValue)) {\n\t\t\t\tonValueChange(value.filter((v) => v !== selectedValue));\n\t\t\t} else if (!atMaxSelected) {\n\t\t\t\tonValueChange([...value, selectedValue]);\n\t\t\t}\n\t\t} else {\n\t\t\tonValueChange([selectedValue]);\n\t\t\tif (filter.closeOnSelect !== false) {\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst getOptionLabel = (optionValue: string) =>\n\t\tgetFilterOptionLabel(filter, optionValue) ?? optionValue;\n\tconst nestedNodes = useMemo(() => (hasNestedFilterOptions(options) ? toCascaderNodes(options ?? []) : null), [options]);\n\n\tconst items = useMemo<PopoverMenuItem[]>(() => {\n\t\treturn (options ?? []).map((option) => ({\n\t\t\tvalue: option.value,\n\t\t\tlabel: option.label,\n\t\t\tdescription: option.description,\n\t\t\ticon: option.icon,\n\t\t\tselected: value.includes(option.value),\n\t\t\tdisabled: option.disabled || (atMaxSelected && !value.includes(option.value)),\n\t\t}));\n\t}, [options, value, atMaxSelected]);\n\n\tconst placeholderInterpolated = interpolateFilterString(\n\t\tstrings.searchPlaceholder,\n\t\t{ filterLabel: filter.label.toLowerCase() },\n\t);\n\n\tconst selectedText = interpolateFilterString(strings.selected, {\n\t\tcount: value.length,\n\t\tfilterLabel: labelInRunningText((value.length > 1 ? filter.pluralLabel : filter.label) ?? filter.label),\n\t});\n\n\tif (nestedNodes) {\n\t\treturn (\n\t\t\t<div className={cn('select-facet--component', 'relative', className)}>\n\t\t\t\t<Cascader\n\t\t\t\t\titems={nestedNodes}\n\t\t\t\t\tvalue={isMulti ? value : (value[0] ?? null)}\n\t\t\t\t\tmultiple={isMulti}\n\t\t\t\t\tselectable={filter.selectableOptions ?? 'leaf'}\n\t\t\t\t\tsize={size}\n\t\t\t\t\taria-label={filter.label}\n\t\t\t\t\tstrings={{\n\t\t\t\t\t\tplaceholder: filter.placeholder ?? strings.select,\n\t\t\t\t\t\tsearch: placeholderInterpolated,\n\t\t\t\t\t\tempty: strings.noOptionsFound,\n\t\t\t\t\t\troot: filter.label,\n\t\t\t\t\t\tback: strings.previousLevel,\n\t\t\t\t\t\tselectCurrent: strings.selectCurrentLevel,\n\t\t\t\t\t}}\n\t\t\t\t\trenderValue={value.length > 1 ? () => selectedText : undefined}\n\t\t\t\t\tonValueChange={(next) => onValueChange(next == null ? [] : typeof next === 'string' ? [next] : [...next])}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div className={cn('select-facet--component', 'relative', className)}>\n\t\t\t<PopoverMenu\n\t\t\t\topen={open}\n\t\t\t\tonOpenChange={setOpen}\n\t\t\t\tsearch\n\t\t\t\tsearchValue={searchInput}\n\t\t\t\tonSearchChange={setSearchInput}\n\t\t\t\tstrings={{\n\t\t\t\t\tsearchPlaceholder: placeholderInterpolated,\n\t\t\t\t\tempty: strings.noOptionsFound,\n\t\t\t\t}}\n\t\t\t\tcontentClassName=\"w-(--anchor-width) min-w-56\"\n\t\t\t\ttrigger={\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t// oxlint-disable-next-line jsx-a11y/role-has-required-aria-props -- PopoverTrigger supplies aria-controls while the popup is open.\n\t\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\t\taria-expanded={open}\n\t\t\t\t\t\tclassName={formFieldTriggerClasses(size)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{hasSelection ? (\n\t\t\t\t\t\t\tvalue.length === 1 ? (\n\t\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"semibold\" className=\"truncate\">\n\t\t\t\t\t\t\t\t\t{getOptionLabel(value[0])}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<Text tag=\"span\" weight=\"semibold\">\n\t\t\t\t\t\t\t\t\t{selectedText}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text tag=\"span\" type=\"secondary\">\n\t\t\t\t\t\t\t\t{filter.placeholder ?? strings.select}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<ChevronsUpDown className=\"ml-control-gap-small size-icon-sm shrink-0 opacity-50\" />\n\t\t\t\t\t</Button>\n\t\t\t\t}\n\t\t\t\titems={items}\n\t\t\t\tonSelect={(item) => handleSelect(item.value)}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { Check, ChevronsUpDown } from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { formFieldTriggerClasses, resolveFormControlSize } from '../../../base/forms/form-sizing';\nimport { useDensityConfig } from '../../../../lib/ui-provider';\nimport {\n\tCommand,\n\tCommandEmpty,\n\tCommandGroup,\n\tCommandInput,\n\tCommandItem,\n\tCommandList,\n} from '../../../base/command';\nimport {\n\tPopover,\n\tPopoverContent,\n\tPopoverTrigger,\n} from '../../../base/popover';\nimport { ErrorState, LoadingState } from '../../../base/feedback';\nimport { Text } from '../../../typography';\nimport { cn } from '../../../../lib/utils';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig, FilterOption } from '../filters.types';\nimport { useAsyncOptions } from '../hooks';\nimport { AsyncOptionsAnnouncer, AsyncOptionsStatus } from '../partials/async-options-status';\nimport { labelInRunningText } from '../utils/filter-utils';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AsyncSelectFacetProps {\n\t/** Definition of the filter this control edits. */\n\tfilter: FilterConfig;\n\t/** Current value. */\n\tvalue: string[];\n\t/** Fired with the next value. */\n\tonValueChange: (value: string[]) => void;\n\t/** Merged onto the outermost node. */\n\tclassName?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * Async Select Filter Facet\n *\n * Async option facet for server-side or consumer-managed option loading.\n * Supports:\n * - Live typeahead search with debounce + AbortSignal\n * - Loading, error, empty, min-query-hint states\n * - Preload (fetch default options on open)\n * - Multi-select with maxSelected enforcement\n * - Options label cache for pill display after popover close\n */\nexport function AsyncSelectFacet({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: AsyncSelectFacetProps) {\n\tconst { defaultScale } = useDensityConfig();\n\tconst size = resolveFormControlSize(undefined, defaultScale);\n\tconst { strings, cacheAsyncOptions, getAsyncOptionLabel, reportError } = useFilters();\n\tconst [open, setOpen] = useState(false);\n\tconst [searchInput, setSearchInput] = useState('');\n\n\t// Cache resolved option labels so pills can show labels after popover closes\n\t// oxlint-disable-next-line react-hooks/exhaustive-deps -- The key, fetcher and mapper reset the cache; the factory reads none of them.\n\tconst labelCache = useMemo(() => new Map<string, FilterOption>(), [\n\t\tfilter.key, filter.asyncConfig?.fetcher, filter.asyncConfig?.mapToOption,\n\t]);\n\n\tconst {\n\t\toptions,\n\t\tisLoading,\n\t\tisFetching,\n\t\tisError,\n\t\trefetch,\n\t\tisBelowMinQuery,\n\t\tminQueryLength,\n\t} = useAsyncOptions(filter, searchInput, open, {\n\t\tonError: reportError,\n\t});\n\n\t// Update label caches after render; cacheAsyncOptions triggers provider state.\n\tuseEffect(() => {\n\t\tif (options.length === 0) return;\n\n\t\tfor (const opt of options) {\n\t\t\tlabelCache.set(opt.value, opt);\n\t\t}\n\t\tcacheAsyncOptions(filter.key, options);\n\t}, [cacheAsyncOptions, filter.key, labelCache, options]);\n\n\tconst isMulti = filter.multiple !== false;\n\tconst maxSelected = filter.maxSelected;\n\tconst initialOptions = useMemo(() => filter.options ?? [], [filter.options]);\n\n\t// Sort options: selected items first, then the rest.\n\t// Also include cached selected items that may not be in current search results.\n\tconst sortedOptions = useMemo(() => {\n\t\tconst selectedSet = new Set(value);\n\t\tconst optionValueSet = new Set(\n\t\t\t[...initialOptions, ...options].map((o) => o.value),\n\t\t);\n\n\t\t// Resolve selected items missing from current results via caches\n\t\tconst missingSelected: FilterOption[] = [];\n\t\tfor (const val of value) {\n\t\t\tif (!optionValueSet.has(val)) {\n\t\t\t\tconst cached = labelCache.get(val);\n\t\t\t\tif (cached) {\n\t\t\t\t\tmissingSelected.push(cached);\n\t\t\t\t} else {\n\t\t\t\t\tconst initial = initialOptions.find((o) => o.value === val);\n\t\t\t\t\tif (initial) {\n\t\t\t\t\t\tmissingSelected.push(initial);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// An unresolved value stays listed by its raw value, so it can be deselected.\n\t\t\t\t\tconst label = getAsyncOptionLabel(filter.key, val) ?? val;\n\t\t\t\t\tmissingSelected.push({ value: val, label, icon: filter.icon });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst all = [...missingSelected, ...initialOptions, ...options];\n\t\treturn all.sort((a, b) => {\n\t\t\tconst aSelected = selectedSet.has(a.value) ? 0 : 1;\n\t\t\tconst bSelected = selectedSet.has(b.value) ? 0 : 1;\n\t\t\treturn aSelected - bSelected;\n\t\t});\n\t}, [initialOptions, options, value, filter.key, filter.icon, labelCache, getAsyncOptionLabel]);\n\n\tconst handleSelect = (selectedValue: string) => {\n\t\tif (isMulti) {\n\t\t\tif (value.includes(selectedValue)) {\n\t\t\t\tonValueChange(value.filter((v) => v !== selectedValue));\n\t\t\t} else {\n\t\t\t\tif (maxSelected && value.length >= maxSelected) return;\n\t\t\t\tonValueChange([...value, selectedValue]);\n\t\t\t}\n\t\t} else {\n\t\t\tonValueChange([selectedValue]);\n\t\t\tif (filter.closeOnSelect !== false) {\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst getOptionLabel = (optionValue: string): string => {\n\t\t// Check current options first, then cache\n\t\tconst fromOptions = options.find((o) => o.value === optionValue);\n\t\tif (fromOptions) return fromOptions.label;\n\t\tconst fromInitialOptions = initialOptions.find((o) => o.value === optionValue);\n\t\tif (fromInitialOptions) return fromInitialOptions.label;\n\t\tconst cached = labelCache.get(optionValue);\n\t\tif (cached) return cached.label;\n\t\treturn getAsyncOptionLabel(filter.key, optionValue) ?? optionValue;\n\t};\n\n\tconst hasSelection = value.length > 0;\n\n\t// Determine the empty state message\n\tconst emptyMessage = useMemo(() => {\n\t\tif (isLoading || isFetching) {\n\t\t\treturn (\n\t\t\t\t<LoadingState className=\"async-select-facet--component\" label={strings.searching} />\n\t\t\t);\n\t\t}\n\n\t\tif (isError) {\n\t\t\treturn (\n\t\t\t\t<ErrorState\n\t\t\t\t\tvariant=\"inline\"\n\t\t\t\t\ttitle={strings.fetchError}\n\t\t\t\t\taction={\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.stopPropagation();\n\t\t\t\t\t\t\t\tvoid refetch();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{strings.retryFetch}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\tif (isBelowMinQuery) {\n\t\t\treturn (\n\t\t\t\t<div className=\"text-muted-foreground flex items-center justify-center py-space-xl\">\n\t\t\t\t\t<Text\n\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\tsize=\"xs\"\n\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{interpolateFilterString(strings.minQueryHint, {\n\t\t\t\t\t\t\tmin: minQueryLength,\n\t\t\t\t\t\t})}\n\t\t\t\t\t</Text>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<Text\n\t\t\t\ttag=\"span\"\n\t\t\t\ttype=\"secondary\"\n\t\t\t>\n\t\t\t\t{strings.noOptionsFound}\n\t\t\t</Text>\n\t\t);\n\t}, [\n\t\tisLoading,\n\t\tisFetching,\n\t\tisError,\n\t\tisBelowMinQuery,\n\t\tminQueryLength,\n\t\tstrings,\n\t\trefetch,\n\t]);\n\n\treturn (\n\t\t<div className={cn('async-select-facet--component relative', className)}>\n\t\t\t<Popover\n\t\t\t\topen={open}\n\t\t\t\tonOpenChange={(next) => {\n\t\t\t\t\tsetOpen(next);\n\t\t\t\t\tif (!next) setSearchInput('');\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<PopoverTrigger\n\t\t\t\t\trender={\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"outline\"\n\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t\t// oxlint-disable-next-line jsx-a11y/role-has-required-aria-props -- PopoverTrigger supplies aria-controls while the popup is open.\n\t\t\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\t\t\taria-expanded={open}\n\t\t\t\t\t\t\tclassName={formFieldTriggerClasses(size)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{hasSelection ? (\n\t\t\t\t\t\t\t\tvalue.length === 1 ? (\n\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"truncate\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{getOptionLabel(value[0])}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\tweight=\"semibold\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{interpolateFilterString(strings.selected, {\n\t\t\t\t\t\t\t\t\t\t\tcount: value.length,\n\t\t\t\t\t\t\t\t\t\t\tfilterLabel: labelInRunningText(\n\t\t\t\t\t\t\t\t\t\t\t\t(value.length > 1\n\t\t\t\t\t\t\t\t\t\t\t\t\t? filter.pluralLabel\n\t\t\t\t\t\t\t\t\t\t\t\t\t: filter.label) ?? filter.label,\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\ttype=\"secondary\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{filter.placeholder ?? strings.select}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<ChevronsUpDown className=\"ml-control-gap-small size-icon-sm shrink-0 opacity-50\" />\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t\t<PopoverContent type=\"menu\" inset=\"flush\" className=\"w-full min-w-70 gap-0\">\n\t\t\t\t\t<Command shouldFilter={false} inset=\"flush\" className=\"rounded-none\">\n\t\t\t\t\t\t<CommandInput\n\t\t\t\t\t\t\tplaceholder={interpolateFilterString(\n\t\t\t\t\t\t\t\tstrings.searchPlaceholder,\n\t\t\t\t\t\t\t\t{ filterLabel: filter.label },\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tvalue={searchInput}\n\t\t\t\t\t\t\tonValueChange={setSearchInput}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<CommandList aria-busy={isFetching || undefined}>\n\t\t\t\t\t\t\t{sortedOptions.length === 0 ? (\n\t\t\t\t\t\t\t\t<CommandEmpty>{emptyMessage}</CommandEmpty>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<CommandGroup>\n\t\t\t\t\t\t\t\t\t<AsyncOptionsStatus fetching={isFetching} error={isError} onRetry={refetch} />\n\t\t\t\t\t\t\t\t\t{sortedOptions.map((option) => (\n\t\t\t\t\t\t\t\t\t\t<CommandItem\n\t\t\t\t\t\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\t\t\t\t\t\tvalue={option.value}\n\t\t\t\t\t\t\t\t\t\t\tonSelect={() => handleSelect(option.value)}\n\t\t\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\t\t\toption.disabled ||\n\t\t\t\t\t\t\t\t\t\t\t\t(!!maxSelected &&\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue.length >= maxSelected &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t!value.includes(option.value))\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<Check\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'mr-control-gap size-icon-sm',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue.includes(option.value)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'opacity-100'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'opacity-0',\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t{Boolean(option.icon) && (\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"mr-1.5\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{option.icon}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</CommandItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</CommandGroup>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</CommandList>\n\t\t\t\t\t</Command>\n\t\t\t\t\t<AsyncOptionsAnnouncer fetching={isFetching} error={isError} count={options.length} hasRows={sortedOptions.length > 0} />\n\t\t\t\t</PopoverContent>\n\t\t\t</Popover>\n\t\t</div>\n\t);\n}\n\n/**\n * Retrieve the label cache ref from an AsyncSelectFacet instance.\n * This is used by FilterValueDisplay to resolve labels for active async filters.\n */\nexport type AsyncSelectLabelCache = Map<string, FilterOption>;\n","/**\n * Validator helpers for `FilterConfig.validation.custom`.\n *\n * Our `ValidationConfig` accepts `custom: (value) => boolean | string`\n * already (`true` = valid, `false` = generic invalid, `string` = custom\n * error message). These helpers adapt common third-party validators\n * — Zod, Valibot, plain async-safe predicates — to that shape so\n * consumers don't reinvent the bridge.\n *\n * The library does NOT depend on Zod or any specific validation lib.\n * The helpers are written against minimal duck-typed shapes that any\n * library implementing `safeParse` can satisfy.\n */\nimport type { ValidationConfig } from './filters.types';\n\n/**\n * Minimal Zod-compatible interface — a schema with a `safeParse` method\n * that returns `{ success: boolean, error?: { message?: string,\n * issues?: { message: string }[] } }`. Both Zod 3 and Zod 4 satisfy\n * this; Valibot's `safeParse` differs slightly but a thin wrapper\n * works.\n */\nexport interface SafeParseSchema<TInput = unknown> {\n\tsafeParse(value: TInput): {\n\t\tsuccess: boolean;\n\t\terror?: {\n\t\t\tmessage?: string;\n\t\t\tissues?: { message: string }[];\n\t\t};\n\t};\n}\n\n/**\n * Adapter: turn a Zod-like schema into a `ValidationConfig['custom']`.\n *\n * import { z } from 'zod';\n * import { zodValidator } from '.';\n *\n * const emailSchema = z.string().email();\n * const config: FilterConfig = {\n * …,\n * validation: { custom: zodValidator(emailSchema) },\n * };\n *\n * On parse failure the first issue's `message` is returned (so\n * Zod's `.refine(...).message('Custom')` flows through). On success\n * returns `true`. The empty-string case is bypassed — let\n * `validation.required` handle \"must not be empty\" so error messages\n * stay coherent.\n */\nexport function zodValidator<TInput = unknown>(\n\tschema: SafeParseSchema<TInput>,\n): NonNullable<ValidationConfig['custom']> {\n\treturn (value: unknown): boolean | string => {\n\t\t// Skip empty strings — `validation.required` is the right channel\n\t\t// for \"missing value\" messaging.\n\t\tif (value === undefined || value === null) return true;\n\t\tif (typeof value === 'string' && value.length === 0) return true;\n\t\tconst result = schema.safeParse(value as TInput);\n\t\tif (result.success) return true;\n\t\tconst message =\n\t\t\tresult.error?.issues?.[0]?.message ??\n\t\t\tresult.error?.message ??\n\t\t\tfalse;\n\t\treturn message as string | false;\n\t};\n}\n\n/**\n * Adapter: pair a predicate with a static error message. Useful when\n * the consumer doesn't want to pull a validation library at all.\n *\n * validation: {\n * custom: predicateValidator(\n * (v) => /^https?:\\/\\//.test(String(v)),\n * 'URL must start with http:// or https://',\n * ),\n * }\n */\nexport function predicateValidator(\n\tpredicate: (value: unknown) => boolean,\n\tmessage: string,\n): NonNullable<ValidationConfig['custom']> {\n\treturn (value: unknown) => (predicate(value) ? true : message);\n}\n"],"mappings":"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"}