@marimo-team/frontend 0.20.5-dev11 → 0.20.5-dev16

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 (352) hide show
  1. package/dist/assets/{CellStatus-DRjSVmK4.js → CellStatus-C7YcGVz5.js} +1 -1
  2. package/dist/assets/{Combination-tjZP3FH6.js → Combination-CvuTtFZA.js} +1 -1
  3. package/dist/assets/{ConnectedDataExplorerComponent-BmYLGaEV.js → ConnectedDataExplorerComponent-s90oP5MC.js} +1 -1
  4. package/dist/assets/{DeferredRequestRegistry-CMZsNx4R.js → DeferredRequestRegistry-TekxUirp.js} +1 -1
  5. package/dist/assets/{ErrorBoundary-dVj6GVNE.js → ErrorBoundary-CnuID9Cd.js} +1 -1
  6. package/dist/assets/{ImperativeModal-CRNJOvqT.js → ImperativeModal-CPUoA52T.js} +1 -1
  7. package/dist/assets/{JsonOutput-BW2KjuuO.js → JsonOutput-CHgq3R6J.js} +3 -3
  8. package/dist/assets/{LazyAnyLanguageCodeMirror-BdX_Y5NA.js → LazyAnyLanguageCodeMirror-B11pcXh7.js} +2 -2
  9. package/dist/assets/{MarimoErrorOutput-B0ZtYqUC.js → MarimoErrorOutput-CQ3kdm1P.js} +1 -1
  10. package/dist/assets/{RenderHTML-qh-NzTWO.js → RenderHTML-pLlj26l9.js} +1 -1
  11. package/dist/assets/{add-cell-with-ai-CjNE3wDD.js → add-cell-with-ai-BK9zCuNy.js} +11 -11
  12. package/dist/assets/add-connection-dialog-CmJm_APe.js +138 -0
  13. package/dist/assets/{agent-panel-Bs4U7zuM.js → agent-panel-DHwIjihK.js} +15 -15
  14. package/dist/assets/{ai-model-dropdown-BvC7PrEP.js → ai-model-dropdown-B44FMVQo.js} +2 -2
  15. package/dist/assets/{alert-dialog-DsNfSYaw.js → alert-dialog-7IgjDQnl.js} +1 -1
  16. package/dist/assets/{any-language-editor-Drlg63ge.js → any-language-editor-oszZpJ9n.js} +1 -1
  17. package/dist/assets/{app-config-button-Ah2MpPwh.js → app-config-button-D9y29OVK.js} +1 -1
  18. package/dist/assets/{architectureDiagram-VXUJARFQ-KOgWVxSC.js → architectureDiagram-VXUJARFQ-PitjPG8V.js} +1 -1
  19. package/dist/assets/{assertNever-Dw9aFN4h.js → assertNever-BrLJ0NwL.js} +1 -1
  20. package/dist/assets/{azure-Ddr1pZpW.js → azure-IIVDdkEa.js} +1 -1
  21. package/dist/assets/{blockDiagram-VD42YOAC-DjazSe-Z.js → blockDiagram-VD42YOAC-BIJ4EhZR.js} +1 -1
  22. package/dist/assets/{button-BmOH9agK.js → button-B_BBklax.js} +1 -1
  23. package/dist/assets/{c4Diagram-YG6GDRKO-CkwpyaIV.js → c4Diagram-YG6GDRKO-DM49Cvfe.js} +1 -1
  24. package/dist/assets/{cache-panel-DRhH4wqG.js → cache-panel-B1U_4_r0.js} +1 -1
  25. package/dist/assets/{capabilities-CeYo4YI0.js → capabilities-BK7HaT7a.js} +1 -1
  26. package/dist/assets/{capitalize-irHJCpFh.js → capitalize-D0VWeP6D.js} +1 -1
  27. package/dist/assets/{cell-editor-BEiX1UeB.js → cell-editor-B2FqB6tW.js} +6 -6
  28. package/dist/assets/{cell-link-B59Kn5nL.js → cell-link-DaAxXyUN.js} +1 -1
  29. package/dist/assets/{cells-CCtxWKxf.js → cells-BLS3X4Af.js} +3 -3
  30. package/dist/assets/channel-DNdp-eCE.js +1 -0
  31. package/dist/assets/{chat-display-D9cwUpnQ.js → chat-display-BcoYsiMy.js} +1 -1
  32. package/dist/assets/{chat-panel-DsThKBAA.js → chat-panel-CMpcjtJu.js} +1 -1
  33. package/dist/assets/{chunk-5FQGJX7Z-BJDu6jwt.js → chunk-5FQGJX7Z-Cyze_Wbx.js} +3 -3
  34. package/dist/assets/{chunk-ABZYJK2D-B4uBM2QW.js → chunk-ABZYJK2D-CIP2m5SK.js} +3 -3
  35. package/dist/assets/{chunk-ATLVNIR6-Du2yaFpm.js → chunk-ATLVNIR6-dCnEfemD.js} +1 -1
  36. package/dist/assets/{chunk-B4BG7PRW-CyuK4uRN.js → chunk-B4BG7PRW-sXSaKV4v.js} +1 -1
  37. package/dist/assets/{chunk-DI55MBZ5-BwWd5dH1.js → chunk-DI55MBZ5-DjV-ScSc.js} +1 -1
  38. package/dist/assets/{chunk-EXTU4WIE-KqUhNQvn.js → chunk-EXTU4WIE-PLvknOI8.js} +1 -1
  39. package/dist/assets/{chunk-JA3XYJ7Z-C-v9pa_-.js → chunk-JA3XYJ7Z-BM9i2UKq.js} +1 -1
  40. package/dist/assets/{chunk-JZLCHNYA-DNCs8LM0.js → chunk-JZLCHNYA-m6YUUy9x.js} +1 -1
  41. package/dist/assets/{chunk-N4CR4FBY-CT58_cui.js → chunk-N4CR4FBY-C1lKPnWl.js} +2 -2
  42. package/dist/assets/{chunk-QN33PNHL-BboxAxJa.js → chunk-QN33PNHL-Czx-c7tW.js} +1 -1
  43. package/dist/assets/{chunk-QXUST7PY-BlINr7uS.js → chunk-QXUST7PY-CcYtOR78.js} +1 -1
  44. package/dist/assets/{chunk-S3R3BYOJ-DI9xzpBm.js → chunk-S3R3BYOJ-JNQMgAH6.js} +1 -1
  45. package/dist/assets/{chunk-TZMSLE5B-C4sxb3v-.js → chunk-TZMSLE5B-C9T1sILA.js} +1 -1
  46. package/dist/assets/classDiagram-2ON5EDUG-BqtRsi1m.js +1 -0
  47. package/dist/assets/classDiagram-v2-WZHVMYZB-CVoqYiM8.js +1 -0
  48. package/dist/assets/{code-block-37QAKDTI-Cl0NTdrS.js → code-block-37QAKDTI-BeUkwW5f.js} +1 -1
  49. package/dist/assets/{column-preview-Bd1U8JUS.js → column-preview-DusIZuR5.js} +1 -1
  50. package/dist/assets/{command-DQqqP-WF.js → command-CQd7U1fL.js} +1 -1
  51. package/dist/assets/{command-palette-D0TGx7YC.js → command-palette-MijyB7K_.js} +1 -1
  52. package/dist/assets/{common-CKAiz8xx.js → common-ed7Ffv7I.js} +1 -1
  53. package/dist/assets/{components-BZCdnYSp.js → components-8Q-wOvzt.js} +1 -1
  54. package/dist/assets/components-BnwE0U6X.js +1 -0
  55. package/dist/assets/{config-D9X9QKiL.js → config-CEhpfPsm.js} +1 -1
  56. package/dist/assets/{context-B1_BdDTF.js → context-CRApIvpB.js} +1 -1
  57. package/dist/assets/context-aware-panel-4SL9IzEa.js +3 -0
  58. package/dist/assets/{copy-DMCkK2TI.js → copy-BxX1HhLi.js} +1 -1
  59. package/dist/assets/{copy-icon-6RnnFDPt.js → copy-icon-C7DYKLrA.js} +1 -1
  60. package/dist/assets/{createReducer-BcTiTw8T.js → createReducer-DlNDr--8.js} +1 -1
  61. package/dist/assets/{dagre-6UL2VRFP-BrBSRtN5.js → dagre-6UL2VRFP-D-I1QR9s.js} +1 -1
  62. package/dist/assets/{data-grid-overlay-editor-NBBEPhQq.js → data-grid-overlay-editor-DXzdnLZF.js} +1 -1
  63. package/dist/assets/{datasource-B2Fl6iYU.js → datasource-Rhwrf7V5.js} +1 -1
  64. package/dist/assets/{dates-CzBDvj6R.js → dates-DbMtViXe.js} +1 -1
  65. package/dist/assets/{dependency-graph-panel-Dk4iQGft.js → dependency-graph-panel-BbynHTqX.js} +1 -1
  66. package/dist/assets/{diagram-PSM6KHXK-DPC85L-O.js → diagram-PSM6KHXK-DcjdxOTC.js} +1 -1
  67. package/dist/assets/{diagram-QEK2KX5R-CRPLkmdi.js → diagram-QEK2KX5R-Dx1WtjkT.js} +1 -1
  68. package/dist/assets/{diagram-S2PKOQOG-Bsc6mZUW.js → diagram-S2PKOQOG-CXJzGs3_.js} +1 -1
  69. package/dist/assets/{dialog-BXzvlof-.js → dialog-BGSIIw3z.js} +1 -1
  70. package/dist/assets/{dist-i0ilBbwP.js → dist-0PMxXIr6.js} +1 -1
  71. package/dist/assets/{dist-DGPCoel5.js → dist-6HEOc3hy.js} +1 -1
  72. package/dist/assets/{dist-CEQIJ2pn.js → dist-B7Qj0ClH.js} +1 -1
  73. package/dist/assets/{dist-C30-xTdI.js → dist-BIYYQefO.js} +1 -1
  74. package/dist/assets/{dist-DU2EJ7el.js → dist-BL52mbxW.js} +1 -1
  75. package/dist/assets/{dist-Dg61kQNR.js → dist-BQ7MrVoG.js} +1 -1
  76. package/dist/assets/{dist-CU-Ty5ht.js → dist-BUr9VSV4.js} +1 -1
  77. package/dist/assets/{dist-BjtLy-VA.js → dist-Bagw3W9X.js} +1 -1
  78. package/dist/assets/dist-BbkZJt99.js +1 -0
  79. package/dist/assets/{dist-Q0--6AMp.js → dist-BrDOLuMx.js} +1 -1
  80. package/dist/assets/dist-BvqRyXNf.js +1 -0
  81. package/dist/assets/{dist-DFv45CtW.js → dist-C1g0ZQqM.js} +1 -1
  82. package/dist/assets/dist-C88PeA-j.js +1 -0
  83. package/dist/assets/{dist-DQgu-tmt.js → dist-C8DU7LS7.js} +1 -1
  84. package/dist/assets/dist-CT29HpLU.js +1 -0
  85. package/dist/assets/dist-CaN3pnGY.js +1 -0
  86. package/dist/assets/dist-CdZrtzmM.js +1 -0
  87. package/dist/assets/{dist-Dq_iQ08e.js → dist-Cf47zp7b.js} +1 -1
  88. package/dist/assets/dist-CiBv1uBX.js +1 -0
  89. package/dist/assets/dist-Cn-s3n4_.js +1 -0
  90. package/dist/assets/{dist-DVh79TGS.js → dist-CrFxmtyb.js} +1 -1
  91. package/dist/assets/{dist-y6DTGoUH.js → dist-CsQrBXB1.js} +1 -1
  92. package/dist/assets/{dist-BjnzbwCx.js → dist-D-tCQoCo.js} +1 -1
  93. package/dist/assets/{dist-51xFOPFs.js → dist-D3OoaVQX.js} +1 -1
  94. package/dist/assets/dist-DHmVMXm2.js +1 -0
  95. package/dist/assets/dist-DHn8amAr.js +1 -0
  96. package/dist/assets/dist-DK2oA8K0.js +1 -0
  97. package/dist/assets/{dist-Bq1BhBMA.js → dist-DKPpxz2S.js} +1 -1
  98. package/dist/assets/{dist-DwtQnQ8D.js → dist-DPW-YadP.js} +1 -1
  99. package/dist/assets/{dist-BTEPE6IB.js → dist-DRX_D8V4.js} +1 -1
  100. package/dist/assets/{dist-Bbmd3uCi.js → dist-D_4TSZPK.js} +1 -1
  101. package/dist/assets/dist-Ddx3eonB.js +1 -0
  102. package/dist/assets/dist-DnPN36vC.js +1 -0
  103. package/dist/assets/dist-Doi_61Lm.js +1 -0
  104. package/dist/assets/{dist-Dy5EHuDu.js → dist-Dq1aTs7B.js} +1 -1
  105. package/dist/assets/dist-Dr9qtoId.js +13 -0
  106. package/dist/assets/dist-EtvDr9lo.js +1 -0
  107. package/dist/assets/dist-JYMkroTn.js +1 -0
  108. package/dist/assets/{dist-DfBASypd.js → dist-Jp_4M-Ei.js} +1 -1
  109. package/dist/assets/dist-QoV0fohO.js +1 -0
  110. package/dist/assets/dist-TtVOJU5I.js +1 -0
  111. package/dist/assets/dist-doJt8agZ.js +1 -0
  112. package/dist/assets/{dist-CIuh_TIk.js → dist-etSPFHi_.js} +1 -1
  113. package/dist/assets/{dist-CqnPIH_S.js → dist-f-ru44Xm.js} +1 -1
  114. package/dist/assets/{dist-odxAaH5Z.js → dist-t1vdhOX_.js} +1 -1
  115. package/dist/assets/{dist-6QbI72oM.js → dist-wBVaU_K6.js} +1 -1
  116. package/dist/assets/{dist-C-_581uo.js → dist-ykiUNgjx.js} +1 -1
  117. package/dist/assets/{dist-CIU0Lack.js → dist-zdBcSuGn.js} +1 -1
  118. package/dist/assets/{documentation-panel-DSqxsEBu.js → documentation-panel-BmFztrAu.js} +1 -1
  119. package/dist/assets/download-dbepOsRi.js +9 -0
  120. package/dist/assets/{dropdown-menu-CKhrfxsx.js → dropdown-menu-C8nocIkm.js} +1 -1
  121. package/dist/assets/{edit-page-CTQGyajl.js → edit-page-D2Ln_CDa.js} +7 -7
  122. package/dist/assets/{erDiagram-Q2GNP2WA-B7kZxL-n.js → erDiagram-Q2GNP2WA-BQUYpiEQ.js} +1 -1
  123. package/dist/assets/{error-banner-R2OkQKR0.js → error-banner-DC7kSyWN.js} +1 -1
  124. package/dist/assets/{error-panel-CtyexAW6.js → error-panel-ilD7L2wL.js} +1 -1
  125. package/dist/assets/{es-1hBRXVlM.js → es-DgeOOQmd.js} +1 -1
  126. package/dist/assets/{esm-BQUzYly2.js → esm-Hlfcqnf0.js} +1 -1
  127. package/dist/assets/{esm-BTyesPLl.js → esm-MvMf2P5n.js} +1 -1
  128. package/dist/assets/{field-DGtw6Lae.js → field-D3rHE7aa.js} +1 -1
  129. package/dist/assets/file-explorer-panel-3SczjS2n.js +17 -0
  130. package/dist/assets/{file-video-camera-Fa5c_iPb.js → file-headphone-daOQzJg0.js} +1 -1
  131. package/dist/assets/file-icons-DN9ij4Wl.js +1 -0
  132. package/dist/assets/{floating-outline-BWK_nLJy.js → floating-outline-CJ9IGAYq.js} +1 -1
  133. package/dist/assets/{flowDiagram-NV44I4VS-DR-64sse.js → flowDiagram-NV44I4VS-xMIxed1s.js} +1 -1
  134. package/dist/assets/{focus-ShrwcKIv.js → focus-YYacdzxP.js} +1 -1
  135. package/dist/assets/{form-B7_NRa34.js → form-C0LTsPPL.js} +1 -1
  136. package/dist/assets/{formats-C3K3rlAZ.js → formats-CnvgO4Do.js} +1 -1
  137. package/dist/assets/{formatting-8bP-RDnl.js → formatting-B5u5A8vd.js} +1 -1
  138. package/dist/assets/{gallery-page-DRBZRnaN.js → gallery-page-DD7Wys3m.js} +1 -1
  139. package/dist/assets/{ganttDiagram-JELNMOA3-BWuQMrGd.js → ganttDiagram-JELNMOA3-Be16Pv8U.js} +1 -1
  140. package/dist/assets/{gitGraphDiagram-V2S2FVAM-Mr5-PYgM.js → gitGraphDiagram-V2S2FVAM-DQ4scp6S.js} +1 -1
  141. package/dist/assets/{glide-data-editor-BurnHmgR.js → glide-data-editor-BBNY066L.js} +4 -4
  142. package/dist/assets/{globals-BlB0Ba6E.js → globals-B1fld-Rj.js} +1 -1
  143. package/dist/assets/home-page-B6sVet_m.js +4 -0
  144. package/dist/assets/{hooks-BllYlfDO.js → hooks-DLXDseF0.js} +1 -1
  145. package/dist/assets/html-to-image-Fz0aHtSN.js +2 -0
  146. package/dist/assets/image-CBwHq93J.js +1 -0
  147. package/dist/assets/{index-6w6yEdfY.js → index-FWhMvrQZ.js} +10 -10
  148. package/dist/assets/{index-Dzwe9vKA.css → index-fYvRsNGP.css} +1 -1
  149. package/dist/assets/{infoDiagram-HS3SLOUP-Bs8aKpuZ.js → infoDiagram-HS3SLOUP-DzsICEl9.js} +1 -1
  150. package/dist/assets/{input-BPldEXfy.js → input-BSqIiBgk.js} +1 -1
  151. package/dist/assets/{journeyDiagram-XKPGCS4Q-aCZRxOHn.js → journeyDiagram-XKPGCS4Q-Dt4UItaM.js} +1 -1
  152. package/dist/assets/{kanban-definition-3W4ZIXB7-BlOJJ-5B.js → kanban-definition-3W4ZIXB7-Do_8fQeU.js} +1 -1
  153. package/dist/assets/katex-BalO4WMU.js +1 -0
  154. package/dist/assets/{kiosk-mode-BBqwMND1.js → kiosk-mode-owaVEljR.js} +1 -1
  155. package/dist/assets/{label-DmqkEXI4.js → label-Dyfjlw7l.js} +1 -1
  156. package/dist/assets/{layout-DcfIrJXW.js → layout-bJhK1MU7.js} +3 -3
  157. package/dist/assets/{linear-2A1iDmqT.js → linear-c4WCYuol.js} +1 -1
  158. package/dist/assets/{links-syPBpTLO.js → links-DwLHiCvK.js} +1 -1
  159. package/dist/assets/{logs-panel-BHFI-jG1.js → logs-panel-RcBRKpKx.js} +1 -1
  160. package/dist/assets/{maps-8VTEe-0T.js → maps-BLIeOscV.js} +1 -1
  161. package/dist/assets/{markdown-renderer-B6a5ZAwT.js → markdown-renderer-rEsmEgLk.js} +4 -4
  162. package/dist/assets/{menu-items-Bs2e3wuf.js → menu-items-5L8KP3TE.js} +1 -1
  163. package/dist/assets/mermaid-4DMBBIKO-C2MO8Ayk.js +1 -0
  164. package/dist/assets/{mermaid-Cq8ttjss.js → mermaid-Cpuf_CFq.js} +3 -3
  165. package/dist/assets/{mermaid-parser.core-DbGD2gKa.js → mermaid-parser.core-C-MdXFgl.js} +1 -1
  166. package/dist/assets/{mhchem-BJZpIgRF.js → mhchem-DqNBdKjC.js} +1 -1
  167. package/dist/assets/{mindmap-definition-VGOIOE7T-Dt6ZRws3.js → mindmap-definition-VGOIOE7T-YOE4okXd.js} +1 -1
  168. package/dist/assets/{multi-map-kCmlVJ-5.js → multi-map-DNuS4OLr.js} +1 -1
  169. package/dist/assets/{name-cell-input-BRHlWy2Y.js → name-cell-input-CDeuhMiw.js} +1 -1
  170. package/dist/assets/{number-overlay-editor-BDnI-mwa.js → number-overlay-editor-zZDGu9D2.js} +1 -1
  171. package/dist/assets/{numbers-44Cj1Me-.js → numbers-BUwP5i6C.js} +1 -1
  172. package/dist/assets/{outline-panel-uyRmU3NX.js → outline-panel-8W_UW9ZN.js} +1 -1
  173. package/dist/assets/{packages-panel-JdLxEG_7.js → packages-panel-BrrY9zA4.js} +1 -1
  174. package/dist/assets/{panels-BN71Cgvz.js → panels-u3TLFAyo.js} +1 -1
  175. package/dist/assets/{pieDiagram-ADFJNKIX-3GEmpmfg.js → pieDiagram-ADFJNKIX-CjRyNR5b.js} +1 -1
  176. package/dist/assets/{popover-Cvl9xY6R.js → popover-BoqMUhMK.js} +1 -1
  177. package/dist/assets/{precisionRound-BOmLQIKI.js → precisionRound-CCOoIlcP.js} +1 -1
  178. package/dist/assets/{process-output-4yip1nZE.js → process-output-CsBDUnVX.js} +1 -1
  179. package/dist/assets/purify.es-BBn8CPhf.js +2 -0
  180. package/dist/assets/{quadrantDiagram-AYHSOK5B-Dela17qb.js → quadrantDiagram-AYHSOK5B-ZvWY20UO.js} +1 -1
  181. package/dist/assets/{react-vega-C6zUovDg.js → react-vega-DzWik59S.js} +1 -1
  182. package/dist/assets/react-vega-plcnUXVG.js +1 -0
  183. package/dist/assets/{readonly-python-code-DmjbJYSq.js → readonly-python-code-B6oaMq65.js} +1 -1
  184. package/dist/assets/{renderShortcut-BJEd-iA7.js → renderShortcut-D-zdqWZr.js} +1 -1
  185. package/dist/assets/{request-registry-CN4oD1xn.js → request-registry-LM8kl4Xv.js} +1 -1
  186. package/dist/assets/{requirementDiagram-UZGBJVZJ-CjimGyZ2.js → requirementDiagram-UZGBJVZJ-4LJ2QyR9.js} +1 -1
  187. package/dist/assets/{run-page-aSmNe5eg.js → run-page-BbVBeMzX.js} +1 -1
  188. package/dist/assets/{runs-BMpRKQKC.js → runs-SgngHXOQ.js} +1 -1
  189. package/dist/assets/{sankeyDiagram-TZEHDZUN-CBE98yUR.js → sankeyDiagram-TZEHDZUN-7OqUpHYR.js} +1 -1
  190. package/dist/assets/{scratchpad-panel-DRCYEcZM.js → scratchpad-panel-Ba9QTbWc.js} +1 -1
  191. package/dist/assets/{secrets-panel-C2n4dedt.js → secrets-panel-Dw0Ba5RP.js} +1 -1
  192. package/dist/assets/{select-DygbgNTD.js → select-BVf30BUG.js} +1 -1
  193. package/dist/assets/{sequenceDiagram-WL72ISMW-DSgG0Zyn.js → sequenceDiagram-WL72ISMW-C4sGREOt.js} +1 -1
  194. package/dist/assets/{session-DnMOyddG.js → session--x-9D3HE.js} +1 -1
  195. package/dist/assets/session-panel-BxSqsEW2.js +1 -0
  196. package/dist/assets/{share-sD4fbzpH.js → share-BCg8HRWb.js} +1 -1
  197. package/dist/assets/{slides-component-B6-Jz3p0.js → slides-component-ZaY98c0Q.js} +1 -1
  198. package/dist/assets/{snippets-panel-Bzz2M38q.js → snippets-panel-C9eE9sLd.js} +1 -1
  199. package/dist/assets/{spec-Be-iRLAY.js → spec-koLy2UDc.js} +1 -1
  200. package/dist/assets/{state-B_fNn_z_.js → state-BI4WmvIs.js} +1 -1
  201. package/dist/assets/{state-Xu6bDsJl.js → state-CjHlU-bK.js} +1 -1
  202. package/dist/assets/{state-D2jTOQOG.js → state-CqgD8hLj.js} +1 -1
  203. package/dist/assets/{stateDiagram-FKZM4ZOC-By2PSLiJ.js → stateDiagram-FKZM4ZOC-4PvEH0nH.js} +1 -1
  204. package/dist/assets/stateDiagram-v2-4FDKWEC3-CpKgwrjU.js +1 -0
  205. package/dist/assets/stex-BBWVYm-R.js +1 -0
  206. package/dist/assets/{switch-tdkZNn4k.js → switch-CbXfU6RG.js} +1 -1
  207. package/dist/assets/{terminal-CGmjeYqa.js → terminal-CfcXJOVD.js} +1 -1
  208. package/dist/assets/{time-BLCpKsnL.js → time-BuGE4zW4.js} +1 -1
  209. package/dist/assets/{timeline-definition-IT6M3QCI-rq80_nVa.js → timeline-definition-IT6M3QCI-D9wk3zrs.js} +1 -1
  210. package/dist/assets/{toggle-BhEcsHTu.js → toggle-yITwWbFe.js} +1 -1
  211. package/dist/assets/{tooltip-DOQlecCr.js → tooltip-CSN_sVIP.js} +1 -1
  212. package/dist/assets/{tooltip-D_HRHf_c.js → tooltip-Mz5m-WBI.js} +1 -1
  213. package/dist/assets/{tracing-BZx6nEPl.js → tracing-Cq6U9xkY.js} +1 -1
  214. package/dist/assets/tracing-panel-DCKD_wl6.js +2 -0
  215. package/dist/assets/{tree-D0AxVJ_I.js → tree-DFAMcRzN.js} +1 -1
  216. package/dist/assets/{useAddCell-BRlAqdmq.js → useAddCell-CHcSa2S1.js} +1 -1
  217. package/dist/assets/{useBoolean-eWwLICkT.js → useBoolean-BkvPje4S.js} +1 -1
  218. package/dist/assets/useCellActionButton-B_j24wIu.js +1 -0
  219. package/dist/assets/{useDateFormatter-CmtFqjqu.js → useDateFormatter-DfEfyPT1.js} +1 -1
  220. package/dist/assets/{useDeleteCell-BAfiIxKf.js → useDeleteCell--rxnx-v-.js} +1 -1
  221. package/dist/assets/{useDependencyPanelTab-jTu3L200.js → useDependencyPanelTab-Czes6RSz.js} +1 -1
  222. package/dist/assets/{useEventListener-CjXriKgk.js → useEventListener-CTPW4ELK.js} +1 -1
  223. package/dist/assets/{useIframeCapabilities-T3alJPda.js → useIframeCapabilities-5-CXF3BR.js} +1 -1
  224. package/dist/assets/{useInstallPackage-jGxNsOWc.js → useInstallPackage-CvexojR5.js} +1 -1
  225. package/dist/assets/{useInterval-lamrIyKJ.js → useInterval-dMGmU9jM.js} +1 -1
  226. package/dist/assets/{useLifecycle-BDXC6oVR.js → useLifecycle-iL8mLF8h.js} +1 -1
  227. package/dist/assets/useNotebookActions-DaQJ5dOH.js +1 -0
  228. package/dist/assets/{useNumberFormatter-DMA_kIIZ.js → useNumberFormatter-DQd-h5xR.js} +1 -1
  229. package/dist/assets/{usePress-DsLftN-x.js → usePress-DcdVsIfA.js} +1 -1
  230. package/dist/assets/{useSplitCell-CB32IpFa.js → useSplitCell-CBScsxFG.js} +1 -1
  231. package/dist/assets/{useTheme-CwdqVOYu.js → useTheme-DKICbfFh.js} +1 -1
  232. package/dist/assets/{utils-CORJ8yYa.js → utils-D6N4h71e.js} +1 -1
  233. package/dist/assets/{vega-component-BLW2fY7v.js → vega-component-CptSPDCF.js} +1 -1
  234. package/dist/assets/{vega-loader.browser-CZV6_g2i.js → vega-loader.browser-BJ9oKrvH.js} +1 -1
  235. package/dist/assets/{write-secret-modal-DuxmGjDn.js → write-secret-modal-UFEJUct8.js} +1 -1
  236. package/dist/assets/{xychartDiagram-PRI3JC2R-Bnjm0Q9u.js → xychartDiagram-PRI3JC2R-CTDFOoiw.js} +1 -1
  237. package/dist/index.html +131 -130
  238. package/package.json +1 -1
  239. package/src/__mocks__/requests.ts +1 -0
  240. package/src/components/datasources/components.tsx +3 -6
  241. package/src/components/datasources/datasources.tsx +8 -21
  242. package/src/components/editor/actions/useNotebookActions.tsx +34 -2
  243. package/src/components/editor/controls/keyboard-shortcuts.tsx +3 -1
  244. package/src/components/editor/file-tree/file-explorer.tsx +48 -62
  245. package/src/components/editor/file-tree/file-icons.tsx +132 -0
  246. package/src/components/editor/file-tree/file-viewer.tsx +1 -1
  247. package/src/components/editor/file-tree/tree-actions.tsx +107 -0
  248. package/src/components/editor/file-tree/types.ts +2 -96
  249. package/src/components/editor/header/filename-input.tsx +4 -1
  250. package/src/components/pages/home-page.tsx +5 -5
  251. package/src/components/storage/components.tsx +0 -38
  252. package/src/components/storage/storage-file-viewer.tsx +1 -1
  253. package/src/components/storage/storage-inspector.tsx +28 -45
  254. package/src/core/hotkeys/__tests__/hotkeys.test.ts +64 -1
  255. package/src/core/hotkeys/hotkeys.ts +18 -2
  256. package/src/core/islands/bridge.ts +1 -0
  257. package/src/core/network/__tests__/requests-network.test.ts +17 -0
  258. package/src/core/network/requests-lazy.ts +1 -0
  259. package/src/core/network/requests-network.ts +9 -0
  260. package/src/core/network/requests-static.ts +1 -0
  261. package/src/core/network/requests-toasting.tsx +1 -0
  262. package/src/core/network/types.ts +1 -0
  263. package/src/core/wasm/bridge.ts +1 -0
  264. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -4
  265. package/src/utils/__tests__/filenames.test.ts +7 -0
  266. package/src/utils/filenames.ts +3 -0
  267. package/dist/assets/add-connection-dialog-9CzjZlY9.js +0 -138
  268. package/dist/assets/channel-k8gMdpPa.js +0 -1
  269. package/dist/assets/classDiagram-2ON5EDUG-DDFZaNDy.js +0 -1
  270. package/dist/assets/classDiagram-v2-WZHVMYZB-CEbmnHKU.js +0 -1
  271. package/dist/assets/components-CF9x5raB.js +0 -1
  272. package/dist/assets/context-aware-panel-C1uqjYZU.js +0 -3
  273. package/dist/assets/dist-B8osAFLA.js +0 -1
  274. package/dist/assets/dist-BYtATjzn.js +0 -1
  275. package/dist/assets/dist-Bb40mZM7.js +0 -1
  276. package/dist/assets/dist-C3z6pMsI.js +0 -1
  277. package/dist/assets/dist-CA6NQs25.js +0 -1
  278. package/dist/assets/dist-CCW85AP3.js +0 -1
  279. package/dist/assets/dist-CCnNQVp_.js +0 -1
  280. package/dist/assets/dist-CRVvx8nD.js +0 -1
  281. package/dist/assets/dist-CdZb2Grj.js +0 -1
  282. package/dist/assets/dist-ClLHDbNP.js +0 -1
  283. package/dist/assets/dist-CtKltiBh.js +0 -1
  284. package/dist/assets/dist-D-_c0KFz.js +0 -1
  285. package/dist/assets/dist-D6kWc2hF.js +0 -1
  286. package/dist/assets/dist-D89dID68.js +0 -1
  287. package/dist/assets/dist-DUY6xZX8.js +0 -13
  288. package/dist/assets/dist-DVHYieHl.js +0 -1
  289. package/dist/assets/dist-Q0mIwD1V.js +0 -1
  290. package/dist/assets/dist-aBuSkHFR.js +0 -1
  291. package/dist/assets/dist-gm5AeuIM.js +0 -1
  292. package/dist/assets/dist-p-IM2PMR.js +0 -1
  293. package/dist/assets/download-BTm4CTKr.js +0 -9
  294. package/dist/assets/file-code-D9wtWSiR.js +0 -1
  295. package/dist/assets/file-explorer-panel-UQLj2Iiw.js +0 -1
  296. package/dist/assets/home-page-WDj2x_g2.js +0 -4
  297. package/dist/assets/html-to-image-b9BimK8l.js +0 -2
  298. package/dist/assets/katex-YDobqqVd.js +0 -1
  299. package/dist/assets/mermaid-4DMBBIKO-C0QemhGt.js +0 -1
  300. package/dist/assets/purify.es-CPplrWRQ.js +0 -2
  301. package/dist/assets/react-vega-1nuO-sn0.js +0 -1
  302. package/dist/assets/session-panel-B5JEvDHe.js +0 -1
  303. package/dist/assets/stateDiagram-v2-4FDKWEC3-ct96_mle.js +0 -1
  304. package/dist/assets/stex-pjf-hOob.js +0 -1
  305. package/dist/assets/tracing-panel-Dz9mRjXj.js +0 -2
  306. package/dist/assets/types-DFiYrN2w.js +0 -17
  307. package/dist/assets/useCellActionButton-DFgACqVf.js +0 -1
  308. package/dist/assets/useNotebookActions-B2BTRuJb.js +0 -1
  309. /package/dist/assets/{Deferred-D2igisxY.js → Deferred-BMfCOLaw.js} +0 -0
  310. /package/dist/assets/{SSRProvider-DC7ElCZZ.js → SSRProvider-CwqN9FWV.js} +0 -0
  311. /package/dist/assets/{alert-0YTlkh9P.js → alert-Bs8tbZo_.js} +0 -0
  312. /package/dist/assets/{badge-CNBv2dAU.js → badge-BUFDGZ04.js} +0 -0
  313. /package/dist/assets/{blob-CObhN-9g.js → blob-DgooIGjS.js} +0 -0
  314. /package/dist/assets/{defaultLocale-DK1MWd7f.js → defaultLocale-CGfP-Ye3.js} +0 -0
  315. /package/dist/assets/{defaultLocale-OkOxlkkM.js → defaultLocale-CuYNS33t.js} +0 -0
  316. /package/dist/assets/{emotion-is-prop-valid.esm-D7FeWASw.js → emotion-is-prop-valid.esm-lG8j6oqk.js} +0 -0
  317. /package/dist/assets/{en-US-DBqDb4Nb.js → en-US-k6sS5Nab.js} +0 -0
  318. /package/dist/assets/{errors-Bfogio62.js → errors-0IrrdfSG.js} +0 -0
  319. /package/dist/assets/{extends-aq1t6BkR.js → extends-B9D0JO9U.js} +0 -0
  320. /package/dist/assets/{github-BrsjF9dp.js → github-BY6XM4ej.js} +0 -0
  321. /package/dist/assets/{isValid-D3F4nmET.js → isValid-CUXKlcrM.js} +0 -0
  322. /package/dist/assets/{katex-rvFxOCU-.js → katex-FSdXOW5Y.js} +0 -0
  323. /package/dist/assets/{kbd-CVbqSkT8.js → kbd-Rn7tWvNg.js} +0 -0
  324. /package/dist/assets/{link-Cpo6yhBB.js → link-BmtFffTv.js} +0 -0
  325. /package/dist/assets/{links-BKV6zi_7.js → links-MkDbmF2p.js} +0 -0
  326. /package/dist/assets/{objectWithoutPropertiesLoose-Dxmp_Bd_.js → objectWithoutPropertiesLoose-CboCOq4o.js} +0 -0
  327. /package/dist/assets/{ordinal-BEKpVWu-.js → ordinal-DMIExrUm.js} +0 -0
  328. /package/dist/assets/{paths-bMgYkaP2.js → paths-D2lG83Oh.js} +0 -0
  329. /package/dist/assets/{play-D4Tdvkms.js → play-CkqWG85-.js} +0 -0
  330. /package/dist/assets/{plus-B-s-VRHt.js → plus-C9B_qWUi.js} +0 -0
  331. /package/dist/assets/{preload-helper-TXkS1QI3.js → preload-helper-BW0IMuFq.js} +0 -0
  332. /package/dist/assets/{prop-types-DRf51_gT.js → prop-types-C638SUfx.js} +0 -0
  333. /package/dist/assets/{range-DNqFcYmr.js → range-ClqUI25v.js} +0 -0
  334. /package/dist/assets/{refresh-ccw-BOzRCrXK.js → refresh-ccw-B3lGEyQm.js} +0 -0
  335. /package/dist/assets/{refresh-cw-DeCFDX1B.js → refresh-cw-fLeDriQe.js} +0 -0
  336. /package/dist/assets/{rotate-ccw-BG5BZyzw.js → rotate-ccw-DgH8qERb.js} +0 -0
  337. /package/dist/assets/{save-I_RGv5p0.js → save-C91FTnFa.js} +0 -0
  338. /package/dist/assets/{settings-DD8FJvQ_.js → settings-DRfuuLRT.js} +0 -0
  339. /package/dist/assets/{spinner-DCSoZZhh.js → spinner-Dt4SmUsI.js} +0 -0
  340. /package/dist/assets/{square-oV8Csj8Y.js → square-DZpWT_hp.js} +0 -0
  341. /package/dist/assets/{square-function-4zY5Dv0P.js → square-function-DEp1ozoA.js} +0 -0
  342. /package/dist/assets/{stex-FMMSUPAS.js → stex-0ac7Aukl.js} +0 -0
  343. /package/dist/assets/{trash-2-DtQaB9NM.js → trash-2-CrA4LwJ2.js} +0 -0
  344. /package/dist/assets/{trash-Basz0Kvc.js → trash-ZGxZ3QGq.js} +0 -0
  345. /package/dist/assets/{triangle-alert-n1-FF7zs.js → triangle-alert-CzmxsxFO.js} +0 -0
  346. /package/dist/assets/{types-BhvWC48z.js → types-CswNghXe.js} +0 -0
  347. /package/dist/assets/{use-toast-BhMe50aT.js → use-toast-Hc8CXlvz.js} +0 -0
  348. /package/dist/assets/{useAsyncData-DVm0BCFt.js → useAsyncData-CI3ntihq.js} +0 -0
  349. /package/dist/assets/{useDebounce-BUC67G8E.js → useDebounce-S9zaMzrr.js} +0 -0
  350. /package/dist/assets/{uuid-ImXS-885.js → uuid-ClFZlR7U.js} +0 -0
  351. /package/dist/assets/{workflow-CU6kAL_h.js → workflow-DgZ_19fF.js} +0 -0
  352. /package/dist/assets/{youtube-fKFch587.js → youtube-DfMgNU9-.js} +0 -0
