@marimo-team/frontend 0.23.17-dev4 → 0.23.17-dev40
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-DIW20_Z8.js → CellStatus-XlxL4ctu.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-C4zEgCZh.js → ConnectedDataExplorerComponent-BF5CJvB2.js} +1 -1
- package/dist/assets/{ErrorBoundary-DzTD8LVq.js → ErrorBoundary-BfMsWVQU.js} +1 -1
- package/dist/assets/ImageComparisonComponent-CukPDP1p.js +1 -0
- package/dist/assets/{ImperativeModal-fY-ZfT0b.js → ImperativeModal-Ci0icDPt.js} +1 -1
- package/dist/assets/{JsonOutput-Bk2exFh0.js → JsonOutput-CWfu9qbN.js} +13 -13
- package/dist/assets/{LazyAnyLanguageCodeMirror-A-Ant1Ad.js → LazyAnyLanguageCodeMirror-Dcvy_p3-.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-L_o2Knzo.js → MarimoErrorOutput-B9QSRg6T.js} +5 -5
- package/dist/assets/{RSPContexts-WiCgGm__.js → RSPContexts-IrDQoFki.js} +1 -1
- package/dist/assets/{RenderHTML-BTDLQMKg.js → RenderHTML-CQC8I348.js} +1 -1
- package/dist/assets/{RunButton-DiHX9YjB.js → RunButton-DRxV8u_T.js} +1 -1
- package/dist/assets/add-cell-with-ai-GZi9Icll.js +107 -0
- package/dist/assets/{add-connection-dialog-BZaJAQCM.js → add-connection-dialog-D2WiF1f8.js} +31 -31
- package/dist/assets/{agent-panel-CRxiqCgP.js → agent-panel-BWIkm6ln.js} +6 -6
- package/dist/assets/ai-model-dropdown-BmcXWjub.js +5 -0
- package/dist/assets/{alert-dialog-Bb8Lz8ko.js → alert-dialog-DMh8_LWc.js} +1 -1
- package/dist/assets/{any-language-editor-BIeaxtdD.js → any-language-editor-DUQN91an.js} +1 -1
- package/dist/assets/{app-config-button-BS4LSo1l.js → app-config-button-QHaORuxs.js} +1 -1
- package/dist/assets/{blob-B9eg-RfN.js → blob-BzgGkt3B.js} +1 -1
- package/dist/assets/{button-DDGiD1NW.js → button-BB1AV4Rb.js} +1 -1
- package/dist/assets/{cache-panel-B2B1ePao.js → cache-panel-hpL5o4Y7.js} +1 -1
- package/dist/assets/{capabilities-DoEg0XwL.js → capabilities-LI6_PoMn.js} +1 -1
- package/dist/assets/{cell-editor-OC7h_nZ3.js → cell-editor-Cwor7oUx.js} +11 -11
- package/dist/assets/{cell-link-D0aELsL_.js → cell-link-uPmFMRTh.js} +1 -1
- package/dist/assets/cells-BE1kpmPF.css +2 -0
- package/dist/assets/{cells-DLYs3NiJ.js → cells-DxL32Atg.js} +60 -60
- package/dist/assets/chat-display-CH-dFAC3.js +1 -0
- package/dist/assets/chat-panel-DLgorYjE.js +4 -0
- package/dist/assets/chat-ui-DDkwFM3p.js +4 -0
- package/dist/assets/{column-preview-CnqeJb-x.js → column-preview-Dw1ASLnm.js} +1 -1
- package/dist/assets/{command-Dqxie4gq.js → command-CPFHYoYk.js} +1 -1
- package/dist/assets/command-palette--Mo9OaH2.js +1 -0
- package/dist/assets/{common-D_beLbpm.js → common-aHaDUD0-.js} +1 -1
- package/dist/assets/{components-CxEGXaTB.js → components-BQ3c1B_F.js} +1 -1
- package/dist/assets/components-Bm1d4vm9.js +1 -0
- package/dist/assets/config-Bm5B9wGP.js +1 -0
- package/dist/assets/{config-BJVx3eBW.js → config-Cbkt6Rb1.js} +1 -1
- package/dist/assets/{copy-Bxb1_Gtw.js → copy-B-LLR1Yy.js} +1 -1
- package/dist/assets/{copy-icon-neDQUo4Q.js → copy-icon-DWG8Y-xW.js} +1 -1
- package/dist/assets/{createReducer-DGx5Af-C.js → createReducer-DNehfY0t.js} +1 -1
- package/dist/assets/{datasource-Bfg8PKXp.js → datasource-DfQvKiJ1.js} +2 -2
- package/dist/assets/{dates-C2LWzsCZ.js → dates-BzOh4kS_.js} +1 -1
- package/dist/assets/defaultLocale-t77eoiwF.js +1 -0
- package/dist/assets/{dependency-graph-panel-CB5ie0zu.js → dependency-graph-panel-gbgUGtYS.js} +2 -2
- package/dist/assets/{diagram-PSM6KHXK-DIXxW5au.js → diagram-PSM6KHXK-CrTUa1Xy.js} +1 -1
- package/dist/assets/{dialog-BCVepWLJ.js → dialog-88bLE398.js} +1 -1
- package/dist/assets/{dist-CPjTeT8p.js → dist-6qzebh8f.js} +1 -1
- package/dist/assets/dist-BLqRx0W-.js +1 -0
- package/dist/assets/{dist-BP4hpPAE.js → dist-BVr4HQPR.js} +1 -1
- package/dist/assets/{dist-DnjsPBRJ.js → dist-BWXIz8tq.js} +1 -1
- package/dist/assets/{dist-Cros4IAo.js → dist-BWbS__vR.js} +1 -1
- package/dist/assets/dist-BZehnCk2.js +1 -0
- package/dist/assets/dist-BaRgF7DU.js +1 -0
- package/dist/assets/{dist-DYEuVkEX.js → dist-BblMEWTQ.js} +1 -1
- package/dist/assets/dist-BlMeFaGB.js +1 -0
- package/dist/assets/{dist-CrKffqgx.js → dist-BmYa2llD.js} +1 -1
- package/dist/assets/{dist-9o0Xjd5v.js → dist-Btp8vRFr.js} +1 -1
- package/dist/assets/{dist-C-3FVUQA.js → dist-BvMWjDxm.js} +1 -1
- package/dist/assets/{dist-DeJBvhAc.js → dist-ByfZ_2N7.js} +1 -1
- package/dist/assets/dist-C-g2AKOo.js +1 -0
- package/dist/assets/{dist-DQl27SFq.js → dist-C52BqSeO.js} +1 -1
- package/dist/assets/{dist-CiVShZKM.js → dist-C7rDfTPJ.js} +1 -1
- package/dist/assets/{dist-BKgHjzML.js → dist-C830fIIj.js} +1 -1
- package/dist/assets/{dist-fLBYOt9R.js → dist-CHN_sQZw.js} +1 -1
- package/dist/assets/dist-CLFhXj8x.js +1 -0
- package/dist/assets/{dist-D47O3FBX.js → dist-CLQWOmD7.js} +1 -1
- package/dist/assets/dist-CO4dulTL.js +1 -0
- package/dist/assets/dist-CPw3iq_l.js +1 -0
- package/dist/assets/dist-CQtN-vVI.js +1 -0
- package/dist/assets/dist-CZE9FE_5.js +1 -0
- package/dist/assets/dist-CexuM4NA.js +1 -0
- package/dist/assets/{dist-DJuRuTXr.js → dist-CfiLpZZj.js} +1 -1
- package/dist/assets/dist-CjSt6gRp.js +1 -0
- package/dist/assets/dist-Cr4q2U0d.js +1 -0
- package/dist/assets/{dist-C6_DArtj.js → dist-CxaoIFrU.js} +1 -1
- package/dist/assets/{dist-aRc_dRed.js → dist-D5nYeU7Q.js} +1 -1
- package/dist/assets/{dist-BJZAIIze.js → dist-DX04AOlt.js} +1 -1
- package/dist/assets/dist-DkZos4_s.js +1 -0
- package/dist/assets/{dist-DI1-Z60I.js → dist-DmCNk9gq.js} +1 -1
- package/dist/assets/{dist-kLs0VbW_.js → dist-DmjT6iaH.js} +1 -1
- package/dist/assets/{dist-CvWC93qL.js → dist-DrY8fZeD.js} +1 -1
- package/dist/assets/{dist-l4RTzHX-.js → dist-Drexw1Ir.js} +1 -1
- package/dist/assets/{dist-DrBqBDHF.js → dist-DtNSqHzW.js} +1 -1
- package/dist/assets/dist-DxQA7Dn1.js +1 -0
- package/dist/assets/{dist-BLN8PNJV.js → dist-Dza6FJtV.js} +1 -1
- package/dist/assets/{dist-8SH6SWEG.js → dist-HrXjBuXP.js} +1 -1
- package/dist/assets/dist-J00F7mRY.js +1 -0
- package/dist/assets/{dist-DcwTQG1A.js → dist-Jbd9zUbK.js} +1 -1
- package/dist/assets/{dist-CZvbHnyT.js → dist-bvfx5OQE.js} +1 -1
- package/dist/assets/{dist-12S8I4CH.js → dist-gUHullA_.js} +11 -11
- package/dist/assets/dist-nYKCNtEX.js +1 -0
- package/dist/assets/dist-oK8dffBy.js +1 -0
- package/dist/assets/{documentation-panel-Dii7ouzj.js → documentation-panel-DotG4o5W.js} +1 -1
- package/dist/assets/{download-DenADH0w.js → download-Tklnz6pn.js} +3 -3
- package/dist/assets/{dropdown-menu-dHmZR8bI.js → dropdown-menu-BGBlPKNz.js} +1 -1
- package/dist/assets/{edit-page-B0EhuiM-.js → edit-page-DhZPSJ6P.js} +6 -6
- package/dist/assets/{error-banner-BSxEOIn2.js → error-banner-BkIr-0dH.js} +1 -1
- package/dist/assets/{error-entries-4XYBryls.js → error-entries-BvUR_22-.js} +3 -3
- package/dist/assets/{error-panel-xYZ4lX0A.js → error-panel-Upmm4kG5.js} +1 -1
- package/dist/assets/{errors-PgHhDa-M.js → errors-DCPV979Q.js} +1 -1
- package/dist/assets/{es-gYgfF8y5.js → es-Dl2xAwTv.js} +1 -1
- package/dist/assets/{esm-B30N1GS0.js → esm-Bmzgrl_5.js} +1 -1
- package/dist/assets/{esm-BDGraAqp.js → esm-Nb9m4lqg.js} +1 -1
- package/dist/assets/{field-BsxD35VE.js → field-BFgvUZyh.js} +1 -1
- package/dist/assets/file-explorer-panel-BulU96v_.js +37 -0
- package/dist/assets/{file-icons-mgXTzM1c.js → file-icons-NkObNkr_.js} +1 -1
- package/dist/assets/{file-name-input-Dq7Z_QmU.js → file-name-input-BQJ9U9lU.js} +1 -1
- package/dist/assets/{floating-outline-ypOHt2wD.js → floating-outline-BHmregl1.js} +1 -1
- package/dist/assets/{focus-0L1nX7M9.js → focus-BBiJct2G.js} +1 -1
- package/dist/assets/{form-BsW7zr4t.js → form-BIUQB1NI.js} +1 -1
- package/dist/assets/{form-oz4Z280Z.js → form-D-Bo8F9Q.js} +1 -1
- package/dist/assets/{formats-DzmLpc9A.js → formats-DNYtnQk7.js} +1 -1
- package/dist/assets/{formatting-COz4XEaB.js → formatting-qNOrQYRN.js} +1 -1
- package/dist/assets/{fullscreen-CTDqNQr6.js → fullscreen-B51geQ_6.js} +1 -1
- package/dist/assets/{gallery-page-DbuxknAw.js → gallery-page-DBHHOraF.js} +1 -1
- package/dist/assets/{ganttDiagram-JELNMOA3-DaS60lKW.js → ganttDiagram-JELNMOA3-C9KBLmAA.js} +1 -1
- package/dist/assets/{glide-data-editor-CejKKgnN.js → glide-data-editor-CHN4-xUu.js} +1 -1
- package/dist/assets/{home-page-BOP1dDcM.js → home-page-Dvm2dFdU.js} +2 -2
- package/dist/assets/{html-to-image-D_C-hjtC.js → html-to-image-ChNWEUlR.js} +1 -1
- package/dist/assets/index-BPwg3EAk.js +38 -0
- package/dist/assets/index-Dttsymhw.css +2 -0
- package/dist/assets/{input-JxFwu-3G.js → input-_AaMXWgD.js} +1 -1
- package/dist/assets/{kiosk-mode-BvKMuigM.js → kiosk-mode-RTwj6XH4.js} +1 -1
- package/dist/assets/{label-CqjrpwRC.js → label-DUD3SZnk.js} +1 -1
- package/dist/assets/{layout-yfmf2ZBx.js → layout-D7Yzn4XY.js} +4 -4
- package/dist/assets/{linear-BPv4krGt.js → linear-B1ROUUtm.js} +1 -1
- package/dist/assets/{links-ClNQSIal.js → links-DBc28bsl.js} +1 -1
- package/dist/assets/{logs-panel-OMd1Z9CL.js → logs-panel-Cdcjc_fq.js} +1 -1
- package/dist/assets/markdown-export-CNu5ZTPR.js +1 -0
- package/dist/assets/{markdown-renderer-BfLNJGNj.js → markdown-renderer-DpskAUxO.js} +1 -1
- package/dist/assets/{menu-items-CCi6aOPm.js → menu-items-Db-bgz92.js} +1 -1
- package/dist/assets/{mermaid-B8gNHyGy.js → mermaid-OU2hLna0.js} +3 -3
- package/dist/assets/{name-cell-input-COtjRghz.js → name-cell-input-DoxL2EXI.js} +1 -1
- package/dist/assets/{numbers-rmawRqQP.js → numbers-D9g2ArIv.js} +1 -1
- package/dist/assets/{outline-panel-CIGf4SLb.js → outline-panel-BxjI-YSj.js} +1 -1
- package/dist/assets/{packages-panel-DLuMuNuG.js → packages-panel-IN-yS3e2.js} +1 -1
- package/dist/assets/{pair-with-agent-modal-C5OhJ8rX.js → pair-with-agent-modal-1b5Eh8Xo.js} +1 -1
- package/dist/assets/{panel-accordion-state-D1UP17Lk.js → panel-accordion-state-BkWYwckU.js} +1 -1
- package/dist/assets/{panels-B0w23XJS.js → panels-C5PIEySE.js} +2 -2
- package/dist/assets/{popover-Bcz1Zikb.js → popover-DHbixh3D.js} +1 -1
- package/dist/assets/{precisionRound-i2ImZxgc.js → precisionRound-DORAUfVY.js} +1 -1
- package/dist/assets/process-output-DJonUYp2.js +1 -0
- package/dist/assets/{quadrantDiagram-AYHSOK5B-DJuGB95-.js → quadrantDiagram-AYHSOK5B-Duf8sGaa.js} +1 -1
- package/dist/assets/{radio-group-BGXYy3u5.js → radio-group-ByLzIKjm.js} +1 -1
- package/dist/assets/react-vega-J-J2akIt.js +191 -0
- package/dist/assets/{readonly-code-display-DdABj8tH.js → readonly-code-display-B_ZHScA7.js} +1 -1
- package/dist/assets/{readonly-python-code-DUjqXwhi.js → readonly-python-code-C4GeGU7O.js} +1 -1
- package/dist/assets/{renderShortcut-Bl8_FVn8.js → renderShortcut-DnqsU4zj.js} +1 -1
- package/dist/assets/{reveal-component-BjgfnO81.js → reveal-component-BPaqYFXU.js} +2 -2
- package/dist/assets/{run-page-DDty5GvQ.js → run-page-kWVbQ6KV.js} +1 -1
- package/dist/assets/{runs-s9t2f_Tg.js → runs-C6avq6Gi.js} +1 -1
- package/dist/assets/scratchpad-panel-l1iGto9s.js +1 -0
- package/dist/assets/{scroll-to-bottom-button-C8yfT4wq.js → scroll-to-bottom-button-CRMPUjYZ.js} +1 -1
- package/dist/assets/{secrets-panel-Cz17_MLf.js → secrets-panel-DmAwH7vI.js} +1 -1
- package/dist/assets/{select-BP75_5jJ.js → select-Clmc8Hw2.js} +1 -1
- package/dist/assets/{session-BmukRjSi.js → session-BtBr2zr3.js} +1 -1
- package/dist/assets/{session-panel-aMoQPTCB.js → session-panel-CBmLYzFL.js} +1 -1
- package/dist/assets/{share-852X_cqy.js → share-DSOv_SvY.js} +1 -1
- package/dist/assets/{skeleton-CPuDx7yn.js → skeleton-DhhF_mJP.js} +1 -1
- package/dist/assets/{snippets-panel-DBDXr-XP.js → snippets-panel-l_HnIWUj.js} +1 -1
- package/dist/assets/{spec-C7opZZRp.js → spec-CdDzA5ef.js} +1 -1
- package/dist/assets/{state-DCtLlFJq.js → state-B4lC29et.js} +1 -1
- package/dist/assets/{state-C4kiwedg.js → state-BkoVfBqt.js} +1 -1
- package/dist/assets/{state-Brswj8bD.js → state-COqqdiUM.js} +1 -1
- package/dist/assets/{state-hlEqpZfH.js → state-D9xpDCxa.js} +2 -2
- package/dist/assets/{strings--BknHX9C.js → strings-DMKwTex-.js} +1 -1
- package/dist/assets/{swiper-component-DXW8snlt.js → swiper-component-pSAP3cRf.js} +1 -1
- package/dist/assets/switch-8FxRs-OU.js +1 -0
- package/dist/assets/{terminal-CaHTVNrz.js → terminal-DPQJ6hNg.js} +1 -1
- package/dist/assets/{textarea-DtCcemo9.js → textarea-BzWvGIrJ.js} +1 -1
- package/dist/assets/{time-p47i6wvp.js → time-BO-naW1O.js} +1 -1
- package/dist/assets/tooltip-BMi4WFDl.js +61 -0
- package/dist/assets/{tooltip-4bZlU7jl.js → tooltip-BcgbFR7q.js} +1 -1
- package/dist/assets/{tracing-CStM7RGI.js → tracing-DCuWLKnk.js} +1 -1
- package/dist/assets/{tracing-panel-BTLzu8L-.js → tracing-panel-dVtThkzL.js} +2 -2
- package/dist/assets/{tree-actions-BwwVyp3l.js → tree-actions-o2iyMmKN.js} +1 -1
- package/dist/assets/{useBoolean-DIi7jQLa.js → useBoolean-sASJEpGA.js} +1 -1
- package/dist/assets/{useCellActionButton-uxVyv3JK.js → useCellActionButton-CrFbi8en.js} +1 -1
- package/dist/assets/{useDeleteCell-Cy23OP4e.js → useDeleteCell-DH0weyin.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-DNfjp_-X.js → useDependencyPanelTab-OeFV2bye.js} +1 -1
- package/dist/assets/{useEventListener-C0195JsF.js → useEventListener-B_wSLgFR.js} +1 -1
- package/dist/assets/{useHotkey-DLZvrRZT.js → useHotkey-DJyYmk5P.js} +1 -1
- package/dist/assets/{useIframeCapabilities-j6fR_dBA.js → useIframeCapabilities-D_6fB_8O.js} +1 -1
- package/dist/assets/{useInstallPackage-WiYBwhUO.js → useInstallPackage-DyNrAhrx.js} +1 -1
- package/dist/assets/{useInterval-CnQfyMa9.js → useInterval-CjGsg4ie.js} +1 -1
- package/dist/assets/useNotebookActions-CylmZilh.js +12 -0
- package/dist/assets/useRunCells-8xYRh7wH.js +1 -0
- package/dist/assets/{useSplitCell-BK5mnkkL.js → useSplitCell-BvgvIZaz.js} +1 -1
- package/dist/assets/{useTheme-Bxv9B31g.js → useTheme-BR31Gjbc.js} +1 -1
- package/dist/assets/utils-C5VWChv9.js +1 -0
- package/dist/assets/{vega-component-BGiCExka.js → vega-component-DG9G1qk2.js} +1 -1
- package/dist/assets/{vega-embed-container-DxSqUOCK.js → vega-embed-container-BJRQVehC.js} +1 -1
- package/dist/assets/vega-loader.browser-CAfmqKEc.js +6 -0
- package/dist/assets/{write-secret-modal-Dtm66yVf.js → write-secret-modal-DwCUuNRy.js} +1 -1
- package/dist/assets/{xychartDiagram-PRI3JC2R-B8A0hi-Q.js → xychartDiagram-PRI3JC2R-ClPpSFDI.js} +1 -1
- package/dist/assets/{zod-H_cgTO0M.js → zod-CIOjj3iA.js} +5 -5
- package/dist/index.html +87 -87
- package/package.json +6 -6
- package/src/__mocks__/requests.ts +5 -0
- package/src/components/app-config/user-config-form.tsx +26 -0
- package/src/components/chat/__tests__/chat-abort.test.ts +51 -0
- package/src/components/chat/chat-abort.ts +44 -0
- package/src/components/chat/chat-display.tsx +17 -0
- package/src/components/chat/chat-panel.tsx +85 -37
- package/src/components/chat/chat-utils.ts +1 -1
- package/src/components/data-table/charts/__tests__/schemas.test.ts +35 -0
- package/src/components/data-table/charts/schemas.ts +5 -2
- package/src/components/databases/icons/huggingface.svg +8 -0
- package/src/components/datasets/__tests__/icons.test.ts +21 -0
- package/src/components/datasets/icons.tsx +10 -0
- package/src/components/datasources/__tests__/components.test.tsx +29 -0
- package/src/components/datasources/components.tsx +8 -3
- package/src/components/editor/actions/export-dialog/__tests__/export-dialog.test.tsx +35 -0
- package/src/components/editor/actions/export-dialog/__tests__/state.test.ts +61 -0
- package/src/components/editor/actions/export-dialog/export-command.ts +4 -9
- package/src/components/editor/actions/export-dialog/export-dialog.tsx +27 -23
- package/src/components/editor/actions/export-dialog/format-notice.tsx +28 -0
- package/src/components/editor/actions/export-dialog/state.ts +23 -5
- package/src/components/editor/actions/export-dialog/use-export-dialog.ts +7 -15
- package/src/components/editor/actions/useConfigActions.tsx +24 -0
- package/src/components/editor/ai/add-cell-with-ai.tsx +2 -2
- package/src/components/editor/ai/ai-completion-editor.tsx +2 -2
- package/src/components/editor/chrome/panels/outline/__tests__/useActiveOutline.test.ts +26 -0
- package/src/components/editor/code/__tests__/readonly-python-code.test.tsx +114 -2
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +14 -0
- package/src/components/editor/connections/storage/__tests__/as-code.test.ts +20 -0
- package/src/components/editor/connections/storage/add-storage-form.tsx +10 -0
- package/src/components/editor/connections/storage/as-code.ts +19 -1
- package/src/components/editor/connections/storage/schemas.ts +19 -0
- package/src/components/storage/__tests__/storage-snippets.test.ts +88 -0
- package/src/components/storage/components.tsx +2 -0
- package/src/components/storage/storage-snippets.ts +58 -0
- package/src/core/__tests__/mode.test.ts +85 -0
- package/src/core/ai/constants.ts +7 -0
- package/src/core/ai/staged-cells.ts +3 -0
- package/src/core/codemirror/__tests__/setup.test.ts +1 -1
- package/src/core/codemirror/cm.ts +2 -2
- package/src/core/codemirror/code-lens/__tests__/extension.test.ts +4 -5
- package/src/core/codemirror/code-lens/extension.ts +3 -3
- package/src/core/codemirror/find-replace/search-highlight.ts +8 -3
- package/src/core/codemirror/language/languages/sql/__tests__/renderers.test.tsx +44 -0
- package/src/core/codemirror/language/languages/sql/renderers.tsx +3 -3
- package/src/core/codemirror/theme/__tests__/light.test.ts +59 -123
- package/src/core/codemirror/theme/dark.ts +6 -5
- package/src/core/codemirror/theme/light.ts +6 -4
- package/src/core/config/__tests__/config-schema.test.ts +2 -0
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/dom/outline.ts +25 -2
- package/src/core/hotkeys/hotkeys.ts +2 -0
- package/src/core/mode.ts +11 -9
- package/src/core/network/__tests__/api.test.ts +132 -17
- package/src/core/network/__tests__/export-filename.test.ts +43 -0
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -0
- package/src/core/network/api.ts +47 -12
- package/src/core/network/export-filename.ts +37 -0
- package/src/core/network/markdown-export.ts +19 -0
- package/src/core/network/requests-network.ts +29 -5
- package/src/core/network/types.ts +3 -0
- package/src/core/storage/types.ts +1 -0
- package/src/css/app/codemirror.css +11 -7
- package/src/css/globals.css +8 -0
- package/src/plugins/impl/DataEditorPlugin.tsx +2 -9
- package/src/plugins/impl/__tests__/DataEditorPlugin.test.ts +18 -0
- package/src/plugins/impl/chat/chat-ui.tsx +51 -3
- package/src/plugins/impl/data-frames/__tests__/schema.test.ts +30 -0
- package/src/plugins/impl/data-frames/schema.ts +4 -1
- package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +20 -1
- package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +58 -0
- package/src/stories/theme.stories.tsx +71 -1
- package/dist/assets/ImageComparisonComponent-COvcNAUu.js +0 -1
- package/dist/assets/add-cell-with-ai-BU5EDuHt.js +0 -107
- package/dist/assets/ai-model-dropdown-CLCa-gsg.js +0 -5
- package/dist/assets/cells-BVzo2MHf.css +0 -2
- package/dist/assets/chat-display-7CzBSZRm.js +0 -1
- package/dist/assets/chat-panel-Dd5WiR1a.js +0 -4
- package/dist/assets/chat-ui-CYqqqoSC.js +0 -4
- package/dist/assets/command-palette-BBlSC8AZ.js +0 -1
- package/dist/assets/components-K_Mi0vdC.js +0 -1
- package/dist/assets/config-DAL-jiRM.js +0 -1
- package/dist/assets/defaultLocale-DOVIEEPN.js +0 -1
- package/dist/assets/dist-B99-E4qp.js +0 -1
- package/dist/assets/dist-Bfm9U3vp.js +0 -1
- package/dist/assets/dist-BiwuSVkx.js +0 -1
- package/dist/assets/dist-BrZjJXDA.js +0 -1
- package/dist/assets/dist-CaZf6AoY.js +0 -1
- package/dist/assets/dist-Cgoy5550.js +0 -1
- package/dist/assets/dist-Csf5i4KY.js +0 -1
- package/dist/assets/dist-D6Iobl3P.js +0 -1
- package/dist/assets/dist-D6WgndTj.js +0 -1
- package/dist/assets/dist-DcXy-1eJ.js +0 -1
- package/dist/assets/dist-DsfPGbgk.js +0 -1
- package/dist/assets/dist-DtbtRAqz.js +0 -1
- package/dist/assets/dist-I3qeQWuP.js +0 -1
- package/dist/assets/dist-aeKlrIMv.js +0 -1
- package/dist/assets/dist-gDi2I7IJ.js +0 -1
- package/dist/assets/dist-miDa4-cz.js +0 -1
- package/dist/assets/dist-nDEBxpL6.js +0 -1
- package/dist/assets/dist-oUL4XFdB.js +0 -1
- package/dist/assets/file-explorer-panel-4h-BKKaM.js +0 -26
- package/dist/assets/house-DS0r7dNZ.js +0 -1
- package/dist/assets/index-BXlfeAku.js +0 -38
- package/dist/assets/index-DYycoCjG.css +0 -2
- package/dist/assets/process-output-Cm_vuKBw.js +0 -1
- package/dist/assets/react-vega-BLc5RhC7.js +0 -188
- package/dist/assets/scratchpad-panel-DJkO5OrI.js +0 -1
- package/dist/assets/switch-CONP-vq2.js +0 -1
- package/dist/assets/tooltip-B7U4xkIN.js +0 -61
- package/dist/assets/useNotebookActions-BHaEvPEM.js +0 -12
- package/dist/assets/useRunCells-kmbsc2R5.js +0 -1
- package/dist/assets/utils-BWBBpCkT.js +0 -1
- package/dist/assets/vega-loader.browser-Dun7Qe4B.js +0 -6
- /package/dist/assets/{bundle.esm-D0TWQ6iT.js → bundle.esm-CvMga-X6.js} +0 -0
- /package/dist/assets/{icons-CIPE8AIY.js → icons-NFYKylj6.js} +0 -0
- /package/dist/assets/{useDeepCompareMemoize-CSMoa-ga.js → useDeepCompareMemoize-BLRnan2Y.js} +0 -0
|
@@ -101,31 +101,35 @@ export const ExportDialog: React.FC<{
|
|
|
101
101
|
})}
|
|
102
102
|
</TabsList>
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
formatLabel={definition.label}
|
|
118
|
-
status={status}
|
|
119
|
-
/>
|
|
104
|
+
{/* One panel per tab so each trigger's aria-controls resolves. */}
|
|
105
|
+
{formats.map(({ format: candidate }) => (
|
|
106
|
+
<TabsContent
|
|
107
|
+
key={candidate}
|
|
108
|
+
value={candidate}
|
|
109
|
+
className="mt-0 min-h-0 min-w-0 overflow-y-auto px-4 py-3"
|
|
110
|
+
>
|
|
111
|
+
<div className="mb-3">
|
|
112
|
+
<h3 className="text-base font-semibold">{definition.label}</h3>
|
|
113
|
+
<p className="mt-0.5 text-sm text-muted-foreground">
|
|
114
|
+
{definition.description}
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
120
117
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
disabled={isExporting}
|
|
118
|
+
<FormatNotice
|
|
119
|
+
format={format}
|
|
120
|
+
formatLabel={definition.label}
|
|
121
|
+
status={status}
|
|
126
122
|
/>
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
|
|
124
|
+
{usesBrowserPrint ? null : (
|
|
125
|
+
<FormatOptions
|
|
126
|
+
options={options}
|
|
127
|
+
updateOptions={updateOptions}
|
|
128
|
+
disabled={isExporting}
|
|
129
|
+
/>
|
|
130
|
+
)}
|
|
131
|
+
</TabsContent>
|
|
132
|
+
))}
|
|
129
133
|
</Tabs>
|
|
130
134
|
|
|
131
135
|
<footer className="min-w-0 border-t bg-muted/20 px-4 py-3">
|
|
@@ -10,8 +10,18 @@ import type {
|
|
|
10
10
|
ExportBlockReason,
|
|
11
11
|
ExportFormat,
|
|
12
12
|
ExportFormatStatus,
|
|
13
|
+
ExportSetupRequirement,
|
|
13
14
|
} from "./state";
|
|
14
15
|
|
|
16
|
+
const SETUP_REQUIREMENTS: Record<
|
|
17
|
+
ExportSetupRequirement["name"],
|
|
18
|
+
{ description: string }
|
|
19
|
+
> = {
|
|
20
|
+
"playwright-chromium": {
|
|
21
|
+
description: "PDF export requires Playwright Chromium.",
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
15
25
|
export function FormatStatusIcon({ status }: { status: ExportFormatStatus }) {
|
|
16
26
|
if (status.available && !status.availabilityCheckFailed) {
|
|
17
27
|
return null;
|
|
@@ -124,6 +134,24 @@ function ReasonNotice({
|
|
|
124
134
|
where marimo is running to use this export.
|
|
125
135
|
</Notice>
|
|
126
136
|
);
|
|
137
|
+
case "missing-setup":
|
|
138
|
+
return (
|
|
139
|
+
<Notice>
|
|
140
|
+
<span className="block min-w-0">
|
|
141
|
+
{reason.requirements.map((requirement) => {
|
|
142
|
+
const details = SETUP_REQUIREMENTS[requirement.name];
|
|
143
|
+
return (
|
|
144
|
+
<span className="block" key={requirement.name}>
|
|
145
|
+
{details.description}
|
|
146
|
+
<code className="mt-1 block break-all font-mono">
|
|
147
|
+
{requirement.command}
|
|
148
|
+
</code>
|
|
149
|
+
</span>
|
|
150
|
+
);
|
|
151
|
+
})}
|
|
152
|
+
</span>
|
|
153
|
+
</Notice>
|
|
154
|
+
);
|
|
127
155
|
case "wasm-runtime":
|
|
128
156
|
return (
|
|
129
157
|
<Notice>
|
|
@@ -15,6 +15,8 @@ export const EXPORT_FORMATS = [
|
|
|
15
15
|
] as const;
|
|
16
16
|
|
|
17
17
|
export type ExportFormat = (typeof EXPORT_FORMATS)[number];
|
|
18
|
+
export type ExportSetupRequirement =
|
|
19
|
+
ExportAvailabilityResponse["formats"][number]["missingSetup"][number];
|
|
18
20
|
|
|
19
21
|
export const MARKDOWN_FLAVORS = ["pymdown", "qmd", "mystmd", "mdx"] as const;
|
|
20
22
|
export const IPYNB_SORT_MODES = ["topological", "top-down"] as const;
|
|
@@ -185,6 +187,7 @@ export type ExportBlockReason =
|
|
|
185
187
|
| { type: "checking-requirements" }
|
|
186
188
|
| { type: "notebook-must-be-named" }
|
|
187
189
|
| { type: "missing-packages"; packages: string[] }
|
|
190
|
+
| { type: "missing-setup"; requirements: ExportSetupRequirement[] }
|
|
188
191
|
| { type: "wasm-runtime" };
|
|
189
192
|
|
|
190
193
|
export interface ExportFormatStatus {
|
|
@@ -308,12 +311,27 @@ export function getExportFormatStatus({
|
|
|
308
311
|
return { available: true, availabilityCheckFailed: true };
|
|
309
312
|
}
|
|
310
313
|
if (!serverStatus.dependenciesAvailable) {
|
|
314
|
+
if (serverStatus.missingPackages.length > 0) {
|
|
315
|
+
return {
|
|
316
|
+
available: false,
|
|
317
|
+
reason: {
|
|
318
|
+
type: "missing-packages",
|
|
319
|
+
packages: serverStatus.missingPackages,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (serverStatus.missingSetup.length > 0) {
|
|
324
|
+
return {
|
|
325
|
+
available: false,
|
|
326
|
+
reason: {
|
|
327
|
+
type: "missing-setup",
|
|
328
|
+
requirements: serverStatus.missingSetup,
|
|
329
|
+
},
|
|
330
|
+
};
|
|
331
|
+
}
|
|
311
332
|
return {
|
|
312
|
-
available:
|
|
313
|
-
|
|
314
|
-
type: "missing-packages",
|
|
315
|
-
packages: serverStatus.missingPackages,
|
|
316
|
-
},
|
|
333
|
+
available: true,
|
|
334
|
+
availabilityCheckFailed: true,
|
|
317
335
|
};
|
|
318
336
|
}
|
|
319
337
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { useAtom
|
|
3
|
+
import { useAtom } from "jotai";
|
|
4
4
|
import { useEffect, useRef, useState } from "react";
|
|
5
5
|
import { toast } from "@/components/ui/use-toast";
|
|
6
6
|
import {
|
|
7
7
|
updateCellOutputsWithScreenshots,
|
|
8
8
|
useEnrichCellOutputs,
|
|
9
9
|
} from "@/core/export/hooks";
|
|
10
|
-
import { runDuringPresentMode
|
|
10
|
+
import { runDuringPresentMode } from "@/core/mode";
|
|
11
11
|
import { useRequestClient } from "@/core/network/requests";
|
|
12
12
|
import type { ExportAvailabilityResponse } from "@/core/network/types";
|
|
13
13
|
import { useFilename } from "@/core/saving/filename";
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
withLoadingToast,
|
|
22
22
|
} from "@/utils/download";
|
|
23
23
|
import { Filenames } from "@/utils/filenames";
|
|
24
|
+
import { Logger } from "@/utils/Logger";
|
|
24
25
|
import { Paths } from "@/utils/paths";
|
|
25
26
|
import { getExportCommand } from "./export-command";
|
|
26
27
|
import { exportNotebook } from "./export-notebook";
|
|
@@ -277,8 +278,6 @@ function useExportDialogAction({
|
|
|
277
278
|
}) {
|
|
278
279
|
const requests = useRequestClient();
|
|
279
280
|
const takeScreenshots = useEnrichCellOutputs();
|
|
280
|
-
const viewState = useAtomValue(viewStateAtom);
|
|
281
|
-
const setViewState = useSetAtom(viewStateAtom);
|
|
282
281
|
const [isExporting, setIsExporting] = useState(false);
|
|
283
282
|
const dialogRef = useRef<HTMLDivElement>(null);
|
|
284
283
|
const mountedRef = useRef(true);
|
|
@@ -302,15 +301,7 @@ function useExportDialogAction({
|
|
|
302
301
|
const capturePNG = async () => {
|
|
303
302
|
const capture = () =>
|
|
304
303
|
captureCurrentAppView(dialogRef.current?.parentElement ?? null);
|
|
305
|
-
|
|
306
|
-
await capture();
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
await runDuringPresentMode(capture);
|
|
311
|
-
} finally {
|
|
312
|
-
setViewState(viewState);
|
|
313
|
-
}
|
|
304
|
+
await runDuringPresentMode(capture);
|
|
314
305
|
};
|
|
315
306
|
|
|
316
307
|
const submit = async () => {
|
|
@@ -342,8 +333,9 @@ function useExportDialogAction({
|
|
|
342
333
|
if (mountedRef.current) {
|
|
343
334
|
onClose();
|
|
344
335
|
}
|
|
345
|
-
} catch {
|
|
346
|
-
//
|
|
336
|
+
} catch (error) {
|
|
337
|
+
// Most helpers toast actionable errors, but not all (e.g. updateCellOutputs).
|
|
338
|
+
Logger.error("Export failed", error);
|
|
347
339
|
} finally {
|
|
348
340
|
if (mountedRef.current) {
|
|
349
341
|
setIsExporting(false);
|
|
@@ -141,6 +141,30 @@ export function useConfigActions() {
|
|
|
141
141
|
});
|
|
142
142
|
},
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
label: "Config > Disable code lens",
|
|
146
|
+
hidden: !(config.display.code_lens ?? true),
|
|
147
|
+
handle: () => {
|
|
148
|
+
handleUserConfig({
|
|
149
|
+
display: {
|
|
150
|
+
...config.display,
|
|
151
|
+
code_lens: false,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
label: "Config > Enable code lens",
|
|
158
|
+
hidden: config.display.code_lens ?? true,
|
|
159
|
+
handle: () => {
|
|
160
|
+
handleUserConfig({
|
|
161
|
+
display: {
|
|
162
|
+
...config.display,
|
|
163
|
+
code_lens: true,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
},
|
|
144
168
|
{
|
|
145
169
|
label: "Config > Set cell output area: above",
|
|
146
170
|
hidden: config.display.cell_output === "above",
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
} from "@/components/ui/dropdown-menu";
|
|
52
52
|
import { toast } from "@/components/ui/use-toast";
|
|
53
53
|
import { AiModelId } from "@/core/ai/ids/ids";
|
|
54
|
+
import { AI_SDK_UI_THROTTLE_MS } from "@/core/ai/constants";
|
|
54
55
|
import { stagedAICellsAtom, useStagedCells } from "@/core/ai/staged-cells";
|
|
55
56
|
import type { ToolNotebookContext } from "@/core/ai/tools/base";
|
|
56
57
|
import { useCellActions } from "@/core/cells/cells";
|
|
@@ -117,8 +118,7 @@ export const AddCellWithAI: React.FC<{
|
|
|
117
118
|
};
|
|
118
119
|
|
|
119
120
|
const { sendMessage, stop, status, addToolOutput } = useChat({
|
|
120
|
-
|
|
121
|
-
experimental_throttle: 100,
|
|
121
|
+
throttle: AI_SDK_UI_THROTTLE_MS,
|
|
122
122
|
transport: new StreamingChunkTransport(
|
|
123
123
|
{
|
|
124
124
|
api: runtimeManager.getAiURL("completion").toString(),
|
|
@@ -27,6 +27,7 @@ import { Label } from "@/components/ui/label";
|
|
|
27
27
|
import { Switch } from "@/components/ui/switch";
|
|
28
28
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
29
29
|
import { toast } from "@/components/ui/use-toast";
|
|
30
|
+
import { AI_SDK_UI_THROTTLE_MS } from "@/core/ai/constants";
|
|
30
31
|
import { stripWrappingBackticks } from "@/core/ai/strip-wrapping-backticks";
|
|
31
32
|
import { type AiCompletionCell, includeOtherCellsAtom } from "@/core/ai/state";
|
|
32
33
|
import type { CellId } from "@/core/cells/ids";
|
|
@@ -124,8 +125,7 @@ export const AiCompletionEditor: React.FC<Props> = ({
|
|
|
124
125
|
api: runtimeManager.getAiURL("completion").toString(),
|
|
125
126
|
headers: runtimeManager.headers(),
|
|
126
127
|
initialInput: initialPrompt,
|
|
127
|
-
|
|
128
|
-
experimental_throttle: 100,
|
|
128
|
+
throttle: AI_SDK_UI_THROTTLE_MS,
|
|
129
129
|
body: {
|
|
130
130
|
...(Object.keys(completionBody).length > 0
|
|
131
131
|
? completionBody
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { parseOutline } from "@/core/dom/outline";
|
|
4
|
+
import { findOutlineElements } from "../useActiveOutline";
|
|
5
|
+
|
|
6
|
+
describe("findOutlineElements", () => {
|
|
7
|
+
it.each([
|
|
8
|
+
"Design from the portfolio",
|
|
9
|
+
'Decorative Art of "Spanish California"',
|
|
10
|
+
`The painter's "Study"`,
|
|
11
|
+
])("finds an id-less heading named %s", (name) => {
|
|
12
|
+
const html = `<h3>${name}</h3>`;
|
|
13
|
+
document.body.innerHTML = html;
|
|
14
|
+
|
|
15
|
+
const outline = parseOutline({
|
|
16
|
+
mimetype: "text/html",
|
|
17
|
+
timestamp: 0,
|
|
18
|
+
channel: "output",
|
|
19
|
+
data: html,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(
|
|
23
|
+
findOutlineElements(outline?.items ?? []).map(([element]) => element),
|
|
24
|
+
).toEqual([document.querySelector("h3")]);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -1,13 +1,61 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { EditorView } from "@codemirror/view";
|
|
4
|
+
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
5
|
+
import {
|
|
6
|
+
afterAll,
|
|
7
|
+
beforeAll,
|
|
8
|
+
beforeEach,
|
|
9
|
+
describe,
|
|
10
|
+
expect,
|
|
11
|
+
it,
|
|
12
|
+
vi,
|
|
13
|
+
} from "vitest";
|
|
5
14
|
import { SetupMocks } from "@/__mocks__/common";
|
|
6
15
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
7
16
|
import { ReadonlyCode } from "../readonly-python-code";
|
|
8
17
|
|
|
18
|
+
const themeState = vi.hoisted(() => ({
|
|
19
|
+
value: "light" as "light" | "dark",
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
let originalRangeGetClientRects: PropertyDescriptor | undefined;
|
|
23
|
+
|
|
24
|
+
vi.mock("@/theme/useTheme", async (importOriginal) => {
|
|
25
|
+
const actual = await importOriginal<typeof import("@/theme/useTheme")>();
|
|
26
|
+
return {
|
|
27
|
+
...actual,
|
|
28
|
+
useTheme: () => ({ theme: themeState.value }),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
9
32
|
beforeAll(() => {
|
|
10
33
|
SetupMocks.resizeObserver();
|
|
34
|
+
originalRangeGetClientRects = Object.getOwnPropertyDescriptor(
|
|
35
|
+
Range.prototype,
|
|
36
|
+
"getClientRects",
|
|
37
|
+
);
|
|
38
|
+
Object.defineProperty(Range.prototype, "getClientRects", {
|
|
39
|
+
configurable: true,
|
|
40
|
+
value: () => [],
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
afterAll(() => {
|
|
45
|
+
// Keep the shared JSDOM prototype unchanged for other test files.
|
|
46
|
+
if (originalRangeGetClientRects) {
|
|
47
|
+
Object.defineProperty(
|
|
48
|
+
Range.prototype,
|
|
49
|
+
"getClientRects",
|
|
50
|
+
originalRangeGetClientRects,
|
|
51
|
+
);
|
|
52
|
+
} else {
|
|
53
|
+
Reflect.deleteProperty(Range.prototype, "getClientRects");
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
themeState.value = "light";
|
|
11
59
|
});
|
|
12
60
|
|
|
13
61
|
/**
|
|
@@ -26,7 +74,71 @@ function isCollapsed(root: ParentNode) {
|
|
|
26
74
|
return root.querySelector(".cm")?.classList.contains("opacity-20") ?? false;
|
|
27
75
|
}
|
|
28
76
|
|
|
77
|
+
function getEditorIdentity(view: EditorView) {
|
|
78
|
+
return {
|
|
79
|
+
doc: view.state.doc,
|
|
80
|
+
dom: view.dom,
|
|
81
|
+
contentDOM: view.contentDOM,
|
|
82
|
+
scrollDOM: view.scrollDOM,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function expectEditorIdentity(
|
|
87
|
+
view: EditorView,
|
|
88
|
+
identity: ReturnType<typeof getEditorIdentity>,
|
|
89
|
+
) {
|
|
90
|
+
expect(view.state.doc).toBe(identity.doc);
|
|
91
|
+
expect(view.dom).toBe(identity.dom);
|
|
92
|
+
expect(view.contentDOM).toBe(identity.contentDOM);
|
|
93
|
+
expect(view.scrollDOM).toBe(identity.scrollDOM);
|
|
94
|
+
}
|
|
95
|
+
|
|
29
96
|
describe("ReadonlyCode", () => {
|
|
97
|
+
it("reconfigures the theme without replacing the editor", async () => {
|
|
98
|
+
let createdView: EditorView | undefined;
|
|
99
|
+
const onCreateEditor = (view: EditorView) => {
|
|
100
|
+
createdView = view;
|
|
101
|
+
};
|
|
102
|
+
const renderCode = (id: string) => (
|
|
103
|
+
<TooltipProvider>
|
|
104
|
+
<ReadonlyCode
|
|
105
|
+
id={id}
|
|
106
|
+
code={"line_1 = 1\nline_2 = 2\nline_3 = 3"}
|
|
107
|
+
showCopyCode={false}
|
|
108
|
+
onCreateEditor={onCreateEditor}
|
|
109
|
+
/>
|
|
110
|
+
</TooltipProvider>
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const { rerender } = render(renderCode("light"));
|
|
114
|
+
await waitFor(() => {
|
|
115
|
+
expect(createdView).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const view = createdView;
|
|
119
|
+
if (!view) {
|
|
120
|
+
throw new Error("ReadonlyCode did not create an editor view");
|
|
121
|
+
}
|
|
122
|
+
const identity = getEditorIdentity(view);
|
|
123
|
+
expect(view.state.facet(EditorView.darkTheme)).toBe(false);
|
|
124
|
+
|
|
125
|
+
themeState.value = "dark";
|
|
126
|
+
rerender(renderCode("dark"));
|
|
127
|
+
await waitFor(() => {
|
|
128
|
+
expect(view.state.facet(EditorView.darkTheme)).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
expect(createdView).toBe(view);
|
|
131
|
+
expectEditorIdentity(view, identity);
|
|
132
|
+
|
|
133
|
+
themeState.value = "light";
|
|
134
|
+
rerender(renderCode("light-again"));
|
|
135
|
+
await waitFor(() => {
|
|
136
|
+
expect(view.state.facet(EditorView.darkTheme)).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
expect(createdView).toBe(view);
|
|
139
|
+
expectEditorIdentity(view, identity);
|
|
140
|
+
});
|
|
141
|
+
|
|
30
142
|
it("starts collapsed when initiallyHideCode is true", () => {
|
|
31
143
|
const { container } = renderReadonly({ initiallyHideCode: true });
|
|
32
144
|
expect(isCollapsed(container)).toBe(true);
|
package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap
CHANGED
|
@@ -154,6 +154,20 @@ _creds = json.loads(_credentials_json)
|
|
|
154
154
|
fs = GoogleDriveFileSystem(creds=_creds, token="service_account", use_listings_cache=False, skip_instance_cache=True)"
|
|
155
155
|
`;
|
|
156
156
|
|
|
157
|
+
exports[`generateStorageCode > Hugging Face > default connection 1`] = `
|
|
158
|
+
"from huggingface_hub import HfApi
|
|
159
|
+
|
|
160
|
+
hf = HfApi()"
|
|
161
|
+
`;
|
|
162
|
+
|
|
163
|
+
exports[`generateStorageCode > Hugging Face > with token from secrets 1`] = `
|
|
164
|
+
"from huggingface_hub import HfApi
|
|
165
|
+
import os
|
|
166
|
+
|
|
167
|
+
_token = os.environ.get("HF_TOKEN")
|
|
168
|
+
hf = HfApi(token=_token)"
|
|
169
|
+
`;
|
|
170
|
+
|
|
157
171
|
exports[`generateStorageCode > S3 > basic connection with all fields 1`] = `
|
|
158
172
|
"from obstore.store import S3Store
|
|
159
173
|
|
|
@@ -309,6 +309,26 @@ describe("generateStorageCode", () => {
|
|
|
309
309
|
});
|
|
310
310
|
});
|
|
311
311
|
|
|
312
|
+
describe("Hugging Face", () => {
|
|
313
|
+
it("default connection", () => {
|
|
314
|
+
expect(
|
|
315
|
+
generateStorageCode({ type: "huggingface" }, { library: "fsspec" }),
|
|
316
|
+
).toMatchSnapshot();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it("with token from secrets", () => {
|
|
320
|
+
expect(
|
|
321
|
+
generateStorageCode(
|
|
322
|
+
{
|
|
323
|
+
type: "huggingface",
|
|
324
|
+
token: prefixSecret("HF_TOKEN"),
|
|
325
|
+
},
|
|
326
|
+
{ library: "fsspec" },
|
|
327
|
+
),
|
|
328
|
+
).toMatchSnapshot();
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
312
332
|
describe("invalid cases", () => {
|
|
313
333
|
it("throws for empty S3 bucket", () => {
|
|
314
334
|
expect(() =>
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CoreWeaveStorageSchema,
|
|
18
18
|
GCSStorageSchema,
|
|
19
19
|
GoogleDriveStorageSchema,
|
|
20
|
+
HuggingfaceStorageSchema,
|
|
20
21
|
S3StorageSchema,
|
|
21
22
|
type StorageConnection,
|
|
22
23
|
} from "./schemas";
|
|
@@ -79,6 +80,15 @@ const STORAGE_PROVIDERS = [
|
|
|
79
80
|
preferred: "fsspec",
|
|
80
81
|
},
|
|
81
82
|
},
|
|
83
|
+
{
|
|
84
|
+
name: "Hugging Face Hub",
|
|
85
|
+
schema: HuggingfaceStorageSchema,
|
|
86
|
+
protocol: "hf",
|
|
87
|
+
storageLibraries: {
|
|
88
|
+
libraries: ["huggingface_hub"],
|
|
89
|
+
preferred: "huggingface_hub",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
82
92
|
] satisfies StorageProviderSchema[];
|
|
83
93
|
|
|
84
94
|
const StorageProviderSelector: React.FC<{
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
StorageConnectionSchema,
|
|
11
11
|
} from "./schemas";
|
|
12
12
|
|
|
13
|
-
export type StorageLibrary = "obstore" | "fsspec";
|
|
13
|
+
export type StorageLibrary = "obstore" | "fsspec" | "huggingface_hub";
|
|
14
14
|
|
|
15
15
|
export interface StorageCodeOptions {
|
|
16
16
|
library: StorageLibrary;
|
|
@@ -20,6 +20,7 @@ export interface StorageCodeOptions {
|
|
|
20
20
|
export const StorageLibraryDisplayNames: Record<StorageLibrary, string> = {
|
|
21
21
|
obstore: "obstore",
|
|
22
22
|
fsspec: "fsspec",
|
|
23
|
+
huggingface_hub: "huggingface_hub",
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
class SecretContainer {
|
|
@@ -245,6 +246,20 @@ function generateGDriveCode(
|
|
|
245
246
|
return { imports, code };
|
|
246
247
|
}
|
|
247
248
|
|
|
249
|
+
function generateHuggingfaceCode(
|
|
250
|
+
connection: Extract<StorageConnection, { type: "huggingface" }>,
|
|
251
|
+
secrets: SecretContainer,
|
|
252
|
+
): { imports: Set<string>; code: string } {
|
|
253
|
+
const imports = new Set(["from huggingface_hub import HfApi"]);
|
|
254
|
+
|
|
255
|
+
if (!connection.token) {
|
|
256
|
+
return { imports, code: "hf = HfApi()" };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const token = secrets.print("token", connection.token);
|
|
260
|
+
return { imports, code: `hf = HfApi(token=${token})` };
|
|
261
|
+
}
|
|
262
|
+
|
|
248
263
|
export function generateStorageCode(
|
|
249
264
|
connection: StorageConnection,
|
|
250
265
|
options: StorageCodeOptions,
|
|
@@ -273,6 +288,9 @@ export function generateStorageCode(
|
|
|
273
288
|
isEmbedded: options.isEmbedded,
|
|
274
289
|
});
|
|
275
290
|
break;
|
|
291
|
+
case "huggingface":
|
|
292
|
+
result = generateHuggingfaceCode(connection, secrets);
|
|
293
|
+
break;
|
|
276
294
|
default:
|
|
277
295
|
assertNever(connection);
|
|
278
296
|
}
|
|
@@ -220,12 +220,31 @@ export const GoogleDriveStorageSchema = z
|
|
|
220
220
|
})
|
|
221
221
|
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
222
222
|
|
|
223
|
+
export const HuggingfaceStorageSchema = z
|
|
224
|
+
.object({
|
|
225
|
+
type: z.literal("huggingface"),
|
|
226
|
+
token: z
|
|
227
|
+
.string()
|
|
228
|
+
.optional()
|
|
229
|
+
.describe(
|
|
230
|
+
FieldOptions.of({
|
|
231
|
+
label: "Access Token",
|
|
232
|
+
description:
|
|
233
|
+
"Leave empty to use the HF_TOKEN environment variable or cached login",
|
|
234
|
+
inputType: "password",
|
|
235
|
+
optionRegex: "(hf.?token|hugging.?face.?token|hub.?token)",
|
|
236
|
+
}),
|
|
237
|
+
),
|
|
238
|
+
})
|
|
239
|
+
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
240
|
+
|
|
223
241
|
export const StorageConnectionSchema = z.discriminatedUnion("type", [
|
|
224
242
|
S3StorageSchema,
|
|
225
243
|
GCSStorageSchema,
|
|
226
244
|
AzureStorageSchema,
|
|
227
245
|
CoreWeaveStorageSchema,
|
|
228
246
|
GoogleDriveStorageSchema,
|
|
247
|
+
HuggingfaceStorageSchema,
|
|
229
248
|
]);
|
|
230
249
|
|
|
231
250
|
export type StorageConnection = z.infer<typeof StorageConnectionSchema>;
|