@marimo-team/islands 0.24.3-dev9 → 0.25.1-dev1

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-pXXIvlr3.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-BC_yF09p.js +138 -0
  46. package/dist/{common-Cv-4hMa0.js → common-Dv227ygK.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-B-I2K7z3.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-D2hUXe09.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-B851uguN.js} +2143 -1910
  105. package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
  106. package/dist/globals-CmijFoIU.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-BtdoxWiD.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-DQq7NUGJ.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
@@ -0,0 +1,155 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { isPlainObject } from "lodash-es";
3
+
4
+ export const PAGE_SIZE = 30;
5
+
6
+ interface Page {
7
+ path: string;
8
+ remaining: number;
9
+ }
10
+
11
+ interface Options {
12
+ limits: Record<string, number>;
13
+ pageSize: number;
14
+ }
15
+
16
+ export function paginateJson(data: object, { limits, pageSize }: Options) {
17
+ const originals = new WeakMap<object, object>();
18
+ const pages = new Map<symbol, Page>();
19
+
20
+ function visit(node: object, path: string[]): object {
21
+ if (!Array.isArray(node) && !isPlainObject(node)) {
22
+ return node;
23
+ }
24
+ const pathKey = JSON.stringify(path);
25
+ const limit = limits[pathKey] ?? pageSize;
26
+ const keys = Array.isArray(node)
27
+ ? Array.from({ length: Math.min(node.length, limit) }, (_, i) =>
28
+ String(i),
29
+ )
30
+ : Object.keys(node).slice(0, limit);
31
+ const count = Array.isArray(node) ? node.length : Object.keys(node).length;
32
+ const result: object = Array.isArray(node) ? [] : Object.create(null);
33
+ originals.set(result, node);
34
+
35
+ for (const key of keys) {
36
+ // Materialize only the branches the viewer reads, including after expansion.
37
+ Object.defineProperty(result, key, {
38
+ enumerable: true,
39
+ configurable: true,
40
+ get() {
41
+ const original: unknown = Reflect.get(node, key);
42
+ const value =
43
+ original !== null && typeof original === "object"
44
+ ? visit(original, [...path, key])
45
+ : original;
46
+ Object.defineProperty(result, key, {
47
+ value,
48
+ enumerable: true,
49
+ configurable: true,
50
+ });
51
+ return value;
52
+ },
53
+ });
54
+ }
55
+ if (count > limit) {
56
+ const marker = Symbol("show more");
57
+ pages.set(marker, { remaining: count - limit, path: pathKey });
58
+ let key = Array.isArray(node) ? String(limit) : "";
59
+ while (Object.hasOwn(result, key)) {
60
+ key += "\0";
61
+ }
62
+ Object.defineProperty(result, key, { value: marker, enumerable: true });
63
+ }
64
+ return result;
65
+ }
66
+
67
+ return {
68
+ data: visit(data, []),
69
+ getOriginal(value: unknown): unknown {
70
+ return value !== null && typeof value === "object"
71
+ ? (originals.get(value) ?? value)
72
+ : value;
73
+ },
74
+ getPage(value: unknown): Page | undefined {
75
+ return typeof value === "symbol" ? pages.get(value) : undefined;
76
+ },
77
+ };
78
+ }
79
+
80
+ export function estimateExpandedLines(
81
+ node: unknown,
82
+ cap: number,
83
+ depth = 0,
84
+ ): number {
85
+ if (
86
+ depth > 4 ||
87
+ node === null ||
88
+ node === undefined ||
89
+ typeof node !== "object"
90
+ ) {
91
+ return 1;
92
+ }
93
+ const children: unknown[] = Array.isArray(node) ? node : Object.values(node);
94
+ let lines = 0;
95
+ for (let i = 0; i < children.length && lines < cap; i++) {
96
+ const child = children[i];
97
+ if (child === null || child === undefined || typeof child !== "object") {
98
+ lines++;
99
+ } else {
100
+ const childLen = Array.isArray(child)
101
+ ? child.length
102
+ : Object.keys(child).length;
103
+ lines +=
104
+ childLen <= 8
105
+ ? estimateExpandedLines(child, cap - lines, depth + 1)
106
+ : 1;
107
+ }
108
+ }
109
+ return lines;
110
+ }
111
+
112
+ export function shouldExpandNode(
113
+ _isExpanded: boolean,
114
+ { value, level }: { value?: object; level: number },
115
+ ): boolean {
116
+ if (level <= 1) {
117
+ return true;
118
+ }
119
+ if (level > 5) {
120
+ return false;
121
+ }
122
+ if (value === null || value === undefined || typeof value !== "object") {
123
+ return true;
124
+ }
125
+ const len = Array.isArray(value) ? value.length : Object.keys(value).length;
126
+ if (len === 0) {
127
+ return true;
128
+ }
129
+ if (len > 200) {
130
+ return false;
131
+ }
132
+ return estimateExpandedLines(value, 150) <= 120;
133
+ }
134
+
135
+ export function determineMaxDisplayLength(data: unknown): number | undefined {
136
+ if (!Array.isArray(data)) {
137
+ return undefined;
138
+ }
139
+ const sample = data.slice(0, 15);
140
+ let maxLength = 0;
141
+ for (const el of sample) {
142
+ if (Array.isArray(el)) {
143
+ for (const next of el.slice(0, 5)) {
144
+ if (Array.isArray(next)) {
145
+ return 5;
146
+ }
147
+ }
148
+ maxLength = Math.max(maxLength, el.length);
149
+ }
150
+ }
151
+ if (maxLength <= 20) {
152
+ return undefined;
153
+ }
154
+ return maxLength >= 50 ? 5 : 10;
155
+ }
@@ -0,0 +1,196 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { useState } from "react";
3
+ import type { OutputMessage } from "@/core/kernel/messages";
4
+ import { isUrl } from "@/utils/urls";
5
+ import { OutputRenderer } from "../../Output";
6
+ import { HtmlOutput } from "../HtmlOutput";
7
+ import { ImageOutput } from "../ImageOutput";
8
+ import { JsonOutput } from "../JsonOutput";
9
+ import { VideoOutput } from "../VideoOutput";
10
+ import {
11
+ decodePythonKey,
12
+ formatTuplePayload,
13
+ formatSetPayload,
14
+ formatFrozensetPayload,
15
+ splitLeaf,
16
+ } from "./formatting";
17
+
18
+ export const COLLAPSED_TEXT_LENGTH = 100;
19
+
20
+ // Keep long text and quotes wrapping together.
21
+ /* oxlint-disable jsx-a11y/prefer-tag-over-role */
22
+ const CollapsibleTextOutput: React.FC<{ text: string }> = ({ text }) => {
23
+ const [collapsed, setCollapsed] = useState(true);
24
+ if (text.length <= COLLAPSED_TEXT_LENGTH) {
25
+ return <span className="break-all">{text}</span>;
26
+ }
27
+ return (
28
+ <span
29
+ className="cursor-pointer hover:opacity-90 break-all"
30
+ role="button"
31
+ tabIndex={0}
32
+ aria-expanded={!collapsed}
33
+ onClick={() => setCollapsed(!collapsed)}
34
+ onKeyDown={(event) => {
35
+ if (event.key === "Enter" || event.key === " ") {
36
+ event.preventDefault();
37
+ setCollapsed(!collapsed);
38
+ }
39
+ }}
40
+ >
41
+ {collapsed ? `${text.slice(0, COLLAPSED_TEXT_LENGTH)}...` : text}
42
+ </span>
43
+ );
44
+ };
45
+
46
+ /* oxlint-enable jsx-a11y/prefer-tag-over-role */
47
+
48
+ type LeafRenderer = (
49
+ data: string,
50
+ mimeType: OutputMessage["mimetype"],
51
+ ) => React.ReactNode;
52
+
53
+ const LEAF_RENDERERS: Record<string, LeafRenderer> = {
54
+ "image/": (v) => <ImageOutput src={v} />,
55
+ "video/": (v) => <VideoOutput src={v} />,
56
+ "text/html:": (v) => (
57
+ <HtmlOutput html={v} inline={true} alwaysSanitizeHtml={false} />
58
+ ),
59
+ "text/markdown:": (v) => (
60
+ <HtmlOutput html={v} inline={true} alwaysSanitizeHtml={true} />
61
+ ),
62
+ "text/plain+float:": (v) => <span>{v}</span>,
63
+ "text/plain+bigint:": (v) => <span>{v}</span>,
64
+ "text/plain+set:": (v) => <span>{formatSetPayload(v)}</span>,
65
+ "text/plain+frozenset:": (v) => <span>{formatFrozensetPayload(v)}</span>,
66
+ "text/plain+tuple:": (v) => <span>{formatTuplePayload(v)}</span>,
67
+ "text/plain:": (v) => <CollapsibleTextOutput text={v} />,
68
+ "application/json:": (v) => <JsonOutput data={JSON.parse(v)} />,
69
+ "application/": (v, mime) => (
70
+ <OutputRenderer
71
+ message={{ channel: "output", data: v, mimetype: mime }}
72
+ renderFallback={() => (
73
+ <span>
74
+ {mime}:{v}
75
+ </span>
76
+ )}
77
+ />
78
+ ),
79
+ };
80
+
81
+ function tryRenderMimeLeaf(value: string): React.ReactNode | null {
82
+ for (const prefix of Object.keys(LEAF_RENDERERS)) {
83
+ if (value.startsWith(prefix)) {
84
+ const [data, mime] = splitLeaf(value);
85
+ return mime
86
+ ? LEAF_RENDERERS[prefix](data, mime as OutputMessage["mimetype"])
87
+ : null;
88
+ }
89
+ }
90
+ return null;
91
+ }
92
+
93
+ interface KeyRenderResult {
94
+ keyName?: string | number;
95
+ }
96
+
97
+ export function renderKeyName(
98
+ props: Record<string, unknown>,
99
+ { keyName }: KeyRenderResult,
100
+ ): React.ReactNode {
101
+ const decoded = decodePythonKey(keyName);
102
+ if (!decoded) {
103
+ return undefined;
104
+ }
105
+ return <span {...props}>{decoded.text}</span>;
106
+ }
107
+
108
+ export function renderKeyQuote(
109
+ _props: Record<string, unknown>,
110
+ { keyName }: KeyRenderResult,
111
+ ): React.ReactNode {
112
+ // The viewer treats null/undefined as a request for its default quotes.
113
+ return decodePythonKey(keyName)?.quoted === false ? <span /> : undefined;
114
+ }
115
+
116
+ export interface RenderResult {
117
+ type: string;
118
+ value?: unknown;
119
+ }
120
+
121
+ export function renderStringValue(
122
+ _props: React.HTMLAttributes<HTMLSpanElement>,
123
+ result: RenderResult,
124
+ mode: "python" | "json",
125
+ ): React.ReactNode {
126
+ if (result.type !== "value" || typeof result.value !== "string") {
127
+ return undefined;
128
+ }
129
+ const { value } = result;
130
+ if (mode !== "python") {
131
+ return renderPlainString(value);
132
+ }
133
+
134
+ const mimeResult = tryRenderMimeLeaf(value);
135
+ if (mimeResult !== null) {
136
+ return <span className="w-rjv-value">{mimeResult}</span>;
137
+ }
138
+ if (isUrl(value)) {
139
+ return (
140
+ <span className="w-rjv-value">
141
+ <a
142
+ href={value}
143
+ target="_blank"
144
+ rel="noopener noreferrer"
145
+ className="text-link hover:underline"
146
+ >
147
+ {value}
148
+ </a>
149
+ </span>
150
+ );
151
+ }
152
+ return renderPlainString(value);
153
+ }
154
+
155
+ function renderPlainString(value: string) {
156
+ if (value.length <= COLLAPSED_TEXT_LENGTH) {
157
+ return undefined;
158
+ }
159
+ return (
160
+ <span
161
+ className="inline-block"
162
+ style={{ color: "var(--w-rjv-type-string-color)" }}
163
+ >
164
+ &quot;
165
+ <CollapsibleTextOutput text={value} />
166
+ &quot;
167
+ </span>
168
+ );
169
+ }
170
+
171
+ export function renderArrow(
172
+ props: React.HTMLAttributes<HTMLSpanElement>,
173
+ { keyName }: KeyRenderResult,
174
+ ): React.ReactNode {
175
+ // alpha.43's data-expanded is inverted and omits initial collapse rules.
176
+ // NestedOpen's transform reflects the effective state.
177
+ const expanded = props.style?.transform === "rotate(0deg)";
178
+ return (
179
+ <button
180
+ {...props}
181
+ type="button"
182
+ aria-label={`${expanded ? "Collapse" : "Expand"} ${keyName ?? "root"}`}
183
+ aria-expanded={expanded}
184
+ />
185
+ );
186
+ }
187
+
188
+ function renderLiteral(text: string) {
189
+ return (_props: Record<string, unknown>, { type }: RenderResult) =>
190
+ type === "value" ? <span className="w-rjv-value">{text}</span> : undefined;
191
+ }
192
+
193
+ export const PYTHON_TRUE_RENDER = renderLiteral("True");
194
+ export const PYTHON_FALSE_RENDER = renderLiteral("False");
195
+ export const PYTHON_NULL_RENDER = renderLiteral("None");
196
+ export const JSON_NULL_RENDER = renderLiteral("null");
@@ -0,0 +1,52 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type React from "react";
3
+
4
+ type ViewerStyle = React.CSSProperties & Record<`--w-rjv-${string}`, string>;
5
+
6
+ const BASE_THEME: ViewerStyle = {
7
+ fontSize: "var(--text-xs, .75rem)",
8
+ lineHeight: "var(--text-xs--line-height, 1rem)",
9
+ "--w-rjv-font-family": "monospace",
10
+ "--w-rjv-background-color": "transparent",
11
+ "--w-rjv-key-string": "var(--w-rjv-color)",
12
+ "--w-rjv-arrow-color": "var(--w-rjv-color)",
13
+ "--w-rjv-curlybraces-color": "var(--w-rjv-color)",
14
+ "--w-rjv-colon-color": "var(--w-rjv-color)",
15
+ "--w-rjv-brackets-color": "var(--w-rjv-color)",
16
+ "--w-rjv-quotes-color": "var(--w-rjv-color)",
17
+ "--w-rjv-ellipsis-color": "var(--w-rjv-type-string-color)",
18
+ "--w-rjv-quotes-string-color": "var(--w-rjv-type-string-color)",
19
+ "--w-rjv-type-bigint-color": "var(--w-rjv-type-int-color)",
20
+ "--w-rjv-type-url-color": "var(--link)",
21
+ "--w-rjv-type-nan-color": "var(--w-rjv-type-null-color)",
22
+ };
23
+
24
+ export const marimoLightTheme: ViewerStyle = {
25
+ ...BASE_THEME,
26
+ "--w-rjv-color": "#002b36",
27
+ "--w-rjv-key-number": "#6c71c4",
28
+ "--w-rjv-line-color": "rgb(235, 235, 235)",
29
+ "--w-rjv-info-color": "rgba(0, 0, 0, 0.3)",
30
+ "--w-rjv-type-string-color": "#cb4b16",
31
+ "--w-rjv-type-int-color": "#268bd2",
32
+ "--w-rjv-type-float-color": "#859900",
33
+ "--w-rjv-type-boolean-color": "#2aa198",
34
+ "--w-rjv-type-date-color": "#586e75",
35
+ "--w-rjv-type-null-color": "#d33682",
36
+ "--w-rjv-type-undefined-color": "#586e75",
37
+ };
38
+
39
+ export const marimoDarkTheme: ViewerStyle = {
40
+ ...BASE_THEME,
41
+ "--w-rjv-color": "#f8f8f8",
42
+ "--w-rjv-key-number": "#86c1b9",
43
+ "--w-rjv-line-color": "#383838",
44
+ "--w-rjv-info-color": "#b8b8b8",
45
+ "--w-rjv-type-string-color": "#dc9656",
46
+ "--w-rjv-type-int-color": "#a16946",
47
+ "--w-rjv-type-float-color": "#a1b56c",
48
+ "--w-rjv-type-boolean-color": "#ba8baf",
49
+ "--w-rjv-type-date-color": "#7cafc2",
50
+ "--w-rjv-type-null-color": "#ab4642",
51
+ "--w-rjv-type-undefined-color": "#d8d8d8",
52
+ };
@@ -14,7 +14,7 @@ import {
14
14
  XIcon,
15
15
  } from "lucide-react";
