@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.
Files changed (284) hide show
  1. package/dist/assets/ConnectedDataExplorerComponent-B5cPvWoQ.js +19 -0
  2. package/dist/assets/{ImageComparisonComponent-fTHv1Ih0.js → ImageComparisonComponent-CqR26LSv.js} +1 -1
  3. package/dist/assets/{VegaLite-Bdi-TyfY.js → VegaLite-DvQDATwI.js} +1 -1
  4. package/dist/assets/_baseEach--KDTwKbG.js +1 -0
  5. package/dist/assets/_baseMap-Cu3o-eyO.js +1 -0
  6. package/dist/assets/{_baseUniq-CCgDNtZb.js → _baseUniq-y7ZXnMo1.js} +1 -1
  7. package/dist/assets/{_createAggregator-DcD0kTA5.js → _createAggregator-ZcHkHPNJ.js} +1 -1
  8. package/dist/assets/{agent-panel-Crv430aI.js → agent-panel-B91RoLct.js} +76 -57
  9. package/dist/assets/{any-language-editor-CQh552Wu.js → any-language-editor-CxfHcm5h.js} +1 -1
  10. package/dist/assets/{architectureDiagram-W76B3OCA-BAJeBxzt.js → architectureDiagram-W76B3OCA-BQsvK8uR.js} +1 -1
  11. package/dist/assets/{between-horizontal-start-Boxgxbt_.js → between-horizontal-start-BmYToIaM.js} +1 -1
  12. package/dist/assets/{blockDiagram-QIGZ2CNN-CL-1svEK.js → blockDiagram-QIGZ2CNN-r3HgCj4w.js} +1 -1
  13. package/dist/assets/{c4Diagram-FPNF74CW-BbEqbCTl.js → c4Diagram-FPNF74CW-BJbPNt41.js} +1 -1
  14. package/dist/assets/channel-DFaEx1fu.js +1 -0
  15. package/dist/assets/chat-panel-IoPMv8e2.js +3 -0
  16. package/dist/assets/{chunk-4BX2VUAB-C--8TXeE.js → chunk-4BX2VUAB-Dv4MZ9Hj.js} +1 -1
  17. package/dist/assets/{chunk-55IACEB6-Bj00HDqq.js → chunk-55IACEB6-CM4AHquB.js} +1 -1
  18. package/dist/assets/{chunk-FMBD7UC4-C-lhB6hN.js → chunk-FMBD7UC4-C_Zz0ENB.js} +1 -1
  19. package/dist/assets/{chunk-K7UQS3LO-B-pGTXPt.js → chunk-K7UQS3LO-DYSmiXYq.js} +1 -1
  20. package/dist/assets/{chunk-QN33PNHL-DqUzGhvm.js → chunk-QN33PNHL-QM4OPuQP.js} +1 -1
  21. package/dist/assets/{chunk-QZHKN3VN-TntJHfSk.js → chunk-QZHKN3VN-CfAsGyeB.js} +1 -1
  22. package/dist/assets/{chunk-TVAH2DTR-HUJb1psV.js → chunk-TVAH2DTR-6j_Cpjsi.js} +1 -1
  23. package/dist/assets/{chunk-TZMSLE5B-BK3C__t3.js → chunk-TZMSLE5B-BHslFJQE.js} +1 -1
  24. package/dist/assets/{circle-play-DBLOv1Yu.js → circle-play-CK3UZRYQ.js} +1 -1
  25. package/dist/assets/classDiagram-KNZD7YFC-BsZtvV5O.js +1 -0
  26. package/dist/assets/classDiagram-v2-RKCZMP56-BsZtvV5O.js +1 -0
  27. package/dist/assets/{clear-button-BeoFbEKH.js → clear-button-C4fDVSv8.js} +1 -1
  28. package/dist/assets/clone-YBEvPE-s.js +1 -0
  29. package/dist/assets/command-palette-D7hOfvf6.js +1 -0
  30. package/dist/assets/{common-C7oJcmCT.js → common-D-lbuUwz.js} +1 -1
  31. package/dist/assets/{compile-7L0MwhyI.js → compile-DVQe1Mzk.js} +1 -1
  32. package/dist/assets/{cose-bilkent-S5V4N54A-BMkGLcVC.js → cose-bilkent-S5V4N54A-D-IS7WC8.js} +1 -1
  33. package/dist/assets/{dagre-5GWH7T2D-BJtRienS.js → dagre-5GWH7T2D-lYu-tEWT.js} +1 -1
  34. package/dist/assets/{data-grid-overlay-editor-DBkmGtNs.js → data-grid-overlay-editor-C5peOCit.js} +1 -1
  35. package/dist/assets/datasources-panel-D3NA20uZ.js +1 -0
  36. package/dist/assets/{dependency-graph-panel-DEdOxp2X.js → dependency-graph-panel-BGVYOfkV.js} +1 -1
  37. package/dist/assets/{diagram-N5W7TBWH-CmECY3nb.js → diagram-N5W7TBWH-BnvIuYUp.js} +1 -1
  38. package/dist/assets/{diagram-QEK2KX5R-DMOVSNKD.js → diagram-QEK2KX5R-DemedRK3.js} +1 -1
  39. package/dist/assets/{diagram-S2PKOQOG-BiJ96PNQ.js → diagram-S2PKOQOG-iiY7AuyH.js} +1 -1
  40. package/dist/assets/{documentation-panel-xULhaEv3.js → documentation-panel-C3dSwOSQ.js} +1 -1
  41. package/dist/assets/edit-page-C5TsEeSo.js +129 -0
  42. package/dist/assets/{ellipsis-vertical-BBqXIlc2.js → ellipsis-vertical-CazJl8M7.js} +1 -1
  43. package/dist/assets/{empty-state-B3dA3G5P.js → empty-state-DW308mFO.js} +1 -1
  44. package/dist/assets/{erDiagram-AWTI2OKA-MP1DiFRo.js → erDiagram-AWTI2OKA-6wQ8Ugg0.js} +1 -1
  45. package/dist/assets/{error-panel-Cc1sv-Ag.js → error-panel-D1VnJ1yP.js} +1 -1
  46. package/dist/assets/file-explorer-panel-0oVd4t-D.js +1 -0
  47. package/dist/assets/{flowDiagram-PVAE7QVJ-BX7caPp7.js → flowDiagram-PVAE7QVJ-C55IUWjm.js} +1 -1
  48. package/dist/assets/{ganttDiagram-OWAHRB6G-B462g4Yf.js → ganttDiagram-OWAHRB6G-DmqCM6ME.js} +4 -4
  49. package/dist/assets/{gitGraphDiagram-NY62KEGX-CGgvZ9-9.js → gitGraphDiagram-NY62KEGX-DBvhAeM_.js} +1 -1
  50. package/dist/assets/{glide-data-editor-C0gUFZON.js → glide-data-editor-CHNuHidQ.js} +4 -4
  51. package/dist/assets/{graph-CHRVBzY5.js → graph-CG6BgUWQ.js} +1 -1
  52. package/dist/assets/home-page-dgivXuSR.js +9 -0
  53. package/dist/assets/{index-Clbi_Yaq.js → index-BTGpssVX.js} +1 -1
  54. package/dist/assets/{index-CQDrxQ0j.js → index-BYVZlBF8.js} +1 -1
  55. package/dist/assets/{index-lYa_leQE.js → index-BelfnXwL.js} +1 -1
  56. package/dist/assets/{index-DRMm6SNo.js → index-BneyUujp.js} +1 -1
  57. package/dist/assets/{index-BY93Ejhl.js → index-C02SqeRj.js} +1 -1
  58. package/dist/assets/{index-C-8WADat.js → index-C7dtgr9A.js} +1 -1
  59. package/dist/assets/{index-D9UKkrr2.js → index-CAQvMTzM.js} +1 -1
  60. package/dist/assets/index-CGDMlQfO.css +1 -0
  61. package/dist/assets/index-CelXfcd8.js +580 -0
  62. package/dist/assets/{index-vmICa5KN.js → index-Csd6QrCV.js} +1 -1
  63. package/dist/assets/{index-DoRmcrKM.js → index-CtPksxf0.js} +1 -1
  64. package/dist/assets/{index-C1v_Z9et.js → index-Cxyk7pt-.js} +1 -1
  65. package/dist/assets/{index-CpTPJo4k.js → index-DAZ-9ri2.js} +1 -1
  66. package/dist/assets/{index-DEQvTChO.js → index-DONRrmA2.js} +1 -1
  67. package/dist/assets/{index-C4Tn5NvJ.js → index-Db36XTG_.js} +1 -1
  68. package/dist/assets/{index-z9bohSQJ.js → index-DdIhdEVw.js} +1 -1
  69. package/dist/assets/{index-C-GhZ7ti.js → index-M_pBKDSe.js} +1 -1
  70. package/dist/assets/{index-C77h_TXN.js → index-_luCZMLM.js} +1 -1
  71. package/dist/assets/{index-D1vmG6DS.js → index-mkubqy9-.js} +1 -1
  72. package/dist/assets/{index-BVgAenPd.js → index-sbO9UaUU.js} +1 -1
  73. package/dist/assets/{index-CWMgowgL.js → index-z4krxQ4j.js} +1 -1
  74. package/dist/assets/infoDiagram-STP46IZ2-wTALjfPc.js +2 -0
  75. package/dist/assets/{isEmpty-DU_ogP_D.js → isEmpty-CqX_YTIf.js} +1 -1
  76. package/dist/assets/{journeyDiagram-BIP6EPQ6-C6EgLP_Q.js → journeyDiagram-BIP6EPQ6-Y5w_Tqe_.js} +1 -1
  77. package/dist/assets/{kanban-definition-6OIFK2YF-BXzYO1yj.js → kanban-definition-6OIFK2YF-DbXs5Rxi.js} +1 -1
  78. package/dist/assets/{layout-jihVw5-i.js → layout-BCNPDACj.js} +1 -1
  79. package/dist/assets/{linear-C4blANlC.js → linear-uO6UVhXt.js} +1 -1
  80. package/dist/assets/links-Drv7cJgN.js +7 -0
  81. package/dist/assets/{logs-panel-D401qzZh.js → logs-panel-BEQ1eRUp.js} +1 -1
  82. package/dist/assets/{markdown-renderer-Cd9eYyaL.js → markdown-renderer-Dmzbb00W.js} +20 -20
  83. package/dist/assets/{mermaid-BEVuRz_O.js → mermaid-qRc4MXIj.js} +1 -1
  84. package/dist/assets/{mermaid.core-CaSnaLH0.js → mermaid.core-CvvJtCRj.js} +4 -4
  85. package/dist/assets/min-DYUOb1RR.js +1 -0
  86. package/dist/assets/{mindmap-definition-Q6HEUPPD-BXUM5MT2.js → mindmap-definition-Q6HEUPPD-G5NognM-.js} +1 -1
  87. package/dist/assets/{number-overlay-editor-4uWXGlPG.js → number-overlay-editor-DPr5sHFu.js} +1 -1
  88. package/dist/assets/outline-panel-gxQXvVi4.js +1 -0
  89. package/dist/assets/{packages-panel-CJL0MVlj.js → packages-panel-B1T0VPlg.js} +1 -1
  90. package/dist/assets/{pieDiagram-ADFJNKIX-Dxt5PVNo.js → pieDiagram-ADFJNKIX-DK9SHkfc.js} +1 -1
  91. package/dist/assets/{quadrantDiagram-LMRXKWRM-D4pUaA31.js → quadrantDiagram-LMRXKWRM-D1DdWF8C.js} +1 -1
  92. package/dist/assets/{react-plotly-cJZ0VWBq.js → react-plotly-CTwajqCb.js} +1 -1
  93. package/dist/assets/{requirementDiagram-4UW4RH46-DVRTjgas.js → requirementDiagram-4UW4RH46-DnjDAypr.js} +1 -1
  94. package/dist/assets/{run-page-BUEnMC9w.js → run-page-CQY9im22.js} +1 -1
  95. package/dist/assets/{sankeyDiagram-GR3RE2ED-CVFnD9C-.js → sankeyDiagram-GR3RE2ED-B67Va-ER.js} +1 -1
  96. package/dist/assets/{scratchpad-panel-BIgRENkI.js → scratchpad-panel-DlDfcDtW.js} +1 -1
  97. package/dist/assets/{secrets-panel-xY5-V_BD.js → secrets-panel-BDGyuGZA.js} +1 -1
  98. package/dist/assets/{sequenceDiagram-C3RYC4MD-_lY4ZN_S.js → sequenceDiagram-C3RYC4MD-DiWgZPtN.js} +1 -1
  99. package/dist/assets/{slides-component-DMjQomc3.css → slides-component-C-LoGC1U.css} +1 -1
  100. package/dist/assets/{slides-component-Xjymwj7X.js → slides-component-DhpPRtQp.js} +1 -1
  101. package/dist/assets/snippets-panel-CLkBXhJ2.js +1 -0
  102. package/dist/assets/sortBy-D4OG7w4O.js +1 -0
  103. package/dist/assets/{state-C4NiC9tO.js → state-Dz_3JyED.js} +1 -1
  104. package/dist/assets/{stateDiagram-KXAO66HF-Da0JQWCn.js → stateDiagram-KXAO66HF-ByF2AULw.js} +1 -1
  105. package/dist/assets/stateDiagram-v2-UMBNRL4Z-CtBJqosP.js +1 -0
  106. package/dist/assets/storage-Dr0CC44z.js +26 -0
  107. package/dist/assets/{terminal-BPwTkXae.js → terminal-BtdissBf.js} +1 -1
  108. package/dist/assets/{time-Dv5_Ouz_.js → time-DKdOTnQg.js} +1 -1
  109. package/dist/assets/{timeline-definition-XQNQX7LJ-Dxh5Zu2e.js → timeline-definition-XQNQX7LJ-DzER9bf6.js} +1 -1
  110. package/dist/assets/tracing-Dpx5M-u3.js +2 -0
  111. package/dist/assets/{tracing-panel-DAzrzNmm.js → tracing-panel-hCjBkSER.js} +2 -2
  112. package/dist/assets/{trash-Dc6DSjz_.js → trash-C6Ko-g5q.js} +1 -1
  113. package/dist/assets/{tree-jheoerAX.js → tree-BHN2gcCF.js} +6 -6
  114. package/dist/assets/{treemap-75Q7IDZK-IgpxeGaf.js → treemap-75Q7IDZK-DR79Mhzt.js} +27 -27
  115. package/dist/assets/variable-panel-PFBCFz36.js +1 -0
  116. package/dist/assets/{vega-component-BpfpiPKI.js → vega-component-Db6-uY4C.js} +1 -1
  117. package/dist/assets/worker-fHbtoWvT.js +1 -0
  118. package/dist/assets/{xychartDiagram-6GGTOJPD-CmNigJ31.js → xychartDiagram-6GGTOJPD-DWzBP3tZ.js} +1 -1
  119. package/dist/index.html +2 -2
  120. package/package.json +5 -4
  121. package/src/__mocks__/requests.ts +1 -0
  122. package/src/components/app-config/user-config-form.tsx +46 -1
  123. package/src/components/chat/acp/__tests__/__snapshots__/prompt.test.ts.snap +62 -43
  124. package/src/components/chat/acp/__tests__/atoms.test.ts +1 -1
  125. package/src/components/chat/acp/__tests__/state.test.ts +36 -36
  126. package/src/components/chat/acp/agent-panel.tsx +24 -27
  127. package/src/components/chat/acp/blocks.tsx +6 -6
  128. package/src/components/chat/acp/prompt.ts +62 -43
  129. package/src/components/chat/chat-panel.tsx +5 -1
  130. package/src/components/chat/markdown-renderer.tsx +6 -10
  131. package/src/components/chat/tool-call-accordion.tsx +52 -20
  132. package/src/components/data-table/SearchBar.tsx +8 -7
  133. package/src/components/data-table/__tests__/column_formatting.test.ts +50 -35
  134. package/src/components/data-table/__tests__/columns.test.tsx +38 -0
  135. package/src/components/data-table/__tests__/data-table.test.tsx +39 -1
  136. package/src/components/data-table/cell-hover-template/feature.ts +14 -0
  137. package/src/components/data-table/cell-hover-template/types.ts +11 -0
  138. package/src/components/data-table/charts/components/form-fields.tsx +41 -37
  139. package/src/components/data-table/charts/forms/common-chart.tsx +2 -2
  140. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +5 -2
  141. package/src/components/data-table/column-formatting/feature.ts +62 -29
  142. package/src/components/data-table/column-formatting/types.ts +1 -0
  143. package/src/components/data-table/column-header.tsx +3 -1
  144. package/src/components/data-table/column-summary/chart-spec-model.tsx +24 -7
  145. package/src/components/data-table/column-summary/column-summary.tsx +18 -9
  146. package/src/components/data-table/columns.tsx +63 -20
  147. package/src/components/data-table/data-table.tsx +10 -2
  148. package/src/components/data-table/date-popover.tsx +85 -75
  149. package/src/components/data-table/filter-pills.tsx +14 -9
  150. package/src/components/data-table/header-items.tsx +5 -1
  151. package/src/components/data-table/pagination.tsx +20 -13
  152. package/src/components/data-table/renderers.tsx +36 -0
  153. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +10 -8
  154. package/src/components/data-table/schemas.ts +16 -0
  155. package/src/components/datasources/column-preview.tsx +6 -2
  156. package/src/components/datasources/datasources.tsx +8 -12
  157. package/src/components/editor/Cell.tsx +2 -0
  158. package/src/components/editor/ai/transport/chat-transport.tsx +4 -1
  159. package/src/components/editor/cell/CellStatus.tsx +23 -20
  160. package/src/components/editor/cell/CreateCellButton.tsx +3 -4
  161. package/src/components/editor/cell/code/language-toggle.tsx +3 -4
  162. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +39 -28
  163. package/src/components/editor/controls/notebook-menu-dropdown.tsx +4 -2
  164. package/src/components/editor/errors/sql-validation-errors.tsx +34 -0
  165. package/src/components/editor/file-tree/requesting-tree.tsx +14 -8
  166. package/src/components/editor/output/ConsoleOutput.tsx +13 -1
  167. package/src/components/editor/output/MarimoErrorOutput.tsx +60 -1
  168. package/src/components/editor/renderers/CellArray.tsx +3 -4
  169. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +3 -3
  170. package/src/components/editor/renderers/slides-layout/types.ts +1 -0
  171. package/src/components/pages/home-page.tsx +4 -1
  172. package/src/components/slides/slides-component.tsx +1 -1
  173. package/src/components/slides/slides.css +6 -0
  174. package/src/components/terminal/theme.tsx +1 -0
  175. package/src/components/tracing/tracing-spec.ts +5 -4
  176. package/src/components/ui/range-slider.tsx +4 -2
  177. package/src/components/ui/slider.tsx +3 -1
  178. package/src/components/variables/variables-table.tsx +3 -0
  179. package/src/core/MarimoApp.tsx +9 -6
  180. package/src/core/ai/context/__tests__/registry.test.ts +6 -4
  181. package/src/core/ai/context/providers/cell-output.ts +4 -20
  182. package/src/core/ai/context/providers/error.ts +3 -1
  183. package/src/core/ai/context/providers/file.ts +7 -2
  184. package/src/core/ai/context/providers/tables.ts +3 -2
  185. package/src/core/ai/context/providers/variable.ts +6 -4
  186. package/src/core/ai/staged-cells.ts +34 -1
  187. package/src/core/cells/__tests__/add-missing-import.test.ts +67 -22
  188. package/src/core/cells/add-missing-import.ts +24 -7
  189. package/src/core/cells/cells.ts +26 -27
  190. package/src/core/cells/logs.ts +1 -1
  191. package/src/core/codemirror/find-replace/search-highlight.ts +3 -1
  192. package/src/core/codemirror/language/LanguageAdapters.ts +9 -3
  193. package/src/core/codemirror/language/__tests__/extension.test.ts +24 -0
  194. package/src/core/codemirror/language/__tests__/sql-validation.test.ts +133 -0
  195. package/src/core/codemirror/language/languages/sql/sql-mode.ts +20 -0
  196. package/src/core/codemirror/language/languages/sql/sql.ts +90 -3
  197. package/src/core/codemirror/language/languages/sql/validation-errors.ts +79 -0
  198. package/src/core/codemirror/language/panel/panel.tsx +8 -2
  199. package/src/core/codemirror/language/panel/sql.tsx +81 -4
  200. package/src/core/codemirror/lsp/notebook-lsp.ts +8 -2
  201. package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
  202. package/src/core/codemirror/rtc/loro/awareness.ts +52 -17
  203. package/src/core/codemirror/rtc/loro/sync.ts +12 -4
  204. package/src/core/config/config-schema.ts +1 -0
  205. package/src/core/config/config.ts +4 -0
  206. package/src/core/config/feature-flag.tsx +3 -1
  207. package/src/core/datasets/request-registry.ts +17 -1
  208. package/src/core/hotkeys/hotkeys.ts +8 -4
  209. package/src/core/i18n/__tests__/locale-provider.test.tsx +176 -0
  210. package/src/core/i18n/locale-provider.tsx +35 -0
  211. package/src/core/i18n/with-locale.tsx +12 -0
  212. package/src/core/islands/bridge.ts +1 -0
  213. package/src/core/islands/components/web-components.tsx +13 -10
  214. package/src/core/islands/main.ts +1 -0
  215. package/src/core/kernel/RuntimeState.ts +4 -1
  216. package/src/core/kernel/messages.ts +3 -2
  217. package/src/core/network/DeferredRequestRegistry.ts +16 -4
  218. package/src/core/network/requests-network.ts +7 -0
  219. package/src/core/network/requests-static.ts +1 -0
  220. package/src/core/network/requests-toasting.ts +1 -0
  221. package/src/core/network/types.ts +2 -0
  222. package/src/core/runtime/runtime.ts +5 -4
  223. package/src/core/wasm/bridge.ts +10 -1
  224. package/src/core/wasm/store.ts +4 -1
  225. package/src/core/wasm/worker/message-buffer.ts +3 -2
  226. package/src/core/websocket/types.ts +22 -16
  227. package/src/core/websocket/useMarimoWebSocket.tsx +4 -0
  228. package/src/hooks/useFormatting.ts +97 -0
  229. package/src/hooks/useTimer.ts +8 -5
  230. package/src/plugins/core/registerReactComponent.tsx +39 -29
  231. package/src/plugins/impl/DataTablePlugin.tsx +15 -4
  232. package/src/plugins/impl/RangeSliderPlugin.tsx +5 -3
  233. package/src/plugins/impl/SliderPlugin.tsx +3 -1
  234. package/src/plugins/impl/anywidget/model.ts +16 -5
  235. package/src/plugins/impl/data-editor/types.ts +7 -5
  236. package/src/plugins/impl/data-explorer/components/column-summary.tsx +20 -13
  237. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +17 -5
  238. package/src/plugins/impl/panel/utils.ts +6 -4
  239. package/src/plugins/layout/OutlinePlugin.tsx +69 -0
  240. package/src/plugins/layout/StatPlugin.tsx +4 -1
  241. package/src/plugins/plugins.ts +2 -0
  242. package/src/stories/dataframe.stories.tsx +2 -0
  243. package/src/utils/__tests__/dates.test.ts +45 -24
  244. package/src/utils/__tests__/dom.test.ts +167 -0
  245. package/src/utils/__tests__/numbers.test.ts +42 -30
  246. package/src/utils/__tests__/once.test.ts +187 -0
  247. package/src/utils/dates.ts +15 -10
  248. package/src/utils/dom.ts +55 -0
  249. package/src/utils/edit-distance.ts +8 -6
  250. package/src/utils/errors.ts +1 -1
  251. package/src/utils/id-tree.tsx +21 -10
  252. package/src/utils/localStorage.ts +13 -4
  253. package/src/utils/numbers.ts +11 -11
  254. package/src/utils/once.ts +32 -0
  255. package/src/utils/paths.ts +4 -1
  256. package/src/utils/pluralize.ts +12 -5
  257. package/src/utils/python-poet/poet.ts +30 -15
  258. package/src/utils/time.ts +5 -1
  259. package/dist/assets/ConnectedDataExplorerComponent-BErMbWvG.js +0 -19
  260. package/dist/assets/_baseEach-CNBxBxvS.js +0 -1
  261. package/dist/assets/_baseMap-D1WHjKrd.js +0 -1
  262. package/dist/assets/channel-_2eNSz0n.js +0 -1
  263. package/dist/assets/chat-panel-CXh5Wl6C.js +0 -3
  264. package/dist/assets/classDiagram-KNZD7YFC-BGmh9POF.js +0 -1
  265. package/dist/assets/classDiagram-v2-RKCZMP56-BGmh9POF.js +0 -1
  266. package/dist/assets/clone-BFDSPAj3.js +0 -1
  267. package/dist/assets/command-palette-CXZiSv0I.js +0 -1
  268. package/dist/assets/datasources-panel-B7FbYLiy.js +0 -1
  269. package/dist/assets/edit-page-BrYda9VE.js +0 -129
  270. package/dist/assets/file-explorer-panel-Bw59Kva1.js +0 -1
  271. package/dist/assets/home-page-Fb2osjys.js +0 -9
  272. package/dist/assets/index-Cx0bsY1w.css +0 -1
  273. package/dist/assets/index-DKEudB02.js +0 -578
  274. package/dist/assets/infoDiagram-STP46IZ2-CVyrdLc8.js +0 -2
  275. package/dist/assets/links-D59GIweI.js +0 -7
  276. package/dist/assets/min-DUMu_zeK.js +0 -1
  277. package/dist/assets/outline-panel-DIzkvm2I.js +0 -1
  278. package/dist/assets/snippets-panel-CTPYW41n.js +0 -1
  279. package/dist/assets/sortBy-BNZKwiq_.js +0 -1
  280. package/dist/assets/stateDiagram-v2-UMBNRL4Z-D5lYZOOt.js +0 -1
  281. package/dist/assets/storage-CMdLzB_c.js +0 -26
  282. package/dist/assets/tracing-BCIurUfa.js +0 -2
  283. package/dist/assets/variable-panel-DYAiLBmF.js +0 -1
  284. 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: (req: { format: "csv" | "json" | "parquet" }) => Promise<string>;
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: rpc
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
- valueMap(internalValue[0]),
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(private timeout = 10_000) {}
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
- private data: T,
70
- private onChange: (value: Partial<T>) => void,
71
- private sendToWidget: (req: {
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 enum BulkEdit {
14
- Insert = "insert",
15
- Remove = "remove",
16
- Rename = "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>{formatStat(stats?.[key])}</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
- function formatStat(value: unknown) {
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
- // Decimal .2
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
- // Just day, month, year
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={false}
274
- download_as={Functions.THROW}
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
- private processEvents: () => void,
63
- private blockDuration = 200,
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") {
@@ -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(),
@@ -40,6 +40,8 @@ export const DataFrame: StoryObj = {
40
40
  get_dataframe={() => Promise.reject(new Error("not implemented"))}
41
41
  search={Functions.THROW}
42
42
  host={document.body}
43
+ showDownload={false}
44
+ download_as={async () => ""}
43
45
  />
44
46
  );
45
47
  },
@@ -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(/May 15, 2023/);
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(/May 15, 2023/);
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("15 mai 2023");
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("2023-05-15 12:00:00");
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("2023-05-15 12:00:00.123");
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("2023-05-15 12:00:00 UTC");
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("2023-05-15 12:00:00.123 UTC");
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("Invalid Date at Invalid Date");
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(["EDT", "EST"]);
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