@marimo-team/islands 0.25.3-dev28 → 0.25.3-dev281
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-7EaP9VWb.js → ConnectedDataExplorerComponent-CErm132k.js} +116 -113
- package/dist/{ErrorBoundary-CUdSBv06.js → ErrorBoundary-fSq1YI-S.js} +76 -82
- package/dist/_baseSet-BfI5FjBM.js +328 -0
- package/dist/{abnfDiagram-VCTEODGH-z_OSynK8.js → abnfDiagram-VCTEODGH-d-Qn2fwb.js} +2 -2
- package/dist/any-language-editor-6k6F12Z3.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-Cs8J8BZr.js → architectureDiagram-5GKGNRK7-DxragHYv.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
- package/dist/assertNever-B-YzWzbL.js +507 -0
- package/dist/assets/__vite-browser-external-BKBpimif.js +1 -0
- package/dist/assets/worker-CgoMtD-_.js +113 -0
- package/dist/{blockDiagram-I7D4REHJ-Cg25UrxT.js → blockDiagram-I7D4REHJ-Dkhe6_PP.js} +1 -1
- package/dist/{button-CvjkwdSk.js → button-DZuNnIZO.js} +56 -48
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-D9FskwsK.js} +2 -2
- package/dist/{chat-ui-BzjAsTFN.js → chat-ui-ByGe2rP1.js} +2100 -1810
- package/dist/{check-BMKBBrdc.js → check-XFzZeH-y.js} +1 -1
- package/dist/{chunk-IMKFNOWR-aoSFasqF.js → chunk-IMKFNOWR-C0x0feFg.js} +1 -1
- package/dist/{chunk-SHT3W25Y-CMaybO3O.js → chunk-SHT3W25Y-D0ZdASqB.js} +1 -1
- package/dist/{chunk-SVP7TREG-BNBrTAw1.js → chunk-SVP7TREG-BHjL96zx.js} +1 -1
- package/dist/{chunk-TICWLB2K-DXNxvUJn.js → chunk-TICWLB2K-CzcrwGfp.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-DXdCCDOg.js → classDiagram-ZZMXUADV-BTqFAZTP.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DyZqrtLP.js → classDiagram-v2-VYDZK3BY-EPXb0Elt.js} +2 -2
- package/dist/{code-visibility-BuxqA3v5.js → code-visibility-BhtW7mrV.js} +43 -50
- package/dist/{common-xtZHxsM2.js → common-BIZJLLSc.js} +10605 -10045
- package/dist/config-C8MFHQ2E.js +637 -0
- package/dist/{copy-icon-BgUO8jsi.js → copy-icon-CtllOdmg.js} +3 -3
- package/dist/createReducer-DRqwmaTc.js +67 -0
- package/dist/{cynefinDiagram-5FMLGOSQ-DWHuKJs8.js → cynefinDiagram-5FMLGOSQ-CBSD344q.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-DYLu-OCU.js → dagre-GXQ25YYZ-JItjh3Ge.js} +3 -3
- package/dist/{dagre-BGSfXNEb.js → dagre-mqiMAsFY.js} +531 -680
- package/dist/{data-grid-overlay-editor-qnbf5J94.js → data-grid-overlay-editor-B8b_mHmv.js} +1 -1
- package/dist/{debounce-C3jyATpc.js → debounce-DrhhziJv.js} +2 -2
- package/dist/{diagram-S7CK7UJ4-PwwcUOHP.js → diagram-S7CK7UJ4-CTD9xTVb.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-CvJbL_IM.js → diagram-UQ7AKVKN-DTfnFai8.js} +1 -1
- package/dist/{diagram-VX7I27RA-B5RkqnzN.js → diagram-VX7I27RA-BcSnucV-.js} +1 -1
- package/dist/{diagram-Z3DM3KII-CyijwTR2.js → diagram-Z3DM3KII-C2ATIE8A.js} +1 -1
- package/dist/{dialog-Cc479ZEH.js → dialog-CaYm5imE.js} +32 -32
- package/dist/{dist-Bvs24R_E.js → dist-11T5wq3_.js} +31 -30
- package/dist/{dist-F8Ep36rk.js → dist-17ugwGZc.js} +59 -58
- package/dist/{dist-BMQf5zIS.js → dist-7cRjf--y.js} +123 -122
- package/dist/{dist-diIx5qJW.js → dist-B8pkfkzc.js} +31 -30
- package/dist/{dist-CN_BeG2I.js → dist-B9UoM_wq.js} +58 -57
- package/dist/{dist-CLdpGQVr.js → dist-BGuMTs1i.js} +118 -117
- package/dist/{dist-BK4Oj99o.js → dist-BHW11fni.js} +18 -17
- package/dist/dist-BLY4m1Wi.js +850 -0
- package/dist/{dist-PXYI_yuP.js → dist-BNlcVoxs.js} +24 -23
- package/dist/{dist-D6d86eNJ.js → dist-BQYe5Bju.js} +47 -46
- package/dist/{dist-CkTTIdBe.js → dist-BX1mn8na.js} +337 -337
- package/dist/{dist-DiDibOYr.js → dist-Bh0PTKUW.js} +151 -150
- package/dist/{dist-CSJ0MDRw.js → dist-CKaXK92p.js} +56 -55
- package/dist/{dist-C8fAKSH1.js → dist-CLhwfhpJ.js} +53 -52
- package/dist/{dist-DoE4XJBC.js → dist-CYeqK4Xw.js} +9801 -10649
- package/dist/{dist-BLfKmR-l.js → dist-Cxlp3WH6.js} +16 -15
- package/dist/{dist-D-wwqlzJ.js → dist-DSJPGj42.js} +158 -157
- package/dist/{dist-BorMD-uX.js → dist-DU9ICsWZ.js} +75 -74
- package/dist/{dist-DBtSl3sf.js → dist-DWv0ALBi.js} +47 -46
- package/dist/{dist-OR1OnN-y.js → dist-DiBpWEsB.js} +31 -30
- package/dist/{dist-CrSP_H1M.js → dist-DiLFTlnl.js} +242 -242
- package/dist/{dist-CN8zI-XC.js → dist-X9CsotJl.js} +239 -239
- package/dist/{dist-CSbh1PNP.js → dist-cVDV5IuI.js} +23 -22
- package/dist/{dist-BuaRHxOc.js → dist-fRfaOoq8.js} +44 -43
- package/dist/{dist-Cg7gzw-a.js → dist-gTTI-9Px.js} +78 -77
- package/dist/{dropdown-menu-BuE2b8Yb.js → dropdown-menu-Bb0bFOIk.js} +2904 -1493
- package/dist/{ebnfDiagram-PWID7BFC-DG90ELFp.js → ebnfDiagram-PWID7BFC-B7B9JPxc.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-FMo_SpyX.js → erDiagram-RLTQ6QDP-v6hDno1O.js} +1 -1
- package/dist/{error-banner-CFPHFw4h.js → error-banner-CHCdHVFB.js} +87 -87
- package/dist/error-entries-9U4BFHjf.js +2586 -0
- package/dist/{esm-AMFssoNp.js → esm-BDqqT86j.js} +329 -329
- package/dist/{esm-D2gTsXEV.js → esm-BgKjMvWw.js} +530 -529
- package/dist/feedback-button-CY92zeC6.js +374 -0
- package/dist/{flowDiagram-HODETNUW-DQ4JuadE.js → flowDiagram-HODETNUW-aIFlAtOy.js} +2 -2
- package/dist/{formats-Bv_5N2Ff.js → formats-PzBQMUnr.js} +6 -6
- package/dist/{glide-data-editor-DQ_cEi05.js → glide-data-editor-BdgfR8uu.js} +6630 -2846
- package/dist/{glide-utils-pisbYVjH.js → glide-utils-BSQr4d90.js} +107 -76
- package/dist/{globals-D7vITxEX.js → globals-CjnqsurJ.js} +3 -3
- package/dist/{graphlib-BmY_CCV9.js → graphlib-nlwT3Wvy.js} +177 -220
- package/dist/hasIn-C20JsQ2m.js +28 -0
- package/dist/{error-entries-j85LP88u.js → html-to-image-BYh_MorV.js} +26294 -26451
- package/dist/{infoDiagram-27XIBGKW-CRSDtRrd.js → infoDiagram-27XIBGKW-D6YHLeCP.js} +1 -1
- package/dist/isArrayLikeObject-B-HXCsex.js +626 -0
- package/dist/isEmpty-CdX7MTE1.js +14 -0
- package/dist/{ishikawaDiagram-5VMMS53U-DxLEUldB.js → ishikawaDiagram-5VMMS53U-D1ZvprOX.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-BLhvu8o4.js → kanban-definition-UXKFOSKX-Bna_3BMr.js} +1 -1
- package/dist/{loader-BPdQhmlq.js → loader-DZvtzQoD.js} +3 -3
- package/dist/main.js +10276 -8171
- package/dist/{mermaid-Bjm6C1qN.js → mermaid-A36unKXJ.js} +62 -62
- package/dist/{mindmap-definition-YA3MSWOX-g2LwxnYQ.js → mindmap-definition-YA3MSWOX-CyVCs__G.js} +1 -1
- package/dist/{now-jM8-M7IR.js → now-BKZCLE5P.js} +12 -13
- package/dist/{number-overlay-editor-DJHB-CGK.js → number-overlay-editor-BQBhWG2O.js} +1 -1
- 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-CpMAt3Qs.js → pegDiagram-XKGWAZYB-9hNBD2wZ.js} +2 -2
- package/dist/pencil-DYUlSKxZ.js +10 -0
- package/dist/pick-tCszMUbm.js +35 -0
- package/dist/{pieDiagram-E7YTZNPT-CVTthoZo.js → pieDiagram-E7YTZNPT-8tr-NYo7.js} +1 -1
- package/dist/{process-output-DGzGHArA.js → process-output-bS3MGJ3f.js} +4 -4
- package/dist/{railroadDiagram-O6MQD6OU-ao8cqqFB.js → railroadDiagram-O6MQD6OU-Dzg1dyyp.js} +2 -2
- package/dist/{react-vega-BDpbvBCb.js → react-vega-C4T9Rb_w.js} +1 -1
- package/dist/{requirementDiagram-BXWQKSXE--J8vyfm-.js → requirementDiagram-BXWQKSXE-B7sNqwGG.js} +1 -1
- package/dist/{reveal-component-BxYUpAPg.js → reveal-component-BqyL-_xE.js} +1151 -1128
- package/dist/select-DsoP1qe8.js +1200 -0
- package/dist/{sequenceDiagram-WJ2MYXX4-CiQbn62x.js → sequenceDiagram-WJ2MYXX4-oP9shbaG.js} +1 -1
- package/dist/{spec-D_u2ipzF.js → spec-BZMDxAu7.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-DVEeGs5b.js → stateDiagram-D77RDMKH-CjCv4ogv.js} +4 -4
- package/dist/{stateDiagram-v2-MP3YSRHH-1OQRe6iA.js → stateDiagram-v2-MP3YSRHH-BW9X162a.js} +2 -2
- package/dist/static-state-D-Q-Ajaa.js +72 -0
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-CqkGoGqn.js → swimlanes-42K2YHIH-Ckfs9Wrn.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-CszjkrKo.js → swimlanesDiagram-VR7AAH4N-DpTNG9YP.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-DQbK_ZWm.js} +7 -7
- package/dist/{timeline-definition-24CTP7MA-DLRUNVAx.js → timeline-definition-24CTP7MA-BXaBlV6U.js} +1 -1
- package/dist/toast-BhjIy3Tq.js +491 -0
- package/dist/{tooltip-CtBZ5q8p.js → tooltip-DMMiOn2f.js} +321 -297
- package/dist/use-restore-focus-CosX7-gx.js +7568 -0
- package/dist/{useAsyncData-BneN349z.js → useAsyncData-Ci4AvJff.js} +18 -17
- package/dist/{useDateFormatter-DkajGwwd.js → useDateFormatter-CPlava52.js} +2 -2
- package/dist/{useDeepCompareMemoize-Z_7R8wTt.js → useDeepCompareMemoize-NaaWoFlX.js} +1 -1
- package/dist/useEvent-BRH-aCqi.js +19 -0
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-BXhDDoCG.js} +1 -1
- package/dist/useLifecycle-SniivYmC.js +112 -0
- package/dist/{vega-component-DPd52jvr.js → vega-component-DIxaDQNs.js} +161 -160
- package/dist/{vega-embed-container-BgKnsDbB.js → vega-embed-container--LYZqguO.js} +2 -2
- package/dist/{vega-loader.browser-CpbZAXub.js → vega-loader.browser-B9Pz0EGP.js} +1 -1
- package/dist/{vennDiagram-4TSXK5OY-CypgoBVZ.js → vennDiagram-4TSXK5OY-C-hQ4iNJ.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-B6xjiQ_g.js → wardleyDiagram-VM6X3IG4-C2MQ_Umv.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-e0PefDVs.js → xychartDiagram-S5SC5T6Z-BtTTBn7Q.js} +1 -1
- package/package.json +16 -20
- package/src/__mocks__/document.tsx +63 -0
- package/src/__mocks__/executions.ts +197 -0
- package/src/__mocks__/notebook.ts +3 -7
- package/src/__mocks__/partial.ts +26 -0
- package/src/__mocks__/requests.ts +1 -4
- package/src/__tests__/CellStatus.test.tsx +25 -26
- package/src/__tests__/fixtures/pair-config.ts +1 -1
- 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/__tests__/state.test.tsx +50 -0
- package/src/components/app-config/ai-config.tsx +156 -150
- package/src/components/app-config/app-config-button.tsx +6 -5
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/app-config/common.tsx +7 -9
- package/src/components/app-config/data-form.tsx +112 -113
- package/src/components/app-config/mcp-config.tsx +30 -53
- package/src/components/app-config/user-config-form.css +91 -0
- package/src/components/app-config/user-config-form.tsx +266 -349
- package/src/components/chat/__tests__/capabilities-popover.test.tsx +0 -1
- package/src/components/chat/__tests__/chat-display.test.tsx +196 -0
- package/src/components/chat/__tests__/chat-markdown.test.tsx +43 -0
- package/src/components/chat/__tests__/chat-utils.test.ts +93 -1
- 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/__tests__/turn-timing.test.ts +84 -0
- package/src/components/chat/__tests__/use-assistant-turn.test.ts +95 -0
- package/src/components/chat/__tests__/user-message.test.tsx +27 -0
- package/src/components/chat/acp/__tests__/agent-panel-initialization.test.tsx +1 -1
- package/src/components/chat/acp/__tests__/agent-panel.test.tsx +22 -17
- 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/agent-panel.tsx +6 -3
- package/src/components/chat/acp/blocks.tsx +13 -12
- package/src/components/chat/acp/common.tsx +4 -5
- package/src/components/chat/acp/model-selector.tsx +1 -1
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/agent-activity.tsx +132 -0
- package/src/components/chat/capabilities-popover.tsx +2 -11
- package/src/components/chat/chat-components.tsx +9 -4
- package/src/components/chat/chat-display.tsx +131 -57
- package/src/components/chat/chat-history-popover.tsx +6 -1
- package/src/components/chat/chat-markdown.tsx +15 -0
- package/src/components/chat/chat-panel.tsx +216 -294
- package/src/components/chat/chat-typography.css +108 -0
- package/src/components/chat/chat-utils.ts +24 -35
- package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
- package/src/components/chat/notebook-access-selector.tsx +100 -0
- package/src/components/chat/tool-call/__tests__/tool-labels.test.ts +76 -0
- package/src/components/chat/tool-call/__tests__/tool-step.test.tsx +57 -0
- package/src/components/chat/tool-call/shared.ts +6 -0
- package/src/components/chat/tool-call/tool-call-view.tsx +22 -76
- package/src/components/chat/tool-call/tool-labels.ts +172 -0
- package/src/components/chat/tool-call/tool-result.tsx +1 -1
- package/src/components/chat/tool-call/tool-step.tsx +145 -0
- package/src/components/chat/turn-timing.ts +73 -0
- package/src/components/chat/use-assistant-turn.ts +65 -0
- package/src/components/chat/use-chat-generation.ts +20 -0
- package/src/components/chat/user-message.tsx +145 -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-formatting/types.ts +1 -2
- 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 +15 -20
- 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 -23
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/output-persistence.test.tsx +28 -9
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +21 -40
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +41 -14
- package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +6 -24
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +131 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/pair-with-agent-commands.ts +10 -7
- package/src/components/editor/actions/pair-with-agent-modal.tsx +29 -30
- package/src/components/editor/actions/pair-with-agent.tsx +16 -39
- package/src/components/editor/actions/useCellActionButton.tsx +47 -35
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +25 -29
- package/src/components/editor/actions/useRestartKernel.tsx +1 -1
- package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
- package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
- package/src/components/editor/ai/ai-completion-editor.tsx +2 -1
- package/src/components/editor/ai/completion-handlers.tsx +0 -37
- package/src/components/editor/ai/prompt-input.tsx +189 -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 +4 -2
- 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/CellStatus.tsx +28 -23
- 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 +18 -8
- package/src/components/editor/cell/StagedAICell.tsx +52 -137
- package/src/components/editor/cell/StopButton.tsx +2 -2
- package/src/components/editor/cell/__tests__/useRunCells.test.tsx +169 -0
- 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/cell-context-menu.tsx +4 -1
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +65 -169
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +16 -6
- 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 +49 -8
- 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/panel-header.tsx +13 -0
- 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/types.ts +1 -1
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +7 -9
- package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +265 -37
- package/src/components/editor/chrome/wrapper/__tests__/useAskAiAboutCell.test.tsx +58 -0
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +91 -74
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +4 -4
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
- package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -2
- package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +143 -72
- package/src/components/editor/chrome/wrapper/pending-ai-changes-badge.tsx +25 -0
- package/src/components/editor/chrome/wrapper/sidebar.tsx +8 -4
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/chrome/wrapper/useAskAiAboutCell.ts +36 -0
- 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 +26 -22
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/errors/send-error-report-button.tsx +3 -6
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +48 -15
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/header/__tests__/filename-form.test.tsx +1 -4
- package/src/components/editor/header/__tests__/status.test.tsx +5 -3
- package/src/components/editor/header/app-header.tsx +1 -1
- package/src/components/editor/header/filename-form.tsx +1 -1
- package/src/components/editor/header/status.tsx +44 -22
- 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 +21 -11
- 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 +74 -72
- 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 +126 -152
- package/src/components/editor/output/MarimoErrorOutput.tsx +2 -1
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- package/src/components/editor/output/Outputs.css +8 -0
- package/src/components/editor/output/VideoOutput.tsx +6 -0
- package/src/components/editor/output/__tests__/VideoOutput.test.tsx +131 -0
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +33 -20
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/__tests__/add-cell-buttons.test.tsx +18 -0
- package/src/components/editor/renderers/cell-array.tsx +32 -100
- package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +28 -22
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -4
- 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 +19 -37
- package/src/components/editor/stdin-blocking-alert.tsx +4 -2
- 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 +39 -28
- package/src/components/mcp/mcp-status-indicator.tsx +18 -14
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/edit-page.tsx +19 -17
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +89 -0
- package/src/components/scratchpad/scratchpad.tsx +47 -33
- package/src/components/scratchpad/state.ts +7 -0
- package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
- package/src/components/slides/__tests__/minimap.test.ts +38 -19
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
- package/src/components/slides/minimap.tsx +22 -14
- package/src/components/slides/reveal-component.tsx +73 -36
- package/src/components/slides/reveal-slides.css +5 -4
- package/src/components/slides/slide-cell-view.tsx +37 -34
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/slides/slide-scroll-hint.tsx +3 -1
- package/src/components/slides/slide.tsx +3 -4
- package/src/components/sort/SortableCellsProvider.tsx +8 -25
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +46 -42
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/__tests__/fullscreen.test.tsx +44 -2
- package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/components/ui/fullscreen.tsx +25 -1
- package/src/components/ui/range-slider.tsx +22 -9
- package/src/components/ui/toast.tsx +1 -1
- package/src/core/MarimoApp.tsx +3 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +89 -608
- package/src/core/ai/context/context.ts +2 -0
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
- package/src/core/ai/context/providers/__tests__/cell.test.ts +49 -0
- package/src/core/ai/context/providers/cell-output.ts +2 -2
- package/src/core/ai/context/providers/cell.ts +54 -0
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/staged-cells.ts +56 -323
- package/src/core/ai/state.ts +3 -0
- 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 -527
- package/src/core/cells/__tests__/actions.test.ts +623 -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 +148 -150
- package/src/core/cells/__tests__/cells.test.ts +225 -2723
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/document.test.ts +158 -0
- package/src/core/cells/__tests__/editor.test.ts +57 -0
- package/src/core/cells/__tests__/flush-document.test.ts +40 -0
- package/src/core/cells/__tests__/harness.ts +106 -0
- package/src/core/cells/__tests__/layout.test.ts +177 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +122 -0
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
- package/src/core/cells/__tests__/session.test.ts +445 -211
- package/src/core/cells/__tests__/utils.test.ts +135 -337
- package/src/core/cells/actions.ts +677 -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 +78 -146
- package/src/core/cells/cells.ts +116 -1457
- package/src/core/cells/columns.ts +38 -0
- package/src/core/cells/document.ts +167 -0
- package/src/core/cells/edit.ts +30 -0
- package/src/core/cells/editor.ts +82 -0
- package/src/core/cells/focus.ts +27 -6
- package/src/core/cells/layout.ts +221 -0
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/cells/pending-delete-service.ts +8 -14
- package/src/core/cells/scrollCellIntoView.ts +6 -0
- package/src/core/cells/session.ts +76 -53
- package/src/core/cells/types.ts +21 -51
- package/src/core/cells/utils.ts +85 -87
- package/src/core/codemirror/__tests__/format.test.ts +0 -34
- package/src/core/codemirror/__tests__/setup.test.ts +61 -29
- package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
- package/src/core/codemirror/ai/resources.ts +1 -1
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +2 -6
- package/src/core/codemirror/cells/extensions.ts +18 -30
- package/src/core/codemirror/cells/state.ts +2 -6
- package/src/core/codemirror/cm.ts +5 -1
- package/src/core/codemirror/config/types.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 -23
- package/src/core/codemirror/keymaps/vim.ts +4 -8
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
- package/src/core/codemirror/language/cell-code.ts +114 -0
- package/src/core/codemirror/language/extension.ts +52 -35
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +19 -13
- package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/language/utils.ts +9 -39
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
- package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
- package/src/core/codemirror/lsp/utils.ts +1 -1
- package/src/core/codemirror/misc/__tests__/paste.test.ts +3 -1
- package/src/core/codemirror/misc/paste.ts +1 -1
- package/src/core/codemirror/placeholder/__tests__/extensions.test.ts +75 -0
- package/src/core/codemirror/placeholder/extensions.ts +80 -19
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/readonly/extension.ts +2 -2
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/config/__tests__/app-config.test.ts +64 -0
- package/src/core/config/__tests__/config-schema.test.ts +56 -6
- package/src/core/config/config-schema.ts +17 -4
- package/src/core/config/config.ts +65 -20
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/documentation/doc-lookup.ts +1 -1
- package/src/core/edit-app.tsx +22 -28
- package/src/core/errors/__tests__/error-entries.test.ts +40 -1
- package/src/core/errors/error-entries.ts +6 -4
- package/src/core/executions/__tests__/atoms.test.ts +99 -0
- package/src/core/executions/__tests__/freshness.test.ts +482 -0
- package/src/core/executions/__tests__/hooks.test.tsx +106 -0
- package/src/core/executions/__tests__/select.test.ts +268 -0
- package/src/core/executions/atoms.ts +228 -0
- package/src/core/executions/freshness.ts +171 -0
- package/src/core/executions/hooks.ts +47 -0
- package/src/core/executions/index.ts +33 -0
- package/src/core/executions/select.ts +175 -0
- package/src/core/export/__tests__/hooks.test.ts +0 -5
- 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/hotkeys/hotkeys.ts +2 -1
- package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
- package/src/core/islands/__tests__/bridge.test.ts +85 -27
- package/src/core/islands/bootstrap.ts +49 -54
- package/src/core/islands/bridge.ts +84 -25
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/islands/components/__tests__/web-components.test.tsx +63 -0
- package/src/core/islands/components/output-wrapper.tsx +5 -5
- package/src/core/islands/components/web-components.tsx +12 -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 +13 -79
- package/src/core/kernel/state.ts +0 -15
- package/src/core/lifecycle/render-policy.ts +12 -26
- 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 +6 -8
- package/src/core/network/connection-notice.ts +1 -1
- package/src/core/network/connection.ts +1 -1
- package/src/core/network/requests-lazy.ts +5 -8
- package/src/core/network/requests-network.ts +5 -31
- package/src/core/network/requests-static.ts +1 -4
- package/src/core/network/requests-toasting.tsx +1 -4
- package/src/core/network/types.ts +6 -14
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/notebook/__tests__/operations.test.ts +51 -0
- package/src/core/notebook/attachments.ts +38 -0
- package/src/core/notebook/document/__tests__/codemirror.test.ts +759 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
- package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
- package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
- package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/notebook/document/__tests__/model.test.ts +247 -0
- package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/notebook/document/__tests__/state.test.ts +459 -0
- package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
- package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
- package/src/core/notebook/document/__tests__/test-host.ts +247 -0
- package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
- package/src/core/notebook/document/__tests__/user.ts +61 -0
- package/src/core/notebook/document/codemirror.ts +216 -0
- package/src/core/notebook/document/draft.ts +502 -0
- package/src/core/notebook/document/hooks.tsx +118 -0
- package/src/core/notebook/document/index.ts +24 -0
- package/src/core/notebook/document/model.ts +102 -0
- package/src/core/notebook/document/select.ts +41 -0
- package/src/core/notebook/document/state.ts +378 -0
- package/src/core/notebook/document/sync.ts +369 -0
- package/src/core/notebook/index.ts +19 -0
- package/src/core/notebook/operations.ts +30 -0
- package/src/core/notebook/replica/AGENTS.md +11 -0
- package/src/core/{host → notebook/replica}/__tests__/attachments.test.ts +9 -10
- package/src/core/{host → notebook/replica}/__tests__/document.test.ts +18 -16
- package/src/core/notebook/replica/__tests__/executions.test.ts +200 -0
- package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
- package/src/core/notebook/replica/__tests__/replica.test.ts +559 -0
- package/src/core/notebook/replica/__tests__/results.test.ts +193 -0
- package/src/core/notebook/replica/__tests__/runtime.test.ts +78 -0
- package/src/core/notebook/replica/backend.ts +19 -0
- package/src/core/notebook/replica/connection.ts +42 -0
- package/src/core/notebook/replica/index.ts +20 -0
- package/src/core/notebook/replica/replica.ts +336 -0
- package/src/core/{host → notebook/replica}/resources/attachments.ts +6 -3
- package/src/core/{host → notebook/replica}/resources/document.ts +3 -3
- package/src/core/notebook/replica/resources/executions.ts +157 -0
- package/src/core/notebook/replica/resources/results.ts +48 -0
- package/src/core/notebook/replica/resources/runtime.ts +14 -0
- package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
- package/src/core/packages/useSandboxController.ts +1 -1
- package/src/core/run-app.tsx +49 -51
- package/src/core/runtime/__tests__/adapter.test.ts +4 -4
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -74
- package/src/core/runtime/adapter.ts +5 -5
- package/src/core/runtime/config.ts +2 -2
- package/src/core/runtime/runtime.ts +33 -46
- package/src/core/runtime/types.ts +0 -2
- package/src/core/saving/__tests__/document.test.tsx +123 -0
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
- package/src/core/saving/document.ts +33 -0
- package/src/core/saving/filename.ts +1 -1
- package/src/core/saving/save-component.tsx +39 -60
- package/src/core/saving/state.ts +38 -39
- package/src/core/saving/useAutoSave.ts +17 -53
- package/src/core/session/__tests__/backend.test.ts +236 -0
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +186 -0
- package/src/core/{websocket → session}/__tests__/useNotebookSession.hook.test.tsx +247 -262
- package/src/core/session/active-notebook.ts +28 -0
- package/src/core/session/backend.ts +123 -0
- package/src/core/session/embedded.ts +7 -0
- package/src/core/{websocket → session}/types.ts +2 -2
- package/src/core/session/useNotebookReplica.ts +74 -0
- package/src/core/{websocket → session}/useNotebookSession.tsx +80 -67
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/{websocket → transports}/__tests__/connection-state.test.ts +1 -13
- package/src/core/transports/__tests__/server.test.ts +408 -0
- package/src/core/transports/__tests__/static.test.ts +306 -0
- package/src/core/transports/__tests__/wasm.test.ts +166 -0
- package/src/core/{websocket → transports}/connection-state.ts +9 -16
- package/src/core/transports/server.ts +152 -0
- package/src/core/transports/static.ts +166 -0
- package/src/core/transports/wasm.ts +97 -0
- package/src/core/vscode/__tests__/vscode-bindings.test.ts +125 -0
- package/src/core/vscode/vscode-bindings.ts +14 -2
- package/src/core/wasm/__tests__/bridge.test.ts +210 -64
- package/src/core/wasm/__tests__/worker.test.ts +188 -0
- package/src/core/wasm/bridge.ts +120 -73
- 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 +30 -18
- package/src/core/wasm/worker/worker.ts +118 -72
- package/src/css/app/Cell.css +7 -36
- package/src/css/app/codemirror.css +1 -1
- package/src/css/common.css +1 -1
- package/src/css/globals.css +72 -24
- 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/RenderHTML.tsx +3 -5
- package/src/plugins/core/__test__/RenderHTML-copy.test.tsx +60 -0
- package/src/plugins/core/registerReactComponent.tsx +5 -14
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +34 -13
- 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__/DataEditorPlugin.test.ts +93 -4
- 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 +17 -15
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/common/error-banner.tsx +5 -3
- package/src/plugins/impl/data-editor/__tests__/column-types.test.ts +42 -0
- package/src/plugins/impl/data-editor/__tests__/editor-state.test.ts +52 -1
- package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +120 -4
- package/src/plugins/impl/data-editor/__tests__/glide-utils.test.ts +116 -0
- package/src/plugins/impl/data-editor/column-types.ts +55 -0
- package/src/plugins/impl/data-editor/editor-state.ts +18 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +74 -12
- package/src/plugins/impl/data-editor/glide-utils.ts +39 -38
- package/src/plugins/impl/data-editor/types.ts +5 -0
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +44 -16
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/DownloadPlugin.tsx +7 -11
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/plugins/layout/__test__/DownloadPlugin.test.tsx +205 -0
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/cell-status.stories.tsx +29 -24
- package/src/stories/cell.stories.tsx +46 -46
- package/src/stories/data-table.stories.tsx +31 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +28 -42
- 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/theme/__tests__/islands-theme.test.tsx +276 -0
- package/src/theme/namespace.tsx +4 -3
- package/src/theme/useTheme.ts +71 -41
- 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} +127 -1
- package/src/utils/__tests__/download.test.tsx +183 -23
- 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 +115 -79
- package/src/utils/download.ts +67 -6
- package/src/utils/maps.ts +0 -3
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +4 -9
- package/src/utils/time.ts +10 -0
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/_baseMerge-BiGRwuqv.js +0 -165
- package/dist/any-language-editor-D4q-IFcM.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/assets/worker-HPY9fbhz.js +0 -114
- package/dist/feedback-button-g9eH5l7Q.js +0 -379
- package/dist/hasIn-o2Us0uVx.js +0 -132
- package/dist/html-to-image-B5H-xKRH.js +0 -3251
- package/dist/isArrayLikeObject-BZl-15ir.js +0 -450
- package/dist/isEmpty-BSZ1LaUo.js +0 -35
- package/dist/isSymbol-kQcfYbNX.js +0 -8
- package/dist/label-DoysmLMW.js +0 -281
- package/dist/pick-CJeoxYOS.js +0 -51
- package/dist/select-DemoKT4G.js +0 -1344
- package/dist/toDate-BvdkR0aH.js +0 -1185
- package/dist/toast-PkdZraM8.js +0 -1830
- package/dist/use-restore-focus-CKjfFjLM.js +0 -6369
- package/dist/useLifecycle-Dfq8UD-b.js +0 -169
- package/dist/useTheme-Bu5bBgrh.js +0 -904
- package/src/components/chat/reasoning-accordion.tsx +0 -61
- package/src/components/chat/tool-call/tool-error-card.tsx +0 -81
- package/src/components/chat/tool-call/tool-history-row.tsx +0 -174
- package/src/components/editor/ai/__tests__/staged-cell-submission.test.ts +0 -106
- package/src/components/editor/ai/add-cell-with-ai.tsx +0 -506
- package/src/components/editor/ai/staged-cell-submission.ts +0 -46
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +0 -64
- package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +0 -50
- package/src/components/editor/chrome/wrapper/footer-items/rtc-status.tsx +0 -65
- package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
- package/src/components/editor/navigation/state.ts +0 -65
- package/src/components/icons/loading-ellipsis.tsx +0 -46
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
- package/src/core/ai/tools/run-cells-tool.ts +0 -303
- package/src/core/attachments/state.ts +0 -18
- package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
- package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
- package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
- package/src/core/cells/document-changes.ts +0 -944
- package/src/core/codemirror/rtc/extension.ts +0 -453
- package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +0 -52
- package/src/core/codemirror/rtc/loro/awareness.ts +0 -531
- package/src/core/codemirror/rtc/loro/colors.ts +0 -38
- package/src/core/codemirror/rtc/loro/sync.ts +0 -168
- package/src/core/host/AGENTS.md +0 -11
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/fixtures.ts +0 -39
- package/src/core/host/__tests__/notebook-client.test.ts +0 -433
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/__tests__/stream.test.ts +0 -209
- package/src/core/host/connection.ts +0 -81
- package/src/core/host/events.ts +0 -61
- package/src/core/host/notebook-client.ts +0 -290
- package/src/core/host/protocol.ts +0 -1945
- package/src/core/host/resources/resource.ts +0 -47
- package/src/core/host/stream.ts +0 -211
- package/src/core/rtc/state.ts +0 -34
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/wasm/worker/message-buffer.ts +0 -33
- package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -170
- package/src/core/websocket/state.ts +0 -7
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/create.ts +0 -31
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -50
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useNotebookClient.ts +0 -88
- package/src/utils/__tests__/id-tree.test.ts +0 -2145
- package/src/utils/id-tree.tsx +0 -1134
- /package/src/{core/attachments/toast.ts → components/editor/agent-toast.ts} +0 -0
- /package/src/core/{websocket → session}/connection-utils.ts +0 -0
package/src/core/cells/cells.ts
CHANGED
|
@@ -1,51 +1,43 @@
|
|
|
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 {
|
|
8
|
+
import type { EditableDocument, Placement } from "@/core/notebook/document";
|
|
10
9
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
cellExecutionInputsAtom,
|
|
11
|
+
cellExecutionView,
|
|
12
|
+
cellFreshnessAtom,
|
|
13
|
+
withdrawCells,
|
|
14
|
+
} from "@/core/executions";
|
|
15
|
+
import type { CellColumnId } from "./layout";
|
|
15
16
|
import { invariant } from "@/utils/invariant";
|
|
16
17
|
import { Logger } from "@/utils/Logger";
|
|
17
|
-
import { clamp } from "@/utils/math";
|
|
18
18
|
import { Objects } from "@/utils/objects";
|
|
19
19
|
import { extractAllTracebackInfo, type TracebackInfo } from "@/utils/traceback";
|
|
20
20
|
import { createReducerAndAtoms } from "../../utils/createReducer";
|
|
21
21
|
import { foldAllBulk, unfoldAllBulk } from "../codemirror/editing/commands";
|
|
22
22
|
import { editorMountScheduler } from "../codemirror/editor-mount-scheduler";
|
|
23
|
-
import {
|
|
24
|
-
splitEditor,
|
|
25
|
-
updateEditorCodeFromPython,
|
|
26
|
-
} from "../codemirror/language/utils";
|
|
27
23
|
import type { SerializedEditorState } from "../codemirror/types";
|
|
28
|
-
import {
|
|
24
|
+
import { mergeOutlines } from "../dom/outline";
|
|
29
25
|
import type { CellMessage } from "../kernel/messages";
|
|
30
26
|
import { isErrorMime } from "../mime";
|
|
31
27
|
import type { CellConfig } from "../network/types";
|
|
32
|
-
import { canUseRtc, isRtcEnabled } from "../rtc/state";
|
|
33
28
|
import { createDeepEqualAtom, store } from "../state/jotai";
|
|
34
29
|
import { isWasm } from "../wasm/utils";
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
30
|
+
import { transitionCell } from "./cell";
|
|
31
|
+
import { applyDocument } from "./document";
|
|
32
|
+
import { isCodeHidden, shownHiddenCodeAtom } from "./editor";
|
|
33
|
+
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
38
34
|
import { type CellLog, getCellLogsForMessage } from "./logs";
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
scrollToBottom,
|
|
42
|
-
scrollToTop,
|
|
43
|
-
} from "./scrollCellIntoView";
|
|
35
|
+
import type { Outline } from "./outline";
|
|
36
|
+
import { focusAndScrollCellIntoView } from "./scrollCellIntoView";
|
|
44
37
|
import {
|
|
45
38
|
type CellData,
|
|
46
39
|
type CellRuntimeState,
|
|
47
40
|
createCell,
|
|
48
|
-
createCellConfig,
|
|
49
41
|
createCellRuntimeState,
|
|
50
42
|
} from "./types";
|
|
51
43
|
import {
|
|
@@ -53,22 +45,24 @@ import {
|
|
|
53
45
|
disabledCellIds,
|
|
54
46
|
enabledCellIds,
|
|
55
47
|
getUndoLabel,
|
|
56
|
-
notebookIsRunning,
|
|
57
48
|
notebookNeedsRun,
|
|
58
|
-
notebookQueueOrRunningCount,
|
|
59
49
|
} from "./utils";
|
|
60
50
|
|
|
51
|
+
/** A deleted cell as it was, with where it went in the document. */
|
|
52
|
+
export interface DeletedCell {
|
|
53
|
+
cell: Protocol.CellInput;
|
|
54
|
+
placement: Placement;
|
|
55
|
+
/** The editor's state at deletion, so undo brings its history back. */
|
|
56
|
+
serializedEditorState: SerializedEditorState | null;
|
|
57
|
+
}
|
|
58
|
+
|
|
61
59
|
/**
|
|
62
|
-
* History entry for undoing
|
|
60
|
+
* History entry for undoing one deletion, of one or more cells.
|
|
63
61
|
*/
|
|
64
62
|
export interface UndoDeleteEntry {
|
|
65
63
|
type: "delete";
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
column: CellColumnId;
|
|
69
|
-
index: CellIndex;
|
|
70
|
-
isSetupCell: boolean;
|
|
71
|
-
config: CellConfig;
|
|
64
|
+
/** In document order. Each cell is placed after the one before it. */
|
|
65
|
+
cells: DeletedCell[];
|
|
72
66
|
}
|
|
73
67
|
|
|
74
68
|
/**
|
|
@@ -77,7 +71,7 @@ export interface UndoDeleteEntry {
|
|
|
77
71
|
export interface UndoMoveEntry {
|
|
78
72
|
type: "move";
|
|
79
73
|
cellIds: CellId[];
|
|
80
|
-
placements: Array<{ columnId: CellColumnId; index:
|
|
74
|
+
placements: Array<{ columnId: CellColumnId; index: number }>;
|
|
81
75
|
}
|
|
82
76
|
|
|
83
77
|
export type HistoryEntry = UndoDeleteEntry | UndoMoveEntry;
|
|
@@ -89,7 +83,8 @@ export interface NotebookState {
|
|
|
89
83
|
/**
|
|
90
84
|
* Order of cells on the page.
|
|
91
85
|
*/
|
|
92
|
-
|
|
86
|
+
/** The cells in document order. */
|
|
87
|
+
cellIds: CellId[];
|
|
93
88
|
/**
|
|
94
89
|
* Map of cells to their view state
|
|
95
90
|
*/
|
|
@@ -116,12 +111,6 @@ export interface NotebookState {
|
|
|
116
111
|
* Logs of all cell messages
|
|
117
112
|
*/
|
|
118
113
|
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
114
|
}
|
|
126
115
|
|
|
127
116
|
function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
@@ -153,781 +142,40 @@ function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
|
153
142
|
*/
|
|
154
143
|
export function initialNotebookState(): NotebookState {
|
|
155
144
|
return withScratchCell({
|
|
156
|
-
cellIds:
|
|
145
|
+
cellIds: [],
|
|
157
146
|
cellData: {},
|
|
158
147
|
cellRuntime: {},
|
|
159
148
|
cellHandles: {},
|
|
160
149
|
history: [],
|
|
161
150
|
scrollKey: null,
|
|
162
151
|
cellLogs: [],
|
|
163
|
-
untouchedNewCells: new Set<CellId>(),
|
|
164
152
|
});
|
|
165
153
|
}
|
|
166
154
|
|
|
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
155
|
/**
|
|
202
156
|
* Actions and reducer for the notebook state.
|
|
203
157
|
*/
|
|
204
158
|
const {
|
|
205
159
|
reducer,
|
|
206
|
-
addMiddleware,
|
|
207
160
|
createActions,
|
|
208
161
|
useActions,
|
|
209
|
-
valueAtom: notebookAtom,
|
|
210
|
-
} = createReducerAndAtoms(initialNotebookState, {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
cellId,
|
|
214
|
-
before,
|
|
215
|
-
code,
|
|
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
|
-
},
|
|
821
|
-
updateCellCode: (
|
|
822
|
-
state,
|
|
823
|
-
action: {
|
|
824
|
-
cellId: CellId;
|
|
825
|
-
code: string;
|
|
826
|
-
/**
|
|
827
|
-
* Whether or not the update is a formatting change,
|
|
828
|
-
* if so, the 'edited' state will be handled differently.
|
|
829
|
-
*/
|
|
830
|
-
formattingChange: boolean;
|
|
831
|
-
},
|
|
832
|
-
) => {
|
|
833
|
-
const { cellId, code, formattingChange } = action;
|
|
834
|
-
if (!state.cellData[cellId]) {
|
|
835
|
-
return state;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
return updateCellData({
|
|
839
|
-
state,
|
|
840
|
-
cellId,
|
|
841
|
-
cellReducer: (cell) => {
|
|
842
|
-
// Formatting-only change means we can re-use the last code run
|
|
843
|
-
// if it was not previously edited. And we don't change the edited state.
|
|
844
|
-
return formattingChange
|
|
845
|
-
? {
|
|
846
|
-
...cell,
|
|
847
|
-
code: code,
|
|
848
|
-
lastCodeRun: cell.edited ? cell.lastCodeRun : code,
|
|
849
|
-
}
|
|
850
|
-
: {
|
|
851
|
-
...cell,
|
|
852
|
-
code: code,
|
|
853
|
-
edited: code.trim() !== cell.lastCodeRun,
|
|
854
|
-
};
|
|
855
|
-
},
|
|
856
|
-
});
|
|
857
|
-
},
|
|
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
|
-
prepareForRun: (state, action: { cellId: CellId }) => {
|
|
888
|
-
const newState = updateCellRuntimeState({
|
|
162
|
+
valueAtom: notebookAtom,
|
|
163
|
+
} = createReducerAndAtoms(initialNotebookState, {
|
|
164
|
+
prepareForRun: (state, action: { cellId: CellId }) =>
|
|
165
|
+
updateCellRuntimeState({
|
|
889
166
|
state,
|
|
890
167
|
cellId: action.cellId,
|
|
891
|
-
cellReducer: (cell) => {
|
|
892
|
-
|
|
893
|
-
},
|
|
894
|
-
});
|
|
895
|
-
return updateCellData({
|
|
896
|
-
state: newState,
|
|
897
|
-
cellId: action.cellId,
|
|
898
|
-
cellReducer: (cell) => {
|
|
899
|
-
return {
|
|
900
|
-
...cell,
|
|
901
|
-
edited: false,
|
|
902
|
-
lastCodeRun: cell.code.trim(),
|
|
903
|
-
};
|
|
904
|
-
},
|
|
905
|
-
});
|
|
906
|
-
},
|
|
168
|
+
cellReducer: (cell) => ({ ...cell, debuggerActive: false }),
|
|
169
|
+
}),
|
|
907
170
|
handleCellMessage: (state, message: CellMessage) => {
|
|
908
171
|
const cellId = message.cell_id;
|
|
909
|
-
|
|
172
|
+
const nextState = updateCellRuntimeState({
|
|
910
173
|
state,
|
|
911
174
|
cellId,
|
|
912
175
|
cellReducer: (cell) => {
|
|
913
176
|
return transitionCell(cell, message);
|
|
914
177
|
},
|
|
915
178
|
});
|
|
916
|
-
// When a cell is queued for execution, snapshot the current code
|
|
917
|
-
// as lastCodeRun. This clears staleness for cells executed by the
|
|
918
|
-
// kernel (e.g. via code_mode). If the user edits during execution,
|
|
919
|
-
// code !== lastCodeRun keeps the cell stale.
|
|
920
|
-
if (message.status === "queued") {
|
|
921
|
-
nextState = updateCellData({
|
|
922
|
-
state: nextState,
|
|
923
|
-
cellId,
|
|
924
|
-
cellReducer: (cell) => ({
|
|
925
|
-
...cell,
|
|
926
|
-
lastCodeRun: cell.code.trim(),
|
|
927
|
-
edited: false,
|
|
928
|
-
}),
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
179
|
return {
|
|
932
180
|
...nextState,
|
|
933
181
|
cellLogs: [...nextState.cellLogs, ...getCellLogsForMessage(message)],
|
|
@@ -939,158 +187,14 @@ const {
|
|
|
939
187
|
cellLogs: [...state.cellLogs, ...action.logs],
|
|
940
188
|
};
|
|
941
189
|
},
|
|
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();
|
|
962
|
-
}
|
|
963
|
-
}
|
|
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;
|
|
190
|
+
/** Follow the host document's cells and order. */
|
|
191
|
+
reconcileDocument: (state, document: EditableDocument) => {
|
|
192
|
+
const nextState = applyDocument(state, document);
|
|
193
|
+
for (const cellId of state.cellIds) {
|
|
194
|
+
if (!(cellId in nextState.cellData)) {
|
|
195
|
+
releaseCellAtoms(cellId);
|
|
1076
196
|
}
|
|
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
197
|
}
|
|
1093
|
-
|
|
1094
198
|
return nextState;
|
|
1095
199
|
},
|
|
1096
200
|
setStdinResponse: (
|
|
@@ -1114,6 +218,7 @@ const {
|
|
|
1114
218
|
mimetype: stdinOutput.mimetype,
|
|
1115
219
|
data: stdinOutput.data,
|
|
1116
220
|
timestamp: stdinOutput.timestamp,
|
|
221
|
+
id: stdinOutput.id,
|
|
1117
222
|
// An empty response resolves the prompt without retaining the secret.
|
|
1118
223
|
response: stdinOutput.mimetype === "text/password" ? "" : response,
|
|
1119
224
|
};
|
|
@@ -1126,155 +231,22 @@ const {
|
|
|
1126
231
|
},
|
|
1127
232
|
});
|
|
1128
233
|
},
|
|
1129
|
-
setCells: (state, cells: CellData[]) => {
|
|
1130
|
-
const cellData = Object.fromEntries(cells.map((cell) => [cell.id, cell]));
|
|
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
234
|
/**
|
|
1161
|
-
*
|
|
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
|
|
235
|
+
* Start each cell's runtime over for a new kernel. WASM keeps the outputs
|
|
236
|
+
* its mount-time snapshot gave it.
|
|
1168
237
|
*/
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
const column = state.cellIds.findWithId(cellId);
|
|
1181
|
-
const index = column.indexOfOrThrow(cellId);
|
|
1182
|
-
const nextCellIndex = before ? index - 1 : index + 1;
|
|
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,
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
return state;
|
|
1264
|
-
},
|
|
1265
|
-
markUntouched: (state, action: { cellId: CellId }) => {
|
|
1266
|
-
const { cellId } = action;
|
|
1267
|
-
|
|
1268
|
-
if (!state.untouchedNewCells.has(cellId)) {
|
|
1269
|
-
const nextUntouchedNewCells = new Set(state.untouchedNewCells);
|
|
1270
|
-
nextUntouchedNewCells.add(cellId);
|
|
1271
|
-
return {
|
|
1272
|
-
...state,
|
|
1273
|
-
untouchedNewCells: nextUntouchedNewCells,
|
|
1274
|
-
};
|
|
238
|
+
resetCellRuntimes: (state) => {
|
|
239
|
+
const preserveSnapshot = isWasm();
|
|
240
|
+
const cellRuntime = { ...state.cellRuntime };
|
|
241
|
+
for (const cellId of [...state.cellIds, SCRATCH_CELL_ID]) {
|
|
242
|
+
const previous = state.cellRuntime[cellId];
|
|
243
|
+
const hasSnapshot =
|
|
244
|
+
preserveSnapshot &&
|
|
245
|
+
previous !== undefined &&
|
|
246
|
+
(previous.output != null || previous.consoleOutputs.length > 0);
|
|
247
|
+
cellRuntime[cellId] = hasSnapshot ? previous : createCellRuntimeState();
|
|
1275
248
|
}
|
|
1276
|
-
|
|
1277
|
-
return state;
|
|
249
|
+
return { ...state, cellRuntime };
|
|
1278
250
|
},
|
|
1279
251
|
scrollToTarget: (state) => {
|
|
1280
252
|
// Scroll to the specified cell and clear the scroll key.
|
|
@@ -1283,16 +255,15 @@ const {
|
|
|
1283
255
|
return state;
|
|
1284
256
|
}
|
|
1285
257
|
|
|
1286
|
-
const
|
|
1287
|
-
const index = column.indexOfOrThrow(scrollKey);
|
|
1288
|
-
|
|
1289
|
-
const cellId =
|
|
1290
|
-
index === column.length - 1 ? column.last() : column.atOrThrow(index);
|
|
1291
|
-
|
|
258
|
+
const cellId = scrollKey;
|
|
1292
259
|
focusAndScrollCellIntoView({
|
|
1293
260
|
cellId: cellId,
|
|
1294
261
|
cell: state.cellHandles[cellId],
|
|
1295
|
-
isCodeHidden:
|
|
262
|
+
isCodeHidden: isCodeHidden(
|
|
263
|
+
state.cellData[cellId]?.config.hide_code,
|
|
264
|
+
store.get(shownHiddenCodeAtom),
|
|
265
|
+
cellId,
|
|
266
|
+
),
|
|
1296
267
|
codeFocus: undefined,
|
|
1297
268
|
variableName: undefined,
|
|
1298
269
|
});
|
|
@@ -1322,201 +293,6 @@ const {
|
|
|
1322
293
|
cellLogs: [],
|
|
1323
294
|
};
|
|
1324
295
|
},
|
|
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
296
|
clearCellOutput: (state, action: { cellId: CellId }) => {
|
|
1521
297
|
const { cellId } = action;
|
|
1522
298
|
return updateCellRuntimeState({
|
|
@@ -1545,7 +321,7 @@ const {
|
|
|
1545
321
|
},
|
|
1546
322
|
clearAllCellOutputs: (state) => {
|
|
1547
323
|
const newCellRuntime = { ...state.cellRuntime };
|
|
1548
|
-
for (const cellId of state.cellIds
|
|
324
|
+
for (const cellId of state.cellIds) {
|
|
1549
325
|
newCellRuntime[cellId] = {
|
|
1550
326
|
...newCellRuntime[cellId],
|
|
1551
327
|
output: null,
|
|
@@ -1557,58 +333,8 @@ const {
|
|
|
1557
333
|
cellRuntime: newCellRuntime,
|
|
1558
334
|
};
|
|
1559
335
|
},
|
|
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
336
|
});
|
|
1599
337
|
|
|
1600
|
-
// We apply the middleware here (rather than inline in createReducerAndAtoms)
|
|
1601
|
-
// so that the document transaction middleware can import CellActions and
|
|
1602
|
-
// strictly type the dispatched actions without creating a circular dependency.
|
|
1603
|
-
addMiddleware(documentTransactionMiddleware);
|
|
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
|
-
}
|
|
1611
|
-
|
|
1612
338
|
// Helper function to update a cell in the array
|
|
1613
339
|
function updateCellRuntimeState({
|
|
1614
340
|
state,
|
|
@@ -1633,66 +359,12 @@ function updateCellRuntimeState({
|
|
|
1633
359
|
};
|
|
1634
360
|
}
|
|
1635
361
|
|
|
1636
|
-
|
|
1637
|
-
state,
|
|
1638
|
-
cellId,
|
|
1639
|
-
cellReducer,
|
|
1640
|
-
}: {
|
|
1641
|
-
state: NotebookState;
|
|
1642
|
-
cellId: CellId;
|
|
1643
|
-
cellReducer: ReducerWithoutAction<CellData>;
|
|
1644
|
-
}) {
|
|
1645
|
-
if (!(cellId in state.cellData)) {
|
|
1646
|
-
Logger.warn(`Cell ${cellId} not found in state`);
|
|
1647
|
-
return state;
|
|
1648
|
-
}
|
|
1649
|
-
|
|
1650
|
-
return {
|
|
1651
|
-
...state,
|
|
1652
|
-
cellData: {
|
|
1653
|
-
...state.cellData,
|
|
1654
|
-
[cellId]: cellReducer(state.cellData[cellId]),
|
|
1655
|
-
},
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
|
|
362
|
+
/** Each cell's config in order. The document's `column` configs are canonical. */
|
|
1659
363
|
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
|
-
});
|
|
364
|
+
return state.cellIds.map((cellId) => ({
|
|
365
|
+
...state.cellData[cellId].config,
|
|
366
|
+
column: state.cellData[cellId].config.column ?? null,
|
|
367
|
+
}));
|
|
1696
368
|
}
|
|
1697
369
|
|
|
1698
370
|
export {
|
|
@@ -1712,9 +384,7 @@ export const addLogs = imperativeActions.addLogs;
|
|
|
1712
384
|
|
|
1713
385
|
export const cellIdsAtom = atom((get) => get(notebookAtom).cellIds);
|
|
1714
386
|
|
|
1715
|
-
export const hasOnlyOneCellAtom = atom((get) =>
|
|
1716
|
-
get(cellIdsAtom).hasOnlyOneId(),
|
|
1717
|
-
);
|
|
387
|
+
export const hasOnlyOneCellAtom = atom((get) => get(cellIdsAtom).length === 1);
|
|
1718
388
|
|
|
1719
389
|
export const hasDisabledCellsAtom = atom(
|
|
1720
390
|
(get) => disabledCellIds(get(notebookAtom)).length > 0,
|
|
@@ -1728,11 +398,17 @@ export const canUndoDeletesAtom = atom((get) =>
|
|
|
1728
398
|
|
|
1729
399
|
export const undoLabelAtom = atom((get) => getUndoLabel(get(notebookAtom)));
|
|
1730
400
|
|
|
1731
|
-
export const needsRunAtom = atom((get) =>
|
|
401
|
+
export const needsRunAtom = atom((get) =>
|
|
402
|
+
notebookNeedsRun(
|
|
403
|
+
get(notebookAtom),
|
|
404
|
+
get(cellExecutionInputsAtom),
|
|
405
|
+
get(cellFreshnessAtom),
|
|
406
|
+
),
|
|
407
|
+
);
|
|
1732
408
|
|
|
1733
409
|
export const cellErrorsAtom = atom((get) => {
|
|
1734
410
|
const { cellIds, cellRuntime, cellData } = get(notebookAtom);
|
|
1735
|
-
const errors = cellIds
|
|
411
|
+
const errors = cellIds
|
|
1736
412
|
.map((cellId) => {
|
|
1737
413
|
const cell = cellRuntime[cellId];
|
|
1738
414
|
const { name } = cellData[cellId];
|
|
@@ -1760,11 +436,28 @@ export const cellErrorsAtom = atom((get) => {
|
|
|
1760
436
|
return errors;
|
|
1761
437
|
});
|
|
1762
438
|
|
|
439
|
+
/**
|
|
440
|
+
* The outline of each cell whose output has a heading. Compared by value, so
|
|
441
|
+
* readers are left alone by the runtime messages that change no heading.
|
|
442
|
+
*/
|
|
443
|
+
export const cellOutlinesAtom = createDeepEqualAtom(
|
|
444
|
+
atom((get) => {
|
|
445
|
+
const outlines: Partial<Record<CellId, Outline>> = {};
|
|
446
|
+
for (const [id, runtime] of Objects.entries(
|
|
447
|
+
get(notebookAtom).cellRuntime,
|
|
448
|
+
)) {
|
|
449
|
+
if (runtime.outline !== null && runtime.outline.items.length > 0) {
|
|
450
|
+
outlines[id] = runtime.outline;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return outlines;
|
|
454
|
+
}),
|
|
455
|
+
);
|
|
456
|
+
|
|
1763
457
|
export const notebookOutline = atom((get) => {
|
|
1764
|
-
const
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
);
|
|
458
|
+
const cellIds = get(cellIdsAtom);
|
|
459
|
+
const cellRuntime = get(cellsRuntimeAtom);
|
|
460
|
+
const outlines = cellIds.map((cellId) => cellRuntime[cellId].outline);
|
|
1768
461
|
return mergeOutlines(outlines);
|
|
1769
462
|
});
|
|
1770
463
|
|
|
@@ -1774,7 +467,7 @@ export const cellIdToNamesMap = createDeepEqualAtom(
|
|
|
1774
467
|
atom((get) => {
|
|
1775
468
|
const { cellIds, cellData } = get(notebookAtom);
|
|
1776
469
|
const names: Record<CellId, string | undefined> = Objects.fromEntries(
|
|
1777
|
-
cellIds.
|
|
470
|
+
cellIds.map((cellId) => [cellId, cellData[cellId]?.name]),
|
|
1778
471
|
);
|
|
1779
472
|
return names;
|
|
1780
473
|
}),
|
|
@@ -1831,41 +524,19 @@ export const getCells = () => store.get(notebookAtom).cellIds;
|
|
|
1831
524
|
*/
|
|
1832
525
|
export const getCellNames = () => {
|
|
1833
526
|
const { cellIds, cellData } = store.get(notebookAtom);
|
|
1834
|
-
return cellIds.
|
|
527
|
+
return cellIds.map((id) => cellData[id]?.name).filter(Boolean);
|
|
1835
528
|
};
|
|
1836
529
|
|
|
1837
530
|
const cellDataAtoms = splitAtom(
|
|
1838
531
|
selectAtom(notebookAtom, (cells) =>
|
|
1839
|
-
cells.cellIds.
|
|
532
|
+
cells.cellIds.map((id) => cells.cellData[id]),
|
|
1840
533
|
),
|
|
1841
534
|
);
|
|
1842
535
|
export const useCellDataAtoms = () => useAtom(cellDataAtoms);
|
|
1843
536
|
|
|
1844
537
|
export const cellsRuntimeAtom = atom((get) => get(notebookAtom).cellRuntime);
|
|
1845
538
|
|
|
1846
|
-
export const
|
|
1847
|
-
notebookIsRunning(get(notebookAtom)),
|
|
1848
|
-
);
|
|
1849
|
-
export const onlyScratchpadIsRunningAtom = atom((get) => {
|
|
1850
|
-
const { cellRuntime } = get(notebookAtom);
|
|
1851
|
-
return Object.entries(cellRuntime).every(
|
|
1852
|
-
([id, rt]) => rt.status !== "running" || id === SCRATCH_CELL_ID,
|
|
1853
|
-
);
|
|
1854
|
-
});
|
|
1855
|
-
export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
1856
|
-
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
1857
|
-
);
|
|
1858
|
-
|
|
1859
|
-
export const numColumnsAtom = atom(
|
|
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
|
-
|
|
539
|
+
export const hasCellsAtom = atom((get) => get(notebookAtom).cellIds.length > 0);
|
|
1869
540
|
export const cellDataAtom = atomFamily((cellId: CellId) =>
|
|
1870
541
|
atom((get) => get(notebookAtom).cellData[cellId]),
|
|
1871
542
|
);
|
|
@@ -1889,6 +560,7 @@ export function releaseCellAtoms(cellId: CellId) {
|
|
|
1889
560
|
cellDataAtom.remove(cellId);
|
|
1890
561
|
cellRuntimeAtom.remove(cellId);
|
|
1891
562
|
cellHandleAtom.remove(cellId);
|
|
563
|
+
withdrawCells(store, [cellId]);
|
|
1892
564
|
}
|
|
1893
565
|
|
|
1894
566
|
/** Subscribes to reactive updates of the cell's data. */
|
|
@@ -1906,7 +578,7 @@ export const useCellHandle = (cellId: CellId) =>
|
|
|
1906
578
|
*/
|
|
1907
579
|
export const getAllEditorViews = () => {
|
|
1908
580
|
const { cellIds, cellHandles } = store.get(notebookAtom);
|
|
1909
|
-
return cellIds
|
|
581
|
+
return cellIds
|
|
1910
582
|
.map((cellId) => cellHandles[cellId]?.current?.editorViewOrNull)
|
|
1911
583
|
.filter(Boolean);
|
|
1912
584
|
};
|
|
@@ -1930,16 +602,10 @@ export function flattenTopLevelNotebookCells(
|
|
|
1930
602
|
state: NotebookState,
|
|
1931
603
|
): (CellData & CellRuntimeState)[] {
|
|
1932
604
|
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));
|
|
605
|
+
return cellIds.map((cellId) => ({
|
|
606
|
+
...cellData[cellId],
|
|
607
|
+
...cellRuntime[cellId],
|
|
608
|
+
}));
|
|
1943
609
|
}
|
|
1944
610
|
|
|
1945
611
|
export function createTracebackInfoAtom(
|
|
@@ -1955,7 +621,8 @@ export function createTracebackInfoAtom(
|
|
|
1955
621
|
return undefined;
|
|
1956
622
|
}
|
|
1957
623
|
|
|
1958
|
-
|
|
624
|
+
const { status } = cellExecutionView(get(cellExecutionInputsAtom), cellId);
|
|
625
|
+
if (status === "queued" || status === "running") {
|
|
1959
626
|
return undefined;
|
|
1960
627
|
}
|
|
1961
628
|
|
|
@@ -2001,20 +668,13 @@ export function createTracebackInfoAtom(
|
|
|
2001
668
|
});
|
|
2002
669
|
}
|
|
2003
670
|
|
|
2004
|
-
/**
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
*/
|
|
2008
|
-
export function useCellActions(
|
|
2009
|
-
options: { skipMiddleware?: boolean } = {},
|
|
2010
|
-
): CellActions {
|
|
2011
|
-
return useActions(options);
|
|
671
|
+
/** The reducer's actions. Components use `useCellActions` from `./actions`. */
|
|
672
|
+
export function useReducerActions(): ReducerCellActions {
|
|
673
|
+
return useActions();
|
|
2012
674
|
}
|
|
2013
675
|
|
|
2014
|
-
/**
|
|
2015
|
-
|
|
2016
|
-
*/
|
|
2017
|
-
export type CellActions = ReturnType<typeof createActions>;
|
|
676
|
+
/** The actions the reducer still handles. */
|
|
677
|
+
export type ReducerCellActions = ReturnType<typeof createActions>;
|
|
2018
678
|
|
|
2019
679
|
/**
|
|
2020
680
|
* This is exported for testing purposes only.
|
|
@@ -2023,7 +683,6 @@ export const exportedForTesting = {
|
|
|
2023
683
|
reducer,
|
|
2024
684
|
createActions,
|
|
2025
685
|
initialNotebookState,
|
|
2026
|
-
isCellCodeHidden,
|
|
2027
686
|
// Export atom families for testing cleanup
|
|
2028
687
|
cellDataAtom,
|
|
2029
688
|
cellRuntimeAtom,
|