@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
@@ -1,19 +1,19 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_react } from "./react-Bs6Z0kvn.js";
3
3
  import { t as require_compiler_runtime } from "./compiler-runtime-B_OLMU9S.js";
4
- import "./Combination-BTMrlhzT.js";
5
- import { S as CircleQuestionMark, a as AlertTitle, m as asRemoteURL, n as arrow, o as isValid, r as Alert, t as useDeepCompareMemoize } from "./useDeepCompareMemoize-ChviuF5n.js";
6
- import { l as Events } from "./button-Cy0ElmIm.js";
7
- import { o as Objects, s as Logger } from "./hotkeys-B5WnGZXF.js";
4
+ import { S as CircleQuestionMark, a as AlertTitle, m as asRemoteURL, n as arrow, o as isValid, r as Alert, t as useDeepCompareMemoize } from "./useDeepCompareMemoize-C8Ms87P-.js";
5
+ import { d as Objects, g as Logger, h as Events } from "./button-KYalaJYu.js";
6
+ import "./Combination-Du-o_hC9.js";
8
7
  import { t as require_jsx_runtime } from "./jsx-runtime-CTBg5pdT.js";
9
8
  import "./react-dom-CqtLRVZP.js";
10
- import { l as Tooltip, n as ErrorBanner } from "./error-banner-D2zjeN_a.js";
11
- import { h as useEvent_default, n as useTheme } from "./useTheme-SlKl8MlS.js";
12
- import { t as _baseUniq_default } from "./_baseUniq-4lqa8rDi.js";
13
- import { i as debounce_default } from "./constants-DrOu5vvd.js";
14
- import { a as tooltipHandler, n as vegaLoadData } from "./loader-C0-eIoas.js";
9
+ import { t as Tooltip } from "./tooltip-CL8m4f9y.js";
10
+ import { t as _baseUniq_default } from "./_baseUniq-BlF21ach.js";
11
+ import { i as debounce_default } from "./constants-BGRTDzdW.js";
12
+ import { C as useEvent_default, n as useTheme } from "./useTheme-Cq-gIssy.js";
13
+ import { a as tooltipHandler, n as vegaLoadData } from "./loader-Cob3XFOw.js";
14
+ import { n as ErrorBanner } from "./error-banner-vCG-EbUQ.js";
15
15
  import { n as formats } from "./vega-loader.browser-DqHiiBeQ.js";
16
- import { t as useAsyncData } from "./useAsyncData-dr8GazGv.js";
16
+ import { t as useAsyncData } from "./useAsyncData-BPpyKjTJ.js";
17
17
  import { t as j } from "./react-vega-CCNu2JE0.js";
18
18
  import "./defaultLocale-DjFHq3Xk.js";
19
19
  import "./defaultLocale-B_A76Zpk.js";
@@ -1,17 +1,17 @@
1
1
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2
- import "./purify.es-Brw-U87Q.js";
2
+ import "./purify.es-D4vaFt5N.js";
3
3
  import { t as linear } from "./linear-Bnc6E9kA.js";
4
4
  import { n as ordinal } from "./ordinal-DLLbwLkP.js";
5
5
  import { t as range } from "./range-DwpxnYuB.js";
6
6
  import "./defaultLocale-DjFHq3Xk.js";
7
7
  import { t as line_default } from "./line-Bc27KE1D.js";
8
- import { i as cleanAndMerge } from "./chunk-S3R3BYOJ-CwDGYMVf.js";
8
+ import { i as cleanAndMerge } from "./chunk-S3R3BYOJ-C_1SJcWo.js";
9
9
  import { n as initRange } from "./init-TaqZJsBY.js";
10
10
  import { i as log, r as __name } from "./src-jICM_d2B.js";
11
- import { B as setAccTitle, C as getDiagramTitle, I as sanitizeText, T as getThemeVariables3, U as setDiagramTitle, _ as getAccDescription, a as clear, c as configureSvgSize, d as defaultConfig_default, v as getAccTitle, y as getConfig, z as setAccDescription } from "./chunk-ABZYJK2D-BGWvKte3.js";
12
- import { t as selectSvgElement } from "./chunk-EXTU4WIE-BlA7aWEw.js";
11
+ import { B as setAccTitle, C as getDiagramTitle, I as sanitizeText, T as getThemeVariables3, U as setDiagramTitle, _ as getAccDescription, a as clear, c as configureSvgSize, d as defaultConfig_default, v as getAccTitle, y as getConfig, z as setAccDescription } from "./chunk-ABZYJK2D-BwNsaa1P.js";
12
+ import { t as selectSvgElement } from "./chunk-EXTU4WIE-Bmo660a9.js";
13
13
  import "./dist-BYznkC5E.js";
