@forgeax/app-shell 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dock.d.ts CHANGED
@@ -43,6 +43,32 @@ interface SerializedDockLayoutLike {
43
43
  * leaves and branches. The input snapshot is never mutated.
44
44
  */
45
45
  declare function pruneSerializedDockLayout<T extends SerializedDockLayoutLike>(layout: T, knownComponents: ReadonlySet<string>, allowedPanelIds?: ReadonlySet<string>): T | null;
46
+ type DockLayoutOrientation = 'HORIZONTAL' | 'VERTICAL';
47
+ type DockReopenDirection = 'left' | 'right' | 'above' | 'below' | 'within';
48
+ /** Structural shape shared by concrete serialized dock tree implementations. */
49
+ interface AuthoredDockNodeLike {
50
+ readonly type: 'leaf' | 'branch';
51
+ readonly data: unknown;
52
+ }
53
+ interface AuthoredDockLayoutLike {
54
+ readonly grid?: {
55
+ readonly orientation: DockLayoutOrientation;
56
+ readonly root?: AuthoredDockNodeLike;
57
+ };
58
+ }
59
+ type DesignedDockPanelPosition = {
60
+ readonly kind: 'relative';
61
+ readonly referencePanel: string;
62
+ readonly direction: DockReopenDirection;
63
+ } | {
64
+ readonly kind: 'edge';
65
+ readonly direction: Exclude<DockReopenDirection, 'within'>;
66
+ };
67
+ /**
68
+ * Derive a closed panel's authored seat against a panel that is still open.
69
+ * Returns undefined when the panel is absent or no live sibling can anchor it.
70
+ */
71
+ declare function designedDockPanelPosition(layout: AuthoredDockLayoutLike, panelId: string, isOpen: (id: string) => boolean): DesignedDockPanelPosition | undefined;
46
72
  type SideEdge = 'left' | 'right';
47
73
  interface RectLike {
48
74
  left: number;
@@ -80,4 +106,4 @@ declare function handleCrossInstanceDrop(event: CrossInstanceDropEvent, targetRe
80
106
  titleFor?: (panelId: string) => string | undefined;
81
107
  }): void;
82
108
 
83
- export { type CrossInstanceDropEvent, DOCK_REGIONS, type DockRegion, type DockRegionEntry, type DockviewApiLike, type PanelDescriptorLite, REGIONS, type RectLike, type Region, type SerializedDockLayoutLike, type SerializedDockPanelLike, type SideEdge, getDockRegions, getDockviewApi, handleCrossInstanceDrop, hasMountedPanelPlacement, isDockPanelVisible, isDockRegion, isOnSideEdge, nearerSideEdge, pruneSerializedDockLayout, registerDockRegion, registerDockviewApi, resolveRegion, trackDockPanelVisibility };
109
+ export { type AuthoredDockLayoutLike, type AuthoredDockNodeLike, type CrossInstanceDropEvent, DOCK_REGIONS, type DesignedDockPanelPosition, type DockLayoutOrientation, type DockRegion, type DockRegionEntry, type DockReopenDirection, type DockviewApiLike, type PanelDescriptorLite, REGIONS, type RectLike, type Region, type SerializedDockLayoutLike, type SerializedDockPanelLike, type SideEdge, designedDockPanelPosition, getDockRegions, getDockviewApi, handleCrossInstanceDrop, hasMountedPanelPlacement, isDockPanelVisible, isDockRegion, isOnSideEdge, nearerSideEdge, pruneSerializedDockLayout, registerDockRegion, registerDockviewApi, resolveRegion, trackDockPanelVisibility };
package/dist/dock.js CHANGED
@@ -84,6 +84,75 @@ function pruneSerializedDockLayout(layout, knownComponents, allowedPanelIds) {
84
84
  grid: layout.grid ? { ...layout.grid, root } : layout.grid
85
85
  };
86
86
  }
