@marimo-team/islands 0.23.15-dev37 → 0.23.15-dev39

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.
@@ -6,13 +6,13 @@ import { _ as Logger, c as Objects, g as cn, l as useEventListener, t as Button
6
6
  import { t as require_react } from "./react-DA-nE2FX.js";
7
7
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
8
8
  import { r as toast } from "./copy-COam1EG7.js";
9
- import { C as Accordion, Dn as atomWithStorage, Dt as createVariableInfoElement, E as AccordionTrigger, F as base64ToDataURL, Fn as Wrench, H as renderHTML, In as Trash2, Jt as allTablesAtom, Kn as ExternalLink, Lt as jotaiJsonStorage, O as ChatBubbleIcon, Pt as generateUUID, Q as notebookAtom, Qt as getRequestClient, Rt as variablesAtom, S as AIContextRegistry, T as AccordionItem, Un as Info, Ut as PluralWord, Vn as LoaderCircle, Wn as FileText, Xt as getTableType, Yn as CircleX, Yt as dataSourceConnectionsAtom, _n as CellOutputId, an as isMarimoErrorsMime, b as contextToXml, bt as displayCellName, c as Popover, d as PopoverTrigger, f as isOutputEmpty, fn as ZodLocalStorage, g as formatDatasourceContextForCell, h as DatasourceContextProvider, in as isErrorMime, jt as moveToEndOfEditor, kn as Anchor2, n as Spinner, on as isTracebackMime, r as MarkdownRenderer, sn as singleFacet, st as parseHtmlContent, t as toPng, u as PopoverContent, v as Boosts, w as AccordionContent, x as AIContextProvider, y as Sections } from "./html-to-image-F0RpWXNK.js";
9
+ import { C as Accordion, Dn as atomWithStorage, Dt as createVariableInfoElement, E as AccordionTrigger, F as base64ToDataURL, Fn as Wrench, H as renderHTML, In as Trash2, Jt as allTablesAtom, Kn as ExternalLink, Lt as jotaiJsonStorage, O as ChatBubbleIcon, Pt as generateUUID, Q as notebookAtom, Qt as getRequestClient, Rt as variablesAtom, S as AIContextRegistry, T as AccordionItem, Un as Info, Ut as PluralWord, Vn as LoaderCircle, Wn as FileText, Xt as getTableType, Yn as CircleX, Yt as dataSourceConnectionsAtom, _n as CellOutputId, an as isMarimoErrorsMime, b as contextToXml, bt as displayCellName, c as Popover, d as PopoverTrigger, f as isOutputEmpty, fn as ZodLocalStorage, g as formatDatasourceContextForCell, h as DatasourceContextProvider, in as isErrorMime, jt as moveToEndOfEditor, kn as Anchor2, n as Spinner, on as isTracebackMime, r as MarkdownRenderer, sn as singleFacet, st as parseHtmlContent, t as toPng, u as PopoverContent, v as Boosts, w as AccordionContent, x as AIContextProvider, y as Sections } from "./html-to-image-CEo5pRYw.js";
10
10
  import "./chunk-5FQGJX7Z-BbqSm5gU.js";
11
11
  import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
12
12
  import { C as logNever, I as X, R as ChevronDown, t as Strings } from "./strings-Dq_j3Rxw.js";
13
13
  import { C as DropdownMenuTrigger, a as NumberField, f as DropdownMenu, h as DropdownMenuItem, p as DropdownMenuContent, r as Input } from "./input-BGPrFH3g.js";
14
- import { p as isUrl, v as CircleQuestionMark } from "./toDate-CKpRx4TS.js";
15
- import { a as MarimoIncomingMessageEvent, d as Square, f as File$1, n as blobToString, t as processOutput, u as deserializeBlob } from "./process-output-C2tUYuG7.js";
14
+ import { p as isUrl, v as CircleQuestionMark } from "./toDate-BRJgtOGm.js";
15
+ import { a as MarimoIncomingMessageEvent, d as Square, f as File$1, n as blobToString, t as processOutput, u as deserializeBlob } from "./process-output-BOvvilRG.js";
16
16
  import "./react-dom-BTJzcVJ9.js";
17
17
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
18
18
  import { A as looseObject, B as union, C as any, D as discriminatedUnion, E as custom, H as safeParseAsync, I as record, L as strictObject, M as never, N as number, O as lazy, P as object$1, R as string, S as _null, T as boolean, V as unknown, W as toJSONSchema, b as _enum, k as literal, w as array$1, x as _instanceof } from "./zod-CijjQh4u.js";
@@ -6,14 +6,14 @@ import { _ as Logger, c as Objects, g as cn, h as Events, m as useComposedRefs,
6
6
  import { t as require_react } from "./react-DA-nE2FX.js";
7
7
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
8
8
  import { n as Copy, r as toast, t as copyToClipboard } from "./copy-COam1EG7.js";
9
- import { $n as import_lib, An as Close$1, At as toggleBreakpoint, B as isDataURLString, Bn as Minus, C as Accordion, Dn as atomWithStorage, E as AccordionTrigger, Fn as Wrench, Ft as useChromeActions, Gn as Eye, Gt as DATA_TYPE_ICON, H as renderHTML, In as Trash2, It as adaptForLocalStorage, J as getCellEditorView, Kn as ExternalLink, Kt as getDataTypeColor, L as base64ToUint8Array, Lt as jotaiJsonStorage, M as DotFilledIcon, Mt as goToCellLine, N as PinLeftIcon, P as PinRightIcon, Q as notebookAtom, Qn as esm_default, Qt as getRequestClient, T as AccordionItem, Tn as jsonToMarkdown, Un as Info, Ut as PluralWord, Vn as LoaderCircle, Wn as FileText, Yn as CircleX, Zn as Braces, _ as getDatasourceContext, _n as CellOutputId, _t as sanitizeHtml, bt as displayCellName, c as Popover, cn as elementContainsMarimoCellFile, ct as AnsiUp, d as PopoverTrigger, dt as kioskModeAtom, en as useRequestClient, ft as useInstallAllowed, it as useCellNames, j as ChevronRightIcon, k as CheckIcon, l as PopoverClose, ln as extractAllTracebackInfo, m as useExpandedOutput, mt as outputIsLoading, n as Spinner, nt as useCellActions, pn as filenameAtom, pt as viewStateAtom, r as MarkdownRenderer, rt as useCellIds, t as toPng, u as PopoverContent, un as getTracebackInfo, vn as HTMLCellId, vt as DATA_CELL_ID, w as AccordionContent, wn as jsonParseWithSpecialChar, wt as Checkbox, yn as SCRATCH_CELL_ID, yt as getCellDomProps, z as extractBase64FromDataURL, zn as NotebookPen, zt as getFeatureFlag, __tla as __tla_0 } from "./html-to-image-F0RpWXNK.js";
9
+ import { $n as import_lib, An as Close$1, At as toggleBreakpoint, B as isDataURLString, Bn as Minus, C as Accordion, Dn as atomWithStorage, E as AccordionTrigger, Fn as Wrench, Ft as useChromeActions, Gn as Eye, Gt as DATA_TYPE_ICON, H as renderHTML, In as Trash2, It as adaptForLocalStorage, J as getCellEditorView, Kn as ExternalLink, Kt as getDataTypeColor, L as base64ToUint8Array, Lt as jotaiJsonStorage, M as DotFilledIcon, Mt as goToCellLine, N as PinLeftIcon, P as PinRightIcon, Q as notebookAtom, Qn as esm_default, Qt as getRequestClient, T as AccordionItem, Tn as jsonToMarkdown, Un as Info, Ut as PluralWord, Vn as LoaderCircle, Wn as FileText, Yn as CircleX, Zn as Braces, _ as getDatasourceContext, _n as CellOutputId, _t as sanitizeHtml, bt as displayCellName, c as Popover, cn as elementContainsMarimoCellFile, ct as AnsiUp, d as PopoverTrigger, dt as kioskModeAtom, en as useRequestClient, ft as useInstallAllowed, it as useCellNames, j as ChevronRightIcon, k as CheckIcon, l as PopoverClose, ln as extractAllTracebackInfo, m as useExpandedOutput, mt as outputIsLoading, n as Spinner, nt as useCellActions, pn as filenameAtom, pt as viewStateAtom, r as MarkdownRenderer, rt as useCellIds, t as toPng, u as PopoverContent, un as getTracebackInfo, vn as HTMLCellId, vt as DATA_CELL_ID, w as AccordionContent, wn as jsonParseWithSpecialChar, wt as Checkbox, yn as SCRATCH_CELL_ID, yt as getCellDomProps, z as extractBase64FromDataURL, zn as NotebookPen, zt as getFeatureFlag, __tla as __tla_0 } from "./html-to-image-CEo5pRYw.js";
10
10
  import { o as useSize, u as createLucideIcon } from "./dist--2Bqjvs0.js";
11
11
  import { c as Calendar, i as createReducerAndAtoms, r as Badge } from "./useLifecycle-C6wHjkhW.js";
12
12
  import { a as ListFilter, i as Table$1, n as $fb18d541ea1ad717$export$ad991b66133851cf, o as ChartPie, r as $5a387cc49350e6db$export$722debc0e56fea39, t as $896ba0a80a8f4d36$export$85fd5fdf27bacc79 } from "./useDateFormatter-CMnRuVmN.js";
13
13
  import { t as Check } from "./check-C9OoNtR4.js";
14
14
  import { C as logNever, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, I as X, N as usePrevious$1, O as $b5e257d569688ac6$export$535bd6ca7f90a273, P as useDirection, R as ChevronDown, S as assertNever, T as $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5, _ as menuControlVariants, b as menuSeparatorVariants, f as selectStyles, g as menuControlCheckVariants, h as menuContentCommon, i as SelectContent, l as SelectTrigger, o as SelectItem, p as MENU_ITEM_DISABLED, r as Select, t as Strings, u as SelectValue, v as menuItemVariants, w as $a916eb452884faea$export$b7a616150fdb9f44, x as menuSubTriggerVariants, y as menuLabelVariants } from "./strings-Dq_j3Rxw.js";
15
15
  import { $ as $e93e671b31057976$export$b8473d3665f3a75a, $t as Item2$2, A as $ee014567cb39d3f0$export$ff05c3ac10437e03, At as $c87311424ea30a05$export$78551043582a6a98, B as $64fa3d84918910a7$export$4d86445c2cf5e3, Bt as $d4ee10de306f2510$export$e58f029f0fbfdb29, C as DropdownMenuTrigger, Ct as $b4b717babfbb907b$export$bebd5a1431fec25d, D as $a049562f99e7db0e$export$f9c6924e160136d1, Dt as $df56164dff5785e2$export$4338b53315abf666, E as $a049562f99e7db0e$export$eb2fcfdbd7ba97d4, Et as $8ae05eaa5c114e9c$export$7f54fc3180508a52, F as $01b77f81d0f07f68$export$75b6ee27786ba447, Ft as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, G as $64fa3d84918910a7$export$ef03459518577ad4, Gt as $bdb11010cef70236$export$b4cc09c592e8fdb8, H as $64fa3d84918910a7$export$c245e6201fed2f75, Ht as $431fbd86ca7dc216$export$b204af158042fbac, I as $01b77f81d0f07f68$export$b04be29aa201d4f5, It as $3ef42575df84b30b$export$9d1611c77c2fe928, J as marked, Jt as Anchor2, K as $64fa3d84918910a7$export$fabf2dc03a41866e, Kt as $bdb11010cef70236$export$f680877a34711e37, L as $f39a9eba43920ace$export$b5d7cc18bb8d2b59, Lt as $d4ee10de306f2510$export$4282f70798064fe0, M as $514c0188e459b4c0$export$9afb8bc826b033ea, Mt as $c87311424ea30a05$export$a11b0059900ceec8, N as $d2b4bc8c273e7be6$export$24d547caef80ccd1, Nt as $c87311424ea30a05$export$fedb369cb70207f1, O as $d3e0e05bdfcf66bd$export$c24727297075ec6a, Ot as $313b98861ee5dd6c$export$d6875122194c7b44, P as $d2b4bc8c273e7be6$export$353f5b6fc5456de1, Pt as $7215afc6de606d6b$export$de79e2c695e052f3, Q as $2baaea4c71418dea$export$294aa081a6c6f55d, Qt as Group, R as $64fa3d84918910a7$export$2881499e37b75b9a, Rt as $d4ee10de306f2510$export$b4f377a2b6254582, S as DropdownMenuSubTrigger, St as $b4b717babfbb907b$export$4c063cf1350e6fed, T as $3985021b0ad6602f$export$f5b8910cec6cf069, Tt as $e9faafb641e167db$export$90fc3a17d93f704c, U as $64fa3d84918910a7$export$c62b8e45d58ddad9, Ut as $431fbd86ca7dc216$export$f21a1ffae260145a, V as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, Vt as $f4e2df6bd15f8569$export$98658e8c59125e6a, W as $64fa3d84918910a7$export$df3a06d6289f983e, Wt as $ff5963eb1fccf552$export$e08e3b67e392101e, Xt as CheckboxItem, Yt as Arrow2, Z as $d2e8511e6f209edf$export$e908e06f4b8e3402, Zt as Content2$1, _ as DropdownMenuPortal, _t as $f6c31cce2adf654f$export$45712eceda6fad21, a as NumberField, an as Root3, at as $319e236875307eab$export$a9b970dcc4ae71a9, b as DropdownMenuSub, bt as $9446cca9a3875146$export$7d15b64cf5a3a4c4, c as prettyEngineeringNumber, cn as SubContent, ct as $6c7bd7858deea686$export$cd11ab140839f11d, dn as Item, dt as $6db58dc88e78b024$export$2f817fcdc4b89ae0, en as ItemIndicator, et as $e5be200c675c3b3a$export$75ee7c75d68f5b0e, f as DropdownMenu, fn as Root$3, ft as $5b160d28a433310d$export$c17fa47878dc55b6, g as DropdownMenuLabel, gn as ChevronRight, gt as $507fabe10e71c6fb$export$630ff653c5ada6a9, h as DropdownMenuItem, hn as Circle, ht as $3ad3f6e1647bc98d$export$80f3e147d781571c, in as RadioItem, it as $e5be200c675c3b3a$export$fc1a364ae1f3ff10, j as $514c0188e459b4c0$export$5f1af8db9871e1d6, jt as $c87311424ea30a05$export$9ac100e40613ea10, k as $ee014567cb39d3f0$export$f551688fc98f2e09, kt as $c87311424ea30a05$export$6446a186d09e379e, l as prettyNumber, ln as SubTrigger, lt as $fca6afa0e843324b$export$87b761675e8eaa10, mn as Search, mt as $9ab94262bd0047c7$export$420e68273165f4ec, nn as Portal, nt as $e5be200c675c3b3a$export$aca958c65c314e6c, on as Separator$1, ot as $f7dceffc5ad7768b$export$4e328f61c538687f, p as DropdownMenuContent, pn as createRovingFocusGroupScope, pt as $6179b936705e76d3$export$ae780daf29e6d456, qt as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c, r as Input, rn as RadioGroup$2, rt as $e5be200c675c3b3a$export$dad6ae84456c676a, s as maxFractionalDigits, sn as Sub, tn as Label$1, tt as $e5be200c675c3b3a$export$a763b9476acd3eb, u as prettyScientificNumber, un as createMenuScope, ut as $fca6afa0e843324b$export$f12b703ca79dfbb1, v as DropdownMenuSeparator, vt as _class_private_field_init, w as $3985021b0ad6602f$export$37fb8590cf2c088c, wt as $99facab73266f662$export$5add1d006293d136, x as DropdownMenuSubContent, xt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, yt as $ae1eeba8b9eafd08$export$5165eccb35aaadb5, z as $64fa3d84918910a7$export$29f1550f4b0d4415, zt as $d4ee10de306f2510$export$cd4e5573fbe2b576 } from "./input-BGPrFH3g.js";
16
- import { _ as isWasm, a as millisecondsInMinute, c as asRemoteURL, d as isStaticNotebook, i as millisecondsInHour, n as constructFrom, o as millisecondsInSecond, p as isUrl, r as millisecondsInDay, s as millisecondsInWeek, t as toDate } from "./toDate-CKpRx4TS.js";
16
+ import { _ as isWasm, a as millisecondsInMinute, c as asRemoteURL, d as isStaticNotebook, i as millisecondsInHour, n as constructFrom, o as millisecondsInSecond, p as isUrl, r as millisecondsInDay, s as millisecondsInWeek, t as toDate } from "./toDate-BRJgtOGm.js";
17
17
  import { r as Plus, t as ErrorBoundary } from "./ErrorBoundary-B_CAG7_e.js";
18
18
  import { n as clsx_default } from "./clsx-CIWA5tNO.js";
19
19
  import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
@@ -28,7 +28,7 @@ import { t as invariant } from "./invariant-wRzNXIsJ.js";
28
28
  import { c as uniqueBy, t as Arrays } from "./arrays-sEtDRoG4.js";
29
29
  import { n as once, t as memoizeLastValue } from "./once-DPuqGUeo.js";
30
30
  import { a as parser } from "./dist-C_Y3oV3C.js";
31
- import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-BX3uDQbB.js";
31
+ import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-CitsMtUm.js";
32
32
  import { n as memoize$1, t as isPropValid } from "./emotion-is-prop-valid.esm-DzSb5hsH.js";
33
33
  import { n as formats } from "./vega-loader.browser-CZ-J8Py3.js";
34
34
  import { a as getContainerWidth, n as vegaLoadData, r as createBatchedLoader, s as tooltipHandler, t as parseCsvData } from "./loader-Boph2xIS.js";
@@ -36290,7 +36290,7 @@ ${d}`,
36290
36290
  return Logger.warn("Failed to get version from mount config"), null;
36291
36291
  }
36292
36292
  }
36293
- marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.15-dev37");
36293
+ marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.15-dev39");
36294
36294
  showCodeInRunModeAtom = atom(true);
36295
36295
  atom(null);
36296
36296
  var import_compiler_runtime = require_compiler_runtime();
@@ -2,7 +2,7 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { g as cn, r as cva } from "./button-BacYv-bE.js";
3
3
  import { t as require_react } from "./react-DA-nE2FX.js";
4
4
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
5
- import { t as toDate } from "./toDate-CKpRx4TS.js";
5
+ import { t as toDate } from "./toDate-BRJgtOGm.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
7
7
  import { i as tableFromIPC } from "./loader-Boph2xIS.js";
8
8
  function isDate(e) {
@@ -12,7 +12,7 @@ import { a as Type, c as Calendar, i as createReducerAndAtoms, o as ToggleLeft,
12
12
  import { t as Check } from "./check-C9OoNtR4.js";
13
13
  import { C as logNever, F as createCollection, I as X, N as usePrevious, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, i as SelectContent, l as SelectTrigger, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue } from "./strings-Dq_j3Rxw.js";
14
14
  import { J as marked, X as useDebouncedCallback, _t as $f6c31cce2adf654f$export$45712eceda6fad21, q as useNonce } from "./input-BGPrFH3g.js";
15
- import { _ as isWasm, g as Deferred, h as waitForConnectionOpen, l as getRuntimeManager, t as toDate, v as CircleQuestionMark } from "./toDate-CKpRx4TS.js";
15
+ import { _ as isWasm, g as Deferred, h as waitForConnectionOpen, l as getRuntimeManager, t as toDate, v as CircleQuestionMark } from "./toDate-BRJgtOGm.js";
16
16
  import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
17
17
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
18
18
  import { B as union, N as number, P as object, Q as withSmartCollisionBoundary, R as string, T as boolean, Y as MAX_HEIGHT_OFFSET, Z as withFullScreenAsRoot, _t as createContextScope, at as Portal, ct as DismissableLayer, dt as useId, et as StyleNamespace, ft as Presence, ht as composeEventHandlers, it as useFocusGuards, k as literal, lt as Root$1, mt as useLayoutEffect2, nt as Combination_default, ot as FocusScope, pt as useControllableState, st as Branch, tt as hideOthers, ut as useCallbackRef, vt as Primitive, w as array, yt as dispatchDiscreteCustomEvent } from "./zod-CijjQh4u.js";
package/dist/main.js CHANGED
@@ -22,17 +22,17 @@ import { _ as Logger, c as Objects, g as cn, h as Events, i as NOT_SET, l as use
22
22
  import { t as require_react } from "./react-DA-nE2FX.js";
23
23
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
24
24
  import { n as Copy, r as toast, t as copyToClipboard } from "./copy-COam1EG7.js";
25
- import { $ as notebookOutline, $t as requestClientAtom, A as ChevronDownIcon, Bt as repl, C as Accordion, Cn as RANDOM_ID_ATTR, Ct as normalizeName, D as BorderAllIcon, Dn as atomWithStorage, E as AccordionTrigger, En as atomWithReducer, Et as MarkdownLanguageAdapter, G as hasRunAnyCellAtom, Gn as Eye, Gt as DATA_TYPE_ICON, H as renderHTML, Hn as Layers, Ht as MarkdownParser, I as base64ToDataView, In as Trash2, Jn as Columns2, K as cellIdsAtom, Ln as Table2, Lt as jotaiJsonStorage, Mn as Item$1, Nn as Root2$1, Nt as DeferredRequestRegistry, On as selectAtom, Ot as PathBuilder, Pn as Trigger2, Pt as generateUUID, Q as notebookAtom, Qt as getRequestClient, R as dataViewToBase64, Rn as PaintRoller, Sn as OBJECT_ID_ATTR, St as isInternalCellName, T as AccordionItem, Tt as customPythonLanguageSupport, U as getMarimoExportContext, Un as Info, V as safeExtractSetUIElementMessageBuffers, Vn as LoaderCircle, Vt as SQLParser, W as hasTrustedExportContext, Wn as FileText, Wt as PluralWords, X as hasOnlyOneCellAtom, Xn as CircleAlert, Y as getCellNames, Z as initialNotebookState, Zn as Braces, Zt as convertStatsName, a as useCellFocusActions, at as createCell, bn as UIElementId, dn as NotebookScopedLocalStorage, dt as kioskModeAtom, en as useRequestClient, et as numColumnsAtom, f as isOutputEmpty, gn as parseInitialValue, gt as headingToIdentifier, hn as parseDataset, ht as outputIsStale, i as LazyAnyLanguageCodeMirror, jn as Content2, kt as Paths, lt as getInitialAppMode, mn as parseAttrValue, mt as outputIsLoading, n as Spinner, nn as publishedCellClasses, nt as useCellActions, o as useLastFocusedCellId, p as useExpandedConsoleOutput, pt as viewStateAtom, q as createActions, qn as Database, qt as require_client, rn as shouldHidePublishedCell, rt as useCellIds, s as maybeAddAltairImport, tn as isUninstantiated, tt as reducer, ut as initialModeAtom, vn as HTMLCellId, w as AccordionContent, wn as jsonParseWithSpecialChar, wt as Checkbox, xn as findCellId, xt as getValidName, __tla as __tla_0 } from "./html-to-image-F0RpWXNK.js";
25
+ import { $ as notebookOutline, $t as requestClientAtom, A as ChevronDownIcon, Bt as repl, C as Accordion, Cn as RANDOM_ID_ATTR, Ct as normalizeName, D as BorderAllIcon, Dn as atomWithStorage, E as AccordionTrigger, En as atomWithReducer, Et as MarkdownLanguageAdapter, G as hasRunAnyCellAtom, Gn as Eye, Gt as DATA_TYPE_ICON, H as renderHTML, Hn as Layers, Ht as MarkdownParser, I as base64ToDataView, In as Trash2, Jn as Columns2, K as cellIdsAtom, Ln as Table2, Lt as jotaiJsonStorage, Mn as Item$1, Nn as Root2$1, Nt as DeferredRequestRegistry, On as selectAtom, Ot as PathBuilder, Pn as Trigger2, Pt as generateUUID, Q as notebookAtom, Qt as getRequestClient, R as dataViewToBase64, Rn as PaintRoller, Sn as OBJECT_ID_ATTR, St as isInternalCellName, T as AccordionItem, Tt as customPythonLanguageSupport, U as getMarimoExportContext, Un as Info, V as safeExtractSetUIElementMessageBuffers, Vn as LoaderCircle, Vt as SQLParser, W as hasTrustedExportContext, Wn as FileText, Wt as PluralWords, X as hasOnlyOneCellAtom, Xn as CircleAlert, Y as getCellNames, Z as initialNotebookState, Zn as Braces, Zt as convertStatsName, a as useCellFocusActions, at as createCell, bn as UIElementId, dn as NotebookScopedLocalStorage, dt as kioskModeAtom, en as useRequestClient, et as numColumnsAtom, f as isOutputEmpty, gn as parseInitialValue, gt as headingToIdentifier, hn as parseDataset, ht as outputIsStale, i as LazyAnyLanguageCodeMirror, jn as Content2, kt as Paths, lt as getInitialAppMode, mn as parseAttrValue, mt as outputIsLoading, n as Spinner, nn as publishedCellClasses, nt as useCellActions, o as useLastFocusedCellId, p as useExpandedConsoleOutput, pt as viewStateAtom, q as createActions, qn as Database, qt as require_client, rn as shouldHidePublishedCell, rt as useCellIds, s as maybeAddAltairImport, tn as isUninstantiated, tt as reducer, ut as initialModeAtom, vn as HTMLCellId, w as AccordionContent, wn as jsonParseWithSpecialChar, wt as Checkbox, xn as findCellId, xt as getValidName, __tla as __tla_0 } from "./html-to-image-CEo5pRYw.js";
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-BbqSm5gU.js";
27
27
  import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist--2Bqjvs0.js";
28
28
  import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS$1, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-DSs9v0xx.js";
29
- import { $ as ContextAwarePanelItem, $t as EmotionCacheProvider, A as prettifyRowColumnCount, At as loadTableData, B as useSelectList, Bt as dateToLocalISOTime, C as Filenames, Ct as ColumnChartContext, D as EmptyState, Dt as usePrevious$1, E as ColumnPreviewContainer, Et as useIntersectionObserver, F as ContextMenuContent, Ft as getMimeValues, G as ComboboxItem, Gt as ChartErrorState, H as DatePicker, Ht as TabsContent, I as ContextMenuItem, It as isNullishFilter, J as CommandInput, Jt as LazyVegaEmbed, K as Command, Kt as ChartInfoState, L as ContextMenuSeparator, Lt as Maps, M as getColumnCountForDisplay, Mt as SELECT_COLUMN_ID, N as getUserColumnVisibilityCounts, Nt as TOO_MANY_ROWS, O as ErrorState, Ot as getPageIndexForRow, P as ContextMenu, Pt as toFieldTypes, Q as smartMatch, Qt as HtmlOutput, R as ContextMenuTrigger, Rt as dateToLocalISODate, S as Progress, St as renderCellValue, T as ColumnName, Tt as DelayMount, U as DateRangePicker, Ut as TabsList, V as CompactChipRow, Vt as Tabs, W as Combobox, Wt as TabsTrigger, X as CommandList, Xt as RenderTextWithLinks, Y as CommandItem, Yt as useOverflowDetection, Z as CommandSeparator, Zt as Kbd, _ as InstallPackageButton, _n as ArrowDownWideNarrow, _t as TableHeader, an as GripHorizontal, at as SlotNames, b as downloadByURL, bt as generateColumns, d as RadioGroup, dn as Code, dt as Fill, en as hasFunctionProperty, et as PANEL_TYPES, f as RadioGroupItem, fn as ChevronsUpDown, ft as Provider$1, g as DataTable, gn as ChevronLeft, gt as TableHead, h as OutputRenderer, hn as ChevronsDownUp, ht as TableCell, in as TextWrap, it as isCellAwareAtom, j as prettifyRowCount, jt as INDEX_COLUMN_NAME, k as LoadingState, kt as loadTableAndRawData, l as Slide, ln as Ellipsis, m as OutputArea, mn as ChevronsLeft, mt as TableBody, n as marimoVersionAtom, nn as $fae977aafc393c5c$export$588937bcd60ade55, nt as contextAwarePanelOwner, on as Funnel, ot as slotsController, p as JsonOutput, pn as ChevronsRight, pt as Table, q as CommandEmpty, qt as ChartLoadingState, r as showCodeInRunModeAtom, rn as $fae977aafc393c5c$export$6b862160d295c8e, rt as contextAwarePanelType, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as EyeOff, st as Toggle, t as useNotebookCodeAvailable, tn as isRecord, tt as contextAwarePanelOpen, u as Switch, un as Download, v as ADD_PRINTING_CLASS, vt as TableRow, w as downloadSizeLimitAtom, wt as ColumnChartSpecModel, x as downloadHTMLAsImage, xt as inferFieldTypes, y as downloadBlob, yt as NAMELESS_COLUMN_PREFIX, z as useInternalStateWithSync, zt as dateToLocalISODateTime, __tla as __tla_2 } from "./code-visibility-D-FHtSSL.js";
29
+ import { $ as ContextAwarePanelItem, $t as EmotionCacheProvider, A as prettifyRowColumnCount, At as loadTableData, B as useSelectList, Bt as dateToLocalISOTime, C as Filenames, Ct as ColumnChartContext, D as EmptyState, Dt as usePrevious$1, E as ColumnPreviewContainer, Et as useIntersectionObserver, F as ContextMenuContent, Ft as getMimeValues, G as ComboboxItem, Gt as ChartErrorState, H as DatePicker, Ht as TabsContent, I as ContextMenuItem, It as isNullishFilter, J as CommandInput, Jt as LazyVegaEmbed, K as Command, Kt as ChartInfoState, L as ContextMenuSeparator, Lt as Maps, M as getColumnCountForDisplay, Mt as SELECT_COLUMN_ID, N as getUserColumnVisibilityCounts, Nt as TOO_MANY_ROWS, O as ErrorState, Ot as getPageIndexForRow, P as ContextMenu, Pt as toFieldTypes, Q as smartMatch, Qt as HtmlOutput, R as ContextMenuTrigger, Rt as dateToLocalISODate, S as Progress, St as renderCellValue, T as ColumnName, Tt as DelayMount, U as DateRangePicker, Ut as TabsList, V as CompactChipRow, Vt as Tabs, W as Combobox, Wt as TabsTrigger, X as CommandList, Xt as RenderTextWithLinks, Y as CommandItem, Yt as useOverflowDetection, Z as CommandSeparator, Zt as Kbd, _ as InstallPackageButton, _n as ArrowDownWideNarrow, _t as TableHeader, an as GripHorizontal, at as SlotNames, b as downloadByURL, bt as generateColumns, d as RadioGroup, dn as Code, dt as Fill, en as hasFunctionProperty, et as PANEL_TYPES, f as RadioGroupItem, fn as ChevronsUpDown, ft as Provider$1, g as DataTable, gn as ChevronLeft, gt as TableHead, h as OutputRenderer, hn as ChevronsDownUp, ht as TableCell, in as TextWrap, it as isCellAwareAtom, j as prettifyRowCount, jt as INDEX_COLUMN_NAME, k as LoadingState, kt as loadTableAndRawData, l as Slide, ln as Ellipsis, m as OutputArea, mn as ChevronsLeft, mt as TableBody, n as marimoVersionAtom, nn as $fae977aafc393c5c$export$588937bcd60ade55, nt as contextAwarePanelOwner, on as Funnel, ot as slotsController, p as JsonOutput, pn as ChevronsRight, pt as Table, q as CommandEmpty, qt as ChartLoadingState, r as showCodeInRunModeAtom, rn as $fae977aafc393c5c$export$6b862160d295c8e, rt as contextAwarePanelType, s as SLIDE_TYPE_OPTIONS_BY_VALUE, sn as EyeOff, st as Toggle, t as useNotebookCodeAvailable, tn as isRecord, tt as contextAwarePanelOpen, u as Switch, un as Download, v as ADD_PRINTING_CLASS, vt as TableRow, w as downloadSizeLimitAtom, wt as ColumnChartSpecModel, x as downloadHTMLAsImage, xt as inferFieldTypes, y as downloadBlob, yt as NAMELESS_COLUMN_PREFIX, z as useInternalStateWithSync, zt as dateToLocalISODateTime, __tla as __tla_2 } from "./code-visibility-DcoFoO9E.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-C6wHjkhW.js";
31
31
  import { t as Check } from "./check-C9OoNtR4.js";
32
32
  import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-Dq_j3Rxw.js";
33
33
  import { B as $64fa3d84918910a7$export$4d86445c2cf5e3, C as DropdownMenuTrigger, Ft as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, It as $3ef42575df84b30b$export$9d1611c77c2fe928, W as $64fa3d84918910a7$export$df3a06d6289f983e, Wt as $ff5963eb1fccf552$export$e08e3b67e392101e, X as useDebouncedCallback, Y as useDebounceControlledState, a as NumberField, d as roundToFractionDigits, f as DropdownMenu, g as DropdownMenuLabel, gn as ChevronRight, h as DropdownMenuItem, hn as Circle, i as OnBlurredInput, l as prettyNumber, m as DropdownMenuGroup, n as DebouncedNumberInput, o as maxFractionDigitsForSteps, ot as $f7dceffc5ad7768b$export$4e328f61c538687f, p as DropdownMenuContent, pt as $6179b936705e76d3$export$ae780daf29e6d456, r as Input, st as $701a24aa0da5b062$export$ea18c227d4417cc3, t as DebouncedInput, u as prettyScientificNumber, v as DropdownMenuSeparator, xt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, y as DropdownMenuShortcut, z as $64fa3d84918910a7$export$29f1550f4b0d4415 } from "./input-BGPrFH3g.js";
34
- import { _ as isWasm, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as Deferred, m as require_cuid2, u as getStaticVirtualFiles, v as CircleQuestionMark } from "./toDate-CKpRx4TS.js";
35
- import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Square, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-C2tUYuG7.js";
34
+ import { _ as isWasm, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as Deferred, m as require_cuid2, u as getStaticVirtualFiles, v as CircleQuestionMark } from "./toDate-BRJgtOGm.js";
35
+ import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Square, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-BOvvilRG.js";
36
36
  import { n as Trash, r as Pencil, t as BulkEdit } from "./types-C2Ir191_.js";
37
37
  import { n as require_prop_types, r as Plus, t as ErrorBoundary } from "./ErrorBoundary-B_CAG7_e.js";
38
38
  import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
@@ -59,7 +59,7 @@ import "./dist-M9Vag9Y0.js";
59
59
  import { r as python } from "./dist-C_Y3oV3C.js";
60
60
  import { n as minimalSetup, t as esm_default } from "./esm-M837UxV5.js";
61
61
  import "./purify.es-H92eMd9-.js";
62
- import { i as AlertTitle, n as Alert, r as AlertDescription } from "./formats-BX3uDQbB.js";
62
+ import { i as AlertTitle, n as Alert, r as AlertDescription } from "./formats-CitsMtUm.js";
63
63
  import "./vega-loader.browser-CZ-J8Py3.js";
64
64
  import { a as getContainerWidth, n as vegaLoadData, o as getVegaFieldTypes, s as tooltipHandler } from "./loader-Boph2xIS.js";
65
65
  import "./defaultLocale-u-3osm0P.js";
@@ -8886,7 +8886,7 @@ let __tla = Promise.all([
8886
8886
  };
8887
8887
  }
8888
8888
  };
8889
- var LazyChatbot = import_react.lazy(() => import("./chat-ui-Dv6Ox7Lu.js").then((e) => ({
8889
+ var LazyChatbot = import_react.lazy(() => import("./chat-ui-C0z13gJB.js").then((e) => ({
8890
8890
  default: e.Chatbot
8891
8891
  }))), messageSchema = array(object({
8892
8892
  id: string(),
@@ -28251,7 +28251,7 @@ ${c}
28251
28251
  return true;
28252
28252
  }
28253
28253
  }
28254
- var LazyVegaComponent = import_react.lazy(() => import("./vega-component-DNHEV0u0.js")), VegaPlugin = class {
28254
+ var LazyVegaComponent = import_react.lazy(() => import("./vega-component-BAvmvTjO.js")), VegaPlugin = class {
28255
28255
  constructor() {
28256
28256
  __publicField(this, "tagName", "marimo-vega");
28257
28257
  __publicField(this, "validator", object({
@@ -38024,7 +38024,7 @@ ${c}
38024
38024
  function _temp2$2(e) {
38025
38025
  e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
38026
38026
  }
38027
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-BcrECfho.js"));
38027
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-D30RNPOZ.js"));
38028
38028
  const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
38029
38029
  var _a5;
38030
38030
  let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
@@ -1,6 +1,6 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
3
- import { ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-F0RpWXNK.js";
3
+ import { ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-CEo5pRYw.js";
4
4
  import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
5
5
  import { t as Strings } from "./strings-Dq_j3Rxw.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
@@ -6,12 +6,12 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
6
6
  import { _ as Logger, g as cn, h as Events, l as useEventListener, t as Button } from "./button-BacYv-bE.js";
7
7
  import { t as require_react } from "./react-DA-nE2FX.js";
8
8
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
9
- import { dt as kioskModeAtom, ht as outputIsStale } from "./html-to-image-F0RpWXNK.js";
9
+ import { dt as kioskModeAtom, ht as outputIsStale } from "./html-to-image-CEo5pRYw.js";
10
10
  import "./chunk-5FQGJX7Z-BbqSm5gU.js";
11
11
  import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
12
- import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, cn as Expand, ct as Panel, dn as Code, i as DEFAULT_DECK_TRANSITION, l as Slide, lt as PanelGroup, o as DEFAULT_SLIDE_TYPE, sn as EyeOff, t as useNotebookCodeAvailable, ut as PanelResizeHandle } from "./code-visibility-D-FHtSSL.js";
12
+ import { a as DEFAULT_DECK_VERTICAL_ALIGN, c as SlideSidebar, cn as Expand, ct as Panel, dn as Code, i as DEFAULT_DECK_TRANSITION, l as Slide, lt as PanelGroup, o as DEFAULT_SLIDE_TYPE, sn as EyeOff, t as useNotebookCodeAvailable, ut as PanelResizeHandle } from "./code-visibility-DcoFoO9E.js";
13
13
  import { X as useDebouncedCallback } from "./input-BGPrFH3g.js";
14
- import "./toDate-CKpRx4TS.js";
14
+ import "./toDate-BRJgtOGm.js";
15
15
  import "./react-dom-BTJzcVJ9.js";
16
16
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
17
17
  import { X as useFullScreenElement } from "./zod-CijjQh4u.js";
@@ -520,13 +520,23 @@ var RuntimeManager = class {
520
520
  for (let [e2, b2] of C.entries()) x && !Object.values(KnownQueryParams).includes(e2) || S.searchParams.set(e2, b2);
521
521
  return S.pathname = `${S.pathname.replace(/\/$/, "")}/${e.replace(/^\//, "")}`, S.hash = "", S;
522
522
  }
523
+ appendCrossOriginAuth(e) {
524
+ return !this.isSameOrigin && this.config.authToken && e.searchParams.set(KnownQueryParams.accessToken, this.config.authToken), e;
525
+ }
526
+ formatNavigableHttpURL(e, b) {
527
+ let x = this.formatHttpURL({
528
+ path: e,
529
+ searchParams: b
530
+ });
531
+ return x.searchParams.delete(KnownQueryParams.accessToken), this.appendCrossOriginAuth(x);
532
+ }
523
533
  formatWsURL(e, b) {
524
534
  let x = this.formatHttpURL({
525
535
  path: e,
526
536
  searchParams: b,
527
537
  restrictToKnownQueryParams: false
528
538
  });
529
- return !this.isSameOrigin && this.config.authToken && x.searchParams.set(KnownQueryParams.accessToken, this.config.authToken), asWsUrl(x.toString());
539
+ return asWsUrl(this.appendCrossOriginAuth(x).toString());
530
540
  }
531
541
  getSessionSearchParams(e) {
532
542
  let b = new URL(this.config.url), x = new URLSearchParams(b.search);
@@ -2,7 +2,7 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { _ as Logger, c as Objects, g as cn, h as Events } from "./button-BacYv-bE.js";
3
3
  import { t as require_react } from "./react-DA-nE2FX.js";
4
4
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
5
- import { c as asRemoteURL, v as CircleQuestionMark } from "./toDate-CKpRx4TS.js";
5
+ import { c as asRemoteURL, v as CircleQuestionMark } from "./toDate-BRJgtOGm.js";
6
6
  import "./react-dom-BTJzcVJ9.js";
7
7
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
8
8
  import "./zod-CijjQh4u.js";
@@ -11,7 +11,7 @@ import { t as Tooltip } from "./tooltip-Czds6Qr8.js";
11
11
  import { t as debounce_default } from "./debounce-BOD3DbfP.js";
12
12
  import { A as useEvent_default, n as useTheme } from "./useTheme-Df_vGflw.js";
13
13
  import { s as uniq } from "./arrays-sEtDRoG4.js";
14
- import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-BX3uDQbB.js";
14
+ import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-CitsMtUm.js";
15
15
  import { n as formats } from "./vega-loader.browser-CZ-J8Py3.js";
16
16
  import { a as getContainerWidth, n as vegaLoadData, s as tooltipHandler } from "./loader-Boph2xIS.js";
17
17
  import { t as j } from "./react-vega-B0sAlDTL.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.15-dev37",
3
+ "version": "0.23.15-dev39",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,46 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { getRequestClient } from "@/core/network/requests";
4
+ import { getRuntimeManager } from "@/core/runtime/config";
5
+ import { isWasm } from "@/core/wasm/utils";
6
+ import { deserializeBlob } from "@/utils/blob";
7
+ import { downloadBlob, downloadByURL } from "@/utils/download";
8
+ import { type Base64String, base64ToDataURL } from "@/utils/json/base64";
9
+
10
+ /**
11
+ * Download a workspace file by path.
12
+ *
13
+ * Over HTTP this navigates to a streaming download endpoint, so the
14
+ * browser's download manager handles the transfer and no file contents
15
+ * are buffered in memory. In WASM there is no HTTP server to stream
16
+ * from; contents come over the pyodide bridge as base64 and are saved
17
+ * via a Blob.
18
+ */
19
+ export async function downloadFile(path: string, name: string): Promise<void> {
20
+ if (!isWasm()) {
21
+ const url = getRuntimeManager().formatNavigableHttpURL(
22
+ "api/files/download",
23
+ new URLSearchParams({ path }),
24
+ );
25
+ downloadByURL(url.toString(), name);
26
+ return;
27
+ }
28
+
29
+ const details = await getRequestClient().sendFileDetails({ path });
30
+ if (details.isBase64 && details.contents) {
31
+ const blob = deserializeBlob(
32
+ base64ToDataURL(
33
+ details.contents as Base64String,
34
+ details.mimeType || "application/octet-stream",
35
+ ),
36
+ );
37
+ downloadBlob(blob, name);
38
+ } else {
39
+ downloadBlob(
40
+ new Blob([details.contents || ""], {
41
+ type: details.mimeType || "application/octet-stream",
42
+ }),
43
+ name,
44
+ );
45
+ }
46
+ }
@@ -62,16 +62,14 @@ import type { FileInfo } from "@/core/network/types";
62
62
  import { isWasm } from "@/core/wasm/utils";
63
63
  import { useAsyncData } from "@/hooks/useAsyncData";
64
64
  import { ErrorBanner } from "@/plugins/impl/common/error-banner";
65
- import { deserializeBlob } from "@/utils/blob";
66
65
  import { cn } from "@/utils/cn";
67
66
  import { copyToClipboard } from "@/utils/copy";
68
- import { downloadBlob } from "@/utils/download";
69
- import { type Base64String, base64ToDataURL } from "@/utils/json/base64";
70
67
  import { openNotebook } from "@/utils/links";
71
68
  import type { FilePath } from "@/utils/paths";
72
69
  import { makeDuplicateName } from "@/utils/pathUtils";
73
70
  import { jotaiJsonStorage } from "@/utils/storage/jotai";
74
71
  import { useTreeDndManager } from "./dnd-wrapper";
72
+ import { downloadFile } from "./download";
75
73
  import { FileViewer } from "./file-viewer";
76
74
  import type { RequestingTree } from "./requesting-tree";
77
75
  import { openStateAtom, treeAtom } from "./state";
@@ -393,7 +391,7 @@ const Show = ({
393
391
  };
394
392
 
395
393
  const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
396
- const { openFile, sendFileDetails } = useRequestClient();
394
+ const { openFile } = useRequestClient();
397
395
  const disableFileDownloads = useAtomValue(disableFileDownloadsAtom);
398
396
 
399
397
  const fileType: FileIconType = node.data.isDirectory
@@ -645,23 +643,7 @@ const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
645
643
  <>
646
644
  <DropdownMenuItem
647
645
  onSelect={async () => {
648
- const details = await sendFileDetails({
649
- path: node.data.path,
650
- });
651
- if (details.isBase64 && details.contents) {
652
- const blob = deserializeBlob(
653
- base64ToDataURL(
654
- details.contents as Base64String,
655
- details.mimeType || "application/octet-stream",
656
- ),
657
- );
658
- downloadBlob(blob, node.data.name);
659
- } else {
660
- downloadBlob(
661
- new Blob([details.contents || ""]),
662
- node.data.name,
663
- );
664
- }
646
+ await downloadFile(node.data.path, node.data.name);
665
647
  }}
666
648
  data-testid="file-explorer-download-menu-item"
667
649
  >
@@ -21,10 +21,9 @@ import { filenameAtom } from "@/core/saving/file-state";
21
21
  import { isWasm } from "@/core/wasm/utils";
22
22
  import { useAsyncData } from "@/hooks/useAsyncData";
23
23
  import { ErrorBanner } from "@/plugins/impl/common/error-banner";
24
- import { deserializeBlob } from "@/utils/blob";
25
24
  import { copyToClipboard } from "@/utils/copy";
26
- import { downloadBlob, downloadByURL } from "@/utils/download";
27
- import { type Base64String, base64ToDataURL } from "@/utils/json/base64";
25
+ import type { Base64String } from "@/utils/json/base64";
26
+ import { downloadFile } from "./download";
28
27
  import { FilePreviewHeader } from "./file-header";
29
28
  import {
30
29
  FileContentRenderer,
@@ -121,30 +120,8 @@ export const FileViewer: React.FC<Props> = ({ file, onOpenNotebook }) => {
121
120
  );
122
121
  }
123
122
 
124
- const handleDownload = () => {
125
- if (data.isBase64 && data.contents) {
126
- if (isMediaMime(mimeType)) {
127
- const dataURL = base64ToDataURL(
128
- data.contents as Base64String,
129
- mimeType,
130
- );
131
- downloadByURL(dataURL, data.file.name);
132
- } else {
133
- const blob = deserializeBlob(
134
- base64ToDataURL(
135
- data.contents as Base64String,
136
- data.mimeType || "application/octet-stream",
137
- ),
138
- );
139
- downloadBlob(blob, data.file.name);
140
- }
141
- return;
142
- }
143
-
144
- downloadBlob(
145
- new Blob([data.contents || internalValue], { type: mimeType }),
146
- data.file.name,
147
- );
123
+ const handleDownload = async () => {
124
+ await downloadFile(file.path, data.file.name);
148
125
  };
149
126
 
150
127
  const header = (
@@ -154,6 +154,70 @@ describe("RuntimeManager", () => {
154
154
  });
155
155
  });
156
156
 
157
+ describe("formatNavigableHttpURL", () => {
158
+ it("adds access_token when cross-origin with authToken", () => {
159
+ const runtime = new RuntimeManager(
160
+ {
161
+ url: "https://sandbox.example.com",
162
+ lazy: true,
163
+ authToken: "my-secret-token",
164
+ },
165
+ true,
166
+ );
167
+ const url = runtime.formatNavigableHttpURL(
168
+ "api/files/download",
169
+ new URLSearchParams({ path: "/tmp/data.csv" }),
170
+ );
171
+
172
+ expect(url.pathname).toBe("/api/files/download");
173
+ expect(url.searchParams.get("path")).toBe("/tmp/data.csv");
174
+ expect(url.searchParams.get("access_token")).toBe("my-secret-token");
175
+ });
176
+
177
+ it("omits access_token when same-origin", () => {
178
+ const runtime = new RuntimeManager(
179
+ {
180
+ url: window.location.origin,
181
+ lazy: true,
182
+ authToken: "my-secret-token",
183
+ },
184
+ true,
185
+ );
186
+ const url = runtime.formatNavigableHttpURL(
187
+ "api/files/download",
188
+ new URLSearchParams({ path: "/tmp/data.csv" }),
189
+ );
190
+
191
+ expect(url.searchParams.get("access_token")).toBeNull();
192
+ expect(url.searchParams.get("path")).toBe("/tmp/data.csv");
193
+ });
194
+
195
+ it("omits access_token when no authToken configured", () => {
196
+ const runtime = new RuntimeManager(
197
+ { url: "https://sandbox.example.com", lazy: true },
198
+ true,
199
+ );
200
+ const url = runtime.formatNavigableHttpURL("api/files/download");
201
+
202
+ expect(url.searchParams.get("access_token")).toBeNull();
203
+ });
204
+
205
+ it("does not forward a page-inherited access_token when same-origin", () => {
206
+ const runtime = new RuntimeManager(
207
+ { url: window.location.origin, lazy: true },
208
+ true,
209
+ );
210
+ const original = window.location.href;
211
+ window.history.replaceState({}, "", "/?access_token=page-token");
212
+ try {
213
+ const url = runtime.formatNavigableHttpURL("api/files/download");
214
+ expect(url.searchParams.get("access_token")).toBeNull();
215
+ } finally {
216
+ window.history.replaceState({}, "", original);
217
+ }
218
+ });
219
+ });
220
+
157
221
  describe("getSseURL", () => {
158
222
  it("should return an http(s) URL with the session ID", () => {
159
223
  const runtime = new RuntimeManager(mockConfig);
@@ -86,6 +86,35 @@ export class RuntimeManager {
86
86
  return baseUrl;
87
87
  }
88
88
 
89
+ /**
90
+ * Channels that cannot send custom headers (WebSockets, and browser
91
+ * navigations such as file downloads) carry the auth token as a query
92
+ * param instead, but only when cross-origin. Same-origin requests
93
+ * authenticate via the session cookie, which keeps the token out of
94
+ * browser history and logs; cross-origin cookies are blocked by browsers,
95
+ * so the access_token query param is the only option there.
96
+ */
97
+ private appendCrossOriginAuth(url: URL): URL {
98
+ if (!this.isSameOrigin && this.config.authToken) {
99
+ url.searchParams.set(KnownQueryParams.accessToken, this.config.authToken);
100
+ }
101
+ return url;
102
+ }
103
+
104
+ /**
105
+ * An HTTP URL for requests made by browser navigation (e.g. anchor-click
106
+ * downloads), which cannot attach auth headers.
107
+ */
108
+ formatNavigableHttpURL(path: string, searchParams?: URLSearchParams): URL {
109
+ const url = this.formatHttpURL({ path, searchParams });
110
+ // Drop any token inherited from the current page's query params; re-add it
111
+ // only when cross-origin. Same-origin downloads authenticate via the
112
+ // session cookie, so a token in the URL would needlessly leak into
113
+ // proxy/server logs.
114
+ url.searchParams.delete(KnownQueryParams.accessToken);
115
+ return this.appendCrossOriginAuth(url);
116
+ }
117
+
89
118
  formatWsURL(path: string, searchParams?: URLSearchParams): URL {
90
119
  // We don't restrict to known query parameters, since mo.query_params()
91
120
  // can accept arbitrary parameters.
@@ -94,16 +123,7 @@ export class RuntimeManager {
94
123
  searchParams,
95
124
  restrictToKnownQueryParams: false,
96
125
  });
97
-
98
- // For cross-origin runtimes, pass the auth token as a query parameter.
99
- // WebSocket connections cannot send custom headers (no Authorization
100
- // header), and cross-origin cookies are blocked by browsers, so the
101
- // access_token query param is the only way to authenticate.
102
- if (!this.isSameOrigin && this.config.authToken) {
103
- url.searchParams.set(KnownQueryParams.accessToken, this.config.authToken);
104
- }
105
-
106
- return asWsUrl(url.toString());
126
+ return asWsUrl(this.appendCrossOriginAuth(url).toString());
107
127
  }
108
128
 
109
129
  /**