14
- import { t as computeDimensionOfText } from "./chunk-JA3XYJ7Z-Cm-pccR-.js";
14
+ import { t as computeDimensionOfText } from "./chunk-JA3XYJ7Z-n8UTzfok.js";
15
15
  function band() {
16
16
  var e = ordinal().unknown(void 0), w = e.domain, T = e.range, D = 0, O = 1, k, A, j = false, M = 0, N = 0, P = 0.5;
17
17
  delete e.unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.19.12-dev1",
3
+ "version": "0.20.0",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -123,6 +123,7 @@ export const OutputRenderer: React.FC<{
123
123
  );
124
124
 
125
125
  case "text/plain":
126
+ case "text/password":
126
127
  invariant(
127
128
  typeof data === "string",
128
129
  `Expected string data for mime=${mimetype}. Got ${typeof data}`,
@@ -141,10 +142,17 @@ export const OutputRenderer: React.FC<{
141
142
  case "image/bmp":
142
143
  case "image/gif":
143
144
  case "image/jpeg":
145
+ case "image/svg+xml":
144
146
  invariant(
145
147
  typeof data === "string",
146
148
  `Expected string data for mime=${mimetype}. Got ${typeof data}`,
147
149
  );
150
+ if (
151
+ mimetype === "image/svg+xml" &&
152
+ !data.startsWith("data:image/svg+xml;base64,")
153
+ ) {
154
+ return renderHTML({ html: data, alwaysSanitizeHtml: true });
155
+ }
148
156
  return (
149
157
  <ImageOutput
150
158
  className={channel}
@@ -154,12 +162,6 @@ export const OutputRenderer: React.FC<{
154
162
  height={metadata?.height}
155
163
  />
156
164
  );
157
- case "image/svg+xml":
158
- invariant(
159
- typeof data === "string",
160
- `Expected string data for mime=${mimetype}. Got ${typeof data}`,
161
- );
162
- return renderHTML({ html: data, alwaysSanitizeHtml: true });
163
165
 
164
166
  case "video/mp4":
165
167
  case "video/mpeg":
@@ -64,3 +64,62 @@ describe("OutputRenderer renderFallback prop", () => {
64
64
  ).toBeInTheDocument();
65
65
  });
66
66
  });
67
+
68
+ describe("OutputRenderer image and SVG rendering", () => {
69
+ const plainSvgString =
70
+ '<svg><rect x="0" y="0" width="10" height="10"></rect></svg>';
71
+ const base64SvgDataUrl =
72
+ "data:image/svg+xml;base64,PHN2Zz48cmVjdCB4PSIwIiB5PSIw";
73
+ const base64PngDataUrl =
74
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB";
75
+
76
+ it("should render plain SVG string via renderHTML", () => {
77
+ const { container } = render(
78
+ <OutputRenderer
79
+ message={{
80
+ channel: "output",
81
+ data: plainSvgString,
82
+ mimetype: "image/svg+xml",
83
+ }}
84
+ />,
85
+ );
86
+ const svgElement = container.querySelector("svg");
87
+ expect(svgElement).not.toBeNull();
88
+ const rectElement = svgElement!.querySelector("rect");
89
+ expect(rectElement).not.toBeNull();
90
+ const imgElement = container.querySelector("img");
91
+ expect(imgElement).toBeNull();
92
+ });
93
+
94
+ it("should render Base64 SVG data URL via ImageOutput", () => {
95
+ const { container } = render(
96
+ <OutputRenderer
97
+ message={{
98
+ channel: "output",
99
+ data: base64SvgDataUrl,
100
+ mimetype: "image/svg+xml",
101
+ }}
102
+ />,
103
+ );
104
+ const imgElement = container.querySelector("img");
105
+ expect(imgElement).not.toBeNull();
106
+ expect(imgElement).toHaveAttribute("src", base64SvgDataUrl);
107
+ const svgElement = container.querySelector("svg");
108
+ expect(svgElement).toBeNull();
109
+ });
110
+
111
+ it("should render Base64 PNG data URL via ImageOutput", () => {
112
+ const { container } = render(
113
+ <OutputRenderer
114
+ message={{
115
+ channel: "output",
116
+ data: base64PngDataUrl,
117
+ mimetype: "image/png",
118
+ }}
119
+ />,
120
+ );
121
+ const imgElement = container.querySelector("img");
122
+ expect(imgElement).not.toBeNull();
123
+ expect(imgElement).toHaveAttribute("src", base64PngDataUrl);
124
+ });
125
+ });
@@ -0,0 +1,321 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { describe, expect, it } from "vitest";
3
+ import { adaptForLocalStorage } from "@/utils/storage/jotai";
4
+ import type { PanelLayout } from "../state";
5
+ import { exportedForTesting } from "../state";
6
+
7
+ const { mergePanelLayout } = exportedForTesting;
8
+
9
+ describe("mergePanelLayout", () => {
10
+ // Exact localStorage value from SageMaker Studio that caused the bug:
11
+ // saved before Terminal was added, so "terminal" is absent from
12
+ // developerPanel and the tab never renders.
13
+ it("appends terminal to a pre-terminal-era saved layout", () => {
14
+ const saved: PanelLayout = {
15
+ sidebar: [
16
+ "files",
17
+ "variables",
18
+ "packages",
19
+ "ai",
20
+ "outline",
21
+ "documentation",
22
+ "dependencies",
23
+ ],
24
+ developerPanel: [
25
+ "errors",
26
+ "scratchpad",
27
+ "tracing",
28
+ "secrets",
29
+ "snippets",
30
+ "logs",
31
+ ],
32
+ };
33
+ expect(mergePanelLayout(saved)).toEqual({
34
+ sidebar: [
35
+ "files",
36
+ "variables",
37
+ "packages",
38
+ "ai",
39
+ "outline",
40
+ "documentation",
41
+ "dependencies",
42
+ ],
43
+ developerPanel: [
44
+ "errors",
45
+ "scratchpad",
46
+ "tracing",
47
+ "secrets",
48
+ "snippets",
49
+ "logs",
50
+ "terminal",
51
+ ],
52
+ });
53
+ });
54
+
55
+ it("appends new sidebar panels missing from saved layout", () => {
56
+ const saved: PanelLayout = {
57
+ sidebar: ["files", "variables"],
58
+ developerPanel: [
59
+ "errors",
60
+ "scratchpad",
61
+ "tracing",
62
+ "secrets",
63
+ "logs",
64
+ "terminal",
65
+ "snippets",
66
+ ],
67
+ };
68
+ expect(mergePanelLayout(saved)).toEqual({
69
+ sidebar: [
70
+ "files",
71
+ "variables",
72
+ "packages",
73
+ "ai",
74
+ "outline",
75
+ "documentation",
76
+ "dependencies",
77
+ ],
78
+ developerPanel: [
79
+ "errors",
80
+ "scratchpad",
81
+ "tracing",
82
+ "secrets",
83
+ "logs",
84
+ "terminal",
85
+ "snippets",
86
+ ],
87
+ });
88
+ });
89
+
90
+ it("appends new developer panel entries missing from saved layout", () => {
91
+ const saved: PanelLayout = {
92
+ sidebar: [
93
+ "files",
94
+ "variables",
95
+ "packages",
96
+ "ai",
97
+ "outline",
98
+ "documentation",
99
+ "dependencies",
100
+ ],
101
+ developerPanel: ["errors", "scratchpad", "tracing", "logs"],
102
+ };
103
+ expect(mergePanelLayout(saved)).toEqual({
104
+ sidebar: [
105
+ "files",
106
+ "variables",
107
+ "packages",
108
+ "ai",
109
+ "outline",
110
+ "documentation",
111
+ "dependencies",
112
+ ],
113
+ developerPanel: [
114
+ "errors",
115
+ "scratchpad",
116
+ "tracing",
117
+ "logs",
118
+ "secrets",
119
+ "terminal",
120
+ "snippets",
121
+ ],
122
+ });
123
+ });
124
+
125
+ it("does not duplicate panels already present", () => {
126
+ const saved: PanelLayout = {
127
+ sidebar: [
128
+ "files",
129
+ "variables",
130
+ "packages",
131
+ "ai",
132
+ "outline",
133
+ "documentation",
134
+ "dependencies",
135
+ ],
136
+ developerPanel: [
137
+ "errors",
138
+ "scratchpad",
139
+ "tracing",
140
+ "secrets",
141
+ "logs",
142
+ "terminal",
143
+ "snippets",
144
+ ],
145
+ };
146
+ expect(mergePanelLayout(saved)).toEqual({
147
+ sidebar: [
148
+ "files",
149
+ "variables",
150
+ "packages",
151
+ "ai",
152
+ "outline",
153
+ "documentation",
154
+ "dependencies",
155
+ ],
156
+ developerPanel: [
157
+ "errors",
158
+ "scratchpad",
159
+ "tracing",
160
+ "secrets",
161
+ "logs",
162
+ "terminal",
163
+ "snippets",
164
+ ],
165
+ });
166
+ });
167
+
168
+ it("preserves panels the user moved between sections", () => {
169
+ const saved: PanelLayout = {
170
+ sidebar: ["files"],
171
+ developerPanel: ["errors", "variables"],
172
+ };
173
+ expect(mergePanelLayout(saved)).toEqual({
174
+ sidebar: [
175
+ "files",
176
+ "packages",
177
+ "ai",
178
+ "outline",
179
+ "documentation",
180
+ "dependencies",
181
+ ],
182
+ developerPanel: [
183
+ "errors",
184
+ "variables",
185
+ "scratchpad",
186
+ "tracing",
187
+ "secrets",
188
+ "logs",
189
+ "terminal",
190
+ "snippets",
191
+ ],
192
+ });
193
+ });
194
+
195
+ it("handles empty saved layout", () => {
196
+ const saved: PanelLayout = {
197
+ sidebar: [],
198
+ developerPanel: [],
199
+ };
200
+ expect(mergePanelLayout(saved)).toEqual({
201
+ sidebar: [
202
+ "files",
203
+ "variables",
204
+ "packages",
205
+ "ai",
206
+ "outline",
207
+ "documentation",
208
+ "dependencies",
209
+ ],
210
+ developerPanel: [
211
+ "errors",
212
+ "scratchpad",
213
+ "tracing",
214
+ "secrets",
215
+ "logs",
216
+ "terminal",
217
+ "snippets",
218
+ ],
219
+ });
220
+ });
221
+ });
222
+
223
+ describe("panelLayoutStorage integration", () => {
224
+ it("merges missing panels when reading from localStorage", () => {
225
+ // Simulate the exact SageMaker bug: stale layout in localStorage
226
+ const staleLayout: PanelLayout = {
227
+ sidebar: [
228
+ "files",
229
+ "variables",
230
+ "packages",
231
+ "ai",
232
+ "outline",
233
+ "documentation",
234
+ "dependencies",
235
+ ],
236
+ developerPanel: [
237
+ "errors",
238
+ "scratchpad",
239
+ "tracing",
240
+ "secrets",
241
+ "snippets",
242
+ "logs",
243
+ ],
244
+ };
245
+
246
+ // Mock localStorage with the stale value
247
+ const mockStorage: Storage = {
248
+ length: 1,
249
+ key: () => null,
250
+ clear: () => undefined,
251
+ removeItem: () => undefined,
252
+ setItem: () => undefined,
253
+ getItem: (key: string) => {
254
+ if (key === "marimo:panel-layout") {
255
+ return JSON.stringify(staleLayout);
256
+ }
257
+ return null;
258
+ },
259
+ };
260
+
261
+ const storage = adaptForLocalStorage<PanelLayout, PanelLayout>({
262
+ toSerializable: (v) => v,
263
+ fromSerializable: (saved) => mergePanelLayout(saved),
264
+ storage: mockStorage,
265
+ });
266
+
267
+ // This is what atomWithStorage calls on init
268
+ const defaultValue: PanelLayout = {
269
+ sidebar: [],
270
+ developerPanel: [],
271
+ };
272
+ const result = storage.getItem("marimo:panel-layout", defaultValue);
273
+
274
+ expect(result).toEqual({
275
+ sidebar: [
276
+ "files",
277
+ "variables",
278
+ "packages",
279
+ "ai",
280
+ "outline",
281
+ "documentation",
282
+ "dependencies",
283
+ ],
284
+ developerPanel: [
285
+ "errors",
286
+ "scratchpad",
287
+ "tracing",
288
+ "secrets",
289
+ "snippets",
290
+ "logs",
291
+ "terminal",
292
+ ],
293
+ });
294
+ });
295
+
296
+ it("returns default when localStorage is empty", () => {
297
+ const mockStorage: Storage = {
298
+ length: 0,
299
+ key: () => null,
300
+ clear: () => undefined,
301
+ removeItem: () => undefined,
302
+ setItem: () => undefined,
303
+ getItem: () => null,
304
+ };
305
+
306
+ const storage = adaptForLocalStorage<PanelLayout, PanelLayout>({
307
+ toSerializable: (v) => v,
308
+ fromSerializable: (saved) => mergePanelLayout(saved),
309
+ storage: mockStorage,
310
+ });
311
+
312
+ const defaultValue: PanelLayout = {
313
+ sidebar: ["files"],
314
+ developerPanel: ["errors"],
315
+ };
316
+ const result = storage.getItem("marimo:panel-layout", defaultValue);
317
+
318
+ // Should return the initialValue (default) since nothing in storage
319
+ expect(result).toEqual(defaultValue);
320
+ });
321
+ });
@@ -5,7 +5,7 @@ import { atomWithStorage } from "jotai/utils";
5
5
  import { z } from "zod";
6
6
  import { store } from "@/core/state/jotai";
7
7
  import { createReducerAndAtoms } from "@/utils/createReducer";
8
- import { jotaiJsonStorage } from "@/utils/storage/jotai";
8
+ import { adaptForLocalStorage } from "@/utils/storage/jotai";
9
9
  import { ZodLocalStorage } from "@/utils/storage/typed";
10
10
  import type { PanelSection, PanelType } from "./types";
11
11
  import { PANELS } from "./types";
@@ -35,10 +35,34 @@ const DEFAULT_PANEL_LAYOUT: PanelLayout = {
35
35
  ).map((p) => p.type),
36
36
  };
