@openfin/core 31.74.31 → 32.75.1

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 (82) hide show
  1. package/package.json +1 -1
  2. package/src/OpenFin.d.ts +58 -13
  3. package/src/api/application/Instance.d.ts +13 -1
  4. package/src/api/application/Instance.js +39 -7
  5. package/src/api/base.d.ts +1 -2
  6. package/src/api/base.js +1 -2
  7. package/src/api/events/application.d.ts +4 -1
  8. package/src/api/events/system.d.ts +6 -3
  9. package/src/api/events/webcontents.d.ts +54 -5
  10. package/src/api/fin.js +1 -2
  11. package/src/api/interappbus/channel/client.d.ts +2 -2
  12. package/src/api/interappbus/channel/index.d.ts +4 -3
  13. package/src/api/interappbus/channel/index.js +111 -74
  14. package/src/api/interappbus/channel/protocols/classic/strategy.js +24 -6
  15. package/src/api/interappbus/index.js +1 -1
  16. package/src/api/interop/InteropClient.d.ts +1 -1
  17. package/src/api/interop/InteropClient.js +1 -1
  18. package/src/api/interop/SessionContextGroupBroker.d.ts +1 -1
  19. package/src/api/interop/SessionContextGroupBroker.js +5 -4
  20. package/src/api/interop/SessionContextGroupClient.js +1 -1
  21. package/src/api/interop/fdc3/PrivateChannelProvider.d.ts +1 -1
  22. package/src/api/interop/fdc3/PrivateChannelProvider.js +1 -8
  23. package/src/api/interop/fdc3/fdc3-1.2.js +34 -1
  24. package/src/api/interop/fdc3/utils.js +24 -4
  25. package/src/api/me.d.ts +1 -1
  26. package/src/api/me.js +2 -1
  27. package/src/api/platform/Factory.d.ts +3 -3
  28. package/src/api/platform/Factory.js +2 -11
  29. package/src/api/platform/Instance.d.ts +5 -4
  30. package/src/api/platform/Instance.js +2 -1
  31. package/src/api/platform/layout/Factory.d.ts +1 -1
  32. package/src/api/platform/layout/Factory.js +7 -39
  33. package/src/api/platform/layout/Instance.js +3 -0
  34. package/src/api/platform/layout/controllers/layout-entities-controller.d.ts +6 -2
  35. package/src/api/platform/layout/controllers/layout-entities-controller.js +40 -8
  36. package/src/api/platform/layout/entities/layout-entities.d.ts +143 -42
  37. package/src/api/platform/layout/entities/layout-entities.js +151 -43
  38. package/src/api/platform/layout/utils/layout-traversal.d.ts +1 -0
  39. package/src/api/platform/layout/utils/layout-traversal.js +11 -11
  40. package/src/api/platform/provider.d.ts +2 -1
  41. package/src/api/system/index.d.ts +9 -0
  42. package/src/api/system/index.js +78 -40
  43. package/src/api/view/Instance.d.ts +6 -3
  44. package/src/api/view/Instance.js +10 -9
  45. package/src/api/webcontents/main.d.ts +2 -22
  46. package/src/api/webcontents/main.js +2 -1
  47. package/src/api/window/Instance.d.ts +10 -0
  48. package/src/api/window/Instance.js +22 -0
  49. package/src/environment/browser.d.ts +4 -2
  50. package/src/environment/browser.js +5 -2
  51. package/src/environment/environment.d.ts +4 -2
  52. package/src/environment/mockEnvironment.d.ts +27 -0
  53. package/src/environment/mockEnvironment.js +61 -0
  54. package/src/environment/node-env.d.ts +3 -2
  55. package/src/environment/node-env.js +5 -2
  56. package/src/environment/openfin-env.d.ts +5 -3
  57. package/src/environment/openfin-env.js +12 -10
  58. package/src/mock.js +4 -83
  59. package/src/shapes/protocol.d.ts +26 -9
  60. package/src/transport/mockWire.d.ts +11 -0
  61. package/src/transport/mockWire.js +26 -0
  62. package/src/transport/transport-errors.d.ts +9 -1
  63. package/src/transport/transport-errors.js +45 -2
  64. package/src/transport/transport.d.ts +16 -5
  65. package/src/transport/transport.js +48 -20
  66. package/src/util/channel-api-relay.js +11 -1
  67. package/src/util/errors.d.ts +1 -0
  68. package/src/util/errors.js +1 -0
  69. package/src/util/lazy.d.ts +18 -0
  70. package/src/util/lazy.js +29 -1
  71. package/src/util/ref-counter.d.ts +1 -1
  72. package/src/util/ref-counter.js +3 -2
  73. package/src/api/platform/layout/controllers/splitter-controller.d.ts +0 -30
  74. package/src/api/platform/layout/controllers/splitter-controller.js +0 -83
  75. package/src/api/platform/layout/controllers/tab-drag-controller.d.ts +0 -58
  76. package/src/api/platform/layout/controllers/tab-drag-controller.js +0 -124
  77. package/src/api/platform/layout/utils/bounds-observer.d.ts +0 -19
  78. package/src/api/platform/layout/utils/bounds-observer.js +0 -52
  79. package/src/api/platform/layout/utils/view-overlay.d.ts +0 -35
  80. package/src/api/platform/layout/utils/view-overlay.js +0 -49
  81. package/src/transport/fin_store.d.ts +0 -4
  82. package/src/transport/fin_store.js +0 -16
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  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");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _Transport_wire;
13
+ var _Transport_wire, _Transport_fin;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.Transport = void 0;
16
16
  const events_1 = require("events");
