@marimo-team/islands 0.19.12-dev1 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/dist/Combination-Du-o_hC9.js +11897 -0
  2. package/dist/{ConnectedDataExplorerComponent-CkXO-pKy.js → ConnectedDataExplorerComponent-BMiGWK57.js} +19 -18
  3. package/dist/{_baseIsEqual-CBSjxu-D.js → _baseIsEqual-DN5YkPnl.js} +1 -1
  4. package/dist/{_baseProperty-BVGrW_NZ.js → _baseProperty-6juuyX7Z.js} +5 -5
  5. package/dist/{_baseUniq-4lqa8rDi.js → _baseUniq-BlF21ach.js} +1 -1
  6. package/dist/{any-language-editor-t_VsTNa-.js → any-language-editor-1OMbohwD.js} +19 -19
  7. package/dist/architecture-U656AL7Q-Jd2CvPgJ.js +6 -0
  8. package/dist/{architectureDiagram-VXUJARFQ-DmJQhcJb.js → architectureDiagram-VXUJARFQ-DhN0C3Xf.js} +15 -15
  9. package/dist/{blockDiagram-VD42YOAC-CRofISJs.js → blockDiagram-VD42YOAC-DrBkIcbV.js} +7 -7
  10. package/dist/{button-Cy0ElmIm.js → button-KYalaJYu.js} +783 -200
  11. package/dist/{c4Diagram-YG6GDRKO-Deqoag4I.js → c4Diagram-YG6GDRKO-pWt4zmu0.js} +4 -4
  12. package/dist/{channel-CMsnebrL.js → channel-C56Jz8EL.js} +1 -1
  13. package/dist/{check-DkNR52Mm.js → check-C50jsehH.js} +1 -1
  14. package/dist/{chunk-76Q3JFCE-jPuajZH_.js → chunk-76Q3JFCE-CQ6a2yGJ.js} +1 -1
  15. package/dist/{chunk-ABZYJK2D-BGWvKte3.js → chunk-ABZYJK2D-BwNsaa1P.js} +1 -1
  16. package/dist/{chunk-ATLVNIR6-BYZB6C5T.js → chunk-ATLVNIR6-DtFMAawc.js} +1 -1
  17. package/dist/{chunk-B4BG7PRW-CwYUp6Uj.js → chunk-B4BG7PRW-lfWcLlzS.js} +4 -4
  18. package/dist/{chunk-DI55MBZ5-Gyro6dvN.js → chunk-DI55MBZ5-RhhAimfG.js} +4 -4
  19. package/dist/{chunk-EXTU4WIE-BlA7aWEw.js → chunk-EXTU4WIE-Bmo660a9.js} +1 -1
  20. package/dist/{chunk-FPAJGGOC-CduL34ft.js → chunk-FPAJGGOC-quWdfNUB.js} +7 -7
  21. package/dist/{chunk-FWNWRKHM-C-2TI4gt.js → chunk-FWNWRKHM-DmrwhAQr.js} +1 -1
  22. package/dist/{chunk-JA3XYJ7Z-Cm-pccR-.js → chunk-JA3XYJ7Z-n8UTzfok.js} +2 -2
  23. package/dist/{chunk-JZLCHNYA-CoLqqXMe.js → chunk-JZLCHNYA-ChKqHUdB.js} +4 -4
  24. package/dist/{chunk-LBM3YZW2-DWgQiioW.js → chunk-LBM3YZW2-BkxsqkNK.js} +1 -1
  25. package/dist/{chunk-LHMN2FUI-Dj_AHSvI.js → chunk-LHMN2FUI-CgYPnxfN.js} +1 -1
  26. package/dist/{chunk-N4CR4FBY-ByLbY9L-.js → chunk-N4CR4FBY-BxOHGL3P.js} +5 -5
  27. package/dist/{chunk-O7ZBX7Z2-CRZ8i1rP.js → chunk-O7ZBX7Z2-CdpLwOP0.js} +1 -1
  28. package/dist/{chunk-QN33PNHL-eodIiY9F.js → chunk-QN33PNHL-Dda-55xY.js} +1 -1
  29. package/dist/{chunk-QXUST7PY-CuJlDW6A.js → chunk-QXUST7PY-ClIEpoCT.js} +5 -5
  30. package/dist/{chunk-S3R3BYOJ-CwDGYMVf.js → chunk-S3R3BYOJ-C_1SJcWo.js} +3 -3
  31. package/dist/{chunk-S6J4BHB3-DNVMr0_v.js → chunk-S6J4BHB3-zfWjyfUg.js} +1 -1
  32. package/dist/{chunk-T53DSG4Q-BFWkpOX5.js → chunk-T53DSG4Q-Bewz1tiU.js} +1 -1
  33. package/dist/{chunk-TZMSLE5B-DFDr5FCr.js → chunk-TZMSLE5B-XW3duOft.js} +1 -1
  34. package/dist/{classDiagram-2ON5EDUG-BDBX9etk.js → classDiagram-2ON5EDUG-CUJlS_eo.js} +10 -10
  35. package/dist/{classDiagram-v2-WZHVMYZB-Bzj_L_BF.js → classDiagram-v2-WZHVMYZB-BhSPpbkE.js} +10 -10
  36. package/dist/{clone-Cc_6PW77.js → clone-V9hndNcj.js} +1 -1
  37. package/dist/{constants-DrOu5vvd.js → constants-BGRTDzdW.js} +2 -2
  38. package/dist/{copy-DRaXIb_a.js → copy-oc-FcZzt.js} +2 -2
  39. package/dist/{dagre-6UL2VRFP-r2rSdJYL.js → dagre-6UL2VRFP-BArPH353.js} +11 -11
  40. package/dist/{dagre-D2F8UdM6.js → dagre-Dcgyn_Uy.js} +15 -15
  41. package/dist/{diagram-PSM6KHXK-BpxVUe9U.js → diagram-PSM6KHXK-B1xAkr9y.js} +16 -16
  42. package/dist/{diagram-QEK2KX5R-q3dHUcp6.js → diagram-QEK2KX5R-CaoqwzPb.js} +14 -14
  43. package/dist/{diagram-S2PKOQOG-MDBKrxSC.js → diagram-S2PKOQOG-NXCsFLvR.js} +14 -14
  44. package/dist/dist-B8Y11RWn.js +1381 -0
  45. package/dist/dist-BA-HK7pI.js +5 -0
  46. package/dist/dist-BD5GU948.js +5 -0
  47. package/dist/{dist-BfactX3G.js → dist-BGzkWRSl.js} +4 -4
  48. package/dist/dist-BIYmAsND.js +5 -0
  49. package/dist/{dist-CmZYrgd_.js → dist-BUEi7EKT.js} +1 -1
  50. package/dist/{dist-B94MxrQS.js → dist-B_i29Q6L.js} +2 -2
  51. package/dist/dist-BcKTJXJi.js +5 -0
  52. package/dist/dist-BgnrtcWg.js +8 -0
  53. package/dist/{dist-glA_fIK_.js → dist-BoagoQQw.js} +2 -2
  54. package/dist/{dist-C2-m5aEk.js → dist-BswsDM4k.js} +2 -2
  55. package/dist/dist-C1njTlBq.js +5 -0
  56. package/dist/{dist-B2-r9y-0.js → dist-C5QB1NtD.js} +3 -3
  57. package/dist/{dist-Crk9ejOy.js → dist-CD7uLx0M.js} +2 -2
  58. package/dist/{dist-B4tYJP_i.js → dist-CMOy93xY.js} +2 -2
  59. package/dist/dist-CSKHwJYH.js +5 -0
  60. package/dist/dist-CSKKyiIq.js +5 -0
  61. package/dist/{dist-iiugPhCC.js → dist-C_9IMrtt.js} +1 -1
  62. package/dist/{dist-CE43BRmt.js → dist-Cb3iqED3.js} +1 -1
  63. package/dist/{dist-Dit9tk8a.js → dist-CoZ8kKKW.js} +1 -1
  64. package/dist/{dist-B5ATpkxy.js → dist-CrAYcS_4.js} +2 -2
  65. package/dist/dist-CrQ_pOuK.js +6 -0
  66. package/dist/dist-Cskx1daf.js +5 -0
  67. package/dist/dist-D4i0Ef34.js +8 -0
  68. package/dist/{dist-T4g7Sr6e.js → dist-D8EhXZ4S.js} +3 -3
  69. package/dist/{dist-CJrHMxlI.js → dist-DOLQQtWK.js} +3 -3
  70. package/dist/dist-DOcn61TX.js +8 -0
  71. package/dist/{dist-DqJdzAYM.js → dist-Dmr_nXF6.js} +2 -2
  72. package/dist/{dist-yVJ4xE5n.js → dist-DpAbrLuF.js} +5 -5
  73. package/dist/{dist-CcOGT46m.js → dist-DrC0QKFK.js} +1 -1
  74. package/dist/{dist-BYmtF1W6.js → dist-Dv2Phbh5.js} +2 -2
  75. package/dist/dist-DwMejAPB.js +6 -0
  76. package/dist/dist-DzSe1wby.js +8 -0
  77. package/dist/{dist-BbBnU4tG.js → dist-EZFqUJhh.js} +1 -1
  78. package/dist/{dist-Cgf353Ki.js → dist-Ey9hP8-j.js} +1 -1
  79. package/dist/{dist-BLwfpZD-.js → dist-IlWGXVjO.js} +2 -2
  80. package/dist/{dist-DOil6y-3.js → dist-LNp8svLl.js} +4 -4
  81. package/dist/{dist-CPTE45iS.js → dist-W6TdeACj.js} +1 -1
  82. package/dist/{dist-Dc1SFk5I.js → dist-a6Obzr07.js} +2 -2
  83. package/dist/{dist-Bsv_ARko.js → dist-bz6WguLy.js} +2 -2
  84. package/dist/{dist-CC9VUnXd.js → dist-iDeoXzdN.js} +1 -1
  85. package/dist/{dist-BoAHOW2l.js → dist-iyBCcLRa.js} +2 -2
  86. package/dist/{dist-CkEUrAus.js → dist-xCB683Dh.js} +2 -2
  87. package/dist/{erDiagram-Q2GNP2WA-CX1XdqVD.js → erDiagram-Q2GNP2WA-DWCa11g5.js} +10 -10
  88. package/dist/error-banner-vCG-EbUQ.js +619 -0
  89. package/dist/{esm-BAS2d2Ad.js → esm-DZSk8vt3.js} +27 -27
  90. package/dist/{flatten-eGRGXrC3.js → flatten-CWZjF1fc.js} +1 -1
  91. package/dist/{flowDiagram-NV44I4VS-BCj-ONTw.js → flowDiagram-NV44I4VS-BQ5PQs4L.js} +10 -10
  92. package/dist/{ganttDiagram-JELNMOA3-D1l5ewiQ.js → ganttDiagram-JELNMOA3-NTOuNWeT.js} +3 -3
  93. package/dist/{gitGraph-F6HP7TQM-CDM3aU-T.js → gitGraph-F6HP7TQM-DfRNsaDw.js} +3 -3
  94. package/dist/{gitGraphDiagram-NY62KEGX-KdZh0iiW.js → gitGraphDiagram-NY62KEGX-CYke62Ot.js} +13 -13
  95. package/dist/{glide-data-editor-2RvcPqmc.js → glide-data-editor-DttqGjrT.js} +571 -572
  96. package/dist/{graphlib-7UgfJadv.js → graphlib-CwMnCnQ9.js} +8 -8
  97. package/dist/{info-NVLQJR56-CoL1x1Fy.js → info-NVLQJR56-CUaoPtis.js} +3 -3
  98. package/dist/{infoDiagram-WHAUD3N6-PSH7lQ0D.js → infoDiagram-WHAUD3N6-B42WjAPh.js} +13 -13
  99. package/dist/{isEmpty-DQXRKNtW.js → isEmpty-6z2uv6gM.js} +2 -2
  100. package/dist/{isString-Clqvtgmo.js → isString-D6abkXrl.js} +1 -1
  101. package/dist/{isSymbol-TWXhTa8k.js → isSymbol-hk7foJ70.js} +1 -1
  102. package/dist/{journeyDiagram-XKPGCS4Q-BrTAxQ1J.js → journeyDiagram-XKPGCS4Q-ahXD97kr.js} +3 -3
  103. package/dist/{kanban-definition-3W4ZIXB7-BoYCDp_9.js → kanban-definition-3W4ZIXB7-CiTIpnhy.js} +7 -7
  104. package/dist/{label-CxU5JNBW.js → label-Cc5tEavt.js} +250 -250
  105. package/dist/{loader-C0-eIoas.js → loader-Cob3XFOw.js} +2 -2
  106. package/dist/main.js +1791 -1056
  107. package/dist/{memoize-Bag7B41I.js → memoize-Ckyqzyu_.js} +1 -1
  108. package/dist/{merge-Dl1bfxsj.js → merge-Db4Uulx4.js} +1 -1
  109. package/dist/{mermaid-C2cSe5YL.js → mermaid-B5xl_2hx.js} +73 -62
  110. package/dist/{mermaid-parser.core-D20zFbMa.js → mermaid-parser.core-BXj7Il0J.js} +8 -8
  111. package/dist/{min-Bg4bqmiD.js → min-ypdVXicC.js} +4 -4
  112. package/dist/{mindmap-definition-VGOIOE7T-CmRjsKEt.js → mindmap-definition-VGOIOE7T-Mni766A_.js} +9 -9
  113. package/dist/{now-mivqkCIv.js → now-Dwu5ou19.js} +2 -2
  114. package/dist/{once-BqS42WgZ.js → once-C9dA9qgQ.js} +1 -1
  115. package/dist/{packet-BFZMPI3H-C6aZmgV-.js → packet-BFZMPI3H-DHtQCusE.js} +3 -3
  116. package/dist/{pie-7BOR55EZ-NB6xYwcB.js → pie-7BOR55EZ-2sVLYbpR.js} +3 -3
  117. package/dist/{pieDiagram-ADFJNKIX-CtxQlnsU.js → pieDiagram-ADFJNKIX-PbXpgT8_.js} +14 -14
  118. package/dist/{quadrantDiagram-AYHSOK5B-DllnB2Hl.js → quadrantDiagram-AYHSOK5B-BtXGnx8i.js} +2 -2
  119. package/dist/{radar-NHE76QYJ-RKhErikV.js → radar-NHE76QYJ-Be0pEUux.js} +3 -3
  120. package/dist/{range-LoQMRQIX.js → range-D9jxVFd_.js} +5 -5
  121. package/dist/{reduce-B9mZDxPo.js → reduce-C6NEPj6s.js} +4 -4
  122. package/dist/{requirementDiagram-UZGBJVZJ-D36MI1k0.js → requirementDiagram-UZGBJVZJ-DxzXQRgq.js} +9 -9
  123. package/dist/{sankeyDiagram-TZEHDZUN-D1mygNPC.js → sankeyDiagram-TZEHDZUN-D-I7dJ0_.js} +2 -2
  124. package/dist/{sequenceDiagram-WL72ISMW-CWdn91Rf.js → sequenceDiagram-WL72ISMW-VDme2ljw.js} +4 -4
  125. package/dist/{slides-component-DfwLApNr.js → slides-component-ql7-5GDI.js} +2 -2
  126. package/dist/{spec-HoYHAQo2.js → spec-GwhMEXwK.js} +8 -9
  127. package/dist/{stateDiagram-FKZM4ZOC-CPxroWXd.js → stateDiagram-FKZM4ZOC-g3GI1EcK.js} +12 -12
  128. package/dist/{stateDiagram-v2-4FDKWEC3-BpM9Q54b.js → stateDiagram-v2-4FDKWEC3-7i6jBXe6.js} +10 -10
  129. package/dist/stex-D2rme5UG.js +4 -0
  130. package/dist/style.css +1 -1
  131. package/dist/{timeline-definition-IT6M3QCI-CVnRHx_t.js → timeline-definition-IT6M3QCI-bhvLlX_b.js} +2 -2
  132. package/dist/{toString-C4TLO6FA.js → toString-BwTJvlyD.js} +2 -2
  133. package/dist/tooltip-CL8m4f9y.js +404 -0
  134. package/dist/{treemap-KMMF4GRG-B37ugcLd.js → treemap-KMMF4GRG-Ba9ifjpG.js} +3 -3
  135. package/dist/{types-Ckva8JJq.js → types-Dsh6yC4B.js} +412 -413
  136. package/dist/{useAsyncData-dr8GazGv.js → useAsyncData-BPpyKjTJ.js} +2 -2
  137. package/dist/{useDeepCompareMemoize-ChviuF5n.js → useDeepCompareMemoize-C8Ms87P-.js} +18 -19
  138. package/dist/{useIframeCapabilities-DurI5SJh.js → useIframeCapabilities-C7z8VrZ1.js} +2 -2
  139. package/dist/{useTheme-SlKl8MlS.js → useTheme-Cq-gIssy.js} +299 -300
  140. package/dist/{vega-component-CnG0vAjf.js → vega-component-B5sxdjMq.js} +10 -10
  141. package/dist/{xychartDiagram-PRI3JC2R-BltwMWKC.js → xychartDiagram-PRI3JC2R-CFxuifYY.js} +5 -5
  142. package/package.json +1 -1
  143. package/src/components/editor/Output.tsx +8 -6
  144. package/src/components/editor/__tests__/Output.test.tsx +59 -0
  145. package/src/components/editor/chrome/__tests__/state.test.ts +321 -0
  146. package/src/components/editor/chrome/state.ts +27 -2
  147. package/src/components/editor/file-tree/upload.tsx +46 -23
  148. package/src/components/editor/links/cell-link.tsx +3 -2
  149. package/src/components/editor/output/console/ConsoleOutput.tsx +13 -3
  150. package/src/components/pages/gallery-page.tsx +1 -1
  151. package/src/components/pages/home-page.tsx +5 -3
  152. package/src/components/tracing/tracing.tsx +50 -39
  153. package/src/core/documentation/DocHoverTarget.tsx +23 -0
  154. package/src/core/documentation/doc-lookup.ts +50 -0
  155. package/src/core/islands/main.ts +1 -0
  156. package/src/core/websocket/useMarimoKernelConnection.tsx +3 -0
  157. package/src/css/app/Cell.css +5 -0
  158. package/src/mount.tsx +2 -2
  159. package/src/plugins/core/RenderHTML.tsx +15 -0
  160. package/src/plugins/core/__test__/registerReactComponent.test.ts +204 -0
  161. package/src/plugins/core/registerReactComponent.tsx +33 -0
  162. package/src/plugins/impl/MatrixPlugin.tsx +275 -0
  163. package/src/plugins/impl/__tests__/MatrixPlugin.test.tsx +415 -0
  164. package/src/plugins/impl/anywidget/model.ts +1 -2
  165. package/src/plugins/impl/matplotlib/MatplotlibPlugin.tsx +70 -0
  166. package/src/plugins/impl/matplotlib/__tests__/matplotlib-renderer.test.ts +152 -0
  167. package/src/plugins/impl/matplotlib/matplotlib-renderer.ts +781 -0
  168. package/src/plugins/impl/matrix.css +45 -0
  169. package/src/plugins/layout/mermaid/mermaid.tsx +11 -3
  170. package/src/plugins/plugins.ts +4 -0
  171. package/src/utils/__tests__/download.test.tsx +47 -0
  172. package/src/utils/download.ts +13 -1
  173. package/src/utils/links.ts +1 -1
  174. package/src/utils/urls.ts +1 -1
  175. package/dist/Combination-BTMrlhzT.js +0 -2611
  176. package/dist/architecture-U656AL7Q-COfwZju8.js +0 -6
  177. package/dist/dist-4YNZxwMI.js +0 -8
  178. package/dist/dist-7nR3r2kG.js +0 -5
  179. package/dist/dist-B2gkyT3r.js +0 -5
  180. package/dist/dist-B8G3I6vJ.js +0 -8
  181. package/dist/dist-BJ96Ykfp.js +0 -8
  182. package/dist/dist-BKLIWGw4.js +0 -5
  183. package/dist/dist-Bf3ou00A.js +0 -6
  184. package/dist/dist-BvkKXuPm.js +0 -5
  185. package/dist/dist-C6NJ3n6r.js +0 -5
  186. package/dist/dist-CecLPYY5.js +0 -5
  187. package/dist/dist-Ch0SwRzK.js +0 -5
  188. package/dist/dist-D6eWHiFh.js +0 -6
  189. package/dist/dist-DCQ710Bv.js +0 -5
  190. package/dist/dist-P_pkS5f-.js +0 -8
  191. package/dist/error-banner-D2zjeN_a.js +0 -1015
  192. package/dist/hotkeys-B5WnGZXF.js +0 -587
  193. package/dist/stex-ChDHQs3R.js +0 -4
  194. package/dist/zod-bjADtMKr.js +0 -10663
  195. /package/dist/{_arrayReduce-DlK7U3Q6.js → _arrayReduce-REKcIEj3.js} +0 -0
  196. /package/dist/{_baseFor-DSVmVciX.js → _baseFor-B69PDbIz.js} +0 -0
  197. /package/dist/{_hasUnicode-Bz2x6u6r.js → _hasUnicode-DrSAc5A5.js} +0 -0
  198. /package/dist/{dist-r8ecBV-v.js → dist-CUOuFgHt.js} +0 -0
  199. /package/dist/{invariant-D9QLJ4SZ.js → invariant-D-K49MfV.js} +0 -0
  200. /package/dist/{main-DhFbkwoC.js → main-DmxVpB19.js} +0 -0
  201. /package/dist/{purify.es-Brw-U87Q.js → purify.es-D4vaFt5N.js} +0 -0
  202. /package/dist/{stex-DrxP7bb3.js → stex-DIvyJfNO.js} +0 -0