@@ -1,105 +1,11 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
- import {
3
- DatabaseIcon,
4
- FileAudioIcon,
5
- FileCodeIcon,
6
- FileIcon,
7
- FileImageIcon,
8
- FileJsonIcon,
9
- FileTextIcon,
10
- FileVideo2Icon,
11
- FolderArchiveIcon,
12
- FolderIcon,
13
- type LucideIcon,
14
- } from "lucide-react";
15
2
 
16
- /* Copyright 2026 Marimo. All rights reserved. */
17
- export type FileType =
18
- | "directory"
19
- | "python"
20
- | "code"
21
- | "json"
22
- | "text"
23
- | "image"
24
- | "audio"
25
- | "video"
26
- | "data"
27
- | "pdf"
28
- | "zip"
29
- | "unknown";
30
-
31
- export function guessFileType(name: string): FileType {
32
- const ext = name.split(".").pop();
33
- if (ext === undefined) {
34
- return "unknown";
35
- }
36
- switch (ext.toLowerCase()) {
37
- case "py":
38
- return "python";
39
- case "txt":
40
- case "md":
41
- case "qmd":
42
- return "text";
43
- case "png":
44
- case "jpg":
45
- case "jpeg":
46
- case "gif":
47
- return "image";
48
- case "csv":
49
- return "data";
50
- case "json":
51
- return "json";
52
- // Non-exhaustive list of code file extensions
53
- case "js":
54
- case "ts":
55
- case "tsx":
56
- case "html":
57
- case "css":
58
- case "toml":
59
- case "yaml":
60
- case "yml":
61
- case "wasm":
62
- return "code";
63
- case "mp3":
64
- case "m4a":
65
- case "m4v":
66
- case "ogg":
67
- case "wav":
68
- return "audio";
69
- case "mp4":
70
- case "webm":
71
- case "mkv":
72
- return "video";
73
- case "pdf":
74
- return "pdf";
75
- case "zip":
76
- case "tar":
77
- case "gz":
78
- return "zip";
79
- default:
80
- return "unknown";
81
- }
82
- }
83
-
84
- export const FILE_TYPE_ICONS: Record<FileType, LucideIcon> = {
85
- directory: FolderIcon,
86
- python: FileCodeIcon,
87
- json: FileJsonIcon,
88
- code: FileCodeIcon,
89
- text: FileTextIcon,
90
- image: FileImageIcon,
91
- audio: FileAudioIcon,
92
- video: FileVideo2Icon,
93
- pdf: FileCodeIcon,
94
- zip: FolderArchiveIcon,
95
- data: DatabaseIcon,
96
- unknown: FileIcon,
97
- };
3
+ import type { FileIconType } from "@/components/editor/file-tree/file-icons";
98
4
 
