@marimo-team/frontend 0.21.2-dev5 → 0.21.2-dev53

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 (386) hide show
  1. package/dist/assets/{CellStatus-CDSBsjjF.js → CellStatus-DX8MnBMk.js} +1 -1
  2. package/dist/assets/{ConnectedDataExplorerComponent-Buaffg3u.js → ConnectedDataExplorerComponent-7yXYooWG.js} +1 -1
  3. package/dist/assets/{DeferredRequestRegistry-O6RDJKs0.js → DeferredRequestRegistry-B8jPCuU1.js} +1 -1
  4. package/dist/assets/{ImperativeModal-qEtcJ95s.js → ImperativeModal-C3CD5-Aq.js} +1 -1
  5. package/dist/assets/JsonOutput-DqjAyzM8.js +46 -0
  6. package/dist/assets/{LazyAnyLanguageCodeMirror-m8w66E4s.js → LazyAnyLanguageCodeMirror-CcCHIX38.js} +2 -2
  7. package/dist/assets/{MarimoErrorOutput-az74f3Mp.js → MarimoErrorOutput-Dat_S09q.js} +5 -5
  8. package/dist/assets/RenderHTML-C7XM39M2.js +1 -0
  9. package/dist/assets/{add-cell-with-ai-DUn4LN4W.js → add-cell-with-ai-y2xroEGf.js} +9 -9
  10. package/dist/assets/{add-connection-dialog-CBz0AUVX.js → add-connection-dialog-QDBOmil3.js} +23 -23
  11. package/dist/assets/{agent-panel-u83dsDsM.js → agent-panel-DziFrEjJ.js} +6 -6
  12. package/dist/assets/ai-model-dropdown-CiJpv5wN.js +5 -0
  13. package/dist/assets/{alert-dialog-9WfvUF7e.js → alert-dialog-ebk_-wsU.js} +1 -1
  14. package/dist/assets/{any-language-editor-DwQMnAM3.js → any-language-editor-DZYnKlJB.js} +1 -1
  15. package/dist/assets/{app-config-button-rDu-lCIB.js → app-config-button-CpAv9Tiu.js} +1 -1
  16. package/dist/assets/{architectureDiagram-VXUJARFQ-DfMHHFZ3.js → architectureDiagram-VXUJARFQ-DKmk99ac.js} +1 -1
  17. package/dist/assets/{azure-BTXHztTw.js → azure-Dw5gKmUz.js} +1 -1
  18. package/dist/assets/{blockDiagram-VD42YOAC-CuEDwbg7.js → blockDiagram-VD42YOAC-TpAhP5OQ.js} +1 -1
  19. package/dist/assets/{c4Diagram-YG6GDRKO-CD9uz7WG.js → c4Diagram-YG6GDRKO-Dg8hCyKf.js} +1 -1
  20. package/dist/assets/{cache-panel-qIxnndwr.js → cache-panel-D0OsHk_D.js} +1 -1
  21. package/dist/assets/cell-editor-RbAVpSFb.js +22 -0
  22. package/dist/assets/{cell-link-Q_UEP94Z.js → cell-link-CNgO3c-T.js} +1 -1
  23. package/dist/assets/{cells-fq1RMGX_.js → cells-39RE4UzS.js} +77 -76
  24. package/dist/assets/channel-D1wPYhc9.js +1 -0
  25. package/dist/assets/{chat-display-D_Fuuy6r.js → chat-display-BPUVrlA6.js} +1 -1
  26. package/dist/assets/{chat-panel-BO-JoQSp.js → chat-panel-esz5TfF-.js} +2 -2
  27. package/dist/assets/{chunk-5FQGJX7Z-CM1a_K7I.js → chunk-5FQGJX7Z-sGWxL7Ey.js} +3 -3
  28. package/dist/assets/{chunk-ABZYJK2D-D_Wumzom.js → chunk-ABZYJK2D-DXJ7hnjx.js} +1 -1
  29. package/dist/assets/{chunk-ATLVNIR6-BZ0lTgIn.js → chunk-ATLVNIR6-CTEqcLEc.js} +1 -1
  30. package/dist/assets/{chunk-B4BG7PRW-Dw1S6osV.js → chunk-B4BG7PRW-CkAIqtPf.js} +1 -1
  31. package/dist/assets/{chunk-DI55MBZ5-Q63FTCPP.js → chunk-DI55MBZ5-C4F9vu8o.js} +1 -1
  32. package/dist/assets/{chunk-EXTU4WIE-CfkJ_R7W.js → chunk-EXTU4WIE-BT0Py-4P.js} +1 -1
  33. package/dist/assets/{chunk-JA3XYJ7Z-B41fGeoj.js → chunk-JA3XYJ7Z-CGd7jja_.js} +1 -1
  34. package/dist/assets/{chunk-JZLCHNYA-D43EJxQw.js → chunk-JZLCHNYA-CqY-RYTj.js} +1 -1
  35. package/dist/assets/{chunk-N4CR4FBY-DCtw0-ni.js → chunk-N4CR4FBY-aUDjVzN7.js} +2 -2
  36. package/dist/assets/{chunk-QN33PNHL-CLA2rsaS.js → chunk-QN33PNHL-DHnCb5-U.js} +1 -1
  37. package/dist/assets/{chunk-QXUST7PY-De1DpbnL.js → chunk-QXUST7PY-CRO5kYCE.js} +1 -1
  38. package/dist/assets/{chunk-S3R3BYOJ-qrwvlUdq.js → chunk-S3R3BYOJ-CSHQgcuP.js} +1 -1
  39. package/dist/assets/{chunk-TZMSLE5B-C4KcThb0.js → chunk-TZMSLE5B-CE7o9asH.js} +1 -1
  40. package/dist/assets/classDiagram-2ON5EDUG-BDIQSKYv.js +1 -0
  41. package/dist/assets/classDiagram-v2-WZHVMYZB-Cdh4cVOB.js +1 -0
  42. package/dist/assets/{code-block-37QAKDTI-D4FF4cnN.js → code-block-37QAKDTI-DMpe1jNG.js} +1 -1
  43. package/dist/assets/{column-preview-WsubyItX.js → column-preview-BUKHsglA.js} +1 -1
  44. package/dist/assets/{command-rfxSsiHU.js → command-DmzEbs6L.js} +1 -1
  45. package/dist/assets/{command-palette-Bez4BqJF.js → command-palette-BX5gNpUr.js} +1 -1
  46. package/dist/assets/{common-BYwO983A.js → common-B4yshY-H.js} +1 -1
  47. package/dist/assets/{components-Ozq0825a.js → components-DCqJqyys.js} +1 -1
  48. package/dist/assets/{components-Bpgzv_5_.js → components-oKCjx6cN.js} +1 -1
  49. package/dist/assets/{config-3Aq84phF.js → config-DqxNMQDN.js} +1 -1
  50. package/dist/assets/{context-CIAP2NOh.js → context-CRmPPhx9.js} +1 -1
  51. package/dist/assets/{context-aware-panel-CfsfBlhO.js → context-aware-panel-DC0Te9Hj.js} +2 -2
  52. package/dist/assets/copy-KjcPgPw9.js +1 -0
  53. package/dist/assets/{copy-icon-BgmMM9Zg.js → copy-icon-P0kzz1Pr.js} +1 -1
  54. package/dist/assets/{dagre-6UL2VRFP-BhMnPhuU.js → dagre-6UL2VRFP-XqoNLMQ3.js} +1 -1
  55. package/dist/assets/{data-grid-overlay-editor-kbv73SQ7.js → data-grid-overlay-editor-Cus1-BFN.js} +1 -1
  56. package/dist/assets/{datasource-F9sJtuof.js → datasource-DKHG39NV.js} +2 -2
  57. package/dist/assets/{dates-CHaNfieI.js → dates-CTqMeMGY.js} +1 -1
  58. package/dist/assets/{dependency-graph-panel-AOBcX2tP.js → dependency-graph-panel-7GKT3dyD.js} +4 -4
  59. package/dist/assets/{diagram-PSM6KHXK-Cr2t4zul.js → diagram-PSM6KHXK-BuzKNNcN.js} +1 -1
  60. package/dist/assets/{diagram-QEK2KX5R-DLU_hSO4.js → diagram-QEK2KX5R-A5LBQS11.js} +1 -1
  61. package/dist/assets/{diagram-S2PKOQOG-C7EkNAO3.js → diagram-S2PKOQOG-dkJE8SA0.js} +1 -1
  62. package/dist/assets/{dialog-CVN1lcMF.js → dialog-1_jIyAb_.js} +1 -1
  63. package/dist/assets/{dist-DJBpXGro.js → dist-6P6vjf93.js} +1 -1
  64. package/dist/assets/dist-BWGxTsTP.js +1 -0
  65. package/dist/assets/{dist-CblX3KGI.js → dist-B_buFm3B.js} +1 -1
  66. package/dist/assets/{dist-CXLJUPFl.js → dist-BatEf-0f.js} +1 -1
  67. package/dist/assets/dist-C3AnARPE.js +1 -0
  68. package/dist/assets/{dist-BNC_tnlW.js → dist-C6ohaMKU.js} +1 -1
  69. package/dist/assets/{dist-BoDHthoc.js → dist-CO9Pg2Rc.js} +1 -1
  70. package/dist/assets/{dist-By6zhkxZ.js → dist-CSV6H5w_.js} +1 -1
  71. package/dist/assets/{dist-6FIAeDIu.js → dist-CYs1oP7g.js} +1 -1
  72. package/dist/assets/{dist-DbK_4_qo.js → dist-DD9ZJMK5.js} +1 -1
  73. package/dist/assets/{dist-DlTbNRBn.js → dist-DReDpc2z.js} +1 -1
  74. package/dist/assets/dist-DSlq5ZeQ.js +1 -0
  75. package/dist/assets/{dist-DrceDAhM.js → dist-DXyIIB32.js} +1 -1
  76. package/dist/assets/{dist-CcGcwrUD.js → dist-DkaderFA.js} +1 -1
  77. package/dist/assets/{dist-BiZQlfhr.js → dist-Dq3BlK4R.js} +1 -1
  78. package/dist/assets/{dist-ClzRAVN-.js → dist-Dxov2ltb.js} +1 -1
  79. package/dist/assets/{dist-BXXPfIam.js → dist-EtGG9C1A.js} +1 -1
  80. package/dist/assets/{dist-C3MmXcLA.js → dist-NjId5Gdz.js} +1 -1
  81. package/dist/assets/dist-ZM59OWYL.js +1 -0
  82. package/dist/assets/dist-_TwZ4tIe.js +1 -0
  83. package/dist/assets/dist-f9b2H4q_.js +1 -0
  84. package/dist/assets/{dist-mxGLXOFm.js → dist-feWVQ4dq.js} +1 -1
  85. package/dist/assets/{documentation-panel-D28MpqbI.js → documentation-panel-D5d_BbHV.js} +1 -1
  86. package/dist/assets/{download-B9_ToVd4.js → download-B1vXaivj.js} +4 -4
  87. package/dist/assets/{dropdown-menu-DdPu5Kfu.js → dropdown-menu-BehqiLFL.js} +1 -1
  88. package/dist/assets/{edit-page-otS-QvnC.js → edit-page-B5cAZdO7.js} +7 -7
  89. package/dist/assets/{en-US-BO8E69bZ.js → en-US-f8tajDx1.js} +1 -1
  90. package/dist/assets/{erDiagram-Q2GNP2WA-DqlEo_Us.js → erDiagram-Q2GNP2WA-CgH6udOW.js} +1 -1
  91. package/dist/assets/{error-banner-BRG6IPhC.js → error-banner-J5F3weEj.js} +1 -1
  92. package/dist/assets/{error-panel-RRoj_iOR.js → error-panel-DnhKJ5Ou.js} +1 -1
  93. package/dist/assets/{es-CzkousWe.js → es-DYI7U61K.js} +1 -1
  94. package/dist/assets/{esm-CBkHtTOV.js → esm-BC1J92im.js} +1 -1
  95. package/dist/assets/{esm-DhTsVMLM.js → esm-DKLLCu3N.js} +1 -1
  96. package/dist/assets/{field-B1jGbQlH.js → field-B08lvxnl.js} +1 -1
  97. package/dist/assets/file-explorer-panel-BUk69TND.js +26 -0
  98. package/dist/assets/{file-icons-CWLHDa1J.js → file-icons-3DTS8ZM7.js} +1 -1
  99. package/dist/assets/{floating-outline-BvQKiC0F.js → floating-outline-DmugATcB.js} +1 -1
  100. package/dist/assets/{flowDiagram-NV44I4VS-CQlIJ12H.js → flowDiagram-NV44I4VS-D85BL4rA.js} +1 -1
  101. package/dist/assets/{focus-DYwTiH9-.js → focus-DlJH7sfh.js} +1 -1
  102. package/dist/assets/{form-CrQYrsUC.js → form-760_EqmF.js} +2 -2
  103. package/dist/assets/{formats-rhOJovGE.js → formats-wYuh1bqp.js} +1 -1
  104. package/dist/assets/{formatting-B4ZCH3ol.js → formatting-CraOPe94.js} +1 -1
  105. package/dist/assets/{gallery-page-eRea0yic.js → gallery-page--paiPvYX.js} +1 -1
  106. package/dist/assets/{ganttDiagram-JELNMOA3-B3EGIuZL.js → ganttDiagram-JELNMOA3-DzCOXWlF.js} +1 -1
  107. package/dist/assets/{gitGraphDiagram-V2S2FVAM-h5SlguJK.js → gitGraphDiagram-V2S2FVAM-BUHURX6t.js} +1 -1
  108. package/dist/assets/{glide-data-editor-xt5xNZeV.js → glide-data-editor-DYdoQTO5.js} +4 -4
  109. package/dist/assets/{globals-BsV5fVR-.js → globals-7M5DRsIb.js} +1 -1
  110. package/dist/assets/home-page-CxQ1e98h.js +4 -0
  111. package/dist/assets/{hooks-CHx5dUUq.js → hooks-C3jEff2O.js} +1 -1
  112. package/dist/assets/html-to-image-DTFXm6_Z.js +2 -0
  113. package/dist/assets/{index-GjXovVsl.css → index-BmoocKR0.css} +1 -1
  114. package/dist/assets/index-DNchElHl.js +38 -0
  115. package/dist/assets/{infoDiagram-HS3SLOUP-pzpClObZ.js → infoDiagram-HS3SLOUP-GG5r0Y5G.js} +1 -1
  116. package/dist/assets/{input-CUwqpKjd.js → input-CN1ZeRYm.js} +1 -1
  117. package/dist/assets/{isValid-BGe7pJXT.js → isValid-DY4Mgbr7.js} +1 -1
  118. package/dist/assets/{journeyDiagram-XKPGCS4Q-BrdRi92v.js → journeyDiagram-XKPGCS4Q-B1dvnV4D.js} +1 -1
  119. package/dist/assets/{kanban-definition-3W4ZIXB7-B6WqgFqh.js → kanban-definition-3W4ZIXB7-CefbrXQv.js} +1 -1
  120. package/dist/assets/{kiosk-mode-DNjEnIWb.js → kiosk-mode-CyTnrzwK.js} +1 -1
  121. package/dist/assets/{layout-CwFtCyW8.js → layout-3b3tzmbb.js} +3 -3
  122. package/dist/assets/{linear-BP9rwmWK.js → linear-BDnrHGYO.js} +1 -1
  123. package/dist/assets/{links-CIQwYQ48.js → links-CptYD1FP.js} +1 -1
  124. package/dist/assets/{logs-panel-BU1tNEVc.js → logs-panel-C4k_2IHW.js} +1 -1
  125. package/dist/assets/{markdown-renderer-MR9df58W.js → markdown-renderer-DSy5IuAx.js} +1 -1
  126. package/dist/assets/{menu-items-UxKrm8hS.js → menu-items-BpHXKv51.js} +1 -1
  127. package/dist/assets/mermaid-4DMBBIKO-g7AL4SLJ.js +1 -0
  128. package/dist/assets/{mermaid-Djr3jUAB.js → mermaid-C43VbdrM.js} +3 -3
  129. package/dist/assets/{mermaid-parser.core-DR82IMb2.js → mermaid-parser.core-CdM8D_p_.js} +1 -1
  130. package/dist/assets/{mindmap-definition-VGOIOE7T-DAmJpbPM.js → mindmap-definition-VGOIOE7T-CcV7D-wF.js} +1 -1
  131. package/dist/assets/{mode-AcL8c6qH.js → mode-D-iRbN9x.js} +1 -1
  132. package/dist/assets/{multi-map-Pp1P2DOX.js → multi-map-C8RbwBrw.js} +1 -1
  133. package/dist/assets/{name-cell-input-DVFEv_aO.js → name-cell-input-Dyb0ZO4X.js} +1 -1
  134. package/dist/assets/{number-overlay-editor-D__AflXQ.js → number-overlay-editor-BBJO1mf8.js} +1 -1
  135. package/dist/assets/{outline-panel-CP0oIuiU.js → outline-panel-D7CJwO8u.js} +1 -1
  136. package/dist/assets/{packages-panel-CzRELimG.js → packages-panel-Bp1SYjgc.js} +1 -1
  137. package/dist/assets/{panels-wTweRyIv.js → panels-D0aw6jdc.js} +1 -1
  138. package/dist/assets/{pieDiagram-ADFJNKIX-DbGIFRoq.js → pieDiagram-ADFJNKIX-C1fBf15W.js} +1 -1
  139. package/dist/assets/{popover-BPGG2gPG.js → popover-Bvoif-Mg.js} +1 -1
  140. package/dist/assets/{precisionRound-BOmLQIKI.js → precisionRound-CCOoIlcP.js} +1 -1
  141. package/dist/assets/{process-output-CTVsT--B.js → process-output-BxPWHcIi.js} +1 -1
  142. package/dist/assets/{quadrantDiagram-AYHSOK5B-CLAtyple.js → quadrantDiagram-AYHSOK5B-RVooN-fX.js} +1 -1
  143. package/dist/assets/{react-vega-BZav_-2n.js → react-vega-BKRQSy0g.js} +1 -1
  144. package/dist/assets/react-vega-DXESF7qN.js +1 -0
  145. package/dist/assets/{readonly-python-code-DH-1xZGq.js → readonly-python-code-D95oshJa.js} +1 -1
  146. package/dist/assets/{renderShortcut-CnD1Dah5.js → renderShortcut-BYvKm38e.js} +1 -1
  147. package/dist/assets/{request-registry-B-7cIM_I.js → request-registry-XB2EzJHm.js} +1 -1
  148. package/dist/assets/{requirementDiagram-UZGBJVZJ-DDDTB1LD.js → requirementDiagram-UZGBJVZJ-DtqOYJpH.js} +1 -1
  149. package/dist/assets/{run-page-FCvGnICa.js → run-page-B7CASued.js} +1 -1
  150. package/dist/assets/{sankeyDiagram-TZEHDZUN-DAWPOfBw.js → sankeyDiagram-TZEHDZUN-DmcooLA8.js} +1 -1
  151. package/dist/assets/{scratchpad-panel-k9lrm-rC.js → scratchpad-panel-BIVRgYOU.js} +1 -1
  152. package/dist/assets/{secrets-panel-B1Z-6dmz.js → secrets-panel-C24hZEiO.js} +1 -1
  153. package/dist/assets/{select-CxT2Geqr.js → select-Cnd3vm9n.js} +1 -1
  154. package/dist/assets/{sequenceDiagram-WL72ISMW-D_qAidD2.js → sequenceDiagram-WL72ISMW-S2qeLb7J.js} +1 -1
  155. package/dist/assets/{session-panel-WhN0qilM.js → session-panel-CNabBHQm.js} +1 -1
  156. package/dist/assets/{share-BdH_5I58.js → share-NjpZ54PJ.js} +1 -1
  157. package/dist/assets/{snippets-panel-BCDHUuku.js → snippets-panel-D1JAeJj1.js} +1 -1
  158. package/dist/assets/{spec-DbmSqx09.js → spec-DnVBmJUh.js} +1 -1
  159. package/dist/assets/{state-Ce7CVShi.js → state-BagvlaEz.js} +1 -1
  160. package/dist/assets/{state-3V5UxC3B.js → state-Cz_wrzCz.js} +1 -1
  161. package/dist/assets/{state-CBmCYWFH.js → state-DMQXxemS.js} +1 -1
  162. package/dist/assets/{stateDiagram-FKZM4ZOC-C7qgDrGA.js → stateDiagram-FKZM4ZOC-uuQ60pIl.js} +1 -1
  163. package/dist/assets/stateDiagram-v2-4FDKWEC3-D-GWhQTG.js +1 -0
  164. package/dist/assets/stex-CruVQx-P.js +1 -0
  165. package/dist/assets/{switch-CVKxYu_0.js → switch-Bwpd2AFq.js} +1 -1
  166. package/dist/assets/{terminal-Cr7wbEjz.js → terminal-Gl8Fi44y.js} +1 -1
  167. package/dist/assets/{time-D2GKc0U6.js → time-Bw8f15NM.js} +1 -1
  168. package/dist/assets/{timeline-definition-IT6M3QCI-hd6uJKGs.js → timeline-definition-IT6M3QCI-TKWeDnSQ.js} +1 -1
  169. package/dist/assets/{toggle-RCwU-rnE.js → toggle-C_gNjXg8.js} +1 -1
  170. package/dist/assets/{tooltip-D9723Brr.js → tooltip-CR_izE8Q.js} +1 -1
  171. package/dist/assets/tracing-DwAC7DWN.js +1 -0
  172. package/dist/assets/tracing-panel-D1iNgclL.js +2 -0
  173. package/dist/assets/{tree-Ch2-GuhG.js → tree-WVrWjdwv.js} +3 -3
  174. package/dist/assets/{useAddCell-YC7rpcmD.js → useAddCell-D6Q7JziZ.js} +1 -1
  175. package/dist/assets/{useBoolean-m1e6E3Ao.js → useBoolean-CrltYVhE.js} +1 -1
  176. package/dist/assets/{useCellActionButton-GUb2fXU8.js → useCellActionButton-B2G9OaX9.js} +1 -1
  177. package/dist/assets/{useDateFormatter-CpE7XQLs.js → useDateFormatter-DOoVZUts.js} +1 -1
  178. package/dist/assets/{useDeleteCell-DRUDRiy0.js → useDeleteCell-d8veThW7.js} +1 -1
  179. package/dist/assets/{useDependencyPanelTab-nFVMlEx0.js → useDependencyPanelTab-B3iIj3MO.js} +1 -1
  180. package/dist/assets/{useInstallPackage-C9V-on2J.js → useInstallPackage-CQEr5429.js} +1 -1
  181. package/dist/assets/{useNotebookActions-ChLHy-0O.js → useNotebookActions-SAEOWcBo.js} +1 -1
  182. package/dist/assets/{useNumberFormatter-DbDKSvEd.js → useNumberFormatter-BXZcbTzH.js} +1 -1
  183. package/dist/assets/{usePress-BHGkpw8X.js → usePress-alQ5Crny.js} +1 -1
  184. package/dist/assets/{useRunCells-5m6jCnyo.js → useRunCells-Dhl8ZTGh.js} +1 -1
  185. package/dist/assets/{useSplitCell-DGD9smMq.js → useSplitCell-BSnFazbH.js} +1 -1
  186. package/dist/assets/{utils-CdjCA1J8.js → utils-C24l2A1T.js} +1 -1
  187. package/dist/assets/{vega-component-CRbeDmeM.js → vega-component-9Pf4pVZL.js} +1 -1
  188. package/dist/assets/{vega-loader.browser-CZV6_g2i.js → vega-loader.browser-BJ9oKrvH.js} +1 -1
  189. package/dist/assets/{write-secret-modal-BCvuRAFb.js → write-secret-modal-BFCsWMoW.js} +1 -1
  190. package/dist/assets/{xychartDiagram-PRI3JC2R-CXlUBSbQ.js → xychartDiagram-PRI3JC2R-CIp-yeSa.js} +1 -1
  191. package/dist/index.html +125 -125
  192. package/package.json +1 -1
  193. package/src/__mocks__/notebook.ts +9 -9
  194. package/src/__tests__/branded.ts +20 -0
  195. package/src/components/app-config/user-config-form.tsx +5 -4
  196. package/src/components/data-table/__tests__/utils.test.ts +138 -1
  197. package/src/components/data-table/charts/__tests__/storage.test.ts +7 -7
  198. package/src/components/data-table/context-menu.tsx +9 -5
  199. package/src/components/data-table/data-table.tsx +3 -0
  200. package/src/components/data-table/range-focus/__tests__/atoms.test.ts +8 -2
  201. package/src/components/data-table/range-focus/__tests__/test-utils.ts +2 -0
  202. package/src/components/data-table/range-focus/__tests__/utils.test.ts +82 -8
  203. package/src/components/data-table/range-focus/atoms.ts +2 -2
  204. package/src/components/data-table/range-focus/utils.ts +50 -12
  205. package/src/components/data-table/types.ts +7 -0
  206. package/src/components/data-table/utils.ts +87 -0
  207. package/src/components/editor/__tests__/data-attributes.test.tsx +8 -8
  208. package/src/components/editor/ai/__tests__/completion-utils.test.ts +15 -15
  209. package/src/components/editor/navigation/__tests__/clipboard.test.ts +2 -2
  210. package/src/components/editor/navigation/__tests__/selection.test.ts +7 -6
  211. package/src/components/editor/navigation/__tests__/state.test.ts +8 -7
  212. package/src/components/editor/output/MarimoErrorOutput.tsx +7 -7
  213. package/src/components/editor/output/__tests__/traceback.test.tsx +4 -4
  214. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +4 -4
  215. package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +8 -1
  216. package/src/components/storage/storage-file-viewer.tsx +35 -1
  217. package/src/components/storage/storage-inspector.tsx +9 -4
  218. package/src/components/storage/storage-snippets.ts +3 -3
  219. package/src/components/tracing/tracing.tsx +3 -1
  220. package/src/components/ui/range-slider.tsx +108 -1
  221. package/src/core/ai/__tests__/staged-cells.test.ts +9 -8
  222. package/src/core/ai/context/providers/__tests__/cell-output.test.ts +31 -31
  223. package/src/core/ai/context/providers/__tests__/datasource.test.ts +3 -3
  224. package/src/core/ai/context/providers/__tests__/tables.test.ts +3 -2
  225. package/src/core/ai/context/providers/__tests__/variable.test.ts +84 -63
  226. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +10 -9
  227. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +6 -6
  228. package/src/core/ai/tools/edit-notebook-tool.ts +3 -3
  229. package/src/core/cells/__tests__/add-missing-import.test.ts +3 -3
  230. package/src/core/cells/__tests__/cells.test.ts +192 -135
  231. package/src/core/cells/__tests__/focus.test.ts +5 -4
  232. package/src/core/cells/__tests__/logs.test.ts +13 -12
  233. package/src/core/cells/__tests__/pending-delete-service.test.tsx +3 -3
  234. package/src/core/cells/__tests__/runs.test.ts +22 -21
  235. package/src/core/cells/__tests__/scrollCellIntoView.test.ts +8 -7
  236. package/src/core/cells/__tests__/session.test.ts +23 -22
  237. package/src/core/cells/cells.ts +1 -1
  238. package/src/core/cells/ids.ts +5 -5
  239. package/src/core/cells/logs.ts +2 -2
  240. package/src/core/cells/runs.ts +6 -8
  241. package/src/core/codemirror/__tests__/format.test.ts +34 -36
  242. package/src/core/codemirror/__tests__/setup.test.ts +2 -2
  243. package/src/core/codemirror/cells/__tests__/extensions.test.ts +114 -0
  244. package/src/core/codemirror/cells/__tests__/traceback-decorations.test.ts +33 -32
  245. package/src/core/codemirror/cells/extensions.ts +66 -23
  246. package/src/core/codemirror/completion/__tests__/keymap.test.ts +15 -35
  247. package/src/core/codemirror/completion/keymap.ts +14 -4
  248. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +12 -13
  249. package/src/core/codemirror/language/__tests__/utils.test.ts +3 -3
  250. package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +7 -8
  251. package/src/core/codemirror/language/languages/python.ts +4 -0
  252. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +4 -3
  253. package/src/core/codemirror/lsp/notebook-lsp.ts +28 -2
  254. package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +7 -6
  255. package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
  256. package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +52 -0
  257. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  258. package/src/core/datasets/__tests__/data-source.test.ts +5 -6
  259. package/src/core/datasets/state.ts +1 -1
  260. package/src/core/errors/__tests__/errors.test.ts +2 -1
  261. package/src/core/export/__tests__/hooks.test.ts +37 -36
  262. package/src/core/islands/main.ts +2 -7
  263. package/src/core/kernel/__tests__/handlers.test.ts +5 -4
  264. package/src/core/kernel/handlers.ts +7 -4
  265. package/src/core/network/DeferredRequestRegistry.ts +2 -2
  266. package/src/core/network/__tests__/CachingRequestRegistry.test.ts +9 -10
  267. package/src/core/network/__tests__/DeferredRequestRegistry.test.ts +4 -6
  268. package/src/core/static/__tests__/virtual-file-tracker.test.ts +8 -8
  269. package/src/core/static/virtual-file-tracker.ts +1 -1
  270. package/src/core/storage/__tests__/state.test.ts +31 -21
  271. package/src/core/storage/state.ts +1 -1
  272. package/src/core/variables/__tests__/state.test.ts +6 -6
  273. package/src/core/variables/types.ts +2 -2
  274. package/src/core/wasm/__tests__/state.test.ts +8 -8
  275. package/src/core/websocket/useMarimoKernelConnection.tsx +12 -15
  276. package/src/css/md-tooltip.css +4 -39
  277. package/src/css/md.css +7 -0
  278. package/src/plugins/core/RenderHTML.tsx +17 -0
  279. package/src/plugins/core/__test__/RenderHTML.test.ts +45 -0
  280. package/src/plugins/core/sanitize-html.ts +25 -18
  281. package/src/plugins/impl/DataTablePlugin.tsx +23 -2
  282. package/src/plugins/impl/SliderPlugin.tsx +1 -3
  283. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +120 -0
  284. package/src/plugins/impl/anywidget/model.ts +1 -2
  285. package/src/stories/cell.stories.tsx +8 -8
  286. package/src/stories/layout/vertical/one-column.stories.tsx +9 -8
  287. package/src/stories/log-viewer.stories.tsx +8 -8
  288. package/src/stories/variables.stories.tsx +2 -2
  289. package/src/utils/__tests__/download.test.tsx +21 -20
  290. package/src/utils/copy.ts +18 -5
  291. package/src/utils/download.ts +4 -3
  292. package/src/utils/html-to-image.ts +6 -0
  293. package/src/utils/json/base64.ts +3 -3
  294. package/src/utils/traceback.ts +5 -3
  295. package/dist/assets/JsonOutput-DKXKGKvX.js +0 -46
  296. package/dist/assets/RenderHTML-DJ8khuob.js +0 -1
  297. package/dist/assets/ai-model-dropdown-DPTa_EpU.js +0 -5
  298. package/dist/assets/cell-editor-DX7IcqNr.js +0 -23
  299. package/dist/assets/channel-CkT8Qdo2.js +0 -1
  300. package/dist/assets/classDiagram-2ON5EDUG-BhMT_rTz.js +0 -1
  301. package/dist/assets/classDiagram-v2-WZHVMYZB-D-F4WEyb.js +0 -1
  302. package/dist/assets/copy-YwM0Pd7v.js +0 -1
  303. package/dist/assets/dist-BTqMkf4j.js +0 -1
  304. package/dist/assets/dist-DHw9sXeN.js +0 -1
  305. package/dist/assets/dist-Du0qZeXz.js +0 -1
  306. package/dist/assets/dist-a0FfbvMD.js +0 -1
  307. package/dist/assets/dist-cfkfP0ni.js +0 -1
  308. package/dist/assets/dist-pzQ9JG-p.js +0 -1
  309. package/dist/assets/file-explorer-panel-CB8vF5ob.js +0 -26
  310. package/dist/assets/home-page-itW0tRmv.js +0 -4
  311. package/dist/assets/html-to-image-BnSc-Wa0.js +0 -2
  312. package/dist/assets/index-0n92c_W7.js +0 -38
  313. package/dist/assets/mermaid-4DMBBIKO-PoHnhmy8.js +0 -1
  314. package/dist/assets/react-vega-Da-Ps9UW.js +0 -1
  315. package/dist/assets/stateDiagram-v2-4FDKWEC3-CEqeIlM0.js +0 -1
  316. package/dist/assets/stex-BBWVYm-R.js +0 -1
  317. package/dist/assets/tracing-DUVd0jtl.js +0 -1
  318. package/dist/assets/tracing-panel-CuTxPn_x.js +0 -2
  319. /package/dist/assets/{Combination-Cs9nbinQ.js → Combination-CSPK4t6z.js} +0 -0
  320. /package/dist/assets/{Deferred-BMfCOLaw.js → Deferred-CfyqLOPG.js} +0 -0
  321. /package/dist/assets/{SSRProvider-DC7ElCZZ.js → SSRProvider-CwqN9FWV.js} +0 -0
  322. /package/dist/assets/{badge-hTpPIsMT.js → badge-DImLVznf.js} +0 -0
  323. /package/dist/assets/{blob-CObhN-9g.js → blob-DgooIGjS.js} +0 -0
  324. /package/dist/assets/{bot-message-square-CK6eoGWy.js → bot-message-square-Dw41U6lL.js} +0 -0
  325. /package/dist/assets/{chart-no-axes-column-DV8gdCvH.js → chart-no-axes-column-a9XtWmzk.js} +0 -0
  326. /package/dist/assets/{check-BE0hEwVo.js → check-DZA_bRpw.js} +0 -0
  327. /package/dist/assets/{chevron-right-D0GQBpTb.js → chevron-right-CvVxySQk.js} +0 -0
  328. /package/dist/assets/{circle-check-gLIOLu8x.js → circle-check-CbaVeozR.js} +0 -0
  329. /package/dist/assets/{circle-play-DYGULlKZ.js → circle-play-DYn5nR6N.js} +0 -0
  330. /package/dist/assets/{circle-plus-CGG-gArM.js → circle-plus-nCze0-py.js} +0 -0
  331. /package/dist/assets/{clipboard-paste-DoYSN8Sv.js → clipboard-paste-EHXeKq9D.js} +0 -0
  332. /package/dist/assets/{code-xml-DwHPF_nL.js → code-xml-BlrJCgNZ.js} +0 -0
  333. /package/dist/assets/{copy-CkudG0Ej.js → copy-D6N1-xc1.js} +0 -0
  334. /package/dist/assets/{database-zap-DTWCDKdn.js → database-zap-BIGMFOfP.js} +0 -0
  335. /package/dist/assets/{defaultLocale-DK1MWd7f.js → defaultLocale-CGfP-Ye3.js} +0 -0
  336. /package/dist/assets/{defaultLocale-OkOxlkkM.js → defaultLocale-CuYNS33t.js} +0 -0
  337. /package/dist/assets/{dist-8UD0A5sU.js → dist-BF9S272t.js} +0 -0
  338. /package/dist/assets/{dist-apDpadc4.js → dist-Bk1itfBD.js} +0 -0
  339. /package/dist/assets/{dist-CQqv2gQL.js → dist-Dm11d0_A.js} +0 -0
  340. /package/dist/assets/{download-DBW9RXtT.js → download-nLboiTtW.js} +0 -0
  341. /package/dist/assets/{ellipsis-0_zJdF6H.js → ellipsis-d7eaKIFn.js} +0 -0
  342. /package/dist/assets/{ellipsis-vertical-CAB7tdza.js → ellipsis-vertical-DBQ5kWTo.js} +0 -0
  343. /package/dist/assets/{emotion-is-prop-valid.esm-D1keIaYa.js → emotion-is-prop-valid.esm-D7FeWASw.js} +0 -0
  344. /package/dist/assets/{errors-Bfogio62.js → errors-0IrrdfSG.js} +0 -0
  345. /package/dist/assets/{extends-DRbCSry7.js → extends-aq1t6BkR.js} +0 -0
  346. /package/dist/assets/{eye-off-vwi9L975.js → eye-off-CF3GmvXV.js} +0 -0
  347. /package/dist/assets/{file-DzHkbIdO.js → file-C-yMeaec.js} +0 -0
  348. /package/dist/assets/{file-headphone-B5q2Ow55.js → file-headphone-CPAP8asn.js} +0 -0
  349. /package/dist/assets/{file-plus-corner-lLQw9OnR.js → file-plus-corner-ks__N1mr.js} +0 -0
  350. /package/dist/assets/{github-BVtI-3F1.js → github-CRD4USKm.js} +0 -0
  351. /package/dist/assets/{image-DXfkah9d.js → image-CfyJzBP9.js} +0 -0
  352. /package/dist/assets/{link-Cf10mh3t.js → link-_dbp0XNB.js} +0 -0
  353. /package/dist/assets/{maps-OKerBHH8.js → maps-DQsjfyTy.js} +0 -0
  354. /package/dist/assets/{numbers-CYnquDho.js → numbers-Cno6K0UF.js} +0 -0
  355. /package/dist/assets/{objectWithoutPropertiesLoose-DP4vAkvg.js → objectWithoutPropertiesLoose-Dxmp_Bd_.js} +0 -0
  356. /package/dist/assets/{ordinal-BjO5SoTk.js → ordinal-CMAUv8ku.js} +0 -0
  357. /package/dist/assets/{paths-D2lG83Oh.js → paths-BVwhPRFT.js} +0 -0
  358. /package/dist/assets/{play-DKSqmedg.js → play-Bu_0ogGD.js} +0 -0
  359. /package/dist/assets/{plus-dVmh0yTy.js → plus-DJ99CUbx.js} +0 -0
  360. /package/dist/assets/{preload-helper-BW0IMuFq.js → preload-helper-y72bE5iF.js} +0 -0
  361. /package/dist/assets/{prop-types-RrUi-pOT.js → prop-types-DRf51_gT.js} +0 -0
  362. /package/dist/assets/{purify.es-BBn8CPhf.js → purify.es-Cf8RQecB.js} +0 -0
  363. /package/dist/assets/{range-DNqFcYmr.js → range-ClqUI25v.js} +0 -0
  364. /package/dist/assets/{refresh-ccw-DLpfIr8v.js → refresh-ccw-DQ6SJ8UC.js} +0 -0
  365. /package/dist/assets/{refresh-cw-CHAHPgkx.js → refresh-cw-Dg9tCj4k.js} +0 -0
  366. /package/dist/assets/{rotate-ccw-hLlF_82X.js → rotate-ccw-BCkZViUZ.js} +0 -0
  367. /package/dist/assets/{save-8fSvKYJT.js → save-CUdcv5qm.js} +0 -0
  368. /package/dist/assets/{session-BrEm7qNv.js → session-CByuQ-M-.js} +0 -0
  369. /package/dist/assets/{settings-CzQUw9rV.js → settings-B7nhfCat.js} +0 -0
  370. /package/dist/assets/{spinner-C5JoisA7.js → spinner-pCogyRyo.js} +0 -0
  371. /package/dist/assets/{square-CxAsQQ77.js → square-KVNDGpgy.js} +0 -0
  372. /package/dist/assets/{square-function-B006EYFX.js → square-function-BMNCw7Qb.js} +0 -0
  373. /package/dist/assets/{stex-0ac7Aukl.js → stex-C6JeW1YI.js} +0 -0
  374. /package/dist/assets/{table-BCnp9gKC.js → table-Od8PbuV-.js} +0 -0
  375. /package/dist/assets/{toDate-BqKH-Jd9.js → toDate-Cfp9W_O9.js} +0 -0
  376. /package/dist/assets/{trash-2-CAoNMkjq.js → trash-2-Bc_J7TQO.js} +0 -0
  377. /package/dist/assets/{trash-BZMAQneW.js → trash-Cxd189Vw.js} +0 -0
  378. /package/dist/assets/{triangle-alert-qZo1ox6x.js → triangle-alert-CzLrbLGN.js} +0 -0
  379. /package/dist/assets/{types-C1RN112u.js → types-CLOMZuqU.js} +0 -0
  380. /package/dist/assets/{use-toast-Hc8CXlvz.js → use-toast-BtZldTi5.js} +0 -0
  381. /package/dist/assets/{useDebounce-B0dx2Gp0.js → useDebounce-DwTO_rGp.js} +0 -0
  382. /package/dist/assets/{useTheme-BYXBU1of.js → useTheme-KDW4sktg.js} +0 -0
  383. /package/dist/assets/{uuid-ClFZlR7U.js → uuid-BukULOeS.js} +0 -0
  384. /package/dist/assets/{workflow-BmeqNuSH.js → workflow-BqHyyStM.js} +0 -0
  385. /package/dist/assets/{x-BI1M8X_v.js → x-CdLP7-v3.js} +0 -0
  386. /package/dist/assets/{youtube-DE-Ej6FR.js → youtube-CfU-SnDw.js} +0 -0