37
37
 
38
+ /**
39
+ * Merge saved layout with current defaults so new panels added in later
40
+ * versions are appended to their default section. Panels the user has
41
+ * moved between sections are left where the user put them.
42
+ */
43
+ function mergePanelLayout(saved: PanelLayout): PanelLayout {
44
+ const allSaved = new Set([...saved.sidebar, ...saved.developerPanel]);
45
+ return {
46
+ sidebar: [
47
+ ...saved.sidebar,
48
+ ...DEFAULT_PANEL_LAYOUT.sidebar.filter((p) => !allSaved.has(p)),
49
+ ],
50
+ developerPanel: [
51
+ ...saved.developerPanel,
52
+ ...DEFAULT_PANEL_LAYOUT.developerPanel.filter((p) => !allSaved.has(p)),
53
+ ],
54
+ };
55
+ }
56
+
57
+ const panelLayoutStorage = adaptForLocalStorage<PanelLayout, PanelLayout>({
58
+ toSerializable: (v) => v,
59
+ fromSerializable: (saved) => mergePanelLayout(saved),
60
+ });
61
+
38
62
  export const panelLayoutAtom = atomWithStorage<PanelLayout>(
39
63
  "marimo:panel-layout",
40
64
  DEFAULT_PANEL_LAYOUT,
41
- jotaiJsonStorage,
65
+ panelLayoutStorage,
42
66
  { getOnInit: true },
43
67
  );
