@marimo-team/frontend 0.25.3-dev13 → 0.25.3-dev134

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 (565) hide show
  1. package/dist/assets/CellStatus-DC6FFQOg.js +1 -0
  2. package/dist/assets/{ConnectedDataExplorerComponent-TprnxZeJ.js → ConnectedDataExplorerComponent-BV1mVpaE.js} +1 -1
  3. package/dist/assets/{ErrorBoundary-CM13wrd8.js → ErrorBoundary-Ce-Ujlwj.js} +2 -2
  4. package/dist/assets/JsonOutput-CfEBzaqW.js +11 -0
  5. package/dist/assets/{LazyAnyLanguageCodeMirror-B4fCknq1.js → LazyAnyLanguageCodeMirror-DoxWX_Wp.js} +2 -2
  6. package/dist/assets/MarimoErrorOutput-Bh6o9zle.js +10 -0
  7. package/dist/assets/{RenderHTML-DX6i99Op.js → RenderHTML-COGZsXQV.js} +1 -1
  8. package/dist/assets/RunButton-DQ51plUv.js +1 -0
  9. package/dist/assets/__vite-browser-external-BynxqS4w.js +1 -0
  10. package/dist/assets/__vite-browser-external-DTOT9NDN.js +1 -0
  11. package/dist/assets/{add-cell-with-ai-BpD_790A.js → add-cell-with-ai-D7gtGUsg.js} +6 -6
  12. package/dist/assets/{add-connection-dialog-B1BXCjex.js → add-connection-dialog-CpMCc97S.js} +1 -1
  13. package/dist/assets/{agent-panel-CDFUc1uu.js → agent-panel-BSFYqJ9B.js} +3 -3
  14. package/dist/assets/ai-model-dropdown-D575Vid8.js +13 -0
  15. package/dist/assets/alert-dialog-8YiYLrfr.js +1 -0
  16. package/dist/assets/any-language-editor-BWmz0P_C.js +1 -0
  17. package/dist/assets/{app-config-button-AdV-QDD7.js → app-config-button-Cfcg_5Bz.js} +1 -1
  18. package/dist/assets/arrays-0R2reF2y.js +1 -0
  19. package/dist/assets/{blob-BG8yoQmx.js → blob-CszMu60N.js} +1 -1
  20. package/dist/assets/{button-COI-NGrx.js → button-Cl7haVNh.js} +1 -1
  21. package/dist/assets/{cache-panel-DTY1dqvi.js → cache-panel-DuBsA6oO.js} +1 -1
  22. package/dist/assets/{capabilities-BJvf-MD4.js → capabilities-DcB-Dd0T.js} +1 -1
  23. package/dist/assets/cell-editor-BLpOlLnM.js +42 -0
  24. package/dist/assets/cell-link-Cj0gGaMV.js +1 -0
  25. package/dist/assets/cells-SvbLY10y.js +220 -0
  26. package/dist/assets/{chat-display-DhgI2MS9.js → chat-display-D43_g3TX.js} +1 -1
  27. package/dist/assets/chat-panel-B_HAJMwx.js +4 -0
  28. package/dist/assets/chat-ui-BEcYCphu.js +4 -0
  29. package/dist/assets/circle-B0vOU-Dh.js +1 -0
  30. package/dist/assets/{code-visibility-BJImdpDi.js → code-visibility-D1Wf7-vD.js} +1 -1
  31. package/dist/assets/column-preview-CrzaJKk8.js +1 -0
  32. package/dist/assets/command-palette-Bm9yIVcD.js +1 -0
  33. package/dist/assets/{common-Sl3uthjg.js → common-BJyUxCzv.js} +1 -1
  34. package/dist/assets/{components-CskjK6xZ.js → components-9p_w2C6e.js} +1 -1
  35. package/dist/assets/components-B6gDDccL.js +1 -0
  36. package/dist/assets/{components-3cou6Mka.js → components-D1f_Cz4i.js} +1 -1
  37. package/dist/assets/config-7IjqNuVp.js +1 -0
  38. package/dist/assets/config-BC32AAdw.js +1 -0
  39. package/dist/assets/{config-CA1V-wjh.js → config-CXnC3MRv.js} +1 -1
  40. package/dist/assets/{copy-D8O_CYCG.js → copy-74EjuZso.js} +1 -1
  41. package/dist/assets/{copy-icon-BIiRXh_3.js → copy-icon-Craaocbu.js} +1 -1
  42. package/dist/assets/{createReducer-DgRODTW6.js → createReducer-B04CIO-e.js} +1 -1
  43. package/dist/assets/{datasource-DfbNb83e.js → datasource-C8KSVfSD.js} +1 -1
  44. package/dist/assets/{dates-CfmdTL6B.js → dates-CaPZVGtm.js} +1 -1
  45. package/dist/assets/{dependency-graph-panel-L5cBE5sl.js → dependency-graph-panel-BhmyJbUl.js} +3 -3
  46. package/dist/assets/dist-gaK_BThd.js +1 -0
  47. package/dist/assets/{documentation-panel-D7S8JIc2.js → documentation-panel-DcVG0Q0d.js} +1 -1
  48. package/dist/assets/download-Bx52VRE4.js +9 -0
  49. package/dist/assets/dropdown-menu-Cwi17BoX.js +1 -0
  50. package/dist/assets/edit-page-DUrwOHR-.js +9 -0
  51. package/dist/assets/{error-banner-COZ7SfYV.js → error-banner-m3mastc-.js} +1 -1
  52. package/dist/assets/{error-entries-CLnPDv7b.js → error-entries-11OuHzUF.js} +1 -1
  53. package/dist/assets/{error-panel-D2xrYLue.js → error-panel-XJy5S25F.js} +1 -1
  54. package/dist/assets/{es-Cqst59WX.js → es-Rg27gAEy.js} +1 -1
  55. package/dist/assets/{feedback-button-DzPunIqU.js → feedback-button-B7jh_B4w.js} +1 -1
  56. package/dist/assets/feedback-button-C-eKtxXE.js +1 -0
  57. package/dist/assets/file-explorer-panel-CnVxbF4A.js +1 -0
  58. package/dist/assets/{file-name-input-B4fRaQkI.js → file-name-input-BJuqjQqH.js} +2 -2
  59. package/dist/assets/floating-outline-8yyZ-MOJ.js +1 -0
  60. package/dist/assets/{formats-yZ06h1Pl.js → formats-CYyvbiZA.js} +1 -1
  61. package/dist/assets/{formatting-BqrP-n49.js → formatting-DW2u7HXI.js} +1 -1
  62. package/dist/assets/fullscreen-D-ldV-19.js +41 -0
  63. package/dist/assets/{gallery-page-BefvdsM7.js → gallery-page-DJvGHePf.js} +1 -1
  64. package/dist/assets/{ganttDiagram-EL5Y4UJY-2n7Ig5Jm.js → ganttDiagram-EL5Y4UJY-CYqkCfFG.js} +1 -1
  65. package/dist/assets/{glide-data-editor-C3eaYlXg.js → glide-data-editor-Cyc8DHZx.js} +2 -2
  66. package/dist/assets/{glide-utils-CIrAxdjv.js → glide-utils-DsTeJ7WA.js} +2 -2
  67. package/dist/assets/home-page-tRZJmSU6.js +1 -0
  68. package/dist/assets/{hooks-DzML9nez.js → hooks-CxGwybGw.js} +1 -1
  69. package/dist/assets/{html-to-image-DK9Zl1lU.js → html-to-image-BW0fcUS8.js} +1 -1
  70. package/dist/assets/index-CoxbqhGH.js +30 -0
  71. package/dist/assets/index-u08m0hQE.css +2 -0
  72. package/dist/assets/{input-BoBxR50a.js → input-DLA5Dhn3.js} +2 -2
  73. package/dist/assets/kiosk-mode-Cbxffiz9.js +1 -0
  74. package/dist/assets/{layout-Ck1RoL1B.js → layout-DvXJxBiL.js} +4 -4
  75. package/dist/assets/linear-Bma8J3iM.js +1 -0
  76. package/dist/assets/links-UwsB2RA1.js +1 -0
  77. package/dist/assets/{logs-panel-BRytaWaO.js → logs-panel-KtsY7TrR.js} +1 -1
  78. package/dist/assets/{markdown-renderer-DX0Xrrfy.js → markdown-renderer-DUgV7_fm.js} +1 -1
  79. package/dist/assets/menu-items-yD7IV3V4.js +1 -0
  80. package/dist/assets/{mermaid-C4EiVqcd.js → mermaid-DmekSy8J.js} +2 -2
  81. package/dist/assets/{name-cell-input-DlpTvPLa.js → name-cell-input-C3-Cj-Ek.js} +1 -1
  82. package/dist/assets/numbers-DJK15_4S.js +1 -0
  83. package/dist/assets/{objects-snlMn4yk.js → objects-rLPlQ3X_.js} +1 -1
  84. package/dist/assets/{once-Haz_uxEL.js → once-6KNTRW0u.js} +1 -1
  85. package/dist/assets/{outline-panel-B2WIpz-1.js → outline-panel-BzyY4JA6.js} +1 -1
  86. package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
  87. package/dist/assets/packages-panel-DxosbWko.js +1 -0
  88. package/dist/assets/{panel-accordion-state-BqSH5ttk.js → panel-accordion-state-BRbTib2B.js} +1 -1
  89. package/dist/assets/panels-Da3071Q4.js +1 -0
  90. package/dist/assets/precisionRound-BxlUs8G4.js +1 -0
  91. package/dist/assets/process-output-CSwx7rvo.js +1 -0
  92. package/dist/assets/{quadrantDiagram-AXDQQJYC-yBhCDI7E.js → quadrantDiagram-AXDQQJYC-D9KH5Zge.js} +1 -1
  93. package/dist/assets/react-vega-BTNeboR2.js +189 -0
  94. package/dist/assets/{readonly-code-display-MnMEoYW5.js → readonly-code-display-B9y9423Y.js} +1 -1
  95. package/dist/assets/{readonly-python-code-ggs4hAzC.js → readonly-python-code-Dgw6trlk.js} +1 -1
  96. package/dist/assets/{renderShortcut-C1JwYcqW.js → renderShortcut-Bxv9ZLnD.js} +1 -1
  97. package/dist/assets/{requests-lt0JK8Jt.js → requests-BIFR-h4M.js} +1 -1
  98. package/dist/assets/requests-DuLJN9Tf.js +1 -0
  99. package/dist/assets/{reveal-component-PiV1eQk9.js → reveal-component-B9A4wkG-.js} +37 -37
  100. package/dist/assets/run-page-C1MQ5b_A.js +1 -0
  101. package/dist/assets/{runs-BLp5jezv.js → runs-C8uOPNAW.js} +1 -1
  102. package/dist/assets/{runtime-details-state-CoL-p0MC.js → runtime-details-state-D_hOQL9T.js} +1 -1
  103. package/dist/assets/{save-worker-BbUSwZRG.js → save-worker-UwdGcNK5.js} +2 -1
  104. package/dist/assets/scratchpad-panel-CBCsPmMW.js +1 -0
  105. package/dist/assets/{scroll-to-bottom-button-1FyowpWV.js → scroll-to-bottom-button-CidjyqiH.js} +1 -1
  106. package/dist/assets/secrets-panel-ConQpchl.js +1 -0
  107. package/dist/assets/select-CgWQvW1F.js +1 -0
  108. package/dist/assets/{session-DqoWmb7X.js → session-BHgGkjDm.js} +1 -1
  109. package/dist/assets/session-panel-CiHCKPlx.js +1 -0
  110. package/dist/assets/snippets-panel-C0VDE_4i.js +1 -0
  111. package/dist/assets/{spec-BfSBcO5B.js → spec-DFtwOyXT.js} +1 -1
  112. package/dist/assets/state-BYETGwDZ.js +1 -0
  113. package/dist/assets/{state-uwRvJLb8.js → state-CZu2E2Lb.js} +1 -1
  114. package/dist/assets/{state-C3oDoyFe.js → state-ClBFtZxn.js} +1 -1
  115. package/dist/assets/{state-DxQnC_1I.js → state-CrLrURYG.js} +1 -1
  116. package/dist/assets/{state-DtGB7xeJ.js → state-DrraMmqz.js} +1 -1
  117. package/dist/assets/state-DvU2AiFx.js +107 -0
  118. package/dist/assets/{strings-B2vv-ENv.js → strings-3lNX212T.js} +1 -1
  119. package/dist/assets/{swiper-component-a07domrZ.js → swiper-component-BwGv-Pu1.js} +1 -1
  120. package/dist/assets/switch-D2gdC_ep.js +1 -0
  121. package/dist/assets/tabs-BLczoY3k.js +1 -0
  122. package/dist/assets/{terminal-wnSHYT8N.js → terminal-DLgGyFIP.js} +1 -1
  123. package/dist/assets/{time-MgToa8VM.js → time-DswSXBDk.js} +1 -1
  124. package/dist/assets/toast-trUlkvx3.js +1 -0
  125. package/dist/assets/tooltip-B5lAA_jn.js +1 -0
  126. package/dist/assets/tooltip-BiQdpXA0.js +61 -0
  127. package/dist/assets/tracing-C5d51Nmi.js +1 -0
  128. package/dist/assets/tracing-panel-B89R8dWE.js +2 -0
  129. package/dist/assets/{tree-actions-DnUokmva.js → tree-actions-Cph8FVzh.js} +1 -1
  130. package/dist/assets/use-restore-focus-DMSzeuUr.js +1 -0
  131. package/dist/assets/{useAddCell-IN24thff.js → useAddCell-VPkB72pn.js} +1 -1
  132. package/dist/assets/useAsyncData-qvoPYHtx.js +1 -0
  133. package/dist/assets/useBoolean-BkeUcn1n.js +1 -0
  134. package/dist/assets/useCellActionButton--zI3GFnt.js +1 -0
  135. package/dist/assets/useDebounce-DwTQ_1Pu.js +1 -0
  136. package/dist/assets/{useDeepCompareMemoize-DFIVN9dn.js → useDeepCompareMemoize-B2DVK2De.js} +1 -1
  137. package/dist/assets/useDelayElapsed-BlsDT4TV.js +1 -0
  138. package/dist/assets/{useDeleteCell-fQlM46Y2.js → useDeleteCell-CjewKeSr.js} +1 -1
  139. package/dist/assets/{useDependencyPanelTab-ImXYINm_.js → useDependencyPanelTab-Bt_ka-wl.js} +1 -1
  140. package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
  141. package/dist/assets/{useEventListener-D9cftcHj.js → useEventListener-DPOTkksd.js} +1 -1
  142. package/dist/assets/{useIframeCapabilities-CwTkczVN.js → useIframeCapabilities-sHeZt_EA.js} +1 -1
  143. package/dist/assets/{useInstallPackage-BW06eter.js → useInstallPackage-BfNKN33w.js} +1 -1
  144. package/dist/assets/{useInterval--x3s1VpI.js → useInterval-BcdwHHB5.js} +1 -1
  145. package/dist/assets/useNotebookActions-DV2S6KaG.js +1 -0
  146. package/dist/assets/{useRunCells-DSJPXE-j.js → useRunCells-BupCZpzk.js} +1 -1
  147. package/dist/assets/{useSplitCell-DQyMF5gd.js → useSplitCell-CaLIR0TS.js} +1 -1
  148. package/dist/assets/useStateForKey-CGMJQT8x.js +1 -0
  149. package/dist/assets/{useTheme-n8Dj1zH7.js → useTheme-C2dnh2vM.js} +1 -1
  150. package/dist/assets/{utils-CaQYvazl.js → utils-DfElfBpz.js} +1 -1
  151. package/dist/assets/vega-component-DJf6ho22.js +1 -0
  152. package/dist/assets/{vega-embed-container-DJPNkHPb.js → vega-embed-container-DtArSJz1.js} +1 -1
  153. package/dist/assets/vega-loader.browser-Bu25TKax.js +6 -0
  154. package/dist/assets/worker-jm2VC7pS.js +159 -0
  155. package/dist/assets/{write-secret-modal-DzKAInL2.js → write-secret-modal-CBi2vNK_.js} +1 -1
  156. package/dist/assets/{xychartDiagram-S5SC5T6Z-KbGzG6-u.js → xychartDiagram-S5SC5T6Z-CeRnBS5e.js} +1 -1
  157. package/dist/index.html +81 -79
  158. package/package.json +14 -14
  159. package/src/__tests__/host-imports.test.ts +1 -0
  160. package/src/__tests__/module-entry.test.ts +32 -0
  161. package/src/__tests__/mount.test.ts +0 -20
  162. package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
  163. package/src/components/ai/ai-model-dropdown.tsx +11 -6
  164. package/src/components/app-config/ai-config.tsx +7 -2
  165. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  166. package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
  167. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  168. package/src/components/chat/acp/blocks.tsx +3 -2
  169. package/src/components/chat/acp/session-tabs.tsx +8 -3
  170. package/src/components/chat/chat-components.tsx +2 -0
  171. package/src/components/chat/chat-panel.tsx +9 -8
  172. package/src/components/chat/chat-utils.ts +4 -8
  173. package/src/components/data-table/TableTopBar.tsx +2 -0
  174. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  175. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  176. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  177. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  178. package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
  179. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  180. package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
  181. package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
  182. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  183. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  184. package/src/components/data-table/cell-selection/feature.ts +2 -2
  185. package/src/components/data-table/cell-selection/types.ts +2 -2
  186. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  187. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  188. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  189. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  190. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  191. package/src/components/data-table/charts/charts.tsx +40 -30
  192. package/src/components/data-table/charts/storage.ts +16 -5
  193. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  194. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  195. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  196. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  197. package/src/components/data-table/columns.tsx +45 -46
  198. package/src/components/data-table/context-menu.tsx +36 -20
  199. package/src/components/data-table/data-table.tsx +13 -1
  200. package/src/components/data-table/date-popover.tsx +6 -4
  201. package/src/components/data-table/export-actions.tsx +76 -48
  202. package/src/components/data-table/range-focus/atoms.ts +4 -6
  203. package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
  204. package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
  205. package/src/components/data-table/renderers.tsx +16 -7
  206. package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
  207. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
  208. package/src/components/data-table/search-highlight.tsx +79 -0
  209. package/src/components/data-table/types.ts +1 -0
  210. package/src/components/data-table/url-detector.tsx +49 -9
  211. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  212. package/src/components/datasources/__tests__/column-preview.test.tsx +63 -2
  213. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  214. package/src/components/datasources/column-preview.tsx +8 -2
  215. package/src/components/datasources/datasources.tsx +48 -35
  216. package/src/components/debugger/debugger-code.tsx +5 -0
  217. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  218. package/src/components/dependency-graph/elements.ts +24 -21
  219. package/src/components/dependency-graph/panels.tsx +2 -1
  220. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  221. package/src/components/editor/SortableCell.tsx +1 -3
  222. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  223. package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
  224. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
  225. package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
  226. package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
  227. package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
  228. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  229. package/src/components/editor/cell/CreateCellButton.tsx +8 -10
  230. package/src/components/editor/cell/DeleteButton.tsx +1 -0
  231. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  232. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  233. package/src/components/editor/cell/code/cell-editor.tsx +1 -1
  234. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  235. package/src/components/editor/cell/collapse.tsx +5 -3
  236. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  237. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
  238. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  239. package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
  240. package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
  241. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
  242. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  243. package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
  244. package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -1
  245. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
  246. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
  247. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  248. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
  249. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  250. package/src/components/editor/connections/components.tsx +1 -1
  251. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  252. package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
  253. package/src/components/editor/controls/command-palette.tsx +22 -10
  254. package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
  255. package/src/components/editor/dynamic-favicon.tsx +21 -40
  256. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
  257. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  258. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
  259. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  260. package/src/components/editor/file-tree/file-explorer.tsx +45 -8
  261. package/src/components/editor/file-tree/file-name-input.tsx +1 -0
  262. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  263. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  264. package/src/components/editor/header/status.tsx +28 -5
  265. package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
  266. package/src/components/editor/links/cell-link.tsx +14 -5
  267. package/src/components/editor/navigation/focus-utils.ts +4 -4
  268. package/src/components/editor/notebook-banner.tsx +1 -0
  269. package/src/components/editor/notebook-cell.tsx +11 -2
  270. package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
  271. package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
  272. package/src/components/editor/output/ansi-reduce.ts +33 -20
  273. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  274. package/src/components/editor/package-alert.tsx +14 -7
  275. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
  276. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  277. package/src/components/home/components.tsx +17 -31
  278. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  279. package/src/components/icons/large-spinner.tsx +3 -14
  280. package/src/components/icons/spinner.tsx +1 -1
  281. package/src/components/mcp/mcp-status-indicator.tsx +1 -1
  282. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  283. package/src/components/pages/home-page.tsx +164 -91
  284. package/src/components/scratchpad/scratchpad.test.tsx +95 -0
  285. package/src/components/scratchpad/scratchpad.tsx +16 -3
  286. package/src/components/slides/reveal-component.tsx +4 -2
  287. package/src/components/slides/slide-cell-view.tsx +1 -1
  288. package/src/components/slides/slide-form.tsx +1 -0
  289. package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
  290. package/src/components/tracing/tracing.tsx +45 -41
  291. package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
  292. package/src/components/ui/alert-dialog.tsx +1 -1
  293. package/src/components/ui/draggable-popover.tsx +24 -2
  294. package/src/core/ai/context/providers/datasource.ts +6 -2
  295. package/src/core/ai/tools/base.ts +16 -7
  296. package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
  297. package/src/core/ai/tools/registry.ts +13 -8
  298. package/src/core/ai/tools/sample-tool.ts +6 -7
  299. package/src/core/attachments/state.ts +5 -8
  300. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
  301. package/src/core/cells/__tests__/cell.test.ts +39 -0
  302. package/src/core/cells/__tests__/cells.test.ts +3 -1
  303. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  304. package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
  305. package/src/core/cells/__tests__/session.test.ts +117 -36
  306. package/src/core/cells/cell.ts +14 -3
  307. package/src/core/cells/cells.ts +3 -1
  308. package/src/core/cells/pending-delete-service.ts +2 -6
  309. package/src/core/cells/session.ts +1 -1
  310. package/src/core/cells/types.ts +10 -1
  311. package/src/core/codemirror/__tests__/setup.test.ts +29 -29
  312. package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -0
  313. package/src/core/codemirror/cells/extensions.ts +7 -3
  314. package/src/core/codemirror/keymaps/vim.ts +2 -6
  315. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  316. package/src/core/codemirror/language/extension.ts +8 -8
  317. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  318. package/src/core/codemirror/language/languages/python.ts +16 -10
  319. package/src/core/codemirror/language/languages/sql/sql.ts +9 -7
  320. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  321. package/src/core/codemirror/language/types.ts +7 -7
  322. package/src/core/codemirror/rtc/extension.ts +24 -12
  323. package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
  324. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  325. package/src/core/codemirror/utils.ts +1 -0
  326. package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
  327. package/src/core/datasets/data-source-discovery.ts +4 -6
  328. package/src/core/document/__tests__/codemirror.test.ts +485 -0
  329. package/src/core/document/__tests__/draft.test.ts +322 -0
  330. package/src/core/document/__tests__/fixtures.ts +92 -0
  331. package/src/core/document/__tests__/hooks.test.tsx +386 -0
  332. package/src/core/document/__tests__/lifecycle-scenarios.test.ts +61 -0
  333. package/src/core/document/__tests__/model.test.ts +191 -0
  334. package/src/core/document/__tests__/protocol-fixtures.ts +38 -0
  335. package/src/core/document/__tests__/recovery-scenarios.test.ts +230 -0
  336. package/src/core/document/__tests__/scenario-fixture.ts +43 -0
  337. package/src/core/document/__tests__/scenarios.test.ts +205 -0
  338. package/src/core/document/__tests__/state.test.ts +438 -0
  339. package/src/core/document/__tests__/submission.test.ts +203 -0
  340. package/src/core/document/__tests__/test-host.test.ts +92 -0
  341. package/src/core/document/__tests__/test-host.ts +247 -0
  342. package/src/core/document/__tests__/test-notebook.ts +149 -0
  343. package/src/core/document/__tests__/user.ts +61 -0
  344. package/src/core/document/codemirror.ts +311 -0
  345. package/src/core/document/draft.ts +472 -0
  346. package/src/core/document/hooks.tsx +118 -0
  347. package/src/core/document/index.ts +15 -0
  348. package/src/core/document/model.ts +55 -0
  349. package/src/core/document/select.ts +41 -0
  350. package/src/core/document/state.ts +374 -0
  351. package/src/core/document/sync.ts +369 -0
  352. package/src/core/host/AGENTS.md +8 -2
  353. package/src/core/host/__tests__/attachments.test.ts +56 -0
  354. package/src/core/host/__tests__/document.test.ts +126 -0
  355. package/src/core/host/__tests__/fixtures.ts +71 -0
  356. package/src/core/host/__tests__/replica.test.ts +550 -0
  357. package/src/core/host/__tests__/static.test.ts +169 -0
  358. package/src/core/host/__tests__/wasm.test.ts +162 -0
  359. package/src/core/host/backend.ts +19 -0
  360. package/src/core/host/connection.ts +1 -40
  361. package/src/core/host/index.ts +14 -0
  362. package/src/core/host/replica.ts +286 -0
  363. package/src/core/host/resources/attachments.ts +22 -0
  364. package/src/core/host/resources/document.ts +101 -0
  365. package/src/core/host/static.ts +72 -0
  366. package/src/core/host/wasm.ts +102 -0
  367. package/src/core/hotkeys/actions.ts +2 -4
  368. package/src/core/islands/__tests__/bootstrap.test.ts +0 -26
  369. package/src/core/islands/bootstrap.ts +0 -1
  370. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  371. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  372. package/src/core/network/connection.ts +4 -2
  373. package/src/core/network/useConnectionNotice.ts +8 -2
  374. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  375. package/src/core/runtime/__tests__/runtime.test.ts +32 -58
  376. package/src/core/runtime/runtime.ts +38 -42
  377. package/src/core/runtime/types.ts +0 -2
  378. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  379. package/src/core/state/jotai.ts +1 -1
  380. package/src/core/static/__tests__/files.test.ts +38 -10
  381. package/src/core/static/files.ts +2 -0
  382. package/src/core/wasm/bridge.ts +38 -10
  383. package/src/core/wasm/store.ts +3 -3
  384. package/src/core/wasm/worker/bootstrap.ts +2 -1
  385. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  386. package/src/core/wasm/worker/types.ts +11 -0
  387. package/src/core/wasm/worker/worker.ts +48 -0
  388. package/src/core/websocket/__tests__/backend.test.ts +200 -0
  389. package/src/core/websocket/__tests__/connection-state.test.ts +0 -12
  390. package/src/core/websocket/__tests__/useNotebookReplica.hook.test.tsx +141 -0
  391. package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +154 -428
  392. package/src/core/websocket/backend.ts +106 -0
  393. package/src/core/websocket/connection-state.ts +1 -11
  394. package/src/core/websocket/state.ts +7 -0
  395. package/src/core/websocket/transports/__tests__/notebook.test.ts +445 -0
  396. package/src/core/websocket/transports/notebook.ts +190 -0
  397. package/src/core/websocket/types.ts +2 -2
  398. package/src/core/websocket/useNotebookReplica.ts +69 -0
  399. package/src/core/websocket/useNotebookSession.tsx +10 -22
  400. package/src/css/globals.css +5 -0
  401. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  402. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  403. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  404. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  405. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  406. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  407. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  408. package/src/hooks/useAsyncData.ts +3 -3
  409. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  410. package/src/hooks/useDebounce.ts +6 -10
  411. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  412. package/src/hooks/useDelayElapsed.ts +14 -10
  413. package/src/hooks/useElapsedTime.ts +3 -3
  414. package/src/hooks/useEventListener.ts +1 -2
  415. package/src/hooks/useInputHistory.ts +4 -7
  416. package/src/hooks/useInternalStateWithSync.ts +6 -6
  417. package/src/hooks/useResizeObserver.ts +4 -7
  418. package/src/hooks/useScript.ts +67 -70
  419. package/src/hooks/useStateForKey.ts +93 -0
  420. package/src/mount.tsx +0 -4
  421. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  422. package/src/plugins/core/registerReactComponent.tsx +1 -1
  423. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  424. package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
  425. package/src/plugins/impl/DataTablePlugin.tsx +29 -33
  426. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  427. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  428. package/src/plugins/impl/FormPlugin.tsx +1 -1
  429. package/src/plugins/impl/RangeSliderPlugin.tsx +0 -1
  430. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  431. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  432. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +117 -1
  433. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  434. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  435. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
  436. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  437. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  438. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  439. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  440. package/src/plugins/impl/chat/chat-ui.tsx +14 -11
  441. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  442. package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
  443. package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
  444. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  445. package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
  446. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  447. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
  448. package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
  449. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
  450. package/src/plugins/impl/data-frames/panel.tsx +43 -16
  451. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  452. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  453. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  454. package/src/plugins/impl/panel/utils.ts +17 -0
  455. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  456. package/src/plugins/impl/plotly/selection.ts +25 -19
  457. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  458. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  459. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  460. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  461. package/src/stories/button.stories.tsx +1 -0
  462. package/src/stories/editor.stories.tsx +24 -17
  463. package/src/stories/form-wrapper.stories.tsx +2 -2
  464. package/src/stories/select.stories.tsx +2 -2
  465. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  466. package/src/utils/__tests__/arrays.test.ts +35 -0
  467. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  468. package/src/utils/__tests__/numbers.test.ts +48 -1
  469. package/src/utils/__tests__/objects.test.ts +21 -0
  470. package/src/utils/arrays.ts +10 -0
  471. package/src/utils/blob.ts +1 -1
  472. package/src/utils/numbers.ts +28 -17
  473. package/src/utils/objects.ts +3 -7
  474. package/src/utils/once.ts +19 -19
  475. package/src/utils/tracer.ts +9 -5
  476. package/src/utils/zod-utils.ts +1 -3
  477. package/dist/assets/CellStatus-DVOHpdeJ.js +0 -1
  478. package/dist/assets/JsonOutput-Cx1iyibB.js +0 -11
  479. package/dist/assets/MarimoErrorOutput-s_5GOX8k.js +0 -10
  480. package/dist/assets/RunButton-BKoh0zYG.js +0 -1
  481. package/dist/assets/__vite-browser-external-CYO_P3S8.js +0 -1
  482. package/dist/assets/__vite-browser-external-FeDVGZU8.js +0 -1
  483. package/dist/assets/ai-model-dropdown-i1vfGeVi.js +0 -13
  484. package/dist/assets/alert-dialog-BaPGzeOK.js +0 -1
  485. package/dist/assets/any-language-editor-BdTWdMCI.js +0 -1
  486. package/dist/assets/arrays-BqUx5USx.js +0 -1
  487. package/dist/assets/cell-editor-BKJ06H5F.js +0 -21
  488. package/dist/assets/cell-link-8Auigi8P.js +0 -1
  489. package/dist/assets/cells-C6YGYGdi.js +0 -220
  490. package/dist/assets/chat-panel-Cau71Ygr.js +0 -4
  491. package/dist/assets/chat-ui-C5ql1Up-.js +0 -4
  492. package/dist/assets/circle-DXf-VWZG.js +0 -1
  493. package/dist/assets/circle-play-CYIb0qT6.js +0 -1
  494. package/dist/assets/column-preview-BZ_iNhtJ.js +0 -1
  495. package/dist/assets/command-palette-DDC3kBet.js +0 -1
  496. package/dist/assets/components-YBmtV0p6.js +0 -1
  497. package/dist/assets/config-DRIpOKqh.js +0 -1
  498. package/dist/assets/config-Dy28fDwn.js +0 -1
  499. package/dist/assets/dist-iaThVDkA.js +0 -1
  500. package/dist/assets/download-C03FOElq.js +0 -9
  501. package/dist/assets/dropdown-menu-C1rnl-0o.js +0 -1
  502. package/dist/assets/edit-page-D_Rg0gQO.js +0 -9
  503. package/dist/assets/feedback-button-Kla7i5RT.js +0 -1
  504. package/dist/assets/file-explorer-panel-Uk4_QIJQ.js +0 -1
  505. package/dist/assets/floating-outline-B5MaM1JS.js +0 -1
  506. package/dist/assets/fullscreen-B9tHcfpV.js +0 -41
  507. package/dist/assets/home-page-hmvKlc1w.js +0 -4
  508. package/dist/assets/index-6b4mf8Ai.css +0 -2
  509. package/dist/assets/index-ptK1gxmo.js +0 -30
  510. package/dist/assets/kiosk-mode-BZECfg9k.js +0 -1
  511. package/dist/assets/linear-0eij_aAG.js +0 -1
  512. package/dist/assets/link-NuFVR7G9.js +0 -1
  513. package/dist/assets/links-DkkL9DVa.js +0 -1
  514. package/dist/assets/menu-items-BrwnTgyK.js +0 -1
  515. package/dist/assets/numbers-Mk3-CcoU.js +0 -1
  516. package/dist/assets/packages-panel-CI5ff9b-.js +0 -1
  517. package/dist/assets/panels-BCcZ_yLK.js +0 -107
  518. package/dist/assets/precisionRound-Bq_nmf5u.js +0 -1
  519. package/dist/assets/process-output-f3C3PD0Z.js +0 -1
  520. package/dist/assets/react-vega-C3rYGtP6.js +0 -189
  521. package/dist/assets/requests-CgSY1X4a.js +0 -1
  522. package/dist/assets/run-page-AfZhtEh1.js +0 -1
  523. package/dist/assets/scratchpad-panel-D2rWg4k8.js +0 -1
  524. package/dist/assets/secrets-panel-D7KN4tVs.js +0 -1
  525. package/dist/assets/select-DTBn5eTb.js +0 -1
  526. package/dist/assets/session-panel-CnANhcTo.js +0 -1
  527. package/dist/assets/snippets-panel-ClGHtEKQ.js +0 -1
  528. package/dist/assets/state-BAJYRhmO.js +0 -1
  529. package/dist/assets/state-CbjBtkdd.js +0 -3
  530. package/dist/assets/switch-CTaiAjrz.js +0 -1
  531. package/dist/assets/tabs-BuQlZFbt.js +0 -1
  532. package/dist/assets/toast-BGzLGnvw.js +0 -1
  533. package/dist/assets/tooltip-C9TuY18o.js +0 -1
  534. package/dist/assets/tooltip-mT3CGest.js +0 -61
  535. package/dist/assets/tracing-Dz2rYOFL.js +0 -1
  536. package/dist/assets/tracing-panel-DqQY9V91.js +0 -2
  537. package/dist/assets/use-restore-focus-BxEGwIbk.js +0 -1
  538. package/dist/assets/useAsyncData-C7aJJz0Y.js +0 -1
  539. package/dist/assets/useBoolean-d0Tty94N.js +0 -1
  540. package/dist/assets/useCellActionButton-DmaFZ4oF.js +0 -1
  541. package/dist/assets/useDebounce-B_ccBZTp.js +0 -1
  542. package/dist/assets/useNotebookActions-DHt3s-ia.js +0 -1
  543. package/dist/assets/vega-component-IouMe13t.js +0 -1
  544. package/dist/assets/vega-loader.browser-CLRkNgm7.js +0 -6
  545. package/dist/assets/worker-DTQ7oH2A.js +0 -158
  546. package/dist/assets/ws-BXWY541V.js +0 -22
  547. package/src/core/host/__tests__/events.test.ts +0 -46
  548. package/src/core/host/__tests__/notebook-client.test.ts +0 -191
  549. package/src/core/host/__tests__/protocol.test.ts +0 -214
  550. package/src/core/host/events.ts +0 -60
  551. package/src/core/host/notebook-client.ts +0 -226
  552. package/src/core/host/protocol.ts +0 -1943
  553. package/src/core/state/__tests__/jotai.test.ts +0 -25
  554. package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
  555. package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -140
  556. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  557. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
  558. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  559. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  560. package/src/core/websocket/transports/basic.ts +0 -102
  561. package/src/core/websocket/transports/create.ts +0 -31
  562. package/src/core/websocket/transports/sse.ts +0 -308
  563. package/src/core/websocket/transports/transport.ts +0 -50
  564. package/src/core/websocket/transports/ws.ts +0 -98
  565. package/src/core/websocket/useNotebookClient.ts +0 -80
