@graphvideo/workbench 1.0.0

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.
Files changed (39) hide show
  1. package/dist/commands/commandRegistry.d.ts +15 -0
  2. package/dist/context/WorkbenchHostContext.d.ts +26 -0
  3. package/dist/context/types.d.ts +26 -0
  4. package/dist/context/workbenchContextStore.d.ts +26 -0
  5. package/dist/dock/AreaShell.d.ts +9 -0
  6. package/dist/dock/Workspace.d.ts +5 -0
  7. package/dist/dock/floatingWindow.d.ts +7 -0
  8. package/dist/dock/layout.d.ts +14 -0
  9. package/dist/dock/splitResizeGesture.d.ts +23 -0
  10. package/dist/dock/workspaceTypes.d.ts +28 -0
  11. package/dist/elements/ExtensionSlot.d.ts +5 -0
  12. package/dist/elements/dispose.d.ts +3 -0
  13. package/dist/elements/elementLoader.d.ts +45 -0
  14. package/dist/elements/manifest.d.ts +2 -0
  15. package/dist/elements/runtimeManager.d.ts +28 -0
  16. package/dist/elements/sourceCatalog.d.ts +24 -0
  17. package/dist/elements/types.d.ts +133 -0
  18. package/dist/index.d.ts +36 -0
  19. package/dist/index.mjs +1809 -0
  20. package/dist/plugins/pluginManager.d.ts +20 -0
  21. package/dist/preferences/themePreferences.d.ts +9 -0
  22. package/dist/preferences/typographyPreferences.d.ts +16 -0
  23. package/dist/registry/eventRegistry.d.ts +29 -0
  24. package/dist/registry/extensionRegistry.d.ts +11 -0
  25. package/dist/registry/ownedRegistry.d.ts +21 -0
  26. package/dist/registry/panelRegistry.d.ts +13 -0
  27. package/dist/registry/serviceRegistry.d.ts +28 -0
  28. package/dist/registry/stateRegistry.d.ts +16 -0
  29. package/dist/ui/AudioPlayer.d.ts +5 -0
  30. package/dist/ui/FloatingScrollbars.d.ts +9 -0
  31. package/dist/ui/InlineSelect.d.ts +16 -0
  32. package/dist/ui/LargeTextEditorDialog.d.ts +14 -0
  33. package/dist/workbench.css +2 -0
  34. package/dist/workspaces/WorkspacePages.d.ts +5 -0
  35. package/dist/workspaces/WorkspaceTabs.d.ts +2 -0
  36. package/dist/workspaces/layoutPreferences.d.ts +10 -0
  37. package/dist/workspaces/manifest.d.ts +25 -0
  38. package/dist/workspaces/workspaceCommands.d.ts +16 -0
  39. package/package.json +35 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1809 @@
