@marimo-team/islands 0.23.17-dev30 → 0.23.17-dev32

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.
@@ -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 { F as base64ToDataURL, ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-B8KJvlou.js";
3
+ import { F as base64ToDataURL, ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-Bgb6aaXi.js";
4
4
  import { u as createLucideIcon } from "./dist-DgzzIPS4.js";
5
5
  import { t as Strings } from "./strings-CITcoFNY.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
@@ -6,10 +6,10 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
6
6
  import { c as useEventListener, g as Logger, h as cn, m as Events, t as Button } from "./button-8aS1QcHr.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 { ut as outputIsStale } from "./html-to-image-B8KJvlou.js";
9
+ import { ut as outputIsStale } from "./html-to-image-Bgb6aaXi.js";
10
10
  import "./chunk-5FQGJX7Z-B9WoXK1R.js";
11
11
  import { u as createLucideIcon } from "./dist-DgzzIPS4.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-BxnkCaMd.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-XU-hyhVj.js";
13
13
  import { R as ChevronDown } from "./strings-CITcoFNY.js";
14
14
  import { X as useDebouncedCallback } from "./input-DtTqU0xh.js";
15
15
  import { v as kioskModeAtom } from "./toDate-kxcuDOWd.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.17-dev30",
3
+ "version": "0.23.17-dev32",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,35 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import { ChartSchema } from "../schemas";
5
+
6
+ describe("ChartSchema", () => {
7
+ it("keeps a known axis column type", () => {
8
+ const result = ChartSchema.parse({
9
+ general: { xColumn: { field: "count", type: "integer" } },
10
+ });
11
+
12
+ expect(result.general?.xColumn?.type).toBe("integer");
13
+ });
14
+
15
+ it("normalizes an unrecognized axis column type", () => {
16
+ const result = ChartSchema.parse({
17
+ general: { xColumn: { field: "geom", type: "geometry" } },
18
+ });
19
+
20
+ expect(result.general?.xColumn?.type).toBe("unknown");
21
+ });
22
+
23
+ it("normalizes an unrecognized tooltip field type", () => {
24
+ const result = ChartSchema.parse({
25
+ tooltips: {
26
+ auto: false,
27
+ fields: [{ field: "geom", type: "geometry" }],
28
+ },
29
+ });
30
+
31
+ expect(result.tooltips?.fields).toEqual([
32
+ { field: "geom", type: "unknown" },
33
+ ]);
34
+ });
35
+ });
@@ -28,7 +28,10 @@ export const BinSchema = z.object({
28
28
 
29
29
  const BaseColumnSchema = z.object({
30
30
  field: z.string().optional(),
31
- type: z.enum([...DATA_TYPES, EMPTY_VALUE]).optional(),
31
+ type: z
32
+ .enum([...DATA_TYPES, EMPTY_VALUE])
33
+ .catch("unknown")
34
+ .optional(),
32
35
  selectedDataType: z.enum([...SELECTABLE_DATA_TYPES, EMPTY_VALUE]).optional(),
33
36
  sort: z.enum(SORT_TYPES).default("ascending").optional(),
34
37
  timeUnit: z.enum(TIME_UNITS).optional(),
@@ -102,7 +105,7 @@ export const ChartSchema = z.object({
102
105
  fields: z.array(
103
106
  z.object({
104
107
  field: z.string(),
105
- type: z.enum(DATA_TYPES),
108
+ type: z.enum(DATA_TYPES).catch("unknown"),
106
109
  }),
107
110
  ),
108
111
  })
@@ -0,0 +1,21 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import type { DataType } from "@/core/kernel/messages";
5
+ import { DATA_TYPE_ICON, resolveDataType } from "../icons";
6
+
7
+ describe("resolveDataType", () => {
8
+ it("passes through every mapped data type", () => {
9
+ for (const dataType of Object.keys(DATA_TYPE_ICON)) {
10
+ expect(resolveDataType(dataType as DataType)).toBe(dataType);
11
+ }
12
+ });
13
+
14
+ it("resolves unmapped data types to unknown", () => {
15
+ expect(resolveDataType("geometry" as DataType)).toBe("unknown");
16
+ });
17
+
18
+ it("resolves data types shadowing Object.prototype keys to unknown", () => {
19
+ expect(resolveDataType("toString" as DataType)).toBe("unknown");
20
+ });
21
+ });
@@ -30,6 +30,16 @@ export const DATA_TYPE_ICON: Record<DataType | SelectableDataType, LucideIcon> =
30
30
  unknown: CurlyBracesIcon,
31
31
  };
32
32
 
33
+ /**
34
+ * A newer backend can send a data type this frontend does not know. Resolve
35
+ * those to `unknown` before indexing icon or color maps.
36
+ */
37
+ export function resolveDataType(
38
+ dataType: DataType | SelectableDataType,
39
+ ): DataType | SelectableDataType {
40
+ return Object.hasOwn(DATA_TYPE_ICON, dataType) ? dataType : "unknown";
41
+ }
42
+
33
43
  export function getDataTypeColor(
34
44
  dataType: DataType | SelectableDataType,
35
45
  ): string {
@@ -0,0 +1,29 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { render } from "@testing-library/react";
4
+ import { describe, expect, it, vi } from "vitest";
5
+ import type { DataType } from "@/core/kernel/messages";
6
+ import { Logger } from "@/utils/Logger";
7
+ import { ColumnName } from "../components";
8
+
9
+ describe("ColumnName", () => {
10
+ it("renders the unknown icon for unrecognized data types", () => {
11
+ const warn = vi.spyOn(Logger, "warn").mockImplementation(() => {});
12
+
13
+ try {
14
+ const unrecognized = render(
15
+ <ColumnName columnName="geom" dataType={"geometry" as DataType} />,
16
+ );
17
+ const unknown = render(
18
+ <ColumnName columnName="geom" dataType="unknown" />,
19
+ );
20
+
21
+ expect(unrecognized.container.innerHTML).toEqual(
22
+ unknown.container.innerHTML,
23
+ );
24
+ expect(warn).not.toHaveBeenCalled();
25
+ } finally {
26
+ warn.mockRestore();
27
+ }
28
+ });
29
+ });
@@ -5,7 +5,11 @@ import type { CSSProperties } from "react";
5
5
  import { TreeChevron } from "@/components/editor/file-tree/tree-actions";
6
6
  import type { DataType } from "@/core/kernel/messages";
7
7
  import { cn } from "@/utils/cn";
8
- import { DATA_TYPE_ICON, getDataTypeColor } from "../datasets/icons";
8
+ import {
9
+ DATA_TYPE_ICON,
10
+ getDataTypeColor,
11
+ resolveDataType,
12
+ } from "../datasets/icons";
9
13
 
10
14
  export const RotatingChevron: React.FC<{ isExpanded: boolean }> = ({
11
15
  isExpanded,
@@ -101,8 +105,9 @@ export const ColumnName = ({
101
105
  columnName: React.ReactNode;
102
106
  dataType: DataType;
103
107
  }) => {
104
- const Icon = DATA_TYPE_ICON[dataType];
105
- const color = getDataTypeColor(dataType);
108
+ const resolvedDataType = resolveDataType(dataType);
109
+ const Icon = DATA_TYPE_ICON[resolvedDataType];
110
+ const color = getDataTypeColor(resolvedDataType);
106
111
 
107
112
  return (
108
113
  <div className="flex flex-row items-center gap-1.5">
@@ -0,0 +1,44 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { render } from "@testing-library/react";
4
+ import { describe, expect, it } from "vitest";
5
+ import type {
6
+ DataTable,
7
+ DataTableColumn,
8
+ DataType,
9
+ } from "@/core/kernel/messages";
10
+ import { renderColumnInfo, renderTableInfo } from "../renderers";
11
+
12
+ const geometryColumn = {
13
+ name: "geom",
14
+ type: "geometry" as DataType,
15
+ external_type: "geometry",
16
+ sample_values: [],
17
+ } as DataTableColumn;
18
+
19
+ describe("SQL renderers", () => {
20
+ it("renders table information with an unrecognized column type", () => {
21
+ const table: DataTable = {
22
+ name: "shapes",
23
+ type: "table",
24
+ source: "local",
25
+ source_type: "local",
26
+ num_rows: null,
27
+ num_columns: 1,
28
+ variable_name: null,
29
+ columns: [geometryColumn],
30
+ primary_keys: [],
31
+ indexes: [],
32
+ };
33
+
34
+ const result = render(renderTableInfo(table));
35
+
36
+ expect(result.container.querySelector("svg")).not.toBeNull();
37
+ });
38
+
39
+ it("renders column information with an unrecognized column type", () => {
40
+ const result = render(renderColumnInfo(geometryColumn));
41
+
42
+ expect(result.container.querySelector("svg")).not.toBeNull();
43
+ });
44
+ });
@@ -13,7 +13,7 @@ import {
13
13
  TableIcon,
14
14
  ViewIcon,
15
15
  } from "@/components/databases/namespace-icons";
16
- import { DATA_TYPE_ICON } from "@/components/datasets/icons";
16
+ import { DATA_TYPE_ICON, resolveDataType } from "@/components/datasets/icons";
17
17
  import { Badge } from "@/components/ui/badge";
18
18
  import {
19
19
  type ConnectionName,
@@ -149,7 +149,7 @@ export const renderTableInfo = (table: DataTable): React.ReactNode => {
149
149
  );
150
150
 
151
151
  const columnItems = table.columns.map((column) => {
152
- const TypeIcon = DATA_TYPE_ICON[column.type];
152
+ const TypeIcon = DATA_TYPE_ICON[resolveDataType(column.type)];
153
153
  return (
154
154
  <div
155
155
  key={column.name}
@@ -288,7 +288,7 @@ export const renderTableInfo = (table: DataTable): React.ReactNode => {
288
288
  };
289
289
 
290
290
  export const renderColumnInfo = (column: DataTableColumn): React.ReactNode => {
291
- const TypeIcon = DATA_TYPE_ICON[column.type];
291
+ const TypeIcon = DATA_TYPE_ICON[resolveDataType(column.type)];
292
292
 
293
293
  const typeBadge = (
294
294
  <Badge
@@ -8,10 +8,10 @@ import { LoadingTable } from "@/components/data-table/loading-table";
8
8
  import { type FieldTypes, toFieldTypes } from "@/components/data-table/types";
9
9
  import { Alert, AlertTitle } from "@/components/ui/alert";
10
10
  import { DelayMount } from "@/components/utils/delay-mount";
11
- import { DATA_TYPES } from "@/core/kernel/messages";
12
11
  import { useAsyncData } from "@/hooks/useAsyncData";
13
12
  import { createPlugin } from "../core/builder";
14
13
  import type { Setter } from "../types";
14
+ import { columnToFieldTypesSchema } from "./data-frames/schema";
15
15
  import {
16
16
  BulkEdit,
17
17
  type DataEditorProps,
@@ -44,14 +44,7 @@ export const DataEditorPlugin = createPlugin<Edits>("marimo-data-editor", {
44
44
  }),
45
45
  label: z.string().nullable(),
46
46
  data: z.union([z.string(), z.array(z.object({}).passthrough())]),
47
- fieldTypes: z
48
- .array(
49
- z.tuple([
50
- z.coerce.string(),
51
- z.tuple([z.enum(DATA_TYPES), z.string()]),
52
- ]),
53
- )
54
- .nullish(),
47
+ fieldTypes: columnToFieldTypesSchema.nullish(),
55
48
  editableColumns: z.union([z.array(z.string()), z.literal("all")]),
56
49
  columnSizingMode: z.enum(["auto", "fit"]).default("auto"), // TODO: Remove this
57
50
  }),
@@ -0,0 +1,18 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import { DataEditorPlugin } from "../DataEditorPlugin";
5
+
6
+ describe("DataEditorPlugin", () => {
7
+ it("normalizes an unrecognized field type", () => {
8
+ const result = DataEditorPlugin.validator.parse({
9
+ initialValue: { edits: [] },
10
+ label: null,
11
+ data: [],
12
+ fieldTypes: [["geom", ["geometry", "geometry"]]],
13
+ editableColumns: "all",
14
+ });
15
+
16
+ expect(result.fieldTypes).toEqual([["geom", ["unknown", "geometry"]]]);
17
+ });
18
+ });
@@ -0,0 +1,30 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import { columnToFieldTypesSchema } from "../schema";
5
+
6
+ describe("columnToFieldTypesSchema", () => {
7
+ it("keeps known field types", () => {
8
+ const result = columnToFieldTypesSchema.parse([
9
+ ["count", ["integer", "int64"]],
10
+ ["label", ["string", "object"]],
11
+ ]);
12
+
13
+ expect(result).toEqual([
14
+ ["count", ["integer", "int64"]],
15
+ ["label", ["string", "object"]],
16
+ ]);
17
+ });
18
+
19
+ it("normalizes an unrecognized field type without discarding other fields", () => {
20
+ const result = columnToFieldTypesSchema.parse([
21
+ ["geom", ["geometry", "geometry"]],
22
+ ["label", ["string", "object"]],
23
+ ]);
24
+
25
+ expect(result).toEqual([
26
+ ["geom", ["unknown", "geometry"]],
27
+ ["label", ["string", "object"]],
28
+ ]);
29
+ });
30
+ });
@@ -15,7 +15,10 @@ import {
15
15
  } from "./utils/operators";
16
16
 
17
17
  export const columnToFieldTypesSchema = z.array(
18
- z.tuple([z.coerce.string(), z.tuple([z.enum(DATA_TYPES), z.string()])]),
18
+ z.tuple([
19
+ z.coerce.string(),
20
+ z.tuple([z.enum(DATA_TYPES).catch("unknown"), z.string()]),
21
+ ]),
19
22
  );
20
23
 
21
24
  export const column_id = z