@forgeax/app-shell 0.1.1 → 0.3.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 +65 -0
- package/dist/dock.js +93 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +19 -1
- package/dist/react.d.ts +11 -0
- package/dist/react.js +12 -0
- package/package.json +18 -3
package/dist/dock.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
declare const REGIONS: readonly ["DockShell", "AuxBar", "ChatDock", "StatusBar"];
|
|
2
|
+
type Region = typeof REGIONS[number];
|
|
3
|
+
declare const DOCK_REGIONS: readonly ["DockShell", "AuxBar", "ChatDock"];
|
|
4
|
+
type DockRegion = typeof DOCK_REGIONS[number];
|
|
5
|
+
declare function isDockRegion(value: string): value is DockRegion;
|
|
6
|
+
interface PanelDescriptorLite {
|
|
7
|
+
defaultRegion?: DockRegion;
|
|
8
|
+
}
|
|
9
|
+
declare function resolveRegion(id: string, descriptor: PanelDescriptorLite, overrides: Readonly<Record<string, DockRegion>>): DockRegion;
|
|
10
|
+
interface DockviewApiLike {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
getPanel(id: string): {
|
|
13
|
+
readonly api: {
|
|
14
|
+
close(): void;
|
|
15
|
+
};
|
|
16
|
+
} | undefined;
|
|
17
|
+
}
|
|
18
|
+
declare function registerDockviewApi(api: DockviewApiLike): () => void;
|
|
19
|
+
declare function getDockviewApi(viewId: string): DockviewApiLike | undefined;
|
|
20
|
+
interface DockRegionEntry {
|
|
21
|
+
readonly viewId: string;
|
|
22
|
+
readonly region: string;
|
|
23
|
+
readonly api: unknown;
|
|
24
|
+
readonly wrapEl: HTMLElement;
|
|
25
|
+
}
|
|
26
|
+
declare function registerDockRegion(entry: DockRegionEntry): () => void;
|
|
27
|
+
declare function getDockRegions(): DockRegionEntry[];
|
|
28
|
+
type SideEdge = 'left' | 'right';
|
|
29
|
+
interface RectLike {
|
|
30
|
+
left: number;
|
|
31
|
+
right: number;
|
|
32
|
+
}
|
|
33
|
+
declare function isOnSideEdge(location: {
|
|
34
|
+
type: string;
|
|
35
|
+
position?: string;
|
|
36
|
+
}): boolean;
|
|
37
|
+
declare function nearerSideEdge(panel: RectLike, shell: RectLike): SideEdge;
|
|
38
|
+
type DropPosition = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
39
|
+
type Direction = 'left' | 'right' | 'above' | 'below' | 'within';
|
|
40
|
+
interface AddPanelPosition {
|
|
41
|
+
referenceGroup?: unknown;
|
|
42
|
+
direction?: Direction;
|
|
43
|
+
}
|
|
44
|
+
interface CrossInstanceDropEvent {
|
|
45
|
+
readonly api: DockviewApiLike & {
|
|
46
|
+
addPanel(options: {
|
|
47
|
+
id: string;
|
|
48
|
+
component: string;
|
|
49
|
+
title?: string;
|
|
50
|
+
position?: AddPanelPosition;
|
|
51
|
+
}): unknown;
|
|
52
|
+
};
|
|
53
|
+
readonly position?: DropPosition;
|
|
54
|
+
readonly group?: unknown;
|
|
55
|
+
getData(): {
|
|
56
|
+
readonly viewId: string;
|
|
57
|
+
readonly panelId: string | null;
|
|
58
|
+
} | undefined;
|
|
59
|
+
}
|
|
60
|
+
declare function handleCrossInstanceDrop(event: CrossInstanceDropEvent, targetRegion: DockRegion, moveTo: (panelId: string, region: DockRegion) => void, options?: {
|
|
61
|
+
componentFor?: (panelId: string) => string;
|
|
62
|
+
titleFor?: (panelId: string) => string | undefined;
|
|
63
|
+
}): void;
|
|
64
|
+
|
|
65
|
+
export { type CrossInstanceDropEvent, DOCK_REGIONS, type DockRegion, type DockRegionEntry, type DockviewApiLike, type PanelDescriptorLite, REGIONS, type RectLike, type Region, type SideEdge, getDockRegions, getDockviewApi, handleCrossInstanceDrop, isDockRegion, isOnSideEdge, nearerSideEdge, registerDockRegion, registerDockviewApi, resolveRegion };
|
package/dist/dock.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// src/dock.ts
|
|
2
|
+
var REGIONS = ["DockShell", "AuxBar", "ChatDock", "StatusBar"];
|
|
3
|
+
var DOCK_REGIONS = ["DockShell", "AuxBar", "ChatDock"];
|
|
4
|
+
function isDockRegion(value) {
|
|
5
|
+
return DOCK_REGIONS.includes(value);
|
|
6
|
+
}
|
|
7
|
+
function resolveRegion(id, descriptor, overrides) {
|
|
8
|
+
return overrides[id] ?? descriptor.defaultRegion ?? "DockShell";
|
|
9
|
+
}
|
|
10
|
+
var dockviewApis = /* @__PURE__ */ new Map();
|
|
11
|
+
function registerDockviewApi(api) {
|
|
12
|
+
dockviewApis.set(api.id, api);
|
|
13
|
+
return () => {
|
|
14
|
+
if (dockviewApis.get(api.id) === api) dockviewApis.delete(api.id);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function getDockviewApi(viewId) {
|
|
18
|
+
return dockviewApis.get(viewId);
|
|
19
|
+
}
|
|
20
|
+
var dockRegions = /* @__PURE__ */ new Map();
|
|
21
|
+
function registerDockRegion(entry) {
|
|
22
|
+
dockRegions.set(entry.viewId, entry);
|
|
23
|
+
return () => {
|
|
24
|
+
if (dockRegions.get(entry.viewId) === entry) dockRegions.delete(entry.viewId);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function getDockRegions() {
|
|
28
|
+
return [...dockRegions.values()];
|
|
29
|
+
}
|
|
30
|
+
function isOnSideEdge(location) {
|
|
31
|
+
return location.type === "edge" && (location.position === "left" || location.position === "right");
|
|
32
|
+
}
|
|
33
|
+
function nearerSideEdge(panel, shell) {
|
|
34
|
+
const middle = (panel.left + panel.right) / 2;
|
|
35
|
+
return middle - shell.left <= shell.right - middle ? "left" : "right";
|
|
36
|
+
}
|
|
37
|
+
function toDirection(position) {
|
|
38
|
+
switch (position) {
|
|
39
|
+
case "top":
|
|
40
|
+
return "above";
|
|
41
|
+
case "bottom":
|
|
42
|
+
return "below";
|
|
43
|
+
case "left":
|
|
44
|
+
return "left";
|
|
45
|
+
case "right":
|
|
46
|
+
return "right";
|
|
47
|
+
case "center":
|
|
48
|
+
return "within";
|
|
49
|
+
default:
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function handleCrossInstanceDrop(event, targetRegion, moveTo, options) {
|
|
54
|
+
const transfer = event.getData();
|
|
55
|
+
if (!transfer?.panelId || transfer.viewId === event.api.id) return;
|
|
56
|
+
const sourceApi = getDockviewApi(transfer.viewId);
|
|
57
|
+
if (sourceApi) {
|
|
58
|
+
try {
|
|
59
|
+
sourceApi.getPanel(transfer.panelId)?.api.close();
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const direction = toDirection(event.position);
|
|
64
|
+
let position;
|
|
65
|
+
if (event.group && direction) {
|
|
66
|
+
position = { referenceGroup: event.group, direction };
|
|
67
|
+
} else if (direction && direction !== "within") {
|
|
68
|
+
position = { direction };
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
event.api.addPanel({
|
|
72
|
+
id: transfer.panelId,
|
|
73
|
+
component: options?.componentFor?.(transfer.panelId) ?? transfer.panelId,
|
|
74
|
+
title: options?.titleFor?.(transfer.panelId),
|
|
75
|
+
...position ? { position } : {}
|
|
76
|
+
});
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
moveTo(transfer.panelId, targetRegion);
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
DOCK_REGIONS,
|
|
83
|
+
REGIONS,
|
|
84
|
+
getDockRegions,
|
|
85
|
+
getDockviewApi,
|
|
86
|
+
handleCrossInstanceDrop,
|
|
87
|
+
isDockRegion,
|
|
88
|
+
isOnSideEdge,
|
|
89
|
+
nearerSideEdge,
|
|
90
|
+
registerDockRegion,
|
|
91
|
+
registerDockviewApi,
|
|
92
|
+
resolveRegion
|
|
93
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -15,5 +15,14 @@ declare class AppShellRegistry {
|
|
|
15
15
|
declare function createShellContribution(input: Omit<ShellContribution, 'contribution'> & {
|
|
16
16
|
contribution: ContributionDeclaration;
|
|
17
17
|
}): ShellContribution;
|
|
18
|
+
type ShellSnapshotPatch<T extends Record<string, unknown>> = {
|
|
19
|
+
readonly [K in keyof T]?: T[K] extends readonly unknown[] ? T[K] : T[K] extends Record<string, unknown> ? Partial<T[K]> : T[K];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Folds ordered shell contributions into an immutable derived snapshot.
|
|
23
|
+
* Object-valued fields merge one level; arrays and scalar values replace the
|
|
24
|
+
* previous value. Undefined fields do not contribute.
|
|
25
|
+
*/
|
|
26
|
+
declare function deriveShellSnapshot<T extends Record<string, unknown>>(base: T, patches: ReadonlyArray<ShellSnapshotPatch<T>>): T;
|
|
18
27
|
|
|
19
|
-
export { AppShellRegistry, type ShellContribution, type ShellSlot, createShellContribution };
|
|
28
|
+
export { AppShellRegistry, type ShellContribution, type ShellSlot, type ShellSnapshotPatch, createShellContribution, deriveShellSnapshot };
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,25 @@ var AppShellRegistry = class {
|
|
|
15
15
|
function createShellContribution(input) {
|
|
16
16
|
return { ...input };
|
|
17
17
|
}
|
|
18
|
+
function deriveShellSnapshot(base, patches) {
|
|
19
|
+
const output = { ...base };
|
|
20
|
+
for (const patch of patches) {
|
|
21
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
22
|
+
if (value === void 0) continue;
|
|
23
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
24
|
+
output[key] = {
|
|
25
|
+
...output[key],
|
|
26
|
+
...value
|
|
27
|
+
};
|
|
28
|
+
} else {
|
|
29
|
+
output[key] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return output;
|
|
34
|
+
}
|
|
18
35
|
export {
|
|
19
36
|
AppShellRegistry,
|
|
20
|
-
createShellContribution
|
|
37
|
+
createShellContribution,
|
|
38
|
+
deriveShellSnapshot
|
|
21
39
|
};
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
type ShellSlotElement = 'aside' | 'div' | 'main' | 'section';
|
|
4
|
+
interface ShellSlotProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
as?: ShellSlotElement;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
/** Structural shell marker that preserves the caller's semantic element. */
|
|
9
|
+
declare function ShellSlot({ as, name, ...props }: ShellSlotProps): ReactElement;
|
|
10
|
+
|
|
11
|
+
export { ShellSlot, type ShellSlotElement, type ShellSlotProps };
|
package/dist/react.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/app-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Generic Dock, Panel, Window, and Slot composition primitives",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -12,20 +12,35 @@
|
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
14
|
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./dock": {
|
|
17
|
+
"types": "./dist/dock.d.ts",
|
|
18
|
+
"import": "./dist/dock.js"
|
|
19
|
+
},
|
|
20
|
+
"./react": {
|
|
21
|
+
"types": "./dist/react.d.ts",
|
|
22
|
+
"import": "./dist/react.js"
|
|
15
23
|
}
|
|
16
24
|
},
|
|
17
25
|
"scripts": {
|
|
18
26
|
"typecheck": "tsc --noEmit",
|
|
19
|
-
"test": "bun test test
|
|
20
|
-
"build": "tsup src/index.ts --format esm --dts --outDir dist",
|
|
27
|
+
"test": "bun test test",
|
|
28
|
+
"build": "tsup src/index.ts src/dock.ts src/react.tsx --format esm --dts --outDir dist",
|
|
21
29
|
"check": "bun run typecheck && bun run test && bun run build",
|
|
22
30
|
"release:preflight": "bun run scripts/release-preflight.ts"
|
|
23
31
|
},
|
|
24
32
|
"dependencies": {
|
|
25
33
|
"@forgeax/extension-contracts": "^0.1.0"
|
|
26
34
|
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"react": "^19.0.0"
|
|
37
|
+
},
|
|
27
38
|
"devDependencies": {
|
|
39
|
+
"@types/react": "^19.0.0",
|
|
40
|
+
"@types/react-dom": "^19.0.0",
|
|
28
41
|
"bun-types": "^1.3.14",
|
|
42
|
+
"react": "^19.0.0",
|
|
43
|
+
"react-dom": "^19.0.0",
|
|
29
44
|
"tsup": "^8.5.0",
|
|
30
45
|
"typescript": "^5.9.2"
|
|
31
46
|
},
|