@flowgram.ai/panel-manager-plugin 0.1.0-alpha.18 → 0.1.0-alpha.20

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.map CHANGED
@@ -1 +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\n className=\"float-panel-wrap\"\n key={i.key}\n style={floatPanelWrap}\n onMouseDown={(e) => e.stopPropagation()}\n >\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"]}
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/panel-layer.tsx","../src/hooks/use-global-css.ts","../src/components/panel-layer/float-panel.tsx","../src/hooks/use-panel-manager.ts","../src/components/panel-layer/css.ts","../src/components/resize-bar/index.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, type PanelManagerConfig } from './services';\n\n/** react hooks */\nexport { usePanelManager } from './hooks/use-panel-manager';\n\nexport { ResizeBar } from './components/resize-bar';\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 }, opt) => {\n bind(PanelManager).to(PanelManager).inSingletonScope();\n bind(PanelManagerConfig).toConstantValue(defineConfig(opt));\n },\n onInit(ctx) {\n ctx.playground.registerLayer(PanelLayer);\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 { PluginContext } from '@flowgram.ai/core';\n\nimport type { PanelFactory, PanelConfig } from '../types';\nimport type { PanelLayerProps } from '../components/panel-layer';\n\nexport interface PanelManagerConfig {\n factories: PanelFactory<any>[];\n right: PanelConfig;\n bottom: PanelConfig;\n autoResize: boolean;\n layerProps: PanelLayerProps;\n getPopupContainer: (ctx: PluginContext) => HTMLElement; // default playground.node.parentElement\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 autoResize: true,\n layerProps: {},\n getPopupContainer: (ctx: PluginContext) => ctx.playground.node.parentNode as HTMLElement,\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) 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) {\n this.right.close(key);\n this.bottom.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 style?: React.CSSProperties;\n el: React.ReactNode;\n}\n\nconst PANEL_SIZE_DEFAULT = 400;\n\nexport class FloatPanel {\n elements: PanelElement[] = [];\n\n private onUpdateEmitter = new Emitter<void>();\n\n sizeMap = new Map<string, number>();\n\n onUpdate = this.onUpdateEmitter.event;\n\n currentFactoryKey = '';\n\n updateSize(newSize: number) {\n this.sizeMap.set(this.currentFactoryKey, newSize);\n this.onUpdateEmitter.fire();\n }\n\n get currentSize(): number {\n return this.sizeMap.get(this.currentFactoryKey) || PANEL_SIZE_DEFAULT;\n }\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 this.currentFactoryKey = factory.key;\n if (!this.sizeMap.has(factory.key)) {\n this.sizeMap.set(factory.key, factory.defaultSize || PANEL_SIZE_DEFAULT);\n }\n if (idx >= 0) {\n this.elements[idx] = { el, key: factory.key, style: factory.style };\n } else {\n this.elements.push({ el, key: factory.key, style: factory.style });\n if (this.elements.length > this.config.max) {\n this.elements.shift();\n }\n }\n this.onUpdateEmitter.fire();\n }\n\n get visible() {\n return this.elements.length > 0;\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 ReactDOM from 'react-dom';\nimport { createElement } from 'react';\n\nimport { injectable, inject } from 'inversify';\nimport { domUtils, Disposable } from '@flowgram.ai/utils';\nimport { Layer, PluginContext } from '@flowgram.ai/core';\n\nimport { PanelLayer as PanelLayerComp } from '../components/panel-layer';\nimport { PanelManagerConfig } from './panel-config';\n\n@injectable()\nexport class PanelLayer extends Layer {\n @inject(PanelManagerConfig) private readonly panelConfig: PanelManagerConfig;\n\n @inject(PluginContext) private readonly pluginContext: PluginContext;\n\n readonly panelRoot = domUtils.createDivWithClass('gedit-flow-panel-layer');\n\n layout: JSX.Element | null = null;\n\n onReady(): void {\n this.panelConfig.getPopupContainer(this.pluginContext).appendChild(this.panelRoot);\n this.toDispose.push(\n Disposable.create(() => {\n // Remove from PopupContainer\n this.panelRoot.remove();\n })\n );\n const commonStyle = {\n pointerEvents: 'none',\n width: '100%',\n height: '100%',\n position: 'absolute',\n left: 0,\n top: 0,\n zIndex: 100,\n };\n domUtils.setStyle(this.panelRoot, commonStyle);\n }\n\n render(): JSX.Element {\n if (!this.layout) {\n const { children, ...layoutProps } = this.panelConfig.layerProps;\n this.layout = createElement(PanelLayerComp, layoutProps, children);\n }\n return ReactDOM.createPortal(this.layout, this.panelRoot);\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport clsx from 'clsx';\n\nimport { useGlobalCSS } from '../../hooks/use-global-css';\nimport { FloatPanel } from './float-panel';\nimport { leftArea, rightArea, mainArea, bottomArea, globalCSS } from './css';\n\nexport type PanelLayerProps = React.PropsWithChildren<{\n className?: string;\n style?: React.CSSProperties;\n}>;\n\nexport const PanelLayer: React.FC<PanelLayerProps> = ({ className, style, children }) => {\n useGlobalCSS({\n cssText: globalCSS,\n id: 'flow-panel-layer-css',\n });\n\n return (\n <div className={clsx('gedit-flow-panel-layer-wrap', className)} style={style}>\n <div className=\"gedit-flow-panel-left-area\" style={leftArea}>\n <div className=\"gedit-flow-panel-main-area\" style={mainArea}>\n {children}\n </div>\n <div className=\"gedit-flow-panel-bottom-area\" style={bottomArea}>\n <FloatPanel area=\"bottom\" />\n </div>\n </div>\n <div className=\"gedit-flow-panel-right-area\" style={rightArea}>\n <FloatPanel area=\"right\" />\n </div>\n </div>\n );\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEffect } from 'react';\n\ninterface UseGlobalCSSOptions {\n cssText: string;\n id: string;\n cleanup?: boolean;\n}\n\nexport const useGlobalCSS = ({ cssText, id, cleanup }: UseGlobalCSSOptions) => {\n useEffect(() => {\n /** SSR safe */\n if (typeof document === 'undefined') return;\n\n if (document.getElementById(id)) return;\n\n const style = document.createElement('style');\n style.id = id;\n style.textContent = cssText;\n document.head.appendChild(style);\n\n return () => {\n const existing = document.getElementById(id);\n if (existing && cleanup) existing.remove();\n };\n }, [id]);\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { useEffect, useRef, startTransition, useState, useCallback } from 'react';\n\nimport { Area } from '../../types';\nimport { usePanelManager } from '../../hooks/use-panel-manager';\nimport { floatPanelWrap } from './css';\nimport { ResizeBar } from '../resize-bar';\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, ...i.style }}>\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 const onResize = useCallback((newSize: number) => panel.current!.updateSize(newSize), []);\n const size = panel.current!.currentSize;\n const sizeStyle =\n area === 'right' ? { width: size, height: '100%' } : { height: size, width: '100%' };\n\n return (\n <div\n className=\"gedit-flow-panel\"\n style={{\n position: 'relative',\n display: panel.current.visible ? 'block' : 'none',\n ...sizeStyle,\n }}\n >\n {panelManager.config.autoResize && panel.current.elements.length > 0 && (\n <ResizeBar size={size} isVertical={area === 'right'} onResize={onResize} />\n )}\n {node.current}\n </div>\n );\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 globalCSS = `\n .gedit-flow-panel-layer * {\n box-sizing: border-box;\n }\n .gedit-flow-panel-layer-wrap {\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n column-gap: 4px;\n width: 100%;\n height: 100%;\n padding: 4px;\n overflow: hidden;\n }\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 overflow: 'auto',\n};\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport React, { useRef, useState } from 'react';\n\ninterface Props {\n onResize: (w: number) => void;\n size: number;\n isVertical?: boolean;\n}\n\nexport const ResizeBar: React.FC<Props> = ({ onResize, size, isVertical }) => {\n const currentPoint = useRef<null | number>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n return (\n <div\n onMouseDown={(e) => {\n currentPoint.current = isVertical ? e.clientX : e.clientY;\n e.stopPropagation();\n e.preventDefault();\n setIsDragging(true);\n const mouseUp = () => {\n currentPoint.current = null;\n document.body.removeEventListener('mouseup', mouseUp);\n document.body.removeEventListener('mousemove', mouseMove);\n setIsDragging(false);\n };\n const mouseMove = (e: MouseEvent) => {\n const delta = currentPoint.current! - (isVertical ? e.clientX : e.clientY);\n onResize(size + delta);\n };\n document.body.addEventListener('mouseup', mouseUp);\n document.body.addEventListener('mousemove', mouseMove);\n }}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n zIndex: 999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n pointerEvents: 'auto',\n ...(isVertical\n ? {\n cursor: 'ew-resize',\n height: '100%',\n marginLeft: -5,\n width: 10,\n }\n : {\n cursor: 'ns-resize',\n width: '100%',\n marginTop: -5,\n height: 10,\n }),\n }}\n >\n <div\n style={{\n ...(isVertical\n ? {\n width: 3,\n height: '100%',\n }\n : {\n height: 3,\n width: '100%',\n }),\n backgroundColor: isDragging || isHovered ? 'var(--g-playground-line)' : 'transparent',\n }}\n />\n </div>\n );\n};\n"],"mappings":"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","names":["import_core","import_react","import_inversify","import_utils","import_core","import_react","import_react","e","import_jsx_runtime","FloatPanel","import_jsx_runtime","clsx","FloatPanel","PanelLayer","ReactDOM","PanelLayer"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowgram.ai/panel-manager-plugin",
3
- "version": "0.1.0-alpha.18",
3
+ "version": "0.1.0-alpha.20",
4
4
  "homepage": "https://flowgram.ai/",
5
5
  "repository": "https://github.com/bytedance/flowgram.ai",
6
6
  "license": "MIT",
@@ -14,19 +14,23 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "dependencies": {
16
16
  "inversify": "^6.0.1",
17
- "@flowgram.ai/core": "0.1.0-alpha.18",
18
- "@flowgram.ai/utils": "0.1.0-alpha.18"
17
+ "clsx": "^1.1.1",
18
+ "@flowgram.ai/core": "0.1.0-alpha.20",
19
+ "@flowgram.ai/utils": "0.1.0-alpha.20"
19
20
  },
20
21
  "devDependencies": {
21
22
  "react": "^18",
23
+ "react-dom": "^18",
22
24
  "@types/react": "^18",
25
+ "@types/react-dom": "^18",
23
26
  "tsup": "^8.0.1",
24
27
  "typescript": "^5.8.3",
25
- "@flowgram.ai/eslint-config": "0.1.0-alpha.18",
26
- "@flowgram.ai/ts-config": "0.1.0-alpha.18"
28
+ "@flowgram.ai/ts-config": "0.1.0-alpha.20",
29
+ "@flowgram.ai/eslint-config": "0.1.0-alpha.20"
27
30
  },
28
31
  "peerDependencies": {
29
- "react": ">=16.8"
32
+ "react": ">=16.8",
33
+ "react-dom": ">=16.8"
30
34
  },
31
35
  "peerDependenciesMeta": {
32
36
  "react": {
@@ -9,13 +9,13 @@ CLI tsup v8.5.0
9
9
  CLI Target: es2020
10
10
  CJS Build start
11
11
  ESM Build start
12
- CJS dist/index.js 8.51 KB
13
- CJS dist/index.js.map 13.80 KB
14
- CJS ⚡️ Build success in 107ms
15
- ESM dist/esm/index.js 7.03 KB
16
- ESM dist/esm/index.js.map 13.34 KB
17
- ESM ⚡️ Build success in 108ms
12
+ CJS dist/index.js 13.82 KB
13
+ CJS dist/index.js.map 22.26 KB
14
+ CJS ⚡️ Build success in 98ms
15
+ ESM dist/esm/index.js 11.54 KB
16
+ ESM dist/esm/index.js.map 21.81 KB
17
+ ESM ⚡️ Build success in 99ms
18
18
  DTS Build start
19
- DTS ⚡️ Build success in 2863ms
20
- DTS dist/index.d.ts 1.87 KB
21
- DTS dist/index.d.mts 1.87 KB
19
+ DTS ⚡️ Build success in 3462ms
20
+ DTS dist/index.d.ts 2.78 KB
21
+ DTS dist/index.d.mts 2.78 KB
@@ -3,19 +3,23 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
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
- };
6
+ export const globalCSS = `
7
+ .gedit-flow-panel-layer * {
8
+ box-sizing: border-box;
9
+ }
10
+ .gedit-flow-panel-layer-wrap {
11
+ pointer-events: none;
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ display: flex;
16
+ column-gap: 4px;
17
+ width: 100%;
18
+ height: 100%;
19
+ padding: 4px;
20
+ overflow: hidden;
21
+ }
22
+ `;
19
23
 
20
24
  export const leftArea: React.CSSProperties = {
21
25
  width: '100%',
@@ -58,4 +62,5 @@ export const floatPanelWrap: React.CSSProperties = {
58
62
  pointerEvents: 'auto',
59
63
  height: '100%',
60
64
  width: '100%',
65
+ overflow: 'auto',
61
66
  };
@@ -3,11 +3,12 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- import { useEffect, useRef, startTransition, useState } from 'react';
6
+ import { useEffect, useRef, startTransition, useState, useCallback } from 'react';
7
7
 
8
8
  import { Area } from '../../types';
9
9
  import { usePanelManager } from '../../hooks/use-panel-manager';
10
10
  import { floatPanelWrap } from './css';
11
+ import { ResizeBar } from '../resize-bar';
11
12
 
12
13
  export const FloatPanel: React.FC<{ area: Area }> = ({ area }) => {
13
14
  const [, setVersion] = useState(0);
@@ -15,12 +16,7 @@ export const FloatPanel: React.FC<{ area: Area }> = ({ area }) => {
15
16
  const panel = useRef(panelManager.getPanel(area));
16
17
  const render = () =>
17
18
  panel.current.elements.map((i) => (
18
- <div
19
- className="float-panel-wrap"
20
- key={i.key}
21
- style={floatPanelWrap}
22
- onMouseDown={(e) => e.stopPropagation()}
23
- >
19
+ <div className="float-panel-wrap" key={i.key} style={{ ...floatPanelWrap, ...i.style }}>
24
20
  {i.el}
25
21
  </div>
26
22
  ));
@@ -35,6 +31,24 @@ export const FloatPanel: React.FC<{ area: Area }> = ({ area }) => {
35
31
  });
36
32
  return () => dispose.dispose();
37
33
  }, [panel]);
34
+ const onResize = useCallback((newSize: number) => panel.current!.updateSize(newSize), []);
35
+ const size = panel.current!.currentSize;
36
+ const sizeStyle =
37
+ area === 'right' ? { width: size, height: '100%' } : { height: size, width: '100%' };
38
38
 
39
- return <>{node.current}</>;
39
+ return (
40
+ <div
41
+ className="gedit-flow-panel"
42
+ style={{
43
+ position: 'relative',
44
+ display: panel.current.visible ? 'block' : 'none',
45
+ ...sizeStyle,
46
+ }}
47
+ >
48
+ {panelManager.config.autoResize && panel.current.elements.length > 0 && (
49
+ <ResizeBar size={size} isVertical={area === 'right'} onResize={onResize} />
50
+ )}
51
+ {node.current}
52
+ </div>
53
+ );
40
54
  };
@@ -3,4 +3,4 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
- export { PanelLayer } from './panel-layer';
6
+ export { PanelLayer, type PanelLayerProps } from './panel-layer';
@@ -3,21 +3,36 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import clsx from 'clsx';
7
+
8
+ import { useGlobalCSS } from '../../hooks/use-global-css';
6
9
  import { FloatPanel } from './float-panel';
7
- import { panelLayer, leftArea, rightArea, mainArea, bottomArea } from './css';
10
+ import { leftArea, rightArea, mainArea, bottomArea, globalCSS } from './css';
11
+
12
+ export type PanelLayerProps = React.PropsWithChildren<{
13
+ className?: string;
14
+ style?: React.CSSProperties;
15
+ }>;
8
16
 
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}
17
+ export const PanelLayer: React.FC<PanelLayerProps> = ({ className, style, children }) => {
18
+ useGlobalCSS({
19
+ cssText: globalCSS,
20
+ id: 'flow-panel-layer-css',
21
+ });
22
+
23
+ return (
24
+ <div className={clsx('gedit-flow-panel-layer-wrap', className)} style={style}>
25
+ <div className="gedit-flow-panel-left-area" style={leftArea}>
26
+ <div className="gedit-flow-panel-main-area" style={mainArea}>
27
+ {children}
28
+ </div>
29
+ <div className="gedit-flow-panel-bottom-area" style={bottomArea}>
30
+ <FloatPanel area="bottom" />
31
+ </div>
14
32
  </div>
15
- <div className="bottom-area" style={bottomArea}>
16
- <FloatPanel area="bottom" />
33
+ <div className="gedit-flow-panel-right-area" style={rightArea}>
34
+ <FloatPanel area="right" />
17
35
  </div>
18
36
  </div>
19
- <div className="right-area" style={rightArea}>
20
- <FloatPanel area="right" />
21
- </div>
22
- </div>
23
- );
37
+ );
38
+ };
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import React, { useRef, useState } from 'react';
7
+
8
+ interface Props {
9
+ onResize: (w: number) => void;
10
+ size: number;
11
+ isVertical?: boolean;
12
+ }
13
+
14
+ export const ResizeBar: React.FC<Props> = ({ onResize, size, isVertical }) => {
15
+ const currentPoint = useRef<null | number>(null);
16
+ const [isDragging, setIsDragging] = useState(false);
17
+ const [isHovered, setIsHovered] = useState(false);
18
+ return (
19
+ <div
20
+ onMouseDown={(e) => {
21
+ currentPoint.current = isVertical ? e.clientX : e.clientY;
22
+ e.stopPropagation();
23
+ e.preventDefault();
24
+ setIsDragging(true);
25
+ const mouseUp = () => {
26
+ currentPoint.current = null;
27
+ document.body.removeEventListener('mouseup', mouseUp);
28
+ document.body.removeEventListener('mousemove', mouseMove);
29
+ setIsDragging(false);
30
+ };
31
+ const mouseMove = (e: MouseEvent) => {
32
+ const delta = currentPoint.current! - (isVertical ? e.clientX : e.clientY);
33
+ onResize(size + delta);
34
+ };
35
+ document.body.addEventListener('mouseup', mouseUp);
36
+ document.body.addEventListener('mousemove', mouseMove);
37
+ }}
38
+ onMouseEnter={() => setIsHovered(true)}
39
+ onMouseLeave={() => setIsHovered(false)}
40
+ style={{
41
+ position: 'absolute',
42
+ top: 0,
43
+ left: 0,
44
+ zIndex: 999,
45
+ display: 'flex',
46
+ alignItems: 'center',
47
+ justifyContent: 'center',
48
+ pointerEvents: 'auto',
49
+ ...(isVertical
50
+ ? {
51
+ cursor: 'ew-resize',
52
+ height: '100%',
53
+ marginLeft: -5,
54
+ width: 10,
55
+ }
56
+ : {
57
+ cursor: 'ns-resize',
58
+ width: '100%',
59
+ marginTop: -5,
60
+ height: 10,
61
+ }),
62
+ }}
63
+ >
64
+ <div
65
+ style={{
66
+ ...(isVertical
67
+ ? {
68
+ width: 3,
69
+ height: '100%',
70
+ }
71
+ : {
72
+ height: 3,
73
+ width: '100%',
74
+ }),
75
+ backgroundColor: isDragging || isHovered ? 'var(--g-playground-line)' : 'transparent',
76
+ }}
77
+ />
78
+ </div>
79
+ );
80
+ };
@@ -9,14 +9,12 @@ import { defineConfig } from './services/panel-config';
9
9
  import { PanelManager, PanelManagerConfig, PanelLayer } from './services';
