@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.
- package/dist/{ConnectedDataExplorerComponent-C9OF_75w.js → ConnectedDataExplorerComponent-KVhjDMSe.js} +1066 -1066
- package/dist/ErrorBoundary-BW0xr_AR.js +200 -0
- package/dist/{ImageComparisonComponent-2a9TMMm2.js → ImageComparisonComponent-Dlm5aWnH.js} +4 -4
- package/dist/{Plot-C-9MQeGP.js → Plot-CTyjbQDT.js} +21032 -20666
- package/dist/_baseMerge-BiGRwuqv.js +165 -0
- package/dist/{abnfDiagram-N423BO3Z-CQKwzX8t.js → abnfDiagram-VCTEODGH-CpN0FRda.js} +17 -18
- package/dist/{any-language-editor-DmQ7dyCx.js → any-language-editor-CycIVIeP.js} +17 -17
- package/dist/arc-7ra3iNdN.js +81 -0
- package/dist/architecture-7GRP2DOG-BWLylgiA.js +3 -0
- package/dist/{architectureDiagram-T3A2C74G-CncrDpfa.js → architectureDiagram-5GKGNRK7-DDyj5SRB.js} +25 -25
- package/dist/assets/__vite-browser-external-BajL8aoc.js +1 -0
- package/dist/assets/worker-BemUy60C.js +109 -0
- package/dist/blockDiagram-I7D4REHJ-BbXEXJRu.js +1922 -0
- package/dist/{button-CKBkqR9J.js → button-DdXAm8iz.js} +5 -5
- package/dist/{c4Diagram-5PPSVZJV-DarUk3Yq.js → c4Diagram-7LVT6UL2-DcLsbQmR.js} +696 -668
- package/dist/{capabilities-CMBBJTcc.js → capabilities-B3ce_GNu.js} +1 -1
- package/dist/{html-to-image-BhNoIBSU.js → cells-BSgNCBZ8.js} +6740 -10126
- package/dist/{channel-CyiYUzJv.js → channel-B5XnTarr.js} +1 -1
- package/dist/chat-ui-CygzVJ9s.js +5786 -0
- package/dist/{check-CHig47QV.js → check-B7cIK6gb.js} +1 -1
- package/dist/{chunk-2Q5K7J3B-BMuJl2jB.js → chunk-2Q5K7J3B-BMkUkeuy.js} +2 -2
- package/dist/chunk-4HAMMTFA-D2qv8E0X.js +4188 -0
- package/dist/{chunk-5VM5RSS4-Bcq0ftdy.js → chunk-5VM5RSS4-DKsmPCL6.js} +2 -2
- package/dist/{chunk-NSK5VX7P-CDTMcJB0.js → chunk-75Z2AOVW-5_HsvXwr.js} +23 -23
- package/dist/{chunk-I66GZJ75-BqyTCAPf.js → chunk-DU6HZSFF-BUgAHvnM.js} +21 -4
- package/dist/{chunk-2GRJ4B5K-DgO8Qudq.js → chunk-F27PBJKO-DHmYWZXr.js} +4 -4
- package/dist/{chunk-KEIR6QF5-C4KX3XYh.js → chunk-FOHPRMQF-BpYR8RqP.js} +4 -4
- package/dist/{chunk-WRU74C26-BpWsbiDK.js → chunk-GMAD6QVW-Czynz8aA.js} +486 -258
- package/dist/chunk-GVQU2GXP-yQEdulRS.js +37 -0
- package/dist/{chunk-5RXB4S5H-tLNUVDdO.js → chunk-IMKFNOWR-BfwTebD0.js} +11 -11
- package/dist/{chunk-JWPE2WC7-BJwjGUnF.js → chunk-JWPE2WC7-DJvv1t8U.js} +2 -2
- package/dist/chunk-L3NEJ4N5-DwRWnDDK.js +245 -0
- package/dist/{chunk-7Z6QIM7H-Dc18hFxH.js → chunk-OSK3NFVY-BBKU_Ign.js} +222 -144
- package/dist/{chunk-W5SLKNZC-DLnvpEtV.js → chunk-P2QGCYS3-C0iGU29N.js} +20 -20
- package/dist/{chunk-KBJHAD2P-BuqWqkcW.js → chunk-POPQ4Y6H-BCbS3Ozc.js} +4 -4
- package/dist/{chunk-4I5QYGJK-DpytHuZQ.js → chunk-PWAF6VOD-CTFCL0jI.js} +4 -4
- package/dist/{chunk-JQJVKLGR-CgqCwe8E.js → chunk-SHT3W25Y-BspJEJ5H.js} +109 -63
- package/dist/{chunk-6Q2QTUOP-DmTcEBMn.js → chunk-SVP7TREG-DX3rFNTe.js} +5 -5
- package/dist/{chunk-GF5L2VYU-B0wgCQgS.js → chunk-TICWLB2K-fVF7Uujg.js} +13 -13
- package/dist/{chunk-XXDRQBXY-D73H4IN0.js → chunk-XXDRQBXY-Dnl5VBqG.js} +3 -3
- package/dist/{chunk-Y2CYZVJY-DoegUj_e.js → chunk-Y2CYZVJY-DKKS1VyV.js} +1 -1
- package/dist/{chunk-5FQGJX7Z-B85XCPv6.js → chunk-YOKDWASO-DrWbKnxA.js} +6925 -5460
- package/dist/classDiagram-ZZMXUADV-Fe-V14Sc.js +30 -0
- package/dist/classDiagram-v2-VYDZK3BY-xTDg7lOs.js +30 -0
- package/dist/code-visibility-BdKqYmPi.js +138 -0
- package/dist/{common-xHoep60C.js → common-D9PY0k7A.js} +8839 -12646
- package/dist/{compiler-runtime-CAH9RLw2.js → compiler-runtime-Cj8ZWiNS.js} +2 -2
- package/dist/copy-icon-CLdENY__.js +190 -0
- package/dist/{cose-bilkent-JH36ORCC-FUWHkXFX.js → cose-bilkent-JH36ORCC-_LyRKVqm.js} +2 -2
- package/dist/cubic-OaEBhQPK.js +1404 -0
- package/dist/cynefin-OW5HDTMX-obq-i80l.js +3 -0
- package/dist/{cynefinDiagram-MW4NZA55-BXSFK93J.js → cynefinDiagram-5FMLGOSQ-CFQrqzSX.js} +10 -10
- package/dist/{dagre-CGyalH38.js → dagre-BGSfXNEb.js} +678 -537
- package/dist/dagre-GXQ25YYZ-xHNAUTyG.js +425 -0
- package/dist/{data-grid-overlay-editor-DZM4BAaI.js → data-grid-overlay-editor-BZiw7m3d.js} +8 -9
- package/dist/{data-grid-types-BnZwWG8z.js → data-grid-types-BucVmDDp.js} +1 -1
- package/dist/{defaultLocale-DKaU_opG.js → defaultLocale-JI_lnoCe.js} +1 -1
- package/dist/{diagram-7IWD3JNH-BjfzDNvj.js → diagram-S7CK7UJ4-Bt1rPbAx.js} +40 -39
- package/dist/{diagram-UB23O5K3-DDg-7wLA.js → diagram-UQ7AKVKN-D1sq5FoZ.js} +10 -10
- package/dist/{diagram-B4RE2ZJO-CKccR9eE.js → diagram-VSXAHHWV-BKpmG23x.js} +10 -10
- package/dist/{diagram-Q27KOJAE-Zhz01ss7.js → diagram-VX7I27RA-BMwGFVD6.js} +21 -21
- package/dist/{diagram-LBJQPF4R-CJ-bOruh.js → diagram-Z3DM3KII--KLDR9Pl.js} +10 -10
- package/dist/dialog-CgNq6y9-.js +94 -0
- package/dist/{dist-dAqZAPcF.js → dist-1HDa70oE.js} +3 -3
- package/dist/{dist-Re9sOPOx.js → dist-9x1ZRe-e.js} +2 -2
- package/dist/{dist-DEeLqRlU.js → dist-B1vYLK28.js} +1 -1
- package/dist/{dist-C5Bn52W4.js → dist-B8D7McG3.js} +3 -3
- package/dist/{dist-_XvgytiS.js → dist-BHCHt1NI.js} +1 -1
- package/dist/{dist-CRjAdnqF.js → dist-BRxfaJgs.js} +3 -3
- package/dist/{dist-Byj2bV8o.js → dist-BVGtK7Ht.js} +1 -1
- package/dist/{dist-BIN5LKyE.js → dist-BaHjhkpZ.js} +2 -2
- package/dist/{dist-DVFbIwc5.js → dist-BtKIs9N-.js} +1 -1
- package/dist/{dist-BrQGcfQ9.js → dist-C2KzV-vf.js} +2 -2
- package/dist/{dist-DJFiGP2k.js → dist-C2wDlYdD.js} +2 -2
- package/dist/{dist-BVRM2y1P.js → dist-C8xMLVYi.js} +2 -2
- package/dist/dist-CMh_W4y4.js +538 -0
- package/dist/{extends-BPB6_lTK.js → dist-CO1AwwG_.js} +516 -561
- package/dist/{dist-BzN60Z2s.js → dist-CPGxfVGX.js} +1 -1
- package/dist/{dist-C7v-9nUK.js → dist-Cm3iAFMD.js} +3 -3
- package/dist/{dist-CGAxEiaM.js → dist-Cs2FijYk.js} +2 -2
- package/dist/{dist-hXd65f0_.js → dist-D1PpnuZB.js} +1 -1
- package/dist/{dist-VdvbxG72.js → dist-DHOTQar0.js} +1 -1
- package/dist/{dist-DcgzXCfy.js → dist-DPcEtqmG.js} +2 -2
- package/dist/{dist-D4Z_qdP4.js → dist-Df0wKI0F.js} +1 -1
- package/dist/{dist-qhLI-SHd.js → dist-DszxuxS1.js} +2 -2
- package/dist/{dist-BEmkrGoQ.js → dist-Kxgjxakw.js} +1 -1
- package/dist/{dist-BbSMhhD2.js → dist-KzZ7WELx.js} +2 -2
- package/dist/{dist-jWUab2d1.js → dist-lA1Cttkb.js} +1 -1
- package/dist/dropdown-menu-CZgjYSAh.js +4502 -0
- package/dist/{ebnfDiagram-BXEA7PRR-Dm75pCAS.js → ebnfDiagram-PWID7BFC-WnG4cvSQ.js} +17 -18
- package/dist/{erDiagram-JOGREHBK-rVDG3VSQ.js → erDiagram-RLTQ6QDP-DhzKiYHc.js} +1037 -798
- package/dist/error-banner-B94dcDmP.js +391 -0
- package/dist/error-entries-iJn-Nryx.js +56 -0
- package/dist/{esm-CR1nhb1c.js → esm-BElI3qKH.js} +22 -22
- package/dist/{esm-C1d0g6Bv.js → esm-G4Fhsgng.js} +51 -37
- package/dist/{esm-CesmlDrs.js → esm-h8f7-1CJ.js} +423 -423
- package/dist/eventmodeling-NTZA5JFV-D7nP7Uyu.js +3 -0
- package/dist/feedback-button-BAHeJT2Q.js +380 -0
- package/dist/flowDiagram-HODETNUW-6dMdB8pR.js +16 -0
- package/dist/{formats-CJMVUfb3.js → formats-BR5iGb4s.js} +8 -8
- package/dist/{ganttDiagram-PKOTCBZU-9D-LXF6P.js → ganttDiagram-EL5Y4UJY-DbzEBLbl.js} +15 -15
- package/dist/gitGraph-4MIJSDKK-Dy9uQXGh.js +3 -0
- package/dist/{gitGraphDiagram-DS77QQ5N-BfpsXTLf.js → gitGraphDiagram-WWUBYQGX-BMf0iKi1.js} +10 -10
- package/dist/{glide-data-editor-sPZ8fUFn.js → glide-data-editor-Bp9hhneH.js} +2143 -1910
- package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
- package/dist/globals-BUgvsAck.js +19 -0
- package/dist/highlighted-body-KPVGNVTW-Ad3MKZ18.js +38 -0
- package/dist/html-to-image-kpuRfdfZ.js +3253 -0
- package/dist/info-A6RAGUB7-DKoayiHY.js +3 -0
- package/dist/{infoDiagram-6WML65LV-DqCTXHVy.js → infoDiagram-27XIBGKW-BagtCX_5.js} +7 -7
- package/dist/{ishikawaDiagram-WSZJBQD7-BCUYmZ1v.js → ishikawaDiagram-5VMMS53U-DByDehYy.js} +8 -8
- package/dist/{journeyDiagram-NVQOT4AX-BXB6M4zN.js → journeyDiagram-3NMN7TZE-D2LcKDUO.js} +8 -8
- package/dist/{jsx-runtime-CpoKNRgu.js → jsx-runtime-DgDPJV9S.js} +1 -1
- package/dist/{kanban-definition-27J2QSJJ-CGRhrDUX.js → kanban-definition-UXKFOSKX-BxwkbBI_.js} +29 -29
- package/dist/katex-DFBiSucW.js +21840 -0
- package/dist/{label-lwzzBHUW.js → label-BJ49YTvk.js} +6 -6
- package/dist/{linear-D5r_1YqD.js → linear-Cnaq3Tfb.js} +4 -4
- package/dist/{loader-VZ__bv4g.js → loader-D2W4oM-3.js} +15 -15
- package/dist/main.js +8105 -13485
- package/dist/mermaid-DPNuhemn.js +3084 -0
- package/dist/mermaid-HWGCJPDP-DYCzSILp.js +2 -0
- package/dist/mermaid-parser.core-DxuSfYwJ.js +638 -0
- package/dist/{mhchem-BjwrxcV-.js → mhchem-DWCF06w9.js} +1 -1
- package/dist/{micromark-factory-space-DruVGzeG.js → micromark-factory-space-DGxAzmw8.js} +2 -2
- package/dist/{mindmap-definition-FAOFIHXS-C9gRhzZq.js → mindmap-definition-YA3MSWOX-Cgvojw3y.js} +17 -17
- package/dist/{node-sql-parser-DesT1xNw.js → node-sql-parser-BiZOJ-FS.js} +0 -3
- package/dist/{number-overlay-editor-De2CabLL.js → number-overlay-editor-C743iqsh.js} +5 -5
- package/dist/objectWithoutPropertiesLoose-BRDcTsfB.js +23 -0
- package/dist/packet-AYTQ26CC-Yw7ajchJ.js +3 -0
- package/dist/{pegDiagram-VL7TDLO6-Df9IUjMD.js → pegDiagram-XKGWAZYB-DahHhYyN.js} +19 -20
- package/dist/{pick-SnHlmIBN.js → pick-CJeoxYOS.js} +1 -1
- package/dist/pie-WAS4IAKB-BKdKOAkL.js +3 -0
- package/dist/{pieDiagram-7S7Q4E2Y-BmRzQ8ZP.js → pieDiagram-E7YTZNPT-CCtX0oCK.js} +29 -31
- package/dist/{process-output-CpK6fX_C.js → process-output-DFe2tVIY.js} +7 -6
- package/dist/purify.es-DgKyQviY.js +805 -0
- package/dist/{quadrantDiagram-CIZ2JOQS-wFBvWcxS.js → quadrantDiagram-AXDQQJYC-DftINo6g.js} +5 -5
- package/dist/radar-RG4KPBEZ-ScR_D_Ts.js +3 -0
- package/dist/railroad-74A4TZTK-DQvPSdo5.js +3 -0
- package/dist/railroad-abnf-HS5TGJTU-CsJQG2O8.js +3 -0
- package/dist/railroad-ebnf-LZEXJU2U-BgEobkSn.js +3 -0
- package/dist/railroad-peg-WCYAUIDC-DjLAjofI.js +3 -0
- package/dist/{railroadDiagram-AXF67PYL-DxbIatiN.js → railroadDiagram-O6MQD6OU-Du5NsPUb.js} +17 -18
- package/dist/{react-dom-C94wmq5w.js → react-dom-BUgJ-ab_.js} +3 -3
- package/dist/{react-DMWcHin-.js → react-ofJbxM4x.js} +2 -2
- package/dist/{react-vega-DSD5aT7_.js → react-vega-5AcMW8gG.js} +10012 -9369
- package/dist/{requirementDiagram-LRYGKXZP-X_x-Y713.js → requirementDiagram-BXWQKSXE-0pmmxL6_.js} +20 -19
- package/dist/{reveal-component-DwuC-61O.js → reveal-component-CgMzL2w5.js} +1303 -1237
- package/dist/{sankeyDiagram-W5VNT64P-BYJALbbm.js → sankeyDiagram-P5KCCOFB-CDKR5TJH.js} +4 -4
- package/dist/{select-3qHpFKF9.js → select-C6plhmZr.js} +317 -562
- package/dist/{sequenceDiagram-SI44F4Z6-BiPBe3Sv.js → sequenceDiagram-WJ2MYXX4-DB-ChWwU.js} +11 -11
- package/dist/{sizeCapture-X5ZJPWSS-BKLDeh5H.js → sizeCapture-INFHLROL-Dx5SpkQF.js} +2 -2
- package/dist/{spec-CutWdqo3.js → spec-CAYwFeV6.js} +4 -4
- package/dist/{src-C31ngt98.js → src-CA_m4ONl.js} +298 -303
- package/dist/{stateDiagram-OKZ733FA-B7QyNBxH.js → stateDiagram-D77RDMKH-orN6AwMx.js} +19 -20
- package/dist/stateDiagram-v2-MP3YSRHH-o05_rJN8.js +30 -0
- package/dist/style.css +2 -2
- package/dist/{swimlanes-SLNWSIFB-B4f8VP3b.js → swimlanes-42K2YHIH-BkSDcqDT.js} +1501 -1591
- package/dist/swimlanesDiagram-VR7AAH4N-D_nFQfRc.js +30 -0
- package/dist/{swiper-component-C90YjhaV.js → swiper-component-IOUowglM.js} +39 -26
- package/dist/{time-aWGfjN8x.js → time-BieKwdYS.js} +42 -42
- package/dist/{timeline-definition-Z64GVDOM-Dacq_5lr.js → timeline-definition-24CTP7MA-BuqJUIRZ.js} +7 -7
- package/dist/{toDate-D-Rx3ux5.js → toDate-WXg1yLcI.js} +10 -9
- package/dist/toast-DvY70eFX.js +1834 -0
- package/dist/tooltip-qB8NlSqV.js +1742 -0
- package/dist/treeView-Q6P3EWNA-DuRV97YF.js +3 -0
- package/dist/treemap-WGGIJYW6-AsLq-uwC.js +3 -0
- package/dist/use-restore-focus-D5D9xEjZ.js +5946 -0
- package/dist/{use-vega-container-remeasure-DUW4tRxq.js → use-vega-container-remeasure-4DwJbPWu.js} +2 -2
- package/dist/{useAsyncData-CH6-CgJF.js → useAsyncData-BD6AStMt.js} +3 -3
- package/dist/{useDateFormatter-Cp9Jdxls.js → useDateFormatter-BRTPsUK7.js} +8 -8
- package/dist/{useDeepCompareMemoize-JC87C_jO.js → useDeepCompareMemoize-D_HNdyvI.js} +2 -2
- package/dist/{useIframeCapabilities-De3C-9b4.js → useIframeCapabilities-CVtNkI3Y.js} +2 -2
- package/dist/{useLifecycle-B4RGlyf0.js → useLifecycle-DPgiiwwU.js} +6 -6
- package/dist/useNumberFormatter-BfDpa21j.js +251 -0
- package/dist/useTheme-DzXmYZ5V.js +904 -0
- package/dist/{vega-component-CPehZbUb.js → vega-component-D0QXopU8.js} +34 -34
- package/dist/{vega-embed-container-TJ5z5dZw.js → vega-embed-container-CbnTccZi.js} +6 -6
- package/dist/vega-loader.browser-D95WfUcj.js +1139 -0
- package/dist/{vennDiagram-T6HMQDX7-D-Rcq3Iu.js → vennDiagram-4TSXK5OY-CTUlJ2PK.js} +9 -9
- package/dist/wardley-WFR3VGLG-Na-tFhQJ.js +3 -0
- package/dist/{wardleyDiagram-T6FBY63Y-Z-Og7_Wd.js → wardleyDiagram-VM6X3IG4-3evLUb0M.js} +10 -10
- package/dist/{xychartDiagram-ELKLHX3M-BDJ2dITA.js → xychartDiagram-S5SC5T6Z-DL2E3K8-.js} +248 -139
- package/package.json +54 -57
- package/src/__mocks__/requests.ts +7 -0
- package/src/__tests__/__snapshots__/CellStatus.test.tsx.snap +12 -12
- package/src/components/chat/acp/__tests__/agent-panel.test.tsx +270 -0
- package/src/components/chat/acp/agent-panel.tsx +45 -44
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -6
- package/src/components/data-table/column-summary/chart-spec-model.tsx +1 -1
- package/src/components/data-table/columns.tsx +64 -67
- package/src/components/editor/RecoveryButton.tsx +1 -0
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
- package/src/components/editor/ai/add-cell-with-ai.tsx +1 -0
- package/src/components/editor/ai/ai-completion-editor.tsx +3 -1
- package/src/components/editor/alerts/connecting-alert.tsx +1 -66
- package/src/components/editor/alerts/connection-notice.tsx +140 -0
- package/src/components/editor/app-container.tsx +9 -3
- package/src/components/editor/boundary/ErrorBoundary.tsx +38 -16
- package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +311 -0
- package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +50 -0
- package/src/components/editor/cell/code/cell-editor.tsx +41 -42
- package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +94 -0
- package/src/components/editor/chrome/components/feedback-button.tsx +63 -42
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +114 -7
- package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +165 -0
- package/src/components/editor/chrome/panels/packages-panel.tsx +93 -166
- package/src/components/editor/chrome/panels/sandbox-controller.tsx +106 -0
- package/src/components/editor/chrome/panels/sandbox-panel.tsx +173 -0
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +3 -1
- package/src/components/editor/code/__tests__/readonly-diff.test.tsx +65 -0
- package/src/components/editor/code/readonly-diff.tsx +1 -1
- package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +98 -98
- package/src/components/editor/connections/database/__tests__/as-code.test.ts +11 -5
- package/src/components/editor/dynamic-favicon.tsx +17 -10
- package/src/components/editor/file-tree/__tests__/tree-actions.test.tsx +54 -0
- package/src/components/editor/file-tree/tree-actions.tsx +11 -14
- package/src/components/editor/header/__tests__/status.test.tsx +8 -20
- package/src/components/editor/header/filename-input.tsx +2 -0
- package/src/components/editor/header/status.tsx +5 -3
- package/src/components/editor/notebook-cell.tsx +4 -2
- package/src/components/editor/output/JsonOutput.tsx +182 -632
- package/src/components/editor/output/Outputs.css +50 -17
- package/src/components/editor/output/__tests__/JsonOutput-interactions.test.tsx +254 -0
- package/src/components/editor/output/__tests__/JsonOutput-mimetype.test.tsx +41 -46
- package/src/components/editor/output/__tests__/{json-output.test.ts → json-output-formatting.test.ts} +113 -75
- package/src/components/editor/output/__tests__/json-output-pagination.test.ts +252 -0
- package/src/components/editor/output/json-output/formatting.ts +167 -0
- package/src/components/editor/output/json-output/pagination.ts +155 -0
- package/src/components/editor/output/json-output/renderers.tsx +196 -0
- package/src/components/editor/output/json-output/themes.ts +52 -0
- package/src/components/editor/renderers/cell-array.tsx +1 -5
- package/src/components/home/components.tsx +17 -0
- package/src/components/pages/gallery-page.tsx +2 -4
- package/src/components/pages/home-page.tsx +2 -4
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/slides/slide-notes-editor.tsx +1 -0
- package/src/components/terminal/terminal.tsx +4 -4
- package/src/components/tracing/tracing-spec.ts +1 -1
- package/src/components/ui/table.tsx +1 -1
- package/src/components/ui/use-toast.ts +8 -0
- package/src/core/MarimoApp.tsx +0 -2
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +259 -259
- package/src/core/cells/__tests__/cell.test.ts +61 -0
- package/src/core/cells/__tests__/cells.test.ts +37 -37
- package/src/core/cells/cell.ts +9 -1
- package/src/core/cells/pending-delete-service.ts +12 -16
- package/src/core/codemirror/language/__tests__/sql.test.ts +70 -2
- package/src/core/codemirror/language/languages/sql/sql.ts +16 -1
- package/src/core/codemirror/rtc/extension.ts +5 -2
- package/src/core/datasets/__tests__/data-source.test.ts +2 -0
- package/src/core/datasets/data-source-connections.ts +15 -10
- package/src/core/edit-app.tsx +8 -5
- package/src/core/errors/state.ts +1 -2
- package/src/core/islands/__tests__/parse.test.ts +140 -7
- package/src/core/islands/bootstrap.ts +1 -0
- package/src/core/islands/bridge.ts +3 -0
- package/src/core/islands/parse.ts +20 -0
- package/src/core/network/connection-notice.ts +84 -0
- package/src/core/network/requests-lazy.ts +3 -0
- package/src/core/network/requests-network.ts +12 -0
- package/src/core/network/requests-static.ts +3 -0
- package/src/core/network/requests-toasting.tsx +3 -0
- package/src/core/network/resolve.ts +2 -1
- package/src/core/network/types.ts +7 -0
- package/src/core/packages/__tests__/usePackageAction.test.tsx +129 -0
- package/src/core/packages/__tests__/useSandboxController.test.tsx +165 -0
- package/src/core/packages/package-data.ts +35 -0
- package/src/core/packages/sandbox-state.ts +15 -0
- package/src/core/packages/toast-components.tsx +11 -0
- package/src/core/packages/useInstallPackage.ts +1 -1
- package/src/core/packages/usePackageAction.ts +51 -0
- package/src/core/packages/usePackageDependencies.ts +22 -0
- package/src/core/packages/useSandboxController.ts +188 -0
- package/src/core/run-app.tsx +2 -0
- package/src/core/runtime/__tests__/runtime.test.ts +11 -0
- package/src/core/runtime/runtime.ts +7 -2
- package/src/core/wasm/bridge.ts +11 -0
- package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +212 -2
- package/src/core/websocket/transports/transport.ts +1 -1
- package/src/core/websocket/transports/ws.ts +1 -1
- package/src/core/websocket/types.ts +11 -1
- package/src/core/websocket/useMarimoKernelConnection.tsx +43 -8
- package/src/css/app/Cell.css +2 -0
- package/src/hooks/useDebounce.ts +2 -0
- package/src/plugins/core/BadPlugin.tsx +3 -14
- package/src/plugins/core/RenderHTML.tsx +22 -2
- package/src/plugins/core/__test__/RenderHTML.test.ts +187 -0
- package/src/plugins/core/registerReactComponent.tsx +0 -1
- package/src/plugins/impl/FormPlugin.tsx +2 -0
- package/src/plugins/impl/MatrixPlugin.tsx +2 -0
- package/src/plugins/impl/RangeSliderPlugin.tsx +2 -0
- package/src/plugins/impl/SliderPlugin.tsx +2 -0
- package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +23 -18
- package/src/plugins/impl/data-frames/panel.tsx +1 -0
- package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +1 -1
- package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +15 -0
- package/src/plugins/layout/AccordionPlugin.tsx +7 -2
- package/src/plugins/layout/JsonOutputPlugin.tsx +7 -10
- package/src/plugins/layout/__test__/AccordionPlugin.test.tsx +66 -0
- package/src/stories/sandbox.stories.tsx +308 -0
- package/dist/ErrorBoundary-CR-ZQN_c.js +0 -125
- package/dist/_baseMerge-Dv8bBloN.js +0 -73
- package/dist/_initCloneObject---vediN2.js +0 -95
- package/dist/arc-DOVLrCPd.js +0 -82
- package/dist/architecture-TIHT7OUA-MiJpPpQW.js +0 -3
- package/dist/array-CApNbSU9.js +0 -6
- package/dist/assets/__vite-browser-external-BdKGjRZ4.js +0 -1
- package/dist/assets/worker-DlIBfp9S.js +0 -98
- package/dist/blockDiagram-VBNYF7ZC-Bc--I65C.js +0 -3158
- package/dist/chat-ui-DjTMZRVP.js +0 -8455
- package/dist/chunk-3NCLNEKW-BIp_lB_4.js +0 -14
- package/dist/chunk-5FCAYU7R-C_HO9A1J.js +0 -23
- package/dist/chunk-5HE753X5-Bixm_MV-.js +0 -38
- package/dist/chunk-5JV3BV7I-CH5J3iZY.js +0 -54
- package/dist/chunk-5TONJI2A-DG6gDiSS.js +0 -62
- package/dist/chunk-7BUUIJ7U-5afmIPeo.js +0 -82
- package/dist/chunk-BIQX33UG-7TMBUf89.js +0 -23
- package/dist/chunk-CQNSW5MT-Cnqqsxt-.js +0 -38
- package/dist/chunk-CYSBUYHQ-BAbymFHR.js +0 -23
- package/dist/chunk-EMLP6XTP-Bsz-QL77.js +0 -23
- package/dist/chunk-J7OUQ5F2-CM_meqZH.js +0 -57
- package/dist/chunk-JG7HCLWE-DUnCDgPk.js +0 -62
- package/dist/chunk-MOZMSUNE-BG6IHvzT.js +0 -35
- package/dist/chunk-OSBZ3O6U-CYwj_bvR.js +0 -23
- package/dist/chunk-QBLGF6JB-B4vJ4j8J.js +0 -23
- package/dist/chunk-QR6OTTB3-D4wH2ldi.js +0 -3738
- package/dist/chunk-R7FJI6CG-Blf8FcmZ.js +0 -64
- package/dist/chunk-RYQCIY6F-BWbIlBIH.js +0 -241
- package/dist/chunk-U6XO7XAA-COw445DS.js +0 -63
- package/dist/chunk-UBXNYLIW-BHigVU4H.js +0 -32
- package/dist/chunk-YOTPTUD7-Dn044Q_d.js +0 -30
- package/dist/chunk-ZIRB5QZD-BR4TMfOa.js +0 -1153
- package/dist/classDiagram-JCYQIIEL-DmXSLxe_.js +0 -30
- package/dist/classDiagram-v2-OCEON4UE-CooqVexA.js +0 -30
- package/dist/click-outside-container-D_URcm3D.js +0 -167
- package/dist/code-block-37QAKDTI-CQrzBOr-.js +0 -107
- package/dist/copy-CD7S58CY.js +0 -141
- package/dist/cynefin-VYW2F7L2-CeHAxOEX.js +0 -3
- package/dist/dagre-VZM6K2ZE-CJggWPTJ.js +0 -328
- package/dist/dist-3_o3T78I.js +0 -1360
- package/dist/dist-ABQjhuek.js +0 -64
- package/dist/dist-CO5R6VMi.js +0 -538
- package/dist/dropdown-menu-DhCfcscX.js +0 -5858
- package/dist/emotion-is-prop-valid.esm-M57VsT8j.js +0 -14
- package/dist/error-banner-CsXbEEjo.js +0 -611
- package/dist/eventmodeling-45OFAUF4-B_lWZ-Pd.js +0 -3
- package/dist/flowDiagram-UKHOOZJN-g1AmrZzM.js +0 -17
- package/dist/gitGraph-TEB2WS4Q-Dj-eXUph.js +0 -3
- package/dist/info-DKCQHKI2-Bhb-pe2e.js +0 -3
- package/dist/line-CuKjIQa1.js +0 -34
- package/dist/map-BJpOfPlL.js +0 -149
- package/dist/math-BXtKgYah.js +0 -10
- package/dist/mermaid-4DMBBIKO-Ddp9TgNp.js +0 -2
- package/dist/mermaid-Bi23Ibnw.js +0 -1173
- package/dist/mermaid-parser.core-Din9FvSi.js +0 -99
- package/dist/packet-7NZHBO7P-fbkIIyKE.js +0 -3
- package/dist/path-BNHuHZP8.js +0 -87
- package/dist/pie-RZYD4A2V-CLRIsxY1.js +0 -3
- package/dist/purify.es-CB-YO1Hn.js +0 -774
- package/dist/radar-I7S5WNFK-BGzCbgXu.js +0 -3
- package/dist/railroad-3IZDKUUU-CvQIIcuU.js +0 -3
- package/dist/railroad-abnf-AHOZXSZD-CMwtlNtu.js +0 -3
- package/dist/railroad-ebnf-EBAXGLYW-n1QUOAsh.js +0 -3
- package/dist/railroad-peg-LSFZ7HO6-PjnrpmCs.js +0 -3
- package/dist/schemas-DzK6U94N.js +0 -6057
- package/dist/stateDiagram-v2-UEYNNEHI-BTRUs8Il.js +0 -30
- package/dist/step-CKczO72Q.js +0 -670
- package/dist/swimlanesDiagram-ULZ7WXOC-NBmgBl9G.js +0 -31
- package/dist/timer-DpDyj9G0.js +0 -596
- package/dist/tooltip-Dt77sBeT.js +0 -390
- package/dist/treeView-QDETBFTQ-DU8LwHuf.js +0 -3
- package/dist/treemap-6X3UGDF4-DUk4-k_O.js +0 -3
- package/dist/useTheme-CVJ0UOf2.js +0 -841
- package/dist/vega-loader.browser-DEggZzni.js +0 -1083
- package/dist/wardley-OPB4EBWU-Db-AaGas.js +0 -3
- package/src/components/editor/output/EmotionCacheProvider.tsx +0 -32
package/src/core/edit-app.tsx
CHANGED
|
@@ -9,7 +9,8 @@ import { useAtomValue, useSetAtom } from "jotai";
|
|
|
9
9
|
import { useEffect } from "react";
|
|
10
10
|
import { NotStartedConnectionAlert } from "@/components/editor/alerts/connecting-alert";
|
|
11
11
|
import { Controls } from "@/components/editor/controls/Controls";
|
|
12
|
-
import {
|
|
12
|
+
import { SandboxController } from "@/components/editor/chrome/panels/sandbox-controller";
|
|
13
|
+
import { ConnectionNotice } from "@/components/editor/alerts/connection-notice";
|
|
13
14
|
import { FilenameForm } from "@/components/editor/header/filename-form";
|
|
14
15
|
import { MultiCellActionToolbar } from "@/components/editor/navigation/multi-cell-action-toolbar";
|
|
15
16
|
import { ViewerBanner } from "@/components/editor/viewer-banner";
|
|
@@ -158,6 +159,7 @@ export const EditApp: React.FC<AppProps> = ({
|
|
|
158
159
|
|
|
159
160
|
return (
|
|
160
161
|
<>
|
|
162
|
+
<SandboxController onReconnect={reconnect} />
|
|
161
163
|
<AppContainer
|
|
162
164
|
connection={connection}
|
|
163
165
|
isRunning={isRunning}
|
|
@@ -165,10 +167,9 @@ export const EditApp: React.FC<AppProps> = ({
|
|
|
165
167
|
onReconnect={reconnect}
|
|
166
168
|
>
|
|
167
169
|
<ViewerBanner />
|
|
168
|
-
<
|
|
169
|
-
connection={connection}
|
|
170
|
+
<div
|
|
170
171
|
className={cn(
|
|
171
|
-
"pt-4 sm:pt-12 pb-
|
|
172
|
+
"pt-4 sm:pt-12 pb-6 print:hidden z-50",
|
|
172
173
|
// Keep the header sticky when scrolling horizontally, for column mode
|
|
173
174
|
"sticky left-0",
|
|
174
175
|
)}
|
|
@@ -178,7 +179,9 @@ export const EditApp: React.FC<AppProps> = ({
|
|
|
178
179
|
<FilenameForm filename={filename} />
|
|
179
180
|
</div>
|
|
180
181
|
)}
|
|
181
|
-
</
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<ConnectionNotice appConfig={appConfig} onRetry={reconnect} />
|
|
182
185
|
|
|
183
186
|
{/* Don't render until we have a single cell. NotStartedConnectionAlert
|
|
184
187
|
still covers the "no remote runtime started" prompt. */}
|
package/src/core/errors/state.ts
CHANGED
|
@@ -7,8 +7,7 @@ import { generateUUID } from "@/utils/uuid";
|
|
|
7
7
|
import type { Banner } from "../kernel/messages";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* When set to a non-null value, shows a modal with the error details.
|
|
10
|
+
* Full startup diagnostics, retained until a new connection attempt or readiness.
|
|
12
11
|
*/
|
|
13
12
|
export const kernelStartupErrorAtom = atom<string | null>(null);
|
|
14
13
|
|
|
@@ -19,6 +19,13 @@ import {
|
|
|
19
19
|
} from "../parse";
|
|
20
20
|
import { createMockIslandElement, createMockIslands } from "./test-utils.tsx";
|
|
21
21
|
|
|
22
|
+
function islandSnapshotPath(filename: string): string {
|
|
23
|
+
return new URL(
|
|
24
|
+
`../../../../../tests/_islands/snapshots/${filename}`,
|
|
25
|
+
import.meta.url,
|
|
26
|
+
).pathname.replace(/^\/@fs/, "");
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
function createPayloadCell(
|
|
23
30
|
overrides: Partial<{
|
|
24
31
|
cellId: string;
|
|
@@ -47,6 +54,7 @@ function appendPayload(
|
|
|
47
54
|
payload: {
|
|
48
55
|
schemaVersion: number;
|
|
49
56
|
appId: string;
|
|
57
|
+
dependencies?: unknown;
|
|
50
58
|
cells: ReturnType<typeof createPayloadCell>[];
|
|
51
59
|
},
|
|
52
60
|
) {
|
|
@@ -58,6 +66,33 @@ function appendPayload(
|
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
describe("createMarimoFile", () => {
|
|
69
|
+
it("should serialize dependencies as top-level script metadata", () => {
|
|
70
|
+
const file = createMarimoFile({
|
|
71
|
+
dependencies: ['cowsay==6.1; sys_platform == "emscripten"'],
|
|
72
|
+
cells: [{ code: "import cowsay" }],
|
|
73
|
+
});
|
|
74
|
+
expect(file).toBe(
|
|
75
|
+
[
|
|
76
|
+
"# /// script",
|
|
77
|
+
'# dependencies = ["cowsay==6.1; sys_platform == \\"emscripten\\""]',
|
|
78
|
+
"# ///",
|
|
79
|
+
"import marimo",
|
|
80
|
+
"app = marimo.App()",
|
|
81
|
+
"@app.cell",
|
|
82
|
+
"def __():",
|
|
83
|
+
" import cowsay",
|
|
84
|
+
" return",
|
|
85
|
+
].join("\n"),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("should omit metadata for empty dependencies", () => {
|
|
90
|
+
const cells = [{ code: "import cowsay" }];
|
|
91
|
+
expect(createMarimoFile({ cells, dependencies: [] })).toBe(
|
|
92
|
+
createMarimoFile({ cells }),
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
61
96
|
it("should return a string", () => {
|
|
62
97
|
const app = {
|
|
63
98
|
cells: [
|
|
@@ -736,13 +771,7 @@ describe("parseMarimoIslandApps", () => {
|
|
|
736
771
|
});
|
|
737
772
|
|
|
738
773
|
it("should parse Python-generated island payload snapshots", () => {
|
|
739
|
-
const html = readFileSync(
|
|
740
|
-
new URL(
|
|
741
|
-
"../../../../../tests/_islands/snapshots/html-payload.txt",
|
|
742
|
-
import.meta.url,
|
|
743
|
-
).pathname.replace(/^\/@fs/, ""),
|
|
744
|
-
"utf8",
|
|
745
|
-
);
|
|
774
|
+
const html = readFileSync(islandSnapshotPath("html-payload.txt"), "utf8");
|
|
746
775
|
container.innerHTML = html;
|
|
747
776
|
|
|
748
777
|
const result = parseMarimoIslandApps(container);
|
|
@@ -775,6 +804,108 @@ describe("parseMarimoIslandApps", () => {
|
|
|
775
804
|
expect(islands[2].getAttribute(ISLAND_DATA_ATTRIBUTES.CELL_IDX)).toBe("1");
|
|
776
805
|
});
|
|
777
806
|
|
|
807
|
+
it("should restore metadata from a Python-generated dependency payload", () => {
|
|
808
|
+
container.innerHTML = readFileSync(
|
|
809
|
+
islandSnapshotPath("body-dependencies.txt"),
|
|
810
|
+
"utf8",
|
|
811
|
+
);
|
|
812
|
+
|
|
813
|
+
const probed = parseMarimoIslandApps(container, { materialize: false });
|
|
814
|
+
const apps = parseMarimoIslandApps(container);
|
|
815
|
+
|
|
816
|
+
expect(probed).toEqual(apps);
|
|
817
|
+
expect(apps).toEqual([
|
|
818
|
+
{
|
|
819
|
+
id: "main",
|
|
820
|
+
payloadBacked: true,
|
|
821
|
+
dependencies: [
|
|
822
|
+
'cowsay==6.1; sys_platform == "emscripten"',
|
|
823
|
+
"rich[jupyter]>=13",
|
|
824
|
+
"desktop; sys_platform != 'emscripten'",
|
|
825
|
+
"older-python; python_version < '3.13'",
|
|
826
|
+
"newer-python; python_version >= '3.13'",
|
|
827
|
+
],
|
|
828
|
+
cells: [{ cellId: "Hbol", code: "import cowsay", output: "", idx: 0 }],
|
|
829
|
+
},
|
|
830
|
+
]);
|
|
831
|
+
// The Python Pyodide test reads this file with the real metadata parser.
|
|
832
|
+
expect(createMarimoFile(apps[0])).toBe(
|
|
833
|
+
readFileSync(islandSnapshotPath("notebook-dependencies.txt"), "utf8"),
|
|
834
|
+
);
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it("should carry dependencies from payloads into each generated notebook", () => {
|
|
838
|
+
for (const [appId, dependencies] of [
|
|
839
|
+
["app1", ["cowsay==6.1"]],
|
|
840
|
+
["app2", ["rich[jupyter]>=13"]],
|
|
841
|
+
] as const) {
|
|
842
|
+
container.appendChild(
|
|
843
|
+
createMockIslandElement({ appId, cellId: "cell-1" }),
|
|
844
|
+
);
|
|
845
|
+
appendPayload(container, {
|
|
846
|
+
schemaVersion: 1,
|
|
847
|
+
appId,
|
|
848
|
+
dependencies,
|
|
849
|
+
cells: [createPayloadCell()],
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
const apps = parseMarimoIslandApps(container);
|
|
854
|
+
expect(apps.map((app) => [app.id, app.dependencies])).toEqual([
|
|
855
|
+
["app1", ["cowsay==6.1"]],
|
|
856
|
+
["app2", ["rich[jupyter]>=13"]],
|
|
857
|
+
]);
|
|
858
|
+
expect(createMarimoFile(apps[0])).toContain(
|
|
859
|
+
'# /// script\n# dependencies = ["cowsay==6.1"]\n# ///\n',
|
|
860
|
+
);
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
it.each([null, "cowsay", [123], ["cowsay", null]])(
|
|
864
|
+
"should ignore payloads with malformed dependencies: %j",
|
|
865
|
+
(dependencies) => {
|
|
866
|
+
const island = createMockIslandElement({
|
|
867
|
+
appId: "app1",
|
|
868
|
+
cellId: "cell-1",
|
|
869
|
+
code: "import cowsay",
|
|
870
|
+
innerHTML: "<div>dom</div>",
|
|
871
|
+
});
|
|
872
|
+
island.setAttribute(ISLAND_DATA_ATTRIBUTES.REACTIVE, "true");
|
|
873
|
+
container.appendChild(island);
|
|
874
|
+
appendPayload(container, {
|
|
875
|
+
schemaVersion: 1,
|
|
876
|
+
appId: "app1",
|
|
877
|
+
dependencies,
|
|
878
|
+
cells: [createPayloadCell()],
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
expect(parseMarimoIslandApps(container)).toEqual([
|
|
882
|
+
{
|
|
883
|
+
id: "app1",
|
|
884
|
+
cells: [{ code: "import cowsay", output: "<div>dom</div>", idx: 0 }],
|
|
885
|
+
},
|
|
886
|
+
]);
|
|
887
|
+
},
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
it("should merge dependencies from payloads belonging to the same app", () => {
|
|
891
|
+
for (const [cellId, dependencies] of [
|
|
892
|
+
["cell-1", ["cowsay"]],
|
|
893
|
+
["cell-2", ["cowsay", "rich"]],
|
|
894
|
+
] as const) {
|
|
895
|
+
container.appendChild(createMockIslandElement({ appId: "app1", cellId }));
|
|
896
|
+
appendPayload(container, {
|
|
897
|
+
schemaVersion: 1,
|
|
898
|
+
appId: "app1",
|
|
899
|
+
dependencies,
|
|
900
|
+
cells: [createPayloadCell({ cellId })],
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
expect(
|
|
905
|
+
parseMarimoIslandApps(container).map((app) => app.dependencies),
|
|
906
|
+
).toEqual([["cowsay", "rich"]]);
|
|
907
|
+
});
|
|
908
|
+
|
|
778
909
|
it("should fall back to DOM islands for unsupported payload versions", () => {
|
|
779
910
|
const island = createMockIslandElement({
|
|
780
911
|
appId: "app1",
|
|
@@ -990,6 +1121,7 @@ describe("parseMarimoIslandApps", () => {
|
|
|
990
1121
|
outputHtml: "<div>payload only</div>",
|
|
991
1122
|
}),
|
|
992
1123
|
],
|
|
1124
|
+
dependencies: ["cowsay"],
|
|
993
1125
|
});
|
|
994
1126
|
|
|
995
1127
|
const result = parseMarimoIslandApps(container);
|
|
@@ -1076,6 +1208,7 @@ describe("parseMarimoIslandApps", () => {
|
|
|
1076
1208
|
reactive: false,
|
|
1077
1209
|
}),
|
|
1078
1210
|
],
|
|
1211
|
+
dependencies: ["cowsay"],
|
|
1079
1212
|
});
|
|
1080
1213
|
|
|
1081
1214
|
const result = parseMarimoIslandApps(container);
|
|
@@ -370,6 +370,9 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
370
370
|
addPackage = throwNotImplemented;
|
|
371
371
|
removePackage = throwNotImplemented;
|
|
372
372
|
getPackageList = throwNotImplemented;
|
|
373
|
+
getSandbox = throwNotImplemented;
|
|
374
|
+
updateManifest = throwNotImplemented;
|
|
375
|
+
syncSandbox = throwNotImplemented;
|
|
373
376
|
getDependencyTree = throwNotImplemented;
|
|
374
377
|
getRecentFiles = throwNotImplemented;
|
|
375
378
|
getWorkspaceFiles = throwNotImplemented;
|
|
@@ -30,6 +30,8 @@ export interface MarimoIslandApp {
|
|
|
30
30
|
* Whether cells came from a supported JSON payload instead of DOM parsing.
|
|
31
31
|
*/
|
|
32
32
|
payloadBacked?: boolean;
|
|
33
|
+
/** Explicit notebook dependencies to install before starting the app. */
|
|
34
|
+
dependencies?: string[];
|
|
33
35
|
/**
|
|
34
36
|
* Cells in the app.
|
|
35
37
|
*/
|
|
@@ -62,6 +64,7 @@ interface MarimoIslandCell {
|
|
|
62
64
|
interface MarimoIslandPayload {
|
|
63
65
|
schemaVersion: 1;
|
|
64
66
|
appId: string;
|
|
67
|
+
dependencies?: string[];
|
|
65
68
|
cells: MarimoIslandPayloadCell[];
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -235,6 +238,12 @@ function parsePayloadBackedApps({
|
|
|
235
238
|
embed?.setAttribute(ISLAND_DATA_ATTRIBUTES.CELL_IDX, idx.toString());
|
|
236
239
|
}
|
|
237
240
|
}
|
|
241
|
+
const app = apps.get(payload.appId);
|
|
242
|
+
if (app && payload.dependencies?.length) {
|
|
243
|
+
app.dependencies = [
|
|
244
|
+
...new Set([...(app.dependencies ?? []), ...payload.dependencies]),
|
|
245
|
+
];
|
|
246
|
+
}
|
|
238
247
|
}
|
|
239
248
|
|
|
240
249
|
// A supported payload is the runtime source for its app. Extra same-app DOM
|
|
@@ -371,6 +380,7 @@ export function parseIslandElement(
|
|
|
371
380
|
|
|
372
381
|
export function createMarimoFile(app: {
|
|
373
382
|
cells: { code: string; disabled?: boolean }[];
|
|
383
|
+
dependencies?: string[];
|
|
374
384
|
}): string {
|
|
375
385
|
const lines = [
|
|
376
386
|
"import marimo",
|
|
@@ -402,6 +412,13 @@ export function createMarimoFile(app: {
|
|
|
402
412
|
.join("\n"),
|
|
403
413
|
];
|
|
404
414
|
|
|
415
|
+
if (app.dependencies?.length) {
|
|
416
|
+
lines.unshift(
|
|
417
|
+
"# /// script",
|
|
418
|
+
`# dependencies = ${JSON.stringify(app.dependencies)}`,
|
|
419
|
+
"# ///",
|
|
420
|
+
);
|
|
421
|
+
}
|
|
405
422
|
return lines.join("\n");
|
|
406
423
|
}
|
|
407
424
|
|
|
@@ -507,6 +524,9 @@ function isMarimoIslandPayload(
|
|
|
507
524
|
return (
|
|
508
525
|
payload.schemaVersion === 1 &&
|
|
509
526
|
typeof payload.appId === "string" &&
|
|
527
|
+
(payload.dependencies === undefined ||
|
|
528
|
+
(Array.isArray(payload.dependencies) &&
|
|
529
|
+
payload.dependencies.every((dep) => typeof dep === "string"))) &&
|
|
510
530
|
Array.isArray(payload.cells) &&
|
|
511
531
|
payload.cells.every(isMarimoIslandPayloadCell)
|
|
512
532
|
);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { atom } from "jotai";
|
|
3
|
+
import { kernelStartupErrorAtom } from "@/core/errors/state";
|
|
4
|
+
import { sandboxAtom, sandboxSyncAtom } from "@/core/packages/sandbox-state";
|
|
5
|
+
import { WebSocketClosedReason, WebSocketState } from "@/core/websocket/types";
|
|
6
|
+
import { connectionAtom } from "./connection";
|
|
7
|
+
|
|
8
|
+
export const connectionNoticeAtom = atom((get) => {
|
|
9
|
+
const connection = get(connectionAtom);
|
|
10
|
+
const backend = get(sandboxAtom)?.backend;
|
|
11
|
+
const sandbox = Boolean(backend);
|
|
12
|
+
const sync = get(sandboxSyncAtom);
|
|
13
|
+
if (
|
|
14
|
+
sandbox &&
|
|
15
|
+
(sync.pending || sync.error) &&
|
|
16
|
+
connection.state === WebSocketState.OPEN
|
|
17
|
+
) {
|
|
18
|
+
return {
|
|
19
|
+
sandbox,
|
|
20
|
+
title: sync.pending ? "Syncing sandbox…" : "Sandbox sync failed",
|
|
21
|
+
description: sync.pending
|
|
22
|
+
? "Applying the saved manifest to this notebook’s environment."
|
|
23
|
+
: "Review the error details, then try again.",
|
|
24
|
+
pending: sync.pending,
|
|
25
|
+
error: sync.error,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (connection.state === WebSocketState.CONNECTING) {
|
|
29
|
+
const messages = {
|
|
30
|
+
"preparing-environment": {
|
|
31
|
+
title: backend
|
|
32
|
+
? `Preparing ${backend} sandbox…`
|
|
33
|
+
: "Preparing environment…",
|
|
34
|
+
description:
|
|
35
|
+
"Getting this notebook’s Python environment ready. The first start can take a few minutes.",
|
|
36
|
+
},
|
|
37
|
+
"starting-kernel": {
|
|
38
|
+
title: "Starting notebook…",
|
|
39
|
+
description:
|
|
40
|
+
"The environment is prepared. Waiting for the Python kernel to connect to this notebook.",
|
|
41
|
+
},
|
|
42
|
+
reconnecting: {
|
|
43
|
+
title: "Reconnecting…",
|
|
44
|
+
description:
|
|
45
|
+
"The connection was interrupted. Your notebook and existing outputs stay visible while the kernel reconnects.",
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
sandbox,
|
|
50
|
+
...(connection.phase
|
|
51
|
+
? messages[connection.phase]
|
|
52
|
+
: {
|
|
53
|
+
title: "Connecting…",
|
|
54
|
+
description: "Waiting for the notebook’s kernel to connect.",
|
|
55
|
+
}),
|
|
56
|
+
pending: true,
|
|
57
|
+
error: null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (connection.state === WebSocketState.CLOSED) {
|
|
61
|
+
const startupFailed =
|
|
62
|
+
connection.code === WebSocketClosedReason.KERNEL_STARTUP_ERROR;
|
|
63
|
+
const environmentFailed =
|
|
64
|
+
startupFailed && connection.phase === "preparing-environment";
|
|
65
|
+
return {
|
|
66
|
+
sandbox,
|
|
67
|
+
title: environmentFailed
|
|
68
|
+
? "Sandbox setup failed"
|
|
69
|
+
: startupFailed
|
|
70
|
+
? "Kernel failed to start"
|
|
71
|
+
: connection.reason,
|
|
72
|
+
description: environmentFailed
|
|
73
|
+
? "The notebook can’t run yet."
|
|
74
|
+
: startupFailed
|
|
75
|
+
? "The Python kernel could not start. Check the error details, then try again."
|
|
76
|
+
: "The connection to the notebook’s kernel was lost.",
|
|
77
|
+
pending: false,
|
|
78
|
+
error: startupFailed
|
|
79
|
+
? (get(kernelStartupErrorAtom) ?? connection.reason)
|
|
80
|
+
: null,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
});
|
|
@@ -93,6 +93,9 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
|
93
93
|
saveUserConfig: "throwError",
|
|
94
94
|
sendShutdown: "throwError",
|
|
95
95
|
getPackageList: "throwError",
|
|
96
|
+
getSandbox: "serverOnly",
|
|
97
|
+
updateManifest: "serverOnly",
|
|
98
|
+
syncSandbox: "serverOnly",
|
|
96
99
|
getDependencyTree: "throwError",
|
|
97
100
|
addPackage: "throwError",
|
|
98
101
|
removePackage: "throwError",
|
|
@@ -532,6 +532,18 @@ export function createNetworkRequests(): EditRequests & RunRequests {
|
|
|
532
532
|
})
|
|
533
533
|
.then(handleResponseReturnNull);
|
|
534
534
|
},
|
|
535
|
+
getSandbox: (request) =>
|
|
536
|
+
getClient()
|
|
537
|
+
.POST("/api/packages/sandbox", { body: request, params: getParams() })
|
|
538
|
+
.then(handleResponse),
|
|
539
|
+
updateManifest: (request) =>
|
|
540
|
+
getClient()
|
|
541
|
+
.POST("/api/packages/manifest", { body: request, params: getParams() })
|
|
542
|
+
.then(handleResponse),
|
|
543
|
+
syncSandbox: (request) =>
|
|
544
|
+
getClient()
|
|
545
|
+
.POST("/api/packages/sync", { body: request, params: getParams() })
|
|
546
|
+
.then(handleResponse),
|
|
535
547
|
addPackage: (request) => {
|
|
536
548
|
return getClient()
|
|
537
549
|
.POST("/api/packages/add", {
|
|
@@ -98,6 +98,9 @@ export function createStaticRequests(): EditRequests & RunRequests {
|
|
|
98
98
|
addPackage: throwNotInEditMode,
|
|
99
99
|
removePackage: throwNotInEditMode,
|
|
100
100
|
getPackageList: throwNotInEditMode,
|
|
101
|
+
getSandbox: throwNotInEditMode,
|
|
102
|
+
updateManifest: throwNotInEditMode,
|
|
103
|
+
syncSandbox: throwNotInEditMode,
|
|
101
104
|
getDependencyTree: throwNotInEditMode,
|
|
102
105
|
listSecretKeys: throwNotInEditMode,
|
|
103
106
|
writeSecret: throwNotInEditMode,
|
|
@@ -79,6 +79,9 @@ export function createErrorToastingRequests(
|
|
|
79
79
|
addPackage: "Failed to add package",
|
|
80
80
|
removePackage: "Failed to remove package",
|
|
81
81
|
getPackageList: "Failed to get package list",
|
|
82
|
+
getSandbox: "",
|
|
83
|
+
updateManifest: "",
|
|
84
|
+
syncSandbox: "",
|
|
82
85
|
getDependencyTree: "Failed to get dependency tree",
|
|
83
86
|
listSecretKeys: "Failed to fetch secrets",
|
|
84
87
|
writeSecret: "Failed to write secret",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { withPackageInvalidation } from "../packages/package-data";
|
|
2
3
|
import { getRuntimeManager } from "../runtime/config";
|
|
3
4
|
import { isStaticNotebook } from "../static/static-state";
|
|
4
5
|
import { PyodideBridge } from "../wasm/bridge";
|
|
@@ -20,5 +21,5 @@ export function resolveRequestClient(): EditRequests & RunRequests {
|
|
|
20
21
|
getRuntimeManager(),
|
|
21
22
|
);
|
|
22
23
|
}
|
|
23
|
-
return createErrorToastingRequests(base);
|
|
24
|
+
return withPackageInvalidation(createErrorToastingRequests(base));
|
|
24
25
|
}
|
|
@@ -69,6 +69,10 @@ export type ListPackagesResponse = schemas["ListPackagesResponse"];
|
|
|
69
69
|
export type DependencyTreeResponse = schemas["DependencyTreeResponse"];
|
|
70
70
|
export type DependencyTreeNode = schemas["DependencyTreeNode"];
|
|
71
71
|
|
|
72
|
+
export type SandboxRequest = schemas["SandboxRequest"];
|
|
73
|
+
export type SandboxResponse = schemas["SandboxResponse"];
|
|
74
|
+
export type UpdateManifestRequest = schemas["UpdateManifestRequest"];
|
|
75
|
+
export type SyncSandboxResponse = schemas["SyncSandboxResponse"];
|
|
72
76
|
export type PackageOperationResponse = schemas["PackageOperationResponse"];
|
|
73
77
|
export type InstantiateNotebookRequest = schemas["InstantiateNotebookRequest"];
|
|
74
78
|
export type MarimoConfig = schemas["MarimoConfig"];
|
|
@@ -246,6 +250,9 @@ export interface EditRequests {
|
|
|
246
250
|
autoExportAsMarkdown: (request: AutoExportAsMarkdownRequest) => Promise<null>;
|
|
247
251
|
autoExportAsIPYNB: (request: AutoExportAsIPYNBRequest) => Promise<null>;
|
|
248
252
|
updateCellOutputs: (request: UpdateCellOutputsRequest) => Promise<null>;
|
|
253
|
+
getSandbox: (request: SandboxRequest) => Promise<SandboxResponse>;
|
|
254
|
+
updateManifest: (request: UpdateManifestRequest) => Promise<SandboxResponse>;
|
|
255
|
+
syncSandbox: (request: SandboxRequest) => Promise<SyncSandboxResponse>;
|
|
249
256
|
// Package requests
|
|
250
257
|
getPackageList: () => Promise<ListPackagesResponse>;
|
|
251
258
|
getDependencyTree: () => Promise<DependencyTreeResponse>;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { act, renderHook } from "@testing-library/react";
|
|
3
|
+
import { createStore, Provider } from "jotai";
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { MockRequestClient } from "@/__mocks__/requests";
|
|
6
|
+
import { toast } from "@/components/ui/use-toast";
|
|
7
|
+
import { requestClientAtom } from "@/core/network/requests";
|
|
8
|
+
import type { PackageOperationResponse } from "@/core/network/types";
|
|
9
|
+
import { usePackageAction } from "../usePackageAction";
|
|
10
|
+
|
|
11
|
+
vi.mock("@/components/ui/use-toast", () => ({ toast: vi.fn() }));
|
|
12
|
+
|
|
13
|
+
function setup(action: "upgrade" | "remove") {
|
|
14
|
+
const client = MockRequestClient.create();
|
|
15
|
+
const store = createStore();
|
|
16
|
+
store.set(requestClientAtom, client);
|
|
17
|
+
return {
|
|
18
|
+
request: vi.mocked(
|
|
19
|
+
action === "upgrade" ? client.addPackage : client.removePackage,
|
|
20
|
+
),
|
|
21
|
+
...renderHook(
|
|
22
|
+
() =>
|
|
23
|
+
usePackageAction(action, "numpy", [{ kind: "group", value: "dev" }]),
|
|
24
|
+
{
|
|
25
|
+
wrapper: ({ children }) => (
|
|
26
|
+
<Provider store={store}>{children}</Provider>
|
|
27
|
+
),
|
|
28
|
+
},
|
|
29
|
+
),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe("usePackageAction", () => {
|
|
34
|
+
beforeEach(() => vi.clearAllMocks());
|
|
35
|
+
|
|
36
|
+
it.each([
|
|
37
|
+
{ action: "upgrade", title: "Package upgraded", upgrade: true },
|
|
38
|
+
{ action: "remove", title: "Package removed" },
|
|
39
|
+
] as const)(
|
|
40
|
+
"preserves dependency groups and prevents duplicate $action requests",
|
|
41
|
+
async ({ action, title, ...options }) => {
|
|
42
|
+
const { result, request } = setup(action);
|
|
43
|
+
const { promise, resolve } =
|
|
44
|
+
Promise.withResolvers<PackageOperationResponse>();
|
|
45
|
+
request.mockReturnValue(promise);
|
|
46
|
+
let pending: Promise<void>;
|
|
47
|
+
act(() => {
|
|
48
|
+
pending = result.current.run();
|
|
49
|
+
});
|
|
50
|
+
expect(result.current.loading).toBe(true);
|
|
51
|
+
await act(async () => {
|
|
52
|
+
await result.current.run();
|
|
53
|
+
});
|
|
54
|
+
expect(request).toHaveBeenCalledExactlyOnceWith({
|
|
55
|
+
package: "numpy",
|
|
56
|
+
group: "dev",
|
|
57
|
+
...options,
|
|
58
|
+
});
|
|
59
|
+
await act(async () => {
|
|
60
|
+
resolve({ success: true });
|
|
61
|
+
await pending;
|
|
62
|
+
});
|
|
63
|
+
expect(result.current.loading).toBe(false);
|
|
64
|
+
expect(toast).toHaveBeenCalledExactlyOnceWith(
|
|
65
|
+
expect.objectContaining({ title }),
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
it("reports saved changes requiring a restart without claiming success", async () => {
|
|
71
|
+
const { result, request } = setup("upgrade");
|
|
72
|
+
request.mockResolvedValue({ success: false, restartRequired: true });
|
|
73
|
+
await act(async () => {
|
|
74
|
+
await result.current.run();
|
|
75
|
+
});
|
|
76
|
+
expect(toast).toHaveBeenCalledExactlyOnceWith(
|
|
77
|
+
expect.objectContaining({
|
|
78
|
+
title: "Changes saved — restart required",
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it.each([
|
|
84
|
+
{
|
|
85
|
+
response: { success: false, error: "resolver failed" },
|
|
86
|
+
description: "resolver failed",
|
|
87
|
+
},
|
|
88
|
+
{ response: { success: false }, description: expect.any(String) },
|
|
89
|
+
])(
|
|
90
|
+
"reports failed responses as errors: $response",
|
|
91
|
+
async ({ response, description }) => {
|
|
92
|
+
const { result, request } = setup("remove");
|
|
93
|
+
request.mockResolvedValue(response);
|
|
94
|
+
await act(async () => {
|
|
95
|
+
await result.current.run();
|
|
96
|
+
});
|
|
97
|
+
expect(toast).toHaveBeenCalledExactlyOnceWith(
|
|
98
|
+
expect.objectContaining({
|
|
99
|
+
title: "Failed to remove package",
|
|
100
|
+
description,
|
|
101
|
+
variant: "danger",
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
},
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
it("reports request errors and allows a retry", async () => {
|
|
108
|
+
const { result, request } = setup("remove");
|
|
109
|
+
request.mockRejectedValueOnce(new Error("offline"));
|
|
110
|
+
await act(async () => {
|
|
111
|
+
await result.current.run();
|
|
112
|
+
});
|
|
113
|
+
expect(toast).toHaveBeenCalledExactlyOnceWith(
|
|
114
|
+
expect.objectContaining({
|
|
115
|
+
title: "Failed to remove package",
|
|
116
|
+
description: "offline",
|
|
117
|
+
variant: "danger",
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
expect(result.current.loading).toBe(false);
|
|
121
|
+
request.mockResolvedValue({ success: true });
|
|
122
|
+
await act(async () => {
|
|
123
|
+
await result.current.run();
|
|
124
|
+
});
|
|
125
|
+
expect(toast).toHaveBeenLastCalledWith(
|
|
126
|
+
expect.objectContaining({ title: "Package removed" }),
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
});
|