@marimo-team/islands 0.25.3-dev20 → 0.25.3-dev200
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-CNMliVzw.js → ConnectedDataExplorerComponent-BsWiIPFk.js} +22 -20
- package/dist/{ErrorBoundary-DAPIRYqd.js → ErrorBoundary-UWARECs-.js} +19 -19
- package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-I2x4Yu25.js} +2 -2
- package/dist/any-language-editor-BVFHDDQ3.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-1bSQMKzK.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
- package/dist/assets/__vite-browser-external-BCJsx8QS.js +1 -0
- package/dist/assets/worker-DodjWT_Z.js +113 -0
- package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-C2QUNRXi.js} +2 -2
- package/dist/{chat-ui-DaHynk8g.js → chat-ui-DXDoSuS4.js} +370 -369
- package/dist/{check-EDwSwP89.js → check-C9Mp9eCK.js} +1 -1
- package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-fsCGAJ9G.js} +1 -1
- package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-D2STW4hj.js} +1 -1
- package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-CiY7cQG-.js} +1 -1
- package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-C_t5RBp9.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-BXXV13Hq.js → classDiagram-ZZMXUADV-B2JvZAP4.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-L8VsZG5A.js} +2 -2
- package/dist/code-visibility-33fxfX1p.js +134 -0
- package/dist/{common-DsUPhkD6.js → common-D09oJJ8Z.js} +6040 -5865
- package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-De584pZ4.js} +3 -3
- package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-DdllC264.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-BaWHw4_f.js} +1 -1
- package/dist/{data-grid-overlay-editor-D7UuVsgB.js → data-grid-overlay-editor-lGsInXfR.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-BsSJJldB.js → diagram-S7CK7UJ4-pFt-tUDe.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-DqGJiBp4.js} +1 -1
- package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-Dr-yzMjf.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-8xzJzv-w.js} +1 -1
- package/dist/{dialog-CEBFZNyc.js → dialog-DVRfQuhD.js} +25 -25
- package/dist/{dist-F8Ep36rk.js → dist-B1M0bGO3.js} +1 -1
- package/dist/{dist-D6d86eNJ.js → dist-BA13RJj5.js} +1 -1
- package/dist/{dist-Bvs24R_E.js → dist-BJtmSgcE.js} +48 -48
- package/dist/{dist-CN_BeG2I.js → dist-Ba2VIn1K.js} +53 -53
- package/dist/{dist-PXYI_yuP.js → dist-Bj4bmwUm.js} +12 -12
- package/dist/{dist-DoE4XJBC.js → dist-BmS-ZGjl.js} +8626 -8626
- package/dist/{dist-BorMD-uX.js → dist-Bzogh7CW.js} +87 -87
- package/dist/{dist-CN8zI-XC.js → dist-CThPVKaP.js} +1385 -1382
- package/dist/{dist-DiDibOYr.js → dist-CTi5FTiV.js} +87 -87
- package/dist/{dist-diIx5qJW.js → dist-Ck_C32ye.js} +2 -2
- package/dist/{dist-BLfKmR-l.js → dist-D1fnFp1J.js} +1 -1
- package/dist/{dist-OR1OnN-y.js → dist-D3x9__Fu.js} +46 -46
- package/dist/{dist-BMQf5zIS.js → dist-D7mrh5sO.js} +36 -36
- package/dist/{dist-CSJ0MDRw.js → dist-D9Q3xjiP.js} +1 -1
- package/dist/{dist-BuaRHxOc.js → dist-DP60Ubh8.js} +2 -2
- package/dist/{dist-CSbh1PNP.js → dist-DTv9KkpW.js} +12 -12
- package/dist/{dist-D-wwqlzJ.js → dist-DVVwOfrD.js} +109 -109
- package/dist/{dist-C8fAKSH1.js → dist-DYXM73-k.js} +36 -36
- package/dist/{dist-DBtSl3sf.js → dist-DjeybPOb.js} +1 -1
- package/dist/{dist-CrSP_H1M.js → dist-DtGn9N4h.js} +197 -197
- package/dist/{dist-CLdpGQVr.js → dist-KN80qWCP.js} +2 -2
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dist-Cg7gzw-a.js → dist-O0qFpEJh.js} +56 -56
- package/dist/{dist-CkTTIdBe.js → dist-OUle2RT7.js} +207 -207
- package/dist/{dist-BK4Oj99o.js → dist-T5rh6JvL.js} +1 -1
- package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-NlnsmNA6.js} +1481 -1433
- package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-Br04Wy-E.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-D5-XVgvv.js} +1 -1
- package/dist/{error-banner-D-WCIiMt.js → error-banner-DxJ3s8YO.js} +86 -86
- package/dist/{error-entries-Bv6bZPF3.js → error-entries-C2Ux0Fjt.js} +8404 -9095
- package/dist/{esm-D2gTsXEV.js → esm-Bbw_Njjx.js} +575 -575
- package/dist/{esm-AMFssoNp.js → esm-mDQNEFe_.js} +354 -354
- package/dist/feedback-button-B0CMhVv7.js +374 -0
- package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-CVl2kREF.js} +2 -2
- package/dist/{formats-27CW_UP4.js → formats-BCYthwyc.js} +3 -3
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-KvS90MGh.js → glide-data-editor-CL535A5q.js} +370 -368
- package/dist/{glide-utils-DJyqh0EM.js → glide-utils-D98laidb.js} +16 -16
- package/dist/{globals-yruoELTW.js → globals-Bsr6T2yD.js} +3 -3
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{html-to-image-Bf8QMGi4.js → html-to-image-CkH7vdBZ.js} +477 -380
- package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-BJ4vNcZE.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-B_Jy1Dsm.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-C6MkS9vw.js} +1 -1
- package/dist/{label-BDKF3Afc.js → label-Qvw1E97W.js} +3 -3
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
- package/dist/main.js +9706 -7709
- package/dist/{mermaid-CHo49Yv-.js → mermaid-Bh918qrq.js} +52 -52
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-BP3ZTuir.js} +1 -1
- package/dist/{number-overlay-editor-R2i0FdxV.js → number-overlay-editor-CzbkG4E2.js} +3 -3
- 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-BqvywNJA.js → pegDiagram-XKGWAZYB-nNGOQtnt.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-CpRz5BZz.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-BZg56CCb.js → process-output-OujAtFW4.js} +5 -5
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-8vFLVTPu.js → railroadDiagram-O6MQD6OU-BqOEN4I0.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-a_MxGvxe.js → requirementDiagram-BXWQKSXE-CEfg6vu9.js} +1 -1
- package/dist/{reveal-component-C42-YBfQ.js → reveal-component-CbEK0sNX.js} +733 -710
- package/dist/{select-BButFi-d.js → select-2KOiReNY.js} +536 -457
- package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-IOmpQcOi.js} +1 -1
- package/dist/{spec-BwarBpUJ.js → spec-Dkp64vVQ.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-tgU-EY9_.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH-BofhG6q1.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-DW4vWDBd.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-BJcrqUJr.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-BVfnhbnt.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-D3c46WM5.js → timeline-definition-24CTP7MA-D_QU3NGs.js} +1 -1
- package/dist/{toDate-UtiwmnH2.js → toDate-BNDEXbfV.js} +44 -43
- package/dist/{toast-B9UMEi8u.js → toast-B5t9o6s_.js} +219 -201
- package/dist/{tooltip-BO1REbqs.js → tooltip-s4zZxwKe.js} +325 -301
- package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-BgDTd2tc.js} +1482 -1433
- package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-ASDni9vH.js} +15 -14
- package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-D3Tkfzej.js} +2 -2
- package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-B1Ogyf53.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-6a_yDNXp.js} +1 -1
- package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-Bfpa2m7k.js} +28 -25
- package/dist/{useTheme-CRnjkku0.js → useTheme-5TwyOh3B.js} +522 -314
- package/dist/{vega-component-BeF9dfyO.js → vega-component-BHS9UOtC.js} +158 -158
- 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-BSZD8JcZ.js → vennDiagram-4TSXK5OY-YFYsNIAh.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-i_n8mAWC.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-BYGN95wW.js} +2 -2
- package/package.json +16 -16
- 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 +0 -3
- 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 +7 -2
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/app-config/user-config-form.tsx +35 -0
- 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/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +20 -101
- 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-modal.test.tsx +34 -8
- package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +2 -6
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/pair-with-agent-commands.ts +2 -2
- package/src/components/editor/actions/pair-with-agent-modal.tsx +19 -16
- package/src/components/editor/actions/useCellActionButton.tsx +26 -31
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +19 -23
- 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 +3 -1
- 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 +36 -43
- 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 +9 -18
- 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 +61 -2
- 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 -0
- 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 +17 -29
- 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__/status.test.tsx +5 -3
- package/src/components/editor/header/app-header.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 -31
- 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/__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 +97 -0
- package/src/components/scratchpad/scratchpad.tsx +20 -11
- 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__/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/range-slider.tsx +22 -9
- package/src/core/MarimoApp.tsx +1 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +27 -26
- 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 +15 -18
- 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 +218 -2491
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/document.test.ts +341 -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 +120 -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/__tests__/with-document-save.test.ts +67 -0
- package/src/core/cells/actions.ts +636 -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 +120 -1337
- package/src/core/cells/columns.ts +38 -0
- package/src/core/cells/document.ts +289 -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__/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 +42 -1
- package/src/core/codemirror/cells/extensions.ts +27 -9
- package/src/core/codemirror/cells/state.ts +1 -1
- 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 -5
- 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/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/readonly/extension.ts +2 -2
- package/src/core/codemirror/rtc/extension.ts +24 -13
- package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
- package/src/core/codemirror/rtc/loro/sync.ts +1 -0
- 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 +13 -6
- package/src/core/config/config-schema.ts +13 -3
- package/src/core/config/config.ts +26 -12
- 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 -43
- package/src/core/islands/__tests__/bridge.test.ts +72 -25
- package/src/core/islands/bootstrap.ts +46 -54
- package/src/core/islands/bridge.ts +74 -23
- 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 +1 -4
- package/src/core/network/requests-network.ts +0 -25
- package/src/core/network/requests-static.ts +0 -3
- package/src/core/network/requests-toasting.tsx +0 -3
- package/src/core/network/types.ts +0 -12
- 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 +586 -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__/hold.test.ts +88 -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 +105 -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 +418 -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/notebook/replica/__tests__/attachments.test.ts +56 -0
- package/src/core/{host → notebook/replica}/__tests__/document.test.ts +18 -16
- package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
- package/src/core/notebook/replica/__tests__/replica.test.ts +550 -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 +13 -0
- package/src/core/notebook/replica/replica.ts +286 -0
- package/src/core/notebook/replica/resources/attachments.ts +22 -0
- package/src/core/{host → notebook/replica}/resources/document.ts +4 -4
- 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 -58
- package/src/core/runtime/adapter.ts +1 -1
- package/src/core/runtime/config.ts +2 -2
- package/src/core/runtime/runtime.ts +38 -42
- package/src/core/runtime/types.ts +0 -2
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
- package/src/core/saving/filename.ts +1 -1
- package/src/core/saving/save-component.tsx +28 -36
- 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/session/__tests__/useNotebookSession.hook.test.tsx +663 -0
- package/src/core/session/active-notebook.ts +22 -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 -72
- 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/wasm/__tests__/bridge.test.ts +214 -50
- package/src/core/wasm/__tests__/worker.test.ts +187 -0
- package/src/core/wasm/bridge.ts +75 -69
- 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 +88 -44
- 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 +43 -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/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/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 +2 -5
- 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__/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/maps.ts +0 -3
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +4 -9
- package/src/utils/once.ts +19 -19
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/any-language-editor-DZ_YTVus.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-DkCqn-PO.js +0 -138
- package/dist/feedback-button-wnAMXOGA.js +0 -379
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- 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 -21
- 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/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 -303
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/__tests__/stream.test.ts +0 -211
- package/src/core/host/connection.ts +0 -81
- package/src/core/host/events.ts +0 -60
- package/src/core/host/notebook-client.ts +0 -272
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/host/resources/resource.ts +0 -59
- package/src/core/host/stream.ts +0 -213
- 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 -140
- package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +0 -883
- 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 -80
- 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
package/src/core/cells/cells.ts
CHANGED
|
@@ -1,52 +1,39 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { dequal as isEqual } from "dequal";
|
|
3
|
+
import type * as Protocol from "@marimo-team/client/protocol";
|
|
5
4
|
import { type Atom, atom, useAtom, useAtomValue } from "jotai";
|
|
6
5
|
import { atomFamily, selectAtom, splitAtom } from "jotai/utils";
|
|
7
6
|
import { createRef, type ReducerWithoutAction } from "react";
|
|
8
7
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
11
|
-
type CellColumnId,
|
|
12
|
-
type CellIndex,
|
|
13
|
-
MultiColumn,
|
|
14
|
-
} from "@/utils/id-tree";
|
|
8
|
+
import type { EditableDocument, Placement } from "@/core/notebook/document";
|
|
9
|
+
import type { CellColumnId } from "./layout";
|
|
15
10
|
import { invariant } from "@/utils/invariant";
|
|
16
11
|
import { Logger } from "@/utils/Logger";
|
|
17
|
-
import { clamp } from "@/utils/math";
|
|
18
12
|
import { Objects } from "@/utils/objects";
|
|
19
13
|
import { extractAllTracebackInfo, type TracebackInfo } from "@/utils/traceback";
|
|
20
14
|
import { createReducerAndAtoms } from "../../utils/createReducer";
|
|
21
15
|
import { foldAllBulk, unfoldAllBulk } from "../codemirror/editing/commands";
|
|
22
16
|
import { editorMountScheduler } from "../codemirror/editor-mount-scheduler";
|
|
23
|
-
import {
|
|
24
|
-
splitEditor,
|
|
25
|
-
updateEditorCodeFromPython,
|
|
26
|
-
} from "../codemirror/language/utils";
|
|
27
17
|
import type { SerializedEditorState } from "../codemirror/types";
|
|
28
|
-
import {
|
|
18
|
+
import { mergeOutlines } from "../dom/outline";
|
|
29
19
|
import type { CellMessage } from "../kernel/messages";
|
|
30
20
|
import { isErrorMime } from "../mime";
|
|
31
21
|
import type { CellConfig } from "../network/types";
|
|
32
|
-
import { canUseRtc, isRtcEnabled } from "../rtc/state";
|
|
33
22
|
import { createDeepEqualAtom, store } from "../state/jotai";
|
|
34
23
|
import { isWasm } from "../wasm/utils";
|
|
35
24
|
import { prepareCellForExecution, transitionCell } from "./cell";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
25
|
+
import { applyDocument, documentEditMiddleware } from "./document";
|
|
26
|
+
import { isCodeHidden, shownHiddenCodeAtom } from "./editor";
|
|
27
|
+
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
38
28
|
import { type CellLog, getCellLogsForMessage } from "./logs";
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
scrollToBottom,
|
|
42
|
-
scrollToTop,
|
|
43
|
-
} from "./scrollCellIntoView";
|
|
29
|
+
import type { Outline } from "./outline";
|
|
30
|
+
import { focusAndScrollCellIntoView } from "./scrollCellIntoView";
|
|
44
31
|
import {
|
|
45
32
|
type CellData,
|
|
46
33
|
type CellRuntimeState,
|
|
47
34
|
createCell,
|
|
48
|
-
createCellConfig,
|
|
49
35
|
createCellRuntimeState,
|
|
36
|
+
isEdited,
|
|
50
37
|
} from "./types";
|
|
51
38
|
import {
|
|
52
39
|
canUndoDeletes,
|
|
@@ -58,17 +45,21 @@ import {
|
|
|
58
45
|
notebookQueueOrRunningCount,
|
|
59
46
|
} from "./utils";
|
|
60
47
|
|
|
48
|
+
/** A deleted cell as it was, with where it went in the document. */
|
|
49
|
+
export interface DeletedCell {
|
|
50
|
+
cell: Protocol.CellInput;
|
|
51
|
+
placement: Placement;
|
|
52
|
+
/** The editor's state at deletion, so undo brings its history back. */
|
|
53
|
+
serializedEditorState: SerializedEditorState | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
61
56
|
/**
|
|
62
|
-
* History entry for undoing
|
|
57
|
+
* History entry for undoing one deletion, of one or more cells.
|
|
63
58
|
*/
|
|
64
59
|
export interface UndoDeleteEntry {
|
|
65
60
|
type: "delete";
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
column: CellColumnId;
|
|
69
|
-
index: CellIndex;
|
|
70
|
-
isSetupCell: boolean;
|
|
71
|
-
config: CellConfig;
|
|
61
|
+
/** In document order. Each cell is placed after the one before it. */
|
|
62
|
+
cells: DeletedCell[];
|
|
72
63
|
}
|
|
73
64
|
|
|
74
65
|
/**
|
|
@@ -77,7 +68,7 @@ export interface UndoDeleteEntry {
|
|
|
77
68
|
export interface UndoMoveEntry {
|
|
78
69
|
type: "move";
|
|
79
70
|
cellIds: CellId[];
|
|
80
|
-
placements: Array<{ columnId: CellColumnId; index:
|
|
71
|
+
placements: Array<{ columnId: CellColumnId; index: number }>;
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
export type HistoryEntry = UndoDeleteEntry | UndoMoveEntry;
|
|
@@ -89,7 +80,8 @@ export interface NotebookState {
|
|
|
89
80
|
/**
|
|
90
81
|
* Order of cells on the page.
|
|
91
82
|
*/
|
|
92
|
-
|
|
83
|
+
/** The cells in document order. */
|
|
84
|
+
cellIds: CellId[];
|
|
93
85
|
/**
|
|
94
86
|
* Map of cells to their view state
|
|
95
87
|
*/
|
|
@@ -116,12 +108,6 @@ export interface NotebookState {
|
|
|
116
108
|
* Logs of all cell messages
|
|
117
109
|
*/
|
|
118
110
|
cellLogs: CellLog[];
|
|
119
|
-
/**
|
|
120
|
-
* Set of cells that have been created that are initialized with `hide_code`.
|
|
121
|
-
*
|
|
122
|
-
* These start temporarily open until their first blur event.
|
|
123
|
-
*/
|
|
124
|
-
untouchedNewCells: Set<CellId>;
|
|
125
111
|
}
|
|
126
112
|
|
|
127
113
|
function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
@@ -153,51 +139,16 @@ function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
|
153
139
|
*/
|
|
154
140
|
export function initialNotebookState(): NotebookState {
|
|
155
141
|
return withScratchCell({
|
|
156
|
-
cellIds:
|
|
142
|
+
cellIds: [],
|
|
157
143
|
cellData: {},
|
|
158
144
|
cellRuntime: {},
|
|
159
145
|
cellHandles: {},
|
|
160
146
|
history: [],
|
|
161
147
|
scrollKey: null,
|
|
162
148
|
cellLogs: [],
|
|
163
|
-
untouchedNewCells: new Set<CellId>(),
|
|
164
149
|
});
|
|
165
150
|
}
|
|
166
151
|
|
|
167
|
-
/** The target cell ID to create a new cell relative to. Can be:
|
|
168
|
-
* - A CellId string for an existing cell
|
|
169
|
-
* - "__end__" to append at the end of the first column
|
|
170
|
-
* - {type: "__end__", columnId} to append at the end of a specific column
|
|
171
|
-
*/
|
|
172
|
-
export type CellPosition =
|
|
173
|
-
| CellId
|
|
174
|
-
| "__end__"
|
|
175
|
-
| { type: "__end__"; columnId: CellColumnId };
|
|
176
|
-
|
|
177
|
-
export interface CreateNewCellAction {
|
|
178
|
-
cellId: CellPosition;
|
|
179
|
-
/** Whether to insert before (true) or after (false) the target cell */
|
|
180
|
-
before: boolean;
|
|
181
|
-
/** Initial code content for the new cell */
|
|
182
|
-
code?: string;
|
|
183
|
-
/** Optional name for the new cell */
|
|
184
|
-
name?: string;
|
|
185
|
-
/** Optional cell configuration */
|
|
186
|
-
config?: CellConfig;
|
|
187
|
-
/** The last executed code for the new cell */
|
|
188
|
-
lastCodeRun?: string;
|
|
189
|
-
/** Timestamp of the last execution */
|
|
190
|
-
lastExecutionTime?: number;
|
|
191
|
-
/** Optional custom ID for the new cell. Auto-generated if not provided */
|
|
192
|
-
newCellId?: CellId;
|
|
193
|
-
/** Whether to focus the new cell after creation */
|
|
194
|
-
autoFocus?: boolean;
|
|
195
|
-
/** If true, skip creation if code already exists */
|
|
196
|
-
skipIfCodeExists?: boolean;
|
|
197
|
-
/** Hide the code in the new cell. This will be initially shown until the cell is blurred for the first time. */
|
|
198
|
-
hideCode?: boolean;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
152
|
/**
|
|
202
153
|
* Actions and reducer for the notebook state.
|
|
203
154
|
*/
|
|
@@ -208,616 +159,11 @@ const {
|
|
|
208
159
|
useActions,
|
|
209
160
|
valueAtom: notebookAtom,
|
|
210
161
|
} = createReducerAndAtoms(initialNotebookState, {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
name,
|
|
217
|
-
config,
|
|
218
|
-
lastCodeRun = null,
|
|
219
|
-
lastExecutionTime = null,
|
|
220
|
-
autoFocus = true,
|
|
221
|
-
skipIfCodeExists = false,
|
|
222
|
-
hideCode = undefined,
|
|
223
|
-
} = action;
|
|
224
|
-
|
|
225
|
-
let columnId: CellColumnId;
|
|
226
|
-
let cellIndex: number;
|
|
227
|
-
|
|
228
|
-
// If skipIfCodeExists is true, check if the code already exists in the notebook
|
|
229
|
-
if (skipIfCodeExists) {
|
|
230
|
-
for (const cellId of state.cellIds.inOrderIds) {
|
|
231
|
-
if (state.cellData[cellId]?.code === code) {
|
|
232
|
-
return state;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (cellId === "__end__") {
|
|
238
|
-
const column = state.cellIds.atOrThrow(0);
|
|
239
|
-
columnId = column.id;
|
|
240
|
-
cellIndex = column.length;
|
|
241
|
-
} else if (typeof cellId === "string") {
|
|
242
|
-
const column = state.cellIds.findWithId(cellId);
|
|
243
|
-
columnId = column.id;
|
|
244
|
-
cellIndex = column.topLevelIds.indexOf(cellId);
|
|
245
|
-
} else if (cellId.type === "__end__") {
|
|
246
|
-
const column =
|
|
247
|
-
state.cellIds.get(cellId.columnId) || state.cellIds.atOrThrow(0);
|
|
248
|
-
columnId = column.id;
|
|
249
|
-
cellIndex = column.length;
|
|
250
|
-
} else {
|
|
251
|
-
throw new Error("Invalid cellId");
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const newCellId = action.newCellId || CellId.create();
|
|
255
|
-
const insertionIndex = before ? cellIndex : cellIndex + 1;
|
|
256
|
-
|
|
257
|
-
return {
|
|
258
|
-
...state,
|
|
259
|
-
cellIds: state.cellIds.insertId(newCellId, columnId, insertionIndex),
|
|
260
|
-
cellData: {
|
|
261
|
-
...state.cellData,
|
|
262
|
-
[newCellId]: createCell({
|
|
263
|
-
id: newCellId,
|
|
264
|
-
code,
|
|
265
|
-
name,
|
|
266
|
-
lastCodeRun,
|
|
267
|
-
config: createCellConfig({
|
|
268
|
-
...config,
|
|
269
|
-
...(hideCode != null && { hide_code: hideCode }),
|
|
270
|
-
}),
|
|
271
|
-
lastExecutionTime,
|
|
272
|
-
edited: Boolean(code) && code !== lastCodeRun,
|
|
273
|
-
}),
|
|
274
|
-
},
|
|
275
|
-
cellRuntime: {
|
|
276
|
-
...state.cellRuntime,
|
|
277
|
-
[newCellId]: createCellRuntimeState(),
|
|
278
|
-
},
|
|
279
|
-
cellHandles: {
|
|
280
|
-
...state.cellHandles,
|
|
281
|
-
[newCellId]: createRef(),
|
|
282
|
-
},
|
|
283
|
-
scrollKey: autoFocus ? newCellId : null,
|
|
284
|
-
untouchedNewCells:
|
|
285
|
-
hideCode && autoFocus
|
|
286
|
-
? new Set([...state.untouchedNewCells, newCellId])
|
|
287
|
-
: state.untouchedNewCells,
|
|
288
|
-
};
|
|
289
|
-
},
|
|
290
|
-
moveCell: (
|
|
291
|
-
state,
|
|
292
|
-
action: {
|
|
293
|
-
cellId: CellId;
|
|
294
|
-
before?: boolean;
|
|
295
|
-
direction?: "left" | "right";
|
|
296
|
-
},
|
|
297
|
-
) => {
|
|
298
|
-
const { cellId, before, direction } = action;
|
|
299
|
-
|
|
300
|
-
if (before !== undefined && direction !== undefined) {
|
|
301
|
-
Logger.warn(
|
|
302
|
-
"Both before and direction specified for moveCell. Ignoring one.",
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Handle left/right movement
|
|
307
|
-
if (direction) {
|
|
308
|
-
const fromColumn = state.cellIds.findWithId(cellId);
|
|
309
|
-
const fromColumnIndex = state.cellIds.indexOf(fromColumn);
|
|
310
|
-
const toColumnIndex =
|
|
311
|
-
direction === "left" ? fromColumnIndex - 1 : fromColumnIndex + 1;
|
|
312
|
-
const toColumn = state.cellIds.at(toColumnIndex);
|
|
313
|
-
|
|
314
|
-
// If no column to move to, return unchanged state
|
|
315
|
-
if (!toColumn) {
|
|
316
|
-
return state;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return {
|
|
320
|
-
...state,
|
|
321
|
-
cellIds: state.cellIds.moveAcrossColumns(
|
|
322
|
-
fromColumn.id,
|
|
323
|
-
cellId,
|
|
324
|
-
toColumn.id,
|
|
325
|
-
undefined,
|
|
326
|
-
),
|
|
327
|
-
scrollKey: cellId,
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Handle up/down movement
|
|
332
|
-
const column = state.cellIds.findWithId(cellId);
|
|
333
|
-
const cellIndex = column.indexOfOrThrow(cellId);
|
|
334
|
-
|
|
335
|
-
if (before && cellIndex === 0) {
|
|
336
|
-
return {
|
|
337
|
-
...state,
|
|
338
|
-
cellIds: state.cellIds.moveWithinColumn(column.id, cellIndex, 0),
|
|
339
|
-
scrollKey: cellId,
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
if (!before && cellIndex === column.length - 1) {
|
|
343
|
-
return {
|
|
344
|
-
...state,
|
|
345
|
-
cellIds: state.cellIds.moveWithinColumn(
|
|
346
|
-
column.id,
|
|
347
|
-
cellIndex,
|
|
348
|
-
column.length - 1,
|
|
349
|
-
),
|
|
350
|
-
scrollKey: cellId,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return before
|
|
355
|
-
? {
|
|
356
|
-
...state,
|
|
357
|
-
cellIds: state.cellIds.moveWithinColumn(
|
|
358
|
-
column.id,
|
|
359
|
-
cellIndex,
|
|
360
|
-
cellIndex - 1,
|
|
361
|
-
),
|
|
362
|
-
scrollKey: cellId,
|
|
363
|
-
}
|
|
364
|
-
: {
|
|
365
|
-
...state,
|
|
366
|
-
cellIds: state.cellIds.moveWithinColumn(
|
|
367
|
-
column.id,
|
|
368
|
-
cellIndex,
|
|
369
|
-
cellIndex + 1,
|
|
370
|
-
),
|
|
371
|
-
scrollKey: cellId,
|
|
372
|
-
};
|
|
373
|
-
},
|
|
374
|
-
moveCellToIndex: (
|
|
375
|
-
state,
|
|
376
|
-
action: {
|
|
377
|
-
cellId: CellId;
|
|
378
|
-
columnId: CellColumnId;
|
|
379
|
-
index: number;
|
|
380
|
-
},
|
|
381
|
-
) => {
|
|
382
|
-
const { cellId, columnId, index } = action;
|
|
383
|
-
const fromColumn = state.cellIds.findWithId(cellId);
|
|
384
|
-
const fromIndex = fromColumn.indexOfOrThrow(cellId);
|
|
385
|
-
|
|
386
|
-
const destinationColumn = state.cellIds.get(columnId);
|
|
387
|
-
if (!destinationColumn) {
|
|
388
|
-
return state;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
const clampedIndex = Math.max(0, Math.min(index, destinationColumn.length));
|
|
392
|
-
const adjustedIndex =
|
|
393
|
-
fromColumn.id === columnId && fromIndex < clampedIndex
|
|
394
|
-
? clampedIndex - 1
|
|
395
|
-
: clampedIndex;
|
|
396
|
-
|
|
397
|
-
if (fromColumn.id === columnId && fromIndex === adjustedIndex) {
|
|
398
|
-
return state;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
const withoutCell = state.cellIds.deleteById(cellId);
|
|
402
|
-
const updatedColumn = withoutCell.get(columnId);
|
|
403
|
-
if (!updatedColumn) {
|
|
404
|
-
return state;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return {
|
|
408
|
-
...state,
|
|
409
|
-
cellIds: withoutCell.insertId(
|
|
410
|
-
cellId,
|
|
411
|
-
columnId,
|
|
412
|
-
Math.max(0, Math.min(adjustedIndex, updatedColumn.length)),
|
|
413
|
-
),
|
|
414
|
-
scrollKey: null,
|
|
415
|
-
};
|
|
416
|
-
},
|
|
417
|
-
dropCellOverCell: (state, action: { cellId: CellId; overCellId: CellId }) => {
|
|
418
|
-
const { cellId, overCellId } = action;
|
|
419
|
-
|
|
420
|
-
const fromColumn = state.cellIds.findWithId(cellId);
|
|
421
|
-
const toColumn = state.cellIds.findWithId(overCellId);
|
|
422
|
-
|
|
423
|
-
const fromIndex = fromColumn.indexOfOrThrow(cellId);
|
|
424
|
-
const toIndex = toColumn.indexOfOrThrow(overCellId);
|
|
425
|
-
|
|
426
|
-
if (fromColumn.id === toColumn.id) {
|
|
427
|
-
if (fromIndex === toIndex) {
|
|
428
|
-
return state;
|
|
429
|
-
}
|
|
430
|
-
return {
|
|
431
|
-
...state,
|
|
432
|
-
cellIds: state.cellIds.moveWithinColumn(
|
|
433
|
-
fromColumn.id,
|
|
434
|
-
fromIndex,
|
|
435
|
-
toIndex,
|
|
436
|
-
),
|
|
437
|
-
scrollKey: null,
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return {
|
|
442
|
-
...state,
|
|
443
|
-
cellIds: state.cellIds.moveAcrossColumns(
|
|
444
|
-
fromColumn.id,
|
|
445
|
-
cellId,
|
|
446
|
-
toColumn.id,
|
|
447
|
-
overCellId,
|
|
448
|
-
),
|
|
449
|
-
scrollKey: null,
|
|
450
|
-
};
|
|
451
|
-
},
|
|
452
|
-
moveCellsRelativeTo: (
|
|
453
|
-
state,
|
|
454
|
-
action: {
|
|
455
|
-
cellIds: CellId[];
|
|
456
|
-
targetCellId: CellId;
|
|
457
|
-
position: "before" | "after";
|
|
458
|
-
previousPlacements?: Array<{ columnId: CellColumnId; index: CellIndex }>;
|
|
459
|
-
},
|
|
460
|
-
) => {
|
|
461
|
-
const { cellIds, targetCellId, position, previousPlacements } = action;
|
|
462
|
-
if (cellIds.length === 0) {
|
|
463
|
-
return state;
|
|
464
|
-
}
|
|
465
|
-
const newCellIds = state.cellIds.moveCellsRelativeTo(
|
|
466
|
-
cellIds,
|
|
467
|
-
targetCellId,
|
|
468
|
-
position,
|
|
469
|
-
);
|
|
470
|
-
// Only record undo when caller provided full before-state
|
|
471
|
-
const canUndoMove =
|
|
472
|
-
previousPlacements && previousPlacements.length === cellIds.length;
|
|
473
|
-
const history = canUndoMove
|
|
474
|
-
? [
|
|
475
|
-
...state.history,
|
|
476
|
-
{ type: "move" as const, cellIds, placements: previousPlacements },
|
|
477
|
-
]
|
|
478
|
-
: state.history;
|
|
479
|
-
return {
|
|
480
|
-
...state,
|
|
481
|
-
cellIds: newCellIds,
|
|
482
|
-
history,
|
|
483
|
-
scrollKey: null,
|
|
484
|
-
};
|
|
485
|
-
},
|
|
486
|
-
dropCellOverColumn: (
|
|
487
|
-
state,
|
|
488
|
-
action: { cellId: CellId; columnId: CellColumnId },
|
|
489
|
-
) => {
|
|
490
|
-
const { cellId, columnId } = action;
|
|
491
|
-
const fromColumn = state.cellIds.findWithId(cellId);
|
|
492
|
-
|
|
493
|
-
return {
|
|
494
|
-
...state,
|
|
495
|
-
cellIds: state.cellIds.moveAcrossColumns(
|
|
496
|
-
fromColumn.id,
|
|
497
|
-
cellId,
|
|
498
|
-
columnId,
|
|
499
|
-
undefined,
|
|
500
|
-
),
|
|
501
|
-
};
|
|
502
|
-
},
|
|
503
|
-
dropOverNewColumn: (state, action: { cellId: CellId }) => {
|
|
504
|
-
const { cellId } = action;
|
|
505
|
-
return {
|
|
506
|
-
...state,
|
|
507
|
-
cellIds: state.cellIds.moveToNewColumn(cellId),
|
|
508
|
-
};
|
|
509
|
-
},
|
|
510
|
-
moveColumn: (
|
|
511
|
-
state,
|
|
512
|
-
action: {
|
|
513
|
-
column: CellColumnId;
|
|
514
|
-
overColumn: CellColumnId | "_left_" | "_right_";
|
|
515
|
-
},
|
|
516
|
-
) => {
|
|
517
|
-
if (action.column === action.overColumn) {
|
|
518
|
-
return state;
|
|
519
|
-
}
|
|
520
|
-
return {
|
|
521
|
-
...state,
|
|
522
|
-
cellIds: state.cellIds.moveColumn(action.column, action.overColumn),
|
|
523
|
-
};
|
|
524
|
-
},
|
|
525
|
-
focusCell: (
|
|
526
|
-
state,
|
|
527
|
-
action: { cellId: CellId; where: "before" | "after" | "exact" },
|
|
528
|
-
) => {
|
|
529
|
-
const column = state.cellIds.findWithId(action.cellId);
|
|
530
|
-
if (column.length === 0) {
|
|
531
|
-
return state;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
const { cellId, where } = action;
|
|
535
|
-
const index = column.indexOfOrThrow(cellId);
|
|
536
|
-
|
|
537
|
-
let focusIndex: number;
|
|
538
|
-
if (where === "before") {
|
|
539
|
-
focusIndex = clamp(index - 1, 0, column.length - 1);
|
|
540
|
-
} else if (where === "after") {
|
|
541
|
-
focusIndex = clamp(index + 1, 0, column.length - 1);
|
|
542
|
-
} else {
|
|
543
|
-
focusIndex = index;
|
|
544
|
-
}
|
|
545
|
-
const focusCellId = column.atOrThrow(focusIndex);
|
|
546
|
-
// can scroll immediately, without setting scrollKey in state, because
|
|
547
|
-
// CellArray won't need to re-render
|
|
548
|
-
focusAndScrollCellIntoView({
|
|
549
|
-
cellId: focusCellId,
|
|
550
|
-
cell: state.cellHandles[focusCellId],
|
|
551
|
-
isCodeHidden: isCellCodeHidden(state, focusCellId),
|
|
552
|
-
codeFocus: where === "after" ? "top" : "bottom",
|
|
553
|
-
variableName: undefined,
|
|
554
|
-
});
|
|
555
|
-
return state;
|
|
556
|
-
},
|
|
557
|
-
focusTopCell: (state) => {
|
|
558
|
-
// TODO: focus the existing column, not the first column
|
|
559
|
-
const column = state.cellIds.getColumns().at(0);
|
|
560
|
-
if (column === undefined || column.length === 0) {
|
|
561
|
-
return state;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
const cellId = column.first();
|
|
565
|
-
focusAndScrollCellIntoView({
|
|
566
|
-
cellId: cellId,
|
|
567
|
-
cell: state.cellHandles[cellId],
|
|
568
|
-
isCodeHidden: isCellCodeHidden(state, cellId),
|
|
569
|
-
codeFocus: undefined,
|
|
570
|
-
variableName: undefined,
|
|
571
|
-
});
|
|
572
|
-
scrollToTop();
|
|
573
|
-
return state;
|
|
574
|
-
},
|
|
575
|
-
focusBottomCell: (state) => {
|
|
576
|
-
// TODO: focus the existing column, not the last column
|
|
577
|
-
const column = state.cellIds.getColumns().at(-1);
|
|
578
|
-
if (column === undefined || column.length === 0) {
|
|
579
|
-
return state;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const cellId = column.last();
|
|
583
|
-
focusAndScrollCellIntoView({
|
|
584
|
-
cellId: cellId,
|
|
585
|
-
cell: state.cellHandles[cellId],
|
|
586
|
-
isCodeHidden: isCellCodeHidden(state, cellId),
|
|
587
|
-
codeFocus: undefined,
|
|
588
|
-
variableName: undefined,
|
|
589
|
-
});
|
|
590
|
-
scrollToBottom();
|
|
591
|
-
return state;
|
|
592
|
-
},
|
|
593
|
-
sendToTop: (state, action: { cellId: CellId; scroll?: boolean }) => {
|
|
594
|
-
const column = state.cellIds.findWithId(action.cellId);
|
|
595
|
-
if (column.length === 0) {
|
|
596
|
-
return state;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
const { cellId, scroll = true } = action;
|
|
600
|
-
const cellIndex = column.indexOfOrThrow(cellId);
|
|
601
|
-
if (cellIndex === 0) {
|
|
602
|
-
return state;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
return {
|
|
606
|
-
...state,
|
|
607
|
-
cellIds: state.cellIds.moveWithinColumn(column.id, cellIndex, 0),
|
|
608
|
-
scrollKey: scroll ? cellId : null,
|
|
609
|
-
};
|
|
610
|
-
},
|
|
611
|
-
sendToBottom: (state, action: { cellId: CellId; scroll?: boolean }) => {
|
|
612
|
-
const column = state.cellIds.findWithId(action.cellId);
|
|
613
|
-
if (column.length === 0) {
|
|
614
|
-
return state;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
const { cellId, scroll = true } = action;
|
|
618
|
-
const cellIndex = column.indexOfOrThrow(cellId);
|
|
619
|
-
const newIndex = column.length - 1;
|
|
620
|
-
|
|
621
|
-
if (cellIndex === newIndex) {
|
|
622
|
-
return state;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
return {
|
|
626
|
-
...state,
|
|
627
|
-
cellIds: state.cellIds.moveWithinColumn(column.id, cellIndex, newIndex),
|
|
628
|
-
scrollKey: scroll ? cellId : null,
|
|
629
|
-
};
|
|
630
|
-
},
|
|
631
|
-
addColumn: (state, action: { columnId: CellColumnId }) => {
|
|
632
|
-
// Add column and new cell
|
|
633
|
-
const newCellId = CellId.create();
|
|
634
|
-
return {
|
|
635
|
-
...state,
|
|
636
|
-
cellIds: state.cellIds.addColumn(action.columnId, [newCellId]),
|
|
637
|
-
cellData: {
|
|
638
|
-
...state.cellData,
|
|
639
|
-
[newCellId]: createCell({
|
|
640
|
-
id: newCellId,
|
|
641
|
-
}),
|
|
642
|
-
},
|
|
643
|
-
cellRuntime: {
|
|
644
|
-
...state.cellRuntime,
|
|
645
|
-
[newCellId]: createCellRuntimeState(),
|
|
646
|
-
},
|
|
647
|
-
cellHandles: {
|
|
648
|
-
...state.cellHandles,
|
|
649
|
-
[newCellId]: createRef(),
|
|
650
|
-
},
|
|
651
|
-
scrollKey: newCellId,
|
|
652
|
-
};
|
|
653
|
-
},
|
|
654
|
-
addColumnBreakpoint: (state, action: { cellId: CellId }) => {
|
|
655
|
-
const { cellId } = action;
|
|
656
|
-
if (state.cellIds.getColumns()[0].inOrderIds[0] === cellId) {
|
|
657
|
-
return state;
|
|
658
|
-
}
|
|
659
|
-
return {
|
|
660
|
-
...state,
|
|
661
|
-
cellIds: state.cellIds.insertBreakpoint(cellId),
|
|
662
|
-
};
|
|
663
|
-
},
|
|
664
|
-
deleteColumn: (state, action: { columnId: CellColumnId }) => {
|
|
665
|
-
// Move all cells in the column to the previous column
|
|
666
|
-
const { columnId } = action;
|
|
667
|
-
return {
|
|
668
|
-
...state,
|
|
669
|
-
cellIds: state.cellIds.delete(columnId),
|
|
670
|
-
};
|
|
671
|
-
},
|
|
672
|
-
mergeAllColumns: (state) => {
|
|
673
|
-
return {
|
|
674
|
-
...state,
|
|
675
|
-
cellIds: state.cellIds.mergeAllColumns(),
|
|
676
|
-
};
|
|
677
|
-
},
|
|
678
|
-
compactColumns: (state) => {
|
|
679
|
-
return {
|
|
680
|
-
...state,
|
|
681
|
-
cellIds: state.cellIds.compact(),
|
|
682
|
-
};
|
|
683
|
-
},
|
|
684
|
-
deleteCell: (state, action: { cellId: CellId }) => {
|
|
685
|
-
const cellId = action.cellId;
|
|
686
|
-
|
|
687
|
-
// Can't delete the last cell, across all columns
|
|
688
|
-
if (state.cellIds.hasOnlyOneId()) {
|
|
689
|
-
return state;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
let column: CollapsibleTree<CellId>;
|
|
693
|
-
try {
|
|
694
|
-
column = state.cellIds.findWithId(cellId);
|
|
695
|
-
} catch (error) {
|
|
696
|
-
// Expected for kernel-only cells or out-of-order transactions.
|
|
697
|
-
Logger.warn("Skipping delete for missing cellId", {
|
|
698
|
-
cellId,
|
|
699
|
-
error,
|
|
700
|
-
});
|
|
701
|
-
return state;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
const cellIndex = column.indexOfOrThrow(cellId);
|
|
705
|
-
const focusIndex = cellIndex === 0 ? 1 : cellIndex - 1;
|
|
706
|
-
let scrollKey: CellId | null = null;
|
|
707
|
-
if (column.length > 1) {
|
|
708
|
-
scrollKey = column.atOrThrow(focusIndex);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
const editorView = state.cellHandles[cellId].current?.editorView;
|
|
712
|
-
const serializedEditorState = editorView?.state.toJSON({
|
|
713
|
-
history: historyField,
|
|
714
|
-
});
|
|
715
|
-
if (serializedEditorState) {
|
|
716
|
-
serializedEditorState.doc = state.cellData[cellId].code;
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
// release the granular atom(s) created for this cell
|
|
720
|
-
releaseCellAtoms(cellId);
|
|
721
|
-
const prevData = state.cellData[cellId];
|
|
722
|
-
return {
|
|
723
|
-
...state,
|
|
724
|
-
cellIds: state.cellIds.deleteById(cellId),
|
|
725
|
-
history: [
|
|
726
|
-
...state.history,
|
|
727
|
-
{
|
|
728
|
-
type: "delete",
|
|
729
|
-
name: prevData.name,
|
|
730
|
-
serializedEditorState: serializedEditorState,
|
|
731
|
-
column: column.id,
|
|
732
|
-
index: cellIndex,
|
|
733
|
-
isSetupCell: cellId === SETUP_CELL_ID,
|
|
734
|
-
config: prevData.config,
|
|
735
|
-
},
|
|
736
|
-
],
|
|
737
|
-
scrollKey: scrollKey,
|
|
738
|
-
};
|
|
739
|
-
},
|
|
740
|
-
undoDeleteCell: (state) => {
|
|
741
|
-
if (state.history.length === 0) {
|
|
742
|
-
return state;
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
const last = state.history[state.history.length - 1];
|
|
746
|
-
|
|
747
|
-
if (last.type === "move") {
|
|
748
|
-
const { cellIds, placements } = last;
|
|
749
|
-
if (
|
|
750
|
-
cellIds.length === 0 ||
|
|
751
|
-
placements.length !== cellIds.length ||
|
|
752
|
-
cellIds.some((id) => !state.cellData[id])
|
|
753
|
-
) {
|
|
754
|
-
return { ...state, history: state.history.slice(0, -1) };
|
|
755
|
-
}
|
|
756
|
-
const toRestore = cellIds.map((id, i) => ({
|
|
757
|
-
id,
|
|
758
|
-
columnId: placements[i].columnId,
|
|
759
|
-
index: placements[i].index,
|
|
760
|
-
}));
|
|
761
|
-
return {
|
|
762
|
-
...state,
|
|
763
|
-
cellIds: state.cellIds.placeCells(toRestore),
|
|
764
|
-
history: state.history.slice(0, -1),
|
|
765
|
-
scrollKey: cellIds[0] ?? null,
|
|
766
|
-
};
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
const {
|
|
770
|
-
name,
|
|
771
|
-
serializedEditorState = { doc: "" },
|
|
772
|
-
column,
|
|
773
|
-
index,
|
|
774
|
-
isSetupCell,
|
|
775
|
-
config,
|
|
776
|
-
} = last;
|
|
777
|
-
|
|
778
|
-
const cellId = isSetupCell ? SETUP_CELL_ID : CellId.create();
|
|
779
|
-
const undoCell = createCell({
|
|
780
|
-
id: cellId,
|
|
781
|
-
name,
|
|
782
|
-
code: serializedEditorState.doc,
|
|
783
|
-
edited: serializedEditorState.doc.trim().length > 0,
|
|
784
|
-
serializedEditorState,
|
|
785
|
-
config,
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
return {
|
|
789
|
-
...state,
|
|
790
|
-
cellIds: state.cellIds.insertId(cellId, column, index),
|
|
791
|
-
cellData: {
|
|
792
|
-
...state.cellData,
|
|
793
|
-
[cellId]: undoCell,
|
|
794
|
-
},
|
|
795
|
-
cellRuntime: {
|
|
796
|
-
...state.cellRuntime,
|
|
797
|
-
[cellId]: createCellRuntimeState(),
|
|
798
|
-
},
|
|
799
|
-
cellHandles: {
|
|
800
|
-
...state.cellHandles,
|
|
801
|
-
[cellId]: createRef(),
|
|
802
|
-
},
|
|
803
|
-
history: state.history.slice(0, -1),
|
|
804
|
-
// Scroll to the newly created cell
|
|
805
|
-
scrollKey: cellId,
|
|
806
|
-
};
|
|
807
|
-
},
|
|
808
|
-
clearSerializedEditorState: (state, action: { cellId: CellId }) => {
|
|
809
|
-
const { cellId } = action;
|
|
810
|
-
return updateCellData({
|
|
811
|
-
state,
|
|
812
|
-
cellId,
|
|
813
|
-
cellReducer: (cell) => {
|
|
814
|
-
return {
|
|
815
|
-
...cell,
|
|
816
|
-
serializedEditorState: null,
|
|
817
|
-
};
|
|
818
|
-
},
|
|
819
|
-
});
|
|
820
|
-
},
|
|
162
|
+
/**
|
|
163
|
+
* Put moved cells back where they were.
|
|
164
|
+
*
|
|
165
|
+
* TODO(MO-8028): Move to `undoDeleteCellAtom` with the order family.
|
|
166
|
+
*/
|
|
821
167
|
updateCellCode: (
|
|
822
168
|
state,
|
|
823
169
|
action: {
|
|
@@ -855,35 +201,6 @@ const {
|
|
|
855
201
|
},
|
|
856
202
|
});
|
|
857
203
|
},
|
|
858
|
-
updateCellName: (state, action: { cellId: CellId; name: string }) => {
|
|
859
|
-
const { cellId, name } = action;
|
|
860
|
-
return updateCellData({
|
|
861
|
-
state,
|
|
862
|
-
cellId,
|
|
863
|
-
cellReducer: (cell) => {
|
|
864
|
-
return {
|
|
865
|
-
...cell,
|
|
866
|
-
name: name,
|
|
867
|
-
};
|
|
868
|
-
},
|
|
869
|
-
});
|
|
870
|
-
},
|
|
871
|
-
updateCellConfig: (
|
|
872
|
-
state,
|
|
873
|
-
action: { cellId: CellId; config: Partial<CellConfig> },
|
|
874
|
-
) => {
|
|
875
|
-
const { cellId, config } = action;
|
|
876
|
-
return updateCellData({
|
|
877
|
-
state,
|
|
878
|
-
cellId,
|
|
879
|
-
cellReducer: (cell) => {
|
|
880
|
-
return {
|
|
881
|
-
...cell,
|
|
882
|
-
config: createCellConfig({ ...cell.config, ...config }),
|
|
883
|
-
};
|
|
884
|
-
},
|
|
885
|
-
});
|
|
886
|
-
},
|
|
887
204
|
prepareForRun: (state, action: { cellId: CellId }) => {
|
|
888
205
|
const newState = updateCellRuntimeState({
|
|
889
206
|
state,
|
|
@@ -939,158 +256,14 @@ const {
|
|
|
939
256
|
cellLogs: [...state.cellLogs, ...action.logs],
|
|
940
257
|
};
|
|
941
258
|
},
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
// Create new cell data and runtime states for the new cell IDs
|
|
949
|
-
const nextCellData = { ...state.cellData };
|
|
950
|
-
const nextCellRuntime = { ...state.cellRuntime };
|
|
951
|
-
const nextCellHandles = { ...state.cellHandles };
|
|
952
|
-
|
|
953
|
-
for (const cellId of action.cellIds) {
|
|
954
|
-
if (!(cellId in state.cellData)) {
|
|
955
|
-
nextCellData[cellId] = createCell({ id: cellId });
|
|
956
|
-
}
|
|
957
|
-
if (!(cellId in state.cellRuntime)) {
|
|
958
|
-
nextCellRuntime[cellId] = createCellRuntimeState();
|
|
959
|
-
}
|
|
960
|
-
if (!(cellId in state.cellHandles)) {
|
|
961
|
-
nextCellHandles[cellId] = createRef();
|
|
259
|
+
/** Follow the host document's cells and order. */
|
|
260
|
+
reconcileDocument: (state, document: EditableDocument) => {
|
|
261
|
+
const nextState = applyDocument(state, document);
|
|
262
|
+
for (const cellId of state.cellIds) {
|
|
263
|
+
if (!(cellId in nextState.cellData)) {
|
|
264
|
+
releaseCellAtoms(cellId);
|
|
962
265
|
}
|
|
963
266
|
}
|
|
964
|
-
|
|
965
|
-
return {
|
|
966
|
-
...state,
|
|
967
|
-
cellIds: MultiColumn.fromWithPreviousShape(action.cellIds, state.cellIds),
|
|
968
|
-
cellData: nextCellData,
|
|
969
|
-
cellRuntime: nextCellRuntime,
|
|
970
|
-
cellHandles: nextCellHandles,
|
|
971
|
-
};
|
|
972
|
-
},
|
|
973
|
-
/**
|
|
974
|
-
* Rebuild the MultiColumn tree using each cell's `config.column` value.
|
|
975
|
-
*
|
|
976
|
-
* Used after a transaction whose `set-config` changes updated cells'
|
|
977
|
-
* column metadata without physically moving them in the tree. Cells with
|
|
978
|
-
* `config.column == null` inherit the column of the previous cell in the
|
|
979
|
-
* given order (see `MultiColumn.fromIdsAndColumns`), which lets the server
|
|
980
|
-
* send column changes only at column boundaries.
|
|
981
|
-
*/
|
|
982
|
-
rebuildCellColumns: (state, action: { cellIds: CellId[] }) => {
|
|
983
|
-
const newCellIds = MultiColumn.fromIdsAndColumns(
|
|
984
|
-
action.cellIds.map((id) => [
|
|
985
|
-
id,
|
|
986
|
-
state.cellData[id]?.config.column ?? null,
|
|
987
|
-
]),
|
|
988
|
-
);
|
|
989
|
-
return { ...state, cellIds: newCellIds };
|
|
990
|
-
},
|
|
991
|
-
setCellCodes: (
|
|
992
|
-
state,
|
|
993
|
-
action: {
|
|
994
|
-
codes: string[];
|
|
995
|
-
ids: CellId[];
|
|
996
|
-
codeIsStale: boolean;
|
|
997
|
-
names?: string[];
|
|
998
|
-
configs?: CellConfig[];
|
|
999
|
-
},
|
|
1000
|
-
) => {
|
|
1001
|
-
invariant(
|
|
1002
|
-
action.codes.length === action.ids.length,
|
|
1003
|
-
"Expected codes and ids to have the same length",
|
|
1004
|
-
);
|
|
1005
|
-
|
|
1006
|
-
let nextState = { ...state };
|
|
1007
|
-
|
|
1008
|
-
const cellReducer = ({
|
|
1009
|
-
cell,
|
|
1010
|
-
code,
|
|
1011
|
-
cellId,
|
|
1012
|
-
name,
|
|
1013
|
-
config,
|
|
1014
|
-
}: {
|
|
1015
|
-
cell: CellData | undefined;
|
|
1016
|
-
code: string;
|
|
1017
|
-
cellId: CellId;
|
|
1018
|
-
name?: string;
|
|
1019
|
-
config?: CellConfig;
|
|
1020
|
-
}) => {
|
|
1021
|
-
if (!cell) {
|
|
1022
|
-
return createCell({
|
|
1023
|
-
id: cellId,
|
|
1024
|
-
code,
|
|
1025
|
-
name: name,
|
|
1026
|
-
config: config,
|
|
1027
|
-
lastCodeRun: action.codeIsStale ? null : code,
|
|
1028
|
-
edited: action.codeIsStale && code.trim().length > 0,
|
|
1029
|
-
});
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// If code is stale, we don't promote it to lastCodeRun
|
|
1033
|
-
const lastCodeRun = action.codeIsStale ? cell.lastCodeRun : code;
|
|
1034
|
-
|
|
1035
|
-
// Mark as edited if the code has changed
|
|
1036
|
-
const edited = lastCodeRun
|
|
1037
|
-
? lastCodeRun.trim() !== code.trim()
|
|
1038
|
-
: Boolean(code);
|
|
1039
|
-
|
|
1040
|
-
// No change
|
|
1041
|
-
if (cell.code.trim() === code.trim()) {
|
|
1042
|
-
return {
|
|
1043
|
-
...cell,
|
|
1044
|
-
code: code,
|
|
1045
|
-
edited,
|
|
1046
|
-
lastCodeRun,
|
|
1047
|
-
...(name !== undefined && { name }),
|
|
1048
|
-
...(config !== undefined && { config }),
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
// Update codemirror if mounted. RTC-backed cells sync via Loro; others
|
|
1053
|
-
// (e.g. scratchpad) still need an explicit editor update.
|
|
1054
|
-
if (!isRtcEnabled() || !canUseRtc(cellId)) {
|
|
1055
|
-
const cellHandle = nextState.cellHandles[cellId].current;
|
|
1056
|
-
if (cellHandle?.editorViewOrNull) {
|
|
1057
|
-
updateEditorCodeFromPython(cellHandle.editorViewOrNull, code);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
return {
|
|
1062
|
-
...cell,
|
|
1063
|
-
code: code,
|
|
1064
|
-
edited,
|
|
1065
|
-
lastCodeRun,
|
|
1066
|
-
...(name !== undefined && { name }),
|
|
1067
|
-
...(config !== undefined && { config }),
|
|
1068
|
-
};
|
|
1069
|
-
};
|
|
1070
|
-
|
|
1071
|
-
for (let i = 0; i < action.ids.length; i++) {
|
|
1072
|
-
const cellId = action.ids[i];
|
|
1073
|
-
const code = action.codes[i];
|
|
1074
|
-
if (cellId === undefined || code === undefined) {
|
|
1075
|
-
continue;
|
|
1076
|
-
}
|
|
1077
|
-
const name = action.names?.[i];
|
|
1078
|
-
const config = action.configs?.[i];
|
|
1079
|
-
nextState = {
|
|
1080
|
-
...nextState,
|
|
1081
|
-
cellData: {
|
|
1082
|
-
...nextState.cellData,
|
|
1083
|
-
[cellId]: cellReducer({
|
|
1084
|
-
cell: nextState.cellData[cellId],
|
|
1085
|
-
code,
|
|
1086
|
-
cellId,
|
|
1087
|
-
name,
|
|
1088
|
-
config,
|
|
1089
|
-
}),
|
|
1090
|
-
},
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
267
|
return nextState;
|
|
1095
268
|
},
|
|
1096
269
|
setStdinResponse: (
|
|
@@ -1114,6 +287,7 @@ const {
|
|
|
1114
287
|
mimetype: stdinOutput.mimetype,
|
|
1115
288
|
data: stdinOutput.data,
|
|
1116
289
|
timestamp: stdinOutput.timestamp,
|
|
290
|
+
id: stdinOutput.id,
|
|
1117
291
|
// An empty response resolves the prompt without retaining the secret.
|
|
1118
292
|
response: stdinOutput.mimetype === "text/password" ? "" : response,
|
|
1119
293
|
};
|
|
@@ -1126,155 +300,44 @@ const {
|
|
|
1126
300
|
},
|
|
1127
301
|
});
|
|
1128
302
|
},
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
// WASM has no server-side SessionView to replay outputs, so the
|
|
1133
|
-
// snapshot hydrated by notebookStateFromSession is the only source.
|
|
1134
|
-
const preserveSnapshot = isWasm();
|
|
1135
|
-
const runtimeFor = (cellId: CellId): CellRuntimeState => {
|
|
1136
|
-
if (!preserveSnapshot) {
|
|
1137
|
-
return createCellRuntimeState();
|
|
1138
|
-
}
|
|
1139
|
-
const prev = state.cellRuntime[cellId];
|
|
1140
|
-
const hasSnapshot =
|
|
1141
|
-
prev && (prev.output != null || prev.consoleOutputs.length > 0);
|
|
1142
|
-
return hasSnapshot ? prev : createCellRuntimeState();
|
|
1143
|
-
};
|
|
1144
|
-
const cellRuntime = Object.fromEntries(
|
|
1145
|
-
cells.map((cell) => [cell.id, runtimeFor(cell.id)]),
|
|
1146
|
-
);
|
|
1147
|
-
|
|
1148
|
-
return withScratchCell({
|
|
1149
|
-
...state,
|
|
1150
|
-
cellIds: MultiColumn.fromIdsAndColumns(
|
|
1151
|
-
cells.map((cell) => [cell.id, cell.config.column]),
|
|
1152
|
-
),
|
|
1153
|
-
cellData: cellData,
|
|
1154
|
-
cellRuntime: cellRuntime,
|
|
1155
|
-
cellHandles: Object.fromEntries(
|
|
1156
|
-
cells.map((cell) => [cell.id, createRef()]),
|
|
1157
|
-
),
|
|
1158
|
-
});
|
|
1159
|
-
},
|
|
1160
|
-
/**
|
|
1161
|
-
* Move focus to next cell
|
|
1162
|
-
*
|
|
1163
|
-
* Creates a new cell if the current cell is the last one in the array.
|
|
1164
|
-
*
|
|
1165
|
-
* If needed, scrolls newly created or focused cell into view.
|
|
1166
|
-
*
|
|
1167
|
-
* Replicates Shift+Enter functionality of Jupyter
|
|
1168
|
-
*/
|
|
1169
|
-
moveToNextCell: (
|
|
303
|
+
/** Record what the kernel last ran for each cell. */
|
|
304
|
+
setLastRun: (
|
|
1170
305
|
state,
|
|
1171
|
-
action: {
|
|
306
|
+
action: {
|
|
307
|
+
lastCodeRun: Record<CellId, string>;
|
|
308
|
+
lastExecutionTime: Record<CellId, number>;
|
|
309
|
+
},
|
|
1172
310
|
) => {
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
const isPastLastCell = nextCellIndex === column.length;
|
|
1185
|
-
const isBeforeFirstCell = nextCellIndex === -1;
|
|
1186
|
-
|
|
1187
|
-
// Create a new cell at the end and set scrollKey to focus it
|
|
1188
|
-
if (isPastLastCell && !noCreate) {
|
|
1189
|
-
const newCellId = CellId.create();
|
|
1190
|
-
return {
|
|
1191
|
-
...state,
|
|
1192
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, nextCellIndex),
|
|
1193
|
-
cellData: {
|
|
1194
|
-
...state.cellData,
|
|
1195
|
-
[newCellId]: createCell({ id: newCellId }),
|
|
1196
|
-
},
|
|
1197
|
-
cellRuntime: {
|
|
1198
|
-
...state.cellRuntime,
|
|
1199
|
-
[newCellId]: createCellRuntimeState(),
|
|
1200
|
-
},
|
|
1201
|
-
cellHandles: {
|
|
1202
|
-
...state.cellHandles,
|
|
1203
|
-
[newCellId]: createRef(),
|
|
1204
|
-
},
|
|
1205
|
-
scrollKey: newCellId,
|
|
1206
|
-
};
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
if (isBeforeFirstCell && !noCreate) {
|
|
1210
|
-
const newCellId = CellId.create();
|
|
1211
|
-
return {
|
|
1212
|
-
...state,
|
|
1213
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, 0),
|
|
1214
|
-
cellData: {
|
|
1215
|
-
...state.cellData,
|
|
1216
|
-
[newCellId]: createCell({ id: newCellId }),
|
|
1217
|
-
},
|
|
1218
|
-
cellRuntime: {
|
|
1219
|
-
...state.cellRuntime,
|
|
1220
|
-
[newCellId]: createCellRuntimeState(),
|
|
1221
|
-
},
|
|
1222
|
-
cellHandles: {
|
|
1223
|
-
...state.cellHandles,
|
|
1224
|
-
[newCellId]: createRef(),
|
|
1225
|
-
},
|
|
1226
|
-
scrollKey: newCellId,
|
|
1227
|
-
};
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
if ((isPastLastCell || isBeforeFirstCell) && noCreate) {
|
|
1231
|
-
// Trying to move past the last cell or before the first cell
|
|
1232
|
-
// with noCreate=true - do nothing
|
|
1233
|
-
return state;
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
if (nextCellIndex >= 0 && nextCellIndex < column.length) {
|
|
1237
|
-
// Move to valid cell within bounds
|
|
1238
|
-
const nextCellId = column.atOrThrow(nextCellIndex);
|
|
1239
|
-
// Just focus, no state change
|
|
1240
|
-
focusAndScrollCellIntoView({
|
|
1241
|
-
cellId: nextCellId,
|
|
1242
|
-
cell: state.cellHandles[nextCellId],
|
|
1243
|
-
isCodeHidden: isCellCodeHidden(state, nextCellId),
|
|
1244
|
-
codeFocus: before ? "bottom" : "top",
|
|
1245
|
-
variableName: undefined,
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
return state;
|
|
1250
|
-
},
|
|
1251
|
-
markTouched: (state, action: { cellId: CellId }) => {
|
|
1252
|
-
const { cellId } = action;
|
|
1253
|
-
|
|
1254
|
-
if (state.untouchedNewCells.has(cellId)) {
|
|
1255
|
-
const nextUntouchedNewCells = new Set(state.untouchedNewCells);
|
|
1256
|
-
nextUntouchedNewCells.delete(cellId);
|
|
1257
|
-
return {
|
|
1258
|
-
...state,
|
|
1259
|
-
untouchedNewCells: nextUntouchedNewCells,
|
|
311
|
+
const cellData = { ...state.cellData };
|
|
312
|
+
for (const cellId of state.cellIds) {
|
|
313
|
+
const cell = state.cellData[cellId];
|
|
314
|
+
const lastCodeRun = action.lastCodeRun[cellId] ?? null;
|
|
315
|
+
cellData[cellId] = {
|
|
316
|
+
...cell,
|
|
317
|
+
lastCodeRun,
|
|
318
|
+
lastExecutionTime: action.lastExecutionTime[cellId] ?? null,
|
|
319
|
+
// A cell the kernel never ran is not stale on load.
|
|
320
|
+
edited: lastCodeRun !== null && isEdited(lastCodeRun, cell.code),
|
|
1260
321
|
};
|
|
1261
322
|
}
|
|
1262
|
-
|
|
1263
|
-
return state;
|
|
323
|
+
return { ...state, cellData };
|
|
1264
324
|
},
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
325
|
+
/**
|
|
326
|
+
* Start each cell's runtime over for a new kernel. WASM keeps the outputs
|
|
327
|
+
* its mount-time snapshot gave it.
|
|
328
|
+
*/
|
|
329
|
+
resetCellRuntimes: (state) => {
|
|
330
|
+
const preserveSnapshot = isWasm();
|
|
331
|
+
const cellRuntime = { ...state.cellRuntime };
|
|
332
|
+
for (const cellId of [...state.cellIds, SCRATCH_CELL_ID]) {
|
|
333
|
+
const previous = state.cellRuntime[cellId];
|
|
334
|
+
const hasSnapshot =
|
|
335
|
+
preserveSnapshot &&
|
|
336
|
+
previous !== undefined &&
|
|
337
|
+
(previous.output != null || previous.consoleOutputs.length > 0);
|
|
338
|
+
cellRuntime[cellId] = hasSnapshot ? previous : createCellRuntimeState();
|
|
1275
339
|
}
|
|
1276
|
-
|
|
1277
|
-
return state;
|
|
340
|
+
return { ...state, cellRuntime };
|
|
1278
341
|
},
|
|
1279
342
|
scrollToTarget: (state) => {
|
|
1280
343
|
// Scroll to the specified cell and clear the scroll key.
|
|
@@ -1283,16 +346,15 @@ const {
|
|
|
1283
346
|
return state;
|
|
1284
347
|
}
|
|
1285
348
|
|
|
1286
|
-
const
|
|
1287
|
-
const index = column.indexOfOrThrow(scrollKey);
|
|
1288
|
-
|
|
1289
|
-
const cellId =
|
|
1290
|
-
index === column.length - 1 ? column.last() : column.atOrThrow(index);
|
|
1291
|
-
|
|
349
|
+
const cellId = scrollKey;
|
|
1292
350
|
focusAndScrollCellIntoView({
|
|
1293
351
|
cellId: cellId,
|
|
1294
352
|
cell: state.cellHandles[cellId],
|
|
1295
|
-
isCodeHidden:
|
|
353
|
+
isCodeHidden: isCodeHidden(
|
|
354
|
+
state.cellData[cellId]?.config.hide_code,
|
|
355
|
+
store.get(shownHiddenCodeAtom),
|
|
356
|
+
cellId,
|
|
357
|
+
),
|
|
1296
358
|
codeFocus: undefined,
|
|
1297
359
|
variableName: undefined,
|
|
1298
360
|
});
|
|
@@ -1322,201 +384,6 @@ const {
|
|
|
1322
384
|
cellLogs: [],
|
|
1323
385
|
};
|
|
1324
386
|
},
|
|
1325
|
-
collapseCell: (state, action: { cellId: CellId }) => {
|
|
1326
|
-
const { cellId } = action;
|
|
1327
|
-
const column = state.cellIds.findWithId(cellId);
|
|
1328
|
-
|
|
1329
|
-
// Get all the top-level outlines
|
|
1330
|
-
const outlines = column.topLevelIds.map((id) => {
|
|
1331
|
-
const cell = state.cellRuntime[id];
|
|
1332
|
-
return cell.outline;
|
|
1333
|
-
});
|
|
1334
|
-
|
|
1335
|
-
// Find the start/end of the collapsed range
|
|
1336
|
-
const startIndex = column.indexOfOrThrow(cellId);
|
|
1337
|
-
const range = findCollapseRange(startIndex, outlines);
|
|
1338
|
-
if (!range) {
|
|
1339
|
-
return state;
|
|
1340
|
-
}
|
|
1341
|
-
const endCellId = column.atOrThrow(range[1]);
|
|
1342
|
-
|
|
1343
|
-
return {
|
|
1344
|
-
...state,
|
|
1345
|
-
// Collapse the range
|
|
1346
|
-
cellIds: state.cellIds.transformWithCellId(cellId, (column) =>
|
|
1347
|
-
column.collapse(cellId, endCellId),
|
|
1348
|
-
),
|
|
1349
|
-
scrollKey: cellId,
|
|
1350
|
-
};
|
|
1351
|
-
},
|
|
1352
|
-
expandCell: (state, action: { cellId: CellId }) => {
|
|
1353
|
-
const { cellId } = action;
|
|
1354
|
-
return {
|
|
1355
|
-
...state,
|
|
1356
|
-
cellIds: state.cellIds.transformWithCellId(cellId, (column) =>
|
|
1357
|
-
column.expand(cellId),
|
|
1358
|
-
),
|
|
1359
|
-
scrollKey: cellId,
|
|
1360
|
-
};
|
|
1361
|
-
},
|
|
1362
|
-
collapseAllCells: (state) => {
|
|
1363
|
-
return {
|
|
1364
|
-
...state,
|
|
1365
|
-
cellIds: state.cellIds.transformAll((column) => {
|
|
1366
|
-
// Get all the top-level outlines
|
|
1367
|
-
const outlines = column.topLevelIds.map((id) => {
|
|
1368
|
-
const cell = state.cellRuntime[id];
|
|
1369
|
-
return cell.outline;
|
|
1370
|
-
});
|
|
1371
|
-
|
|
1372
|
-
// Find the start/end of the collapsed ranges
|
|
1373
|
-
const nodes = [...column.nodes];
|
|
1374
|
-
const visibleEndByOriginalEnd = new Map<CellIndex, CellIndex>();
|
|
1375
|
-
const reversedCollapseRanges = [];
|
|
1376
|
-
|
|
1377
|
-
// Iterate in reverse order (bottom-up) to process children first
|
|
1378
|
-
let i = nodes.length - 1;
|
|
1379
|
-
while (i >= 0) {
|
|
1380
|
-
const range = findCollapseRange(i, outlines);
|
|
1381
|
-
if (range) {
|
|
1382
|
-
const startIndex = i;
|
|
1383
|
-
const originalEnd = range[1];
|
|
1384
|
-
const endIndex =
|
|
1385
|
-
visibleEndByOriginalEnd.get(originalEnd) ?? originalEnd;
|
|
1386
|
-
|
|
1387
|
-
// After this section collapses, its heading represents this
|
|
1388
|
-
// endpoint for any enclosing section that shares it.
|
|
1389
|
-
visibleEndByOriginalEnd.set(originalEnd, startIndex);
|
|
1390
|
-
|
|
1391
|
-
// Add the range to the list of ranges
|
|
1392
|
-
const cellId = column.atOrThrow(startIndex);
|
|
1393
|
-
const until = column.atOrThrow(endIndex);
|
|
1394
|
-
reversedCollapseRanges.push({ id: cellId, until });
|
|
1395
|
-
} else {
|
|
1396
|
-
reversedCollapseRanges.push(null);
|
|
1397
|
-
}
|
|
1398
|
-
i--;
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
const collapseRanges = reversedCollapseRanges.toReversed();
|
|
1402
|
-
return column.collapseAll(collapseRanges);
|
|
1403
|
-
}),
|
|
1404
|
-
};
|
|
1405
|
-
},
|
|
1406
|
-
expandAllCells: (state) => {
|
|
1407
|
-
return {
|
|
1408
|
-
...state,
|
|
1409
|
-
cellIds: state.cellIds.transformAll((column) => column.expandAll()),
|
|
1410
|
-
};
|
|
1411
|
-
},
|
|
1412
|
-
showCellIfHidden: (state, action: { cellId: CellId }) => {
|
|
1413
|
-
const { cellId } = action;
|
|
1414
|
-
const column = state.cellIds.findWithId(cellId);
|
|
1415
|
-
const prev = column;
|
|
1416
|
-
const result = column.findAndExpandDeep(cellId);
|
|
1417
|
-
|
|
1418
|
-
if (result.equals(prev)) {
|
|
1419
|
-
return state;
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
return {
|
|
1423
|
-
...state,
|
|
1424
|
-
cellIds: state.cellIds.transformWithCellId(cellId, () => result),
|
|
1425
|
-
};
|
|
1426
|
-
},
|
|
1427
|
-
splitCell: (state, action: { cellId: CellId }) => {
|
|
1428
|
-
const { cellId } = action;
|
|
1429
|
-
const column = state.cellIds.findWithId(cellId);
|
|
1430
|
-
const index = column.indexOfOrThrow(cellId);
|
|
1431
|
-
const cell = state.cellData[cellId];
|
|
1432
|
-
const cellHandle = state.cellHandles[cellId].current;
|
|
1433
|
-
|
|
1434
|
-
if (cellHandle?.editorView == null) {
|
|
1435
|
-
return state;
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
const { beforeCursorCode, afterCursorCode } = splitEditor(
|
|
1439
|
-
cellHandle.editorView,
|
|
1440
|
-
);
|
|
1441
|
-
|
|
1442
|
-
updateEditorCodeFromPython(cellHandle.editorView, beforeCursorCode);
|
|
1443
|
-
|
|
1444
|
-
const newCellId = CellId.create();
|
|
1445
|
-
|
|
1446
|
-
return {
|
|
1447
|
-
...state,
|
|
1448
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, index + 1),
|
|
1449
|
-
cellData: {
|
|
1450
|
-
...state.cellData,
|
|
1451
|
-
[cellId]: {
|
|
1452
|
-
...cell,
|
|
1453
|
-
code: beforeCursorCode,
|
|
1454
|
-
edited:
|
|
1455
|
-
Boolean(beforeCursorCode) &&
|
|
1456
|
-
beforeCursorCode.trim() !== cell.lastCodeRun?.trim(),
|
|
1457
|
-
},
|
|
1458
|
-
[newCellId]: createCell({
|
|
1459
|
-
id: newCellId,
|
|
1460
|
-
code: afterCursorCode,
|
|
1461
|
-
edited: Boolean(afterCursorCode),
|
|
1462
|
-
}),
|
|
1463
|
-
},
|
|
1464
|
-
cellRuntime: {
|
|
1465
|
-
...state.cellRuntime,
|
|
1466
|
-
[cellId]: {
|
|
1467
|
-
...state.cellRuntime[cellId],
|
|
1468
|
-
output: null,
|
|
1469
|
-
consoleOutputs: [],
|
|
1470
|
-
},
|
|
1471
|
-
[newCellId]: createCellRuntimeState(),
|
|
1472
|
-
},
|
|
1473
|
-
cellHandles: {
|
|
1474
|
-
...state.cellHandles,
|
|
1475
|
-
[newCellId]: createRef(),
|
|
1476
|
-
},
|
|
1477
|
-
scrollKey: newCellId,
|
|
1478
|
-
};
|
|
1479
|
-
},
|
|
1480
|
-
undoSplitCell: (state, action: { cellId: CellId; snapshot: string }) => {
|
|
1481
|
-
const { cellId, snapshot } = action;
|
|
1482
|
-
|
|
1483
|
-
const cell = state.cellData[cellId];
|
|
1484
|
-
const cellHandle = state.cellHandles[cellId].current;
|
|
1485
|
-
|
|
1486
|
-
if (cellHandle?.editorView == null) {
|
|
1487
|
-
return state;
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
updateEditorCodeFromPython(cellHandle.editorView, snapshot);
|
|
1491
|
-
|
|
1492
|
-
return {
|
|
1493
|
-
...state,
|
|
1494
|
-
cellIds: state.cellIds.transformWithCellId(cellId, (column) => {
|
|
1495
|
-
const newCellIndex = column.indexOfOrThrow(cellId) + 1;
|
|
1496
|
-
return column.deleteAtIndex(newCellIndex);
|
|
1497
|
-
}),
|
|
1498
|
-
cellData: {
|
|
1499
|
-
...state.cellData,
|
|
1500
|
-
[cellId]: {
|
|
1501
|
-
...cell,
|
|
1502
|
-
code: snapshot,
|
|
1503
|
-
edited:
|
|
1504
|
-
Boolean(snapshot) && snapshot?.trim() !== cell.lastCodeRun?.trim(),
|
|
1505
|
-
},
|
|
1506
|
-
},
|
|
1507
|
-
cellRuntime: {
|
|
1508
|
-
...state.cellRuntime,
|
|
1509
|
-
[cellId]: {
|
|
1510
|
-
...state.cellRuntime[cellId],
|
|
1511
|
-
output: null,
|
|
1512
|
-
consoleOutputs: [],
|
|
1513
|
-
},
|
|
1514
|
-
},
|
|
1515
|
-
cellHandles: {
|
|
1516
|
-
...state.cellHandles,
|
|
1517
|
-
},
|
|
1518
|
-
};
|
|
1519
|
-
},
|
|
1520
387
|
clearCellOutput: (state, action: { cellId: CellId }) => {
|
|
1521
388
|
const { cellId } = action;
|
|
1522
389
|
return updateCellRuntimeState({
|
|
@@ -1545,7 +412,7 @@ const {
|
|
|
1545
412
|
},
|
|
1546
413
|
clearAllCellOutputs: (state) => {
|
|
1547
414
|
const newCellRuntime = { ...state.cellRuntime };
|
|
1548
|
-
for (const cellId of state.cellIds
|
|
415
|
+
for (const cellId of state.cellIds) {
|
|
1549
416
|
newCellRuntime[cellId] = {
|
|
1550
417
|
...newCellRuntime[cellId],
|
|
1551
418
|
output: null,
|
|
@@ -1557,57 +424,12 @@ const {
|
|
|
1557
424
|
cellRuntime: newCellRuntime,
|
|
1558
425
|
};
|
|
1559
426
|
},
|
|
1560
|
-
addSetupCellIfDoesntExist: (state, action: { code?: string }) => {
|
|
1561
|
-
const { code } = action;
|
|
1562
|
-
|
|
1563
|
-
if (state.cellIds.setupCellExists()) {
|
|
1564
|
-
// Just focus on the existing setup cell
|
|
1565
|
-
return {
|
|
1566
|
-
...state,
|
|
1567
|
-
scrollKey: SETUP_CELL_ID,
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
return {
|
|
1572
|
-
...state,
|
|
1573
|
-
cellIds: state.cellIds.insertId(
|
|
1574
|
-
SETUP_CELL_ID,
|
|
1575
|
-
state.cellIds.atOrThrow(0).id,
|
|
1576
|
-
0,
|
|
1577
|
-
),
|
|
1578
|
-
cellData: {
|
|
1579
|
-
...state.cellData,
|
|
1580
|
-
[SETUP_CELL_ID]: createCell({
|
|
1581
|
-
id: SETUP_CELL_ID,
|
|
1582
|
-
name: SETUP_CELL_ID,
|
|
1583
|
-
code,
|
|
1584
|
-
edited: Boolean(code),
|
|
1585
|
-
}),
|
|
1586
|
-
},
|
|
1587
|
-
cellRuntime: {
|
|
1588
|
-
...state.cellRuntime,
|
|
1589
|
-
[SETUP_CELL_ID]: createCellRuntimeState(),
|
|
1590
|
-
},
|
|
1591
|
-
cellHandles: {
|
|
1592
|
-
...state.cellHandles,
|
|
1593
|
-
[SETUP_CELL_ID]: createRef(),
|
|
1594
|
-
},
|
|
1595
|
-
scrollKey: SETUP_CELL_ID,
|
|
1596
|
-
};
|
|
1597
|
-
},
|
|
1598
427
|
});
|
|
1599
428
|
|
|
1600
429
|
// We apply the middleware here (rather than inline in createReducerAndAtoms)
|
|
1601
|
-
// so that the document
|
|
430
|
+
// so that the document edit middleware can import CellActions and
|
|
1602
431
|
// strictly type the dispatched actions without creating a circular dependency.
|
|
1603
|
-
addMiddleware(
|
|
1604
|
-
|
|
1605
|
-
function isCellCodeHidden(state: NotebookState, cellId: CellId): boolean {
|
|
1606
|
-
return (
|
|
1607
|
-
Boolean(state.cellData[cellId].config.hide_code) &&
|
|
1608
|
-
!state.untouchedNewCells.has(cellId)
|
|
1609
|
-
);
|
|
1610
|
-
}
|
|
432
|
+
addMiddleware(documentEditMiddleware);
|
|
1611
433
|
|
|
1612
434
|
// Helper function to update a cell in the array
|
|
1613
435
|
function updateCellRuntimeState({
|
|
@@ -1656,43 +478,12 @@ function updateCellData({
|
|
|
1656
478
|
};
|
|
1657
479
|
}
|
|
1658
480
|
|
|
481
|
+
/** Each cell's config in order. The document's `column` configs are canonical. */
|
|
1659
482
|
export function getCellConfigs(state: NotebookState): CellConfig[] {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
// Handle the case where there's only one column
|
|
1666
|
-
// We don't want to set the column config
|
|
1667
|
-
const hasMultipleColumns = state.cellIds.getColumns().length > 1;
|
|
1668
|
-
if (!hasMultipleColumns) {
|
|
1669
|
-
return state.cellIds.getColumns().flatMap((column) => {
|
|
1670
|
-
return column.inOrderIds.map((cellId) => {
|
|
1671
|
-
return {
|
|
1672
|
-
...cells[cellId].config,
|
|
1673
|
-
...defaultCellConfig,
|
|
1674
|
-
};
|
|
1675
|
-
});
|
|
1676
|
-
});
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
return state.cellIds.getColumns().flatMap((column, columnIndex) => {
|
|
1680
|
-
return column.inOrderIds.map((cellId, cellIndex) => {
|
|
1681
|
-
const config: Partial<CellConfig> = { ...defaultCellConfig };
|
|
1682
|
-
|
|
1683
|
-
// Only set the column index for the first cell in the column
|
|
1684
|
-
if (cellIndex === 0) {
|
|
1685
|
-
config.column = columnIndex;
|
|
1686
|
-
}
|
|
1687
|
-
|
|
1688
|
-
const newConfig = {
|
|
1689
|
-
...cells[cellId].config,
|
|
1690
|
-
...config,
|
|
1691
|
-
};
|
|
1692
|
-
|
|
1693
|
-
return newConfig;
|
|
1694
|
-
});
|
|
1695
|
-
});
|
|
483
|
+
return state.cellIds.map((cellId) => ({
|
|
484
|
+
...state.cellData[cellId].config,
|
|
485
|
+
column: state.cellData[cellId].config.column ?? null,
|
|
486
|
+
}));
|
|
1696
487
|
}
|
|
1697
488
|
|
|
1698
489
|
export {
|
|
@@ -1712,9 +503,7 @@ export const addLogs = imperativeActions.addLogs;
|
|
|
1712
503
|
|
|
1713
504
|
export const cellIdsAtom = atom((get) => get(notebookAtom).cellIds);
|
|
1714
505
|
|
|
1715
|
-
export const hasOnlyOneCellAtom = atom((get) =>
|
|
1716
|
-
get(cellIdsAtom).hasOnlyOneId(),
|
|
1717
|
-
);
|
|
506
|
+
export const hasOnlyOneCellAtom = atom((get) => get(cellIdsAtom).length === 1);
|
|
1718
507
|
|
|
1719
508
|
export const hasDisabledCellsAtom = atom(
|
|
1720
509
|
(get) => disabledCellIds(get(notebookAtom)).length > 0,
|
|
@@ -1732,7 +521,7 @@ export const needsRunAtom = atom((get) => notebookNeedsRun(get(notebookAtom)));
|
|
|
1732
521
|
|
|
1733
522
|
export const cellErrorsAtom = atom((get) => {
|
|
1734
523
|
const { cellIds, cellRuntime, cellData } = get(notebookAtom);
|
|
1735
|
-
const errors = cellIds
|
|
524
|
+
const errors = cellIds
|
|
1736
525
|
.map((cellId) => {
|
|
1737
526
|
const cell = cellRuntime[cellId];
|
|
1738
527
|
const { name } = cellData[cellId];
|
|
@@ -1760,11 +549,28 @@ export const cellErrorsAtom = atom((get) => {
|
|
|
1760
549
|
return errors;
|
|
1761
550
|
});
|
|
1762
551
|
|
|
552
|
+
/**
|
|
553
|
+
* The outline of each cell whose output has a heading. Compared by value, so
|
|
554
|
+
* readers are left alone by the runtime messages that change no heading.
|
|
555
|
+
*/
|
|
556
|
+
export const cellOutlinesAtom = createDeepEqualAtom(
|
|
557
|
+
atom((get) => {
|
|
558
|
+
const outlines: Partial<Record<CellId, Outline>> = {};
|
|
559
|
+
for (const [id, runtime] of Objects.entries(
|
|
560
|
+
get(notebookAtom).cellRuntime,
|
|
561
|
+
)) {
|
|
562
|
+
if (runtime.outline !== null && runtime.outline.items.length > 0) {
|
|
563
|
+
outlines[id] = runtime.outline;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return outlines;
|
|
567
|
+
}),
|
|
568
|
+
);
|
|
569
|
+
|
|
1763
570
|
export const notebookOutline = atom((get) => {
|
|
1764
|
-
const
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
);
|
|
571
|
+
const cellIds = get(cellIdsAtom);
|
|
572
|
+
const cellRuntime = get(cellsRuntimeAtom);
|
|
573
|
+
const outlines = cellIds.map((cellId) => cellRuntime[cellId].outline);
|
|
1768
574
|
return mergeOutlines(outlines);
|
|
1769
575
|
});
|
|
1770
576
|
|
|
@@ -1774,7 +580,7 @@ export const cellIdToNamesMap = createDeepEqualAtom(
|
|
|
1774
580
|
atom((get) => {
|
|
1775
581
|
const { cellIds, cellData } = get(notebookAtom);
|
|
1776
582
|
const names: Record<CellId, string | undefined> = Objects.fromEntries(
|
|
1777
|
-
cellIds.
|
|
583
|
+
cellIds.map((cellId) => [cellId, cellData[cellId]?.name]),
|
|
1778
584
|
);
|
|
1779
585
|
return names;
|
|
1780
586
|
}),
|
|
@@ -1831,12 +637,12 @@ export const getCells = () => store.get(notebookAtom).cellIds;
|
|
|
1831
637
|
*/
|
|
1832
638
|
export const getCellNames = () => {
|
|
1833
639
|
const { cellIds, cellData } = store.get(notebookAtom);
|
|
1834
|
-
return cellIds.
|
|
640
|
+
return cellIds.map((id) => cellData[id]?.name).filter(Boolean);
|
|
1835
641
|
};
|
|
1836
642
|
|
|
1837
643
|
const cellDataAtoms = splitAtom(
|
|
1838
644
|
selectAtom(notebookAtom, (cells) =>
|
|
1839
|
-
cells.cellIds.
|
|
645
|
+
cells.cellIds.map((id) => cells.cellData[id]),
|
|
1840
646
|
),
|
|
1841
647
|
);
|
|
1842
648
|
export const useCellDataAtoms = () => useAtom(cellDataAtoms);
|
|
@@ -1856,16 +662,7 @@ export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
|
1856
662
|
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
1857
663
|
);
|
|
1858
664
|
|
|
1859
|
-
export const
|
|
1860
|
-
(get) => get(notebookAtom).cellIds.colLength,
|
|
1861
|
-
);
|
|
1862
|
-
export const hasCellsAtom = atom(
|
|
1863
|
-
(get) => get(notebookAtom).cellIds.idLength > 0,
|
|
1864
|
-
);
|
|
1865
|
-
export const columnIdsAtom = atom((get) =>
|
|
1866
|
-
get(notebookAtom).cellIds.getColumnIds(),
|
|
1867
|
-
);
|
|
1868
|
-
|
|
665
|
+
export const hasCellsAtom = atom((get) => get(notebookAtom).cellIds.length > 0);
|
|
1869
666
|
export const cellDataAtom = atomFamily((cellId: CellId) =>
|
|
1870
667
|
atom((get) => get(notebookAtom).cellData[cellId]),
|
|
1871
668
|
);
|
|
@@ -1906,7 +703,7 @@ export const useCellHandle = (cellId: CellId) =>
|
|
|
1906
703
|
*/
|
|
1907
704
|
export const getAllEditorViews = () => {
|
|
1908
705
|
const { cellIds, cellHandles } = store.get(notebookAtom);
|
|
1909
|
-
return cellIds
|
|
706
|
+
return cellIds
|
|
1910
707
|
.map((cellId) => cellHandles[cellId]?.current?.editorViewOrNull)
|
|
1911
708
|
.filter(Boolean);
|
|
1912
709
|
};
|
|
@@ -1930,16 +727,10 @@ export function flattenTopLevelNotebookCells(
|
|
|
1930
727
|
state: NotebookState,
|
|
1931
728
|
): (CellData & CellRuntimeState)[] {
|
|
1932
729
|
const { cellIds, cellData, cellRuntime } = state;
|
|
1933
|
-
return cellIds.
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
})),
|
|
1938
|
-
);
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
export function createUntouchedCellAtom(cellId: CellId): Atom<boolean> {
|
|
1942
|
-
return atom((get) => get(notebookAtom).untouchedNewCells.has(cellId));
|
|
730
|
+
return cellIds.map((cellId) => ({
|
|
731
|
+
...cellData[cellId],
|
|
732
|
+
...cellRuntime[cellId],
|
|
733
|
+
}));
|
|
1943
734
|
}
|
|
1944
735
|
|
|
1945
736
|
export function createTracebackInfoAtom(
|
|
@@ -2001,20 +792,13 @@ export function createTracebackInfoAtom(
|
|
|
2001
792
|
});
|
|
2002
793
|
}
|
|
2003
794
|
|
|
2004
|
-
/**
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
*/
|
|
2008
|
-
export function useCellActions(
|
|
2009
|
-
options: { skipMiddleware?: boolean } = {},
|
|
2010
|
-
): CellActions {
|
|
2011
|
-
return useActions(options);
|
|
795
|
+
/** The reducer's actions. Components use `useCellActions` from `./actions`. */
|
|
796
|
+
export function useReducerActions(): ReducerCellActions {
|
|
797
|
+
return useActions();
|
|
2012
798
|
}
|
|
2013
799
|
|
|
2014
|
-
/**
|
|
2015
|
-
|
|
2016
|
-
*/
|
|
2017
|
-
export type CellActions = ReturnType<typeof createActions>;
|
|
800
|
+
/** The actions the reducer still handles. */
|
|
801
|
+
export type ReducerCellActions = ReturnType<typeof createActions>;
|
|
2018
802
|
|
|
2019
803
|
/**
|
|
2020
804
|
* This is exported for testing purposes only.
|
|
@@ -2023,7 +807,6 @@ export const exportedForTesting = {
|
|
|
2023
807
|
reducer,
|
|
2024
808
|
createActions,
|
|
2025
809
|
initialNotebookState,
|
|
2026
|
-
isCellCodeHidden,
|
|
2027
810
|
// Export atom families for testing cleanup
|
|
2028
811
|
cellDataAtom,
|
|
2029
812
|
cellRuntimeAtom,
|