10
10
 
11
11
  export const createPanelManagerPlugin = definePluginCreator<Partial<PanelManagerConfig>>({
12
- onBind: ({ bind }) => {
12
+ onBind: ({ bind }, opt) => {
13
13
  bind(PanelManager).to(PanelManager).inSingletonScope();
14
- bind(PanelManagerConfig).toConstantValue(defineConfig({}));
14
+ bind(PanelManagerConfig).toConstantValue(defineConfig(opt));
15
15
  },
16
- onInit(ctx, opt) {
16
+ onInit(ctx) {
17
17
  ctx.playground.registerLayer(PanelLayer);
18
- const config = defineConfig(opt);
19
- ctx.container.rebind(PanelManagerConfig).toConstantValue(config);
20
18
  const panelManager = ctx.container.get<PanelManager>(PanelManager);
21
19
  panelManager.init();
22
20
  },
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { useEffect } from 'react';
7
+
8
+ interface UseGlobalCSSOptions {
9
+ cssText: string;
10
+ id: string;
11
+ cleanup?: boolean;
12
+ }
13
+
14
+ export const useGlobalCSS = ({ cssText, id, cleanup }: UseGlobalCSSOptions) => {
15
+ useEffect(() => {
16
+ /** SSR safe */
17
+ if (typeof document === 'undefined') return;
18
+
19
+ if (document.getElementById(id)) return;
20
+
21
+ const style = document.createElement('style');
22
+ style.id = id;
23
+ style.textContent = cssText;
24
+ document.head.appendChild(style);
25
+
26
+ return () => {
27
+ const existing = document.getElementById(id);
28
+ if (existing && cleanup) existing.remove();
29
+ };
30
+ }, [id]);
31
+ };
package/src/index.ts CHANGED
@@ -7,10 +7,12 @@
7
7
  export { createPanelManagerPlugin } from './create-panel-manager-plugin';
8
8
 
9
9
  /** services */
10
- export { PanelManager } from './services';
10
+ export { PanelManager, type PanelManagerConfig } from './services';
11
11
 
12
12
  /** react hooks */
13
13
  export { usePanelManager } from './hooks/use-panel-manager';
14
14
 
15
+ export { ResizeBar } from './components/resize-bar';
16
+
15
17
  /** types */
16
18
  export type { Area, PanelFactory } from './types';
@@ -9,25 +9,45 @@ import type { PanelFactory, PanelConfig } from '../types';
9
9
 
10
10
  export interface PanelElement {
11
11
  key: string;
12
+ style?: React.CSSProperties;
12
13
  el: React.ReactNode;
13
14
  }
14
15
 
16
+ const PANEL_SIZE_DEFAULT = 400;
17
+
15
18
  export class FloatPanel {
16
19
  elements: PanelElement[] = [];
17
20
 
18
21
  private onUpdateEmitter = new Emitter<void>();
19
22
 
23
+ sizeMap = new Map<string, number>();
24
+
20
25
  onUpdate = this.onUpdateEmitter.event;
21
26
 
27
+ currentFactoryKey = '';
28
+
29
+ updateSize(newSize: number) {
30
+ this.sizeMap.set(this.currentFactoryKey, newSize);
31
+ this.onUpdateEmitter.fire();
32
+ }
33
+
34
+ get currentSize(): number {
35
+ return this.sizeMap.get(this.currentFactoryKey) || PANEL_SIZE_DEFAULT;
36
+ }
37
+
22
38
  constructor(private config: PanelConfig) {}
23
39
 
24
40
  open(factory: PanelFactory<any>, options: any) {
25
41
  const el = factory.render(options?.props);
26
42
  const idx = this.elements.findIndex((e) => e.key === factory.key);
43
+ this.currentFactoryKey = factory.key;
44
+ if (!this.sizeMap.has(factory.key)) {
45
+ this.sizeMap.set(factory.key, factory.defaultSize || PANEL_SIZE_DEFAULT);
46
+ }
27
47
  if (idx >= 0) {
28
- this.elements[idx] = { el, key: factory.key };
48
+ this.elements[idx] = { el, key: factory.key, style: factory.style };
29
49
  } else {
30
- this.elements.push({ el, key: factory.key });
50
+ this.elements.push({ el, key: factory.key, style: factory.style });
31
51
  if (this.elements.length > this.config.max) {
32
52
  this.elements.shift();
33
53
  }
@@ -35,6 +55,10 @@ export class FloatPanel {
35
55
  this.onUpdateEmitter.fire();
36
56
  }
37
57
 
58
+ get visible() {
59
+ return this.elements.length > 0;
60
+ }
61
+
38
62
  close(key?: string) {
39
63
  if (!key) {
40
64
  this.elements = [];
@@ -3,12 +3,18 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import { PluginContext } from '@flowgram.ai/core';
7
+
6
8
  import type { PanelFactory, PanelConfig } from '../types';
9
+ import type { PanelLayerProps } from '../components/panel-layer';
7
10
 
8
11
  export interface PanelManagerConfig {
9
12
  factories: PanelFactory<any>[];
10
13
  right: PanelConfig;
11
14
  bottom: PanelConfig;
15
+ autoResize: boolean;
16
+ layerProps: PanelLayerProps;
17
+ getPopupContainer: (ctx: PluginContext) => HTMLElement; // default playground.node.parentElement
12
18
  }
13
19
 
14
20
  export const PanelManagerConfig = Symbol('PanelManagerConfig');
@@ -22,6 +28,9 @@ export const defineConfig = (config: Partial<PanelManagerConfig>) => {
22
28
  max: 1,
23
29
  },
24
30
  factories: [],
31
+ autoResize: true,
32
+ layerProps: {},
33
+ getPopupContainer: (ctx: PluginContext) => ctx.playground.node.parentNode as HTMLElement,
25
34
  };
26
35
  return {
27
36
  ...defaultConfig,
@@ -3,42 +3,51 @@
3
3
  * SPDX-License-Identifier: MIT
4
4
  */
5
5
 
6
+ import ReactDOM from 'react-dom';
6
7
  import { createElement } from 'react';
7
8
 
8
- import { injectable } from 'inversify';
9
- import { domUtils } from '@flowgram.ai/utils';
10
- import { Layer } from '@flowgram.ai/core';
9
+ import { injectable, inject } from 'inversify';
10
+ import { domUtils, Disposable } from '@flowgram.ai/utils';
11
+ import { Layer, PluginContext } from '@flowgram.ai/core';
11
12
 
12
13
  import { PanelLayer as PanelLayerComp } from '../components/panel-layer';
14
+ import { PanelManagerConfig } from './panel-config';
13
15
 
14
16
  @injectable()
15
17
  export class PanelLayer extends Layer {
16
- node = domUtils.createDivWithClass('gedit-flow-panel-layer');
18
+ @inject(PanelManagerConfig) private readonly panelConfig: PanelManagerConfig;
19
+
20
+ @inject(PluginContext) private readonly pluginContext: PluginContext;
21
+
22
+ readonly panelRoot = domUtils.createDivWithClass('gedit-flow-panel-layer');
17
23
 
18
24
  layout: JSX.Element | null = null;
19
25
 
20
26
  onReady(): void {
27
+ this.panelConfig.getPopupContainer(this.pluginContext).appendChild(this.panelRoot);
28
+ this.toDispose.push(
29
+ Disposable.create(() => {
30
+ // Remove from PopupContainer
31
+ this.panelRoot.remove();
32
+ })
33
+ );
21
34
  const commonStyle = {
22
35
  pointerEvents: 'none',
23
- zIndex: 11,
36
+ width: '100%',
37
+ height: '100%',
38
+ position: 'absolute',
39
+ left: 0,
40
+ top: 0,
41
+ zIndex: 100,
24
42
  };
25
- domUtils.setStyle(this.node, commonStyle);
26
- this.config.onDataChange(() => {
27
- const { width, height, scrollX, scrollY } = this.config.config;
28
- domUtils.setStyle(this.node, {
29
- ...commonStyle,
30
- width,
31
- height,
32
- left: scrollX,
33
- top: scrollY,
34
- });
35
- });
43
+ domUtils.setStyle(this.panelRoot, commonStyle);
36
44
  }
37
45
 
38
46
  render(): JSX.Element {
39
47
  if (!this.layout) {
40
- this.layout = createElement(PanelLayerComp);
48
+ const { children, ...layoutProps } = this.panelConfig.layerProps;
49
+ this.layout = createElement(PanelLayerComp, layoutProps, children);
41
50
  }
42
- return this.layout;
51
+ return ReactDOM.createPortal(this.layout, this.panelRoot);
43
52
  }
44
53
  }
@@ -11,7 +11,7 @@ import { FloatPanel } from './float-panel';
11
11
 
12
12
  @injectable()
13
13
  export class PanelManager {
14
- @inject(PanelManagerConfig) private readonly config: PanelManagerConfig;
14
+ @inject(PanelManagerConfig) readonly config: PanelManagerConfig;
15
15
 
16
16
  readonly panelRegistry = new Map<string, PanelFactory<any>>();
17
17
 
@@ -38,9 +38,9 @@ export class PanelManager {
38
38
  panel.open(factory, options);
39
39
  }
40
40
 
41
- close(key: string, area: Area = 'right') {
42
- const panel = this.getPanel(area);
43
- panel.close(key);
41
+ close(key?: string) {
42
+ this.right.close(key);
43
+ this.bottom.close(key);
44
44
  }
45
45
 
46
46
  getPanel(area: Area) {
package/src/types.ts CHANGED
@@ -12,5 +12,7 @@ export interface PanelConfig {
12
12
 
13
13
  export interface PanelFactory<T extends any> {
14
14
  key: string;
15
+ defaultSize: number;
16
+ style?: React.CSSProperties;
15
17
  render: (props: T) => React.ReactNode;
16
18
  }