@marimo-team/islands 0.23.9-dev2 → 0.23.9-dev4

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 (233) hide show
  1. package/dist/{ConnectedDataExplorerComponent-2lBNiUv6.js → ConnectedDataExplorerComponent-OzrfMM5L.js} +20 -20
  2. package/dist/ErrorBoundary-rULOrC_p.js +175 -0
  3. package/dist/{ImageComparisonComponent-CNHIsPDj.js → ImageComparisonComponent-CHrI72em.js} +1 -1
  4. package/dist/{Plot-4wn-lMVn.js → Plot-CAYS29h9.js} +1 -1
  5. package/dist/{_baseUniq-CxZRxRRo.js → _baseUniq-B_2Hw7zG.js} +3 -3
  6. package/dist/{any-language-editor-VWs_7v27.js → any-language-editor-DfdpyDv_.js} +23 -23
  7. package/dist/architecture-7HQA4BMR-Kyc44TmC.js +6 -0
  8. package/dist/{architectureDiagram-VXUJARFQ-CXVJxFhH.js → architectureDiagram-VXUJARFQ-CT2SuxNw.js} +15 -15
  9. package/dist/{arrays-CldYf7p7.js → arrays-sEtDRoG4.js} +1 -1
  10. package/dist/{blockDiagram-VD42YOAC-DGDaxR8I.js → blockDiagram-VD42YOAC-Dy7hlFla.js} +7 -7
  11. package/dist/{button-Dj4BTre0.js → button-C5K9fIPF.js} +2 -2
  12. package/dist/{c4Diagram-YG6GDRKO-C2hc6ne8.js → c4Diagram-YG6GDRKO-BXlAmZ8Z.js} +4 -4
  13. package/dist/{capabilities-C9rrYCzf.js → capabilities-BceAxrAW.js} +2 -2
  14. package/dist/{channel-BBoIVUrJ.js → channel-D_PHgcig.js} +1 -1
  15. package/dist/{chat-ui-D3XBept8.js → chat-ui-BDI3FMI8.js} +29 -29
  16. package/dist/{check-BcUIXnUT.js → check-DTbrK0zt.js} +1 -1
  17. package/dist/{chunk-4F5CHEZ2-BZq7Kom7.js → chunk-4F5CHEZ2-D9nGEHV8.js} +1 -1
  18. package/dist/{chunk-5FQGJX7Z-BOg95xG5.js → chunk-5FQGJX7Z-BNjes6Yx.js} +5 -5
  19. package/dist/{chunk-ABZYJK2D-D0cLy8Bb.js → chunk-ABZYJK2D-Dz0-H2B5.js} +1 -1
  20. package/dist/{chunk-ATLVNIR6-BXsEjlHF.js → chunk-ATLVNIR6-o0Z5MZLd.js} +1 -1
  21. package/dist/{chunk-B2363JML-D9-XOau1.js → chunk-B2363JML-KEJpLGGP.js} +1 -1
  22. package/dist/{chunk-B4BG7PRW-Q1usn6T3.js → chunk-B4BG7PRW-BL98U9B4.js} +4 -4
  23. package/dist/{chunk-DI55MBZ5-D1qLYNrb.js → chunk-DI55MBZ5-Dwkn0LWm.js} +4 -4
  24. package/dist/{chunk-EXTU4WIE-BKNXdLmD.js → chunk-EXTU4WIE-9sNjmQrB.js} +1 -1
  25. package/dist/{chunk-FRFDVMJY-BSBUAX7r.js → chunk-FRFDVMJY-DzQqMWrl.js} +1 -1
  26. package/dist/{chunk-JA3XYJ7Z-D6c6cOBG.js → chunk-JA3XYJ7Z-C32Y7Epf.js} +2 -2
  27. package/dist/{chunk-JZLCHNYA-BvsPHJmL.js → chunk-JZLCHNYA-C6ftyVMN.js} +4 -4
  28. package/dist/{chunk-N4CR4FBY-8ycT-O9a.js → chunk-N4CR4FBY-DUhGZhZs.js} +5 -5
  29. package/dist/{chunk-PL6DKKU2-B0MTXvyc.js → chunk-PL6DKKU2-D7km-08O.js} +1 -1
  30. package/dist/{chunk-QN33PNHL-Bb-eUBW3.js → chunk-QN33PNHL-0K6SDYn3.js} +1 -1
  31. package/dist/{chunk-QXUST7PY-DV8yRwBd.js → chunk-QXUST7PY-DMhsRpYK.js} +5 -5
  32. package/dist/{chunk-S3R3BYOJ-mQeCz5CE.js → chunk-S3R3BYOJ-oAe3dEbO.js} +3 -3
  33. package/dist/{chunk-SJTYNZTY-CEG4F0pB.js → chunk-SJTYNZTY-BkJrPRFC.js} +1 -1
  34. package/dist/{chunk-TCCFYFTB-d3HOqL2I.js → chunk-TCCFYFTB-D58KeXnC.js} +6 -6
  35. package/dist/{chunk-TQ3KTPDO-DiCtqVSi.js → chunk-TQ3KTPDO-D_yA_wAb.js} +1 -1
  36. package/dist/{chunk-TZMSLE5B-BqW10dHe.js → chunk-TZMSLE5B-yBKS_DQU.js} +1 -1
  37. package/dist/{chunk-UMXZTB3W-97iS1iEl.js → chunk-UMXZTB3W-D7uwvNjd.js} +1 -1
  38. package/dist/{classDiagram-2ON5EDUG--Yh__LHb.js → classDiagram-2ON5EDUG-QjoAcuFE.js} +10 -10
  39. package/dist/{classDiagram-v2-WZHVMYZB-BC7X7Xtc.js → classDiagram-v2-WZHVMYZB-bUCv4gu2.js} +10 -10
  40. package/dist/{clone-BuIIsfA8.js → clone-Q4Fqwn6q.js} +1 -1
  41. package/dist/{code-block-37QAKDTI-BsGy1AOJ.js → code-block-37QAKDTI-m92Yc8pv.js} +2 -2
  42. package/dist/{code-visibility-Dt0Aq6-t.js → code-visibility-VZebNmSs.js} +7073 -7439
  43. package/dist/{constants-D0gkYoE2.js → constants-T20xxyNf.js} +2 -2
  44. package/dist/{copy-DLf4aN7I.js → copy-BuQpJEzp.js} +2 -2
  45. package/dist/{dagre-6UL2VRFP-DRBWoQUw.js → dagre-6UL2VRFP-J0JKgwOt.js} +11 -11
  46. package/dist/{dagre-VYEPqXIV.js → dagre-By_QsQgc.js} +11 -11
  47. package/dist/{data-grid-overlay-editor-efe5ZagF.js → data-grid-overlay-editor-mfEJ5475.js} +2 -2
  48. package/dist/{diagram-PSM6KHXK-H66ATWP2.js → diagram-PSM6KHXK-DYgJuNk9.js} +18 -18
  49. package/dist/{diagram-QEK2KX5R-DItl5Wns.js → diagram-QEK2KX5R-CKdBR2sb.js} +14 -14
  50. package/dist/{diagram-S2PKOQOG-CtuW_ZuL.js → diagram-S2PKOQOG-Dpi7mo5W.js} +14 -14
  51. package/dist/dist-0Fif7jnk.js +5 -0
  52. package/dist/{dist-Dh3wkoyH.js → dist-4j4c7bjm.js} +2 -2
  53. package/dist/{dist-CDFZi-QD.js → dist-B3P2fFpz.js} +1 -1
  54. package/dist/{dist-BNyrZfqT.js → dist-B3pZ0Ab6.js} +2 -2
  55. package/dist/dist-B5h_9sHB.js +6 -0
  56. package/dist/dist-B9M6R5ye.js +5 -0
  57. package/dist/dist-BCt3tnck.js +8 -0
  58. package/dist/{dist-BrBucRXs.js → dist-BTfv03uy.js} +2 -2
  59. package/dist/dist-BUIJwMwn.js +8 -0
  60. package/dist/{dist-CYEylvZA.js → dist-BbbIBDiQ.js} +1 -1
  61. package/dist/{dist-KnujRhFL.js → dist-BcuoonNH.js} +4 -4
  62. package/dist/{dist-DJ6zJQZ4.js → dist-Bde4a2kU.js} +2 -2
  63. package/dist/{dist-t_qL7eB8.js → dist-Bfwsv11D.js} +2 -2
  64. package/dist/{dist-CNtV21T_.js → dist-BhM8gdSO.js} +4 -4
  65. package/dist/{dist-nuW5EDYT.js → dist-BotSqB48.js} +2 -2
  66. package/dist/dist-BpquMd3k.js +5 -0
  67. package/dist/dist-BzJsqYfz.js +5 -0
  68. package/dist/{dist-D029TiHd.js → dist-Bz_sYWbr.js} +2 -2
  69. package/dist/{dist-D3ZI9nhS.js → dist-C1BYNeCR.js} +4 -4
  70. package/dist/{dist-Bc5pmZIw.js → dist-C5VC_yzu.js} +1 -1
  71. package/dist/dist-CA5ELXAf.js +6 -0
  72. package/dist/dist-CLBRs6Uv.js +5 -0
  73. package/dist/{dist-Dhk6FMb0.js → dist-CLJWPTX2.js} +3 -3
  74. package/dist/{dist-C34oIrQ9.js → dist-CLUtPrdy.js} +1 -1
  75. package/dist/dist-CStVCMbq.js +5 -0
  76. package/dist/{dist-B8RaFTRF.js → dist-CUCNs1ja.js} +2 -2
  77. package/dist/dist-CZRIEY3Y.js +8 -0
  78. package/dist/{dist-UcOPnRMa.js → dist-CcXxepx6.js} +3 -3
  79. package/dist/dist-CuUHbFD0.js +5 -0
  80. package/dist/{dist-B8BjrFUE.js → dist-Cy1WxgBD.js} +5 -5
  81. package/dist/{dist-WdPUFc56.js → dist-D4CewLk6.js} +1 -1
  82. package/dist/{dist-DMZNjfX4.js → dist-DRfcqpxJ.js} +2 -2
  83. package/dist/dist-DV7Iabxb.js +8 -0
  84. package/dist/{dist-usPCDYx8.js → dist-D_bzzWBm.js} +1 -1
  85. package/dist/{dist-BvCfQQQE.js → dist-DgnE8F-r.js} +1 -1
  86. package/dist/{dist-JEhxD_cn.js → dist-DhHh0jLg.js} +1 -1
  87. package/dist/{dist-DGAfI2rB.js → dist-DqAWR3CS.js} +2 -2
  88. package/dist/{dist--sWVZwjW.js → dist-Du8WkPuU.js} +1 -1
  89. package/dist/dist-DuEeHMvL.js +5 -0
  90. package/dist/{dist-BTyJtnNg.js → dist-DxvORzUR.js} +1 -1
  91. package/dist/{dist-B507mf_I.js → dist-RqXTaiir.js} +2 -2
  92. package/dist/{dist-Yrfc6L0I.js → dist-fQ0ViXGs.js} +3 -3
  93. package/dist/{dist-B4LJpMEg.js → dist-h2c8sZvT.js} +1 -1
  94. package/dist/{dist-C2ej4eOH.js → dist-luvabDEB.js} +2 -2
  95. package/dist/{dist-B52GXZbd.js → dist-p2qyWijU.js} +2 -2
  96. package/dist/{erDiagram-Q2GNP2WA--19X2kU5.js → erDiagram-Q2GNP2WA-BU-m41EQ.js} +10 -10
  97. package/dist/{error-banner-CVkfBUT3.js → error-banner-5bz0L9hS.js} +3 -3
  98. package/dist/{esm-CWp0KQeK.js → esm-BfhQmZjp.js} +4 -4
  99. package/dist/{esm-DjNnlmpf.js → esm-Duie8iU-.js} +23 -23
  100. package/dist/{extends-vAi97cpa.js → extends-BgdxCfYu.js} +6 -6
  101. package/dist/{flatten-CzBvFdvC.js → flatten-Bbw7g6-K.js} +1 -1
  102. package/dist/{flowDiagram-NV44I4VS-DQmWlo7f.js → flowDiagram-NV44I4VS-CRoXKjGq.js} +10 -10
  103. package/dist/{formats-Dsy9kkZu.js → formats-DQ5qjo_Q.js} +4 -4
  104. package/dist/{ganttDiagram-JELNMOA3-BOGXJ8Lk.js → ganttDiagram-JELNMOA3-7mq5f9cO.js} +7 -7
  105. package/dist/{gitGraph-G5XIXVHT-DGlbae5m.js → gitGraph-G5XIXVHT-DiniR35k.js} +3 -3
  106. package/dist/{gitGraphDiagram-V2S2FVAM-DjzxfF0P.js → gitGraphDiagram-V2S2FVAM-Dfuokq6w.js} +13 -13
  107. package/dist/{glide-data-editor-DucgdjRo.js → glide-data-editor-DqRY9naW.js} +557 -557
  108. package/dist/{graphlib-CVPKjKCS.js → graphlib-Ns7y5crs.js} +5 -5
  109. package/dist/{hasIn-COs6vImh.js → hasIn-Deg7jl_j.js} +3 -3
  110. package/dist/{html-to-image-CpggM7u1.js → html-to-image-CiSinpSR.js} +109 -109
  111. package/dist/{info-VBDWY6EO-D2lvLLw5.js → info-VBDWY6EO-DVZvGhkQ.js} +3 -3
  112. package/dist/{infoDiagram-HS3SLOUP-ChNufFsP.js → infoDiagram-HS3SLOUP-CEnzWruK.js} +13 -13
  113. package/dist/{input-D4kjoQUB.js → input-CZD2z6X2.js} +70 -67
  114. package/dist/{isEmpty-Dd8mx_WL.js → isEmpty-CJJMn-QP.js} +1 -1
  115. package/dist/{isSymbol-BvIfMnn6.js → isSymbol-CoUCgMCM.js} +1 -1
  116. package/dist/{journeyDiagram-XKPGCS4Q-BO_O4Ij1.js → journeyDiagram-XKPGCS4Q-8XYSU1GI.js} +3 -3
  117. package/dist/{kanban-definition-3W4ZIXB7-CPpiiiWk.js → kanban-definition-3W4ZIXB7--9pT9z1R.js} +7 -7
  118. package/dist/{label-BLqV33b1.js → label-LWtdw5i8.js} +3 -3
  119. package/dist/{linear-2NnK4cxi.js → linear-B5-AFRiR.js} +2 -2
  120. package/dist/{loader-Dr8Qem8p.js → loader-BWLPpjKK.js} +2 -2
  121. package/dist/main.js +1141 -987
  122. package/dist/{memoize-C9ltv0Cw.js → memoize-BOtf2yFf.js} +1 -1
  123. package/dist/{merge-CHn7Yx0N.js → merge-Be1CqGnU.js} +1 -1
  124. package/dist/mermaid-4DMBBIKO-DIdL224_.js +6 -0
  125. package/dist/{mermaid-DO-Daq7u.js → mermaid-IU93XzmY.js} +44 -44
  126. package/dist/{mermaid-parser.core-DreccfmS.js → mermaid-parser.core-C3XRsazI.js} +8 -8
  127. package/dist/{min-BNz2lZfk.js → min-Dtgc8txR.js} +4 -4
  128. package/dist/{mindmap-definition-VGOIOE7T-CC1_Vl0f.js → mindmap-definition-VGOIOE7T-B-4mnfFG.js} +9 -9
  129. package/dist/{now-Sgq5m3D-.js → now-Ch98bJO_.js} +2 -2
  130. package/dist/{number-overlay-editor-CpKi64Fy.js → number-overlay-editor-D-a0qCT8.js} +1 -1
  131. package/dist/{once-rJImu7SE.js → once-DPuqGUeo.js} +1 -1
  132. package/dist/{packet-DYOGHKS2-CmWtF3uO.js → packet-DYOGHKS2-34raHOiB.js} +3 -3
  133. package/dist/{pick-CRAXxDYn.js → pick-D1Qo8s2C.js} +4 -4
  134. package/dist/{pie-VRWISCQL-B6u8vus8.js → pie-VRWISCQL-BaLlzZa3.js} +3 -3
  135. package/dist/{pieDiagram-ADFJNKIX-Di34MOFQ.js → pieDiagram-ADFJNKIX-Cr3cNpZY.js} +15 -15
  136. package/dist/{precisionRound-CnHPY_5v.js → precisionRound-Tqb4mg-H.js} +1 -1
  137. package/dist/{process-output-X8TR20AK.js → process-output-5qJjMRKh.js} +4 -4
  138. package/dist/{quadrantDiagram-AYHSOK5B-B9kVk1ny.js → quadrantDiagram-AYHSOK5B-BuNL8Q93.js} +4 -4
  139. package/dist/{radar-ZZBFDIW7-XAmXSa8s.js → radar-ZZBFDIW7-Ci7bfoZa.js} +3 -3
  140. package/dist/{react-vega-Dh6-UKKe.js → react-vega-B0sAlDTL.js} +9 -9
  141. package/dist/react-vega-B6ncY2Tp.js +9 -0
  142. package/dist/{requirementDiagram-UZGBJVZJ-BxGfGYEx.js → requirementDiagram-UZGBJVZJ-BG2lLUN1.js} +9 -9
  143. package/dist/{reveal-component-Cj2fUG1Q.js → reveal-component-DZtPMEoM.js} +28 -28
  144. package/dist/{sankeyDiagram-TZEHDZUN-D09PBJ-n.js → sankeyDiagram-TZEHDZUN-DMal8sps.js} +3 -3
  145. package/dist/{sequenceDiagram-WL72ISMW-t_Dpemj0.js → sequenceDiagram-WL72ISMW-DT6Tk-Eo.js} +4 -4
  146. package/dist/{spec-hVaaZsY5.js → spec-a6DaqW__.js} +4 -4
  147. package/dist/{stateDiagram-FKZM4ZOC-B18gTP_j.js → stateDiagram-FKZM4ZOC-CB_lodq3.js} +12 -12
  148. package/dist/{stateDiagram-v2-4FDKWEC3-B6e_t14A.js → stateDiagram-v2-4FDKWEC3-E0RGjKsm.js} +10 -10
  149. package/dist/stex-KfRnSHzF.js +4 -0
  150. package/dist/{strings-BiIhGaI8.js → strings-Bu3vlb6W.js} +7 -7
  151. package/dist/style.css +1 -1
  152. package/dist/{swiper-component-DlD2GU2g.js → swiper-component-B2t5sN1q.js} +3 -3
  153. package/dist/{time-C1SGcFMH.js → time-CsmIF9YZ.js} +3 -3
  154. package/dist/{timeline-definition-IT6M3QCI-DJnh1ks5.js → timeline-definition-IT6M3QCI-NfSKRvH0.js} +2 -2
  155. package/dist/{toDate-CIpC_34u.js → toDate-ZVVIBmdk.js} +5 -5
  156. package/dist/{tooltip-DRaMBu06.js → tooltip-C5FYOpQc.js} +4 -4
  157. package/dist/{treemap-GDKQZRPO-Du95DV6u.js → treemap-GDKQZRPO-Cl6OQh8D.js} +3 -3
  158. package/dist/{types-Dzuoc3LN.js → types-CVvp1fKr.js} +2 -9
  159. package/dist/{useAsyncData-C56Khv_R.js → useAsyncData-C008zUPi.js} +2 -2
  160. package/dist/{useDateFormatter-B_9k85Ex.js → useDateFormatter-BA4FCquG.js} +2 -2
  161. package/dist/{useDeepCompareMemoize-Dt98v2ua.js → useDeepCompareMemoize-BrA3_n61.js} +1 -1
  162. package/dist/{useIframeCapabilities-BkYHTrss.js → useIframeCapabilities-C4JTXTIh.js} +1 -1
  163. package/dist/{useLifecycle-BF6-z62y.js → useLifecycle-BNaoJ5a4.js} +4 -4
  164. package/dist/{useTheme-DykuNHR2.js → useTheme-7O0YWlE5.js} +3 -3
  165. package/dist/{vega-component-cSdqoAxe.js → vega-component-DJNmOdUj.js} +18 -18
  166. package/dist/{vega-loader.browser-3_z8GoFC.js → vega-loader.browser-CZ-J8Py3.js} +3 -3
  167. package/dist/{xychartDiagram-PRI3JC2R-Dk2d_bX0.js → xychartDiagram-PRI3JC2R-BvwftqMA.js} +9 -9
  168. package/dist/{zod-BWkcDORu.js → zod-CoBiJ5v4.js} +3 -3
  169. package/package.json +1 -1
  170. package/src/components/data-table/__tests__/column-header.test.tsx +110 -277
  171. package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +33 -0
  172. package/src/components/data-table/__tests__/filter-pill-editor.test.tsx +75 -38
  173. package/src/components/data-table/__tests__/filter-pills.test.tsx +287 -0
  174. package/src/components/data-table/__tests__/filter-test-utils.ts +47 -0
  175. package/src/components/data-table/__tests__/filters.test.ts +5 -5
  176. package/src/components/data-table/add-filter-button.tsx +85 -0
  177. package/src/components/data-table/column-header.tsx +92 -691
  178. package/src/components/data-table/context-menu.tsx +26 -12
  179. package/src/components/data-table/data-table.tsx +89 -57
  180. package/src/components/data-table/date-filter-inputs.tsx +13 -10
  181. package/src/components/data-table/filter-by-values-picker.tsx +13 -19
  182. package/src/components/data-table/filter-editor-context.tsx +34 -0
  183. package/src/components/data-table/filter-pill-editor.tsx +152 -175
  184. package/src/components/data-table/filter-pills.tsx +190 -153
  185. package/src/components/data-table/filters/builders.ts +102 -0
  186. package/src/components/data-table/filters/defaults.ts +31 -0
  187. package/src/components/data-table/filters/format.ts +131 -0
  188. package/src/components/data-table/filters/guards.ts +51 -0
  189. package/src/components/data-table/filters/index.ts +7 -0
  190. package/src/components/data-table/filters/operators.ts +76 -0
  191. package/src/components/data-table/filters/serialize.ts +186 -0
  192. package/src/components/data-table/filters/types.ts +33 -0
  193. package/src/components/data-table/header-items.tsx +6 -83
  194. package/src/components/data-table/value-chips.tsx +52 -0
  195. package/src/components/dependency-graph/minimap-content.tsx +2 -2
  196. package/src/components/ui/number-field.tsx +13 -1
  197. package/src/utils/dates.ts +39 -0
  198. package/dist/ErrorBoundary-D3wrPNma.js +0 -167
  199. package/dist/architecture-7HQA4BMR-CS9jOrqM.js +0 -6
  200. package/dist/dist-21ButRCu.js +0 -8
  201. package/dist/dist-B--tLnAP.js +0 -5
  202. package/dist/dist-BoHGySTM.js +0 -5
  203. package/dist/dist-ByAz19Qc.js +0 -5
  204. package/dist/dist-C1Ap5CYU.js +0 -5
  205. package/dist/dist-C93EysN4.js +0 -5
  206. package/dist/dist-CY-lVor6.js +0 -8
  207. package/dist/dist-CYDuv4bR.js +0 -8
  208. package/dist/dist-Cfo5EE2t.js +0 -6
  209. package/dist/dist-CjivSDvN.js +0 -5
  210. package/dist/dist-Cqwx-MH7.js +0 -5
  211. package/dist/dist-DbpcoFAV.js +0 -6
  212. package/dist/dist-FUNenbiQ.js +0 -5
  213. package/dist/dist-zhSud5X3.js +0 -8
  214. package/dist/mermaid-4DMBBIKO-B7VQMwJx.js +0 -6
  215. package/dist/react-vega-Cavbrg4l.js +0 -9
  216. package/dist/stex-ChDHQs3R.js +0 -4
  217. package/src/components/data-table/__tests__/column-header.test.ts +0 -65
  218. package/src/components/data-table/filters.ts +0 -386
  219. /package/dist/{_baseFor-BGiY-cm1.js → _baseFor-4jw-lnCC.js} +0 -0
  220. /package/dist/{clsx-CyyyQ8Ue.js → clsx-CIWA5tNO.js} +0 -0
  221. /package/dist/{defaultLocale-DoeErsX2.js → defaultLocale-BoHTsDG6.js} +0 -0
  222. /package/dist/{defaultLocale-BpsHxBd7.js → defaultLocale-u-3osm0P.js} +0 -0
  223. /package/dist/{dist-CCADb07R.js → dist-DNdhYsgW.js} +0 -0
  224. /package/dist/{emotion-is-prop-valid.esm-DtW2o230.js → emotion-is-prop-valid.esm-DzSb5hsH.js} +0 -0
  225. /package/dist/{invariant-UcGKQEhF.js → invariant-wRzNXIsJ.js} +0 -0
  226. /package/dist/{jsx-runtime-COBk7ree.js → jsx-runtime-DebpN0FN.js} +0 -0
  227. /package/dist/{main-CThhXnXU.js → main-Tj_-QTyF.js} +0 -0
  228. /package/dist/{micromark-factory-space-CwHmg6iz.js → micromark-factory-space-DF2w36zS.js} +0 -0
  229. /package/dist/{ordinal-B43ZeR68.js → ordinal-ArJavP1Q.js} +0 -0
  230. /package/dist/{purify.es-DT70lfR0.js → purify.es-H92eMd9-.js} +0 -0
  231. /package/dist/{range-BOiA8qqU.js → range-C-rmrM1O.js} +0 -0
  232. /package/dist/{react-dom-BWRJ_g_k.js → react-dom-BTJzcVJ9.js} +0 -0
  233. /package/dist/{stex-DrxP7bb3.js → stex-BIsgBmK4.js} +0 -0
