@marimo-team/islands 0.23.16-dev45 → 0.23.16-dev47

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 { c as useEventListener, g as Logger, h as cn, t as Button } from "./butt
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-DNq8q3zw.js";
9
- import { Bn as Info, Bt as PluralWord, C as Accordion, E as AccordionTrigger, En as Anchor2, F as base64ToDataURL, Ft as variablesAtom, Gt as allTablesAtom, H as renderHTML, Kn as CircleX, Kt as dataSourceConnectionsAtom, Mn as Wrench, Nn as Trash2, O as ChatBubbleIcon, Pt as jotaiJsonStorage, Q as notebookAtom, Rn as LoaderCircle, S as AIContextRegistry, T as AccordionItem, Un as ExternalLink, Vn as FileText, Yt as getRequestClient, b as contextToXml, c as Popover, d as PopoverTrigger, f as isOutputEmpty, g as formatDatasourceContextForCell, h as DatasourceContextProvider, ht as displayCellName, in as singleFacet, jt as generateUUID, kt as moveToEndOfEditor, ln as ZodLocalStorage, mn as CellOutputId, n as Spinner, nn as isMarimoErrorsMime, qt as getTableType, r as MarkdownRenderer, rn as isTracebackMime, st as parseHtmlContent, t as toPng, tn as isErrorMime, u as PopoverContent, v as Boosts, w as AccordionContent, wn as atomWithStorage, wt as createVariableInfoElement, x as AIContextProvider, y as Sections } from "./html-to-image-3w0AakWW.js";
9
+ import { Bn as Info, Bt as PluralWord, C as Accordion, E as AccordionTrigger, En as Anchor2, Ft as variablesAtom, Gt as allTablesAtom, H as renderHTML, Kn as CircleX, Kt as dataSourceConnectionsAtom, Mn as Wrench, Nn as Trash2, O as ChatBubbleIcon, Pt as jotaiJsonStorage, Q as notebookAtom, Rn as LoaderCircle, S as AIContextRegistry, T as AccordionItem, Un as ExternalLink, Vn as FileText, Yt as getRequestClient, b as contextToXml, c as Popover, d as PopoverTrigger, f as isOutputEmpty, g as formatDatasourceContextForCell, h as DatasourceContextProvider, ht as displayCellName, in as singleFacet, jt as generateUUID, kt as moveToEndOfEditor, ln as ZodLocalStorage, mn as CellOutputId, n as Spinner, nn as isMarimoErrorsMime, qt as getTableType, r as MarkdownRenderer, rn as isTracebackMime, st as parseHtmlContent, t as toPng, tn as isErrorMime, u as PopoverContent, v as Boosts, w as AccordionContent, wn as atomWithStorage, wt as createVariableInfoElement, x as AIContextProvider, y as Sections } from "./html-to-image-3w0AakWW.js";
10
10
  import "./chunk-5FQGJX7Z-B9WoXK1R.js";
11
11
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
12
12
  import { C as logNever, I as X, R as ChevronDown, t as Strings } from "./strings-DIy9NAmg.js";
13
13
  import { C as DropdownMenuTrigger, a as NumberField, f as DropdownMenu, h as DropdownMenuItem, p as DropdownMenuContent, r as Input } from "./input-C5K4VBvB.js";
14
14
  import { p as isUrl, w as CircleQuestionMark } from "./toDate-CqhBWjvO.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-YXcQTd1Y.js";
15
+ import { a as MarimoIncomingMessageEvent, d as fileDetailsToBlob, f as Square, n as blobToString, p as File$1, t as processOutput } from "./process-output-BRwR4QGs.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-BUcyXSdR.js";
@@ -6328,14 +6328,11 @@ var DEFAULT_FILE_SEARCH_CONFIG = {
6328
6328
  description: e20.message
6329
6329
  }), null));
6330
6330
  if (!C) return;