44
68
 
@@ -181,4 +205,5 @@ export const exportedForTesting = {
181
205
  reducer,
182
206
  createActions,
183
207
  initialState,
208
+ mergePanelLayout,
184
209
  };
@@ -4,6 +4,7 @@ import { type DropzoneOptions, useDropzone } from "react-dropzone";
4
4
  import { toast } from "@/components/ui/use-toast";
5
5
  import { useRequestClient } from "@/core/network/requests";
6
6
  import { serializeBlob } from "@/utils/blob";
7
+ import { withLoadingToast } from "@/utils/download";
7
8
  import { Logger } from "@/utils/Logger";
8
9
  import { type FilePath, PathBuilder } from "@/utils/paths";
9
10
  import { refreshRoot } from "./state";
@@ -40,30 +41,52 @@ export function useFileExplorerUpload(options: DropzoneOptions = {}) {
40
41
  });
41
42
  },
42
43
  onDrop: async (acceptedFiles) => {
43
- for (const file of acceptedFiles) {
44
- // We strip the leading slash since File.path can return
45
- // `/path/to/file`.
46
- const filePath = stripLeadingSlash(getPath(file));
47
- let directoryPath = "" as FilePath;
48
- if (filePath) {
49
- directoryPath =
50
- PathBuilder.guessDeliminator(filePath).dirname(filePath);
51
- }
52
-
53
- // File contents are sent base64-encoded to support arbitrary
54
- // bytes data
55
- //
56
- // get the raw base64-encoded data from a string starting with
57
- // data:*/*;base64,
58
- const base64 = (await serializeBlob(file)).split(",")[1];
59
- await sendCreateFileOrFolder({
60
- path: directoryPath,
61
- type: "file",
62
- name: file.name,
63
- contents: base64,
64
- });
44
+ if (acceptedFiles.length === 0) {
45
+ return;
65
46
  }
66
- await refreshRoot();
47
+ const isSingle = acceptedFiles.length === 1;
48
+
49
+ const loadingTitle = isSingle
50
+ ? "Uploading file..."
51
+ : "Uploading files...";
52
+ const onFinish = {
53
+ title: isSingle
54
+ ? "File uploaded"
55
+ : `${acceptedFiles.length} files uploaded`,
56
+ };
57
+
58
+ await withLoadingToast(
59
+ loadingTitle,
60
+ async (progress) => {
61
+ progress.addTotal(acceptedFiles.length);
62
+ for (const file of acceptedFiles) {
63
+ // We strip the leading slash since File.path can return
64
+ // `/path/to/file`.
65
+ const filePath = stripLeadingSlash(getPath(file));
66
+ let directoryPath = "" as FilePath;
67
+ if (filePath) {
68
+ directoryPath =
69
+ PathBuilder.guessDeliminator(filePath).dirname(filePath);
70
+ }
71
+
72
+ // File contents are sent base64-encoded to support arbitrary
73
+ // bytes data
74
+ //
75
+ // get the raw base64-encoded data from a string starting with
76
+ // data:*/*;base64,
77
+ const base64 = (await serializeBlob(file)).split(",")[1];
78
+ await sendCreateFileOrFolder({
79
+ path: directoryPath,
80
+ type: "file",
81
+ name: file.name,
82
+ contents: base64,
83
+ });
84
+ progress.increment(1);
85
+ }
86
+ await refreshRoot();
87
+ },
88
+ onFinish,
89
+ );
67
90
  },
68
91
  ...options,
69
92
  });
@@ -97,6 +97,7 @@ export function scrollAndHighlightCell(
97
97
  ): boolean {
98
98
  const cellHtmlId = HTMLCellId.create(cellId);
99
99
  const cell: HTMLElement | null = document.getElementById(cellHtmlId);
100
+ const isCellErrored = cell?.classList.contains("has-error");
100
101
 
101
102
  if (cell === null) {
102
103
  Logger.error(`Cell ${cellHtmlId} not found on page.`);
@@ -106,13 +107,13 @@ export function scrollAndHighlightCell(
106
107
  cell.scrollIntoView({ behavior: "smooth", block: "center" });
107
108
  }
108
109
 
109
- if (variant === "destructive") {
110
+ if (variant === "destructive" || (isCellErrored && variant === undefined)) {
110
111
  cell.classList.add("error-outline");
111
112
  setTimeout(() => {
112
113
  cell.classList.remove("error-outline");
113
114
  }, 2000);
114
115
  }
115
- if (variant === "focus") {
116
+ if (variant === "focus" || (!isCellErrored && variant === undefined)) {
116
117
  cell.classList.add("focus-outline");
117
118
  setTimeout(() => {
118
119
  cell.classList.remove("focus-outline");