@konitif/workbench 0.285.9 → 0.285.11

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/README.md CHANGED
@@ -14,6 +14,9 @@ npm install @konitif/workbench
14
14
  - Workspace, layout, panel and shell contracts.
15
15
  - Tool and widget admission, registries and hosting adapters.
16
16
  - Generic widget-zone visibility and placement-drop projection.
17
+ - Generic tabbed-region visibility coordination for grouped widgets.
18
+ - Atomic visibility normalization for internal tool docks sharing a region.
19
+ - Root Widget admission that preserves restored region state.
17
20
  - Runtime lifecycle, checkpoint, recovery and observability contracts.
18
21
  - Project preflight and repository-quality contracts.
19
22
  - Explicit workspace persistence, synchronization and surface ports.
@@ -0,0 +1,13 @@
1
+ import type { ShellRegionId, ShellState, ShellWidgetPlacement } from "../../domain/shell/model.js";
2
+ export interface RootShellWidgetAdmissionActions {
3
+ moveShellWidgetToRegion(regionId: ShellRegionId, widgetId: string, placement?: ShellWidgetPlacement): void;
4
+ activateShellWidget(regionId: ShellRegionId, widgetId: string): void;
5
+ setShellRegionVisible(regionId: ShellRegionId, isVisible: boolean): void;
6
+ setShellRegionOpen(regionId: ShellRegionId, isOpen: boolean): void;
7
+ }
8
+ export declare function isShellWidgetAlreadyPlaced(shell: ShellState, widgetId: string): boolean;
9
+ /**
10
+ * Admits one missing root Widget without allowing the placement operation to
11
+ * overwrite the region state restored from the Workspace.
12
+ */
13
+ export declare function admitShellWidgetPlacementPreservingRegionState(shell: ShellState, actions: RootShellWidgetAdmissionActions, regionId: ShellRegionId, widgetId: string, placement?: ShellWidgetPlacement): boolean;
@@ -0,0 +1,20 @@
1
+ export function isShellWidgetAlreadyPlaced(shell, widgetId) {
2
+ return Object.values(shell.regions).some((region) => region.widgetIds.includes(widgetId));
3
+ }
4
+ /**
5
+ * Admits one missing root Widget without allowing the placement operation to
6
+ * overwrite the region state restored from the Workspace.
7
+ */
8
+ export function admitShellWidgetPlacementPreservingRegionState(shell, actions, regionId, widgetId, placement = {}) {
9
+ if (isShellWidgetAlreadyPlaced(shell, widgetId)) {
10
+ return false;
11
+ }
12
+ const region = shell.regions[regionId];
13
+ actions.moveShellWidgetToRegion(regionId, widgetId, placement);
14
+ if (region.activeWidgetId) {
15
+ actions.activateShellWidget(regionId, region.activeWidgetId);
16
+ }
17
+ actions.setShellRegionVisible(regionId, region.isVisible);
18
+ actions.setShellRegionOpen(regionId, region.isOpen);
19
+ return true;
20
+ }
@@ -0,0 +1,14 @@
1
+ import type { ShellRegionState } from "../../domain/shell/model.js";
2
+ export type TabbedShellRegionVisibilityIntent = {
3
+ kind: 'widget';
4
+ } | {
5
+ kind: 'close-group';
6
+ } | {
7
+ kind: 'open-group';
8
+ revealWidgetIds: string[];
9
+ };
10
+ /**
11
+ * Projects a widget visibility request into the coordination required by a
12
+ * tabbed shell region. The host remains responsible for applying the intent.
13
+ */
14
+ export declare function resolveTabbedShellRegionVisibilityIntent(region: ShellRegionState, widgetId: string, isVisible: boolean): TabbedShellRegionVisibilityIntent;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Projects a widget visibility request into the coordination required by a
3
+ * tabbed shell region. The host remains responsible for applying the intent.
4
+ */
5
+ export function resolveTabbedShellRegionVisibilityIntent(region, widgetId, isVisible) {
6
+ if ((region.presentation ?? 'tabs') !== 'tabs'
7
+ || region.widgetIds.length < 2
8
+ || !region.widgetIds.includes(widgetId)) {
9
+ return { kind: 'widget' };
10
+ }
11
+ if (!isVisible) {
12
+ return { kind: 'close-group' };
13
+ }
14
+ return {
15
+ kind: 'open-group',
16
+ revealWidgetIds: region.widgetIds.filter((candidateId) => candidateId !== widgetId),
17
+ };
18
+ }
@@ -1,4 +1,4 @@
1
- import type { ShellRegionId, ShellRegionPresentation } from "../shell/model.js";
1
+ import type { ShellRegionId, ShellRegionPresentation, ShellState } from "../shell/model.js";
2
2
  import type { JsonObject } from "../shared/json.js";
3
3
  export type WorkbenchToolDockActionSide = 'top' | 'right' | 'bottom' | 'left';
