@floegence/floe-webapp-core 0.36.11 → 0.36.13

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,230 +1,252 @@
1
- import { createSignal as _, createMemo as d, onCleanup as mt } from "solid-js";
2
- import { ArrowUp as Wt, Copy as xt, Trash as St } from "../icons/index.js";
3
- import { getTopZIndex as Ct, createContextMenuPosition as pt, createWorkbenchId as kt, findNearestWidget as Ft, clampScale as Xt, WORKBENCH_CANVAS_ZOOM_STEP as Z, WORKBENCH_CONTEXT_MENU_WIDTH_PX as bt, estimateContextMenuHeight as Mt } from "./workbenchHelpers.js";
4
- import { resolveWorkbenchWidgetDefinitions as Yt, getWidgetEntry as $, createWorkbenchFilterState as yt } from "./widgets/widgetRegistry.js";
5
- function Nt(s) {
6
- const [m, W] = _(null), [j, A] = _(null), [D, K] = _({ width: 0, height: 0 });
7
- let r = null, x = null;
8
- const a = s.state, h = d(() => a().widgets), u = d(() => a().viewport), L = d(() => a().locked), T = d(() => a().filters), k = d(() => a().selectedWidgetId), F = d(() => Ct(h())), U = d(() => `${Math.round(u().scale * 100)}%`), G = () => typeof s.widgetDefinitions == "function" ? s.widgetDefinitions() : s.widgetDefinitions, f = d(
9
- () => Yt(G())
10
- ), X = (t, e) => {
11
- const n = Number.isFinite(t) && t > 0 ? t : 0, i = Number.isFinite(e) && e > 0 ? e : 0, o = { width: n, height: i }, c = D();
12
- return c.width === n && c.height === i ? c : (K(o), o);
13
- }, N = () => {
14
- x?.disconnect(), x = null;
15
- }, w = () => r ? X(r.clientWidth, r.clientHeight) : X(0, 0), J = (t) => {
1
+ import { createSignal as V, createMemo as d, onCleanup as xt } from "solid-js";
2
+ import { ArrowUp as St, Copy as Ct, Trash as pt } from "../icons/index.js";
3
+ import { getTopZIndex as kt, createContextMenuPosition as Ft, createWorkbenchId as bt, createWorkbenchViewportCenteredOnWidget as L, findNearestWidget as It, clampScale as Mt, WORKBENCH_CANVAS_ZOOM_STEP as $, WORKBENCH_MIN_SCALE as Xt, createWorkbenchViewportFitForWidget as yt, WORKBENCH_CONTEXT_MENU_WIDTH_PX as Yt, estimateContextMenuHeight as vt } from "./workbenchHelpers.js";
4
+ import { resolveWorkbenchWidgetDefinitions as Ot, getWidgetEntry as j, createWorkbenchFilterState as zt } from "./widgets/widgetRegistry.js";
5
+ function qt(c) {
6
+ const [W, x] = V(null), [U, D] = V(null), [H, G] = V({ width: 0, height: 0 });
7
+ let r = null, S = null;
8
+ const l = c.state, w = d(() => l().widgets), u = d(() => l().viewport), J = d(() => l().locked), N = d(() => l().filters), F = d(() => l().selectedWidgetId), b = d(() => kt(w())), Q = d(() => `${Math.round(u().scale * 100)}%`), tt = () => typeof c.widgetDefinitions == "function" ? c.widgetDefinitions() : c.widgetDefinitions, m = d(
9
+ () => Ot(tt())
10
+ ), I = (t, e) => {
11
+ const n = Number.isFinite(t) && t > 0 ? t : 0, i = Number.isFinite(e) && e > 0 ? e : 0, o = { width: n, height: i }, s = H();
12
+ return s.width === n && s.height === i ? s : (G(o), o);
13
+ }, R = () => {
14
+ S?.disconnect(), S = null;
15
+ }, a = () => r ? I(r.clientWidth, r.clientHeight) : I(0, 0), et = (t) => {
16
16
  if (r === (t ?? null)) {
17
- w();
17
+ a();
18
18
  return;
19
19
  }
20
- N(), r = t ?? null, w(), !(!r || typeof ResizeObserver > "u") && (x = new ResizeObserver((e) => {
20
+ R(), r = t ?? null, a(), !(!r || typeof ResizeObserver > "u") && (S = new ResizeObserver((e) => {
21
21
  const n = e[0];
22
- X(
22
+ I(
23
23
  n?.contentRect.width ?? r?.clientWidth ?? 0,
24
24
  n?.contentRect.height ?? r?.clientHeight ?? 0
25
25
  );
26
- }), x.observe(r));
26
+ }), S.observe(r));
27
27
  };
28
- mt(() => {
29
- N(), r = null;
28
+ xt(() => {
29
+ R(), r = null;
30
30
  });
31
- const Q = (t) => {
32
- W({
31
+ const nt = (t) => {
32
+ x({
33
33
  clientX: t.clientX,
34
34
  clientY: t.clientY,
35
35
  worldX: t.worldX,
36
36
  worldY: t.worldY
37
37
  });
38
- }, tt = (t, e) => {
39
- S(e.id), W({
38
+ }, it = (t, e) => {
39
+ f(e.id), x({
40
40
  clientX: t.clientX,
41
41
  clientY: t.clientY,
42
42
  worldX: e.x,
43
43
  worldY: e.y,
44
44
  widgetId: e.id
45
45
  });
46
- }, g = () => W(null), et = (t) => a().widgets.find((e) => e.id === t) ?? null, b = (t) => a().widgets.find((e) => e.type === t) ?? null, R = d(() => {
47
- const t = m();
46
+ }, h = () => x(null), ot = (t) => l().widgets.find((e) => e.id === t) ?? null, M = (t) => l().widgets.find((e) => e.type === t) ?? null, T = d(() => {
47
+ const t = W();
48
48
  if (!t) return [];
49
49
  if (t.widgetId) {
50
- const e = h().find((i) => i.id === t.widgetId), n = [];
50
+ const e = w().find((i) => i.id === t.widgetId), n = [];
51
51
  return e && (n.push({
52
52
  id: "bring-to-front",
53
53
  kind: "action",
54
54
  label: "Bring to Front",
55
- icon: Wt,
55
+ icon: St,
56
56
  onSelect: () => {
57
- S(e.id), g();
57
+ f(e.id), h();
58
58
  }
59
59
  }), n.push({
60
60
  id: "duplicate",
61
61
  kind: "action",
62
62
  label: "Duplicate",
63
- icon: xt,
63
+ icon: Ct,
64
64
  onSelect: () => {
65
- V(e.type, e.x + 32, e.y + 32), g();
65
+ E(e.type, e.x + 32, e.y + 32), h();
66
66
  }
67
67
  })), n.push({ id: "separator-delete", kind: "separator" }), n.push({
68
68
  id: "delete",
69
69
  kind: "action",
70
70
  label: "Delete",
71
- icon: St,
71
+ icon: pt,
72
72
  destructive: !0,
73
73
  onSelect: () => {
74
- t.widgetId && y(t.widgetId), g();
74
+ t.widgetId && Y(t.widgetId), h();
75
75
  }
76
76
  }), n;
77
77
  }
78
- return f().map((e) => ({
78
+ return m().map((e) => ({
79
79
  id: `add-${e.type}`,
80
80
  kind: "action",
81
81
  label: `Add ${e.label}`,
82
82
  icon: e.icon,
83
83
  onSelect: () => {
84
- Y(e.type, t.worldX, t.worldY), g();
84
+ y(e.type, t.worldX, t.worldY), h();
85
85
  }
86
86
  }));
87
- }), nt = d(() => {
88
- const t = m();
87
+ }), ct = d(() => {
88
+ const t = W();
89
89
  if (!t) return;
90
- const e = R(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
- return pt({
90
+ const e = T(), n = e.filter((o) => o.kind === "action").length, i = e.filter((o) => o.kind === "separator").length;
91
+ return Ft({
92
92
  clientX: t.clientX,
93
93
  clientY: t.clientY,
94
- menuWidth: bt,
95
- menuHeight: Mt(n, i)
94
+ menuWidth: Yt,
95
+ menuHeight: vt(n, i)
96
96
  });
97
- }), M = (t, e, n) => {
98
- const i = $(t, f()), o = i.singleton ? b(t) : null;
97
+ }), X = (t, e, n) => {
98
+ const i = j(t, m()), o = i.singleton ? M(t) : null;
99
99
  if (o)
100
- return C(o, { centerViewport: !0 });
101
- const c = i.defaultSize, l = {
102
- id: kt(),
100
+ return p(o, { centerViewport: !0 });
101
+ const s = i.defaultSize, g = {
102
+ id: bt(),
103
103
  type: t,
104
104
  title: i.defaultTitle,
105
105
  x: e,
106
106
  y: n,
107
- width: c.width,
108
- height: c.height,
109
- z_index: F() + 1,
107
+ width: s.width,
108
+ height: s.height,
109
+ z_index: b() + 1,
110
110
  created_at_unix_ms: Date.now()
111
111
  };
112
- return s.setState((p) => ({
113
- ...p,
114
- widgets: [...p.widgets, l],
115
- selectedWidgetId: l.id
116
- })), l;
117
- }, Y = (t, e, n) => {
118
- const i = $(t, f()).defaultSize;
119
- return M(t, e - i.width / 2, n - i.height / 2);
120
- }, V = (t, e, n) => M(t, e, n), y = (t) => {
121
- s.setState((e) => ({
112
+ return c.setState((k) => ({
113
+ ...k,
114
+ widgets: [...k.widgets, g],
115
+ selectedWidgetId: g.id
116
+ })), g;
117
+ }, y = (t, e, n) => {
118
+ const i = j(t, m()).defaultSize;
119
+ return X(t, e - i.width / 2, n - i.height / 2);
120
+ }, E = (t, e, n) => X(t, e, n), Y = (t) => {
121
+ c.setState((e) => ({
122
122
  ...e,
123
123
  widgets: e.widgets.filter((n) => n.id !== t),
124
124
  selectedWidgetId: e.selectedWidgetId === t ? null : e.selectedWidgetId
125
125
  }));
126
- }, it = (t) => {
127
- A(t);
128
- }, S = (t) => {
129
- A(t);
130
- const e = F(), n = h().find((i) => i.id === t);
131
- n && n.z_index < e && s.setState((i) => ({
126
+ }, st = (t) => {
127
+ D(t);
128
+ }, f = (t) => {
129
+ D(t);
130
+ const e = b(), n = w().find((i) => i.id === t);
131
+ n && n.z_index < e && c.setState((i) => ({
132
132
  ...i,
133
133
  widgets: i.widgets.map(
134
134
  (o) => o.id === t ? { ...o, z_index: e + 1 } : o
135
135
  )
136
136
  }));
137
- }, ot = (t, e) => {
138
- s.setState((n) => ({
137
+ }, rt = (t, e) => {
138
+ c.setState((n) => ({
139
139
  ...n,
140
140
  widgets: n.widgets.map(
141
141
  (i) => i.id === t ? { ...i, x: e.x, y: e.y } : i
142
142
  )
143
143
  }));
144
- }, st = (t, e) => {
145
- s.setState((n) => ({
144
+ }, dt = (t, e) => {
145
+ c.setState((n) => ({
146
146
  ...n,
147
147
  widgets: n.widgets.map(
148
148
  (i) => i.id === t ? { ...i, width: e.width, height: e.height } : i
149
149
  )
150
150
  }));
151
- }, I = (t) => {
152
- s.setState((e) => ({ ...e, viewport: t }));
153
- }, H = (t) => {
154
- const e = u(), n = w(), i = (n.width / 2 - e.x) / e.scale, o = (n.height / 2 - e.y) / e.scale, c = Xt(
155
- t === "in" ? e.scale * Z : e.scale / Z
156
- ), l = {
157
- x: n.width / 2 - i * c,
158
- y: n.height / 2 - o * c,
159
- scale: c
151
+ }, v = (t) => {
152
+ c.setState((e) => ({ ...e, viewport: t }));
153
+ }, B = (t) => {
154
+ const e = u(), n = a(), i = (n.width / 2 - e.x) / e.scale, o = (n.height / 2 - e.y) / e.scale, s = Mt(
155
+ t === "in" ? e.scale * $ : e.scale / $
156
+ ), g = {
157
+ x: n.width / 2 - i * s,
158
+ y: n.height / 2 - o * s,
159
+ scale: s
160
160
  };
161
- I(l);
162
- }, ct = () => {
163
- s.setState((t) => ({ ...t, locked: !t.locked }));
164
- }, rt = (t) => {
165
- s.setState((e) => ({
161
+ v(g);
162
+ }, lt = () => {
163
+ c.setState((t) => ({ ...t, locked: !t.locked }));
164
+ }, at = (t) => {
165
+ c.setState((e) => ({
166
166
  ...e,
167
167
  filters: { ...e.filters, [t]: !e.filters[t] }
168
168
  }));
169
- }, dt = (t) => {
170
- s.setState((e) => {
169
+ }, gt = (t) => {
170
+ c.setState((e) => {
171
171
  const n = { ...e.filters };
172
172
  for (const i of Object.keys(n))
173
173
  n[i] = i === t;
174
174
  return { ...e, filters: n };
175
175
  });
176
- }, lt = () => {
177
- const t = yt(f());
178
- s.setState((e) => ({
176
+ }, ut = () => {
177
+ const t = zt(m());
178
+ c.setState((e) => ({
179
179
  ...e,
180
180
  filters: t
181
181
  }));
182
- }, E = (t) => {
183
- s.setState((e) => ({ ...e, selectedWidgetId: t }));
184
- }, at = () => {
185
- const t = w(), e = u();
182
+ }, C = (t) => {
183
+ c.setState((e) => ({ ...e, selectedWidgetId: t }));
184
+ }, q = () => {
185
+ c.setState(
186
+ (t) => t.selectedWidgetId === null ? t : { ...t, selectedWidgetId: null }
187
+ );
188
+ }, ht = () => {
189
+ const t = a(), e = u();
186
190
  return {
187
191
  worldX: t.width > 0 ? (t.width / 2 - e.x) / e.scale : 240,
188
192
  worldY: t.height > 0 ? (t.height / 2 - e.y) / e.scale : 180
189
193
  };
190
194
  };
191
- let q = 0;
192
- const ut = (t, e, n) => {
193
- const i = u(), o = i.x, c = i.y, l = i.scale, p = performance.now(), gt = 360, ht = ++q, ft = (v) => 1 - Math.pow(1 - v, 3), B = (v) => {
194
- if (ht !== q) return;
195
- const wt = v - p, P = Math.min(Math.max(wt / gt, 0), 1), O = ft(P);
196
- I({
197
- x: o + (t - o) * O,
198
- y: c + (e - c) * O,
199
- scale: l + (n - l) * O
200
- }), P < 1 && requestAnimationFrame(B);
195
+ let P = 0;
196
+ const O = (t) => {
197
+ const e = u(), n = e.x, i = e.y, o = e.scale, s = performance.now(), g = 360, k = ++P, mt = (_) => 1 - Math.pow(1 - _, 3), Z = (_) => {
198
+ if (k !== P) return;
199
+ const Wt = _ - s, K = Math.min(Math.max(Wt / g, 0), 1), A = mt(K);
200
+ v({
201
+ x: n + (t.x - n) * A,
202
+ y: i + (t.y - i) * A,
203
+ scale: o + (t.scale - o) * A
204
+ }), K < 1 && requestAnimationFrame(Z);
201
205
  };
202
- requestAnimationFrame(B);
206
+ requestAnimationFrame(Z);
203
207
  }, z = (t) => {
204
- const e = w();
205
- if (e.width === 0 || e.height === 0) return;
206
- const n = u(), i = e.width / 2 - (t.x + t.width / 2) * n.scale, o = e.height / 2 - (t.y + t.height / 2) * n.scale;
207
- ut(i, o, n.scale);
208
- }, C = (t, e = {}) => (E(t.id), S(t.id), e.centerViewport !== !1 && z(t), t);
208
+ const e = a();
209
+ e.width === 0 || e.height === 0 || O(L({
210
+ widget: t,
211
+ scale: u().scale,
212
+ frameWidth: e.width,
213
+ frameHeight: e.height
214
+ }));
215
+ }, ft = (t) => {
216
+ const e = a();
217
+ e.width === 0 || e.height === 0 || O(yt({
218
+ widget: t,
219
+ frameWidth: e.width,
220
+ frameHeight: e.height
221
+ }));
222
+ }, wt = (t) => {
223
+ const e = a();
224
+ e.width === 0 || e.height === 0 || O(L({
225
+ widget: t,
226
+ scale: Xt,
227
+ frameWidth: e.width,
228
+ frameHeight: e.height
229
+ }));
230
+ }, p = (t, e = {}) => (C(t.id), f(t.id), e.centerViewport !== !1 && z(t), t);
209
231
  return {
210
- widgets: h,
232
+ widgets: w,
211
233
  viewport: u,
212
- canvasFrameSize: D,
213
- locked: L,
214
- filters: T,
215
- selectedWidgetId: k,
216
- topZIndex: F,
217
- scaleLabel: U,
218
- optimisticFrontWidgetId: j,
219
- widgetDefinitions: f,
220
- setCanvasFrameRef: J,
234
+ canvasFrameSize: H,
235
+ locked: J,
236
+ filters: N,
237
+ selectedWidgetId: F,
238
+ topZIndex: b,
239
+ scaleLabel: Q,
240
+ optimisticFrontWidgetId: U,
241
+ widgetDefinitions: m,
242
+ setCanvasFrameRef: et,
221
243
  contextMenu: {
222
- state: m,
223
- items: R,
224
- position: nt,
225
- close: g,
244
+ state: W,
245
+ items: T,
246
+ position: ct,
247
+ close: h,
226
248
  retarget: (t) => {
227
- t.preventDefault(), t.stopPropagation(), W({
249
+ t.preventDefault(), t.stopPropagation(), x({
228
250
  clientX: t.clientX,
229
251
  clientY: t.clientY,
230
252
  worldX: 0,
@@ -233,54 +255,60 @@ function Nt(s) {
233
255
  }
234
256
  },
235
257
  canvas: {
236
- openCanvasContextMenu: Q,
237
- openWidgetContextMenu: tt,
238
- selectWidget: E,
239
- startOptimisticFront: it,
240
- commitFront: S,
241
- commitMove: ot,
242
- commitResize: st,
243
- commitViewport: I
258
+ openCanvasContextMenu: nt,
259
+ openWidgetContextMenu: it,
260
+ selectWidget: C,
261
+ clearSelection: q,
262
+ startOptimisticFront: st,
263
+ commitFront: f,
264
+ commitMove: rt,
265
+ commitResize: dt,
266
+ commitViewport: v
244
267
  },
245
268
  hud: {
246
- zoomIn: () => H("in"),
247
- zoomOut: () => H("out")
269
+ zoomIn: () => B("in"),
270
+ zoomOut: () => B("out")
248
271
  },
249
272
  lock: {
250
- toggle: ct
273
+ toggle: lt
251
274
  },
252
275
  filter: {
253
- toggle: rt,
254
- solo: dt,
255
- showAll: lt
276
+ toggle: at,
277
+ solo: gt,
278
+ showAll: ut
256
279
  },
257
280
  navigation: {
258
281
  handleArrowNavigation: (t) => {
259
- const e = Ft(
260
- h(),
261
- k(),
282
+ const e = It(
283
+ w(),
284
+ F(),
262
285
  t,
263
- T()
286
+ N()
264
287
  );
265
- e && C(e);
288
+ e && p(e);
266
289
  },
267
290
  centerOnWidget: z,
268
- focusWidget: C
291
+ focusWidget: p,
292
+ fitWidget: (t) => (C(t.id), f(t.id), ft(t), t),
293
+ overviewWidget: (t) => (C(t.id), f(t.id), wt(t), t)
294
+ },
295
+ selection: {
296
+ clear: q
269
297
  },
270
298
  widgetActions: {
271
299
  deleteSelected: () => {
272
- const t = k();
273
- t && y(t);
300
+ const t = F();
301
+ t && Y(t);
274
302
  },
275
- deleteWidget: y,
276
- addWidget: M,
277
- addWidgetAtCursor: Y,
278
- addWidgetCentered: V,
303
+ deleteWidget: Y,
304
+ addWidget: X,
305
+ addWidgetAtCursor: y,
306
+ addWidgetCentered: E,
279
307
  ensureWidget: (t, e) => {
280
- const n = b(t);
308
+ const n = M(t);
281
309
  if (n)
282
- return C(n, { centerViewport: e?.centerViewport ?? !0 });
283
- const i = at(), o = Y(
310
+ return p(n, { centerViewport: e?.centerViewport ?? !0 });
311
+ const i = ht(), o = y(
284
312
  t,
285
313
  e?.worldX ?? i.worldX,
286
314
  e?.worldY ?? i.worldY
@@ -289,18 +317,18 @@ function Nt(s) {
289
317
  }
290
318
  },
291
319
  queries: {
292
- findWidgetByType: b,
293
- findWidgetById: et
320
+ findWidgetByType: M,
321
+ findWidgetById: ot
294
322
  },
295
323
  handleCloseRequest: () => {
296
- if (m()) {
297
- g();
324
+ if (W()) {
325
+ h();
298
326
  return;
299
327
  }
300
- s.onClose();
328
+ c.onClose();
301
329
  }
302
330
  };
303
331
  }
304
332
  export {
305
- Nt as useWorkbenchModel
333
+ qt as useWorkbenchModel
306
334
  };
@@ -0,0 +1,5 @@
1
+ export declare const WORKBENCH_CONTEXT_MENU_ATTR = "data-floe-workbench-context-menu";
2
+ export declare function installWorkbenchContextMenuDismissListeners(options: {
3
+ ownerWindow: Window;
4
+ onDismiss: () => void;
5
+ }): () => void;
@@ -0,0 +1,29 @@
1
+ const i = "data-floe-workbench-context-menu";
2
+ function s(e) {
3
+ return !e || typeof e != "object" ? !1 : e.dataset?.floeWorkbenchContextMenu === "true";
4
+ }
5
+ function d(e) {
6
+ if (typeof e.composedPath == "function") {
7
+ for (const t of e.composedPath())
8
+ if (s(t))
9
+ return !0;
10
+ }
11
+ const n = e.target;
12
+ return typeof Element < "u" && n instanceof Element ? n.closest(`[${i}="true"]`) !== null : !1;
13
+ }
14
+ function c(e) {
15
+ const n = (o) => {
16
+ d(o) || e.onDismiss();
17
+ }, t = (o) => {
18
+ o.key === "Escape" && e.onDismiss();
19
+ }, r = () => {
20
+ e.onDismiss();
21
+ };
22
+ return e.ownerWindow.addEventListener("pointerdown", n, !0), e.ownerWindow.addEventListener("keydown", t, !0), e.ownerWindow.addEventListener("resize", r), e.ownerWindow.addEventListener("scroll", r, !0), () => {
23
+ e.ownerWindow.removeEventListener("pointerdown", n, !0), e.ownerWindow.removeEventListener("keydown", t, !0), e.ownerWindow.removeEventListener("resize", r), e.ownerWindow.removeEventListener("scroll", r, !0);
24
+ };
25
+ }
26
+ export {
27
+ i as WORKBENCH_CONTEXT_MENU_ATTR,
28
+ c as installWorkbenchContextMenuDismissListeners
29
+ };
@@ -23,6 +23,23 @@ export declare function sanitizeWorkbenchState(input: unknown, options?: Sanitiz
23
23
  export declare function createDefaultWorkbenchState(widgetDefinitions?: readonly WorkbenchWidgetDefinition[]): WorkbenchState;
24
24
  export declare const WORKBENCH_CANVAS_ZOOM_STEP = 1.18;
25
25
  export declare const WORKBENCH_CONTEXT_MENU_WIDTH_PX = 200;
26
+ export declare const WORKBENCH_MIN_SCALE = 0.45;
27
+ export declare const WORKBENCH_MAX_SCALE = 2.2;
28
+ export declare const WORKBENCH_VIEWPORT_FIT_PADDING_PX = 48;
29
+ export declare function createWorkbenchViewportCenteredOnWidget(options: {
30
+ widget: WorkbenchWidgetItem;
31
+ scale: number;
32
+ frameWidth: number;
33
+ frameHeight: number;
34
+ }): WorkbenchViewport;
35
+ export declare function createWorkbenchViewportFitForWidget(options: {
36
+ widget: WorkbenchWidgetItem;
37
+ frameWidth: number;
38
+ frameHeight: number;
39
+ minScale?: number;
40
+ maxScale?: number;
41
+ paddingPx?: number;
42
+ }): WorkbenchViewport;
26
43
  export interface WorkbenchRenderLayerMap {
27
44
  byWidgetId: ReadonlyMap<string, number>;
28
45
  topRenderLayer: number;