@flowgram.ai/panel-manager-plugin 0.1.0-alpha.23 → 0.1.0-alpha.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -40,14 +40,92 @@ var index_exports = {};
40
40
  __export(index_exports, {
41
41
  DockedPanelLayer: () => DockedPanelLayer,
42
42
  PanelManager: () => PanelManager,
43
+ PanelRestore: () => PanelRestore,
43
44
  ResizeBar: () => ResizeBar,
44
45
  createPanelManagerPlugin: () => createPanelManagerPlugin,
46
+ usePanel: () => usePanel,
45
47
  usePanelManager: () => usePanelManager
46
48
  });
47
49
  module.exports = __toCommonJS(index_exports);
48
50
 
49
51
  // src/create-panel-manager-plugin.ts
50
- var import_core4 = require("@flowgram.ai/core");
52
+ var import_core3 = require("@flowgram.ai/core");
53
+
54
+ // src/services/panel-factory.ts
55
+ var import_vanilla = require("zustand/vanilla");
56
+ var import_nanoid = require("nanoid");
57
+ var import_inversify2 = require("inversify");
58
+
59
+ // src/services/panel-restore.ts
60
+ var import_inversify = require("inversify");
61
+ var PanelRestore = Symbol("PanelRestore");
62
+ var PanelRestoreImpl = class {
63
+ constructor() {
64
+ this.map = /* @__PURE__ */ new Map();
65
+ }
66
+ store(k, v) {
67
+ this.map.set(k, v);
68
+ }
69
+ restore(k) {
70
+ return this.map.get(k);
71
+ }
72
+ };
73
+ PanelRestoreImpl = __decorateClass([
74
+ (0, import_inversify.injectable)()
75
+ ], PanelRestoreImpl);
76
+
77
+ // src/services/panel-factory.ts
78
+ var PanelEntityFactory = Symbol("PanelEntityFactory");
79
+ var PanelEntityFactoryConstant = Symbol("PanelEntityFactoryConstant");
80
+ var PanelEntityConfigConstant = Symbol("PanelEntityConfigConstant");
81
+ var PANEL_SIZE_DEFAULT = 400;
82
+ var PanelEntity = class {
83
+ constructor() {
84
+ this.initialized = false;
85
+ /** 实例唯一标识 */
86
+ this.id = (0, import_nanoid.nanoid)();
87
+ /** 渲染缓存 */
88
+ this.node = null;
89
+ }
90
+ get area() {
91
+ return this.config.area;
92
+ }
93
+ get key() {
94
+ return this.factory.key;
95
+ }
96
+ get renderer() {
97
+ if (!this.node) {
98
+ this.node = this.factory.render(this.config.props);
99
+ }
100
+ return this.node;
101
+ }
102
+ init() {
103
+ if (this.initialized) {
104
+ return;
105
+ }
106
+ this.initialized = true;
107
+ const cache = this.restore.restore(this.key);
108
+ this.store = (0, import_vanilla.createStore)(() => ({
109
+ size: this.config.defaultSize || this.factory.defaultSize || PANEL_SIZE_DEFAULT,
110
+ ...cache ?? {}
111
+ }));
112
+ }
113
+ dispose() {
114
+ this.restore.store(this.key, this.store.getState());
115
+ }
116
+ };
117
+ __decorateClass([
118
+ (0, import_inversify2.inject)(PanelRestore)
119
+ ], PanelEntity.prototype, "restore", 2);
120
+ __decorateClass([
121
+ (0, import_inversify2.inject)(PanelEntityFactoryConstant)
122
+ ], PanelEntity.prototype, "factory", 2);
123
+ __decorateClass([
124
+ (0, import_inversify2.inject)(PanelEntityConfigConstant)
125
+ ], PanelEntity.prototype, "config", 2);
126
+ PanelEntity = __decorateClass([
127
+ (0, import_inversify2.injectable)()
128
+ ], PanelEntity);
51
129
 
52
130
  // src/components/resize-bar/index.tsx