6331
- let w = C.mimeType || "text/plain", T;
6332
- if (w.startsWith("text/") || w.includes("json") || w.includes("xml")) T = new Blob([C.contents || ""], { type: w });
6333
- else if (C.contents) try {
6334
- T = deserializeBlob(base64ToDataURL(C.contents, w));
6335
- } catch {
6336
- T = new Blob([C.contents], { type: w });
6337
- }
6338
- else T = new Blob([""], { type: w });
6331
+ let w = C.mimeType || "text/plain", T = fileDetailsToBlob({
6332
+ contents: C.contents ?? "",
6333
+ mimeType: w,
6334
+ isBase64: C.isBase64 ?? false
6335
+ });
6339
6336
  x(new File([T], g, { type: w })), e19.dispatch({ changes: {
6340
6337
  from: y,
6341
6338
  to: b,
@@ -6760,20 +6757,20 @@ const ToolErrorCard = (e18) => {
6760
6757
  className: "font-semibold",
6761
6758
  children: "Failed:"
6762
6759
  }), h[7] = A) : A = h[7];
6763
- let j;
6764
- h[8] === g ? j = h[9] : (j = formatToolName(g), h[8] = g, h[9] = j);
6760
+ let M;
6761
+ h[8] === g ? M = h[9] : (M = formatToolName(g), h[8] = g, h[9] = M);
6765
6762
  let N;
6766
- h[10] === j ? N = h[11] : (N = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
6763
+ h[10] === M ? N = h[11] : (N = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
6767
6764
  className: "flex-1 text-left",
6768
6765
  children: [
6769
6766
  A,
6770
6767
  " ",
6771
6768
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
6772
6769
  className: "font-mono",
6773
- children: j
6770
+ children: M
6774
6771
  })
6775
6772
  ]
6776
- }), h[10] = j, h[11] = N);
6773
+ }), h[10] = M, h[11] = N);
6777
6774
  let P = S && "rotate-180", F;
6778
6775
  h[12] === P ? F = h[13] : (F = cn("h-3.5 w-3.5 shrink-0 transition-transform", P), h[12] = P, h[13] = F);
6779
6776
  let I;
@@ -6983,8 +6980,8 @@ const ToolHistoryRow = (e18) => {
6983
6980
  className: N,
6984
6981
  children: R
6985
6982
  }), h[19] = R, h[20] = N, h[21] = z) : z = h[21];
6986
- let B;
6987
- h[22] !== x || h[23] !== y || h[24] !== b || h[25] !== _ ? (B = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionContent, {
6983
+ let V;
6984
+ h[22] !== x || h[23] !== y || h[24] !== b || h[25] !== _ ? (V = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionContent, {
6988
6985
  className: "py-2 px-2",
6989
6986
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HistoryContent, {
6990
6987
  state: _,
@@ -6992,13 +6989,13 @@ const ToolHistoryRow = (e18) => {
6992
6989
  result: b,
6993
6990
  approval: x
6994
6991
  })
6995
- }), h[22] = x, h[23] = y, h[24] = b, h[25] = _, h[26] = B) : B = h[26];
6992
+ }), h[22] = x, h[23] = y, h[24] = b, h[25] = _, h[26] = V) : V = h[26];
6996
6993
  let H;
6997
- h[27] !== z || h[28] !== B ? (H = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionItem, {
6994
+ h[27] !== z || h[28] !== V ? (H = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AccordionItem, {
6998
6995
  value: "tool-call",
6999
6996
  className: "border-0",
7000
- children: [z, B]
7001
- }), h[27] = z, h[28] = B, h[29] = H) : H = h[29];
6997
+ children: [z, V]
6998
+ }), h[27] = z, h[28] = V, h[29] = H) : H = h[29];
7002
6999
  let U;
