@flowgram.ai/panel-manager-plugin 0.4.15
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/.eslintrc.cjs +17 -0
- package/.rush/temp/chunked-rush-logs/panel-manager-plugin.build.chunks.jsonl +21 -0
- package/.rush/temp/package-deps_build.json +22 -0
- package/.rush/temp/shrinkwrap-deps.json +158 -0
- package/CHANGELOG.json +11 -0
- package/CHANGELOG.md +9 -0
- package/dist/esm/index.js +259 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +72 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -0
- package/package.json +50 -0
- package/rush-logs/panel-manager-plugin.build.log +21 -0
- package/src/components/panel-layer/css.ts +61 -0
- package/src/components/panel-layer/float-panel.tsx +35 -0
- package/src/components/panel-layer/index.ts +6 -0
- package/src/components/panel-layer/panel-layer.tsx +23 -0
- package/src/create-panel-manager-plugin.ts +23 -0
- package/src/hooks/use-panel-manager.ts +10 -0
- package/src/index.ts +16 -0
- package/src/services/float-panel.ts +51 -0
- package/src/services/index.ts +8 -0
- package/src/services/panel-config.ts +30 -0
- package/src/services/panel-layer.ts +44 -0
- package/src/services/panel-manager.ts +54 -0
- package/src/types.ts +16 -0
- package/tsconfig.json +12 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as _flowgram_ai_core from '@flowgram.ai/core';
|
|
2
|
+
import * as _flowgram_ai_utils from '@flowgram.ai/utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
6
|
+
* SPDX-License-Identifier: MIT
|
|
7
|
+
*/
|
|
8
|
+
type Area = 'right' | 'bottom';
|
|
9
|
+
interface PanelConfig {
|
|
10
|
+
/** max panel */
|
|
11
|
+
max: number;
|
|
12
|
+
}
|
|
13
|
+
interface PanelFactory<T extends any> {
|
|
14
|
+
key: string;
|
|
15
|
+
render: (props: T) => React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface PanelElement {
|
|
19
|
+
key: string;
|
|
20
|
+
el: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
declare class FloatPanel {
|
|
23
|
+
private config;
|
|
24
|
+
elements: PanelElement[];
|
|
25
|
+
private onUpdateEmitter;
|
|
26
|
+
onUpdate: _flowgram_ai_utils.Event<void>;
|
|
27
|
+
constructor(config: PanelConfig);
|
|
28
|
+
open(factory: PanelFactory<any>, options: any): void;
|
|
29
|
+
close(key?: string): void;
|
|
30
|
+
dispose(): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
35
|
+
* SPDX-License-Identifier: MIT
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
declare class PanelManager {
|
|
39
|
+
private readonly config;
|
|
40
|
+
readonly panelRegistry: Map<string, PanelFactory<any>>;
|
|
41
|
+
right: FloatPanel;
|
|
42
|
+
bottom: FloatPanel;
|
|
43
|
+
init(): void;
|
|
44
|
+
register<T extends any>(factory: PanelFactory<T>): void;
|
|
45
|
+
open(key: string, area?: Area, options?: any): void;
|
|
46
|
+
close(key: string, area?: Area): void;
|
|
47
|
+
getPanel(area: Area): FloatPanel;
|
|
48
|
+
dispose(): void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
53
|
+
* SPDX-License-Identifier: MIT
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
interface PanelManagerConfig {
|
|
57
|
+
factories: PanelFactory<any>[];
|
|
58
|
+
right: PanelConfig;
|
|
59
|
+
bottom: PanelConfig;
|
|
60
|
+
}
|
|
61
|
+
declare const PanelManagerConfig: unique symbol;
|
|
62
|
+
|
|
63
|
+
declare const createPanelManagerPlugin: _flowgram_ai_core.PluginCreator<Partial<PanelManagerConfig>>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
67
|
+
* SPDX-License-Identifier: MIT
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
declare const usePanelManager: () => PanelManager;
|
|
71
|
+
|
|
72
|
+
export { type Area, type PanelFactory, PanelManager, createPanelManagerPlugin, usePanelManager };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
20
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
21
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
22
|
+
if (decorator = decorators[i])
|
|
23
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
24
|
+
if (kind && result) __defProp(target, key, result);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/index.ts
|
|
29
|
+
var index_exports = {};
|
|
30
|
+
__export(index_exports, {
|
|
31
|
+
PanelManager: () => PanelManager,
|
|
32
|
+
createPanelManagerPlugin: () => createPanelManagerPlugin,
|
|
33
|
+
usePanelManager: () => usePanelManager
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/create-panel-manager-plugin.ts
|
|
38
|
+
var import_core3 = require("@flowgram.ai/core");
|
|
39
|
+
|
|
40
|
+
// src/services/panel-config.ts
|
|
41
|
+
var PanelManagerConfig = Symbol("PanelManagerConfig");
|
|
42
|
+
var defineConfig = (config) => {
|
|
43
|
+
const defaultConfig = {
|
|
44
|
+
right: {
|
|
45
|
+
max: 1
|
|
46
|
+
},
|
|
47
|
+
bottom: {
|
|
48
|
+
max: 1
|
|
49
|
+
},
|
|
50
|
+
factories: []
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
...defaultConfig,
|
|
54
|
+
...config
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/services/panel-manager.ts
|
|
59
|
+
var import_inversify = require("inversify");
|
|
60
|
+
|
|
61
|
+
// src/services/float-panel.ts
|
|
62
|
+
var import_utils = require("@flowgram.ai/utils");
|
|
63
|
+
var FloatPanel = class {
|
|
64
|
+
constructor(config) {
|
|
65
|
+
this.config = config;
|
|
66
|
+
this.elements = [];
|
|
67
|
+
this.onUpdateEmitter = new import_utils.Emitter();
|
|
68
|
+
this.onUpdate = this.onUpdateEmitter.event;
|
|
69
|
+
}
|
|
70
|
+
open(factory, options) {
|
|
71
|
+
const el = factory.render(options?.props);
|
|
72
|
+
const idx = this.elements.findIndex((e) => e.key === factory.key);
|
|
73
|
+
if (idx >= 0) {
|
|
74
|
+
this.elements[idx] = { el, key: factory.key };
|
|
75
|
+
} else {
|
|
76
|
+
this.elements.push({ el, key: factory.key });
|
|
77
|
+
if (this.elements.length > this.config.max) {
|
|
78
|
+
this.elements.shift();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this.onUpdateEmitter.fire();
|
|
82
|
+
}
|
|
83
|
+
close(key) {
|
|
84
|
+
if (!key) {
|
|
85
|
+
this.elements = [];
|
|
86
|
+
} else {
|
|
87
|
+
this.elements = this.elements.filter((e) => e.key !== key);
|
|
88
|
+
}
|
|
89
|
+
this.onUpdateEmitter.fire();
|
|
90
|
+
}
|
|
91
|
+
dispose() {
|
|
92
|
+
this.elements = [];
|
|
93
|
+
this.onUpdateEmitter.dispose();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/services/panel-manager.ts
|
|
98
|
+
var PanelManager = class {
|
|
99
|
+
constructor() {
|
|
100
|
+
this.panelRegistry = /* @__PURE__ */ new Map();
|
|
101
|
+
}
|
|
102
|
+
init() {
|
|
103
|
+
this.config.factories.forEach((factory) => this.register(factory));
|
|
104
|
+
this.right = new FloatPanel(this.config.right);
|
|
105
|
+
this.bottom = new FloatPanel(this.config.bottom);
|
|
106
|
+
}
|
|
107
|
+
register(factory) {
|
|
108
|
+
this.panelRegistry.set(factory.key, factory);
|
|
109
|
+
}
|
|
110
|
+
open(key, area = "right", options) {
|
|
111
|
+
const factory = this.panelRegistry.get(key);
|
|
112
|
+
if (!factory) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const panel = this.getPanel(area);
|
|
116
|
+
panel.open(factory, options);
|
|
117
|
+
}
|
|
118
|
+
close(key, area = "right") {
|
|
119
|
+
const panel = this.getPanel(area);
|
|
120
|
+
panel.close(key);
|
|
121
|
+
}
|
|
122
|
+
getPanel(area) {
|
|
123
|
+
return area === "right" ? this.right : this.bottom;
|
|
124
|
+
}
|
|
125
|
+
dispose() {
|
|
126
|
+
this.right.dispose();
|
|
127
|
+
this.bottom.dispose();
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
__decorateClass([
|
|
131
|
+
(0, import_inversify.inject)(PanelManagerConfig)
|
|
132
|
+
], PanelManager.prototype, "config", 2);
|
|
133
|
+
PanelManager = __decorateClass([
|
|
134
|
+
(0, import_inversify.injectable)()
|
|
135
|
+
], PanelManager);
|
|
136
|
+
|
|
137
|
+
// src/services/panel-layer.ts
|
|
138
|
+
var import_react2 = require("react");
|
|
139
|
+
var import_inversify2 = require("inversify");
|
|
140
|
+
var import_utils2 = require("@flowgram.ai/utils");
|
|
141
|
+
var import_core2 = require("@flowgram.ai/core");
|
|
142
|
+
|
|
143
|
+
// src/components/panel-layer/float-panel.tsx
|
|
144
|
+
var import_react = require("react");
|
|
145
|
+
|
|
146
|
+
// src/hooks/use-panel-manager.ts
|
|
147
|
+
var import_core = require("@flowgram.ai/core");
|
|
148
|
+
var usePanelManager = () => (0, import_core.useService)(PanelManager);
|
|
149
|
+
|
|
150
|
+
// src/components/panel-layer/css.ts
|
|
151
|
+
var panelLayer = {
|
|
152
|
+
pointerEvents: "none",
|
|
153
|
+
position: "absolute",
|
|
154
|
+
top: 0,
|
|
155
|
+
left: 0,
|
|
156
|
+
display: "flex",
|
|
157
|
+
columnGap: "4px",
|
|
158
|
+
width: "100%",
|
|
159
|
+
height: "100%",
|
|
160
|
+
padding: "4px",
|
|
161
|
+
boxSizing: "border-box"
|
|
162
|
+
};
|
|
163
|
+
var leftArea = {
|
|
164
|
+
width: "100%",
|
|
165
|
+
minWidth: 0,
|
|
166
|
+
flexGrow: 0,
|
|
167
|
+
flexShrink: 1,
|
|
168
|
+
display: "flex",
|
|
169
|
+
flexDirection: "column",
|
|
170
|
+
rowGap: "4px"
|
|
171
|
+
};
|
|
172
|
+
var rightArea = {
|
|
173
|
+
height: "100%",
|
|
174
|
+
flexGrow: 1,
|
|
175
|
+
flexShrink: 0,
|
|
176
|
+
minWidth: 0,
|
|
177
|
+
display: "flex",
|
|
178
|
+
columnGap: "4px"
|
|
179
|
+
};
|
|
180
|
+
var mainArea = {
|
|
181
|
+
position: "relative",
|
|
182
|
+
overflow: "hidden",
|
|
183
|
+
flexGrow: 0,
|
|
184
|
+
flexShrink: 1,
|
|
185
|
+
width: "100%",
|
|
186
|
+
height: "100%"
|
|
187
|
+
};
|
|
188
|
+
var bottomArea = {
|
|
189
|
+
flexGrow: 1,
|
|
190
|
+
flexShrink: 0,
|
|
191
|
+
width: "100%",
|
|
192
|
+
minHeight: 0
|
|
193
|
+
};
|
|
194
|
+
var floatPanelWrap = {
|
|
195
|
+
pointerEvents: "auto",
|
|
196
|
+
height: "100%",
|
|
197
|
+
width: "100%"
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
// src/components/panel-layer/float-panel.tsx
|
|
201
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
202
|
+
var FloatPanel2 = ({ area }) => {
|
|
203
|
+
const [, setVersion] = (0, import_react.useState)(0);
|
|
204
|
+
const panelManager = usePanelManager();
|
|
205
|
+
const panel = (0, import_react.useRef)(panelManager.getPanel(area));
|
|
206
|
+
const render = () => panel.current.elements.map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "float-panel-wrap", style: floatPanelWrap, children: i.el }, i.key));
|
|
207
|
+
const node = (0, import_react.useRef)(render());
|
|
208
|
+
(0, import_react.useEffect)(() => {
|
|
209
|
+
const dispose = panel.current.onUpdate(() => {
|
|
210
|
+
(0, import_react.startTransition)(() => {
|
|
211
|
+
node.current = render();
|
|
212
|
+
setVersion((v) => v + 1);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
return () => dispose.dispose();
|
|
216
|
+
}, [panel]);
|
|
217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: node.current });
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
// src/components/panel-layer/panel-layer.tsx
|
|
221
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
222
|
+
var PanelLayer = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "panel-layer", style: panelLayer, children: [
|
|
223
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "left-area", style: leftArea, children: [
|
|
224
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "main-area", style: mainArea, children }),
|
|
225
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "bottom-area", style: bottomArea, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FloatPanel2, { area: "bottom" }) })
|
|
226
|
+
] }),
|
|
227
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "right-area", style: rightArea, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FloatPanel2, { area: "right" }) })
|
|
228
|
+
] });
|
|
229
|
+
|
|
230
|
+
// src/services/panel-layer.ts
|
|
231
|
+
var PanelLayer2 = class extends import_core2.Layer {
|
|
232
|
+
constructor() {
|
|
233
|
+
super(...arguments);
|
|
234
|
+
this.node = import_utils2.domUtils.createDivWithClass("gedit-flow-panel-layer");
|
|
235
|
+
this.layout = null;
|
|
236
|
+
}
|
|
237
|
+
onReady() {
|
|
238
|
+
const commonStyle = {
|
|
239
|
+
pointerEvents: "none",
|
|
240
|
+
zIndex: 11
|
|
241
|
+
};
|
|
242
|
+
import_utils2.domUtils.setStyle(this.node, commonStyle);
|
|
243
|
+
this.config.onDataChange(() => {
|
|
244
|
+
const { width, height, scrollX, scrollY } = this.config.config;
|
|
245
|
+
import_utils2.domUtils.setStyle(this.node, {
|
|
246
|
+
...commonStyle,
|
|
247
|
+
width,
|
|
248
|
+
height,
|
|
249
|
+
left: scrollX,
|
|
250
|
+
top: scrollY
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
render() {
|
|
255
|
+
if (!this.layout) {
|
|
256
|
+
this.layout = (0, import_react2.createElement)(PanelLayer);
|
|
257
|
+
}
|
|
258
|
+
return this.layout;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
PanelLayer2 = __decorateClass([
|
|
262
|
+
(0, import_inversify2.injectable)()
|
|
263
|
+
], PanelLayer2);
|
|
264
|
+
|
|
265
|
+
// src/create-panel-manager-plugin.ts
|
|
266
|
+
var createPanelManagerPlugin = (0, import_core3.definePluginCreator)({
|
|
267
|
+
onBind: ({ bind }) => {
|
|
268
|
+
bind(PanelManager).to(PanelManager).inSingletonScope();
|
|
269
|
+
bind(PanelManagerConfig).toConstantValue(defineConfig({}));
|
|
270
|
+
},
|
|
271
|
+
onInit(ctx, opt) {
|
|
272
|
+
ctx.playground.registerLayer(PanelLayer2);
|
|
273
|
+
const config = defineConfig(opt);
|
|
274
|
+
ctx.container.rebind(PanelManagerConfig).toConstantValue(config);
|
|
275
|
+
const panelManager = ctx.container.get(PanelManager);
|
|
276
|
+
panelManager.init();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
280
|
+
0 && (module.exports = {
|
|
281
|
+
PanelManager,
|
|
282
|
+
createPanelManagerPlugin,
|
|
283
|
+
usePanelManager
|
|
284
|
+
});
|
|
285
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-panel-manager-plugin.ts","../src/services/panel-config.ts","../src/services/panel-manager.ts","../src/services/float-panel.ts","../src/services/panel-layer.ts","../src/components/panel-layer/float-panel.tsx","../src/hooks/use-panel-manager.ts","../src/components/panel-layer/css.ts","../src/components/panel-layer/panel-layer.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n/** create plugin function */\nexport { createPanelManagerPlugin } from './create-panel-manager-plugin';\n\n/** services */\nexport { PanelManager } from './services';\n\n/** react hooks */\nexport { usePanelManager } from './hooks/use-panel-manager';\n\n/** types */\nexport type { Area, PanelFactory } from './types';\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { definePluginCreator } from '@flowgram.ai/core';\n\nimport { defineConfig } from './services/panel-config';\nimport { PanelManager, PanelManagerConfig, PanelLayer } from './services';\n\nexport const createPanelManagerPlugin = definePluginCreator<Partial<PanelManagerConfig>>({\n onBind: ({ bind }) => {\n bind(PanelManager).to(PanelManager).inSingletonScope();\n bind(PanelManagerConfig).toConstantValue(defineConfig({}));\n },\n onInit(ctx, opt) {\n ctx.playground.registerLayer(PanelLayer);\n const config = defineConfig(opt);\n ctx.container.rebind(PanelManagerConfig).toConstantValue(config);\n const panelManager = ctx.container.get<PanelManager>(PanelManager);\n panelManager.init();\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport type { PanelFactory, PanelConfig } from '../types';\n\nexport interface PanelManagerConfig {\n factories: PanelFactory<any>[];\n right: PanelConfig;\n bottom: PanelConfig;\n}\n\nexport const PanelManagerConfig = Symbol('PanelManagerConfig');\n\nexport const defineConfig = (config: Partial<PanelManagerConfig>) => {\n const defaultConfig: PanelManagerConfig = {\n right: {\n max: 1,\n },\n bottom: {\n max: 1,\n },\n factories: [],\n };\n return {\n ...defaultConfig,\n ...config,\n };\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { injectable, inject } from 'inversify';\n\nimport { PanelManagerConfig } from './panel-config';\nimport type { Area, PanelFactory } from '../types';\nimport { FloatPanel } from './float-panel';\n\n@injectable()\nexport class PanelManager {\n @inject(PanelManagerConfig) private readonly config: PanelManagerConfig;\n\n readonly panelRegistry = new Map<string, PanelFactory<any>>();\n\n right: FloatPanel;\n\n bottom: FloatPanel;\n\n init() {\n this.config.factories.forEach((factory) => this.register(factory));\n this.right = new FloatPanel(this.config.right);\n this.bottom = new FloatPanel(this.config.bottom);\n }\n\n register<T extends any>(factory: PanelFactory<T>) {\n this.panelRegistry.set(factory.key, factory);\n }\n\n open(key: string, area: Area = 'right', options?: any) {\n const factory = this.panelRegistry.get(key);\n if (!factory) {\n return;\n }\n const panel = this.getPanel(area);\n panel.open(factory, options);\n }\n\n close(key: string, area: Area = 'right') {\n const panel = this.getPanel(area);\n panel.close(key);\n }\n\n getPanel(area: Area) {\n return area === 'right' ? this.right : this.bottom;\n }\n\n dispose() {\n this.right.dispose();\n this.bottom.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { Emitter } from '@flowgram.ai/utils';\n\nimport type { PanelFactory, PanelConfig } from '../types';\n\nexport interface PanelElement {\n key: string;\n el: React.ReactNode;\n}\n\nexport class FloatPanel {\n elements: PanelElement[] = [];\n\n private onUpdateEmitter = new Emitter<void>();\n\n onUpdate = this.onUpdateEmitter.event;\n\n constructor(private config: PanelConfig) {}\n\n open(factory: PanelFactory<any>, options: any) {\n const el = factory.render(options?.props);\n const idx = this.elements.findIndex((e) => e.key === factory.key);\n if (idx >= 0) {\n this.elements[idx] = { el, key: factory.key };\n } else {\n this.elements.push({ el, key: factory.key });\n if (this.elements.length > this.config.max) {\n this.elements.shift();\n }\n }\n this.onUpdateEmitter.fire();\n }\n\n close(key?: string) {\n if (!key) {\n this.elements = [];\n } else {\n this.elements = this.elements.filter((e) => e.key !== key);\n }\n this.onUpdateEmitter.fire();\n }\n\n dispose() {\n this.elements = [];\n this.onUpdateEmitter.dispose();\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { createElement } from 'react';\n\nimport { injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Layer } from '@flowgram.ai/core';\n\nimport { PanelLayer as PanelLayerComp } from '../components/panel-layer';\n\n@injectable()\nexport class PanelLayer extends Layer {\n node = domUtils.createDivWithClass('gedit-flow-panel-layer');\n\n layout: JSX.Element | null = null;\n\n onReady(): void {\n const commonStyle = {\n pointerEvents: 'none',\n zIndex: 11,\n };\n domUtils.setStyle(this.node, commonStyle);\n this.config.onDataChange(() => {\n const { width, height, scrollX, scrollY } = this.config.config;\n domUtils.setStyle(this.node, {\n ...commonStyle,\n width,\n height,\n left: scrollX,\n top: scrollY,\n });\n });\n }\n\n render(): JSX.Element {\n if (!this.layout) {\n this.layout = createElement(PanelLayerComp);\n }\n return this.layout;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEffect, useRef, startTransition, useState } from 'react';\n\nimport { Area } from '../../types';\nimport { usePanelManager } from '../../hooks/use-panel-manager';\nimport { floatPanelWrap } from './css';\n\nexport const FloatPanel: React.FC<{ area: Area }> = ({ area }) => {\n const [, setVersion] = useState(0);\n const panelManager = usePanelManager();\n const panel = useRef(panelManager.getPanel(area));\n const render = () =>\n panel.current.elements.map((i) => (\n <div className=\"float-panel-wrap\" key={i.key} style={floatPanelWrap}>\n {i.el}\n </div>\n ));\n const node = useRef(render());\n\n useEffect(() => {\n const dispose = panel.current.onUpdate(() => {\n startTransition(() => {\n node.current = render();\n setVersion((v) => v + 1);\n });\n });\n return () => dispose.dispose();\n }, [panel]);\n\n return <>{node.current}</>;\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useService } from '@flowgram.ai/core';\n\nimport { PanelManager } from '../services/panel-manager';\n\nexport const usePanelManager = () => useService<PanelManager>(PanelManager);\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nexport const panelLayer: React.CSSProperties = {\n pointerEvents: 'none',\n position: 'absolute',\n top: 0,\n left: 0,\n\n display: 'flex',\n columnGap: '4px',\n width: '100%',\n height: '100%',\n padding: '4px',\n boxSizing: 'border-box',\n};\n\nexport const leftArea: React.CSSProperties = {\n width: '100%',\n minWidth: 0,\n flexGrow: 0,\n flexShrink: 1,\n\n display: 'flex',\n flexDirection: 'column',\n rowGap: '4px',\n};\n\nexport const rightArea: React.CSSProperties = {\n height: '100%',\n flexGrow: 1,\n flexShrink: 0,\n minWidth: 0,\n\n display: 'flex',\n columnGap: '4px',\n};\n\nexport const mainArea: React.CSSProperties = {\n position: 'relative',\n overflow: 'hidden',\n flexGrow: 0,\n flexShrink: 1,\n width: '100%',\n height: '100%',\n};\n\nexport const bottomArea: React.CSSProperties = {\n flexGrow: 1,\n flexShrink: 0,\n width: '100%',\n minHeight: 0,\n};\n\nexport const floatPanelWrap: React.CSSProperties = {\n pointerEvents: 'auto',\n height: '100%',\n width: '100%',\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { FloatPanel } from './float-panel';\nimport { panelLayer, leftArea, rightArea, mainArea, bottomArea } from './css';\n\nexport const PanelLayer: React.FC<React.PropsWithChildren> = ({ children }) => (\n <div className=\"panel-layer\" style={panelLayer}>\n <div className=\"left-area\" style={leftArea}>\n <div className=\"main-area\" style={mainArea}>\n {children}\n </div>\n <div className=\"bottom-area\" style={bottomArea}>\n <FloatPanel area=\"bottom\" />\n </div>\n </div>\n <div className=\"right-area\" style={rightArea}>\n <FloatPanel area=\"right\" />\n </div>\n </div>\n);\n"],"mappings":"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","names":["import_core","import_react","import_inversify","import_utils","import_core","FloatPanel","import_jsx_runtime","FloatPanel","PanelLayer","PanelLayer"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flowgram.ai/panel-manager-plugin",
|
|
3
|
+
"version": "0.4.15",
|
|
4
|
+
"homepage": "https://flowgram.ai/",
|
|
5
|
+
"repository": "https://github.com/bytedance/flowgram.ai",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"exports": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/esm/index.js",
|
|
10
|
+
"require": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"module": "./dist/esm/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"inversify": "^6.0.1",
|
|
17
|
+
"@flowgram.ai/core": "0.4.15",
|
|
18
|
+
"@flowgram.ai/utils": "0.4.15"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"react": "^18",
|
|
22
|
+
"@types/react": "^18",
|
|
23
|
+
"tsup": "^8.0.1",
|
|
24
|
+
"typescript": "^5.8.3",
|
|
25
|
+
"@flowgram.ai/eslint-config": "0.4.15",
|
|
26
|
+
"@flowgram.ai/ts-config": "0.4.15"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=16.8"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"react": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public",
|
|
38
|
+
"registry": "https://registry.npmjs.org/"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "npm run build:fast -- --dts-resolve",
|
|
42
|
+
"build:fast": "tsup src/index.ts --format cjs,esm --sourcemap --legacy-output",
|
|
43
|
+
"build:watch": "npm run build:fast -- --dts-resolve",
|
|
44
|
+
"clean": "rimraf dist",
|
|
45
|
+
"test": "exit 0",
|
|
46
|
+
"test:cov": "exit 0",
|
|
47
|
+
"ts-check": "tsc --noEmit",
|
|
48
|
+
"watch": "npm run build:fast -- --dts-resolve --watch --ignore-watch dist"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Invoking: npm run build:fast -- --dts-resolve
|
|
2
|
+
|
|
3
|
+
> @flowgram.ai/panel-manager-plugin@0.1.8 build:fast
|
|
4
|
+
> tsup src/index.ts --format cjs,esm --sourcemap --legacy-output --dts-resolve
|
|
5
|
+
|
|
6
|
+
CLI Building entry: src/index.ts
|
|
7
|
+
CLI Using tsconfig: tsconfig.json
|
|
8
|
+
CLI tsup v8.5.0
|
|
9
|
+
CLI Target: es2020
|
|
10
|
+
CJS Build start
|
|
11
|
+
ESM Build start
|
|
12
|
+
CJS dist/index.js 8.43 KB
|
|
13
|
+
CJS dist/index.js.map 13.65 KB
|
|
14
|
+
CJS ⚡️ Build success in 99ms
|
|
15
|
+
ESM dist/esm/index.js 6.94 KB
|
|
16
|
+
ESM dist/esm/index.js.map 13.19 KB
|
|
17
|
+
ESM ⚡️ Build success in 103ms
|
|
18
|
+
DTS Build start
|
|
19
|
+
DTS ⚡️ Build success in 3112ms
|
|
20
|
+
DTS dist/index.d.ts 1.87 KB
|
|
21
|
+
DTS dist/index.d.mts 1.87 KB
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const panelLayer: React.CSSProperties = {
|
|
7
|
+
pointerEvents: 'none',
|
|
8
|
+
position: 'absolute',
|
|
9
|
+
top: 0,
|
|
10
|
+
left: 0,
|
|
11
|
+
|
|
12
|
+
display: 'flex',
|
|
13
|
+
columnGap: '4px',
|
|
14
|
+
width: '100%',
|
|
15
|
+
height: '100%',
|
|
16
|
+
padding: '4px',
|
|
17
|
+
boxSizing: 'border-box',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const leftArea: React.CSSProperties = {
|
|
21
|
+
width: '100%',
|
|
22
|
+
minWidth: 0,
|
|
23
|
+
flexGrow: 0,
|
|
24
|
+
flexShrink: 1,
|
|
25
|
+
|
|
26
|
+
display: 'flex',
|
|
27
|
+
flexDirection: 'column',
|
|
28
|
+
rowGap: '4px',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const rightArea: React.CSSProperties = {
|
|
32
|
+
height: '100%',
|
|
33
|
+
flexGrow: 1,
|
|
34
|
+
flexShrink: 0,
|
|
35
|
+
minWidth: 0,
|
|
36
|
+
|
|
37
|
+
display: 'flex',
|
|
38
|
+
columnGap: '4px',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const mainArea: React.CSSProperties = {
|
|
42
|
+
position: 'relative',
|
|
43
|
+
overflow: 'hidden',
|
|
44
|
+
flexGrow: 0,
|
|
45
|
+
flexShrink: 1,
|
|
46
|
+
width: '100%',
|
|
47
|
+
height: '100%',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const bottomArea: React.CSSProperties = {
|
|
51
|
+
flexGrow: 1,
|
|
52
|
+
flexShrink: 0,
|
|
53
|
+
width: '100%',
|
|
54
|
+
minHeight: 0,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const floatPanelWrap: React.CSSProperties = {
|
|
58
|
+
pointerEvents: 'auto',
|
|
59
|
+
height: '100%',
|
|
60
|
+
width: '100%',
|
|
61
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useEffect, useRef, startTransition, useState } from 'react';
|
|
7
|
+
|
|
8
|
+
import { Area } from '../../types';
|
|
9
|
+
import { usePanelManager } from '../../hooks/use-panel-manager';
|
|
10
|
+
import { floatPanelWrap } from './css';
|
|
11
|
+
|
|
12
|
+
export const FloatPanel: React.FC<{ area: Area }> = ({ area }) => {
|
|
13
|
+
const [, setVersion] = useState(0);
|
|
14
|
+
const panelManager = usePanelManager();
|
|
15
|
+
const panel = useRef(panelManager.getPanel(area));
|
|
16
|
+
const render = () =>
|
|
17
|
+
panel.current.elements.map((i) => (
|
|
18
|
+
<div className="float-panel-wrap" key={i.key} style={floatPanelWrap}>
|
|
19
|
+
{i.el}
|
|
20
|
+
</div>
|
|
21
|
+
));
|
|
22
|
+
const node = useRef(render());
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const dispose = panel.current.onUpdate(() => {
|
|
26
|
+
startTransition(() => {
|
|
27
|
+
node.current = render();
|
|
28
|
+
setVersion((v) => v + 1);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
return () => dispose.dispose();
|
|
32
|
+
}, [panel]);
|
|
33
|
+
|
|
34
|
+
return <>{node.current}</>;
|
|
35
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { FloatPanel } from './float-panel';
|
|
7
|
+
import { panelLayer, leftArea, rightArea, mainArea, bottomArea } from './css';
|
|
8
|
+
|
|
9
|
+
export const PanelLayer: React.FC<React.PropsWithChildren> = ({ children }) => (
|
|
10
|
+
<div className="panel-layer" style={panelLayer}>
|
|
11
|
+
<div className="left-area" style={leftArea}>
|
|
12
|
+
<div className="main-area" style={mainArea}>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
<div className="bottom-area" style={bottomArea}>
|
|
16
|
+
<FloatPanel area="bottom" />
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
<div className="right-area" style={rightArea}>
|
|
20
|
+
<FloatPanel area="right" />
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { definePluginCreator } from '@flowgram.ai/core';
|
|
7
|
+
|
|
8
|
+
import { defineConfig } from './services/panel-config';
|
|
9
|
+
import { PanelManager, PanelManagerConfig, PanelLayer } from './services';
|
|
10
|
+
|
|
11
|
+
export const createPanelManagerPlugin = definePluginCreator<Partial<PanelManagerConfig>>({
|
|
12
|
+
onBind: ({ bind }) => {
|
|
13
|
+
bind(PanelManager).to(PanelManager).inSingletonScope();
|
|
14
|
+
bind(PanelManagerConfig).toConstantValue(defineConfig({}));
|
|
15
|
+
},
|
|
16
|
+
onInit(ctx, opt) {
|
|
17
|
+
ctx.playground.registerLayer(PanelLayer);
|
|
18
|
+
const config = defineConfig(opt);
|
|
19
|
+
ctx.container.rebind(PanelManagerConfig).toConstantValue(config);
|
|
20
|
+
const panelManager = ctx.container.get<PanelManager>(PanelManager);
|
|
21
|
+
panelManager.init();
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useService } from '@flowgram.ai/core';
|
|
7
|
+
|
|
8
|
+
import { PanelManager } from '../services/panel-manager';
|
|
9
|
+
|
|
10
|
+
export const usePanelManager = () => useService<PanelManager>(PanelManager);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** create plugin function */
|
|
7
|
+
export { createPanelManagerPlugin } from './create-panel-manager-plugin';
|
|
8
|
+
|
|
9
|
+
/** services */
|
|
10
|
+
export { PanelManager } from './services';
|
|
11
|
+
|
|
12
|
+
/** react hooks */
|
|
13
|
+
export { usePanelManager } from './hooks/use-panel-manager';
|
|
14
|
+
|
|
15
|
+
/** types */
|
|
16
|
+
export type { Area, PanelFactory } from './types';
|