@marimo-team/islands 0.24.3-dev4 → 0.24.3-dev41
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-Cg8Ff5uL.js +200 -0
- package/dist/{ImageComparisonComponent-2a9TMMm2.js → ImageComparisonComponent-RspMflu6.js} +3 -3
- 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-BB9okzzY.js +138 -0
- package/dist/{common-BDlauhCU.js → common-aCHtzRnQ.js} +8853 -12653
- 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-yiwy9Vea.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-CfL-qWDi.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-MNFAmb3B.js} +2143 -1910
- package/dist/{glide-utils-NShAPPtn.js → glide-utils-B3rUT5PI.js} +15 -15
- package/dist/globals-DZfCplvV.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-BZuSsCs5.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-BthxSdRc.js → reveal-component-ONiOVUUx.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/column-visibility-dropdown.tsx +9 -3
- package/src/components/data-table/columns.tsx +64 -67
- package/src/components/datasources/components.tsx +4 -2
- package/src/components/editor/RecoveryButton.tsx +1 -0
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +36 -2
- 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/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__/cell.test.ts +61 -0
- 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/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
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { useAtomValue, useStore } from "jotai";
|
|
4
|
-
import { useMemo } from "react";
|
|
5
4
|
import {
|
|
6
5
|
useDeleteCellCallback,
|
|
7
6
|
useDeleteManyCellsCallback,
|
|
@@ -130,21 +129,18 @@ export function usePendingDeleteService() {
|
|
|
130
129
|
const { entries } = useAtomValue(pendingDeleteStateAtom);
|
|
131
130
|
const deleteCell = useDeleteCellCallback();
|
|
132
131
|
const deleteManyCells = useDeleteManyCellsCallback();
|
|
133
|
-
return
|
|
134
|
-
() =>
|
|
135
|
-
submit
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}),
|
|
146
|
-
[store, submit, clear, entries, deleteCell, deleteManyCells],
|
|
147
|
-
);
|
|
132
|
+
return {
|
|
133
|
+
submit: (cellIds: CellId[]) => {
|
|
134
|
+
submit({ cellIds, deleteCell, deleteManyCells, store });
|
|
135
|
+
},
|
|
136
|
+
clear,
|
|
137
|
+
get idle() {
|
|
138
|
+
return entries.size === 0;
|
|
139
|
+
},
|
|
140
|
+
get shouldConfirmDelete() {
|
|
141
|
+
return entries.size > 1;
|
|
142
|
+
},
|
|
143
|
+
};
|
|
148
144
|
}
|
|
149
145
|
|
|
150
146
|
export function usePendingDelete(cellId: CellId) {
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
import type { DataSourceConnection } from "@/core/datasets/data-source-connections";
|
|
18
18
|
import {
|
|
19
19
|
dataSourceConnectionsAtom,
|
|
20
|
+
exportedForTesting as dataSourceTesting,
|
|
20
21
|
setLatestEngineSelected,
|
|
21
22
|
} from "@/core/datasets/data-source-connections";
|
|
22
23
|
import { type ConnectionName, DUCKDB_ENGINE } from "@/core/datasets/engines";
|
|
@@ -550,8 +551,8 @@ _df = mo.sql(
|
|
|
550
551
|
const getLatestEngine = () =>
|
|
551
552
|
store.get(dataSourceConnectionsAtom).latestEngineSelected;
|
|
552
553
|
|
|
553
|
-
it("should
|
|
554
|
-
expect(getLatestEngine()).
|
|
554
|
+
it("should have no selected engine initially", () => {
|
|
555
|
+
expect(getLatestEngine()).toBeNull();
|
|
555
556
|
});
|
|
556
557
|
|
|
557
558
|
it("should persist the selected engine", () => {
|
|
@@ -622,6 +623,73 @@ _df = mo.sql(
|
|
|
622
623
|
});
|
|
623
624
|
|
|
624
625
|
describe("defaultCode", () => {
|
|
626
|
+
it("should prefer the newest usable connection until an engine is selected", () => {
|
|
627
|
+
const previousState = store.get(dataSourceConnectionsAtom);
|
|
628
|
+
const connection: DataSourceConnection = {
|
|
629
|
+
name: "first_connection" as ConnectionName,
|
|
630
|
+
source: "sqlite",
|
|
631
|
+
display_name: "SQLite",
|
|
632
|
+
dialect: "sqlite",
|
|
633
|
+
databases: [],
|
|
634
|
+
};
|
|
635
|
+
const newestConnection = {
|
|
636
|
+
...connection,
|
|
637
|
+
name: "newest_connection" as ConnectionName,
|
|
638
|
+
};
|
|
639
|
+
const icebergConnection = {
|
|
640
|
+
...connection,
|
|
641
|
+
name: "catalog" as ConnectionName,
|
|
642
|
+
source: "iceberg",
|
|
643
|
+
};
|
|
644
|
+
try {
|
|
645
|
+
store.set(dataSourceConnectionsAtom, {
|
|
646
|
+
latestEngineSelected: null,
|
|
647
|
+
connectionsMap: new Map(),
|
|
648
|
+
});
|
|
649
|
+
expect(adapter.defaultMetadata.engine).toBe(DUCKDB_ENGINE);
|
|
650
|
+
expect(adapter.defaultCode).toBe('_df = mo.sql(f"""SELECT * FROM """)');
|
|
651
|
+
|
|
652
|
+
store.set(dataSourceConnectionsAtom, {
|
|
653
|
+
latestEngineSelected: null,
|
|
654
|
+
connectionsMap: new Map([
|
|
655
|
+
[connection.name, connection],
|
|
656
|
+
[newestConnection.name, newestConnection],
|
|
657
|
+
[icebergConnection.name, icebergConnection],
|
|
658
|
+
[DUCKDB_ENGINE, { ...connection, name: DUCKDB_ENGINE }],
|
|
659
|
+
]),
|
|
660
|
+
});
|
|
661
|
+
expect(adapter.defaultMetadata.engine).toBe(newestConnection.name);
|
|
662
|
+
expect(adapter.defaultCode).toContain("engine=newest_connection");
|
|
663
|
+
expect(
|
|
664
|
+
store.get(dataSourceConnectionsAtom).latestEngineSelected,
|
|
665
|
+
).toBeNull();
|
|
666
|
+
|
|
667
|
+
const refreshConnection = (connection: DataSourceConnection) => {
|
|
668
|
+
store.set(
|
|
669
|
+
dataSourceConnectionsAtom,
|
|
670
|
+
dataSourceTesting.reducer(store.get(dataSourceConnectionsAtom), {
|
|
671
|
+
type: "addDataSourceConnection",
|
|
672
|
+
payload: { connections: [connection] },
|
|
673
|
+
}),
|
|
674
|
+
);
|
|
675
|
+
};
|
|
676
|
+
refreshConnection(connection);
|
|
677
|
+
expect(adapter.defaultMetadata.engine).toBe(connection.name);
|
|
678
|
+
expect(adapter.defaultCode).toContain("engine=first_connection");
|
|
679
|
+
|
|
680
|
+
setLatestEngineSelected(connection.name);
|
|
681
|
+
refreshConnection(newestConnection);
|
|
682
|
+
expect(adapter.defaultCode).toContain("engine=first_connection");
|
|
683
|
+
|
|
684
|
+
setLatestEngineSelected(DUCKDB_ENGINE);
|
|
685
|
+
refreshConnection(connection);
|
|
686
|
+
expect(adapter.defaultMetadata.engine).toBe(DUCKDB_ENGINE);
|
|
687
|
+
expect(adapter.defaultCode).toBe('_df = mo.sql(f"""SELECT * FROM """)');
|
|
688
|
+
} finally {
|
|
689
|
+
store.set(dataSourceConnectionsAtom, previousState);
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
|
|
625
693
|
it("should include engine in defaultCode when selected", () => {
|
|
626
694
|
const engine = "postgres_engine" as ConnectionName;
|
|
627
695
|
setLatestEngineSelected(engine);
|
|
@@ -76,7 +76,22 @@ export interface SQLLanguageAdapterMetadata extends SQLMetadata {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function getLatestEngine(): ConnectionName {
|
|
79
|
-
|
|
79
|
+
const { latestEngineSelected, connectionsMap } = store.get(
|
|
80
|
+
dataSourceConnectionsAtom,
|
|
81
|
+
);
|
|
82
|
+
if (latestEngineSelected !== null) {
|
|
83
|
+
return latestEngineSelected;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Map insertion order prefers the most recently discovered connection.
|
|
87
|
+
const connections = [...connectionsMap.values()].reverse();
|
|
88
|
+
return (
|
|
89
|
+
connections.find(
|
|
90
|
+
(connection) =>
|
|
91
|
+
!INTERNAL_SQL_ENGINES.has(connection.name) &&
|
|
92
|
+
connection.source !== "iceberg",
|
|
93
|
+
)?.name ?? DUCKDB_ENGINE
|
|
94
|
+
);
|
|
80
95
|
}
|
|
81
96
|
|
|
82
97
|
/**
|
|
@@ -47,7 +47,10 @@ const awarenessLogger = logger.get("awareness").disabled();
|
|
|
47
47
|
const AWARENESS_PREFIX = "awareness:";
|
|
48
48
|
|
|
49
49
|
// Utility functions for message handling
|
|
50
|
-
function prefixMessage(
|
|
50
|
+
function prefixMessage(
|
|
51
|
+
token: string,
|
|
52
|
+
message: Uint8Array,
|
|
53
|
+
): Uint8Array<ArrayBuffer> {
|
|
51
54
|
const tokenBytes = new TextEncoder().encode(token);
|
|
52
55
|
return new Uint8Array([...tokenBytes, ...message]);
|
|
53
56
|
}
|
|
@@ -154,7 +157,7 @@ if (isRtcEnabled()) {
|
|
|
154
157
|
doc.subscribeLocalUpdates((update) => {
|
|
155
158
|
logger.debug("local update, sending to server");
|
|
156
159
|
const ws = getWs();
|
|
157
|
-
ws.send(update);
|
|
160
|
+
ws.send(new Uint8Array(update));
|
|
158
161
|
});
|
|
159
162
|
|
|
160
163
|
// Handle awareness changes
|
|
@@ -106,6 +106,7 @@ describe("data source connections", () => {
|
|
|
106
106
|
|
|
107
107
|
let newState = addConnection(connections, state);
|
|
108
108
|
expect(newState.connectionsMap.size).toBe(defaultConnSize + 2);
|
|
109
|
+
newState = { ...newState, latestEngineSelected: connections[0].name };
|
|
109
110
|
|
|
110
111
|
newState = reducer(newState, {
|
|
111
112
|
type: "removeDataSourceConnection",
|
|
@@ -113,6 +114,7 @@ describe("data source connections", () => {
|
|
|
113
114
|
});
|
|
114
115
|
expect(newState.connectionsMap.size).toBe(defaultConnSize + 1);
|
|
115
116
|
expect(newState.connectionsMap.has("conn2" as ConnectionName)).toBe(true);
|
|
117
|
+
expect(newState.latestEngineSelected).toBeNull();
|
|
116
118
|
});
|
|
117
119
|
|
|
118
120
|
it("can clear all connections", () => {
|
|
@@ -44,7 +44,8 @@ export interface DataSourceConnection extends Omit<
|
|
|
44
44
|
export type ConnectionsMap = ReadonlyMap<ConnectionName, DataSourceConnection>;
|
|
45
45
|
|
|
46
46
|
export interface DataSourceState {
|
|
47
|
-
|
|
47
|
+
// Null permits automatic selection; DuckDB can also be an explicit choice.
|
|
48
|
+
latestEngineSelected: ConnectionName | null;
|
|
48
49
|
connectionsMap: ConnectionsMap;
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -110,7 +111,7 @@ function tableSchemaPath(sqlTableContext: SQLTableContext): string[] {
|
|
|
110
111
|
|
|
111
112
|
function initialState(): DataSourceState {
|
|
112
113
|
return {
|
|
113
|
-
latestEngineSelected:
|
|
114
|
+
latestEngineSelected: null,
|
|
114
115
|
connectionsMap: initialConnections,
|
|
115
116
|
};
|
|
116
117
|
}
|
|
@@ -136,6 +137,8 @@ const {
|
|
|
136
137
|
// Backend will dedupe by connection name & keep the latest, so we use this as the key
|
|
137
138
|
const newMap = new Map(connectionsMap);
|
|
138
139
|
for (const conn of opts.connections) {
|
|
140
|
+
// Refresh insertion order so automatic selection follows discovery recency.
|
|
141
|
+
newMap.delete(conn.name);
|
|
139
142
|
newMap.set(conn.name, conn);
|
|
140
143
|
}
|
|
141
144
|
|
|
@@ -161,16 +164,17 @@ const {
|
|
|
161
164
|
}),
|
|
162
165
|
);
|
|
163
166
|
return {
|
|
164
|
-
//
|
|
165
|
-
latestEngineSelected:
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
// Allow automatic selection again when the selected connection disappears.
|
|
168
|
+
latestEngineSelected:
|
|
169
|
+
latestEngineSelected && newMap.has(latestEngineSelected)
|
|
170
|
+
? latestEngineSelected
|
|
171
|
+
: null,
|
|
168
172
|
connectionsMap: newMap,
|
|
169
173
|
};
|
|
170
174
|
},
|
|
171
175
|
|
|
172
176
|
clearDataSourceConnections: (): DataSourceState => ({
|
|
173
|
-
latestEngineSelected:
|
|
177
|
+
latestEngineSelected: null,
|
|
174
178
|
connectionsMap: new Map(),
|
|
175
179
|
}),
|
|
176
180
|
|
|
@@ -183,9 +187,10 @@ const {
|
|
|
183
187
|
const newMap = new Map(connectionsMap);
|
|
184
188
|
newMap.delete(connectionName);
|
|
185
189
|
return {
|
|
186
|
-
latestEngineSelected:
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
latestEngineSelected:
|
|
191
|
+
latestEngineSelected && newMap.has(latestEngineSelected)
|
|
192
|
+
? latestEngineSelected
|
|
193
|
+
: null,
|
|
189
194
|
connectionsMap: newMap,
|
|
190
195
|
};
|
|
191
196
|
},
|
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",
|