@marimo-team/islands 0.24.3-dev9 → 0.25.0

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 (440) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C9OF_75w.js → ConnectedDataExplorerComponent-KVhjDMSe.js} +1066 -1066
  2. package/dist/ErrorBoundary-DnNkbB_U.js +200 -0
  3. package/dist/{ImageComparisonComponent-2a9TMMm2.js → ImageComparisonComponent-Dlm5aWnH.js} +4 -4
  4. package/dist/{Plot-C-9MQeGP.js → Plot-CTyjbQDT.js} +21032 -20666
  5. package/dist/_baseMerge-BiGRwuqv.js +165 -0
  6. package/dist/{abnfDiagram-N423BO3Z-CQKwzX8t.js → abnfDiagram-VCTEODGH-CpN0FRda.js} +17 -18
  7. package/dist/{any-language-editor-DmQ7dyCx.js → any-language-editor-CycIVIeP.js} +17 -17
  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-DDyj5SRB.js} +25 -25
  11. package/dist/assets/__vite-browser-external-C9iR87Zl.js +1 -0
  12. package/dist/assets/worker-D7hWi02M.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/{html-to-image-BtFMe_Nq.js → cells-DYIkSxs6.js} +6757 -10137
  18. package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
  19. package/dist/chat-ui-BXj3uYjy.js +5786 -0
  20. package/dist/{check-CHig47QV.js → check-B7cIK6gb.js} +1 -1
  21. package/dist/{chunk-2Q5K7J3B-BMuJl2jB.js → chunk-2Q5K7J3B-BMkUkeuy.js} +2 -2
  22. package/dist/chunk-4HAMMTFA-D2qv8E0X.js +4188 -0
  23. package/dist/{chunk-5VM5RSS4-Bcq0ftdy.js → chunk-5VM5RSS4-DKsmPCL6.js} +2 -2
  24. package/dist/{chunk-NSK5VX7P-CDTMcJB0.js → chunk-75Z2AOVW-5_HsvXwr.js} +23 -23
  25. package/dist/{chunk-I66GZJ75-BqyTCAPf.js → chunk-DU6HZSFF-BUgAHvnM.js} +21 -4
  26. package/dist/{chunk-2GRJ4B5K-DgO8Qudq.js → chunk-F27PBJKO-DHmYWZXr.js} +4 -4
  27. package/dist/{chunk-KEIR6QF5-C4KX3XYh.js → chunk-FOHPRMQF-BpYR8RqP.js} +4 -4
  28. package/dist/{chunk-WRU74C26-BpWsbiDK.js → chunk-GMAD6QVW-Czynz8aA.js} +486 -258
  29. package/dist/chunk-GVQU2GXP-yQEdulRS.js +37 -0
  30. package/dist/{chunk-5RXB4S5H-tLNUVDdO.js → chunk-IMKFNOWR-BfwTebD0.js} +11 -11
  31. package/dist/{chunk-JWPE2WC7-BJwjGUnF.js → chunk-JWPE2WC7-DJvv1t8U.js} +2 -2
  32. package/dist/chunk-L3NEJ4N5-DwRWnDDK.js +245 -0
  33. package/dist/{chunk-7Z6QIM7H-Dc18hFxH.js → chunk-OSK3NFVY-BBKU_Ign.js} +222 -144
  34. package/dist/{chunk-W5SLKNZC-DLnvpEtV.js → chunk-P2QGCYS3-C0iGU29N.js} +20 -20
  35. package/dist/{chunk-KBJHAD2P-BuqWqkcW.js → chunk-POPQ4Y6H-BCbS3Ozc.js} +4 -4
  36. package/dist/{chunk-4I5QYGJK-DpytHuZQ.js → chunk-PWAF6VOD-CTFCL0jI.js} +4 -4
  37. package/dist/{chunk-JQJVKLGR-CgqCwe8E.js → chunk-SHT3W25Y-BspJEJ5H.js} +109 -63
  38. package/dist/{chunk-6Q2QTUOP-DmTcEBMn.js → chunk-SVP7TREG-DX3rFNTe.js} +5 -5
  39. package/dist/{chunk-GF5L2VYU-B0wgCQgS.js → chunk-TICWLB2K-fVF7Uujg.js} +13 -13
  40. package/dist/{chunk-XXDRQBXY-D73H4IN0.js → chunk-XXDRQBXY-Dnl5VBqG.js} +3 -3
  41. package/dist/{chunk-Y2CYZVJY-DoegUj_e.js → chunk-Y2CYZVJY-DKKS1VyV.js} +1 -1
  42. package/dist/{chunk-5FQGJX7Z-B85XCPv6.js → chunk-YOKDWASO-DrWbKnxA.js} +6925 -5460
  43. package/dist/classDiagram-ZZMXUADV-Fe-V14Sc.js +30 -0
  44. package/dist/classDiagram-v2-VYDZK3BY-xTDg7lOs.js +30 -0
  45. package/dist/code-visibility-DElzk_hh.js +138 -0
  46. package/dist/{common-Cv-4hMa0.js → common-B4-ih9IA.js} +8838 -12645
  47. package/dist/{compiler-runtime-CAH9RLw2.js → compiler-runtime-Cj8ZWiNS.js} +2 -2
  48. package/dist/copy-icon-CLdENY__.js +190 -0
  49. package/dist/{cose-bilkent-JH36ORCC-FUWHkXFX.js → cose-bilkent-JH36ORCC-_LyRKVqm.js} +2 -2
  50. package/dist/cubic-OaEBhQPK.js +1404 -0
  51. package/dist/cynefin-OW5HDTMX-obq-i80l.js +3 -0
  52. package/dist/{cynefinDiagram-MW4NZA55-BXSFK93J.js → cynefinDiagram-5FMLGOSQ-CFQrqzSX.js} +10 -10
  53. package/dist/{dagre-CGyalH38.js → dagre-BGSfXNEb.js} +678 -537
  54. package/dist/dagre-GXQ25YYZ-xHNAUTyG.js +425 -0
  55. package/dist/{data-grid-overlay-editor-DZM4BAaI.js → data-grid-overlay-editor-CRH6JQPE.js} +8 -9
  56. package/dist/{data-grid-types-BnZwWG8z.js → data-grid-types-BucVmDDp.js} +1 -1
  57. package/dist/{defaultLocale-DKaU_opG.js → defaultLocale-JI_lnoCe.js} +1 -1
  58. package/dist/{diagram-7IWD3JNH-BjfzDNvj.js → diagram-S7CK7UJ4-Bt1rPbAx.js} +40 -39
  59. package/dist/{diagram-UB23O5K3-DDg-7wLA.js → diagram-UQ7AKVKN-D1sq5FoZ.js} +10 -10
  60. package/dist/{diagram-B4RE2ZJO-CKccR9eE.js → diagram-VSXAHHWV-BKpmG23x.js} +10 -10
  61. package/dist/{diagram-Q27KOJAE-Zhz01ss7.js → diagram-VX7I27RA-BMwGFVD6.js} +21 -21
  62. package/dist/{diagram-LBJQPF4R-CJ-bOruh.js → diagram-Z3DM3KII--KLDR9Pl.js} +10 -10
  63. package/dist/dialog-CgNq6y9-.js +94 -0
  64. package/dist/{dist-dAqZAPcF.js → dist-1HDa70oE.js} +3 -3
  65. package/dist/{dist-Re9sOPOx.js → dist-9x1ZRe-e.js} +2 -2
  66. package/dist/{dist-DEeLqRlU.js → dist-B1vYLK28.js} +1 -1
  67. package/dist/{dist-C5Bn52W4.js → dist-B8D7McG3.js} +3 -3
  68. package/dist/{dist-_XvgytiS.js → dist-BHCHt1NI.js} +1 -1
  69. package/dist/{dist-CRjAdnqF.js → dist-BRxfaJgs.js} +3 -3
  70. package/dist/{dist-Byj2bV8o.js → dist-BVGtK7Ht.js} +1 -1
  71. package/dist/{dist-BIN5LKyE.js → dist-BaHjhkpZ.js} +2 -2
  72. package/dist/{dist-DVFbIwc5.js → dist-BtKIs9N-.js} +1 -1
  73. package/dist/{dist-BrQGcfQ9.js → dist-C2KzV-vf.js} +2 -2
  74. package/dist/{dist-DJFiGP2k.js → dist-C2wDlYdD.js} +2 -2
  75. package/dist/{dist-BVRM2y1P.js → dist-C8xMLVYi.js} +2 -2
  76. package/dist/dist-CMh_W4y4.js +538 -0
  77. package/dist/{extends-BPB6_lTK.js → dist-CO1AwwG_.js} +516 -561
  78. package/dist/{dist-BzN60Z2s.js → dist-CPGxfVGX.js} +1 -1
  79. package/dist/{dist-C7v-9nUK.js → dist-Cm3iAFMD.js} +3 -3
  80. package/dist/{dist-CGAxEiaM.js → dist-Cs2FijYk.js} +2 -2
  81. package/dist/{dist-hXd65f0_.js → dist-D1PpnuZB.js} +1 -1
  82. package/dist/{dist-VdvbxG72.js → dist-DHOTQar0.js} +1 -1
  83. package/dist/{dist-DcgzXCfy.js → dist-DPcEtqmG.js} +2 -2
  84. package/dist/{dist-D4Z_qdP4.js → dist-Df0wKI0F.js} +1 -1
  85. package/dist/{dist-qhLI-SHd.js → dist-DszxuxS1.js} +2 -2
  86. package/dist/{dist-BEmkrGoQ.js → dist-Kxgjxakw.js} +1 -1
  87. package/dist/{dist-BbSMhhD2.js → dist-KzZ7WELx.js} +2 -2
  88. package/dist/{dist-jWUab2d1.js → dist-lA1Cttkb.js} +1 -1
  89. package/dist/dropdown-menu-CZgjYSAh.js +4502 -0
  90. package/dist/{ebnfDiagram-BXEA7PRR-Dm75pCAS.js → ebnfDiagram-PWID7BFC-WnG4cvSQ.js} +17 -18
  91. package/dist/{erDiagram-JOGREHBK-rVDG3VSQ.js → erDiagram-RLTQ6QDP-DhzKiYHc.js} +1037 -798
  92. package/dist/error-banner-B94dcDmP.js +391 -0
  93. package/dist/error-entries-C0NsUqXl.js +56 -0
  94. package/dist/{esm-CR1nhb1c.js → esm-BElI3qKH.js} +22 -22
  95. package/dist/{esm-C1d0g6Bv.js → esm-G4Fhsgng.js} +51 -37
  96. package/dist/{esm-CesmlDrs.js → esm-h8f7-1CJ.js} +423 -423
  97. package/dist/eventmodeling-NTZA5JFV-D7nP7Uyu.js +3 -0
  98. package/dist/feedback-button-cQcMqpEP.js +380 -0
  99. package/dist/flowDiagram-HODETNUW-6dMdB8pR.js +16 -0
  100. package/dist/{formats-CslNOKy0.js → formats-BR5iGb4s.js} +8 -8
  101. package/dist/{ganttDiagram-PKOTCBZU-9D-LXF6P.js → ganttDiagram-EL5Y4UJY-DbzEBLbl.js} +15 -15
  102. package/dist/gitGraph-4MIJSDKK-Dy9uQXGh.js +3 -0
  103. package/dist/{gitGraphDiagram-DS77QQ5N-BfpsXTLf.js → gitGraphDiagram-WWUBYQGX-BMf0iKi1.js} +10 -10
  104. package/dist/{glide-data-editor-sPZ8fUFn.js → glide-data-editor-DYOxfSzI.js} +2143 -1910
  105. package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
  106. package/dist/globals-BOoLHa7X.js +19 -0
  107. package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
  108. package/dist/html-to-image-CeYYvQNb.js +3272 -0
  109. package/dist/info-A6RAGUB7-DKoayiHY.js +3 -0
  110. package/dist/{infoDiagram-6WML65LV-DqCTXHVy.js → infoDiagram-27XIBGKW-BagtCX_5.js} +7 -7
  111. package/dist/{ishikawaDiagram-WSZJBQD7-BCUYmZ1v.js → ishikawaDiagram-5VMMS53U-DByDehYy.js} +8 -8
  112. package/dist/{journeyDiagram-NVQOT4AX-BXB6M4zN.js → journeyDiagram-3NMN7TZE-D2LcKDUO.js} +8 -8
  113. package/dist/{jsx-runtime-CpoKNRgu.js → jsx-runtime-DgDPJV9S.js} +1 -1
  114. package/dist/{kanban-definition-27J2QSJJ-CGRhrDUX.js → kanban-definition-UXKFOSKX-BxwkbBI_.js} +29 -29
  115. package/dist/katex-DFBiSucW.js +21840 -0
  116. package/dist/{label-lwzzBHUW.js → label-BJ49YTvk.js} +6 -6
  117. package/dist/{linear-D5r_1YqD.js → linear-Cnaq3Tfb.js} +4 -4
  118. package/dist/{loader-VZ__bv4g.js → loader-D2W4oM-3.js} +15 -15
  119. package/dist/main.js +8113 -13475
  120. package/dist/mermaid-DPNuhemn.js +3084 -0
  121. package/dist/mermaid-HWGCJPDP-DYCzSILp.js +2 -0
  122. package/dist/mermaid-parser.core-DxuSfYwJ.js +638 -0
  123. package/dist/{mhchem-BjwrxcV-.js → mhchem-DWCF06w9.js} +1 -1
  124. package/dist/{micromark-factory-space-DruVGzeG.js → micromark-factory-space-DGxAzmw8.js} +2 -2
  125. package/dist/{mindmap-definition-FAOFIHXS-C9gRhzZq.js → mindmap-definition-YA3MSWOX-Cgvojw3y.js} +17 -17
  126. package/dist/{node-sql-parser-DesT1xNw.js → node-sql-parser-BiZOJ-FS.js} +0 -3
  127. package/dist/{number-overlay-editor-De2CabLL.js → number-overlay-editor-DZp5bEmI.js} +5 -5
  128. package/dist/objectWithoutPropertiesLoose-BRDcTsfB.js +23 -0
  129. package/dist/packet-AYTQ26CC-Yw7ajchJ.js +3 -0
  130. package/dist/{pegDiagram-VL7TDLO6-Df9IUjMD.js → pegDiagram-XKGWAZYB-DahHhYyN.js} +19 -20
  131. package/dist/{pick-SnHlmIBN.js → pick-CJeoxYOS.js} +1 -1
  132. package/dist/pie-WAS4IAKB-BKdKOAkL.js +3 -0
  133. package/dist/{pieDiagram-7S7Q4E2Y-BmRzQ8ZP.js → pieDiagram-E7YTZNPT-CCtX0oCK.js} +29 -31
  134. package/dist/{process-output-CPy0YKUe.js → process-output-BCTjlyuH.js} +7 -6
  135. package/dist/purify.es-DgKyQviY.js +805 -0
  136. package/dist/{quadrantDiagram-CIZ2JOQS-wFBvWcxS.js → quadrantDiagram-AXDQQJYC-DftINo6g.js} +5 -5
  137. package/dist/radar-RG4KPBEZ-ScR_D_Ts.js +3 -0
  138. package/dist/railroad-74A4TZTK-DQvPSdo5.js +3 -0
  139. package/dist/railroad-abnf-HS5TGJTU-CsJQG2O8.js +3 -0
  140. package/dist/railroad-ebnf-LZEXJU2U-BgEobkSn.js +3 -0
  141. package/dist/railroad-peg-WCYAUIDC-DjLAjofI.js +3 -0
  142. package/dist/{railroadDiagram-AXF67PYL-DxbIatiN.js → railroadDiagram-O6MQD6OU-Du5NsPUb.js} +17 -18
  143. package/dist/{react-dom-C94wmq5w.js → react-dom-BUgJ-ab_.js} +3 -3
  144. package/dist/{react-DMWcHin-.js → react-ofJbxM4x.js} +2 -2
  145. package/dist/{react-vega-DSD5aT7_.js → react-vega-5AcMW8gG.js} +10012 -9369
  146. package/dist/{requirementDiagram-LRYGKXZP-X_x-Y713.js → requirementDiagram-BXWQKSXE-0pmmxL6_.js} +20 -19
  147. package/dist/{reveal-component-CVsYlb9J.js → reveal-component-C9h2Lubu.js} +1303 -1237
  148. package/dist/{sankeyDiagram-W5VNT64P-BYJALbbm.js → sankeyDiagram-P5KCCOFB-CDKR5TJH.js} +4 -4
  149. package/dist/{select-3qHpFKF9.js → select-C6plhmZr.js} +317 -562
  150. package/dist/{sequenceDiagram-SI44F4Z6-BiPBe3Sv.js → sequenceDiagram-WJ2MYXX4-DB-ChWwU.js} +11 -11
  151. package/dist/{sizeCapture-X5ZJPWSS-BKLDeh5H.js → sizeCapture-INFHLROL-Dx5SpkQF.js} +2 -2
  152. package/dist/{spec-CutWdqo3.js → spec-CAYwFeV6.js} +4 -4
  153. package/dist/{src-C31ngt98.js → src-CA_m4ONl.js} +298 -303
  154. package/dist/{stateDiagram-OKZ733FA-B7QyNBxH.js → stateDiagram-D77RDMKH-orN6AwMx.js} +19 -20
  155. package/dist/stateDiagram-v2-MP3YSRHH-o05_rJN8.js +30 -0
  156. package/dist/style.css +2 -2
  157. package/dist/{swimlanes-SLNWSIFB-B4f8VP3b.js → swimlanes-42K2YHIH-BkSDcqDT.js} +1501 -1591
  158. package/dist/swimlanesDiagram-VR7AAH4N-D_nFQfRc.js +30 -0
  159. package/dist/{swiper-component-C90YjhaV.js → swiper-component-IOUowglM.js} +39 -26
  160. package/dist/{time-aWGfjN8x.js → time-BieKwdYS.js} +42 -42
  161. package/dist/{timeline-definition-Z64GVDOM-Dacq_5lr.js → timeline-definition-24CTP7MA-BuqJUIRZ.js} +7 -7
  162. package/dist/{toDate-CpXBeDq0.js → toDate-WXg1yLcI.js} +7 -7
  163. package/dist/toast-DvY70eFX.js +1834 -0
  164. package/dist/tooltip-qB8NlSqV.js +1742 -0
  165. package/dist/treeView-Q6P3EWNA-DuRV97YF.js +3 -0
  166. package/dist/treemap-WGGIJYW6-AsLq-uwC.js +3 -0
  167. package/dist/use-restore-focus-D5D9xEjZ.js +5946 -0
  168. package/dist/{use-vega-container-remeasure-DUW4tRxq.js → use-vega-container-remeasure-4DwJbPWu.js} +2 -2
  169. package/dist/{useAsyncData-CH6-CgJF.js → useAsyncData-BD6AStMt.js} +3 -3
  170. package/dist/{useDateFormatter-Cp9Jdxls.js → useDateFormatter-BRTPsUK7.js} +8 -8
  171. package/dist/{useDeepCompareMemoize-JC87C_jO.js → useDeepCompareMemoize-D_HNdyvI.js} +2 -2
  172. package/dist/{useIframeCapabilities-De3C-9b4.js → useIframeCapabilities-CVtNkI3Y.js} +2 -2
  173. package/dist/{useLifecycle-B4RGlyf0.js → useLifecycle-DPgiiwwU.js} +6 -6
  174. package/dist/useNumberFormatter-BfDpa21j.js +251 -0
  175. package/dist/useTheme-DzXmYZ5V.js +904 -0
  176. package/dist/{vega-component-ovBXgp91.js → vega-component-D0QXopU8.js} +34 -34
  177. package/dist/{vega-embed-container-TJ5z5dZw.js → vega-embed-container-CbnTccZi.js} +6 -6
  178. package/dist/vega-loader.browser-D95WfUcj.js +1139 -0
  179. package/dist/{vennDiagram-T6HMQDX7-D-Rcq3Iu.js → vennDiagram-4TSXK5OY-CTUlJ2PK.js} +9 -9
  180. package/dist/wardley-WFR3VGLG-Na-tFhQJ.js +3 -0
  181. package/dist/{wardleyDiagram-T6FBY63Y-Z-Og7_Wd.js → wardleyDiagram-VM6X3IG4-3evLUb0M.js} +10 -10
  182. package/dist/{xychartDiagram-ELKLHX3M-BDJ2dITA.js → xychartDiagram-S5SC5T6Z-DL2E3K8-.js} +248 -139
  183. package/package.json +54 -57
  184. package/src/__mocks__/notebook.ts +1 -0
  185. package/src/__mocks__/requests.ts +7 -0
  186. package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
  187. package/src/__tests__/fixtures/pair-preview.ts +19 -0
  188. package/src/__tests__/mount.test.ts +18 -0
  189. package/src/components/app-config/optional-features.tsx +6 -0
  190. package/src/components/chat/acp/__tests__/agent-panel-initialization.test.tsx +394 -0
  191. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +272 -0
  192. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  193. package/src/components/chat/acp/agent-panel.tsx +115 -74
  194. package/src/components/chat/acp/state.ts +1 -1
  195. package/src/components/data-table/__tests__/filters.test.ts +21 -21
  196. package/src/components/data-table/charts/__tests__/spec.test.ts +5 -10
  197. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
  198. package/src/components/data-table/column-summary/chart-spec-model.tsx +1 -1
  199. package/src/components/data-table/columns.tsx +64 -67
  200. package/src/components/editor/RecoveryButton.tsx +1 -0
  201. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
  202. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +115 -0
  203. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +218 -0
  204. package/src/components/editor/actions/pair-with-agent-commands.ts +46 -9
  205. package/src/components/editor/actions/pair-with-agent-modal.tsx +49 -23
  206. package/src/components/editor/ai/add-cell-with-ai.tsx +1 -0
  207. package/src/components/editor/ai/ai-completion-editor.tsx +3 -1
  208. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +186 -0
  209. package/src/components/editor/alerts/__tests__/startup-progress.test.tsx +185 -0
  210. package/src/components/editor/alerts/connecting-alert.tsx +1 -66
  211. package/src/components/editor/alerts/connection-notice.tsx +186 -0
  212. package/src/components/editor/alerts/startup-output.tsx +173 -0
  213. package/src/components/editor/alerts/startup-progress.tsx +204 -0
  214. package/src/components/editor/app-container.tsx +9 -3
  215. package/src/components/editor/boundary/ErrorBoundary.tsx +38 -16
  216. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +311 -0
  217. package/src/components/editor/cell/__tests__/toolbar.test.tsx +73 -0
  218. package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +50 -0
  219. package/src/components/editor/cell/code/cell-editor.tsx +41 -42
  220. package/src/components/editor/cell/toolbar.tsx +11 -0
  221. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +94 -0
  222. package/src/components/editor/chrome/components/feedback-button.tsx +63 -42
  223. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +164 -8
  224. package/src/components/editor/chrome/panels/__tests__/sandbox-details.test.tsx +358 -0
  225. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +168 -0
  226. package/src/components/editor/chrome/panels/packages-panel.tsx +113 -175
  227. package/src/components/editor/chrome/panels/sandbox-controller.tsx +106 -0
  228. package/src/components/editor/chrome/panels/sandbox-details-state.ts +38 -0
  229. package/src/components/editor/chrome/panels/sandbox-panel.tsx +230 -0
  230. package/src/components/editor/chrome/panels/sandbox-toggle.tsx +52 -0
  231. package/src/components/editor/chrome/wrapper/app-chrome.tsx +7 -0
  232. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +3 -1
  233. package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
  234. package/src/components/editor/code/readonly-diff.tsx +1 -1
  235. package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +98 -98
  236. package/src/components/editor/connections/database/__tests__/as-code.test.ts +11 -5
  237. package/src/components/editor/dynamic-favicon.tsx +17 -10
  238. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +13 -11
  239. package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
  240. package/src/components/editor/file-tree/tree-actions.tsx +11 -14
  241. package/src/components/editor/header/__tests__/status.test.tsx +8 -20
  242. package/src/components/editor/header/filename-input.tsx +2 -0
  243. package/src/components/editor/header/status.tsx +5 -3
  244. package/src/components/editor/navigation/clipboard.ts +1 -0
  245. package/src/components/editor/notebook-cell.tsx +4 -2
  246. package/src/components/editor/output/JsonOutput.tsx +182 -632
  247. package/src/components/editor/output/Outputs.css +49 -17
  248. package/src/components/editor/output/__tests__/JsonOutput-interactions.test.tsx +254 -0
  249. package/src/components/editor/output/__tests__/JsonOutput-mimetype.test.tsx +41 -46
  250. package/src/components/editor/output/__tests__/{json-output.test.ts → json-output-formatting.test.ts} +113 -75
  251. package/src/components/editor/output/__tests__/json-output-pagination.test.ts +252 -0
  252. package/src/components/editor/output/json-output/formatting.ts +167 -0
  253. package/src/components/editor/output/json-output/pagination.ts +155 -0
  254. package/src/components/editor/output/json-output/renderers.tsx +196 -0
  255. package/src/components/editor/output/json-output/themes.ts +52 -0
  256. package/src/components/editor/package-alert.tsx +112 -66
  257. package/src/components/editor/renderers/cell-array.tsx +1 -5
  258. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +3 -7
  259. package/src/components/slides/slide-form.tsx +1 -0
  260. package/src/components/slides/slide-notes-editor.tsx +1 -0
  261. package/src/components/tracing/tracing-spec.ts +1 -1
  262. package/src/components/ui/__tests__/badge.test.ts +6 -4
  263. package/src/components/ui/use-toast.ts +8 -0
  264. package/src/core/MarimoApp.tsx +0 -2
  265. package/src/core/ai/context/providers/__tests__/error.test.ts +16 -22
  266. package/src/core/alerts/__tests__/environment.test.ts +183 -0
  267. package/src/core/alerts/__tests__/state.test.tsx +240 -0
  268. package/src/core/alerts/environment.ts +57 -0
  269. package/src/core/alerts/state.ts +155 -99
  270. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +296 -259
  271. package/src/core/cells/__tests__/apply-transaction.test.ts +34 -0
  272. package/src/core/cells/__tests__/cell.test.ts +61 -0
  273. package/src/core/cells/__tests__/cells.test.ts +182 -37
  274. package/src/core/cells/__tests__/document-changes.test.ts +39 -1
  275. package/src/core/cells/__tests__/outputs.test.tsx +117 -0
  276. package/src/core/cells/__tests__/pending-delete-service.test.tsx +4 -3
  277. package/src/core/cells/__tests__/session.test.ts +7 -0
  278. package/src/core/cells/cell.ts +9 -1
  279. package/src/core/cells/cells.ts +13 -18
  280. package/src/core/cells/document-changes.ts +11 -1
  281. package/src/core/cells/outputs.ts +66 -9
  282. package/src/core/cells/pending-delete-service.ts +12 -16
  283. package/src/core/cells/session.ts +2 -0
  284. package/src/core/cells/types.ts +2 -0
  285. package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +8 -16
  286. package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
  287. package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +4 -8
  288. package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
  289. package/src/core/codemirror/rtc/extension.ts +5 -2
  290. package/src/core/config/pair.ts +19 -0
  291. package/src/core/datasets/__tests__/data-source.test.ts +2 -0
  292. package/src/core/datasets/data-source-connections.ts +15 -10
  293. package/src/core/edit-app.tsx +8 -5
  294. package/src/core/errors/state.ts +1 -2
  295. package/src/core/export/__tests__/hooks.test.ts +1 -6
  296. package/src/core/islands/bootstrap.ts +3 -1
  297. package/src/core/islands/bridge.ts +3 -0
  298. package/src/core/islands/worker-factory.ts +2 -12
  299. package/src/core/kernel/messages.ts +2 -2
  300. package/src/core/network/__tests__/requests-network.test.ts +4 -3
  301. package/src/core/network/connection-notice.ts +117 -0
  302. package/src/core/network/connection.ts +19 -0
  303. package/src/core/network/requests-lazy.ts +3 -0
  304. package/src/core/network/requests-network.ts +12 -0
  305. package/src/core/network/requests-static.ts +3 -0
  306. package/src/core/network/requests-toasting.tsx +3 -0
  307. package/src/core/network/resolve.ts +2 -1
  308. package/src/core/network/types.ts +7 -0
  309. package/src/core/network/useConnectionNotice.ts +53 -0
  310. package/src/core/packages/__tests__/usePackageAction.test.tsx +129 -0
  311. package/src/core/packages/__tests__/useSandboxController.test.tsx +246 -0
  312. package/src/core/packages/package-data.ts +35 -0
  313. package/src/core/packages/sandbox-state.ts +67 -0
  314. package/src/core/packages/toast-components.tsx +11 -0
  315. package/src/core/packages/useInstallPackage.ts +1 -1
  316. package/src/core/packages/usePackageAction.ts +51 -0
  317. package/src/core/packages/usePackageDependencies.ts +22 -0
  318. package/src/core/packages/useSandboxController.ts +208 -0
  319. package/src/core/run-app.tsx +2 -0
  320. package/src/core/static/__tests__/files.test.ts +12 -30
  321. package/src/core/wasm/__tests__/bootstrap.test.ts +63 -0
  322. package/src/core/wasm/__tests__/bridge.test.ts +13 -4
  323. package/src/core/wasm/__tests__/fs.test.ts +22 -0
  324. package/src/core/wasm/__tests__/runtime-config.test.ts +65 -0
  325. package/src/core/wasm/bridge.ts +35 -23
  326. package/src/core/wasm/rpc.ts +2 -0
  327. package/src/core/wasm/runtime-config.ts +31 -0
  328. package/src/core/wasm/worker/bootstrap.ts +21 -11
  329. package/src/core/wasm/worker/constants.ts +1 -0
  330. package/src/core/wasm/worker/fs.ts +4 -0
  331. package/src/core/wasm/worker/getController.ts +3 -1
  332. package/src/core/wasm/worker/save-worker.ts +10 -9
  333. package/src/core/wasm/worker/types.ts +6 -4
  334. package/src/core/wasm/worker/worker.ts +9 -9
  335. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +404 -3
  336. package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +8 -6
  337. package/src/core/websocket/transports/transport.ts +1 -1
  338. package/src/core/websocket/transports/ws.ts +1 -1
  339. package/src/core/websocket/types.ts +11 -1
  340. package/src/core/websocket/useMarimoKernelConnection.tsx +63 -16
  341. package/src/hooks/useDebounce.ts +2 -0
  342. package/src/mount.tsx +3 -0
  343. package/src/plugins/core/BadPlugin.tsx +3 -14
  344. package/src/plugins/core/RenderHTML.tsx +22 -2
  345. package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
  346. package/src/plugins/core/registerReactComponent.tsx +0 -1
  347. package/src/plugins/impl/FileBrowserPlugin.tsx +10 -4
  348. package/src/plugins/impl/FormPlugin.tsx +2 -0
  349. package/src/plugins/impl/MatrixPlugin.tsx +2 -0
  350. package/src/plugins/impl/RangeSliderPlugin.tsx +2 -0
  351. package/src/plugins/impl/SliderPlugin.tsx +2 -0
  352. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +50 -1
  353. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +23 -18
  354. package/src/plugins/impl/data-frames/panel.tsx +1 -0
  355. package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +1 -1
  356. package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +15 -0
  357. package/src/plugins/impl/vega/__tests__/make-selectable.test.ts +42 -48
  358. package/src/plugins/layout/AccordionPlugin.tsx +7 -2
  359. package/src/plugins/layout/JsonOutputPlugin.tsx +7 -10
  360. package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
  361. package/src/stories/sandbox.stories.tsx +488 -0
  362. package/src/utils/__tests__/path.test.ts +6 -5
  363. package/src/utils/__tests__/worker.test.ts +81 -0
  364. package/src/utils/worker.ts +22 -0
  365. package/dist/ErrorBoundary-CR-ZQN_c.js +0 -125
  366. package/dist/_baseMerge-Dv8bBloN.js +0 -73
  367. package/dist/_initCloneObject---vediN2.js +0 -95
  368. package/dist/arc-DOVLrCPd.js +0 -82
  369. package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
  370. package/dist/array-CApNbSU9.js +0 -6
  371. package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
  372. package/dist/assets/worker-DlIBfp9S.js +0 -98
  373. package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
  374. package/dist/chat-ui-BSwr409J.js +0 -8455
  375. package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
  376. package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
  377. package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
  378. package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
  379. package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
  380. package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
  381. package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
  382. package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
  383. package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
  384. package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
  385. package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
  386. package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
  387. package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
  388. package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
  389. package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
  390. package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
  391. package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
  392. package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
  393. package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
  394. package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
  395. package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
  396. package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
  397. package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
  398. package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
  399. package/dist/click-outside-container-D_URcm3D.js +0 -167
  400. package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
  401. package/dist/copy-CD7S58CY.js +0 -141
  402. package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
  403. package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
  404. package/dist/dist-3_o3T78I.js +0 -1360
  405. package/dist/dist-ABQjhuek.js +0 -64
  406. package/dist/dist-CO5R6VMi.js +0 -538
  407. package/dist/dropdown-menu-DhCfcscX.js +0 -5858
  408. package/dist/emotion-is-prop-valid.esm-M57VsT8j.js +0 -14
  409. package/dist/error-banner-CsXbEEjo.js +0 -611
  410. package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
  411. package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
  412. package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
  413. package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
  414. package/dist/line-CuKjIQa1.js +0 -34
  415. package/dist/map-BJpOfPlL.js +0 -149
  416. package/dist/math-BXtKgYah.js +0 -10
  417. package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
  418. package/dist/mermaid-Bi23Ibnw.js +0 -1173
  419. package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
  420. package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
  421. package/dist/path-BNHuHZP8.js +0 -87
  422. package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
  423. package/dist/purify.es-CB-YO1Hn.js +0 -774
  424. package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
  425. package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
  426. package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
  427. package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
  428. package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
  429. package/dist/schemas-DzK6U94N.js +0 -6057
  430. package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
  431. package/dist/step-CKczO72Q.js +0 -670
  432. package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
  433. package/dist/timer-DpDyj9G0.js +0 -596
  434. package/dist/tooltip-Dt77sBeT.js +0 -390
  435. package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
  436. package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
  437. package/dist/useTheme-CVJ0UOf2.js +0 -841
  438. package/dist/vega-loader.browser-DEggZzni.js +0 -1083
  439. package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
  440. package/src/components/editor/output/EmotionCacheProvider.tsx +0 -32