53
131
  var import_react = require("react");
@@ -149,130 +227,114 @@ var defineConfig = (config) => {
149
227
  };
150
228
 
151
229
  // src/services/panel-manager.ts
152
- var import_inversify = require("inversify");
153
- var import_core = require("@flowgram.ai/core");
154
-
155
- // src/services/float-panel.ts
230
+ var import_inversify3 = require("inversify");
156
231
  var import_utils = require("@flowgram.ai/utils");
157
- var PANEL_SIZE_DEFAULT = 400;
158
- var FloatPanel = class {
159
- constructor(config) {
160
- this.config = config;
161
- this.elements = [];
162
- this.onUpdateEmitter = new import_utils.Emitter();
163
- this.sizeMap = /* @__PURE__ */ new Map();
164
- this.onUpdate = this.onUpdateEmitter.event;
165
- this.currentFactoryKey = "";
166
- }
167
- updateSize(newSize) {
168
- this.sizeMap.set(this.currentFactoryKey, newSize);
169
- this.onUpdateEmitter.fire();
170
- }
171
- get currentSize() {
172
- return this.sizeMap.get(this.currentFactoryKey) || PANEL_SIZE_DEFAULT;
173
- }
174
- open(factory, options) {
175
- const el = factory.render(options?.props);
176
- const idx = this.elements.findIndex((e) => e.key === factory.key);
177
- this.currentFactoryKey = factory.key;
178
- if (!this.sizeMap.has(factory.key)) {
179
- this.sizeMap.set(factory.key, factory.defaultSize || PANEL_SIZE_DEFAULT);
180
- }
181
- if (idx >= 0) {
182
- this.elements[idx] = { el, key: factory.key, style: factory.style };
183
- } else {
184
- this.elements.push({ el, key: factory.key, style: factory.style });
185
- if (this.elements.length > this.config.max) {
186
- this.elements.shift();
187
- }
188
- }
189
- this.onUpdateEmitter.fire();
190
- }
191
- get visible() {
192
- return this.elements.length > 0;
193
- }
194
- close(key) {
195
- if (!key) {
196
- this.elements = [];
197
- } else {
198
- this.elements = this.elements.filter((e) => e.key !== key);
199
- }
200
- this.onUpdateEmitter.fire();
201
- }
202
- dispose() {
203
- this.elements = [];
204
- this.onUpdateEmitter.dispose();
205
- }
206
- };
207
-
208
- // src/services/panel-manager.ts
209
232
  var PanelManager = class {
210
233
  constructor() {
211
234
  this.panelRegistry = /* @__PURE__ */ new Map();
235
+ this.panels = /* @__PURE__ */ new Map();
236
+ this.onPanelsChangeEvent = new import_utils.Emitter();
237
+ this.onPanelsChange = this.onPanelsChangeEvent.event;
212
238
  }
213
239
  init() {
214
240
  this.config.factories.forEach((factory) => this.register(factory));
215
- this.right = new FloatPanel(this.config.right);
216
- this.bottom = new FloatPanel(this.config.bottom);
217
- this.dockedRight = new FloatPanel(this.config.dockedRight);
218
- this.dockedBottom = new FloatPanel(this.config.dockedBottom);
219
241
  }
242
+ /** registry panel factory */
220
243
  register(factory) {
221
244
  this.panelRegistry.set(factory.key, factory);
222
245
  }
246
+ /** open panel */
223
247
  open(key, area = "right", options) {
224
248
  const factory = this.panelRegistry.get(key);
225
249
  if (!factory) {
226
250
  return;
227
251
  }
228
- const panel = this.getPanel(area);
229
- panel.open(factory, options);
252
+ const sameKeyPanels = this.getPanels(area).filter((p) => p.key === key);
253
+ if (!factory.allowDuplicates && sameKeyPanels.length) {
254
+ sameKeyPanels.forEach((p) => this.remove(p.id));
255
+ }
256
+ const panel = this.createPanel({
257
+ factory,
258
+ config: {
259
+ area,
260
+ ...options
261
+ }
262
+ });
263
+ this.panels.set(panel.id, panel);
264
+ this.trim(area);
265
+ this.onPanelsChangeEvent.fire();
266
+ console.log("jxj", this.panels);
230
267
  }
268
+ /** close panel */
231
269
  close(key) {
232
- this.right.close(key);
233
- this.bottom.close(key);
234
- this.dockedRight.close(key);
235
- this.dockedBottom.close(key);
270
+ const panels = this.getPanels();
271
+ const closedPanels = key ? panels.filter((p) => p.key === key) : panels;
272
+ closedPanels.forEach((p) => this.remove(p.id));
273
+ this.onPanelsChangeEvent.fire();
274
+ }
275
+ trim(area) {
276
+ const panels = this.getPanels(area);
277
+ const areaConfig = this.getAreaConfig(area);
278
+ console.log("jxj", areaConfig.max, panels.length);
279
+ while (panels.length > areaConfig.max) {
280
+ const removed = panels.shift();
281
+ if (removed) {
282
+ this.remove(removed.id);
283
+ }
284
+ }
285
+ }
286
+ remove(id) {
287
+ const panel = this.panels.get(id);
288
+ if (panel) {
289
+ panel.dispose();
290
+ this.panels.delete(id);
291
+ }
292
+ }
293
+ getPanels(area) {
294
+ const panels = [];
295
+ this.panels.forEach((panel) => {
296
+ if (!area || panel.area === area) {
297
+ panels.push(panel);
298
+ }
299
+ });
300
+ return panels;
236
301
  }
237
- getPanel(area) {
302
+ getAreaConfig(area) {
238
303
  switch (area) {
239
304
  case "docked-bottom":
240
- return this.dockedBottom;
305
+ return this.config.dockedBottom;
241
306
  case "docked-right":
242
- return this.dockedRight;
307
+ return this.config.dockedRight;
243
308
  case "bottom":
244
- return this.bottom;
309
+ return this.config.bottom;
245
310
  case "right":
246
311
  default:
247
- return this.right;
312
+ return this.config.right;
248
313
  }
249
314
  }
250
315
  dispose() {
251
- this.right.dispose();
252
- this.bottom.dispose();
253
- this.dockedBottom.dispose();
254
- this.dockedRight.dispose();
316
+ this.onPanelsChangeEvent.dispose();
255
317
  }
256
318
  };
257
319
  __decorateClass([
258
- (0, import_inversify.inject)(import_core.Playground)
259
- ], PanelManager.prototype, "playground", 2);
260
- __decorateClass([
261
- (0, import_inversify.inject)(PanelManagerConfig)
320
+ (0, import_inversify3.inject)(PanelManagerConfig)
262
321
  ], PanelManager.prototype, "config", 2);
322
+ __decorateClass([
323
+ (0, import_inversify3.inject)(PanelEntityFactory)
324
+ ], PanelManager.prototype, "createPanel", 2);
263
325
  PanelManager = __decorateClass([
264
- (0, import_inversify.injectable)()
326
+ (0, import_inversify3.injectable)()
265
327
  ], PanelManager);
266
328
 
267
329
  // src/services/panel-layer.ts
268
330
  var import_react_dom = __toESM(require("react-dom"));
269
- var import_react4 = require("react");
270
- var import_inversify2 = require("inversify");
331
+ var import_react5 = require("react");
332
+ var import_inversify4 = require("inversify");
271
333
  var import_utils2 = require("@flowgram.ai/utils");
272
- var import_core3 = require("@flowgram.ai/core");
334
+ var import_core2 = require("@flowgram.ai/core");
273
335
 
274
336
  // src/components/panel-layer/panel-layer.tsx
275
- var import_clsx = __toESM(require("clsx"));
337
+ var import_clsx2 = __toESM(require("clsx"));
276
338
 
277
339
  // src/hooks/use-global-css.ts
278
340
  var import_react2 = require("react");
@@ -291,12 +353,79 @@ var useGlobalCSS = ({ cssText, id, cleanup }) => {
291
353
  }, [id]);