@@ -0,0 +1,45 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ /* Left bracket — vertical line + corner ticks via ::before */
4
+ td.bracket-l::before {
5
+ content: "";
6
+ position: absolute;
7
+ top: 0;
8
+ bottom: 0;
9
+ left: -4px;
10
+ width: 0;
11
+ border-left: 2px solid var(--foreground);
12
+ pointer-events: none;
13
+ }
14
+ td.bracket-l.bracket-t::before {
15
+ top: -1px;
16
+ width: 8px;
17
+ border-top: 2px solid var(--foreground);
18
+ }
19
+ td.bracket-l.bracket-b::before {
20
+ bottom: -1px;
21
+ width: 8px;
22
+ border-bottom: 2px solid var(--foreground);
23
+ }
24
+
25
+ /* Right bracket — vertical line + corner ticks via ::after */
26
+ td.bracket-r::after {
27
+ content: "";
28
+ position: absolute;
29
+ top: 0;
30
+ bottom: 0;
31
+ right: -4px;
32
+ width: 0;
33
+ border-right: 2px solid var(--foreground);
34
+ pointer-events: none;
35
+ }
36
+ td.bracket-r.bracket-t::after {
37
+ top: -1px;
38
+ width: 8px;
39
+ border-top: 2px solid var(--foreground);
40
+ }
41
+ td.bracket-r.bracket-b::after {
42
+ bottom: -1px;
43
+ width: 8px;
44
+ border-bottom: 2px solid var(--foreground);
45
+ }
@@ -4,6 +4,7 @@ import type { MermaidConfig } from "mermaid";
4
4
  import mermaid from "mermaid";
