@marimo-team/islands 0.23.7-dev4 → 0.23.7-dev42
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-PmilQqXR.js → ConnectedDataExplorerComponent-2lBNiUv6.js} +14 -14
- package/dist/{ErrorBoundary-Da4UeYxT.js → ErrorBoundary-D3wrPNma.js} +1 -1
- package/dist/{any-language-editor-BVR0l12r.js → any-language-editor-VWs_7v27.js} +15 -15
- package/dist/apl-Bdc61P1y.js +4 -0
- package/dist/{arc-CHF8PiiF.js → arc-DfkSnvZm.js} +2 -2
- package/dist/{architecture-7HQA4BMR-D0JB_3hE.js → architecture-7HQA4BMR-CS9jOrqM.js} +1 -1
- package/dist/{architectureDiagram-VXUJARFQ-BXQEUDtK.js → architectureDiagram-VXUJARFQ-CXVJxFhH.js} +16 -16
- package/dist/asciiarmor-DVRHDGzT.js +4 -0
- package/dist/asn1-BmuKfkfu.js +4 -0
- package/dist/assets/__vite-browser-external-CAdMKBac.js +1 -0
- package/dist/assets/worker-CpBbwbQo.js +73 -0
- package/dist/{blockDiagram-VD42YOAC-DhJe-Y9i.js → blockDiagram-VD42YOAC-DGDaxR8I.js} +11 -11
- package/dist/brainfuck-DPrRpyTV.js +4 -0
- package/dist/{button-CA5pI2YF.js → button-Dj4BTre0.js} +5 -0
- package/dist/{c4Diagram-YG6GDRKO-9dSfzOFR.js → c4Diagram-YG6GDRKO-C2hc6ne8.js} +5 -5
- package/dist/{capabilities-6laDasij.js → capabilities-C9rrYCzf.js} +1 -1
- package/dist/{channel-MqYIiKgS.js → channel-BBoIVUrJ.js} +1 -1
- package/dist/{chat-ui-B-gbqk_F.js → chat-ui-CufH8sfF.js} +626 -234
- package/dist/{check-CFM2mVDr.js → check-BcUIXnUT.js} +1 -1
- package/dist/{chunk-4BX2VUAB-BwfrWBqN.js → chunk-4BX2VUAB-CzXltWHN.js} +1 -1
- package/dist/{chunk-55IACEB6-D8THf2mi.js → chunk-55IACEB6-B-1mjMMC.js} +1 -1
- package/dist/{chunk-5FQGJX7Z-CO1e63h_.js → chunk-5FQGJX7Z-BOg95xG5.js} +2 -2
- package/dist/{chunk-ABZYJK2D-BrBb_0yY.js → chunk-ABZYJK2D-D0cLy8Bb.js} +2 -2
- package/dist/{chunk-ATLVNIR6-D-0XqNah.js → chunk-ATLVNIR6-BXsEjlHF.js} +2 -2
- package/dist/{chunk-B4BG7PRW-8iRKvugR.js → chunk-B4BG7PRW-Q1usn6T3.js} +7 -7
- package/dist/{chunk-CVBHYZKI-B6xhgaBd.js → chunk-CVBHYZKI-B_c5YBcW.js} +1 -1
- package/dist/{chunk-DI55MBZ5-C0_2D4m4.js → chunk-DI55MBZ5-D1qLYNrb.js} +6 -6
- package/dist/{chunk-EXTU4WIE-Jiw9ca1u.js → chunk-EXTU4WIE-BKNXdLmD.js} +2 -2
- package/dist/{chunk-FMBD7UC4-CHdus51S.js → chunk-FMBD7UC4-Ie8M9q0W.js} +1 -1
- package/dist/{chunk-HN2XXSSU-2Vfbq-kU.js → chunk-HN2XXSSU-E3n-Ys7Z.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-6wbaigKe.js → chunk-JA3XYJ7Z-D6c6cOBG.js} +3 -3
- package/dist/{chunk-JZLCHNYA-_rfptlUP.js → chunk-JZLCHNYA-BvsPHJmL.js} +6 -6
- package/dist/{chunk-MI3HLSF2-Do0-KRc0.js → chunk-MI3HLSF2-CUYEasXO.js} +1 -1
- package/dist/{chunk-N4CR4FBY-DIZG9dVD.js → chunk-N4CR4FBY-8ycT-O9a.js} +7 -7
- package/dist/{chunk-QN33PNHL-Cc64y40m.js → chunk-QN33PNHL-Bb-eUBW3.js} +2 -2
- package/dist/{chunk-QXUST7PY-BDG0-0Or.js → chunk-QXUST7PY-DV8yRwBd.js} +10 -10
- package/dist/{chunk-QZHKN3VN-B_Mdb8GC.js → chunk-QZHKN3VN-DRjXVwuJ.js} +1 -1
- package/dist/{chunk-S3R3BYOJ-DphMP0FA.js → chunk-S3R3BYOJ-mQeCz5CE.js} +4 -4
- package/dist/{chunk-TZMSLE5B-C9LUoYkc.js → chunk-TZMSLE5B-BqW10dHe.js} +3 -3
- package/dist/classDiagram-2ON5EDUG--Yh__LHb.js +30 -0
- package/dist/classDiagram-v2-WZHVMYZB-BC7X7Xtc.js +30 -0
- package/dist/{clike-sBZrGeF8.js → clike-DTxNUn7l.js} +1 -1
- package/dist/clojure-DEttQW5T.js +4 -0
- package/dist/cmake-jNlx_DaM.js +4 -0
- package/dist/cobol-BvvIm5MJ.js +4 -0
- package/dist/{code-block-37QAKDTI-0JNwiPGv.js → code-block-37QAKDTI-BsGy1AOJ.js} +1 -1
- package/dist/{code-visibility-zYxaYsuj.js → code-visibility-CTdccsPx.js} +573 -585
- package/dist/coffeescript-DTpBMyFU.js +4 -0
- package/dist/commonlisp-BmmUG8jb.js +4 -0
- package/dist/{copy-TGGAUEWp.js → copy-DLf4aN7I.js} +2 -2
- package/dist/{cose-bilkent-S5V4N54A-DXHZkJKX.js → cose-bilkent-S5V4N54A-kjoZoid4.js} +2 -2
- package/dist/crystal-BxyqmEWC.js +4 -0
- package/dist/css-BGoCtuG3.js +4 -0
- package/dist/cypher-BmCbdl3u.js +4 -0
- package/dist/d-CFrlbjZt.js +4 -0
- package/dist/{dagre-6UL2VRFP-tH87fkPA.js → dagre-6UL2VRFP-DRBWoQUw.js} +10 -10
- package/dist/{data-grid-overlay-editor-CWUN78-s.js → data-grid-overlay-editor-efe5ZagF.js} +2 -2
- package/dist/{diagram-PSM6KHXK-2VjPSCDn.js → diagram-PSM6KHXK-H66ATWP2.js} +18 -18
- package/dist/{diagram-QEK2KX5R-CiLmNyta.js → diagram-QEK2KX5R-DItl5Wns.js} +14 -14
- package/dist/{diagram-S2PKOQOG-Zha_1CLx.js → diagram-S2PKOQOG-CtuW_ZuL.js} +14 -14
- package/dist/diff-D6XwL6P8.js +4 -0
- package/dist/{dist-Brkazupz.js → dist--sWVZwjW.js} +1 -1
- package/dist/{dist-FN0ZA_8F.js → dist-21ButRCu.js} +1 -1
- package/dist/{dist-BetEKbPG.js → dist-B8RaFTRF.js} +1 -1
- package/dist/dist-BoHGySTM.js +5 -0
- package/dist/dist-ByAz19Qc.js +5 -0
- package/dist/dist-C93EysN4.js +5 -0
- package/dist/{dist-BHnX0ia_.js → dist-CY-lVor6.js} +1 -1
- package/dist/{dist-YP-G7W0f.js → dist-CYDuv4bR.js} +1 -1
- package/dist/{dist-CMjD5MQb.js → dist-Cfo5EE2t.js} +1 -1
- package/dist/dist-CjivSDvN.js +5 -0
- package/dist/dist-Cqwx-MH7.js +5 -0
- package/dist/{dist-ESg7xyoD.js → dist-D3ZI9nhS.js} +2 -2
- package/dist/{dist-DkC6YEo0.js → dist-DMZNjfX4.js} +1 -1
- package/dist/{dist-ChC1BhqM.js → dist-DbpcoFAV.js} +1 -1
- package/dist/dist-FUNenbiQ.js +5 -0
- package/dist/{dist-BEOU2g1b.js → dist-zhSud5X3.js} +1 -1
- package/dist/{dockerfile-COvlVLcE.js → dockerfile-twL37N91.js} +1 -1
- package/dist/dtd-Bw0lRN0-.js +4 -0
- package/dist/dylan-B55eBHTt.js +4 -0
- package/dist/ecl-C8G4p0wn.js +4 -0
- package/dist/eiffel-BmH46VJl.js +4 -0
- package/dist/elm-DhzeFqkl.js +4 -0
- package/dist/{erDiagram-Q2GNP2WA-biHZS05w.js → erDiagram-Q2GNP2WA--19X2kU5.js} +14 -14
- package/dist/erlang-CY-wdlsU.js +4 -0
- package/dist/{error-banner-DnBPzEWg.js → error-banner-CVkfBUT3.js} +2 -2
- package/dist/{esm-Dd1z1auZ.js → esm-CWp0KQeK.js} +1 -1
- package/dist/{esm-CYEyrE3Y.js → esm-DjNnlmpf.js} +96 -96
- package/dist/{extends-CzJgxo2J.js → extends-vAi97cpa.js} +4 -4
- package/dist/{factor-C2GT7jfQ.js → factor-CajWS6mS.js} +1 -1
- package/dist/factor-DWkgl0xw.js +4 -0
- package/dist/{flowDiagram-NV44I4VS-CWWlUpBR.js → flowDiagram-NV44I4VS-DQmWlo7f.js} +16 -16
- package/dist/{formats-CgaK7Gmx.js → formats-CpgZM9BM.js} +3 -3
- package/dist/forth-Cij_ie2t.js +4 -0
- package/dist/fortran-Br3X9cfm.js +4 -0
- package/dist/{ganttDiagram-JELNMOA3-D7B2c4Z9.js → ganttDiagram-JELNMOA3-BOGXJ8Lk.js} +7 -7
- package/dist/gas-DYsGcMN2.js +4 -0
- package/dist/gherkin-eVgXQ0fQ.js +4 -0
- package/dist/{gitGraph-G5XIXVHT-BdepdFa_.js → gitGraph-G5XIXVHT-DGlbae5m.js} +1 -1
- package/dist/{gitGraphDiagram-V2S2FVAM-CtLvNR1S.js → gitGraphDiagram-V2S2FVAM-DjzxfF0P.js} +14 -14
- package/dist/{glide-data-editor-CvlvtPWJ.js → glide-data-editor-BK9s_dqy.js} +13 -13
- package/dist/groovy-_NFHIXG7.js +4 -0
- package/dist/haskell-D6xNG_bH.js +4 -0
- package/dist/haxe-sU_rzAwn.js +5 -0
- package/dist/{html-to-image-hMMPiNe_.js → html-to-image-DxWM1HVj.js} +2395 -2301
- package/dist/idl-Ds_VbrUx.js +4 -0
- package/dist/{info-VBDWY6EO--JNA2rNu.js → info-VBDWY6EO-D2lvLLw5.js} +1 -1
- package/dist/{infoDiagram-HS3SLOUP-BbZyOxsP.js → infoDiagram-HS3SLOUP-ChNufFsP.js} +12 -12
- package/dist/{input-BAOe64zx.js → input-Cc1Vvw9A.js} +6 -6
- package/dist/javascript-CztfIl0i.js +4 -0
- package/dist/{journeyDiagram-XKPGCS4Q-BU2mjjzl.js → journeyDiagram-XKPGCS4Q-BO_O4Ij1.js} +6 -6
- package/dist/julia-DDv40QMV.js +4 -0
- package/dist/{kanban-definition-3W4ZIXB7-BlmczUuw.js → kanban-definition-3W4ZIXB7-CPpiiiWk.js} +11 -11
- package/dist/{katex-qPqrBHZ8.js → katex-9-9QRhxz.js} +1 -1
- package/dist/{label-BCWi-Oqu.js → label-BLqV33b1.js} +2 -2
- package/dist/{line-BWRi3U3S.js → line-C5s_12ee.js} +3 -3
- package/dist/{linear-DnHwODZa.js → linear-2NnK4cxi.js} +2 -2
- package/dist/livescript-BEOngLLc.js +4 -0
- package/dist/{loader-BvW0-YWZ.js → loader-Dr8Qem8p.js} +1 -1
- package/dist/lua-9-7BhQ4Y.js +4 -0
- package/dist/main.js +1175 -1142
- package/dist/mathematica-DDa0Pfxm.js +4 -0
- package/dist/mbox-iO03mmoE.js +4 -0
- package/dist/{mermaid-4DMBBIKO-CG1ECj5W.js → mermaid-4DMBBIKO-B7VQMwJx.js} +1 -1
- package/dist/{mermaid-CEbzCxCc.js → mermaid-DO-Daq7u.js} +46 -46
- package/dist/{mermaid-parser.core-CleJseNW.js → mermaid-parser.core-DreccfmS.js} +7 -7
- package/dist/{mhchem-BwoRNwg_.js → mhchem-yiCCuiEF.js} +1 -1
- package/dist/{mindmap-definition-VGOIOE7T-CcSYqYP9.js → mindmap-definition-VGOIOE7T-CC1_Vl0f.js} +13 -13
- package/dist/mirc-C9z5LT4X.js +4 -0
- package/dist/mllike-jGJbdm_C.js +6 -0
- package/dist/modelica-DzF7oIEL.js +4 -0
- package/dist/mscgen-DB-u125o.js +6 -0
- package/dist/mumps-CRTFHhzh.js +4 -0
- package/dist/nsis-C4NPTuox.js +4 -0
- package/dist/{nsis-B5K1qoyo.js → nsis-ClF3r5Tr.js} +1 -1
- package/dist/ntriples-BCOoGph1.js +4 -0
- package/dist/{number-overlay-editor-_GnlYFHC.js → number-overlay-editor-CpKi64Fy.js} +1 -1
- package/dist/octave-DTwNlazz.js +4 -0
- package/dist/{ordinal-2jIulmcR.js → ordinal-B43ZeR68.js} +1 -1
- package/dist/oz-DD38AzSz.js +4 -0
- package/dist/{packet-DYOGHKS2-CBxXGWNr.js → packet-DYOGHKS2-CmWtF3uO.js} +1 -1
- package/dist/pascal-BohSp9jV.js +4 -0
- package/dist/perl-f5OutoPM.js +4 -0
- package/dist/{pie-VRWISCQL-Bmdnqjip.js → pie-VRWISCQL-B6u8vus8.js} +1 -1
- package/dist/{pieDiagram-ADFJNKIX-DNyLF5H2.js → pieDiagram-ADFJNKIX-Di34MOFQ.js} +19 -19
- package/dist/pig-Dv7wSmHb.js +4 -0
- package/dist/powershell-rYgjKB39.js +4 -0
- package/dist/{process-output-Bza_GK7Q.js → process-output-DBYxXdrN.js} +30 -25
- package/dist/properties-BFUNLRDN.js +4 -0
- package/dist/protobuf-B9QJQPPv.js +4 -0
- package/dist/{pug-tjbzJCFk.js → pug-B_rby2yb.js} +1 -1
- package/dist/pug-DzvWpaMC.js +4 -0
- package/dist/puppet-B_K-n_xK.js +4 -0
- package/dist/python-CAiFcaA2.js +4 -0
- package/dist/q-cLeFIBLK.js +4 -0
- package/dist/{quadrantDiagram-AYHSOK5B-rXwjifrj.js → quadrantDiagram-AYHSOK5B-B9kVk1ny.js} +3 -3
- package/dist/r-04Y-Wco3.js +4 -0
- package/dist/{radar-ZZBFDIW7-BmCWDffL.js → radar-ZZBFDIW7-XAmXSa8s.js} +1 -1
- package/dist/{react-vega-B-rkEqtS.js → react-vega-Cavbrg4l.js} +1 -1
- package/dist/{react-vega-k9ODWPlI.js → react-vega-Dh6-UKKe.js} +13 -13
- package/dist/{requirementDiagram-UZGBJVZJ-DBdrMVbs.js → requirementDiagram-UZGBJVZJ-BxGfGYEx.js} +13 -13
- package/dist/{reveal-component-h0_DDpxE.js → reveal-component-BpKkH57S.js} +10 -10
- package/dist/rpm-FUdrIia9.js +5 -0
- package/dist/ruby-DMjFXuEW.js +4 -0
- package/dist/{sankeyDiagram-TZEHDZUN-CxmzalGv.js → sankeyDiagram-TZEHDZUN-D09PBJ-n.js} +4 -4
- package/dist/sas-DzHZxjXK.js +4 -0
- package/dist/scheme-DxHd_Rb9.js +4 -0
- package/dist/semaphore-CNDGTzkX.js +46 -0
- package/dist/{sequenceDiagram-WL72ISMW-CVCDsJ9h.js → sequenceDiagram-WL72ISMW-t_Dpemj0.js} +7 -7
- package/dist/shell-C8Kwypgf.js +4 -0
- package/dist/sieve-DdyqOKXZ.js +4 -0
- package/dist/smalltalk-pB7X1D9y.js +4 -0
- package/dist/sparql-NhBO6oOa.js +4 -0
- package/dist/{spec-DSIuqd3f.js → spec-hVaaZsY5.js} +4 -4
- package/dist/{src-BY0BGg6V.js → src-Bf2iLOlr.js} +1 -1
- package/dist/{stateDiagram-FKZM4ZOC-D_2djEhW.js → stateDiagram-FKZM4ZOC-B18gTP_j.js} +16 -16
- package/dist/stateDiagram-v2-4FDKWEC3-B6e_t14A.js +29 -0
- package/dist/{step-DGAGWg3y.js → step-CWipAYTY.js} +1 -1
- package/dist/{strings-B_FOH6eV.js → strings-BiIhGaI8.js} +4 -4
- package/dist/style.css +1 -1
- package/dist/stylus-SfWSnzPv.js +4 -0
- package/dist/swift-jRPdq2zR.js +4 -0
- package/dist/{swiper-component-KkEVUDd3.js → swiper-component-DlD2GU2g.js} +2 -2
- package/dist/tcl-_hpTHGX3.js +4 -0
- package/dist/textile-C9h8slqH.js +4 -0
- package/dist/{time-CMdrp3hw.js → time-C1SGcFMH.js} +2 -2
- package/dist/{timeline-definition-IT6M3QCI-E4NzxCs3.js → timeline-definition-IT6M3QCI-DJnh1ks5.js} +3 -3
- package/dist/{toDate-CHtl9vts.js → toDate-CJWlVNGD.js} +3 -3
- package/dist/toml-DWvtinD4.js +4 -0
- package/dist/{tooltip-B0mtKTXm.js → tooltip-DRaMBu06.js} +3 -3
- package/dist/{treemap-GDKQZRPO-CoKHPxa7.js → treemap-GDKQZRPO-Du95DV6u.js} +1 -1
- package/dist/troff-Dwo_A0y7.js +4 -0
- package/dist/ttcn-V--CPFKq.js +4 -0
- package/dist/ttcn-cfg-CPSMchTG.js +4 -0
- package/dist/turtle-B4rPGBWu.js +4 -0
- package/dist/{types-DBtDeUKD.js → types-Dzuoc3LN.js} +1 -1
- package/dist/{useAsyncData-B6hCGywC.js → useAsyncData-C56Khv_R.js} +1 -1
- package/dist/{useDateFormatter-B3mCQMP3.js → useDateFormatter-B_9k85Ex.js} +2 -2
- package/dist/{useDeepCompareMemoize-CmwDuYUH.js → useDeepCompareMemoize-Dt98v2ua.js} +1 -1
- package/dist/{useIframeCapabilities-DbdLoEDm.js → useIframeCapabilities-BkYHTrss.js} +1 -1
- package/dist/{useLifecycle-CjMjllqy.js → useLifecycle-BF6-z62y.js} +3 -3
- package/dist/{useTheme-CByZUW0p.js → useTheme-DykuNHR2.js} +2 -2
- package/dist/vb-DaMBBd4j.js +4 -0
- package/dist/vbscript-BMJQqcE2.js +4 -0
- package/dist/{vega-component-CC8TqWWV.js → vega-component-BtvQ-Kc4.js} +26 -24
- package/dist/velocity-CGq2QRq2.js +4 -0
- package/dist/verilog-CUNo8F5u.js +4 -0
- package/dist/vhdl-CCzA0msW.js +4 -0
- package/dist/webidl-CqIMDIBL.js +4 -0
- package/dist/xquery-XC5Kbr-1.js +4 -0
- package/dist/{xychartDiagram-PRI3JC2R-CuxTvjw5.js → xychartDiagram-PRI3JC2R-Dk2d_bX0.js} +10 -10
- package/dist/yacas-CGOv7Dzy.js +4 -0
- package/dist/z80-CXhVmi-f.js +4 -0
- package/dist/{zod-BxdsqRPd.js → zod-BWkcDORu.js} +1 -1
- package/package.json +3 -3
- package/src/components/chat/chat-components.tsx +47 -0
- package/src/components/chat/chat-display.tsx +41 -7
- package/src/components/chat/chat-panel.tsx +37 -10
- package/src/components/chat/chat-utils.ts +42 -20
- package/src/components/chat/reasoning-accordion.tsx +14 -3
- package/src/components/chat/tool-call/shared.ts +13 -0
- package/src/components/chat/tool-call/tool-approval-card.tsx +62 -0
- package/src/components/chat/tool-call/tool-args.tsx +26 -0
- package/src/components/chat/tool-call/tool-call-view.tsx +99 -0
- package/src/components/chat/tool-call/tool-error-card.tsx +81 -0
- package/src/components/chat/tool-call/tool-history-row.tsx +153 -0
- package/src/components/chat/tool-call/tool-result.tsx +101 -0
- package/src/components/data-table/TableTopBar.tsx +5 -1
- package/src/components/data-table/data-table.tsx +5 -0
- package/src/components/data-table/download-policy/atoms.ts +10 -0
- package/src/components/data-table/export-actions.tsx +31 -4
- package/src/components/editor/actions/useNotebookActions.tsx +3 -1
- package/src/components/editor/app-container.tsx +7 -1
- package/src/components/editor/chrome/panels/context-aware-panel/context-aware-panel.tsx +10 -2
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +1 -0
- package/src/components/editor/chrome/wrapper/footer.tsx +4 -1
- package/src/components/editor/chrome/wrapper/panels.tsx +4 -1
- package/src/components/editor/chrome/wrapper/sidebar.tsx +4 -1
- package/src/components/editor/controls/Controls.tsx +11 -3
- package/src/components/editor/file-tree/requesting-tree.tsx +27 -25
- package/src/components/editor/file-tree/upload.tsx +23 -24
- package/src/components/editor/header/__tests__/status.test.tsx +108 -0
- package/src/components/editor/header/status.tsx +44 -10
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +106 -0
- package/src/components/editor/navigation/__tests__/navigation.test.ts +70 -0
- package/src/components/editor/navigation/clipboard.ts +99 -25
- package/src/components/editor/navigation/navigation.ts +15 -1
- package/src/components/editor/notebook-cell.tsx +3 -0
- package/src/components/home/components.tsx +6 -0
- package/src/components/pages/run-page.tsx +4 -1
- package/src/core/ai/tools/__tests__/registry.test.ts +10 -12
- package/src/core/ai/tools/registry.ts +9 -5
- package/src/core/cells/__tests__/cells.test.ts +187 -0
- package/src/core/cells/__tests__/pending-cut-service.test.tsx +123 -0
- package/src/core/cells/cells.ts +102 -17
- package/src/core/cells/document-changes.ts +6 -1
- package/src/core/cells/pending-cut-service.ts +55 -0
- package/src/core/cells/utils.ts +11 -0
- package/src/core/codemirror/cells/extensions.ts +10 -0
- package/src/core/codemirror/markdown/__tests__/commands.test.ts +3 -3
- package/src/core/codemirror/markdown/commands.ts +1 -2
- package/src/core/edit-app.tsx +2 -1
- package/src/core/hotkeys/hotkeys.ts +5 -0
- package/src/core/islands/worker/worker.tsx +3 -2
- package/src/core/network/requests-network.ts +21 -3
- package/src/core/network/types.ts +12 -1
- package/src/core/run-app.tsx +2 -1
- package/src/core/wasm/__tests__/utils.test.ts +34 -0
- package/src/core/wasm/bridge.ts +14 -1
- package/src/core/wasm/utils.ts +14 -0
- package/src/core/wasm/worker/bootstrap.ts +3 -2
- package/src/core/wasm/worker/worker.ts +3 -2
- package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +155 -0
- package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +137 -0
- package/src/core/websocket/transports/basic.ts +2 -0
- package/src/core/websocket/transports/transport.ts +1 -0
- package/src/core/websocket/useMarimoKernelConnection.tsx +130 -55
- package/src/core/websocket/useWebSocket.tsx +5 -2
- package/src/css/app/Cell.css +10 -0
- package/src/plugins/impl/DataTablePlugin.tsx +12 -0
- package/src/plugins/impl/TabsPlugin.tsx +35 -7
- package/src/plugins/impl/__tests__/TabsPlugin.test.tsx +154 -0
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +6 -0
- package/src/plugins/impl/vega/resolve-data.ts +8 -1
- package/src/utils/__tests__/id-tree.test.ts +71 -0
- package/src/utils/__tests__/semaphore.test.ts +218 -0
- package/src/utils/fileToBase64.ts +8 -7
- package/src/utils/id-tree.tsx +89 -0
- package/src/utils/semaphore.ts +88 -0
- package/dist/apl-BKoVld9y.js +0 -4
- package/dist/asciiarmor-DQrKIjoo.js +0 -4
- package/dist/asn1-BZvnj0dq.js +0 -4
- package/dist/assets/__vite-browser-external-rrUYDKRl.js +0 -1
- package/dist/assets/worker-Bfy15ViQ.js +0 -73
- package/dist/brainfuck-D558nlUv.js +0 -4
- package/dist/classDiagram-2ON5EDUG-CBHMR6ZU.js +0 -30
- package/dist/classDiagram-v2-WZHVMYZB-BsUtUGM_.js +0 -30
- package/dist/clojure-Cq8mTSrE.js +0 -4
- package/dist/cmake-D8HCovWK.js +0 -4
- package/dist/cobol-UolN-9iU.js +0 -4
- package/dist/coffeescript-VdNuWrt5.js +0 -4
- package/dist/commonlisp-ALX7fpDc.js +0 -4
- package/dist/crystal-PbyO9Q_s.js +0 -4
- package/dist/css-DFklJkr_.js +0 -4
- package/dist/cypher-BifNeYlv.js +0 -4
- package/dist/d-BA-JP4PJ.js +0 -4
- package/dist/diff-CtkDpav4.js +0 -4
- package/dist/dist-BuBwsFva.js +0 -5
- package/dist/dist-BzmEQ9u7.js +0 -5
- package/dist/dist-Cih01ssx.js +0 -5
- package/dist/dist-CqfONiY9.js +0 -5
- package/dist/dist-D0iD0Fi9.js +0 -5
- package/dist/dist-DtNLXm8d.js +0 -5
- package/dist/dtd-DW3_UFEG.js +0 -4
- package/dist/dylan-pDhodO2N.js +0 -4
- package/dist/ecl-BJT8-YD7.js +0 -4
- package/dist/eiffel-Dmns-9vS.js +0 -4
- package/dist/elm-Da4sO4Bz.js +0 -4
- package/dist/erlang-C-zBsDi7.js +0 -4
- package/dist/factor-4xPWlWB5.js +0 -4
- package/dist/forth-l-c75zSd.js +0 -4
- package/dist/fortran-DIujSODW.js +0 -4
- package/dist/gas-CXnG5g_b.js +0 -4
- package/dist/gherkin-VPeqd4-X.js +0 -4
- package/dist/groovy-CphhZQgg.js +0 -4
- package/dist/haskell-CCvlS5Iq.js +0 -4
- package/dist/haxe-C_bi66fP.js +0 -5
- package/dist/idl-1DcP4Dm8.js +0 -4
- package/dist/javascript-DUIGhBvO.js +0 -4
- package/dist/julia-Cs2G4PQi.js +0 -4
- package/dist/livescript-DMtVFaAN.js +0 -4
- package/dist/lua-BAoLtdJg.js +0 -4
- package/dist/mathematica-C_NoFtbo.js +0 -4
- package/dist/mbox-DcFJFYrH.js +0 -4
- package/dist/mirc-71dccf_u.js +0 -4
- package/dist/mllike-CWcOFVDq.js +0 -6
- package/dist/modelica-Ape2VXxx.js +0 -4
- package/dist/mscgen-Cc6TwbSN.js +0 -6
- package/dist/mumps-h-ZbdkJ9.js +0 -4
- package/dist/nsis-C0p3m7JW.js +0 -4
- package/dist/ntriples-c9lEeT5w.js +0 -4
- package/dist/octave-DzEgB_74.js +0 -4
- package/dist/oz-CAxvHkyQ.js +0 -4
- package/dist/pascal-BJzu1sgP.js +0 -4
- package/dist/perl--IrOzZ2Z.js +0 -4
- package/dist/pig-CiBKKNhC.js +0 -4
- package/dist/powershell-KY0j6Qop.js +0 -4
- package/dist/properties-BW8q3ziV.js +0 -4
- package/dist/protobuf-BGaeuTGV.js +0 -4
- package/dist/pug-DjOKK-4J.js +0 -4
- package/dist/puppet-DWm2o6zX.js +0 -4
- package/dist/python-Bp2gezZy.js +0 -4
- package/dist/q-DljPshos.js +0 -4
- package/dist/r-BajPMnEu.js +0 -4
- package/dist/rpm-BKx-ZZ62.js +0 -5
- package/dist/ruby-DJq_HNKc.js +0 -4
- package/dist/sas-WANvpcOU.js +0 -4
- package/dist/scheme-CliBbhGF.js +0 -4
- package/dist/shell-BwhrNUvM.js +0 -4
- package/dist/sieve-BIVePvMp.js +0 -4
- package/dist/smalltalk-D6G48JmY.js +0 -4
- package/dist/sparql-jjc3BmEP.js +0 -4
- package/dist/stateDiagram-v2-4FDKWEC3-Cv9Av10H.js +0 -29
- package/dist/stylus-WPBPQ4PE.js +0 -4
- package/dist/swift-O1Qy6iCm.js +0 -4
- package/dist/tcl-BAFdhvsi.js +0 -4
- package/dist/textile-DFuzhNLG.js +0 -4
- package/dist/toml-DRSTeely.js +0 -4
- package/dist/troff-B_ZjwBW0.js +0 -4
- package/dist/ttcn-CAyiB3ic.js +0 -4
- package/dist/ttcn-cfg-BS5_BGBJ.js +0 -4
- package/dist/turtle-CUBEDy3E.js +0 -4
- package/dist/vb-DY9S6-U2.js +0 -4
- package/dist/vbscript-gaHC39Jq.js +0 -4
- package/dist/velocity-TfCOtJZ_.js +0 -4
- package/dist/verilog-c2JOX8mv.js +0 -4
- package/dist/vhdl-dHBirRiO.js +0 -4
- package/dist/webidl-Bauj-i07.js +0 -4
- package/dist/xquery-CtaEAOt8.js +0 -4
- package/dist/yacas-BZ85agQP.js +0 -4
- package/dist/z80-hCgR-L4U.js +0 -4
- package/src/components/chat/tool-call-accordion.tsx +0 -247
- /package/dist/{ImageComparisonComponent-DaocPIse.js → ImageComparisonComponent-CNHIsPDj.js} +0 -0
- /package/dist/{Plot-PIeIvFnD.js → Plot-4wn-lMVn.js} +0 -0
- /package/dist/{apl-Dt8GMXYg.js → apl-BCgCq9iM.js} +0 -0
- /package/dist/{array-B-MVxRIF.js → array-tvvEqPy7.js} +0 -0
- /package/dist/{asciiarmor-CitDQ85h.js → asciiarmor-BtqU-KJQ.js} +0 -0
- /package/dist/{asn1-abrf9SMK.js → asn1-Dmb-dTMx.js} +0 -0
- /package/dist/{asterisk-BUZwqih-.js → asterisk-DaVJJDnV.js} +0 -0
- /package/dist/{brainfuck-BL-Boof0.js → brainfuck-C1HoZKlE.js} +0 -0
- /package/dist/{chunk-4F5CHEZ2-C6tO9vjs.js → chunk-4F5CHEZ2-BZq7Kom7.js} +0 -0
- /package/dist/{chunk-B2363JML-Ds8wZXyP.js → chunk-B2363JML-D9-XOau1.js} +0 -0
- /package/dist/{chunk-DR5Q36YT-CP69aZS_.js → chunk-DR5Q36YT-BflwErH1.js} +0 -0
- /package/dist/{chunk-FRFDVMJY-BgQv1HBE.js → chunk-FRFDVMJY-BSBUAX7r.js} +0 -0
- /package/dist/{chunk-PL6DKKU2-DHfTUHy8.js → chunk-PL6DKKU2-B0MTXvyc.js} +0 -0
- /package/dist/{chunk-SJTYNZTY-Diciw4sx.js → chunk-SJTYNZTY-CEG4F0pB.js} +0 -0
- /package/dist/{chunk-TQ3KTPDO-CQfP9npd.js → chunk-TQ3KTPDO-DiCtqVSi.js} +0 -0
- /package/dist/{chunk-UMXZTB3W-MSKeGL7W.js → chunk-UMXZTB3W-97iS1iEl.js} +0 -0
- /package/dist/{click-outside-container-BZgN7xS_.js → click-outside-container-BDd67_1U.js} +0 -0
- /package/dist/{clike-RWg7anhx.js → clike-CdT0yHjt.js} +0 -0
- /package/dist/{clojure-DaojKHow.js → clojure-CdyrCpUv.js} +0 -0
- /package/dist/{cmake-DN-_v0XE.js → cmake-BFlPxym7.js} +0 -0
- /package/dist/{cobol-C3VpMyux.js → cobol-CcJXewp8.js} +0 -0
- /package/dist/{coffeescript-DIkz3Tbt.js → coffeescript-DnKuIKRo.js} +0 -0
- /package/dist/{colors-Cn2p_FA3.js → colors-CQAOa8cK.js} +0 -0
- /package/dist/{common-keywords-hbLeU7VU.js → common-keywords-FBrXPTcz.js} +0 -0
- /package/dist/{commonlisp-CB1boOiP.js → commonlisp-B-kok83Z.js} +0 -0
- /package/dist/{crystal-DI2oCml6.js → crystal-FYRYjI1I.js} +0 -0
- /package/dist/{css-BdEVwQDV.js → css-B45lc2V3.js} +0 -0
- /package/dist/{cypher-BNHToqxU.js → cypher-DZMLyVY_.js} +0 -0
- /package/dist/{cytoscape.esm-WbbDoCfu.js → cytoscape.esm-ayF70frT.js} +0 -0
- /package/dist/{d-D7we7I1b.js → d-x-VVT4o9.js} +0 -0
- /package/dist/{diff-Cia6fzjN.js → diff-Dxe2mpXk.js} +0 -0
- /package/dist/{dist-BK-3fF4P.js → dist-B4LJpMEg.js} +0 -0
- /package/dist/{dist-CxdUraQr.js → dist-B507mf_I.js} +0 -0
- /package/dist/{dist-C89sHDXk.js → dist-BGdYVvOu.js} +0 -0
- /package/dist/{dist-DquyVv5H.js → dist-BNyrZfqT.js} +0 -0
- /package/dist/{dist-Zn0KNbo9.js → dist-Bc5pmZIw.js} +0 -0
- /package/dist/{dist-C-J0pt5p.js → dist-BvCfQQQE.js} +0 -0
- /package/dist/{dist-D9r7Cmw7.js → dist-C2ej4eOH.js} +0 -0
- /package/dist/{dist-HVuryI1a.js → dist-C34oIrQ9.js} +0 -0
- /package/dist/{dist-CGLzXdrt.js → dist-CDFZi-QD.js} +0 -0
- /package/dist/{dist-C9fmTOin.js → dist-CYEylvZA.js} +0 -0
- /package/dist/{dist-DadjmS-4.js → dist-DJ6zJQZ4.js} +0 -0
- /package/dist/{dist-CtCY55Jf.js → dist-Dh3wkoyH.js} +0 -0
- /package/dist/{dist-C474qFoq.js → dist-Dhk6FMb0.js} +0 -0
- /package/dist/{dist-DZjQ_MBo.js → dist-KnujRhFL.js} +0 -0
- /package/dist/{dist-CinA9Enb.js → dist-WdPUFc56.js} +0 -0
- /package/dist/{dist-DBLeRrPp.js → dist-t_qL7eB8.js} +0 -0
- /package/dist/{dist-CyFFzJTb.js → dist-usPCDYx8.js} +0 -0
- /package/dist/{dtd-H4Hubdwp.js → dtd-C9VM_Wfu.js} +0 -0
- /package/dist/{duckdb-keywords-CZ_ZTscu.js → duckdb-keywords-CvJhR_Yd.js} +0 -0
- /package/dist/{dylan-fVO6rnq3.js → dylan-DTSnEIFO.js} +0 -0
- /package/dist/{ebnf-WEXPLEWb.js → ebnf-2D4Ctp3y.js} +0 -0
- /package/dist/{ecl-B94VPjNR.js → ecl-N04ptnRK.js} +0 -0
- /package/dist/{eiffel-C_R6TusS.js → eiffel-Dd8rpqr_.js} +0 -0
- /package/dist/{elm-DzCHbO2g.js → elm-GT2E866W.js} +0 -0
- /package/dist/{erlang-BGNkx6JU.js → erlang-Cf0Bp5pY.js} +0 -0
- /package/dist/{esm-Bb_hbWan.js → esm-BaaaPNGl.js} +0 -0
- /package/dist/{fcl-B_Gv5Jfx.js → fcl-Ccj8Z5Xd.js} +0 -0
- /package/dist/{forth-Bybw0cJ7.js → forth-wd_XzGTg.js} +0 -0
- /package/dist/{fortran-C6PoCLkI.js → fortran-DcwUTZFe.js} +0 -0
- /package/dist/{gas-BBlhenj4.js → gas-DeALIER3.js} +0 -0
- /package/dist/{gherkin-NXtNG85X.js → gherkin-CKTqaJNX.js} +0 -0
- /package/dist/{groovy-BoFYK9xM.js → groovy-Bwdp_d8D.js} +0 -0
- /package/dist/{haskell-BtBdvQ1n.js → haskell-DCdCcPLK.js} +0 -0
- /package/dist/{haxe-D--o6dr0.js → haxe-DAyktQWJ.js} +0 -0
- /package/dist/{http-Dc2fv19V.js → http-_DVAYWoR.js} +0 -0
- /package/dist/{idl-AqTq5l7e.js → idl-CBuZiRYu.js} +0 -0
- /package/dist/{init-D-g0ONX1.js → init-uv0kkh4g.js} +0 -0
- /package/dist/{javascript-DvwNVye9.js → javascript-DzigE11c.js} +0 -0
- /package/dist/{julia-DoKiagZC.js → julia-PwfB-0Cm.js} +0 -0
- /package/dist/{katex-B7pMJpE0.js → katex-C_XRmjAP.js} +0 -0
- /package/dist/{livescript-DxBZMiWB.js → livescript-BJLz1EbT.js} +0 -0
- /package/dist/{lua-DmS_0NTu.js → lua-ZC-XC2jf.js} +0 -0
- /package/dist/{math-BYK36kWZ.js → math-DFcdCCU8.js} +0 -0
- /package/dist/{mathematica-ChlDFeIC.js → mathematica-DCYMx6qB.js} +0 -0
- /package/dist/{mbox-CguZuODr.js → mbox-OxMK_9XI.js} +0 -0
- /package/dist/{mirc-CFtY8dqz.js → mirc-nJVyhA0H.js} +0 -0
- /package/dist/{mllike-C0EJrEOk.js → mllike-DRO89bsU.js} +0 -0
- /package/dist/{modelica-C1kO1nfS.js → modelica-Don3E6ZD.js} +0 -0
- /package/dist/{mscgen-DEYdr7AY.js → mscgen-DJfqD3bN.js} +0 -0
- /package/dist/{mumps-B3NVJs2V.js → mumps-SjGTvDYL.js} +0 -0
- /package/dist/{nginx-ComVAAGN.js → nginx-DasThI7R.js} +0 -0
- /package/dist/{node-sql-parser-DNGGJ-Rw.js → node-sql-parser-B8nBD36q.js} +0 -0
- /package/dist/{ntriples-DHol9X9H.js → ntriples-CNBKRl3I.js} +0 -0
- /package/dist/{octave-CYGz0bfo.js → octave-DdeVHNlx.js} +0 -0
- /package/dist/{oz-kPxb2ni5.js → oz-CcKSoNvN.js} +0 -0
- /package/dist/{pascal-bZ0yrJKy.js → pascal-6leftwNj.js} +0 -0
- /package/dist/{path-Du6n3sOU.js → path-BGaWgPKg.js} +0 -0
- /package/dist/{perl-z4hvqyqz.js → perl-BhJIwWzN.js} +0 -0
- /package/dist/{pig-DZO8QDF9.js → pig-r-xDHqRf.js} +0 -0
- /package/dist/{powershell-BSuaDQEC.js → powershell-D-BELeNi.js} +0 -0
- /package/dist/{properties-BXhGLlIx.js → properties-CnuDhbll.js} +0 -0
- /package/dist/{protobuf-DM6iybWV.js → protobuf-CO8RBhvX.js} +0 -0
- /package/dist/{puppet-Bn05sQT8.js → puppet-NmXHjLy8.js} +0 -0
- /package/dist/{python-Cvnhm0g7.js → python-DAQXi720.js} +0 -0
- /package/dist/{q-B9V8hzex.js → q-DlikXfV0.js} +0 -0
- /package/dist/{r-Cf0gFqmq.js → r-CuohilwT.js} +0 -0
- /package/dist/{rpm-D-LMkTV1.js → rpm-0Pjwp0Pb.js} +0 -0
- /package/dist/{ruby-DeuPikpK.js → ruby-Dq8NJTDG.js} +0 -0
- /package/dist/{sas-C9tjgAo9.js → sas-CuwonyVP.js} +0 -0
- /package/dist/{scheme-D1_bUF0G.js → scheme-CYU-RRIf.js} +0 -0
- /package/dist/{shell-CJBmnks3.js → shell-COPmX2qE.js} +0 -0
- /package/dist/{sieve-1fSV75CF.js → sieve-B_3zyLne.js} +0 -0
- /package/dist/{simple-mode-B90Wdavj.js → simple-mode-DSBniks8.js} +0 -0
- /package/dist/{smalltalk-sZNPD0HO.js → smalltalk-DRft7iPv.js} +0 -0
- /package/dist/{solr-DTkyqJ-Z.js → solr-RZ9uTl59.js} +0 -0
- /package/dist/{sparql-oHc1nm77.js → sparql-CN6qj55H.js} +0 -0
- /package/dist/{spreadsheet-CER0raqY.js → spreadsheet-BNNUNXA2.js} +0 -0
- /package/dist/{sql-ByOoEONQ.js → sql-B4x8IkwU.js} +0 -0
- /package/dist/{stylus-KzkX6zRB.js → stylus-Bn_ZjOQ3.js} +0 -0
- /package/dist/{swift-DqVxZvKo.js → swift-BLUJhMbz.js} +0 -0
- /package/dist/{tcl-BtWSwXfA.js → tcl-C86fxecl.js} +0 -0
- /package/dist/{textile-CWDbn9Ql.js → textile-DmHh2rsK.js} +0 -0
- /package/dist/{tiddlywiki-Cr9xyOY1.js → tiddlywiki-DI0mF2WJ.js} +0 -0
- /package/dist/{tiki-D5JONyfZ.js → tiki-2HU6XLLn.js} +0 -0
- /package/dist/{timer-D7JVdX9U.js → timer-YZl28NYN.js} +0 -0
- /package/dist/{toml-BfehlgmL.js → toml-GWANRNAD.js} +0 -0
- /package/dist/{treemap-qFGzn7xk.js → treemap-D-ka1hvx.js} +0 -0
- /package/dist/{troff-BZBk6AAu.js → troff-BHTsomIy.js} +0 -0
- /package/dist/{ttcn-DVwvXg0_.js → ttcn-DQuhn5Mn.js} +0 -0
- /package/dist/{ttcn-cfg-gjbVLf1L.js → ttcn-cfg-HjFYtdB-.js} +0 -0
- /package/dist/{turtle-CgxKXorV.js → turtle-nCay33Nv.js} +0 -0
- /package/dist/{vb-B9kSwTdM.js → vb-BG-XlqqJ.js} +0 -0
- /package/dist/{vbscript-DrUKSCdb.js → vbscript-B6vyW0-D.js} +0 -0
- /package/dist/{velocity-AlMYTnMy.js → velocity-CWegueqO.js} +0 -0
- /package/dist/{verilog-DLUaM05j.js → verilog-CzSQm4cG.js} +0 -0
- /package/dist/{vhdl-DUJOtSmO.js → vhdl-DqnNVL7r.js} +0 -0
- /package/dist/{webidl-CQp4aHk_.js → webidl-DXEUpDWH.js} +0 -0
- /package/dist/{xquery-IxkjlwOD.js → xquery-Ba_NB5bD.js} +0 -0
- /package/dist/{yacas-Bnctn5w8.js → yacas-HKQU6hyk.js} +0 -0
- /package/dist/{z80-DrFwhx53.js → z80-CXkHXLdj.js} +0 -0
|
@@ -11,7 +11,10 @@ import type {
|
|
|
11
11
|
NotificationMessageData,
|
|
12
12
|
NotificationPayload,
|
|
13
13
|
} from "@/core/kernel/messages";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
MAX_RETRIES,
|
|
16
|
+
useConnectionTransport,
|
|
17
|
+
} from "@/core/websocket/useWebSocket";
|
|
15
18
|
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
16
19
|
import {
|
|
17
20
|
handleWidgetMessage,
|
|
@@ -69,10 +72,96 @@ import { useStorageActions } from "../storage/state";
|
|
|
69
72
|
import { useVariablesActions } from "../variables/state";
|
|
70
73
|
import type { VariableName } from "../variables/types";
|
|
71
74
|
import { isWasm } from "../wasm/utils";
|
|
72
|
-
import {
|
|
75
|
+
import {
|
|
76
|
+
type ConnectionStatus,
|
|
77
|
+
WebSocketClosedReason,
|
|
78
|
+
WebSocketState,
|
|
79
|
+
} from "./types";
|
|
73
80
|
|
|
74
81
|
const SUPPORTS_LAZY_KERNELS = true;
|
|
75
82
|
|
|
83
|
+
export type CloseDecision =
|
|
84
|
+
| { kind: "terminal"; status: ConnectionStatus; closeTransport: boolean }
|
|
85
|
+
| { kind: "gave-up"; status: ConnectionStatus }
|
|
86
|
+
| { kind: "retry"; status: ConnectionStatus };
|
|
87
|
+
|
|
88
|
+
export function classifyCloseEvent(
|
|
89
|
+
event: { reason?: string },
|
|
90
|
+
context: { retryCount: number; maxRetries: number },
|
|
91
|
+
): CloseDecision {
|
|
92
|
+
switch (event.reason) {
|
|
93
|
+
case "MARIMO_ALREADY_CONNECTED":
|
|
94
|
+
return {
|
|
95
|
+
kind: "terminal",
|
|
96
|
+
status: {
|
|
97
|
+
state: WebSocketState.CLOSED,
|
|
98
|
+
code: WebSocketClosedReason.ALREADY_RUNNING,
|
|
99
|
+
reason: "another browser tab is already connected to the kernel",
|
|
100
|
+
canTakeover: true,
|
|
101
|
+
},
|
|
102
|
+
closeTransport: true,
|
|
103
|
+
};
|
|
104
|
+
case "MARIMO_WRONG_KERNEL_ID":
|
|
105
|
+
case "MARIMO_NO_FILE_KEY":
|
|
106
|
+
case "MARIMO_NO_SESSION_ID":
|
|
107
|
+
case "MARIMO_NO_SESSION":
|
|
108
|
+
case "MARIMO_SHUTDOWN":
|
|
109
|
+
return {
|
|
110
|
+
kind: "terminal",
|
|
111
|
+
status: {
|
|
112
|
+
state: WebSocketState.CLOSED,
|
|
113
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
114
|
+
reason: "kernel not found",
|
|
115
|
+
},
|
|
116
|
+
closeTransport: true,
|
|
117
|
+
};
|
|
118
|
+
case "MARIMO_MALFORMED_QUERY":
|
|
119
|
+
return {
|
|
120
|
+
kind: "terminal",
|
|
121
|
+
status: {
|
|
122
|
+
state: WebSocketState.CLOSED,
|
|
123
|
+
code: WebSocketClosedReason.MALFORMED_QUERY,
|
|
124
|
+
reason:
|
|
125
|
+
"the kernel did not recognize a request; please file a bug with marimo",
|
|
126
|
+
},
|
|
127
|
+
closeTransport: false,
|
|
128
|
+
};
|
|
129
|
+
case "MARIMO_KERNEL_STARTUP_ERROR":
|
|
130
|
+
return {
|
|
131
|
+
kind: "terminal",
|
|
132
|
+
status: {
|
|
133
|
+
state: WebSocketState.CLOSED,
|
|
134
|
+
code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
|
|
135
|
+
reason: "Failed to start kernel sandbox",
|
|
136
|
+
},
|
|
137
|
+
closeTransport: true,
|
|
138
|
+
};
|
|
139
|
+
default:
|
|
140
|
+
// Empty/undefined reasons are normal transient closes. Anything else is
|
|
141
|
+
// an unknown server reason; warn so a new MARIMO_* reason doesn't fall
|
|
142
|
+
// silently into the retry path.
|
|
143
|
+
if (event.reason) {
|
|
144
|
+
logNever(event.reason as never);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// partysocket stops retrying silently once `maxRetries` is hit; surface
|
|
148
|
+
// CLOSED so callers can detect the give-up.
|
|
149
|
+
if (context.retryCount >= context.maxRetries) {
|
|
150
|
+
return {
|
|
151
|
+
kind: "gave-up",
|
|
152
|
+
status: {
|
|
153
|
+
state: WebSocketState.CLOSED,
|
|
154
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
155
|
+
reason: "kernel not found",
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
kind: "retry",
|
|
161
|
+
status: { state: WebSocketState.CONNECTING },
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
76
165
|
function getExistingCells(): CellData[] | undefined {
|
|
77
166
|
if (!SUPPORTS_LAZY_KERNELS) {
|
|
78
167
|
return undefined;
|
|
@@ -340,6 +429,30 @@ export function useMarimoKernelConnection(opts: {
|
|
|
340
429
|
}
|
|
341
430
|
};
|
|
342
431
|
|
|
432
|
+
// Manual reconnect. Probes /health first to fail fast when the runtime
|
|
433
|
+
// is unreachable, instead of waiting on partysocket's retry budget.
|
|
434
|
+
const reconnect = async () => {
|
|
435
|
+
if (
|
|
436
|
+
ws.readyState === WebSocket.OPEN ||
|
|
437
|
+
ws.readyState === WebSocket.CONNECTING
|
|
438
|
+
) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
shouldTryReconnecting.current = true;
|
|
442
|
+
setConnection({ state: WebSocketState.CONNECTING });
|
|
443
|
+
const healthy = await runtimeManager.isHealthy();
|
|
444
|
+
if (!healthy) {
|
|
445
|
+
shouldTryReconnecting.current = false;
|
|
446
|
+
setConnection({
|
|
447
|
+
state: WebSocketState.CLOSED,
|
|
448
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
449
|
+
reason: "kernel not found",
|
|
450
|
+
});
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
ws.reconnect();
|
|
454
|
+
};
|
|
455
|
+
|
|
343
456
|
const ws = useConnectionTransport({
|
|
344
457
|
static: isStaticNotebook(),
|
|
345
458
|
/**
|
|
@@ -399,58 +512,20 @@ export function useMarimoKernelConnection(opts: {
|
|
|
399
512
|
*/
|
|
400
513
|
onClose: (e) => {
|
|
401
514
|
Logger.warn("WebSocket closed", e.code, e.reason);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
case "MARIMO_NO_SESSION":
|
|
417
|
-
case "MARIMO_SHUTDOWN":
|
|
418
|
-
setConnection({
|
|
419
|
-
state: WebSocketState.CLOSED,
|
|
420
|
-
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
421
|
-
reason: "kernel not found",
|
|
422
|
-
});
|
|
423
|
-
ws.close(); // close to prevent reconnecting
|
|
424
|
-
return;
|
|
425
|
-
|
|
426
|
-
case "MARIMO_MALFORMED_QUERY":
|
|
427
|
-
setConnection({
|
|
428
|
-
state: WebSocketState.CLOSED,
|
|
429
|
-
code: WebSocketClosedReason.MALFORMED_QUERY,
|
|
430
|
-
reason:
|
|
431
|
-
"the kernel did not recognize a request; please file a bug with marimo",
|
|
432
|
-
});
|
|
433
|
-
return;
|
|
434
|
-
|
|
435
|
-
default:
|
|
436
|
-
// Check for kernel startup error (full error already received via message)
|
|
437
|
-
if (e.reason === "MARIMO_KERNEL_STARTUP_ERROR") {
|
|
438
|
-
setConnection({
|
|
439
|
-
state: WebSocketState.CLOSED,
|
|
440
|
-
code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
|
|
441
|
-
reason: "Failed to start kernel sandbox",
|
|
442
|
-
});
|
|
443
|
-
ws.close(); // prevent reconnecting
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Session should be valid
|
|
448
|
-
// - browser tab might have been closed or re-opened
|
|
449
|
-
// - computer might have just woken from sleep
|
|
450
|
-
//
|
|
451
|
-
// so try reconnecting.
|
|
452
|
-
setConnection({ state: WebSocketState.CONNECTING });
|
|
453
|
-
tryReconnecting(e.code, e.reason);
|
|
515
|
+
const decision = classifyCloseEvent(e, {
|
|
516
|
+
retryCount: ws.retryCount,
|
|
517
|
+
maxRetries: MAX_RETRIES,
|
|
518
|
+
});
|
|
519
|
+
setConnection(decision.status);
|
|
520
|
+
if (decision.kind === "terminal" && decision.closeTransport) {
|
|
521
|
+
ws.close(); // close to prevent reconnecting
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (decision.kind === "retry") {
|
|
525
|
+
// Session should be valid
|
|
526
|
+
// - browser tab might have been closed or re-opened
|
|
527
|
+
// - computer might have just woken from sleep
|
|
528
|
+
tryReconnecting(e.code, e.reason);
|
|
454
529
|
}
|
|
455
530
|
},
|
|
456
531
|
|
|
@@ -468,5 +543,5 @@ export function useMarimoKernelConnection(opts: {
|
|
|
468
543
|
},
|
|
469
544
|
});
|
|
470
545
|
|
|
471
|
-
return { connection };
|
|
546
|
+
return { connection, reconnect };
|
|
472
547
|
}
|
|
@@ -18,6 +18,10 @@ interface UseConnectionTransportOptions {
|
|
|
18
18
|
onError: (event: WebSocketEventMap["error"]) => void;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// Per-`reconnect()` retry budget for partysocket. After exhaustion, partysocket
|
|
22
|
+
// stops silently; treat `retryCount >= MAX_RETRIES` as the give-up signal.
|
|
23
|
+
export const MAX_RETRIES = 10;
|
|
24
|
+
|
|
21
25
|
function createConnectionTransport(
|
|
22
26
|
options: Pick<UseConnectionTransportOptions, "url" | "static">,
|
|
23
27
|
): IConnectionTransport {
|
|
@@ -33,8 +37,7 @@ function createConnectionTransport(
|
|
|
33
37
|
// Cast needed: ReconnectingWebSocket types readyState as `number`
|
|
34
38
|
// but IConnectionTransport expects `0 | 1 | 2 | 3`
|
|
35
39
|
return new ReconnectingWebSocket(urlProvider, undefined, {
|
|
36
|
-
|
|
37
|
-
maxRetries: 10,
|
|
40
|
+
maxRetries: MAX_RETRIES,
|
|
38
41
|
debug: false,
|
|
39
42
|
startClosed: true,
|
|
40
43
|
// long timeout -- the server can become slow when many notebooks
|
package/src/css/app/Cell.css
CHANGED
|
@@ -194,6 +194,7 @@ interface Data<T> {
|
|
|
194
194
|
wrappedColumns?: string[];
|
|
195
195
|
headerTooltip?: Record<string, string>;
|
|
196
196
|
totalColumns: number;
|
|
197
|
+
sizeBytes?: number | null;
|
|
197
198
|
maxColumns: number | "all";
|
|
198
199
|
hasStableRowId: boolean;
|
|
199
200
|
lazy: boolean;
|
|
@@ -220,6 +221,7 @@ type DataTableFunctions = {
|
|
|
220
221
|
cell_styles?: CellStyleState | null;
|
|
221
222
|
cell_hover_texts?: Record<string, Record<string, string | null>> | null;
|
|
222
223
|
raw_data?: TableData<T> | null;
|
|
224
|
+
size_bytes?: number | null;
|
|
223
225
|
}>;
|
|
224
226
|
get_data_url?: GetDataUrl;
|
|
225
227
|
get_row_ids?: GetRowIds;
|
|
@@ -270,6 +272,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
270
272
|
headerTooltip: z.record(z.string(), z.string()).optional(),
|
|
271
273
|
fieldTypes: columnToFieldTypesSchema.nullish(),
|
|
272
274
|
totalColumns: z.number(),
|
|
275
|
+
sizeBytes: z.number().nullish(),
|
|
273
276
|
maxColumns: z.union([z.number(), z.literal("all")]).default("all"),
|
|
274
277
|
hasStableRowId: z.boolean().default(false),
|
|
275
278
|
maxHeight: z.number().optional(),
|
|
@@ -327,6 +330,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
327
330
|
.nullable(),
|
|
328
331
|
cell_hover_texts: cellHoverTextSchema.nullable(),
|
|
329
332
|
raw_data: z.union([z.string(), z.array(z.looseObject({}))]).nullish(),
|
|
333
|
+
size_bytes: z.number().nullish(),
|
|
330
334
|
}),
|
|
331
335
|
),
|
|
332
336
|
get_row_ids: rpc.input(z.object({}).passthrough()).output(
|
|
@@ -532,6 +536,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
532
536
|
rows: T[];
|
|
533
537
|
rawRows?: T[];
|
|
534
538
|
totalRows: number | TooManyRows;
|
|
539
|
+
sizeBytes?: number | null;
|
|
535
540
|
cellStyles: CellStyleState | undefined | null;
|
|
536
541
|
cellHoverTexts?: Record<string, Record<string, string | null>> | null;
|
|
537
542
|
}>(async () => {
|
|
@@ -548,6 +553,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
548
553
|
let tableData = props.data;
|
|
549
554
|
let rawTableData: TableData<T> | undefined | null = props.rawData;
|
|
550
555
|
let totalRows = props.totalRows;
|
|
556
|
+
let sizeBytes = props.sizeBytes ?? null;
|
|
551
557
|
let cellStyles = props.cellStyles;
|
|
552
558
|
let cellHoverTexts = props.cellHoverTexts;
|
|
553
559
|
|
|
@@ -591,6 +597,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
591
597
|
tableData = searchResults.data;
|
|
592
598
|
rawTableData = searchResults.raw_data;
|
|
593
599
|
totalRows = searchResults.total_rows;
|
|
600
|
+
sizeBytes = searchResults.size_bytes ?? null;
|
|
594
601
|
cellStyles = searchResults.cell_styles || {};
|
|
595
602
|
cellHoverTexts = searchResults.cell_hover_texts || {};
|
|
596
603
|
}
|
|
@@ -603,6 +610,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
603
610
|
rows: tableData,
|
|
604
611
|
rawRows: rawData,
|
|
605
612
|
totalRows: totalRows,
|
|
613
|
+
sizeBytes,
|
|
606
614
|
cellStyles,
|
|
607
615
|
cellHoverTexts,
|
|
608
616
|
};
|
|
@@ -614,6 +622,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
614
622
|
useDeepCompareMemoize(props.fieldTypes),
|
|
615
623
|
props.data,
|
|
616
624
|
props.totalRows,
|
|
625
|
+
props.sizeBytes,
|
|
617
626
|
props.lazy,
|
|
618
627
|
props.cellHoverTexts,
|
|
619
628
|
props.cellStyles,
|
|
@@ -728,6 +737,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
728
737
|
setFilters={setFilters}
|
|
729
738
|
reloading={isFetching && !isPending}
|
|
730
739
|
totalRows={data?.totalRows ?? props.totalRows}
|
|
740
|
+
sizeBytes={data?.sizeBytes ?? props.sizeBytes ?? null}
|
|
731
741
|
paginationState={paginationState}
|
|
732
742
|
setPaginationState={setPaginationState}
|
|
733
743
|
cellStyles={data?.cellStyles ?? props.cellStyles}
|
|
@@ -774,6 +784,7 @@ const DataTableComponent = ({
|
|
|
774
784
|
data,
|
|
775
785
|
rawData,
|
|
776
786
|
totalRows,
|
|
787
|
+
sizeBytes,
|
|
777
788
|
maxColumns,
|
|
778
789
|
pagination,
|
|
779
790
|
selection,
|
|
@@ -1053,6 +1064,7 @@ const DataTableComponent = ({
|
|
|
1053
1064
|
maxHeight={maxHeight}
|
|
1054
1065
|
sorting={sorting}
|
|
1055
1066
|
totalRows={totalRows}
|
|
1067
|
+
sizeBytes={sizeBytes}
|
|
1056
1068
|
totalColumns={totalColumns}
|
|
1057
1069
|
manualSorting={true}
|
|
1058
1070
|
setSorting={setSorting}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
TabsList,
|
|
8
8
|
TabsTrigger,
|
|
9
9
|
} from "../../components/ui/tabs";
|
|
10
|
+
import { cn } from "../../utils/cn";
|
|
10
11
|
import { renderHTML } from "../core/RenderHTML";
|
|
11
12
|
import type { IPlugin, IPluginProps } from "../types";
|
|
12
13
|
import { Labeled } from "./common/labeled";
|
|
@@ -17,6 +18,7 @@ interface Data {
|
|
|
17
18
|
*/
|
|
18
19
|
tabs: string[];
|
|
19
20
|
label: string | null;
|
|
21
|
+
orientation: "horizontal" | "vertical";
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
// Selected tab index
|
|
@@ -28,6 +30,7 @@ export class TabsPlugin implements IPlugin<T, Data> {
|
|
|
28
30
|
validator = z.object({
|
|
29
31
|
tabs: z.array(z.string()),
|
|
30
32
|
label: z.string().nullable(),
|
|
33
|
+
orientation: z.enum(["horizontal", "vertical"]).default("horizontal"),
|
|
31
34
|
});
|
|
32
35
|
|
|
33
36
|
render(props: IPluginProps<T, Data>): JSX.Element {
|
|
@@ -51,6 +54,7 @@ interface TabComponentProps extends Data {
|
|
|
51
54
|
const TabComponent = ({
|
|
52
55
|
tabs,
|
|
53
56
|
label,
|
|
57
|
+
orientation,
|
|
54
58
|
value,
|
|
55
59
|
setValue,
|
|
56
60
|
children,
|
|
@@ -70,19 +74,43 @@ const TabComponent = ({
|
|
|
70
74
|
setInternalValue(value);
|
|
71
75
|
}
|
|
72
76
|
|
|
77
|
+
const isVertical = orientation === "vertical";
|
|
78
|
+
const childArray =
|
|
79
|
+
children == null ? [] : Array.isArray(children) ? children : [children];
|
|
80
|
+
|
|
73
81
|
return (
|
|
74
|
-
<Labeled label={label} align="top">
|
|
75
|
-
<Tabs
|
|
76
|
-
|
|
82
|
+
<Labeled label={label} align="top" fullWidth={true}>
|
|
83
|
+
<Tabs
|
|
84
|
+
value={internalValue}
|
|
85
|
+
onValueChange={handleChange}
|
|
86
|
+
orientation={orientation}
|
|
87
|
+
className={cn(isVertical && "flex flex-row gap-3")}
|
|
88
|
+
>
|
|
89
|
+
<TabsList
|
|
90
|
+
className={cn(
|
|
91
|
+
"scrollbar-thin",
|
|
92
|
+
isVertical
|
|
93
|
+
? "flex flex-col items-stretch justify-start h-auto max-h-none shrink-0 min-w-[10rem] overflow-y-auto"
|
|
94
|
+
: "max-w-full overflow-x-auto justify-start",
|
|
95
|
+
)}
|
|
96
|
+
>
|
|
77
97
|
{tabs.map((tab, index) => (
|
|
78
|
-
<TabsTrigger
|
|
98
|
+
<TabsTrigger
|
|
99
|
+
key={index}
|
|
100
|
+
value={index.toString()}
|
|
101
|
+
className={cn(isVertical && "w-full justify-start")}
|
|
102
|
+
>
|
|
79
103
|
{renderHTML({ html: tab })}
|
|
80
104
|
</TabsTrigger>
|
|
81
105
|
))}
|
|
82
106
|
</TabsList>
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
<div className={cn(isVertical && "flex-1 min-w-0")}>
|
|
108
|
+
{childArray.map((child, index) => (
|
|
109
|
+
<TabsContent key={index} value={index.toString()}>
|
|
110
|
+
{child}
|
|
111
|
+
</TabsContent>
|
|
112
|
+
))}
|
|
113
|
+
</div>
|
|
86
114
|
</Tabs>
|
|
87
115
|
</Labeled>
|
|
88
116
|
);
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
import { initialModeAtom } from "@/core/mode";
|
|
7
|
+
import { store } from "@/core/state/jotai";
|
|
8
|
+
import type { IPluginProps } from "../../types";
|
|
9
|
+
import { TabsPlugin } from "../TabsPlugin";
|
|
10
|
+
|
|
11
|
+
describe("TabsPlugin", () => {
|
|
12
|
+
beforeAll(() => {
|
|
13
|
+
store.set(initialModeAtom, "edit");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const renderPlugin = (
|
|
17
|
+
data: z.input<TabsPlugin["validator"]>,
|
|
18
|
+
initialValue = "0",
|
|
19
|
+
) => {
|
|
20
|
+
const plugin = new TabsPlugin();
|
|
21
|
+
const host = document.createElement("div");
|
|
22
|
+
const setValue = vi.fn();
|
|
23
|
+
const children = [
|
|
24
|
+
<span key="0">Content 0</span>,
|
|
25
|
+
<span key="1">Content 1</span>,
|
|
26
|
+
<span key="2">Content 2</span>,
|
|
27
|
+
];
|
|
28
|
+
const makeProps = (
|
|
29
|
+
value: string,
|
|
30
|
+
): IPluginProps<string, z.infer<TabsPlugin["validator"]>> => ({
|
|
31
|
+
data: plugin.validator.parse(data),
|
|
32
|
+
value,
|
|
33
|
+
setValue,
|
|
34
|
+
host,
|
|
35
|
+
functions: {},
|
|
36
|
+
children,
|
|
37
|
+
});
|
|
38
|
+
const result = render(plugin.render(makeProps(initialValue)));
|
|
39
|
+
return {
|
|
40
|
+
...result,
|
|
41
|
+
setValue,
|
|
42
|
+
rerenderWithValue: (newValue: string) =>
|
|
43
|
+
result.rerender(plugin.render(makeProps(newValue))),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
it("renders all tab triggers", () => {
|
|
48
|
+
renderPlugin({
|
|
49
|
+
tabs: ["First", "Second", "Third"],
|
|
50
|
+
label: null,
|
|
51
|
+
});
|
|
52
|
+
expect(screen.getByRole("tab", { name: "First" })).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByRole("tab", { name: "Second" })).toBeInTheDocument();
|
|
54
|
+
expect(screen.getByRole("tab", { name: "Third" })).toBeInTheDocument();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("supports vertical orientation", () => {
|
|
58
|
+
renderPlugin({
|
|
59
|
+
tabs: ["First", "Second"],
|
|
60
|
+
label: null,
|
|
61
|
+
orientation: "vertical",
|
|
62
|
+
});
|
|
63
|
+
const tablist = screen.getByRole("tablist");
|
|
64
|
+
expect(tablist).toHaveAttribute("data-orientation", "vertical");
|
|
65
|
+
expect(tablist.className).toMatch(/flex-col/);
|
|
66
|
+
// Horizontal scroll classes should not be applied in vertical mode.
|
|
67
|
+
expect(tablist.className).not.toMatch(/overflow-x-auto/);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("falls back to horizontal when orientation is omitted (back-compat)", () => {
|
|
71
|
+
// Older Python kernels won't send `orientation` — make sure the validator
|
|
72
|
+
// defaults it so the frontend keeps working.
|
|
73
|
+
const plugin = new TabsPlugin();
|
|
74
|
+
const parsed = plugin.validator.parse({
|
|
75
|
+
tabs: ["First"],
|
|
76
|
+
label: null,
|
|
77
|
+
});
|
|
78
|
+
expect(parsed.orientation).toBe("horizontal");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("selects the tab matching the initial value", () => {
|
|
82
|
+
renderPlugin({ tabs: ["First", "Second", "Third"], label: null }, "1");
|
|
83
|
+
const tabs = screen.getAllByRole("tab");
|
|
84
|
+
expect(tabs[0]).toHaveAttribute("data-state", "inactive");
|
|
85
|
+
expect(tabs[1]).toHaveAttribute("data-state", "active");
|
|
86
|
+
expect(tabs[2]).toHaveAttribute("data-state", "inactive");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("defaults to the first tab when value is empty", () => {
|
|
90
|
+
renderPlugin({ tabs: ["First", "Second"], label: null }, "");
|
|
91
|
+
const tabs = screen.getAllByRole("tab");
|
|
92
|
+
expect(tabs[0]).toHaveAttribute("data-state", "active");
|
|
93
|
+
expect(tabs[1]).toHaveAttribute("data-state", "inactive");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("calls setValue with the clicked tab's index", () => {
|
|
97
|
+
const { setValue } = renderPlugin({
|
|
98
|
+
tabs: ["First", "Second", "Third"],
|
|
99
|
+
label: null,
|
|
100
|
+
});
|
|
101
|
+
// Radix Tabs' trigger reacts to mousedown (left button), not click —
|
|
102
|
+
// see https://github.com/radix-ui/primitives/blob/main/packages/react/tabs/src/Tabs.tsx
|
|
103
|
+
fireEvent.mouseDown(screen.getByRole("tab", { name: "Third" }), {
|
|
104
|
+
button: 0,
|
|
105
|
+
});
|
|
106
|
+
expect(setValue).toHaveBeenCalledWith("2");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("syncs selection when value is updated externally", () => {
|
|
110
|
+
const { rerenderWithValue } = renderPlugin(
|
|
111
|
+
{ tabs: ["First", "Second", "Third"], label: null },
|
|
112
|
+
"0",
|
|
113
|
+
);
|
|
114
|
+
expect(screen.getAllByRole("tab")[0]).toHaveAttribute(
|
|
115
|
+
"data-state",
|
|
116
|
+
"active",
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
rerenderWithValue("2");
|
|
120
|
+
const tabs = screen.getAllByRole("tab");
|
|
121
|
+
expect(tabs[0]).toHaveAttribute("data-state", "inactive");
|
|
122
|
+
expect(tabs[2]).toHaveAttribute("data-state", "active");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("renders HTML in tab labels via renderHTML", () => {
|
|
126
|
+
renderPlugin({
|
|
127
|
+
tabs: ["<strong>Bold</strong>", "Plain"],
|
|
128
|
+
label: null,
|
|
129
|
+
});
|
|
130
|
+
const boldTab = screen.getByRole("tab", { name: "Bold" });
|
|
131
|
+
// The label markup is preserved (not escaped as text), so the trigger
|
|
132
|
+
// contains a real <strong> element.
|
|
133
|
+
expect(boldTab.querySelector("strong")).not.toBeNull();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("renders no tabpanels when tabs and children are empty", () => {
|
|
137
|
+
// When the Python side passes `tabs={}`, slotted HTML is empty and the
|
|
138
|
+
// resulting React children are null/undefined. We should render zero
|
|
139
|
+
// `TabsContent`s — not a stray one paired to a non-existent trigger.
|
|
140
|
+
const plugin = new TabsPlugin();
|
|
141
|
+
const host = document.createElement("div");
|
|
142
|
+
const props: IPluginProps<string, z.infer<TabsPlugin["validator"]>> = {
|
|
143
|
+
data: plugin.validator.parse({ tabs: [], label: null }),
|
|
144
|
+
value: "",
|
|
145
|
+
setValue: vi.fn(),
|
|
146
|
+
host,
|
|
147
|
+
functions: {},
|
|
148
|
+
children: null,
|
|
149
|
+
};
|
|
150
|
+
render(plugin.render(props));
|
|
151
|
+
expect(screen.queryAllByRole("tab")).toHaveLength(0);
|
|
152
|
+
expect(screen.queryAllByRole("tabpanel")).toHaveLength(0);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -64,6 +64,7 @@ type PluginFunctions = {
|
|
|
64
64
|
column_types_per_step: FieldTypesWithExternalType[];
|
|
65
65
|
python_code?: string | null;
|
|
66
66
|
sql_code?: string | null;
|
|
67
|
+
size_bytes?: number | null;
|
|
67
68
|
}>;
|
|
68
69
|
get_column_values: (req: { column: string }) => Promise<{
|
|
69
70
|
values: unknown[];
|
|
@@ -81,6 +82,7 @@ type PluginFunctions = {
|
|
|
81
82
|
}) => Promise<{
|
|
82
83
|
data: TableData<T>;
|
|
83
84
|
total_rows: number;
|
|
85
|
+
size_bytes?: number | null;
|
|
84
86
|
}>;
|
|
85
87
|
download_as: DownloadAsArgs;
|
|
86
88
|
};
|
|
@@ -118,6 +120,7 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
118
120
|
column_types_per_step: z.array(columnToFieldTypesSchema),
|
|
119
121
|
python_code: z.string().nullish(),
|
|
120
122
|
sql_code: z.string().nullish(),
|
|
123
|
+
size_bytes: z.number().nullish(),
|
|
121
124
|
}),
|
|
122
125
|
),
|
|
123
126
|
get_column_values: rpc.input(z.object({ column: z.string() })).output(
|
|
@@ -147,6 +150,7 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
147
150
|
z.object({
|
|
148
151
|
data: z.union([z.string(), z.array(z.object({}).passthrough())]),
|
|
149
152
|
total_rows: z.number(),
|
|
153
|
+
size_bytes: z.number().nullish(),
|
|
150
154
|
}),
|
|
151
155
|
),
|
|
152
156
|
download_as: DownloadAsSchema,
|
|
@@ -203,6 +207,7 @@ export const DataFrameComponent = memo(
|
|
|
203
207
|
column_types_per_step,
|
|
204
208
|
python_code,
|
|
205
209
|
sql_code,
|
|
210
|
+
size_bytes,
|
|
206
211
|
} = data || {};
|
|
207
212
|
|
|
208
213
|
const totalColumns = field_types?.length;
|
|
@@ -322,6 +327,7 @@ export const DataFrameComponent = memo(
|
|
|
322
327
|
data={url || ""}
|
|
323
328
|
hasStableRowId={false}
|
|
324
329
|
totalRows={total_rows ?? 0}
|
|
330
|
+
sizeBytes={size_bytes ?? null}
|
|
325
331
|
totalColumns={totalColumns ?? 0}
|
|
326
332
|
maxColumns="all"
|
|
327
333
|
pageSize={pageSize}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { asRemoteURL } from "@/core/runtime/config";
|
|
4
|
+
import { Semaphore } from "@/utils/semaphore";
|
|
4
5
|
import { vegaLoadData } from "./loader";
|
|
5
6
|
import type {
|
|
6
7
|
FacetedUnitSpec,
|
|
@@ -17,6 +18,8 @@ type AnySpec =
|
|
|
17
18
|
| UnitSpec<Field>
|
|
18
19
|
| GenericFacetSpec<FacetedUnitSpec<Field>, LayerSpec<Field>, Field>;
|
|
19
20
|
|
|
21
|
+
const VEGA_DATA_FETCH_CONCURRENCY = 5;
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* Given a VegaLite spec with URL data, resolve the data and return a new spec with the resolved data.
|
|
22
25
|
*
|
|
@@ -30,6 +33,9 @@ export async function resolveVegaSpecData(
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
const datasets = "datasets" in spec ? { ...spec.datasets } : {};
|
|
36
|
+
// Single semaphore shared across the whole spec so total in-flight fetches
|
|
37
|
+
// (across all nested layers/hconcat/vconcat) stay bounded.
|
|
38
|
+
const fetchSem = new Semaphore(VEGA_DATA_FETCH_CONCURRENCY);
|
|
33
39
|
|
|
34
40
|
const traverse = async <T extends AnySpec>(spec: T): Promise<T> => {
|
|
35
41
|
if (!spec) {
|
|
@@ -80,7 +86,8 @@ export async function resolveVegaSpecData(
|
|
|
80
86
|
} catch {
|
|
81
87
|
return spec;
|
|
82
88
|
}
|
|
83
|
-
const
|
|
89
|
+
const format = spec.data.format;
|
|
90
|
+
const data = await fetchSem.run(() => vegaLoadData(url.href, format));
|
|
84
91
|
|
|
85
92
|
datasets[url.pathname] = data;
|
|
86
93
|
|