1
+ import * as e from "react";
2
+ import { createContext as t, createElement as n, memo as r, useCallback as i, useContext as a, useEffect as o, useId as s, useLayoutEffect as c, useRef as l, useState as u, useSyncExternalStore as d } from "react";
3
+ import { ChevronDown as f, ChevronsUp as p, Columns2 as m, Maximize2 as h, Minimize2 as g, Pause as _, PictureInPicture2 as v, Play as y, Rows2 as b, X as x } from "lucide-react";
4
+ import { createPortal as S } from "react-dom";
5
+ import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
6
+ //#region workbench/src/commands/commandRegistry.ts
7
+ var E = class {
8
+ handlers = /* @__PURE__ */ new Map();
9
+ register(e, t, n = "core") {
10
+ let r = this.handlers.get(e);
11
+ if (r && r.owner !== n) throw Error(`Command ID conflict: ${e} (${r.owner} / ${n})`);
12
+ this.handlers.set(e, {
13
+ owner: n,
14
+ handler: t
15
+ });
16
+ }
17
+ assertCanReplace(e, t) {
18
+ let n = /* @__PURE__ */ new Set();
19
+ for (let r of t) {
20
+ if (n.has(r.id)) throw Error(`Command ID conflict: ${r.id} (${e})`);
21
+ n.add(r.id);
22
+ let t = this.handlers.get(r.id);
23
+ if (t && t.owner !== e) throw Error(`Command ID conflict: ${r.id} (${t.owner} / ${e})`);
24
+ }
25
+ }
26
+ replaceOwner(e, t) {
27
+ this.assertCanReplace(e, t), this.unregisterOwner(e), t.forEach((t) => this.handlers.set(t.id, {
28
+ owner: e,
29
+ handler: t.handler
30
+ }));
31
+ }
32
+ unregisterOwner(e) {
33
+ for (let [t, n] of this.handlers) n.owner === e && this.handlers.delete(t);
34
+ }
35
+ execute(e, t) {
36
+ let n = this.handlers.get(e);
37
+ if (!n) throw Error(`Unknown command: ${e}`);
38
+ return n.handler(t);
39
+ }
40
+ };
41
+ //#endregion
42
+ //#region workbench/src/context/workbenchContextStore.ts
43
+ function D(e) {
44
+ try {
45
+ return structuredClone(e);
46
+ } catch {
47
+ return e;
48
+ }
49
+ }
50
+ var O = class {
51
+ cells = /* @__PURE__ */ new Map();
52
+ getOrCreateCell(e, t = {}) {
53
+ let n = this.cellKey(e, t), r = this.cells.get(n);
54
+ if (!r) {
55
+ let t = D(e.initialValue);
56
+ r = {
57
+ value: t,
58
+ initialValue: t,
59
+ listeners: /* @__PURE__ */ new Set()
60
+ }, this.cells.set(n, r);
61
+ }
62
+ return r;
63
+ }
64
+ get(e, t = {}) {
65
+ let n = this.getOrCreateCell(e, t);
66
+ return {
67
+ read: () => n.value,
68
+ write: (e) => {
69
+ let t = typeof e == "function" ? e(n.value) : e;
70
+ Object.is(t, n.value) || (n.value = t, n.listeners.forEach((e) => e()));
71
+ },
72
+ subscribe: (e) => (n.listeners.add(e), () => n.listeners.delete(e))
73
+ };
74
+ }
75
+ purgeNamespace(e) {
76
+ let t = `${e}/`, n = `${e}:`;
77
+ for (let [r, i] of this.cells.entries()) {
78
+ let a = r.slice(r.lastIndexOf(":") + 1);
79
+ if (a === e || a.startsWith(t) || a.startsWith(n)) {
80
+ let e = D(i.initialValue);
81
+ Object.is(e, i.value) || (i.value = e, i.listeners.forEach((e) => e()));
82
+ }
83
+ }
84
+ }
85
+ clearPluginContexts(e) {
86
+ if (typeof e == "string") {
87
+ this.purgeNamespace(e);
88
+ return;
89
+ }
90
+ let t = /* @__PURE__ */ new Set();
91
+ if (e.id && t.add(e.id), e.contributes?.elements) for (let n of e.contributes.elements) t.add(n);
92
+ if (e.contributes?.workspaces) for (let n of e.contributes.workspaces) t.add(n);
93
+ for (let e of t) this.purgeNamespace(e);
94
+ }
95
+ disposePluginContexts(e) {
96
+ let t = /* @__PURE__ */ new Set([
97
+ e.id,
98
+ ...e.contributes?.elements ?? [],
99
+ ...e.contributes?.workspaces ?? []
100
+ ]);
101
+ for (let [e, n] of [...this.cells]) {
102
+ let r = e.slice(e.lastIndexOf(":") + 1);
103
+ [...t].some((e) => r === e || r.startsWith(`${e}/`) || r.startsWith(`${e}:`)) && (n.value = D(n.initialValue), n.listeners.forEach((e) => e()), n.listeners.clear(), this.cells.delete(e));
104
+ }
105
+ }
106
+ clearScope(e, t) {
107
+ let n = `${e}:${t}:`;
108
+ for (let [e, t] of this.cells.entries()) if (e.startsWith(n)) {
109
+ let e = D(t.initialValue);
110
+ Object.is(e, t.value) || (t.value = e, t.listeners.forEach((e) => e()));
111
+ }
112
+ }
113
+ clearAll() {
114
+ for (let e of this.cells.values()) {
115
+ let t = D(e.initialValue);
116
+ Object.is(t, e.value) || (e.value = t, e.listeners.forEach((e) => e()));
117
+ }
118
+ }
119
+ cellKey(e, t) {
120
+ if (e.scope === "application") return `application:${e.id}`;
121
+ if (e.scope === "project") return `project:${t.projectId ?? "no-project"}:${e.id}`;
122
+ if (e.scope === "workspace") {
123
+ if (!t.workspaceId) throw Error(`Context ${e.id} 缺少 workspaceId`);
124
+ return `workspace:${t.workspaceId}:${e.id}`;
125
+ }
126
+ if (!t.instanceId) throw Error(`Context ${e.id} 缺少 instanceId`);
127
+ return `instance:${t.instanceId}:${e.id}`;
128
+ }
129
+ }, ee = /^[a-z][a-z0-9.-]*(\/[a-z][a-z0-9.-]*)+$/;
130
+ function te(e, t) {
131
+ if (!ee.test(e)) throw Error(`Workbench Context ID 无效: ${e}`);
132
+ return Object.freeze({
133
+ id: e,
134
+ scope: t.scope,
135
+ initialValue: t.initialValue
136
+ });
137
+ }
138
+ //#endregion
139
+ //#region workbench/src/context/WorkbenchHostContext.tsx
140
+ var k = t(null);
141
+ function A() {
142
+ let e = a(k);
143
+ if (!e) throw Error("WorkbenchHostContext must be provided to render workbench components");
144
+ return e.services;
145
+ }
146
+ function j(e) {
147
+ let t = a(k);
148
+ if (!t) throw Error("WorkbenchHostContext must be provided to render workbench components");
149
+ return t.useWorkspaceState(e);
150
+ }
151
+ //#endregion
152
+ //#region workbench/src/ui/FloatingScrollbars.tsx
153
+ var ne = 24, re = 700;
154
+ function ie(e, t, n, r) {
155
+ if (e <= 0 || t <= 0 || n <= t) return null;
156
+ let i = Math.min(e, Math.max(ne, e * t / n)), a = n - t, o = e - i;
157
+ return {
158
+ offset: a > 0 ? o * r / a : 0,
159
+ size: i,
160
+ scrollRange: a,
161
+ thumbRange: o
162
+ };
163
+ }
164
+ function ae(e) {
165
+ if (!e.isConnected) return null;
166
+ let t = e.getBoundingClientRect();
167
+ return t.width <= 0 || t.height <= 0 ? null : {
168
+ target: e,
169
+ top: t.top,
170
+ left: t.left,
171
+ width: t.width,
172
+ height: t.height,
173
+ clientWidth: e.clientWidth,
174
+ clientHeight: e.clientHeight,
175
+ scrollWidth: e.scrollWidth,
176
+ scrollHeight: e.scrollHeight,
177
+ scrollLeft: e.scrollLeft,
178
+ scrollTop: e.scrollTop
179
+ };
180
+ }
181
+ function oe({ ownerDocument: e = document }) {
182
+ let t = e.defaultView ?? window, [n, r] = u(null), a = l(null), s = l(null), c = i(() => {
183
+ a.current !== null && (t.clearTimeout(a.current), a.current = null);
184
+ }, [t]), d = i(() => {
185
+ c(), a.current = t.setTimeout(() => {
186
+ s.current || r(null);
187
+ }, re);
188
+ }, [c, t]), f = i((e) => {
189
+ let t = ae(e);
190
+ !t || t.scrollHeight <= t.clientHeight && t.scrollWidth <= t.clientWidth || (r(t), d());
191
+ }, [d]);
192
+ if (o(() => {
193
+ function r(e) {
194
+ e.target instanceof HTMLElement && f(e.target);
195
+ }
196
+ function i() {
197
+ n?.target && f(n.target);
198
+ }
199
+ return e.addEventListener("scroll", r, !0), t.addEventListener("resize", i), () => {
200
+ e.removeEventListener("scroll", r, !0), t.removeEventListener("resize", i), c();
201
+ };
202
+ }, [
203
+ c,
204
+ e,
205
+ t,
206
+ n?.target,
207
+ f
208
+ ]), !n) return null;
209
+ let p = ie(n.height, n.clientHeight, n.scrollHeight, n.scrollTop), m = ie(n.width, n.clientWidth, n.scrollWidth, n.scrollLeft);
210
+ function h(e, t, r) {
211
+ c(), t.currentTarget.setPointerCapture(t.pointerId), s.current = {
212
+ axis: e,
213
+ target: n.target,
214
+ startPointer: e === "vertical" ? t.clientY : t.clientX,
215
+ startScroll: e === "vertical" ? n.scrollTop : n.scrollLeft,
216
+ scrollRange: r.scrollRange,
217
+ thumbRange: r.thumbRange
218
+ };
219
+ }
220
+ function g(e) {
221
+ let t = s.current;
222
+ if (!t || t.thumbRange <= 0) return;
223
+ let n = t.axis === "vertical" ? e.clientY : e.clientX, r = t.startScroll + (n - t.startPointer) * t.scrollRange / t.thumbRange;
224
+ t.axis === "vertical" ? t.target.scrollTop = r : t.target.scrollLeft = r;
225
+ }
226
+ function _(e) {
227
+ e.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId), s.current = null, d();
228
+ }
229
+ return S(/* @__PURE__ */ T("div", {
230
+ className: "floating-scrollbars",
231
+ "aria-hidden": "true",
232
+ children: [p && /* @__PURE__ */ w("div", {
233
+ className: "floating-scrollbar-thumb is-vertical",
234
+ style: {
235
+ left: n.left + n.width - 6,
236
+ top: n.top + p.offset,
237
+ height: p.size
238
+ },
239
+ onPointerDown: (e) => h("vertical", e, p),
240
+ onPointerMove: g,
241
+ onPointerUp: _,
242
+ onPointerCancel: _
243
+ }), m && /* @__PURE__ */ w("div", {
244
+ className: "floating-scrollbar-thumb is-horizontal",
245
+ style: {
246
+ left: n.left + m.offset,
247
+ top: n.top + n.height - 6,
248
+ width: m.size
249
+ },
250
+ onPointerDown: (e) => h("horizontal", e, m),
251
+ onPointerMove: g,
252
+ onPointerUp: _,
253
+ onPointerCancel: _
254
+ })]
255
+ }), e.body);
256
+ }
257
+ //#endregion
258
+ //#region workbench/src/elements/ExtensionSlot.tsx
259
+ function M({ point: e, className: t, ...r }) {
260
+ let { extensions: i } = A();
261
+ d(i.subscribe, i.getSnapshot);
262
+ let a = i.list(e);
263
+ return a.length === 0 ? null : /* @__PURE__ */ w("div", {
264
+ className: t,
265
+ children: a.map((e) => {
266
+ let t = e.component;
267
+ return /* @__PURE__ */ n(t, {
268
+ ...r,
269
+ key: e.id
270
+ });
271
+ })
272
+ });
273
+ }
274
+ //#endregion
275
+ //#region workbench/src/ui/InlineSelect.tsx
276
+ function N({ align: e = "start", ariaLabel: t, className: n = "", disabled: r = !1, menuClassName: i = "", onChange: a, options: s, value: c }) {
277
+ let [d, p] = u(!1), [m, h] = u(document), [g, _] = u({}), v = l(null), y = l(null), b = l(null), x = s.find((e) => e.value === c) ?? s[0];
278
+ if (o(() => {
279
+ if (!d) return;
280
+ function e(e) {
281
+ let t = e.target;
282
+ !v.current?.contains(t) && !y.current?.contains(t) && p(!1);
283
+ }
284
+ return m.addEventListener("pointerdown", e), () => m.removeEventListener("pointerdown", e);
285
+ }, [d, m]), !x) return null;
286
+ function C() {
287
+ let t = b.current;
288
+ if (t) {
289
+ let n = t.getBoundingClientRect(), r = t.ownerDocument, i = r.defaultView ?? window;
290
+ h(r), _(e === "end" ? {
291
+ top: n.bottom + 3,
292
+ right: i.innerWidth - n.right
293
+ } : {
294
+ top: n.bottom + 3,
295
+ left: n.left,
296
+ minWidth: n.width
297
+ });
298
+ }
299
+ p((e) => !e);
300
+ }
301
+ return /* @__PURE__ */ T("div", {
302
+ className: `inline-select ${n}`,
303
+ ref: v,
304
+ children: [/* @__PURE__ */ T("button", {
305
+ "aria-expanded": d,
306
+ "aria-haspopup": "listbox",
307
+ "aria-label": t,
308
+ className: "inline-select-trigger",
309
+ disabled: r,
310
+ ref: b,
311
+ type: "button",
312
+ onClick: C,
313
+ children: [/* @__PURE__ */ w("span", { children: x.label }), /* @__PURE__ */ w(f, {
314
+ size: 12,
315
+ "aria-hidden": "true"
316
+ })]
317
+ }), d && S(/* @__PURE__ */ w("div", {
318
+ "aria-label": t,
319
+ className: `inline-select-menu ${i}`,
320
+ ref: y,
321
+ role: "listbox",
322
+ style: g,
323
+ children: s.map((e) => /* @__PURE__ */ w("button", {
324
+ "aria-selected": e.value === c,
325
+ className: e.value === c ? "is-selected" : "",
326
+ role: "option",
327
+ type: "button",
328
+ onClick: () => {
329
+ a(e.value), p(!1);
330
+ },
331
+ children: e.label
332
+ }, e.value))
333
+ }), m.body)]
334
+ });
335
+ }
336
+ //#endregion
337
+ //#region workbench/src/dock/layout.ts
338
+ function P(e) {
339
+ return e.kind === "area" ? [e] : [...P(e.first), ...P(e.second)];
340
+ }
341
+ function F(e, t) {
342
+ return e.kind === "area" ? e.id === t ? e : null : F(e.first, t) ?? F(e.second, t);
343
+ }
344
+ function I(e, t) {
345
+ if (e.kind === "area") return t.has(e.id) ? null : e;
346
+ let n = I(e.first, t), r = I(e.second, t);
347
+ return n ? r ? n === e.first && r === e.second ? e : {
348
+ ...e,
349
+ first: n,
350
+ second: r
351
+ } : n : r;
352
+ }
353
+ function L(e, t) {
354
+ return !!F(e, t) && P(e).length > 1;
355
+ }
356
+ function R(e, t, n) {
357
+ return e.kind === "area" ? e.id === t ? n(e) : e : {
358
+ ...e,
359
+ first: R(e.first, t, n),
360
+ second: R(e.second, t, n)
361
+ };
362
+ }
363
+ function se(e, t, n, r) {
364
+ return R(e, t, (e) => ({
365
+ ...e,
366
+ activePanelId: n,
367
+ panelHistory: e.panelHistory.includes(n) ? e.panelHistory : [...e.panelHistory, n],
368
+ panelInstanceIds: e.panelInstanceIds[n] ? e.panelInstanceIds : {
369
+ ...e.panelInstanceIds,
370
+ [n]: r
371
+ }
372
+ }));
373
+ }
374
+ function ce(e, t, n, r) {
375
+ return R(e, t, (e) => ({
376
+ kind: "split",
377
+ id: r.splitId,
378
+ direction: n,
379
+ ratio: .5,
380
+ first: e,
381
+ second: {
382
+ kind: "area",
383
+ id: r.areaId,
384
+ activePanelId: e.activePanelId,
385
+ panelHistory: [e.activePanelId],
386
+ panelInstanceIds: { [e.activePanelId]: r.panelInstanceId }
387
+ }
388
+ }));
389
+ }
390
+ function z(e, t) {
391
+ return e.kind === "area" ? e : e.first.kind === "area" && e.first.id === t ? e.second : e.second.kind === "area" && e.second.id === t ? e.first : {
392
+ ...e,
393
+ first: z(e.first, t),
394
+ second: z(e.second, t)
395
+ };
396
+ }
397
+ function le(e, t) {
398
+ return L(e, t) ? z(e, t) : e;
399
+ }
400
+ function B(e, t, n) {
401
+ return e.kind === "area" ? e : e.id === t ? {
402
+ ...e,
403
+ ratio: Math.min(.85, Math.max(.15, n))
404
+ } : {
405
+ ...e,
406
+ first: B(e.first, t, n),
407
+ second: B(e.second, t, n)
408
+ };
409
+ }
410
+ function ue(e, t, n) {
411
+ let r = F(e, t), i = F(e, n);
412
+ return !r || !i || r.id === i.id ? e : R(R(e, t, (e) => ({
413
+ ...e,
414
+ activePanelId: i.activePanelId,
415
+ panelHistory: i.panelHistory,
416
+ panelInstanceIds: i.panelInstanceIds
417
+ })), n, (e) => ({
418
+ ...e,
419
+ activePanelId: r.activePanelId,
420
+ panelHistory: r.panelHistory,
421
+ panelInstanceIds: r.panelInstanceIds
422
+ }));
423
+ }
424
+ //#endregion
425
+ //#region workbench/src/dock/floatingWindow.ts
426
+ function V(e, t, n, r) {
427
+ return e <= 0 || t <= 0 || e >= n || t >= r;
428
+ }
429
+ function H(e) {
430
+ e.head.querySelectorAll("[data-graphvideo-shared-style]").forEach((e) => e.remove()), document.head.querySelectorAll("style, link[rel=\"stylesheet\"]").forEach((t) => {
431
+ let n = t.cloneNode(!0);
432
+ n.dataset.graphvideoSharedStyle = "true", n instanceof HTMLLinkElement && t instanceof HTMLLinkElement && (n.href = t.href), e.head.append(n);
433
+ });
434
+ }
435
+ var de = [
436
+ "class",
437
+ "data-theme",
438
+ "data-font-family",
439
+ "data-font-size"
440
+ ];
441
+ function U(e, t) {
442
+ de.forEach((n) => {
443
+ let r = e.getAttribute(n);
444
+ r === null ? t.removeAttribute(n) : t.setAttribute(n, r);
445
+ });
446
+ }
447
+ function fe(e, t) {
448
+ let n = e.document;
449
+ n.title = t, U(document.documentElement, n.documentElement), n.body.replaceChildren(), n.body.className = "floating-panel-body";
450
+ let r = n.createElement("div");
451
+ r.className = "floating-panel-root", n.body.append(r), H(n);
452
+ let i = new MutationObserver(() => H(n));
453
+ i.observe(document.head, {
454
+ childList: !0,
455
+ subtree: !0,
456
+ characterData: !0
457
+ });
458
+ let a = new MutationObserver(() => U(document.documentElement, n.documentElement));
459
+ return a.observe(document.documentElement, { attributes: !0 }), {
460
+ container: r,
461
+ disconnect: () => {
462
+ i.disconnect(), a.disconnect();
463
+ }
464
+ };
465
+ }
466
+ //#endregion
467
+ //#region workbench/src/dock/AreaShell.tsx
468
+ function pe({ workspaceId: e, area: t, panel: n, runtime: r }) {
469
+ let i = n.component, a = t.panelInstanceIds[n.id], s = `${e}:${t.id}:${n.id}`;
470
+ return o(() => (r.attach(s), () => r.detach(s)), [r, s]), /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(i, {
471
+ workspaceId: e,
472
+ areaId: t.id,
473
+ viewId: s,
474
+ instanceId: a,
475
+ runtime: r
476
+ }), /* @__PURE__ */ w(M, {
477
+ point: `panel:${n.id}:overlay`,
478
+ className: "extension-slot-overlay",
479
+ panelId: n.id,
480
+ workspaceId: e,
481
+ areaId: t.id,
482
+ viewId: s,
483
+ instanceId: a,
484
+ runtime: r
485
+ })] });
486
+ }
487
+ function me({ workspaceId: e, area: t, floating: n = !1, onFloatToggle: r }) {
488
+ let { commands: i, panels: a, elementRuntimes: o } = A(), s = typeof navigator < "u" && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
489
+ d(a.subscribe, a.getSnapshot), d(o.subscribe, o.getSnapshot);
490
+ let c = j((t) => t.items[e]), l = c?.focusedAreaId === t.id, u = c?.maximizedAreaId === t.id, f = c ? L(c.layout, t.id) : !1, _ = a.get(t.activePanelId), y = _?.icon ?? p, S = a.ownerOf(t.activePanelId), C = t.panelInstanceIds[t.activePanelId], E = S && C ? o.getOrCreate(S, C) : null, D = `${e}:${t.id}:${t.activePanelId}`;
491
+ return /* @__PURE__ */ T("article", {
492
+ className: `area-shell ${l ? "is-focused" : ""}`,
493
+ onPointerDown: () => void i.execute("workspace.area.focus", {
494
+ workspaceId: e,
495
+ areaId: t.id
496
+ }),
497
+ onDragOver: (e) => e.preventDefault(),
498
+ onDrop: (n) => {
499
+ n.preventDefault();
500
+ let r = n.dataTransfer.getData("application/x-graphvideo-area").split(":");
501
+ r.length === 2 && r[0] === e && i.execute("workspace.area.swap", {
502
+ workspaceId: e,
503
+ sourceAreaId: r[1],
504
+ targetAreaId: t.id
505
+ });
506
+ },
507
+ children: [/* @__PURE__ */ T("header", {
508
+ className: "area-header",
509
+ draggable: !n,
510
+ onDragStart: (n) => {
511
+ if (n.target.closest("button, .inline-select")) {
512
+ n.preventDefault();
513
+ return;
514
+ }
515
+ n.dataTransfer.effectAllowed = "move", n.dataTransfer.setData("application/x-graphvideo-area", `${e}:${t.id}`);
516
+ },
517
+ onDragEnd: (e) => {
518
+ r && V(e.clientX, e.clientY, window.innerWidth, window.innerHeight) && r(t.id);
519
+ },
520
+ children: [
521
+ /* @__PURE__ */ w(y, { size: 14 }),
522
+ /* @__PURE__ */ w(N, {
523
+ ariaLabel: "切换面板",
524
+ className: "area-panel-select",
525
+ value: t.activePanelId,
526
+ options: [..._ ? [] : [{
527
+ value: t.activePanelId,
528
+ label: `未加载 · ${t.activePanelId}`
529
+ }], ...a.list().map((e) => ({
530
+ value: e.id,
531
+ label: e.title
532
+ }))],
533
+ onChange: (n) => void i.execute("workspace.panel.switch", {
534
+ workspaceId: e,
535
+ areaId: t.id,
536
+ panelId: n
537
+ })
538
+ }),
539
+ _ && E && /* @__PURE__ */ w(M, {
540
+ point: `panel:${_.id}:header`,
541
+ panelId: _.id,
542
+ workspaceId: e,
543
+ areaId: t.id,
544
+ viewId: D,
545
+ instanceId: C,
546
+ runtime: E
547
+ }),
548
+ /* @__PURE__ */ w("span", { className: "area-header-spacer" }),
549
+ /* @__PURE__ */ w("button", {
550
+ className: "area-header-button",
551
+ type: "button",
552
+ title: n ? "放回主窗口" : "弹出为悬浮窗口",
553
+ onClick: () => r?.(t.id),
554
+ children: /* @__PURE__ */ w(v, { size: 13 })
555
+ }),
556
+ /* @__PURE__ */ w("button", {
557
+ className: "area-header-button",
558
+ type: "button",
559
+ title: "左右切分",
560
+ onClick: () => void i.execute("workspace.area.split", {
561
+ workspaceId: e,
562
+ areaId: t.id,
563
+ direction: "horizontal"
564
+ }),
565
+ children: /* @__PURE__ */ w(m, { size: 13 })
566
+ }),
567
+ /* @__PURE__ */ w("button", {
568
+ className: "area-header-button",
569
+ type: "button",
570
+ title: "上下切分",
571
+ onClick: () => void i.execute("workspace.area.split", {
572
+ workspaceId: e,
573
+ areaId: t.id,
574
+ direction: "vertical"
575
+ }),
576
+ children: /* @__PURE__ */ w(b, { size: 13 })
577
+ }),
578
+ /* @__PURE__ */ w("button", {
579
+ className: "area-header-button",
580
+ type: "button",
581
+ title: u ? s ? "恢复区域 (⌘+Space)" : "恢复区域 (Ctrl+Space)" : s ? "最大化区域 (⌘+Space)" : "最大化区域 (Ctrl+Space)",
582
+ onClick: () => void i.execute("workspace.area.maximize", {
583
+ workspaceId: e,
584
+ areaId: t.id
585
+ }),
586
+ children: w(u ? g : h, { size: 13 })
587
+ }),
588
+ /* @__PURE__ */ w("button", {
589
+ className: "area-header-button",
590
+ type: "button",
591
+ title: f ? "关闭并与相邻区域合并" : "至少保留一个区域",
592
+ disabled: !f,
593
+ onClick: () => void i.execute("workspace.area.close", {
594
+ workspaceId: e,
595
+ areaId: t.id
596
+ }),
597
+ children: /* @__PURE__ */ w(x, { size: 13 })
598
+ })
599
+ ]
600
+ }), /* @__PURE__ */ w("div", {
601
+ className: "area-content",
602
+ children: t.panelHistory.map((n) => {
603
+ let r = a.get(n), i = a.ownerOf(n), s = t.panelInstanceIds[n];
604
+ if (!r || !i || !s) return n === t.activePanelId ? /* @__PURE__ */ w("div", {
605
+ className: "panel-instance is-active",
606
+ children: /* @__PURE__ */ T("div", {
607
+ className: "missing-element-panel",
608
+ children: [
609
+ /* @__PURE__ */ w(p, { size: 24 }),
610
+ /* @__PURE__ */ w("strong", { children: "Element 当前未加载" }),
611
+ /* @__PURE__ */ w("span", { children: n })
612
+ ]
613
+ })
614
+ }, n) : null;
615
+ let c = o.getOrCreate(i, s);
616
+ return /* @__PURE__ */ w("div", {
617
+ className: `panel-instance ${n === t.activePanelId ? "is-active" : ""}`,
618
+ children: /* @__PURE__ */ w(pe, {
619
+ workspaceId: e,
620
+ area: t,
621
+ panel: r,
622
+ runtime: c
623
+ })
624
+ }, n);
625
+ })
626
+ })]
627
+ });
628
+ }
629
+ //#endregion
630
+ //#region workbench/src/dock/splitResizeGesture.ts
631
+ var he = .15, ge = .85, _e = 1e-6;
632
+ function ve(e) {
633
+ return Math.min(ge, Math.max(he, e));
634
+ }
635
+ function ye(e) {
636
+ let t = e.direction === "horizontal" ? e.startX : e.startY, n = e.direction === "horizontal" ? e.bounds.width : e.bounds.height, r = e.initialRatio, i = null, a = !1;
637
+ function o(r, i) {
638
+ if (n <= 0) return e.initialRatio;
639
+ let a = e.direction === "horizontal" ? r : i;
640
+ return ve(e.initialRatio + (a - t) / n);
641
+ }
642
+ function s() {
643
+ i = null, e.preview(r);
644
+ }
645
+ function c(t, n) {
646
+ a || (r = o(t, n), i === null && (i = e.scheduleFrame(s)));
647
+ }
648
+ function l() {
649
+ i !== null && (e.cancelFrame(i), i = null);
650
+ }
651
+ return {
652
+ move(e, t) {
653
+ c(e, t);
654
+ },
655
+ finish(t, n) {
656
+ if (!a) {
657
+ if (c(t, n), a = !0, l(), Math.abs(r - e.initialRatio) <= _e) {
658
+ e.cancel();
659
+ return;
660
+ }
661
+ e.preview(r), e.commit(r);
662
+ }
663
+ },
664
+ abort(t = !0) {
665
+ a || (a = !0, l(), t && e.cancel());
666
+ }
667
+ };
668
+ }
669
+ //#endregion
670
+ //#region workbench/src/dock/Workspace.tsx
671
+ function be({ container: e, className: t }) {
672
+ let n = l(null);
673
+ return c(() => {
674
+ let t = n.current;
675
+ if (t) return t.append(e), () => {
676
+ e.parentElement === t && e.remove();
677
+ };
678
+ }, [e]), /* @__PURE__ */ w("div", {
679
+ className: t,
680
+ ref: n
681
+ });
682
+ }
683
+ function xe({ workspaceId: e, split: t, getAreaElement: n }) {
684
+ let { commands: r } = A(), [i, a] = u(null), s = l(null);
685
+ o(() => () => {
686
+ s.current?.abort(!1), document.body.classList.remove("is-resizing");
687
+ }, []);
688
+ function c(n) {
689
+ n.preventDefault();
690
+ let i = n.currentTarget.parentElement;
691
+ if (!i) return;
692
+ let o = i.getBoundingClientRect();
693
+ n.currentTarget.setPointerCapture(n.pointerId), document.body.classList.add("is-resizing"), s.current = ye({
694
+ direction: t.direction,
695
+ bounds: o,
696
+ initialRatio: t.ratio,
697
+ startX: n.clientX,
698
+ startY: n.clientY,
699
+ scheduleFrame: (e) => window.requestAnimationFrame(e),
700
+ cancelFrame: (e) => window.cancelAnimationFrame(e),
701
+ preview: a,
702
+ commit: (n) => {
703
+ Promise.resolve(r.execute("workspace.split.resize", {
704
+ workspaceId: e,
705
+ splitId: t.id,
706
+ ratio: n
707
+ })).then(() => a(null), () => a(null));
708
+ },
709
+ cancel: () => a(null)
710
+ });
711
+ }
712
+ function d(e) {
713
+ s.current?.move(e.clientX, e.clientY);
714
+ }
715
+ function f(e) {
716
+ let t = s.current;
717
+ t && (s.current = null, t.finish(e.clientX, e.clientY), e.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId), document.body.classList.remove("is-resizing"));
718
+ }
719
+ function p(e) {
720
+ s.current?.abort(), s.current = null, e.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId), document.body.classList.remove("is-resizing");
721
+ }
722
+ let m = i ?? t.ratio, h = t.direction === "horizontal" ? { gridTemplateColumns: `${m}fr 4px ${1 - m}fr` } : { gridTemplateRows: `${m}fr 4px ${1 - m}fr` };
723
+ return /* @__PURE__ */ T("div", {
724
+ className: `dock-split is-${t.direction}`,
725
+ style: h,
726
+ children: [
727
+ /* @__PURE__ */ w("div", {
728
+ className: "dock-pane",
729
+ children: /* @__PURE__ */ w(W, {
730
+ workspaceId: e,
731
+ node: t.first,
732
+ getAreaElement: n
733
+ })
734
+ }),
735
+ /* @__PURE__ */ w("button", {
736
+ "aria-label": t.direction === "horizontal" ? "调整左右区域宽度" : "调整上下区域高度",
737
+ className: "dock-resizer",
738
+ type: "button",
739
+ onPointerDown: c,
740
+ onPointerMove: d,
741
+ onPointerUp: f,
742
+ onPointerCancel: p
743
+ }),
744
+ /* @__PURE__ */ w("div", {
745
+ className: "dock-pane",
746
+ children: /* @__PURE__ */ w(W, {
747
+ workspaceId: e,
748
+ node: t.second,
749
+ getAreaElement: n
750
+ })
751
+ })
752
+ ]
753
+ });
754
+ }
755
+ function W({ workspaceId: e, node: t, getAreaElement: n }) {
756
+ return t.kind === "area" ? /* @__PURE__ */ w(be, {
757
+ container: n(t.id),
758
+ className: "area-slot"
759
+ }) : /* @__PURE__ */ w(xe, {
760
+ workspaceId: e,
761
+ split: t,
762
+ getAreaElement: n
763
+ });
764
+ }
765
+ var Se = r(function({ workspaceId: e, active: t }) {
766
+ let { commands: n, panels: r } = A(), a = j((t) => t.items[e]), [s, c] = u(/* @__PURE__ */ new Map()), [d] = u(() => /* @__PURE__ */ new Map()), f = l(s), p = i((e) => {
767
+ let t = d.get(e);
768
+ if (t) return t;
769
+ let n = document.createElement("div");
770
+ return n.className = "area-render-root", d.set(e, n), n;
771
+ }, [d]), m = i((e, t) => {
772
+ let n = f.current.get(e);
773
+ if (!n) return;
774
+ n.disconnect();
775
+ let r = new Map(f.current);
776
+ r.delete(e), f.current = r, c(r), t && !n.window.closed && n.window.close();
777
+ }, []), h = i((t) => {
778
+ if (f.current.get(t)) {
779
+ m(t, !0);
780
+ return;
781
+ }
782
+ let n = F(a.layout, t);
783
+ if (!n) return;
784
+ let i = r.get(n.activePanelId)?.title ?? "GraphVideo Panel", o = window.open("about:blank", `graphvideo-floating-${e}-${t}`, "popup=yes,width=760,height=560,resizable=yes");
785
+ if (!o) return;
786
+ let s = {
787
+ window: o,
788
+ ...fe(o, `GraphVideo · ${i}`)
789
+ };
790
+ o.addEventListener("beforeunload", () => m(t, !1), { once: !0 });
791
+ let l = new Map(f.current).set(t, s);
792
+ f.current = l, c(l);
793
+ }, [
794
+ m,
795
+ r,
796
+ a.layout,
797
+ e
798
+ ]);
799
+ o(() => {
800
+ function r(r) {
801
+ t && (r.ctrlKey || r.metaKey) && r.code === "Space" && (r.preventDefault(), n.execute("workspace.area.maximize", {
802
+ workspaceId: e,
803
+ areaId: a.focusedAreaId
804
+ }));
805
+ }
806
+ return window.addEventListener("keydown", r), () => window.removeEventListener("keydown", r);
807
+ }, [
808
+ t,
809
+ n,
810
+ a.focusedAreaId,
811
+ e
812
+ ]), o(() => {
813
+ let e = [...s.keys()].filter((e) => !F(a.layout, e));
814
+ if (e.length === 0) return;
815
+ let t = window.setTimeout(() => {
816
+ e.forEach((e) => m(e, !0));
817
+ }, 0);
818
+ return () => window.clearTimeout(t);
819
+ }, [
820
+ m,
821
+ s,
822
+ a.layout
823
+ ]), o(() => {
824
+ let e = new Set(P(a.layout).map((e) => e.id));
825
+ for (let t of d.keys()) e.has(t) || d.delete(t);
826
+ }, [d, a.layout]), o(() => {
827
+ f.current = s;
828
+ }, [s]), o(() => () => {
829
+ for (let e of f.current.values()) e.disconnect(), e.window.closed || e.window.close();
830
+ }, []);
831
+ let g = a.maximizedAreaId ? F(a.layout, a.maximizedAreaId) : null, _ = I(a.layout, new Set(s.keys())), y = g && !s.has(g.id) ? g : null;
832
+ return /* @__PURE__ */ T("div", {
833
+ className: `workspace workspace-page ${t ? "is-active" : "is-inactive"}`,
834
+ "aria-hidden": !t,
835
+ inert: !t,
836
+ children: [
837
+ y ? /* @__PURE__ */ w(W, {
838
+ workspaceId: e,
839
+ node: y,
840
+ getAreaElement: p
841
+ }) : _ ? /* @__PURE__ */ w(W, {
842
+ workspaceId: e,
843
+ node: _,
844
+ getAreaElement: p
845
+ }) : /* @__PURE__ */ T("div", {
846
+ className: "floating-area-placeholder",
847
+ children: [
848
+ /* @__PURE__ */ w(v, { size: 22 }),
849
+ /* @__PURE__ */ w("span", { children: "所有区域均已在悬浮窗口中打开" }),
850
+ /* @__PURE__ */ w("button", {
851
+ type: "button",
852
+ onClick: () => {
853
+ for (let e of s.keys()) m(e, !0);
854
+ },
855
+ children: "全部放回主窗口"
856
+ })
857
+ ]
858
+ }),
859
+ P(a.layout).map((t) => S(/* @__PURE__ */ w(me, {
860
+ workspaceId: e,
861
+ area: t,
862
+ floating: s.has(t.id),
863
+ onFloatToggle: h
864
+ }), p(t.id), t.id)),
865
+ [...s].map(([e, t]) => F(a.layout, e) ? S(/* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(oe, { ownerDocument: t.window.document }), /* @__PURE__ */ w(be, {
866
+ container: p(e),
867
+ className: "floating-area-content"
868
+ })] }), t.container, `floating-host-${e}`) : null)
869
+ ]
870
+ });
871
+ }), Ce = /^[a-z0-9][a-z0-9._-]*$/;
872
+ function we(e) {
873
+ let t;
874
+ try {
875
+ t = JSON.parse(e);
876
+ } catch {
877
+ throw Error("element.json 不是有效 JSON");
878
+ }
879
+ if (!t || typeof t != "object") throw Error("element.json 必须是对象");
880
+ let n = t;
881
+ if (typeof n.id != "string" || !Ce.test(n.id)) throw Error("Element id 只能包含小写字母、数字、点、下划线和短横线");
882
+ if (typeof n.name != "string" || !n.name.trim()) throw Error("Element name 不能为空");
883
+ if (n.apiVersion !== 1) throw Error("Element apiVersion 必须是 1");
884
+ if (typeof n.entry != "string" || !n.entry.trim()) throw Error("Element entry 不能为空");
885
+ let r = n.entry.replace(/\\/g, "/");
886
+ if (r !== "element.ts") throw Error("Element entry 必须是 element.ts");
887
+ return {
888
+ id: n.id,
889
+ name: n.name.trim(),
890
+ apiVersion: 1,
891
+ entry: r
892
+ };
893
+ }
894
+ //#endregion
895
+ //#region workbench/src/elements/dispose.ts
896
+ async function G(e) {
897
+ for (let t of e.splice(0).reverse()) try {
898
+ await t();
899
+ } catch (e) {
900
+ console.error("Element cleanup failed:", e);
901
+ }
902
+ }
903
+ //#endregion
904
+ //#region workbench/src/elements/elementLoader.ts
905
+ var Te = class {
906
+ registries;
907
+ loaded = /* @__PURE__ */ new Map();
908
+ listeners = /* @__PURE__ */ new Set();
909
+ errors = [];
910
+ version = 0;
911
+ contexts;
912
+ constructor(e) {
913
+ this.registries = e, this.contexts = e.contexts ?? new O();
914
+ }
915
+ subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
916
+ getSnapshot = () => this.version;
917
+ listErrors() {
918
+ return this.errors;
919
+ }
920
+ listLoaded() {
921
+ return [...this.loaded.values()].map(({ manifest: e, owner: t, version: n }) => ({
922
+ manifest: e,
923
+ owner: t,
924
+ version: n
925
+ }));
926
+ }
927
+ async reconcile(e) {
928
+ let t = new Set(e.map((e) => e.owner)), n = [];
929
+ for (let t of e) if (this.loaded.get(t.owner)?.version !== t.version) try {
930
+ await this.load(t);
931
+ } catch (e) {
932
+ n.push(e instanceof Error ? e.message : `无法加载 ${t.owner}`);
933
+ }
934
+ for (let e of [...this.loaded.values()]) t.has(e.owner) || await this.unload(e.owner);
935
+ this.errors = n, this.emit();
936
+ }
937
+ reportError(e) {
938
+ this.errors = [e], this.emit();
939
+ }
940
+ async unload(e) {
941
+ let t = this.loaded.get(e);
942
+ t && (this.loaded.delete(e), this.registries.panels.unregisterOwner(e), this.registries.extensions.unregisterOwner(e), this.registries.commands.unregisterOwner(e), await this.registries.runtimes.removeElement(e), this.registries.services.unregisterOwner(e), this.registries.events.unregisterOwner(e), this.registries.states.unregisterOwner(e), await Promise.allSettled([Promise.resolve().then(t.disposeDefinition)]), this.emit());
943
+ }
944
+ async load(e) {
945
+ let t = we(e.manifestText);
946
+ if (e.owner !== t.id) throw Error(`Element 目录名与 Manifest ID 不一致: ${e.owner} / ${t.id}`);
947
+ let n = await e.load(t);
948
+ if (!n || typeof n.register != "function") throw Error(`Element ${t.id} 未导出 register(context)`);
949
+ let r = await this.stage(t, n);
950
+ try {
951
+ this.registries.panels.assertCanReplace(t.id, r.panels), this.registries.extensions.assertCanReplace(t.id, r.extensions), this.registries.commands.assertCanReplace(t.id, r.commands), this.registries.states.assertCanReplace(t.id, r.states), this.registries.services.assertCanReplace(t.id, r.services);
952
+ } catch (e) {
953
+ throw await Promise.allSettled([Promise.resolve().then(r.disposeDefinition)]), e;
954
+ }
955
+ let i = this.loaded.get(t.id), a = this.registries.states.getOwnerDefinitions(t.id), o = this.registries.services.getOwnerDefinitions(t.id);
956
+ this.registries.states.replaceOwner(t.id, r.states), this.registries.services.replaceOwner(t.id, r.services);
957
+ try {
958
+ await this.registries.runtimes.replaceFactory(t.id, r.runtimeFactory);
959
+ } catch (e) {
960
+ throw this.registries.states.replaceOwner(t.id, a), this.registries.services.replaceOwner(t.id, o), await Promise.allSettled([Promise.resolve().then(r.disposeDefinition)]), e;
961
+ }
962
+ this.registries.panels.replaceOwner(t.id, r.panels), this.registries.extensions.replaceOwner(t.id, r.extensions), this.registries.commands.replaceOwner(t.id, r.commands), this.registries.events.replaceOwner(t.id, r.events), this.loaded.set(t.id, {
963
+ owner: t.id,
964
+ manifest: t,
965
+ version: e.version,
966
+ module: n,
967
+ disposeDefinition: r.disposeDefinition
968
+ }), i && await Promise.allSettled([Promise.resolve().then(i.disposeDefinition)]);
969
+ }
970
+ async stage(t, n) {
971
+ let r = [], i = [], a = [], o = [], s = [], c = [], l = [], u = null;
972
+ try {
973
+ let d = await n.register({
974
+ manifest: t,
975
+ react: e,
976
+ host: this.registries.host,
977
+ application: this.registries.application,
978
+ events: {
979
+ on: (e, t) => s.push({
980
+ event: e,
981
+ listener: t
982
+ }),
983
+ emit: (e, t) => this.registries.events.emit(e, t)
984
+ },
985
+ services: {
986
+ provide: (e, t) => c.push({
987
+ id: e.id,
988
+ token: e,
989
+ value: t
990
+ }),
991
+ get: (e) => this.registries.services.require(e),
992
+ has: (e) => this.registries.services.has(e)
993
+ },
994
+ contexts: { get: (e, t = {}) => this.contexts.get(e, {
995
+ ...t,
996
+ projectId: "projectId" in t ? t.projectId : this.registries.host.getProjectId()
997
+ }) },
998
+ panels: { register: (e) => r.push(e) },
999
+ extensions: { register: (e) => i.push(e) },
1000
+ commands: { register: (e, t) => a.push({
1001
+ id: e,
1002
+ handler: t
1003
+ }) },
1004
+ states: { define: (e) => o.push(e) },
1005
+ runtime: { define: (e) => {
1006
+ if (u) throw Error(`Element ${t.id} 只能定义一个 Runtime Factory`);
1007
+ u = e;
1008
+ } },
1009
+ onDispose: (e) => l.push(e)
1010
+ });
1011
+ d && l.push(d);
1012
+ } catch (e) {
1013
+ throw await G(l), e;
1014
+ }
1015
+ return {
1016
+ panels: r,
1017
+ extensions: i,
1018
+ commands: a,
1019
+ states: o,
1020
+ events: s,
1021
+ services: c,
1022
+ runtimeFactory: u,
1023
+ disposeDefinition: async () => {
1024
+ await G(l);
1025
+ }
1026
+ };
1027
+ }
1028
+ emit() {
1029
+ this.version += 1, this.listeners.forEach((e) => e());
1030
+ }
1031
+ }, Ee = class {
1032
+ states;
1033
+ host;
1034
+ services;
1035
+ events;
1036
+ contexts;
1037
+ factories = /* @__PURE__ */ new Map();
1038
+ instances = /* @__PURE__ */ new Map();
1039
+ listeners = /* @__PURE__ */ new Set();
1040
+ version = 0;
1041
+ pendingCleanups = /* @__PURE__ */ new Set();
1042
+ constructor(e, t, n, r, i = new O()) {
1043
+ this.states = e, this.host = t, this.services = n, this.events = r, this.contexts = i;
1044
+ }
1045
+ subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
1046
+ getSnapshot = () => this.version;
1047
+ getOrCreate(e, t) {
1048
+ let n = this.key(e, t), r = this.instances.get(n);
1049
+ if (r) return r.handle;
1050
+ if (!this.factories.has(e)) throw Error(`Element Runtime 未注册: ${e}`);
1051
+ let i = this.createEntry(e, t, this.factories.get(e) ?? null);
1052
+ return this.instances.set(n, i), i.handle;
1053
+ }
1054
+ async replaceFactory(e, t) {
1055
+ let n = [...this.instances.entries()].filter(([t]) => t.startsWith(`${e}:`)), r = /* @__PURE__ */ new Map();
1056
+ try {
1057
+ for (let [i, a] of n) r.set(i, this.createEntry(e, a.handle.instanceId, t));
1058
+ } catch (e) {
1059
+ throw await Promise.allSettled([...r.values()].map((e) => e.dispose())), await Promise.all(this.pendingCleanups), e;
1060
+ }
1061
+ this.factories.set(e, t), r.forEach((e, t) => this.instances.set(t, e)), this.emit(), await Promise.allSettled(n.map(([, e]) => e.dispose()));
1062
+ }
1063
+ async removeElement(e) {
1064
+ this.factories.delete(e);
1065
+ let t = [];
1066
+ for (let [n, r] of [...this.instances]) n.startsWith(`${e}:`) && (this.instances.delete(n), t.push(r));
1067
+ this.emit(), await Promise.allSettled(t.map((e) => e.dispose())), await Promise.all(this.pendingCleanups);
1068
+ }
1069
+ async disposeAll() {
1070
+ this.factories.clear();
1071
+ let e = [...this.instances.values()];
1072
+ this.instances.clear(), this.emit(), await Promise.allSettled(e.map((e) => e.dispose())), await Promise.all(this.pendingCleanups);
1073
+ }
1074
+ listInstances() {
1075
+ return [...this.instances.values()].map((e) => e.handle);
1076
+ }
1077
+ createEntry(e, t, n) {
1078
+ let r = /* @__PURE__ */ new Set(), i = [], a = { get: (n, r = {}) => {
1079
+ let i = () => this.states.bind(e, n, {
1080
+ projectId: "projectId" in r ? r.projectId : this.host.getProjectId(),
1081
+ workspaceId: r.workspaceId,
1082
+ instanceId: t
1083
+ });
1084
+ return {
1085
+ read: () => i().read(),
1086
+ write: (e) => i().write(e),
1087
+ subscribe: (e) => i().subscribe(e)
1088
+ };
1089
+ } }, o;
1090
+ try {
1091
+ o = n?.create({
1092
+ elementId: e,
1093
+ instanceId: t,
1094
+ host: this.host,
1095
+ events: { emit: (e, t) => this.events.emit(e, t) },
1096
+ services: {
1097
+ get: (e) => this.services.require(e),
1098
+ has: (e) => this.services.has(e)
1099
+ },
1100
+ states: a,
1101
+ contexts: { get: (e, n = {}) => this.contexts.get(e, {
1102
+ ...n,
1103
+ projectId: "projectId" in n ? n.projectId : this.host.getProjectId(),
1104
+ instanceId: n.instanceId ?? t
1105
+ }) },
1106
+ onDispose: (e) => i.push(e)
1107
+ }) ?? {};
1108
+ } catch (e) {
1109
+ let t = G(i);
1110
+ throw this.pendingCleanups.add(t), t.finally(() => this.pendingCleanups.delete(t)), e;
1111
+ }
1112
+ let s = o;
1113
+ return s.dispose && i.push(() => s.dispose()), {
1114
+ handle: {
1115
+ elementId: e,
1116
+ instanceId: t,
1117
+ value: s,
1118
+ states: a,
1119
+ attach: (e) => r.add(e),
1120
+ detach: (e) => r.delete(e)
1121
+ },
1122
+ dispose: async () => {
1123
+ await G(i), r.clear();
1124
+ }
1125
+ };
1126
+ }
1127
+ key(e, t) {
1128
+ return `${e}:${t}`;
1129
+ }
1130
+ emit() {
1131
+ this.version += 1, this.listeners.forEach((e) => e());
1132
+ }
1133
+ };
1134
+ //#endregion
1135
+ //#region workbench/src/elements/types.ts
1136
+ function De(e) {
1137
+ return e;
1138
+ }
1139
+ //#endregion
1140
+ //#region workbench/src/plugins/pluginManager.ts
1141
+ var Oe = class {
1142
+ options;
1143
+ constructor(e) {
1144
+ this.options = e;
1145
+ }
1146
+ async uninstall(e) {
1147
+ if (e.contributes?.elements) for (let t of e.contributes.elements) await this.options.elementLoader.unload(t);
1148
+ this.options.contextStore.disposePluginContexts(e);
1149
+ }
1150
+ }, K = class {
1151
+ entries = /* @__PURE__ */ new Map();
1152
+ listeners = /* @__PURE__ */ new Set();
1153
+ version = 0;
1154
+ subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
1155
+ getSnapshot = () => this.version;
1156
+ register(e, t) {
1157
+ let n = this.entries.get(t.id);
1158
+ if (n && n.owner !== e) throw Error(`Contribution ID conflict: ${t.id} (${n.owner} / ${e})`);
1159
+ this.entries.set(t.id, {
1160
+ owner: e,
1161
+ value: t
1162
+ }), this.emit();
1163
+ }
1164
+ assertCanReplace(e, t) {
1165
+ let n = /* @__PURE__ */ new Set();
1166
+ for (let r of t) {
1167
+ if (n.has(r.id)) throw Error(`Contribution ID conflict: ${r.id} (${e})`);
1168
+ n.add(r.id);
1169
+ let t = this.entries.get(r.id);
1170
+ if (t && t.owner !== e) throw Error(`Contribution ID conflict: ${r.id} (${t.owner} / ${e})`);
1171
+ }
1172
+ }
1173
+ replaceOwner(e, t) {
1174
+ this.assertCanReplace(e, t);
1175
+ for (let [t, n] of this.entries) n.owner === e && this.entries.delete(t);
1176
+ t.forEach((t) => this.entries.set(t.id, {
1177
+ owner: e,
1178
+ value: t
1179
+ })), this.emit();
1180
+ }
1181
+ unregisterOwner(e) {
1182
+ let t = !1;
1183
+ for (let [n, r] of this.entries) r.owner === e && (this.entries.delete(n), t = !0);
1184
+ t && this.emit();
1185
+ }
1186
+ get(e) {
1187
+ return this.entries.get(e)?.value;
1188
+ }
1189
+ list() {
1190
+ return [...this.entries.values()].map((e) => e.value);
1191
+ }
1192
+ ownerOf(e) {
1193
+ return this.entries.get(e)?.owner;
1194
+ }
1195
+ emit() {
1196
+ this.version += 1, this.listeners.forEach((e) => e());
1197
+ }
1198
+ }, ke = class {
1199
+ registry = new K();
1200
+ subscribe = this.registry.subscribe;
1201
+ getSnapshot = this.registry.getSnapshot;
1202
+ register(e, t) {
1203
+ this.registry.register(e, t);
1204
+ }
1205
+ assertCanReplace(e, t) {
1206
+ this.registry.assertCanReplace(e, t);
1207
+ }
1208
+ replaceOwner(e, t) {
1209
+ this.registry.replaceOwner(e, t);
1210
+ }
1211
+ unregisterOwner(e) {
1212
+ this.registry.unregisterOwner(e);
1213
+ }
1214
+ get(e) {
1215
+ return this.registry.get(e);
1216
+ }
1217
+ list() {
1218
+ return this.registry.list();
1219
+ }
1220
+ ownerOf(e) {
1221
+ return this.registry.ownerOf(e);
1222
+ }
1223
+ }, Ae = /^[a-z][a-z0-9.-]*$/;
1224
+ function je(e) {
1225
+ if (!Ae.test(e)) throw Error(`Service ID 无效: ${e}`);
1226
+ return Object.freeze({ id: e });
1227
+ }
1228
+ var Me = class {
1229
+ providers = /* @__PURE__ */ new Map();
1230
+ listeners = /* @__PURE__ */ new Set();
1231
+ version = 0;
1232
+ subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
1233
+ getSnapshot = () => this.version;
1234
+ assertCanReplace(e, t) {
1235
+ let n = /* @__PURE__ */ new Set();
1236
+ for (let r of t) {
1237
+ if (!Ae.test(r.id) || r.id !== r.token.id) throw Error(`Service ID 无效: ${r.id}`);
1238
+ if (n.has(r.id)) throw Error(`Service ID 重复: ${r.id} (${e})`);
1239
+ n.add(r.id);
1240
+ let t = this.providers.get(r.id);
1241
+ if (t && t.owner !== e) throw Error(`Service ID conflict: ${r.id} (${t.owner} / ${e})`);
1242
+ }
1243
+ }
1244
+ replaceOwner(e, t) {
1245
+ this.assertCanReplace(e, t);
1246
+ let n = !1;
1247
+ for (let [t, r] of this.providers) r.owner === e && (this.providers.delete(t), n = !0);
1248
+ for (let r of t) this.providers.set(r.id, {
1249
+ owner: e,
1250
+ definition: r
1251
+ }), n = !0;
1252
+ n && this.emit();
1253
+ }
1254
+ unregisterOwner(e) {
1255
+ let t = !1;
1256
+ for (let [n, r] of this.providers) r.owner === e && (this.providers.delete(n), t = !0);
1257
+ t && this.emit();
1258
+ }
1259
+ get(e) {
1260
+ return this.providers.get(e.id)?.definition.value;
1261
+ }
1262
+ require(e) {
1263
+ let t = this.get(e);
1264
+ if (!t) throw Error(`Service Provider 不可用: ${e.id}`);
1265
+ return t;
1266
+ }
1267
+ has(e) {
1268
+ return this.providers.has(e.id);
1269
+ }
1270
+ getOwnerDefinitions(e) {
1271
+ return [...this.providers.values()].filter((t) => t.owner === e).map((e) => e.definition);
1272
+ }
1273
+ ownerOf(e) {
1274
+ return this.providers.get(e.id)?.owner;
1275
+ }
1276
+ emit() {
1277
+ this.version += 1, this.listeners.forEach((e) => e());
1278
+ }
1279
+ }, Ne = /^[a-z][a-z0-9.-]*(\/[a-z][a-z0-9.-]*)+$/;
1280
+ function Pe(e) {
1281
+ if (!Ne.test(e)) throw Error(`Event ID 无效: ${e}`);
1282
+ return Object.freeze({ id: e });
1283
+ }
1284
+ var Fe = class {
1285
+ listeners = /* @__PURE__ */ new Map();
1286
+ reportFailure;
1287
+ constructor(e = () => void 0) {
1288
+ this.reportFailure = e;
1289
+ }
1290
+ setFailureReporter(e) {
1291
+ this.reportFailure = e;
1292
+ }
1293
+ replaceOwner(e, t) {
1294
+ this.assertDefinitions(t), this.unregisterOwner(e), t.forEach((t) => {
1295
+ let n = this.listeners.get(t.event.id) ?? [];
1296
+ n.push({
1297
+ owner: e,
1298
+ definition: t
1299
+ }), this.listeners.set(t.event.id, n);
1300
+ });
1301
+ }
1302
+ listen(e, t, n) {
1303
+ this.assertDefinitions([{
1304
+ event: t,
1305
+ listener: n
1306
+ }]);
1307
+ let r = this.listeners.get(t.id) ?? [], i = {
1308
+ owner: e,
1309
+ definition: {
1310
+ event: t,
1311
+ listener: n
1312
+ }
1313
+ };
1314
+ return r.push(i), this.listeners.set(t.id, r), () => {
1315
+ let e = this.listeners.get(t.id);
1316
+ if (!e) return;
1317
+ let n = e.filter((e) => e !== i);
1318
+ n.length ? this.listeners.set(t.id, n) : this.listeners.delete(t.id);
1319
+ };
1320
+ }
1321
+ unregisterOwner(e) {
1322
+ for (let [t, n] of this.listeners) {
1323
+ let r = n.filter((t) => t.owner !== e);
1324
+ r.length ? this.listeners.set(t, r) : this.listeners.delete(t);
1325
+ }
1326
+ }
1327
+ emit(e, t) {
1328
+ [...this.listeners.get(e.id) ?? []].forEach(({ owner: n, definition: r }) => {
1329
+ try {
1330
+ let i = r.listener(t);
1331
+ i && typeof i.then == "function" && i.catch((t) => this.reportFailure({
1332
+ eventId: e.id,
1333
+ owner: n,
1334
+ error: t
1335
+ }));
1336
+ } catch (t) {
1337
+ this.reportFailure({
1338
+ eventId: e.id,
1339
+ owner: n,
1340
+ error: t
1341
+ });
1342
+ }
1343
+ });
1344
+ }
1345
+ listenerCount(e) {
1346
+ return this.listeners.get(e.id)?.length ?? 0;
1347
+ }
1348
+ assertDefinitions(e) {
1349
+ e.forEach((e) => {
1350
+ if (!Ne.test(e.event.id)) throw Error(`Event ID 无效: ${e.event.id}`);
1351
+ if (typeof e.listener != "function") throw Error(`Event Listener 无效: ${e.event.id}`);
1352
+ });
1353
+ }
1354
+ };
1355
+ //#endregion
1356
+ //#region workbench/src/registry/stateRegistry.ts
1357
+ function Ie(e) {
1358
+ try {
1359
+ return structuredClone(e);
1360
+ } catch {
1361
+ return e;
1362
+ }
1363
+ }
1364
+ var Le = class {
1365
+ definitions = /* @__PURE__ */ new Map();
1366
+ cells = /* @__PURE__ */ new Map();
1367
+ assertCanReplace(e, t) {
1368
+ let n = /* @__PURE__ */ new Set();
1369
+ for (let r of t) {
1370
+ if (!r.id || n.has(r.id)) throw Error(`State ID 重复: ${r.id}`);
1371
+ n.add(r.id);
1372
+ let t = this.definitionKey(e, r.id), i = this.definitions.get(t);
1373
+ if (i && i.definition.scope !== r.scope) throw Error(`State Scope 不允许热变更: ${r.id}`);
1374
+ }
1375
+ }
1376
+ replaceOwner(e, t) {
1377
+ this.assertCanReplace(e, t), this.unregisterOwner(e);
1378
+ for (let n of t) this.definitions.set(this.definitionKey(e, n.id), {
1379
+ owner: e,
1380
+ definition: n
1381
+ });
1382
+ }
1383
+ unregisterOwner(e) {
1384
+ for (let [t, n] of this.definitions) n.owner === e && this.definitions.delete(t);
1385
+ }
1386
+ bind(e, t, n) {
1387
+ let r = this.definitions.get(this.definitionKey(e, t));
1388
+ if (!r) throw Error(`Unknown Element State: ${e}.${t}`);
1389
+ let i = this.cellKey(e, r.definition, n), a = this.cells.get(i);
1390
+ return a || (a = {
1391
+ value: Ie(r.definition.initialValue),
1392
+ listeners: /* @__PURE__ */ new Set()
1393
+ }, this.cells.set(i, a)), {
1394
+ read: () => a.value,
1395
+ write: (e) => {
1396
+ a.value = typeof e == "function" ? e(a.value) : e, a.listeners.forEach((e) => e());
1397
+ },
1398
+ subscribe: (e) => (a.listeners.add(e), () => a.listeners.delete(e))
1399
+ };
1400
+ }
1401
+ listDefinitions() {
1402
+ return [...this.definitions.values()].map(({ owner: e, definition: t }) => ({
1403
+ owner: e,
1404
+ definition: t
1405
+ }));
1406
+ }
1407
+ getOwnerDefinitions(e) {
1408
+ return [...this.definitions.values()].filter((t) => t.owner === e).map((e) => e.definition);
1409
+ }
1410
+ definitionKey(e, t) {
1411
+ return `${e}:${t}`;
1412
+ }
1413
+ cellKey(e, t, n) {
1414
+ let r = `${e}:${t.id}`;
1415
+ if (t.scope === "application") return `application:${r}`;
1416
+ if (t.scope === "project") return `project:${n.projectId ?? "no-project"}:${r}`;
1417
+ if (t.scope === "workspace") {
1418
+ if (!n.workspaceId) throw Error(`State ${t.id} 缺少 workspaceId`);
1419
+ return `workspace:${n.workspaceId}:${r}`;
1420
+ }
1421
+ if (!n.instanceId) throw Error(`State ${t.id} 缺少 instanceId`);
1422
+ return `instance:${e}:${n.instanceId}:${t.id}`;
1423
+ }
1424
+ }, Re = class {
1425
+ registry = new K();
1426
+ subscribe = this.registry.subscribe;
1427
+ getSnapshot = this.registry.getSnapshot;
1428
+ register(e, t) {
1429
+ this.registry.register(e, t);
1430
+ }
1431
+ assertCanReplace(e, t) {
1432
+ this.registry.assertCanReplace(e, t);
1433
+ }
1434
+ replaceOwner(e, t) {
1435
+ this.registry.replaceOwner(e, t);
1436
+ }
1437
+ unregisterOwner(e) {
1438
+ this.registry.unregisterOwner(e);
1439
+ }
1440
+ list(e) {
1441
+ let t = this.registry.list();
1442
+ return e ? t.filter((t) => t.point === e) : t;
1443
+ }
1444
+ };
1445
+ //#endregion
1446
+ //#region workbench/src/ui/AudioPlayer.tsx
1447
+ function ze(e) {
1448
+ return !Number.isFinite(e) || e < 0 ? "0:00" : `${Math.floor(e / 60)}:${Math.floor(e % 60).toString().padStart(2, "0")}`;
1449
+ }
1450
+ function Be({ source: e, label: t, className: n = "" }) {
1451
+ let r = l(null), [i, a] = u(!1), [o, s] = u(0), [c, d] = u(0);
1452
+ async function f() {
1453
+ let e = r.current;
1454
+ e && (e.paused ? await e.play().catch(() => void 0) : e.pause());
1455
+ }
1456
+ return /* @__PURE__ */ T("div", {
1457
+ className: `custom-audio ${n}`.trim(),
1458
+ children: [
1459
+ /* @__PURE__ */ w("audio", {
1460
+ ref: r,
1461
+ src: e,
1462
+ preload: "metadata",
1463
+ onDurationChange: (e) => d(e.currentTarget.duration || 0),
1464
+ onTimeUpdate: (e) => s(e.currentTarget.currentTime),
1465
+ onPlay: () => a(!0),
1466
+ onPause: () => a(!1),
1467
+ onEnded: () => a(!1)
1468
+ }),
1469
+ /* @__PURE__ */ w("button", {
1470
+ type: "button",
1471
+ "aria-label": i ? "暂停" : "播放",
1472
+ title: i ? "暂停" : "播放",
1473
+ onClick: () => void f(),
1474
+ children: w(i ? _ : y, { size: 13 })
1475
+ }),
1476
+ /* @__PURE__ */ w("strong", {
1477
+ title: t,
1478
+ children: t
1479
+ }),
1480
+ /* @__PURE__ */ w("input", {
1481
+ type: "range",
1482
+ "aria-label": "音频进度",
1483
+ min: 0,
1484
+ max: c || 0,
1485
+ step: .01,
1486
+ value: Math.min(o, c || 0),
1487
+ onChange: (e) => {
1488
+ let t = Number(e.target.value);
1489
+ r.current && (r.current.currentTime = t), s(t);
1490
+ }
1491
+ }),
1492
+ /* @__PURE__ */ T("span", { children: [
1493
+ ze(o),
1494
+ " / ",
1495
+ ze(c)
1496
+ ] })
1497
+ ]
1498
+ });
1499
+ }
1500
+ //#endregion
1501
+ //#region workbench/src/ui/LargeTextEditorDialog.tsx
1502
+ function Ve({ busy: e = !1, label: t = "文本内容", onChange: n, onClose: r, onSave: i, placeholder: a, readOnly: c = !1, saveDisabled: u = !1, saveLabel: d = "保存", title: f, value: p }) {
1503
+ let m = s(), h = l(null), g = l(e), _ = l(r), v = typeof document > "u" ? null : document;
1504
+ if (g.current = e, _.current = r, o(() => {
1505
+ if (!v) return;
1506
+ let e = v.activeElement;
1507
+ h.current?.focus();
1508
+ function t(e) {
1509
+ e.key !== "Escape" || g.current || (e.preventDefault(), _.current());
1510
+ }
1511
+ return v.addEventListener("keydown", t), () => {
1512
+ v.removeEventListener("keydown", t), e?.focus();
1513
+ };
1514
+ }, [v]), !v) return null;
1515
+ let y = !!i && !c && !e && !u;
1516
+ return S(/* @__PURE__ */ w("div", {
1517
+ className: "large-text-dialog-backdrop",
1518
+ role: "presentation",
1519
+ onMouseDown: (t) => {
1520
+ t.target === t.currentTarget && !e && r();
1521
+ },
1522
+ children: /* @__PURE__ */ T("form", {
1523
+ className: "large-text-dialog",
1524
+ role: "dialog",
1525
+ "aria-modal": "true",
1526
+ "aria-labelledby": m,
1527
+ onKeyDown: (e) => {
1528
+ e.key === "Enter" && (e.ctrlKey || e.metaKey) && y && (e.preventDefault(), i?.());
1529
+ },
1530
+ onSubmit: (e) => {
1531
+ e.preventDefault(), y && i?.();
1532
+ },
1533
+ children: [
1534
+ /* @__PURE__ */ T("header", { children: [/* @__PURE__ */ w("strong", {
1535
+ id: m,
1536
+ title: f,
1537
+ children: f
1538
+ }), /* @__PURE__ */ w("button", {
1539
+ type: "button",
1540
+ title: "关闭",
1541
+ "aria-label": "关闭",
1542
+ disabled: e,
1543
+ onClick: r,
1544
+ children: /* @__PURE__ */ w(x, { size: 17 })
1545
+ })] }),
1546
+ /* @__PURE__ */ T("label", { children: [/* @__PURE__ */ w("span", { children: t }), /* @__PURE__ */ w("textarea", {
1547
+ ref: h,
1548
+ spellCheck: !1,
1549
+ readOnly: c,
1550
+ value: p,
1551
+ placeholder: a,
1552
+ onChange: (e) => n(e.target.value)
1553
+ })] }),
1554
+ /* @__PURE__ */ w("footer", { children: c || !i ? /* @__PURE__ */ w("button", {
1555
+ type: "button",
1556
+ onClick: r,
1557
+ children: "关闭"
1558
+ }) : /* @__PURE__ */ T(C, { children: [
1559
+ /* @__PURE__ */ w("span", { children: "Ctrl / ⌘ + Enter 保存" }),
1560
+ /* @__PURE__ */ w("button", {
1561
+ type: "button",
1562
+ disabled: e,
1563
+ onClick: r,
1564
+ children: "取消"
1565
+ }),
1566
+ /* @__PURE__ */ w("button", {
1567
+ className: "is-primary",
1568
+ type: "submit",
1569
+ disabled: !y,
1570
+ children: d
1571
+ })
1572
+ ] }) })
1573
+ ]
1574
+ })
1575
+ }), v.body);
1576
+ }
1577
+ //#endregion
1578
+ //#region workbench/src/workspaces/layoutPreferences.ts
1579
+ var He = "graphvideo-workspace-default-layouts-v1", Ue = "graphvideo-active-workspace-v1";
1580
+ function q(e) {
1581
+ return !!e && typeof e == "object" && !Array.isArray(e);
1582
+ }
1583
+ function J(e, t = /* @__PURE__ */ new Set()) {
1584
+ if (!q(e) || typeof e.id != "string" || t.has(e.id)) return !1;
1585
+ if (t.add(e.id), e.kind === "area") {
1586
+ let t = e.panelInstanceIds;
1587
+ return typeof e.activePanelId != "string" || !Array.isArray(e.panelHistory) || !e.panelHistory.every((e) => typeof e == "string") || !e.panelHistory.includes(e.activePanelId) || !q(t) ? !1 : e.panelHistory.every((e) => typeof t[e] == "string");
1588
+ }
1589
+ return e.kind === "split" && (e.direction === "horizontal" || e.direction === "vertical") && typeof e.ratio == "number" && e.ratio >= .15 && e.ratio <= .85 && J(e.first, t) && J(e.second, t);
1590
+ }
1591
+ function We() {
1592
+ try {
1593
+ if (typeof localStorage > "u" || typeof localStorage.getItem != "function") return {};
1594
+ let e = JSON.parse(localStorage.getItem(He) ?? "{}");
1595
+ return q(e) ? e : {};
1596
+ } catch {
1597
+ return {};
1598
+ }
1599
+ }
1600
+ function Ge(e) {
1601
+ let t = We()[e];
1602
+ if (!q(t) || !J(t.layout)) return null;
1603
+ let n = P(t.layout), r = typeof t.focusedAreaId == "string" && n.some((e) => e.id === t.focusedAreaId) ? t.focusedAreaId : n[0]?.id;
1604
+ return r ? {
1605
+ layout: t.layout,
1606
+ focusedAreaId: r
1607
+ } : null;
1608
+ }
1609
+ function Ke(e) {
1610
+ let t = We();
1611
+ t[e.id] = {
1612
+ layout: e.layout,
1613
+ focusedAreaId: e.focusedAreaId
1614
+ }, typeof localStorage < "u" && typeof localStorage.setItem == "function" && localStorage.setItem(He, JSON.stringify(t));
1615
+ }
1616
+ function qe() {
1617
+ return typeof localStorage > "u" || typeof localStorage.getItem != "function" ? null : localStorage.getItem(Ue)?.trim() || null;
1618
+ }
1619
+ function Je(e) {
1620
+ typeof localStorage < "u" && typeof localStorage.setItem == "function" && localStorage.setItem(Ue, e);
1621
+ }
1622
+ //#endregion
1623
+ //#region workbench/src/workspaces/manifest.ts
1624
+ var Y = /^[a-z0-9][a-z0-9._-]*$/;
1625
+ function X(e, t) {
1626
+ if (!e || typeof e != "object" || Array.isArray(e)) throw Error("Workspace layout 节点必须是对象");
1627
+ let n = e;
1628
+ if (typeof n.id != "string" || !Y.test(n.id) || t.has(n.id)) throw Error(`Workspace layout ID 无效或重复: ${String(n.id)}`);
1629
+ if (t.add(n.id), n.kind === "area") {
1630
+ if (typeof n.panelId != "string" || !Y.test(n.panelId) || typeof n.instanceId != "string" || !Y.test(n.instanceId)) throw Error(`Workspace Area ${n.id} 缺少 panelId/instanceId`);
1631
+ return {
1632
+ kind: "area",
1633
+ id: n.id,
1634
+ panelId: n.panelId,
1635
+ instanceId: n.instanceId
1636
+ };
1637
+ }
1638
+ if (n.kind !== "split" || n.direction !== "horizontal" && n.direction !== "vertical") throw Error(`Workspace 节点 ${n.id} 的 kind/direction 无效`);
1639
+ if (typeof n.ratio != "number" || n.ratio < .15 || n.ratio > .85) throw Error(`Workspace Split ${n.id} 的 ratio 必须在 0.15 到 0.85 之间`);
1640
+ return {
1641
+ kind: "split",
1642
+ id: n.id,
1643
+ direction: n.direction,
1644
+ ratio: n.ratio,
1645
+ first: X(n.first, t),
1646
+ second: X(n.second, t)
1647
+ };
1648
+ }
1649
+ function Ye(e, t) {
1650
+ let n;
1651
+ try {
1652
+ n = JSON.parse(t);
1653
+ } catch {
1654
+ throw Error(`Workspace ${e} 的 workspace.json 不是有效 JSON`);
1655
+ }
1656
+ if (!n || typeof n != "object" || Array.isArray(n)) throw Error(`Workspace ${e} 必须是对象`);
1657
+ let r = n;
1658
+ if (r.id !== e || typeof r.name != "string" || !r.name.trim()) throw Error(`Workspace ${e} 的 id/name 无效`);
1659
+ if (typeof r.order != "number" || !Number.isFinite(r.order)) throw Error(`Workspace ${e} 的 order 无效`);
1660
+ return {
1661
+ id: e,
1662
+ name: r.name.trim(),
1663
+ order: r.order,
1664
+ layout: X(r.layout, /* @__PURE__ */ new Set())
1665
+ };
1666
+ }
1667
+ function Z(e) {
1668
+ return e.kind === "area" ? {
1669
+ kind: "area",
1670
+ id: e.id,
1671
+ activePanelId: e.panelId,
1672
+ panelHistory: [e.panelId],
1673
+ panelInstanceIds: { [e.panelId]: e.instanceId }
1674
+ } : {
1675
+ ...e,
1676
+ first: Z(e.first),
1677
+ second: Z(e.second)
1678
+ };
1679
+ }
1680
+ function Xe(e) {
1681
+ return e.kind === "area" ? e.id : Xe(e.first);
1682
+ }
1683
+ function Ze(e) {
1684
+ return {
1685
+ id: e.id,
1686
+ name: e.name,
1687
+ order: e.order,
1688
+ layout: Z(e.layout),
1689
+ focusedAreaId: Xe(e.layout),
1690
+ maximizedAreaId: null
1691
+ };
1692
+ }
1693
+ //#endregion
1694
+ //#region workbench/src/workspaces/WorkspaceTabs.tsx
1695
+ function Qe() {
1696
+ let { commands: e } = A(), t = j((e) => Object.values(e.items).sort((e, t) => e.order - t.order || e.id.localeCompare(t.id))), n = j((e) => e.activeWorkspaceId);
1697
+ return /* @__PURE__ */ w("nav", {
1698
+ className: "workspace-tabs",
1699
+ "aria-label": "工作区",
1700
+ children: t.map((t) => /* @__PURE__ */ w("button", {
1701
+ className: t.id === n ? "is-active" : "",
1702
+ type: "button",
1703
+ onClick: () => void e.execute("workspace.activate", t.id),
1704
+ children: t.name
1705
+ }, t.id))
1706
+ });
1707
+ }
1708
+ //#endregion
1709
+ //#region workbench/src/workspaces/WorkspacePages.tsx
1710
+ function $e() {
1711
+ let e = j((e) => Object.values(e.items).sort((e, t) => e.order - t.order || e.id.localeCompare(t.id)).map((e) => e.id)), t = j((e) => e.activeWorkspaceId);
1712
+ return /* @__PURE__ */ w("div", {
1713
+ className: "workspace-pages",
1714
+ children: e.map((e) => /* @__PURE__ */ w(Se, {
1715
+ workspaceId: e,
1716
+ active: e === t
1717
+ }, e))
1718
+ });
1719
+ }
1720
+ //#endregion
1721
+ //#region workbench/src/workspaces/workspaceCommands.ts
1722
+ function et(e, t, n = "core") {
1723
+ e.register("workspace.activate", (e) => {
1724
+ t.activate(e), Je(e);
1725
+ }, n), e.register("workspace.layout.save-default", (e) => {
1726
+ let n = t.readWorkspace(e);
1727
+ if (!n) throw Error(`工作区不存在:${e}`);
1728
+ Ke(n);
1729
+ }, n), e.register("workspace.area.focus", ({ workspaceId: e, areaId: n }) => t.focus(e, n), n), e.register("workspace.panel.switch", ({ workspaceId: e, areaId: n, panelId: r }) => t.switchPanel(e, n, r), n), e.register("workspace.area.split", ({ workspaceId: e, areaId: n, direction: r }) => t.splitArea(e, n, r), n), e.register("workspace.area.close", ({ workspaceId: e, areaId: n }) => t.closeArea(e, n), n), e.register("workspace.split.resize", ({ workspaceId: e, splitId: n, ratio: r, historyGroupId: i }) => t.resizeSplit(e, n, r, i), n), e.register("workspace.area.swap", ({ workspaceId: e, sourceAreaId: n, targetAreaId: r }) => t.swapAreas(e, n, r), n), e.register("workspace.area.maximize", ({ workspaceId: e, areaId: n }) => t.toggleMaximize(e, n), n);
1730
+ }
1731
+ //#endregion
1732
+ //#region workbench/src/preferences/themePreferences.ts
1733
+ var tt = [
1734
+ "dark",
1735
+ "light",
1736
+ "xueqing",
1737
+ "shiliuqun"
1738
+ ], nt = "dark", Q = "graphvideo-theme", rt = "graphvideo-theme-change", it = {
1739
+ getItem: (e) => typeof localStorage < "u" && typeof localStorage.getItem == "function" ? localStorage.getItem(e) : null,
1740
+ setItem: (e, t) => {
1741
+ typeof localStorage < "u" && typeof localStorage.setItem == "function" && localStorage.setItem(e, t);
1742
+ }
1743
+ };
1744
+ function at(e) {
1745
+ return tt.includes(e);
1746
+ }
1747
+ function ot(e = nt, t = it) {
1748
+ let n = t.getItem(Q);
1749
+ return at(n) ? n : e;
1750
+ }
1751
+ function st(e, t = document.documentElement, n = it) {
1752
+ t.dataset.theme = e, n.setItem(Q, e);
1753
+ let r = t.ownerDocument?.defaultView;
1754
+ r && typeof r.dispatchEvent == "function" && r.dispatchEvent(new Event(rt));
1755
+ }
1756
+ //#endregion
1757
+ //#region workbench/src/preferences/typographyPreferences.ts
1758
+ var ct = "graphvideo-interface-font", lt = "graphvideo-interface-font-size", ut = [
1759
+ "default",
1760
+ "system",
1761
+ "mono"
1762
+ ], dt = [
1763
+ "compact",
1764
+ "standard",
1765
+ "comfortable"
1766
+ ], ft = [
1767
+ {
1768
+ value: "default",
1769
+ label: "默认"
1770
+ },
1771
+ {
1772
+ value: "system",
1773
+ label: "系统"
1774
+ },
1775
+ {
1776
+ value: "mono",
1777
+ label: "等宽"
1778
+ }
1779
+ ], pt = [
1780
+ {
1781
+ value: "compact",
1782
+ label: "紧凑"
1783
+ },
1784
+ {
1785
+ value: "standard",
1786
+ label: "标准"
1787
+ },
1788
+ {
1789
+ value: "comfortable",
1790
+ label: "舒适"
1791
+ }
1792
+ ], $ = {
1793
+ getItem: (e) => typeof localStorage < "u" && typeof localStorage.getItem == "function" ? localStorage.getItem(e) : null,
1794
+ setItem: (e, t) => {
1795
+ typeof localStorage < "u" && typeof localStorage.setItem == "function" && localStorage.setItem(e, t);
1796
+ }
1797
+ };
1798
+ function mt(e = $) {
1799
+ let t = e.getItem(ct), n = e.getItem(lt);
1800
+ return {
1801
+ font: t && ut.includes(t) ? t : "default",
1802
+ size: n && dt.includes(n) ? n : "standard"
1803
+ };
1804
+ }
1805
+ function ht(e, t = document.documentElement, n = $) {
1806
+ t.dataset.fontFamily = e.font, t.dataset.fontSize = e.size, n.setItem(ct, e.font), n.setItem(lt, e.size);
1807
+ }
1808
+ //#endregion
1809
+ export { me as AreaShell, Be as AudioPlayer, E as CommandRegistry, Te as ElementLoader, Ee as ElementRuntimeManager, Le as ElementStateRegistry, Fe as EventRegistry, Re as ExtensionRegistry, M as ExtensionSlot, oe as FloatingScrollbars, N as InlineSelect, Ve as LargeTextEditorDialog, K as OwnedRegistry, ke as PanelRegistry, Oe as PluginRuntimeManager, Me as ServiceRegistry, O as WorkbenchContextStore, k as WorkbenchHostContext, Se as Workspace, $e as WorkspacePages, Qe as WorkspaceTabs, st as applyThemePreference, ht as applyTypographyPreferences, L as canCloseArea, le as closeArea, ye as createSplitResizeGesture, Ze as createWorkspaceRuntime, nt as defaultTheme, De as defineElement, Pe as defineEvent, je as defineService, te as defineWorkbenchContext, I as excludeAreas, F as findArea, ft as interfaceFontOptions, pt as interfaceFontSizeOptions, V as isOutsideViewport, at as isThemeName, P as listAreas, qe as loadActiveWorkspacePreference, Ge as loadWorkspaceDefault, we as parseElementManifest, Ye as parseWorkspaceDefinition, fe as prepareFloatingWindow, ot as readThemePreference, mt as readTypographyPreferences, et as registerWorkspaceCommands, B as resizeSplit, Je as saveActiveWorkspacePreference, Ke as saveWorkspaceDefault, ce as splitArea, ue as swapAreaPanels, se as switchAreaPanel, U as synchronizeFloatingRoot, tt as themeNames, A as useWorkbenchServices, j as useWorkbenchWorkspace };