@marimo-team/islands 0.25.2 → 0.25.3-dev100
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-CNSxdKyJ.js → ConnectedDataExplorerComponent-Dhf5EGs5.js} +14 -14
- package/dist/{ErrorBoundary-HusVNio-.js → ErrorBoundary-GScQVnJ8.js} +8 -8
- package/dist/{abnfDiagram-VCTEODGH-DQDjNXt3.js → abnfDiagram-VCTEODGH-Di400kYu.js} +2 -2
- package/dist/any-language-editor-k2B8YI3Y.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-Nmls7Wxn.js → architectureDiagram-5GKGNRK7-BdTJcsNJ.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
- package/dist/assets/__vite-browser-external-35VXYmnw.js +1 -0
- package/dist/assets/{worker-HPY9fbhz.js → worker-Dq8y-WM5.js} +2 -2
- package/dist/{button-CvjkwdSk.js → button-BxB3RDjN.js} +1 -1
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-BgR0osfN.js} +2 -2
- package/dist/{chat-ui-BDpymeoe.js → chat-ui-BIgPxfPP.js} +1193 -1194
- package/dist/{check-EDwSwP89.js → check-P35dc2dH.js} +1 -1
- package/dist/{chunk-IMKFNOWR-CoIFEo-1.js → chunk-IMKFNOWR-mtD7aJBw.js} +1 -1
- package/dist/{chunk-SHT3W25Y-lHiGx3ZC.js → chunk-SHT3W25Y-DybB1ShH.js} +1 -1
- package/dist/{chunk-SVP7TREG-BvsHIrY_.js → chunk-SVP7TREG-DNhhdCex.js} +1 -1
- package/dist/{chunk-TICWLB2K-BC8YIm_n.js → chunk-TICWLB2K-NhAQhlDf.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-Bt98lkkv.js → classDiagram-ZZMXUADV-GTL0l5xS.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-D9bfbcC3.js → classDiagram-v2-VYDZK3BY-BWrM2ruI.js} +2 -2
- package/dist/{code-visibility-4aW5326K.js → code-visibility-DnqM5oW_.js} +17 -17
- package/dist/{common-Cjo7bjRK.js → common-D2HSo8Gy.js} +6091 -5697
- package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-CPoxUG7G.js} +3 -3
- package/dist/{cynefinDiagram-5FMLGOSQ-CgWra7wt.js → cynefinDiagram-5FMLGOSQ-CX22wa7c.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-CFZ8-35c.js → dagre-GXQ25YYZ-Df6Pp-cl.js} +1 -1
- package/dist/{data-grid-overlay-editor-CvdQXfSk.js → data-grid-overlay-editor-BgIMQs9G.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-lCNQrW7d.js → diagram-S7CK7UJ4-CctU9kVx.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-CQPQ6pP_.js → diagram-UQ7AKVKN-FVHjCF9j.js} +1 -1
- package/dist/{diagram-VX7I27RA-Cf3b0llz.js → diagram-VX7I27RA-BSDbwFFv.js} +1 -1
- package/dist/{diagram-Z3DM3KII-Bt4QLrpn.js → diagram-Z3DM3KII-BX8kW7Nc.js} +1 -1
- package/dist/{dialog-CEBFZNyc.js → dialog-C1PcpCqX.js} +3 -3
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-B_7xD2X4.js} +177 -169
- package/dist/{ebnfDiagram-PWID7BFC-D3NAyPFY.js → ebnfDiagram-PWID7BFC-DtapdLet.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-Tlu09_Nm.js → erDiagram-RLTQ6QDP-BAru9jHt.js} +1 -1
- package/dist/{error-banner-Da600cwz.js → error-banner-Sl2FlSJ4.js} +12 -7
- package/dist/{cells-C8iCYvLU.js → error-entries-TAO6kEhF.js} +1573 -1504
- package/dist/{feedback-button-ZuLnINhC.js → feedback-button-BXcB6llx.js} +122 -123
- package/dist/{flowDiagram-HODETNUW-CAYbpJmV.js → flowDiagram-HODETNUW-CjaeFeea.js} +2 -2
- package/dist/{formats-BGh2thRc.js → formats-V8ifA0Bk.js} +3 -3
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-qM9FSJA9.js → glide-data-editor-S-_J-7SO.js} +370 -368
- package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Bt8_pBa2.js} +16 -16
- package/dist/{globals-Ci7B9t6C.js → globals-D4vBwcD6.js} +3 -3
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{html-to-image-CZY1pIZH.js → html-to-image-CWdayGZU.js} +35 -35
- package/dist/{infoDiagram-27XIBGKW-XrDxhr0x.js → infoDiagram-27XIBGKW-B1hmUggC.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-CD1muzov.js → ishikawaDiagram-5VMMS53U-DUeT3t-d.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-Dg9W142_.js → kanban-definition-UXKFOSKX-DEUnNNgc.js} +1 -1
- package/dist/{label-BDKF3Afc.js → label-BRnUC0NX.js} +2 -2
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-Bm8cy3e8.js} +12 -12
- package/dist/main.js +3262 -3044
- package/dist/{mermaid-CiAXjLpA.js → mermaid-B0fXpsNP.js} +38 -38
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-DgCidgYJ.js → mindmap-definition-YA3MSWOX-CPexlhDQ.js} +1 -1
- package/dist/{number-overlay-editor-DunDxAzh.js → number-overlay-editor-CUrUm7Np.js} +3 -3
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{once-BtE-wKRL.js → once-eG8Vmvjd.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-coOYYKB6.js → pegDiagram-XKGWAZYB-CMpp1OOQ.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-BnXTc3bj.js → pieDiagram-E7YTZNPT-DlMWg5t1.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-e4jj9Ijt.js → process-output-DD-oSvZk.js} +5 -5
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-B28-u83n.js → railroadDiagram-O6MQD6OU-DBJfseeO.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-CdYCTMu0.js → requirementDiagram-BXWQKSXE-BC7V639r.js} +1 -1
- package/dist/{reveal-component-A7HedxmE.js → reveal-component-CFzdsOg8.js} +23 -23
- package/dist/{select-BButFi-d.js → select-B0LRDH0g.js} +4 -4
- package/dist/{sequenceDiagram-WJ2MYXX4-CM3aRAe_.js → sequenceDiagram-WJ2MYXX4-CgesU6F-.js} +1 -1
- package/dist/{spec-BwarBpUJ.js → spec-CcT0slVc.js} +4 -4
- package/dist/{stateDiagram-D77RDMKH-DOZUMVj8.js → stateDiagram-D77RDMKH-lH_BUhs3.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-CISYxma6.js → stateDiagram-v2-MP3YSRHH-8LL6FrBe.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-BkSppxp8.js → swimlanes-42K2YHIH-Cuf9B9kE.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-c8G5pGxC.js → swimlanesDiagram-VR7AAH4N-BoMMtOPh.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-DfhRvAFi.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-CaMQayqK.js → timeline-definition-24CTP7MA-yzzw4TF4.js} +1 -1
- package/dist/{toDate-BNJf01u1.js → toDate-DKH0_kMo.js} +53 -54
- package/dist/{toast-B9UMEi8u.js → toast-CFWpihJU.js} +4 -4
- package/dist/{tooltip-BO1REbqs.js → tooltip-CKO1pHJo.js} +2 -2
- package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-DBCITLeF.js} +1 -1
- package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-D0mLJstx.js} +15 -14
- package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-c_yJtkAe.js} +2 -2
- package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-BpPWi3G3.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-BkdeVdXC.js} +1 -1
- package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-Dum8WSXq.js} +3 -3
- package/dist/{useTheme-CRnjkku0.js → useTheme-CfeaVw5D.js} +6 -6
- package/dist/{vega-component-DG29TAB7.js → vega-component-DgytCKrL.js} +147 -147
- package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
- package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
- package/dist/{vennDiagram-4TSXK5OY-CF8pfaK3.js → vennDiagram-4TSXK5OY-eJOrTqqC.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-dGPu39d-.js → wardleyDiagram-VM6X3IG4-TILPvee6.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CP6-9q56.js → xychartDiagram-S5SC5T6Z-DUPvRwwJ.js} +2 -2
- package/package.json +8 -5
- package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +3 -2
- package/src/__tests__/host-imports.test.ts +101 -0
- package/src/__tests__/mount.test.ts +8 -8
- package/src/components/app-config/ai-config.tsx +7 -2
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +2 -2
- package/src/components/chat/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +9 -8
- package/src/components/chat/chat-utils.ts +4 -8
- package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
- package/src/components/data-table/__tests__/columns.test.tsx +105 -0
- package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
- package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
- package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +434 -6
- package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
- package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
- package/src/components/data-table/cell-selection/feature.ts +2 -2
- package/src/components/data-table/cell-selection/types.ts +2 -2
- package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/charts.tsx +35 -25
- package/src/components/data-table/charts/storage.ts +16 -5
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/column-summary.tsx +2 -4
- package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
- package/src/components/data-table/columns.tsx +45 -46
- package/src/components/data-table/context-menu.tsx +161 -46
- package/src/components/data-table/data-table.tsx +7 -1
- package/src/components/data-table/date-filter-inputs.tsx +15 -42
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +267 -163
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +2 -2
- package/src/components/data-table/schemas.ts +14 -36
- package/src/components/data-table/search-highlight.tsx +79 -0
- package/src/components/data-table/types.ts +1 -0
- package/src/components/data-table/url-detector.tsx +49 -9
- package/src/components/data-table/utils.ts +18 -0
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +63 -2
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/column-preview.tsx +8 -2
- package/src/components/datasources/datasources.tsx +47 -35
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/editor/Output.tsx +9 -2
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +80 -252
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +210 -34
- package/src/components/editor/actions/pair-with-agent-commands.ts +42 -51
- package/src/components/editor/actions/pair-with-agent-modal.tsx +100 -37
- package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
- package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/cell/CreateCellButton.tsx +8 -10
- package/src/components/editor/cell/DeleteButton.tsx +1 -0
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +1 -1
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +366 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
- package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/connections/components.tsx +1 -1
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +537 -0
- package/src/components/editor/errors/send-error-report-button.tsx +69 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +10 -5
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/output/MarimoErrorOutput.tsx +21 -5
- package/src/components/editor/output/MarimoTracebackOutput.tsx +37 -22
- package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
- package/src/components/editor/output/ansi-reduce.ts +12 -0
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/package-alert.tsx +6 -4
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/home/components.tsx +17 -31
- package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
- package/src/components/icons/large-spinner.tsx +3 -14
- package/src/components/icons/spinner.tsx +1 -1
- package/src/components/mcp/mcp-status-indicator.tsx +1 -1
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.tsx +2 -2
- package/src/components/slides/reveal-component.tsx +4 -2
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/tracing/tracing.tsx +2 -2
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/attachments/__tests__/toast.test.tsx +58 -0
- package/src/core/attachments/state.ts +18 -0
- package/src/core/attachments/toast.ts +15 -0
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +55 -1
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/error-report.test.ts +139 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
- package/src/core/cells/__tests__/session.test.ts +50 -1
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +3 -1
- package/src/core/cells/error-report.ts +63 -0
- package/src/core/cells/pending-delete-service.ts +2 -6
- package/src/core/cells/session.ts +29 -2
- package/src/core/cells/types.ts +10 -1
- package/src/core/codemirror/__tests__/setup.test.ts +1 -1
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/languages/markdown.ts +1 -1
- package/src/core/codemirror/language/languages/python.ts +3 -3
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/config/pair.ts +5 -3
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/document/__tests__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/model.test.ts +483 -0
- package/src/core/document/__tests__/state.test.ts +446 -0
- package/src/core/document/__tests__/submission.test.ts +346 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/index.ts +10 -0
- package/src/core/document/model.ts +53 -0
- package/src/core/document/state.ts +401 -0
- package/src/core/document/sync.ts +359 -0
- package/src/core/edit-app.tsx +2 -2
- package/src/core/host/AGENTS.md +16 -0
- package/src/core/host/__tests__/attachments.test.ts +56 -0
- package/src/core/host/__tests__/document.test.ts +126 -0
- package/src/core/host/__tests__/fixtures.ts +41 -0
- package/src/core/host/__tests__/notebook-client.test.ts +570 -0
- package/src/core/host/connection.ts +42 -0
- package/src/core/host/notebook-client.ts +297 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/network/connection.ts +4 -2
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/run-app.tsx +2 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +18 -17
- package/src/core/runtime/runtime.ts +26 -30
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/files.ts +2 -0
- package/src/core/wasm/bridge.ts +2 -10
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +1 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -29
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +223 -0
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.hook.test.tsx → useNotebookSession.hook.test.tsx} +194 -184
- package/src/core/websocket/connection-state.ts +60 -0
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +502 -0
- package/src/core/websocket/transports/notebook.ts +213 -0
- package/src/core/websocket/types.ts +9 -39
- package/src/core/websocket/useNotebookClient.ts +89 -0
- package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +53 -224
- package/src/css/globals.css +5 -0
- package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
- package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
- package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
- package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
- package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
- package/src/hooks/__tests__/useScript.test.tsx +77 -0
- package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
- package/src/hooks/useAsyncData.ts +3 -3
- package/src/hooks/useDataSourceDiscovery.ts +6 -4
- package/src/hooks/useDebounce.ts +5 -8
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useInputHistory.ts +4 -7
- package/src/hooks/useInternalStateWithSync.ts +6 -6
- package/src/hooks/useResizeObserver.ts +4 -7
- package/src/hooks/useScript.ts +67 -70
- package/src/hooks/useStateForKey.ts +93 -0
- package/src/mount.tsx +3 -3
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +14 -15
- package/src/plugins/impl/DropdownPlugin.tsx +2 -6
- package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/RangeSliderPlugin.tsx +0 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +201 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/runtime.ts +21 -9
- package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
- package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
- package/src/plugins/impl/chat/chat-ui.tsx +12 -10
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
- package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +0 -1
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/select.stories.tsx +2 -2
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/utils/__tests__/arrays.test.ts +35 -0
- package/src/utils/__tests__/batch-requests.test.ts +3 -3
- package/src/utils/__tests__/dates.test.ts +116 -0
- package/src/utils/__tests__/numbers.test.ts +48 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +10 -0
- package/src/utils/blob.ts +1 -1
- package/src/utils/dates.ts +94 -0
- package/src/utils/numbers.ts +28 -17
- package/src/utils/objects.ts +3 -7
- package/src/utils/once.ts +19 -19
- package/src/utils/zod-utils.ts +1 -3
- package/dist/any-language-editor-B9REGlD9.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/error-entries-CzoYkIQZ.js +0 -56
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -61
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useWebSocket.tsx +0 -88
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type NotebookTransport,
|
|
5
|
+
sse,
|
|
6
|
+
StreamStopped,
|
|
7
|
+
type StreamUrl,
|
|
8
|
+
} from "@marimo-team/client";
|
|
9
|
+
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
10
|
+
import { PyodideBridge } from "../../wasm/bridge";
|
|
11
|
+
import { isWasm } from "../../wasm/utils";
|
|
12
|
+
import { classifyCloseEvent } from "../connection-state";
|
|
13
|
+
|
|
14
|
+
/** The server can be slow to accept when many notebooks are open. */
|
|
15
|
+
const CONNECT_MS = 10_000;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The error that ends a stream on this close, or none to retry.
|
|
19
|
+
*
|
|
20
|
+
* `cause` is the connection status the editor shows.
|
|
21
|
+
*/
|
|
22
|
+
function stopOn(close: { code?: number; reason?: string }) {
|
|
23
|
+
const decision = classifyCloseEvent(close);
|
|
24
|
+
if (decision.kind === "retry") {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const reason = "reason" in decision.status ? decision.status.reason : "";
|
|
28
|
+
return new StreamStopped(reason, { cause: decision.status });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Read a URL provider, stopping the stream when it gives up. */
|
|
32
|
+
async function resolve(url: StreamUrl): Promise<URL | undefined> {
|
|
33
|
+
try {
|
|
34
|
+
return new URL(typeof url === "function" ? await url() : url);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (error instanceof StreamStopped) {
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** A resume cursor and replica belong to the session that produced them. */
|
|
44
|
+
function withSessionIdentity(
|
|
45
|
+
url: StreamUrl,
|
|
46
|
+
connect: (target: URL) => NotebookTransport,
|
|
47
|
+
): NotebookTransport {
|
|
48
|
+
let previous: string | undefined;
|
|
49
|
+
return async (attempt, handlers) => {
|
|
50
|
+
const target = await resolve(url);
|
|
51
|
+
if (target === undefined || attempt.signal.aborted) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
target.searchParams.delete("cursor");
|
|
55
|
+
const identity = new URL(target);
|
|
56
|
+
identity.searchParams.delete("access_token");
|
|
57
|
+
identity.searchParams.sort();
|
|
58
|
+
identity.hash = "";
|
|
59
|
+
const key = identity.toString();
|
|
60
|
+
let { cursor } = attempt;
|
|
61
|
+
if (previous !== undefined && previous !== key) {
|
|
62
|
+
// Reset both the stream's cursor and its subscribers' state.
|
|
63
|
+
handlers.message({ event: "reset", data: {} });
|
|
64
|
+
cursor = null;
|
|
65
|
+
}
|
|
66
|
+
previous = key;
|
|
67
|
+
if (!attempt.signal.aborted) {
|
|
68
|
+
return connect(target)({ ...attempt, cursor }, handlers);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Follow a marimo session over its WebSocket route.
|
|
75
|
+
*
|
|
76
|
+
* Each attempt opens one socket with the cursor as a query parameter. The
|
|
77
|
+
* editor's close policy decides which closes end the stream.
|
|
78
|
+
*
|
|
79
|
+
* TODO: Notice a connection that died without closing, such as after a laptop
|
|
80
|
+
* sleeps. `/sse` sends a heartbeat that its silence limit relies on, and
|
|
81
|
+
* `/ws` drops it. Sending it on `/ws` would let this transport close a
|
|
82
|
+
* silent socket.
|
|
83
|
+
*/
|
|
84
|
+
export function websocket(url: StreamUrl): NotebookTransport {
|
|
85
|
+
return withSessionIdentity(
|
|
86
|
+
url,
|
|
87
|
+
(target) =>
|
|
88
|
+
async ({ cursor, signal }, { open, message }) => {
|
|
89
|
+
if (cursor !== null) {
|
|
90
|
+
target.searchParams.set("cursor", cursor);
|
|
91
|
+
}
|
|
92
|
+
await new Promise<void>((settle, reject) => {
|
|
93
|
+
const socket = new WebSocket(target);
|
|
94
|
+
const timeout = setTimeout(() => socket.close(), CONNECT_MS);
|
|
95
|
+
const abort = () => socket.close();
|
|
96
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
97
|
+
socket.addEventListener("open", () => {
|
|
98
|
+
clearTimeout(timeout);
|
|
99
|
+
open();
|
|
100
|
+
});
|
|
101
|
+
socket.addEventListener("message", ({ data }) =>
|
|
102
|
+
// marimo's parser reads `NaN`. A message it cannot read arrives as an
|
|
103
|
+
// empty object, which `NotebookEvents` rejects as not an event.
|
|
104
|
+
message(jsonParseWithSpecialChar(String(data))),
|
|
105
|
+
);
|
|
106
|
+
socket.addEventListener("close", (event) => {
|
|
107
|
+
clearTimeout(timeout);
|
|
108
|
+
signal.removeEventListener("abort", abort);
|
|
109
|
+
const stopped = signal.aborted ? undefined : stopOn(event);
|
|
110
|
+
if (stopped === undefined) {
|
|
111
|
+
settle();
|
|
112
|
+
} else {
|
|
113
|
+
reject(stopped);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Follow a marimo session over its server-sent events route.
|
|
123
|
+
*
|
|
124
|
+
* The session's `close` frames carry the same reasons as WebSocket closes.
|
|
125
|
+
* marimo's parser decodes tagged bigints and non-finite numbers in every frame.
|
|
126
|
+
*/
|
|
127
|
+
export function sessionSse(
|
|
128
|
+
url: StreamUrl,
|
|
129
|
+
headers: () => Record<string, string>,
|
|
130
|
+
): NotebookTransport {
|
|
131
|
+
return withSessionIdentity(url, (target) =>
|
|
132
|
+
sse(target, {
|
|
133
|
+
parseData: jsonParseWithSpecialChar,
|
|
134
|
+
fetch: (input, init) => {
|
|
135
|
+
const sent = new Headers(init?.headers);
|
|
136
|
+
for (const [name, value] of Object.entries(headers())) {
|
|
137
|
+
sent.set(name, value);
|
|
138
|
+
}
|
|
139
|
+
return globalThis.fetch(input, { ...init, headers: sent });
|
|
140
|
+
},
|
|
141
|
+
stop: (frame) =>
|
|
142
|
+
frame.event === "close"
|
|
143
|
+
? stopOn(frame.data as { code?: number; reason?: string })
|
|
144
|
+
: undefined,
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** A connection that opens and delivers nothing, for static notebooks. */
|
|
150
|
+
const idle: NotebookTransport = ({ signal }, { open }) =>
|
|
151
|
+
new Promise((settle) => {
|
|
152
|
+
open();
|
|
153
|
+
signal.addEventListener("abort", () => settle(), { once: true });
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Follow the notebook running in the WASM worker.
|
|
158
|
+
*
|
|
159
|
+
* The worker sends marimo notifications as `{ data: notification }`, which
|
|
160
|
+
* arrive as `marimo` events.
|
|
161
|
+
*/
|
|
162
|
+
export function pyodide(
|
|
163
|
+
attach: (consumer: (message: MessageEvent<string>) => void) => void,
|
|
164
|
+
): NotebookTransport {
|
|
165
|
+
return ({ signal }, { open, message }) =>
|
|
166
|
+
new Promise((settle) => {
|
|
167
|
+
open();
|
|
168
|
+
attach(({ data }) => {
|
|
169
|
+
if (signal.aborted) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const value = jsonParseWithSpecialChar(data);
|
|
173
|
+
// The worker sends notifications without the host's event envelope.
|
|
174
|
+
message(
|
|
175
|
+
typeof value === "object" &&
|
|
176
|
+
value !== null &&
|
|
177
|
+
!("event" in value) &&
|
|
178
|
+
"data" in value
|
|
179
|
+
? { event: "marimo", data: { marimo: value.data } }
|
|
180
|
+
: value,
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
signal.addEventListener("abort", () => settle(), { once: true });
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** How the editor follows its notebook. */
|
|
188
|
+
export interface NotebookTransportOptions {
|
|
189
|
+
static: boolean;
|
|
190
|
+
transportType: "websocket" | "sse";
|
|
191
|
+
/** The session route, read before each connection. */
|
|
192
|
+
url: StreamUrl;
|
|
193
|
+
/** The runtime's headers, read before each request. */
|
|
194
|
+
headers: () => Record<string, string>;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Choose the transport for the editor's notebook. */
|
|
198
|
+
export function createNotebookTransport(
|
|
199
|
+
options: NotebookTransportOptions,
|
|
200
|
+
): NotebookTransport {
|
|
201
|
+
if (options.static) {
|
|
202
|
+
return idle;
|
|
203
|
+
}
|
|
204
|
+
if (isWasm()) {
|
|
205
|
+
return pyodide((consumer) =>
|
|
206
|
+
PyodideBridge.INSTANCE.attachMessageConsumer(consumer),
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (options.transportType === "sse") {
|
|
210
|
+
return sessionSse(options.url, options.headers);
|
|
211
|
+
}
|
|
212
|
+
return websocket(options.url);
|
|
213
|
+
}
|
|
@@ -1,47 +1,17 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import type { ConnectionStatus as HostConnectionStatus } from "../host/connection";
|
|
3
4
|
import type { NotificationMessageData } from "../kernel/messages";
|
|
4
5
|
|
|
6
|
+
export {
|
|
7
|
+
ConnectionState,
|
|
8
|
+
ConnectionClosedReason as WebSocketClosedReason,
|
|
9
|
+
} from "../host/connection";
|
|
10
|
+
|
|
5
11
|
export type ConnectionPhase =
|
|
6
12
|
| NotificationMessageData<"startup-progress">["phase"]
|
|
7
13
|
| "reconnecting";
|
|
8
14
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
OPEN: "OPEN",
|
|
13
|
-
CLOSING: "CLOSING",
|
|
14
|
-
CLOSED: "CLOSED",
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
export type ConnectionState =
|
|
18
|
-
(typeof ConnectionState)[keyof typeof ConnectionState];
|
|
19
|
-
|
|
20
|
-
export const WebSocketClosedReason = {
|
|
21
|
-
KERNEL_DISCONNECTED: "KERNEL_DISCONNECTED",
|
|
22
|
-
KERNEL_STARTUP_ERROR: "KERNEL_STARTUP_ERROR",
|
|
23
|
-
} as const;
|
|
24
|
-
|
|
25
|
-
export type WebSocketClosedReason =
|
|
26
|
-
(typeof WebSocketClosedReason)[keyof typeof WebSocketClosedReason];
|
|
27
|
-
|
|
28
|
-
export type ConnectionStatus =
|
|
29
|
-
| {
|
|
30
|
-
state: typeof ConnectionState.CLOSED;
|
|
31
|
-
code: WebSocketClosedReason;
|
|
32
|
-
/**
|
|
33
|
-
* Human-readable reason for closing the connection.
|
|
34
|
-
*/
|
|
35
|
-
reason: string;
|
|
36
|
-
phase?: ConnectionPhase;
|
|
37
|
-
}
|
|
38
|
-
| {
|
|
39
|
-
state: typeof ConnectionState.CONNECTING;
|
|
40
|
-
phase?: ConnectionPhase;
|
|
41
|
-
}
|
|
42
|
-
| {
|
|
43
|
-
state:
|
|
44
|
-
| typeof ConnectionState.OPEN
|
|
45
|
-
| typeof ConnectionState.CLOSING
|
|
46
|
-
| typeof ConnectionState.NOT_STARTED;
|
|
47
|
-
};
|
|
15
|
+
export type ConnectionStatus = HostConnectionStatus & {
|
|
16
|
+
phase?: ConnectionPhase;
|
|
17
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { StreamStopped } from "@marimo-team/client";
|
|
4
|
+
import { useStore } from "jotai";
|
|
5
|
+
import { useEffect, useMemo } from "react";
|
|
6
|
+
import useEvent from "react-use-event-hook";
|
|
7
|
+
import type {
|
|
8
|
+
NotificationMessage,
|
|
9
|
+
NotificationPayload,
|
|
10
|
+
} from "../kernel/messages";
|
|
11
|
+
import {
|
|
12
|
+
createNotebookClient,
|
|
13
|
+
type NotebookClient,
|
|
14
|
+
} from "../host/notebook-client";
|
|
15
|
+
import { notebookClientAtom } from "./state";
|
|
16
|
+
import {
|
|
17
|
+
createNotebookTransport,
|
|
18
|
+
type NotebookTransportOptions,
|
|
19
|
+
} from "./transports/notebook";
|
|
20
|
+
|
|
21
|
+
type Options = Omit<NotebookTransportOptions, "url"> & {
|
|
22
|
+
/** The session route, read before each connection. */
|
|
23
|
+
url: () => string;
|
|
24
|
+
/** Wait until the host can accept a connection. */
|
|
25
|
+
waitUntilReady: () => Promise<void>;
|
|
26
|
+
checkHealth: () => Promise<boolean>;
|
|
27
|
+
onNotification: (notification: NotificationPayload) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function useNotebookClient(options: Options): NotebookClient {
|
|
31
|
+
const store = useStore();
|
|
32
|
+
const { static: isStatic, transportType } = options;
|
|
33
|
+
const controller = useMemo(() => createNotebookClient(store), [store]);
|
|
34
|
+
const url = useEvent(options.url);
|
|
35
|
+
const headers = useEvent(options.headers);
|
|
36
|
+
const waitUntilReady = useEvent(options.waitUntilReady);
|
|
37
|
+
const checkHealth = useEvent(options.checkHealth);
|
|
38
|
+
const onNotification = useEvent(options.onNotification);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const lifetime = new AbortController();
|
|
42
|
+
let needsInitialReadiness = true;
|
|
43
|
+
store.set(notebookClientAtom, controller.client);
|
|
44
|
+
controller.connect({
|
|
45
|
+
transport: createNotebookTransport({
|
|
46
|
+
static: isStatic,
|
|
47
|
+
transportType,
|
|
48
|
+
url: async () => {
|
|
49
|
+
if (needsInitialReadiness) {
|
|
50
|
+
// Explicit retries check current health, even if startup failed.
|
|
51
|
+
needsInitialReadiness = false;
|
|
52
|
+
try {
|
|
53
|
+
await waitUntilReady();
|
|
54
|
+
} catch (error) {
|
|
55
|
+
throw new StreamStopped("Healthy connection never made", {
|
|
56
|
+
cause: error,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return url();
|
|
61
|
+
},
|
|
62
|
+
headers,
|
|
63
|
+
}),
|
|
64
|
+
signal: lifetime.signal,
|
|
65
|
+
checkHealth,
|
|
66
|
+
// The host validates the envelope, not the native notification contents.
|
|
67
|
+
onNotification: (notification) =>
|
|
68
|
+
onNotification({ data: notification as NotificationMessage }),
|
|
69
|
+
});
|
|
70
|
+
return () => {
|
|
71
|
+
lifetime.abort();
|
|
72
|
+
if (store.get(notebookClientAtom) === controller.client) {
|
|
73
|
+
store.set(notebookClientAtom, null);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}, [
|
|
77
|
+
controller,
|
|
78
|
+
store,
|
|
79
|
+
isStatic,
|
|
80
|
+
transportType,
|
|
81
|
+
url,
|
|
82
|
+
headers,
|
|
83
|
+
waitUntilReady,
|
|
84
|
+
checkHealth,
|
|
85
|
+
onNotification,
|
|
86
|
+
]);
|
|
87
|
+
|
|
88
|
+
return controller.client;
|
|
89
|
+
}
|