@@ -41,6 +41,7 @@ import {
41
41
  isNumericType,
42
42
  } from "./types";
43
43
  import { SentinelCell, WhitespaceMarkers } from "./sentinel-cell";
44
+ import { highlightMatches } from "./search-highlight";
44
45
  import { detectSentinel, splitLeadingTrailingWhitespace } from "./utils";
45
46
  import { uniformSample } from "./uniformSample";
46
47
  import { MarkdownUrlDetector, UrlDetector } from "./url-detector";
@@ -135,6 +136,7 @@ export function generateColumns<T>({
135
136
  }): ColumnDef<T>[] {
136
137
  // Row-headers are typically index columns
137
138
  const rowHeadersSet = new Set(rowHeaders.map(([columnName]) => columnName));
139
+ const wrappedColumnsSet = new Set(wrappedColumns);
138
140
 
139
141
  const typesByColumn = Maps.keyBy(fieldTypes, (entry) => entry[0]);
140
142
 
@@ -277,7 +279,7 @@ export function generateColumns<T>({
277
279
  );
278
280
  },
279
281
 
280
- cell: ({ column, renderValue, getValue, cell }) => {
282
+ cell: ({ column, renderValue, getValue, cell, table }) => {
281
283
  function selectCell() {
282
284
  if (selection !== "single-cell" && selection !== "multi-cell") {
283
285
  return;
@@ -287,7 +289,7 @@ export function generateColumns<T>({
287
289
  }
288
290
 
289
291
  const justify = getJustify(key);
290
- const wrapped = wrappedColumns?.includes(key);
292
+ const wrapped = wrappedColumnsSet.has(key);
291
293
  const isCellSelected = cell?.getIsSelected?.() || false;
292
294
  const canSelectCell =
293
295
  (selection === "single-cell" || selection === "multi-cell") &&
@@ -309,6 +311,7 @@ export function generateColumns<T>({
309
311
  getValue,
310
312
  selectCell,
311
313
  cellStyles,
314
+ highlightPattern: table.options.meta?.highlightPattern,
312
315
  });
313
316
 
314
317
  // Row headers are bold
@@ -585,12 +588,14 @@ function renderDate({
585
588
  dtype,
586
589
  displayValue,
587
590
  locale,
591
+ highlightPattern,
588
592
  }: {
589
593
  value: Date;
590
594
  dataType?: DataType;
591
595
  dtype?: string;
592
596
  displayValue?: string;
593
597
  locale: string;
598
+ highlightPattern?: RegExp;
594
599
  }): React.ReactNode {
595
600
  const type = dataType === "date" ? "date" : "datetime";
596
601
  const timezone = extractTimezone(dtype);
@@ -599,7 +604,7 @@ function renderDate({
599
604
 
600
605
  return (
601
606
  <DatePopover date={value} type={type}>
602
- {exactValue}
607
+ {highlightMatches(exactValue, highlightPattern)}
603
608
  </DatePopover>
604
609
  );
605
610
  }
@@ -610,12 +615,14 @@ export function renderCellValue<TData, TValue>({
610
615
  getValue,
611
616
  selectCell,
612
617
  cellStyles,
618
+ highlightPattern,
613
619
  }: {
614
620
  column: Column<TData, TValue>;
615
621
  renderValue: () => TValue | null;
616
622
  getValue: () => TValue;
617
623
  selectCell?: () => void;
618
624
  cellStyles?: string;
625
+ highlightPattern?: RegExp;
619
626
  }) {
620
627
  const value = getValue();
621
628
  const format = column.getColumnFormatting?.();
@@ -625,6 +632,28 @@ export function renderCellValue<TData, TValue>({
625
632
 
626
633
  const isWrapped = column.getColumnWrapping?.() === "wrap";
627
634
 
635
+ const textCell = (text: string) => (
636
+ <div onClick={selectCell} className={cellStyles}>
637
+ {highlightMatches(text, highlightPattern)}
638
+ </div>
639
+ );
640
+ const dateCell = (date: Date, displayValue?: string) => (
641
+ <div onClick={selectCell} className={cellStyles}>
642
+ <WithLocale>
643
+ {(locale) =>
644
+ renderDate({
645
+ value: date,
646
+ dataType,
647
+ dtype,
648
+ displayValue,
649
+ locale,
650
+ highlightPattern,
651
+ })
652
+ }
653
+ </WithLocale>
654
+ </div>
655
+ );
656
+
628
657
  // Sentinel values (null, whitespace, NaN, Infinity, NaT) rendered specially.
629
658
  // Empty strings are left as-is
630
659
  const sentinel = detectSentinel(value, dataType, dtype);
@@ -640,23 +669,10 @@ export function renderCellValue<TData, TValue>({
640
669
  try {
641
670
  const date = new Date(value);
642
671
  if (!format || !isValid(date)) {
643
- return (
644
- <div onClick={selectCell} className={cellStyles}>
645
- {value}
646
- </div>
647
- );
672
+ return textCell(value);
648
673
  }
649
674
 
650
- const displayValue = String(column.applyColumnFormatting(value));
651
- return (
652
- <div onClick={selectCell} className={cellStyles}>
653
- <WithLocale>
654
- {(locale) =>
655
- renderDate({ value: date, dataType, dtype, displayValue, locale })
656
- }
657
- </WithLocale>
658
- </div>
659
- );
675
+ return dateCell(date, String(column.applyColumnFormatting(value)));
660
676
  } catch (error) {
661
677
  Logger.error("Error parsing datetime, fallback to string", error);
662
678
  }
@@ -672,17 +688,9 @@ export function renderCellValue<TData, TValue>({
672
688
  }
673
689
 
674
690
  // e.g. 2010-10-07 17:15:00
675
- const displayValue = format
676
- ? String(column.applyColumnFormatting(value))
677
- : undefined;
678
- return (
679
- <div onClick={selectCell} className={cellStyles}>
680
- <WithLocale>
681
- {(locale) =>
682
- renderDate({ value, dataType, dtype, displayValue, locale })
683
- }
684
- </WithLocale>
685
- </div>
691
+ return dateCell(
692
+ value,
693
+ format ? String(column.applyColumnFormatting(value)) : undefined,
686
694
  );
687
695
  }
688
696
 
@@ -728,7 +736,7 @@ export function renderCellValue<TData, TValue>({
728
736
  className={cn(cellStyles, isWrapped && COLUMN_WRAPPING_STYLES)}
729
737
  >
730
738
  <WhitespaceMarkers value={leading} />
731
- <UrlDetector parts={parts} />
739
+ <UrlDetector parts={parts} highlightPattern={highlightPattern} />
732
740
  <WhitespaceMarkers value={trailing} />
733
741
  </div>
734
742
  );
@@ -754,11 +762,7 @@ export function renderCellValue<TData, TValue>({
754
762
  }
755
763
 
756
764
  if (format) {
757
- return (
758
- <div onClick={selectCell} className={cellStyles}>
759
- {column.applyColumnFormatting(value)}
760
- </div>
761
- );
765
+ return textCell(String(column.applyColumnFormatting(value)));
762
766
  }
763
767
 
764
768
  // Format to the correct locale
@@ -768,26 +772,19 @@ export function renderCellValue<TData, TValue>({
768
772
  <LocaleNumber
769
773
  value={value}
770
774
  minFractionDigits={column.columnDef.meta?.minFractionDigits}
775
+ highlightPattern={highlightPattern}
771
776
  />
772
777
  </div>
773
778
  );
774
779
  }
775
780
 
776
781
  if (typeof value === "boolean") {
777
- return (
778
- <div onClick={selectCell} className={cellStyles}>
779
- {value ? "True" : "False"}
780
- </div>
781
- );
782
+ return textCell(value ? "True" : "False");
782
783
  }
783
784
 
784
785
  if (isPrimitiveOrNullish(value)) {
785
786
  const rendered = renderValue();
786
- return (
787
- <div onClick={selectCell} className={cellStyles}>
788
- {rendered == null ? "" : String(rendered)}
789
- </div>
790
- );
787
+ return textCell(rendered == null ? "" : String(rendered));
791
788
  }
792
789
 
793
790
  const mimeValues = getMimeValues(value);
@@ -825,14 +822,16 @@ export function renderCellValue<TData, TValue>({
825
822
  export const LocaleNumber = ({
826
823
  value,
827
824
  minFractionDigits,
825
+ highlightPattern,
828
826
  }: {
829
827
  value: number;
830
828
  minFractionDigits?: number;
829
+ highlightPattern?: RegExp;
831
830
  }) => {
832
831
  const { locale } = useLocale();
833
832
  const format = useNumberFormatter({
834
833
  minimumFractionDigits: minFractionDigits,
835
834
  maximumFractionDigits: maxFractionalDigits(locale),
836
835
  });
837
- return format.format(value);
836
+ return highlightMatches(format.format(value), highlightPattern);
838
837
  };
@@ -12,7 +12,7 @@ import { Logger } from "@/utils/Logger";
12
12
  import type { Cell } from "@tanstack/react-table";
13
13
  import { useAtomValue } from "jotai";
14
14
  import { CopyIcon, FilterIcon, SquareStack } from "lucide-react";
15
- import type { RefObject } from "react";
15
+ import { type RefObject, useRef, useState } from "react";
16
16
  import useEvent from "react-use-event-hook";
17
17
  import {
18
18
  ContextMenu,
@@ -123,8 +123,21 @@ export const DataTableContextMenu = <TData,>({
123
123
  tableRef: RefObject<HTMLTableSectionElement | null>;
124
124
  copyAllCells: () => void;
125
125
  }) => {
126
+ const [activeCell, setActiveCell] = useState<Cell<TData, unknown> | null>(
127
+ null,
128
+ );
129
+ const highlightedCell = useRef<Element | null>(null);
126
130
  const handleContextMenuChange = useEvent((open: boolean) => {
131
+ highlightedCell.current?.classList.remove("bg-(--green-4)");
132
+ highlightedCell.current = null;
133
+ if (!open) {
134
+ // Forget the cell so a later right-click outside any cell can't reuse it
135
+ contextMenuRef.current = null;
136
+ return;
137
+ }
138
+
127
139
  const cell = contextMenuRef.current;
140
+ setActiveCell(cell);
128
141
  if (!cell) {
129
142
  return;
130
143
  }
@@ -138,42 +151,45 @@ export const DataTableContextMenu = <TData,>({
138
151
  return;
139
152
  }
140
153
 
141
- if (open) {
142
- cellElement.classList.add("bg-(--green-4)");
143
- } else {
144
- cellElement.classList.remove("bg-(--green-4)");
145
- }
154
+ cellElement.classList.add("bg-(--green-4)");
155
+ highlightedCell.current = cellElement;
146
156
  });
147
157
 
148
158
  return (
149
- <ContextMenu onOpenChange={handleContextMenuChange}>
150
- <ContextMenuTrigger asChild={true}>{tableBody}</ContextMenuTrigger>
159
+ // Open via the trigger so a right-click while already open retargets the
160
+ // menu; Radix only reports open changes, so use it for closing.
161
+ <ContextMenu
162
+ onOpenChange={(open) => {
163
+ if (!open) {
164
+ handleContextMenuChange(false);
165
+ }
166
+ }}
167
+ >
168
+ <ContextMenuTrigger
169
+ asChild={true}
170
+ onContextMenu={() => handleContextMenuChange(true)}
171
+ >
172
+ {tableBody}
173
+ </ContextMenuTrigger>
151
174
  <ContextMenuPortal>
152
- <CellContextMenu
153
- cellRef={contextMenuRef}
154
- copySelectedCells={copyAllCells}
155
- />
175
+ {activeCell && (
176
+ <CellContextMenu cell={activeCell} copySelectedCells={copyAllCells} />
177
+ )}
156
178
  </ContextMenuPortal>
157
179
  </ContextMenu>
158
180
  );
159
181
  };
160
182
 
161
183
  export const CellContextMenu = <TData,>({
162
- cellRef,
184
+ cell,
163
185
  copySelectedCells,
164
186
  }: {
165
- cellRef: RefObject<Cell<TData, unknown> | null>;
187
+ cell: Cell<TData, unknown>;
166
188
  copySelectedCells: () => void;
167
189
  }) => {
168
190
  const selectedCells = useAtomValue(selectedCellsAtom);
169
191
  const multipleSelectedCells = selectedCells.size > 1;
170
192
 
171
- const cell = cellRef.current;
172
- if (!cell) {
173
- Logger.error("No cell found in context menu");
174
- return;
175
- }
176
-
177
193
  const table = cell.getContext().table;
178
194
  const displayedValue = cell.getValue();
179
195
  const rawValue =
@@ -58,6 +58,7 @@ import { useColumnPinning } from "./hooks/use-column-pinning";
58
58
  import { useScrollContainerHeight } from "./hooks/use-scroll-container-height";
59
59
  import { CellSelectionProvider } from "./range-focus/provider";
60
60
  import { DataTableBody, renderTableHeader } from "./renderers";
61
+ import { buildHighlightPattern } from "./search-highlight";
61
62
  import { TableBottomBar } from "./TableBottomBar";
62
63
  import { TableTopBar } from "./TableTopBar";
63
64
  import {
@@ -231,6 +232,11 @@ const DataTableInternal = <TData,>({
231
232
  return idx + offset;
232
233
  }
233
234
 
235
+ const highlightPattern = React.useMemo(
236
+ () => buildHighlightPattern(searchQuery),
237
+ [searchQuery],
238
+ );
239
+
234
240
  const table = useReactTable<TData>({
235
241
  _features: [
236
242
  ColumnPinning,
@@ -245,7 +251,7 @@ const DataTableInternal = <TData,>({
245
251
  ],
246
252
  data,
247
253
  columns,
248
- meta: { rawData },
254
+ meta: { rawData, highlightPattern },
249
255
  getCoreRowModel: getCoreRowModel(),
250
256
  // pagination
251
257
  rowCount: totalRows === "too_many" ? undefined : totalRows,
@@ -396,6 +402,12 @@ const DataTableInternal = <TData,>({
396
402
  </Banner>
397
403
  )}
398
404
  <Table
405
+ role={table.options.enableCellSelection ? "grid" : undefined}
406
+ aria-multiselectable={
407
+ table.options.enableCellSelection
408
+ ? table.options.enableMultiCellSelection
409
+ : undefined
410
+ }
399
411
  className={cn(
400
412
  "relative",
401
413
  columns.length <= AUTO_WIDTH_MAX_COLUMNS ? "w-auto" : "w-full",
@@ -1,5 +1,5 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
- import React from "react";
2
+ import React, { useMemo } from "react";
3
3
  import { useDateFormatter, useLocale } from "react-aria";
4
4
  import { Tooltip } from "@/components/ui/tooltip";
5
5
 
@@ -45,6 +45,7 @@ export const DatePopover: React.FC<DatePopoverProps> = ({
45
45
 
46
46
  const TimezoneDisplay = ({ date }: { date: Date }) => {
47
47
  const { locale } = useLocale();
48
+ // The system timezone can change without the locale changing.
48
49
  const localTimezone = new Intl.DateTimeFormat(locale).resolvedOptions()
49
50
  .timeZone;
50
51
  const hasSubSeconds = date.getUTCMilliseconds() !== 0;
@@ -116,9 +117,10 @@ const RelativeTime = ({ date }: { date: Date }) => {
116
117
  const { locale } = useLocale();
117
118
 
118
119
  // Initialize relative time formatter with current locale and "auto" numeric style
119
- const relativeTimeFormatter = new Intl.RelativeTimeFormat(locale, {
120
- numeric: "auto",
121
- });
120
+ const relativeTimeFormatter = useMemo(
121
+ () => new Intl.RelativeTimeFormat(locale, { numeric: "auto" }),
122
+ [locale],
123
+ );
122
124
 
123
125
  const currentTime = new Date();
124
126
  // Get difference in seconds between now and the input date
@@ -24,6 +24,7 @@ import type {
24
24
  GetExportMetadata,
25
25
  } from "./schemas";
26
26
  import { useAsyncData } from "@/hooks/useAsyncData";
27
+ import { useStateForKey } from "@/hooks/useStateForKey";
27
28
  import { logNever } from "@/utils/assertNever";
28
29
  import { cn } from "@/utils/cn";
29
30
  import { copyToClipboard } from "@/utils/copy";
@@ -354,7 +355,6 @@ interface ExportContext {
354
355
  export const ExportActions: React.FC<ExportActionProps> = (props) => {
355
356
  const { getExportMetadata, metadataSource } = props;
356
357
  const [exportDialogOpen, setExportDialogOpen] = React.useState(false);
357
- const [failure, setFailure] = React.useState<ExportFailure | null>(null);
358
358
  const [settings, setSettings] =
359
359
  React.useState<ExportSettings>(DEFAULT_SETTINGS);
360
360
  const [exportContext, setExportContext] = React.useState<ExportContext>(
@@ -363,6 +363,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
363
363
  if (exportContext.source !== metadataSource) {
364
364
  setExportContext({ source: metadataSource });
365
365
  }
366
+ const [failure, setFailure] = useStateForKey<ExportFailure | null>(
367
+ exportContext,
368
+ () => null,
369
+ );
366
370
  const mounted = React.useRef(false);
367
371
  const isCurrentContext = useEvent(
368
372
  (context: ExportContext) => mounted.current && context === exportContext,
@@ -416,7 +420,6 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
416
420
  }, []);
417
421
  React.useEffect(() => {
418
422
  latestActionId.current += 1;
419
- setFailure(null);
420
423
  }, [metadataSource]);
421
424
  const policy = useAtomValue(downloadSizeLimitAtom);
422
425
  const overLimit = !!(
@@ -452,7 +455,6 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
452
455
  setExportDialogOpen(open);
453
456
  if (!open) {
454
457
  latestActionId.current += 1;
455
- setFailure(null);
456
458
  setExpandedFormat(null);
457
459
  setSettings(DEFAULT_SETTINGS);
458
460
  setGeometryColumn(null);
@@ -761,7 +763,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
761
763
  const expanded =
762
764
  configurableFormat !== null &&
763
765
  expandedFormat === configurableFormat;
766
+ const FormatHeader = configurableFormat ? "button" : "div";
764
767
  const panelId = `export-options-${option.format}`;
768
+ const descriptionId = `${panelId}-description`;
769
+ const summaryId = `${panelId}-summary`;
765
770
  const rowFailure =
766
771
  failure?.action.format === option.format ? failure : null;
767
772
  const summary =
@@ -802,55 +807,78 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
802
807
  data-testid={`export-row-${option.format}`}
803
808
  className={cn(expanded && "bg-muted/40")}
804
809
  >
805
- <div className="grid min-h-[60px] grid-cols-[28px_minmax(0,1fr)_auto] items-center gap-x-1 px-2.5 py-2 hover:bg-accent/50">
806
- {configurableFormat ? (
807
- <Button
808
- type="button"
809
- variant="ghost"
810
- size="icon"
811
- aria-label={`${optionLabel} options`}
812
- aria-expanded={expanded}
813
- aria-controls={panelId}
814
- onClick={() => toggleExpanded(option.format)}
810
+ <div className="grid grid-cols-[minmax(0,1fr)_auto] items-center hover:bg-accent/50">
811
+ <FormatHeader
812
+ type={configurableFormat ? "button" : undefined}
813
+ className={cn(
814
+ "grid min-h-[60px] min-w-0 grid-cols-[28px_minmax(0,1fr)] items-center gap-x-1 py-2 pl-2.5 pr-1 text-left",
815
+ configurableFormat &&
816
+ "cursor-pointer focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
817
+ )}
818
+ aria-label={
819
+ configurableFormat ? `${optionLabel} options` : undefined
820
+ }
821
+ aria-describedby={
822
+ configurableFormat
823
+ ? [descriptionId, summary && summaryId]
824
+ .filter(Boolean)
825
+ .join(" ")
826
+ : undefined
827
+ }
828
+ aria-expanded={configurableFormat ? expanded : undefined}
829
+ aria-controls={configurableFormat ? panelId : undefined}
830
+ onClick={
831
+ configurableFormat
832
+ ? () => toggleExpanded(option.format)
833
+ : undefined
834
+ }
835
+ >
836
+ <span
837
+ aria-hidden={true}
838
+ className="inline-flex h-6 w-6 items-center justify-center"
815
839
  >
816
- <ChevronRightIcon
817
- className={cn(
818
- "h-4 w-4 text-muted-foreground transition-transform",
819
- expanded && "rotate-90",
820
- )}
840
+ {configurableFormat && (
841
+ <ChevronRightIcon
842
+ className={cn(
843
+ "h-4 w-4 text-muted-foreground transition-transform",
844
+ expanded && "rotate-90",
845
+ )}
846
+ />
847
+ )}
848
+ </span>
849
+ <span className="flex min-w-0 items-center gap-3 pl-1">
850
+ <option.icon
851
+ aria-hidden={true}
852
+ data-testid={`export-format-icon-${option.format}`}
853
+ className="h-4 w-4 shrink-0 text-muted-foreground"
821
854
  />
822
- </Button>
823
- ) : (
824
- <span aria-hidden={true} className="h-6 w-6" />
825
- )}
826
- <div className="flex min-w-0 items-center gap-3 pl-1">
827
- <option.icon
828
- aria-hidden={true}
829
- data-testid={`export-format-icon-${option.format}`}
830
- className="h-4 w-4 shrink-0 text-muted-foreground"
831
- />
832
- <div className="grid min-w-0 gap-1">
833
- <span className="flex min-w-0 items-baseline gap-x-2">
834
- <span className="text-sm font-medium leading-tight">
835
- {optionLabel}
836
- </span>
837
- {summary && (
838
- <span
839
- data-testid={`export-summary-${option.format}`}
840
- className="min-w-0 truncate text-xs text-muted-foreground"
841
- >
842
- {summary}
855
+ <span className="grid min-w-0 gap-1">
856
+ <span className="flex min-w-0 items-baseline gap-x-2">
857
+ <span className="text-sm font-medium leading-tight">
858
+ {optionLabel}
843
859
  </span>
844
- )}
845
- </span>
846
- <span className="text-xs text-muted-foreground leading-tight">
847
- {option.format === "parquet" && hasGeometry
848
- ? "Parquet with geometry and CRS metadata"
849
- : option.description}
860
+ {summary && (
861
+ <span
862
+ id={summaryId}
863
+ data-testid={`export-summary-${option.format}`}
864
+ className="min-w-0 truncate text-xs text-muted-foreground"
865
+ >
866
+ {summary}
867
+ </span>
868
+ )}
869
+ </span>
870
+ <span
871
+ id={descriptionId}
872
+ className="text-xs text-muted-foreground leading-tight"
873
+ >
874
+ {option.format === "parquet" && hasGeometry
875
+ ? "Parquet with geometry and CRS metadata"
876
+ : option.description}
877
+ </span>
850
878
  </span>
851
- </div>
852
- </div>
853
- <div className="flex items-center gap-0.5">
879
+ </span>
880
+ </FormatHeader>
881
+ <div className="flex items-center gap-0.5 pr-2.5">
854
882
  <Tooltip
855
883
  content={
856
884
  option.canDownload
@@ -244,15 +244,13 @@ const {
244
244
  cellId: nextCell.id,
245
245
  };
246
246
 
247
- if (isShiftKey && state.selectedStartCell) {
248
- const cellsInRange = getCellsBetween(
249
- table,
250
- state.selectedStartCell,
251
- newCell,
252
- );
247
+ if (isShiftKey) {
248
+ const anchor = state.selectedStartCell ?? currentCell;
249
+ const cellsInRange = getCellsBetween(table, anchor, newCell);
253
250
  return {
254
251
  ...state,
255
252
  selectedCells: new Set(cellsInRange),
253
+ selectedStartCell: anchor,
256
254
  focusedCell: newCell,
257
255
  };
258
256
  } else {