@deephaven/golden-layout 0.43.0 → 0.44.0

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 (79) hide show
  1. package/css/goldenlayout-base.css +1 -1
  2. package/css/goldenlayout-base.css.map +1 -1
  3. package/css/goldenlayout-dark-theme.css +1 -1
  4. package/css/goldenlayout-dark-theme.css.map +1 -1
  5. package/dist/GoldenLayout.module.css +1 -0
  6. package/dist/GoldenLayout.module.css.map +1 -0
  7. package/dist/GoldenLayoutThemeExport.js +6 -0
  8. package/dist/GoldenLayoutThemeExport.js.map +1 -0
  9. package/dist/LayoutManager.js +1001 -0
  10. package/dist/LayoutManager.js.map +1 -0
  11. package/dist/base.js +16 -0
  12. package/dist/base.js.map +1 -0
  13. package/dist/config/Config.js +42 -0
  14. package/dist/config/Config.js.map +1 -0
  15. package/dist/config/ItemConfig.js +14 -0
  16. package/dist/config/ItemConfig.js.map +1 -0
  17. package/dist/config/index.js +3 -0
  18. package/dist/config/index.js.map +1 -0
  19. package/dist/container/ItemContainer.js +199 -0
  20. package/dist/container/ItemContainer.js.map +1 -0
  21. package/dist/container/index.js +3 -0
  22. package/dist/container/index.js.map +1 -0
  23. package/dist/controls/BrowserPopout.js +250 -0
  24. package/dist/controls/BrowserPopout.js.map +1 -0
  25. package/dist/controls/DragProxy.js +204 -0
  26. package/dist/controls/DragProxy.js.map +1 -0
  27. package/dist/controls/DragSource.js +52 -0
  28. package/dist/controls/DragSource.js.map +1 -0
  29. package/dist/controls/DragSourceFromEvent.js +71 -0
  30. package/dist/controls/DragSourceFromEvent.js.map +1 -0
  31. package/dist/controls/DropTargetIndicator.js +27 -0
  32. package/dist/controls/DropTargetIndicator.js.map +1 -0
  33. package/dist/controls/Header.js +736 -0
  34. package/dist/controls/Header.js.map +1 -0
  35. package/dist/controls/HeaderButton.js +22 -0
  36. package/dist/controls/HeaderButton.js.map +1 -0
  37. package/dist/controls/Splitter.js +49 -0
  38. package/dist/controls/Splitter.js.map +1 -0
  39. package/dist/controls/Tab.js +225 -0
  40. package/dist/controls/Tab.js.map +1 -0
  41. package/dist/controls/index.js +10 -0
  42. package/dist/controls/index.js.map +1 -0
  43. package/dist/declaration.d.js +2 -0
  44. package/dist/declaration.d.js.map +1 -0
  45. package/dist/errors/ConfigurationError.js +14 -0
  46. package/dist/errors/ConfigurationError.js.map +1 -0
  47. package/dist/errors/index.js +2 -0
  48. package/dist/errors/index.js.map +1 -0
  49. package/dist/index.js +11 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/items/AbstractContentItem.js +565 -0
  52. package/dist/items/AbstractContentItem.js.map +1 -0
  53. package/dist/items/Component.js +80 -0
  54. package/dist/items/Component.js.map +1 -0
  55. package/dist/items/Root.js +100 -0
  56. package/dist/items/Root.js.map +1 -0
  57. package/dist/items/RowOrColumn.js +488 -0
  58. package/dist/items/RowOrColumn.js.map +1 -0
  59. package/dist/items/Stack.js +479 -0
  60. package/dist/items/Stack.js.map +1 -0
  61. package/dist/items/index.js +8 -0
  62. package/dist/items/index.js.map +1 -0
  63. package/dist/utils/BubblingEvent.js +17 -0
  64. package/dist/utils/BubblingEvent.js.map +1 -0
  65. package/dist/utils/ConfigMinifier.js +147 -0
  66. package/dist/utils/ConfigMinifier.js.map +1 -0
  67. package/dist/utils/DragListener.js +125 -0
  68. package/dist/utils/DragListener.js.map +1 -0
  69. package/dist/utils/EventEmitter.js +117 -0
  70. package/dist/utils/EventEmitter.js.map +1 -0
  71. package/dist/utils/EventHub.js +108 -0
  72. package/dist/utils/EventHub.js.map +1 -0
  73. package/dist/utils/ReactComponentHandler.js +136 -0
  74. package/dist/utils/ReactComponentHandler.js.map +1 -0
  75. package/dist/utils/index.js +8 -0
  76. package/dist/utils/index.js.map +1 -0
  77. package/dist/utils/utils.js +65 -0
  78. package/dist/utils/utils.js.map +1 -0
  79. package/package.json +3 -3
