@openfin/core 31.74.27 → 31.74.29

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.
Files changed (28) hide show
  1. package/package.json +1 -1
  2. package/src/OpenFin.d.ts +20 -2
  3. package/src/api/platform/Instance.d.ts +1 -1
  4. package/src/api/platform/Instance.js +1 -1
  5. package/src/api/platform/layout/Factory.js +10 -1
  6. package/src/api/platform/layout/Instance.d.ts +6 -0
  7. package/src/api/platform/layout/Instance.js +26 -1
  8. package/src/api/platform/layout/controllers/layout-content-cache.d.ts +9 -0
  9. package/src/api/platform/layout/controllers/layout-content-cache.js +54 -0
  10. package/src/api/platform/layout/controllers/layout-entities-controller.d.ts +116 -0
  11. package/src/api/platform/layout/controllers/layout-entities-controller.js +256 -0
  12. package/src/api/platform/layout/entities/layout-entities.d.ts +134 -0
  13. package/src/api/platform/layout/entities/layout-entities.js +204 -0
  14. package/src/api/platform/layout/entities/shapes.d.ts +6 -0
  15. package/src/api/platform/layout/entities/shapes.js +2 -0
  16. package/src/api/platform/layout/layout.constants.d.ts +1 -0
  17. package/src/api/platform/layout/layout.constants.js +4 -0
  18. package/src/api/platform/layout/shapes.d.ts +3 -0
  19. package/src/api/platform/layout/utils/layout-traversal.d.ts +3 -0
  20. package/src/api/platform/layout/utils/layout-traversal.js +65 -0
  21. package/src/api/view/Instance.d.ts +8 -2
  22. package/src/api/view/Instance.js +37 -4
  23. package/src/util/channel-api-relay.d.ts +13 -0
  24. package/src/util/channel-api-relay.js +37 -0
  25. package/src/util/lazy.d.ts +16 -0
  26. package/src/util/lazy.js +26 -0
  27. package/src/util/reversible-map.d.ts +11 -0
  28. package/src/util/reversible-map.js +49 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfin/core",
3
- "version": "31.74.27",
3
+ "version": "31.74.29",
4
4
  "license": "SEE LICENSE IN LICENSE.MD",
5
5
  "main": "./src/mock.js",
6
6
  "types": "./src/mock.d.ts",
package/src/OpenFin.d.ts CHANGED
@@ -10,12 +10,14 @@ import type { ChannelProvider } from './api/interappbus/channel/provider';
10
10
  import type { InteropBroker, InteropClient } from './api/interop';
11
11
  import type { Platform } from './api/platform';
12
12
  import type { Layout } from './api/platform/layout';
13
+ import type { ColumnOrRow, TabStack } from './api/platform/layout/entities/layout-entities';
13
14
  import { PlatformProvider } from './api/platform/provider';
14
15
  import { SnapshotSource } from './api/snapshot-source';
15
16
  import type { View } from './api/view';
16
17
  import { _Window } from './api/window';
17
18
  export type Fin<MeType extends EntityType = 'window' | 'view'> = FinApi<MeType>;
18
- export type { Application, ExternalApplication, _Frame as Frame, ChannelClient, ChannelProvider, Platform, Layout, View, _Window as Window, InteropClient, InteropBroker, SnapshotSource };
19
+ export type { Application, ExternalApplication, _Frame as Frame, ChannelClient, ChannelProvider, Platform, Layout, View, ColumnOrRow, TabStack, _Window as Window, InteropClient, InteropBroker, SnapshotSource };
20
+ export type { LayoutEntityDefinition, LayoutEntityTypes, LayoutPosition } from './api/platform/layout/entities/shapes';
19
21
  export type WebContent = View | _Window;
20
22
  export type { PlatformProvider };
