@persona/design-system 0.9.1 → 0.10.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 +43 -0
- package/README.md +1 -1
- package/dist/Accordion.d.mts +1 -1
- package/dist/AccordionItem.d.mts +1 -1
- package/dist/{Action-BleGvmsy.d.mts → Action-DT8WqfEg.d.mts} +3 -3
- package/dist/Action.d.mts +1 -1
- package/dist/AdvancedFilterRuleRow.d.mts +2 -2
- package/dist/AdvancedFilterRulesPopover.d.mts +2 -2
- package/dist/ArrayValueControl.d.mts +1 -1
- package/dist/Attribute.d.mts +4 -4
- package/dist/{Badge-BYa-iqNE.mjs → Badge-Bvn3afds.mjs} +2 -2
- package/dist/{Badge-BYa-iqNE.mjs.map → Badge-Bvn3afds.mjs.map} +1 -1
- package/dist/BooleanValueControl.d.mts +1 -1
- package/dist/{Breadcrumb-CEHEUe8l.d.mts → Breadcrumb-BDbY1Ffu.d.mts} +1 -1
- package/dist/Breadcrumb.d.mts +1 -1
- package/dist/{Breadcrumbs-BQ-Gj6UV.d.mts → Breadcrumbs-C2ThOYJ-.d.mts} +2 -2
- package/dist/{Breadcrumbs-BmlndU4V.mjs → Breadcrumbs-CQUe9VTM.mjs} +8 -8
- package/dist/{Breadcrumbs-BmlndU4V.mjs.map → Breadcrumbs-CQUe9VTM.mjs.map} +1 -1
- package/dist/Breadcrumbs.d.mts +1 -1
- package/dist/{Button-Dx7mHjWC.d.mts → Button-CyjqQa5v.d.mts} +5 -5
- package/dist/Button.d.mts +1 -1
- package/dist/{Calendar-BvsTQ3e1.d.mts → Calendar-DAfQCLOJ.d.mts} +1 -1
- package/dist/Calendar.d.mts +1 -1
- package/dist/CalendarBase.d.mts +1 -1
- package/dist/{Card-BPY0OU7e.d.mts → Card-CzRHVUFo.d.mts} +4 -4
- package/dist/Card.d.mts +1 -1
- package/dist/Card2.d.mts +1 -1
- package/dist/CardGrouping.d.mts +2 -2
- package/dist/{CardV2-Cq4QODeE.mjs → CardV2-Dp4eHSE-.mjs} +11 -11
- package/dist/{CardV2-Cq4QODeE.mjs.map → CardV2-Dp4eHSE-.mjs.map} +1 -1
- package/dist/{Checkbox-CVa8WOf2.d.mts → Checkbox-B2MZShdu.d.mts} +1 -1
- package/dist/{Checkbox-Cttn1t8T.mjs → Checkbox-BaJ-dGdX.mjs} +5 -5
- package/dist/{Checkbox-Cttn1t8T.mjs.map → Checkbox-BaJ-dGdX.mjs.map} +1 -1
- package/dist/Checkbox.d.mts +1 -1
- package/dist/{CheckboxGroupField-BpHN_2QP.d.mts → CheckboxGroupField-BYB4OBlW.d.mts} +3 -3
- package/dist/CheckboxGroupField.d.mts +1 -1
- package/dist/ChoicesValueControl.d.mts +1 -1
- package/dist/{Combobox-CsXnJKvB.mjs → Combobox-CcFJo68g.mjs} +19 -11
- package/dist/Combobox-CcFJo68g.mjs.map +1 -0
- package/dist/{Combobox-C4C2P8lF.d.mts → Combobox-DH5ycYlG.d.mts} +3 -3
- package/dist/Combobox.d.mts +2 -2
- package/dist/{ComboboxBase-2nVpt8oj.d.mts → ComboboxBase-BQQSKUBU.d.mts} +7 -7
- package/dist/ComboboxBase.d.mts +1 -1
- package/dist/{ComboboxMultiSelect-BvJ--m6z.d.mts → ComboboxMultiSelect-Da3Gv1k5.d.mts} +2 -2
- package/dist/ComboboxMultiSelect.d.mts +1 -1
- package/dist/{ComboboxSingleSelect-BWrnRA2x.d.mts → ComboboxSingleSelect-BUDovONU.d.mts} +4 -4
- package/dist/ComboboxSingleSelect.d.mts +1 -1
- package/dist/{CompactBar-CmTT9iuT.d.mts → CompactBar-D12R7Nm2.d.mts} +3 -3
- package/dist/CompactBar.d.mts +1 -1
- package/dist/{ConfigFormGroup-C0orlWwb.mjs → ConfigFormGroup-CidT_cE9.mjs} +2 -2
- package/dist/{ConfigFormGroup-C0orlWwb.mjs.map → ConfigFormGroup-CidT_cE9.mjs.map} +1 -1
- package/dist/{ControlBar-Cg36sjz3.d.mts → ControlBar-D9KflqmH.d.mts} +22 -9
- package/dist/ControlBar.d.mts +1 -1
- package/dist/DataTable-95ZxiPlV.mjs +1547 -0
- package/dist/DataTable-95ZxiPlV.mjs.map +1 -0
- package/dist/DataTable-fZ7SNbIH.d.mts +439 -0
- package/dist/DataTable.d.mts +2 -396
- package/dist/{DateField-BXUuqbnb.d.mts → DateField-DLz13Ksl.d.mts} +2 -2
- package/dist/DateField.d.mts +1 -1
- package/dist/{DatePicker-DQHVCGnP.mjs → DatePicker-D0cvVbzq.mjs} +374 -374
- package/dist/DatePicker-D0cvVbzq.mjs.map +1 -0
- package/dist/{DatePicker-Cmn1vViU.d.mts → DatePicker-DYVWmbrb.d.mts} +2 -2
- package/dist/DatePicker.d.mts +1 -1
- package/dist/{DateRangePicker-CKhp9Obv.d.mts → DateRangePicker-Be8TYtjz.d.mts} +3 -3
- package/dist/DateRangePicker.d.mts +1 -1
- package/dist/DateRangeValueControl.d.mts +2 -2
- package/dist/DateValueControl.d.mts +1 -1
- package/dist/{DropdownButton-C9wWnB5w.mjs → DropdownButton-5oNcpsOq.mjs} +3 -3
- package/dist/{DropdownButton-C9wWnB5w.mjs.map → DropdownButton-5oNcpsOq.mjs.map} +1 -1
- package/dist/DropdownButton.d.mts +2 -2
- package/dist/{DropdownMenu-CPE8Q56k.mjs → DropdownMenu-CedsmO5h.mjs} +2 -2
- package/dist/{DropdownMenu-CPE8Q56k.mjs.map → DropdownMenu-CedsmO5h.mjs.map} +1 -1
- package/dist/{DropdownMenu-BZ62b8Cv.d.mts → DropdownMenu-DAa2kNrt.d.mts} +3 -3
- package/dist/DropdownMenu.d.mts +1 -1
- package/dist/{ErrorProps-oCHtJzEB.d.mts → ErrorProps-DH0fzeGf.d.mts} +1 -1
- package/dist/ErrorProps.d.mts +1 -1
- package/dist/{FieldRegistry-DAk_3PhH.d.mts → FieldRegistry-d5tGpSch.d.mts} +2 -2
- package/dist/FieldRegistry.d.mts +1 -1
- package/dist/{FilterBar-C7ch6kYM.d.mts → FilterBar-Bh18VyOK.d.mts} +4 -4
- package/dist/FilterBar.d.mts +1 -1
- package/dist/FilterPickerMenu.d.mts +2 -2
- package/dist/FilterPill.d.mts +1 -1
- package/dist/FilterPopover.d.mts +1 -1
- package/dist/FloatValueControl.d.mts +1 -1
- package/dist/FloatingActionBar-CpvLefPm.d.mts +41 -0
- package/dist/FloatingActionBar.d.mts +2 -41
- package/dist/{FormControl-CD_FdAXA.mjs → FormControl-C4CiA0H-.mjs} +4 -4
- package/dist/{FormControl-CD_FdAXA.mjs.map → FormControl-C4CiA0H-.mjs.map} +1 -1
- package/dist/{FormControl-DX4vtUp6.d.mts → FormControl-DEG_0oXt.d.mts} +3 -3
- package/dist/FormControl.d.mts +1 -1
- package/dist/FormControlLabel.d.mts +2 -2
- package/dist/{FormField-DjysBTKn.mjs → FormField-cSG93kuo.mjs} +15 -15
- package/dist/{FormField-DjysBTKn.mjs.map → FormField-cSG93kuo.mjs.map} +1 -1
- package/dist/{FormField-C80kGAIV.d.mts → FormField-mLbXDJ9B.d.mts} +2 -2
- package/dist/FormField.d.mts +1 -1
- package/dist/{Grid-D0mlxk8_.mjs → Grid-DXVkhyNQ.mjs} +1 -1
- package/dist/{Grid-D0mlxk8_.mjs.map → Grid-DXVkhyNQ.mjs.map} +1 -1
- package/dist/{Header-C-a5fL3k.d.mts → Header-ayDu4VWE.d.mts} +2 -2
- package/dist/Header.d.mts +1 -1
- package/dist/{HelperTooltip-hhMFkKmn.d.mts → HelperTooltip-BB9Vznnx.d.mts} +2 -2
- package/dist/HelperTooltip.d.mts +1 -1
- package/dist/HighlightedText.d.mts +3 -3
- package/dist/{HoverCopyableField-Cgu3W31s.mjs → HoverCopyableField-D-BubaRd.mjs} +4 -4
- package/dist/{HoverCopyableField-Cgu3W31s.mjs.map → HoverCopyableField-D-BubaRd.mjs.map} +1 -1
- package/dist/{I18nContext-ioYM_vqG.d.mts → I18nContext-TXS9M8t5.d.mts} +2 -2
- package/dist/I18nContext.d.mts +1 -1
- package/dist/{IconButton-DJ3L_ZqN.d.mts → IconButton-Bigvu1Q4.d.mts} +2 -2
- package/dist/{IconButton-D4awF770.mjs → IconButton-HWx5Hlmi.mjs} +14 -11
- package/dist/{IconButton-D4awF770.mjs.map → IconButton-HWx5Hlmi.mjs.map} +1 -1
- package/dist/IconButton.d.mts +1 -1
- package/dist/ImageTile.d.mts +4 -3
- package/dist/IndexTableLayout.d.mts +45 -0
- package/dist/InlineCombobox.d.mts +1 -1
- package/dist/InlineInput.d.mts +1 -1
- package/dist/{Input-D3lXfJHq.d.mts → Input-Bg4bi6VZ.d.mts} +4 -4
- package/dist/{Input-DD4jzJhK.mjs → Input-Dap055xf.mjs} +5 -5
- package/dist/{Input-DD4jzJhK.mjs.map → Input-Dap055xf.mjs.map} +1 -1
- package/dist/Input.d.mts +1 -1
- package/dist/{InputProps-BU9iiBBz.d.mts → InputProps-Bl-G826g.d.mts} +2 -2
- package/dist/InputProps.d.mts +1 -1
- package/dist/Inserter-BKVrJ4M5.d.mts +12 -0
- package/dist/Inserter.d.mts +2 -12
- package/dist/IntegerValueControl.d.mts +1 -1
- package/dist/{Link-DGZu4J0x.mjs → Link-Cf__H8gD.mjs} +4 -4
- package/dist/{Link-DGZu4J0x.mjs.map → Link-Cf__H8gD.mjs.map} +1 -1
- package/dist/Link.d.mts +1 -1
- package/dist/{ListBox-CjGb0mMY.d.mts → ListBox-Bj5c626-.d.mts} +3 -3
- package/dist/{ListBox-BhWLad_L.mjs → ListBox-C80J7DCG.mjs} +12 -12
- package/dist/{ListBox-BhWLad_L.mjs.map → ListBox-C80J7DCG.mjs.map} +1 -1
- package/dist/ListBox.d.mts +1 -1
- package/dist/{ListBoxField-BUkPeLiB.d.mts → ListBoxField-DsJRabgE.d.mts} +4 -4
- package/dist/ListBoxField.d.mts +1 -1
- package/dist/LoadingShimmer.d.mts +2 -2
- package/dist/{LogicRow-Bt6NPLOd.d.mts → LogicRow-CcpD-Kk3.d.mts} +3 -3
- package/dist/LogicRow.d.mts +1 -1
- package/dist/MaskedInput.d.mts +1 -1
- package/dist/MatchHighlight.d.mts +1 -1
- package/dist/{Menu-BMrsN-Jz.d.mts → Menu-C0FU9WEF.d.mts} +4 -4
- package/dist/{Menu-DlN0A5Nb.mjs → Menu-Dw6Rcpk6.mjs} +4 -4
- package/dist/{Menu-DlN0A5Nb.mjs.map → Menu-Dw6Rcpk6.mjs.map} +1 -1
- package/dist/Menu.d.mts +1 -1
- package/dist/{Modal-BoeGuR-h.d.mts → Modal-BuxggahW.d.mts} +7 -3
- package/dist/{Modal-Cs5cZpEr.mjs → Modal-kjUptzg1.mjs} +8 -6
- package/dist/Modal-kjUptzg1.mjs.map +1 -0
- package/dist/Modal.d.mts +1 -1
- package/dist/PageHeader-Czj42pyK.d.mts +40 -0
- package/dist/{PageHeader-CCoAJUwJ.mjs → PageHeader-DJF7nxgN.mjs} +2 -2
- package/dist/{PageHeader-CCoAJUwJ.mjs.map → PageHeader-DJF7nxgN.mjs.map} +1 -1
- package/dist/PageHeader.d.mts +2 -40
- package/dist/{PageLayout-BlCo4hN4.d.mts → PageLayout-TBemv7oL.d.mts} +2 -2
- package/dist/{PageLayout-C7ZC7GBA.mjs → PageLayout-fXJW7daI.mjs} +2 -2
- package/dist/{PageLayout-C7ZC7GBA.mjs.map → PageLayout-fXJW7daI.mjs.map} +1 -1
- package/dist/PageLayout.d.mts +1 -1
- package/dist/{PageLayoutFrame--HlvI4Pp.d.mts → PageLayoutFrame-DzwlkNZ1.d.mts} +1 -1
- package/dist/PageLayoutFrame.d.mts +1 -1
- package/dist/{PageSelector-BmevrorJ.d.mts → PageSelector-DXCeBUoU.d.mts} +3 -3
- package/dist/PageSelector.d.mts +1 -1
- package/dist/{Pagination-C67fsrxl.d.mts → Pagination-COcFWlha.d.mts} +2 -2
- package/dist/{Pagination-Du2CPW2l.mjs → Pagination-DtK-jbEY.mjs} +5 -5
- package/dist/{Pagination-Du2CPW2l.mjs.map → Pagination-DtK-jbEY.mjs.map} +1 -1
- package/dist/Pagination.d.mts +1 -1
- package/dist/{Pii-CFVWZ_Yx.mjs → Pii-DueIK287.mjs} +2 -2
- package/dist/{Pii-CFVWZ_Yx.mjs.map → Pii-DueIK287.mjs.map} +1 -1
- package/dist/{PillShell-jr6OyAd3.d.mts → PillShell-CXROf8gO.d.mts} +2 -2
- package/dist/PillShell.d.mts +1 -1
- package/dist/{Popover-DewrGOJB.mjs → Popover-BcII7usF.mjs} +2 -2
- package/dist/{Popover-DewrGOJB.mjs.map → Popover-BcII7usF.mjs.map} +1 -1
- package/dist/{ProgressIndicator-CdhC2LVI.d.mts → ProgressIndicator-C5sbFQcd.d.mts} +1 -1
- package/dist/{ProgressIndicator-xV5Cl2Bw.mjs → ProgressIndicator-CM37EU1B.mjs} +3 -3
- package/dist/{ProgressIndicator-xV5Cl2Bw.mjs.map → ProgressIndicator-CM37EU1B.mjs.map} +1 -1
- package/dist/ProgressIndicator.d.mts +1 -1
- package/dist/{PseudoClassProps-CverE9Ni.d.mts → PseudoClassProps-BFFh2-u8.d.mts} +1 -1
- package/dist/PseudoClassProps.d.mts +1 -1
- package/dist/{Radio-i7AEQZHb.mjs → Radio-DDT_l8rd.mjs} +4 -4
- package/dist/{Radio-i7AEQZHb.mjs.map → Radio-DDT_l8rd.mjs.map} +1 -1
- package/dist/{RadioGroup-CDEfCg-b.d.mts → RadioGroup-BxEmipHa.d.mts} +1 -1
- package/dist/{RadioGroup-B0KcQpS7.mjs → RadioGroup-CmD8NFCL.mjs} +2 -2
- package/dist/{RadioGroup-B0KcQpS7.mjs.map → RadioGroup-CmD8NFCL.mjs.map} +1 -1
- package/dist/RadioGroup.d.mts +1 -1
- package/dist/{RangeCalendar-BOt59kTG.d.mts → RangeCalendar-cZSYjuOZ.d.mts} +2 -2
- package/dist/RangeCalendar.d.mts +1 -1
- package/dist/RangeCalendarPresets.d.mts +1 -1
- package/dist/{RouterContext-D7HBESqO.d.mts → RouterContext-CoDbEb_X.d.mts} +2 -2
- package/dist/RouterContext.d.mts +1 -1
- package/dist/{RouterLink-dppNWLgP.d.mts → RouterLink-BnIEi8d4.d.mts} +2 -2
- package/dist/RouterLink.d.mts +1 -1
- package/dist/RuleEditorFields.d.mts +2 -2
- package/dist/RulesPill.d.mts +1 -1
- package/dist/{SearchInput-B7JYHJZI.d.mts → SearchInput-DLC7-A7K.d.mts} +2 -2
- package/dist/SearchInput.d.mts +1 -1
- package/dist/SectionHeading.d.mts +1 -1
- package/dist/{SegmentedControl-B2_bS806.mjs → SegmentedControl-CcKPfxBR.mjs} +2 -2
- package/dist/{SegmentedControl-B2_bS806.mjs.map → SegmentedControl-CcKPfxBR.mjs.map} +1 -1
- package/dist/{SegmentedControl-C_7mTcuL.d.mts → SegmentedControl-xjU-2IsJ.d.mts} +1 -1
- package/dist/SegmentedControl.d.mts +1 -1
- package/dist/{Select-oVJ0uLa7.mjs → Select-BJ9ACmRD.mjs} +8 -8
- package/dist/{Select-oVJ0uLa7.mjs.map → Select-BJ9ACmRD.mjs.map} +1 -1
- package/dist/{Select-BpAA5ETS.d.mts → Select-sBEBrNgo.d.mts} +3 -3
- package/dist/Select.d.mts +1 -1
- package/dist/{SingleColumnLayout-ByWxiD7d.d.mts → SingleColumnLayout-CBynMc76.d.mts} +2 -2
- package/dist/SingleColumnLayout.d.mts +1 -1
- package/dist/SmartTextInput.d.mts +6 -6
- package/dist/SmartTextInputField.d.mts +2 -2
- package/dist/SmartTextInputFunctionDialog.d.mts +4 -4
- package/dist/SmartTextInputListbox.d.mts +2 -2
- package/dist/SmartTextInputPopover.d.mts +2 -2
- package/dist/{Spinner-0Vqw_68r.mjs → Spinner-uVZyOh1T.mjs} +2 -2
- package/dist/{Spinner-0Vqw_68r.mjs.map → Spinner-uVZyOh1T.mjs.map} +1 -1
- package/dist/{SplitColumnLayout-DYyJabQ3.d.mts → SplitColumnLayout-BVzGbEDC.d.mts} +2 -2
- package/dist/SplitColumnLayout.d.mts +1 -1
- package/dist/{Stack-DpWl6orU.d.mts → Stack-BZyboHQl.d.mts} +2 -2
- package/dist/Stack.d.mts +1 -1
- package/dist/{StatusIndicator-QsVgjRrt.mjs → StatusIndicator-Bunn9YLV.mjs} +3 -3
- package/dist/{StatusIndicator-QsVgjRrt.mjs.map → StatusIndicator-Bunn9YLV.mjs.map} +1 -1
- package/dist/{Sticker-C260e6kl.d.mts → Sticker-CsUSNIH-.d.mts} +5 -5
- package/dist/{Sticker-CUqHa9Mo.mjs → Sticker-yhxtIYH8.mjs} +5 -5
- package/dist/{Sticker-CUqHa9Mo.mjs.map → Sticker-yhxtIYH8.mjs.map} +1 -1
- package/dist/Sticker.d.mts +1 -1
- package/dist/StringValueControl.d.mts +1 -1
- package/dist/Tab.d.mts +2 -2
- package/dist/{TabBar-w_gxXSwA.mjs → TabBar-SX8E9-Bk.mjs} +5 -5
- package/dist/{TabBar-w_gxXSwA.mjs.map → TabBar-SX8E9-Bk.mjs.map} +1 -1
- package/dist/{Table-PbYGf3PG.mjs → Table--o4ZLRbb.mjs} +8 -8
- package/dist/{Table-PbYGf3PG.mjs.map → Table--o4ZLRbb.mjs.map} +1 -1
- package/dist/{Table-BtNYI6QX.d.mts → Table-CadXF71E.d.mts} +1 -1
- package/dist/Table.d.mts +1 -1
- package/dist/{TableBody-DQ7pivxP.d.mts → TableBody-BKSHNSTo.d.mts} +1 -1
- package/dist/TableBody.d.mts +1 -1
- package/dist/{TableBox-DMYLTIpr.mjs → TableBox-3qunC9Nl.mjs} +13 -13
- package/dist/{TableBox-DMYLTIpr.mjs.map → TableBox-3qunC9Nl.mjs.map} +1 -1
- package/dist/TableBox.d.mts +2 -2
- package/dist/{TableBoxCell-DwAOA-oO.d.mts → TableBoxCell-BRECnVTs.d.mts} +7 -7
- package/dist/TableBoxCell.d.mts +1 -1
- package/dist/{TableBoxField-Bdj_nY7j.d.mts → TableBoxField-Lm_tn73M.d.mts} +5 -5
- package/dist/TableBoxField.d.mts +1 -1
- package/dist/{TableBoxRow-5WBwyAyn.d.mts → TableBoxRow-BS8Dc-zw.d.mts} +3 -3
- package/dist/TableBoxRow.d.mts +1 -1
- package/dist/{TableBoxRowActions-Dq_Z2ted.d.mts → TableBoxRowActions-oLMb8XcM.d.mts} +2 -2
- package/dist/TableBoxRowActions.d.mts +1 -1
- package/dist/{TableCell-DXBHZ52E.d.mts → TableCell-4u5_BgTC.d.mts} +3 -3
- package/dist/TableCell.d.mts +1 -1
- package/dist/{TableControls-C1MF2JvY.mjs → TableControls-DxSFqRwJ.mjs} +623 -131
- package/dist/TableControls-DxSFqRwJ.mjs.map +1 -0
- package/dist/{TableControls-Cw7LDHWj.d.mts → TableControls-UfObf-ZN.d.mts} +14 -7
- package/dist/TableControls.d.mts +1 -1
- package/dist/{TableControlsContext-DgoZhMpQ.d.mts → TableControlsContext-Bhtb0cMs.d.mts} +4 -4
- package/dist/TableControlsContext.d.mts +1 -1
- package/dist/{TableHead-BGUg_aXc.d.mts → TableHead-BuCQeDAq.d.mts} +1 -1
- package/dist/TableHead.d.mts +1 -1
- package/dist/{TableHeaderCell-DcZcMQyR.d.mts → TableHeaderCell-DIcQlZps.d.mts} +1 -1
- package/dist/TableHeaderCell.d.mts +1 -1
- package/dist/{TableLayout-CwYQaZlA.d.mts → TableLayout-ScEVdvvA.d.mts} +1 -1
- package/dist/TableLayout.d.mts +1 -1
- package/dist/{TableRow-Dad6_CoD.d.mts → TableRow-lCsvG0a-.d.mts} +2 -2
- package/dist/TableRow.d.mts +1 -1
- package/dist/TableTH.d.mts +1 -1
- package/dist/{TableViewConfigurationDropdown-BGuWAarQ.d.mts → TableViewConfigurationDropdown-BDXe2Q1Y.d.mts} +2 -2
- package/dist/TableViewConfigurationDropdown.d.mts +1 -1
- package/dist/{TechnicalSticker-RQ-4_Tdr.mjs → TechnicalSticker-CALVwnrT.mjs} +5 -5
- package/dist/{TechnicalSticker-RQ-4_Tdr.mjs.map → TechnicalSticker-CALVwnrT.mjs.map} +1 -1
- package/dist/{Text-BBMau410.d.mts → Text-RSzei6Se.d.mts} +4 -4
- package/dist/Text.d.mts +1 -1
- package/dist/{TextArea-BaA8H7s7.mjs → TextArea-CFf0Lspu.mjs} +2 -2
- package/dist/{TextArea-BaA8H7s7.mjs.map → TextArea-CFf0Lspu.mjs.map} +1 -1
- package/dist/{TextArea-Djd1uT3B.d.mts → TextArea-DFn4XuG-.d.mts} +2 -2
- package/dist/TextArea.d.mts +1 -1
- package/dist/{TextUnderlineTooltip-C4N0bqbh.d.mts → TextUnderlineTooltip-B0iYaPM1.d.mts} +3 -3
- package/dist/TextUnderlineTooltip.d.mts +1 -1
- package/dist/Tile.d.mts +1 -1
- package/dist/Toast.d.mts +1 -1
- package/dist/{Toggle-C9cZnajR.mjs → Toggle-BLdemkh_.mjs} +6 -6
- package/dist/{Toggle-C9cZnajR.mjs.map → Toggle-BLdemkh_.mjs.map} +1 -1
- package/dist/{Toggle-EYpW34LO.d.mts → Toggle-xtPgGaGD.d.mts} +1 -1
- package/dist/Toggle.d.mts +1 -1
- package/dist/{Tooltip-DogEteGl.mjs → Tooltip-B-0VRuKT.mjs} +2 -2
- package/dist/{Tooltip-DogEteGl.mjs.map → Tooltip-B-0VRuKT.mjs.map} +1 -1
- package/dist/{Tooltip-Dj-DtGKz.d.mts → Tooltip-Blfhi2gT.d.mts} +3 -3
- package/dist/Tooltip.d.mts +1 -1
- package/dist/{TruncatedText-BDNFUuhG.d.mts → TruncatedText-BMQmveJG.d.mts} +2 -2
- package/dist/VersionHistory.d.mts +1 -1
- package/dist/{VersionHistoryItem-iUabmk_y.d.mts → VersionHistoryItem-BExp7oSr.d.mts} +1 -1
- package/dist/VersionHistoryItem.d.mts +1 -1
- package/dist/WizardModal.d.mts +2 -2
- package/dist/{accordionTitleTypography-C7VVJvlx.d.mts → accordionTitleTypography-PMKnfoy0.d.mts} +2 -2
- package/dist/accordionTitleTypography.d.mts +1 -1
- package/dist/{chainTypes-DT-9j_sG.d.mts → chainTypes-BbFZn8a9.d.mts} +4 -4
- package/dist/clientFilterUtils-c5xzvoBj.d.mts +20 -0
- package/dist/clientFilterUtils.d.mts +2 -0
- package/dist/{codec-CGj8cwcj.d.mts → codec-DIp7dhcN.d.mts} +2 -2
- package/dist/codec.d.mts +1 -1
- package/dist/{color-BOm5A1Si.d.mts → color-C5B1pN1D.d.mts} +2 -2
- package/dist/components/Accordion/index.d.mts +1 -1
- package/dist/components/Accordion/index.mjs +4 -4
- package/dist/components/Attribute/index.mjs +4 -4
- package/dist/components/Badge/index.mjs +1 -1
- package/dist/components/Banner/index.mjs +3 -3
- package/dist/components/BottomPanel/index.mjs +4 -4
- package/dist/components/Breadcrumbs/index.d.mts +1 -1
- package/dist/components/Breadcrumbs/index.mjs +1 -1
- package/dist/components/Button/index.d.mts +2 -2
- package/dist/components/Button/index.mjs +1 -1
- package/dist/components/ButtonGroup/index.mjs +2 -2
- package/dist/components/Card/index.d.mts +2 -2
- package/dist/components/CardV2/index.d.mts +1 -1
- package/dist/components/CardV2/index.mjs +1 -1
- package/dist/components/Checkbox/index.d.mts +1 -1
- package/dist/components/Checkbox/index.mjs +1 -1
- package/dist/components/CodeHighlight/index.mjs +3 -3
- package/dist/components/Combobox/index.d.mts +2 -2
- package/dist/components/Combobox/index.mjs +1 -1
- package/dist/components/ConfigFormGroup/index.mjs +2 -2
- package/dist/components/DataTable/TableControls/index.d.mts +22 -20
- package/dist/components/DataTable/TableControls/index.mjs +2 -2
- package/dist/components/DataTable/index.d.mts +9 -8
- package/dist/components/DataTable/index.mjs +2 -1474
- package/dist/components/DataTable/types.d.mts +2 -166
- package/dist/components/DatePicker/index.d.mts +5 -5
- package/dist/components/DatePicker/index.mjs +1 -1
- package/dist/components/DropdownButton/index.mjs +1 -1
- package/dist/components/DropdownMenu/index.d.mts +1 -1
- package/dist/components/DropdownMenu/index.mjs +1 -1
- package/dist/components/FloatingPanel/index.mjs +5 -5
- package/dist/components/FormControl/index.d.mts +2 -2
- package/dist/components/FormControl/index.mjs +2 -2
- package/dist/components/FormField/index.d.mts +5 -5
- package/dist/components/FormField/index.mjs +1 -1
- package/dist/components/Grid/index.mjs +1 -1
- package/dist/components/HoverCopyableField/index.mjs +1 -1
- package/dist/components/ImageTile/index.mjs +30 -17
- package/dist/components/ImageTile/index.mjs.map +1 -1
- package/dist/components/Input/index.d.mts +1 -1
- package/dist/components/Input/index.mjs +1 -1
- package/dist/components/Link/index.mjs +1 -1
- package/dist/components/ListBox/index.d.mts +3 -3
- package/dist/components/ListBox/index.mjs +1 -1
- package/dist/components/MaskedInput/index.mjs +1 -1
- package/dist/components/Menu/index.d.mts +1 -1
- package/dist/components/Menu/index.mjs +1 -1
- package/dist/components/Modal/index.d.mts +1 -1
- package/dist/components/Modal/index.mjs +1 -1
- package/dist/components/PageHeader/index.d.mts +1 -1
- package/dist/components/PageHeader/index.mjs +1 -1
- package/dist/components/Pagination/index.d.mts +3 -3
- package/dist/components/Pagination/index.mjs +1 -1
- package/dist/components/Pii/index.mjs +1 -1
- package/dist/components/Popover/index.mjs +1 -1
- package/dist/components/ProgressBar/index.mjs +1 -1
- package/dist/components/ProgressIndicator/index.d.mts +1 -1
- package/dist/components/ProgressIndicator/index.mjs +1 -1
- package/dist/components/Radio/index.mjs +1 -1
- package/dist/components/RadioGroup/index.d.mts +1 -1
- package/dist/components/RadioGroup/index.mjs +1 -1
- package/dist/components/RightPanel/index.mjs +2 -2
- package/dist/components/SegmentedControl/index.d.mts +1 -1
- package/dist/components/SegmentedControl/index.mjs +1 -1
- package/dist/components/Select/index.d.mts +1 -1
- package/dist/components/Select/index.mjs +1 -1
- package/dist/components/Slider/index.mjs +2 -2
- package/dist/components/SmartTextInput/index.d.mts +2 -2
- package/dist/components/SmartTextInput/index.mjs +6 -6
- package/dist/components/SmartTextInput/parser/method-chain/types.d.mts +1 -1
- package/dist/components/SmartTextInput/parser/smart-text/types.d.mts +2 -2
- package/dist/components/Spinner/index.mjs +1 -1
- package/dist/components/Stack/index.d.mts +1 -1
- package/dist/components/StatusIndicator/index.mjs +1 -1
- package/dist/components/Sticker/index.d.mts +1 -1
- package/dist/components/Sticker/index.mjs +1 -1
- package/dist/components/TabBar/index.mjs +1 -1
- package/dist/components/Table/index.d.mts +8 -8
- package/dist/components/Table/index.mjs +1 -1
- package/dist/components/TableBox/index.d.mts +2 -2
- package/dist/components/TableBox/index.mjs +1 -1
- package/dist/components/TechnicalSticker/index.mjs +1 -1
- package/dist/components/Text/index.d.mts +1 -1
- package/dist/components/TextArea/index.d.mts +1 -1
- package/dist/components/TextArea/index.mjs +1 -1
- package/dist/components/Tile/index.mjs +2 -2
- package/dist/components/Toast/index.mjs +4 -4
- package/dist/components/Toggle/index.d.mts +1 -1
- package/dist/components/Toggle/index.mjs +1 -1
- package/dist/components/Tooltip/index.d.mts +3 -3
- package/dist/components/Tooltip/index.mjs +1 -1
- package/dist/components/VersionHistory/index.d.mts +1 -1
- package/dist/components/VersionHistory/index.mjs +7 -7
- package/dist/compound-expression.d.mts +1 -1
- package/dist/{constants-CwzbyAdc.d.mts → constants-4rSh8e5G.d.mts} +1 -1
- package/dist/constants-BaMvTUbS.d.mts +10 -0
- package/dist/constants.d.mts +1 -1
- package/dist/constants2.d.mts +2 -10
- package/dist/{createPath-C4jIHe68.d.mts → createPath-B_CLq82C.d.mts} +2 -2
- package/dist/createPath.d.mts +1 -1
- package/dist/{date-filter-CWgCXz85.mjs → date-filter-D0ys8s0D.mjs} +1 -1
- package/dist/{date-filter-CWgCXz85.mjs.map → date-filter-D0ys8s0D.mjs.map} +1 -1
- package/dist/{date-range-rule-value-BkbGpLNH.d.mts → date-range-rule-value-D01nn054.d.mts} +2 -2
- package/dist/date-range-rule-value.d.mts +1 -1
- package/dist/{date-rule-intent-zdKP-tW_.d.mts → date-rule-intent-B4hQ_APa.d.mts} +3 -3
- package/dist/date-rule-intent.d.mts +1 -1
- package/dist/display.d.mts +2 -2
- package/dist/fieldPickerOptions.d.mts +2 -2
- package/dist/{filter-size-context-CW1guBfI.d.mts → filter-size-context-Dj7Idc8j.d.mts} +2 -2
- package/dist/filter-size-context.d.mts +1 -1
- package/dist/filters-DDrsgRYy.d.mts +22 -0
- package/dist/filters.d.mts +2 -0
- package/dist/{formatDateTime-zyRMjfH8.d.mts → formatDateTime-Dd9inM5H.d.mts} +1 -1
- package/dist/formatDateTime.d.mts +1 -1
- package/dist/helpers-D8_2I4ZX.d.mts +90 -0
- package/dist/helpers.d.mts +2 -90
- package/dist/{i18n-CeRarJIa.mjs → i18n-BscB9FUy.mjs} +14 -2
- package/dist/i18n-BscB9FUy.mjs.map +1 -0
- package/dist/{index-C7hEdRqK.d.mts → index-DkXly4xw.d.mts} +2 -2
- package/dist/{index-DxFh2ArY.d.mts → index-DsjvDLF8.d.mts} +3 -3
- package/dist/{index-B7KIL3U6.d.mts → index-EGvEhP1j.d.mts} +2 -2
- package/dist/index-K614ZhWK.d.mts +1 -0
- package/dist/index-NKYLt_R9.d.mts +1 -0
- package/dist/index-VWno75SQ.d.mts +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index2.d.mts +1 -1
- package/dist/index3.d.mts +3 -3
- package/dist/index4.d.mts +1 -1
- package/dist/index5.d.mts +14 -14
- package/dist/{input-DMPo8gRT.d.mts → input-CKhARTlS.d.mts} +3 -3
- package/dist/{inputFields-BCNC1FWx.d.mts → inputFields-DyOZHse2.d.mts} +11 -11
- package/dist/inputFields.d.mts +1 -1
- package/dist/{intersperse-B8s6clcc.mjs → intersperse-ObkRVOag.mjs} +1 -1
- package/dist/{intersperse-B8s6clcc.mjs.map → intersperse-ObkRVOag.mjs.map} +1 -1
- package/dist/{jsonSchema-6mcLrVG3.d.mts → jsonSchema-COo0XQLA.d.mts} +1 -1
- package/dist/lib/PDSProvider.d.mts +3 -3
- package/dist/lib/PDSProvider.mjs +1 -1
- package/dist/lib/TruncatedText.d.mts +1 -1
- package/dist/lib/TruncatedTextWithTooltip.d.mts +1 -1
- package/dist/lib/TruncatedTextWithTooltip.mjs +1 -1
- package/dist/lib/chainTypes.d.mts +1 -1
- package/dist/lib/color.d.mts +1 -1
- package/dist/lib/customFunctionSchema.d.mts +1 -1
- package/dist/lib/date-filter/index.d.mts +2 -2
- package/dist/lib/date-filter/index.mjs +1 -1
- package/dist/lib/i18n/index.d.mts +3 -3
- package/dist/lib/i18n/index.mjs +1 -1
- package/dist/lib/jsonSchema.d.mts +1 -1
- package/dist/lib/jsonSchemaType.d.mts +1 -1
- package/dist/lib/message.d.mts +1 -1
- package/dist/lib/methodChain.d.mts +2 -2
- package/dist/lib/methodChainNormalize.d.mts +2 -2
- package/dist/lib/methodChainTypes.d.mts +1 -1
- package/dist/lib/objectSchemaTypes.d.mts +1 -1
- package/dist/lib/platformObject.d.mts +1 -1
- package/dist/lib/pseudoClass.d.mts +1 -1
- package/dist/lib/router/adapters/reactRouter.d.mts +1 -1
- package/dist/lib/router/adapters/tanstack.d.mts +1 -1
- package/dist/lib/router/index.d.mts +5 -5
- package/dist/lib/schemaOptions.d.mts +1 -1
- package/dist/lib/semanticColor.d.mts +1 -1
- package/dist/lib/useChain.d.mts +1 -1
- package/dist/{listbox-options-yLjqZp4H.d.mts → listbox-options-D-DyLUdi.d.mts} +3 -3
- package/dist/listbox-options.d.mts +1 -1
- package/dist/{message-C5n7wFiN.d.mts → message-Dti22dmx.d.mts} +1 -1
- package/dist/{methodChain-BNDytoaD.d.mts → methodChain-BAUFBbR9.d.mts} +4 -4
- package/dist/{methodChainTypes-BuwpPC73.d.mts → methodChainTypes-a7kHYhs7.d.mts} +2 -2
- package/dist/mixins/focus.d.mts +1 -1
- package/dist/mixins/focus.mjs +1 -1
- package/dist/mixins/hoverable.d.mts +2 -2
- package/dist/mixins/hoverable.mjs +1 -1
- package/dist/mixins/input.d.mts +1 -1
- package/dist/mixins/input.mjs +2 -2
- package/dist/mixins/menuItem.d.mts +2 -2
- package/dist/mixins/scrollbar.d.mts +1 -1
- package/dist/mixins/text.d.mts +1 -1
- package/dist/{operators-C34nhBuK.d.mts → operators-DjQXVNVI.d.mts} +3 -3
- package/dist/operators.d.mts +1 -1
- package/dist/{palette-BCszfY7I.d.mts → palette-Bp5G-S_5.d.mts} +3 -3
- package/dist/palette.d.mts +1 -1
- package/dist/patterns/CardGrouping/index.mjs +8 -8
- package/dist/patterns/IndexTableLayout/index.d.mts +3 -0
- package/dist/patterns/IndexTableLayout/index.mjs +87 -0
- package/dist/patterns/IndexTableLayout/index.mjs.map +1 -0
- package/dist/patterns/LayoutLoadingShimmer/index.mjs +3 -3
- package/dist/patterns/PageLayout/index.d.mts +4 -4
- package/dist/patterns/PageLayout/index.mjs +1 -1
- package/dist/patterns/WizardModal/index.mjs +3 -3
- package/dist/reactRouterFallback.d.mts +1 -1
- package/dist/relative-date-label.d.mts +1 -1
- package/dist/safe-parse.d.mts +1 -1
- package/dist/{schemaOptions-DBOUChxi.d.mts → schemaOptions-D536qhSd.d.mts} +3 -3
- package/dist/{semantic-Duoh2Pxp.d.mts → semantic-DjKvtUi8.d.mts} +1 -1
- package/dist/{semanticColor-BuG977_M.d.mts → semanticColor-CmGmGRj8.d.mts} +3 -3
- package/dist/{strings-CUZrwL-Q.d.mts → strings-FWNWdSn1.d.mts} +14 -2
- package/dist/strings.d.mts +1 -1
- package/dist/{text-B7hx6G99.d.mts → text-BNfECpa5.d.mts} +1 -1
- package/dist/{theme-BKg55Zk1.d.mts → theme-VNhXxAF3.d.mts} +3 -3
- package/dist/theme.d.mts +1 -1
- package/dist/tone.d.mts +3 -3
- package/dist/tree.d.mts +1 -1
- package/dist/{types-DEzlAdZW.d.mts → types-BMpEizJP.d.mts} +2 -2
- package/dist/{types-C_ZEgHNa.d.mts → types-BhHdS6QP.d.mts} +2 -2
- package/dist/{types-6QeQmbFm.d.mts → types-CFe4tA8Q.d.mts} +1 -1
- package/dist/types-CjQzH0MM.d.mts +180 -0
- package/dist/{types-CEQWndtF.d.mts → types-DFU6M0OL.d.mts} +4 -4
- package/dist/{types-BjMJFNYH.d.mts → types-DHTFd-5t.d.mts} +1 -1
- package/dist/{types-VgGkS4JB.d.mts → types-DfpVVjso.d.mts} +2 -2
- package/dist/types-Dx8PgO8a.d.mts +95 -0
- package/dist/{types-CgKSEQyB.d.mts → types-HxiGiwQN.d.mts} +1 -1
- package/dist/{types-4wnr5R9P.d.mts → types-Kmnood9Y.d.mts} +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types2.d.mts +2 -2
- package/dist/types3.d.mts +1 -1
- package/dist/types4.d.mts +2 -2
- package/dist/types5.d.mts +2 -2
- package/dist/types6.d.mts +2 -2
- package/dist/types7.d.mts +1 -1
- package/dist/{url-state-B_gTQ9uu.d.mts → url-state-D1muieS7.d.mts} +2 -2
- package/dist/url-state.d.mts +1 -1
- package/dist/{useChain-DPRVMwX8.d.mts → useChain-D5LvupTW.d.mts} +6 -6
- package/dist/useChainAtCursor.d.mts +6 -6
- package/dist/useCodeChainFunctionPanel.d.mts +1 -1
- package/dist/useColumnConfiguration.d.mts +34 -0
- package/dist/useComboboxFooterAction.d.mts +1 -1
- package/dist/{useFilterStateV2-BQZppUR0.d.mts → useFilterStateV2-MH3zbQFr.d.mts} +3 -3
- package/dist/useFilterStateV2.d.mts +1 -1
- package/dist/{useFormField-DAwApAKK.d.mts → useFormField-Ba8rh1CH.d.mts} +2 -2
- package/dist/{useFormField-BAmkdxtA.mjs → useFormField-CbNYbDdp.mjs} +2 -2
- package/dist/{useFormField-BAmkdxtA.mjs.map → useFormField-CbNYbDdp.mjs.map} +1 -1
- package/dist/useFormField.d.mts +1 -1
- package/dist/{useFormGroup-BZayb9fZ.mjs → useFormGroup-CsKC93Pt.mjs} +1 -1
- package/dist/{useFormGroup-BZayb9fZ.mjs.map → useFormGroup-CsKC93Pt.mjs.map} +1 -1
- package/dist/{useLocationPathname-BHL0pgiu.d.mts → useLocationPathname-OsvI7mH5.d.mts} +1 -1
- package/dist/useLocationPathname.d.mts +1 -1
- package/dist/{useTableBoxDragAndDrop-Dq30b6yY.d.mts → useTableBoxDragAndDrop-CKPIY98e.d.mts} +1 -1
- package/dist/useTableBoxDragAndDrop.d.mts +1 -1
- package/dist/useTableColumns-rLskKJhd.d.mts +72 -0
- package/dist/useTableColumns.d.mts +2 -72
- package/dist/useTruncation.d.mts +1 -1
- package/dist/{utilities-B2ry7_20.d.mts → utilities-BrEUGFGq.d.mts} +1 -1
- package/dist/utilities.d.mts +1 -1
- package/dist/utils/testing.d.mts +1 -1
- package/dist/utils.d.mts +1 -1
- package/dist/utils4.d.mts +5 -5
- package/dist/{validation-BODkbEvr.d.mts → validation-Csi2SJxm.d.mts} +3 -3
- package/dist/validation.d.mts +1 -1
- package/dist/validation2.d.mts +4 -4
- package/dist/{value-control-resolver-BcZiReQ7.d.mts → value-control-resolver-BoBFvQ_0.d.mts} +2 -2
- package/dist/value-control-resolver.d.mts +1 -1
- package/dist/variables/effect.d.mts +1 -1
- package/dist/variables/semantic.d.mts +1 -1
- package/llms.txt +6 -2
- package/package.json +5 -3
- package/skills/ui-authoring/COMPONENTS.md +1 -0
- package/skills/ui-authoring/PATTERNS.md +4 -2
- package/skills/ui-authoring/SKILL.md +9 -2
- package/skills/ui-authoring/TOKENS.md +457 -119
- package/dist/Combobox-CsXnJKvB.mjs.map +0 -1
- package/dist/DatePicker-DQHVCGnP.mjs.map +0 -1
- package/dist/Modal-Cs5cZpEr.mjs.map +0 -1
- package/dist/TableControls-C1MF2JvY.mjs.map +0 -1
- package/dist/components/DataTable/index.mjs.map +0 -1
- package/dist/i18n-CeRarJIa.mjs.map +0 -1
- package/dist/types-CwzwClJx.d.mts +0 -27
- /package/dist/{index-7in8TPrM.d.mts → index-AnhM47-e2.d.mts} +0 -0
- /package/dist/{index-8SLBz2NH.d.mts → index-B33elXxm.d.mts} +0 -0
- /package/dist/{index-B24gUwOx.d.mts → index-B4woaFSm.d.mts} +0 -0
- /package/dist/{index-B8M0Grl_2.d.mts → index-B6T7ov8p.d.mts} +0 -0
- /package/dist/{index-BFnNtGdX.d.mts → index-BNRXMhlr.d.mts} +0 -0
- /package/dist/{index-BjgW3E7y.d.mts → index-BOaE2xDE.d.mts} +0 -0
- /package/dist/{index-BwFl_eS0.d.mts → index-BPiqSRRl.d.mts} +0 -0
- /package/dist/{index-C3kE54DD.d.mts → index-BYd3Btr1.d.mts} +0 -0
- /package/dist/{index-C3usUse7.d.mts → index-BcsXXrHq.d.mts} +0 -0
- /package/dist/{index-C6HcjJiY.d.mts → index-Bo9LXG4r.d.mts} +0 -0
- /package/dist/{index-CP2eJYlK.d.mts → index-BrGZHEgX.d.mts} +0 -0
- /package/dist/{index-CSf15oCd.d.mts → index-Bt4QNofW.d.mts} +0 -0
- /package/dist/{index-CX869wwk.d.mts → index-CFuHCx9T.d.mts} +0 -0
- /package/dist/{index-CXaDbCtw.d.mts → index-CLTQPxoD.d.mts} +0 -0
- /package/dist/{index-D4DUvwPf.d.mts → index-CaqYCRmZ.d.mts} +0 -0
- /package/dist/{index-DB7t8whN.d.mts → index-CjDodOH2.d.mts} +0 -0
- /package/dist/{index-Deol7ZWO.d.mts → index-CjmAoxrR2.d.mts} +0 -0
- /package/dist/{index-DhiymMxa.d.mts → index-Cx0vQ6ld.d.mts} +0 -0
- /package/dist/{index-DjOaHFU3.d.mts → index-CzItj62a.d.mts} +0 -0
- /package/dist/{index-DkrC-i1D.d.mts → index-CzUpNo0e.d.mts} +0 -0
- /package/dist/{index-DvwPIy8X.d.mts → index-DBGd4WeR.d.mts} +0 -0
- /package/dist/{index-Oio5ygqN.d.mts → index-DMRtRo7y.d.mts} +0 -0
- /package/dist/{index-Wc1llEvP.d.mts → index-DNjQe1D8.d.mts} +0 -0
- /package/dist/{index-bHnO4ZKt.d.mts → index-DW3xeuzq.d.mts} +0 -0
- /package/dist/{index-dzI_9J-Z.d.mts → index-DZlqSwCF.d.mts} +0 -0
- /package/dist/{index-gpCH5158.d.mts → index-De7MV8-j.d.mts} +0 -0
- /package/dist/{index-lIMqGGJz.d.mts → index-DjG1RCY5.d.mts} +0 -0
- /package/dist/{index-luywJTzJ.d.mts → index-Dlcv6Ku22.d.mts} +0 -0
- /package/dist/{index-sViox9YW.d.mts → index-DrK1_jKY.d.mts} +0 -0
- /package/dist/{index-xAZnxq0d2.d.mts → index-IJ_PXwxI2.d.mts} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TableControls-C1MF2JvY.mjs","names":["Label","Input","SmallSearchIcon","Input","Popover","LockedIcon","Modal","DragIcon","PopoverCard","Card","Popover","Label","Spacer","TIME_COMPONENT","Input","Card","DropdownMenu","MoreIcon","SmallPlusIcon","Input","DATE_ONLY","parseIsoDate","Input","Input","Input","DismissButton","CaretDownIcon","CaretDownIcon16","XIcon","XIcon16","DropdownMenu","CaretDownIcon","CaretDownIcon16","CircleInfoIcon","CircleInfoIcon16","Popover","uuid"],"sources":["../components/DataTable/FormControlLabel/FormControlLabel.ts","../components/DataTable/SearchInput/SearchInput.tsx","../components/DataTable/TableControls/CompactBar.tsx","../components/DataTable/TableControls/utils/positioning.ts","../components/DataTable/TableControls/ControlBar.tsx","../components/DataTable/TableControls/TableControls.tsx","../components/DataTable/dnd/StyledIconDrag.tsx","../components/DataTable/dnd/utils.ts","../components/DataTable/TableControls/TableViewConfigurationDropdown.tsx","../components/DataTable/TableControls/TableControlsContext.ts","../components/DataTable/TableControls/FiltersV2/date-rule-intent.ts","../components/DataTable/TableControls/FiltersV2/operators.ts","../components/DataTable/TableControls/FiltersV2/date-range-rule-value.ts","../components/DataTable/TableControls/FiltersV2/format-date-value.ts","../components/DataTable/TableControls/FiltersV2/relative-date-label.ts","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/display.ts","../components/DataTable/TableControls/FiltersV2/fieldPickerOptions.ts","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/RuleEditorFields.tsx","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRuleRow.tsx","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/compound-expression.ts","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/use-rules-popover-selection.ts","../components/DataTable/TableControls/FiltersV2/filter-size-context.ts","../components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRulesPopover.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/ArrayValueControl/ArrayValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/BooleanValueControl/BooleanValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/ChoicesValueControl/ChoicesValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/DateRangeValueControl/DateRangeValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/DateValueControl/DateValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/utils.ts","../components/DataTable/TableControls/FiltersV2/value-controls/FloatValueControl/FloatValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/IntegerValueControl/IntegerValueControl.tsx","../components/DataTable/TableControls/FiltersV2/value-controls/StringValueControl/StringValueControl.tsx","../components/DataTable/TableControls/FiltersV2/FilterBar/value-control-resolver.tsx","../components/DataTable/TableControls/FiltersV2/FilterPickerMenu/FilterPickerMenu.tsx","../components/DataTable/TableControls/FiltersV2/PillShell/PillShell.tsx","../components/DataTable/TableControls/FiltersV2/FilterPill/FilterPill.tsx","../components/DataTable/TableControls/FiltersV2/FilterPopover/FilterPopover.tsx","../components/DataTable/TableControls/FiltersV2/RulesPill/RulesPill.tsx","../components/DataTable/TableControls/FiltersV2/types.ts","../components/DataTable/TableControls/FiltersV2/validation.ts","../components/DataTable/TableControls/FiltersV2/useFilterStateV2.ts","../components/DataTable/TableControls/FiltersV2/FilterBar/FilterBar.tsx","../components/DataTable/TableControls/FiltersV2/FilterBar/index.ts","../components/DataTable/TableControls/FiltersV2/FieldRegistry.ts","../components/DataTable/TableControls/FiltersV2/url-state.ts"],"sourcesContent":["import styled, { css } from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport { Label } from 'design-system/components/Text';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\nconst FormControlLabel = styled(Label).attrs(() => ({ size: 'md', weight: 'bold' }))<{\n isDisabled?: boolean;\n}>`\n margin-bottom: ${Spacing[2]};\n transition: ${TransitionDuration.Fast};\n display: inline-block;\n\n ${({ theme, isDisabled }) => css`\n color: ${\n isDisabled\n ? semanticColor(theme, 'FgDisabled', theme.color.text.disabled)\n : semanticColor(theme, 'FgPrimary', theme.color.text.primary)\n };\n `}\n`;\n\nexport default FormControlLabel;\n","import { noop } from 'lodash-es';\nimport {\n type ChangeEvent,\n type FocusEventHandler,\n type PointerEvent as ReactPointerEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { SearchIcon } from '@persona/icons';\nimport { SearchIcon as SmallSearchIcon } from '@persona/icons/12px';\nimport FormControlLabel from 'design-system/components/DataTable/FormControlLabel/FormControlLabel';\nimport Input, { InputGroup } from 'design-system/components/Input';\nimport Tooltip from 'design-system/components/Tooltip';\nimport {\n isActive,\n isDisabled,\n isFocused,\n isHovered,\n isNotDisabled,\n} from 'design-system/lib/pseudoClass';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport type { InputSizes } from 'design-system/mixins/input';\n\n/**\n * Matches the delay Tooltip applies to its own hover handling, which the cursor anchor bypasses by\n * controlling `open`.\n */\nconst TOOLTIP_DELAY_MS = 300;\n\nconst SearchBar = styled.div`\n position: relative;\n`;\n\n/**\n * Zero-size anchor that gets moved to the pointer, so the disabled tooltip surfaces next to the\n * cursor rather than in the middle of a search bar that can span the full width of the table.\n */\nconst CursorAnchor = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n pointer-events: none;\n`;\n\ninterface StyledInputProps {\n flattenDisplay: boolean;\n}\n\nconst StyledInput = styled(Input)<StyledInputProps>`\n &&,\n &&${isHovered}${isNotDisabled},\n &&${isDisabled} {\n background: transparent;\n }\n\n ${({ theme, flattenDisplay }) =>\n flattenDisplay &&\n css`\n border-width: 0px;\n\n &${isActive}, &${isFocused}, &${isHovered}&${isNotDisabled}, &${isHovered}&${isFocused} {\n border-color: ${semanticColor(theme, 'BorderDefault', theme.color.border.input)};\n box-shadow: none;\n }\n `}\n`;\n\nexport interface OmniSearchProps {\n className?: string;\n title?: ReactNode;\n handleInput: (value: string) => void;\n id?: string;\n value: string;\n placeholder: string;\n dataTest?: string;\n autoFocus?: boolean;\n useClearIcon?: boolean;\n leftIcon?: ReactNode;\n handleOnFocus?: () => void;\n onBlur?: FocusEventHandler<HTMLInputElement>;\n disabled?: boolean;\n disabledTooltip?: string;\n /**\n * Anchor the disabled tooltip to the cursor instead of centering it over the bar. Opt-in for the\n * index-table search bars, which can span the full table width; elsewhere the centered default\n * reads fine.\n */\n anchorTooltipToCursor?: boolean;\n flattenDisplay?: boolean;\n size?: InputSizes;\n maxLength?: number;\n}\n\nconst SearchInput = ({\n className,\n title = 'Search',\n handleInput,\n handleOnFocus = noop,\n onBlur = noop,\n id,\n value,\n placeholder,\n dataTest,\n autoFocus,\n useClearIcon = false,\n disabled = false,\n disabledTooltip,\n anchorTooltipToCursor = false,\n size = 'md',\n leftIcon = size === 'sm' ? <SmallSearchIcon /> : <SearchIcon />,\n flattenDisplay = false,\n maxLength,\n}: OmniSearchProps) => {\n // We duplicate state and track it separately here. This allows us to:\n // 1. immediately update the <input/> value\n // 2. do a debounced update of the actual state\n // We expect the callback passed to this input to be a debounced that updates\n // props.value.\n const [innerValue, setInnerValue] = useState<string>(value);\n\n // Strings this input has emitted through handleInput but not yet seen echoed\n // back through `value`. `handleInput` is expected to be debounced upstream,\n // so commits land one debounce behind the user's keystrokes — a `value` that\n // matches a pending emission is our own text arriving late and must not\n // overwrite newer in-flight input.\n const pendingEmissionsRef = useRef<string[]>([]);\n const emit = useCallback(\n (next: string) => {\n pendingEmissionsRef.current.push(next);\n handleInput(next);\n },\n [handleInput],\n );\n\n const handleChange = useCallback(\n ({ target }: ChangeEvent<HTMLInputElement>): void => {\n setInnerValue(target.value);\n emit(target.value);\n },\n [emit, setInnerValue],\n );\n\n useEffect(() => {\n const pending = pendingEmissionsRef.current;\n\n // Acknowledge the LAST matching emission: upstream commits correspond to\n // the most recent occurrence of a repeated value (type `ab`, backspace to\n // `a` → pending `['a', 'ab', 'a']` → the `a` commit retires all three), so\n // superseded duplicates can't linger and suppress later external updates.\n // A match that isn't the newest emission is our own stale text arriving\n // late — skip it so it can't clobber newer in-flight input. Entries are\n // retained until acknowledged: an emission equal to the committed `value`\n // can still be in flight upstream (committed before the user reverted,\n // prop update delayed), so emissions are never inferred cancelled.\n const pendingIndex = pending.lastIndexOf(value);\n if (pendingIndex >= 0 && pendingIndex < pending.length - 1) {\n pending.splice(0, pendingIndex + 1);\n return;\n }\n // External change — or our newest emission echoing back, which is never\n // stale: innerValue should already equal `value`, and adopting it\n // restores the user's latest text if a stale sync ever clobbered it.\n pending.length = 0;\n setInnerValue(value);\n }, [value]);\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleClear = useCallback(() => {\n setInnerValue('');\n emit('');\n handleOnFocus();\n inputRef.current?.focus();\n }, [emit, handleOnFocus, inputRef, setInnerValue]);\n\n const canClear = useClearIcon && !!innerValue;\n\n const showDisabledTooltip = disabled && !!disabledTooltip;\n const showCursorAnchoredTooltip = showDisabledTooltip && anchorTooltipToCursor;\n\n const searchBarRef = useRef<HTMLDivElement>(null);\n const cursorAnchorRef = useRef<HTMLDivElement>(null);\n const tooltipDelayRef = useRef<ReturnType<typeof setTimeout>>();\n const [isTooltipOpen, setIsTooltipOpen] = useState(false);\n\n useEffect(() => {\n // Without this the tooltip would reappear, unhovered and at a stale position, whenever the\n // input goes back to being disabled.\n if (!showCursorAnchoredTooltip) {\n clearTimeout(tooltipDelayRef.current);\n tooltipDelayRef.current = undefined;\n setIsTooltipOpen(false);\n }\n\n return () => clearTimeout(tooltipDelayRef.current);\n }, [showCursorAnchoredTooltip]);\n\n const handlePointerMove = useCallback((event: ReactPointerEvent<HTMLDivElement>) => {\n const searchBarElement = searchBarRef.current;\n const cursorAnchor = cursorAnchorRef.current;\n\n // The anchor only exists alongside a disabled tooltip, so this is a no-op otherwise. Touch\n // input is ignored to match how Tooltip's own trigger treats it.\n if (!searchBarElement || !cursorAnchor || event.pointerType === 'touch') {\n return;\n }\n\n const { left, top } = searchBarElement.getBoundingClientRect();\n const offsetX = event.clientX - left;\n const offsetY = event.clientY - top;\n\n // Written straight to the node to keep pointer tracking off the render path; the tooltip\n // re-reads the anchor every frame because of `updatePositionStrategy`.\n cursorAnchor.style.transform = `translate(${offsetX}px, ${offsetY}px)`;\n\n tooltipDelayRef.current ??= setTimeout(() => setIsTooltipOpen(true), TOOLTIP_DELAY_MS);\n }, []);\n\n const handlePointerLeave = useCallback(() => {\n clearTimeout(tooltipDelayRef.current);\n tooltipDelayRef.current = undefined;\n setIsTooltipOpen(false);\n }, []);\n\n const searchBar = (\n <SearchBar\n ref={searchBarRef}\n className={className}\n data-test={dataTest}\n onPointerMove={showCursorAnchoredTooltip ? handlePointerMove : undefined}\n onPointerLeave={showCursorAnchoredTooltip ? handlePointerLeave : undefined}\n >\n {title != null && <FormControlLabel htmlFor={id}>{title}</FormControlLabel>}\n <InputGroup\n leftIcon={leftIcon}\n onClear={\n canClear\n ? (e) => {\n e.preventDefault();\n e.stopPropagation();\n handleClear();\n }\n : undefined\n }\n size={size}\n >\n <StyledInput\n id={id}\n onChange={handleChange}\n placeholder={placeholder}\n value={innerValue}\n autoFocus={autoFocus}\n ref={inputRef}\n onFocus={handleOnFocus}\n onBlur={onBlur}\n disabled={disabled}\n maxLength={maxLength}\n flattenDisplay={flattenDisplay}\n />\n </InputGroup>\n\n {/*\n The disabled <input> doesn't emit hover events, but the SearchBar wrapper does, so a\n cursor-following anchor surfaces the reason the search is unavailable without taking up\n layout room.\n */}\n {showCursorAnchoredTooltip && (\n <Tooltip\n trigger={<CursorAnchor ref={cursorAnchorRef} data-test='search-input__cursor-anchor' />}\n open={isTooltipOpen}\n side='top'\n updatePositionStrategy='always'\n >\n {disabledTooltip}\n </Tooltip>\n )}\n </SearchBar>\n );\n\n // When not anchoring to the cursor, fall back to a plain tooltip centered over the whole bar.\n if (showDisabledTooltip && !anchorTooltipToCursor) {\n return (\n <Tooltip trigger={searchBar} side='top'>\n {disabledTooltip}\n </Tooltip>\n );\n }\n\n return searchBar;\n};\n\nexport default SearchInput;\n","import { useState } from 'react';\nimport styled from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport { FilterIcon, SearchIcon } from '@persona/icons';\nimport Button from 'design-system/components/Button';\nimport SearchInput from 'design-system/components/DataTable/SearchInput';\nimport { HStack } from 'design-system/components/Stack';\nimport { Paragraph } from 'design-system/components/Text';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nimport type { ControlBarProps } from './ControlBar';\n\nexport const DataTableCompactBar = styled(HStack)`\n border-bottom: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', theme.color.border.secondary)};\n padding-bottom: ${Spacing[1]};\n`;\n\nconst CompactSearchInput = styled(SearchInput)<{ $autoExpand: boolean }>`\n width: ${({ $autoExpand }) => ($autoExpand ? '100%' : '240px')};\n margin-right: ${Spacing[1]};\n`;\n\ntype CompactBarProps = Pick<\n ControlBarProps,\n | 'title'\n | 'searchProps'\n | 'showFilters'\n | 'setShowFilters'\n | 'filtersId'\n | 'isLoading'\n | 'isFilterPanelLoading'\n | 'propertiesButton'\n | 'tableActions'\n | 'data-tour-target'\n | 'filterPanel'\n>;\n\n/**\n * Compact variant of the ControlBar.\n * Not intended to be used by itself.\n *\n * Tested using the ControlBar specs.\n *\n * @see ControlBar.tsx\n * @see ControlBar.spec.tsx\n */\nconst CompactBar: React.FC<CompactBarProps> = ({\n title,\n searchProps,\n showFilters,\n setShowFilters,\n filtersId,\n isLoading,\n isFilterPanelLoading,\n propertiesButton,\n tableActions,\n 'data-tour-target': dataTourTarget,\n filterPanel,\n}) => {\n const strings = usePDSStrings();\n const autoExpandSearch = !title;\n const [showSearch, setShowSearch] = useState<boolean>(autoExpandSearch);\n\n return (\n <>\n <DataTableCompactBar data-tour-target={dataTourTarget} justify='space-between' align='center'>\n {title && (\n <Paragraph size='md' weight='bold' color='primary'>\n {title}\n </Paragraph>\n )}\n\n <HStack\n spacing={Spacing[1]}\n align='center'\n justify='right'\n style={autoExpandSearch ? { width: '100%' } : { marginLeft: 'auto' }}\n >\n <HStack spacing={Spacing[1]} align='center' style={{ width: '100%' }}>\n {searchProps &&\n (showSearch ? (\n <CompactSearchInput\n title={null}\n size='sm'\n $autoExpand={autoExpandSearch}\n autoFocus={!autoExpandSearch}\n onBlur={\n autoExpandSearch\n ? undefined\n : () => {\n if (!searchProps.value) {\n setShowSearch(false);\n }\n }\n }\n useClearIcon\n {...searchProps}\n />\n ) : (\n <Button\n id='table-controls__compact-search-toggle'\n variant='text'\n width='icon'\n size='sm'\n aria-label={strings.showSearchBar}\n onClick={() => setShowSearch(true)}\n >\n <SearchIcon />\n </Button>\n ))}\n\n {setShowFilters && (\n <Button\n id='table-controls__view-tab-filters'\n variant='text'\n onClick={() => setShowFilters?.(!showFilters)}\n aria-label={showFilters ? strings.hideFilters : strings.showFilters}\n aria-expanded={showFilters}\n aria-controls={filtersId}\n disabled={isLoading || isFilterPanelLoading}\n isPending={isFilterPanelLoading}\n active={showFilters}\n width='icon'\n size='sm'\n >\n <FilterIcon />\n </Button>\n )}\n\n {propertiesButton}\n </HStack>\n\n {tableActions && Array.isArray(tableActions)\n ? tableActions.map((action) => (\n <Button\n id={`table-controls__compact-action-${action.label.toLowerCase().replace(/\\s+/g, '-')}`}\n key={action.label}\n variant='basic'\n size='sm'\n width='auto'\n onClick={action.onClick}\n >\n {action.label}\n </Button>\n ))\n : tableActions}\n </HStack>\n </DataTableCompactBar>\n {showFilters && filterPanel}\n </>\n );\n};\n\nexport default CompactBar;\n","/**\n * Check if a child rect is contained within a parent rect.\n * @param parent - The parent rect.\n * @param child - The child rect.\n * @returns True if the child rect is contained within the parent rect, false otherwise.\n */\nexport const rectContainsRect = (parent: DOMRect, child: DOMRect) => {\n return (\n child.top >= parent.top &&\n child.bottom <= parent.bottom &&\n child.left >= parent.left &&\n child.right <= parent.right\n );\n};\n","import {\n closestCenter,\n DndContext,\n pointerWithin,\n type CollisionDetection,\n type DragEndEvent,\n type Modifier,\n PointerSensor,\n useSensor,\n useSensors,\n} from '@dnd-kit/core';\nimport { horizontalListSortingStrategy, SortableContext, useSortable } from '@dnd-kit/sortable';\nimport { mergeRefs } from '@react-aria/utils';\nimport {\n type ComponentProps,\n type CSSProperties,\n type FC,\n forwardRef,\n type Ref,\n type SyntheticEvent,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport styled, { createGlobalStyle } from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport {\n CirclePlusIcon,\n CopyIcon,\n EyeIcon,\n EyeOffIcon,\n FilterIcon,\n MoreIcon,\n RotateCcwIcon,\n SaveIcon,\n StarIcon,\n TrashIcon,\n XIcon,\n} from '@persona/icons';\nimport { LockedIcon } from '@persona/icons/12px';\nimport Button, { IconButton } from 'design-system/components/Button';\nimport SearchInput, { type OmniSearchProps } from 'design-system/components/DataTable/SearchInput';\nimport Input from 'design-system/components/Input';\nimport { MenuItem, MenuList } from 'design-system/components/Menu';\nimport Modal from 'design-system/components/Modal';\nimport Popover from 'design-system/components/Popover';\nimport Stack, { HStack } from 'design-system/components/Stack';\nimport TabBar, { StyledTab, Tab } from 'design-system/components/TabBar';\nimport { Paragraph } from 'design-system/components/Text';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { isDisabled, isHovered, isNotDisabled } from 'design-system/lib/pseudoClass';\nimport { moveItemByIndex } from 'design-system/lib/reorderItems';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport { semanticScrollbar } from 'design-system/mixins/scrollbar';\n\nimport CompactBar from './CompactBar';\nimport { rectContainsRect } from './utils/positioning';\n\nconst TAB_ID_PREFIX = 'table-controls__view-tab_';\nconst OVERFLOW_TAB_ID_PREFIX = 'table-controls__view-tab-overflow_';\nconst ADD_VIEW_BUTTON_ID = 'table-controls__view-tab-new';\n// A few px of \"10 more…\" vs \"11 more…\" can re-wrap a tab and flip the count back forever.\nconst OVERFLOW_WIDTH_SHRINK_THRESHOLD = 16;\nconst OVERFLOW_GAP = 8;\n\nfunction enterProxiesClick(e: React.KeyboardEvent<HTMLDivElement>) {\n if (e.key === 'Enter') {\n e.target.dispatchEvent(new Event('click', { bubbles: true }));\n }\n}\n\ninterface TableViewConfig {\n id: string;\n name: string;\n /**\n * Whether this view is currently marked as the default view. Used to toggle the\n * \"Set as default\"/\"Already the default\" menu item label when `onSetDefaultView` is provided.\n */\n isDefault?: boolean;\n}\n\ninterface EventHandlers {\n /**\n * Called when the duplicate view button is clicked. If not provided, the duplicate view button will not be displayed.\n *\n * @returns Promise<{ id: string }> - The id of the newly created view\n */\n onDuplicateView?: (viewId: string) => Promise<{ id: string } | void>;\n /**\n * Called when the delete view button is clicked. If not provided, the delete view button will not be displayed.\n */\n onDeleteView?: (viewId: string) => Promise<void>;\n /**\n * Called when a view tab is selected\n */\n onSelectView?: (viewId: string | null) => void;\n /**\n * Called when the reset view button is clicked. If not provided, the reset view button will not be displayed.\n */\n onResetCurrentView?: () => void;\n /**\n * Called when the save view button is clicked. If not provided, the save view button will not be displayed.\n */\n onSaveView?: () => Promise<void>;\n /**\n * Called when the \"Set as default\" menu item is clicked. If not provided, the menu item\n * will not be displayed.\n */\n onSetDefaultView?: (viewId: string) => Promise<void>;\n /**\n * Called when the add view button is clicked. If not provided, the add view button will not be displayed.\n *\n * @returns Promise<{ id: string }> - The id of the newly created view\n */\n onAddView?: () => Promise<{ id: string } | void>;\n /**\n * Called when the view name is changed. If not provided, the view name will not be editable.\n */\n onViewNameChange?: (viewId: string, name: string) => void;\n /**\n * Called with every view id in its new order when the user drags a tab or opens a view from the\n * overflow menu, which moves it to the front. If not provided, tabs cannot be reordered.\n */\n onReorderViews?: (viewIds: string[]) => void;\n /**\n * Called when the user hides a view from the tab bar or shows it again. If not provided, views\n * cannot be hidden.\n */\n onViewHiddenChange?: (viewId: string, hidden: boolean) => void;\n /**\n * Called when the selection is cleared\n */\n onClearSelection?: () => void;\n}\n\nexport interface ControlBarProps extends EventHandlers {\n /**\n * Preset views that are not editable by the user.\n */\n presetViews?: TableViewConfig[];\n /**\n * Table view tabs\n */\n views?: TableViewConfig[];\n /**\n * Ids of views hidden from the tab bar. Hidden views are listed in the overflow menu; opening one\n * shows it again.\n */\n hiddenViewIds?: string[];\n /**\n * Current table view id\n */\n currentView?: string | null;\n /**\n * Whether the filters have been changed and can be saved\n */\n isViewDirty?: boolean;\n /**\n * Whether the user has permission to edit views\n */\n canEditViews?: boolean;\n /**\n * Whether to show filters\n */\n showFilters?: boolean;\n /**\n * Called when the filters are toggled\n */\n setShowFilters?: (show: boolean) => void;\n /**\n * Search props\n */\n searchProps?: Omit<OmniSearchProps, 'size'>;\n /**\n * The id of the filters container\n */\n filtersId?: string;\n /**\n * Properties button\n */\n propertiesButton?: React.ReactNode;\n /**\n * Table actions\n */\n tableActions?:\n | React.ReactNode\n | { label: string; onClick: React.MouseEventHandler<HTMLButtonElement> }[];\n /**\n * Whether the table is loading\n */\n isLoading?: boolean;\n /**\n * Renders the filter toggle disabled with a pending spinner, e.g. while the filter panel's\n * schema loads. The toggle renders even when `filterPanel` is not yet available.\n */\n isFilterPanelLoading?: boolean;\n /**\n * Whether to show the views bar\n */\n showViews?: boolean;\n /**\n * The ids of the selected rows\n */\n selectedRows?: string[];\n /**\n * Bulk actions to display when there are selected rows.\n */\n bulkActions?: (\n | {\n label: string;\n icon?: React.ReactNode;\n disabled?: boolean;\n onClick: (selectedRows: string[], clearSelection: () => void) => void | Promise<void>;\n }\n | {\n 'aria-label': string;\n icon: React.ReactNode;\n disabled?: boolean;\n onClick: (selectedRows: string[], clearSelection: () => void) => void | Promise<void>;\n }\n )[];\n /**\n * The title of the table\n */\n title?: string;\n /**\n * The data-tour-target of the table\n */\n 'data-tour-target'?: string;\n /**\n * Whether to use compact spacing and styling.\n * The compact variant does not support views.\n */\n compact?: boolean;\n\n /** Use this to handle errors that occur in the control bar.\n * This can be helpful if you want to trigger a toast message.\n */\n onError?: (error: Error) => void;\n\n /**\n * Content to render in the filter panel area below the controls row.\n * Rendered when showFilters is true.\n */\n filterPanel?: React.ReactNode;\n}\n\nconst ViewNameInput = styled(Input)`\n &&,\n &&${isHovered}${isNotDisabled},\n &&${isDisabled} {\n background: transparent;\n }\n`;\n\nconst AddViewButton = styled(IconButton)`\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n`;\n\n// The hover × would cover all of a tab narrower than this, so such tabs leave it out.\nconst MIN_TAB_WIDTH_FOR_HIDE_BUTTON = 32;\n\nconst HideViewButton = styled(IconButton)`\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n opacity: 0;\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.white)};\n box-shadow: -${Spacing[2]} 0 ${Spacing[2]}\n ${({ theme }) => semanticColor(theme, 'SurfacePrimary', theme.color.white)};\n\n /* The icon's own \"XIcon\" title would otherwise replace the button's \"Hide view\" tooltip. */\n svg {\n pointer-events: none;\n }\n\n /* Without hover, a tap on the tab's edge must not land on the invisible button. */\n @media (hover: none) {\n pointer-events: none;\n }\n`;\n\nconst TabSlot = styled.div`\n position: relative;\n display: inline-flex;\n\n &:hover,\n &:has(:focus-visible) {\n ${HideViewButton} {\n opacity: 1;\n pointer-events: auto;\n }\n }\n`;\n\nconst LockedTab = styled(Tab)`\n svg {\n height: 12px;\n width: 12px;\n }\n`;\n\nconst OverflowMenuList = styled(MenuList)`\n max-height: 300px;\n overflow: auto;\n ${semanticScrollbar}\n`;\n\nconst ExpandedSearchInput = styled(SearchInput)`\n flex-basis: 440px;\n flex-grow: 1;\n`;\n\nconst ViewsBar = styled(TabBar)<{ $isAddingView: boolean }>`\n ${AddViewButton} {\n /* Shows button when view is in progress of being added */\n opacity: ${({ $isAddingView }) => ($isAddingView ? 1 : 0)};\n }\n\n &:hover,\n &:hover:focus,\n &:focus-within {\n ${AddViewButton} {\n opacity: 1;\n }\n }\n`;\n\nconst TabOverflowContainer = styled.div`\n display: flex;\n align-items: center;\n gap: ${Spacing[2]};\n position: absolute;\n height: 32px;\n`;\n\n/**\n * Base props for the SavedViewTab component\n * These are the props that must be passed to TabOverflow so it can render a SavedViewTab\n */\ninterface BaseSavedViewTabProps extends Omit<EventHandlers, 'onDeleteView' | 'onReorderViews'> {\n onRequestDeleteView?: (view: TableViewConfig) => void;\n canEditViews: boolean;\n isViewDirty: boolean;\n showTabContextMenu: boolean;\n setShowTabContextMenu: (show: boolean) => void;\n handleNameChange: (view: TableViewConfig, newName: string) => void;\n onKeyboardMove?: (viewId: string, direction: -1 | 1) => void;\n onHideView?: (viewId: string) => void;\n}\n\nconst SavedViewTab = ({\n view,\n selected,\n tabIdPrefix = TAB_ID_PREFIX,\n canEditViews,\n handleNameChange,\n onDuplicateView,\n onRequestDeleteView,\n onSelectView,\n onResetCurrentView,\n onSaveView,\n onSetDefaultView,\n onViewHiddenChange,\n onHideView,\n onKeyboardMove,\n isHidden = false,\n isViewDirty,\n showTabContextMenu,\n setShowTabContextMenu,\n className,\n ...rest\n}: BaseSavedViewTabProps & {\n tabIdPrefix?: string;\n view: TableViewConfig;\n selected: boolean;\n isHidden?: boolean;\n className?: string;\n}) => {\n const strings = usePDSStrings();\n const showMenu = selected && (canEditViews || !!onViewHiddenChange);\n\n const inputRef = useRef<HTMLInputElement>(null);\n // Blur, Enter, and popover-close can all report the same rename — only forward a\n // name once per popover session.\n const lastSubmittedNameRef = useRef<string | null>(null);\n const submitNameChange = (newName: string) => {\n if (newName === view.name || newName === lastSubmittedNameRef.current) {\n return;\n }\n lastSubmittedNameRef.current = newName;\n handleNameChange?.(view, newName);\n };\n\n const tab = (\n <StyledTab\n id={`${tabIdPrefix}${view.id}`}\n selected={selected}\n aria-selected={selected}\n role='tab'\n onClick={!selected ? () => onSelectView?.(view.id) : undefined}\n onKeyDown={\n onKeyboardMove\n ? (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.altKey && e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {\n e.preventDefault();\n e.stopPropagation();\n onKeyboardMove(view.id, e.key === 'ArrowLeft' ? -1 : 1);\n }\n }\n : undefined\n }\n aria-keyshortcuts={onKeyboardMove ? 'Alt+Shift+ArrowLeft Alt+Shift+ArrowRight' : undefined}\n suffixIcon={showMenu ? <MoreIcon /> : undefined}\n className={className}\n {...rest}\n >\n {view.name}\n </StyledTab>\n );\n\n if (showMenu) {\n return (\n <Popover\n trigger={tab}\n open={showTabContextMenu}\n onOpenChange={(open) => {\n if (selected) {\n setShowTabContextMenu(open);\n }\n if (open) {\n lastSubmittedNameRef.current = null;\n } else if (inputRef.current) {\n submitNameChange(inputRef.current.value);\n }\n }}\n contentProps={{ align: 'start', padding: Spacing[2] }}\n >\n <Stack spacing={Spacing[3]}>\n {canEditViews && (\n <ViewNameInput\n defaultValue={view.name}\n onBlur={(e) => submitNameChange(e.currentTarget.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n submitNameChange(e.currentTarget.value);\n }\n }}\n disabled={!handleNameChange}\n ref={inputRef}\n />\n )}\n <MenuList padding={Spacing[0]}>\n {canEditViews && onDuplicateView && (\n <MenuItem\n id='table-controls__view__menu-duplicate'\n prefixIcon={<CopyIcon />}\n onClick={async () => {\n const newTableView = await onDuplicateView(view.id);\n if (newTableView) {\n const { id } = newTableView;\n if (view.id !== id) {\n onSelectView?.(id);\n setShowTabContextMenu(true);\n }\n }\n }}\n onKeyDown={enterProxiesClick}\n >\n {strings.duplicateView}\n </MenuItem>\n )}\n {canEditViews && onResetCurrentView && (\n <MenuItem\n id='table-controls__view__menu-reset'\n prefixIcon={<RotateCcwIcon />}\n onClick={onResetCurrentView}\n onKeyDown={enterProxiesClick}\n >\n {strings.resetView}\n </MenuItem>\n )}\n {canEditViews && onSaveView && (\n <MenuItem\n id='table-controls__view__menu-save'\n prefixIcon={<SaveIcon />}\n disabled={!isViewDirty}\n onClick={() => {\n void onSaveView();\n setShowTabContextMenu(false);\n }}\n onKeyDown={enterProxiesClick}\n >\n {strings.saveViewMenuItem}\n </MenuItem>\n )}\n {canEditViews && onSetDefaultView && (\n <MenuItem\n id='table-controls__view__menu-set-default'\n prefixIcon={<StarIcon />}\n disabled={view.isDefault}\n onClick={async () => {\n await onSetDefaultView(view.id);\n setShowTabContextMenu(false);\n }}\n onKeyDown={enterProxiesClick}\n >\n {view.isDefault ? strings.alreadyDefaultView : strings.setAsDefaultView}\n </MenuItem>\n )}\n {onViewHiddenChange && (\n <MenuItem\n id='table-controls__view__menu-toggle-hidden'\n prefixIcon={isHidden ? <EyeIcon /> : <EyeOffIcon />}\n onClick={() => {\n setShowTabContextMenu(false);\n if (isHidden) {\n onViewHiddenChange(view.id, false);\n } else {\n onHideView?.(view.id);\n }\n }}\n onKeyDown={enterProxiesClick}\n >\n {isHidden ? strings.showView : strings.hideView}\n </MenuItem>\n )}\n {canEditViews && onRequestDeleteView && (\n <MenuItem\n id='table-controls__view__menu-delete'\n prefixIcon={<TrashIcon />}\n onClick={() => {\n setShowTabContextMenu(false);\n onRequestDeleteView(view);\n }}\n onKeyDown={enterProxiesClick}\n >\n {strings.delete}\n </MenuItem>\n )}\n </MenuList>\n </Stack>\n </Popover>\n );\n }\n\n return tab;\n};\n\ntype SavedViewTabSlotProps = ComponentProps<typeof SavedViewTab> & {\n slotRef?: Ref<HTMLDivElement>;\n slotStyle?: CSSProperties;\n slotListeners?: ReturnType<typeof useSortable>['listeners'];\n};\n\nconst SavedViewTabSlot = ({\n slotRef,\n slotStyle,\n slotListeners,\n ...props\n}: SavedViewTabSlotProps) => {\n const { view, selected, onViewHiddenChange, onHideView } = props;\n const strings = usePDSStrings();\n const [slotElement, setSlotElement] = useState<HTMLDivElement | null>(null);\n const mergedSlotRef = useMemo(() => mergeRefs(slotRef, setSlotElement), [slotRef]);\n const [isTooNarrowForHideButton, setIsTooNarrowForHideButton] = useState(false);\n\n // The × is positioned over the tab, so leaving it out never changes the width measured here.\n useLayoutEffect(() => {\n const tab = slotElement?.querySelector<HTMLElement>('[role=\"tab\"]');\n if (!tab) {\n return;\n }\n // A width of 0 means the tab has not been laid out, so keep the × until it has.\n const measure = () =>\n setIsTooNarrowForHideButton(\n tab.offsetWidth > 0 && tab.offsetWidth < MIN_TAB_WIDTH_FOR_HIDE_BUTTON,\n );\n measure();\n const resizeObserver = new ResizeObserver(measure);\n resizeObserver.observe(tab);\n return () => resizeObserver.disconnect();\n // Selecting a tab wraps it in its menu's popover, which can replace the tab element.\n }, [slotElement, selected]);\n\n return (\n // The hover × covers the end of the tab, so the whole slot is the drag handle. A press that\n // never moves still clicks the ×.\n <TabSlot ref={mergedSlotRef} data-tab-view data-tab-slot style={slotStyle} {...slotListeners}>\n <SavedViewTab {...props} />\n {!selected && onViewHiddenChange && !isTooNarrowForHideButton && (\n <HideViewButton\n id={`table-controls__view-tab-hide_${view.id}`}\n aria-label={strings.hideViewNamed(view.name)}\n title={strings.hideViewTitle}\n onClick={() => onHideView?.(view.id)}\n >\n <XIcon />\n </HideViewButton>\n )}\n </TabSlot>\n );\n};\n\nconst SortableSavedViewTab = (props: ComponentProps<typeof SavedViewTab>) => {\n const { setNodeRef, listeners, transform, transition, isDragging } = useSortable({\n id: props.view.id,\n });\n // The selected tab's popover is portaled, but its events still bubble through the slot in React,\n // so only presses on the slot's own elements start a drag.\n const slotListeners = useMemo(\n () =>\n listeners &&\n Object.fromEntries(\n Object.entries(listeners).map(([eventName, handler]) => [\n eventName,\n (event: SyntheticEvent<HTMLElement>) => {\n if (event.currentTarget.contains(event.target as Node)) {\n handler(event);\n }\n },\n ]),\n ),\n [listeners],\n );\n\n return (\n <SavedViewTabSlot\n {...props}\n slotListeners={slotListeners}\n slotRef={setNodeRef}\n slotStyle={{\n transform: transform ? `translate3d(${transform.x}px, 0, 0)` : undefined,\n transition,\n zIndex: isDragging ? 1 : undefined,\n }}\n />\n );\n};\n\ninterface LockedViewTabProps {\n id: string;\n /**\n * Whether the tab is selected. If true, the tab will not be clickable.\n */\n selected?: boolean;\n /**\n * Called when the tab is clicked. If the tab is selected, the click will be ignored.\n */\n onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n children: React.ReactNode;\n}\n\n/**\n * A tab that is locked and does not support editing or actions.\n */\nconst LockedViewTab = ({ id, selected, onClick, children, ...props }: LockedViewTabProps) => {\n return (\n <LockedTab\n id={id}\n selected={selected}\n onClick={selected ? undefined : onClick}\n suffixIcon={<LockedIcon />}\n {...props}\n >\n {children}\n </LockedTab>\n );\n};\n\nconst OverflowSavedViewTab = styled(SavedViewTab)`\n margin-left: ${Spacing[2]};\n`;\n\nconst TabOverflow = forwardRef<\n HTMLDivElement,\n BaseSavedViewTabProps & {\n overflowViews: TableViewConfig[];\n hiddenViews: TableViewConfig[];\n currentView: string | null | undefined;\n handleAddView: (() => void) | null;\n onOpenView: (viewId: string) => void;\n left: number | null;\n }\n>(function TabOverflow(\n {\n overflowViews,\n hiddenViews,\n currentView: currentViewId,\n handleAddView,\n onOpenView,\n onViewHiddenChange,\n canEditViews,\n left,\n ...rest\n },\n ref,\n) {\n const strings = usePDSStrings();\n const [filter, setFilter] = useState('');\n const [openPopover, setOpenPopover] = useState<boolean>(false);\n\n const menuViews = useMemo(() => [...overflowViews, ...hiddenViews], [overflowViews, hiddenViews]);\n\n const currentView = useMemo(\n () => menuViews.find((view) => view.id === currentViewId),\n [currentViewId, menuViews],\n );\n\n const filteredViews = useMemo(\n () =>\n menuViews.filter(\n (view) =>\n view.name.toLowerCase().includes(filter.toLowerCase()) && view.id !== currentView?.id,\n ),\n [menuViews, filter, currentView],\n );\n\n const moreCount = menuViews.length - (currentView ? 1 : 0);\n\n const renderMenuItem = (view: TableViewConfig) => (\n <MenuItem\n key={view.id}\n id={`${OVERFLOW_TAB_ID_PREFIX}${view.id}`}\n onClick={() => {\n onOpenView(view.id);\n setOpenPopover(false);\n }}\n onKeyDown={enterProxiesClick}\n >\n {view.name}\n </MenuItem>\n );\n\n return (\n <TabOverflowContainer ref={ref} style={left != null ? { left } : undefined}>\n {currentView && (\n <OverflowSavedViewTab\n view={currentView}\n canEditViews={canEditViews}\n selected={true}\n tabIdPrefix={OVERFLOW_TAB_ID_PREFIX}\n onViewHiddenChange={onViewHiddenChange}\n isHidden={hiddenViews.some((view) => view.id === currentView.id)}\n {...rest}\n />\n )}\n {moreCount > 0 && (\n <Popover\n trigger={\n <Button variant='basic' size='sm' width='auto'>\n {strings.moreViews(moreCount)}\n </Button>\n }\n contentProps={{ align: 'start', padding: Spacing[2] }}\n open={openPopover}\n onOpenChange={(open) => {\n if (!open) {\n setFilter('');\n }\n setOpenPopover(open);\n }}\n >\n <Input\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n placeholder={strings.searchViews}\n />\n <OverflowMenuList padding={Spacing[0]}>\n {filteredViews.map(renderMenuItem)}\n </OverflowMenuList>\n </Popover>\n )}\n {canEditViews && handleAddView && (\n <AddViewButton\n id={`${OVERFLOW_TAB_ID_PREFIX}overflow-new`}\n onClick={handleAddView}\n size='md'\n aria-label={strings.addNewView}\n >\n <CirclePlusIcon />\n </AddViewButton>\n )}\n </TabOverflowContainer>\n );\n});\n\n/**\n * Force the add button to be visible when the product tour is active\n */\nconst ProductTourStyles = createGlobalStyle`\n body:has(#react-joyride-portal) {\n [data-tour-target='saved-views-add-button'] {\n opacity: 1;\n }\n }\n`;\n\nconst ControlBar: FC<ControlBarProps> = ({\n presetViews,\n currentView,\n onSelectView,\n views,\n hiddenViewIds,\n onAddView,\n onDuplicateView,\n onDeleteView,\n onViewNameChange,\n onReorderViews,\n onViewHiddenChange,\n onSaveView,\n onSetDefaultView,\n isViewDirty,\n canEditViews,\n showFilters,\n setShowFilters,\n searchProps,\n filtersId,\n propertiesButton,\n tableActions,\n isLoading,\n isFilterPanelLoading,\n showViews,\n selectedRows = [],\n bulkActions,\n onResetCurrentView,\n onClearSelection,\n title,\n 'data-tour-target': dataTourTarget,\n compact,\n onError,\n filterPanel,\n}) => {\n const strings = usePDSStrings();\n const tabListRef = useRef<HTMLDivElement>(null);\n const tabOverflowRef = useRef<HTMLDivElement>(null);\n // The same could be done to get the visible views to only render them but that causes other jittery problems\n const [overflowViews, setOverflowViews] = useState<TableViewConfig[]>([]);\n const [showTabContextMenu, setShowTabContextMenu] = useState<boolean>(false);\n const [pendingDeleteView, setPendingDeleteView] = useState<TableViewConfig | null>(null);\n const previousPendingDeleteViewRef = useRef<TableViewConfig | null>(null);\n const [isDeletingView, setIsDeletingView] = useState(false);\n const [isAddingView, setIsAddingView] = useState<boolean>(false);\n const [overflowLeft, setOverflowLeft] = useState<number | null>(null);\n const [tabOverflowWidth, setTabOverflowWidth] = useState<number | null>(null);\n const [isAddViewOverflowing, setIsAddViewOverflowing] = useState(false);\n\n useEffect(() => {\n const previousPendingDeleteView = previousPendingDeleteViewRef.current;\n if (!pendingDeleteView && previousPendingDeleteView) {\n const tab =\n document.getElementById(`${OVERFLOW_TAB_ID_PREFIX}${previousPendingDeleteView.id}`) ??\n document.getElementById(`${TAB_ID_PREFIX}${previousPendingDeleteView.id}`);\n tab?.focus({ preventScroll: true });\n }\n previousPendingDeleteViewRef.current = pendingDeleteView;\n }, [pendingDeleteView]);\n\n const [shownViews, hiddenViews] = useMemo(() => {\n const hiddenIds = new Set(hiddenViewIds);\n const allViews = views ?? [];\n return [\n allViews.filter((view) => !hiddenIds.has(view.id)),\n allViews.filter((view) => hiddenIds.has(view.id)),\n ];\n }, [views, hiddenViewIds]);\n\n const onResize = useCallback(() => {\n if (!tabListRef.current) {\n return;\n }\n\n const containerRect = tabListRef.current.getBoundingClientRect();\n const tabListContainer = tabListRef.current;\n const tabElements = Array.from(\n tabListContainer.querySelectorAll('[data-tab-view]'),\n ) as HTMLElement[];\n\n const firstOverflowIndex = tabElements.findIndex(\n (el) => !rectContainsRect(containerRect, el.getBoundingClientRect()),\n );\n\n const nextOverflowViews = firstOverflowIndex === -1 ? [] : shownViews.slice(firstOverflowIndex);\n setOverflowViews((prev) =>\n prev.length === nextOverflowViews.length &&\n prev.every((view, index) => view === nextOverflowViews[index])\n ? prev\n : nextOverflowViews,\n );\n\n // Anything that wrapped onto the clipped second row, the add button included, is not a\n // valid anchor.\n const firstRowElements = Array.from(tabListContainer.children).filter(\n (el): el is HTMLElement =>\n el instanceof HTMLElement &&\n el !== tabOverflowRef.current &&\n rectContainsRect(containerRect, el.getBoundingClientRect()),\n );\n const anchor = firstRowElements[firstRowElements.length - 1];\n setOverflowLeft(anchor ? anchor.offsetLeft + anchor.offsetWidth + OVERFLOW_GAP : null);\n\n const addViewButton = tabListContainer.querySelector(`#${ADD_VIEW_BUTTON_ID}`);\n setIsAddViewOverflowing(\n addViewButton instanceof HTMLElement && !firstRowElements.includes(addViewButton),\n );\n\n const tabOverflowWidth = tabOverflowRef.current?.getBoundingClientRect().width;\n if (tabOverflowWidth) {\n setTabOverflowWidth((prev) =>\n prev != null &&\n prev > tabOverflowWidth &&\n prev - tabOverflowWidth < OVERFLOW_WIDTH_SHRINK_THRESHOLD\n ? prev\n : tabOverflowWidth,\n );\n }\n }, [shownViews]);\n\n // A tab can change width (rename, selection, font load) without the tab list resizing, so every\n // child is observed too, re-attached whenever the children change.\n useLayoutEffect(() => {\n const tabList = tabListRef.current;\n if (!showViews || !tabList) {\n return;\n }\n\n const resizeObserver = new ResizeObserver(() => {\n onResize();\n });\n const observeTabList = () => {\n resizeObserver.disconnect();\n resizeObserver.observe(tabList);\n Array.from(tabList.children).forEach((child) => resizeObserver.observe(child));\n };\n const mutationObserver = new MutationObserver(observeTabList);\n\n observeTabList();\n mutationObserver.observe(tabList, { childList: true });\n\n return () => {\n mutationObserver.disconnect();\n resizeObserver.disconnect();\n };\n }, [onResize, showViews]);\n\n // Update hidden tabs when views change. This needs to fire when we initially load the page, then again when the views load, and also when a view is added or removed\n useLayoutEffect(() => {\n if (showViews) {\n onResize();\n }\n }, [onResize, showViews, shownViews]);\n\n const isCurrentViewInOverflow = useMemo(\n () =>\n !!currentView && [...overflowViews, ...hiddenViews].some((view) => view.id === currentView),\n [currentView, overflowViews, hiddenViews],\n );\n\n const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));\n\n const dragBoundsRef = useRef<{ left: number; right: number; bottom: number } | null>(null);\n\n const handleDragStart = () => {\n const tabList = tabListRef.current;\n if (!tabList) {\n return;\n }\n const tabListRect = tabList.getBoundingClientRect();\n const visibleSlotRects = Array.from(tabList.querySelectorAll('[data-tab-view]'))\n .map((slot) => slot.getBoundingClientRect())\n .filter((rect) => rectContainsRect(tabListRect, rect));\n dragBoundsRef.current =\n visibleSlotRects.length > 0\n ? {\n left: visibleSlotRects[0].left,\n right: visibleSlotRects[visibleSlotRects.length - 1].right,\n bottom: tabListRect.bottom,\n }\n : null;\n };\n\n // Tabs wrapped onto the clipped second row are still sortable, and one directly below the pointer\n // can be nearer than a visible tab, flipping the drop target and snapping visible tabs back.\n // The tab under the pointer wins, so a narrow tab reorders past a wide neighbour's edge.\n const visibleTabCollision = useCallback<CollisionDetection>((args) => {\n const bounds = dragBoundsRef.current;\n const visibleArgs = {\n ...args,\n droppableContainers: args.droppableContainers.filter((container) => {\n const rect = args.droppableRects.get(container.id);\n return bounds == null || (rect != null && rect.bottom <= bounds.bottom + 1);\n }),\n };\n const pointerCollisions = pointerWithin(visibleArgs);\n return pointerCollisions.length > 0 ? pointerCollisions : closestCenter(visibleArgs);\n }, []);\n\n // Keeps a dragged tab among the visible saved tabs, off the locked tabs and the overflow menu.\n const restrictToVisibleSavedTabs = useCallback<Modifier>(({ transform, draggingNodeRect }) => {\n const bounds = dragBoundsRef.current;\n if (!bounds || !draggingNodeRect) {\n return { ...transform, y: 0 };\n }\n const minX = bounds.left - draggingNodeRect.left;\n const maxX = bounds.right - draggingNodeRect.right;\n return { ...transform, x: Math.min(Math.max(transform.x, minX), maxX), y: 0 };\n }, []);\n\n // A view picked from the overflow menu moves to the front so it stays in the tab bar while the\n // user picks the next one.\n const moveView = (viewId: string, toIndex: number) => {\n if (!views || !onReorderViews) {\n return;\n }\n const viewIds = views.map((view) => view.id);\n const reordered = moveItemByIndex(viewIds, viewIds.indexOf(viewId), toIndex);\n if (reordered !== viewIds) {\n onReorderViews(reordered);\n }\n };\n const indexOfView = (viewId: string) => views?.findIndex((view) => view.id === viewId) ?? -1;\n\n const openViewFromMenu = (viewId: string) => {\n if (hiddenViews.some((view) => view.id === viewId)) {\n onViewHiddenChange?.(viewId, false);\n }\n moveView(viewId, 0);\n onSelectView?.(viewId);\n };\n\n const handleDragEnd = ({ active, over }: DragEndEvent) => {\n if (over) {\n moveView(String(active.id), indexOfView(String(over.id)));\n }\n };\n\n const hideView = (viewId: string) => {\n const overflowIds = new Set(overflowViews.map((view) => view.id));\n const visibleViews = shownViews.filter((view) => !overflowIds.has(view.id));\n const index = visibleViews.findIndex((view) => view.id === viewId);\n const isCurrent = viewId === currentView;\n const focusTarget =\n isCurrent || index === -1 ? undefined : (visibleViews[index + 1] ?? visibleViews[index - 1]);\n\n onViewHiddenChange?.(viewId, true);\n if (isCurrent) {\n onSelectView?.(null);\n }\n // The hidden tab's controls unmount, so focus a visible neighbour, or Default when the active\n // view is hidden. Focusing must not scroll the clipped tab list.\n document\n .getElementById(`${TAB_ID_PREFIX}${focusTarget ? focusTarget.id : 'default'}`)\n ?.focus({ preventScroll: true });\n };\n\n const moveViewWithKeyboard = (viewId: string, direction: -1 | 1) => {\n const neighbor = shownViews[shownViews.findIndex((view) => view.id === viewId) + direction];\n if (!neighbor) {\n return;\n }\n moveView(viewId, indexOfView(neighbor.id));\n };\n\n const handleAddView = async () => {\n try {\n setIsAddingView(true);\n if (onAddView) {\n const view = await onAddView();\n\n // Occurs if there is an error adding the view\n if (!view || !view.id) {\n return;\n }\n\n if (currentView !== view.id) {\n onSelectView?.(view.id);\n }\n\n setShowTabContextMenu(true);\n }\n } catch {\n onError?.(new Error('Error adding view'));\n } finally {\n setIsAddingView(false);\n }\n };\n\n const handleNameChange = (view: TableViewConfig, newName: string) => {\n if (canEditViews && view.name !== newName) {\n onViewNameChange?.(view.id, newName);\n }\n };\n\n const onRequestDeleteView = onDeleteView\n ? (view: TableViewConfig) => setPendingDeleteView(view)\n : undefined;\n\n const confirmDeleteView = async () => {\n if (!pendingDeleteView || !onDeleteView) {\n return;\n }\n\n setIsDeletingView(true);\n try {\n await onDeleteView(pendingDeleteView.id);\n setPendingDeleteView(null);\n } catch {\n // Keep the dialog open so the user can retry.\n } finally {\n setIsDeletingView(false);\n }\n };\n\n // Compact variant with simplified layout\n if (compact) {\n // todo(joseph): add bulk actions\n return (\n <CompactBar\n data-tour-target={dataTourTarget}\n title={title}\n searchProps={searchProps}\n showFilters={showFilters}\n setShowFilters={setShowFilters}\n filtersId={filtersId}\n isLoading={isLoading}\n isFilterPanelLoading={isFilterPanelLoading}\n propertiesButton={propertiesButton}\n tableActions={tableActions}\n filterPanel={filterPanel}\n />\n );\n }\n\n // Generate persistent bulk action buttons\n const bulkActionButtons = bulkActions?.map((action, index) => {\n const key = 'label' in action ? action.label : `action-${index}`;\n const isDisabled = selectedRows.length === 0 || action.disabled === true;\n const selectedCount = selectedRows.length;\n\n const clearSelection = () => {\n onClearSelection?.();\n };\n\n if ('icon' in action && 'aria-label' in action) {\n // Icon-only action\n return (\n <IconButton\n key={key}\n size='sm'\n aria-label={action['aria-label']}\n onClick={async () => {\n await action.onClick(selectedRows, clearSelection);\n }}\n disabled={isDisabled}\n >\n {action.icon}\n </IconButton>\n );\n }\n\n // Append count to label if rows are selected\n const displayLabel =\n 'label' in action && selectedCount > 0\n ? `${action.label} (${selectedCount})`\n : 'label' in action\n ? action.label\n : '';\n\n return (\n <Button\n id={`table-controls__view-tab-bulk-action-${index}`}\n variant='basic'\n size='sm'\n width='auto'\n key={key}\n onClick={async () => {\n await action.onClick(selectedRows, clearSelection);\n }}\n disabled={isDisabled}\n >\n {displayLabel}\n </Button>\n );\n });\n\n const showViewsBar =\n title || showViews || (canEditViews && onSaveView) || tableActions || bulkActions;\n\n const getSavedViewTabProps = (view: TableViewConfig) => ({\n view,\n onKeyboardMove: onReorderViews ? moveViewWithKeyboard : undefined,\n onHideView: hideView,\n canEditViews: canEditViews ?? false,\n handleNameChange,\n onDuplicateView,\n onRequestDeleteView,\n onSelectView,\n onResetCurrentView,\n onSaveView,\n onSetDefaultView,\n onViewHiddenChange,\n isViewDirty: isViewDirty ?? false,\n selected: view.id === currentView,\n showTabContextMenu: showTabContextMenu && !isCurrentViewInOverflow,\n setShowTabContextMenu,\n });\n\n const viewsBar = (\n <ViewsBar\n ref={tabListRef}\n title={title}\n maxTabChars={25}\n $isAddingView={isAddingView}\n data-tour-target={dataTourTarget}\n actions={\n <HStack\n spacing={Spacing[3]}\n align='center'\n style={tabOverflowWidth ? { paddingLeft: `${tabOverflowWidth + 16}px` } : undefined}\n >\n {canEditViews && onSaveView && (\n <Button\n id='table-controls__view-tab-save'\n onClick={onSaveView}\n aria-label={strings.saveCurrentView}\n disabled={!isViewDirty || isLoading}\n size='sm'\n variant='basic'\n width='auto'\n data-tour-target='saved-views-save-button'\n >\n {strings.saveView}\n </Button>\n )}\n {bulkActionButtons}\n {tableActions}\n </HStack>\n }\n >\n {showViews && (\n <>\n <LockedViewTab\n id={`${TAB_ID_PREFIX}default`}\n selected={!currentView}\n onClick={() => onSelectView?.(null)}\n data-tour-target='saved-views-default-view'\n >\n {strings.defaultView}\n </LockedViewTab>\n {presetViews?.map((view) => {\n const selected = view.id === currentView;\n return (\n <LockedViewTab\n key={view.id}\n id={`${TAB_ID_PREFIX}preset-${view.id}`}\n selected={selected}\n onClick={() => onSelectView?.(view.id)}\n >\n {view.name}\n </LockedViewTab>\n );\n })}\n {onReorderViews ? (\n <SortableContext\n items={shownViews.map((view) => view.id)}\n strategy={horizontalListSortingStrategy}\n >\n {shownViews.map((view) => (\n <SortableSavedViewTab key={view.id} {...getSavedViewTabProps(view)} />\n ))}\n </SortableContext>\n ) : (\n shownViews.map((view) => (\n <SavedViewTabSlot key={view.id} {...getSavedViewTabProps(view)} />\n ))\n )}\n {canEditViews && onAddView && (\n <AddViewButton\n id={ADD_VIEW_BUTTON_ID}\n size='md'\n onClick={handleAddView}\n aria-label={strings.addNewView}\n data-tour-target='saved-views-add-button'\n >\n <CirclePlusIcon />\n </AddViewButton>\n )}\n {(overflowViews.length > 0 || hiddenViews.length > 0) && (\n <TabOverflow\n ref={tabOverflowRef}\n overflowViews={overflowViews}\n hiddenViews={hiddenViews}\n currentView={currentView}\n onSelectView={onSelectView}\n onOpenView={openViewFromMenu}\n canEditViews={canEditViews ?? false}\n handleAddView={onAddView && isAddViewOverflowing ? handleAddView : null}\n handleNameChange={handleNameChange}\n onDuplicateView={onDuplicateView}\n onRequestDeleteView={onRequestDeleteView}\n onResetCurrentView={onResetCurrentView}\n onSaveView={onSaveView}\n onSetDefaultView={onSetDefaultView}\n onViewHiddenChange={onViewHiddenChange}\n onHideView={hideView}\n isViewDirty={isViewDirty ?? false}\n showTabContextMenu={showTabContextMenu && isCurrentViewInOverflow}\n setShowTabContextMenu={setShowTabContextMenu}\n left={overflowLeft}\n />\n )}\n </>\n )}\n </ViewsBar>\n );\n\n return (\n <>\n <ProductTourStyles />\n {showViewsBar &&\n (onReorderViews ? (\n <DndContext\n sensors={sensors}\n collisionDetection={visibleTabCollision}\n modifiers={[restrictToVisibleSavedTabs]}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n {viewsBar}\n </DndContext>\n ) : (\n viewsBar\n ))}\n <HStack align='center' spacing={Spacing[2]} justify='right'>\n {searchProps && (\n <ExpandedSearchInput title={null} useClearIcon {...searchProps} size='md' />\n )}\n {setShowFilters && (\n <Button\n id='table-controls__view-tab-filters'\n variant='basic'\n onClick={() => setShowFilters?.(!showFilters)}\n aria-label={showFilters ? strings.hideFilters : strings.showFilters}\n aria-expanded={showFilters}\n aria-controls={filtersId}\n disabled={isLoading || isFilterPanelLoading}\n isPending={isFilterPanelLoading}\n active={showFilters}\n width='icon'\n size='md'\n data-tour-target='table-filters-toggle-button'\n >\n <FilterIcon />\n </Button>\n )}\n {propertiesButton}\n </HStack>\n {showFilters && filterPanel}\n <Modal\n open={pendingDeleteView != null}\n onOpenChange={(open) => {\n if (!open && !isDeletingView) {\n setPendingDeleteView(null);\n }\n }}\n isKeyboardDismissDisabled={isDeletingView}\n contentProps={isDeletingView ? { showCloseButton: false } : undefined}\n title={strings.deleteViewTitle}\n footer={\n <>\n <Button\n variant='basic'\n width='auto'\n disabled={isDeletingView}\n onClick={() => setPendingDeleteView(null)}\n >\n {strings.cancel}\n </Button>\n <Button\n id='table-controls__view__delete-confirm'\n variant='danger'\n width='auto'\n isPending={isDeletingView}\n onClick={confirmDeleteView}\n >\n {strings.delete}\n </Button>\n </>\n }\n >\n <Paragraph>{strings.deleteViewConfirmation(pendingDeleteView?.name ?? '')}</Paragraph>\n </Modal>\n </>\n );\n};\n\nexport default ControlBar;\n","import { type ReactNode, useMemo, useState } from 'react';\nimport { useId } from 'react-aria';\nimport styled from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport {\n ControlBar,\n TableViewConfigurationDropdown,\n type ControlBarProps,\n} from 'design-system/components/DataTable/TableControls';\nimport Stack from 'design-system/components/Stack';\n\nimport type { TableViewConfigurationProps } from './TableViewConfigurationDropdown';\n\nexport interface TableControlsProps extends ControlBarProps {\n defaultShowFilters?: boolean;\n className?: string;\n tableActions?: ReactNode;\n propertiesButton?: ReactNode;\n isLoading?: boolean;\n\n /**\n * Whether to show filters always. If true, the filter row toggle button will not be rendered.\n */\n showFiltersAlways?: boolean;\n\n /**\n * Whether to display table views tab bar\n */\n showViews?: boolean;\n\n /**\n * Whether to use compact spacing and styling.\n * The compact variant does not support views.\n */\n compact?: boolean;\n\n /**\n * Column configuration options for the table.\n * If provided, displays a settings button to configure visible columns.\n */\n columnConfigurationProps?: TableViewConfigurationProps;\n}\n\nconst TableControls = ({\n filterPanel,\n searchProps,\n defaultShowFilters,\n showFilters: controlledShowFilters,\n setShowFilters: controlledSetShowFilters,\n className,\n tableActions,\n propertiesButton,\n isLoading,\n isFilterPanelLoading,\n showViews,\n canEditViews,\n onSelectView,\n views,\n hiddenViewIds,\n currentView,\n onAddView,\n onViewNameChange,\n onReorderViews,\n onViewHiddenChange,\n onDuplicateView,\n onDeleteView,\n onSaveView,\n onSetDefaultView,\n isViewDirty,\n selectedRows,\n bulkActions,\n onClearSelection,\n title,\n presetViews,\n compact,\n columnConfigurationProps,\n showFiltersAlways = false,\n onError,\n 'data-tour-target': dataTourTarget,\n}: TableControlsProps) => {\n const filtersId = useId();\n const [internalShowFilters, internalSetShowFilters] = useState(defaultShowFilters ?? false);\n const showFilters = controlledShowFilters != null ? controlledShowFilters : internalShowFilters;\n const setShowFilters =\n controlledSetShowFilters != null ? controlledSetShowFilters : internalSetShowFilters;\n\n // Create enhanced properties button that includes column configuration if provided\n const enhancedPropertiesButton = useMemo(() => {\n if (!columnConfigurationProps && !propertiesButton) {\n return undefined;\n }\n\n const elements = [];\n\n // Add original properties button if provided\n if (propertiesButton) {\n elements.push(propertiesButton);\n }\n\n // Add column configuration dropdown if provided\n if (columnConfigurationProps) {\n elements.push(\n <TableViewConfigurationDropdown\n key='column-config'\n disabled={false}\n {...columnConfigurationProps}\n />,\n );\n }\n\n // Return single element or fragment with multiple elements\n if (elements.length === 1) {\n return elements[0];\n }\n\n return <StyledEnhancedPropertiesButton>{elements}</StyledEnhancedPropertiesButton>;\n }, [columnConfigurationProps, propertiesButton]);\n\n return (\n <Container className={className}>\n <ControlBar\n showViews={compact ? false : showViews}\n views={compact ? undefined : views}\n hiddenViewIds={compact ? undefined : hiddenViewIds}\n onSelectView={compact ? undefined : onSelectView}\n currentView={compact ? undefined : currentView}\n onAddView={compact ? undefined : onAddView}\n onDeleteView={compact ? undefined : onDeleteView}\n onDuplicateView={compact ? undefined : onDuplicateView}\n onViewNameChange={compact ? undefined : onViewNameChange}\n onReorderViews={compact ? undefined : onReorderViews}\n onViewHiddenChange={compact ? undefined : onViewHiddenChange}\n onSaveView={compact ? undefined : onSaveView}\n onSetDefaultView={compact ? undefined : onSetDefaultView}\n isViewDirty={isViewDirty}\n canEditViews={compact ? false : canEditViews}\n showFilters={showFilters && (showFiltersAlways || !isFilterPanelLoading)}\n setShowFilters={\n (filterPanel != null || isFilterPanelLoading) && !showFiltersAlways\n ? setShowFilters\n : undefined\n }\n filtersId={filtersId}\n searchProps={searchProps}\n propertiesButton={enhancedPropertiesButton}\n tableActions={tableActions}\n isLoading={isLoading}\n isFilterPanelLoading={isFilterPanelLoading}\n selectedRows={selectedRows}\n bulkActions={bulkActions}\n onClearSelection={onClearSelection}\n title={title}\n data-tour-target={dataTourTarget}\n presetViews={compact ? undefined : presetViews}\n compact={compact}\n onError={onError}\n filterPanel={filterPanel}\n />\n </Container>\n );\n};\n\nexport default TableControls;\n\nconst Container = styled(Stack)`\n margin-bottom: ${Spacing[2]};\n`;\n\nconst StyledEnhancedPropertiesButton = styled.div`\n display: flex;\n gap: ${Spacing[1]};\n`;\n","import styled, { css } from 'styled-components';\n\nimport { Color } from '@persona/design-tokens';\nimport { DragIcon } from '@persona/icons/24px';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\n// StyledIconDrag is an IconDrag which changes color as you hover over it\nexport const StyledIconDrag = styled(DragIcon)<{\n $active: boolean;\n $hover?: boolean;\n $shouldHide?: boolean;\n $horizontal?: boolean;\n}>`\n display: ${({ $shouldHide = false }) => ($shouldHide ? 'none' : 'inline')};\n\n ${({ $horizontal = false }) =>\n $horizontal\n ? css`\n transform: rotate(90deg);\n `\n : ''}\n\n ${({ $active = false, $hover = false }) =>\n $active\n ? css`\n cursor: grabbing;\n opacity: 1;\n `\n : $hover\n ? css`\n cursor: grab;\n opacity: 1;\n `\n : css`\n cursor: normal;\n opacity: 0.4;\n `}\n\n transition: opacity 0.2s ease-in-out;\n\n path {\n stroke: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.CoreSlate1000)};\n stroke-width: 1px;\n }\n`;\n","/**\n * reorder returns a reordered version of the inputed list by swapping the element\n * at startIndex with the one at endIndex\n */\nexport function reorder<A>(list: A[], startIndex: number, endIndex: number): A[] {\n const result = Array.from(list);\n const [removed] = result.splice(startIndex, 1);\n result.splice(endIndex, 0, removed);\n\n return result;\n}\n\n/**\n * Translates a drag result into indices into the full list. dnd reports positions among the\n * rendered rows, which diverge from the full list as soon as the view is filtered.\n *\n * Returns null when either end cannot be resolved, in which case the drag should be ignored\n * rather than applied at the wrong position.\n */\nexport function resolveDragIndices(\n listKeys: string[],\n renderedKeys: string[],\n draggableId: string,\n destinationIndex: number,\n): { from: number; to: number } | null {\n const destinationKey = renderedKeys[destinationIndex];\n if (destinationKey == null) {\n return null;\n }\n\n const from = listKeys.indexOf(draggableId);\n const to = listKeys.indexOf(destinationKey);\n\n return from === -1 || to === -1 ? null : { from, to };\n}\n","import {\n DragDropContext,\n Draggable,\n Droppable,\n type DropResult,\n type ResponderProvided,\n} from '@hello-pangea/dnd';\nimport Fuse, { type IFuseOptions } from 'fuse.js';\nimport { partition, union } from 'lodash-es';\nimport { type ComponentProps, forwardRef, useMemo, useState } from 'react';\nimport styled from 'styled-components';\n\nimport { Spacing } from '@persona/design-tokens';\nimport { SettingsIcon } from '@persona/icons';\nimport Button from 'design-system/components/Button';\nimport Card from 'design-system/components/Card';\nimport { StyledIconDrag } from 'design-system/components/DataTable/dnd/StyledIconDrag';\nimport { reorder, resolveDragIndices } from 'design-system/components/DataTable/dnd/utils';\nimport SearchInput from 'design-system/components/DataTable/SearchInput';\nimport Popover from 'design-system/components/Popover';\nimport Spacer from 'design-system/components/Spacer';\nimport { Label, Paragraph } from 'design-system/components/Text';\nimport Toggle from 'design-system/components/Toggle';\nimport Tooltip from 'design-system/components/Tooltip';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor, semanticOnly } from 'design-system/lib/semanticColor';\nimport { Z_INDICES } from 'design-system/lib/zindex';\n\nimport type { AttributeColumn } from './types';\n\nconst SHOWN_DROPPABLE_ID = 'cases-view__configure-shown-columns';\n\nconst startsCapitalized = (label: string) => {\n const first = label.charAt(0);\n return first !== '' && first === first.toUpperCase() && first !== first.toLowerCase();\n};\n\n// `numeric` keeps \"Address 2\" ahead of \"Address 10\".\nconst byLabel = (a: AttributeColumn, b: AttributeColumn) => {\n const aCapitalized = startsCapitalized(a.label);\n if (aCapitalized !== startsCapitalized(b.label)) {\n return aCapitalized ? -1 : 1;\n }\n\n return a.label.localeCompare(b.label, undefined, { numeric: true });\n};\n\nconst DndSection = styled('div')`\n max-height: 400px;\n\n overflow: scroll;\n ::-webkit-scrollbar {\n display: none;\n }\n`;\n\nconst DndItemWrapper = styled('div')`\n background: white;\n ${semanticOnly((tokens) => `background: ${tokens.SurfacePrimary};`)}\n width: 100%;\n border-bottom: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', theme.color.border.secondary)};\n padding: ${Spacing[2]} ${Spacing[2]};\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: left;\n`;\n\nconst SuffixContainer = styled('div')`\n padding-left: ${Spacing[2]};\n margin-left: auto;\n align-self: center;\n`;\n\nconst SearchContainer = styled.div`\n display: flex;\n`;\n\nconst StyledSearchInput = styled(SearchInput)`\n width: 100%;\n`;\n\nconst PopoverCard = styled(Card)`\n width: 300px;\n padding: ${Spacing[4]};\n`;\n\nconst TriggerIconButton = forwardRef<HTMLButtonElement, ComponentProps<typeof Button>>(\n function TriggerIconButton({ disabled, ...elemProps }, ref) {\n const strings = usePDSStrings();\n return (\n <Button\n disabled={disabled}\n width='icon'\n variant='basic'\n size='md'\n {...elemProps}\n ref={ref}\n data-tour-target='table-properties-button'\n aria-label={strings.tableProperties}\n >\n <SettingsIcon />\n </Button>\n );\n },\n);\n\nconst TooltipButtonWrapper = styled('div')`\n display: inline-block;\n`;\n\nexport interface TableViewConfigurationDropdownProps extends TableViewConfigurationProps {\n disabled: boolean;\n disabledTooltipMessage?: string;\n size?: 'sm' | 'md';\n variant?: 'basic' | 'text';\n}\n\nconst TableViewConfigurationDropdown = ({\n disabled = false,\n disabledTooltipMessage,\n size = 'md',\n variant = 'basic',\n ...props\n}: TableViewConfigurationDropdownProps) => {\n const strings = usePDSStrings();\n return disabled ? (\n <Tooltip\n trigger={\n // NB: this wrapping div is needed to properly display the tooltip. The library we're using, floating-ui\n // doesn't support displaying tooltips on disabled buttons.\n <TooltipButtonWrapper>\n <TriggerIconButton disabled={true} size={size} variant={variant} />\n </TooltipButtonWrapper>\n }\n >\n {disabledTooltipMessage ?? strings.configureViewPermissionDenied}\n </Tooltip>\n ) : (\n <Popover>\n <Popover.Trigger asChild>\n <TriggerIconButton disabled={false} size={size} variant={variant} />\n </Popover.Trigger>\n <Popover.Content\n style={{ zIndex: Z_INDICES.dropdown }}\n sideOffset={8}\n side='bottom'\n align='end'\n >\n <PopoverCard elevated>\n <TableViewConfiguration {...props} />\n </PopoverCard>\n </Popover.Content>\n </Popover>\n );\n};\n\nexport interface TableViewConfigurationProps {\n columnConfiguration: AttributeColumn[];\n attributeOptions: AttributeColumn[];\n updateColumnConfiguration: (newConfiguration: AttributeColumn[]) => void;\n getColumnDisabled?: (columnId: string, shownColumnIds: string[]) => boolean;\n sortByRelevance?: boolean;\n}\n\nexport const TableViewConfiguration = ({\n columnConfiguration,\n attributeOptions,\n updateColumnConfiguration,\n getColumnDisabled,\n sortByRelevance = false,\n}: TableViewConfigurationProps) => {\n const strings = usePDSStrings();\n const [searchTerm, setSearchTerm] = useState<string>('');\n\n const fuse = useMemo(() => {\n const fuseOptions: IFuseOptions<AttributeColumn> = sortByRelevance\n ? {\n shouldSort: true,\n threshold: 0.3,\n ignoreLocation: true,\n includeScore: true,\n minMatchCharLength: 1,\n keys: [{ name: 'label', weight: 1.0 }],\n }\n : {\n shouldSort: false,\n threshold: 0.4,\n location: 0,\n distance: 100,\n minMatchCharLength: 1,\n keys: [{ name: 'label', weight: 1.0 }],\n };\n return new Fuse(attributeOptions, fuseOptions);\n }, [attributeOptions, sortByRelevance]);\n\n // NB: we do this to make sure that attributes that exist in the column configuration but NOT the standardized options still show up in the menu.\n // Options are deduped.\n const allOptions = useMemo(\n () => union(attributeOptions, columnConfiguration),\n [attributeOptions, columnConfiguration],\n );\n\n const filteredSearchOptions = useMemo(() => {\n if (searchTerm === '') {\n return allOptions;\n }\n\n const results = fuse.search(searchTerm);\n if (!sortByRelevance) {\n return results.map(({ item }) => item);\n }\n\n // Fuse leaves equally-scored matches in corpus order, so tie-break by label.\n return [...results]\n .sort((a, b) => (a.score ?? 0) - (b.score ?? 0) || byLabel(a.item, b.item))\n .map(({ item }) => item);\n }, [allOptions, fuse, searchTerm, sortByRelevance]);\n\n const hiddenAttributes = useMemo(() => {\n const columnConfigurationKeys = new Set(columnConfiguration.map((c) => c.key));\n const hidden = filteredSearchOptions.filter(\n (attribute) => !columnConfigurationKeys.has(attribute.key),\n );\n\n // While searching, fuse has already ordered these by match strength.\n if (!sortByRelevance || searchTerm !== '') {\n return hidden;\n }\n\n const [systemColumns, customFields] = partition(hidden, (a) => !a.isCustomField);\n return [...systemColumns, ...[...customFields].sort(byLabel)];\n }, [columnConfiguration, filteredSearchOptions, sortByRelevance, searchTerm]);\n\n const filteredShownAttributes = useMemo(() => {\n return columnConfiguration.filter((column) =>\n filteredSearchOptions.map((o) => o.key).includes(column.key),\n );\n }, [columnConfiguration, filteredSearchOptions]);\n\n const handleDragEnd = (result: DropResult, _provided: ResponderProvided) => {\n const { destination, source } = result;\n if (\n !destination ||\n (destination.droppableId === source.droppableId && destination.index === source.index)\n ) {\n return;\n }\n\n const indices = resolveDragIndices(\n columnConfiguration.map((c) => c.key),\n filteredShownAttributes.map((c) => c.key),\n result.draggableId,\n destination.index,\n );\n if (!indices) {\n return;\n }\n\n updateColumnConfiguration(reorder(columnConfiguration, indices.from, indices.to));\n };\n\n const generateShownAttributesToggle = (column: AttributeColumn) => () => {\n const updatedAttributes = columnConfiguration.filter((a) => a.key !== column.key);\n updateColumnConfiguration(updatedAttributes);\n };\n\n const generateHiddenAttributesToggle = (column: AttributeColumn) => () => {\n // Persisted verbatim into the saved view, so drop `isCustomField`.\n const updatedAttributes = columnConfiguration.concat({\n key: column.key,\n label: column.label,\n });\n updateColumnConfiguration(updatedAttributes);\n };\n\n const shownColumnIds = useMemo(() => {\n return columnConfiguration.map((c) => c.key);\n }, [columnConfiguration]);\n\n const shownDndItemProps: AttributeDndProps[] = filteredShownAttributes.map((column, index) => {\n const isDisabledByDefault = columnConfiguration.length === 1;\n const isDisabledByCustom = getColumnDisabled?.(column.key, shownColumnIds) ?? false;\n const shouldDisableDragForColumn =\n isDisabledByCustom && index === filteredShownAttributes.length - 1;\n const result: AttributeDndProps = {\n column: column,\n index: index,\n isDisabled: isDisabledByDefault || isDisabledByCustom,\n isToggled: true,\n shouldDisableDrag: shouldDisableDragForColumn,\n handleToggle: generateShownAttributesToggle(column),\n };\n return result;\n });\n\n const hiddenDndItemProps: AttributeDndProps[] = hiddenAttributes.map((column, index) => {\n const result: AttributeDndProps = {\n column: column,\n index: index,\n isToggled: false,\n shouldDisableDrag: true,\n handleToggle: generateHiddenAttributesToggle(column),\n };\n return result;\n });\n\n return (\n <div>\n <Label size='lg' weight='bold'>\n {strings.configureColumns}\n </Label>\n <Spacer height={2} />\n <SearchContainer>\n <StyledSearchInput\n title={null}\n value={searchTerm}\n handleInput={setSearchTerm}\n size='md'\n placeholder={strings.searchColumns}\n dataTest='checklist-item-panel-item-table__search'\n />\n </SearchContainer>\n <Spacer height={2} />\n {shownDndItemProps.length > 0 || hiddenDndItemProps.length > 0 ? (\n <DndSection>\n {shownDndItemProps.length > 0 && (\n <div>\n <Paragraph>{strings.shownColumns}</Paragraph>\n {/* Issue with @hello-pangea/dnd and transformed parent elements: https://github.com/hello-pangea/dnd/blob/main/docs/guides/reparenting.md\n We have to use the renderClone API to get the dragging working correctly. This has to do with one of the parent elements being a Popover. */}\n <DragDropContext onDragEnd={handleDragEnd}>\n <Droppable\n droppableId={SHOWN_DROPPABLE_ID}\n renderClone={(provided, _snapshot, rubric) => {\n return (\n <div\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n ref={provided.innerRef}\n >\n <AttributeDnd {...shownDndItemProps[rubric.source.index]} />\n </div>\n );\n }}\n >\n {(provided) => {\n return (\n <div ref={provided.innerRef} {...provided.droppableProps}>\n {shownDndItemProps.map((props, idx) => {\n return (\n <Draggable\n key={`${props.column.key}`}\n draggableId={props.column.key}\n index={idx}\n isDragDisabled={props.shouldDisableDrag}\n >\n {(provided) => {\n return (\n <div\n ref={provided.innerRef}\n {...provided.draggableProps}\n {...provided.dragHandleProps}\n >\n <AttributeDnd {...props} />\n </div>\n );\n }}\n </Draggable>\n );\n })}\n {provided.placeholder}\n </div>\n );\n }}\n </Droppable>\n </DragDropContext>\n </div>\n )}\n <Spacer height={2} />\n {hiddenDndItemProps.length > 0 && (\n <div>\n <Paragraph>{strings.hiddenColumns}</Paragraph>\n {/* Hidden columns are sorted by relevance rather than carrying a user-defined\n order, so these rows are a plain list rather than a droppable. */}\n {hiddenDndItemProps.map((props) => (\n <AttributeDnd key={props.column.key} {...props} />\n ))}\n </div>\n )}\n </DndSection>\n ) : (\n <div>\n <Paragraph>{strings.noMatchingColumns}</Paragraph>\n </div>\n )}\n </div>\n );\n};\n\nconst OverflowText = styled('div')`\n max-width: 160px;\n flex-wrap: wrap;\n display: flex;\n`;\n\ninterface AttributeDndProps {\n column: AttributeColumn;\n index: number;\n isDisabled?: boolean;\n isToggled: boolean;\n shouldDisableDrag: boolean;\n handleToggle: () => void;\n}\n\nconst AttributeDnd = ({\n column,\n index,\n isDisabled = false,\n isToggled,\n shouldDisableDrag,\n handleToggle,\n}: AttributeDndProps) => {\n const strings = usePDSStrings();\n return (\n <DndItemWrapper key={`${column.key}-${index}`}>\n <StyledIconDrag $active $shouldHide={shouldDisableDrag} />\n <OverflowText>\n <Paragraph color='primary' size='sm'>\n {column.label}\n </Paragraph>\n </OverflowText>\n <SuffixContainer>\n <Toggle\n value={isToggled}\n disabled={isDisabled}\n onChange={handleToggle}\n aria-label={\n isToggled ? strings.hideColumn(column.label) : strings.showColumn(column.label)\n }\n />\n </SuffixContainer>\n </DndItemWrapper>\n );\n};\n\nexport default TableViewConfigurationDropdown;\n","import { type ReactNode, createElement, createContext, useContext } from 'react';\n\nimport type { BaseActiveFilter, BaseFilterConfig } from './types';\n\nexport interface TableControlsContextProps<\n TFilter extends BaseFilterConfig = BaseFilterConfig,\n TActiveFilter extends BaseActiveFilter<TFilter> = BaseActiveFilter<TFilter>,\n> {\n filters: TFilter[];\n activeFilters: TActiveFilter[];\n setActiveFilters: (filters: TActiveFilter[]) => void;\n}\n\nconst TableControlsContext = createContext<TableControlsContextProps>({\n filters: [],\n activeFilters: [],\n setActiveFilters: () => {},\n});\n\nexport function useTableControls<\n TFilter extends BaseFilterConfig = BaseFilterConfig,\n TActiveFilter extends BaseActiveFilter<TFilter> = BaseActiveFilter<TFilter>,\n>(): TableControlsContextProps<TFilter, TActiveFilter> {\n return useContext(TableControlsContext) as unknown as TableControlsContextProps<\n TFilter,\n TActiveFilter\n >;\n}\n\nexport function TableControlsProvider<\n TFilter extends BaseFilterConfig = BaseFilterConfig,\n TActiveFilter extends BaseActiveFilter<TFilter> = BaseActiveFilter<TFilter>,\n>({\n children,\n ...value\n}: TableControlsContextProps<TFilter, TActiveFilter> & { children: ReactNode }) {\n return createElement(\n TableControlsContext.Provider,\n { value: value as unknown as TableControlsContextProps },\n children,\n );\n}\n\nexport default TableControlsContext;\n","import type { DateValue } from '@internationalized/date';\nimport type { RangeValue } from '@react-types/shared';\n\nimport type { DateFilterChange } from '@persona/design-system/components/DatePicker';\nimport type { DateFilterPreset } from '@persona/design-system/lib/date-filter';\n\ntype DateRuleIntent =\n | { kind: 'clear' }\n | { kind: 'absolute'; range: RangeValue<DateValue> }\n | { kind: 'relative'; preset: DateFilterPreset; range: RangeValue<DateValue> };\n\nexport function dateRuleIntent(change: DateFilterChange, writesEnabled: boolean): DateRuleIntent {\n if (change.source === 'clear') {\n return { kind: 'clear' };\n }\n if (change.source === 'calendar' || !writesEnabled) {\n return change.range == null ? { kind: 'clear' } : { kind: 'absolute', range: change.range };\n }\n return { kind: 'relative', preset: change.preset, range: change.range };\n}\n","import { DateTime, Settings } from 'luxon';\n\nimport type {\n DateRangeFilterValue,\n FilterField,\n FilterFieldType,\n FilterOperator,\n FilterRule,\n FilterRuleValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { DEFAULT_COMMON_STRINGS, type CommonStrings } from 'design-system/lib/i18n';\n\ntype OperatorLabelKey =\n | 'operatorIs'\n | 'operatorIsNot'\n | 'operatorContains'\n | 'operatorDoesNotContain'\n | 'operatorIsEmpty'\n | 'operatorIsNotEmpty'\n | 'operatorIsTrue'\n | 'operatorIsFalse'\n | 'operatorBefore'\n | 'operatorAfter'\n | 'operatorBetween'\n | 'operatorIsAnyOf'\n | 'operatorIsNoneOf'\n | 'operatorGreaterThan'\n | 'operatorGreaterThanOrEqual'\n | 'operatorLessThan'\n | 'operatorLessThanOrEqual'\n | 'operatorIsEqualTo'\n | 'operatorIsGreaterThan'\n | 'operatorIsLessThan';\n\n/**\n * Operator vocabulary per field type. The UI uses this to populate the\n * operator dropdown in the Filter popover and to gate which operators are\n * reachable for a given field. `is_empty` / `is_not_empty` apply broadly;\n * everything else is type-specific.\n *\n * The first entry for each type is the default operator selected when a\n * pill is created from the picker.\n */\nconst OPERATORS_BY_TYPE: Record<FilterFieldType, ReadonlyArray<FilterOperator>> = {\n string: ['is', 'is_not', 'contains', 'does_not_contain', 'is_empty', 'is_not_empty'],\n email: ['is', 'is_not', 'contains', 'does_not_contain', 'is_empty', 'is_not_empty'],\n choices: ['is', 'is_not', 'is_empty', 'is_not_empty'],\n multi_choices: ['is', 'is_not', 'is_empty', 'is_not_empty'],\n boolean: ['is'],\n integer: ['is', 'is_not', 'is_empty', 'is_not_empty'],\n float: ['is', 'is_not', 'is_empty', 'is_not_empty'],\n date: ['is', 'before', 'after', 'between', 'is_empty', 'is_not_empty'],\n array: ['contains', 'does_not_contain', 'is_empty', 'is_not_empty'],\n tags_conditions: ['is'],\n signals: ['is'],\n date_range: ['is'],\n};\n\n/**\n * Numeric comparison operators. Together with `is` (is equal to) they give\n * `integer` and `float` fields greater-than / less-than / equal-to filtering.\n * Inclusive bounds are deliberately not offered: \"at least 5\" is\n * `gt 5` OR `is 5`, built with the Rules editor.\n *\n * They are opt-in rather than part of the default numeric vocabulary above:\n * a host whose backend serializes them lists them in the field's\n * `allowedOperators` (e.g. `['is', ...NUMERIC_COMPARISON_OPERATORS]`).\n * Adding them to the default vocabulary would surface operators in every\n * existing numeric field whose host can't serialize them.\n */\nexport const NUMERIC_COMPARISON_OPERATORS = ['gt', 'lt'] as const;\n\nexport type NumericComparisonOperator = (typeof NUMERIC_COMPARISON_OPERATORS)[number];\n\nconst NUMERIC_COMPARISON_OPERATOR_SET: ReadonlySet<FilterOperator> = new Set(\n NUMERIC_COMPARISON_OPERATORS,\n);\n\nconst NUMERIC_FIELD_TYPES: ReadonlySet<FilterFieldType> = new Set(['integer', 'float']);\n\nexport function isNumericComparisonOperator(\n operator: FilterOperator,\n): operator is NumericComparisonOperator {\n return NUMERIC_COMPARISON_OPERATOR_SET.has(operator);\n}\n\n/**\n * Whether a comparison value is complete for a numeric field: a finite\n * number, and a safe integer when the field is an `integer`. Strings are\n * rejected — the numeric value controls always emit numbers, so a string\n * here is a corrupted or hand-crafted rule the backend can't compare.\n */\nexport function isCompleteNumericComparisonValue(\n value: FilterRuleValue,\n fieldType: FilterFieldType,\n): value is number {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n return false;\n }\n return fieldType === 'integer' ? Number.isSafeInteger(value) : true;\n}\n\n/**\n * Carry `value` into a numeric comparison. Equality rules on numeric fields\n * tolerate strings (v1 URLs hydrate `'5'`), but a comparison is only complete\n * with a number, so a numeric string is converted — truncated on `integer`\n * fields, matching what `IntegerValueControl` emits — and anything else\n * becomes an empty draft rather than a committed rule validation rejects.\n */\nfunction numericComparisonValue(\n value: FilterRuleValue,\n fieldType: FilterFieldType,\n): FilterRuleValue {\n const parsed =\n typeof value === 'number'\n ? value\n : typeof value === 'string' && value.trim() !== ''\n ? Number(value)\n : Number.NaN;\n if (!Number.isFinite(parsed)) {\n return '';\n }\n const normalized = fieldType === 'integer' ? Math.trunc(parsed) : parsed;\n return isCompleteNumericComparisonValue(normalized, fieldType) ? normalized : '';\n}\n\n/**\n * Whether `(fieldType, operator)` is a built-in numeric comparison — the\n * case validators and labels specialize. Comparisons on non-numeric types\n * (only reachable through `condition`) are not.\n */\nexport function isNumericComparison(\n operator: FilterOperator,\n fieldType: FilterFieldType | undefined,\n): boolean {\n return (\n fieldType != null && NUMERIC_FIELD_TYPES.has(fieldType) && isNumericComparisonOperator(operator)\n );\n}\n\n/** Operators that have no value control (the operator itself is the predicate). */\nconst VALUELESS_OPERATORS: ReadonlySet<FilterOperator> = new Set(['is_empty', 'is_not_empty']);\n\n/**\n * Operators whose value is a {@link DateRangeFilterValue} rather than the\n * scalar its field type would otherwise carry. The value control, the draft\n * seed, and every validator branch on this rather than on field type alone —\n * a `date` field carries an ISO day string for `is` / `before` / `after` and\n * a `{ startDate, endDate }` pair for `between`.\n */\nconst RANGE_OPERATORS: ReadonlySet<FilterOperator> = new Set(['between']);\nconst TIME_COMPONENT = /T\\d{2}:\\d{2}/;\n\nexport function getOperatorsForType(type: FilterFieldType): ReadonlyArray<FilterOperator> {\n return OPERATORS_BY_TYPE[type] ?? [];\n}\n\n/**\n * Effective operator vocabulary for a concrete field: its `allowedOperators`\n * allow-list, or the field type's full vocabulary when the allow-list is\n * absent or empty. An empty allow-list means \"unconstrained\" rather than\n * \"no operators\" — the latter would leave the field selectable in the picker\n * but incapable of producing a rule that passes validation.\n *\n * Prefer this over {@link getOperatorsForType} anywhere a real field is in\n * hand — the popover's operator dropdown, `FieldRegistry`, validation — so a\n * field can never surface an operator the host application can't serialize.\n */\nexport function getOperatorsForField(\n field: Pick<FilterField, 'type' | 'allowedOperators' | 'condition'>,\n): ReadonlyArray<FilterOperator> {\n if (field.condition != null) {\n return field.condition.operators.map(({ operator }) => operator);\n }\n const { allowedOperators } = field;\n if (allowedOperators == null || allowedOperators.length === 0) {\n return getOperatorsForType(field.type);\n }\n return allowedOperators;\n}\n\nexport function getDefaultOperatorForType(type: FilterFieldType): FilterOperator {\n const list = OPERATORS_BY_TYPE[type];\n if (list.length === 0) {\n throw new Error(`No operators defined for field type \"${type}\"`);\n }\n return list[0]!;\n}\n\nexport function getConditionOperator(\n field: Pick<FilterField, 'condition'> | undefined,\n operator: FilterOperator,\n) {\n return field?.condition?.operators.find((config) => config.operator === operator);\n}\n\nexport function isValuelessOperator(\n operator: FilterOperator,\n field?: Pick<FilterField, 'condition'>,\n): boolean {\n const config = getConditionOperator(field, operator);\n return config != null ? config.valueType === 'none' : VALUELESS_OPERATORS.has(operator);\n}\n\nexport function hasCompleteConditionValue(rule: FilterRule, field: FilterField): boolean {\n const config = getConditionOperator(field, rule.operator);\n if (config == null) {\n return false;\n }\n const { value } = rule;\n if (config.isComplete != null && !config.isComplete(value)) {\n return false;\n }\n switch (config.valueType) {\n case 'none':\n return value === null;\n case 'boolean':\n return typeof value === 'boolean';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value);\n case 'integer':\n return typeof value === 'number' && Number.isSafeInteger(value);\n case 'string':\n return typeof value === 'string' && value.length > 0;\n case 'string_array':\n return (\n Array.isArray(value) &&\n value.length > 0 &&\n value.every((entry) => typeof entry === 'string')\n );\n }\n}\n\n/**\n * Whether a rule's value is a date range: a range operator, or a field that is\n * one by type. Relative metadata only describes a range, so resolving or\n * labelling it on a scalar rule would put a `{ startDate, endDate }` object\n * where the wire expects a day string.\n */\nexport function carriesDateRange(operator: FilterOperator, fieldType?: FilterFieldType): boolean {\n return isRangeOperator(operator) || fieldType === 'date_range';\n}\n\n/**\n * Whether a rule's value control edits minute-precision date-times: the bar\n * and field both opt in, and the value is a range or a before/after instant\n * (`date` + `is` stays a whole calendar day).\n */\nexport function isMinutePrecisionDate(\n field: Pick<FilterField, 'type' | 'timeGranularity'>,\n operator: FilterOperator,\n dateTimesEnabled: boolean,\n): boolean {\n return (\n dateTimesEnabled &&\n field.timeGranularity === 'minute' &&\n (field.type === 'date_range' || (field.type === 'date' && operator !== 'is'))\n );\n}\n\nexport function isRangeOperator(operator: FilterOperator): boolean {\n return RANGE_OPERATORS.has(operator);\n}\n\n/**\n * Whether `value` carries both endpoints of a range. Shared by the pill,\n * the validators, and the serialize boundary so \"complete enough to send\"\n * has one definition.\n */\nexport function isCompleteDateRange(value: FilterRuleValue): value is DateRangeFilterValue {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) {\n return false;\n }\n const { startDate, endDate } = value as DateRangeFilterValue;\n return (\n typeof startDate === 'string' &&\n startDate.length > 0 &&\n typeof endDate === 'string' &&\n endDate.length > 0\n );\n}\n\n/**\n * Whether a concrete field's operator selector should be shown. A field\n * pinned to one operator renders it as static text rather than a caret that\n * opens a one-item menu.\n */\nexport function fieldHasMultipleOperators(\n field: Pick<FilterField, 'type' | 'allowedOperators' | 'condition'>,\n): boolean {\n return getOperatorsForField(field).length > 1;\n}\n\n/**\n * Human-readable operator labels for the operator dropdown and filled pill, as keys into the\n * translatable `CommonStrings` table (English defaults: \"is\", \"is not\", \"contains\", ...).\n */\nconst OPERATOR_LABEL_KEYS: Record<Exclude<FilterOperator, `custom:${string}`>, OperatorLabelKey> = {\n gt: 'operatorGreaterThan',\n gte: 'operatorGreaterThanOrEqual',\n lt: 'operatorLessThan',\n lte: 'operatorLessThanOrEqual',\n is: 'operatorIs',\n is_not: 'operatorIsNot',\n contains: 'operatorContains',\n does_not_contain: 'operatorDoesNotContain',\n is_empty: 'operatorIsEmpty',\n is_not_empty: 'operatorIsNotEmpty',\n is_true: 'operatorIsTrue',\n is_false: 'operatorIsFalse',\n before: 'operatorBefore',\n after: 'operatorAfter',\n between: 'operatorBetween',\n};\n\n/**\n * Field-type-specific label overrides. The operator vocabulary itself\n * stays unchanged (operator tokens are `is` / `is_not` across types), but\n * labels can be more specific where the generic label is ambiguous.\n *\n * Only present for `(fieldType, operator)` pairs that diverge from the\n * generic label; everything else falls through to `OPERATOR_LABEL_KEYS`.\n */\n/**\n * Numeric fields read as a sentence (\"Members is equal to 5\", \"Members is greater\n * than 5\") rather than the generic \"is\" / bare `>` labels. `is_not` keeps the\n * generic \"is not\".\n */\nconst NUMERIC_LABEL_KEYS: Partial<Record<FilterOperator, OperatorLabelKey>> = {\n is: 'operatorIsEqualTo',\n gt: 'operatorIsGreaterThan',\n lt: 'operatorIsLessThan',\n};\n\nconst OPERATOR_LABEL_KEYS_BY_TYPE: Partial<\n Record<FilterFieldType, Partial<Record<FilterOperator, OperatorLabelKey>>>\n> = {\n multi_choices: {\n is: 'operatorIsAnyOf',\n is_not: 'operatorIsNoneOf',\n },\n integer: NUMERIC_LABEL_KEYS,\n float: NUMERIC_LABEL_KEYS,\n};\n\n/**\n * The label for `operator`, specialized for `fieldType` where the generic label is ambiguous.\n * Pass `strings` from `usePDSStrings()` to translate it; English when omitted.\n */\nexport function getOperatorLabel(\n operator: FilterOperator,\n fieldType?: FilterFieldType,\n strings: Pick<CommonStrings, OperatorLabelKey> = DEFAULT_COMMON_STRINGS,\n field?: Pick<FilterField, 'condition'>,\n): string {\n const config = getConditionOperator(field, operator);\n if (config != null) {\n return config.label;\n }\n const key =\n (fieldType && OPERATOR_LABEL_KEYS_BY_TYPE[fieldType]?.[operator]) ||\n OPERATOR_LABEL_KEYS[operator as keyof typeof OPERATOR_LABEL_KEYS];\n return key != null ? strings[key] : operator;\n}\n\n/**\n * Return a copy of `rule` whose `value` honors the valueless-operator\n * invariant: any rule whose operator is in the valueless set\n * (`is_empty`, `is_not_empty`) carries `value: null`. Use this anywhere\n * a rule's value would otherwise drift out of sync with its operator —\n * operator-change handlers, field-swap handlers, and defensive coercions\n * before serialization.\n */\nexport function withValue(\n rule: FilterRule,\n value: FilterRuleValue,\n field?: Pick<FilterField, 'condition'>,\n): FilterRule {\n return {\n ...rule,\n value: isValuelessOperator(rule.operator, field) ? null : value,\n };\n}\n\n/**\n * Empty-but-present value seeded when a rule switches from a valueless operator\n * (`is_empty`) to one that requires a value. Non-null on purpose: a `null` value\n * reads as a removal and drops the pill mid-edit.\n */\nexport function emptyValueForFieldType(type: FilterFieldType): FilterRuleValue {\n switch (type) {\n case 'multi_choices':\n case 'tags_conditions':\n case 'signals':\n return [];\n default:\n return '';\n }\n}\n\n/**\n * Empty endpoints are written as `''` rather than omitted so the object still\n * reads as a date range after a JSON round-trip — `undefined` keys don't\n * survive `JSON.stringify`, and a bare `{}` is indistinguishable from a\n * corrupted value at the validation boundary.\n */\nfunction emptyDateRange(): DateRangeFilterValue {\n return { startDate: '', endDate: '' };\n}\n\n/**\n * Empty-but-present value for a concrete `(field, operator)` pair. Prefer this\n * over {@link emptyValueForFieldType} anywhere an operator is in hand: the same\n * `date` field seeds an empty string for `before` and an empty range for\n * `between`.\n */\nexport function emptyValueForRule(\n field: Pick<FilterField, 'type' | 'condition'>,\n operator: FilterOperator,\n): FilterRuleValue {\n if (isValuelessOperator(operator, field)) {\n return null;\n }\n const config = getConditionOperator(field, operator);\n if (config != null) {\n if (config.defaultValue != null) {\n return config.defaultValue;\n }\n switch (config.valueType) {\n case 'string_array':\n return [];\n case 'boolean':\n return true;\n default:\n return '';\n }\n }\n if (isRangeOperator(operator) || field.type === 'date_range') {\n return emptyDateRange();\n }\n return emptyValueForFieldType(field.type);\n}\n\n/**\n * Carry `value` across an operator change, replacing it with a fresh draft\n * when the two operators disagree about value shape. Switching a date pill\n * from `after` to `between` must not leave the old ISO day string behind —\n * the range control can't read it and the wire format would reject it.\n */\nexport function reconcileValueForOperator(\n field: Pick<FilterField, 'type' | 'condition'>,\n nextOperator: FilterOperator,\n previousOperator: FilterOperator,\n value: FilterRuleValue,\n): FilterRuleValue {\n if (isValuelessOperator(nextOperator, field)) {\n return null;\n }\n if (field.condition != null) {\n const nextType = getConditionOperator(field, nextOperator)?.valueType;\n const previousType = getConditionOperator(field, previousOperator)?.valueType;\n return nextType === previousType\n ? (value ?? emptyValueForRule(field, nextOperator))\n : emptyValueForRule(field, nextOperator);\n }\n if (isRangeOperator(nextOperator) !== isRangeOperator(previousOperator)) {\n return emptyValueForRule(field, nextOperator);\n }\n if (isNumericComparison(nextOperator, field.type)) {\n return numericComparisonValue(value, field.type);\n }\n if (\n field.type === 'date' &&\n nextOperator === 'is' &&\n typeof value === 'string' &&\n TIME_COMPONENT.test(value)\n ) {\n return DateTime.fromISO(value).setZone(Settings.defaultZone).toISODate();\n }\n if (\n field.type === 'date' &&\n (previousOperator === 'before' || previousOperator === 'after') &&\n (nextOperator === 'before' || nextOperator === 'after') &&\n previousOperator !== nextOperator &&\n typeof value === 'string' &&\n TIME_COMPONENT.test(value)\n ) {\n const dateTime = DateTime.fromISO(value, { setZone: true });\n return nextOperator === 'after'\n ? dateTime.set({ second: 0, millisecond: 0 }).toISO()\n : dateTime.set({ second: 59, millisecond: 999 }).toISO();\n }\n return value ?? emptyValueForRule(field, nextOperator);\n}\n","import { parseDateFilterValue, resolveDateFilterValue } from 'design-system/lib/date-filter';\n\nimport { carriesDateRange } from './operators';\nimport type { DateRangeFilterValue, FilterFieldType, FilterRule } from './types';\n\n/**\n * The absolute bounds a rule should be queried with, or `null` when it does not\n * carry a date range.\n *\n * Relative metadata wins over the stored snapshot: the snapshot is a picture of\n * the window when it was saved, and the point of a relative rule is that the\n * window moves. The operator gate is part of this rather than the caller's job —\n * metadata only ever describes a range, so resolving it onto a scalar rule\n * would put a `{ startDate, endDate }` object where the wire expects a day.\n */\nexport function resolveDateRangeRuleValue(\n rule: Pick<FilterRule, 'operator' | 'relativeDate' | 'value'>,\n fieldType?: FilterFieldType,\n): DateRangeFilterValue | null {\n if (!carriesDateRange(rule.operator, fieldType)) {\n return null;\n }\n const relative = parseDateFilterValue(rule.relativeDate);\n if (relative?.kind === 'relative') {\n return resolveDateFilterValue(relative);\n }\n const parsed = parseDateFilterValue(rule.value);\n return parsed ? resolveDateFilterValue(parsed) : null;\n}\n","import { DateTime, Settings } from 'luxon';\n\nimport { formatDateTime } from 'design-system/lib/i18n';\n\nconst TIME_COMPONENT = /T\\d{2}:\\d{2}/;\n\n/**\n * Display form of a minute-precision filter value (\"Oct 5, 2011 2:48 PM\"). Date-only values are\n * returned untouched. Pass the `PDSProvider` locale (`usePDSLocale()`) to follow it; omitted or\n * en-US keeps the English format.\n */\nexport function formatDateValueForDisplay(value: string, locale?: string): string {\n if (!TIME_COMPONENT.test(value)) {\n return value;\n }\n\n const dateTime = DateTime.fromISO(value).setZone(Settings.defaultZone);\n return dateTime.isValid ? formatDateTime(dateTime, { locale }) : value;\n}\n","import { formatDateFilterValue, parseDateFilterValue } from 'design-system/lib/date-filter/codec';\n\nimport { isCompleteDateRange } from './operators';\nimport type { FilterRule, FilterRuleValue } from './types';\n\n/**\n * The preset name a rule should display instead of its dates, or `undefined`\n * when it has none and the caller should fall back to rendering the value.\n *\n * Completeness is checked against the same predicate the serialize boundary\n * uses: labelling a rule `hasCompleteValue` drops would advertise a filter the\n * request never carries.\n */\nexport function relativePresetLabel(\n value: FilterRuleValue,\n relativeDate: FilterRule['relativeDate'],\n): string | undefined {\n const parsed = relativeDate ? parseDateFilterValue(relativeDate) : null;\n if (parsed?.kind !== 'relative' || !isCompleteDateRange(value)) {\n return undefined;\n }\n return formatDateFilterValue(parsed) ?? undefined;\n}\n","import { formatDateValueForDisplay } from 'design-system/components/DataTable/TableControls/FiltersV2/format-date-value';\nimport {\n emptyValueForFieldType,\n emptyValueForRule,\n isRangeOperator,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport { relativePresetLabel } from 'design-system/components/DataTable/TableControls/FiltersV2/relative-date-label';\nimport type {\n FilterField,\n FilterFieldType,\n FilterOperator,\n FilterRule,\n FilterRuleValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { DEFAULT_COMMON_STRINGS, type CommonStrings } from 'design-system/lib/i18n';\n\nexport interface ValueDisplayOptions {\n /** `PDSProvider` locale for date values; English format when omitted. */\n locale?: string;\n strings?: Pick<CommonStrings, 'booleanTrue' | 'booleanFalse'>;\n}\n\nexport function valueDisplayString(\n value: FilterRuleValue,\n optionLabels?: Record<string, string>,\n relativeDate?: FilterRule['relativeDate'],\n fieldType?: FilterFieldType,\n { locale, strings = DEFAULT_COMMON_STRINGS }: ValueDisplayOptions = {},\n): string | undefined {\n if (value == null) {\n return undefined;\n }\n const relativeLabel = relativePresetLabel(value, relativeDate);\n if (relativeLabel) {\n return relativeLabel;\n }\n\n const display = (raw: string): string =>\n optionLabels?.[raw] ??\n (fieldType === 'date' || fieldType === 'date_range'\n ? formatDateValueForDisplay(raw, locale)\n : raw);\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return undefined;\n }\n if (value.length === 1) {\n return display(String(value[0]));\n }\n return `${display(String(value[0]))} +${value.length - 1}`;\n }\n\n if (typeof value === 'boolean') {\n const label = value ? strings.booleanTrue : strings.booleanFalse;\n // The rules row has always shown the English literals as `true`/`false`; keep that for the\n // untranslated defaults, but show a host's translation exactly as the pill and control do.\n const englishLabel = value\n ? DEFAULT_COMMON_STRINGS.booleanTrue\n : DEFAULT_COMMON_STRINGS.booleanFalse;\n return label === englishLabel ? String(value) : label;\n }\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'string') {\n return value.length > 0 ? display(value) : undefined;\n }\n if (typeof value === 'object') {\n const { startDate, endDate } = value as { startDate?: string; endDate?: string };\n if (startDate && endDate) {\n return `${display(startDate)} – ${display(endDate)}`;\n }\n return startDate ? display(startDate) : endDate ? display(endDate) : undefined;\n }\n return undefined;\n}\n\nexport function draftValueFor(field: FilterField, operator: FilterOperator): FilterRuleValue {\n if (field.condition != null) {\n return emptyValueForRule(field, operator);\n }\n if (isValuelessOperator(operator)) {\n return null;\n }\n if (field.type === 'boolean') {\n return true;\n }\n if (isRangeOperator(operator)) {\n return emptyValueForRule(field, operator);\n }\n return emptyValueForFieldType(field.type);\n}\n","import { startCase } from 'lodash-es';\n\nimport type {\n ComboboxOption,\n ComboboxOptionGroup,\n ComboboxOptionsOrGroups,\n} from 'design-system/components/Combobox';\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport type { FilterField } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\n// Label for the single nested-navigation submenu that hosts every custom\n// field. The group has no value, so selecting it only navigates.\nexport const FIELDS_SUBMENU_LABEL = 'Fields';\n\ninterface FieldTreeNode {\n leaves: ComboboxOption<string>[];\n /** Keyed by raw path segment (`address`) so sibling subfields share a group. */\n groups: Map<string, FieldTreeNode>;\n /** Parent record types of every field beneath this node. */\n parents: Set<string>;\n}\n\nfunction newNode(): FieldTreeNode {\n return { leaves: [], groups: new Map(), parents: new Set() };\n}\n\n/**\n * The leaf `value` stays the full field id even when nested, so selection,\n * serialization, and persisted filter state are unaffected by the grouping.\n */\nfunction insertField(root: FieldTreeNode, field: FilterField, description: string | undefined) {\n const path = field.path && field.path.length > 1 ? field.path : null;\n if (!path) {\n root.leaves.push({ label: field.label, value: field.id, description });\n return;\n }\n\n let node = root;\n for (const segment of path.slice(0, -1)) {\n let child = node.groups.get(segment);\n if (!child) {\n child = newNode();\n node.groups.set(segment, child);\n }\n if (description != null) {\n child.parents.add(description);\n }\n node = child;\n }\n // A subfield's label is derived from the whole dotted key (\"Address city\"),\n // which reads as a stutter under an \"Address\" group — so the leaf is named\n // for its own segment. This does override a hand-written subfield label;\n // restoring those needs per-segment labels from the backend.\n node.leaves.push({ label: startCase(path[path.length - 1]), value: field.id, description });\n}\n\n/**\n * A group gets a parent-record-type sublabel only when every field beneath it\n * shares one — a segment reused across templates has no single owner to name.\n */\nfunction nodeToOptions(node: FieldTreeNode): ComboboxOptionsOrGroups<string> {\n const groups: ComboboxOptionGroup<string>[] = [];\n for (const [segment, child] of node.groups) {\n const [onlyParent] = child.parents;\n groups.push({\n label: startCase(segment),\n description: child.parents.size === 1 ? onlyParent : undefined,\n nested: true,\n options: nodeToOptions(child),\n });\n }\n return [...node.leaves, ...groups];\n}\n\n/**\n * Build the field-picker option tree shared by the `⊕ Filter` pill picker\n * (`FilterPickerMenu`) and the advanced-rules field dropdown\n * (`RuleEditorFields`) so both surface custom fields identically.\n *\n * System fields are top-level leaves; every custom field lives behind a\n * single `nested: true` \"Fields\" group, with its parent record type rendered\n * as the leaf's `description` sublabel. Hash subfields (fields whose backend\n * `path` has more than one segment, e.g. `address.city`) nest one level\n * deeper, behind their parent segment (`address`). The `nested`\n * flag is what makes the single-select Combobox render a group as an\n * expandable submenu — leaf selections commit via `onChange`, group descents\n * only navigate.\n *\n * `visibleCustomFieldParents`, when provided, narrows the Fields submenu to\n * only the listed parent record-type labels; passing an empty array hides the\n * submenu entirely. Omit it (or pass `undefined`) to show every group.\n *\n * `excludeFieldIds`, when provided, drops those fields from the tree.\n *\n * `fieldsLabel` names the custom-field submenu; pass `usePDSStrings().fields` to translate it.\n */\nexport function buildFieldPickerOptions(\n registry: FieldRegistry,\n visibleCustomFieldParents?: ReadonlyArray<string>,\n excludeFieldIds?: ReadonlyArray<string>,\n fieldsLabel: string = FIELDS_SUBMENU_LABEL,\n): ComboboxOptionsOrGroups<string> {\n const systemFields = registry\n .all()\n .filter((field) => field.source === 'system' || field.pickerGroup != null);\n const customGroups = registry.customFieldGroups();\n const excluded = excludeFieldIds == null ? null : new Set(excludeFieldIds);\n const tree: (ComboboxOption<string> | ComboboxOptionGroup<string>)[] = [];\n const pickerGroups = new Map<string, (ComboboxOption<string> | ComboboxOptionGroup<string>)[]>();\n for (const field of systemFields) {\n if (excluded?.has(field.id)) {\n continue;\n }\n const option = { label: field.label, value: field.id };\n if (field.pickerGroup == null) {\n tree.push(option);\n continue;\n }\n const options = pickerGroups.get(field.pickerGroup) ?? [];\n options.push(option);\n pickerGroups.set(field.pickerGroup, options);\n }\n for (const [label, options] of pickerGroups) {\n tree.push({ label, nested: true, options });\n }\n const allowedParents =\n visibleCustomFieldParents == null ? null : new Set(visibleCustomFieldParents);\n const customRoot = newNode();\n for (const group of customGroups) {\n if (allowedParents != null && !allowedParents.has(group.parent)) {\n continue;\n }\n const description = group.parent !== '' ? group.parent : undefined;\n for (const field of group.fields) {\n if (field.pickerGroup != null || excluded?.has(field.id)) {\n continue;\n }\n insertField(customRoot, field, description);\n }\n }\n const customOptions = nodeToOptions(customRoot);\n if (customOptions.length > 0) {\n const existingGroup = pickerGroups.get(fieldsLabel);\n if (existingGroup != null) {\n existingGroup.push(...customOptions);\n } else {\n tree.push({ label: fieldsLabel, nested: true, options: customOptions });\n }\n }\n return tree;\n}\n","import { type ReactNode, useCallback, useMemo } from 'react';\nimport styled from 'styled-components';\n\nimport type { ComboboxOption } from 'design-system/components/Combobox';\nimport { buildFieldPickerOptions } from 'design-system/components/DataTable/TableControls/FiltersV2/fieldPickerOptions';\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport {\n getOperatorLabel,\n isMinutePrecisionDate,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterOperator,\n FilterRule,\n FilterRuleValueChange,\n FilterRuleValue,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport FormField, { ComboboxField } from 'design-system/components/FormField';\nimport Input from 'design-system/components/Input';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { isDisabled, isHovered, isNotDisabled } from 'design-system/lib/pseudoClass';\n\ninterface RuleEditorFieldsProps {\n registry: FieldRegistry;\n dateTimesEnabled: boolean;\n field: FilterField | undefined;\n groupIndex: number;\n ruleIndex: number;\n rule: FilterRule;\n size: FilterSize;\n operators: ReadonlyArray<FilterOperator>;\n operatorConfigurable: boolean;\n onFieldChange: (groupIndex: number, ruleIndex: number, nextFieldId: string) => void;\n onOperatorChange: (groupIndex: number, ruleIndex: number, nextOperator: FilterOperator) => void;\n onValueChange: (\n groupIndex: number,\n ruleIndex: number,\n nextValue: FilterRuleValue,\n relativeDate?: FilterRule['relativeDate'] | null,\n ) => void;\n renderValueControl: (\n field: FilterField,\n operator: FilterOperator,\n value: FilterRuleValue,\n onChange: FilterRuleValueChange,\n relativeDate?: FilterRule['relativeDate'],\n ) => ReactNode;\n}\n\nconst StatementFields = styled.div`\n display: contents;\n\n && input,\n && input${isHovered}${isNotDisabled},\n && input${isDisabled},\n && [role='group'],\n && [role='group']${isHovered}${isNotDisabled},\n && [role='group']${isDisabled} {\n background: transparent;\n }\n`;\n\nexport default function RuleEditorFields({\n registry,\n dateTimesEnabled,\n field,\n groupIndex,\n ruleIndex,\n rule,\n size,\n operators,\n operatorConfigurable,\n onFieldChange,\n onOperatorChange,\n onValueChange,\n renderValueControl,\n}: RuleEditorFieldsProps) {\n const strings = usePDSStrings();\n const minutePrecisionValue =\n field != null && isMinutePrecisionDate(field, rule.operator, dateTimesEnabled);\n\n // Same nested \"Fields\" submenu the `⊕ Filter` pill picker uses, for parity.\n const fieldOptions = useMemo(\n () => buildFieldPickerOptions(registry, undefined, undefined, strings.fields),\n [registry, strings.fields],\n );\n const optionDisabledReason = useCallback(\n (option: ComboboxOption<string>) => registry.get(option.value)?.disabledReason,\n [registry],\n );\n const operatorOptions = useMemo(\n () =>\n operators.map((operator) => ({\n label: getOperatorLabel(operator, field?.type, strings, field),\n value: operator,\n })),\n [operators, field, strings],\n );\n const handleFieldChange = useCallback(\n (next: string | null) => {\n if (next != null && registry.get(next)?.disabledReason == null) {\n onFieldChange(groupIndex, ruleIndex, next);\n }\n },\n [registry, onFieldChange, groupIndex, ruleIndex],\n );\n const handleOperatorChange = useCallback(\n (next: string | null) => {\n if (next != null) {\n onOperatorChange(groupIndex, ruleIndex, next as FilterOperator);\n }\n },\n [onOperatorChange, groupIndex, ruleIndex],\n );\n const handleValueChange = useCallback<FilterRuleValueChange>(\n (next, relativeDate) => onValueChange(groupIndex, ruleIndex, next, relativeDate),\n [onValueChange, groupIndex, ruleIndex],\n );\n return (\n <StatementFields>\n <ComboboxField\n label={strings.field}\n labelProps={{ size }}\n aria-label={strings.fieldForRule(ruleIndex + 1, groupIndex + 1)}\n size={size}\n options={fieldOptions}\n optionDisabledReason={optionDisabledReason}\n value={rule.fieldId}\n onChange={handleFieldChange}\n placeholder={strings.selectField}\n portal={false}\n />\n {operatorConfigurable ? (\n <ComboboxField\n label={strings.operator}\n labelProps={{ size }}\n aria-label={strings.operatorForRule(ruleIndex + 1, groupIndex + 1)}\n size={size}\n options={operatorOptions}\n value={rule.operator}\n onChange={handleOperatorChange}\n portal={false}\n />\n ) : (\n <FormField label={strings.operator} labelProps={{ size }}>\n <Input\n size={size}\n aria-label={strings.operatorForRule(ruleIndex + 1, groupIndex + 1)}\n value={getOperatorLabel(rule.operator, field?.type, strings, field)}\n disabled\n readOnly\n />\n </FormField>\n )}\n {field && !isValuelessOperator(rule.operator, field) ? (\n <FormField\n label={strings.value}\n labelProps={{ size }}\n configField={minutePrecisionValue ? false : undefined}\n >\n <>\n {renderValueControl(\n field,\n rule.operator,\n rule.value,\n handleValueChange,\n rule.relativeDate,\n )}\n </>\n </FormField>\n ) : null}\n </StatementFields>\n );\n}\n","import type { ReactNode } from 'react';\n\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport {\n carriesDateRange,\n fieldHasMultipleOperators,\n getOperatorLabel,\n getOperatorsForField,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterOperator,\n FilterRule,\n FilterRuleValueChange,\n FilterRuleValue,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport ListBox from 'design-system/components/ListBox';\nimport { usePDSLocale, usePDSStrings } from 'design-system/lib/i18n';\n\nimport { valueDisplayString } from './display';\nimport RuleEditorFields from './RuleEditorFields';\n\ninterface AdvancedFilterRuleRowProps {\n registry: FieldRegistry;\n dateTimesEnabled: boolean;\n groupIndex: number;\n ruleIndex: number;\n rule: FilterRule;\n size: FilterSize;\n isOpen: boolean;\n onClose: () => void;\n onDelete: () => void;\n onFieldChange: (groupIndex: number, ruleIndex: number, nextFieldId: string) => void;\n onOperatorChange: (groupIndex: number, ruleIndex: number, nextOperator: FilterOperator) => void;\n onValueChange: (\n groupIndex: number,\n ruleIndex: number,\n nextValue: FilterRuleValue,\n relativeDate?: FilterRule['relativeDate'] | null,\n ) => void;\n renderValueControl: (\n field: FilterField,\n operator: FilterOperator,\n value: FilterRuleValue,\n onChange: FilterRuleValueChange,\n relativeDate?: FilterRule['relativeDate'],\n ) => ReactNode;\n}\n\nexport default function AdvancedFilterRuleRow({\n registry,\n dateTimesEnabled,\n groupIndex,\n ruleIndex,\n rule,\n size,\n isOpen,\n onClose,\n onDelete,\n onFieldChange,\n onOperatorChange,\n onValueChange,\n renderValueControl,\n}: AdvancedFilterRuleRowProps) {\n const strings = usePDSStrings();\n const locale = usePDSLocale();\n const field = registry.get(rule.fieldId);\n const operators = field ? getOperatorsForField(field) : ([] as ReadonlyArray<FilterOperator>);\n const operatorConfigurable = field ? fieldHasMultipleOperators(field) : true;\n const condition = ruleIndex === 0 ? strings.conditionIf : strings.conditionAnd;\n const rowId = `${groupIndex}-${ruleIndex}`;\n const valueDisplay = isValuelessOperator(rule.operator, field)\n ? undefined\n : valueDisplayString(\n rule.value,\n registry.optionLabelsFor(rule.fieldId),\n carriesDateRange(rule.operator, field?.type) ? rule.relativeDate : undefined,\n field?.type,\n { locale, strings },\n );\n const textValue = [\n condition,\n field?.label ?? rule.fieldId,\n getOperatorLabel(rule.operator, field?.type, strings, field),\n valueDisplay,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <ListBox.LogicRow\n id={rowId}\n condition={condition}\n hideCondition\n attributeName={field?.label ?? rule.fieldId}\n operator={getOperatorLabel(rule.operator, field?.type, strings, field)}\n matchLevelName={valueDisplay}\n textValue={textValue}\n size={size}\n onClick={() => {\n if (isOpen) {\n onClose();\n }\n }}\n onDelete={onDelete}\n dropdownHeadingText={strings.editStatement(condition)}\n dropdownFormFields={\n <RuleEditorFields\n registry={registry}\n dateTimesEnabled={dateTimesEnabled}\n field={field}\n groupIndex={groupIndex}\n ruleIndex={ruleIndex}\n rule={rule}\n size={size}\n operators={operators}\n operatorConfigurable={operatorConfigurable}\n onFieldChange={onFieldChange}\n onOperatorChange={onOperatorChange}\n onValueChange={onValueChange}\n renderValueControl={renderValueControl}\n />\n }\n />\n );\n}\n","import type {\n AndGroup,\n CompoundExpression,\n FilterRule,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\nfunction withGroup(\n compound: CompoundExpression,\n index: number,\n group: AndGroup,\n): CompoundExpression {\n const groups = [...compound.groups];\n groups[index] = group;\n return { groups };\n}\n\nexport function addRuleToGroup(\n compound: CompoundExpression,\n groupIndex: number,\n rule: FilterRule,\n): CompoundExpression {\n const groups = [...compound.groups];\n while (groups.length <= groupIndex) {\n groups.push({ rules: [] });\n }\n groups[groupIndex] = { rules: [...groups[groupIndex]!.rules, rule] };\n return { groups };\n}\n\nexport function setRuleInGroup(\n compound: CompoundExpression,\n groupIndex: number,\n ruleIndex: number,\n rule: FilterRule,\n): CompoundExpression {\n const group = compound.groups[groupIndex];\n if (!group || ruleIndex < 0 || ruleIndex >= group.rules.length) {\n return compound;\n }\n const rules = [...group.rules];\n rules[ruleIndex] = rule;\n return withGroup(compound, groupIndex, { rules });\n}\n\nexport function removeRuleFromGroup(\n compound: CompoundExpression,\n groupIndex: number,\n ruleIndex: number,\n): CompoundExpression {\n const group = compound.groups[groupIndex];\n if (!group || ruleIndex < 0 || ruleIndex >= group.rules.length) {\n return compound;\n }\n const rules = group.rules.filter((_, i) => i !== ruleIndex);\n if (rules.length === 0) {\n return { groups: compound.groups.filter((_, i) => i !== groupIndex) };\n }\n return withGroup(compound, groupIndex, { rules });\n}\n","import { useEffect, useRef, useState } from 'react';\n\ninterface UseRulesPopoverSelectionOptions {\n isOpen: boolean;\n}\n\nexport function useRulesPopoverSelection({ isOpen }: UseRulesPopoverSelectionOptions) {\n const [selectedRowKey, setSelectedRowKey] = useState<string | null>(null);\n const popoverContentRef = useRef<HTMLDivElement>(null);\n const lastPointerDownTargetRef = useRef<Node | null>(null);\n\n useEffect(() => {\n if (!isOpen && selectedRowKey != null) {\n setSelectedRowKey(null);\n }\n }, [isOpen, selectedRowKey]);\n\n useEffect(() => {\n const onPointerDown = (event: MouseEvent) => {\n lastPointerDownTargetRef.current = event.target as Node | null;\n };\n document.addEventListener('mousedown', onPointerDown, true);\n return () => document.removeEventListener('mousedown', onPointerDown, true);\n }, []);\n\n const closeSelectedRow = () => setSelectedRowKey(null);\n\n const handleGroupSelectionChange = (keys: Set<unknown> | 'all') => {\n const next = keys instanceof Set ? ((Array.from(keys)[0] as string | undefined) ?? null) : null;\n\n if (next == null) {\n const target = lastPointerDownTargetRef.current;\n if (target && popoverContentRef.current?.contains(target)) {\n closeSelectedRow();\n }\n return;\n }\n\n setSelectedRowKey(next);\n };\n\n const selectedKeysForGroup = (groupIndex: number): Set<string> => {\n return selectedRowKey != null && selectedRowKey.startsWith(`${groupIndex}-`)\n ? new Set([selectedRowKey])\n : new Set<string>();\n };\n\n return {\n selectedRowKey,\n setSelectedRowKey,\n closeSelectedRow,\n popoverContentRef,\n handleGroupSelectionChange,\n selectedKeysForGroup,\n };\n}\n","import { createContext, useContext } from 'react';\n\nimport type { FilterSize } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\nexport interface FilterBarContextValue {\n size: FilterSize;\n}\n\n/**\n * Context for FilterBar-wide rendering settings. It currently carries\n * only `size`, but the object shape leaves room for future bar-level\n * settings without introducing another provider.\n */\nexport const FilterBarContext = createContext<FilterBarContextValue>({ size: 'sm' });\n\n/**\n * Resolve the active filter-bar size, honoring an explicit prop\n * override before falling back to the surrounding `FilterBarContext`.\n * Pattern is the same as the design-system FormControl size hook —\n * components accept an optional `size` prop that wins, otherwise\n * follow the ambient context.\n */\nexport function useFilterBarSize(override?: FilterSize): FilterSize {\n const { size } = useContext(FilterBarContext);\n return override ?? size;\n}\n\n/**\n * Dimensional tokens for each filter-bar size variant. Co-locating the\n * pixel values here keeps the per-component styled primitives free of\n * magic numbers and ensures both variants stay in lockstep across the\n * Filter UI v2 family of components.\n *\n * Current size contract:\n * sm → 12px font, 12px icons, 24px controls, 18px chip\n * md → 14px font, 16px icons, 32px controls, 24px chip\n *\n * These values stay centralized here so subcomponents do not duplicate\n * hardcoded dimensions.\n */\nexport interface FilterSizeTokens {\n /** Height of pills, the picker trigger, and other \"control\" surfaces. */\n controlHeight: string;\n /** Height of value chips embedded in pills (proportional to controlHeight). */\n chipHeight: string;\n /** Base font size for pill labels, header text, and option rows. */\n fontSize: string;\n /** Line height paired with `fontSize`. */\n lineHeight: string;\n /** Glyph size for caret/dismiss icons inside pills. */\n iconSize: string;\n}\n\nexport const FILTER_SIZE_TOKENS: Record<FilterSize, FilterSizeTokens> = {\n sm: {\n controlHeight: '24px',\n chipHeight: '18px',\n fontSize: '12px',\n lineHeight: '18px',\n iconSize: '12px',\n },\n md: {\n controlHeight: '32px',\n chipHeight: '24px',\n fontSize: '14px',\n lineHeight: '22px',\n iconSize: '16px',\n },\n};\n\n/** Convenience accessor — returns the token bundle for the resolved size. */\nexport function useFilterSizeTokens(override?: FilterSize): FilterSizeTokens {\n const size = useFilterBarSize(override);\n return FILTER_SIZE_TOKENS[size];\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { uniqueId } from 'lodash-es';\nimport { Fragment, type ReactElement, type ReactNode, useCallback, useMemo, useState } from 'react';\nimport styled from 'styled-components';\n\nimport { BorderRadius, Color, Spacing } from '@persona/design-tokens';\nimport { PlusIcon } from '@persona/icons';\nimport { MoreIcon, PlusIcon as SmallPlusIcon } from '@persona/icons/12px';\nimport Button, { IconButton } from 'design-system/components/Button';\nimport Card from 'design-system/components/Card';\nimport AdvancedFilterRuleRow from 'design-system/components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRuleRow';\nimport {\n addRuleToGroup,\n removeRuleFromGroup,\n setRuleInGroup,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/compound-expression';\nimport { draftValueFor } from 'design-system/components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/display';\nimport { useRulesPopoverSelection } from 'design-system/components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/use-rules-popover-selection';\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport {\n FILTER_SIZE_TOKENS,\n useFilterBarSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { reconcileValueForOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n CompoundExpression,\n FilterField,\n FilterOperator,\n FilterRule,\n FilterRuleValueChange,\n FilterRuleValue,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport DropdownMenu from 'design-system/components/DropdownMenu';\nimport ListBox from 'design-system/components/ListBox';\nimport { Paragraph } from 'design-system/components/Text';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { letPointerDownReachDocument } from 'design-system/lib/letPointerDownReachDocument';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport { Z_INDICES } from 'design-system/lib/zindex';\nimport { semanticScrollbar } from 'design-system/mixins/scrollbar';\n\nexport interface AdvancedFilterRulesPopoverProps {\n registry: FieldRegistry;\n dateTimesEnabled?: boolean;\n compound: CompoundExpression;\n onChange: (next: CompoundExpression) => void;\n /**\n * Trigger element supplied by parent (typically a ref-forwarding\n * `<RulesPill>`). Radix `Popover.Trigger asChild` injects trigger props\n * and a ref into this element, so callers should pass a native element\n * or a ref-forwarding component.\n */\n trigger: ReactElement;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /**\n * Size variant. Defaults to whatever the surrounding\n * `FilterBarContext` provides (`'sm'` outside a `FilterBar`).\n */\n size?: FilterSize;\n /**\n * Slot renderer parents use to plug type-aware value controls into\n * the row dropdown when a rule is being edited. Required — every\n * production caller routes through `resolveValueControl` from\n * `FilterBar/value-control-resolver.tsx`. Storybook stories that\n * exercise this component in isolation should pass a story-local\n * stub.\n */\n renderValueControl: (\n field: FilterField,\n operator: FilterOperator,\n value: FilterRuleValue,\n onChange: FilterRuleValueChange,\n relativeDate?: FilterRule['relativeDate'],\n ) => ReactNode;\n}\n\n// ---------------------------------------------------------------------------\n// Layout primitives for the Rules popover.\n// ---------------------------------------------------------------------------\n\n// Use the design system's `Z_INDICES.modalDropdown` (10010) for the\n// popover surface so it always renders above the table layout and the\n// nested LogicRow row dropdowns that themselves use `modalDropdown`\n// through `AdvancedFilterRuleRow`.\nconst PopoverContent = styled(PopoverPrimitive.Content)`\n z-index: ${Z_INDICES.modalDropdown};\n`;\n\n// Minute-precision ranges put two date-time fields side by side in a\n// full-width value row, which needs the wider card.\nconst PopoverCard = styled(Card)<{ $wide: boolean }>`\n width: ${({ $wide }) => ($wide ? '520px' : '384px')};\n max-width: calc(100vw - ${Spacing[4]});\n margin-bottom: 0;\n\n && {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n }\n`;\n\nconst Header = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: ${Spacing[3]};\n`;\n\nconst Body = styled.div`\n display: flex;\n flex-direction: column;\n gap: ${Spacing[2]};\n padding: 0 ${Spacing[3]} ${Spacing[3]};\n max-height: 60vh;\n overflow-y: auto;\n ${semanticScrollbar}\n`;\n\n/**\n * Bordered container that wraps a single AndGroup. Visually mirrors the\n * `TableBox` shell (1px BorderDivider + BorderRadius.Md) but is built\n * standalone here because the rows inside are `LogicRow`s, which depend\n * on a parent `ListBox` rather than `TableBox`. Each group owns its\n * \"If\" / \"Or\" title and rule actions in the card header.\n */\nconst GroupCard = styled.div`\n display: flex;\n flex-direction: column;\n border: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n border-radius: ${BorderRadius.Md};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfacePrimary', Color.BackgroundPrimary)};\n overflow: hidden;\n`;\n\nconst GroupHeader = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: ${Spacing[1]} ${Spacing[2]};\n border-bottom: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n background-color: ${({ theme }) => semanticColor(theme, 'SurfaceSecondary', Color.BackgroundSecondary)};\n`;\n\nconst GroupTitle = styled.span<{ $size: FilterSize }>`\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n`;\n\nconst GroupHeaderActions = styled.div`\n display: inline-flex;\n align-items: center;\n gap: ${Spacing[1]};\n`;\n\nconst GroupActionsMenu = styled(DropdownMenu)`\n && {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n }\n`;\n\n/**\n * A focused-down `ListBox` for the rules in one AndGroup. Strips the\n * default 204px width AND the standalone border (the parent `GroupCard`\n * supplies the border now). Removes the per-listbox padding so the row\n * cells sit flush against the card.\n */\nconst RulesListBox = styled(ListBox)`\n width: 100%;\n border: 0;\n border-radius: 0;\n padding: 0;\n` as typeof ListBox;\n\n/**\n * \"Or group\" affordance that appears between consecutive groups and at\n * the bottom of the popover. Adds a new empty `AndGroup` at the end of\n * `compound.groups` when clicked.\n */\nconst OrGroupRow = styled.div`\n display: flex;\n`;\n\n/**\n * Pure helper that returns the groups to render — always at least one,\n * so the popover shows the \"If\" group chrome (header + add-rule button)\n * even when no rules exist yet. The `synthetic` flag tells the render\n * loop whether the \"Delete group\" action is a no-op (synthetic → close\n * the popover) or a real state mutation (real → drop the group from\n * `compound.groups`).\n *\n * Encoding the placeholder here keeps the JSX map clean: callers don't\n * branch inline on `compound.groups.length === 0`, and the special\n * case is one named function instead of an inline conditional.\n */\ninterface RenderableGroup {\n rules: ReadonlyArray<FilterRule>;\n /** True for the synthetic placeholder when `compound.groups` is empty. */\n synthetic: boolean;\n}\n\nfunction groupsForRender(compound: CompoundExpression): ReadonlyArray<RenderableGroup> {\n if (compound.groups.length === 0) {\n return [{ rules: [], synthetic: true }];\n }\n return compound.groups.map((g) => ({ rules: g.rules, synthetic: false }));\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\n/**\n * DNF (OR-of-AND) editor popover for the compound expression owned by the\n * Rules pill.\n *\n * The popover is fully controlled by `compound` + `onChange` — it never\n * holds compound state internally so parents can persist edits incrementally\n * (URL state, saved-view dual-write, etc.). `open` / `onOpenChange` are\n * optional; when omitted the popover manages its own open state and is\n * opened by clicking the parent-supplied trigger.\n *\n * Each AndGroup's rules are rendered as a `<ListBox>` of `<LogicRow>` items.\n * The collapsed row reads `[If/And] [field-sticker] [operator] [value-sticker]`\n * inline; clicking a row reveals the field/operator/value editor inside the\n * row's dropdown popover.\n */\nconst AdvancedFilterRulesPopover = ({\n registry,\n compound,\n onChange,\n trigger,\n open,\n onOpenChange,\n renderValueControl,\n size,\n dateTimesEnabled = false,\n}: AdvancedFilterRulesPopoverProps) => {\n const strings = usePDSStrings();\n const resolvedSize = useFilterBarSize(size);\n const subtleIconSize: 'xs' | 'sm' = resolvedSize === 'sm' ? 'xs' : 'sm';\n // Sized from the registry rather than the open rule so the card doesn't\n // jump width as rules change.\n const wide = useMemo(\n () => dateTimesEnabled && registry.all().some((field) => field.timeGranularity === 'minute'),\n [registry, dateTimesEnabled],\n );\n const [internalOpen, setInternalOpen] = useState(false);\n const isControlled = open != null;\n const isOpen = isControlled ? open : internalOpen;\n const {\n selectedRowKey,\n setSelectedRowKey,\n closeSelectedRow,\n popoverContentRef,\n handleGroupSelectionChange,\n selectedKeysForGroup,\n } = useRulesPopoverSelection({ isOpen });\n const handleOpenChange = useCallback(\n (next: boolean) => {\n if (!isControlled) {\n setInternalOpen(next);\n }\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n const baseId = useMemo(() => uniqueId('advanced-filter-rules__'), []);\n\n const fields = useMemo(\n () => registry.all().filter((field) => field.disabledReason == null),\n [registry],\n );\n\n const handleAddOrGroup = useCallback(() => {\n const firstField = fields[0];\n if (!firstField) {\n return;\n }\n const operator =\n firstField.condition != null\n ? registry.defaultOperatorFor(firstField.id)\n : registry.reconcileOperator(firstField.id, 'is');\n const groupIndex = compound.groups.length;\n onChange(\n addRuleToGroup(compound, groupIndex, {\n fieldId: firstField.id,\n operator,\n value: draftValueFor(firstField, operator),\n }),\n );\n setSelectedRowKey(`${groupIndex}-0`);\n }, [compound, fields, onChange, registry]);\n\n const handleAddRuleToGroup = useCallback(\n (groupIndex: number) => {\n const firstField = fields[0];\n if (!firstField) {\n return;\n }\n const operator =\n firstField.condition != null\n ? registry.defaultOperatorFor(firstField.id)\n : registry.reconcileOperator(firstField.id, 'is');\n // The new rule lands at the end of the existing rules array; its\n // row id is `${groupIndex}-${prevLength}`. Selecting it drives the\n // LogicRow's dropdown open via the controlled `selectedKeys` so the\n // user can edit the rule immediately, no extra row click needed.\n const newRuleIndex = compound.groups[groupIndex]?.rules.length ?? 0;\n const newRowId = `${groupIndex}-${newRuleIndex}`;\n onChange(\n addRuleToGroup(compound, groupIndex, {\n fieldId: firstField.id,\n operator,\n value: draftValueFor(firstField, operator),\n }),\n );\n setSelectedRowKey(newRowId);\n },\n [compound, fields, onChange, registry],\n );\n\n // Thin wrapper around `onChange` kept for symmetry with the existing\n // delete-group / delete-rule paths. We used to also close the popover\n // when the mutation emptied the compound, but the popover now always\n // renders a synthetic \"If\" group with the empty state inside, so an\n // empty compound is a valid resting state and shouldn't dismiss.\n const applyCompoundChange = useCallback(\n (next: CompoundExpression) => {\n onChange(next);\n },\n [onChange],\n );\n\n const handleRemoveRule = useCallback(\n (groupIndex: number, ruleIndex: number) => {\n applyCompoundChange(removeRuleFromGroup(compound, groupIndex, ruleIndex));\n },\n [compound, applyCompoundChange],\n );\n\n const handleFieldChange = useCallback(\n (groupIndex: number, ruleIndex: number, nextFieldId: string) => {\n const field = registry.get(nextFieldId);\n if (!field || field.disabledReason != null) {\n return;\n }\n const prev = compound.groups[groupIndex]?.rules[ruleIndex];\n if (!prev) {\n return;\n }\n const operator = registry.reconcileOperator(field.id, prev.operator);\n onChange(\n setRuleInGroup(compound, groupIndex, ruleIndex, {\n fieldId: nextFieldId,\n operator,\n value: draftValueFor(field, operator),\n }),\n );\n },\n [compound, onChange, registry],\n );\n\n const handleOperatorChange = useCallback(\n (groupIndex: number, ruleIndex: number, nextOperator: FilterOperator) => {\n const prev = compound.groups[groupIndex]?.rules[ruleIndex];\n if (!prev) {\n return;\n }\n const field = registry.get(prev.fieldId);\n onChange(\n setRuleInGroup(compound, groupIndex, ruleIndex, {\n fieldId: prev.fieldId,\n operator: nextOperator,\n // Drop the value when the next operator can't carry it — a\n // valueless operator, or a range/scalar shape change — so we don't\n // leak stale text into the wire payload.\n value: field\n ? reconcileValueForOperator(field, nextOperator, prev.operator, prev.value)\n : null,\n }),\n );\n },\n [compound, onChange, registry],\n );\n\n const handleValueChange = useCallback(\n (\n groupIndex: number,\n ruleIndex: number,\n nextValue: FilterRuleValue,\n relativeDate?: FilterRule['relativeDate'] | null,\n ) => {\n const prev = compound.groups[groupIndex]?.rules[ruleIndex];\n if (!prev) {\n return;\n }\n const { relativeDate: _previousRelativeDate, ...rest } = prev;\n onChange(\n setRuleInGroup(compound, groupIndex, ruleIndex, {\n ...rest,\n value: nextValue,\n ...(relativeDate ? { relativeDate } : {}),\n }),\n );\n },\n [compound, onChange],\n );\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={handleOpenChange}>\n <PopoverPrimitive.Trigger asChild>{trigger}</PopoverPrimitive.Trigger>\n <PopoverPrimitive.Portal>\n <PopoverContent\n align='start'\n sideOffset={8}\n collisionPadding={8}\n role='dialog'\n aria-label={strings.advancedFilterRules}\n id={baseId}\n onPointerDownCapture={letPointerDownReachDocument}\n ref={popoverContentRef}\n // `tabIndex={-1}` so we can programmatically focus the\n // popover surface after closing a row dropdown — without it,\n // `element.focus()` is a no-op on a non-tabbable div.\n tabIndex={-1}\n // Enter inside the rules popover commits one step of the\n // edit-cancel-out dance:\n // 1. If a LogicRow dropdown is open, Enter closes it\n // (final-select commit / typed-value commit). After\n // closing, focus is re-pointed at the popover surface —\n // otherwise Radix's auto-focus-on-close returns focus\n // to the row trigger, and the next Enter re-selects the\n // row (re-opening the dropdown) via react-aria's\n // GridListItem keyboard handler.\n // 2. After (1), pressing Enter again while focus is on the\n // popover surface closes the rules popover itself\n // (\"done editing rules\"). Enter on any inner button /\n // menu item / select trigger is intentionally left alone\n // so those controls activate normally — e.g. the\n // GroupCard `+` IconButton's Enter adds a new logic row.\n // The handler runs in the BUBBLE phase so inner Selects /\n // Comboboxes get to commit their own selection on Enter first;\n // we only close once the bubbled Enter reaches the popover.\n onKeyDown={(event) => {\n if (event.key !== 'Enter') {\n return;\n }\n if (selectedRowKey != null) {\n event.preventDefault();\n requestAnimationFrame(() => {\n closeSelectedRow();\n requestAnimationFrame(() => {\n popoverContentRef.current?.focus();\n });\n });\n return;\n }\n // Only the surface-Enter case: focus is on the popover\n // content itself (i.e., we re-pointed it there above).\n // If focus is on an inner control — `+` IconButton, the\n // `…` group actions menu, the `Or group` button, etc. —\n // leave the event alone so the control fires its own\n // onClick / onSelect via the native Enter semantics.\n if (event.target !== popoverContentRef.current) {\n return;\n }\n event.preventDefault();\n handleOpenChange(false);\n }}\n >\n <PopoverCard elevated $wide={wide}>\n <Header>\n <Paragraph size={resolvedSize} color='secondary'>\n {strings.advancedFilterRules}\n </Paragraph>\n </Header>\n\n <Body>\n {groupsForRender(compound).map((group, groupIndex, renderableGroups) => {\n const isFirstGroup = groupIndex === 0;\n const groupTitle = isFirstGroup ? strings.conditionIf : strings.conditionOr;\n const isSynthetic = group.synthetic;\n const isOnlyGroup = renderableGroups.length === 1;\n const isEmptyGroup = group.rules.length === 0;\n // Hide the group overflow menu when the only available\n // action would be deleting an already-empty group.\n const hideGroupMenu = isOnlyGroup && isEmptyGroup;\n // When this is the sole (first & only) group and it has\n // rules, \"Delete group\" really clears every active rule —\n // relabel it \"Clear all\" to match what it does.\n const deleteGroupLabel =\n isOnlyGroup && !isEmptyGroup ? strings.clearAll : strings.deleteGroup;\n return (\n <Fragment key={`${baseId}__group-${groupIndex}`}>\n <GroupCard\n data-test={`advanced-filter-rules__group-${groupIndex}`}\n role='group'\n aria-label={strings.filterGroup(groupIndex + 1)}\n >\n <GroupHeader>\n <GroupTitle $size={resolvedSize}>{groupTitle}</GroupTitle>\n <GroupHeaderActions>\n {hideGroupMenu ? null : (\n <GroupActionsMenu\n trigger={\n <IconButton\n size={subtleIconSize}\n aria-label={strings.moreActionsForFilterGroup(groupIndex + 1)}\n data-test={`advanced-filter-rules__group-more-${groupIndex}`}\n >\n <MoreIcon />\n </IconButton>\n }\n align='end'\n portal\n // Keep this portal above the rules popover and\n // aligned with ListBox row dropdowns.\n zIndex={Z_INDICES.modalDropdown}\n >\n <DropdownMenu.Item\n size={resolvedSize}\n onClick={() => {\n if (isSynthetic) {\n // Nothing to remove from state — just\n // close the popover so the user gets the\n // resting Rules pill back.\n handleOpenChange(false);\n return;\n }\n applyCompoundChange({\n groups: compound.groups.filter((_, i) => i !== groupIndex),\n });\n }}\n data-test={`advanced-filter-rules__delete-group-${groupIndex}`}\n >\n {deleteGroupLabel}\n </DropdownMenu.Item>\n </GroupActionsMenu>\n )}\n <IconButton\n size={subtleIconSize}\n disabled={fields.length === 0}\n onClick={() => handleAddRuleToGroup(groupIndex)}\n aria-label={strings.addRuleToFilterGroup(groupIndex + 1)}\n data-test={`advanced-filter-rules__add-rule-${groupIndex}`}\n >\n <SmallPlusIcon />\n </IconButton>\n </GroupHeaderActions>\n </GroupHeader>\n {group.rules.length === 0 ? (\n <Paragraph\n size={resolvedSize}\n color='secondary'\n style={{ padding: Spacing[2] }}\n >\n {strings.noRulesYet}\n </Paragraph>\n ) : (\n <RulesListBox\n aria-label={strings.rulesInGroup(groupIndex + 1)}\n selectionMode='single'\n size={resolvedSize}\n fullWidth\n selectedKeys={selectedKeysForGroup(groupIndex)}\n onSelectionChange={handleGroupSelectionChange}\n >\n {group.rules.map((rule, ruleIndex) => {\n const rowId = `${groupIndex}-${ruleIndex}`;\n return (\n <AdvancedFilterRuleRow\n key={rowId}\n registry={registry}\n dateTimesEnabled={dateTimesEnabled}\n groupIndex={groupIndex}\n ruleIndex={ruleIndex}\n rule={rule}\n size={resolvedSize}\n isOpen={selectedRowKey === rowId}\n onClose={closeSelectedRow}\n onDelete={() => handleRemoveRule(groupIndex, ruleIndex)}\n onFieldChange={handleFieldChange}\n onOperatorChange={handleOperatorChange}\n onValueChange={handleValueChange}\n renderValueControl={renderValueControl}\n />\n );\n })}\n </RulesListBox>\n )}\n </GroupCard>\n </Fragment>\n );\n })}\n\n <OrGroupRow>\n <Button\n variant='basic'\n size={resolvedSize}\n width='auto'\n prefixIcon={<PlusIcon />}\n onClick={handleAddOrGroup}\n disabled={fields.length === 0}\n data-test='advanced-filter-rules__add-or-group'\n >\n {strings.orGroup}\n </Button>\n </OrGroupRow>\n </Body>\n </PopoverCard>\n </PopoverContent>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n );\n};\n\nexport default AdvancedFilterRulesPopover;\n","import { useCallback, useEffect, useState } from 'react';\n\nimport Combobox from 'design-system/components/Combobox';\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { FilterRuleValue } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport Input from 'design-system/components/Input';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nexport type ArrayValueControlProps = ValueControlProps;\n\nconst stringDisplayValue = (value: FilterRuleValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' && Number.isFinite(value)) {\n return String(value);\n }\n return '';\n};\n\nconst stringValue = (value: FilterRuleValue): string | null => {\n if (typeof value === 'string' && value !== '') {\n return value;\n }\n if (typeof value === 'number' && Number.isFinite(value)) {\n return String(value);\n }\n return null;\n};\n\n/**\n * Array-typed value control for the Filter UI v2 popover.\n *\n * Used for `array` fields with operators `contains` / `does_not_contain`.\n * The popover renders nothing when the operator is valueless\n * (`is_empty` / `is_not_empty`).\n *\n * The rendered control depends on the inner item type advertised by the\n * field's `itemType`:\n *\n * - `'choices'` → single-select Combobox sourced from `field.options`.\n * - `'string'` or unset → free-text input (a single value to test for\n * membership against the array column).\n *\n * Output value is always a single string; an empty text input emits `''`, not\n * `null`, because the pill lifecycle reads a `null` value on a value-requiring\n * operator as a removal and drops the pill. `''` keeps the pill as a visible\n * draft; the serialize boundary is what filters incomplete values out of the\n * request. The predicate is \"does this array contain (or not contain) this\n * scalar?\", so we never produce an array-of-values from this control.\n */\nexport const ArrayValueControl = ({\n field,\n operator,\n value,\n onChange,\n onCommit,\n ariaLabel,\n layout = 'popover',\n}: ArrayValueControlProps) => {\n const strings = usePDSStrings();\n const size = useFilterBarSize();\n const [localValue, setLocalValue] = useState<string>(() => stringDisplayValue(value));\n\n useEffect(() => {\n setLocalValue(stringDisplayValue(value));\n }, [value]);\n\n const handleTextChange = useCallback(\n (raw: string) => {\n setLocalValue(raw);\n onChange(raw);\n },\n [onChange],\n );\n\n const handleComboboxChange = useCallback(\n (next: string | null) => {\n onChange(next ?? null);\n // A choice selection is a complete, one-action edit — commit it so\n // the host `FilterPopover` closes (mirrors `ChoicesValueControl`).\n // No-op in the Advanced Rules `inline` layout, which omits `onCommit`.\n onCommit?.();\n },\n [onChange, onCommit],\n );\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n const label = ariaLabel ?? strings.fieldValue(field.label);\n const itemType = field.itemType ?? 'string';\n\n if (itemType === 'choices') {\n const options = field.options ?? [];\n return (\n <Combobox<string>\n aria-label={label}\n options={options.map((opt) => ({ label: opt.label, value: opt.value }))}\n value={stringValue(value)}\n onChange={handleComboboxChange}\n placeholder={strings.selectAnOptionPlaceholder}\n size={size}\n embedded={layout === 'popover'}\n />\n );\n }\n\n return (\n <Input\n type='text'\n size={size}\n placeholder={strings.enterAValue}\n aria-label={label}\n value={localValue}\n onChange={(e) => handleTextChange(e.target.value)}\n />\n );\n};\n\nexport default ArrayValueControl;\n","import styled from 'styled-components';\n\nimport { BorderRadius, Color, Spacing, Typography } from '@persona/design-tokens';\nimport { CheckIcon } from '@persona/icons';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nexport type BooleanValueControlProps = ValueControlProps;\n\nconst OPTIONS: ReadonlyArray<{ labelKey: 'booleanTrue' | 'booleanFalse'; value: boolean }> = [\n { labelKey: 'booleanTrue', value: true },\n { labelKey: 'booleanFalse', value: false },\n];\n\nconst Row = styled.button<{ $selected: boolean }>`\n ${Typography.TextSmall};\n display: flex;\n align-items: center;\n justify-content: space-between;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: ${Spacing[1]} ${Spacing[2]};\n border: none;\n appearance: none;\n border-radius: ${BorderRadius.Sm};\n background: ${({ theme, $selected }) =>\n $selected ? semanticColor(theme, 'SurfaceAccentStatic', Color.CorePurple100) : 'transparent'};\n color: ${({ theme, $selected }) =>\n $selected\n ? semanticColor(theme, 'FgAccentStatic', Color.TextActive)\n : semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n font-family: inherit;\n text-align: left;\n cursor: pointer;\n\n &:hover {\n background: ${({ theme, $selected }) =>\n $selected\n ? semanticColor(theme, 'SurfaceAccentStatic', Color.CorePurple100)\n : semanticColor(theme, 'ActionNeutral', Color.BackgroundSecondary)};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => semanticColor(theme, 'BorderFocus', Color.BorderFocus)};\n outline-offset: 1px;\n }\n\n svg {\n flex-shrink: 0;\n color: inherit;\n }\n`;\n\nconst Root = styled.div`\n display: flex;\n flex-direction: column;\n gap: ${Spacing[0]};\n`;\n\n/**\n * Filter UI v2 — boolean value picker for `boolean`-typed fields with `is` /\n * `is_not` operators. Renders two rows (True / False); the selected row uses\n * the same purple treatment as other filter value selections. Renders nothing\n * for valueless operators (`is_empty`, `is_not_empty`).\n */\nexport default function BooleanValueControl({\n operator,\n value,\n onChange,\n ariaLabel,\n}: BooleanValueControlProps) {\n const strings = usePDSStrings();\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n const selected = typeof value === 'boolean' ? value : null;\n\n return (\n <Root role='radiogroup' aria-label={ariaLabel ?? strings.booleanValue}>\n {OPTIONS.map((opt) => {\n const isSelected = selected === opt.value;\n return (\n <Row\n key={String(opt.value)}\n type='button'\n role='radio'\n aria-checked={isSelected}\n $selected={isSelected}\n onClick={() => onChange(opt.value)}\n >\n {strings[opt.labelKey]}\n {isSelected ? <CheckIcon aria-hidden /> : null}\n </Row>\n );\n })}\n </Root>\n );\n}\n","import { uniqueId } from 'lodash-es';\nimport { useMemo } from 'react';\n\nimport Combobox from 'design-system/components/Combobox';\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nconst EMPTY_OPTIONS: ReadonlyArray<{ label: string; value: string }> = [];\nconst EMPTY_VALUES: string[] = [];\n\nexport interface ChoicesValueControlProps extends ValueControlProps {\n /**\n * When `true`, renders a multi-select combobox backed by an array value\n * (`multi_choices`-typed fields). When `false`/omitted, renders a\n * single-select combobox backed by a string value (`choices`-typed fields).\n */\n multiple?: boolean;\n}\n\n/**\n * Filter UI v2 — value control for `choices` / `multi_choices`-typed fields.\n *\n * Backed by the design-system `Combobox`. In single-select mode the value is a\n * string; in `multiple` mode it is an array of strings. Options come from\n * `field.options` (populated by `FieldRegistry` from the backend's\n * `field_key_to_info` payload). Renders nothing when the active operator is\n * valueless (e.g. `is_empty`).\n */\nexport default function ChoicesValueControl({\n field,\n operator,\n value,\n onChange,\n onCommit,\n ariaLabel,\n trigger,\n layout = 'popover',\n multiple = false,\n}: ChoicesValueControlProps) {\n const strings = usePDSStrings();\n const generatedId = useMemo(\n () => uniqueId(multiple ? 'filter_v2_multi_choices_' : 'filter_v2_choices_'),\n [multiple],\n );\n const size = useFilterBarSize();\n\n const options = field.options ?? EMPTY_OPTIONS;\n\n const values = useMemo<string[]>(\n () => (Array.isArray(value) ? [...value] : EMPTY_VALUES),\n [value],\n );\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n const useEmbeddedCombobox = layout === 'popover' && trigger == null;\n\n if (multiple) {\n return (\n <Combobox<string>\n id={generatedId}\n size={size}\n aria-label={ariaLabel ?? field.label}\n placeholder={field.label}\n searchPlaceholder={strings.searchPlaceholder}\n emptyStateMessage={strings.noMatches}\n options={options}\n values={values}\n trigger={trigger}\n // Multi-select stays open across toggles — committing (which closes\n // the popover) on each option click would defeat picking several\n // values. The popover closes when the user dismisses it (pill click\n // / click-outside), not on selection. Single-select commits on pick.\n onValuesChange={onChange}\n embedded={useEmbeddedCombobox}\n multiple\n truncate\n // Keep options in a fixed order. By default selected options float to\n // the top, so toggling a value mid-edit shifts the rows under the\n // pointer — clicking the 2nd of 3 selected values makes the 3rd look\n // removed. Stable order avoids that jump.\n stableOptionOrder\n />\n );\n }\n\n return (\n <Combobox<string>\n id={generatedId}\n size={size}\n aria-label={ariaLabel ?? field.label}\n placeholder={field.label}\n options={options}\n value={typeof value === 'string' ? value : null}\n trigger={trigger}\n onChange={(next) => {\n onChange(next ?? null);\n onCommit?.();\n }}\n embedded={useEmbeddedCombobox}\n />\n );\n}\n","import { type DateValue, parseDate, toCalendarDate, toZoned } from '@internationalized/date';\nimport type { RangeValue } from '@react-types/shared';\nimport { DateTime, Settings } from 'luxon';\nimport { type ReactElement, useCallback, useMemo } from 'react';\n\nimport {\n type DateFilterChange,\n DateRangePicker,\n type DateRange,\n type DateRangePickerProps,\n} from '@persona/design-system/components/DatePicker';\nimport {\n parseDateFilterValue,\n resolveDateFilterValue,\n selectedPresetFor,\n} from '@persona/design-system/lib/date-filter';\nimport { Z_INDICES } from '@persona/design-system/lib/zindex';\nimport { dateRuleIntent } from 'design-system/components/DataTable/TableControls/FiltersV2/date-rule-intent';\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { FilterRuleValue } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nexport interface DateRangeValueControlProps\n extends\n ValueControlProps,\n Pick<DateRangePickerProps, 'hidePresets' | 'portalContainer' | 'visibleMonths'> {\n relativeDatesEnabled?: boolean;\n dateTimesEnabled?: boolean;\n}\n\nconst CALENDAR_DATE = /^(\\d{4}-\\d{2}-\\d{2})/;\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst parseIsoDate = (value: string | undefined): DateTime | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n // Keep the written calendar day; fromISO would shift timestamp-shaped values by zone.\n const calendarDay = CALENDAR_DATE.exec(value)?.[1];\n if (calendarDay == null) {\n return undefined;\n }\n try {\n const parsed = parseDate(calendarDay);\n return DateTime.fromObject({\n year: parsed.year,\n month: parsed.month,\n day: parsed.day,\n });\n } catch {\n return undefined;\n }\n};\n\nconst parseIsoDateTime = (\n value: string | undefined,\n endpoint: 'start' | 'end',\n): DateTime | undefined => {\n if (typeof value !== 'string') {\n return undefined;\n }\n const dateTime = DateTime.fromISO(\n value,\n DATE_ONLY.test(value) ? { zone: Settings.defaultZone } : {},\n ).setZone(Settings.defaultZone);\n if (!dateTime.isValid) {\n return undefined;\n }\n return DATE_ONLY.test(value)\n ? dateTime[endpoint === 'start' ? 'startOf' : 'endOf']('day')\n : dateTime;\n};\n\nconst useDateRange = (\n value: FilterRuleValue,\n relativeDate: DateRangeValueControlProps['relativeDate'],\n minuteMode: boolean,\n): DateRange => {\n const parsedRelativeDate = parseDateFilterValue(relativeDate);\n const parsed =\n parsedRelativeDate?.kind === 'relative' ? parsedRelativeDate : parseDateFilterValue(value);\n const resolved = parsed ? resolveDateFilterValue(parsed) : undefined;\n const isRelative = parsed?.kind === 'relative';\n const nowMinuteMillis =\n minuteMode && isRelative\n ? DateTime.now().setZone(Settings.defaultZone).set({ second: 0, millisecond: 0 }).toMillis()\n : undefined;\n return useMemo(() => {\n const startDate = minuteMode\n ? parseIsoDateTime(resolved?.startDate, 'start')\n : parseIsoDate(resolved?.startDate);\n let endDate = minuteMode\n ? parseIsoDateTime(resolved?.endDate, 'end')\n : parseIsoDate(resolved?.endDate);\n\n if (minuteMode && isRelative && endDate && nowMinuteMillis !== undefined) {\n const now = DateTime.fromMillis(nowMinuteMillis, { zone: Settings.defaultZone });\n if (endDate.toMillis() > now.toMillis()) {\n endDate = now;\n }\n }\n\n return { startDate, endDate };\n }, [isRelative, minuteMode, nowMinuteMillis, resolved?.startDate, resolved?.endDate]);\n};\n\nexport const DateRangeValueControl = ({\n field,\n operator,\n value,\n relativeDate,\n onChange,\n ariaLabel,\n hidePresets,\n portalContainer,\n visibleMonths,\n relativeDatesEnabled = false,\n dateTimesEnabled = false,\n}: DateRangeValueControlProps): ReactElement | null => {\n const strings = usePDSStrings();\n const size = useFilterBarSize();\n const minuteMode = dateTimesEnabled && field.timeGranularity === 'minute';\n const dateRange = useDateRange(value, relativeDate, minuteMode);\n // The picker also echoes prop syncs through onChange; only this callback is\n // limited to interactions, and the rule's relative metadata turns on that.\n const noopChange = useCallback(() => undefined, []);\n const handleChange = useCallback(\n (range: RangeValue<DateValue> | null) => {\n if (!range?.start || !range.end || range.start.compare(range.end) > 0) {\n onChange(null);\n return;\n }\n if (!minuteMode) {\n onChange({\n startDate: range.start.toString(),\n endDate: range.end.toString(),\n });\n return;\n }\n const zone = Settings.defaultZone.name;\n const toDateTime = (date: DateValue) =>\n DateTime.fromJSDate(toZoned(date, zone).toDate(), { zone });\n const startDate = toDateTime(range.start).set({ second: 0, millisecond: 0 });\n const endDate = toDateTime(range.end).set({ second: 59, millisecond: 999 });\n if (!startDate.isValid || !endDate.isValid) {\n onChange(null);\n return;\n }\n const startIso = startDate.toISO();\n const endIso = endDate.toISO();\n onChange(startIso && endIso ? { startDate: startIso, endDate: endIso } : null);\n },\n [minuteMode, onChange],\n );\n const handleDateFilterChange = useCallback(\n (change: DateFilterChange) => {\n const intent = dateRuleIntent(change, relativeDatesEnabled);\n if (intent.kind === 'clear') {\n handleChange(null);\n return;\n }\n if (intent.kind === 'absolute') {\n handleChange(intent.range);\n return;\n }\n onChange(\n {\n startDate: toCalendarDate(intent.range.start).toString(),\n endDate: toCalendarDate(intent.range.end).toString(),\n },\n { kind: 'relative', preset: intent.preset },\n );\n },\n [handleChange, onChange, relativeDatesEnabled],\n );\n const parsedRelativeDate = parseDateFilterValue(relativeDate);\n const relativePreset = selectedPresetFor(parsedRelativeDate, relativeDatesEnabled);\n const hasDayEdgeBounds =\n dateRange.startDate !== undefined &&\n dateRange.endDate !== undefined &&\n dateRange.startDate.toMillis() === dateRange.startDate.startOf('day').toMillis() &&\n dateRange.endDate.toMillis() === dateRange.endDate.endOf('day').toMillis();\n const selectedPreset =\n minuteMode && relativePreset === undefined && !hasDayEdgeBounds ? null : relativePreset;\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n // DateRangePicker keeps its last range when endpoints go missing; remount to clear.\n const hasCompleteRange = dateRange.startDate != null && dateRange.endDate != null;\n\n return (\n <DateRangePicker\n key={hasCompleteRange ? 'range' : 'empty'}\n aria-label={ariaLabel ?? strings.fieldValue(field.label)}\n calendarZIndex={Z_INDICES.modalDropdown}\n dateRange={dateRange}\n hidePresets={hidePresets}\n label={null}\n onChange={noopChange}\n onDateFilterChange={handleDateFilterChange}\n selectedPreset={selectedPreset}\n portalContainer={portalContainer}\n showClear={false}\n size={size}\n visibleMonths={visibleMonths}\n granularity={minuteMode ? 'minute' : 'day'}\n hideTimeZone={!minuteMode}\n />\n );\n};\n\nexport default DateRangeValueControl;\n","import {\n type DateValue,\n parseAbsolute,\n parseDate,\n toCalendarDate,\n toZoned,\n} from '@internationalized/date';\nimport { DateTime, Settings } from 'luxon';\nimport { useCallback } from 'react';\n\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport {\n isMinutePrecisionDate,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterRuleValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport DatePicker from 'design-system/components/DatePicker';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nexport interface DateValueControlProps extends ValueControlProps {\n dateTimesEnabled?: boolean;\n}\n\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\nconst parseIsoDate = (\n value: FilterRuleValue,\n field: FilterField,\n operator: string,\n dateTimesEnabled: boolean,\n): DateValue | null => {\n if (typeof value !== 'string') {\n return null;\n }\n try {\n if (isMinutePrecisionDate(field, operator, dateTimesEnabled)) {\n if (DATE_ONLY.test(value)) {\n const dateTime = DateTime.fromISO(value, { zone: Settings.defaultZone });\n const boundary = operator === 'after' ? dateTime.startOf('day') : dateTime.endOf('day');\n const iso = boundary.toISO();\n return iso ? parseAbsolute(iso, Settings.defaultZone.name) : null;\n }\n return parseAbsolute(value, Settings.defaultZone.name);\n }\n return DATE_ONLY.test(value)\n ? parseDate(value)\n : toCalendarDate(parseAbsolute(value, Settings.defaultZone.name));\n } catch {\n return null;\n }\n};\n\n/**\n * Single-date value control for the Filter UI v2 popover.\n *\n * Used for `date` fields with operators `is` / `before` / `after`. The\n * popover renders nothing when the selected operator is valueless\n * (`is_empty` / `is_not_empty`) — those operators are themselves the\n * predicate and need no companion value.\n *\n * Before/after values may use minute-precision ISO instants when the field\n * and bar both opt in; other date values remain `YYYY-MM-DD`.\n */\nexport const DateValueControl = ({\n field,\n operator,\n value,\n onChange,\n ariaLabel,\n dateTimesEnabled = false,\n}: DateValueControlProps) => {\n const strings = usePDSStrings();\n const size = useFilterBarSize();\n const minuteMode = isMinutePrecisionDate(field, operator, dateTimesEnabled);\n const handleChange = useCallback(\n (nextDate: DateValue | null) => {\n if (!nextDate || !minuteMode) {\n onChange(nextDate ? nextDate.toString() : null);\n return;\n }\n const zone = Settings.defaultZone.name;\n const dateTime = DateTime.fromJSDate(toZoned(nextDate, zone).toDate(), { zone });\n const boundary =\n operator === 'after'\n ? dateTime.set({ second: 0, millisecond: 0 })\n : dateTime.set({ second: 59, millisecond: 999 });\n onChange(boundary.toISO() ?? null);\n },\n [minuteMode, onChange, operator],\n );\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n const dateValue = parseIsoDate(value, field, operator, dateTimesEnabled);\n const label = ariaLabel ?? strings.fieldValue(field.label);\n\n return (\n <DatePicker\n value={dateValue}\n size={size}\n aria-label={label}\n onChange={handleChange}\n granularity={minuteMode ? 'minute' : 'day'}\n // `useModalZIndex` switches the calendar popover from\n // `Z_INDICES.dropdown` (1001) to `Z_INDICES.modalDropdown`\n // (10010). The LogicRow row dropdown that hosts this control\n // sits at `modalDropdown`, so without this the calendar\n // renders behind the row dropdown when opened.\n useModalZIndex\n />\n );\n};\n\nexport default DateValueControl;\n","import type { FilterRuleValue } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\n/**\n * Debounce window (ms) shared by the input-backed value controls\n * (`IntegerValueControl`, `FloatValueControl`) so they commit `onChange`\n * on the same cadence. Mirrors the V1 `InputFilter` 300ms pattern.\n */\nexport const DEBOUNCE_MS = 300;\n\n/**\n * Coerce a `FilterRuleValue` into a string suitable for an `<input>`'s\n * `value` prop. Used by `IntegerValueControl` and `FloatValueControl` so\n * both share identical display-coercion semantics — without this, drift\n * (e.g. different handling of `''`) would let the two controls disagree\n * about how to render the same hydrated rule.\n *\n * `Number.isFinite` rules out `NaN` / `±Infinity` (a hydrated state that\n * round-tripped through JSON should never carry those, but the guard is\n * cheap defense). Empty strings collapse to `''` rather than falling\n * through to `'undefined'` / `'null'` if the rule arrives in a malformed\n * shape.\n */\nexport function numericDisplayValue(value: FilterRuleValue): string {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === 'string' && value !== '') {\n return value;\n }\n return '';\n}\n","import { debounce } from 'lodash-es';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport {\n DEBOUNCE_MS,\n numericDisplayValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/utils';\nimport Input from 'design-system/components/Input';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nexport type FloatValueControlProps = ValueControlProps;\n\n/**\n * Float-typed value control for the Filter UI v2 popover.\n *\n * Used for `float` fields with operators `is` / `is_not`, and with the\n * opt-in comparisons `gt` / `lt` when the field's\n * `allowedOperators` lists them — all carry a single number. The popover\n * renders nothing when the operator is valueless (`is_empty` /\n * `is_not_empty`). Range operators are not part of the numeric vocabulary.\n *\n * The control accepts decimal input and emits a `number` via `onChange`.\n * We keep local display state as a string so partial input like `\"3.\"` is\n * preserved while the user types; the emitted numeric value is only updated\n * once the input parses to a finite number.\n *\n * `isFocused` ref guards the external-value sync effect: typing a\n * mid-decimal value like `\"3.\"` parses to `3` and emits it, which\n * round-trips back through the controlled `value` prop. Without the\n * guard, the sync effect would rewrite the display from `\"3.\"` to\n * `\"3\"` and the next keystroke (`\"7\"`) would land at the wrong cursor\n * position. The blur handler resyncs the display so any half-typed\n * string that never parsed (`\"-\"`, `\".\"`) renders as whatever the\n * rule actually carries when focus leaves.\n *\n * `onChange` is debounced (300ms) to avoid committing on every keystroke;\n * the debounce flushes on blur or Enter and cancels on unmount.\n */\nexport const FloatValueControl = ({\n field,\n operator,\n value,\n onChange,\n ariaLabel,\n}: FloatValueControlProps) => {\n const strings = usePDSStrings();\n const size = useFilterBarSize();\n const [localValue, setLocalValue] = useState<string>(() => numericDisplayValue(value));\n const isFocusedRef = useRef(false);\n\n const debouncedOnChange = useMemo(() => debounce(onChange, DEBOUNCE_MS), [onChange]);\n\n useEffect(() => {\n const cancelPendingChange = () => {\n debouncedOnChange.cancel();\n };\n return cancelPendingChange;\n }, [debouncedOnChange]);\n\n useEffect(() => {\n if (isFocusedRef.current) {\n return;\n }\n setLocalValue(numericDisplayValue(value));\n }, [value]);\n\n const handleChange = useCallback(\n (raw: string) => {\n setLocalValue(raw);\n if (raw === '' || raw === '-' || raw === '.') {\n debouncedOnChange(null);\n return;\n }\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) {\n return;\n }\n debouncedOnChange(parsed);\n },\n [debouncedOnChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter' && !event.defaultPrevented && !event.nativeEvent.isComposing) {\n debouncedOnChange.flush();\n }\n },\n [debouncedOnChange],\n );\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n return (\n <Input\n type='number'\n size={size}\n step='any'\n inputMode='decimal'\n placeholder={strings.enterANumber}\n aria-label={ariaLabel ?? strings.fieldValue(field.label)}\n value={localValue}\n onChange={(e) => handleChange(e.target.value)}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n isFocusedRef.current = true;\n }}\n onBlur={() => {\n isFocusedRef.current = false;\n debouncedOnChange.flush();\n setLocalValue(numericDisplayValue(value));\n }}\n />\n );\n};\n\nexport default FloatValueControl;\n","import { debounce } from 'lodash-es';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport {\n DEBOUNCE_MS,\n numericDisplayValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/utils';\nimport Input from 'design-system/components/Input';\nimport { usePDSStrings } from 'design-system/lib/i18n';\n\nexport type IntegerValueControlProps = ValueControlProps;\n\n/**\n * Integer-typed value control for the Filter UI v2 popover.\n *\n * Used for `integer` fields with operators `is` / `is_not`, and with the\n * opt-in comparisons `gt` / `lt` when the field's\n * `allowedOperators` lists them — all carry a single number. The popover\n * renders nothing when the operator is valueless (`is_empty` /\n * `is_not_empty`). Range operators are not part of the numeric vocabulary.\n *\n * The control accepts any numeric input but always emits an integer via\n * `onChange`. We truncate (rather than round) so that typing `3` -> `3.` -> `3.7`\n * does not jump to `4` mid-typing; the wire-format value follows `parseInt`\n * semantics, matching common backend integer-coercion behavior.\n *\n * `isFocused` ref guards the external-value sync effect: while the user\n * is actively typing, an external value change (which we ourselves\n * triggered by emitting `onChange`) must NOT clobber the local display\n * string. Without this guard, typing `3` -> emits `3` -> external value\n * becomes `3` -> the sync effect resets local back to `'3'`, which\n * looks fine until you type `-` to clear and the sync races against\n * the user's next keystroke.\n *\n * `onChange` is debounced (300ms) to avoid committing on every keystroke;\n * the debounce flushes on blur or Enter and cancels on unmount.\n */\nexport const IntegerValueControl = ({\n field,\n operator,\n value,\n onChange,\n ariaLabel,\n}: IntegerValueControlProps) => {\n const strings = usePDSStrings();\n const size = useFilterBarSize();\n const [localValue, setLocalValue] = useState<string>(() => numericDisplayValue(value));\n const isFocusedRef = useRef(false);\n\n const debouncedOnChange = useMemo(() => debounce(onChange, DEBOUNCE_MS), [onChange]);\n\n useEffect(() => {\n const cancelPendingChange = () => {\n debouncedOnChange.cancel();\n };\n return cancelPendingChange;\n }, [debouncedOnChange]);\n\n useEffect(() => {\n if (isFocusedRef.current) {\n return;\n }\n setLocalValue(numericDisplayValue(value));\n }, [value]);\n\n const handleChange = useCallback(\n (raw: string) => {\n setLocalValue(raw);\n if (raw === '' || raw === '-') {\n debouncedOnChange(null);\n return;\n }\n const parsed = Number(raw);\n if (!Number.isFinite(parsed)) {\n return;\n }\n debouncedOnChange(Math.trunc(parsed));\n },\n [debouncedOnChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === 'Enter' && !event.defaultPrevented && !event.nativeEvent.isComposing) {\n debouncedOnChange.flush();\n }\n },\n [debouncedOnChange],\n );\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n return (\n <Input\n type='number'\n size={size}\n step={1}\n inputMode='numeric'\n placeholder={strings.enterANumber}\n aria-label={ariaLabel ?? strings.fieldValue(field.label)}\n value={localValue}\n onChange={(e) => handleChange(e.target.value)}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n isFocusedRef.current = true;\n }}\n onBlur={() => {\n isFocusedRef.current = false;\n debouncedOnChange.flush();\n setLocalValue(numericDisplayValue(value));\n }}\n />\n );\n};\n\nexport default IntegerValueControl;\n","import { debounce, uniqueId } from 'lodash-es';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type { ValueControlProps } from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/types';\nimport Input from 'design-system/components/Input';\n\nconst DEBOUNCE_MS = 300;\n\n/**\n * Filter UI v2 — text input value control for `string` and `email`\n * fields. The component picks the `<input type>` from `field.type`\n * (`'email'` for email fields, otherwise the explicit `inputType`\n * override or `'text'`).\n *\n * Mirrors the V1 `InputFilter`'s debounce-300ms pattern: the input\n * mirrors keystrokes immediately but the rule's `onChange` only fires\n * once typing settles. Renders nothing when the active operator is\n * valueless (e.g. `is_empty`) — the operator alone is the predicate.\n */\nexport interface StringValueControlProps extends ValueControlProps {\n /**\n * Override the `<input type>` attribute. When omitted, the control\n * picks `'email'` for email fields and `'text'` for everything else.\n */\n inputType?: string;\n /** Override the placeholder. Defaults to the field label. */\n placeholder?: string;\n /** Override the generated DOM id. */\n id?: string;\n}\n\nexport default function StringValueControl({\n field,\n operator,\n value,\n onChange,\n ariaLabel,\n inputType,\n placeholder,\n id,\n}: StringValueControlProps) {\n const generatedId = useMemo(() => uniqueId('filter_v2_string_'), []);\n const inputId = id ?? generatedId;\n const resolvedInputType = inputType ?? (field.type === 'email' ? 'email' : 'text');\n const size = useFilterBarSize();\n\n const initialString = typeof value === 'string' ? value : '';\n const [localValue, setLocalValue] = useState<string>(initialString);\n\n const debouncedOnChange = useMemo(() => debounce(onChange, DEBOUNCE_MS), [onChange]);\n\n // Cancel any pending trailing invocation when the component unmounts\n // or when `onChange` swaps the debounced wrapper. Without this, a\n // user who types and immediately switches operator/field within\n // 300ms would have the stale text written into whatever rule the UI\n // navigated to — `onChange` is rebound by the parent on every\n // navigation, so the abandoned trailing call could fire after we've\n // already moved on. Explicit commits (blur / Enter) flush first, so a\n // value the user just typed is committed before the popover closes;\n // only genuinely abandoned controls reach this cancel.\n useEffect(\n () => () => {\n debouncedOnChange.cancel();\n },\n [debouncedOnChange],\n );\n\n useEffect(() => {\n setLocalValue(typeof value === 'string' ? value : '');\n }, [value]);\n\n if (isValuelessOperator(operator)) {\n return null;\n }\n\n return (\n <Input\n id={inputId}\n type={resolvedInputType}\n size={size}\n placeholder={placeholder ?? field.label}\n aria-label={ariaLabel ?? field.label}\n value={localValue}\n onChange={({ target }) => {\n setLocalValue(target.value);\n debouncedOnChange(target.value);\n }}\n onBlur={() => {\n debouncedOnChange.flush();\n }}\n onKeyDown={(event) => {\n // Enter closes the popover (handled by FilterPopover); commit the\n // in-flight value synchronously before the control unmounts.\n if (event.key === 'Enter' && !event.defaultPrevented && !event.nativeEvent.isComposing) {\n debouncedOnChange.flush();\n }\n }}\n />\n );\n}\n","import type { ReactNode } from 'react';\n\nimport {\n getConditionOperator,\n isRangeOperator,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterFieldType,\n FilterOperator,\n FilterRule,\n FilterRuleValueChange,\n FilterRuleValue,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport ArrayValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/ArrayValueControl/ArrayValueControl';\nimport BooleanValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/BooleanValueControl/BooleanValueControl';\nimport ChoicesValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/ChoicesValueControl/ChoicesValueControl';\nimport DateRangeValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/DateRangeValueControl/DateRangeValueControl';\nimport DateValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/DateValueControl/DateValueControl';\nimport FloatValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/FloatValueControl/FloatValueControl';\nimport IntegerValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/IntegerValueControl/IntegerValueControl';\nimport StringValueControl from 'design-system/components/DataTable/TableControls/FiltersV2/value-controls/StringValueControl/StringValueControl';\n\n/**\n * Single dispatch point that picks the right type-aware value control for a\n * given `FilterField`. Used by both the simple-rule `FilterPopover` and the\n * Advanced Filter Rules editor so the per-type input behavior stays\n * consistent across surfaces.\n *\n * Adding a new field type:\n *\n * 1. Add the type to `FilterFieldType` in `../types.ts` (and decide its\n * operator vocabulary in `../operators.ts`).\n * 2. Implement a control under `../value-controls/<NewType>ValueControl/`\n * that accepts `ValueControlProps` from `../value-controls/types.ts`.\n * 3. Add the new branch to `RESOLVERS` below. TypeScript will require it\n * because the `Record<FilterFieldType, …>` keying makes the table\n * exhaustive.\n *\n * `layout` is forwarded to the underlying control so the same component\n * can render differently between the two surfaces — see\n * `ChoicesValueControl` in `multiple` mode (\"popover\" → inline checkbox\n * list, \"inline\" → compact Combobox with chips).\n */\nexport interface ResolveValueControlOptions {\n field: FilterField;\n operator: FilterOperator;\n value: FilterRuleValue;\n relativeDate?: FilterRule['relativeDate'];\n onChange: FilterRuleValueChange;\n onCommit?: () => void;\n ariaLabel?: string;\n relativeDatesEnabled?: boolean;\n dateTimesEnabled?: boolean;\n /**\n * Where the control is being rendered. `popover` (default) is the\n * simple-pill `FilterPopover` surface — dedicated to one rule with\n * room for an inline checkbox list. `inline` is the Advanced Filter\n * Rules `LogicRow` dropdown surface — compact, prefers a Combobox\n * with chips over a vertically expansive list.\n */\n layout?: 'popover' | 'inline';\n}\n\nexport type ValueControlResolver = (opts: ResolveValueControlOptions) => ReactNode | undefined;\n\n/* eslint-disable @typescript-eslint/naming-convention --\n Keys must match the `FilterFieldType` union, which uses snake_case\n to mirror the backend's `field_key_to_info` payload's `type`. */\nconst RESOLVERS: Partial<Record<FilterFieldType, (opts: ResolveValueControlOptions) => ReactNode>> =\n {\n // `string` and `email` both dispatch to `StringValueControl`; the\n // control derives `<input type>` from `field.type`.\n string: (opts) => <StringValueControl {...opts} />,\n email: (opts) => <StringValueControl {...opts} />,\n choices: (opts) => <ChoicesValueControl {...opts} />,\n multi_choices: (opts) => <ChoicesValueControl multiple {...opts} />,\n // Boolean fields use the `is` operator with a True/False value.\n boolean: (opts) => <BooleanValueControl {...opts} />,\n // A date field's value control follows the operator, not just the type:\n // `between` carries a `{ startDate, endDate }` pair, everything else a\n // single ISO day.\n date: (opts) =>\n isRangeOperator(opts.operator) ? (\n <DateRangeValueControl {...opts} />\n ) : (\n <DateValueControl {...opts} />\n ),\n date_range: (opts) => <DateRangeValueControl {...opts} />,\n integer: (opts) => <IntegerValueControl {...opts} />,\n float: (opts) => <FloatValueControl {...opts} />,\n array: (opts) => <ArrayValueControl {...opts} />,\n };\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport function resolveValueControl(\n opts: ResolveValueControlOptions,\n hostResolver?: ValueControlResolver,\n): ReactNode {\n if (opts.field.condition != null && isValuelessOperator(opts.operator, opts.field)) {\n return null;\n }\n const hostControl = hostResolver?.(opts);\n if (hostControl != null) {\n return hostControl;\n }\n\n const config = getConditionOperator(opts.field, opts.operator);\n if (config != null) {\n if (config.valueType === 'string_array') {\n return opts.field.options != null ? (\n <ChoicesValueControl multiple {...opts} operator='is' />\n ) : null;\n }\n const type = config.valueType === 'number' ? 'float' : config.valueType;\n if (type === 'none') {\n return null;\n }\n return RESOLVERS[type]?.({ ...opts, operator: 'is', field: { ...opts.field, type } }) ?? null;\n }\n const renderer = RESOLVERS[opts.field.type];\n if (!renderer) {\n return null;\n }\n return renderer(opts);\n}\n","import { type HTMLAttributes, useCallback, useMemo } from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { CirclePlusIcon } from '@persona/icons';\nimport Button, { IconButton } from 'design-system/components/Button';\nimport {\n Combobox,\n type ComboboxOption,\n type ComboboxOptionsOrGroups,\n} from 'design-system/components/Combobox';\nimport { buildFieldPickerOptions } from 'design-system/components/DataTable/TableControls/FiltersV2/fieldPickerOptions';\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport { useFilterBarSize } from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport type {\n FilterField,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\n/**\n * Props for `FilterPickerMenu` — the `⊕ Filter` cascading picker.\n *\n * The picker surfaces a `FilterField` selection back to the parent\n * (TableControls/FiltersV2) via `onPickField`. The parent owns the subsequent\n * FilterPopover that lets the user pick an operator and value.\n *\n * Internally this is a thin wrapper around the design-system Combobox's\n * `trigger` prop: the `⊕ Filter` button (or compact `⊕` icon button) is\n * passed as the trigger, and the Combobox renders the search input\n * + nested-navigation dropdown content directly beneath it. System\n * fields live at the root; every custom field sits behind a single\n * \"Fields\" submenu with its parent record type as a sublabel. Typing\n * flattens the whole tree and surfaces every matching leaf with a\n * breadcrumb in its description.\n */\nexport interface FilterPickerMenuProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {\n /** Registry exposing the resource's system + custom fields. */\n registry: FieldRegistry;\n /**\n * Called when the user picks a field. The parent is responsible for\n * opening the value-control popover for the picked field.\n */\n onPickField: (field: FilterField) => void;\n /**\n * Override for the default `Filter` trigger button label.\n *\n * @defaultValue `'Filter'` (`usePDSStrings().filter`)\n */\n triggerLabel?: string;\n /**\n * When true, the trigger renders icon-only (the `⊕` prefix icon\n * without the visible label). The `triggerLabel` is still used as\n * the button's `aria-label` for accessibility. Used once the bar\n * already has pills.\n */\n compact?: boolean;\n /** Disables the trigger button (e.g. while the registry is loading). */\n disabled?: boolean;\n /**\n * Allow-list of `parentRecordType` labels that should appear in the\n * \"Fields\" submenu. When omitted (or `undefined`), every custom-field\n * group is shown — the default behavior.\n *\n * The picker is intentionally policy-free here — it just applies the\n * filter. The parent (`FilterBar`) derives this list from the active\n * rules on `registry.recordTypeSelectorFields()` and passes it\n * through. Passing an empty array hides the Fields submenu entirely\n * (no parents match, so no custom fields render).\n */\n visibleCustomFieldParents?: ReadonlyArray<string>;\n /**\n * Deny-list of field ids to omit from the menu. When it covers every\n * selectable field the trigger is not rendered at all.\n */\n excludeFieldIds?: ReadonlyArray<string>;\n /**\n * Size variant. Defaults to whatever the surrounding\n * `FilterBarContext` provides (`'sm'` outside a FilterBar).\n * Threaded into the Combobox and the trigger Button/IconButton so the\n * picker matches the surrounding pills.\n */\n size?: FilterSize;\n}\n\n// Trigger color states:\n// default: text/secondary\n// hover: text/primary, no background\n// active / selected (popover open): text/primary, no background\n//\n// Recolor only via \"color\" -- the PDS icons are fill-based, so the\n// glyph follows. Painting a \"stroke\" over the path would visually\n// double the outline. The styles live on a wrapper because we can't\n// add custom CSS directly to the Combobox-cloned trigger element\n// without losing the spread props that downshift relies on.\nconst TriggerWrapper = styled.span<{ $isOpen: boolean }>`\n display: inline-flex;\n\n & button {\n background-color: transparent;\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', theme.color.text.secondary)};\n }\n\n & button:hover,\n & button:active {\n background-color: transparent;\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n }\n\n ${({ $isOpen, theme }) =>\n $isOpen &&\n css`\n & button {\n background-color: transparent;\n color: ${semanticColor(theme, 'FgPrimary', theme.color.text.primary)};\n }\n `}\n`;\n\nconst FilterPickerMenu = ({\n registry,\n onPickField,\n triggerLabel,\n compact = false,\n disabled = false,\n visibleCustomFieldParents,\n excludeFieldIds,\n size,\n ...rest\n}: FilterPickerMenuProps) => {\n const resolvedSize = useFilterBarSize(size);\n const strings = usePDSStrings();\n const resolvedTriggerLabel = triggerLabel ?? strings.filter;\n // What the picker would offer with nothing excluded, so an empty option\n // list can be attributed to the exclusions rather than to the registry.\n const unfilteredOptions = useMemo<ComboboxOptionsOrGroups<string>>(\n () => buildFieldPickerOptions(registry, visibleCustomFieldParents, undefined, strings.fields),\n [registry, visibleCustomFieldParents, strings.fields],\n );\n // Without exclusions the two trees are the same one — building it twice\n // would tax every bar for a feature none of them turn on.\n const options = useMemo<ComboboxOptionsOrGroups<string>>(\n () =>\n excludeFieldIds == null || excludeFieldIds.length === 0\n ? unfilteredOptions\n : buildFieldPickerOptions(\n registry,\n visibleCustomFieldParents,\n excludeFieldIds,\n strings.fields,\n ),\n [registry, visibleCustomFieldParents, excludeFieldIds, unfilteredOptions, strings.fields],\n );\n\n const optionDisabledReason = useCallback(\n (option: ComboboxOption<string>) => registry.get(option.value)?.disabledReason,\n [registry],\n );\n\n const handleChange = useCallback(\n (value: string | null) => {\n if (value == null) {\n return;\n }\n // Nested-group descents never reach here — the Combobox only\n // commits via `onChange` for leaf selections. Anything that\n // arrives is a real field id.\n const field = registry.get(value);\n if (!field || field.disabledReason != null) {\n return;\n }\n onPickField(field);\n },\n [registry, onPickField],\n );\n\n // Every field is already in use — render nothing rather than a trigger\n // that opens onto an empty dropdown. A registry that offers nothing of its\n // own keeps the trigger and the Combobox's empty state, which is what a\n // table whose filterable fields haven't loaded yet shows.\n if (options.length === 0 && unfilteredOptions.length > 0) {\n return null;\n }\n\n // The trigger is rendered directly by the Combobox via its `trigger`\n // prop (the Combobox clones it with downshift's toggle button props).\n // We don't track open state here — downshift owns it.\n const trigger = compact ? (\n <IconButton size={resolvedSize} disabled={disabled} aria-label={resolvedTriggerLabel}>\n <CirclePlusIcon />\n </IconButton>\n ) : (\n // The no-pills trigger uses the same plus icon as the compact\n // add-pill button, with the text label shown.\n <Button\n variant='text'\n size={resolvedSize}\n width='auto'\n prefixIcon={<CirclePlusIcon />}\n disabled={disabled}\n >\n {resolvedTriggerLabel}\n </Button>\n );\n\n // The TriggerWrapper styles drive hover/active colors. We're not\n // tracking open state on this side, so the Combobox owns open/closed\n // behavior entirely.\n return (\n <TriggerWrapper {...rest} $isOpen={false}>\n <Combobox<string>\n options={options}\n optionDisabledReason={optionDisabledReason}\n value={null}\n onChange={handleChange}\n size={resolvedSize}\n aria-label={strings.filterFieldPicker}\n trigger={trigger}\n />\n </TriggerWrapper>\n );\n};\n\nexport default FilterPickerMenu;\n","// oxlint-disable rulesdir/no-core-color-tokens\nimport {\n type HTMLAttributes,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n forwardRef,\n} from 'react';\nimport styled, { css } from 'styled-components';\n\nimport { BorderRadius, Color, Spacing, Typography } from '@persona/design-tokens';\nimport { CaretDownIcon as CaretDownIcon16, XIcon as XIcon16 } from '@persona/icons';\nimport { CaretDownIcon, XIcon } from '@persona/icons/12px';\nimport {\n FILTER_SIZE_TOKENS,\n useFilterBarSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport type { FilterSize } from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { withAlpha } from 'design-system/lib/color';\nimport { semanticColor, semanticTokens } from 'design-system/lib/semanticColor';\nimport { focusOutline, focusWithinOutline } from 'design-system/mixins/focus';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\n/**\n * Shared rounded-pill primitive that both `FilterPill` (simple-rule\n * pill) and `RulesPill` (compound-expression pill) compose. Owns:\n *\n * - the variant-aware container (gray default, `ube/100` purple\n * active) with a `:focus-within` outline so the focus ring sits on\n * the whole pill rather than the inner body;\n * - the trailing-affordance slot that shows a caret in the resting\n * state and swaps to a dismiss `×` on hover or when the popover is\n * open (`variant=\"active\"`);\n * - the dismiss button's `stopPropagation` so clicks on `×` never\n * reach the body's click handler (which Radix typically wires as\n * \"toggle popover\");\n * - size-variant threading (`sm` / `md`) — applies the matching PDS\n * typography mixin and pulls dimensions from `FILTER_SIZE_TOKENS[size]`\n * so both pills stay visually aligned regardless of the surrounding\n * `FilterBarContext`.\n *\n * Callers own only the body content (`children`) and the\n * accessibility labels for the body / dismiss buttons.\n *\n * The outer element is a `<span>` rather than a `<button>` so the\n * primitive works as a Radix `Popover.Trigger asChild` anchor in both\n * pill contexts (the immediate child of `asChild` must accept the\n * injected `onClick` + `ref`). The inner `<button>` is the\n * keyboard-focusable click target.\n */\nexport interface PillShellProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'onClick'> {\n /**\n * Visual variant. `'default'` is the gray resting state;\n * `'active'` is the purple state used when the associated popover\n * is open. Active also pins the dismiss `×` visible (no caret).\n */\n variant: 'default' | 'active';\n /**\n * Body content rendered inside the focusable inner button. Typically\n * the pill's label + value chips + count chip. Keep it presentational\n * — no nested buttons / clickable elements (they'd compete with the\n * outer body button for the user's click).\n */\n children: ReactNode;\n /**\n * aria-label for the inner body button — used both as the pill's\n * accessible name and as the verbalized \"what this opens\" hint.\n * Pass a sentence like `\"Edit filter: Country is US\"` rather than\n * a single noun so VoiceOver reads the active state clearly.\n */\n bodyAriaLabel: string;\n /**\n * Click handler for the body. Optional because the pill is most\n * commonly used as a Radix `Popover.Trigger asChild`, in which case\n * Radix injects its own toggle handler via `...rest` onto the outer\n * span — clicks bubble from the inner body button up to the span and\n * fire it.\n */\n onBodyClick?: () => void;\n /**\n * Dismiss-button handler. When omitted, the trailing `×` is decorative\n * only (used by `RulesPill`, whose whole body toggles the popover and\n * does not have a clear-all action yet).\n */\n onDismiss?: () => void;\n /**\n * aria-label for the dismiss button. Pass a sentence like\n * `\"Remove filter: Country is US\"` so screen-reader users hear which\n * pill they're removing.\n */\n dismissAriaLabel?: string;\n /**\n * Size variant. Defaults to whatever the surrounding\n * `FilterBarContext` provides (`'sm'` outside a `FilterBar`).\n * Pass an explicit prop to override the context — useful for\n * Storybook stories that render multiple sizes side-by-side.\n */\n size?: FilterSize;\n}\n\n// ---------------------------------------------------------------------------\n// Styled primitives for the shared pill shell.\n// ---------------------------------------------------------------------------\n\nconst PillRoot = styled.span<{ $variant: 'default' | 'active'; $size: FilterSize }>`\n display: inline-flex;\n align-items: center;\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].controlHeight};\n padding: 0 ${Spacing[1]} 0 ${Spacing[2]};\n gap: 2px;\n border-radius: ${BorderRadius.Md};\n ${({ $size }) => ($size === 'sm' ? Typography.TextSmall : Typography.TextMedium)};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n max-width: 100%;\n cursor: pointer;\n user-select: none;\n transition: background-color ${TransitionDuration.Faster} ease-out;\n\n /* Keyboard focus lands on the inner body button, so the visible focus\n ring is drawn on the whole pill via :focus-within. */\n ${focusWithinOutline};\n\n ${({ theme, $variant }) => {\n const tokens = semanticTokens(theme);\n return $variant === 'active'\n ? css`\n background-color: ${\n tokens ? withAlpha(tokens.SurfaceAccent, tokens.Opacity25) : Color.CorePurple100\n };\n color: ${semanticColor(theme, 'FgAccent', Color.TextActive)};\n `\n : css`\n background-color: ${semanticColor(theme, 'SurfaceSecondary', theme.color.background.secondary)};\n color: ${semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n\n &:hover {\n background-color: ${semanticColor(theme, 'ActionOutlineHover', Color.BackgroundLabelGrey)};\n }\n `;\n }}\n`;\n\n/**\n * The clickable body of the pill. Suppresses its own focus outline\n * (the parent `PillRoot` carries the visible focus ring via\n * `:focus-within`) and is otherwise a transparent wrapper that\n * inherits the pill's typography + color.\n */\nconst PillBody = styled.button`\n display: inline-flex;\n align-items: center;\n gap: ${Spacing[1]};\n height: 100%;\n background: transparent;\n border: 0;\n padding: 0;\n margin: 0;\n appearance: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n min-width: 0;\n max-width: 100%;\n\n &:focus-visible {\n outline: none;\n }\n\n ${PillRoot}:focus-within & {\n outline: none;\n }\n`;\n\n/**\n * Square slot containing the trailing caret or dismiss glyph. Slot\n * size scales with the pill (`sm` = 16x16 / 12px glyph; `md` = 20x20\n * / 16px glyph) so the visual weight stays proportional to the pill\n * height.\n */\nconst actionSlotStyles = css<{ $size: FilterSize }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: ${({ $size }) => ($size === 'sm' ? '16px' : '20px')};\n height: ${({ $size }) => ($size === 'sm' ? '16px' : '20px')};\n flex: 0 0 auto;\n border-radius: ${BorderRadius.Sm};\n color: inherit;\n\n svg {\n width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};\n }\n`;\n\nconst ActionSlot = styled.span<{ $size: FilterSize }>`\n ${actionSlotStyles};\n`;\n\nconst DismissibleCaretWrapper = styled(ActionSlot)`\n ${PillRoot}:hover &,\n ${PillRoot}[data-variant='active'] & {\n display: none;\n }\n`;\n\nconst DismissButton = styled.button<{ $size: FilterSize }>`\n ${actionSlotStyles};\n display: none; /* see :hover / [data-variant='active'] overrides below */\n padding: 0;\n margin: 0;\n border: 0;\n appearance: none;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n\n &:hover {\n background-color: ${({ theme }) => {\n const tokens = semanticTokens(theme);\n return tokens\n ? withAlpha(tokens.ActionNeutralHover, tokens.Opacity25)\n : Color.BackgroundButtonTextHover;\n }};\n }\n\n ${focusOutline};\n\n ${PillRoot}:hover &,\n ${PillRoot}[data-variant='active'] & {\n display: inline-flex;\n }\n\n ${PillRoot}[data-variant='active'] &:hover {\n background-color: ${({ theme }) => {\n const tokens = semanticTokens(theme);\n return tokens\n ? withAlpha(tokens.FeedbackAccent1Static, tokens.Opacity25)\n : Color.CorePurple200;\n }};\n }\n`;\n\nconst PillShell = forwardRef<HTMLSpanElement, PillShellProps>(function PillShell(\n { variant, children, bodyAriaLabel, onBodyClick, onDismiss, dismissAriaLabel, size, ...rest },\n ref,\n) {\n const ariaExpanded = rest['aria-expanded'];\n const resolvedSize = useFilterBarSize(size);\n // 12px icons for `sm`, 16px icons for `md` — separate icon assets so\n // the SVG content scales cleanly rather than just sizing a single\n // base asset up.\n const CaretIcon = resolvedSize === 'sm' ? CaretDownIcon : CaretDownIcon16;\n const DismissIcon = resolvedSize === 'sm' ? XIcon : XIcon16;\n\n const handleDismissClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onDismiss?.();\n };\n\n // Suppress Enter / Space bubbling from the inner body so it doesn't\n // double-fire the outer span's click handler that Radix injects via\n // `Popover.Trigger asChild`. The body's native keyboard handler\n // already produces a click event for both keys.\n const handleBodyKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n };\n\n return (\n <PillRoot\n ref={ref}\n $variant={variant}\n $size={resolvedSize}\n data-variant={variant}\n onClick={onBodyClick}\n {...rest}\n >\n <PillBody\n type='button'\n onKeyDown={handleBodyKeyDown}\n aria-label={bodyAriaLabel}\n aria-haspopup='dialog'\n aria-expanded={ariaExpanded}\n >\n {children}\n </PillBody>\n {onDismiss ? (\n <>\n <DismissibleCaretWrapper aria-hidden='true' $size={resolvedSize}>\n <CaretIcon />\n </DismissibleCaretWrapper>\n <DismissButton\n $size={resolvedSize}\n type='button'\n onClick={handleDismissClick}\n aria-label={dismissAriaLabel}\n >\n <DismissIcon />\n </DismissButton>\n </>\n ) : (\n <ActionSlot aria-hidden='true' $size={resolvedSize}>\n <CaretIcon />\n </ActionSlot>\n )}\n </PillRoot>\n );\n});\n\nexport default PillShell;\n","// oxlint-disable rulesdir/no-core-color-tokens\nimport { uniqueId } from 'lodash-es';\nimport { type HTMLAttributes, forwardRef, useMemo } from 'react';\nimport styled from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport {\n FILTER_SIZE_TOKENS,\n useFilterBarSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport { formatDateValueForDisplay } from 'design-system/components/DataTable/TableControls/FiltersV2/format-date-value';\nimport {\n carriesDateRange,\n getOperatorLabel,\n hasCompleteConditionValue,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport PillShell from 'design-system/components/DataTable/TableControls/FiltersV2/PillShell';\nimport { relativePresetLabel } from 'design-system/components/DataTable/TableControls/FiltersV2/relative-date-label';\nimport type {\n FilterField,\n FilterFieldType,\n FilterRule,\n FilterRuleValue,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport Stack from 'design-system/components/Stack';\nimport Tooltip from 'design-system/components/Tooltip';\nimport {\n DEFAULT_COMMON_STRINGS,\n usePDSLocale,\n usePDSStrings,\n type CommonStrings,\n} from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport TruncatedText from 'design-system/lib/TruncatedText';\n\n/**\n * Props for `FilterPill` — one entry in `FilterStateV2.topLevelRules`\n * rendered as an interactive pill.\n *\n * The container chrome (rounded 24px pill, variant background, focus\n * ring, caret↔dismiss swap) is provided by `PillShell`. This file\n * owns the pill's filter-specific body content: field label, operator\n * label, and value chip(s).\n */\nexport interface FilterPillProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'onClick'> {\n /** Field metadata, used for the label and value-chip lookups. */\n field: FilterField;\n /** Active rule, or `null` for the default/unset state. */\n rule: FilterRule | null;\n /**\n * User clicked the pill body — parent should open the value-edit popover.\n *\n * Optional because the most common usage is as a Radix `Popover.Trigger`\n * `asChild` element. In that case Radix's `Slot` injects its own click\n * handler on the outer `<span>` that toggles the popover; clicks bubble\n * from the inner body button up to the span and fire it. The dismiss\n * button's `stopPropagation` (inside `PillShell`) keeps ✕ clicks from\n * triggering the popover.\n */\n onClick?: () => void;\n /** User clicked the ✕ — parent should remove the rule. */\n onDismiss: () => void;\n /**\n * Visual variant.\n *\n * - `'default'` (default) — neutral gray pill, shows `▾`.\n * - `'active'` — purple pill used when the popover is open. Always\n * shows `×` (in place of the caret).\n *\n * On hover, the default variant also swaps `▾` for `×`.\n */\n variant?: 'default' | 'active';\n /**\n * Optional label-lookup map for `choices` / `multi_choices` fields. When\n * provided, raw option values in the rule are translated to their\n * human-readable labels before rendering. Falls through to the raw value\n * when the map is missing or doesn't contain the option.\n */\n optionLabels?: Record<string, string>;\n /**\n * Size variant. Forwarded to `PillShell` and to the value-chip\n * styling. Defaults to whatever the surrounding `FilterBarContext`\n * provides (`'sm'` outside a `FilterBar`).\n */\n size?: FilterSize;\n}\n\n// ---------------------------------------------------------------------------\n// Filter-pill-specific body content. The outer pill chrome (variant\n// background, focus ring, caret/dismiss slot) lives in `PillShell`.\n// ---------------------------------------------------------------------------\n\nconst FieldLabel = styled.span`\n max-width: 120px;\n flex: 0 1 auto;\n`;\n\nconst OperatorLabel = styled.span`\n color: inherit;\n white-space: nowrap;\n flex: 0 0 auto;\n`;\n\nconst ValueChipGroup = styled.span`\n display: inline-flex;\n align-items: center;\n gap: 2px;\n flex: 0 1 auto;\n`;\n\nconst ValueChip = styled.span<{ $variant: 'default' | 'active'; $size: FilterSize }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};\n min-width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};\n max-width: 120px;\n padding: 0 ${Spacing[1]};\n border-radius: 3px;\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n\n background-color: ${({ theme, $variant }) =>\n $variant === 'active'\n ? semanticColor(theme, 'FeedbackAccent1Static', Color.CorePurple200)\n : semanticColor(theme, 'FeedbackNeutral2', Color.CoreSlate200)};\n color: ${({ theme, $variant }) =>\n $variant === 'active'\n ? semanticColor(theme, 'FgAccentStatic', Color.TextActive)\n : semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n`;\n\nconst OverflowChip = styled(ValueChip)`\n flex: 0 0 auto;\n`;\n\nconst OverflowTooltipList = styled(Stack).attrs({ as: 'ul', spacing: Spacing[1] })`\n margin: 0;\n padding: 0;\n list-style: none;\n\n & > li {\n margin: 0;\n padding: 0;\n }\n`;\n\n/**\n * Normalize a `FilterRuleValue` to a list of display strings, applying the\n * `optionLabels` lookup so the pill renders human-readable option labels\n * instead of raw option ids. Null / undefined collapses to an empty list.\n */\nfunction normalizeValueToDisplay(\n value: FilterRuleValue,\n optionLabels?: Record<string, string>,\n relativeDate?: FilterRule['relativeDate'],\n fieldType?: FilterFieldType,\n strings: Pick<\n CommonStrings,\n 'booleanTrue' | 'booleanFalse' | 'groupCount'\n > = DEFAULT_COMMON_STRINGS,\n locale?: string,\n): string[] {\n if (value == null) {\n return [];\n }\n const relativeLabel = relativePresetLabel(value, relativeDate);\n if (relativeLabel) {\n return [relativeLabel];\n }\n const lookup = (raw: string): string =>\n optionLabels?.[raw] ??\n (fieldType === 'date' || fieldType === 'date_range'\n ? formatDateValueForDisplay(raw, locale)\n : raw);\n\n if (Array.isArray(value)) {\n if (value.length > 0 && Array.isArray(value[0])) {\n return [strings.groupCount(value.length)];\n }\n return value.map((entry) => lookup(String(entry)));\n }\n // A date range never falls through to the scalar branch below — a\n // half-picked one has no chip to show, and the raw object would reach\n // React as a child.\n if (typeof value === 'object') {\n const { startDate, endDate } = value as { startDate?: string; endDate?: string };\n if (startDate && endDate) {\n return [`${lookup(startDate)} – ${lookup(endDate)}`];\n }\n const single = startDate || endDate;\n return single ? [lookup(single)] : [];\n }\n if (typeof value === 'boolean') {\n return [value ? strings.booleanTrue : strings.booleanFalse];\n }\n if (typeof value === 'number') {\n return [String(value)];\n }\n return [lookup(value as string)];\n}\n\n/**\n * Accessible name builder used both for the pill body's `aria-label` and the\n * dismiss button's `aria-label`. We assemble a human sentence rather than\n * relying on child text nodes because the chip components don't always read\n * cleanly when concatenated by the AT.\n */\nfunction buildAccessibleName(\n field: FilterField,\n rule: FilterRule | null,\n displayedValues: string[],\n strings: CommonStrings = DEFAULT_COMMON_STRINGS,\n): string {\n if (rule == null) {\n return field.label;\n }\n // Incomplete (operator selected, no value, not valueless) — accessible\n // name mirrors the visible pill, which only renders the field label.\n if (field.condition != null && !hasCompleteConditionValue(rule, field)) {\n return field.label;\n }\n if (!isValuelessOperator(rule.operator, field) && displayedValues.length === 0) {\n return field.label;\n }\n const operatorLabel = getOperatorLabel(rule.operator, field.type, strings, field);\n if (isValuelessOperator(rule.operator, field)) {\n return `${field.label} ${operatorLabel}`;\n }\n return `${field.label} ${operatorLabel} ${displayedValues.join(', ')}`;\n}\n\nconst FilterPill = forwardRef<HTMLSpanElement, FilterPillProps>(function FilterPill(\n { field, rule, onClick, onDismiss, variant = 'default', optionLabels, size, ...rest },\n ref,\n) {\n const reactId = useMemo(() => uniqueId('filter-pill-'), []);\n const resolvedSize = useFilterBarSize(size);\n const strings = usePDSStrings();\n const locale = usePDSLocale();\n\n const displayedValues = useMemo(\n () =>\n rule && !isValuelessOperator(rule.operator, field)\n ? normalizeValueToDisplay(\n rule.value,\n optionLabels,\n carriesDateRange(rule.operator, field?.type) ? rule.relativeDate : undefined,\n field?.type,\n strings,\n locale,\n )\n : [],\n [rule, optionLabels, field, strings, locale],\n );\n\n const accessibleName = buildAccessibleName(field, rule, displayedValues, strings);\n const hasRule = rule != null;\n\n // Incomplete filters render as a bare field label.\n const isComplete =\n hasRule &&\n (field.condition != null\n ? hasCompleteConditionValue(rule, field)\n : isValuelessOperator(rule.operator, field) || displayedValues.length > 0);\n\n const firstValue = displayedValues[0];\n const overflowValues = displayedValues.slice(1);\n const overflowTooltipId = `${reactId}-overflow`;\n\n return (\n <PillShell\n ref={ref}\n variant={variant}\n size={resolvedSize}\n bodyAriaLabel={strings.editFilter(accessibleName)}\n onBodyClick={onClick}\n onDismiss={onDismiss}\n dismissAriaLabel={strings.removeFilter(accessibleName)}\n {...rest}\n >\n <FieldLabel>\n <TruncatedText>{field.label}</TruncatedText>\n </FieldLabel>\n {isComplete && hasRule && (\n <OperatorLabel>{getOperatorLabel(rule.operator, field.type, strings, field)}</OperatorLabel>\n )}\n {isComplete &&\n hasRule &&\n !isValuelessOperator(rule.operator, field) &&\n firstValue != null && (\n <ValueChipGroup>\n <ValueChip $variant={variant} $size={resolvedSize}>\n <TruncatedText>{firstValue}</TruncatedText>\n </ValueChip>\n {overflowValues.length > 0 && (\n <Tooltip\n trigger={\n <OverflowChip\n $variant={variant}\n $size={resolvedSize}\n aria-describedby={overflowTooltipId}\n >\n {`+${overflowValues.length}`}\n </OverflowChip>\n }\n side='bottom'\n hideArrow\n >\n <OverflowTooltipList id={overflowTooltipId} aria-label={strings.additionalValues}>\n {overflowValues.map((entry, index) => (\n <li key={`${entry}-${index}`}>{entry}</li>\n ))}\n </OverflowTooltipList>\n </Tooltip>\n )}\n </ValueChipGroup>\n )}\n </PillShell>\n );\n});\n\nexport default FilterPill;\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { type KeyboardEvent, type ReactNode, useCallback, useEffect, useMemo, useRef } from 'react';\nimport styled from 'styled-components';\n\nimport { BorderRadius, Color, Spacing } from '@persona/design-tokens';\nimport {\n CaretDownIcon as CaretDownIcon16,\n CircleInfoIcon as CircleInfoIcon16,\n} from '@persona/icons';\nimport { CaretDownIcon, CircleInfoIcon } from '@persona/icons/12px';\nimport Button from 'design-system/components/Button';\nimport {\n FILTER_SIZE_TOKENS,\n useFilterBarSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport {\n fieldHasMultipleOperators,\n getOperatorLabel,\n getOperatorsForField,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterOperator,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport DropdownMenu from 'design-system/components/DropdownMenu';\nimport Popover from 'design-system/components/Popover';\nimport Stack, { HStack } from 'design-system/components/Stack';\nimport { transparent } from 'design-system/lib/color';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport TruncatedText from 'design-system/lib/TruncatedText';\nimport { Z_INDICES } from 'design-system/lib/zindex';\nimport { paragraphMixins } from 'design-system/mixins/text';\n\n/**\n * Props for `FilterPopover` — the single-rule editor that opens from a\n * `FilterPill` body click or from the `FilterPickerMenu` after a field\n * is picked.\n *\n * ┌──────────────────────────────────┐\n * │ Field name is ▾ │ ← inline header (12px secondary + operator)\n * │ ┌────────────────────────────┐ │\n * │ │ value control (parent slot)│ │\n * │ └────────────────────────────┘ │\n * ├──────────────────────────────────┤\n * │ ⓘ Field name is a field on … │ ← footer (10px secondary, custom fields only)\n * └──────────────────────────────────┘\n *\n * The value control slot is whatever the parent passes\n * — text input, multi-select, calendar, etc.\n */\nexport interface FilterPopoverProps {\n /** Field metadata, used for the header label, operator vocabulary, and footer. */\n field: FilterField;\n /** Currently selected operator for this rule. */\n operator: FilterOperator;\n /** Called when the user picks a new operator from the dropdown. */\n onChangeOperator: (op: FilterOperator) => void;\n /**\n * The parent-supplied value control. This component is intentionally\n * agnostic about the inner UI — the per-type value controls (text input,\n * multi-select, calendar, etc.) live outside this file and are wired in\n * by the parent via this slot.\n */\n valueControlSlot: ReactNode;\n /** Called when the popover should close (e.g. Escape, click-outside). */\n onClose: () => void;\n onApply?: () => void;\n /** Anchor element — passed through to Radix `Popover.Trigger` as a child. */\n trigger: ReactNode;\n /**\n * Controlled-open flag. Same pass-through convention as `FilterPickerMenu`:\n * when both `open` and `onOpenChange` are provided the popover behaves as a\n * fully controlled component; otherwise Radix manages open state internally.\n */\n open?: boolean;\n /**\n * Controlled-open setter, called by Radix whenever it wants to transition\n * the popover's open state. The parent is free to ignore this and force a\n * different state if it needs to (e.g. block-close while editing).\n */\n onOpenChange?: (open: boolean) => void;\n /**\n * Size variant. Defaults to whatever the surrounding\n * `FilterBarContext` provides (`'sm'` outside a FilterBar).\n * Drives header/operator font + glyph sizes plus the `size` prop\n * passed to any DropdownMenu items.\n */\n size?: FilterSize;\n /**\n * Lets the panel grow past the default max width for value controls that\n * need two date-time fields side by side (minute-precision ranges).\n */\n wide?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Styled primitives for the filter editing popover.\n// ---------------------------------------------------------------------------\n\n/** Wide controls size to their content while retaining a viewport gutter. */\nconst POPOVER_MIN_WIDTH = '196px';\nconst POPOVER_MAX_WIDTH = '320px';\nconst POPOVER_WIDE_MAX_WIDTH = `calc(100vw - ${Spacing[4]} - ${Spacing[4]})`;\n\nconst OperatorMenu = styled(DropdownMenu)`\n && {\n background-color: ${({ theme }) =>\n semanticColor(theme, 'SurfaceElevated', theme.color.background.primary)};\n }\n`;\n\nconst PopoverPanel = styled(Stack).attrs({ spacing: Spacing[0] })<{ $wide: boolean }>`\n min-width: ${POPOVER_MIN_WIDTH};\n max-width: ${({ $wide }) => ($wide ? 'none' : POPOVER_MAX_WIDTH)};\n /* The design-system Popover.Card already supplies bg, border, shadow,\n and 6px corner radius — we just constrain the inner content. */\n`;\n\nconst Main = styled(Stack).attrs({ spacing: Spacing[1] })<{ $valueless: boolean }>`\n /* Valueless operators have no input below the header — symmetric padding\n keeps the popover tight. Valued operators keep extra bottom padding so\n the control's baseline has breathing room before the edge or footer. */\n padding: ${({ $valueless }) =>\n $valueless ? Spacing[2] : `${Spacing[2]} ${Spacing[2]} ${Spacing[3]}`};\n`;\n\nconst HeaderRow = styled(HStack).attrs({ align: 'center', spacing: Spacing[1] })<{\n $size: FilterSize;\n}>`\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n padding: 0 ${Spacing[1]};\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n white-space: nowrap;\n`;\n\nconst FieldTypeLabel = styled.span<{ $size: FilterSize }>`\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n white-space: nowrap;\n flex: 0 1 auto;\n min-width: 0;\n`;\n\n/**\n * Inline operator picker — a text button (sized to the resolved\n * filter-bar size) with a trailing caret that opens a `DropdownMenu`\n * of operator options. Uses `DropdownMenu` rather than the design-system\n * `Select` so the menu auto-sizes to the longest operator label\n * (`is_not_empty` etc.) instead of inheriting the trigger's narrow\n * width, which clipped labels to \"is e...\" in the previous styling.\n */\nconst InlineOperatorTrigger = styled.button<{ $size: FilterSize }>`\n display: inline-flex;\n align-items: center;\n gap: 2px;\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n padding: 0 ${Spacing[1]};\n margin: 0;\n border: 0;\n border-radius: ${BorderRadius.Sm};\n appearance: none;\n background: ${transparent};\n color: ${({ theme }) => semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n font-family: inherit;\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n cursor: pointer;\n\n &:hover {\n background: ${({ theme }) => semanticColor(theme, 'SurfaceHover', Color.BackgroundSecondary)};\n }\n\n &[data-state='open'] {\n background: ${({ theme }) =>\n semanticColor(theme, 'ActionOutlineHover', Color.BackgroundLabelGrey)};\n }\n\n &:focus-visible {\n outline: 2px solid ${({ theme }) => semanticColor(theme, 'BorderFocus', Color.BorderFocus)};\n outline-offset: 1px;\n }\n\n svg {\n width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};\n flex-shrink: 0;\n }\n`;\n\nconst ValueSlot = styled.div`\n padding: 0 ${Spacing[1]};\n`;\n\nconst Footer = styled(HStack).attrs({ align: 'center', spacing: Spacing[1] })`\n padding: 6px ${Spacing[2]};\n border-top: 1px solid ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n color: ${({ theme }) => semanticColor(theme, 'FgSecondary', Color.TextSecondary)};\n ${paragraphMixins.xs};\n\n svg {\n flex-shrink: 0;\n }\n`;\n\n/**\n * The single-rule editor popover. Renders a Radix `Popover` anchored on\n * `trigger`, with a `Popover.Card` body that stacks:\n *\n * 1. Inline header — \"[Field name] [operator ▾]\" on one line.\n * 2. Parent-supplied value control.\n * 3. Custom-field footer (`ⓘ [label] is a field on [parentRecordType]`).\n *\n * The popover stays purely presentational. Rule state lives in the parent's\n * `useFilterStateV2()` hook; this component just routes operator changes\n * back through `onChangeOperator` and forwards open/close transitions\n * through Radix's controlled props.\n */\nconst FilterPopover = ({\n field,\n operator,\n onChangeOperator,\n valueControlSlot,\n onClose,\n onApply,\n trigger,\n open,\n onOpenChange,\n size,\n wide = false,\n}: FilterPopoverProps) => {\n const strings = usePDSStrings();\n const resolvedSize = useFilterBarSize(size);\n const valueless = isValuelessOperator(operator, field);\n const CaretIcon = resolvedSize === 'sm' ? CaretDownIcon : CaretDownIcon16;\n const InfoIcon = resolvedSize === 'sm' ? CircleInfoIcon : CircleInfoIcon16;\n\n // Gate the operator dropdown on the field's *effective* vocabulary so a\n // field that pins `allowedOperators` (e.g. `['is']` for inclusion-only\n // index fields) can't surface operators the host can't serialize.\n const showOperatorSelector = fieldHasMultipleOperators(field);\n const operatorOptions = useMemo(() => getOperatorsForField(field), [field]);\n\n const handleOpenChange = useCallback(\n (next: boolean) => {\n onOpenChange?.(next);\n if (!next) {\n onClose();\n }\n },\n [onOpenChange, onClose],\n );\n\n // Push focus into the first focusable element inside the value slot\n // so the user can start typing immediately after clicking the pill.\n const valueSlotRef = useRef<HTMLDivElement>(null);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n if (open !== true || valueless) {\n return;\n }\n // Defer until after Radix mounts content and runs its own focus\n // restoration (returns focus to the trigger on close). One animation\n // frame is enough; the design-system Combobox and DatePicker both\n // mount synchronously inside the slot so their inputs are queryable.\n const handle = requestAnimationFrame(() => {\n const root = valueSlotRef.current;\n if (!root) {\n return;\n }\n const focusable = root.querySelector<HTMLElement>(\n 'input:not([disabled]), [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])',\n );\n focusable?.focus();\n });\n return () => cancelAnimationFrame(handle);\n }, [open, field.id, valueless]);\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (event.key !== 'Enter' || event.defaultPrevented || event.nativeEvent.isComposing) {\n return;\n }\n const target = event.target as HTMLElement | null;\n if (!target || target.tagName !== 'INPUT') {\n return;\n }\n const input = target as HTMLInputElement;\n if (\n input.type === 'checkbox' ||\n input.type === 'radio' ||\n input.getAttribute('role') === 'combobox'\n ) {\n return;\n }\n event.preventDefault();\n if (applyButtonRef.current != null) {\n applyButtonRef.current.click();\n return;\n }\n handleOpenChange(false);\n },\n [handleOpenChange],\n );\n\n return (\n <Popover open={open} onOpenChange={handleOpenChange}>\n <Popover.Trigger asChild>{trigger}</Popover.Trigger>\n <Popover.Card\n align='start'\n sideOffset={4}\n avoidCollisions\n // Above the host's sticky/tooltip layers, below page headers (`topNav`).\n zIndex={Z_INDICES.floatingBar}\n aria-label={strings.editFilterFor(field.label)}\n noPadding\n style={wide ? { width: 'max-content', maxWidth: POPOVER_WIDE_MAX_WIDTH } : undefined}\n >\n <PopoverPanel $wide={wide} onKeyDown={handleKeyDown}>\n <Main $valueless={valueless} data-test='filter-popover__main'>\n <HeaderRow $size={resolvedSize}>\n <FieldTypeLabel $size={resolvedSize}>\n <TruncatedText>{field.label}</TruncatedText>\n </FieldTypeLabel>\n {showOperatorSelector ? (\n <OperatorMenu\n trigger={\n <InlineOperatorTrigger\n type='button'\n aria-label={strings.operator}\n $size={resolvedSize}\n >\n {getOperatorLabel(operator, field.type, strings, field)}\n <CaretIcon aria-hidden='true' />\n </InlineOperatorTrigger>\n }\n align='start'\n portal\n // The operator menu drops over the panel it opens from, so it has to\n // outrank the panel's own dropdown layer.\n zIndex={Z_INDICES.layeredDropdown}\n >\n {operatorOptions.map((op) => (\n <DropdownMenu.Item\n key={op}\n size={resolvedSize}\n onClick={() => onChangeOperator(op)}\n >\n {getOperatorLabel(op, field.type, strings, field)}\n </DropdownMenu.Item>\n ))}\n </OperatorMenu>\n ) : (\n <span>{getOperatorLabel(operator, field.type, strings, field)}</span>\n )}\n </HeaderRow>\n\n {!valueless ? <ValueSlot ref={valueSlotRef}>{valueControlSlot}</ValueSlot> : null}\n {onApply != null && (\n <PopoverPrimitive.Close asChild>\n <Button ref={applyButtonRef} size={resolvedSize} onClick={onApply}>\n {strings.applyFilter}\n </Button>\n </PopoverPrimitive.Close>\n )}\n </Main>\n\n {field.source === 'custom' && field.parentRecordType != null && (\n // Only render the footer when the registry actually knows\n // which parent record the field belongs to. The previous\n // implementation rendered \"is a field on a custom record\"\n // when `parentRecordType` was missing, which is technically\n // wrong (a field can only be custom *because* it's attached\n // to a specific parent record) and reads as a debug-only\n // string. Hiding the footer is better than lying about the\n // relationship.\n <Footer>\n <InfoIcon aria-hidden='true' />\n <TruncatedText>\n {field.label} is a field on {field.parentRecordType}\n </TruncatedText>\n </Footer>\n )}\n </PopoverPanel>\n </Popover.Card>\n </Popover>\n );\n};\n\nexport default FilterPopover;\n","// oxlint-disable rulesdir/no-core-color-tokens\nimport { type HTMLAttributes, forwardRef } from 'react';\nimport styled from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport {\n FILTER_SIZE_TOKENS,\n useFilterBarSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport PillShell from 'design-system/components/DataTable/TableControls/FiltersV2/PillShell';\nimport type {\n CompoundExpression,\n FilterSize,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\n\nexport interface RulesPillProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'onClick'> {\n /** The compound expression owned by this pill. Drives the count chip. */\n compound: CompoundExpression;\n /**\n * When `false`, the pill renders `null`. The owning view sets this from\n * `useFilterStateV2().advancedRulesEnabled` (which is itself driven by the\n * org/resource feature flag and the per-view `advancedRulesEnabled` flag).\n */\n enabled: boolean;\n /**\n * Click handler — typically opens an `AdvancedFilterRulesPopover`.\n *\n * Optional because the most common usage is as a Radix `Popover.Trigger`\n * `asChild` element, in which case Radix injects its own toggle onClick\n * via `Slot`. Standalone usage passes an explicit handler.\n */\n onClick?: () => void;\n /**\n * Whether the associated popover is open. Only the open state uses the\n * active treatment. Existing rules alone keep the pill in its resting\n * state.\n */\n isOpen?: boolean;\n /** Override the default test id (`rules-pill__trigger`). */\n 'data-test'?: string;\n /**\n * Size variant. Defaults to whatever the surrounding\n * `FilterBarContext` provides (`'sm'` outside a `FilterBar`).\n */\n size?: FilterSize;\n}\n\n/**\n * Total rule count across every AndGroup in the compound expression.\n *\n * Empty groups contribute zero (they're pruned at adapter serialization time\n * anyway). The number drives the count chip's visibility.\n */\nfunction countRules(compound: CompoundExpression): number {\n let n = 0;\n for (const group of compound.groups) {\n n += group.rules.length;\n }\n return n;\n}\n\nconst Label = styled.span`\n flex: 0 0 auto;\n`;\n\nconst CountChip = styled.span<{ $variant: 'default' | 'active'; $size: FilterSize }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};\n min-width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};\n padding: 0 ${Spacing[1]};\n border-radius: 3px;\n font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};\n line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};\n flex: 0 0 auto;\n\n background-color: ${({ theme, $variant }) =>\n $variant === 'active'\n ? semanticColor(theme, 'FeedbackAccent1Static', Color.CorePurple200)\n : semanticColor(theme, 'FeedbackNeutral2', Color.CoreSlate200)};\n color: ${({ theme, $variant }) =>\n $variant === 'active'\n ? semanticColor(theme, 'FgAccentStatic', Color.TextActive)\n : semanticColor(theme, 'FgPrimary', Color.TextPrimary)};\n`;\n\n/**\n * Always-visible filter pill that owns the entire compound (DNF) expression.\n *\n * Composes `PillShell` for the rounded variant-aware container, the\n * `:focus-within` outline, and the trailing caret↔dismiss swap that's\n * identical to `FilterPill`. The pill-specific body content is just\n * the \"Rules\" label + an optional count chip.\n *\n * Visual states:\n * - `enabled === false` → renders `null` (the owning view has opted out of\n * Advanced Filter Rules).\n * - resting (no popover, no rules) → gray pill, label `Rules`, caret `▾`.\n * - resting (no popover, N rules) → gray pill, label `Rules` + `[N]` chip,\n * caret `▾`.\n * - hover (no popover) → gray-hover bg, caret stays visible.\n * - active (popover open) → \"ube\" purple pill, `TextActive` color, purple\n * `[N]` chip when N > 0, caret stays visible.\n *\n * The pill itself owns no popover state — parents place it inside an\n * `AdvancedFilterRulesPopover` (or any other popover container) and wire\n * `onClick` / `isOpen` themselves.\n *\n * RulesPill does not expose a dismiss action; clicking the pill toggles\n * the popover.\n */\nconst RulesPill = forwardRef<HTMLSpanElement, RulesPillProps>(function RulesPill(\n {\n compound,\n enabled,\n onClick,\n isOpen = false,\n 'aria-label': ariaLabel,\n 'data-test': dataTest,\n size,\n ...rest\n },\n ref,\n) {\n const resolvedSize = useFilterBarSize(size);\n const strings = usePDSStrings();\n\n if (!enabled) {\n return null;\n }\n\n const count = countRules(compound);\n const hasCount = count > 0;\n const variant: 'default' | 'active' = isOpen ? 'active' : 'default';\n // aria-label keeps the \"Rules N\" / \"Rules\" form so specs querying by\n // accessible name (`getByRole('button', { name: 'Rules 5' })`) keep\n // working regardless of how the chip's whitespace renders.\n const accessibleName = hasCount ? strings.rulesWithCount(count) : strings.rules;\n\n return (\n <PillShell\n ref={ref}\n variant={variant}\n size={resolvedSize}\n bodyAriaLabel={ariaLabel ?? accessibleName}\n onBodyClick={onClick}\n data-test={dataTest ?? 'rules-pill__trigger'}\n aria-expanded={isOpen}\n {...rest}\n >\n <Label>{strings.rules}</Label>\n {hasCount && (\n <CountChip $variant={variant} $size={resolvedSize} data-test='rules-pill__count'>\n {count}\n </CountChip>\n )}\n </PillShell>\n );\n});\n\nexport default RulesPill;\n","import type { RelativeDateFilterValue } from '@persona/design-system/lib/date-filter';\n\n/**\n * Filter UI v2 — client-side state shape.\n *\n * Conceptual predicate (what the user sees in the bar):\n * AND(...topLevelRules) AND OR(...compound.groups)\n * where each `AndGroup` inside `compound.groups` is itself AND'd internally.\n *\n * - Simple pills compose into `topLevelRules` and every one of them\n * narrows the result set, on the same field as much as across fields.\n * OR lives inside a single pill's multi-select value (\"is any of these\n * values\") or in the Rules pill.\n * - The Rules pill owns `compound.groups` (OR-of-AND / DNF).\n */\n\n/** All available field types we render type-aware controls + operators for. */\nexport type FilterFieldType =\n | 'string'\n | 'email'\n | 'choices'\n | 'multi_choices'\n | 'boolean'\n | 'integer'\n | 'float'\n | 'date'\n | 'array'\n /** OR-of-AND tag conditions (`FilterTagsCondition[][]`). */\n | 'tags_conditions'\n /** Platform signals; aggregate unless `condition` is explicitly configured. */\n | 'signals'\n /** ISO date range (`DateRangeFilterValue`). */\n | 'date_range';\n\n/**\n * Per-rule operator vocabulary.\n *\n * Not every operator is valid for every field. See `getOperatorsForField` in\n * `./operators.ts` for the resolution the UI and `FieldRegistry` use to gate\n * which operators are pickable in the Filter popover: a field's\n * `allowedOperators`, or its type's vocabulary when that list is absent.\n *\n */\nexport type FilterOperator =\n | 'is'\n | 'is_not'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | `custom:${string}`\n | 'contains'\n | 'does_not_contain'\n | 'is_empty'\n | 'is_not_empty'\n | 'is_true'\n | 'is_false'\n | 'before'\n | 'after'\n /** Inclusive range over a `date` field. Its value is a {@link DateRangeFilterValue}. */\n | 'between';\n\n/** Whether a field is a system/built-in field or a custom field on a parent record type. */\nexport type FilterFieldSource = 'system' | 'custom';\n\n/**\n * Static metadata for one filterable field, exposed by `FieldRegistry`.\n *\n * Shape is mostly derived from the backend's `field_key_to_info` payload.\n * The registry tolerates missing metadata and falls back to `'string'`.\n */\nexport interface FilterField {\n /** Stable id used by `FilterRule.fieldId`. Backend's `field_key`. */\n id: string;\n /** Human-readable label rendered in the filter picker and pill. */\n label: string;\n /** Field type that drives operator vocabulary and value control rendering. */\n type: FilterFieldType;\n /**\n * Date precision supported by the backend for this field. Only system timestamp fields should\n * use `'minute'`; custom date fields are day-granular on the backend.\n */\n timeGranularity?: 'day' | 'minute';\n /** System vs custom — drives the popover footer affordance + picker grouping. */\n source: FilterFieldSource;\n /**\n * For `choices` / `multi_choices`, the option list shown in the value control.\n * Backend metadata `options`.\n */\n options?: ReadonlyArray<{ label: string; value: string }>;\n /**\n * For `array` fields, the inner item type. Drives whether the value control\n * is a text input vs. multi-select. Backend metadata `item_type`.\n */\n itemType?: FilterFieldType;\n /**\n * For custom fields, the human-readable parent-scope label (record type\n * / Case template name). Display-only: the popover footer\n * (`ⓘ [label] is a field on [parentRecordType]`) and the picker submenu\n * grouping/sublabel. Narrowing keys off {@link parentRecordId}, not this\n * label (labels can collide or carry a suffix). Backend `parent_record_type`.\n */\n parentRecordType?: string;\n /**\n * For custom fields, the parent scope's token (the public id the\n * account-type / case-template records expose as `id`) — the\n * picker-narrowing key. A selector field whose `options[].value`\n * intersects the registry's `parentRecordId`s is inferred as a scoping\n * selector, and an `is` pill on it narrows the picker to that scope.\n * Matching on the token, not the label, keeps narrowing exact. Backend\n * `parent_record_id`.\n */\n parentRecordId?: string;\n /**\n * Reserved slot for nested-path filtering (hash subfields). The frontend\n * never produces a non-empty `path` today; this is shape-stable so that\n * hash subfield support can land without a state migration once the backend\n * `SearchAliasMap` decision is made.\n */\n path?: ReadonlyArray<string>;\n /**\n * Optional operator allow-list, for a field whose host can only serialize\n * part of its type's vocabulary. When omitted or empty, the full per-type\n * vocabulary from `operators.ts` applies.\n *\n * Also how a numeric (`integer` / `float`) field opts into comparisons:\n * `['is', ...NUMERIC_COMPARISON_OPERATORS]` (`['is', 'gt', 'lt']`) gives\n * equal to / greater than / less than filtering with numeric validation.\n */\n allowedOperators?: ReadonlyArray<FilterOperator>;\n pickerGroup?: string;\n disabledReason?: string;\n condition?: {\n operators: readonly [FilterConditionOperator, ...FilterConditionOperator[]];\n defaultOperator?: FilterOperator;\n };\n}\n\nexport type FilterConditionOperator = {\n operator: FilterOperator;\n label: string;\n isComplete?: (value: FilterRuleValue) => boolean;\n} & (\n | { valueType: 'string'; defaultValue?: string }\n | { valueType: 'number' | 'integer'; defaultValue?: number }\n | { valueType: 'boolean'; defaultValue?: boolean }\n | { valueType: 'string_array'; defaultValue?: ReadonlyArray<string> }\n | { valueType: 'none'; defaultValue?: null }\n);\n\n/**\n * ISO calendar-date range. Carried by `date_range` fields and by the\n * `between` operator on a `date` field.\n */\nexport interface DateRangeFilterValue {\n startDate?: string;\n endDate?: string;\n}\n\n/** Value shape for a single rule. Matches the union the value controls produce. */\nexport type FilterRuleValue =\n | string\n | ReadonlyArray<string>\n | number\n | boolean\n | null\n | DateRangeFilterValue\n | ReadonlyArray<ReadonlyArray<Record<string, unknown>>>\n | ReadonlyArray<ReadonlyArray<unknown>>;\n\n/** A single field/operator/value triple — one row in the Advanced Filter Rules editor. */\nexport interface FilterRule {\n fieldId: string;\n operator: FilterOperator;\n value: FilterRuleValue;\n /**\n * Semantic metadata; `value` remains an old-client-safe absolute snapshot.\n *\n * Deliberately not checked by `isFilterRule`: readers fall back to the\n * snapshot when this is unparseable, so rejecting the rule would discard a\n * usable range over a bad label.\n */\n relativeDate?: RelativeDateFilterValue;\n}\n\nexport type FilterRuleValueChange = (\n value: FilterRuleValue,\n relativeDate?: RelativeDateFilterValue | null,\n) => void;\n\n/**\n * A top-level (simple pill) rule. Carries a stable `id` so multiple\n * pills for the same field can coexist — the \"Add filter\" picker\n * always creates a new id rather than collapsing duplicate field\n * selections back onto a single existing rule. `id` is local to the\n * client state; it is not serialized to the backend payload.\n */\nexport interface TopLevelFilterRule extends FilterRule {\n id: string;\n}\n\n/** One AND group inside the compound expression. Rules inside are AND'd. */\nexport interface AndGroup {\n rules: FilterRule[];\n}\n\n/**\n * The compound expression owned by the Rules pill.\n *\n * Groups are OR'd (DNF). When `groups.length === 0` no compound predicate\n * applies and the Rules pill still renders in its default `Rules ▾` state.\n */\nexport interface CompoundExpression {\n groups: AndGroup[];\n}\n\n/** Client-side state shape for the v2 filter UI. */\nexport interface FilterStateV2 {\n /**\n * Simple pills. Multiple pills for the same field remain distinct so\n * host applications can preserve the user's filter expression.\n */\n topLevelRules: TopLevelFilterRule[];\n /** Rules pill content. Empty `groups` means no compound rules are applied. */\n compound: CompoundExpression;\n}\n\n/**\n * Filter-bar size variant. Drives the size of every nested PDS component\n * (Button, Input, Combobox, IconButton, etc.) plus the hand-tuned\n * dimensions of the Filter UI v2 styled primitives (pill heights,\n * font sizes, icon glyph sizes). Two values supported:\n *\n * - `'sm'` — 12px font, 12px icons, 24px-tall inputs/pills. Designed\n * for the compact DataTable layout.\n * - `'md'` (default) — 14px font, 16px icons, 32px-tall inputs/pills. Designed\n * for the standard DataTable layout.\n *\n * The active default is owned by `FilterBar`'s `size` prop, not this type.\n */\nexport type FilterSize = 'sm' | 'md';\n\n/** The empty state — no filters applied. */\nexport const EMPTY_FILTER_STATE: FilterStateV2 = Object.freeze({\n topLevelRules: [],\n compound: Object.freeze({ groups: [] }) as CompoundExpression,\n}) as FilterStateV2;\n\n/** True when no filters are applied — no pills and no compound groups. */\nexport function isEmptyState(state: FilterStateV2): boolean {\n return state.topLevelRules.length === 0 && state.compound.groups.length === 0;\n}\n","import type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport {\n getConditionOperator,\n hasCompleteConditionValue,\n isCompleteDateRange,\n isCompleteNumericComparisonValue,\n isNumericComparison,\n isRangeOperator,\n isValuelessOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n AndGroup,\n FilterOperator,\n FilterRule,\n FilterStateV2,\n TopLevelFilterRule,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\n/**\n * Shared runtime validators for `FilterStateV2`, consumed by the URL\n * codec, the saved-view dual-write helpers, and `useFilterStateV2`.\n *\n * Validation is defense-in-depth: the type system prevents bad shapes\n * in code we control, but URL state and saved-view blobs are external\n * input — corrupted bookmarks, bad clipboard pastes, future-build\n * rules rolled back to an older build, attacker-crafted params — and\n * the validators are the last line of defense before anything reaches\n * the hook, the bar, or the adapter.\n */\n\n// Mirrors the `FilterOperator` union in `types.ts`. Kept as a `Set`\n// rather than `Object.values` so the runtime lookup stays O(1) and so\n// changes to the union don't silently invalidate this guard (TypeScript\n// will flag the divergence at the `OPERATOR_SET satisfies …` site below\n// the table — see `OPERATOR_SET` in this file).\nconst OPERATOR_SET: ReadonlySet<FilterOperator> = new Set<FilterOperator>([\n 'is',\n 'is_not',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'contains',\n 'does_not_contain',\n 'is_empty',\n 'is_not_empty',\n 'is_true',\n 'is_false',\n 'before',\n 'after',\n 'between',\n]);\n\n/**\n * Returns `true` when `value` is a structurally-valid `FilterStateV2`,\n * including per-rule content validation. A `topLevelRules` element\n * with a non-string `fieldId`, an operator not in the known\n * vocabulary, or a value of an unsupported type is rejected — a\n * shallow shape sniff would let those reach the adapter.\n */\nexport function isFilterStateV2(value: unknown): value is FilterStateV2 {\n if (typeof value !== 'object' || value == null) {\n return false;\n }\n const v = value as { topLevelRules?: unknown; compound?: unknown };\n if (!Array.isArray(v.topLevelRules)) {\n return false;\n }\n if (!v.topLevelRules.every(isTopLevelFilterRule)) {\n return false;\n }\n if (typeof v.compound !== 'object' || v.compound == null) {\n return false;\n }\n const compound = v.compound as { groups?: unknown };\n if (!Array.isArray(compound.groups)) {\n return false;\n }\n if (!compound.groups.every(isAndGroup)) {\n return false;\n }\n return true;\n}\n\nfunction isAndGroup(value: unknown): value is AndGroup {\n if (typeof value !== 'object' || value == null) {\n return false;\n }\n const v = value as { rules?: unknown };\n if (!Array.isArray(v.rules)) {\n return false;\n }\n return v.rules.every(isFilterRule);\n}\n\nfunction isFilterRule(value: unknown): value is FilterRule {\n if (typeof value !== 'object' || value == null) {\n return false;\n }\n const v = value as { fieldId?: unknown; operator?: unknown; value?: unknown };\n if (typeof v.fieldId !== 'string' || v.fieldId.length === 0) {\n return false;\n }\n if (\n typeof v.operator !== 'string' ||\n (!OPERATOR_SET.has(v.operator as FilterOperator) && !/^custom:.+/.test(v.operator))\n ) {\n return false;\n }\n if (!isFilterRuleValue(v.value)) {\n return false;\n }\n return true;\n}\n\nfunction isTopLevelFilterRule(value: unknown): value is TopLevelFilterRule {\n if (!isFilterRule(value)) {\n return false;\n }\n const v = value as { id?: unknown };\n return typeof v.id === 'string' && v.id.length > 0;\n}\n\nfunction isFilterRuleValue(value: unknown): boolean {\n if (value == null) {\n return true;\n }\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return true;\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return true;\n }\n if (value.every((entry) => typeof entry === 'string')) {\n return true;\n }\n return value.every(\n (group) =>\n Array.isArray(group) &&\n group.every((entry) => typeof entry === 'object' && entry != null && !Array.isArray(entry)),\n );\n }\n if (typeof value === 'object') {\n const record = value as Record<string, unknown>;\n // An empty object is the freshly-seeded `between` draft after a JSON\n // round-trip has dropped its `undefined` endpoints — still a date range.\n const keys = Object.keys(record);\n if (keys.every((key) => key === 'startDate' || key === 'endDate')) {\n const { startDate, endDate } = record;\n return (\n (startDate == null || typeof startDate === 'string') &&\n (endDate == null || typeof endDate === 'string')\n );\n }\n }\n return false;\n}\n\n/**\n * Strip rules referencing unregistered `fieldId`s from a decoded state.\n * Pairs with `isFilterStateV2` for defense-in-depth: even after the\n * shape guard passes, a rule with a `fieldId` that doesn't exist in the\n * current resource's registry would silently render nothing in the UI\n * but still reach the adapter and ship to the backend. Pruning closes\n * that gap.\n *\n * Empty AND-groups created by pruning are also dropped, since the\n * adapter prunes them on serialize anyway and the editor UI hides\n * empty groups too.\n *\n * Skips its own work and returns the input unchanged when `registry`\n * is `undefined` — useful for callers that hydrate before the registry\n * is built.\n *\n * For valueless operators (`is_empty`, etc.) the value contract is\n * `null`. Non-valueless operators keep in-progress draft values (an empty\n * string / empty array) so a pill the user is mid-editing survives the\n * report/hydrate round-trip and stays visible — top-level and compound\n * rules are treated alike here, and the serialize boundary\n * (`hasCompleteValue`) is what drops incomplete rules from the request.\n */\nexport function pruneToRegistry(\n state: FilterStateV2,\n registry: FieldRegistry | undefined,\n): FilterStateV2 {\n if (!registry) {\n return state;\n }\n const coerced = coerceBooleanRules(state, registry);\n const topLevelRules = coerced.topLevelRules.filter((rule) =>\n isRuleAllowed(rule, registry, { allowDraftValues: true }),\n );\n const groups = coerced.compound.groups\n .map((group) => ({\n rules: group.rules.filter((rule) =>\n isRuleAllowed(rule, registry, { allowDraftValues: true }),\n ),\n }))\n .filter((group) => group.rules.length > 0);\n return { topLevelRules, compound: { groups } };\n}\n\n/**\n * Normalizes boolean-field rules into the in-memory contract the new UI\n * and adapter expect — `is` / `is_not` + a real boolean `value`. Two\n * legacy shapes are coerced, both only for rules whose registered field\n * type is `boolean`:\n *\n * - Pre–value-control rules using the `is_true` / `is_false` operators\n * (from saved views) become `is` + boolean `value` so they survive\n * operator-vocabulary pruning and render in the new UI.\n * - v1-URL bookmarks hydrate query params as strings, so\n * `filter[custom][active]=true` arrives as `{ operator: 'is', value:\n * 'true' }`. The string is coerced back to a boolean so the adapter\n * emits the legacy `is_true` / `is_false` wire operator instead of\n * shipping the raw string (which would break old boolean bookmarks).\n * Non-`'true'`/`'false'` strings are left as-is and dropped later by\n * `isRuleAllowed`.\n */\n// Generic over the rule type so a `TopLevelFilterRule` in yields a\n// `TopLevelFilterRule` out — every branch spreads `...rule`, so the\n// `id` (and any other keys) are preserved at runtime, and the signature\n// keeps that guarantee in the type system without a call-site cast.\nfunction coerceBooleanRule<T extends FilterRule>(rule: T, registry: FieldRegistry): T {\n const field = registry.get(rule.fieldId);\n if (!field || field.condition != null || field.type !== 'boolean') {\n return rule;\n }\n if (rule.operator === 'is_true') {\n return { ...rule, operator: 'is', value: true };\n }\n if (rule.operator === 'is_false') {\n return { ...rule, operator: 'is', value: false };\n }\n if (rule.operator === 'is' || rule.operator === 'is_not') {\n if (rule.value === 'true') {\n return { ...rule, value: true };\n }\n if (rule.value === 'false') {\n return { ...rule, value: false };\n }\n }\n return rule;\n}\n\nfunction coerceBooleanRules(state: FilterStateV2, registry: FieldRegistry): FilterStateV2 {\n return {\n topLevelRules: state.topLevelRules.map((r) => coerceBooleanRule(r, registry)),\n compound: {\n groups: state.compound.groups.map((g) => ({\n rules: g.rules.map((r) => coerceBooleanRule(r, registry)),\n })),\n },\n };\n}\n\nfunction isDraftRuleValue(rule: FilterRule, registry: FieldRegistry): boolean {\n const field = registry.get(rule.fieldId);\n if (!field) {\n return false;\n }\n const config = getConditionOperator(field, rule.operator);\n if (config != null) {\n switch (config.valueType) {\n case 'none':\n case 'boolean':\n return false;\n case 'string_array':\n return Array.isArray(rule.value) && rule.value.length === 0;\n default:\n return rule.value === '' || rule.value == null;\n }\n }\n if (isValuelessOperator(rule.operator)) {\n return false;\n }\n // A half-picked range is the normal state while the calendar is open, so it\n // has to survive the hydrate round-trip the same way an empty text input does.\n if (isRangeOperator(rule.operator)) {\n return !isCompleteDateRange(rule.value);\n }\n switch (field.type) {\n case 'multi_choices':\n case 'tags_conditions':\n case 'signals':\n return Array.isArray(rule.value) && rule.value.length === 0;\n case 'date':\n return rule.value === '' || rule.value == null;\n case 'date_range':\n return false;\n case 'boolean':\n return false;\n default:\n return rule.value === '' || rule.value == null;\n }\n}\n\nfunction isRuleAllowed(\n rule: FilterRule,\n registry: FieldRegistry,\n options: { allowDraftValues: boolean } = { allowDraftValues: false },\n): boolean {\n const field = registry.get(rule.fieldId);\n if (field == null) {\n return false;\n }\n // Field-aware, so a saved view or hydrated URL can't smuggle in an\n // operator the field's `allowedOperators` keeps out of the popover.\n const allowedOperators = registry.operatorsFor(rule.fieldId);\n if (!allowedOperators.includes(rule.operator)) {\n return false;\n }\n if (field.condition != null) {\n return (\n hasCompleteConditionValue(rule, field) ||\n (options.allowDraftValues && isDraftRuleValue(rule, registry))\n );\n }\n if (isValuelessOperator(rule.operator)) {\n return rule.value == null;\n }\n if (options.allowDraftValues && isDraftRuleValue(rule, registry)) {\n return true;\n }\n if (isRangeOperator(rule.operator)) {\n return isCompleteDateRange(rule.value);\n }\n // A comparison is only meaningful against a number; an `integer` field\n // also rejects fractions so `gt 2.5` can't reach an integer column.\n if (isNumericComparison(rule.operator, field.type)) {\n return isCompleteNumericComparisonValue(rule.value, field.type);\n }\n // Boolean fields carry a real boolean for `is` / `is_not`. A leftover\n // string (e.g. an un-coerced v1-URL value that wasn't `'true'`/`'false'`)\n // would otherwise reach the adapter and ship as a raw string, so drop it.\n if (registry.get(rule.fieldId)?.type === 'boolean') {\n return typeof rule.value === 'boolean';\n }\n if (registry.get(rule.fieldId)?.type === 'date') {\n return typeof rule.value === 'string' && rule.value.length > 0;\n }\n if (registry.get(rule.fieldId)?.type === 'multi_choices') {\n if (Array.isArray(rule.value)) {\n return rule.value.length > 0;\n }\n return typeof rule.value === 'string' && rule.value.length > 0;\n }\n if (registry.get(rule.fieldId)?.type === 'date_range') {\n return isCompleteDateRange(rule.value);\n }\n const conditionGroupType = registry.get(rule.fieldId)?.type;\n if (conditionGroupType === 'tags_conditions' || conditionGroupType === 'signals') {\n return Array.isArray(rule.value) && rule.value.length > 0;\n }\n // Only boolean fields carry boolean values. A boolean on a non-boolean\n // field (a corrupted/crafted blob) would otherwise be rewritten into a\n // boolean-only wire operator (`is_true`/`is_false`) by the adapter, so\n // reject it here at the pruning boundary.\n return rule.value != null && typeof rule.value !== 'boolean';\n}\n\n/**\n * Whether `rule` carries a complete value for its field type — the\n * serialize-boundary predicate `pruneEmptyRulesForSerialize` uses to drop\n * half-edited rules from the request (a value-requiring operator like\n * `is_not` with no value yet makes the backend reject the whole request).\n *\n * Deliberately stricter than `isRuleAllowed`'s hydration policy, which keeps\n * an empty string so an in-progress pill survives the state round-trip and\n * stays visible for the user to finish. Checks value completeness only — it\n * does not gate operator vocabulary or registry membership.\n */\nexport function hasCompleteValue(rule: FilterRule, registry: FieldRegistry): boolean {\n const field = registry.get(rule.fieldId);\n if (field?.condition != null) {\n return hasCompleteConditionValue(rule, field);\n }\n if (isValuelessOperator(rule.operator)) {\n return rule.value == null;\n }\n const { value } = rule;\n if (value == null) {\n return false;\n }\n if (isRangeOperator(rule.operator)) {\n return isCompleteDateRange(value);\n }\n if (field != null && isNumericComparison(rule.operator, field.type)) {\n return isCompleteNumericComparisonValue(value, field.type);\n }\n switch (registry.get(rule.fieldId)?.type) {\n case 'boolean':\n return typeof value === 'boolean';\n case 'date':\n return typeof value === 'string' && value.length > 0;\n case 'multi_choices':\n return Array.isArray(value)\n ? value.length > 0\n : typeof value === 'string' && value.length > 0;\n case 'tags_conditions':\n case 'signals':\n return Array.isArray(value) && value.length > 0;\n case 'date_range':\n return isCompleteDateRange(value);\n default:\n if (typeof value === 'string') {\n return value.length > 0;\n }\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n return typeof value !== 'boolean';\n }\n}\n","import { isEqual } from 'lodash-es';\nimport { type SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { v4 as uuid } from 'uuid';\n\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport { isValuelessOperator } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport {\n type CompoundExpression,\n EMPTY_FILTER_STATE,\n type FilterRule,\n type FilterStateV2,\n type TopLevelFilterRule,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport {\n hasCompleteValue,\n pruneToRegistry,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/validation';\n\n// Rule ids outlive the page that minted them — they round-trip through the\n// `fv2` URL param and saved views — so a per-page counter would eventually\n// reissue an id an older view already uses.\nconst nextRuleId = () => `top-rule-${uuid()}`;\n\nexport interface UseFilterStateV2Options {\n /** Initial state. Defaults to the empty state. */\n initialState?: FilterStateV2;\n /**\n * When `false`, the Rules pill is hidden and the hook force-pins\n * `compound.groups` to `[]`. Mutations targeting compound state become\n * no-ops. Defaults to `true`.\n *\n * Each owning index view decides whether Advanced Filter Rules is in or\n * out for its surface.\n */\n advancedRulesEnabled?: boolean;\n /** Field registry for the resource this hook is filtering. */\n registry: FieldRegistry;\n}\n\nexport interface UseFilterStateV2Result {\n /**\n * Everything the bar renders: the committed filters plus the pills the\n * user has picked but not yet given a value to.\n */\n state: FilterStateV2;\n /**\n * The filters the parent owns — `state` without in-progress pills. This is\n * what `FilterBar` reports through `onChange`, so a controlled parent that\n * hands it straight back as `initialState` hydrates to exactly what it\n * sent, and nothing has to distinguish that echo from a saved view.\n */\n committedState: FilterStateV2;\n /** Whether the Rules pill is visible. */\n advancedRulesEnabled: boolean;\n\n /**\n * Replace the whole state, in-progress pills included. Useful for\n * saved-view loading and URL hydration, where the caller means \"these\n * are the filters now\" and a surviving pill would be a filter the\n * caller didn't ask for.\n */\n setState: (next: FilterStateV2) => void;\n /**\n * Replace the compound expression, leaving every pill alone. The\n * `AdvancedFilterRulesPopover` edits the compound expression as a value\n * and emits one full expression per user action, so the hook exposes no\n * per-rule compound mutators.\n */\n setCompound: (compound: CompoundExpression) => void;\n /** Reset to the empty state — used when the user clicks \"Clear all filters\". */\n reset: () => void;\n\n /**\n * Append a new top-level rule and return the freshly-generated id.\n * The caller uses the returned id to identify the new pill (e.g. for\n * \"open the editor for the rule I just created\"). Each call always\n * creates a new rule — duplicate `fieldId`s are allowed so a user\n * can pick the same field twice from the picker and get two pills.\n */\n addTopLevelRule: (rule: Omit<FilterRule, never>) => string;\n /**\n * Update an existing top-level rule by `id`. No-op if no rule with\n * that id exists (e.g. it was removed between event and dispatch).\n */\n updateTopLevelRule: (id: string, rule: SetStateAction<FilterRule>) => void;\n /** Remove the top-level rule with the given id. No-op if absent. */\n removeTopLevelRule: (id: string) => void;\n}\n\n/**\n * Owns `FilterStateV2` for a filter surface and exposes a small mutator API.\n *\n * When `advancedRulesEnabled` is false, `compound.groups` is forced to\n * `[]`.\n *\n * Putting that invariant here (rather than in the components) keeps\n * `TableControls/FiltersV2` callers from accidentally leaking compound state when\n * the owning view has opted out.\n *\n * The mutator surface is deliberately small: top-level rules get\n * upsert/remove, the compound expression gets whole-value writes. That\n * matches how the UI emits changes — simple pills mutate one rule at a\n * time; the rules popover always emits a full compound expression as\n * one `onChange`.\n *\n * A pill the user has picked but not yet valued is held by the bar rather\n * than committed. Which pills those are is recorded when the picker mints\n * them rather than inferred: they are never reported, so incoming state never\n * describes one and hydration has nothing to reconcile against them. They\n * stay in the same row as the committed pills, so giving one a value doesn't\n * move it.\n */\nexport function useFilterStateV2(options: UseFilterStateV2Options): UseFilterStateV2Result {\n const { initialState = EMPTY_FILTER_STATE, advancedRulesEnabled = true, registry } = options;\n\n // Initial state is sanitized: rules whose `fieldId` is not in the\n // current registry, or whose operator isn't in that field's allowed\n // vocabulary, are stripped. This is defense-in-depth on top of\n // `isFilterStateV2` — the URL/saved-view validators already enforce\n // the wire-shape invariants, but neither knows which `fieldId`s the\n // current view supports. Without this prune, a saved view exported\n // from the Cases page and loaded on Accounts would silently render\n // empty pills but still ship the unknown-field rule to the backend.\n const [internal, setInternal] = useState<InternalState>(() => ({\n all: pruneToRegistry(initialState, registry),\n heldIds: new Set<string>(),\n }));\n const { all, heldIds } = internal;\n const lastHydratedState = useRef(all);\n\n useEffect(() => {\n const nextHydratedState = pruneToRegistry(initialState, registry);\n // Re-hydrating on an unchanged value would reset the user's edits every\n // render for a parent that rebuilds `initialState` inline.\n const hydrate = !isEqual(nextHydratedState, lastHydratedState.current);\n if (hydrate) {\n lastHydratedState.current = nextHydratedState;\n }\n setInternal((prev) => {\n // Held pills outlive hydration but not their field: a resource switch\n // can retire the field or the operator one was picked for.\n const pruned = pruneHeldRules(prev, registry);\n return hydrate ? withHeldRules(nextHydratedState, pruned) : pruned;\n });\n }, [initialState, registry]);\n\n // Derived effective state: enforce the `advancedRulesEnabled` pin on\n // every render, not just on mutation. If a parent flips\n // `advancedRulesEnabled` from `true` to `false` after mount (e.g. a\n // feature flag or view config update), `state.compound.groups` may\n // still hold the user's previous expression. Computing this here\n // guarantees the hook's exposed `state` always reflects the current\n // `advancedRulesEnabled` value instead of retaining hidden compound\n // conditions.\n const state = useMemo(\n () => enforceAdvancedRulesEnabled(all, advancedRulesEnabled),\n [all, advancedRulesEnabled],\n );\n\n const committedState = useMemo(\n () =>\n heldIds.size === 0\n ? state\n : {\n ...state,\n topLevelRules: state.topLevelRules.filter((rule) => !heldIds.has(rule.id)),\n },\n [state, heldIds],\n );\n\n const setState = useCallback(\n (next: FilterStateV2) => {\n setInternal({ all: pruneToRegistry(next, registry), heldIds: new Set<string>() });\n },\n [registry],\n );\n\n const setCompound = useCallback((compound: CompoundExpression) => {\n setInternal((prev) => ({ ...prev, all: { ...prev.all, compound } }));\n }, []);\n\n const reset = useCallback(() => {\n setInternal({\n all: { topLevelRules: [], compound: { groups: [] } },\n heldIds: new Set<string>(),\n });\n }, []);\n\n const addTopLevelRule = useCallback(\n (rule: FilterRule): string => {\n const id = nextRuleId();\n const added: TopLevelFilterRule = { ...rule, id };\n setInternal((prev) => ({\n all: { ...prev.all, topLevelRules: [...prev.all.topLevelRules, added] },\n heldIds:\n registry.get(rule.fieldId)?.condition != null || isHeldRule(added, registry)\n ? withId(prev.heldIds, id)\n : prev.heldIds,\n }));\n return id;\n },\n [registry],\n );\n\n const updateTopLevelRule = useCallback(\n (id: string, update: SetStateAction<FilterRule>) => {\n setInternal((prev) => {\n const idx = prev.all.topLevelRules.findIndex((r) => r.id === id);\n const currentRule = prev.all.topLevelRules[idx];\n if (currentRule == null) {\n return prev;\n }\n const rule = typeof update === 'function' ? update(currentRule) : update;\n const topLevelRules = [...prev.all.topLevelRules];\n topLevelRules[idx] = { ...rule, id };\n // A pill is a filter exactly while it has a value: it starts being\n // reported when the user gives it one and stops when the user takes it\n // away again. Clearing to an empty value (`''`, `[]`, `false`) is a\n // choice, not the absence of one, so it stays a filter.\n const heldIds = isHeldRule(rule, registry)\n ? withId(prev.heldIds, id)\n : withoutId(prev.heldIds, id);\n return { all: { ...prev.all, topLevelRules }, heldIds };\n });\n },\n [registry],\n );\n\n const removeTopLevelRule = useCallback((id: string) => {\n setInternal((prev) => {\n const topLevelRules = prev.all.topLevelRules.filter((r) => r.id !== id);\n if (topLevelRules.length === prev.all.topLevelRules.length) {\n return prev;\n }\n return {\n all: { ...prev.all, topLevelRules },\n heldIds: prev.heldIds.has(id) ? withoutId(prev.heldIds, id) : prev.heldIds,\n };\n });\n }, []);\n\n return {\n state,\n committedState,\n advancedRulesEnabled,\n setState,\n setCompound,\n reset,\n addTopLevelRule,\n updateTopLevelRule,\n removeTopLevelRule,\n };\n}\n\ninterface InternalState {\n /** Every pill in row order; `heldIds` says which of them the bar holds. */\n all: FilterStateV2;\n heldIds: ReadonlySet<string>;\n}\n\n/**\n * A pill the picker minted that has no value yet. `null` and not \"empty\":\n * `''` and `[]` are values a user can choose, and a filter cleared to one is\n * still a filter.\n */\nfunction isHeldRule(rule: FilterRule, registry: FieldRegistry): boolean {\n if (registry.get(rule.fieldId)?.condition != null) {\n return !hasCompleteValue(rule, registry);\n }\n return !isValuelessOperator(rule.operator) && rule.value == null;\n}\n\nfunction heldRulesOf(state: InternalState): ReadonlyArray<TopLevelFilterRule> {\n return state.heldIds.size === 0\n ? []\n : state.all.topLevelRules.filter((rule) => state.heldIds.has(rule.id));\n}\n\n/**\n * Lays incoming committed rules into the row, keeping the held pills where the\n * user left them: a held pill goes back after however many committed rules\n * preceded it before. An id the incoming state now uses is the parent's, so the\n * held pill of that id gives way rather than duplicating it.\n */\nfunction withHeldRules(committed: FilterStateV2, prev: InternalState): InternalState {\n if (prev.heldIds.size === 0) {\n return { all: committed, heldIds: prev.heldIds };\n }\n const incoming = committed.topLevelRules;\n const incomingIds = new Set(incoming.map((rule) => rule.id));\n const topLevelRules: TopLevelFilterRule[] = [];\n const heldIds = new Set<string>();\n // Walked in one pass: `taken` is how much of the incoming row has been laid\n // down, `committedBefore` how many committed rules preceded the pill in the\n // old row, so each held pill lands at the same offset it had.\n let taken = 0;\n let committedBefore = 0;\n prev.all.topLevelRules.forEach((rule) => {\n if (!prev.heldIds.has(rule.id)) {\n committedBefore += 1;\n return;\n }\n if (incomingIds.has(rule.id)) {\n return;\n }\n while (taken < committedBefore && taken < incoming.length) {\n topLevelRules.push(incoming[taken]);\n taken += 1;\n }\n topLevelRules.push(rule);\n heldIds.add(rule.id);\n });\n if (heldIds.size === 0) {\n return { all: committed, heldIds };\n }\n while (taken < incoming.length) {\n topLevelRules.push(incoming[taken]);\n taken += 1;\n }\n return { all: { ...committed, topLevelRules }, heldIds };\n}\n\n/**\n * Drops held pills whose field or operator the registry no longer supports,\n * preserving the state's identity when there are none so an unchanged registry\n * can't loop the effect.\n */\nfunction pruneHeldRules(state: InternalState, registry: FieldRegistry): InternalState {\n const droppedIds = new Set(\n heldRulesOf(state)\n .filter(\n (rule) =>\n !registry.has(rule.fieldId) ||\n !registry.operatorsFor(rule.fieldId).includes(rule.operator),\n )\n .map((rule) => rule.id),\n );\n if (droppedIds.size === 0) {\n return state;\n }\n const heldIds = new Set(state.heldIds);\n droppedIds.forEach((id) => heldIds.delete(id));\n return {\n all: {\n ...state.all,\n topLevelRules: state.all.topLevelRules.filter((rule) => !droppedIds.has(rule.id)),\n },\n heldIds,\n };\n}\n\nfunction withId(ids: ReadonlySet<string>, id: string): ReadonlySet<string> {\n return ids.has(id) ? ids : new Set(ids).add(id);\n}\n\nfunction withoutId(ids: ReadonlySet<string>, id: string): ReadonlySet<string> {\n if (!ids.has(id)) {\n return ids;\n }\n const next = new Set(ids);\n next.delete(id);\n return next;\n}\n\nfunction enforceAdvancedRulesEnabled(\n state: FilterStateV2,\n advancedRulesEnabled: boolean,\n): FilterStateV2 {\n if (advancedRulesEnabled) {\n return state;\n }\n if (state.compound.groups.length === 0) {\n return state;\n }\n return { ...state, compound: { groups: [] } };\n}\n","import { isEqual } from 'lodash-es';\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport styled from 'styled-components';\n\nimport { Color, Spacing } from '@persona/design-tokens';\nimport AdvancedFilterRulesPopover from 'design-system/components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRulesPopover';\nimport type { FieldRegistry } from 'design-system/components/DataTable/TableControls/FiltersV2/FieldRegistry';\nimport {\n FILTER_SIZE_TOKENS,\n FilterBarContext,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/filter-size-context';\nimport {\n resolveValueControl,\n type ValueControlResolver,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/FilterBar/value-control-resolver';\nimport FilterPickerMenu from 'design-system/components/DataTable/TableControls/FiltersV2/FilterPickerMenu/FilterPickerMenu';\nimport FilterPill from 'design-system/components/DataTable/TableControls/FiltersV2/FilterPill/FilterPill';\nimport FilterPopover from 'design-system/components/DataTable/TableControls/FiltersV2/FilterPopover/FilterPopover';\nimport {\n carriesDateRange,\n emptyValueForRule,\n isMinutePrecisionDate,\n reconcileValueForOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport RulesPill from 'design-system/components/DataTable/TableControls/FiltersV2/RulesPill/RulesPill';\nimport type {\n FilterField,\n FilterOperator,\n FilterRuleValue,\n FilterSize,\n FilterStateV2,\n TopLevelFilterRule,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\nimport { useFilterStateV2 } from 'design-system/components/DataTable/TableControls/FiltersV2/useFilterStateV2';\nimport { hasCompleteValue } from 'design-system/components/DataTable/TableControls/FiltersV2/validation';\nimport { usePDSStrings } from 'design-system/lib/i18n';\nimport { semanticColor } from 'design-system/lib/semanticColor';\nimport { useScrollOverflow } from 'design-system/lib/useScrollOverflow';\nimport { TransitionDuration } from 'design-system/variables/transitions';\n\n/**\n * Filter UI v2 — the top-level FilterBar component.\n *\n * Composes the picker, simple-rule pills, simple-rule popovers, Rules pill,\n * Advanced Filter Rules popover, and type-aware value controls into one bar.\n *\n * Popover open/close transitions flow through Radix's `onOpenChange`\n * callbacks rather than explicit `onClick` handlers on the pills. That keeps\n * the user's pill click and Radix's `Slot`-injected toggle handler from\n * fighting over which one wins (the symptom looks like \"the popover opens\n * and immediately closes\" — both fire, the first sets open=true, the second\n * toggles open back to false).\n */\n\nexport interface FilterBarProps {\n /**\n * Registry built from this resource's `field_key_to_info` response.\n * The registry defines which fields are filterable, each field's type,\n * option labels, and custom-field parent grouping.\n */\n registry: FieldRegistry;\n /**\n * Initial state. Defaults to the empty state. For URL/saved-view\n * hydration, pass the decoded `FilterStateV2` here.\n *\n * Re-read when it changes. This lets saved-view and URL hydration swap\n * the whole filter state after mount without requiring the caller to\n * remount the bar.\n *\n * A pill without a value isn't part of this state and survives hydration —\n * it is the bar's while it has none, and only its field leaving the registry\n * drops it.\n */\n initialState?: FilterStateV2;\n /**\n * Called whenever the structured filter state changes.\n *\n * Kept as a single-arg callback so the most common consumer — a\n * `setState`-style parent driving the bar as a controlled component\n * (`<FilterBar initialState={state} onChange={setState} />`) — can\n * pass `setState` directly.\n *\n * Reports only valued filters, so feeding the reported state straight\n * back as `initialState` is a no-op.\n */\n onChange?: (state: FilterStateV2) => void;\n /**\n * Whether this bar should show the Rules pill + Advanced Filter Rules\n * popover. When `false`, compound state is pinned to empty.\n *\n * @defaultValue `true`\n */\n advancedRulesEnabled?: boolean;\n /**\n * Enables emitting relative-date metadata from preset interactions. Existing\n * metadata is always read and resolved regardless of this value.\n */\n relativeDatesEnabled?: boolean;\n /**\n * Enables minute-precision pickers for fields whose metadata supports them.\n *\n * @defaultValue `false`\n */\n dateTimesEnabled?: boolean;\n /**\n * Keeps the Add-filter picker from building a second top-level pill on a\n * field that already has one: a field in use drops out of the picker, and\n * the trigger disappears once no field is left. Compound rules are\n * unaffected — a field can back a pill and any number of Advanced Filter\n * Rules at once. Leave off for hosts whose serializer reads repeated rules\n * on one field as a conjunction (e.g. two date bounds spanning a range).\n *\n * Rules arriving through `initialState` are rendered as given; a saved view\n * holding duplicates keeps them rather than having pills silently dropped\n * out from under it, so a host that stored duplicates before enabling this\n * can migrate them on its own terms.\n *\n * @defaultValue `false`\n */\n singleUseFields?: boolean;\n /**\n * Size variant for every Filter UI v2 subcomponent. `'md'` is the\n * standard-DataTable default (14px font, 16px icons, 32px-tall\n * controls). `'sm'` is the compact-DataTable variant (12px font,\n * 12px icons, 24px-tall controls). Propagated to subcomponents via\n * `FilterBarContext` so each one reads the active size without\n * the caller having to pass it through every level.\n *\n * @defaultValue `'md'`\n */\n size?: FilterSize;\n /**\n * Renders host-specific field types before falling back to PDS controls.\n * Return a nullish value to use the built-in resolver.\n */\n valueControlResolver?: ValueControlResolver;\n}\n\nconst Bar = styled.div`\n display: flex;\n align-items: center;\n gap: ${Spacing[2]};\n flex-wrap: nowrap;\n min-width: 0;\n padding: ${Spacing[2]} 0;\n`;\n\nconst SCROLL_FADE_WIDTH = 48;\n\n// Upper bound on how long to wait for a `scrollend` event before opening a\n// newly added pill's popover anyway. Smooth-scroll duration is browser\n// controlled (proportional to distance), so this is a generous ceiling\n// rather than an exact match — it only matters for browsers that don't\n// support `scrollend` at all.\nconst SCROLL_SETTLE_FALLBACK_MS = 400;\n\n// Buffer distance (px) an open pill's trigger may be clipped by the scroll\n// track's edge before its popover auto-closes. See the scroll-out-of-view\n// effect below for why a small buffer (rather than closing at the first\n// clipped pixel) is worth having.\nconst POPOVER_CLOSE_BUFFER_PX = 8;\n\n// Pills draw their focus ring via `outline: 2px solid` + `outline-offset:\n// 1px` (see `focusWithinOutline`), which bleeds 3px past the pill's box on\n// every side. `overflow-*: hidden` below would otherwise clip that ring for\n// the first/last pill and for any pill focused mid-scroll. Padding the\n// track by the ring's bleed distance gives it room to render, and the\n// matching negative margin cancels the padding back out so the track's\n// visible box — and the rest of the bar's layout — doesn't shift.\nconst PILL_FOCUS_RING_SPACE = 3;\n\n/**\n * Builds the `mask-image` gradient that fades the scroll track's edges.\n *\n * A `mask-image` (rather than a same-colored overlay painted on top) fades\n * the track's *entire rendered output* — pill backgrounds, borders, and any\n * focus ring that bleeds into the padding above — because masking\n * composites against the real pixels the element paints, instead of\n * relying on an opaque sibling layer to visually cover them. An overlay\n * approach only hides whatever happens to sit below it in paint order;\n * a mask fades everything, including outlines.\n */\nconst buildEdgeMaskImage = (showLeftFade: boolean, showRightFade: boolean) => {\n const leftStop = showLeftFade ? `transparent 0, black ${SCROLL_FADE_WIDTH}px` : 'black 0';\n const rightStop = showRightFade\n ? `black calc(100% - ${SCROLL_FADE_WIDTH}px), transparent 100%`\n : 'black 100%';\n return `linear-gradient(to right, ${leftStop}, ${rightStop})`;\n};\n\n// Groups the pill scroll track and compact `⊕` picker so the picker sits\n// immediately after the last pill when the row fits. `width: max-content`\n// sizes to pill + picker width; `max-width: 100%` caps the group at the\n// bar's remaining width so the track can shrink and scroll when it doesn't.\nconst PillsScrollRegion = styled.div`\n display: flex;\n align-items: center;\n gap: ${Spacing[1]};\n flex: 0 1 auto;\n min-width: 0;\n width: max-content;\n max-width: 100%;\n`;\n\nconst PillsScrollTrack = styled.div<{ $showLeftFade: boolean; $showRightFade: boolean }>`\n display: flex;\n align-items: center;\n flex: 1 1 auto;\n min-width: 0;\n flex-wrap: nowrap;\n gap: ${Spacing[1]};\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n padding: ${PILL_FOCUS_RING_SPACE}px;\n margin: -${PILL_FOCUS_RING_SPACE}px;\n -webkit-mask-image: ${({ $showLeftFade, $showRightFade }) =>\n buildEdgeMaskImage($showLeftFade, $showRightFade)};\n mask-image: ${({ $showLeftFade, $showRightFade }) =>\n buildEdgeMaskImage($showLeftFade, $showRightFade)};\n transition:\n -webkit-mask-image ${TransitionDuration.Fast} ease-out,\n mask-image ${TransitionDuration.Fast} ease-out;\n\n & > * {\n flex: 0 0 auto;\n }\n\n &::-webkit-scrollbar {\n display: none;\n }\n`;\n\nconst Divider = styled.div<{ $size: FilterSize; $flush?: boolean }>`\n width: 1px;\n height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].controlHeight};\n background: ${({ theme }) => semanticColor(theme, 'BorderSubtle', Color.BorderDivider)};\n flex: 0 0 auto;\n margin: 0 ${({ $flush }) => ($flush ? 0 : Spacing[1])};\n`;\n\nconst PickerSlot = styled.div`\n flex: 0 0 auto;\n`;\n\n// Tighter gap between the divider and labeled picker when no pills exist yet.\nconst EmptyTrailingGroup = styled.div`\n display: flex;\n align-items: center;\n gap: ${Spacing[1]};\n flex: 0 0 auto;\n`;\n\n/**\n * Returns the previous array whenever its contents still match, so the field\n * ids can be derived on every render without giving the picker a new array to\n * rebuild its whole option tree from. Editing a pill's value rewrites the\n * rules while leaving the fields in use unchanged.\n */\nfunction useStableFieldIds(fieldIds: readonly string[] | undefined) {\n const stable = useRef(fieldIds);\n const previous = stable.current;\n if (\n previous == null ||\n fieldIds == null ||\n previous.length !== fieldIds.length ||\n fieldIds.some((id, index) => previous[index] !== id)\n ) {\n stable.current = fieldIds;\n }\n return stable.current;\n}\n\nexport default function FilterBar({\n registry,\n initialState,\n onChange,\n advancedRulesEnabled = true,\n relativeDatesEnabled = false,\n dateTimesEnabled = false,\n singleUseFields = false,\n size = 'md',\n valueControlResolver,\n}: FilterBarProps) {\n const strings = usePDSStrings();\n const filterState = useFilterStateV2({\n registry,\n initialState,\n advancedRulesEnabled,\n });\n\n // Which simple-rule popover is open (by fieldId), or null when none.\n const [editingRuleId, setEditingRuleId] = useState<string | null>(null);\n const [rulesPopoverOpen, setRulesPopoverOpen] = useState(false);\n\n // Maps rule id -> its pill's DOM node, populated by the ref callback on\n // each `FilterPill` below. Read by the scroll-out-of-view effect to find\n // the currently-open pill without re-querying the DOM.\n const pillNodesRef = useRef(new Map<string, HTMLSpanElement>());\n\n // Surface state changes to the parent. The callback is held in a\n // ref so an inline `onChange={(s) => …}` doesn't re-trigger the\n // effect every render; only a real state change fires it.\n // `lastReportedState` skips the no-op mount emit for the common\n // controlled-state pattern (`initialState={state}` +\n // `onChange={setState}`).\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n const { committedState } = filterState;\n const committedRuleIds = useMemo(\n () => new Set(committedState.topLevelRules.map((rule) => rule.id)),\n [committedState.topLevelRules],\n );\n const lastReportedState = useRef(committedState);\n useEffect(() => {\n if (isEqual(lastReportedState.current, committedState)) {\n return;\n }\n lastReportedState.current = committedState;\n onChangeRef.current?.(committedState);\n }, [committedState]);\n\n // Set by `handlePickField`, read (and cleared) by the scroll-into-view\n // effect below — opening the new pill's popover is deferred until it\n // scrolls into view rather than fired immediately.\n const pendingEditRuleIdRef = useRef<string | null>(null);\n\n // Set by the scroll-into-view effect's `openPendingRule`, consumed once\n // by the scroll-out-of-view close effect below. Distinguishes \"this pill\n // was just opened via the deferred scroll-into-view flow\" (where the\n // observer's first report can reflect sub-pixel settle imprecision, not\n // a real clipped state) from \"the user directly opened an existing pill\n // that already sits partly clipped\" (where that first report is the only\n // signal we'll get, and must be acted on, or the popover would stay open\n // indefinitely anchored to a clipped trigger).\n const openedViaScrollIntoViewRef = useRef(false);\n\n const { addTopLevelRule } = filterState;\n const handlePickField = useCallback(\n (field: FilterField) => {\n // The new pill's popover opens once the scroll-into-view effect below\n // confirms it's visible — opening it immediately let the popover appear\n // and then visually jump mid-animation as the row scrolled the trigger\n // into view.\n const operator = registry.defaultOperatorFor(field.id);\n const id = addTopLevelRule({\n fieldId: field.id,\n operator,\n value: field.condition != null ? emptyValueForRule(field, operator) : null,\n });\n pendingEditRuleIdRef.current = id;\n },\n [addTopLevelRule, registry],\n );\n\n const hasPills = filterState.state.topLevelRules.length > 0;\n\n // Valueless pills are included, so a field leaves the picker the moment it's\n // picked and returns if the pill is abandoned.\n const excludeFieldIds = useStableFieldIds(\n singleUseFields ? filterState.state.topLevelRules.map((rule) => rule.fieldId) : undefined,\n );\n\n const pillsScrollRef = useRef<HTMLDivElement>(null);\n const { hasHorizontalOverflow, hasMoreScrollLeft, hasMoreScrollRight } = useScrollOverflow(\n pillsScrollRef,\n { enabled: hasPills },\n );\n\n // New rules are always appended (see `addTopLevelRule`), so scrolling the\n // track to its far edge reveals whichever pill was just added. Only fires\n // on growth — removing a pill, or the initial mount with a hydrated\n // `initialState`, should not yank the scroll position.\n //\n // `scrollend` reports when the smooth scroll actually finishes; a\n // fallback timer covers browsers without `scrollend` support and the\n // case where nothing needed to scroll (it never fires then).\n const ruleCount = filterState.state.topLevelRules.length;\n const previousRuleCountRef = useRef(ruleCount);\n useEffect(() => {\n const grew = ruleCount > previousRuleCountRef.current;\n previousRuleCountRef.current = ruleCount;\n // `topLevelRules` can also grow via an `initialState` prop swap (the\n // documented saved-view/URL hydration path), not just `handlePickField`.\n // Without a pending id, there's no new pill to scroll to or open — and\n // blindly calling `setEditingRuleId(null)` below would close whatever\n // popover the user already had open.\n if (!grew || pendingEditRuleIdRef.current == null) {\n return undefined;\n }\n const openPendingRule = () => {\n openedViaScrollIntoViewRef.current = true;\n setEditingRuleId(pendingEditRuleIdRef.current);\n pendingEditRuleIdRef.current = null;\n };\n const track = pillsScrollRef.current;\n // `Element.scrollTo` isn't implemented in jsdom (only `window.scrollTo`\n // is stubbed there) — open immediately rather than assume it exists.\n if (!track || !track.scrollTo) {\n openPendingRule();\n return undefined;\n }\n const maxScrollLeft = Math.max(track.scrollWidth - track.clientWidth, 0);\n if (Math.abs(track.scrollLeft - maxScrollLeft) <= 1) {\n // Already at the far edge — nothing to scroll, so no need to wait.\n openPendingRule();\n return undefined;\n }\n let settled = false;\n const finish = () => {\n if (settled) {\n return;\n }\n settled = true;\n track.removeEventListener('scrollend', finish);\n window.clearTimeout(fallbackTimer);\n openPendingRule();\n };\n track.addEventListener('scrollend', finish, { once: true });\n const fallbackTimer = window.setTimeout(finish, SCROLL_SETTLE_FALLBACK_MS);\n track.scrollTo({ left: track.scrollWidth, behavior: 'smooth' });\n return () => {\n track.removeEventListener('scrollend', finish);\n window.clearTimeout(fallbackTimer);\n };\n }, [ruleCount]);\n\n // Close the open pill's popover as soon as any part of its trigger\n // scrolls out of the track's visible area (past a small buffer).\n // Floating-ui positions the popover card relative to the trigger's\n // bounding rect, so a partially clipped trigger already looks broken —\n // no need to wait until it's fully scrolled away.\n //\n // `threshold: 1` schedules a callback as soon as the target's coverage\n // ratio crosses full (1.0) in either direction — checking\n // `intersectionRatio < 1` (rather than `isIntersecting`, which only\n // turns `false` once coverage hits exactly 0) is what actually detects\n // \"no longer entirely covered\". `rootMargin` grows the observed area\n // outward by `POPOVER_CLOSE_BUFFER_PX` on the scroll axis, so a few\n // pixels of clipping (sub-pixel scroll jitter, the tail end of the\n // scroll-into-view animation settling) don't immediately close it.\n useEffect(() => {\n if (editingRuleId == null) {\n return undefined;\n }\n const root = pillsScrollRef.current;\n const target = pillNodesRef.current.get(editingRuleId);\n if (!root || !target || typeof IntersectionObserver === 'undefined') {\n return undefined;\n }\n // The observer's first callback fires immediately on `observe()` and\n // just reports whatever state the trigger is already in at setup time.\n // For a pill just opened via the deferred scroll-into-view flow, that\n // report can reflect sub-pixel settle imprecision rather than a real\n // clipped state, so it's ignored — but only for that flow. A pill\n // opened by a direct click (e.g. one already sitting partly under the\n // edge fade) gets no such pass: its first report is the only signal\n // this observer will ever produce until some *other* scroll happens,\n // so it must be evaluated for real, or a pill that starts out clipped\n // would stay open indefinitely.\n let skipInitialReport = openedViaScrollIntoViewRef.current;\n openedViaScrollIntoViewRef.current = false;\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (skipInitialReport) {\n skipInitialReport = false;\n return;\n }\n if (entry && entry.intersectionRatio < 1) {\n setEditingRuleId(null);\n }\n },\n {\n root,\n threshold: 1,\n rootMargin: `0px ${POPOVER_CLOSE_BUFFER_PX}px 0px ${POPOVER_CLOSE_BUFFER_PX}px`,\n },\n );\n observer.observe(target);\n return () => observer.disconnect();\n }, [editingRuleId]);\n\n // Committing a value (typing text, picking another choice) can widen the\n // open pill itself — e.g. the last pill sitting at the scrolled-to-end\n // edge growing past the track's right boundary. Left alone, that clips\n // the trigger against the edge and the close effect above would end the\n // popover on the user mid-edit. Re-scrolling the trigger back into view\n // here runs synchronously in the same commit as the value update — before\n // the browser has a chance to notify the close effect's\n // `IntersectionObserver` of the old, clipped position — so that observer\n // only ever sees the corrected, fully-visible state.\n const editingRuleValue = useMemo(\n () =>\n editingRuleId == null\n ? null\n : (filterState.state.topLevelRules.find((rule) => rule.id === editingRuleId)?.value ??\n null),\n [editingRuleId, filterState.state.topLevelRules],\n );\n useLayoutEffect(() => {\n if (editingRuleId == null) {\n return;\n }\n pillNodesRef.current\n .get(editingRuleId)\n ?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });\n }, [editingRuleId, editingRuleValue]);\n\n // Active `is` rules on scoping selector fields narrow the picker's\n // Fields submenu to matching parent record types. `undefined` means\n // no narrowing.\n //\n // The selector concept is generic: a record-type field (e.g.\n // `account_type` with Individual / Business options) and a template\n // field (e.g. `case_template` with Case-template names as options)\n // both qualify whenever the backend ships custom fields whose\n // `parent_record_type` matches one of their option labels. Multiple\n // selectors can be active at once; the allow-lists union.\n //\n // Lives in the FilterBar (not the picker) so the picker stays\n // policy-free: it just applies whatever allow-list it's given. The\n // FilterBar owns the rules → parents mapping because that needs\n // access to both `state.topLevelRules` (the active filters) and the\n // selector field's option-label table (to translate option values\n // like `\"individual\"` to parent labels like `\"Individual\"`).\n const visibleCustomFieldParents = useMemo(\n () => deriveVisibleCustomFieldParents(registry, filterState.state.topLevelRules),\n [registry, filterState.state.topLevelRules],\n );\n\n // `useFilterStateV2` already pins `compound` to `[]` when\n // `advancedRulesEnabled === false`, so when Rules is off we skip both\n // the pill and the divider in one branch.\n return (\n <FilterBarContext.Provider value={{ size }}>\n <Bar role='toolbar' aria-label={strings.filterBar}>\n {filterState.advancedRulesEnabled ? (\n <AdvancedFilterRulesPopover\n registry={registry}\n dateTimesEnabled={dateTimesEnabled}\n compound={filterState.state.compound}\n open={rulesPopoverOpen}\n onOpenChange={setRulesPopoverOpen}\n onChange={(compound) => {\n filterState.setCompound(compound);\n }}\n renderValueControl={(field, operator, value, onChange, relativeDate) =>\n // `layout: 'inline'` flips multi-value controls\n // (`multi_choices`) from the `popover`-mode inline\n // checkbox list to a compact `Combobox` with chips, which\n // fits the LogicRow dropdown's vertical budget.\n resolveValueControl(\n {\n field,\n operator,\n value,\n relativeDate,\n onChange,\n layout: 'inline',\n relativeDatesEnabled,\n dateTimesEnabled,\n },\n valueControlResolver,\n )\n }\n trigger={\n <RulesPill\n compound={filterState.state.compound}\n enabled={true}\n isOpen={rulesPopoverOpen}\n />\n }\n />\n ) : null}\n\n {hasPills ? (\n <>\n {filterState.advancedRulesEnabled ? <Divider aria-hidden='true' $size={size} /> : null}\n <PillsScrollRegion data-test='filter-bar-pills-scroll-region'>\n <PillsScrollTrack\n ref={pillsScrollRef}\n data-test='filter-bar-pills-scroll-track'\n $showLeftFade={hasMoreScrollLeft}\n $showRightFade={hasHorizontalOverflow && hasMoreScrollRight}\n >\n {filterState.state.topLevelRules.map((rule) => {\n const field = registry.get(rule.fieldId);\n if (!field) {\n return null;\n }\n const optionLabels = registry.optionLabelsFor(field.id);\n const isOpen = editingRuleId === rule.id;\n return (\n <FilterPopover\n key={rule.id}\n field={field}\n operator={rule.operator}\n wide={\n isMinutePrecisionDate(field, rule.operator, dateTimesEnabled) &&\n carriesDateRange(rule.operator, field.type)\n }\n onChangeOperator={(op: FilterOperator) => {\n const { relativeDate: _staleRelativeDate, ...rest } = rule;\n filterState.updateTopLevelRule(rule.id, {\n ...rest,\n operator: op,\n value: reconcileValueForOperator(field, op, rule.operator, rule.value),\n });\n }}\n valueControlSlot={resolveValueControl(\n {\n field,\n operator: rule.operator,\n value: rule.value,\n relativeDate: rule.relativeDate,\n onChange: (value: FilterRuleValue, relativeDate) => {\n const { relativeDate: _staleRelativeDate, ...rest } = rule;\n filterState.updateTopLevelRule(rule.id, {\n ...rest,\n value,\n ...(relativeDate ? { relativeDate } : {}),\n });\n },\n onCommit: () => setEditingRuleId(null),\n relativeDatesEnabled,\n dateTimesEnabled,\n },\n valueControlResolver,\n )}\n onClose={() => setEditingRuleId(null)}\n onApply={\n field.condition != null &&\n !committedRuleIds.has(rule.id) &&\n hasCompleteValue(rule, registry)\n ? () =>\n filterState.updateTopLevelRule(rule.id, (currentRule) => currentRule)\n : undefined\n }\n open={isOpen}\n onOpenChange={(open) => setEditingRuleId(open ? rule.id : null)}\n trigger={\n <FilterPill\n ref={(node) => {\n if (node) {\n pillNodesRef.current.set(rule.id, node);\n } else {\n pillNodesRef.current.delete(rule.id);\n }\n }}\n field={field}\n rule={\n field.condition != null && !committedRuleIds.has(rule.id) ? null : rule\n }\n variant={isOpen ? 'active' : 'default'}\n optionLabels={optionLabels}\n onDismiss={() => filterState.removeTopLevelRule(rule.id)}\n />\n }\n />\n );\n })}\n </PillsScrollTrack>\n <PickerSlot>\n <FilterPickerMenu\n registry={registry}\n onPickField={handlePickField}\n compact\n visibleCustomFieldParents={visibleCustomFieldParents}\n excludeFieldIds={excludeFieldIds}\n />\n </PickerSlot>\n </PillsScrollRegion>\n </>\n ) : filterState.advancedRulesEnabled ? (\n <EmptyTrailingGroup>\n <Divider aria-hidden='true' $size={size} $flush />\n <PickerSlot>\n <FilterPickerMenu\n registry={registry}\n onPickField={handlePickField}\n visibleCustomFieldParents={visibleCustomFieldParents}\n excludeFieldIds={excludeFieldIds}\n />\n </PickerSlot>\n </EmptyTrailingGroup>\n ) : (\n <PickerSlot>\n <FilterPickerMenu\n registry={registry}\n onPickField={handlePickField}\n visibleCustomFieldParents={visibleCustomFieldParents}\n excludeFieldIds={excludeFieldIds}\n />\n </PickerSlot>\n )}\n </Bar>\n </FilterBarContext.Provider>\n );\n}\n\n/**\n * The parent labels the picker's Fields submenu should keep visible,\n * derived from active `is` pills on scoping selector fields\n * ({@link FieldRegistry.narrowingSelectorFields}). Each selected option\n * value is a backend record-type/template id, resolved to its parent\n * label via {@link FieldRegistry.parentRecordLabelForId}.\n *\n * Returns `undefined` only when no `is` selector pill is active (show\n * everything). An active pill always returns an array, possibly empty:\n * selecting a scope with no custom fields narrows to *nothing*, not to\n * everything — conflating the two would leak other scopes' fields in.\n *\n * Only `is` narrows; multiple pills union their parents.\n */\nfunction deriveVisibleCustomFieldParents(\n registry: FieldRegistry,\n topLevelRules: ReadonlyArray<TopLevelFilterRule>,\n): ReadonlyArray<string> | undefined {\n const selectorFields = registry.narrowingSelectorFields();\n if (selectorFields.length === 0 || topLevelRules.length === 0) {\n return undefined;\n }\n const selectorIds = new Set(selectorFields.map((f) => f.id));\n const allowedParents = new Set<string>();\n let hasActiveSelectorRule = false;\n for (const rule of topLevelRules) {\n if (!selectorIds.has(rule.fieldId)) {\n continue;\n }\n if (rule.operator !== 'is') {\n continue;\n }\n hasActiveSelectorRule = true;\n const values = Array.isArray(rule.value) ? rule.value : [rule.value];\n for (const value of values) {\n if (typeof value !== 'string') {\n continue;\n }\n const parentLabel = registry.parentRecordLabelForId(value);\n if (parentLabel != null) {\n allowedParents.add(parentLabel);\n }\n }\n }\n return hasActiveSelectorRule ? Array.from(allowedParents) : undefined;\n}\n","import FilterBar, {\n type FilterBarProps as _FilterBarProps,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/FilterBar/FilterBar';\n\nexport { resolveValueControl } from './value-control-resolver';\n\nexport type FilterBarProps = _FilterBarProps;\nexport default FilterBar;\n","import { getOperatorsForField } from 'design-system/components/DataTable/TableControls/FiltersV2/operators';\nimport type {\n FilterField,\n FilterFieldSource,\n FilterFieldType,\n FilterOperator,\n} from 'design-system/components/DataTable/TableControls/FiltersV2/types';\n\n/**\n * Per-resource field registry.\n *\n * Built from the backend's `field_key_to_info` payload (extended in v2 to\n * include `type`, `options`, `item_type`, and a `source`/`parent_record_type`\n * pair for custom fields). The registry is the single place the UI looks up\n * \"what field is this and what can the user do with it\" — value control\n * rendering, operator vocabulary, picker grouping, and popover footer text\n * all route through here.\n *\n * Construction is tolerant of partial metadata: if `type` is missing the\n * field falls back to `'string'`.\n */\nexport class FieldRegistry<TField extends FilterField = FilterField> {\n readonly resource: string;\n private readonly byId: Map<string, TField>;\n /** Custom fields grouped by parent record type label, used by the picker submenu. */\n private readonly customByParent: Map<string, TField[]>;\n /** Parent record id → its display label, used to resolve selector pills to picker groups. */\n private readonly parentLabelByRecordId: Map<string, string>;\n private readonly systemFields: TField[];\n private readonly narrowingSelectors: TField[];\n\n constructor(resource: string, fields: ReadonlyArray<TField>) {\n this.resource = resource;\n this.byId = new Map();\n this.customByParent = new Map();\n this.parentLabelByRecordId = new Map();\n this.systemFields = [];\n\n // Collect every distinct parent record id first so we can infer\n // narrowing selectors in a second pass without a separate scan.\n const parentRecordIds = new Set<string>();\n for (const field of fields) {\n this.byId.set(field.id, field);\n if (field.source === 'custom') {\n const parent = field.parentRecordType ?? '';\n const bucket = this.customByParent.get(parent) ?? [];\n bucket.push(field);\n this.customByParent.set(parent, bucket);\n if (field.parentRecordId) {\n parentRecordIds.add(field.parentRecordId);\n if (field.parentRecordType) {\n this.parentLabelByRecordId.set(field.parentRecordId, field.parentRecordType);\n }\n }\n } else {\n this.systemFields.push(field);\n }\n }\n\n this.narrowingSelectors = [];\n if (parentRecordIds.size > 0) {\n for (const field of fields) {\n if (!field.options || field.options.length === 0) {\n continue;\n }\n const matches = field.options.some((opt) => parentRecordIds.has(opt.value));\n if (matches) {\n this.narrowingSelectors.push(field);\n }\n }\n }\n }\n\n parentRecordLabelForId(recordId: string): string | undefined {\n return this.parentLabelByRecordId.get(recordId);\n }\n\n has(fieldId: string): boolean {\n return this.byId.has(fieldId);\n }\n\n get(fieldId: string): TField | undefined {\n return this.byId.get(fieldId);\n }\n\n /**\n * Get a field by id, throwing if it isn't registered. Use this when the\n * fieldId came from state we own (e.g. an existing `FilterRule`) and a\n * missing field is a programming error rather than user input.\n */\n getOrThrow(fieldId: string): TField {\n const field = this.byId.get(fieldId);\n if (!field) {\n throw new Error(`FieldRegistry(${this.resource}): unknown fieldId \"${fieldId}\"`);\n }\n return field;\n }\n\n /** All registered fields, in insertion order. */\n all(): ReadonlyArray<TField> {\n return Array.from(this.byId.values());\n }\n\n /** System / built-in fields, used as the top section of the `⊕ Filter` menu. */\n systemFieldsList(): ReadonlyArray<TField> {\n return this.systemFields;\n }\n\n /** Custom fields grouped by parent record type for the picker submenu. */\n customFieldGroups(): ReadonlyArray<{ parent: string; fields: ReadonlyArray<TField> }> {\n return Array.from(this.customByParent.entries()).map(([parent, fields]) => ({\n parent,\n fields,\n }));\n }\n\n /**\n * Fields that drive the picker's field-narrowing. A field is inferred\n * as a scoping selector (e.g. `account_type`, `case_template`) when its\n * `options[].value` set intersects the registry's custom-field\n * `parentRecordId`s — matching on the backend id, not the display label,\n * so a suffixed or colliding label (`\"KYC Standard (CAS)\"`) still\n * narrows correctly. `FilterBar` turns an active `is` pill on such a\n * field into the visible parent labels via {@link parentRecordLabelForId}.\n *\n * A coincidental id collision would falsely tag a field as a selector —\n * benign (it just narrows too); layer on a backend flag if ever needed.\n */\n narrowingSelectorFields(): ReadonlyArray<TField> {\n return this.narrowingSelectors;\n }\n\n /** Operator vocabulary for a registered field, gated by its `allowedOperators` then type. */\n operatorsFor(fieldId: string): ReadonlyArray<FilterOperator> {\n return getOperatorsForField(this.getOrThrow(fieldId));\n }\n\n /** Default operator for a registered field. Used when creating a new pill. */\n defaultOperatorFor(fieldId: string): FilterOperator {\n const field = this.getOrThrow(fieldId);\n const operators = getOperatorsForField(field);\n const defaultOperator = field.condition?.defaultOperator ?? operators[0];\n if (defaultOperator != null && !operators.includes(defaultOperator)) {\n throw new Error(`FieldRegistry: default operator is not available for field \"${fieldId}\"`);\n }\n if (defaultOperator == null) {\n throw new Error(`FieldRegistry: no operators available for field \"${fieldId}\"`);\n }\n return defaultOperator;\n }\n\n /**\n * Pick the operator to use for a rule after a field swap. If the\n * previous operator is still in the new field's vocabulary, keep it\n * (the user's intent likely carries over — e.g. `is_empty` stays\n * `is_empty` regardless of field type). Otherwise fall back to the\n * field's default operator.\n *\n * Lives on the registry rather than as a free helper because the\n * answer is entirely a function of registry-owned data (operator\n * vocabulary per type) — and centralizing it keeps the field-swap\n * semantics consistent across `FilterBar.handlePickField`,\n * `AdvancedFilterRulesPopover.handleFieldChange`, and any future\n * caller.\n */\n reconcileOperator(fieldId: string, prevOperator: FilterOperator): FilterOperator {\n const ops = this.operatorsFor(fieldId);\n return (ops as ReadonlyArray<FilterOperator>).includes(prevOperator)\n ? prevOperator\n : this.defaultOperatorFor(fieldId);\n }\n\n /**\n * Build a `value → label` lookup for a `choices` / `multi_choices`\n * field, suitable for translating raw option ids into the human\n * labels rendered by `FilterPill` chips and value-control headers.\n * Returns `undefined` when the field has no options so callers can\n * skip the lookup entirely.\n *\n * Memoized per-field so repeated reads from render loops don't\n * rebuild the same map. Field options are immutable for the lifetime\n * of a `FieldRegistry`, so the cache never needs invalidation.\n */\n optionLabelsFor(fieldId: string): Record<string, string> | undefined {\n const cached = this.optionLabelCache.get(fieldId);\n if (cached != null) {\n return cached === EMPTY_OPTION_LABELS ? undefined : cached;\n }\n const field = this.byId.get(fieldId);\n if (!field?.options || field.options.length === 0) {\n this.optionLabelCache.set(fieldId, EMPTY_OPTION_LABELS);\n return undefined;\n }\n const map: Record<string, string> = {};\n for (const opt of field.options) {\n map[opt.value] = opt.label;\n }\n this.optionLabelCache.set(fieldId, map);\n return map;\n }\n\n // Sentinel cached for fields whose `options` are missing or empty,\n // so the cache hit-or-miss check stays a single `Map.get`.\n private readonly optionLabelCache: Map<string, Record<string, string>> = new Map();\n}\n\n// Cache sentinel for \"no options to label.\" Stored in the same map so\n// the lookup is one read, not two.\nconst EMPTY_OPTION_LABELS: Record<string, string> = Object.freeze({});\n\n/**\n * Backend metadata for one field as exposed by the v2 `field_key_to_info`\n * payload. All fields except `label` are optional — v1 responses only carry\n * `label`/`tokens`. The registry tolerates the missing fields and falls back\n * to safe defaults.\n */\nexport interface RawFieldInfo {\n label: string;\n tokens?: ReadonlyArray<string>;\n /** v2 metadata — present once the backend ships its extended schema. */\n type?: string;\n source?: string;\n parent_record_type?: string;\n parent_record_id?: string;\n options?: ReadonlyArray<{ label: string; value: string }>;\n item_type?: string;\n path?: ReadonlyArray<string>;\n}\n\n/**\n * Build a registry from a `field_key_to_info` map. Forgiving by design — any\n * key whose `type` is missing or unrecognized falls back to `'string'`, and\n * `source` defaults to `'custom'` (current `customFilters` are all custom).\n */\nexport function buildFieldRegistry(\n resource: string,\n fieldKeyToInfo: Record<string, RawFieldInfo>,\n options?: {\n systemFields?: ReadonlyArray<FilterField>;\n },\n): FieldRegistry {\n const apiFields = Object.entries(fieldKeyToInfo).map(([id, raw]) =>\n rawFieldInfoToFilterField(id, raw),\n );\n const systemFields = options?.systemFields ?? [];\n return new FieldRegistry(resource, [...systemFields, ...apiFields]);\n}\n\nfunction rawFieldInfoToFilterField(id: string, raw: RawFieldInfo): FilterField {\n const type = normalizeFieldType(raw.type);\n const itemType = raw.item_type ? normalizeFieldType(raw.item_type) : undefined;\n const source = normalizeFieldSource(raw.source);\n return {\n id,\n label: raw.label,\n type,\n source,\n options: raw.options,\n itemType,\n parentRecordType: raw.parent_record_type,\n parentRecordId: raw.parent_record_id,\n path: raw.path,\n };\n}\n\nconst KNOWN_TYPES: ReadonlySet<FilterFieldType> = new Set<FilterFieldType>([\n 'string',\n 'email',\n 'choices',\n 'multi_choices',\n 'boolean',\n 'integer',\n 'float',\n 'date',\n 'array',\n 'tags_conditions',\n 'signals',\n 'date_range',\n]);\n\nfunction normalizeFieldType(raw: string | undefined): FilterFieldType {\n if (raw && (KNOWN_TYPES as ReadonlySet<string>).has(raw)) {\n return raw as FilterFieldType;\n }\n return 'string';\n}\n\nfunction normalizeFieldSource(raw: string | undefined): FilterFieldSource {\n return raw === 'system' ? 'system' : 'custom';\n}\n","import { EMPTY_FILTER_STATE, type FilterStateV2, isEmptyState } from './types';\nimport { isFilterStateV2 } from './validation';\n\n/**\n * URL state encoding/decoding for the `fv2=` namespace.\n *\n * v2 URL state is base64'd JSON of `FilterStateV2`. Encoding is a lossless\n * mirror of the in-memory shape — no schema migrations required when the\n * vocabulary grows because the type already models OR-of-AND.\n *\n * Hosts that persist filter state elsewhere (saved views, session storage)\n * store the same encoded string the URL carries; see\n * {@link decodeFilterStateFromString}.\n */\n\n/** The query param the FilterBar's full rule state travels in. */\nexport const FILTER_STATE_URL_PARAM = 'fv2';\n\nexport interface UrlStateCodecResult {\n /** The filter state recovered from the URL (or `EMPTY_FILTER_STATE` if absent). */\n state: FilterStateV2;\n /** True when an `fv2=…` param was present (regardless of decode success). */\n hadParam: boolean;\n /** True when the param was present but failed to decode. */\n invalid: boolean;\n}\n\n/** Read `fv2=…` from a query string and return the decoded state. */\nexport function decodeFilterStateFromUrl(search: string | URLSearchParams): UrlStateCodecResult {\n const params = typeof search === 'string' ? new URLSearchParams(search) : search;\n const raw = params.get(FILTER_STATE_URL_PARAM);\n if (raw == null) {\n return { state: EMPTY_FILTER_STATE, hadParam: false, invalid: false };\n }\n const decoded = tryDecode(raw);\n if (decoded == null) {\n return { state: EMPTY_FILTER_STATE, hadParam: true, invalid: true };\n }\n return { state: decoded, hadParam: true, invalid: false };\n}\n\n/**\n * Produce a `fv2=…` segment for the given state. Returns `null` when the\n * state is empty — callers should treat that as \"no param at all\" so URLs\n * stay clean in the common case of no filters.\n */\nexport function encodeFilterStateToUrlParam(state: FilterStateV2): string | null {\n if (isEmptyState(state)) {\n return null;\n }\n return encodeBase64(JSON.stringify(state));\n}\n\nexport function applyFilterStateToSearchParams(\n params: URLSearchParams,\n state: FilterStateV2,\n): URLSearchParams {\n const encoded = encodeFilterStateToUrlParam(state);\n if (encoded == null) {\n params.delete(FILTER_STATE_URL_PARAM);\n } else {\n params.set(FILTER_STATE_URL_PARAM, encoded);\n }\n return params;\n}\n\n/**\n * Decode a bare base64 string (as produced by {@link encodeFilterStateToUrlParam})\n * back into a {@link FilterStateV2}, or `null` when it is absent/corrupt/from a\n * future vocabulary.\n */\nexport function decodeFilterStateFromString(raw: string | null | undefined): FilterStateV2 | null {\n if (raw == null || raw === '') {\n return null;\n }\n return tryDecode(raw);\n}\n\nfunction tryDecode(raw: string): FilterStateV2 | null {\n try {\n const json = decodeBase64(raw);\n const parsed = JSON.parse(json) as unknown;\n // `isFilterStateV2` validates per-rule contents (fieldId is a\n // non-empty string, operator is in the known vocabulary, value is\n // a supported primitive). A bookmarked URL from a future build with\n // operators outside the current vocabulary fails this guard and\n // falls back to the empty state — better than letting an unknown\n // operator reach a backend adapter where the wire payload would be\n // malformed.\n if (!isFilterStateV2(parsed)) {\n return null;\n }\n return parsed;\n } catch {\n return null;\n }\n}\n\n// `btoa`/`atob` only handle Latin-1, so UTF-8 encode through\n// percent-escapes first; the reverse on the way out.\nfunction encodeBase64(input: string): string {\n return btoa(unescape(encodeURIComponent(input)));\n}\n\nfunction decodeBase64(input: string): string {\n return decodeURIComponent(escape(atob(input)));\n}\n"],"mappings":"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"}
|