@marimo-team/islands 0.23.9-dev1 → 0.23.9-dev11
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-2lBNiUv6.js → ConnectedDataExplorerComponent-DFQ1yVhp.js} +20 -20
- package/dist/ErrorBoundary-rULOrC_p.js +175 -0
- package/dist/{ImageComparisonComponent-CNHIsPDj.js → ImageComparisonComponent-CHrI72em.js} +1 -1
- package/dist/{Plot-4wn-lMVn.js → Plot-CAYS29h9.js} +1 -1
- package/dist/{_baseUniq-CxZRxRRo.js → _baseUniq-B_2Hw7zG.js} +3 -3
- package/dist/{any-language-editor-VWs_7v27.js → any-language-editor-DfdpyDv_.js} +23 -23
- package/dist/architecture-7HQA4BMR-Kyc44TmC.js +6 -0
- package/dist/{architectureDiagram-VXUJARFQ-CXVJxFhH.js → architectureDiagram-VXUJARFQ-CT2SuxNw.js} +15 -15
- package/dist/{arrays-CldYf7p7.js → arrays-sEtDRoG4.js} +1 -1
- package/dist/{blockDiagram-VD42YOAC-DGDaxR8I.js → blockDiagram-VD42YOAC-Dy7hlFla.js} +7 -7
- package/dist/{button-Dj4BTre0.js → button-C5K9fIPF.js} +2 -2
- package/dist/{c4Diagram-YG6GDRKO-C2hc6ne8.js → c4Diagram-YG6GDRKO-BXlAmZ8Z.js} +4 -4
- package/dist/{capabilities-C9rrYCzf.js → capabilities-BceAxrAW.js} +2 -2
- package/dist/{channel-BBoIVUrJ.js → channel-D_PHgcig.js} +1 -1
- package/dist/{chat-ui-D3XBept8.js → chat-ui-xfKWgbtB.js} +29 -29
- package/dist/{check-BcUIXnUT.js → check-DTbrK0zt.js} +1 -1
- package/dist/{chunk-4F5CHEZ2-BZq7Kom7.js → chunk-4F5CHEZ2-D9nGEHV8.js} +1 -1
- package/dist/{chunk-5FQGJX7Z-BOg95xG5.js → chunk-5FQGJX7Z-BNjes6Yx.js} +5 -5
- package/dist/{chunk-ABZYJK2D-D0cLy8Bb.js → chunk-ABZYJK2D-Dz0-H2B5.js} +1 -1
- package/dist/{chunk-ATLVNIR6-BXsEjlHF.js → chunk-ATLVNIR6-o0Z5MZLd.js} +1 -1
- package/dist/{chunk-B2363JML-D9-XOau1.js → chunk-B2363JML-KEJpLGGP.js} +1 -1
- package/dist/{chunk-B4BG7PRW-Q1usn6T3.js → chunk-B4BG7PRW-BL98U9B4.js} +4 -4
- package/dist/{chunk-DI55MBZ5-D1qLYNrb.js → chunk-DI55MBZ5-Dwkn0LWm.js} +4 -4
- package/dist/{chunk-EXTU4WIE-BKNXdLmD.js → chunk-EXTU4WIE-9sNjmQrB.js} +1 -1
- package/dist/{chunk-FRFDVMJY-BSBUAX7r.js → chunk-FRFDVMJY-DzQqMWrl.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-D6c6cOBG.js → chunk-JA3XYJ7Z-C32Y7Epf.js} +2 -2
- package/dist/{chunk-JZLCHNYA-BvsPHJmL.js → chunk-JZLCHNYA-C6ftyVMN.js} +4 -4
- package/dist/{chunk-N4CR4FBY-8ycT-O9a.js → chunk-N4CR4FBY-DUhGZhZs.js} +5 -5
- package/dist/{chunk-PL6DKKU2-B0MTXvyc.js → chunk-PL6DKKU2-D7km-08O.js} +1 -1
- package/dist/{chunk-QN33PNHL-Bb-eUBW3.js → chunk-QN33PNHL-0K6SDYn3.js} +1 -1
- package/dist/{chunk-QXUST7PY-DV8yRwBd.js → chunk-QXUST7PY-DMhsRpYK.js} +5 -5
- package/dist/{chunk-S3R3BYOJ-mQeCz5CE.js → chunk-S3R3BYOJ-oAe3dEbO.js} +3 -3
- package/dist/{chunk-SJTYNZTY-CEG4F0pB.js → chunk-SJTYNZTY-BkJrPRFC.js} +1 -1
- package/dist/{chunk-TCCFYFTB-d3HOqL2I.js → chunk-TCCFYFTB-D58KeXnC.js} +6 -6
- package/dist/{chunk-TQ3KTPDO-DiCtqVSi.js → chunk-TQ3KTPDO-D_yA_wAb.js} +1 -1
- package/dist/{chunk-TZMSLE5B-BqW10dHe.js → chunk-TZMSLE5B-yBKS_DQU.js} +1 -1
- package/dist/{chunk-UMXZTB3W-97iS1iEl.js → chunk-UMXZTB3W-D7uwvNjd.js} +1 -1
- package/dist/{classDiagram-2ON5EDUG--Yh__LHb.js → classDiagram-2ON5EDUG-QjoAcuFE.js} +10 -10
- package/dist/{classDiagram-v2-WZHVMYZB-BC7X7Xtc.js → classDiagram-v2-WZHVMYZB-bUCv4gu2.js} +10 -10
- package/dist/{clone-BuIIsfA8.js → clone-Q4Fqwn6q.js} +1 -1
- package/dist/{code-block-37QAKDTI-BsGy1AOJ.js → code-block-37QAKDTI-m92Yc8pv.js} +2 -2
- package/dist/{code-visibility-BEBL2NuO.js → code-visibility-Dv-4kU3M.js} +8425 -8595
- package/dist/{constants-D0gkYoE2.js → constants-T20xxyNf.js} +2 -2
- package/dist/{copy-DLf4aN7I.js → copy-BuQpJEzp.js} +2 -2
- package/dist/{dagre-6UL2VRFP-DRBWoQUw.js → dagre-6UL2VRFP-J0JKgwOt.js} +11 -11
- package/dist/{dagre-VYEPqXIV.js → dagre-By_QsQgc.js} +11 -11
- package/dist/{data-grid-overlay-editor-efe5ZagF.js → data-grid-overlay-editor-mfEJ5475.js} +2 -2
- package/dist/{diagram-PSM6KHXK-H66ATWP2.js → diagram-PSM6KHXK-DYgJuNk9.js} +18 -18
- package/dist/{diagram-QEK2KX5R-DItl5Wns.js → diagram-QEK2KX5R-CKdBR2sb.js} +14 -14
- package/dist/{diagram-S2PKOQOG-CtuW_ZuL.js → diagram-S2PKOQOG-Dpi7mo5W.js} +14 -14
- package/dist/dist-0Fif7jnk.js +5 -0
- package/dist/{dist-Dh3wkoyH.js → dist-4j4c7bjm.js} +2 -2
- package/dist/{dist-CDFZi-QD.js → dist-B3P2fFpz.js} +1 -1
- package/dist/{dist-BNyrZfqT.js → dist-B3pZ0Ab6.js} +2 -2
- package/dist/dist-B5h_9sHB.js +6 -0
- package/dist/dist-B9M6R5ye.js +5 -0
- package/dist/dist-BCt3tnck.js +8 -0
- package/dist/{dist-BrBucRXs.js → dist-BTfv03uy.js} +2 -2
- package/dist/dist-BUIJwMwn.js +8 -0
- package/dist/{dist-CYEylvZA.js → dist-BbbIBDiQ.js} +1 -1
- package/dist/{dist-KnujRhFL.js → dist-BcuoonNH.js} +4 -4
- package/dist/{dist-DJ6zJQZ4.js → dist-Bde4a2kU.js} +2 -2
- package/dist/{dist-t_qL7eB8.js → dist-Bfwsv11D.js} +2 -2
- package/dist/{dist-CNtV21T_.js → dist-BhM8gdSO.js} +4 -4
- package/dist/{dist-nuW5EDYT.js → dist-BotSqB48.js} +2 -2
- package/dist/dist-BpquMd3k.js +5 -0
- package/dist/dist-BzJsqYfz.js +5 -0
- package/dist/{dist-D029TiHd.js → dist-Bz_sYWbr.js} +2 -2
- package/dist/{dist-D3ZI9nhS.js → dist-C1BYNeCR.js} +4 -4
- package/dist/{dist-Bc5pmZIw.js → dist-C5VC_yzu.js} +1 -1
- package/dist/dist-CA5ELXAf.js +6 -0
- package/dist/dist-CLBRs6Uv.js +5 -0
- package/dist/{dist-Dhk6FMb0.js → dist-CLJWPTX2.js} +3 -3
- package/dist/{dist-C34oIrQ9.js → dist-CLUtPrdy.js} +1 -1
- package/dist/dist-CStVCMbq.js +5 -0
- package/dist/{dist-B8RaFTRF.js → dist-CUCNs1ja.js} +2 -2
- package/dist/dist-CZRIEY3Y.js +8 -0
- package/dist/{dist-UcOPnRMa.js → dist-CcXxepx6.js} +3 -3
- package/dist/dist-CuUHbFD0.js +5 -0
- package/dist/{dist-B8BjrFUE.js → dist-Cy1WxgBD.js} +5 -5
- package/dist/{dist-WdPUFc56.js → dist-D4CewLk6.js} +1 -1
- package/dist/{dist-DMZNjfX4.js → dist-DRfcqpxJ.js} +2 -2
- package/dist/dist-DV7Iabxb.js +8 -0
- package/dist/{dist-usPCDYx8.js → dist-D_bzzWBm.js} +1 -1
- package/dist/{dist-BvCfQQQE.js → dist-DgnE8F-r.js} +1 -1
- package/dist/{dist-JEhxD_cn.js → dist-DhHh0jLg.js} +1 -1
- package/dist/{dist-DGAfI2rB.js → dist-DqAWR3CS.js} +2 -2
- package/dist/{dist--sWVZwjW.js → dist-Du8WkPuU.js} +1 -1
- package/dist/dist-DuEeHMvL.js +5 -0
- package/dist/{dist-BTyJtnNg.js → dist-DxvORzUR.js} +1 -1
- package/dist/{dist-B507mf_I.js → dist-RqXTaiir.js} +2 -2
- package/dist/{dist-Yrfc6L0I.js → dist-fQ0ViXGs.js} +3 -3
- package/dist/{dist-B4LJpMEg.js → dist-h2c8sZvT.js} +1 -1
- package/dist/{dist-C2ej4eOH.js → dist-luvabDEB.js} +2 -2
- package/dist/{dist-B52GXZbd.js → dist-p2qyWijU.js} +2 -2
- package/dist/{erDiagram-Q2GNP2WA--19X2kU5.js → erDiagram-Q2GNP2WA-BU-m41EQ.js} +10 -10
- package/dist/{error-banner-CVkfBUT3.js → error-banner-5bz0L9hS.js} +3 -3
- package/dist/{esm-CWp0KQeK.js → esm-BfhQmZjp.js} +4 -4
- package/dist/{esm-DjNnlmpf.js → esm-Duie8iU-.js} +23 -23
- package/dist/{extends-vAi97cpa.js → extends-BgdxCfYu.js} +6 -6
- package/dist/{flatten-CzBvFdvC.js → flatten-Bbw7g6-K.js} +1 -1
- package/dist/{flowDiagram-NV44I4VS-DQmWlo7f.js → flowDiagram-NV44I4VS-CRoXKjGq.js} +10 -10
- package/dist/{formats-Dsy9kkZu.js → formats-BHOojBDG.js} +4 -4
- package/dist/{ganttDiagram-JELNMOA3-BOGXJ8Lk.js → ganttDiagram-JELNMOA3-7mq5f9cO.js} +7 -7
- package/dist/{gitGraph-G5XIXVHT-DGlbae5m.js → gitGraph-G5XIXVHT-DiniR35k.js} +3 -3
- package/dist/{gitGraphDiagram-V2S2FVAM-DjzxfF0P.js → gitGraphDiagram-V2S2FVAM-Dfuokq6w.js} +13 -13
- package/dist/{glide-data-editor-DucgdjRo.js → glide-data-editor-CpzEdx8N.js} +557 -557
- package/dist/{graphlib-CVPKjKCS.js → graphlib-Ns7y5crs.js} +5 -5
- package/dist/{hasIn-COs6vImh.js → hasIn-Deg7jl_j.js} +3 -3
- package/dist/{html-to-image-CpggM7u1.js → html-to-image-DjEqYaQd.js} +109 -109
- package/dist/{info-VBDWY6EO-D2lvLLw5.js → info-VBDWY6EO-DVZvGhkQ.js} +3 -3
- package/dist/{infoDiagram-HS3SLOUP-ChNufFsP.js → infoDiagram-HS3SLOUP-CEnzWruK.js} +13 -13
- package/dist/{input-D4kjoQUB.js → input-DBDlwwuD.js} +70 -67
- package/dist/{isEmpty-Dd8mx_WL.js → isEmpty-CJJMn-QP.js} +1 -1
- package/dist/{isSymbol-BvIfMnn6.js → isSymbol-CoUCgMCM.js} +1 -1
- package/dist/{journeyDiagram-XKPGCS4Q-BO_O4Ij1.js → journeyDiagram-XKPGCS4Q-8XYSU1GI.js} +3 -3
- package/dist/{kanban-definition-3W4ZIXB7-CPpiiiWk.js → kanban-definition-3W4ZIXB7--9pT9z1R.js} +7 -7
- package/dist/{label-BLqV33b1.js → label-LWtdw5i8.js} +3 -3
- package/dist/{linear-2NnK4cxi.js → linear-B5-AFRiR.js} +2 -2
- package/dist/{loader-Dr8Qem8p.js → loader-BWLPpjKK.js} +2 -2
- package/dist/main.js +1681 -1555
- package/dist/{memoize-C9ltv0Cw.js → memoize-BOtf2yFf.js} +1 -1
- package/dist/{merge-CHn7Yx0N.js → merge-Be1CqGnU.js} +1 -1
- package/dist/mermaid-4DMBBIKO-DIdL224_.js +6 -0
- package/dist/{mermaid-DO-Daq7u.js → mermaid-D00onudG.js} +44 -44
- package/dist/{mermaid-parser.core-DreccfmS.js → mermaid-parser.core-C3XRsazI.js} +8 -8
- package/dist/{min-BNz2lZfk.js → min-Dtgc8txR.js} +4 -4
- package/dist/{mindmap-definition-VGOIOE7T-CC1_Vl0f.js → mindmap-definition-VGOIOE7T-B-4mnfFG.js} +9 -9
- package/dist/{now-Sgq5m3D-.js → now-Ch98bJO_.js} +2 -2
- package/dist/{number-overlay-editor-CpKi64Fy.js → number-overlay-editor-D-a0qCT8.js} +1 -1
- package/dist/{once-rJImu7SE.js → once-DPuqGUeo.js} +1 -1
- package/dist/{packet-DYOGHKS2-CmWtF3uO.js → packet-DYOGHKS2-34raHOiB.js} +3 -3
- package/dist/{pick-CRAXxDYn.js → pick-D1Qo8s2C.js} +4 -4
- package/dist/{pie-VRWISCQL-B6u8vus8.js → pie-VRWISCQL-BaLlzZa3.js} +3 -3
- package/dist/{pieDiagram-ADFJNKIX-Di34MOFQ.js → pieDiagram-ADFJNKIX-Cr3cNpZY.js} +15 -15
- package/dist/{precisionRound-CnHPY_5v.js → precisionRound-Tqb4mg-H.js} +1 -1
- package/dist/{process-output-X8TR20AK.js → process-output-Cz6wQSkL.js} +4 -4
- package/dist/{quadrantDiagram-AYHSOK5B-B9kVk1ny.js → quadrantDiagram-AYHSOK5B-BuNL8Q93.js} +4 -4
- package/dist/{radar-ZZBFDIW7-XAmXSa8s.js → radar-ZZBFDIW7-Ci7bfoZa.js} +3 -3
- package/dist/{react-vega-Dh6-UKKe.js → react-vega-B0sAlDTL.js} +9 -9
- package/dist/react-vega-B6ncY2Tp.js +9 -0
- package/dist/{requirementDiagram-UZGBJVZJ-BxGfGYEx.js → requirementDiagram-UZGBJVZJ-BG2lLUN1.js} +9 -9
- package/dist/{reveal-component-CEHb1Q34.js → reveal-component-BsyenC3H.js} +31 -31
- package/dist/{sankeyDiagram-TZEHDZUN-D09PBJ-n.js → sankeyDiagram-TZEHDZUN-DMal8sps.js} +3 -3
- package/dist/{sequenceDiagram-WL72ISMW-t_Dpemj0.js → sequenceDiagram-WL72ISMW-DT6Tk-Eo.js} +4 -4
- package/dist/{spec-hVaaZsY5.js → spec-BQbOvWbq.js} +4 -4
- package/dist/{stateDiagram-FKZM4ZOC-B18gTP_j.js → stateDiagram-FKZM4ZOC-CB_lodq3.js} +12 -12
- package/dist/{stateDiagram-v2-4FDKWEC3-B6e_t14A.js → stateDiagram-v2-4FDKWEC3-E0RGjKsm.js} +10 -10
- package/dist/stex-KfRnSHzF.js +4 -0
- package/dist/{strings-BiIhGaI8.js → strings-Bu3vlb6W.js} +7 -7
- package/dist/style.css +1 -1
- package/dist/{swiper-component-DlD2GU2g.js → swiper-component-B2t5sN1q.js} +3 -3
- package/dist/{time-C1SGcFMH.js → time-CsmIF9YZ.js} +3 -3
- package/dist/{timeline-definition-IT6M3QCI-DJnh1ks5.js → timeline-definition-IT6M3QCI-NfSKRvH0.js} +2 -2
- package/dist/{toDate-CIpC_34u.js → toDate-DqrFDZlc.js} +5 -5
- package/dist/{tooltip-DRaMBu06.js → tooltip-C5FYOpQc.js} +4 -4
- package/dist/{treemap-GDKQZRPO-Du95DV6u.js → treemap-GDKQZRPO-Cl6OQh8D.js} +3 -3
- package/dist/{types-Dzuoc3LN.js → types-CVvp1fKr.js} +2 -9
- package/dist/{useAsyncData-C56Khv_R.js → useAsyncData-4lY05iWF.js} +2 -2
- package/dist/{useDateFormatter-B_9k85Ex.js → useDateFormatter-BA4FCquG.js} +2 -2
- package/dist/{useDeepCompareMemoize-Dt98v2ua.js → useDeepCompareMemoize-C5Zu9gK6.js} +1 -1
- package/dist/{useIframeCapabilities-BkYHTrss.js → useIframeCapabilities-C4JTXTIh.js} +1 -1
- package/dist/{useLifecycle-BF6-z62y.js → useLifecycle-YLdDriVo.js} +4 -4
- package/dist/{useTheme-DykuNHR2.js → useTheme-u3PW8S24.js} +22 -21
- package/dist/{vega-component-cSdqoAxe.js → vega-component-CdQu2ErN.js} +18 -18
- package/dist/{vega-loader.browser-3_z8GoFC.js → vega-loader.browser-CZ-J8Py3.js} +3 -3
- package/dist/{xychartDiagram-PRI3JC2R-Dk2d_bX0.js → xychartDiagram-PRI3JC2R-BvwftqMA.js} +9 -9
- package/dist/{zod-BWkcDORu.js → zod-CoBiJ5v4.js} +3 -3
- package/package.json +1 -1
- package/src/components/data-table/TableBottomBar.tsx +27 -6
- package/src/components/data-table/TableTopBar.tsx +7 -1
- package/src/components/data-table/__tests__/TableBottomBar.test.tsx +73 -0
- package/src/components/data-table/__tests__/column-explorer.test.tsx +128 -0
- package/src/components/data-table/__tests__/column-header.test.tsx +110 -277
- package/src/components/data-table/__tests__/data-table.test.tsx +52 -1
- package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +33 -0
- package/src/components/data-table/__tests__/filter-pill-editor.test.tsx +75 -38
- package/src/components/data-table/__tests__/filter-pills.test.tsx +287 -0
- package/src/components/data-table/__tests__/filter-test-utils.ts +47 -0
- package/src/components/data-table/__tests__/filters.test.ts +5 -5
- package/src/components/data-table/__tests__/header-items.test.tsx +47 -1
- package/src/components/data-table/__tests__/useColumnVisibility.test.ts +42 -0
- package/src/components/data-table/add-filter-button.tsx +85 -0
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +98 -26
- package/src/components/data-table/column-header.tsx +94 -691
- package/src/components/data-table/columns.tsx +3 -4
- package/src/components/data-table/context-menu.tsx +26 -12
- package/src/components/data-table/data-table.tsx +125 -56
- package/src/components/data-table/date-filter-inputs.tsx +13 -10
- package/src/components/data-table/export-actions.tsx +17 -6
- package/src/components/data-table/filter-by-values-picker.tsx +13 -19
- package/src/components/data-table/filter-editor-context.tsx +34 -0
- package/src/components/data-table/filter-pill-editor.tsx +152 -175
- package/src/components/data-table/filter-pills.tsx +190 -153
- package/src/components/data-table/filters/builders.ts +102 -0
- package/src/components/data-table/filters/defaults.ts +31 -0
- package/src/components/data-table/filters/format.ts +131 -0
- package/src/components/data-table/filters/guards.ts +51 -0
- package/src/components/data-table/filters/index.ts +7 -0
- package/src/components/data-table/filters/operators.ts +76 -0
- package/src/components/data-table/filters/serialize.ts +186 -0
- package/src/components/data-table/filters/types.ts +33 -0
- package/src/components/data-table/header-items.tsx +25 -85
- package/src/components/data-table/hooks/use-column-visibility.ts +56 -0
- package/src/components/data-table/pagination.tsx +16 -3
- package/src/components/data-table/table-explorer-panel/table-explorer-panel.tsx +16 -6
- package/src/components/data-table/value-chips.tsx +52 -0
- package/src/components/dependency-graph/minimap-content.tsx +2 -2
- package/src/components/editor/errors/mangled-local-chip.tsx +50 -0
- package/src/components/editor/output/MarimoErrorOutput.tsx +110 -27
- package/src/components/editor/output/MarimoTracebackOutput.tsx +51 -34
- package/src/components/ui/number-field.tsx +13 -1
- package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
- package/src/css/app/Cell.css +0 -1
- package/src/plugins/impl/DataTablePlugin.tsx +94 -33
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +1 -0
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +8 -6
- package/src/stories/dataframe.stories.tsx +1 -0
- package/src/utils/__tests__/local-variables.test.ts +132 -0
- package/src/utils/dates.ts +39 -0
- package/src/utils/local-variables.ts +67 -0
- package/dist/ErrorBoundary-D3wrPNma.js +0 -167
- package/dist/architecture-7HQA4BMR-CS9jOrqM.js +0 -6
- package/dist/dist-21ButRCu.js +0 -8
- package/dist/dist-B--tLnAP.js +0 -5
- package/dist/dist-BoHGySTM.js +0 -5
- package/dist/dist-ByAz19Qc.js +0 -5
- package/dist/dist-C1Ap5CYU.js +0 -5
- package/dist/dist-C93EysN4.js +0 -5
- package/dist/dist-CY-lVor6.js +0 -8
- package/dist/dist-CYDuv4bR.js +0 -8
- package/dist/dist-Cfo5EE2t.js +0 -6
- package/dist/dist-CjivSDvN.js +0 -5
- package/dist/dist-Cqwx-MH7.js +0 -5
- package/dist/dist-DbpcoFAV.js +0 -6
- package/dist/dist-FUNenbiQ.js +0 -5
- package/dist/dist-zhSud5X3.js +0 -8
- package/dist/mermaid-4DMBBIKO-B7VQMwJx.js +0 -6
- package/dist/react-vega-Cavbrg4l.js +0 -9
- package/dist/stex-ChDHQs3R.js +0 -4
- package/src/components/data-table/__tests__/column-header.test.ts +0 -65
- package/src/components/data-table/filters.ts +0 -386
- /package/dist/{_baseFor-BGiY-cm1.js → _baseFor-4jw-lnCC.js} +0 -0
- /package/dist/{clsx-CyyyQ8Ue.js → clsx-CIWA5tNO.js} +0 -0
- /package/dist/{defaultLocale-DoeErsX2.js → defaultLocale-BoHTsDG6.js} +0 -0
- /package/dist/{defaultLocale-BpsHxBd7.js → defaultLocale-u-3osm0P.js} +0 -0
- /package/dist/{dist-CCADb07R.js → dist-DNdhYsgW.js} +0 -0
- /package/dist/{emotion-is-prop-valid.esm-DtW2o230.js → emotion-is-prop-valid.esm-DzSb5hsH.js} +0 -0
- /package/dist/{invariant-UcGKQEhF.js → invariant-wRzNXIsJ.js} +0 -0
- /package/dist/{jsx-runtime-COBk7ree.js → jsx-runtime-DebpN0FN.js} +0 -0
- /package/dist/{main-CThhXnXU.js → main-Tj_-QTyF.js} +0 -0
- /package/dist/{micromark-factory-space-CwHmg6iz.js → micromark-factory-space-DF2w36zS.js} +0 -0
- /package/dist/{ordinal-B43ZeR68.js → ordinal-ArJavP1Q.js} +0 -0
- /package/dist/{purify.es-DT70lfR0.js → purify.es-H92eMd9-.js} +0 -0
- /package/dist/{range-BOiA8qqU.js → range-C-rmrM1O.js} +0 -0
- /package/dist/{react-dom-BWRJ_g_k.js → react-dom-BTJzcVJ9.js} +0 -0
- /package/dist/{stex-DrxP7bb3.js → stex-BIsgBmK4.js} +0 -0
|
@@ -8,8 +8,9 @@ import type {
|
|
|
8
8
|
PaginationState,
|
|
9
9
|
RowSelectionState,
|
|
10
10
|
SortingState,
|
|
11
|
+
Table as TanstackTable,
|
|
11
12
|
} from "@tanstack/react-table";
|
|
12
|
-
import { Provider } from "jotai";
|
|
13
|
+
import { Provider, useAtomValue } from "jotai";
|
|
13
14
|
import { Table2Icon } from "lucide-react";
|
|
14
15
|
import type { JSX } from "react";
|
|
15
16
|
import React, {
|
|
@@ -28,6 +29,7 @@ import { TablePanel } from "@/components/data-table/charts/charts";
|
|
|
28
29
|
import { hasChart } from "@/components/data-table/charts/storage";
|
|
29
30
|
import { ColumnChartSpecModel } from "@/components/data-table/column-summary/chart-spec-model";
|
|
30
31
|
import { ColumnChartContext } from "@/components/data-table/column-summary/column-summary";
|
|
32
|
+
import { downloadSizeLimitAtom } from "@/components/data-table/download-policy/atoms";
|
|
31
33
|
import { filtersToFilterGroup } from "@/components/data-table/filters";
|
|
32
34
|
import { usePanelOwnership } from "@/components/data-table/hooks/use-panel-ownership";
|
|
33
35
|
import { LoadingTable } from "@/components/data-table/loading-table";
|
|
@@ -190,11 +192,11 @@ interface Data<T> {
|
|
|
190
192
|
fieldTypes?: FieldTypesWithExternalType | null;
|
|
191
193
|
freezeColumnsLeft?: string[];
|
|
192
194
|
freezeColumnsRight?: string[];
|
|
195
|
+
hiddenColumns?: string[];
|
|
193
196
|
textJustifyColumns?: Record<string, "left" | "center" | "right">;
|
|
194
197
|
wrappedColumns?: string[];
|
|
195
198
|
headerTooltip?: Record<string, string>;
|
|
196
199
|
totalColumns: number;
|
|
197
|
-
sizeBytes?: number | null;
|
|
198
200
|
maxColumns: number | "all";
|
|
199
201
|
hasStableRowId: boolean;
|
|
200
202
|
lazy: boolean;
|
|
@@ -221,12 +223,14 @@ type DataTableFunctions = {
|
|
|
221
223
|
cell_styles?: CellStyleState | null;
|
|
222
224
|
cell_hover_texts?: Record<string, Record<string, string | null>> | null;
|
|
223
225
|
raw_data?: TableData<T> | null;
|
|
224
|
-
size_bytes?: number | null;
|
|
225
226
|
}>;
|
|
226
227
|
get_data_url?: GetDataUrl;
|
|
227
228
|
get_row_ids?: GetRowIds;
|
|
228
229
|
calculate_top_k_rows?: CalculateTopKRows;
|
|
229
230
|
preview_column?: PreviewColumn;
|
|
231
|
+
get_size_bytes: (opts: Record<string, never>) => Promise<{
|
|
232
|
+
size_bytes?: number | null;
|
|
233
|
+
}>;
|
|
230
234
|
};
|
|
231
235
|
|
|
232
236
|
type S = (number | string | { rowId: string; columnName?: string })[];
|
|
@@ -265,6 +269,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
265
269
|
rowHeaders: columnToFieldTypesSchema,
|
|
266
270
|
freezeColumnsLeft: z.array(z.string()).optional(),
|
|
267
271
|
freezeColumnsRight: z.array(z.string()).optional(),
|
|
272
|
+
hiddenColumns: z.array(z.string()).optional(),
|
|
268
273
|
textJustifyColumns: z
|
|
269
274
|
.record(z.string(), z.enum(["left", "center", "right"]))
|
|
270
275
|
.optional(),
|
|
@@ -272,7 +277,6 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
272
277
|
headerTooltip: z.record(z.string(), z.string()).optional(),
|
|
273
278
|
fieldTypes: columnToFieldTypesSchema.nullish(),
|
|
274
279
|
totalColumns: z.number(),
|
|
275
|
-
sizeBytes: z.number().nullish(),
|
|
276
280
|
maxColumns: z.union([z.number(), z.literal("all")]).default("all"),
|
|
277
281
|
hasStableRowId: z.boolean().default(false),
|
|
278
282
|
maxHeight: z.number().optional(),
|
|
@@ -330,7 +334,6 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
330
334
|
.nullable(),
|
|
331
335
|
cell_hover_texts: cellHoverTextSchema.nullable(),
|
|
332
336
|
raw_data: z.union([z.string(), z.array(z.looseObject({}))]).nullish(),
|
|
333
|
-
size_bytes: z.number().nullish(),
|
|
334
337
|
}),
|
|
335
338
|
),
|
|
336
339
|
get_row_ids: rpc.input(z.object({}).passthrough()).output(
|
|
@@ -362,6 +365,9 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
362
365
|
stats: columnStats.nullable(),
|
|
363
366
|
}),
|
|
364
367
|
),
|
|
368
|
+
get_size_bytes: rpc
|
|
369
|
+
.input(z.object({}))
|
|
370
|
+
.output(z.object({ size_bytes: z.number().nullish() })),
|
|
365
371
|
})
|
|
366
372
|
.renderer((props) => {
|
|
367
373
|
return (
|
|
@@ -536,7 +542,6 @@ export const LoadingDataTableComponent = memo(
|
|
|
536
542
|
rows: T[];
|
|
537
543
|
rawRows?: T[];
|
|
538
544
|
totalRows: number | TooManyRows;
|
|
539
|
-
sizeBytes?: number | null;
|
|
540
545
|
cellStyles: CellStyleState | undefined | null;
|
|
541
546
|
cellHoverTexts?: Record<string, Record<string, string | null>> | null;
|
|
542
547
|
}>(async () => {
|
|
@@ -553,7 +558,6 @@ export const LoadingDataTableComponent = memo(
|
|
|
553
558
|
let tableData = props.data;
|
|
554
559
|
let rawTableData: TableData<T> | undefined | null = props.rawData;
|
|
555
560
|
let totalRows = props.totalRows;
|
|
556
|
-
let sizeBytes = props.sizeBytes ?? null;
|
|
557
561
|
let cellStyles = props.cellStyles;
|
|
558
562
|
let cellHoverTexts = props.cellHoverTexts;
|
|
559
563
|
|
|
@@ -597,7 +601,6 @@ export const LoadingDataTableComponent = memo(
|
|
|
597
601
|
tableData = searchResults.data;
|
|
598
602
|
rawTableData = searchResults.raw_data;
|
|
599
603
|
totalRows = searchResults.total_rows;
|
|
600
|
-
sizeBytes = searchResults.size_bytes ?? null;
|
|
601
604
|
cellStyles = searchResults.cell_styles || {};
|
|
602
605
|
cellHoverTexts = searchResults.cell_hover_texts || {};
|
|
603
606
|
}
|
|
@@ -610,7 +613,6 @@ export const LoadingDataTableComponent = memo(
|
|
|
610
613
|
rows: tableData,
|
|
611
614
|
rawRows: rawData,
|
|
612
615
|
totalRows: totalRows,
|
|
613
|
-
sizeBytes,
|
|
614
616
|
cellStyles,
|
|
615
617
|
cellHoverTexts,
|
|
616
618
|
};
|
|
@@ -622,7 +624,6 @@ export const LoadingDataTableComponent = memo(
|
|
|
622
624
|
useDeepCompareMemoize(props.fieldTypes),
|
|
623
625
|
props.data,
|
|
624
626
|
props.totalRows,
|
|
625
|
-
props.sizeBytes,
|
|
626
627
|
props.lazy,
|
|
627
628
|
props.cellHoverTexts,
|
|
628
629
|
props.cellStyles,
|
|
@@ -630,6 +631,34 @@ export const LoadingDataTableComponent = memo(
|
|
|
630
631
|
paginationState.pageIndex,
|
|
631
632
|
]);
|
|
632
633
|
|
|
634
|
+
const policy = useAtomValue(downloadSizeLimitAtom);
|
|
635
|
+
const { data: sizeBytesData, isPending: sizeBytesPending } = useAsyncData<
|
|
636
|
+
number | null
|
|
637
|
+
>(async () => {
|
|
638
|
+
if (
|
|
639
|
+
!policy ||
|
|
640
|
+
!props.showDownload ||
|
|
641
|
+
props.lazy ||
|
|
642
|
+
props.totalRows === 0
|
|
643
|
+
) {
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
const result = await props.get_size_bytes({});
|
|
647
|
+
return result.size_bytes ?? null;
|
|
648
|
+
}, [
|
|
649
|
+
policy,
|
|
650
|
+
props.showDownload,
|
|
651
|
+
props.get_size_bytes,
|
|
652
|
+
props.lazy,
|
|
653
|
+
props.totalRows,
|
|
654
|
+
searchQuery,
|
|
655
|
+
useDeepCompareMemoize(filters),
|
|
656
|
+
useDeepCompareMemoize(sorting),
|
|
657
|
+
]);
|
|
658
|
+
const sizeBytes = sizeBytesData ?? null;
|
|
659
|
+
const sizeBytesIsLoading =
|
|
660
|
+
!!policy && props.showDownload && sizeBytesPending;
|
|
661
|
+
|
|
633
662
|
const getRow = useCallback(
|
|
634
663
|
async (rowId: number) => {
|
|
635
664
|
const sortArgs =
|
|
@@ -737,7 +766,8 @@ export const LoadingDataTableComponent = memo(
|
|
|
737
766
|
setFilters={setFilters}
|
|
738
767
|
reloading={isFetching && !isPending}
|
|
739
768
|
totalRows={data?.totalRows ?? props.totalRows}
|
|
740
|
-
sizeBytes={
|
|
769
|
+
sizeBytes={sizeBytes}
|
|
770
|
+
sizeBytesIsLoading={sizeBytesIsLoading}
|
|
741
771
|
paginationState={paginationState}
|
|
742
772
|
setPaginationState={setPaginationState}
|
|
743
773
|
cellStyles={data?.cellStyles ?? props.cellStyles}
|
|
@@ -785,6 +815,7 @@ const DataTableComponent = ({
|
|
|
785
815
|
rawData,
|
|
786
816
|
totalRows,
|
|
787
817
|
sizeBytes,
|
|
818
|
+
sizeBytesIsLoading,
|
|
788
819
|
maxColumns,
|
|
789
820
|
pagination,
|
|
790
821
|
selection,
|
|
@@ -814,6 +845,7 @@ const DataTableComponent = ({
|
|
|
814
845
|
reloading,
|
|
815
846
|
freezeColumnsLeft,
|
|
816
847
|
freezeColumnsRight,
|
|
848
|
+
hiddenColumns,
|
|
817
849
|
textJustifyColumns,
|
|
818
850
|
wrappedColumns,
|
|
819
851
|
headerTooltip,
|
|
@@ -835,6 +867,8 @@ const DataTableComponent = ({
|
|
|
835
867
|
rawData?: unknown[];
|
|
836
868
|
columnSummaries?: ColumnSummaries;
|
|
837
869
|
getRow: (rowIdx: number) => Promise<GetRowResult>;
|
|
870
|
+
sizeBytes?: number | null;
|
|
871
|
+
sizeBytesIsLoading?: boolean;
|
|
838
872
|
}): JSX.Element => {
|
|
839
873
|
const id = useId();
|
|
840
874
|
const [viewedRowIdx, setViewedRowIdx] = useState(0);
|
|
@@ -1007,6 +1041,52 @@ const DataTableComponent = ({
|
|
|
1007
1041
|
const isInVscode = isInVscodeExtension();
|
|
1008
1042
|
const isIslandsMode = isIslands();
|
|
1009
1043
|
|
|
1044
|
+
const renderTableExplorerPanel = useMemo(() => {
|
|
1045
|
+
if (!isAnyPanelOpen || !(showRowExplorer || canShowColumnExplorer)) {
|
|
1046
|
+
return undefined;
|
|
1047
|
+
}
|
|
1048
|
+
return (table: TanstackTable<unknown>) => (
|
|
1049
|
+
<ContextAwarePanelItem>
|
|
1050
|
+
<TableExplorerPanel
|
|
1051
|
+
rowIdx={viewedRowIdx}
|
|
1052
|
+
setRowIdx={setViewedRow}
|
|
1053
|
+
totalRows={totalRows}
|
|
1054
|
+
fieldTypes={memoizedUnclampedFieldTypes}
|
|
1055
|
+
getRow={getRow}
|
|
1056
|
+
isSelectable={isSelectable}
|
|
1057
|
+
isRowSelected={Boolean(rowSelection[viewedRowIdx])}
|
|
1058
|
+
handleRowSelectionChange={handleRowSelectionChange}
|
|
1059
|
+
previewColumn={preview_column}
|
|
1060
|
+
totalColumns={totalColumns}
|
|
1061
|
+
tableId={id}
|
|
1062
|
+
table={table}
|
|
1063
|
+
showRowExplorer={showRowExplorer && !isInVscode}
|
|
1064
|
+
showColumnExplorer={canShowColumnExplorer && !isInVscode}
|
|
1065
|
+
activeTab={panelType}
|
|
1066
|
+
onTabChange={setPanelType}
|
|
1067
|
+
/>
|
|
1068
|
+
</ContextAwarePanelItem>
|
|
1069
|
+
);
|
|
1070
|
+
}, [
|
|
1071
|
+
isAnyPanelOpen,
|
|
1072
|
+
showRowExplorer,
|
|
1073
|
+
canShowColumnExplorer,
|
|
1074
|
+
viewedRowIdx,
|
|
1075
|
+
setViewedRow,
|
|
1076
|
+
totalRows,
|
|
1077
|
+
memoizedUnclampedFieldTypes,
|
|
1078
|
+
getRow,
|
|
1079
|
+
isSelectable,
|
|
1080
|
+
rowSelection,
|
|
1081
|
+
handleRowSelectionChange,
|
|
1082
|
+
preview_column,
|
|
1083
|
+
totalColumns,
|
|
1084
|
+
id,
|
|
1085
|
+
isInVscode,
|
|
1086
|
+
panelType,
|
|
1087
|
+
setPanelType,
|
|
1088
|
+
]);
|
|
1089
|
+
|
|
1010
1090
|
return (
|
|
1011
1091
|
<>
|
|
1012
1092
|
{/* When the totalRows is "too_many" and the pageSize is the same as the
|
|
@@ -1032,28 +1112,6 @@ const DataTableComponent = ({
|
|
|
1032
1112
|
</Banner>
|
|
1033
1113
|
)}
|
|
1034
1114
|
|
|
1035
|
-
{isAnyPanelOpen && (showRowExplorer || canShowColumnExplorer) && (
|
|
1036
|
-
<ContextAwarePanelItem>
|
|
1037
|
-
<TableExplorerPanel
|
|
1038
|
-
rowIdx={viewedRowIdx}
|
|
1039
|
-
setRowIdx={setViewedRow}
|
|
1040
|
-
totalRows={totalRows}
|
|
1041
|
-
fieldTypes={memoizedUnclampedFieldTypes}
|
|
1042
|
-
getRow={getRow}
|
|
1043
|
-
isSelectable={isSelectable}
|
|
1044
|
-
isRowSelected={Boolean(rowSelection[viewedRowIdx])}
|
|
1045
|
-
handleRowSelectionChange={handleRowSelectionChange}
|
|
1046
|
-
previewColumn={preview_column}
|
|
1047
|
-
totalColumns={totalColumns}
|
|
1048
|
-
tableId={id}
|
|
1049
|
-
showRowExplorer={showRowExplorer && !isInVscode}
|
|
1050
|
-
showColumnExplorer={canShowColumnExplorer && !isInVscode}
|
|
1051
|
-
activeTab={panelType}
|
|
1052
|
-
onTabChange={setPanelType}
|
|
1053
|
-
/>
|
|
1054
|
-
</ContextAwarePanelItem>
|
|
1055
|
-
)}
|
|
1056
|
-
|
|
1057
1115
|
<ColumnChartContext value={chartSpecModel}>
|
|
1058
1116
|
<Labeled label={label} align="top" fullWidth={true}>
|
|
1059
1117
|
<DataTable
|
|
@@ -1065,6 +1123,7 @@ const DataTableComponent = ({
|
|
|
1065
1123
|
sorting={sorting}
|
|
1066
1124
|
totalRows={totalRows}
|
|
1067
1125
|
sizeBytes={sizeBytes}
|
|
1126
|
+
sizeBytesIsLoading={sizeBytesIsLoading}
|
|
1068
1127
|
totalColumns={totalColumns}
|
|
1069
1128
|
manualSorting={true}
|
|
1070
1129
|
setSorting={setSorting}
|
|
@@ -1090,6 +1149,7 @@ const DataTableComponent = ({
|
|
|
1090
1149
|
onRowSelectionChange={handleRowSelectionChange}
|
|
1091
1150
|
freezeColumnsLeft={freezeColumnsLeft}
|
|
1092
1151
|
freezeColumnsRight={freezeColumnsRight}
|
|
1152
|
+
hiddenColumns={hiddenColumns}
|
|
1093
1153
|
onCellSelectionChange={handleCellSelectionChange}
|
|
1094
1154
|
getRowIds={get_row_ids}
|
|
1095
1155
|
toggleDisplayHeader={toggleDisplayHeader}
|
|
@@ -1108,6 +1168,7 @@ const DataTableComponent = ({
|
|
|
1108
1168
|
isAnyPanelOpen={isAnyPanelOpen}
|
|
1109
1169
|
viewedRowIdx={viewedRowIdx}
|
|
1110
1170
|
onViewedRowChange={(rowIdx) => setViewedRowIdx(rowIdx)}
|
|
1171
|
+
renderTableExplorerPanel={renderTableExplorerPanel}
|
|
1111
1172
|
/>
|
|
1112
1173
|
</Labeled>
|
|
1113
1174
|
</ColumnChartContext>
|
|
@@ -107,6 +107,7 @@ describe("LoadingDataTableComponent", () => {
|
|
|
107
107
|
}),
|
|
108
108
|
get_data_url: vi.fn() as GetDataUrl,
|
|
109
109
|
get_row_ids: vi.fn() as GetRowIds,
|
|
110
|
+
get_size_bytes: vi.fn().mockResolvedValue({ size_bytes: null }),
|
|
110
111
|
};
|
|
111
112
|
|
|
112
113
|
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
@@ -64,7 +64,6 @@ type PluginFunctions = {
|
|
|
64
64
|
column_types_per_step: FieldTypesWithExternalType[];
|
|
65
65
|
python_code?: string | null;
|
|
66
66
|
sql_code?: string | null;
|
|
67
|
-
size_bytes?: number | null;
|
|
68
67
|
}>;
|
|
69
68
|
get_column_values: (req: { column: string }) => Promise<{
|
|
70
69
|
values: unknown[];
|
|
@@ -82,9 +81,11 @@ type PluginFunctions = {
|
|
|
82
81
|
}) => Promise<{
|
|
83
82
|
data: TableData<T>;
|
|
84
83
|
total_rows: number;
|
|
85
|
-
size_bytes?: number | null;
|
|
86
84
|
}>;
|
|
87
85
|
download_as: DownloadAsArgs;
|
|
86
|
+
get_size_bytes: (opts: Record<string, never>) => Promise<{
|
|
87
|
+
size_bytes?: number | null;
|
|
88
|
+
}>;
|
|
88
89
|
};
|
|
89
90
|
|
|
90
91
|
// Value is selection, but it is not currently exposed to the user
|
|
@@ -120,7 +121,6 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
120
121
|
column_types_per_step: z.array(columnToFieldTypesSchema),
|
|
121
122
|
python_code: z.string().nullish(),
|
|
122
123
|
sql_code: z.string().nullish(),
|
|
123
|
-
size_bytes: z.number().nullish(),
|
|
124
124
|
}),
|
|
125
125
|
),
|
|
126
126
|
get_column_values: rpc.input(z.object({ column: z.string() })).output(
|
|
@@ -150,10 +150,12 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
150
150
|
z.object({
|
|
151
151
|
data: z.union([z.string(), z.array(z.object({}).passthrough())]),
|
|
152
152
|
total_rows: z.number(),
|
|
153
|
-
size_bytes: z.number().nullish(),
|
|
154
153
|
}),
|
|
155
154
|
),
|
|
156
155
|
download_as: DownloadAsSchema,
|
|
156
|
+
get_size_bytes: rpc
|
|
157
|
+
.input(z.object({}))
|
|
158
|
+
.output(z.object({ size_bytes: z.number().nullish() })),
|
|
157
159
|
})
|
|
158
160
|
.renderer((props) => (
|
|
159
161
|
<TableProviders>
|
|
@@ -192,6 +194,7 @@ export const DataFrameComponent = memo(
|
|
|
192
194
|
get_column_values,
|
|
193
195
|
search,
|
|
194
196
|
download_as,
|
|
197
|
+
get_size_bytes,
|
|
195
198
|
host,
|
|
196
199
|
}: DataTableProps): JSX.Element => {
|
|
197
200
|
const { data, error, isPending } = useAsyncData(
|
|
@@ -207,7 +210,6 @@ export const DataFrameComponent = memo(
|
|
|
207
210
|
column_types_per_step,
|
|
208
211
|
python_code,
|
|
209
212
|
sql_code,
|
|
210
|
-
size_bytes,
|
|
211
213
|
} = data || {};
|
|
212
214
|
|
|
213
215
|
const totalColumns = field_types?.length;
|
|
@@ -327,7 +329,6 @@ export const DataFrameComponent = memo(
|
|
|
327
329
|
data={url || ""}
|
|
328
330
|
hasStableRowId={false}
|
|
329
331
|
totalRows={total_rows ?? 0}
|
|
330
|
-
sizeBytes={size_bytes ?? null}
|
|
331
332
|
totalColumns={totalColumns ?? 0}
|
|
332
333
|
maxColumns="all"
|
|
333
334
|
pageSize={pageSize}
|
|
@@ -336,6 +337,7 @@ export const DataFrameComponent = memo(
|
|
|
336
337
|
rowHeaders={row_headers || Arrays.EMPTY}
|
|
337
338
|
showDownload={showDownload}
|
|
338
339
|
download_as={download_as}
|
|
340
|
+
get_size_bytes={get_size_bytes}
|
|
339
341
|
enableSearch={false}
|
|
340
342
|
showFilters={false}
|
|
341
343
|
search={search}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
containsMangledLocal,
|
|
5
|
+
splitMangledLocals,
|
|
6
|
+
unmangleLocal,
|
|
7
|
+
} from "../local-variables";
|
|
8
|
+
|
|
9
|
+
describe("unmangleLocal", () => {
|
|
10
|
+
it("extracts the cell id and original name", () => {
|
|
11
|
+
expect(unmangleLocal("_cell_Hbol_a")).toEqual({
|
|
12
|
+
cellId: "Hbol",
|
|
13
|
+
name: "_a",
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("handles names with multiple underscore segments", () => {
|
|
18
|
+
expect(unmangleLocal("_cell_Hbol_a_b")).toEqual({
|
|
19
|
+
cellId: "Hbol",
|
|
20
|
+
name: "_a_b",
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("returns null for non-mangled strings", () => {
|
|
25
|
+
expect(unmangleLocal("just_a_variable")).toBeNull();
|
|
26
|
+
expect(unmangleLocal("_private")).toBeNull();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("handles the single-underscore local", () => {
|
|
30
|
+
// `_` is a valid local name (variables.py:62-63), mangling to
|
|
31
|
+
// `_cell_<id>_` with no trailing suffix.
|
|
32
|
+
expect(unmangleLocal("_cell_Hbol_")).toEqual({
|
|
33
|
+
cellId: "Hbol",
|
|
34
|
+
name: "_",
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("handles UUID-style cell ids", () => {
|
|
39
|
+
// External / VSCode notebooks use `external_prefix()` which is a
|
|
40
|
+
// `uuid4()` (hyphenated).
|
|
41
|
+
expect(
|
|
42
|
+
unmangleLocal("_cell_c9bf9e57-1685-4c89-bafb-ff5af830be8a_a"),
|
|
43
|
+
).toEqual({
|
|
44
|
+
cellId: "c9bf9e57-1685-4c89-bafb-ff5af830be8a",
|
|
45
|
+
name: "_a",
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("does not match marimo cell file paths", () => {
|
|
50
|
+
// The compiled cell file is `__marimo__cell_<id>_.py` (two leading
|
|
51
|
+
// underscores, trailing `_` with no name); it must not be confused with a
|
|
52
|
+
// mangled local.
|
|
53
|
+
expect(unmangleLocal("__marimo__cell_Hbol_.py")).toBeNull();
|
|
54
|
+
expect(unmangleLocal("/tmp/marimo_42/__marimo__cell_Hbol_.py")).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("splitMangledLocals", () => {
|
|
59
|
+
it("returns a single text segment when nothing matches", () => {
|
|
60
|
+
expect(splitMangledLocals("plain text")).toEqual(["plain text"]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("splits a NameError message", () => {
|
|
64
|
+
expect(splitMangledLocals("name '_cell_Hbol_a' is not defined")).toEqual([
|
|
65
|
+
"name '",
|
|
66
|
+
{ cellId: "Hbol", name: "_a" },
|
|
67
|
+
"' is not defined",
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("handles multiple mangled names in one string", () => {
|
|
72
|
+
expect(splitMangledLocals("_cell_AAAA_x and _cell_BBBB_y")).toEqual([
|
|
73
|
+
{ cellId: "AAAA", name: "_x" },
|
|
74
|
+
" and ",
|
|
75
|
+
{ cellId: "BBBB", name: "_y" },
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("leaves the cell file path alone", () => {
|
|
80
|
+
const path = "/tmp/marimo_42/__marimo__cell_Hbol_.py";
|
|
81
|
+
expect(splitMangledLocals(path)).toEqual([path]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("ignores `_cell_...` substrings preceded by `_`", () => {
|
|
85
|
+
// Mirrors `(?<!_)` in `variables.py`: a leading `_` (e.g. inside
|
|
86
|
+
// `__marimo__cell_<id>_<...>`) means this is not a mangle the compiler
|
|
87
|
+
// produced, so we must not demangle it.
|
|
88
|
+
const text = "see __marimo__cell_Hbol_a for details";
|
|
89
|
+
expect(splitMangledLocals(text)).toEqual([text]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("splits a UUID-style cell id", () => {
|
|
93
|
+
expect(
|
|
94
|
+
splitMangledLocals(
|
|
95
|
+
"name '_cell_c9bf9e57-1685-4c89-bafb-ff5af830be8a_a' is not defined",
|
|
96
|
+
),
|
|
97
|
+
).toEqual([
|
|
98
|
+
"name '",
|
|
99
|
+
{
|
|
100
|
+
cellId: "c9bf9e57-1685-4c89-bafb-ff5af830be8a",
|
|
101
|
+
name: "_a",
|
|
102
|
+
},
|
|
103
|
+
"' is not defined",
|
|
104
|
+
]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("splits the single-underscore local", () => {
|
|
108
|
+
expect(splitMangledLocals("name '_cell_Hbol_' is not defined")).toEqual([
|
|
109
|
+
"name '",
|
|
110
|
+
{ cellId: "Hbol", name: "_" },
|
|
111
|
+
"' is not defined",
|
|
112
|
+
]);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe("containsMangledLocal", () => {
|
|
117
|
+
it("detects mangled names", () => {
|
|
118
|
+
expect(containsMangledLocal("name '_cell_Hbol_a' is not defined")).toBe(
|
|
119
|
+
true,
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("ignores the cell file path", () => {
|
|
124
|
+
expect(containsMangledLocal("/tmp/marimo_42/__marimo__cell_Hbol_.py")).toBe(
|
|
125
|
+
false,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("ignores `_cell_...` substrings preceded by `_`", () => {
|
|
130
|
+
expect(containsMangledLocal("see __marimo__cell_Hbol_a")).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
});
|
package/src/utils/dates.ts
CHANGED
|
@@ -134,6 +134,45 @@ export function timeAgo(
|
|
|
134
134
|
return value.toString();
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
function pad2(n: number): string {
|
|
138
|
+
return n.toString().padStart(2, "0");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function pad4(n: number): string {
|
|
142
|
+
return n.toString().padStart(4, "0");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Format a Date as `YYYY-MM-DD` using the date's local-time fields.
|
|
147
|
+
*
|
|
148
|
+
* The output reflects what the user sees in their own timezone (the calendar
|
|
149
|
+
* day on their clock), not the UTC day. Use this when round-tripping values
|
|
150
|
+
* that originated from local-time inputs — date pickers, "filter on this
|
|
151
|
+
* day", calendar UI — so the displayed and serialized days agree.
|
|
152
|
+
*
|
|
153
|
+
* Not suitable for cross-timezone storage; use `Date.toISOString()` for that.
|
|
154
|
+
*/
|
|
155
|
+
export function dateToLocalISODate(d: Date): string {
|
|
156
|
+
return `${pad4(d.getFullYear())}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Format a Date as `HH:MM:SS` using the date's local-time fields.
|
|
161
|
+
*
|
|
162
|
+
* See `dateToLocalISODate` for the rationale on local vs UTC.
|
|
163
|
+
*/
|
|
164
|
+
export function dateToLocalISOTime(d: Date): string {
|
|
165
|
+
return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Format a Date as `YYYY-MM-DDTHH:MM:SS` (no timezone suffix) using local
|
|
170
|
+
* fields. See `dateToLocalISODate` for the rationale on local vs UTC.
|
|
171
|
+
*/
|
|
172
|
+
export function dateToLocalISODateTime(d: Date): string {
|
|
173
|
+
return `${dateToLocalISODate(d)}T${dateToLocalISOTime(d)}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
137
176
|
export const supportedDateFormats = ["yyyy", "yyyy-MM", "yyyy-MM-dd"] as const;
|
|
138
177
|
export type DateFormat = (typeof supportedDateFormats)[number];
|
|
139
178
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import type { CellId } from "@/core/cells/ids";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The marimo compiler rewrites underscore-prefixed references inside a cell
|
|
6
|
+
* (which Python would treat as module-private) into `_cell_<cell_id>_<name>`
|
|
7
|
+
* so each cell gets its own private namespace. When such a reference fails at
|
|
8
|
+
* runtime (`NameError: name '_cell_Hbol_a' is not defined`), the mangled name
|
|
9
|
+
* leaks into the error UI. These helpers undo that mangling for display.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `marimo/_ast/variables.py`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// Matches `_cell_<cell_id><name>` for normal ids and UUIDs. The `[\w-]`
|
|
15
|
+
// id class admits hyphens; the `_\w*` name group admits the bare `_`
|
|
16
|
+
// local; the `(?<!_)` lookbehind skips `__marimo__cell_...` paths.
|
|
17
|
+
// Mirrors `_MANGLED_LOCAL_IN_TEXT_RE` in `variables.py`.
|
|
18
|
+
const MANGLED_LOCAL_BODY = String.raw`_cell_([^\W_][\w-]*?)(_\w*)`;
|
|
19
|
+
const MANGLED_LOCAL_PATTERN = String.raw`(?<!_)${MANGLED_LOCAL_BODY}`;
|
|
20
|
+
// Strict (whole-string) form for `unmangleLocal`; the leading `^` makes the
|
|
21
|
+
// lookbehind trivially satisfied, so use the bare body.
|
|
22
|
+
const ANCHORED_RE = new RegExp(`^${MANGLED_LOCAL_BODY}$`);
|
|
23
|
+
const UNANCHORED_RE = new RegExp(MANGLED_LOCAL_PATTERN);
|
|
24
|
+
const GLOBAL_RE = new RegExp(MANGLED_LOCAL_PATTERN, "g");
|
|
25
|
+
|
|
26
|
+
export interface UnmangledLocal {
|
|
27
|
+
cellId: CellId;
|
|
28
|
+
/** The original underscore-prefixed name, e.g. "_a". */
|
|
29
|
+
name: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function unmangleLocal(mangled: string): UnmangledLocal | null {
|
|
33
|
+
const match = ANCHORED_RE.exec(mangled);
|
|
34
|
+
if (!match) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return { cellId: match[1] as CellId, name: match[2] };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type MangledSegment = string | UnmangledLocal;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Split a plain text string into alternating literal text and unmangled-local
|
|
44
|
+
* segments, so callers can render mixed React content.
|
|
45
|
+
*/
|
|
46
|
+
export function splitMangledLocals(text: string): MangledSegment[] {
|
|
47
|
+
const segments: MangledSegment[] = [];
|
|
48
|
+
GLOBAL_RE.lastIndex = 0;
|
|
49
|
+
let lastIndex = 0;
|
|
50
|
+
let match: RegExpExecArray | null = GLOBAL_RE.exec(text);
|
|
51
|
+
while (match !== null) {
|
|
52
|
+
if (match.index > lastIndex) {
|
|
53
|
+
segments.push(text.slice(lastIndex, match.index));
|
|
54
|
+
}
|
|
55
|
+
segments.push({ cellId: match[1] as CellId, name: match[2] });
|
|
56
|
+
lastIndex = match.index + match[0].length;
|
|
57
|
+
match = GLOBAL_RE.exec(text);
|
|
58
|
+
}
|
|
59
|
+
if (lastIndex < text.length) {
|
|
60
|
+
segments.push(text.slice(lastIndex));
|
|
61
|
+
}
|
|
62
|
+
return segments;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function containsMangledLocal(text: string): boolean {
|
|
66
|
+
return UNANCHORED_RE.test(text);
|
|
67
|
+
}
|