@marimo-team/islands 0.24.3-dev5 → 0.24.3-dev50

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 (376) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C9OF_75w.js → ConnectedDataExplorerComponent-KVhjDMSe.js} +1066 -1066
  2. package/dist/ErrorBoundary-BW0xr_AR.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-BajL8aoc.js +1 -0
  12. package/dist/assets/worker-BemUy60C.js +109 -0
  13. package/dist/blockDiagram-I7D4REHJ-BbXEXJRu.js +1922 -0
  14. package/dist/{button-CKBkqR9J.js → button-DdXAm8iz.js} +5 -5
  15. package/dist/{c4Diagram-5PPSVZJV-DarUk3Yq.js → c4Diagram-7LVT6UL2-DcLsbQmR.js} +696 -668
  16. package/dist/{capabilities-CMBBJTcc.js → capabilities-B3ce_GNu.js} +1 -1
  17. package/dist/{html-to-image-BhNoIBSU.js → cells-BSgNCBZ8.js} +6740 -10126
  18. package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
  19. package/dist/chat-ui-CygzVJ9s.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-BdKqYmPi.js +138 -0
  46. package/dist/{common-xHoep60C.js → common-D9PY0k7A.js} +8839 -12646
  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-BZiw7m3d.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-iJn-Nryx.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-BAHeJT2Q.js +380 -0
  99. package/dist/flowDiagram-HODETNUW-6dMdB8pR.js +16 -0
  100. package/dist/{formats-CJMVUfb3.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-Bp9hhneH.js} +2143 -1910
  105. package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
  106. package/dist/globals-BUgvsAck.js +19 -0
  107. package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
  108. package/dist/html-to-image-kpuRfdfZ.js +3253 -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 +8105 -13485
  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-C743iqsh.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-CpK6fX_C.js → process-output-DFe2tVIY.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-DwuC-61O.js → reveal-component-CgMzL2w5.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-D-Rx3ux5.js → toDate-WXg1yLcI.js} +10 -9
  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-CPehZbUb.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__/requests.ts +7 -0
  185. package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
  186. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +270 -0
  187. package/src/components/chat/acp/agent-panel.tsx +45 -44
  188. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
  189. package/src/components/data-table/column-summary/chart-spec-model.tsx +1 -1
  190. package/src/components/data-table/columns.tsx +64 -67
  191. package/src/components/editor/RecoveryButton.tsx +1 -0
  192. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
  193. package/src/components/editor/ai/add-cell-with-ai.tsx +1 -0
  194. package/src/components/editor/ai/ai-completion-editor.tsx +3 -1
  195. package/src/components/editor/alerts/connecting-alert.tsx +1 -66
  196. package/src/components/editor/alerts/connection-notice.tsx +140 -0
  197. package/src/components/editor/app-container.tsx +9 -3
  198. package/src/components/editor/boundary/ErrorBoundary.tsx +38 -16
  199. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +311 -0
  200. package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +50 -0
  201. package/src/components/editor/cell/code/cell-editor.tsx +41 -42
  202. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +94 -0
  203. package/src/components/editor/chrome/components/feedback-button.tsx +63 -42
  204. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +114 -7
  205. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +165 -0
  206. package/src/components/editor/chrome/panels/packages-panel.tsx +93 -166
  207. package/src/components/editor/chrome/panels/sandbox-controller.tsx +106 -0
  208. package/src/components/editor/chrome/panels/sandbox-panel.tsx +173 -0
  209. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +3 -1
  210. package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
  211. package/src/components/editor/code/readonly-diff.tsx +1 -1
  212. package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +98 -98
  213. package/src/components/editor/connections/database/__tests__/as-code.test.ts +11 -5
  214. package/src/components/editor/dynamic-favicon.tsx +17 -10
  215. package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
  216. package/src/components/editor/file-tree/tree-actions.tsx +11 -14
  217. package/src/components/editor/header/__tests__/status.test.tsx +8 -20
  218. package/src/components/editor/header/filename-input.tsx +2 -0
  219. package/src/components/editor/header/status.tsx +5 -3
  220. package/src/components/editor/notebook-cell.tsx +4 -2
  221. package/src/components/editor/output/JsonOutput.tsx +182 -632
  222. package/src/components/editor/output/Outputs.css +50 -17
  223. package/src/components/editor/output/__tests__/JsonOutput-interactions.test.tsx +254 -0
  224. package/src/components/editor/output/__tests__/JsonOutput-mimetype.test.tsx +41 -46
  225. package/src/components/editor/output/__tests__/{json-output.test.ts → json-output-formatting.test.ts} +113 -75
  226. package/src/components/editor/output/__tests__/json-output-pagination.test.ts +252 -0
  227. package/src/components/editor/output/json-output/formatting.ts +167 -0
  228. package/src/components/editor/output/json-output/pagination.ts +155 -0
  229. package/src/components/editor/output/json-output/renderers.tsx +196 -0
  230. package/src/components/editor/output/json-output/themes.ts +52 -0
  231. package/src/components/editor/renderers/cell-array.tsx +1 -5
  232. package/src/components/home/components.tsx +17 -0
  233. package/src/components/pages/gallery-page.tsx +2 -4
  234. package/src/components/pages/home-page.tsx +2 -4
  235. package/src/components/slides/slide-form.tsx +1 -0
  236. package/src/components/slides/slide-notes-editor.tsx +1 -0
  237. package/src/components/terminal/terminal.tsx +4 -4
  238. package/src/components/tracing/tracing-spec.ts +1 -1
  239. package/src/components/ui/table.tsx +1 -1
  240. package/src/components/ui/use-toast.ts +8 -0
  241. package/src/core/MarimoApp.tsx +0 -2
  242. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +259 -259
  243. package/src/core/cells/__tests__/cell.test.ts +61 -0
  244. package/src/core/cells/__tests__/cells.test.ts +37 -37
  245. package/src/core/cells/cell.ts +9 -1
  246. package/src/core/cells/pending-delete-service.ts +12 -16
  247. package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
  248. package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
  249. package/src/core/codemirror/rtc/extension.ts +5 -2
  250. package/src/core/datasets/__tests__/data-source.test.ts +2 -0
  251. package/src/core/datasets/data-source-connections.ts +15 -10
  252. package/src/core/edit-app.tsx +8 -5
  253. package/src/core/errors/state.ts +1 -2
  254. package/src/core/islands/__tests__/parse.test.ts +140 -7
  255. package/src/core/islands/bootstrap.ts +1 -0
  256. package/src/core/islands/bridge.ts +3 -0
  257. package/src/core/islands/parse.ts +20 -0
  258. package/src/core/network/connection-notice.ts +84 -0
  259. package/src/core/network/requests-lazy.ts +3 -0
  260. package/src/core/network/requests-network.ts +12 -0
  261. package/src/core/network/requests-static.ts +3 -0
  262. package/src/core/network/requests-toasting.tsx +3 -0
  263. package/src/core/network/resolve.ts +2 -1
  264. package/src/core/network/types.ts +7 -0
  265. package/src/core/packages/__tests__/usePackageAction.test.tsx +129 -0
  266. package/src/core/packages/__tests__/useSandboxController.test.tsx +165 -0
  267. package/src/core/packages/package-data.ts +35 -0
  268. package/src/core/packages/sandbox-state.ts +15 -0
  269. package/src/core/packages/toast-components.tsx +11 -0
  270. package/src/core/packages/useInstallPackage.ts +1 -1
  271. package/src/core/packages/usePackageAction.ts +51 -0
  272. package/src/core/packages/usePackageDependencies.ts +22 -0
  273. package/src/core/packages/useSandboxController.ts +188 -0
  274. package/src/core/run-app.tsx +2 -0
  275. package/src/core/runtime/__tests__/runtime.test.ts +11 -0
  276. package/src/core/runtime/runtime.ts +7 -2
  277. package/src/core/wasm/bridge.ts +11 -0
  278. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +212 -2
  279. package/src/core/websocket/transports/transport.ts +1 -1
  280. package/src/core/websocket/transports/ws.ts +1 -1
  281. package/src/core/websocket/types.ts +11 -1
  282. package/src/core/websocket/useMarimoKernelConnection.tsx +43 -8
  283. package/src/css/app/Cell.css +2 -0
  284. package/src/hooks/useDebounce.ts +2 -0
  285. package/src/plugins/core/BadPlugin.tsx +3 -14
  286. package/src/plugins/core/RenderHTML.tsx +22 -2
  287. package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
  288. package/src/plugins/core/registerReactComponent.tsx +0 -1
  289. package/src/plugins/impl/FormPlugin.tsx +2 -0
  290. package/src/plugins/impl/MatrixPlugin.tsx +2 -0
  291. package/src/plugins/impl/RangeSliderPlugin.tsx +2 -0
  292. package/src/plugins/impl/SliderPlugin.tsx +2 -0
  293. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +23 -18
  294. package/src/plugins/impl/data-frames/panel.tsx +1 -0
  295. package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +1 -1
  296. package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +15 -0
  297. package/src/plugins/layout/AccordionPlugin.tsx +7 -2
  298. package/src/plugins/layout/JsonOutputPlugin.tsx +7 -10
  299. package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
  300. package/src/stories/sandbox.stories.tsx +308 -0
  301. package/dist/ErrorBoundary-CR-ZQN_c.js +0 -125
  302. package/dist/_baseMerge-Dv8bBloN.js +0 -73
  303. package/dist/_initCloneObject---vediN2.js +0 -95
  304. package/dist/arc-DOVLrCPd.js +0 -82
  305. package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
  306. package/dist/array-CApNbSU9.js +0 -6
  307. package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
  308. package/dist/assets/worker-DlIBfp9S.js +0 -98
  309. package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
  310. package/dist/chat-ui-DjTMZRVP.js +0 -8455
  311. package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
  312. package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
  313. package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
  314. package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
  315. package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
  316. package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
  317. package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
  318. package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
  319. package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
  320. package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
  321. package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
  322. package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
  323. package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
  324. package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
  325. package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
  326. package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
  327. package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
  328. package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
  329. package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
  330. package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
  331. package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
  332. package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
  333. package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
  334. package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
  335. package/dist/click-outside-container-D_URcm3D.js +0 -167
  336. package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
  337. package/dist/copy-CD7S58CY.js +0 -141
  338. package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
  339. package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
  340. package/dist/dist-3_o3T78I.js +0 -1360
  341. package/dist/dist-ABQjhuek.js +0 -64
  342. package/dist/dist-CO5R6VMi.js +0 -538
  343. package/dist/dropdown-menu-DhCfcscX.js +0 -5858
  344. package/dist/emotion-is-prop-valid.esm-M57VsT8j.js +0 -14
  345. package/dist/error-banner-CsXbEEjo.js +0 -611
  346. package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
  347. package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
  348. package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
  349. package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
  350. package/dist/line-CuKjIQa1.js +0 -34
  351. package/dist/map-BJpOfPlL.js +0 -149
  352. package/dist/math-BXtKgYah.js +0 -10
  353. package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
  354. package/dist/mermaid-Bi23Ibnw.js +0 -1173
  355. package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
  356. package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
  357. package/dist/path-BNHuHZP8.js +0 -87
  358. package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
  359. package/dist/purify.es-CB-YO1Hn.js +0 -774
  360. package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
  361. package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
  362. package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
  363. package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
  364. package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
  365. package/dist/schemas-DzK6U94N.js +0 -6057
  366. package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
  367. package/dist/step-CKczO72Q.js +0 -670
  368. package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
  369. package/dist/timer-DpDyj9G0.js +0 -596
  370. package/dist/tooltip-Dt77sBeT.js +0 -390
  371. package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
  372. package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
  373. package/dist/useTheme-CVJ0UOf2.js +0 -841
  374. package/dist/vega-loader.browser-DEggZzni.js +0 -1083
  375. package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
  376. package/src/components/editor/output/EmotionCacheProvider.tsx +0 -32