7003
7000
  return h[30] !== H || h[31] !== j || h[32] !== M ? (U = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Accordion, {
7004
7001
  type: "single",
@@ -7826,7 +7823,7 @@ const Chatbot = (e18) => {
7826
7823
  Object.keys(e18.config).some((h2) => e18.config[h2] !== C[h2]) && (S(e18.config), w(e18.config));
7827
7824
  let j = (0, import_react.useRef)(x);
7828
7825
  j.current = x;
7829
- let M = (0, import_react.useRef)(null), N = (0, import_react.useRef)(null), { data: P } = useAsyncData(async () => (await e18.get_chat_history({})).messages, []), I = e18.value.length > 0 ? e18.value : P, { messages: L, sendMessage: R, setMessages: z, status: B, stop: V, error: H, regenerate: U, clearError: W, addToolApprovalResponse: G } = useChat({
7826
+ let M = (0, import_react.useRef)(null), N = (0, import_react.useRef)(null), { data: F } = useAsyncData(async () => (await e18.get_chat_history({})).messages, []), I = e18.value.length > 0 ? e18.value : F, { messages: L, sendMessage: R, setMessages: z, status: B, stop: V, error: H, regenerate: U, clearError: W, addToolApprovalResponse: G } = useChat({
7830
7827
  sendAutomaticallyWhen: ({ messages: e19 }) => hasPendingToolCalls(e19),
7831
7828
  transport: new DefaultChatTransport({ fetch: async (h2, g) => {
7832
7829
  var _a2;
@@ -36338,7 +36338,7 @@ ${d}`,
36338
36338
  return Logger.warn("Failed to get version from mount config"), null;
36339
36339
  }
36340
36340
  }
36341
- marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev45");
36341
+ marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev47");
36342
36342
  showCodeInRunModeAtom = atom(true);
36343
36343
  atom(null);
36344
36344
  var import_compiler_runtime = require_compiler_runtime();
package/dist/main.js CHANGED
@@ -26,13 +26,13 @@ import { $ as notebookOutline, $t as publishedCellClasses, A as ChevronDownIcon,
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-B9WoXK1R.js";
27
27
  import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-DIlxLFXG.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-CQKL_D3i.js";
29
- import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-CWszsqAm.js";
29
+ import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-CrqeqHZV.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CMJGqBaY.js";
31
31
  import { t as Check } from "./check-DP7U0H0G.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-DIy9NAmg.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-C5K4VBvB.js";
34
34
  import { S as isWasm, _ as initialModeAtom, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as getInitialAppMode, m as require_cuid2, u as getStaticVirtualFiles, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-CqhBWjvO.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-YXcQTd1Y.js";
35
+ import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, f as Square, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, p as File, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-BRwR4QGs.js";
36
36
  import { n as Trash, r as Pencil, t as BulkEdit } from "./types-DicH9Oi0.js";
37
37
  import { n as require_prop_types, r as Plus, t as ErrorBoundary } from "./ErrorBoundary-DhLqwSWA.js";
38
38
  import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
@@ -9009,7 +9009,7 @@ let __tla = Promise.all([
9009
9009
  };
9010
9010
  }
9011
9011
  };
9012
- var LazyChatbot = import_react.lazy(() => import("./chat-ui-BhycUrBk.js").then((e) => ({
9012
+ var LazyChatbot = import_react.lazy(() => import("./chat-ui-1e7PcW56.js").then((e) => ({
9013
9013
  default: e.Chatbot
9014
9014
  }))), messageSchema = array(object({
9015
9015
  id: string(),
@@ -38147,7 +38147,7 @@ ${c}
38147
38147
  function _temp2$2(e) {
38148
38148
  e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
38149
38149
  }
38150
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-C1UBr2Io.js"));
38150
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-DpS6VbRW.js"));
38151
38151
  const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
38152
38152
  var _a5;
38153
38153
  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-3w0AakWW.js";
3
+ import { F as base64ToDataURL, ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-3w0AakWW.js";
4
4
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
5
5
  import { t as Strings } from "./strings-DIy9NAmg.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
@@ -21,64 +21,67 @@ var File = createLucideIcon("file", [["path", {
21
21
  }]]);
22
22
  function deserializeBlob(e) {
23
23
  var _a;
24
- let [v, y] = e.split(",", 2), b = (_a = /^data:(.+);base64$/.exec(v)) == null ? void 0 : _a[1], x = atob(y), S = x.length, C = new Uint8Array(S);
25
- for (let e2 = 0; e2 < S; e2++) C[e2] = x.charCodeAt(e2);
26
- return new Blob([C], { type: b });
24
+ let [b, x] = e.split(",", 2), S = (_a = /^data:(.+);base64$/.exec(b)) == null ? void 0 : _a[1], C = atob(x), w = C.length, T = new Uint8Array(w);
25
+ for (let e2 = 0; e2 < w; e2++) T[e2] = C.charCodeAt(e2);
26
+ return new Blob([T], { type: S });
27
+ }
28
+ function fileDetailsToBlob({ contents: e, mimeType: b, isBase64: S }) {
29
+ return S ? deserializeBlob(base64ToDataURL(e, b)) : new Blob([e], { type: b });
27
30
  }
28
31
  function defineCustomEvent(e) {
29
32
  return () => ({
30
33
  TYPE: e,
31
- is(v) {
32
- return v.type === e;
34
+ is(b) {
35
+ return b.type === e;
33
36
  },
34
- create(v) {
35
- return new CustomEvent(e, v);
37
+ create(b) {
38
+ return new CustomEvent(e, b);
36
39
  }
37
40
  });
38
41
  }
39
42
  const MarimoValueInputEvent = defineCustomEvent("marimo-value-input")(), MarimoValueUpdateEvent = defineCustomEvent("marimo-value-update")(), MarimoValueReadyEvent = defineCustomEvent("marimo-value-ready")(), MarimoIncomingMessageEvent = defineCustomEvent("marimo-incoming-message")();
40
- function createInputEvent(e, v) {
43
+ function createInputEvent(e, b) {
41
44
  return MarimoValueInputEvent.create({
42
45
  bubbles: true,
43
46
  composed: true,
44
47
  detail: {
45
48
  value: e,
46
- element: v
49
+ element: b
47
50
  }
48
51
  });
49
52
  }
50
53
  var import_compiler_runtime = require_compiler_runtime(), import_jsx_runtime = /* @__PURE__ */ __toESM(require_jsx_runtime(), 1);
51
54
  const PythonIcon = (e) => {
52
- let v = (0, import_compiler_runtime.c)(4), y, b;
53
- v[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (y = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("title", { children: "Python Logo" }), b = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M439.8 200.5c-7.7-30.9-22.3-54.2-53.4-54.2h-40.1v47.4c0 36.8-31.2 67.8-66.8 67.8H172.7c-29.2 0-53.4 25-53.4 54.3v101.8c0 29 25.2 46 53.4 54.3 33.8 9.9 66.3 11.7 106.8 0 26.9-7.8 53.4-23.5 53.4-54.3v-40.7H226.2v-13.6h160.2c31.1 0 42.6-21.7 53.4-54.2 11.2-33.5 10.7-65.7 0-108.6zM286.2 404c11.1 0 20.1 9.1 20.1 20.3 0 11.3-9 20.4-20.1 20.4-11 0-20.1-9.2-20.1-20.4.1-11.3 9.1-20.3 20.1-20.3zM167.8 248.1h106.8c29.7 0 53.4-24.5 53.4-54.3V91.9c0-29-24.4-50.7-53.4-55.6-35.8-5.9-74.7-5.6-106.8.1-45.2 8-53.4 24.7-53.4 55.6v40.7h106.9v13.6h-147c-31.1 0-58.3 18.7-66.8 54.2-9.8 40.7-10.2 66.1 0 108.6 7.6 31.6 25.7 54.2 56.8 54.2H101v-48.8c0-35.3 30.5-66.4 66.8-66.4zm-6.7-142.6c-11.1 0-20.1-9.1-20.1-20.3.1-11.3 9-20.4 20.1-20.4 11 0 20.1 9.2 20.1 20.4s-9 20.3-20.1 20.3z" }), v[0] = y, v[1] = b) : (y = v[0], b = v[1]);
54
- let x;
55
- return v[2] === e ? x = v[3] : (x = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
55
+ let b = (0, import_compiler_runtime.c)(4), x, S;
56
+ b[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel") ? (x = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("title", { children: "Python Logo" }), S = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M439.8 200.5c-7.7-30.9-22.3-54.2-53.4-54.2h-40.1v47.4c0 36.8-31.2 67.8-66.8 67.8H172.7c-29.2 0-53.4 25-53.4 54.3v101.8c0 29 25.2 46 53.4 54.3 33.8 9.9 66.3 11.7 106.8 0 26.9-7.8 53.4-23.5 53.4-54.3v-40.7H226.2v-13.6h160.2c31.1 0 42.6-21.7 53.4-54.2 11.2-33.5 10.7-65.7 0-108.6zM286.2 404c11.1 0 20.1 9.1 20.1 20.3 0 11.3-9 20.4-20.1 20.4-11 0-20.1-9.2-20.1-20.4.1-11.3 9.1-20.3 20.1-20.3zM167.8 248.1h106.8c29.7 0 53.4-24.5 53.4-54.3V91.9c0-29-24.4-50.7-53.4-55.6-35.8-5.9-74.7-5.6-106.8.1-45.2 8-53.4 24.7-53.4 55.6v40.7h106.9v13.6h-147c-31.1 0-58.3 18.7-66.8 54.2-9.8 40.7-10.2 66.1 0 108.6 7.6 31.6 25.7 54.2 56.8 54.2H101v-48.8c0-35.3 30.5-66.4 66.8-66.4zm-6.7-142.6c-11.1 0-20.1-9.1-20.1-20.3.1-11.3 9-20.4 20.1-20.4 11 0 20.1 9.2 20.1 20.4s-9 20.3-20.1 20.3z" }), b[0] = x, b[1] = S) : (x = b[0], S = b[1]);
57
+ let C;
58
+ return b[2] === e ? C = b[3] : (C = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
56
59
  xmlns: "http://www.w3.org/2000/svg",
57
60
  width: "1em",
58
61
  height: "1em",
59
62
  fill: "currentColor",
60
63
  viewBox: "0 0 448 512",
61
64
  ...e,
62
- children: [y, b]
63
- }), v[2] = e, v[3] = x), x;
65
+ children: [x, S]
66
+ }), b[2] = e, b[3] = C), C;
64
67
  };
65
68
  var FILE_READ_CONCURRENCY = 5;
66
- function blobToString(e, v) {
67
- return new Promise((y) => {
68
- let b = new FileReader();
69
- b.readAsDataURL(e), b.onload = (e2) => {
69
+ function blobToString(e, b) {
70
+ return new Promise((x) => {
71
+ let S = new FileReader();
72
+ S.readAsDataURL(e), S.onload = (e2) => {
70
73
  var _a;
71
74
  if ((_a = e2.target) == null ? void 0 : _a.result) {
72
- let b2 = e2.target.result;
73
- y(v === "base64" ? b2.slice(b2.indexOf(",") + 1) : b2);
75
+ let S2 = e2.target.result;
76
+ x(b === "base64" ? S2.slice(S2.indexOf(",") + 1) : S2);
74
77
  }
75
78
  };
76
79
  });
77
80
  }
78
81
  function filesToBase64(e) {
79
82
  return mapWithConcurrency(e, FILE_READ_CONCURRENCY, async (e2) => {
80
- let v = await blobToString(e2, "base64");
81
- return [e2.name, v];
83
+ let b = await blobToString(e2, "base64");
84
+ return [e2.name, b];
82
85
  });
83
86
  }
84
87
  function processOutput(e) {
@@ -87,12 +90,13 @@ function processOutput(e) {
87
90
  export {
88
91
  MarimoIncomingMessageEvent as a,
89
92
  MarimoValueUpdateEvent as c,
90
- Square as d,
91
- File as f,
93
+ fileDetailsToBlob as d,
94
+ Square as f,
92
95
  PythonIcon as i,
93
96
  createInputEvent as l,
94
97
  blobToString as n,
95
98
  MarimoValueInputEvent as o,
99
+ File as p,
96
100
  filesToBase64 as r,
97
101
  MarimoValueReadyEvent as s,
98
102
  processOutput as t,
@@ -9,7 +9,7 @@ import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
9
9
  import { ut as outputIsStale } from "./html-to-image-3w0AakWW.js";
10
10
  import "./chunk-5FQGJX7Z-B9WoXK1R.js";
11
11
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
12
- import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-CWszsqAm.js";
12
+ import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-CrqeqHZV.js";
13
13
  import { R as ChevronDown } from "./strings-DIy9NAmg.js";
14
14
  import { X as useDebouncedCallback } from "./input-C5K4VBvB.js";
15
15
  import { v as kioskModeAtom } from "./toDate-CqhBWjvO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.16-dev45",
3
+ "version": "0.23.16-dev47",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,31 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { describe, expect, it } from "vitest";
3
+ import { buildMediaSource } from "../renderers";
4
+
5
+ describe("buildMediaSource", () => {
6
+ it("returns base64 source for binary media", () => {
7
+ expect(
8
+ buildMediaSource({
9
+ contents: "aGVsbG8=",
10
+ mimeType: "image/png",
11
+ isBase64: true,
12
+ }),
13
+ ).toEqual({
14
+ base64: "aGVsbG8=",
15
+ mime: "image/png",
16
+ });
17
+ });
18
+
19
+ it("returns UTF-8 data URL for text-based media", () => {
20
+ const svg = '<svg xmlns="http://www.w3.org/2000/svg"></svg>';
21
+ expect(
22
+ buildMediaSource({
23
+ contents: svg,
24
+ mimeType: "image/svg+xml",
25
+ isBase64: false,
26
+ }),
27
+ ).toEqual({
28
+ url: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`,
29
+ });
30
+ });
31
+ });
@@ -22,12 +22,11 @@ import { isWasm } from "@/core/wasm/utils";
22
22
  import { useAsyncData } from "@/hooks/useAsyncData";
23
23
  import { ErrorBanner } from "@/plugins/impl/common/error-banner";
24
24
  import { copyToClipboard } from "@/utils/copy";
25
- import type { Base64String } from "@/utils/json/base64";
26
25
  import { downloadFile } from "./download";
27
26
  import { FilePreviewHeader } from "./file-header";
28
27
  import { FilePreviewMetadata } from "./file-preview-metadata";
29
28
  import { getFileRenderMode } from "./file-render-mode";
30
- import { FileContentRenderer } from "./renderers";
29
+ import { buildMediaSource, FileContentRenderer } from "./renderers";
31
30
 
32
31
  export const MAX_FILE_PREVIEW_BYTES = 10 * 1024 * 1024;
33
32
 
@@ -226,6 +225,15 @@ export const FileViewer: React.FC<Props> = ({ file, onOpenNotebook }) => {
226
225
  </Alert>
227
226
  );
228
227
 
228
+ const mediaSource =
229
+ isMedia && data.contents
230
+ ? buildMediaSource({
231
+ contents: data.contents,
232
+ mimeType,
233
+ isBase64: data.isBase64 ?? false,
234
+ })
235
+ : undefined;
236
+
229
237
  return (
230
238
  <>
231
239
  {header}
@@ -239,11 +247,7 @@ export const FileViewer: React.FC<Props> = ({ file, onOpenNotebook }) => {
239
247
  ? (data.contents ?? undefined)
240
248
  : undefined
241
249
  }
242
- mediaSource={
243
- isMedia && data.contents
244
- ? { base64: data.contents as Base64String, mime: mimeType }
245
- : undefined
246
- }
250
+ mediaSource={mediaSource}
247
251
  readOnly={!isText}
248
252
  onChange={isText ? setInternalValue : undefined}
249
253
  extensions={isText ? [saveKeymapExtension] : []}
@@ -60,6 +60,27 @@ function resolveMediaSrc(source: MediaSource): string {
60
60
  return base64ToDataURL(source.base64, source.mime);
61
61
  }
62
62
 
63
+ /**
64
+ * Build a {@link MediaSource} from file details.
65
+ * Binary media is base64-encoded; text-based media (e.g. SVG) uses a UTF-8 data URL.
66
+ */
67
+ export function buildMediaSource({
68
+ contents,
69
+ mimeType,
70
+ isBase64,
71
+ }: {
72
+ contents: string;
73
+ mimeType: string;
74
+ isBase64: boolean;
75
+ }): MediaSource {
76
+ if (isBase64) {
77
+ return { base64: contents as Base64String, mime: mimeType };
78
+ }
79
+ return {
80
+ url: `data:${mimeType};charset=utf-8,${encodeURIComponent(contents)}`,
81
+ };
82
+ }
83
+
63
84
  export const CsvViewer: React.FC<{ contents: string }> = ({ contents }) => {
64
85
  const data = useMemo(() => parseCsvData(contents), [contents]);
65
86
  const [pagination, setPagination] = useState<PaginationState>({
@@ -10,8 +10,7 @@ import {
10
10
  import { toast } from "@/components/ui/use-toast";
11
11
  import { contextCallbacks } from "@/core/codemirror/ai/state";
12
12
  import type { EditRequests, FileInfo, RunRequests } from "@/core/network/types";
13
- import { deserializeBlob } from "@/utils/blob";
14
- import { type Base64String, base64ToDataURL } from "@/utils/json/base64";
13
+ import { fileDetailsToBlob } from "@/utils/blob";
15
14
  import { Logger } from "@/utils/Logger";
16
15
  import { type AIContextItem, AIContextProvider } from "../registry";
17
16
  import { contextToXml } from "../utils";
@@ -219,33 +218,13 @@ export class FileContextProvider extends AIContextProvider<FileContextItem> {
219
218
 
220
219
  const mimeType = fileDetails.mimeType || "text/plain";
221
220
 
222
- // Handle binary vs text files
223
- let blob: Blob;
224
- if (
225
- mimeType.startsWith("text/") ||
226
- mimeType.includes("json") ||
227
- mimeType.includes("xml")
228
- ) {
229
- // Text files - create blob directly from contents
230
- blob = new Blob([fileDetails.contents || ""], { type: mimeType });
231
- } else {
232
- // Binary files - use blob utility to decode base64
233
- if (fileDetails.contents) {
234
- try {
235
- // Create data URL using utility and deserialize blob
236
- const dataURL = base64ToDataURL(
237
- fileDetails.contents as Base64String,
238
- mimeType,
239
- );
240
- blob = deserializeBlob(dataURL);
241
- } catch {
242
- // Fallback to treating as text
243
- blob = new Blob([fileDetails.contents], { type: mimeType });
244
- }
245
- } else {
246
- blob = new Blob([""], { type: mimeType });
247
- }
248
- }
221
+ // The backend's `isBase64` flag authoritatively distinguishes binary
222
+ // (base64-encoded) from UTF-8 text contents.
223
+ const blob = fileDetailsToBlob({
224
+ contents: fileDetails.contents ?? "",
225
+ mimeType,
226
+ isBase64: fileDetails.isBase64 ?? false,
227
+ });
249
228
 
250
229
  const file = new File([blob], name, { type: mimeType });
251
230
  addAttachment(file);
@@ -1,6 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { beforeEach, describe, expect, test } from "vitest";
3
- import { deserializeBlob, serializeBlob } from "../blob";
3
+ import { deserializeBlob, fileDetailsToBlob, serializeBlob } from "../blob";
4
4
  import { blobToString } from "../fileToBase64";
5
5
 
6
6
  describe("Blob serialization and deserialization", () => {
@@ -52,6 +52,32 @@ describe("Blob serialization and deserialization", () => {
52
52
  });
53
53
  });
54
54
 
55
+ describe("fileDetailsToBlob", () => {
56
+ test("decodes base64 contents into a binary blob", async () => {
57
+ const bytes = new Uint8Array([0, 1, 2, 3, 255]);
58
+ const base64 = btoa(String.fromCharCode(...bytes));
59
+ const blob = fileDetailsToBlob({
60
+ contents: base64,
61
+ mimeType: "image/png",
62
+ isBase64: true,
63
+ });
64
+ expect(blob.type).toBe("image/png");
65
+ const roundTripped = new Uint8Array(await blob.arrayBuffer());
66
+ expect(roundTripped).toEqual(bytes);
67
+ });
68
+
69
+ test("treats non-base64 contents as UTF-8 text", async () => {
70
+ const svg = '<svg xmlns="http://www.w3.org/2000/svg"></svg>';
71
+ const blob = fileDetailsToBlob({
72
+ contents: svg,
73
+ mimeType: "image/svg+xml",
74
+ isBase64: false,
75
+ });
76
+ expect(blob.type).toBe("image/svg+xml");
77
+ expect(await blob.text()).toBe(svg);
78
+ });
79
+ });
80
+
55
81
  describe("blobToString", () => {
56
82
  const testString = "Hello, world!";
57
83
  const mimeType = "text/plain";
package/src/utils/blob.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
- import type { DataURLString } from "./json/base64";
2
+ import {
3
+ type Base64String,
4
+ base64ToDataURL,
5
+ type DataURLString,
6
+ } from "./json/base64";
3
7
 
4
8
  export function serializeBlob<T>(blob: Blob): Promise<DataURLString> {
5
9
  return new Promise<DataURLString>((resolve, reject) => {
@@ -30,3 +34,22 @@ export function deserializeBlob(serializedBlob: DataURLString): Blob {
30
34
  const blob = new Blob([bytes], { type: mimeType });
31
35
  return blob;
32
36
  }
37
+
38
+ /**
39
+ * Convert file details into a `Blob`, using the authoritative `isBase64` flag
40
+ * to decide between decoding base64 bytes and treating contents as UTF-8 text.
41
+ */
42
+ export function fileDetailsToBlob({
43
+ contents,
44
+ mimeType,
45
+ isBase64,
46
+ }: {
47
+ contents: string;
48
+ mimeType: string;
49
+ isBase64: boolean;
50
+ }): Blob {
51
+ if (isBase64) {
52
+ return deserializeBlob(base64ToDataURL(contents as Base64String, mimeType));
53
+ }
54
+ return new Blob([contents], { type: mimeType });
55
+ }