@@ -7,6 +7,7 @@ import {
7
7
  HelpCircleIcon,
8
8
  } from "lucide-react";
9
9
  import React from "react";
10
+ import { useConnectionNotice } from "@/core/network/useConnectionNotice";
10
11
  import { useOpenSettingsToTab } from "@/components/app-config/state";
11
12
  import { Spinner } from "@/components/icons/spinner";
12
13
  import { SearchInput } from "@/components/ui/input";
@@ -20,25 +21,22 @@ import {
20
21
  } from "@/components/ui/table";
21
22
  import { Tooltip } from "@/components/ui/tooltip";
22
23
  import { toast } from "@/components/ui/use-toast";
23
- import { useResolvedMarimoConfig } from "@/core/config/config";
24
- import { useRequestClient } from "@/core/network/requests";
24
+ import { isConnectedAtom } from "@/core/network/connection";
25
25
  import type {
26
26
  DependencyTreeNode,
27
27
  DependencyTreeResponse,
28
28
  } from "@/core/network/types";
29
+ import { sandboxAtom, sandboxSyncAtom } from "@/core/packages/sandbox-state";
29
30
  import { stripPackageManagerPrefix } from "@/core/packages/package-input-utils";
30
- import {
31
- showPackageRestartToast,
32
- showRemovePackageToast,
33
- showUpgradePackageToast,
34
- } from "@/core/packages/toast-components";
31
+ import { usePackageAction } from "@/core/packages/usePackageAction";
32
+ import { usePackageDependencies } from "@/core/packages/usePackageDependencies";
35
33
  import { useInstallPackages } from "@/core/packages/useInstallPackage";
