@marimo-team/frontend 0.16.0-dev96986 → 0.16.0
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-BErMbWvG.js +19 -0
- package/dist/assets/{ImageComparisonComponent-SX7fDaTK.js → ImageComparisonComponent-fTHv1Ih0.js} +1 -1
- package/dist/assets/{VegaLite-MJUW3b7C.js → VegaLite-Bdi-TyfY.js} +1 -1
- package/dist/assets/_baseEach-CNBxBxvS.js +1 -0
- package/dist/assets/_baseMap-D1WHjKrd.js +1 -0
- package/dist/assets/_baseUniq-CCgDNtZb.js +1 -0
- package/dist/assets/{_createAggregator-ZRm2b6Zm.js → _createAggregator-DcD0kTA5.js} +1 -1
- package/dist/assets/{agent-panel-BBd11wNX.js → agent-panel-Crv430aI.js} +57 -76
- package/dist/assets/{any-language-editor-DwAaEQfS.js → any-language-editor-CQh552Wu.js} +1 -1
- package/dist/assets/{architectureDiagram-W76B3OCA-BJmVXUoW.js → architectureDiagram-W76B3OCA-BAJeBxzt.js} +1 -1
- package/dist/assets/{between-horizontal-start-KiwU-a3C.js → between-horizontal-start-Boxgxbt_.js} +1 -1
- package/dist/assets/{blockDiagram-QIGZ2CNN-DzxZjE7B.js → blockDiagram-QIGZ2CNN-CL-1svEK.js} +1 -1
- package/dist/assets/{c4Diagram-FPNF74CW-DjmldG_J.js → c4Diagram-FPNF74CW-BbEqbCTl.js} +1 -1
- package/dist/assets/channel-_2eNSz0n.js +1 -0
- package/dist/assets/chat-panel-CXh5Wl6C.js +3 -0
- package/dist/assets/{chunk-4BX2VUAB-EUTQThiZ.js → chunk-4BX2VUAB-C--8TXeE.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DZAiDJxy.js → chunk-55IACEB6-Bj00HDqq.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-Bd0Czs-J.js → chunk-FMBD7UC4-C-lhB6hN.js} +1 -1
- package/dist/assets/{chunk-K7UQS3LO-DEKMIknX.js → chunk-K7UQS3LO-B-pGTXPt.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-E0jwHU_n.js → chunk-QN33PNHL-DqUzGhvm.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-BzaIHJbq.js → chunk-QZHKN3VN-TntJHfSk.js} +1 -1
- package/dist/assets/{chunk-TVAH2DTR-CZFYvqnm.js → chunk-TVAH2DTR-HUJb1psV.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-BNqnFjtv.js → chunk-TZMSLE5B-BK3C__t3.js} +1 -1
- package/dist/assets/{circle-play-D3J_mYrF.js → circle-play-DBLOv1Yu.js} +1 -1
- package/dist/assets/classDiagram-KNZD7YFC-BGmh9POF.js +1 -0
- package/dist/assets/classDiagram-v2-RKCZMP56-BGmh9POF.js +1 -0
- package/dist/assets/{clear-button-ifzRuAR3.js → clear-button-BeoFbEKH.js} +1 -1
- package/dist/assets/clone-BFDSPAj3.js +1 -0
- package/dist/assets/{command-palette-D2fdVSET.js → command-palette-CXZiSv0I.js} +1 -1
- package/dist/assets/{common-Ku-cF_2J.js → common-C7oJcmCT.js} +1 -1
- package/dist/assets/{compile-BgZlHW1c.js → compile-7L0MwhyI.js} +1 -1
- package/dist/assets/{cose-bilkent-S5V4N54A-CVM83SqK.js → cose-bilkent-S5V4N54A-BMkGLcVC.js} +1 -1
- package/dist/assets/{dagre-5GWH7T2D-ouQPkxT3.js → dagre-5GWH7T2D-BJtRienS.js} +1 -1
- package/dist/assets/{data-grid-overlay-editor-B47j5GJJ.js → data-grid-overlay-editor-DBkmGtNs.js} +1 -1
- package/dist/assets/datasources-panel-B7FbYLiy.js +1 -0
- package/dist/assets/{dependency-graph-panel-CZC_B7pK.js → dependency-graph-panel-DEdOxp2X.js} +1 -1
- package/dist/assets/{diagram-N5W7TBWH-CQ817ZdR.js → diagram-N5W7TBWH-CmECY3nb.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-DOK_psUO.js → diagram-QEK2KX5R-DMOVSNKD.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-CVljmOW8.js → diagram-S2PKOQOG-BiJ96PNQ.js} +1 -1
- package/dist/assets/{documentation-panel-C7yIvGg1.js → documentation-panel-xULhaEv3.js} +1 -1
- package/dist/assets/edit-page-BrYda9VE.js +129 -0
- package/dist/assets/{ellipsis-vertical-C7FjlUsY.js → ellipsis-vertical-BBqXIlc2.js} +1 -1
- package/dist/assets/{empty-state-DIOGM_CU.js → empty-state-B3dA3G5P.js} +1 -1
- package/dist/assets/{erDiagram-AWTI2OKA-DYu8cEdc.js → erDiagram-AWTI2OKA-MP1DiFRo.js} +1 -1
- package/dist/assets/{error-panel-Ddb8RkFG.js → error-panel-Cc1sv-Ag.js} +1 -1
- package/dist/assets/file-explorer-panel-Bw59Kva1.js +1 -0
- package/dist/assets/{flowDiagram-PVAE7QVJ-CmvW5iTb.js → flowDiagram-PVAE7QVJ-BX7caPp7.js} +1 -1
- package/dist/assets/{ganttDiagram-OWAHRB6G-BaKQlCaT.js → ganttDiagram-OWAHRB6G-B462g4Yf.js} +4 -4
- package/dist/assets/{gitGraphDiagram-NY62KEGX-CWO24eP6.js → gitGraphDiagram-NY62KEGX-CGgvZ9-9.js} +1 -1
- package/dist/assets/{glide-data-editor-CNDLEJ9a.js → glide-data-editor-C0gUFZON.js} +11 -11
- package/dist/assets/{graph-BZKTtxsc.js → graph-CHRVBzY5.js} +1 -1
- package/dist/assets/home-page-Fb2osjys.js +9 -0
- package/dist/assets/{index-zrSUQXha.js → index-BVgAenPd.js} +1 -1
- package/dist/assets/{index-Brf2DwUM.js → index-BY93Ejhl.js} +1 -1
- package/dist/assets/{index-CerjupfZ.js → index-C-8WADat.js} +1 -1
- package/dist/assets/{index-DZhOPkOB.js → index-C-GhZ7ti.js} +1 -1
- package/dist/assets/{index-CZaurnA9.js → index-C1v_Z9et.js} +1 -1
- package/dist/assets/{index-0XOUPdwT.js → index-C4Tn5NvJ.js} +1 -1
- package/dist/assets/{index-B_d_JZGI.js → index-C77h_TXN.js} +1 -1
- package/dist/assets/{index-BJVyzkx5.js → index-CQDrxQ0j.js} +1 -1
- package/dist/assets/{index-DFrGFNW1.js → index-CWMgowgL.js} +1 -1
- package/dist/assets/{index-DmgwT3sx.js → index-Clbi_Yaq.js} +1 -1
- package/dist/assets/{index-D-tZfElD.js → index-CpTPJo4k.js} +1 -1
- package/dist/assets/index-Cx0bsY1w.css +1 -0
- package/dist/assets/{index-DkntzpX4.js → index-D1vmG6DS.js} +1 -1
- package/dist/assets/{index-D3PqGupX.js → index-D9UKkrr2.js} +1 -1
- package/dist/assets/{index-BgXbBA39.js → index-DEQvTChO.js} +1 -1
- package/dist/assets/index-DKEudB02.js +578 -0
- package/dist/assets/{index-DCkzth56.js → index-DRMm6SNo.js} +1 -1
- package/dist/assets/{index-WXJFkQHg.js → index-DoRmcrKM.js} +1 -1
- package/dist/assets/{index-qE8lHQ-N.js → index-lYa_leQE.js} +1 -1
- package/dist/assets/{index-CXrWwFX6.js → index-vmICa5KN.js} +1 -1
- package/dist/assets/{index-BH7f3aiU.js → index-z9bohSQJ.js} +1 -1
- package/dist/assets/infoDiagram-STP46IZ2-CVyrdLc8.js +2 -0
- package/dist/assets/{isEmpty-D1t7Gran.js → isEmpty-DU_ogP_D.js} +1 -1
- package/dist/assets/{journeyDiagram-BIP6EPQ6-D4Rp6H_h.js → journeyDiagram-BIP6EPQ6-C6EgLP_Q.js} +1 -1
- package/dist/assets/{kanban-definition-6OIFK2YF-DFt9DftA.js → kanban-definition-6OIFK2YF-BXzYO1yj.js} +1 -1
- package/dist/assets/{layout-D8WXi2_g.js → layout-jihVw5-i.js} +1 -1
- package/dist/assets/{linear-BwY8e5hA.js → linear-C4blANlC.js} +1 -1
- package/dist/assets/links-D59GIweI.js +7 -0
- package/dist/assets/{logs-panel-Dxiyt7dO.js → logs-panel-D401qzZh.js} +1 -1
- package/dist/assets/{markdown-renderer-VDu-NBKB.js → markdown-renderer-Cd9eYyaL.js} +20 -20
- package/dist/assets/{mermaid-B-O-Puyi.js → mermaid-BEVuRz_O.js} +1 -1
- package/dist/assets/{mermaid.core-BFFCqfOn.js → mermaid.core-CaSnaLH0.js} +4 -4
- package/dist/assets/min-DUMu_zeK.js +1 -0
- package/dist/assets/{mindmap-definition-Q6HEUPPD-kyvIY8Dg.js → mindmap-definition-Q6HEUPPD-BXUM5MT2.js} +1 -1
- package/dist/assets/{number-overlay-editor-GjLB2UK4.js → number-overlay-editor-4uWXGlPG.js} +1 -1
- package/dist/assets/outline-panel-DIzkvm2I.js +1 -0
- package/dist/assets/{packages-panel-nfXB-bKW.js → packages-panel-CJL0MVlj.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-D8JFQcWR.js → pieDiagram-ADFJNKIX-Dxt5PVNo.js} +1 -1
- package/dist/assets/{quadrantDiagram-LMRXKWRM-Nf8GzxXG.js → quadrantDiagram-LMRXKWRM-D4pUaA31.js} +1 -1
- package/dist/assets/{react-plotly-CnW9p7ZA.js → react-plotly-cJZ0VWBq.js} +1 -1
- package/dist/assets/{requirementDiagram-4UW4RH46-CCUxF8BZ.js → requirementDiagram-4UW4RH46-DVRTjgas.js} +1 -1
- package/dist/assets/{run-page-Bl4p3AbZ.js → run-page-BUEnMC9w.js} +1 -1
- package/dist/assets/{sankeyDiagram-GR3RE2ED-Sr8kDwP1.js → sankeyDiagram-GR3RE2ED-CVFnD9C-.js} +1 -1
- package/dist/assets/{scratchpad-panel-Ja1Mu-W3.js → scratchpad-panel-BIgRENkI.js} +1 -1
- package/dist/assets/{secrets-panel-B-3fcSyP.js → secrets-panel-xY5-V_BD.js} +1 -1
- package/dist/assets/{sequenceDiagram-C3RYC4MD-CBJ152Q3.js → sequenceDiagram-C3RYC4MD-_lY4ZN_S.js} +1 -1
- package/dist/assets/{slides-component-C-LoGC1U.css → slides-component-DMjQomc3.css} +1 -1
- package/dist/assets/{slides-component-DGtsVP5o.js → slides-component-Xjymwj7X.js} +1 -1
- package/dist/assets/snippets-panel-CTPYW41n.js +1 -0
- package/dist/assets/sortBy-BNZKwiq_.js +1 -0
- package/dist/assets/{state-B_RCHTH5.js → state-C4NiC9tO.js} +1 -1
- package/dist/assets/{stateDiagram-KXAO66HF-BlBFSAZr.js → stateDiagram-KXAO66HF-Da0JQWCn.js} +1 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-D5lYZOOt.js +1 -0
- package/dist/assets/storage-CMdLzB_c.js +26 -0
- package/dist/assets/{terminal-CATzv5Hd.js → terminal-BPwTkXae.js} +1 -1
- package/dist/assets/{time-CsYqILfB.js → time-Dv5_Ouz_.js} +1 -1
- package/dist/assets/{timeline-definition-XQNQX7LJ-CGrhjuAs.js → timeline-definition-XQNQX7LJ-Dxh5Zu2e.js} +1 -1
- package/dist/assets/tracing-BCIurUfa.js +2 -0
- package/dist/assets/{tracing-panel-DmzqPUtc.js → tracing-panel-DAzrzNmm.js} +2 -2
- package/dist/assets/{trash-rxdjLzkf.js → trash-Dc6DSjz_.js} +1 -1
- package/dist/assets/{tree-C2Ul1h1C.js → tree-jheoerAX.js} +1 -1
- package/dist/assets/{treemap-75Q7IDZK-N9hyUpyj.js → treemap-75Q7IDZK-IgpxeGaf.js} +27 -27
- package/dist/assets/variable-panel-DYAiLBmF.js +1 -0
- package/dist/assets/{vega-component-CR_MHOBT.js → vega-component-BpfpiPKI.js} +1 -1
- package/dist/assets/worker-X5rxzQGQ.js +1 -0
- package/dist/assets/{xychartDiagram-6GGTOJPD-jdLZsMb2.js → xychartDiagram-6GGTOJPD-CmNigJ31.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +2 -3
- package/src/components/app-config/user-config-form.tsx +1 -46
- package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +43 -62
- 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 +27 -24
- package/src/components/chat/acp/blocks.tsx +6 -6
- package/src/components/chat/acp/prompt.ts +43 -62
- package/src/components/chat/chat-panel.tsx +1 -5
- package/src/components/chat/markdown-renderer.tsx +10 -6
- package/src/components/chat/tool-call-accordion.tsx +20 -52
- package/src/components/data-table/SearchBar.tsx +7 -8
- package/src/components/data-table/__tests__/column_formatting.test.ts +35 -50
- package/src/components/data-table/__tests__/data-table.test.tsx +1 -39
- package/src/components/data-table/charts/components/form-fields.tsx +37 -41
- package/src/components/data-table/charts/forms/common-chart.tsx +2 -2
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +2 -5
- package/src/components/data-table/column-formatting/feature.ts +29 -62
- package/src/components/data-table/column-formatting/types.ts +0 -1
- package/src/components/data-table/column-header.tsx +1 -3
- package/src/components/data-table/column-summary/chart-spec-model.tsx +7 -24
- package/src/components/data-table/column-summary/column-summary.tsx +9 -18
- package/src/components/data-table/columns.tsx +18 -42
- package/src/components/data-table/data-table.tsx +2 -10
- package/src/components/data-table/date-popover.tsx +75 -85
- package/src/components/data-table/filter-pills.tsx +9 -14
- package/src/components/data-table/header-items.tsx +1 -5
- package/src/components/data-table/pagination.tsx +13 -20
- package/src/components/data-table/renderers.tsx +0 -28
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +8 -10
- package/src/components/datasources/column-preview.tsx +2 -6
- package/src/components/datasources/datasources.tsx +12 -8
- package/src/components/editor/ai/transport/chat-transport.tsx +1 -4
- package/src/components/editor/cell/CellStatus.tsx +20 -23
- package/src/components/editor/cell/CreateCellButton.tsx +4 -3
- package/src/components/editor/cell/code/language-toggle.tsx +4 -3
- package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +28 -39
- package/src/components/editor/controls/notebook-menu-dropdown.tsx +2 -4
- package/src/components/editor/file-tree/requesting-tree.tsx +8 -14
- package/src/components/editor/renderers/CellArray.tsx +4 -3
- package/src/components/editor/renderers/slides-layout/slides-layout.tsx +3 -3
- package/src/components/editor/renderers/slides-layout/types.ts +0 -1
- package/src/components/pages/home-page.tsx +1 -4
- package/src/components/slides/slides-component.tsx +1 -1
- package/src/components/slides/slides.css +0 -6
- package/src/components/terminal/theme.tsx +0 -1
- package/src/components/tracing/tracing-spec.ts +4 -5
- package/src/components/ui/range-slider.tsx +2 -4
- package/src/components/ui/slider.tsx +1 -3
- package/src/components/variables/variables-table.tsx +0 -3
- package/src/core/MarimoApp.tsx +6 -9
- package/src/core/ai/context/__tests__/registry.test.ts +4 -6
- package/src/core/ai/context/providers/cell-output.ts +2 -3
- package/src/core/ai/context/providers/error.ts +1 -3
- package/src/core/ai/context/providers/file.ts +2 -7
- package/src/core/ai/context/providers/tables.ts +2 -3
- package/src/core/ai/context/providers/variable.ts +4 -6
- package/src/core/cells/logs.ts +1 -1
- package/src/core/codemirror/find-replace/search-highlight.ts +1 -3
- package/src/core/codemirror/language/LanguageAdapters.ts +3 -9
- package/src/core/codemirror/lsp/notebook-lsp.ts +2 -8
- package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/rtc/loro/awareness.ts +17 -52
- package/src/core/codemirror/rtc/loro/sync.ts +4 -12
- package/src/core/config/config-schema.ts +0 -1
- package/src/core/config/config.ts +0 -4
- package/src/core/hotkeys/hotkeys.ts +4 -8
- package/src/core/islands/components/web-components.tsx +10 -13
- package/src/core/kernel/RuntimeState.ts +1 -4
- package/src/core/kernel/messages.ts +2 -2
- package/src/core/network/DeferredRequestRegistry.ts +4 -16
- package/src/core/runtime/runtime.ts +4 -5
- package/src/core/wasm/bridge.ts +1 -5
- package/src/core/wasm/store.ts +1 -4
- package/src/core/wasm/worker/message-buffer.ts +2 -3
- package/src/core/websocket/types.ts +16 -22
- package/src/hooks/useTimer.ts +5 -8
- package/src/plugins/core/registerReactComponent.tsx +10 -16
- package/src/plugins/impl/DataTablePlugin.tsx +0 -4
- package/src/plugins/impl/RangeSliderPlugin.tsx +3 -5
- package/src/plugins/impl/SliderPlugin.tsx +1 -3
- package/src/plugins/impl/anywidget/model.ts +5 -16
- package/src/plugins/impl/data-editor/types.ts +5 -7
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +13 -20
- package/src/plugins/impl/panel/utils.ts +4 -6
- package/src/plugins/layout/StatPlugin.tsx +1 -4
- package/src/plugins/plugins.ts +0 -2
- package/src/utils/__tests__/dates.test.ts +24 -45
- package/src/utils/__tests__/numbers.test.ts +30 -42
- package/src/utils/dates.ts +10 -15
- package/src/utils/edit-distance.ts +6 -8
- package/src/utils/errors.ts +1 -1
- package/src/utils/id-tree.tsx +10 -21
- package/src/utils/localStorage.ts +4 -13
- package/src/utils/numbers.ts +11 -11
- package/src/utils/once.ts +0 -32
- package/src/utils/paths.ts +1 -4
- package/src/utils/pluralize.ts +5 -12
- package/src/utils/python-poet/poet.ts +15 -30
- package/src/utils/time.ts +1 -5
- package/dist/assets/ConnectedDataExplorerComponent-CNLoZkWr.js +0 -19
- package/dist/assets/_baseEach-9_logFrf.js +0 -1
- package/dist/assets/_baseMap-NzEbKt5c.js +0 -1
- package/dist/assets/_baseUniq-C5LFcyNC.js +0 -1
- package/dist/assets/channel-DHcKBVM4.js +0 -1
- package/dist/assets/chat-panel-DgJZr0eS.js +0 -3
- package/dist/assets/classDiagram-KNZD7YFC-D-xwLnlX.js +0 -1
- package/dist/assets/classDiagram-v2-RKCZMP56-D-xwLnlX.js +0 -1
- package/dist/assets/clone-CSxIll62.js +0 -1
- package/dist/assets/datasources-panel-Bt41Zir-.js +0 -1
- package/dist/assets/edit-page-CyTMQV2u.js +0 -129
- package/dist/assets/file-explorer-panel-Oy9DbyFP.js +0 -1
- package/dist/assets/home-page-Bvwppn9N.js +0 -9
- package/dist/assets/index-DadI618h.css +0 -1
- package/dist/assets/index-PmY0x4Zd.js +0 -578
- package/dist/assets/infoDiagram-STP46IZ2-CAuVVehw.js +0 -2
- package/dist/assets/links-4B6ldZ5P.js +0 -7
- package/dist/assets/min-DtVSfYKl.js +0 -1
- package/dist/assets/outline-panel-CMJjOoN7.js +0 -1
- package/dist/assets/snippets-panel-ClNnwKBM.js +0 -1
- package/dist/assets/sortBy-D47H6Vyl.js +0 -1
- package/dist/assets/stateDiagram-v2-UMBNRL4Z-DbA-iToo.js +0 -1
- package/dist/assets/storage-BNcWOH3-.js +0 -26
- package/dist/assets/tracing-DUbJtOyq.js +0 -2
- package/dist/assets/variable-panel-BbgupOdG.js +0 -1
- package/dist/assets/worker-fHbtoWvT.js +0 -1
- package/src/components/data-table/cell-hover-template/feature.ts +0 -14
- package/src/components/data-table/cell-hover-template/types.ts +0 -11
- package/src/core/i18n/__tests__/locale-provider.test.tsx +0 -176
- package/src/core/i18n/locale-provider.tsx +0 -35
- package/src/core/i18n/with-locale.tsx +0 -12
- package/src/hooks/useFormatting.ts +0 -97
- package/src/plugins/layout/OutlinePlugin.tsx +0 -69
- package/src/utils/__tests__/once.test.ts +0 -187
|
@@ -17,10 +17,8 @@ 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(timeout = 10_000) {
|
|
22
|
-
this.timeout = timeout;
|
|
23
|
-
}
|
|
20
|
+
|
|
21
|
+
constructor(private timeout = 10_000) {}
|
|
24
22
|
|
|
25
23
|
get(key: string): Promise<Model<any>> {
|
|
26
24
|
let deferred = this.models.get(key);
|
|
@@ -66,25 +64,16 @@ export class Model<T extends Record<string, any>> implements AnyModel<T> {
|
|
|
66
64
|
private ANY_CHANGE_EVENT = "change";
|
|
67
65
|
private dirtyFields;
|
|
68
66
|
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>;
|
|
75
67
|
|
|
76
68
|
constructor(
|
|
77
|
-
data: T,
|
|
78
|
-
onChange: (value: Partial<T>) => void,
|
|
79
|
-
sendToWidget: (req: {
|
|
69
|
+
private data: T,
|
|
70
|
+
private onChange: (value: Partial<T>) => void,
|
|
71
|
+
private sendToWidget: (req: {
|
|
80
72
|
content?: any;
|
|
81
73
|
buffers?: ArrayBuffer[] | ArrayBufferView[];
|
|
82
74
|
}) => Promise<null | undefined>,
|
|
83
75
|
initialDirtyFields: Set<keyof T>,
|
|
84
76
|
) {
|
|
85
|
-
this.data = data;
|
|
86
|
-
this.onChange = onChange;
|
|
87
|
-
this.sendToWidget = sendToWidget;
|
|
88
77
|
this.dirtyFields = new Set(initialDirtyFields);
|
|
89
78
|
}
|
|
90
79
|
|
|
@@ -10,13 +10,11 @@ export interface PositionalEdit {
|
|
|
10
10
|
value: unknown;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export
|
|
14
|
-
Insert
|
|
15
|
-
Remove
|
|
16
|
-
Rename
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type BulkEdit = (typeof BulkEdit)[keyof typeof BulkEdit];
|
|
13
|
+
export enum BulkEdit {
|
|
14
|
+
Insert = "insert",
|
|
15
|
+
Remove = "remove",
|
|
16
|
+
Rename = "rename",
|
|
17
|
+
}
|
|
20
18
|
|
|
21
19
|
export interface RowEdit {
|
|
22
20
|
rowIdx: number;
|
|
@@ -3,7 +3,6 @@
|
|
|
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";
|
|
7
6
|
import { Button } from "@/components/ui/button";
|
|
8
7
|
import {
|
|
9
8
|
Select,
|
|
@@ -132,9 +131,7 @@ export const ColumnSummary: React.FC<Props> = ({ schema }) => {
|
|
|
132
131
|
{STAT_KEYS.map((key) => (
|
|
133
132
|
<div key={key} className="flex flex-row gap-2 min-w-[100px]">
|
|
134
133
|
<span className="font-semibold">{key}</span>
|
|
135
|
-
<span>
|
|
136
|
-
<FormatStat value={stats?.[key]} />
|
|
137
|
-
</span>
|
|
134
|
+
<span>{formatStat(stats?.[key])}</span>
|
|
138
135
|
</div>
|
|
139
136
|
))}
|
|
140
137
|
</div>
|
|
@@ -154,28 +151,24 @@ const STAT_KEYS = [
|
|
|
154
151
|
"stdev",
|
|
155
152
|
];
|
|
156
153
|
|
|
157
|
-
|
|
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
|
-
|
|
154
|
+
function formatStat(value: unknown) {
|
|
170
155
|
if (typeof value === "number") {
|
|
171
|
-
|
|
156
|
+
// Decimal .2
|
|
157
|
+
return new Intl.NumberFormat("en-US", {
|
|
158
|
+
maximumFractionDigits: 2,
|
|
159
|
+
}).format(value);
|
|
172
160
|
}
|
|
173
161
|
if (typeof value === "string") {
|
|
174
162
|
return value;
|
|
175
163
|
}
|
|
176
164
|
if (typeof value === "object" && value instanceof Date) {
|
|
177
|
-
|
|
165
|
+
// Just day, month, year
|
|
166
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
167
|
+
year: "numeric",
|
|
168
|
+
month: "short",
|
|
169
|
+
day: "numeric",
|
|
170
|
+
}).format(value);
|
|
178
171
|
}
|
|
179
172
|
|
|
180
173
|
return String(value);
|
|
181
|
-
}
|
|
174
|
+
}
|
|
@@ -57,13 +57,11 @@ 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;
|
|
62
60
|
|
|
63
|
-
constructor(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
61
|
+
constructor(
|
|
62
|
+
private processEvents: () => void,
|
|
63
|
+
private blockDuration = 200,
|
|
64
|
+
) {}
|
|
67
65
|
|
|
68
66
|
add(event: T) {
|
|
69
67
|
this.buffer.push(event);
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { TriangleIcon } from "lucide-react";
|
|
4
4
|
import type { JSX } from "react";
|
|
5
|
-
import { useLocale } from "react-aria";
|
|
6
5
|
import { z } from "zod";
|
|
7
6
|
import { cn } from "@/utils/cn";
|
|
8
7
|
import { prettyNumber } from "@/utils/numbers";
|
|
@@ -42,8 +41,6 @@ export const StatComponent: React.FC<Data> = ({
|
|
|
42
41
|
bordered,
|
|
43
42
|
direction,
|
|
44
43
|
}) => {
|
|
45
|
-
const { locale } = useLocale();
|
|
46
|
-
|
|
47
44
|
const renderPrettyValue = () => {
|
|
48
45
|
if (value == null) {
|
|
49
46
|
return <i>No value</i>;
|
|
@@ -54,7 +51,7 @@ export const StatComponent: React.FC<Data> = ({
|
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
if (typeof value === "number") {
|
|
57
|
-
return prettyNumber(value
|
|
54
|
+
return prettyNumber(value);
|
|
58
55
|
}
|
|
59
56
|
|
|
60
57
|
if (typeof value === "boolean") {
|
package/src/plugins/plugins.ts
CHANGED
|
@@ -45,7 +45,6 @@ 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";
|
|
49
48
|
import { ProgressPlugin } from "./layout/ProgressPlugin";
|
|
50
49
|
import { RoutesPlugin } from "./layout/RoutesPlugin";
|
|
51
50
|
import { StatPlugin } from "./layout/StatPlugin";
|
|
@@ -100,7 +99,6 @@ const LAYOUT_PLUGINS: Array<IStatelessPlugin<unknown>> = [
|
|
|
100
99
|
new MimeRendererPlugin(),
|
|
101
100
|
new MermaidPlugin(),
|
|
102
101
|
new NavigationMenuPlugin(),
|
|
103
|
-
new OutlinePlugin(),
|
|
104
102
|
new ProgressPlugin(),
|
|
105
103
|
new RoutesPlugin(),
|
|
106
104
|
new StatPlugin(),
|
|
@@ -8,8 +8,6 @@ import {
|
|
|
8
8
|
timeAgo,
|
|
9
9
|
} from "../dates";
|
|
10
10
|
|
|
11
|
-
const locale = "en-US";
|
|
12
|
-
|
|
13
11
|
describe("dates", () => {
|
|
14
12
|
// Save original timezone
|
|
15
13
|
let originalTimezone: string | undefined;
|
|
@@ -27,38 +25,36 @@ describe("dates", () => {
|
|
|
27
25
|
|
|
28
26
|
describe("prettyDate", () => {
|
|
29
27
|
it("returns empty string for null or undefined", () => {
|
|
30
|
-
expect(prettyDate(null, "date"
|
|
31
|
-
expect(prettyDate(undefined, "date"
|
|
28
|
+
expect(prettyDate(null, "date")).toBe("");
|
|
29
|
+
expect(prettyDate(undefined, "date")).toBe("");
|
|
32
30
|
});
|
|
33
31
|
|
|
34
32
|
it("formats date correctly", () => {
|
|
35
33
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
36
34
|
// Using a regex to match the pattern since exact format may vary by locale
|
|
37
|
-
expect(prettyDate(date.toISOString(), "date"
|
|
38
|
-
/May 15, 2023/,
|
|
39
|
-
);
|
|
35
|
+
expect(prettyDate(date.toISOString(), "date")).toMatch(/May 15, 2023/);
|
|
40
36
|
});
|
|
41
37
|
|
|
42
38
|
it("formats datetime correctly", () => {
|
|
43
39
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
44
|
-
expect(prettyDate(date.toISOString(), "datetime"
|
|
40
|
+
expect(prettyDate(date.toISOString(), "datetime")).toMatch(
|
|
45
41
|
/May 15, 2023/,
|
|
46
42
|
);
|
|
47
43
|
});
|
|
48
44
|
|
|
49
45
|
it("handles errors gracefully", () => {
|
|
50
|
-
expect(prettyDate("invalid-date", "date"
|
|
46
|
+
expect(prettyDate("invalid-date", "date")).toBe("Invalid Date");
|
|
51
47
|
});
|
|
52
48
|
|
|
53
49
|
it("handles numeric timestamp input", () => {
|
|
54
50
|
const timestamp = 1_684_152_000_000; // 2023-05-15T12:00:00Z in milliseconds
|
|
55
|
-
expect(prettyDate(timestamp, "date"
|
|
51
|
+
expect(prettyDate(timestamp, "date")).toMatch(/May 15, 2023/);
|
|
56
52
|
});
|
|
57
53
|
|
|
58
54
|
it("preserves timezone for datetime type", () => {
|
|
59
55
|
// This date is in winter time to avoid daylight saving time issues
|
|
60
56
|
const date = new Date("2023-01-15T15:30:00Z");
|
|
61
|
-
expect(prettyDate(date.toISOString(), "datetime"
|
|
57
|
+
expect(prettyDate(date.toISOString(), "datetime")).toMatch(
|
|
62
58
|
/Jan 15, 2023/,
|
|
63
59
|
);
|
|
64
60
|
});
|
|
@@ -66,9 +62,7 @@ describe("dates", () => {
|
|
|
66
62
|
it("drops timezone for date type by using UTC", () => {
|
|
67
63
|
// Create a date that would be different days in different timezones
|
|
68
64
|
const date = new Date("2023-05-15T23:30:00Z"); // Late in the day UTC
|
|
69
|
-
expect(prettyDate(date.toISOString(), "date"
|
|
70
|
-
/May 15, 2023/,
|
|
71
|
-
);
|
|
65
|
+
expect(prettyDate(date.toISOString(), "date")).toMatch(/May 15, 2023/);
|
|
72
66
|
});
|
|
73
67
|
|
|
74
68
|
describe("with different locales", () => {
|
|
@@ -92,9 +86,7 @@ describe("dates", () => {
|
|
|
92
86
|
};
|
|
93
87
|
|
|
94
88
|
const date = new Date("2023-05-15T12:00:00Z");
|
|
95
|
-
expect(prettyDate(date.toISOString(), "date"
|
|
96
|
-
"15 mai 2023",
|
|
97
|
-
);
|
|
89
|
+
expect(prettyDate(date.toISOString(), "date")).toBe("15 mai 2023");
|
|
98
90
|
});
|
|
99
91
|
});
|
|
100
92
|
});
|
|
@@ -102,42 +94,34 @@ describe("dates", () => {
|
|
|
102
94
|
describe("exactDateTime", () => {
|
|
103
95
|
it("formats date without milliseconds", () => {
|
|
104
96
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
105
|
-
expect(exactDateTime(date, undefined
|
|
106
|
-
"2023-05-15 12:00:00",
|
|
107
|
-
);
|
|
97
|
+
expect(exactDateTime(date, undefined)).toBe("2023-05-15 12:00:00");
|
|
108
98
|
});
|
|
109
99
|
|
|
110
100
|
it("formats date with milliseconds", () => {
|
|
111
101
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
112
|
-
expect(exactDateTime(date, undefined
|
|
113
|
-
"2023-05-15 12:00:00.123",
|
|
114
|
-
);
|
|
102
|
+
expect(exactDateTime(date, undefined)).toBe("2023-05-15 12:00:00.123");
|
|
115
103
|
});
|
|
116
104
|
|
|
117
105
|
it("formats date in UTC when renderInUTC is true", () => {
|
|
118
106
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
119
|
-
expect(exactDateTime(date, "UTC"
|
|
120
|
-
"2023-05-15 12:00:00 UTC",
|
|
121
|
-
);
|
|
107
|
+
expect(exactDateTime(date, "UTC")).toBe("2023-05-15 12:00:00 UTC");
|
|
122
108
|
});
|
|
123
109
|
|
|
124
110
|
it("formats date with milliseconds in UTC when renderInUTC is true", () => {
|
|
125
111
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
126
|
-
expect(exactDateTime(date, "UTC"
|
|
127
|
-
"2023-05-15 12:00:00.123 UTC",
|
|
128
|
-
);
|
|
112
|
+
expect(exactDateTime(date, "UTC")).toBe("2023-05-15 12:00:00.123 UTC");
|
|
129
113
|
});
|
|
130
114
|
|
|
131
115
|
it("formats date in America/New_York timezone", () => {
|
|
132
116
|
const date = new Date("2023-05-15T12:00:00.000Z");
|
|
133
|
-
expect(exactDateTime(date, "America/New_York"
|
|
117
|
+
expect(exactDateTime(date, "America/New_York")).toBe(
|
|
134
118
|
"2023-05-15 08:00:00 EDT",
|
|
135
119
|
);
|
|
136
120
|
});
|
|
137
121
|
|
|
138
122
|
it("formats date with milliseconds in America/New_York timezone", () => {
|
|
139
123
|
const date = new Date("2023-05-15T12:00:00.123Z");
|
|
140
|
-
expect(exactDateTime(date, "America/New_York"
|
|
124
|
+
expect(exactDateTime(date, "America/New_York")).toBe(
|
|
141
125
|
"2023-05-15 08:00:00.123 EDT",
|
|
142
126
|
);
|
|
143
127
|
});
|
|
@@ -145,47 +129,42 @@ describe("dates", () => {
|
|
|
145
129
|
|
|
146
130
|
describe("timeAgo", () => {
|
|
147
131
|
it("returns empty string for null, undefined, or 0", () => {
|
|
148
|
-
expect(timeAgo(null
|
|
149
|
-
expect(timeAgo(undefined
|
|
150
|
-
expect(timeAgo(0
|
|
132
|
+
expect(timeAgo(null)).toBe("");
|
|
133
|
+
expect(timeAgo(undefined)).toBe("");
|
|
134
|
+
expect(timeAgo(0)).toBe("");
|
|
151
135
|
});
|
|
152
136
|
|
|
153
137
|
it("formats today's date correctly", () => {
|
|
154
138
|
const today = new Date();
|
|
155
|
-
const result = timeAgo(today.toISOString()
|
|
139
|
+
const result = timeAgo(today.toISOString());
|
|
156
140
|
expect(result).toMatch(/Today at/);
|
|
157
141
|
});
|
|
158
142
|
|
|
159
143
|
it("formats yesterday's date correctly", () => {
|
|
160
144
|
const yesterday = new Date();
|
|
161
145
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
162
|
-
const result = timeAgo(yesterday.toISOString()
|
|
146
|
+
const result = timeAgo(yesterday.toISOString());
|
|
163
147
|
expect(result).toMatch(/Yesterday at/);
|
|
164
148
|
});
|
|
165
149
|
|
|
166
150
|
it("formats older dates correctly", () => {
|
|
167
151
|
const oldDate = new Date("2020-01-01T12:00:00Z");
|
|
168
|
-
const result = timeAgo(oldDate.toISOString()
|
|
152
|
+
const result = timeAgo(oldDate.toISOString());
|
|
169
153
|
expect(result).toMatch(/Jan 1, 2020 at/);
|
|
170
154
|
});
|
|
171
155
|
|
|
172
156
|
it("handles errors gracefully", () => {
|
|
173
|
-
expect(timeAgo("invalid-date"
|
|
174
|
-
"Invalid Date at Invalid Date",
|
|
175
|
-
);
|
|
157
|
+
expect(timeAgo("invalid-date")).toBe("Invalid Date at Invalid Date");
|
|
176
158
|
});
|
|
177
159
|
});
|
|
178
160
|
|
|
179
161
|
describe("getShortTimeZone", () => {
|
|
180
162
|
it("returns the short timezone", () => {
|
|
181
|
-
expect(getShortTimeZone("America/New_York"
|
|
182
|
-
"EDT",
|
|
183
|
-
"EST",
|
|
184
|
-
]);
|
|
163
|
+
expect(getShortTimeZone("America/New_York")).toBeOneOf(["EDT", "EST"]);
|
|
185
164
|
});
|
|
186
165
|
|
|
187
166
|
it("handles errors gracefully", () => {
|
|
188
|
-
expect(getShortTimeZone("MarimoLand"
|
|
167
|
+
expect(getShortTimeZone("MarimoLand")).toBe("MarimoLand");
|
|
189
168
|
});
|
|
190
169
|
});
|
|
191
170
|
|
|
@@ -6,32 +6,24 @@ import {
|
|
|
6
6
|
prettyScientificNumber,
|
|
7
7
|
} from "../numbers";
|
|
8
8
|
|
|
9
|
-
const locale = "en-US";
|
|
10
|
-
|
|
11
9
|
describe("prettyNumber", () => {
|
|
12
10
|
it("should format numbers", () => {
|
|
13
|
-
expect(prettyNumber(123_456_789
|
|
14
|
-
expect(prettyNumber(1234.567_89
|
|
15
|
-
expect(prettyNumber(0
|
|
11
|
+
expect(prettyNumber(123_456_789)).toBe("123,456,789");
|
|
12
|
+
expect(prettyNumber(1234.567_89)).toBe("1,234.57");
|
|
13
|
+
expect(prettyNumber(0)).toBe("0");
|
|
16
14
|
});
|
|
17
15
|
});
|
|
18
16
|
|
|
19
|
-
const options = { locale };
|
|
20
|
-
|
|
21
17
|
describe("prettyScientificNumber", () => {
|
|
22
18
|
it("should handle special cases", () => {
|
|
23
|
-
expect(prettyScientificNumber(0
|
|
24
|
-
expect(prettyScientificNumber(Number.NaN
|
|
25
|
-
expect(prettyScientificNumber(Number.POSITIVE_INFINITY
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
expect(prettyScientificNumber(Number.NEGATIVE_INFINITY, options)).toBe(
|
|
29
|
-
"-Infinity",
|
|
30
|
-
);
|
|
19
|
+
expect(prettyScientificNumber(0)).toBe("0");
|
|
20
|
+
expect(prettyScientificNumber(Number.NaN)).toBe("NaN");
|
|
21
|
+
expect(prettyScientificNumber(Number.POSITIVE_INFINITY)).toBe("Infinity");
|
|
22
|
+
expect(prettyScientificNumber(Number.NEGATIVE_INFINITY)).toBe("-Infinity");
|
|
31
23
|
});
|
|
32
24
|
|
|
33
25
|
it("should format decimals with scientific notation, ignoring integer part rounding", () => {
|
|
34
|
-
const opts = { shouldRound: true
|
|
26
|
+
const opts = { shouldRound: true };
|
|
35
27
|
expect(prettyScientificNumber(123_456, opts)).toBe("123,456");
|
|
36
28
|
expect(prettyScientificNumber(123_456.7, opts)).toBe("123,456.7");
|
|
37
29
|
expect(prettyScientificNumber(12_345.6789, opts)).toBe("12,345.68");
|
|
@@ -48,10 +40,10 @@ describe("prettyScientificNumber", () => {
|
|
|
48
40
|
});
|
|
49
41
|
|
|
50
42
|
it("should not round numbers when shouldRound is false", () => {
|
|
51
|
-
expect(prettyScientificNumber(123_456
|
|
52
|
-
expect(prettyScientificNumber(123_456.7
|
|
53
|
-
expect(prettyScientificNumber(12_345.6789
|
|
54
|
-
expect(prettyScientificNumber(1.234_567_891_011_12
|
|
43
|
+
expect(prettyScientificNumber(123_456)).toBe("123,456");
|
|
44
|
+
expect(prettyScientificNumber(123_456.7)).toBe("123,456.7");
|
|
45
|
+
expect(prettyScientificNumber(12_345.6789)).toBe("12,345.6789");
|
|
46
|
+
expect(prettyScientificNumber(1.234_567_891_011_12)).toBe(
|
|
55
47
|
"1.23456789101112",
|
|
56
48
|
);
|
|
57
49
|
});
|
|
@@ -59,30 +51,26 @@ describe("prettyScientificNumber", () => {
|
|
|
59
51
|
|
|
60
52
|
describe("prettyEngineeringNumber", () => {
|
|
61
53
|
it("should handle special cases", () => {
|
|
62
|
-
expect(prettyEngineeringNumber(0
|
|
63
|
-
expect(prettyEngineeringNumber(-0
|
|
64
|
-
expect(prettyEngineeringNumber(Number.NaN
|
|
65
|
-
expect(prettyEngineeringNumber(Number.POSITIVE_INFINITY
|
|
66
|
-
|
|
67
|
-
);
|
|
68
|
-
expect(prettyEngineeringNumber(Number.NEGATIVE_INFINITY, locale)).toBe(
|
|
69
|
-
"-Infinity",
|
|
70
|
-
);
|
|
54
|
+
expect(prettyEngineeringNumber(0)).toBe("0");
|
|
55
|
+
expect(prettyEngineeringNumber(-0)).toBe("0"); // Test with negative zero
|
|
56
|
+
expect(prettyEngineeringNumber(Number.NaN)).toBe("NaN");
|
|
57
|
+
expect(prettyEngineeringNumber(Number.POSITIVE_INFINITY)).toBe("Infinity");
|
|
58
|
+
expect(prettyEngineeringNumber(Number.NEGATIVE_INFINITY)).toBe("-Infinity");
|
|
71
59
|
});
|
|
72
60
|
|
|
73
61
|
it("should format decimals with engineering notation, ignoring integer part", () => {
|
|
74
|
-
expect(prettyEngineeringNumber(123_456
|
|
75
|
-
expect(prettyEngineeringNumber(123_456.7
|
|
76
|
-
expect(prettyEngineeringNumber(12_345.6789
|
|
77
|
-
expect(prettyEngineeringNumber(1.2345
|
|
78
|
-
expect(prettyEngineeringNumber(1.000_001_234
|
|
79
|
-
expect(prettyEngineeringNumber(0.12
|
|
80
|
-
expect(prettyEngineeringNumber(0.1234
|
|
81
|
-
expect(prettyEngineeringNumber(0.000_123_4
|
|
82
|
-
expect(prettyEngineeringNumber(-1.2345
|
|
83
|
-
expect(prettyEngineeringNumber(-1.000_001_234
|
|
84
|
-
expect(prettyEngineeringNumber(-0.12
|
|
85
|
-
expect(prettyEngineeringNumber(-0.1234
|
|
86
|
-
expect(prettyEngineeringNumber(-0.000_123_4
|
|
62
|
+
expect(prettyEngineeringNumber(123_456)).toBe("123k");
|
|
63
|
+
expect(prettyEngineeringNumber(123_456.7)).toBe("123k");
|
|
64
|
+
expect(prettyEngineeringNumber(12_345.6789)).toBe("12.3k");
|
|
65
|
+
expect(prettyEngineeringNumber(1.2345)).toBe("1.23");
|
|
66
|
+
expect(prettyEngineeringNumber(1.000_001_234)).toBe("1");
|
|
67
|
+
expect(prettyEngineeringNumber(0.12)).toBe("120m");
|
|
68
|
+
expect(prettyEngineeringNumber(0.1234)).toBe("123m");
|
|
69
|
+
expect(prettyEngineeringNumber(0.000_123_4)).toBe("123µ");
|
|
70
|
+
expect(prettyEngineeringNumber(-1.2345)).toBe("-1.23"); // Test with negative numbers
|
|
71
|
+
expect(prettyEngineeringNumber(-1.000_001_234)).toBe("-1");
|
|
72
|
+
expect(prettyEngineeringNumber(-0.12)).toBe("-120m");
|
|
73
|
+
expect(prettyEngineeringNumber(-0.1234)).toBe("-123m");
|
|
74
|
+
expect(prettyEngineeringNumber(-0.000_123_4)).toBe("-123µ");
|
|
87
75
|
});
|
|
88
76
|
});
|
package/src/utils/dates.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { Logger } from "./Logger";
|
|
|
7
7
|
export function prettyDate(
|
|
8
8
|
value: string | number | null | undefined,
|
|
9
9
|
type: "date" | "datetime",
|
|
10
|
-
locale: string,
|
|
11
10
|
): string {
|
|
12
11
|
if (value == null) {
|
|
13
12
|
return "";
|
|
@@ -17,7 +16,7 @@ export function prettyDate(
|
|
|
17
16
|
// If type is date, drop the timezone by rendering in UTC
|
|
18
17
|
// since dates are absolute
|
|
19
18
|
if (type === "date") {
|
|
20
|
-
return new Date(value).toLocaleDateString(
|
|
19
|
+
return new Date(value).toLocaleDateString(undefined, {
|
|
21
20
|
year: "numeric",
|
|
22
21
|
month: "short",
|
|
23
22
|
day: "numeric",
|
|
@@ -26,7 +25,7 @@ export function prettyDate(
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
// For datetime, we keep the original timezone
|
|
29
|
-
return new Date(value).toLocaleDateString(
|
|
28
|
+
return new Date(value).toLocaleDateString(undefined, {
|
|
30
29
|
year: "numeric",
|
|
31
30
|
month: "short",
|
|
32
31
|
day: "numeric",
|
|
@@ -44,13 +43,12 @@ export function prettyDate(
|
|
|
44
43
|
export function exactDateTime(
|
|
45
44
|
value: Date,
|
|
46
45
|
timezone: string | undefined,
|
|
47
|
-
locale: string,
|
|
48
46
|
): string {
|
|
49
47
|
const hasSubSeconds = value.getUTCMilliseconds() !== 0;
|
|
50
48
|
try {
|
|
51
49
|
if (timezone) {
|
|
52
50
|
const valueWithTimezone = new TZDate(value, timezone);
|
|
53
|
-
const shortTimeZone = getShortTimeZone(timezone
|
|
51
|
+
const shortTimeZone = getShortTimeZone(timezone);
|
|
54
52
|
if (hasSubSeconds) {
|
|
55
53
|
return `${formatDate(valueWithTimezone, "yyyy-MM-dd HH:mm:ss.SSS")} ${shortTimeZone}`;
|
|
56
54
|
}
|
|
@@ -68,9 +66,9 @@ export function exactDateTime(
|
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
export function getShortTimeZone(timezone: string
|
|
69
|
+
export function getShortTimeZone(timezone: string): string {
|
|
72
70
|
try {
|
|
73
|
-
const abbrev = new Intl.DateTimeFormat(
|
|
71
|
+
const abbrev = new Intl.DateTimeFormat("en-US", {
|
|
74
72
|
timeZone: timezone,
|
|
75
73
|
timeZoneName: "short",
|
|
76
74
|
})
|
|
@@ -90,10 +88,7 @@ export function getShortTimeZone(timezone: string, locale: string): string {
|
|
|
90
88
|
*
|
|
91
89
|
* If a date in the past, it should say "<date> at 8:00 AM".
|
|
92
90
|
*/
|
|
93
|
-
export function timeAgo(
|
|
94
|
-
value: string | number | null | undefined,
|
|
95
|
-
locale: string,
|
|
96
|
-
): string {
|
|
91
|
+
export function timeAgo(value: string | number | null | undefined): string {
|
|
97
92
|
if (value == null) {
|
|
98
93
|
return "";
|
|
99
94
|
}
|
|
@@ -108,22 +103,22 @@ export function timeAgo(
|
|
|
108
103
|
yesterday.setDate(yesterday.getDate() - 1);
|
|
109
104
|
|
|
110
105
|
if (date.toDateString() === today.toDateString()) {
|
|
111
|
-
return `Today at ${date.toLocaleTimeString(
|
|
106
|
+
return `Today at ${date.toLocaleTimeString(undefined, {
|
|
112
107
|
hour: "numeric",
|
|
113
108
|
minute: "numeric",
|
|
114
109
|
})}`;
|
|
115
110
|
}
|
|
116
111
|
if (date.toDateString() === yesterday.toDateString()) {
|
|
117
|
-
return `Yesterday at ${date.toLocaleTimeString(
|
|
112
|
+
return `Yesterday at ${date.toLocaleTimeString(undefined, {
|
|
118
113
|
hour: "numeric",
|
|
119
114
|
minute: "numeric",
|
|
120
115
|
})}`;
|
|
121
116
|
}
|
|
122
|
-
return `${date.toLocaleDateString(
|
|
117
|
+
return `${date.toLocaleDateString(undefined, {
|
|
123
118
|
year: "numeric",
|
|
124
119
|
month: "short",
|
|
125
120
|
day: "numeric",
|
|
126
|
-
})} at ${date.toLocaleTimeString(
|
|
121
|
+
})} at ${date.toLocaleTimeString(undefined, {
|
|
127
122
|
hour: "numeric",
|
|
128
123
|
minute: "numeric",
|
|
129
124
|
})}`;
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
INSERT
|
|
5
|
-
DELETE
|
|
6
|
-
SUBSTITUTE
|
|
7
|
-
MATCH
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type OperationType = (typeof OperationType)[keyof typeof OperationType];
|
|
3
|
+
export enum OperationType {
|
|
4
|
+
INSERT = "insert",
|
|
5
|
+
DELETE = "delete",
|
|
6
|
+
SUBSTITUTE = "substitute",
|
|
7
|
+
MATCH = "match",
|
|
8
|
+
}
|
|
11
9
|
|
|
12
10
|
export interface EditOperation {
|
|
13
11
|
type: OperationType;
|
package/src/utils/errors.ts
CHANGED
|
@@ -64,7 +64,7 @@ function safeJSONParse(message: string): unknown {
|
|
|
64
64
|
|
|
65
65
|
export class CellNotInitializedError extends Error {
|
|
66
66
|
constructor(
|
|
67
|
-
message = "The cell containing this UI element has not been run yet. Please run the cell first.",
|
|
67
|
+
message: string = "The cell containing this UI element has not been run yet. Please run the cell first.",
|
|
68
68
|
) {
|
|
69
69
|
super(message);
|
|
70
70
|
this.name = "CellNotInitializedError";
|
package/src/utils/id-tree.tsx
CHANGED
|
@@ -23,15 +23,11 @@ export type CellIndex = number & { __brand?: "CellIndex" };
|
|
|
23
23
|
* Tree data structure for handling ids with nested children
|
|
24
24
|
*/
|
|
25
25
|
export class TreeNode<T> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this.value = value;
|
|
32
|
-
this.isCollapsed = isCollapsed;
|
|
33
|
-
this.children = children;
|
|
34
|
-
}
|
|
26
|
+
constructor(
|
|
27
|
+
public value: T,
|
|
28
|
+
public isCollapsed: boolean,
|
|
29
|
+
public children: Array<TreeNode<T>>,
|
|
30
|
+
) {}
|
|
35
31
|
|
|
36
32
|
/**
|
|
37
33
|
* Recursively count the number of nodes in the tree
|
|
@@ -106,13 +102,10 @@ export class TreeNode<T> {
|
|
|
106
102
|
let uniqueId = 0;
|
|
107
103
|
|
|
108
104
|
export class CollapsibleTree<T> {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this.nodes = nodes;
|
|
114
|
-
this.id = id;
|
|
115
|
-
}
|
|
105
|
+
private constructor(
|
|
106
|
+
public readonly nodes: Array<TreeNode<T>>,
|
|
107
|
+
public readonly id: CellColumnId,
|
|
108
|
+
) {}
|
|
116
109
|
|
|
117
110
|
static from<T>(ids: T[]): CollapsibleTree<T> {
|
|
118
111
|
const id = `tree_${uniqueId++}` as CellColumnId;
|
|
@@ -599,11 +592,7 @@ export class CollapsibleTree<T> {
|
|
|
599
592
|
}
|
|
600
593
|
|
|
601
594
|
export class MultiColumn<T> {
|
|
602
|
-
private readonly columns: ReadonlyArray<CollapsibleTree<T
|
|
603
|
-
|
|
604
|
-
constructor(columns: ReadonlyArray<CollapsibleTree<T>>) {
|
|
605
|
-
this.columns = columns;
|
|
606
|
-
|
|
595
|
+
constructor(private readonly columns: ReadonlyArray<CollapsibleTree<T>>) {
|
|
607
596
|
// Ensure there is always at least one column
|
|
608
597
|
if (columns.length === 0) {
|
|
609
598
|
this.columns = [CollapsibleTree.from([])];
|