@marimo-team/frontend 0.25.3-dev13 → 0.25.3-dev135
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-Bu_cFOaf.js +1 -0
- package/dist/assets/{ConnectedDataExplorerComponent-TprnxZeJ.js → ConnectedDataExplorerComponent-BV1mVpaE.js} +1 -1
- package/dist/assets/{ErrorBoundary-CM13wrd8.js → ErrorBoundary-Cy4lxM4U.js} +2 -2
- package/dist/assets/JsonOutput-Dnd0uzN4.js +11 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-B4fCknq1.js → LazyAnyLanguageCodeMirror-DoxWX_Wp.js} +2 -2
- package/dist/assets/MarimoErrorOutput-DWgmERpO.js +10 -0
- package/dist/assets/{RenderHTML-DX6i99Op.js → RenderHTML-BuZ8DdVv.js} +2 -2
- package/dist/assets/RunButton-BXXDV5w-.js +1 -0
- package/dist/assets/__vite-browser-external-BynxqS4w.js +1 -0
- package/dist/assets/__vite-browser-external-DTOT9NDN.js +1 -0
- package/dist/assets/{add-cell-with-ai-BpD_790A.js → add-cell-with-ai-DYahRMb_.js} +26 -26
- package/dist/assets/{add-connection-dialog-B1BXCjex.js → add-connection-dialog-CjRaQbDW.js} +51 -51
- package/dist/assets/{agent-panel-CDFUc1uu.js → agent-panel-Cb9PZdDM.js} +4 -4
- package/dist/assets/ai-model-dropdown-Bbr2oylS.js +13 -0
- package/dist/assets/alert-dialog-8YiYLrfr.js +1 -0
- package/dist/assets/any-language-editor-BWmz0P_C.js +1 -0
- package/dist/assets/{app-config-button-AdV-QDD7.js → app-config-button-CPNc_---.js} +1 -1
- package/dist/assets/arrays-0R2reF2y.js +1 -0
- package/dist/assets/{blob-BG8yoQmx.js → blob-CQAkRxR1.js} +1 -1
- package/dist/assets/{button-COI-NGrx.js → button-Cl7haVNh.js} +1 -1
- package/dist/assets/{cache-panel-DTY1dqvi.js → cache-panel-DuBsA6oO.js} +1 -1
- package/dist/assets/{capabilities-BJvf-MD4.js → capabilities-DcB-Dd0T.js} +1 -1
- package/dist/assets/cell-editor-CjvWSYDB.js +42 -0
- package/dist/assets/cell-link-DIOanEQB.js +1 -0
- package/dist/assets/cells-lwP9-xsQ.js +220 -0
- package/dist/assets/{chat-display-DhgI2MS9.js → chat-display-DpCQoui-.js} +1 -1
- package/dist/assets/chat-panel-C79_pWxF.js +4 -0
- package/dist/assets/chat-ui-DOOiaOcb.js +4 -0
- package/dist/assets/circle-B0vOU-Dh.js +1 -0
- package/dist/assets/{code-visibility-BJImdpDi.js → code-visibility-D1Wf7-vD.js} +1 -1
- package/dist/assets/column-preview-DIvrCqra.js +1 -0
- package/dist/assets/command-palette-BYgBVslq.js +1 -0
- package/dist/assets/{common-Sl3uthjg.js → common-B7U2CeDc.js} +1 -1
- package/dist/assets/{components-CskjK6xZ.js → components-9p_w2C6e.js} +1 -1
- package/dist/assets/components-B6gDDccL.js +1 -0
- package/dist/assets/{components-3cou6Mka.js → components-Vz1pD133.js} +1 -1
- package/dist/assets/config-7IjqNuVp.js +1 -0
- package/dist/assets/config-BC32AAdw.js +1 -0
- package/dist/assets/{config-CA1V-wjh.js → config-CXnC3MRv.js} +1 -1
- package/dist/assets/{copy-D8O_CYCG.js → copy-74EjuZso.js} +1 -1
- package/dist/assets/{copy-icon-BIiRXh_3.js → copy-icon-Craaocbu.js} +1 -1
- package/dist/assets/{createReducer-DgRODTW6.js → createReducer-B04CIO-e.js} +1 -1
- package/dist/assets/{datasource-DfbNb83e.js → datasource-Bp8TnG7a.js} +2 -2
- package/dist/assets/{dates-CfmdTL6B.js → dates-CaPZVGtm.js} +1 -1
- package/dist/assets/{dependency-graph-panel-L5cBE5sl.js → dependency-graph-panel-B31-YcSF.js} +3 -3
- package/dist/assets/dist-gaK_BThd.js +1 -0
- package/dist/assets/{documentation-panel-D7S8JIc2.js → documentation-panel-C2MJwSef.js} +1 -1
- package/dist/assets/download-J6sWXUJR.js +9 -0
- package/dist/assets/dropdown-menu-Cwi17BoX.js +1 -0
- package/dist/assets/edit-page-DfxHDnWP.js +9 -0
- package/dist/assets/{error-banner-COZ7SfYV.js → error-banner-m3mastc-.js} +1 -1
- package/dist/assets/{error-entries-CLnPDv7b.js → error-entries-BcRbOxwK.js} +1 -1
- package/dist/assets/{error-panel-D2xrYLue.js → error-panel-jZlFCjdy.js} +1 -1
- package/dist/assets/{es-Cqst59WX.js → es-Rg27gAEy.js} +1 -1
- package/dist/assets/feedback-button-94vZrmBy.js +1 -0
- package/dist/assets/{feedback-button-DzPunIqU.js → feedback-button-C2XmZw_y.js} +2 -2
- package/dist/assets/file-explorer-panel-Cg9UovsS.js +1 -0
- package/dist/assets/{file-name-input-B4fRaQkI.js → file-name-input-y9ggAMGJ.js} +2 -2
- package/dist/assets/floating-outline-CE1olGl0.js +1 -0
- package/dist/assets/{formats-yZ06h1Pl.js → formats-CYyvbiZA.js} +1 -1
- package/dist/assets/{formatting-BqrP-n49.js → formatting-DW2u7HXI.js} +1 -1
- package/dist/assets/fullscreen-D-ldV-19.js +41 -0
- package/dist/assets/{gallery-page-BefvdsM7.js → gallery-page-ClEnoAT-.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-2n7Ig5Jm.js → ganttDiagram-EL5Y4UJY-CYqkCfFG.js} +1 -1
- package/dist/assets/{glide-data-editor-C3eaYlXg.js → glide-data-editor-Cp0q28Zz.js} +2 -2
- package/dist/assets/{glide-utils-CIrAxdjv.js → glide-utils-DsTeJ7WA.js} +2 -2
- package/dist/assets/home-page-DJsI6Od_.js +1 -0
- package/dist/assets/{hooks-DzML9nez.js → hooks-DGSryuSD.js} +1 -1
- package/dist/assets/{html-to-image-DK9Zl1lU.js → html-to-image-BW0fcUS8.js} +1 -1
- package/dist/assets/index-BjNf54kO.js +30 -0
- package/dist/assets/index-u08m0hQE.css +2 -0
- package/dist/assets/{input-BoBxR50a.js → input-DLA5Dhn3.js} +2 -2
- package/dist/assets/kiosk-mode-Cbxffiz9.js +1 -0
- package/dist/assets/{layout-Ck1RoL1B.js → layout-DRVIFud8.js} +5 -5
- package/dist/assets/linear-Bma8J3iM.js +1 -0
- package/dist/assets/links-UwsB2RA1.js +1 -0
- package/dist/assets/{logs-panel-BRytaWaO.js → logs-panel-Db38azhc.js} +1 -1
- package/dist/assets/{markdown-renderer-DX0Xrrfy.js → markdown-renderer-D2td9eFc.js} +1 -1
- package/dist/assets/menu-items-yD7IV3V4.js +1 -0
- package/dist/assets/{mermaid-C4EiVqcd.js → mermaid-DmekSy8J.js} +2 -2
- package/dist/assets/{name-cell-input-DlpTvPLa.js → name-cell-input-CJpi0Kvu.js} +1 -1
- package/dist/assets/numbers-DJK15_4S.js +1 -0
- package/dist/assets/{objects-snlMn4yk.js → objects-rLPlQ3X_.js} +1 -1
- package/dist/assets/{once-Haz_uxEL.js → once-6KNTRW0u.js} +1 -1
- package/dist/assets/{outline-panel-B2WIpz-1.js → outline-panel-DxQKP4eN.js} +1 -1
- package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
- package/dist/assets/packages-panel-BFzN4mNb.js +1 -0
- package/dist/assets/{panel-accordion-state-BqSH5ttk.js → panel-accordion-state-D3RiRniG.js} +1 -1
- package/dist/assets/panels-CpUpLOy4.js +1 -0
- package/dist/assets/precisionRound-BxlUs8G4.js +1 -0
- package/dist/assets/process-output-B6v1FE29.js +1 -0
- package/dist/assets/{quadrantDiagram-AXDQQJYC-yBhCDI7E.js → quadrantDiagram-AXDQQJYC-D9KH5Zge.js} +1 -1
- package/dist/assets/react-vega-BTNeboR2.js +189 -0
- package/dist/assets/{readonly-code-display-MnMEoYW5.js → readonly-code-display-Deg2hzFh.js} +1 -1
- package/dist/assets/{readonly-python-code-ggs4hAzC.js → readonly-python-code-DPGknu49.js} +1 -1
- package/dist/assets/{renderShortcut-C1JwYcqW.js → renderShortcut-Bxv9ZLnD.js} +1 -1
- package/dist/assets/{requests-lt0JK8Jt.js → requests-BIFR-h4M.js} +1 -1
- package/dist/assets/requests-DuLJN9Tf.js +1 -0
- package/dist/assets/{reveal-component-PiV1eQk9.js → reveal-component-CXkDpGxy.js} +37 -37
- package/dist/assets/run-page-qp2KKYgs.js +1 -0
- package/dist/assets/{runs-BLp5jezv.js → runs-C8uOPNAW.js} +1 -1
- package/dist/assets/{runtime-details-state-CoL-p0MC.js → runtime-details-state-BiGF299n.js} +1 -1
- package/dist/assets/{save-worker-BbUSwZRG.js → save-worker-UwdGcNK5.js} +2 -1
- package/dist/assets/scratchpad-panel-QV0lacAe.js +1 -0
- package/dist/assets/{scroll-to-bottom-button-1FyowpWV.js → scroll-to-bottom-button-CidjyqiH.js} +1 -1
- package/dist/assets/secrets-panel-ConQpchl.js +1 -0
- package/dist/assets/select-CgWQvW1F.js +1 -0
- package/dist/assets/{session-DqoWmb7X.js → session-BHgGkjDm.js} +1 -1
- package/dist/assets/session-panel-CrWluawa.js +1 -0
- package/dist/assets/snippets-panel-CM7g9b6c.js +1 -0
- package/dist/assets/{spec-BfSBcO5B.js → spec-DFtwOyXT.js} +1 -1
- package/dist/assets/state-BYETGwDZ.js +1 -0
- package/dist/assets/{state-uwRvJLb8.js → state-CZu2E2Lb.js} +1 -1
- package/dist/assets/{state-C3oDoyFe.js → state-ClBFtZxn.js} +1 -1
- package/dist/assets/{state-DxQnC_1I.js → state-CrLrURYG.js} +1 -1
- package/dist/assets/{state-DtGB7xeJ.js → state-DhMztz1E.js} +1 -1
- package/dist/assets/state-lEPoZS4k.js +107 -0
- package/dist/assets/{strings-B2vv-ENv.js → strings-3lNX212T.js} +1 -1
- package/dist/assets/{swiper-component-a07domrZ.js → swiper-component-BwGv-Pu1.js} +1 -1
- package/dist/assets/switch-D2gdC_ep.js +1 -0
- package/dist/assets/tabs-BLczoY3k.js +1 -0
- package/dist/assets/{terminal-wnSHYT8N.js → terminal-DLgGyFIP.js} +1 -1
- package/dist/assets/{time-MgToa8VM.js → time-DswSXBDk.js} +1 -1
- package/dist/assets/toast-trUlkvx3.js +1 -0
- package/dist/assets/tooltip-B5lAA_jn.js +1 -0
- package/dist/assets/tooltip-BiQdpXA0.js +61 -0
- package/dist/assets/tracing-DRA8maZB.js +1 -0
- package/dist/assets/tracing-panel-DLxPRadV.js +2 -0
- package/dist/assets/{tree-actions-DnUokmva.js → tree-actions-COtU5qy_.js} +1 -1
- package/dist/assets/use-restore-focus-DMSzeuUr.js +1 -0
- package/dist/assets/{useAddCell-IN24thff.js → useAddCell-BAEOA87M.js} +1 -1
- package/dist/assets/useAsyncData-qvoPYHtx.js +1 -0
- package/dist/assets/useBoolean-BkeUcn1n.js +1 -0
- package/dist/assets/useCellActionButton-BobjsJfu.js +1 -0
- package/dist/assets/useDebounce-DwTQ_1Pu.js +1 -0
- package/dist/assets/{useDeepCompareMemoize-DFIVN9dn.js → useDeepCompareMemoize-B2DVK2De.js} +1 -1
- package/dist/assets/useDelayElapsed-BlsDT4TV.js +1 -0
- package/dist/assets/{useDeleteCell-fQlM46Y2.js → useDeleteCell-gedazkBF.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-ImXYINm_.js → useDependencyPanelTab-DAJ6BOUm.js} +1 -1
- package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
- package/dist/assets/{useEventListener-D9cftcHj.js → useEventListener-DPOTkksd.js} +1 -1
- package/dist/assets/{useIframeCapabilities-CwTkczVN.js → useIframeCapabilities-sHeZt_EA.js} +1 -1
- package/dist/assets/{useInstallPackage-BW06eter.js → useInstallPackage-BfNKN33w.js} +1 -1
- package/dist/assets/{useInterval--x3s1VpI.js → useInterval-BcdwHHB5.js} +1 -1
- package/dist/assets/useNotebookActions-CnLArLoz.js +1 -0
- package/dist/assets/{useRunCells-DSJPXE-j.js → useRunCells-CUknep7p.js} +1 -1
- package/dist/assets/{useSplitCell-DQyMF5gd.js → useSplitCell-DeXniINv.js} +1 -1
- package/dist/assets/useStateForKey-CGMJQT8x.js +1 -0
- package/dist/assets/{useTheme-n8Dj1zH7.js → useTheme-C2dnh2vM.js} +1 -1
- package/dist/assets/{utils-CaQYvazl.js → utils-DfElfBpz.js} +1 -1
- package/dist/assets/vega-component-DJf6ho22.js +1 -0
- package/dist/assets/{vega-embed-container-DJPNkHPb.js → vega-embed-container-DtArSJz1.js} +1 -1
- package/dist/assets/vega-loader.browser-Bu25TKax.js +6 -0
- package/dist/assets/worker-jm2VC7pS.js +159 -0
- package/dist/assets/{write-secret-modal-DzKAInL2.js → write-secret-modal-CBi2vNK_.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-KbGzG6-u.js → xychartDiagram-S5SC5T6Z-CeRnBS5e.js} +1 -1
- package/dist/index.html +81 -79
- package/package.json +14 -14
- package/src/__tests__/host-imports.test.ts +1 -0
- package/src/__tests__/module-entry.test.ts +32 -0
- package/src/__tests__/mount.test.ts +0 -20
- 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/chat/__tests__/message-queue.test.tsx +17 -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 +9 -8
- package/src/components/chat/chat-utils.ts +4 -8
- 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__/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 +13 -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/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 +98 -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 +13 -4
- package/src/components/datasources/datasources.tsx +51 -39
- package/src/components/datasources/utils.ts +32 -23
- package/src/components/debugger/debugger-code.tsx +5 -0
- 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/panels.tsx +2 -1
- 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__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
- package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
- 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/startup-logs-alert.tsx +1 -0
- package/src/components/editor/cell/CreateCellButton.tsx +8 -10
- package/src/components/editor/cell/DeleteButton.tsx +1 -0
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +1 -1
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +5 -3
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- 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/snippets-panel.tsx +5 -1
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- 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/connections/components.tsx +1 -1
- 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/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
- 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 +45 -8
- 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/status.tsx +28 -5
- package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
- package/src/components/editor/links/cell-link.tsx +14 -5
- package/src/components/editor/navigation/focus-utils.ts +4 -4
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +11 -2
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- 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/package-alert.tsx +14 -7
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -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/mcp/mcp-status-indicator.tsx +1 -1
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +95 -0
- package/src/components/scratchpad/scratchpad.tsx +16 -3
- package/src/components/slides/reveal-component.tsx +4 -2
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +45 -41
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/tools/base.ts +16 -7
- package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
- package/src/core/ai/tools/registry.ts +13 -8
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/attachments/state.ts +5 -8
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +3 -1
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
- package/src/core/cells/__tests__/session.test.ts +117 -36
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +3 -1
- package/src/core/cells/pending-delete-service.ts +2 -6
- package/src/core/cells/session.ts +1 -1
- package/src/core/cells/types.ts +10 -1
- package/src/core/codemirror/__tests__/setup.test.ts +29 -29
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -0
- package/src/core/codemirror/cells/extensions.ts +7 -3
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/extension.ts +8 -8
- 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 +9 -7
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/rtc/extension.ts +24 -12
- package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
- package/src/core/codemirror/rtc/loro/sync.ts +1 -0
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/document/__tests__/codemirror.test.ts +485 -0
- package/src/core/document/__tests__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/hooks.test.tsx +386 -0
- package/src/core/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/document/__tests__/model.test.ts +191 -0
- package/src/core/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/document/__tests__/state.test.ts +438 -0
- package/src/core/document/__tests__/submission.test.ts +203 -0
- package/src/core/document/__tests__/test-host.test.ts +92 -0
- package/src/core/document/__tests__/test-host.ts +247 -0
- package/src/core/document/__tests__/test-notebook.ts +149 -0
- package/src/core/document/__tests__/user.ts +61 -0
- package/src/core/document/codemirror.ts +311 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/hooks.tsx +118 -0
- package/src/core/document/index.ts +15 -0
- package/src/core/document/model.ts +55 -0
- package/src/core/document/select.ts +41 -0
- package/src/core/document/state.ts +374 -0
- package/src/core/document/sync.ts +369 -0
- package/src/core/host/AGENTS.md +8 -2
- package/src/core/host/__tests__/attachments.test.ts +56 -0
- package/src/core/host/__tests__/document.test.ts +126 -0
- package/src/core/host/__tests__/fixtures.ts +71 -0
- package/src/core/host/__tests__/replica.test.ts +550 -0
- package/src/core/host/__tests__/static.test.ts +169 -0
- package/src/core/host/__tests__/wasm.test.ts +162 -0
- package/src/core/host/backend.ts +19 -0
- package/src/core/host/connection.ts +1 -40
- package/src/core/host/index.ts +14 -0
- package/src/core/host/replica.ts +286 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/host/static.ts +72 -0
- package/src/core/host/wasm.ts +102 -0
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/islands/__tests__/bootstrap.test.ts +0 -26
- package/src/core/islands/bootstrap.ts +0 -1
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/network/connection.ts +4 -2
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -58
- package/src/core/runtime/runtime.ts +38 -42
- package/src/core/runtime/types.ts +0 -2
- 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/wasm/bridge.ts +38 -10
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +2 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/types.ts +11 -0
- package/src/core/wasm/worker/worker.ts +48 -0
- package/src/core/websocket/__tests__/backend.test.ts +200 -0
- package/src/core/websocket/__tests__/connection-state.test.ts +0 -12
- package/src/core/websocket/__tests__/useNotebookReplica.hook.test.tsx +141 -0
- package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +154 -428
- package/src/core/websocket/backend.ts +106 -0
- package/src/core/websocket/connection-state.ts +1 -11
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +445 -0
- package/src/core/websocket/transports/notebook.ts +190 -0
- package/src/core/websocket/types.ts +2 -2
- package/src/core/websocket/useNotebookReplica.ts +69 -0
- package/src/core/websocket/useNotebookSession.tsx +10 -22
- package/src/css/globals.css +5 -0
- 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 +0 -4
- 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 +29 -33
- 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 +0 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +117 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- 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/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- 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__/numbers.test.ts +48 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +10 -0
- package/src/utils/blob.ts +1 -1
- package/src/utils/numbers.ts +28 -17
- package/src/utils/objects.ts +3 -7
- package/src/utils/once.ts +19 -19
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/assets/CellStatus-DVOHpdeJ.js +0 -1
- package/dist/assets/JsonOutput-Cx1iyibB.js +0 -11
- package/dist/assets/MarimoErrorOutput-s_5GOX8k.js +0 -10
- package/dist/assets/RunButton-BKoh0zYG.js +0 -1
- package/dist/assets/__vite-browser-external-CYO_P3S8.js +0 -1
- package/dist/assets/__vite-browser-external-FeDVGZU8.js +0 -1
- package/dist/assets/ai-model-dropdown-i1vfGeVi.js +0 -13
- package/dist/assets/alert-dialog-BaPGzeOK.js +0 -1
- package/dist/assets/any-language-editor-BdTWdMCI.js +0 -1
- package/dist/assets/arrays-BqUx5USx.js +0 -1
- package/dist/assets/cell-editor-BKJ06H5F.js +0 -21
- package/dist/assets/cell-link-8Auigi8P.js +0 -1
- package/dist/assets/cells-C6YGYGdi.js +0 -220
- package/dist/assets/chat-panel-Cau71Ygr.js +0 -4
- package/dist/assets/chat-ui-C5ql1Up-.js +0 -4
- package/dist/assets/circle-DXf-VWZG.js +0 -1
- package/dist/assets/circle-play-CYIb0qT6.js +0 -1
- package/dist/assets/column-preview-BZ_iNhtJ.js +0 -1
- package/dist/assets/command-palette-DDC3kBet.js +0 -1
- package/dist/assets/components-YBmtV0p6.js +0 -1
- package/dist/assets/config-DRIpOKqh.js +0 -1
- package/dist/assets/config-Dy28fDwn.js +0 -1
- package/dist/assets/dist-iaThVDkA.js +0 -1
- package/dist/assets/download-C03FOElq.js +0 -9
- package/dist/assets/dropdown-menu-C1rnl-0o.js +0 -1
- package/dist/assets/edit-page-D_Rg0gQO.js +0 -9
- package/dist/assets/feedback-button-Kla7i5RT.js +0 -1
- package/dist/assets/file-explorer-panel-Uk4_QIJQ.js +0 -1
- package/dist/assets/floating-outline-B5MaM1JS.js +0 -1
- package/dist/assets/fullscreen-B9tHcfpV.js +0 -41
- package/dist/assets/home-page-hmvKlc1w.js +0 -4
- package/dist/assets/index-6b4mf8Ai.css +0 -2
- package/dist/assets/index-ptK1gxmo.js +0 -30
- package/dist/assets/kiosk-mode-BZECfg9k.js +0 -1
- package/dist/assets/linear-0eij_aAG.js +0 -1
- package/dist/assets/link-NuFVR7G9.js +0 -1
- package/dist/assets/links-DkkL9DVa.js +0 -1
- package/dist/assets/menu-items-BrwnTgyK.js +0 -1
- package/dist/assets/numbers-Mk3-CcoU.js +0 -1
- package/dist/assets/packages-panel-CI5ff9b-.js +0 -1
- package/dist/assets/panels-BCcZ_yLK.js +0 -107
- package/dist/assets/precisionRound-Bq_nmf5u.js +0 -1
- package/dist/assets/process-output-f3C3PD0Z.js +0 -1
- package/dist/assets/react-vega-C3rYGtP6.js +0 -189
- package/dist/assets/requests-CgSY1X4a.js +0 -1
- package/dist/assets/run-page-AfZhtEh1.js +0 -1
- package/dist/assets/scratchpad-panel-D2rWg4k8.js +0 -1
- package/dist/assets/secrets-panel-D7KN4tVs.js +0 -1
- package/dist/assets/select-DTBn5eTb.js +0 -1
- package/dist/assets/session-panel-CnANhcTo.js +0 -1
- package/dist/assets/snippets-panel-ClGHtEKQ.js +0 -1
- package/dist/assets/state-BAJYRhmO.js +0 -1
- package/dist/assets/state-CbjBtkdd.js +0 -3
- package/dist/assets/switch-CTaiAjrz.js +0 -1
- package/dist/assets/tabs-BuQlZFbt.js +0 -1
- package/dist/assets/toast-BGzLGnvw.js +0 -1
- package/dist/assets/tooltip-C9TuY18o.js +0 -1
- package/dist/assets/tooltip-mT3CGest.js +0 -61
- package/dist/assets/tracing-Dz2rYOFL.js +0 -1
- package/dist/assets/tracing-panel-DqQY9V91.js +0 -2
- package/dist/assets/use-restore-focus-BxEGwIbk.js +0 -1
- package/dist/assets/useAsyncData-C7aJJz0Y.js +0 -1
- package/dist/assets/useBoolean-d0Tty94N.js +0 -1
- package/dist/assets/useCellActionButton-DmaFZ4oF.js +0 -1
- package/dist/assets/useDebounce-B_ccBZTp.js +0 -1
- package/dist/assets/useNotebookActions-DHt3s-ia.js +0 -1
- package/dist/assets/vega-component-IouMe13t.js +0 -1
- package/dist/assets/vega-loader.browser-CLRkNgm7.js +0 -6
- package/dist/assets/worker-DTQ7oH2A.js +0 -158
- package/dist/assets/ws-BXWY541V.js +0 -22
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/notebook-client.test.ts +0 -191
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/events.ts +0 -60
- package/src/core/host/notebook-client.ts +0 -226
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -140
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/create.ts +0 -31
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -50
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useNotebookClient.ts +0 -80
|
@@ -46,38 +46,80 @@ function abortSignalAny(signals: AbortSignal[]): AbortSignal {
|
|
|
46
46
|
return controller.signal;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
interface ModuleEntry {
|
|
50
|
+
promise: Promise<unknown>;
|
|
51
|
+
references: number;
|
|
52
|
+
dispose: () => void;
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
/**
|
|
50
56
|
* Deduplicates ESM imports by jsHash.
|
|
51
57
|
* A single import is shared across all widget instances using the same module.
|
|
52
58
|
*/
|
|
53
59
|
class WidgetDefRegistry {
|
|
54
|
-
#cache = new Map<string,
|
|
60
|
+
#cache = new Map<string, ModuleEntry>();
|
|
55
61
|
|
|
56
62
|
/**
|
|
57
63
|
* Get (or start) the ESM import for a widget module, cached by
|
|
58
64
|
* jsHash so multiple instances share one import. Pass
|
|
59
65
|
* `kernelAuthored: true` only for URLs from an `EsmSpec`; it widens
|
|
60
|
-
* the import gate to remote and data URLs.
|
|
66
|
+
* the import gate to remote and data URLs. A lifetime retains the module's
|
|
67
|
+
* temporary URL until that signal aborts; omit it to retain the URL for
|
|
68
|
+
* the notebook's lifetime. The evaluated module itself stays cached.
|
|
61
69
|
*/
|
|
62
70
|
public getModule(options: {
|
|
63
71
|
jsUrl: string;
|
|
64
72
|
jsHash: string;
|
|
65
73
|
kernelAuthored?: boolean;
|
|
74
|
+
lifetime?: AbortSignal;
|
|
66
75
|
}): Promise<unknown> {
|
|
67
|
-
const { jsUrl, jsHash, kernelAuthored = false } = options;
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
76
|
+
const { jsUrl, jsHash, kernelAuthored = false, lifetime } = options;
|
|
77
|
+
let entry = this.#cache.get(jsHash);
|
|
78
|
+
if (!entry) {
|
|
79
|
+
const imported = this.#doImport(jsUrl, { kernelAuthored });
|
|
80
|
+
const created: ModuleEntry = {
|
|
81
|
+
references: 0,
|
|
82
|
+
dispose: () => undefined,
|
|
83
|
+
promise: imported.then(
|
|
84
|
+
({ module, dispose }) => {
|
|
85
|
+
created.dispose = dispose;
|
|
86
|
+
return module;
|
|
87
|
+
},
|
|
88
|
+
(error) => {
|
|
89
|
+
// An invalidated import must not evict its replacement.
|
|
90
|
+
if (this.#cache.get(jsHash) === created) {
|
|
91
|
+
this.#cache.delete(jsHash);
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
},
|
|
95
|
+
),
|
|
96
|
+
};
|
|
97
|
+
this.#cache.set(jsHash, created);
|
|
98
|
+
entry = created;
|
|
71
99
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
100
|
+
const retained = entry;
|
|
101
|
+
retained.references += 1;
|
|
102
|
+
const release = () => {
|
|
103
|
+
retained.references -= 1;
|
|
104
|
+
if (retained.references === 0) {
|
|
105
|
+
// Keep the evaluated module cached: re-importing would re-run its
|
|
106
|
+
// top-level side effects (e.g. `customElements.define`). Only the
|
|
107
|
+
// temporary URL is released.
|
|
108
|
+
void retained.promise.then(
|
|
109
|
+
() => {
|
|
110
|
+
retained.dispose();
|
|
111
|
+
retained.dispose = () => undefined;
|
|
112
|
+
},
|
|
113
|
+
() => undefined,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
if (lifetime?.aborted) {
|
|
118
|
+
release();
|
|
119
|
+
} else {
|
|
120
|
+
lifetime?.addEventListener("abort", release, { once: true });
|
|
121
|
+
}
|
|
122
|
+
return retained.promise;
|
|
81
123
|
}
|
|
82
124
|
|
|
83
125
|
public invalidate(jsHash: string): void {
|
|
@@ -87,7 +129,7 @@ class WidgetDefRegistry {
|
|
|
87
129
|
async #doImport(
|
|
88
130
|
jsUrl: string,
|
|
89
131
|
opts: { kernelAuthored?: boolean } = {},
|
|
90
|
-
): Promise<unknown> {
|
|
132
|
+
): Promise<{ module: unknown; dispose: () => void }> {
|
|
91
133
|
// By default, only trust marimo virtual file paths: arbitrary URLs
|
|
92
134
|
// would let markdown-injected elements import attacker-controlled
|
|
93
135
|
// JavaScript. Kernel-authored URLs (from an `EsmSpec`) are exempt —
|
|
@@ -103,11 +145,23 @@ class WidgetDefRegistry {
|
|
|
103
145
|
)}`,
|
|
104
146
|
);
|
|
105
147
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
148
|
+
const remoteUrl = asRemoteURL(jsUrl).toString();
|
|
149
|
+
const url = isStaticNotebook()
|
|
150
|
+
? resolveVirtualFileURL(remoteUrl)
|
|
151
|
+
: remoteUrl;
|
|
152
|
+
const dispose = () => {
|
|
153
|
+
// Only the static-file resolver's newly created URL belongs to us.
|
|
154
|
+
if (url !== remoteUrl) {
|
|
155
|
+
URL.revokeObjectURL(url);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
try {
|
|
159
|
+
const module = await import(/* @vite-ignore */ url);
|
|
160
|
+
return { module, dispose };
|
|
161
|
+
} catch (error) {
|
|
162
|
+
dispose();
|
|
163
|
+
throw error;
|
|
109
164
|
}
|
|
110
|
-
return import(/* @vite-ignore */ url);
|
|
111
165
|
}
|
|
112
166
|
}
|
|
113
167
|
|
|
@@ -132,6 +186,7 @@ interface CreateWidgetBindingOptions<T extends ModelState> {
|
|
|
132
186
|
model: Model<T>;
|
|
133
187
|
createHost: HostFactory;
|
|
134
188
|
controller?: AbortController;
|
|
189
|
+
onDestroy?: () => void;
|
|
135
190
|
}
|
|
136
191
|
|
|
137
192
|
async function safelyRunCleanup(cleanup: Cleanup, reason: string) {
|
|
@@ -159,6 +214,7 @@ export class WidgetBinding<T extends ModelState = ModelState> {
|
|
|
159
214
|
#createHost: HostFactory;
|
|
160
215
|
#cleanupTasks = new Set<Promise<void>>();
|
|
161
216
|
#viewTasks = new Set<Promise<void>>();
|
|
217
|
+
#onDestroy?: () => void;
|
|
162
218
|
|
|
163
219
|
private constructor(options: {
|
|
164
220
|
widget: ResolvedWidget<T>;
|
|
@@ -166,12 +222,14 @@ export class WidgetBinding<T extends ModelState = ModelState> {
|
|
|
166
222
|
exports: unknown;
|
|
167
223
|
controller: AbortController;
|
|
168
224
|
createHost: HostFactory;
|
|
225
|
+
onDestroy?: () => void;
|
|
169
226
|
}) {
|
|
170
227
|
this.#widget = options.widget;
|
|
171
228
|
this.#model = options.model;
|
|
172
229
|
this.#exports = options.exports;
|
|
173
230
|
this.#controller = options.controller;
|
|
174
231
|
this.#createHost = options.createHost;
|
|
232
|
+
this.#onDestroy = options.onDestroy;
|
|
175
233
|
}
|
|
176
234
|
|
|
177
235
|
/**
|
|
@@ -185,76 +243,94 @@ export class WidgetBinding<T extends ModelState = ModelState> {
|
|
|
185
243
|
model,
|
|
186
244
|
createHost,
|
|
187
245
|
controller = new AbortController(),
|
|
246
|
+
onDestroy,
|
|
188
247
|
}: CreateWidgetBindingOptions<T>): Promise<WidgetBinding<T>> {
|
|
189
248
|
const signal = controller.signal;
|
|
190
|
-
|
|
191
|
-
|
|
249
|
+
let lateCleanup: Promise<void> | undefined;
|
|
250
|
+
try {
|
|
251
|
+
const widget: ResolvedWidget<T> =
|
|
252
|
+
typeof widgetDef === "function" ? await widgetDef() : widgetDef;
|
|
192
253
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
254
|
+
if (signal.aborted) {
|
|
255
|
+
throw new Error("[anywidget] binding destroyed");
|
|
256
|
+
}
|
|
257
|
+
const initPromise = Promise.resolve(
|
|
258
|
+
widget.initialize?.({
|
|
259
|
+
model: modelProxy(model, signal),
|
|
260
|
+
experimental,
|
|
261
|
+
signal,
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
// If destroyed mid-initialize, still run a late-arriving legacy
|
|
265
|
+
// cleanup callback: the widget acquired resources.
|
|
266
|
+
lateCleanup = initPromise
|
|
267
|
+
.then(async (settled) => {
|
|
268
|
+
if (signal.aborted && isCleanup(settled)) {
|
|
269
|
+
await safelyRunCleanup(settled, "late initialize");
|
|
270
|
+
}
|
|
271
|
+
})
|
|
272
|
+
.catch(() => undefined);
|
|
209
273
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
274
|
+
// Race against destruction so a hung `initialize` can't strand
|
|
275
|
+
// callers whose model already closed.
|
|
276
|
+
const result = await Promise.race([
|
|
277
|
+
initPromise,
|
|
278
|
+
new Promise<never>((_, reject) => {
|
|
279
|
+
const abort = () =>
|
|
280
|
+
reject(new Error("[anywidget] binding destroyed"));
|
|
281
|
+
if (signal.aborted) {
|
|
282
|
+
abort();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
286
|
+
}),
|
|
287
|
+
]);
|
|
223
288
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
289
|
+
if (signal.aborted) {
|
|
290
|
+
throw new Error("[anywidget] binding destroyed");
|
|
291
|
+
}
|
|
227
292
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
293
|
+
// Distinguish anywidget's three return shapes:
|
|
294
|
+
// function → legacy cleanup callback (run on destroy)
|
|
295
|
+
// object → widget exports (anywidget>=0.11)
|
|
296
|
+
// void → nothing
|
|
297
|
+
let exports: unknown;
|
|
298
|
+
let initializeCleanup: Cleanup | undefined;
|
|
299
|
+
if (isCleanup(result)) {
|
|
300
|
+
initializeCleanup = result;
|
|
301
|
+
exports = undefined;
|
|
302
|
+
} else if (typeof result === "object" && result !== null) {
|
|
303
|
+
exports = result;
|
|
304
|
+
} else {
|
|
305
|
+
exports = undefined;
|
|
306
|
+
}
|
|
242
307
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
308
|
+
const binding = new WidgetBinding({
|
|
309
|
+
widget,
|
|
310
|
+
model,
|
|
311
|
+
exports,
|
|
312
|
+
controller,
|
|
313
|
+
createHost,
|
|
314
|
+
onDestroy,
|
|
315
|
+
});
|
|
316
|
+
if (initializeCleanup) {
|
|
317
|
+
signal.addEventListener(
|
|
318
|
+
"abort",
|
|
319
|
+
() => void binding.#trackCleanup(initializeCleanup, "initialize"),
|
|
320
|
+
{ once: true },
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
return binding;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
// A canceled initialize may still be using import.meta.url in its
|
|
326
|
+
// late cleanup. Keep the module alive until that work settles.
|
|
327
|
+
if (lateCleanup) {
|
|
328
|
+
void lateCleanup.then(() => onDestroy?.());
|
|
329
|
+
} else {
|
|
330
|
+
onDestroy?.();
|
|
331
|
+
}
|
|
332
|
+
throw error;
|
|
256
333
|
}
|
|
257
|
-
return binding;
|
|
258
334
|
}
|
|
259
335
|
|
|
260
336
|
/**
|
|
@@ -353,6 +429,8 @@ export class WidgetBinding<T extends ModelState = ModelState> {
|
|
|
353
429
|
while (this.#cleanupTasks.size > 0) {
|
|
354
430
|
await Promise.all(this.#cleanupTasks);
|
|
355
431
|
}
|
|
432
|
+
this.#onDestroy?.();
|
|
433
|
+
this.#onDestroy = undefined;
|
|
356
434
|
}
|
|
357
435
|
}
|
|
358
436
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
4
|
+
import type { ComponentProps } from "react";
|
|
5
|
+
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
|
6
|
+
import type { PopoverContent } from "@/components/ui/popover";
|
|
7
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
8
|
+
import { Chatbot } from "../chat-ui";
|
|
9
|
+
|
|
10
|
+
vi.mock("@/components/editor/ai/add-cell-with-ai", () => ({
|
|
11
|
+
PromptInput: ({ value }: { value: string }) => (
|
|
12
|
+
<textarea aria-label="Chat prompt" value={value} readOnly={true} />
|
|
13
|
+
),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
vi.mock("@/components/ui/popover", async (importOriginal) => {
|
|
17
|
+
const actual =
|
|
18
|
+
await importOriginal<typeof import("@/components/ui/popover")>();
|
|
19
|
+
return {
|
|
20
|
+
...actual,
|
|
21
|
+
// Keep the form mounted when the prompt menu takes focus so this tests
|
|
22
|
+
// the prompt reset rather than the overlay's incidental unmount.
|
|
23
|
+
PopoverContent: (props: ComponentProps<typeof PopoverContent>) => (
|
|
24
|
+
<actual.PopoverContent
|
|
25
|
+
{...props}
|
|
26
|
+
onInteractOutside={(event) => event.preventDefault()}
|
|
27
|
+
/>
|
|
28
|
+
),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("chat prompt variables", () => {
|
|
33
|
+
const originalScrollTo = HTMLElement.prototype.scrollTo;
|
|
34
|
+
beforeAll(() => {
|
|
35
|
+
HTMLElement.prototype.scrollTo = vi.fn();
|
|
36
|
+
});
|
|
37
|
+
afterAll(() => {
|
|
38
|
+
HTMLElement.prototype.scrollTo = originalScrollTo;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("clears entered values and replaces the fields when selecting another prompt", async () => {
|
|
42
|
+
const firstPrompt = "Tell {{name}} about {{topic}}";
|
|
43
|
+
const secondPrompt = "Send {{name}} to {{destination}}";
|
|
44
|
+
render(
|
|
45
|
+
<TooltipProvider>
|
|
46
|
+
<Chatbot
|
|
47
|
+
prompts={[firstPrompt, secondPrompt]}
|
|
48
|
+
config={{
|
|
49
|
+
max_tokens: null,
|
|
50
|
+
temperature: null,
|
|
51
|
+
top_p: null,
|
|
52
|
+
top_k: null,
|
|
53
|
+
frequency_penalty: null,
|
|
54
|
+
presence_penalty: null,
|
|
55
|
+
}}
|
|
56
|
+
showConfigurationControls={false}
|
|
57
|
+
maxHeight={undefined}
|
|
58
|
+
allowAttachments={false}
|
|
59
|
+
disabled={false}
|
|
60
|
+
value={[]}
|
|
61
|
+
setValue={vi.fn()}
|
|
62
|
+
host={document.createElement("div")}
|
|
63
|
+
get_chat_history={vi.fn().mockResolvedValue({ messages: [] })}
|
|
64
|
+
delete_chat_history={vi.fn().mockResolvedValue(null)}
|
|
65
|
+
delete_chat_message={vi.fn().mockResolvedValue(null)}
|
|
66
|
+
send_prompt={vi.fn().mockResolvedValue(null)}
|
|
67
|
+
cancel_prompt={vi.fn().mockResolvedValue(null)}
|
|
68
|
+
/>
|
|
69
|
+
</TooltipProvider>,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const promptMenu = screen.getByRole("button", { expanded: false });
|
|
73
|
+
fireEvent.keyDown(promptMenu, { key: "ArrowDown" });
|
|
74
|
+
fireEvent.click(await screen.findByRole("menuitem", { name: firstPrompt }));
|
|
75
|
+
fireEvent.change(await screen.findByLabelText("name"), {
|
|
76
|
+
target: { value: "Ada" },
|
|
77
|
+
});
|
|
78
|
+
fireEvent.change(screen.getByLabelText("topic"), {
|
|
79
|
+
target: { value: "Python" },
|
|
80
|
+
});
|
|
81
|
+
expect(screen.getByRole("button", { name: "Submit" })).toBeEnabled();
|
|
82
|
+
|
|
83
|
+
fireEvent.keyDown(promptMenu, { key: "ArrowDown" });
|
|
84
|
+
fireEvent.click(
|
|
85
|
+
await screen.findByRole("menuitem", { name: secondPrompt }),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(await screen.findByLabelText("destination")).toHaveValue("");
|
|
89
|
+
expect(screen.getByLabelText("name")).toHaveValue("");
|
|
90
|
+
expect(screen.queryByLabelText("topic")).not.toBeInTheDocument();
|
|
91
|
+
expect(screen.getByRole("button", { name: "Submit" })).toBeDisabled();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
Trash2Icon,
|
|
25
25
|
X,
|
|
26
26
|
} from "lucide-react";
|
|
27
|
-
import React, { useEffect, useRef, useState } from "react";
|
|
27
|
+
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
28
28
|
import { z } from "zod";
|
|
29
29
|
import {
|
|
30
30
|
describeChatAbortReason,
|
|
@@ -163,7 +163,9 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
163
163
|
|
|
164
164
|
// Use a ref to avoid stale closure in the fetch callback
|
|
165
165
|
const configRef = useRef<ChatConfig>(config);
|
|
166
|
-
|
|
166
|
+
useLayoutEffect(() => {
|
|
167
|
+
configRef.current = config;
|
|
168
|
+
}, [config]);
|
|
167
169
|
|
|
168
170
|
// For frontend-managed streaming, create a controller to enqueue chunks to.
|
|
169
171
|
const frontendStreamControllerRef =
|
|
@@ -411,9 +413,8 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
411
413
|
});
|
|
412
414
|
}, [messages.length, scrollContainerRef]);
|
|
413
415
|
|
|
414
|
-
const codemirrorView = codeMirrorInputRef.current?.view;
|
|
415
|
-
|
|
416
416
|
const resetInput = () => {
|
|
417
|
+
const codemirrorView = codeMirrorInputRef.current?.view;
|
|
417
418
|
// Clear input immediately by directly manipulating the editor
|
|
418
419
|
// There is some delay if we use setInput("") only
|
|
419
420
|
if (codemirrorView) {
|
|
@@ -440,6 +441,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
440
441
|
>
|
|
441
442
|
<div className="absolute top-0 right-0 flex justify-end z-10 border border-(--slate-6) bg-inherit rounded-bl-lg">
|
|
442
443
|
<Button
|
|
444
|
+
aria-label="Reset chat"
|
|
443
445
|
variant="text"
|
|
444
446
|
size="icon"
|
|
445
447
|
disabled={messages.length === 0}
|
|
@@ -470,7 +472,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
470
472
|
|
|
471
473
|
return (
|
|
472
474
|
<div
|
|
473
|
-
key={
|
|
475
|
+
key={message.id}
|
|
474
476
|
className={cn(
|
|
475
477
|
"flex flex-col group gap-2",
|
|
476
478
|
message.role === "user" ? "items-end" : "items-start",
|
|
@@ -493,7 +495,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
493
495
|
: undefined,
|
|
494
496
|
})}
|
|
495
497
|
</div>
|
|
496
|
-
<div className="flex justify-end text-xs gap-2
|
|
498
|
+
<div className="flex justify-end text-xs gap-2 opacity-0 group-hover:opacity-100 focus-within:opacity-100">
|
|
497
499
|
<CopyClipboardIcon
|
|
498
500
|
value={textContent}
|
|
499
501
|
className="h-3 w-3"
|
|
@@ -501,6 +503,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
501
503
|
/>
|
|
502
504
|
<button
|
|
503
505
|
type="button"
|
|
506
|
+
aria-label="Delete message"
|
|
504
507
|
onClick={() => handleDelete(message.id)}
|
|
505
508
|
className="text-xs text-(--slate-9) hover:text-(--slate-11)"
|
|
506
509
|
>
|
|
@@ -566,6 +569,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
566
569
|
onSelect={(prompt) => {
|
|
567
570
|
setInput(prompt);
|
|
568
571
|
requestAnimationFrame(() => {
|
|
572
|
+
const codemirrorView = codeMirrorInputRef.current?.view;
|
|
569
573
|
codemirrorView?.focus();
|
|
570
574
|
moveToEndOfEditor(codemirrorView);
|
|
571
575
|
});
|
|
@@ -862,6 +866,7 @@ const PromptsPopover: React.FC<{
|
|
|
862
866
|
|
|
863
867
|
<PopoverContent side="right" align="end" className="min-w-80 px-2">
|
|
864
868
|
<PromptVariablesForm
|
|
869
|
+
key={selectedPrompt}
|
|
865
870
|
prompt={selectedPrompt}
|
|
866
871
|
onClose={() => setIsPopoverOpen(false)}
|
|
867
872
|
onSelect={onSelect}
|
|
@@ -876,9 +881,7 @@ const PromptVariablesForm: React.FC<{
|
|
|
876
881
|
onClose: () => void;
|
|
877
882
|
onSelect: (prompt: string) => void;
|
|
878
883
|
}> = ({ prompt, onClose, onSelect }) => {
|
|
879
|
-
const [variables, setVariables] = useState<{ [key: string]: string }>({
|
|
880
|
-
|
|
881
|
-
useEffect(() => {
|
|
884
|
+
const [variables, setVariables] = useState<{ [key: string]: string }>(() => {
|
|
882
885
|
const variableRegex = /{{(\w+)}}/g;
|
|
883
886
|
const matches = [...prompt.matchAll(variableRegex)];
|
|
884
887
|
const initialVariables = matches.reduce<{ [key: string]: string }>(
|
|
@@ -888,8 +891,8 @@ const PromptVariablesForm: React.FC<{
|
|
|
888
891
|
},
|
|
889
892
|
{},
|
|
890
893
|
);
|
|
891
|
-
|
|
892
|
-
}
|
|
894
|
+
return initialVariables;
|
|
895
|
+
});
|
|
893
896
|
|
|
894
897
|
const handleVariableChange = (variable: string, value: string) => {
|
|
895
898
|
setVariables((prev) => ({ ...prev, [variable]: value }));
|
|
@@ -53,14 +53,14 @@ const AnyLanguageCodeMirror: React.FC<
|
|
|
53
53
|
extensions?: readonly Extension[];
|
|
54
54
|
}
|
|
55
55
|
> = ({
|
|
56
|
-
language,
|
|
56
|
+
language: requestedLanguage,
|
|
57
57
|
hideUnsupportedLanguageErrors,
|
|
58
58
|
showCopyButton,
|
|
59
59
|
extensions = EMPTY_EXTENSIONS,
|
|
60
60
|
...props
|
|
61
61
|
}) => {
|
|
62
62
|
// Maybe normalize the language to the extension
|
|
63
|
-
language = LANGUAGE_MAP[
|
|
63
|
+
const language = LANGUAGE_MAP[requestedLanguage || ""] || requestedLanguage;
|
|
64
64
|
|
|
65
65
|
const isSupported = isSupportedLanguage(language);
|
|
66
66
|
if (!isSupported) {
|
|
@@ -73,12 +73,16 @@ export const GlideDataEditor = ({
|
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
|
|
76
|
+
const editableColumnSet = useMemo(
|
|
77
|
+
() => (editableColumns === "all" ? null : new Set(editableColumns)),
|
|
78
|
+
[editableColumns],
|
|
79
|
+
);
|
|
76
80
|
|
|
77
81
|
const columns: ModifiedGridColumn[] = useMemo(() => {
|
|
78
82
|
const columns: ModifiedGridColumn[] = [];
|
|
79
83
|
for (const [columnName, fieldType] of columnFields) {
|
|
80
84
|
const editable =
|
|
81
|
-
|
|
85
|
+
editableColumnSet === null || editableColumnSet.has(columnName);
|
|
82
86
|
|
|
83
87
|
columns.push({
|
|
84
88
|
id: columnName,
|
|
@@ -100,7 +104,7 @@ export const GlideDataEditor = ({
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
return columns;
|
|
103
|
-
}, [columnFields, columnWidths,
|
|
107
|
+
}, [columnFields, columnWidths, editableColumnSet, theme]);
|
|
104
108
|
|
|
105
109
|
const getCellContent = useCallback(
|
|
106
110
|
(cell: Item): GridCell => {
|
|
@@ -110,8 +114,7 @@ export const GlideDataEditor = ({
|
|
|
110
114
|
const dataItem = dataRow[columns[col].title];
|
|
111
115
|
const columnKind = columns[col].kind;
|
|
112
116
|
const editable =
|
|
113
|
-
|
|
114
|
-
editableColumns.includes(columns[col].title);
|
|
117
|
+
editableColumnSet === null || editableColumnSet.has(columns[col].title);
|
|
115
118
|
|
|
116
119
|
if (columnKind === GridCellKind.Boolean) {
|
|
117
120
|
const value = Boolean(dataItem);
|
|
@@ -141,7 +144,7 @@ export const GlideDataEditor = ({
|
|
|
141
144
|
data: String(dataItem),
|
|
142
145
|
};
|
|
143
146
|
},
|
|
144
|
-
[columns, data,
|
|
147
|
+
[columns, data, editableColumnSet],
|
|
145
148
|
);
|
|
146
149
|
|
|
147
150
|
const onCellEdited = useCallback(
|
|
@@ -147,6 +147,8 @@ export function pasteCells(options: {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
const edits: Edits["edits"] = [];
|
|
150
|
+
const editableColumnSet =
|
|
151
|
+
editableColumns === "all" ? null : new Set(editableColumns);
|
|
150
152
|
|
|
151
153
|
for (const [rowIndex, dataRow] of parsedData.entries()) {
|
|
152
154
|
if (!dataRow) {
|
|
@@ -175,7 +177,7 @@ export function pasteCells(options: {
|
|
|
175
177
|
const column = columns[targetColIdx];
|
|
176
178
|
const columnType = column.dataType;
|
|
177
179
|
const editable =
|
|
178
|
-
|
|
180
|
+
editableColumnSet === null || editableColumnSet.has(column.title);
|
|
179
181
|
|
|
180
182
|
if (!editable) {
|
|
181
183
|
continue;
|
|
@@ -47,7 +47,7 @@ const ConnectedDataExplorerComponent = (props: DataTableProps): JSX.Element => {
|
|
|
47
47
|
// Subscribe to the store
|
|
48
48
|
const unsub = store.sub(chartSpecAtom, () => {
|
|
49
49
|
const value = store.get(chartSpecAtom);
|
|
50
|
-
const { schema, ...withoutSchema } = value;
|
|
50
|
+
const { schema: _schema, ...withoutSchema } = value;
|
|
51
51
|
props.setValue(withoutSchema);
|
|
52
52
|
});
|
|
53
53
|
|
|
@@ -60,7 +60,9 @@ export const ColumnSummary: React.FC<Props> = ({ schema }) => {
|
|
|
60
60
|
field: field,
|
|
61
61
|
});
|
|
62
62
|
return (
|
|
63
|
-
<
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
aria-pressed={selectedField === field}
|
|
64
66
|
key={field}
|
|
65
67
|
className={cn(
|
|
66
68
|
"hover:bg-muted self-start px-2 py-2 rounded flex flex-row gap-1 items-center cursor-pointer lg:justify-center text-sm truncate shrink-0 overflow-hidden",
|
|
@@ -81,7 +83,7 @@ export const ColumnSummary: React.FC<Props> = ({ schema }) => {
|
|
|
81
83
|
({cardinality})
|
|
82
84
|
</span>
|
|
83
85
|
)}
|
|
84
|
-
</
|
|
86
|
+
</button>
|
|
85
87
|
);
|
|
86
88
|
})}
|
|
87
89
|
{hasMore && (
|
|
@@ -47,7 +47,7 @@ const { valueAtom: chartSpecAtom, useActions } = createReducerAndAtoms(
|
|
|
47
47
|
},
|
|
48
48
|
set: (state, next: ChartSpec) => {
|
|
49
49
|
// remove schema
|
|
50
|
-
const { schema, ...rest } = next;
|
|
50
|
+
const { schema: _schema, ...rest } = next;
|
|
51
51
|
return { ...state, ...rest };
|
|
52
52
|
},
|
|
53
53
|
},
|
|
@@ -154,7 +154,7 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
154
154
|
)
|
|
155
155
|
.output(
|
|
156
156
|
z.object({
|
|
157
|
-
data: z.union([z.string(), z.array(z.
|
|
157
|
+
data: z.union([z.string(), z.array(z.looseObject({}))]),
|
|
158
158
|
total_rows: z.number(),
|
|
159
159
|
}),
|
|
160
160
|
),
|
|
@@ -192,7 +192,6 @@ const EMPTY: Transformations = {
|
|
|
192
192
|
export const DataFrameComponent = memo(
|
|
193
193
|
({
|
|
194
194
|
columns,
|
|
195
|
-
dataframeName,
|
|
196
195
|
pageSize,
|
|
197
196
|
showDownload,
|
|
198
197
|
lazy,
|