@marimo-team/frontend 0.24.1-dev99 → 0.24.2-dev129
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/assets/{CellStatus-wvvZkEPY.js → CellStatus-LoTwk7fR.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-Dkqk66Mv.js → ConnectedDataExplorerComponent-DW6cJ-Lr.js} +1 -1
- package/dist/assets/{ErrorBoundary-npvnLp9x.js → ErrorBoundary-CDVGFYfr.js} +1 -1
- package/dist/assets/JsonOutput-CzIGPEZQ.js +50 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-zSwE3dvU.js → LazyAnyLanguageCodeMirror-LboTfNDv.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-CeUo5oka.js → MarimoErrorOutput-DqpoYOvw.js} +1 -1
- package/dist/assets/RenderHTML-DwhMAd9l.js +1 -0
- package/dist/assets/{RunButton-BaV8A-z4.js → RunButton-BlpbweyH.js} +1 -1
- package/dist/assets/{VisuallyHidden-SChAyKIQ.js → VisuallyHidden-CBMDmozt.js} +1 -1
- package/dist/assets/{add-cell-with-ai-DoLkfzYn.js → add-cell-with-ai-R-3DS79K.js} +1 -1
- package/dist/assets/{add-connection-dialog-C1IF1nR0.js → add-connection-dialog-BGfpw5lC.js} +1 -1
- package/dist/assets/{agent-panel-CG154QrU.js → agent-panel-Cgt_K0tD.js} +1 -1
- package/dist/assets/ai-model-dropdown-DCmiuk7x.js +3 -0
- package/dist/assets/alert-dialog-CA-2mBs3.js +11 -0
- package/dist/assets/any-language-editor-DflLjPSQ.js +1 -0
- package/dist/assets/{app-config-button-ktBH1pEB.js → app-config-button-DUJC6b6x.js} +1 -1
- package/dist/assets/badge-BSgtkC2e.js +1 -0
- package/dist/assets/{blob-DVtvZmWH.js → blob-B2d_dHwI.js} +1 -1
- package/dist/assets/button-Dh8EwhsF.js +1 -0
- package/dist/assets/{cache-panel-C7jsiqCa.js → cache-panel-DqgtC98s.js} +1 -1
- package/dist/assets/{capabilities-LWzb3E3M.js → capabilities-D8kPgMKr.js} +1 -1
- package/dist/assets/{cell-editor-DoDqaCZp.js → cell-editor-Dw09J9yD.js} +6 -6
- package/dist/assets/{cell-link-Dqqt6Rgs.js → cell-link-6burT2XF.js} +1 -1
- package/dist/assets/{cells-D4RwofRx.js → cells-Cp-G34Rz.js} +56 -56
- package/dist/assets/{chat-display-COmzHgx5.js → chat-display-Bu405iyc.js} +1 -1
- package/dist/assets/{chat-panel-B2tyEfGW.js → chat-panel-BlUwNY5j.js} +1 -1
- package/dist/assets/{chat-ui-B5bsr-7V.js → chat-ui-DGiVDzNh.js} +1 -1
- package/dist/assets/{circle--ysFeW9z.js → circle-ByJdIf5p.js} +1 -1
- package/dist/assets/{column-preview-CW5DPFvy.js → column-preview-riSXbYe_.js} +1 -1
- package/dist/assets/{command-palette-B9dyvMvJ.js → command-palette-CCVzJcyf.js} +1 -1
- package/dist/assets/{common-CC3tuCpi.js → common-CHR7w7aQ.js} +1 -1
- package/dist/assets/{components-D02ZZZMP.js → components-C7mWrmXr.js} +1 -1
- package/dist/assets/{components-CBlGIIAX.js → components-DUYCXngU.js} +1 -1
- package/dist/assets/config-B-r81uZ6.js +1 -0
- package/dist/assets/{config-D4frVGQ4.js → config-BlNM0caL.js} +1 -1
- package/dist/assets/{copy-Cg05mM3C.js → copy-DlEomWzI.js} +1 -1
- package/dist/assets/{copy-icon-CRxVZTJ9.js → copy-icon-z8fuTE3w.js} +1 -1
- package/dist/assets/{createReducer-Bq-nQJiK.js → createReducer-B_XmHROl.js} +1 -1
- package/dist/assets/{datasource-Do8f2hFf.js → datasource-DrODSIs0.js} +1 -1
- package/dist/assets/{dates-DK5JikJo.js → dates-B58T85Jq.js} +1 -1
- package/dist/assets/dependency-graph-panel-AY5BEVH2.js +5 -0
- package/dist/assets/{dist-7qdHLg-L.js → dist-B0RXffUm.js} +1 -1
- package/dist/assets/dist-B0qYy1Ye.js +1 -0
- package/dist/assets/{dist-B97dKQGP.js → dist-B8pdsUrS.js} +1 -1
- package/dist/assets/{dist-BcfF-rkl.js → dist-BF7Lrekv.js} +1 -1
- package/dist/assets/dist-BL8RjfvI.js +1 -0
- package/dist/assets/dist-BVZxge7j.js +1 -0
- package/dist/assets/{dist-fxnYzq-R.js → dist-BaRNSaca.js} +1 -1
- package/dist/assets/dist-Bk2yQtw4.js +1 -0
- package/dist/assets/dist-BsfiiKoy.js +1 -0
- package/dist/assets/dist-BskmVd3B.js +1 -0
- package/dist/assets/{dist-DL1Thauf.js → dist-Bsu3h9O7.js} +1 -1
- package/dist/assets/{dist-PIe1xcZo.js → dist-BtC9ym6k.js} +7 -7
- package/dist/assets/{dist-DeuWxYVk.js → dist-Bv0S1RlZ.js} +1 -1
- package/dist/assets/{dist-CidBzUqR.js → dist-C--ZICxQ.js} +1 -1
- package/dist/assets/dist-C-2fD3XY.js +1 -0
- package/dist/assets/{dist-DzAWvPVK.js → dist-CKUpxYGQ.js} +1 -1
- package/dist/assets/dist-CMFMfBm1.js +1 -0
- package/dist/assets/dist-CZNULd6Z.js +2 -0
- package/dist/assets/dist-CjFduPiC.js +1 -0
- package/dist/assets/{dist-DoAjHgMj.js → dist-CmImLjus.js} +1 -1
- package/dist/assets/{dist-BKx0MLbb.js → dist-Cq8NOszX.js} +1 -1
- package/dist/assets/{dist-DCc0VfiO.js → dist-Cx4BE7jC.js} +3 -3
- package/dist/assets/dist-D45ScydS.js +1 -0
- package/dist/assets/dist-D6dg87r7.js +1 -0
- package/dist/assets/dist-DEjfQLz0.js +1 -0
- package/dist/assets/{dist-BcYW-EJk.js → dist-DJOWOALB.js} +1 -1
- package/dist/assets/{dist-CxxZaSme.js → dist-DPoYlxSC.js} +1 -1
- package/dist/assets/dist-DR-Y-nl3.js +1 -0
- package/dist/assets/dist-Dahlp9JQ.js +1 -0
- package/dist/assets/{dist-DIkuvChK.js → dist-Db-HC93w.js} +1 -1
- package/dist/assets/{dist-DTM7BAUu.js → dist-DdOlZ6mj.js} +1 -1
- package/dist/assets/{dist-Dz_04liz.js → dist-DiYjQAhI.js} +1 -1
- package/dist/assets/{dist-BO5c5n_b.js → dist-DkPPv0FB.js} +1 -1
- package/dist/assets/{dist-DkCO0b-0.js → dist-DmGtPaVM.js} +1 -1
- package/dist/assets/{dist-CXmhxecl.js → dist-DnxYYyU7.js} +1 -1
- package/dist/assets/{dist-CO1Hfv5H.js → dist-Dw9YRsCU.js} +1 -1
- package/dist/assets/dist-Dwx3KdUP.js +1 -0
- package/dist/assets/{dist-BgL43w5r.js → dist-DzCQtGkt.js} +1 -1
- package/dist/assets/dist-JweaDt6P.js +1 -0
- package/dist/assets/{dist-Dbu5sPgR.js → dist-gELFCfHH.js} +1 -1
- package/dist/assets/dist-kGDJ0AWF.js +1 -0
- package/dist/assets/{dist-Cqm1W-Zm.js → dist-kaLvV_d4.js} +1 -1
- package/dist/assets/{dist-CEeRVpMD.js → dist-qvk3g06H.js} +1 -1
- package/dist/assets/dist-wCw2twuB.js +1 -0
- package/dist/assets/dist-wF42tUcr.js +1 -0
- package/dist/assets/dist-wY2yia-1.js +3 -0
- package/dist/assets/{documentation-panel-DvHjxlli.js → documentation-panel-CaJF7e-j.js} +1 -1
- package/dist/assets/{download-BP8MrprC.js → download-DMxOzI7b.js} +1 -1
- package/dist/assets/dropdown-menu-C40jM9o4.js +1 -0
- package/dist/assets/{edit-page-71cK-Nhe.js → edit-page-Vqd9NedM.js} +6 -6
- package/dist/assets/{error-banner-BYN8YUMe.js → error-banner-Dw5YY9wq.js} +1 -1
- package/dist/assets/{error-entries-DOZ1u97X.js → error-entries-Cv2m1yhc.js} +1 -1
- package/dist/assets/{error-panel-CINcf76Z.js → error-panel-Bhlvt6_H.js} +1 -1
- package/dist/assets/{es-BuMFDpR4.js → es-CrFhA96G.js} +1 -1
- package/dist/assets/{esm-Dw0vvSg2.js → esm-BHMOvJzM.js} +1 -1
- package/dist/assets/{esm-BGpfQNhD.js → esm-DmqQGMel.js} +1 -1
- package/dist/assets/file-explorer-panel-6HvNfCrJ.js +1 -0
- package/dist/assets/{file-icons-DgKj9mrV.js → file-icons-DdGYuADJ.js} +1 -1
- package/dist/assets/file-name-input-K4MKESI_.js +3 -0
- package/dist/assets/{floating-outline-CRXIsrPm.js → floating-outline-DaUHnl_e.js} +1 -1
- package/dist/assets/{formats-DSzGCKeO.js → formats-C6s96nu2.js} +1 -1
- package/dist/assets/{formatting-BJlT1s_3.js → formatting-BWZH2nBg.js} +1 -1
- package/dist/assets/{fullscreen-0EEPR7uc.js → fullscreen-BH2jz-F4.js} +5 -5
- package/dist/assets/{gallery-page-TqnFYECu.js → gallery-page-C3pBpHlY.js} +1 -1
- package/dist/assets/{glide-data-editor-DcY3nXI8.js → glide-data-editor-sICUMEhk.js} +1 -1
- package/dist/assets/{glide-utils-CR1sWLZU.js → glide-utils-UGsrRHYj.js} +1 -1
- package/dist/assets/home-page-BLd6rnbk.js +4 -0
- package/dist/assets/{html-to-image-DMn_7CCA.js → html-to-image-D6GUC5q6.js} +1 -1
- package/dist/assets/index-BGT7have.css +2 -0
- package/dist/assets/index-ipFYAeCF.js +29 -0
- package/dist/assets/{input-Daz6sk8l.js → input-DEbY281O.js} +2 -2
- package/dist/assets/{kiosk-mode-CzGt3mc2.js → kiosk-mode-mxgb5lWf.js} +1 -1
- package/dist/assets/{layout-KJMQADEj.js → layout-DWnrxIo2.js} +5 -5
- package/dist/assets/links-DLvOXyO_.js +1 -0
- package/dist/assets/{logs-panel-DFibPeCT.js → logs-panel-BGS2v3ba.js} +1 -1
- package/dist/assets/lua-1tNpM92n.js +1 -0
- package/dist/assets/{lua-CRIS5afH.js → lua-DXBxhmso.js} +1 -1
- package/dist/assets/{markdown-renderer-CdZX2MvM.js → markdown-renderer-BZKlbm2Q.js} +1 -1
- package/dist/assets/menu-items-BSRA2YI9.js +1 -0
- package/dist/assets/{mermaid-CeseGGnS.js → mermaid-l6lQkCib.js} +1 -1
- package/dist/assets/{name-cell-input-B-d5Jwh4.js → name-cell-input-BMCdK-el.js} +1 -1
- package/dist/assets/{numbers-DKurV_vq.js → numbers-Bc-r3jsC.js} +1 -1
- package/dist/assets/{outline-panel-D2Wk10hY.js → outline-panel-Dr5u73V6.js} +1 -1
- package/dist/assets/{packages-panel-CQsbxIlG.js → packages-panel-BdpRg9tX.js} +1 -1
- package/dist/assets/{pair-with-agent-modal-CNxmIMFM.js → pair-with-agent-modal-CbUFKJHP.js} +1 -1
- package/dist/assets/{panel-accordion-state-D6-FMXE2.js → panel-accordion-state-DjUTN7i5.js} +1 -1
- package/dist/assets/{panels-BgcK_4M7.js → panels-CWn0Yh1D.js} +1 -1
- package/dist/assets/process-output-Ck7-P_xp.js +1 -0
- package/dist/assets/{readonly-code-display-BvqLeUsJ.js → readonly-code-display--S2daDa6.js} +1 -1
- package/dist/assets/{readonly-python-code-GSN4D4sb.js → readonly-python-code-DpIyjHqY.js} +1 -1
- package/dist/assets/{renderShortcut-DK_OucLT.js → renderShortcut-X-CJUSM8.js} +1 -1
- package/dist/assets/{reveal-component-u9ED2diI.js → reveal-component-nZIAapoD.js} +1 -1
- package/dist/assets/{run-page-U5iuhyz8.js → run-page-9pl8qhQR.js} +1 -1
- package/dist/assets/{runs-BQTlv6Ja.js → runs-euHSzlw_.js} +1 -1
- package/dist/assets/{scratchpad-panel--YOR0kUB.js → scratchpad-panel-BleGt2KM.js} +1 -1
- package/dist/assets/{scroll-to-bottom-button-xua0e9rA.js → scroll-to-bottom-button-DufiYUD7.js} +1 -1
- package/dist/assets/{secrets-panel-CZPbFAZH.js → secrets-panel-D3BpDIgg.js} +1 -1
- package/dist/assets/select-nLt2y0Sw.js +1 -0
- package/dist/assets/{session-CEdta5_Q.js → session-Sz5nSFku.js} +1 -1
- package/dist/assets/session-panel-DRGPlL5J.js +1 -0
- package/dist/assets/{share-C2MPy_VX.js → share-CPtBiNgr.js} +1 -1
- package/dist/assets/{skeleton-CsceCAjw.js → skeleton-BKeh8hf3.js} +1 -1
- package/dist/assets/{snippets-panel-BxwHsPmW.js → snippets-panel-D5yy7kj0.js} +1 -1
- package/dist/assets/{spec-CUFquO6R.js → spec-DKsAmLTi.js} +1 -1
- package/dist/assets/{state-BqrF--O0.js → state-B6AklCzD.js} +1 -1
- package/dist/assets/{state-C2c3_VuY.js → state-B8XRqyFg.js} +1 -1
- package/dist/assets/{state-CHplO0zn.js → state-Di9TbuV9.js} +1 -1
- package/dist/assets/{strings-CpYReX2Q.js → strings-CReV1AYG.js} +1 -1
- package/dist/assets/{swiper-component-Bot7ehYH.js → swiper-component-5Kdi1-Gn.js} +1 -1
- package/dist/assets/{switch-CtH5Ct94.js → switch-DjXr9Y9D.js} +1 -1
- package/dist/assets/{tabs-c6mpccpH.js → tabs-Cy1qXLzH.js} +1 -1
- package/dist/assets/{terminal-C73iz1fU.js → terminal-CQAFGBfN.js} +1 -1
- package/dist/assets/{tooltip-Cwltdez8.js → tooltip-BG35uS_N.js} +1 -1
- package/dist/assets/{tooltip-D7dq6bnc.js → tooltip-BUtPzKB4.js} +1 -1
- package/dist/assets/{tracing-Dhq121dR.js → tracing-DNk3gmWv.js} +1 -1
- package/dist/assets/{tracing-panel-IKt1933_.js → tracing-panel-Yqazr6w_.js} +2 -2
- package/dist/assets/{tree-actions-DIfWonCA.js → tree-actions-CG5g7aUQ.js} +1 -1
- package/dist/assets/{useAddCell-BYrVaYfZ.js → useAddCell-DdB_uBif.js} +1 -1
- package/dist/assets/{useBoolean-ZU5StAbr.js → useBoolean-BXC4CItZ.js} +1 -1
- package/dist/assets/{useCellActionButton-DbXDs0MA.js → useCellActionButton-B31neI3m.js} +1 -1
- package/dist/assets/{useDebounce-Dulm61-t.js → useDebounce-DgpSQhrP.js} +1 -1
- package/dist/assets/{useDeleteCell-Wgcl3CRG.js → useDeleteCell-Bz49_cFj.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-C5AU8GKL.js → useDependencyPanelTab-C_ps0r--.js} +1 -1
- package/dist/assets/{useEventListener-D27Dii_l.js → useEventListener-92uWqz-P.js} +1 -1
- package/dist/assets/{useIframeCapabilities-DEpTCh1Q.js → useIframeCapabilities-C7Di8f2y.js} +1 -1
- package/dist/assets/{useInstallPackage-u7d0wo79.js → useInstallPackage-DsD08SLK.js} +1 -1
- package/dist/assets/{useInterval-B1_J4wdT.js → useInterval-B4v7_zd0.js} +1 -1
- package/dist/assets/{useNotebookActions-FuMERtHq.js → useNotebookActions-CQtbk9CB.js} +2 -2
- package/dist/assets/{useRunCells-DTdMRbkE.js → useRunCells-CX7oW5zy.js} +1 -1
- package/dist/assets/{useSplitCell-2z0zEB8X.js → useSplitCell-Dy2_DmJR.js} +1 -1
- package/dist/assets/{useTheme-CF-zG9YH.js → useTheme-C-ri8BtY.js} +1 -1
- package/dist/assets/utils-D5Ywm7-q.js +1 -0
- package/dist/assets/{vega-component-BSXJcTJb.js → vega-component-C7TCzyaU.js} +1 -1
- package/dist/assets/write-secret-modal-D6zoZgLY.js +2 -0
- package/dist/index.html +73 -73
- package/package.json +26 -26
- package/src/components/ai/ai-provider-icon.tsx +2 -2
- package/src/components/ai/ai-utils.ts +1 -1
- package/src/components/app-config/ai-config.tsx +33 -37
- package/src/components/app-config/user-config-form.tsx +1 -1
- package/src/components/data-table/__tests__/column-explorer.test.tsx +64 -4
- package/src/components/data-table/__tests__/column-visibility-dropdown.test.tsx +137 -4
- package/src/components/data-table/__tests__/url-detector.test.tsx +1 -1
- package/src/components/data-table/__tests__/useColumnVisibility.test.ts +153 -1
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +54 -25
- package/src/components/data-table/column-visibility-dropdown.tsx +62 -14
- package/src/components/data-table/date-popover.tsx +2 -1
- package/src/components/data-table/hooks/use-column-visibility.ts +76 -0
- package/src/components/data-table/renderers.tsx +4 -8
- package/src/components/data-table/show-only-column-button.tsx +58 -0
- package/src/components/dependency-graph/__tests__/elements.test.ts +151 -0
- package/src/components/dependency-graph/custom-edge.tsx +68 -0
- package/src/components/dependency-graph/custom-node.tsx +54 -26
- package/src/components/dependency-graph/dependency-graph-tree.tsx +110 -21
- package/src/components/dependency-graph/elements.ts +225 -31
- package/src/components/dependency-graph/panels.tsx +23 -2
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +78 -0
- package/src/components/dependency-graph/utils/layout.ts +108 -18
- package/src/components/editor/Output.tsx +40 -0
- package/src/components/editor/__tests__/Output.test.tsx +85 -2
- package/src/components/editor/connections/secret-combobox.tsx +3 -1
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +832 -0
- package/src/components/editor/file-tree/__tests__/file-viewer.test.tsx +27 -0
- package/src/components/editor/file-tree/__tests__/requesting-tree.test.ts +130 -0
- package/src/components/editor/file-tree/file-browser-row.tsx +82 -0
- package/src/components/editor/file-tree/file-explorer.tsx +377 -159
- package/src/components/editor/file-tree/file-operations.tsx +1 -1
- package/src/components/editor/file-tree/file-search-results.tsx +142 -0
- package/src/components/editor/file-tree/file-tree-row.tsx +40 -0
- package/src/components/editor/file-tree/file-viewer.tsx +2 -1
- package/src/components/editor/file-tree/renderers.tsx +4 -2
- package/src/components/editor/file-tree/requesting-tree.tsx +162 -32
- package/src/components/editor/file-tree/use-file-search.ts +142 -0
- package/src/components/editor/file-tree/use-hover-expand.ts +34 -0
- package/src/components/editor/navigation/__tests__/navigation.test.ts +30 -0
- package/src/components/editor/navigation/navigation.ts +20 -0
- package/src/components/forms/form.tsx +6 -4
- package/src/components/home/components.tsx +1 -0
- package/src/components/static-html/share-modal.tsx +3 -2
- package/src/components/ui/__tests__/badge.test.ts +63 -0
- package/src/components/ui/__tests__/button.test.ts +19 -0
- package/src/components/ui/__tests__/fullscreen.test.tsx +88 -0
- package/src/components/ui/__tests__/menu-items.test.ts +31 -0
- package/src/components/ui/badge.tsx +9 -7
- package/src/components/ui/button.tsx +1 -0
- package/src/components/ui/combobox.tsx +1 -1
- package/src/components/ui/date-input.tsx +1 -1
- package/src/components/ui/dialog.tsx +3 -1
- package/src/components/ui/fullscreen.tsx +43 -1
- package/src/components/ui/input.tsx +5 -1
- package/src/components/ui/links.tsx +2 -1
- package/src/components/ui/menu-items.tsx +9 -9
- package/src/components/ui/native-select.tsx +2 -2
- package/src/components/ui/navigation.tsx +1 -1
- package/src/components/ui/range-slider.tsx +5 -3
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/toast.tsx +8 -5
- package/src/components/ui/toaster.tsx +2 -2
- package/src/core/ai/ids/__tests__/ids.test.ts +0 -8
- package/src/core/ai/ids/ids.ts +1 -1
- package/src/core/cells/__tests__/add-missing-import.test.ts +20 -0
- package/src/core/codemirror/language/__tests__/utils.test.ts +1 -1
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/hotkeys/hotkeys.ts +5 -0
- package/src/core/network/__tests__/requests-toasting.test.tsx +14 -0
- package/src/core/network/requests-toasting.tsx +1 -1
- package/src/css/globals.css +28 -0
- package/src/hooks/useEventListener.ts +1 -1
- package/src/plugins/core/RenderHTML.tsx +6 -4
- package/src/plugins/impl/MatrixPlugin.tsx +1 -1
- package/src/plugins/impl/code/any-language-editor.tsx +7 -4
- package/src/plugins/impl/data-frames/__tests__/schema.test.ts +34 -1
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +25 -25
- package/src/plugins/impl/data-frames/schema.ts +5 -11
- package/src/plugins/impl/panel/__tests__/utils.test.ts +4 -4
- package/src/plugins/impl/vega/__tests__/vega.test.ts +1 -1
- package/src/stories/cell.stories.tsx +15 -11
- package/src/utils/__tests__/events.test.ts +1 -1
- package/dist/assets/JsonOutput-CRLQQVKf.js +0 -50
- package/dist/assets/RenderHTML-YkwVPe9V.js +0 -1
- package/dist/assets/ai-model-dropdown-CrSrb8Zz.js +0 -3
- package/dist/assets/alert-dialog-BVi_GyOB.js +0 -11
- package/dist/assets/any-language-editor-BL8H-DwB.js +0 -1
- package/dist/assets/badge-D_-uqy2N.js +0 -1
- package/dist/assets/button-Btj6GXNy.js +0 -1
- package/dist/assets/config-ycxJQP2b.js +0 -1
- package/dist/assets/dependency-graph-panel-Dg-tUB9T.js +0 -5
- package/dist/assets/dist-2oRmY-BC.js +0 -1
- package/dist/assets/dist-8lhGoJ54.js +0 -3
- package/dist/assets/dist-B4QaGCvF.js +0 -1
- package/dist/assets/dist-B_ABJVTW.js +0 -1
- package/dist/assets/dist-Bke0Ybxy.js +0 -1
- package/dist/assets/dist-Bw8CAY5i.js +0 -1
- package/dist/assets/dist-BwmO3SSk.js +0 -1
- package/dist/assets/dist-C3KxgR0m.js +0 -1
- package/dist/assets/dist-CLE562nZ.js +0 -1
- package/dist/assets/dist-CLi0j3bw.js +0 -1
- package/dist/assets/dist-CMIyXejt.js +0 -1
- package/dist/assets/dist-CbQrIaPV.js +0 -2
- package/dist/assets/dist-CpgfIIzU.js +0 -1
- package/dist/assets/dist-D7aYPqs9.js +0 -1
- package/dist/assets/dist-DKCF5R0T.js +0 -1
- package/dist/assets/dist-DbFa9cik.js +0 -1
- package/dist/assets/dist-DdPuhs_-.js +0 -1
- package/dist/assets/dist-DkfdZExz.js +0 -1
- package/dist/assets/dist-hOh6JBwi.js +0 -1
- package/dist/assets/dist-mY1j_5eA.js +0 -1
- package/dist/assets/dist-tg3aVnpD.js +0 -1
- package/dist/assets/dropdown-menu-CqNabM1f.js +0 -1
- package/dist/assets/file-explorer-panel-cflxW8a7.js +0 -1
- package/dist/assets/file-name-input-CQF4Ovwx.js +0 -3
- package/dist/assets/home-page-DPRHPAQM.js +0 -4
- package/dist/assets/index-BkIXRAbi.css +0 -2
- package/dist/assets/index-p49fbIlR.js +0 -29
- package/dist/assets/links-DPh7yoP-.js +0 -1
- package/dist/assets/lua-_4wuYo1j.js +0 -1
- package/dist/assets/menu-items-BSVrMleU.js +0 -1
- package/dist/assets/process-output-DvTtgoMs.js +0 -1
- package/dist/assets/select-czJLm6jf.js +0 -1
- package/dist/assets/session-panel-C_N3WGWQ.js +0 -1
- package/dist/assets/utils-CWSZQEjr.js +0 -1
- package/dist/assets/write-secret-modal-lNU_7c2x.js +0 -2
|
@@ -71,11 +71,7 @@ export function renderTableHeader<TData>(
|
|
|
71
71
|
{renderHeaderGroup(table.getCenterHeaderGroups())}
|
|
72
72
|
{renderHeaderGroup(table.getRightHeaderGroups())}
|
|
73
73
|
{table.getAllColumns().length <= AUTO_WIDTH_MAX_COLUMNS && (
|
|
74
|
-
<th
|
|
75
|
-
className="w-full border-0"
|
|
76
|
-
aria-hidden="true"
|
|
77
|
-
role="presentation"
|
|
78
|
-
/>
|
|
74
|
+
<th className="w-full border-0" aria-hidden="true" />
|
|
79
75
|
)}
|
|
80
76
|
</TableRow>
|
|
81
77
|
</TableHeader>
|
|
@@ -217,7 +213,7 @@ export const DataTableBody = <TData,>({
|
|
|
217
213
|
{renderCells(row.getCenterVisibleCells())}
|
|
218
214
|
{renderCells(row.getRightVisibleCells())}
|
|
219
215
|
{columns.length <= AUTO_WIDTH_MAX_COLUMNS && (
|
|
220
|
-
<td className="border-0" aria-hidden="true"
|
|
216
|
+
<td className="border-0" aria-hidden="true" />
|
|
221
217
|
)}
|
|
222
218
|
</TableRow>
|
|
223
219
|
);
|
|
@@ -247,7 +243,7 @@ export const DataTableBody = <TData,>({
|
|
|
247
243
|
data-virtual-spacer=""
|
|
248
244
|
style={{ height: virtualItems[0].start }}
|
|
249
245
|
>
|
|
250
|
-
<td colSpan={totalColSpan} />
|
|
246
|
+
<td aria-hidden="true" colSpan={totalColSpan} />
|
|
251
247
|
</tr>
|
|
252
248
|
)}
|
|
253
249
|
{virtualItems.map((vItem) => renderRow(rows[vItem.index]))}
|
|
@@ -258,7 +254,7 @@ export const DataTableBody = <TData,>({
|
|
|
258
254
|
height: totalSize - (virtualItems.at(-1)?.end ?? totalSize),
|
|
259
255
|
}}
|
|
260
256
|
>
|
|
261
|
-
<td colSpan={totalColSpan} />
|
|
257
|
+
<td aria-hidden="true" colSpan={totalColSpan} />
|
|
262
258
|
</tr>
|
|
263
259
|
)}
|
|
264
260
|
</>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
"use no memo";
|
|
3
|
+
|
|
4
|
+
import type { Table } from "@tanstack/react-table";
|
|
5
|
+
import { ScanEyeIcon } from "lucide-react";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
import { Tooltip } from "@/components/ui/tooltip";
|
|
8
|
+
import { cn } from "@/utils/cn";
|
|
9
|
+
import { applyShowOnlyColumns } from "./hooks/use-column-visibility";
|
|
10
|
+
|
|
11
|
+
export const SHOW_ONLY_COLUMN_LABEL = "Show only this column";
|
|
12
|
+
|
|
13
|
+
interface ShowOnlyColumnButtonProps<TData> {
|
|
14
|
+
table: Table<TData>;
|
|
15
|
+
columnIds: string[];
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
iconClassName?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function ShowOnlyColumnButton<TData>({
|
|
22
|
+
table,
|
|
23
|
+
columnIds,
|
|
24
|
+
disabled,
|
|
25
|
+
className,
|
|
26
|
+
iconClassName = "h-3 w-3",
|
|
27
|
+
}: ShowOnlyColumnButtonProps<TData>) {
|
|
28
|
+
return (
|
|
29
|
+
<Tooltip content={SHOW_ONLY_COLUMN_LABEL} delayDuration={400}>
|
|
30
|
+
<Button
|
|
31
|
+
type="button"
|
|
32
|
+
variant="text"
|
|
33
|
+
size="icon"
|
|
34
|
+
aria-label={SHOW_ONLY_COLUMN_LABEL}
|
|
35
|
+
aria-disabled={disabled}
|
|
36
|
+
tabIndex={disabled ? -1 : 0}
|
|
37
|
+
className={cn(
|
|
38
|
+
"h-6 w-6 hover:bg-muted text-muted-foreground hover:text-primary",
|
|
39
|
+
disabled && "opacity-50",
|
|
40
|
+
className,
|
|
41
|
+
)}
|
|
42
|
+
onPointerDown={(event) => {
|
|
43
|
+
event.stopPropagation();
|
|
44
|
+
}}
|
|
45
|
+
onClick={(event) => {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
if (disabled) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
applyShowOnlyColumns(table, columnIds);
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
<ScanEyeIcon className={iconClassName} strokeWidth={2.5} />
|
|
55
|
+
</Button>
|
|
56
|
+
</Tooltip>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import type { CellId } from "@/core/cells/ids";
|
|
5
|
+
import type { Variable, VariableName, Variables } from "@/core/variables/types";
|
|
6
|
+
import { createCellRuntimeState } from "@/core/cells/types";
|
|
7
|
+
import {
|
|
8
|
+
collapsedNodeWidth,
|
|
9
|
+
computeDefsByCell,
|
|
10
|
+
isStateFlowVariable,
|
|
11
|
+
reusableCellIds,
|
|
12
|
+
wrapDefs,
|
|
13
|
+
} from "../elements";
|
|
14
|
+
|
|
15
|
+
const names = (list: string[]) => list as VariableName[];
|
|
16
|
+
|
|
17
|
+
function variable(
|
|
18
|
+
partial: Omit<Partial<Variable>, "name"> & { name: string },
|
|
19
|
+
): Variable {
|
|
20
|
+
return {
|
|
21
|
+
declaredBy: [],
|
|
22
|
+
usedBy: [],
|
|
23
|
+
...partial,
|
|
24
|
+
name: partial.name as VariableName,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe("collapsedNodeWidth", () => {
|
|
29
|
+
it("clamps short labels to the minimum width", () => {
|
|
30
|
+
expect(collapsedNodeWidth("")).toBe(90);
|
|
31
|
+
expect(collapsedNodeWidth("x")).toBe(90);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("clamps long labels to the maximum width", () => {
|
|
35
|
+
expect(collapsedNodeWidth("a".repeat(100))).toBe(240);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("scales with label length between the bounds", () => {
|
|
39
|
+
const width = collapsedNodeWidth("df, summary");
|
|
40
|
+
expect(width).toBeGreaterThan(90);
|
|
41
|
+
expect(width).toBeLessThan(240);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("isStateFlowVariable", () => {
|
|
46
|
+
it("flags State and SetFunctor (from mo.state)", () => {
|
|
47
|
+
expect(
|
|
48
|
+
isStateFlowVariable(variable({ name: "g", dataType: "State" })),
|
|
49
|
+
).toBe(true);
|
|
50
|
+
expect(
|
|
51
|
+
isStateFlowVariable(variable({ name: "s", dataType: "SetFunctor" })),
|
|
52
|
+
).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("does not flag UI elements or plain values", () => {
|
|
56
|
+
// UIElement is frontend-driven / immutable during a run — not a state flow.
|
|
57
|
+
expect(
|
|
58
|
+
isStateFlowVariable(variable({ name: "sl", dataType: "slider" })),
|
|
59
|
+
).toBe(false);
|
|
60
|
+
expect(isStateFlowVariable(variable({ name: "n", dataType: "int" }))).toBe(
|
|
61
|
+
false,
|
|
62
|
+
);
|
|
63
|
+
expect(isStateFlowVariable(variable({ name: "u", dataType: null }))).toBe(
|
|
64
|
+
false,
|
|
65
|
+
);
|
|
66
|
+
expect(isStateFlowVariable(variable({ name: "u2" }))).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("wrapDefs", () => {
|
|
71
|
+
it("packs short names to the 12-char minimum budget", () => {
|
|
72
|
+
expect(
|
|
73
|
+
wrapDefs(names(["np", "math", "time", "io", "numpy", "pandas"])),
|
|
74
|
+
).toEqual(["np, math", "time, io", "numpy", "pandas"]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("gives a long name its own line, then packs the rest to its width", () => {
|
|
78
|
+
expect(
|
|
79
|
+
wrapDefs(
|
|
80
|
+
names([
|
|
81
|
+
"very_very_very_long_variable_name",
|
|
82
|
+
"short_var",
|
|
83
|
+
"shr_v",
|
|
84
|
+
"io",
|
|
85
|
+
"numpy",
|
|
86
|
+
"wev",
|
|
87
|
+
]),
|
|
88
|
+
),
|
|
89
|
+
).toEqual([
|
|
90
|
+
"very_very_very_long_variable_name",
|
|
91
|
+
"short_var, shr_v, io, numpy, wev",
|
|
92
|
+
]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("returns an empty list for no defs", () => {
|
|
96
|
+
expect(wrapDefs(names([]))).toEqual([]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("caps the budget so packed lines fit the max node width", () => {
|
|
100
|
+
// One name far beyond the width cap must not widen every other line.
|
|
101
|
+
const huge = "x".repeat(60);
|
|
102
|
+
const lines = wrapDefs(
|
|
103
|
+
names([huge, "aaaaaaaaaa", "bbbbbbbbbb", "cccccccccc"]),
|
|
104
|
+
);
|
|
105
|
+
expect(lines[0]).toBe(huge);
|
|
106
|
+
for (const line of lines.slice(1)) {
|
|
107
|
+
expect(line.length).toBeLessThanOrEqual(33);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("computeDefsByCell", () => {
|
|
113
|
+
it("maps each cell to the variables it declares", () => {
|
|
114
|
+
const c1 = "c1" as CellId;
|
|
115
|
+
const c2 = "c2" as CellId;
|
|
116
|
+
const a = "a" as VariableName;
|
|
117
|
+
const b = "b" as VariableName;
|
|
118
|
+
const c = "c" as VariableName;
|
|
119
|
+
const variables: Variables = {
|
|
120
|
+
[a]: variable({ name: a, declaredBy: [c1], usedBy: [c2] }),
|
|
121
|
+
[b]: variable({ name: b, declaredBy: [c1] }),
|
|
122
|
+
[c]: variable({ name: c, declaredBy: [c2] }),
|
|
123
|
+
};
|
|
124
|
+
const defs = computeDefsByCell(variables);
|
|
125
|
+
expect(defs.get(c1)).toEqual([a, b]);
|
|
126
|
+
expect(defs.get(c2)).toEqual([c]);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("returns an empty map when there are no variables", () => {
|
|
130
|
+
expect(computeDefsByCell({}).size).toBe(0);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("reusableCellIds", () => {
|
|
135
|
+
const c1 = "c1" as CellId;
|
|
136
|
+
const c2 = "c2" as CellId;
|
|
137
|
+
const c3 = "c3" as CellId;
|
|
138
|
+
|
|
139
|
+
it("collects cells whose serialization hint is valid, case-insensitively", () => {
|
|
140
|
+
const runtime = {
|
|
141
|
+
[c1]: createCellRuntimeState({ serialization: "Valid" }),
|
|
142
|
+
[c2]: createCellRuntimeState({ serialization: "Unparsable" }),
|
|
143
|
+
[c3]: createCellRuntimeState(),
|
|
144
|
+
};
|
|
145
|
+
expect(reusableCellIds([c1, c2, c3], runtime)).toEqual(new Set([c1]));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("ignores cells with no runtime entry", () => {
|
|
149
|
+
expect(reusableCellIds([c1], {})).toEqual(new Set());
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { memo } from "react";
|
|
4
|
+
import { BaseEdge, type EdgeProps, getBezierPath } from "reactflow";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_EDGE_COLOR,
|
|
7
|
+
type DependencyEdgeData,
|
|
8
|
+
STATE_FLOW_EDGE_COLOR,
|
|
9
|
+
} from "./elements";
|
|
10
|
+
|
|
11
|
+
// Gentle curvature keeps edges reading as clean directional splines
|
|
12
|
+
// (TensorBoard-style) rather than hard right-angle elbows.
|
|
13
|
+
const EDGE_CURVATURE = 0.35;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A dependency edge, drawn as a smooth curved spline that flows out of the
|
|
17
|
+
* source handle and into the target — the TensorBoard graph aesthetic. Mutable
|
|
18
|
+
* `State`/setter flows get a distinct dashed accent style.
|
|
19
|
+
*/
|
|
20
|
+
export const DependencyEdge = memo((props: EdgeProps<DependencyEdgeData>) => {
|
|
21
|
+
const {
|
|
22
|
+
sourceX,
|
|
23
|
+
sourceY,
|
|
24
|
+
targetX,
|
|
25
|
+
targetY,
|
|
26
|
+
sourcePosition,
|
|
27
|
+
targetPosition,
|
|
28
|
+
markerEnd,
|
|
29
|
+
data,
|
|
30
|
+
selected,
|
|
31
|
+
} = props;
|
|
32
|
+
|
|
33
|
+
const [path] = getBezierPath({
|
|
34
|
+
sourceX,
|
|
35
|
+
sourceY,
|
|
36
|
+
targetX,
|
|
37
|
+
targetY,
|
|
38
|
+
sourcePosition,
|
|
39
|
+
targetPosition,
|
|
40
|
+
curvature: EDGE_CURVATURE,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const isStateFlow = data?.isStateFlow ?? false;
|
|
44
|
+
// The inline stroke replaces React Flow's stylesheet-driven edge colors, so
|
|
45
|
+
// the selected state must be restyled here too or it becomes invisible.
|
|
46
|
+
const stroke = selected
|
|
47
|
+
? "var(--primary)"
|
|
48
|
+
: isStateFlow
|
|
49
|
+
? STATE_FLOW_EDGE_COLOR
|
|
50
|
+
: DEFAULT_EDGE_COLOR;
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<BaseEdge
|
|
54
|
+
path={path}
|
|
55
|
+
markerEnd={markerEnd}
|
|
56
|
+
style={{
|
|
57
|
+
strokeWidth: selected ? 2.5 : isStateFlow ? 2 : 1.5,
|
|
58
|
+
stroke,
|
|
59
|
+
strokeDasharray: isStateFlow ? "5 3" : undefined,
|
|
60
|
+
}}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
DependencyEdge.displayName = "DependencyEdge";
|
|
65
|
+
|
|
66
|
+
export const edgeTypes = {
|
|
67
|
+
dependency: DependencyEdge,
|
|
68
|
+
};
|
|
@@ -2,25 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import { useAtomValue } from "jotai";
|
|
4
4
|
import React, { memo, use } from "react";
|
|
5
|
-
import { Handle, Position
|
|
5
|
+
import { Handle, Position } from "reactflow";
|
|
6
6
|
import { TinyCode } from "@/components/editor/cell/TinyCode";
|
|
7
7
|
import { useCellIds } from "@/core/cells/cells";
|
|
8
|
-
import { displayCellName } from "@/core/cells/names";
|
|
8
|
+
import { displayCellName, isInternalCellName } from "@/core/cells/names";
|
|
9
9
|
import { cn } from "@/utils/cn";
|
|
10
10
|
import {
|
|
11
11
|
type CustomNodeProps,
|
|
12
|
-
getNodeHeight,
|
|
13
12
|
INPUTS_HANDLE_ID,
|
|
13
|
+
nodeBodyLines,
|
|
14
|
+
nodeDimensions,
|
|
14
15
|
OUTPUTS_HANDLE_ID,
|
|
15
16
|
} from "./elements";
|
|
16
17
|
import type { LayoutDirection } from "./types";
|
|
17
|
-
|
|
18
|
-
function getWidth(canvasWidth: number) {
|
|
19
|
-
const minWidth = 100;
|
|
20
|
-
const maxWidth = 400;
|
|
21
|
-
const padding = 50;
|
|
22
|
-
return Math.min(Math.max(canvasWidth - padding * 2, minWidth), maxWidth);
|
|
23
|
-
}
|
|
18
|
+
import { extractCellPreview } from "./utils/cell-preview";
|
|
24
19
|
|
|
25
20
|
export const EdgeMarkerContext = React.createContext<LayoutDirection>("LR");
|
|
26
21
|
|
|
@@ -36,13 +31,19 @@ export const CustomNode = memo((props: CustomNodeProps) => {
|
|
|
36
31
|
const { data, selected } = props; // must match the equality check
|
|
37
32
|
const cell = useAtomValue(data.atom);
|
|
38
33
|
const cellIndex = useCellIds().inOrderIds.indexOf(cell.id);
|
|
39
|
-
const
|
|
40
|
-
const selectedColor = "var(--gray-9)";
|
|
41
|
-
const color = selected ? selectedColor : nonSelectedColor;
|
|
42
|
-
const reactFlowWidth = useStore(({ width }) => width);
|
|
34
|
+
const handleColor = selected ? "var(--gray-9)" : "var(--gray-3)";
|
|
43
35
|
const edgeMarkers = use(EdgeMarkerContext);
|
|
44
36
|
|
|
45
|
-
const
|
|
37
|
+
const { width, height } = nodeDimensions(data);
|
|
38
|
+
const isNamed = !isInternalCellName(cell.name);
|
|
39
|
+
const name = displayCellName(cell.name, cellIndex);
|
|
40
|
+
// Only collapsed nodes without defs render the preview; skip the parse
|
|
41
|
+
// otherwise, since it scales with notebook size.
|
|
42
|
+
const preview =
|
|
43
|
+
!data.expanded && data.defs.length === 0
|
|
44
|
+
? extractCellPreview(cell.code).text
|
|
45
|
+
: undefined;
|
|
46
|
+
|
|
46
47
|
return (
|
|
47
48
|
<div>
|
|
48
49
|
<Handle
|
|
@@ -50,43 +51,70 @@ export const CustomNode = memo((props: CustomNodeProps) => {
|
|
|
50
51
|
id={INPUTS_HANDLE_ID}
|
|
51
52
|
data-testid="input-one"
|
|
52
53
|
position={edgeMarkers === "LR" ? Position.Left : Position.Top}
|
|
53
|
-
style={{ background:
|
|
54
|
+
style={{ background: handleColor }}
|
|
54
55
|
/>
|
|
55
56
|
<Handle
|
|
56
57
|
type="source"
|
|
57
58
|
id={INPUTS_HANDLE_ID}
|
|
58
59
|
data-testid="input-two"
|
|
59
60
|
position={edgeMarkers === "LR" ? Position.Left : Position.Top}
|
|
60
|
-
style={{ background:
|
|
61
|
+
style={{ background: handleColor }}
|
|
61
62
|
/>
|
|
62
63
|
<div
|
|
63
64
|
className={cn(
|
|
64
65
|
"flex flex-col bg-card border border-input/50 rounded-md mx-[2px] overflow-hidden",
|
|
65
66
|
selected && "border-primary",
|
|
66
67
|
)}
|
|
67
|
-
style={{
|
|
68
|
-
height: getNodeHeight(linesOfCode),
|
|
69
|
-
width: data.forceWidth || getWidth(reactFlowWidth),
|
|
70
|
-
}}
|
|
68
|
+
style={{ height, width }}
|
|
71
69
|
>
|
|
72
|
-
<div className="text-
|
|
73
|
-
|
|
70
|
+
<div className="text-xs py-0.5 px-2 bg-muted border-b flex items-center justify-between gap-2 shrink-0">
|
|
71
|
+
<span
|
|
72
|
+
className={cn(
|
|
73
|
+
"truncate",
|
|
74
|
+
isNamed
|
|
75
|
+
? "font-semibold text-foreground"
|
|
76
|
+
: "text-muted-foreground/70",
|
|
77
|
+
)}
|
|
78
|
+
>
|
|
79
|
+
{name}
|
|
80
|
+
</span>
|
|
74
81
|
</div>
|
|
75
|
-
|
|
82
|
+
{data.expanded ? (
|
|
83
|
+
<TinyCode code={cell.code} />
|
|
84
|
+
) : (
|
|
85
|
+
<div className="flex-1 min-h-0 flex flex-col justify-center px-2 py-1 font-mono text-xs leading-4">
|
|
86
|
+
{data.defs.length > 0 ? (
|
|
87
|
+
// Defs wrapped into comma-separated lines — taller, not wider.
|
|
88
|
+
nodeBodyLines(data).map((line) => (
|
|
89
|
+
<span
|
|
90
|
+
key={line}
|
|
91
|
+
className="text-foreground truncate"
|
|
92
|
+
title={line}
|
|
93
|
+
>
|
|
94
|
+
{line}
|
|
95
|
+
</span>
|
|
96
|
+
))
|
|
97
|
+
) : (
|
|
98
|
+
<span className="truncate italic text-muted-foreground/60">
|
|
99
|
+
{preview ?? "empty"}
|
|
100
|
+
</span>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
76
104
|
</div>
|
|
77
105
|
<Handle
|
|
78
106
|
type="source"
|
|
79
107
|
id={OUTPUTS_HANDLE_ID}
|
|
80
108
|
data-testid="output-one"
|
|
81
109
|
position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
|
|
82
|
-
style={{ background:
|
|
110
|
+
style={{ background: handleColor }}
|
|
83
111
|
/>
|
|
84
112
|
<Handle
|
|
85
113
|
type="target"
|
|
86
114
|
id={OUTPUTS_HANDLE_ID}
|
|
87
115
|
data-testid="output-two"
|
|
88
116
|
position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
|
|
89
|
-
style={{ background:
|
|
117
|
+
style={{ background: handleColor }}
|
|
90
118
|
/>
|
|
91
119
|
</div>
|
|
92
120
|
);
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import type
|
|
3
|
+
import { type Atom, atom, useAtomValue } from "jotai";
|
|
4
4
|
import { MapPinIcon } from "lucide-react";
|
|
5
|
-
import React, {
|
|
5
|
+
import React, {
|
|
6
|
+
type PropsWithChildren,
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useState,
|
|
10
|
+
} from "react";
|
|
6
11
|
import useEvent from "react-use-event-hook";
|
|
7
12
|
import ReactFlow, {
|
|
8
13
|
Background,
|
|
@@ -15,6 +20,7 @@ import ReactFlow, {
|
|
|
15
20
|
useNodesState,
|
|
16
21
|
useReactFlow,
|
|
17
22
|
} from "reactflow";
|
|
23
|
+
import { edgeTypes } from "@/components/dependency-graph/custom-edge";
|
|
18
24
|
import {
|
|
19
25
|
EdgeMarkerContext,
|
|
20
26
|
nodeTypes,
|
|
@@ -25,11 +31,16 @@ import type { CellData } from "@/core/cells/types";
|
|
|
25
31
|
import { store } from "@/core/state/jotai";
|
|
26
32
|
import type { Variables } from "@/core/variables/types";
|
|
27
33
|
import { Events } from "@/utils/events";
|
|
28
|
-
import { scrollAndHighlightCell } from "../editor/links/cell-link";
|
|
29
34
|
import { Tooltip } from "../ui/tooltip";
|
|
30
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
computeDefsByCell,
|
|
37
|
+
type NodeData,
|
|
38
|
+
nodeDimensions,
|
|
39
|
+
TreeElementsBuilder,
|
|
40
|
+
} from "./elements";
|
|
31
41
|
import { GraphSelectionPanel } from "./panels";
|
|
32
42
|
import type { GraphSelection, GraphSettings, LayoutDirection } from "./types";
|
|
43
|
+
import { extractCellPreview } from "./utils/cell-preview";
|
|
33
44
|
import { layoutElements } from "./utils/layout";
|
|
34
45
|
import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionChange";
|
|
35
46
|
|
|
@@ -43,6 +54,24 @@ interface Props {
|
|
|
43
54
|
|
|
44
55
|
const elementsBuilder = new TreeElementsBuilder();
|
|
45
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Apply the current expand/collapse selection to freshly-built nodes, resizing
|
|
59
|
+
* each so the layout engine and the DOM agree on node dimensions.
|
|
60
|
+
*/
|
|
61
|
+
function withExpansion(
|
|
62
|
+
nodes: Node<NodeData>[],
|
|
63
|
+
expandedIds: Set<CellId>,
|
|
64
|
+
): Node<NodeData>[] {
|
|
65
|
+
return nodes.map((node) => {
|
|
66
|
+
const data: NodeData = {
|
|
67
|
+
...node.data,
|
|
68
|
+
expanded: expandedIds.has(node.id as CellId),
|
|
69
|
+
};
|
|
70
|
+
const { width, height } = nodeDimensions(data);
|
|
71
|
+
return { ...node, data, width, height };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
46
75
|
export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
47
76
|
cellIds,
|
|
48
77
|
variables,
|
|
@@ -51,22 +80,23 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
51
80
|
layoutDirection,
|
|
52
81
|
settings,
|
|
53
82
|
}) => {
|
|
83
|
+
// Cells whose node is expanded to show its full code (toggled by double-click).
|
|
84
|
+
const [expandedIds, setExpandedIds] = useState<Set<CellId>>(() => new Set());
|
|
85
|
+
|
|
54
86
|
// oxlint-disable-next-line react/hook-use-state
|
|
55
87
|
const [initial] = useState(() => {
|
|
56
|
-
|
|
88
|
+
const elements = elementsBuilder.createElements(
|
|
57
89
|
cellIds,
|
|
58
90
|
cellAtoms,
|
|
59
91
|
variables,
|
|
60
92
|
settings.hidePureMarkdown,
|
|
61
93
|
settings.hideReusableFunctions,
|
|
62
94
|
);
|
|
63
|
-
|
|
64
|
-
nodes: elements.nodes,
|
|
95
|
+
return layoutElements({
|
|
96
|
+
nodes: withExpansion(elements.nodes, expandedIds),
|
|
65
97
|
edges: elements.edges,
|
|
66
98
|
direction: layoutDirection,
|
|
67
99
|
});
|
|
68
|
-
|
|
69
|
-
return elements;
|
|
70
100
|
// Only run once
|
|
71
101
|
});
|
|
72
102
|
|
|
@@ -82,22 +112,68 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
82
112
|
edges: elements.edges,
|
|
83
113
|
direction: layoutDirection,
|
|
84
114
|
});
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
// Rebuilt elements are fresh objects; carry selection over so a
|
|
116
|
+
// re-layout (e.g. toggling expansion) doesn't silently clear it while
|
|
117
|
+
// the selection panel still targets the element.
|
|
118
|
+
setNodes((prev) => {
|
|
119
|
+
const selected = new Set(
|
|
120
|
+
prev.filter((node) => node.selected).map((node) => node.id),
|
|
121
|
+
);
|
|
122
|
+
return result.nodes.map((node) =>
|
|
123
|
+
selected.has(node.id) ? { ...node, selected: true } : node,
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
setEdges((prev) => {
|
|
127
|
+
const selected = new Set(
|
|
128
|
+
prev.filter((edge) => edge.selected).map((edge) => edge.id),
|
|
129
|
+
);
|
|
130
|
+
return result.edges.map((edge) =>
|
|
131
|
+
selected.has(edge.id) ? { ...edge, selected: true } : edge,
|
|
132
|
+
);
|
|
133
|
+
});
|
|
87
134
|
},
|
|
88
135
|
);
|
|
89
136
|
|
|
90
|
-
//
|
|
137
|
+
// Node sizes depend on live cell code: the line count when expanded, or the
|
|
138
|
+
// preview when a cell defines nothing. The cell atoms keep their identity
|
|
139
|
+
// across edits, so the rebuild effect below can't see code changes through
|
|
140
|
+
// its deps — subscribe to the size-relevant inputs explicitly.
|
|
141
|
+
const defsByCell = useMemo(() => computeDefsByCell(variables), [variables]);
|
|
142
|
+
const sizeSignature = useAtomValue(
|
|
143
|
+
useMemo(
|
|
144
|
+
() =>
|
|
145
|
+
atom((get) =>
|
|
146
|
+
cellIds
|
|
147
|
+
.map((cellId, index) => {
|
|
148
|
+
const code = get(cellAtoms[index]).code;
|
|
149
|
+
if (expandedIds.has(cellId)) {
|
|
150
|
+
return `e${code.trim().split("\n").length}`;
|
|
151
|
+
}
|
|
152
|
+
if ((defsByCell.get(cellId) ?? []).length > 0) {
|
|
153
|
+
// Collapsed nodes with defs size off the defs, not the code.
|
|
154
|
+
return "d";
|
|
155
|
+
}
|
|
156
|
+
return `p${extractCellPreview(code).text?.length ?? 0}`;
|
|
157
|
+
})
|
|
158
|
+
.join(),
|
|
159
|
+
),
|
|
160
|
+
[cellIds, cellAtoms, expandedIds, defsByCell],
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Rebuild + re-layout when the graph inputs or the expand/collapse set change.
|
|
91
165
|
useEffect(() => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
settings.hideReusableFunctions,
|
|
99
|
-
),
|
|
166
|
+
const elements = elementsBuilder.createElements(
|
|
167
|
+
cellIds,
|
|
168
|
+
cellAtoms,
|
|
169
|
+
variables,
|
|
170
|
+
settings.hidePureMarkdown,
|
|
171
|
+
settings.hideReusableFunctions,
|
|
100
172
|
);
|
|
173
|
+
syncChanges({
|
|
174
|
+
nodes: withExpansion(elements.nodes, expandedIds),
|
|
175
|
+
edges: elements.edges,
|
|
176
|
+
});
|
|
101
177
|
}, [
|
|
102
178
|
cellIds,
|
|
103
179
|
variables,
|
|
@@ -105,6 +181,8 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
105
181
|
syncChanges,
|
|
106
182
|
settings.hidePureMarkdown,
|
|
107
183
|
settings.hideReusableFunctions,
|
|
184
|
+
expandedIds,
|
|
185
|
+
sizeSignature,
|
|
108
186
|
]);
|
|
109
187
|
|
|
110
188
|
const [selection, setSelection] = useState<GraphSelection>();
|
|
@@ -120,6 +198,7 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
120
198
|
nodes={nodes}
|
|
121
199
|
edges={edges}
|
|
122
200
|
nodeTypes={nodeTypes}
|
|
201
|
+
edgeTypes={edgeTypes}
|
|
123
202
|
minZoom={0.2}
|
|
124
203
|
fitViewOptions={{
|
|
125
204
|
minZoom: 0.5,
|
|
@@ -137,7 +216,17 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
137
216
|
});
|
|
138
217
|
}}
|
|
139
218
|
onNodeDoubleClick={(_event, node) => {
|
|
140
|
-
|
|
219
|
+
// Expand/collapse the node to reveal its full code in place.
|
|
220
|
+
const id = node.id as CellId;
|
|
221
|
+
setExpandedIds((prev) => {
|
|
222
|
+
const next = new Set(prev);
|
|
223
|
+
if (next.has(id)) {
|
|
224
|
+
next.delete(id);
|
|
225
|
+
} else {
|
|
226
|
+
next.add(id);
|
|
227
|
+
}
|
|
228
|
+
return next;
|
|
229
|
+
});
|
|
141
230
|
}}
|
|
142
231
|
fitView={true}
|
|
143
232
|
onNodesChange={onNodesChange}
|