@marimo-team/islands 0.24.3-dev3 → 0.24.3-dev30

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 (289) hide show
  1. package/dist/{ConnectedDataExplorerComponent-qIKbwYin.js → ConnectedDataExplorerComponent-BLO7UDpo.js} +18 -18
  2. package/dist/{ErrorBoundary-CR-ZQN_c.js → ErrorBoundary-B7uSdDUm.js} +6 -6
  3. package/dist/{ImageComparisonComponent-2a9TMMm2.js → ImageComparisonComponent-RspMflu6.js} +3 -3
  4. package/dist/{Plot-C-9MQeGP.js → Plot-CTyjbQDT.js} +21032 -20666
  5. package/dist/_baseMerge-Bnytch8P.js +165 -0
  6. package/dist/{abnfDiagram-N423BO3Z-CQKwzX8t.js → abnfDiagram-VCTEODGH-DCb2K_RB.js} +17 -18
  7. package/dist/{any-language-editor-CpTnK43-.js → any-language-editor-C0dftc2Z.js} +8 -8
  8. package/dist/arc-7ra3iNdN.js +81 -0
  9. package/dist/architecture-7GRP2DOG-BWLylgiA.js +3 -0
  10. package/dist/{architectureDiagram-T3A2C74G-CncrDpfa.js → architectureDiagram-5GKGNRK7-Bb_n642s.js} +25 -25
  11. package/dist/assets/__vite-browser-external-BajL8aoc.js +1 -0
  12. package/dist/assets/worker-BemUy60C.js +109 -0
  13. package/dist/blockDiagram-I7D4REHJ-BbXEXJRu.js +1922 -0
  14. package/dist/{button-CKBkqR9J.js → button-DdXAm8iz.js} +5 -5
  15. package/dist/{c4Diagram-5PPSVZJV-DarUk3Yq.js → c4Diagram-7LVT6UL2-DcLsbQmR.js} +696 -668
  16. package/dist/{capabilities-CMBBJTcc.js → capabilities-B3ce_GNu.js} +1 -1
  17. package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
  18. package/dist/chat-ui-DiMxe-GH.js +5835 -0
  19. package/dist/{check-CHig47QV.js → check-mcQyZmFG.js} +1 -1
  20. package/dist/{chunk-2Q5K7J3B-BMuJl2jB.js → chunk-2Q5K7J3B-BMkUkeuy.js} +2 -2
  21. package/dist/chunk-4HAMMTFA-D2qv8E0X.js +4188 -0
  22. package/dist/{chunk-5VM5RSS4-Bcq0ftdy.js → chunk-5VM5RSS4-DKsmPCL6.js} +2 -2
  23. package/dist/{chunk-NSK5VX7P-CDTMcJB0.js → chunk-75Z2AOVW-5_HsvXwr.js} +23 -23
  24. package/dist/{chunk-I66GZJ75-BqyTCAPf.js → chunk-DU6HZSFF-BUgAHvnM.js} +21 -4
  25. package/dist/{chunk-2GRJ4B5K-DgO8Qudq.js → chunk-F27PBJKO-DHmYWZXr.js} +4 -4
  26. package/dist/{chunk-KEIR6QF5-C4KX3XYh.js → chunk-FOHPRMQF-BpYR8RqP.js} +4 -4
  27. package/dist/{chunk-WRU74C26-BpWsbiDK.js → chunk-GMAD6QVW-Czynz8aA.js} +486 -258
  28. package/dist/chunk-GVQU2GXP-yQEdulRS.js +37 -0
  29. package/dist/{chunk-5RXB4S5H-tLNUVDdO.js → chunk-IMKFNOWR-Du9BN2Ul.js} +11 -11
  30. package/dist/{chunk-JWPE2WC7-BJwjGUnF.js → chunk-JWPE2WC7-DJvv1t8U.js} +2 -2
  31. package/dist/chunk-L3NEJ4N5-DwRWnDDK.js +245 -0
  32. package/dist/{chunk-7Z6QIM7H-Dc18hFxH.js → chunk-OSK3NFVY-BBKU_Ign.js} +222 -144
  33. package/dist/{chunk-W5SLKNZC-DLnvpEtV.js → chunk-P2QGCYS3-C0iGU29N.js} +20 -20
  34. package/dist/{chunk-KBJHAD2P-BuqWqkcW.js → chunk-POPQ4Y6H-BCbS3Ozc.js} +4 -4
  35. package/dist/{chunk-4I5QYGJK-DpytHuZQ.js → chunk-PWAF6VOD-CTFCL0jI.js} +4 -4
  36. package/dist/{chunk-JQJVKLGR-CgqCwe8E.js → chunk-SHT3W25Y-tUelricH.js} +109 -63
  37. package/dist/{chunk-6Q2QTUOP-DmTcEBMn.js → chunk-SVP7TREG-DK3egkfQ.js} +5 -5
  38. package/dist/{chunk-GF5L2VYU-B0wgCQgS.js → chunk-TICWLB2K-DRANTdnp.js} +13 -13
  39. package/dist/{chunk-XXDRQBXY-D73H4IN0.js → chunk-XXDRQBXY-Dnl5VBqG.js} +3 -3
  40. package/dist/{chunk-Y2CYZVJY-DoegUj_e.js → chunk-Y2CYZVJY-DKKS1VyV.js} +1 -1
  41. package/dist/{chunk-5FQGJX7Z-B85XCPv6.js → chunk-YOKDWASO-DrWbKnxA.js} +6925 -5460
  42. package/dist/classDiagram-ZZMXUADV-7wCSVH7o.js +30 -0
  43. package/dist/classDiagram-v2-VYDZK3BY-QwnvcnhB.js +30 -0
  44. package/dist/{common-CwJerb7K.js → common-_pES-ftX.js} +7398 -6912
  45. package/dist/{compiler-runtime-CAH9RLw2.js → compiler-runtime-Cj8ZWiNS.js} +2 -2
  46. package/dist/{copy-CD7S58CY.js → copy-C0N4m1lm.js} +4 -4
  47. package/dist/{cose-bilkent-JH36ORCC-FUWHkXFX.js → cose-bilkent-JH36ORCC-_LyRKVqm.js} +2 -2
  48. package/dist/cubic-OaEBhQPK.js +1404 -0
  49. package/dist/cynefin-OW5HDTMX-obq-i80l.js +3 -0
  50. package/dist/{cynefinDiagram-MW4NZA55-BXSFK93J.js → cynefinDiagram-5FMLGOSQ-CB7O4IZB.js} +10 -10
  51. package/dist/{dagre-CGyalH38.js → dagre-DfYd3btw.js} +678 -537
  52. package/dist/dagre-GXQ25YYZ-C-a95ISW.js +425 -0
  53. package/dist/{data-grid-overlay-editor-DZM4BAaI.js → data-grid-overlay-editor-C5eUZVTo.js} +8 -9
  54. package/dist/{data-grid-types-BnZwWG8z.js → data-grid-types-BucVmDDp.js} +1 -1
  55. package/dist/{defaultLocale-DKaU_opG.js → defaultLocale-JI_lnoCe.js} +1 -1
  56. package/dist/{diagram-7IWD3JNH-BjfzDNvj.js → diagram-S7CK7UJ4-BsKLYQaH.js} +40 -39
  57. package/dist/{diagram-UB23O5K3-DDg-7wLA.js → diagram-UQ7AKVKN-ppYdvuTN.js} +10 -10
  58. package/dist/{diagram-B4RE2ZJO-CKccR9eE.js → diagram-VSXAHHWV-BKpmG23x.js} +10 -10
  59. package/dist/{diagram-Q27KOJAE-Zhz01ss7.js → diagram-VX7I27RA-CAMK2l0E.js} +21 -21
  60. package/dist/{diagram-LBJQPF4R-CJ-bOruh.js → diagram-Z3DM3KII-CxQ7MggT.js} +10 -10
  61. package/dist/{dist-dAqZAPcF.js → dist-1HDa70oE.js} +3 -3
  62. package/dist/{dist-3_o3T78I.js → dist-6ChWbo8z.js} +13 -13
  63. package/dist/{dist-Re9sOPOx.js → dist-9x1ZRe-e.js} +2 -2
  64. package/dist/{dist-DEeLqRlU.js → dist-B1vYLK28.js} +1 -1
  65. package/dist/{dist-C5Bn52W4.js → dist-B8D7McG3.js} +3 -3
  66. package/dist/{dist-_XvgytiS.js → dist-BHCHt1NI.js} +1 -1
  67. package/dist/{dist-CRjAdnqF.js → dist-BRxfaJgs.js} +3 -3
  68. package/dist/{dist-Byj2bV8o.js → dist-BVGtK7Ht.js} +1 -1
  69. package/dist/{dist-BIN5LKyE.js → dist-BaHjhkpZ.js} +2 -2
  70. package/dist/{dist-DVFbIwc5.js → dist-BtKIs9N-.js} +1 -1
  71. package/dist/{dist-BrQGcfQ9.js → dist-C2KzV-vf.js} +2 -2
  72. package/dist/{dist-DJFiGP2k.js → dist-C2wDlYdD.js} +2 -2
  73. package/dist/{dist-BVRM2y1P.js → dist-C8xMLVYi.js} +2 -2
  74. package/dist/dist-CMh_W4y4.js +538 -0
  75. package/dist/{dist-BzN60Z2s.js → dist-CPGxfVGX.js} +1 -1
  76. package/dist/{dist-C7v-9nUK.js → dist-Cm3iAFMD.js} +3 -3
  77. package/dist/{dist-CGAxEiaM.js → dist-Cs2FijYk.js} +2 -2
  78. package/dist/{dist-hXd65f0_.js → dist-D1PpnuZB.js} +1 -1
  79. package/dist/{dist-VdvbxG72.js → dist-DHOTQar0.js} +1 -1
  80. package/dist/{dist-DcgzXCfy.js → dist-DPcEtqmG.js} +2 -2
  81. package/dist/{dist-D4Z_qdP4.js → dist-Df0wKI0F.js} +1 -1
  82. package/dist/{dist-qhLI-SHd.js → dist-DszxuxS1.js} +2 -2
  83. package/dist/{dist-BEmkrGoQ.js → dist-Kxgjxakw.js} +1 -1
  84. package/dist/{dist-BbSMhhD2.js → dist-KzZ7WELx.js} +2 -2
  85. package/dist/{dist-jWUab2d1.js → dist-lA1Cttkb.js} +1 -1
  86. package/dist/{dropdown-menu-DhCfcscX.js → dropdown-menu-C73aTomr.js} +184 -184
  87. package/dist/{ebnfDiagram-BXEA7PRR-Dm75pCAS.js → ebnfDiagram-PWID7BFC-DzybELvk.js} +17 -18
  88. package/dist/{erDiagram-JOGREHBK-rVDG3VSQ.js → erDiagram-RLTQ6QDP-BVxV97ld.js} +1037 -798
  89. package/dist/{error-banner-WDhUzJyg.js → error-banner-hCaH06e3.js} +207 -207
  90. package/dist/{esm-CR1nhb1c.js → esm-BElI3qKH.js} +22 -22
  91. package/dist/{esm-C1d0g6Bv.js → esm-G4Fhsgng.js} +51 -37
  92. package/dist/{esm-CesmlDrs.js → esm-blALgIVy.js} +332 -319
  93. package/dist/eventmodeling-NTZA5JFV-D7nP7Uyu.js +3 -0
  94. package/dist/{extends-BPB6_lTK.js → extends-Do6pRuJa.js} +8 -8
  95. package/dist/flowDiagram-HODETNUW-BKvXsWYX.js +16 -0
  96. package/dist/{formats-CJMVUfb3.js → formats-vDAoRpYs.js} +8 -8
  97. package/dist/{ganttDiagram-PKOTCBZU-9D-LXF6P.js → ganttDiagram-EL5Y4UJY-DbzEBLbl.js} +15 -15
  98. package/dist/gitGraph-4MIJSDKK-Dy9uQXGh.js +3 -0
  99. package/dist/{gitGraphDiagram-DS77QQ5N-BfpsXTLf.js → gitGraphDiagram-WWUBYQGX-BMf0iKi1.js} +10 -10
  100. package/dist/{glide-data-editor-sPZ8fUFn.js → glide-data-editor-Bcy8iaZa.js} +2785 -2562
  101. package/dist/{glide-utils-NShAPPtn.js → glide-utils-BMnFm0vZ.js} +4 -4
  102. package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
  103. package/dist/{html-to-image-BTYnN4ev.js → html-to-image-mVIbKn_Y.js} +5720 -5452
  104. package/dist/info-A6RAGUB7-DKoayiHY.js +3 -0
  105. package/dist/{infoDiagram-6WML65LV-DqCTXHVy.js → infoDiagram-27XIBGKW-B_ucqo-U.js} +7 -7
  106. package/dist/{ishikawaDiagram-WSZJBQD7-BCUYmZ1v.js → ishikawaDiagram-5VMMS53U-BZFx9b-o.js} +8 -8
  107. package/dist/{journeyDiagram-NVQOT4AX-BXB6M4zN.js → journeyDiagram-3NMN7TZE-D2LcKDUO.js} +8 -8
  108. package/dist/{jsx-runtime-CpoKNRgu.js → jsx-runtime-DgDPJV9S.js} +1 -1
  109. package/dist/{kanban-definition-27J2QSJJ-CGRhrDUX.js → kanban-definition-UXKFOSKX-BpIfcu3G.js} +29 -29
  110. package/dist/katex-DFBiSucW.js +21840 -0
  111. package/dist/{label-lwzzBHUW.js → label-e37ixur5.js} +6 -6
  112. package/dist/{linear-D5r_1YqD.js → linear-Cnaq3Tfb.js} +4 -4
  113. package/dist/{loader-VZ__bv4g.js → loader-D2W4oM-3.js} +15 -15
  114. package/dist/main.js +7018 -12382
  115. package/dist/mermaid-B1Jb9HfY.js +3084 -0
  116. package/dist/mermaid-HWGCJPDP-DYCzSILp.js +2 -0
  117. package/dist/mermaid-parser.core-DxuSfYwJ.js +638 -0
  118. package/dist/{mhchem-BjwrxcV-.js → mhchem-DWCF06w9.js} +1 -1
  119. package/dist/{micromark-factory-space-DruVGzeG.js → micromark-factory-space-DGxAzmw8.js} +2 -2
  120. package/dist/{mindmap-definition-FAOFIHXS-C9gRhzZq.js → mindmap-definition-YA3MSWOX-CmpAfv8K.js} +17 -17
  121. package/dist/{node-sql-parser-DesT1xNw.js → node-sql-parser-BiZOJ-FS.js} +0 -3
  122. package/dist/{number-overlay-editor-De2CabLL.js → number-overlay-editor-CFofZaOi.js} +5 -5
  123. package/dist/packet-AYTQ26CC-Yw7ajchJ.js +3 -0
  124. package/dist/{pegDiagram-VL7TDLO6-Df9IUjMD.js → pegDiagram-XKGWAZYB-DO-0Q8SE.js} +19 -20
  125. package/dist/{pick-SnHlmIBN.js → pick-B7vX8zxG.js} +1 -1
  126. package/dist/pie-WAS4IAKB-BKdKOAkL.js +3 -0
  127. package/dist/{pieDiagram-7S7Q4E2Y-BmRzQ8ZP.js → pieDiagram-E7YTZNPT-B1MbuA_g.js} +29 -31
  128. package/dist/{process-output-CsALk6tp.js → process-output-Cr6U5ULK.js} +4 -4
  129. package/dist/purify.es-DgKyQviY.js +805 -0
  130. package/dist/{quadrantDiagram-CIZ2JOQS-wFBvWcxS.js → quadrantDiagram-AXDQQJYC-DftINo6g.js} +5 -5
  131. package/dist/radar-RG4KPBEZ-ScR_D_Ts.js +3 -0
  132. package/dist/railroad-74A4TZTK-DQvPSdo5.js +3 -0
  133. package/dist/railroad-abnf-HS5TGJTU-CsJQG2O8.js +3 -0
  134. package/dist/railroad-ebnf-LZEXJU2U-BgEobkSn.js +3 -0
  135. package/dist/railroad-peg-WCYAUIDC-DjLAjofI.js +3 -0
  136. package/dist/{railroadDiagram-AXF67PYL-DxbIatiN.js → railroadDiagram-O6MQD6OU-DPVOQUXC.js} +17 -18
  137. package/dist/{react-dom-C94wmq5w.js → react-dom-BUgJ-ab_.js} +3 -3
  138. package/dist/{react-DMWcHin-.js → react-ofJbxM4x.js} +2 -2
  139. package/dist/{react-vega-DSD5aT7_.js → react-vega-5AcMW8gG.js} +10012 -9369
  140. package/dist/{requirementDiagram-LRYGKXZP-X_x-Y713.js → requirementDiagram-BXWQKSXE-CC7wZ-tM.js} +20 -19
  141. package/dist/{reveal-component-DVMzBxwv.js → reveal-component-DAv6PYTL.js} +1171 -1105
  142. package/dist/{sankeyDiagram-W5VNT64P-BYJALbbm.js → sankeyDiagram-P5KCCOFB-CDKR5TJH.js} +4 -4
  143. package/dist/schemas-BDZr-nP0.js +5727 -0
  144. package/dist/{select-3qHpFKF9.js → select-UMOSCa3W.js} +246 -246
  145. package/dist/{sequenceDiagram-SI44F4Z6-BiPBe3Sv.js → sequenceDiagram-WJ2MYXX4-DomSyoJI.js} +11 -11
  146. package/dist/{sizeCapture-X5ZJPWSS-BKLDeh5H.js → sizeCapture-INFHLROL-Dx5SpkQF.js} +2 -2
  147. package/dist/{spec-CutWdqo3.js → spec-g740fOWu.js} +4 -4
  148. package/dist/{src-C31ngt98.js → src-CA_m4ONl.js} +298 -303
  149. package/dist/{stateDiagram-OKZ733FA-B7QyNBxH.js → stateDiagram-D77RDMKH-SQLLjdtF.js} +19 -20
  150. package/dist/stateDiagram-v2-MP3YSRHH-Dup4KkIr.js +30 -0
  151. package/dist/style.css +2 -2
  152. package/dist/{swimlanes-SLNWSIFB-B4f8VP3b.js → swimlanes-42K2YHIH-ZXbhyGv6.js} +1501 -1591
  153. package/dist/swimlanesDiagram-VR7AAH4N-CluwxV0g.js +30 -0
  154. package/dist/{swiper-component-C90YjhaV.js → swiper-component-IOUowglM.js} +39 -26
  155. package/dist/{time-aWGfjN8x.js → time-BieKwdYS.js} +42 -42
  156. package/dist/{timeline-definition-Z64GVDOM-Dacq_5lr.js → timeline-definition-24CTP7MA-B8i6B9RR.js} +7 -7
  157. package/dist/{toDate-D-Rx3ux5.js → toDate-C3JOXlJT.js} +10 -9
  158. package/dist/{tooltip-Dt77sBeT.js → tooltip-CdE8k0pS.js} +42 -42
  159. package/dist/treeView-Q6P3EWNA-DuRV97YF.js +3 -0
  160. package/dist/treemap-WGGIJYW6-AsLq-uwC.js +3 -0
  161. package/dist/{use-vega-container-remeasure-DUW4tRxq.js → use-vega-container-remeasure-4DwJbPWu.js} +2 -2
  162. package/dist/{useAsyncData-CH6-CgJF.js → useAsyncData-C0f7qnnN.js} +3 -3
  163. package/dist/{useDateFormatter-Cp9Jdxls.js → useDateFormatter-BKpQHt-W.js} +8 -8
  164. package/dist/{useDeepCompareMemoize-JC87C_jO.js → useDeepCompareMemoize-QCa0HbWB.js} +2 -2
  165. package/dist/{useIframeCapabilities-De3C-9b4.js → useIframeCapabilities-CVtNkI3Y.js} +2 -2
  166. package/dist/{useLifecycle-B4RGlyf0.js → useLifecycle-BGRBkTFT.js} +6 -6
  167. package/dist/useTheme-iQ0VoptU.js +904 -0
  168. package/dist/{vega-component-D-IXRnlx.js → vega-component-DRI4BDLQ.js} +15 -15
  169. package/dist/{vega-embed-container-TJ5z5dZw.js → vega-embed-container-CbnTccZi.js} +6 -6
  170. package/dist/vega-loader.browser-D95WfUcj.js +1139 -0
  171. package/dist/{vennDiagram-T6HMQDX7-D-Rcq3Iu.js → vennDiagram-4TSXK5OY-CS7lHhxI.js} +9 -9
  172. package/dist/wardley-WFR3VGLG-Na-tFhQJ.js +3 -0
  173. package/dist/{wardleyDiagram-T6FBY63Y-Z-Og7_Wd.js → wardleyDiagram-VM6X3IG4-BSm-L8JI.js} +10 -10
  174. package/dist/{xychartDiagram-ELKLHX3M-BDJ2dITA.js → xychartDiagram-S5SC5T6Z-8fKCJGrJ.js} +248 -139
  175. package/package.json +52 -52
  176. package/src/__mocks__/requests.ts +7 -2
  177. package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
  178. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +270 -0
  179. package/src/components/chat/acp/agent-panel.tsx +45 -44
  180. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
  181. package/src/components/data-table/column-visibility-dropdown.tsx +9 -3
  182. package/src/components/datasources/components.tsx +4 -2
  183. package/src/components/editor/chrome/components/feedback-button.tsx +10 -9
  184. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +143 -0
  185. package/src/components/editor/chrome/panels/packages-panel.tsx +145 -51
  186. package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
  187. package/src/components/editor/code/readonly-diff.tsx +1 -1
  188. package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
  189. package/src/components/editor/file-tree/tree-actions.tsx +11 -14
  190. package/src/components/editor/notebook-cell.tsx +4 -2
  191. package/src/components/editor/output/Outputs.css +1 -0
  192. package/src/components/editor/package-alert.tsx +25 -1
  193. package/src/components/home/components.tsx +17 -0
  194. package/src/components/pages/gallery-page.tsx +2 -4
  195. package/src/components/pages/home-page.tsx +2 -4
  196. package/src/components/terminal/terminal.tsx +4 -4
  197. package/src/components/tracing/tracing-spec.ts +1 -1
  198. package/src/components/ui/table.tsx +1 -1
  199. package/src/core/cells/__tests__/cell.test.ts +61 -0
  200. package/src/core/cells/cell.ts +9 -1
  201. package/src/core/cells/pending-delete-service.ts +12 -16
  202. package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
  203. package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
  204. package/src/core/codemirror/rtc/extension.ts +5 -2
  205. package/src/core/datasets/__tests__/data-source.test.ts +2 -0
  206. package/src/core/datasets/data-source-connections.ts +15 -10
  207. package/src/core/islands/__tests__/parse.test.ts +140 -7
  208. package/src/core/islands/parse.ts +20 -0
  209. package/src/core/packages/__tests__/useInstallPackage.test.tsx +47 -1
  210. package/src/core/packages/toast-components.tsx +26 -0
  211. package/src/core/packages/useInstallPackage.ts +7 -2
  212. package/src/core/runtime/__tests__/runtime.test.ts +11 -0
  213. package/src/core/runtime/runtime.ts +7 -2
  214. package/src/core/wasm/bridge.ts +1 -0
  215. package/src/core/websocket/transports/transport.ts +1 -1
  216. package/src/core/websocket/transports/ws.ts +1 -1
  217. package/src/css/app/Cell.css +2 -0
  218. package/src/plugins/core/RenderHTML.tsx +22 -2
  219. package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
  220. package/src/plugins/layout/AccordionPlugin.tsx +7 -2
  221. package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
  222. package/dist/_baseMerge-Dv8bBloN.js +0 -73
  223. package/dist/_initCloneObject---vediN2.js +0 -95
  224. package/dist/arc-DOVLrCPd.js +0 -82
  225. package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
  226. package/dist/array-CApNbSU9.js +0 -6
  227. package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
  228. package/dist/assets/worker-DlIBfp9S.js +0 -98
  229. package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
  230. package/dist/chat-ui-DttQ-5Ut.js +0 -8455
  231. package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
  232. package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
  233. package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
  234. package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
  235. package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
  236. package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
  237. package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
  238. package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
  239. package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
  240. package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
  241. package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
  242. package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
  243. package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
  244. package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
  245. package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
  246. package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
  247. package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
  248. package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
  249. package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
  250. package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
  251. package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
  252. package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
  253. package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
  254. package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
  255. package/dist/click-outside-container-D_URcm3D.js +0 -167
  256. package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
  257. package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
  258. package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
  259. package/dist/dist-ABQjhuek.js +0 -64
  260. package/dist/dist-CO5R6VMi.js +0 -538
  261. package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
  262. package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
  263. package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
  264. package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
  265. package/dist/line-CuKjIQa1.js +0 -34
  266. package/dist/map-BJpOfPlL.js +0 -149
  267. package/dist/math-BXtKgYah.js +0 -10
  268. package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
  269. package/dist/mermaid-BsHdQeQf.js +0 -1173
  270. package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
  271. package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
  272. package/dist/path-BNHuHZP8.js +0 -87
  273. package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
  274. package/dist/purify.es-CB-YO1Hn.js +0 -774
  275. package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
  276. package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
  277. package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
  278. package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
  279. package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
  280. package/dist/schemas-DzK6U94N.js +0 -6057
  281. package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
  282. package/dist/step-CKczO72Q.js +0 -670
  283. package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
  284. package/dist/timer-DpDyj9G0.js +0 -596
  285. package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
  286. package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
  287. package/dist/useTheme-CVJ0UOf2.js +0 -841
  288. package/dist/vega-loader.browser-DEggZzni.js +0 -1083
  289. package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