292
354
  };
293
355
 
294
- // src/components/panel-layer/float-panel.tsx
295
- var import_react3 = require("react");
356
+ // src/components/panel-layer/panel.tsx
357
+ var import_react4 = require("react");
358
+ var import_traditional = require("zustand/traditional");
359
+ var import_shallow = require("zustand/shallow");
360
+ var import_clsx = __toESM(require("clsx"));
296
361
 
297
362
  // src/hooks/use-panel-manager.ts
298
- var import_core2 = require("@flowgram.ai/core");
299
- var usePanelManager = () => (0, import_core2.useService)(PanelManager);
363
+ var import_core = require("@flowgram.ai/core");
364
+ var usePanelManager = () => (0, import_core.useService)(PanelManager);
365
+
366
+ // src/contexts.ts
367
+ var import_react3 = require("react");
368
+ var PanelContext = (0, import_react3.createContext)({});
369
+
370
+ // src/components/panel-layer/panel.tsx
371
+ var import_jsx_runtime2 = require("react/jsx-runtime");
372
+ var PanelItem = ({ panel }) => {
373
+ const panelManager = usePanelManager();
374
+ const ref = (0, import_react4.useRef)(null);
375
+ const resize = panel.factory.resize !== void 0 ? panel.factory.resize : panelManager.config.autoResize;
376
+ const isHorizontal = ["right", "docked-right"].includes(panel.area);
377
+ const size = (0, import_traditional.useStoreWithEqualityFn)(panel.store, (s) => s.size, import_shallow.shallow);
378
+ const sizeStyle = isHorizontal ? { width: size } : { height: size };
379
+ const handleResize = (next) => {
380
+ let nextSize = next;
381
+ if (typeof panel.factory.maxSize === "number" && nextSize > panel.factory.maxSize) {
382
+ nextSize = panel.factory.maxSize;
383
+ } else if (typeof panel.factory.minSize === "number" && nextSize < panel.factory.minSize) {
384
+ nextSize = panel.factory.minSize;
385
+ }
386
+ panel.store.setState({ size: nextSize });
387
+ };
388
+ (0, import_react4.useEffect)(() => {
389
+ if (ref.current) {
390
+ const { width, height } = ref.current.getBoundingClientRect();
391
+ const realSize = isHorizontal ? width : height;
392
+ panel.store.setState({ size: realSize });
393
+ }
394
+ }, []);
395
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
396
+ "div",
397
+ {
398
+ className: (0, import_clsx.default)(
399
+ "gedit-flow-panel-wrap",
400
+ isHorizontal ? "panel-horizontal" : "panel-vertical"
401
+ ),
402
+ ref,
403
+ style: { ...panel.factory.style, ...panel.config.style, ...sizeStyle },
404
+ children: [
405
+ resize && panelManager.config.resizeBarRender({
406
+ size,
407
+ direction: isHorizontal ? "vertical" : "horizontal",
408
+ onResize: handleResize
409
+ }),
410
+ panel.renderer
411
+ ]
412
+ },
413
+ panel.id
414
+ );
415
+ };
416
+ var PanelArea = ({ area }) => {
417
+ const panelManager = usePanelManager();
418
+ const [panels, setPanels] = (0, import_react4.useState)(panelManager.getPanels(area));
419
+ (0, import_react4.useEffect)(() => {
420
+ const dispose = panelManager.onPanelsChange(() => {
421
+ (0, import_react4.startTransition)(() => {
422
+ setPanels(panelManager.getPanels(area));
423
+ });
424
+ });
425
+ return () => dispose.dispose();
426
+ }, []);
427
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: panels.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PanelContext.Provider, { value: panel, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(PanelItem, { panel }) }, panel.id)) });
428
+ };
300
429
 
