@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
@@ -52,7 +52,7 @@ export function getAgentPrompt(filename: string) {
52
52
  ## Best Practices
53
53
 
54
54
  <data_handling>
55
- - Use pandas for data manipulation
55
+ - Use polars for data manipulation
56
56
  - Implement proper data validation
57
57
  - Handle missing values appropriately
58
58
  - Use efficient data structures
@@ -62,7 +62,7 @@ export function getAgentPrompt(filename: string) {
62
62
  <visualization>
63
63
  - For matplotlib: use plt.gca() as the last expression instead of plt.show()
64
64
  - For plotly: return the figure object directly
65
- - For altair: return the chart object directly
65
+ - For altair: return the chart object directly. Add tooltips where appropriate. You can pass polars dataframes directly to altair.
66
66
  - Include proper labels, titles, and color schemes
67
67
  - Make visualizations interactive where appropriate
68
68
  </visualization>
@@ -76,7 +76,7 @@ export function getAgentPrompt(filename: string) {
76
76
  </ui_elements>
77
77
 
78
78
  <sql>
79
- - When writing duckdb, prefer using marimo's SQL cells, which start with _df = mo.sql(query)
79
+ - When writing duckdb, prefer using marimo's SQL cells, which start with df = mo.sql(f"""<your query>""") for DuckDB, or df = mo.sql(f"""<your query>""", engine=engine) for other SQL engines.
80
80
  - See the SQL with duckdb example for an example on how to do this
81
81
  - Don't add comments in cells that use mo.sql()
82
82
  - Consider using \`vega_datasets\` for common example datasets
@@ -144,7 +144,8 @@ export function getAgentPrompt(filename: string) {
144
144
  ${formatCells([
145
145
  `
146
146
  import marimo as mo
147
- import matplotlib.pyplot as plt
147
+ import altair as alt
148
+ import polars as pl
148
149
  import numpy as np
149
150
  `,
150
151
  `
@@ -155,12 +156,18 @@ export function getAgentPrompt(filename: string) {
155
156
  x = np.random.rand(n_points.value)
156
157
  y = np.random.rand(n_points.value)
157
158
 
158
- plt.figure(figsize=(8, 6))
159
- plt.scatter(x, y, alpha=0.7)
160
- plt.title(f"Scatter plot with {n_points.value} points")
161
- plt.xlabel("X axis")
162
- plt.ylabel("Y axis")
163
- plt.gca()
159
+ df = pl.DataFrame({"x": x, "y": y})
160
+
161
+ chart = alt.Chart(df).mark_circle(opacity=0.7).encode(
162
+ x=alt.X('x', title='X axis'),
163
+ y=alt.Y('y', title='Y axis')
164
+ ).properties(
165
+ title=f"Scatter plot with {n_points.value} points",
166
+ width=400,
167
+ height=300
168
+ )
169
+
170
+ chart
164
171
  `,
165
172
  ])}
166
173
  </example>
@@ -169,11 +176,11 @@ export function getAgentPrompt(filename: string) {
169
176
  ${formatCells([
170
177
  `
171
178
  import marimo as mo
172
- import pandas as pd
179
+ import polars as pl
173
180
  from vega_datasets import data
174
181
  `,
175
182
  `
176
- cars_df = data.cars()
183
+ cars_df = pl.DataFrame(data.cars())
177
184
  mo.ui.data_explorer(cars_df)
178
185
  `,
179
186
  ])}
@@ -183,43 +190,44 @@ export function getAgentPrompt(filename: string) {
183
190
  ${formatCells([
184
191
  `
185
192
  import marimo as mo
186
- import pandas as pd
187
- import matplotlib.pyplot as plt
188
- import seaborn as sns
193
+ import polars as pl
194
+ import altair as alt
189
195
  `,
190
196
  `
191
- iris = sns.load_dataset('iris')
197
+ iris = pl.read_csv("hf://datasets/scikit-learn/iris/Iris.csv")
192
198
  `,
193
199
  `
194
200
  species_selector = mo.ui.dropdown(
195
- options=["All"] + iris["species"].unique().tolist(),
201
+ options=["All"] + iris["Species"].unique().to_list(),
196
202
  value="All",
197
- label="Species"
203
+ label="Species",
198
204
  )
199
205
  x_feature = mo.ui.dropdown(
200
- options=iris.select_dtypes('number').columns.tolist(),
201
- value="sepal_length",
202
- label="X Feature"
206
+ options=iris.select(pl.col(pl.Float64, pl.Int64)).columns,
207
+ value="SepalLengthCm",
208
+ label="X Feature",
203
209
  )
204
210
  y_feature = mo.ui.dropdown(
205
- options=iris.select_dtypes('number').columns.tolist(),
206
- value="sepal_width",
207
- label="Y Feature"
211
+ options=iris.select(pl.col(pl.Float64, pl.Int64)).columns,
212
+ value="SepalWidthCm",
213
+ label="Y Feature",
208
214
  )
209
215
  mo.hstack([species_selector, x_feature, y_feature])
210
216
  `,
211
217
  `
212
- filtered_data = iris if species_selector.value == "All" else iris[iris["species"] == species_selector.value]
213
-
214
- plt.figure(figsize=(10, 6))
215
- sns.scatterplot(
216
- data=filtered_data,
217
- x=x_feature.value,
218
- y=y_feature.value,
219
- hue="species"
218
+ filtered_data = iris if species_selector.value == "All" else iris.filter(pl.col("Species") == species_selector.value)
219
+
220
+ chart = alt.Chart(filtered_data).mark_circle().encode(
221
+ x=alt.X(x_feature.value, title=x_feature.value),
222
+ y=alt.Y(y_feature.value, title=y_feature.value),
223
+ color='Species'
224
+ ).properties(
225
+ title=f"{y_feature.value} vs {x_feature.value}",
226
+ width=500,
227
+ height=400
220
228
  )
221
- plt.title(f"{y_feature.value} vs {x_feature.value}")
222
- plt.gca()
229
+
230
+ chart
223
231
  `,
224
232
  ])}
225
233
  </example>
@@ -242,14 +250,21 @@ export function getAgentPrompt(filename: string) {
242
250
  `
243
251
  import marimo as mo
244
252
  import altair as alt
245
- import pandas as pd
253
+ import polars as pl
246
254
  `,
247
255
  `# Load dataset
248
- cars_df = pd.read_csv('<https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json>')
249
- _chart = alt.Chart(cars_df).mark_point().encode(
250
- x='Horsepower',
251
- y='Miles_per_Gallon',
252
- color='Origin',
256
+ weather = pl.read_csv("https://raw.githubusercontent.com/vega/vega-datasets/refs/heads/main/data/weather.csv")
257
+ weather_dates = weather.with_columns(
258
+ pl.col("date").str.strptime(pl.Date, format="%Y-%m-%d")
259
+ )
260
+ _chart = (
261
+ alt.Chart(weather_dates)
262
+ .mark_point()
263
+ .encode(
264
+ x="date:T",
265
+ y="temp_max",
266
+ color="location",
267
+ )
253
268
  )
254
269
  `,
255
270
  "chart = mo.ui.altair_chart(_chart)\nchart",
@@ -278,9 +293,13 @@ export function getAgentPrompt(filename: string) {
278
293
 
279
294
  <example title="SQL with duckdb">
280
295
  ${formatCells([
281
- "import marimo as mo\nimport pandas as pd",
282
- `cars_df = pd.read_csv('<https://raw.githubusercontent.com/vega/vega-datasets/master/data/cars.json>')`,
283
- `_df = mo.sql("SELECT * from cars_df WHERE Miles_per_Gallon > 20")`,
296
+ "import marimo as mo\n import polars as pl",
297
+ `weather = pl.read_csv('https://raw.githubusercontent.com/vega/vega-datasets/refs/heads/main/data/weather.csv')`,
298
+ `seattle_weather_df = mo.sql(
299
+ f"""
300
+ SELECT * FROM weather WHERE location = 'Seattle';
301
+ """
302
+ )`,
284
303
  ])}
285
304
  </example>`;
286
305
  }
@@ -18,6 +18,7 @@ import {
18
18
  SquareIcon,
19
19
  } from "lucide-react";
20
20
  import { memo, useEffect, useMemo, useRef, useState } from "react";
21
+ import { useLocale } from "react-aria";
21
22
  import useEvent from "react-use-event-hook";
22
23
  import { Button } from "@/components/ui/button";
23
24
  import {
@@ -103,6 +104,7 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
103
104
  }) => {
104
105
  const { handleClick } = useOpenSettingsToTab();
105
106
  const chatState = useAtomValue(chatStateAtom);
107
+ const { locale } = useLocale();
106
108
  const chats = useMemo(() => {
107
109
  return [...chatState.chats.values()].sort(
108
110
  (a, b) => b.updatedAt - a.updatedAt,
@@ -159,7 +161,7 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
159
161
  >
160
162
  <div className="font-medium">{chat.title}</div>
161
163
  <div className="text-sm text-muted-foreground">
162
- {timeAgo(chat.updatedAt)}
164
+ {timeAgo(chat.updatedAt, locale)}
163
165
  </div>
164
166
  </button>
165
167
  ))}
@@ -236,6 +238,7 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
236
238
  result={part.output}
237
239
  className="my-2"
238
240
  state={part.state}
241
+ input={part.input}
239
242
  />
240
243
  );
241
244
  }
@@ -267,6 +270,7 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
267
270
  toolName={part.type}
268
271
  result={part.output}
269
272
  state={part.state}
273
+ input={part.input}
270
274
  className="my-2"
271
275
  />
272
276
  );
@@ -3,7 +3,7 @@
3
3
  import { EditorView } from "@codemirror/view";
4
4
  import { useAtomValue } from "jotai";
5
5
  import { BetweenHorizontalStartIcon } from "lucide-react";
6
- import { memo, Suspense, useEffect, useState } from "react";
6
+ import { memo, Suspense, useState } from "react";
7
7
  import { Streamdown, type StreamdownProps } from "streamdown";
8
8
  import { Button, type ButtonProps } from "@/components/ui/button";
9
9
  import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
@@ -114,9 +114,9 @@ const CodeBlock = ({ code, language }: CodeBlockProps) => {
114
114
  const { theme } = useTheme();
115
115
  const [value, setValue] = useState(code);
116
116
 
117
- useEffect(() => {
117
+ if (value !== code) {
118
118
  setValue(code);
119
- }, [code]);
119
+ }
120
120
 
121
121
  const handleCopyCode = async () => {
122
122
  await copyToClipboard(value);
@@ -150,18 +150,13 @@ const CodeBlock = ({ code, language }: CodeBlockProps) => {
150
150
  const CopyButton: React.FC<ButtonProps> = ({ onClick, ...props }) => {
151
151
  const [copied, setCopied] = useState(false);
152
152
 
153
- useEffect(() => {
154
- if (copied) {
155
- setTimeout(() => setCopied(false), 1000);
156
- }
157
- }, [copied]);
158
-
159
153
  return (
160
154
  <Button
161
155
  {...props}
162
156
  onClick={(e) => {
163
157
  onClick?.(e);
164
158
  setCopied(true);
159
+ setTimeout(() => setCopied(false), 1000);
165
160
  }}
166
161
  >
167
162
  {copied ? "Copied" : "Copy"}
@@ -175,10 +170,11 @@ const COMPONENTS: Components = {
175
170
  code: ({ children, className }) => {
176
171
  const language = className?.replace("language-", "");
177
172
  if (language && typeof children === "string") {
173
+ const code = children.trim();
178
174
  return (
179
175
  <div>
180
176
  <div className="text-xs text-muted-foreground pl-1">{language}</div>
181
- <CodeBlock code={children.trim()} language={language} />
177
+ <CodeBlock code={code} language={language} />
182
178
  </div>
183
179
  );
184
180
  }
@@ -45,17 +45,21 @@ const PrettySuccessResult: React.FC<{ data: SuccessResult }> = ({ data }) => {
45
45
  } = data;
46
46
 
47
47
  return (
48
- <div className="py-1 flex flex-col gap-1">
49
- {/* Status */}
50
- <div className="flex items-center gap-2">
51
- <span className="text-xs font-medium text-[var(--grass-11)] capitalize">
52
- {status}
53
- </span>
54
- {auth_required && (
55
- <span className="text-xs px-2 py-0.5 bg-[var(--amber-2)] text-[var(--amber-11)] rounded-full">
56
- Auth Required
48
+ <div className="flex flex-col gap-1.5">
49
+ <div className="flex items-center justify-between">
50
+ <h3 className="text-xs font-semibold text-muted-foreground">
51
+ Tool Result
52
+ </h3>
53
+ <div className="flex items-center gap-2">
54
+ <span className="text-xs px-2 py-0.5 bg-[var(--grass-2)] text-[var(--grass-11)] rounded-full font-medium capitalize">
55
+ {status}
57
56
  </span>
58
- )}
57
+ {auth_required && (
58
+ <span className="text-xs px-2 py-0.5 bg-[var(--amber-2)] text-[var(--amber-11)] rounded-full">
59
+ Auth Required
60
+ </span>
61
+ )}
62
+ </div>
59
63
  </div>
60
64
 
61
65
  {/* Message */}
@@ -68,17 +72,18 @@ const PrettySuccessResult: React.FC<{ data: SuccessResult }> = ({ data }) => {
68
72
 
69
73
  {/* Data */}
70
74
  {rest && (
71
- <div className="flex flex-col gap-1">
75
+ <div className="space-y-3">
72
76
  {Object.entries(rest).map(([key, value]) => {
73
77
  if (isEmpty(value)) {
74
78
  return null;
75
79
  }
76
80
  return (
77
- <div key={key}>
78
- <div className="text-xs font-medium text-muted-foreground mb-1 capitalize">
79
- {key}:
81
+ <div key={key} className="space-y-1.5">
82
+ <div className="text-xs font-medium text-muted-foreground capitalize flex items-center gap-2">
83
+ <div className="w-1.5 h-1.5 bg-[var(--blue-9)] rounded-full" />
84
+ {key}
80
85
  </div>
81
- <pre className="bg-[var(--slate-2)] p-1 text-muted-foreground border border-[var(--slate-4)] rounded text-xs overflow-auto scrollbar-thin max-h-64">
86
+ <pre className="bg-[var(--slate-2)] p-2 text-muted-foreground border border-[var(--slate-4)] rounded text-xs overflow-auto scrollbar-thin max-h-64">
82
87
  {JSON.stringify(value, null, 2)}
83
88
  </pre>
84
89
  </div>
@@ -107,6 +112,29 @@ const ResultRenderer: React.FC<{ result: unknown }> = ({ result }) => {
107
112
  );
108
113
  };
109
114
 
115
+ const ToolArgsRenderer: React.FC<{ input: unknown }> = ({ input }) => {
116
+ const hasinput = input && input !== null;
117
+
118
+ if (!hasinput) {
119
+ return null;
120
+ }
121
+
122
+ const isObject =
123
+ typeof input === "object" &&
124
+ Object.keys(input as Record<string, unknown>).length > 0;
125
+
126
+ return (
127
+ <div className="space-y-2">
128
+ <h3 className="text-xs font-semibold text-muted-foreground">
129
+ Tool Request
130
+ </h3>
131
+ <pre className="bg-[var(--slate-2)] p-2 text-muted-foreground border border-[var(--slate-4)] rounded text-xs overflow-auto scrollbar-thin max-h-64">
132
+ {isObject ? JSON.stringify(input, null, 2) : String(input)}
133
+ </pre>
134
+ </div>
135
+ );
136
+ };
137
+
110
138
  interface ToolCallAccordionProps {
111
139
  toolName: string;
112
140
  result: unknown;
@@ -114,6 +142,7 @@ interface ToolCallAccordionProps {
114
142
  index?: number;
115
143
  state?: ToolUIPart["state"];
116
144
  className?: string;
145
+ input?: unknown;
117
146
  }
118
147
 
119
148
  export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
@@ -123,6 +152,7 @@ export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
123
152
  index = 0,
124
153
  state,
125
154
  className,
155
+ input,
126
156
  }) => {
127
157
  const hasResult = state === "output-available" && (result || error);
128
158
  const status = error ? "error" : hasResult ? "success" : "loading";
@@ -176,21 +206,23 @@ export const ToolCallAccordion: React.FC<ToolCallAccordionProps> = ({
176
206
  </code>
177
207
  </span>
178
208
  </AccordionTrigger>
179
- <AccordionContent className="pb-2 px-2">
209
+ <AccordionContent className="py-2 px-2">
180
210
  {/* Only show content when tool is complete */}
181
211
  {hasResult && (
182
212
  <div className="space-y-3">
213
+ <ToolArgsRenderer input={input} />
183
214
  {result !== undefined && result !== null && (
184
215
  <ResultRenderer result={result} />
185
216
  )}
186
217
 
187
218
  {/* Error */}
188
219
  {error && (
189
- <div>
190
- <div className="text-xs font-medium text-[var(--red-11)] mb-1">
191
- Error:
220
+ <div className="bg-[var(--red-2)] border border-[var(--red-6)] rounded-lg p-3">
221
+ <div className="text-xs font-semibold text-[var(--red-11)] mb-2 flex items-center gap-2">
222
+ <div className="w-1.5 h-1.5 bg-[var(--red-9)] rounded-full" />
223
+ Error
192
224
  </div>
193
- <div className="bg-[var(--red-2)] border border-[var(--red-6)] rounded-md p-3 text-sm text-[var(--red-11)]">
225
+ <div className="text-sm text-[var(--red-11)] leading-relaxed">
194
226
  {error}
195
227
  </div>
196
228
  </div>
@@ -31,13 +31,14 @@ export const SearchBar = ({
31
31
  onSearch(debouncedSearch);
32
32
  }, [debouncedSearch, onSearch]);
33
33
 
34
- useEffect(() => {
35
- if (hidden) {
36
- setInternalValue("");
37
- } else {
38
- ref.current?.focus();
39
- }
40
- }, [hidden]);
34
+ if (!hidden) {
35
+ ref.current?.focus();
36
+ }
37
+
38
+ // Reset internal value when hidden becomes true
39
+ if (hidden && internalValue !== "") {
40
+ setInternalValue("");
41
+ }
41
42
 
42
43
  return (
43
44
  <div
@@ -6,37 +6,44 @@ import {
6
6
  } from "@/utils/numbers";
7
7
  import { applyFormat } from "../column-formatting/feature";
8
8
 
9
+ const locale = "en-US";
10
+
9
11
  describe("applyFormat", () => {
10
12
  it("should return an empty string for null, undefined, or empty string values", () => {
11
- expect(applyFormat(null, { format: "Date", dataType: "date" })).toBe("");
12
- expect(applyFormat(undefined, { format: "Date", dataType: "date" })).toBe(
13
+ expect(
14
+ applyFormat(null, { format: "Date", dataType: "date", locale }),
15
+ ).toBe("");
16
+ expect(
17
+ applyFormat(undefined, { format: "Date", dataType: "date", locale }),
18
+ ).toBe("");
19
+ expect(applyFormat("", { format: "Date", dataType: "date", locale })).toBe(
13
20
  "",
14
21
  );
15
- expect(applyFormat("", { format: "Date", dataType: "date" })).toBe("");
16
22
  });
17
23
 
18
24
  describe("date formatting", () => {
19
25
  it("should format date values correctly", () => {
20
26
  const date = "2023-10-01T12:00:00Z";
21
- expect(applyFormat(date, { format: "Date", dataType: "date" })).toBe(
22
- "10/1/23",
23
- );
24
- expect(applyFormat(date, { format: "Datetime", dataType: "date" })).toBe(
25
- "10/1/23, 12:00:00 PM UTC",
26
- );
27
+ expect(
28
+ applyFormat(date, { format: "Date", dataType: "date", locale }),
29
+ ).toBe("10/1/23");
30
+ expect(
31
+ applyFormat(date, { format: "Datetime", dataType: "date", locale }),
32
+ ).toBe("10/1/23, 12:00:00 PM UTC");
27
33
  });
28
34
 
29
35
  it("should format time values correctly", () => {
30
36
  const time = "12:00:00Z";
31
- expect(applyFormat(time, { format: "Time", dataType: "time" })).toBe(
32
- "12:00:00Z",
33
- );
37
+ expect(
38
+ applyFormat(time, { format: "Time", dataType: "time", locale }),
39
+ ).toBe("12:00:00Z");
34
40
  });
35
41
 
36
42
  it("should format datetime values correctly", () => {
37
43
  const datetime = "2023-10-01T12:00:00Z";
38
44
  expect(
39
45
  applyFormat(datetime, {
46
+ locale,
40
47
  format: "Datetime",
41
48
  dataType: "datetime",
42
49
  }),
@@ -47,26 +54,28 @@ describe("applyFormat", () => {
47
54
  describe("number formatting", () => {
48
55
  it("should format number values correctly", () => {
49
56
  const number = "1234.567";
50
- expect(applyFormat(number, { format: "Auto", dataType: "number" })).toBe(
51
- "1,234.57",
52
- );
53
57
  expect(
54
- applyFormat(number, { format: "Percent", dataType: "number" }),
58
+ applyFormat(number, { format: "Auto", dataType: "number", locale }),
59
+ ).toBe("1,234.57");
60
+ expect(
61
+ applyFormat(number, { format: "Percent", dataType: "number", locale }),
55
62
  ).toBe("123,456.7%");
56
63
  expect(
57
64
  applyFormat(number, {
65
+ locale,
58
66
  format: "Scientific",
59
67
  dataType: "number",
60
68
  }),
61
- ).toBe(prettyScientificNumber(1234.567, { shouldRound: true }));
69
+ ).toBe(prettyScientificNumber(1234.567, { shouldRound: true, locale }));
62
70
  expect(
63
71
  applyFormat(number, {
64
72
  format: "Engineering",
65
73
  dataType: "number",
74
+ locale,
66
75
  }),
67
- ).toBe(prettyEngineeringNumber(1234.567));
76
+ ).toBe(prettyEngineeringNumber(1234.567, locale));
68
77
  expect(
69
- applyFormat(number, { format: "Integer", dataType: "number" }),
78
+ applyFormat(number, { format: "Integer", dataType: "number", locale }),
70
79
  ).toBe("1,235");
71
80
  });
72
81
  });
@@ -75,41 +84,47 @@ describe("applyFormat", () => {
75
84
  it("should format string values correctly", () => {
76
85
  const str = "hello world";
77
86
  expect(
78
- applyFormat(str, { format: "Uppercase", dataType: "string" }),
87
+ applyFormat(str, { format: "Uppercase", dataType: "string", locale }),
79
88
  ).toBe("HELLO WORLD");
80
89
  expect(
81
- applyFormat(str, { format: "Lowercase", dataType: "string" }),
90
+ applyFormat(str, { format: "Lowercase", dataType: "string", locale }),
82
91
  ).toBe("hello world");
83
92
  expect(
84
- applyFormat(str, { format: "Capitalize", dataType: "string" }),
93
+ applyFormat(str, { format: "Capitalize", dataType: "string", locale }),
85
94
  ).toBe("Hello world");
86
- expect(applyFormat(str, { format: "Title", dataType: "string" })).toBe(
87
- "Hello World",
88
- );
95
+ expect(
96
+ applyFormat(str, { format: "Title", dataType: "string", locale }),
97
+ ).toBe("Hello World");
89
98
  });
90
99
  });
91
100
 
92
101
  describe("boolean formatting", () => {
93
102
  it("should format boolean values correctly", () => {
94
- expect(applyFormat(true, { format: "Yes/No", dataType: "boolean" })).toBe(
95
- "Yes",
96
- );
97
103
  expect(
98
- applyFormat(false, { format: "Yes/No", dataType: "boolean" }),
104
+ applyFormat(true, { format: "Yes/No", dataType: "boolean", locale }),
105
+ ).toBe("Yes");
106
+ expect(
107
+ applyFormat(false, { format: "Yes/No", dataType: "boolean", locale }),
99
108
  ).toBe("No");
100
- expect(applyFormat(true, { format: "On/Off", dataType: "boolean" })).toBe(
101
- "On",
102
- );
103
109
  expect(
104
- applyFormat(false, { format: "On/Off", dataType: "boolean" }),
110
+ applyFormat(true, { format: "On/Off", dataType: "boolean", locale }),
111
+ ).toBe("On");
112
+ expect(
113
+ applyFormat(false, { format: "On/Off", dataType: "boolean", locale }),
105
114
  ).toBe("Off");
106
115
  });
107
116
  });
108
117
 
109
118
  it("should return the original value for unknown data types or formats", () => {
110
119
  expect(
111
- applyFormat("some value", { format: "Auto", dataType: "unknown" }),
120
+ applyFormat("some value", {
121
+ format: "Auto",
122
+ dataType: "unknown",
123
+ locale,
124
+ }),
112
125
  ).toBe("some value");
113
- expect(applyFormat(123, { format: "Auto", dataType: "unknown" })).toBe(123);
126
+ expect(
127
+ applyFormat(123, { format: "Auto", dataType: "unknown", locale }),
128
+ ).toBe(123);
114
129
  });
115
130
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { render } from "@testing-library/react";
4
4
  import { describe, expect, it, test } from "vitest";
5
+ import { TooltipProvider } from "@/components/ui/tooltip";
5
6
  import { generateColumns, inferFieldTypes } from "../columns";
6
7
  import { getMimeValues, isMimeValue, MimeCell } from "../mime-cell";
7
8
  import type { FieldTypesWithExternalType } from "../types";
@@ -245,6 +246,43 @@ describe("generateColumns", () => {
245
246
  expect(columns[0].id).toBe("name");
246
247
  expect(columns[1].id).toBe("age");
247
248
  });
249
+
250
+ it("should render header with tooltip when headerTooltip is provided", () => {
251
+ const columns = generateColumns({
252
+ rowHeaders: [],
253
+ selection: null,
254
+ fieldTypes,
255
+ headerTooltip: { name: "Custom Name Tooltip" },
256
+ });
257
+
258
+ // Get the header function for the first column
259
+ const headerFunction = columns[0].header;
260
+ expect(headerFunction).toBeTypeOf("function");
261
+
262
+ const mockColumn = {
263
+ id: "name",
264
+ getCanSort: () => false,
265
+ getCanFilter: () => false,
266
+ columnDef: {
267
+ meta: {
268
+ dtype: "string",
269
+ dataType: "string",
270
+ },
271
+ },
272
+ };
273
+
274
+ const { container } = render(
275
+ <TooltipProvider>
276
+ {/* @ts-expect-error: mock column and header function */}
277
+ {headerFunction({ column: mockColumn })}
278
+ </TooltipProvider>,
279
+ );
280
+
281
+ expect(container.textContent).toContain("name");
282
+ // The tooltip functionality is tested by verifying that the header renders correctly
283
+ // when headerTooltip is provided.
284
+ expect(container.firstChild).toBeTruthy();
285
+ });
248
286
  });
249
287
 
250
288
  describe("MimeCell", () => {