bm-core-ui 2.8.2 → 2.9.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.
- package/build/@types/index.d.ts +327 -31
- package/build/BMCollectionView/BMCollectionView.js +33 -16
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +159 -39
- package/build/BMCollectionView/BMCollectionViewLayout.js +4 -1
- package/build/BMCoreUI.css +161 -13
- package/build/BMView/BMLayoutConstraint_v2.5.js +1 -1
- package/build/BMView/BMMenu.js +790 -65
- package/build/BMView/BMScrollView.js +1 -1
- package/build/BMView/BMTextFieldDelegate.js +6 -6
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +2 -2
- package/build/BMViewLayoutEditor/BMLayoutEditorViewSettings.js +5 -2
- package/build/BMWindow/BMConfirmationPopup.js +21 -1
- package/build/BMWindow/BMPopover/BMPopover.js +310 -52
- package/build/BMWindow/BMWindow.js +61 -18
- package/lib/@types/BMCoreUI.min.d.ts +327 -31
- package/lib/BMCoreUI.min.js +1 -1
- package/package.json +1 -1
- package/CHANGELOG.md +0 -1739
- package/build/BMViewLayoutEditor/BMLayoutEditorDelegate.js +0 -59
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingsDelegate.js +0 -46
- package/build/BMViewLayoutEditor/BMLayoutVariableProvider.js +0 -202
|
@@ -257,30 +257,38 @@ BMWindow.unregisterShowcaseElement = function (element) {
|
|
|
257
257
|
BMWindow.enterShowcase = async function () {
|
|
258
258
|
if (BMWindow._isShowcasing) return;
|
|
259
259
|
|
|
260
|
+
// Set a background color for the body to have a good contrast between the windows
|
|
261
|
+
// and the "empty space"
|
|
260
262
|
document.body.style.backgroundColor = 'rgb(60, 60, 60)';
|
|
261
263
|
|
|
262
264
|
BMWindow._isShowcasing = YES;
|
|
263
265
|
|
|
266
|
+
// Set up a handler to exit the showcase when clicking outside of any window
|
|
264
267
|
document.body.addEventListener('click', BMWindow.exitShowcase);
|
|
265
268
|
|
|
269
|
+
// Only include non-minimized windows in the showcase
|
|
266
270
|
let openWindows = BMWindow._windows.filter(value => !value._minimizedWindow);
|
|
267
271
|
|
|
268
|
-
|
|
269
|
-
|
|
272
|
+
// Add any window-like elements that have been registered to participate in the showcase
|
|
270
273
|
for (let element of BMWindow._showcaseElements) {
|
|
271
274
|
openWindows.unshift(element);
|
|
272
275
|
}
|
|
273
276
|
|
|
274
277
|
openWindows.forEach(window => {
|
|
278
|
+
// For each window, create a mask that consumes mouse events instead of the windows
|
|
279
|
+
// and disable pointer events for the windows
|
|
275
280
|
window.node.classList.add('BMWindowShowcaseWindow');
|
|
276
281
|
|
|
277
282
|
let selector = document.createElement('div');
|
|
278
283
|
selector.classList.add('BMWindowShowcaseWindowSelector');
|
|
279
284
|
selector.addEventListener('click', event => {
|
|
280
285
|
if (window.becomeKeyWindow) {
|
|
286
|
+
// If the clicked element is a window, make it the key window
|
|
281
287
|
window.becomeKeyWindow();
|
|
282
288
|
}
|
|
283
289
|
else {
|
|
290
|
+
// If a non-window element is clicked, bring it to the front by hiding
|
|
291
|
+
// all windows
|
|
284
292
|
BMWindow.hideAll();
|
|
285
293
|
}
|
|
286
294
|
BMWindow.exitShowcase();
|
|
@@ -289,16 +297,30 @@ BMWindow.enterShowcase = async function () {
|
|
|
289
297
|
window.node.appendChild(selector);
|
|
290
298
|
});
|
|
291
299
|
|
|
300
|
+
|
|
301
|
+
let viewportFrame = BMRectMake(0, 0, window.innerWidth, window.innerHeight);
|
|
302
|
+
// Create a copy of each window's frame which will be used to determine where to place each window
|
|
303
|
+
// in the showcase
|
|
292
304
|
let sourceRects = openWindows.map(window => window._fullScreen ? viewportFrame.copy() : window.frame.copy());
|
|
305
|
+
|
|
306
|
+
// Retain a copy of the original frames to determine what transforms to apply to each window
|
|
293
307
|
let originalRects = sourceRects.map(rect => rect.copy());
|
|
308
|
+
|
|
309
|
+
// Set to NO when no windows overlap
|
|
294
310
|
let overlap;
|
|
295
311
|
|
|
312
|
+
// Initialize the bounds with the viewport frame; this will expand to represent the entire area
|
|
313
|
+
// used by all windows as they get pushed apart
|
|
296
314
|
let bounds = viewportFrame.copy();
|
|
297
315
|
|
|
316
|
+
// Because the algorithm works through multiple iterations where each intersecting windows
|
|
317
|
+
// are pushed apart slightly, set a maximum number of iterations to avoid situations
|
|
318
|
+
// where a fully non-intersecting layout cannot be obtained in an acceptable amount of time
|
|
298
319
|
for (let i = 0; i < BM_WINDOW_SHOWCASE_MAX_ITERATIONS; i++) {
|
|
299
320
|
|
|
300
321
|
for (let j = 0; j < sourceRects.length; j++) {
|
|
301
322
|
for (let k = 0; k < sourceRects.length; k++) {
|
|
323
|
+
// Iterate through each pair of windows and push apart those windows that intersect
|
|
302
324
|
if (j != k && sourceRects[j].intersectsRect(sourceRects[k])) {
|
|
303
325
|
overlap = YES;
|
|
304
326
|
|
|
@@ -307,11 +329,15 @@ BMWindow.enterShowcase = async function () {
|
|
|
307
329
|
|
|
308
330
|
let difference = rect2.center.pointBySubtractingPoint(rect1.center);
|
|
309
331
|
|
|
332
|
+
// If the windows have the same center point, choose a random direction
|
|
333
|
+
// in which to push them apart
|
|
310
334
|
if (!difference.x && !difference.y) {
|
|
311
335
|
difference.x = Math.random() * 2 - 1;
|
|
312
336
|
difference.y = Math.random() * 2 - 1;
|
|
313
337
|
}
|
|
314
338
|
|
|
339
|
+
// Adjust the direction in which the windows are pushed apart to maintain a similar
|
|
340
|
+
// aspect ratio between the bounds and the viewport
|
|
315
341
|
if (bounds.height / bounds.width > viewportFrame.height / viewportFrame.width) {
|
|
316
342
|
difference.x = difference.x * 2;
|
|
317
343
|
}
|
|
@@ -319,13 +345,16 @@ BMWindow.enterShowcase = async function () {
|
|
|
319
345
|
difference.y = difference.y * 2;
|
|
320
346
|
}
|
|
321
347
|
|
|
348
|
+
// Normalize the distance
|
|
322
349
|
let length = Math.sqrt(difference.x * difference.x + difference.y * difference.y);
|
|
323
350
|
difference.x = difference.x * 20 / length;
|
|
324
351
|
difference.y = difference.y * 20 / length;
|
|
325
352
|
|
|
353
|
+
// Push the two windows apart in opposite directions
|
|
326
354
|
rect1.offsetWithX(-difference.x, {y: -difference.y});
|
|
327
355
|
rect2.offsetWithX(difference.x, {y: difference.y});
|
|
328
356
|
|
|
357
|
+
// Extend the bounds to contain the windows in their new positions
|
|
329
358
|
bounds = bounds.rectByUnionWithRect(rect1).rectByUnionWithRect(rect2);
|
|
330
359
|
|
|
331
360
|
}
|
|
@@ -335,11 +364,14 @@ BMWindow.enterShowcase = async function () {
|
|
|
335
364
|
if (!overlap) break;
|
|
336
365
|
}
|
|
337
366
|
|
|
367
|
+
// Determine how much the windows need to be shrinked to fit on screen
|
|
338
368
|
let scale = Math.min(1, viewportFrame.width / bounds.width, viewportFrame.height / bounds.height);
|
|
339
369
|
|
|
340
370
|
for (let rect of sourceRects) {
|
|
371
|
+
// Adjust the rect's origin so that it is relative to the bounds instead of the viewport
|
|
341
372
|
rect.offset(-bounds.left, -bounds.top);
|
|
342
373
|
|
|
374
|
+
// Apply the scale
|
|
343
375
|
rect.origin.x = rect.origin.x * scale;
|
|
344
376
|
rect.origin.y = rect.origin.y * scale;
|
|
345
377
|
|
|
@@ -351,11 +383,8 @@ BMWindow.enterShowcase = async function () {
|
|
|
351
383
|
BMAnimateWithBlock(() => {
|
|
352
384
|
BMAnimationContextEnableWebAnimations();
|
|
353
385
|
|
|
354
|
-
/*let header = document.getElementById('twStudioHeader');
|
|
355
|
-
let headerController = BMAnimationContextGetCurrent().controllerForObject(header, {node: header});
|
|
356
|
-
headerController.registerBuiltInProperty('translateY', {withValue: -header.offsetHeight + 'px'});*/
|
|
357
|
-
|
|
358
386
|
for (let i = 0; i < sourceRects.length; i++) {
|
|
387
|
+
// For each window, determine which transforms to apply and animate to them
|
|
359
388
|
let transformRect = originalRects[i].rectWithTransformToRect(sourceRects[i]);
|
|
360
389
|
|
|
361
390
|
let controller = BMAnimationContextGetCurrent().controllerForObject(openWindows[i].node, {node: openWindows[i].node});
|
|
@@ -391,19 +420,18 @@ BMWindow.exitShowcase = function (event) {
|
|
|
391
420
|
|
|
392
421
|
BMWindow._isShowcasing = NO;
|
|
393
422
|
|
|
423
|
+
// Clear the event handlers set up for the showcase
|
|
394
424
|
document.body.removeEventListener('click', BMWindow.exitShowcase);
|
|
395
425
|
document.body.removeEventListener('wheel', BMWindow._wheelHandler, YES);
|
|
396
426
|
|
|
397
427
|
let openWindows = BMWindow._windows.filter(value => !value._minimizedWindow);
|
|
398
|
-
/*let twStudio = document.querySelector('#twStudioBody');
|
|
399
|
-
let pageWindow = {node: twStudio};
|
|
400
|
-
openWindows.unshift(pageWindow);*/
|
|
401
428
|
|
|
402
429
|
for (let element of BMWindow._showcaseElements) {
|
|
403
430
|
openWindows.unshift(element);
|
|
404
431
|
}
|
|
405
432
|
|
|
406
433
|
openWindows.forEach(window => {
|
|
434
|
+
// Clear the classes and masks created for each window
|
|
407
435
|
window.node.classList.remove('BMWindowShowcaseWindow');
|
|
408
436
|
|
|
409
437
|
let selector = window.node.querySelector('.BMWindowShowcaseWindowSelector');
|
|
@@ -413,11 +441,8 @@ BMWindow.exitShowcase = function (event) {
|
|
|
413
441
|
BMAnimateWithBlock(() => {
|
|
414
442
|
BMAnimationContextEnableWebAnimations();
|
|
415
443
|
|
|
416
|
-
/*let header = document.getElementById('twStudioHeader');
|
|
417
|
-
let headerController = BMAnimationContextGetCurrent().controllerForObject(header, {node: header});
|
|
418
|
-
headerController.registerBuiltInProperty('translateY', {withValue: '0px'});*/
|
|
419
|
-
|
|
420
444
|
for (let i = 0; i < openWindows.length; i++) {
|
|
445
|
+
// For each window, animate back to no transforms
|
|
421
446
|
let controller = BMAnimationContextGetCurrent().controllerForObject(openWindows[i].node, {node: openWindows[i].node});
|
|
422
447
|
controller.registerBuiltInPropertiesWithDictionary({
|
|
423
448
|
translateX: '0px',
|
|
@@ -1124,6 +1149,7 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1124
1149
|
const animationNode = node.cloneNode(YES);
|
|
1125
1150
|
|
|
1126
1151
|
const nodeDisplay = node.style.display;
|
|
1152
|
+
self._nodeDisplay = nodeDisplay;
|
|
1127
1153
|
|
|
1128
1154
|
animationNode.style.position = 'fixed';
|
|
1129
1155
|
animationNode.style.zIndex = BM_WINDOW_Z_INDEX_MAX + 1;
|
|
@@ -1165,6 +1191,7 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1165
1191
|
}
|
|
1166
1192
|
else {
|
|
1167
1193
|
node.style.display = nodeDisplay;
|
|
1194
|
+
self._nodeDisplay = undefined;
|
|
1168
1195
|
}
|
|
1169
1196
|
|
|
1170
1197
|
completionHandler();
|
|
@@ -1326,14 +1353,14 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1326
1353
|
// Create a copy of the given node which will be used in the animation in place of the original node
|
|
1327
1354
|
const node = this._anchorNode;
|
|
1328
1355
|
|
|
1329
|
-
if (
|
|
1356
|
+
if (typeof self._nodeDisplay != 'undefined') {
|
|
1330
1357
|
node.style.display = self._nodeDisplay;
|
|
1331
1358
|
}
|
|
1332
1359
|
|
|
1333
1360
|
const rect = BMRectMakeWithNodeFrame(node);
|
|
1334
1361
|
const animationNode = node.cloneNode(YES);
|
|
1335
1362
|
|
|
1336
|
-
const nodeDisplay = (
|
|
1363
|
+
const nodeDisplay = (typeof self._nodeDisplay != 'undefined') ? self._nodeDisplay : node.style.display;
|
|
1337
1364
|
self._nodeDisplay = undefined;
|
|
1338
1365
|
|
|
1339
1366
|
animationNode.style.position = 'fixed';
|
|
@@ -1425,6 +1452,7 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1425
1452
|
self._blocker.style.backdropFilter = 'blur(' + ((1 - complete) * 15).toFixed(2) + 'px)';
|
|
1426
1453
|
},*/
|
|
1427
1454
|
complete: function () {
|
|
1455
|
+
self.windowDidClose();
|
|
1428
1456
|
if (self.delegate && self.delegate.windowDidClose) {
|
|
1429
1457
|
self.delegate.windowDidClose(self);
|
|
1430
1458
|
}
|
|
@@ -1465,6 +1493,8 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1465
1493
|
|
|
1466
1494
|
this._window.style.opacity = 0;
|
|
1467
1495
|
this._window.style.display = 'none';
|
|
1496
|
+
|
|
1497
|
+
self.windowDidClose();
|
|
1468
1498
|
|
|
1469
1499
|
if (self.delegate && self.delegate.windowDidClose) {
|
|
1470
1500
|
self.delegate.windowDidClose(self);
|
|
@@ -1473,6 +1503,14 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1473
1503
|
}
|
|
1474
1504
|
},
|
|
1475
1505
|
|
|
1506
|
+
/**
|
|
1507
|
+
* Invoked after this window closes. Subclasses overriding this method must invoked
|
|
1508
|
+
* the superclass method at some point in their implementation.
|
|
1509
|
+
*/
|
|
1510
|
+
windowDidClose() {
|
|
1511
|
+
|
|
1512
|
+
},
|
|
1513
|
+
|
|
1476
1514
|
/**
|
|
1477
1515
|
* Minimizes this window. This method will raise an error if this window is modal.
|
|
1478
1516
|
* If this window is already minimized, this method will have no effect.
|
|
@@ -1791,14 +1829,14 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1791
1829
|
if (BMWindow._keyWindow == this && !this._modal) {
|
|
1792
1830
|
this.node.classList.remove('BMKeyWindow');
|
|
1793
1831
|
this.node.classList.add('BMWindowInactive');
|
|
1794
|
-
if (this.delegate && this.delegate.windowDidResignKeyWindow) {
|
|
1795
|
-
this.delegate.windowDidResignKeyWindow(this);
|
|
1796
|
-
}
|
|
1797
1832
|
BMWindow._keyWindow = undefined;
|
|
1798
1833
|
|
|
1799
1834
|
for (let toolWindow of this._toolWindows) {
|
|
1800
1835
|
toolWindow.hide();
|
|
1801
1836
|
}
|
|
1837
|
+
if (this.delegate && this.delegate.windowDidResignKeyWindow) {
|
|
1838
|
+
this.delegate.windowDidResignKeyWindow(this);
|
|
1839
|
+
}
|
|
1802
1840
|
}
|
|
1803
1841
|
},
|
|
1804
1842
|
|
|
@@ -1865,6 +1903,11 @@ BMWindow.prototype = BMExtend(Object.create(BMView.prototype), {
|
|
|
1865
1903
|
* This instance should not be reused after invoking this method.
|
|
1866
1904
|
*/
|
|
1867
1905
|
release() {
|
|
1906
|
+
if (this.__released) {
|
|
1907
|
+
// This needs to be handled because of the way Thingworx DOM nodes are removed and recreated in the composer
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1868
1911
|
if (BMWindow._keyWindow == this) BMWindow._keyWindow = undefined;
|
|
1869
1912
|
|
|
1870
1913
|
if (this._boundViewportDidResize) {
|