301
430
  // src/components/panel-layer/css.ts
302
431
  var globalCSS = `
@@ -339,8 +468,9 @@ var globalCSS = `
339
468
  min-width: 0;
340
469
  display: flex;
341
470
  column-gap: 4px;
471
+ max-width: 100%;
342
472
  }
343
-
473
+
344
474
  .gedit-flow-panel-main-area {
345
475
  position: relative;
346
476
  overflow: hidden;
@@ -355,55 +485,18 @@ var globalCSS = `
355
485
  width: 100%;
356
486
  min-height: 0;
357
487
  }
488
+ .gedit-flow-panel-wrap {
489
+ pointer-events: auto;
490
+ overflow: auto;
491
+ position: relative;
492
+ }
493
+ .gedit-flow-panel-wrap.panel-horizontal {
494
+ height: 100%;
495
+ }
496
+ .gedit-flow-panel-wrap.panel-vertical {
497
+ width: 100%;
498
+ }
358
499
  `;
359
- var floatPanelWrap = {
360
- pointerEvents: "auto",
361
- height: "100%",
362
- width: "100%",
363
- overflow: "auto"
364
- };
365
-
366
- // src/components/panel-layer/float-panel.tsx
367
- var import_jsx_runtime2 = require("react/jsx-runtime");
368
- var FloatPanel2 = ({ area }) => {
369
- const [, setVersion] = (0, import_react3.useState)(0);
370
- const panelManager = usePanelManager();
371
- const panel = (0, import_react3.useRef)(panelManager.getPanel(area));
372
- const isHorizontal = ["right", "docked-right"].includes(area);
373
- const render = () => panel.current.elements.map((i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "float-panel-wrap", style: { ...floatPanelWrap, ...i.style }, children: i.el }, i.key));
374
- const node = (0, import_react3.useRef)(render());
375
- (0, import_react3.useEffect)(() => {
376
- const dispose = panel.current.onUpdate(() => {
377
- (0, import_react3.startTransition)(() => {
378
- node.current = render();
379
- setVersion((v) => v + 1);
380
- });
381
- });
382
- return () => dispose.dispose();
383
- }, [panel]);
384
- const onResize = (0, import_react3.useCallback)((newSize) => panel.current.updateSize(newSize), []);
385
- const size = panel.current.currentSize;
386
- const sizeStyle = isHorizontal ? { width: size, height: "100%" } : { height: size, width: "100%" };
387
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
388
- "div",
389
- {
390
- className: "gedit-flow-panel",
391
- style: {
392
- position: "relative",
393
- display: panel.current.visible ? "block" : "none",
394
- ...sizeStyle
395
- },
396
- children: [
397
- panelManager.config.resizeBarRender({
398
- size,
399
- direction: isHorizontal ? "vertical" : "horizontal",
400
- onResize
401
- }),
402
- node.current
403
- ]
404
- }
405
- );
406
- };
407
500
 
