@marimo-team/frontend 0.16.0 → 0.16.2
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 +19 -0
- package/dist/assets/{ImageComparisonComponent-fTHv1Ih0.js → ImageComparisonComponent-CqR26LSv.js} +1 -1
- package/dist/assets/{VegaLite-Bdi-TyfY.js → VegaLite-DvQDATwI.js} +1 -1
- package/dist/assets/_baseEach--KDTwKbG.js +1 -0
- package/dist/assets/_baseMap-Cu3o-eyO.js +1 -0
- package/dist/assets/{_baseUniq-CCgDNtZb.js → _baseUniq-y7ZXnMo1.js} +1 -1
- package/dist/assets/{_createAggregator-DcD0kTA5.js → _createAggregator-ZcHkHPNJ.js} +1 -1
- package/dist/assets/{agent-panel-Crv430aI.js → agent-panel-B91RoLct.js} +76 -57
- package/dist/assets/{any-language-editor-CQh552Wu.js → any-language-editor-CxfHcm5h.js} +1 -1
- package/dist/assets/{architectureDiagram-W76B3OCA-BAJeBxzt.js → architectureDiagram-W76B3OCA-BQsvK8uR.js} +1 -1
- package/dist/assets/{between-horizontal-start-Boxgxbt_.js → between-horizontal-start-BmYToIaM.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-CL-1svEK.js → blockDiagram-QIGZ2CNN-r3HgCj4w.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-BbEqbCTl.js → c4Diagram-FPNF74CW-BJbPNt41.js} +1 -1
- package/dist/assets/channel-DFaEx1fu.js +1 -0
- package/dist/assets/chat-panel-IoPMv8e2.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-C--8TXeE.js → chunk-4BX2VUAB-Dv4MZ9Hj.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-Bj00HDqq.js → chunk-55IACEB6-CM4AHquB.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-C-lhB6hN.js → chunk-FMBD7UC4-C_Zz0ENB.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-B-pGTXPt.js → chunk-K7UQS3LO-DYSmiXYq.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-DqUzGhvm.js → chunk-QN33PNHL-QM4OPuQP.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-TntJHfSk.js → chunk-QZHKN3VN-CfAsGyeB.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-HUJb1psV.js → chunk-TVAH2DTR-6j_Cpjsi.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-BK3C__t3.js → chunk-TZMSLE5B-BHslFJQE.js} +1 -1
- package/dist/assets/{circle-play-DBLOv1Yu.js → circle-play-CK3UZRYQ.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-BsZtvV5O.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-BsZtvV5O.js +1 -0
- package/dist/assets/{clear-button-BeoFbEKH.js → clear-button-C4fDVSv8.js} +1 -1
- package/dist/assets/clone-YBEvPE-s.js +1 -0
- package/dist/assets/command-palette-D7hOfvf6.js +1 -0
- package/dist/assets/{common-C7oJcmCT.js → common-D-lbuUwz.js} +1 -1
- package/dist/assets/{compile-7L0MwhyI.js → compile-DVQe1Mzk.js} +1 -1
- package/dist/assets/{cose-bilkent-S5V4N54A-BMkGLcVC.js → cose-bilkent-S5V4N54A-D-IS7WC8.js} +1 -1
- package/dist/assets/{dagre-5GWH7T2D-BJtRienS.js → dagre-5GWH7T2D-lYu-tEWT.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-DBkmGtNs.js → data-grid-overlay-editor-C5peOCit.js} +1 -1
- package/dist/assets/datasources-panel-D3NA20uZ.js +1 -0
- package/dist/assets/{dependency-graph-panel-DEdOxp2X.js → dependency-graph-panel-BGVYOfkV.js} +1 -1
- package/dist/assets/{diagram-N5W7TBWH-CmECY3nb.js → diagram-N5W7TBWH-BnvIuYUp.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-DMOVSNKD.js → diagram-QEK2KX5R-DemedRK3.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-BiJ96PNQ.js → diagram-S2PKOQOG-iiY7AuyH.js} +1 -1
- package/dist/assets/{documentation-panel-xULhaEv3.js → documentation-panel-C3dSwOSQ.js} +1 -1
- package/dist/assets/edit-page-C5TsEeSo.js +129 -0
- package/dist/assets/{ellipsis-vertical-BBqXIlc2.js → ellipsis-vertical-CazJl8M7.js} +1 -1
- package/dist/assets/{empty-state-B3dA3G5P.js → empty-state-DW308mFO.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-MP1DiFRo.js → erDiagram-AWTI2OKA-6wQ8Ugg0.js} +1 -1
- package/dist/assets/{error-panel-Cc1sv-Ag.js → error-panel-D1VnJ1yP.js} +1 -1
- package/dist/assets/file-explorer-panel-0oVd4t-D.js +1 -0
- package/dist/assets/{flowDiagram-PVAE7QVJ-BX7caPp7.js → flowDiagram-PVAE7QVJ-C55IUWjm.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-B462g4Yf.js → ganttDiagram-OWAHRB6G-DmqCM6ME.js} +4 -4
- package/dist/assets/{gitGraphDiagram-NY62KEGX-CGgvZ9-9.js → gitGraphDiagram-NY62KEGX-DBvhAeM_.js} +1 -1
- package/dist/assets/{glide-data-editor-C0gUFZON.js → glide-data-editor-CHNuHidQ.js} +4 -4
- package/dist/assets/{graph-CHRVBzY5.js → graph-CG6BgUWQ.js} +1 -1
- package/dist/assets/home-page-dgivXuSR.js +9 -0
- package/dist/assets/{index-Clbi_Yaq.js → index-BTGpssVX.js} +1 -1
- package/dist/assets/{index-CQDrxQ0j.js → index-BYVZlBF8.js} +1 -1
- package/dist/assets/{index-lYa_leQE.js → index-BelfnXwL.js} +1 -1
- package/dist/assets/{index-DRMm6SNo.js → index-BneyUujp.js} +1 -1
- package/dist/assets/{index-BY93Ejhl.js → index-C02SqeRj.js} +1 -1
- package/dist/assets/{index-C-8WADat.js → index-C7dtgr9A.js} +1 -1
- package/dist/assets/{index-D9UKkrr2.js → index-CAQvMTzM.js} +1 -1
- package/dist/assets/index-CGDMlQfO.css +1 -0
- package/dist/assets/index-CelXfcd8.js +580 -0
- package/dist/assets/{index-vmICa5KN.js → index-Csd6QrCV.js} +1 -1
- package/dist/assets/{index-DoRmcrKM.js → index-CtPksxf0.js} +1 -1
- package/dist/assets/{index-C1v_Z9et.js → index-Cxyk7pt-.js} +1 -1
- package/dist/assets/{index-CpTPJo4k.js → index-DAZ-9ri2.js} +1 -1
- package/dist/assets/{index-DEQvTChO.js → index-DONRrmA2.js} +1 -1
- package/dist/assets/{index-C4Tn5NvJ.js → index-Db36XTG_.js} +1 -1
- package/dist/assets/{index-z9bohSQJ.js → index-DdIhdEVw.js} +1 -1
- package/dist/assets/{index-C-GhZ7ti.js → index-M_pBKDSe.js} +1 -1
- package/dist/assets/{index-C77h_TXN.js → index-_luCZMLM.js} +1 -1
- package/dist/assets/{index-D1vmG6DS.js → index-mkubqy9-.js} +1 -1
- package/dist/assets/{index-BVgAenPd.js → index-sbO9UaUU.js} +1 -1
- package/dist/assets/{index-CWMgowgL.js → index-z4krxQ4j.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-wTALjfPc.js +2 -0
- package/dist/assets/{isEmpty-DU_ogP_D.js → isEmpty-CqX_YTIf.js} +1 -1
- package/dist/assets/{journeyDiagram-BIP6EPQ6-C6EgLP_Q.js → journeyDiagram-BIP6EPQ6-Y5w_Tqe_.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-BXzYO1yj.js → kanban-definition-6OIFK2YF-DbXs5Rxi.js} +1 -1
- package/dist/assets/{layout-jihVw5-i.js → layout-BCNPDACj.js} +1 -1
- package/dist/assets/{linear-C4blANlC.js → linear-uO6UVhXt.js} +1 -1
- package/dist/assets/links-Drv7cJgN.js +7 -0
- package/dist/assets/{logs-panel-D401qzZh.js → logs-panel-BEQ1eRUp.js} +1 -1
- package/dist/assets/{markdown-renderer-Cd9eYyaL.js → markdown-renderer-Dmzbb00W.js} +20 -20
- package/dist/assets/{mermaid-BEVuRz_O.js → mermaid-qRc4MXIj.js} +1 -1
- package/dist/assets/{mermaid.core-CaSnaLH0.js → mermaid.core-CvvJtCRj.js} +4 -4
- package/dist/assets/min-DYUOb1RR.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-BXUM5MT2.js → mindmap-definition-Q6HEUPPD-G5NognM-.js} +1 -1
- package/dist/assets/{number-overlay-editor-4uWXGlPG.js → number-overlay-editor-DPr5sHFu.js} +1 -1
- package/dist/assets/outline-panel-gxQXvVi4.js +1 -0
- package/dist/assets/{packages-panel-CJL0MVlj.js → packages-panel-B1T0VPlg.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-Dxt5PVNo.js → pieDiagram-ADFJNKIX-DK9SHkfc.js} +1 -1
- package/dist/assets/{quadrantDiagram-LMRXKWRM-D4pUaA31.js → quadrantDiagram-LMRXKWRM-D1DdWF8C.js} +1 -1
- package/dist/assets/{react-plotly-cJZ0VWBq.js → react-plotly-CTwajqCb.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-DVRTjgas.js → requirementDiagram-4UW4RH46-DnjDAypr.js} +1 -1
- package/dist/assets/{run-page-BUEnMC9w.js → run-page-CQY9im22.js} +1 -1
- package/dist/assets/{sankeyDiagram-GR3RE2ED-CVFnD9C-.js → sankeyDiagram-GR3RE2ED-B67Va-ER.js} +1 -1
- package/dist/assets/{scratchpad-panel-BIgRENkI.js → scratchpad-panel-DlDfcDtW.js} +1 -1
- package/dist/assets/{secrets-panel-xY5-V_BD.js → secrets-panel-BDGyuGZA.js} +1 -1
- package/dist/assets/{sequenceDiagram-C3RYC4MD-_lY4ZN_S.js → sequenceDiagram-C3RYC4MD-DiWgZPtN.js} +1 -1
- package/dist/assets/{slides-component-DMjQomc3.css → slides-component-C-LoGC1U.css} +1 -1
- package/dist/assets/{slides-component-Xjymwj7X.js → slides-component-DhpPRtQp.js} +1 -1
- package/dist/assets/snippets-panel-CLkBXhJ2.js +1 -0
- package/dist/assets/sortBy-D4OG7w4O.js +1 -0
- package/dist/assets/{state-C4NiC9tO.js → state-Dz_3JyED.js} +1 -1
- package/dist/assets/{stateDiagram-KXAO66HF-Da0JQWCn.js → stateDiagram-KXAO66HF-ByF2AULw.js} +1 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-CtBJqosP.js +1 -0
- package/dist/assets/storage-Dr0CC44z.js +26 -0
- package/dist/assets/{terminal-BPwTkXae.js → terminal-BtdissBf.js} +1 -1
- package/dist/assets/{time-Dv5_Ouz_.js → time-DKdOTnQg.js} +1 -1
- package/dist/assets/{timeline-definition-XQNQX7LJ-Dxh5Zu2e.js → timeline-definition-XQNQX7LJ-DzER9bf6.js} +1 -1
- package/dist/assets/tracing-Dpx5M-u3.js +2 -0
- package/dist/assets/{tracing-panel-DAzrzNmm.js → tracing-panel-hCjBkSER.js} +2 -2
- package/dist/assets/{trash-Dc6DSjz_.js → trash-C6Ko-g5q.js} +1 -1
- package/dist/assets/{tree-jheoerAX.js → tree-BHN2gcCF.js} +6 -6
- package/dist/assets/{treemap-75Q7IDZK-IgpxeGaf.js → treemap-75Q7IDZK-DR79Mhzt.js} +27 -27
- package/dist/assets/variable-panel-PFBCFz36.js +1 -0
- package/dist/assets/{vega-component-BpfpiPKI.js → vega-component-Db6-uY4C.js} +1 -1
- package/dist/assets/worker-fHbtoWvT.js +1 -0
- package/dist/assets/{xychartDiagram-6GGTOJPD-CmNigJ31.js → xychartDiagram-6GGTOJPD-DWzBP3tZ.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +5 -4
- package/src/__mocks__/requests.ts +1 -0
- package/src/components/app-config/user-config-form.tsx +46 -1
- package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +62 -43
- package/src/components/chat/acp/__tests__/atoms.test.ts +1 -1
- package/src/components/chat/acp/__tests__/state.test.ts +36 -36
- package/src/components/chat/acp/agent-panel.tsx +24 -27
- package/src/components/chat/acp/blocks.tsx +6 -6
- package/src/components/chat/acp/prompt.ts +62 -43
- package/src/components/chat/chat-panel.tsx +5 -1
- package/src/components/chat/markdown-renderer.tsx +6 -10
- package/src/components/chat/tool-call-accordion.tsx +52 -20
- package/src/components/data-table/SearchBar.tsx +8 -7
- package/src/components/data-table/__tests__/column_formatting.test.ts +50 -35
- package/src/components/data-table/__tests__/columns.test.tsx +38 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +39 -1
- package/src/components/data-table/cell-hover-template/feature.ts +14 -0
- package/src/components/data-table/cell-hover-template/types.ts +11 -0
- package/src/components/data-table/charts/components/form-fields.tsx +41 -37
- package/src/components/data-table/charts/forms/common-chart.tsx +2 -2
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +5 -2
- package/src/components/data-table/column-formatting/feature.ts +62 -29
- package/src/components/data-table/column-formatting/types.ts +1 -0
- package/src/components/data-table/column-header.tsx +3 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +24 -7
- package/src/components/data-table/column-summary/column-summary.tsx +18 -9
- package/src/components/data-table/columns.tsx +63 -20
- package/src/components/data-table/data-table.tsx +10 -2
- package/src/components/data-table/date-popover.tsx +85 -75
- package/src/components/data-table/filter-pills.tsx +14 -9
- package/src/components/data-table/header-items.tsx +5 -1
- package/src/components/data-table/pagination.tsx +20 -13
- package/src/components/data-table/renderers.tsx +36 -0
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +10 -8
- package/src/components/data-table/schemas.ts +16 -0
- package/src/components/datasources/column-preview.tsx +6 -2
- package/src/components/datasources/datasources.tsx +8 -12
- package/src/components/editor/Cell.tsx +2 -0
- package/src/components/editor/ai/transport/chat-transport.tsx +4 -1
- package/src/components/editor/cell/CellStatus.tsx +23 -20
- package/src/components/editor/cell/CreateCellButton.tsx +3 -4
- package/src/components/editor/cell/code/language-toggle.tsx +3 -4
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +39 -28
- package/src/components/editor/controls/notebook-menu-dropdown.tsx +4 -2
- package/src/components/editor/errors/sql-validation-errors.tsx +34 -0
- package/src/components/editor/file-tree/requesting-tree.tsx +14 -8
- package/src/components/editor/output/ConsoleOutput.tsx +13 -1
- package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
- package/src/components/editor/renderers/CellArray.tsx +3 -4
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +3 -3
- package/src/components/editor/renderers/slides-layout/types.ts +1 -0
- package/src/components/pages/home-page.tsx +4 -1
- package/src/components/slides/slides-component.tsx +1 -1
- package/src/components/slides/slides.css +6 -0
- package/src/components/terminal/theme.tsx +1 -0
- package/src/components/tracing/tracing-spec.ts +5 -4
- package/src/components/ui/range-slider.tsx +4 -2
- package/src/components/ui/slider.tsx +3 -1
- package/src/components/variables/variables-table.tsx +3 -0
- package/src/core/MarimoApp.tsx +9 -6
- package/src/core/ai/context/__tests__/registry.test.ts +6 -4
- package/src/core/ai/context/providers/cell-output.ts +4 -20
- package/src/core/ai/context/providers/error.ts +3 -1
- package/src/core/ai/context/providers/file.ts +7 -2
- package/src/core/ai/context/providers/tables.ts +3 -2
- package/src/core/ai/context/providers/variable.ts +6 -4
- package/src/core/ai/staged-cells.ts +34 -1
- package/src/core/cells/__tests__/add-missing-import.test.ts +67 -22
- package/src/core/cells/add-missing-import.ts +24 -7
- package/src/core/cells/cells.ts +26 -27
- package/src/core/cells/logs.ts +1 -1
- package/src/core/codemirror/find-replace/search-highlight.ts +3 -1
- package/src/core/codemirror/language/LanguageAdapters.ts +9 -3
- package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
- package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
- package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
- package/src/core/codemirror/language/languages/sql/sql.ts +90 -3
- package/src/core/codemirror/language/languages/sql/validation-errors.ts +79 -0
- package/src/core/codemirror/language/panel/panel.tsx +8 -2
- package/src/core/codemirror/language/panel/sql.tsx +81 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +8 -2
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/rtc/loro/awareness.ts +52 -17
- package/src/core/codemirror/rtc/loro/sync.ts +12 -4
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/config.ts +4 -0
- package/src/core/config/feature-flag.tsx +3 -1
- package/src/core/datasets/request-registry.ts +17 -1
- package/src/core/hotkeys/hotkeys.ts +8 -4
- package/src/core/i18n/__tests__/locale-provider.test.tsx +176 -0
- package/src/core/i18n/locale-provider.tsx +35 -0
- package/src/core/i18n/with-locale.tsx +12 -0
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/islands/components/web-components.tsx +13 -10
- package/src/core/islands/main.ts +1 -0
- package/src/core/kernel/RuntimeState.ts +4 -1
- package/src/core/kernel/messages.ts +3 -2
- package/src/core/network/DeferredRequestRegistry.ts +16 -4
- package/src/core/network/requests-network.ts +7 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.ts +1 -0
- package/src/core/network/types.ts +2 -0
- package/src/core/runtime/runtime.ts +5 -4
- package/src/core/wasm/bridge.ts +10 -1
- package/src/core/wasm/store.ts +4 -1
- package/src/core/wasm/worker/message-buffer.ts +3 -2
- package/src/core/websocket/types.ts +22 -16
- package/src/core/websocket/useMarimoWebSocket.tsx +4 -0
- package/src/hooks/useFormatting.ts +97 -0
- package/src/hooks/useTimer.ts +8 -5
- package/src/plugins/core/registerReactComponent.tsx +39 -29
- package/src/plugins/impl/DataTablePlugin.tsx +15 -4
- package/src/plugins/impl/RangeSliderPlugin.tsx +5 -3
- package/src/plugins/impl/SliderPlugin.tsx +3 -1
- package/src/plugins/impl/anywidget/model.ts +16 -5
- package/src/plugins/impl/data-editor/types.ts +7 -5
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +20 -13
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
- package/src/plugins/impl/panel/utils.ts +6 -4
- package/src/plugins/layout/OutlinePlugin.tsx +69 -0
- package/src/plugins/layout/StatPlugin.tsx +4 -1
- package/src/plugins/plugins.ts +2 -0
- package/src/stories/dataframe.stories.tsx +2 -0
- package/src/utils/__tests__/dates.test.ts +45 -24
- package/src/utils/__tests__/dom.test.ts +167 -0
- package/src/utils/__tests__/numbers.test.ts +42 -30
- package/src/utils/__tests__/once.test.ts +187 -0
- package/src/utils/dates.ts +15 -10
- package/src/utils/dom.ts +55 -0
- package/src/utils/edit-distance.ts +8 -6
- package/src/utils/errors.ts +1 -1
- package/src/utils/id-tree.tsx +21 -10
- package/src/utils/localStorage.ts +13 -4
- package/src/utils/numbers.ts +11 -11
- package/src/utils/once.ts +32 -0
- package/src/utils/paths.ts +4 -1
- package/src/utils/pluralize.ts +12 -5
- package/src/utils/python-poet/poet.ts +30 -15
- package/src/utils/time.ts +5 -1
- package/dist/assets/ConnectedDataExplorerComponent-BErMbWvG.js +0 -19
- package/dist/assets/_baseEach-CNBxBxvS.js +0 -1
- package/dist/assets/_baseMap-D1WHjKrd.js +0 -1
- package/dist/assets/channel-_2eNSz0n.js +0 -1
- package/dist/assets/chat-panel-CXh5Wl6C.js +0 -3
- package/dist/assets/classDiagram-KNZD7YFC-BGmh9POF.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-BGmh9POF.js +0 -1
- package/dist/assets/clone-BFDSPAj3.js +0 -1
- package/dist/assets/command-palette-CXZiSv0I.js +0 -1
- package/dist/assets/datasources-panel-B7FbYLiy.js +0 -1
- package/dist/assets/edit-page-BrYda9VE.js +0 -129
- package/dist/assets/file-explorer-panel-Bw59Kva1.js +0 -1
- package/dist/assets/home-page-Fb2osjys.js +0 -9
- package/dist/assets/index-Cx0bsY1w.css +0 -1
- package/dist/assets/index-DKEudB02.js +0 -578
- package/dist/assets/infoDiagram-STP46IZ2-CVyrdLc8.js +0 -2
- package/dist/assets/links-D59GIweI.js +0 -7
- package/dist/assets/min-DUMu_zeK.js +0 -1
- package/dist/assets/outline-panel-DIzkvm2I.js +0 -1
- package/dist/assets/snippets-panel-CTPYW41n.js +0 -1
- package/dist/assets/sortBy-BNZKwiq_.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-D5lYZOOt.js +0 -1
- package/dist/assets/storage-CMdLzB_c.js +0 -26
- package/dist/assets/tracing-BCIurUfa.js +0 -2
- package/dist/assets/variable-panel-DYAiLBmF.js +0 -1
- package/dist/assets/worker-X5rxzQGQ.js +0 -1
|
@@ -36,6 +36,10 @@ import {
|
|
|
36
36
|
import { usePanelOwnership } from "@/components/data-table/hooks/use-panel-ownership";
|
|
37
37
|
import { LoadingTable } from "@/components/data-table/loading-table";
|
|
38
38
|
import { RowViewerPanel } from "@/components/data-table/row-viewer-panel/row-viewer";
|
|
39
|
+
import {
|
|
40
|
+
type DownloadAsArgs,
|
|
41
|
+
DownloadAsSchema,
|
|
42
|
+
} from "@/components/data-table/schemas";
|
|
39
43
|
import {
|
|
40
44
|
type BinValues,
|
|
41
45
|
type ColumnHeaderStats,
|
|
@@ -182,6 +186,7 @@ interface Data<T> {
|
|
|
182
186
|
freezeColumnsRight?: string[];
|
|
183
187
|
textJustifyColumns?: Record<string, "left" | "center" | "right">;
|
|
184
188
|
wrappedColumns?: string[];
|
|
189
|
+
headerTooltip?: Record<string, string>;
|
|
185
190
|
totalColumns: number;
|
|
186
191
|
maxColumns: number | "all";
|
|
187
192
|
hasStableRowId: boolean;
|
|
@@ -190,7 +195,7 @@ interface Data<T> {
|
|
|
190
195
|
|
|
191
196
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
192
197
|
type DataTableFunctions = {
|
|
193
|
-
download_as:
|
|
198
|
+
download_as: DownloadAsArgs;
|
|
194
199
|
get_column_summaries: <T>(
|
|
195
200
|
opts: ColumnSummariesArgs,
|
|
196
201
|
) => Promise<ColumnSummaries<T>>;
|
|
@@ -249,11 +254,13 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
249
254
|
.record(z.enum(["left", "center", "right"]))
|
|
250
255
|
.optional(),
|
|
251
256
|
wrappedColumns: z.array(z.string()).optional(),
|
|
257
|
+
headerTooltip: z.record(z.string()).optional(),
|
|
252
258
|
fieldTypes: columnToFieldTypesSchema.nullish(),
|
|
253
259
|
totalColumns: z.number(),
|
|
254
260
|
maxColumns: z.union([z.number(), z.literal("all")]).default("all"),
|
|
255
261
|
hasStableRowId: z.boolean().default(false),
|
|
256
262
|
cellStyles: z.record(z.record(z.object({}).passthrough())).optional(),
|
|
263
|
+
hoverTemplate: z.string().optional(),
|
|
257
264
|
// Whether to load the data lazily.
|
|
258
265
|
lazy: z.boolean().default(false),
|
|
259
266
|
// If lazy, this will preload the first page of data
|
|
@@ -262,9 +269,7 @@ export const DataTablePlugin = createPlugin<S>("marimo-table")
|
|
|
262
269
|
}),
|
|
263
270
|
)
|
|
264
271
|
.withFunctions<DataTableFunctions>({
|
|
265
|
-
download_as:
|
|
266
|
-
.input(z.object({ format: z.enum(["csv", "json", "parquet"]) }))
|
|
267
|
-
.output(z.string()),
|
|
272
|
+
download_as: DownloadAsSchema,
|
|
268
273
|
get_column_summaries: rpc
|
|
269
274
|
.input(z.object({ precompute: z.boolean() }))
|
|
270
275
|
.output(
|
|
@@ -385,6 +390,7 @@ interface DataTableProps<T> extends Data<T>, DataTableFunctions {
|
|
|
385
390
|
// Filters
|
|
386
391
|
enableFilters?: boolean;
|
|
387
392
|
cellStyles?: CellStyleState | null;
|
|
393
|
+
hoverTemplate?: string | null;
|
|
388
394
|
toggleDisplayHeader?: () => void;
|
|
389
395
|
host: HTMLElement;
|
|
390
396
|
cellId?: CellId | null;
|
|
@@ -704,9 +710,11 @@ const DataTableComponent = ({
|
|
|
704
710
|
freezeColumnsRight,
|
|
705
711
|
textJustifyColumns,
|
|
706
712
|
wrappedColumns,
|
|
713
|
+
headerTooltip,
|
|
707
714
|
totalColumns,
|
|
708
715
|
get_row_ids,
|
|
709
716
|
cellStyles,
|
|
717
|
+
hoverTemplate,
|
|
710
718
|
toggleDisplayHeader,
|
|
711
719
|
calculate_top_k_rows,
|
|
712
720
|
preview_column,
|
|
@@ -776,6 +784,7 @@ const DataTableComponent = ({
|
|
|
776
784
|
fieldTypes: memoizedClampedFieldTypes,
|
|
777
785
|
textJustifyColumns: memoizedTextJustifyColumns,
|
|
778
786
|
wrappedColumns: memoizedWrappedColumns,
|
|
787
|
+
headerTooltip: headerTooltip,
|
|
779
788
|
// Only show data types if they are explicitly set
|
|
780
789
|
showDataTypes: showDataTypes,
|
|
781
790
|
calculateTopKRows: calculate_top_k_rows,
|
|
@@ -788,6 +797,7 @@ const DataTableComponent = ({
|
|
|
788
797
|
memoizedClampedFieldTypes,
|
|
789
798
|
memoizedTextJustifyColumns,
|
|
790
799
|
memoizedWrappedColumns,
|
|
800
|
+
headerTooltip,
|
|
791
801
|
calculate_top_k_rows,
|
|
792
802
|
],
|
|
793
803
|
);
|
|
@@ -904,6 +914,7 @@ const DataTableComponent = ({
|
|
|
904
914
|
rowSelection={rowSelection}
|
|
905
915
|
cellSelection={cellSelection}
|
|
906
916
|
cellStyling={cellStyles}
|
|
917
|
+
hoverTemplate={hoverTemplate}
|
|
907
918
|
downloadAs={showDownload ? downloadAs : undefined}
|
|
908
919
|
enableSearch={enableSearch}
|
|
909
920
|
searchQuery={searchQuery}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { isEqual } from "lodash-es";
|
|
4
4
|
import { type JSX, useEffect, useId, useState } from "react";
|
|
5
|
+
import { useLocale } from "react-aria";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import { cn } from "@/utils/cn";
|
|
7
8
|
import { prettyScientificNumber } from "@/utils/numbers";
|
|
@@ -82,6 +83,7 @@ const RangeSliderComponent = ({
|
|
|
82
83
|
valueMap,
|
|
83
84
|
}: RangeSliderProps): JSX.Element => {
|
|
84
85
|
const id = useId();
|
|
86
|
+
const { locale } = useLocale();
|
|
85
87
|
|
|
86
88
|
// Hold internal value
|
|
87
89
|
const [internalValue, setInternalValue] = useState(value);
|
|
@@ -150,9 +152,9 @@ const RangeSliderComponent = ({
|
|
|
150
152
|
/>
|
|
151
153
|
{showValue && (
|
|
152
154
|
<div className="text-xs text-muted-foreground min-w-[16px]">
|
|
153
|
-
{`${prettyScientificNumber(
|
|
154
|
-
|
|
155
|
-
)}, ${prettyScientificNumber(valueMap(internalValue[1]))}`}
|
|
155
|
+
{`${prettyScientificNumber(valueMap(internalValue[0]), {
|
|
156
|
+
locale,
|
|
157
|
+
})}, ${prettyScientificNumber(valueMap(internalValue[1]), { locale })}`}
|
|
156
158
|
</div>
|
|
157
159
|
)}
|
|
158
160
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
import { type JSX, useEffect, useId, useState } from "react";
|
|
3
|
+
import { useLocale } from "react-aria";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
import { NumberField } from "@/components/ui/number-field";
|
|
5
6
|
import { cn } from "@/utils/cn";
|
|
@@ -85,6 +86,7 @@ const SliderComponent = ({
|
|
|
85
86
|
disabled,
|
|
86
87
|
}: SliderProps): JSX.Element => {
|
|
87
88
|
const id = useId();
|
|
89
|
+
const { locale } = useLocale();
|
|
88
90
|
|
|
89
91
|
// Hold internal value
|
|
90
92
|
const [internalValue, setInternalValue] = useState(value);
|
|
@@ -138,7 +140,7 @@ const SliderComponent = ({
|
|
|
138
140
|
/>
|
|
139
141
|
{showValue && (
|
|
140
142
|
<div className="text-xs text-muted-foreground min-w-[16px]">
|
|
141
|
-
{prettyScientificNumber(valueMap(internalValue))}
|
|
143
|
+
{prettyScientificNumber(valueMap(internalValue), { locale })}
|
|
142
144
|
</div>
|
|
143
145
|
)}
|
|
144
146
|
{includeInput && (
|
|
@@ -17,8 +17,10 @@ export type EventHandler = (...args: any[]) => void;
|
|
|
17
17
|
|
|
18
18
|
class ModelManager {
|
|
19
19
|
private models = new Map<string, Deferred<Model<any>>>();
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
20
|
+
private timeout: number;
|
|
21
|
+
constructor(timeout = 10_000) {
|
|
22
|
+
this.timeout = timeout;
|
|
23
|
+
}
|
|
22
24
|
|
|
23
25
|
get(key: string): Promise<Model<any>> {
|
|
24
26
|
let deferred = this.models.get(key);
|
|
@@ -64,16 +66,25 @@ export class Model<T extends Record<string, any>> implements AnyModel<T> {
|
|
|
64
66
|
private ANY_CHANGE_EVENT = "change";
|
|
65
67
|
private dirtyFields;
|
|
66
68
|
public static _modelManager: ModelManager = MODEL_MANAGER;
|
|
69
|
+
private data: T;
|
|
70
|
+
private onChange: (value: Partial<T>) => void;
|
|
71
|
+
private sendToWidget: (req: {
|
|
72
|
+
content?: any;
|
|
73
|
+
buffers?: ArrayBuffer[] | ArrayBufferView[];
|
|
74
|
+
}) => Promise<null | undefined>;
|
|
67
75
|
|
|
68
76
|
constructor(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
77
|
+
data: T,
|
|
78
|
+
onChange: (value: Partial<T>) => void,
|
|
79
|
+
sendToWidget: (req: {
|
|
72
80
|
content?: any;
|
|
73
81
|
buffers?: ArrayBuffer[] | ArrayBufferView[];
|
|
74
82
|
}) => Promise<null | undefined>,
|
|
75
83
|
initialDirtyFields: Set<keyof T>,
|
|
76
84
|
) {
|
|
85
|
+
this.data = data;
|
|
86
|
+
this.onChange = onChange;
|
|
87
|
+
this.sendToWidget = sendToWidget;
|
|
77
88
|
this.dirtyFields = new Set(initialDirtyFields);
|
|
78
89
|
}
|
|
79
90
|
|
|
@@ -10,11 +10,13 @@ export interface PositionalEdit {
|
|
|
10
10
|
value: unknown;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
Insert
|
|
15
|
-
Remove
|
|
16
|
-
Rename
|
|
17
|
-
}
|
|
13
|
+
export const BulkEdit = {
|
|
14
|
+
Insert: "insert",
|
|
15
|
+
Remove: "remove",
|
|
16
|
+
Rename: "rename",
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
type BulkEdit = (typeof BulkEdit)[keyof typeof BulkEdit];
|
|
18
20
|
|
|
19
21
|
export interface RowEdit {
|
|
20
22
|
rowIdx: number;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import type { Schema } from "compassql/build/src/schema";
|
|
4
4
|
import { BarChartBigIcon } from "lucide-react";
|
|
5
5
|
import React, { useState } from "react";
|
|
6
|
+
import { useDateFormatter, useNumberFormatter } from "react-aria";
|
|
6
7
|
import { Button } from "@/components/ui/button";
|
|
7
8
|
import {
|
|
8
9
|
Select,
|
|
@@ -131,7 +132,9 @@ export const ColumnSummary: React.FC<Props> = ({ schema }) => {
|
|
|
131
132
|
{STAT_KEYS.map((key) => (
|
|
132
133
|
<div key={key} className="flex flex-row gap-2 min-w-[100px]">
|
|
133
134
|
<span className="font-semibold">{key}</span>
|
|
134
|
-
<span>
|
|
135
|
+
<span>
|
|
136
|
+
<FormatStat value={stats?.[key]} />
|
|
137
|
+
</span>
|
|
135
138
|
</div>
|
|
136
139
|
))}
|
|
137
140
|
</div>
|
|
@@ -151,24 +154,28 @@ const STAT_KEYS = [
|
|
|
151
154
|
"stdev",
|
|
152
155
|
];
|
|
153
156
|
|
|
154
|
-
|
|
157
|
+
const FormatStat = ({ value }: { value: unknown }) => {
|
|
158
|
+
// Decimal .2
|
|
159
|
+
const numberFormatter = useNumberFormatter({
|
|
160
|
+
maximumFractionDigits: 2,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Just day, month, year
|
|
164
|
+
const dateFormatter = useDateFormatter({
|
|
165
|
+
year: "numeric",
|
|
166
|
+
month: "short",
|
|
167
|
+
day: "numeric",
|
|
168
|
+
});
|
|
169
|
+
|
|
155
170
|
if (typeof value === "number") {
|
|
156
|
-
|
|
157
|
-
return new Intl.NumberFormat("en-US", {
|
|
158
|
-
maximumFractionDigits: 2,
|
|
159
|
-
}).format(value);
|
|
171
|
+
return numberFormatter.format(value);
|
|
160
172
|
}
|
|
161
173
|
if (typeof value === "string") {
|
|
162
174
|
return value;
|
|
163
175
|
}
|
|
164
176
|
if (typeof value === "object" && value instanceof Date) {
|
|
165
|
-
|
|
166
|
-
return new Intl.DateTimeFormat("en-US", {
|
|
167
|
-
year: "numeric",
|
|
168
|
-
month: "short",
|
|
169
|
-
day: "numeric",
|
|
170
|
-
}).format(value);
|
|
177
|
+
return dateFormatter.format(value);
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
return String(value);
|
|
174
|
-
}
|
|
181
|
+
};
|
|
@@ -4,6 +4,10 @@ import { isEqual } from "lodash-es";
|
|
|
4
4
|
import { Code2Icon, DatabaseIcon, FunctionSquareIcon } from "lucide-react";
|
|
5
5
|
import { type JSX, memo, useEffect, useRef, useState } from "react";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
import {
|
|
8
|
+
type DownloadAsArgs,
|
|
9
|
+
DownloadAsSchema,
|
|
10
|
+
} from "@/components/data-table/schemas";
|
|
7
11
|
import type { FieldTypesWithExternalType } from "@/components/data-table/types";
|
|
8
12
|
import { ReadonlyCode } from "@/components/editor/code/readonly-python-code";
|
|
9
13
|
import { Spinner } from "@/components/icons/spinner";
|
|
@@ -38,6 +42,7 @@ interface Data {
|
|
|
38
42
|
label?: string | null;
|
|
39
43
|
columns: ColumnDataTypes;
|
|
40
44
|
pageSize: number;
|
|
45
|
+
showDownload: boolean;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
@@ -67,6 +72,7 @@ type PluginFunctions = {
|
|
|
67
72
|
data: TableData<T>;
|
|
68
73
|
total_rows: number;
|
|
69
74
|
}>;
|
|
75
|
+
download_as: DownloadAsArgs;
|
|
70
76
|
};
|
|
71
77
|
|
|
72
78
|
// Value is selection, but it is not currently exposed to the user
|
|
@@ -77,13 +83,14 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
77
83
|
z.object({
|
|
78
84
|
label: z.string().nullish(),
|
|
79
85
|
pageSize: z.number().default(5),
|
|
86
|
+
showDownload: z.boolean().default(true),
|
|
80
87
|
columns: z
|
|
81
88
|
.array(z.tuple([z.string().or(z.number()), z.string(), z.string()]))
|
|
82
89
|
.transform((value) => {
|
|
83
90
|
const map = new Map<ColumnId, string>();
|
|
84
|
-
value.forEach(([key, dataType]) =>
|
|
85
|
-
map.set(key as ColumnId, dataType as DataType)
|
|
86
|
-
);
|
|
91
|
+
value.forEach(([key, dataType]) => {
|
|
92
|
+
map.set(key as ColumnId, dataType as DataType);
|
|
93
|
+
});
|
|
87
94
|
return map;
|
|
88
95
|
}),
|
|
89
96
|
}),
|
|
@@ -124,6 +131,7 @@ export const DataFramePlugin = createPlugin<S>("marimo-dataframe")
|
|
|
124
131
|
total_rows: z.number(),
|
|
125
132
|
}),
|
|
126
133
|
),
|
|
134
|
+
download_as: DownloadAsSchema,
|
|
127
135
|
})
|
|
128
136
|
.renderer((props) => (
|
|
129
137
|
<TableProviders>
|
|
@@ -141,6 +149,8 @@ interface DataTableProps extends Data, PluginFunctions {
|
|
|
141
149
|
value: S;
|
|
142
150
|
setValue: (value: S) => void;
|
|
143
151
|
host: HTMLElement;
|
|
152
|
+
showDownload: boolean;
|
|
153
|
+
download_as: DownloadAsArgs;
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
const EMPTY: Transformations = {
|
|
@@ -151,11 +161,13 @@ export const DataFrameComponent = memo(
|
|
|
151
161
|
({
|
|
152
162
|
columns,
|
|
153
163
|
pageSize,
|
|
164
|
+
showDownload,
|
|
154
165
|
value,
|
|
155
166
|
setValue,
|
|
156
167
|
get_dataframe,
|
|
157
168
|
get_column_values,
|
|
158
169
|
search,
|
|
170
|
+
download_as,
|
|
159
171
|
host,
|
|
160
172
|
}: DataTableProps): JSX.Element => {
|
|
161
173
|
const { data, error, isPending } = useAsyncData(
|
|
@@ -270,8 +282,8 @@ export const DataFrameComponent = memo(
|
|
|
270
282
|
pagination={true}
|
|
271
283
|
fieldTypes={field_types}
|
|
272
284
|
rowHeaders={row_headers || Arrays.EMPTY}
|
|
273
|
-
showDownload={
|
|
274
|
-
download_as={
|
|
285
|
+
showDownload={showDownload}
|
|
286
|
+
download_as={download_as}
|
|
275
287
|
enableSearch={false}
|
|
276
288
|
showFilters={false}
|
|
277
289
|
search={search}
|
|
@@ -57,11 +57,13 @@ export class EventBuffer<T> {
|
|
|
57
57
|
private buffer: T[] = [];
|
|
58
58
|
private isBlocked = false;
|
|
59
59
|
private timeout: number | null = null;
|
|
60
|
+
private processEvents: () => void;
|
|
61
|
+
private blockDuration: number;
|
|
60
62
|
|
|
61
|
-
constructor(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
constructor(processEvents: () => void, blockDuration = 200) {
|
|
64
|
+
this.processEvents = processEvents;
|
|
65
|
+
this.blockDuration = blockDuration;
|
|
66
|
+
}
|
|
65
67
|
|
|
66
68
|
add(event: T) {
|
|
67
69
|
this.buffer.push(event);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
|
+
import { Provider, useAtomValue } from "jotai";
|
|
3
|
+
import type { JSX } from "react";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { notebookOutline } from "@/core/cells/cells";
|
|
6
|
+
import { store } from "@/core/state/jotai";
|
|
7
|
+
import { OutlineList } from "../../components/editor/chrome/panels/outline/floating-outline";
|
|
8
|
+
import {
|
|
9
|
+
findOutlineElements,
|
|
10
|
+
useActiveOutline,
|
|
11
|
+
} from "../../components/editor/chrome/panels/outline/useActiveOutline";
|
|
12
|
+
import type {
|
|
13
|
+
IStatelessPlugin,
|
|
14
|
+
IStatelessPluginProps,
|
|
15
|
+
} from "../stateless-plugin";
|
|
16
|
+
|
|
17
|
+
interface Data {
|
|
18
|
+
label?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const OutlineContent: React.FC<{ label?: string }> = ({ label }) => {
|
|
22
|
+
const { items } = useAtomValue(notebookOutline);
|
|
23
|
+
const headerElements = findOutlineElements(items);
|
|
24
|
+
const { activeHeaderId, activeOccurrences } =
|
|
25
|
+
useActiveOutline(headerElements);
|
|
26
|
+
|
|
27
|
+
if (items.length === 0) {
|
|
28
|
+
return (
|
|
29
|
+
<div className="text-muted-foreground text-sm p-4 border border-dashed border-border rounded-lg">
|
|
30
|
+
No outline found. Add markdown headings to your notebook to create an
|
|
31
|
+
outline.
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="border border-border rounded-lg">
|
|
38
|
+
{label && (
|
|
39
|
+
<div className="px-4 py-2 border-b border-border font-medium text-sm">
|
|
40
|
+
{label}
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
43
|
+
<OutlineList
|
|
44
|
+
className="max-h-[400px]"
|
|
45
|
+
items={items}
|
|
46
|
+
activeHeaderId={activeHeaderId}
|
|
47
|
+
activeOccurrences={activeOccurrences}
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export class OutlinePlugin implements IStatelessPlugin<Data> {
|
|
54
|
+
tagName = "marimo-outline";
|
|
55
|
+
|
|
56
|
+
validator = z.object({
|
|
57
|
+
label: z.string().optional(),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
render(props: IStatelessPluginProps<Data>): JSX.Element {
|
|
61
|
+
const { label } = props.data;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Provider store={store}>
|
|
65
|
+
<OutlineContent label={label} />
|
|
66
|
+
</Provider>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { TriangleIcon } from "lucide-react";
|
|
4
4
|
import type { JSX } from "react";
|
|
5
|
+
import { useLocale } from "react-aria";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import { cn } from "@/utils/cn";
|
|
7
8
|
import { prettyNumber } from "@/utils/numbers";
|
|
@@ -41,6 +42,8 @@ export const StatComponent: React.FC<Data> = ({
|
|
|
41
42
|
bordered,
|
|
42
43
|
direction,
|
|
43
44
|
}) => {
|
|
45
|
+
const { locale } = useLocale();
|
|
46
|
+
|
|
44
47
|
const renderPrettyValue = () => {
|
|
45
48
|
if (value == null) {
|
|
46
49
|
return <i>No value</i>;
|
|
@@ -51,7 +54,7 @@ export const StatComponent: React.FC<Data> = ({
|
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
if (typeof value === "number") {
|
|
54
|
-
return prettyNumber(value);
|
|
57
|
+
return prettyNumber(value, locale);
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
if (typeof value === "boolean") {
|
package/src/plugins/plugins.ts
CHANGED
|
@@ -45,6 +45,7 @@ import { JsonOutputPlugin } from "./layout/JsonOutputPlugin";
|
|
|
45
45
|
import { LazyPlugin } from "./layout/LazyPlugin";
|
|
46
46
|
import { MimeRendererPlugin } from "./layout/MimeRenderPlugin";
|
|
47
47
|
import { MermaidPlugin } from "./layout/mermaid/MermaidPlugin";
|
|
48
|
+
import { OutlinePlugin } from "./layout/OutlinePlugin";
|
|
48
49
|
import { ProgressPlugin } from "./layout/ProgressPlugin";
|
|
49
50
|
import { RoutesPlugin } from "./layout/RoutesPlugin";
|
|
50
51
|
import { StatPlugin } from "./layout/StatPlugin";
|
|
@@ -99,6 +100,7 @@ const LAYOUT_PLUGINS: Array<IStatelessPlugin<unknown>> = [
|
|
|
99
100
|
new MimeRendererPlugin(),
|
|
100
101
|
new MermaidPlugin(),
|
|
101
102
|
new NavigationMenuPlugin(),
|
|
103
|
+
new OutlinePlugin(),
|
|
102
104
|
new ProgressPlugin(),
|
|
103
105
|
new RoutesPlugin(),
|
|
104
106
|
new StatPlugin(),
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
timeAgo,
|
|
9
9
|
} from "../dates";
|
|
10
10
|
|
|
11
|
+
const locale = "en-US";
|
|
12
|
+
|
|
11
13
|
describe("dates", () => {
|
|
12
14
|
// Save original timezone
|
|
13
15
|
let originalTimezone: string | undefined;
|
|
@@ -25,36 +27,38 @@ describe("dates", () => {
|
|
|
25
27
|
|
|
26
28
|
describe("prettyDate", () => {
|
|
27
29
|
it("returns empty string for null or undefined", () => {
|
|
28
|
-
expect(prettyDate(null, "date")).toBe("");
|
|
29
|
-
expect(prettyDate(undefined, "date")).toBe("");
|
|
30
|
+
expect(prettyDate(null, "date", locale)).toBe("");
|
|
31
|
+
expect(prettyDate(undefined, "date", locale)).toBe("");
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
it("formats date correctly", () => {
|
|
33
35
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
34
36
|
// Using a regex to match the pattern since exact format may vary by locale
|
|
35
|
-
expect(prettyDate(date.toISOString(), "date")).toMatch(
|
|
37
|
+
expect(prettyDate(date.toISOString(), "date", locale)).toMatch(
|
|
38
|
+
/May 15, 2023/,
|
|
39
|
+
);
|
|
36
40
|
});
|
|
37
41
|
|
|
38
42
|
it("formats datetime correctly", () => {
|
|
39
43
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
40
|
-
expect(prettyDate(date.toISOString(), "datetime")).toMatch(
|
|
44
|
+
expect(prettyDate(date.toISOString(), "datetime", locale)).toMatch(
|
|
41
45
|
/May 15, 2023/,
|
|
42
46
|
);
|
|
43
47
|
});
|
|
44
48
|
|
|
45
49
|
it("handles errors gracefully", () => {
|
|
46
|
-
expect(prettyDate("invalid-date", "date")).toBe("Invalid Date");
|
|
50
|
+
expect(prettyDate("invalid-date", "date", locale)).toBe("Invalid Date");
|
|
47
51
|
});
|
|
48
52
|
|
|
49
53
|
it("handles numeric timestamp input", () => {
|
|
50
54
|
const timestamp = 1_684_152_000_000; // 2023-05-15T12:00:00Z in milliseconds
|
|
51
|
-
expect(prettyDate(timestamp, "date")).toMatch(/May 15, 2023/);
|
|
55
|
+
expect(prettyDate(timestamp, "date", locale)).toMatch(/May 15, 2023/);
|
|
52
56
|
});
|
|
53
57
|
|
|
54
58
|
it("preserves timezone for datetime type", () => {
|
|
55
59
|
// This date is in winter time to avoid daylight saving time issues
|
|
56
60
|
const date = new Date("2023-01-15T15:30:00Z");
|
|
57
|
-
expect(prettyDate(date.toISOString(), "datetime")).toMatch(
|
|
61
|
+
expect(prettyDate(date.toISOString(), "datetime", locale)).toMatch(
|
|
58
62
|
/Jan 15, 2023/,
|
|
59
63
|
);
|
|
60
64
|
});
|
|
@@ -62,7 +66,9 @@ describe("dates", () => {
|
|
|
62
66
|
it("drops timezone for date type by using UTC", () => {
|
|
63
67
|
// Create a date that would be different days in different timezones
|
|
64
68
|
const date = new Date("2023-05-15T23:30:00Z"); // Late in the day UTC
|
|
65
|
-
expect(prettyDate(date.toISOString(), "date")).toMatch(
|
|
69
|
+
expect(prettyDate(date.toISOString(), "date", locale)).toMatch(
|
|
70
|
+
/May 15, 2023/,
|
|
71
|
+
);
|
|
66
72
|
});
|
|
67
73
|
|
|
68
74
|
describe("with different locales", () => {
|
|
@@ -86,7 +92,9 @@ describe("dates", () => {
|
|
|
86
92
|
};
|
|
87
93
|
|
|
88
94
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
89
|
-
expect(prettyDate(date.toISOString(), "date")).toBe(
|
|
95
|
+
expect(prettyDate(date.toISOString(), "date", locale)).toBe(
|
|
96
|
+
"15 mai 2023",
|
|
97
|
+
);
|
|
90
98
|
});
|
|
91
99
|
});
|
|
92
100
|
});
|
|
@@ -94,34 +102,42 @@ describe("dates", () => {
|
|
|
94
102
|
describe("exactDateTime", () => {
|
|
95
103
|
it("formats date without milliseconds", () => {
|
|
96
104
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
97
|
-
expect(exactDateTime(date, undefined)).toBe(
|
|
105
|
+
expect(exactDateTime(date, undefined, locale)).toBe(
|
|
106
|
+
"2023-05-15 12:00:00",
|
|
107
|
+
);
|
|
98
108
|
});
|
|
99
109
|
|
|
100
110
|
it("formats date with milliseconds", () => {
|
|
101
111
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
102
|
-
expect(exactDateTime(date, undefined)).toBe(
|
|
112
|
+
expect(exactDateTime(date, undefined, locale)).toBe(
|
|
113
|
+
"2023-05-15 12:00:00.123",
|
|
114
|
+
);
|
|
103
115
|
});
|
|
104
116
|
|
|
105
117
|
it("formats date in UTC when renderInUTC is true", () => {
|
|
106
118
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
107
|
-
expect(exactDateTime(date, "UTC")).toBe(
|
|
119
|
+
expect(exactDateTime(date, "UTC", locale)).toBe(
|
|
120
|
+
"2023-05-15 12:00:00 UTC",
|
|
121
|
+
);
|
|
108
122
|
});
|
|
109
123
|
|
|
110
124
|
it("formats date with milliseconds in UTC when renderInUTC is true", () => {
|
|
111
125
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
112
|
-
expect(exactDateTime(date, "UTC")).toBe(
|
|
126
|
+
expect(exactDateTime(date, "UTC", locale)).toBe(
|
|
127
|
+
"2023-05-15 12:00:00.123 UTC",
|
|
128
|
+
);
|
|
113
129
|
});
|
|
114
130
|
|
|
115
131
|
it("formats date in America/New_York timezone", () => {
|
|
116
132
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
117
|
-
expect(exactDateTime(date, "America/New_York")).toBe(
|
|
133
|
+
expect(exactDateTime(date, "America/New_York", locale)).toBe(
|
|
118
134
|
"2023-05-15 08:00:00 EDT",
|
|
119
135
|
);
|
|
120
136
|
});
|
|
121
137
|
|
|
122
138
|
it("formats date with milliseconds in America/New_York timezone", () => {
|
|
123
139
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
124
|
-
expect(exactDateTime(date, "America/New_York")).toBe(
|
|
140
|
+
expect(exactDateTime(date, "America/New_York", locale)).toBe(
|
|
125
141
|
"2023-05-15 08:00:00.123 EDT",
|
|
126
142
|
);
|
|
127
143
|
});
|
|
@@ -129,42 +145,47 @@ describe("dates", () => {
|
|
|
129
145
|
|
|
130
146
|
describe("timeAgo", () => {
|
|
131
147
|
it("returns empty string for null, undefined, or 0", () => {
|
|
132
|
-
expect(timeAgo(null)).toBe("");
|
|
133
|
-
expect(timeAgo(undefined)).toBe("");
|
|
134
|
-
expect(timeAgo(0)).toBe("");
|
|
148
|
+
expect(timeAgo(null, locale)).toBe("");
|
|
149
|
+
expect(timeAgo(undefined, locale)).toBe("");
|
|
150
|
+
expect(timeAgo(0, locale)).toBe("");
|
|
135
151
|
});
|
|
136
152
|
|
|
137
153
|
it("formats today's date correctly", () => {
|
|
138
154
|
const today = new Date();
|
|
139
|
-
const result = timeAgo(today.toISOString());
|
|
155
|
+
const result = timeAgo(today.toISOString(), locale);
|
|
140
156
|
expect(result).toMatch(/Today at/);
|
|
141
157
|
});
|
|
142
158
|
|
|
143
159
|
it("formats yesterday's date correctly", () => {
|
|
144
160
|
const yesterday = new Date();
|
|
145
161
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
146
|
-
const result = timeAgo(yesterday.toISOString());
|
|
162
|
+
const result = timeAgo(yesterday.toISOString(), locale);
|
|
147
163
|
expect(result).toMatch(/Yesterday at/);
|
|
148
164
|
});
|
|
149
165
|
|
|
150
166
|
it("formats older dates correctly", () => {
|
|
151
167
|
const oldDate = new Date("2020-01-01T12:00:00Z");
|
|
152
|
-
const result = timeAgo(oldDate.toISOString());
|
|
168
|
+
const result = timeAgo(oldDate.toISOString(), locale);
|
|
153
169
|
expect(result).toMatch(/Jan 1, 2020 at/);
|
|
154
170
|
});
|
|
155
171
|
|
|
156
172
|
it("handles errors gracefully", () => {
|
|
157
|
-
expect(timeAgo("invalid-date")).toBe(
|
|
173
|
+
expect(timeAgo("invalid-date", locale)).toBe(
|
|
174
|
+
"Invalid Date at Invalid Date",
|
|
175
|
+
);
|
|
158
176
|
});
|
|
159
177
|
});
|
|
160
178
|
|
|
161
179
|
describe("getShortTimeZone", () => {
|
|
162
180
|
it("returns the short timezone", () => {
|
|
163
|
-
expect(getShortTimeZone("America/New_York")).toBeOneOf([
|
|
181
|
+
expect(getShortTimeZone("America/New_York", locale)).toBeOneOf([
|
|
182
|
+
"EDT",
|
|
183
|
+
"EST",
|
|
184
|
+
]);
|
|
164
185
|
});
|
|
165
186
|
|
|
166
187
|
it("handles errors gracefully", () => {
|
|
167
|
-
expect(getShortTimeZone("MarimoLand")).toBe("MarimoLand");
|
|
188
|
+
expect(getShortTimeZone("MarimoLand", locale)).toBe("MarimoLand");
|
|
168
189
|
});
|
|
169
190
|
});
|
|
170
191
|
|