@@ -274,7 +274,6 @@ function PluginSlotInternal<T>(
274
274
  Objects.mapValues(hostElement.dataset, (value) =>
275
275
  typeof value === "string" ? parseAttrValue(value) : value,
276
276
  ),
277
- hostElement.shadowRoot,
278
277
  );
279
278
  }
280
279
 
@@ -219,6 +219,8 @@ const Form = ({
219
219
  // The Form may be rendered before the child plugin is, so after mount
220
220
  // we lookup the plugin once again.
221
221
  useEffect(() => {
222
+ // TODO: Replace the post-mount registry lookup with reactive initialization.
223
+ // oxlint-disable-next-line react/no-deriving-state-in-effects -- The child registry entry may not exist until after the parent mounts.
222
224
  setInternalValue(UI_ELEMENT_REGISTRY.lookupValue(elementId));
223
225
  }, [elementId]);
224
226
 
@@ -126,6 +126,8 @@ const MatrixComponent = ({
126
126
  // which avoids stale-state bugs when the matrix shape changes.
127
127
  const [draft, setDraft] = useState(value);
128
128
  useEffect(() => {
129
+ // TODO: Model the active draft without synchronizing state in an effect.
130
+ // oxlint-disable-next-line react/no-deriving-state-in-effects -- Synchronize the editable draft when the controlled value changes.
129
131
  setDraft(value);
130
132
  }, [value]);
131
133
  const displayValue = activeCell == null ? value : draft;
@@ -90,6 +90,8 @@ const RangeSliderComponent = ({
90
90
 
91
91
  // Update internal value on prop change
92
92
  useEffect(() => {
93
+ // TODO: Replace this synchronization with a controlled-state primitive.
94
+ // oxlint-disable-next-line react/no-deriving-state-in-effects -- Synchronize the editable buffer when the controlled value changes.
93
95
  setInternalValue(value);
94
96
  }, [value]);
95
97
 
@@ -158,6 +158,8 @@ const SliderComponent = ({
158
158
  const [internalValue, setInternalValue] = useState(value);
159
159
  // Update internal value on prop change
160
160
  useEffect(() => {
161
+ // TODO: Replace this synchronization with a controlled-state primitive.
162
+ // oxlint-disable-next-line react/no-deriving-state-in-effects -- Synchronize the editable buffer when the controlled value changes.
161
163
  setInternalValue(value);
162
164
  }, [value]);
163
165
 
@@ -6,31 +6,36 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
6
6
  import { TooltipProvider } from "@/components/ui/tooltip";
7
7
  import { GlideDataEditor } from "../glide-data-editor";
8
8
 
9
- const capturedDataEditor = vi.hoisted(() => ({
10
- ref: undefined as React.RefObject<HTMLElement> | undefined,
11
- onCellEdited: undefined as
12
- | ((cell: [number, number], value: { data: unknown }) => void)
13
- | undefined,
14
- onRowAppended: undefined as (() => void) | undefined,
15
- }));
9
+ interface MockDataEditorProps {
10
+ portalElementRef?: React.RefObject<HTMLElement>;
11
+ onCellEdited?: (cell: [number, number], value: { data: unknown }) => void;
12
+ onRowAppended?: () => void;
13
+ }
14
+
15
+ const captureDataEditorProps = vi.hoisted(() =>
16
+ vi.fn<(props: MockDataEditorProps) => void>(),
17
+ );
18
+
19
+ const capturedDataEditor = {
20
+ get ref() {
21
+ return captureDataEditorProps.mock.lastCall?.[0].portalElementRef;
22
+ },
23
+ get onCellEdited() {
24
+ return captureDataEditorProps.mock.lastCall?.[0].onCellEdited;
25
+ },
26
+ get onRowAppended() {
27
+ return captureDataEditorProps.mock.lastCall?.[0].onRowAppended;
28
+ },
29
+ };
16
30
 
17
31
  vi.mock("@glideapps/glide-data-grid", async () => {
18
32
  const React = await import("react");
19
33
  return {
20
34
  default: React.forwardRef(function MockDataEditor(
21
- props: {
22
- portalElementRef?: React.RefObject<HTMLElement>;
23
- onCellEdited?: (
24
- cell: [number, number],
25
- value: { data: unknown },
26
- ) => void;
27
- onRowAppended?: () => void;
28
- },
35
+ props: MockDataEditorProps,
29
36
  _ref: React.Ref<HTMLDivElement>,
30
37
  ) {
31
- capturedDataEditor.ref = props.portalElementRef;
32
- capturedDataEditor.onCellEdited = props.onCellEdited;
33
- capturedDataEditor.onRowAppended = props.onRowAppended;
38
+ captureDataEditorProps(props);
34
39
  return <div data-testid="mock-data-editor" />;
35
40
  }),
36
41
  CompactSelection: {
@@ -177,6 +177,7 @@ export const TransformPanel: React.FC<Props> = ({
177
177
  return (
178
178
  <ColumnInfoContext value={effectiveColumns}>
179
179
  <ColumnFetchValuesContext value={getColumnValues}>
180
+ {/* oxlint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- Prevent Enter from submitting while using controls in the lazy form. */}
180
181
  <form
181
182
  onSubmit={(e) => e.preventDefault()}
182
183
  // When lazy, prevent Enter from submitting
@@ -41,7 +41,7 @@ const ImageComparisonComponent: React.FC<ImageComparisonData> = ({
41
41
 
42
42
  const containerStyle: React.CSSProperties = {
43
43
  width: width || "100%",
44
- height: height || (direction === "vertical" ? "400px" : "auto"),
44
+ height: height || "auto",
45
45
  maxWidth: "100%",
46
46
  // The slider derives its height entirely from its (loaded) images, so a
47
47
  // broken/slow-loading source would otherwise collapse it to nothing and
@@ -115,6 +115,21 @@ describe("ImageComparisonComponent", () => {
115
115
  }
116
116
  });
117
117
 
118
+ it.each(["horizontal", "vertical"] as const)(
119
+ "lets the container grow to the images when no height is given (%s)",
120
+ (direction) => {
121
+ const { container } = render(
122
+ <ImageComparisonComponent {...baseProps} direction={direction} />,
123
+ );
124
+
125
+ // A fixed height would crop tall images and leave the output's expand
126
+ // button with nothing to reveal.
127
+ const slider = container.querySelector("img-comparison-slider");
128
+ expect(slider).toBeTruthy();
129
+ expect(slider?.parentElement?.style.height).toBe("auto");
130
+ },
131
+ );
132
+
118
133
  it("leaves images unstyled when no dimensions are given", () => {
119
134
  const { getAllByAltText } = render(
120
135
  <ImageComparisonComponent {...baseProps} />,
@@ -23,6 +23,7 @@ interface Data {
23
23
  * Whether to allow multiple tabs to be open.
24
24
  */
25
25
  multiple: boolean;
26
+ expanded: string[];
26
27
  }
27
28
 
28
29
  export class AccordionPlugin implements IStatelessPlugin<Data> {
@@ -31,6 +32,7 @@ export class AccordionPlugin implements IStatelessPlugin<Data> {
31
32
  validator = z.object({
32
33
  labels: z.array(z.string()),
33
34
  multiple: z.boolean(),
35
+ expanded: z.array(z.string()).default([]),
34
36
  });
35
37
 
36
38
  render(props: IStatelessPluginProps<Data>): JSX.Element {
@@ -43,11 +45,14 @@ export class AccordionPlugin implements IStatelessPlugin<Data> {
43
45
  const AccordionComponent = ({
44
46
  labels,
45
47
  multiple,
48
+ expanded,
46
49
  children,
47
50
  }: PropsWithChildren<Data>): JSX.Element => {
48
- const type = multiple ? "multiple" : "single";
51
+ const expansionProps = multiple
52
+ ? { type: "multiple" as const, defaultValue: expanded }
53
+ : { type: "single" as const, defaultValue: expanded[0], collapsible: true };
49
54
  return (
50
- <Accordion type={type} className="text-muted-foreground" collapsible={true}>
55
+ <Accordion {...expansionProps} className="text-muted-foreground">
51
56
  {React.Children.map(children, (child, index) => {
52
57
  return (
53
58
  <AccordionItem key={index} value={index.toString()}>
@@ -2,7 +2,6 @@
2
2
 
3
3
  import type { JSX } from "react";
4
4
  import { z } from "zod";
5
- import { EmotionCacheProvider } from "../../components/editor/output/EmotionCacheProvider";
6
5
  import { JsonOutput } from "../../components/editor/output/JsonOutput";
7
6
  import type {
8
7
  IStatelessPlugin,
@@ -30,18 +29,16 @@ export class JsonOutputPlugin implements IStatelessPlugin<Data> {
30
29
  valueTypes: z.enum(["json", "python"]).default("python"),
31
30
  });
32
31
 
33
- render({ data, host }: IStatelessPluginProps<Data>): JSX.Element {
32
+ render({ data }: IStatelessPluginProps<Data>): JSX.Element {
34
33
  // `false` defaults to no text label
35
34
  const name = data.name === undefined ? false : data.name || "";
36
35
  return (
37
- <EmotionCacheProvider container={host.shadowRoot}>
38
- <JsonOutput
39
- data={data.jsonData}
40
- format="auto"
41
- valueTypes={data.valueTypes}
42
- name={name}
43
- />
44
- </EmotionCacheProvider>
36
+ <JsonOutput
37
+ data={data.jsonData}
38
+ format="auto"
39
+ valueTypes={data.valueTypes}
40
+ name={name}
41
+ />
45
42
  );
46
43
  }
47
44
  }
@@ -0,0 +1,66 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { cleanup, fireEvent, render } from "@testing-library/react";
3
+ import { afterEach, describe, expect, it } from "vitest";
4
+ import { AccordionPlugin } from "../AccordionPlugin";
5
+
6
+ const plugin = new AccordionPlugin();
7
+
8
+ function renderAccordion(multiple: boolean, expanded?: string[]) {
9
+ return plugin.render({
10
+ host: document.createElement("marimo-accordion"),
11
+ data: plugin.validator.parse({
12
+ labels: ["Summary", "Details"],
13
+ multiple,
14
+ expanded,
15
+ }),
16
+ children: [
17
+ <p key="summary">Overview</p>,
18
+ <p key="details">More information</p>,
19
+ ],
20
+ });
21
+ }
22
+
23
+ describe("AccordionPlugin", () => {
24
+ afterEach(cleanup);
25
+
26
+ it.each([
27
+ { multiple: false, expanded: undefined, expected: ["false", "false"] },
28
+ { multiple: true, expanded: [], expected: ["false", "false"] },
29
+ { multiple: false, expanded: ["0"], expected: ["true", "false"] },
30
+ { multiple: false, expanded: ["1"], expected: ["false", "true"] },
31
+ { multiple: true, expanded: ["0", "1"], expected: ["true", "true"] },
32
+ ])(
33
+ "sets initial expansion: $multiple, $expanded",
34
+ ({ multiple, expanded, expected }) => {
35
+ const { getAllByRole } = render(renderAccordion(multiple, expanded));
36
+ expect(
37
+ getAllByRole("button").map((button) =>
38
+ button.getAttribute("aria-expanded"),
39
+ ),
40
+ ).toEqual(expected);
41
+ },
42
+ );
43
+
44
+ it("lets users collapse and switch the initially expanded item", () => {
45
+ const { getAllByRole, rerender } = render(renderAccordion(false, ["1"]));
46
+ const [summary, details] = getAllByRole("button");
47
+ fireEvent.click(details);
48
+ expect(details.getAttribute("aria-expanded")).toBe("false");
49
+ rerender(renderAccordion(false, ["1"]));
50
+ expect(details.getAttribute("aria-expanded")).toBe("false");
51
+ fireEvent.click(details);
52
+ fireEvent.click(summary);
53
+ expect(
54
+ [summary, details].map((button) => button.getAttribute("aria-expanded")),
55
+ ).toEqual(["true", "false"]);
56
+ });
57
+
58
+ it("lets users collapse items independently with multiple enabled", () => {
59
+ const { getAllByRole } = render(renderAccordion(true, ["0", "1"]));
60
+ const [summary, details] = getAllByRole("button");
61
+ fireEvent.click(summary);
62
+ expect(
63
+ [summary, details].map((button) => button.getAttribute("aria-expanded")),
64
+ ).toEqual(["false", "true"]);
65
+ });
66
+ });
@@ -0,0 +1,308 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { createStore, Provider, useAtomValue } from "jotai";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { ConnectionNotice } from "@/components/editor/alerts/connection-notice";
6
+ import {
7
+ SandboxFooter,
8
+ SandboxStartupPanel,
9
+ } from "@/components/editor/chrome/panels/sandbox-panel";
10
+ import { SandboxController } from "@/components/editor/chrome/panels/sandbox-controller";
11
+ import { chromeAtom } from "@/components/editor/chrome/state";
12
+ import { Cell } from "@/components/editor/notebook-cell";
13
+ import { VerticalLayoutWrapper } from "@/components/editor/renderers/vertical-layout/vertical-layout-wrapper";
14
+ import {
15
+ createNotebookActions,
16
+ notebookAtom,
17
+ notebookReducer,
18
+ } from "@/core/cells/cells";
19
+ import { userConfigAtom } from "@/core/config/config";
20
+ import {
21
+ AppConfigSchema,
22
+ defaultUserConfig,
23
+ } from "@/core/config/config-schema";
24
+ import { kernelStartupErrorAtom } from "@/core/errors/state";
25
+ import { connectionAtom } from "@/core/network/connection";
26
+ import { requestClientAtom } from "@/core/network/requests";
27
+ import { createStaticRequests } from "@/core/network/requests-static";
28
+ import {
29
+ sandboxActionsAtom,
30
+ sandboxAtom,
31
+ sandboxSyncAtom,
32
+ } from "@/core/packages/sandbox-state";
33
+ import { filenameAtom } from "@/core/saving/file-state";
34
+ import { WebSocketClosedReason, WebSocketState } from "@/core/websocket/types";
35
+ import { HTTPError } from "@/utils/errors";
36
+
37
+ const manifest = `requires-python = ">=3.13"
38
+ dependencies = ["marimo", "polars", "rich==999.0.0"]
39
+
40
+ [tool.uv]
41
+ index-url = "https://pypi.org/simple"
42
+
43
+ [tool.notebook]
44
+ description = "Explore bike trips"
45
+ `;
46
+ const resolutionError = `No solution found when resolving dependencies:
47
+ Because there is no version of rich==999.0.0 and your script depends
48
+ on rich==999.0.0, your script's requirements are unsatisfiable.`;
49
+
50
+ interface Props {
51
+ surface: "notebook" | "packages" | "manifest";
52
+ phase:
53
+ | "preparing"
54
+ | "starting"
55
+ | "failed"
56
+ | "ready"
57
+ | "syncing"
58
+ | "sync-failed";
59
+ existingCells: boolean;
60
+ backend: "uv" | "pixi";
61
+ saveResult: "success" | "failure" | "stale";
62
+ theme: "light" | "dark";
63
+ }
64
+
65
+ function OpenManifest() {
66
+ const actions = useAtomValue(sandboxActionsAtom);
67
+ const opened = useRef(false);
68
+ useEffect(() => {
69
+ if (actions && !opened.current) {
70
+ opened.current = true;
71
+ void actions.editManifest();
72
+ }
73
+ }, [actions]);
74
+ return null;
75
+ }
76
+
77
+ function SandboxStory(props: Props) {
78
+ const [store] = useState(() => {
79
+ const state = createStore();
80
+ let currentManifest =
81
+ props.phase === "failed"
82
+ ? manifest
83
+ : manifest.replace("rich==999.0.0", "rich>=13.0.0");
84
+ const config = defaultUserConfig();
85
+ state.set(userConfigAtom, {
86
+ ...config,
87
+ display: { ...config.display, theme: props.theme },
88
+ });
89
+ state.set(filenameAtom, "bike_trips.py");
90
+ state.set(sandboxAtom, {
91
+ backend: props.backend,
92
+ manifest: currentManifest,
93
+ filename: "bike_trips.py",
94
+ });
95
+ state.set(chromeAtom, {
96
+ selectedPanel: "packages",
97
+ isSidebarOpen: props.surface !== "notebook",
98
+ isDeveloperPanelOpen: false,
99
+ selectedDeveloperPanelTab: "errors",
100
+ });
101
+ state.set(
102
+ connectionAtom,
103
+ props.phase === "preparing" || props.phase === "starting"
104
+ ? {
105
+ state: WebSocketState.CONNECTING,
106
+ phase:
107
+ props.phase === "preparing"
108
+ ? "preparing-environment"
109
+ : "starting-kernel",
110
+ }
111
+ : props.phase === "failed"
112
+ ? {
113
+ state: WebSocketState.CLOSED,
114
+ code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
115
+ reason: "Kernel startup failed",
116
+ phase: "preparing-environment",
117
+ }
118
+ : { state: WebSocketState.OPEN },
119
+ );
120
+ state.set(
121
+ kernelStartupErrorAtom,
122
+ props.phase === "failed" ? resolutionError : null,
123
+ );
124
+ state.set(sandboxSyncAtom, {
125
+ pending: props.phase === "syncing",
126
+ error: props.phase === "sync-failed" ? resolutionError : null,
127
+ });
128
+ if (props.existingCells) {
129
+ const actions = createNotebookActions((action) =>
130
+ state.set(notebookAtom, (value) => notebookReducer(value, action)),
131
+ );
132
+ actions.createNewCell({
133
+ cellId: "__end__",
134
+ before: false,
135
+ code: 'import polars as pl\n\ntrips = pl.read_csv("bike_trips.csv")\ntrips.head()',
136
+ autoFocus: false,
137
+ });
138
+ }
139
+ state.set(requestClientAtom, {
140
+ ...createStaticRequests(),
141
+ getSandbox: async () => ({
142
+ backend: props.backend,
143
+ manifest: currentManifest,
144
+ filename: "bike_trips.py",
145
+ }),
146
+ updateManifest: async ({ contents }) => {
147
+ if (props.saveResult === "stale") {
148
+ throw new HTTPError(
149
+ 409,
150
+ "The manifest changed on disk. Reopen it before saving.",
151
+ );
152
+ }
153
+ currentManifest = contents;
154
+ return {
155
+ backend: props.backend,
156
+ manifest: currentManifest,
157
+ filename: "bike_trips.py",
158
+ };
159
+ },
160
+ syncSandbox: async () => {
161
+ await new Promise((resolve) => setTimeout(resolve, 2000));
162
+ if (props.saveResult === "failure") {
163
+ return {
164
+ success: false,
165
+ error:
166
+ "Failed to download rich from https://pypi.org/simple/rich/\n Request failed after 3 retries: connection timed out",
167
+ restartRequired: false,
168
+ reconnect: false,
169
+ };
170
+ }
171
+ state.set(connectionAtom, { state: WebSocketState.OPEN });
172
+ state.set(kernelStartupErrorAtom, null);
173
+ return {
174
+ success: true,
175
+ error: null,
176
+ restartRequired: false,
177
+ reconnect: false,
178
+ };
179
+ },
180
+ });
181
+ return state;
182
+ });
183
+ const appConfig = AppConfigSchema.parse({ width: "full" });
184
+ const reconnect = async () => {
185
+ store.set(connectionAtom, { state: WebSocketState.OPEN });
186
+ };
187
+ return (
188
+ <Provider store={store}>
189
+ <SandboxController onReconnect={reconnect} />
190
+ {props.surface === "manifest" && <OpenManifest />}
191
+ <div
192
+ data-testid="sandbox-story"
193
+ className="bg-background text-foreground"
194
+ style={{
195
+ width: props.surface === "notebook" ? 820 : 400,
196
+ }}
197
+ >
198
+ {props.surface === "notebook" && (
199
+ <>
200
+ <ConnectionNotice appConfig={appConfig} onRetry={reconnect} />
201
+ {store.get(notebookAtom).cellIds.inOrderIds.map((cellId) => (
202
+ <VerticalLayoutWrapper key={cellId} appConfig={appConfig}>
203
+ <Cell
204
+ cellId={cellId}
205
+ theme={props.theme}
206
+ mode="edit"
207
+ showPlaceholder={false}
208
+ canDelete={true}
209
+ isCollapsed={false}
210
+ collapseCount={0}
211
+ canMoveX={false}
212
+ userConfig={store.get(userConfigAtom)}
213
+ />
214
+ </VerticalLayoutWrapper>
215
+ ))}
216
+ </>
217
+ )}
218
+ {props.surface === "packages" &&
219
+ (props.phase === "failed" ||
220
+ props.phase === "sync-failed" ||
221
+ props.phase === "preparing" ? (
222
+ <SandboxStartupPanel />
223
+ ) : (
224
+ <SandboxFooter />
225
+ ))}
226
+ </div>
227
+ </Provider>
228
+ );
229
+ }
230
+
231
+ const meta = {
232
+ title: "Sandbox/States",
233
+ component: SandboxStory,
234
+ parameters: { layout: "centered" },
235
+ args: {
236
+ surface: "notebook",
237
+ phase: "preparing",
238
+ existingCells: true,
239
+ backend: "uv",
240
+ saveResult: "success",
241
+ theme: "light",
242
+ },
243
+ render: (args, context) => (
244
+ <SandboxStory
245
+ key={JSON.stringify([args, context.globals.theme])}
246
+ {...args}
247
+ theme={context.globals.theme === "dark" ? "dark" : "light"}
248
+ />
249
+ ),
250
+ } satisfies Meta<typeof SandboxStory>;
251
+ export default meta;
252
+ type Story = StoryObj<typeof meta>;
253
+
254
+ export const ExistingNotebookPreparing: Story = {
255
+ name: "Startup notice / preparing",
256
+ };
257
+ export const EmptyNotebookPreparing: Story = {
258
+ name: "Empty notebook / preparing",
259
+ args: { existingCells: false },
260
+ };
261
+ export const StartingKernel: Story = {
262
+ name: "Startup notice / starting kernel",
263
+ args: { phase: "starting" },
264
+ };
265
+ export const ExistingNotebookFailed: Story = {
266
+ name: "Startup notice / failed",
267
+ args: { phase: "failed" },
268
+ };
269
+ export const EmptyNotebookFailed: Story = {
270
+ name: "Empty notebook / failed",
271
+ args: { phase: "failed", existingCells: false },
272
+ };
273
+ export const PackagesPreparing: Story = {
274
+ name: "Setup details / preparing",
275
+ args: { surface: "packages" },
276
+ };
277
+ export const PackagesFailed: Story = {
278
+ name: "Setup details / failed",
279
+ args: { surface: "packages", phase: "failed" },
280
+ };
281
+ export const PackagesReady: Story = {
282
+ name: "Status row / ready",
283
+ args: { surface: "packages", phase: "ready" },
284
+ };
285
+ export const PackagesSyncing: Story = {
286
+ name: "Status row / syncing",
287
+ args: { surface: "packages", phase: "syncing" },
288
+ };
289
+ export const PackagesSyncFailed: Story = {
290
+ name: "Setup details / sync failed",
291
+ args: { surface: "packages", phase: "sync-failed" },
292
+ };
293
+ export const PixiPackagesReady: Story = {
294
+ name: "Status row / pixi",
295
+ args: { surface: "packages", phase: "ready", backend: "pixi" },
296
+ };
297
+ export const ManifestEditor: Story = {
298
+ name: "Manifest / edit",
299
+ args: { surface: "manifest", phase: "failed" },
300
+ };
301
+ export const ManifestSyncFails: Story = {
302
+ name: "Manifest / failed save",
303
+ args: { surface: "manifest", phase: "failed", saveResult: "failure" },
304
+ };
305
+ export const ManifestChangedOnDisk: Story = {
306
+ name: "Manifest / changed on disk",
307
+ args: { surface: "manifest", phase: "failed", saveResult: "stale" },
308
+ };