5
5
  import React, { useState } from "react";
6
6
  import { useAsyncData } from "@/hooks/useAsyncData";
7
+ import { ErrorBanner } from "@/plugins/impl/common/error-banner";
7
8
  import { useTheme } from "@/theme/useTheme";
8
9
  import { Logger } from "@/utils/Logger";
9
10
 
@@ -72,9 +73,12 @@ const Mermaid: React.FC<Props> = ({ diagram }) => {
72
73
  darkMode: darkMode,
73
74
  });
74
75
 
75
- const { data: svg } = useAsyncData(async () => {
76
+ // Frontmatter does not work with newlines, so we trim the diagram to avoid these errors
77
+ const trimmedDiagram = diagram.trim();
78
+
79
+ const { data: svg, error } = useAsyncData(async () => {
76
80
  const result = await mermaid
77
- .render(id, diagram, undefined)
81
+ .render(id, trimmedDiagram, undefined)
78
82
  .catch((error) => {
79
83
  document.getElementById(id)?.remove();
80
84
  Logger.warn("Failed to render mermaid diagram", error);
@@ -82,7 +86,11 @@ const Mermaid: React.FC<Props> = ({ diagram }) => {
82
86
  });
83
87
 
84
88
  return result.svg;
85
- }, [diagram, id, darkMode]);
89
+ }, [trimmedDiagram, id, darkMode]);
90
+
91
+ if (error) {
92
+ return <ErrorBanner error={error} />;
93
+ }
86
94
 
87
95
  if (!svg) {
88
96
  return null;
@@ -22,8 +22,10 @@ import { DataFramePlugin } from "./impl/data-frames/DataFramePlugin";
22
22
  import { FileBrowserPlugin } from "./impl/FileBrowserPlugin";
23
23
  import { FileUploadPlugin } from "./impl/FileUploadPlugin";
24
24
  import { FormPlugin } from "./impl/FormPlugin";
25
+ import { MatrixPlugin } from "./impl/MatrixPlugin";
25
26
  import { MicrophonePlugin } from "./impl/MicrophonePlugin";
26
27
  import { MultiselectPlugin } from "./impl/MultiselectPlugin";
28
+ import { MatplotlibPlugin } from "./impl/matplotlib/MatplotlibPlugin";
27
29
  import { NumberPlugin } from "./impl/NumberPlugin";
28
30
  import { PanelPlugin } from "./impl/panel/PanelPlugin";
29
31
  import { PlotlyPlugin } from "./impl/plotly/PlotlyPlugin";
@@ -67,6 +69,7 @@ export const UI_PLUGINS: IPlugin<any, unknown>[] = [
67
69
  new FileUploadPlugin(),
68
70
  FileBrowserPlugin,
69
71
  FormPlugin,
72
+ new MatrixPlugin(),
70
73
  new MicrophonePlugin(),
71
74
  new MultiselectPlugin(),
72
75
  new NumberPlugin(),
@@ -79,6 +82,7 @@ export const UI_PLUGINS: IPlugin<any, unknown>[] = [
79
82
  new TextAreaPlugin(),
80
83
  new TextInputPlugin(),
81
84
  new VegaPlugin(),
85
+ new MatplotlibPlugin(),
82
86
  new PlotlyPlugin(),
83
87
  ChatPlugin,
84
88
  DataExplorerPlugin,
@@ -17,9 +17,11 @@ vi.mock("html-to-image", () => ({
17
17
 
18
18
  // Mock the toast module
19
19
  const mockDismiss = vi.fn();
20
+ const mockUpdate = vi.fn();
20
21
  vi.mock("@/components/ui/use-toast", () => ({
21
22
  toast: vi.fn(() => ({
22
23
  dismiss: mockDismiss,
24
+ update: mockUpdate,
23
25
  })),
24
26
  }));
25
27
 
@@ -113,6 +115,51 @@ describe("withLoadingToast", () => {
113
115
  );
114
116
  });
115
117
 
118
+ it("should update toast on finish when onFinish is provided", async () => {
119
+ await withLoadingToast("Uploading files...", async () => "done", {
120
+ title: "Upload complete",
121
+ });
122
+
123
+ expect(toast).toHaveBeenCalledTimes(1);
124
+ expect(mockUpdate).toHaveBeenCalledTimes(1);
125
+ expect(mockUpdate).toHaveBeenCalledWith(
126
+ expect.objectContaining({
127
+ title: "Upload complete",
128
+ description: undefined,
129
+ duration: 1200,
130
+ }),
131
+ );
132
+ expect(mockDismiss).not.toHaveBeenCalled();
133
+ });
134
+
135
+ it("should allow onFinish to override duration", async () => {
136
+ await withLoadingToast("Uploading files...", async () => "done", {
137
+ title: "Upload complete",
138
+ duration: 2000,
139
+ });
140
+
141
+ expect(mockUpdate).toHaveBeenCalledWith(
142
+ expect.objectContaining({
143
+ duration: 2000,
144
+ }),
145
+ );
146
+ });
147
+
148
+ it("should not update toast when the operation fails", async () => {
149
+ await expect(
150
+ withLoadingToast(
151
+ "Uploading files...",
152
+ async () => {
153
+ throw new Error("Upload failed");
154
+ },
155
+ { title: "Upload complete" },
156
+ ),
157
+ ).rejects.toThrow("Upload failed");
158
+
159
+ expect(toast).toHaveBeenCalledTimes(1);
160
+ expect(mockUpdate).not.toHaveBeenCalled();
161
+ });
162
+
116
163
  it("should wait for the async function to complete", async () => {
117
164
  const events: string[] = [];
118
165
 
@@ -13,6 +13,9 @@ import { Logger } from "./Logger";
13
13
  import { ProgressState } from "./progress";
14
14
  import { ToastProgress } from "./toast-progress";
15
15
 
16
+ const FINISH_TOAST_DURATION_MS = 1200;
17
+ type ToastConfig = Omit<Parameters<typeof toast>[0], "id">;
18
+
16
19
  /**
17
20
  * Show a loading toast while an async operation is in progress.
18
21
  * Automatically dismisses the toast when the operation completes or fails.
@@ -20,6 +23,7 @@ import { ToastProgress } from "./toast-progress";
20
23
  export async function withLoadingToast<T>(
21
24
  title: string,
22
25
  fn: (progress: ProgressState) => Promise<T>,
26
+ onFinish?: ToastConfig,
23
27
  ): Promise<T> {
24
28
  const progress = ProgressState.indeterminate();
25
29
  const loadingToast = toast({
@@ -29,7 +33,15 @@ export async function withLoadingToast<T>(
29
33
  });
30
34
  try {
31
35
  const result = await fn(progress);
32
- loadingToast.dismiss();
36
+ if (onFinish) {
37
+ loadingToast.update({
38
+ duration: FINISH_TOAST_DURATION_MS,
39
+ description: undefined,
40
+ ...onFinish,
41
+ });
42
+ } else {
43
+ loadingToast.dismiss();
44
+ }
33
45
  return result;
34
46
  } catch (error) {
35
47
  loadingToast.dismiss();
@@ -7,5 +7,5 @@ import { asURL } from "./url";
7
7
  */
8
8
  export function openNotebook(path: string) {
9
9
  // There is no leading `/` in the path in order to work when marimo is at a subpath.
10
- window.open(asURL(`?file=${path}`).toString(), "_blank");
10
+ window.open(asURL(`?file=${encodeURIComponent(path)}`).toString(), "_blank");
11
11
  }
package/src/utils/urls.ts CHANGED
@@ -24,7 +24,7 @@ export function hasQueryParam(key: string, value?: string): boolean {
24
24
  export function newNotebookURL() {
25
25
  const sessionId = generateSessionId();
26
26
  const initializationId = `__new__${sessionId}`;
27
- return asURL(`?file=${initializationId}`).toString();
27
+ return asURL(`?file=${encodeURIComponent(initializationId)}`).toString();
28
28
  }
29
29
 
30
30
  const urlRegex = /^(https?:\/\/\S+)$/;