99
5
  const TAB = " ";
100
6
 
101
7
  export const PYTHON_CODE_FOR_FILE_TYPE: Record<
102
- FileType,
8
+ FileIconType,
103
9
  (path: string) => string
104
10
  > = {
105
11
  directory: (path) => `os.listdir("${path}")`,
@@ -3,6 +3,10 @@
3
3
  import { PopoverAnchor } from "@radix-ui/react-popover";
4
4
  import { FilePenIcon } from "lucide-react";
5
5
  import { type JSX, useEffect, useRef, useState } from "react";
6
+ import {
7
+ FILE_ICON as FILE_TYPE_ICONS,
8
+ guessFileIconType as guessFileType,
9
+ } from "@/components/editor/file-tree/file-icons";
6
10
  import type { FileInfo } from "@/core/network/types";
7
11
  import { useAsyncData } from "@/hooks/useAsyncData";
8
12
  import { Paths } from "@/utils/paths";
@@ -15,7 +19,6 @@ import {
15
19
  CommandList,
16
20
  } from "../../ui/command";
17
21
  import { Popover, PopoverContent } from "../../ui/popover";
18
- import { FILE_TYPE_ICONS, guessFileType } from "../file-tree/types";
19
22
 
20
23
  import "./filename-input.css";
21
24
  import { getFeatureFlag } from "@/core/config/feature-flag";
@@ -23,6 +23,11 @@ import {
23
23
  } from "react-arborist";
24
24
  import { useLocale } from "react-aria";
25
25
  import { MarkdownIcon } from "@/components/editor/cell/code/icons";
26
+ import {
27
+ FILE_ICON as FILE_TYPE_ICONS,
28
+ type FileIconType as FileType,
29
+ guessFileIconType as guessFileType,
30
+ } from "@/components/editor/file-tree/file-icons";
26
31
  import { useImperativeModal } from "@/components/modal/ImperativeModal";
27
32
  import { AlertDialogDestructiveAction } from "@/components/ui/alert-dialog";
28
33
  import { Button } from "@/components/ui/button";
@@ -47,11 +52,6 @@ import { newNotebookURL } from "@/utils/urls";
47
52
  import { ConfigButton } from "../app-config/app-config-button";
48
53
  import { ErrorBoundary } from "../editor/boundary/ErrorBoundary";
49
54
  import { ShutdownButton } from "../editor/controls/shutdown-button";
50
- import {
51
- FILE_TYPE_ICONS,
52
- type FileType,
53
- guessFileType,
54
- } from "../editor/file-tree/types";
55
55
  import {
56
56
  Header,
57
57
  OpenTutorialDropDown,
@@ -8,15 +8,9 @@ import CoreweaveIcon from "@marimo-team/llm-info/icons/coreweave.svg?inline";
8
8
  import CoreweaveDarkIcon from "@marimo-team/llm-info/icons/coreweave-dark.svg?inline";
9
9
  import {
10
10
  DatabaseZapIcon,
11
- FileCodeIcon,
12
- FileIcon,
13
- FileSpreadsheetIcon,
14
- FileTextIcon,
15
- FileVideoIcon,
16
11
  GithubIcon,
17
12
  GlobeIcon,
18
13
  HardDriveIcon,
19
- ImageIcon,
20
14
  } from "lucide-react";
21
15
  import GoogleCloudIcon from "@/components/databases/icons/google-cloud-storage.svg?inline";
22
16
  import GoogleDriveIcon from "@/components/databases/icons/google-drive.svg?inline";
@@ -24,38 +18,6 @@ import type { KnownStorageProtocol } from "@/core/storage/types";
24
18
  import { useTheme } from "@/theme/useTheme";
25
19
  import { cn } from "@/utils/cn";
26
20
 
27
- export function renderFileIcon(name: string): React.ReactNode {
28
- const ext = name.split(".").pop()?.toLowerCase();
29
- switch (ext) {
30
- case "png":
31
- case "jpg":
32
- case "jpeg":
33
- case "gif":
34
- case "svg":
35
- case "webp":
36
- return <ImageIcon className="h-3.5 w-3.5 text-purple-500" />;
37
- case "csv":
38
- case "parquet":
39
- case "arrow":
40
- case "xlsx":
41
- return <FileSpreadsheetIcon className="h-3.5 w-3.5 text-green-500" />;
42
- case "py":
43
- case "js":
44
- case "ts":
45
- case "json":
46
- return <FileCodeIcon className="h-3.5 w-3.5 text-blue-500" />;
47
- case "mp4":
48
- case "mpeg":
49
- return <FileVideoIcon className="h-3.5 w-3.5 text-orange-500" />;
50
- case "txt":
51
- case "md":
52
- case "log":
53
- return <FileTextIcon className="h-3.5 w-3.5 text-muted-foreground" />;
54
- default:
55
- return <FileIcon className="h-3.5 w-3.5 text-muted-foreground" />;
56
- }
57
- }
58
-
59
21
  type IconEntry =
60
22
  | { src: string; dark?: string }
61
23
  | React.ComponentType<{ className?: string }>;
@@ -5,6 +5,7 @@ import type React from "react";
5
5
  import { useCallback } from "react";
6
6
  import { useLocale } from "react-aria";
7
7
  import { FilePreviewHeader } from "@/components/editor/file-tree/file-header";
8
+ import { renderFileIcon } from "@/components/editor/file-tree/file-icons";
8
9
  import {
9
10
  FileContentRenderer,
10
11
  isMediaMime,
@@ -18,7 +19,6 @@ import { formatBytes } from "@/utils/formatting";
18
19
  import { Logger } from "@/utils/Logger";
19
20
  import { CopyClipboardIcon } from "../icons/copy-icon";
20
21
  import { Button } from "../ui/button";
21
- import { renderFileIcon } from "./components";
22
22
 
23
23
  const MAX_MEDIA_PREVIEW_SIZE = 100 * 1024 * 1024; // 100 MB
24
24
 
@@ -2,16 +2,13 @@
2
2
 
3
3
  import { CommandList } from "cmdk";
4
4
  import {
5
- ChevronRightIcon,
6
5
  CopyIcon,
7
6
  DownloadIcon,
8
7
  FolderIcon,
9
8
  HardDriveIcon,
10
9
  HelpCircleIcon,
11
10
  LoaderCircle,
12
- MoreVerticalIcon,
13
11
  PlusIcon,
14
- RefreshCwIcon,
15
12
  ViewIcon,
16
13
  XIcon,
17
14
  } from "lucide-react";
@@ -20,6 +17,16 @@ import { useLocale } from "react-aria";
20
17
  import { EngineVariable } from "@/components/databases/engine-variable";
21
18
  import { PanelEmptyState } from "@/components/editor/chrome/panels/empty-state";
22
19
  import { AddConnectionDialog } from "@/components/editor/connections/add-connection-dialog";
20
+ import {
21
+ FILE_ICON_COLOR,
22
+ renderFileIcon,
23
+ } from "@/components/editor/file-tree/file-icons";
24
+ import {
25
+ MENU_ITEM_ICON_CLASS,
26
+ MoreActionsButton,
27
+ RefreshIconButton,
28
+ TreeChevron,
29
+ } from "@/components/editor/file-tree/tree-actions";
23
30
  import { Command, CommandInput, CommandItem } from "@/components/ui/command";
24
31
  import {
25
32
  DropdownMenu,
@@ -49,7 +56,7 @@ import { formatBytes } from "@/utils/formatting";
49
56
  import { Logger } from "@/utils/Logger";
50
57
  import { ErrorState } from "../datasources/components";
51
58
  import { Button } from "../ui/button";
52
- import { ProtocolIcon, renderFileIcon } from "./components";
59
+ import { ProtocolIcon } from "./components";
53
60
  import { StorageFileViewer } from "./storage-file-viewer";
54
61
 
55
62
  interface OpenFileInfo {
@@ -305,17 +312,14 @@ const StorageEntryRow: React.FC<{
305
312
  }}
306
313
  >
307
314
  {isDir ? (
308
- <ChevronRightIcon
309
- className={cn(
310
- "h-3 w-3 shrink-0 transition-transform",
311
- effectiveExpanded && "rotate-90",
312
- )}
313
- />
315
+ <TreeChevron isExpanded={effectiveExpanded} className="h-3 w-3" />
314
316
  ) : (
315
317
  <span className="w-3 shrink-0" />
316
318
  )}
317
319
  {isDir ? (
318
- <FolderIcon className="h-3.5 w-3.5 text-amber-500 shrink-0" />
320
+ <FolderIcon
321
+ className={cn("h-3.5 w-3.5 shrink-0", FILE_ICON_COLOR.directory)}
322
+ />
319
323
  ) : (
320
324
  renderFileIcon(name)
321
325
  )}
@@ -337,14 +341,10 @@ const StorageEntryRow: React.FC<{
337
341
  )}
338
342
  <DropdownMenu>
339
343
  <DropdownMenuTrigger asChild={true}>
340
- <Button
341
- variant="text"
342
- size="icon"
343
- className="opacity-0 group-hover:opacity-100 transition-opacity hover:shadow-none hover:text-link text-muted-foreground"
344
+ <MoreActionsButton
345
+ iconClassName="h-3 w-3"
344
346
  onClick={(e) => e.stopPropagation()}
345
- >
346
- <MoreVerticalIcon className="h-3 w-3" />
347
- </Button>
347
+ />
348
348
  </DropdownMenuTrigger>
349
349
  <DropdownMenuContent
350
350
  align="end"
@@ -355,7 +355,7 @@ const StorageEntryRow: React.FC<{
355
355
  <DropdownMenuItem
356
356
  onSelect={() => onOpenFile({ entry, namespace })}
357
357
  >
358
- <ViewIcon className="h-3.5 w-3.5 mr-2" />
358
+ <ViewIcon className={MENU_ITEM_ICON_CLASS} />
359
359
  View
360
360
  </DropdownMenuItem>
361
361
  )}
@@ -366,12 +366,12 @@ const StorageEntryRow: React.FC<{
366
366
  toast({ title: "Copied to clipboard" });
367
367
  }}
368
368
  >
369
- <CopyIcon className="h-3.5 w-3.5 mr-2" />
369
+ <CopyIcon className={MENU_ITEM_ICON_CLASS} />
370
370
  Copy URL
371
371
  </DropdownMenuItem>
372
372
  {!isDir && (
373
373
  <DropdownMenuItem onSelect={() => handleDownload()}>
374
- <DownloadIcon className="h-3.5 w-3.5 mr-2" />
374
+ <DownloadIcon className={MENU_ITEM_ICON_CLASS} />
375
375
  Download
376
376
  </DropdownMenuItem>
377
377
  )}
@@ -402,7 +402,6 @@ const StorageNamespaceSection: React.FC<{
402
402
  onOpenFile: (info: OpenFileInfo) => void;
403
403
  }> = ({ namespace, locale, searchValue, onOpenFile }) => {
404
404
  const [isExpanded, setIsExpanded] = useState(true);
405
- const [isSpinning, setIsSpinning] = useState(false);
406
405
  const { entriesByPath } = useStorage();
407
406
  const { clearNamespaceCache } = useStorageActions();
408
407
  const namespaceName = namespace.name ?? namespace.displayName;
@@ -417,10 +416,8 @@ const StorageNamespaceSection: React.FC<{
417
416
  const handleRefresh = useCallback(
418
417
  (e: React.MouseEvent) => {
419
418
  e.stopPropagation();
420
- setIsSpinning(true);
421
419
  clearNamespaceCache(namespaceName);
422
420
  refetch();
423
- setTimeout(() => setIsSpinning(false), 500);
424
421
  },
425
422
  [namespaceName, clearNamespaceCache, refetch],
426
423
  );
@@ -441,12 +438,7 @@ const StorageNamespaceSection: React.FC<{
441
438
  onSelect={() => setIsExpanded(!isExpanded)}
442
439
  className="flex flex-row font-semibold h-7 text-xs gap-1.5 bg-(--slate-2) text-muted-foreground rounded-none"
443
440
  >
444
- <ChevronRightIcon
445
- className={cn(
446
- "h-3 w-3 shrink-0 transition-transform",
447
- isExpanded && "rotate-90",
448
- )}
449
- />
441
+ <TreeChevron isExpanded={isExpanded} className="h-3 w-3" />
450
442
  <ProtocolIcon protocol={namespace.protocol} />
451
443
  <span>{namespace.displayName}</span>
452
444
  {namespace.name && (
@@ -454,21 +446,12 @@ const StorageNamespaceSection: React.FC<{
454
446
  (<EngineVariable variableName={namespace.name as VariableName} />)
455
447
  </span>
456
448
  )}
457
- <Tooltip content="Refresh storage connection">
458
- <Button
459
- variant="ghost"
460
- size="icon"
461
- className="hover:bg-transparent hover:shadow-none"
462
- onClick={handleRefresh}
463
- >
464
- <RefreshCwIcon
465
- className={cn(
466
- "h-3 w-3 text-muted-foreground hover:text-foreground",
467
- isSpinning && "animate-[spin_0.5s]",
468
- )}
469
- />
470
- </Button>
471
- </Tooltip>
449
+ <RefreshIconButton
450
+ onClick={handleRefresh}
451
+ tooltip="Refresh storage connection"
452
+ className="p-0"
453
+ iconClassName="h-3 w-3"
454
+ />
472
455
  <span className="text-[10px] text-muted-foreground font-normal tabular-nums ml-auto">
473
456
  {namespace.rootPath || "(root)"}
474
457
  </span>
@@ -1,6 +1,12 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { describe, expect, it } from "vitest";
3
- import { type Hotkey, type HotkeyAction, HotkeyProvider } from "../hotkeys";
3
+ import {
4
+ type Hotkey,
5
+ type HotkeyAction,
6
+ HotkeyProvider,
7
+ normalizeKeyString,
8
+ OverridingHotkeyProvider,
9
+ } from "../hotkeys";
4
10
 
5
11
  /**
6
12
  * Just a helper.
@@ -72,3 +78,60 @@ describe("HotkeyProvider platform separation", () => {
72
78
  expect(linux.getHotkey("cell.format").key).toBe("Ctrl-Shift-L");
73
79
  });
74
80
  });
81
+
82
+ describe("normalizeKeyString", () => {
83
+ it("should capitalize multi-character base key names", () => {
84
+ expect(normalizeKeyString("Shift-enter")).toBe("Shift-Enter");
85
+ expect(normalizeKeyString("Cmd-enter")).toBe("Cmd-Enter");
86
+ expect(normalizeKeyString("Ctrl-backspace")).toBe("Ctrl-Backspace");
87
+ expect(normalizeKeyString("Alt-tab")).toBe("Alt-Tab");
88
+ expect(normalizeKeyString("Cmd-Shift-arrowUp")).toBe("Cmd-Shift-ArrowUp");
89
+ });
90
+
91
+ it("should leave already-correct key names unchanged", () => {
92
+ expect(normalizeKeyString("Shift-Enter")).toBe("Shift-Enter");
93
+ expect(normalizeKeyString("Cmd-Enter")).toBe("Cmd-Enter");
94
+ expect(normalizeKeyString("Mod-Shift-Enter")).toBe("Mod-Shift-Enter");
95
+ });
96
+
97
+ it("should leave single-character keys unchanged", () => {
98
+ expect(normalizeKeyString("Cmd-a")).toBe("Cmd-a");
99
+ expect(normalizeKeyString("Ctrl-Shift-z")).toBe("Ctrl-Shift-z");
100
+ expect(normalizeKeyString("a")).toBe("a");
101
+ });
102
+
103
+ it("should handle keys without modifiers", () => {
104
+ expect(normalizeKeyString("enter")).toBe("Enter");
105
+ expect(normalizeKeyString("Escape")).toBe("Escape");
106
+ expect(normalizeKeyString("F12")).toBe("F12");
107
+ });
108
+ });
109
+
110
+ describe("OverridingHotkeyProvider", () => {
111
+ it("should normalize lowercase key overrides", () => {
112
+ const provider = new OverridingHotkeyProvider(
113
+ {
114
+ "cell.run": "Shift-enter",
115
+ "cell.runAndNewBelow": "Cmd-enter",
116
+ },
117
+ { platform: "mac" },
118
+ );
119
+
120
+ expect(provider.getHotkey("cell.run").key).toBe("Shift-Enter");
121
+ expect(provider.getHotkey("cell.runAndNewBelow").key).toBe("Cmd-Enter");
122
+ });
123
+
124
+ it("should return defaults when no override is set", () => {
125
+ const provider = new OverridingHotkeyProvider({}, { platform: "mac" });
126
+ expect(provider.getHotkey("cell.run").key).toBe("Cmd-Enter");
127
+ expect(provider.getHotkey("cell.runAndNewBelow").key).toBe("Shift-Enter");
128
+ });
129
+
130
+ it("should pass through correctly-cased overrides unchanged", () => {
131
+ const provider = new OverridingHotkeyProvider(
132
+ { "cell.run": "Shift-Enter" },
133
+ { platform: "mac" },
134
+ );
135
+ expect(provider.getHotkey("cell.run").key).toBe("Shift-Enter");
136
+ });
137
+ });
@@ -535,10 +535,26 @@ export class OverridingHotkeyProvider extends HotkeyProvider {
535
535
 
536
536
  override getHotkey(action: HotkeyAction): ResolvedHotkey {
537
537
  const base = super.getHotkey(action);
538
- const key = this.overrides[action] || base.key;
538
+ const override = this.overrides[action];
539
539
  return {
540
540
  name: base.name,
541
- key,
541
+ key: override ? normalizeKeyString(override) : base.key,
542
542
  };
543
543
  }
544
544
  }
545
+
546
+ const MODIFIER_RE = /^(cmd|ctrl|alt|shift|meta|mod)$/i;
547
+
548
+ /**
549
+ * Capitalize multi-character base key names so they match the
550
+ * casing that KeyboardEvent.key (and therefore CodeMirror) uses.
551
+ * e.g. "Shift-enter" → "Shift-Enter", "Cmd-backspace" → "Cmd-Backspace"
552
+ */
553
+ export function normalizeKeyString(key: string): string {
554
+ const parts = key.split("-");
555
+ const last = parts[parts.length - 1];
556
+ if (last.length > 1 && !MODIFIER_RE.test(last)) {
557
+ parts[parts.length - 1] = last.charAt(0).toUpperCase() + last.slice(1);
558
+ }
559
+ return parts.join("-");
560
+ }
@@ -181,6 +181,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
181
181
  sendFileDetails = throwNotImplemented;
182
182
  openTutorial = throwNotImplemented;
183
183
  exportAsHTML = throwNotImplemented;
184
+ exportAsIPYNB = throwNotImplemented;
184
185
  exportAsMarkdown = throwNotImplemented;
185
186
  exportAsPDF = throwNotImplemented;
186
187
  autoExportAsHTML = throwNotImplemented;
@@ -113,5 +113,22 @@ describe("createNetworkRequests", () => {
113
113
  }),
114
114
  );
115
115
  });
116
+
117
+ it("exportAsIPYNB should call the new endpoint as text", async () => {
118
+ const requests = createNetworkRequests();
119
+ await requests.exportAsIPYNB({
120
+ download: false,
121
+ } as any);
122
+
123
+ expect(mockClient.POST).toHaveBeenCalledWith(
124
+ "/api/export/ipynb",
125
+ expect.objectContaining({
126
+ body: expect.objectContaining({
127
+ download: false,
128
+ }),
129
+ parseAs: "text",
130
+ }),
131
+ );
132
+ });
116
133
  });
