@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
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
VisibilityToggleButton,
|
|
14
14
|
} from "@/components/editor/file-tree/tree-actions";
|
|
15
15
|
import { CopyClipboardIcon } from "@/components/icons/copy-icon";
|
|
16
|
-
import { Button } from "@/components/ui/button";
|
|
16
|
+
import { Button, buttonVariants } from "@/components/ui/button";
|
|
17
17
|
import { Command, CommandInput, CommandItem } from "@/components/ui/command";
|
|
18
18
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
19
19
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
@@ -78,6 +78,7 @@ import {
|
|
|
78
78
|
areChildSchemasResolved,
|
|
79
79
|
areSchemasResolved,
|
|
80
80
|
areTablesResolved,
|
|
81
|
+
fullyQualifiedTableName,
|
|
81
82
|
isSchemaless,
|
|
82
83
|
schemaSubtreeMatchesSearch,
|
|
83
84
|
shouldExpandDatabaseForSearch,
|
|
@@ -284,6 +285,7 @@ export const DataSources: React.FC = () => {
|
|
|
284
285
|
{hasSearch && (
|
|
285
286
|
<button
|
|
286
287
|
type="button"
|
|
288
|
+
aria-label="Clear table search"
|
|
287
289
|
className="float-right border-b px-2 m-0 h-full hover:bg-accent hover:text-accent-foreground"
|
|
288
290
|
onClick={() => setSearchValue("")}
|
|
289
291
|
>
|
|
@@ -636,7 +638,7 @@ const SchemaNode: React.FC<SchemaNodeProps> = (props) => {
|
|
|
636
638
|
const [prevSearchValue, setPrevSearchValue] = React.useState(searchValue);
|
|
637
639
|
const [prevExpandForSearch, setPrevExpandForSearch] =
|
|
638
640
|
React.useState(expandForSearch);
|
|
639
|
-
const uniqueValue =
|
|
641
|
+
const uniqueValue = JSON.stringify(["schema", databaseName, ...schemaPath]);
|
|
640
642
|
const childSchemas = schema.child_schemas ?? [];
|
|
641
643
|
|
|
642
644
|
// Re-sync when the query changes or when newly resolved data turns this
|
|
@@ -702,7 +704,40 @@ const SchemaNode: React.FC<SchemaNodeProps> = (props) => {
|
|
|
702
704
|
);
|
|
703
705
|
};
|
|
704
706
|
|
|
705
|
-
|
|
707
|
+
// Kept outside the component because the React Compiler does not yet
|
|
708
|
+
// support try/finally inside component bodies.
|
|
709
|
+
async function loadTableList(
|
|
710
|
+
sqlTableContext: SQLTableContext,
|
|
711
|
+
addTableList: ReturnType<typeof useDataSourceActions>["addTableList"],
|
|
712
|
+
setLoading: (loading: boolean) => void,
|
|
713
|
+
) {
|
|
714
|
+
setLoading(true);
|
|
715
|
+
try {
|
|
716
|
+
const { engine, database, schema, schemaPath } = sqlTableContext;
|
|
717
|
+
const previewTableList = await PreviewSQLTableList.request({
|
|
718
|
+
engine: engine,
|
|
719
|
+
database: database,
|
|
720
|
+
schema: schema,
|
|
721
|
+
schemaPath: schemaPath ?? [],
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
if (!previewTableList?.tables) {
|
|
725
|
+
throw new Error("No tables available");
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
addTableList({
|
|
729
|
+
tables: previewTableList.tables,
|
|
730
|
+
sqlTableContext: sqlTableContext,
|
|
731
|
+
});
|
|
732
|
+
} finally {
|
|
733
|
+
setLoading(false);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* This is exported for testing purposes only.
|
|
739
|
+
*/
|
|
740
|
+
export const TableList: React.FC<{
|
|
706
741
|
tables: DataTable[];
|
|
707
742
|
sqlTableContext?: SQLTableContext;
|
|
708
743
|
searchValue?: string;
|
|
@@ -731,26 +766,7 @@ const TableList: React.FC<{
|
|
|
731
766
|
// resets tablesResolved to false).
|
|
732
767
|
const { isPending, error } = useAsyncData(async () => {
|
|
733
768
|
if (!tablesResolved && sqlTableContext) {
|
|
734
|
-
setTablesLoading
|
|
735
|
-
|
|
736
|
-
const { engine, database, schema, schemaPath } = sqlTableContext;
|
|
737
|
-
const previewTableList = await PreviewSQLTableList.request({
|
|
738
|
-
engine: engine,
|
|
739
|
-
database: database,
|
|
740
|
-
schema: schema,
|
|
741
|
-
schemaPath: schemaPath ?? [],
|
|
742
|
-
});
|
|
743
|
-
|
|
744
|
-
if (!previewTableList?.tables) {
|
|
745
|
-
setTablesLoading(false);
|
|
746
|
-
throw new Error("No tables available");
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
addTableList({
|
|
750
|
-
tables: previewTableList.tables,
|
|
751
|
-
sqlTableContext: sqlTableContext,
|
|
752
|
-
});
|
|
753
|
-
setTablesLoading(false);
|
|
769
|
+
await loadTableList(sqlTableContext, addTableList, setTablesLoading);
|
|
754
770
|
}
|
|
755
771
|
}, [tablesResolved, sqlTableContext]);
|
|
756
772
|
|
|
@@ -964,6 +980,7 @@ const DatasetTableItem: React.FC<{
|
|
|
964
980
|
{renderRowsByColumns()}
|
|
965
981
|
<Tooltip content="Add table to notebook" delayDuration={400}>
|
|
966
982
|
<Button
|
|
983
|
+
aria-label={`Add table ${table.name} to notebook`}
|
|
967
984
|
className="group-hover:inline-flex hidden"
|
|
968
985
|
variant="text"
|
|
969
986
|
size="icon"
|
|
@@ -1054,19 +1071,16 @@ const DatasetColumnItem: React.FC<{
|
|
|
1054
1071
|
{isIndexed &&
|
|
1055
1072
|
renderItemSubtext({ tooltipContent: "Indexed", content: "IDX" })}
|
|
1056
1073
|
</div>
|
|
1057
|
-
<
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
/>
|
|
1068
|
-
</Button>
|
|
1069
|
-
</Tooltip>
|
|
1074
|
+
<CopyClipboardIcon
|
|
1075
|
+
tooltip="Copy column name"
|
|
1076
|
+
value={column.name}
|
|
1077
|
+
ariaLabel={`Copy column name ${column.name}`}
|
|
1078
|
+
className="h-3 w-3"
|
|
1079
|
+
buttonClassName={cn(
|
|
1080
|
+
buttonVariants({ variant: "text", size: "icon" }),
|
|
1081
|
+
"group-hover:opacity-100 opacity-0 hover:bg-muted text-muted-foreground hover:text-foreground",
|
|
1082
|
+
)}
|
|
1083
|
+
/>
|
|
1070
1084
|
<span className="text-xs text-muted-foreground">
|
|
1071
1085
|
{column.external_type}
|
|
1072
1086
|
</span>
|
|
@@ -1082,9 +1096,7 @@ const DatasetColumnItem: React.FC<{
|
|
|
1082
1096
|
column={column}
|
|
1083
1097
|
onAddColumnChart={handleAddColumn}
|
|
1084
1098
|
preview={columnsPreviews.get(
|
|
1085
|
-
sqlTableContext
|
|
1086
|
-
? `${sqlTableContext.database}.${sqlTableContext.schema}.${table.name}:${column.name}`
|
|
1087
|
-
: `${table.name}:${column.name}`,
|
|
1099
|
+
`${fullyQualifiedTableName(sqlTableContext, table.name)}:${column.name}`,
|
|
1088
1100
|
)}
|
|
1089
1101
|
sqlTableContext={sqlTableContext}
|
|
1090
1102
|
/>
|
|
@@ -13,26 +13,29 @@ import type {
|
|
|
13
13
|
import { logNever } from "@/utils/assertNever";
|
|
14
14
|
import type { ColumnHeaderStatsKey } from "../data-table/types";
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
function tablePath(context: SQLTableContext, tableName: string): string[] {
|
|
17
|
+
const segments = context.schemaPath?.length
|
|
18
|
+
? context.schemaPath
|
|
19
|
+
: [context.schema];
|
|
20
|
+
return [context.database, ...segments.filter(Boolean), tableName];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
23
|
export function tableUniqueId(
|
|
24
|
-
|
|
24
|
+
context: SQLTableContext | undefined,
|
|
25
25
|
tableName: string,
|
|
26
26
|
): string {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
return context ? JSON.stringify(tablePath(context, tableName)) : tableName;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function fullyQualifiedTableName(
|
|
31
|
+
context: SQLTableContext | undefined,
|
|
32
|
+
tableName: string,
|
|
33
|
+
): string {
|
|
34
|
+
return context
|
|
35
|
+
? getFormatter(context.dialect).formatTablePath(
|
|
36
|
+
tablePath(context, tableName),
|
|
37
|
+
)
|
|
38
|
+
: tableName;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
// Some databases have no schemas, so we don't show it (eg. Clickhouse)
|
|
@@ -114,6 +117,10 @@ const defaultFormatter: SqlCodeFormatter = {
|
|
|
114
117
|
`SELECT ${columnName} FROM ${tableName} LIMIT 100`,
|
|
115
118
|
};
|
|
116
119
|
|
|
120
|
+
function quoteIdentifier(identifier: string): string {
|
|
121
|
+
return `"${identifier.replaceAll('"', '""')}"`;
|
|
122
|
+
}
|
|
123
|
+
|
|
117
124
|
function getFormatter(dialect: string): SqlCodeFormatter {
|
|
118
125
|
dialect = dialect.toLowerCase();
|
|
119
126
|
if (!isKnownDialect(dialect)) {
|
|
@@ -146,9 +153,9 @@ function getFormatter(dialect: string): SqlCodeFormatter {
|
|
|
146
153
|
// Quote column and table names to avoid raising errors on weird characters
|
|
147
154
|
return {
|
|
148
155
|
formatTablePath: (tablePath: string[]) =>
|
|
149
|
-
tablePath.map(
|
|
156
|
+
tablePath.map(quoteIdentifier).join("."),
|
|
150
157
|
formatSelectClause: (columnName: string, tableName: string) =>
|
|
151
|
-
`SELECT ${columnName === "*" ? "*" :
|
|
158
|
+
`SELECT ${columnName === "*" ? "*" : quoteIdentifier(columnName)} FROM ${tableName} LIMIT 100`,
|
|
152
159
|
};
|
|
153
160
|
case "db2":
|
|
154
161
|
case "db2i":
|
|
@@ -194,6 +201,7 @@ export function sqlCode({
|
|
|
194
201
|
engine,
|
|
195
202
|
schema,
|
|
196
203
|
defaultSchema,
|
|
204
|
+
schemaPath,
|
|
197
205
|
defaultDatabase,
|
|
198
206
|
database,
|
|
199
207
|
dialect,
|
|
@@ -207,12 +215,13 @@ export function sqlCode({
|
|
|
207
215
|
}
|
|
208
216
|
} else {
|
|
209
217
|
// Include schema if it's not the default schema
|
|
210
|
-
|
|
211
|
-
|
|
218
|
+
const path = schemaPath?.length ? schemaPath : [schema];
|
|
219
|
+
if (path.length > 1 || path[0] !== defaultSchema) {
|
|
220
|
+
tablePath.unshift(...path);
|
|
212
221
|
}
|
|
213
222
|
|
|
214
|
-
//
|
|
215
|
-
if (database !== defaultDatabase) {
|
|
223
|
+
// Nested schema names can also be attached catalog names.
|
|
224
|
+
if (path.length > 1 || database !== defaultDatabase) {
|
|
216
225
|
tablePath.unshift(database);
|
|
217
226
|
}
|
|
218
227
|
}
|
|
@@ -162,6 +162,7 @@ export const DebuggerControls: React.FC<{
|
|
|
162
162
|
<div className="flex">
|
|
163
163
|
<Tooltip content="Next line">
|
|
164
164
|
<Button
|
|
165
|
+
aria-label="Next line"
|
|
165
166
|
variant="text"
|
|
166
167
|
size="icon"
|
|
167
168
|
data-testid="debugger-next-button"
|
|
@@ -173,6 +174,7 @@ export const DebuggerControls: React.FC<{
|
|
|
173
174
|
</Tooltip>
|
|
174
175
|
<Tooltip content="Continue execution">
|
|
175
176
|
<Button
|
|
177
|
+
aria-label="Continue execution"
|
|
176
178
|
variant="text"
|
|
177
179
|
size="icon"
|
|
178
180
|
data-testid="debugger-continue-button"
|
|
@@ -187,6 +189,7 @@ export const DebuggerControls: React.FC<{
|
|
|
187
189
|
</Tooltip>
|
|
188
190
|
<Tooltip content="Print stack trace">
|
|
189
191
|
<Button
|
|
192
|
+
aria-label="Print stack trace"
|
|
190
193
|
variant="text"
|
|
191
194
|
size="icon"
|
|
192
195
|
data-testid="debugger-stack-button"
|
|
@@ -198,6 +201,7 @@ export const DebuggerControls: React.FC<{
|
|
|
198
201
|
</Tooltip>
|
|
199
202
|
<Tooltip content="Help">
|
|
200
203
|
<Button
|
|
204
|
+
aria-label="Debugger help"
|
|
201
205
|
variant="text"
|
|
202
206
|
size="icon"
|
|
203
207
|
data-testid="debugger-help-button"
|
|
@@ -210,6 +214,7 @@ export const DebuggerControls: React.FC<{
|
|
|
210
214
|
{onClear && (
|
|
211
215
|
<Tooltip content="Quit and clear">
|
|
212
216
|
<Button
|
|
217
|
+
aria-label="Quit and clear debugger"
|
|
213
218
|
variant="text"
|
|
214
219
|
size="icon"
|
|
215
220
|
data-testid="debugger-clear-button"
|
|
@@ -85,13 +85,13 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
85
85
|
|
|
86
86
|
// oxlint-disable-next-line react/hook-use-state
|
|
87
87
|
const [initial] = useState(() => {
|
|
88
|
-
const elements = elementsBuilder.createElements(
|
|
88
|
+
const elements = elementsBuilder.createElements({
|
|
89
89
|
cellIds,
|
|
90
90
|
cellAtoms,
|
|
91
91
|
variables,
|
|
92
|
-
settings.hidePureMarkdown,
|
|
93
|
-
settings.hideReusableFunctions,
|
|
94
|
-
);
|
|
92
|
+
hidePureMarkdown: settings.hidePureMarkdown,
|
|
93
|
+
hideReusableFunctions: settings.hideReusableFunctions,
|
|
94
|
+
});
|
|
95
95
|
return layoutElements({
|
|
96
96
|
nodes: withExpansion(elements.nodes, expandedIds),
|
|
97
97
|
edges: elements.edges,
|
|
@@ -163,13 +163,13 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
163
163
|
|
|
164
164
|
// Rebuild + re-layout when the graph inputs or the expand/collapse set change.
|
|
165
165
|
useEffect(() => {
|
|
166
|
-
const elements = elementsBuilder.createElements(
|
|
166
|
+
const elements = elementsBuilder.createElements({
|
|
167
167
|
cellIds,
|
|
168
168
|
cellAtoms,
|
|
169
169
|
variables,
|
|
170
|
-
settings.hidePureMarkdown,
|
|
171
|
-
settings.hideReusableFunctions,
|
|
172
|
-
);
|
|
170
|
+
hidePureMarkdown: settings.hidePureMarkdown,
|
|
171
|
+
hideReusableFunctions: settings.hideReusableFunctions,
|
|
172
|
+
});
|
|
173
173
|
syncChanges({
|
|
174
174
|
nodes: withExpansion(elements.nodes, expandedIds),
|
|
175
175
|
edges: elements.edges,
|
|
@@ -42,6 +42,14 @@ export interface NodeData {
|
|
|
42
42
|
}
|
|
43
43
|
export type CustomNodeProps = NodeProps<NodeData>;
|
|
44
44
|
|
|
45
|
+
interface CreateElementsOptions {
|
|
46
|
+
cellIds: CellId[];
|
|
47
|
+
cellAtoms: Atom<CellData>[];
|
|
48
|
+
variables: Variables;
|
|
49
|
+
hidePureMarkdown: boolean;
|
|
50
|
+
hideReusableFunctions: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
const LINE_HEIGHT = 11; // matches TinyCode.css
|
|
46
54
|
|
|
47
55
|
export function getNodeHeight(linesOfCode: number) {
|
|
@@ -176,13 +184,10 @@ export function computeDefsByCell(
|
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
interface ElementsBuilder {
|
|
179
|
-
createElements: (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
hidePureMarkdown: boolean,
|
|
184
|
-
hideReusableFunctions: boolean,
|
|
185
|
-
) => { nodes: Node<NodeData>[]; edges: Edge[] };
|
|
187
|
+
createElements: (options: CreateElementsOptions) => {
|
|
188
|
+
nodes: Node<NodeData>[];
|
|
189
|
+
edges: Edge[];
|
|
190
|
+
};
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
export class VerticalElementsBuilder implements ElementsBuilder {
|
|
@@ -225,13 +230,11 @@ export class VerticalElementsBuilder implements ElementsBuilder {
|
|
|
225
230
|
};
|
|
226
231
|
}
|
|
227
232
|
|
|
228
|
-
public createElements(
|
|
229
|
-
cellIds
|
|
230
|
-
cellAtoms
|
|
231
|
-
variables
|
|
232
|
-
|
|
233
|
-
_hideReusableFunctions: boolean,
|
|
234
|
-
) {
|
|
233
|
+
public createElements({
|
|
234
|
+
cellIds,
|
|
235
|
+
cellAtoms,
|
|
236
|
+
variables,
|
|
237
|
+
}: CreateElementsOptions) {
|
|
235
238
|
let prevY = 0;
|
|
236
239
|
const nodes: Node<NodeData>[] = [];
|
|
237
240
|
const edges: Edge[] = [];
|
|
@@ -311,13 +314,13 @@ export class TreeElementsBuilder implements ElementsBuilder {
|
|
|
311
314
|
};
|
|
312
315
|
}
|
|
313
316
|
|
|
314
|
-
public createElements(
|
|
315
|
-
cellIds
|
|
316
|
-
cellAtoms
|
|
317
|
-
variables
|
|
318
|
-
hidePureMarkdown
|
|
319
|
-
hideReusableFunctions
|
|
320
|
-
) {
|
|
317
|
+
public createElements({
|
|
318
|
+
cellIds,
|
|
319
|
+
cellAtoms,
|
|
320
|
+
variables,
|
|
321
|
+
hidePureMarkdown,
|
|
322
|
+
hideReusableFunctions,
|
|
323
|
+
}: CreateElementsOptions) {
|
|
321
324
|
const nodes: Node<NodeData>[] = [];
|
|
322
325
|
|
|
323
326
|
const cellRuntime = getNotebook().cellRuntime;
|
|
@@ -216,11 +216,12 @@ export const GraphSelectionPanel: React.FC<{
|
|
|
216
216
|
</Button>
|
|
217
217
|
</Tooltip>
|
|
218
218
|
<ConnectionCellActionsDropdown cellId={selection.id}>
|
|
219
|
-
<Button variant="ghost" size="icon">
|
|
219
|
+
<Button aria-label="Cell actions" variant="ghost" size="icon">
|
|
220
220
|
<MoreVerticalIcon className="w-4 h-4" />
|
|
221
221
|
</Button>
|
|
222
222
|
</ConnectionCellActionsDropdown>
|
|
223
223
|
<Button
|
|
224
|
+
aria-label="Close cell details"
|
|
224
225
|
variant="text"
|
|
225
226
|
size="icon"
|
|
226
227
|
onClick={() => {
|
|
@@ -7,10 +7,12 @@ import { boundingBox, placeIslands } from "../layout";
|
|
|
7
7
|
|
|
8
8
|
function node(
|
|
9
9
|
id: string,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
{
|
|
11
|
+
x,
|
|
12
|
+
y,
|
|
13
|
+
width,
|
|
14
|
+
height,
|
|
15
|
+
}: { x: number; y: number; width: number; height: number },
|
|
14
16
|
): Node<NodeData> {
|
|
15
17
|
return {
|
|
16
18
|
id,
|
|
@@ -28,8 +30,8 @@ describe("boundingBox", () => {
|
|
|
28
30
|
|
|
29
31
|
it("spans position + size across nodes", () => {
|
|
30
32
|
const box = boundingBox([
|
|
31
|
-
node("a", 0, 0, 50, 50),
|
|
32
|
-
node("b", 10, 20, 100, 40),
|
|
33
|
+
node("a", { x: 0, y: 0, width: 50, height: 50 }),
|
|
34
|
+
node("b", { x: 10, y: 20, width: 100, height: 40 }),
|
|
33
35
|
]);
|
|
34
36
|
expect(box).toEqual({ minX: 0, minY: 0, maxX: 110, maxY: 60 });
|
|
35
37
|
});
|
|
@@ -52,12 +54,17 @@ describe("boundingBox", () => {
|
|
|
52
54
|
|
|
53
55
|
describe("placeIslands", () => {
|
|
54
56
|
it("returns nothing when there are no islands", () => {
|
|
55
|
-
expect(
|
|
57
|
+
expect(
|
|
58
|
+
placeIslands([], [node("a", { x: 0, y: 0, width: 100, height: 100 })]),
|
|
59
|
+
).toEqual([]);
|
|
56
60
|
});
|
|
57
61
|
|
|
58
62
|
it("stacks islands in a column to the right of the placed graph", () => {
|
|
59
|
-
const placed = [node("main", 0, 0, 200, 300)];
|
|
60
|
-
const islands = [
|
|
63
|
+
const placed = [node("main", { x: 0, y: 0, width: 200, height: 300 })];
|
|
64
|
+
const islands = [
|
|
65
|
+
node("i0", { x: 0, y: 0, width: 90, height: 40 }),
|
|
66
|
+
node("i1", { x: 0, y: 0, width: 90, height: 40 }),
|
|
67
|
+
];
|
|
61
68
|
const result = placeIslands(islands, placed);
|
|
62
69
|
// startX = maxX(200) + margin(40) = 240; startY = minY(0).
|
|
63
70
|
expect(result[0].position).toEqual({ x: 240, y: 0 });
|
|
@@ -66,9 +73,9 @@ describe("placeIslands", () => {
|
|
|
66
73
|
});
|
|
67
74
|
|
|
68
75
|
it("wraps into a new column when the column gets too tall", () => {
|
|
69
|
-
const placed = [node("main", 0, 0, 200, 300)];
|
|
76
|
+
const placed = [node("main", { x: 0, y: 0, width: 200, height: 300 })];
|
|
70
77
|
const islands = Array.from({ length: 10 }, (_, i) =>
|
|
71
|
-
node(`i${i}`, 0, 0, 90, 40),
|
|
78
|
+
node(`i${i}`, { x: 0, y: 0, width: 90, height: 40 }),
|
|
72
79
|
);
|
|
73
80
|
const result = placeIslands(islands, placed);
|
|
74
81
|
const firstColumnX = result[0].position.x;
|
|
@@ -71,7 +71,6 @@ export const SortableCell = React.forwardRef(
|
|
|
71
71
|
return (
|
|
72
72
|
<SortableCellInternal
|
|
73
73
|
ref={ref}
|
|
74
|
-
cellId={cellId}
|
|
75
74
|
canMoveX={canMoveX}
|
|
76
75
|
{...props}
|
|
77
76
|
attributes={attributes}
|
|
@@ -86,7 +85,7 @@ export const SortableCell = React.forwardRef(
|
|
|
86
85
|
);
|
|
87
86
|
SortableCell.displayName = "SortableCell";
|
|
88
87
|
|
|
89
|
-
interface SortableCellInternalProps extends Props {
|
|
88
|
+
interface SortableCellInternalProps extends Omit<Props, "cellId"> {
|
|
90
89
|
children: React.ReactNode;
|
|
91
90
|
attributes: DraggableAttributes;
|
|
92
91
|
listeners: SyntheticListenerMap | undefined;
|
|
@@ -99,7 +98,6 @@ interface SortableCellInternalProps extends Props {
|
|
|
99
98
|
const SortableCellInternal = React.forwardRef(
|
|
100
99
|
(
|
|
101
100
|
{
|
|
102
|
-
cellId,
|
|
103
101
|
canMoveX,
|
|
104
102
|
children,
|
|
105
103
|
attributes,
|
|
@@ -1,17 +1,41 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
act,
|
|
5
|
+
render as renderComponent,
|
|
6
|
+
waitFor,
|
|
7
|
+
} from "@testing-library/react";
|
|
4
8
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
-
import {
|
|
9
|
+
import { Provider, createStore } from "jotai";
|
|
10
|
+
import type { ReactNode } from "react";
|
|
11
|
+
import { MockNotebook } from "@/__mocks__/notebook";
|
|
12
|
+
import { cellId } from "@/__tests__/branded";
|
|
13
|
+
import { notebookAtom } from "@/core/cells/cells";
|
|
6
14
|
import { DynamicFavicon } from "../dynamic-favicon";
|
|
7
15
|
|
|
8
|
-
// Mock useCellErrors hook
|
|
9
|
-
vi.mock("@/core/cells/cells", () => ({
|
|
10
|
-
useCellErrors: vi.fn(),
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
16
|
describe("DynamicFavicon", () => {
|
|
14
17
|
let favicon: HTMLLinkElement;
|
|
18
|
+
let store: ReturnType<typeof createStore>;
|
|
19
|
+
const id = cellId("cell");
|
|
20
|
+
|
|
21
|
+
function render(ui: ReactNode) {
|
|
22
|
+
return renderComponent(ui, {
|
|
23
|
+
wrapper: ({ children }) => <Provider store={store}>{children}</Provider>,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function setErrors() {
|
|
28
|
+
store.set(
|
|
29
|
+
notebookAtom,
|
|
30
|
+
MockNotebook.notebookStateWithErrors([
|
|
31
|
+
{
|
|
32
|
+
cellId: id,
|
|
33
|
+
cellName: "cell",
|
|
34
|
+
errorData: [MockNotebook.errors.syntax("Invalid syntax")],
|
|
35
|
+
},
|
|
36
|
+
]),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
15
39
|
|
|
16
40
|
beforeEach(() => {
|
|
17
41
|
document
|
|
@@ -27,15 +51,20 @@ describe("DynamicFavicon", () => {
|
|
|
27
51
|
// Mock document.hasFocus
|
|
28
52
|
vi.spyOn(document, "hasFocus").mockReturnValue(true);
|
|
29
53
|
|
|
30
|
-
|
|
31
|
-
|
|
54
|
+
store = createStore();
|
|
55
|
+
store.set(
|
|
56
|
+
notebookAtom,
|
|
57
|
+
MockNotebook.notebookState({
|
|
58
|
+
cellData: { [id]: { code: "x = 1" } },
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
32
61
|
});
|
|
33
62
|
|
|
34
63
|
afterEach(() => {
|
|
35
64
|
document
|
|
36
65
|
.querySelectorAll("link[rel~='icon']")
|
|
37
66
|
.forEach((element) => element.remove());
|
|
38
|
-
vi.
|
|
67
|
+
vi.restoreAllMocks();
|
|
39
68
|
vi.useRealTimers();
|
|
40
69
|
});
|
|
41
70
|
|
|
@@ -67,9 +96,7 @@ describe("DynamicFavicon", () => {
|
|
|
67
96
|
});
|
|
68
97
|
|
|
69
98
|
it("should show error favicon when run completes with errors", async () => {
|
|
70
|
-
(
|
|
71
|
-
{ error: "mock error" },
|
|
72
|
-
]);
|
|
99
|
+
setErrors();
|
|
73
100
|
|
|
74
101
|
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
75
102
|
|
|
@@ -147,6 +174,72 @@ describe("DynamicFavicon", () => {
|
|
|
147
174
|
});
|
|
148
175
|
});
|
|
149
176
|
|
|
177
|
+
it("does not look up or rewrite the favicon when code changes", async () => {
|
|
178
|
+
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
179
|
+
await waitFor(() => expect(favicon.href).toContain("circle-play.ico"));
|
|
180
|
+
rerender(<DynamicFavicon isRunning={false} />);
|
|
181
|
+
await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
|
|
182
|
+
const lookup = vi.spyOn(document, "querySelector");
|
|
183
|
+
const write = vi.spyOn(favicon, "href", "set");
|
|
184
|
+
|
|
185
|
+
await act(async () => {
|
|
186
|
+
store.set(notebookAtom, (state) => ({
|
|
187
|
+
...state,
|
|
188
|
+
cellData: {
|
|
189
|
+
...state.cellData,
|
|
190
|
+
[id]: { ...state.cellData[id], code: "x = 2" },
|
|
191
|
+
},
|
|
192
|
+
}));
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
expect(
|
|
196
|
+
lookup.mock.calls.filter(
|
|
197
|
+
([selector]) => selector === "link[rel~='icon']",
|
|
198
|
+
),
|
|
199
|
+
).toEqual([]);
|
|
200
|
+
expect(write).not.toHaveBeenCalled();
|
|
201
|
+
lookup.mockRestore();
|
|
202
|
+
write.mockRestore();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("updates the favicon when the error count changes", async () => {
|
|
206
|
+
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
207
|
+
await waitFor(() => expect(favicon.href).toContain("circle-play.ico"));
|
|
208
|
+
rerender(<DynamicFavicon isRunning={false} />);
|
|
209
|
+
await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
|
|
210
|
+
|
|
211
|
+
act(() => setErrors());
|
|
212
|
+
await waitFor(() => expect(favicon.href).toContain("circle-x.ico"));
|
|
213
|
+
|
|
214
|
+
act(() =>
|
|
215
|
+
store.set(
|
|
216
|
+
notebookAtom,
|
|
217
|
+
MockNotebook.notebookState({ cellData: { [id]: {} } }),
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
await waitFor(() => expect(favicon.href).toContain("circle-check.ico"));
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("keeps the completion icon until its own reset timer expires", async () => {
|
|
224
|
+
vi.useFakeTimers();
|
|
225
|
+
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
226
|
+
await act(() => vi.advanceTimersByTimeAsync(1000));
|
|
227
|
+
rerender(<DynamicFavicon isRunning={false} />);
|
|
228
|
+
await act(() => vi.advanceTimersByTimeAsync(2000));
|
|
229
|
+
expect(favicon.href).toContain("circle-check.ico");
|
|
230
|
+
await act(() => vi.advanceTimersByTimeAsync(1000));
|
|
231
|
+
expect(favicon.href).toContain("favicon.ico");
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("cancels the reset timer when unmounted", async () => {
|
|
235
|
+
vi.useFakeTimers();
|
|
236
|
+
const { unmount } = render(<DynamicFavicon isRunning={true} />);
|
|
237
|
+
await act(() => vi.advanceTimersByTimeAsync(0));
|
|
238
|
+
expect(vi.getTimerCount()).toBe(1);
|
|
239
|
+
unmount();
|
|
240
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
241
|
+
});
|
|
242
|
+
|
|
150
243
|
describe("notifications", () => {
|
|
151
244
|
beforeEach(() => {
|
|
152
245
|
vi.spyOn(document, "visibilityState", "get").mockReturnValue("hidden");
|
|
@@ -156,7 +249,7 @@ describe("DynamicFavicon", () => {
|
|
|
156
249
|
global.Notification.permission = "granted";
|
|
157
250
|
});
|
|
158
251
|
|
|
159
|
-
it("should send success notification when run completes without errors", () => {
|
|
252
|
+
it("should send success notification when run completes without errors", async () => {
|
|
160
253
|
// @ts-expect-error ok in tests
|
|
161
254
|
global.Notification = vi
|
|
162
255
|
.fn()
|
|
@@ -172,12 +265,11 @@ describe("DynamicFavicon", () => {
|
|
|
172
265
|
|
|
173
266
|
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
174
267
|
rerender(<DynamicFavicon isRunning={false} />);
|
|
268
|
+
await waitFor(() => expect(Notification).toHaveBeenCalledOnce());
|
|
175
269
|
});
|
|
176
270
|
|
|
177
|
-
it("should send error notification when run completes with errors", () => {
|
|
178
|
-
(
|
|
179
|
-
{ error: "mock error" },
|
|
180
|
-
]);
|
|
271
|
+
it("should send error notification when run completes with errors", async () => {
|
|
272
|
+
setErrors();
|
|
181
273
|
|
|
182
274
|
// @ts-expect-error ok in tests
|
|
183
275
|
global.Notification = vi
|
|
@@ -194,6 +286,7 @@ describe("DynamicFavicon", () => {
|
|
|
194
286
|
|
|
195
287
|
const { rerender } = render(<DynamicFavicon isRunning={true} />);
|
|
196
288
|
rerender(<DynamicFavicon isRunning={false} />);
|
|
289
|
+
await waitFor(() => expect(Notification).toHaveBeenCalledOnce());
|
|
197
290
|
});
|
|
198
291
|
|
|
199
292
|
it("should not send notification when document is visible", () => {
|