16
16
  import type React from "react";
17
- import { useState } from "react";
17
+ import { useEffect, useState } from "react";
18
18
  import { useForm } from "react-hook-form";
19
19
  import type { z } from "zod";
20
20
  import {
@@ -25,19 +25,20 @@ import {
25
25
  FormMessage,
26
26
  } from "@/components/ui/form";
27
27
  import {
28
- isInstallingPackageAlert,
28
+ type EnvironmentOperationAlert,
29
+ isEnvironmentOperationAlert,
29
30
  isMissingPackageAlert,
30
31
  useAlertActions,
31
32
  useAlerts,
32
33
  } from "@/core/alerts/state";
33
34
  import { useResolvedMarimoConfig } from "@/core/config/config";
34
- import type { PackageInstallationStatus } from "@/core/kernel/messages";
35
+ import type { PackageOperationStatus } from "@/core/kernel/messages";
35
36
  import { useRequestClient } from "@/core/network/requests";
36
37
  import { RESTART_REQUIRED_DESCRIPTION } from "@/core/packages/toast-components";
37
38
  import { isWasm } from "@/core/wasm/utils";
38
39
  import { usePackageMetadata } from "@/hooks/usePackageMetadata";
39
40
  import { Banner } from "@/plugins/impl/common/error-banner";
40
- import { logNever } from "@/utils/assertNever";
41
+ import { assertNever, logNever } from "@/utils/assertNever";
41
42
  import { cn } from "@/utils/cn";
42
43
  import { Logger } from "@/utils/Logger";
43
44
  import {
@@ -100,7 +101,7 @@ const SourceBadge: React.FC<{ source?: "kernel" | "server" }> = ({
100
101
  };
101
102
 
102
103
  export const PackageAlert: React.FC = () => {
103
- const { packageAlert, packageLogs } = useAlerts();
104
+ const { packageAlert } = useAlerts();
104
105
  const { clearPackageAlert } = useAlertActions();
105
106
  const [userConfig] = useResolvedMarimoConfig();
106
107
  const [desiredPackageVersions, setDesiredPackageVersions] = useState<
@@ -110,6 +111,23 @@ export const PackageAlert: React.FC = () => {
110
111
  Record<string, string[]>
111
112
  >({});
112
113
 
114
+ const completedAlertId =
115
+ packageAlert?.kind === "environment" &&
116
+ packageAlert.status.kind === "succeeded" &&
117
+ !packageAlert.restartRequired
118
+ ? packageAlert.id
119
+ : null;
120
+ useEffect(() => {
121
+ if (completedAlertId === null) {
122
+ return;
123
+ }
124
+ const timeout = setTimeout(
125
+ () => clearPackageAlert(completedAlertId),
126
+ 10_000,
127
+ );
128
+ return () => clearTimeout(timeout);
129
+ }, [completedAlertId, clearPackageAlert]);
130
+
113
131
  if (packageAlert === null) {
114
132
  return null;
115
133
  }
@@ -224,12 +242,9 @@ export const PackageAlert: React.FC = () => {
224
242
  );
225
243
  }
226
244
 
227
- if (isInstallingPackageAlert(packageAlert)) {
245
+ if (isEnvironmentOperationAlert(packageAlert)) {
228
246
  const { status, title, titleIcon, description } =
229
- getInstallationStatusElements(packageAlert.packages);
230
- if (status === "installed") {
231
- setTimeout(() => clearPackageAlert(packageAlert.id), 10_000);
232
- }
247
+ getOperationStatusElements(packageAlert);
233
248
 
234
249
  return (
235
250
  <div className="flex flex-col gap-4 mb-5 fixed top-5 left-12 min-w-[400px] z-200 opacity-95 max-w-[600px] pointer-events-none">
@@ -255,23 +270,27 @@ export const PackageAlert: React.FC = () => {
255
270
  <div
256
271
  className={cn(
257
272
  "flex flex-col gap-4 justify-between items-start text-muted-foreground text-base",
258
- status === "installed" && "text-accent-foreground",
273
+ status === "succeeded" && "text-accent-foreground",
259
274
  )}
260
275
  >
261
276
  <p>{description}</p>
262
- {status !== "installing" &&
263
- Object.values(packageAlert.packages).includes(
264
- "restart-required",
265
- ) && <RestartKernelButton />}
277
+ {status !== "running" && packageAlert.restartRequired && (
278
+ <>
279
+ {status !== "restart-required" && (
280
+ <p>{RESTART_REQUIRED_DESCRIPTION}</p>
281
+ )}
282
+ <RestartKernelButton />
283
+ </>
284
+ )}
266
285
  <ul className="list-disc ml-2 mt-1">
267
286
  {Object.entries(packageAlert.packages).map(([pkg, st], index) => (
268
287
  <li
269
288
  className={cn(
270
289
  "flex items-center gap-1 font-mono text-sm",
271
- st === "installing" && "font-semibold",
290
+ st === "running" && "font-semibold",
272
291
  st === "failed" && "text-destructive",
273
- st === "installed" && "text-accent-foreground",
274
- st === "installed" &&
292
+ st === "succeeded" && "text-accent-foreground",
293
+ st === "succeeded" &&
275
294
  status === "failed" &&
276
295
  "text-muted-foreground",
277
296
  )}
@@ -282,8 +301,11 @@ export const PackageAlert: React.FC = () => {
282
301
  </li>
283
302
  ))}
284
303
  </ul>
285
- {Object.keys(packageLogs).length > 0 && (
286
- <StreamingLogsViewer packageLogs={packageLogs} />
304
+ {Object.keys(packageAlert.logs).length > 0 && (
305
+ <StreamingLogsViewer
306
+ key={packageAlert.id}
307
+ packageLogs={packageAlert.logs}
308
+ />
287
309
  )}
288
310
  </div>
289
311
  </Banner>
@@ -295,60 +317,84 @@ export const PackageAlert: React.FC = () => {
295
317
  return null;
296
318
  };
297
319
 
298
- function getInstallationStatusElements(packages: PackageInstallationStatus) {
299
- const statuses = new Set(Object.values(packages));
300
- const status =
301
- statuses.has("queued") || statuses.has("installing")
302
- ? "installing"
303
- : statuses.has("failed")
304
- ? "failed"
305
- : statuses.has("restart-required")
306
- ? "restart-required"
307
- : "installed";
308
-
309
- if (status === "installing") {
310
- return {
311
- status: "installing",
312
- title: "Installing packages",
313
- titleIcon: <DownloadCloudIcon className="w-5 h-5 inline-block mr-2" />,
314
- description: "Installing packages:",
315
- };
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
- }
325
- if (status === "installed") {
326
- return {
327
- status: "installed",
328
- title: "All packages installed!",
329
- titleIcon: <PackageCheckIcon className="w-5 h-5 inline-block mr-2" />,
330
- description: "Installed packages:",
331
- };
320
+ function getOperationStatusElements({
321
+ action,
322
+ status: outcome,
323
+ restartRequired,
324
+ }: EnvironmentOperationAlert) {
325
+ const status: EnvironmentOperationAlert["status"] =
326
+ outcome.kind === "succeeded" && restartRequired
327
+ ? { kind: "restart-required", reason: RESTART_REQUIRED_DESCRIPTION }
328
+ : outcome;
329
+ const titles = {
330
+ install: {
331
+ running: "Installing packages",
332
+ succeeded: "All packages installed!",
333
+ failed: "Some packages failed to install",
334
+ cancelled: "Package installation cancelled",
335
+ },
336
+ remove: {
337
+ running: "Removing packages",
338
+ succeeded: "Packages removed",
339
+ failed: "Some packages failed to remove",
340
+ cancelled: "Package removal cancelled",
341
+ },
342
+ }[action];
343
+ switch (status.kind) {
344
+ case "running":
345
+ return {
346
+ status: "running",
347
+ title: titles.running,
348
+ titleIcon: <DownloadCloudIcon className="w-5 h-5 inline-block mr-2" />,
349
+ description:
350
+ action === "install" ? "Installing packages:" : "Removing packages:",
351
+ };
352
+ case "restart-required":
353
+ return {
354
+ status: "restart-required",
355
+ title: "Changes saved — restart required",
356
+ titleIcon: <RotateCwIcon className="w-5 h-5 inline-block mr-2" />,
357
+ description: status.reason,
358
+ };
359
+ case "succeeded":
360
+ return {
361
+ status: "succeeded",
362
+ title: titles.succeeded,
363
+ titleIcon: <PackageCheckIcon className="w-5 h-5 inline-block mr-2" />,
364
+ description:
365
+ action === "install" ? "Installed packages:" : "Removed packages:",
366
+ };
367
+ case "failed":
368
+ return {
369
+ status: "failed",
370
+ title: titles.failed,
371
+ titleIcon: <PackageXIcon className="w-5 h-5 inline-block mr-2" />,
372
+ description: status.error,
373
+ };
374
+ case "cancelled":
375
+ return {
376
+ status: "cancelled",
377
+ title: titles.cancelled,
378
+ titleIcon: <XIcon className="w-5 h-5 inline-block mr-2" />,
379
+ description:
380
+ "The operation was interrupted. Some packages may have changed.",
381
+ };
382
+ default:
383
+ return assertNever(status);
332
384
  }
333
- return {
334
- status: "failed",
335
- title: "Some packages failed to install",
336
- titleIcon: <PackageXIcon className="w-5 h-5 inline-block mr-2" />,
337
- description: "See error logs.",
338
- };
339
385
  }
340
386
 
341
387
  const ProgressIcon = ({
342
388
  status,
343
389
  }: {
344
- status: PackageInstallationStatus[string];
390
+ status: PackageOperationStatus[string];
345
391
  }) => {
346
392
  switch (status) {
347
393
  case "queued":
348
394
  return <BoxIcon size="1rem" />;
349
- case "installing":
395
+ case "running":
350
396
  return <DownloadCloudIcon size="1rem" />;
351
- case "installed":
397
+ case "succeeded":
352
398
  return <CheckIcon size="1rem" />;
353
399
  case "failed":
354
400
  return <XIcon size="1rem" />;
@@ -672,7 +718,7 @@ const StreamingLogsViewer: React.FC<StreamingLogsViewerProps> = ({
672
718
  }
673
719
 
674
720
  return (
675
- <div className="mt-4 border-t border-border pt-4 w-full">
721
+ <div className="mt-4 border-t border-border pt-4 w-full contain-inline-size">
676
722
  <button
677
723
  onClick={() => setIsExpanded(!isExpanded)}
678
724
  className="flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors"
@@ -683,7 +729,7 @@ const StreamingLogsViewer: React.FC<StreamingLogsViewerProps> = ({
683
729
  ) : (
684
730
  <ChevronRightIcon className="w-4 h-4" />
685
731
  )}
686
- Installation logs
732
+ Logs
687
733
  </button>
688
734
 
689
735
  {isExpanded && (
@@ -694,7 +740,7 @@ const StreamingLogsViewer: React.FC<StreamingLogsViewerProps> = ({
694
740
  {packageName}
695
741
  </h4>
696
742
  <div className="border border-border rounded w-full">
697
- <pre className="p-3 text-xs font-mono bg-background max-h-64 overflow-y-auto text-muted-foreground whitespace-pre-wrap scrollbar-thin">
743
+ <pre className="p-3 text-xs font-mono bg-background max-h-64 overflow-auto text-muted-foreground whitespace-pre scrollbar-thin">
698
744
  {logs || "No logs available"}
699
745
  </pre>
700
746
  </div>