117
134
  });
@@ -49,6 +49,7 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
49
49
 
50
50
  // Export operations start a connection
51
51
  exportAsHTML: "startConnection",
52
+ exportAsIPYNB: "startConnection",
52
53
  exportAsMarkdown: "startConnection",
53
54
  exportAsPDF: "startConnection",
54
55
  readCode: "startConnection",
@@ -381,6 +381,15 @@ export function createNetworkRequests(): EditRequests & RunRequests {
381
381
  })
382
382
  .then(handleResponse);
383
383
  },
384
+ exportAsIPYNB: async (request) => {
385
+ return getClient()
386
+ .POST("/api/export/ipynb", {
387
+ body: request,
388
+ parseAs: "text",
389
+ params: getParams(),
390
+ })
391
+ .then(handleResponse);
392
+ },
384
393
  exportAsPDF: async (request) => {
385
394
  return getClient()
386
395
  .POST("/api/export/pdf", {
@@ -75,6 +75,7 @@ export function createStaticRequests(): EditRequests & RunRequests {
75
75
  getRunningNotebooks: throwNotInEditMode,
76
76
  shutdownSession: throwNotInEditMode,
77
77
  exportAsHTML: throwNotInEditMode,
78
+ exportAsIPYNB: throwNotInEditMode,
78
79
  exportAsMarkdown: throwNotInEditMode,
79
80
  exportAsPDF: throwNotInEditMode,
80
81
  autoExportAsHTML: throwNotInEditMode,
@@ -60,6 +60,7 @@ export function createErrorToastingRequests(
60
60
  getRunningNotebooks: "Failed to get running notebooks",
61
61
  shutdownSession: "Failed to shutdown session",
62
62
  exportAsHTML: "Failed to export HTML",
63
+ exportAsIPYNB: "Failed to export ipynb",
63
64
  exportAsMarkdown: "Failed to export Markdown",
64
65
  exportAsPDF: "Failed to export PDF",
65
66
  autoExportAsHTML: "", // No toast
@@ -180,6 +180,7 @@ export interface EditRequests {
180
180
  ) => Promise<RunningNotebooksResponse>;
181
181
  // Export requests
182
182
  exportAsHTML: (request: ExportAsHTMLRequest) => Promise<string>;
183
+ exportAsIPYNB: (request: ExportAsIPYNBRequest) => Promise<string>;
183
184
  exportAsMarkdown: (request: ExportAsMarkdownRequest) => Promise<string>;
184
185
  exportAsPDF: (request: ExportAsPDFRequest) => Promise<Blob>;
185
186
  autoExportAsHTML: (request: ExportAsHTMLRequest) => Promise<null>;
@@ -587,6 +587,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
587
587
  getWorkspaceFiles = throwNotImplemented;
588
588
  getRunningNotebooks = throwNotImplemented;
589
589
  shutdownSession = throwNotImplemented;
590
+ exportAsIPYNB = throwNotImplemented;
590
591
  exportAsPDF = throwNotImplemented;
591
592
  autoExportAsHTML = throwNotImplemented;
592
593
  autoExportAsMarkdown = throwNotImplemented;
@@ -4,10 +4,10 @@ import { CornerLeftUp } from "lucide-react";
4
4
  import { type JSX, useEffect, useState } from "react";
5
5
  import { z } from "zod";
6
6
  import {
7
- FILE_TYPE_ICONS,
8
- type FileType,
9
- guessFileType,
10
- } from "@/components/editor/file-tree/types";
7
+ FILE_ICON as FILE_TYPE_ICONS,
8
+ type FileIconType as FileType,
9
+ guessFileIconType as guessFileType,
10
+ } from "@/components/editor/file-tree/file-icons";
11
11
  import { Spinner } from "@/components/icons/spinner";
12
12
  import { Button } from "@/components/ui/button";
13
13
  import { Checkbox } from "@/components/ui/checkbox";
@@ -23,6 +23,12 @@ describe("Filenames", () => {
23
23
  expect(Filenames.toPNG("test.foo.py")).toEqual("test.foo.png");
24
24
  });
25
25
 
26
+ it("should convert filename to ipynb", () => {
27
+ expect(Filenames.toIPYNB("test")).toEqual("test.ipynb");
28
+ expect(Filenames.toIPYNB("test.txt")).toEqual("test.ipynb");
29
+ expect(Filenames.toIPYNB("test.foo.py")).toEqual("test.foo.ipynb");
30
+ });
31
+
26
32
  it("should remove extension from filename", () => {
27
33
  expect(Filenames.withoutExtension("test")).toEqual("test");
28
34
  expect(Filenames.withoutExtension("test.txt")).toEqual("test");
@@ -39,6 +45,7 @@ describe("Filenames", () => {
39
45
  expect(Filenames.toHTML(filename)).toEqual(`${withoutExt}.html`);
40
46
  expect(Filenames.toPNG(filename)).toEqual(`${withoutExt}.png`);
41
47
  expect(Filenames.toPY(filename)).toEqual(`${withoutExt}.py`);
48
+ expect(Filenames.toIPYNB(filename)).toEqual(`${withoutExt}.ipynb`);
42
49
 
43
50
  // Ensure operations preserve unicode and special characters in base name
44
51
  expect(withoutExt).not.toEqual("");
@@ -15,6 +15,9 @@ export const Filenames = {
15
15
  toPY: (filename: string): string => {
16
16
  return Filenames.replace(filename, "py");
17
17
  },
18
+ toIPYNB: (filename: string): string => {
19
+ return Filenames.replace(filename, "ipynb");
20
+ },
18
21
  withoutExtension: (filename: string): string => {
19
22
  // Just remove the last extension
20
23
  const parts = filename.split(".");