4
4
  export interface WorkbenchToolDockVisibilityConfig {
@@ -6,6 +6,10 @@ export interface WorkbenchToolDockVisibilityConfig {
6
6
  legacyVisibleKey?: string | null;
7
7
  defaultVisible?: boolean;
8
8
  }
9
+ export interface WorkbenchGroupedToolDockConfig extends WorkbenchToolDockVisibilityConfig {
10
+ defaultRegionId: ShellRegionId;
11
+ rootWidgetId?: string | null;
12
+ }
9
13
  export interface WorkbenchToolDockRootConfig extends WorkbenchToolDockVisibilityConfig {
10
14
  commandId: string;
11
15
  widgetId: string;
@@ -17,6 +21,7 @@ export interface WorkbenchToolDockRootLocation {
17
21
  isOpen: boolean;
18
22
  activeWidgetId: string | null;
19
23
  presentation?: ShellRegionPresentation;
24
+ size?: number;
20
25
  }
21
26
  export declare function resolveWorkbenchToolDockSide(regionId: ShellRegionId | null | undefined): WorkbenchToolDockActionSide;
22
27
  export declare function readWorkbenchToolDockVisibility(state: unknown, config: WorkbenchToolDockVisibilityConfig): boolean;
@@ -25,6 +30,14 @@ export declare function resolveWorkbenchToolDockEffectiveVisibility(input: {
25
30
  internalVisible: boolean;
26
31
  widgetId: string;
27
32
  }): boolean;
33
+ export declare function resolveWorkbenchToolDockRootLocation(shellState: ShellState, widgetId: string): WorkbenchToolDockRootLocation | null;
28
34
  export declare function patchWorkbenchToolDockVisibilityState(state: unknown, input: WorkbenchToolDockVisibilityConfig & {
29
35
  isVisible: boolean;
30
36
  }): JsonObject;
37
+ /**
38
+ * Normalizes the single-dock visibility request emitted by a tabbed tool dock
39
+ * into one atomic state snapshot for every dock sharing the same region.
40
+ * Docks projected into a root shell region remain independently managed.
41
+ */
42
+ export declare function normalizeGroupedWorkbenchToolDockVisibility(currentState: JsonObject, requestedState: JsonObject, docks: readonly WorkbenchGroupedToolDockConfig[], individuallyManagedDockIds?: ReadonlySet<string>): JsonObject;
43
+ export declare function normalizeGroupedWorkbenchToolDockVisibilityForShellState(currentState: JsonObject, requestedState: JsonObject, docks: readonly WorkbenchGroupedToolDockConfig[], shellState: ShellState): JsonObject;
@@ -27,6 +27,23 @@ export function resolveWorkbenchToolDockEffectiveVisibility(input) {
27
27
  }
28
28
  return location.isVisible && location.isOpen && (location.presentation === 'stack' || location.activeWidgetId === input.widgetId);
29
29
  }
30
+ export function resolveWorkbenchToolDockRootLocation(shellState, widgetId) {
31
+ const regionIds = ['left', 'right', 'bottom'];
32
+ for (const regionId of regionIds) {
33
+ const region = shellState.regions[regionId];
34
+ if (region.widgetIds.includes(widgetId)) {
35
+ return {
36
+ regionId,
37
+ isVisible: region.isVisible && !(region.hiddenWidgetIds ?? []).includes(widgetId),
38
+ isOpen: region.isOpen,
39
+ activeWidgetId: region.activeWidgetId,
40
+ presentation: region.presentation ?? 'tabs',
41
+ size: region.size
42
+ };
43
+ }
44
+ }
45
+ return null;
46
+ }
30
47
  export function patchWorkbenchToolDockVisibilityState(state, input) {
31
48
  const currentState = isRecord(state) ? state : {};
32
49
  const dockContainers = isRecord(currentState.dockContainers) ? currentState.dockContainers : {};
@@ -47,6 +64,37 @@ export function patchWorkbenchToolDockVisibilityState(state, input) {
47
64
  }
48
65
  return nextState;
49
66
  }
67
+ /**
68
+ * Normalizes the single-dock visibility request emitted by a tabbed tool dock
69
+ * into one atomic state snapshot for every dock sharing the same region.
70
+ * Docks projected into a root shell region remain independently managed.
71
+ */
72
+ export function normalizeGroupedWorkbenchToolDockVisibility(currentState, requestedState, docks, individuallyManagedDockIds = new Set()) {
73
+ const changedDocks = docks.filter((dock) => readWorkbenchToolDockVisibility(currentState, dock) !==
74
+ readWorkbenchToolDockVisibility(requestedState, dock));
75
+ if (changedDocks.length !== 1) {
76
+ return requestedState;
77
+ }
78
+ const changedDock = changedDocks[0];
79
+ if (individuallyManagedDockIds.has(changedDock.dockId)) {
80
+ return requestedState;
81
+ }
82
+ const groupedDocks = docks.filter((dock) => dock.defaultRegionId === changedDock.defaultRegionId);
83
+ if (groupedDocks.length < 2) {
84
+ return requestedState;
85
+ }
86
+ const isVisible = readWorkbenchToolDockVisibility(requestedState, changedDock);
87
+ return groupedDocks.reduce((state, dock) => patchWorkbenchToolDockVisibilityState(state, {
88
+ ...dock,
89
+ isVisible
90
+ }), requestedState);
91
+ }
92
+ export function normalizeGroupedWorkbenchToolDockVisibilityForShellState(currentState, requestedState, docks, shellState) {
93
+ const rootManagedDockIds = new Set(docks.flatMap((dock) => dock.rootWidgetId && resolveWorkbenchToolDockRootLocation(shellState, dock.rootWidgetId)
94
+ ? [dock.dockId]
95
+ : []));
96
+ return normalizeGroupedWorkbenchToolDockVisibility(currentState, requestedState, docks, rootManagedDockIds);
97
+ }
50
98
  function isRecord(value) {
51
99
  return !!value && typeof value === 'object' && !Array.isArray(value);
52
100
  }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export * from "./boot/index.js";
2
2
  export * from "./application/launch/workbenchLaunchPolicy.js";
3
3
  export * from "./application/launch/catalogShareReference.js";
4
4
  export * from "./application/widgets/createWorkbenchWidgetAdapter.js";
5
+ export * from "./application/widgets/rootShellWidgetAdmission.js";
6
+ export * from "./application/widgets/tabbedShellRegionVisibility.js";
5
7
  export * from "./application/widgets/widgetZoneProjection.js";
6
8
  export * from "./application/tool/experienceToolSelection.js";
7
9
  export * from "./stage/index.js";
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@ export * from "./boot/index.js";
2
2
  export * from "./application/launch/workbenchLaunchPolicy.js";
3
3
  export * from "./application/launch/catalogShareReference.js";
4
4
  export * from "./application/widgets/createWorkbenchWidgetAdapter.js";
5
+ export * from "./application/widgets/rootShellWidgetAdmission.js";
6
+ export * from "./application/widgets/tabbedShellRegionVisibility.js";
5
7
  export * from "./application/widgets/widgetZoneProjection.js";
6
8
  export * from "./application/tool/experienceToolSelection.js";
7
9
  export * from "./stage/index.js";
@@ -1,3 +1,4 @@
1
+ export { admitShellWidgetPlacementPreservingRegionState, isShellWidgetAlreadyPlaced } from "./application/widgets/rootShellWidgetAdmission.js";
1
2
  export { setShellRegionArrangement, setShellRegionWidgetProportions, createShellState, setShellRegionVisible, setShellRegionOpen, setShellRegionSize, activateShellWidget, setShellRegionWidgetVisible, addShellWidgetToRegion, moveShellWidgetToRegion, removeShellWidgetFromRegion } from "./application/shell/state.js";
2
3
  export { collapseSplit } from "./application/workspace/collapseSplit.js";
3
4
  export { collapseSplitBoundary } from "./application/workspace/collapseSplitBoundary.js";
@@ -1,5 +1,6 @@
1
1
  // Explicit workspace contracts for state orchestration. No host adapters.
2
2
  // Reexports preserve the authority and identity of the existing implementations.
3
+ export { admitShellWidgetPlacementPreservingRegionState, isShellWidgetAlreadyPlaced } from "./application/widgets/rootShellWidgetAdmission.js";
3
4
  export { setShellRegionArrangement, setShellRegionWidgetProportions, createShellState, setShellRegionVisible, setShellRegionOpen, setShellRegionSize, activateShellWidget, setShellRegionWidgetVisible, addShellWidgetToRegion, moveShellWidgetToRegion, removeShellWidgetFromRegion } from "./application/shell/state.js";
4
5
  export { collapseSplit } from "./application/workspace/collapseSplit.js";
5
6
  export { collapseSplitBoundary } from "./application/workspace/collapseSplitBoundary.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@konitif/workbench",
3
3
  "license": "PolyForm-Noncommercial-1.0.0",
4
- "version": "0.285.9",
4
+ "version": "0.285.11",
5
5
  "description": "Workspace composition, docking, registries and hosting contracts for KONITIF.",
6
6
  "repository": {
7
7
  "type": "git",
@@ -109,7 +109,12 @@
109
109
  "createWorkbenchWidgetAdapter",
110
110
  "WorkbenchWidgetHosting",
111
111
  "projectWorkbenchWidgetZone",
112
- "WorkbenchWidgetZoneProjection"
112
+ "WorkbenchWidgetZoneProjection",
113
+ "resolveTabbedShellRegionVisibilityIntent",
114
+ "TabbedShellRegionVisibilityIntent",
115
+ "normalizeGroupedWorkbenchToolDockVisibility",
116
+ "WorkbenchGroupedToolDockConfig",
117
+ "admitShellWidgetPlacementPreservingRegionState"
113
118
  ]
114
119
  },
115
120
  {