@konitif/workbench 0.285.8 → 0.285.10

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
@@ -13,6 +13,10 @@ npm install @konitif/workbench
13
13
 
14
14
  - Workspace, layout, panel and shell contracts.
15
15
  - Tool and widget admission, registries and hosting adapters.
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.
16
20
  - Runtime lifecycle, checkpoint, recovery and observability contracts.
17
21
  - Project preflight and repository-quality contracts.
18
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
+ }
@@ -0,0 +1,15 @@
1
+ export type WorkbenchWidgetZoneProjectionReason = 'closed' | 'visible-content' | 'empty-edit-drop-target' | 'empty-runtime';
2
+ export interface WorkbenchWidgetZoneProjection {
3
+ visible: boolean;
4
+ acceptsPlacementDrop: boolean;
5
+ reason: WorkbenchWidgetZoneProjectionReason;
6
+ }
7
+ /**
8
+ * Projects an authored widget-zone state into host-facing visibility and drop
9
+ * affordances without owning either the zone content or its renderer.
10
+ */
11
+ export declare function projectWorkbenchWidgetZone(input: {
12
+ containerOpen: boolean;
13
+ visiblePlacementCount: number;
14
+ layoutEditingEnabled: boolean;
15
+ }): WorkbenchWidgetZoneProjection;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Projects an authored widget-zone state into host-facing visibility and drop
3
+ * affordances without owning either the zone content or its renderer.
4
+ */
5
+ export function projectWorkbenchWidgetZone(input) {
6
+ if (!input.containerOpen) {
7
+ return { visible: false, acceptsPlacementDrop: false, reason: 'closed' };
8
+ }
9
+ if (input.visiblePlacementCount > 0) {
10
+ return {
11
+ visible: true,
12
+ acceptsPlacementDrop: input.layoutEditingEnabled,
13
+ reason: 'visible-content'
14
+ };
15
+ }
16
+ if (input.layoutEditingEnabled) {
17
+ return { visible: true, acceptsPlacementDrop: true, reason: 'empty-edit-drop-target' };
18
+ }
19
+ return { visible: false, acceptsPlacementDrop: false, reason: 'empty-runtime' };
20
+ }
@@ -6,6 +6,9 @@ export interface WorkbenchToolDockVisibilityConfig {
6
6
  legacyVisibleKey?: string | null;
7
7
  defaultVisible?: boolean;
8
8
  }
9
+ export interface WorkbenchGroupedToolDockConfig extends WorkbenchToolDockVisibilityConfig {
10
+ defaultRegionId: ShellRegionId;
11
+ }
9
12
  export interface WorkbenchToolDockRootConfig extends WorkbenchToolDockVisibilityConfig {
10
13
  commandId: string;
11
14
  widgetId: string;
@@ -28,3 +31,9 @@ export declare function resolveWorkbenchToolDockEffectiveVisibility(input: {
28
31
  export declare function patchWorkbenchToolDockVisibilityState(state: unknown, input: WorkbenchToolDockVisibilityConfig & {
29
32
  isVisible: boolean;
30
33
  }): JsonObject;
34
+ /**
35
+ * Normalizes the single-dock visibility request emitted by a tabbed tool dock
36
+ * into one atomic state snapshot for every dock sharing the same region.
37
+ * Docks projected into a root shell region remain independently managed.
38
+ */
39
+ export declare function normalizeGroupedWorkbenchToolDockVisibility(currentState: JsonObject, requestedState: JsonObject, docks: readonly WorkbenchGroupedToolDockConfig[], individuallyManagedDockIds?: ReadonlySet<string>): JsonObject;
@@ -47,6 +47,31 @@ export function patchWorkbenchToolDockVisibilityState(state, input) {
47
47
  }
48
48
  return nextState;
49
49
  }
50
+ /**
51
+ * Normalizes the single-dock visibility request emitted by a tabbed tool dock
52
+ * into one atomic state snapshot for every dock sharing the same region.
53
+ * Docks projected into a root shell region remain independently managed.
54
+ */
55
+ export function normalizeGroupedWorkbenchToolDockVisibility(currentState, requestedState, docks, individuallyManagedDockIds = new Set()) {
56
+ const changedDocks = docks.filter((dock) => readWorkbenchToolDockVisibility(currentState, dock) !==
57
+ readWorkbenchToolDockVisibility(requestedState, dock));
58
+ if (changedDocks.length !== 1) {
59
+ return requestedState;
60
+ }
61
+ const changedDock = changedDocks[0];
62
+ if (individuallyManagedDockIds.has(changedDock.dockId)) {
63
+ return requestedState;
64
+ }
65
+ const groupedDocks = docks.filter((dock) => dock.defaultRegionId === changedDock.defaultRegionId);
66
+ if (groupedDocks.length < 2) {
67
+ return requestedState;
68
+ }
69
+ const isVisible = readWorkbenchToolDockVisibility(requestedState, changedDock);
70
+ return groupedDocks.reduce((state, dock) => patchWorkbenchToolDockVisibilityState(state, {
71
+ ...dock,
72
+ isVisible
73
+ }), requestedState);
74
+ }
50
75
  function isRecord(value) {
51
76
  return !!value && typeof value === 'object' && !Array.isArray(value);
52
77
  }
package/dist/index.d.ts CHANGED
@@ -2,6 +2,9 @@ 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";
7
+ export * from "./application/widgets/widgetZoneProjection.js";
5
8
  export * from "./application/tool/experienceToolSelection.js";
6
9
  export * from "./stage/index.js";
7
10
  export * from "./application/shell/state.js";
package/dist/index.js CHANGED
@@ -2,6 +2,9 @@ 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";
7
+ export * from "./application/widgets/widgetZoneProjection.js";
5
8
  export * from "./application/tool/experienceToolSelection.js";
6
9
  export * from "./stage/index.js";
7
10
  export * from "./application/shell/state.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.8",
4
+ "version": "0.285.10",
5
5
  "description": "Workspace composition, docking, registries and hosting contracts for KONITIF.",
6
6
  "repository": {
7
7
  "type": "git",
@@ -107,7 +107,14 @@
107
107
  ],
108
108
  "symbolNames": [
109
109
  "createWorkbenchWidgetAdapter",
110
- "WorkbenchWidgetHosting"
110
+ "WorkbenchWidgetHosting",
111
+ "projectWorkbenchWidgetZone",
112
+ "WorkbenchWidgetZoneProjection",
113
+ "resolveTabbedShellRegionVisibilityIntent",
114
+ "TabbedShellRegionVisibilityIntent",
115
+ "normalizeGroupedWorkbenchToolDockVisibility",
116
+ "WorkbenchGroupedToolDockConfig",
117
+ "admitShellWidgetPlacementPreservingRegionState"
111
118
  ]
112
119
  },
113
120
  {