@genesislcap/foundation-layout 14.72.0 → 14.74.0

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -240,8 +240,12 @@ This section concerns the behaviour of elements inside the layout. If you are us
240
240
 
241
241
  ### Element lifecycle
242
242
 
243
- When an item is dragged around the layout, its lifecycle functions `connectedCallback` and `disconnectedCallback` are called.
244
- It is important that the element accounts for this, including such requirements as caching data, or resizing correctly.
243
+ There are actions that the user can perform with items in the layout which will run the component lifecycle functions (`connectedCallback` and `disconnectedCallback`) at times when you don't want them to run:
244
+ - When an item is dragged around the layout.
245
+ - Potentially, when another item is removed from the layout
246
+ - Potentially, when new items are added to the layout.
247
+
248
+ For example, if you have a component with a loaded resource on the layout (such as a grid with a `grid-pro-genesis-datasource`) and you add a new item to the layout with the JavaScript API, then the component with the loaded resource will have to reload too. It is important that any such element accounts for this, including such requirements as caching data, or resizing correctly.
245
249
 
246
250
  In the `@genesislcap/foundation-utils` package, there is a mix-in class `LifecycleMixin` which exposes two protected members:
247
251
 
@@ -250,7 +254,7 @@ In the `@genesislcap/foundation-utils` package, there is a mix-in class `Lifecyc
250
254
 
251
255
  These can be used to gate certain functionality.
252
256
 
253
- For example, if there are parts of `disconnectedCallback` that you don't want to run when the item is being dragged around the layout, you can gate it behind a `(!this.shouldRunDisconnect) return;` early return.
257
+ For example, if there are parts of `disconnectedCallback` that you don't want to run when the item is being dragged around the layout, you can gate it behind a `(!this.shouldRunDisconnect) return;` early return. See [this example](#resource-intensive-component-resetting-in-layout).
254
258
 
255
259
  :::warning
256
260
  At the very least, you must run `super` calls to the lifecycle methods, or else your custom element will not work correctly.
@@ -1033,6 +1037,71 @@ The user of your layout will move things around and this will cache the layout.
1033
1037
  You and the user will only see the first two items like before. This is because the cached layout is being loaded, which does not contain the
1034
1038
  new item. To fix this you must [invalidate the cache](#invalidating-the-cache).
1035
1039
 
1040
+ ### Resource intensive component resetting in layout
1041
+
1042
+ Say you have a component which has to initialise a resource heavy or long awaited asynchronous task, such as the following:
1043
+ ```typescript
1044
+ @customElement({
1045
+ name: 'mock-connected',
1046
+ })
1047
+ export class MockConnected extends FASTElement {
1048
+ @observable resource = '';
1049
+
1050
+ async connectedCallback(): Promise<void> {
1051
+ super.connectedCallback();
1052
+ // Simulate doing some work with an external service
1053
+ }
1054
+
1055
+ async disconnectedCallback(): Promise<void> {
1056
+ super.disconnectedCallback();
1057
+ // Simulate cleaning an external service
1058
+ }
1059
+ }
1060
+ ```
1061
+
1062
+ As explained in the [lifecycle info section](#element-lifecycle), this component may have its `disconnectedCallback` and `connectedCallback` lifecycle at unnecessary times, effectively wasting time re-initialising a potentially heavy resource.
1063
+
1064
+ Use the `LifecycleMixin` to be able to access properties on the class which can be used to more thoughtfully run lifecycle functionality. In the following example we split out the resource intensive work and conditionally call them when needed.
1065
+
1066
+ ```typescript
1067
+ @customElement({
1068
+ name: 'mock-connected',
1069
+ })
1070
+ export class MockConnected extends LifecycleMixin(FASTElement) {
1071
+ @observable resource = '';
1072
+
1073
+ async connectedCallback(): Promise<void> {
1074
+ super.connectedCallback();
1075
+ const shouldRunConnect = this.shouldRunConnect;
1076
+ DOM.queueUpdate(async () => {
1077
+ if (!shouldRunConnect) return;
1078
+ await this.init();
1079
+ });
1080
+ }
1081
+
1082
+ async disconnectedCallback(): Promise<void> {
1083
+ super.disconnectedCallback();
1084
+ const shouldRunDisconnect = this.shouldRunDisconnect;
1085
+ DOM.queueUpdate(async () => {
1086
+ if (!shouldRunDisconnect) return;
1087
+ await this.deInit();
1088
+ });
1089
+ }
1090
+
1091
+ // Simulate doing work with an external service
1092
+ async init(): Promise<void> { }
1093
+
1094
+ // Simulate cleaning an external service
1095
+ async deInit(): Promise<void> { }
1096
+ }
1097
+ ```
1098
+
1099
+ The above is quite a comprehensive example, it doesn't necessarily have to be so complicated. You may just want to exit early from the connected callback without using the `DOM.queueUpdate` functionality. However, using it can be useful to properly handle `async` setup process.
1100
+
1101
+ :::warning
1102
+ The requirement to capture the parameter in the example above (e.g. `const shouldRunDisconnect = shouldRunDisconnect`) is to cache the information at the time of the lifecycle change, for use when the `DOM.queueUpdate` work is performed. This is not required if you run your lifecycle methods synchronously, but if you follow the above pattern you need to consider the `async` functionality being scheduled for after the layout considers the relevant lifecycle-gating functionality (such as dragging) to be over.
1103
+ :::
1104
+
1036
1105
  ## Supplementary information
1037
1106
 
1038
1107
  ### Custom components to handle bindings and event listeners
@@ -491,6 +491,16 @@
491
491
  "default": "false",
492
492
  "privacy": "public"
493
493
  },
494
+ {
495
+ "kind": "field",
496
+ "name": "lifecycleUpdateToken",
497
+ "type": {
498
+ "text": "string | undefined"
499
+ },
500
+ "privacy": "public",
501
+ "default": "undefined",
502
+ "description": "Used to calculate whether a layout item should run its lifecycle methods or not"
503
+ },
494
504
  {
495
505
  "kind": "method",
496
506
  "name": "layoutRequiredRegistrations",
@@ -613,6 +623,17 @@
613
623
  ],
614
624
  "privacy": "public"
615
625
  },
626
+ {
627
+ "kind": "method",
628
+ "name": "updateLifecycleToken",
629
+ "privacy": "private",
630
+ "return": {
631
+ "type": {
632
+ "text": "void"
633
+ }
634
+ },
635
+ "description": "The `LifecycleMixin` can use the lifecycleUpdateToken to determine if it needs to gate\nlifecycle methods from running when other items have been added or deleted.\nThis key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.\nThis method should be called whenever we are about to perform an action which will cause a lifecycle update, should as adding or removing an item from the layout"
636
+ },
616
637
  {
617
638
  "kind": "field",
618
639
  "name": "_presentation",
@@ -61,6 +61,15 @@ export declare class FoundationLayout extends FoundationElement implements Layou
61
61
  * Set to true when the user is currently dragging the panes inside of the layout
62
62
  */
63
63
  dragging: boolean;
64
+ /**
65
+ * Used to calculate whether a layout item should run its lifecycle methods or not
66
+ * @remarks
67
+ * When using the `LifecycleMixin`, the mixin can be used to gate lifecycle methods from
68
+ * running when other items have been added or deleted.
69
+ * This key is updated every time one of these actions are performed, so you can check if the key
70
+ * has changed and know you potentially need to gate some of your lifecycle functionality.
71
+ */
72
+ lifecycleUpdateToken: string | undefined;
64
73
  /** @internal */
65
74
  constructor();
66
75
  /** @internal */
@@ -72,11 +81,13 @@ export declare class FoundationLayout extends FoundationElement implements Layou
72
81
  /** @internal */
73
82
  private onDragStop;
74
83
  /** @internal */
75
- private onItemAdded;
84
+ private onPostItemAdded;
76
85
  /** @internal */
77
- private onItemRemoved;
86
+ private onPreItemRemoved;
78
87
  /** @internal */
79
- private onItemResized;
88
+ private onPostItemRemoved;
89
+ /** @internal */
90
+ private onPostItemResized;
80
91
  /**
81
92
  * JS API, public
82
93
  */
@@ -168,6 +179,13 @@ export declare class FoundationLayout extends FoundationElement implements Layou
168
179
  /**
169
180
  * Internal APIs
170
181
  */
182
+ /**
183
+ * The `LifecycleMixin` can use the lifecycleUpdateToken to determine if it needs to gate
184
+ * lifecycle methods from running when other items have been added or deleted.
185
+ * This key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.
186
+ * This method should be called whenever we are about to perform an action which will cause a lifecycle update, should as adding or removing an item from the layout
187
+ */
188
+ private updateLifecycleToken;
171
189
  /**
172
190
  * Request to reload the layout using the private member config. Debounced using the time set
173
191
  * in this.reloadBuffer
@@ -1 +1 @@
1
- {"version":3,"file":"layout-main.d.ts","sourceRoot":"","sources":["../../../src/main/layout-main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout-main.d.ts","sourceRoot":"","sources":["../../../src/main/layout-main.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- var _FoundationLayout__boundDragListener, _a;
1
+ var _FoundationLayout__boundPreDeletionListener, _FoundationLayout__boundDragListener, _a;
2
2
  import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib";
3
3
  import { GoldenLayout, LayoutConfig, ResolvedLayoutConfig, } from '@genesis-community/golden-layout';
4
4
  import { Session } from '@genesislcap/foundation-comms';
@@ -71,17 +71,30 @@ export class FoundationLayout extends FoundationElement {
71
71
  * Set to true when the user is currently dragging the panes inside of the layout
72
72
  */
73
73
  this.dragging = false;
74
+ /**
75
+ * Used to calculate whether a layout item should run its lifecycle methods or not
76
+ * @remarks
77
+ * When using the `LifecycleMixin`, the mixin can be used to gate lifecycle methods from
78
+ * running when other items have been added or deleted.
79
+ * This key is updated every time one of these actions are performed, so you can check if the key
80
+ * has changed and know you potentially need to gate some of your lifecycle functionality.
81
+ */
82
+ this.lifecycleUpdateToken = undefined;
83
+ /** @internal */
84
+ _FoundationLayout__boundPreDeletionListener.set(this, undefined);
74
85
  /** @internal */
75
86
  _FoundationLayout__boundDragListener.set(this, undefined);
76
87
  this.onDragStart = this.onDragStart.bind(this);
77
88
  this.onDragStop = this.onDragStop.bind(this);
78
89
  this.cacheAndSaveLayout = this.cacheAndSaveLayout.bind(this);
79
- this.onItemRemoved = this.onItemRemoved.bind(this);
90
+ this.onPostItemRemoved = this.onPostItemRemoved.bind(this);
91
+ this.onPreItemRemoved = this.onPreItemRemoved.bind(this);
80
92
  }
81
93
  /** @internal */
82
94
  connectedCallback() {
83
95
  super.connectedCallback();
84
96
  logger.debug(`FoundationLayout connected to the DOM`);
97
+ this.updateLifecycleToken();
85
98
  this.layout = new GoldenLayout(this.layoutElement);
86
99
  this.layout.resizeWithContainerAutomatically = true;
87
100
  if (!appliedGlobalStyles) {
@@ -93,13 +106,15 @@ export class FoundationLayout extends FoundationElement {
93
106
  }
94
107
  this.shadowRoot.addEventListener('dragStart', this.onDragStart, true);
95
108
  this.shadowRoot.addEventListener('dragStop', this.onDragStop, true);
96
- this.shadowRoot.addEventListener('closeButtonPressed', this.onItemRemoved, true);
109
+ this.shadowRoot.addEventListener('closeButtonPre', this.onPreItemRemoved, true);
110
+ this.shadowRoot.addEventListener('closeButtonPressed', this.onPostItemRemoved, true);
97
111
  }
98
112
  /** @internal */
99
113
  disconnectedCallback() {
100
114
  this.shadowRoot.removeEventListener('dragStart', this.onDragStart);
101
115
  this.shadowRoot.removeEventListener('dragStop', this.onDragStop);
102
- this.shadowRoot.removeEventListener('closeButtonPressed', this.onItemRemoved);
116
+ this.shadowRoot.removeEventListener('closeButtonPre', this.onPreItemRemoved);
117
+ this.shadowRoot.removeEventListener('closeButtonPressed', this.onPostItemRemoved);
103
118
  }
104
119
  /** @internal */
105
120
  onDragStart() {
@@ -112,17 +127,21 @@ export class FoundationLayout extends FoundationElement {
112
127
  this.attatchResizeEvents();
113
128
  }
114
129
  /** @internal */
115
- onItemAdded() {
130
+ onPostItemAdded() {
116
131
  this.$emit(LayoutEmitEvents.itemAdded);
117
132
  this.cacheAndSaveLayout();
118
133
  }
119
134
  /** @internal */
120
- onItemRemoved() {
135
+ onPreItemRemoved() {
136
+ this.updateLifecycleToken();
137
+ }
138
+ /** @internal */
139
+ onPostItemRemoved() {
121
140
  this.$emit(LayoutEmitEvents.itemRemoved);
122
141
  this.cacheAndSaveLayout();
123
142
  }
124
143
  /** @internal */
125
- onItemResized() {
144
+ onPostItemResized() {
126
145
  this.$emit(LayoutEmitEvents.itemResized);
127
146
  this.cacheAndSaveLayout();
128
147
  }
@@ -258,6 +277,7 @@ export class FoundationLayout extends FoundationElement {
258
277
  content: childItems,
259
278
  size: isSingleItem ? configArray[0].size : (_c = placement === null || placement === void 0 ? void 0 : placement.multiple) === null || _c === void 0 ? void 0 : _c.size,
260
279
  };
280
+ this.updateLifecycleToken();
261
281
  /**
262
282
  * If no root is added (no items via declerative API) then
263
283
  * this new item is the root so set it and return
@@ -267,7 +287,7 @@ export class FoundationLayout extends FoundationElement {
267
287
  root: itemConfig,
268
288
  };
269
289
  this.loadGLConfigAndSetup(this.layoutConfig);
270
- this.onItemAdded();
290
+ this.onPostItemAdded();
271
291
  return;
272
292
  }
273
293
  // Else we add the item relative to existing items
@@ -282,7 +302,7 @@ export class FoundationLayout extends FoundationElement {
282
302
  },
283
303
  };
284
304
  this.loadGLConfigAndSetup(this.layoutConfig);
285
- this.onItemAdded();
305
+ this.onPostItemAdded();
286
306
  }
287
307
  /**
288
308
  * @public
@@ -312,6 +332,15 @@ export class FoundationLayout extends FoundationElement {
312
332
  /**
313
333
  * Internal APIs
314
334
  */
335
+ /**
336
+ * The `LifecycleMixin` can use the lifecycleUpdateToken to determine if it needs to gate
337
+ * lifecycle methods from running when other items have been added or deleted.
338
+ * This key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.
339
+ * This method should be called whenever we are about to perform an action which will cause a lifecycle update, should as adding or removing an item from the layout
340
+ */
341
+ updateLifecycleToken() {
342
+ this.lifecycleUpdateToken = this.uuid.createId();
343
+ }
315
344
  /**
316
345
  * Request to reload the layout using the private member config. Debounced using the time set
317
346
  * in this.reloadBuffer
@@ -488,7 +517,7 @@ export class FoundationLayout extends FoundationElement {
488
517
  */
489
518
  attatchResizeEvents() {
490
519
  if (__classPrivateFieldGet(this, _FoundationLayout__boundDragListener, "f") === undefined) {
491
- __classPrivateFieldSet(this, _FoundationLayout__boundDragListener, () => this.onItemResized.bind(this)(), "f");
520
+ __classPrivateFieldSet(this, _FoundationLayout__boundDragListener, () => this.onPostItemResized.bind(this)(), "f");
492
521
  }
493
522
  this.shadowRoot.querySelectorAll('div.lm_drag_handle').forEach((h) => {
494
523
  h.removeEventListener('click', __classPrivateFieldGet(this, _FoundationLayout__boundDragListener, "f"));
@@ -496,7 +525,7 @@ export class FoundationLayout extends FoundationElement {
496
525
  });
497
526
  }
498
527
  }
499
- _FoundationLayout__boundDragListener = new WeakMap(), _a = componentType;
528
+ _FoundationLayout__boundPreDeletionListener = new WeakMap(), _FoundationLayout__boundDragListener = new WeakMap(), _a = componentType;
500
529
  __decorate([
501
530
  attr({ attribute: 'reload-buffer' })
502
531
  ], FoundationLayout.prototype, "reloadBuffer", void 0);
@@ -495,6 +495,36 @@
495
495
  "isAbstract": false,
496
496
  "name": "layoutRequiredRegistrations"
497
497
  },
498
+ {
499
+ "kind": "Property",
500
+ "canonicalReference": "@genesislcap/foundation-layout!FoundationLayout#lifecycleUpdateToken:member",
501
+ "docComment": "/**\n * Used to calculate whether a layout item should run its lifecycle methods or not\n *\n * @remarks\n *\n * When using the `LifecycleMixin`, the mixin can be used to gate lifecycle methods from running when other items have been added or deleted. This key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.\n */\n",
502
+ "excerptTokens": [
503
+ {
504
+ "kind": "Content",
505
+ "text": "lifecycleUpdateToken: "
506
+ },
507
+ {
508
+ "kind": "Content",
509
+ "text": "string | undefined"
510
+ },
511
+ {
512
+ "kind": "Content",
513
+ "text": ";"
514
+ }
515
+ ],
516
+ "isReadonly": false,
517
+ "isOptional": false,
518
+ "releaseTag": "Public",
519
+ "name": "lifecycleUpdateToken",
520
+ "propertyTypeTokenRange": {
521
+ "startIndex": 1,
522
+ "endIndex": 2
523
+ },
524
+ "isStatic": false,
525
+ "isProtected": false,
526
+ "isAbstract": false
527
+ },
498
528
  {
499
529
  "kind": "Method",
500
530
  "canonicalReference": "@genesislcap/foundation-layout!FoundationLayout#loadLayout:member(1)",
@@ -84,6 +84,15 @@ export declare class FoundationLayout extends FoundationElement implements Layou
84
84
  * Set to true when the user is currently dragging the panes inside of the layout
85
85
  */
86
86
  dragging: boolean;
87
+ /**
88
+ * Used to calculate whether a layout item should run its lifecycle methods or not
89
+ * @remarks
90
+ * When using the `LifecycleMixin`, the mixin can be used to gate lifecycle methods from
91
+ * running when other items have been added or deleted.
92
+ * This key is updated every time one of these actions are performed, so you can check if the key
93
+ * has changed and know you potentially need to gate some of your lifecycle functionality.
94
+ */
95
+ lifecycleUpdateToken: string | undefined;
87
96
  /** @internal */
88
97
  constructor();
89
98
  /** @internal */
@@ -95,11 +104,13 @@ export declare class FoundationLayout extends FoundationElement implements Layou
95
104
  /** @internal */
96
105
  private onDragStop;
97
106
  /** @internal */
98
- private onItemAdded;
107
+ private onPostItemAdded;
99
108
  /** @internal */
100
- private onItemRemoved;
109
+ private onPreItemRemoved;
101
110
  /** @internal */
102
- private onItemResized;
111
+ private onPostItemRemoved;
112
+ /** @internal */
113
+ private onPostItemResized;
103
114
  /**
104
115
  * JS API, public
105
116
  */
@@ -191,6 +202,13 @@ export declare class FoundationLayout extends FoundationElement implements Layou
191
202
  /**
192
203
  * Internal APIs
193
204
  */
205
+ /**
206
+ * The `LifecycleMixin` can use the lifecycleUpdateToken to determine if it needs to gate
207
+ * lifecycle methods from running when other items have been added or deleted.
208
+ * This key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.
209
+ * This method should be called whenever we are about to perform an action which will cause a lifecycle update, should as adding or removing an item from the layout
210
+ */
211
+ private updateLifecycleToken;
194
212
  /**
195
213
  * Request to reload the layout using the private member config. Debounced using the time set
196
214
  * in this.reloadBuffer
@@ -0,0 +1,18 @@
1
+ <!-- Do not edit this file. It is automatically generated by API Documenter. -->
2
+
3
+ [Home](./index.md) &gt; [@genesislcap/foundation-layout](./foundation-layout.md) &gt; [FoundationLayout](./foundation-layout.foundationlayout.md) &gt; [lifecycleUpdateToken](./foundation-layout.foundationlayout.lifecycleupdatetoken.md)
4
+
5
+ ## FoundationLayout.lifecycleUpdateToken property
6
+
7
+ Used to calculate whether a layout item should run its lifecycle methods or not
8
+
9
+ **Signature:**
10
+
11
+ ```typescript
12
+ lifecycleUpdateToken: string | undefined;
13
+ ```
14
+
15
+ ## Remarks
16
+
17
+ When using the `LifecycleMixin`<!-- -->, the mixin can be used to gate lifecycle methods from running when other items have been added or deleted. This key is updated every time one of these actions are performed, so you can check if the key has changed and know you potentially need to gate some of your lifecycle functionality.
18
+
@@ -28,6 +28,7 @@ The constructor for this class is marked as internal. Third-party code should no
28
28
  | [autoSaveKey?](./foundation-layout.foundationlayout.autosavekey.md) | | string | _(Optional)_ Attribute which if set will auto save and load the layout as the user changes it. Omit this attribute to disable this feature. Set attribute using <code>auto-save-key</code>. |
29
29
  | [dragging](./foundation-layout.foundationlayout.dragging.md) | | boolean | Set to true when the user is currently dragging the panes inside of the layout |
30
30
  | [hasFirstLoaded](./foundation-layout.foundationlayout.hasfirstloaded.md) | | boolean | Boolean signifies whether the layout has loaded for the first time or not. |
31
+ | [lifecycleUpdateToken](./foundation-layout.foundationlayout.lifecycleupdatetoken.md) | | string \| undefined | Used to calculate whether a layout item should run its lifecycle methods or not |
31
32
  | [missingItemPlaceholder](./foundation-layout.foundationlayout.missingitemplaceholder.md) | | (missingItem: string) =&gt; string | Function which is used to generate the placeholder text when a layout is loaded with a missing item. |
32
33
  | [reloadBuffer](./foundation-layout.foundationlayout.reloadbuffer.md) | | number | Number describing how long to wait in ms before reloading the config when adding items declaratively by the html API. Default 500 (ms). |
33
34
 
@@ -40,6 +40,7 @@ export class FoundationLayout extends FoundationElement implements LayoutCompone
40
40
  // @internal (undocumented)
41
41
  layoutElement: HTMLElement;
42
42
  static layoutRequiredRegistrations(layout: SerialisedLayout): string[];
43
+ lifecycleUpdateToken: string | undefined;
43
44
  loadLayout(layout: SerialisedLayout, handleMissingItem?: 'placeholder' | 'error'): void;
44
45
  missingItemPlaceholder: (missingItem: string) => string;
45
46
  registeredItems(): string[];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-layout",
3
3
  "description": "Genesis Foundation UI App Layout",
4
- "version": "14.72.0",
4
+ "version": "14.74.0",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/esm/index.js",
7
7
  "types": "dist/foundation-layout.d.ts",
@@ -24,14 +24,14 @@
24
24
  "test:debug": "genx test --debug"
25
25
  },
26
26
  "devDependencies": {
27
- "@genesislcap/foundation-testing": "14.72.0",
28
- "@genesislcap/genx": "14.72.0",
27
+ "@genesislcap/foundation-testing": "14.74.0",
28
+ "@genesislcap/genx": "14.74.0",
29
29
  "rimraf": "^3.0.2"
30
30
  },
31
31
  "dependencies": {
32
- "@genesis-community/golden-layout": "^2.9.3",
33
- "@genesislcap/foundation-comms": "14.72.0",
34
- "@genesislcap/foundation-utils": "14.72.0",
32
+ "@genesis-community/golden-layout": "^2.10.0",
33
+ "@genesislcap/foundation-comms": "14.74.0",
34
+ "@genesislcap/foundation-utils": "14.74.0",
35
35
  "@microsoft/fast-components": "^2.21.3",
36
36
  "@microsoft/fast-element": "^1.7.0",
37
37
  "@microsoft/fast-foundation": "^2.33.2",
@@ -46,5 +46,5 @@
46
46
  "access": "public"
47
47
  },
48
48
  "customElements": "dist/custom-elements.json",
49
- "gitHead": "c352280fa2af8458c0ab91fa5b97e13e4f1886ad"
49
+ "gitHead": "744f54392e6e9f73c0cddd55300925aa594020d2"
50
50
  }