@marimo-team/frontend 0.25.3-dev10 → 0.25.3-dev100
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-fK4n2NPc.js +1 -0
- package/dist/assets/{ConnectedDataExplorerComponent-t8fH_TNc.js → ConnectedDataExplorerComponent-Dft8R6l5.js} +1 -1
- package/dist/assets/{ErrorBoundary-B4n9EnHB.js → ErrorBoundary-CAEGdoFW.js} +2 -2
- package/dist/assets/JsonOutput-CyAKmZDD.js +11 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-CKcCbG2G.js → LazyAnyLanguageCodeMirror-BPYE76jR.js} +2 -2
- package/dist/assets/MarimoErrorOutput-CgZvP0p0.js +10 -0
- package/dist/assets/{RenderHTML-9bMgbYmo.js → RenderHTML-DQvxDDNS.js} +1 -1
- package/dist/assets/RunButton-BBDnDL6G.js +1 -0
- package/dist/assets/__vite-browser-external-8vDMR0Kk.js +1 -0
- package/dist/assets/__vite-browser-external-mKcnhO20.js +1 -0
- package/dist/assets/{add-cell-with-ai-f_MnLCwI.js → add-cell-with-ai-Clg5FELx.js} +7 -7
- package/dist/assets/{add-connection-dialog-CoE_PhuD.js → add-connection-dialog-BqdWmD-7.js} +2 -2
- package/dist/assets/{agent-panel-BWZz24jK.js → agent-panel-5RxG5Y82.js} +3 -3
- package/dist/assets/ai-model-dropdown-Bvl1ktQq.js +13 -0
- package/dist/assets/{alert-dialog-BaPGzeOK.js → alert-dialog-C-sWmKva.js} +1 -1
- package/dist/assets/any-language-editor-DUMe1UCk.js +1 -0
- package/dist/assets/{app-config-button-BhU0ulYs.js → app-config-button-0QTeQ2Mv.js} +1 -1
- package/dist/assets/arrays-0R2reF2y.js +1 -0
- package/dist/assets/{blob-iOBwGaP9.js → blob-5VcB8K_t.js} +1 -1
- package/dist/assets/{button-COI-NGrx.js → button-D8gVKwe-.js} +1 -1
- package/dist/assets/{cache-panel-DTY1dqvi.js → cache-panel-BV-c7ed0.js} +1 -1
- package/dist/assets/{capabilities-BJvf-MD4.js → capabilities-Pq1YNPlK.js} +1 -1
- package/dist/assets/cell-editor-Byw5y-oI.js +42 -0
- package/dist/assets/cell-link-C5yYyzuF.js +1 -0
- package/dist/assets/{cells-rA_jsZCj.js → cells-D_11MjVB.js} +60 -60
- package/dist/assets/{chat-display-BmEPmhDP.js → chat-display-BCR_ySiV.js} +1 -1
- package/dist/assets/chat-panel-RPRvBsaU.js +4 -0
- package/dist/assets/chat-ui-CGviVaRA.js +4 -0
- package/dist/assets/{circle-DXf-VWZG.js → circle-B6D_6D8w.js} +1 -1
- package/dist/assets/code-visibility-DYDagVy7.js +1 -0
- package/dist/assets/coerce-DWjFeXOY.js +1 -0
- package/dist/assets/column-preview-xe533-Cn.js +1 -0
- package/dist/assets/command-palette-BB9bWdWp.js +1 -0
- package/dist/assets/{common-lisZ0l6a.js → common-CaeItbcI.js} +1 -1
- package/dist/assets/components-CBE8cOLK.js +1 -0
- package/dist/assets/{components-CP_UoFtT.js → components-DCo7mAWO.js} +1 -1
- package/dist/assets/{components-Dvd1GnD6.js → components-G6frbw0c.js} +1 -1
- package/dist/assets/config-CD1IuZFJ.js +1 -0
- package/dist/assets/{config-DJLAC21v.js → config-DMz7oN0r.js} +1 -1
- package/dist/assets/config-DpY86_Yq.js +1 -0
- package/dist/assets/{copy-D8O_CYCG.js → copy-KlhazlhB.js} +1 -1
- package/dist/assets/{copy-icon-BIiRXh_3.js → copy-icon-8-a5vovc.js} +1 -1
- package/dist/assets/{createReducer-DgRODTW6.js → createReducer-CaI_Oa0v.js} +1 -1
- package/dist/assets/{datasource-Dr1xNKUn.js → datasource-deuXnlU-.js} +1 -1
- package/dist/assets/{dates-CfmdTL6B.js → dates-CQMwFko2.js} +1 -1
- package/dist/assets/{dependency-graph-panel-B0uP-_id.js → dependency-graph-panel-CIykLnJe.js} +2 -2
- package/dist/assets/{dist-iaThVDkA.js → dist-jlhMTKo_.js} +1 -1
- package/dist/assets/{documentation-panel-DVl_ebWy.js → documentation-panel-2PQ8kQLa.js} +1 -1
- package/dist/assets/{download-Bx55LMki.js → download-dK52bLxZ.js} +1 -1
- package/dist/assets/{dropdown-menu-C1rnl-0o.js → dropdown-menu-DS6umAnH.js} +1 -1
- package/dist/assets/edit-page-DrElzw10.js +9 -0
- package/dist/assets/{error-banner-Cd69vvyX.js → error-banner-B5kzVf_0.js} +1 -1
- package/dist/assets/{error-entries-DOWpdGvI.js → error-entries-3GVk2KjS.js} +1 -1
- package/dist/assets/{error-panel-DpbNKSLs.js → error-panel-CzDRGPeC.js} +1 -1
- package/dist/assets/{errors-DCrsa1nH.js → errors-CNsgAw6m.js} +1 -1
- package/dist/assets/{es-Cqst59WX.js → es-N9SHpmG7.js} +1 -1
- package/dist/assets/{feedback-button-B99ThNJW.js → feedback-button-C5NgWpFg.js} +2 -2
- package/dist/assets/feedback-button-CONwLFpw.js +1 -0
- package/dist/assets/file-explorer-panel-B50xDnTZ.js +1 -0
- package/dist/assets/{file-name-input-ChnBsDE_.js → file-name-input-DqwMSgGU.js} +1 -1
- package/dist/assets/{floating-outline-MYqQW4Vp.js → floating-outline-ChmAuvxz.js} +1 -1
- package/dist/assets/{formats-yZ06h1Pl.js → formats-zylfwejq.js} +1 -1
- package/dist/assets/{formatting-BqrP-n49.js → formatting-uom1es4b.js} +1 -1
- package/dist/assets/{fullscreen-B9tHcfpV.js → fullscreen-BWTs8pYZ.js} +1 -1
- package/dist/assets/{gallery-page-DSL0J4md.js → gallery-page-CiL8aMS1.js} +1 -1
- package/dist/assets/{ganttDiagram-EL5Y4UJY-2n7Ig5Jm.js → ganttDiagram-EL5Y4UJY-CYqkCfFG.js} +1 -1
- package/dist/assets/{glide-data-editor-B1MWlKeM.js → glide-data-editor-CqRclBkp.js} +2 -2
- package/dist/assets/{glide-utils-CIrAxdjv.js → glide-utils-HFqhvWHI.js} +2 -2
- package/dist/assets/home-page-BgZVl4dP.js +1 -0
- package/dist/assets/{hooks-BIogTGCr.js → hooks-DM5n7Osw.js} +1 -1
- package/dist/assets/{html-to-image-DK9Zl1lU.js → html-to-image-D_0rd3_B.js} +1 -1
- package/dist/assets/index-BnhSnwvB.css +2 -0
- package/dist/assets/index-EG2n8Oht.js +30 -0
- package/dist/assets/{input-BoBxR50a.js → input-DmHMEZGh.js} +1 -1
- package/dist/assets/kiosk-mode-DFS6HopF.js +1 -0
- package/dist/assets/layout-BpP8nTjb.js +9 -0
- package/dist/assets/linear-Bma8J3iM.js +1 -0
- package/dist/assets/links-DX2w97N9.js +1 -0
- package/dist/assets/{logs-panel-y0XnfulJ.js → logs-panel-B5eVAZtH.js} +1 -1
- package/dist/assets/{markdown-renderer-Q5AhbRU3.js → markdown-renderer-BWUzqkJM.js} +1 -1
- package/dist/assets/{menu-items-BrwnTgyK.js → menu-items-BgUyNUpu.js} +1 -1
- package/dist/assets/{mermaid-a3xYymTy.js → mermaid-BKXlWk4F.js} +2 -2
- package/dist/assets/{name-cell-input-BNOnF6-0.js → name-cell-input-DXW68gRW.js} +1 -1
- package/dist/assets/numbers-CsZVw3Dc.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-Be7stWwv.js → outline-panel-DPxJhJ_A.js} +1 -1
- package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
- package/dist/assets/packages-panel-gBE2FWQr.js +1 -0
- package/dist/assets/{panel-accordion-state-GeMEdCPw.js → panel-accordion-state-CCF5Gxnc.js} +1 -1
- package/dist/assets/panels-Dr6qMCvU.js +105 -0
- package/dist/assets/precisionRound-BxlUs8G4.js +1 -0
- package/dist/assets/process-output-Cw9IDcKQ.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-YULOXf4h.js → readonly-code-display-DYcZQ28T.js} +1 -1
- package/dist/assets/{readonly-python-code-CadgXgRu.js → readonly-python-code-RFuQP50v.js} +1 -1
- package/dist/assets/{renderShortcut-BkVJQ_Zh.js → renderShortcut-rUwGqKgC.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-BVAR7ayZ.js → reveal-component-yRrDmCQz.js} +37 -37
- package/dist/assets/run-page-B69M4-zE.js +1 -0
- package/dist/assets/{runs-BLp5jezv.js → runs-C49hleBy.js} +1 -1
- package/dist/assets/{runtime-details-state-DuChzsA6.js → runtime-details-state-pobtu6TO.js} +1 -1
- package/dist/assets/{save-worker-BbUSwZRG.js → save-worker-pCkSHhuz.js} +1 -1
- package/dist/assets/{schemas-Dv42wLFq.js → schemas-ChRqMOTL.js} +1 -1
- package/dist/assets/scratchpad-panel-H44_pvb_.js +1 -0
- package/dist/assets/{scroll-to-bottom-button-1FyowpWV.js → scroll-to-bottom-button-CIkON2WJ.js} +1 -1
- package/dist/assets/{secrets-panel-Bctbtkrp.js → secrets-panel-bcfEKxRx.js} +1 -1
- package/dist/assets/{select-DTBn5eTb.js → select-3CVGlYrC.js} +1 -1
- package/dist/assets/{session-DqoWmb7X.js → session-CMLIzZKw.js} +1 -1
- package/dist/assets/session-panel-Bnd1iXkO.js +1 -0
- package/dist/assets/{snippets-panel-CQ1dn3lA.js → snippets-panel-DKApxKx9.js} +1 -1
- package/dist/assets/{spec-BfSBcO5B.js → spec-uCpVvaAR.js} +1 -1
- package/dist/assets/{state-uwRvJLb8.js → state-3mcyTS9q.js} +1 -1
- package/dist/assets/state-B_MCKzBL.js +1 -0
- package/dist/assets/state-Bl9BiY_s.js +3 -0
- package/dist/assets/{state-C3oDoyFe.js → state-C5WAeuTu.js} +1 -1
- package/dist/assets/{state-DxQnC_1I.js → state-Cv2JW3l9.js} +1 -1
- package/dist/assets/{state-Bfh_2SLl.js → state-Dv059B3A.js} +1 -1
- package/dist/assets/{strings-B2vv-ENv.js → strings-C25fhMR_.js} +1 -1
- package/dist/assets/{swiper-component-a07domrZ.js → swiper-component-CRGRy5_O.js} +1 -1
- package/dist/assets/{switch-CTaiAjrz.js → switch-DYjBfpNJ.js} +1 -1
- package/dist/assets/{tabs-BuQlZFbt.js → tabs-CY8E4r9U.js} +1 -1
- package/dist/assets/{terminal-Ck_vK-34.js → terminal-Ca-kubKb.js} +1 -1
- package/dist/assets/{time-MgToa8VM.js → time-DswSXBDk.js} +1 -1
- package/dist/assets/{toast-BGzLGnvw.js → toast-Gzxi-le_.js} +1 -1
- package/dist/assets/tooltip-Brya4Ghn.js +61 -0
- package/dist/assets/{tooltip-C9TuY18o.js → tooltip-CkGm8X7m.js} +1 -1
- package/dist/assets/tracing-Clwy4SlW.js +1 -0
- package/dist/assets/tracing-panel-BwjLG_aC.js +2 -0
- package/dist/assets/{tree-actions-DAd80MbP.js → tree-actions-BZNTQ12N.js} +1 -1
- package/dist/assets/{use-restore-focus-BxEGwIbk.js → use-restore-focus-DdS7Tl0F.js} +1 -1
- package/dist/assets/{useAddCell-DGstJK0S.js → useAddCell-Cjuqk2YR.js} +1 -1
- package/dist/assets/useAsyncData-qvoPYHtx.js +1 -0
- package/dist/assets/useBoolean-Dd2nWXFJ.js +1 -0
- package/dist/assets/useCellActionButton-MoWLvuGe.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-DFBGlSQk.js → useDeleteCell-BC-MW7d1.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-DydxsE5d.js → useDependencyPanelTab-CZU7i-B3.js} +1 -1
- package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
- package/dist/assets/{useEventListener-D9cftcHj.js → useEventListener-CjDeLqFC.js} +1 -1
- package/dist/assets/{useIframeCapabilities-CwTkczVN.js → useIframeCapabilities-Czr9e4uG.js} +1 -1
- package/dist/assets/{useInstallPackage-iX1eufdl.js → useInstallPackage-wcDq9hYT.js} +1 -1
- package/dist/assets/{useInterval--x3s1VpI.js → useInterval-DJdQmXnq.js} +1 -1
- package/dist/assets/useNotebookActions-wFxVdRXQ.js +1 -0
- package/dist/assets/{useRunCells-BFjFX3hz.js → useRunCells-ByaWxoIt.js} +1 -1
- package/dist/assets/{useSplitCell-Tqv5pPtL.js → useSplitCell-YJIystwv.js} +1 -1
- package/dist/assets/useStateForKey-CGMJQT8x.js +1 -0
- package/dist/assets/{useTheme-COhSHkCj.js → useTheme-BAA27lh7.js} +1 -1
- package/dist/assets/{utils-CaQYvazl.js → utils-DfElfBpz.js} +1 -1
- package/dist/assets/vega-component-BeyxAJad.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-DTQ7oH2A.js → worker-bSCjCvwz.js} +1 -1
- package/dist/assets/{write-secret-modal-DzKAInL2.js → write-secret-modal-BEx-EUlh.js} +1 -1
- package/dist/assets/{xychartDiagram-S5SC5T6Z-KbGzG6-u.js → xychartDiagram-S5SC5T6Z-CeRnBS5e.js} +1 -1
- package/dist/index.html +80 -78
- package/package.json +7 -7
- package/src/__tests__/host-imports.test.ts +1 -0
- 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__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +2 -2
- 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/__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__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +105 -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__/storage.test.ts +4 -1
- package/src/components/data-table/charts/charts.tsx +35 -25
- 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/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 +7 -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/row-viewer-panel/row-viewer.tsx +2 -2
- 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 +63 -2
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/column-preview.tsx +8 -2
- package/src/components/datasources/datasources.tsx +47 -35
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- 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/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/packages-panel.tsx +4 -7
- 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/command-palette.tsx +22 -10
- 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__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +10 -5
- 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/notebook-banner.tsx +1 -0
- package/src/components/editor/output/MarimoTracebackOutput.tsx +2 -2
- package/src/components/editor/output/ansi-reduce.ts +6 -0
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/package-alert.tsx +6 -4
- 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.tsx +2 -2
- 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.tsx +2 -2
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/core/ai/context/providers/datasource.ts +6 -2
- 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/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 +1 -1
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/languages/markdown.ts +1 -1
- package/src/core/codemirror/language/languages/python.ts +3 -3
- package/src/core/codemirror/language/panel/panel.tsx +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__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/model.test.ts +483 -0
- package/src/core/document/__tests__/state.test.ts +446 -0
- package/src/core/document/__tests__/submission.test.ts +346 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/index.ts +10 -0
- package/src/core/document/model.ts +53 -0
- package/src/core/document/state.ts +401 -0
- package/src/core/document/sync.ts +359 -0
- package/src/core/edit-app.tsx +2 -2
- package/src/core/host/AGENTS.md +12 -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 +41 -0
- package/src/core/host/__tests__/notebook-client.test.ts +570 -0
- package/src/core/host/connection.ts +42 -0
- package/src/core/host/notebook-client.ts +297 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -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/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/run-app.tsx +2 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +18 -17
- package/src/core/runtime/runtime.ts +26 -30
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/files.ts +2 -0
- package/src/core/wasm/bridge.ts +2 -10
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +1 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -29
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +223 -0
- package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +606 -0
- package/src/core/websocket/connection-state.ts +60 -0
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +502 -0
- package/src/core/websocket/transports/notebook.ts +213 -0
- package/src/core/websocket/types.ts +9 -39
- package/src/core/websocket/useNotebookClient.ts +89 -0
- package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +53 -233
- 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 +5 -8
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- 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/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +14 -15
- 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 +12 -10
- 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/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +0 -1
- 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/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/zod-utils.ts +1 -3
- package/dist/assets/CellStatus-nZpuDkm7.js +0 -1
- package/dist/assets/JsonOutput-BxB0NL8w.js +0 -11
- package/dist/assets/MarimoErrorOutput-BTy4MOzX.js +0 -10
- package/dist/assets/RunButton-CFQUNN5c.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-zm-2fXzf.js +0 -13
- package/dist/assets/any-language-editor-BLCAD3yx.js +0 -1
- package/dist/assets/arrays-BqUx5USx.js +0 -1
- package/dist/assets/cell-editor-CAj1UKxx.js +0 -21
- package/dist/assets/cell-link-1CynTVGQ.js +0 -1
- package/dist/assets/chat-panel-Ce2Xh7dM.js +0 -4
- package/dist/assets/chat-ui-DTy98rP3.js +0 -4
- package/dist/assets/circle-play-CYIb0qT6.js +0 -1
- package/dist/assets/code-visibility-B-_GvwR5.js +0 -1
- package/dist/assets/coerce-CpE6kUdX.js +0 -1
- package/dist/assets/column-preview-DU6dT80y.js +0 -1
- package/dist/assets/command-palette-BMqFKXVr.js +0 -1
- package/dist/assets/components-CXfO-F47.js +0 -1
- package/dist/assets/config-DX8Y2WbJ.js +0 -1
- package/dist/assets/config-VPSq73n8.js +0 -1
- package/dist/assets/edit-page-DlfCLUaq.js +0 -9
- package/dist/assets/feedback-button-DlqZkJwz.js +0 -1
- package/dist/assets/file-explorer-panel-Bo9eN3rW.js +0 -1
- package/dist/assets/home-page-KrhQ55Vg.js +0 -4
- package/dist/assets/index-6b4mf8Ai.css +0 -2
- package/dist/assets/index-B3fcrmuf.js +0 -30
- package/dist/assets/kiosk-mode-BZECfg9k.js +0 -1
- package/dist/assets/layout-DOpdUwym.js +0 -9
- 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/numbers-Mk3-CcoU.js +0 -1
- package/dist/assets/packages-panel-ClxOAEGy.js +0 -1
- package/dist/assets/panels-DfCmzLtT.js +0 -4
- package/dist/assets/precisionRound-Bq_nmf5u.js +0 -1
- package/dist/assets/process-output-DNFKMODr.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-Cxu1yV8Q.js +0 -1
- package/dist/assets/scratchpad-panel-By-ybhjg.js +0 -1
- package/dist/assets/session-panel-BmW6PH4z.js +0 -1
- package/dist/assets/state-BAJYRhmO.js +0 -1
- package/dist/assets/state-z3dlofZB.js +0 -3
- package/dist/assets/tooltip-mT3CGest.js +0 -61
- package/dist/assets/tracing-BARlJ_Dk.js +0 -1
- package/dist/assets/tracing-panel-dgnr2fIN.js +0 -2
- package/dist/assets/useAsyncData-C7aJJz0Y.js +0 -1
- package/dist/assets/useBoolean-BDD6_xQQ.js +0 -1
- package/dist/assets/useCellActionButton-DY9RlJTb.js +0 -1
- package/dist/assets/useDebounce-B_ccBZTp.js +0 -1
- package/dist/assets/useNotebookActions-DfvB7RD_.js +0 -1
- package/dist/assets/vega-component-CnadTgoE.js +0 -1
- package/dist/assets/vega-loader.browser-CLRkNgm7.js +0 -6
- package/dist/assets/ws-BXWY541V.js +0 -22
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +0 -789
- package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
- 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/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -61
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useWebSocket.tsx +0 -88
|
@@ -30,7 +30,7 @@ export interface CellSelectionCell {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// These are additional properties add to the table instance in createTable
|
|
33
|
-
export interface CellSelectionInstance
|
|
33
|
+
export interface CellSelectionInstance {
|
|
34
34
|
setCellSelection?: (updater: Updater<CellSelectionState>) => void;
|
|
35
35
|
|
|
36
36
|
resetCellSelection?(defaultValue?: CellSelectionState): void;
|
|
@@ -44,7 +44,7 @@ declare module "@tanstack/react-table" {
|
|
|
44
44
|
TData extends RowData,
|
|
45
45
|
> extends CellSelectionOptions {}
|
|
46
46
|
|
|
47
|
-
interface Table<TData extends RowData> extends CellSelectionInstance
|
|
47
|
+
interface Table<TData extends RowData> extends CellSelectionInstance {}
|
|
48
48
|
|
|
49
49
|
interface Cell<TData extends RowData, TValue> extends CellSelectionCell {}
|
|
50
50
|
}
|
|
@@ -10,13 +10,27 @@ import { cellId } from "@/__tests__/branded";
|
|
|
10
10
|
import { LazyVegaEmbed } from "@/components/charts/lazy";
|
|
11
11
|
import { vegaLoader } from "@/plugins/impl/vega/loader";
|
|
12
12
|
import { ChartPanel, TablePanel, type TablePanelProps } from "../charts";
|
|
13
|
-
import { getChartTabName, tabsStorageAtom } from "../storage";
|
|
13
|
+
import { createTabId, getChartTabName, tabsStorageAtom } from "../storage";
|
|
14
14
|
import { ChartType, NONE_VALUE } from "../types";
|
|
15
|
+
import { TOO_MANY_ROWS } from "../../types";
|
|
15
16
|
|
|
16
17
|
vi.mock("@/components/charts/lazy", () => ({
|
|
17
18
|
LazyVegaEmbed: vi.fn(() => null),
|
|
18
19
|
}));
|
|
19
20
|
|
|
21
|
+
vi.mock("../components/chart-items", async (importOriginal) => ({
|
|
22
|
+
...(await importOriginal<typeof import("../components/chart-items")>()),
|
|
23
|
+
ChartTypeSelect: ({
|
|
24
|
+
onValueChange,
|
|
25
|
+
}: {
|
|
26
|
+
onValueChange: (value: string) => void;
|
|
27
|
+
}) => (
|
|
28
|
+
<button type="button" onClick={() => onValueChange("line")}>
|
|
29
|
+
Change chart type
|
|
30
|
+
</button>
|
|
31
|
+
),
|
|
32
|
+
}));
|
|
33
|
+
|
|
20
34
|
beforeAll(() => {
|
|
21
35
|
SetupMocks.resizeObserver();
|
|
22
36
|
});
|
|
@@ -38,6 +52,7 @@ describe("ChartPanel", () => {
|
|
|
38
52
|
id,
|
|
39
53
|
[
|
|
40
54
|
{
|
|
55
|
+
id: createTabId(),
|
|
41
56
|
tabName,
|
|
42
57
|
chartType: ChartType.BAR,
|
|
43
58
|
config: {
|
|
@@ -283,4 +298,62 @@ describe("ChartPanel", () => {
|
|
|
283
298
|
});
|
|
284
299
|
},
|
|
285
300
|
);
|
|
301
|
+
it("keeps panel state when a chart type change renames the tab", async () => {
|
|
302
|
+
const store = createStore();
|
|
303
|
+
const id = cellId("rename-keeps-state");
|
|
304
|
+
const tabName = getChartTabName(0, ChartType.BAR);
|
|
305
|
+
store.set(
|
|
306
|
+
tabsStorageAtom,
|
|
307
|
+
new Map([
|
|
308
|
+
[
|
|
309
|
+
id,
|
|
310
|
+
[
|
|
311
|
+
{
|
|
312
|
+
id: createTabId(),
|
|
313
|
+
tabName,
|
|
314
|
+
chartType: ChartType.BAR,
|
|
315
|
+
config: {
|
|
316
|
+
general: {
|
|
317
|
+
xColumn: { field: "value", type: "number" },
|
|
318
|
+
yColumn: {
|
|
319
|
+
field: "value",
|
|
320
|
+
type: "integer",
|
|
321
|
+
aggregate: NONE_VALUE,
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
],
|
|
328
|
+
]),
|
|
329
|
+
);
|
|
330
|
+
const sample = [{ value: 1 }];
|
|
331
|
+
const props: TablePanelProps = {
|
|
332
|
+
cellId: id,
|
|
333
|
+
data: sample,
|
|
334
|
+
dataTable: <div />,
|
|
335
|
+
totalRows: TOO_MANY_ROWS,
|
|
336
|
+
columns: 1,
|
|
337
|
+
displayHeader: true,
|
|
338
|
+
fieldTypes: [["value", ["number", "float64"]]],
|
|
339
|
+
};
|
|
340
|
+
const { getByRole, findByRole, queryByRole } = render(
|
|
341
|
+
<Provider store={store}>
|
|
342
|
+
<Tooltip.Provider>
|
|
343
|
+
<TablePanel {...props} />
|
|
344
|
+
</Tooltip.Provider>
|
|
345
|
+
</Provider>,
|
|
346
|
+
);
|
|
347
|
+
fireEvent.click(getByRole("tab", { name: tabName }));
|
|
348
|
+
fireEvent.click(await findByRole("button", { name: "Proceed" }));
|
|
349
|
+
await waitFor(() => {
|
|
350
|
+
expect(queryByRole("button", { name: "Proceed" })).toBeNull();
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
fireEvent.click(getByRole("button", { name: "Change chart type" }));
|
|
354
|
+
|
|
355
|
+
const renamed = getChartTabName(0, ChartType.LINE);
|
|
356
|
+
await findByRole("tab", { name: renamed });
|
|
357
|
+
expect(queryByRole("button", { name: "Proceed" })).toBeNull();
|
|
358
|
+
});
|
|
286
359
|
});
|
|
@@ -16,7 +16,7 @@ import { cellId } from "@/__tests__/branded";
|
|
|
16
16
|
import { availableStorage } from "@/utils/storage/storage";
|
|
17
17
|
import { ChartSchema } from "../schemas";
|
|
18
18
|
import type { TabName } from "../storage";
|
|
19
|
-
import { KEY, tabsStorageAtom } from "../storage";
|
|
19
|
+
import { createTabId, KEY, tabsStorageAtom } from "../storage";
|
|
20
20
|
import { ChartType } from "../types";
|
|
21
21
|
|
|
22
22
|
describe("Chart Transforms Storage", () => {
|
|
@@ -39,6 +39,7 @@ describe("Chart Transforms Storage", () => {
|
|
|
39
39
|
const store = getDefaultStore();
|
|
40
40
|
const cid = cellId("cell-1");
|
|
41
41
|
const tabData = {
|
|
42
|
+
id: createTabId(),
|
|
42
43
|
tabName: "Tab 1" as TabName,
|
|
43
44
|
chartType: ChartType.LINE,
|
|
44
45
|
config: ChartSchema.parse({
|
|
@@ -63,6 +64,7 @@ describe("Chart Transforms Storage", () => {
|
|
|
63
64
|
const store = getDefaultStore();
|
|
64
65
|
const cid = cellId("cell-1");
|
|
65
66
|
const tabData1 = {
|
|
67
|
+
id: createTabId(),
|
|
66
68
|
tabName: "Tab 1" as TabName,
|
|
67
69
|
chartType: ChartType.LINE,
|
|
68
70
|
config: ChartSchema.parse({
|
|
@@ -73,6 +75,7 @@ describe("Chart Transforms Storage", () => {
|
|
|
73
75
|
}),
|
|
74
76
|
};
|
|
75
77
|
const tabData2 = {
|
|
78
|
+
id: createTabId(),
|
|
76
79
|
tabName: "Tab 2" as TabName,
|
|
77
80
|
chartType: ChartType.BAR,
|
|
78
81
|
config: ChartSchema.parse({
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
XIcon,
|
|
14
14
|
} from "lucide-react";
|
|
15
15
|
import type { JSX } from "react";
|
|
16
|
-
import React, { useMemo,
|
|
17
|
-
import { type UseFormReturn, useForm } from "react-hook-form";
|
|
16
|
+
import React, { useMemo, useState } from "react";
|
|
17
|
+
import { type UseFormReturn, useForm, useWatch } from "react-hook-form";
|
|
18
18
|
import useResizeObserver from "use-resize-observer";
|
|
19
19
|
import { PythonIcon } from "@/components/editor/cell/code/icons";
|
|
20
20
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
@@ -48,7 +48,12 @@ import { HeatmapForm } from "./forms/heatmap";
|
|
|
48
48
|
import { PieForm } from "./forms/pie";
|
|
49
49
|
import { LazyChart } from "./lazy-chart";
|
|
50
50
|
import { ChartSchema, type ChartSchemaType, getChartDefaults } from "./schemas";
|
|
51
|
-
import {
|
|
51
|
+
import {
|
|
52
|
+
createTabId,
|
|
53
|
+
getChartTabName,
|
|
54
|
+
type TabName,
|
|
55
|
+
tabsStorageAtom,
|
|
56
|
+
} from "./storage";
|
|
52
57
|
import { ChartType } from "./types";
|
|
53
58
|
|
|
54
59
|
const NEW_CHART_TYPE = "bar" as ChartType;
|
|
@@ -103,26 +108,28 @@ export const TablePanel: React.FC<TablePanelProps> = ({
|
|
|
103
108
|
|
|
104
109
|
const [selectedTab, setSelectedTab] = useState(DEFAULT_TAB_NAME);
|
|
105
110
|
const [tabCounter, setTabCounter] = useState(tabs.length);
|
|
106
|
-
const prevDisplayHeader =
|
|
111
|
+
const [prevDisplayHeader, setPrevDisplayHeader] = useState(displayHeader);
|
|
112
|
+
|
|
113
|
+
if (displayHeader !== prevDisplayHeader) {
|
|
114
|
+
setPrevDisplayHeader(displayHeader);
|
|
115
|
+
}
|
|
107
116
|
|
|
108
117
|
// Auto-create a default chart tab when chart builder opens with no tabs
|
|
109
|
-
if (
|
|
110
|
-
displayHeader &&
|
|
111
|
-
!prevDisplayHeader.current &&
|
|
112
|
-
tabs.length === 0 &&
|
|
113
|
-
cellId
|
|
114
|
-
) {
|
|
115
|
-
prevDisplayHeader.current = displayHeader;
|
|
118
|
+
if (displayHeader && !prevDisplayHeader && tabs.length === 0 && cellId) {
|
|
116
119
|
const tabName = getChartTabName(0, NEW_CHART_TYPE);
|
|
117
120
|
const newTabs = new Map(tabsMap);
|
|
118
121
|
newTabs.set(cellId, [
|
|
119
|
-
{
|
|
122
|
+
{
|
|
123
|
+
id: createTabId(),
|
|
124
|
+
tabName,
|
|
125
|
+
chartType: NEW_CHART_TYPE,
|
|
126
|
+
config: getChartDefaults(),
|
|
127
|
+
},
|
|
120
128
|
]);
|
|
121
129
|
saveTabsMap(newTabs);
|
|
122
130
|
setTabCounter(1);
|
|
123
131
|
setSelectedTab(tabName);
|
|
124
132
|
}
|
|
125
|
-
prevDisplayHeader.current = displayHeader;
|
|
126
133
|
|
|
127
134
|
if (!displayHeader || (tabs.length === 0 && !displayHeader)) {
|
|
128
135
|
return dataTable;
|
|
@@ -138,6 +145,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
|
|
|
138
145
|
newTabs.set(cellId, [
|
|
139
146
|
...tabs,
|
|
140
147
|
{
|
|
148
|
+
id: createTabId(),
|
|
141
149
|
tabName,
|
|
142
150
|
chartType: NEW_CHART_TYPE,
|
|
143
151
|
config: getChartDefaults(),
|
|
@@ -236,9 +244,9 @@ export const TablePanel: React.FC<TablePanelProps> = ({
|
|
|
236
244
|
>
|
|
237
245
|
Table
|
|
238
246
|
</TabsTrigger>
|
|
239
|
-
{tabs.map((tab
|
|
247
|
+
{tabs.map((tab) => (
|
|
240
248
|
<TabsTrigger
|
|
241
|
-
key={
|
|
249
|
+
key={tab.id}
|
|
242
250
|
className="text-xs"
|
|
243
251
|
value={tab.tabName}
|
|
244
252
|
onClick={() => setSelectedTab(tab.tabName)}
|
|
@@ -266,7 +274,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
|
|
|
266
274
|
<TabsContent className="mt-1 overflow-hidden" value={DEFAULT_TAB_NAME}>
|
|
267
275
|
{dataTable}
|
|
268
276
|
</TabsContent>
|
|
269
|
-
{tabs.map((tab
|
|
277
|
+
{tabs.map((tab) => {
|
|
270
278
|
const saveChart = (formValues: ChartSchemaType) => {
|
|
271
279
|
saveTabChart({
|
|
272
280
|
tabName: tab.tabName,
|
|
@@ -278,7 +286,11 @@ export const TablePanel: React.FC<TablePanelProps> = ({
|
|
|
278
286
|
saveTabChartType(tab.tabName, chartType);
|
|
279
287
|
};
|
|
280
288
|
return (
|
|
281
|
-
<TabsContent
|
|
289
|
+
<TabsContent
|
|
290
|
+
key={tab.id}
|
|
291
|
+
value={tab.tabName}
|
|
292
|
+
className="h-[400px] mt-0"
|
|
293
|
+
>
|
|
282
294
|
<ChartPanel
|
|
283
295
|
tableData={data}
|
|
284
296
|
chartConfig={tab.config}
|
|
@@ -320,9 +332,10 @@ export const ChartPanel: React.FC<{
|
|
|
320
332
|
saveChartType,
|
|
321
333
|
getDataUrl,
|
|
322
334
|
fieldTypes,
|
|
323
|
-
hasSchema
|
|
335
|
+
hasSchema: providedHasSchema,
|
|
324
336
|
isLargeDataset,
|
|
325
337
|
}) => {
|
|
338
|
+
const hasSchema = providedHasSchema ?? Boolean(fieldTypes?.length);
|
|
326
339
|
const { theme } = useTheme();
|
|
327
340
|
const form = useForm<ChartSchemaType>({
|
|
328
341
|
defaultValues: chartConfig ?? getChartDefaults(),
|
|
@@ -370,16 +383,13 @@ export const ChartPanel: React.FC<{
|
|
|
370
383
|
// Re-run when the data table changes
|
|
371
384
|
}, [tableData, renderLargeCharts, csvFieldTypes]);
|
|
372
385
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const memoizedFormValues = useMemo(() => {
|
|
377
|
-
return structuredClone(formValues);
|
|
378
|
-
}, [formValues]);
|
|
386
|
+
// useWatch returns a new object only when a value changes. It is typed as
|
|
387
|
+
// deeply partial, but the form always starts from complete defaults.
|
|
388
|
+
const formValues = useWatch({ control: form.control }) as ChartSchemaType;
|
|
379
389
|
|
|
380
390
|
const specWithoutData = createSpecWithoutData(
|
|
381
391
|
selectedChartType,
|
|
382
|
-
|
|
392
|
+
formValues,
|
|
383
393
|
theme,
|
|
384
394
|
"container",
|
|
385
395
|
CHART_HEIGHT,
|
|
@@ -7,13 +7,16 @@ import { Logger } from "@/utils/Logger";
|
|
|
7
7
|
import { NotebookScopedLocalStorage } from "@/utils/storage/typed";
|
|
8
8
|
import { capitalize } from "@/utils/strings";
|
|
9
9
|
import type { TypedString } from "@/utils/typed";
|
|
10
|
+
import { generateUUID } from "@/utils/uuid";
|
|
10
11
|
import { ChartSchema, type ChartSchemaType } from "./schemas";
|
|
11
12
|
import type { ChartType } from "./types";
|
|
12
13
|
|
|
13
14
|
export type TabName = TypedString<"TabName">;
|
|
15
|
+
export type TabId = TypedString<"TabId">;
|
|
14
16
|
export const KEY = "marimo:charts:v2";
|
|
15
17
|
|
|
16
18
|
interface TabStorage {
|
|
19
|
+
id: TabId;
|
|
17
20
|
tabName: TabName; // unique within cell
|
|
18
21
|
chartType: ChartType;
|
|
19
22
|
config: ChartSchemaType;
|
|
@@ -21,11 +24,15 @@ interface TabStorage {
|
|
|
21
24
|
|
|
22
25
|
type TabStorageMap = Map<CellId, TabStorage[]>;
|
|
23
26
|
|
|
24
|
-
const TabStorageSchema = z
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const TabStorageSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
id: z.string().optional(),
|
|
30
|
+
tabName: z.string().transform((name) => name as TabName),
|
|
31
|
+
chartType: z.string().transform((type) => type as ChartType),
|
|
32
|
+
config: ChartSchema,
|
|
33
|
+
})
|
|
34
|
+
// Stored tabs without an id use their name, which is unique within a cell.
|
|
35
|
+
.transform((tab) => ({ ...tab, id: (tab.id ?? tab.tabName) as TabId }));
|
|
29
36
|
const TabStorageEntriesSchema = z.array(
|
|
30
37
|
z.tuple([
|
|
31
38
|
z.string().transform((name) => name as CellId),
|
|
@@ -64,6 +71,10 @@ export const tabsStorageAtom = atomWithStorage<TabStorageMap>(
|
|
|
64
71
|
mapStorage,
|
|
65
72
|
);
|
|
66
73
|
|
|
74
|
+
export function createTabId(): TabId {
|
|
75
|
+
return generateUUID() as TabId;
|
|
76
|
+
}
|
|
77
|
+
|
|
67
78
|
/**
|
|
68
79
|
* Convenience function to get the tab name for a given tab number and chart type
|
|
69
80
|
*/
|
|
@@ -345,7 +345,7 @@ const ColumnPreview = ({
|
|
|
345
345
|
const chart = chart_spec && renderChart(chart_spec, theme);
|
|
346
346
|
|
|
347
347
|
const addDataframeChart = chart_code && (
|
|
348
|
-
<AddDataframeChart chartCode={chart_code} />
|
|
348
|
+
<AddDataframeChart chartCode={chart_code} columnName={columnName} />
|
|
349
349
|
);
|
|
350
350
|
|
|
351
351
|
return (
|
|
@@ -16,7 +16,7 @@ export const ColumnChartContext = React.createContext<
|
|
|
16
16
|
ColumnChartSpecModel<unknown>
|
|
17
17
|
>(ColumnChartSpecModel.EMPTY);
|
|
18
18
|
|
|
19
|
-
interface Props
|
|
19
|
+
interface Props {
|
|
20
20
|
columnId: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -24,9 +24,7 @@ interface Props<TData, TValue> {
|
|
|
24
24
|
// for all calls with the same key.
|
|
25
25
|
const batchedLoader = createBatchedLoader();
|
|
26
26
|
|
|
27
|
-
export const TableColumnSummary =
|
|
28
|
-
columnId,
|
|
29
|
-
}: Props<TData, TValue>) => {
|
|
27
|
+
export const TableColumnSummary = ({ columnId }: Props) => {
|
|
30
28
|
const { locale } = useLocale();
|
|
31
29
|
|
|
32
30
|
const chartSpecModel = React.use(ColumnChartContext);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Table } from "@tanstack/react-table";
|
|
8
8
|
import { Columns3Icon, EyeIcon, EyeOffIcon, ScanEyeIcon } from "lucide-react";
|
|
9
|
-
import React
|
|
9
|
+
import React from "react";
|
|
10
10
|
import { ColumnName } from "@/components/datasources/components";
|
|
11
11
|
import { Button } from "@/components/ui/button";
|
|
12
12
|
import {
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
} from "@/components/ui/popover";
|
|
25
25
|
import { type BulkAction, useSelectList } from "@/components/ui/select-core";
|
|
26
26
|
import type { DataType } from "@/core/kernel/messages";
|
|
27
|
+
import { Arrays } from "@/utils/arrays";
|
|
27
28
|
import { cn } from "@/utils/cn";
|
|
28
29
|
import { Events } from "@/utils/events";
|
|
29
30
|
import { smartMatchFilter } from "@/utils/smartMatch";
|
|
@@ -67,9 +68,8 @@ export const ColumnVisibilityDropdown = <TData,>({
|
|
|
67
68
|
const hideableIds = userColumns
|
|
68
69
|
.filter((column) => column.getCanHide())
|
|
69
70
|
.map((column) => column.id);
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
).length;
|
|
71
|
+
const visibleHideableColumnIds = Arrays.difference(hideableIds, hiddenIds);
|
|
72
|
+
const visibleHideableCount = visibleHideableColumnIds.length;
|
|
73
73
|
|
|
74
74
|
const applyHidden = (next: string[] | string | null) => {
|
|
75
75
|
const hidden = new Set(Array.isArray(next) ? next : []);
|
|
@@ -106,15 +106,10 @@ export const ColumnVisibilityDropdown = <TData,>({
|
|
|
106
106
|
.filter((option) => !option.disabled)
|
|
107
107
|
.map((option) => option.value)
|
|
108
108
|
: [];
|
|
109
|
-
const showOnlyColumnState =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
),
|
|
114
|
-
hideableColumnIdSet: new Set(hideableIds),
|
|
115
|
-
}),
|
|
116
|
-
[hideableIds, hiddenIds],
|
|
117
|
-
);
|
|
109
|
+
const showOnlyColumnState = {
|
|
110
|
+
visibleHideableColumnIds,
|
|
111
|
+
hideableColumnIdSet: new Set(hideableIds),
|
|
112
|
+
};
|
|
118
113
|
const hasSearchBulkActions =
|
|
119
114
|
showOnlyMatchIds.length > 0 || matchingActions.length > 0;
|
|
120
115
|
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
isNumericType,
|
|
42
42
|
} from "./types";
|
|
43
43
|
import { SentinelCell, WhitespaceMarkers } from "./sentinel-cell";
|
|
44
|
+
import { highlightMatches } from "./search-highlight";
|
|
44
45
|
import { detectSentinel, splitLeadingTrailingWhitespace } from "./utils";
|
|
45
46
|
import { uniformSample } from "./uniformSample";
|
|
46
47
|
import { MarkdownUrlDetector, UrlDetector } from "./url-detector";
|
|
@@ -135,6 +136,7 @@ export function generateColumns<T>({
|
|
|
135
136
|
}): ColumnDef<T>[] {
|
|
136
137
|
// Row-headers are typically index columns
|
|
137
138
|
const rowHeadersSet = new Set(rowHeaders.map(([columnName]) => columnName));
|
|
139
|
+
const wrappedColumnsSet = new Set(wrappedColumns);
|
|
138
140
|
|
|
139
141
|
const typesByColumn = Maps.keyBy(fieldTypes, (entry) => entry[0]);
|
|
140
142
|
|
|
@@ -277,7 +279,7 @@ export function generateColumns<T>({
|
|
|
277
279
|
);
|
|
278
280
|
},
|
|
279
281
|
|
|
280
|
-
cell: ({ column, renderValue, getValue, cell }) => {
|
|
282
|
+
cell: ({ column, renderValue, getValue, cell, table }) => {
|
|
281
283
|
function selectCell() {
|
|
282
284
|
if (selection !== "single-cell" && selection !== "multi-cell") {
|
|
283
285
|
return;
|
|
@@ -287,7 +289,7 @@ export function generateColumns<T>({
|
|
|
287
289
|
}
|
|
288
290
|
|
|
289
291
|
const justify = getJustify(key);
|
|
290
|
-
const wrapped =
|
|
292
|
+
const wrapped = wrappedColumnsSet.has(key);
|
|
291
293
|
const isCellSelected = cell?.getIsSelected?.() || false;
|
|
292
294
|
const canSelectCell =
|
|
293
295
|
(selection === "single-cell" || selection === "multi-cell") &&
|
|
@@ -309,6 +311,7 @@ export function generateColumns<T>({
|
|
|
309
311
|
getValue,
|
|
310
312
|
selectCell,
|
|
311
313
|
cellStyles,
|
|
314
|
+
highlightPattern: table.options.meta?.highlightPattern,
|
|
312
315
|
});
|
|
313
316
|
|
|
314
317
|
// Row headers are bold
|
|
@@ -585,12 +588,14 @@ function renderDate({
|
|
|
585
588
|
dtype,
|
|
586
589
|
displayValue,
|
|
587
590
|
locale,
|
|
591
|
+
highlightPattern,
|
|
588
592
|
}: {
|
|
589
593
|
value: Date;
|
|
590
594
|
dataType?: DataType;
|
|
591
595
|
dtype?: string;
|
|
592
596
|
displayValue?: string;
|
|
593
597
|
locale: string;
|
|
598
|
+
highlightPattern?: RegExp;
|
|
594
599
|
}): React.ReactNode {
|
|
595
600
|
const type = dataType === "date" ? "date" : "datetime";
|
|
596
601
|
const timezone = extractTimezone(dtype);
|
|
@@ -599,7 +604,7 @@ function renderDate({
|
|
|
599
604
|
|
|
600
605
|
return (
|
|
601
606
|
<DatePopover date={value} type={type}>
|
|
602
|
-
{exactValue}
|
|
607
|
+
{highlightMatches(exactValue, highlightPattern)}
|
|
603
608
|
</DatePopover>
|
|
604
609
|
);
|
|
605
610
|
}
|
|
@@ -610,12 +615,14 @@ export function renderCellValue<TData, TValue>({
|
|
|
610
615
|
getValue,
|
|
611
616
|
selectCell,
|
|
612
617
|
cellStyles,
|
|
618
|
+
highlightPattern,
|
|
613
619
|
}: {
|
|
614
620
|
column: Column<TData, TValue>;
|
|
615
621
|
renderValue: () => TValue | null;
|
|
616
622
|
getValue: () => TValue;
|
|
617
623
|
selectCell?: () => void;
|
|
618
624
|
cellStyles?: string;
|
|
625
|
+
highlightPattern?: RegExp;
|
|
619
626
|
}) {
|
|
620
627
|
const value = getValue();
|
|
621
628
|
const format = column.getColumnFormatting?.();
|
|
@@ -625,6 +632,28 @@ export function renderCellValue<TData, TValue>({
|
|
|
625
632
|
|
|
626
633
|
const isWrapped = column.getColumnWrapping?.() === "wrap";
|
|
627
634
|
|
|
635
|
+
const textCell = (text: string) => (
|
|
636
|
+
<div onClick={selectCell} className={cellStyles}>
|
|
637
|
+
{highlightMatches(text, highlightPattern)}
|
|
638
|
+
</div>
|
|
639
|
+
);
|
|
640
|
+
const dateCell = (date: Date, displayValue?: string) => (
|
|
641
|
+
<div onClick={selectCell} className={cellStyles}>
|
|
642
|
+
<WithLocale>
|
|
643
|
+
{(locale) =>
|
|
644
|
+
renderDate({
|
|
645
|
+
value: date,
|
|
646
|
+
dataType,
|
|
647
|
+
dtype,
|
|
648
|
+
displayValue,
|
|
649
|
+
locale,
|
|
650
|
+
highlightPattern,
|
|
651
|
+
})
|
|
652
|
+
}
|
|
653
|
+
</WithLocale>
|
|
654
|
+
</div>
|
|
655
|
+
);
|
|
656
|
+
|
|
628
657
|
// Sentinel values (null, whitespace, NaN, Infinity, NaT) rendered specially.
|
|
629
658
|
// Empty strings are left as-is
|
|
630
659
|
const sentinel = detectSentinel(value, dataType, dtype);
|
|
@@ -640,23 +669,10 @@ export function renderCellValue<TData, TValue>({
|
|
|
640
669
|
try {
|
|
641
670
|
const date = new Date(value);
|
|
642
671
|
if (!format || !isValid(date)) {
|
|
643
|
-
return (
|
|
644
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
645
|
-
{value}
|
|
646
|
-
</div>
|
|
647
|
-
);
|
|
672
|
+
return textCell(value);
|
|
648
673
|
}
|
|
649
674
|
|
|
650
|
-
|
|
651
|
-
return (
|
|
652
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
653
|
-
<WithLocale>
|
|
654
|
-
{(locale) =>
|
|
655
|
-
renderDate({ value: date, dataType, dtype, displayValue, locale })
|
|
656
|
-
}
|
|
657
|
-
</WithLocale>
|
|
658
|
-
</div>
|
|
659
|
-
);
|
|
675
|
+
return dateCell(date, String(column.applyColumnFormatting(value)));
|
|
660
676
|
} catch (error) {
|
|
661
677
|
Logger.error("Error parsing datetime, fallback to string", error);
|
|
662
678
|
}
|
|
@@ -672,17 +688,9 @@ export function renderCellValue<TData, TValue>({
|
|
|
672
688
|
}
|
|
673
689
|
|
|
674
690
|
// e.g. 2010-10-07 17:15:00
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
: undefined
|
|
678
|
-
return (
|
|
679
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
680
|
-
<WithLocale>
|
|
681
|
-
{(locale) =>
|
|
682
|
-
renderDate({ value, dataType, dtype, displayValue, locale })
|
|
683
|
-
}
|
|
684
|
-
</WithLocale>
|
|
685
|
-
</div>
|
|
691
|
+
return dateCell(
|
|
692
|
+
value,
|
|
693
|
+
format ? String(column.applyColumnFormatting(value)) : undefined,
|
|
686
694
|
);
|
|
687
695
|
}
|
|
688
696
|
|
|
@@ -728,7 +736,7 @@ export function renderCellValue<TData, TValue>({
|
|
|
728
736
|
className={cn(cellStyles, isWrapped && COLUMN_WRAPPING_STYLES)}
|
|
729
737
|
>
|
|
730
738
|
<WhitespaceMarkers value={leading} />
|
|
731
|
-
<UrlDetector parts={parts} />
|
|
739
|
+
<UrlDetector parts={parts} highlightPattern={highlightPattern} />
|
|
732
740
|
<WhitespaceMarkers value={trailing} />
|
|
733
741
|
</div>
|
|
734
742
|
);
|
|
@@ -754,11 +762,7 @@ export function renderCellValue<TData, TValue>({
|
|
|
754
762
|
}
|
|
755
763
|
|
|
756
764
|
if (format) {
|
|
757
|
-
return (
|
|
758
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
759
|
-
{column.applyColumnFormatting(value)}
|
|
760
|
-
</div>
|
|
761
|
-
);
|
|
765
|
+
return textCell(String(column.applyColumnFormatting(value)));
|
|
762
766
|
}
|
|
763
767
|
|
|
764
768
|
// Format to the correct locale
|
|
@@ -768,26 +772,19 @@ export function renderCellValue<TData, TValue>({
|
|
|
768
772
|
<LocaleNumber
|
|
769
773
|
value={value}
|
|
770
774
|
minFractionDigits={column.columnDef.meta?.minFractionDigits}
|
|
775
|
+
highlightPattern={highlightPattern}
|
|
771
776
|
/>
|
|
772
777
|
</div>
|
|
773
778
|
);
|
|
774
779
|
}
|
|
775
780
|
|
|
776
781
|
if (typeof value === "boolean") {
|
|
777
|
-
return (
|
|
778
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
779
|
-
{value ? "True" : "False"}
|
|
780
|
-
</div>
|
|
781
|
-
);
|
|
782
|
+
return textCell(value ? "True" : "False");
|
|
782
783
|
}
|
|
783
784
|
|
|
784
785
|
if (isPrimitiveOrNullish(value)) {
|
|
785
786
|
const rendered = renderValue();
|
|
786
|
-
return (
|
|
787
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
788
|
-
{rendered == null ? "" : String(rendered)}
|
|
789
|
-
</div>
|
|
790
|
-
);
|
|
787
|
+
return textCell(rendered == null ? "" : String(rendered));
|
|
791
788
|
}
|
|
792
789
|
|
|
793
790
|
const mimeValues = getMimeValues(value);
|
|
@@ -825,14 +822,16 @@ export function renderCellValue<TData, TValue>({
|
|
|
825
822
|
export const LocaleNumber = ({
|
|
826
823
|
value,
|
|
827
824
|
minFractionDigits,
|
|
825
|
+
highlightPattern,
|
|
828
826
|
}: {
|
|
829
827
|
value: number;
|
|
830
828
|
minFractionDigits?: number;
|
|
829
|
+
highlightPattern?: RegExp;
|
|
831
830
|
}) => {
|
|
832
831
|
const { locale } = useLocale();
|
|
833
832
|
const format = useNumberFormatter({
|
|
834
833
|
minimumFractionDigits: minFractionDigits,
|
|
835
834
|
maximumFractionDigits: maxFractionalDigits(locale),
|
|
836
835
|
});
|
|
837
|
-
return format.format(value);
|
|
836
|
+
return highlightMatches(format.format(value), highlightPattern);
|
|
838
837
|
};
|