project-graph-mcp 2.3.2 → 2.4.1
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/package.json +3 -2
- package/src/analysis/analysis-cache.ctx +9 -0
- package/src/analysis/analysis-cache.js +1 -1
- package/src/analysis/complexity.ctx +6 -0
- package/src/analysis/complexity.js +1 -1
- package/src/analysis/custom-rules.ctx +14 -0
- package/src/analysis/custom-rules.js +1 -1
- package/src/analysis/db-analysis.ctx +7 -0
- package/src/analysis/db-analysis.js +1 -1
- package/src/analysis/dead-code.ctx +6 -0
- package/src/analysis/dead-code.js +1 -1
- package/src/analysis/full-analysis.ctx +9 -0
- package/src/analysis/full-analysis.js +1 -1
- package/src/analysis/jsdoc-checker.ctx +10 -0
- package/src/analysis/jsdoc-checker.js +1 -1
- package/src/analysis/jsdoc-generator.ctx +9 -0
- package/src/analysis/jsdoc-generator.js +1 -1
- package/src/analysis/large-files.ctx +6 -0
- package/src/analysis/large-files.js +1 -1
- package/src/analysis/outdated-patterns.ctx +7 -0
- package/src/analysis/outdated-patterns.js +1 -1
- package/src/analysis/similar-functions.ctx +6 -0
- package/src/analysis/similar-functions.js +1 -1
- package/src/analysis/test-annotations.ctx +11 -0
- package/src/analysis/test-annotations.js +1 -1
- package/src/analysis/type-checker.ctx +6 -0
- package/src/analysis/type-checker.js +1 -1
- package/src/analysis/undocumented.ctx +8 -0
- package/src/analysis/undocumented.js +1 -1
- package/src/cli/cli-handlers.ctx +7 -0
- package/src/cli/cli-handlers.js +1 -1
- package/src/cli/cli.ctx +6 -0
- package/src/cli/cli.js +1 -1
- package/src/compact/ai-context.ctx +6 -0
- package/src/compact/ai-context.js +1 -1
- package/src/compact/compact-migrate.ctx +8 -0
- package/src/compact/compact-migrate.js +1 -1
- package/src/compact/compact.ctx +11 -0
- package/src/compact/compact.js +1 -1
- package/src/compact/compress.ctx +7 -0
- package/src/compact/compress.js +1 -1
- package/src/compact/ctx-resolver.ctx +2 -0
- package/src/compact/ctx-resolver.js +1 -1
- package/src/compact/ctx-to-jsdoc.ctx +11 -0
- package/src/compact/ctx-to-jsdoc.js +1 -1
- package/src/compact/doc-dialect.ctx +11 -0
- package/src/compact/doc-dialect.js +2 -2
- package/src/compact/expand.ctx +14 -0
- package/src/compact/expand.js +1 -1
- package/src/compact/framework-references.ctx +7 -0
- package/src/compact/framework-references.js +1 -1
- package/src/compact/instructions.ctx +6 -0
- package/src/compact/instructions.js +1 -1
- package/src/compact/jsdoc-builder.ctx +4 -0
- package/src/compact/jsdoc-builder.js +1 -1
- package/src/compact/mode-config.ctx +8 -0
- package/src/compact/mode-config.js +1 -1
- package/src/compact/split-declarations.ctx +6 -0
- package/src/compact/split-declarations.js +1 -1
- package/src/compact/validate-pipeline.ctx +12 -0
- package/src/compact/validate-pipeline.js +1 -1
- package/src/core/event-bus.ctx +9 -0
- package/src/core/event-bus.js +1 -1
- package/src/core/file-walker.ctx +1 -0
- package/src/core/file-walker.js +1 -1
- package/src/core/filters.ctx +12 -0
- package/src/core/filters.js +1 -1
- package/src/core/graph-builder.ctx +7 -0
- package/src/core/graph-builder.js +1 -1
- package/src/core/parser.ctx +12 -0
- package/src/core/parser.js +1 -1
- package/src/core/utils.ctx +1 -0
- package/src/core/utils.js +1 -1
- package/src/core/workspace.ctx +7 -0
- package/src/core/workspace.js +1 -1
- package/src/lang/lang-go.ctx +8 -0
- package/src/lang/lang-go.js +1 -1
- package/src/lang/lang-python.ctx +5 -0
- package/src/lang/lang-python.js +1 -1
- package/src/lang/lang-sql.ctx +10 -0
- package/src/lang/lang-sql.js +1 -1
- package/src/lang/lang-typescript.ctx +6 -0
- package/src/lang/lang-typescript.js +1 -1
- package/src/lang/lang-utils.ctx +5 -0
- package/src/lang/lang-utils.js +1 -1
- package/src/mcp/mcp-server.ctx +6 -0
- package/src/mcp/mcp-server.js +1 -1
- package/src/mcp/tool-defs.ctx +2 -0
- package/src/mcp/tool-defs.js +1 -1
- package/src/mcp/tools.ctx +13 -0
- package/src/mcp/tools.js +1 -1
- package/src/network/backend-lifecycle.ctx +10 -0
- package/src/network/backend-lifecycle.js +1 -1
- package/src/network/backend.ctx +5 -0
- package/src/network/backend.js +1 -1
- package/src/network/local-gateway.ctx +9 -0
- package/src/network/local-gateway.js +1 -1
- package/src/network/mdns.ctx +6 -0
- package/src/network/mdns.js +1 -1
- package/src/network/server.ctx +2 -0
- package/src/network/server.js +2 -2
- package/src/network/web-server.ctx +17 -0
- package/src/network/web-server.js +2 -2
- package/web/follow-controller.js +94 -25
- package/web/panels/dep-graph.js +207 -21
- package/project-graph-mcp-2.3.0.tgz +0 -0
- package/vendor/symbiote-node/CHANGELOG.md +0 -31
- package/vendor/symbiote-node/LICENSE +0 -21
- package/vendor/symbiote-node/README.md +0 -206
- package/vendor/symbiote-node/canvas/AutoLayout.js +0 -725
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.css.js +0 -73
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.js +0 -93
- package/vendor/symbiote-node/canvas/Breadcrumb/Breadcrumb.tpl.js +0 -9
- package/vendor/symbiote-node/canvas/CanvasConnectionRenderer.js +0 -962
- package/vendor/symbiote-node/canvas/ConnectionRenderer.js +0 -1468
- package/vendor/symbiote-node/canvas/FlowSimulator.js +0 -323
- package/vendor/symbiote-node/canvas/ForceLayout.js +0 -189
- package/vendor/symbiote-node/canvas/ForceWorker.js +0 -1325
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.css.js +0 -97
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.js +0 -176
- package/vendor/symbiote-node/canvas/GraphTabs/GraphTabs.tpl.js +0 -12
- package/vendor/symbiote-node/canvas/LODManager.js +0 -88
- package/vendor/symbiote-node/canvas/Minimap/Minimap.css.js +0 -71
- package/vendor/symbiote-node/canvas/Minimap/Minimap.js +0 -207
- package/vendor/symbiote-node/canvas/Minimap/Minimap.tpl.js +0 -9
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.css.js +0 -261
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.js +0 -1840
- package/vendor/symbiote-node/canvas/NodeCanvas/NodeCanvas.tpl.js +0 -22
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.css.js +0 -97
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.js +0 -132
- package/vendor/symbiote-node/canvas/NodeSearch/NodeSearch.tpl.js +0 -21
- package/vendor/symbiote-node/canvas/NodeViewManager.js +0 -584
- package/vendor/symbiote-node/canvas/PinExpansion.js +0 -131
- package/vendor/symbiote-node/canvas/PseudoConnection.js +0 -80
- package/vendor/symbiote-node/canvas/SubgraphManager.js +0 -201
- package/vendor/symbiote-node/canvas/SubgraphRouter.js +0 -443
- package/vendor/symbiote-node/canvas/ViewportActions.js +0 -446
- package/vendor/symbiote-node/core/Connection.js +0 -45
- package/vendor/symbiote-node/core/Editor.js +0 -451
- package/vendor/symbiote-node/core/Frame.js +0 -31
- package/vendor/symbiote-node/core/GraphMermaid.js +0 -348
- package/vendor/symbiote-node/core/GraphText.js +0 -210
- package/vendor/symbiote-node/core/Node.js +0 -143
- package/vendor/symbiote-node/core/Portal.js +0 -104
- package/vendor/symbiote-node/core/Socket.js +0 -185
- package/vendor/symbiote-node/core/SubgraphNode.js +0 -125
- package/vendor/symbiote-node/engine/AgentUICommands.js +0 -100
- package/vendor/symbiote-node/engine/Executor.js +0 -371
- package/vendor/symbiote-node/engine/Graph.js +0 -314
- package/vendor/symbiote-node/engine/GraphServer.js +0 -353
- package/vendor/symbiote-node/engine/HandlerLoader.js +0 -145
- package/vendor/symbiote-node/engine/History.js +0 -83
- package/vendor/symbiote-node/engine/Lifecycle.js +0 -118
- package/vendor/symbiote-node/engine/Persistence.js +0 -84
- package/vendor/symbiote-node/engine/Registry.js +0 -264
- package/vendor/symbiote-node/engine/SocketTypes.js +0 -79
- package/vendor/symbiote-node/engine/cli.js +0 -404
- package/vendor/symbiote-node/engine/index.js +0 -56
- package/vendor/symbiote-node/engine/nanoid.js +0 -28
- package/vendor/symbiote-node/engine/package.json +0 -26
- package/vendor/symbiote-node/engine/packs/ai/beat-detect.handler.js +0 -215
- package/vendor/symbiote-node/engine/packs/ai/content-adapt.handler.js +0 -238
- package/vendor/symbiote-node/engine/packs/ai/face-detect.handler.js +0 -287
- package/vendor/symbiote-node/engine/packs/ai/grok-generate.handler.js +0 -565
- package/vendor/symbiote-node/engine/packs/ai/kling-lipsync.handler.js +0 -414
- package/vendor/symbiote-node/engine/packs/ai/lesson-generate.handler.js +0 -343
- package/vendor/symbiote-node/engine/packs/ai/opencode.handler.js +0 -164
- package/vendor/symbiote-node/engine/packs/ai/replicate-lipsync.handler.js +0 -341
- package/vendor/symbiote-node/engine/packs/ai/tts.handler.js +0 -241
- package/vendor/symbiote-node/engine/packs/ai/whisper.handler.js +0 -191
- package/vendor/symbiote-node/engine/packs/data/db-query.handler.js +0 -67
- package/vendor/symbiote-node/engine/packs/data/news-accumulate.handler.js +0 -281
- package/vendor/symbiote-node/engine/packs/data/personas.handler.js +0 -160
- package/vendor/symbiote-node/engine/packs/data/prompt-loader.handler.js +0 -193
- package/vendor/symbiote-node/engine/packs/data/roles.handler.js +0 -216
- package/vendor/symbiote-node/engine/packs/data/rss-feed.handler.js +0 -244
- package/vendor/symbiote-node/engine/packs/debug/inject.handler.js +0 -52
- package/vendor/symbiote-node/engine/packs/flow/agent.handler.js +0 -73
- package/vendor/symbiote-node/engine/packs/flow/if.handler.js +0 -107
- package/vendor/symbiote-node/engine/packs/flow/loop.handler.js +0 -58
- package/vendor/symbiote-node/engine/packs/flow/merge.handler.js +0 -60
- package/vendor/symbiote-node/engine/packs/flow/retry.handler.js +0 -65
- package/vendor/symbiote-node/engine/packs/flow/switch.handler.js +0 -64
- package/vendor/symbiote-node/engine/packs/flow/wait-all.handler.js +0 -39
- package/vendor/symbiote-node/engine/packs/io/http-request.handler.js +0 -82
- package/vendor/symbiote-node/engine/packs/io/read-file.handler.js +0 -60
- package/vendor/symbiote-node/engine/packs/io/write-file.handler.js +0 -63
- package/vendor/symbiote-node/engine/packs/transform/anchor-match.handler.js +0 -494
- package/vendor/symbiote-node/engine/packs/transform/effects-skeleton.handler.js +0 -417
- package/vendor/symbiote-node/engine/packs/transform/json-parse.handler.js +0 -43
- package/vendor/symbiote-node/engine/packs/transform/lipsync-select.handler.js +0 -339
- package/vendor/symbiote-node/engine/packs/transform/riopla-adapt.handler.js +0 -432
- package/vendor/symbiote-node/engine/packs/transform/set.handler.js +0 -57
- package/vendor/symbiote-node/engine/packs/transform/template-builder.handler.js +0 -134
- package/vendor/symbiote-node/engine/packs/transform/template.handler.js +0 -79
- package/vendor/symbiote-node/engine/packs/transform/timeline-build.handler.js +0 -399
- package/vendor/symbiote-node/engine/packs/util/delay.handler.js +0 -39
- package/vendor/symbiote-node/engine/packs/util/log.handler.js +0 -44
- package/vendor/symbiote-node/engine/packs/video-pack.js +0 -323
- package/vendor/symbiote-node/index.js +0 -103
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.css.js +0 -361
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.js +0 -332
- package/vendor/symbiote-node/inspector/InspectorPanel/InspectorPanel.tpl.js +0 -96
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.css.js +0 -104
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.js +0 -133
- package/vendor/symbiote-node/inspector/TemplatePreview/TemplatePreview.tpl.js +0 -33
- package/vendor/symbiote-node/interactions/ConnectFlow.js +0 -307
- package/vendor/symbiote-node/interactions/Drag.js +0 -102
- package/vendor/symbiote-node/interactions/Selector.js +0 -132
- package/vendor/symbiote-node/interactions/SnapGrid.js +0 -65
- package/vendor/symbiote-node/interactions/Zoom.js +0 -140
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.css.js +0 -88
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.js +0 -254
- package/vendor/symbiote-node/layout/ActionZone/ActionZone.tpl.js +0 -11
- package/vendor/symbiote-node/layout/Layout/Layout.css.js +0 -88
- package/vendor/symbiote-node/layout/Layout/Layout.js +0 -622
- package/vendor/symbiote-node/layout/Layout/Layout.tpl.js +0 -25
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.css.js +0 -293
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.js +0 -467
- package/vendor/symbiote-node/layout/LayoutNode/LayoutNode.tpl.js +0 -33
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.css.js +0 -46
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.js +0 -102
- package/vendor/symbiote-node/layout/LayoutPreview/LayoutPreview.tpl.js +0 -6
- package/vendor/symbiote-node/layout/LayoutRouter/LayoutRouter.js +0 -156
- package/vendor/symbiote-node/layout/LayoutRouter/routerSync.js +0 -250
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.css.js +0 -379
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.js +0 -263
- package/vendor/symbiote-node/layout/LayoutSidebar/LayoutSidebar.tpl.js +0 -20
- package/vendor/symbiote-node/layout/LayoutSidebar/SidebarSection.js +0 -183
- package/vendor/symbiote-node/layout/LayoutTree.js +0 -246
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.css.js +0 -43
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.js +0 -89
- package/vendor/symbiote-node/layout/PanelMenu/PanelMenu.tpl.js +0 -14
- package/vendor/symbiote-node/layout/index.js +0 -16
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.css.js +0 -61
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.js +0 -79
- package/vendor/symbiote-node/menu/ContextMenu/ContextMenu.tpl.js +0 -19
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.css.js +0 -41
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.js +0 -24
- package/vendor/symbiote-node/node/CtrlItem/CtrlItem.tpl.js +0 -16
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.css.js +0 -65
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.js +0 -29
- package/vendor/symbiote-node/node/GraphFrame/GraphFrame.tpl.js +0 -13
- package/vendor/symbiote-node/node/GraphNode/GraphNode.css.js +0 -683
- package/vendor/symbiote-node/node/GraphNode/GraphNode.js +0 -92
- package/vendor/symbiote-node/node/GraphNode/GraphNode.tpl.js +0 -17
- package/vendor/symbiote-node/node/NodeSocket/NodeSocket.js +0 -25
- package/vendor/symbiote-node/node/NodeSocket/NodeSocket.tpl.js +0 -7
- package/vendor/symbiote-node/node/PortItem/PortItem.css.js +0 -90
- package/vendor/symbiote-node/node/PortItem/PortItem.js +0 -87
- package/vendor/symbiote-node/node/PortItem/PortItem.tpl.js +0 -10
- package/vendor/symbiote-node/package.json +0 -59
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.css.js +0 -143
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.js +0 -131
- package/vendor/symbiote-node/palette/PaletteBrowser/PaletteBrowser.tpl.js +0 -16
- package/vendor/symbiote-node/plugins/History.js +0 -384
- package/vendor/symbiote-node/plugins/Readonly.js +0 -59
- package/vendor/symbiote-node/shapes/CircleShape.js +0 -80
- package/vendor/symbiote-node/shapes/CommentShape.js +0 -35
- package/vendor/symbiote-node/shapes/DiamondShape.js +0 -115
- package/vendor/symbiote-node/shapes/NodeShape.js +0 -80
- package/vendor/symbiote-node/shapes/PillShape.js +0 -91
- package/vendor/symbiote-node/shapes/RectShape.js +0 -72
- package/vendor/symbiote-node/shapes/SVGShape.js +0 -494
- package/vendor/symbiote-node/shapes/index.js +0 -53
- package/vendor/symbiote-node/themes/Palette.js +0 -32
- package/vendor/symbiote-node/themes/Skin.js +0 -113
- package/vendor/symbiote-node/themes/Theme.js +0 -84
- package/vendor/symbiote-node/themes/carbon.js +0 -137
- package/vendor/symbiote-node/themes/dark.js +0 -137
- package/vendor/symbiote-node/themes/ebook.js +0 -138
- package/vendor/symbiote-node/themes/grey.js +0 -137
- package/vendor/symbiote-node/themes/light.js +0 -137
- package/vendor/symbiote-node/themes/neon.js +0 -138
- package/vendor/symbiote-node/themes/pcb.js +0 -273
- package/vendor/symbiote-node/themes/synthwave.js +0 -137
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.css.js +0 -86
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.js +0 -128
- package/vendor/symbiote-node/toolbar/QuickToolbar/QuickToolbar.tpl.js +0 -29
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview LayoutNode - Universal recursive layout node
|
|
3
|
-
* Renders panel or split based on node type.
|
|
4
|
-
* Split nodes recursively create child LayoutNodes.
|
|
5
|
-
* Panels include action zones for split/join gestures.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import Symbiote from '@symbiotejs/symbiote';
|
|
9
|
-
import { template } from './LayoutNode.tpl.js';
|
|
10
|
-
import { styles } from './LayoutNode.css.js';
|
|
11
|
-
import './../ActionZone/ActionZone.js';
|
|
12
|
-
|
|
13
|
-
export class LayoutNode extends Symbiote {
|
|
14
|
-
static isoMode = true;
|
|
15
|
-
|
|
16
|
-
init$ = {
|
|
17
|
-
// Node data
|
|
18
|
-
nodeData: null,
|
|
19
|
-
|
|
20
|
-
// Computed values (updated in sub())
|
|
21
|
-
nodeType: 'panel',
|
|
22
|
-
isPanel: true,
|
|
23
|
-
isSplit: false,
|
|
24
|
-
direction: 'horizontal',
|
|
25
|
-
ratio: 0.5,
|
|
26
|
-
panelType: 'default',
|
|
27
|
-
nodeId: '',
|
|
28
|
-
|
|
29
|
-
// Panel display
|
|
30
|
-
panelTitle: 'Panel',
|
|
31
|
-
panelIcon: 'dashboard',
|
|
32
|
-
|
|
33
|
-
// Panel states
|
|
34
|
-
isCollapsed: false,
|
|
35
|
-
canCollapse: true, // Whether collapse is possible (has sibling panel)
|
|
36
|
-
collapseDirection: 'vertical', // 'vertical' or 'horizontal' - based on parent split
|
|
37
|
-
collapseIcon: 'expand_less',
|
|
38
|
-
savedRatio: 0.5, // Saved ratio before collapse for proper restore
|
|
39
|
-
isFullscreen: false,
|
|
40
|
-
fullscreenIcon: 'fullscreen',
|
|
41
|
-
|
|
42
|
-
// Split sizing
|
|
43
|
-
firstStyle: '',
|
|
44
|
-
secondStyle: '',
|
|
45
|
-
|
|
46
|
-
// Inherited from Layout
|
|
47
|
-
'^panelTypes': {},
|
|
48
|
-
'^fullscreenPanelId': null,
|
|
49
|
-
|
|
50
|
-
// Handlers
|
|
51
|
-
onResizerDown: (e) => this._startResize(e),
|
|
52
|
-
onTypeClick: (e) => this._showTypeMenu(e),
|
|
53
|
-
onCollapseClick: () => this._toggleCollapse(),
|
|
54
|
-
onExpandClick: () => this._toggleCollapse(), // Alias for collapsed state
|
|
55
|
-
onFullscreenClick: () => this._toggleFullscreen(),
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
renderCallback() {
|
|
59
|
-
// Subscribe to nodeData changes and update computed values
|
|
60
|
-
this.sub('nodeData', (data) => {
|
|
61
|
-
if (!data) return;
|
|
62
|
-
|
|
63
|
-
this.$.nodeType = data.type || 'panel';
|
|
64
|
-
this.$.isPanel = this.$.nodeType === 'panel';
|
|
65
|
-
this.$.isSplit = this.$.nodeType === 'split';
|
|
66
|
-
this.$.direction = data.direction || 'horizontal';
|
|
67
|
-
this.$.ratio = data.ratio || 0.5;
|
|
68
|
-
this.$.panelType = data.panelType || 'default';
|
|
69
|
-
this.$.nodeId = data.id || '';
|
|
70
|
-
|
|
71
|
-
// Read collapsed state from data (declarative)
|
|
72
|
-
if (data.type === 'panel') {
|
|
73
|
-
this.$.isCollapsed = data.collapsed || false;
|
|
74
|
-
if (this.$.isCollapsed) {
|
|
75
|
-
this.setAttribute('collapsed', '');
|
|
76
|
-
this.setAttribute('collapse-dir', this.$.collapseDirection);
|
|
77
|
-
} else {
|
|
78
|
-
this.removeAttribute('collapsed');
|
|
79
|
-
this.removeAttribute('collapse-dir');
|
|
80
|
-
}
|
|
81
|
-
// Update icon based on direction
|
|
82
|
-
if (this.$.isCollapsed) {
|
|
83
|
-
if (this.$.collapseDirection === 'horizontal') {
|
|
84
|
-
this.$.collapseIcon = 'chevron_right';
|
|
85
|
-
} else {
|
|
86
|
-
this.$.collapseIcon = 'expand_more';
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
if (this.$.collapseDirection === 'horizontal') {
|
|
90
|
-
this.$.collapseIcon = 'chevron_left';
|
|
91
|
-
} else {
|
|
92
|
-
this.$.collapseIcon = 'expand_less';
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
this._updateStyles();
|
|
98
|
-
this._updatePanelInfo();
|
|
99
|
-
this._renderNode(data);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
// Subscribe to panelTypes changes to update icons when registered after render
|
|
103
|
-
this.sub('^panelTypes', () => {
|
|
104
|
-
this._updatePanelInfo();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Subscribe to panelType changes to inject component when type changes via menu
|
|
108
|
-
this.sub('panelType', () => {
|
|
109
|
-
this._updatePanelInfo();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// Initial render if data already set
|
|
113
|
-
if (this.$.nodeData) {
|
|
114
|
-
this.sub('nodeData', (d) => { }); // Trigger subscription
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
_updateStyles() {
|
|
119
|
-
const ratio = this.$.ratio;
|
|
120
|
-
const dir = this.$.direction;
|
|
121
|
-
const data = this.$.nodeData;
|
|
122
|
-
|
|
123
|
-
// Check if children are collapsed (declarative from nodeData)
|
|
124
|
-
const firstCollapsed = data?.first?.collapsed || false;
|
|
125
|
-
const secondCollapsed = data?.second?.collapsed || false;
|
|
126
|
-
|
|
127
|
-
// Collapsed size constants
|
|
128
|
-
const COLLAPSED_SIZE = dir === 'horizontal' ? '32px' : '28px';
|
|
129
|
-
|
|
130
|
-
if (firstCollapsed) {
|
|
131
|
-
// First child collapsed - fixed size, second expands
|
|
132
|
-
if (dir === 'horizontal') {
|
|
133
|
-
this.$.firstStyle = `width: ${COLLAPSED_SIZE}; height: 100%; flex: 0 0 ${COLLAPSED_SIZE};`;
|
|
134
|
-
this.$.secondStyle = 'flex: 1; height: 100%;';
|
|
135
|
-
} else {
|
|
136
|
-
this.$.firstStyle = `height: ${COLLAPSED_SIZE}; width: 100%; flex: 0 0 ${COLLAPSED_SIZE};`;
|
|
137
|
-
this.$.secondStyle = 'flex: 1; width: 100%;';
|
|
138
|
-
}
|
|
139
|
-
} else if (secondCollapsed) {
|
|
140
|
-
// Second child collapsed - first expands, fixed size
|
|
141
|
-
if (dir === 'horizontal') {
|
|
142
|
-
this.$.firstStyle = 'flex: 1; height: 100%;';
|
|
143
|
-
this.$.secondStyle = `width: ${COLLAPSED_SIZE}; height: 100%; flex: 0 0 ${COLLAPSED_SIZE};`;
|
|
144
|
-
} else {
|
|
145
|
-
this.$.firstStyle = 'flex: 1; width: 100%;';
|
|
146
|
-
this.$.secondStyle = `height: ${COLLAPSED_SIZE}; width: 100%; flex: 0 0 ${COLLAPSED_SIZE};`;
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
// Normal ratio-based sizing
|
|
150
|
-
if (dir === 'horizontal') {
|
|
151
|
-
this.$.firstStyle = `width: ${ratio * 100}%; height: 100%;`;
|
|
152
|
-
this.$.secondStyle = `width: ${(1 - ratio) * 100}%; height: 100%;`;
|
|
153
|
-
} else {
|
|
154
|
-
this.$.firstStyle = `height: ${ratio * 100}%; width: 100%;`;
|
|
155
|
-
this.$.secondStyle = `height: ${(1 - ratio) * 100}%; width: 100%;`;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
_updatePanelInfo() {
|
|
161
|
-
const panelTypes = this.$['^panelTypes'] || {};
|
|
162
|
-
const config = panelTypes[this.$.panelType] || {};
|
|
163
|
-
this.$.panelTitle = config.title || this.$.panelType;
|
|
164
|
-
this.$.panelIcon = config.icon || 'dashboard';
|
|
165
|
-
|
|
166
|
-
// Inject component if specified and not already created
|
|
167
|
-
this._injectPanelComponent(config);
|
|
168
|
-
|
|
169
|
-
// Check if panel can collapse (must be child of a split)
|
|
170
|
-
const container = this.parentElement;
|
|
171
|
-
if (!container) return;
|
|
172
|
-
const isSplitChild = container && (container.classList.contains('split-first') || container.classList.contains('split-second'));
|
|
173
|
-
|
|
174
|
-
// Additional safety check: Ensure sibling exists and is not collapsed
|
|
175
|
-
let siblingExists = false;
|
|
176
|
-
let siblingCollapsed = false;
|
|
177
|
-
let isFirst = false;
|
|
178
|
-
|
|
179
|
-
if (isSplitChild) {
|
|
180
|
-
isFirst = container.classList.contains('split-first');
|
|
181
|
-
// Use :scope > to find direct child only, not nested ones
|
|
182
|
-
const siblingContainer = isFirst
|
|
183
|
-
? container.parentElement.querySelector(':scope > .split-second')
|
|
184
|
-
: container.parentElement.querySelector(':scope > .split-first');
|
|
185
|
-
siblingExists = !!siblingContainer;
|
|
186
|
-
|
|
187
|
-
// Check if sibling panel is collapsed (direct child panel only)
|
|
188
|
-
if (siblingContainer) {
|
|
189
|
-
const siblingNode = siblingContainer.querySelector(':scope > layout-node');
|
|
190
|
-
// Only check collapsed state if sibling is a panel
|
|
191
|
-
if (siblingNode?.getAttribute('node-type') === 'panel') {
|
|
192
|
-
siblingCollapsed = siblingNode.$.isCollapsed || false;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// If we are a panel, update canCollapse based on position
|
|
198
|
-
if (this.$.nodeType === 'panel') {
|
|
199
|
-
// Can't collapse if no sibling OR if sibling is already collapsed (would leave empty space)
|
|
200
|
-
this.$.canCollapse = !!isSplitChild && siblingExists && !siblingCollapsed;
|
|
201
|
-
|
|
202
|
-
if (isSplitChild) {
|
|
203
|
-
// Update direction based on parent split
|
|
204
|
-
let parentNode = container.closest('layout-node');
|
|
205
|
-
if (!parentNode && container.getRootNode() instanceof ShadowRoot) {
|
|
206
|
-
parentNode = container.getRootNode().host;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (parentNode) {
|
|
210
|
-
const parentDir = parentNode.getAttribute('direction');
|
|
211
|
-
this.$.collapseDirection = parentDir;
|
|
212
|
-
|
|
213
|
-
// Arrow shows direction panel will collapse TO:
|
|
214
|
-
// First panel collapses left/up, second panel collapses right/down
|
|
215
|
-
if (!this.$.isCollapsed) {
|
|
216
|
-
if (parentDir === 'horizontal') {
|
|
217
|
-
this.$.collapseIcon = isFirst ? 'chevron_left' : 'chevron_right';
|
|
218
|
-
} else {
|
|
219
|
-
this.$.collapseIcon = isFirst ? 'expand_less' : 'expand_more';
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Inject custom component into panel content.
|
|
229
|
-
* Hides existing components instead of destroying them to preserve state.
|
|
230
|
-
* Uses style.display instead of hidden attribute because components may have
|
|
231
|
-
* CSS rules (e.g. display:block) that override the hidden attribute.
|
|
232
|
-
* @param {Object} config - Panel type configuration
|
|
233
|
-
*/
|
|
234
|
-
_injectPanelComponent(config) {
|
|
235
|
-
const contentEl = this.ref.panelContent;
|
|
236
|
-
if (!contentEl) return;
|
|
237
|
-
|
|
238
|
-
const componentTag = config.component;
|
|
239
|
-
if (!componentTag) return;
|
|
240
|
-
|
|
241
|
-
// Hide all existing panel components via inline style (overrides CSS)
|
|
242
|
-
for (const child of contentEl.children) {
|
|
243
|
-
child.style.display = 'none';
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Check if target component already exists — show it
|
|
247
|
-
const existing = contentEl.querySelector(componentTag);
|
|
248
|
-
if (existing) {
|
|
249
|
-
existing.style.display = '';
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Create new component
|
|
254
|
-
const component = document.createElement(componentTag);
|
|
255
|
-
component.setAttribute('data-panel-id', this.$.nodeData?.id || '');
|
|
256
|
-
contentEl.appendChild(component);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
_renderNode(data) {
|
|
260
|
-
// Update attributes for CSS selectors
|
|
261
|
-
const prevType = this.getAttribute('node-type');
|
|
262
|
-
this.setAttribute('node-type', data.type);
|
|
263
|
-
|
|
264
|
-
if (data.type === 'split') {
|
|
265
|
-
this.setAttribute('direction', data.direction);
|
|
266
|
-
this._renderSplit(data);
|
|
267
|
-
} else {
|
|
268
|
-
this.removeAttribute('direction');
|
|
269
|
-
|
|
270
|
-
// CRITICAL: Clean up child nodes if we changed from split to panel
|
|
271
|
-
// This prevents orphan layout-node elements staying in DOM
|
|
272
|
-
if (prevType === 'split') {
|
|
273
|
-
if (this.ref.first) this.ref.first.innerHTML = '';
|
|
274
|
-
if (this.ref.second) this.ref.second.innerHTML = '';
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// For panels, setup action zones
|
|
278
|
-
this._setupActionZones(data.id);
|
|
279
|
-
// Ensure collapse status is updated
|
|
280
|
-
this._updatePanelInfo();
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
_renderSplit(data) {
|
|
285
|
-
// Create child nodes for first and second
|
|
286
|
-
// Pass the current split direction so panels know which way to collapse
|
|
287
|
-
if (data.first && this.ref.first) {
|
|
288
|
-
this._ensureChildNode(this.ref.first, data.first);
|
|
289
|
-
}
|
|
290
|
-
if (data.second && this.ref.second) {
|
|
291
|
-
this._ensureChildNode(this.ref.second, data.second);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* @param {HTMLElement} container
|
|
297
|
-
* @param {Object} nodeData
|
|
298
|
-
*/
|
|
299
|
-
_ensureChildNode(container, nodeData) {
|
|
300
|
-
let child = container.querySelector('layout-node');
|
|
301
|
-
if (!child) {
|
|
302
|
-
child = document.createElement('layout-node');
|
|
303
|
-
container.appendChild(child);
|
|
304
|
-
// Wait for child to initialize then update info
|
|
305
|
-
if (typeof setTimeout !== 'undefined') {
|
|
306
|
-
setTimeout(() => child._updatePanelInfo && child._updatePanelInfo());
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// Use shallow copy to ensure subscription triggers even if only nested properties changed
|
|
310
|
-
child.$.nodeData = { ...nodeData };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
_setupActionZones(panelId) {
|
|
314
|
-
// Action zones are in the template, just set their panel ID
|
|
315
|
-
const zones = this.querySelectorAll('action-zone');
|
|
316
|
-
zones.forEach((zone) => {
|
|
317
|
-
zone.$.panelId = panelId;
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
_startResize(e) {
|
|
322
|
-
e.preventDefault();
|
|
323
|
-
const startPos = this.$.direction === 'horizontal' ? e.clientX : e.clientY;
|
|
324
|
-
const startRatio = this.$.ratio;
|
|
325
|
-
|
|
326
|
-
this.setAttribute('resizing', '');
|
|
327
|
-
|
|
328
|
-
// Collapse thresholds
|
|
329
|
-
const COLLAPSE_THRESHOLD = 0.05;
|
|
330
|
-
const UNCOLLAPSE_THRESHOLD = 0.08;
|
|
331
|
-
|
|
332
|
-
const onMove = (moveEvent) => {
|
|
333
|
-
const rect = this.getBoundingClientRect();
|
|
334
|
-
const currentPos = this.$.direction === 'horizontal' ? moveEvent.clientX : moveEvent.clientY;
|
|
335
|
-
const containerSize = this.$.direction === 'horizontal' ? rect.width : rect.height;
|
|
336
|
-
const startOffset = this.$.direction === 'horizontal' ? rect.left : rect.top;
|
|
337
|
-
|
|
338
|
-
// Calculate new ratio based on mouse position relative to container
|
|
339
|
-
let rawRatio = (currentPos - startOffset) / containerSize;
|
|
340
|
-
|
|
341
|
-
// Get first and second child nodes
|
|
342
|
-
const firstChild = this.ref.first?.querySelector('layout-node');
|
|
343
|
-
const secondChild = this.ref.second?.querySelector('layout-node');
|
|
344
|
-
|
|
345
|
-
// Check for collapse/uncollapse of first panel
|
|
346
|
-
if (rawRatio < COLLAPSE_THRESHOLD && firstChild && !firstChild.$.isCollapsed) {
|
|
347
|
-
// Collapse first panel
|
|
348
|
-
firstChild._setCollapsed(true);
|
|
349
|
-
return; // Don't update styles further when collapsed
|
|
350
|
-
} else if (rawRatio > UNCOLLAPSE_THRESHOLD && firstChild?.$.isCollapsed) {
|
|
351
|
-
// Uncollapse first panel
|
|
352
|
-
firstChild._setCollapsed(false);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// Check for collapse/uncollapse of second panel
|
|
356
|
-
if (rawRatio > (1 - COLLAPSE_THRESHOLD) && secondChild && !secondChild.$.isCollapsed) {
|
|
357
|
-
// Collapse second panel
|
|
358
|
-
secondChild._setCollapsed(true);
|
|
359
|
-
return; // Don't update styles further when collapsed
|
|
360
|
-
} else if (rawRatio < (1 - UNCOLLAPSE_THRESHOLD) && secondChild?.$.isCollapsed) {
|
|
361
|
-
// Uncollapse second panel
|
|
362
|
-
secondChild._setCollapsed(false);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Skip style updates if any panel is still collapsed
|
|
366
|
-
if (firstChild?.$.isCollapsed || secondChild?.$.isCollapsed) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Clamp ratio
|
|
371
|
-
let newRatio = Math.max(0.1, Math.min(0.9, rawRatio));
|
|
372
|
-
|
|
373
|
-
// Update ratio and styles
|
|
374
|
-
this.$.ratio = newRatio;
|
|
375
|
-
this._updateStyles();
|
|
376
|
-
|
|
377
|
-
// Update nodeData for persistence
|
|
378
|
-
if (this.$.nodeData) {
|
|
379
|
-
this.$.nodeData.ratio = newRatio;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// Notify parent
|
|
383
|
-
this._notifyChange();
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
const onUp = () => {
|
|
387
|
-
this.removeAttribute('resizing');
|
|
388
|
-
document.removeEventListener('pointermove', onMove);
|
|
389
|
-
document.removeEventListener('pointerup', onUp);
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
document.addEventListener('pointermove', onMove);
|
|
393
|
-
document.addEventListener('pointerup', onUp);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
_notifyChange() {
|
|
397
|
-
this.dispatchEvent(new CustomEvent('layout-change', {
|
|
398
|
-
bubbles: true,
|
|
399
|
-
detail: { nodeId: this.$.nodeId }
|
|
400
|
-
}));
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
_toggleCollapse() {
|
|
404
|
-
// Dispatch event to Layout - it will update the tree data
|
|
405
|
-
// which triggers a re-render with declarative collapsed handling
|
|
406
|
-
this.dispatchEvent(new CustomEvent('panel-collapse-toggle', {
|
|
407
|
-
bubbles: true,
|
|
408
|
-
composed: true,
|
|
409
|
-
detail: {
|
|
410
|
-
panelId: this.$.nodeId,
|
|
411
|
-
collapsed: !this.$.isCollapsed
|
|
412
|
-
}
|
|
413
|
-
}));
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Programmatically set collapsed state (used by resize gesture)
|
|
418
|
-
* @param {boolean} collapsed
|
|
419
|
-
*/
|
|
420
|
-
_setCollapsed(collapsed) {
|
|
421
|
-
if (this.$.isCollapsed === collapsed) return;
|
|
422
|
-
|
|
423
|
-
// Dispatch event to Layout - it will update the tree data
|
|
424
|
-
this.dispatchEvent(new CustomEvent('panel-collapse-toggle', {
|
|
425
|
-
bubbles: true,
|
|
426
|
-
composed: true,
|
|
427
|
-
detail: {
|
|
428
|
-
panelId: this.$.nodeId,
|
|
429
|
-
collapsed: collapsed
|
|
430
|
-
}
|
|
431
|
-
}));
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
_toggleFullscreen() {
|
|
435
|
-
// Don't allow fullscreen when collapsed
|
|
436
|
-
if (this.$.isCollapsed) return;
|
|
437
|
-
|
|
438
|
-
this.dispatchEvent(new CustomEvent('panel-fullscreen', {
|
|
439
|
-
bubbles: true,
|
|
440
|
-
composed: true,
|
|
441
|
-
detail: { panelId: this.$.nodeId }
|
|
442
|
-
}));
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
_showTypeMenu(e) {
|
|
446
|
-
// Don't show type menu when collapsed
|
|
447
|
-
if (this.$.isCollapsed) return;
|
|
448
|
-
|
|
449
|
-
const rect = e.target.getBoundingClientRect();
|
|
450
|
-
this.dispatchEvent(new CustomEvent('panel-type-menu', {
|
|
451
|
-
bubbles: true,
|
|
452
|
-
composed: true,
|
|
453
|
-
detail: {
|
|
454
|
-
panelId: this.$.nodeId,
|
|
455
|
-
currentType: this.$.panelType,
|
|
456
|
-
x: rect.left,
|
|
457
|
-
y: rect.bottom + 4
|
|
458
|
-
}
|
|
459
|
-
}));
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
LayoutNode.template = template;
|
|
464
|
-
LayoutNode.rootStyles = styles;
|
|
465
|
-
|
|
466
|
-
LayoutNode.reg('layout-node');
|
|
467
|
-
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { html } from '@symbiotejs/symbiote';
|
|
2
|
-
|
|
3
|
-
export const template = html`
|
|
4
|
-
<div class="panel-view" ${{ '@hidden': '!isPanel' }}>
|
|
5
|
-
<div class="panel-header">
|
|
6
|
-
<button class="header-btn type-btn" ${{ onclick: 'onTypeClick' }}>
|
|
7
|
-
<span class="material-symbols-outlined panel-icon" ${{ textContent: 'panelIcon' }}></span>
|
|
8
|
-
<span class="panel-title" ${{ textContent: 'panelTitle' }}></span>
|
|
9
|
-
<span class="material-symbols-outlined dropdown-arrow">arrow_drop_down</span>
|
|
10
|
-
</button>
|
|
11
|
-
<div class="header-spacer"></div>
|
|
12
|
-
<button class="header-btn collapse-btn" ${{ onclick: 'onCollapseClick', '@hidden': '!canCollapse' }} title="Collapse">
|
|
13
|
-
<span class="material-symbols-outlined" ${{ textContent: 'collapseIcon' }}></span>
|
|
14
|
-
</button>
|
|
15
|
-
<button class="header-btn fullscreen-btn" ${{ onclick: 'onFullscreenClick' }} title="Fullscreen">
|
|
16
|
-
<span class="material-symbols-outlined" ${{ textContent: 'fullscreenIcon' }}></span>
|
|
17
|
-
</button>
|
|
18
|
-
</div>
|
|
19
|
-
<div class="panel-content" ref="panelContent" ${{ '@hidden': 'isCollapsed' }}></div>
|
|
20
|
-
|
|
21
|
-
<!-- Action zones for split/join -->
|
|
22
|
-
<action-zone corner="tl"></action-zone>
|
|
23
|
-
<action-zone corner="tr"></action-zone>
|
|
24
|
-
<action-zone corner="bl"></action-zone>
|
|
25
|
-
<action-zone corner="br"></action-zone>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<div class="split-view" ${{ '@hidden': '!isSplit', '@direction': 'direction' }}>
|
|
29
|
-
<div class="split-first" ref="first" ${{ '@style': 'firstStyle' }}></div>
|
|
30
|
-
<div class="split-resizer" ${{ onpointerdown: 'onResizerDown' }}></div>
|
|
31
|
-
<div class="split-second" ref="second" ${{ '@style': 'secondStyle' }}></div>
|
|
32
|
-
</div>
|
|
33
|
-
`;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { css } from '@symbiotejs/symbiote';
|
|
2
|
-
|
|
3
|
-
export const styles = css`
|
|
4
|
-
layout-preview {
|
|
5
|
-
position: fixed;
|
|
6
|
-
top: 0;
|
|
7
|
-
left: 0;
|
|
8
|
-
width: 100%;
|
|
9
|
-
height: 100%;
|
|
10
|
-
pointer-events: none;
|
|
11
|
-
z-index: 9999;
|
|
12
|
-
|
|
13
|
-
&[hidden] {
|
|
14
|
-
display: none;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.preview-overlay {
|
|
18
|
-
position: absolute;
|
|
19
|
-
background: color-mix(in srgb, var(--sn-danger-color, #ef4444) 30%, transparent);
|
|
20
|
-
border: 2px solid color-mix(in srgb, var(--sn-danger-color, #ef4444) 60%, transparent);
|
|
21
|
-
display: none;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
&[type="join"] .preview-overlay {
|
|
25
|
-
display: block;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.preview-line {
|
|
29
|
-
position: absolute;
|
|
30
|
-
background: var(--layout-highlight, #888);
|
|
31
|
-
box-shadow: 0 0 8px var(--layout-highlight, #888);
|
|
32
|
-
display: none;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
&[type="split-h"] .preview-line,
|
|
36
|
-
&[type="split-v"] .preview-line {
|
|
37
|
-
display: block;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* Hidden attribute overrides */
|
|
41
|
-
.preview-overlay[hidden],
|
|
42
|
-
.preview-line[hidden] {
|
|
43
|
-
display: none !important;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
`;
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview LayoutPreview - Visual preview for split/join operations
|
|
3
|
-
* Shows where the new panel will be created or which panel will be removed.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import Symbiote from '@symbiotejs/symbiote';
|
|
7
|
-
import { template } from './LayoutPreview.tpl.js';
|
|
8
|
-
import { styles } from './LayoutPreview.css.js';
|
|
9
|
-
|
|
10
|
-
export class LayoutPreview extends Symbiote {
|
|
11
|
-
static isoMode = true;
|
|
12
|
-
|
|
13
|
-
init$ = {
|
|
14
|
-
// Preview type: 'split-h' | 'split-v' | 'join' | null
|
|
15
|
-
previewType: null,
|
|
16
|
-
|
|
17
|
-
// Target panel rect for positioning
|
|
18
|
-
targetRect: null,
|
|
19
|
-
|
|
20
|
-
// Preview visibility
|
|
21
|
-
visible: false,
|
|
22
|
-
|
|
23
|
-
// Computed styles
|
|
24
|
-
overlayStyle: '',
|
|
25
|
-
lineStyle: '',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
renderCallback() {
|
|
29
|
-
this.sub('previewType', (type) => {
|
|
30
|
-
if (type) {
|
|
31
|
-
this.setAttribute('type', type);
|
|
32
|
-
} else {
|
|
33
|
-
this.removeAttribute('type');
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Show split preview
|
|
40
|
-
* @param {'split-h' | 'split-v'} direction
|
|
41
|
-
* @param {DOMRect} panelRect
|
|
42
|
-
* @param {number} [ratio=0.5]
|
|
43
|
-
*/
|
|
44
|
-
showSplit(direction, panelRect, ratio = 0.5) {
|
|
45
|
-
this.$.previewType = direction;
|
|
46
|
-
this.$.visible = true;
|
|
47
|
-
|
|
48
|
-
if (direction === 'split-h') {
|
|
49
|
-
// Horizontal split - vertical line
|
|
50
|
-
const x = panelRect.left + panelRect.width * ratio;
|
|
51
|
-
this.$.lineStyle = `
|
|
52
|
-
left: ${x}px;
|
|
53
|
-
top: ${panelRect.top}px;
|
|
54
|
-
width: 4px;
|
|
55
|
-
height: ${panelRect.height}px;
|
|
56
|
-
`;
|
|
57
|
-
this.$.overlayStyle = '';
|
|
58
|
-
} else {
|
|
59
|
-
// Vertical split - horizontal line
|
|
60
|
-
const y = panelRect.top + panelRect.height * ratio;
|
|
61
|
-
this.$.lineStyle = `
|
|
62
|
-
left: ${panelRect.left}px;
|
|
63
|
-
top: ${y}px;
|
|
64
|
-
width: ${panelRect.width}px;
|
|
65
|
-
height: 4px;
|
|
66
|
-
`;
|
|
67
|
-
this.$.overlayStyle = '';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Show join preview (overlay on target panel)
|
|
73
|
-
* @param {DOMRect} targetRect - Panel that will be removed
|
|
74
|
-
*/
|
|
75
|
-
showJoin(targetRect) {
|
|
76
|
-
this.$.previewType = 'join';
|
|
77
|
-
this.$.visible = true;
|
|
78
|
-
|
|
79
|
-
this.$.overlayStyle = `
|
|
80
|
-
left: ${targetRect.left}px;
|
|
81
|
-
top: ${targetRect.top}px;
|
|
82
|
-
width: ${targetRect.width}px;
|
|
83
|
-
height: ${targetRect.height}px;
|
|
84
|
-
`;
|
|
85
|
-
this.$.lineStyle = '';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Hide preview
|
|
90
|
-
*/
|
|
91
|
-
hide() {
|
|
92
|
-
this.$.visible = false;
|
|
93
|
-
this.$.previewType = null;
|
|
94
|
-
this.$.overlayStyle = '';
|
|
95
|
-
this.$.lineStyle = '';
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
LayoutPreview.template = template;
|
|
100
|
-
LayoutPreview.rootStyles = styles;
|
|
101
|
-
|
|
102
|
-
LayoutPreview.reg('layout-preview');
|