@marimo-team/islands 0.22.1-dev41 → 0.22.1-dev43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -14080,7 +14080,11 @@ Defaulting to \`null\`.`;
14080
14080
  ]
14081
14081
  });
14082
14082
  }
14083
- var import_client$1 = __toESM(require_client(), 1), UIElementRegistry = class e {
14083
+ var import_client$1 = __toESM(require_client(), 1);
14084
+ function isUIValueUpdateMessage(e) {
14085
+ return typeof e != "object" || !e ? false : "type" in e && e.type === "marimo-ui-value-update";
14086
+ }
14087
+ var UIElementRegistry = class e {
14084
14088
  static get INSTANCE() {
14085
14089
  let r = "_marimo_private_UIElementRegistry";
14086
14090
  return window[r] || (window[r] = new e()), window[r];
@@ -14125,7 +14129,24 @@ Defaulting to \`null\`.`;
14125
14129
  }
14126
14130
  broadcastMessage(e2, r, c) {
14127
14131
  let d = this.entries.get(e2);
14128
- d === void 0 ? Logger.warn("UIElementRegistry missing entry", e2) : d.elements.forEach((d2) => {
14132
+ if (d === void 0) {
14133
+ Logger.warn("UIElementRegistry missing entry", e2);
14134
+ return;
14135
+ }
14136
+ if (isUIValueUpdateMessage(r)) {
14137
+ d.value = r.value, d.elements.forEach((e3) => {
14138
+ e3.dispatchEvent(MarimoValueUpdateEvent.create({
14139
+ bubbles: false,
14140
+ composed: true,
14141
+ detail: {
14142
+ value: r.value,
14143
+ element: e3
14144
+ }
14145
+ }));
14146
+ });
14147
+ return;
14148
+ }
14149
+ d.elements.forEach((d2) => {
14129
14150
  d2.dispatchEvent(MarimoIncomingMessageEvent.create({
14130
14151
  bubbles: false,
14131
14152
  composed: true,
@@ -33827,7 +33848,11 @@ Database schema: ${c}`), (_a4 = r2.aiFix) == null ? void 0 : _a4.setAiCompletion
33827
33848
  className: cn("h-auto min-h-10 whitespace-pre align-top", c2),
33828
33849
  style: d,
33829
33850
  ref: (c3) => {
33830
- columnSizingHandler(c3, e, r4.column);
33851
+ columnSizingHandler({
33852
+ table: e,
33853
+ column: r4.column,
33854
+ thead: c3
33855
+ });
33831
33856
  },
33832
33857
  children: r4.isPlaceholder ? null : flexRender(r4.column.columnDef.header, r4.getContext())
33833
33858
  }, r4.id);
@@ -33982,10 +34007,12 @@ Database schema: ${c}`), (_a4 = r2.aiFix) == null ? void 0 : _a4.setAiCompletion
33982
34007
  }
33983
34008
  };
33984
34009
  }
33985
- function columnSizingHandler(e, r, c) {
33986
- e && r.getState().columnSizing[c.id] !== e.getBoundingClientRect().width && r.setColumnSizing((r2) => ({
33987
- ...r2,
33988
- [c.id]: e.getBoundingClientRect().width
34010
+ function columnSizingHandler({ table: e, column: r, thead: c }) {
34011
+ if (!c) return;
34012
+ let d = Math.round(c.getBoundingClientRect().width);
34013
+ e.getState().columnSizing[r.id] !== d && e.setColumnSizing((e2) => ({
34014
+ ...e2,
34015
+ [r.id]: d
33989
34016
  }));
33990
34017
  }
33991
34018
  var MAX_PAGES_BEFORE_CLAMPING = 100;
@@ -65513,7 +65540,7 @@ ${c}
65513
65540
  return Logger.warn("Failed to get version from mount config"), null;
65514
65541
  }
65515
65542
  }
65516
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.22.1-dev41"), showCodeInRunModeAtom = atom(true);
65543
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.22.1-dev43"), showCodeInRunModeAtom = atom(true);
65517
65544
  atom(null);
65518
65545
  var VIRTUAL_FILE_REGEX = /\/@file\/([^\s"&'/]+)\.([\dA-Za-z]+)/g, VirtualFileTracker = class e {
65519
65546
  constructor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.22.1-dev41",
3
+ "version": "0.22.1-dev43",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -9,7 +9,6 @@ import {
9
9
  type HeaderGroup,
10
10
  type Row,
11
11
  type Table,
12
- type Table as TanStackTable,
13
12
  } from "@tanstack/react-table";
14
13
  import { useVirtualizer } from "@tanstack/react-virtual";
15
14
  import { type JSX, useLayoutEffect, useRef, useState } from "react";
@@ -52,7 +51,7 @@ export function renderTableHeader<TData>(
52
51
  )}
53
52
  style={style}
54
53
  ref={(thead) => {
55
- columnSizingHandler(thead, table, header.column);
54
+ columnSizingHandler({ table, column: header.column, thead });
56
55
  }}
57
56
  >
58
57
  {header.isPlaceholder
@@ -323,23 +322,30 @@ function getPinningStyles<TData>(
323
322
 
324
323
  // Update column sizes in table state for column pinning offsets
325
324
  // https://github.com/TanStack/table/discussions/3947#discussioncomment-9564867
326
- function columnSizingHandler<TData>(
327
- thead: HTMLTableCellElement | null,
328
- table: TanStackTable<TData>,
329
- column: Column<TData>,
330
- ) {
325
+ function columnSizingHandler<TData>({
326
+ table,
327
+ column,
328
+ thead,
329
+ }: {
330
+ table: Table<TData>;
331
+ column: Column<TData>;
332
+ thead: HTMLTableCellElement | null;
333
+ }): void {
331
334
  if (!thead) {
332
335
  return;
333
336
  }
334
- if (
335
- table.getState().columnSizing[column.id] ===
336
- thead.getBoundingClientRect().width
337
- ) {
337
+ // Round to avoid infinite re-render loops: the browser's table layout
338
+ // algorithm may render a <th> at a slightly different width than the
339
+ // CSS `width` we set via column.getSize(), so a strict float === float
340
+ // comparison never stabilizes. Rounding to integers ensures convergence
341
+ // after at most one cycle.
342
+ const measuredWidth = Math.round(thead.getBoundingClientRect().width);
343
+ if (table.getState().columnSizing[column.id] === measuredWidth) {
338
344
  return;
339
345
  }
340
346
 
341
347
  table.setColumnSizing((prevSizes) => ({
342
348
  ...prevSizes,
343
- [column.id]: thead.getBoundingClientRect().width,
349
+ [column.id]: measuredWidth,
344
350
  }));
345
351
  }
@@ -10,6 +10,23 @@ import {
10
10
  } from "./events";
11
11
  import { parseInitialValue } from "./htmlUtils";
12
12
 
13
+ /**
14
+ * Kernel-initiated UI value update, sent via the existing
15
+ * `send-ui-element-message` channel when `set_ui_value` (code_mode)
16
+ * changes a widget's value so the frontend can reflect the new state.
17
+ */
18
+ interface UIValueUpdateMessage {
19
+ type: "marimo-ui-value-update";
20
+ value: ValueType;
21
+ }
22
+
23
+ function isUIValueUpdateMessage(msg: unknown): msg is UIValueUpdateMessage {
24
+ if (typeof msg !== "object" || msg === null) {
25
+ return false;
26
+ }
27
+ return "type" in msg && msg.type === "marimo-ui-value-update";
28
+ }
29
+
13
30
  interface UIElementEntry {
14
31
  objectId: string;
15
32
  value: ValueType;
@@ -141,21 +158,38 @@ export class UIElementRegistry {
141
158
  const entry = this.entries.get(objectId);
142
159
  if (entry === undefined) {
143
160
  Logger.warn("UIElementRegistry missing entry", objectId);
144
- } else {
161
+ return;
162
+ }
163
+
164
+ // Kernel-initiated value update — push into DOM elements without
165
+ // dispatching MarimoValueReadyEvent to avoid a round-trip.
166
+ if (isUIValueUpdateMessage(message)) {
167
+ entry.value = message.value;
145
168
  entry.elements.forEach((element) => {
146
169
  element.dispatchEvent(
147
- MarimoIncomingMessageEvent.create({
148
- bubbles: false, // only the intended target gets the message
170
+ MarimoValueUpdateEvent.create({
171
+ bubbles: false,
149
172
  composed: true,
150
- detail: {
151
- objectId: objectId,
152
- message: message,
153
- buffers: buffers,
154
- },
173
+ detail: { value: message.value, element: element },
155
174
  }),
156
175
  );
157
176
  });
177
+ return;
158
178
  }
179
+
180
+ entry.elements.forEach((element) => {
181
+ element.dispatchEvent(
182
+ MarimoIncomingMessageEvent.create({
183
+ bubbles: false, // only the intended target gets the message
184
+ composed: true,
185
+ detail: {
186
+ objectId: objectId,
187
+ message: message,
188
+ buffers: buffers,
189
+ },
190
+ }),
191
+ );
192
+ });
159
193
  }
160
194
 
161
195
  /**