@marimo-team/islands 0.23.7-dev1 → 0.23.7-dev3

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.
@@ -25680,7 +25680,7 @@ ${_}`,
25680
25680
  return Logger.warn("Failed to get version from mount config"), null;
25681
25681
  }
25682
25682
  }
25683
- marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.7-dev1");
25683
+ marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.7-dev3");
25684
25684
  showCodeInRunModeAtom = atom(true);
25685
25685
  atom(null);
25686
25686
  var import_compiler_runtime = require_compiler_runtime();
package/dist/main.js CHANGED
@@ -26,7 +26,7 @@ import { $ as useCellActions, At as DeferredRequestRegistry, B as safeExtractSet
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-CO1e63h_.js";
27
27
  import { o as useSize, s as Root$2, u as createLucideIcon } from "./dist-ESg7xyoD.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-DSIuqd3f.js";
29
- import { $ as filtersToFilterGroup, A as contextAwarePanelOwner, At as Funnel, B as TableCell, Bt as ChevronLeft, C as prettifyRowCount, Ct as useOverflowDetection, D as ContextAwarePanelItem, Dt as EmotionCacheProvider, E as ComboboxItem, Et as HtmlOutput, F as Toggle, Ft as Code, G as generateColumns, H as TableHeader, I as Fill, It as ChevronsUpDown, J as ColumnChartContext, K as inferFieldTypes, L as Provider$1, Lt as ChevronsRight, M as isCellAwareAtom, N as SlotNames, Nt as Ellipsis, O as PANEL_TYPES, Ot as TextWrap, P as slotsController, Pt as Download, Q as usePrevious$1, R as Table, Rt as ChevronsLeft, S as prettifyRowColumnCount, St as LazyVegaEmbed, T as Combobox, Tt as Kbd, U as TableRow, V as TableHead, Vt as ArrowDownWideNarrow, W as NAMELESS_COLUMN_PREFIX, X as DelayMount, Y as ColumnChartSpecModel, Z as useIntersectionObserver, _ as downloadBlob, _t as TabsList, at as TOO_MANY_ROWS, b as Progress, bt as ChartInfoState, c as Slide, ct as Command, d as JsonOutput, dt as CommandItem, et as getPageIndexForRow, f as OutputArea, ft as CommandList, g as ADD_PRINTING_CLASS, gt as TabsContent, h as InstallPackageButton, ht as Tabs, it as SELECT_COLUMN_ID, j as contextAwarePanelType, jt as EyeOff, k as contextAwarePanelOpen, kt as GripHorizontal, l as RadioGroup, lt as CommandEmpty, m as DataTable, mt as Maps, n as marimoVersionAtom, nt as loadTableData, o as SLIDE_TYPE_OPTIONS_BY_VALUE, ot as toFieldTypes, p as OutputRenderer, pt as CommandSeparator, q as renderCellValue, r as showCodeInRunModeAtom, rt as INDEX_COLUMN_NAME, st as getMimeValues, t as useNotebookCodeAvailable, tt as loadTableAndRawData, u as RadioGroupItem, ut as CommandInput, v as downloadByURL, vt as TabsTrigger, w as useInternalStateWithSync, wt as RenderTextWithLinks, x as Filenames, xt as ChartLoadingState, y as downloadHTMLAsImage, yt as ChartErrorState, z as TableBody, zt as ChevronsDownUp, __tla as __tla_2 } from "./code-visibility-DafdYnEy.js";
29
+ import { $ as filtersToFilterGroup, A as contextAwarePanelOwner, At as Funnel, B as TableCell, Bt as ChevronLeft, C as prettifyRowCount, Ct as useOverflowDetection, D as ContextAwarePanelItem, Dt as EmotionCacheProvider, E as ComboboxItem, Et as HtmlOutput, F as Toggle, Ft as Code, G as generateColumns, H as TableHeader, I as Fill, It as ChevronsUpDown, J as ColumnChartContext, K as inferFieldTypes, L as Provider$1, Lt as ChevronsRight, M as isCellAwareAtom, N as SlotNames, Nt as Ellipsis, O as PANEL_TYPES, Ot as TextWrap, P as slotsController, Pt as Download, Q as usePrevious$1, R as Table, Rt as ChevronsLeft, S as prettifyRowColumnCount, St as LazyVegaEmbed, T as Combobox, Tt as Kbd, U as TableRow, V as TableHead, Vt as ArrowDownWideNarrow, W as NAMELESS_COLUMN_PREFIX, X as DelayMount, Y as ColumnChartSpecModel, Z as useIntersectionObserver, _ as downloadBlob, _t as TabsList, at as TOO_MANY_ROWS, b as Progress, bt as ChartInfoState, c as Slide, ct as Command, d as JsonOutput, dt as CommandItem, et as getPageIndexForRow, f as OutputArea, ft as CommandList, g as ADD_PRINTING_CLASS, gt as TabsContent, h as InstallPackageButton, ht as Tabs, it as SELECT_COLUMN_ID, j as contextAwarePanelType, jt as EyeOff, k as contextAwarePanelOpen, kt as GripHorizontal, l as RadioGroup, lt as CommandEmpty, m as DataTable, mt as Maps, n as marimoVersionAtom, nt as loadTableData, o as SLIDE_TYPE_OPTIONS_BY_VALUE, ot as toFieldTypes, p as OutputRenderer, pt as CommandSeparator, q as renderCellValue, r as showCodeInRunModeAtom, rt as INDEX_COLUMN_NAME, st as getMimeValues, t as useNotebookCodeAvailable, tt as loadTableAndRawData, u as RadioGroupItem, ut as CommandInput, v as downloadByURL, vt as TabsTrigger, w as useInternalStateWithSync, wt as RenderTextWithLinks, x as Filenames, xt as ChartLoadingState, y as downloadHTMLAsImage, yt as ChartErrorState, z as TableBody, zt as ChevronsDownUp, __tla as __tla_2 } from "./code-visibility-Dk3LFszN.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CjMjllqy.js";
31
31
  import { n as $fb18d541ea1ad717$export$ad991b66133851cf, r as $5a387cc49350e6db$export$722debc0e56fea39, t as $896ba0a80a8f4d36$export$85fd5fdf27bacc79 } from "./useDateFormatter-B3mCQMP3.js";
32
32
  import { t as Check } from "./check-CFM2mVDr.js";
@@ -35311,15 +35311,19 @@ ${c}
35311
35311
  constructor() {
35312
35312
  __publicField(this, "tagName", "marimo-mermaid");
35313
35313
  __publicField(this, "validator", object({
35314
- diagram: string()
35314
+ diagram: string(),
35315
+ theme: string().optional(),
35316
+ theme_variables: record(string(), string()).optional()
35315
35317
  }));
35316
35318
  }
35317
35319
  render(e) {
35318
35320
  return (0, import_jsx_runtime.jsx)(LazyMermaid, {
35319
- diagram: e.data.diagram
35321
+ diagram: e.data.diagram,
35322
+ theme: e.data.theme,
35323
+ themeVariables: e.data.theme_variables
35320
35324
  });
35321
35325
  }
35322
- }, LazyMermaid = (0, import_react.lazy)(() => import("./mermaid-DJ1NyBGw.js").then(async (m) => {
35326
+ }, LazyMermaid = (0, import_react.lazy)(() => import("./mermaid-CEbzCxCc.js").then(async (m) => {
35323
35327
  await m.__tla;
35324
35328
  return m;
35325
35329
  })), import_compiler_runtime$20 = require_compiler_runtime();
@@ -44563,7 +44567,7 @@ ${c}
44563
44567
  if (l && l !== "slide") return l;
44564
44568
  if (c == null ? void 0 : c.has(e)) return "skip";
44565
44569
  }
44566
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-FVQZK4p1.js"));
44570
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-FAv_bXNy.js"));
44567
44571
  const SlidesLayoutPlugin = {
44568
44572
  type: "slides",
44569
44573
  name: "Slides",
@@ -1053,39 +1053,42 @@ ${e.themeCSS}`), e.fontFamily !== void 0 && (C += `
1053
1053
  }, () => "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)]).join("");
1054
1054
  }
1055
1055
  mermaid_default = (e) => {
1056
- let C = (0, import_compiler_runtime.c)(13), { diagram: w } = e, [T] = (0, import_react.useState)(_temp), D = useTheme().theme === "dark";
1056
+ let C = (0, import_compiler_runtime.c)(15), { diagram: w, theme: T, themeVariables: D } = e, [k] = (0, import_react.useState)(_temp), j = useTheme().theme === "dark", M = T ?? (j ? "dark" : "forest");
1057
1057
  mermaid_default$1.initialize({
1058
1058
  ...DEFAULT_CONFIG,
1059
- theme: D ? "dark" : "forest",
1060
- darkMode: D
1059
+ theme: M,
1060
+ themeVariables: D,
1061
+ darkMode: j
1061
1062
  });
1062
- let k;
1063
- C[0] === w ? k = C[1] : (k = w.trim(), C[0] = w, C[1] = k);
1064
- let j = k, M;
1065
- C[2] !== T || C[3] !== j ? (M = async () => (await mermaid_default$1.render(T, j, void 0).catch((e2) => {
1066
- var _a2;
1067
- throw (_a2 = document.getElementById(T)) == null ? void 0 : _a2.remove(), Logger.warn("Failed to render mermaid diagram", e2), e2;
1068
- })).svg, C[2] = T, C[3] = j, C[4] = M) : M = C[4];
1069
1063
  let N;
1070
- C[5] !== D || C[6] !== T || C[7] !== j ? (N = [
1064
+ C[0] === w ? N = C[1] : (N = w.trim(), C[0] = w, C[1] = N);
1065
+ let P = N, F;
1066
+ C[2] !== k || C[3] !== P ? (F = async () => (await mermaid_default$1.render(k, P, void 0).catch((e2) => {
1067
+ var _a2;
1068
+ throw (_a2 = document.getElementById(k)) == null ? void 0 : _a2.remove(), Logger.warn("Failed to render mermaid diagram", e2), e2;
1069
+ })).svg, C[2] = k, C[3] = P, C[4] = F) : F = C[4];
1070
+ let I;
1071
+ C[5] !== j || C[6] !== k || C[7] !== M || C[8] !== D || C[9] !== P ? (I = [
1072
+ P,
1073
+ k,
1071
1074
  j,
1072
- T,
1075
+ M,
1073
1076
  D
1074
- ], C[5] = D, C[6] = T, C[7] = j, C[8] = N) : N = C[8];
1075
- let { data: P, error: F } = useAsyncData(M, N);
1076
- if (F) {
1077
+ ], C[5] = j, C[6] = k, C[7] = M, C[8] = D, C[9] = P, C[10] = I) : I = C[10];
1078
+ let { data: L, error: R } = useAsyncData(F, I);
1079
+ if (R) {
1077
1080
  let e2;
1078
- return C[9] === F ? e2 = C[10] : (e2 = (0, import_jsx_runtime.jsx)(ErrorBanner, {
1079
- error: F
1080
- }), C[9] = F, C[10] = e2), e2;
1081
+ return C[11] === R ? e2 = C[12] : (e2 = (0, import_jsx_runtime.jsx)(ErrorBanner, {
1082
+ error: R
1083
+ }), C[11] = R, C[12] = e2), e2;
1081
1084
  }
1082
- if (!P) return null;
1083
- let I;
1084
- return C[11] === P ? I = C[12] : (I = (0, import_jsx_runtime.jsx)("div", {
1085
+ if (!L) return null;
1086
+ let z;
1087
+ return C[13] === L ? z = C[14] : (z = (0, import_jsx_runtime.jsx)("div", {
1085
1088
  dangerouslySetInnerHTML: {
1086
- __html: P
1089
+ __html: L
1087
1090
  }
1088
- }), C[11] = P, C[12] = I), I;
1091
+ }), C[13] = L, C[14] = z), z;
1089
1092
  };
1090
1093
  function _temp() {
1091
1094
  return randomAlpha();
@@ -8,7 +8,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
9
  import "./html-to-image-hMMPiNe_.js";
10
10
  import "./chunk-5FQGJX7Z-CO1e63h_.js";
11
- import { Ft as Code, Mt as Expand, a as DEFAULT_SLIDE_TYPE, c as Slide, i as DEFAULT_DECK_TRANSITION, jt as EyeOff, s as SlideSidebar, t as useNotebookCodeAvailable } from "./code-visibility-DafdYnEy.js";
11
+ import { Ft as Code, Mt as Expand, a as DEFAULT_SLIDE_TYPE, c as Slide, i as DEFAULT_DECK_TRANSITION, jt as EyeOff, s as SlideSidebar, t as useNotebookCodeAvailable } from "./code-visibility-Dk3LFszN.js";
12
12
  import "./input-BAOe64zx.js";
13
13
  import "./toDate-CHtl9vts.js";
14
14
  import "./react-dom-BWRJ_g_k.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.7-dev1",
3
+ "version": "0.23.7-dev3",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -145,6 +145,14 @@ describe("sanitizeHtml", () => {
145
145
  );
146
146
  });
147
147
 
148
+ test("preserves marimo-mermaid with theme attributes", () => {
149
+ const html =
150
+ "<marimo-mermaid data-diagram='&quot;graph TD\\nA --&gt; B&quot;' data-theme='&quot;base&quot;' data-theme_variables='{&quot;primaryColor&quot;: &quot;#E8EEF5&quot;, &quot;lineColor&quot;: &quot;#475569&quot;}'></marimo-mermaid>";
151
+ expect(sanitizeHtml(html)).toMatchInlineSnapshot(
152
+ `"<marimo-mermaid data-diagram="&quot;graph TD\\nA --> B&quot;" data-theme="&quot;base&quot;" data-theme_variables="{&quot;primaryColor&quot;: &quot;#E8EEF5&quot;, &quot;lineColor&quot;: &quot;#475569&quot;}"></marimo-mermaid>"`,
153
+ );
154
+ });
155
+
148
156
  test("keeps style tags with FORCE_BODY", () => {
149
157
  const html = "<style>body { color: red; }</style><p>Text</p>";
150
158
  expect(sanitizeHtml(html)).toMatchInlineSnapshot(
@@ -0,0 +1,50 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, test } from "vitest";
4
+ import { MermaidPlugin } from "../mermaid/MermaidPlugin";
5
+
6
+ describe("MermaidPlugin validator", () => {
7
+ test("accepts optional theme and theme_variables", () => {
8
+ const plugin = new MermaidPlugin();
9
+ const result = plugin.validator.safeParse({
10
+ diagram: "graph TD\nA --> B",
11
+ theme: "base",
12
+ theme_variables: {
13
+ primaryColor: "#E8EEF5",
14
+ lineColor: "#475569",
15
+ },
16
+ });
17
+
18
+ expect(result.success).toBe(true);
19
+ if (!result.success) {
20
+ return;
21
+ }
22
+
23
+ expect(result.data).toEqual({
24
+ diagram: "graph TD\nA --> B",
25
+ theme: "base",
26
+ theme_variables: {
27
+ primaryColor: "#E8EEF5",
28
+ lineColor: "#475569",
29
+ },
30
+ });
31
+ });
32
+
33
+ test("accepts any string as theme", () => {
34
+ const plugin = new MermaidPlugin();
35
+ const result = plugin.validator.safeParse({
36
+ diagram: "graph TD\nA --> B",
37
+ theme: "invalid",
38
+ });
39
+
40
+ expect(result.success).toBe(true);
41
+ if (!result.success) {
42
+ return;
43
+ }
44
+
45
+ expect(result.data).toEqual({
46
+ diagram: "graph TD\nA --> B",
47
+ theme: "invalid",
48
+ });
49
+ });
50
+ });
@@ -9,6 +9,8 @@ import type {
9
9
 
10
10
  interface Data {
11
11
  diagram: string;
12
+ theme?: string;
13
+ theme_variables?: Record<string, string>;
12
14
  }
13
15
 
14
16
  export class MermaidPlugin implements IStatelessPlugin<Data> {
@@ -16,10 +18,18 @@ export class MermaidPlugin implements IStatelessPlugin<Data> {
16
18
 
17
19
  validator = z.object({
18
20
  diagram: z.string(),
21
+ theme: z.string().optional(),
22
+ theme_variables: z.record(z.string(), z.string()).optional(),
19
23
  });
20
24
 
21
25
  render(props: IStatelessPluginProps<Data>): JSX.Element {
22
- return <LazyMermaid diagram={props.data.diagram} />;
26
+ return (
27
+ <LazyMermaid
28
+ diagram={props.data.diagram}
29
+ theme={props.data.theme}
30
+ themeVariables={props.data.theme_variables}
31
+ />
32
+ );
23
33
  }
24
34
  }
25
35
 
@@ -10,6 +10,8 @@ import { Logger } from "@/utils/Logger";
10
10
 
11
11
  interface Props {
12
12
  diagram: string;
13
+ theme?: string;
14
+ themeVariables?: Record<string, string>;
13
15
  config?: MermaidConfig;
14
16
  }
15
17
 
@@ -62,14 +64,16 @@ function randomAlpha() {
62
64
  ).join("");
63
65
  }
64
66
 
65
- const Mermaid: React.FC<Props> = ({ diagram }) => {
67
+ const Mermaid: React.FC<Props> = ({ diagram, theme, themeVariables }) => {
66
68
  // oxlint-disable-next-line react/hook-use-state
67
69
  const [id] = useState(() => randomAlpha());
68
70
 
69
71
  const darkMode = useTheme().theme === "dark";
72
+ const resolvedTheme = theme ?? (darkMode ? "dark" : "forest");
70
73
  mermaid.initialize({
71
74
  ...DEFAULT_CONFIG,
72
- theme: darkMode ? "dark" : "forest",
75
+ theme: resolvedTheme as MermaidConfig["theme"],
76
+ themeVariables,
73
77
  darkMode: darkMode,
74
78
  });
75
79
 
@@ -86,7 +90,7 @@ const Mermaid: React.FC<Props> = ({ diagram }) => {
86
90
  });
87
91
 
88
92
  return result.svg;
89
- }, [trimmedDiagram, id, darkMode]);
93
+ }, [trimmedDiagram, id, darkMode, resolvedTheme, themeVariables]);
90
94
 
91
95
  if (error) {
92
96
  return <ErrorBanner error={error} />;