@marimo-team/islands 0.25.3-dev24 → 0.25.3-dev244
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-DfG3PRaJ.js → ConnectedDataExplorerComponent-BBihxHrr.js} +120 -116
- package/dist/{ErrorBoundary-LHjDFqXG.js → ErrorBoundary-DKniGLW9.js} +16 -16
- package/dist/_baseSet-BfI5FjBM.js +328 -0
- package/dist/{abnfDiagram-VCTEODGH-B3w-XWX8.js → abnfDiagram-VCTEODGH-DBcJVxYP.js} +2 -2
- package/dist/any-language-editor-jGaR0EAo.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-C18U9A6k.js → architectureDiagram-5GKGNRK7-BcHZXF4S.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
- package/dist/assets/__vite-browser-external-BKBpimif.js +1 -0
- package/dist/assets/worker-CgoMtD-_.js +113 -0
- package/dist/{blockDiagram-I7D4REHJ-Cg25UrxT.js → blockDiagram-I7D4REHJ-Dkhe6_PP.js} +1 -1
- package/dist/{button-CvjkwdSk.js → button-B6RjDKJx.js} +227 -217
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-CkVzWJEX.js} +2 -2
- package/dist/{chat-ui-w8SVynkn.js → chat-ui-DgaVxFrc.js} +1309 -1307
- package/dist/{check-BMKBBrdc.js → check-Z_vtI3OL.js} +1 -1
- package/dist/{chunk-IMKFNOWR-CrS5bzqW.js → chunk-IMKFNOWR-CTZlwBAA.js} +1 -1
- package/dist/{chunk-SHT3W25Y-StpvPvUG.js → chunk-SHT3W25Y-53g_RZHm.js} +1 -1
- package/dist/{chunk-SVP7TREG-CBXjbYZC.js → chunk-SVP7TREG-P6abNGV_.js} +1 -1
- package/dist/{chunk-TICWLB2K-Dp6bIb-q.js → chunk-TICWLB2K-BTJJqkyF.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-BFYuxV5g.js → classDiagram-ZZMXUADV-BUGqOrTm.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-D_tjXVMl.js → classDiagram-v2-VYDZK3BY-CXpQvO-s.js} +2 -2
- package/dist/code-visibility-CIUgREo9.js +134 -0
- package/dist/{common-1pRFQo1N.js → common-DzCPFBsv.js} +9917 -9686
- package/dist/config-DbjzjwxX.js +636 -0
- package/dist/{copy-icon-BgUO8jsi.js → copy-icon-CG57cxwb.js} +3 -3
- package/dist/createReducer-DePYJ0F3.js +63 -0
- package/dist/{cynefinDiagram-5FMLGOSQ-DSgYrHB2.js → cynefinDiagram-5FMLGOSQ-DOcnl8wW.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-GYlruCBf.js → dagre-GXQ25YYZ-CuHR9QfG.js} +3 -3
- package/dist/{dagre-BGSfXNEb.js → dagre-mqiMAsFY.js} +531 -680
- package/dist/{data-grid-overlay-editor-UR0x91Ij.js → data-grid-overlay-editor-PstJqwhX.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{debounce-C3jyATpc.js → debounce-DrhhziJv.js} +2 -2
- package/dist/{diagram-S7CK7UJ4-DRu5LX5_.js → diagram-S7CK7UJ4-BPiG4kso.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-DD7uiejP.js → diagram-UQ7AKVKN-_piBOvOC.js} +1 -1
- package/dist/{diagram-VX7I27RA-ByH9KAJJ.js → diagram-VX7I27RA-DCzVeJ8M.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BsQHPRke.js → diagram-Z3DM3KII-D64CF1jQ.js} +1 -1
- package/dist/{dialog-Cc479ZEH.js → dialog-DsZ49mmU.js} +26 -26
- package/dist/{dist-Bvs24R_E.js → dist-11T5wq3_.js} +31 -30
- package/dist/{dist-F8Ep36rk.js → dist-17ugwGZc.js} +59 -58
- package/dist/{dist-BMQf5zIS.js → dist-7cRjf--y.js} +123 -122
- package/dist/{dist-diIx5qJW.js → dist-B8pkfkzc.js} +31 -30
- package/dist/{dist-CN_BeG2I.js → dist-B9UoM_wq.js} +58 -57
- package/dist/{dist-CLdpGQVr.js → dist-BGuMTs1i.js} +118 -117
- package/dist/{dist-BK4Oj99o.js → dist-BHW11fni.js} +18 -17
- package/dist/dist-BLY4m1Wi.js +850 -0
- package/dist/{dist-PXYI_yuP.js → dist-BNlcVoxs.js} +24 -23
- package/dist/{dist-D6d86eNJ.js → dist-BQYe5Bju.js} +47 -46
- package/dist/{dist-CkTTIdBe.js → dist-BX1mn8na.js} +337 -337
- package/dist/{dist-DiDibOYr.js → dist-Bh0PTKUW.js} +151 -150
- package/dist/{dist-CSJ0MDRw.js → dist-CKaXK92p.js} +56 -55
- package/dist/{dist-C8fAKSH1.js → dist-CLhwfhpJ.js} +53 -52
- package/dist/{dist-DoE4XJBC.js → dist-CYeqK4Xw.js} +9801 -10649
- package/dist/{dist-BLfKmR-l.js → dist-Cxlp3WH6.js} +16 -15
- package/dist/{dist-D-wwqlzJ.js → dist-DSJPGj42.js} +158 -157
- package/dist/{dist-BorMD-uX.js → dist-DU9ICsWZ.js} +75 -74
- package/dist/{dist-DBtSl3sf.js → dist-DWv0ALBi.js} +47 -46
- package/dist/{dist-OR1OnN-y.js → dist-DiBpWEsB.js} +31 -30
- package/dist/{dist-CrSP_H1M.js → dist-DiLFTlnl.js} +242 -242
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dist-CSbh1PNP.js → dist-cVDV5IuI.js} +23 -22
- package/dist/{dist-BuaRHxOc.js → dist-fRfaOoq8.js} +44 -43
- package/dist/{dist-Cg7gzw-a.js → dist-gTTI-9Px.js} +78 -77
- package/dist/dropdown-menu-BRiE7Vnp.js +6083 -0
- package/dist/{ebnfDiagram-PWID7BFC-CQRK5_eT.js → ebnfDiagram-PWID7BFC-BapQPML-.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-BKtWrDVh.js → erDiagram-RLTQ6QDP-CNQvC2_Q.js} +1 -1
- package/dist/{error-banner-CFPHFw4h.js → error-banner-IsonnvA0.js} +84 -83
- package/dist/error-entries-CRPfxMqm.js +2505 -0
- package/dist/{esm-D2gTsXEV.js → esm-BgKjMvWw.js} +530 -529
- package/dist/{esm-AMFssoNp.js → esm-CHjVSexr.js} +328 -329
- package/dist/feedback-button-C0iLkz-H.js +374 -0
- package/dist/{flowDiagram-HODETNUW-1IN-ih2E.js → flowDiagram-HODETNUW-BBt6S6oe.js} +2 -2
- package/dist/{formats-X4mMQWzX.js → formats-BK4VefeF.js} +6 -6
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-DPjObn47.js → glide-data-editor-8CBjuK8C.js} +417 -415
- package/dist/{glide-utils-DM9zBO4W.js → glide-utils-CQddGpa-.js} +16 -16
- package/dist/{globals-DOHFyDcV.js → globals-M9WsksQz.js} +3 -3
- package/dist/{graphlib-BmY_CCV9.js → graphlib-nlwT3Wvy.js} +177 -220
- package/dist/hasIn-C20JsQ2m.js +28 -0
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{error-entries-Damuuclv.js → html-to-image-Gx4q3ZoD.js} +26911 -26769
- package/dist/{infoDiagram-27XIBGKW-CkB-zr4p.js → infoDiagram-27XIBGKW-Hd8Ifz82.js} +1 -1
- package/dist/isArrayLikeObject-B-HXCsex.js +626 -0
- package/dist/isEmpty-CdX7MTE1.js +14 -0
- package/dist/{ishikawaDiagram-5VMMS53U-wlyLjBmM.js → ishikawaDiagram-5VMMS53U-CP7hnHWx.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-C2usY0i-.js → kanban-definition-UXKFOSKX-CX91sa9b.js} +1 -1
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-BisjOLiW.js} +12 -12
- package/dist/main.js +10234 -8104
- package/dist/{mermaid-BA-Z6wGL.js → mermaid-Djb3Ni9t.js} +54 -54
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-nKOWS8RR.js → mindmap-definition-YA3MSWOX-DgCNo07O.js} +1 -1
- package/dist/{now-jM8-M7IR.js → now-BKZCLE5P.js} +12 -13
- package/dist/{number-overlay-editor-B3cSnrr6.js → number-overlay-editor-uvNY9IUz.js} +3 -3
- package/dist/{dist-CN8zI-XC.js → objectWithoutPropertiesLoose-ai5NUqGa.js} +262 -240
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{once-BtE-wKRL.js → once-NnpX_HnX.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-Dac9EIKD.js → pegDiagram-XKGWAZYB-SGJhnIKo.js} +2 -2
- package/dist/pick-tCszMUbm.js +35 -0
- package/dist/{pieDiagram-E7YTZNPT-B7S-DsW_.js → pieDiagram-E7YTZNPT-1stXIWCQ.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-CTPTtxXB.js → process-output-D2ISIyIs.js} +4 -4
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-Cfa5Q-hr.js → railroadDiagram-O6MQD6OU-DY1mojzB.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-d8zXCJIk.js → requirementDiagram-BXWQKSXE-gHzhUp0D.js} +1 -1
- package/dist/{reveal-component-CFFzSsPX.js → reveal-component-GMnfGiUU.js} +430 -407
- package/dist/schemas-CdscWNy_.js +4747 -0
- package/dist/select-BSxlITBo.js +1200 -0
- package/dist/{sequenceDiagram-WJ2MYXX4-b6pei3lJ.js → sequenceDiagram-WJ2MYXX4-rjPtD9fB.js} +1 -1
- package/dist/{spec-BJzgmvVa.js → spec-Dq8RNplp.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-Be-xSpaZ.js → stateDiagram-D77RDMKH-DMNxjUxV.js} +4 -4
- package/dist/{stateDiagram-v2-MP3YSRHH-5Y-FxesJ.js → stateDiagram-v2-MP3YSRHH-CumAaqGo.js} +2 -2
- package/dist/static-state-BldGd99T.js +72 -0
- package/dist/strings-BGW-fXVJ.js +507 -0
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-nRRl4NU0.js → swimlanes-42K2YHIH-BU14_Tej.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-BS79510V.js → swimlanesDiagram-VR7AAH4N-CieAnPqJ.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-Dir1o8ml.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-Cfzf8WPf.js → timeline-definition-24CTP7MA-CrVj4E1K.js} +1 -1
- package/dist/toast-BWIPi3aF.js +491 -0
- package/dist/{tooltip-CtBZ5q8p.js → tooltip-C3UnvsRe.js} +329 -305
- package/dist/use-restore-focus-BWO0z1lo.js +1672 -0
- package/dist/{useAsyncData-BD534XmW.js → useAsyncData-DsZMvNXn.js} +15 -14
- package/dist/{useDateFormatter-DkajGwwd.js → useDateFormatter-ChB4eyim.js} +2 -2
- package/dist/{useDeepCompareMemoize-C72_RNsu.js → useDeepCompareMemoize-KMBBux8C.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-cMNQ80CK.js} +1 -1
- package/dist/useLifecycle-BquH9ET-.js +112 -0
- package/dist/useTheme-DgOLVISn.js +337 -0
- package/dist/utils-DXkj82sK.js +813 -0
- package/dist/{vega-component-DfcYgj-Y.js → vega-component-Bwg_Kuh-.js} +171 -170
- 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-CeY6Z1xZ.js → vennDiagram-4TSXK5OY-ZLxQ8yhm.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-Cxs9NtVi.js → wardleyDiagram-VM6X3IG4-D88pcLY1.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-DNWbvPK7.js → xychartDiagram-S5SC5T6Z-_13d4g8g.js} +2 -2
- package/package.json +16 -20
- package/src/__mocks__/document.tsx +63 -0
- package/src/__mocks__/notebook.ts +3 -4
- package/src/__mocks__/partial.ts +26 -0
- package/src/__mocks__/requests.ts +1 -4
- package/src/__tests__/main.test.tsx +24 -1
- package/src/__tests__/module-entry.test.ts +44 -0
- package/src/__tests__/mount.test.ts +1 -21
- package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
- package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
- package/src/components/ai/ai-model-dropdown.tsx +11 -6
- package/src/components/app-config/ai-config.tsx +155 -149
- package/src/components/app-config/app-config-button.tsx +6 -5
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/app-config/common.tsx +7 -9
- package/src/components/app-config/data-form.tsx +112 -113
- package/src/components/app-config/mcp-config.tsx +30 -53
- package/src/components/app-config/user-config-form.css +91 -0
- package/src/components/app-config/user-config-form.tsx +266 -349
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/__tests__/notebook-access-selector.test.tsx +64 -0
- package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +3 -2
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/capabilities-popover.tsx +1 -5
- package/src/components/chat/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +23 -104
- package/src/components/chat/chat-utils.ts +4 -8
- package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
- package/src/components/chat/notebook-access-selector.tsx +100 -0
- package/src/components/data-table/TableBottomBar.tsx +4 -1
- package/src/components/data-table/TableTopBar.tsx +2 -0
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
- 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__/data-table.test.tsx +1 -0
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
- package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
- package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
- 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__/spec-snapshot.test.ts +20 -20
- package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
- package/src/components/data-table/charts/charts.tsx +40 -30
- 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/chart-spec-model.tsx +23 -16
- 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 +36 -20
- package/src/components/data-table/data-table.tsx +17 -1
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +76 -48
- package/src/components/data-table/pagination.tsx +44 -33
- package/src/components/data-table/range-focus/atoms.ts +4 -6
- package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
- package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
- package/src/components/data-table/renderers.tsx +16 -7
- package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
- 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/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +96 -5
- package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/__tests__/utils.test.ts +57 -6
- package/src/components/datasources/column-preview.tsx +17 -12
- package/src/components/datasources/datasources.tsx +56 -43
- package/src/components/datasources/utils.ts +32 -23
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/custom-node.tsx +1 -1
- package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
- package/src/components/dependency-graph/elements.ts +24 -21
- package/src/components/dependency-graph/minimap-content.tsx +13 -19
- package/src/components/dependency-graph/panels.tsx +4 -2
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/Output.test.tsx +50 -32
- package/src/{core/attachments/__tests__/toast.test.tsx → components/editor/__tests__/agent-toast.test.tsx} +1 -1
- package/src/components/editor/__tests__/data-attributes.test.tsx +28 -14
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/output-persistence.test.tsx +6 -2
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +3 -3
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +40 -10
- package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +6 -10
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +113 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/pair-with-agent-commands.ts +10 -6
- package/src/components/editor/actions/pair-with-agent-modal.tsx +24 -21
- package/src/components/editor/actions/pair-with-agent.tsx +15 -10
- package/src/components/editor/actions/useCellActionButton.tsx +36 -31
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +25 -29
- package/src/components/editor/actions/useRestartKernel.tsx +1 -1
- package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
- package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
- 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/__tests__/connection-notice.test.tsx +1 -1
- package/src/components/editor/alerts/connection-notice.tsx +1 -1
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +1 -1
- package/src/components/editor/app-container.tsx +1 -1
- package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
- package/src/components/editor/cell/CreateCellButton.tsx +15 -21
- package/src/components/editor/cell/DeleteButton.tsx +3 -2
- package/src/components/editor/cell/RunButton.tsx +2 -2
- package/src/components/editor/cell/StagedAICell.tsx +10 -2
- package/src/components/editor/cell/StopButton.tsx +2 -2
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +4 -2
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/cell-actions.tsx +12 -1
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +46 -165
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +11 -4
- package/src/components/editor/cell/useAddCell.ts +4 -8
- package/src/components/editor/cell/useDeleteCell.tsx +10 -36
- package/src/components/editor/cell/useRunCells.ts +2 -5
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/cell/useSplitCell.tsx +10 -6
- package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
- package/src/components/editor/chrome/components/feedback-button.tsx +2 -8
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
- package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
- package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
- package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
- package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +10 -12
- package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +6 -9
- package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +62 -3
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +4 -4
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
- package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -2
- package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
- 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/columns/__tests__/cell-column.test.tsx +1 -1
- package/src/components/editor/columns/cell-column.tsx +1 -1
- package/src/components/editor/columns/sortable-column.tsx +2 -2
- package/src/components/editor/connections/components.tsx +5 -10
- package/src/components/editor/controls/Controls.tsx +4 -4
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +10 -4
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/documentation.css +34 -11
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +25 -20
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/errors/send-error-report-button.tsx +3 -6
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +48 -15
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- 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/header/__tests__/filename-form.test.tsx +1 -4
- package/src/components/editor/header/__tests__/status.test.tsx +5 -3
- package/src/components/editor/header/app-header.tsx +1 -1
- package/src/components/editor/header/filename-form.tsx +1 -1
- package/src/components/editor/header/status.tsx +40 -20
- package/src/components/editor/links/__tests__/cell-link.test.tsx +148 -0
- package/src/components/editor/links/cell-link-list.tsx +1 -1
- package/src/components/editor/links/cell-link.tsx +17 -7
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
- package/src/components/editor/navigation/__tests__/navigation.test.ts +108 -85
- package/src/components/editor/navigation/__tests__/selection.test.ts +43 -21
- package/src/components/editor/navigation/clipboard.ts +17 -14
- package/src/components/editor/navigation/focus-utils.ts +23 -4
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +17 -33
- package/src/components/editor/navigation/navigation.ts +71 -70
- package/src/components/editor/navigation/selection.ts +30 -29
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +29 -32
- package/src/components/editor/output/MarimoErrorOutput.tsx +2 -1
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- package/src/components/editor/output/Outputs.css +8 -0
- package/src/components/editor/output/VideoOutput.tsx +6 -0
- package/src/components/editor/output/__tests__/VideoOutput.test.tsx +131 -0
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +33 -20
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/cell-array.tsx +22 -33
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
- package/src/components/editor/stdin-blocking-alert.tsx +1 -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/markdown/markdown-renderer.tsx +4 -8
- 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/edit-page.tsx +19 -17
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +89 -0
- package/src/components/scratchpad/scratchpad.tsx +43 -32
- package/src/components/scratchpad/state.ts +7 -0
- package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
- package/src/components/slides/__tests__/minimap.test.ts +38 -19
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
- package/src/components/slides/minimap.tsx +17 -12
- package/src/components/slides/reveal-component.tsx +58 -26
- package/src/components/slides/reveal-slides.css +5 -4
- package/src/components/slides/slide-cell-view.tsx +4 -5
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/slides/slide-scroll-hint.tsx +3 -1
- package/src/components/sort/SortableCellsProvider.tsx +8 -25
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +46 -42
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/__tests__/fullscreen.test.tsx +44 -2
- package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/components/ui/fullscreen.tsx +25 -1
- package/src/components/ui/range-slider.tsx +22 -9
- package/src/core/MarimoApp.tsx +3 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +32 -33
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
- package/src/core/ai/context/providers/cell-output.ts +2 -2
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/staged-cells.ts +18 -19
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +40 -88
- package/src/core/ai/tools/__tests__/registry.test.ts +17 -0
- package/src/core/ai/tools/base.ts +18 -15
- package/src/core/ai/tools/edit-notebook-tool.ts +86 -80
- package/src/core/ai/tools/registry.ts +13 -10
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -37
- package/src/core/cells/__tests__/actions.test.ts +624 -35
- package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
- package/src/core/cells/__tests__/arrange.test.ts +432 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +251 -2540
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/document.test.ts +164 -0
- package/src/core/cells/__tests__/editor.test.ts +57 -0
- package/src/core/cells/__tests__/flush-document.test.ts +40 -0
- package/src/core/cells/__tests__/harness.ts +106 -0
- package/src/core/cells/__tests__/layout.test.ts +177 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +122 -0
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/__tests__/session.test.ts +445 -211
- package/src/core/cells/__tests__/utils.test.ts +9 -108
- package/src/core/cells/actions.ts +675 -6
- package/src/core/cells/add-missing-import.ts +47 -43
- package/src/core/cells/arrange.ts +529 -0
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +126 -1363
- package/src/core/cells/columns.ts +38 -0
- package/src/core/cells/document.ts +178 -0
- package/src/core/cells/edit.ts +30 -0
- package/src/core/cells/editor.ts +82 -0
- package/src/core/cells/layout.ts +221 -0
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/cells/pending-delete-service.ts +3 -7
- package/src/core/cells/session.ts +76 -53
- package/src/core/cells/types.ts +22 -6
- package/src/core/cells/utils.ts +10 -8
- package/src/core/codemirror/__tests__/format.test.ts +0 -34
- package/src/core/codemirror/__tests__/setup.test.ts +29 -29
- package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
- package/src/core/codemirror/ai/resources.ts +1 -1
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +2 -6
- package/src/core/codemirror/cells/extensions.ts +30 -28
- package/src/core/codemirror/cells/state.ts +1 -6
- package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
- package/src/core/codemirror/copilot/getCodes.ts +2 -2
- package/src/core/codemirror/format.ts +6 -23
- package/src/core/codemirror/keymaps/vim.ts +4 -8
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
- package/src/core/codemirror/language/cell-code.ts +114 -0
- package/src/core/codemirror/language/extension.ts +52 -35
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +16 -10
- package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/language/utils.ts +9 -39
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
- package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
- package/src/core/codemirror/lsp/utils.ts +1 -1
- package/src/core/codemirror/misc/__tests__/paste.test.ts +3 -1
- package/src/core/codemirror/misc/paste.ts +1 -1
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/readonly/extension.ts +2 -2
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/config/__tests__/app-config.test.ts +64 -0
- package/src/core/config/__tests__/config-schema.test.ts +56 -6
- package/src/core/config/config-schema.ts +17 -4
- package/src/core/config/config.ts +65 -20
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/documentation/doc-lookup.ts +1 -1
- package/src/core/edit-app.tsx +21 -28
- package/src/core/errors/error-entries.ts +4 -1
- package/src/core/export/hooks.ts +1 -1
- package/src/core/export/layout.ts +2 -2
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
- package/src/core/islands/__tests__/bridge.test.ts +85 -27
- package/src/core/islands/bootstrap.ts +46 -53
- package/src/core/islands/bridge.ts +84 -25
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/islands/components/web-components.tsx +1 -1
- package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
- package/src/core/islands/worker/controller.ts +4 -10
- package/src/core/islands/worker/worker.tsx +33 -33
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/kernel/__tests__/handlers.test.ts +7 -153
- package/src/core/kernel/handlers.ts +19 -72
- package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
- package/src/core/meta/code-visibility.ts +18 -9
- package/src/core/network/__tests__/connection.test.ts +1 -1
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
- package/src/core/network/connection-notice.ts +1 -1
- package/src/core/network/connection.ts +1 -1
- package/src/core/network/requests-lazy.ts +2 -5
- package/src/core/network/requests-network.ts +5 -31
- package/src/core/network/requests-static.ts +1 -4
- package/src/core/network/requests-toasting.tsx +1 -4
- package/src/core/network/types.ts +6 -14
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/notebook/__tests__/operations.test.ts +51 -0
- package/src/core/notebook/attachments.ts +38 -0
- package/src/core/notebook/document/__tests__/codemirror.test.ts +758 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
- package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
- package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
- package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/notebook/document/__tests__/model.test.ts +247 -0
- package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/notebook/document/__tests__/state.test.ts +459 -0
- package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
- package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
- package/src/core/notebook/document/__tests__/test-host.ts +247 -0
- package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
- package/src/core/notebook/document/__tests__/user.ts +61 -0
- package/src/core/notebook/document/codemirror.ts +216 -0
- package/src/core/notebook/document/draft.ts +502 -0
- package/src/core/notebook/document/hooks.tsx +118 -0
- package/src/core/notebook/document/index.ts +24 -0
- package/src/core/notebook/document/model.ts +102 -0
- package/src/core/notebook/document/select.ts +41 -0
- package/src/core/notebook/document/state.ts +378 -0
- package/src/core/notebook/document/sync.ts +369 -0
- package/src/core/notebook/index.ts +19 -0
- package/src/core/notebook/operations.ts +30 -0
- package/src/core/notebook/replica/AGENTS.md +11 -0
- package/src/core/{host → notebook/replica}/__tests__/attachments.test.ts +9 -10
- package/src/core/{host → notebook/replica}/__tests__/document.test.ts +18 -16
- package/src/core/notebook/replica/__tests__/executions.test.ts +201 -0
- package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
- package/src/core/notebook/replica/__tests__/replica.test.ts +559 -0
- package/src/core/notebook/replica/__tests__/results.test.ts +193 -0
- package/src/core/notebook/replica/__tests__/runtime.test.ts +78 -0
- package/src/core/notebook/replica/backend.ts +19 -0
- package/src/core/notebook/replica/connection.ts +42 -0
- package/src/core/notebook/replica/index.ts +20 -0
- package/src/core/notebook/replica/replica.ts +336 -0
- package/src/core/{host → notebook/replica}/resources/attachments.ts +6 -3
- package/src/core/{host → notebook/replica}/resources/document.ts +3 -3
- package/src/core/notebook/replica/resources/executions.ts +157 -0
- package/src/core/notebook/replica/resources/results.ts +48 -0
- package/src/core/notebook/replica/resources/runtime.ts +14 -0
- package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
- package/src/core/packages/useSandboxController.ts +1 -1
- package/src/core/run-app.tsx +48 -51
- package/src/core/runtime/__tests__/adapter.test.ts +1 -1
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -74
- package/src/core/runtime/adapter.ts +1 -1
- package/src/core/runtime/config.ts +2 -2
- package/src/core/runtime/runtime.ts +33 -46
- package/src/core/runtime/types.ts +0 -2
- package/src/core/saving/__tests__/document.test.tsx +123 -0
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
- package/src/core/saving/document.ts +33 -0
- package/src/core/saving/filename.ts +1 -1
- package/src/core/saving/save-component.tsx +39 -60
- package/src/core/saving/state.ts +38 -39
- package/src/core/saving/useAutoSave.ts +17 -53
- package/src/core/session/__tests__/backend.test.ts +236 -0
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +184 -0
- package/src/core/{websocket → session}/__tests__/useNotebookSession.hook.test.tsx +213 -262
- package/src/core/session/active-notebook.ts +28 -0
- package/src/core/session/backend.ts +123 -0
- package/src/core/session/embedded.ts +7 -0
- package/src/core/{websocket → session}/types.ts +2 -2
- package/src/core/session/useNotebookReplica.ts +74 -0
- package/src/core/{websocket → session}/useNotebookSession.tsx +77 -64
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/{websocket → transports}/__tests__/connection-state.test.ts +1 -13
- package/src/core/transports/__tests__/server.test.ts +408 -0
- package/src/core/transports/__tests__/static.test.ts +306 -0
- package/src/core/transports/__tests__/wasm.test.ts +166 -0
- package/src/core/{websocket → transports}/connection-state.ts +9 -16
- package/src/core/transports/server.ts +152 -0
- package/src/core/transports/static.ts +166 -0
- package/src/core/transports/wasm.ts +97 -0
- package/src/core/vscode/__tests__/vscode-bindings.test.ts +125 -0
- package/src/core/vscode/vscode-bindings.ts +14 -2
- package/src/core/wasm/__tests__/bridge.test.ts +105 -65
- package/src/core/wasm/__tests__/worker.test.ts +187 -0
- package/src/core/wasm/bridge.ts +69 -72
- package/src/core/wasm/rpc.ts +15 -3
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +55 -51
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/save-worker.ts +9 -10
- package/src/core/wasm/worker/types.ts +29 -18
- package/src/core/wasm/worker/worker.ts +89 -45
- package/src/css/app/codemirror.css +1 -1
- package/src/css/common.css +1 -1
- package/src/css/globals.css +66 -22
- 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 +6 -10
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useEventListener.ts +1 -2
- 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 +20 -15
- package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +69 -37
- 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 +16 -2
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +387 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/model.ts +3 -1
- package/src/plugins/impl/anywidget/registry.ts +18 -14
- 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 +14 -11
- 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/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +44 -16
- 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/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/DownloadPlugin.tsx +7 -11
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/plugins/layout/__test__/DownloadPlugin.test.tsx +196 -0
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/cell.stories.tsx +2 -5
- package/src/stories/data-table.stories.tsx +31 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +28 -23
- package/src/stories/runtime-story.tsx +23 -17
- 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__/{createReducer.test.ts → createReducer.test.tsx} +29 -0
- package/src/utils/__tests__/download.test.tsx +62 -9
- package/src/utils/__tests__/numbers.test.ts +105 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +11 -2
- package/src/utils/blob.ts +1 -1
- package/src/utils/createReducer.ts +53 -26
- package/src/utils/download.ts +55 -3
- package/src/utils/maps.ts +0 -3
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +4 -9
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/_baseMerge-BiGRwuqv.js +0 -165
- package/dist/any-language-editor-D4q-IFcM.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/assets/worker-HPY9fbhz.js +0 -114
- package/dist/code-visibility-HTfE7PV1.js +0 -138
- package/dist/dropdown-menu-DHP9P4VE.js +0 -4678
- package/dist/feedback-button-BL7Ed1J3.js +0 -379
- package/dist/hasIn-o2Us0uVx.js +0 -132
- package/dist/html-to-image-BdA59IUD.js +0 -3251
- package/dist/isArrayLikeObject-BZl-15ir.js +0 -450
- package/dist/isEmpty-BSZ1LaUo.js +0 -35
- package/dist/isSymbol-kQcfYbNX.js +0 -8
- package/dist/label-DoysmLMW.js +0 -281
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/objectWithoutPropertiesLoose-BRDcTsfB.js +0 -23
- package/dist/pick-CJeoxYOS.js +0 -51
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/dist/select-DemoKT4G.js +0 -1344
- package/dist/toDate-B5mIgxwZ.js +0 -1185
- package/dist/toast-PkdZraM8.js +0 -1830
- package/dist/use-restore-focus-CKjfFjLM.js +0 -6369
- package/dist/useLifecycle-BGWzTwHK.js +0 -169
- package/dist/useTheme-BhQvec43.js +0 -904
- package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +0 -50
- package/src/components/editor/chrome/wrapper/footer-items/rtc-status.tsx +0 -65
- package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
- package/src/components/editor/navigation/state.ts +0 -65
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
- package/src/core/ai/tools/run-cells-tool.ts +0 -303
- package/src/core/attachments/state.ts +0 -18
- package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
- package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
- package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
- package/src/core/cells/document-changes.ts +0 -944
- package/src/core/codemirror/rtc/extension.ts +0 -453
- package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +0 -52
- package/src/core/codemirror/rtc/loro/awareness.ts +0 -531
- package/src/core/codemirror/rtc/loro/colors.ts +0 -38
- package/src/core/codemirror/rtc/loro/sync.ts +0 -168
- package/src/core/host/AGENTS.md +0 -11
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/fixtures.ts +0 -39
- package/src/core/host/__tests__/notebook-client.test.ts +0 -433
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/__tests__/stream.test.ts +0 -209
- package/src/core/host/connection.ts +0 -81
- package/src/core/host/events.ts +0 -61
- package/src/core/host/notebook-client.ts +0 -290
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/host/resources/resource.ts +0 -47
- package/src/core/host/stream.ts +0 -211
- package/src/core/rtc/state.ts +0 -34
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/wasm/worker/message-buffer.ts +0 -33
- package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -170
- package/src/core/websocket/state.ts +0 -7
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
- 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/create.ts +0 -31
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -50
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useNotebookClient.ts +0 -88
- package/src/utils/__tests__/id-tree.test.ts +0 -2145
- package/src/utils/id-tree.tsx +0 -1134
- /package/src/{core/attachments/toast.ts → components/editor/agent-toast.ts} +0 -0
- /package/src/core/{websocket → session}/connection-utils.ts +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/** How a document's cells fall into columns. */
|
|
4
|
+
|
|
5
|
+
import type { EditableDocument } from "@/core/notebook/document";
|
|
6
|
+
import type { CellId } from "./ids";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Each cell's column: its `column` config, or the column of the cell before
|
|
10
|
+
* it. The first cell starts in column 0.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveColumns(
|
|
13
|
+
document: EditableDocument,
|
|
14
|
+
): Map<CellId, number> {
|
|
15
|
+
const columns = new Map<CellId, number>();
|
|
16
|
+
let current = 0;
|
|
17
|
+
for (const id of document.order) {
|
|
18
|
+
const column = document.cells.get(id)?.config.column;
|
|
19
|
+
if (column != null && column >= 0) {
|
|
20
|
+
current = column;
|
|
21
|
+
}
|
|
22
|
+
// The protocol's ids are plain strings; the notebook brands them.
|
|
23
|
+
columns.set(id as CellId, current);
|
|
24
|
+
}
|
|
25
|
+
return columns;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The cells of each column in order, with empty columns for gaps. */
|
|
29
|
+
export function groupByColumn(document: EditableDocument): CellId[][] {
|
|
30
|
+
const columns: CellId[][] = [[]];
|
|
31
|
+
for (const [id, column] of resolveColumns(document)) {
|
|
32
|
+
while (columns.length <= column) {
|
|
33
|
+
columns.push([]);
|
|
34
|
+
}
|
|
35
|
+
columns[column].push(id);
|
|
36
|
+
}
|
|
37
|
+
return columns;
|
|
38
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Make the notebook state follow the host document while cells live in
|
|
5
|
+
* both. Edits go the other way through the document model directly: the
|
|
6
|
+
* cell operations write it, and each cell editor is bound to its cell.
|
|
7
|
+
*
|
|
8
|
+
* TODO(MO-8028): Delete this module once components read cells from the
|
|
9
|
+
* document model and `notebookAtom` holds only runtime and editor state.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { dequal as isEqual } from "dequal";
|
|
13
|
+
import type { createStore } from "jotai";
|
|
14
|
+
import { createRef } from "react";
|
|
15
|
+
import type {
|
|
16
|
+
DocumentModel,
|
|
17
|
+
EditableCell,
|
|
18
|
+
EditableDocument,
|
|
19
|
+
} from "@/core/notebook/document";
|
|
20
|
+
import { store } from "../state/jotai";
|
|
21
|
+
import { activeDocumentModelAtom } from "../session/active-notebook";
|
|
22
|
+
import type { NotebookState } from "./cells";
|
|
23
|
+
import type { CellId } from "./ids";
|
|
24
|
+
import { followColumnsAtom } from "./layout";
|
|
25
|
+
import {
|
|
26
|
+
type CellData,
|
|
27
|
+
createCell,
|
|
28
|
+
createCellConfig,
|
|
29
|
+
createCellRuntimeState,
|
|
30
|
+
isEdited,
|
|
31
|
+
} from "./types";
|
|
32
|
+
|
|
33
|
+
// Following the document ----------------------------------------------------
|
|
34
|
+
|
|
35
|
+
/** The cell's data after the document's cell, the same object when nothing differs. */
|
|
36
|
+
function followCell(current: CellData, cell: EditableCell): CellData {
|
|
37
|
+
// Withheld source keeps the code this client has.
|
|
38
|
+
const code = cell.code ?? current.code;
|
|
39
|
+
const config = isEqual(current.config, cell.config)
|
|
40
|
+
? current.config
|
|
41
|
+
: createCellConfig(cell.config);
|
|
42
|
+
if (
|
|
43
|
+
code === current.code &&
|
|
44
|
+
cell.name === current.name &&
|
|
45
|
+
config === current.config
|
|
46
|
+
) {
|
|
47
|
+
return current;
|
|
48
|
+
}
|
|
49
|
+
if (code === current.code) {
|
|
50
|
+
return { ...current, name: cell.name, config };
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
...current,
|
|
54
|
+
code,
|
|
55
|
+
name: cell.name,
|
|
56
|
+
config,
|
|
57
|
+
edited: isEdited(current.lastCodeRun, code),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Make the notebook's cells and order follow the document.
|
|
63
|
+
*
|
|
64
|
+
* Returns the same state when nothing differs, so a local edit that the
|
|
65
|
+
* document already reflects changes nothing.
|
|
66
|
+
*
|
|
67
|
+
* TODO(MO-8028): Delete with `reconcileDocument` once cells are read from
|
|
68
|
+
* the document model.
|
|
69
|
+
*/
|
|
70
|
+
export function applyDocument(
|
|
71
|
+
state: NotebookState,
|
|
72
|
+
document: EditableDocument,
|
|
73
|
+
): NotebookState {
|
|
74
|
+
// The protocol's ids are plain strings; the notebook brands them.
|
|
75
|
+
const cellIds = isEqual(document.order, state.cellIds)
|
|
76
|
+
? state.cellIds
|
|
77
|
+
: ([...document.order] as CellId[]);
|
|
78
|
+
let { cellData, cellRuntime, cellHandles } = state;
|
|
79
|
+
for (const id of cellIds) {
|
|
80
|
+
const cell = document.cells.get(id);
|
|
81
|
+
const current = state.cellData[id];
|
|
82
|
+
if (cell === undefined) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (current === undefined) {
|
|
86
|
+
// A new cell with code is stale until it runs. The kernel's last run
|
|
87
|
+
// settles it on kernel-ready.
|
|
88
|
+
const code = cell.code ?? "";
|
|
89
|
+
cellData = {
|
|
90
|
+
...cellData,
|
|
91
|
+
[id]: createCell({
|
|
92
|
+
id,
|
|
93
|
+
code,
|
|
94
|
+
name: cell.name,
|
|
95
|
+
config: createCellConfig(cell.config),
|
|
96
|
+
edited: isEdited(null, code),
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
cellRuntime = {
|
|
100
|
+
...cellRuntime,
|
|
101
|
+
[id]: cellRuntime[id] ?? createCellRuntimeState(),
|
|
102
|
+
};
|
|
103
|
+
cellHandles = { ...cellHandles, [id]: createRef() };
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const next = followCell(current, cell);
|
|
107
|
+
if (next !== current) {
|
|
108
|
+
cellData = { ...cellData, [id]: next };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const present = new Set(cellIds);
|
|
112
|
+
const removed = state.cellIds.filter((id) => !present.has(id));
|
|
113
|
+
if (removed.length > 0) {
|
|
114
|
+
const gone = new Set(removed);
|
|
115
|
+
const keep = <V>(record: Record<CellId, V>): Record<CellId, V> =>
|
|
116
|
+
Object.fromEntries(
|
|
117
|
+
Object.entries(record).filter(([id]) => !gone.has(id as CellId)),
|
|
118
|
+
) as Record<CellId, V>;
|
|
119
|
+
cellData = keep(cellData);
|
|
120
|
+
cellRuntime = keep(cellRuntime);
|
|
121
|
+
cellHandles = keep(cellHandles);
|
|
122
|
+
}
|
|
123
|
+
if (
|
|
124
|
+
cellIds === state.cellIds &&
|
|
125
|
+
cellData === state.cellData &&
|
|
126
|
+
removed.length === 0
|
|
127
|
+
) {
|
|
128
|
+
return state;
|
|
129
|
+
}
|
|
130
|
+
return { ...state, cellIds, cellData, cellRuntime, cellHandles };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Reconcile the model's document and name its columns, now and on each
|
|
135
|
+
* change, until the signal aborts.
|
|
136
|
+
*
|
|
137
|
+
* TODO(MO-8028): Delete with `applyDocument`.
|
|
138
|
+
*/
|
|
139
|
+
export function followDocument({
|
|
140
|
+
store,
|
|
141
|
+
model,
|
|
142
|
+
reconcile,
|
|
143
|
+
signal,
|
|
144
|
+
}: {
|
|
145
|
+
store: ReturnType<typeof createStore>;
|
|
146
|
+
model: Pick<DocumentModel, "documentAtom">;
|
|
147
|
+
reconcile: (document: EditableDocument) => void;
|
|
148
|
+
signal: AbortSignal;
|
|
149
|
+
}): void {
|
|
150
|
+
const follow = () => {
|
|
151
|
+
const document = store.get(model.documentAtom);
|
|
152
|
+
if (document !== null) {
|
|
153
|
+
reconcile(document);
|
|
154
|
+
store.set(followColumnsAtom, document);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const unsubscribe = store.sub(model.documentAtom, follow);
|
|
158
|
+
signal.addEventListener("abort", unsubscribe, { once: true });
|
|
159
|
+
follow();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Commands that read the document on the host -------------------------------
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Send this client's edits to the host before a command that reads them
|
|
166
|
+
* there. Without a document or a backend, as on a static page, there is
|
|
167
|
+
* nothing to send and the command proceeds.
|
|
168
|
+
*/
|
|
169
|
+
export async function flushDocument(): Promise<void> {
|
|
170
|
+
const model = store.get(activeDocumentModelAtom);
|
|
171
|
+
if (
|
|
172
|
+
model === null ||
|
|
173
|
+
store.get(model.syncStatusAtom).status === "unavailable"
|
|
174
|
+
) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
await model.flush();
|
|
178
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/** The active document model, as the notebook operations reach it. */
|
|
4
|
+
|
|
5
|
+
import type { Getter, Setter } from "jotai";
|
|
6
|
+
import type { DocumentModel, EditableDocument } from "@/core/notebook/document";
|
|
7
|
+
import { activeDocumentModelAtom } from "../session/active-notebook";
|
|
8
|
+
import { notebookAtom } from "./cells";
|
|
9
|
+
import type { CellId } from "./ids";
|
|
10
|
+
|
|
11
|
+
export function modelOf(get: Getter): DocumentModel {
|
|
12
|
+
const model = get(activeDocumentModelAtom);
|
|
13
|
+
if (!model) {
|
|
14
|
+
throw new Error("The notebook has no document to edit");
|
|
15
|
+
}
|
|
16
|
+
return model;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function documentOf(get: Getter): EditableDocument {
|
|
20
|
+
const document = get(modelOf(get).documentAtom);
|
|
21
|
+
if (!document) {
|
|
22
|
+
throw new Error("The notebook has no document to edit");
|
|
23
|
+
}
|
|
24
|
+
return document;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Scroll to and focus the cell once it mounts. */
|
|
28
|
+
export function focusWhenMounted(set: Setter, cellId: CellId): void {
|
|
29
|
+
set(notebookAtom, (state) => ({ ...state, scrollKey: cellId }));
|
|
30
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/** What only this browser knows about cells: hidden code showing for now, and editor state to restore. */
|
|
4
|
+
|
|
5
|
+
import { atom, useAtomValue } from "jotai";
|
|
6
|
+
import { useMemo } from "react";
|
|
7
|
+
import type { SerializedEditorState } from "../codemirror/types";
|
|
8
|
+
import type { CellId } from "./ids";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hidden cells whose code is showing for now: a cell being edited, one just
|
|
12
|
+
* created, or one just made hidden. Blurring the cell hides it again.
|
|
13
|
+
*/
|
|
14
|
+
export const shownHiddenCodeAtom = atom<ReadonlySet<CellId>>(new Set<CellId>());
|
|
15
|
+
|
|
16
|
+
export const useShowsHiddenCode = (cellId: CellId) =>
|
|
17
|
+
useAtomValue(
|
|
18
|
+
useMemo(
|
|
19
|
+
() => atom((get) => get(shownHiddenCodeAtom).has(cellId)),
|
|
20
|
+
[cellId],
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
/** Whether a cell's code is hidden on the page. */
|
|
25
|
+
export function isCodeHidden(
|
|
26
|
+
hideCode: boolean | undefined,
|
|
27
|
+
shown: ReadonlySet<CellId>,
|
|
28
|
+
cellId: CellId,
|
|
29
|
+
): boolean {
|
|
30
|
+
return Boolean(hideCode) && !shown.has(cellId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const showHiddenCodeAtom = atom(
|
|
34
|
+
null,
|
|
35
|
+
(_get, set, { cellId }: { cellId: CellId }): void => {
|
|
36
|
+
set(shownHiddenCodeAtom, (cells) => new Set([...cells, cellId]));
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/** Hide a cell's code again. Returns whether it was showing. */
|
|
41
|
+
export const hideShownCodeAtom = atom(
|
|
42
|
+
null,
|
|
43
|
+
(get, set, { cellId }: { cellId: CellId }): boolean => {
|
|
44
|
+
if (!get(shownHiddenCodeAtom).has(cellId)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
set(shownHiddenCodeAtom, (cells) => {
|
|
48
|
+
const next = new Set(cells);
|
|
49
|
+
next.delete(cellId);
|
|
50
|
+
return next;
|
|
51
|
+
});
|
|
52
|
+
return true;
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Editor state for cells about to mount again, such as a cell undo brings
|
|
58
|
+
* back. The editor takes its entry when it mounts, and deleting the cell
|
|
59
|
+
* drops it.
|
|
60
|
+
*/
|
|
61
|
+
export const restoredEditorStatesAtom = atom<
|
|
62
|
+
ReadonlyMap<CellId, SerializedEditorState>
|
|
63
|
+
>(new Map<CellId, SerializedEditorState>());
|
|
64
|
+
|
|
65
|
+
export const useRestoredEditorState = (cellId: CellId) =>
|
|
66
|
+
useAtomValue(
|
|
67
|
+
useMemo(
|
|
68
|
+
() => atom((get) => get(restoredEditorStatesAtom).get(cellId) ?? null),
|
|
69
|
+
[cellId],
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
export const takeRestoredEditorStateAtom = atom(
|
|
74
|
+
null,
|
|
75
|
+
(_get, set, { cellId }: { cellId: CellId }): void => {
|
|
76
|
+
set(restoredEditorStatesAtom, (states) => {
|
|
77
|
+
const next = new Map(states);
|
|
78
|
+
next.delete(cellId);
|
|
79
|
+
return next;
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
);
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/** The cells as they appear on the page: by column, with folded sections hidden. */
|
|
4
|
+
|
|
5
|
+
import { atom, useAtomValue } from "jotai";
|
|
6
|
+
import type { EditableDocument } from "@/core/notebook/document";
|
|
7
|
+
import { findCollapseRange } from "../dom/outline";
|
|
8
|
+
import { activeDocumentModelAtom } from "../session/active-notebook";
|
|
9
|
+
import { cellOutlinesAtom } from "./cells";
|
|
10
|
+
import { groupByColumn } from "./columns";
|
|
11
|
+
import { CellId } from "./ids";
|
|
12
|
+
import type { Outline } from "./outline";
|
|
13
|
+
|
|
14
|
+
/** A column's identity on this page, as drag and drop and saved widths refer to it. */
|
|
15
|
+
export type CellColumnId = string & { __brand: "CellColumnId" };
|
|
16
|
+
|
|
17
|
+
/** The headers whose sections the user folded. Only this browser knows. */
|
|
18
|
+
export const collapsedAtom = atom<ReadonlySet<CellId>>(new Set<CellId>());
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* This browser's names for the document's columns, by position. The
|
|
22
|
+
* document knows columns only by position, so `followColumnsAtom` names
|
|
23
|
+
* a column as it appears and forgets one as it goes, and the column
|
|
24
|
+
* operations carry the names along as they rearrange.
|
|
25
|
+
*/
|
|
26
|
+
export const columnIdsAtom = atom<readonly CellColumnId[]>([]);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Trailing columns a rearrangement here emptied. The document cannot hold
|
|
30
|
+
* an empty column at its end, so the page keeps them, as drop targets for
|
|
31
|
+
* the cell being dragged, until a drop compacts them.
|
|
32
|
+
*/
|
|
33
|
+
export const emptyColumnIdsAtom = atom<readonly CellColumnId[]>([]);
|
|
34
|
+
|
|
35
|
+
export function newColumnId(): CellColumnId {
|
|
36
|
+
return `column-${CellId.create()}` as CellColumnId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isColumnId(id: unknown): id is CellColumnId {
|
|
40
|
+
return typeof id === "string" && id.startsWith("column-");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Name the document's columns as the document changes. A column that
|
|
45
|
+
* appears takes over an empty column the page keeps, or gets a fresh id;
|
|
46
|
+
* one that goes is forgotten.
|
|
47
|
+
*/
|
|
48
|
+
export const followColumnsAtom = atom(
|
|
49
|
+
null,
|
|
50
|
+
(get, set, document: EditableDocument): void => {
|
|
51
|
+
const count = groupByColumn(document).length;
|
|
52
|
+
const ids = get(columnIdsAtom);
|
|
53
|
+
if (ids.length === count) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const empty = get(emptyColumnIdsAtom);
|
|
57
|
+
const named = [...ids, ...empty].slice(0, count);
|
|
58
|
+
while (named.length < count) {
|
|
59
|
+
named.push(newColumnId());
|
|
60
|
+
}
|
|
61
|
+
set(columnIdsAtom, named);
|
|
62
|
+
set(emptyColumnIdsAtom, empty.slice(Math.max(0, count - ids.length)));
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
/** The document's columns, each with its id, then the empty ones the page keeps. */
|
|
67
|
+
function columnsOf(
|
|
68
|
+
document: EditableDocument | null,
|
|
69
|
+
ids: readonly CellColumnId[],
|
|
70
|
+
empty: readonly CellColumnId[],
|
|
71
|
+
): Array<{ id: CellColumnId; ids: CellId[] }> {
|
|
72
|
+
const groups = document === null ? [[]] : groupByColumn(document);
|
|
73
|
+
return [
|
|
74
|
+
...groups.map((cells, index) => ({
|
|
75
|
+
// Before the first document names them, columns go by position.
|
|
76
|
+
id: ids[index] ?? (`column-${index}` as CellColumnId),
|
|
77
|
+
ids: cells,
|
|
78
|
+
})),
|
|
79
|
+
...empty.map((id) => ({ id, ids: [] as CellId[] })),
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface LayoutColumn {
|
|
84
|
+
readonly id: CellColumnId;
|
|
85
|
+
/** Every cell of the column, in order. */
|
|
86
|
+
readonly ids: readonly CellId[];
|
|
87
|
+
/** The cells on the page: those no fold hides. */
|
|
88
|
+
readonly visible: readonly CellId[];
|
|
89
|
+
/**
|
|
90
|
+
* Each folded header and the cells it hides, nested sections included. A
|
|
91
|
+
* folded header with nothing under it yet has an empty fold.
|
|
92
|
+
*/
|
|
93
|
+
readonly folds: ReadonlyMap<CellId, readonly CellId[]>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface Layout {
|
|
97
|
+
readonly columns: readonly LayoutColumn[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The cells each folded header hides. A section runs from its header to the
|
|
102
|
+
* cell before the next header of the same or a higher level, so a folded
|
|
103
|
+
* header inside a folded section is hidden along with its own section.
|
|
104
|
+
*/
|
|
105
|
+
export function foldSections(
|
|
106
|
+
ids: readonly CellId[],
|
|
107
|
+
outlines: (Outline | null)[],
|
|
108
|
+
collapsed: ReadonlySet<CellId>,
|
|
109
|
+
): Map<CellId, readonly CellId[]> {
|
|
110
|
+
const folds = new Map<CellId, readonly CellId[]>();
|
|
111
|
+
ids.forEach((id, index) => {
|
|
112
|
+
const outline = outlines[index];
|
|
113
|
+
if (!collapsed.has(id) || !outline || outline.items.length === 0) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const range = findCollapseRange(index, outlines);
|
|
117
|
+
if (range === null) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
folds.set(id, ids.slice(index + 1, range[1] + 1));
|
|
121
|
+
});
|
|
122
|
+
return folds;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function deriveLayout(
|
|
126
|
+
columns: ReadonlyArray<{ id: CellColumnId; ids: readonly CellId[] }>,
|
|
127
|
+
outlineOf: (id: CellId) => Outline | null,
|
|
128
|
+
collapsed: ReadonlySet<CellId>,
|
|
129
|
+
): Layout {
|
|
130
|
+
return {
|
|
131
|
+
columns: columns.map(({ id, ids }) => {
|
|
132
|
+
const folds = foldSections(ids, ids.map(outlineOf), collapsed);
|
|
133
|
+
const hidden = new Set([...folds.values()].flat());
|
|
134
|
+
return { id, ids, visible: ids.filter((c) => !hidden.has(c)), folds };
|
|
135
|
+
}),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The layout of the notebook's cells: the document's order and columns,
|
|
141
|
+
* this browser's column ids and folds, and the kernel's outlines.
|
|
142
|
+
*
|
|
143
|
+
* TODO(MO-8028): Outlines come from executions later.
|
|
144
|
+
*/
|
|
145
|
+
export const layoutAtom = atom((get): Layout => {
|
|
146
|
+
const model = get(activeDocumentModelAtom);
|
|
147
|
+
const document = model === null ? null : get(model.documentAtom);
|
|
148
|
+
const outlines = get(cellOutlinesAtom);
|
|
149
|
+
return deriveLayout(
|
|
150
|
+
columnsOf(document, get(columnIdsAtom), get(emptyColumnIdsAtom)),
|
|
151
|
+
(id) => outlines[id] ?? null,
|
|
152
|
+
get(collapsedAtom),
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
export const useLayout = () => useAtomValue(layoutAtom);
|
|
157
|
+
|
|
158
|
+
export const numColumnsAtom = atom((get) => get(layoutAtom).columns.length);
|
|
159
|
+
|
|
160
|
+
export function findColumn(
|
|
161
|
+
layout: Layout,
|
|
162
|
+
columnId: CellColumnId,
|
|
163
|
+
): LayoutColumn | undefined {
|
|
164
|
+
return layout.columns.find((column) => column.id === columnId);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** The column holding `id`. Throws for a cell the layout does not have. */
|
|
168
|
+
export function columnOf(layout: Layout, id: CellId): LayoutColumn {
|
|
169
|
+
const column = layout.columns.find((column) => column.ids.includes(id));
|
|
170
|
+
if (column === undefined) {
|
|
171
|
+
throw new Error(`Cell ${id} is not in the layout`);
|
|
172
|
+
}
|
|
173
|
+
return column;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** The cells a folded header hides, or undefined when `id` is not a folded header. */
|
|
177
|
+
export function foldOf(
|
|
178
|
+
layout: Layout,
|
|
179
|
+
id: CellId,
|
|
180
|
+
): readonly CellId[] | undefined {
|
|
181
|
+
for (const column of layout.columns) {
|
|
182
|
+
const fold = column.folds.get(id);
|
|
183
|
+
if (fold !== undefined) {
|
|
184
|
+
return fold;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** The headers whose folds hide `id`. */
|
|
191
|
+
export function foldsHiding(layout: Layout, id: CellId): CellId[] {
|
|
192
|
+
const column = layout.columns.find((column) => column.ids.includes(id));
|
|
193
|
+
if (column === undefined) {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
return [...column.folds]
|
|
197
|
+
.filter(([, hidden]) => hidden.includes(id))
|
|
198
|
+
.map(([header]) => header);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* The folded headers whose sections a cell without a heading would fall
|
|
203
|
+
* into, placed right after `id`: those hiding `id`, and `id` itself when it
|
|
204
|
+
* is a folded header. A section runs until the next heading, so a cell
|
|
205
|
+
* placed after the last cell of a fold is still inside it.
|
|
206
|
+
*/
|
|
207
|
+
export function foldsAfter(layout: Layout, id: CellId): CellId[] {
|
|
208
|
+
const hiding = foldsHiding(layout, id);
|
|
209
|
+
return foldOf(layout, id) === undefined ? hiding : [...hiding, id];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** The visible cell `offset` places from `id` in its column, if there is one. */
|
|
213
|
+
export function visibleNeighbor(
|
|
214
|
+
layout: Layout,
|
|
215
|
+
id: CellId,
|
|
216
|
+
offset: -1 | 1,
|
|
217
|
+
): CellId | undefined {
|
|
218
|
+
const { visible } = columnOf(layout, id);
|
|
219
|
+
const index = visible.indexOf(id);
|
|
220
|
+
return index === -1 ? undefined : visible[index + offset];
|
|
221
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { useAtomValue } from "jotai";
|
|
4
|
-
import {
|
|
5
|
-
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
6
5
|
import { useEvent } from "@/hooks/useEvent";
|
|
7
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
useNotebookCellConfig,
|
|
8
|
+
useNotebookDocumentEdit,
|
|
9
|
+
} from "../notebook/document";
|
|
8
10
|
import type { OutputMessage } from "../kernel/messages";
|
|
9
11
|
import { viewStateAtom } from "../mode";
|
|
10
|
-
import {
|
|
11
|
-
import { cellDataAtom, useCellActions } from "./cells";
|
|
12
|
-
import type { CellId } from "./ids";
|
|
12
|
+
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
13
13
|
|
|
14
14
|
// This does not need to be overcomplicated. We can just store the expanded
|
|
15
15
|
// state in a global map instead of Jotai since state is not shared between cells.
|
|
@@ -27,20 +27,9 @@ const expandedConsoleOutputs: Record<CellId, boolean> = {};
|
|
|
27
27
|
*/
|
|
28
28
|
export function useExpandedOutput(cellId: CellId) {
|
|
29
29
|
const { mode } = useAtomValue(viewStateAtom);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const isConfigExpanded = useAtomValue(
|
|
34
|
-
useMemo(
|
|
35
|
-
() =>
|
|
36
|
-
selectAtom(
|
|
37
|
-
cellDataAtom(cellId),
|
|
38
|
-
(data) => data?.config.expand_output ?? false,
|
|
39
|
-
Object.is,
|
|
40
|
-
),
|
|
41
|
-
[cellId],
|
|
42
|
-
),
|
|
43
|
-
);
|
|
30
|
+
const edit = useNotebookDocumentEdit();
|
|
31
|
+
const isConfigExpanded =
|
|
32
|
+
useNotebookCellConfig(cellId)?.expand_output ?? false;
|
|
44
33
|
const [isSessionExpanded, setIsSessionExpanded] = useState(
|
|
45
34
|
() => expandedOutputs[cellId] ?? isConfigExpanded,
|
|
46
35
|
);
|
|
@@ -55,16 +44,11 @@ export function useExpandedOutput(cellId: CellId) {
|
|
|
55
44
|
|
|
56
45
|
const setIsExpanded = useEvent((expanded: boolean) => {
|
|
57
46
|
setIsSessionExpanded(expanded);
|
|
58
|
-
|
|
47
|
+
// The scratchpad is not in the document.
|
|
48
|
+
if (!isEditable || cellId === SCRATCH_CELL_ID) {
|
|
59
49
|
return;
|
|
60
50
|
}
|
|
61
|
-
|
|
62
|
-
updateCellConfig({ cellId, config });
|
|
63
|
-
getRequestClient()
|
|
64
|
-
.saveCellConfig({ configs: { [cellId]: config } })
|
|
65
|
-
.catch((error) => {
|
|
66
|
-
Logger.error("Failed to save expand_output config", error);
|
|
67
|
-
});
|
|
51
|
+
edit((tx) => tx.updateConfig(cellId, { expand_output: expanded }));
|
|
68
52
|
});
|
|
69
53
|
|
|
70
54
|
return [isExpanded, setIsExpanded] as const;
|
|
@@ -49,7 +49,7 @@ const { valueAtom: pendingDeleteStateAtom, useActions } = createReducerAndAtoms(
|
|
|
49
49
|
const variables = store.get(variablesAtom);
|
|
50
50
|
|
|
51
51
|
const emptyCells = new Set(
|
|
52
|
-
notebook.cellIds.
|
|
52
|
+
notebook.cellIds.filter(
|
|
53
53
|
(id) => notebook.cellData[id].code.trim() === "",
|
|
54
54
|
),
|
|
55
55
|
);
|
|
@@ -134,12 +134,8 @@ export function usePendingDeleteService() {
|
|
|
134
134
|
submit({ cellIds, deleteCell, deleteManyCells, store });
|
|
135
135
|
},
|
|
136
136
|
clear,
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
},
|
|
140
|
-
get shouldConfirmDelete() {
|
|
141
|
-
return entries.size > 1;
|
|
142
|
-
},
|
|
137
|
+
idle: entries.size === 0,
|
|
138
|
+
shouldConfirmDelete: entries.size > 1,
|
|
143
139
|
};
|
|
144
140
|
}
|
|
145
141
|
|