@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.
- package/dist/Combination-Du-o_hC9.js +11897 -0
- package/dist/{ConnectedDataExplorerComponent-CkXO-pKy.js → ConnectedDataExplorerComponent-BMiGWK57.js} +19 -18
- package/dist/{_baseIsEqual-CBSjxu-D.js → _baseIsEqual-DN5YkPnl.js} +1 -1
- package/dist/{_baseProperty-BVGrW_NZ.js → _baseProperty-6juuyX7Z.js} +5 -5
- package/dist/{_baseUniq-4lqa8rDi.js → _baseUniq-BlF21ach.js} +1 -1
- package/dist/{any-language-editor-t_VsTNa-.js → any-language-editor-1OMbohwD.js} +19 -19
- package/dist/architecture-U656AL7Q-Jd2CvPgJ.js +6 -0
- package/dist/{architectureDiagram-VXUJARFQ-DmJQhcJb.js → architectureDiagram-VXUJARFQ-DhN0C3Xf.js} +15 -15
- package/dist/{blockDiagram-VD42YOAC-CRofISJs.js → blockDiagram-VD42YOAC-DrBkIcbV.js} +7 -7
- package/dist/{button-Cy0ElmIm.js → button-KYalaJYu.js} +783 -200
- package/dist/{c4Diagram-YG6GDRKO-Deqoag4I.js → c4Diagram-YG6GDRKO-pWt4zmu0.js} +4 -4
- package/dist/{channel-CMsnebrL.js → channel-C56Jz8EL.js} +1 -1
- package/dist/{check-DkNR52Mm.js → check-C50jsehH.js} +1 -1
- package/dist/{chunk-76Q3JFCE-jPuajZH_.js → chunk-76Q3JFCE-CQ6a2yGJ.js} +1 -1
- package/dist/{chunk-ABZYJK2D-BGWvKte3.js → chunk-ABZYJK2D-BwNsaa1P.js} +1 -1
- package/dist/{chunk-ATLVNIR6-BYZB6C5T.js → chunk-ATLVNIR6-DtFMAawc.js} +1 -1
- package/dist/{chunk-B4BG7PRW-CwYUp6Uj.js → chunk-B4BG7PRW-lfWcLlzS.js} +4 -4
- package/dist/{chunk-DI55MBZ5-Gyro6dvN.js → chunk-DI55MBZ5-RhhAimfG.js} +4 -4
- package/dist/{chunk-EXTU4WIE-BlA7aWEw.js → chunk-EXTU4WIE-Bmo660a9.js} +1 -1
- package/dist/{chunk-FPAJGGOC-CduL34ft.js → chunk-FPAJGGOC-quWdfNUB.js} +7 -7
- package/dist/{chunk-FWNWRKHM-C-2TI4gt.js → chunk-FWNWRKHM-DmrwhAQr.js} +1 -1
- package/dist/{chunk-JA3XYJ7Z-Cm-pccR-.js → chunk-JA3XYJ7Z-n8UTzfok.js} +2 -2
- package/dist/{chunk-JZLCHNYA-CoLqqXMe.js → chunk-JZLCHNYA-ChKqHUdB.js} +4 -4
- package/dist/{chunk-LBM3YZW2-DWgQiioW.js → chunk-LBM3YZW2-BkxsqkNK.js} +1 -1
- package/dist/{chunk-LHMN2FUI-Dj_AHSvI.js → chunk-LHMN2FUI-CgYPnxfN.js} +1 -1
- package/dist/{chunk-N4CR4FBY-ByLbY9L-.js → chunk-N4CR4FBY-BxOHGL3P.js} +5 -5
- package/dist/{chunk-O7ZBX7Z2-CRZ8i1rP.js → chunk-O7ZBX7Z2-CdpLwOP0.js} +1 -1
- package/dist/{chunk-QN33PNHL-eodIiY9F.js → chunk-QN33PNHL-Dda-55xY.js} +1 -1
- package/dist/{chunk-QXUST7PY-CuJlDW6A.js → chunk-QXUST7PY-ClIEpoCT.js} +5 -5
- package/dist/{chunk-S3R3BYOJ-CwDGYMVf.js → chunk-S3R3BYOJ-C_1SJcWo.js} +3 -3
- package/dist/{chunk-S6J4BHB3-DNVMr0_v.js → chunk-S6J4BHB3-zfWjyfUg.js} +1 -1
- package/dist/{chunk-T53DSG4Q-BFWkpOX5.js → chunk-T53DSG4Q-Bewz1tiU.js} +1 -1
- package/dist/{chunk-TZMSLE5B-DFDr5FCr.js → chunk-TZMSLE5B-XW3duOft.js} +1 -1
- package/dist/{classDiagram-2ON5EDUG-BDBX9etk.js → classDiagram-2ON5EDUG-CUJlS_eo.js} +10 -10
- package/dist/{classDiagram-v2-WZHVMYZB-Bzj_L_BF.js → classDiagram-v2-WZHVMYZB-BhSPpbkE.js} +10 -10
- package/dist/{clone-Cc_6PW77.js → clone-V9hndNcj.js} +1 -1
- package/dist/{constants-DrOu5vvd.js → constants-BGRTDzdW.js} +2 -2
- package/dist/{copy-DRaXIb_a.js → copy-oc-FcZzt.js} +2 -2
- package/dist/{dagre-6UL2VRFP-r2rSdJYL.js → dagre-6UL2VRFP-BArPH353.js} +11 -11
- package/dist/{dagre-D2F8UdM6.js → dagre-Dcgyn_Uy.js} +15 -15
- package/dist/{diagram-PSM6KHXK-BpxVUe9U.js → diagram-PSM6KHXK-B1xAkr9y.js} +16 -16
- package/dist/{diagram-QEK2KX5R-q3dHUcp6.js → diagram-QEK2KX5R-CaoqwzPb.js} +14 -14
- package/dist/{diagram-S2PKOQOG-MDBKrxSC.js → diagram-S2PKOQOG-NXCsFLvR.js} +14 -14
- package/dist/dist-B8Y11RWn.js +1381 -0
- package/dist/dist-BA-HK7pI.js +5 -0
- package/dist/dist-BD5GU948.js +5 -0
- package/dist/{dist-BfactX3G.js → dist-BGzkWRSl.js} +4 -4
- package/dist/dist-BIYmAsND.js +5 -0
- package/dist/{dist-CmZYrgd_.js → dist-BUEi7EKT.js} +1 -1
- package/dist/{dist-B94MxrQS.js → dist-B_i29Q6L.js} +2 -2
- package/dist/dist-BcKTJXJi.js +5 -0
- package/dist/dist-BgnrtcWg.js +8 -0
- package/dist/{dist-glA_fIK_.js → dist-BoagoQQw.js} +2 -2
- package/dist/{dist-C2-m5aEk.js → dist-BswsDM4k.js} +2 -2
- package/dist/dist-C1njTlBq.js +5 -0
- package/dist/{dist-B2-r9y-0.js → dist-C5QB1NtD.js} +3 -3
- package/dist/{dist-Crk9ejOy.js → dist-CD7uLx0M.js} +2 -2
- package/dist/{dist-B4tYJP_i.js → dist-CMOy93xY.js} +2 -2
- package/dist/dist-CSKHwJYH.js +5 -0
- package/dist/dist-CSKKyiIq.js +5 -0
- package/dist/{dist-iiugPhCC.js → dist-C_9IMrtt.js} +1 -1
- package/dist/{dist-CE43BRmt.js → dist-Cb3iqED3.js} +1 -1
- package/dist/{dist-Dit9tk8a.js → dist-CoZ8kKKW.js} +1 -1
- package/dist/{dist-B5ATpkxy.js → dist-CrAYcS_4.js} +2 -2
- package/dist/dist-CrQ_pOuK.js +6 -0
- package/dist/dist-Cskx1daf.js +5 -0
- package/dist/dist-D4i0Ef34.js +8 -0
- package/dist/{dist-T4g7Sr6e.js → dist-D8EhXZ4S.js} +3 -3
- package/dist/{dist-CJrHMxlI.js → dist-DOLQQtWK.js} +3 -3
- package/dist/dist-DOcn61TX.js +8 -0
- package/dist/{dist-DqJdzAYM.js → dist-Dmr_nXF6.js} +2 -2
- package/dist/{dist-yVJ4xE5n.js → dist-DpAbrLuF.js} +5 -5
- package/dist/{dist-CcOGT46m.js → dist-DrC0QKFK.js} +1 -1
- package/dist/{dist-BYmtF1W6.js → dist-Dv2Phbh5.js} +2 -2
- package/dist/dist-DwMejAPB.js +6 -0
- package/dist/dist-DzSe1wby.js +8 -0
- package/dist/{dist-BbBnU4tG.js → dist-EZFqUJhh.js} +1 -1
- package/dist/{dist-Cgf353Ki.js → dist-Ey9hP8-j.js} +1 -1
- package/dist/{dist-BLwfpZD-.js → dist-IlWGXVjO.js} +2 -2
- package/dist/{dist-DOil6y-3.js → dist-LNp8svLl.js} +4 -4
- package/dist/{dist-CPTE45iS.js → dist-W6TdeACj.js} +1 -1
- package/dist/{dist-Dc1SFk5I.js → dist-a6Obzr07.js} +2 -2
- package/dist/{dist-Bsv_ARko.js → dist-bz6WguLy.js} +2 -2
- package/dist/{dist-CC9VUnXd.js → dist-iDeoXzdN.js} +1 -1
- package/dist/{dist-BoAHOW2l.js → dist-iyBCcLRa.js} +2 -2
- package/dist/{dist-CkEUrAus.js → dist-xCB683Dh.js} +2 -2
- package/dist/{erDiagram-Q2GNP2WA-CX1XdqVD.js → erDiagram-Q2GNP2WA-DWCa11g5.js} +10 -10
- package/dist/error-banner-vCG-EbUQ.js +619 -0
- package/dist/{esm-BAS2d2Ad.js → esm-DZSk8vt3.js} +27 -27
- package/dist/{flatten-eGRGXrC3.js → flatten-CWZjF1fc.js} +1 -1
- package/dist/{flowDiagram-NV44I4VS-BCj-ONTw.js → flowDiagram-NV44I4VS-BQ5PQs4L.js} +10 -10
- package/dist/{ganttDiagram-JELNMOA3-D1l5ewiQ.js → ganttDiagram-JELNMOA3-NTOuNWeT.js} +3 -3
- package/dist/{gitGraph-F6HP7TQM-CDM3aU-T.js → gitGraph-F6HP7TQM-DfRNsaDw.js} +3 -3
- package/dist/{gitGraphDiagram-NY62KEGX-KdZh0iiW.js → gitGraphDiagram-NY62KEGX-CYke62Ot.js} +13 -13
- package/dist/{glide-data-editor-2RvcPqmc.js → glide-data-editor-DttqGjrT.js} +571 -572
- package/dist/{graphlib-7UgfJadv.js → graphlib-CwMnCnQ9.js} +8 -8
- package/dist/{info-NVLQJR56-CoL1x1Fy.js → info-NVLQJR56-CUaoPtis.js} +3 -3
- package/dist/{infoDiagram-WHAUD3N6-PSH7lQ0D.js → infoDiagram-WHAUD3N6-B42WjAPh.js} +13 -13
- package/dist/{isEmpty-DQXRKNtW.js → isEmpty-6z2uv6gM.js} +2 -2
- package/dist/{isString-Clqvtgmo.js → isString-D6abkXrl.js} +1 -1
- package/dist/{isSymbol-TWXhTa8k.js → isSymbol-hk7foJ70.js} +1 -1
- package/dist/{journeyDiagram-XKPGCS4Q-BrTAxQ1J.js → journeyDiagram-XKPGCS4Q-ahXD97kr.js} +3 -3
- package/dist/{kanban-definition-3W4ZIXB7-BoYCDp_9.js → kanban-definition-3W4ZIXB7-CiTIpnhy.js} +7 -7
- package/dist/{label-CxU5JNBW.js → label-Cc5tEavt.js} +250 -250
- package/dist/{loader-C0-eIoas.js → loader-Cob3XFOw.js} +2 -2
- package/dist/main.js +1791 -1056
- package/dist/{memoize-Bag7B41I.js → memoize-Ckyqzyu_.js} +1 -1
- package/dist/{merge-Dl1bfxsj.js → merge-Db4Uulx4.js} +1 -1
- package/dist/{mermaid-C2cSe5YL.js → mermaid-B5xl_2hx.js} +73 -62
- package/dist/{mermaid-parser.core-D20zFbMa.js → mermaid-parser.core-BXj7Il0J.js} +8 -8
- package/dist/{min-Bg4bqmiD.js → min-ypdVXicC.js} +4 -4
- package/dist/{mindmap-definition-VGOIOE7T-CmRjsKEt.js → mindmap-definition-VGOIOE7T-Mni766A_.js} +9 -9
- package/dist/{now-mivqkCIv.js → now-Dwu5ou19.js} +2 -2
- package/dist/{once-BqS42WgZ.js → once-C9dA9qgQ.js} +1 -1
- package/dist/{packet-BFZMPI3H-C6aZmgV-.js → packet-BFZMPI3H-DHtQCusE.js} +3 -3
- package/dist/{pie-7BOR55EZ-NB6xYwcB.js → pie-7BOR55EZ-2sVLYbpR.js} +3 -3
- package/dist/{pieDiagram-ADFJNKIX-CtxQlnsU.js → pieDiagram-ADFJNKIX-PbXpgT8_.js} +14 -14
- package/dist/{quadrantDiagram-AYHSOK5B-DllnB2Hl.js → quadrantDiagram-AYHSOK5B-BtXGnx8i.js} +2 -2
- package/dist/{radar-NHE76QYJ-RKhErikV.js → radar-NHE76QYJ-Be0pEUux.js} +3 -3
- package/dist/{range-LoQMRQIX.js → range-D9jxVFd_.js} +5 -5
- package/dist/{reduce-B9mZDxPo.js → reduce-C6NEPj6s.js} +4 -4
- package/dist/{requirementDiagram-UZGBJVZJ-D36MI1k0.js → requirementDiagram-UZGBJVZJ-DxzXQRgq.js} +9 -9
- package/dist/{sankeyDiagram-TZEHDZUN-D1mygNPC.js → sankeyDiagram-TZEHDZUN-D-I7dJ0_.js} +2 -2
- package/dist/{sequenceDiagram-WL72ISMW-CWdn91Rf.js → sequenceDiagram-WL72ISMW-VDme2ljw.js} +4 -4
- package/dist/{slides-component-DfwLApNr.js → slides-component-ql7-5GDI.js} +2 -2
- package/dist/{spec-HoYHAQo2.js → spec-GwhMEXwK.js} +8 -9
- package/dist/{stateDiagram-FKZM4ZOC-CPxroWXd.js → stateDiagram-FKZM4ZOC-g3GI1EcK.js} +12 -12
- package/dist/{stateDiagram-v2-4FDKWEC3-BpM9Q54b.js → stateDiagram-v2-4FDKWEC3-7i6jBXe6.js} +10 -10
- package/dist/stex-D2rme5UG.js +4 -0
- package/dist/style.css +1 -1
- package/dist/{timeline-definition-IT6M3QCI-CVnRHx_t.js → timeline-definition-IT6M3QCI-bhvLlX_b.js} +2 -2
- package/dist/{toString-C4TLO6FA.js → toString-BwTJvlyD.js} +2 -2
- package/dist/tooltip-CL8m4f9y.js +404 -0
- package/dist/{treemap-KMMF4GRG-B37ugcLd.js → treemap-KMMF4GRG-Ba9ifjpG.js} +3 -3
- package/dist/{types-Ckva8JJq.js → types-Dsh6yC4B.js} +412 -413
- package/dist/{useAsyncData-dr8GazGv.js → useAsyncData-BPpyKjTJ.js} +2 -2
- package/dist/{useDeepCompareMemoize-ChviuF5n.js → useDeepCompareMemoize-C8Ms87P-.js} +18 -19
- package/dist/{useIframeCapabilities-DurI5SJh.js → useIframeCapabilities-C7z8VrZ1.js} +2 -2
- package/dist/{useTheme-SlKl8MlS.js → useTheme-Cq-gIssy.js} +299 -300
- package/dist/{vega-component-CnG0vAjf.js → vega-component-B5sxdjMq.js} +10 -10
- package/dist/{xychartDiagram-PRI3JC2R-BltwMWKC.js → xychartDiagram-PRI3JC2R-CFxuifYY.js} +5 -5
- package/package.json +1 -1
- package/src/components/editor/Output.tsx +8 -6
- package/src/components/editor/__tests__/Output.test.tsx +59 -0
- package/src/components/editor/chrome/__tests__/state.test.ts +321 -0
- package/src/components/editor/chrome/state.ts +27 -2
- package/src/components/editor/file-tree/upload.tsx +46 -23
- package/src/components/editor/links/cell-link.tsx +3 -2
- package/src/components/editor/output/console/ConsoleOutput.tsx +13 -3
- package/src/components/pages/gallery-page.tsx +1 -1
- package/src/components/pages/home-page.tsx +5 -3
- package/src/components/tracing/tracing.tsx +50 -39
- package/src/core/documentation/DocHoverTarget.tsx +23 -0
- package/src/core/documentation/doc-lookup.ts +50 -0
- package/src/core/islands/main.ts +1 -0
- package/src/core/websocket/useMarimoKernelConnection.tsx +3 -0
- package/src/css/app/Cell.css +5 -0
- package/src/mount.tsx +2 -2
- package/src/plugins/core/RenderHTML.tsx +15 -0
- package/src/plugins/core/__test__/registerReactComponent.test.ts +204 -0
- package/src/plugins/core/registerReactComponent.tsx +33 -0
- package/src/plugins/impl/MatrixPlugin.tsx +275 -0
- package/src/plugins/impl/__tests__/MatrixPlugin.test.tsx +415 -0
- package/src/plugins/impl/anywidget/model.ts +1 -2
- package/src/plugins/impl/matplotlib/MatplotlibPlugin.tsx +70 -0
- package/src/plugins/impl/matplotlib/__tests__/matplotlib-renderer.test.ts +152 -0
- package/src/plugins/impl/matplotlib/matplotlib-renderer.ts +781 -0
- package/src/plugins/impl/matrix.css +45 -0
- package/src/plugins/layout/mermaid/mermaid.tsx +11 -3
- package/src/plugins/plugins.ts +4 -0
- package/src/utils/__tests__/download.test.tsx +47 -0
- package/src/utils/download.ts +13 -1
- package/src/utils/links.ts +1 -1
- package/src/utils/urls.ts +1 -1
- package/dist/Combination-BTMrlhzT.js +0 -2611
- package/dist/architecture-U656AL7Q-COfwZju8.js +0 -6
- package/dist/dist-4YNZxwMI.js +0 -8
- package/dist/dist-7nR3r2kG.js +0 -5
- package/dist/dist-B2gkyT3r.js +0 -5
- package/dist/dist-B8G3I6vJ.js +0 -8
- package/dist/dist-BJ96Ykfp.js +0 -8
- package/dist/dist-BKLIWGw4.js +0 -5
- package/dist/dist-Bf3ou00A.js +0 -6
- package/dist/dist-BvkKXuPm.js +0 -5
- package/dist/dist-C6NJ3n6r.js +0 -5
- package/dist/dist-CecLPYY5.js +0 -5
- package/dist/dist-Ch0SwRzK.js +0 -5
- package/dist/dist-D6eWHiFh.js +0 -6
- package/dist/dist-DCQ710Bv.js +0 -5
- package/dist/dist-P_pkS5f-.js +0 -8
- package/dist/error-banner-D2zjeN_a.js +0 -1015
- package/dist/hotkeys-B5WnGZXF.js +0 -587
- package/dist/stex-ChDHQs3R.js +0 -4
- package/dist/zod-bjADtMKr.js +0 -10663
- /package/dist/{_arrayReduce-DlK7U3Q6.js → _arrayReduce-REKcIEj3.js} +0 -0
- /package/dist/{_baseFor-DSVmVciX.js → _baseFor-B69PDbIz.js} +0 -0
- /package/dist/{_hasUnicode-Bz2x6u6r.js → _hasUnicode-DrSAc5A5.js} +0 -0
- /package/dist/{dist-r8ecBV-v.js → dist-CUOuFgHt.js} +0 -0
- /package/dist/{invariant-D9QLJ4SZ.js → invariant-D-K49MfV.js} +0 -0
- /package/dist/{main-DhFbkwoC.js → main-DmxVpB19.js} +0 -0
- /package/dist/{purify.es-Brw-U87Q.js → purify.es-D4vaFt5N.js} +0 -0
- /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 "./
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
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 {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { a as tooltipHandler, n as vegaLoadData } from "./loader-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
12
|
-
import { t as selectSvgElement } from "./chunk-EXTU4WIE-
|
|
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-
|
|
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
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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");
|