themelia-react-ui 1.0.1 → 2.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.
- package/CHANGELOG.md +417 -0
- package/README.md +67 -16
- package/dist/{accordion-B-5Focs8.js → accordion-CQXVcd7Q.js} +15 -15
- package/dist/accordion-CQXVcd7Q.js.map +1 -0
- package/dist/action-menu-BTpyPWJ2.js +264 -0
- package/dist/action-menu-BTpyPWJ2.js.map +1 -0
- package/dist/affordance-geometry.generated-CCIXb2A1.js +68 -0
- package/dist/affordance-geometry.generated-CCIXb2A1.js.map +1 -0
- package/dist/{ai-artifact-B5tPpXnS.js → ai-artifact-2PQ2fItc.js} +206 -215
- package/dist/ai-artifact-2PQ2fItc.js.map +1 -0
- package/dist/{app-shell-at8Kt4l_.js → app-shell-BE_j8-AT.js} +11 -10
- package/dist/app-shell-BE_j8-AT.js.map +1 -0
- package/dist/{attachment-BO2R47wn.js → attachment-q69dlt5Y.js} +14 -14
- package/dist/attachment-q69dlt5Y.js.map +1 -0
- package/dist/auth-M3vGMgDR.js +723 -0
- package/dist/auth-M3vGMgDR.js.map +1 -0
- package/dist/{avatar-Bpzty83c.js → avatar-djdaaQ_s.js} +15 -13
- package/dist/avatar-djdaaQ_s.js.map +1 -0
- package/dist/{badge-BZXZT9wd.js → badge-0tATj-tW.js} +9 -9
- package/dist/badge-0tATj-tW.js.map +1 -0
- package/dist/base/accordion.js +1 -1
- package/dist/base/action-menu.js +1 -1
- package/dist/base/attachment.js +1 -1
- package/dist/base/avatar.js +1 -1
- package/dist/base/badge.js +1 -1
- package/dist/base/buttons.js +3 -2
- package/dist/base/cards.js +3 -3
- package/dist/base/carousel.js +33 -35
- package/dist/base/carousel.js.map +1 -1
- package/dist/base/cascader.js +246 -222
- package/dist/base/cascader.js.map +1 -1
- package/dist/base/chart.js +1 -1
- package/dist/base/choice-inputs.js +2 -2
- package/dist/base/code-block.js +1 -1
- package/dist/base/combobox.js +1 -1
- package/dist/base/command.js +1 -1
- package/dist/base/copyable.js +1 -1
- package/dist/base/date-pickers.js +3 -3
- package/dist/base/display.js +7 -7
- package/dist/base/feedback.js +4 -4
- package/dist/base/forms-numeric.js +1 -1
- package/dist/base/forms.js +2 -2
- package/dist/base/inline-edit.js +94 -92
- package/dist/base/inline-edit.js.map +1 -1
- package/dist/base/item.js +1 -1
- package/dist/base/media-gallery.js +1 -1
- package/dist/base/navigation.js +6 -6
- package/dist/base/popover-menu.js +1 -1
- package/dist/base/popover.js +1 -1
- package/dist/base/qr-code.js +7 -4
- package/dist/base/qr-code.js.map +1 -1
- package/dist/base/repeaters.js +53 -53
- package/dist/base/repeaters.js.map +1 -1
- package/dist/base/sheet.js +1 -1
- package/dist/base/sidebar.js +1 -1
- package/dist/base/signature-pad.js +84 -82
- package/dist/base/signature-pad.js.map +1 -1
- package/dist/base/skeleton.js +1 -1
- package/dist/base/spinner.js +1 -1
- package/dist/base/structure.js +1 -1
- package/dist/base/table.js +1 -1
- package/dist/base/text-inputs.js +2 -2
- package/dist/base/toaster.js +7 -7
- package/dist/base/toaster.js.map +1 -1
- package/dist/base/tree.js +1 -1
- package/dist/base/upload-queue.js +1 -1
- package/dist/base/upload.js +3 -3
- package/dist/base/value-inputs.js +1 -1
- package/dist/blocks/admin.js +228 -219
- package/dist/blocks/admin.js.map +1 -1
- package/dist/blocks/ai.js +182 -212
- package/dist/blocks/ai.js.map +1 -1
- package/dist/blocks/analytics/usage-card.js +1 -1
- package/dist/blocks/analytics.js +665 -620
- package/dist/blocks/analytics.js.map +1 -1
- package/dist/blocks/collaboration.js +2 -2
- package/dist/blocks/commerce/receipt.js +1 -1
- package/dist/blocks/commerce.js +1439 -1553
- package/dist/blocks/commerce.js.map +1 -1
- package/dist/blocks/data-display.js +1 -1
- package/dist/blocks/onboarding.js +6 -6
- package/dist/blocks/onboarding.js.map +1 -1
- package/dist/blocks/planning.js +88 -97
- package/dist/blocks/planning.js.map +1 -1
- package/dist/blocks/timelines.js +1 -1
- package/dist/{breadcrumbs-DdQ_I5ra.js → breadcrumbs-BG_FfMK4.js} +10 -9
- package/dist/breadcrumbs-BG_FfMK4.js.map +1 -0
- package/dist/button-BS3KDg00.js +674 -0
- package/dist/button-BS3KDg00.js.map +1 -0
- package/dist/{button-BS6l5JUw.js → button-R9CCoH7A.js} +3 -3
- package/dist/button-R9CCoH7A.js.map +1 -0
- package/dist/buttons-DS0ZIwJ_.js +99 -0
- package/dist/buttons-DS0ZIwJ_.js.map +1 -0
- package/dist/{cards-Cum56XOF.js → cards-QoJ4syG9.js} +12 -12
- package/dist/{cards-Cum56XOF.js.map → cards-QoJ4syG9.js.map} +1 -1
- package/dist/chart-DwYRKKc-.js +152 -0
- package/dist/chart-DwYRKKc-.js.map +1 -0
- package/dist/checkbox-B7ygNTYp.js +35 -0
- package/dist/checkbox-B7ygNTYp.js.map +1 -0
- package/dist/choice-inputs-DrJ17tpL.js +752 -0
- package/dist/choice-inputs-DrJ17tpL.js.map +1 -0
- package/dist/{code-block-xHKbAJDj.js → code-block-CD0B7M93.js} +27 -27
- package/dist/code-block-CD0B7M93.js.map +1 -0
- package/dist/{collapsible-DsnktFNv.js → collapsible-oMUGM4tr.js} +3 -3
- package/dist/{collapsible-DsnktFNv.js.map → collapsible-oMUGM4tr.js.map} +1 -1
- package/dist/{collection-content-C4fthJV_.js → collection-content-Ys-OZOkY.js} +3 -3
- package/dist/{collection-content-C4fthJV_.js.map → collection-content-Ys-OZOkY.js.map} +1 -1
- package/dist/combobox-6dvVny2q.js +272 -0
- package/dist/combobox-6dvVny2q.js.map +1 -0
- package/dist/combobox-CB7039j7.js +865 -0
- package/dist/combobox-CB7039j7.js.map +1 -0
- package/dist/{command-C0xe7u9B.js → command-kPMPjIxJ.js} +35 -31
- package/dist/command-kPMPjIxJ.js.map +1 -0
- package/dist/{comments-DviPLnwy.js → comments-You0Bzbr.js} +434 -409
- package/dist/comments-You0Bzbr.js.map +1 -0
- package/dist/components/base/accordion/accordion-variants.d.ts +3 -3
- package/dist/components/base/action-menu/action-menu.d.ts +7 -2
- package/dist/components/base/avatar/stacked-avatars.d.ts +5 -4
- package/dist/components/base/badge/badge.d.ts +1 -1
- package/dist/components/base/badge/badge.recipes.d.ts +4 -4
- package/dist/components/base/buttons/base-button.d.ts +7 -0
- package/dist/components/base/buttons/button-group.recipes.d.ts +2 -2
- package/dist/components/base/buttons/button.recipes.d.ts +10 -19
- package/dist/components/base/buttons/button.variants.d.ts +1 -0
- package/dist/components/base/buttons/loader-button.d.ts +3 -1
- package/dist/components/base/buttons/text-button.d.ts +2 -2
- package/dist/components/base/buttons/use-pending-button-focus.d.ts +3 -0
- package/dist/components/base/cards/card.recipes.d.ts +13 -5
- package/dist/components/base/cards/partials/card-primitives.d.ts +9 -4
- package/dist/components/base/cards/smart-card.types.d.ts +1 -1
- package/dist/components/base/carousel/carousel.d.ts +3 -1
- package/dist/components/base/chart/chart.d.ts +7 -7
- package/dist/components/base/choice-inputs/checkbox.d.ts +6 -7
- package/dist/components/base/choice-inputs/choice-types.d.ts +10 -1
- package/dist/components/base/choice-inputs/pill-radio-group.d.ts +9 -0
- package/dist/components/base/choice-inputs/select-popup.d.ts +9 -1
- package/dist/components/base/choice-inputs/switch-card.d.ts +1 -1
- package/dist/components/base/date-pickers/date-picker-field.d.ts +23 -0
- package/dist/components/base/date-pickers/date-picker.recipes.d.ts +5 -18
- package/dist/components/base/date-pickers/datepicker.types.d.ts +16 -3
- package/dist/components/base/display/alert-dialog.d.ts +8 -2
- package/dist/components/base/display/content-block.d.ts +4 -2
- package/dist/components/base/display/date-block.d.ts +1 -1
- package/dist/components/base/display/dialog.d.ts +12 -5
- package/dist/components/base/display/surface-title.d.ts +6 -1
- package/dist/components/base/feedback/alert.d.ts +1 -1
- package/dist/components/base/feedback/state-display.d.ts +5 -4
- package/dist/components/base/forms/form-field.d.ts +1 -0
- package/dist/components/base/forms/form-sizing.d.ts +35 -3
- package/dist/components/base/forms/workflow.d.ts +2 -0
- package/dist/components/base/forms-numeric/coordinates-input.d.ts +3 -0
- package/dist/components/base/forms-numeric/rounding-mode-select.d.ts +4 -1
- package/dist/components/base/navigation/dropdown-menu.d.ts +2 -2
- package/dist/components/base/navigation/language-switcher.d.ts +4 -1
- package/dist/components/base/navigation/overflow-tab-bar.d.ts +7 -0
- package/dist/components/base/navigation/page-header/page-header.d.ts +4 -1
- package/dist/components/base/navigation/tabs.d.ts +3 -5
- package/dist/components/base/popover/popover.recipes.d.ts +3 -3
- package/dist/components/base/qr-code/qr-code.d.ts +2 -0
- package/dist/components/base/sheet/index.d.ts +29 -1
- package/dist/components/base/sheet/sheet.d.ts +14 -5
- package/dist/components/base/spinner/spinner.d.ts +3 -2
- package/dist/components/base/structure/structure.types.d.ts +1 -1
- package/dist/components/base/table/index.d.ts +1 -1
- package/dist/components/base/text-inputs/clear-native-field.d.ts +2 -0
- package/dist/components/base/text-inputs/input-group.d.ts +2 -2
- package/dist/components/base/text-inputs/input-trailing-action.d.ts +3 -0
- package/dist/components/base/upload/upload.recipes.d.ts +11 -0
- package/dist/components/base/value-inputs/date-time-input.d.ts +4 -2
- package/dist/components/base/value-inputs/tags-input.d.ts +2 -0
- package/dist/components/blocks/admin/api-key-list/api-key-list.types.d.ts +1 -1
- package/dist/components/blocks/analytics/format-metric-value.d.ts +11 -1
- package/dist/components/blocks/analytics/index.d.ts +1 -1
- package/dist/components/blocks/analytics/types.d.ts +1 -1
- package/dist/components/blocks/analytics/use-metric-format-options.d.ts +3 -0
- package/dist/components/blocks/collaboration/message/message.recipes.d.ts +12 -0
- package/dist/components/blocks/commerce/address-card/address-card.d.ts +1 -1
- package/dist/components/blocks/commerce/address-card/types.d.ts +3 -1
- package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.d.ts +4 -0
- package/dist/components/blocks/commerce/booking-calendar-event-card/booking-calendar-event-card.types.d.ts +2 -2
- package/dist/components/blocks/commerce/discount-stack/types.d.ts +1 -1
- package/dist/components/blocks/commerce/inventory-section/types.d.ts +4 -1
- package/dist/components/blocks/commerce/loyalty-points/types.d.ts +1 -1
- package/dist/components/blocks/commerce/order-status/types.d.ts +4 -0
- package/dist/components/blocks/commerce/payment-method/payment-method.d.ts +1 -1
- package/dist/components/blocks/commerce/payment-method/types.d.ts +3 -1
- package/dist/components/blocks/commerce/seo-listing/seo-listing-card.d.ts +1 -1
- package/dist/components/blocks/commerce/seo-listing/types.d.ts +3 -1
- package/dist/components/blocks/commerce/vendor-profile/types.d.ts +4 -1
- package/dist/components/blocks/data-display/dense-info-card/dense-info.strings.d.ts +4 -1
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/document-stack.d.ts +1 -4
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/inbox-clean.d.ts +1 -4
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/index.d.ts +3 -3
- package/dist/components/blocks/data-display/empty-state/partials/illustrations/stacked-cards.d.ts +1 -6
- package/dist/components/blocks/data-display/inline-stat/inline-stat.d.ts +4 -1
- package/dist/components/features/combobox/components/error-message.d.ts +1 -1
- package/dist/components/features/comments/hooks/use-attachment-upload.d.ts +5 -0
- package/dist/components/features/filters/facets/search-facet.d.ts +0 -12
- package/dist/components/features/filters/facets/tags-facet.d.ts +1 -1
- package/dist/components/features/global-search/partials/global-search-idle-state.d.ts +1 -1
- package/dist/components/features/media-library/media-library.d.ts +1 -1
- package/dist/components/features/media-library/media-library.types.d.ts +9 -1
- package/dist/components/features/media-library/partials/media-library-partials.d.ts +1 -1
- package/dist/components/features/overlays/alert-dialog.d.ts +1 -1
- package/dist/components/features/overlays/drawer.d.ts +1 -1
- package/dist/components/features/overlays/hooks/use-overlay-actions.d.ts +2 -2
- package/dist/components/features/overlays/hooks/use-overlay-visibility.d.ts +11 -4
- package/dist/components/features/overlays/hooks/use-pending-overlay-focus.d.ts +2 -0
- package/dist/components/features/overlays/overlay-tone-icon.d.ts +37 -0
- package/dist/components/features/overlays/overlays.types.d.ts +46 -22
- package/dist/components/features/products/components/product-variants-manager.d.ts +1 -1
- package/dist/components/features/products/partials/index.d.ts +1 -1
- package/dist/components/features/products/partials/product-metric-tile.d.ts +6 -0
- package/dist/components/features/products/partials/product-tone.d.ts +11 -1
- package/dist/components/features/products/products.types.d.ts +2 -1
- package/dist/components/features/rich-text-editor/rich-text-editor.recipes.d.ts +2 -1
- package/dist/components/features/table/data-table.d.ts +1 -1
- package/dist/components/features/table/partials/cell-renderers.d.ts +1 -1
- package/dist/components/features/table/table.types.d.ts +1 -1
- package/dist/components/features/theme-tweaker/theme-provider-settings.d.ts +3 -1
- package/dist/components/layout/auth/auth.types.d.ts +1 -0
- package/dist/components/layout/page/index.d.ts +1 -1
- package/dist/components/layout/page/page.d.ts +0 -1
- package/dist/components/layout/page/page.types.d.ts +62 -6
- package/dist/components/layout/page/partials/page-header-commands.d.ts +13 -0
- package/dist/components/layout/page/partials/page-header.d.ts +1 -1
- package/dist/components/layout/sidebar/sidebar.context.d.ts +1 -1
- package/dist/components/layout/sidebar/sidebar.types.d.ts +4 -0
- package/dist/components/layout/workspace/workspace.types.d.ts +3 -0
- package/dist/components/primitives/date.d.ts +16 -3
- package/dist/components/primitives/dimensions.d.ts +6 -0
- package/dist/components/primitives/duration.d.ts +6 -0
- package/dist/components/primitives/file-size.d.ts +6 -0
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/initials.d.ts +11 -2
- package/dist/components/primitives/link.d.ts +7 -0
- package/dist/components/primitives/money.d.ts +29 -7
- package/dist/components/primitives/number.d.ts +17 -0
- package/dist/components/primitives/value-typography.d.ts +54 -0
- package/dist/components/primitives/value.d.ts +31 -6
- package/dist/components/typography/heading.d.ts +13 -2
- package/dist/components/typography/index.d.ts +1 -1
- package/dist/components/typography/label.d.ts +3 -0
- package/dist/components/typography/running-text.d.ts +12 -0
- package/dist/components/typography/text-link.d.ts +23 -1
- package/dist/components/typography/text.d.ts +12 -0
- package/dist/components/typography/text.styles.d.ts +37 -5
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/checkbox.d.ts +5 -0
- package/dist/components/ui/overlay.recipes.d.ts +15 -2
- package/dist/components/ui/popover.d.ts +1 -1
- package/dist/components/ui/select.d.ts +3 -1
- package/dist/components/ui/sidebar.d.ts +1 -1
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/components/ui/table.d.ts +2 -1
- package/dist/container.recipes-D9t8MHR3.js +27 -0
- package/dist/container.recipes-D9t8MHR3.js.map +1 -0
- package/dist/{containers-6s-ucRQQ.js → containers-D_L4mTVb.js} +34 -57
- package/dist/containers-D_L4mTVb.js.map +1 -0
- package/dist/control-group-recipes-DBXmfh2E.js +21 -0
- package/dist/control-group-recipes-DBXmfh2E.js.map +1 -0
- package/dist/{copyable-B7SBXJMr.js → copyable-DDjTeW_j.js} +6 -6
- package/dist/{copyable-B7SBXJMr.js.map → copyable-DDjTeW_j.js.map} +1 -1
- package/dist/data-display-3xWQUnMA.js +1335 -0
- package/dist/data-display-3xWQUnMA.js.map +1 -0
- package/dist/date-picker-DrDFj8Lo.js +1527 -0
- package/dist/date-picker-DrDFj8Lo.js.map +1 -0
- package/dist/date-pickers-CnFCb0n2.js +174 -0
- package/dist/date-pickers-CnFCb0n2.js.map +1 -0
- package/dist/date-uf3z37Nm.js +144 -0
- package/dist/date-uf3z37Nm.js.map +1 -0
- package/dist/{display-CFM5myut.js → display-DrdvPwF0.js} +25 -25
- package/dist/display-DrdvPwF0.js.map +1 -0
- package/dist/{dropdown-menu-BlnyHr-9.js → dropdown-menu-CURh59jb.js} +22 -15
- package/dist/dropdown-menu-CURh59jb.js.map +1 -0
- package/dist/features/activities.js +177 -163
- package/dist/features/activities.js.map +1 -1
- package/dist/features/ai-chat.js +187 -183
- package/dist/features/ai-chat.js.map +1 -1
- package/dist/features/async-preview.js +9 -9
- package/dist/features/async-preview.js.map +1 -1
- package/dist/features/combobox.js +1 -1
- package/dist/features/comments.js +1 -1
- package/dist/features/data-view.js +25 -23
- package/dist/features/data-view.js.map +1 -1
- package/dist/features/email-composer/engine.js +1 -1
- package/dist/features/email-composer.js +353 -355
- package/dist/features/email-composer.js.map +1 -1
- package/dist/features/event-calendar.js +346 -354
- package/dist/features/event-calendar.js.map +1 -1
- package/dist/features/filters.js +1 -1
- package/dist/features/global-search.js +225 -227
- package/dist/features/global-search.js.map +1 -1
- package/dist/features/kanban.js +29 -29
- package/dist/features/kanban.js.map +1 -1
- package/dist/features/map.js +59 -58
- package/dist/features/map.js.map +1 -1
- package/dist/features/media-library.js +898 -900
- package/dist/features/media-library.js.map +1 -1
- package/dist/features/mentions.js +1 -1
- package/dist/features/overlays.js +1 -1
- package/dist/features/products.js +1412 -1444
- package/dist/features/products.js.map +1 -1
- package/dist/features/questionnaire.js +51 -49
- package/dist/features/questionnaire.js.map +1 -1
- package/dist/features/resource-assignment.js +103 -97
- package/dist/features/resource-assignment.js.map +1 -1
- package/dist/features/resource.js +13 -13
- package/dist/features/resource.js.map +1 -1
- package/dist/features/rich-text-editor.js +2 -2
- package/dist/features/schema-form.js +187 -183
- package/dist/features/schema-form.js.map +1 -1
- package/dist/features/suggestions.js +3 -3
- package/dist/features/sync.js +7 -7
- package/dist/features/sync.js.map +1 -1
- package/dist/features/table.js +1 -1
- package/dist/features/theme-tweaker.js +508 -503
- package/dist/features/theme-tweaker.js.map +1 -1
- package/dist/{feedback-DWUkgEjR.js → feedback-C7nR0UtT.js} +30 -31
- package/dist/feedback-C7nR0UtT.js.map +1 -0
- package/dist/field-affordance-recipes-CkOCdE2y.js +46 -0
- package/dist/field-affordance-recipes-CkOCdE2y.js.map +1 -0
- package/dist/{field-state-recipes-CBTRt9Bt.js → field-state-recipes-C-MFBX_8.js} +5 -5
- package/dist/field-state-recipes-C-MFBX_8.js.map +1 -0
- package/dist/{filters-BhsUtsxW.js → filters-Da-gNPsE.js} +760 -765
- package/dist/filters-Da-gNPsE.js.map +1 -0
- package/dist/{form-field-Bn7ZH1rA.js → form-field-VZRULhUK.js} +20 -12
- package/dist/form-field-VZRULhUK.js.map +1 -0
- package/dist/form-sizing-uWP4lzVh.js +126 -0
- package/dist/form-sizing-uWP4lzVh.js.map +1 -0
- package/dist/{forms-B7pzS25o.js → forms-DDeEnXSY.js} +38 -38
- package/dist/forms-DDeEnXSY.js.map +1 -0
- package/dist/forms-numeric-D3CO60IF.js +905 -0
- package/dist/forms-numeric-D3CO60IF.js.map +1 -0
- package/dist/{header-C59QZyxV.js → header-2ycNqGOR.js} +42 -37
- package/dist/header-2ycNqGOR.js.map +1 -0
- package/dist/{hooks-CM1Vp9Pe.js → hooks-DQ5SPwZw.js} +2 -2
- package/dist/{hooks-CM1Vp9Pe.js.map → hooks-DQ5SPwZw.js.map} +1 -1
- package/dist/{http-CLTVJc5I.js → http-CdEIHyQf.js} +2 -2
- package/dist/http-CdEIHyQf.js.map +1 -0
- package/dist/{icon-badge-Dv0RYQwj.js → icon-badge-DKlaKXoo.js} +4 -4
- package/dist/{icon-badge-Dv0RYQwj.js.map → icon-badge-DKlaKXoo.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/input-BoLm9Hks.js +20 -0
- package/dist/input-BoLm9Hks.js.map +1 -0
- package/dist/input-DhQdBnV3.js +255 -0
- package/dist/input-DhQdBnV3.js.map +1 -0
- package/dist/item-xzh8Df65.js +264 -0
- package/dist/item-xzh8Df65.js.map +1 -0
- package/dist/layout/app-shell.js +1 -1
- package/dist/layout/auth.js +1 -1
- package/dist/layout/containers.js +1 -1
- package/dist/layout/header.js +1 -1
- package/dist/layout/hooks.js +1 -1
- package/dist/layout/navigation.js +1 -1
- package/dist/layout/page.js +1 -1
- package/dist/layout/settings.js +1 -1
- package/dist/layout/sidebar.js +2 -2
- package/dist/layout/workspace.js +1 -1
- package/dist/layout.js +10 -10
- package/dist/lib/affordance-geometry.generated.d.ts +46 -10
- package/dist/lib/control-group-recipes.d.ts +22 -0
- package/dist/lib/field-affordance-recipes.d.ts +70 -2
- package/dist/lib/field-state-recipes.d.ts +6 -4
- package/dist/lib/format.d.ts +9 -0
- package/dist/lib/money-format.d.ts +30 -0
- package/dist/lib/navigation-row-recipes.d.ts +3 -2
- package/dist/lib/overlay-anatomy-recipes.d.ts +2 -2
- package/dist/lib/surface-recipes.d.ts +13 -8
- package/dist/lib/token-merge.generated.d.ts +144 -2
- package/dist/lib/track-recipes.d.ts +1 -1
- package/dist/lib/ui-provider/provider.d.ts +7 -2
- package/dist/lib/ui-provider/store.d.ts +6 -2
- package/dist/lib/ui-provider/types.d.ts +9 -4
- package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
- package/dist/lib/utils.js +1 -1
- package/dist/media-gallery-DQUQ0m3O.js +201 -0
- package/dist/media-gallery-DQUQ0m3O.js.map +1 -0
- package/dist/{mentions-B8Ko-fhS.js → mentions-DwnO1hh4.js} +40 -39
- package/dist/{mentions-B8Ko-fhS.js.map → mentions-DwnO1hh4.js.map} +1 -1
- package/dist/message-YfFmbXNP.js +127 -0
- package/dist/message-YfFmbXNP.js.map +1 -0
- package/dist/{navigation-BUIn2Qxx.js → navigation-Cbp5V8gG.js} +27 -28
- package/dist/navigation-Cbp5V8gG.js.map +1 -0
- package/dist/navigation-Cs1npsPm.js +300 -0
- package/dist/navigation-Cs1npsPm.js.map +1 -0
- package/dist/{navigation-row-recipes-GVh11KiT.js → navigation-row-recipes-DlU-4QYO.js} +3 -3
- package/dist/navigation-row-recipes-DlU-4QYO.js.map +1 -0
- package/dist/number-CKRBYmZK.js +352 -0
- package/dist/number-CKRBYmZK.js.map +1 -0
- package/dist/overlay.recipes-CNO2S9V6.js +34 -0
- package/dist/overlay.recipes-CNO2S9V6.js.map +1 -0
- package/dist/overlays-DhZO7N-I.js +994 -0
- package/dist/overlays-DhZO7N-I.js.map +1 -0
- package/dist/page-C6R_8jFt.js +325 -0
- package/dist/page-C6R_8jFt.js.map +1 -0
- package/dist/{page-header-DQRa0jug.js → page-header-hUTzcRZX.js} +12 -12
- package/dist/page-header-hUTzcRZX.js.map +1 -0
- package/dist/{pagination-C29vvt3I.js → pagination-Cm0jqa3I.js} +21 -21
- package/dist/pagination-Cm0jqa3I.js.map +1 -0
- package/dist/{popover-CoLDEg19.js → popover-Dcv_9jxr.js} +23 -22
- package/dist/popover-Dcv_9jxr.js.map +1 -0
- package/dist/{popover-menu-GLIQTJTx.js → popover-menu-DnRFKnHP.js} +6 -6
- package/dist/{popover-menu-GLIQTJTx.js.map → popover-menu-DnRFKnHP.js.map} +1 -1
- package/dist/{popover.recipes-zgBhMlUu.js → popover.recipes-wmbvL8Ah.js} +5 -5
- package/dist/popover.recipes-wmbvL8Ah.js.map +1 -0
- package/dist/primitives-BHrwQXFC.js +379 -0
- package/dist/primitives-BHrwQXFC.js.map +1 -0
- package/dist/primitives.js +5 -5
- package/dist/{progress-BOe8l_FZ.js → progress-Br9WTFya.js} +12 -11
- package/dist/progress-Br9WTFya.js.map +1 -0
- package/dist/{receipt-BM8xsGFy.js → receipt-CV89q1fs.js} +8 -8
- package/dist/{receipt-BM8xsGFy.js.map → receipt-CV89q1fs.js.map} +1 -1
- package/dist/rich-text-editor-CF8QYt5p.js +574 -0
- package/dist/rich-text-editor-CF8QYt5p.js.map +1 -0
- package/dist/{rich-text-editor.recipes-DxvOE0Lp.js → rich-text-editor.recipes-CnrbmTS1.js} +35 -26
- package/dist/rich-text-editor.recipes-CnrbmTS1.js.map +1 -0
- package/dist/{rich-text-B7sBAdDG.js → rich-text-j-FGAeZW.js} +4 -4
- package/dist/{rich-text-B7sBAdDG.js.map → rich-text-j-FGAeZW.js.map} +1 -1
- package/dist/{scroll-area-BheMQ270.js → scroll-area-DRdr16Pt.js} +3 -3
- package/dist/scroll-area-DRdr16Pt.js.map +1 -0
- package/dist/{separator-DO0EbCEm.js → separator-BMEvwnSX.js} +2 -2
- package/dist/{separator-DO0EbCEm.js.map → separator-BMEvwnSX.js.map} +1 -1
- package/dist/{separator-Gk_WXH-l.js → separator-Do5GWDYi.js} +4 -4
- package/dist/separator-Do5GWDYi.js.map +1 -0
- package/dist/services/actions/action-adapters.d.ts +4 -0
- package/dist/services/actions.js +8 -3
- package/dist/services/actions.js.map +1 -1
- package/dist/{settings-BnCyyPOJ.js → settings-DHk0L2MF.js} +20 -19
- package/dist/settings-DHk0L2MF.js.map +1 -0
- package/dist/sheet-DRFNY1_D.js +207 -0
- package/dist/sheet-DRFNY1_D.js.map +1 -0
- package/dist/sidebar-Cb8WzOvE.js +511 -0
- package/dist/sidebar-Cb8WzOvE.js.map +1 -0
- package/dist/{sidebar-DPR7fmqN.js → sidebar-Crc9M9JV.js} +220 -201
- package/dist/sidebar-Crc9M9JV.js.map +1 -0
- package/dist/{skeleton-CmT1ppqb.js → skeleton-DVMXr15h.js} +5 -5
- package/dist/{skeleton-CmT1ppqb.js.map → skeleton-DVMXr15h.js.map} +1 -1
- package/dist/smart-card-Bek-TwUp.js +599 -0
- package/dist/smart-card-Bek-TwUp.js.map +1 -0
- package/dist/{spinner-BY9HbUEh.js → spinner-CmTAbEp0.js} +8 -6
- package/dist/spinner-CmTAbEp0.js.map +1 -0
- package/dist/{structure-MvKVq-oL.js → structure-hzCW-XsV.js} +3 -3
- package/dist/{structure-MvKVq-oL.js.map → structure-hzCW-XsV.js.map} +1 -1
- package/dist/{structure.recipes-Bqhf9oIh.js → structure.recipes-EPz60cU8.js} +37 -19
- package/dist/structure.recipes-EPz60cU8.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/surface-recipes-DOdoBXGm.js +28 -0
- package/dist/surface-recipes-DOdoBXGm.js.map +1 -0
- package/dist/table-D6zKeYQX.js +162 -0
- package/dist/table-D6zKeYQX.js.map +1 -0
- package/dist/table-Dn4XSrSB.js +1444 -0
- package/dist/table-Dn4XSrSB.js.map +1 -0
- package/dist/tabs-Dk8E_knt.js +189 -0
- package/dist/tabs-Dk8E_knt.js.map +1 -0
- package/dist/text-inputs-BFpku0Qd.js +331 -0
- package/dist/text-inputs-BFpku0Qd.js.map +1 -0
- package/dist/{text.styles-BwB7vAF2.js → text.styles-g4He6UIW.js} +26 -15
- package/dist/text.styles-g4He6UIW.js.map +1 -0
- package/dist/theme.css +90 -124
- package/dist/themes/green.css +24 -0
- package/dist/{timelines-B9ICkQcV.js → timelines-CxuAFIc2.js} +97 -104
- package/dist/timelines-CxuAFIc2.js.map +1 -0
- package/dist/track-recipes-CDcKmndW.js +10 -0
- package/dist/track-recipes-CDcKmndW.js.map +1 -0
- package/dist/{tree-BdWSaoFT.js → tree-BotPlyiD.js} +13 -13
- package/dist/{tree-BdWSaoFT.js.map → tree-BotPlyiD.js.map} +1 -1
- package/dist/typography/rich-text.js +1 -1
- package/dist/typography-CAr3dQhX.js +116 -0
- package/dist/typography-CAr3dQhX.js.map +1 -0
- package/dist/typography.js +2 -2
- package/dist/{ui-provider-CftIB6TY.js → ui-provider-D2_TeLqw.js} +22 -22
- package/dist/ui-provider-D2_TeLqw.js.map +1 -0
- package/dist/ui-provider.js +1 -1
- package/dist/{upload-D8Za5x_c.js → upload-B0WHW7ak.js} +278 -274
- package/dist/upload-B0WHW7ak.js.map +1 -0
- package/dist/{upload-queue-hIIYBLS7.js → upload-queue-BHZ_wBfd.js} +72 -75
- package/dist/upload-queue-BHZ_wBfd.js.map +1 -0
- package/dist/{usage-card-DnmnJ58D.js → usage-card-U0YBLTNT.js} +31 -33
- package/dist/usage-card-U0YBLTNT.js.map +1 -0
- package/dist/utils-Cospvlj1.js +4445 -0
- package/dist/utils-Cospvlj1.js.map +1 -0
- package/dist/value-inputs-CjfzGMsN.js +854 -0
- package/dist/value-inputs-CjfzGMsN.js.map +1 -0
- package/dist/value-typography-Deb3yQZg.js +116 -0
- package/dist/value-typography-Deb3yQZg.js.map +1 -0
- package/dist/{workspace-C1PZmk8L.js → workspace-YoFjXi6i.js} +97 -105
- package/dist/workspace-YoFjXi6i.js.map +1 -0
- package/docs/consumer-skill/SKILL.md +123 -119
- package/docs/consumer-skill/examples/analytics.tsx +34 -0
- package/docs/consumer-skill/examples/app-layout.tsx +42 -14
- package/docs/consumer-skill/examples/detail.tsx +20 -5
- package/docs/consumer-skill/examples/edit.tsx +1 -1
- package/docs/consumer-skill/examples/layout-blocks.tsx +20 -0
- package/docs/consumer-skill/examples/manifest.json +37 -3
- package/docs/consumer-skill/examples/scoped-directory.tsx +2 -2
- package/docs/consumer-skill/examples/website.tsx +56 -0
- package/docs/consumer-skill/references/analytics.md +70 -0
- package/docs/consumer-skill/references/composition.md +195 -9
- package/docs/consumer-skill/references/design-contract.md +33 -7
- package/docs/consumer-skill/references/discovery.md +80 -5
- package/docs/consumer-skill/references/installation.md +22 -0
- package/docs/consumer-skill/references/integration.md +46 -1
- package/docs/consumer-skill/references/public-api.json +2083 -237
- package/docs/consumer-skill/references/review.md +74 -6
- package/docs/consumer-skill/references/theming.md +59 -8
- package/docs/consumer-skill/references/tokens.json +180 -9
- package/docs/consumer-skill/references/workflows.md +34 -0
- package/docs/consumer-skill/scripts/check-composition.mjs +1 -1
- package/docs/consumer-skill/scripts/composition-policy.mjs +271 -18
- package/docs/consumer-skill/scripts/discovery.mjs +69 -9
- package/docs/consumer-skill/scripts/pin-button-defaults.mjs +95 -0
- package/docs/consumer-skill/scripts/surface-policy.mjs +44 -0
- package/package.json +11 -6
- package/dist/accordion-B-5Focs8.js.map +0 -1
- package/dist/action-menu-Cx3SdfbN.js +0 -265
- package/dist/action-menu-Cx3SdfbN.js.map +0 -1
- package/dist/affordance-geometry.generated-D8Jcfb0G.js +0 -32
- package/dist/affordance-geometry.generated-D8Jcfb0G.js.map +0 -1
- package/dist/ai-artifact-B5tPpXnS.js.map +0 -1
- package/dist/app-shell-at8Kt4l_.js.map +0 -1
- package/dist/attachment-BO2R47wn.js.map +0 -1
- package/dist/auth-OFwWSAap.js +0 -704
- package/dist/auth-OFwWSAap.js.map +0 -1
- package/dist/avatar-Bpzty83c.js.map +0 -1
- package/dist/badge-BZXZT9wd.js.map +0 -1
- package/dist/breadcrumbs-DdQ_I5ra.js.map +0 -1
- package/dist/button-BS6l5JUw.js.map +0 -1
- package/dist/buttons-Co6GavvM.js +0 -674
- package/dist/buttons-Co6GavvM.js.map +0 -1
- package/dist/chart-DVfcwQu6.js +0 -149
- package/dist/chart-DVfcwQu6.js.map +0 -1
- package/dist/checkbox-BavDRjF7.js +0 -34
- package/dist/checkbox-BavDRjF7.js.map +0 -1
- package/dist/choice-inputs-CC7XqPQO.js +0 -619
- package/dist/choice-inputs-CC7XqPQO.js.map +0 -1
- package/dist/code-block-xHKbAJDj.js.map +0 -1
- package/dist/combobox-DEbdr-3u.js +0 -273
- package/dist/combobox-DEbdr-3u.js.map +0 -1
- package/dist/combobox-xv3yJbzl.js +0 -850
- package/dist/combobox-xv3yJbzl.js.map +0 -1
- package/dist/command-C0xe7u9B.js.map +0 -1
- package/dist/comments-DviPLnwy.js.map +0 -1
- package/dist/containers-6s-ucRQQ.js.map +0 -1
- package/dist/data-display-cWIRdeaf.js +0 -1129
- package/dist/data-display-cWIRdeaf.js.map +0 -1
- package/dist/date-BFNMnrS5.js +0 -140
- package/dist/date-BFNMnrS5.js.map +0 -1
- package/dist/date-picker-CA6ogMQB.js +0 -1521
- package/dist/date-picker-CA6ogMQB.js.map +0 -1
- package/dist/date-pickers-BPIKLdsD.js +0 -224
- package/dist/date-pickers-BPIKLdsD.js.map +0 -1
- package/dist/display-CFM5myut.js.map +0 -1
- package/dist/dropdown-menu-BlnyHr-9.js.map +0 -1
- package/dist/feedback-DWUkgEjR.js.map +0 -1
- package/dist/field-affordance-recipes-IjzPrCTw.js +0 -17
- package/dist/field-affordance-recipes-IjzPrCTw.js.map +0 -1
- package/dist/field-state-recipes-CBTRt9Bt.js.map +0 -1
- package/dist/filters-BhsUtsxW.js.map +0 -1
- package/dist/form-field-Bn7ZH1rA.js.map +0 -1
- package/dist/form-sizing-BWs70_a2.js +0 -100
- package/dist/form-sizing-BWs70_a2.js.map +0 -1
- package/dist/format-iamDSqs2.js +0 -110
- package/dist/format-iamDSqs2.js.map +0 -1
- package/dist/forms-B7pzS25o.js.map +0 -1
- package/dist/forms-numeric-BUBxELBv.js +0 -867
- package/dist/forms-numeric-BUBxELBv.js.map +0 -1
- package/dist/header-C59QZyxV.js.map +0 -1
- package/dist/http-CLTVJc5I.js.map +0 -1
- package/dist/input-WwYQZJzG.js +0 -202
- package/dist/input-WwYQZJzG.js.map +0 -1
- package/dist/input-ci9fIgFH.js +0 -20
- package/dist/input-ci9fIgFH.js.map +0 -1
- package/dist/item-pJ0GsOiJ.js +0 -257
- package/dist/item-pJ0GsOiJ.js.map +0 -1
- package/dist/media-gallery-DhDRgnVZ.js +0 -200
- package/dist/media-gallery-DhDRgnVZ.js.map +0 -1
- package/dist/message-COsdEvXT.js +0 -108
- package/dist/message-COsdEvXT.js.map +0 -1
- package/dist/navigation-BUIn2Qxx.js.map +0 -1
- package/dist/navigation-DBEu4POU.js +0 -267
- package/dist/navigation-DBEu4POU.js.map +0 -1
- package/dist/navigation-row-recipes-GVh11KiT.js.map +0 -1
- package/dist/number-BNT_BIzJ.js +0 -269
- package/dist/number-BNT_BIzJ.js.map +0 -1
- package/dist/overlay.recipes-BxW5FIfK.js +0 -6
- package/dist/overlay.recipes-BxW5FIfK.js.map +0 -1
- package/dist/overlays-B11wZka6.js +0 -982
- package/dist/overlays-B11wZka6.js.map +0 -1
- package/dist/page-BV6ioQg3.js +0 -202
- package/dist/page-BV6ioQg3.js.map +0 -1
- package/dist/page-header-DQRa0jug.js.map +0 -1
- package/dist/pagination-C29vvt3I.js.map +0 -1
- package/dist/popover-CoLDEg19.js.map +0 -1
- package/dist/popover.recipes-zgBhMlUu.js.map +0 -1
- package/dist/primitives-DKPOGVpj.js +0 -330
- package/dist/primitives-DKPOGVpj.js.map +0 -1
- package/dist/progress-BOe8l_FZ.js.map +0 -1
- package/dist/rich-text-editor-CoVrTiSv.js +0 -575
- package/dist/rich-text-editor-CoVrTiSv.js.map +0 -1
- package/dist/rich-text-editor.recipes-DxvOE0Lp.js.map +0 -1
- package/dist/scroll-area-BheMQ270.js.map +0 -1
- package/dist/select-B2mb-qN2.js +0 -108
- package/dist/select-B2mb-qN2.js.map +0 -1
- package/dist/separator-Gk_WXH-l.js.map +0 -1
- package/dist/settings-BnCyyPOJ.js.map +0 -1
- package/dist/sheet-B-q914Ad.js +0 -205
- package/dist/sheet-B-q914Ad.js.map +0 -1
- package/dist/sidebar-C_2p3Tfj.js +0 -501
- package/dist/sidebar-C_2p3Tfj.js.map +0 -1
- package/dist/sidebar-DPR7fmqN.js.map +0 -1
- package/dist/smart-card-CYLn46e6.js +0 -578
- package/dist/smart-card-CYLn46e6.js.map +0 -1
- package/dist/spinner-BY9HbUEh.js.map +0 -1
- package/dist/structure.recipes-Bqhf9oIh.js.map +0 -1
- package/dist/surface-recipes-CQfRr-VL.js +0 -27
- package/dist/surface-recipes-CQfRr-VL.js.map +0 -1
- package/dist/table-BS39xnlq.js +0 -1424
- package/dist/table-BS39xnlq.js.map +0 -1
- package/dist/table-DnlAJ-xR.js +0 -146
- package/dist/table-DnlAJ-xR.js.map +0 -1
- package/dist/tabs-B5cNMWiP.js +0 -187
- package/dist/tabs-B5cNMWiP.js.map +0 -1
- package/dist/text-inputs-Dh9XGyiS.js +0 -331
- package/dist/text-inputs-Dh9XGyiS.js.map +0 -1
- package/dist/text.styles-BwB7vAF2.js.map +0 -1
- package/dist/timelines-B9ICkQcV.js.map +0 -1
- package/dist/track-recipes-LLPNVwFg.js +0 -10
- package/dist/track-recipes-LLPNVwFg.js.map +0 -1
- package/dist/typography-Cv8MT-82.js +0 -96
- package/dist/typography-Cv8MT-82.js.map +0 -1
- package/dist/ui-provider-CftIB6TY.js.map +0 -1
- package/dist/upload-D8Za5x_c.js.map +0 -1
- package/dist/upload-queue-hIIYBLS7.js.map +0 -1
- package/dist/usage-card-DnmnJ58D.js.map +0 -1
- package/dist/utils-C2EKeIw3.js +0 -72
- package/dist/utils-C2EKeIw3.js.map +0 -1
- package/dist/value-inputs-DX2dbxjj.js +0 -824
- package/dist/value-inputs-DX2dbxjj.js.map +0 -1
- package/dist/workspace-C1PZmk8L.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"filters-BhsUtsxW.js","names":["NumberValue","DateValue","_Fragment","_Fragment","_Fragment","_Fragment","Text","Label","DisplayLabel","Grid","Stack","LoadingState","ErrorState","Value","SecondaryValue","MonoValue","Number$1","DateRange","DatePrimitive","Badge","CommandItem","CommandInput","CommandEmpty","CommandList","CommandGroup","CommandSeparator","Command","Input","DatePicker","PopoverTitle","PopoverTrigger","PopoverHeader","Popover","PopoverFooter","PopoverContent","TabsTrigger","TabsList","Tabs","PopoverMenu","useDebouncedCallback","useDebounce","React","Fragment$1","defaultFilterStrings","interpolateFilterString","template","params","key","match","getFilterString","keys","path","result","strings","FILTER_ELEMENT_HEIGHT","FilterType","FilterOperatorEnum","defineAsyncSelectConfig","config","getTextOperators","getSelectOperators","getNumberOperators","getDateOperators","getBooleanOperators","getOperatorsForType","type","getDefaultOperatorForType","validateFilterValue","filter","value","v","t","customValidation","FilterContext","createContext","FilterProvider","isNavigatingProp","stringsProp","filtersRef","useRef","filters","onFilterChangeRef","onFilterChange","onErrorRef","onError","asyncCacheVersion","setAsyncCacheVersion","useState","asyncLabelsRef","asyncLabels","useMemo","next","fetcher","mapToOption","limit","previous","sameSource","entry","activeAsyncValues","activeFilters","useStrings","useEffect","addFilter","useCallback","newFilters","removeFilter","f","id","updateFilter","updates","clearFilters","replaceFilters","getFilterByKey","getFilterValue","setFilterValue","existingFilter","filterConfig","defaultOperator","isFilterActive","getFilterOperator","setFilterOperator","validateFilter","getDependentFilters","dep","cacheAsyncOptions","filterMap","filterKey","changed","option","options","version","getAsyncOptionLabel","optionValue","reportError","error","context","controller","reportPreloadError","selectedValues","cache","active","items","useFilters","useContext","useFilterGroups","processedFilters","dynamicFilterOptions","dyn","searchFilters","visibleFilters","activeRegularFilters","alwaysVisibleFilters","popoverFilters","activeFilterKeys","FilterOperatorSelect","open","setOpen","currentOperatorLabel","operators","op","operator","Button","cn","segmentResetClass","onOperatorChange","item","FilterValueDisplay","renderAsyncValueText","o","val","index","renderValueText","CalendarIcon","renderDateValue","renderDateRangeValue","renderSingleDateValue","_filter","isValidDateValue","parsed","rawValue","pattern","start","end","ActiveFilterItem","labelId","valueId","SEGMENT_RESET","Divider","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","AsyncFilterContent","setSearchInput","tempValue","setTempValue","prevValueRef","isMulti","maxSelected","showBackButton","triggerSource","isDirty","sortedOptions","selectedSet","optionValueSet","missingSelected","label","a","b","handleValueSelect","onClose","handleDone","emptyContent","isLoading","isFetching","isError","onBackToFilterList","ChevronLeft","Loader2","EMPTY_PRESETS","DateFacet","isRangeMode","dateFormat","readableFormat","placeholder","withConfirm","closeOnSelect","showShortcuts","rangeValue","singleValue","isValid","commonProps","className","output","DateFilterContent","parseInputDate","input","parse","startDate","endDate","formatOutputDate","date","format","handleDateChange","formattedStart","formattedEnd","facetValue","FilterErrorBoundaryBase","Component","fallback","labels","FilterErrorBoundary","props","FilterListItem","subtitle","FilterListContent","handleFilterSelect","availableFilters","RegularFilterContent","isMultiSelect","newValue","isSelected","TagsFacetComponent","inputValue","setInputValue","handleAddTag","trimmedValue","onValueChange","handleRemoveTag","tag","tagToRemove","handleKeyDown","handleClearAll","hasTags","tagCountLabel","tagSummary","Plus","TagsFacet","TagsFilterContent","FilterPopoverContent","popoverWidth","activeFilterInPopover","handleSetFilterValue","FilterPill","localRef","isOperatorChangeRef","operatorChangeRef","labelRef","editorFocusRef","isOpen","onClear","event","FiltersButton","setIsOpen","setActiveFilterInPopover","Filter","FilterTabs","nonSearchFilters","fc","activeTabId","tab","tabs","preset","sortedPreset","sortedActive","i","handleTabClick","presetFilters","SearchFacetComponent","inputValueRef","lastEmittedValue","isUserTypingRef","isNavigating","currentInput","emitValue","debouncedUpdate","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","normalized","toPublicRecord","out","values","readValues","arrayFormat","normalizeValues","formatValues","transformed","formatted","getDefaultOperator","readOperator","operatorSuffix","shouldEncodeOperator","mode","isMultiValueFilter","parseFiltersFromQuery","query","filterConfigs","serializeFiltersToQuery","preserveUnrelated","includeOperators","resetPageKeys","nextRecord","currentQuery","configByKey","activeFilter","mergeFilterQuery","current","nextFilterQuery","SelectFacet","hasSelection","handleSelect","selectedValue","getOptionLabel","opt","placeholderInterpolated","ChevronsUpDown","AsyncSelectFacet","labelCache","initialOptions","initial","fromOptions","fromInitialOptions","emptyMessage","Check","RangeFacet","minValue","setMinValue","maxValue","setMaxValue","instanceId","useId","emitRange","zodValidator","schema","predicateValidator","predicate","message"],"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/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/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/facets/range-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}\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\tdateSelected: string;\n\t\tnotDateSelected: string;\n\t\tnotDateRangeSelected: string;\n\t\tselectedEndDate: string;\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\tcustomRange: 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\n\t// Filter list\n\tsearchFilters: string;\n\tnoFiltersAvailable: string;\n\tavailableFilters: string;\n\tactiveFilters: string;\n\tclearSearch: string;\n\tbackToFilters: string;\n\tselect: string;\n\toptions: 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\n\t// Error boundary\n\terror: {\n\t\ttitle: string;\n\t\tdescriptionWithKey: string;\n\t\tgeneric: string;\n\t\tunknown: 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\tdateSelected: 'Date selected',\n\t\tnotDateSelected: 'No date selected',\n\t\tnotDateRangeSelected: 'No date range selected',\n\t\tselectedEndDate: 'Select end date',\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\tcustomRange: 'Custom range',\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\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\tselect: 'Select',\n\toptions: 'options',\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},\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\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 * 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';\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\tchildren?: FilterOption[];\n\t/** Renders the entry as unselectable. */\n\tdisabled?: boolean;\n\t/** Supporting copy shown under the label. */\n\tdescription?: string;\n\tcolor?: string;\n}\n\nexport interface DisplayConfig {\n\t/** Replaces the default config rendering. */\n\trenderConfig?: {\n\t\tdesktop: string;\n\t\tmobile?: string;\n\t\ttablet?: string;\n\t};\n\tdisplay?: FilterDisplay;\n\tcategory?: FilterCategory;\n\tpriority?: number;\n\thidden?: boolean;\n\t/** Merged onto the outermost node. */\n\tclassName?: string; // Simplified config for basic styling needs\n}\n\nexport interface ValidationConfig {\n\tmin?: number;\n\tmax?: number;\n\tpattern?: RegExp;\n\trequired?: boolean;\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/** 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 before a cached result refetches (default: 60_000). */\n\tstaleTime?: number;\n\t/** Retention window in ms before a cached result is discarded (default: 300_000). */\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 shown under the label. */\n\tdescription?: string;\n\t/** Comparison currently chosen. */\n\toperator?: FilterOperator;\n\t/** Comparisons this filter offers. */\n\toperators?: OperatorOption[]; // Available operators for this filter\n\toptions?: FilterOption[];\n\tplaceholder?: string;\n\tdelay?: number;\n\t/** Leading glyph. */\n\ticon: ReactNode;\n\tdisplayConfig: DisplayConfig;\n\tdefaultValue?: string | string[];\n\tvalidation?: ValidationConfig;\n\tdependencies?: FilterDependency[];\n\tmultiple?: boolean;\n\tcloseOnSelect?: boolean;\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\tfullWidth?: boolean;\n\t\tnoDatePlaceholder?: string;\n\t\tnoRangePlaceholder?: string;\n\t\tautoApply?: boolean; // Whether to automatically apply date selections\n\t};\n\t// Optional formatting functions\n\tformat?: (value: unknown) => string;\n\tparse?: (value: string) => unknown;\n\ttransform?: (value: unknown) => unknown;\n}\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. */\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 FilterOperator,\n\ttype OperatorOption,\n\tFilterType,\n} from './filters.types';\nimport 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\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.RANGE:\n\t\t\treturn getNumberOperators(strings);\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.EQUALS;\n\t\tcase FilterType.DATE:\n\t\t\treturn FilterOperatorEnum.BEFORE;\n\t\tdefault:\n\t\t\treturn FilterOperatorEnum.EQUALS;\n\t}\n}\n","import type { ReactNode } from 'react';\nimport type { FilterConfig, FilterDependency } from '../filters.types';\n\n/**\n * Gets the label for a filter option\n */\nexport function getFilterOptionLabel(\n\tfilter: FilterConfig,\n\tvalue: string,\n): string | undefined {\n\treturn filter.options?.find((opt) => opt.value === value)?.label;\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 filter.options?.find((opt) => opt.value === value)?.icon;\n}\n\n/**\n * Validates a filter value against the filter configuration\n *\n * @param filter - The filter configuration to validate against\n * @param value - The value to validate\n * @param t\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\t// Special case for date filters - always allow date strings\n\tif (filter.type === 'date') {\n\t\t// If the value is a date string array, it's valid\n\t\tif (Array.isArray(value) && value.every((v) => typeof v === 'string')) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// Require if marked as required\n\tif (\n\t\tfilter.validation?.required &&\n\t\t(!value || (Array.isArray(value) && value.length === 0))\n\t) {\n\t\treturn t('validation.required');\n\t}\n\n\t// Only check min/max for numeric values\n\tif (typeof value === 'number') {\n\t\tif (\n\t\t\tfilter.validation?.min !== undefined &&\n\t\t\tvalue < filter.validation.min\n\t\t) {\n\t\t\treturn t('validation.minValue').replace(\n\t\t\t\t'{min}',\n\t\t\t\tString(filter.validation.min),\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tfilter.validation?.max !== undefined &&\n\t\t\tvalue > filter.validation.max\n\t\t) {\n\t\t\treturn t('validation.maxValue').replace(\n\t\t\t\t'{max}',\n\t\t\t\tString(filter.validation.max),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Pattern validation for strings only\n\tif (filter.validation?.pattern && typeof value === 'string') {\n\t\tconst regex = new RegExp(filter.validation.pattern);\n\t\tif (!regex.test(value)) {\n\t\t\treturn t('validation.invalidFormat');\n\t\t}\n\t}\n\n\t// Custom validation if provided\n\tif (filter.validation?.custom) {\n\t\tconst customValidation = filter.validation.custom(value);\n\t\tif (typeof customValidation === 'string' || !customValidation) {\n\t\t\treturn customValidation;\n\t\t}\n\t}\n\n\t// If we got here, the value is valid\n\treturn true;\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\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\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\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\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 { getDefaultOperatorForType } from './operator-options';\nimport { 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\tvalidateFilter: (key: string, value: unknown) => boolean | string;\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\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\n\t// Trigger re-render when async labels are resolved\n\tconst [asyncCacheVersion, setAsyncCacheVersion] = useState(0);\n\tconst asyncLabelsRef = useRef(new Map<string, AsyncLabelCache>());\n\tconst asyncLabels = useMemo(() => {\n\t\tconst next = new Map<string, AsyncLabelCache>();\n\t\tfor (const filter of filters) {\n\t\t\tif (filter.type !== FilterType.ASYNC_SELECT) continue;\n\t\t\tconst fetcher = filter.asyncConfig?.fetcher;\n\t\t\tconst mapToOption = filter.asyncConfig?.mapToOption;\n\t\t\tconst limit = filter.asyncConfig?.limit ?? 10;\n\t\t\tconst previous = asyncLabelsRef.current.get(filter.key);\n\t\t\tconst sameSource = previous && previous.fetcher === fetcher && previous.mapToOption === mapToOption;\n\t\t\tnext.set(filter.key, sameSource && previous.limit === limit\n\t\t\t\t? previous\n\t\t\t\t: { fetcher, mapToOption, limit, options: sameSource ? previous.options : new Map() });\n\t\t}\n\t\tif (next.size === asyncLabelsRef.current.size && [...next].every(([key, entry]) => asyncLabelsRef.current.get(key) === entry)) {\n\t\t\treturn asyncLabelsRef.current;\n\t\t}\n\t\tasyncLabelsRef.current = next;\n\t\treturn next;\n\t}, [filters]);\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\tuseEffect(() => {\n\t\tonFilterChangeRef.current = onFilterChange;\n\t}, [onFilterChange]);\n\n\tconst addFilter = useCallback(\n\t\t(filter: ActiveFilter) => {\n\t\t\tconst newFilters = [...activeFilters, filter];\n\t\t\tonFilterChangeRef.current(newFilters);\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst removeFilter = useCallback(\n\t\t(id: string) => {\n\t\t\tconst newFilters = activeFilters.filter(\n\t\t\t\t(f: ActiveFilter) => f.id !== id && f.key !== id,\n\t\t\t);\n\t\t\tonFilterChangeRef.current(newFilters);\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst updateFilter = useCallback(\n\t\t(id: string, updates: Partial<ActiveFilter>) => {\n\t\t\tconst newFilters = activeFilters.map((f: ActiveFilter) =>\n\t\t\t\tf.id === id || f.key === id ? { ...f, ...updates } : f,\n\t\t\t);\n\t\t\tonFilterChangeRef.current(newFilters);\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst clearFilters = useCallback(() => {\n\t\tonFilterChangeRef.current([]);\n\t}, []);\n\n\tconst replaceFilters = useCallback((newFilters: ActiveFilter[]) => {\n\t\tonFilterChangeRef.current(newFilters);\n\t}, []);\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 || [];\n\t\t},\n\t\t[activeFilters],\n\t);\n\n\tconst setFilterValue = useCallback(\n\t\t(key: string, value: string[]) => {\n\t\t\tconst existingFilter = activeFilters.find(\n\t\t\t\t(f: ActiveFilter) => f.key === key,\n\t\t\t);\n\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 {\n\t\t\t\t// Update or add filter\n\t\t\t\tif (existingFilter) {\n\t\t\t\t\tupdateFilter(key, { value });\n\t\t\t\t} else {\n\t\t\t\t\t// Get the filter config to check for default operator\n\t\t\t\t\tconst filterConfig = filtersRef.current.find(\n\t\t\t\t\t\t(f: FilterConfig) => f.key === key,\n\t\t\t\t\t);\n\t\t\t\t\tconst defaultOperator =\n\t\t\t\t\t\tfilterConfig?.operator ??\n\t\t\t\t\t\tfilterConfig?.operators?.[0]?.value ??\n\t\t\t\t\t\t(filterConfig\n\t\t\t\t\t\t\t? getDefaultOperatorForType(filterConfig.type)\n\t\t\t\t\t\t\t: 'equals');\n\n\t\t\t\t\taddFilter({\n\t\t\t\t\t\tid: key,\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\toperator: defaultOperator,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[activeFilters, addFilter, 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 getFilterOperator = useCallback(\n\t\t(key: string): FilterOperator | undefined => {\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?.operator || 'equals';\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 = activeFilters.find(\n\t\t\t\t(f: ActiveFilter) => f.key === key,\n\t\t\t);\n\t\t\tif (existingFilter) {\n\t\t\t\tupdateFilter(key, { operator });\n\t\t\t}\n\t\t},\n\t\t[activeFilters, 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[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\tif (active.every((value) => cache.options.has(value))) continue;\n\n\t\t\tconst { fetcher, mapToOption, limit } = cache;\n\t\t\tif (fetcher && mapToOption) {\n\t\t\t\tvoid fetcher({ query: '', limit, signal: controller.signal })\n\t\t\t\t\t.then((items) => {\n\t\t\t\t\t\tif (controller.signal.aborted) return;\n\t\t\t\t\t\tcacheAsyncOptions(filterKey, items.map(mapToOption));\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error) => reportPreloadError(error, filterKey));\n\t\t\t}\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';\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/** 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\tsegmentResetClass?: 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\tsegmentResetClass,\n}: FilterOperatorSelectProps) {\n\tconst [open, setOpen] = useState(false);\n\tconst { strings } = useFilters();\n\n\tconst currentOperatorLabel =\n\t\toperators.find((op) => op.value === operator)?.label || 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}\n\t\t\tonOpenChange={setOpen}\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\tsegmentResetClass,\n\t\t\t\t\t\t'h-full 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=\"secondary\">\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=\"w-48\"\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 { useFilters } from '../filter-context';\nimport type { FilterStrings } from '../filters.strings';\nimport { interpolateFilterString } from '../filters.strings';\nimport { FilterType, type FilterConfig } from '../filters.types';\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 } = 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\" className=\"filter-value-display--component leading-none\">\n\t\t\t\t{strings.nothingSelected}\n\t\t\t</Text>\n\t\t);\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\" weight=\"semibold\" className=\"filter-value-display--component leading-none\">\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 */}\n\t\t\t\t<div className=\"relative flex\">\n\t\t\t\t\t{value.slice(0, 2).map((val, index) => {\n\t\t\t\t\t\tconst option = filter.options?.find(\n\t\t\t\t\t\t\t(o) => o.value === val,\n\t\t\t\t\t\t);\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={`${index > 0 ? '-ml-space-sm' : ''} border-background bg-background relative rounded-full border`}\n\t\t\t\t\t\t\t\tstyle={{ zIndex: 10 - index }}\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 -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\" weight=\"semibold\" className=\"truncate leading-none\">\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{renderDateValue(filter, value, strings)}\n\t\t\t</Stack>\n\t\t);\n\t}\n\n\t// For other filters\n\treturn (\n\t\t<Text tag=\"span\" weight=\"semibold\" className=\"filter-value-display--component truncate leading-none\">\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 (filter.operator === 'between' && value.length === 2) {\n\t\treturn renderDateRangeValue(value[0], value[1], filter.dateFormat?.display);\n\t}\n\n\tif (value.length === 1) {\n\t\treturn renderSingleDateValue(value[0], filter.dateFormat?.display);\n\t}\n\n\tif (value.length === 2) {\n\t\treturn renderDateRangeValue(value[0], value[1], filter.dateFormat?.display);\n\t}\n\n\treturn (\n\t\t<Value weight=\"semibold\" className=\"truncate leading-none\">\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: (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: filter.pluralLabel ?? filter.label,\n\t\t});\n\t}\n\n\treturn value\n\t\t.map((val) => {\n\t\t\tconst option = filter.options?.find((o) => o.value === val);\n\t\t\treturn option?.label || val;\n\t\t})\n\t\t.join(', ');\n}\n\nfunction isValidDateValue(rawValue: string) {\n\tconst parsed = new Date(rawValue);\n\treturn !Number.isNaN(parsed.getTime());\n}\n\nfunction renderSingleDateValue(rawValue: string, pattern?: string) {\n\tif (!isValidDateValue(rawValue)) {\n\t\treturn (\n\t\t\t<Value weight=\"semibold\" className=\"truncate leading-none\">\n\t\t\t\t{rawValue}\n\t\t\t</Value>\n\t\t);\n\t}\n\n\treturn (\n\t\t<DateValue\n\t\t\tvalue={rawValue}\n\t\t\tformat={pattern}\n\t\t\tweight=\"semibold\"\n\t\t\tclassName=\"truncate leading-none\"\n\t\t/>\n\t);\n}\n\nfunction renderDateRangeValue(start: string, end: string, pattern?: string) {\n\tif (isValidDateValue(start) && isValidDateValue(end)) {\n\t\treturn (\n\t\t\t<DateRange\n\t\t\t\tfrom={start}\n\t\t\t\tto={end}\n\t\t\t\tformat={pattern}\n\t\t\t\tweight=\"semibold\"\n\t\t\t\tclassName=\"truncate leading-none\"\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<span className=\"inline-flex min-w-0 items-center gap-space-xs truncate leading-none\">\n\t\t\t{renderSingleDateValue(start, pattern)}\n\t\t\t<Value weight=\"semibold\">–</Value>\n\t\t\t{renderSingleDateValue(end, pattern)}\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 { useFilters } from '../filter-context';\nimport {\n\tFILTER_ELEMENT_HEIGHT,\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\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 { strings } = 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 or\n\t// focus ring — the pill itself is the visual container. The global\n\t// `<Button>` primitive bakes in `border border-transparent\n\t// focus-visible:border-ring focus-visible:ring-3`, so without these\n\t// overrides every segment paints a full 1px box (showing as a\n\t// double-border just inside the pill chrome) and a rounded focus ring\n\t// when the popover opens.\n\tconst SEGMENT_RESET =\n\t\t'!border-0 !rounded-none !shadow-none focus-visible:!ring-0 focus-visible:!border-transparent';\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\tconst Divider = () => <div aria-hidden className=\"w-px self-stretch bg-border\" />;\n\n\treturn (\n\t\t<div\n\t\t\trole=\"group\"\n\t\t\taria-label={filter.label}\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\t`border-input bg-background flex ${FILTER_ELEMENT_HEIGHT} items-center overflow-hidden rounded-radius border`,\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 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={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\" 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\tsegmentResetClass={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={onFilterClick}\n\t\t\t\tclassName={cn(SEGMENT_RESET, 'flex h-full 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 shrink-0 items-center justify-center px-space-sm text-muted-foreground hover:bg-accent hover:text-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\tonFilterClear();\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\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","import {\n\tChevronLeft,\n\tLoader2,\n} from 'lucide-react';\nimport { useEffect, useMemo, useRef, 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 { Stack } from '../../../base/structure';\nimport { PopoverHeader, PopoverFooter } from '../../../base/popover';\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';\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\tconst [tempValue, setTempValue] = useState<string[]>(value ?? []);\n\n\t// Sync tempValue when external value changes\n\tconst prevValueRef = useRef(value);\n\tif (value !== prevValueRef.current) {\n\t\tconst previous = prevValueRef.current ?? [];\n\t\tconst next = value ?? [];\n\t\tprevValueRef.current = value;\n\t\tif (next.length !== previous.length || next.some((item, index) => item !== previous[index])) {\n\t\t\tsetTempValue(next);\n\t\t}\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, 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\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// Resolve selected items missing from current results via the provider cache\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);\n\t\t\t\tif (label) {\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, ...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\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\treturn (\n\t\t<>\n\t\t\t{/* Header – matches RegularFilterContent */}\n\t\t\t<PopoverHeader start={showBackButton ? (\n\t\t\t\t<Button\n\t\t\t\t\t\ttone=\"secondary\"\n\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\tonClick={onBackToFilterList}\n\t\t\t\t\t\taria-label={strings.backToFilters}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronLeft aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />\n\t\t\t\t\t</Button>\n\t\t\t) : undefined}>\n\t\t\t\t<Text tag=\"span\" weight=\"semibold\">{filter.label}</Text>\n\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">{strings.selectValues}</Text>\n\t\t\t</PopoverHeader>\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: filter.label.toLowerCase() },\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>\n\t\t\t\t\t{sortedOptions.length === 0 ? (\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{Boolean(isFetching && !isLoading) && (\n\t\t\t\t\t\t\t\t<Stack direction=\"horizontal\" gap=\"sm\" wrap={false} className=\"px-control-sm py-space-xs\">\n\t\t\t\t\t\t\t\t\t<Loader2 className=\"text-muted-foreground size-icon-sm animate-spin\" />\n\t\t\t\t\t\t\t\t\t<Text tag=\"span\" size=\"xs\" type=\"secondary\">\n\t\t\t\t\t\t\t\t\t\t{strings.searching}\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\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\" 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{/* Like static selections, confirmation only appears for a changed draft. */}\n\t\t\t{isDirty && (\n\t\t\t\t<PopoverFooter caption={interpolateFilterString(strings.selected, {\n\t\t\t\t\tcount: tempValue.length,\n\t\t\t\t\tfilterLabel: (tempValue.length > 1 ? filter.pluralLabel : filter.label) ?? filter.label,\n\t\t\t\t})}>\n\t\t\t\t\t<Button tone=\"primary\" size=\"sm\" onClick={handleDone}>\n\t\t\t\t\t\t{strings.confirm}\n\t\t\t\t\t</Button>\n\t\t\t\t</PopoverFooter>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import { isValid } from 'date-fns';\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 { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig } from '../filters.types';\n\nconst EMPTY_PRESETS: PresetDateRange[] = [];\n\nexport interface DateFacetProps {\n\t\t/** Definition of the filter this control edits. */\n\t\tfilter: FilterConfig;\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\tvalue,\n\t\tonValueChange,\n\t\tclassName,\n}: DateFacetProps) {\n\t\tconst { strings } = useFilters();\n\n\t\tconst isRangeMode =\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\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\tconst commonProps = {\n\t\t\t\tformat: dateFormat,\n\t\t\t\treadableFormat,\n\t\t\t\tplaceholder,\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 presetsProp = showShortcuts ? undefined : EMPTY_PRESETS;\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, parse, isValid } from 'date-fns';\nimport { ChevronLeft } from 'lucide-react';\nimport { Button } from '../../../base/buttons';\nimport { PopoverHeader, PopoverTitle } from '../../../base/popover';\nimport { DateFacet } from '../facets/date-facet';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig, FilterTriggerSource } from '../filters.types';\n\ninterface DateFilterContentProps {\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\t/** Origin of the editor, which determines back-button behavior. */\n\ttriggerSource?: FilterTriggerSource;\n}\n\nexport function DateFilterContent({\n\tfilter,\n\tvalue,\n\tonFilterChange,\n\tonBackToFilterList,\n\ttriggerSource = 'chip',\n}: DateFilterContentProps) {\n\tconst { strings } = useFilters();\n\n\tconst parseInputDate = (input?: string) => {\n\t\tif (!input) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (filter.dateFormat?.param) {\n\t\t\tconst parsed = parse(input, filter.dateFormat.param, new Date());\n\t\t\treturn isValid(parsed) ? parsed : undefined;\n\t\t}\n\n\t\tconst parsed = new Date(input);\n\t\treturn isValid(parsed) ? parsed : undefined;\n\t};\n\n\tconst startDate = parseInputDate(value[0]);\n\tconst endDate = parseInputDate(value[1]);\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\tonFilterChange(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<PopoverHeader\n\t\t\t\tstart={showBackButton ? (\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\tsize=\"sm\" iconOnly\n\t\t\t\t\t\tonClick={onBackToFilterList}\n\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\taria-label={strings.backToFilters}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronLeft aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />\n\t\t\t\t\t</Button>\n\t\t\t\t) : undefined}\n\t\t\t>\n\t\t\t\t<PopoverTitle>{filter.label}</PopoverTitle>\n\t\t\t</PopoverHeader>\n\n\t\t\t<div className=\"p-surface\">\n\t\t\t\t<DateFacet\n\t\t\t\t\tfilter={filter}\n\t\t\t\t\tvalue={facetValue}\n\t\t\t\t\tonValueChange={handleDateChange}\n\t\t\t\t/>\n\t\t\t</div>\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';\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=\"filter-error-boundary--component rounded-radius-md border border-destructive/30 bg-destructive/10 p-surface-xs text-destructive\">\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\tclassName=\"rounded-full p-0\"\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<MonoValue size=\"xs\" className=\"mt-space-xs text-destructive\">\n\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</MonoValue>\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.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 { 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? `${filter.options.length} ${strings?.options ?? ''}`.trim()\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\" 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 { ChevronLeft } from 'lucide-react';\nimport { useState, useEffect } from 'react';\n\nimport { Button } from '../../../base/buttons';\nimport { PopoverHeader, PopoverFooter } from '../../../base/popover';\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 { FilterType, type FilterConfig, type FilterTriggerSource } from '../filters.types';\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.\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 =\n\t\tfilter.multiple === true || filter.type === FilterType.MULTI_SELECT;\n\tconst showBackButton = triggerSource === 'toolbar';\n\n\tconst [tempValue, setTempValue] = useState<string[]>(value || []);\n\n\tuseEffect(() => {\n\t\tsetTempValue(value || []);\n\t}, [value]);\n\n\tconst handleValueSelect = (optionValue: string) => {\n\t\tif (isMultiSelect) {\n\t\t\tconst newValue = tempValue.includes(optionValue)\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\tconst handleDone = () => {\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\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t{/* SECTION 1 — Label header */}\n\t\t\t<PopoverHeader start={showBackButton ? (\n\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\tsize=\"sm\" iconOnly\n\t\t\t\t\t\tonClick={onBackToFilterList}\n\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\taria-label={strings.backToFilters}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronLeft aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />\n\t\t\t\t\t</Button>\n\t\t\t) : undefined}>\n\t\t\t\t<Text tag=\"span\" weight=\"semibold\">{filter.label}</Text>\n\t\t\t</PopoverHeader>\n\n\t\t\t<Command inset=\"flush\" className=\"rounded-none\">\n\t\t\t\t{/* SECTION 2 — Search. The search row owns its inset; the\n\t\t\t\t\tcollection below owns the compact surface inset. */}\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: filter.label.toLowerCase() },\n\t\t\t\t\t)}\n\t\t\t\t/>\n\n\t\t\t\t{/* SECTION 3 — Values list.\n\t\t\t\t\tSame tokenized outer padding as the other two sections.\n\t\t\t\t\tItems inside have additional inner padding so option\n\t\t\t\t\tlabels are slightly more indented than the section frame —\n\t\t\t\t\tthat's what tells the eye \"these are list rows, not header text\". */}\n\t\t\t\t<CommandList className=\"max-h-64\">\n\t\t\t\t\t<CommandEmpty>\n\t\t\t\t\t\t<Text type=\"secondary\" align=\"center\" className=\"py-space-xl\">\n\t\t\t\t\t\t\t{strings.noOptionsFound}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</CommandEmpty>\n\t\t\t\t\t<CommandGroup>\n\t\t\t\t\t\t{filter.options?.map((option) => {\n\t\t\t\t\t\t\tconst isSelected = tempValue.includes(option.value);\n\t\t\t\t\t\t\t// data-checked toggles the CommandItem's built-in\n\t\t\t\t\t\t\t// CheckIcon (rendered after children with ml-auto).\n\t\t\t\t\t\t\treturn (\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={isSelected || undefined}\n\t\t\t\t\t\t\t\t\tdisabled={option.disabled}\n\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>\n\t\t\t\t\t\t\t\t\t{!!option.icon && (\n\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{option.icon}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<div className=\"flex min-w-0 flex-1 flex-col leading-tight\">\n\t\t\t\t\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\t\t\t\t\ttag=\"span\"\n\t\t\t\t\t\t\t\t\t\t\tlineHeight=\"tight\"\n\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\tclassName=\"truncate\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t{!!option.description && (\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\tsize=\"xs\"\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\ttype=\"secondary\"\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"truncate mt-space-2xs\"\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.description}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\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})}\n\t\t\t\t\t</CommandGroup>\n\t\t\t\t</CommandList>\n\t\t\t</Command>\n\n\t\t\t{/* Compact footer — only shows when dirty */}\n\t\t\t{!!isDirty && (\n\t\t\t\t<PopoverFooter caption={interpolateFilterString(strings.selected, {\n\t\t\t\t\tcount: tempValue.length,\n\t\t\t\t\tfilterLabel: (tempValue.length > 1 ? filter.pluralLabel : filter.label) ?? filter.label,\n\t\t\t\t})}>\n\t\t\t\t\t<Button tone=\"primary\" size=\"sm\" onClick={handleDone}>\n\t\t\t\t\t\t{strings.confirm}\n\t\t\t\t\t</Button>\n\t\t\t\t</PopoverFooter>\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 { Stack } from '../../../base/structure';\nimport { Text } from '../../../typography';\nimport { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport { FILTER_ELEMENT_HEIGHT, 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 { 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\tif (e.key === 'Enter') {\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{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=\"h-auto px-space-sm py-0 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\ttone=\"secondary\"\n\t\t\t\t\t\t\tbuttonStyle=\"ghost\"\n\t\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\t\t\tclassName=\"ml-space-sm size-icon rounded-full p-0 hover:bg-muted-foreground/20\"\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=\"size-icon-sm\" />\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\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\tclassName={FILTER_ELEMENT_HEIGHT}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<Button\n\t\t\t\t\tonClick={handleAddTag}\n\t\t\t\t\tdisabled={!inputValue.trim()}\n\t\t\t\t\tsize=\"md\"\n\t\t\t\t\tclassName={FILTER_ELEMENT_HEIGHT}\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 { ChevronLeft } from 'lucide-react';\nimport { useState, useEffect } from 'react';\nimport { Button } from '../../../base/buttons';\nimport { PopoverHeader, PopoverTitle, PopoverFooter } from '../../../base/popover';\nimport { TagsFacet } from '../facets/tags-facet';\nimport { SecondaryValue } from '../../../primitives';\nimport { useFilters } from '../filter-context';\nimport type { FilterConfig, FilterTriggerSource } from '../filters.types';\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// Use local state to track temporary values before committing\n\tconst [tempValue, setTempValue] = useState<string[]>(value || []);\n\tconst showBackButton = triggerSource === 'toolbar';\n\tconst tagCountLabel =\n\t\ttempValue.length === 1 ? strings.tag : strings.tags;\n\n\t// Update tempValue when value changes (for initial or external updates)\n\tuseEffect(() => {\n\t\tsetTempValue(value || []);\n\t}, [value]);\n\n\t// Apply changes when Done is clicked\n\tconst handleDone = () => {\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\n\treturn (\n\t\t<div className=\"flex flex-col\">\n\t\t\t<PopoverHeader\n\t\t\t\tstart={showBackButton ? (\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\tsize=\"sm\" iconOnly\n\t\t\t\t\t\tonClick={onBackToFilterList}\n\t\t\t\t\t\tclassName=\"shrink-0\"\n\t\t\t\t\t\taria-label={strings.backToFilters}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ChevronLeft aria-hidden=\"true\" className=\"size-icon-sm rtl:rotate-180\" />\n\t\t\t\t\t</Button>\n\t\t\t\t) : undefined}\n\t\t\t>\n\t\t\t\t<PopoverTitle>{filter.label}</PopoverTitle>\n\t\t\t</PopoverHeader>\n\n\t\t\t<div className=\"p-surface\">\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<PopoverFooter caption={<SecondaryValue size=\"xs\" className=\"tabular-nums\">{tempValue.length} {tagCountLabel}</SecondaryValue>}>\n\t\t\t\t\t<Button tone=\"primary\" size=\"sm\" onClick={handleDone}>{strings.confirm}</Button>\n\t\t\t\t</PopoverFooter>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import type { ComponentProps } from 'react';\nimport { useFilters } from '../filter-context';\nimport { PopoverContent } from '../../../base/popover';\nimport { cn } from '../../../../lib/utils';\nimport { FilterType, type FilterConfig, type FilterTriggerSource } from '../filters.types';\nimport { AsyncFilterContent } from './async-filter-content';\nimport { DateFilterContent } from './date-filter-content';\nimport { FilterListContent } from './filter-list-content';\nimport { RegularFilterContent } from './regular-filter-content';\nimport { TagsFilterContent } from './tags-filter-content';\n\nexport interface FilterPopoverContentProps {\n\t\t/** Which filter the popover is currently editing. */\n\t\tactiveFilterInPopover: FilterConfig | null;\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\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 } = useFilters();\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? 'w-72 gap-0 overflow-hidden'\n\t\t\t\t\t\t\t: 'w-64 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 finalFocus={finalFocus} type={activeFilterInPopover?.type === FilterType.DATE || activeFilterInPopover?.type === FilterType.TAGS ? 'display' : '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\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.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 { 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 { 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/** External signal to suppress popover open during operator change. */\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 localRef = useRef(false);\n\tconst isOperatorChangeRef = operatorChangeRef ?? localRef;\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 && isOperatorChangeRef.current) 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\tisOperatorChangeRef.current = true;\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\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tisOperatorChangeRef.current = false;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonFilterClear={() => {\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 (!isOperatorChangeRef.current) {\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\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 {\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\t// Control popover state explicitly\n\tconst [isOpen, setIsOpen] = useState(false);\n\tconst { strings } = 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={setIsOpen}>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tref={triggerRef}\n\t\t\t\t\ttone=\"secondary\" buttonStyle=\"outline\"\n\t\t\t\t\tsize=\"md\" iconOnly\n\t\t\t\t\taria-label={strings.addFilter}\n\t\t\t\t\tclassName=\"filters-button--component shrink-0\"\n\t\t\t\t>\n\t\t\t\t\t<Filter className=\"size-icon-sm\" />\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\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 { cn } from '../../../../lib/utils';\nimport { useFilters } from '../filter-context';\nimport { FilterType, type ActiveFilter, type FilterTab } from '../filters.types';\nimport { getDefaultOperatorForType } 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.\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 =\n\t\t\t\t\tpreset.operator ??\n\t\t\t\t\tfilterConfig?.operator ??\n\t\t\t\t\t(filterConfig\n\t\t\t\t\t\t? getDefaultOperatorForType(filterConfig.type)\n\t\t\t\t\t\t: 'equals');\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 <TabsList role=\"group\" aria-orientation={undefined} activateOnFocus className=\"h-auto! flex-wrap justify-start gap-space-md bg-transparent p-0\">\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={cn(\n\t\t\t\t\t\t\t'h-action-sm flex-none rounded-radius-md px-control-sm py-0 transition-colors after:hidden data-active:bg-foreground data-active:text-background data-active:hover:bg-foreground data-active:hover:text-background',\n\t\t\t\t\t\t\tisActive\n\t\t\t\t\t\t\t\t? 'bg-foreground text-background'\n\t\t\t\t\t\t\t\t: 'bg-muted text-muted-foreground hover:bg-accent hover:text-accent-foreground',\n\t\t\t\t\t\t)}\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=\"semibold\"\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\tweight=\"semibold\"\n\t\t\t\t\t\t\t\tnumeric\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'ml-space-sm text-inherit',\n\t\t\t\t\t\t\t\t\tisActive\n\t\t\t\t\t\t\t\t\t\t? 'text-background'\n\t\t\t\t\t\t\t\t\t\t: 'text-muted-foreground',\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{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, X } from 'lucide-react';\nimport React, {\n\t\ttype ChangeEvent,\n\t\tuseState,\n\t\tuseEffect,\n\t\tuseRef,\n} from 'react';\nimport { Input } from '../../../base/text-inputs';\nimport { Button } from '../../../base/buttons';\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';\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\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\tinputValueRef.current = inputValue;\n\t\t// Tracking the last value we emitted to prevent duplicate emissions\n\t\tconst lastEmittedValue = useRef<string | null>(value[0] || null);\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// Consistently handles ALL input changes\n\t\tconst debouncedUpdate = (newValue: string) => {\n\t\t\t\t// Don't emit the same value twice\n\t\t\t\tif (lastEmittedValue.current === newValue) {\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\t\t// Handle clear button click\n\t\tconst handleClear = () => {\n\t\t\t\tisUserTypingRef.current = true;\n\t\t\t\tsetInputValue('');\n\t\t\t\tdebouncedUpdate('');\n\t\t};\n\n\t\treturn (\n\t\t<div className={cn('search-facet--component', 'search-facet relative w-full min-w-0 rounded-radius bg-background', className)}>\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 = filter.label.trim().toLowerCase();\n\t\t\t\t\t\t\t\t\t\t\t\tif (!label || label === 'search') {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Collapse \"Search …\" stray space when the\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// filter label would otherwise duplicate the\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// template's leading \"Search\" word.\n\t\t\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\t\t\tstrings.searchPlaceholder,\n\t\t\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\t\t)\n\t\t\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\t\t.replace(/\\s{2,}/g, ' ')\n\t\t\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}\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\tclassName=\"w-full pr-9\"\n\t\t\t/>\n\t\t\t\t\t\t{inputValue.trim() !== '' && !isNavigating && (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\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\t\t\t\t\t\tsize=\"sm\" iconOnly\n\t\t\t\t\tonClick={handleClear}\n\t\t\t\t\t\t\t\t\t\tclassName=\"absolute right-control-gap-small top-1/2 -translate-y-1/2\"\n\t\t\t\t\taria-label={strings.clearSearch}\n\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<X className=\"size-icon-sm\" />\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{!!isNavigating && (\n\t\t\t\t\t\t\t\t<span className=\"text-muted-foreground absolute right-control-px top-1/2 -translate-y-1/2\">\n\t\t\t\t\t\t\t\t\t\t<Loader2 className=\"size-icon animate-spin\" />\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t</div>\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 { 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 { getOperatorsForType } 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\tif (filter.operators && filter.operators.length > 0) return filter.operators;\n\t\treturn getOperatorsForType(filter.type, 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\" gap={controlRowGap[variant]}>\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<div className={cn('contents', isNavigating && 'pointer-events-none opacity-60')}>\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\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=\"rounded-radius-md bg-muted/50 px-control-sm py-space-xs\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div 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\tsize=\"md\"\n\t\t\t\t\t\t\tonClick={clearFilters}\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 { getDefaultOperatorForType } from './operator-options';\nimport {\n\ttype ActiveFilter,\n\ttype FilterConfig,\n\ttype FilterOperator,\n\tFilterOperatorEnum,\n\tFilterType,\n} from './filters.types';\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\tString(item).length > 0\n\t\t\t))\n\t\t\t.map((item) => String(item));\n\n\t\tif (normalized.length > 0) {\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\nfunction getDefaultOperator(config: FilterConfig): FilterOperator {\n\treturn (\n\t\tconfig.operator ??\n\t\tconfig.operators?.[0]?.value ??\n\t\tgetDefaultOperatorForType(config.type)\n\t);\n}\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\nfunction isMultiValueFilter(config: FilterConfig): boolean {\n\treturn (\n\t\tconfig.type === FilterType.MULTI_SELECT ||\n\t\tconfig.type === FilterType.TAGS ||\n\t\tconfig.multiple === true\n\t);\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 values = normalizeValues(config, rawValues);\n\t\tif (values.length === 0) return [];\n\n\t\treturn [{\n\t\t\tid: config.key,\n\t\t\tkey: config.key,\n\t\t\toperator: readOperator(config, record, operatorSuffix),\n\t\t\tvalue: 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 = formatValues(config, activeFilter.value);\n\t\tif (values.length === 0) 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 { cn } from '../../../../lib/utils';\n\nimport { useFilters } from '../filter-context';\nimport { interpolateFilterString } from '../filters.strings';\nimport type { FilterConfig } from '../filters.types';\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.\n */\nexport function SelectFacet({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: SelectFacetProps) {\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\n\tconst handleSelect = (selectedValue: string) => {\n\t\tif (filter.multiple) {\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\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\toptions?.find((opt) => opt.value === optionValue)?.label ?? optionValue;\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,\n\t\t}));\n\t}, [options, value]);\n\n\tconst placeholderInterpolated = interpolateFilterString(\n\t\tstrings.searchPlaceholder,\n\t\t{ filterLabel: filter.label.toLowerCase() },\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=\"md\"\n\t\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\t\taria-expanded={open}\n\t\t\t\t\t\tclassName=\"w-full justify-between\"\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{interpolateFilterString(strings.selected, {\n\t\t\t\t\t\t\t\t\t\tcount: value.length,\n\t\t\t\t\t\t\t\t\t\tfilterLabel:\n\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? filter.pluralLabel\n\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})}\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, Loader2 } from 'lucide-react';\nimport { 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 {\n\tPopover,\n\tPopoverContent,\n\tPopoverTrigger,\n} from '../../../base/popover';\nimport { ErrorState, LoadingState } from '../../../base/feedback';\nimport { Stack } from '../../../base/structure';\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';\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 { 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\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\tconst label = getAsyncOptionLabel(filter.key, val);\n\t\t\t\t\tif (label) {\n\t\t\t\t\t\tmissingSelected.push({ value: val, label, icon: filter.icon });\n\t\t\t\t\t}\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=\"md\"\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=\"w-full justify-between\"\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:\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})}\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>\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{Boolean(isFetching && !isLoading) && (\n\t\t\t\t\t\t\t\t\t\t<Stack direction=\"horizontal\" gap=\"sm\" wrap={false} className=\"px-control-sm py-space-xs\">\n\t\t\t\t\t\t\t\t\t\t\t<Loader2 className=\"text-muted-foreground size-icon-sm animate-spin\" />\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\tsize=\"xs\"\n\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>\n\t\t\t\t\t\t\t\t\t\t\t\t{strings.searching}\n\t\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t\t</Stack>\n\t\t\t\t\t\t\t\t\t)}\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</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","import { useState, useEffect, useId, type ChangeEvent } from 'react';\nimport { Input } from '../../../base/text-inputs';\nimport { Grid, Stack } from '../../../base/structure';\nimport { Label } 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';\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/**\n * Range Filter Facet\n *\n * This component implements a numeric range filter that allows users to:\n * - Set minimum and maximum values\n * - Configure step size and precision\n * - Set value constraints (min/max allowed values)\n * - Customize the range input appearance\n *\n * The component integrates with the filter context to manage the range values\n * and provides a user-friendly interface for range selection.\n */\n\nexport function RangeFacet({\n\tfilter,\n\tvalue,\n\tonValueChange,\n\tclassName,\n}: RangeFacetProps) {\n\tconst { strings } = useFilters();\n\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 instanceId = useId(); // Keep ids unique when multiple range facets render\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\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\temitRange({\n\t\t\tmin: minValue ? Number(minValue) : undefined,\n\t\t\tmax: maxValue ? Number(maxValue) : undefined,\n\t\t});\n\n\t\treturn emitRange.cancel;\n\t}, [minValue, maxValue, emitRange]);\n\n\tconst handleMinChange = (e: ChangeEvent<HTMLInputElement>) => {\n\t\tconst val = e.target.value;\n\t\tif (val === '' || /^\\d*\\.?\\d*$/.test(val)) {\n\t\t\tsetMinValue(val);\n\t\t}\n\t};\n\n\tconst handleMaxChange = (e: ChangeEvent<HTMLInputElement>) => {\n\t\tconst val = e.target.value;\n\t\tif (val === '' || /^\\d*\\.?\\d*$/.test(val)) {\n\t\t\tsetMaxValue(val);\n\t\t}\n\t};\n\n\treturn (\n\t\t<Stack gap=\"md\" className={cn('range-facet--component', className)}>\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`}>\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\tvalue={minValue}\n\t\t\t\t\t\tonChange={handleMinChange}\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`}>\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\tvalue={maxValue}\n\t\t\t\t\t\tonChange={handleMaxChange}\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</Stack>\n\t);\n}\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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"}
|