@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
@@ -93,6 +93,25 @@ export const DataTableBody = <TData,>({
93
93
  handleCellsKeyDown,
94
94
  } = useCellRangeSelection({ table });
95
95
 
96
+ function applyHoverTemplate(
97
+ template: string,
98
+ cells: Array<Cell<TData, unknown>>,
99
+ ): string {
100
+ const variableRegex = /{{(\w+)}}/g;
101
+ // Map column id -> stringified value
102
+ const idToValue = new Map<string, string>();
103
+ for (const c of cells) {
104
+ const v = c.getValue();
105
+ // Prefer empty string for nulls to keep tooltip clean
106
+ const s = renderUnknownValue({ value: v, nullAsEmptyString: true });
107
+ idToValue.set(c.column.id, s);
108
+ }
109
+ return template.replaceAll(variableRegex, (_substr, varName: string) => {
110
+ const val = idToValue.get(varName);
111
+ return val === undefined ? `{{${varName}}}` : val;
112
+ });
113
+ }
114
+
96
115
  const renderCells = (cells: Array<Cell<TData, unknown>>) => {
97
116
  return cells.map((cell) => {
98
117
  const { className, style: pinningstyle } = getPinningStyles(cell.column);
@@ -101,6 +120,7 @@ export const DataTableBody = <TData,>({
101
120
  cell.getUserStyling?.() || {},
102
121
  pinningstyle,
103
122
  );
123
+
104
124
  return (
105
125
  <TableCell
106
126
  tabIndex={0}
@@ -134,6 +154,8 @@ export const DataTableBody = <TData,>({
134
154
  }
135
155
  };
136
156
 
157
+ const hoverTemplate = table.getState().cellHoverTemplate || null;
158
+
137
159
  return (
138
160
  <TableBody onKeyDown={handleCellsKeyDown} ref={tableRef}>
139
161
  {table.getRowModel().rows?.length ? (
@@ -145,10 +167,24 @@ export const DataTableBody = <TData,>({
145
167
  const isRowViewedInPanel =
146
168
  rowViewerPanelOpen && viewedRowIdx === rowIndex;
147
169
 
170
+ // Compute hover title once per row using all visible cells
171
+ let rowTitle: string | undefined;
172
+ if (hoverTemplate) {
173
+ const visibleCells = row.getVisibleCells?.() ?? [
174
+ ...row.getLeftVisibleCells(),
175
+ ...row.getCenterVisibleCells(),
176
+ ...row.getRightVisibleCells(),
177
+ ];
178
+ rowTitle = hoverTemplate
179
+ ? applyHoverTemplate(hoverTemplate, visibleCells)
180
+ : undefined;
181
+ }
182
+
148
183
  return (
149
184
  <TableRow
150
185
  key={row.id}
151
186
  data-state={row.getIsSelected() && "selected"}
187
+ title={rowTitle}
152
188
  // These classes ensure that empty rows (nulls) still render
153
189
  className={cn(
154
190
  "border-t h-6",
@@ -15,6 +15,7 @@ import {
15
15
  SearchIcon,
16
16
  } from "lucide-react";
17
17
  import { useRef, useState } from "react";
18
+ import { useLocale } from "react-aria";
18
19
  import { ColumnName } from "@/components/datasources/components";
19
20
  import { CopyClipboardIcon } from "@/components/icons/copy-icon";
20
21
  import { KeyboardHotkeys } from "@/components/shortcuts/renderShortcut";
@@ -66,6 +67,7 @@ export const RowViewerPanel: React.FC<RowViewerPanelProps> = ({
66
67
  const [searchQuery, setSearchQuery] = useState("");
67
68
  const panelRef = useRef<HTMLDivElement>(null);
68
69
  const searchInputRef = useRef<HTMLInputElement>(null);
70
+ const { locale } = useLocale();
69
71
 
70
72
  const tooManyRows = totalRows === TOO_MANY_ROWS;
71
73
 
@@ -204,13 +206,13 @@ export const RowViewerPanel: React.FC<RowViewerPanelProps> = ({
204
206
  applyColumnFormatting: (value) => value,
205
207
  } as Column<unknown>;
206
208
 
207
- const cellContent = renderCellValue(
208
- mockColumn,
209
- () => columnValue,
210
- () => columnValue,
211
- undefined,
212
- "text-left break-word",
213
- );
209
+ const cellContent = renderCellValue({
210
+ column: mockColumn,
211
+ renderValue: () => columnValue,
212
+ getValue: () => columnValue,
213
+ selectCell: undefined,
214
+ cellStyles: "text-left break-word",
215
+ });
214
216
 
215
217
  const copyValue =
216
218
  typeof columnValue === "object"
@@ -286,7 +288,7 @@ export const RowViewerPanel: React.FC<RowViewerPanelProps> = ({
286
288
  <span className="text-xs">
287
289
  {tooManyRows
288
290
  ? `Row ${rowIdx + 1}`
289
- : `Row ${rowIdx + 1} of ${prettifyRowCount(totalRows)}`}
291
+ : `Row ${rowIdx + 1} of ${prettifyRowCount(totalRows, locale)}`}
290
292
  </span>
291
293
  <Button
292
294
  variant="outline"
@@ -0,0 +1,16 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import z from "zod";
4
+ import { rpc } from "@/plugins/core/rpc";
5
+
6
+ export type DownloadAsArgs = (req: {
7
+ format: "csv" | "json" | "parquet";
8
+ }) => Promise<string>;
9
+
10
+ export const DownloadAsSchema = rpc
11
+ .input(
12
+ z.object({
13
+ format: z.enum(["csv", "json", "parquet"]),
14
+ }),
15
+ )
16
+ .output(z.string());
@@ -3,6 +3,7 @@
3
3
  import { useAtomValue } from "jotai";
4
4
  import { PlusSquareIcon } from "lucide-react";
5
5
  import React, { Suspense } from "react";
6
+ import { useLocale } from "react-aria";
6
7
  import { maybeAddAltairImport } from "@/core/cells/add-missing-import";
7
8
  import { useCellActions } from "@/core/cells/cells";
8
9
  import { useLastFocusedCellId } from "@/core/cells/focus";
@@ -42,6 +43,7 @@ export const DatasetColumnPreview: React.FC<{
42
43
  }> = ({ table, column, preview, onAddColumnChart, sqlTableContext }) => {
43
44
  const { theme } = useTheme();
44
45
  const { previewDatasetColumn } = useRequestClient();
46
+ const { locale } = useLocale();
45
47
 
46
48
  const previewColumn = () => {
47
49
  previewDatasetColumn({
@@ -107,7 +109,8 @@ export const DatasetColumnPreview: React.FC<{
107
109
  refetchPreview: previewColumn,
108
110
  });
109
111
 
110
- const stats = preview.stats && renderStats(preview.stats, column.type);
112
+ const stats =
113
+ preview.stats && renderStats(preview.stats, column.type, locale);
111
114
 
112
115
  const chart = preview.chart_spec && renderChart(preview.chart_spec, theme);
113
116
 
@@ -175,6 +178,7 @@ export function renderPreviewError({
175
178
  export function renderStats(
176
179
  stats: Partial<Record<ColumnHeaderStatsKey, unknown>>,
177
180
  dataType: DataType,
181
+ locale: string,
178
182
  ) {
179
183
  return (
180
184
  <div className="gap-x-16 gap-y-1 grid grid-cols-2-fit border rounded p-2 empty:hidden">
@@ -189,7 +193,7 @@ export function renderStats(
189
193
  {convertStatsName(key as ColumnHeaderStatsKey, dataType)}
190
194
  </span>
191
195
  <span className="text-xs font-bold text-muted-foreground tracking-wide">
192
- {prettyNumber(value)}
196
+ {prettyNumber(value, locale)}
193
197
  </span>
194
198
  <CopyClipboardIcon
195
199
  className="h-3 w-3 invisible group-hover:visible"
@@ -304,10 +304,12 @@ const DatabaseItem: React.FC<{
304
304
  }> = ({ hasSearch, engineName, database, children }) => {
305
305
  const [isExpanded, setIsExpanded] = React.useState(false);
306
306
  const [isSelected, setIsSelected] = React.useState(false);
307
+ const [prevHasSearch, setPrevHasSearch] = React.useState(hasSearch);
307
308
 
308
- React.useEffect(() => {
309
+ if (prevHasSearch !== hasSearch) {
310
+ setPrevHasSearch(hasSearch);
309
311
  setIsExpanded(hasSearch);
310
- }, [hasSearch]);
312
+ }
311
313
 
312
314
  return (
313
315
  <>
@@ -399,14 +401,10 @@ const SchemaItem: React.FC<{
399
401
  children: React.ReactNode;
400
402
  hasSearch: boolean;
401
403
  }> = ({ databaseName, schema, children, hasSearch }) => {
402
- const [isExpanded, setIsExpanded] = React.useState(false);
404
+ const [isExpanded, setIsExpanded] = React.useState(hasSearch);
403
405
  const [isSelected, setIsSelected] = React.useState(false);
404
406
  const uniqueValue = `${databaseName}:${schema.name}`;
405
407
 
406
- React.useEffect(() => {
407
- setIsExpanded(hasSearch);
408
- }, [hasSearch]);
409
-
410
408
  if (isSchemaless(schema.name)) {
411
409
  return children;
412
410
  }
@@ -693,11 +691,9 @@ const DatasetColumnItem: React.FC<{
693
691
  const closeAllColumns = useAtomValue(closeAllColumnsAtom);
694
692
  const setExpandedColumns = useSetAtom(expandedColumnsAtom);
695
693
 
696
- React.useEffect(() => {
697
- if (closeAllColumns) {
698
- setIsExpanded(false);
699
- }
700
- }, [closeAllColumns]);
694
+ if (closeAllColumns && isExpanded) {
695
+ setIsExpanded(false);
696
+ }
701
697
 
702
698
  if (isExpanded) {
703
699
  setExpandedColumns(
@@ -80,6 +80,7 @@ import { useDeleteCellCallback } from "./cell/useDeleteCell";
80
80
  import { useRunCell } from "./cell/useRunCells";
81
81
  import { HideCodeButton } from "./code/readonly-python-code";
82
82
  import { cellDomProps } from "./common";
83
+ import { SqlValidationErrorBanner } from "./errors/sql-validation-errors";
83
84
  import { useCellNavigationProps } from "./navigation/navigation";
84
85
  import {
85
86
  useTemporarilyShownCode,
@@ -653,6 +654,7 @@ const EditableCellComponent = ({
653
654
  )}
654
655
  </div>
655
656
  </div>
657
+ <SqlValidationErrorBanner cellId={cellId} />
656
658
  {cellOutput === "below" && outputArea}
657
659
  {cellRuntime.serialization && (
658
660
  <div className="py-1 px-2 flex items-center justify-end gap-2 last:rounded-b">
@@ -13,11 +13,14 @@ import {
13
13
  export class StreamingChunkTransport<
14
14
  UI_MESSAGE extends UIMessage,
15
15
  > extends DefaultChatTransport<UI_MESSAGE> {
16
+ private onChunkReceived: (chunk: UIMessageChunk) => void;
17
+
16
18
  constructor(
17
19
  options: HttpChatTransportInitOptions<UI_MESSAGE> = {},
18
- private onChunkReceived: (chunk: UIMessageChunk) => void,
20
+ onChunkReceived: (chunk: UIMessageChunk) => void,
19
21
  ) {
20
22
  super(options);
23
+ this.onChunkReceived = onChunkReceived;
21
24
  }
22
25
 
23
26
  protected override processResponseStream(
@@ -5,6 +5,7 @@ import {
5
5
  RefreshCwIcon,
6
6
  WorkflowIcon,
7
7
  } from "lucide-react";
8
+ import { useDateFormatter } from "react-aria";
8
9
  import { MultiIcon } from "@/components/icons/multi-icon";
9
10
  import { Logger } from "@/utils/Logger";
10
11
  import type { CellRuntimeState } from "../../../core/cells/types";
@@ -28,26 +29,6 @@ export interface CellStatusComponentProps
28
29
  uninstantiated: boolean;
29
30
  }
30
31
 
31
- // Looks like HH:MM:SS.SSS AM/PM
32
- const timeFormatter = new Intl.DateTimeFormat("en-US", {
33
- hour: "numeric",
34
- minute: "numeric",
35
- second: "numeric",
36
- fractionalSecondDigits: 3,
37
- hour12: true,
38
- });
39
-
40
- // Looks like MM/DD HH:MM:SS.SSS AM/PM
41
- const dateTimeFormatter = new Intl.DateTimeFormat("en-US", {
42
- month: "numeric",
43
- day: "numeric",
44
- hour: "numeric",
45
- minute: "numeric",
46
- second: "numeric",
47
- fractionalSecondDigits: 3,
48
- hour12: true,
49
- });
50
-
51
32
  export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
52
33
  editing,
53
34
  status,
@@ -329,10 +310,32 @@ export const ElapsedTime = (props: { elapsedTime: string }) => {
329
310
  const LastRanTime = (props: { lastRanTime: number }) => {
330
311
  const date = new Date(props.lastRanTime * 1000);
331
312
  const today = new Date();
313
+
314
+ // Looks like HH:MM:SS.SSS AM/PM
315
+ const timeFormatter = useDateFormatter({
316
+ hour: "numeric",
317
+ minute: "numeric",
318
+ second: "numeric",
319
+ fractionalSecondDigits: 3,
320
+ hour12: true,
321
+ });
322
+
323
+ // Looks like MM/DD HH:MM:SS.SSS AM/PM
324
+ const dateTimeFormatter = useDateFormatter({
325
+ month: "numeric",
326
+ day: "numeric",
327
+ hour: "numeric",
328
+ minute: "numeric",
329
+ second: "numeric",
330
+ fractionalSecondDigits: 3,
331
+ hour12: true,
332
+ });
333
+
332
334
  const formatter =
333
335
  date.toDateString() === today.toDateString()
334
336
  ? timeFormatter
335
337
  : dateTimeFormatter;
338
+
336
339
  return (
337
340
  <span>
338
341
  Ran at{" "}
@@ -9,8 +9,7 @@ import {
9
9
  } from "@/components/ui/context-menu";
10
10
  import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
11
11
  import { useCellActions } from "@/core/cells/cells";
12
- import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
13
- import { SQLLanguageAdapter } from "@/core/codemirror/language/languages/sql/sql";
12
+ import { LanguageAdapters } from "@/core/codemirror/language/LanguageAdapters";
14
13
  import {
15
14
  getConnectionTooltip,
16
15
  isAppInteractionDisabled,
@@ -103,7 +102,7 @@ const CreateCellButtonContextMenu = (props: {
103
102
  evt.stopPropagation();
104
103
  maybeAddMarimoImport({ autoInstantiate: true, createNewCell });
105
104
  onClick({
106
- code: new MarkdownLanguageAdapter().defaultCode,
105
+ code: LanguageAdapters.markdown.defaultCode,
107
106
  hideCode: true,
108
107
  });
109
108
  }}
@@ -118,7 +117,7 @@ const CreateCellButtonContextMenu = (props: {
118
117
  onSelect={(evt) => {
119
118
  evt.stopPropagation();
120
119
  maybeAddMarimoImport({ autoInstantiate: true, createNewCell });
121
- onClick({ code: new SQLLanguageAdapter().defaultCode });
120
+ onClick({ code: LanguageAdapters.sql.defaultCode });
122
121
  }}
123
122
  >
124
123
  <div className="mr-3 text-muted-foreground">
@@ -7,8 +7,7 @@ import { useMemo } from "react";
7
7
  import { Button } from "@/components/ui/button";
8
8
  import { Tooltip } from "@/components/ui/tooltip";
9
9
  import { switchLanguage } from "@/core/codemirror/language/extension";
10
- import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
11
- import { SQLLanguageAdapter } from "@/core/codemirror/language/languages/sql/sql";
10
+ import { LanguageAdapters } from "@/core/codemirror/language/LanguageAdapters";
12
11
  import type { LanguageAdapter } from "@/core/codemirror/language/types";
13
12
  import { Functions } from "@/utils/functions";
14
13
  import { MarkdownIcon, PythonIcon } from "./icons";
@@ -27,11 +26,11 @@ export const LanguageToggles: React.FC<LanguageTogglesProps> = ({
27
26
  onAfterToggle,
28
27
  }) => {
29
28
  const canUseMarkdown = useMemo(
30
- () => new MarkdownLanguageAdapter().isSupported(code) || code.trim() === "",
29
+ () => LanguageAdapters.markdown.isSupported(code) || code.trim() === "",
31
30
  [code],
32
31
  );
33
32
  const canUseSQL = useMemo(
34
- () => new SQLLanguageAdapter().isSupported(code) || code.trim() === "",
33
+ () => LanguageAdapters.sql.isSupported(code) || code.trim() === "",
35
34
  [code],
36
35
  );
37
36
 
@@ -4,6 +4,7 @@ import { useAtomValue } from "jotai";
4
4
  import { CpuIcon, MemoryStickIcon, MicrochipIcon } from "lucide-react";
5
5
  import type React from "react";
6
6
  import { useState } from "react";
7
+ import { useNumberFormatter } from "react-aria";
7
8
  import { Tooltip } from "@/components/ui/tooltip";
8
9
  import { connectionAtom } from "@/core/network/connection";
9
10
  import { useRequestClient } from "@/core/network/requests";
@@ -56,23 +57,42 @@ const MemoryUsageBar: React.FC<{
56
57
  }> = ({ memory, kernel, server }) => {
57
58
  const { percent, total, available } = memory;
58
59
  const roundedPercent = Math.round(percent);
60
+
61
+ const gbFormatter = useNumberFormatter({
62
+ maximumFractionDigits: 2,
63
+ });
64
+ const mbFormatter = useNumberFormatter({
65
+ maximumFractionDigits: 0,
66
+ });
67
+
68
+ const formatBytes = (bytes: number): string => {
69
+ if (bytes > 1024 * 1024 * 1024) {
70
+ return `${gbFormatter.format(bytes / (1024 * 1024 * 1024))} GB`;
71
+ }
72
+ return `${mbFormatter.format(bytes / (1024 * 1024))} MB`;
73
+ };
74
+
75
+ const formatGB = (bytes: number): string => {
76
+ return gbFormatter.format(bytes / (1024 * 1024 * 1024));
77
+ };
78
+
59
79
  return (
60
80
  <Tooltip
61
81
  delayDuration={200}
62
82
  content={
63
83
  <div className="flex flex-col gap-1">
64
84
  <span>
65
- <b>computer memory:</b> {asGB(total - available)} / {asGB(total)} GB
66
- ({roundedPercent}%)
85
+ <b>computer memory:</b> {formatGB(total - available)} /{" "}
86
+ {formatGB(total)} GB ({roundedPercent}%)
67
87
  </span>
68
88
  {server?.memory && (
69
89
  <span>
70
- <b>marimo server:</b> {asGBorMB(server.memory)}
90
+ <b>marimo server:</b> {formatBytes(server.memory)}
71
91
  </span>
72
92
  )}
73
93
  {kernel?.memory && (
74
94
  <span>
75
- <b>kernel:</b> {asGBorMB(kernel.memory)}
95
+ <b>kernel:</b> {formatBytes(kernel.memory)}
76
96
  </span>
77
97
  )}
78
98
  </div>
@@ -122,6 +142,20 @@ const GPUBar: React.FC<{ gpus: GPU[] }> = ({ gpus }) => {
122
142
  gpus.length,
123
143
  );
124
144
 
145
+ const gbFormatter = useNumberFormatter({
146
+ maximumFractionDigits: 2,
147
+ });
148
+ const mbFormatter = useNumberFormatter({
149
+ maximumFractionDigits: 0,
150
+ });
151
+
152
+ const formatBytes = (bytes: number): string => {
153
+ if (bytes > 1024 * 1024 * 1024) {
154
+ return `${gbFormatter.format(bytes / (1024 * 1024 * 1024))} GB`;
155
+ }
156
+ return `${mbFormatter.format(bytes / (1024 * 1024))} MB`;
157
+ };
158
+
125
159
  return (
126
160
  <Tooltip
127
161
  delayDuration={200}
@@ -132,7 +166,7 @@ const GPUBar: React.FC<{ gpus: GPU[] }> = ({ gpus }) => {
132
166
  <b>
133
167
  GPU {gpu.index} ({gpu.name}):
134
168
  </b>{" "}
135
- {asGBorMB(gpu.memory.used)} / {asGBorMB(gpu.memory.total)} GB (
169
+ {formatBytes(gpu.memory.used)} / {formatBytes(gpu.memory.total)} (
136
170
  {Math.round(gpu.memory.percent)}%)
137
171
  </span>
138
172
  ))}
@@ -160,26 +194,3 @@ const Bar: React.FC<{ percent: number; colorClassName?: string }> = ({
160
194
  </div>
161
195
  );
162
196
  };
163
-
164
- function asGBorMB(bytes: number): string {
165
- if (bytes > 1024 * 1024 * 1024) {
166
- return `${asGB(bytes)} GB`;
167
- }
168
- return `${asMB(bytes)} MB`;
169
- }
170
-
171
- function asMB(bytes: number) {
172
- // 0 decimal places
173
- const format = new Intl.NumberFormat("en-US", {
174
- maximumFractionDigits: 0,
175
- });
176
- return format.format(bytes / (1024 * 1024));
177
- }
178
-
179
- function asGB(bytes: number) {
180
- // At most 2 decimal places
181
- const format = new Intl.NumberFormat("en-US", {
182
- maximumFractionDigits: 2,
183
- });
184
- return format.format(bytes / (1024 * 1024 * 1024));
185
- }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { MenuIcon } from "lucide-react";
4
4
  import React from "react";
5
+ import { useLocale } from "react-aria";
5
6
  import { Button } from "@/components/editor/inputs/Inputs";
6
7
  import {
7
8
  DropdownMenu,
@@ -33,7 +34,7 @@ export const NotebookMenuDropdown: React.FC<Props> = ({
33
34
  tooltip = "Actions",
34
35
  }) => {
35
36
  const actions = useNotebookActions();
36
-
37
+ const { locale } = useLocale();
37
38
  // Create tooltip content with keyboard shortcut decoration
38
39
  const tooltipContent = (
39
40
  <div className="flex flex-col gap-2">
@@ -148,7 +149,8 @@ export const NotebookMenuDropdown: React.FC<Props> = ({
148
149
  );
149
150
  })}
150
151
  <DropdownMenuSeparator />
151
- <div className="flex-1 px-2 text-xs text-muted-foreground">
152
+ <div className="flex-1 px-2 text-xs text-muted-foreground flex flex-col gap-1">
153
+ <span>Locale: {locale}</span>
152
154
  <span>Version: {getMarimoVersion()}</span>
153
155
  </div>
154
156
  </DropdownMenuContent>
@@ -0,0 +1,34 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import { AlertCircleIcon } from "lucide-react";
4
+ import type { CellId } from "@/core/cells/ids";
5
+ import { useSqlValidationErrorsForCell } from "@/core/codemirror/language/languages/sql/validation-errors";
6
+
7
+ export const SqlValidationErrorBanner = ({ cellId }: { cellId: CellId }) => {
8
+ const error = useSqlValidationErrorsForCell(cellId);
9
+
10
+ if (!error) {
11
+ return;
12
+ }
13
+
14
+ return (
15
+ <div className="p-3 text-sm flex flex-col text-muted-foreground gap-1.5 bg-destructive/5">
16
+ <div className="flex items-start gap-1.5">
17
+ <AlertCircleIcon size={13} className="mt-[3px] text-destructive" />
18
+ <p>
19
+ <span className="font-bold text-destructive">{error.errorType}:</span>{" "}
20
+ {error.errorMessage}
21
+ </p>
22
+ </div>
23
+
24
+ {error.codeblock && (
25
+ <pre
26
+ lang="sql"
27
+ className="text-xs bg-muted rounded p-2 pb-0 mx-3 overflow-x-auto font-mono whitespace-pre-wrap"
28
+ >
29
+ {error.codeblock}
30
+ </pre>
31
+ )}
32
+ </div>
33
+ );
34
+ };
@@ -13,15 +13,21 @@ import { type FilePath, PathBuilder } from "@/utils/paths";
13
13
 
14
14
  export class RequestingTree {
15
15
  private delegate = new SimpleTree<FileInfo>([]);
16
+ private callbacks: {
17
+ listFiles: EditRequests["sendListFiles"];
18
+ createFileOrFolder: EditRequests["sendCreateFileOrFolder"];
19
+ deleteFileOrFolder: EditRequests["sendDeleteFileOrFolder"];
20
+ renameFileOrFolder: EditRequests["sendRenameFileOrFolder"];
21
+ };
16
22
 
17
- constructor(
18
- private callbacks: {
19
- listFiles: EditRequests["sendListFiles"];
20
- createFileOrFolder: EditRequests["sendCreateFileOrFolder"];
21
- deleteFileOrFolder: EditRequests["sendDeleteFileOrFolder"];
22
- renameFileOrFolder: EditRequests["sendRenameFileOrFolder"];
23
- },
24
- ) {}
23
+ constructor(callbacks: {
24
+ listFiles: EditRequests["sendListFiles"];
25
+ createFileOrFolder: EditRequests["sendCreateFileOrFolder"];
26
+ deleteFileOrFolder: EditRequests["sendDeleteFileOrFolder"];
27
+ renameFileOrFolder: EditRequests["sendRenameFileOrFolder"];
28
+ }) {
29
+ this.callbacks = callbacks;
30
+ }
25
31
 
26
32
  private rootPath: FilePath = "" as FilePath;
27
33
  private onChange: (data: FileInfo[]) => void = Functions.NOOP;
@@ -14,6 +14,7 @@ import type { OutputMessage } from "@/core/kernel/messages";
14
14
  import { useSelectAllContent } from "@/hooks/useSelectAllContent";
15
15
  import { cn } from "@/utils/cn";
16
16
  import { copyToClipboard } from "@/utils/copy";
17
+ import { ansiToPlainText, parseHtmlContent } from "@/utils/dom";
17
18
  import { invariant } from "@/utils/invariant";
18
19
  import { Strings } from "@/utils/strings";
19
20
  import { NameCellContentEditable } from "../actions/name-cell-input";
@@ -124,7 +125,18 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
124
125
  onClick={() => {
125
126
  const text = reversedOutputs
126
127
  .filter((output) => output.channel !== "pdb")
127
- .map((output) => Strings.asString(output.data))
128
+ .map((output) => {
129
+ // If starts with `<`, then assume it's HTML
130
+ if (
131
+ typeof output.data === "string" &&
132
+ output.data.startsWith("<")
133
+ ) {
134
+ return parseHtmlContent(output.data);
135
+ }
136
+
137
+ // Otherwise, convert the ANSI to HTML, then parse as HTML
138
+ return ansiToPlainText(Strings.asString(output.data));
139
+ })
128
140
  .join("\n");
129
141
  void copyToClipboard(text);
130
142
  }}