408
501
  // src/components/panel-layer/panel-layer.tsx
409
502
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -420,7 +513,7 @@ var PanelLayer = ({
420
513
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
421
514
  "div",
422
515
  {
423
- className: (0, import_clsx.default)(
516
+ className: (0, import_clsx2.default)(
424
517
  "gedit-flow-panel-layer-wrap",
425
518
  mode === "docked" && "gedit-flow-panel-layer-wrap-docked",
426
519
  mode === "floating" && "gedit-flow-panel-layer-wrap-floating",
@@ -430,9 +523,9 @@ var PanelLayer = ({
430
523
  children: [
431
524
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "gedit-flow-panel-left-area", children: [
432
525
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "gedit-flow-panel-main-area", children }),
433
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "gedit-flow-panel-bottom-area", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FloatPanel2, { area: mode === "docked" ? "docked-bottom" : "bottom" }) })
526
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "gedit-flow-panel-bottom-area", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PanelArea, { area: mode === "docked" ? "docked-bottom" : "bottom" }) })
434
527
  ] }),
435
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "gedit-flow-panel-right-area", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FloatPanel2, { area: mode === "docked" ? "docked-right" : "right" }) })
528
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "gedit-flow-panel-right-area", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PanelArea, { area: mode === "docked" ? "docked-right" : "right" }) })
436
529
  ]