36
34
  import { isWasm } from "@/core/wasm/utils";
37
- import { useAsyncData } from "@/hooks/useAsyncData";
38
35
  import { ErrorBanner } from "@/plugins/impl/common/error-banner";
39
36
  import { cn } from "@/utils/cn";
40
37
  import { copyToClipboard } from "@/utils/copy";
41
38
  import { Events } from "@/utils/events";
39
+ import { SandboxDetails } from "./sandbox-panel";
42
40
  import { PanelEmptyState } from "./empty-state";
43
41
  import { PACKAGES_INPUT_ID, packagesToInstallAtom } from "./packages-utils";
44
42
 
@@ -71,40 +69,48 @@ const PackageActionButton: React.FC<{
71
69
  };
72
70
 
73
71
  const PackagesPanel: React.FC = () => {
74
- const [config] = useResolvedMarimoConfig();
75
- const packageManager = config.package_management.manager;
76
- const { getDependencyTree, getPackageList } = useRequestClient();
72
+ const sandbox = useAtomValue(sandboxAtom);
73
+ const connected = useAtomValue(isConnectedAtom);
74
+ const notice = useConnectionNotice(0);
75
+ if (sandbox?.backend) {
76
+ return (
77
+ <div className="flex flex-col flex-1 min-h-0 overflow-hidden">
78
+ <SandboxDetails />
79
+ {connected && <PackageContents />}
80
+ </div>
81
+ );
82
+ }
83
+ if (notice) {
84
+ return (
85
+ <div className="p-4 text-sm text-muted-foreground">
86
+ <div className="flex items-center gap-2">
87
+ {notice.pending && <Spinner className="size-3" />}
88
+ {notice.title}
89
+ </div>
90
+ {notice.error && (
91
+ <pre className="mt-3 text-xs whitespace-pre-wrap break-words max-h-52 overflow-auto">
92
+ {notice.error}
93
+ </pre>
94
+ )}
95
+ </div>
96
+ );
97
+ }
98
+ return <PackageContents />;
99
+ };
77
100
 