@@ -2,71 +2,27 @@
2
2
  "use no memo";
3
3
 
4
4
  import type { Column, Table } from "@tanstack/react-table";
5
- import {
6
- EllipsisIcon,
7
- FilterIcon,
8
- MinusIcon,
9
- TextIcon,
10
- XIcon,
11
- } from "lucide-react";
12
- import { useState } from "react";
5
+ import { EllipsisIcon, FilterIcon, ListFilterIcon } from "lucide-react";
13
6
  import { useLocale } from "react-aria";
14
7
  import {
15
8
  DropdownMenu,
16
9
  DropdownMenuContent,
17
10
  DropdownMenuItem,
18
- DropdownMenuPortal,
19
11
  DropdownMenuSeparator,
20
- DropdownMenuSub,
21
- DropdownMenuSubContent,
22
- DropdownMenuSubTrigger,
23
12
  DropdownMenuTrigger,
24
13
  } from "@/components/ui/dropdown-menu";
25
14
  import type { CalculateTopKRows } from "@/plugins/impl/DataTablePlugin";
26
- import type { OperatorType } from "@/plugins/impl/data-frames/utils/operators";
27
- import { logNever } from "@/utils/assertNever";
28
15
  import { cn } from "@/utils/cn";
29
- import { Button } from "../ui/button";
30
- import { DraggablePopover } from "../ui/draggable-popover";
31
- import { Input } from "../ui/input";
32
- import { RegexInput } from "./regex-input";
33
- import { NumberField } from "../ui/number-field";
34
- import { PopoverClose } from "../ui/popover";
35
- import {
36
- Select,
37
- SelectContent,
38
- SelectItem,
39
- SelectTrigger,
40
- SelectValue,
41
- } from "../ui/select";
42
- import { FilterByValuesList } from "./filter-by-values-picker";
43
- import { OPERATOR_LABELS } from "./operator-labels";
44
- import {
45
- type ColumnFilterForType,
46
- type ColumnFilterValue,
47
- DATETIME_OPS,
48
- Filter,
49
- isDatetimeComparisonOp,
50
- isNumberComparisonOp,
51
- isTextScalarOp,
52
- NUMBER_OPS,
53
- TEXT_OPS,
54
- } from "./filters";
55
- import {
56
- type DateLikeFilterType,
57
- DateLikeInput,
58
- DateLikeRangeInput,
59
- } from "./date-filter-inputs";
16
+ import { useFilterEditor } from "./filter-editor-context";
17
+ import { EDITABLE_FILTER_TYPES, isMembershipFilterType } from "./filters";
60
18
  import {
61
19
  ClearFilterMenuItem,
62
- FilterButtons,
63
20
  renderColumnPinning,
64
21
  renderColumnWrapping,
65
22
  renderCopyColumn,
66
23
  renderDataType,
67
- renderFilterByValues,
68
24
  renderFormatOptions,
69
- renderSortFilterIcon,
25
+ renderSortIcon,
70
26
  renderSorts,
71
27
  } from "./header-items";