437
530
  }
438
531
  );
@@ -443,7 +536,7 @@ var import_jsx_runtime4 = require("react/jsx-runtime");
443
536
  var DockedPanelLayer = (props) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PanelLayer, { mode: "docked", ...props });
444
537
 
445
538
  // src/services/panel-layer.ts
446
- var PanelLayer2 = class extends import_core3.Layer {
539
+ var PanelLayer2 = class extends import_core2.Layer {
447
540
  constructor() {
448
541
  super(...arguments);
449
542
  this.panelRoot = import_utils2.domUtils.createDivWithClass("gedit-flow-panel-layer");
@@ -470,26 +563,40 @@ var PanelLayer2 = class extends import_core3.Layer {
470
563
  render() {
471
564
  if (!this.layout) {
472
565
  const { children, ...layoutProps } = this.panelConfig.layerProps;
473
- this.layout = (0, import_react4.createElement)(PanelLayer, layoutProps, children);
566
+ this.layout = (0, import_react5.createElement)(PanelLayer, layoutProps, children);
474
567
  }
475
568
  return import_react_dom.default.createPortal(this.layout, this.panelRoot);
476
569
  }
477
570
  };
478
571
  __decorateClass([
479
- (0, import_inversify2.inject)(PanelManagerConfig)
572
+ (0, import_inversify4.inject)(PanelManagerConfig)
480
573
  ], PanelLayer2.prototype, "panelConfig", 2);
481
574
  __decorateClass([
482
- (0, import_inversify2.inject)(import_core3.PluginContext)
575
+ (0, import_inversify4.inject)(import_core2.PluginContext)
483
576
  ], PanelLayer2.prototype, "pluginContext", 2);
484
577
  PanelLayer2 = __decorateClass([
485
- (0, import_inversify2.injectable)()
578
+ (0, import_inversify4.injectable)()
486
579
  ], PanelLayer2);
487
580
 
488
581
  // src/create-panel-manager-plugin.ts
489
- var createPanelManagerPlugin = (0, import_core4.definePluginCreator)({
582
+ var createPanelManagerPlugin = (0, import_core3.definePluginCreator)({
490
583
  onBind: ({ bind }, opt) => {
491
584
  bind(PanelManager).to(PanelManager).inSingletonScope();
585
+ bind(PanelRestore).to(PanelRestoreImpl).inSingletonScope();
492
586
  bind(PanelManagerConfig).toConstantValue(defineConfig(opt));
587
+ bind(PanelEntityFactory).toFactory(
588
+ (context) => ({
589
+ factory,
590
+ config
591
+ }) => {
592
+ const container = context.container.createChild();
593
+ container.bind(PanelEntityFactoryConstant).toConstantValue(factory);
594
+ container.bind(PanelEntityConfigConstant).toConstantValue(config);
595
+ const panel = container.resolve(PanelEntity);
596
+ panel.init();
597
+ return panel;
598
+ }
599
+ );
493
600
  },
494
601
  onInit(ctx) {
495
602
  ctx.playground.registerLayer(PanelLayer2);
@@ -497,12 +604,18 @@ var createPanelManagerPlugin = (0, import_core4.definePluginCreator)({
497
604
  panelManager.init();
498
605
  }
499
606
  });
607
+
608
+ // src/hooks/use-panel.ts
609
+ var import_react6 = require("react");
610
+ var usePanel = () => (0, import_react6.useContext)(PanelContext);
500
611
  // Annotate the CommonJS export names for ESM import in node:
501
612
  0 && (module.exports = {
502
613
  DockedPanelLayer,
503
614
  PanelManager,
615
+ PanelRestore,
504
616
  ResizeBar,
505
617
  createPanelManagerPlugin,
618
+ usePanel,
506
619
  usePanelManager
507
620
  });
508
621
  //# sourceMappingURL=index.js.map