@@ -0,0 +1,1001 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
3
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
4
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
6
+ import $ from 'jquery';
7
+ import lm from "./base.js";
8
+ import { defaultConfig } from "./config/index.js";
9
+ import { BrowserPopout, DragSource, DragSourceFromEvent, DropTargetIndicator } from "./controls/index.js";
10
+ import { ConfigurationError } from "./errors/index.js";
11
+ import { AbstractContentItem, isStack, Component, Root, RowOrColumn, Stack } from "./items/index.js";
12
+ import { minifyConfig, unminifyConfig, EventEmitter, EventHub, ReactComponentHandler, getQueryStringParam, getUniqueId, stripTags } from "./utils/index.js";
13
+ /**
14
+ * The main class that will be exposed as GoldenLayout.
15
+ *
16
+ * @param config
17
+ * @param container Can be a jQuery selector string or a Dom element. Defaults to body
18
+ */
19
+ export class LayoutManager extends EventEmitter {
20
+ /**
21
+ * Hook that allows to access private classes
22
+ */
23
+
24
+ /**
25
+ * Takes a GoldenLayout configuration object and
26
+ * replaces its keys and values recursively with
27
+ * one letter codes
28
+ *
29
+ * @param config A GoldenLayout config object
30
+ * @returns minified config
31
+ */
32
+ static minifyConfig(config) {
33
+ return minifyConfig(config);
34
+ }
35
+
36
+ /**
37
+ * Takes a configuration Object that was previously minified
38
+ * using minifyConfig and returns its original version
39
+ *
40
+ * @param minifiedConfig
41
+ * @returns the original configuration
42
+ */
43
+ static unminifyConfig(config) {
44
+ return unminifyConfig(config);
45
+ }
46
+ constructor(config, container) {
47
+ super();
48
+ _defineProperty(this, "isInitialised", false);
49
+ _defineProperty(this, "_isFullPage", false);
50
+ _defineProperty(this, "_resizeTimeoutId", void 0);
51
+ _defineProperty(this, "_components", {
52
+ 'lm-react-component': ReactComponentHandler
53
+ });
54
+ _defineProperty(this, "_fallbackComponent", void 0);
55
+ _defineProperty(this, "_itemAreas", []);
56
+ _defineProperty(this, "_maximisedItem", null);
57
+ _defineProperty(this, "_maximisePlaceholder", $('<div class="lm_maximise_place"></div>'));
58
+ _defineProperty(this, "_creationTimeoutPassed", false);
59
+ _defineProperty(this, "_subWindowsCreated", false);
60
+ _defineProperty(this, "_dragSources", []);
61
+ _defineProperty(this, "_updatingColumnsResponsive", false);
62
+ _defineProperty(this, "_firstLoad", true);
63
+ _defineProperty(this, "_reactChildMap", new Map());
64
+ _defineProperty(this, "_reactChildren", null);
65
+ _defineProperty(this, "width", null);
66
+ _defineProperty(this, "height", null);
67
+ _defineProperty(this, "root", void 0);
68
+ _defineProperty(this, "openPopouts", []);
69
+ _defineProperty(this, "selectedItem", null);
70
+ _defineProperty(this, "isSubWindow", false);
71
+ _defineProperty(this, "eventHub", new EventHub(this));
72
+ _defineProperty(this, "config", void 0);
73
+ _defineProperty(this, "container", void 0);
74
+ _defineProperty(this, "_originalContainer", void 0);
75
+ _defineProperty(this, "dropTargetIndicator", null);
76
+ _defineProperty(this, "tabDropPlaceholder", $('<div class="lm_drop_tab_placeholder"></div>'));
77
+ _defineProperty(this, "_typeToItem", void 0);
78
+ this._onResize = this._onResize.bind(this);
79
+ this._onUnload = this._onUnload.bind(this);
80
+ this._windowBlur = this._windowBlur.bind(this);
81
+ this._windowFocus = this._windowFocus.bind(this);
82
+ this.config = this._createConfig(config);
83
+ this._originalContainer = container;
84
+ this.container = this._getContainer();
85
+ if (this.isSubWindow) {
86
+ $('body').css('visibility', 'hidden');
87
+ }
88
+ this._typeToItem = {
89
+ column: RowOrColumn.bind(this, true),
90
+ row: RowOrColumn.bind(this, false),
91
+ stack: Stack,
92
+ component: Component
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Register a component with the layout manager. If a configuration node
98
+ * of type component is reached it will look up componentName and create the
99
+ * associated component
100
+ *
101
+ * {
102
+ * type: "component",
103
+ * componentName: "EquityNewsFeed",
104
+ * componentState: { "feedTopic": "us-bluechips" }
105
+ * }
106
+ *
107
+ * @param name
108
+ * @param constructor
109
+ * @returns cleanup function to deregister component
110
+ */
111
+ registerComponent(name, constructor) {
112
+ if (typeof constructor !== 'function' && (constructor == null || constructor.render == null || typeof constructor.render !== 'function')) {
113
+ throw new Error('Please register a constructor function');
114
+ }
115
+ if (this._components[name] !== undefined) {
116
+ throw new Error('Component ' + name + ' is already registered');
117
+ }
118
+ this._components[name] = constructor;
119
+ var cleanup = () => {
120
+ if (this._components[name] === undefined) {
121
+ throw new Error('Component ' + name + ' is not registered');
122
+ }
123
+ delete this._components[name];
124
+ };
125
+ return cleanup;
126
+ }
127
+
128
+ /**
129
+ * Set a fallback component to be rendered in place of unregistered components
130
+ * @param constructor
131
+ */
132
+ setFallbackComponent(constructor) {
133
+ this._fallbackComponent = constructor;
134
+ }
135
+
136
+ /**
137
+ * Creates a layout configuration object based on the the current state
138
+ * @param root
139
+ * @returns GoldenLayout configuration
140
+ */
141
+ toConfig(root) {
142
+ if (this.isInitialised === false) {
143
+ throw new Error("Can't create config, layout not yet initialised");
144
+ }
145
+ if (root && !(root instanceof AbstractContentItem)) {
146
+ throw new Error('Root must be a ContentItem');
147
+ }
148
+
149
+ /*
150
+ * settings & labels
151
+ */
152
+ var config = {
153
+ settings: _objectSpread({}, this.config.settings),
154
+ dimensions: _objectSpread({}, this.config.dimensions),
155
+ labels: _objectSpread({}, this.config.labels),
156
+ content: []
157
+ };
158
+
159
+ /*
160
+ * Content
161
+ */
162
+ var next = function next(configNode, item) {
163
+ for (var _key in item.config) {
164
+ if (_key !== 'content') {
165
+ configNode[_key] = item.config[_key];
166
+ }
167
+ }
168
+ if (configNode.componentName === 'lm-react-component') {
169
+ // We change the type in `createContentItem`, so change it back here
170
+ configNode.type = 'react-component';
171
+ }
172
+ if (item.contentItems.length) {
173
+ configNode.content = [];
174
+ for (var i = 0; i < item.contentItems.length; i++) {
175
+ configNode.content[i] = {};
176
+ next(configNode.content[i], item.contentItems[i]);
177
+ }
178
+ }
179
+ };
180
+ if (root) {
181
+ next(config, {
182
+ contentItems: [root]
183
+ });
184
+ } else {
185
+ next(config, this.root);
186
+ }
187
+
188
+ /*
189
+ * Retrieve config for subwindows
190
+ */
191
+ this._$reconcilePopoutWindows();
192
+ config.openPopouts = [];
193
+ for (var i = 0; i < this.openPopouts.length; i++) {
194
+ config.openPopouts.push(this.openPopouts[i].toConfig());
195
+ }
196
+
197
+ /*
198
+ * Add maximised item
199
+ */
200
+ config.maximisedItemId = this._maximisedItem ? '__glMaximised' : undefined;
201
+ return config;
202
+ }
203
+
204
+ /**
205
+ * Returns a previously registered component
206
+ * @param name The name used
207
+ */
208
+ getComponent(name) {
209
+ return this._components[name];
210
+ }
211
+
212
+ /**
213
+ * Returns a fallback component to render in place of unregistered components
214
+ *
215
+ * @public
216
+ *
217
+ * @returns {Function}
218
+ */
219
+ getFallbackComponent() {
220
+ return this._fallbackComponent;
221
+ }
222
+
223
+ /**
224
+ * Creates the actual layout. Must be called after all initial components
225
+ * are registered. Recurses through the configuration and sets up
226
+ * the item tree.
227
+ *
228
+ * If called before the document is ready it adds itself as a listener
229
+ * to the document.ready event
230
+ */
231
+ init() {
232
+ /**
233
+ * Create the popout windows straight away. If popouts are blocked
234
+ * an error is thrown on the same 'thread' rather than a timeout and can
235
+ * be caught. This also prevents any further initilisation from taking place.
236
+ */
237
+ if (this._subWindowsCreated === false) {
238
+ this._createSubWindows();
239
+ this._subWindowsCreated = true;
240
+ }
241
+
242
+ /**
243
+ * If the document isn't ready yet, wait for it.
244
+ */
245
+ if (document.readyState === 'loading' || document.body === null) {
246
+ $(document).ready(this.init.bind(this));
247
+ return;
248
+ }
249
+
250
+ /**
251
+ * If this is a subwindow, wait a few milliseconds for the original
252
+ * page's js calls to be executed, then replace the bodies content
253
+ * with GoldenLayout
254
+ */
255
+ if (this.isSubWindow === true && this._creationTimeoutPassed === false) {
256
+ setTimeout(this.init.bind(this), 7);
257
+ this._creationTimeoutPassed = true;
258
+ return;
259
+ }
260
+ if (this.isSubWindow === true) {
261
+ this._adjustToWindowMode();
262
+ }
263
+ this._setContainer();
264
+ this.dropTargetIndicator = new DropTargetIndicator();
265
+ this.updateSize();
266
+ this._create(this.config);
267
+ this._bindEvents();
268
+ this.isInitialised = true;
269
+ this._adjustColumnsResponsive();
270
+ this.emit('initialised');
271
+ }
272
+
273
+ /**
274
+ * Adds a react child to the layout manager
275
+ * @param id Unique panel id
276
+ * @param element The React element
277
+ */
278
+ addReactChild(id, element) {
279
+ this._reactChildMap.set(id, element);
280
+ this._reactChildren = [...this._reactChildMap.values()];
281
+ this.emit('reactChildrenChanged');
282
+ }
283
+
284
+ /**
285
+ * Removes a react child from the layout manager
286
+ * Only removes if the elements for the panelId has not been replaced by a different element
287
+ * @param id Unique panel id
288
+ * @param element The React element
289
+ */
290
+ removeReactChild(id, element) {
291
+ var mapElem = this._reactChildMap.get(id);
292
+ if (mapElem === element) {
293
+ // If an element was replaced it may be destroyed after the other is created
294
+ // In that case, the new element would be removed
295
+ // Make sure the element being removed is the current element associated with its id
296
+ this._reactChildMap.delete(id);
297
+ this._reactChildren = [...this._reactChildMap.values()];
298
+ this.emit('reactChildrenChanged');
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Gets the react children in the layout
304
+ *
305
+ * Used in @deephaven/dashboard to mount the react elements
306
+ * inside the app's React tree
307
+ *
308
+ * @returns The react children to mount for this layout manager
309
+ */
310
+ getReactChildren() {
311
+ return this._reactChildren;
312
+ }
313
+
314
+ /**
315
+ * Updates the layout managers size
316
+ * @param width width in pixels
317
+ * @param height height in pixels
318
+ */
319
+ updateSize(width, height) {
320
+ var _ref, _ref2;
321
+ this.width = (_ref = width !== null && width !== void 0 ? width : this.container.width()) !== null && _ref !== void 0 ? _ref : 0;
322
+ this.height = (_ref2 = height !== null && height !== void 0 ? height : this.container.height()) !== null && _ref2 !== void 0 ? _ref2 : 0;
323
+ if (this.isInitialised === true) {
324
+ this.root.callDownwards('setSize', [this.width, this.height]);
325
+ if (this._maximisedItem) {
326
+ var _this$container$width, _this$container$heigh;
327
+ this._maximisedItem.element.width((_this$container$width = this.container.width()) !== null && _this$container$width !== void 0 ? _this$container$width : 0);
328
+ this._maximisedItem.element.height((_this$container$heigh = this.container.height()) !== null && _this$container$heigh !== void 0 ? _this$container$heigh : 0);
329
+ this._maximisedItem.callDownwards('setSize');
330
+ }
331
+ this._adjustColumnsResponsive();
332
+ }
333
+ }
334
+
335
+ /**
336
+ * Destroys the LayoutManager instance itself as well as every ContentItem
337
+ * within it. After this is called nothing should be left of the LayoutManager.
338
+ */
339
+ destroy() {
340
+ var _this$dropTargetIndic;
341
+ if (this.isInitialised === false || !this.root) {
342
+ return;
343
+ }
344
+ this._onUnload();
345
+ $(window).off('resize', this._onResize);
346
+ $(window).off('unload beforeunload', this._onUnload);
347
+ $(window).off('blur.lm').off('focus.lm');
348
+ this.root.callDownwards('_$destroy', [], true);
349
+ this.root.contentItems = [];
350
+ this.tabDropPlaceholder.remove();
351
+ (_this$dropTargetIndic = this.dropTargetIndicator) === null || _this$dropTargetIndic === void 0 ? void 0 : _this$dropTargetIndic.destroy();
352
+ this.eventHub.destroy();
353
+ this._dragSources.forEach(function (dragSource) {
354
+ dragSource._dragListener.destroy();
355
+ });
356
+ this._dragSources = [];
357
+ }
358
+
359
+ /**
360
+ * Recursively creates new item tree structures based on a provided
361
+ * ItemConfiguration object
362
+ *
363
+ * @public
364
+ * @param config ItemConfig
365
+ * @param parent The item the newly created item should be a child of
366
+ *
367
+ * @returns Created item
368
+ */
369
+ createContentItem(config, parent) {
370
+ var typeErrorMsg, contentItem;
371
+ if (typeof config.type !== 'string') {
372
+ throw new ConfigurationError("Missing parameter 'type'", config);
373
+ }
374
+ if (config.type === 'react-component') {
375
+ config.type = 'component';
376
+ config.componentName = 'lm-react-component';
377
+ }
378
+ if (!this._typeToItem[config.type]) {
379
+ typeErrorMsg = "Unknown type '" + config.type + "'. " + 'Valid types are ' + Object.keys(this._typeToItem).join(',');
380
+ throw new ConfigurationError(typeErrorMsg);
381
+ }
382
+
383
+ /**
384
+ * We add an additional stack around every component that's not within a stack anyways.
385
+ */
386
+ if (
387
+ // If this is a component
388
+ config.type === 'component' &&
389
+ // and it's not already within a stack
390
+ !(parent instanceof Stack) &&
391
+ // and we have a parent
392
+ !!parent &&
393
+ // and it's not the topmost item in a new window
394
+ !(this.isSubWindow === true && parent instanceof Root)) {
395
+ config = {
396
+ type: 'stack',
397
+ width: config.width,
398
+ height: config.height,
399
+ content: [config]
400
+ };
401
+ }
402
+ contentItem = new this._typeToItem[config.type](this, config, parent);
403
+ return contentItem;
404
+ }
405
+
406
+ /**
407
+ * Creates a popout window with the specified content and dimensions
408
+ *
409
+ * @param configOrContentItem
410
+ * @param dimensions A map with width, height, left and top
411
+ * @param parentId the id of the element this item will be appended to
412
+ * when popIn is called
413
+ * @param indexInParent The position of this item within its parent element
414
+ * @returns Created popout
415
+ */
416
+ createPopout(configOrContentItem, dimensions, parentId, indexInParent) {
417
+ var config = configOrContentItem;
418
+ var configArray = [];
419
+ var isItem = configOrContentItem instanceof AbstractContentItem;
420
+ var self = this;
421
+ if (isItem) {
422
+ var _parent2;
423
+ configArray = this.toConfig(configOrContentItem).content;
424
+ parentId = getUniqueId();
425
+
426
+ /**
427
+ * If the item is the only component within a stack or for some
428
+ * other reason the only child of its parent the parent will be destroyed
429
+ * when the child is removed.
430
+ *
431
+ * In order to support this we move up the tree until we find something
432
+ * that will remain after the item is being popped out
433
+ */
434
+ var parent = configOrContentItem.parent;
435
+ var child = configOrContentItem;
436
+ while (((_parent = parent) === null || _parent === void 0 ? void 0 : _parent.contentItems.length) === 1 && !parent.isRoot) {
437
+ var _parent;
438
+ child = parent;
439
+ parent = parent.parent;
440
+ }
441
+ (_parent2 = parent) === null || _parent2 === void 0 ? void 0 : _parent2.addId(parentId);
442
+ if (indexInParent == undefined || Number.isNaN(indexInParent)) {
443
+ var _parent3;
444
+ indexInParent = (_parent3 = parent) === null || _parent3 === void 0 ? void 0 : _parent3.contentItems.indexOf(child);
445
+ }
446
+ } else {
447
+ if (!(configOrContentItem instanceof Array)) {
448
+ configArray = [configOrContentItem];
449
+ } else {
450
+ configArray = configOrContentItem;
451
+ }
452
+ }
453
+ if (!dimensions && isItem) {
454
+ var _configOrContentItem$, _configOrContentItem$2, _configOrContentItem$3;
455
+ var windowLeft = window.screenX || window.screenLeft;
456
+ var windowTop = window.screenY || window.screenTop;
457
+ var offset = (_configOrContentItem$ = configOrContentItem.element.offset()) !== null && _configOrContentItem$ !== void 0 ? _configOrContentItem$ : {
458
+ left: 0,
459
+ top: 0
460
+ };
461
+ dimensions = {
462
+ left: windowLeft + offset.left,
463
+ top: windowTop + offset.top,
464
+ width: (_configOrContentItem$2 = configOrContentItem.element.width()) !== null && _configOrContentItem$2 !== void 0 ? _configOrContentItem$2 : 0,
465
+ height: (_configOrContentItem$3 = configOrContentItem.element.height()) !== null && _configOrContentItem$3 !== void 0 ? _configOrContentItem$3 : 0
466
+ };
467
+ }
468
+ if (!dimensions && !isItem) {
469
+ dimensions = {
470
+ left: window.screenX || window.screenLeft + 20,
471
+ top: window.screenY || window.screenTop + 20,
472
+ width: 500,
473
+ height: 309
474
+ };
475
+ }
476
+ if (isItem) {
477
+ configOrContentItem.remove();
478
+ }
479
+ if (!dimensions || !parentId || indexInParent === undefined) {
480
+ return;
481
+ }
482
+ var browserPopout = new BrowserPopout(configArray, dimensions, parentId, indexInParent, this);
483
+ browserPopout.on('initialised', function () {
484
+ self.emit('windowOpened', browserPopout);
485
+ });
486
+ browserPopout.on('closed', function () {
487
+ self._$reconcilePopoutWindows();
488
+ });
489
+ this.openPopouts.push(browserPopout);
490
+ return browserPopout;
491
+ }
492
+
493
+ /**
494
+ * Attaches DragListener to any given DOM element
495
+ * and turns it into a way of creating new ContentItems
496
+ * by 'dragging' the DOM element into the layout
497
+ *
498
+ * @param element
499
+ * @param itemConfig for the new item to be created, or a function which will provide it
500
+ */
501
+ createDragSource(element, itemConfig) {
502
+ this.config.settings.constrainDragToContainer = false;
503
+ var dragSource = new DragSource(element, itemConfig, this);
504
+ this._dragSources.push(dragSource);
505
+ return dragSource;
506
+ }
507
+
508
+ /**
509
+ * Create a new item in a dragging state, given a starting mouse event to act as the initial position
510
+ *
511
+ * @param itemConfig for the new item to be created, or a function which will provide it
512
+ * @param event used as the starting position for the dragProxy
513
+ */
514
+ createDragSourceFromEvent(itemConfig, event) {
515
+ this.config.settings.constrainDragToContainer = false;
516
+ return new DragSourceFromEvent(itemConfig, this, event);
517
+ }
518
+
519
+ /**
520
+ * Programmatically selects an item. This deselects
521
+ * the currently selected item, selects the specified item
522
+ * and emits a selectionChanged event
523
+ *
524
+ * @param item
525
+ * @param _$silent Wheather to notify the item of its selection
526
+ */
527
+ selectItem(item, _$silent) {
528
+ if (this.config.settings.selectionEnabled !== true) {
529
+ throw new Error('Please set selectionEnabled to true to use this feature');
530
+ }
531
+ if (item === this.selectedItem) {
532
+ return;
533
+ }
534
+ if (this.selectedItem !== null) {
535
+ this.selectedItem.deselect();
536
+ }
537
+ if (item && _$silent !== true) {
538
+ item.select();
539
+ }
540
+ this.selectedItem = item;
541
+ this.emit('selectionChanged', item);
542
+ }
543
+
544
+ /*************************
545
+ * PACKAGE PRIVATE
546
+ *************************/
547
+ _$maximiseItem(contentItem) {
548
+ var _this$container$width2, _this$container$heigh2;
549
+ if (this._maximisedItem !== null) {
550
+ this._$minimiseItem(this._maximisedItem);
551
+ }
552
+ this._maximisedItem = contentItem;
553
+ this._maximisedItem.addId('__glMaximised');
554
+ contentItem.element.addClass('lm_maximised');
555
+ contentItem.element.after(this._maximisePlaceholder);
556
+ this.root.element.prepend(contentItem.element);
557
+ contentItem.element.width((_this$container$width2 = this.container.width()) !== null && _this$container$width2 !== void 0 ? _this$container$width2 : 0);
558
+ contentItem.element.height((_this$container$heigh2 = this.container.height()) !== null && _this$container$heigh2 !== void 0 ? _this$container$heigh2 : 0);
559
+ contentItem.callDownwards('setSize');
560
+ this._maximisedItem.emit('maximised');
561
+ this.emit('stateChanged');
562
+ }
563
+ _$minimiseItem(contentItem) {
564
+ var _contentItem$parent;
565
+ contentItem.element.removeClass('lm_maximised');
566
+ contentItem.removeId('__glMaximised');
567
+ this._maximisePlaceholder.after(contentItem.element);
568
+ this._maximisePlaceholder.remove();
569
+ (_contentItem$parent = contentItem.parent) === null || _contentItem$parent === void 0 ? void 0 : _contentItem$parent.callDownwards('setSize');
570
+ this._maximisedItem = null;
571
+ contentItem.emit('minimised');
572
+ this.emit('stateChanged');
573
+ }
574
+
575
+ /**
576
+ * This method is used to get around sandboxed iframe restrictions.
577
+ * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute
578
+ * (as is the case with codepens) the parent window is forbidden from calling certain
579
+ * methods on the child, such as window.close() or setting document.location.href.
580
+ *
581
+ * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call
582
+ * _$closeWindow on the child window's gl instance which (after a timeout to disconnect
583
+ * the invoking method from the close call) closes itself.
584
+ */
585
+ _$closeWindow() {
586
+ window.setTimeout(function () {
587
+ window.close();
588
+ }, 1);
589
+ }
590
+ _$getArea(x, y) {
591
+ var smallestSurface = Infinity;
592
+ var mathingArea = null;
593
+ for (var i = 0; i < this._itemAreas.length; i++) {
594
+ var area = this._itemAreas[i];
595
+ if (x > area.x1 && x < area.x2 && y > area.y1 && y < area.y2 && smallestSurface > area.surface) {
596
+ smallestSurface = area.surface;
597
+ mathingArea = area;
598
+ }
599
+ }
600
+ return mathingArea;
601
+ }
602
+
603
+ /**
604
+ * Creates the drop zones at the edges of the screen
605
+ */
606
+ _$createRootItemAreas() {
607
+ var areaSize = 50;
608
+ var rootArea = _objectSpread({}, this.root._$getArea());
609
+ var areas = [_objectSpread(_objectSpread({}, rootArea), {}, {
610
+ side: 'left',
611
+ x2: rootArea.x1 + areaSize
612
+ }), _objectSpread(_objectSpread({}, rootArea), {}, {
613
+ side: 'right',
614
+ x1: rootArea.x2 - areaSize
615
+ }), _objectSpread(_objectSpread({}, rootArea), {}, {
616
+ side: 'top',
617
+ y2: rootArea.y1 + areaSize
618
+ }), _objectSpread(_objectSpread({}, rootArea), {}, {
619
+ side: 'bottom',
620
+ y1: rootArea.y2 - areaSize
621
+ })];
622
+ areas.forEach(area => {
623
+ area.surface = (area.x2 - area.x1) * (area.y2 - area.y1);
624
+ });
625
+ this._itemAreas.push(...areas);
626
+ }
627
+ _$calculateItemAreas() {
628
+ var allContentItems = this._getAllContentItems();
629
+ this._itemAreas = [];
630
+
631
+ /**
632
+ * If the last item is dragged out, highlight the entire container size to
633
+ * allow to re-drop it. allContentItems[ 0 ] === this.root at this point
634
+ *
635
+ * Don't include root into the possible drop areas though otherwise since it
636
+ * will used for every gap in the layout, e.g. splitters
637
+ */
638
+ if (allContentItems.length === 1) {
639
+ this._itemAreas.push(this.root._$getArea());
640
+ return;
641
+ }
642
+ this._$createRootItemAreas();
643
+ for (var i = 0; i < allContentItems.length; i++) {
644
+ var item = allContentItems[i];
645
+ if (!isStack(item)) {
646
+ continue;
647
+ }
648
+ var area = item._$getArea();
649
+ if (area === null) {
650
+ continue;
651
+ } else if (area instanceof Array) {
652
+ this._itemAreas = this._itemAreas.concat(area);
653
+ } else {
654
+ var _area$contentItem$_co;
655
+ this._itemAreas.push(area);
656
+ var header = _objectSpread(_objectSpread({}, area), (_area$contentItem$_co = area.contentItem._contentAreaDimensions) === null || _area$contentItem$_co === void 0 ? void 0 : _area$contentItem$_co.header.highlightArea);
657
+ header.surface = (header.x2 - header.x1) * (header.y2 - header.y1);
658
+ this._itemAreas.push(header);
659
+ }
660
+ }
661
+ }
662
+
663
+ /**
664
+ * Takes a contentItem or a configuration and optionally a parent
665
+ * item and returns an initialised instance of the contentItem.
666
+ * If the contentItem is a function, it is first called
667
+ *
668
+ * @param contentItemOrConfig
669
+ * @param parent Only necessary when passing in config
670
+ */
671
+ _$normalizeContentItem(contentItemOrConfig, parent) {
672
+ if (!contentItemOrConfig) {
673
+ throw new Error('No content item defined');
674
+ }
675
+ if (typeof contentItemOrConfig === 'function') {
676
+ contentItemOrConfig = contentItemOrConfig();
677
+ }
678
+ if (contentItemOrConfig instanceof AbstractContentItem) {
679
+ return contentItemOrConfig;
680
+ }
681
+ if ($.isPlainObject(contentItemOrConfig) && contentItemOrConfig.type) {
682
+ var newContentItem = this.createContentItem(contentItemOrConfig, parent);
683
+ newContentItem.callDownwards('_$init');
684
+ return newContentItem;
685
+ } else {
686
+ throw new Error('Invalid contentItem');
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Iterates through the array of open popout windows and removes the ones
692
+ * that are effectively closed. This is necessary due to the lack of reliably
693
+ * listening for window.close / unload events in a cross browser compatible fashion.
694
+ */
695
+ _$reconcilePopoutWindows() {
696
+ var openPopouts = [];
697
+ for (var i = 0; i < this.openPopouts.length; i++) {
698
+ var _this$openPopouts$i$g;
699
+ if (((_this$openPopouts$i$g = this.openPopouts[i].getWindow()) === null || _this$openPopouts$i$g === void 0 ? void 0 : _this$openPopouts$i$g.closed) === false) {
700
+ openPopouts.push(this.openPopouts[i]);
701
+ } else {
702
+ this.emit('windowClosed', this.openPopouts[i]);
703
+ }
704
+ }
705
+ if (this.openPopouts.length !== openPopouts.length) {
706
+ this.emit('stateChanged');
707
+ this.openPopouts = openPopouts;
708
+ }
709
+ }
710
+
711
+ /***************************
712
+ * PRIVATE
713
+ ***************************/
714
+ /**
715
+ * Returns a flattened array of all content items,
716
+ * regardles of level or type
717
+ * @return Flattened array of content items
718
+ */
719
+ _getAllContentItems() {
720
+ var allContentItems = [];
721
+ var addChildren = contentItem => {
722
+ allContentItems.push(contentItem);
723
+ if (contentItem.contentItems instanceof Array) {
724
+ for (var i = 0; i < contentItem.contentItems.length; i++) {
725
+ addChildren(contentItem.contentItems[i]);
726
+ }
727
+ }
728
+ };
729
+ addChildren(this.root);
730
+ return allContentItems;
731
+ }
732
+
733
+ /**
734
+ * Binds to DOM/BOM events on init
735
+ */
736
+ _bindEvents() {
737
+ if (this._isFullPage) {
738
+ $(window).resize(this._onResize);
739
+ }
740
+ $(window).on('unload beforeunload', this._onUnload).on('blur.lm', this._windowBlur).on('focus.lm', this._windowFocus);
741
+ }
742
+
743
+ /**
744
+ * Handles setting a class based on window focus, useful for focus indicators
745
+ */
746
+ _windowBlur() {
747
+ this.root.element.addClass('lm_window_blur');
748
+ }
749
+ _windowFocus() {
750
+ this.root.element.removeClass('lm_window_blur');
751
+ }
752
+
753
+ /**
754
+ * Debounces resize events
755
+ */
756
+ _onResize() {
757
+ clearTimeout(this._resizeTimeoutId);
758
+ this._resizeTimeoutId = window.setTimeout(this.updateSize.bind(this), 100);
759
+ }
760
+
761
+ /**
762
+ * Extends the default config with the user specific settings and applies
763
+ * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode)
764
+ * that deals with the extension of item configs
765
+ *
766
+ * @param config
767
+ * @returns config
768
+ */
769
+ _createConfig(config) {
770
+ var _config$settings;
771
+ var windowConfigKey = getQueryStringParam('gl-window');
772
+ if (windowConfigKey) {
773
+ this.isSubWindow = true;
774
+ config = JSON.parse(localStorage.getItem(windowConfigKey) || '{}');
775
+ config = unminifyConfig(config);
776
+ localStorage.removeItem(windowConfigKey);
777
+ }
778
+ config = $.extend(true, {}, defaultConfig, config);
779
+ var nextNode = function nextNode(node) {
780
+ for (var key in node) {
781
+ var value = node[key];
782
+ if (key !== 'props' && typeof value === 'object' && value != null) {
783
+ nextNode(value);
784
+ } else if (key === 'type' && value === 'react-component') {
785
+ node.type = 'component';
786
+ node.componentName = 'lm-react-component';
787
+ }
788
+ }
789
+ };
790
+ nextNode(config);
791
+ if (((_config$settings = config.settings) === null || _config$settings === void 0 ? void 0 : _config$settings.hasHeaders) === false) {
792
+ config.dimensions.headerHeight = 0;
793
+ }
794
+ return config;
795
+ }
796
+
797
+ /**
798
+ * This is executed when GoldenLayout detects that it is run
799
+ * within a previously opened popout window.
800
+ */
801
+ _adjustToWindowMode() {
802
+ var _this$config$content$;
803
+ var popInButton = $('<div class="lm_popin" title="' + this.config.labels.popin + '">' + '<div class="lm_icon"></div>' + '<div class="lm_bg"></div>' + '</div>');
804
+ popInButton.click(() => {
805
+ this.emit('popIn');
806
+ });
807
+ document.title = stripTags((_this$config$content$ = this.config.content[0].title) !== null && _this$config$content$ !== void 0 ? _this$config$content$ : '');
808
+ $('head').append($('body link, body style, template, .gl_keep'));
809
+ this.container = $('body').html('').css('visibility', 'visible').append(popInButton);
810
+
811
+ /*
812
+ * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around
813
+ * slickgrid's "Cannot find stylesheet." bug in chrome
814
+ */
815
+ var x = document.body.offsetHeight; // jshint ignore:line
816
+
817
+ /*
818
+ * Expose this instance on the window object
819
+ * to allow the opening window to interact with
820
+ * it
821
+ */
822
+ window.__glInstance = this;
823
+ }
824
+
825
+ /**
826
+ * Creates Subwindows (if there are any). Throws an error
827
+ * if popouts are blocked.
828
+ */
829
+ _createSubWindows() {
830
+ if (!this.config.openPopouts) {
831
+ return;
832
+ }
833
+ for (var i = 0; i < this.config.openPopouts.length; i++) {
834
+ var popout = this.config.openPopouts[i];
835
+ this.createPopout(popout.content, popout.dimensions, popout.parentId, popout.indexInParent);
836
+ }
837
+ }
838
+ _getContainer() {
839
+ var container = this._originalContainer ? $(this._originalContainer) : $('body');
840
+ if (container.length === 0) {
841
+ throw new Error('GoldenLayout container not found');
842
+ }
843
+ if (container.length > 1) {
844
+ throw new Error('GoldenLayout more than one container element specified');
845
+ }
846
+ return container;
847
+ }
848
+
849
+ /**
850
+ * Determines what element the layout will be created in
851
+ */
852
+ _setContainer() {
853
+ var container = this._getContainer();
854
+ if (container[0] === document.body) {
855
+ this._isFullPage = true;
856
+ $('html, body').css({
857
+ height: '100%',
858
+ margin: 0,
859
+ padding: 0,
860
+ overflow: 'hidden'
861
+ });
862
+ }
863
+ this.container = container;
864
+ }
865
+
866
+ /**
867
+ * Kicks of the initial, recursive creation chain
868
+ *
869
+ * @param config GoldenLayout Config
870
+ */
871
+ _create(config) {
872
+ var errorMsg;
873
+ if (!(config.content instanceof Array)) {
874
+ if (config.content === undefined) {
875
+ errorMsg = "Missing setting 'content' on top level of configuration";
876
+ } else {
877
+ errorMsg = "Configuration parameter 'content' must be an array";
878
+ }
879
+ throw new ConfigurationError(errorMsg, config);
880
+ }
881
+ if (config.content.length > 1) {
882
+ errorMsg = "Top level content can't contain more then one element.";
883
+ throw new ConfigurationError(errorMsg, config);
884
+ }
885
+ this.root = new Root(this, {
886
+ content: config.content
887
+ }, this.container);
888
+ this.root.callDownwards('_$init');
889
+ if (config.maximisedItemId === '__glMaximised') {
890
+ this.root.getItemsById(config.maximisedItemId)[0].toggleMaximise();
891
+ }
892
+ }
893
+
894
+ /**
895
+ * Called when the window is closed or the user navigates away
896
+ * from the page
897
+ */
898
+ _onUnload() {
899
+ if (this.config.settings.closePopoutsOnUnload === true) {
900
+ for (var i = 0; i < this.openPopouts.length; i++) {
901
+ this.openPopouts[i].close();
902
+ }
903
+ }
904
+ }
905
+
906
+ /**
907
+ * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth.
908
+ */
909
+ _adjustColumnsResponsive() {
910
+ // If there is no min width set, or not content items, do nothing.
911
+ if (!this._useResponsiveLayout() || this._updatingColumnsResponsive || !this.config.dimensions || !this.config.dimensions.minItemWidth || this.root.contentItems.length === 0 || !this.root.contentItems[0].isRow) {
912
+ this._firstLoad = false;
913
+ return;
914
+ }
915
+ this._firstLoad = false;
916
+
917
+ // If there is only one column, do nothing.
918
+ var columnCount = this.root.contentItems[0].contentItems.length;
919
+ if (columnCount <= 1) {
920
+ return;
921
+ }
922
+
923
+ // If they all still fit, do nothing.
924
+ var minItemWidth = this.config.dimensions.minItemWidth;
925
+ var totalMinWidth = columnCount * minItemWidth;
926
+ if (this.width == null || totalMinWidth <= this.width) {
927
+ return;
928
+ }
929
+
930
+ // Prevent updates while it is already happening.
931
+ this._updatingColumnsResponsive = true;
932
+
933
+ // Figure out how many columns to stack, and put them all in the first stack container.
934
+ var finalColumnCount = Math.max(Math.floor(this.width / minItemWidth), 1);
935
+ var stackColumnCount = columnCount - finalColumnCount;
936
+ var rootContentItem = this.root.contentItems[0];
937
+ var firstStackContainer = this._findAllStackContainers()[0];
938
+ for (var i = 0; i < stackColumnCount; i++) {
939
+ // Stack from right.
940
+ var column = rootContentItem.contentItems[rootContentItem.contentItems.length - 1];
941
+ this._addChildContentItemsToContainer(firstStackContainer, column);
942
+ }
943
+ this._updatingColumnsResponsive = false;
944
+ }
945
+
946
+ /**
947
+ * Determines if responsive layout should be used.
948
+ *
949
+ * @returns True if responsive layout should be used; otherwise false.
950
+ */
951
+ _useResponsiveLayout() {
952
+ return this.config.settings && (this.config.settings.responsiveMode == 'always' || this.config.settings.responsiveMode == 'onload' && this._firstLoad);
953
+ }
954
+
955
+ /**
956
+ * Adds all children of a node to another container recursively.
957
+ * @param container - Container to add child content items to.
958
+ * @param node - Node to search for content items.
959
+ */
960
+ _addChildContentItemsToContainer(container, node) {
961
+ if (node.type === 'stack') {
962
+ node.contentItems.forEach(function (item) {
963
+ container.addChild(item);
964
+ node.removeChild(item, true);
965
+ });
966
+ } else {
967
+ node.contentItems.forEach(item => {
968
+ this._addChildContentItemsToContainer(container, item);
969
+ });
970
+ }
971
+ }
972
+
973
+ /**
974
+ * Finds all the stack containers.
975
+ * @returns The found stack containers.
976
+ */
977
+ _findAllStackContainers() {
978
+ var stackContainers = [];
979
+ this._findAllStackContainersRecursive(stackContainers, this.root);
980
+ return stackContainers;
981
+ }
982
+
983
+ /**
984
+ * Finds all the stack containers.
985
+ *
986
+ * @param stackContainers Set of containers to populate.
987
+ * @param node Current node to process.
988
+ */
989
+ _findAllStackContainersRecursive(stackContainers, node) {
990
+ node.contentItems.forEach(item => {
991
+ if (isStack(item)) {
992
+ stackContainers.push(item);
993
+ } else if (!item.isComponent) {
994
+ this._findAllStackContainersRecursive(stackContainers, item);
995
+ }
996
+ });
997
+ }
998
+ }
999
+ _defineProperty(LayoutManager, "__lm", lm);
1000
+ export default LayoutManager;
1001
+ //# sourceMappingURL=LayoutManager.js.map