@marimo-team/islands 0.25.3-dev21 → 0.25.3-dev210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ConnectedDataExplorerComponent-DfG3PRaJ.js → ConnectedDataExplorerComponent-D6RHJV8D.js} +120 -116
- package/dist/{ErrorBoundary-ttSr7_91.js → ErrorBoundary-VruaQLnK.js} +16 -16
- package/dist/{abnfDiagram-VCTEODGH-B3w-XWX8.js → abnfDiagram-VCTEODGH-0q7Lbmii.js} +2 -2
- package/dist/any-language-editor-jGaR0EAo.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-C18U9A6k.js → architectureDiagram-5GKGNRK7-1PydKPmE.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
- package/dist/assets/__vite-browser-external-CBRgnYY0.js +1 -0
- package/dist/assets/worker-DiPNP__U.js +113 -0
- package/dist/{button-CvjkwdSk.js → button-B6RjDKJx.js} +227 -217
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-CkVzWJEX.js} +2 -2
- package/dist/{chat-ui-w8SVynkn.js → chat-ui-B5pH_aXk.js} +1277 -1275
- package/dist/{check-BMKBBrdc.js → check-Z_vtI3OL.js} +1 -1
- package/dist/{chunk-IMKFNOWR-CrS5bzqW.js → chunk-IMKFNOWR-DEzZZ1Zc.js} +1 -1
- package/dist/{chunk-SHT3W25Y-StpvPvUG.js → chunk-SHT3W25Y-CuHj-hnn.js} +1 -1
- package/dist/{chunk-SVP7TREG-CBXjbYZC.js → chunk-SVP7TREG-BPiZK2bA.js} +1 -1
- package/dist/{chunk-TICWLB2K-Dp6bIb-q.js → chunk-TICWLB2K-DF6XcIjM.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-BFYuxV5g.js → classDiagram-ZZMXUADV-CMdR-cP4.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-D_tjXVMl.js → classDiagram-v2-VYDZK3BY-DRvc3_7Y.js} +2 -2
- package/dist/code-visibility-BdFhHfIC.js +134 -0
- package/dist/{common-CeebhhhO.js → common-Ce1SgsX1.js} +9837 -9658
- package/dist/config-DbjzjwxX.js +636 -0
- package/dist/{copy-icon-BgUO8jsi.js → copy-icon-CG57cxwb.js} +3 -3
- package/dist/createReducer-DePYJ0F3.js +63 -0
- package/dist/{cynefinDiagram-5FMLGOSQ-DSgYrHB2.js → cynefinDiagram-5FMLGOSQ-BkBjEY9l.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-GYlruCBf.js → dagre-GXQ25YYZ-D-HEaW4I.js} +1 -1
- package/dist/{data-grid-overlay-editor-vxQ4E6k1.js → data-grid-overlay-editor-Bps1p6jQ.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-DRu5LX5_.js → diagram-S7CK7UJ4-Bn-oF-rB.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-DD7uiejP.js → diagram-UQ7AKVKN-BpzzXWBj.js} +1 -1
- package/dist/{diagram-VX7I27RA-ByH9KAJJ.js → diagram-VX7I27RA-COOtvfBP.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BsQHPRke.js → diagram-Z3DM3KII-K5cXvbrl.js} +1 -1
- package/dist/{dialog-Cc479ZEH.js → dialog-DsZ49mmU.js} +26 -26
- package/dist/{dist-Bvs24R_E.js → dist-11T5wq3_.js} +31 -30
- package/dist/{dist-F8Ep36rk.js → dist-17ugwGZc.js} +59 -58
- package/dist/{dist-BMQf5zIS.js → dist-7cRjf--y.js} +123 -122
- package/dist/{dist-diIx5qJW.js → dist-B8pkfkzc.js} +31 -30
- package/dist/{dist-CN_BeG2I.js → dist-B9UoM_wq.js} +58 -57
- package/dist/{dist-CLdpGQVr.js → dist-BGuMTs1i.js} +118 -117
- package/dist/{dist-BK4Oj99o.js → dist-BHW11fni.js} +18 -17
- package/dist/dist-BLY4m1Wi.js +850 -0
- package/dist/{dist-PXYI_yuP.js → dist-BNlcVoxs.js} +24 -23
- package/dist/{dist-D6d86eNJ.js → dist-BQYe5Bju.js} +47 -46
- package/dist/{dist-CkTTIdBe.js → dist-BX1mn8na.js} +337 -337
- package/dist/{dist-DiDibOYr.js → dist-Bh0PTKUW.js} +151 -150
- package/dist/{dist-CSJ0MDRw.js → dist-CKaXK92p.js} +56 -55
- package/dist/{dist-C8fAKSH1.js → dist-CLhwfhpJ.js} +53 -52
- package/dist/{dist-DoE4XJBC.js → dist-CYeqK4Xw.js} +9801 -10649
- package/dist/{dist-BLfKmR-l.js → dist-Cxlp3WH6.js} +16 -15
- package/dist/{dist-D-wwqlzJ.js → dist-DSJPGj42.js} +158 -157
- package/dist/{dist-BorMD-uX.js → dist-DU9ICsWZ.js} +75 -74
- package/dist/{dist-DBtSl3sf.js → dist-DWv0ALBi.js} +47 -46
- package/dist/{dist-OR1OnN-y.js → dist-DiBpWEsB.js} +31 -30
- package/dist/{dist-CrSP_H1M.js → dist-DiLFTlnl.js} +242 -242
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dist-CSbh1PNP.js → dist-cVDV5IuI.js} +23 -22
- package/dist/{dist-BuaRHxOc.js → dist-fRfaOoq8.js} +44 -43
- package/dist/{dist-Cg7gzw-a.js → dist-gTTI-9Px.js} +78 -77
- package/dist/dropdown-menu-CSNdPSnS.js +6083 -0
- package/dist/{ebnfDiagram-PWID7BFC-CQRK5_eT.js → ebnfDiagram-PWID7BFC-BI1ZmjVm.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-BKtWrDVh.js → erDiagram-RLTQ6QDP-BtWjj9xy.js} +1 -1
- package/dist/{error-banner-CFPHFw4h.js → error-banner-IsonnvA0.js} +84 -83
- package/dist/error-entries-CRPfxMqm.js +2505 -0
- package/dist/{esm-D2gTsXEV.js → esm-BgKjMvWw.js} +530 -529
- package/dist/{esm-AMFssoNp.js → esm-CHjVSexr.js} +328 -329
- package/dist/feedback-button-2ycmR9GG.js +374 -0
- package/dist/{flowDiagram-HODETNUW-1IN-ih2E.js → flowDiagram-HODETNUW-DQvZh96A.js} +2 -2
- package/dist/{formats-X4mMQWzX.js → formats-BK4VefeF.js} +6 -6
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-CSYHMRDu.js → glide-data-editor-Buj2OZjL.js} +417 -415
- package/dist/{glide-utils-DM9zBO4W.js → glide-utils-CQddGpa-.js} +16 -16
- package/dist/{globals-Fpiwkv4D.js → globals-B-14fUeb.js} +3 -3
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{error-entries-Damuuclv.js → html-to-image-CgAnxFi8.js} +26911 -26769
- package/dist/{infoDiagram-27XIBGKW-CkB-zr4p.js → infoDiagram-27XIBGKW-BdAObnc_.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-wlyLjBmM.js → ishikawaDiagram-5VMMS53U-DP-jE8dw.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-C2usY0i-.js → kanban-definition-UXKFOSKX-BkMgPjfm.js} +1 -1
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-BisjOLiW.js} +12 -12
- package/dist/main.js +9981 -8001
- package/dist/{mermaid-BA-Z6wGL.js → mermaid-B-OFqheA.js} +52 -52
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-nKOWS8RR.js → mindmap-definition-YA3MSWOX-Du7toAZX.js} +1 -1
- package/dist/{number-overlay-editor-BOjqsq7D.js → number-overlay-editor-ZVFcJ7_u.js} +3 -3
- package/dist/{dist-CN8zI-XC.js → objectWithoutPropertiesLoose-ai5NUqGa.js} +262 -240
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{once-BtE-wKRL.js → once-NnpX_HnX.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-Dac9EIKD.js → pegDiagram-XKGWAZYB-CX_729j0.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-B7S-DsW_.js → pieDiagram-E7YTZNPT-dtTFJcVI.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-CTPTtxXB.js → process-output-Bmev5azU.js} +4 -4
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-Cfa5Q-hr.js → railroadDiagram-O6MQD6OU-Dsc2Cf4c.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-d8zXCJIk.js → requirementDiagram-BXWQKSXE-D3g0c60I.js} +1 -1
- package/dist/{reveal-component-Brpo7CP8.js → reveal-component-BWz1KjWe.js} +426 -403
- package/dist/schemas-CdscWNy_.js +4747 -0
- package/dist/select-BSxlITBo.js +1200 -0
- package/dist/{sequenceDiagram-WJ2MYXX4-b6pei3lJ.js → sequenceDiagram-WJ2MYXX4-w1pWbIpk.js} +1 -1
- package/dist/{spec-BJzgmvVa.js → spec-Dq8RNplp.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-Be-xSpaZ.js → stateDiagram-D77RDMKH-BCv7kP4H.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-5Y-FxesJ.js → stateDiagram-v2-MP3YSRHH-D1cTOt0x.js} +2 -2
- package/dist/static-state-BldGd99T.js +72 -0
- package/dist/strings-BGW-fXVJ.js +507 -0
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-nRRl4NU0.js → swimlanes-42K2YHIH-DNO6jDnd.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-BS79510V.js → swimlanesDiagram-VR7AAH4N-CkSWsxYJ.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-Dir1o8ml.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-Cfzf8WPf.js → timeline-definition-24CTP7MA-DQvqGFM9.js} +1 -1
- package/dist/toast-BWIPi3aF.js +491 -0
- package/dist/{tooltip-CtBZ5q8p.js → tooltip-C3UnvsRe.js} +329 -305
- package/dist/use-restore-focus-BWO0z1lo.js +1672 -0
- package/dist/{useAsyncData-BD534XmW.js → useAsyncData-DsZMvNXn.js} +15 -14
- package/dist/{useDateFormatter-DkajGwwd.js → useDateFormatter-ChB4eyim.js} +2 -2
- package/dist/{useDeepCompareMemoize-C72_RNsu.js → useDeepCompareMemoize-KMBBux8C.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-cMNQ80CK.js} +1 -1
- package/dist/useLifecycle-BquH9ET-.js +112 -0
- package/dist/useTheme-B9C1JIy9.js +307 -0
- package/dist/utils-DXkj82sK.js +813 -0
- package/dist/{vega-component-DfcYgj-Y.js → vega-component-9NOEITbg.js} +170 -169
- package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
- package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
- package/dist/{vennDiagram-4TSXK5OY-CeY6Z1xZ.js → vennDiagram-4TSXK5OY-BfzXp4SH.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-Cxs9NtVi.js → wardleyDiagram-VM6X3IG4-CiqEE8eq.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-DNWbvPK7.js → xychartDiagram-S5SC5T6Z-BTIHCVOI.js} +2 -2
- package/package.json +16 -20
- package/src/__mocks__/document.tsx +63 -0
- package/src/__mocks__/notebook.ts +3 -4
- package/src/__mocks__/partial.ts +26 -0
- package/src/__mocks__/requests.ts +1 -4
- package/src/__tests__/main.test.tsx +24 -1
- package/src/__tests__/module-entry.test.ts +44 -0
- package/src/__tests__/mount.test.ts +1 -21
- package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
- package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
- package/src/components/ai/ai-model-dropdown.tsx +11 -6
- package/src/components/app-config/ai-config.tsx +7 -2
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/app-config/user-config-form.tsx +35 -56
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/__tests__/notebook-access-selector.test.tsx +64 -0
- package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +3 -2
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +20 -101
- package/src/components/chat/chat-utils.ts +4 -8
- package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
- package/src/components/chat/notebook-access-selector.tsx +100 -0
- package/src/components/data-table/TableBottomBar.tsx +4 -1
- package/src/components/data-table/TableTopBar.tsx +2 -0
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
- package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
- package/src/components/data-table/__tests__/columns.test.tsx +105 -0
- package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
- package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
- package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
- package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
- package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
- package/src/components/data-table/cell-selection/feature.ts +2 -2
- package/src/components/data-table/cell-selection/types.ts +2 -2
- package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
- package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
- package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
- package/src/components/data-table/charts/charts.tsx +40 -30
- package/src/components/data-table/charts/storage.ts +16 -5
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
- package/src/components/data-table/column-summary/column-summary.tsx +2 -4
- package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
- package/src/components/data-table/columns.tsx +45 -46
- package/src/components/data-table/context-menu.tsx +36 -20
- package/src/components/data-table/data-table.tsx +17 -1
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +76 -48
- package/src/components/data-table/pagination.tsx +44 -33
- package/src/components/data-table/range-focus/atoms.ts +4 -6
- package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
- package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
- package/src/components/data-table/renderers.tsx +16 -7
- package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
- package/src/components/data-table/search-highlight.tsx +79 -0
- package/src/components/data-table/types.ts +1 -0
- package/src/components/data-table/url-detector.tsx +49 -9
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +96 -5
- package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/__tests__/utils.test.ts +57 -6
- package/src/components/datasources/column-preview.tsx +17 -12
- package/src/components/datasources/datasources.tsx +56 -43
- package/src/components/datasources/utils.ts +32 -23
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/custom-node.tsx +1 -1
- package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
- package/src/components/dependency-graph/elements.ts +24 -21
- package/src/components/dependency-graph/minimap-content.tsx +13 -19
- package/src/components/dependency-graph/panels.tsx +4 -2
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/Output.test.tsx +50 -32
- package/src/{core/attachments/__tests__/toast.test.tsx → components/editor/__tests__/agent-toast.test.tsx} +1 -1
- package/src/components/editor/__tests__/data-attributes.test.tsx +28 -14
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/output-persistence.test.tsx +6 -2
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +34 -8
- package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +2 -6
- package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +113 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/pair-with-agent-commands.ts +2 -2
- package/src/components/editor/actions/pair-with-agent-modal.tsx +19 -16
- package/src/components/editor/actions/useCellActionButton.tsx +36 -31
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +19 -23
- package/src/components/editor/actions/useRestartKernel.tsx +1 -1
- package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
- package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
- package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
- package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
- package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +1 -1
- package/src/components/editor/alerts/connection-notice.tsx +1 -1
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/alerts/stdin-blocking-alert.tsx +1 -1
- package/src/components/editor/app-container.tsx +1 -1
- package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
- package/src/components/editor/cell/CreateCellButton.tsx +15 -21
- package/src/components/editor/cell/DeleteButton.tsx +3 -2
- package/src/components/editor/cell/RunButton.tsx +2 -2
- package/src/components/editor/cell/StagedAICell.tsx +10 -2
- package/src/components/editor/cell/StopButton.tsx +2 -2
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +4 -2
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/cell-actions.tsx +12 -1
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +46 -165
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +11 -4
- package/src/components/editor/cell/useAddCell.ts +4 -8
- package/src/components/editor/cell/useDeleteCell.tsx +10 -36
- package/src/components/editor/cell/useRunCells.ts +2 -5
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/cell/useSplitCell.tsx +10 -6
- package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
- package/src/components/editor/chrome/components/feedback-button.tsx +2 -8
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
- package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
- package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
- package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
- package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +10 -12
- package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +6 -9
- package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +62 -3
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +4 -4
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
- package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -2
- package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/columns/__tests__/cell-column.test.tsx +1 -1
- package/src/components/editor/columns/cell-column.tsx +1 -1
- package/src/components/editor/columns/sortable-column.tsx +2 -2
- package/src/components/editor/connections/components.tsx +5 -10
- package/src/components/editor/controls/Controls.tsx +4 -4
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +10 -4
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/documentation.css +34 -11
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +25 -20
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/errors/send-error-report-button.tsx +3 -6
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +48 -15
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/header/__tests__/filename-form.test.tsx +1 -4
- package/src/components/editor/header/__tests__/status.test.tsx +5 -3
- package/src/components/editor/header/app-header.tsx +1 -1
- package/src/components/editor/header/filename-form.tsx +1 -1
- package/src/components/editor/header/status.tsx +40 -20
- package/src/components/editor/links/__tests__/cell-link.test.tsx +148 -0
- package/src/components/editor/links/cell-link-list.tsx +1 -1
- package/src/components/editor/links/cell-link.tsx +17 -7
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
- package/src/components/editor/navigation/__tests__/navigation.test.ts +108 -85
- package/src/components/editor/navigation/__tests__/selection.test.ts +43 -21
- package/src/components/editor/navigation/clipboard.ts +17 -14
- package/src/components/editor/navigation/focus-utils.ts +23 -4
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +17 -33
- package/src/components/editor/navigation/navigation.ts +71 -70
- package/src/components/editor/navigation/selection.ts +30 -29
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +29 -32
- package/src/components/editor/output/MarimoErrorOutput.tsx +2 -1
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- package/src/components/editor/output/Outputs.css +8 -0
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +33 -20
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/cell-array.tsx +22 -33
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
- package/src/components/editor/stdin-blocking-alert.tsx +1 -1
- package/src/components/home/components.tsx +17 -31
- package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
- package/src/components/icons/large-spinner.tsx +3 -14
- package/src/components/icons/spinner.tsx +1 -1
- package/src/components/markdown/markdown-renderer.tsx +4 -8
- package/src/components/mcp/mcp-status-indicator.tsx +1 -1
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/edit-page.tsx +19 -17
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +89 -0
- package/src/components/scratchpad/scratchpad.tsx +43 -32
- package/src/components/scratchpad/state.ts +7 -0
- package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
- package/src/components/slides/__tests__/minimap.test.ts +38 -19
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
- package/src/components/slides/minimap.tsx +17 -12
- package/src/components/slides/reveal-component.tsx +58 -26
- package/src/components/slides/reveal-slides.css +5 -4
- package/src/components/slides/slide-cell-view.tsx +4 -5
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/slides/slide-scroll-hint.tsx +3 -1
- package/src/components/sort/SortableCellsProvider.tsx +8 -25
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +46 -42
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/components/ui/range-slider.tsx +22 -9
- package/src/core/MarimoApp.tsx +1 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +32 -33
- package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
- package/src/core/ai/context/providers/cell-output.ts +2 -2
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/staged-cells.ts +18 -19
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +40 -88
- package/src/core/ai/tools/__tests__/registry.test.ts +17 -0
- package/src/core/ai/tools/base.ts +18 -15
- package/src/core/ai/tools/edit-notebook-tool.ts +86 -80
- package/src/core/ai/tools/registry.ts +13 -10
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -37
- package/src/core/cells/__tests__/actions.test.ts +624 -35
- package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
- package/src/core/cells/__tests__/arrange.test.ts +432 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +251 -2540
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/document.test.ts +164 -0
- package/src/core/cells/__tests__/editor.test.ts +57 -0
- package/src/core/cells/__tests__/flush-document.test.ts +40 -0
- package/src/core/cells/__tests__/harness.ts +106 -0
- package/src/core/cells/__tests__/layout.test.ts +177 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +122 -0
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/__tests__/session.test.ts +445 -211
- package/src/core/cells/__tests__/utils.test.ts +9 -108
- package/src/core/cells/actions.ts +675 -6
- package/src/core/cells/add-missing-import.ts +47 -43
- package/src/core/cells/arrange.ts +529 -0
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +126 -1363
- package/src/core/cells/columns.ts +38 -0
- package/src/core/cells/document.ts +178 -0
- package/src/core/cells/edit.ts +30 -0
- package/src/core/cells/editor.ts +82 -0
- package/src/core/cells/layout.ts +221 -0
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/cells/pending-delete-service.ts +3 -7
- package/src/core/cells/session.ts +76 -53
- package/src/core/cells/types.ts +22 -6
- package/src/core/cells/utils.ts +10 -8
- package/src/core/codemirror/__tests__/format.test.ts +0 -34
- package/src/core/codemirror/__tests__/setup.test.ts +29 -29
- package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
- package/src/core/codemirror/ai/resources.ts +1 -1
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +2 -6
- package/src/core/codemirror/cells/extensions.ts +30 -28
- package/src/core/codemirror/cells/state.ts +1 -6
- package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
- package/src/core/codemirror/copilot/getCodes.ts +2 -2
- package/src/core/codemirror/format.ts +6 -23
- package/src/core/codemirror/keymaps/vim.ts +4 -8
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
- package/src/core/codemirror/language/cell-code.ts +114 -0
- package/src/core/codemirror/language/extension.ts +52 -35
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +16 -10
- package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/language/utils.ts +9 -39
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
- package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
- package/src/core/codemirror/lsp/utils.ts +1 -1
- package/src/core/codemirror/misc/__tests__/paste.test.ts +3 -1
- package/src/core/codemirror/misc/paste.ts +1 -1
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/readonly/extension.ts +2 -2
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/config/__tests__/app-config.test.ts +64 -0
- package/src/core/config/__tests__/config-schema.test.ts +13 -6
- package/src/core/config/config-schema.ts +13 -4
- package/src/core/config/config.ts +26 -12
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/documentation/doc-lookup.ts +1 -1
- package/src/core/edit-app.tsx +21 -28
- package/src/core/errors/error-entries.ts +4 -1
- package/src/core/export/hooks.ts +1 -1
- package/src/core/export/layout.ts +2 -2
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
- package/src/core/islands/__tests__/bridge.test.ts +72 -25
- package/src/core/islands/bootstrap.ts +46 -53
- package/src/core/islands/bridge.ts +75 -24
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/islands/components/web-components.tsx +1 -1
- package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
- package/src/core/islands/worker/controller.ts +4 -10
- package/src/core/islands/worker/worker.tsx +33 -33
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/kernel/__tests__/handlers.test.ts +7 -153
- package/src/core/kernel/handlers.ts +19 -72
- package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
- package/src/core/meta/code-visibility.ts +18 -9
- package/src/core/network/__tests__/connection.test.ts +1 -1
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
- package/src/core/network/connection-notice.ts +1 -1
- package/src/core/network/connection.ts +1 -1
- package/src/core/network/requests-lazy.ts +2 -5
- package/src/core/network/requests-network.ts +5 -31
- package/src/core/network/requests-static.ts +1 -4
- package/src/core/network/requests-toasting.tsx +1 -4
- package/src/core/network/types.ts +6 -14
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/notebook/__tests__/operations.test.ts +51 -0
- package/src/core/notebook/attachments.ts +38 -0
- package/src/core/notebook/document/__tests__/codemirror.test.ts +758 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
- package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
- package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
- package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/notebook/document/__tests__/model.test.ts +247 -0
- package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/notebook/document/__tests__/state.test.ts +459 -0
- package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
- package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
- package/src/core/notebook/document/__tests__/test-host.ts +247 -0
- package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
- package/src/core/notebook/document/__tests__/user.ts +61 -0
- package/src/core/notebook/document/codemirror.ts +216 -0
- package/src/core/notebook/document/draft.ts +502 -0
- package/src/core/notebook/document/hooks.tsx +118 -0
- package/src/core/notebook/document/index.ts +24 -0
- package/src/core/notebook/document/model.ts +102 -0
- package/src/core/notebook/document/select.ts +41 -0
- package/src/core/notebook/document/state.ts +378 -0
- package/src/core/notebook/document/sync.ts +369 -0
- package/src/core/notebook/index.ts +19 -0
- package/src/core/notebook/operations.ts +30 -0
- package/src/core/notebook/replica/AGENTS.md +11 -0
- package/src/core/{host → notebook/replica}/__tests__/attachments.test.ts +9 -10
- package/src/core/{host → notebook/replica}/__tests__/document.test.ts +18 -16
- package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
- package/src/core/notebook/replica/__tests__/replica.test.ts +550 -0
- package/src/core/notebook/replica/backend.ts +19 -0
- package/src/core/notebook/replica/connection.ts +42 -0
- package/src/core/notebook/replica/index.ts +13 -0
- package/src/core/notebook/replica/replica.ts +286 -0
- package/src/core/{host → notebook/replica}/resources/attachments.ts +6 -3
- package/src/core/{host → notebook/replica}/resources/document.ts +4 -4
- package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
- package/src/core/packages/useSandboxController.ts +1 -1
- package/src/core/run-app.tsx +48 -51
- package/src/core/runtime/__tests__/adapter.test.ts +1 -1
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -74
- package/src/core/runtime/adapter.ts +1 -1
- package/src/core/runtime/config.ts +2 -2
- package/src/core/runtime/runtime.ts +33 -46
- package/src/core/runtime/types.ts +0 -2
- package/src/core/saving/__tests__/document.test.tsx +123 -0
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
- package/src/core/saving/document.ts +33 -0
- package/src/core/saving/filename.ts +1 -1
- package/src/core/saving/save-component.tsx +39 -60
- package/src/core/saving/state.ts +38 -39
- package/src/core/saving/useAutoSave.ts +17 -53
- package/src/core/session/__tests__/backend.test.ts +236 -0
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +184 -0
- package/src/core/{websocket → session}/__tests__/useNotebookSession.hook.test.tsx +213 -262
- package/src/core/session/active-notebook.ts +28 -0
- package/src/core/session/backend.ts +123 -0
- package/src/core/session/embedded.ts +7 -0
- package/src/core/{websocket → session}/types.ts +2 -2
- package/src/core/session/useNotebookReplica.ts +74 -0
- package/src/core/{websocket → session}/useNotebookSession.tsx +77 -64
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/{websocket → transports}/__tests__/connection-state.test.ts +1 -13
- package/src/core/transports/__tests__/server.test.ts +408 -0
- package/src/core/transports/__tests__/static.test.ts +306 -0
- package/src/core/transports/__tests__/wasm.test.ts +166 -0
- package/src/core/{websocket → transports}/connection-state.ts +9 -16
- package/src/core/transports/server.ts +152 -0
- package/src/core/transports/static.ts +166 -0
- package/src/core/transports/wasm.ts +97 -0
- package/src/core/wasm/__tests__/bridge.test.ts +105 -65
- package/src/core/wasm/__tests__/worker.test.ts +187 -0
- package/src/core/wasm/bridge.ts +60 -71
- package/src/core/wasm/rpc.ts +15 -3
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +55 -51
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/save-worker.ts +9 -10
- package/src/core/wasm/worker/types.ts +29 -18
- package/src/core/wasm/worker/worker.ts +89 -45
- package/src/css/app/codemirror.css +1 -1
- package/src/css/globals.css +66 -22
- package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
- package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
- package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
- package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
- package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
- package/src/hooks/__tests__/useScript.test.tsx +77 -0
- package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
- package/src/hooks/useAsyncData.ts +3 -3
- package/src/hooks/useDataSourceDiscovery.ts +6 -4
- package/src/hooks/useDebounce.ts +6 -10
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useEventListener.ts +1 -2
- package/src/hooks/useInputHistory.ts +4 -7
- package/src/hooks/useInternalStateWithSync.ts +6 -6
- package/src/hooks/useResizeObserver.ts +4 -7
- package/src/hooks/useScript.ts +67 -70
- package/src/hooks/useStateForKey.ts +93 -0
- package/src/mount.tsx +20 -15
- package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +69 -37
- package/src/plugins/impl/DropdownPlugin.tsx +2 -6
- package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +387 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/model.ts +3 -1
- package/src/plugins/impl/anywidget/registry.ts +18 -14
- package/src/plugins/impl/anywidget/runtime.ts +21 -9
- package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
- package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
- package/src/plugins/impl/chat/chat-ui.tsx +14 -11
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
- package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +43 -16
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/cell.stories.tsx +2 -5
- package/src/stories/data-table.stories.tsx +31 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +28 -23
- package/src/stories/runtime-story.tsx +23 -17
- package/src/stories/select.stories.tsx +2 -2
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/utils/__tests__/arrays.test.ts +35 -0
- package/src/utils/__tests__/batch-requests.test.ts +3 -3
- package/src/utils/__tests__/{createReducer.test.ts → createReducer.test.tsx} +29 -0
- package/src/utils/__tests__/numbers.test.ts +105 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +11 -2
- package/src/utils/blob.ts +1 -1
- package/src/utils/createReducer.ts +53 -26
- package/src/utils/maps.ts +0 -3
- package/src/utils/numbers.ts +79 -18
- package/src/utils/objects.ts +4 -9
- package/src/utils/once.ts +19 -19
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/any-language-editor-D4q-IFcM.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/assets/worker-HPY9fbhz.js +0 -114
- package/dist/code-visibility-DPm4oWK1.js +0 -138
- package/dist/dropdown-menu-DHP9P4VE.js +0 -4678
- package/dist/feedback-button-DVgw4Y7F.js +0 -379
- package/dist/html-to-image-BdA59IUD.js +0 -3251
- package/dist/label-DoysmLMW.js +0 -281
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/objectWithoutPropertiesLoose-BRDcTsfB.js +0 -23
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/dist/select-DemoKT4G.js +0 -1344
- package/dist/toDate-B5mIgxwZ.js +0 -1185
- package/dist/toast-PkdZraM8.js +0 -1830
- package/dist/use-restore-focus-CKjfFjLM.js +0 -6369
- package/dist/useLifecycle-BGWzTwHK.js +0 -169
- package/dist/useTheme-BhQvec43.js +0 -904
- package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +0 -50
- package/src/components/editor/chrome/wrapper/footer-items/rtc-status.tsx +0 -65
- package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
- package/src/components/editor/navigation/state.ts +0 -65
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
- package/src/core/ai/tools/run-cells-tool.ts +0 -303
- package/src/core/attachments/state.ts +0 -18
- package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
- package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
- package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
- package/src/core/cells/document-changes.ts +0 -944
- package/src/core/codemirror/rtc/extension.ts +0 -453
- package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +0 -52
- package/src/core/codemirror/rtc/loro/awareness.ts +0 -531
- package/src/core/codemirror/rtc/loro/colors.ts +0 -38
- package/src/core/codemirror/rtc/loro/sync.ts +0 -168
- package/src/core/host/AGENTS.md +0 -11
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/fixtures.ts +0 -39
- package/src/core/host/__tests__/notebook-client.test.ts +0 -433
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/__tests__/stream.test.ts +0 -211
- package/src/core/host/connection.ts +0 -81
- package/src/core/host/events.ts +0 -61
- package/src/core/host/notebook-client.ts +0 -290
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/host/resources/resource.ts +0 -59
- package/src/core/host/stream.ts +0 -213
- 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,52 +1,39 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import { dequal as isEqual } from "dequal";
|
|
3
|
+
import type * as Protocol from "@marimo-team/client/protocol";
|
|
5
4
|
import { type Atom, atom, useAtom, useAtomValue } from "jotai";
|
|
6
5
|
import { atomFamily, selectAtom, splitAtom } from "jotai/utils";
|
|
7
6
|
import { createRef, type ReducerWithoutAction } from "react";
|
|
8
7
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
11
|
-
type CellColumnId,
|
|
12
|
-
type CellIndex,
|
|
13
|
-
MultiColumn,
|
|
14
|
-
} from "@/utils/id-tree";
|
|
8
|
+
import type { EditableDocument, Placement } from "@/core/notebook/document";
|
|
9
|
+
import type { CellColumnId } from "./layout";
|
|
15
10
|
import { invariant } from "@/utils/invariant";
|
|
16
11
|
import { Logger } from "@/utils/Logger";
|
|
17
|
-
import { clamp } from "@/utils/math";
|
|
18
12
|
import { Objects } from "@/utils/objects";
|
|
19
13
|
import { extractAllTracebackInfo, type TracebackInfo } from "@/utils/traceback";
|
|
20
14
|
import { createReducerAndAtoms } from "../../utils/createReducer";
|
|
21
15
|
import { foldAllBulk, unfoldAllBulk } from "../codemirror/editing/commands";
|
|
22
16
|
import { editorMountScheduler } from "../codemirror/editor-mount-scheduler";
|
|
23
|
-
import {
|
|
24
|
-
splitEditor,
|
|
25
|
-
updateEditorCodeFromPython,
|
|
26
|
-
} from "../codemirror/language/utils";
|
|
27
17
|
import type { SerializedEditorState } from "../codemirror/types";
|
|
28
|
-
import {
|
|
18
|
+
import { mergeOutlines } from "../dom/outline";
|
|
29
19
|
import type { CellMessage } from "../kernel/messages";
|
|
30
20
|
import { isErrorMime } from "../mime";
|
|
31
21
|
import type { CellConfig } from "../network/types";
|
|
32
|
-
import { canUseRtc, isRtcEnabled } from "../rtc/state";
|
|
33
22
|
import { createDeepEqualAtom, store } from "../state/jotai";
|
|
34
23
|
import { isWasm } from "../wasm/utils";
|
|
35
24
|
import { prepareCellForExecution, transitionCell } from "./cell";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
25
|
+
import { applyDocument } from "./document";
|
|
26
|
+
import { isCodeHidden, shownHiddenCodeAtom } from "./editor";
|
|
27
|
+
import { type CellId, SCRATCH_CELL_ID } from "./ids";
|
|
38
28
|
import { type CellLog, getCellLogsForMessage } from "./logs";
|
|
39
|
-
import {
|
|
40
|
-
|
|
41
|
-
scrollToBottom,
|
|
42
|
-
scrollToTop,
|
|
43
|
-
} from "./scrollCellIntoView";
|
|
29
|
+
import type { Outline } from "./outline";
|
|
30
|
+
import { focusAndScrollCellIntoView } from "./scrollCellIntoView";
|
|
44
31
|
import {
|
|
45
32
|
type CellData,
|
|
46
33
|
type CellRuntimeState,
|
|
47
34
|
createCell,
|
|
48
|
-
createCellConfig,
|
|
49
35
|
createCellRuntimeState,
|
|
36
|
+
isEdited,
|
|
50
37
|
} from "./types";
|
|
51
38
|
import {
|
|
52
39
|
canUndoDeletes,
|
|
@@ -58,17 +45,21 @@ import {
|
|
|
58
45
|
notebookQueueOrRunningCount,
|
|
59
46
|
} from "./utils";
|
|
60
47
|
|
|
48
|
+
/** A deleted cell as it was, with where it went in the document. */
|
|
49
|
+
export interface DeletedCell {
|
|
50
|
+
cell: Protocol.CellInput;
|
|
51
|
+
placement: Placement;
|
|
52
|
+
/** The editor's state at deletion, so undo brings its history back. */
|
|
53
|
+
serializedEditorState: SerializedEditorState | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
61
56
|
/**
|
|
62
|
-
* History entry for undoing
|
|
57
|
+
* History entry for undoing one deletion, of one or more cells.
|
|
63
58
|
*/
|
|
64
59
|
export interface UndoDeleteEntry {
|
|
65
60
|
type: "delete";
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
column: CellColumnId;
|
|
69
|
-
index: CellIndex;
|
|
70
|
-
isSetupCell: boolean;
|
|
71
|
-
config: CellConfig;
|
|
61
|
+
/** In document order. Each cell is placed after the one before it. */
|
|
62
|
+
cells: DeletedCell[];
|
|
72
63
|
}
|
|
73
64
|
|
|
74
65
|
/**
|
|
@@ -77,7 +68,7 @@ export interface UndoDeleteEntry {
|
|
|
77
68
|
export interface UndoMoveEntry {
|
|
78
69
|
type: "move";
|
|
79
70
|
cellIds: CellId[];
|
|
80
|
-
placements: Array<{ columnId: CellColumnId; index:
|
|
71
|
+
placements: Array<{ columnId: CellColumnId; index: number }>;
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
export type HistoryEntry = UndoDeleteEntry | UndoMoveEntry;
|
|
@@ -89,7 +80,8 @@ export interface NotebookState {
|
|
|
89
80
|
/**
|
|
90
81
|
* Order of cells on the page.
|
|
91
82
|
*/
|
|
92
|
-
|
|
83
|
+
/** The cells in document order. */
|
|
84
|
+
cellIds: CellId[];
|
|
93
85
|
/**
|
|
94
86
|
* Map of cells to their view state
|
|
95
87
|
*/
|
|
@@ -116,12 +108,6 @@ export interface NotebookState {
|
|
|
116
108
|
* Logs of all cell messages
|
|
117
109
|
*/
|
|
118
110
|
cellLogs: CellLog[];
|
|
119
|
-
/**
|
|
120
|
-
* Set of cells that have been created that are initialized with `hide_code`.
|
|
121
|
-
*
|
|
122
|
-
* These start temporarily open until their first blur event.
|
|
123
|
-
*/
|
|
124
|
-
untouchedNewCells: Set<CellId>;
|
|
125
111
|
}
|
|
126
112
|
|
|
127
113
|
function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
@@ -153,733 +139,49 @@ function withScratchCell(notebookState: NotebookState): NotebookState {
|
|
|
153
139
|
*/
|
|
154
140
|
export function initialNotebookState(): NotebookState {
|
|
155
141
|
return withScratchCell({
|
|
156
|
-
cellIds:
|
|
142
|
+
cellIds: [],
|
|
157
143
|
cellData: {},
|
|
158
144
|
cellRuntime: {},
|
|
159
145
|
cellHandles: {},
|
|
160
146
|
history: [],
|
|
161
147
|
scrollKey: null,
|
|
162
148
|
cellLogs: [],
|
|
163
|
-
untouchedNewCells: new Set<CellId>(),
|
|
164
149
|
});
|
|
165
150
|
}
|
|
166
151
|
|
|
167
|
-
/** The target cell ID to create a new cell relative to. Can be:
|
|
168
|
-
* - A CellId string for an existing cell
|
|
169
|
-
* - "__end__" to append at the end of the first column
|
|
170
|
-
* - {type: "__end__", columnId} to append at the end of a specific column
|
|
171
|
-
*/
|
|
172
|
-
export type CellPosition =
|
|
173
|
-
| CellId
|
|
174
|
-
| "__end__"
|
|
175
|
-
| { type: "__end__"; columnId: CellColumnId };
|
|
176
|
-
|
|
177
|
-
export interface CreateNewCellAction {
|
|
178
|
-
cellId: CellPosition;
|
|
179
|
-
/** Whether to insert before (true) or after (false) the target cell */
|
|
180
|
-
before: boolean;
|
|
181
|
-
/** Initial code content for the new cell */
|
|
182
|
-
code?: string;
|
|
183
|
-
/** Optional name for the new cell */
|
|
184
|
-
name?: string;
|
|
185
|
-
/** Optional cell configuration */
|
|
186
|
-
config?: CellConfig;
|
|
187
|
-
/** The last executed code for the new cell */
|
|
188
|
-
lastCodeRun?: string;
|
|
189
|
-
/** Timestamp of the last execution */
|
|
190
|
-
lastExecutionTime?: number;
|
|
191
|
-
/** Optional custom ID for the new cell. Auto-generated if not provided */
|
|
192
|
-
newCellId?: CellId;
|
|
193
|
-
/** Whether to focus the new cell after creation */
|
|
194
|
-
autoFocus?: boolean;
|
|
195
|
-
/** If true, skip creation if code already exists */
|
|
196
|
-
skipIfCodeExists?: boolean;
|
|
197
|
-
/** Hide the code in the new cell. This will be initially shown until the cell is blurred for the first time. */
|
|
198
|
-
hideCode?: boolean;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
152
|
/**
|
|
202
153
|
* Actions and reducer for the notebook state.
|
|
203
154
|
*/
|
|
204
155
|
const {
|
|
205
156
|
reducer,
|
|
206
|
-
addMiddleware,
|
|
207
157
|
createActions,
|
|
208
158
|
useActions,
|
|
209
159
|
valueAtom: notebookAtom,
|
|
210
160
|
} = createReducerAndAtoms(initialNotebookState, {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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: (
|
|
161
|
+
/**
|
|
162
|
+
* Keep a cell as run, or as edited, as it was before formatting rewrote
|
|
163
|
+
* its code from `before` to `after`. The code itself arrives through the
|
|
164
|
+
* document.
|
|
165
|
+
*/
|
|
166
|
+
codeFormatted: (
|
|
822
167
|
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
|
-
},
|
|
168
|
+
action: { cellId: CellId; before: string; after: string },
|
|
832
169
|
) => {
|
|
833
|
-
const { cellId,
|
|
170
|
+
const { cellId, before, after } = action;
|
|
834
171
|
if (!state.cellData[cellId]) {
|
|
835
172
|
return state;
|
|
836
173
|
}
|
|
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
174
|
return updateCellData({
|
|
877
175
|
state,
|
|
878
176
|
cellId,
|
|
879
177
|
cellReducer: (cell) => {
|
|
178
|
+
const lastCodeRun = isEdited(cell.lastCodeRun, before)
|
|
179
|
+
? cell.lastCodeRun
|
|
180
|
+
: after;
|
|
880
181
|
return {
|
|
881
182
|
...cell,
|
|
882
|
-
|
|
183
|
+
lastCodeRun,
|
|
184
|
+
edited: isEdited(lastCodeRun, cell.code),
|
|
883
185
|
};
|
|
884
186
|
},
|
|
885
187
|
});
|
|
@@ -939,158 +241,14 @@ const {
|
|
|
939
241
|
cellLogs: [...state.cellLogs, ...action.logs],
|
|
940
242
|
};
|
|
941
243
|
},
|
|
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();
|
|
244
|
+
/** Follow the host document's cells and order. */
|
|
245
|
+
reconcileDocument: (state, document: EditableDocument) => {
|
|
246
|
+
const nextState = applyDocument(state, document);
|
|
247
|
+
for (const cellId of state.cellIds) {
|
|
248
|
+
if (!(cellId in nextState.cellData)) {
|
|
249
|
+
releaseCellAtoms(cellId);
|
|
962
250
|
}
|
|
963
251
|
}
|
|
964
|
-
|
|
965
|
-
return {
|
|
966
|
-
...state,
|
|
967
|
-
cellIds: MultiColumn.fromWithPreviousShape(action.cellIds, state.cellIds),
|
|
968
|
-
cellData: nextCellData,
|
|
969
|
-
cellRuntime: nextCellRuntime,
|
|
970
|
-
cellHandles: nextCellHandles,
|
|
971
|
-
};
|
|
972
|
-
},
|
|
973
|
-
/**
|
|
974
|
-
* Rebuild the MultiColumn tree using each cell's `config.column` value.
|
|
975
|
-
*
|
|
976
|
-
* Used after a transaction whose `set-config` changes updated cells'
|
|
977
|
-
* column metadata without physically moving them in the tree. Cells with
|
|
978
|
-
* `config.column == null` inherit the column of the previous cell in the
|
|
979
|
-
* given order (see `MultiColumn.fromIdsAndColumns`), which lets the server
|
|
980
|
-
* send column changes only at column boundaries.
|
|
981
|
-
*/
|
|
982
|
-
rebuildCellColumns: (state, action: { cellIds: CellId[] }) => {
|
|
983
|
-
const newCellIds = MultiColumn.fromIdsAndColumns(
|
|
984
|
-
action.cellIds.map((id) => [
|
|
985
|
-
id,
|
|
986
|
-
state.cellData[id]?.config.column ?? null,
|
|
987
|
-
]),
|
|
988
|
-
);
|
|
989
|
-
return { ...state, cellIds: newCellIds };
|
|
990
|
-
},
|
|
991
|
-
setCellCodes: (
|
|
992
|
-
state,
|
|
993
|
-
action: {
|
|
994
|
-
codes: string[];
|
|
995
|
-
ids: CellId[];
|
|
996
|
-
codeIsStale: boolean;
|
|
997
|
-
names?: string[];
|
|
998
|
-
configs?: CellConfig[];
|
|
999
|
-
},
|
|
1000
|
-
) => {
|
|
1001
|
-
invariant(
|
|
1002
|
-
action.codes.length === action.ids.length,
|
|
1003
|
-
"Expected codes and ids to have the same length",
|
|
1004
|
-
);
|
|
1005
|
-
|
|
1006
|
-
let nextState = { ...state };
|
|
1007
|
-
|
|
1008
|
-
const cellReducer = ({
|
|
1009
|
-
cell,
|
|
1010
|
-
code,
|
|
1011
|
-
cellId,
|
|
1012
|
-
name,
|
|
1013
|
-
config,
|
|
1014
|
-
}: {
|
|
1015
|
-
cell: CellData | undefined;
|
|
1016
|
-
code: string;
|
|
1017
|
-
cellId: CellId;
|
|
1018
|
-
name?: string;
|
|
1019
|
-
config?: CellConfig;
|
|
1020
|
-
}) => {
|
|
1021
|
-
if (!cell) {
|
|
1022
|
-
return createCell({
|
|
1023
|
-
id: cellId,
|
|
1024
|
-
code,
|
|
1025
|
-
name: name,
|
|
1026
|
-
config: config,
|
|
1027
|
-
lastCodeRun: action.codeIsStale ? null : code,
|
|
1028
|
-
edited: action.codeIsStale && code.trim().length > 0,
|
|
1029
|
-
});
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// If code is stale, we don't promote it to lastCodeRun
|
|
1033
|
-
const lastCodeRun = action.codeIsStale ? cell.lastCodeRun : code;
|
|
1034
|
-
|
|
1035
|
-
// Mark as edited if the code has changed
|
|
1036
|
-
const edited = lastCodeRun
|
|
1037
|
-
? lastCodeRun.trim() !== code.trim()
|
|
1038
|
-
: Boolean(code);
|
|
1039
|
-
|
|
1040
|
-
// No change
|
|
1041
|
-
if (cell.code.trim() === code.trim()) {
|
|
1042
|
-
return {
|
|
1043
|
-
...cell,
|
|
1044
|
-
code: code,
|
|
1045
|
-
edited,
|
|
1046
|
-
lastCodeRun,
|
|
1047
|
-
...(name !== undefined && { name }),
|
|
1048
|
-
...(config !== undefined && { config }),
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
// Update codemirror if mounted. RTC-backed cells sync via Loro; others
|
|
1053
|
-
// (e.g. scratchpad) still need an explicit editor update.
|
|
1054
|
-
if (!isRtcEnabled() || !canUseRtc(cellId)) {
|
|
1055
|
-
const cellHandle = nextState.cellHandles[cellId].current;
|
|
1056
|
-
if (cellHandle?.editorViewOrNull) {
|
|
1057
|
-
updateEditorCodeFromPython(cellHandle.editorViewOrNull, code);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
return {
|
|
1062
|
-
...cell,
|
|
1063
|
-
code: code,
|
|
1064
|
-
edited,
|
|
1065
|
-
lastCodeRun,
|
|
1066
|
-
...(name !== undefined && { name }),
|
|
1067
|
-
...(config !== undefined && { config }),
|
|
1068
|
-
};
|
|
1069
|
-
};
|
|
1070
|
-
|
|
1071
|
-
for (let i = 0; i < action.ids.length; i++) {
|
|
1072
|
-
const cellId = action.ids[i];
|
|
1073
|
-
const code = action.codes[i];
|
|
1074
|
-
if (cellId === undefined || code === undefined) {
|
|
1075
|
-
continue;
|
|
1076
|
-
}
|
|
1077
|
-
const name = action.names?.[i];
|
|
1078
|
-
const config = action.configs?.[i];
|
|
1079
|
-
nextState = {
|
|
1080
|
-
...nextState,
|
|
1081
|
-
cellData: {
|
|
1082
|
-
...nextState.cellData,
|
|
1083
|
-
[cellId]: cellReducer({
|
|
1084
|
-
cell: nextState.cellData[cellId],
|
|
1085
|
-
code,
|
|
1086
|
-
cellId,
|
|
1087
|
-
name,
|
|
1088
|
-
config,
|
|
1089
|
-
}),
|
|
1090
|
-
},
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
252
|
return nextState;
|
|
1095
253
|
},
|
|
1096
254
|
setStdinResponse: (
|
|
@@ -1114,6 +272,7 @@ const {
|
|
|
1114
272
|
mimetype: stdinOutput.mimetype,
|
|
1115
273
|
data: stdinOutput.data,
|
|
1116
274
|
timestamp: stdinOutput.timestamp,
|
|
275
|
+
id: stdinOutput.id,
|
|
1117
276
|
// An empty response resolves the prompt without retaining the secret.
|
|
1118
277
|
response: stdinOutput.mimetype === "text/password" ? "" : response,
|
|
1119
278
|
};
|
|
@@ -1126,155 +285,44 @@ const {
|
|
|
1126
285
|
},
|
|
1127
286
|
});
|
|
1128
287
|
},
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
// WASM has no server-side SessionView to replay outputs, so the
|
|
1133
|
-
// snapshot hydrated by notebookStateFromSession is the only source.
|
|
1134
|
-
const preserveSnapshot = isWasm();
|
|
1135
|
-
const runtimeFor = (cellId: CellId): CellRuntimeState => {
|
|
1136
|
-
if (!preserveSnapshot) {
|
|
1137
|
-
return createCellRuntimeState();
|
|
1138
|
-
}
|
|
1139
|
-
const prev = state.cellRuntime[cellId];
|
|
1140
|
-
const hasSnapshot =
|
|
1141
|
-
prev && (prev.output != null || prev.consoleOutputs.length > 0);
|
|
1142
|
-
return hasSnapshot ? prev : createCellRuntimeState();
|
|
1143
|
-
};
|
|
1144
|
-
const cellRuntime = Object.fromEntries(
|
|
1145
|
-
cells.map((cell) => [cell.id, runtimeFor(cell.id)]),
|
|
1146
|
-
);
|
|
1147
|
-
|
|
1148
|
-
return withScratchCell({
|
|
1149
|
-
...state,
|
|
1150
|
-
cellIds: MultiColumn.fromIdsAndColumns(
|
|
1151
|
-
cells.map((cell) => [cell.id, cell.config.column]),
|
|
1152
|
-
),
|
|
1153
|
-
cellData: cellData,
|
|
1154
|
-
cellRuntime: cellRuntime,
|
|
1155
|
-
cellHandles: Object.fromEntries(
|
|
1156
|
-
cells.map((cell) => [cell.id, createRef()]),
|
|
1157
|
-
),
|
|
1158
|
-
});
|
|
1159
|
-
},
|
|
1160
|
-
/**
|
|
1161
|
-
* Move focus to next cell
|
|
1162
|
-
*
|
|
1163
|
-
* Creates a new cell if the current cell is the last one in the array.
|
|
1164
|
-
*
|
|
1165
|
-
* If needed, scrolls newly created or focused cell into view.
|
|
1166
|
-
*
|
|
1167
|
-
* Replicates Shift+Enter functionality of Jupyter
|
|
1168
|
-
*/
|
|
1169
|
-
moveToNextCell: (
|
|
288
|
+
/** Record what the kernel last ran for each cell. */
|
|
289
|
+
setLastRun: (
|
|
1170
290
|
state,
|
|
1171
|
-
action: {
|
|
291
|
+
action: {
|
|
292
|
+
lastCodeRun: Record<CellId, string>;
|
|
293
|
+
lastExecutionTime: Record<CellId, number>;
|
|
294
|
+
},
|
|
1172
295
|
) => {
|
|
1173
|
-
const
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
const isPastLastCell = nextCellIndex === column.length;
|
|
1185
|
-
const isBeforeFirstCell = nextCellIndex === -1;
|
|
1186
|
-
|
|
1187
|
-
// Create a new cell at the end and set scrollKey to focus it
|
|
1188
|
-
if (isPastLastCell && !noCreate) {
|
|
1189
|
-
const newCellId = CellId.create();
|
|
1190
|
-
return {
|
|
1191
|
-
...state,
|
|
1192
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, nextCellIndex),
|
|
1193
|
-
cellData: {
|
|
1194
|
-
...state.cellData,
|
|
1195
|
-
[newCellId]: createCell({ id: newCellId }),
|
|
1196
|
-
},
|
|
1197
|
-
cellRuntime: {
|
|
1198
|
-
...state.cellRuntime,
|
|
1199
|
-
[newCellId]: createCellRuntimeState(),
|
|
1200
|
-
},
|
|
1201
|
-
cellHandles: {
|
|
1202
|
-
...state.cellHandles,
|
|
1203
|
-
[newCellId]: createRef(),
|
|
1204
|
-
},
|
|
1205
|
-
scrollKey: newCellId,
|
|
1206
|
-
};
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
if (isBeforeFirstCell && !noCreate) {
|
|
1210
|
-
const newCellId = CellId.create();
|
|
1211
|
-
return {
|
|
1212
|
-
...state,
|
|
1213
|
-
cellIds: state.cellIds.insertId(newCellId, column.id, 0),
|
|
1214
|
-
cellData: {
|
|
1215
|
-
...state.cellData,
|
|
1216
|
-
[newCellId]: createCell({ id: newCellId }),
|
|
1217
|
-
},
|
|
1218
|
-
cellRuntime: {
|
|
1219
|
-
...state.cellRuntime,
|
|
1220
|
-
[newCellId]: createCellRuntimeState(),
|
|
1221
|
-
},
|
|
1222
|
-
cellHandles: {
|
|
1223
|
-
...state.cellHandles,
|
|
1224
|
-
[newCellId]: createRef(),
|
|
1225
|
-
},
|
|
1226
|
-
scrollKey: newCellId,
|
|
1227
|
-
};
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
if ((isPastLastCell || isBeforeFirstCell) && noCreate) {
|
|
1231
|
-
// Trying to move past the last cell or before the first cell
|
|
1232
|
-
// with noCreate=true - do nothing
|
|
1233
|
-
return state;
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
if (nextCellIndex >= 0 && nextCellIndex < column.length) {
|
|
1237
|
-
// Move to valid cell within bounds
|
|
1238
|
-
const nextCellId = column.atOrThrow(nextCellIndex);
|
|
1239
|
-
// Just focus, no state change
|
|
1240
|
-
focusAndScrollCellIntoView({
|
|
1241
|
-
cellId: nextCellId,
|
|
1242
|
-
cell: state.cellHandles[nextCellId],
|
|
1243
|
-
isCodeHidden: isCellCodeHidden(state, nextCellId),
|
|
1244
|
-
codeFocus: before ? "bottom" : "top",
|
|
1245
|
-
variableName: undefined,
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
return state;
|
|
1250
|
-
},
|
|
1251
|
-
markTouched: (state, action: { cellId: CellId }) => {
|
|
1252
|
-
const { cellId } = action;
|
|
1253
|
-
|
|
1254
|
-
if (state.untouchedNewCells.has(cellId)) {
|
|
1255
|
-
const nextUntouchedNewCells = new Set(state.untouchedNewCells);
|
|
1256
|
-
nextUntouchedNewCells.delete(cellId);
|
|
1257
|
-
return {
|
|
1258
|
-
...state,
|
|
1259
|
-
untouchedNewCells: nextUntouchedNewCells,
|
|
296
|
+
const cellData = { ...state.cellData };
|
|
297
|
+
for (const cellId of state.cellIds) {
|
|
298
|
+
const cell = state.cellData[cellId];
|
|
299
|
+
const lastCodeRun = action.lastCodeRun[cellId] ?? null;
|
|
300
|
+
cellData[cellId] = {
|
|
301
|
+
...cell,
|
|
302
|
+
lastCodeRun,
|
|
303
|
+
lastExecutionTime: action.lastExecutionTime[cellId] ?? null,
|
|
304
|
+
// A cell the kernel never ran is not stale on load.
|
|
305
|
+
edited: lastCodeRun !== null && isEdited(lastCodeRun, cell.code),
|
|
1260
306
|
};
|
|
1261
307
|
}
|
|
1262
|
-
|
|
1263
|
-
return state;
|
|
308
|
+
return { ...state, cellData };
|
|
1264
309
|
},
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Start each cell's runtime over for a new kernel. WASM keeps the outputs
|
|
312
|
+
* its mount-time snapshot gave it.
|
|
313
|
+
*/
|
|
314
|
+
resetCellRuntimes: (state) => {
|
|
315
|
+
const preserveSnapshot = isWasm();
|
|
316
|
+
const cellRuntime = { ...state.cellRuntime };
|
|
317
|
+
for (const cellId of [...state.cellIds, SCRATCH_CELL_ID]) {
|
|
318
|
+
const previous = state.cellRuntime[cellId];
|
|
319
|
+
const hasSnapshot =
|
|
320
|
+
preserveSnapshot &&
|
|
321
|
+
previous !== undefined &&
|
|
322
|
+
(previous.output != null || previous.consoleOutputs.length > 0);
|
|
323
|
+
cellRuntime[cellId] = hasSnapshot ? previous : createCellRuntimeState();
|
|
1275
324
|
}
|
|
1276
|
-
|
|
1277
|
-
return state;
|
|
325
|
+
return { ...state, cellRuntime };
|
|
1278
326
|
},
|
|
1279
327
|
scrollToTarget: (state) => {
|
|
1280
328
|
// Scroll to the specified cell and clear the scroll key.
|
|
@@ -1283,16 +331,15 @@ const {
|
|
|
1283
331
|
return state;
|
|
1284
332
|
}
|
|
1285
333
|
|
|
1286
|
-
const
|
|
1287
|
-
const index = column.indexOfOrThrow(scrollKey);
|
|
1288
|
-
|
|
1289
|
-
const cellId =
|
|
1290
|
-
index === column.length - 1 ? column.last() : column.atOrThrow(index);
|
|
1291
|
-
|
|
334
|
+
const cellId = scrollKey;
|
|
1292
335
|
focusAndScrollCellIntoView({
|
|
1293
336
|
cellId: cellId,
|
|
1294
337
|
cell: state.cellHandles[cellId],
|
|
1295
|
-
isCodeHidden:
|
|
338
|
+
isCodeHidden: isCodeHidden(
|
|
339
|
+
state.cellData[cellId]?.config.hide_code,
|
|
340
|
+
store.get(shownHiddenCodeAtom),
|
|
341
|
+
cellId,
|
|
342
|
+
),
|
|
1296
343
|
codeFocus: undefined,
|
|
1297
344
|
variableName: undefined,
|
|
1298
345
|
});
|
|
@@ -1322,201 +369,6 @@ const {
|
|
|
1322
369
|
cellLogs: [],
|
|
1323
370
|
};
|
|
1324
371
|
},
|
|
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
372
|
clearCellOutput: (state, action: { cellId: CellId }) => {
|
|
1521
373
|
const { cellId } = action;
|
|
1522
374
|
return updateCellRuntimeState({
|
|
@@ -1545,7 +397,7 @@ const {
|
|
|
1545
397
|
},
|
|
1546
398
|
clearAllCellOutputs: (state) => {
|
|
1547
399
|
const newCellRuntime = { ...state.cellRuntime };
|
|
1548
|
-
for (const cellId of state.cellIds
|
|
400
|
+
for (const cellId of state.cellIds) {
|
|
1549
401
|
newCellRuntime[cellId] = {
|
|
1550
402
|
...newCellRuntime[cellId],
|
|
1551
403
|
output: null,
|
|
@@ -1557,58 +409,8 @@ const {
|
|
|
1557
409
|
cellRuntime: newCellRuntime,
|
|
1558
410
|
};
|
|
1559
411
|
},
|
|
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
412
|
});
|
|
1599
413
|
|
|
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
414
|
// Helper function to update a cell in the array
|
|
1613
415
|
function updateCellRuntimeState({
|
|
1614
416
|
state,
|
|
@@ -1656,43 +458,12 @@ function updateCellData({
|
|
|
1656
458
|
};
|
|
1657
459
|
}
|
|
1658
460
|
|
|
461
|
+
/** Each cell's config in order. The document's `column` configs are canonical. */
|
|
1659
462
|
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
|
-
});
|
|
463
|
+
return state.cellIds.map((cellId) => ({
|
|
464
|
+
...state.cellData[cellId].config,
|
|
465
|
+
column: state.cellData[cellId].config.column ?? null,
|
|
466
|
+
}));
|
|
1696
467
|
}
|
|
1697
468
|
|
|
1698
469
|
export {
|
|
@@ -1712,9 +483,7 @@ export const addLogs = imperativeActions.addLogs;
|
|
|
1712
483
|
|
|
1713
484
|
export const cellIdsAtom = atom((get) => get(notebookAtom).cellIds);
|
|
1714
485
|
|
|
1715
|
-
export const hasOnlyOneCellAtom = atom((get) =>
|
|
1716
|
-
get(cellIdsAtom).hasOnlyOneId(),
|
|
1717
|
-
);
|
|
486
|
+
export const hasOnlyOneCellAtom = atom((get) => get(cellIdsAtom).length === 1);
|
|
1718
487
|
|
|
1719
488
|
export const hasDisabledCellsAtom = atom(
|
|
1720
489
|
(get) => disabledCellIds(get(notebookAtom)).length > 0,
|
|
@@ -1732,7 +501,7 @@ export const needsRunAtom = atom((get) => notebookNeedsRun(get(notebookAtom)));
|
|
|
1732
501
|
|
|
1733
502
|
export const cellErrorsAtom = atom((get) => {
|
|
1734
503
|
const { cellIds, cellRuntime, cellData } = get(notebookAtom);
|
|
1735
|
-
const errors = cellIds
|
|
504
|
+
const errors = cellIds
|
|
1736
505
|
.map((cellId) => {
|
|
1737
506
|
const cell = cellRuntime[cellId];
|
|
1738
507
|
const { name } = cellData[cellId];
|
|
@@ -1760,11 +529,28 @@ export const cellErrorsAtom = atom((get) => {
|
|
|
1760
529
|
return errors;
|
|
1761
530
|
});
|
|
1762
531
|
|
|
532
|
+
/**
|
|
533
|
+
* The outline of each cell whose output has a heading. Compared by value, so
|
|
534
|
+
* readers are left alone by the runtime messages that change no heading.
|
|
535
|
+
*/
|
|
536
|
+
export const cellOutlinesAtom = createDeepEqualAtom(
|
|
537
|
+
atom((get) => {
|
|
538
|
+
const outlines: Partial<Record<CellId, Outline>> = {};
|
|
539
|
+
for (const [id, runtime] of Objects.entries(
|
|
540
|
+
get(notebookAtom).cellRuntime,
|
|
541
|
+
)) {
|
|
542
|
+
if (runtime.outline !== null && runtime.outline.items.length > 0) {
|
|
543
|
+
outlines[id] = runtime.outline;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return outlines;
|
|
547
|
+
}),
|
|
548
|
+
);
|
|
549
|
+
|
|
1763
550
|
export const notebookOutline = atom((get) => {
|
|
1764
|
-
const
|
|
1765
|
-
const
|
|
1766
|
-
|
|
1767
|
-
);
|
|
551
|
+
const cellIds = get(cellIdsAtom);
|
|
552
|
+
const cellRuntime = get(cellsRuntimeAtom);
|
|
553
|
+
const outlines = cellIds.map((cellId) => cellRuntime[cellId].outline);
|
|
1768
554
|
return mergeOutlines(outlines);
|
|
1769
555
|
});
|
|
1770
556
|
|
|
@@ -1774,7 +560,7 @@ export const cellIdToNamesMap = createDeepEqualAtom(
|
|
|
1774
560
|
atom((get) => {
|
|
1775
561
|
const { cellIds, cellData } = get(notebookAtom);
|
|
1776
562
|
const names: Record<CellId, string | undefined> = Objects.fromEntries(
|
|
1777
|
-
cellIds.
|
|
563
|
+
cellIds.map((cellId) => [cellId, cellData[cellId]?.name]),
|
|
1778
564
|
);
|
|
1779
565
|
return names;
|
|
1780
566
|
}),
|
|
@@ -1831,12 +617,12 @@ export const getCells = () => store.get(notebookAtom).cellIds;
|
|
|
1831
617
|
*/
|
|
1832
618
|
export const getCellNames = () => {
|
|
1833
619
|
const { cellIds, cellData } = store.get(notebookAtom);
|
|
1834
|
-
return cellIds.
|
|
620
|
+
return cellIds.map((id) => cellData[id]?.name).filter(Boolean);
|
|
1835
621
|
};
|
|
1836
622
|
|
|
1837
623
|
const cellDataAtoms = splitAtom(
|
|
1838
624
|
selectAtom(notebookAtom, (cells) =>
|
|
1839
|
-
cells.cellIds.
|
|
625
|
+
cells.cellIds.map((id) => cells.cellData[id]),
|
|
1840
626
|
),
|
|
1841
627
|
);
|
|
1842
628
|
export const useCellDataAtoms = () => useAtom(cellDataAtoms);
|
|
@@ -1856,16 +642,7 @@ export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
|
1856
642
|
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
1857
643
|
);
|
|
1858
644
|
|
|
1859
|
-
export const
|
|
1860
|
-
(get) => get(notebookAtom).cellIds.colLength,
|
|
1861
|
-
);
|
|
1862
|
-
export const hasCellsAtom = atom(
|
|
1863
|
-
(get) => get(notebookAtom).cellIds.idLength > 0,
|
|
1864
|
-
);
|
|
1865
|
-
export const columnIdsAtom = atom((get) =>
|
|
1866
|
-
get(notebookAtom).cellIds.getColumnIds(),
|
|
1867
|
-
);
|
|
1868
|
-
|
|
645
|
+
export const hasCellsAtom = atom((get) => get(notebookAtom).cellIds.length > 0);
|
|
1869
646
|
export const cellDataAtom = atomFamily((cellId: CellId) =>
|
|
1870
647
|
atom((get) => get(notebookAtom).cellData[cellId]),
|
|
1871
648
|
);
|
|
@@ -1906,7 +683,7 @@ export const useCellHandle = (cellId: CellId) =>
|
|
|
1906
683
|
*/
|
|
1907
684
|
export const getAllEditorViews = () => {
|
|
1908
685
|
const { cellIds, cellHandles } = store.get(notebookAtom);
|
|
1909
|
-
return cellIds
|
|
686
|
+
return cellIds
|
|
1910
687
|
.map((cellId) => cellHandles[cellId]?.current?.editorViewOrNull)
|
|
1911
688
|
.filter(Boolean);
|
|
1912
689
|
};
|
|
@@ -1930,16 +707,10 @@ export function flattenTopLevelNotebookCells(
|
|
|
1930
707
|
state: NotebookState,
|
|
1931
708
|
): (CellData & CellRuntimeState)[] {
|
|
1932
709
|
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));
|
|
710
|
+
return cellIds.map((cellId) => ({
|
|
711
|
+
...cellData[cellId],
|
|
712
|
+
...cellRuntime[cellId],
|
|
713
|
+
}));
|
|
1943
714
|
}
|
|
1944
715
|
|
|
1945
716
|
export function createTracebackInfoAtom(
|
|
@@ -2001,20 +772,13 @@ export function createTracebackInfoAtom(
|
|
|
2001
772
|
});
|
|
2002
773
|
}
|
|
2003
774
|
|
|
2004
|
-
/**
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
*/
|
|
2008
|
-
export function useCellActions(
|
|
2009
|
-
options: { skipMiddleware?: boolean } = {},
|
|
2010
|
-
): CellActions {
|
|
2011
|
-
return useActions(options);
|
|
775
|
+
/** The reducer's actions. Components use `useCellActions` from `./actions`. */
|
|
776
|
+
export function useReducerActions(): ReducerCellActions {
|
|
777
|
+
return useActions();
|
|
2012
778
|
}
|
|
2013
779
|
|
|
2014
|
-
/**
|
|
2015
|
-
|
|
2016
|
-
*/
|
|
2017
|
-
export type CellActions = ReturnType<typeof createActions>;
|
|
780
|
+
/** The actions the reducer still handles. */
|
|
781
|
+
export type ReducerCellActions = ReturnType<typeof createActions>;
|
|
2018
782
|
|
|
2019
783
|
/**
|
|
2020
784
|
* This is exported for testing purposes only.
|
|
@@ -2023,7 +787,6 @@ export const exportedForTesting = {
|
|
|
2023
787
|
reducer,
|
|
2024
788
|
createActions,
|
|
2025
789
|
initialNotebookState,
|
|
2026
|
-
isCellCodeHidden,
|
|
2027
790
|
// Export atom families for testing cleanup
|
|
2028
791
|
cellDataAtom,
|
|
2029
792
|
cellRuntimeAtom,
|