21
23
  export type ApplicationIdentity = {
@@ -1330,6 +1332,22 @@ export type ApplySnapshotPayload = {
1330
1332
  */
1331
1333
  options?: ApplySnapshotOptions;
1332
1334
  };
1335
+ export type AddViewToStackOptions = {
1336
+ /**
1337
+ * Optional index within the stack to insert the view. Defaults to 0
1338
+ */
1339
+ index?: number;
1340
+ };
1341
+ export type CreateViewTarget = Identity & {
1342
+ /**
1343
+ * If specified, view creation will not attach to a window and caller must
1344
+ * insert the view into the layout explicitly
1345
+ */
1346
+ location?: {
1347
+ id: string;
1348
+ index?: number;
1349
+ };
1350
+ };
1333
1351
  export type CreateViewPayload = {
1334
1352
  /**
1335
1353
  * Options for the view to be added.
@@ -1338,7 +1356,7 @@ export type CreateViewPayload = {
1338
1356
  /**
1339
1357
  * Window the view will be added to. If no target is provided, a new window will be created.
1340
1358
  */
1341
- target?: Identity;
1359
+ target?: CreateViewTarget;
1342
1360
  targetView?: Identity;
1343
1361
  };
1344
1362
  export type ReplaceViewPayload = {
@@ -27,7 +27,7 @@ export declare class Platform extends EmitterBase<OpenFin.PlatformEvent> {
27
27
  * @return { Promise<View> }
28
28
  * @tutorial Platform.createView
29
29
  */
30
- createView(viewOptions: OpenFin.PlatformViewCreationOptions, target?: OpenFin.Identity, targetView?: OpenFin.Identity): Promise<View>;
30
+ createView(viewOptions: OpenFin.PlatformViewCreationOptions, target?: OpenFin.CreateViewTarget, targetView?: OpenFin.Identity): Promise<View>;
31
31
  /**
32
32
  * Creates a new Window.
33
33
  * @param { Window~options } options Window creation options
@@ -78,7 +78,7 @@ class Platform extends base_1.EmitterBase {
78
78
  const response = await client.dispatch('create-view', {
79
79
  target,
80
80
  opts: viewOptions,
81
- targetView
81
+ targetView,
82
82
  });
83
83
  if (!response || (0, validate_1.validateIdentity)(response.identity)) {
84
84
  throw new Error(`When overwriting the createView call, please return an object that has a valid 'identity' property: ${JSON.stringify(response)}`);
@@ -19,6 +19,10 @@ const Instance_1 = require("./Instance");
19
19
  const base_1 = require("../../base");
20
20
  const splitter_controller_1 = require("./controllers/splitter-controller");
21
21
  const view_overlay_1 = require("./utils/view-overlay");
22
+ const api_exposer_1 = require("../../api-exposer");
23
+ const layout_entities_controller_1 = require("./controllers/layout-entities-controller");
24
+ const layout_constants_1 = require("./layout.constants");
25
+ const layout_content_cache_1 = require("./controllers/layout-content-cache");
22
26
  /**
23
27
  * @PORTED
24
28
  * InitLayoutOptions interface
@@ -113,7 +117,8 @@ class LayoutModule extends base_1.Base {
113
117
  const viewOverlay = new view_overlay_1.ViewOverlay(this.wire);
114
118
  const splitterController = new splitter_controller_1.SplitterController(viewOverlay);
115
119
  const tabDragController = new tab_drag_controller_1.TabDragController(viewOverlay);
116
- __classPrivateFieldSet(this, _LayoutModule_layoutManager, new ManagerConstructor(splitterController, tabDragController), "f");
120
+ const contentItemCache = new layout_content_cache_1.LayoutContentCache();
121
+ __classPrivateFieldSet(this, _LayoutModule_layoutManager, new ManagerConstructor(splitterController, tabDragController, contentItemCache), "f");
117
122
  // @ts-expect-error - layout warning here for backwards compatibility, can remove layout check in .52
118
123
  let { layout, containerId } = options;
119
124
  if (layout) {
@@ -128,6 +133,10 @@ class LayoutModule extends base_1.Base {
128
133
  // pull createChannelConnection out of LayoutManager and setup channel connections here using layoutmanager instance methods?
129
134
  await __classPrivateFieldGet(this, _LayoutModule_layoutManager, "f").initManager();
130
135
  await __classPrivateFieldGet(this, _LayoutModule_layoutManager, "f").createLayout(layout, container);
136
+ const { client, ofWindow } = ManagerConstructor.getClientAndWindow(__classPrivateFieldGet(this, _LayoutModule_layoutManager, "f"));
137
+ // expose LayoutEntitiesController instance for API consumption
138
+ const channelStrategy = new api_exposer_1.ChannelsExposer(client);
139
+ await new api_exposer_1.ApiExposer(channelStrategy).exposeInstance(new layout_entities_controller_1.LayoutEntitiesController(__classPrivateFieldGet(this, _LayoutModule_layoutManager, "f"), ofWindow.identity.uuid, contentItemCache), { id: layout_constants_1.LAYOUT_CONTROLLER_ID });
131
140
  // Adding this to the returned instance undocumented/typed for Browser.
132
141
  return Object.assign(this.getCurrentSync(), { layoutManager: __classPrivateFieldGet(this, _LayoutModule_layoutManager, "f") });
133
142
  };
@@ -8,6 +8,7 @@ type PresetLayoutOptions = OpenFin.PresetLayoutOptions;
8
8
  * @lends Platform#Layout
9
9
  */
10
10
  export declare class Layout extends Base {
11
+ #private;
11
12
  init: (options?: InitLayoutOptions) => Promise<Layout>;
12
13
  identity: Identity;
13
14
  private platform;
@@ -19,6 +20,11 @@ export declare class Layout extends Base {
19
20
  * @tutorial Layout.getConfig
20
21
  */
21
22
  getConfig(): Promise<any>;
23
+ /**
24
+ * Retrieves the top level content item of the layout.
25
+ * @return {Promise<TabStack | ColumnOrRow>}
26
+ */
27
+ getRootItem(): Promise<OpenFin.ColumnOrRow | OpenFin.TabStack>;
22
28
  /**
23
29
  * Replaces a Platform window's layout with a new layout. Any views that were in the old layout but not the new layout
24
30
  * will be destroyed.
@@ -1,9 +1,18 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _Layout_layoutClient;
2
8
  Object.defineProperty(exports, "__esModule", { value: true });
3
9
  exports.Layout = void 0;
10
+ const lazy_1 = require("../../../util/lazy");
4
11
  const validate_1 = require("../../../util/validate");
5
- const common_utils_1 = require("../common-utils");
6
12
  const base_1 = require("../../base");
13
+ const common_utils_1 = require("../common-utils");
14
+ const layout_entities_1 = require("./entities/layout-entities");
15
+ const layout_constants_1 = require("./layout.constants");
7
16
  /**
8
17
  * @lends Platform#Layout
9
18
  */
@@ -11,6 +20,12 @@ class Layout extends base_1.Base {
11
20
  // eslint-disable-next-line no-shadow
12
21
  constructor(identity, wire) {
13
22
  super(wire);
23
+ /**
24
+ * @internal
25
+ * Lazily constructed {@link LayoutEntitiesClient} bound to this platform's client and identity
26
+ * The client is for {@link LayoutEntitiesController}
27
+ */
28
+ _Layout_layoutClient.set(this, new lazy_1.Lazy(async () => layout_entities_1.LayoutNode.newLayoutEntitiesClient(await this.platform.getClient(), layout_constants_1.LAYOUT_CONTROLLER_ID, this.identity)));
14
29
  /**
15
30
  * Replaces a Platform window's layout with a new layout. Any views that were in the old layout but not the new layout
16
31
  * will be destroyed.
@@ -94,5 +109,15 @@ class Layout extends base_1.Base {
94
109
  target: this.identity
95
110
  });
96
111
  }
112
+ /**
113
+ * Retrieves the top level content item of the layout.
114
+ * @return {Promise<TabStack | ColumnOrRow>}
115
+ */
116
+ async getRootItem() {
117
+ const client = await __classPrivateFieldGet(this, _Layout_layoutClient, "f").getValue();
118
+ const root = await client.getRoot();
119
+ return layout_entities_1.LayoutNode.getEntity(root, client);
120
+ }
97
121
  }
98
122
  exports.Layout = Layout;
123
+ _Layout_layoutClient = new WeakMap();
@@ -0,0 +1,9 @@
1
+ export declare class LayoutContentCache {
2
+ private contentItemCache;
3
+ private contentItemCacheId;
4
+ private createCacheKey;
5
+ hasKey: (id: string) => boolean;
6
+ getItemOrUndefined: (id: string) => GoldenLayout.ContentItem | undefined;
7
+ getContentItemOrThrow: (id: string, expectedType?: string[]) => GoldenLayout.ContentItem;
8
+ getOrCreateEntityId: (contentItem: GoldenLayout.ContentItem) => string;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LayoutContentCache = void 0;
4
+ const reversible_map_1 = require("../../../../util/reversible-map");
5
+ class LayoutContentCache {
6
+ constructor() {
7
+ // ContentItems currently do not have a unique id, this helps us to lookup items by value
8
+ this.contentItemCache = new reversible_map_1.ReversibleMap();
9
+ this.contentItemCacheId = 0;
10
+ this.createCacheKey = () => {
11
+ const key = `entity-${this.contentItemCacheId.toString()}`;
12
+ this.contentItemCacheId += 1;
13
+ return key;
14
+ };
15
+ this.hasKey = (id) => {
16
+ return this.contentItemCache.hasKey(id);
17
+ };
18
+ this.getItemOrUndefined = (id) => {
19
+ try {
20
+ return this.getContentItemOrThrow(id);
21
+ }
22
+ catch (error) {
23
+ return undefined;
24
+ }
25
+ };
26
+ this.getContentItemOrThrow = (id, expectedType) => {
27
+ if (!this.contentItemCache.hasKey(id)) {
28
+ throw new Error('Layout component has been destroyed or detached from the current layout.');
29
+ }
30
+ const contentItem = this.contentItemCache.getValue(id);
31
+ if (expectedType && !expectedType.includes(contentItem.type)) {
32
+ throw new Error(`Layout item is not the expected type. Expected ${expectedType.join(', ')}, got ${contentItem.type}.`);
33
+ }
34
+ return contentItem;
35
+ };
36
+ this.getOrCreateEntityId = (contentItem) => {
37
+ if (this.contentItemCache.hasValue(contentItem)) {
38
+ return this.contentItemCache.getKey(contentItem);
39
+ }
40
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
41
+ const onItemDestroyed = ({ origin, ...rest }) => {
42
+ if (origin === contentItem) {
43
+ this.contentItemCache.deleteValue(contentItem);
44
+ contentItem.unbind('itemDestroyed', onItemDestroyed);
45
+ }
46
+ };
47
+ contentItem.on('itemDestroyed', onItemDestroyed);
48
+ const key = this.createCacheKey();
49
+ this.contentItemCache.setUnique(key, contentItem);
50
+ return key;
51
+ };
52
+ }
53
+ }
54
+ exports.LayoutContentCache = LayoutContentCache;
@@ -0,0 +1,116 @@
1
+ import type * as OpenFin from '../../../../OpenFin';
2
+ import type { LayoutContentCache } from './layout-content-cache';
3
+ type ViewCreationOrReference = OpenFin.Identity | OpenFin.PlatformViewCreationOptions;
4
+ /**
5
+ * @internal
6
+ * Controller for the layout entities apis, allowing alterations to be applied
7
+ * to an instance of layout manager in a structured manner.
8
+ */
9
+ export declare class LayoutEntitiesController {
10
+ private layoutManager;
11
+ private uuid;
12
+ private layoutContentCache;
13
+ constructor(layoutManager: any, uuid: string, layoutContentCache: LayoutContentCache);
14
+ /**
15
+ * @internal
16
+ * @returns the root contentItem of the layout.
17
+ */
18
+ getRoot: () => OpenFin.LayoutEntityDefinition;
19
+ /**
20
+ * @internal
21
+ * Retrieves the containing stack of a given view identity.
22
+ * @param view Identity of the view to retrieve the stack of.
23
+ * @returns Stack containing the given view.
24
+ * @throws If the view does not belong to a stack within the layout manager.
25
+ */
26
+ getStackByView: (view: OpenFin.Identity) => Promise<OpenFin.LayoutEntityDefinition | undefined>;
27
+ /**
28
+ * @internal
29
+ * Returns all views belonging to a given stack
30
+ *
31
+ * NOTE: Due to (TODO: ticket) Golden Layouts has an issue which changes the order of tabs
32
+ * when the amount of new views to add overflows the width of the container. This results
33
+ * in tabs being re-ordered in the UI, while the underlying content item array remains in the
34
+ * original order specified. So calling getStackViews() will return this underlying array order,
35
+ * with indexes that will not match up to the render-order of the tabs.
36
+ *
37
+ * @param id - Entity id of the stack.
38
+ * @returns A list of view identities in order of appearance.
39
+ * @throws if the content item associated with the entity id does not exist or is not a stack.
40
+ */
41
+ getStackViews: (id: string) => OpenFin.Identity[];
42
+ /**
43
+ * @internal
44
+ * Retrieves the content of a column or row and adds each to the
45
+ * entity cache to allow them to be addressed externally.
46
+ * @param id Entity id of the Column Or Row to retrieve the content of.
47
+ * @returns Array of layout entity definitions
48
+ * @throws if the entity associated with {@link id} is not in the entity cache, does not belogn to a layout, or is not a column/row.
49
+ */
50
+ getContent(id: string): OpenFin.LayoutEntityDefinition[];
51
+ /**
52
+ * @internal
53
+ * Retrieves the parent content item of the given entity, and adds it to the entity cache
54
+ * so it can be addressed externally.
55
+ * @param id Entity id associated with a layout content item.
56
+ * @returns An entity definition for the given entity's parent, or undefined if the entity is the top level
57
+ * content item or has been removed from the layout entirely.
58
+ */
59
+ getParent(id: string): OpenFin.LayoutEntityDefinition | undefined;
60
+ /**
61
+ * @internal
62
+ * @param id Entity id associated with a layout content item.
63
+ * @returns true if the given entity is the root content item, false otherwise.
64
+ */
65
+ isRoot: (id: string) => boolean;
66
+ /**
67
+ * @internal
68
+ * Checks whether the given entity exists.
69
+ * @param entityId Id of a content item within the layout
70
+ * @returns True if the content item exists and belongs to the layout.
71
+ */
72
+ exists: (entityId: string) => boolean;
73
+ /**
74
+ * @internal
75
+ * Adds an existing view to the stack, or creates and adds a view to the given stack.
76
+ *
77
+ * NOTE: Due to (TODO: ticket) Golden Layouts has an issue which changes the order of tabs
78
+ * when the amount of new views to add overflows the width of the container. This results
79
+ * in tabs being re-ordered in the UI, while the underlying content item array remains in the
80
+ * original order specified. So calling getStackViews() will return this underlying array order,
81
+ * with indexes that will not match up to the render-order of the tabs.
82
+ *
83
+ * @param stackEntityId Entity id of the stack content item within the layout.
84
+ * @param viewCreationOrReference View identity or creation options
85
+ * @param options Optional view options: index number used to insert the view into the stack at that index. Defaults to 0 (front of the stack)
86
+ * @returns Promise resolving with the identity of the newly added view.
87
+ * @throws If the view does not exist, fails to create, or the stack does not exist.
88
+ */
89
+ addViewToStack: (stackEntityId: string, viewCreationOrReference: ViewCreationOrReference, { index }?: OpenFin.AddViewToStackOptions) => Promise<OpenFin.Identity>;
90
+ /**
91
+ * @internal
92
+ * Removes a view from the given stack. If it's the only view, the stack will be destroyed, unless window creation
93
+ * option closeOnLastViewRemoved is set to false.
94
+ *
95
+ * @param stackEntityId Entity id of a stack content item to remove the view from.
96
+ * @param view Identity of the view to remove.
97
+ * @throws If the stack does not exist or the view does not exist or belong to the stack.
98
+ */
99
+ removeViewFromStack: (stackEntityId: string, view: OpenFin.Identity) => Promise<void>;
100
+ /**
101
+ * @internal
102
+ * Creates a new adjacent 'stack' and adds the views to it at the specified position
103
+ * @param targetId Entity id of the content item to add a stack adjacent to it
104
+ * @param views List of identities or view creation options of the views to include in the stack
105
+ * @param options Creation options, defaults to position: 'right'
106
+ * @returns the Entity Id of the new stack
107
+ */
108
+ createAdjacentStack: (targetId: string, views: ViewCreationOrReference[], options: {
109
+ position?: OpenFin.LayoutPosition;
110
+ }) => Promise<string>;
111
+ getAdjacentStacks: ({ targetId, edge }: {
112
+ targetId: string;
113
+ edge: OpenFin.LayoutPosition;
114
+ }) => Promise<Pick<OpenFin.LayoutEntityDefinition, 'entityId'>[]>;
115
+ }
116
+ export {};
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.LayoutEntitiesController = void 0;
10
+ const decorators_1 = require("../../../api-exposer/decorators");
11
+ const layout_traversal_1 = require("../utils/layout-traversal");
12
+ /**
13
+ * @internal
14
+ * Controller for the layout entities apis, allowing alterations to be applied
15
+ * to an instance of layout manager in a structured manner.
16
+ */
17
+ class LayoutEntitiesController {
18
+ constructor(
19
+ // workaround to prevent importing entire GoldenLayouts, also re-written at build time to type any
20
+ layoutManager, uuid, layoutContentCache) {
21
+ this.layoutManager = layoutManager;
22
+ this.uuid = uuid;
23
+ this.layoutContentCache = layoutContentCache;
24
+ /**
25
+ * @internal
26
+ * @returns the root contentItem of the layout.
27
+ */
28
+ this.getRoot = () => {
29
+ const root = this.layoutManager.layout.root.contentItems[0];
30
+ return {
31
+ // TODO: fix typing
32
+ type: root.type,
33
+ entityId: this.layoutContentCache.getOrCreateEntityId(root)
34
+ };
35
+ };
36
+ /**
37
+ * @internal
38
+ * Retrieves the containing stack of a given view identity.
39
+ * @param view Identity of the view to retrieve the stack of.
40
+ * @returns Stack containing the given view.
41
+ * @throws If the view does not belong to a stack within the layout manager.
42
+ */
43
+ this.getStackByView = async (view) => {
44
+ var _a, _b, _c, _d;
45
+ const viewComponent = this.layoutManager.getViewComponent(view);
46
+ if (!viewComponent || ((_b = (_a = viewComponent.container) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent.type) !== 'stack') {
47
+ return undefined;
48
+ }
49
+ const stack = (_d = (_c = viewComponent.container) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.parent;
50
+ return { entityId: this.layoutContentCache.getOrCreateEntityId(stack), type: 'stack' };
51
+ };
52
+ /**
53
+ * @internal
54
+ * Returns all views belonging to a given stack
55
+ *
56
+ * NOTE: Due to (TODO: ticket) Golden Layouts has an issue which changes the order of tabs
57
+ * when the amount of new views to add overflows the width of the container. This results
58
+ * in tabs being re-ordered in the UI, while the underlying content item array remains in the
59
+ * original order specified. So calling getStackViews() will return this underlying array order,
60
+ * with indexes that will not match up to the render-order of the tabs.
61
+ *
62
+ * @param id - Entity id of the stack.
63
+ * @returns A list of view identities in order of appearance.
64
+ * @throws if the content item associated with the entity id does not exist or is not a stack.
65
+ */
66
+ this.getStackViews = (id) => {
67
+ const stack = this.layoutContentCache.getContentItemOrThrow(id, ['stack']);
68
+ const views = stack.contentItems.map((ci) => {
69
+ var _a;
70
+ return ({
71
+ name: (_a = ci.config.componentState) === null || _a === void 0 ? void 0 : _a.name,
72
+ uuid: this.uuid
73
+ });
74
+ });
75
+ return views;
76
+ };
77
+ /**
78
+ * @internal
79
+ * @param id Entity id associated with a layout content item.
80
+ * @returns true if the given entity is the root content item, false otherwise.
81
+ */
82
+ this.isRoot = (id) => {
83
+ var _a;
84
+ const ci = this.layoutContentCache.getContentItemOrThrow(id);
85
+ return !!((_a = ci.parent) === null || _a === void 0 ? void 0 : _a.isRoot);
86
+ };
87
+ /**
88
+ * @internal
89
+ * Checks whether the given entity exists.
90
+ * @param entityId Id of a content item within the layout
91
+ * @returns True if the content item exists and belongs to the layout.
92
+ */
93
+ this.exists = (entityId) => {
94
+ return this.layoutContentCache.hasKey(entityId);
95
+ };
96
+ /**
97
+ * @internal
98
+ * Adds an existing view to the stack, or creates and adds a view to the given stack.
99
+ *
100
+ * NOTE: Due to (TODO: ticket) Golden Layouts has an issue which changes the order of tabs
101
+ * when the amount of new views to add overflows the width of the container. This results
102
+ * in tabs being re-ordered in the UI, while the underlying content item array remains in the
103
+ * original order specified. So calling getStackViews() will return this underlying array order,
104
+ * with indexes that will not match up to the render-order of the tabs.
105
+ *
106
+ * @param stackEntityId Entity id of the stack content item within the layout.
107
+ * @param viewCreationOrReference View identity or creation options
108
+ * @param options Optional view options: index number used to insert the view into the stack at that index. Defaults to 0 (front of the stack)
109
+ * @returns Promise resolving with the identity of the newly added view.
110
+ * @throws If the view does not exist, fails to create, or the stack does not exist.
111
+ */
112
+ this.addViewToStack = async (stackEntityId, viewCreationOrReference, { index } = { index: 0 }) => {
113
+ const currentStack = this.layoutContentCache.getContentItemOrThrow(stackEntityId);
114
+ if (index && index > currentStack.contentItems.length + 1) {
115
+ throw new Error(`Index '${index}' out of range, please exclude the index or specify a number between 0 and ${currentStack.contentItems.length}`);
116
+ }
117
+ const location = {
118
+ id: stackEntityId,
119
+ index
120
+ };
121
+ const { identity } = await this.layoutManager.platform.createView(viewCreationOrReference, {
122
+ ...this.layoutManager.ofWindow.identity,
123
+ location,
124
+ });
125
+ return identity;
126
+ };
127
+ /**
128
+ * @internal
129
+ * Removes a view from the given stack. If it's the only view, the stack will be destroyed, unless window creation
130
+ * option closeOnLastViewRemoved is set to false.
131
+ *
132
+ * @param stackEntityId Entity id of a stack content item to remove the view from.
133
+ * @param view Identity of the view to remove.
134
+ * @throws If the stack does not exist or the view does not exist or belong to the stack.
135
+ */
136
+ this.removeViewFromStack = async (stackEntityId, view) => {
137
+ const views = this.getStackViews(stackEntityId);
138
+ if (!views.find((existingView) => existingView.name === view.name)) {
139
+ throw new Error(`Tried to remove a view ('${view.name}') which does not exist in the stack.`);
140
+ }
141
+ await this.layoutManager.platform.closeView(view);
142
+ };
143
+ /**
144
+ * @internal
145
+ * Creates a new adjacent 'stack' and adds the views to it at the specified position
146
+ * @param targetId Entity id of the content item to add a stack adjacent to it
147
+ * @param views List of identities or view creation options of the views to include in the stack
148
+ * @param options Creation options, defaults to position: 'right'
149
+ * @returns the Entity Id of the new stack
150
+ */
151
+ this.createAdjacentStack = async (targetId, views, options) => {
152
+ if (views.length === 0) {
153
+ throw new Error('Cannot create stack with empty view array.');
154
+ }
155
+ const { position = 'right' } = options;
156
+ if (!['top', 'bottom', 'left', 'right'].includes(position)) {
157
+ throw new Error(`Invalid position '${position}' specified.`);
158
+ }
159
+ const currentStack = this.layoutContentCache.getContentItemOrThrow(targetId);
160
+ const { parent } = currentStack;
161
+ const containerType = ['top', 'bottom'].includes(position) ? 'column' : 'row';
162
+ const newContainer = this.layoutManager.layout.createContentItem({
163
+ type: containerType,
164
+ });
165
+ const newStack = this.layoutManager.layout.createContentItem({
166
+ type: 'stack'
167
+ });
168
+ parent.replaceChild(currentStack, newContainer);
169
+ newContainer.addChild(currentStack);
170
+ const offset = ['left', 'top'].includes(position) ? -1 : 1;
171
+ const newStackIndex = newContainer.contentItems.indexOf(currentStack) + offset;
172
+ newContainer.addChild(newStack, newStackIndex);
173
+ const entityId = this.layoutContentCache.getOrCreateEntityId(newStack);
174
+ // !! reverse the views list so we can utilize index=0 (prepending each tab)
175
+ // which will maintain correct order in the underlying GL structure and avoids the reflow bug
176
+ await Promise.all(views.reverse().map((view) => this.addViewToStack(entityId, view)));
177
+ return entityId;
178
+ };
179
+ this.getAdjacentStacks = async ({ targetId, edge }) => {
180
+ const contentItem = this.layoutContentCache.getContentItemOrThrow(targetId);
181
+ // call utils helper to traverse and return adjacent stacks
182
+ return (0, layout_traversal_1.getAdjacentStacks)(contentItem, edge).map((stack) => ({
183
+ entityId: this.layoutContentCache.getOrCreateEntityId(stack),
184
+ }));
185
+ };
186
+ }
187
+ /**
188
+ * @internal
189
+ * Retrieves the content of a column or row and adds each to the
190
+ * entity cache to allow them to be addressed externally.
191
+ * @param id Entity id of the Column Or Row to retrieve the content of.
192
+ * @returns Array of layout entity definitions
193
+ * @throws if the entity associated with {@link id} is not in the entity cache, does not belogn to a layout, or is not a column/row.
194
+ */
195
+ getContent(id) {
196
+ const ci = this.layoutContentCache.getContentItemOrThrow(id, ['column', 'row']);
197
+ return ci.contentItems.map((item) => ({
198
+ type: item.type,
199
+ entityId: this.layoutContentCache.getOrCreateEntityId(item)
200
+ }));
201
+ }
202
+ ;
203
+ /**
204
+ * @internal
205
+ * Retrieves the parent content item of the given entity, and adds it to the entity cache
206
+ * so it can be addressed externally.
207
+ * @param id Entity id associated with a layout content item.
208
+ * @returns An entity definition for the given entity's parent, or undefined if the entity is the top level
209
+ * content item or has been removed from the layout entirely.
210
+ */
211
+ getParent(id) {
212
+ const ci = this.layoutContentCache.getContentItemOrThrow(id);
213
+ if (ci.parent && !ci.parent.isRoot && ci.parent.contentItems.includes(ci)) {
214
+ return {
215
+ type: ci.parent.type,
216
+ entityId: this.layoutContentCache.getOrCreateEntityId(ci.parent)
217
+ };
218
+ }
219
+ return undefined;
220
+ }
221
+ ;
222
+ }
223
+ __decorate([
224
+ (0, decorators_1.expose)()
225
+ ], LayoutEntitiesController.prototype, "getRoot", void 0);
226
+ __decorate([
227
+ (0, decorators_1.expose)()
228
+ ], LayoutEntitiesController.prototype, "getStackByView", void 0);
229
+ __decorate([
230
+ (0, decorators_1.expose)()
231
+ ], LayoutEntitiesController.prototype, "getStackViews", void 0);
232
+ __decorate([
233
+ (0, decorators_1.expose)()
234
+ ], LayoutEntitiesController.prototype, "getContent", null);
235
+ __decorate([
236
+ (0, decorators_1.expose)()
237
+ ], LayoutEntitiesController.prototype, "getParent", null);
238
+ __decorate([
239
+ (0, decorators_1.expose)()
240
+ ], LayoutEntitiesController.prototype, "isRoot", void 0);
241
+ __decorate([
242
+ (0, decorators_1.expose)()
243
+ ], LayoutEntitiesController.prototype, "exists", void 0);
244
+ __decorate([
245
+ (0, decorators_1.expose)()
246
+ ], LayoutEntitiesController.prototype, "addViewToStack", void 0);
247
+ __decorate([
248
+ (0, decorators_1.expose)()
249
+ ], LayoutEntitiesController.prototype, "removeViewFromStack", void 0);
250
+ __decorate([
251
+ (0, decorators_1.expose)()
252
+ ], LayoutEntitiesController.prototype, "createAdjacentStack", void 0);
253
+ __decorate([
254
+ (0, decorators_1.expose)()
255
+ ], LayoutEntitiesController.prototype, "getAdjacentStacks", void 0);
256
+ exports.LayoutEntitiesController = LayoutEntitiesController;