@marimo-team/islands 0.20.3-dev80 → 0.20.3-dev83
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
|
@@ -70347,7 +70347,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
|
|
|
70347
70347
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
70348
70348
|
}
|
|
70349
70349
|
}
|
|
70350
|
-
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-
|
|
70350
|
+
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.3-dev83"), showCodeInRunModeAtom = atom(true);
|
|
70351
70351
|
atom(null);
|
|
70352
70352
|
var import_compiler_runtime$88 = require_compiler_runtime();
|
|
70353
70353
|
function useKeydownOnElement(e, r) {
|
|
@@ -78866,7 +78866,7 @@ ${c}
|
|
|
78866
78866
|
resizeHandleEnabled: "data-panel-resize-handle-enabled",
|
|
78867
78867
|
resizeHandleId: "data-panel-resize-handle-id",
|
|
78868
78868
|
resizeHandleState: "data-resize-handle-state"
|
|
78869
|
-
}, PRECISION = 10, useIsomorphicLayoutEffect
|
|
78869
|
+
}, PRECISION = 10, useIsomorphicLayoutEffect = import_react.useLayoutEffect, useId$8 = import_react.useId, wrappedUseId = typeof useId$8 == "function" ? useId$8 : () => null, counter = 0;
|
|
78870
78870
|
function useUniqueId(e = null) {
|
|
78871
78871
|
let r = wrappedUseId(), c = (0, import_react.useRef)(e || r || null);
|
|
78872
78872
|
return c.current === null && (c.current = "" + counter++), e ?? c.current;
|
|
@@ -78893,12 +78893,12 @@ ${c}
|
|
|
78893
78893
|
});
|
|
78894
78894
|
(0, import_react.useRef)({
|
|
78895
78895
|
didLogMissingDefaultSizeWarning: false
|
|
78896
|
-
}), useIsomorphicLayoutEffect
|
|
78896
|
+
}), useIsomorphicLayoutEffect(() => {
|
|
78897
78897
|
let { callbacks: e2, constraints: r2 } = qY.current, _2 = {
|
|
78898
78898
|
...r2
|
|
78899
78899
|
};
|
|
78900
78900
|
qY.current.id = KY, qY.current.idIsFromProps = v !== void 0, qY.current.order = M, e2.onCollapse = w, e2.onExpand = E, e2.onResize = O, r2.collapsedSize = c, r2.collapsible = d, r2.defaultSize = f, r2.maxSize = y, r2.minSize = S, (_2.collapsedSize !== r2.collapsedSize || _2.collapsible !== r2.collapsible || _2.maxSize !== r2.maxSize || _2.minSize !== r2.minSize) && HY(qY.current, _2);
|
|
78901
|
-
}), useIsomorphicLayoutEffect
|
|
78901
|
+
}), useIsomorphicLayoutEffect(() => {
|
|
78902
78902
|
let e2 = qY.current;
|
|
78903
78903
|
return UY(e2), () => {
|
|
78904
78904
|
GY(e2);
|
|
@@ -79364,7 +79364,7 @@ ${c}
|
|
|
79364
79364
|
function useWindowSplitterPanelGroupBehavior({ committedValuesRef: e, eagerValuesRef: r, groupId: c, layout: d, panelDataArray: f, panelGroupElement: _, setLayout: v }) {
|
|
79365
79365
|
(0, import_react.useRef)({
|
|
79366
79366
|
didWarnAboutMissingResizeHandle: false
|
|
79367
|
-
}), useIsomorphicLayoutEffect
|
|
79367
|
+
}), useIsomorphicLayoutEffect(() => {
|
|
79368
79368
|
if (!_) return;
|
|
79369
79369
|
let e2 = getResizeHandleElementsForGroup(c, _);
|
|
79370
79370
|
for (let r2 = 0; r2 < f.length - 1; r2++) {
|
|
@@ -79662,7 +79662,7 @@ ${c}
|
|
|
79662
79662
|
});
|
|
79663
79663
|
areEqual(c2, f2) || (IY(f2), HY.current.layout = f2, r2 && r2(f2), callPanelCallbacks(d2, f2, RY.current));
|
|
79664
79664
|
}
|
|
79665
|
-
}), []), useIsomorphicLayoutEffect
|
|
79665
|
+
}), []), useIsomorphicLayoutEffect(() => {
|
|
79666
79666
|
VY.current.autoSaveId = e, VY.current.direction = d, VY.current.dragState = z, VY.current.id = M, VY.current.onLayout = v, VY.current.storage = S;
|
|
79667
79667
|
}), useWindowSplitterPanelGroupBehavior({
|
|
79668
79668
|
committedValuesRef: VY,
|
|
@@ -79752,7 +79752,7 @@ ${c}
|
|
|
79752
79752
|
}, [
|
|
79753
79753
|
LY
|
|
79754
79754
|
]);
|
|
79755
|
-
useIsomorphicLayoutEffect
|
|
79755
|
+
useIsomorphicLayoutEffect(() => {
|
|
79756
79756
|
if (HY.current.panelDataArrayChanged) {
|
|
79757
79757
|
HY.current.panelDataArrayChanged = false;
|
|
79758
79758
|
let { autoSaveId: e2, onLayout: r2, storage: c2 } = VY.current, { layout: d2, panelDataArray: f2 } = HY.current, _2 = null;
|
|
@@ -79769,7 +79769,7 @@ ${c}
|
|
|
79769
79769
|
});
|
|
79770
79770
|
areEqual(d2, v2) || (IY(v2), HY.current.layout = v2, r2 && r2(v2), callPanelCallbacks(f2, v2, RY.current));
|
|
79771
79771
|
}
|
|
79772
|
-
}), useIsomorphicLayoutEffect
|
|
79772
|
+
}), useIsomorphicLayoutEffect(() => {
|
|
79773
79773
|
let e2 = HY.current;
|
|
79774
79774
|
return () => {
|
|
79775
79775
|
e2.layout = [];
|
|
@@ -79960,7 +79960,7 @@ ${c}
|
|
|
79960
79960
|
let { direction: LY, groupId: RY, registerResizeHandle: zY, startDragging: BY, stopDragging: VY, panelGroupElement: HY } = IY, UY = useUniqueId(f), [WY, GY] = (0, import_react.useState)("inactive"), [KY, qY] = (0, import_react.useState)(false), [JY, YY] = (0, import_react.useState)(null), XY = (0, import_react.useRef)({
|
|
79961
79961
|
state: WY
|
|
79962
79962
|
});
|
|
79963
|
-
useIsomorphicLayoutEffect
|
|
79963
|
+
useIsomorphicLayoutEffect(() => {
|
|
79964
79964
|
XY.current.state = WY;
|
|
79965
79965
|
}), (0, import_react.useEffect)(() => {
|
|
79966
79966
|
if (c) YY(null);
|
|
@@ -91520,18 +91520,6 @@ ${c}
|
|
|
91520
91520
|
function withoutNaN(e) {
|
|
91521
91521
|
return e == null || Number.isNaN(e) ? null : e;
|
|
91522
91522
|
}
|
|
91523
|
-
var useIsomorphicLayoutEffect = typeof window < "u" && window.document !== void 0 && window.document.createElement !== void 0 ? import_react.useLayoutEffect : import_react.useEffect;
|
|
91524
|
-
function useEvent(e) {
|
|
91525
|
-
let r = (0, import_react.useRef)(e);
|
|
91526
|
-
return useIsomorphicLayoutEffect(() => {
|
|
91527
|
-
r.current = e;
|
|
91528
|
-
}), (0, import_react.useCallback)(function() {
|
|
91529
|
-
var e2 = [
|
|
91530
|
-
...arguments
|
|
91531
|
-
];
|
|
91532
|
-
return r.current == null ? void 0 : r.current(...e2);
|
|
91533
|
-
}, []);
|
|
91534
|
-
}
|
|
91535
91523
|
const MessageSchema = object$1({
|
|
91536
91524
|
content: union([
|
|
91537
91525
|
object$1({
|
|
@@ -91585,10 +91573,8 @@ ${c}
|
|
|
91585
91573
|
this.buffer = [];
|
|
91586
91574
|
}
|
|
91587
91575
|
getAndClear() {
|
|
91588
|
-
let e =
|
|
91589
|
-
|
|
91590
|
-
];
|
|
91591
|
-
return this.clear(), e;
|
|
91576
|
+
let e = this.buffer;
|
|
91577
|
+
return this.buffer = [], e;
|
|
91592
91578
|
}
|
|
91593
91579
|
};
|
|
91594
91580
|
const PanelPlugin = createPlugin("marimo-panel").withData(object$1({
|
|
@@ -91609,16 +91595,22 @@ ${c}
|
|
|
91609
91595
|
return window.Bokeh != null;
|
|
91610
91596
|
}
|
|
91611
91597
|
var PanelSlot = (e) => {
|
|
91612
|
-
let { data: r, functions: c, host: d } = e, { extension: f, docs_json: _, render_json: v } = r, y = (0, import_react.useRef)(null), S = (0, import_react.useRef)(null), w = (0, import_react.useRef)(null), [E, O] = (0, import_react.useState)(false), [M, I] = (0, import_react.useState)(null), z =
|
|
91613
|
-
|
|
91614
|
-
|
|
91615
|
-
|
|
91616
|
-
|
|
91617
|
-
|
|
91618
|
-
|
|
91619
|
-
|
|
91620
|
-
});
|
|
91621
|
-
|
|
91598
|
+
let { data: r, functions: c, host: d } = e, { extension: f, docs_json: _, render_json: v } = r, y = (0, import_react.useRef)(null), S = (0, import_react.useRef)(null), w = (0, import_react.useRef)(null), [E, O] = (0, import_react.useState)(false), [M, I] = (0, import_react.useState)(null), z = (0, import_react.useRef)(c);
|
|
91599
|
+
z.current = c;
|
|
91600
|
+
let G = (0, import_react.useCallback)(() => {
|
|
91601
|
+
if (!q.current) return;
|
|
91602
|
+
let e2 = q.current.getAndClear();
|
|
91603
|
+
if (e2.length === 0) return;
|
|
91604
|
+
let r2 = e2.at(0);
|
|
91605
|
+
if (!isDocumentEvent(r2)) return;
|
|
91606
|
+
let c2 = r2.document, d2 = e2.filter((e3) => isDocumentEvent(e3) && e3.document === c2), f2 = c2.create_json_patch(d2), _2 = window.Bokeh.protocol.Message.create("PATCH-DOC", {}, f2), v2 = [];
|
|
91607
|
+
_2.content = extractBuffers(_2.content, v2), z.current.send_to_widget({
|
|
91608
|
+
message: _2,
|
|
91609
|
+
buffers: v2
|
|
91610
|
+
}).catch((e3) => {
|
|
91611
|
+
Logger.warn("Failed to send Panel event to backend", e3);
|
|
91612
|
+
});
|
|
91613
|
+
}, []), q = (0, import_react.useRef)(new EventBuffer(G));
|
|
91622
91614
|
return (0, import_react.useEffect)(() => {
|
|
91623
91615
|
if (isBokehLoaded()) {
|
|
91624
91616
|
O(true);
|
|
@@ -91637,20 +91629,25 @@ ${c}
|
|
|
91637
91629
|
O
|
|
91638
91630
|
]), useEventListener(d, MarimoIncomingMessageEvent.TYPE, (e2) => {
|
|
91639
91631
|
if (e2.detail.message == null) return;
|
|
91640
|
-
let r2 = MessageSchema.parse(e2.detail.message), c2 = e2.detail.buffers, d2 = w.current
|
|
91641
|
-
if (!d2
|
|
91642
|
-
let
|
|
91643
|
-
if (
|
|
91644
|
-
|
|
91632
|
+
let r2 = MessageSchema.parse(e2.detail.message), c2 = e2.detail.buffers, d2 = w.current;
|
|
91633
|
+
if (!d2) return;
|
|
91634
|
+
let f2 = r2.content;
|
|
91635
|
+
if (f2 !== null && typeof r2.content != "string") {
|
|
91636
|
+
q.current && q.current.size() > 0 && G();
|
|
91645
91637
|
return;
|
|
91646
91638
|
}
|
|
91639
|
+
let _2 = getDoc(S.current);
|
|
91640
|
+
if (!_2) return;
|
|
91647
91641
|
if (c2 && c2.length > 0) {
|
|
91648
91642
|
let e3 = c2[0];
|
|
91649
91643
|
e3 instanceof ArrayBuffer ? d2.consume(e3) : e3.buffer instanceof ArrayBuffer && d2.consume(e3.buffer);
|
|
91650
|
-
} else if (
|
|
91644
|
+
} else if (f2 && typeof f2 == "string") d2.consume(f2);
|
|
91651
91645
|
else return;
|
|
91652
91646
|
let v2 = d2.message;
|
|
91653
|
-
v2 != null && Object.keys(v2.content).length > 0 && (v2.content.events !== void 0 && (v2.content.events = v2.content.events.filter((e3) =>
|
|
91647
|
+
v2 != null && Object.keys(v2.content).length > 0 && (v2.content.events !== void 0 && (v2.content.events = v2.content.events.filter((e3) => {
|
|
91648
|
+
var _a3;
|
|
91649
|
+
return ((_a3 = e3 == null ? void 0 : e3.model) == null ? void 0 : _a3.id) && _2._all_models.has(e3.model.id);
|
|
91650
|
+
})), _2.apply_json_patch(v2.content, v2.buffers));
|
|
91654
91651
|
}), (0, import_react.useEffect)(() => {
|
|
91655
91652
|
let e2 = Object.keys(_)[0];
|
|
91656
91653
|
!E || M === e2 || (async () => {
|
|
@@ -91661,16 +91658,18 @@ ${c}
|
|
|
91661
91658
|
for (let e3 of Object.keys(v.roots)) {
|
|
91662
91659
|
let c3 = v.roots[e3];
|
|
91663
91660
|
if (y.current) {
|
|
91664
|
-
let
|
|
91665
|
-
r2.roots[e3] =
|
|
91661
|
+
let d3 = y.current.querySelector(`#${c3}`);
|
|
91662
|
+
r2.roots[e3] = d3;
|
|
91666
91663
|
}
|
|
91667
91664
|
}
|
|
91668
91665
|
let c2 = Object.keys(r2.roots)[0];
|
|
91669
91666
|
await window.Bokeh.embed.embed_items_notebook(_, [
|
|
91670
91667
|
r2
|
|
91671
|
-
]), S.current =
|
|
91668
|
+
]), S.current = c2;
|
|
91669
|
+
let d2 = window.Bokeh.index.get_by_id(c2).model.document;
|
|
91670
|
+
w.current = new window.Bokeh.protocol.Receiver(), d2.on_change((e3) => {
|
|
91672
91671
|
var _a3;
|
|
91673
|
-
|
|
91672
|
+
isSyncEvent(e3) && e3.sync && ((_a3 = q.current) == null ? void 0 : _a3.add(e3));
|
|
91674
91673
|
}), I(e2);
|
|
91675
91674
|
})();
|
|
91676
91675
|
}, [
|
|
@@ -91690,7 +91689,22 @@ ${c}
|
|
|
91690
91689
|
})
|
|
91691
91690
|
}, e2))
|
|
91692
91691
|
});
|
|
91693
|
-
}
|
|
91692
|
+
};
|
|
91693
|
+
function getDoc(e) {
|
|
91694
|
+
if (!e) return null;
|
|
91695
|
+
try {
|
|
91696
|
+
return window.Bokeh.index.get_by_id(e).model.document;
|
|
91697
|
+
} catch (e2) {
|
|
91698
|
+
return Logger.warn("Failed to get Bokeh document", e2), null;
|
|
91699
|
+
}
|
|
91700
|
+
}
|
|
91701
|
+
function isSyncEvent(e) {
|
|
91702
|
+
return !!e && typeof e == "object" && "sync" in e;
|
|
91703
|
+
}
|
|
91704
|
+
function isDocumentEvent(e) {
|
|
91705
|
+
return !!e && typeof e == "object" && "document" in e;
|
|
91706
|
+
}
|
|
91707
|
+
var defaultOptions = {
|
|
91694
91708
|
removeOnUnmount: false
|
|
91695
91709
|
};
|
|
91696
91710
|
function useScript(e, r = defaultOptions) {
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
5
|
import { z } from "zod";
|
|
7
6
|
import { MarimoIncomingMessageEvent } from "@/core/dom/events";
|
|
8
7
|
import {
|
|
@@ -12,13 +11,14 @@ import {
|
|
|
12
11
|
import { createPlugin } from "@/plugins/core/builder";
|
|
13
12
|
import { rpc } from "@/plugins/core/rpc";
|
|
14
13
|
import type { IPluginProps } from "@/plugins/types";
|
|
14
|
+
import { Logger } from "@/utils/Logger";
|
|
15
15
|
import { EventBuffer, extractBuffers, MessageSchema } from "./utils";
|
|
16
16
|
|
|
17
17
|
interface BokehDocument {
|
|
18
18
|
create_json_patch: (events: unknown[]) => unknown;
|
|
19
19
|
apply_json_patch: (content: unknown, buffers: ArrayBuffer[]) => void;
|
|
20
20
|
on_change: (callback: (event: unknown) => void) => void;
|
|
21
|
-
_all_models:
|
|
21
|
+
_all_models: Map<string, unknown>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface RenderItems {
|
|
@@ -77,8 +77,8 @@ type T = Record<string, unknown>;
|
|
|
77
77
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
78
78
|
type PluginFunctions = {
|
|
79
79
|
send_to_widget: <T>(req: {
|
|
80
|
-
message?:
|
|
81
|
-
buffers?:
|
|
80
|
+
message?: unknown;
|
|
81
|
+
buffers?: unknown;
|
|
82
82
|
}) => Promise<null | undefined>;
|
|
83
83
|
};
|
|
84
84
|
|
|
@@ -114,27 +114,52 @@ const PanelSlot = (props: Props) => {
|
|
|
114
114
|
const { data, functions, host } = props;
|
|
115
115
|
const { extension, docs_json: docsJson, render_json: renderJson } = data;
|
|
116
116
|
const ref = useRef<HTMLDivElement>(null);
|
|
117
|
-
const
|
|
117
|
+
const rootModelIdRef = useRef<string | null>(null);
|
|
118
118
|
const receiverRef = useRef<InstanceType<
|
|
119
119
|
typeof window.Bokeh.protocol.Receiver
|
|
120
120
|
> | null>(null);
|
|
121
121
|
const [loaded, setLoaded] = useState<boolean>(false);
|
|
122
122
|
const [rendered, setRendered] = useState<string | null>(null);
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
// Store functions in a ref so the callback captured by EventBuffer stays current
|
|
125
|
+
const functionsRef = useRef(functions);
|
|
126
|
+
functionsRef.current = functions;
|
|
127
|
+
|
|
128
|
+
const processEvents = useCallback(() => {
|
|
129
|
+
if (!eventBufferRef.current) {
|
|
126
130
|
return;
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
const events = eventBufferRef.current.getAndClear();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
if (events.length === 0) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Use the event's own document — it is always current, even when
|
|
139
|
+
// DynamicMap/HoloViews has replaced the document after embedding.
|
|
140
|
+
const firstEvent = events.at(0);
|
|
141
|
+
if (!isDocumentEvent(firstEvent)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const doc = firstEvent.document;
|
|
145
|
+
|
|
146
|
+
// Keep only events that belong to this document
|
|
147
|
+
const sameDocEvents = events.filter(
|
|
148
|
+
(ev) => isDocumentEvent(ev) && ev.document === doc,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const patch = doc.create_json_patch(sameDocEvents);
|
|
152
|
+
const message = window.Bokeh.protocol.Message.create(
|
|
153
|
+
"PATCH-DOC",
|
|
154
|
+
{},
|
|
155
|
+
patch,
|
|
156
|
+
);
|
|
134
157
|
const buffers: ArrayBuffer[] = [];
|
|
135
158
|
message.content = extractBuffers(message.content, buffers);
|
|
136
|
-
|
|
137
|
-
|
|
159
|
+
functionsRef.current.send_to_widget({ message, buffers }).catch((error) => {
|
|
160
|
+
Logger.warn("Failed to send Panel event to backend", error);
|
|
161
|
+
});
|
|
162
|
+
}, []);
|
|
138
163
|
|
|
139
164
|
const eventBufferRef = useRef<EventBuffer<unknown> | null>(
|
|
140
165
|
new EventBuffer(processEvents),
|
|
@@ -178,9 +203,8 @@ const PanelSlot = (props: Props) => {
|
|
|
178
203
|
const message = MessageSchema.parse(e.detail.message);
|
|
179
204
|
const buffers = e.detail.buffers;
|
|
180
205
|
const receiver = receiverRef.current;
|
|
181
|
-
const doc = docRef.current;
|
|
182
206
|
|
|
183
|
-
if (!receiver
|
|
207
|
+
if (!receiver) {
|
|
184
208
|
return;
|
|
185
209
|
}
|
|
186
210
|
|
|
@@ -193,6 +217,11 @@ const PanelSlot = (props: Props) => {
|
|
|
193
217
|
return;
|
|
194
218
|
}
|
|
195
219
|
|
|
220
|
+
const doc = getDoc(rootModelIdRef.current);
|
|
221
|
+
if (!doc) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
196
225
|
if (buffers && buffers.length > 0) {
|
|
197
226
|
// Check if we already have an ArrayBuffer
|
|
198
227
|
const buffer = buffers[0];
|
|
@@ -212,7 +241,7 @@ const PanelSlot = (props: Props) => {
|
|
|
212
241
|
if (commMessage != null && Object.keys(commMessage.content).length > 0) {
|
|
213
242
|
if (commMessage.content.events !== undefined) {
|
|
214
243
|
commMessage.content.events = commMessage.content.events.filter(
|
|
215
|
-
(e
|
|
244
|
+
(e) => e?.model?.id && doc._all_models.has(e.model.id),
|
|
216
245
|
);
|
|
217
246
|
}
|
|
218
247
|
doc.apply_json_patch(commMessage.content, commMessage.buffers);
|
|
@@ -243,9 +272,17 @@ const PanelSlot = (props: Props) => {
|
|
|
243
272
|
}
|
|
244
273
|
const modelId = Object.keys(renderItem.roots)[0];
|
|
245
274
|
await window.Bokeh.embed.embed_items_notebook(docsJson, [renderItem]);
|
|
246
|
-
|
|
275
|
+
rootModelIdRef.current = modelId;
|
|
276
|
+
const doc = window.Bokeh.index.get_by_id(modelId).model.document;
|
|
247
277
|
receiverRef.current = new window.Bokeh.protocol.Receiver();
|
|
248
|
-
|
|
278
|
+
doc.on_change((event) => {
|
|
279
|
+
// Bokeh tags server-applied patch events with sync=false via
|
|
280
|
+
// model.setv({...}, {sync: false}) inside apply_json_patch.
|
|
281
|
+
// Only forward user-initiated events (sync=true, the default).
|
|
282
|
+
if (isSyncEvent(event) && event.sync) {
|
|
283
|
+
eventBufferRef.current?.add(event);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
249
286
|
setRendered(docId);
|
|
250
287
|
};
|
|
251
288
|
|
|
@@ -263,4 +300,29 @@ const PanelSlot = (props: Props) => {
|
|
|
263
300
|
);
|
|
264
301
|
};
|
|
265
302
|
|
|
303
|
+
// Re-fetch the live document from the Bokeh index. DynamicMap/HoloViews
|
|
304
|
+
// may replace the document after initial embedding, so a stale ref would
|
|
305
|
+
// cause "Cannot create a patch using events from a different document".
|
|
306
|
+
function getDoc(id: string | null): BokehDocument | null {
|
|
307
|
+
if (!id) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
return window.Bokeh.index.get_by_id(id).model.document;
|
|
312
|
+
} catch (error) {
|
|
313
|
+
Logger.warn("Failed to get Bokeh document", error);
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function isSyncEvent(x: unknown): x is { sync: boolean } {
|
|
319
|
+
const isObject = !!x && typeof x === "object";
|
|
320
|
+
return isObject && "sync" in x;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function isDocumentEvent(x: unknown): x is { document: BokehDocument } {
|
|
324
|
+
const isObject = !!x && typeof x === "object";
|
|
325
|
+
return isObject && "document" in x;
|
|
326
|
+
}
|
|
327
|
+
|
|
266
328
|
type Props = IPluginProps<T, PanelData, PluginFunctions>;
|