@marimo-team/frontend 0.16.2 → 0.16.3
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/{ConnectedDataExplorerComponent-B5cPvWoQ.js → ConnectedDataExplorerComponent-Brtw1DxF.js} +1 -1
- package/dist/assets/{ImageComparisonComponent-CqR26LSv.js → ImageComparisonComponent-Dxl-PbZX.js} +1 -1
- package/dist/assets/{VegaLite-DvQDATwI.js → VegaLite-BXQF0Cx_.js} +1 -1
- package/dist/assets/_baseEach-BjSm9ht3.js +1 -0
- package/dist/assets/_baseMap-CV4Ezmtf.js +1 -0
- package/dist/assets/_baseUniq-Ci9yZGxz.js +1 -0
- package/dist/assets/{_createAggregator-ZcHkHPNJ.js → _createAggregator-VFK9K2d9.js} +1 -1
- package/dist/assets/{agent-panel-B91RoLct.js → agent-panel-BoscVLCT.js} +7 -7
- package/dist/assets/{any-language-editor-CxfHcm5h.js → any-language-editor-ChaY_VUU.js} +1 -1
- package/dist/assets/{architectureDiagram-W76B3OCA-BQsvK8uR.js → architectureDiagram-W76B3OCA-CueUUFYd.js} +1 -1
- package/dist/assets/{between-horizontal-start-BmYToIaM.js → between-horizontal-start-DAHqmLYT.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-r3HgCj4w.js → blockDiagram-QIGZ2CNN-BYYygyWn.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-BJbPNt41.js → c4Diagram-FPNF74CW-DAz3xEh1.js} +1 -1
- package/dist/assets/channel-6SqQ2U_X.js +1 -0
- package/dist/assets/chat-panel-DJkOLrw9.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-Dv4MZ9Hj.js → chunk-4BX2VUAB-8g-RyHdt.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-CM4AHquB.js → chunk-55IACEB6-iWZZ8Mt6.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-C_Zz0ENB.js → chunk-FMBD7UC4-knjss4wk.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-DYSmiXYq.js → chunk-K7UQS3LO-DVIwPBgZ.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-QM4OPuQP.js → chunk-QN33PNHL-CBU8pN6I.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-CfAsGyeB.js → chunk-QZHKN3VN-5ljElUF4.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-6j_Cpjsi.js → chunk-TVAH2DTR-DkIdGINc.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-BHslFJQE.js → chunk-TZMSLE5B-CIFOSTqh.js} +1 -1
- package/dist/assets/{circle-play-CK3UZRYQ.js → circle-play-BOdsbq5u.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-DVqXcTYf.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-DVqXcTYf.js +1 -0
- package/dist/assets/{clear-button-C4fDVSv8.js → clear-button-GAjXl0CQ.js} +1 -1
- package/dist/assets/clone-DSDb0xen.js +1 -0
- package/dist/assets/command-palette-BUXkqoLh.js +1 -0
- package/dist/assets/{common-D-lbuUwz.js → common-DahoYqdi.js} +1 -1
- package/dist/assets/{compile-DVQe1Mzk.js → compile-Bg8uJ7vm.js} +1 -1
- package/dist/assets/{cose-bilkent-S5V4N54A-D-IS7WC8.js → cose-bilkent-S5V4N54A-z_0gqD9K.js} +1 -1
- package/dist/assets/{dagre-5GWH7T2D-lYu-tEWT.js → dagre-5GWH7T2D-BMt7CNXL.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-C5peOCit.js → data-grid-overlay-editor-Ctn4XtXx.js} +1 -1
- package/dist/assets/{datasources-panel-D3NA20uZ.js → datasources-panel-C7sqRIHs.js} +1 -1
- package/dist/assets/{dependency-graph-panel-BGVYOfkV.js → dependency-graph-panel-DNajptzv.js} +4 -4
- package/dist/assets/{diagram-N5W7TBWH-BnvIuYUp.js → diagram-N5W7TBWH-BzwvLvAy.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-DemedRK3.js → diagram-QEK2KX5R-DRLJ56FS.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-iiY7AuyH.js → diagram-S2PKOQOG-Bf8x4KTU.js} +1 -1
- package/dist/assets/{documentation-panel-C3dSwOSQ.js → documentation-panel-Dm6Ozl67.js} +1 -1
- package/dist/assets/edit-page-CGc9EjuG.js +140 -0
- package/dist/assets/{ellipsis-vertical-CazJl8M7.js → ellipsis-vertical-Bj1YXvZe.js} +1 -1
- package/dist/assets/{empty-state-DW308mFO.js → empty-state-CYev-D31.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-6wQ8Ugg0.js → erDiagram-AWTI2OKA-DmgzgN_I.js} +1 -1
- package/dist/assets/{error-panel-D1VnJ1yP.js → error-panel-BYG4twCa.js} +1 -1
- package/dist/assets/{file-explorer-panel-0oVd4t-D.js → file-explorer-panel-BSMiOApi.js} +1 -1
- package/dist/assets/{flowDiagram-PVAE7QVJ-C55IUWjm.js → flowDiagram-PVAE7QVJ-BdRKkajr.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-DmqCM6ME.js → ganttDiagram-OWAHRB6G-lfRAMnq_.js} +5 -5
- package/dist/assets/{gitGraphDiagram-NY62KEGX-DBvhAeM_.js → gitGraphDiagram-NY62KEGX-CQVTIrHF.js} +1 -1
- package/dist/assets/{glide-data-editor-CHNuHidQ.js → glide-data-editor-D5A4pou7.js} +11 -11
- package/dist/assets/{graph-CG6BgUWQ.js → graph-CBNo279v.js} +1 -1
- package/dist/assets/{home-page-dgivXuSR.js → home-page-CmdznBJR.js} +3 -3
- package/dist/assets/{index-BTGpssVX.js → index-0dfGh-Gj.js} +1 -1
- package/dist/assets/{index-C7dtgr9A.js → index-BDYVSSzB.js} +1 -1
- package/dist/assets/{index-C02SqeRj.js → index-B_KyDZ94.js} +1 -1
- package/dist/assets/{index-mkubqy9-.js → index-Bfy-I_lW.js} +1 -1
- package/dist/assets/{index-BelfnXwL.js → index-Bh98Tp-z.js} +1 -1
- package/dist/assets/{index-CAQvMTzM.js → index-BhroIwBL.js} +1 -1
- package/dist/assets/{index-BneyUujp.js → index-BtQtesaI.js} +1 -1
- package/dist/assets/index-C0iXCvyY.css +1 -0
- package/dist/assets/index-C1SHFMCp.js +581 -0
- package/dist/assets/{index-Csd6QrCV.js → index-C6DWtSls.js} +1 -1
- package/dist/assets/{index-BYVZlBF8.js → index-C71cdkH-.js} +1 -1
- package/dist/assets/{index-z4krxQ4j.js → index-CT_FTqvK.js} +1 -1
- package/dist/assets/{index-Db36XTG_.js → index-CU5rRr66.js} +1 -1
- package/dist/assets/{index-CtPksxf0.js → index-Cb6duXQm.js} +1 -1
- package/dist/assets/{index-DAZ-9ri2.js → index-D23e9zQj.js} +1 -1
- package/dist/assets/index-DUGecC2Z.js +68 -0
- package/dist/assets/{index-M_pBKDSe.js → index-DcGIOAQi.js} +1 -1
- package/dist/assets/{index-DONRrmA2.js → index-PJfa9qXY.js} +1 -1
- package/dist/assets/{index-sbO9UaUU.js → index-SPslPC2B.js} +1 -1
- package/dist/assets/{index-DdIhdEVw.js → index-VPQlo4Uz.js} +1 -1
- package/dist/assets/{index-_luCZMLM.js → index-qbTLKWyG.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-DBu8p9gd.js +2 -0
- package/dist/assets/{isEmpty-CqX_YTIf.js → isEmpty-CnOLuQIv.js} +1 -1
- package/dist/assets/{journeyDiagram-BIP6EPQ6-Y5w_Tqe_.js → journeyDiagram-BIP6EPQ6-6U_vHJBH.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-DbXs5Rxi.js → kanban-definition-6OIFK2YF-DgnR14ys.js} +1 -1
- package/dist/assets/{layout-BCNPDACj.js → layout-RHmq4fP9.js} +1 -1
- package/dist/assets/{linear-uO6UVhXt.js → linear-CLdOVPGV.js} +1 -1
- package/dist/assets/links-Dd1icsEk.js +7 -0
- package/dist/assets/{logs-panel-BEQ1eRUp.js → logs-panel-CjbuhBLx.js} +1 -1
- package/dist/assets/{markdown-renderer-Dmzbb00W.js → markdown-renderer-X5YJvAZq.js} +3 -3
- package/dist/assets/{mermaid-qRc4MXIj.js → mermaid-Bl2T5oEC.js} +1 -1
- package/dist/assets/{mermaid.core-CvvJtCRj.js → mermaid.core-CfukBvGI.js} +4 -4
- package/dist/assets/min-BXIes1Za.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-G5NognM-.js → mindmap-definition-Q6HEUPPD-BXCjP4Lu.js} +1 -1
- package/dist/assets/{number-overlay-editor-DPr5sHFu.js → number-overlay-editor-BUyqkSes.js} +1 -1
- package/dist/assets/{outline-panel-gxQXvVi4.js → outline-panel-BvGcPKdd.js} +1 -1
- package/dist/assets/{packages-panel-B1T0VPlg.js → packages-panel-BichDQWG.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-DK9SHkfc.js → pieDiagram-ADFJNKIX-CMzJFIJM.js} +1 -1
- package/dist/assets/{quadrantDiagram-LMRXKWRM-D1DdWF8C.js → quadrantDiagram-LMRXKWRM-CfGssUlO.js} +1 -1
- package/dist/assets/{react-plotly-CTwajqCb.js → react-plotly-DR3hV0HW.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-DnjDAypr.js → requirementDiagram-4UW4RH46-CfrFolth.js} +1 -1
- package/dist/assets/{run-page-CQY9im22.js → run-page-Bqd_4ePD.js} +1 -1
- package/dist/assets/{sankeyDiagram-GR3RE2ED-B67Va-ER.js → sankeyDiagram-GR3RE2ED-D_UttKU0.js} +1 -1
- package/dist/assets/scratchpad-panel-D5N15ji1.js +1 -0
- package/dist/assets/secrets-panel-BpbnAO4R.js +1 -0
- package/dist/assets/{sequenceDiagram-C3RYC4MD-DiWgZPtN.js → sequenceDiagram-C3RYC4MD-MdfQQApP.js} +1 -1
- package/dist/assets/{slides-component-DhpPRtQp.js → slides-component-C0z7rXmk.js} +1 -1
- package/dist/assets/{snippets-panel-CLkBXhJ2.js → snippets-panel-wlpZ_Wzx.js} +1 -1
- package/dist/assets/{sortBy-D4OG7w4O.js → sortBy-BW_zNHP6.js} +1 -1
- package/dist/assets/{state-Dz_3JyED.js → state-CDooX-dk.js} +1 -1
- package/dist/assets/{stateDiagram-KXAO66HF-ByF2AULw.js → stateDiagram-KXAO66HF-H7kfw3ot.js} +1 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-YMeb9qMR.js +1 -0
- package/dist/assets/{storage-Dr0CC44z.js → storage-b1QCapTq.js} +6 -6
- package/dist/assets/{terminal-BtdissBf.js → terminal-CPV44BXz.js} +1 -1
- package/dist/assets/{time-DKdOTnQg.js → time-DDy3xv5Y.js} +1 -1
- package/dist/assets/{timeline-definition-XQNQX7LJ-DzER9bf6.js → timeline-definition-XQNQX7LJ-J-cPRT2_.js} +1 -1
- package/dist/assets/{tracing-Dpx5M-u3.js → tracing-3eHHRUiJ.js} +2 -2
- package/dist/assets/{tracing-panel-hCjBkSER.js → tracing-panel-BMgy3D7d.js} +2 -2
- package/dist/assets/{trash-C6Ko-g5q.js → trash--tonOuDe.js} +1 -1
- package/dist/assets/{tree-BHN2gcCF.js → tree-ouIGEsVg.js} +6 -6
- package/dist/assets/{treemap-75Q7IDZK-DR79Mhzt.js → treemap-75Q7IDZK-CzJTJ_3R.js} +20 -20
- package/dist/assets/{variable-panel-PFBCFz36.js → variable-panel-sFTn4Oih.js} +1 -1
- package/dist/assets/{vega-component-Db6-uY4C.js → vega-component-BkPkzX9r.js} +1 -1
- package/dist/assets/{xychartDiagram-6GGTOJPD-DWzBP3tZ.js → xychartDiagram-6GGTOJPD-BZ8WOb_8.js} +1 -1
- package/dist/index.html +10 -3
- package/package.json +6 -6
- package/src/__mocks__/common.ts +5 -3
- package/src/__mocks__/notebook.ts +2 -2
- package/src/__tests__/main.test.tsx +2 -2
- package/src/components/ai/ai-provider-icon.tsx +2 -0
- package/src/components/app-config/ai-config.tsx +32 -1
- package/src/components/app-config/common.tsx +2 -2
- package/src/components/app-config/user-config-form.tsx +26 -0
- package/src/components/audio/audio-recorder.tsx +0 -1
- package/src/components/chat/acp/blocks.tsx +2 -2
- package/src/components/chat/acp/thread.tsx +3 -5
- package/src/components/chat/acp/utils.ts +5 -5
- package/src/components/chat/chat-panel.tsx +1 -1
- package/src/components/data-table/__tests__/data-table.test.tsx +2 -2
- package/src/components/data-table/charts/__tests__/altair-generator.test.ts +1 -1
- package/src/components/data-table/charts/chart-spec/tooltips.ts +3 -3
- package/src/components/data-table/charts/components/chart-items.tsx +1 -1
- package/src/components/data-table/charts/components/form-fields.tsx +2 -2
- package/src/components/data-table/charts/constants.ts +1 -1
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +2 -2
- package/src/components/data-table/columns.tsx +1 -1
- package/src/components/data-table/data-table.tsx +35 -3
- package/src/components/data-table/date-popover.tsx +1 -1
- package/src/components/data-table/download-actions.tsx +1 -1
- package/src/components/data-table/range-focus/__tests__/utils.test.ts +5 -5
- package/src/components/data-table/renderers.tsx +6 -5
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
- package/src/components/data-table/types.ts +4 -3
- package/src/components/datasources/column-preview.tsx +9 -6
- package/src/components/debugger/debugger-code.tsx +1 -1
- package/src/components/dependency-graph/custom-node.tsx +15 -6
- package/src/components/dependency-graph/dependency-graph-minimap.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph-tree.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph.tsx +1 -1
- package/src/components/dependency-graph/elements.ts +7 -7
- package/src/components/dependency-graph/utils/changes.ts +4 -4
- package/src/components/editor/Cell.tsx +6 -2
- package/src/components/editor/ai/transport/chat-transport.tsx +1 -1
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +1 -1
- package/src/components/editor/chrome/panels/packages-panel.tsx +1 -1
- package/src/components/editor/columns/storage.ts +1 -1
- package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +36 -0
- package/src/components/editor/database/__tests__/as-code.test.ts +30 -7
- package/src/components/editor/database/add-database-form.tsx +11 -0
- package/src/components/editor/database/as-code.ts +104 -5
- package/src/components/editor/database/schemas.ts +36 -18
- package/src/components/editor/errors/auto-fix.tsx +12 -2
- package/src/components/editor/errors/sql-validation-errors.tsx +12 -6
- package/src/components/editor/navigation/clipboard.ts +2 -2
- package/src/components/editor/output/ConsoleOutput.tsx +1 -1
- package/src/components/editor/output/JsonOutput.tsx +1 -1
- package/src/components/editor/output/MarimoErrorOutput.tsx +25 -25
- package/src/components/editor/output/MarimoTracebackOutput.tsx +17 -2
- package/src/components/editor/renderers/grid-layout/types.ts +2 -2
- package/src/components/editor/renderers/plugins.ts +1 -1
- package/src/components/editor/renderers/types.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -7
- package/src/components/forms/form.tsx +5 -5
- package/src/components/ui/links.tsx +1 -0
- package/src/core/ai/__tests__/model-registry.test.ts +0 -10
- package/src/core/ai/context/providers/error.ts +2 -2
- package/src/core/ai/ids/ids.ts +1 -0
- package/src/core/ai/model-registry.ts +2 -1
- package/src/core/cells/cells.ts +5 -5
- package/src/core/cells/logs.ts +1 -1
- package/src/core/cells/types.ts +1 -1
- package/src/core/codemirror/__tests__/format.test.ts +6 -0
- package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
- package/src/core/codemirror/editing/commands.ts +2 -2
- package/src/core/codemirror/find-replace/navigate.ts +1 -1
- package/src/core/codemirror/language/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/language/__tests__/sql-validation.test.ts +1 -1
- package/src/core/codemirror/language/__tests__/sql.test.ts +764 -79
- package/src/core/codemirror/language/languages/markdown.ts +4 -1
- package/src/core/codemirror/language/languages/sql/{validation-errors.ts → banner-validation-errors.ts} +9 -3
- package/src/core/codemirror/language/languages/sql/completion-builder.ts +160 -0
- package/src/core/codemirror/language/languages/sql/completion-sources.tsx +9 -3
- package/src/core/codemirror/language/languages/sql/completion-store.ts +46 -50
- package/src/core/codemirror/language/languages/sql/renderers.tsx +485 -0
- package/src/core/codemirror/language/languages/sql/sql.ts +151 -24
- package/src/core/codemirror/language/languages/sql/utils.ts +4 -1
- package/src/core/codemirror/language/panel/sql.tsx +6 -1
- package/src/core/codemirror/language/utils/ast.ts +3 -3
- package/src/core/codemirror/lsp/federated-lsp.ts +4 -4
- package/src/core/codemirror/lsp/lens.ts +4 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
- package/src/core/codemirror/lsp/types.ts +1 -1
- package/src/core/codemirror/markdown/completions.ts +1 -1
- package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
- package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/feature-flag.tsx +3 -1
- package/src/core/datasets/request-registry.ts +17 -10
- package/src/core/dom/events.ts +1 -1
- package/src/core/dom/outline.ts +2 -2
- package/src/core/dom/uiregistry.ts +2 -8
- package/src/core/errors/__tests__/errors.test.ts +22 -4
- package/src/core/errors/errors.ts +29 -1
- package/src/core/errors/state.ts +1 -1
- package/src/core/islands/main.ts +2 -2
- package/src/core/islands/parse.ts +1 -3
- package/src/core/kernel/messages.ts +1 -1
- package/src/core/network/CachingRequestRegistry.ts +74 -0
- package/src/core/network/DeferredRequestRegistry.ts +3 -1
- package/src/core/network/__tests__/CachingRequestRegistry.test.ts +73 -0
- package/src/core/network/types.ts +1 -1
- package/src/core/variables/state.ts +2 -2
- package/src/core/wasm/__tests__/state.test.ts +1 -1
- package/src/core/websocket/useMarimoWebSocket.tsx +5 -2
- package/src/custom.d.ts +1 -1
- package/src/hooks/useCellRenderCount.ts +1 -0
- package/src/hooks/useResizeHandle.ts +4 -1
- package/src/plugins/core/RenderHTML.tsx +1 -2
- package/src/plugins/impl/DataTablePlugin.tsx +7 -2
- package/src/plugins/impl/FileUploadPlugin.tsx +1 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -1
- package/src/plugins/impl/SliderPlugin.tsx +4 -0
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +27 -9
- package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +58 -2
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +3 -4
- package/src/plugins/impl/anywidget/model.ts +2 -3
- package/src/plugins/impl/data-editor/types.ts +1 -1
- package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
- package/src/plugins/impl/data-frames/types.ts +1 -1
- package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +3 -3
- package/src/plugins/impl/vega/__tests__/loader.test.ts +2 -2
- package/src/plugins/impl/vega/loader.ts +1 -1
- package/src/plugins/impl/vega/vega-component.tsx +1 -1
- package/src/plugins/impl/vega/vega-loader.ts +2 -2
- package/src/plugins/layout/NavigationMenuPlugin.tsx +1 -1
- package/src/plugins/layout/RoutesPlugin.tsx +1 -2
- package/src/plugins/plugins.ts +2 -2
- package/src/utils/Logger.ts +1 -1
- package/src/utils/__tests__/data-views.test.ts +30 -68
- package/src/utils/__tests__/dom.test.ts +10 -10
- package/src/utils/__tests__/id-tree.test.ts +49 -1
- package/src/utils/__tests__/storage.test.ts +1 -1
- package/src/utils/__tests__/traceback.test.ts +13 -2
- package/src/utils/arrays.ts +1 -1
- package/src/utils/createReducer.ts +1 -5
- package/src/utils/data-views.ts +6 -19
- package/src/utils/edit-distance.ts +1 -1
- package/src/utils/fileToBase64.ts +1 -1
- package/src/utils/id-tree.tsx +20 -18
- package/src/utils/json/base64.ts +13 -0
- package/src/utils/json/json-parser.ts +2 -2
- package/src/utils/lru.ts +4 -0
- package/src/utils/mergeRefs.ts +1 -1
- package/src/utils/objects.ts +3 -3
- package/src/utils/pluralize.ts +1 -1
- package/src/utils/routes.ts +2 -2
- package/src/utils/sets.ts +1 -1
- package/src/utils/traceback.ts +45 -15
- package/src/utils/tracer.ts +11 -9
- package/dist/assets/_baseEach--KDTwKbG.js +0 -1
- package/dist/assets/_baseMap-Cu3o-eyO.js +0 -1
- package/dist/assets/_baseUniq-y7ZXnMo1.js +0 -1
- package/dist/assets/channel-DFaEx1fu.js +0 -1
- package/dist/assets/chat-panel-IoPMv8e2.js +0 -3
- package/dist/assets/classDiagram-KNZD7YFC-BsZtvV5O.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-BsZtvV5O.js +0 -1
- package/dist/assets/clone-YBEvPE-s.js +0 -1
- package/dist/assets/command-palette-D7hOfvf6.js +0 -1
- package/dist/assets/edit-page-C5TsEeSo.js +0 -129
- package/dist/assets/index-CGDMlQfO.css +0 -1
- package/dist/assets/index-CelXfcd8.js +0 -580
- package/dist/assets/index-Cxyk7pt-.js +0 -68
- package/dist/assets/infoDiagram-STP46IZ2-wTALjfPc.js +0 -2
- package/dist/assets/links-Drv7cJgN.js +0 -7
- package/dist/assets/min-DYUOb1RR.js +0 -1
- package/dist/assets/scratchpad-panel-DlDfcDtW.js +0 -1
- package/dist/assets/secrets-panel-BDGyuGZA.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-CtBJqosP.js +0 -1
- package/src/__tests__/lru.test.ts +0 -74
package/src/core/islands/main.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
|
16
16
|
import { initializePlugins } from "@/plugins/plugins";
|
|
17
17
|
import { logNever } from "@/utils/assertNever";
|
|
18
18
|
import { Functions } from "@/utils/functions";
|
|
19
|
-
import
|
|
19
|
+
import { safeExtractSetUIElementMessageBuffers } from "@/utils/json/base64";
|
|
20
20
|
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
21
21
|
import { Logger } from "@/utils/Logger";
|
|
22
22
|
import {
|
|
@@ -145,7 +145,7 @@ export async function initialize() {
|
|
|
145
145
|
UI_ELEMENT_REGISTRY.broadcastMessage(
|
|
146
146
|
msg.data.ui_element as UIElementId,
|
|
147
147
|
msg.data.message,
|
|
148
|
-
msg.data
|
|
148
|
+
safeExtractSetUIElementMessageBuffers(msg.data),
|
|
149
149
|
);
|
|
150
150
|
return;
|
|
151
151
|
|
|
@@ -88,9 +88,7 @@ export function parseMarimoIslandApps(): MarimoIslandApp[] {
|
|
|
88
88
|
return [...apps.values()];
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export function createMarimoFile(app: {
|
|
92
|
-
cells: Array<{ code: string }>;
|
|
93
|
-
}): string {
|
|
91
|
+
export function createMarimoFile(app: { cells: { code: string }[] }): string {
|
|
94
92
|
const lines = [
|
|
95
93
|
"import marimo",
|
|
96
94
|
"app = marimo.App()",
|
|
@@ -24,7 +24,7 @@ export type OutputChannel = schemas["CellChannel"];
|
|
|
24
24
|
export type CellOutput = schemas["CellOutput"];
|
|
25
25
|
export type MarimoError = Extract<
|
|
26
26
|
CellOutput["data"],
|
|
27
|
-
|
|
27
|
+
{ type: string }[]
|
|
28
28
|
>[number];
|
|
29
29
|
export type OutputMessage = schemas["CellOutput"];
|
|
30
30
|
export type CompletionOption = schemas["CompletionResult"]["options"][0];
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { LRUCache } from "@/utils/lru";
|
|
4
|
+
import type {
|
|
5
|
+
DeferredRequestRegistry,
|
|
6
|
+
RequestId,
|
|
7
|
+
} from "./DeferredRequestRegistry";
|
|
8
|
+
|
|
9
|
+
type ToKey<REQ> = (request: REQ) => string;
|
|
10
|
+
|
|
11
|
+
interface CachingOptions<REQ> {
|
|
12
|
+
toKey?: ToKey<REQ>;
|
|
13
|
+
maxSize?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Light wrapper adding memoization and in-flight de-duplication on top of
|
|
18
|
+
* DeferredRequestRegistry, keyed by a string representation of the request.
|
|
19
|
+
*/
|
|
20
|
+
export class CachingRequestRegistry<REQ, RES> {
|
|
21
|
+
private delegate: DeferredRequestRegistry<REQ, RES>;
|
|
22
|
+
private toKey: ToKey<REQ>;
|
|
23
|
+
private cache: LRUCache<string, Promise<RES>>;
|
|
24
|
+
|
|
25
|
+
static jsonStringifySortKeys<T>(): ToKey<T> {
|
|
26
|
+
return (o: T) => {
|
|
27
|
+
if (typeof o !== "object" || o === null) {
|
|
28
|
+
return String(o);
|
|
29
|
+
}
|
|
30
|
+
return JSON.stringify(o, Object.keys(o).sort(), 2);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
delegate: DeferredRequestRegistry<REQ, RES>,
|
|
36
|
+
options: CachingOptions<REQ> = {},
|
|
37
|
+
) {
|
|
38
|
+
this.delegate = delegate;
|
|
39
|
+
this.toKey =
|
|
40
|
+
options.toKey ?? CachingRequestRegistry.jsonStringifySortKeys();
|
|
41
|
+
const maxSize = options.maxSize ?? 128;
|
|
42
|
+
this.cache = new LRUCache<string, Promise<RES>>(maxSize);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolve via cache if present, else delegate; de-duplicates concurrent
|
|
47
|
+
* requests with the same key and stores successful results in the cache.
|
|
48
|
+
*/
|
|
49
|
+
public request(req: REQ): Promise<RES> {
|
|
50
|
+
const key = this.toKey(req);
|
|
51
|
+
|
|
52
|
+
const cached = this.cache.get(key);
|
|
53
|
+
if (cached !== undefined) {
|
|
54
|
+
return cached;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const promise = this.delegate.request(req);
|
|
58
|
+
this.cache.set(key, promise);
|
|
59
|
+
return promise.catch((err) => {
|
|
60
|
+
this.cache.delete(key);
|
|
61
|
+
throw err;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Path through to the delegate
|
|
66
|
+
public resolve(requestId: RequestId, response: RES) {
|
|
67
|
+
this.delegate.resolve(requestId, response);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Path through to the delegate
|
|
71
|
+
public reject(requestId: RequestId, error: Error) {
|
|
72
|
+
this.delegate.reject(requestId, error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -45,7 +45,9 @@ export class DeferredRequestRegistry<REQ, RES> {
|
|
|
45
45
|
async request(opts: REQ): Promise<RES> {
|
|
46
46
|
if (this.opts.resolveExistingRequests) {
|
|
47
47
|
const result = this.opts.resolveExistingRequests();
|
|
48
|
-
|
|
48
|
+
for (const deferred of this.requests.values()) {
|
|
49
|
+
deferred.resolve(result);
|
|
50
|
+
}
|
|
49
51
|
this.requests.clear();
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { CachingRequestRegistry } from "../CachingRequestRegistry";
|
|
4
|
+
import {
|
|
5
|
+
DeferredRequestRegistry,
|
|
6
|
+
type RequestId,
|
|
7
|
+
} from "../DeferredRequestRegistry";
|
|
8
|
+
|
|
9
|
+
vi.mock("@/utils/uuid", () => ({
|
|
10
|
+
generateUUID: vi.fn().mockReturnValue("uuid"),
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe("CachingRequestRegistry", () => {
|
|
14
|
+
const REQUEST_ID = "uuid" as RequestId;
|
|
15
|
+
let makeRequestMock = vi.fn();
|
|
16
|
+
let delegate: DeferredRequestRegistry<unknown, unknown>;
|
|
17
|
+
let caching: CachingRequestRegistry<unknown, unknown>;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
makeRequestMock = vi.fn().mockResolvedValue(undefined);
|
|
21
|
+
delegate = new DeferredRequestRegistry("operation", makeRequestMock);
|
|
22
|
+
caching = new CachingRequestRegistry(delegate);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should cache successful responses for identical requests", async () => {
|
|
26
|
+
const req = { a: 1 };
|
|
27
|
+
|
|
28
|
+
const p1 = caching.request(req);
|
|
29
|
+
expect(makeRequestMock).toHaveBeenCalledTimes(1);
|
|
30
|
+
expect(makeRequestMock).toHaveBeenCalledWith(REQUEST_ID, req);
|
|
31
|
+
|
|
32
|
+
// Resolve first request
|
|
33
|
+
delegate.resolve(REQUEST_ID, "response");
|
|
34
|
+
await expect(p1).resolves.toBe("response");
|
|
35
|
+
|
|
36
|
+
// Second call with equivalent request gets served from cache
|
|
37
|
+
const p2 = caching.request({ a: 1 });
|
|
38
|
+
expect(makeRequestMock).toHaveBeenCalledTimes(1);
|
|
39
|
+
await expect(p2).resolves.toBe("response");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should de-duplicate in-flight requests with the same key", async () => {
|
|
43
|
+
const req = { q: "select *" };
|
|
44
|
+
|
|
45
|
+
const p1 = caching.request(req);
|
|
46
|
+
const p2 = caching.request({ q: "select *" });
|
|
47
|
+
|
|
48
|
+
// Only one network invocation while in-flight
|
|
49
|
+
expect(makeRequestMock).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(p1).toStrictEqual(p2);
|
|
51
|
+
|
|
52
|
+
// Resolve and ensure both resolve to same result
|
|
53
|
+
delegate.resolve(REQUEST_ID, "ok");
|
|
54
|
+
await expect(p1).resolves.toBe("ok");
|
|
55
|
+
await expect(p2).resolves.toBe("ok");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should not cache errors", async () => {
|
|
59
|
+
// First call rejects
|
|
60
|
+
makeRequestMock.mockRejectedValueOnce(new Error("boom"));
|
|
61
|
+
|
|
62
|
+
await expect(caching.request({ x: 1 })).rejects.toThrow("boom");
|
|
63
|
+
expect(makeRequestMock).toHaveBeenCalledTimes(1);
|
|
64
|
+
|
|
65
|
+
// Next call should attempt again (not cached)
|
|
66
|
+
const p2 = caching.request({ x: 1 });
|
|
67
|
+
expect(makeRequestMock).toHaveBeenCalledTimes(2);
|
|
68
|
+
|
|
69
|
+
// Resolve the second request
|
|
70
|
+
delegate.resolve(REQUEST_ID, "ok");
|
|
71
|
+
await expect(p2).resolves.toBe("ok");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -142,7 +142,7 @@ export interface EditRequests {
|
|
|
142
142
|
request: PreviewDataSourceConnectionRequest,
|
|
143
143
|
) => Promise<null>;
|
|
144
144
|
validateSQL: (request: ValidateSQLRequest) => Promise<null>;
|
|
145
|
-
openFile: (request: { path: string }) => Promise<null>;
|
|
145
|
+
openFile: (request: { path: string; lineNumber?: number }) => Promise<null>;
|
|
146
146
|
getUsageStats: () => Promise<UsageResponse>;
|
|
147
147
|
// Debugger
|
|
148
148
|
sendPdb: (request: PdbRequest) => Promise<null>;
|
|
@@ -38,11 +38,11 @@ const {
|
|
|
38
38
|
},
|
|
39
39
|
setMetadata: (
|
|
40
40
|
state,
|
|
41
|
-
metadata:
|
|
41
|
+
metadata: {
|
|
42
42
|
name: VariableName;
|
|
43
43
|
value?: string | null;
|
|
44
44
|
dataType?: string | null;
|
|
45
|
-
}
|
|
45
|
+
}[],
|
|
46
46
|
) => {
|
|
47
47
|
const newVariables = { ...state };
|
|
48
48
|
for (const { name, value, dataType } of metadata) {
|
|
@@ -13,7 +13,7 @@ import { hasAnyOutputAtom } from "../state";
|
|
|
13
13
|
|
|
14
14
|
describe("hasAnyOutputAtom", () => {
|
|
15
15
|
const createNotebookState = (
|
|
16
|
-
outputs:
|
|
16
|
+
outputs: (OutputMessage | null)[],
|
|
17
17
|
): NotebookState => ({
|
|
18
18
|
...initialNotebookState(),
|
|
19
19
|
cellIds: new MultiColumn([
|
|
@@ -16,7 +16,10 @@ import {
|
|
|
16
16
|
} from "@/plugins/impl/anywidget/model";
|
|
17
17
|
import { logNever } from "@/utils/assertNever";
|
|
18
18
|
import { prettyError } from "@/utils/errors";
|
|
19
|
-
import
|
|
19
|
+
import {
|
|
20
|
+
type JsonString,
|
|
21
|
+
safeExtractSetUIElementMessageBuffers,
|
|
22
|
+
} from "@/utils/json/base64";
|
|
20
23
|
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
21
24
|
import { Logger } from "@/utils/Logger";
|
|
22
25
|
import { reloadSafe } from "@/utils/reload-safe";
|
|
@@ -112,7 +115,7 @@ export function useMarimoWebSocket(opts: {
|
|
|
112
115
|
const modelId = msg.data.model_id;
|
|
113
116
|
const uiElement = msg.data.ui_element;
|
|
114
117
|
const message = msg.data.message;
|
|
115
|
-
const buffers = (msg.data
|
|
118
|
+
const buffers = safeExtractSetUIElementMessageBuffers(msg.data);
|
|
116
119
|
|
|
117
120
|
if (modelId && isMessageWidgetState(message)) {
|
|
118
121
|
handleWidgetMessage({
|
package/src/custom.d.ts
CHANGED
|
@@ -29,7 +29,10 @@ export const useResizeHandle = ({
|
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
let width = Number.parseInt(
|
|
32
|
+
let width = Number.parseInt(
|
|
33
|
+
window.getComputedStyle(resizableDiv).width,
|
|
34
|
+
10,
|
|
35
|
+
);
|
|
33
36
|
let lastX = 0;
|
|
34
37
|
let isResizing = false;
|
|
35
38
|
let activeDirection: "left" | "right" | null = null;
|
|
@@ -89,7 +89,7 @@ const replaceSrcScripts = (domNode: DOMNode): JSX.Element | undefined => {
|
|
|
89
89
|
script.src = src;
|
|
90
90
|
document.head.append(script);
|
|
91
91
|
}
|
|
92
|
-
//
|
|
92
|
+
// biome-ignore lint/complexity/noUselessFragments: this is intentional
|
|
93
93
|
return <></>;
|
|
94
94
|
}
|
|
95
95
|
};
|
|
@@ -163,7 +163,6 @@ export const renderHTML = ({ html, additionalReplacements = [] }: Options) => {
|
|
|
163
163
|
return transformed;
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
-
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
167
166
|
return reactNode as JSX.Element;
|
|
168
167
|
},
|
|
169
168
|
});
|
|
@@ -112,7 +112,7 @@ export type CalculateTopKRows = (req: {
|
|
|
112
112
|
column: string;
|
|
113
113
|
k: number;
|
|
114
114
|
}) => Promise<{
|
|
115
|
-
data:
|
|
115
|
+
data: [unknown, number][];
|
|
116
116
|
}>;
|
|
117
117
|
|
|
118
118
|
export type PreviewColumn = (opts: { column: string }) => Promise<{
|
|
@@ -172,6 +172,7 @@ interface Data<T> {
|
|
|
172
172
|
totalRows: number | TooManyRows;
|
|
173
173
|
pagination: boolean;
|
|
174
174
|
pageSize: number;
|
|
175
|
+
maxHeight?: number;
|
|
175
176
|
selection: DataTableSelection;
|
|
176
177
|
showDownload: boolean;
|
|
177
178
|
showFilters: boolean;
|
|
@@ -220,7 +221,7 @@ type DataTableFunctions = {
|
|
|
220
221
|
preview_column?: PreviewColumn;
|
|
221
222
|
};
|
|
222
223
|
|
|
223
|
-
type S =
|
|
224
|
+
type S = (number | string | { rowId: string; columnName?: string })[];
|
|
224
225
|
|
|
225
226
|
export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
226
227
|
.withData(
|
|
@@ -259,6 +260,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
259
260
|
totalColumns: z.number(),
|
|
260
261
|
maxColumns: z.union([z.number(), z.literal("all")]).default("all"),
|
|
261
262
|
hasStableRowId: z.boolean().default(false),
|
|
263
|
+
maxHeight: z.number().optional(),
|
|
262
264
|
cellStyles: z.record(z.record(z.object({}).passthrough())).optional(),
|
|
263
265
|
hoverTemplate: z.string().optional(),
|
|
264
266
|
// Whether to load the data lazily.
|
|
@@ -653,6 +655,7 @@ export const LoadingDataTableComponent = memo(
|
|
|
653
655
|
toggleDisplayHeader={toggleDisplayHeader}
|
|
654
656
|
getRow={getRow}
|
|
655
657
|
cellId={cellId}
|
|
658
|
+
maxHeight={props.maxHeight}
|
|
656
659
|
/>
|
|
657
660
|
);
|
|
658
661
|
|
|
@@ -720,6 +723,7 @@ const DataTableComponent = ({
|
|
|
720
723
|
preview_column,
|
|
721
724
|
getRow,
|
|
722
725
|
cellId,
|
|
726
|
+
maxHeight,
|
|
723
727
|
}: DataTableProps<unknown> &
|
|
724
728
|
DataTableSearchProps & {
|
|
725
729
|
data: unknown[];
|
|
@@ -901,6 +905,7 @@ const DataTableComponent = ({
|
|
|
901
905
|
data={data}
|
|
902
906
|
columns={columns}
|
|
903
907
|
className={className}
|
|
908
|
+
maxHeight={maxHeight}
|
|
904
909
|
sorting={sorting}
|
|
905
910
|
totalRows={totalRows}
|
|
906
911
|
totalColumns={totalColumns}
|
|
@@ -147,6 +147,10 @@ const SliderComponent = ({
|
|
|
147
147
|
<NumberField
|
|
148
148
|
value={valueMap(internalValue)}
|
|
149
149
|
onChange={(nextValue) => {
|
|
150
|
+
// If nextValue is null/undefined/NaN (input cleared), set to start
|
|
151
|
+
if (nextValue == null || Number.isNaN(nextValue)) {
|
|
152
|
+
nextValue = Number(start);
|
|
153
|
+
}
|
|
150
154
|
setInternalValue(nextValue);
|
|
151
155
|
if (!debounce) {
|
|
152
156
|
setValue(nextValue);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
|
|
4
4
|
import type { AnyWidget, Experimental } from "@anywidget/types";
|
|
5
|
-
import { isEqual } from "lodash-es";
|
|
5
|
+
import { get, isEqual, set } from "lodash-es";
|
|
6
6
|
import { useEffect, useMemo, useRef } from "react";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { MarimoIncomingMessageEvent } from "@/core/dom/events";
|
|
@@ -16,7 +16,11 @@ import {
|
|
|
16
16
|
import { createPlugin } from "@/plugins/core/builder";
|
|
17
17
|
import { rpc } from "@/plugins/core/rpc";
|
|
18
18
|
import type { IPluginProps } from "@/plugins/types";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
type Base64String,
|
|
21
|
+
byteStringToBinary,
|
|
22
|
+
typedAtob,
|
|
23
|
+
} from "@/utils/json/base64";
|
|
20
24
|
import { Logger } from "@/utils/Logger";
|
|
21
25
|
import { ErrorBanner } from "../common/error-banner";
|
|
22
26
|
import { MODEL_MANAGER, Model } from "./model";
|
|
@@ -25,7 +29,7 @@ interface Data {
|
|
|
25
29
|
jsUrl: string;
|
|
26
30
|
jsHash: string;
|
|
27
31
|
css?: string | null;
|
|
28
|
-
bufferPaths?:
|
|
32
|
+
bufferPaths?: (string | number)[][] | null;
|
|
29
33
|
initialValue: T;
|
|
30
34
|
}
|
|
31
35
|
|
|
@@ -59,6 +63,11 @@ type Props = IPluginProps<T, Data, PluginFunctions>;
|
|
|
59
63
|
|
|
60
64
|
const AnyWidgetSlot = (props: Props) => {
|
|
61
65
|
const { css, jsUrl, jsHash, bufferPaths } = props.data;
|
|
66
|
+
|
|
67
|
+
const valueWithBuffers = useMemo(() => {
|
|
68
|
+
return resolveInitialValue(props.value, bufferPaths ?? []);
|
|
69
|
+
}, [props.value, bufferPaths]);
|
|
70
|
+
|
|
62
71
|
// JS is an ESM file with a render function on it
|
|
63
72
|
// export function render({ model, el }) {
|
|
64
73
|
// ...
|
|
@@ -85,10 +94,6 @@ const AnyWidgetSlot = (props: Props) => {
|
|
|
85
94
|
}
|
|
86
95
|
}, [hasError, jsUrl]);
|
|
87
96
|
|
|
88
|
-
const valueWithBuffer = useMemo(() => {
|
|
89
|
-
return updateBufferPaths(props.value, bufferPaths);
|
|
90
|
-
}, [props.value, bufferPaths]);
|
|
91
|
-
|
|
92
97
|
// Mount the CSS
|
|
93
98
|
useEffect(() => {
|
|
94
99
|
const shadowRoot = props.host.shadowRoot;
|
|
@@ -157,7 +162,7 @@ const AnyWidgetSlot = (props: Props) => {
|
|
|
157
162
|
key={key}
|
|
158
163
|
{...props}
|
|
159
164
|
widget={module.default}
|
|
160
|
-
value={
|
|
165
|
+
value={valueWithBuffers}
|
|
161
166
|
/>
|
|
162
167
|
);
|
|
163
168
|
};
|
|
@@ -174,7 +179,7 @@ async function runAnyWidgetModule(
|
|
|
174
179
|
el: HTMLElement,
|
|
175
180
|
): Promise<() => void> {
|
|
176
181
|
const experimental: Experimental = {
|
|
177
|
-
invoke: async (
|
|
182
|
+
invoke: async (_name, _msg, _options) => {
|
|
178
183
|
const message =
|
|
179
184
|
"anywidget.invoke not supported in marimo. Please file an issue at https://github.com/marimo-team/marimo/issues";
|
|
180
185
|
Logger.warn(message);
|
|
@@ -284,3 +289,16 @@ export const visibleForTesting = {
|
|
|
284
289
|
isAnyWidgetModule,
|
|
285
290
|
getDirtyFields,
|
|
286
291
|
};
|
|
292
|
+
|
|
293
|
+
export function resolveInitialValue(
|
|
294
|
+
raw: Record<string, any>,
|
|
295
|
+
bufferPaths: readonly (readonly (string | number)[])[],
|
|
296
|
+
) {
|
|
297
|
+
const out = structuredClone(raw);
|
|
298
|
+
for (const bufferPath of bufferPaths) {
|
|
299
|
+
const base64String: Base64String = get(raw, bufferPath);
|
|
300
|
+
const bytes = byteStringToBinary(typedAtob(base64String));
|
|
301
|
+
set(out, bufferPath, new DataView(bytes.buffer));
|
|
302
|
+
}
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
@@ -5,7 +5,11 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
5
5
|
import { TestUtils } from "@/__tests__/test-helpers";
|
|
6
6
|
import type { UIElementId } from "@/core/cells/ids";
|
|
7
7
|
import { MarimoIncomingMessageEvent } from "@/core/dom/events";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getDirtyFields,
|
|
10
|
+
resolveInitialValue,
|
|
11
|
+
visibleForTesting,
|
|
12
|
+
} from "../AnyWidgetPlugin";
|
|
9
13
|
import { Model } from "../model";
|
|
10
14
|
|
|
11
15
|
const { LoadedSlot } = visibleForTesting;
|
|
@@ -129,7 +133,7 @@ describe("LoadedSlot", () => {
|
|
|
129
133
|
method: "update",
|
|
130
134
|
state: { count: 10 },
|
|
131
135
|
},
|
|
132
|
-
buffers:
|
|
136
|
+
buffers: [],
|
|
133
137
|
},
|
|
134
138
|
bubbles: false,
|
|
135
139
|
composed: true,
|
|
@@ -179,3 +183,55 @@ describe("LoadedSlot", () => {
|
|
|
179
183
|
});
|
|
180
184
|
});
|
|
181
185
|
});
|
|
186
|
+
|
|
187
|
+
describe("resolveInitialValue", () => {
|
|
188
|
+
it("should convert base64 strings to DataView at specified paths", () => {
|
|
189
|
+
const result = resolveInitialValue(
|
|
190
|
+
{
|
|
191
|
+
a: 10,
|
|
192
|
+
b: "aGVsbG8=", // "hello" in base64
|
|
193
|
+
c: [1, "d29ybGQ="], // "world" in base64
|
|
194
|
+
d: {
|
|
195
|
+
foo: "bWFyaW1vCg==", // "marimo" in base64
|
|
196
|
+
baz: 20,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
[["b"], ["c", 1], ["d", "foo"]],
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
expect(result).toMatchInlineSnapshot(`
|
|
203
|
+
{
|
|
204
|
+
"a": 10,
|
|
205
|
+
"b": DataView [
|
|
206
|
+
104,
|
|
207
|
+
101,
|
|
208
|
+
108,
|
|
209
|
+
108,
|
|
210
|
+
111,
|
|
211
|
+
],
|
|
212
|
+
"c": [
|
|
213
|
+
1,
|
|
214
|
+
DataView [
|
|
215
|
+
119,
|
|
216
|
+
111,
|
|
217
|
+
114,
|
|
218
|
+
108,
|
|
219
|
+
100,
|
|
220
|
+
],
|
|
221
|
+
],
|
|
222
|
+
"d": {
|
|
223
|
+
"baz": 20,
|
|
224
|
+
"foo": DataView [
|
|
225
|
+
109,
|
|
226
|
+
97,
|
|
227
|
+
114,
|
|
228
|
+
105,
|
|
229
|
+
109,
|
|
230
|
+
111,
|
|
231
|
+
10,
|
|
232
|
+
],
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
`);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
vi,
|
|
10
10
|
} from "vitest";
|
|
11
11
|
import { TestUtils } from "@/__tests__/test-helpers";
|
|
12
|
-
import type { Base64String } from "@/utils/json/base64";
|
|
13
12
|
import {
|
|
14
13
|
type AnyWidgetMessage,
|
|
15
14
|
handleWidgetMessage,
|
|
@@ -246,7 +245,7 @@ describe("Model", () => {
|
|
|
246
245
|
content,
|
|
247
246
|
});
|
|
248
247
|
|
|
249
|
-
expect(callback).toHaveBeenCalledWith(content,
|
|
248
|
+
expect(callback).toHaveBeenCalledWith(content, []);
|
|
250
249
|
});
|
|
251
250
|
|
|
252
251
|
it("should handle custom messages with buffers", () => {
|
|
@@ -286,7 +285,7 @@ describe("ModelManager", () => {
|
|
|
286
285
|
}: {
|
|
287
286
|
modelId: string;
|
|
288
287
|
message: AnyWidgetMessage;
|
|
289
|
-
buffers:
|
|
288
|
+
buffers: readonly DataView[];
|
|
290
289
|
}) => {
|
|
291
290
|
return handleWidgetMessage({
|
|
292
291
|
modelId,
|
|
@@ -353,7 +352,7 @@ describe("ModelManager", () => {
|
|
|
353
352
|
message: { method: "custom", content: { count: 1 } },
|
|
354
353
|
buffers: [],
|
|
355
354
|
});
|
|
356
|
-
expect(callback).toHaveBeenCalledWith({ count: 1 },
|
|
355
|
+
expect(callback).toHaveBeenCalledWith({ count: 1 }, []);
|
|
357
356
|
});
|
|
358
357
|
|
|
359
358
|
it("should handle close messages", async () => {
|
|
@@ -10,7 +10,6 @@ import { assertNever } from "@/utils/assertNever";
|
|
|
10
10
|
import { Deferred } from "@/utils/Deferred";
|
|
11
11
|
import { updateBufferPaths } from "@/utils/data-views";
|
|
12
12
|
import { throwNotImplemented } from "@/utils/functions";
|
|
13
|
-
import type { Base64String } from "@/utils/json/base64";
|
|
14
13
|
import { Logger } from "@/utils/Logger";
|
|
15
14
|
|
|
16
15
|
export type EventHandler = (...args: any[]) => void;
|
|
@@ -171,7 +170,7 @@ export class Model<T extends Record<string, any>> implements AnyModel<T> {
|
|
|
171
170
|
* When receiving a message from the backend.
|
|
172
171
|
* We want to notify all listeners with `msg:custom`
|
|
173
172
|
*/
|
|
174
|
-
receiveCustomMessage(message: any, buffers
|
|
173
|
+
receiveCustomMessage(message: any, buffers: readonly DataView[] = []): void {
|
|
175
174
|
const response = AnyWidgetMessageSchema.safeParse(message);
|
|
176
175
|
if (response.success) {
|
|
177
176
|
const data = response.data;
|
|
@@ -260,7 +259,7 @@ export async function handleWidgetMessage({
|
|
|
260
259
|
}: {
|
|
261
260
|
modelId: string;
|
|
262
261
|
msg: AnyWidgetMessage;
|
|
263
|
-
buffers:
|
|
262
|
+
buffers: readonly DataView[];
|
|
264
263
|
modelManager: ModelManager;
|
|
265
264
|
}): Promise<void> {
|
|
266
265
|
if (msg.method === "echo_update") {
|
|
@@ -238,7 +238,7 @@ const FieldOptions = ({
|
|
|
238
238
|
return null;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
let options:
|
|
241
|
+
let options: [string, FieldFunction[]][] = [];
|
|
242
242
|
|
|
243
243
|
if (field.type === ExpandedType.QUANTITATIVE) {
|
|
244
244
|
options = [["", QUANTITATIVE_FUNCTIONS]];
|
|
@@ -15,7 +15,7 @@ export type NumPyType = string;
|
|
|
15
15
|
*
|
|
16
16
|
* We cannot use a js map, since maps don't preserve keys as ints (e.g. "1" and 1 are the same key)
|
|
17
17
|
*/
|
|
18
|
-
export type RawColumnDataTypes =
|
|
18
|
+
export type RawColumnDataTypes = [ColumnId, [DataType, NumPyType]][];
|
|
19
19
|
/**
|
|
20
20
|
* Map of column Id and their data types
|
|
21
21
|
* ES6 maps preserve keys as ints (e.g. "1" and 1 are different keys)
|