@persona/design-system 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (796) hide show
  1. package/CHANGELOG.md +343 -221
  2. package/dist/{Action-DkNqzc2X.d.mts → Action-CVtzREhU.d.mts} +3 -3
  3. package/dist/{Action-z1rV4qON.d.cts → Action-E90Wvqmc.d.cts} +3 -3
  4. package/dist/Action.d.cts +1 -1
  5. package/dist/Action.d.mts +1 -1
  6. package/dist/AdvancedFilterRuleRow.d.mts +37 -0
  7. package/dist/AdvancedFilterRulesPopover.d.mts +62 -0
  8. package/dist/ArrayValueControl.d.mts +38 -0
  9. package/dist/Attribute.d.mts +4 -4
  10. package/dist/AttributeGrid.d.mts +1 -1
  11. package/dist/{Badge-DAGPU4-e.cjs → Badge-ADPloFsd.cjs} +2 -2
  12. package/dist/{Badge-DAGPU4-e.cjs.map → Badge-ADPloFsd.cjs.map} +1 -1
  13. package/dist/{Badge-DRn_r6is.mjs → Badge-DortWowZ.mjs} +2 -2
  14. package/dist/{Badge-DRn_r6is.mjs.map → Badge-DortWowZ.mjs.map} +1 -1
  15. package/dist/Banner.d.mts +1 -1
  16. package/dist/BooleanValueControl.d.mts +20 -0
  17. package/dist/{Breadcrumb-BOxfam3E.d.cts → Breadcrumb-VH-Mwo-M.d.cts} +15 -2
  18. package/dist/{Breadcrumb-On7pOpgt.d.mts → Breadcrumb-lziQ1FX9.d.mts} +15 -2
  19. package/dist/Breadcrumb.d.cts +2 -2
  20. package/dist/Breadcrumb.d.mts +2 -2
  21. package/dist/Breadcrumbs-BBREROrw.d.cts +26 -0
  22. package/dist/Breadcrumbs-CDZ_Mrcg.mjs +288 -0
  23. package/dist/Breadcrumbs-CDZ_Mrcg.mjs.map +1 -0
  24. package/dist/Breadcrumbs-DJ5qqqRD.d.mts +26 -0
  25. package/dist/Breadcrumbs-tR49JqAS.cjs +295 -0
  26. package/dist/Breadcrumbs-tR49JqAS.cjs.map +1 -0
  27. package/dist/Breadcrumbs.d.cts +2 -20
  28. package/dist/Breadcrumbs.d.mts +2 -20
  29. package/dist/{Button-DXsYU5qU.d.mts → Button-9p469xA1.d.mts} +3 -3
  30. package/dist/Button.d.mts +1 -1
  31. package/dist/ButtonGroup.d.mts +1 -1
  32. package/dist/Calendar.d.mts +1 -1
  33. package/dist/CalendarBase.d.mts +1 -1
  34. package/dist/{Card-CLTkZLKr.mjs → Card-BMCB9eFC.mjs} +4 -4
  35. package/dist/{Card-CLTkZLKr.mjs.map → Card-BMCB9eFC.mjs.map} +1 -1
  36. package/dist/{Card-DnmrsQWi.d.cts → Card-CJPEmUvg.d.cts} +2 -2
  37. package/dist/{Card-IOBCsfke.d.mts → Card-CqnG--CU.d.mts} +4 -4
  38. package/dist/{Card-CaOItkgL.cjs → Card-Csz-PxX0.cjs} +4 -4
  39. package/dist/{Card-CaOItkgL.cjs.map → Card-Csz-PxX0.cjs.map} +1 -1
  40. package/dist/Card.d.cts +1 -1
  41. package/dist/Card.d.mts +1 -1
  42. package/dist/Card2.d.cts +1 -1
  43. package/dist/Card2.d.mts +1 -1
  44. package/dist/CardV2-C9z0Hr-c.mjs +411 -0
  45. package/dist/CardV2-C9z0Hr-c.mjs.map +1 -0
  46. package/dist/CardV2-DJXgFomd.cjs +419 -0
  47. package/dist/CardV2-DJXgFomd.cjs.map +1 -0
  48. package/dist/{Checkbox-BghGF-iW.mjs → Checkbox-B0bjZbji.mjs} +5 -5
  49. package/dist/{Checkbox-BghGF-iW.mjs.map → Checkbox-B0bjZbji.mjs.map} +1 -1
  50. package/dist/{Checkbox-MUC37dLY.d.mts → Checkbox-Bm8exUfH.d.mts} +1 -1
  51. package/dist/{Checkbox-DhxpxzGp.cjs → Checkbox-CmCujC1W.cjs} +5 -5
  52. package/dist/{Checkbox-DhxpxzGp.cjs.map → Checkbox-CmCujC1W.cjs.map} +1 -1
  53. package/dist/{Checkbox-DfI0Xp3y.d.cts → Checkbox-Cr8ifm10.d.cts} +1 -1
  54. package/dist/Checkbox.d.cts +1 -1
  55. package/dist/Checkbox.d.mts +1 -1
  56. package/dist/CheckboxGroupField.d.cts +1 -1
  57. package/dist/CheckboxGroupField.d.mts +2 -2
  58. package/dist/ChoicesValueControl.d.mts +35 -0
  59. package/dist/{Combobox-CeKMrlxy.mjs → Combobox-BdqU5WLG.mjs} +254 -70
  60. package/dist/Combobox-BdqU5WLG.mjs.map +1 -0
  61. package/dist/{Combobox-Bedo_GIj.d.mts → Combobox-C99xluaM.d.mts} +3 -3
  62. package/dist/{Combobox-4Bi9-N1p.cjs → Combobox-COXvmxlM.cjs} +247 -63
  63. package/dist/Combobox-COXvmxlM.cjs.map +1 -0
  64. package/dist/{Combobox-5rAFq_52.d.cts → Combobox-DBWMHwUt.d.cts} +3 -3
  65. package/dist/Combobox.d.cts +2 -2
  66. package/dist/Combobox.d.mts +2 -2
  67. package/dist/{ComboboxBase-DGZUdsQa.d.mts → ComboboxBase-BsY7CYoB.d.mts} +48 -8
  68. package/dist/{ComboboxBase-BoR9DVwe.d.cts → ComboboxBase-zZ3tE-dH.d.cts} +45 -5
  69. package/dist/ComboboxBase.d.cts +2 -2
  70. package/dist/ComboboxBase.d.mts +2 -2
  71. package/dist/{ComboboxMultiSelect-DMWPiBrE.d.mts → ComboboxMultiSelect-dNuETspL.d.mts} +2 -2
  72. package/dist/{ComboboxMultiSelect-CnI6sFAF.d.cts → ComboboxMultiSelect-ioB4Jx7_.d.cts} +2 -2
  73. package/dist/ComboboxMultiSelect.d.cts +1 -1
  74. package/dist/ComboboxMultiSelect.d.mts +1 -1
  75. package/dist/{ComboboxSingleSelect-CcppU_hq.d.mts → ComboboxSingleSelect-C8KvIJ43.d.mts} +4 -4
  76. package/dist/{ComboboxSingleSelect-Japejm0g.d.cts → ComboboxSingleSelect-Fn80tdhz.d.cts} +4 -4
  77. package/dist/ComboboxSingleSelect.d.cts +1 -1
  78. package/dist/ComboboxSingleSelect.d.mts +1 -1
  79. package/dist/{CompactBar-DTsGo1zU.d.cts → CompactBar-BEAK55kh.d.cts} +3 -3
  80. package/dist/{CompactBar-2cpJD7qg.d.mts → CompactBar-CXqlVKy7.d.mts} +3 -3
  81. package/dist/CompactBar.d.cts +1 -1
  82. package/dist/CompactBar.d.mts +1 -1
  83. package/dist/{ConfigFormGroup-DVRhkS2L.cjs → ConfigFormGroup-m5YdVa9n.cjs} +3 -3
  84. package/dist/{ConfigFormGroup-DVRhkS2L.cjs.map → ConfigFormGroup-m5YdVa9n.cjs.map} +1 -1
  85. package/dist/{ConfigFormGroup-DISUwz5j.mjs → ConfigFormGroup-yhb2jldT.mjs} +3 -3
  86. package/dist/{ConfigFormGroup-DISUwz5j.mjs.map → ConfigFormGroup-yhb2jldT.mjs.map} +1 -1
  87. package/dist/{ControlBar-DXyl1gjc.d.mts → ControlBar-D8CirAyZ.d.cts} +2 -2
  88. package/dist/{ControlBar-BGmXymCB.d.cts → ControlBar-tOCQnbAl.d.mts} +2 -2
  89. package/dist/ControlBar.d.cts +1 -1
  90. package/dist/ControlBar.d.mts +1 -1
  91. package/dist/DataTable.d.cts +3 -3
  92. package/dist/DataTable.d.mts +4 -4
  93. package/dist/DateField.d.cts +1 -1
  94. package/dist/DateField.d.mts +1 -1
  95. package/dist/DatePicker-BlCgFb7g.cjs +948 -0
  96. package/dist/DatePicker-BlCgFb7g.cjs.map +1 -0
  97. package/dist/DatePicker-DY1YA_Fu.mjs +922 -0
  98. package/dist/DatePicker-DY1YA_Fu.mjs.map +1 -0
  99. package/dist/DatePicker.d.cts +1 -1
  100. package/dist/DatePicker.d.mts +1 -1
  101. package/dist/DateRangePicker.d.cts +1 -1
  102. package/dist/DateRangePicker.d.mts +1 -1
  103. package/dist/DateValueControl.d.mts +26 -0
  104. package/dist/{DropdownButton-B397h6ka.mjs → DropdownButton-DKLjJylQ.mjs} +3 -3
  105. package/dist/{DropdownButton-B397h6ka.mjs.map → DropdownButton-DKLjJylQ.mjs.map} +1 -1
  106. package/dist/{DropdownButton-Du6dwZVL.cjs → DropdownButton-Dl7IEzAc.cjs} +3 -3
  107. package/dist/{DropdownButton-Du6dwZVL.cjs.map → DropdownButton-Dl7IEzAc.cjs.map} +1 -1
  108. package/dist/DropdownButton.d.cts +1 -1
  109. package/dist/DropdownButton.d.mts +2 -2
  110. package/dist/{DropdownMenu-5qIgQ14A.d.mts → DropdownMenu-CVPanvKA.d.mts} +3 -3
  111. package/dist/{DropdownMenu-cnkoGc7C.mjs → DropdownMenu-DGYexb7s.mjs} +3 -3
  112. package/dist/{DropdownMenu-cnkoGc7C.mjs.map → DropdownMenu-DGYexb7s.mjs.map} +1 -1
  113. package/dist/{DropdownMenu-CfJxgWN5.cjs → DropdownMenu-DnlQqTjs.cjs} +3 -3
  114. package/dist/{DropdownMenu-CfJxgWN5.cjs.map → DropdownMenu-DnlQqTjs.cjs.map} +1 -1
  115. package/dist/{DropdownMenu-FIYz6oAo.d.cts → DropdownMenu-FkiManPP.d.cts} +2 -2
  116. package/dist/DropdownMenu.d.cts +1 -1
  117. package/dist/DropdownMenu.d.mts +1 -1
  118. package/dist/{ErrorProps-BosuK6zJ.d.cts → ErrorProps-CN2XjaOX.d.mts} +1 -1
  119. package/dist/{ErrorProps-iEj4BIVA.d.mts → ErrorProps-Dxqb4gw_.d.cts} +1 -1
  120. package/dist/ErrorProps.d.cts +1 -1
  121. package/dist/ErrorProps.d.mts +1 -1
  122. package/dist/FieldRegistry-OX60T3hr.d.cts +122 -0
  123. package/dist/FieldRegistry-rqSkjchY.d.mts +122 -0
  124. package/dist/FieldRegistry.d.cts +2 -0
  125. package/dist/FieldRegistry.d.mts +2 -0
  126. package/dist/FilterBar-D3LiIy1-.d.mts +103 -0
  127. package/dist/FilterBar-YzOh02f9.d.cts +103 -0
  128. package/dist/FilterBar.d.cts +2 -0
  129. package/dist/FilterBar.d.mts +2 -0
  130. package/dist/FilterPickerMenu.d.mts +84 -0
  131. package/dist/FilterPill.d.mts +60 -0
  132. package/dist/FilterPopover.d.mts +87 -0
  133. package/dist/FloatValueControl.d.mts +40 -0
  134. package/dist/{FormControl-ArDcvmir.mjs → FormControl-B28qa7aQ.mjs} +6 -6
  135. package/dist/{FormControl-ArDcvmir.mjs.map → FormControl-B28qa7aQ.mjs.map} +1 -1
  136. package/dist/{FormControl-BrsML00L.d.cts → FormControl-DFp_qcW1.d.cts} +2 -2
  137. package/dist/{FormControl-DnsC4vTX.d.mts → FormControl-DH3bgqaB.d.mts} +3 -3
  138. package/dist/{FormControl-Czt95h2L.cjs → FormControl-MkBXuUF6.cjs} +6 -6
  139. package/dist/{FormControl-Czt95h2L.cjs.map → FormControl-MkBXuUF6.cjs.map} +1 -1
  140. package/dist/FormControl.d.cts +1 -1
  141. package/dist/FormControl.d.mts +1 -1
  142. package/dist/FormControlLabel.d.mts +1 -1
  143. package/dist/{FormField-BddCs6P0.d.mts → FormField-BugkBvN4.d.mts} +2 -2
  144. package/dist/FormField-D3XhxTMg.cjs +550 -0
  145. package/dist/FormField-D3XhxTMg.cjs.map +1 -0
  146. package/dist/FormField-PeYYRO4s.mjs +471 -0
  147. package/dist/FormField-PeYYRO4s.mjs.map +1 -0
  148. package/dist/{FormField-DoSXvnJ3.d.cts → FormField-idNLw5PW.d.cts} +2 -2
  149. package/dist/FormField.d.cts +1 -1
  150. package/dist/FormField.d.mts +1 -1
  151. package/dist/{Header-CkZvzbzL.d.cts → Header-C-WhPOin.d.cts} +3 -3
  152. package/dist/{Header-B-Us54dR.d.mts → Header-CDTYK1XJ.d.mts} +2 -2
  153. package/dist/Header.d.cts +1 -1
  154. package/dist/Header.d.mts +1 -1
  155. package/dist/{HelperTooltip-CofPKyZh.d.mts → HelperTooltip-B7Ysh8B3.d.mts} +3 -3
  156. package/dist/{HelperTooltip-C1CYMpJP.d.cts → HelperTooltip-T-sTGGLD.d.cts} +2 -2
  157. package/dist/HelperTooltip.d.cts +1 -1
  158. package/dist/HelperTooltip.d.mts +1 -1
  159. package/dist/{HoverCopyableField-B_WNB7Qp.cjs → HoverCopyableField-CRkM7o4B.cjs} +6 -6
  160. package/dist/{HoverCopyableField-B_WNB7Qp.cjs.map → HoverCopyableField-CRkM7o4B.cjs.map} +1 -1
  161. package/dist/{HoverCopyableField-DR575ayC.mjs → HoverCopyableField-ClXBg_ld.mjs} +6 -6
  162. package/dist/{HoverCopyableField-DR575ayC.mjs.map → HoverCopyableField-ClXBg_ld.mjs.map} +1 -1
  163. package/dist/HoverCopyableField.d.mts +1 -1
  164. package/dist/{IconButton-Dnnlf9uO.d.mts → IconButton-BSES_-6g.d.mts} +2 -2
  165. package/dist/{IconButton-DC4rh6ow.mjs → IconButton-CIWiEsS-.mjs} +5 -5
  166. package/dist/{IconButton-DC4rh6ow.mjs.map → IconButton-CIWiEsS-.mjs.map} +1 -1
  167. package/dist/{IconButton-DNy7g5zh.cjs → IconButton-nlgjJQCS.cjs} +4 -4
  168. package/dist/{IconButton-DNy7g5zh.cjs.map → IconButton-nlgjJQCS.cjs.map} +1 -1
  169. package/dist/IconButton.d.mts +1 -1
  170. package/dist/ImageTile.d.cts +1 -1
  171. package/dist/ImageTile.d.mts +2 -2
  172. package/dist/InlineCombobox.d.mts +2 -2
  173. package/dist/InlineInput.d.mts +1 -1
  174. package/dist/{Input-PWfwMSJ7.mjs → Input-BFI_e7aU.mjs} +5 -5
  175. package/dist/{Input-PWfwMSJ7.mjs.map → Input-BFI_e7aU.mjs.map} +1 -1
  176. package/dist/{Input-CEcTvtX2.d.cts → Input-BM0DzWEf.d.cts} +2 -2
  177. package/dist/{Input-4KeYlOWM.d.mts → Input-BPClVzwD.d.mts} +4 -4
  178. package/dist/{Input-BDLUq-pK.cjs → Input-OJPQ07TW.cjs} +5 -5
  179. package/dist/{Input-BDLUq-pK.cjs.map → Input-OJPQ07TW.cjs.map} +1 -1
  180. package/dist/Input.d.cts +1 -1
  181. package/dist/Input.d.mts +1 -1
  182. package/dist/{InputProps-DNlik5IZ.d.cts → InputProps-BnjxrdWQ.d.mts} +2 -2
  183. package/dist/{InputProps-CTLG2Tr0.d.mts → InputProps-CoVNpQSj.d.cts} +2 -2
  184. package/dist/InputProps.d.cts +1 -1
  185. package/dist/InputProps.d.mts +1 -1
  186. package/dist/IntegerValueControl.d.mts +39 -0
  187. package/dist/LayoutLoadingShimmer.d.cts +20 -0
  188. package/dist/LayoutLoadingShimmer.d.mts +20 -0
  189. package/dist/Link.d.mts +1 -1
  190. package/dist/{ListBox-BCscLcYL.cjs → ListBox-BP1eaG7L.cjs} +83 -14
  191. package/dist/ListBox-BP1eaG7L.cjs.map +1 -0
  192. package/dist/{ListBox-CDNOJmvz.mjs → ListBox-BwID8jpk.mjs} +83 -14
  193. package/dist/ListBox-BwID8jpk.mjs.map +1 -0
  194. package/dist/{ListBox-WyZvseo5.d.cts → ListBox-QaeRQBSC.d.cts} +2 -2
  195. package/dist/{ListBox-DZIAlPbc.d.mts → ListBox-_fcSPynx.d.mts} +5 -5
  196. package/dist/ListBox.d.cts +1 -1
  197. package/dist/ListBox.d.mts +1 -1
  198. package/dist/ListBoxField.d.cts +2 -2
  199. package/dist/ListBoxField.d.mts +3 -3
  200. package/dist/{LoadingShimmer-Bu6KtQ06.mjs → LoadingShimmer-Dsc_RCCf.mjs} +1 -1
  201. package/dist/{LoadingShimmer-Bu6KtQ06.mjs.map → LoadingShimmer-Dsc_RCCf.mjs.map} +1 -1
  202. package/dist/{LoadingShimmer-CUjbAqGd.cjs → LoadingShimmer-Dx6ncVUV.cjs} +1 -1
  203. package/dist/{LoadingShimmer-CUjbAqGd.cjs.map → LoadingShimmer-Dx6ncVUV.cjs.map} +1 -1
  204. package/dist/LoadingShimmer.d.mts +2 -2
  205. package/dist/LogicRow-BtCKGX_j.d.mts +40 -0
  206. package/dist/LogicRow-C6lrFIq0.d.cts +40 -0
  207. package/dist/LogicRow.d.cts +2 -0
  208. package/dist/LogicRow.d.mts +2 -0
  209. package/dist/MaskedInput.d.cts +2 -2
  210. package/dist/MaskedInput.d.mts +1 -1
  211. package/dist/{Menu-CVuFAxl2.mjs → Menu-CPYXo61N.mjs} +5 -5
  212. package/dist/{Menu-CVuFAxl2.mjs.map → Menu-CPYXo61N.mjs.map} +1 -1
  213. package/dist/{Menu-BJ5c7HGD.d.mts → Menu-CUp_9HgC.d.mts} +4 -4
  214. package/dist/{Menu-BKMxOXkj.d.cts → Menu-fUnbIYr5.d.cts} +3 -3
  215. package/dist/{Menu-BXic-30n.cjs → Menu-t2q8NrV0.cjs} +5 -5
  216. package/dist/{Menu-BXic-30n.cjs.map → Menu-t2q8NrV0.cjs.map} +1 -1
  217. package/dist/Menu.d.cts +1 -1
  218. package/dist/Menu.d.mts +1 -1
  219. package/dist/{MiddleTruncatedText-BIzKECv9.cjs → MiddleTruncatedText-CO76xIqP.cjs} +2 -2
  220. package/dist/{MiddleTruncatedText-BIzKECv9.cjs.map → MiddleTruncatedText-CO76xIqP.cjs.map} +1 -1
  221. package/dist/{MiddleTruncatedText-Bzpg3zAU.mjs → MiddleTruncatedText-GXI-CPvs.mjs} +3 -3
  222. package/dist/{MiddleTruncatedText-Bzpg3zAU.mjs.map → MiddleTruncatedText-GXI-CPvs.mjs.map} +1 -1
  223. package/dist/Modal.d.mts +3 -3
  224. package/dist/PageHeader-CUDnarkt.cjs +77 -0
  225. package/dist/PageHeader-CUDnarkt.cjs.map +1 -0
  226. package/dist/PageHeader-D-6W61E_.mjs +64 -0
  227. package/dist/PageHeader-D-6W61E_.mjs.map +1 -0
  228. package/dist/PageHeader.d.cts +11 -2
  229. package/dist/PageHeader.d.mts +12 -3
  230. package/dist/{PageSelector-DoROR_Uh.d.cts → PageSelector-CNnVp3Al.d.cts} +3 -3
  231. package/dist/{PageSelector-CMoV-cHa.d.mts → PageSelector-vay4jpMp.d.mts} +3 -3
  232. package/dist/PageSelector.d.cts +1 -1
  233. package/dist/PageSelector.d.mts +1 -1
  234. package/dist/PageSizeSelector.d.mts +7 -1
  235. package/dist/{Pagination-D4IVVj3S.cjs → Pagination-2Yo1vRJZ.cjs} +12 -9
  236. package/dist/Pagination-2Yo1vRJZ.cjs.map +1 -0
  237. package/dist/{Pagination-B97xQ-Wk.d.cts → Pagination-D04tn-tf.d.cts} +9 -3
  238. package/dist/{Pagination-QWNK_hH7.d.mts → Pagination-ygLutOst.d.mts} +9 -3
  239. package/dist/{Pagination-Cj08JRG9.mjs → Pagination-ztqhywAP.mjs} +13 -10
  240. package/dist/Pagination-ztqhywAP.mjs.map +1 -0
  241. package/dist/Pagination.d.cts +1 -1
  242. package/dist/Pagination.d.mts +1 -1
  243. package/dist/{Pii-D-Ry7L0t.cjs → Pii-DHTb3ewO.cjs} +2 -2
  244. package/dist/{Pii-D-Ry7L0t.cjs.map → Pii-DHTb3ewO.cjs.map} +1 -1
  245. package/dist/{Pii-Bxh6_R4T.mjs → Pii-DrrtEz7U.mjs} +2 -2
  246. package/dist/{Pii-Bxh6_R4T.mjs.map → Pii-DrrtEz7U.mjs.map} +1 -1
  247. package/dist/Pii.d.mts +1 -1
  248. package/dist/PillShell.d.mts +85 -0
  249. package/dist/{Popover-D0QY5f-J.mjs → Popover-BkDpDdaO.mjs} +5 -5
  250. package/dist/{Popover-D0QY5f-J.mjs.map → Popover-BkDpDdaO.mjs.map} +1 -1
  251. package/dist/{Popover-BAv7BujW.cjs → Popover-BzgMAhsX.cjs} +4 -4
  252. package/dist/{Popover-BAv7BujW.cjs.map → Popover-BzgMAhsX.cjs.map} +1 -1
  253. package/dist/Popover.d.mts +1 -1
  254. package/dist/ProgressBar.d.mts +1 -1
  255. package/dist/ProgressIndicator.d.mts +1 -1
  256. package/dist/{PseudoClassProps-ySXCGUEQ.d.mts → PseudoClassProps-DLxPxo7T.d.mts} +1 -1
  257. package/dist/PseudoClassProps.d.mts +1 -1
  258. package/dist/{Radio-nw846eRv.cjs → Radio-BrTzy7-C.cjs} +3 -3
  259. package/dist/{Radio-nw846eRv.cjs.map → Radio-BrTzy7-C.cjs.map} +1 -1
  260. package/dist/{Radio-C9DevagH.mjs → Radio-CSX2eO-O.mjs} +3 -3
  261. package/dist/{Radio-C9DevagH.mjs.map → Radio-CSX2eO-O.mjs.map} +1 -1
  262. package/dist/{RadioGroup-B3hRbIWF.mjs → RadioGroup-CnK0opBd.mjs} +3 -3
  263. package/dist/{RadioGroup-B3hRbIWF.mjs.map → RadioGroup-CnK0opBd.mjs.map} +1 -1
  264. package/dist/{RadioGroup-DmGVJCgT.cjs → RadioGroup-CriF2InQ.cjs} +3 -3
  265. package/dist/{RadioGroup-DmGVJCgT.cjs.map → RadioGroup-CriF2InQ.cjs.map} +1 -1
  266. package/dist/{RadioGroup-D_H1B7JV.d.cts → RadioGroup-DKqbSfju.d.mts} +1 -1
  267. package/dist/{RadioGroup-nhMXEbCx.d.mts → RadioGroup-XYWjprsv.d.cts} +1 -1
  268. package/dist/RadioGroup.d.cts +1 -1
  269. package/dist/RadioGroup.d.mts +1 -1
  270. package/dist/RangeCalendar.d.mts +1 -1
  271. package/dist/RangeCalendarPresets.d.mts +1 -1
  272. package/dist/RuleEditorFields.d.mts +37 -0
  273. package/dist/RulesPill.d.mts +65 -0
  274. package/dist/{SearchInput-s6qGC2WZ.d.mts → SearchInput-Bp2yjaE1.d.mts} +3 -3
  275. package/dist/{SearchInput-CAHYPQVX.d.cts → SearchInput-CTI59-NW.d.cts} +2 -2
  276. package/dist/SearchInput.d.cts +1 -1
  277. package/dist/SearchInput.d.mts +1 -1
  278. package/dist/Section.d.mts +1 -1
  279. package/dist/{SectionHeading-CDBQ4m9E.d.mts → SectionHeading-C6hjGdK-.d.cts} +2 -2
  280. package/dist/{SectionHeading-D-L4uPoX.d.cts → SectionHeading-Q-rx2LEd.d.mts} +2 -2
  281. package/dist/SectionHeading.d.cts +1 -1
  282. package/dist/SectionHeading.d.mts +1 -1
  283. package/dist/{SegmentedControl-CIJz0oxY.cjs → SegmentedControl-C2XZF0ys.cjs} +8 -7
  284. package/dist/SegmentedControl-C2XZF0ys.cjs.map +1 -0
  285. package/dist/{SegmentedControl-B1ZLgu61.mjs → SegmentedControl-CgDQIVll.mjs} +8 -7
  286. package/dist/SegmentedControl-CgDQIVll.mjs.map +1 -0
  287. package/dist/{SegmentedControl-BYuXohIp.d.cts → SegmentedControl-DrjdUOU9.d.mts} +2 -2
  288. package/dist/{SegmentedControl-CE845gnm.d.mts → SegmentedControl-nHIK1ZvR.d.cts} +1 -1
  289. package/dist/SegmentedControl.d.cts +1 -1
  290. package/dist/SegmentedControl.d.mts +1 -1
  291. package/dist/{Select-NcaURrGZ.d.cts → Select-2KbtKawr.d.mts} +11 -5
  292. package/dist/{Select-BMEwCfbv.d.mts → Select-BH3hXMxp.d.cts} +11 -5
  293. package/dist/{Select-C65bfYeT.cjs → Select-BurtT6bN.cjs} +13 -10
  294. package/dist/Select-BurtT6bN.cjs.map +1 -0
  295. package/dist/{Select-ByTgXOlU.mjs → Select-cPEORy70.mjs} +14 -11
  296. package/dist/Select-cPEORy70.mjs.map +1 -0
  297. package/dist/Select.d.cts +1 -1
  298. package/dist/Select.d.mts +1 -1
  299. package/dist/Slider.d.mts +1 -1
  300. package/dist/SliderRHF.d.mts +1 -1
  301. package/dist/SliderThumb.d.mts +1 -1
  302. package/dist/{Spacer-GYHbk-dS.cjs → Spacer-B2CerL6e.cjs} +1 -1
  303. package/dist/{Spacer-GYHbk-dS.cjs.map → Spacer-B2CerL6e.cjs.map} +1 -1
  304. package/dist/{Spacer-Ln3KChb5.mjs → Spacer-CJp0lwkL.mjs} +1 -1
  305. package/dist/{Spacer-Ln3KChb5.mjs.map → Spacer-CJp0lwkL.mjs.map} +1 -1
  306. package/dist/{Stack-ckRN7LrP.mjs → Stack-Bl54WmhY.mjs} +1 -1
  307. package/dist/{Stack-ckRN7LrP.mjs.map → Stack-Bl54WmhY.mjs.map} +1 -1
  308. package/dist/{Stack-D979gYU9.d.cts → Stack-BzVkf3cz.d.cts} +1 -1
  309. package/dist/{Stack-UMhJ6F_3.d.mts → Stack-CkV7k7TE.d.mts} +2 -2
  310. package/dist/{Stack-BF-9YjA1.cjs → Stack-UeifHn3c.cjs} +1 -1
  311. package/dist/{Stack-BF-9YjA1.cjs.map → Stack-UeifHn3c.cjs.map} +1 -1
  312. package/dist/Stack.d.cts +1 -1
  313. package/dist/Stack.d.mts +1 -1
  314. package/dist/StatusIndicator.d.cts +31 -3
  315. package/dist/StatusIndicator.d.mts +32 -4
  316. package/dist/{Sticker-DjF9VJQB.d.mts → Sticker-Bs25ISz7.d.mts} +5 -5
  317. package/dist/{Sticker-N8XZnv7M.d.cts → Sticker-CI-XxUmM.d.cts} +3 -3
  318. package/dist/{Sticker-D0jIU2Dt.cjs → Sticker-CIoseh9f.cjs} +3 -3
  319. package/dist/{Sticker-D0jIU2Dt.cjs.map → Sticker-CIoseh9f.cjs.map} +1 -1
  320. package/dist/{Sticker-B0TbkV4o.mjs → Sticker-DbqKLe33.mjs} +3 -3
  321. package/dist/{Sticker-B0TbkV4o.mjs.map → Sticker-DbqKLe33.mjs.map} +1 -1
  322. package/dist/Sticker.d.cts +1 -1
  323. package/dist/Sticker.d.mts +1 -1
  324. package/dist/StringValueControl.d.mts +39 -0
  325. package/dist/SwatchPicker.d.mts +1 -1
  326. package/dist/Tab.d.mts +2 -2
  327. package/dist/{TabBar-BpHMYvNb.cjs → TabBar-PFaDNRw0.cjs} +4 -4
  328. package/dist/{TabBar-BpHMYvNb.cjs.map → TabBar-PFaDNRw0.cjs.map} +1 -1
  329. package/dist/{TabBar-ByusqAXF.mjs → TabBar-zSA8kyE6.mjs} +4 -4
  330. package/dist/{TabBar-ByusqAXF.mjs.map → TabBar-zSA8kyE6.mjs.map} +1 -1
  331. package/dist/TabBarIconButton.d.mts +1 -1
  332. package/dist/{Table-DJZtluW3.d.cts → Table-BNScLj9g.d.mts} +1 -1
  333. package/dist/{Table-CNs8p8hL.mjs → Table-D8IcpACv.mjs} +5 -5
  334. package/dist/{Table-CNs8p8hL.mjs.map → Table-D8IcpACv.mjs.map} +1 -1
  335. package/dist/{Table-D3nyiZt0.d.mts → Table-DXqyNohc.d.cts} +1 -1
  336. package/dist/{Table-C9rjUVpn.cjs → Table-DxLvJYWK.cjs} +5 -5
  337. package/dist/{Table-C9rjUVpn.cjs.map → Table-DxLvJYWK.cjs.map} +1 -1
  338. package/dist/Table.d.cts +1 -1
  339. package/dist/Table.d.mts +1 -1
  340. package/dist/{TableBody-BFPF07n4.d.cts → TableBody-CrDNMyT8.d.mts} +1 -1
  341. package/dist/{TableBody-DpRjZgzU.d.mts → TableBody-CxwHmdNb.d.cts} +1 -1
  342. package/dist/TableBody.d.cts +1 -1
  343. package/dist/TableBody.d.mts +1 -1
  344. package/dist/{TableBox-DO-yToJk.cjs → TableBox-CiuXCXyv.cjs} +11 -11
  345. package/dist/{TableBox-DO-yToJk.cjs.map → TableBox-CiuXCXyv.cjs.map} +1 -1
  346. package/dist/{TableBox-DIJffyts.mjs → TableBox-luasMC73.mjs} +11 -11
  347. package/dist/{TableBox-DIJffyts.mjs.map → TableBox-luasMC73.mjs.map} +1 -1
  348. package/dist/TableBox.d.cts +2 -2
  349. package/dist/TableBox.d.mts +2 -2
  350. package/dist/{TableBoxCell-D1bjYv7b.d.mts → TableBoxCell-By1xE6_Q.d.mts} +7 -7
  351. package/dist/{TableBoxCell-DOQ8PnAT.d.cts → TableBoxCell-DIMenSwX.d.cts} +6 -6
  352. package/dist/TableBoxCell.d.cts +1 -1
  353. package/dist/TableBoxCell.d.mts +1 -1
  354. package/dist/TableBoxField.d.cts +3 -3
  355. package/dist/TableBoxField.d.mts +4 -4
  356. package/dist/{TableBoxRow-CTR14HJF.d.mts → TableBoxRow-CsRPRPQ-.d.mts} +4 -4
  357. package/dist/{TableBoxRow-BUK5RjRA.d.cts → TableBoxRow-RNQ6wJLh.d.cts} +3 -3
  358. package/dist/TableBoxRow.d.cts +1 -1
  359. package/dist/TableBoxRow.d.mts +1 -1
  360. package/dist/{TableBoxRowActions-CKgUEH38.d.cts → TableBoxRowActions-CYpoPhYZ.d.cts} +2 -2
  361. package/dist/{TableBoxRowActions-BoMt5d0b.d.mts → TableBoxRowActions-DMYOI8Do.d.mts} +2 -2
  362. package/dist/TableBoxRowActions.d.cts +1 -1
  363. package/dist/TableBoxRowActions.d.mts +1 -1
  364. package/dist/TableCell.d.cts +1 -1
  365. package/dist/TableCell.d.mts +1 -1
  366. package/dist/{TableControls-BZyiqk9V.d.mts → TableControls-BehR7CKS.d.mts} +4 -4
  367. package/dist/TableControls-BtXK7Ils.cjs +3995 -0
  368. package/dist/TableControls-BtXK7Ils.cjs.map +1 -0
  369. package/dist/{TableControls-Bkd3jhC1.d.cts → TableControls-CLNF0AJG.d.cts} +3 -3
  370. package/dist/TableControls-DHMs7o58.mjs +3859 -0
  371. package/dist/TableControls-DHMs7o58.mjs.map +1 -0
  372. package/dist/TableControls.d.cts +1 -1
  373. package/dist/TableControls.d.mts +1 -1
  374. package/dist/{TableControlsContext-D6XpuRVw.d.cts → TableControlsContext-DAZx6Rrj.d.cts} +2 -2
  375. package/dist/{TableControlsContext-CleTWT7z.d.mts → TableControlsContext-D_SBFZN1.d.mts} +2 -2
  376. package/dist/TableControlsContext.d.cts +1 -1
  377. package/dist/TableControlsContext.d.mts +1 -1
  378. package/dist/{TableHead-CTsZNRJm.d.cts → TableHead-Ch4Ho3LW.d.cts} +1 -1
  379. package/dist/{TableHead-wl78HqPT.d.mts → TableHead-LxvG0e9k.d.mts} +1 -1
  380. package/dist/TableHead.d.cts +1 -1
  381. package/dist/TableHead.d.mts +1 -1
  382. package/dist/{TableHeaderCell-UoY92mzR.d.cts → TableHeaderCell-Br8ZE3Xe.d.mts} +1 -1
  383. package/dist/{TableHeaderCell-B2yiOw4w.d.mts → TableHeaderCell-Crsa2R2g.d.cts} +1 -1
  384. package/dist/TableHeaderCell.d.cts +1 -1
  385. package/dist/TableHeaderCell.d.mts +1 -1
  386. package/dist/{TableLayout-GyRS-Awa.d.cts → TableLayout-Ct0kepcA.d.cts} +1 -1
  387. package/dist/{TableLayout-_TWUnffx.d.mts → TableLayout-nwy094C_.d.mts} +1 -1
  388. package/dist/TableLayout.d.cts +1 -1
  389. package/dist/TableLayout.d.mts +1 -1
  390. package/dist/{TableRow-C-faHbkL.d.mts → TableRow-BvS4yjo6.d.mts} +2 -2
  391. package/dist/{TableRow-BVzduO4G.d.cts → TableRow-DVTPqT4w.d.cts} +1 -1
  392. package/dist/TableRow.d.cts +1 -1
  393. package/dist/TableRow.d.mts +1 -1
  394. package/dist/TableTH.d.cts +1 -1
  395. package/dist/TableTH.d.mts +1 -1
  396. package/dist/{TableViewConfigurationDropdown-D2TM2wCv.d.mts → TableViewConfigurationDropdown-BYPh4dIP.d.mts} +2 -2
  397. package/dist/{TableViewConfigurationDropdown-u3-prEHJ.d.cts → TableViewConfigurationDropdown-CaiOGyrU.d.cts} +2 -2
  398. package/dist/TableViewConfigurationDropdown.d.cts +1 -1
  399. package/dist/TableViewConfigurationDropdown.d.mts +1 -1
  400. package/dist/TechnicalSticker.d.mts +1 -1
  401. package/dist/{Text-D3FXEnG6.d.mts → Text-DNPbAuUG.d.mts} +3 -3
  402. package/dist/{Text-CzN0DOXV.cjs → Text-G9QmYf0P.cjs} +1 -1
  403. package/dist/{Text-CzN0DOXV.cjs.map → Text-G9QmYf0P.cjs.map} +1 -1
  404. package/dist/{Text-hEoPeOc9.mjs → Text-RcEfNFLx.mjs} +1 -1
  405. package/dist/{Text-hEoPeOc9.mjs.map → Text-RcEfNFLx.mjs.map} +1 -1
  406. package/dist/Text.d.mts +1 -1
  407. package/dist/{TextArea-KpDoXg-5.d.cts → TextArea-B89wtTsF.d.mts} +2 -2
  408. package/dist/{TextArea-DVHi0K7M.cjs → TextArea-BNiipQDb.cjs} +3 -3
  409. package/dist/{TextArea-DVHi0K7M.cjs.map → TextArea-BNiipQDb.cjs.map} +1 -1
  410. package/dist/{TextArea-weASn4Hq.d.mts → TextArea-CHW9FKM4.d.cts} +2 -2
  411. package/dist/{TextArea-DIPeBLkr.mjs → TextArea-NCLsW-03.mjs} +3 -3
  412. package/dist/{TextArea-DIPeBLkr.mjs.map → TextArea-NCLsW-03.mjs.map} +1 -1
  413. package/dist/TextArea.d.cts +1 -1
  414. package/dist/TextArea.d.mts +1 -1
  415. package/dist/{TextUnderlineTooltip-Cep5cgEQ.d.mts → TextUnderlineTooltip-5-0D8s4z.d.mts} +3 -3
  416. package/dist/{TextUnderlineTooltip-cSMjZOuB.d.cts → TextUnderlineTooltip-DMEyOu8C.d.cts} +2 -2
  417. package/dist/TextUnderlineTooltip.d.cts +1 -1
  418. package/dist/TextUnderlineTooltip.d.mts +1 -1
  419. package/dist/Tile.d.cts +1 -1
  420. package/dist/Tile.d.mts +2 -2
  421. package/dist/Toast.d.cts +1 -1
  422. package/dist/Toast.d.mts +1 -1
  423. package/dist/{Toggle-CfjUQlcK.mjs → Toggle-Bie9zCem.mjs} +5 -5
  424. package/dist/{Toggle-CfjUQlcK.mjs.map → Toggle-Bie9zCem.mjs.map} +1 -1
  425. package/dist/{Toggle-CTtrhzsV.cjs → Toggle-Ce-rF8Xp.cjs} +5 -5
  426. package/dist/{Toggle-CTtrhzsV.cjs.map → Toggle-Ce-rF8Xp.cjs.map} +1 -1
  427. package/dist/{Toggle-BQCOJZjZ.d.mts → Toggle-DzYLgxGk.d.mts} +1 -1
  428. package/dist/{Toggle-CYQE1Nk_.d.cts → Toggle-tbIebQWC.d.cts} +1 -1
  429. package/dist/Toggle.d.cts +1 -1
  430. package/dist/Toggle.d.mts +1 -1
  431. package/dist/{Tooltip-BhGRP9QA.d.cts → Tooltip--eDrrk2r.d.cts} +2 -2
  432. package/dist/{Tooltip-CDvOu1UN.mjs → Tooltip-C6AR1xT-.mjs} +3 -3
  433. package/dist/{Tooltip-CDvOu1UN.mjs.map → Tooltip-C6AR1xT-.mjs.map} +1 -1
  434. package/dist/{Tooltip-DRgufW3i.d.mts → Tooltip-CUC-JuRL.d.mts} +3 -3
  435. package/dist/{Tooltip-vylydKVv.cjs → Tooltip-olP3rdUO.cjs} +3 -3
  436. package/dist/{Tooltip-vylydKVv.cjs.map → Tooltip-olP3rdUO.cjs.map} +1 -1
  437. package/dist/Tooltip.d.cts +1 -1
  438. package/dist/Tooltip.d.mts +1 -1
  439. package/dist/{TruncatedText-Cy8NpHzm.d.mts → TruncatedText-BJnowVTx.d.mts} +1 -1
  440. package/dist/{TruncatedText-D8f3AiBL.d.cts → TruncatedText-Dit2NJI6.d.cts} +1 -1
  441. package/dist/components/Attribute/index.cjs +6 -6
  442. package/dist/components/Attribute/index.mjs +10 -10
  443. package/dist/components/Attribute/index.mjs.map +1 -1
  444. package/dist/components/Badge/index.cjs +1 -1
  445. package/dist/components/Badge/index.mjs +1 -1
  446. package/dist/components/Banner/index.cjs +1 -1
  447. package/dist/components/Banner/index.mjs +1 -1
  448. package/dist/components/Breadcrumbs/index.cjs +3 -271
  449. package/dist/components/Breadcrumbs/index.d.cts +2 -2
  450. package/dist/components/Breadcrumbs/index.d.mts +2 -2
  451. package/dist/components/Breadcrumbs/index.mjs +1 -267
  452. package/dist/components/Button/index.cjs +1 -1
  453. package/dist/components/Button/index.d.mts +2 -2
  454. package/dist/components/Button/index.mjs +1 -1
  455. package/dist/components/ButtonGroup/index.cjs +3 -3
  456. package/dist/components/ButtonGroup/index.mjs +3 -3
  457. package/dist/components/Card/index.cjs +1 -1
  458. package/dist/components/Card/index.d.cts +2 -2
  459. package/dist/components/Card/index.d.mts +2 -2
  460. package/dist/components/Card/index.mjs +1 -1
  461. package/dist/components/CardV2/index.cjs +3 -415
  462. package/dist/components/CardV2/index.d.cts +1 -1
  463. package/dist/components/CardV2/index.d.mts +1 -1
  464. package/dist/components/CardV2/index.mjs +1 -410
  465. package/dist/components/Checkbox/index.cjs +1 -1
  466. package/dist/components/Checkbox/index.d.cts +1 -1
  467. package/dist/components/Checkbox/index.d.mts +1 -1
  468. package/dist/components/Checkbox/index.mjs +1 -1
  469. package/dist/components/Combobox/index.cjs +1 -1
  470. package/dist/components/Combobox/index.d.cts +2 -2
  471. package/dist/components/Combobox/index.d.mts +2 -2
  472. package/dist/components/Combobox/index.mjs +1 -1
  473. package/dist/components/ConfigFormGroup/index.cjs +2 -2
  474. package/dist/components/ConfigFormGroup/index.mjs +2 -2
  475. package/dist/components/DataTable/TableControls/index.cjs +15 -1
  476. package/dist/components/DataTable/TableControls/index.d.cts +16 -6
  477. package/dist/components/DataTable/TableControls/index.d.mts +16 -6
  478. package/dist/components/DataTable/TableControls/index.mjs +2 -2
  479. package/dist/components/DataTable/index.cjs +14 -14
  480. package/dist/components/DataTable/index.mjs +24 -24
  481. package/dist/components/DataTable/index.mjs.map +1 -1
  482. package/dist/components/DataTable/types.d.cts +2 -2
  483. package/dist/components/DataTable/types.d.mts +2 -2
  484. package/dist/components/DatePicker/index.cjs +6 -929
  485. package/dist/components/DatePicker/index.mjs +1 -921
  486. package/dist/components/DropdownButton/index.cjs +1 -1
  487. package/dist/components/DropdownButton/index.mjs +1 -1
  488. package/dist/components/DropdownMenu/index.cjs +1 -1
  489. package/dist/components/DropdownMenu/index.d.cts +1 -1
  490. package/dist/components/DropdownMenu/index.d.mts +1 -1
  491. package/dist/components/DropdownMenu/index.mjs +1 -1
  492. package/dist/components/FormControl/index.cjs +2 -2
  493. package/dist/components/FormControl/index.d.cts +2 -2
  494. package/dist/components/FormControl/index.d.mts +2 -2
  495. package/dist/components/FormControl/index.mjs +2 -2
  496. package/dist/components/FormField/index.cjs +15 -486
  497. package/dist/components/FormField/index.d.cts +1 -1
  498. package/dist/components/FormField/index.d.mts +1 -1
  499. package/dist/components/FormField/index.mjs +1 -470
  500. package/dist/components/HoverCopyableField/index.cjs +1 -1
  501. package/dist/components/HoverCopyableField/index.mjs +1 -1
  502. package/dist/components/ImageTile/index.cjs +8 -8
  503. package/dist/components/ImageTile/index.mjs +8 -8
  504. package/dist/components/Input/index.cjs +1 -1
  505. package/dist/components/Input/index.d.cts +1 -1
  506. package/dist/components/Input/index.d.mts +1 -1
  507. package/dist/components/Input/index.mjs +1 -1
  508. package/dist/components/Link/index.cjs +1 -1
  509. package/dist/components/Link/index.mjs +1 -1
  510. package/dist/components/ListBox/index.cjs +1 -1
  511. package/dist/components/ListBox/index.d.cts +4 -2
  512. package/dist/components/ListBox/index.d.mts +4 -2
  513. package/dist/components/ListBox/index.mjs +1 -1
  514. package/dist/components/LoadingShimmer/index.cjs +1 -1
  515. package/dist/components/LoadingShimmer/index.mjs +1 -1
  516. package/dist/components/MaskedInput/index.cjs +2 -2
  517. package/dist/components/MaskedInput/index.mjs +2 -2
  518. package/dist/components/Menu/index.cjs +1 -1
  519. package/dist/components/Menu/index.d.cts +1 -1
  520. package/dist/components/Menu/index.d.mts +1 -1
  521. package/dist/components/Menu/index.mjs +1 -1
  522. package/dist/components/Modal/index.cjs +7 -7
  523. package/dist/components/Modal/index.mjs +7 -7
  524. package/dist/components/PageHeader/index.cjs +3 -67
  525. package/dist/components/PageHeader/index.mjs +1 -63
  526. package/dist/components/Pagination/index.cjs +1 -1
  527. package/dist/components/Pagination/index.d.cts +3 -3
  528. package/dist/components/Pagination/index.d.mts +3 -3
  529. package/dist/components/Pagination/index.mjs +1 -1
  530. package/dist/components/Pii/index.cjs +1 -1
  531. package/dist/components/Pii/index.mjs +1 -1
  532. package/dist/components/Popover/index.cjs +1 -1
  533. package/dist/components/Popover/index.mjs +1 -1
  534. package/dist/components/ProgressBar/index.cjs +1 -1
  535. package/dist/components/ProgressBar/index.mjs +1 -1
  536. package/dist/components/Radio/index.cjs +1 -1
  537. package/dist/components/Radio/index.mjs +1 -1
  538. package/dist/components/RadioGroup/index.cjs +1 -1
  539. package/dist/components/RadioGroup/index.d.cts +1 -1
  540. package/dist/components/RadioGroup/index.d.mts +1 -1
  541. package/dist/components/RadioGroup/index.mjs +1 -1
  542. package/dist/components/SegmentedControl/index.cjs +1 -1
  543. package/dist/components/SegmentedControl/index.d.cts +1 -1
  544. package/dist/components/SegmentedControl/index.d.mts +1 -1
  545. package/dist/components/SegmentedControl/index.mjs +1 -1
  546. package/dist/components/Select/index.cjs +1 -1
  547. package/dist/components/Select/index.d.cts +1 -1
  548. package/dist/components/Select/index.d.mts +1 -1
  549. package/dist/components/Select/index.mjs +1 -1
  550. package/dist/components/Slider/index.cjs +2 -2
  551. package/dist/components/Slider/index.mjs +2 -2
  552. package/dist/components/Spacer/index.cjs +1 -1
  553. package/dist/components/Spacer/index.mjs +1 -1
  554. package/dist/components/Stack/index.cjs +1 -1
  555. package/dist/components/Stack/index.d.cts +1 -1
  556. package/dist/components/Stack/index.d.mts +1 -1
  557. package/dist/components/Stack/index.mjs +1 -1
  558. package/dist/components/StatusIndicator/index.cjs +60 -10
  559. package/dist/components/StatusIndicator/index.cjs.map +1 -1
  560. package/dist/components/StatusIndicator/index.d.cts +2 -2
  561. package/dist/components/StatusIndicator/index.d.mts +2 -2
  562. package/dist/components/StatusIndicator/index.mjs +61 -12
  563. package/dist/components/StatusIndicator/index.mjs.map +1 -1
  564. package/dist/components/Sticker/index.cjs +1 -1
  565. package/dist/components/Sticker/index.d.cts +1 -1
  566. package/dist/components/Sticker/index.d.mts +1 -1
  567. package/dist/components/Sticker/index.mjs +1 -1
  568. package/dist/components/TabBar/index.cjs +1 -1
  569. package/dist/components/TabBar/index.mjs +1 -1
  570. package/dist/components/Table/index.cjs +1 -1
  571. package/dist/components/Table/index.d.cts +7 -7
  572. package/dist/components/Table/index.d.mts +7 -7
  573. package/dist/components/Table/index.mjs +1 -1
  574. package/dist/components/TableBox/index.cjs +1 -1
  575. package/dist/components/TableBox/index.d.cts +2 -2
  576. package/dist/components/TableBox/index.d.mts +2 -2
  577. package/dist/components/TableBox/index.mjs +1 -1
  578. package/dist/components/TechnicalSticker/index.cjs +4 -4
  579. package/dist/components/TechnicalSticker/index.mjs +4 -4
  580. package/dist/components/Text/index.cjs +1 -1
  581. package/dist/components/Text/index.d.mts +1 -1
  582. package/dist/components/Text/index.mjs +1 -1
  583. package/dist/components/TextArea/index.cjs +1 -1
  584. package/dist/components/TextArea/index.d.cts +1 -1
  585. package/dist/components/TextArea/index.d.mts +1 -1
  586. package/dist/components/TextArea/index.mjs +1 -1
  587. package/dist/components/Tile/index.cjs +4 -4
  588. package/dist/components/Tile/index.mjs +4 -4
  589. package/dist/components/Toast/index.cjs +1 -1
  590. package/dist/components/Toast/index.mjs +1 -1
  591. package/dist/components/Toggle/index.cjs +1 -1
  592. package/dist/components/Toggle/index.d.cts +1 -1
  593. package/dist/components/Toggle/index.d.mts +1 -1
  594. package/dist/components/Toggle/index.mjs +1 -1
  595. package/dist/components/Tooltip/index.cjs +1 -1
  596. package/dist/components/Tooltip/index.d.cts +3 -3
  597. package/dist/components/Tooltip/index.d.mts +3 -3
  598. package/dist/components/Tooltip/index.mjs +1 -1
  599. package/dist/compound-expression.d.mts +9 -0
  600. package/dist/{constants-kwVsjw8O.d.cts → constants-B6c8S033.d.cts} +1 -1
  601. package/dist/{constants-DVwPpTt5.d.mts → constants-BASogfT_.d.mts} +1 -1
  602. package/dist/constants.d.cts +1 -1
  603. package/dist/constants.d.mts +1 -1
  604. package/dist/containers.d.mts +8 -0
  605. package/dist/display.d.mts +8 -0
  606. package/dist/fieldPickerOptions.d.mts +29 -0
  607. package/dist/filter-size-context-Blw6Sd69.d.mts +52 -0
  608. package/dist/filter-size-context-CIw0Zi6r.d.cts +52 -0
  609. package/dist/filter-size-context.d.cts +2 -0
  610. package/dist/filter-size-context.d.mts +2 -0
  611. package/dist/helpers.d.cts +1 -1
  612. package/dist/helpers.d.mts +1 -1
  613. package/dist/index-4_B2yRzD.d.mts +7 -0
  614. package/dist/{index-_tQRydn9.d.cts → index-Bw8QVu_o.d.cts} +3 -3
  615. package/dist/index-C9EIpBh8.d.cts +7 -0
  616. package/dist/index-D34XP8vp.d.cts +54 -0
  617. package/dist/{index-BPnJP0jZ.d.mts → index-DDbjWdk0.d.mts} +4 -4
  618. package/dist/index-IlwGkCAe2.d.mts +54 -0
  619. package/dist/index-sQecLSpR.d.cts +1 -0
  620. package/dist/index-sViox9YW.d.mts +1 -0
  621. package/dist/index.d.cts +1 -1
  622. package/dist/index.d.mts +1 -1
  623. package/dist/index2.d.cts +1 -1
  624. package/dist/index2.d.mts +1 -1
  625. package/dist/index3.d.cts +4 -1
  626. package/dist/index3.d.mts +4 -1
  627. package/dist/index4.d.cts +11 -0
  628. package/dist/index4.d.mts +11 -0
  629. package/dist/index5.d.cts +1 -0
  630. package/dist/index5.d.mts +2 -0
  631. package/dist/index6.d.mts +1 -0
  632. package/dist/{input-DrG6mA0V.d.mts → input-Bv5fKt5J.d.mts} +3 -3
  633. package/dist/{input-BkzqXwn7.d.cts → input-DPB0cX2m.d.cts} +2 -2
  634. package/dist/inputFields.d.cts +10 -10
  635. package/dist/inputFields.d.mts +11 -11
  636. package/dist/{intersperse-Gxwgpbk8.cjs → intersperse-_0nQM5Rb.cjs} +1 -1
  637. package/dist/{intersperse-Gxwgpbk8.cjs.map → intersperse-_0nQM5Rb.cjs.map} +1 -1
  638. package/dist/{intersperse-yd3oMrQl.mjs → intersperse-vOYvFOfF.mjs} +1 -1
  639. package/dist/{intersperse-yd3oMrQl.mjs.map → intersperse-vOYvFOfF.mjs.map} +1 -1
  640. package/dist/layouts/LayoutLoadingShimmer/index.cjs +139 -0
  641. package/dist/layouts/LayoutLoadingShimmer/index.cjs.map +1 -0
  642. package/dist/layouts/LayoutLoadingShimmer/index.d.cts +2 -0
  643. package/dist/layouts/LayoutLoadingShimmer/index.d.mts +2 -0
  644. package/dist/layouts/LayoutLoadingShimmer/index.mjs +133 -0
  645. package/dist/layouts/LayoutLoadingShimmer/index.mjs.map +1 -0
  646. package/dist/lib/MiddleTruncatedText.cjs +1 -1
  647. package/dist/lib/MiddleTruncatedText.mjs +1 -1
  648. package/dist/lib/PDSProvider.d.mts +1 -1
  649. package/dist/lib/TruncatedText.cjs +1 -1
  650. package/dist/lib/TruncatedText.d.cts +1 -1
  651. package/dist/lib/TruncatedText.d.mts +1 -1
  652. package/dist/lib/TruncatedText.mjs +1 -1
  653. package/dist/lib/TruncatedTextWithTooltip.cjs +2 -2
  654. package/dist/lib/TruncatedTextWithTooltip.d.cts +1 -1
  655. package/dist/lib/TruncatedTextWithTooltip.d.mts +1 -1
  656. package/dist/lib/TruncatedTextWithTooltip.mjs +2 -2
  657. package/dist/lib/message.d.cts +1 -1
  658. package/dist/lib/message.d.mts +1 -1
  659. package/dist/lib/pseudoClass.d.mts +1 -1
  660. package/dist/{message-C2286H-r.d.cts → message-BEgtEjQC.d.cts} +1 -1
  661. package/dist/{message-BfJ87aIU.d.mts → message-CMHvlPGn.d.mts} +1 -1
  662. package/dist/mixins/focus.d.mts +1 -1
  663. package/dist/mixins/hoverable.d.mts +2 -2
  664. package/dist/mixins/input.d.cts +1 -1
  665. package/dist/mixins/input.d.mts +1 -1
  666. package/dist/mixins/menuItem.d.mts +2 -2
  667. package/dist/mixins/text.d.mts +1 -1
  668. package/dist/operators-1qE2GpC7.d.cts +43 -0
  669. package/dist/operators-Bo31xlc2.d.mts +43 -0
  670. package/dist/operators.d.cts +2 -0
  671. package/dist/operators.d.mts +2 -0
  672. package/dist/{text-CtoDqqAO.d.mts → text-B21s9mRZ.d.mts} +1 -1
  673. package/dist/{theme-Bx2sn3Lt.d.mts → theme-BzBpJXhO.d.mts} +1 -1
  674. package/dist/theme.d.mts +1 -1
  675. package/dist/types-B_HHNlia.d.cts +158 -0
  676. package/dist/types-CCvc590y.d.cts +45 -0
  677. package/dist/{types-CuCT-YnX.d.cts → types-CkiXVJeR.d.cts} +1 -1
  678. package/dist/types-D58IoRx6.d.mts +158 -0
  679. package/dist/types-D7ppqnNj.d.mts +45 -0
  680. package/dist/{types-B34lbI2k.d.mts → types-DEh_pXgS.d.mts} +1 -1
  681. package/dist/{types-C_AUGurs.d.cts → types-SYSKcZKW.d.cts} +1 -1
  682. package/dist/{types-DTak9UTv.d.mts → types-TV9nVfSe.d.mts} +1 -1
  683. package/dist/types.d.cts +1 -1
  684. package/dist/types.d.mts +1 -1
  685. package/dist/types2.d.cts +2 -2
  686. package/dist/types2.d.mts +2 -2
  687. package/dist/types3.d.cts +2 -0
  688. package/dist/types3.d.mts +2 -0
  689. package/dist/types4.d.cts +2 -0
  690. package/dist/types4.d.mts +2 -0
  691. package/dist/use-rules-popover-selection.d.mts +19 -0
  692. package/dist/useComboboxFooterAction.d.mts +47 -0
  693. package/dist/useFilterStateV2-DCQghouq.d.mts +93 -0
  694. package/dist/useFilterStateV2-DbPwX5N1.d.cts +93 -0
  695. package/dist/useFilterStateV2.d.cts +2 -0
  696. package/dist/useFilterStateV2.d.mts +2 -0
  697. package/dist/{useFormField-CaIdE7JQ.d.cts → useFormField--Q8ZdpW5.d.cts} +2 -2
  698. package/dist/{useFormField-B98dmreO.cjs → useFormField-BZlArnsI.cjs} +2 -2
  699. package/dist/{useFormField-B98dmreO.cjs.map → useFormField-BZlArnsI.cjs.map} +1 -1
  700. package/dist/{useFormField-BE0rTBF1.d.mts → useFormField-D8mLsiQc.d.mts} +2 -2
  701. package/dist/{useFormField-eftOPiXj.mjs → useFormField-DhYd6bNn.mjs} +2 -2
  702. package/dist/{useFormField-eftOPiXj.mjs.map → useFormField-DhYd6bNn.mjs.map} +1 -1
  703. package/dist/useFormField.d.cts +1 -1
  704. package/dist/useFormField.d.mts +1 -1
  705. package/dist/{useFormGroup-BE7v9eAj.cjs → useFormGroup-Bmnzgq0S.cjs} +1 -1
  706. package/dist/{useFormGroup-BE7v9eAj.cjs.map → useFormGroup-Bmnzgq0S.cjs.map} +1 -1
  707. package/dist/{useFormGroup-BMukAMAd.mjs → useFormGroup-DWVW7A9f.mjs} +1 -1
  708. package/dist/{useFormGroup-BMukAMAd.mjs.map → useFormGroup-DWVW7A9f.mjs.map} +1 -1
  709. package/dist/{useTableBoxDragAndDrop--QBq2FQh.d.cts → useTableBoxDragAndDrop-BMo-iaUF.d.mts} +1 -1
  710. package/dist/{useTableBoxDragAndDrop-BTtv9PEt.d.mts → useTableBoxDragAndDrop-DnbUToce.d.cts} +1 -1
  711. package/dist/useTableBoxDragAndDrop.d.cts +1 -1
  712. package/dist/useTableBoxDragAndDrop.d.mts +1 -1
  713. package/dist/{useToggle-3k3EkV8V.mjs → useToggle-Bo3yd14Y.mjs} +1 -1
  714. package/dist/{useToggle-3k3EkV8V.mjs.map → useToggle-Bo3yd14Y.mjs.map} +1 -1
  715. package/dist/{useToggle-CSkZWXtQ.cjs → useToggle-DARO917w.cjs} +1 -1
  716. package/dist/{useToggle-CSkZWXtQ.cjs.map → useToggle-DARO917w.cjs.map} +1 -1
  717. package/dist/useTruncation.d.mts +1 -1
  718. package/dist/{utilities-DqO6Sh94.d.cts → utilities-BO_95qFA.d.mts} +1 -1
  719. package/dist/{utilities-SMbDe8oK.d.mts → utilities-mSlaTrjB.d.cts} +1 -1
  720. package/dist/utilities.d.cts +1 -1
  721. package/dist/utilities.d.mts +1 -1
  722. package/dist/utils/storybook.cjs +1 -1
  723. package/dist/utils/storybook.mjs +1 -1
  724. package/dist/utils/testing.cjs +1 -1
  725. package/dist/utils/testing.d.mts +1 -1
  726. package/dist/utils/testing.mjs +1 -1
  727. package/dist/utils.d.mts +22 -5
  728. package/dist/utils2.d.mts +9 -0
  729. package/dist/validation-CJymv6JE.d.cts +51 -0
  730. package/dist/validation-vLh3t2dk.d.mts +51 -0
  731. package/dist/validation.d.cts +2 -0
  732. package/dist/validation.d.mts +2 -0
  733. package/dist/value-control-resolver-B9p25q3G.d.cts +46 -0
  734. package/dist/value-control-resolver-CE-bqdAl.d.mts +46 -0
  735. package/dist/value-control-resolver.d.cts +2 -0
  736. package/dist/value-control-resolver.d.mts +2 -0
  737. package/package.json +12 -3
  738. package/dist/Combobox-4Bi9-N1p.cjs.map +0 -1
  739. package/dist/Combobox-CeKMrlxy.mjs.map +0 -1
  740. package/dist/ListBox-BCscLcYL.cjs.map +0 -1
  741. package/dist/ListBox-CDNOJmvz.mjs.map +0 -1
  742. package/dist/Pagination-Cj08JRG9.mjs.map +0 -1
  743. package/dist/Pagination-D4IVVj3S.cjs.map +0 -1
  744. package/dist/SegmentedControl-B1ZLgu61.mjs.map +0 -1
  745. package/dist/SegmentedControl-CIJz0oxY.cjs.map +0 -1
  746. package/dist/Select-ByTgXOlU.mjs.map +0 -1
  747. package/dist/Select-C65bfYeT.cjs.map +0 -1
  748. package/dist/TableControls-BkdSeQvt.mjs +0 -1029
  749. package/dist/TableControls-BkdSeQvt.mjs.map +0 -1
  750. package/dist/TableControls-DcbnNqeK.cjs +0 -1080
  751. package/dist/TableControls-DcbnNqeK.cjs.map +0 -1
  752. package/dist/components/Breadcrumbs/index.cjs.map +0 -1
  753. package/dist/components/Breadcrumbs/index.mjs.map +0 -1
  754. package/dist/components/CardV2/index.cjs.map +0 -1
  755. package/dist/components/CardV2/index.mjs.map +0 -1
  756. package/dist/components/DatePicker/index.cjs.map +0 -1
  757. package/dist/components/DatePicker/index.mjs.map +0 -1
  758. package/dist/components/FormField/index.cjs.map +0 -1
  759. package/dist/components/FormField/index.mjs.map +0 -1
  760. package/dist/components/PageHeader/index.cjs.map +0 -1
  761. package/dist/components/PageHeader/index.mjs.map +0 -1
  762. /package/dist/{index-8SLBz2NH.d.mts → index--p6oQT9I.d.mts} +0 -0
  763. /package/dist/{index-B2KLYYkM.d.cts → index-BIAn8oQh.d.cts} +0 -0
  764. /package/dist/{index-B5cbLMbC2.d.cts → index-BL32-cvv.d.cts} +0 -0
  765. /package/dist/{index-BCsiC0tv.d.cts → index-BXpMZvwA.d.cts} +0 -0
  766. /package/dist/{index-BPiqSRRl.d.mts → index-BYd3Btr1.d.mts} +0 -0
  767. /package/dist/{index-BSVhZrWN.d.mts → index-BhY1qu3m.d.cts} +0 -0
  768. /package/dist/{index-BTImeehL2.d.mts → index-BlwcRiXv.d.cts} +0 -0
  769. /package/dist/{index-C3kE54DD.d.mts → index-C1ihAKnV.d.cts} +0 -0
  770. /package/dist/{index-C6yvNuzO.d.cts → index-CDAfh8Ew.d.cts} +0 -0
  771. /package/dist/{index-C8k_zgEm.d.cts → index-CDGG7lCB.d.mts} +0 -0
  772. /package/dist/{index-CEqOS-7M.d.mts → index-CFG0_wK4.d.cts} +0 -0
  773. /package/dist/{index-CROz1VSV.d.mts → index-CKKoxA9V.d.mts} +0 -0
  774. /package/dist/{index-CWt1yJ75.d.cts → index-CMuRFTR3.d.mts} +0 -0
  775. /package/dist/{index-CmCelmEL.d.cts → index-CNxS4Tlu.d.mts} +0 -0
  776. /package/dist/{index-CmUzJ4E-2.d.cts → index-CQ25UCod.d.cts} +0 -0
  777. /package/dist/{index-CsuikFeJ.d.mts → index-CWB6exYm.d.mts} +0 -0
  778. /package/dist/{index-CtCMUyZA.d.cts → index-Cv0jeUQf2.d.cts} +0 -0
  779. /package/dist/{index-Cz6N-KeS.d.cts → index-CwSIy_W-.d.cts} +0 -0
  780. /package/dist/{index-D2HUTZ-d.d.cts → index-CzItj62a.d.mts} +0 -0
  781. /package/dist/{index-D8dPsry7.d.mts → index-D4DUvwPf.d.mts} +0 -0
  782. /package/dist/{index-DeEmP3Jc.d.cts → index-D6CnpA_r.d.cts} +0 -0
  783. /package/dist/{index-DeVKzGce.d.mts → index-D9IqtUDs.d.cts} +0 -0
  784. /package/dist/{index-DrZ2Dh-H.d.cts → index-DFKoAoY2.d.cts} +0 -0
  785. /package/dist/{index-DxSM7VXJ.d.cts → index-DGsJdI5l.d.mts} +0 -0
  786. /package/dist/{index-FtE8MXJ_.d.mts → index-DM6vVDZD.d.mts} +0 -0
  787. /package/dist/{index-JuxZj_Qp2.d.mts → index-DWfPppPU.d.mts} +0 -0
  788. /package/dist/{index-LhFpnU-f.d.mts → index-DXJd7-2Z.d.mts} +0 -0
  789. /package/dist/{index-N-OgGgfF.d.mts → index-DkrC-i1D.d.mts} +0 -0
  790. /package/dist/{index-NKYLt_R9.d.mts → index-DpEKQcoR.d.cts} +0 -0
  791. /package/dist/{index-VWno75SQ.d.mts → index-DvuJXuAN.d.mts} +0 -0
  792. /package/dist/{index-c55Utzva.d.mts → index-Iujpc9_6.d.mts} +0 -0
  793. /package/dist/{index-gpCH5158.d.mts → index-PWQavSPf.d.mts} +0 -0
  794. /package/dist/{index-lQ_hGQ08.d.cts → index-dC-i2r_u.d.cts} +0 -0
  795. /package/dist/{index-luywJTzJ.d.mts → index-e6k85DKM.d.mts} +0 -0
  796. /package/dist/{index-zO0Ly4bS.d.cts → index-lIMqGGJz.d.mts} +0 -0