@@ -18,6 +18,7 @@ const wire_1 = require("./wire");
18
18
  const transport_errors_1 = require("./transport-errors");
19
19
  const eventAggregator_1 = require("../api/events/eventAggregator");
20
20
  const me_1 = require("../api/me");
21
+ const errors_1 = require("../util/errors");
21
22
  class Transport extends events_1.EventEmitter {
22
23
  constructor(WireType, environment, config) {
23
24
  super();
@@ -26,6 +27,8 @@ class Transport extends events_1.EventEmitter {
26
27
  this.eventAggregator = new eventAggregator_1.default();
27
28
  this.messageHandlers = [this.eventAggregator.dispatchEvent];
28
29
  _Transport_wire.set(this, void 0);
30
+ // Typing as unknown to avoid circular dependency, should not be used directly.
31
+ _Transport_fin.set(this, void 0);
29
32
  this.connectSync = () => {
30
33
  const wire = __classPrivateFieldGet(this, _Transport_wire, "f");
31
34
  wire.connectSync();
@@ -40,8 +43,8 @@ class Transport extends events_1.EventEmitter {
40
43
  this.sendRaw = __classPrivateFieldGet(this, _Transport_wire, "f").send.bind(__classPrivateFieldGet(this, _Transport_wire, "f"));
41
44
  this.registerMessageHandler(this.handleMessage.bind(this));
42
45
  __classPrivateFieldGet(this, _Transport_wire, "f").on('disconnected', () => {
43
- for (const [, { reject }] of this.wireListeners) {
44
- reject('Remote connection has closed');
46
+ for (const [, { handleNack }] of this.wireListeners) {
47
+ handleNack({ reason: 'Remote connection has closed' });
45
48
  }
46
49
  this.wireListeners.clear();
47
50
  this.emit('disconnected');
@@ -50,6 +53,18 @@ class Transport extends events_1.EventEmitter {
50
53
  const entityType = this.environment.getCurrentEntityType();
51
54
  this.me = (0, me_1.getBaseMe)(entityType, uuid, name);
52
55
  }
56
+ getFin() {
57
+ if (!__classPrivateFieldGet(this, _Transport_fin, "f")) {
58
+ throw new Error("No Fin object registered for this transport");
59
+ }
60
+ return __classPrivateFieldGet(this, _Transport_fin, "f");
61
+ }
62
+ registerFin(_fin) {
63
+ if (__classPrivateFieldGet(this, _Transport_fin, "f")) {
64
+ throw new Error("Fin object has already been registered for this transport");
65
+ }
66
+ __classPrivateFieldSet(this, _Transport_fin, _fin, "f");
67
+ }
53
68
  shutdown() {
54
69
  const wire = __classPrivateFieldGet(this, _Transport_wire, "f");
55
70
  return wire.shutdown();
@@ -95,20 +110,33 @@ class Transport extends events_1.EventEmitter {
95
110
  throw new transport_errors_1.RuntimeError(requestAuthRet.payload);
96
111
  }
97
112
  }
98
- sendAction(action, payload = {}, uncorrelated = false
99
- // specialResponse type is only used for 'requestAuthorization'
100
- ) {
101
- return new Promise((resolve, reject) => {
102
- const id = this.environment.getNextMessageId();
113
+ sendAction(action, payload = {}, uncorrelated = false) {
114
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
115
+ let cancel = () => { };
116
+ // We want the callsite from the caller of this function, not from here.
117
+ const callSites = transport_errors_1.RuntimeError.getCallSite(1);
118
+ const messageId = this.environment.getNextMessageId();
119
+ const prom = new Promise((resolve, reject) => {
120
+ cancel = reject;
103
121
  const msg = {
104
122
  action,
105
123
  payload,
106
- messageId: id
124
+ messageId
107
125
  };
108
126
  const wire = __classPrivateFieldGet(this, _Transport_wire, "f");
109
- this.addWireListener(id, resolve, reject, uncorrelated);
127
+ this.addWireListener(messageId, resolve, (payload) => this.nackHandler(payload, reject, callSites), uncorrelated);
110
128
  return wire.send(msg).catch(reject);
111
129
  });
130
+ return Object.assign(prom, { cancel, messageId });
131
+ }
132
+ nackHandler(payloadOrMessage, reject, callSites) {
133
+ if (typeof payloadOrMessage === 'string') {
134
+ // NOTE: this is for backwards compatibility to support plain string rejections
135
+ reject(payloadOrMessage);
136
+ }
137
+ else {
138
+ reject(new transport_errors_1.RuntimeError(payloadOrMessage, callSites));
139
+ }
112
140
  }
113
141
  ferryAction(origData) {
114
142
  return new Promise((resolve, reject) => {
@@ -120,22 +148,22 @@ class Transport extends events_1.EventEmitter {
120
148
  const wire = __classPrivateFieldGet(this, _Transport_wire, "f");
121
149
  return wire
122
150
  .send(origData)
123
- .then(() => this.addWireListener(id, resolver, reject, false))
151
+ .then(() => this.addWireListener(id, resolver, (payload) => this.nackHandler(payload, reject), false))
124
152
  .catch(reject);
125
153
  });
126
154
  }
127
155
  registerMessageHandler(handler) {
128
156
  this.messageHandlers.push(handler);
129
157
  }
130
- addWireListener(id, resolve, reject, uncorrelated) {
158
+ addWireListener(id, resolve, handleNack, uncorrelated) {
131
159
  if (uncorrelated) {
132
160
  this.uncorrelatedListener = resolve;
133
161
  }
134
162
  else if (this.wireListeners.has(id)) {
135
- reject(new transport_errors_1.DuplicateCorrelationError(String(id)));
163
+ handleNack({ reason: 'Duplicate handler id', error: (0, errors_1.errorToPOJO)(new transport_errors_1.DuplicateCorrelationError(String(id))) });
136
164
  }
137
165
  else {
138
- this.wireListeners.set(id, { resolve, reject });
166
+ this.wireListeners.set(id, { resolve, handleNack });
139
167
  }
140
168
  // Timeout and reject()?
141
169
  }
@@ -161,23 +189,23 @@ class Transport extends events_1.EventEmitter {
161
189
  else {
162
190
  // We just checked for existence above
163
191
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
164
- const { resolve, reject } = this.wireListeners.get(id);
192
+ const { resolve, handleNack } = this.wireListeners.get(id);
165
193
  if (data.action !== 'ack') {
166
- reject(new transport_errors_1.NoAckError(data.action));
194
+ handleNack({ reason: 'Did not receive ack action', error: (0, errors_1.errorToPOJO)(new transport_errors_1.NoAckError(data.action)) });
167
195
  }
168
196
  else if (!('payload' in data)) {
169
197
  // I'm not sure when this code would actually run, but passing in something that doeesn't have a reason to the runtimeerror constructor will not end well.
170
198
  // @ts-expect-error
171
199
  if (typeof data.reason === 'string') {
172
- reject(new transport_errors_1.RuntimeError(data));
200
+ handleNack(data);
173
201
  }
174
202
  else {
175
203
  console.warn('Received invalid response from core', data);
176
- reject(new Error('Invalid response'));
204
+ handleNack({ reason: 'invalid response shape' });
177
205
  }
178
206
  }
179
207
  else if (!data.payload.success) {
180
- reject(new transport_errors_1.RuntimeError(data.payload));
208
+ handleNack(data.payload);
181
209
  }
182
210
  else {
183
211
  resolve.call(null, data);
@@ -188,4 +216,4 @@ class Transport extends events_1.EventEmitter {
188
216
  }
189
217
  }
190
218
  exports.Transport = Transport;
191
- _Transport_wire = new WeakMap();
219
+ _Transport_wire = new WeakMap(), _Transport_fin = new WeakMap();
@@ -1,6 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createRelayedDispatch = exports.relayChannelClientApi = void 0;
4
+ const EXPECTED_ERRORS = [
5
+ 'no longer connected',
6
+ 'RTCDataChannel closed unexpectedly',
7
+ 'The client you are trying to dispatch from is disconnected from the target provider',
8
+ ];
9
+ // Checks possible error messages that we want to trap, client error message can originate
10
+ // from ChannelProvider::dispatch OR ClassicStrategy::closeEndpoint OR RTCEndPoint::dataChannel::onclose
11
+ const isDisconnectedError = (errorMsg) => {
12
+ return EXPECTED_ERRORS.some(e => errorMsg.includes(e));
13
+ };
4
14
  /**
5
15
  * @internal
6
16
  * Create a channel relay for a given channel exposition, allowing a single provider to route
@@ -27,7 +37,7 @@ const createRelayedDispatch = (client, target, relayId, relayErrorMsg) => async
27
37
  });
28
38
  }
29
39
  catch (e) {
30
- if (e.message.includes('no longer connected') && relayErrorMsg) {
40
+ if (isDisconnectedError(e.message) && relayErrorMsg) {
31
41
  throw new Error(relayErrorMsg);
32
42
  }
33
43
  ;
@@ -4,6 +4,7 @@
4
4
  export type ErrorPlainObject = {
5
5
  stack?: string;
6
6
  message: string;
7
+ name?: string;
7
8
  toString(): string;
8
9
  };
9
10
  export declare function errorToPOJO(error: Error): ErrorPlainObject;
@@ -4,6 +4,7 @@ exports.errorToPOJO = void 0;
4
4
  function errorToPOJO(error) {
5
5
  return {
6
6
  stack: error.stack,
7
+ name: error.name,
7
8
  message: error.message,
8
9
  toString: error.toString
9
10
  };
@@ -14,3 +14,21 @@ export declare class Lazy<T> {
14
14
  */
15
15
  getValue(): T;
16
16
  }
17
+ /**
18
+ * Handy class for managing asynchronous dependencies of classes.
19
+ *
20
+ * Will call asynchronous producer only after `getValue` is called. If the
21
+ * deferred code errors, we can try it again by re-calling `getValue` after
22
+ * the promise rejects.
23
+ */
24
+ export declare class AsyncRetryableLazy<T> {
25
+ private producerFn;
26
+ constructor(producerFn: () => Promise<T>);
27
+ private promise?;
28
+ /**
29
+ * Lazily get the value returned by the async producer.
30
+ *
31
+ * @returns The value returned from the producer function
32
+ */
33
+ getValue(): Promise<T>;
34
+ }
package/src/util/lazy.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Lazy = void 0;
3
+ exports.AsyncRetryableLazy = exports.Lazy = void 0;
4
4
  /**
5
5
  * Handy class for managing asynchronous dependencies of classes.
6
6
  *
@@ -24,3 +24,31 @@ class Lazy {
24
24
  }
25
25
  }
26
26
  exports.Lazy = Lazy;
27
+ /**
28
+ * Handy class for managing asynchronous dependencies of classes.
29
+ *
30
+ * Will call asynchronous producer only after `getValue` is called. If the
31
+ * deferred code errors, we can try it again by re-calling `getValue` after
32
+ * the promise rejects.
33
+ */
34
+ class AsyncRetryableLazy {
35
+ // eslint-disable-next-line
36
+ constructor(producerFn) {
37
+ this.producerFn = producerFn;
38
+ }
39
+ /**
40
+ * Lazily get the value returned by the async producer.
41
+ *
42
+ * @returns The value returned from the producer function
43
+ */
44
+ async getValue() {
45
+ if (!this.promise) {
46
+ this.promise = this.producerFn().catch((e) => {
47
+ delete this.promise;
48
+ throw e;
49
+ });
50
+ }
51
+ return this.promise;
52
+ }
53
+ }
54
+ exports.AsyncRetryableLazy = AsyncRetryableLazy;
@@ -1,4 +1,4 @@
1
- export default class RefCoutner {
1
+ export declare class RefCounter {
2
2
  topicRefMap: Map<any, any>;
3
3
  incRefCount(key: string): number;
4
4
  decRefCount(key: string): number;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- class RefCoutner {
3
+ exports.RefCounter = void 0;
4
+ class RefCounter {
4
5
  constructor() {
5
6
  this.topicRefMap = new Map();
6
7
  }
@@ -48,4 +49,4 @@ class RefCoutner {
48
49
  return isLastRef ? lastAction() : nonLastAction();
49
50
  }
50
51
  }
51
- exports.default = RefCoutner;
52
+ exports.RefCounter = RefCounter;
@@ -1,30 +0,0 @@
1
- import { ViewOverlay } from '../utils/view-overlay';
2
- export type SplitterItem = GoldenLayout.ContentItem & {
3
- viewEventsAdded: boolean;
4
- isVertical: boolean;
5
- };
6
- /**
7
- * Utility class for managing Golden Layout splitter drag interactions.
8
- * @ignore
9
- */
10
- export declare class SplitterController {
11
- private readonly viewOverlay;
12
- constructor(viewOverlay: ViewOverlay);
13
- private teardown?;
14
- private tryTeardown;
15
- /**
16
- * Disables the pointer events on the splitters, preventing them from being dragged.
17
- */
18
- preventSplitterResize: () => void;
19
- /**
20
- * Ends a splitter drag move, if one is in progress.
21
- */
22
- endMove: () => Promise<void>;
23
- /**
24
- * Initialises a splitter drag move, rendering a view on top of the splitter
25
- * to allow it to render on top of the views within a layout (as they will always
26
- * have a higher z-index to the platform window itself).
27
- * @param splitterItem The Golden Layout splitter item that is currently being dragged.
28
- */
29
- startMove: (splitterItem: SplitterItem) => Promise<void>;
30
- }
@@ -1,83 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SplitterController = void 0;
4
- const bounds_observer_1 = require("../utils/bounds-observer");
5
- const applyBoundsOffset = (bounds, offsets = {}) => {
6
- const sum = (bound, offset) => {
7
- return bound + (offset || 0);
8
- };
9
- return {
10
- left: sum(bounds.left, offsets.left),
11
- top: sum(bounds.top, offsets.top),
12
- width: sum(bounds.width, offsets.width),
13
- height: sum(bounds.height, offsets.height)
14
- };
15
- };
16
- /**
17
- * Utility class for managing Golden Layout splitter drag interactions.
18
- * @ignore
19
- */
20
- class SplitterController {
21
- // eslint-disable-next-line
22
- constructor(viewOverlay) {
23
- this.viewOverlay = viewOverlay;
24
- this.tryTeardown = () => {
25
- if (this.teardown) {
26
- this.teardown();
27
- this.teardown = undefined;
28
- }
29
- };
30
- /**
31
- * Disables the pointer events on the splitters, preventing them from being dragged.
32
- */
33
- this.preventSplitterResize = () => {
34
- document.querySelectorAll('.lm_splitter').forEach((splitter) => {
35
- splitter.style.pointerEvents = 'none';
36
- });
37
- };
38
- /**
39
- * Ends a splitter drag move, if one is in progress.
40
- */
41
- this.endMove = async () => {
42
- try {
43
- this.viewOverlay.detachOverlay();
44
- this.tryTeardown();
45
- }
46
- catch (error) {
47
- throw new Error(`Failed to end splitter move: ${error.stack}`);
48
- }
49
- };
50
- /**
51
- * Initialises a splitter drag move, rendering a view on top of the splitter
52
- * to allow it to render on top of the views within a layout (as they will always
53
- * have a higher z-index to the platform window itself).
54
- * @param splitterItem The Golden Layout splitter item that is currently being dragged.
55
- */
56
- this.startMove = async (splitterItem) => {
57
- try {
58
- if (this.teardown) {
59
- console.warn('Splitter move started before other move has been torn down.');
60
- this.tryTeardown();
61
- }
62
- const splitterDiv = splitterItem.element.get(0);
63
- const { backgroundColor } = getComputedStyle(splitterDiv);
64
- const initialVisibility = splitterDiv.style.visibility;
65
- splitterDiv.style.visibility = 'hidden';
66
- const onBoundsChange = (bounds) => {
67
- const offsetBounds = applyBoundsOffset(bounds, { height: splitterItem.isVertical ? 0 : 2 });
68
- this.viewOverlay.renderOverlay(offsetBounds);
69
- };
70
- await this.viewOverlay.setStyle({ backgroundColor });
71
- const teardownBoundsObserver = (0, bounds_observer_1.observeBounds)(splitterDiv, onBoundsChange);
72
- this.teardown = () => {
73
- teardownBoundsObserver();
74
- splitterDiv.style.visibility = initialVisibility;
75
- };
76
- }
77
- catch (error) {
78
- throw new Error(`Failed to start splitter move: ${error.stack}`);
79
- }
80
- };
81
- }
82
- }
83
- exports.SplitterController = SplitterController;
@@ -1,58 +0,0 @@
1
- import type * as OpenFin from '../../../../OpenFin';
2
- import { ViewOverlay } from '../utils/view-overlay';
3
- import { View } from '../../../view';
4
- /**
5
- * Set of apis used to facilitate tab drag interactions without needing to hide views.
6
- * @ignore
7
- */
8
- export declare class TabDragController {
9
- private readonly viewOverlay;
10
- constructor(viewOverlay: ViewOverlay);
11
- private dropZonePreview?;
12
- /**
13
- *
14
- * When a tab is dragged out of a stack, it will need to be hidden from the stack.
15
- *
16
- * Additionally, if there is a new view to show in the stack, it will be shown at the position specified by
17
- * containerBounds
18
- *
19
- * As drag interactions can under extreme circumstances complete before this chain of promises has completed,
20
- * we need to pass in a isDragging() function which returns whether the drag is in progress.
21
- * This allows us to cancel any layout affecting operations.
22
- *
23
- * @param draggingView The view which is currently being dragged
24
- * @param isLastViewInWindow Whether the draggin view is the last view in a window or not. If false, the dragging view will not hide.
25
- * @param isDragging A function which returns true if the drag is still in progress. As we chain some async calls here, we want to avoid
26
- * modifying any views if the drag has completed (as the post drag procedure will have taken care of it.)
27
- * @param containerBounds The bounds of the container of the view to be shown in the stack
28
- * @param nextView The view which has become active after dragging the draggingView out.
29
- */
30
- handleTabStackActiveView: (draggingView: View, isLastViewInWindow: boolean, isDragging: () => boolean, containerBounds?: OpenFin.Bounds, nextView?: View) => Promise<void>;
31
- /**
32
- * Extracts the border and backgroundColor css values from the drop zone preview,
33
- * and sets the viewOverlay to match them.
34
- */
35
- inheritStyles: () => Promise<void>;
36
- /**
37
- * Called when a tab drag interaction is started from the current window (not when it enters the window).
38
- *
39
- * Sets all views in the platform to ignore mouse events so that they can pass through to the golden-layout
40
- * document whilst remaining visible.
41
- */
42
- startDrag: () => Promise<void>;
43
- /**
44
- * Called when a tab drag interaction which was started from the current window ends.
45
- *
46
- * Disables the click through setting on every view in the platform.
47
- */
48
- endDrag: () => Promise<void>;
49
- private disposeObserve?;
50
- disposeOverlayObserver: () => void;
51
- /**
52
- * Observes a golden-layout drop zone preview in order to render a BrowserView
53
- * overlay whenever a tab is dragged over a droppable region.
54
- * @param dropZonePreview The drop zone preview element created by Golden Layout in order to highlight
55
- * droppable regions of the UI.
56
- */
57
- observeOverlay: (dropZonePreview: HTMLElement) => Promise<void>;
58
- }
@@ -1,124 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TabDragController = void 0;
4
- const bounds_observer_1 = require("../utils/bounds-observer");
5
- /**
6
- * Set of apis used to facilitate tab drag interactions without needing to hide views.
7
- * @ignore
8
- */
9
- class TabDragController {
10
- // eslint-disable-next-line
11
- constructor(viewOverlay) {
12
- this.viewOverlay = viewOverlay;
13
- /**
14
- *
15
- * When a tab is dragged out of a stack, it will need to be hidden from the stack.
16
- *
17
- * Additionally, if there is a new view to show in the stack, it will be shown at the position specified by
18
- * containerBounds
19
- *
20
- * As drag interactions can under extreme circumstances complete before this chain of promises has completed,
21
- * we need to pass in a isDragging() function which returns whether the drag is in progress.
22
- * This allows us to cancel any layout affecting operations.
23
- *
24
- * @param draggingView The view which is currently being dragged
25
- * @param isLastViewInWindow Whether the draggin view is the last view in a window or not. If false, the dragging view will not hide.
26
- * @param isDragging A function which returns true if the drag is still in progress. As we chain some async calls here, we want to avoid
27
- * modifying any views if the drag has completed (as the post drag procedure will have taken care of it.)
28
- * @param containerBounds The bounds of the container of the view to be shown in the stack
29
- * @param nextView The view which has become active after dragging the draggingView out.
30
- */
31
- this.handleTabStackActiveView = async (draggingView, isLastViewInWindow, isDragging, containerBounds, nextView) => {
32
- if (this.dropZonePreview) {
33
- if (nextView && containerBounds) {
34
- if (isDragging()) {
35
- await (nextView === null || nextView === void 0 ? void 0 : nextView.show());
36
- }
37
- if (isDragging()) {
38
- await (nextView === null || nextView === void 0 ? void 0 : nextView.setBounds(containerBounds));
39
- }
40
- }
41
- if (isDragging() && !isLastViewInWindow) {
42
- await draggingView.hide();
43
- }
44
- }
45
- };
46
- /**
47
- * Extracts the border and backgroundColor css values from the drop zone preview,
48
- * and sets the viewOverlay to match them.
49
- */
50
- this.inheritStyles = async () => {
51
- if (this.dropZonePreview) {
52
- const { border, backgroundColor } = getComputedStyle(this.dropZonePreview);
53
- await this.viewOverlay.setStyle({ border, backgroundColor });
54
- }
55
- };
56
- /**
57
- * Called when a tab drag interaction is started from the current window (not when it enters the window).
58
- *
59
- * Sets all views in the platform to ignore mouse events so that they can pass through to the golden-layout
60
- * document whilst remaining visible.
61
- */
62
- this.startDrag = async () => {
63
- await this.viewOverlay.setIgnoreViewMouseEvents(true);
64
- };
65
- /**
66
- * Called when a tab drag interaction which was started from the current window ends.
67
- *
68
- * Disables the click through setting on every view in the platform.
69
- */
70
- this.endDrag = async () => {
71
- await this.viewOverlay.setIgnoreViewMouseEvents(false);
72
- };
73
- this.disposeOverlayObserver = () => {
74
- if (this.disposeObserve) {
75
- this.disposeObserve();
76
- }
77
- this.dropZonePreview = undefined;
78
- };
79
- /**
80
- * Observes a golden-layout drop zone preview in order to render a BrowserView
81
- * overlay whenever a tab is dragged over a droppable region.
82
- * @param dropZonePreview The drop zone preview element created by Golden Layout in order to highlight
83
- * droppable regions of the UI.
84
- */
85
- this.observeOverlay = async (dropZonePreview) => {
86
- if (!this.dropZonePreview) {
87
- this.dropZonePreview = dropZonePreview;
88
- let lastBounds;
89
- dropZonePreview.style.visibility = 'hidden';
90
- const onDropAreaHighlighted = async (e) => {
91
- try {
92
- const { bounds } = e.detail;
93
- if (!lastBounds || !(0, bounds_observer_1.isDomRectEqual)(lastBounds, bounds)) {
94
- lastBounds = bounds;
95
- await this.viewOverlay.renderOverlay(bounds);
96
- }
97
- }
98
- catch (error) {
99
- console.warn('Unexpected error encountered rendering tab drag preview.', error);
100
- }
101
- };
102
- const onDropAreaHidden = async () => {
103
- try {
104
- lastBounds = undefined;
105
- await this.viewOverlay.detachOverlay();
106
- }
107
- catch (error) {
108
- console.warn('Unexpected error encountered hiding tab drag preview.', error);
109
- }
110
- };
111
- dropZonePreview.addEventListener('drop-area-highlighted', onDropAreaHighlighted);
112
- dropZonePreview.addEventListener('drop-area-hidden', onDropAreaHidden);
113
- this.disposeObserve = () => {
114
- dropZonePreview.removeEventListener('drop-area-highlighted', onDropAreaHighlighted);
115
- dropZonePreview.removeEventListener('drop-area-hidden', onDropAreaHidden);
116
- };
117
- }
118
- else {
119
- console.warn('Tried to observe a drop zone overlay without disposing the previous.');
120
- }
121
- };
122
- }
123
- }
124
- exports.TabDragController = TabDragController;
@@ -1,19 +0,0 @@
1
- export declare const isDomRectEqual: (a: DOMRect, b: DOMRect) => boolean;
2
- /**
3
- * Observes the bounding client box rectangle of the given element for changes.
4
- *
5
- * This solution only works for 2 scenarios, though could be updated to support more
6
- * (e.g. via polling).
7
- *
8
- * MutationObserver will only pick up changes to bounds if they are specified via fixed
9
- * style rules in the element's attribtues.
10
- *
11
- * ResizeObserver will pick up all changes to an element's width and height but will not capture
12
- * any changes to position.
13
- *
14
- * @param element The element to observe the bounding box for (i.e. position, width, height)
15
- * @param onChange Called every time the bounding box changes.
16
- * @returns Function which disposes the observers when invoked.
17
- * @ignore
18
- */
19
- export declare const observeBounds: (element: Element, onChange: (bounds: DOMRect) => Promise<void> | void) => (() => void);
@@ -1,52 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.observeBounds = exports.isDomRectEqual = void 0;
4
- const isDomRectEqual = (a, b) => {
5
- if (a.top !== b.top ||
6
- a.left !== b.left ||
7
- a.width !== b.width ||
8
- a.height !== b.height ||
9
- a.x !== b.x ||
10
- a.y !== b.y) {
11
- return false;
12
- }
13
- return true;
14
- };
15
- exports.isDomRectEqual = isDomRectEqual;
16
- /**
17
- * Observes the bounding client box rectangle of the given element for changes.
18
- *
19
- * This solution only works for 2 scenarios, though could be updated to support more
20
- * (e.g. via polling).
21
- *
22
- * MutationObserver will only pick up changes to bounds if they are specified via fixed
23
- * style rules in the element's attribtues.
24
- *
25
- * ResizeObserver will pick up all changes to an element's width and height but will not capture
26
- * any changes to position.
27
- *
28
- * @param element The element to observe the bounding box for (i.e. position, width, height)
29
- * @param onChange Called every time the bounding box changes.
30
- * @returns Function which disposes the observers when invoked.
31
- * @ignore
32
- */
33
- const observeBounds = (element, onChange) => {
34
- let lastBounds;
35
- const checkBounds = async () => {
36
- const currentBounds = element.getBoundingClientRect();
37
- if (!lastBounds || !(0, exports.isDomRectEqual)(lastBounds, currentBounds)) {
38
- lastBounds = currentBounds;
39
- await onChange(element.getBoundingClientRect());
40
- }
41
- };
42
- const resizeObserver = new ResizeObserver(() => checkBounds());
43
- const mutationObserver = new MutationObserver(() => checkBounds());
44
- resizeObserver.observe(element, { box: 'content-box' });
45
- mutationObserver.observe(element, { attributes: true, attributeFilter: ['style'] });
46
- checkBounds();
47
- return () => {
48
- resizeObserver.disconnect();
49
- mutationObserver.disconnect();
50
- };
51
- };
52
- exports.observeBounds = observeBounds;