72
28
 
@@ -88,11 +44,10 @@ export const DataTableColumnHeader = <TData, TValue>({
88
44
  subheader,
89
45
  justify,
90
46
  className,
91
- calculateTopKRows,
92
47
  table,
93
48
  }: DataTableColumnHeaderProps<TData, TValue>) => {
94
- const [isFilterValueOpen, setIsFilterValueOpen] = useState(false);
95
49
  const { locale } = useLocale();
50
+ const editor = useFilterEditor();
96
51
 
97
52
  // No header
98
53
  if (!header) {
@@ -116,68 +71,101 @@ export const DataTableColumnHeader = <TData, TValue>({
116
71
  }
117
72
 
118
73
  const hasFilter = column.getFilterValue() !== undefined;
74
+ const filterType = column.columnDef.meta?.filterType;
75
+ const canEditFilter =
76
+ editor !== null &&
77
+ column.getCanFilter() &&
78
+ filterType !== undefined &&
79
+ EDITABLE_FILTER_TYPES.has(filterType);
80
+ const canFilterByValues =
81
+ canEditFilter &&
82
+ filterType !== undefined &&
83
+ isMembershipFilterType(filterType);
119
84
 
120
85
  return (
121
- <>
86
+ <div
87
+ className={cn("group flex flex-col my-1 w-full select-none", className)}
88
+ >
122
89
  <div
123
- className={cn("group flex flex-col my-1 w-full select-none", className)}
90
+ className={cn(
91
+ "flex items-center gap-1",
92
+ justify === "right" && "flex-row-reverse",
93
+ justify === "center" && "mx-auto",
94
+ )}
124
95
  >
125
- <div
126
- className={cn(
127
- "flex items-center gap-1",
128
- justify === "right" && "flex-row-reverse",
129
- justify === "center" && "mx-auto",
130
- )}
131
- >
132
- {justify === "center" ? (
133
- <>
134
- {column.getCanSort() && <SortButton column={column} />}
135
- <span>{header}</span>
136
- </>
137
- ) : (
138
- <>
139
- <span>{header}</span>
140
- {column.getCanSort() && <SortButton column={column} />}
141
- </>
142
- )}
143
- <DropdownMenu modal={false}>
144
- <DropdownMenuTrigger asChild={true}>
145
- <button
146
- type="button"
147
- className="inline-flex items-center justify-center h-5 w-5 rounded hover:bg-(--slate-4) text-muted-foreground opacity-0 group-hover:opacity-100 focus:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100 data-[state=open]:text-accent-foreground"
148
- aria-label="Column options"
149
- data-testid="data-table-column-menu-button"
96
+ {justify === "center" ? (
97
+ <>
98
+ {column.getCanSort() && <SortButton column={column} />}
99
+ {hasFilter && <FilterIndicator />}
100
+ <span>{header}</span>
101
+ </>
102
+ ) : (
103
+ <>
104
+ <span>{header}</span>
105
+ {hasFilter && <FilterIndicator />}
106
+ {column.getCanSort() && <SortButton column={column} />}
107
+ </>
108
+ )}
109
+ <DropdownMenu modal={false}>
110
+ <DropdownMenuTrigger asChild={true}>
111
+ <button
112
+ type="button"
113
+ className="inline-flex items-center justify-center h-5 w-5 rounded hover:bg-(--slate-4) text-muted-foreground opacity-0 group-hover:opacity-100 focus:opacity-100 group-focus-within:opacity-100 data-[state=open]:opacity-100 data-[state=open]:text-accent-foreground"
114
+ aria-label="Column options"
115
+ data-testid="data-table-column-menu-button"
116
+ >
117
+ <EllipsisIcon className="h-3.5 w-3.5" />
118
+ </button>
119
+ </DropdownMenuTrigger>
120
+ <DropdownMenuContent align="start">
121
+ {renderDataType(column)}
122
+ {renderSorts(column, table)}
123
+ {renderCopyColumn(column)}
124
+ {renderColumnPinning(column)}
125
+ {renderColumnWrapping(column)}
126
+ {renderFormatOptions(column, locale)}
127
+ {canEditFilter && <DropdownMenuSeparator />}
128
+ {canEditFilter && (
129
+ <DropdownMenuItem
130
+ onSelect={() =>
131
+ editor.requestAddFilter({ columnId: column.id })
132
+ }
150
133
  >
151
- <EllipsisIcon className="h-3.5 w-3.5" />
152
- </button>
153
- </DropdownMenuTrigger>
154
- <DropdownMenuContent align="start">
155
- {renderDataType(column)}
156
- {renderSorts(column, table)}
157
- {renderCopyColumn(column)}
158
- {renderColumnPinning(column)}
159
- {renderColumnWrapping(column)}
160
- {renderFormatOptions(column, locale)}
161
- <DropdownMenuSeparator />
162
- {renderMenuItemFilter(column, calculateTopKRows)}
163
- {renderFilterByValues(column, setIsFilterValueOpen)}
164
- {hasFilter && <ClearFilterMenuItem column={column} />}
165
- </DropdownMenuContent>
166
- </DropdownMenu>
167
- </div>
168
- {subheader}
134
+ <FilterIcon className="mo-dropdown-icon" />
135
+ Filter
136
+ </DropdownMenuItem>
137
+ )}
138
+ {canFilterByValues && (
139
+ <DropdownMenuItem
140
+ onSelect={() =>
141
+ editor.requestAddFilter({
142
+ columnId: column.id,
143
+ operator: "in",
144
+ })
145
+ }
146
+ >
147
+ <ListFilterIcon className="mo-dropdown-icon" />
148
+ Filter by values
149
+ </DropdownMenuItem>
150
+ )}
151
+ {hasFilter && <ClearFilterMenuItem column={column} />}
152
+ </DropdownMenuContent>
153
+ </DropdownMenu>
169
154
  </div>
170
- {isFilterValueOpen && (
171
- <PopoverFilterByValues
172
- setIsFilterValueOpen={setIsFilterValueOpen}
173
- calculateTopKRows={calculateTopKRows}
174
- column={column}
175
- />
176
- )}
177
- </>
155
+ {subheader}
156
+ </div>
178
157
  );
179
158
  };
180
159
 
160
+ const FilterIndicator = () => (
161
+ <span
162
+ className="inline-flex items-center justify-center h-5 w-5 text-primary"
163
+ aria-label="Column is filtered"
164
+ >
165
+ <FilterIcon className="h-3 w-3" aria-hidden={true} />
166
+ </span>
167
+ );
168
+
181
169
  const SortButton = <TData, TValue>({
182
170
  column,
183
171
  }: {
@@ -215,594 +203,7 @@ const SortButton = <TData, TValue>({
215
203
  }
216
204
  data-testid="data-table-sort-button"
217
205
  >
218
- {renderSortFilterIcon(column)}
206
+ {renderSortIcon(column)}
219
207
  </button>
220
208
  );
221
209
  };
222
-
223
- export function renderMenuItemFilter<TData, TValue>(
224
- column: Column<TData, TValue>,
225
- calculateTopKRows?: CalculateTopKRows,
226
- ) {
227
- const canFilter = column.getCanFilter();
228
- if (!canFilter) {
229
- return null;
230
- }
231
-
232
- const filterType = column.columnDef.meta?.filterType;
233
- if (!filterType) {
234
- return null;
235
- }
236
-
237
- const filterMenuItem = (
238
- <DropdownMenuSubTrigger>
239
- <FilterIcon className="mo-dropdown-icon" />
240
- Filter
241
- </DropdownMenuSubTrigger>
242
- );
243
-
244
- if (filterType === "boolean") {
245
- return (
246
- <DropdownMenuSub>
247
- {filterMenuItem}
248
- <DropdownMenuPortal>
249
- <DropdownMenuSubContent>
250
- <BooleanFilter column={column} />
251
- </DropdownMenuSubContent>
252
- </DropdownMenuPortal>
253
- </DropdownMenuSub>
254
- );
255
- }
256
-
257
- if (filterType === "text") {
258
- return (
259
- <DropdownMenuSub>
260
- {filterMenuItem}
261
- <DropdownMenuPortal>
262
- <DropdownMenuSubContent>
263
- <TextFilterMenu
264
- column={column}
265
- calculateTopKRows={calculateTopKRows}
266
- />
267
- </DropdownMenuSubContent>
268
- </DropdownMenuPortal>
269
- </DropdownMenuSub>
270
- );
271
- }
272
-
273
- if (filterType === "number") {
274
- return (
275
- <DropdownMenuSub>
276
- {filterMenuItem}
277
- <DropdownMenuPortal>
278
- <DropdownMenuSubContent>
279
- <NumberFilterMenu column={column} />
280
- </DropdownMenuSubContent>
281
- </DropdownMenuPortal>
282
- </DropdownMenuSub>
283
- );
284
- }
285
-
286
- if (filterType === "select") {
287
- // Not implemented
288
- return null;
289
- }
290
-
291
- if (
292
- filterType === "date" ||
293
- filterType === "datetime" ||
294
- filterType === "time"
295
- ) {
296
- return (
297
- <DropdownMenuSub>
298
- {filterMenuItem}
299
- <DropdownMenuPortal>
300
- <DropdownMenuSubContent>
301
- <DateFilterMenu column={column} filterType={filterType} />
302
- </DropdownMenuSubContent>
303
- </DropdownMenuPortal>
304
- </DropdownMenuSub>
305
- );
306
- }
307
-
308
- logNever(filterType);
309
- return null;
310
- }
311
-
312
- const OperatorSelect = ({
313
- operator,
314
- options,
315
- onChange,
316
- }: {
317
- operator: OperatorType;
318
- options: readonly OperatorType[];
319
- onChange: (next: OperatorType) => void;
320
- }) => (
321
- <Select value={operator} onValueChange={(v) => onChange(v as OperatorType)}>
322
- <SelectTrigger className="border-border shadow-none! ring-0! w-full mb-0.5">
323
- <SelectValue />
324
- </SelectTrigger>
325
- <SelectContent>
326
- {options.map((op) => (
327
- <SelectItem key={op} value={op}>
328
- {OPERATOR_LABELS[op]}
329
- </SelectItem>
330
- ))}
331
- </SelectContent>
332
- </Select>
333
- );
334
-
335
- const BooleanFilter = <TData, TValue>({
336
- column,
337
- }: {
338
- column: Column<TData, TValue>;
339
- }) => {
340
- return (
341
- <>
342
- <DropdownMenuItem
343
- onClick={() =>
344
- column.setFilterValue(
345
- Filter.boolean({ value: true, operator: "is_true" }),
346
- )
347
- }
348
- >
349
- True
350
- </DropdownMenuItem>
351
- <DropdownMenuItem
352
- onClick={() =>
353
- column.setFilterValue(
354
- Filter.boolean({ value: false, operator: "is_false" }),
355
- )
356
- }
357
- >
358
- False
359
- </DropdownMenuItem>
360
- <DropdownMenuSeparator />
361
- <DropdownMenuItem
362
- onClick={() =>
363
- column.setFilterValue(Filter.boolean({ operator: "is_null" }))
364
- }
365
- >
366
- Is null
367
- </DropdownMenuItem>
368
- <DropdownMenuItem
369
- onClick={() =>
370
- column.setFilterValue(Filter.boolean({ operator: "is_not_null" }))
371
- }
372
- >
373
- Is not null
374
- </DropdownMenuItem>
375
- </>
376
- );
377
- };
378
-
379
- type NumberComparisonFilter = Extract<
380
- ColumnFilterForType<"number">,
381
- { value: number }
382
- >;
383
- const isNumberComparisonFilter = (
384
- filter: ColumnFilterForType<"number">,
385
- ): filter is NumberComparisonFilter => isNumberComparisonOp(filter.operator);
386
-
387
- export const NumberFilterMenu = <TData, TValue>({
388
- column,
389
- }: {
390
- column: Column<TData, TValue>;
391
- }) => {
392
- const currentFilter = column.getFilterValue() as
393
- | ColumnFilterForType<"number">
394
- | undefined;
395
- const hasFilter = currentFilter !== undefined;
396
-
397
- const [operator, setOperator] = useState<OperatorType>(
398
- currentFilter?.operator ?? "between",
399
- );
400
- const [min, setMin] = useState<number | undefined>(
401
- currentFilter?.operator === "between" ? currentFilter.min : undefined,
402
- );
403
- const [max, setMax] = useState<number | undefined>(
404
- currentFilter?.operator === "between" ? currentFilter.max : undefined,
405
- );
406
- const [value, setValue] = useState<number | undefined>(
407
- currentFilter !== undefined && isNumberComparisonFilter(currentFilter)
408
- ? currentFilter.value
409
- : undefined,
410
- );
411
-
412
- const isComparison = isNumberComparisonOp(operator);
413
- const isNullish = operator === "is_null" || operator === "is_not_null";
414
-
415
- const applyDisabled =
416
- (operator === "between" && (min === undefined || max === undefined)) ||
417
- (isComparison && value === undefined);
418
-
419
- const handleApply = () => {
420
- if (isNullish) {
421
- column.setFilterValue(Filter.number({ operator }));
422
- return;
423
- }
424
- if (operator === "between" && min !== undefined && max !== undefined) {
425
- column.setFilterValue(Filter.number({ operator: "between", min, max }));
426
- return;
427
- }
428
- if (isComparison && value !== undefined) {
429
- column.setFilterValue(Filter.number({ operator, value }));
430
- }
431
- };
432
-
433
- const handleClear = () => {
434
- setMin(undefined);
435
- setMax(undefined);
436
- setValue(undefined);
437
- column.setFilterValue(undefined);
438
- };
439
-
440
- const handleOperatorChange = (next: OperatorType) => {
441
- setOperator(next);
442
- };
443
-
444
- return (
445
- <div className="flex flex-col gap-1 pt-3 px-2">
446
- <OperatorSelect
447
- operator={operator}
448
- options={NUMBER_OPS}
449
- onChange={handleOperatorChange}
450
- />
451
- {operator === "between" && (
452
- <div className="flex gap-1 items-center">
453
- <NumberField
454
- value={min}
455
- onChange={setMin}
456
- aria-label="min"
457
- placeholder="min"
458
- className="shadow-none! border-border hover:shadow-none!"
459
- />
460
- <MinusIcon className="h-5 w-5 text-muted-foreground" />
461
- <NumberField
462
- value={max}
463
- onChange={setMax}
464
- aria-label="max"
465
- placeholder="max"
466
- className="shadow-none! border-border hover:shadow-none!"
467
- />
468
- </div>
469
- )}
470
- {isComparison && (
471
- <NumberField
472
- value={value}
473
- onChange={setValue}
474
- aria-label="value"
475
- placeholder="value"
476
- className="shadow-none! border-border hover:shadow-none!"
477
- />
478
- )}
479
- <FilterButtons
480
- onApply={handleApply}
481
- onClear={handleClear}
482
- clearButtonDisabled={!hasFilter}
483
- applyButtonDisabled={applyDisabled}
484
- />
485
- </div>
486
- );
487
- };
488
-
489
- type DateComparisonFilter = Extract<
490
- ColumnFilterForType<DateLikeFilterType>,
491
- { value: Date }
492
- >;
493
- const isDateComparisonFilter = (
494
- filter: ColumnFilterForType<DateLikeFilterType>,
495
- ): filter is DateComparisonFilter => isDatetimeComparisonOp(filter.operator);
496
-
497
- export const DateFilterMenu = <TData, TValue>({
498
- column,
499
- filterType,
500
- }: {
501
- column: Column<TData, TValue>;
502
- filterType: DateLikeFilterType;
503
- }) => {
504
- const currentFilter = column.getFilterValue() as
505
- | ColumnFilterForType<DateLikeFilterType>
506
- | undefined;
507
- const hasFilter = currentFilter !== undefined;
508
-
509
- const [operator, setOperator] = useState<OperatorType>(
510
- currentFilter?.operator ?? "between",
511
- );
512
- const [min, setMin] = useState<Date | undefined>(
513
- currentFilter?.operator === "between" ? currentFilter.min : undefined,
514
- );
515
- const [max, setMax] = useState<Date | undefined>(
516
- currentFilter?.operator === "between" ? currentFilter.max : undefined,
517
- );
518
- const [value, setValue] = useState<Date | undefined>(
519
- currentFilter !== undefined && isDateComparisonFilter(currentFilter)
520
- ? currentFilter.value
521
- : undefined,
522
- );
523
-
524
- const isComparison = isDatetimeComparisonOp(operator);
525
- const isNullish = operator === "is_null" || operator === "is_not_null";
526
-
527
- const applyDisabled =
528
- (operator === "between" && (min === undefined || max === undefined)) ||
529
- (isComparison && value === undefined);
530
-
531
- const buildFilter = (
532
- opts: Parameters<typeof Filter.date>[0],
533
- ): ColumnFilterForType<DateLikeFilterType> => {
534
- switch (filterType) {
535
- case "date":
536
- return Filter.date(opts);
537
- case "datetime":
538
- return Filter.datetime(opts);
539
- case "time":
540
- return Filter.time(opts);
541
- }
542
- };
543
-
544
- const handleApply = () => {
545
- if (isNullish) {
546
- column.setFilterValue(buildFilter({ operator }));
547
- return;
548
- }
549
- if (operator === "between" && min !== undefined && max !== undefined) {
550
- column.setFilterValue(buildFilter({ operator: "between", min, max }));
551
- return;
552
- }
553
- if (isComparison && value !== undefined) {
554
- column.setFilterValue(buildFilter({ operator, value }));
555
- }
556
- };
557
-
558
- const [resetKey, setResetKey] = useState(0);
559
- const handleClear = () => {
560
- setMin(undefined);
561
- setMax(undefined);
562
- setValue(undefined);
563
- setResetKey((k) => k + 1);
564
- column.setFilterValue(undefined);
565
- };
566
-
567
- const handleOperatorChange = (next: OperatorType) => {
568
- setOperator(next);
569
- };
570
-
571
- return (
572
- <div
573
- className="flex flex-col gap-1 pt-3 px-2"
574
- onKeyDownCapture={(e) => {
575
- if (e.key === "Tab") {
576
- e.stopPropagation();
577
- }
578
- }}
579
- >
580
- <OperatorSelect
581
- operator={operator}
582
- options={DATETIME_OPS}
583
- onChange={handleOperatorChange}
584
- />
585
- {operator === "between" && (
586
- <DateLikeRangeInput
587
- key={`${filterType}-${resetKey}`}
588
- filterType={filterType}
589
- min={min}
590
- max={max}
591
- onRangeChange={(nextMin, nextMax) => {
592
- setMin(nextMin);
593
- setMax(nextMax);
594
- }}
595
- className="shadow-none! border-border hover:shadow-none!"
596
- />
597
- )}
598
- {isComparison && (
599
- <DateLikeInput
600
- key={`${filterType}-${resetKey}`}
601
- filterType={filterType}
602
- value={value}
603
- onChange={setValue}
604
- aria-label="value"
605
- className="shadow-none! border-border hover:shadow-none!"
606
- />
607
- )}
608
- <FilterButtons
609
- onApply={handleApply}
610
- onClear={handleClear}
611
- clearButtonDisabled={!hasFilter}
612
- applyButtonDisabled={applyDisabled}
613
- />
614
- </div>
615
- );
616
- };
617
-
618
- export const TextFilterMenu = <TData, TValue>({
619
- column,
620
- calculateTopKRows,
621
- }: {
622
- column: Column<TData, TValue>;
623
- calculateTopKRows?: CalculateTopKRows;
624
- }) => {
625
- const currentFilter = column.getFilterValue() as
626
- | ColumnFilterForType<"text">
627
- | undefined;
628
- const hasFilter = currentFilter !== undefined;
629
-
630
- const [operator, setOperator] = useState<OperatorType>(
631
- currentFilter?.operator ?? "contains",
632
- );
633
- const [text, setText] = useState<string>(
634
- currentFilter && "text" in currentFilter ? currentFilter.text : "",
635
- );
636
- const [values, setValues] = useState<string[]>(
637
- currentFilter && "values" in currentFilter ? [...currentFilter.values] : [],
638
- );
639
-
640
- const isScalar = isTextScalarOp(operator);
641
- const isMulti = operator === "in" || operator === "not_in";
642
- const isNullish =
643
- operator === "is_null" ||
644
- operator === "is_not_null" ||
645
- operator === "is_empty";
646
-
647
- const applyDisabled =
648
- (isScalar && text === "") || (isMulti && values.length === 0);
649
-
650
- const handleApply = () => {
651
- if (isNullish) {
652
- column.setFilterValue(Filter.text({ operator }));
653
- return;
654
- }
655
- if (isScalar && text !== "") {
656
- column.setFilterValue(Filter.text({ operator, text }));
657
- return;
658
- }
659
- if (isMulti && values.length > 0) {
660
- column.setFilterValue(Filter.text({ operator, values }));
661
- }
662
- };
663
-
664
- const handleClear = () => {
665
- setText("");
666
- setValues([]);
667
- column.setFilterValue(undefined);
668
- };
669
-
670
- const handleOperatorChange = (next: OperatorType) => {
671
- setOperator(next);
672
- };
673
-
674
- return (
675
- <div className="flex flex-col gap-1 pt-3 px-2">
676
- <OperatorSelect
677
- operator={operator}
678
- options={TEXT_OPS}
679
- onChange={handleOperatorChange}
680
- />
681
- {isScalar && operator === "regex" && (
682
- <RegexInput
683
- value={text}
684
- onChange={setText}
685
- onKeyDown={(e) => {
686
- e.stopPropagation();
687
- if (e.key === "Enter") {
688
- handleApply();
689
- }
690
- }}
691
- />
692
- )}
693
- {isScalar && operator !== "regex" && (
694
- <Input
695
- type="text"
696
- icon={<TextIcon className="h-3 w-3 text-muted-foreground mb-1" />}
697
- value={text}
698
- onChange={(e) => setText(e.target.value)}
699
- placeholder="Text..."
700
- onKeyDown={(e) => {
701
- e.stopPropagation();
702
- if (e.key === "Enter") {
703
- handleApply();
704
- }
705
- }}
706
- className="shadow-none! border-border hover:shadow-none!"
707
- />
708
- )}
709
- {isMulti && (
710
- <FilterByValuesList
711
- column={column}
712
- calculateTopKRows={calculateTopKRows}
713
- chosenValues={new Set(values)}
714
- onChange={(next) => setValues(next.map(String))}
715
- creatable={true}
716
- />
717
- )}
718
- <FilterButtons
719
- onApply={handleApply}
720
- onClear={handleClear}
721
- clearButtonDisabled={!hasFilter}
722
- applyButtonDisabled={applyDisabled}
723
- />
724
- </div>
725
- );
726
- };
727
-
728
- /**
729
- * Seed the filter-by-values picker from a column's existing filter value.
730
- *
731
- * Reopening the picker should reflect what's already applied. Only `select`
732
- * filters carry checkbox-style values; other filter shapes (number, text,
733
- * etc.) seed an empty list.
734
- */
735
- export function seedFromFilter(value: ColumnFilterValue | undefined): {
736
- values: unknown[];
737
- operator: Extract<OperatorType, "in" | "not_in">;
738
- } {
739
- if (value && "type" in value && value.type === "select") {
740
- return {
741
- values: [...value.options],
742
- operator: value.operator === "not_in" ? "not_in" : "in",
743
- };
744
- }
745
- return { values: [], operator: "in" };
746
- }
747
-
748
- const PopoverFilterByValues = <TData, TValue>({
749
- setIsFilterValueOpen,
750
- calculateTopKRows,
751
- column,
752
- }: {
753
- setIsFilterValueOpen: (open: boolean) => void;
754
- calculateTopKRows?: CalculateTopKRows;
755
- column: Column<TData, TValue>;
756
- }) => {
757
- const seed = seedFromFilter(
758
- column.getFilterValue() as ColumnFilterValue | undefined,
759
- );
760
-
761
- const [chosenValues, setChosenValues] = useState<Set<unknown>>(
762
- () => new Set(seed.values),
763
- );
764
-
765
- const handleApply = () => {
766
- if (chosenValues.size === 0) {
767
- column.setFilterValue(undefined);
768
- return;
769
- }
770
- column.setFilterValue(
771
- Filter.select({
772
- options: [...chosenValues],
773
- operator: seed.operator,
774
- }),
775
- );
776
- };
777
-
778
- return (
779
- <DraggablePopover
780
- open={true}
781
- onOpenChange={(open) => !open && setIsFilterValueOpen(false)}
782
- className="w-80 p-0"
783
- >
784
- <PopoverClose className="absolute top-2 right-2">
785
- <Button
786
- variant="link"
787
- size="sm"
788
- onClick={() => setIsFilterValueOpen(false)}
789
- >
790
- <XIcon className="h-4 w-4" />
791
- </Button>
792
- </PopoverClose>
793
- <div className="flex flex-col gap-1.5 py-2">
794
- <FilterByValuesList
795
- column={column}
796
- calculateTopKRows={calculateTopKRows}
797
- chosenValues={chosenValues}
798
- onChange={(values) => setChosenValues(new Set(values))}
799
- />
800
- <FilterButtons
801
- onApply={handleApply}
802
- onClear={() => setChosenValues(new Set())}
803
- clearButtonDisabled={chosenValues.size === 0}
804
- />
805
- </div>
806
- </DraggablePopover>
807
- );
808
- };