101
+ const PackageContents: React.FC = () => {
102
+ const syncing = useAtomValue(sandboxSyncAtom).kind === "running";
78
103
  const [userViewMode, setUserViewMode] = React.useState<ViewMode | null>(null);
79
- const {
80
- data: dependencies,
81
- error,
82
- refetch,
83
- isPending,
84
- } = useAsyncData(async () => {
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();
98
- return {
99
- list: listPackagesResponse.packages,
100
- context: dependencyTreeResponse.context,
101
- tree: dependencyTreeResponse.tree,
102
- };
103
- }, [packageManager]);
104
+ const { data: dependencies, error, isPending } = usePackageDependencies();
104
105
 
105
106
  // Only show on the first load
106
107
  if (isPending) {
107
- return <Spinner size="medium" centered={true} />;
108
+ return (
109
+ <output className="flex flex-1 items-center justify-center gap-2 text-xs text-muted-foreground">
110
+ <Spinner className="size-4" />
111
+ Loading installed packages…
112
+ </output>
113
+ );
108
114
  }
109
115
 
110
116
  if (error) {
@@ -122,58 +128,49 @@ const PackagesPanel: React.FC = () => {
122
128
  const viewMode = isSandbox
123
129
  ? "tree"
124
130
  : 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;
131
+ const scopeLabel = name && name !== "<root>" ? "project" : "environment";
133
132
 
134
133
  return (
135
134
  <div className="flex-1 flex flex-col overflow-hidden">
136
- <InstallPackageForm context={dependencies.context} onSuccess={refetch} />
137
- {(isTreeSupported || isSandbox) && (
135
+ <fieldset disabled={syncing} className="contents">
136
+ <InstallPackageForm context={dependencies.context} />
137
+ </fieldset>
138
+ {isTreeSupported && !isSandbox && (
138
139
  <div className="flex items-center justify-between px-2 py-1 border-b">
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
- )}
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>
169
166
  <div className="flex items-center gap-2">
170
167
  <div
171
168
  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"
172
- title={scopeTitle}
169
+ title={scopeLabel}
173
170
  >
174
171
  {scopeLabel}
175
172
  </div>
176
- {name && !isSandbox && (
173
+ {name && (
177
174
  <span className="text-xs text-muted-foreground">
178
175
  {name}
179
176
  {version && ` v${version}`}
@@ -182,16 +179,26 @@ const PackagesPanel: React.FC = () => {
182
179
  </div>
183
180
  </div>
184
181
  )}
185
- {viewMode === "list" ? (
186
- <PackagesList packages={dependencies.list} onSuccess={refetch} />
187
- ) : (
188
- <DependencyTree
189
- tree={dependencies.tree}
190
- error={error}
191
- sandboxBackend={sandboxBackend}
192
- onSuccess={refetch}
193
- />
194
- )}
182
+ <fieldset
183
+ disabled={syncing}
184
+ className="flex flex-col flex-1 min-h-0"
185
+ aria-busy={syncing}
186
+ >
187
+ {syncing && (
188
+ <p className="px-3 py-2 text-xs text-muted-foreground">
189
+ Showing packages from the last sync.
190
+ </p>
191
+ )}
192
+ {viewMode === "list" ? (
193
+ <PackagesList packages={dependencies.list} />
194
+ ) : (
195
+ <DependencyTree
196
+ tree={dependencies.tree}
197
+ error={error}
198
+ sandboxBackend={sandboxBackend}
199
+ />
200
+ )}
201
+ </fieldset>
195
202
  </div>
196
203
  );
197
204
  };
@@ -200,8 +207,7 @@ export default PackagesPanel;
200
207
 
201
208
  const InstallPackageForm: React.FC<{
202
209
  context: PackageInstallationContext;
203
- onSuccess: () => void;
204
- }> = ({ onSuccess, context }) => {
210
+ }> = ({ context }) => {
205
211
  const [input, setInput] = React.useState("");
206
212
  const { handleClick: openSettings } = useOpenSettingsToTab();
207
213
  const isSandbox = context.kind === "sandbox";
@@ -222,7 +228,6 @@ const InstallPackageForm: React.FC<{
222
228
 
223
229
  const { loading, handleInstallPackages } = useInstallPackages();
224
230
  const onSuccessInstallPackages = () => {
225
- onSuccess();
226
231
  setInput("");
227
232
  };
228
233
 
@@ -363,9 +368,8 @@ const InstallPackageForm: React.FC<{
363
368
  };
364
369
 
365
370
  const PackagesList: React.FC<{
366
- onSuccess: () => void;
367
371
  packages: { name: string; version: string }[];
368
- }> = ({ onSuccess, packages }) => {
372
+ }> = ({ packages }) => {
369
373
  // Sort case-insensitively so packages are strictly alphabetical
370
374
  // regardless of capitalization (package managers sort inconsistently).
371
375
  const sortedPackages = React.useMemo(
@@ -410,8 +414,8 @@ const PackagesList: React.FC<{
410
414
  <TableCell>{item.name}</TableCell>
411
415
  <TableCell>{item.version}</TableCell>
412
416
  <TableCell className="flex justify-end">
413
- <UpgradeButton packageName={item.name} onSuccess={onSuccess} />
414
- <RemoveButton packageName={item.name} onSuccess={onSuccess} />
417
+ <UpgradeButton packageName={item.name} />
418
+ <RemoveButton packageName={item.name} />
415
419
  </TableCell>
416
420
  </TableRow>
417
421
  ))}
@@ -423,40 +427,14 @@ const PackagesList: React.FC<{
423
427
  const UpgradeButton: React.FC<{
424
428
  packageName: string;
425
429
  tags?: { kind: string; value: string }[];
426
- onSuccess: () => void;
427
- }> = ({ packageName, tags, onSuccess }) => {
428
- const [loading, setLoading] = React.useState(false);
429
- const { addPackage } = useRequestClient();
430
-
431
- // Hide upgrade button in WASM
430
+ }> = ({ packageName, tags }) => {
431
+ const { loading, run } = usePackageAction("upgrade", packageName, tags);
432
432
  if (isWasm()) {
433
433
  return null;
434
434
  }
435
435
 
436
- const handleUpgradePackage = async () => {
437
- try {
438
- setLoading(true);
439
- const group = tags?.find((tag) => tag.kind === "group")?.value;
440
- const response = await addPackage({
441
- package: packageName,
442
- upgrade: true,
443
- group,
444
- });
445
- if (response.restartRequired) {
446
- showPackageRestartToast();
447
- } else if (response.success) {
448
- onSuccess();
449
- showUpgradePackageToast(packageName);
450
- } else {
451
- showUpgradePackageToast(packageName, response.error);
452
- }
453
- } finally {
454
- setLoading(false);
455
- }
456
- };
457
-
458
436
  return (
459
- <PackageActionButton onClick={handleUpgradePackage} loading={loading}>
437
+ <PackageActionButton onClick={run} loading={loading}>
460
438
  Upgrade
461
439
  </PackageActionButton>
462
440
  );
@@ -465,34 +443,14 @@ const UpgradeButton: React.FC<{
465
443
  const RemoveButton: React.FC<{
466
444
  packageName: string;
467
445
  tags?: { kind: string; value: string }[];
468
- onSuccess: () => void;
469
- }> = ({ packageName, tags, onSuccess }) => {
470
- const [loading, setLoading] = React.useState(false);
471
- const { removePackage } = useRequestClient();
472
-
473
- const handleRemovePackage = async () => {
474
- try {
475
- setLoading(true);
476
- const group = tags?.find((tag) => tag.kind === "group")?.value;
477
- const response = await removePackage({
478
- package: packageName,
479
- group,
480
- });
481
- if (response.restartRequired) {
482
- showPackageRestartToast();
483
- } else if (response.success) {
484
- onSuccess();
485
- showRemovePackageToast(packageName);
486
- } else {
487
- showRemovePackageToast(packageName, response.error);
488
- }
489
- } finally {
490
- setLoading(false);
491
- }
492
- };
446
+ }> = ({ packageName, tags }) => {
447
+ const { loading, run } = usePackageAction("remove", packageName, tags);
448
+ if (packageName.toLowerCase() === "marimo") {
449
+ return null;
450
+ }
493
451
 
494
452
  return (
495
- <PackageActionButton onClick={handleRemovePackage} loading={loading}>
453
+ <PackageActionButton onClick={run} loading={loading}>
496
454
  Remove
497
455
  </PackageActionButton>
498
456
  );
@@ -502,8 +460,7 @@ const DependencyTree: React.FC<{
502
460
  tree: DependencyTreeNode | null;
503
461
  error?: Error | null;
504
462
  sandboxBackend: "uv" | "pixi" | null;
505
- onSuccess: () => void;
506
- }> = ({ tree, error, sandboxBackend, onSuccess }) => {
463
+ }> = ({ tree, error, sandboxBackend }) => {
507
464
  const [expandedNodes, setExpandedNodes] = React.useState<Set<string>>(
508
465
  new Set(),
509
466
  );
@@ -570,7 +527,6 @@ const DependencyTree: React.FC<{
570
527
  isTopLevel={true}
571
528
  expandedNodes={expandedNodes}
572
529
  onToggle={toggleNode}
573
- onSuccess={onSuccess}
574
530
  />
575
531
  </div>
576
532
  ))}
@@ -586,16 +542,7 @@ const DependencyTreeNode: React.FC<{
586
542
  isTopLevel?: boolean;
587
543
  expandedNodes: Set<string>;
588
544
  onToggle: (nodeId: string) => void;
589
- onSuccess: () => void;
590
- }> = ({
591
- nodeId,
592
- node,
593
- level,
594
- isTopLevel = false,
595
- expandedNodes,
596
- onToggle,
597
- onSuccess,
598
- }) => {
545
+ }> = ({ nodeId, node, level, isTopLevel = false, expandedNodes, onToggle }) => {
599
546
  const hasChildren = node.dependencies.length > 0;
600
547
  const isExpanded = expandedNodes.has(nodeId);
601
548
  const indent = isTopLevel ? 0 : 16 + level * 16; // Top-level uses CSS padding, children use calculated indent
@@ -709,17 +656,9 @@ const DependencyTreeNode: React.FC<{
709
656
  {/* Actions for top-level packages */}
710
657
  {isTopLevel && (
711
658
  <div className="flex gap-1 invisible group-hover:visible">
712
- <UpgradeButton
713
- packageName={node.name}
714
- tags={node.tags}
715
- onSuccess={onSuccess}
716
- />
659
+ <UpgradeButton packageName={node.name} tags={node.tags} />
717
660
 
718
- <RemoveButton
719
- packageName={node.name}
720
- tags={node.tags}
721
- onSuccess={onSuccess}
722
- />
661
+ <RemoveButton packageName={node.name} tags={node.tags} />
723
662
  </div>
724
663
  )}
725
664
  </div>
@@ -736,7 +675,6 @@ const DependencyTreeNode: React.FC<{
736
675
  isTopLevel={false}
737
676
  expandedNodes={expandedNodes}
738
677
  onToggle={onToggle}
739
- onSuccess={onSuccess}
740
678
  />
741
679
  ))}
742
680
  </div>
@@ -0,0 +1,106 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { Suspense } from "react";
3
+ import { Spinner } from "@/components/icons/spinner";
4
+ import { Button } from "@/components/ui/button";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogDescription,
9
+ DialogFooter,
10
+ DialogHeader,
11
+ DialogTitle,
12
+ } from "@/components/ui/dialog";
13
+ import { useSandboxController } from "@/core/packages/useSandboxController";
14
+ import { LazyAnyLanguageCodeMirror } from "@/plugins/impl/code/LazyAnyLanguageCodeMirror";
15
+ import { useTheme } from "@/theme/useTheme";
16
+ import { Paths } from "@/utils/paths";
17
+ import { SandboxErrorOutput } from "./sandbox-panel";
18
+
19
+ export function SandboxController({
20
+ onReconnect,
21
+ }: {
22
+ onReconnect: () => Promise<void>;
23
+ }) {
24
+ const {
25
+ filename,
26
+ open,
27
+ setOpen,
28
+ draft,
29
+ setDraft,
30
+ dirty,
31
+ loading,
32
+ saving,
33
+ pending,
34
+ error,
35
+ diagnostic,
36
+ conflict,
37
+ loadManifest,
38
+ saveAndSync,
39
+ } = useSandboxController(onReconnect);
40
+ const { theme } = useTheme();
41
+ return (
42
+ <Dialog open={open} onOpenChange={setOpen}>
43
+ <DialogContent className="sm:max-w-xl grid-cols-1 max-h-[80vh] overflow-auto">
44
+ <DialogHeader>
45
+ <DialogTitle>Edit manifest</DialogTitle>
46
+ <DialogDescription className="font-mono text-xs">
47
+ {Paths.basename(filename ?? "Untitled notebook")} · script metadata
48
+ </DialogDescription>
49
+ </DialogHeader>
50
+ {draft !== null && !loading ? (
51
+ <Suspense fallback={<Spinner />}>
52
+ <LazyAnyLanguageCodeMirror
53
+ language="toml"
54
+ theme={theme}
55
+ value={draft}
56
+ onChange={setDraft}
57
+ editable={!pending}
58
+ height="260px"
59
+ basicSetup={{ lineNumbers: false, foldGutter: false }}
60
+ className="border rounded overflow-hidden"
61
+ aria-label="Notebook manifest"
62
+ />
63
+ </Suspense>
64
+ ) : (
65
+ !error && <Spinner />
66
+ )}
67
+ {diagnostic && <SandboxErrorOutput error={diagnostic} />}
68
+ {conflict && (
69
+ <Button variant="text" size="sm" onClick={loadManifest}>
70
+ Discard draft and reload manifest
71
+ </Button>
72
+ )}
73
+ <DialogFooter className="items-center sm:justify-between gap-3">
74
+ <span className="text-xs text-muted-foreground mr-auto">
75
+ {loading
76
+ ? "Loading…"
77
+ : dirty
78
+ ? "Unsaved changes"
79
+ : draft !== null
80
+ ? "Saved"
81
+ : ""}
82
+ </span>
83
+ <Button variant="text" size="sm" onClick={() => setOpen(false)}>
84
+ Close
85
+ </Button>
86
+ <Button
87
+ size="sm"
88
+ disabled={draft === null || pending}
89
+ onClick={saveAndSync}
90
+ >
91
+ {pending && <Spinner className="size-3 mr-2" />}
92
+ {loading
93
+ ? "Loading…"
94
+ : saving
95
+ ? "Saving…"
96
+ : pending
97
+ ? "Syncing…"
98
+ : dirty
99
+ ? "Save & sync"
100
+ : "Sync"}
101
+ </Button>
102
+ </DialogFooter>
103
+ </DialogContent>
104
+ </Dialog>
105
+ );
106
+ }
@@ -0,0 +1,38 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { atom } from "jotai";
3
+ import { connectionNoticeAtom } from "@/core/network/connection-notice";
4
+ import { preparationAtom } from "@/core/packages/sandbox-state";
5
+
6
+ const preferenceAtom = atom<{
7
+ preparationId: string | undefined;
8
+ error: string | null;
9
+ expanded: boolean;
10
+ } | null>(null);
11
+
12
+ const disclosureContextAtom = atom((get) => {
13
+ const notice = get(connectionNoticeAtom);
14
+ return {
15
+ preparationId: get(preparationAtom)?.operation_id,
16
+ error: notice && !notice.pending ? (notice.error ?? notice.title) : null,
17
+ };
18
+ });
19
+
20
+ export const sandboxDetailsExpandedAtom = atom(
21
+ (get) => {
22
+ const context = get(disclosureContextAtom);
23
+ const preference = get(preferenceAtom);
24
+ if (
25
+ preference &&
26
+ preference.preparationId === context.preparationId &&
27
+ preference.error === context.error
28
+ ) {
29
+ return preference.expanded;
30
+ }
31
+ // New work and failures open automatically. Completed startup stays quiet
32
+ // unless the user chose to inspect it.
33
+ return get(connectionNoticeAtom) !== null;
34
+ },
35
+ (get, set, expanded: boolean) => {
36
+ set(preferenceAtom, { ...get(disclosureContextAtom), expanded });
37
+ },
38
+ );