@marimo-team/islands 0.23.16-dev54 → 0.23.16-dev56
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/{common-DwIK9Ruq.js → common-Dwe0Uq2u.js} +1 -1
- package/dist/main.js +14 -6
- package/dist/{reveal-component-DlbR8R40.js → reveal-component-DentpkqC.js} +1 -1
- package/package.json +1 -1
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +55 -0
- package/src/plugins/impl/anywidget/model.ts +20 -5
|
@@ -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-
|
|
36341
|
+
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev56");
|
|
36342
36342
|
showCodeInRunModeAtom = atom(true);
|
|
36343
36343
|
atom(null);
|
|
36344
36344
|
var import_compiler_runtime = require_compiler_runtime();
|
package/dist/main.js
CHANGED
|
@@ -26,7 +26,7 @@ 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-
|
|
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-Dwe0Uq2u.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";
|
|
@@ -3574,7 +3574,7 @@ let __tla = Promise.all([
|
|
|
3574
3574
|
Logger.error("Error emitting event", e2);
|
|
3575
3575
|
}
|
|
3576
3576
|
}, 0));
|
|
3577
|
-
__privateSet(this, _n2, e), __privateSet(this, _r, r), __privateSet(this, _t2, /* @__PURE__ */ new
|
|
3577
|
+
__privateSet(this, _n2, e), __privateSet(this, _r, r), __privateSet(this, _t2, /* @__PURE__ */ new Set()), c && c.addEventListener("abort", () => {
|
|
3578
3578
|
Logger.debug("[Model] Signal aborted, clearing all listeners"), __privateSet(this, _i, {});
|
|
3579
3579
|
});
|
|
3580
3580
|
}
|
|
@@ -3601,11 +3601,16 @@ let __tla = Promise.all([
|
|
|
3601
3601
|
__privateSet(this, _n2, {
|
|
3602
3602
|
...__privateGet(this, _n2),
|
|
3603
3603
|
[e]: r
|
|
3604
|
-
}), __privateGet(this, _t2).
|
|
3604
|
+
}), __privateGet(this, _t2).add(e), __privateMethod(this, _e_instances, a_fn).call(this, `change:${e}`, r), __privateGet(this, _c).call(this);
|
|
3605
3605
|
}
|
|
3606
3606
|
save_changes() {
|
|
3607
3607
|
if (__privateGet(this, _t2).size === 0) return;
|
|
3608
|
-
let e = Object.fromEntries(
|
|
3608
|
+
let e = Object.fromEntries([
|
|
3609
|
+
...__privateGet(this, _t2)
|
|
3610
|
+
].map((e2) => [
|
|
3611
|
+
e2,
|
|
3612
|
+
__privateGet(this, _n2)[e2]
|
|
3613
|
+
]));
|
|
3609
3614
|
__privateGet(this, _t2).clear(), __privateGet(this, _r).sendUpdate(e);
|
|
3610
3615
|
}
|
|
3611
3616
|
on(e, r, c) {
|
|
@@ -3626,7 +3631,10 @@ let __tla = Promise.all([
|
|
|
3626
3631
|
}, o_fn = function(e) {
|
|
3627
3632
|
e != null && Object.keys(e).forEach((r) => {
|
|
3628
3633
|
let c = r;
|
|
3629
|
-
__privateGet(this, _n2)[c] !== e[c] && this
|
|
3634
|
+
__privateGet(this, _t2).delete(c), __privateGet(this, _n2)[c] !== e[c] && (__privateSet(this, _n2, {
|
|
3635
|
+
...__privateGet(this, _n2),
|
|
3636
|
+
[c]: e[c]
|
|
3637
|
+
}), __privateMethod(this, _e_instances, a_fn).call(this, `change:${c}`, e[c]), __privateGet(this, _c).call(this));
|
|
3630
3638
|
});
|
|
3631
3639
|
}, s_fn = function(e, r = []) {
|
|
3632
3640
|
let c = __privateGet(this, _i)["msg:custom"];
|
|
@@ -38147,7 +38155,7 @@ ${c}
|
|
|
38147
38155
|
function _temp2$2(e) {
|
|
38148
38156
|
e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
|
|
38149
38157
|
}
|
|
38150
|
-
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-
|
|
38158
|
+
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-DentpkqC.js"));
|
|
38151
38159
|
const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
|
|
38152
38160
|
var _a5;
|
|
38153
38161
|
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), [
|
|
@@ -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-DzQw9y4M.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-
|
|
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-Dwe0Uq2u.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
|
@@ -263,6 +263,61 @@ describe("Model", () => {
|
|
|
263
263
|
await TestUtils.nextTick(); // flush
|
|
264
264
|
expect(callback).toHaveBeenCalledTimes(1);
|
|
265
265
|
});
|
|
266
|
+
|
|
267
|
+
it("should not mark kernel-pushed state dirty", () => {
|
|
268
|
+
getMarimoInternal(model).updateAndEmitDiffs({ foo: "changed", bar: 456 });
|
|
269
|
+
|
|
270
|
+
model.save_changes();
|
|
271
|
+
expect(mockComm.sendUpdate).not.toHaveBeenCalled();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it("should not echo kernel-pushed state alongside a local set", () => {
|
|
275
|
+
// Kernel pushes a large trait; widget ESM then sets one field.
|
|
276
|
+
getMarimoInternal(model).updateAndEmitDiffs({
|
|
277
|
+
foo: "from kernel",
|
|
278
|
+
bar: 123,
|
|
279
|
+
});
|
|
280
|
+
model.set("bar", 456);
|
|
281
|
+
|
|
282
|
+
model.save_changes();
|
|
283
|
+
expect(mockComm.sendUpdate).toHaveBeenCalledExactlyOnceWith({
|
|
284
|
+
bar: 456,
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("should drop a pending local write superseded by a kernel push", () => {
|
|
289
|
+
// Local write, not yet saved...
|
|
290
|
+
model.set("foo", "local");
|
|
291
|
+
// ...then the kernel pushes a newer value for the same key.
|
|
292
|
+
getMarimoInternal(model).updateAndEmitDiffs({
|
|
293
|
+
foo: "from kernel",
|
|
294
|
+
bar: 123,
|
|
295
|
+
});
|
|
296
|
+
expect(model.get("foo")).toBe("from kernel");
|
|
297
|
+
|
|
298
|
+
// Saving must not resend the stale local value.
|
|
299
|
+
model.save_changes();
|
|
300
|
+
expect(mockComm.sendUpdate).not.toHaveBeenCalled();
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it("should drop a pending local write the kernel pushed the same value for", () => {
|
|
304
|
+
const callback = vi.fn();
|
|
305
|
+
model.on("change:foo", callback);
|
|
306
|
+
|
|
307
|
+
// Local write, not yet saved...
|
|
308
|
+
model.set("foo", "agreed");
|
|
309
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
310
|
+
|
|
311
|
+
// ...then the kernel independently pushes the same value.
|
|
312
|
+
getMarimoInternal(model).updateAndEmitDiffs({
|
|
313
|
+
foo: "agreed",
|
|
314
|
+
bar: 123,
|
|
315
|
+
});
|
|
316
|
+
expect(callback).toHaveBeenCalledTimes(1); // no spurious re-emit
|
|
317
|
+
|
|
318
|
+
model.save_changes();
|
|
319
|
+
expect(mockComm.sendUpdate).not.toHaveBeenCalled();
|
|
320
|
+
});
|
|
266
321
|
});
|
|
267
322
|
|
|
268
323
|
describe("emitCustomMessage", () => {
|
|
@@ -53,7 +53,8 @@ export function getMarimoInternal<T extends ModelState>(
|
|
|
53
53
|
|
|
54
54
|
export class Model<T extends ModelState> implements AnyModel<T> {
|
|
55
55
|
#ANY_CHANGE_EVENT = "change";
|
|
56
|
-
|
|
56
|
+
/** Keys last written by the widget that the kernel hasn't seen yet. */
|
|
57
|
+
#dirtyFields: Set<keyof T>;
|
|
57
58
|
#data: T;
|
|
58
59
|
#comm: MarimoComm<T>;
|
|
59
60
|
#listeners: Record<string, Set<EventHandler> | undefined> = {};
|
|
@@ -70,7 +71,7 @@ export class Model<T extends ModelState> implements AnyModel<T> {
|
|
|
70
71
|
constructor(data: T, comm: MarimoComm<T>, signal?: AbortSignal) {
|
|
71
72
|
this.#data = data;
|
|
72
73
|
this.#comm = comm;
|
|
73
|
-
this.#dirtyFields = new
|
|
74
|
+
this.#dirtyFields = new Set();
|
|
74
75
|
if (signal) {
|
|
75
76
|
signal.addEventListener("abort", () => {
|
|
76
77
|
Logger.debug("[Model] Signal aborted, clearing all listeners");
|
|
@@ -140,7 +141,7 @@ export class Model<T extends ModelState> implements AnyModel<T> {
|
|
|
140
141
|
|
|
141
142
|
set<K extends keyof T>(key: K, value: T[K]): void {
|
|
142
143
|
this.#data = { ...this.#data, [key]: value };
|
|
143
|
-
this.#dirtyFields.
|
|
144
|
+
this.#dirtyFields.add(key);
|
|
144
145
|
this.#emit(`change:${key as K & string}`, value);
|
|
145
146
|
this.#emitAnyChange();
|
|
146
147
|
}
|
|
@@ -151,7 +152,7 @@ export class Model<T extends ModelState> implements AnyModel<T> {
|
|
|
151
152
|
}
|
|
152
153
|
// Only send the dirty fields, not the entire state.
|
|
153
154
|
const partialData = Object.fromEntries(
|
|
154
|
-
this.#dirtyFields.
|
|
155
|
+
[...this.#dirtyFields].map((key) => [key, this.#data[key]]),
|
|
155
156
|
) as Partial<T>;
|
|
156
157
|
|
|
157
158
|
// Clear the dirty fields to avoid sending again.
|
|
@@ -204,6 +205,15 @@ export class Model<T extends ModelState> implements AnyModel<T> {
|
|
|
204
205
|
}
|
|
205
206
|
}
|
|
206
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Apply a kernel-originated state update.
|
|
210
|
+
*
|
|
211
|
+
* Unlike `set()`, this never marks fields dirty — the kernel already
|
|
212
|
+
* has these values, so `save_changes()` must not echo them back.
|
|
213
|
+
*
|
|
214
|
+
* The kernel wins conflicts: a pending unsaved widget write to the same
|
|
215
|
+
* key is dropped, not replayed on top.
|
|
216
|
+
*/
|
|
207
217
|
#updateAndEmitDiffs(value: T) {
|
|
208
218
|
if (value == null) {
|
|
209
219
|
return;
|
|
@@ -211,9 +221,14 @@ export class Model<T extends ModelState> implements AnyModel<T> {
|
|
|
211
221
|
|
|
212
222
|
Object.keys(value).forEach((key) => {
|
|
213
223
|
const k = key as keyof T;
|
|
224
|
+
// Unconditional: guarding on inequality would leave a same-valued
|
|
225
|
+
// pending write dirty, and echo it back on save.
|
|
226
|
+
this.#dirtyFields.delete(k);
|
|
214
227
|
// Shallow equal since these can be large objects
|
|
215
228
|
if (this.#data[k] !== value[k]) {
|
|
216
|
-
this
|
|
229
|
+
this.#data = { ...this.#data, [k]: value[k] };
|
|
230
|
+
this.#emit(`change:${k as keyof T & string}`, value[k]);
|
|
231
|
+
this.#emitAnyChange();
|
|
217
232
|
}
|
|
218
233
|
});
|
|
219
234
|
}
|