@@ -1,5 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { beforeEach, describe, expect, it } from "vitest";
3
+ import { variableName } from "@/__tests__/branded";
3
4
  import type { VariableName } from "../../variables/types";
4
5
  import { exportedForTesting } from "../state";
5
6
  import type { StorageEntry, StorageNamespace, StorageState } from "../types";
@@ -7,7 +8,7 @@ import type { StorageEntry, StorageNamespace, StorageState } from "../types";
7
8
  const { initialState, reducer, createActions } = exportedForTesting;
8
9
 
9
10
  function makeNamespace(
10
- overrides: Partial<StorageNamespace> & { name: string },
11
+ overrides: Partial<StorageNamespace> & { name: VariableName },
11
12
  ): StorageNamespace {
12
13
  return {
13
14
  backendType: overrides.backendType ?? "obstore",
@@ -53,8 +54,14 @@ describe("storage state", () => {
53
54
 
54
55
  describe("setNamespaces", () => {
55
56
  it("should add namespaces from an empty state", () => {
56
- const ns1 = makeNamespace({ name: "my_s3", protocol: "s3" });
57
- const ns2 = makeNamespace({ name: "my_gcs", protocol: "gcs" });
57
+ const ns1 = makeNamespace({
58
+ name: variableName("my_s3"),
59
+ protocol: "s3",
60
+ });
61
+ const ns2 = makeNamespace({
62
+ name: variableName("my_gcs"),
63
+ protocol: "gcs",
64
+ });
58
65
 
59
66
  actions.setNamespaces({ namespaces: [ns1, ns2] });
60
67
 
@@ -63,15 +70,18 @@ describe("storage state", () => {
63
70
 
64
71
  it("should merge namespaces by name, replacing existing ones", () => {
65
72
  const nsOld = makeNamespace({
66
- name: "my_s3",
73
+ name: variableName("my_s3"),
67
74
  protocol: "s3",
68
75
  rootPath: "/old",
69
76
  });
70
- const nsOther = makeNamespace({ name: "my_gcs", protocol: "gcs" });
77
+ const nsOther = makeNamespace({
78
+ name: variableName("my_gcs"),
79
+ protocol: "gcs",
80
+ });
71
81
  actions.setNamespaces({ namespaces: [nsOld, nsOther] });
72
82
 
73
83
  const nsUpdated = makeNamespace({
74
- name: "my_s3",
84
+ name: variableName("my_s3"),
75
85
  protocol: "s3",
76
86
  rootPath: "/new",
77
87
  });
@@ -82,10 +92,10 @@ describe("storage state", () => {
82
92
  });
83
93
 
84
94
  it("should add new namespaces alongside existing ones", () => {
85
- const ns1 = makeNamespace({ name: "ns1" });
95
+ const ns1 = makeNamespace({ name: variableName("ns1") });
86
96
  actions.setNamespaces({ namespaces: [ns1] });
87
97
 
88
- const ns2 = makeNamespace({ name: "ns2" });
98
+ const ns2 = makeNamespace({ name: variableName("ns2") });
89
99
  actions.setNamespaces({ namespaces: [ns2] });
90
100
 
91
101
  expect(state.namespaces).toHaveLength(2);
@@ -101,7 +111,7 @@ describe("storage state", () => {
101
111
  });
102
112
 
103
113
  actions.setNamespaces({
104
- namespaces: [makeNamespace({ name: "ns" })],
114
+ namespaces: [makeNamespace({ name: variableName("ns") })],
105
115
  });
106
116
 
107
117
  expect(state.entriesByPath.get("ns::")).toEqual([entry]);
@@ -205,7 +215,7 @@ describe("storage state", () => {
205
215
  });
206
216
 
207
217
  it("should not affect namespaces", () => {
208
- const ns = makeNamespace({ name: "ns" });
218
+ const ns = makeNamespace({ name: variableName("ns") });
209
219
  actions.setNamespaces({ namespaces: [ns] });
210
220
 
211
221
  actions.setEntries({
@@ -263,7 +273,7 @@ describe("storage state", () => {
263
273
  });
264
274
 
265
275
  it("should not affect namespaces", () => {
266
- const ns = makeNamespace({ name: "my_s3" });
276
+ const ns = makeNamespace({ name: variableName("my_s3") });
267
277
  actions.setNamespaces({ namespaces: [ns] });
268
278
  actions.setEntries({
269
279
  namespace: "my_s3",
@@ -293,31 +303,31 @@ describe("storage state", () => {
293
303
 
294
304
  describe("filterFromVariables", () => {
295
305
  it("should keep namespaces whose variable is still in scope", () => {
296
- const ns1 = makeNamespace({ name: "var_a" });
297
- const ns2 = makeNamespace({ name: "var_b" });
306
+ const ns1 = makeNamespace({ name: variableName("var_a") });
307
+ const ns2 = makeNamespace({ name: variableName("var_b") });
298
308
  actions.setNamespaces({ namespaces: [ns1, ns2] });
299
309
 
300
310
  actions.filterFromVariables([
301
- "var_a" as VariableName,
302
- "var_b" as VariableName,
311
+ variableName("var_a"),
312
+ variableName("var_b"),
303
313
  ]);
304
314
 
305
315
  expect(state.namespaces).toEqual([ns1, ns2]);
306
316
  });
307
317
 
308
318
  it("should remove namespaces whose variable is no longer in scope", () => {
309
- const ns1 = makeNamespace({ name: "var_a" });
310
- const ns2 = makeNamespace({ name: "var_b" });
319
+ const ns1 = makeNamespace({ name: variableName("var_a") });
320
+ const ns2 = makeNamespace({ name: variableName("var_b") });
311
321
  actions.setNamespaces({ namespaces: [ns1, ns2] });
312
322
 
313
- actions.filterFromVariables(["var_a" as VariableName]);
323
+ actions.filterFromVariables([variableName("var_a")]);
314
324
 
315
325
  expect(state.namespaces).toEqual([ns1]);
316
326
  });
317
327
 
318
328
  it("should remove all named namespaces when given an empty variable list", () => {
319
- const ns1 = makeNamespace({ name: "var_a" });
320
- const ns2 = makeNamespace({ name: "var_b" });
329
+ const ns1 = makeNamespace({ name: variableName("var_a") });
330
+ const ns2 = makeNamespace({ name: variableName("var_b") });
321
331
  actions.setNamespaces({ namespaces: [ns1, ns2] });
322
332
 
323
333
  actions.filterFromVariables([]);
@@ -326,7 +336,7 @@ describe("storage state", () => {
326
336
  });
327
337
 
328
338
  it("should not affect entriesByPath", () => {
329
- const ns = makeNamespace({ name: "ns" });
339
+ const ns = makeNamespace({ name: variableName("ns") });
330
340
  actions.setNamespaces({ namespaces: [ns] });
331
341
 
332
342
  const entry = makeEntry({ path: "file.txt" });
@@ -71,7 +71,7 @@ const {
71
71
  const names = new Set(variableNames);
72
72
  // Filter out namespaces whose backing variable is no longer in scope
73
73
  const namespaces = state.namespaces.filter((ns) => {
74
- return names.has(ns.name as VariableName);
74
+ return names.has(ns.name);
75
75
  });
76
76
  return { ...state, namespaces };
77
77
  },
@@ -1,19 +1,19 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { beforeEach, describe, expect, it } from "vitest";
3
- import type { CellId } from "@/core/cells/ids";
3
+ import { cellId, variableName } from "@/__tests__/branded";
4
4
  import { exportedForTesting } from "../state";
5
- import type { VariableName, Variables } from "../types";
5
+ import type { Variables } from "../types";
6
6
 
7
7
  const { initialState, reducer, createActions } = exportedForTesting;
8
8
 
9
9
  const CellIds = {
10
- a: "a" as CellId,
11
- b: "b" as CellId,
10
+ a: cellId("a"),
11
+ b: cellId("b"),
12
12
  };
13
13
 
14
14
  const Names = {
15
- x: "x" as VariableName,
16
- y: "y" as VariableName,
15
+ x: variableName("x"),
16
+ y: variableName("y"),
17
17
  };
18
18
 
19
19
  describe("cell reducer", () => {
@@ -1,9 +1,9 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import type { TypedString } from "../../utils/typed";
3
+ import type { components } from "@marimo-team/marimo-api";
4
4
  import type { CellId } from "../cells/ids";
5
5
 
6
- export type VariableName = TypedString<"VariableName">;
6
+ export type VariableName = components["schemas"]["VariableName"];
7
7
 
8
8
  export interface Variable {
9
9
  name: VariableName;
@@ -2,9 +2,9 @@
2
2
 
3
3
  import { createRef } from "react";
4
4
  import { describe, expect, it } from "vitest";
5
+ import { cellId } from "@/__tests__/branded";
5
6
  import type { NotebookState } from "@/core/cells/cells";
6
7
  import { initialNotebookState, notebookAtom } from "@/core/cells/cells";
7
- import type { CellId } from "@/core/cells/ids";
8
8
  import { createCell, createCellRuntimeState } from "@/core/cells/types";
9
9
  import type { OutputMessage } from "@/core/kernel/messages";
10
10
  import { store } from "@/core/state/jotai";
@@ -17,17 +17,17 @@ describe("hasAnyOutputAtom", () => {
17
17
  ): NotebookState => ({
18
18
  ...initialNotebookState(),
19
19
  cellIds: new MultiColumn([
20
- CollapsibleTree.from(outputs.map((_, i) => `${i}` as CellId)),
20
+ CollapsibleTree.from(outputs.map((_, i) => cellId(`${i}`))),
21
21
  ]),
22
22
  cellData: Object.fromEntries(
23
23
  outputs.map((_, i) => [
24
- `${i}` as CellId,
25
- createCell({ id: `${i}` as CellId }),
24
+ cellId(`${i}`),
25
+ createCell({ id: cellId(`${i}`) }),
26
26
  ]),
27
27
  ),
28
28
  cellRuntime: Object.fromEntries(
29
29
  outputs.map((output, i) => [
30
- `${i}` as CellId,
30
+ `${i}`,
31
31
  createCellRuntimeState({
32
32
  output,
33
33
  status: "queued",
@@ -36,7 +36,7 @@ describe("hasAnyOutputAtom", () => {
36
36
  ]),
37
37
  ),
38
38
  cellHandles: Object.fromEntries(
39
- outputs.map((_, i) => [`${i}` as CellId, createRef()]),
39
+ outputs.map((_, i) => [cellId(`${i}`), createRef()]),
40
40
  ),
41
41
  });
42
42
 
@@ -90,8 +90,8 @@ describe("hasAnyOutputAtom", () => {
90
90
 
91
91
  it("should return true when all outputs are idle", () => {
92
92
  const notebookState = createNotebookState([null, null]);
93
- const cellId0 = "0" as CellId;
94
- const cellId1 = "1" as CellId;
93
+ const cellId0 = cellId("0");
94
+ const cellId1 = cellId("1");
95
95
  // Some idle cell, so returns false
96
96
  store.set(notebookAtom, {
97
97
  ...notebookState,
@@ -24,7 +24,7 @@ import { Logger } from "@/utils/Logger";
24
24
  import { reloadSafe } from "@/utils/reload-safe";
25
25
  import { useAlertActions } from "../alerts/state";
26
26
  import { cacheInfoAtom } from "../cache/requests";
27
- import { type CellId, SCRATCH_CELL_ID, type UIElementId } from "../cells/ids";
27
+ import { SCRATCH_CELL_ID } from "../cells/ids";
28
28
  import { useRunsActions } from "../cells/runs";
29
29
  import { focusAndScrollCellOutputIntoView } from "../cells/scrollCellIntoView";
30
30
  import type { CellData } from "../cells/types";
@@ -153,7 +153,7 @@ export function useMarimoKernelConnection(opts: {
153
153
  if (uiElement) {
154
154
  const buffers = safeExtractSetUIElementMessageBuffers(msg.data);
155
155
  UI_ELEMENT_REGISTRY.broadcastMessage(
156
- uiElement as UIElementId,
156
+ uiElement,
157
157
  msg.data.message,
158
158
  buffers,
159
159
  );
@@ -173,14 +173,11 @@ export function useMarimoKernelConnection(opts: {
173
173
  AUTOCOMPLETER.resolve(msg.data.completion_id as RequestId, msg.data);
174
174
  return;
175
175
  case "function-call-result":
176
- FUNCTIONS_REGISTRY.resolve(
177
- msg.data.function_call_id as RequestId,
178
- msg.data,
179
- );
176
+ FUNCTIONS_REGISTRY.resolve(msg.data.function_call_id, msg.data);
180
177
  return;
181
178
  case "cell-op": {
182
179
  handleCellNotificationeration(msg.data, handleCellMessage);
183
- const cellData = getNotebook().cellData[msg.data.cell_id as CellId];
180
+ const cellData = getNotebook().cellData[msg.data.cell_id];
184
181
  if (!cellData) {
185
182
  return;
186
183
  }
@@ -195,8 +192,8 @@ export function useMarimoKernelConnection(opts: {
195
192
  setVariables(
196
193
  msg.data.variables.map((v) => ({
197
194
  name: v.name as VariableName,
198
- declaredBy: v.declared_by as CellId[],
199
- usedBy: v.used_by as CellId[],
195
+ declaredBy: v.declared_by,
196
+ usedBy: v.used_by,
200
197
  })),
201
198
  );
202
199
  filterDatasetsFromVariables(
@@ -271,16 +268,16 @@ export function useMarimoKernelConnection(opts: {
271
268
  addColumnPreview(msg.data);
272
269
  return;
273
270
  case "sql-table-preview":
274
- PreviewSQLTable.resolve(msg.data.request_id as RequestId, msg.data);
271
+ PreviewSQLTable.resolve(msg.data.request_id, msg.data);
275
272
  return;
276
273
  case "sql-table-list-preview":
277
- PreviewSQLTableList.resolve(msg.data.request_id as RequestId, msg.data);
274
+ PreviewSQLTableList.resolve(msg.data.request_id, msg.data);
278
275
  return;
279
276
  case "validate-sql-result":
280
277
  ValidateSQL.resolve(msg.data.request_id as RequestId, msg.data);
281
278
  return;
282
279
  case "secret-keys-result":
283
- SECRETS_REGISTRY.resolve(msg.data.request_id as RequestId, msg.data);
280
+ SECRETS_REGISTRY.resolve(msg.data.request_id, msg.data);
284
281
  return;
285
282
  case "cache-info":
286
283
  setCacheInfo(msg.data);
@@ -310,19 +307,19 @@ export function useMarimoKernelConnection(opts: {
310
307
  return;
311
308
 
312
309
  case "focus-cell":
313
- focusAndScrollCellOutputIntoView(msg.data.cell_id as CellId);
310
+ focusAndScrollCellOutputIntoView(msg.data.cell_id);
314
311
  return;
315
312
  case "update-cell-codes":
316
313
  setCellCodes({
317
314
  codes: msg.data.codes,
318
- ids: msg.data.cell_ids as CellId[],
315
+ ids: msg.data.cell_ids,
319
316
  codeIsStale: msg.data.code_is_stale,
320
317
  names: msg.data.names,
321
318
  configs: msg.data.configs,
322
319
  });
323
320
  return;
324
321
  case "update-cell-ids":
325
- setCellIds({ cellIds: msg.data.cell_ids as CellId[] });
322
+ setCellIds({ cellIds: msg.data.cell_ids });
326
323
  return;
327
324
  default:
328
325
  logNever(msg.data);
@@ -3,50 +3,15 @@
3
3
  /*
4
4
  This allows you to create a basic tooltip using the data-tooltip attribute
5
5
  e.g. <span data-tooltip="Hello, World!">Hover me</span>
6
+
7
+ The tooltip content is rendered via the React Tooltip component (Radix UI portal),
8
+ which prevents clipping inside containers with overflow:hidden.
9
+ See: RenderHTML.tsx -> wrapTooltipTargets
6
10
  */
7
11
 
8
12
  .markdown {
9
13
  [data-tooltip] {
10
- position: relative;
11
14
  cursor: pointer;
12
15
  text-decoration: underline dotted;
13
16
  }
14
-
15
- [data-tooltip]::before,
16
- [data-tooltip]::after {
17
- visibility: hidden;
18
- opacity: 0;
19
- pointer-events: none;
20
- transition: all 0.2s ease;
21
- position: absolute;
22
- z-index: 1000;
23
- left: 50%;
24
- transform: translateX(-50%);
25
- }
26
-
27
- [data-tooltip]::before {
28
- content: attr(data-tooltip);
29
- bottom: calc(100% + 10px);
30
- padding: 5px 10px;
31
- width: max-content;
32
- max-width: 300px;
33
- border-radius: 6px;
34
- background-color: ;
35
- text-align: center;
36
- line-height: 1.4;
37
- white-space: pre-wrap;
38
-
39
- @apply bg-background text-foreground shadow-md border text-base;
40
- }
41
-
42
- [data-tooltip]:hover::before,
43
- [data-tooltip]:hover::after {
44
- visibility: visible;
45
- opacity: 1;
46
- }
47
-
48
- [data-tooltip]:hover::before {
49
- /* stylelint-disable-next-line unit-allowed-list */
50
- transform: translateX(-50%) translateY(10px);
51
- }
52
17
  }
package/src/css/md.css CHANGED
@@ -374,6 +374,13 @@ button .prose.prose {
374
374
  @apply p-4 pt-0;
375
375
  }
376
376
 
377
+ /* Restore proper list indentation inside details blocks.
378
+ The p-4 above overrides prose's padding-inline-start for bullet space.
379
+ This ensures bullets render correctly with list-style-position: outside. */
380
+ .markdown details > :is(ul, ol) {
381
+ padding-inline-start: 2.5rem;
382
+ }
383
+
377
384
  .markdown .codehilite {
378
385
  background-color: var(--slate-2);
379
386
  border-radius: 4px;
@@ -14,6 +14,7 @@ import React, {
14
14
  } from "react";
15
15
  import { CopyClipboardIcon } from "@/components/icons/copy-icon";
16
16
  import { QueryParamPreservingLink } from "@/components/ui/query-param-preserving-link";
17
+ import { Tooltip } from "@/components/ui/tooltip";
17
18
  import { DocHoverTarget } from "@/core/documentation/DocHoverTarget";
18
19
  import { sanitizeHtml, useSanitizeHtml } from "./sanitize";
19
20
 
@@ -160,6 +161,21 @@ const wrapDocHoverTargets: TransformFn = (
160
161
  }
161
162
  };
162
163
 
164
+ // Wrap elements with data-tooltip attribute in a Tooltip component.
165
+ // This renders the tooltip in a portal (top layer), fixing clipping inside
166
+ // containers with overflow:hidden (e.g. grid cells).
167
+ const wrapTooltipTargets: TransformFn = (
168
+ reactNode: ReactNode,
169
+ domNode: DOMNode,
170
+ ): JSX.Element | undefined => {
171
+ if (domNode instanceof Element && domNode.attribs?.["data-tooltip"]) {
172
+ const tooltipContent = domNode.attribs["data-tooltip"];
173
+ return (
174
+ <Tooltip content={tooltipContent}>{reactNode as JSX.Element}</Tooltip>
175
+ );
176
+ }
177
+ };
178
+
163
179
  const CopyableCode = ({ children }: { children: ReactNode }) => {
164
180
  const ref = useRef<HTMLDivElement>(null);
165
181
  return (
@@ -239,6 +255,7 @@ function parseHtml({
239
255
  addCopyButtonToCodehilite,
240
256
  preserveQueryParamsInAnchorLinks,
241
257
  wrapDocHoverTargets,
258
+ wrapTooltipTargets,
242
259
  removeWrappingBodyTags,
243
260
  removeWrappingHtmlTags,
244
261
  ];
@@ -197,6 +197,51 @@ describe("parseHtml", () => {
197
197
  });
198
198
  });
199
199
 
200
+ describe("wrapTooltipTargets", () => {
201
+ test("data-tooltip wraps element in Tooltip component", () => {
202
+ const html = '<span data-tooltip="Hello world">Hover me</span>';
203
+ expect(parseHtml({ html })).toMatchInlineSnapshot(`
204
+ <Tooltip
205
+ content="Hello world"
206
+ >
207
+ <span
208
+ data-tooltip="Hello world"
209
+ >
210
+ Hover me
211
+ </span>
212
+ </Tooltip>
213
+ `);
214
+ });
215
+
216
+ test("element without data-tooltip is not wrapped", () => {
217
+ const html = "<span>No tooltip</span>";
218
+ expect(parseHtml({ html })).toMatchInlineSnapshot(`
219
+ <span>
220
+ No tooltip
221
+ </span>
222
+ `);
223
+ });
224
+
225
+ test("data-tooltip on nested element wraps only that element", () => {
226
+ const html = '<p>Outer <span data-tooltip="tip">inner</span> text</p>';
227
+ expect(parseHtml({ html })).toMatchInlineSnapshot(`
228
+ <p>
229
+ Outer
230
+ <Tooltip
231
+ content="tip"
232
+ >
233
+ <span
234
+ data-tooltip="tip"
235
+ >
236
+ inner
237
+ </span>
238
+ </Tooltip>
239
+ text
240
+ </p>
241
+ `);
242
+ });
243
+ });
244
+
200
245
  describe("parseHtml with < nad >", () => {
201
246
  const html =
202
247
  'thread <unnamed> panicked at "assertion failed: `(left == right)`"';
@@ -2,28 +2,35 @@
2
2
  import DOMPurify, { type Config } from "dompurify";
3
3
 
4
4
  // preserve target=_blank https://github.com/cure53/DOMPurify/issues/317#issuecomment-912474068
5
- const TEMPORARY_ATTRIBUTE = "data-temp-href-target";
6
- DOMPurify.addHook("beforeSanitizeAttributes", (node) => {
7
- if (node.tagName === "A") {
8
- if (!node.hasAttribute("target")) {
9
- node.setAttribute("target", "_self");
10
- }
5
+ // Guard for non-browser environments (e.g. Node.js in the marimo-lsp extension)
6
+ // where `document` is not available.
7
+ if (typeof document !== "undefined") {
8
+ const TEMPORARY_ATTRIBUTE = "data-temp-href-target";
9
+ DOMPurify.addHook("beforeSanitizeAttributes", (node) => {
10
+ if (node.tagName === "A") {
11
+ if (!node.hasAttribute("target")) {
12
+ node.setAttribute("target", "_self");
13
+ }
11
14
 
12
- if (node.hasAttribute("target")) {
13
- node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute("target") || "");
15
+ if (node.hasAttribute("target")) {
16
+ node.setAttribute(
17
+ TEMPORARY_ATTRIBUTE,
18
+ node.getAttribute("target") || "",
19
+ );
20
+ }
14
21
  }
15
- }
16
- });
22
+ });
17
23
 
18
- DOMPurify.addHook("afterSanitizeAttributes", (node) => {
19
- if (node.tagName === "A" && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
20
- node.setAttribute("target", node.getAttribute(TEMPORARY_ATTRIBUTE) || "");
21
- node.removeAttribute(TEMPORARY_ATTRIBUTE);
22
- if (node.getAttribute("target") === "_blank") {
23
- node.setAttribute("rel", "noopener noreferrer");
24
+ DOMPurify.addHook("afterSanitizeAttributes", (node) => {
25
+ if (node.tagName === "A" && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
26
+ node.setAttribute("target", node.getAttribute(TEMPORARY_ATTRIBUTE) || "");
27
+ node.removeAttribute(TEMPORARY_ATTRIBUTE);
28
+ if (node.getAttribute("target") === "_blank") {
29
+ node.setAttribute("rel", "noopener noreferrer");
30
+ }
24
31
  }
25
- }
26
- });
32
+ });
33
+ }
27
34
 
28
35
  /**
29
36
  * This removes script tags, form tags, iframe tags, and other potentially dangerous tags
@@ -53,6 +53,7 @@ import {
53
53
  } from "@/components/data-table/types";
54
54
  import {
55
55
  getPageIndexForRow,
56
+ loadTableAndRawData,
56
57
  loadTableData,
57
58
  } from "@/components/data-table/utils";
58
59
  import { ErrorBoundary } from "@/components/editor/boundary/ErrorBoundary";
@@ -174,6 +175,7 @@ const valueCounts: z.ZodType<ValueCounts> = z.array(
174
175
  interface Data<T> {
175
176
  label: string | null;
176
177
  data: TableData<T>;
178
+ rawData?: TableData<T> | null;
177
179
  totalRows: number | TooManyRows;
178
180
  pagination: boolean;
179
181
  pageSize: number;
@@ -221,6 +223,7 @@ type DataTableFunctions = {
221
223
  total_rows: number | TooManyRows;
222
224
  cell_styles?: CellStyleState | null;
223
225
  cell_hover_texts?: Record<string, Record<string, string | null>> | null;
226
+ raw_data?: TableData<T> | null;
224
227
  }>;
225
228
  get_data_url?: GetDataUrl;
226
229
  get_row_ids?: GetRowIds;
@@ -243,6 +246,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
243
246
  ]),
244
247
  label: z.string().nullable(),
245
248
  data: z.union([z.string(), z.array(z.object({}).passthrough())]),
249
+ rawData: z.union([z.string(), z.array(z.looseObject({}))]).nullish(),
246
250
  totalRows: z.union([z.number(), z.literal(TOO_MANY_ROWS)]),
247
251
  pagination: z.boolean().default(false),
248
252
  pageSize: z.number().default(10),
@@ -327,6 +331,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
327
331
  )
328
332
  .nullable(),
329
333
  cell_hover_texts: cellHoverTextSchema.nullable(),
334
+ raw_data: z.union([z.string(), z.array(z.looseObject({}))]).nullish(),
330
335
  }),
331
336
  ),
332
337
  get_row_ids: rpc.input(z.object({}).passthrough()).output(
@@ -529,17 +534,23 @@ export const LoadingDataTableComponent = memo(
529
534
  // Data loading
530
535
  const { data, error, isPending, isFetching } = useAsyncData<{
531
536
  rows: T[];
537
+ rawRows?: T[];
532
538
  totalRows: number | TooManyRows;
533
539
  cellStyles: CellStyleState | undefined | null;
534
540
  cellHoverTexts?: Record<string, Record<string, string | null>> | null;
535
541
  }>(async () => {
536
542
  // If there is no data, return an empty array
537
543
  if (props.totalRows === 0) {
538
- return { rows: Arrays.EMPTY, totalRows: 0, cellStyles: {} };
544
+ return {
545
+ rows: Arrays.EMPTY,
546
+ totalRows: 0,
547
+ cellStyles: {},
548
+ };
539
549
  }
540
550
 
541
551
  // Table data is a url string or an array of objects
542
552
  let tableData = props.data;
553
+ let rawTableData: TableData<T> | undefined | null = props.rawData;
543
554
  let totalRows = props.totalRows;
544
555
  let cellStyles = props.cellStyles;
545
556
  let cellHoverTexts = props.cellHoverTexts;
@@ -587,13 +598,19 @@ export const LoadingDataTableComponent = memo(
587
598
  } else {
588
599
  const searchResults = await searchResultsPromise;
589
600
  tableData = searchResults.data;
601
+ rawTableData = searchResults.raw_data;
590
602
  totalRows = searchResults.total_rows;
591
603
  cellStyles = searchResults.cell_styles || {};
592
604
  cellHoverTexts = searchResults.cell_hover_texts || {};
593
605
  }
594
- tableData = await loadTableData(tableData);
606
+ const [data, rawData] = await loadTableAndRawData(
607
+ tableData,
608
+ rawTableData,
609
+ );
610
+ tableData = data;
595
611
  return {
596
612
  rows: tableData,
613
+ rawRows: rawData,
597
614
  totalRows: totalRows,
598
615
  cellStyles,
599
616
  cellHoverTexts,
@@ -715,6 +732,7 @@ export const LoadingDataTableComponent = memo(
715
732
  <DataTableComponent
716
733
  {...props}
717
734
  data={data?.rows ?? Arrays.EMPTY}
735
+ rawData={data?.rawRows}
718
736
  columnSummaries={columnSummaries}
719
737
  sorting={sorting}
720
738
  setSorting={setSorting}
@@ -766,6 +784,7 @@ LoadingDataTableComponent.displayName = "LoadingDataTableComponent";
766
784
  const DataTableComponent = ({
767
785
  label,
768
786
  data,
787
+ rawData,
769
788
  totalRows,
770
789
  maxColumns,
771
790
  pagination,
@@ -814,6 +833,7 @@ const DataTableComponent = ({
814
833
  }: DataTableProps<unknown> &
815
834
  DataTableSearchProps & {
816
835
  data: unknown[];
836
+ rawData?: unknown[];
817
837
  columnSummaries?: ColumnSummaries;
818
838
  getRow: (rowIdx: number) => Promise<GetRowResult>;
819
839
  }): JSX.Element => {
@@ -1015,6 +1035,7 @@ const DataTableComponent = ({
1015
1035
  <Labeled label={label} align="top" fullWidth={true}>
1016
1036
  <DataTable
1017
1037
  data={data}
1038
+ rawData={rawData}
1018
1039
  columns={columns}
1019
1040
  className={className}
1020
1041
  maxHeight={maxHeight}
@@ -152,9 +152,7 @@ const SliderComponent = ({
152
152
  nextValue = Number(start);
153
153
  }
154
154
  setInternalValue(nextValue);
155
- if (!debounce) {
156
- setValue(nextValue);
157
- }
155
+ setValue(nextValue);
158
156
  }}
159
157
  minValue={start}
160
158
  maxValue={stop}