@@ -0,0 +1,3859 @@
1
+ import { isActive, isFocused, isHovered, isNotDisabled } from "./lib/pseudoClass.mjs";
2
+ import { focusOutline, focusWithinOutline } from "./mixins/focus.mjs";
3
+ import "./variables/transitions.mjs";
4
+ import { paragraphMixins } from "./mixins/text.mjs";
5
+ import { n as Stack, t as HStack } from "./Stack-Bl54WmhY.mjs";
6
+ import { TruncatedText } from "./lib/TruncatedText.mjs";
7
+ import { t as Card_default } from "./Card-BMCB9eFC.mjs";
8
+ import { t as Spacer_default } from "./Spacer-CJp0lwkL.mjs";
9
+ import { i as Paragraph, r as Label$1 } from "./Text-RcEfNFLx.mjs";
10
+ import { a as Tooltip } from "./Tooltip-C6AR1xT-.mjs";
11
+ import { useScrollOverflow } from "./lib/useScrollOverflow.mjs";
12
+ import { Z_INDICES } from "./lib/zindex.mjs";
13
+ import { n as Button, t as IconButton } from "./IconButton-CIWiEsS-.mjs";
14
+ import { c as MenuList, s as MenuItem } from "./Menu-CPYXo61N.mjs";
15
+ import { n as DropdownMenu_default } from "./DropdownMenu-DGYexb7s.mjs";
16
+ import { r as InputGroup } from "./Input-BFI_e7aU.mjs";
17
+ import Input_default from "./components/Input/index.mjs";
18
+ import { t as Combobox } from "./Combobox-BdqU5WLG.mjs";
19
+ import { s as Popover_default } from "./Popover-BkDpDdaO.mjs";
20
+ import { i as TabBar, n as StyledTab, r as Tab } from "./TabBar-zSA8kyE6.mjs";
21
+ import { t as Toggle } from "./Toggle-Bie9zCem.mjs";
22
+ import { t as ListBox } from "./ListBox-BwID8jpk.mjs";
23
+ import { a as ComboboxField, p as FormField } from "./FormField-PeYYRO4s.mjs";
24
+ import { n as DatePicker } from "./DatePicker-DY1YA_Fu.mjs";
25
+ import { BorderRadius, Color, Spacing, Typography } from "@persona/design-tokens";
26
+ import styled, { createGlobalStyle, css } from "styled-components";
27
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
28
+ import { Fragment as Fragment$1, createContext, createElement, forwardRef, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
29
+ import { CaretDownIcon, CheckIcon, CircleInfoIcon, CirclePlusIcon, CopyIcon, FilterIcon, MoreIcon, PlusIcon, RotateCcwIcon, SaveIcon, SearchIcon, SettingsIcon, TrashIcon, XIcon } from "@persona/icons";
30
+ import { CaretDownIcon as CaretDownIcon$1, CircleInfoIcon as CircleInfoIcon$1, LockedIcon as LockedIcon$1, MoreIcon as MoreIcon$1, PlusIcon as PlusIcon$1, SearchIcon as SearchIcon$1, XIcon as XIcon$1 } from "@persona/icons/12px";
31
+ import { debounce, union, uniqueId } from "lodash/fp.js";
32
+ import { useId } from "react-aria";
33
+ import { DragIcon as DragIcon$1 } from "@persona/icons/24px";
34
+ import { isEqual, noop, startCase, uniqueId as uniqueId$1 } from "lodash";
35
+ import Fuse from "fuse.js";
36
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
37
+ import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
38
+ import { parseDate } from "@internationalized/date";
39
+ import { v4 } from "uuid";
40
+ //#region components/DataTable/FormControlLabel/FormControlLabel.ts
41
+ const FormControlLabel = styled(Label$1).attrs(() => ({
42
+ size: "md",
43
+ weight: "bold"
44
+ }))`
45
+ margin-bottom: ${Spacing[2]};
46
+ transition: ${"200ms"};
47
+ display: inline-block;
48
+
49
+ ${({ theme, isDisabled }) => css`
50
+ color: ${isDisabled ? theme.color.text.disabled : theme.color.text.primary};
51
+ `}
52
+ `;
53
+ //#endregion
54
+ //#region components/DataTable/SearchInput/SearchInput.tsx
55
+ const SearchBar = styled.div``;
56
+ const StyledInput = styled(Input_default)`
57
+ ${({ theme, flattenDisplay }) => flattenDisplay && css`
58
+ border-width: 0px;
59
+
60
+ &${isActive}, &${isFocused}, &${isHovered}&${isNotDisabled}, &${isHovered}&${isFocused} {
61
+ border-color: ${theme.color.border.input};
62
+ box-shadow: none;
63
+ }
64
+ `}
65
+ `;
66
+ const SearchInput = ({ className, title = "Search", handleInput, handleOnFocus = noop, onBlur = noop, id, value, placeholder, dataTest, autoFocus, useClearIcon = false, disabled = false, disabledTooltip, size = "md", leftIcon = size === "sm" ? /* @__PURE__ */ jsx(SearchIcon$1, {}) : /* @__PURE__ */ jsx(SearchIcon, {}), flattenDisplay = false, maxLength }) => {
67
+ const [innerValue, setInnerValue] = useState(value);
68
+ const handleChange = useCallback(({ target }) => {
69
+ setInnerValue(target.value);
70
+ handleInput(target.value);
71
+ }, [handleInput, setInnerValue]);
72
+ useEffect(() => {
73
+ setInnerValue(value);
74
+ }, [value]);
75
+ const inputRef = useRef(null);
76
+ const handleClear = useCallback(() => {
77
+ setInnerValue("");
78
+ handleInput("");
79
+ handleOnFocus();
80
+ inputRef.current?.focus();
81
+ }, [
82
+ handleInput,
83
+ handleOnFocus,
84
+ inputRef,
85
+ setInnerValue
86
+ ]);
87
+ const searchBar = /* @__PURE__ */ jsxs(SearchBar, {
88
+ className,
89
+ "data-test": dataTest,
90
+ children: [title != null && /* @__PURE__ */ jsx(FormControlLabel, {
91
+ htmlFor: id,
92
+ children: title
93
+ }), /* @__PURE__ */ jsx(InputGroup, {
94
+ leftIcon,
95
+ onClear: useClearIcon && !!innerValue ? (e) => {
96
+ e.preventDefault();
97
+ e.stopPropagation();
98
+ handleClear();
99
+ } : void 0,
100
+ size,
101
+ children: /* @__PURE__ */ jsx(StyledInput, {
102
+ id,
103
+ onChange: handleChange,
104
+ placeholder,
105
+ value: innerValue,
106
+ autoFocus,
107
+ ref: inputRef,
108
+ onFocus: handleOnFocus,
109
+ onBlur,
110
+ disabled,
111
+ maxLength,
112
+ flattenDisplay
113
+ })
114
+ })]
115
+ });
116
+ return disabled && disabledTooltip ? /* @__PURE__ */ jsx(Tooltip, {
117
+ trigger: searchBar,
118
+ side: "top",
119
+ children: disabledTooltip
120
+ }) : searchBar;
121
+ };
122
+ //#endregion
123
+ //#region components/DataTable/TableControls/CompactBar.tsx
124
+ const DataTableCompactBar = styled(HStack)`
125
+ border-bottom: 1px solid ${({ theme }) => theme.color.border.secondary};
126
+ padding-bottom: ${Spacing[1]};
127
+ `;
128
+ const CompactSearchInput = styled(SearchInput)`
129
+ width: ${({ $autoExpand }) => $autoExpand ? "100%" : "240px"};
130
+ margin-right: ${Spacing[1]};
131
+ `;
132
+ /**
133
+ * Compact variant of the ControlBar.
134
+ * Not intended to be used by itself.
135
+ *
136
+ * Tested using the ControlBar specs.
137
+ *
138
+ * @see ControlBar.tsx
139
+ * @see ControlBar.spec.tsx
140
+ */
141
+ const CompactBar = ({ title, searchProps, showFilters, setShowFilters, filtersId, isLoading, propertiesButton, tableActions, "data-tour-target": dataTourTarget, filterPanel }) => {
142
+ const autoExpandSearch = !title;
143
+ const [showSearch, setShowSearch] = useState(autoExpandSearch);
144
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(DataTableCompactBar, {
145
+ "data-tour-target": dataTourTarget,
146
+ justify: "space-between",
147
+ align: "center",
148
+ children: [title && /* @__PURE__ */ jsx(Paragraph, {
149
+ size: "md",
150
+ weight: "bold",
151
+ color: "primary",
152
+ children: title
153
+ }), /* @__PURE__ */ jsxs(HStack, {
154
+ spacing: Spacing[1],
155
+ align: "center",
156
+ justify: "right",
157
+ style: autoExpandSearch ? { width: "100%" } : { marginLeft: "auto" },
158
+ children: [/* @__PURE__ */ jsxs(HStack, {
159
+ spacing: Spacing[1],
160
+ align: "center",
161
+ style: { width: "100%" },
162
+ children: [
163
+ searchProps && (showSearch ? /* @__PURE__ */ jsx(CompactSearchInput, {
164
+ title: null,
165
+ size: "sm",
166
+ $autoExpand: autoExpandSearch,
167
+ autoFocus: !autoExpandSearch,
168
+ onBlur: autoExpandSearch ? void 0 : () => {
169
+ if (!searchProps.value) setShowSearch(false);
170
+ },
171
+ useClearIcon: true,
172
+ ...searchProps
173
+ }) : /* @__PURE__ */ jsx(Button, {
174
+ id: "table-controls__compact-search-toggle",
175
+ variant: "text",
176
+ width: "icon",
177
+ size: "sm",
178
+ "aria-label": "Show search bar",
179
+ onClick: () => setShowSearch(true),
180
+ children: /* @__PURE__ */ jsx(SearchIcon, {})
181
+ })),
182
+ setShowFilters && /* @__PURE__ */ jsx(Button, {
183
+ id: "table-controls__view-tab-filters",
184
+ variant: "text",
185
+ onClick: () => setShowFilters?.(!showFilters),
186
+ "aria-label": showFilters ? "Hide filters" : "Show filters",
187
+ "aria-expanded": showFilters,
188
+ "aria-controls": filtersId,
189
+ disabled: isLoading,
190
+ active: showFilters,
191
+ width: "icon",
192
+ size: "sm",
193
+ children: /* @__PURE__ */ jsx(FilterIcon, {})
194
+ }),
195
+ propertiesButton
196
+ ]
197
+ }), tableActions && Array.isArray(tableActions) ? tableActions.map((action) => /* @__PURE__ */ jsx(Button, {
198
+ id: `table-controls__compact-action-${action.label.toLowerCase().replace(/\s+/g, "-")}`,
199
+ variant: "basic",
200
+ size: "sm",
201
+ width: "auto",
202
+ onClick: action.onClick,
203
+ children: action.label
204
+ }, action.label)) : tableActions]
205
+ })]
206
+ }), showFilters && filterPanel] });
207
+ };
208
+ //#endregion
209
+ //#region components/DataTable/TableControls/utils/positioning.ts
210
+ /**
211
+ * Check if a child rect is contained within a parent rect.
212
+ * @param parent - The parent rect.
213
+ * @param child - The child rect.
214
+ * @returns True if the child rect is contained within the parent rect, false otherwise.
215
+ */
216
+ const rectContainsRect = (parent, child) => {
217
+ return child.top >= parent.top && child.bottom <= parent.bottom && child.left >= parent.left && child.right <= parent.right;
218
+ };
219
+ //#endregion
220
+ //#region components/DataTable/TableControls/ControlBar.tsx
221
+ const TAB_ID_PREFIX = "table-controls__view-tab_";
222
+ const OVERFLOW_TAB_ID_PREFIX = "table-controls__view-tab-overflow_";
223
+ function enterProxiesClick(e) {
224
+ if (e.key === "Enter") e.target.dispatchEvent(new Event("click", { bubbles: true }));
225
+ }
226
+ const AddViewButton = styled(IconButton)`
227
+ color: ${({ theme }) => theme.color.text.secondary};
228
+ `;
229
+ const LockedTab = styled(Tab)`
230
+ svg {
231
+ height: 12px;
232
+ width: 12px;
233
+ }
234
+ `;
235
+ const OverflowMenuList = styled(MenuList)`
236
+ max-height: 300px;
237
+ overflow: auto;
238
+ `;
239
+ const ExpandedSearchInput = styled(SearchInput)`
240
+ flex-basis: 440px;
241
+ flex-grow: 1;
242
+ `;
243
+ const ViewsBar = styled(TabBar)`
244
+ ${AddViewButton} {
245
+ /* Shows button when view is in progress of being added */
246
+ opacity: ${({ $isAddingView }) => $isAddingView ? 1 : 0};
247
+ }
248
+
249
+ &:hover,
250
+ &:hover:focus,
251
+ &:focus-within {
252
+ ${AddViewButton} {
253
+ opacity: 1;
254
+ }
255
+ }
256
+ `;
257
+ const TabOverflowContainer = styled.div`
258
+ display: flex;
259
+ align-items: center;
260
+ gap: ${Spacing[2]};
261
+ position: absolute;
262
+ height: 32px;
263
+ `;
264
+ const SavedViewTab = ({ view, selected, tabIdPrefix = TAB_ID_PREFIX, canEditViews, handleNameChange, onDuplicateView, onDeleteView, onSelectView, onResetCurrentView, onSaveView, isViewDirty, showTabContextMenu, setShowTabContextMenu, className, ...rest }) => {
265
+ const inputRef = useRef(null);
266
+ const tab = /* @__PURE__ */ jsx(StyledTab, {
267
+ id: `${tabIdPrefix}${view.id}`,
268
+ selected,
269
+ "aria-selected": selected,
270
+ role: "tab",
271
+ onClick: !selected ? () => onSelectView?.(view.id) : void 0,
272
+ suffixIcon: selected && canEditViews ? /* @__PURE__ */ jsx(MoreIcon, {}) : void 0,
273
+ className,
274
+ ...rest,
275
+ children: view.name
276
+ });
277
+ if (canEditViews && selected) return /* @__PURE__ */ jsx(Popover_default, {
278
+ trigger: tab,
279
+ open: showTabContextMenu,
280
+ onOpenChange: (open) => {
281
+ if (selected) setShowTabContextMenu(open);
282
+ if (!open && inputRef.current) handleNameChange?.(view, inputRef.current.value);
283
+ },
284
+ contentProps: {
285
+ align: "start",
286
+ padding: Spacing[2]
287
+ },
288
+ children: /* @__PURE__ */ jsxs(Stack, {
289
+ spacing: Spacing[3],
290
+ children: [/* @__PURE__ */ jsx(Input_default, {
291
+ defaultValue: view.name,
292
+ onBlur: (e) => handleNameChange?.(view, e.currentTarget.value),
293
+ onKeyDown: (e) => {
294
+ if (e.key === "Enter") handleNameChange?.(view, e.currentTarget.value);
295
+ },
296
+ disabled: !handleNameChange,
297
+ ref: inputRef
298
+ }), /* @__PURE__ */ jsxs(MenuList, {
299
+ padding: Spacing[0],
300
+ children: [
301
+ onDuplicateView && /* @__PURE__ */ jsx(MenuItem, {
302
+ id: "table-controls__view__menu-duplicate",
303
+ prefixIcon: /* @__PURE__ */ jsx(CopyIcon, {}),
304
+ onClick: async () => {
305
+ const newTableView = await onDuplicateView(view.id);
306
+ if (newTableView) {
307
+ const { id } = newTableView;
308
+ if (view.id !== id) {
309
+ onSelectView?.(id);
310
+ setShowTabContextMenu(true);
311
+ }
312
+ }
313
+ },
314
+ onKeyDown: enterProxiesClick,
315
+ children: "Duplicate"
316
+ }),
317
+ canEditViews && onResetCurrentView && /* @__PURE__ */ jsx(MenuItem, {
318
+ id: "table-controls__view__menu-reset",
319
+ prefixIcon: /* @__PURE__ */ jsx(RotateCcwIcon, {}),
320
+ onClick: onResetCurrentView,
321
+ onKeyDown: enterProxiesClick,
322
+ children: "Reset"
323
+ }),
324
+ canEditViews && onSaveView && /* @__PURE__ */ jsx(MenuItem, {
325
+ id: "table-controls__view__menu-save",
326
+ prefixIcon: /* @__PURE__ */ jsx(SaveIcon, {}),
327
+ disabled: !isViewDirty,
328
+ onClick: () => {
329
+ onSaveView();
330
+ setShowTabContextMenu(false);
331
+ },
332
+ onKeyDown: enterProxiesClick,
333
+ children: "Save"
334
+ }),
335
+ onDeleteView && /* @__PURE__ */ jsx(MenuItem, {
336
+ id: "table-controls__view__menu-delete",
337
+ prefixIcon: /* @__PURE__ */ jsx(TrashIcon, {}),
338
+ onClick: async () => {
339
+ await onDeleteView(view.id);
340
+ setShowTabContextMenu(false);
341
+ },
342
+ onKeyDown: enterProxiesClick,
343
+ children: "Delete"
344
+ })
345
+ ]
346
+ })]
347
+ })
348
+ });
349
+ return tab;
350
+ };
351
+ /**
352
+ * A tab that is locked and does not support editing or actions.
353
+ */
354
+ const LockedViewTab = ({ id, selected, onClick, children, ...props }) => {
355
+ return /* @__PURE__ */ jsx(LockedTab, {
356
+ id,
357
+ selected,
358
+ onClick: selected ? void 0 : onClick,
359
+ suffixIcon: /* @__PURE__ */ jsx(LockedIcon$1, {}),
360
+ ...props,
361
+ children
362
+ });
363
+ };
364
+ const OverflowSavedViewTab = styled(SavedViewTab)`
365
+ margin-left: ${Spacing[2]};
366
+ `;
367
+ const TabOverflow = forwardRef(function TabOverflow({ hiddenViews, currentView: currentViewId, handleAddView, onSelectView, canEditViews, lastVisibleViewElement, ...rest }, ref) {
368
+ const [filter, setFilter] = useState("");
369
+ const [openPopover, setOpenPopover] = useState(false);
370
+ const currentView = useMemo(() => {
371
+ return hiddenViews.find((view) => view.id === currentViewId);
372
+ }, [currentViewId, hiddenViews]);
373
+ const filteredViews = useMemo(() => hiddenViews.filter((view) => view.name.toLowerCase().includes(filter.toLowerCase()) && view.id !== currentView?.id), [
374
+ hiddenViews,
375
+ filter,
376
+ currentView
377
+ ]);
378
+ return /* @__PURE__ */ jsxs(TabOverflowContainer, {
379
+ ref,
380
+ style: useMemo(() => {
381
+ if (!lastVisibleViewElement) return;
382
+ return { left: lastVisibleViewElement.offsetLeft + lastVisibleViewElement.offsetWidth + 8 };
383
+ }, [lastVisibleViewElement]),
384
+ children: [
385
+ currentView && /* @__PURE__ */ jsx(OverflowSavedViewTab, {
386
+ view: currentView,
387
+ canEditViews,
388
+ selected: true,
389
+ tabIdPrefix: OVERFLOW_TAB_ID_PREFIX,
390
+ ...rest
391
+ }),
392
+ hiddenViews.length === 1 && currentView && hiddenViews[0].id !== currentView.id ? null : /* @__PURE__ */ jsxs(Popover_default, {
393
+ trigger: /* @__PURE__ */ jsxs(Button, {
394
+ variant: "basic",
395
+ size: "sm",
396
+ width: "auto",
397
+ children: [currentView ? hiddenViews.length - 1 : hiddenViews.length, " more…"]
398
+ }),
399
+ contentProps: {
400
+ align: "start",
401
+ padding: Spacing[2]
402
+ },
403
+ open: openPopover,
404
+ onOpenChange: (open) => {
405
+ if (!open) setFilter("");
406
+ setOpenPopover(open);
407
+ },
408
+ children: [/* @__PURE__ */ jsx(Input_default, {
409
+ value: filter,
410
+ onChange: (e) => setFilter(e.target.value),
411
+ placeholder: "Search for a view..."
412
+ }), /* @__PURE__ */ jsx(OverflowMenuList, {
413
+ padding: Spacing[0],
414
+ children: filteredViews.map((view) => {
415
+ return /* @__PURE__ */ jsx(MenuItem, {
416
+ id: `${OVERFLOW_TAB_ID_PREFIX}${view.id}`,
417
+ onClick: () => {
418
+ onSelectView?.(view.id);
419
+ setOpenPopover(false);
420
+ },
421
+ onKeyDown: enterProxiesClick,
422
+ children: view.name
423
+ }, view.id);
424
+ })
425
+ })]
426
+ }),
427
+ canEditViews && handleAddView && /* @__PURE__ */ jsx(AddViewButton, {
428
+ id: `${OVERFLOW_TAB_ID_PREFIX}overflow-new`,
429
+ onClick: handleAddView,
430
+ size: "md",
431
+ "aria-label": "Add new view",
432
+ children: /* @__PURE__ */ jsx(CirclePlusIcon, {})
433
+ })
434
+ ]
435
+ });
436
+ });
437
+ /**
438
+ * Force the add button to be visible when the product tour is active
439
+ */
440
+ const ProductTourStyles = createGlobalStyle`
441
+ body:has(#react-joyride-portal) {
442
+ [data-tour-target='saved-views-add-button'] {
443
+ opacity: 1;
444
+ }
445
+ }
446
+ `;
447
+ const ControlBar = ({ presetViews, currentView, onSelectView, views, onAddView, onDuplicateView, onDeleteView, onViewNameChange, onSaveView, isViewDirty, canEditViews, showFilters, setShowFilters, searchProps, filtersId, propertiesButton, tableActions, isLoading, showViews, selectedRows = [], bulkActions, onResetCurrentView, onClearSelection, title, "data-tour-target": dataTourTarget, compact, onError, filterPanel }) => {
448
+ const tabListRef = useRef(null);
449
+ const tabOverflowRef = useRef(null);
450
+ const [hiddenViews, setHiddenViews] = useState([]);
451
+ const [showTabContextMenu, setShowTabContextMenu] = useState(false);
452
+ const [isAddingView, setIsAddingView] = useState(false);
453
+ const [lastVisibleViewElement, setLastVisibleViewElement] = useState(null);
454
+ const [tabOverflowWidth, setTabOverflowWidth] = useState(null);
455
+ const onResize = useCallback(() => {
456
+ if (!tabListRef.current) return;
457
+ const containerRect = tabListRef.current.getBoundingClientRect();
458
+ const tabListContainer = tabListRef.current;
459
+ const tabElements = Array.from(tabListContainer.querySelectorAll("[data-tab-view]"));
460
+ if (tabElements.length === 0 || rectContainsRect(containerRect, tabElements[tabElements.length - 1].getBoundingClientRect())) {
461
+ setHiddenViews([]);
462
+ return;
463
+ }
464
+ const firstHiddenIndex = tabElements.findIndex((el) => !rectContainsRect(containerRect, el.getBoundingClientRect()));
465
+ if (firstHiddenIndex === -1) setLastVisibleViewElement(null);
466
+ else {
467
+ const lastVisibleViewElement = tabElements[firstHiddenIndex - 1];
468
+ if (lastVisibleViewElement) setLastVisibleViewElement(lastVisibleViewElement);
469
+ }
470
+ setHiddenViews((firstHiddenIndex === -1 ? [] : views?.slice(firstHiddenIndex)) || []);
471
+ const tabOverflowWidth = tabOverflowRef.current?.getBoundingClientRect().width;
472
+ if (tabOverflowWidth) setTabOverflowWidth(tabOverflowWidth);
473
+ }, [setHiddenViews, views]);
474
+ useLayoutEffect(() => {
475
+ if (!showViews || !tabListRef.current) return;
476
+ const resizeObserver = new ResizeObserver(() => {
477
+ onResize();
478
+ });
479
+ resizeObserver.observe(tabListRef.current);
480
+ return () => {
481
+ resizeObserver.disconnect();
482
+ };
483
+ }, [onResize, showViews]);
484
+ useLayoutEffect(() => {
485
+ if (showViews) onResize();
486
+ }, [
487
+ onResize,
488
+ showViews,
489
+ views
490
+ ]);
491
+ const currentViewHidden = useMemo(() => {
492
+ if (currentView) return !!hiddenViews.find((view) => view.id === currentView);
493
+ return false;
494
+ }, [currentView, hiddenViews]);
495
+ const handleAddView = async () => {
496
+ try {
497
+ setIsAddingView(true);
498
+ if (onAddView) {
499
+ const view = await onAddView();
500
+ if (!view || !view.id) return;
501
+ if (currentView !== view.id) onSelectView?.(view.id);
502
+ setShowTabContextMenu(true);
503
+ }
504
+ } catch {
505
+ onError?.(/* @__PURE__ */ new Error("Error adding view"));
506
+ } finally {
507
+ setIsAddingView(false);
508
+ }
509
+ };
510
+ const handleNameChange = (view, newName) => {
511
+ if (canEditViews && view.name !== newName) onViewNameChange?.(view.id, newName);
512
+ };
513
+ if (compact) return /* @__PURE__ */ jsx(CompactBar, {
514
+ "data-tour-target": dataTourTarget,
515
+ title,
516
+ searchProps,
517
+ showFilters,
518
+ setShowFilters,
519
+ filtersId,
520
+ isLoading,
521
+ propertiesButton,
522
+ tableActions,
523
+ filterPanel
524
+ });
525
+ const bulkActionButtons = bulkActions?.map((action, index) => {
526
+ const key = "label" in action ? action.label : `action-${index}`;
527
+ const isDisabled = selectedRows.length === 0 || action.disabled === true;
528
+ const selectedCount = selectedRows.length;
529
+ const clearSelection = () => {
530
+ onClearSelection?.();
531
+ };
532
+ if ("icon" in action && "aria-label" in action) return /* @__PURE__ */ jsx(IconButton, {
533
+ size: "sm",
534
+ "aria-label": action["aria-label"],
535
+ onClick: async () => {
536
+ await action.onClick(selectedRows, clearSelection);
537
+ },
538
+ disabled: isDisabled,
539
+ children: action.icon
540
+ }, key);
541
+ const displayLabel = "label" in action && selectedCount > 0 ? `${action.label} (${selectedCount})` : "label" in action ? action.label : "";
542
+ return /* @__PURE__ */ jsx(Button, {
543
+ id: `table-controls__view-tab-bulk-action-${index}`,
544
+ variant: "basic",
545
+ size: "sm",
546
+ width: "auto",
547
+ onClick: async () => {
548
+ await action.onClick(selectedRows, clearSelection);
549
+ },
550
+ disabled: isDisabled,
551
+ children: displayLabel
552
+ }, key);
553
+ });
554
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
555
+ /* @__PURE__ */ jsx(ProductTourStyles, {}),
556
+ (title || showViews || canEditViews && onSaveView || tableActions || bulkActions) && /* @__PURE__ */ jsx(ViewsBar, {
557
+ ref: tabListRef,
558
+ title,
559
+ maxTabChars: 25,
560
+ $isAddingView: isAddingView,
561
+ "data-tour-target": dataTourTarget,
562
+ actions: /* @__PURE__ */ jsxs(HStack, {
563
+ spacing: Spacing[3],
564
+ align: "center",
565
+ style: tabOverflowWidth ? { paddingLeft: `${tabOverflowWidth + 16}px` } : void 0,
566
+ children: [
567
+ canEditViews && onSaveView && /* @__PURE__ */ jsx(Button, {
568
+ id: "table-controls__view-tab-save",
569
+ onClick: onSaveView,
570
+ "aria-label": "Save current view",
571
+ disabled: !isViewDirty || isLoading,
572
+ size: "sm",
573
+ variant: "basic",
574
+ width: "auto",
575
+ "data-tour-target": "saved-views-save-button",
576
+ children: "Save view"
577
+ }),
578
+ bulkActionButtons,
579
+ tableActions
580
+ ]
581
+ }),
582
+ children: showViews && /* @__PURE__ */ jsxs(Fragment, { children: [
583
+ /* @__PURE__ */ jsx(LockedViewTab, {
584
+ id: `${TAB_ID_PREFIX}default`,
585
+ selected: !currentView,
586
+ onClick: () => onSelectView?.(null),
587
+ "data-tour-target": "saved-views-default-view",
588
+ children: "Default view"
589
+ }),
590
+ presetViews?.map((view) => {
591
+ const selected = view.id === currentView;
592
+ return /* @__PURE__ */ jsx(LockedViewTab, {
593
+ id: `${TAB_ID_PREFIX}preset-${view.id}`,
594
+ selected,
595
+ onClick: () => onSelectView?.(view.id),
596
+ children: view.name
597
+ }, view.id);
598
+ }),
599
+ views?.map((view) => {
600
+ return /* @__PURE__ */ jsx(SavedViewTab, {
601
+ view,
602
+ canEditViews: canEditViews ?? false,
603
+ handleNameChange,
604
+ onDuplicateView,
605
+ onDeleteView,
606
+ onSelectView,
607
+ onResetCurrentView,
608
+ onSaveView,
609
+ isViewDirty: isViewDirty ?? false,
610
+ selected: view.id === currentView,
611
+ showTabContextMenu: showTabContextMenu && !currentViewHidden,
612
+ setShowTabContextMenu,
613
+ "data-tab-view": true
614
+ }, view.id);
615
+ }),
616
+ canEditViews && onAddView && /* @__PURE__ */ jsx(AddViewButton, {
617
+ id: "table-controls__view-tab-new",
618
+ size: "md",
619
+ onClick: handleAddView,
620
+ "aria-label": "Add new view",
621
+ "data-tour-target": "saved-views-add-button",
622
+ children: /* @__PURE__ */ jsx(CirclePlusIcon, {})
623
+ }),
624
+ hiddenViews.length > 0 && /* @__PURE__ */ jsx(TabOverflow, {
625
+ ref: tabOverflowRef,
626
+ hiddenViews,
627
+ currentView,
628
+ onSelectView,
629
+ canEditViews: canEditViews ?? false,
630
+ handleAddView: onAddView ? handleAddView : null,
631
+ handleNameChange,
632
+ onDuplicateView,
633
+ onDeleteView,
634
+ onResetCurrentView,
635
+ onSaveView,
636
+ isViewDirty: isViewDirty ?? false,
637
+ showTabContextMenu: showTabContextMenu && currentViewHidden,
638
+ setShowTabContextMenu,
639
+ lastVisibleViewElement
640
+ })
641
+ ] })
642
+ }),
643
+ /* @__PURE__ */ jsxs(HStack, {
644
+ align: "center",
645
+ spacing: Spacing[2],
646
+ justify: "right",
647
+ children: [
648
+ searchProps && /* @__PURE__ */ jsx(ExpandedSearchInput, {
649
+ title: null,
650
+ useClearIcon: true,
651
+ ...searchProps,
652
+ size: "md"
653
+ }),
654
+ setShowFilters && /* @__PURE__ */ jsx(Button, {
655
+ id: "table-controls__view-tab-filters",
656
+ variant: "basic",
657
+ onClick: () => setShowFilters?.(!showFilters),
658
+ "aria-label": showFilters ? "Hide filters" : "Show filters",
659
+ "aria-expanded": showFilters,
660
+ "aria-controls": filtersId,
661
+ disabled: isLoading,
662
+ active: showFilters,
663
+ width: "icon",
664
+ size: "md",
665
+ "data-tour-target": "table-filters-toggle-button",
666
+ children: /* @__PURE__ */ jsx(FilterIcon, {})
667
+ }),
668
+ propertiesButton
669
+ ]
670
+ }),
671
+ showFilters && filterPanel
672
+ ] });
673
+ };
674
+ //#endregion
675
+ //#region components/DataTable/TableControls/TableControls.tsx
676
+ const TableControls = ({ filterPanel, searchProps, defaultShowFilters, showFilters: controlledShowFilters, setShowFilters: controlledSetShowFilters, className, tableActions, propertiesButton, isLoading, showViews, canEditViews, onSelectView, views, currentView, onAddView, onViewNameChange, onDuplicateView, onDeleteView, onSaveView, isViewDirty, selectedRows, bulkActions, onClearSelection, title, presetViews, compact, columnConfigurationProps, showFiltersAlways = false, onError, "data-tour-target": dataTourTarget }) => {
677
+ const filtersId = useId();
678
+ const [internalShowFilters, internalSetShowFilters] = useState(defaultShowFilters ?? false);
679
+ const showFilters = controlledShowFilters != null ? controlledShowFilters : internalShowFilters;
680
+ const setShowFilters = controlledSetShowFilters != null ? controlledSetShowFilters : internalSetShowFilters;
681
+ const enhancedPropertiesButton = useMemo(() => {
682
+ if (!columnConfigurationProps && !propertiesButton) return;
683
+ const elements = [];
684
+ if (propertiesButton) elements.push(propertiesButton);
685
+ if (columnConfigurationProps) elements.push(/* @__PURE__ */ jsx(TableViewConfigurationDropdown, {
686
+ disabled: false,
687
+ ...columnConfigurationProps
688
+ }, "column-config"));
689
+ if (elements.length === 1) return elements[0];
690
+ return /* @__PURE__ */ jsx(StyledEnhancedPropertiesButton, { children: elements });
691
+ }, [columnConfigurationProps, propertiesButton]);
692
+ return /* @__PURE__ */ jsx(Container, {
693
+ className,
694
+ children: /* @__PURE__ */ jsx(ControlBar, {
695
+ showViews: compact ? false : showViews,
696
+ views: compact ? void 0 : views,
697
+ onSelectView: compact ? void 0 : onSelectView,
698
+ currentView: compact ? void 0 : currentView,
699
+ onAddView: compact ? void 0 : onAddView,
700
+ onDeleteView: compact ? void 0 : onDeleteView,
701
+ onDuplicateView: compact ? void 0 : onDuplicateView,
702
+ onViewNameChange: compact ? void 0 : onViewNameChange,
703
+ onSaveView: compact ? void 0 : onSaveView,
704
+ isViewDirty,
705
+ canEditViews: compact ? false : canEditViews,
706
+ showFilters,
707
+ setShowFilters: filterPanel != null && !showFiltersAlways ? setShowFilters : void 0,
708
+ filtersId,
709
+ searchProps,
710
+ propertiesButton: enhancedPropertiesButton,
711
+ tableActions,
712
+ isLoading,
713
+ selectedRows,
714
+ bulkActions,
715
+ onClearSelection,
716
+ title,
717
+ "data-tour-target": dataTourTarget,
718
+ presetViews: compact ? void 0 : presetViews,
719
+ compact,
720
+ onError,
721
+ filterPanel
722
+ })
723
+ });
724
+ };
725
+ const Container = styled(Stack)`
726
+ margin-bottom: ${Spacing[2]};
727
+ `;
728
+ const StyledEnhancedPropertiesButton = styled.div`
729
+ display: flex;
730
+ gap: ${Spacing[1]};
731
+ `;
732
+ //#endregion
733
+ //#region components/DataTable/dnd/StyledIconDrag.tsx
734
+ const StyledIconDrag = styled(DragIcon$1)`
735
+ display: ${({ $shouldHide = false }) => $shouldHide ? "none" : "inline"};
736
+
737
+ ${({ $horizontal = false }) => $horizontal ? css`
738
+ transform: rotate(90deg);
739
+ ` : ""}
740
+
741
+ ${({ $active = false, $hover = false }) => $active ? css`
742
+ cursor: grabbing;
743
+ opacity: 1;
744
+ ` : $hover ? css`
745
+ cursor: grab;
746
+ opacity: 1;
747
+ ` : css`
748
+ cursor: normal;
749
+ opacity: 0.4;
750
+ `}
751
+
752
+ transition: opacity 0.2s ease-in-out;
753
+
754
+ path {
755
+ stroke: ${Color.CoreSlate1000};
756
+ stroke-width: 1px;
757
+ }
758
+ `;
759
+ //#endregion
760
+ //#region components/DataTable/dnd/utils.ts
761
+ /**
762
+ * reorder returns a reordered version of the inputed list by swapping the element
763
+ * at startIndex with the one at endIndex
764
+ */
765
+ function reorder(list, startIndex, endIndex) {
766
+ const result = Array.from(list);
767
+ const [removed] = result.splice(startIndex, 1);
768
+ result.splice(endIndex, 0, removed);
769
+ return result;
770
+ }
771
+ //#endregion
772
+ //#region components/DataTable/TableControls/TableViewConfigurationDropdown.tsx
773
+ const DndSection = styled("div")`
774
+ max-height: 400px;
775
+
776
+ overflow: scroll;
777
+ ::-webkit-scrollbar {
778
+ display: none;
779
+ }
780
+ `;
781
+ const DndItemWrapper = styled("div")`
782
+ background: white;
783
+ width: 100%;
784
+ border-bottom: 1px solid ${({ theme }) => theme.color.border.secondary};
785
+ padding: ${Spacing[2]} ${Spacing[2]};
786
+
787
+ display: flex;
788
+ flex-direction: row;
789
+ align-items: center;
790
+ justify-content: left;
791
+ `;
792
+ const SuffixContainer = styled("div")`
793
+ padding-left: ${Spacing[2]};
794
+ margin-left: auto;
795
+ align-self: center;
796
+ `;
797
+ const SearchContainer = styled.div`
798
+ display: flex;
799
+ `;
800
+ const StyledSearchInput = styled(SearchInput)`
801
+ width: 100%;
802
+ `;
803
+ const PopoverCard$1 = styled(Card_default)`
804
+ width: 300px;
805
+ padding: ${Spacing[4]};
806
+ `;
807
+ const TriggerIconButton = forwardRef(function TriggerIconButton({ disabled, ...elemProps }, ref) {
808
+ return /* @__PURE__ */ jsx(Button, {
809
+ disabled,
810
+ width: "icon",
811
+ variant: "basic",
812
+ size: "md",
813
+ ...elemProps,
814
+ ref,
815
+ "data-tour-target": "table-properties-button",
816
+ "aria-label": "Table Properties",
817
+ children: /* @__PURE__ */ jsx(SettingsIcon, {})
818
+ });
819
+ });
820
+ const TooltipButtonWrapper = styled("div")`
821
+ display: inline-block;
822
+ `;
823
+ const TableViewConfigurationDropdown = ({ disabled = false, disabledTooltipMessage = "Your role does not have permission to configure the view.", size = "md", variant = "basic", ...props }) => {
824
+ return disabled ? /* @__PURE__ */ jsx(Tooltip, {
825
+ trigger: /* @__PURE__ */ jsx(TooltipButtonWrapper, { children: /* @__PURE__ */ jsx(TriggerIconButton, {
826
+ disabled: true,
827
+ size,
828
+ variant
829
+ }) }),
830
+ children: disabledTooltipMessage
831
+ }) : /* @__PURE__ */ jsxs(Popover_default, { children: [/* @__PURE__ */ jsx(Popover_default.Trigger, {
832
+ asChild: true,
833
+ children: /* @__PURE__ */ jsx(TriggerIconButton, {
834
+ disabled: false,
835
+ size,
836
+ variant
837
+ })
838
+ }), /* @__PURE__ */ jsx(Popover_default.Content, {
839
+ style: { zIndex: Z_INDICES.dropdown },
840
+ sideOffset: 8,
841
+ side: "bottom",
842
+ align: "end",
843
+ children: /* @__PURE__ */ jsx(PopoverCard$1, {
844
+ elevated: true,
845
+ children: /* @__PURE__ */ jsx(TableViewConfiguration, { ...props })
846
+ })
847
+ })] });
848
+ };
849
+ const TableViewConfiguration = ({ columnConfiguration, attributeOptions, updateColumnConfiguration, getColumnDisabled }) => {
850
+ const [searchTerm, setSearchTerm] = useState("");
851
+ const fuse = useMemo(() => {
852
+ return new Fuse(attributeOptions, {
853
+ shouldSort: false,
854
+ threshold: .4,
855
+ location: 0,
856
+ distance: 100,
857
+ minMatchCharLength: 1,
858
+ keys: [{
859
+ name: "label",
860
+ weight: 1
861
+ }]
862
+ });
863
+ }, [attributeOptions]);
864
+ const allOptions = useMemo(() => union(attributeOptions, columnConfiguration), [attributeOptions, columnConfiguration]);
865
+ const filteredSearchOptions = searchTerm === "" ? allOptions : fuse.search(searchTerm).map(({ item }) => item);
866
+ const hiddenAttributes = useMemo(() => {
867
+ return filteredSearchOptions.filter((attribute) => {
868
+ return !columnConfiguration.map((c) => c.key).includes(attribute.key);
869
+ });
870
+ }, [columnConfiguration, filteredSearchOptions]);
871
+ const filteredShownAttributes = useMemo(() => {
872
+ return columnConfiguration.filter((column) => filteredSearchOptions.map((o) => o.key).includes(column.key));
873
+ }, [columnConfiguration, filteredSearchOptions]);
874
+ const handleDragEnd = (result, _provided) => {
875
+ const { destination, source } = result;
876
+ if (!destination || destination.droppableId === source.droppableId && destination.index === source.index) return;
877
+ updateColumnConfiguration(reorder(columnConfiguration, source.index, destination.index));
878
+ };
879
+ const generateShownAttributesToggle = (column) => () => {
880
+ updateColumnConfiguration(columnConfiguration.filter((a) => a.key !== column.key));
881
+ };
882
+ const generateHiddenAttributesToggle = (column) => () => {
883
+ updateColumnConfiguration(columnConfiguration.concat(column));
884
+ };
885
+ const shownColumnIds = useMemo(() => {
886
+ return columnConfiguration.map((c) => c.key);
887
+ }, [columnConfiguration]);
888
+ const shownDndItemProps = filteredShownAttributes.map((column, index) => {
889
+ const isDisabledByDefault = columnConfiguration.length === 1;
890
+ const isDisabledByCustom = getColumnDisabled?.(column.key, shownColumnIds) ?? false;
891
+ const shouldDisableDragForColumn = isDisabledByCustom && index === filteredShownAttributes.length - 1;
892
+ return {
893
+ column,
894
+ index,
895
+ isDisabled: isDisabledByDefault || isDisabledByCustom,
896
+ isToggled: true,
897
+ shouldDisableDrag: shouldDisableDragForColumn,
898
+ handleToggle: generateShownAttributesToggle(column)
899
+ };
900
+ });
901
+ const hiddenDndItemProps = hiddenAttributes.map((column, index) => {
902
+ return {
903
+ column,
904
+ index,
905
+ isToggled: false,
906
+ shouldDisableDrag: true,
907
+ handleToggle: generateHiddenAttributesToggle(column)
908
+ };
909
+ });
910
+ return /* @__PURE__ */ jsxs("div", { children: [
911
+ /* @__PURE__ */ jsx(Label$1, {
912
+ size: "lg",
913
+ weight: "bold",
914
+ children: "Configure columns"
915
+ }),
916
+ /* @__PURE__ */ jsx(Spacer_default, { height: 2 }),
917
+ /* @__PURE__ */ jsx(SearchContainer, { children: /* @__PURE__ */ jsx(StyledSearchInput, {
918
+ title: null,
919
+ value: searchTerm,
920
+ handleInput: setSearchTerm,
921
+ size: "md",
922
+ placeholder: "Search by item...",
923
+ dataTest: "checklist-item-panel-item-table__search"
924
+ }) }),
925
+ /* @__PURE__ */ jsx(Spacer_default, { height: 2 }),
926
+ shownDndItemProps.length > 0 || hiddenDndItemProps.length > 0 ? /* @__PURE__ */ jsxs(DndSection, { children: [
927
+ shownDndItemProps.length > 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Paragraph, { children: "Shown attributes" }), /* @__PURE__ */ jsx(DragDropContext, {
928
+ onDragEnd: handleDragEnd,
929
+ children: /* @__PURE__ */ jsx(Droppable, {
930
+ droppableId: "cases-view__configure-shown-columns",
931
+ renderClone: (provided, _snapshot, rubric) => {
932
+ return /* @__PURE__ */ jsx("div", {
933
+ ...provided.draggableProps,
934
+ ...provided.dragHandleProps,
935
+ ref: provided.innerRef,
936
+ children: /* @__PURE__ */ jsx(AttributeDnd, { ...shownDndItemProps[rubric.source.index] })
937
+ });
938
+ },
939
+ children: (provided) => {
940
+ return /* @__PURE__ */ jsxs("div", {
941
+ ref: provided.innerRef,
942
+ ...provided.droppableProps,
943
+ children: [shownDndItemProps.map((props, idx) => {
944
+ return /* @__PURE__ */ jsx(Draggable, {
945
+ draggableId: props.column.key,
946
+ index: idx,
947
+ isDragDisabled: props.shouldDisableDrag,
948
+ children: (provided) => {
949
+ return /* @__PURE__ */ jsx("div", {
950
+ ref: provided.innerRef,
951
+ ...provided.draggableProps,
952
+ ...provided.dragHandleProps,
953
+ children: /* @__PURE__ */ jsx(AttributeDnd, { ...props })
954
+ });
955
+ }
956
+ }, `${props.column.key}`);
957
+ }), provided.placeholder]
958
+ });
959
+ }
960
+ })
961
+ })] }),
962
+ /* @__PURE__ */ jsx(Spacer_default, { height: 2 }),
963
+ hiddenDndItemProps.length > 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Paragraph, { children: "Hidden attributes" }), /* @__PURE__ */ jsx(DragDropContext, {
964
+ onDragEnd: handleDragEnd,
965
+ children: /* @__PURE__ */ jsx(Droppable, {
966
+ droppableId: "cases-view__configure-hidden-columns",
967
+ renderClone: (provided, _snapshot, rubric) => {
968
+ return /* @__PURE__ */ jsx("div", {
969
+ ...provided.draggableProps,
970
+ ...provided.dragHandleProps,
971
+ ref: provided.innerRef,
972
+ children: /* @__PURE__ */ jsx(AttributeDnd, { ...hiddenDndItemProps[rubric.source.index] })
973
+ });
974
+ },
975
+ children: (provided) => {
976
+ return /* @__PURE__ */ jsxs("div", {
977
+ ref: provided.innerRef,
978
+ ...provided.droppableProps,
979
+ children: [hiddenDndItemProps.map((props, idx) => {
980
+ return /* @__PURE__ */ jsx(Draggable, {
981
+ draggableId: props.column.key,
982
+ index: idx,
983
+ isDragDisabled: props.shouldDisableDrag,
984
+ children: (provided) => {
985
+ return /* @__PURE__ */ jsx("div", {
986
+ ref: provided.innerRef,
987
+ ...provided.draggableProps,
988
+ ...provided.dragHandleProps,
989
+ children: /* @__PURE__ */ jsx(AttributeDnd, { ...props })
990
+ });
991
+ }
992
+ }, `${props.column.key}`);
993
+ }), provided.placeholder]
994
+ });
995
+ }
996
+ })
997
+ })] })
998
+ ] }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Paragraph, { children: "No matching attributes" }) })
999
+ ] });
1000
+ };
1001
+ const OverflowText = styled("div")`
1002
+ max-width: 160px;
1003
+ flex-wrap: wrap;
1004
+ display: flex;
1005
+ `;
1006
+ const AttributeDnd = ({ column, index, isDisabled = false, isToggled, shouldDisableDrag, handleToggle }) => {
1007
+ return /* @__PURE__ */ jsxs(DndItemWrapper, { children: [
1008
+ /* @__PURE__ */ jsx(StyledIconDrag, {
1009
+ $active: true,
1010
+ $shouldHide: shouldDisableDrag
1011
+ }),
1012
+ /* @__PURE__ */ jsx(OverflowText, { children: /* @__PURE__ */ jsx(Paragraph, {
1013
+ color: "primary",
1014
+ size: "sm",
1015
+ children: column.label
1016
+ }) }),
1017
+ /* @__PURE__ */ jsx(SuffixContainer, { children: /* @__PURE__ */ jsx(Toggle, {
1018
+ value: isToggled,
1019
+ disabled: isDisabled,
1020
+ onChange: handleToggle,
1021
+ "aria-label": isToggled ? `Hide ${column.label}` : `Show ${column.label}`
1022
+ }) })
1023
+ ] }, `${column.key}-${index}`);
1024
+ };
1025
+ //#endregion
1026
+ //#region components/DataTable/TableControls/TableControlsContext.ts
1027
+ const TableControlsContext = createContext({
1028
+ filters: [],
1029
+ activeFilters: [],
1030
+ setActiveFilters: () => {}
1031
+ });
1032
+ function useTableControls() {
1033
+ return useContext(TableControlsContext);
1034
+ }
1035
+ function TableControlsProvider({ children, ...value }) {
1036
+ return createElement(TableControlsContext.Provider, { value }, children);
1037
+ }
1038
+ //#endregion
1039
+ //#region components/DataTable/TableControls/FiltersV2/operators.ts
1040
+ /**
1041
+ * Operator vocabulary per field type. The UI uses this to populate the
1042
+ * operator dropdown in the Filter popover and to gate which operators are
1043
+ * reachable for a given field. `is_empty` / `is_not_empty` apply broadly;
1044
+ * everything else is type-specific.
1045
+ *
1046
+ * The first entry for each type is the default operator selected when a
1047
+ * pill is created from the picker.
1048
+ */
1049
+ const OPERATORS_BY_TYPE = {
1050
+ string: [
1051
+ "is",
1052
+ "is_not",
1053
+ "contains",
1054
+ "does_not_contain",
1055
+ "is_empty",
1056
+ "is_not_empty"
1057
+ ],
1058
+ email: [
1059
+ "is",
1060
+ "is_not",
1061
+ "contains",
1062
+ "does_not_contain",
1063
+ "is_empty",
1064
+ "is_not_empty"
1065
+ ],
1066
+ choices: [
1067
+ "is",
1068
+ "is_not",
1069
+ "is_empty",
1070
+ "is_not_empty"
1071
+ ],
1072
+ multi_choices: [
1073
+ "is",
1074
+ "is_not",
1075
+ "is_empty",
1076
+ "is_not_empty"
1077
+ ],
1078
+ boolean: ["is"],
1079
+ integer: [
1080
+ "is",
1081
+ "is_not",
1082
+ "is_empty",
1083
+ "is_not_empty"
1084
+ ],
1085
+ float: [
1086
+ "is",
1087
+ "is_not",
1088
+ "is_empty",
1089
+ "is_not_empty"
1090
+ ],
1091
+ date: [
1092
+ "is",
1093
+ "before",
1094
+ "after",
1095
+ "is_empty",
1096
+ "is_not_empty"
1097
+ ],
1098
+ array: [
1099
+ "contains",
1100
+ "does_not_contain",
1101
+ "is_empty",
1102
+ "is_not_empty"
1103
+ ],
1104
+ tags_conditions: ["is"],
1105
+ date_range: ["is"]
1106
+ };
1107
+ /** Operators that have no value control (the operator itself is the predicate). */
1108
+ const VALUELESS_OPERATORS = new Set(["is_empty", "is_not_empty"]);
1109
+ function getOperatorsForType(type) {
1110
+ return OPERATORS_BY_TYPE[type] ?? [];
1111
+ }
1112
+ /**
1113
+ * Effective operator vocabulary for a concrete field: its `allowedOperators`
1114
+ * allow-list, or the field type's full vocabulary when the allow-list is
1115
+ * absent or empty. An empty allow-list means "unconstrained" rather than
1116
+ * "no operators" — the latter would leave the field selectable in the picker
1117
+ * but incapable of producing a rule that passes validation.
1118
+ *
1119
+ * Prefer this over {@link getOperatorsForType} anywhere a real field is in
1120
+ * hand — the popover's operator dropdown, `FieldRegistry`, validation — so a
1121
+ * field can never surface an operator the host application can't serialize.
1122
+ */
1123
+ function getOperatorsForField(field) {
1124
+ const { allowedOperators } = field;
1125
+ if (allowedOperators == null || allowedOperators.length === 0) return getOperatorsForType(field.type);
1126
+ return allowedOperators;
1127
+ }
1128
+ function getDefaultOperatorForType(type) {
1129
+ const list = OPERATORS_BY_TYPE[type];
1130
+ if (list.length === 0) throw new Error(`No operators defined for field type "${type}"`);
1131
+ return list[0];
1132
+ }
1133
+ function isValuelessOperator(operator) {
1134
+ return VALUELESS_OPERATORS.has(operator);
1135
+ }
1136
+ /**
1137
+ * Whether a concrete field's operator selector should be shown. A field
1138
+ * pinned to one operator renders it as static text rather than a caret that
1139
+ * opens a one-item menu.
1140
+ */
1141
+ function fieldHasMultipleOperators(field) {
1142
+ return getOperatorsForField(field).length > 1;
1143
+ }
1144
+ /**
1145
+ * Human-readable operator labels for the operator dropdown and filled pill.
1146
+ */
1147
+ const OPERATOR_LABELS = {
1148
+ is: "is",
1149
+ is_not: "is not",
1150
+ contains: "contains",
1151
+ does_not_contain: "does not contain",
1152
+ is_empty: "is empty",
1153
+ is_not_empty: "is not empty",
1154
+ is_true: "is true",
1155
+ is_false: "is false",
1156
+ before: "before",
1157
+ after: "after"
1158
+ };
1159
+ /**
1160
+ * Field-type-specific label overrides. The operator vocabulary itself
1161
+ * stays unchanged (operator tokens are `is` / `is_not` across types), but
1162
+ * labels can be more specific where the generic label is ambiguous.
1163
+ *
1164
+ * Only present for `(fieldType, operator)` pairs that diverge from the
1165
+ * generic label; everything else falls through to `OPERATOR_LABELS`.
1166
+ */
1167
+ const OPERATOR_LABELS_BY_TYPE = { multi_choices: {
1168
+ is: "is any of",
1169
+ is_not: "is none of"
1170
+ } };
1171
+ function getOperatorLabel(operator, fieldType) {
1172
+ if (fieldType) {
1173
+ const override = OPERATOR_LABELS_BY_TYPE[fieldType]?.[operator];
1174
+ if (override) return override;
1175
+ }
1176
+ return OPERATOR_LABELS[operator];
1177
+ }
1178
+ /**
1179
+ * Empty-but-present value seeded when a rule switches from a valueless operator
1180
+ * (`is_empty`) to one that requires a value. Non-null on purpose: a `null` value
1181
+ * reads as a removal and drops the pill mid-edit.
1182
+ */
1183
+ function emptyValueForFieldType(type) {
1184
+ switch (type) {
1185
+ case "multi_choices":
1186
+ case "tags_conditions": return [];
1187
+ default: return "";
1188
+ }
1189
+ }
1190
+ //#endregion
1191
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/display.ts
1192
+ function valueDisplayString(value, optionLabels) {
1193
+ if (value == null) return;
1194
+ const display = (raw) => optionLabels?.[raw] ?? raw;
1195
+ if (Array.isArray(value)) {
1196
+ if (value.length === 0) return;
1197
+ if (value.length === 1) return display(String(value[0]));
1198
+ return `${display(String(value[0]))} +${value.length - 1}`;
1199
+ }
1200
+ if (typeof value === "boolean") return value ? "true" : "false";
1201
+ if (typeof value === "number") return String(value);
1202
+ if (typeof value === "string") return value.length > 0 ? display(value) : void 0;
1203
+ }
1204
+ function draftValueFor(field, operator) {
1205
+ if (isValuelessOperator(operator)) return null;
1206
+ if (field.type === "boolean") return true;
1207
+ if (field.type === "multi_choices") return [];
1208
+ return "";
1209
+ }
1210
+ //#endregion
1211
+ //#region components/DataTable/TableControls/FiltersV2/fieldPickerOptions.ts
1212
+ const FIELDS_SUBMENU_LABEL = "Fields";
1213
+ function newNode() {
1214
+ return {
1215
+ leaves: [],
1216
+ groups: /* @__PURE__ */ new Map(),
1217
+ parents: /* @__PURE__ */ new Set()
1218
+ };
1219
+ }
1220
+ /**
1221
+ * The leaf `value` stays the full field id even when nested, so selection,
1222
+ * serialization, and persisted filter state are unaffected by the grouping.
1223
+ */
1224
+ function insertField(root, field, description) {
1225
+ const path = field.path && field.path.length > 1 ? field.path : null;
1226
+ if (!path) {
1227
+ root.leaves.push({
1228
+ label: field.label,
1229
+ value: field.id,
1230
+ description
1231
+ });
1232
+ return;
1233
+ }
1234
+ let node = root;
1235
+ for (const segment of path.slice(0, -1)) {
1236
+ let child = node.groups.get(segment);
1237
+ if (!child) {
1238
+ child = newNode();
1239
+ node.groups.set(segment, child);
1240
+ }
1241
+ if (description != null) child.parents.add(description);
1242
+ node = child;
1243
+ }
1244
+ node.leaves.push({
1245
+ label: startCase(path[path.length - 1]),
1246
+ value: field.id,
1247
+ description
1248
+ });
1249
+ }
1250
+ /**
1251
+ * A group gets a parent-record-type sublabel only when every field beneath it
1252
+ * shares one — a segment reused across templates has no single owner to name.
1253
+ */
1254
+ function nodeToOptions(node) {
1255
+ const groups = [];
1256
+ for (const [segment, child] of node.groups) {
1257
+ const [onlyParent] = child.parents;
1258
+ groups.push({
1259
+ label: startCase(segment),
1260
+ description: child.parents.size === 1 ? onlyParent : void 0,
1261
+ nested: true,
1262
+ options: nodeToOptions(child)
1263
+ });
1264
+ }
1265
+ return [...node.leaves, ...groups];
1266
+ }
1267
+ /**
1268
+ * Build the field-picker option tree shared by the `⊕ Filter` pill picker
1269
+ * (`FilterPickerMenu`) and the advanced-rules field dropdown
1270
+ * (`RuleEditorFields`) so both surface custom fields identically.
1271
+ *
1272
+ * System fields are top-level leaves; every custom field lives behind a
1273
+ * single `nested: true` "Fields" group, with its parent record type rendered
1274
+ * as the leaf's `description` sublabel. Hash subfields (fields whose backend
1275
+ * `path` has more than one segment, e.g. `address.city`) nest one level
1276
+ * deeper, behind their parent segment (`address`). The `nested`
1277
+ * flag is what makes the single-select Combobox render a group as an
1278
+ * expandable submenu — leaf selections commit via `onChange`, group descents
1279
+ * only navigate.
1280
+ *
1281
+ * `visibleCustomFieldParents`, when provided, narrows the Fields submenu to
1282
+ * only the listed parent record-type labels; passing an empty array hides the
1283
+ * submenu entirely. Omit it (or pass `undefined`) to show every group.
1284
+ *
1285
+ * `excludeFieldIds`, when provided, drops those fields from the tree.
1286
+ */
1287
+ function buildFieldPickerOptions(registry, visibleCustomFieldParents, excludeFieldIds) {
1288
+ const systemFields = registry.systemFieldsList();
1289
+ const customGroups = registry.customFieldGroups();
1290
+ const excluded = excludeFieldIds == null ? null : new Set(excludeFieldIds);
1291
+ const tree = systemFields.filter((field) => excluded == null || !excluded.has(field.id)).map((field) => ({
1292
+ label: field.label,
1293
+ value: field.id
1294
+ }));
1295
+ const allowedParents = visibleCustomFieldParents == null ? null : new Set(visibleCustomFieldParents);
1296
+ const customRoot = newNode();
1297
+ for (const group of customGroups) {
1298
+ if (allowedParents != null && !allowedParents.has(group.parent)) continue;
1299
+ const description = group.parent !== "" ? group.parent : void 0;
1300
+ for (const field of group.fields) {
1301
+ if (excluded != null && excluded.has(field.id)) continue;
1302
+ insertField(customRoot, field, description);
1303
+ }
1304
+ }
1305
+ const customOptions = nodeToOptions(customRoot);
1306
+ if (customOptions.length > 0) tree.push({
1307
+ label: FIELDS_SUBMENU_LABEL,
1308
+ nested: true,
1309
+ options: customOptions
1310
+ });
1311
+ return tree;
1312
+ }
1313
+ //#endregion
1314
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/RuleEditorFields.tsx
1315
+ function RuleEditorFields({ registry, field, groupIndex, ruleIndex, rule, size, operators, operatorConfigurable, onFieldChange, onOperatorChange, onValueChange, renderValueControl }) {
1316
+ const fieldOptions = useMemo(() => buildFieldPickerOptions(registry), [registry]);
1317
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1318
+ /* @__PURE__ */ jsx(ComboboxField, {
1319
+ label: "Value",
1320
+ labelProps: { size },
1321
+ "aria-label": `Field for rule ${ruleIndex + 1} in group ${groupIndex + 1}`,
1322
+ size,
1323
+ options: fieldOptions,
1324
+ value: rule.fieldId,
1325
+ onChange: (next) => {
1326
+ if (typeof next === "string") onFieldChange(groupIndex, ruleIndex, next);
1327
+ },
1328
+ placeholder: "Select field",
1329
+ portal: false
1330
+ }),
1331
+ operatorConfigurable ? /* @__PURE__ */ jsx(ComboboxField, {
1332
+ label: "Operator",
1333
+ labelProps: { size },
1334
+ "aria-label": `Operator for rule ${ruleIndex + 1} in group ${groupIndex + 1}`,
1335
+ size,
1336
+ options: operators.map((op) => ({
1337
+ label: getOperatorLabel(op, field?.type),
1338
+ value: op
1339
+ })),
1340
+ value: rule.operator,
1341
+ onChange: (next) => {
1342
+ if (typeof next === "string") onOperatorChange(groupIndex, ruleIndex, next);
1343
+ },
1344
+ portal: false
1345
+ }) : /* @__PURE__ */ jsx(FormField, {
1346
+ label: "Operator",
1347
+ labelProps: { size },
1348
+ children: /* @__PURE__ */ jsx(Input_default, {
1349
+ size,
1350
+ "aria-label": `Operator for rule ${ruleIndex + 1} in group ${groupIndex + 1}`,
1351
+ value: getOperatorLabel(rule.operator, field?.type),
1352
+ disabled: true,
1353
+ readOnly: true
1354
+ })
1355
+ }),
1356
+ field && !isValuelessOperator(rule.operator) ? /* @__PURE__ */ jsx(FormField, {
1357
+ label: "Value",
1358
+ labelProps: { size },
1359
+ children: /* @__PURE__ */ jsx(Fragment, { children: renderValueControl(field, rule.operator, rule.value, (next) => onValueChange(groupIndex, ruleIndex, next)) })
1360
+ }) : null
1361
+ ] });
1362
+ }
1363
+ //#endregion
1364
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRuleRow.tsx
1365
+ function AdvancedFilterRuleRow({ registry, groupIndex, ruleIndex, rule, size, isOpen, onClose, onDelete, onFieldChange, onOperatorChange, onValueChange, renderValueControl }) {
1366
+ const field = registry.get(rule.fieldId);
1367
+ const operators = field ? getOperatorsForField(field) : [];
1368
+ const operatorConfigurable = field ? fieldHasMultipleOperators(field) : true;
1369
+ const condition = ruleIndex === 0 ? "If" : "And";
1370
+ const rowId = `${groupIndex}-${ruleIndex}`;
1371
+ const valueDisplay = isValuelessOperator(rule.operator) ? void 0 : valueDisplayString(rule.value, registry.optionLabelsFor(rule.fieldId));
1372
+ const textValue = [
1373
+ condition,
1374
+ field?.label ?? rule.fieldId,
1375
+ getOperatorLabel(rule.operator, field?.type),
1376
+ valueDisplay
1377
+ ].filter(Boolean).join(" ");
1378
+ return /* @__PURE__ */ jsx(ListBox.LogicRow, {
1379
+ id: rowId,
1380
+ condition,
1381
+ hideCondition: true,
1382
+ attributeName: field?.label ?? rule.fieldId,
1383
+ operator: getOperatorLabel(rule.operator, field?.type),
1384
+ matchLevelName: valueDisplay,
1385
+ textValue,
1386
+ size,
1387
+ onClick: () => {
1388
+ if (isOpen) onClose();
1389
+ },
1390
+ onDelete,
1391
+ dropdownHeadingText: `Edit \u2018${condition}\u2019 statement`,
1392
+ dropdownFormFields: /* @__PURE__ */ jsx(RuleEditorFields, {
1393
+ registry,
1394
+ field,
1395
+ groupIndex,
1396
+ ruleIndex,
1397
+ rule,
1398
+ size,
1399
+ operators,
1400
+ operatorConfigurable,
1401
+ onFieldChange,
1402
+ onOperatorChange,
1403
+ onValueChange,
1404
+ renderValueControl
1405
+ })
1406
+ });
1407
+ }
1408
+ //#endregion
1409
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/compound-expression.ts
1410
+ function withGroup(compound, index, group) {
1411
+ const groups = [...compound.groups];
1412
+ groups[index] = group;
1413
+ return { groups };
1414
+ }
1415
+ function addRuleToGroup(compound, groupIndex, rule) {
1416
+ const groups = [...compound.groups];
1417
+ while (groups.length <= groupIndex) groups.push({ rules: [] });
1418
+ groups[groupIndex] = { rules: [...groups[groupIndex].rules, rule] };
1419
+ return { groups };
1420
+ }
1421
+ function setRuleInGroup(compound, groupIndex, ruleIndex, rule) {
1422
+ const group = compound.groups[groupIndex];
1423
+ if (!group || ruleIndex < 0 || ruleIndex >= group.rules.length) return compound;
1424
+ const rules = [...group.rules];
1425
+ rules[ruleIndex] = rule;
1426
+ return withGroup(compound, groupIndex, { rules });
1427
+ }
1428
+ function removeRuleFromGroup(compound, groupIndex, ruleIndex) {
1429
+ const group = compound.groups[groupIndex];
1430
+ if (!group || ruleIndex < 0 || ruleIndex >= group.rules.length) return compound;
1431
+ const rules = group.rules.filter((_, i) => i !== ruleIndex);
1432
+ if (rules.length === 0) return { groups: compound.groups.filter((_, i) => i !== groupIndex) };
1433
+ return withGroup(compound, groupIndex, { rules });
1434
+ }
1435
+ //#endregion
1436
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/use-rules-popover-selection.ts
1437
+ function useRulesPopoverSelection({ isOpen }) {
1438
+ const [selectedRowKey, setSelectedRowKey] = useState(null);
1439
+ const popoverContentRef = useRef(null);
1440
+ const lastPointerDownTargetRef = useRef(null);
1441
+ useEffect(() => {
1442
+ if (!isOpen && selectedRowKey != null) setSelectedRowKey(null);
1443
+ }, [isOpen, selectedRowKey]);
1444
+ useEffect(() => {
1445
+ const onPointerDown = (event) => {
1446
+ lastPointerDownTargetRef.current = event.target;
1447
+ };
1448
+ document.addEventListener("mousedown", onPointerDown, true);
1449
+ return () => document.removeEventListener("mousedown", onPointerDown, true);
1450
+ }, []);
1451
+ const closeSelectedRow = () => setSelectedRowKey(null);
1452
+ const handleGroupSelectionChange = (keys) => {
1453
+ const next = keys instanceof Set ? Array.from(keys)[0] ?? null : null;
1454
+ if (next == null) {
1455
+ const target = lastPointerDownTargetRef.current;
1456
+ if (target && popoverContentRef.current?.contains(target)) closeSelectedRow();
1457
+ return;
1458
+ }
1459
+ setSelectedRowKey(next);
1460
+ };
1461
+ const selectedKeysForGroup = (groupIndex) => {
1462
+ return selectedRowKey != null && selectedRowKey.startsWith(`${groupIndex}-`) ? new Set([selectedRowKey]) : /* @__PURE__ */ new Set();
1463
+ };
1464
+ return {
1465
+ selectedRowKey,
1466
+ setSelectedRowKey,
1467
+ closeSelectedRow,
1468
+ popoverContentRef,
1469
+ handleGroupSelectionChange,
1470
+ selectedKeysForGroup
1471
+ };
1472
+ }
1473
+ //#endregion
1474
+ //#region components/DataTable/TableControls/FiltersV2/filter-size-context.ts
1475
+ /**
1476
+ * Context for FilterBar-wide rendering settings. It currently carries
1477
+ * only `size`, but the object shape leaves room for future bar-level
1478
+ * settings without introducing another provider.
1479
+ */
1480
+ const FilterBarContext = createContext({ size: "sm" });
1481
+ /**
1482
+ * Resolve the active filter-bar size, honoring an explicit prop
1483
+ * override before falling back to the surrounding `FilterBarContext`.
1484
+ * Pattern is the same as the design-system FormControl size hook —
1485
+ * components accept an optional `size` prop that wins, otherwise
1486
+ * follow the ambient context.
1487
+ */
1488
+ function useFilterBarSize(override) {
1489
+ const { size } = useContext(FilterBarContext);
1490
+ return override ?? size;
1491
+ }
1492
+ const FILTER_SIZE_TOKENS = {
1493
+ sm: {
1494
+ controlHeight: "24px",
1495
+ chipHeight: "18px",
1496
+ fontSize: "12px",
1497
+ lineHeight: "18px",
1498
+ iconSize: "12px"
1499
+ },
1500
+ md: {
1501
+ controlHeight: "32px",
1502
+ chipHeight: "24px",
1503
+ fontSize: "14px",
1504
+ lineHeight: "22px",
1505
+ iconSize: "16px"
1506
+ }
1507
+ };
1508
+ //#endregion
1509
+ //#region components/DataTable/TableControls/FiltersV2/AdvancedFilterRulesPopover/AdvancedFilterRulesPopover.tsx
1510
+ const PopoverContent = styled(PopoverPrimitive.Content)`
1511
+ z-index: ${Z_INDICES.modalDropdown};
1512
+ `;
1513
+ const PopoverCard = styled(Card_default)`
1514
+ width: 384px;
1515
+ max-width: calc(100vw - ${Spacing[4]});
1516
+ margin-bottom: 0;
1517
+ `;
1518
+ const Header = styled.div`
1519
+ display: flex;
1520
+ align-items: center;
1521
+ justify-content: space-between;
1522
+ padding: ${Spacing[3]};
1523
+ `;
1524
+ const Body = styled.div`
1525
+ display: flex;
1526
+ flex-direction: column;
1527
+ gap: ${Spacing[2]};
1528
+ padding: 0 ${Spacing[3]} ${Spacing[3]};
1529
+ max-height: 60vh;
1530
+ overflow-y: auto;
1531
+ `;
1532
+ /**
1533
+ * Bordered container that wraps a single AndGroup. Visually mirrors the
1534
+ * `TableBox` shell (1px BorderDivider + BorderRadius.Md) but is built
1535
+ * standalone here because the rows inside are `LogicRow`s, which depend
1536
+ * on a parent `ListBox` rather than `TableBox`. Each group owns its
1537
+ * "If" / "Or" title and rule actions in the card header.
1538
+ */
1539
+ const GroupCard = styled.div`
1540
+ display: flex;
1541
+ flex-direction: column;
1542
+ border: 1px solid ${Color.BorderDivider};
1543
+ border-radius: ${BorderRadius.Md};
1544
+ background-color: ${Color.BackgroundPrimary};
1545
+ overflow: hidden;
1546
+ `;
1547
+ const GroupHeader = styled.div`
1548
+ display: flex;
1549
+ align-items: center;
1550
+ justify-content: space-between;
1551
+ padding: ${Spacing[1]} ${Spacing[2]};
1552
+ border-bottom: 1px solid ${Color.BorderDivider};
1553
+ background-color: ${Color.BackgroundSecondary};
1554
+ `;
1555
+ const GroupTitle = styled.span`
1556
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
1557
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
1558
+ color: ${Color.TextPrimary};
1559
+ `;
1560
+ const GroupHeaderActions = styled.div`
1561
+ display: inline-flex;
1562
+ align-items: center;
1563
+ gap: ${Spacing[1]};
1564
+ `;
1565
+ /**
1566
+ * A focused-down `ListBox` for the rules in one AndGroup. Strips the
1567
+ * default 204px width AND the standalone border (the parent `GroupCard`
1568
+ * supplies the border now). Removes the per-listbox padding so the row
1569
+ * cells sit flush against the card.
1570
+ */
1571
+ const RulesListBox = styled(ListBox)`
1572
+ width: 100%;
1573
+ border: 0;
1574
+ border-radius: 0;
1575
+ padding: 0;
1576
+ `;
1577
+ /**
1578
+ * "Or group" affordance that appears between consecutive groups and at
1579
+ * the bottom of the popover. Adds a new empty `AndGroup` at the end of
1580
+ * `compound.groups` when clicked.
1581
+ */
1582
+ const OrGroupRow = styled.div`
1583
+ display: flex;
1584
+ `;
1585
+ function groupsForRender(compound) {
1586
+ if (compound.groups.length === 0) return [{
1587
+ rules: [],
1588
+ synthetic: true
1589
+ }];
1590
+ return compound.groups.map((g) => ({
1591
+ rules: g.rules,
1592
+ synthetic: false
1593
+ }));
1594
+ }
1595
+ /**
1596
+ * DNF (OR-of-AND) editor popover for the compound expression owned by the
1597
+ * Rules pill.
1598
+ *
1599
+ * The popover is fully controlled by `compound` + `onChange` — it never
1600
+ * holds compound state internally so parents can persist edits incrementally
1601
+ * (URL state, saved-view dual-write, etc.). `open` / `onOpenChange` are
1602
+ * optional; when omitted the popover manages its own open state and is
1603
+ * opened by clicking the parent-supplied trigger.
1604
+ *
1605
+ * Each AndGroup's rules are rendered as a `<ListBox>` of `<LogicRow>` items.
1606
+ * The collapsed row reads `[If/And] [field-sticker] [operator] [value-sticker]`
1607
+ * inline; clicking a row reveals the field/operator/value editor inside the
1608
+ * row's dropdown popover.
1609
+ */
1610
+ const AdvancedFilterRulesPopover = ({ registry, compound, onChange, trigger, open, onOpenChange, renderValueControl, size }) => {
1611
+ const resolvedSize = useFilterBarSize(size);
1612
+ const subtleIconSize = resolvedSize === "sm" ? "xs" : "sm";
1613
+ const [internalOpen, setInternalOpen] = useState(false);
1614
+ const isControlled = open != null;
1615
+ const isOpen = isControlled ? open : internalOpen;
1616
+ const { selectedRowKey, setSelectedRowKey, closeSelectedRow, popoverContentRef, handleGroupSelectionChange, selectedKeysForGroup } = useRulesPopoverSelection({ isOpen });
1617
+ const handleOpenChange = useCallback((next) => {
1618
+ if (!isControlled) setInternalOpen(next);
1619
+ onOpenChange?.(next);
1620
+ }, [isControlled, onOpenChange]);
1621
+ const baseId = useMemo(() => uniqueId$1("advanced-filter-rules__"), []);
1622
+ const fields = registry.all();
1623
+ const handleAddOrGroup = useCallback(() => {
1624
+ const firstField = fields[0];
1625
+ if (!firstField) return;
1626
+ const operator = registry.reconcileOperator(firstField.id, "is");
1627
+ const groupIndex = compound.groups.length;
1628
+ onChange(addRuleToGroup(compound, groupIndex, {
1629
+ fieldId: firstField.id,
1630
+ operator,
1631
+ value: draftValueFor(firstField, operator)
1632
+ }));
1633
+ setSelectedRowKey(`${groupIndex}-0`);
1634
+ }, [
1635
+ compound,
1636
+ fields,
1637
+ onChange,
1638
+ registry
1639
+ ]);
1640
+ const handleAddRuleToGroup = useCallback((groupIndex) => {
1641
+ const firstField = fields[0];
1642
+ if (!firstField) return;
1643
+ const operator = registry.reconcileOperator(firstField.id, "is");
1644
+ const newRowId = `${groupIndex}-${compound.groups[groupIndex]?.rules.length ?? 0}`;
1645
+ onChange(addRuleToGroup(compound, groupIndex, {
1646
+ fieldId: firstField.id,
1647
+ operator,
1648
+ value: draftValueFor(firstField, operator)
1649
+ }));
1650
+ setSelectedRowKey(newRowId);
1651
+ }, [
1652
+ compound,
1653
+ fields,
1654
+ onChange,
1655
+ registry
1656
+ ]);
1657
+ const applyCompoundChange = useCallback((next) => {
1658
+ onChange(next);
1659
+ }, [onChange]);
1660
+ const handleRemoveRule = useCallback((groupIndex, ruleIndex) => {
1661
+ applyCompoundChange(removeRuleFromGroup(compound, groupIndex, ruleIndex));
1662
+ }, [compound, applyCompoundChange]);
1663
+ const handleFieldChange = useCallback((groupIndex, ruleIndex, nextFieldId) => {
1664
+ const field = registry.get(nextFieldId);
1665
+ if (!field) return;
1666
+ const prev = compound.groups[groupIndex]?.rules[ruleIndex];
1667
+ if (!prev) return;
1668
+ const operator = registry.reconcileOperator(field.id, prev.operator);
1669
+ onChange(setRuleInGroup(compound, groupIndex, ruleIndex, {
1670
+ fieldId: nextFieldId,
1671
+ operator,
1672
+ value: draftValueFor(field, operator)
1673
+ }));
1674
+ }, [
1675
+ compound,
1676
+ onChange,
1677
+ registry
1678
+ ]);
1679
+ const handleOperatorChange = useCallback((groupIndex, ruleIndex, nextOperator) => {
1680
+ const prev = compound.groups[groupIndex]?.rules[ruleIndex];
1681
+ if (!prev) return;
1682
+ onChange(setRuleInGroup(compound, groupIndex, ruleIndex, {
1683
+ fieldId: prev.fieldId,
1684
+ operator: nextOperator,
1685
+ value: isValuelessOperator(nextOperator) ? null : prev.value
1686
+ }));
1687
+ }, [compound, onChange]);
1688
+ const handleValueChange = useCallback((groupIndex, ruleIndex, nextValue) => {
1689
+ const prev = compound.groups[groupIndex]?.rules[ruleIndex];
1690
+ if (!prev) return;
1691
+ onChange(setRuleInGroup(compound, groupIndex, ruleIndex, {
1692
+ fieldId: prev.fieldId,
1693
+ operator: prev.operator,
1694
+ value: nextValue
1695
+ }));
1696
+ }, [compound, onChange]);
1697
+ return /* @__PURE__ */ jsxs(PopoverPrimitive.Root, {
1698
+ open: isOpen,
1699
+ onOpenChange: handleOpenChange,
1700
+ children: [/* @__PURE__ */ jsx(PopoverPrimitive.Trigger, {
1701
+ asChild: true,
1702
+ children: trigger
1703
+ }), /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(PopoverContent, {
1704
+ align: "start",
1705
+ sideOffset: 8,
1706
+ collisionPadding: 8,
1707
+ role: "dialog",
1708
+ "aria-label": "Advanced filter rules",
1709
+ id: baseId,
1710
+ ref: popoverContentRef,
1711
+ tabIndex: -1,
1712
+ onKeyDown: (event) => {
1713
+ if (event.key !== "Enter") return;
1714
+ if (selectedRowKey != null) {
1715
+ event.preventDefault();
1716
+ closeSelectedRow();
1717
+ requestAnimationFrame(() => {
1718
+ popoverContentRef.current?.focus();
1719
+ });
1720
+ return;
1721
+ }
1722
+ if (event.target !== popoverContentRef.current) return;
1723
+ event.preventDefault();
1724
+ handleOpenChange(false);
1725
+ },
1726
+ children: /* @__PURE__ */ jsxs(PopoverCard, {
1727
+ elevated: true,
1728
+ children: [/* @__PURE__ */ jsx(Header, { children: /* @__PURE__ */ jsx(Paragraph, {
1729
+ size: resolvedSize,
1730
+ color: "secondary",
1731
+ children: "Advanced filter rules"
1732
+ }) }), /* @__PURE__ */ jsxs(Body, { children: [groupsForRender(compound).map((group, groupIndex, renderableGroups) => {
1733
+ const groupTitle = groupIndex === 0 ? "If" : "Or";
1734
+ const isSynthetic = group.synthetic;
1735
+ const isOnlyGroup = renderableGroups.length === 1;
1736
+ const isEmptyGroup = group.rules.length === 0;
1737
+ const hideGroupMenu = isOnlyGroup && isEmptyGroup;
1738
+ const deleteGroupLabel = isOnlyGroup && !isEmptyGroup ? "Clear all" : "Delete group";
1739
+ return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs(GroupCard, {
1740
+ "data-test": `advanced-filter-rules__group-${groupIndex}`,
1741
+ role: "group",
1742
+ "aria-label": `Filter group ${groupIndex + 1}`,
1743
+ children: [/* @__PURE__ */ jsxs(GroupHeader, { children: [/* @__PURE__ */ jsx(GroupTitle, {
1744
+ $size: resolvedSize,
1745
+ children: groupTitle
1746
+ }), /* @__PURE__ */ jsxs(GroupHeaderActions, { children: [hideGroupMenu ? null : /* @__PURE__ */ jsx(DropdownMenu_default, {
1747
+ trigger: /* @__PURE__ */ jsx(IconButton, {
1748
+ size: subtleIconSize,
1749
+ "aria-label": `More actions for filter group ${groupIndex + 1}`,
1750
+ "data-test": `advanced-filter-rules__group-more-${groupIndex}`,
1751
+ children: /* @__PURE__ */ jsx(MoreIcon$1, {})
1752
+ }),
1753
+ align: "end",
1754
+ portal: true,
1755
+ zIndex: Z_INDICES.modalDropdown,
1756
+ children: /* @__PURE__ */ jsx(DropdownMenu_default.Item, {
1757
+ size: resolvedSize,
1758
+ onClick: () => {
1759
+ if (isSynthetic) {
1760
+ handleOpenChange(false);
1761
+ return;
1762
+ }
1763
+ applyCompoundChange({ groups: compound.groups.filter((_, i) => i !== groupIndex) });
1764
+ },
1765
+ "data-test": `advanced-filter-rules__delete-group-${groupIndex}`,
1766
+ children: deleteGroupLabel
1767
+ })
1768
+ }), /* @__PURE__ */ jsx(IconButton, {
1769
+ size: subtleIconSize,
1770
+ onClick: () => handleAddRuleToGroup(groupIndex),
1771
+ "aria-label": `Add rule to filter group ${groupIndex + 1}`,
1772
+ "data-test": `advanced-filter-rules__add-rule-${groupIndex}`,
1773
+ children: /* @__PURE__ */ jsx(PlusIcon$1, {})
1774
+ })] })] }), group.rules.length === 0 ? /* @__PURE__ */ jsx(Paragraph, {
1775
+ size: resolvedSize,
1776
+ color: "secondary",
1777
+ style: { padding: Spacing[2] },
1778
+ children: "No rules yet"
1779
+ }) : /* @__PURE__ */ jsx(RulesListBox, {
1780
+ "aria-label": `Rules in group ${groupIndex + 1}`,
1781
+ selectionMode: "single",
1782
+ size: resolvedSize,
1783
+ fullWidth: true,
1784
+ selectedKeys: selectedKeysForGroup(groupIndex),
1785
+ onSelectionChange: handleGroupSelectionChange,
1786
+ children: group.rules.map((rule, ruleIndex) => {
1787
+ const rowId = `${groupIndex}-${ruleIndex}`;
1788
+ return /* @__PURE__ */ jsx(AdvancedFilterRuleRow, {
1789
+ registry,
1790
+ groupIndex,
1791
+ ruleIndex,
1792
+ rule,
1793
+ size: resolvedSize,
1794
+ isOpen: selectedRowKey === rowId,
1795
+ onClose: closeSelectedRow,
1796
+ onDelete: () => handleRemoveRule(groupIndex, ruleIndex),
1797
+ onFieldChange: handleFieldChange,
1798
+ onOperatorChange: handleOperatorChange,
1799
+ onValueChange: handleValueChange,
1800
+ renderValueControl
1801
+ }, rowId);
1802
+ })
1803
+ })]
1804
+ }) }, `${baseId}__group-${groupIndex}`);
1805
+ }), /* @__PURE__ */ jsx(OrGroupRow, { children: /* @__PURE__ */ jsx(Button, {
1806
+ variant: "basic",
1807
+ size: resolvedSize,
1808
+ width: "auto",
1809
+ prefixIcon: /* @__PURE__ */ jsx(PlusIcon, {}),
1810
+ onClick: handleAddOrGroup,
1811
+ "data-test": "advanced-filter-rules__add-or-group",
1812
+ children: "Or group"
1813
+ }) })] })]
1814
+ })
1815
+ }) })]
1816
+ });
1817
+ };
1818
+ //#endregion
1819
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/ArrayValueControl/ArrayValueControl.tsx
1820
+ const stringDisplayValue = (value) => {
1821
+ if (typeof value === "string") return value;
1822
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
1823
+ return "";
1824
+ };
1825
+ const stringValue = (value) => {
1826
+ if (typeof value === "string" && value !== "") return value;
1827
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
1828
+ return null;
1829
+ };
1830
+ /**
1831
+ * Array-typed value control for the Filter UI v2 popover.
1832
+ *
1833
+ * Used for `array` fields with operators `contains` / `does_not_contain`.
1834
+ * The popover renders nothing when the operator is valueless
1835
+ * (`is_empty` / `is_not_empty`).
1836
+ *
1837
+ * The rendered control depends on the inner item type advertised by the
1838
+ * field's `itemType`:
1839
+ *
1840
+ * - `'choices'` → single-select Combobox sourced from `field.options`.
1841
+ * - `'string'` or unset → free-text input (a single value to test for
1842
+ * membership against the array column).
1843
+ *
1844
+ * Output value is always a single string; an empty text input emits `''`, not
1845
+ * `null`, because the pill lifecycle reads a `null` value on a value-requiring
1846
+ * operator as a removal and drops the pill. `''` keeps the pill as a visible
1847
+ * draft; the serialize boundary is what filters incomplete values out of the
1848
+ * request. The predicate is "does this array contain (or not contain) this
1849
+ * scalar?", so we never produce an array-of-values from this control.
1850
+ */
1851
+ const ArrayValueControl = ({ field, operator, value, onChange, onCommit, ariaLabel, layout = "popover" }) => {
1852
+ const size = useFilterBarSize();
1853
+ const [localValue, setLocalValue] = useState(() => stringDisplayValue(value));
1854
+ useEffect(() => {
1855
+ setLocalValue(stringDisplayValue(value));
1856
+ }, [value]);
1857
+ const handleTextChange = useCallback((raw) => {
1858
+ setLocalValue(raw);
1859
+ onChange(raw);
1860
+ }, [onChange]);
1861
+ const handleComboboxChange = useCallback((next) => {
1862
+ onChange(next ?? null);
1863
+ onCommit?.();
1864
+ }, [onChange, onCommit]);
1865
+ if (isValuelessOperator(operator)) return null;
1866
+ const label = ariaLabel ?? `${field.label} value`;
1867
+ if ((field.itemType ?? "string") === "choices") return /* @__PURE__ */ jsx(Combobox, {
1868
+ "aria-label": label,
1869
+ options: (field.options ?? []).map((opt) => ({
1870
+ label: opt.label,
1871
+ value: opt.value
1872
+ })),
1873
+ value: stringValue(value),
1874
+ onChange: handleComboboxChange,
1875
+ placeholder: "Select an option",
1876
+ size,
1877
+ embedded: layout === "popover"
1878
+ });
1879
+ return /* @__PURE__ */ jsx(Input_default, {
1880
+ type: "text",
1881
+ size,
1882
+ placeholder: "Enter a value",
1883
+ "aria-label": label,
1884
+ value: localValue,
1885
+ onChange: (e) => handleTextChange(e.target.value)
1886
+ });
1887
+ };
1888
+ //#endregion
1889
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/BooleanValueControl/BooleanValueControl.tsx
1890
+ const OPTIONS = [{
1891
+ label: "True",
1892
+ value: true
1893
+ }, {
1894
+ label: "False",
1895
+ value: false
1896
+ }];
1897
+ const Row = styled.button`
1898
+ ${Typography.TextSmall};
1899
+ display: flex;
1900
+ align-items: center;
1901
+ justify-content: space-between;
1902
+ box-sizing: border-box;
1903
+ width: 100%;
1904
+ margin: 0;
1905
+ padding: ${Spacing[1]} ${Spacing[2]};
1906
+ border: none;
1907
+ appearance: none;
1908
+ border-radius: ${BorderRadius.Sm};
1909
+ background: ${({ $selected }) => $selected ? Color.CorePurple100 : "transparent"};
1910
+ color: ${({ $selected }) => $selected ? Color.TextActive : Color.TextPrimary};
1911
+ font-family: inherit;
1912
+ text-align: left;
1913
+ cursor: pointer;
1914
+
1915
+ &:hover {
1916
+ background: ${({ $selected }) => $selected ? Color.CorePurple100 : Color.BackgroundSecondary};
1917
+ }
1918
+
1919
+ &:focus-visible {
1920
+ outline: 2px solid ${Color.BorderFocus};
1921
+ outline-offset: 1px;
1922
+ }
1923
+
1924
+ svg {
1925
+ flex-shrink: 0;
1926
+ color: inherit;
1927
+ }
1928
+ `;
1929
+ const Root = styled.div`
1930
+ display: flex;
1931
+ flex-direction: column;
1932
+ gap: ${Spacing[0]};
1933
+ `;
1934
+ /**
1935
+ * Filter UI v2 — boolean value picker for `boolean`-typed fields with `is` /
1936
+ * `is_not` operators. Renders two rows (True / False); the selected row uses
1937
+ * the same purple treatment as other filter value selections. Renders nothing
1938
+ * for valueless operators (`is_empty`, `is_not_empty`).
1939
+ */
1940
+ function BooleanValueControl({ operator, value, onChange, ariaLabel }) {
1941
+ if (isValuelessOperator(operator)) return null;
1942
+ const selected = typeof value === "boolean" ? value : null;
1943
+ return /* @__PURE__ */ jsx(Root, {
1944
+ role: "radiogroup",
1945
+ "aria-label": ariaLabel ?? "Boolean value",
1946
+ children: OPTIONS.map((opt) => {
1947
+ const isSelected = selected === opt.value;
1948
+ return /* @__PURE__ */ jsxs(Row, {
1949
+ type: "button",
1950
+ role: "radio",
1951
+ "aria-checked": isSelected,
1952
+ $selected: isSelected,
1953
+ onClick: () => onChange(opt.value),
1954
+ children: [opt.label, isSelected ? /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": true }) : null]
1955
+ }, String(opt.value));
1956
+ })
1957
+ });
1958
+ }
1959
+ //#endregion
1960
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/ChoicesValueControl/ChoicesValueControl.tsx
1961
+ const EMPTY_OPTIONS = [];
1962
+ const EMPTY_VALUES = [];
1963
+ /**
1964
+ * Filter UI v2 — value control for `choices` / `multi_choices`-typed fields.
1965
+ *
1966
+ * Backed by the design-system `Combobox`. In single-select mode the value is a
1967
+ * string; in `multiple` mode it is an array of strings. Options come from
1968
+ * `field.options` (populated by `FieldRegistry` from the backend's
1969
+ * `field_key_to_info` payload). Renders nothing when the active operator is
1970
+ * valueless (e.g. `is_empty`).
1971
+ */
1972
+ function ChoicesValueControl({ field, operator, value, onChange, onCommit, ariaLabel, trigger, layout = "popover", multiple = false }) {
1973
+ const generatedId = useMemo(() => uniqueId$1(multiple ? "filter_v2_multi_choices_" : "filter_v2_choices_"), [multiple]);
1974
+ const size = useFilterBarSize();
1975
+ const options = field.options ?? EMPTY_OPTIONS;
1976
+ const values = useMemo(() => Array.isArray(value) ? [...value] : EMPTY_VALUES, [value]);
1977
+ if (isValuelessOperator(operator)) return null;
1978
+ const useEmbeddedCombobox = layout === "popover" && trigger == null;
1979
+ if (multiple) return /* @__PURE__ */ jsx(Combobox, {
1980
+ id: generatedId,
1981
+ size,
1982
+ "aria-label": ariaLabel ?? field.label,
1983
+ placeholder: field.label,
1984
+ searchPlaceholder: "Search",
1985
+ emptyStateMessage: "No matches",
1986
+ options,
1987
+ values,
1988
+ trigger,
1989
+ onValuesChange: onChange,
1990
+ embedded: useEmbeddedCombobox,
1991
+ multiple: true,
1992
+ truncate: true,
1993
+ stableOptionOrder: true
1994
+ });
1995
+ return /* @__PURE__ */ jsx(Combobox, {
1996
+ id: generatedId,
1997
+ size,
1998
+ "aria-label": ariaLabel ?? field.label,
1999
+ placeholder: field.label,
2000
+ options,
2001
+ value: typeof value === "string" ? value : null,
2002
+ trigger,
2003
+ onChange: (next) => {
2004
+ onChange(next ?? null);
2005
+ onCommit?.();
2006
+ },
2007
+ embedded: useEmbeddedCombobox
2008
+ });
2009
+ }
2010
+ //#endregion
2011
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/DateValueControl/DateValueControl.tsx
2012
+ const parseIsoDate = (value) => {
2013
+ if (typeof value !== "string") return null;
2014
+ try {
2015
+ return parseDate(value);
2016
+ } catch {
2017
+ return null;
2018
+ }
2019
+ };
2020
+ /**
2021
+ * Single-date value control for the Filter UI v2 popover.
2022
+ *
2023
+ * Used for `date` fields with operators `is` / `before` / `after`. The
2024
+ * popover renders nothing when the selected operator is valueless
2025
+ * (`is_empty` / `is_not_empty`) — those operators are themselves the
2026
+ * predicate and need no companion value.
2027
+ *
2028
+ * Output value is always a `YYYY-MM-DD` ISO date string (or `null` when
2029
+ * cleared).
2030
+ */
2031
+ const DateValueControl = ({ field, operator, value, onChange, ariaLabel }) => {
2032
+ const size = useFilterBarSize();
2033
+ const handleChange = useCallback((nextDate) => {
2034
+ onChange(nextDate ? nextDate.toString() : null);
2035
+ }, [onChange]);
2036
+ if (isValuelessOperator(operator)) return null;
2037
+ return /* @__PURE__ */ jsx(DatePicker, {
2038
+ value: parseIsoDate(value),
2039
+ size,
2040
+ "aria-label": ariaLabel ?? `${field.label} value`,
2041
+ onChange: handleChange,
2042
+ useModalZIndex: true
2043
+ });
2044
+ };
2045
+ //#endregion
2046
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/utils.ts
2047
+ /**
2048
+ * Coerce a `FilterRuleValue` into a string suitable for an `<input>`'s
2049
+ * `value` prop. Used by `IntegerValueControl` and `FloatValueControl` so
2050
+ * both share identical display-coercion semantics — without this, drift
2051
+ * (e.g. different handling of `''`) would let the two controls disagree
2052
+ * about how to render the same hydrated rule.
2053
+ *
2054
+ * `Number.isFinite` rules out `NaN` / `±Infinity` (a hydrated state that
2055
+ * round-tripped through JSON should never carry those, but the guard is
2056
+ * cheap defense). Empty strings collapse to `''` rather than falling
2057
+ * through to `'undefined'` / `'null'` if the rule arrives in a malformed
2058
+ * shape.
2059
+ */
2060
+ function numericDisplayValue(value) {
2061
+ if (typeof value === "number" && Number.isFinite(value)) return String(value);
2062
+ if (typeof value === "string" && value !== "") return value;
2063
+ return "";
2064
+ }
2065
+ //#endregion
2066
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/FloatValueControl/FloatValueControl.tsx
2067
+ /**
2068
+ * Float-typed value control for the Filter UI v2 popover.
2069
+ *
2070
+ * Used for `float` fields with operators `is` / `is_not`. The popover
2071
+ * renders nothing when the operator is valueless (`is_empty` /
2072
+ * `is_not_empty`). Range operators are not part of the current numeric
2073
+ * field vocabulary.
2074
+ *
2075
+ * The control accepts decimal input and emits a `number` via `onChange`.
2076
+ * We keep local display state as a string so partial input like `"3."` is
2077
+ * preserved while the user types; the emitted numeric value is only updated
2078
+ * once the input parses to a finite number.
2079
+ *
2080
+ * `isFocused` ref guards the external-value sync effect: typing a
2081
+ * mid-decimal value like `"3."` parses to `3` and emits it, which
2082
+ * round-trips back through the controlled `value` prop. Without the
2083
+ * guard, the sync effect would rewrite the display from `"3."` to
2084
+ * `"3"` and the next keystroke (`"7"`) would land at the wrong cursor
2085
+ * position. The blur handler resyncs the display so any half-typed
2086
+ * string that never parsed (`"-"`, `"."`) renders as whatever the
2087
+ * rule actually carries when focus leaves.
2088
+ *
2089
+ * `onChange` is debounced (300ms) to avoid committing on every keystroke;
2090
+ * the debounce flushes on blur and on unmount so no pending value is lost.
2091
+ */
2092
+ const FloatValueControl = ({ field, operator, value, onChange, ariaLabel }) => {
2093
+ const size = useFilterBarSize();
2094
+ const [localValue, setLocalValue] = useState(() => numericDisplayValue(value));
2095
+ const isFocusedRef = useRef(false);
2096
+ const debouncedOnChange = useMemo(() => debounce(300, onChange), [onChange]);
2097
+ useEffect(() => {
2098
+ const cancelPendingChange = () => {
2099
+ debouncedOnChange.cancel();
2100
+ };
2101
+ return cancelPendingChange;
2102
+ }, [debouncedOnChange]);
2103
+ useEffect(() => {
2104
+ if (isFocusedRef.current) return;
2105
+ setLocalValue(numericDisplayValue(value));
2106
+ }, [value]);
2107
+ const handleChange = useCallback((raw) => {
2108
+ setLocalValue(raw);
2109
+ if (raw === "" || raw === "-" || raw === ".") {
2110
+ debouncedOnChange(null);
2111
+ return;
2112
+ }
2113
+ const parsed = Number(raw);
2114
+ if (!Number.isFinite(parsed)) return;
2115
+ debouncedOnChange(parsed);
2116
+ }, [debouncedOnChange]);
2117
+ if (isValuelessOperator(operator)) return null;
2118
+ return /* @__PURE__ */ jsx(Input_default, {
2119
+ type: "number",
2120
+ size,
2121
+ step: "any",
2122
+ inputMode: "decimal",
2123
+ placeholder: "Enter a number",
2124
+ "aria-label": ariaLabel ?? `${field.label} value`,
2125
+ value: localValue,
2126
+ onChange: (e) => handleChange(e.target.value),
2127
+ onFocus: () => {
2128
+ isFocusedRef.current = true;
2129
+ },
2130
+ onBlur: () => {
2131
+ isFocusedRef.current = false;
2132
+ debouncedOnChange.flush();
2133
+ setLocalValue(numericDisplayValue(value));
2134
+ }
2135
+ });
2136
+ };
2137
+ //#endregion
2138
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/IntegerValueControl/IntegerValueControl.tsx
2139
+ /**
2140
+ * Integer-typed value control for the Filter UI v2 popover.
2141
+ *
2142
+ * Used for `integer` fields with operators `is` / `is_not`. The popover
2143
+ * renders nothing when the operator is valueless (`is_empty` /
2144
+ * `is_not_empty`). Range operators are not part of the current numeric
2145
+ * field vocabulary.
2146
+ *
2147
+ * The control accepts any numeric input but always emits an integer via
2148
+ * `onChange`. We truncate (rather than round) so that typing `3` -> `3.` -> `3.7`
2149
+ * does not jump to `4` mid-typing; the wire-format value follows `parseInt`
2150
+ * semantics, matching common backend integer-coercion behavior.
2151
+ *
2152
+ * `isFocused` ref guards the external-value sync effect: while the user
2153
+ * is actively typing, an external value change (which we ourselves
2154
+ * triggered by emitting `onChange`) must NOT clobber the local display
2155
+ * string. Without this guard, typing `3` -> emits `3` -> external value
2156
+ * becomes `3` -> the sync effect resets local back to `'3'`, which
2157
+ * looks fine until you type `-` to clear and the sync races against
2158
+ * the user's next keystroke.
2159
+ *
2160
+ * `onChange` is debounced (300ms) to avoid committing on every keystroke;
2161
+ * the debounce flushes on blur and on unmount so no pending value is lost.
2162
+ */
2163
+ const IntegerValueControl = ({ field, operator, value, onChange, ariaLabel }) => {
2164
+ const size = useFilterBarSize();
2165
+ const [localValue, setLocalValue] = useState(() => numericDisplayValue(value));
2166
+ const isFocusedRef = useRef(false);
2167
+ const debouncedOnChange = useMemo(() => debounce(300, onChange), [onChange]);
2168
+ useEffect(() => {
2169
+ const cancelPendingChange = () => {
2170
+ debouncedOnChange.cancel();
2171
+ };
2172
+ return cancelPendingChange;
2173
+ }, [debouncedOnChange]);
2174
+ useEffect(() => {
2175
+ if (isFocusedRef.current) return;
2176
+ setLocalValue(numericDisplayValue(value));
2177
+ }, [value]);
2178
+ const handleChange = useCallback((raw) => {
2179
+ setLocalValue(raw);
2180
+ if (raw === "" || raw === "-") {
2181
+ debouncedOnChange(null);
2182
+ return;
2183
+ }
2184
+ const parsed = Number(raw);
2185
+ if (!Number.isFinite(parsed)) return;
2186
+ debouncedOnChange(Math.trunc(parsed));
2187
+ }, [debouncedOnChange]);
2188
+ if (isValuelessOperator(operator)) return null;
2189
+ return /* @__PURE__ */ jsx(Input_default, {
2190
+ type: "number",
2191
+ size,
2192
+ step: 1,
2193
+ inputMode: "numeric",
2194
+ placeholder: "Enter a number",
2195
+ "aria-label": ariaLabel ?? `${field.label} value`,
2196
+ value: localValue,
2197
+ onChange: (e) => handleChange(e.target.value),
2198
+ onFocus: () => {
2199
+ isFocusedRef.current = true;
2200
+ },
2201
+ onBlur: () => {
2202
+ isFocusedRef.current = false;
2203
+ debouncedOnChange.flush();
2204
+ setLocalValue(numericDisplayValue(value));
2205
+ }
2206
+ });
2207
+ };
2208
+ //#endregion
2209
+ //#region components/DataTable/TableControls/FiltersV2/value-controls/StringValueControl/StringValueControl.tsx
2210
+ const DEBOUNCE_MS = 300;
2211
+ function StringValueControl({ field, operator, value, onChange, ariaLabel, inputType, placeholder, id }) {
2212
+ const generatedId = useMemo(() => uniqueId$1("filter_v2_string_"), []);
2213
+ const inputId = id ?? generatedId;
2214
+ const resolvedInputType = inputType ?? (field.type === "email" ? "email" : "text");
2215
+ const size = useFilterBarSize();
2216
+ const [localValue, setLocalValue] = useState(typeof value === "string" ? value : "");
2217
+ const debouncedOnChange = useMemo(() => debounce(DEBOUNCE_MS, onChange), [onChange]);
2218
+ useEffect(() => () => {
2219
+ debouncedOnChange.cancel();
2220
+ }, [debouncedOnChange]);
2221
+ useEffect(() => {
2222
+ setLocalValue(typeof value === "string" ? value : "");
2223
+ }, [value]);
2224
+ if (isValuelessOperator(operator)) return null;
2225
+ return /* @__PURE__ */ jsx(Input_default, {
2226
+ id: inputId,
2227
+ type: resolvedInputType,
2228
+ size,
2229
+ placeholder: placeholder ?? field.label,
2230
+ "aria-label": ariaLabel ?? field.label,
2231
+ value: localValue,
2232
+ onChange: ({ target }) => {
2233
+ setLocalValue(target.value);
2234
+ debouncedOnChange(target.value);
2235
+ },
2236
+ onBlur: () => {
2237
+ debouncedOnChange.flush();
2238
+ },
2239
+ onKeyDown: (event) => {
2240
+ if (event.key === "Enter") debouncedOnChange.flush();
2241
+ }
2242
+ });
2243
+ }
2244
+ //#endregion
2245
+ //#region components/DataTable/TableControls/FiltersV2/FilterBar/value-control-resolver.tsx
2246
+ const RESOLVERS = {
2247
+ string: (opts) => /* @__PURE__ */ jsx(StringValueControl, { ...opts }),
2248
+ email: (opts) => /* @__PURE__ */ jsx(StringValueControl, { ...opts }),
2249
+ choices: (opts) => /* @__PURE__ */ jsx(ChoicesValueControl, { ...opts }),
2250
+ multi_choices: (opts) => /* @__PURE__ */ jsx(ChoicesValueControl, {
2251
+ multiple: true,
2252
+ ...opts
2253
+ }),
2254
+ boolean: (opts) => /* @__PURE__ */ jsx(BooleanValueControl, { ...opts }),
2255
+ date: (opts) => /* @__PURE__ */ jsx(DateValueControl, { ...opts }),
2256
+ integer: (opts) => /* @__PURE__ */ jsx(IntegerValueControl, { ...opts }),
2257
+ float: (opts) => /* @__PURE__ */ jsx(FloatValueControl, { ...opts }),
2258
+ array: (opts) => /* @__PURE__ */ jsx(ArrayValueControl, { ...opts })
2259
+ };
2260
+ function resolveValueControl(opts, hostResolver) {
2261
+ const hostControl = hostResolver?.(opts);
2262
+ if (hostControl != null) return hostControl;
2263
+ const renderer = RESOLVERS[opts.field.type];
2264
+ if (!renderer) return null;
2265
+ return renderer(opts);
2266
+ }
2267
+ //#endregion
2268
+ //#region components/DataTable/TableControls/FiltersV2/FilterPickerMenu/FilterPickerMenu.tsx
2269
+ const TriggerWrapper = styled.span`
2270
+ display: inline-flex;
2271
+
2272
+ & button {
2273
+ background-color: transparent;
2274
+ color: ${({ theme }) => theme.color.text.secondary};
2275
+ }
2276
+
2277
+ & button:hover,
2278
+ & button:active {
2279
+ background-color: transparent;
2280
+ color: ${({ theme }) => theme.color.text.primary};
2281
+ }
2282
+
2283
+ ${({ $isOpen, theme }) => $isOpen && css`
2284
+ & button {
2285
+ background-color: transparent;
2286
+ color: ${theme.color.text.primary};
2287
+ }
2288
+ `}
2289
+ `;
2290
+ const FilterPickerMenu = ({ registry, onPickField, triggerLabel = "Filter", compact = false, disabled = false, visibleCustomFieldParents, excludeFieldIds, size, ...rest }) => {
2291
+ const resolvedSize = useFilterBarSize(size);
2292
+ const unfilteredOptions = useMemo(() => buildFieldPickerOptions(registry, visibleCustomFieldParents), [registry, visibleCustomFieldParents]);
2293
+ const options = useMemo(() => excludeFieldIds == null || excludeFieldIds.length === 0 ? unfilteredOptions : buildFieldPickerOptions(registry, visibleCustomFieldParents, excludeFieldIds), [
2294
+ registry,
2295
+ visibleCustomFieldParents,
2296
+ excludeFieldIds,
2297
+ unfilteredOptions
2298
+ ]);
2299
+ const handleChange = useCallback((value) => {
2300
+ if (value == null) return;
2301
+ const field = registry.get(value);
2302
+ if (!field) return;
2303
+ onPickField(field);
2304
+ }, [registry, onPickField]);
2305
+ if (options.length === 0 && unfilteredOptions.length > 0) return null;
2306
+ const trigger = compact ? /* @__PURE__ */ jsx(IconButton, {
2307
+ size: resolvedSize,
2308
+ disabled,
2309
+ "aria-label": triggerLabel,
2310
+ children: /* @__PURE__ */ jsx(CirclePlusIcon, {})
2311
+ }) : /* @__PURE__ */ jsx(Button, {
2312
+ variant: "text",
2313
+ size: resolvedSize,
2314
+ width: "auto",
2315
+ prefixIcon: /* @__PURE__ */ jsx(CirclePlusIcon, {}),
2316
+ disabled,
2317
+ children: triggerLabel
2318
+ });
2319
+ return /* @__PURE__ */ jsx(TriggerWrapper, {
2320
+ ...rest,
2321
+ $isOpen: false,
2322
+ children: /* @__PURE__ */ jsx(Combobox, {
2323
+ options,
2324
+ value: null,
2325
+ onChange: handleChange,
2326
+ size: resolvedSize,
2327
+ "aria-label": "Filter field picker",
2328
+ trigger
2329
+ })
2330
+ });
2331
+ };
2332
+ //#endregion
2333
+ //#region components/DataTable/TableControls/FiltersV2/PillShell/PillShell.tsx
2334
+ const PillRoot = styled.span`
2335
+ display: inline-flex;
2336
+ align-items: center;
2337
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].controlHeight};
2338
+ padding: 0 ${Spacing[1]} 0 ${Spacing[2]};
2339
+ gap: 2px;
2340
+ border-radius: ${BorderRadius.Md};
2341
+ ${({ $size }) => $size === "sm" ? Typography.TextSmall : Typography.TextMedium};
2342
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2343
+ max-width: 100%;
2344
+ cursor: pointer;
2345
+ user-select: none;
2346
+ transition: background-color ${"150ms"} ease-out;
2347
+
2348
+ /* Keyboard focus lands on the inner body button, so the visible focus
2349
+ ring is drawn on the whole pill via :focus-within. */
2350
+ ${focusWithinOutline};
2351
+
2352
+ ${({ $variant }) => $variant === "active" ? css`
2353
+ background-color: ${Color.CorePurple100};
2354
+ color: ${Color.TextActive};
2355
+ ` : css`
2356
+ background-color: ${Color.BackgroundSecondary};
2357
+ color: ${Color.TextPrimary};
2358
+
2359
+ &:hover {
2360
+ background-color: ${Color.BackgroundLabelGrey};
2361
+ }
2362
+ `}
2363
+ `;
2364
+ /**
2365
+ * The clickable body of the pill. Suppresses its own focus outline
2366
+ * (the parent `PillRoot` carries the visible focus ring via
2367
+ * `:focus-within`) and is otherwise a transparent wrapper that
2368
+ * inherits the pill's typography + color.
2369
+ */
2370
+ const PillBody = styled.button`
2371
+ display: inline-flex;
2372
+ align-items: center;
2373
+ gap: ${Spacing[1]};
2374
+ height: 100%;
2375
+ background: transparent;
2376
+ border: 0;
2377
+ padding: 0;
2378
+ margin: 0;
2379
+ appearance: none;
2380
+ color: inherit;
2381
+ font: inherit;
2382
+ cursor: pointer;
2383
+ min-width: 0;
2384
+ max-width: 100%;
2385
+
2386
+ &:focus-visible {
2387
+ outline: none;
2388
+ }
2389
+
2390
+ ${PillRoot}:focus-within & {
2391
+ outline: none;
2392
+ }
2393
+ `;
2394
+ /**
2395
+ * Square slot containing the trailing caret or dismiss glyph. Slot
2396
+ * size scales with the pill (`sm` = 16x16 / 12px glyph; `md` = 20x20
2397
+ * / 16px glyph) so the visual weight stays proportional to the pill
2398
+ * height.
2399
+ */
2400
+ const actionSlotStyles = css`
2401
+ display: inline-flex;
2402
+ align-items: center;
2403
+ justify-content: center;
2404
+ width: ${({ $size }) => $size === "sm" ? "16px" : "20px"};
2405
+ height: ${({ $size }) => $size === "sm" ? "16px" : "20px"};
2406
+ flex: 0 0 auto;
2407
+ border-radius: ${BorderRadius.Sm};
2408
+ color: inherit;
2409
+
2410
+ svg {
2411
+ width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};
2412
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};
2413
+ }
2414
+ `;
2415
+ const ActionSlot = styled.span`
2416
+ ${actionSlotStyles};
2417
+ `;
2418
+ const DismissibleCaretWrapper = styled(ActionSlot)`
2419
+ ${PillRoot}:hover &,
2420
+ ${PillRoot}[data-variant='active'] & {
2421
+ display: none;
2422
+ }
2423
+ `;
2424
+ const DismissButton$1 = styled.button`
2425
+ ${actionSlotStyles};
2426
+ display: none; /* see :hover / [data-variant='active'] overrides below */
2427
+ padding: 0;
2428
+ margin: 0;
2429
+ border: 0;
2430
+ appearance: none;
2431
+ background: transparent;
2432
+ color: inherit;
2433
+ font: inherit;
2434
+ cursor: pointer;
2435
+
2436
+ &:hover {
2437
+ background-color: ${Color.BackgroundButtonTextHover};
2438
+ }
2439
+
2440
+ ${focusOutline};
2441
+
2442
+ ${PillRoot}:hover &,
2443
+ ${PillRoot}[data-variant='active'] & {
2444
+ display: inline-flex;
2445
+ }
2446
+
2447
+ ${PillRoot}[data-variant='active'] &:hover {
2448
+ background-color: ${Color.CorePurple200};
2449
+ }
2450
+ `;
2451
+ const PillShell = forwardRef(function PillShell({ variant, children, bodyAriaLabel, onBodyClick, onDismiss, dismissAriaLabel, size, ...rest }, ref) {
2452
+ const ariaExpanded = rest["aria-expanded"];
2453
+ const resolvedSize = useFilterBarSize(size);
2454
+ const CaretIcon = resolvedSize === "sm" ? CaretDownIcon$1 : CaretDownIcon;
2455
+ const DismissIcon = resolvedSize === "sm" ? XIcon$1 : XIcon;
2456
+ const handleDismissClick = (event) => {
2457
+ event.stopPropagation();
2458
+ onDismiss?.();
2459
+ };
2460
+ const handleBodyKeyDown = (event) => {
2461
+ if (event.key === "Enter" || event.key === " ") event.stopPropagation();
2462
+ };
2463
+ return /* @__PURE__ */ jsxs(PillRoot, {
2464
+ ref,
2465
+ $variant: variant,
2466
+ $size: resolvedSize,
2467
+ "data-variant": variant,
2468
+ onClick: onBodyClick,
2469
+ ...rest,
2470
+ children: [/* @__PURE__ */ jsx(PillBody, {
2471
+ type: "button",
2472
+ onKeyDown: handleBodyKeyDown,
2473
+ "aria-label": bodyAriaLabel,
2474
+ "aria-haspopup": "dialog",
2475
+ "aria-expanded": ariaExpanded,
2476
+ children
2477
+ }), onDismiss ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DismissibleCaretWrapper, {
2478
+ "aria-hidden": "true",
2479
+ $size: resolvedSize,
2480
+ children: /* @__PURE__ */ jsx(CaretIcon, {})
2481
+ }), /* @__PURE__ */ jsx(DismissButton$1, {
2482
+ $size: resolvedSize,
2483
+ type: "button",
2484
+ onClick: handleDismissClick,
2485
+ "aria-label": dismissAriaLabel,
2486
+ children: /* @__PURE__ */ jsx(DismissIcon, {})
2487
+ })] }) : /* @__PURE__ */ jsx(ActionSlot, {
2488
+ "aria-hidden": "true",
2489
+ $size: resolvedSize,
2490
+ children: /* @__PURE__ */ jsx(CaretIcon, {})
2491
+ })]
2492
+ });
2493
+ });
2494
+ //#endregion
2495
+ //#region components/DataTable/TableControls/FiltersV2/FilterPill/FilterPill.tsx
2496
+ const FieldLabel = styled.span`
2497
+ max-width: 120px;
2498
+ flex: 0 1 auto;
2499
+ `;
2500
+ const OperatorLabel = styled.span`
2501
+ color: inherit;
2502
+ white-space: nowrap;
2503
+ flex: 0 0 auto;
2504
+ `;
2505
+ const ValueChipGroup = styled.span`
2506
+ display: inline-flex;
2507
+ align-items: center;
2508
+ gap: 2px;
2509
+ flex: 0 1 auto;
2510
+ `;
2511
+ const ValueChip = styled.span`
2512
+ display: inline-flex;
2513
+ align-items: center;
2514
+ justify-content: center;
2515
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};
2516
+ min-width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};
2517
+ max-width: 120px;
2518
+ padding: 0 ${Spacing[1]};
2519
+ border-radius: 3px;
2520
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
2521
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2522
+
2523
+ background-color: ${({ $variant }) => $variant === "active" ? Color.CorePurple200 : Color.CoreSlate200};
2524
+ color: ${({ $variant }) => $variant === "active" ? Color.TextActive : Color.TextPrimary};
2525
+ `;
2526
+ const OverflowChip = styled(ValueChip)`
2527
+ flex: 0 0 auto;
2528
+ `;
2529
+ const OverflowTooltipList = styled(Stack).attrs({
2530
+ as: "ul",
2531
+ spacing: Spacing[1]
2532
+ })`
2533
+ margin: 0;
2534
+ padding: 0;
2535
+ list-style: none;
2536
+
2537
+ & > li {
2538
+ margin: 0;
2539
+ padding: 0;
2540
+ }
2541
+ `;
2542
+ /**
2543
+ * Normalize a `FilterRuleValue` to a list of display strings, applying the
2544
+ * `optionLabels` lookup so the pill renders human-readable option labels
2545
+ * instead of raw option ids. Null / undefined collapses to an empty list.
2546
+ */
2547
+ function normalizeValueToDisplay(value, optionLabels) {
2548
+ if (value == null) return [];
2549
+ const lookup = (raw) => optionLabels?.[raw] ?? raw;
2550
+ if (Array.isArray(value)) {
2551
+ if (value.length > 0 && Array.isArray(value[0])) return [`${value.length} group${value.length === 1 ? "" : "s"}`];
2552
+ return value.map((entry) => lookup(String(entry)));
2553
+ }
2554
+ if (typeof value === "object") {
2555
+ const record = value;
2556
+ if (record.startDate && record.endDate) return [`${record.startDate} – ${record.endDate}`];
2557
+ if (record.startDate || record.endDate) return [record.startDate ?? record.endDate ?? ""];
2558
+ }
2559
+ if (typeof value === "boolean") return [value ? "True" : "False"];
2560
+ if (typeof value === "number") return [String(value)];
2561
+ return [lookup(value)];
2562
+ }
2563
+ /**
2564
+ * Accessible name builder used both for the pill body's `aria-label` and the
2565
+ * dismiss button's `aria-label`. We assemble a human sentence rather than
2566
+ * relying on child text nodes because the chip components don't always read
2567
+ * cleanly when concatenated by the AT.
2568
+ */
2569
+ function buildAccessibleName(field, rule, displayedValues) {
2570
+ if (rule == null) return field.label;
2571
+ if (!isValuelessOperator(rule.operator) && displayedValues.length === 0) return field.label;
2572
+ const operatorLabel = getOperatorLabel(rule.operator, field.type);
2573
+ if (isValuelessOperator(rule.operator)) return `${field.label} ${operatorLabel}`;
2574
+ return `${field.label} ${operatorLabel} ${displayedValues.join(", ")}`;
2575
+ }
2576
+ const FilterPill = forwardRef(function FilterPill({ field, rule, onClick, onDismiss, variant = "default", optionLabels, size, ...rest }, ref) {
2577
+ const reactId = useMemo(() => uniqueId("filter-pill-"), []);
2578
+ const resolvedSize = useFilterBarSize(size);
2579
+ const displayedValues = useMemo(() => rule && !isValuelessOperator(rule.operator) ? normalizeValueToDisplay(rule.value, optionLabels) : [], [rule, optionLabels]);
2580
+ const accessibleName = buildAccessibleName(field, rule, displayedValues);
2581
+ const hasRule = rule != null;
2582
+ const isComplete = hasRule && (isValuelessOperator(rule.operator) || displayedValues.length > 0);
2583
+ const firstValue = displayedValues[0];
2584
+ const overflowValues = displayedValues.slice(1);
2585
+ const overflowTooltipId = `${reactId}-overflow`;
2586
+ return /* @__PURE__ */ jsxs(PillShell, {
2587
+ ref,
2588
+ variant,
2589
+ size: resolvedSize,
2590
+ bodyAriaLabel: `Edit filter: ${accessibleName}`,
2591
+ onBodyClick: onClick,
2592
+ onDismiss,
2593
+ dismissAriaLabel: `Remove filter: ${accessibleName}`,
2594
+ ...rest,
2595
+ children: [
2596
+ /* @__PURE__ */ jsx(FieldLabel, { children: /* @__PURE__ */ jsx(TruncatedText, { children: field.label }) }),
2597
+ isComplete && hasRule && /* @__PURE__ */ jsx(OperatorLabel, { children: getOperatorLabel(rule.operator, field.type) }),
2598
+ isComplete && hasRule && !isValuelessOperator(rule.operator) && firstValue != null && /* @__PURE__ */ jsxs(ValueChipGroup, { children: [/* @__PURE__ */ jsx(ValueChip, {
2599
+ $variant: variant,
2600
+ $size: resolvedSize,
2601
+ children: /* @__PURE__ */ jsx(TruncatedText, { children: firstValue })
2602
+ }), overflowValues.length > 0 && /* @__PURE__ */ jsx(Tooltip, {
2603
+ trigger: /* @__PURE__ */ jsx(OverflowChip, {
2604
+ $variant: variant,
2605
+ $size: resolvedSize,
2606
+ "aria-describedby": overflowTooltipId,
2607
+ children: `+${overflowValues.length}`
2608
+ }),
2609
+ side: "bottom",
2610
+ hideArrow: true,
2611
+ children: /* @__PURE__ */ jsx(OverflowTooltipList, {
2612
+ id: overflowTooltipId,
2613
+ "aria-label": "Additional values",
2614
+ children: overflowValues.map((entry, index) => /* @__PURE__ */ jsx("li", { children: entry }, `${entry}-${index}`))
2615
+ })
2616
+ })] })
2617
+ ]
2618
+ });
2619
+ });
2620
+ //#endregion
2621
+ //#region components/DataTable/TableControls/FiltersV2/FilterPopover/FilterPopover.tsx
2622
+ const PopoverPanel = styled(Stack).attrs({ spacing: Spacing[0] })`
2623
+ min-width: ${"196px"};
2624
+ max-width: ${"320px"};
2625
+ /* The design-system Popover.Card already supplies bg, border, shadow,
2626
+ and 6px corner radius — we just constrain the inner content. */
2627
+ `;
2628
+ const Main = styled(Stack).attrs({ spacing: Spacing[1] })`
2629
+ /* Valueless operators have no input below the header — symmetric padding
2630
+ keeps the popover tight. Valued operators keep extra bottom padding so
2631
+ the control's baseline has breathing room before the edge or footer. */
2632
+ padding: ${({ $valueless }) => $valueless ? Spacing[2] : `${Spacing[2]} ${Spacing[2]} ${Spacing[3]}`};
2633
+ `;
2634
+ const HeaderRow = styled(HStack).attrs({
2635
+ align: "center",
2636
+ spacing: Spacing[1]
2637
+ })`
2638
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2639
+ padding: 0 ${Spacing[1]};
2640
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
2641
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2642
+ color: ${Color.TextSecondary};
2643
+ white-space: nowrap;
2644
+ `;
2645
+ const FieldTypeLabel = styled.span`
2646
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
2647
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2648
+ color: ${Color.TextSecondary};
2649
+ white-space: nowrap;
2650
+ flex: 0 1 auto;
2651
+ min-width: 0;
2652
+ `;
2653
+ /**
2654
+ * Inline operator picker — a text button (sized to the resolved
2655
+ * filter-bar size) with a trailing caret that opens a `DropdownMenu`
2656
+ * of operator options. Uses `DropdownMenu` rather than the design-system
2657
+ * `Select` so the menu auto-sizes to the longest operator label
2658
+ * (`is_not_empty` etc.) instead of inheriting the trigger's narrow
2659
+ * width, which clipped labels to "is e..." in the previous styling.
2660
+ */
2661
+ const InlineOperatorTrigger = styled.button`
2662
+ display: inline-flex;
2663
+ align-items: center;
2664
+ gap: 2px;
2665
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2666
+ padding: 0 ${Spacing[1]};
2667
+ margin: 0;
2668
+ border: 0;
2669
+ border-radius: ${BorderRadius.Sm};
2670
+ appearance: none;
2671
+ background: transparent;
2672
+ color: ${Color.TextPrimary};
2673
+ font-family: inherit;
2674
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
2675
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2676
+ cursor: pointer;
2677
+
2678
+ &:hover {
2679
+ background: ${Color.BackgroundSecondary};
2680
+ }
2681
+
2682
+ &[data-state='open'] {
2683
+ background: ${Color.BackgroundLabelGrey};
2684
+ }
2685
+
2686
+ &:focus-visible {
2687
+ outline: 2px solid ${Color.BorderFocus};
2688
+ outline-offset: 1px;
2689
+ }
2690
+
2691
+ svg {
2692
+ width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};
2693
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].iconSize};
2694
+ flex-shrink: 0;
2695
+ }
2696
+ `;
2697
+ const ValueSlot = styled.div`
2698
+ padding: 0 ${Spacing[1]};
2699
+ `;
2700
+ const Footer = styled(HStack).attrs({
2701
+ align: "center",
2702
+ spacing: Spacing[1]
2703
+ })`
2704
+ padding: 6px ${Spacing[2]};
2705
+ border-top: 1px solid ${Color.BorderDivider};
2706
+ color: ${Color.TextSecondary};
2707
+ ${paragraphMixins.xs};
2708
+
2709
+ svg {
2710
+ flex-shrink: 0;
2711
+ }
2712
+ `;
2713
+ /**
2714
+ * The single-rule editor popover. Renders a Radix `Popover` anchored on
2715
+ * `trigger`, with a `Popover.Card` body that stacks:
2716
+ *
2717
+ * 1. Inline header — "[Field name] [operator ▾]" on one line.
2718
+ * 2. Parent-supplied value control.
2719
+ * 3. Custom-field footer (`ⓘ [label] is a field on [parentRecordType]`).
2720
+ *
2721
+ * The popover stays purely presentational. Rule state lives in the parent's
2722
+ * `useFilterStateV2()` hook; this component just routes operator changes
2723
+ * back through `onChangeOperator` and forwards open/close transitions
2724
+ * through Radix's controlled props.
2725
+ */
2726
+ const FilterPopover = ({ field, operator, onChangeOperator, valueControlSlot, onClose, trigger, open, onOpenChange, size }) => {
2727
+ const resolvedSize = useFilterBarSize(size);
2728
+ const valueless = isValuelessOperator(operator);
2729
+ const CaretIcon = resolvedSize === "sm" ? CaretDownIcon$1 : CaretDownIcon;
2730
+ const InfoIcon = resolvedSize === "sm" ? CircleInfoIcon$1 : CircleInfoIcon;
2731
+ const showOperatorSelector = fieldHasMultipleOperators(field);
2732
+ const operatorOptions = useMemo(() => getOperatorsForField(field), [field]);
2733
+ const handleOpenChange = useCallback((next) => {
2734
+ onOpenChange?.(next);
2735
+ if (!next) onClose();
2736
+ }, [onOpenChange, onClose]);
2737
+ const valueSlotRef = useRef(null);
2738
+ useEffect(() => {
2739
+ if (open !== true || valueless) return;
2740
+ const handle = requestAnimationFrame(() => {
2741
+ const root = valueSlotRef.current;
2742
+ if (!root) return;
2743
+ root.querySelector("input:not([disabled]), [contenteditable=\"true\"], [tabindex]:not([tabindex=\"-1\"])")?.focus();
2744
+ });
2745
+ return () => cancelAnimationFrame(handle);
2746
+ }, [
2747
+ open,
2748
+ field.id,
2749
+ valueless
2750
+ ]);
2751
+ const handleKeyDown = (event) => {
2752
+ if (event.key !== "Enter") return;
2753
+ const target = event.target;
2754
+ if (!target || target.tagName !== "INPUT") return;
2755
+ const input = target;
2756
+ if (input.type === "checkbox" || input.type === "radio") return;
2757
+ if (input.getAttribute("role") === "combobox") return;
2758
+ event.preventDefault();
2759
+ handleOpenChange(false);
2760
+ };
2761
+ return /* @__PURE__ */ jsxs(Popover_default, {
2762
+ open,
2763
+ onOpenChange: handleOpenChange,
2764
+ children: [/* @__PURE__ */ jsx(Popover_default.Trigger, {
2765
+ asChild: true,
2766
+ children: trigger
2767
+ }), /* @__PURE__ */ jsx(Popover_default.Card, {
2768
+ align: "start",
2769
+ sideOffset: 4,
2770
+ "aria-label": `Edit filter for ${field.label}`,
2771
+ noPadding: true,
2772
+ children: /* @__PURE__ */ jsxs(PopoverPanel, {
2773
+ onKeyDown: handleKeyDown,
2774
+ children: [/* @__PURE__ */ jsxs(Main, {
2775
+ $valueless: valueless,
2776
+ "data-test": "filter-popover__main",
2777
+ children: [/* @__PURE__ */ jsxs(HeaderRow, {
2778
+ $size: resolvedSize,
2779
+ children: [/* @__PURE__ */ jsx(FieldTypeLabel, {
2780
+ $size: resolvedSize,
2781
+ children: /* @__PURE__ */ jsx(TruncatedText, { children: field.label })
2782
+ }), showOperatorSelector ? /* @__PURE__ */ jsx(DropdownMenu_default, {
2783
+ trigger: /* @__PURE__ */ jsxs(InlineOperatorTrigger, {
2784
+ type: "button",
2785
+ "aria-label": "Operator",
2786
+ $size: resolvedSize,
2787
+ children: [getOperatorLabel(operator, field.type), /* @__PURE__ */ jsx(CaretIcon, { "aria-hidden": "true" })]
2788
+ }),
2789
+ align: "start",
2790
+ portal: true,
2791
+ children: operatorOptions.map((op) => /* @__PURE__ */ jsx(DropdownMenu_default.Item, {
2792
+ size: resolvedSize,
2793
+ onClick: () => onChangeOperator(op),
2794
+ children: getOperatorLabel(op, field.type)
2795
+ }, op))
2796
+ }) : /* @__PURE__ */ jsx("span", { children: getOperatorLabel(operator, field.type) })]
2797
+ }), !valueless ? /* @__PURE__ */ jsx(ValueSlot, {
2798
+ ref: valueSlotRef,
2799
+ children: valueControlSlot
2800
+ }) : null]
2801
+ }), field.source === "custom" && field.parentRecordType != null && /* @__PURE__ */ jsxs(Footer, { children: [/* @__PURE__ */ jsx(InfoIcon, { "aria-hidden": "true" }), /* @__PURE__ */ jsxs(TruncatedText, { children: [
2802
+ field.label,
2803
+ " is a field on ",
2804
+ field.parentRecordType
2805
+ ] })] })]
2806
+ })
2807
+ })]
2808
+ });
2809
+ };
2810
+ //#endregion
2811
+ //#region components/DataTable/TableControls/FiltersV2/RulesPill/RulesPill.tsx
2812
+ /**
2813
+ * Total rule count across every AndGroup in the compound expression.
2814
+ *
2815
+ * Empty groups contribute zero (they're pruned at adapter serialization time
2816
+ * anyway). The number drives the count chip's visibility.
2817
+ */
2818
+ function countRules(compound) {
2819
+ let n = 0;
2820
+ for (const group of compound.groups) n += group.rules.length;
2821
+ return n;
2822
+ }
2823
+ const Label = styled.span`
2824
+ flex: 0 0 auto;
2825
+ `;
2826
+ const CountChip = styled.span`
2827
+ display: inline-flex;
2828
+ align-items: center;
2829
+ justify-content: center;
2830
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};
2831
+ min-width: ${({ $size }) => FILTER_SIZE_TOKENS[$size].chipHeight};
2832
+ padding: 0 ${Spacing[1]};
2833
+ border-radius: 3px;
2834
+ font-size: ${({ $size }) => FILTER_SIZE_TOKENS[$size].fontSize};
2835
+ line-height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].lineHeight};
2836
+ flex: 0 0 auto;
2837
+
2838
+ background-color: ${({ $variant }) => $variant === "active" ? Color.CorePurple200 : Color.CoreSlate200};
2839
+ color: ${({ $variant }) => $variant === "active" ? Color.TextActive : Color.TextPrimary};
2840
+ `;
2841
+ /**
2842
+ * Always-visible filter pill that owns the entire compound (DNF) expression.
2843
+ *
2844
+ * Composes `PillShell` for the rounded variant-aware container, the
2845
+ * `:focus-within` outline, and the trailing caret↔dismiss swap that's
2846
+ * identical to `FilterPill`. The pill-specific body content is just
2847
+ * the "Rules" label + an optional count chip.
2848
+ *
2849
+ * Visual states:
2850
+ * - `enabled === false` → renders `null` (the owning view has opted out of
2851
+ * Advanced Filter Rules).
2852
+ * - resting (no popover, no rules) → gray pill, label `Rules`, caret `▾`.
2853
+ * - resting (no popover, N rules) → gray pill, label `Rules` + `[N]` chip,
2854
+ * caret `▾`.
2855
+ * - hover (no popover) → gray-hover bg, caret stays visible.
2856
+ * - active (popover open) → "ube" purple pill, `TextActive` color, purple
2857
+ * `[N]` chip when N > 0, caret stays visible.
2858
+ *
2859
+ * The pill itself owns no popover state — parents place it inside an
2860
+ * `AdvancedFilterRulesPopover` (or any other popover container) and wire
2861
+ * `onClick` / `isOpen` themselves.
2862
+ *
2863
+ * RulesPill does not expose a dismiss action; clicking the pill toggles
2864
+ * the popover.
2865
+ */
2866
+ const RulesPill = forwardRef(function RulesPill({ compound, enabled, onClick, isOpen = false, "aria-label": ariaLabel, "data-test": dataTest, size, ...rest }, ref) {
2867
+ const resolvedSize = useFilterBarSize(size);
2868
+ if (!enabled) return null;
2869
+ const count = countRules(compound);
2870
+ const hasCount = count > 0;
2871
+ const variant = isOpen ? "active" : "default";
2872
+ const accessibleName = hasCount ? `Rules ${count}` : "Rules";
2873
+ return /* @__PURE__ */ jsxs(PillShell, {
2874
+ ref,
2875
+ variant,
2876
+ size: resolvedSize,
2877
+ bodyAriaLabel: ariaLabel ?? accessibleName,
2878
+ onBodyClick: onClick,
2879
+ "data-test": dataTest ?? "rules-pill__trigger",
2880
+ "aria-expanded": isOpen,
2881
+ ...rest,
2882
+ children: [/* @__PURE__ */ jsx(Label, { children: "Rules" }), hasCount && /* @__PURE__ */ jsx(CountChip, {
2883
+ $variant: variant,
2884
+ $size: resolvedSize,
2885
+ "data-test": "rules-pill__count",
2886
+ children: count
2887
+ })]
2888
+ });
2889
+ });
2890
+ //#endregion
2891
+ //#region components/DataTable/TableControls/FiltersV2/types.ts
2892
+ /** The empty state — no filters applied. */
2893
+ const EMPTY_FILTER_STATE = Object.freeze({
2894
+ topLevelRules: [],
2895
+ compound: Object.freeze({ groups: [] })
2896
+ });
2897
+ //#endregion
2898
+ //#region components/DataTable/TableControls/FiltersV2/validation.ts
2899
+ /**
2900
+ * Shared runtime validators for `FilterStateV2`, consumed by the URL
2901
+ * codec, the saved-view dual-write helpers, and `useFilterStateV2`.
2902
+ *
2903
+ * Validation is defense-in-depth: the type system prevents bad shapes
2904
+ * in code we control, but URL state and saved-view blobs are external
2905
+ * input — corrupted bookmarks, bad clipboard pastes, future-build
2906
+ * rules rolled back to an older build, attacker-crafted params — and
2907
+ * the validators are the last line of defense before anything reaches
2908
+ * the hook, the bar, or the adapter.
2909
+ */
2910
+ const OPERATOR_SET = new Set([
2911
+ "is",
2912
+ "is_not",
2913
+ "contains",
2914
+ "does_not_contain",
2915
+ "is_empty",
2916
+ "is_not_empty",
2917
+ "is_true",
2918
+ "is_false",
2919
+ "before",
2920
+ "after"
2921
+ ]);
2922
+ /**
2923
+ * Returns `true` when `value` is a structurally-valid `FilterStateV2`,
2924
+ * including per-rule content validation. A `topLevelRules` element
2925
+ * with a non-string `fieldId`, an operator not in the known
2926
+ * vocabulary, or a value of an unsupported type is rejected — a
2927
+ * shallow shape sniff would let those reach the adapter.
2928
+ */
2929
+ function isFilterStateV2(value) {
2930
+ if (typeof value !== "object" || value == null) return false;
2931
+ const v = value;
2932
+ if (!Array.isArray(v.topLevelRules)) return false;
2933
+ if (!v.topLevelRules.every(isTopLevelFilterRule)) return false;
2934
+ if (typeof v.compound !== "object" || v.compound == null) return false;
2935
+ const compound = v.compound;
2936
+ if (!Array.isArray(compound.groups)) return false;
2937
+ if (!compound.groups.every(isAndGroup)) return false;
2938
+ return true;
2939
+ }
2940
+ function isAndGroup(value) {
2941
+ if (typeof value !== "object" || value == null) return false;
2942
+ const v = value;
2943
+ if (!Array.isArray(v.rules)) return false;
2944
+ return v.rules.every(isFilterRule);
2945
+ }
2946
+ function isFilterRule(value) {
2947
+ if (typeof value !== "object" || value == null) return false;
2948
+ const v = value;
2949
+ if (typeof v.fieldId !== "string" || v.fieldId.length === 0) return false;
2950
+ if (typeof v.operator !== "string" || !OPERATOR_SET.has(v.operator)) return false;
2951
+ if (!isFilterRuleValue(v.value)) return false;
2952
+ return true;
2953
+ }
2954
+ function isTopLevelFilterRule(value) {
2955
+ if (!isFilterRule(value)) return false;
2956
+ const v = value;
2957
+ return typeof v.id === "string" && v.id.length > 0;
2958
+ }
2959
+ function isFilterRuleValue(value) {
2960
+ if (value == null) return true;
2961
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return true;
2962
+ if (Array.isArray(value)) {
2963
+ if (value.length === 0) return true;
2964
+ if (value.every((entry) => typeof entry === "string")) return true;
2965
+ return value.every((group) => Array.isArray(group) && group.every((entry) => typeof entry === "object" && entry != null && !Array.isArray(entry)));
2966
+ }
2967
+ if (typeof value === "object") {
2968
+ const record = value;
2969
+ if ("startDate" in record || "endDate" in record) {
2970
+ const { startDate, endDate } = record;
2971
+ return (startDate == null || typeof startDate === "string") && (endDate == null || typeof endDate === "string");
2972
+ }
2973
+ }
2974
+ return false;
2975
+ }
2976
+ /**
2977
+ * Strip rules referencing unregistered `fieldId`s from a decoded state.
2978
+ * Pairs with `isFilterStateV2` for defense-in-depth: even after the
2979
+ * shape guard passes, a rule with a `fieldId` that doesn't exist in the
2980
+ * current resource's registry would silently render nothing in the UI
2981
+ * but still reach the adapter and ship to the backend. Pruning closes
2982
+ * that gap.
2983
+ *
2984
+ * Empty AND-groups created by pruning are also dropped, since the
2985
+ * adapter prunes them on serialize anyway and the editor UI hides
2986
+ * empty groups too.
2987
+ *
2988
+ * Skips its own work and returns the input unchanged when `registry`
2989
+ * is `undefined` — useful for callers that hydrate before the registry
2990
+ * is built.
2991
+ *
2992
+ * For valueless operators (`is_empty`, etc.) the value contract is
2993
+ * `null`. Non-valueless operators keep in-progress draft values (an empty
2994
+ * string / empty array) so a pill the user is mid-editing survives the
2995
+ * report/hydrate round-trip and stays visible — top-level and compound
2996
+ * rules are treated alike here, and the serialize boundary
2997
+ * (`hasCompleteValue`) is what drops incomplete rules from the request.
2998
+ */
2999
+ function pruneToRegistry(state, registry) {
3000
+ if (!registry) return state;
3001
+ const coerced = coerceBooleanRules(state, registry);
3002
+ return {
3003
+ topLevelRules: coerced.topLevelRules.filter((rule) => isRuleAllowed(rule, registry, { allowDraftValues: true })),
3004
+ compound: { groups: coerced.compound.groups.map((group) => ({ rules: group.rules.filter((rule) => isRuleAllowed(rule, registry, { allowDraftValues: true })) })).filter((group) => group.rules.length > 0) }
3005
+ };
3006
+ }
3007
+ /**
3008
+ * Normalizes boolean-field rules into the in-memory contract the new UI
3009
+ * and adapter expect — `is` / `is_not` + a real boolean `value`. Two
3010
+ * legacy shapes are coerced, both only for rules whose registered field
3011
+ * type is `boolean`:
3012
+ *
3013
+ * - Pre–value-control rules using the `is_true` / `is_false` operators
3014
+ * (from saved views) become `is` + boolean `value` so they survive
3015
+ * operator-vocabulary pruning and render in the new UI.
3016
+ * - v1-URL bookmarks hydrate query params as strings, so
3017
+ * `filter[custom][active]=true` arrives as `{ operator: 'is', value:
3018
+ * 'true' }`. The string is coerced back to a boolean so the adapter
3019
+ * emits the legacy `is_true` / `is_false` wire operator instead of
3020
+ * shipping the raw string (which would break old boolean bookmarks).
3021
+ * Non-`'true'`/`'false'` strings are left as-is and dropped later by
3022
+ * `isRuleAllowed`.
3023
+ */
3024
+ function coerceBooleanRule(rule, registry) {
3025
+ const field = registry.get(rule.fieldId);
3026
+ if (!field || field.type !== "boolean") return rule;
3027
+ if (rule.operator === "is_true") return {
3028
+ ...rule,
3029
+ operator: "is",
3030
+ value: true
3031
+ };
3032
+ if (rule.operator === "is_false") return {
3033
+ ...rule,
3034
+ operator: "is",
3035
+ value: false
3036
+ };
3037
+ if (rule.operator === "is" || rule.operator === "is_not") {
3038
+ if (rule.value === "true") return {
3039
+ ...rule,
3040
+ value: true
3041
+ };
3042
+ if (rule.value === "false") return {
3043
+ ...rule,
3044
+ value: false
3045
+ };
3046
+ }
3047
+ return rule;
3048
+ }
3049
+ function coerceBooleanRules(state, registry) {
3050
+ return {
3051
+ topLevelRules: state.topLevelRules.map((r) => coerceBooleanRule(r, registry)),
3052
+ compound: { groups: state.compound.groups.map((g) => ({ rules: g.rules.map((r) => coerceBooleanRule(r, registry)) })) }
3053
+ };
3054
+ }
3055
+ function isDraftRuleValue(rule, registry) {
3056
+ if (isValuelessOperator(rule.operator)) return false;
3057
+ const field = registry.get(rule.fieldId);
3058
+ if (!field) return false;
3059
+ switch (field.type) {
3060
+ case "multi_choices":
3061
+ case "tags_conditions": return Array.isArray(rule.value) && rule.value.length === 0;
3062
+ case "date": return rule.value === "" || rule.value == null;
3063
+ case "date_range": return false;
3064
+ case "boolean": return false;
3065
+ default: return rule.value === "" || rule.value == null;
3066
+ }
3067
+ }
3068
+ function isRuleAllowed(rule, registry, options = { allowDraftValues: false }) {
3069
+ if (!registry.has(rule.fieldId)) return false;
3070
+ if (!registry.operatorsFor(rule.fieldId).includes(rule.operator)) return false;
3071
+ if (isValuelessOperator(rule.operator)) return rule.value == null;
3072
+ if (options.allowDraftValues && isDraftRuleValue(rule, registry)) return true;
3073
+ if (registry.get(rule.fieldId)?.type === "boolean") return typeof rule.value === "boolean";
3074
+ if (registry.get(rule.fieldId)?.type === "date") return typeof rule.value === "string" && rule.value.length > 0;
3075
+ if (registry.get(rule.fieldId)?.type === "multi_choices") {
3076
+ if (Array.isArray(rule.value)) return rule.value.length > 0;
3077
+ return typeof rule.value === "string" && rule.value.length > 0;
3078
+ }
3079
+ if (registry.get(rule.fieldId)?.type === "date_range") {
3080
+ const value = rule.value;
3081
+ if (value == null || typeof value !== "object" || Array.isArray(value)) return false;
3082
+ const { startDate, endDate } = value;
3083
+ return typeof startDate === "string" && startDate.length > 0 && typeof endDate === "string" && endDate.length > 0;
3084
+ }
3085
+ if (registry.get(rule.fieldId)?.type === "tags_conditions") return Array.isArray(rule.value) && rule.value.length > 0;
3086
+ return rule.value != null && typeof rule.value !== "boolean";
3087
+ }
3088
+ /**
3089
+ * Whether `rule` carries a complete value for its field type — the
3090
+ * serialize-boundary predicate `pruneEmptyRulesForSerialize` uses to drop
3091
+ * half-edited rules from the request (a value-requiring operator like
3092
+ * `is_not` with no value yet makes the backend reject the whole request).
3093
+ *
3094
+ * Deliberately stricter than `isRuleAllowed`'s hydration policy, which keeps
3095
+ * an empty string so an in-progress pill survives the state round-trip and
3096
+ * stays visible for the user to finish. Checks value completeness only — it
3097
+ * does not gate operator vocabulary or registry membership.
3098
+ */
3099
+ function hasCompleteValue(rule, registry) {
3100
+ if (isValuelessOperator(rule.operator)) return rule.value == null;
3101
+ const { value } = rule;
3102
+ if (value == null) return false;
3103
+ switch (registry.get(rule.fieldId)?.type) {
3104
+ case "boolean": return typeof value === "boolean";
3105
+ case "date": return typeof value === "string" && value.length > 0;
3106
+ case "multi_choices": return Array.isArray(value) ? value.length > 0 : typeof value === "string" && value.length > 0;
3107
+ case "tags_conditions": return Array.isArray(value) && value.length > 0;
3108
+ case "date_range": {
3109
+ if (typeof value !== "object" || Array.isArray(value)) return false;
3110
+ const { startDate, endDate } = value;
3111
+ return typeof startDate === "string" && startDate.length > 0 && typeof endDate === "string" && endDate.length > 0;
3112
+ }
3113
+ default:
3114
+ if (typeof value === "string") return value.length > 0;
3115
+ if (Array.isArray(value)) return value.length > 0;
3116
+ return typeof value !== "boolean";
3117
+ }
3118
+ }
3119
+ //#endregion
3120
+ //#region components/DataTable/TableControls/FiltersV2/useFilterStateV2.ts
3121
+ const nextRuleId = () => `top-rule-${v4()}`;
3122
+ /**
3123
+ * Owns `FilterStateV2` for a filter surface and exposes a small mutator API.
3124
+ *
3125
+ * When `advancedRulesEnabled` is false, `compound.groups` is forced to
3126
+ * `[]`.
3127
+ *
3128
+ * Putting that invariant here (rather than in the components) keeps
3129
+ * `TableControls/FiltersV2` callers from accidentally leaking compound state when
3130
+ * the owning view has opted out.
3131
+ *
3132
+ * The mutator surface is deliberately small: top-level rules get
3133
+ * upsert/remove, the compound expression gets whole-value writes. That
3134
+ * matches how the UI emits changes — simple pills mutate one rule at a
3135
+ * time; the rules popover always emits a full compound expression as
3136
+ * one `onChange`.
3137
+ *
3138
+ * A pill the user has picked but not yet valued is held by the bar rather
3139
+ * than committed. Which pills those are is recorded when the picker mints
3140
+ * them rather than inferred: they are never reported, so incoming state never
3141
+ * describes one and hydration has nothing to reconcile against them. They
3142
+ * stay in the same row as the committed pills, so giving one a value doesn't
3143
+ * move it.
3144
+ */
3145
+ function useFilterStateV2(options) {
3146
+ const { initialState = EMPTY_FILTER_STATE, advancedRulesEnabled = true, registry } = options;
3147
+ const [internal, setInternal] = useState(() => ({
3148
+ all: pruneToRegistry(initialState, registry),
3149
+ heldIds: /* @__PURE__ */ new Set()
3150
+ }));
3151
+ const { all, heldIds } = internal;
3152
+ const lastHydratedState = useRef(all);
3153
+ useEffect(() => {
3154
+ const nextHydratedState = pruneToRegistry(initialState, registry);
3155
+ const hydrate = !isEqual(nextHydratedState, lastHydratedState.current);
3156
+ if (hydrate) lastHydratedState.current = nextHydratedState;
3157
+ setInternal((prev) => {
3158
+ const pruned = pruneHeldRules(prev, registry);
3159
+ return hydrate ? withHeldRules(nextHydratedState, pruned) : pruned;
3160
+ });
3161
+ }, [initialState, registry]);
3162
+ const state = useMemo(() => enforceAdvancedRulesEnabled(all, advancedRulesEnabled), [all, advancedRulesEnabled]);
3163
+ return {
3164
+ state,
3165
+ committedState: useMemo(() => heldIds.size === 0 ? state : {
3166
+ ...state,
3167
+ topLevelRules: state.topLevelRules.filter((rule) => !heldIds.has(rule.id))
3168
+ }, [state, heldIds]),
3169
+ advancedRulesEnabled,
3170
+ setState: useCallback((next) => {
3171
+ setInternal({
3172
+ all: pruneToRegistry(next, registry),
3173
+ heldIds: /* @__PURE__ */ new Set()
3174
+ });
3175
+ }, [registry]),
3176
+ setCompound: useCallback((compound) => {
3177
+ setInternal((prev) => ({
3178
+ ...prev,
3179
+ all: {
3180
+ ...prev.all,
3181
+ compound
3182
+ }
3183
+ }));
3184
+ }, []),
3185
+ reset: useCallback(() => {
3186
+ setInternal({
3187
+ all: {
3188
+ topLevelRules: [],
3189
+ compound: { groups: [] }
3190
+ },
3191
+ heldIds: /* @__PURE__ */ new Set()
3192
+ });
3193
+ }, []),
3194
+ addTopLevelRule: useCallback((rule) => {
3195
+ const id = nextRuleId();
3196
+ const added = {
3197
+ ...rule,
3198
+ id
3199
+ };
3200
+ setInternal((prev) => ({
3201
+ all: {
3202
+ ...prev.all,
3203
+ topLevelRules: [...prev.all.topLevelRules, added]
3204
+ },
3205
+ heldIds: isHeldRule(added) ? withId(prev.heldIds, id) : prev.heldIds
3206
+ }));
3207
+ return id;
3208
+ }, []),
3209
+ updateTopLevelRule: useCallback((id, rule) => {
3210
+ setInternal((prev) => {
3211
+ const idx = prev.all.topLevelRules.findIndex((r) => r.id === id);
3212
+ if (idx < 0) return prev;
3213
+ const topLevelRules = [...prev.all.topLevelRules];
3214
+ topLevelRules[idx] = {
3215
+ ...rule,
3216
+ id
3217
+ };
3218
+ const heldIds = isHeldRule(rule) ? withId(prev.heldIds, id) : withoutId(prev.heldIds, id);
3219
+ return {
3220
+ all: {
3221
+ ...prev.all,
3222
+ topLevelRules
3223
+ },
3224
+ heldIds
3225
+ };
3226
+ });
3227
+ }, []),
3228
+ removeTopLevelRule: useCallback((id) => {
3229
+ setInternal((prev) => {
3230
+ const topLevelRules = prev.all.topLevelRules.filter((r) => r.id !== id);
3231
+ if (topLevelRules.length === prev.all.topLevelRules.length) return prev;
3232
+ return {
3233
+ all: {
3234
+ ...prev.all,
3235
+ topLevelRules
3236
+ },
3237
+ heldIds: prev.heldIds.has(id) ? withoutId(prev.heldIds, id) : prev.heldIds
3238
+ };
3239
+ });
3240
+ }, [])
3241
+ };
3242
+ }
3243
+ /**
3244
+ * A pill the picker minted that has no value yet. `null` and not "empty":
3245
+ * `''` and `[]` are values a user can choose, and a filter cleared to one is
3246
+ * still a filter.
3247
+ */
3248
+ function isHeldRule(rule) {
3249
+ return !isValuelessOperator(rule.operator) && rule.value == null;
3250
+ }
3251
+ function heldRulesOf(state) {
3252
+ return state.heldIds.size === 0 ? [] : state.all.topLevelRules.filter((rule) => state.heldIds.has(rule.id));
3253
+ }
3254
+ /**
3255
+ * Lays incoming committed rules into the row, keeping the held pills where the
3256
+ * user left them: a held pill goes back after however many committed rules
3257
+ * preceded it before. An id the incoming state now uses is the parent's, so the
3258
+ * held pill of that id gives way rather than duplicating it.
3259
+ */
3260
+ function withHeldRules(committed, prev) {
3261
+ if (prev.heldIds.size === 0) return {
3262
+ all: committed,
3263
+ heldIds: prev.heldIds
3264
+ };
3265
+ const incoming = committed.topLevelRules;
3266
+ const incomingIds = new Set(incoming.map((rule) => rule.id));
3267
+ const topLevelRules = [];
3268
+ const heldIds = /* @__PURE__ */ new Set();
3269
+ let taken = 0;
3270
+ let committedBefore = 0;
3271
+ prev.all.topLevelRules.forEach((rule) => {
3272
+ if (!prev.heldIds.has(rule.id)) {
3273
+ committedBefore += 1;
3274
+ return;
3275
+ }
3276
+ if (incomingIds.has(rule.id)) return;
3277
+ while (taken < committedBefore && taken < incoming.length) {
3278
+ topLevelRules.push(incoming[taken]);
3279
+ taken += 1;
3280
+ }
3281
+ topLevelRules.push(rule);
3282
+ heldIds.add(rule.id);
3283
+ });
3284
+ if (heldIds.size === 0) return {
3285
+ all: committed,
3286
+ heldIds
3287
+ };
3288
+ while (taken < incoming.length) {
3289
+ topLevelRules.push(incoming[taken]);
3290
+ taken += 1;
3291
+ }
3292
+ return {
3293
+ all: {
3294
+ ...committed,
3295
+ topLevelRules
3296
+ },
3297
+ heldIds
3298
+ };
3299
+ }
3300
+ /**
3301
+ * Drops held pills whose field or operator the registry no longer supports,
3302
+ * preserving the state's identity when there are none so an unchanged registry
3303
+ * can't loop the effect.
3304
+ */
3305
+ function pruneHeldRules(state, registry) {
3306
+ const droppedIds = new Set(heldRulesOf(state).filter((rule) => !registry.has(rule.fieldId) || !registry.operatorsFor(rule.fieldId).includes(rule.operator)).map((rule) => rule.id));
3307
+ if (droppedIds.size === 0) return state;
3308
+ const heldIds = new Set(state.heldIds);
3309
+ droppedIds.forEach((id) => heldIds.delete(id));
3310
+ return {
3311
+ all: {
3312
+ ...state.all,
3313
+ topLevelRules: state.all.topLevelRules.filter((rule) => !droppedIds.has(rule.id))
3314
+ },
3315
+ heldIds
3316
+ };
3317
+ }
3318
+ function withId(ids, id) {
3319
+ return ids.has(id) ? ids : new Set(ids).add(id);
3320
+ }
3321
+ function withoutId(ids, id) {
3322
+ if (!ids.has(id)) return ids;
3323
+ const next = new Set(ids);
3324
+ next.delete(id);
3325
+ return next;
3326
+ }
3327
+ function enforceAdvancedRulesEnabled(state, advancedRulesEnabled) {
3328
+ if (advancedRulesEnabled) return state;
3329
+ if (state.compound.groups.length === 0) return state;
3330
+ return {
3331
+ ...state,
3332
+ compound: { groups: [] }
3333
+ };
3334
+ }
3335
+ //#endregion
3336
+ //#region components/DataTable/TableControls/FiltersV2/FilterBar/FilterBar.tsx
3337
+ const Bar = styled.div`
3338
+ display: flex;
3339
+ align-items: center;
3340
+ gap: ${Spacing[2]};
3341
+ flex-wrap: nowrap;
3342
+ min-width: 0;
3343
+ padding: ${Spacing[2]} 0;
3344
+ `;
3345
+ const SCROLL_FADE_WIDTH = 48;
3346
+ const SCROLL_SETTLE_FALLBACK_MS = 400;
3347
+ const POPOVER_CLOSE_BUFFER_PX = 8;
3348
+ const PILL_FOCUS_RING_SPACE = 3;
3349
+ /**
3350
+ * Builds the `mask-image` gradient that fades the scroll track's edges.
3351
+ *
3352
+ * A `mask-image` (rather than a same-colored overlay painted on top) fades
3353
+ * the track's *entire rendered output* — pill backgrounds, borders, and any
3354
+ * focus ring that bleeds into the padding above — because masking
3355
+ * composites against the real pixels the element paints, instead of
3356
+ * relying on an opaque sibling layer to visually cover them. An overlay
3357
+ * approach only hides whatever happens to sit below it in paint order;
3358
+ * a mask fades everything, including outlines.
3359
+ */
3360
+ const buildEdgeMaskImage = (showLeftFade, showRightFade) => {
3361
+ return `linear-gradient(to right, ${showLeftFade ? `transparent 0, black ${SCROLL_FADE_WIDTH}px` : "black 0"}, ${showRightFade ? `black calc(100% - ${SCROLL_FADE_WIDTH}px), transparent 100%` : "black 100%"})`;
3362
+ };
3363
+ const PillsScrollRegion = styled.div`
3364
+ display: flex;
3365
+ align-items: center;
3366
+ gap: ${Spacing[1]};
3367
+ flex: 0 1 auto;
3368
+ min-width: 0;
3369
+ width: max-content;
3370
+ max-width: 100%;
3371
+ `;
3372
+ const PillsScrollTrack = styled.div`
3373
+ display: flex;
3374
+ align-items: center;
3375
+ flex: 1 1 auto;
3376
+ min-width: 0;
3377
+ flex-wrap: nowrap;
3378
+ gap: ${Spacing[1]};
3379
+ overflow-x: auto;
3380
+ overflow-y: hidden;
3381
+ -webkit-overflow-scrolling: touch;
3382
+ scrollbar-width: none;
3383
+ padding: ${PILL_FOCUS_RING_SPACE}px;
3384
+ margin: -${PILL_FOCUS_RING_SPACE}px;
3385
+ -webkit-mask-image: ${({ $showLeftFade, $showRightFade }) => buildEdgeMaskImage($showLeftFade, $showRightFade)};
3386
+ mask-image: ${({ $showLeftFade, $showRightFade }) => buildEdgeMaskImage($showLeftFade, $showRightFade)};
3387
+ transition:
3388
+ -webkit-mask-image ${"200ms"} ease-out,
3389
+ mask-image ${"200ms"} ease-out;
3390
+
3391
+ & > * {
3392
+ flex: 0 0 auto;
3393
+ }
3394
+
3395
+ &::-webkit-scrollbar {
3396
+ display: none;
3397
+ }
3398
+ `;
3399
+ const Divider = styled.div`
3400
+ width: 1px;
3401
+ height: ${({ $size }) => FILTER_SIZE_TOKENS[$size].controlHeight};
3402
+ background: ${Color.BorderDivider};
3403
+ flex: 0 0 auto;
3404
+ margin: 0 ${({ $flush }) => $flush ? 0 : Spacing[1]};
3405
+ `;
3406
+ const PickerSlot = styled.div`
3407
+ flex: 0 0 auto;
3408
+ `;
3409
+ const EmptyTrailingGroup = styled.div`
3410
+ display: flex;
3411
+ align-items: center;
3412
+ gap: ${Spacing[1]};
3413
+ flex: 0 0 auto;
3414
+ `;
3415
+ /**
3416
+ * Returns the previous array whenever its contents still match, so the field
3417
+ * ids can be derived on every render without giving the picker a new array to
3418
+ * rebuild its whole option tree from. Editing a pill's value rewrites the
3419
+ * rules while leaving the fields in use unchanged.
3420
+ */
3421
+ function useStableFieldIds(fieldIds) {
3422
+ const stable = useRef(fieldIds);
3423
+ const previous = stable.current;
3424
+ if (previous == null || fieldIds == null || previous.length !== fieldIds.length || fieldIds.some((id, index) => previous[index] !== id)) stable.current = fieldIds;
3425
+ return stable.current;
3426
+ }
3427
+ function FilterBar({ registry, initialState, onChange, advancedRulesEnabled = true, singleUseFields = false, size = "md", valueControlResolver }) {
3428
+ const filterState = useFilterStateV2({
3429
+ registry,
3430
+ initialState,
3431
+ advancedRulesEnabled
3432
+ });
3433
+ const [editingRuleId, setEditingRuleId] = useState(null);
3434
+ const [rulesPopoverOpen, setRulesPopoverOpen] = useState(false);
3435
+ const pillNodesRef = useRef(/* @__PURE__ */ new Map());
3436
+ const onChangeRef = useRef(onChange);
3437
+ useEffect(() => {
3438
+ onChangeRef.current = onChange;
3439
+ }, [onChange]);
3440
+ const { committedState } = filterState;
3441
+ const lastReportedState = useRef(committedState);
3442
+ useEffect(() => {
3443
+ if (isEqual(lastReportedState.current, committedState)) return;
3444
+ lastReportedState.current = committedState;
3445
+ onChangeRef.current?.(committedState);
3446
+ }, [committedState]);
3447
+ const pendingEditRuleIdRef = useRef(null);
3448
+ const openedViaScrollIntoViewRef = useRef(false);
3449
+ const handlePickField = (field) => {
3450
+ pendingEditRuleIdRef.current = filterState.addTopLevelRule({
3451
+ fieldId: field.id,
3452
+ operator: registry.defaultOperatorFor(field.id),
3453
+ value: null
3454
+ });
3455
+ };
3456
+ const hasPills = filterState.state.topLevelRules.length > 0;
3457
+ const excludeFieldIds = useStableFieldIds(singleUseFields ? filterState.state.topLevelRules.map((rule) => rule.fieldId) : void 0);
3458
+ const pillsScrollRef = useRef(null);
3459
+ const { hasHorizontalOverflow, hasMoreScrollLeft, hasMoreScrollRight } = useScrollOverflow(pillsScrollRef, { enabled: hasPills });
3460
+ const ruleCount = filterState.state.topLevelRules.length;
3461
+ const previousRuleCountRef = useRef(ruleCount);
3462
+ useEffect(() => {
3463
+ const grew = ruleCount > previousRuleCountRef.current;
3464
+ previousRuleCountRef.current = ruleCount;
3465
+ if (!grew || pendingEditRuleIdRef.current == null) return;
3466
+ const openPendingRule = () => {
3467
+ openedViaScrollIntoViewRef.current = true;
3468
+ setEditingRuleId(pendingEditRuleIdRef.current);
3469
+ pendingEditRuleIdRef.current = null;
3470
+ };
3471
+ const track = pillsScrollRef.current;
3472
+ if (!track || !track.scrollTo) {
3473
+ openPendingRule();
3474
+ return;
3475
+ }
3476
+ const maxScrollLeft = Math.max(track.scrollWidth - track.clientWidth, 0);
3477
+ if (Math.abs(track.scrollLeft - maxScrollLeft) <= 1) {
3478
+ openPendingRule();
3479
+ return;
3480
+ }
3481
+ let settled = false;
3482
+ const finish = () => {
3483
+ if (settled) return;
3484
+ settled = true;
3485
+ track.removeEventListener("scrollend", finish);
3486
+ window.clearTimeout(fallbackTimer);
3487
+ openPendingRule();
3488
+ };
3489
+ track.addEventListener("scrollend", finish, { once: true });
3490
+ const fallbackTimer = window.setTimeout(finish, SCROLL_SETTLE_FALLBACK_MS);
3491
+ track.scrollTo({
3492
+ left: track.scrollWidth,
3493
+ behavior: "smooth"
3494
+ });
3495
+ return () => {
3496
+ track.removeEventListener("scrollend", finish);
3497
+ window.clearTimeout(fallbackTimer);
3498
+ };
3499
+ }, [ruleCount]);
3500
+ useEffect(() => {
3501
+ if (editingRuleId == null) return;
3502
+ const root = pillsScrollRef.current;
3503
+ const target = pillNodesRef.current.get(editingRuleId);
3504
+ if (!root || !target || typeof IntersectionObserver === "undefined") return;
3505
+ let skipInitialReport = openedViaScrollIntoViewRef.current;
3506
+ openedViaScrollIntoViewRef.current = false;
3507
+ const observer = new IntersectionObserver(([entry]) => {
3508
+ if (skipInitialReport) {
3509
+ skipInitialReport = false;
3510
+ return;
3511
+ }
3512
+ if (entry && entry.intersectionRatio < 1) setEditingRuleId(null);
3513
+ }, {
3514
+ root,
3515
+ threshold: 1,
3516
+ rootMargin: `0px ${POPOVER_CLOSE_BUFFER_PX}px 0px ${POPOVER_CLOSE_BUFFER_PX}px`
3517
+ });
3518
+ observer.observe(target);
3519
+ return () => observer.disconnect();
3520
+ }, [editingRuleId]);
3521
+ useLayoutEffect(() => {
3522
+ if (editingRuleId == null) return;
3523
+ pillNodesRef.current.get(editingRuleId)?.scrollIntoView?.({
3524
+ block: "nearest",
3525
+ inline: "nearest"
3526
+ });
3527
+ }, [editingRuleId, useMemo(() => editingRuleId == null ? null : filterState.state.topLevelRules.find((rule) => rule.id === editingRuleId)?.value ?? null, [editingRuleId, filterState.state.topLevelRules])]);
3528
+ const visibleCustomFieldParents = useMemo(() => deriveVisibleCustomFieldParents(registry, filterState.state.topLevelRules), [registry, filterState.state.topLevelRules]);
3529
+ return /* @__PURE__ */ jsx(FilterBarContext.Provider, {
3530
+ value: { size },
3531
+ children: /* @__PURE__ */ jsxs(Bar, {
3532
+ role: "toolbar",
3533
+ "aria-label": "Filter bar",
3534
+ children: [filterState.advancedRulesEnabled ? /* @__PURE__ */ jsx(AdvancedFilterRulesPopover, {
3535
+ registry,
3536
+ compound: filterState.state.compound,
3537
+ open: rulesPopoverOpen,
3538
+ onOpenChange: setRulesPopoverOpen,
3539
+ onChange: (compound) => {
3540
+ filterState.setCompound(compound);
3541
+ },
3542
+ renderValueControl: (field, operator, value, onChange) => resolveValueControl({
3543
+ field,
3544
+ operator,
3545
+ value,
3546
+ onChange,
3547
+ layout: "inline"
3548
+ }, valueControlResolver),
3549
+ trigger: /* @__PURE__ */ jsx(RulesPill, {
3550
+ compound: filterState.state.compound,
3551
+ enabled: true,
3552
+ isOpen: rulesPopoverOpen
3553
+ })
3554
+ }) : null, hasPills ? /* @__PURE__ */ jsxs(Fragment, { children: [filterState.advancedRulesEnabled ? /* @__PURE__ */ jsx(Divider, {
3555
+ "aria-hidden": "true",
3556
+ $size: size
3557
+ }) : null, /* @__PURE__ */ jsxs(PillsScrollRegion, {
3558
+ "data-test": "filter-bar-pills-scroll-region",
3559
+ children: [/* @__PURE__ */ jsx(PillsScrollTrack, {
3560
+ ref: pillsScrollRef,
3561
+ "data-test": "filter-bar-pills-scroll-track",
3562
+ $showLeftFade: hasMoreScrollLeft,
3563
+ $showRightFade: hasHorizontalOverflow && hasMoreScrollRight,
3564
+ children: filterState.state.topLevelRules.map((rule) => {
3565
+ const field = registry.get(rule.fieldId);
3566
+ if (!field) return null;
3567
+ const optionLabels = registry.optionLabelsFor(field.id);
3568
+ const isOpen = editingRuleId === rule.id;
3569
+ return /* @__PURE__ */ jsx(FilterPopover, {
3570
+ field,
3571
+ operator: rule.operator,
3572
+ onChangeOperator: (op) => {
3573
+ filterState.updateTopLevelRule(rule.id, {
3574
+ ...rule,
3575
+ operator: op,
3576
+ value: isValuelessOperator(op) ? null : rule.value ?? emptyValueForFieldType(field.type)
3577
+ });
3578
+ },
3579
+ valueControlSlot: resolveValueControl({
3580
+ field,
3581
+ operator: rule.operator,
3582
+ value: rule.value,
3583
+ onChange: (value) => filterState.updateTopLevelRule(rule.id, {
3584
+ ...rule,
3585
+ value
3586
+ }),
3587
+ onCommit: () => setEditingRuleId(null)
3588
+ }, valueControlResolver),
3589
+ onClose: () => setEditingRuleId(null),
3590
+ open: isOpen,
3591
+ onOpenChange: (open) => setEditingRuleId(open ? rule.id : null),
3592
+ trigger: /* @__PURE__ */ jsx(FilterPill, {
3593
+ ref: (node) => {
3594
+ if (node) pillNodesRef.current.set(rule.id, node);
3595
+ else pillNodesRef.current.delete(rule.id);
3596
+ },
3597
+ field,
3598
+ rule,
3599
+ variant: isOpen ? "active" : "default",
3600
+ optionLabels,
3601
+ onDismiss: () => filterState.removeTopLevelRule(rule.id)
3602
+ })
3603
+ }, rule.id);
3604
+ })
3605
+ }), /* @__PURE__ */ jsx(PickerSlot, { children: /* @__PURE__ */ jsx(FilterPickerMenu, {
3606
+ registry,
3607
+ onPickField: handlePickField,
3608
+ compact: true,
3609
+ visibleCustomFieldParents,
3610
+ excludeFieldIds
3611
+ }) })]
3612
+ })] }) : filterState.advancedRulesEnabled ? /* @__PURE__ */ jsxs(EmptyTrailingGroup, { children: [/* @__PURE__ */ jsx(Divider, {
3613
+ "aria-hidden": "true",
3614
+ $size: size,
3615
+ $flush: true
3616
+ }), /* @__PURE__ */ jsx(PickerSlot, { children: /* @__PURE__ */ jsx(FilterPickerMenu, {
3617
+ registry,
3618
+ onPickField: handlePickField,
3619
+ visibleCustomFieldParents,
3620
+ excludeFieldIds
3621
+ }) })] }) : /* @__PURE__ */ jsx(PickerSlot, { children: /* @__PURE__ */ jsx(FilterPickerMenu, {
3622
+ registry,
3623
+ onPickField: handlePickField,
3624
+ visibleCustomFieldParents,
3625
+ excludeFieldIds
3626
+ }) })]
3627
+ })
3628
+ });
3629
+ }
3630
+ /**
3631
+ * The parent labels the picker's Fields submenu should keep visible,
3632
+ * derived from active `is` pills on scoping selector fields
3633
+ * ({@link FieldRegistry.narrowingSelectorFields}). Each selected option
3634
+ * value is a backend record-type/template id, resolved to its parent
3635
+ * label via {@link FieldRegistry.parentRecordLabelForId}.
3636
+ *
3637
+ * Returns `undefined` only when no `is` selector pill is active (show
3638
+ * everything). An active pill always returns an array, possibly empty:
3639
+ * selecting a scope with no custom fields narrows to *nothing*, not to
3640
+ * everything — conflating the two would leak other scopes' fields in.
3641
+ *
3642
+ * Only `is` narrows; multiple pills union their parents.
3643
+ */
3644
+ function deriveVisibleCustomFieldParents(registry, topLevelRules) {
3645
+ const selectorFields = registry.narrowingSelectorFields();
3646
+ if (selectorFields.length === 0 || topLevelRules.length === 0) return;
3647
+ const selectorIds = new Set(selectorFields.map((f) => f.id));
3648
+ const allowedParents = /* @__PURE__ */ new Set();
3649
+ let hasActiveSelectorRule = false;
3650
+ for (const rule of topLevelRules) {
3651
+ if (!selectorIds.has(rule.fieldId)) continue;
3652
+ if (rule.operator !== "is") continue;
3653
+ hasActiveSelectorRule = true;
3654
+ const values = Array.isArray(rule.value) ? rule.value : [rule.value];
3655
+ for (const value of values) {
3656
+ if (typeof value !== "string") continue;
3657
+ const parentLabel = registry.parentRecordLabelForId(value);
3658
+ if (parentLabel != null) allowedParents.add(parentLabel);
3659
+ }
3660
+ }
3661
+ return hasActiveSelectorRule ? Array.from(allowedParents) : void 0;
3662
+ }
3663
+ //#endregion
3664
+ //#region components/DataTable/TableControls/FiltersV2/FilterBar/index.ts
3665
+ var FilterBar_default = FilterBar;
3666
+ //#endregion
3667
+ //#region components/DataTable/TableControls/FiltersV2/FieldRegistry.ts
3668
+ /**
3669
+ * Per-resource field registry.
3670
+ *
3671
+ * Built from the backend's `field_key_to_info` payload (extended in v2 to
3672
+ * include `type`, `options`, `item_type`, and a `source`/`parent_record_type`
3673
+ * pair for custom fields). The registry is the single place the UI looks up
3674
+ * "what field is this and what can the user do with it" — value control
3675
+ * rendering, operator vocabulary, picker grouping, and popover footer text
3676
+ * all route through here.
3677
+ *
3678
+ * Construction is tolerant of partial metadata: if `type` is missing the
3679
+ * field falls back to `'string'`.
3680
+ */
3681
+ var FieldRegistry = class {
3682
+ constructor(resource, fields) {
3683
+ this.optionLabelCache = /* @__PURE__ */ new Map();
3684
+ this.resource = resource;
3685
+ this.byId = /* @__PURE__ */ new Map();
3686
+ this.customByParent = /* @__PURE__ */ new Map();
3687
+ this.parentLabelByRecordId = /* @__PURE__ */ new Map();
3688
+ this.systemFields = [];
3689
+ const parentRecordIds = /* @__PURE__ */ new Set();
3690
+ for (const field of fields) {
3691
+ this.byId.set(field.id, field);
3692
+ if (field.source === "custom") {
3693
+ const parent = field.parentRecordType ?? "";
3694
+ const bucket = this.customByParent.get(parent) ?? [];
3695
+ bucket.push(field);
3696
+ this.customByParent.set(parent, bucket);
3697
+ if (field.parentRecordId) {
3698
+ parentRecordIds.add(field.parentRecordId);
3699
+ if (field.parentRecordType) this.parentLabelByRecordId.set(field.parentRecordId, field.parentRecordType);
3700
+ }
3701
+ } else this.systemFields.push(field);
3702
+ }
3703
+ this.narrowingSelectors = [];
3704
+ if (parentRecordIds.size > 0) for (const field of fields) {
3705
+ if (!field.options || field.options.length === 0) continue;
3706
+ if (field.options.some((opt) => parentRecordIds.has(opt.value))) this.narrowingSelectors.push(field);
3707
+ }
3708
+ }
3709
+ parentRecordLabelForId(recordId) {
3710
+ return this.parentLabelByRecordId.get(recordId);
3711
+ }
3712
+ has(fieldId) {
3713
+ return this.byId.has(fieldId);
3714
+ }
3715
+ get(fieldId) {
3716
+ return this.byId.get(fieldId);
3717
+ }
3718
+ /**
3719
+ * Get a field by id, throwing if it isn't registered. Use this when the
3720
+ * fieldId came from state we own (e.g. an existing `FilterRule`) and a
3721
+ * missing field is a programming error rather than user input.
3722
+ */
3723
+ getOrThrow(fieldId) {
3724
+ const field = this.byId.get(fieldId);
3725
+ if (!field) throw new Error(`FieldRegistry(${this.resource}): unknown fieldId "${fieldId}"`);
3726
+ return field;
3727
+ }
3728
+ /** All registered fields, in insertion order. */
3729
+ all() {
3730
+ return Array.from(this.byId.values());
3731
+ }
3732
+ /** System / built-in fields, used as the top section of the `⊕ Filter` menu. */
3733
+ systemFieldsList() {
3734
+ return this.systemFields;
3735
+ }
3736
+ /** Custom fields grouped by parent record type for the picker submenu. */
3737
+ customFieldGroups() {
3738
+ return Array.from(this.customByParent.entries()).map(([parent, fields]) => ({
3739
+ parent,
3740
+ fields
3741
+ }));
3742
+ }
3743
+ /**
3744
+ * Fields that drive the picker's field-narrowing. A field is inferred
3745
+ * as a scoping selector (e.g. `account_type`, `case_template`) when its
3746
+ * `options[].value` set intersects the registry's custom-field
3747
+ * `parentRecordId`s — matching on the backend id, not the display label,
3748
+ * so a suffixed or colliding label (`"KYC Standard (CAS)"`) still
3749
+ * narrows correctly. `FilterBar` turns an active `is` pill on such a
3750
+ * field into the visible parent labels via {@link parentRecordLabelForId}.
3751
+ *
3752
+ * A coincidental id collision would falsely tag a field as a selector —
3753
+ * benign (it just narrows too); layer on a backend flag if ever needed.
3754
+ */
3755
+ narrowingSelectorFields() {
3756
+ return this.narrowingSelectors;
3757
+ }
3758
+ /** Operator vocabulary for a registered field, gated by its `allowedOperators` then type. */
3759
+ operatorsFor(fieldId) {
3760
+ return getOperatorsForField(this.getOrThrow(fieldId));
3761
+ }
3762
+ /** Default operator for a registered field. Used when creating a new pill. */
3763
+ defaultOperatorFor(fieldId) {
3764
+ const [defaultOperator] = getOperatorsForField(this.getOrThrow(fieldId));
3765
+ if (defaultOperator == null) throw new Error(`FieldRegistry: no operators available for field "${fieldId}"`);
3766
+ return defaultOperator;
3767
+ }
3768
+ /**
3769
+ * Pick the operator to use for a rule after a field swap. If the
3770
+ * previous operator is still in the new field's vocabulary, keep it
3771
+ * (the user's intent likely carries over — e.g. `is_empty` stays
3772
+ * `is_empty` regardless of field type). Otherwise fall back to the
3773
+ * field's default operator.
3774
+ *
3775
+ * Lives on the registry rather than as a free helper because the
3776
+ * answer is entirely a function of registry-owned data (operator
3777
+ * vocabulary per type) — and centralizing it keeps the field-swap
3778
+ * semantics consistent across `FilterBar.handlePickField`,
3779
+ * `AdvancedFilterRulesPopover.handleFieldChange`, and any future
3780
+ * caller.
3781
+ */
3782
+ reconcileOperator(fieldId, prevOperator) {
3783
+ return this.operatorsFor(fieldId).includes(prevOperator) ? prevOperator : this.defaultOperatorFor(fieldId);
3784
+ }
3785
+ /**
3786
+ * Build a `value → label` lookup for a `choices` / `multi_choices`
3787
+ * field, suitable for translating raw option ids into the human
3788
+ * labels rendered by `FilterPill` chips and value-control headers.
3789
+ * Returns `undefined` when the field has no options so callers can
3790
+ * skip the lookup entirely.
3791
+ *
3792
+ * Memoized per-field so repeated reads from render loops don't
3793
+ * rebuild the same map. Field options are immutable for the lifetime
3794
+ * of a `FieldRegistry`, so the cache never needs invalidation.
3795
+ */
3796
+ optionLabelsFor(fieldId) {
3797
+ const cached = this.optionLabelCache.get(fieldId);
3798
+ if (cached != null) return cached === EMPTY_OPTION_LABELS ? void 0 : cached;
3799
+ const field = this.byId.get(fieldId);
3800
+ if (!field?.options || field.options.length === 0) {
3801
+ this.optionLabelCache.set(fieldId, EMPTY_OPTION_LABELS);
3802
+ return;
3803
+ }
3804
+ const map = {};
3805
+ for (const opt of field.options) map[opt.value] = opt.label;
3806
+ this.optionLabelCache.set(fieldId, map);
3807
+ return map;
3808
+ }
3809
+ };
3810
+ const EMPTY_OPTION_LABELS = Object.freeze({});
3811
+ /**
3812
+ * Build a registry from a `field_key_to_info` map. Forgiving by design — any
3813
+ * key whose `type` is missing or unrecognized falls back to `'string'`, and
3814
+ * `source` defaults to `'custom'` (current `customFilters` are all custom).
3815
+ */
3816
+ function buildFieldRegistry(resource, fieldKeyToInfo, options) {
3817
+ const apiFields = Object.entries(fieldKeyToInfo).map(([id, raw]) => rawFieldInfoToFilterField(id, raw));
3818
+ return new FieldRegistry(resource, [...options?.systemFields ?? [], ...apiFields]);
3819
+ }
3820
+ function rawFieldInfoToFilterField(id, raw) {
3821
+ const type = normalizeFieldType(raw.type);
3822
+ const itemType = raw.item_type ? normalizeFieldType(raw.item_type) : void 0;
3823
+ const source = normalizeFieldSource(raw.source);
3824
+ return {
3825
+ id,
3826
+ label: raw.label,
3827
+ type,
3828
+ source,
3829
+ options: raw.options,
3830
+ itemType,
3831
+ parentRecordType: raw.parent_record_type,
3832
+ parentRecordId: raw.parent_record_id,
3833
+ path: raw.path
3834
+ };
3835
+ }
3836
+ const KNOWN_TYPES = new Set([
3837
+ "string",
3838
+ "email",
3839
+ "choices",
3840
+ "multi_choices",
3841
+ "boolean",
3842
+ "integer",
3843
+ "float",
3844
+ "date",
3845
+ "array",
3846
+ "tags_conditions",
3847
+ "date_range"
3848
+ ]);
3849
+ function normalizeFieldType(raw) {
3850
+ if (raw && KNOWN_TYPES.has(raw)) return raw;
3851
+ return "string";
3852
+ }
3853
+ function normalizeFieldSource(raw) {
3854
+ return raw === "system" ? "system" : "custom";
3855
+ }
3856
+ //#endregion
3857
+ export { DataTableCompactBar as S, useTableControls as _, hasCompleteValue as a, TableControls as b, EMPTY_FILTER_STATE as c, getDefaultOperatorForType as d, getOperatorsForField as f, TableControlsProvider as g, TableControlsContext as h, useFilterStateV2 as i, resolveValueControl as l, isValuelessOperator as m, buildFieldRegistry as n, isFilterStateV2 as o, getOperatorsForType as p, FilterBar_default as r, pruneToRegistry as s, FieldRegistry as t, useFilterBarSize as u, TableViewConfiguration as v, ControlBar as x, TableViewConfigurationDropdown as y };
3858
+
3859
+ //# sourceMappingURL=TableControls-DHMs7o58.mjs.map