@@ -22,9 +22,13 @@ import { Tooltip } from "@/components/ui/tooltip";
22
22
  import { toast } from "@/components/ui/use-toast";
23
23
  import { useResolvedMarimoConfig } from "@/core/config/config";
24
24
  import { useRequestClient } from "@/core/network/requests";
25
- import type { DependencyTreeNode } from "@/core/network/types";
25
+ import type {
26
+ DependencyTreeNode,
27
+ DependencyTreeResponse,
28
+ } from "@/core/network/types";
26
29
  import { stripPackageManagerPrefix } from "@/core/packages/package-input-utils";
27
30
  import {
31
+ showPackageRestartToast,
28
32
  showRemovePackageToast,
29
33
  showUpgradePackageToast,
30
34
  } from "@/core/packages/toast-components";
@@ -39,6 +43,7 @@ import { PanelEmptyState } from "./empty-state";
39
43
  import { PACKAGES_INPUT_ID, packagesToInstallAtom } from "./packages-utils";
40
44
 
41
45
  type ViewMode = "tree" | "list";
46
+ type PackageInstallationContext = DependencyTreeResponse["context"];
42
47
 
43
48
  const PackageActionButton: React.FC<{
44
49
  onClick: () => void;
@@ -77,12 +82,22 @@ const PackagesPanel: React.FC = () => {
77
82
  refetch,
78
83
  isPending,
79
84
  } = useAsyncData(async () => {
80
- const [listPackagesResponse, dependencyTreeResponse] = await Promise.all([
81
- getPackageList(),
82
- getDependencyTree(),
83
- ]);
85
+ // A sandbox's list and tree both inspect the same environment. Wait for
86
+ // the context before issuing the list request so sandboxes do that work
87
+ // only once; non-sandbox managers still need both views.
88
+ const dependencyTreeResponse = await getDependencyTree();
89
+ if (dependencyTreeResponse.context.kind === "sandbox") {
90
+ return {
91
+ list: [],
92
+ context: dependencyTreeResponse.context,
93
+ tree: dependencyTreeResponse.tree,
94
+ };
95
+ }
96
+
97
+ const listPackagesResponse = await getPackageList();
84
98
  return {
85
99
  list: listPackagesResponse.packages,
100
+ context: dependencyTreeResponse.context,
86
101
  tree: dependencyTreeResponse.tree,
87
102
  };
88
103
  }, [packageManager]);
@@ -97,48 +112,66 @@ const PackagesPanel: React.FC = () => {
97
112
  }
98
113
 
99
114
  const isTreeSupported = dependencies.tree != null;
100
- const viewMode = resolveViewMode(userViewMode, isTreeSupported);
101
115
  const name = dependencies.tree?.name;
102
116
  const version = dependencies?.tree?.version;
103
- const isSandbox = name === "<root>"; // name is the project name otherwise
117
+ const sandboxBackend =
118
+ dependencies.context.kind === "sandbox"
119
+ ? dependencies.context.backend
120
+ : null;
121
+ const isSandbox = sandboxBackend !== null;
122
+ const viewMode = isSandbox
123
+ ? "tree"
124
+ : resolveViewMode(userViewMode, isTreeSupported);
125
+ const scopeLabel = sandboxBackend
126
+ ? `${sandboxBackend} sandbox`
127
+ : name && name !== "<root>"
128
+ ? "project"
129
+ : "environment";
130
+ const scopeTitle = sandboxBackend
131
+ ? `Dependencies are managed by the ${sandboxBackend} sandbox selected when marimo started.`
132
+ : scopeLabel;
104
133
 
105
134
  return (
106
135
  <div className="flex-1 flex flex-col overflow-hidden">
107
- <InstallPackageForm packageManager={packageManager} onSuccess={refetch} />
108
- {isTreeSupported && (
136
+ <InstallPackageForm context={dependencies.context} onSuccess={refetch} />
137
+ {(isTreeSupported || isSandbox) && (
109
138
  <div className="flex items-center justify-between px-2 py-1 border-b">
110
- <div className="flex gap-1">
111
- <button
112
- type="button"
113
- className={cn(
114
- "px-2 py-1 text-xs rounded",
115
- viewMode === "list"
116
- ? "bg-accent text-accent-foreground"
117
- : "text-muted-foreground hover:text-foreground",
118
- )}
119
- onClick={() => setUserViewMode("list")}
120
- >
121
- List
122
- </button>
123
- <button
124
- type="button"
125
- className={cn(
126
- "px-2 py-1 text-xs rounded",
127
- viewMode === "tree"
128
- ? "bg-accent text-accent-foreground"
129
- : "text-muted-foreground hover:text-foreground",
130
- )}
131
- onClick={() => setUserViewMode("tree")}
132
- >
133
- Tree
134
- </button>
135
- </div>
139
+ {isTreeSupported && !isSandbox ? (
140
+ <div className="flex gap-1">
141
+ <button
142
+ type="button"
143
+ className={cn(
144
+ "px-2 py-1 text-xs rounded",
145
+ viewMode === "list"
146
+ ? "bg-accent text-accent-foreground"
147
+ : "text-muted-foreground hover:text-foreground",
148
+ )}
149
+ onClick={() => setUserViewMode("list")}
150
+ >
151
+ List
152
+ </button>
153
+ <button
154
+ type="button"
155
+ className={cn(
156
+ "px-2 py-1 text-xs rounded",
157
+ viewMode === "tree"
158
+ ? "bg-accent text-accent-foreground"
159
+ : "text-muted-foreground hover:text-foreground",
160
+ )}
161
+ onClick={() => setUserViewMode("tree")}
162
+ >
163
+ Tree
164
+ </button>
165
+ </div>
166
+ ) : (
167
+ <div />
168
+ )}
136
169
  <div className="flex items-center gap-2">
137
170
  <div
138
171
  className="items-center border px-2 py-0.5 text-xs transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 text-foreground rounded-sm text-ellipsis block overflow-hidden max-w-fit font-medium"
139
- title={isSandbox ? "sandbox" : "project"}
172
+ title={scopeTitle}
140
173
  >
141
- {isSandbox ? "sandbox" : "project"}
174
+ {scopeLabel}
142
175
  </div>
143
176
  {name && !isSandbox && (
144
177
  <span className="text-xs text-muted-foreground">
@@ -155,6 +188,7 @@ const PackagesPanel: React.FC = () => {
155
188
  <DependencyTree
156
189
  tree={dependencies.tree}
157
190
  error={error}
191
+ sandboxBackend={sandboxBackend}
158
192
  onSuccess={refetch}
159
193
  />
160
194
  )}
@@ -165,11 +199,13 @@ const PackagesPanel: React.FC = () => {
165
199
  export default PackagesPanel;
166
200
 
167
201
  const InstallPackageForm: React.FC<{
168
- packageManager: string;
202
+ context: PackageInstallationContext;
169
203
  onSuccess: () => void;
170
- }> = ({ onSuccess, packageManager }) => {
204
+ }> = ({ onSuccess, context }) => {
171
205
  const [input, setInput] = React.useState("");
172
206
  const { handleClick: openSettings } = useOpenSettingsToTab();
207
+ const isSandbox = context.kind === "sandbox";
208
+ const packageManager = isSandbox ? context.backend : context.name;
173
209
 
174
210
  // Get the packages to install from the atom
175
211
  const packagesToInstall = useAtomValue(packagesToInstallAtom);
@@ -201,7 +237,11 @@ const InstallPackageForm: React.FC<{
201
237
  return (
202
238
  <div className="flex items-center w-full border-b">
203
239
  <SearchInput
204
- placeholder={`Install packages with ${packageManager}...`}
240
+ placeholder={
241
+ isSandbox
242
+ ? `Add packages to ${packageManager} sandbox...`
243
+ : `Install packages with ${packageManager}...`
244
+ }
205
245
  id={PACKAGES_INPUT_ID}
206
246
  icon={
207
247
  loading ? (
@@ -209,12 +249,23 @@ const InstallPackageForm: React.FC<{
209
249
  size="small"
210
250
  className="mr-2 h-4 w-4 shrink-0 opacity-50"
211
251
  />
252
+ ) : isSandbox ? (
253
+ <BoxIcon
254
+ aria-hidden="true"
255
+ className="mr-2 h-4 w-4 shrink-0 opacity-50"
256
+ />
212
257
  ) : (
213
- <Tooltip content="Change package manager">
214
- <BoxIcon
258
+ <Tooltip
259
+ content={`Change package manager (currently ${packageManager})`}
260
+ >
261
+ <button
262
+ type="button"
263
+ aria-label="Change package manager"
215
264
  onClick={() => openSettings("packageManagementAndData")}
216
- className="mr-2 h-4 w-4 shrink-0 opacity-50 hover:opacity-80 cursor-pointer"
217
- />
265
+ className="pointer-events-auto mr-2 rounded-sm opacity-50 hover:opacity-80 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring"
266
+ >
267
+ <BoxIcon aria-hidden="true" className="h-4 w-4 shrink-0" />
268
+ </button>
218
269
  </Tooltip>
219
270
  )
220
271
  }
@@ -234,9 +285,21 @@ const InstallPackageForm: React.FC<{
234
285
  align="start"
235
286
  content={
236
287
  <div className="text-sm flex flex-col w-full max-w-[360px]">
237
- Packages are installed using the package manager specified in your
238
- user configuration. Depending on your package manager, you can
239
- install packages with various formats:
288
+ {isSandbox ? (
289
+ <span>
290
+ Packages are recorded in this notebook&apos;s inline metadata
291
+ and synchronized with its {packageManager} sandbox. To switch
292
+ backends, restart marimo with a different --sandbox option.
293
+ </span>
294
+ ) : (
295
+ <span>
296
+ Packages are installed using {packageManager}, selected in your
297
+ user configuration.
298
+ </span>
299
+ )}
300
+ <span className="mt-2">
301
+ You can install packages with various formats:
302
+ </span>
240
303
  <div className="flex flex-col gap-2 mt-2">
241
304
  <div>
242
305
  <span className="font-bold tracking-wide">Package name:</span> A
@@ -379,7 +442,9 @@ const UpgradeButton: React.FC<{
379
442
  upgrade: true,
380
443
  group,
381
444
  });
382
- if (response.success) {
445
+ if (response.restartRequired) {
446
+ showPackageRestartToast();
447
+ } else if (response.success) {
383
448
  onSuccess();
384
449
  showUpgradePackageToast(packageName);
385
450
  } else {
@@ -413,7 +478,9 @@ const RemoveButton: React.FC<{
413
478
  package: packageName,
414
479
  group,
415
480
  });
416
- if (response.success) {
481
+ if (response.restartRequired) {
482
+ showPackageRestartToast();
483
+ } else if (response.success) {
417
484
  onSuccess();
418
485
  showRemovePackageToast(packageName);
419
486
  } else {
@@ -434,8 +501,9 @@ const RemoveButton: React.FC<{
434
501
  const DependencyTree: React.FC<{
435
502
  tree: DependencyTreeNode | null;
436
503
  error?: Error | null;
504
+ sandboxBackend: "uv" | "pixi" | null;
437
505
  onSuccess: () => void;
438
- }> = ({ tree, error, onSuccess }) => {
506
+ }> = ({ tree, error, sandboxBackend, onSuccess }) => {
439
507
  const [expandedNodes, setExpandedNodes] = React.useState<Set<string>>(
440
508
  new Set(),
441
509
  );
@@ -450,10 +518,25 @@ const DependencyTree: React.FC<{
450
518
  }
451
519
 
452
520
  if (!tree) {
453
- return <Spinner size="medium" centered={true} />;
521
+ return (
522
+ <PanelEmptyState
523
+ title="Dependency tree unavailable"
524
+ description="The sandbox did not return a dependency tree."
525
+ icon={<BoxIcon />}
526
+ />
527
+ );
454
528
  }
455
529
 
456
530
  if (tree.dependencies.length === 0) {
531
+ if (sandboxBackend === "pixi") {
532
+ return (
533
+ <PanelEmptyState
534
+ title="No PyPI dependencies"
535
+ description="Conda dependencies are not shown in this panel."
536
+ icon={<BoxIcon />}
537
+ />
538
+ );
539
+ }
457
540
  return (
458
541
  <PanelEmptyState
459
542
  title="No dependencies"
@@ -575,6 +658,17 @@ const DependencyTreeNode: React.FC<{
575
658
  {/* Tags */}
576
659
  <div className="flex items-center gap-1 ml-2">
577
660
  {node.tags.map((tag, index) => {
661
+ if (tag.kind === "dedupe") {
662
+ return (
663
+ <div
664
+ key={index}
665
+ className="items-center border px-2 py-0.5 text-xs transition-colors focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 text-muted-foreground rounded-sm text-ellipsis block overflow-hidden max-w-fit font-medium"
666
+ title="Package tree already displayed"
667
+ >
668
+ already in tree
669
+ </div>
670
+ );
671
+ }
578
672
  if (tag.kind === "cycle") {
579
673
  return (
580
674
  <div
@@ -0,0 +1,65 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { render, screen } from "@testing-library/react";
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { ReadonlyDiff } from "../readonly-diff";
6
+
7
+ const mocks = vi.hoisted(() => ({
8
+ mergeView: vi.fn(),
9
+ useTheme: vi.fn(),
10
+ }));
11
+
12
+ vi.mock("@codemirror/merge", () => ({
13
+ unifiedMergeView: mocks.mergeView,
14
+ }));
15
+
16
+ vi.mock("@uiw/react-codemirror", () => ({
17
+ default: ({ theme, value }: { theme: string; value: string }) => (
18
+ <div data-testid="code-mirror" data-theme={theme} data-value={value} />
19
+ ),
20
+ }));
21
+
22
+ vi.mock("@/theme/useTheme", () => ({
23
+ useTheme: mocks.useTheme,
24
+ }));
25
+
26
+ describe("ReadonlyDiff", () => {
27
+ beforeEach(() => {
28
+ mocks.mergeView.mockReset();
29
+ mocks.mergeView.mockReturnValue([]);
30
+ mocks.useTheme.mockReturnValue({ theme: "light" });
31
+ });
32
+
33
+ it("updates modified code without rebuilding the diff extensions", () => {
34
+ const { rerender } = render(
35
+ <ReadonlyDiff original="before" modified="first revision" />,
36
+ );
37
+
38
+ expect(screen.getByTestId("code-mirror")).toHaveAttribute(
39
+ "data-value",
40
+ "first revision",
41
+ );
42
+ expect(mocks.mergeView).toHaveBeenCalledTimes(1);
43
+
44
+ rerender(<ReadonlyDiff original="before" modified="second revision" />);
45
+
46
+ expect(screen.getByTestId("code-mirror")).toHaveAttribute(
47
+ "data-value",
48
+ "second revision",
49
+ );
50
+ expect(mocks.mergeView).toHaveBeenCalledTimes(1);
51
+ });
52
+
53
+ it("rebuilds diff extensions when the original code changes", () => {
54
+ const { rerender } = render(
55
+ <ReadonlyDiff original="before" modified="after" />,
56
+ );
57
+
58
+ rerender(<ReadonlyDiff original="earlier" modified="after" />);
59
+
60
+ expect(mocks.mergeView).toHaveBeenCalledTimes(2);
61
+ expect(mocks.mergeView).toHaveBeenLastCalledWith(
62
+ expect.objectContaining({ original: "earlier" }),
63
+ );
64
+ });
65
+ });
@@ -21,7 +21,7 @@ export const ReadonlyDiff = memo(
21
21
  },
22
22
  }),
23
23
  ];
24
- }, [props.original, props.modified, theme]);
24
+ }, [props.original]);
25
25
 
26
26
  return (
27
27
  <CodeMirror
@@ -0,0 +1,54 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { act, fireEvent, render, screen } from "@testing-library/react";
4
+ import type React from "react";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { RefreshIconButton } from "../tree-actions";
7
+
8
+ vi.mock("@/components/ui/tooltip", () => ({
9
+ Tooltip: ({ children }: { children: React.ReactNode }) => children,
10
+ }));
11
+
12
+ describe("RefreshIconButton", () => {
13
+ beforeEach(() => {
14
+ vi.useFakeTimers();
15
+ });
16
+
17
+ afterEach(() => {
18
+ vi.useRealTimers();
19
+ });
20
+
21
+ it("spins for at least 500ms after a refresh completes", async () => {
22
+ const onClick = vi.fn().mockResolvedValue(undefined);
23
+ const { container } = render(<RefreshIconButton onClick={onClick} />);
24
+
25
+ fireEvent.click(screen.getByRole("button"));
26
+
27
+ expect(onClick).toHaveBeenCalledOnce();
28
+ expect(container.querySelector("svg")).toHaveClass("animate-[spin_0.5s]");
29
+
30
+ await act(async () => {
31
+ await vi.advanceTimersByTimeAsync(500);
32
+ });
33
+
34
+ expect(container.querySelector("svg")).not.toHaveClass(
35
+ "animate-[spin_0.5s]",
36
+ );
37
+ });
38
+
39
+ it("uses the latest refresh callback after a rerender", async () => {
40
+ const initialOnClick = vi.fn().mockResolvedValue(undefined);
41
+ const updatedOnClick = vi.fn().mockResolvedValue(undefined);
42
+ const { rerender } = render(<RefreshIconButton onClick={initialOnClick} />);
43
+
44
+ rerender(<RefreshIconButton onClick={updatedOnClick} />);
45
+ fireEvent.click(screen.getByRole("button"));
46
+
47
+ expect(initialOnClick).not.toHaveBeenCalled();
48
+ expect(updatedOnClick).toHaveBeenCalledOnce();
49
+
50
+ await act(async () => {
51
+ await vi.advanceTimersByTimeAsync(500);
52
+ });
53
+ });
54
+ });
@@ -7,7 +7,7 @@ import {
7
7
  MoreVerticalIcon,
8
8
  RefreshCwIcon,
9
9
  } from "lucide-react";
10
- import React, { useCallback, useState } from "react";
10
+ import React, { useState } from "react";
11
11
  import { Button, type ButtonProps } from "@/components/ui/button";
12
12
  import { Tooltip } from "@/components/ui/tooltip";
13
13
  import { cn } from "@/utils/cn";
@@ -41,19 +41,16 @@ export const RefreshIconButton: React.FC<{
41
41
  }> = ({ onClick, tooltip = "Refresh", className, iconClassName }) => {
42
42
  const [isSpinning, setIsSpinning] = useState(false);
43
43
 
44
- const handleClick = useCallback(
45
- async (e: React.MouseEvent) => {
46
- setIsSpinning(true);
47
- // Artificially spin for 500ms to show the user that the button is working.
48
- const minDelay = new Promise<void>((r) => setTimeout(r, 500));
49
- try {
50
- await Promise.all([onClick(e), minDelay]);
51
- } finally {
52
- setIsSpinning(false);
53
- }
54
- },
55
- [onClick],
56
- );
44
+ const handleClick = async (e: React.MouseEvent) => {
45
+ setIsSpinning(true);
46
+ // Artificially spin for 500ms to show the user that the button is working.
47
+ const minDelay = new Promise<void>((r) => setTimeout(r, 500));
48
+ try {
49
+ await Promise.all([onClick(e), minDelay]);
50
+ } finally {
51
+ setIsSpinning(false);
52
+ }
53
+ };
57
54
 
58
55
  const button = (
59
56
  <Button
@@ -451,7 +451,8 @@ const EditableCellComponent = ({
451
451
  cellRuntime.staleInputs) &&
452
452
  !cellRuntime.interrupted;
453
453
 
454
- // Callback to get the editor view.
454
+ // This getter is called during render, so useEvent cannot be used here.
455
+ // oxlint-disable-next-line react/preserve-manual-memoization
455
456
  const getEditorView = useCallback(() => editorView.current, [editorView]);
456
457
 
457
458
  // Use the extracted hooks
@@ -1096,7 +1097,8 @@ const SetupCellComponent = ({
1096
1097
  cellRuntime.staleInputs) &&
1097
1098
  !cellRuntime.interrupted;
1098
1099
 
1099
- // Callback to get the editor view.
1100
+ // This getter is called during render, so useEvent cannot be used here.
1101
+ // oxlint-disable-next-line react/preserve-manual-memoization
1100
1102
  const getEditorView = useCallback(() => editorView.current, [editorView]);
1101
1103
 
1102
1104
  const { isCellCodeShown, showHiddenCode } = useCellHiddenLogic({
@@ -72,6 +72,7 @@
72
72
  /* Coarse hack to stop children from overflowing; doesn't seem to affect
73
73
  * margin collapse. */
74
74
  overflow: auto;
75
+ overscroll-behavior: contain;
75
76
  @apply text-xs;
76
77
 
77
78
  .data-key-pair:not(:last-child) {
@@ -10,6 +10,7 @@ import {
10
10
  PackageCheckIcon,
11
11
  PackageXIcon,
12
12
  PlusIcon,
13
+ RotateCwIcon,
13
14
  XIcon,
14
15
  } from "lucide-react";
15
16
  import type React from "react";
@@ -32,6 +33,7 @@ import {
32
33
  import { useResolvedMarimoConfig } from "@/core/config/config";
33
34
  import type { PackageInstallationStatus } from "@/core/kernel/messages";
34
35
  import { useRequestClient } from "@/core/network/requests";
36
+ import { RESTART_REQUIRED_DESCRIPTION } from "@/core/packages/toast-components";
35
37
  import { isWasm } from "@/core/wasm/utils";
36
38
  import { usePackageMetadata } from "@/hooks/usePackageMetadata";
37
39
  import { Banner } from "@/plugins/impl/common/error-banner";
@@ -55,6 +57,12 @@ import {
55
57
  import { ExternalLink } from "../ui/links";
56
58
  import { NativeSelect } from "../ui/native-select";
57
59
  import { Tooltip } from "../ui/tooltip";
60
+ import { useRestartKernel } from "./actions/useRestartKernel";
61
+
62
+ const RestartKernelButton = () => {
63
+ const restartKernel = useRestartKernel();
64
+ return <Button onClick={restartKernel}>Restart Kernel</Button>;
65
+ };
58
66
 
59
67
  function parsePackageSpecifier(spec: string): {
60
68
  name: string;
@@ -251,6 +259,10 @@ export const PackageAlert: React.FC = () => {
251
259
  )}
252
260
  >
253
261
  <p>{description}</p>
262
+ {status !== "installing" &&
263
+ Object.values(packageAlert.packages).includes(
264
+ "restart-required",
265
+ ) && <RestartKernelButton />}
254
266
  <ul className="list-disc ml-2 mt-1">
255
267
  {Object.entries(packageAlert.packages).map(([pkg, st], index) => (
256
268
  <li
@@ -290,7 +302,9 @@ function getInstallationStatusElements(packages: PackageInstallationStatus) {
290
302
  ? "installing"
291
303
  : statuses.has("failed")
292
304
  ? "failed"
293
- : "installed";
305
+ : statuses.has("restart-required")
306
+ ? "restart-required"
307
+ : "installed";
294
308
 
295
309
  if (status === "installing") {
296
310
  return {
@@ -300,6 +314,14 @@ function getInstallationStatusElements(packages: PackageInstallationStatus) {
300
314
  description: "Installing packages:",
301
315
  };
302
316
  }
317
+ if (status === "restart-required") {
318
+ return {
319
+ status,
320
+ title: "Changes saved — restart required",
321
+ titleIcon: <RotateCwIcon className="w-5 h-5 inline-block mr-2" />,
322
+ description: RESTART_REQUIRED_DESCRIPTION,
323
+ };
324
+ }
303
325
  if (status === "installed") {
304
326
  return {
305
327
  status: "installed",
@@ -330,6 +352,8 @@ const ProgressIcon = ({
330
352
  return <CheckIcon size="1rem" />;
331
353
  case "failed":
332
354
  return <XIcon size="1rem" />;
355
+ case "restart-required":
356
+ return <RotateCwIcon size="1rem" />;
333
357
  default:
334
358
  logNever(status);
335
359
  return null;
@@ -31,6 +31,7 @@ import {
31
31
  import { Constants } from "@/core/constants";
32
32
  import { useRequestClient } from "@/core/network/requests";
33
33
  import type { TutorialId } from "@/core/network/types";
34
+ import { Banner } from "@/plugins/impl/common/error-banner";
34
35
  import { openNotebook } from "@/utils/links";
35
36
  import { Objects } from "@/utils/objects";
36
37
  import { MarimoPlusIcon } from "../icons/marimo-icons";
@@ -186,6 +187,22 @@ export const ResourceLinks: React.FC = () => {
186
187
  );
187
188
  };
188
189
 
190
+ /**
191
+ * Shown when the workspace scan stopped early, so the file list the user is
192
+ * looking at is missing files and folders.
193
+ */
194
+ export const TruncatedWorkspaceBanner: React.FC<{
195
+ fileCount: number | undefined;
196
+ }> = ({ fileCount }) => {
197
+ return (
198
+ <Banner kind="warn" className="rounded p-4">
199
+ Showing {fileCount} files. Some files and folders were skipped because
200
+ your workspace is large or deeply nested. Start marimo from a subfolder to
201
+ see them.
202
+ </Banner>
203
+ );
204
+ };
205
+
189
206
  export const Header: React.FC<{
190
207
  Icon: React.FC<React.SVGProps<SVGSVGElement>>;
191
208
  control?: React.ReactNode;
@@ -4,6 +4,7 @@ import { SearchIcon } from "lucide-react";
4
4
  import type React from "react";
5
5
  import { Suspense, useMemo, useState } from "react";
6
6
  import { ErrorBoundary } from "@/components/editor/boundary/ErrorBoundary";
7
+ import { TruncatedWorkspaceBanner } from "@/components/home/components";
7
8
  import { Spinner } from "@/components/icons/spinner";
8
9
  import { Card, CardContent } from "@/components/ui/card";
9
10
  import { Input } from "@/components/ui/input";
@@ -119,10 +120,7 @@ const GalleryPage: React.FC = () => {
119
120
  <ErrorBoundary>
120
121
  <div className="flex flex-col gap-2">
121
122
  {workspace.hasMore && (
122
- <Banner kind="warn" className="rounded p-4">
123
- Showing first {workspace.fileCount} files. Your workspace has
124
- more files.
125
- </Banner>
123
+ <TruncatedWorkspaceBanner fileCount={workspace.fileCount} />
126
124
  )}
127
125
  {formattedFiles.length > SEARCH_THRESHOLD && (
128
126
  <Input
@@ -67,6 +67,7 @@ import {
67
67
  Header,
68
68
  OpenTutorialDropDown,
69
69
  ResourceLinks,
70
+ TruncatedWorkspaceBanner,
70
71
  } from "../home/components";
71
72
  import {
72
73
  expandedFoldersAtom,
@@ -196,10 +197,7 @@ const WorkspaceNotebooks: React.FC<{ onRefreshRecents: () => void }> = ({
196
197
  <WorkspaceContext value={workspaceContextValue}>
197
198
  <div className="flex flex-col gap-2">
198
199
  {workspace.hasMore && (
199
- <Banner kind="warn" className="rounded p-4">
200
- Showing first {workspace.fileCount} files. Your workspace has more
201
- files.
202
- </Banner>
200
+ <TruncatedWorkspaceBanner fileCount={workspace.fileCount} />
203
201
  )}
204
202
  <Header
205
203
  Icon={BookTextIcon}