@marimo-team/islands 0.22.1-dev3 → 0.22.1-dev30
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/{ConnectedDataExplorerComponent-Dl1grr8z.js → ConnectedDataExplorerComponent-DTOsfq2x.js} +54 -54
- package/dist/_basePickBy-Sow3pJjS.js +41 -0
- package/dist/{_baseUniq-B4eL5sTC.js → _baseUniq-C87CckHL.js} +15 -54
- package/dist/{any-language-editor-CT_9yBde.js → any-language-editor-BHH_pQ6M.js} +21 -21
- package/dist/architecture-7HQA4BMR-BHdkAMvZ.js +6 -0
- package/dist/{architectureDiagram-VXUJARFQ-vxgYGIMP.js → architectureDiagram-VXUJARFQ-B3YQo9At.js} +15 -15
- package/dist/{arrays-Du-jRBAy.js → arrays-beUWo8RF.js} +1 -1
- package/dist/assets/__vite-browser-external-WSlCcXn_.js +1 -0
- package/dist/assets/{worker-D10K3OOz.js → worker-DUYMdbtA.js} +2 -2
- package/dist/{blockDiagram-VD42YOAC-C7x6YTH7.js → blockDiagram-VD42YOAC-CpQ3TKEN.js} +7 -7
- package/dist/{button-qsiIHncQ.js → button-DNlNlZY_.js} +82 -84
- package/dist/{c4Diagram-YG6GDRKO-Cx4oseGg.js → c4Diagram-YG6GDRKO-CZSU4uqU.js} +4 -4
- package/dist/{capabilities-26mwv03y.js → capabilities-Coe9eM9T.js} +2 -2
- package/dist/{channel-C_50jIAn.js → channel-X3JKk8gE.js} +1 -1
- package/dist/{chat-ui-CtqUthFR.js → chat-ui-eH46RYWT.js} +147 -146
- package/dist/{check-D_YwHEgY.js → check-CWUkiHmb.js} +1 -1
- package/dist/{chunk-4F5CHEZ2-Dvo_CFnR.js → chunk-4F5CHEZ2-D5mClyDv.js} +1 -1
- package/dist/{chunk-ABZYJK2D-D5YIs71w.js → chunk-ABZYJK2D-CZYCCtLy.js} +1 -1
- package/dist/{chunk-ATLVNIR6-CyOjzOcf.js → chunk-ATLVNIR6-DaOzLLgN.js} +1 -1
- package/dist/{chunk-B2363JML-BzZqINRO.js → chunk-B2363JML-Br0eA2T3.js} +1 -1
- package/dist/{chunk-B4BG7PRW-ZJeV3KdD.js → chunk-B4BG7PRW-4BjV11Br.js} +4 -4
- package/dist/{chunk-DI55MBZ5-Dx_wwX6l.js → chunk-DI55MBZ5-DITY3EyP.js} +4 -4
- package/dist/{chunk-EXTU4WIE-CgefpSXQ.js → chunk-EXTU4WIE-jUPSAk3i.js} +1 -1
- package/dist/{chunk-FRFDVMJY-Derq8UzY.js → chunk-FRFDVMJY-DnEvEFRR.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-CcIOIFpc.js → chunk-JA3XYJ7Z-BcPEfxk_.js} +2 -2
- package/dist/{chunk-JZLCHNYA-CgO0GG1p.js → chunk-JZLCHNYA-2bnLL3xL.js} +4 -4
- package/dist/{chunk-N4CR4FBY-2qzGzAxT.js → chunk-N4CR4FBY-CpZSuGSU.js} +5 -5
- package/dist/{chunk-PL6DKKU2-KoG71Zin.js → chunk-PL6DKKU2-DnId6G-x.js} +1 -1
- package/dist/{chunk-QN33PNHL-Dp1qBo28.js → chunk-QN33PNHL-B9p5ojHB.js} +1 -1
- package/dist/{chunk-QXUST7PY-BxmmeIwf.js → chunk-QXUST7PY-Ch6F5Obl.js} +5 -5
- package/dist/{chunk-S3R3BYOJ-D3Rys9ZW.js → chunk-S3R3BYOJ-B0UOFJwq.js} +3 -3
- package/dist/{chunk-SJTYNZTY-Co-DhKAG.js → chunk-SJTYNZTY-BsBZnJUj.js} +1 -1
- package/dist/{chunk-TCCFYFTB-BAhzIqBO.js → chunk-TCCFYFTB-Clbl-fTg.js} +8 -7
- package/dist/{chunk-TQ3KTPDO-DxYI735Z.js → chunk-TQ3KTPDO-CFkSQ30e.js} +1 -1
- package/dist/{chunk-TZMSLE5B-Dxumt0wv.js → chunk-TZMSLE5B-D45397J2.js} +1 -1
- package/dist/{chunk-UMXZTB3W-CuahpKin.js → chunk-UMXZTB3W-D-A834Bq.js} +1 -1
- package/dist/{classDiagram-v2-WZHVMYZB-CYoFMQKE.js → classDiagram-2ON5EDUG-C8-zE3Zv.js} +10 -10
- package/dist/{classDiagram-2ON5EDUG-DkOvXRlx.js → classDiagram-v2-WZHVMYZB-DrmbGANl.js} +10 -10
- package/dist/{clone-DDndUqI0.js → clone-DZFQCtFJ.js} +1 -1
- package/dist/{constants-D1Am36hX.js → constants-CvyfaCvs.js} +3 -3
- package/dist/{copy-CBo9JcJW.js → copy-B7781WJ3.js} +2 -2
- package/dist/{dagre-6UL2VRFP-BXBaU8PB.js → dagre-6UL2VRFP-OMItEBnY.js} +12 -12
- package/dist/{dagre-D3dlYz-r.js → dagre-QVd-lCXU.js} +13 -23
- package/dist/{data-grid-overlay-editor-nZux6_d2.js → data-grid-overlay-editor-lKF301ME.js} +1 -1
- package/dist/{diagram-PSM6KHXK-CJxjk4LG.js → diagram-PSM6KHXK-CkKbohWI.js} +16 -16
- package/dist/{diagram-QEK2KX5R-IMILPh_p.js → diagram-QEK2KX5R-DjUMpVcx.js} +14 -14
- package/dist/{diagram-S2PKOQOG-6O0g6Boj.js → diagram-S2PKOQOG-b-c0d-wZ.js} +14 -14
- package/dist/{dist-BkXs8bw0.js → dist--6TSlp8H.js} +1 -1
- package/dist/dist-7K5doRvB.js +6 -0
- package/dist/{dist-CQidOwep.js → dist-B43sbpd0.js} +3 -3
- package/dist/dist-B6I_A2-E.js +8 -0
- package/dist/dist-BEQsmaZY.js +5 -0
- package/dist/dist-BasY2RHp.js +8 -0
- package/dist/{dist-BemtTYzN.js → dist-Bfp1XXWt.js} +5 -5
- package/dist/{dist-v-1kgqZ3.js → dist-BjDuO5JW.js} +1 -1
- package/dist/dist-Bosc00dY.js +5 -0
- package/dist/{dist-DLNKBPsk.js → dist-BrxqmS9Q.js} +4 -4
- package/dist/{dist-DBYL08Lu.js → dist-BvhGByxL.js} +4 -4
- package/dist/{dist-CVqlhD3M.js → dist-C4bq5Ioy.js} +2 -2
- package/dist/{dist-DwmxBUOe.js → dist-CFKdzOIu.js} +2 -2
- package/dist/{dist-5nTQE2yt.js → dist-CIB8w0Fl.js} +2 -2
- package/dist/{dist-C-EcLtO9.js → dist-CNF0QBLR.js} +1 -1
- package/dist/dist-CQMZOn-_.js +8 -0
- package/dist/dist-CViQhWZ8.js +5 -0
- package/dist/{dist-Dg65j0em.js → dist-CcMfr7jD.js} +1 -1
- package/dist/{dist-C0XYIHKJ.js → dist-Ci0CXEFt.js} +1 -1
- package/dist/dist-Cz6rLfwY.js +5 -0
- package/dist/dist-D8eq8st3.js +6 -0
- package/dist/{dist-qoCY8giM.js → dist-DAfcmt-d.js} +2 -2
- package/dist/{dist-B6Op2ogv.js → dist-DD_cYHOl.js} +2 -2
- package/dist/{dist-BUSLKXcu.js → dist-DFK94vuS.js} +2 -2
- package/dist/{dist-DBXPlQ0D.js → dist-DGNtjMZu.js} +1 -1
- package/dist/{dist-C9qF7MRB.js → dist-DJ9F1eHs.js} +2 -2
- package/dist/{dist-Ci_jEudG.js → dist-DJKubHDd.js} +1 -1
- package/dist/{dist-CnFp2Kcl.js → dist-DLafRu9s.js} +2 -2
- package/dist/dist-DM1UDXdl.js +5 -0
- package/dist/dist-DNrtWPgS.js +5 -0
- package/dist/dist-D_UjpfOY.js +1381 -0
- package/dist/{dist-DmFS6KZW.js → dist-DbnBiLNH.js} +3 -3
- package/dist/{dist-BiZZAo22.js → dist-DlSUOIm9.js} +1 -1
- package/dist/{dist-DStU8He1.js → dist-Doy0mQDg.js} +2 -2
- package/dist/{dist-CxAX99oC.js → dist-DpkJHKB8.js} +2 -2
- package/dist/{dist-DjaZNkZ7.js → dist-LhQNUe5A.js} +3 -3
- package/dist/dist-V7q2qnpA.js +5 -0
- package/dist/{dist-BJ3fhRYu.js → dist-VqF3W_ue.js} +2 -2
- package/dist/dist-a5_hPgu2.js +8 -0
- package/dist/{dist-B9KLrfoh.js → dist-ej6AQKaS.js} +1 -1
- package/dist/{dist-Brb6VNc4.js → dist-m9tsXsFf.js} +2 -2
- package/dist/{dist-CBwMSFDu.js → dist-tGk0aZ--.js} +2 -2
- package/dist/dist-uVyZcV1-.js +5 -0
- package/dist/{erDiagram-Q2GNP2WA-sho7Cl9f.js → erDiagram-Q2GNP2WA-CDhLaOZ1.js} +10 -10
- package/dist/{error-banner-Bx9kIgrs.js → error-banner-Cjf0RU9I.js} +79 -79
- package/dist/{esm-CMg2ABu6.js → esm-4wmsH2lp.js} +6 -6
- package/dist/{esm-cqK9POGH.js → esm-CD1iby2n.js} +23 -23
- package/dist/{flowDiagram-NV44I4VS-C4nY4Fbz.js → flowDiagram-NV44I4VS-BDi4O4CL.js} +10 -10
- package/dist/{ganttDiagram-JELNMOA3-CtxNcCM2.js → ganttDiagram-JELNMOA3-BpZE6kVp.js} +3 -3
- package/dist/{gitGraph-G5XIXVHT-SL6TDof6.js → gitGraph-G5XIXVHT-B_c6xFJv.js} +3 -3
- package/dist/{gitGraphDiagram-V2S2FVAM-D9885mxd.js → gitGraphDiagram-V2S2FVAM-iQnXzbPM.js} +13 -13
- package/dist/{glide-data-editor-CkVEV-Gk.js → glide-data-editor-VgPtWvhu.js} +63 -63
- package/dist/{graphlib-CxWdvYQt.js → graphlib-BV1_gi0C.js} +4 -3
- package/dist/hasIn-DnfJcYpY.js +108 -0
- package/dist/{info-VBDWY6EO-6MXPTSmi.js → info-VBDWY6EO-BTyzxmhr.js} +3 -3
- package/dist/{infoDiagram-HS3SLOUP-Bw2FlRwF.js → infoDiagram-HS3SLOUP-OYrX6uO3.js} +13 -13
- package/dist/{input-BSde8uV4.js → input-CFY9gApZ.js} +5055 -5055
- package/dist/{isEmpty-BQtUinxJ.js → isEmpty-B7FX9wKt.js} +1 -1
- package/dist/{isSymbol-DFp8040B.js → isSymbol-DCbjQG_U.js} +1 -1
- package/dist/{journeyDiagram-XKPGCS4Q-BXlCEth8.js → journeyDiagram-XKPGCS4Q-ClPC94aN.js} +3 -3
- package/dist/{kanban-definition-3W4ZIXB7-CorxzSYm.js → kanban-definition-3W4ZIXB7-DHEAKdZt.js} +7 -7
- package/dist/{label-DTNqw9tv.js → label-DbZGAoCH.js} +538 -569
- package/dist/{loader-3c9hT4kT.js → loader-Bd1kgLn7.js} +19 -16
- package/dist/main.js +2602 -2594
- package/dist/{memoize-CuHciEBb.js → memoize-CSTI9eOX.js} +1 -1
- package/dist/{merge-CA_buyY3.js → merge-CVhG7q_o.js} +1 -1
- package/dist/{mermaid-CEKslOkI.js → mermaid-B2HDLx2g.js} +54 -54
- package/dist/{mermaid-parser.core-cq4YDee-.js → mermaid-parser.core-ntCgyx0x.js} +8 -8
- package/dist/min-Ds3gG0Ff.js +96 -0
- package/dist/{mindmap-definition-VGOIOE7T-DRsT8UaN.js → mindmap-definition-VGOIOE7T-CxEUZZvY.js} +9 -9
- package/dist/{now-CXAdKY5k.js → now-nrrrOr01.js} +1 -1
- package/dist/{once-CZno0h-b.js → once-C_TIu-kR.js} +1 -1
- package/dist/{packet-DYOGHKS2-Dw08gMaZ.js → packet-DYOGHKS2-BhvnpoGi.js} +3 -3
- package/dist/{pie-VRWISCQL-C5SPSvT8.js → pie-VRWISCQL-dILuA3iG.js} +3 -3
- package/dist/{pieDiagram-ADFJNKIX-DhJ1Cx2O.js → pieDiagram-ADFJNKIX-U3LrUqAS.js} +14 -14
- package/dist/{process-output-KyzWazB-.js → process-output-BbUNe4iH.js} +3181 -3204
- package/dist/{quadrantDiagram-AYHSOK5B-DXUFIWlz.js → quadrantDiagram-AYHSOK5B-BVWuq-3R.js} +2 -2
- package/dist/{radar-ZZBFDIW7-BvY0bgSg.js → radar-ZZBFDIW7-DwFrOJDj.js} +3 -3
- package/dist/range-fJeId9Ri.js +30 -0
- package/dist/{requirementDiagram-UZGBJVZJ-DO_gtQIb.js → requirementDiagram-UZGBJVZJ-D0zpQnKC.js} +9 -9
- package/dist/{sankeyDiagram-TZEHDZUN-OZzXEkuG.js → sankeyDiagram-TZEHDZUN-CExy1joT.js} +2 -2
- package/dist/{sequenceDiagram-WL72ISMW-K7nZRifV.js → sequenceDiagram-WL72ISMW-D1BJxLjH.js} +4 -4
- package/dist/{slides-component-CIcSvFh7.js → slides-component-CX2JC-Ws.js} +2 -2
- package/dist/{spec-DYaR1rJh.js → spec-CiHus5Bb.js} +3 -3
- package/dist/{stateDiagram-FKZM4ZOC-DzXJZAq7.js → stateDiagram-FKZM4ZOC-B1S8jGMn.js} +12 -12
- package/dist/{stateDiagram-v2-4FDKWEC3-BZBPUmyF.js → stateDiagram-v2-4FDKWEC3-BH5ozUbc.js} +10 -10
- package/dist/stex-CQDv3aS8.js +4 -0
- package/dist/style.css +1 -1
- package/dist/{timeline-definition-IT6M3QCI-DNoLAh-i.js → timeline-definition-IT6M3QCI-BDT9JAmn.js} +2 -2
- package/dist/{toDate-D6VXexnV.js → toDate-BzYZtEK7.js} +4 -4
- package/dist/{toNumber-xFPoy1OI.js → toNumber-55tjPCWr.js} +2 -2
- package/dist/tooltip-BXEpXV3R.js +404 -0
- package/dist/{treemap-GDKQZRPO-C5OoxpmV.js → treemap-GDKQZRPO-bx2ngsgN.js} +3 -3
- package/dist/{types-CQ-RbYxp.js → types-D_ntCXg0.js} +3 -3
- package/dist/{useAsyncData-Cd4Urlww.js → useAsyncData-rN1nzPaS.js} +2 -2
- package/dist/{useDeepCompareMemoize-X7clcrcQ.js → useDeepCompareMemoize-iM1YNTEF.js} +4 -4
- package/dist/{useIframeCapabilities-BVQrlRBd.js → useIframeCapabilities-CqhrVue6.js} +1 -1
- package/dist/{useLifecycle-Dids8BPm.js → useLifecycle-DgDTfOLZ.js} +9 -9
- package/dist/{useTheme-Dm1WaAGy.js → useTheme-MWfxn4oz.js} +4 -5
- package/dist/{vega-component-A6unyUJS.js → vega-component-CkpTXaRx.js} +23 -23
- package/dist/{xychartDiagram-PRI3JC2R-ehVeySMW.js → xychartDiagram-PRI3JC2R-CuAZiqHS.js} +5 -5
- package/dist/{Combination-B--d1_LV.js → zod-C6UGQ3fz.js} +8085 -8151
- package/package.json +8 -41
- package/src/__tests__/branded.ts +6 -0
- package/src/__tests__/main.test.tsx +12 -14
- package/src/components/ai/ai-provider-icon.tsx +3 -2
- package/src/components/app-config/user-config-form.tsx +0 -27
- package/src/components/chat/acp/agent-docs.tsx +3 -3
- package/src/components/chat/acp/agent-panel.tsx +69 -22
- package/src/components/chat/acp/agent-selector.tsx +2 -11
- package/src/components/chat/acp/state.ts +14 -2
- package/src/components/chat/chat-panel.tsx +2 -1
- package/src/components/data-table/TableBottomBar.tsx +12 -1
- package/src/components/data-table/TableTopBar.tsx +31 -35
- package/src/components/data-table/cell-selection/types.ts +3 -2
- package/src/components/data-table/charts/charts.tsx +42 -13
- package/src/components/data-table/charts/components/chart-items.tsx +1 -1
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-formatting/types.ts +3 -2
- package/src/components/data-table/column-header.tsx +4 -2
- package/src/components/data-table/column-wrapping/types.ts +3 -2
- package/src/components/data-table/columns.tsx +4 -1
- package/src/components/data-table/copy-column/types.ts +3 -2
- package/src/components/data-table/data-table.tsx +6 -1
- package/src/components/data-table/focus-row/types.ts +3 -2
- package/src/components/data-table/loading-table.tsx +4 -1
- package/src/components/data-table/range-focus/__tests__/atoms.test.ts +11 -11
- package/src/components/data-table/range-focus/__tests__/use-cell-range-selection.test.ts +9 -11
- package/src/components/data-table/range-focus/cell-selection-stats.tsx +3 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
- package/src/components/data-table/table-explorer-panel/table-explorer-panel.tsx +2 -2
- package/src/components/editor/__tests__/data-attributes.test.tsx +93 -94
- package/src/components/editor/actions/name-cell-input.tsx +4 -2
- package/src/components/editor/actions/useCellActionButton.tsx +4 -2
- package/src/components/editor/ai/add-cell-with-ai.tsx +2 -1
- package/src/components/editor/cell/CellStatus.tsx +4 -5
- package/src/components/editor/cell/cell-context-menu.tsx +4 -2
- package/src/components/editor/cell/code/cell-editor.tsx +2 -1
- package/src/components/editor/cell/toolbar.tsx +2 -1
- package/src/components/editor/chrome/components/contribute-snippet-button.tsx +4 -1
- package/src/components/editor/chrome/components/feedback-button.tsx +4 -1
- package/src/components/editor/chrome/panels/context-aware-panel/context-aware-panel.tsx +1 -1
- package/src/components/editor/chrome/panels/file-explorer-panel.tsx +0 -10
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +4 -1
- package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +2 -1
- package/src/components/editor/header/filename-input.tsx +4 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +11 -12
- package/src/components/storage/__tests__/storage-snippets.test.ts +4 -6
- package/src/components/tracing/tracing.test.tsx +30 -30
- package/src/components/ui/accordion.tsx +1 -1
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/badge.tsx +2 -1
- package/src/components/ui/button.tsx +4 -3
- package/src/components/ui/calendar.tsx +3 -2
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/combobox.tsx +2 -1
- package/src/components/ui/command.tsx +4 -1
- package/src/components/ui/context-menu.tsx +1 -1
- package/src/components/ui/date-input.tsx +7 -6
- package/src/components/ui/date-picker.tsx +6 -4
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +1 -1
- package/src/components/ui/dropdown-menu.tsx +2 -1
- package/src/components/ui/field.tsx +1 -2
- package/src/components/ui/form.tsx +4 -5
- package/src/components/ui/fullscreen.tsx +4 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/navigation.tsx +1 -1
- package/src/components/ui/popover.tsx +1 -1
- package/src/components/ui/progress.tsx +4 -3
- package/src/components/ui/query-param-preserving-link.tsx +4 -2
- package/src/components/ui/radio-group.tsx +1 -1
- package/src/components/ui/range-slider.tsx +1 -1
- package/src/components/ui/scroll-area.tsx +1 -1
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/sheet.tsx +3 -2
- package/src/components/ui/slider.tsx +1 -1
- package/src/components/ui/switch.tsx +1 -1
- package/src/components/ui/tabs.tsx +1 -1
- package/src/components/ui/textarea.tsx +1 -2
- package/src/components/ui/toast.tsx +1 -1
- package/src/components/ui/toggle.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/core/ai/context/providers/cell-output.ts +1 -2
- package/src/core/ai/tools/edit-notebook-tool.ts +4 -3
- package/src/core/ai/tools/run-cells-tool.ts +4 -3
- package/src/core/cells/__tests__/add-missing-import.test.ts +23 -22
- package/src/core/cells/__tests__/apply-transaction.test.ts +12 -11
- package/src/core/cells/__tests__/cell.test.ts +14 -13
- package/src/core/cells/document-changes.ts +9 -9
- package/src/core/cells/logs.ts +1 -1
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -17
- package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -2
- package/src/core/codemirror/copilot/client.ts +9 -2
- package/src/core/codemirror/copilot/language-server.ts +11 -0
- package/src/core/codemirror/copilot/transport.ts +33 -8
- package/src/core/codemirror/language/languages/markdown.ts +1 -3
- package/src/core/codemirror/language/languages/python.ts +4 -0
- package/src/core/codemirror/language/languages/sql/completion-sources.tsx +4 -6
- package/src/core/codemirror/language/languages/sql/sql.ts +1 -3
- package/src/core/codemirror/language/panel/sql.tsx +4 -1
- package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +28 -42
- package/src/core/config/__tests__/config-schema.test.ts +2 -6
- package/src/core/config/config-schema.ts +0 -1
- package/src/core/config/feature-flag.tsx +0 -2
- package/src/core/datasets/data-source-connections.ts +4 -2
- package/src/core/dom/__tests__/htmlUtils.test.ts +8 -14
- package/src/core/dom/__tests__/outline.test.ts +2 -3
- package/src/core/edit-app.tsx +4 -1
- package/src/core/islands/__tests__/bridge.test.ts +20 -10
- package/src/core/islands/__tests__/parse.test.ts +8 -7
- package/src/core/network/__tests__/requests-lazy.test.ts +30 -14
- package/src/core/saving/__tests__/filename.test.ts +7 -6
- package/src/core/static/__tests__/download-html.test.ts +16 -15
- package/src/core/static/__tests__/files.test.ts +30 -28
- package/src/core/websocket/useMarimoKernelConnection.tsx +5 -11
- package/src/core/websocket/useWebSocket.tsx +3 -1
- package/src/css/app/Cell.css +25 -1
- package/src/css/globals.css +40 -14
- package/src/css/table.css +17 -0
- package/src/plugins/core/BadPlugin.tsx +7 -6
- package/src/plugins/impl/CheckboxPlugin.tsx +4 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +8 -3
- package/src/plugins/impl/DataTablePlugin.tsx +5 -1
- package/src/plugins/impl/FormPlugin.tsx +1 -2
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +4 -1
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +43 -15
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +2 -11
- package/src/plugins/impl/chat/chat-ui.tsx +4 -1
- package/src/plugins/impl/data-frames/forms/__tests__/form.test.tsx +7 -9
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +12 -68
- package/src/plugins/impl/plotly/__tests__/selection.test.ts +237 -0
- package/src/plugins/impl/plotly/selection.ts +118 -0
- package/src/plugins/impl/vega/__tests__/make-selectable.test.ts +13 -14
- package/src/plugins/impl/vega/__tests__/utils.test.ts +68 -0
- package/src/plugins/impl/vega/utils.ts +14 -5
- package/src/plugins/impl/vega/vega.css +2 -1
- package/src/plugins/layout/ImageComparisonPlugin.tsx +1 -3
- package/src/plugins/stateless-plugin.ts +4 -2
- package/src/utils/__tests__/cell-urls.test.ts +24 -21
- package/src/utils/__tests__/filenames.test.ts +15 -14
- package/src/utils/__tests__/json-parser.test.ts +14 -21
- package/src/utils/__tests__/path.test.ts +34 -31
- package/src/utils/__tests__/urls.test.ts +19 -18
- package/src/utils/json/base64.ts +2 -5
- package/src/utils/time.ts +4 -2
- package/src/utils/tracer.ts +1 -0
- package/src/utils/typed.ts +2 -2
- package/dist/_basePickBy-QjOmBDRE.js +0 -110
- package/dist/_baseSet-xgn1IbGV.js +0 -27
- package/dist/architecture-7HQA4BMR-BRyVh_Za.js +0 -6
- package/dist/assets/__vite-browser-external-Us1ds95c.js +0 -1
- package/dist/dist-B0R_ZM4-.js +0 -6
- package/dist/dist-B4a9_9pj.js +0 -5
- package/dist/dist-BCSUKEwO.js +0 -5
- package/dist/dist-BONIDQq6.js +0 -5
- package/dist/dist-BYeRx2hb.js +0 -5
- package/dist/dist-D2Rk1j4R.js +0 -1381
- package/dist/dist-DZjX5TYv.js +0 -5
- package/dist/dist-Dkw9x6kc.js +0 -5
- package/dist/dist-Ds6UaXGR.js +0 -6
- package/dist/dist-KuEJ1Q53.js +0 -8
- package/dist/dist-S72WNyTZ.js +0 -5
- package/dist/dist-bTG-yssT.js +0 -5
- package/dist/dist-diF0sguc.js +0 -8
- package/dist/dist-mJ84BIgu.js +0 -8
- package/dist/dist-wSIhFWQz.js +0 -8
- package/dist/get-CqrzlV1v.js +0 -68
- package/dist/range-CYz5jI--.js +0 -17
- package/dist/stex-CZyTRGVB.js +0 -4
- package/dist/tooltip-DGHTbHl5.js +0 -404
- /package/dist/{dist-KZI_BHqV.js → dist-CxZvoNao.js} +0 -0
- /package/dist/{invariant-D4hPsZFI.js → invariant-e8eBgdux.js} +0 -0
- /package/dist/{isArrayLikeObject-C-hFPChh.js → isArrayLikeObject-LXbTYiBa.js} +0 -0
- /package/dist/{main-CvkAPtaq.js → main-XimWhSi_.js} +0 -0
- /package/dist/{purify.es-ukiMXY-F.js → purify.es-hTCfRGdl.js} +0 -0
- /package/dist/{react-dom-BKwCWYPW.js → react-dom-BSUuJjCR.js} +0 -0
- /package/dist/{stex-Ze8D4R_5.js → stex-D887Ylhf.js} +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type * as Plotly from "plotly.js";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
extractClickSelection,
|
|
7
|
+
extractIndices,
|
|
8
|
+
extractPoints,
|
|
9
|
+
} from "../selection";
|
|
10
|
+
|
|
11
|
+
interface PlotlyPointInput {
|
|
12
|
+
data: {
|
|
13
|
+
type: string;
|
|
14
|
+
hovertemplate?: string | string[];
|
|
15
|
+
};
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function makePoint(point: PlotlyPointInput): Plotly.PlotDatum {
|
|
20
|
+
return point as unknown as Plotly.PlotDatum;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function makeClickEvent(
|
|
24
|
+
points: Plotly.PlotDatum[],
|
|
25
|
+
): Readonly<Plotly.PlotMouseEvent> {
|
|
26
|
+
return { points } as unknown as Readonly<Plotly.PlotMouseEvent>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe("extractIndices", () => {
|
|
30
|
+
it("prefers pointIndex and falls back to pointNumber", () => {
|
|
31
|
+
const points = [
|
|
32
|
+
makePoint({
|
|
33
|
+
pointIndex: 2,
|
|
34
|
+
pointNumber: 99,
|
|
35
|
+
data: { type: "scatter" },
|
|
36
|
+
}),
|
|
37
|
+
makePoint({
|
|
38
|
+
pointNumber: 4,
|
|
39
|
+
data: { type: "scattergl" },
|
|
40
|
+
}),
|
|
41
|
+
makePoint({
|
|
42
|
+
data: { type: "heatmap" },
|
|
43
|
+
}),
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
expect(extractIndices(points)).toEqual([2, 4]);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("extractPoints", () => {
|
|
51
|
+
it("extracts parsed scatter payload fields from the hovertemplate", () => {
|
|
52
|
+
const points = [
|
|
53
|
+
makePoint({
|
|
54
|
+
x: 3,
|
|
55
|
+
y: 7,
|
|
56
|
+
curveNumber: 0,
|
|
57
|
+
pointIndex: 1,
|
|
58
|
+
customdata: ["B"],
|
|
59
|
+
data: {
|
|
60
|
+
type: "scatter",
|
|
61
|
+
hovertemplate:
|
|
62
|
+
"label=%{customdata[0]}<br>x=%{x}<br>y=%{y}<extra></extra>",
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
expect(extractPoints(points)).toEqual([
|
|
68
|
+
{
|
|
69
|
+
x: 3,
|
|
70
|
+
y: 7,
|
|
71
|
+
curveNumber: 0,
|
|
72
|
+
pointIndex: 1,
|
|
73
|
+
label: "B",
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("keeps standard heatmap keys without hovertemplate parsing", () => {
|
|
79
|
+
const points = [
|
|
80
|
+
makePoint({
|
|
81
|
+
x: "B",
|
|
82
|
+
y: "Row 2",
|
|
83
|
+
z: 6,
|
|
84
|
+
curveNumber: 0,
|
|
85
|
+
pointIndex: 5,
|
|
86
|
+
data: { type: "heatmap", hovertemplate: "ignored=%{z}" },
|
|
87
|
+
}),
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
expect(extractPoints(points)).toEqual([
|
|
91
|
+
{
|
|
92
|
+
x: "B",
|
|
93
|
+
y: "Row 2",
|
|
94
|
+
z: 6,
|
|
95
|
+
curveNumber: 0,
|
|
96
|
+
pointIndex: 5,
|
|
97
|
+
},
|
|
98
|
+
]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("extractClickSelection", () => {
|
|
103
|
+
it("returns undefined for unsupported trace types", () => {
|
|
104
|
+
const event = makeClickEvent([
|
|
105
|
+
makePoint({
|
|
106
|
+
x: "A",
|
|
107
|
+
y: 10,
|
|
108
|
+
pointIndex: 0,
|
|
109
|
+
data: { type: "bar" },
|
|
110
|
+
}),
|
|
111
|
+
]);
|
|
112
|
+
|
|
113
|
+
expect(extractClickSelection(event)).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("returns undefined when all points are non-click-selectable trace types", () => {
|
|
117
|
+
// scatter and scattergl use onSelected (box/lasso) for selection, not onClick.
|
|
118
|
+
// Clicks on these traces fire both plotly_click and plotly_selected; the
|
|
119
|
+
// latter provides a range and must be the authoritative source.
|
|
120
|
+
const event = makeClickEvent([
|
|
121
|
+
makePoint({
|
|
122
|
+
x: "ignore",
|
|
123
|
+
y: 1,
|
|
124
|
+
pointIndex: 0,
|
|
125
|
+
data: { type: "bar" },
|
|
126
|
+
}),
|
|
127
|
+
makePoint({
|
|
128
|
+
x: 2,
|
|
129
|
+
y: 5,
|
|
130
|
+
curveNumber: 1,
|
|
131
|
+
pointIndex: 3,
|
|
132
|
+
data: { type: "scatter" },
|
|
133
|
+
}),
|
|
134
|
+
makePoint({
|
|
135
|
+
x: 4,
|
|
136
|
+
y: 12,
|
|
137
|
+
curveNumber: 2,
|
|
138
|
+
pointNumber: 5,
|
|
139
|
+
data: { type: "scattergl" },
|
|
140
|
+
}),
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
expect(extractClickSelection(event)).toBeUndefined();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("filters unsupported points and preserves supported click payloads", () => {
|
|
147
|
+
// bar is unsupported; histogram is supported and its pointNumbers must be
|
|
148
|
+
// forwarded so the backend can recover the exact sample rows.
|
|
149
|
+
const event = makeClickEvent([
|
|
150
|
+
makePoint({
|
|
151
|
+
x: "ignore",
|
|
152
|
+
y: 1,
|
|
153
|
+
pointIndex: 0,
|
|
154
|
+
data: { type: "bar" },
|
|
155
|
+
}),
|
|
156
|
+
makePoint({
|
|
157
|
+
x: 8,
|
|
158
|
+
y: 3,
|
|
159
|
+
curveNumber: 1,
|
|
160
|
+
pointNumber: 2,
|
|
161
|
+
pointNumbers: [4, 5, 6],
|
|
162
|
+
data: { type: "histogram" },
|
|
163
|
+
}),
|
|
164
|
+
]);
|
|
165
|
+
|
|
166
|
+
expect(extractClickSelection(event)).toEqual({
|
|
167
|
+
selections: [],
|
|
168
|
+
range: undefined,
|
|
169
|
+
indices: [2],
|
|
170
|
+
points: [
|
|
171
|
+
{
|
|
172
|
+
x: 8,
|
|
173
|
+
y: 3,
|
|
174
|
+
curveNumber: 1,
|
|
175
|
+
pointNumber: 2,
|
|
176
|
+
pointNumbers: [4, 5, 6],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("preserves histogram pointNumbers for backend row extraction", () => {
|
|
183
|
+
const event = makeClickEvent([
|
|
184
|
+
makePoint({
|
|
185
|
+
x: 8,
|
|
186
|
+
y: 2,
|
|
187
|
+
curveNumber: 0,
|
|
188
|
+
pointNumber: 3,
|
|
189
|
+
pointNumbers: [6, 7],
|
|
190
|
+
data: { type: "histogram" },
|
|
191
|
+
}),
|
|
192
|
+
]);
|
|
193
|
+
|
|
194
|
+
expect(extractClickSelection(event)).toEqual({
|
|
195
|
+
selections: [],
|
|
196
|
+
range: undefined,
|
|
197
|
+
indices: [3],
|
|
198
|
+
points: [
|
|
199
|
+
{
|
|
200
|
+
x: 8,
|
|
201
|
+
y: 2,
|
|
202
|
+
curveNumber: 0,
|
|
203
|
+
pointNumber: 3,
|
|
204
|
+
pointNumbers: [6, 7],
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("preserves standard heatmap click payloads", () => {
|
|
211
|
+
const event = makeClickEvent([
|
|
212
|
+
makePoint({
|
|
213
|
+
x: "C",
|
|
214
|
+
y: "Row 3",
|
|
215
|
+
z: 11,
|
|
216
|
+
curveNumber: 0,
|
|
217
|
+
pointIndex: 10,
|
|
218
|
+
data: { type: "heatmap" },
|
|
219
|
+
}),
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
expect(extractClickSelection(event)).toEqual({
|
|
223
|
+
selections: [],
|
|
224
|
+
range: undefined,
|
|
225
|
+
indices: [10],
|
|
226
|
+
points: [
|
|
227
|
+
{
|
|
228
|
+
x: "C",
|
|
229
|
+
y: "Row 3",
|
|
230
|
+
z: 11,
|
|
231
|
+
curveNumber: 0,
|
|
232
|
+
pointIndex: 10,
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { pick } from "lodash-es";
|
|
4
|
+
import type * as Plotly from "plotly.js";
|
|
5
|
+
import { Arrays } from "@/utils/arrays";
|
|
6
|
+
import { createParser, type PlotlyTemplateParser } from "./parse-from-template";
|
|
7
|
+
|
|
8
|
+
type AxisName = string;
|
|
9
|
+
type AxisDatum = unknown;
|
|
10
|
+
|
|
11
|
+
export interface PlotlyClickSelection {
|
|
12
|
+
points: Record<AxisName, AxisDatum>[] | Plotly.PlotDatum[];
|
|
13
|
+
indices: number[];
|
|
14
|
+
range: undefined;
|
|
15
|
+
selections: unknown[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CLICK_SELECTABLE_TRACE_TYPES = new Set([
|
|
19
|
+
"heatmap",
|
|
20
|
+
"histogram",
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const STANDARD_POINT_KEYS: string[] = [
|
|
24
|
+
"x",
|
|
25
|
+
"y",
|
|
26
|
+
"z",
|
|
27
|
+
"lat",
|
|
28
|
+
"lon",
|
|
29
|
+
"curveNumber",
|
|
30
|
+
"pointNumber",
|
|
31
|
+
"pointNumbers",
|
|
32
|
+
"pointIndex",
|
|
33
|
+
] as const;
|
|
34
|
+
|
|
35
|
+
function getPointIndex(point: Plotly.PlotDatum): number | undefined {
|
|
36
|
+
if (typeof point.pointIndex === "number") {
|
|
37
|
+
return point.pointIndex;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (typeof point.pointNumber === "number") {
|
|
41
|
+
return point.pointNumber;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isClickSelectablePoint(point: Plotly.PlotDatum): boolean {
|
|
48
|
+
const traceType = point.data?.type;
|
|
49
|
+
return typeof traceType === "string"
|
|
50
|
+
? CLICK_SELECTABLE_TRACE_TYPES.has(traceType)
|
|
51
|
+
: false;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function extractIndices(points: Plotly.PlotDatum[]): number[] {
|
|
55
|
+
return points.flatMap((point) => {
|
|
56
|
+
const index = getPointIndex(point);
|
|
57
|
+
return typeof index === "number" ? [index] : [];
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* This is a hack to extract the points with their original keys,
|
|
63
|
+
* instead of the ones that Plotly uses internally,
|
|
64
|
+
* by using the hovertemplate.
|
|
65
|
+
*/
|
|
66
|
+
export function extractPoints(
|
|
67
|
+
points: Plotly.PlotDatum[],
|
|
68
|
+
): Record<AxisName, AxisDatum>[] {
|
|
69
|
+
if (!points) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let parser: PlotlyTemplateParser | undefined;
|
|
74
|
+
|
|
75
|
+
return points.map((point) => {
|
|
76
|
+
const standardPointFields = pick(point, STANDARD_POINT_KEYS);
|
|
77
|
+
|
|
78
|
+
// Get the first hovertemplate
|
|
79
|
+
const hovertemplate = Array.isArray(point.data.hovertemplate)
|
|
80
|
+
? point.data.hovertemplate[0]
|
|
81
|
+
: point.data.hovertemplate;
|
|
82
|
+
|
|
83
|
+
// For chart types with standard point keys (e.g. heatmaps),
|
|
84
|
+
// or when there's no hovertemplate, pick keys directly from the point.
|
|
85
|
+
if (!hovertemplate || point.data?.type === "heatmap") {
|
|
86
|
+
return standardPointFields;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Update or create a parser
|
|
90
|
+
parser = parser
|
|
91
|
+
? parser.update(hovertemplate)
|
|
92
|
+
: createParser(hovertemplate);
|
|
93
|
+
return {
|
|
94
|
+
...standardPointFields,
|
|
95
|
+
...parser.parse(point),
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function extractClickSelection(
|
|
101
|
+
evt: Readonly<Plotly.PlotMouseEvent>,
|
|
102
|
+
): PlotlyClickSelection | undefined {
|
|
103
|
+
if (!evt.points?.length) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const points = evt.points.filter(isClickSelectablePoint);
|
|
108
|
+
if (points.length === 0) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
selections: Arrays.EMPTY,
|
|
114
|
+
points: extractPoints(points),
|
|
115
|
+
indices: extractIndices(points),
|
|
116
|
+
range: undefined,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -578,20 +578,19 @@ describe("makeSelectable", () => {
|
|
|
578
578
|
`);
|
|
579
579
|
});
|
|
580
580
|
|
|
581
|
-
it.each([
|
|
582
|
-
"
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
});
|
|
581
|
+
it.each(["errorbar", "errorband", "boxplot"])(
|
|
582
|
+
"should return the same spec if mark is %s",
|
|
583
|
+
(mark) => {
|
|
584
|
+
const spec = {
|
|
585
|
+
mark,
|
|
586
|
+
} as unknown as VegaLiteSpec;
|
|
587
|
+
const newSpec = makeSelectable(spec, {});
|
|
588
|
+
expect(newSpec).toEqual(spec);
|
|
589
|
+
expect(getSelectionParamNames(newSpec)).toEqual([]);
|
|
590
|
+
expect(newSpec).toMatchSnapshot();
|
|
591
|
+
expect(parse(newSpec)).toBeDefined();
|
|
592
|
+
},
|
|
593
|
+
);
|
|
595
594
|
|
|
596
595
|
it("should add legend selection to composite charts (issue #6676)", () => {
|
|
597
596
|
// Test case from https://github.com/marimo-team/marimo/issues/6676
|
|
@@ -33,4 +33,72 @@ describe("getContainerWidth", () => {
|
|
|
33
33
|
it("should return undefined when width is explicitly undefined", () => {
|
|
34
34
|
expect(getContainerWidth({ width: undefined })).toBeUndefined();
|
|
35
35
|
});
|
|
36
|
+
|
|
37
|
+
it("should find width in nested facet spec", () => {
|
|
38
|
+
expect(
|
|
39
|
+
getContainerWidth({
|
|
40
|
+
$schema: "https://vega.github.io/schema/vega-lite/v6.json",
|
|
41
|
+
facet: { column: { field: "Origin", type: "nominal" } },
|
|
42
|
+
spec: {
|
|
43
|
+
mark: "point",
|
|
44
|
+
encoding: {},
|
|
45
|
+
width: "container",
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
).toBe("container");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should find width in nested repeat spec", () => {
|
|
52
|
+
expect(
|
|
53
|
+
getContainerWidth({
|
|
54
|
+
$schema: "https://vega.github.io/schema/vega-lite/v6.json",
|
|
55
|
+
repeat: { row: ["A", "B"] },
|
|
56
|
+
spec: {
|
|
57
|
+
mark: "point",
|
|
58
|
+
encoding: {},
|
|
59
|
+
width: "container",
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
).toBe("container");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should return undefined for nested spec without width", () => {
|
|
66
|
+
expect(
|
|
67
|
+
getContainerWidth({
|
|
68
|
+
facet: { column: { field: "Origin" } },
|
|
69
|
+
spec: { mark: "point", encoding: {} },
|
|
70
|
+
}),
|
|
71
|
+
).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should return undefined for hconcat (width on sub-specs)", () => {
|
|
75
|
+
expect(
|
|
76
|
+
getContainerWidth({
|
|
77
|
+
hconcat: [{ width: "container" }, { width: "container" }],
|
|
78
|
+
}),
|
|
79
|
+
).toBeUndefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should return undefined for vconcat (width on sub-specs)", () => {
|
|
83
|
+
expect(
|
|
84
|
+
getContainerWidth({
|
|
85
|
+
vconcat: [{ width: "container" }, { width: "container" }],
|
|
86
|
+
}),
|
|
87
|
+
).toBeUndefined();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should return undefined for compiled Vega spec (width as signal)", () => {
|
|
91
|
+
expect(
|
|
92
|
+
getContainerWidth({
|
|
93
|
+
$schema: "https://vega.github.io/schema/vega/v6.json",
|
|
94
|
+
autosize: { contains: "padding", type: "fit-x" },
|
|
95
|
+
signals: [
|
|
96
|
+
{
|
|
97
|
+
name: "width",
|
|
98
|
+
init: "isFinite(containerSize()[0]) ? containerSize()[0] : 300",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
}),
|
|
102
|
+
).toBeUndefined();
|
|
103
|
+
});
|
|
36
104
|
});
|
|
@@ -6,13 +6,22 @@ import type { DataType, FieldTypes, VegaDataType } from "./vega-loader";
|
|
|
6
6
|
export type ContainerWidth = number | "container";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Get the container width from a
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Get the container width from a Vega-Lite spec.
|
|
10
|
+
*
|
|
11
|
+
* For unit specs, `width` is at the top level. For facet/repeat specs,
|
|
12
|
+
* `width` is nested inside `spec`. This does not handle hconcat/vconcat and Vega spec
|
|
13
|
+
* where the width may be a signal. These cases are covered by
|
|
14
|
+
* the CSS fallback `.vega-embed:has(> .chart-wrapper.fit-x)`.
|
|
12
15
|
*/
|
|
13
16
|
export function getContainerWidth(spec: unknown): ContainerWidth | undefined {
|
|
14
|
-
if (typeof spec === "object" && spec !== null
|
|
15
|
-
|
|
17
|
+
if (typeof spec === "object" && spec !== null) {
|
|
18
|
+
if ("width" in spec) {
|
|
19
|
+
return spec.width as ContainerWidth | undefined;
|
|
20
|
+
}
|
|
21
|
+
// Faceted/repeated spec
|
|
22
|
+
if ("spec" in spec) {
|
|
23
|
+
return getContainerWidth(spec.spec);
|
|
24
|
+
}
|
|
16
25
|
}
|
|
17
26
|
return undefined;
|
|
18
27
|
}
|
|
@@ -11,9 +11,7 @@ const LazyImageComparisonComponent = React.lazy(
|
|
|
11
11
|
() => import("../impl/image-comparison/ImageComparisonComponent"),
|
|
12
12
|
);
|
|
13
13
|
|
|
14
|
-
export class ImageComparisonPlugin
|
|
15
|
-
implements IStatelessPlugin<ImageComparisonData>
|
|
16
|
-
{
|
|
14
|
+
export class ImageComparisonPlugin implements IStatelessPlugin<ImageComparisonData> {
|
|
17
15
|
tagName = "marimo-image-comparison";
|
|
18
16
|
|
|
19
17
|
validator = z.object({
|
|
@@ -20,8 +20,10 @@ export interface IStatelessPluginProps<D> {
|
|
|
20
20
|
children?: React.ReactNode | undefined;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface IStatelessPlugin<D>
|
|
24
|
-
|
|
23
|
+
export interface IStatelessPlugin<D> extends Omit<
|
|
24
|
+
IPlugin<never, D>,
|
|
25
|
+
"render" | "functions"
|
|
26
|
+
> {
|
|
25
27
|
/**
|
|
26
28
|
* Render the plugin.
|
|
27
29
|
*/
|
|
@@ -92,27 +92,30 @@ describe("cell-urls utilities", () => {
|
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
describe("edge case cell names with unicode and special characters", () => {
|
|
95
|
-
it.each(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
96
|
+
"should handle unicode cell names in createCellLink: %s",
|
|
97
|
+
(cellName) => {
|
|
98
|
+
const url = createCellLink(cellName);
|
|
99
|
+
expect(url).toContain("scrollTo=");
|
|
100
|
+
expect(url).toContain(encodeURIComponent(cellName));
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
105
|
+
"should round-trip unicode cell names correctly: %s",
|
|
106
|
+
(cellName) => {
|
|
107
|
+
const url = createCellLink(cellName);
|
|
108
|
+
const hash = url.split("#")[1];
|
|
109
|
+
const extracted = extractCellNameFromHash(`#${hash}`);
|
|
110
|
+
expect(extracted).toBe(cellName);
|
|
111
|
+
},
|
|
112
|
+
);
|
|
111
113
|
|
|
112
|
-
it.each(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
it.each(EDGE_CASE_CELL_NAMES)(
|
|
115
|
+
"should allow linking to unicode cell names: %s",
|
|
116
|
+
(cellName) => {
|
|
117
|
+
expect(canLinkToCell(cellName)).toBe(true);
|
|
118
|
+
},
|
|
119
|
+
);
|
|
117
120
|
});
|
|
118
121
|
});
|
|
@@ -35,22 +35,23 @@ describe("Filenames", () => {
|
|
|
35
35
|
expect(Filenames.withoutExtension("test.foo.txt")).toEqual("test.foo");
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
it.each(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
it.each(EDGE_CASE_FILENAMES)(
|
|
39
|
+
"should handle edge case filenames: %s",
|
|
40
|
+
(filename) => {
|
|
41
|
+
// Test all filename operations with edge cases
|
|
42
|
+
const withoutExt = Filenames.withoutExtension(filename);
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
expect(Filenames.toMarkdown(filename)).toEqual(`${withoutExt}.md`);
|
|
45
|
+
expect(Filenames.toHTML(filename)).toEqual(`${withoutExt}.html`);
|
|
46
|
+
expect(Filenames.toPNG(filename)).toEqual(`${withoutExt}.png`);
|
|
47
|
+
expect(Filenames.toPY(filename)).toEqual(`${withoutExt}.py`);
|
|
48
|
+
expect(Filenames.toIPYNB(filename)).toEqual(`${withoutExt}.ipynb`);
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
// Ensure operations preserve unicode and special characters in base name
|
|
51
|
+
expect(withoutExt).not.toEqual("");
|
|
52
|
+
expect(typeof withoutExt).toBe("string");
|
|
53
|
+
},
|
|
54
|
+
);
|
|
54
55
|
});
|
|
55
56
|
|
|
56
57
|
describe("getImageExtension", () => {
|