@genesislcap/foundation-layout 14.393.2 → 14.393.3-FUI-2471.2
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/custom-elements.json +318 -24
- package/dist/dts/index.d.ts +1 -1
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/layout-main.d.ts +12 -5
- package/dist/dts/main/layout-main.d.ts.map +1 -1
- package/dist/dts/main/layout-popout-controller.d.ts +40 -0
- package/dist/dts/main/layout-popout-controller.d.ts.map +1 -0
- package/dist/dts/utils/constants.d.ts +7 -1
- package/dist/dts/utils/constants.d.ts.map +1 -1
- package/dist/dts/utils/index.d.ts +1 -0
- package/dist/dts/utils/index.d.ts.map +1 -1
- package/dist/dts/utils/popout-events.d.ts +37 -0
- package/dist/dts/utils/popout-events.d.ts.map +1 -0
- package/dist/dts/utils/types.d.ts +28 -0
- package/dist/dts/utils/types.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/main/layout-main.js +47 -21
- package/dist/esm/main/layout-popout-controller.js +243 -0
- package/dist/esm/utils/constants.js +7 -1
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/popout-events.js +5 -0
- package/dist/foundation-layout.api.json +94 -10
- package/dist/foundation-layout.d.ts +96 -4
- package/docs/api/foundation-layout.foundationlayout.md +3 -3
- package/docs/api/foundation-layout.foundationlayout.popoutconfig.md +2 -2
- package/docs/api/foundation-layout.foundationlayout.tryactivatepopoutmode.md +38 -1
- package/docs/api/foundation-layout.layout_popout_control_key.md +16 -0
- package/docs/api/foundation-layout.layoutpopoutconfig.md +22 -0
- package/docs/api/foundation-layout.md +22 -0
- package/docs/api/foundation-layout.serialisedlayout.md +3 -0
- package/docs/api-report.md.api.md +29 -2
- package/package.json +15 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAC5F,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/types.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from './main';
|
|
2
2
|
export { LAYOUT_ICONS } from './styles';
|
|
3
|
-
export { DEFAULT_RELOAD_BUFFER, LayoutEmitEvents, LayoutReceiveEvents, LayoutRegistrationError, LayoutUsageError, LAYOUT_POPOUT_CONTAINER_CLASS, } from './utils';
|
|
3
|
+
export { DEFAULT_RELOAD_BUFFER, LayoutEmitEvents, LayoutReceiveEvents, LayoutRegistrationError, LayoutUsageError, LAYOUT_POPOUT_CONTAINER_CLASS, LAYOUT_POPOUT_CONTROL_KEY, } from './utils';
|
|
4
4
|
export { registerFactory, getFactory, unregisterFactory } from './utils/factory-registry';
|
|
@@ -11,7 +11,9 @@ import { AUTOSAVE_KEY, componentType, DEFAULT_RELOAD_BUFFER, getMissingArrayItem
|
|
|
11
11
|
import { LayoutRegistrationError, LayoutUsageError } from '../utils/error';
|
|
12
12
|
import { getFactory } from '../utils/factory-registry';
|
|
13
13
|
import { logger } from '../utils/logger';
|
|
14
|
+
import { FoundationLayoutPopoutController } from './layout-popout-controller';
|
|
14
15
|
export { layoutStyles } from '../styles';
|
|
16
|
+
FoundationLayoutPopoutController;
|
|
15
17
|
/*
|
|
16
18
|
* We only want to apply the global stylesheet required for golden layout
|
|
17
19
|
* to work once, and only apply it if we actually use an instance of the
|
|
@@ -101,13 +103,14 @@ export class FoundationLayout extends FoundationElement {
|
|
|
101
103
|
* has changed and know you potentially need to gate some of your lifecycle functionality.
|
|
102
104
|
*/
|
|
103
105
|
this.lifecycleUpdateToken = undefined;
|
|
106
|
+
/** @internal */
|
|
107
|
+
this.popupMode = false;
|
|
104
108
|
/**
|
|
105
109
|
* Controls whether popout functionality is enabled on the layout. Defaults to disabled.
|
|
106
|
-
*
|
|
110
|
+
* Pass an empty object `{}` to use default configurations, or a {@link LayoutPopoutConfig} object to further customise.
|
|
107
111
|
* @beta
|
|
108
112
|
*/
|
|
109
113
|
this.popoutConfig = undefined;
|
|
110
|
-
this.popupMode = false;
|
|
111
114
|
/** @internal */
|
|
112
115
|
_FoundationLayout__boundDragListener.set(this, undefined);
|
|
113
116
|
/** @internal */
|
|
@@ -256,6 +259,7 @@ export class FoundationLayout extends FoundationElement {
|
|
|
256
259
|
* @returns - latest version of {@link SerialisedLayout} describing the layout
|
|
257
260
|
*/
|
|
258
261
|
getLayout() {
|
|
262
|
+
var _b, _c;
|
|
259
263
|
const componentCollection = this.getLayoutComponents();
|
|
260
264
|
componentCollection.forEach((items) => {
|
|
261
265
|
if (!items.length)
|
|
@@ -276,7 +280,11 @@ export class FoundationLayout extends FoundationElement {
|
|
|
276
280
|
orderedStates,
|
|
277
281
|
});
|
|
278
282
|
});
|
|
279
|
-
return {
|
|
283
|
+
return {
|
|
284
|
+
v: '1',
|
|
285
|
+
c: ResolvedLayoutConfig.minifyConfig(this.layout.saveLayout()),
|
|
286
|
+
popouts: (_c = (_b = this.popoutController) === null || _b === void 0 ? void 0 : _b.getRegistry()) !== null && _c !== void 0 ? _c : {},
|
|
287
|
+
};
|
|
280
288
|
}
|
|
281
289
|
/**
|
|
282
290
|
* If in a popout window from the dynamic layout, this function will run the flow to put the component in popout mode.
|
|
@@ -287,13 +295,19 @@ export class FoundationLayout extends FoundationElement {
|
|
|
287
295
|
* If you set the `LAYOUT_POPOUT_CONTAINER_CLASS` on an element which is a DOM parent of the layout,
|
|
288
296
|
* then if the layout goes into popout mode then it will place itself as the only child for the popout container you set.
|
|
289
297
|
* It is likely you'll want to attach this class to your design system provider.
|
|
298
|
+
*
|
|
299
|
+
* @param autoloading - If true, this respects the {@link LayoutPopoutConfig.loadAutomatically} property.
|
|
300
|
+
* You might want to set this to false and call it manually if you're manually registering components to the layout in order to avoid race conditions.
|
|
290
301
|
* @beta
|
|
291
302
|
*/
|
|
292
|
-
tryActivatePopoutMode() {
|
|
303
|
+
tryActivatePopoutMode(autoloading = false) {
|
|
304
|
+
var _b;
|
|
293
305
|
if (!this.popupMode)
|
|
294
306
|
return false;
|
|
307
|
+
if (autoloading && ((_b = this.popoutConfig) === null || _b === void 0 ? void 0 : _b.loadAutomatically) === false)
|
|
308
|
+
return;
|
|
295
309
|
const popoutComponentRegistration = new URLSearchParams(window.location.search).get(LAYOUT_POPOUT_CONTROL_KEY);
|
|
296
|
-
const
|
|
310
|
+
const glPopoutConfig = {
|
|
297
311
|
root: {
|
|
298
312
|
type: 'component',
|
|
299
313
|
componentType: popoutComponentRegistration,
|
|
@@ -303,7 +317,7 @@ export class FoundationLayout extends FoundationElement {
|
|
|
303
317
|
hasHeaders: false,
|
|
304
318
|
},
|
|
305
319
|
};
|
|
306
|
-
this.loadGLConfigAndSetup(
|
|
320
|
+
this.loadGLConfigAndSetup(glPopoutConfig);
|
|
307
321
|
const tryFindNewLayoutDOMLocation = (e) => {
|
|
308
322
|
if (e.classList.contains(LAYOUT_POPOUT_CONTAINER_CLASS))
|
|
309
323
|
return e;
|
|
@@ -397,6 +411,7 @@ export class FoundationLayout extends FoundationElement {
|
|
|
397
411
|
* @throws various errors if the layout string is malformed and cannot be parsed
|
|
398
412
|
*/
|
|
399
413
|
loadLayout(layout, handleMissingItem = 'error', disableCache = false) {
|
|
414
|
+
var _b;
|
|
400
415
|
const alreadyRegistered = this.registeredItems();
|
|
401
416
|
const wantedRegistered = FoundationLayout.layoutRequiredRegistrations(layout);
|
|
402
417
|
const missingRegisteredItems = getMissingArrayItems(wantedRegistered, alreadyRegistered);
|
|
@@ -408,6 +423,9 @@ export class FoundationLayout extends FoundationElement {
|
|
|
408
423
|
const layoutConfig = LayoutConfig.fromResolved(ResolvedLayoutConfig.unminifyConfig(layout.c));
|
|
409
424
|
if (disableCache)
|
|
410
425
|
this.removeConfigCacheInformation(layoutConfig);
|
|
426
|
+
if (!this.popupMode && this.popoutController) {
|
|
427
|
+
this.popoutController.restorePopouts((_b = layout.popouts) !== null && _b !== void 0 ? _b : {}, this.uuid);
|
|
428
|
+
}
|
|
411
429
|
if (missingRegisteredItems.length !== 0 && handleMissingItem === 'placeholder') {
|
|
412
430
|
this.registerPlaceholdersAndSetClosable(layoutConfig, missingRegisteredItems);
|
|
413
431
|
}
|
|
@@ -644,7 +662,7 @@ export class FoundationLayout extends FoundationElement {
|
|
|
644
662
|
this.hasFirstLoaded = true;
|
|
645
663
|
// Store the default layout config before attempting to load from storage
|
|
646
664
|
this.defaultLayoutConfig = JSON.parse(JSON.stringify(this.layoutConfig));
|
|
647
|
-
const res = this.tryLoadLayoutFromLocalStorage() || this.tryActivatePopoutMode();
|
|
665
|
+
const res = this.tryLoadLayoutFromLocalStorage() || this.tryActivatePopoutMode(true);
|
|
648
666
|
if (!res) {
|
|
649
667
|
this.loadGLConfigAndSetup(this.layoutConfig);
|
|
650
668
|
}
|
|
@@ -973,23 +991,22 @@ export class FoundationLayout extends FoundationElement {
|
|
|
973
991
|
if (!this.popoutConfig)
|
|
974
992
|
return;
|
|
975
993
|
logger.warn('Layout pop-out mode is enabled, this is an experimental feature and may change in future versions');
|
|
976
|
-
const
|
|
977
|
-
const matcher = /(\d+);(\d+)/;
|
|
978
|
-
const mMatches = popoutConfig.match(matcher);
|
|
979
|
-
if (!mMatches)
|
|
980
|
-
return '';
|
|
981
|
-
const [, width, height] = mMatches;
|
|
982
|
-
return `,width=${width},height=${height}`;
|
|
983
|
-
};
|
|
994
|
+
const configWithDefaults = Object.assign(Object.assign({}, this.popoutConfig), { loadAutomatically: true, popoutDimension: Object.assign(Object.assign({}, this.popoutConfig.popoutDimension), { width: 960, height: 720 }) });
|
|
984
995
|
this.customButtons.push({
|
|
985
996
|
svg: LAYOUT_ICONS.popoutSVG,
|
|
986
997
|
onClick: (_, elem) => {
|
|
998
|
+
var _b;
|
|
987
999
|
const registration = elem.firstChild[instanceContainer].registration;
|
|
988
|
-
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1000
|
+
// Use default dimensions from config
|
|
1001
|
+
const defaultGeometry = {
|
|
1002
|
+
screenX: undefined,
|
|
1003
|
+
screenY: undefined,
|
|
1004
|
+
outerWidth: configWithDefaults.popoutDimension.width,
|
|
1005
|
+
outerHeight: configWithDefaults.popoutDimension.height,
|
|
1006
|
+
};
|
|
1007
|
+
// Add to controller registry immediately so it tracks it
|
|
1008
|
+
(_b = this.popoutController) === null || _b === void 0 ? void 0 : _b.openPopout(registration, defaultGeometry, this.uuid);
|
|
1009
|
+
this.cacheAndSaveLayout();
|
|
993
1010
|
},
|
|
994
1011
|
});
|
|
995
1012
|
this.popupMode = window.location.search.includes(LAYOUT_POPOUT_CONTROL_KEY);
|
|
@@ -1021,7 +1038,10 @@ __decorate([
|
|
|
1021
1038
|
observable
|
|
1022
1039
|
], FoundationLayout.prototype, "dragging", void 0);
|
|
1023
1040
|
__decorate([
|
|
1024
|
-
|
|
1041
|
+
observable
|
|
1042
|
+
], FoundationLayout.prototype, "popupMode", void 0);
|
|
1043
|
+
__decorate([
|
|
1044
|
+
observable
|
|
1025
1045
|
], FoundationLayout.prototype, "popoutConfig", void 0);
|
|
1026
1046
|
__decorate([
|
|
1027
1047
|
observable
|
|
@@ -1037,6 +1057,12 @@ const loadingTemplate = html `
|
|
|
1037
1057
|
*/
|
|
1038
1058
|
export const layoutTemplate = html `
|
|
1039
1059
|
<template>
|
|
1060
|
+
${when((x) => Boolean(x.popoutConfig), html `
|
|
1061
|
+
<foundation-layout-popout-controller
|
|
1062
|
+
${ref('popoutController')}
|
|
1063
|
+
channel-name="${(x) => { var _b; return (_b = x.popoutConfig) === null || _b === void 0 ? void 0 : _b.channelName; }}"
|
|
1064
|
+
></foundation-layout-popout-controller>
|
|
1065
|
+
`)}
|
|
1040
1066
|
${when((x) => !x.hasFirstLoaded && x.usingDeclerativeAPI, loadingTemplate)}
|
|
1041
1067
|
<div class="layout-container" ${ref('layoutElement')}></div>
|
|
1042
1068
|
</template>
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { __awaiter, __decorate } from "tslib";
|
|
2
|
+
import { createTypedBroadcastChannel, } from '@genesislcap/foundation-broadcast-channel';
|
|
3
|
+
import { attr, customElement, FASTElement } from '@microsoft/fast-element';
|
|
4
|
+
import { LAYOUT_POPOUT_CONTROL_KEY, LayoutReceiveEvents, POPOUT_GEOMETRY_BROADCAST_INTERVAL, } from '../utils';
|
|
5
|
+
import { LAYOUT_POPOUT_CHANNEL_NAME } from '../utils/popout-events';
|
|
6
|
+
let FoundationLayoutPopoutController = class FoundationLayoutPopoutController extends FASTElement {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
// Internal registry to track both geometry and active window references
|
|
10
|
+
this.popoutRegistry = new Map();
|
|
11
|
+
}
|
|
12
|
+
connectedCallback() {
|
|
13
|
+
super.connectedCallback();
|
|
14
|
+
this.layoutKey = new URLSearchParams(window.location.search).get(LAYOUT_POPOUT_CONTROL_KEY);
|
|
15
|
+
this.setupChannel();
|
|
16
|
+
this.setupUnloadListener();
|
|
17
|
+
if (this.layoutKey) {
|
|
18
|
+
this.startPolling();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.setupListener();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
disconnectedCallback() {
|
|
25
|
+
super.disconnectedCallback();
|
|
26
|
+
if (this.channel) {
|
|
27
|
+
this.channel.close();
|
|
28
|
+
}
|
|
29
|
+
this.stopPolling();
|
|
30
|
+
this.teardownUnloadListener();
|
|
31
|
+
if (!this.layoutKey) {
|
|
32
|
+
this.closeAllPopouts();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
setupChannel() {
|
|
36
|
+
const name = this.channelName || LAYOUT_POPOUT_CHANNEL_NAME;
|
|
37
|
+
this.channel = createTypedBroadcastChannel(name);
|
|
38
|
+
}
|
|
39
|
+
setupListener() {
|
|
40
|
+
if (!this.channel)
|
|
41
|
+
return;
|
|
42
|
+
this.channel.onmessage = (ev) => {
|
|
43
|
+
if (this.channel.isMessageType('popout-geometry-change', ev)) {
|
|
44
|
+
const { layoutKey, geometry } = ev.data
|
|
45
|
+
.detail;
|
|
46
|
+
const current = this.popoutRegistry.get(layoutKey);
|
|
47
|
+
this.popoutRegistry.set(layoutKey, Object.assign(Object.assign({}, current), { geometry }));
|
|
48
|
+
this.emitAutosave();
|
|
49
|
+
}
|
|
50
|
+
else if (this.channel.isMessageType('popout-closed', ev)) {
|
|
51
|
+
const { layoutKey } = ev.data.detail;
|
|
52
|
+
this.popoutRegistry.delete(layoutKey);
|
|
53
|
+
this.emitAutosave();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
setupUnloadListener() {
|
|
58
|
+
this.unloadHandler = () => {
|
|
59
|
+
if (this.layoutKey) {
|
|
60
|
+
if (this.channel) {
|
|
61
|
+
this.channel.postMessage('popout-closed', { layoutKey: this.layoutKey });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.closeAllPopouts();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
window.addEventListener('beforeunload', this.unloadHandler);
|
|
69
|
+
}
|
|
70
|
+
teardownUnloadListener() {
|
|
71
|
+
if (this.unloadHandler) {
|
|
72
|
+
window.removeEventListener('beforeunload', this.unloadHandler);
|
|
73
|
+
this.unloadHandler = null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
emitAutosave() {
|
|
77
|
+
this.$emit(LayoutReceiveEvents.autosave, undefined, {
|
|
78
|
+
bubbles: true,
|
|
79
|
+
composed: true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
startPolling() {
|
|
83
|
+
this.pollInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const currentGeo = yield this.getGeometry();
|
|
85
|
+
const geoString = JSON.stringify(currentGeo);
|
|
86
|
+
if (geoString !== this.lastGeometry) {
|
|
87
|
+
this.broadcastGeometry(currentGeo);
|
|
88
|
+
this.lastGeometry = geoString;
|
|
89
|
+
}
|
|
90
|
+
}), POPOUT_GEOMETRY_BROADCAST_INTERVAL);
|
|
91
|
+
}
|
|
92
|
+
stopPolling() {
|
|
93
|
+
if (this.pollInterval) {
|
|
94
|
+
clearInterval(this.pollInterval);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getGeometry() {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
const screenId = yield (() => __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
var _a;
|
|
101
|
+
if ('getScreenDetails' in window) {
|
|
102
|
+
try {
|
|
103
|
+
// This may prompt the user for permission if not already granted
|
|
104
|
+
const details = yield window.getScreenDetails();
|
|
105
|
+
return (_a = details.currentScreen) === null || _a === void 0 ? void 0 : _a.label;
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
// Silent fail - permission denied or API error
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}))();
|
|
114
|
+
return {
|
|
115
|
+
screenX: window.screenX,
|
|
116
|
+
screenY: window.screenY,
|
|
117
|
+
outerWidth: window.outerWidth,
|
|
118
|
+
outerHeight: window.outerHeight,
|
|
119
|
+
screenId,
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
broadcastGeometry(geometry) {
|
|
124
|
+
if (!this.channel || !this.layoutKey)
|
|
125
|
+
return;
|
|
126
|
+
this.channel.postMessage('popout-geometry-change', {
|
|
127
|
+
layoutKey: this.layoutKey,
|
|
128
|
+
geometry,
|
|
129
|
+
});
|
|
130
|
+
console.log('[PopoutController] Broadcasting geometry:', geometry);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Opens a component in a popout window.
|
|
134
|
+
* @param registration - The registration ID of the component to pop out.
|
|
135
|
+
* @param geometry - Optional geometry to use for the new window.
|
|
136
|
+
* @param uuid - UUID generator from parent layout
|
|
137
|
+
*/
|
|
138
|
+
openPopout(registration, geometry, uuid) {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
const url = new URL(window.location.toString());
|
|
141
|
+
const itemParams = new URLSearchParams();
|
|
142
|
+
itemParams.append(LAYOUT_POPOUT_CONTROL_KEY, registration);
|
|
143
|
+
url.search = itemParams.toString();
|
|
144
|
+
let features = 'popup';
|
|
145
|
+
let targetLeft = geometry === null || geometry === void 0 ? void 0 : geometry.screenX;
|
|
146
|
+
let targetTop = geometry === null || geometry === void 0 ? void 0 : geometry.screenY;
|
|
147
|
+
// If we have a screenId, try to find the screen and ensure coordinates are valid
|
|
148
|
+
if ((geometry === null || geometry === void 0 ? void 0 : geometry.screenId) && 'getScreenDetails' in window) {
|
|
149
|
+
try {
|
|
150
|
+
const details = yield window.getScreenDetails();
|
|
151
|
+
const targetScreen = details.screens.find((s) => s.label === geometry.screenId);
|
|
152
|
+
if (targetScreen) {
|
|
153
|
+
const isWithin = targetLeft >= targetScreen.availLeft &&
|
|
154
|
+
targetLeft < targetScreen.availLeft + targetScreen.availWidth &&
|
|
155
|
+
targetTop >= targetScreen.availTop &&
|
|
156
|
+
targetTop < targetScreen.availTop + targetScreen.availHeight;
|
|
157
|
+
if (!isWithin) {
|
|
158
|
+
targetLeft = targetScreen.availLeft;
|
|
159
|
+
targetTop = targetScreen.availTop;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
targetLeft = undefined;
|
|
164
|
+
targetTop = undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
// Fallback
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (geometry) {
|
|
172
|
+
features += `,width=${geometry.outerWidth},height=${geometry.outerHeight}`;
|
|
173
|
+
if (targetLeft !== undefined)
|
|
174
|
+
features += `,left=${targetLeft}`;
|
|
175
|
+
if (targetTop !== undefined)
|
|
176
|
+
features += `,top=${targetTop}`;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
features += ',width=800,height=600'; // Default fallback
|
|
180
|
+
}
|
|
181
|
+
const win = window.open(url, `popout-${registration}-${(uuid === null || uuid === void 0 ? void 0 : uuid.createId()) || Date.now()}`, features);
|
|
182
|
+
if (!win) {
|
|
183
|
+
console.warn(`Popout window for ${registration} was blocked.`);
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
// Update registry with the window reference and geometry (if provided)
|
|
187
|
+
const current = this.popoutRegistry.get(registration);
|
|
188
|
+
this.popoutRegistry.set(registration, {
|
|
189
|
+
geometry: geometry || (current === null || current === void 0 ? void 0 : current.geometry),
|
|
190
|
+
window: win,
|
|
191
|
+
});
|
|
192
|
+
return win;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
getRegistry() {
|
|
196
|
+
const output = {};
|
|
197
|
+
for (const [key, val] of this.popoutRegistry.entries()) {
|
|
198
|
+
if (val.geometry) {
|
|
199
|
+
output[key] = { geometry: val.geometry };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return output;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Restores popouts from a registry
|
|
206
|
+
*/
|
|
207
|
+
restorePopouts(registry, uuid) {
|
|
208
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
209
|
+
this.closeAllPopouts();
|
|
210
|
+
// Populate the registry with serialized data
|
|
211
|
+
for (const [key, val] of Object.entries(registry)) {
|
|
212
|
+
this.popoutRegistry.set(key, { geometry: val.geometry });
|
|
213
|
+
}
|
|
214
|
+
const keys = Array.from(this.popoutRegistry.keys());
|
|
215
|
+
if (keys.length === 0)
|
|
216
|
+
return;
|
|
217
|
+
console.debug(`Restoring ${keys.length} popout windows`);
|
|
218
|
+
yield Promise.all(keys.map((key) => {
|
|
219
|
+
const state = this.popoutRegistry.get(key);
|
|
220
|
+
return this.openPopout(key, state.geometry, uuid);
|
|
221
|
+
}));
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
closeAllPopouts() {
|
|
225
|
+
for (const val of this.popoutRegistry.values()) {
|
|
226
|
+
if (val.window && !val.window.closed) {
|
|
227
|
+
val.window.close();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
this.popoutRegistry.clear();
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
__decorate([
|
|
234
|
+
attr({ attribute: 'channel-name' })
|
|
235
|
+
], FoundationLayoutPopoutController.prototype, "channelName", void 0);
|
|
236
|
+
FoundationLayoutPopoutController = __decorate([
|
|
237
|
+
customElement({
|
|
238
|
+
name: 'foundation-layout-popout-controller',
|
|
239
|
+
template: null,
|
|
240
|
+
styles: null,
|
|
241
|
+
})
|
|
242
|
+
], FoundationLayoutPopoutController);
|
|
243
|
+
export { FoundationLayoutPopoutController };
|
|
@@ -25,9 +25,15 @@ export const DEFAULT_RELOAD_BUFFER = 500;
|
|
|
25
25
|
export const AUTOSAVE_KEY = 'foundation-layout-autosave';
|
|
26
26
|
/**
|
|
27
27
|
* Key to be used for controlling popout behaviour
|
|
28
|
-
* @
|
|
28
|
+
* @beta
|
|
29
29
|
*/
|
|
30
30
|
export const LAYOUT_POPOUT_CONTROL_KEY = 'f-layout-key';
|
|
31
|
+
/**
|
|
32
|
+
* How often a popout window should check to broadcast its
|
|
33
|
+
* geometry
|
|
34
|
+
* @interal
|
|
35
|
+
*/
|
|
36
|
+
export const POPOUT_GEOMETRY_BROADCAST_INTERVAL = 1000;
|
|
31
37
|
/**
|
|
32
38
|
* Put this classname on an element which is a DOM parent of the layout, and
|
|
33
39
|
* if the layout goes into popout mode then it will place itself as the only child
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -845,15 +845,20 @@
|
|
|
845
845
|
{
|
|
846
846
|
"kind": "Property",
|
|
847
847
|
"canonicalReference": "@genesislcap/foundation-layout!FoundationLayout#popoutConfig:member",
|
|
848
|
-
"docComment": "/**\n * Controls whether popout functionality is enabled on the layout. Defaults to disabled.
|
|
848
|
+
"docComment": "/**\n * Controls whether popout functionality is enabled on the layout. Defaults to disabled. Pass an empty object `{}` to use default configurations, or a {@link LayoutPopoutConfig} object to further customise.\n *\n * @beta\n */\n",
|
|
849
849
|
"excerptTokens": [
|
|
850
850
|
{
|
|
851
851
|
"kind": "Content",
|
|
852
852
|
"text": "popoutConfig: "
|
|
853
853
|
},
|
|
854
|
+
{
|
|
855
|
+
"kind": "Reference",
|
|
856
|
+
"text": "LayoutPopoutConfig",
|
|
857
|
+
"canonicalReference": "@genesislcap/foundation-layout!LayoutPopoutConfig:type"
|
|
858
|
+
},
|
|
854
859
|
{
|
|
855
860
|
"kind": "Content",
|
|
856
|
-
"text": "
|
|
861
|
+
"text": " | undefined"
|
|
857
862
|
},
|
|
858
863
|
{
|
|
859
864
|
"kind": "Content",
|
|
@@ -866,7 +871,7 @@
|
|
|
866
871
|
"name": "popoutConfig",
|
|
867
872
|
"propertyTypeTokenRange": {
|
|
868
873
|
"startIndex": 1,
|
|
869
|
-
"endIndex":
|
|
874
|
+
"endIndex": 3
|
|
870
875
|
},
|
|
871
876
|
"isStatic": false,
|
|
872
877
|
"isProtected": false,
|
|
@@ -1074,11 +1079,19 @@
|
|
|
1074
1079
|
{
|
|
1075
1080
|
"kind": "Method",
|
|
1076
1081
|
"canonicalReference": "@genesislcap/foundation-layout!FoundationLayout#tryActivatePopoutMode:member(1)",
|
|
1077
|
-
"docComment": "/**\n * If in a popout window from the dynamic layout, this function will run the flow to put the component in popout mode. This function is automatically called if using the declarative HTML API, but if only using the JavaScript API then you will need to call this function manually.\n *\n * @remarks\n *\n * If you need to call this manually then you should do it as soon as you register all of the required components with {@link FoundationLayout.registerItem}.\n *\n * If you set the `LAYOUT_POPOUT_CONTAINER_CLASS` on an element which is a DOM parent of the layout, then if the layout goes into popout mode then it will place itself as the only child for the popout container you set. It is likely you'll want to attach this class to your design system provider.\n *\n * @beta\n */\n",
|
|
1082
|
+
"docComment": "/**\n * If in a popout window from the dynamic layout, this function will run the flow to put the component in popout mode. This function is automatically called if using the declarative HTML API, but if only using the JavaScript API then you will need to call this function manually.\n *\n * @remarks\n *\n * If you need to call this manually then you should do it as soon as you register all of the required components with {@link FoundationLayout.registerItem}.\n *\n * If you set the `LAYOUT_POPOUT_CONTAINER_CLASS` on an element which is a DOM parent of the layout, then if the layout goes into popout mode then it will place itself as the only child for the popout container you set. It is likely you'll want to attach this class to your design system provider.\n *\n * @param autoloading - If true, this respects the {@link LayoutPopoutConfig.loadAutomatically} property. You might want to set this to false and call it manually if you're manually registering components to the layout in order to avoid race conditions.\n *\n * @beta\n */\n",
|
|
1078
1083
|
"excerptTokens": [
|
|
1079
1084
|
{
|
|
1080
1085
|
"kind": "Content",
|
|
1081
|
-
"text": "tryActivatePopoutMode(
|
|
1086
|
+
"text": "tryActivatePopoutMode(autoloading?: "
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
"kind": "Content",
|
|
1090
|
+
"text": "boolean"
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
"kind": "Content",
|
|
1094
|
+
"text": "): "
|
|
1082
1095
|
},
|
|
1083
1096
|
{
|
|
1084
1097
|
"kind": "Content",
|
|
@@ -1091,13 +1104,22 @@
|
|
|
1091
1104
|
],
|
|
1092
1105
|
"isStatic": false,
|
|
1093
1106
|
"returnTypeTokenRange": {
|
|
1094
|
-
"startIndex":
|
|
1095
|
-
"endIndex":
|
|
1107
|
+
"startIndex": 3,
|
|
1108
|
+
"endIndex": 4
|
|
1096
1109
|
},
|
|
1097
1110
|
"releaseTag": "Beta",
|
|
1098
1111
|
"isProtected": false,
|
|
1099
1112
|
"overloadIndex": 1,
|
|
1100
|
-
"parameters": [
|
|
1113
|
+
"parameters": [
|
|
1114
|
+
{
|
|
1115
|
+
"parameterName": "autoloading",
|
|
1116
|
+
"parameterTypeTokenRange": {
|
|
1117
|
+
"startIndex": 1,
|
|
1118
|
+
"endIndex": 2
|
|
1119
|
+
},
|
|
1120
|
+
"isOptional": true
|
|
1121
|
+
}
|
|
1122
|
+
],
|
|
1101
1123
|
"isOptional": false,
|
|
1102
1124
|
"isAbstract": false,
|
|
1103
1125
|
"name": "tryActivatePopoutMode"
|
|
@@ -1721,6 +1743,33 @@
|
|
|
1721
1743
|
"endIndex": 0
|
|
1722
1744
|
}
|
|
1723
1745
|
},
|
|
1746
|
+
{
|
|
1747
|
+
"kind": "Variable",
|
|
1748
|
+
"canonicalReference": "@genesislcap/foundation-layout!LAYOUT_POPOUT_CONTROL_KEY:var",
|
|
1749
|
+
"docComment": "/**\n * Key to be used for controlling popout behaviour\n *\n * @beta\n */\n",
|
|
1750
|
+
"excerptTokens": [
|
|
1751
|
+
{
|
|
1752
|
+
"kind": "Content",
|
|
1753
|
+
"text": "LAYOUT_POPOUT_CONTROL_KEY = "
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
"kind": "Content",
|
|
1757
|
+
"text": "\"f-layout-key\""
|
|
1758
|
+
}
|
|
1759
|
+
],
|
|
1760
|
+
"fileUrlPath": "src/utils/constants.ts",
|
|
1761
|
+
"initializerTokenRange": {
|
|
1762
|
+
"startIndex": 1,
|
|
1763
|
+
"endIndex": 2
|
|
1764
|
+
},
|
|
1765
|
+
"isReadonly": true,
|
|
1766
|
+
"releaseTag": "Beta",
|
|
1767
|
+
"name": "LAYOUT_POPOUT_CONTROL_KEY",
|
|
1768
|
+
"variableTypeTokenRange": {
|
|
1769
|
+
"startIndex": 0,
|
|
1770
|
+
"endIndex": 0
|
|
1771
|
+
}
|
|
1772
|
+
},
|
|
1724
1773
|
{
|
|
1725
1774
|
"kind": "Interface",
|
|
1726
1775
|
"canonicalReference": "@genesislcap/foundation-layout!LayoutComponentWithState:interface",
|
|
@@ -1848,6 +1897,32 @@
|
|
|
1848
1897
|
"endIndex": 2
|
|
1849
1898
|
}
|
|
1850
1899
|
},
|
|
1900
|
+
{
|
|
1901
|
+
"kind": "TypeAlias",
|
|
1902
|
+
"canonicalReference": "@genesislcap/foundation-layout!LayoutPopoutConfig:type",
|
|
1903
|
+
"docComment": "/**\n * @beta\n */\n",
|
|
1904
|
+
"excerptTokens": [
|
|
1905
|
+
{
|
|
1906
|
+
"kind": "Content",
|
|
1907
|
+
"text": "export type LayoutPopoutConfig = "
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
"kind": "Content",
|
|
1911
|
+
"text": "{\n channelName?: string;\n loadAutomatically?: boolean;\n popoutDimension?: {\n width: number;\n height: number;\n };\n}"
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
"kind": "Content",
|
|
1915
|
+
"text": ";"
|
|
1916
|
+
}
|
|
1917
|
+
],
|
|
1918
|
+
"fileUrlPath": "src/utils/types.ts",
|
|
1919
|
+
"releaseTag": "Beta",
|
|
1920
|
+
"name": "LayoutPopoutConfig",
|
|
1921
|
+
"typeTokenRange": {
|
|
1922
|
+
"startIndex": 1,
|
|
1923
|
+
"endIndex": 2
|
|
1924
|
+
}
|
|
1925
|
+
},
|
|
1851
1926
|
{
|
|
1852
1927
|
"kind": "Variable",
|
|
1853
1928
|
"canonicalReference": "@genesislcap/foundation-layout!LayoutReceiveEvents:var",
|
|
@@ -2399,7 +2474,16 @@
|
|
|
2399
2474
|
},
|
|
2400
2475
|
{
|
|
2401
2476
|
"kind": "Content",
|
|
2402
|
-
"text": ";\n
|
|
2477
|
+
"text": ";\n popouts?: {\n [layoutKey: string]: "
|
|
2478
|
+
},
|
|
2479
|
+
{
|
|
2480
|
+
"kind": "Reference",
|
|
2481
|
+
"text": "PopoutState",
|
|
2482
|
+
"canonicalReference": "@genesislcap/foundation-layout!~PopoutState:type"
|
|
2483
|
+
},
|
|
2484
|
+
{
|
|
2485
|
+
"kind": "Content",
|
|
2486
|
+
"text": ";\n };\n}"
|
|
2403
2487
|
},
|
|
2404
2488
|
{
|
|
2405
2489
|
"kind": "Content",
|
|
@@ -2411,7 +2495,7 @@
|
|
|
2411
2495
|
"name": "SerialisedLayout",
|
|
2412
2496
|
"typeTokenRange": {
|
|
2413
2497
|
"startIndex": 1,
|
|
2414
|
-
"endIndex":
|
|
2498
|
+
"endIndex": 6
|
|
2415
2499
|
}
|
|
2416
2500
|
},
|
|
2417
2501
|
{
|