87
+ function authoredLeafViews(node) {
88
+ if (node.type !== "leaf" || !node.data || typeof node.data !== "object") return [];
89
+ const views = node.data.views;
90
+ return Array.isArray(views) ? views : [];
91
+ }
92
+ function authoredBranchChildren(node) {
93
+ return node.type === "branch" && Array.isArray(node.data) ? node.data : [];
94
+ }
95
+ function firstOpenAuthoredPanel(node, isOpen) {
96
+ if (node.type === "leaf") return authoredLeafViews(node).find(isOpen);
97
+ for (const child of authoredBranchChildren(node)) {
98
+ const match = firstOpenAuthoredPanel(child, isOpen);
99
+ if (match) return match;
100
+ }
101
+ return void 0;
102
+ }
103
+ function findAuthoredPanelPath(root, panelId) {
104
+ if (root.type === "leaf") {
105
+ return authoredLeafViews(root).includes(panelId) ? [root] : void 0;
106
+ }
107
+ for (const child of authoredBranchChildren(root)) {
108
+ const path = findAuthoredPanelPath(child, panelId);
109
+ if (path) return [root, ...path];
110
+ }
111
+ return void 0;
112
+ }
113
+ function authoredBranchOrientation(rootOrientation, depth) {
114
+ if (depth % 2 === 0) return rootOrientation;
115
+ return rootOrientation === "HORIZONTAL" ? "VERTICAL" : "HORIZONTAL";
116
+ }
117
+ function designedDockPanelPosition(layout, panelId, isOpen) {
118
+ const root = layout.grid?.root;
119
+ if (!root) return void 0;
120
+ const path = findAuthoredPanelPath(root, panelId);
121
+ if (!path) return void 0;
122
+ const leaf = path[path.length - 1];
123
+ const tabMate = authoredLeafViews(leaf).find((id) => id !== panelId && isOpen(id));
124
+ if (tabMate) return { kind: "relative", referencePanel: tabMate, direction: "within" };
125
+ if (path.length === 2 && path[0].type === "branch") {
126
+ const siblings = authoredBranchChildren(path[0]);
127
+ const index = siblings.indexOf(leaf);
128
+ const horizontal = layout.grid?.orientation === "HORIZONTAL";
129
+ if (index === 0) return { kind: "edge", direction: horizontal ? "left" : "above" };
130
+ if (index === siblings.length - 1) {
131
+ return { kind: "edge", direction: horizontal ? "right" : "below" };
132
+ }
133
+ }
134
+ for (let depth = path.length - 2; depth >= 0; depth--) {
135
+ const branch = path[depth];
136
+ if (branch.type !== "branch") continue;
137
+ const children = authoredBranchChildren(branch);
138
+ const index = children.indexOf(path[depth + 1]);
139
+ if (index < 0) continue;
140
+ const horizontal = authoredBranchOrientation(layout.grid.orientation, depth) === "HORIZONTAL";
141
+ for (let i = index + 1; i < children.length; i++) {
142
+ const referencePanel = firstOpenAuthoredPanel(children[i], isOpen);
143
+ if (referencePanel) {
144
+ return { kind: "relative", referencePanel, direction: horizontal ? "left" : "above" };
145
+ }
146
+ }
147
+ for (let i = index - 1; i >= 0; i--) {
148
+ const referencePanel = firstOpenAuthoredPanel(children[i], isOpen);
149
+ if (referencePanel) {
150
+ return { kind: "relative", referencePanel, direction: horizontal ? "right" : "below" };
151
+ }
152
+ }
153
+ }
154
+ return void 0;
155
+ }
87
156
  function isOnSideEdge(location) {
88
157
  return location.type === "edge" && (location.position === "left" || location.position === "right");
89
158
  }
@@ -138,6 +207,7 @@ function handleCrossInstanceDrop(event, targetRegion, moveTo, options) {
138
207
  export {
139
208
  DOCK_REGIONS,
140
209
  REGIONS,
210
+ designedDockPanelPosition,
141
211
  getDockRegions,
142
212
  getDockviewApi,
143
213
  handleCrossInstanceDrop,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/app-shell",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Generic Dock, Panel, Window, and Slot composition primitives",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",