bm-core-ui 2.9.5 → 2.10.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.
- package/build/@types/index.d.ts +320 -61
- package/build/BMCollectionView/BMCollectionView.js +79 -41
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +18 -5
- package/build/BMCoreUI.css +45 -18
- package/build/BMView/BMMenu.js +135 -7
- package/build/BMView/BMView_v2.5.js +59 -0
- package/build/BMWindow/BMKeyboardShortcut.js +338 -88
- package/build/BMWindow/BMPopover/BMPopover.js +52 -11
- package/build/BMWindow/BMWindow.js +32 -6
- package/build/Core/BMCoreUI.js +20 -8
- package/build/images/AlignBottom.png +0 -0
- package/build/images/AlignCenterX.png +0 -0
- package/build/images/AlignCenterY.png +0 -0
- package/build/images/AlignLeading.png +0 -0
- package/build/images/AlignTop.png +0 -0
- package/build/images/AlignTrailing.png +0 -0
- package/build/images/AllConstraints.png +0 -0
- package/build/images/BottomConstraint.png +0 -0
- package/build/images/CenterXConstraint.png +0 -0
- package/build/images/CenterYConstraint.png +0 -0
- package/build/images/CoreUI2.png +0 -0
- package/build/images/CoreUI2@2x.png +0 -0
- package/build/images/Desktop.png +0 -0
- package/build/images/DesktopMini.png +0 -0
- package/build/images/EqualHeight.png +0 -0
- package/build/images/EqualHorizontalSpacing.png +0 -0
- package/build/images/EqualHorizontalSpacingInSuperview.png +0 -0
- package/build/images/EqualVerticalSpacing.png +0 -0
- package/build/images/EqualVerticalSpacingInSuperview.png +0 -0
- package/build/images/EqualWidth.png +0 -0
- package/build/images/HeightConstraint.png +0 -0
- package/build/images/InactiveConstraints.png +0 -0
- package/build/images/Layout.png +0 -0
- package/build/images/LayoutVariables.png +0 -0
- package/build/images/LeftConstraint.png +0 -0
- package/build/images/OwnConstraints.png +0 -0
- package/build/images/Phone.png +0 -0
- package/build/images/PhoneLandscape.png +0 -0
- package/build/images/PhoneLandscapeMini.png +0 -0
- package/build/images/PhoneMini.png +0 -0
- package/build/images/PhonePortrait.png +0 -0
- package/build/images/PhonePortraitMini.png +0 -0
- package/build/images/Properties.png +0 -0
- package/build/images/RightConstraint.png +0 -0
- package/build/images/SubviewConstraints.png +0 -0
- package/build/images/Tablet.png +0 -0
- package/build/images/TabletLandscape.png +0 -0
- package/build/images/TabletLandscapeMini.png +0 -0
- package/build/images/TabletMini.png +0 -0
- package/build/images/TabletPortrait.png +0 -0
- package/build/images/TabletPortraitMini.png +0 -0
- package/build/images/TopConstraint.png +0 -0
- package/build/images/WidthConstraint.png +0 -0
- package/lib/@types/BMCoreUI.min.d.ts +320 -61
- package/lib/BMCoreUI.min.js +3 -1
- package/package.json +9 -10
package/build/BMView/BMMenu.js
CHANGED
|
@@ -128,12 +128,72 @@ BMMenuItem.prototype = {
|
|
|
128
128
|
this._CSSClass = cls || '';
|
|
129
129
|
},
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* An optional key sequence that may be used to select this menu item via a keyboard shortcut.
|
|
133
|
+
* Updates to this property do not take effect while a menu displaying this menu item is open.
|
|
134
|
+
*/
|
|
135
|
+
_keySequence: undefined, // <BMKeySequence, nullable>
|
|
136
|
+
get keySequence() {
|
|
137
|
+
return this._keySequence;
|
|
138
|
+
},
|
|
139
|
+
set keySequence(sequence) {
|
|
140
|
+
this._keySequence = sequence;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* An optional hint HTML text that will be displayed next to the menu item.
|
|
145
|
+
*/
|
|
146
|
+
_hintHTML: undefined, // <String, nullable>
|
|
147
|
+
get hintHTML() {
|
|
148
|
+
return this._hintHTML;
|
|
149
|
+
},
|
|
150
|
+
set hintHTML(hint) {
|
|
151
|
+
this._hintHTML = hint;
|
|
152
|
+
if (this._node) {
|
|
153
|
+
const hintContainer = this._node.querySelector('.BMMenuItemHint');
|
|
154
|
+
if (hintContainer) {
|
|
155
|
+
hintContainer.innerHTML = hint;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
131
160
|
/**
|
|
132
161
|
* The node that represents this menu item, available while its menu
|
|
133
162
|
* is open.
|
|
134
163
|
*/
|
|
135
164
|
_node: undefined, // <DOMNode, nullable>
|
|
136
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Defaults to `YES`. Controls whether this menu item is enabled. If this menu
|
|
168
|
+
* item is not enabled, it can not be highlighted or selected.
|
|
169
|
+
*/
|
|
170
|
+
_enabled: YES, // <Boolean>
|
|
171
|
+
get enabled() {
|
|
172
|
+
return this._enabled;
|
|
173
|
+
},
|
|
174
|
+
set enabled(enabled) {
|
|
175
|
+
if (this._enabled == enabled) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Separators can never be enabled
|
|
180
|
+
if (this._isSeparator) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
this._enabled = enabled;
|
|
185
|
+
|
|
186
|
+
if (this._node) {
|
|
187
|
+
/** @type {HTMLElement} */ const node = this._node;
|
|
188
|
+
if (enabled) {
|
|
189
|
+
node.classList.remove('BMMenuItemDisabled');
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
node.classList.add('BMMenuItemDisabled');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
|
|
137
197
|
/**
|
|
138
198
|
* Constructs and returns a menu item with the given name.
|
|
139
199
|
* Optionally, the menu item may have an icon associated with it as well as an
|
|
@@ -145,12 +205,13 @@ BMMenuItem.prototype = {
|
|
|
145
205
|
*
|
|
146
206
|
* @param action <void ^ (BMMenuItem), nullable> If specified, this is a function that will be invoked when this menu item is selected.
|
|
147
207
|
* This function will receive the selected menu item as a parameter.
|
|
208
|
+
* @param enabled <Boolean, nullable> Defaults to `YES`. Controls whether this item is enabled and can be selected.
|
|
148
209
|
* @param submenu <BMMenu, nullable> Optional. If specified, this represents a menu that opens from this menu item.
|
|
149
210
|
* @param userInfo <AnyObject, nullable> Optional. If specified, this represents additional arbitrary data attached to this menu item.
|
|
150
211
|
* }
|
|
151
212
|
* @return <BMMenuItem> This menu item.
|
|
152
213
|
*/
|
|
153
|
-
initWithName(name, {icon, action, submenu, userInfo} = {}) {
|
|
214
|
+
initWithName(name, {icon, action, submenu, enabled = true, userInfo} = {}) {
|
|
154
215
|
this._name = name;
|
|
155
216
|
this._icon = icon;
|
|
156
217
|
this._action = action;
|
|
@@ -159,8 +220,11 @@ BMMenuItem.prototype = {
|
|
|
159
220
|
|
|
160
221
|
if (name.startsWith('---')) {
|
|
161
222
|
this._isSeparator = YES;
|
|
223
|
+
this._enabled = NO;
|
|
162
224
|
}
|
|
163
225
|
|
|
226
|
+
this._enabled = enabled;
|
|
227
|
+
|
|
164
228
|
return this;
|
|
165
229
|
}
|
|
166
230
|
|
|
@@ -177,6 +241,7 @@ BMMenuItem.prototype = {
|
|
|
177
241
|
*
|
|
178
242
|
* @param action <void ^ (BMMenuItem), nullable> If specified, this is a function that will be invoked when this menu item is selected.
|
|
179
243
|
* This function will receive the selected menu item as a parameter.
|
|
244
|
+
* @param enabled <Boolean, nullable> Defaults to `YES`. Controls whether this item is enabled and can be selected.
|
|
180
245
|
* @param submenu <BMMenu, nullable> Optional. If specified, this represents a menu that opens from this menu item.
|
|
181
246
|
* @param userInfo <AnyObject, nullable> Optional. If specified, this represents additional arbitrary data attached to this menu item.
|
|
182
247
|
* }
|
|
@@ -225,7 +290,7 @@ BMMenu.prototype = {
|
|
|
225
290
|
},
|
|
226
291
|
|
|
227
292
|
/**
|
|
228
|
-
* Defaults to 24
|
|
293
|
+
* Defaults to `24`. The size to use for this menu's icons.
|
|
229
294
|
*/
|
|
230
295
|
_iconSize: 24, // <Number>
|
|
231
296
|
get iconSize() {
|
|
@@ -461,6 +526,15 @@ BMMenu.prototype = {
|
|
|
461
526
|
escape.preventsDefault = YES;
|
|
462
527
|
BMView.registerKeyboardShortcut(escape, {forNode: menuNode});
|
|
463
528
|
|
|
529
|
+
// Register a keyboard shortcut for each menu item that specifies one
|
|
530
|
+
for (const item of this._items) {
|
|
531
|
+
if (item.keySequence) {
|
|
532
|
+
const shortcut = BMKeyboardShortcut.keyboardShortcutWithKeySequence(item.keySequence, {target: this, action: '_selectMenuItemWithEvent'});
|
|
533
|
+
shortcut._menuItem = item;
|
|
534
|
+
BMView.registerKeyboardShortcut(shortcut, {forNode: menuNode});
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
464
538
|
// The overlay which intercepts clicks outside of the menu
|
|
465
539
|
const menuContainer = container || document.createElement('div');
|
|
466
540
|
if (!container) {
|
|
@@ -560,6 +634,12 @@ BMMenu.prototype = {
|
|
|
560
634
|
itemText.innerText = item.name;
|
|
561
635
|
itemNode.appendChild(itemText);
|
|
562
636
|
|
|
637
|
+
// Create the hint container
|
|
638
|
+
const hint = document.createElement('div');
|
|
639
|
+
hint.classList.add('BMMenuItemHint');
|
|
640
|
+
hint.innerHTML = item._hintHTML || '';
|
|
641
|
+
itemNode.appendChild(hint);
|
|
642
|
+
|
|
563
643
|
// Create the disclosure container
|
|
564
644
|
const submenuIcon = document.createElement('div');
|
|
565
645
|
submenuIcon.classList.add('BMMenuItemDisclosure');
|
|
@@ -568,9 +648,18 @@ BMMenu.prototype = {
|
|
|
568
648
|
submenuIcon.classList.add('BMMenuItemDisclosureSubmenu');
|
|
569
649
|
}
|
|
570
650
|
itemNode.appendChild(submenuIcon);
|
|
651
|
+
|
|
652
|
+
if (!item._enabled) {
|
|
653
|
+
itemNode.classList.add('BMMenuItemDisabled');
|
|
654
|
+
}
|
|
571
655
|
|
|
572
656
|
// TWhen clicking an item, trigger its action, if it has one
|
|
573
657
|
itemNode.addEventListener('click', event => {
|
|
658
|
+
// Disabled items can't be clicked
|
|
659
|
+
if (!item._enabled) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
|
|
574
663
|
if (item.submenu && this._sourceNodeShadow) {
|
|
575
664
|
// For touch menus, if the item has a submenu, open it
|
|
576
665
|
this._openSubmenuForMenuItem(item, {animated: YES, delayEvents: NO, acquireFocus: YES});
|
|
@@ -611,6 +700,12 @@ BMMenu.prototype = {
|
|
|
611
700
|
// When moving the mouse over an item, set the highlight index to it,
|
|
612
701
|
// allowing further keyboard navigation to continute from this item
|
|
613
702
|
itemNode.addEventListener('mouseover', event => {
|
|
703
|
+
// Disabled items can't be highlighted and can't open submenus
|
|
704
|
+
if (!item._enabled) {
|
|
705
|
+
this.highlightedIndex = -1;
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
|
|
614
709
|
if (this._highlightedIndex == index) return;
|
|
615
710
|
|
|
616
711
|
// If events should be delayed, don't process this mouseover event
|
|
@@ -642,7 +737,8 @@ BMMenu.prototype = {
|
|
|
642
737
|
_kind: BMMenuKind.Menu,
|
|
643
738
|
|
|
644
739
|
/**
|
|
645
|
-
* Animatable. Shows this menu from the
|
|
740
|
+
* Animatable. Shows this menu from the specified DOM node. The menu will be displayed as a touch menu,
|
|
741
|
+
* highlighting the source node and de-emphasizing the rest of the document.
|
|
646
742
|
* @param node <DOMNode> The node from which to show this menu.
|
|
647
743
|
* {
|
|
648
744
|
* @param animated <Boolean, nullable> Defaults to `NO`. If set to `YES`, this change will be animated.
|
|
@@ -1315,8 +1411,8 @@ BMMenu.prototype = {
|
|
|
1315
1411
|
while (YES) {
|
|
1316
1412
|
previousIndex = BMNumberByConstrainingNumberToBounds(previousIndex - 1, 0, this._items.length - 1);
|
|
1317
1413
|
|
|
1318
|
-
// If item at the previous index isn't a separator, highlight it
|
|
1319
|
-
if (!this._items[previousIndex]._isSeparator) break;
|
|
1414
|
+
// If item at the previous index isn't a separator or disabled, highlight it
|
|
1415
|
+
if (!this._items[previousIndex]._isSeparator && this._items[previousIndex]._enabled) break;
|
|
1320
1416
|
|
|
1321
1417
|
// If the start of the items array has been reached and a viable highlightable item hasn't
|
|
1322
1418
|
// been found, don't take any action
|
|
@@ -1337,8 +1433,8 @@ BMMenu.prototype = {
|
|
|
1337
1433
|
while (YES) {
|
|
1338
1434
|
nextIndex = BMNumberByConstrainingNumberToBounds(nextIndex + 1, 0, this._items.length - 1);
|
|
1339
1435
|
|
|
1340
|
-
// If item at the next index isn't a separator, highlight it
|
|
1341
|
-
if (!this._items[nextIndex]._isSeparator) break;
|
|
1436
|
+
// If item at the next index isn't a separator or disabled, highlight it
|
|
1437
|
+
if (!this._items[nextIndex]._isSeparator && this._items[nextIndex]._enabled) break;
|
|
1342
1438
|
|
|
1343
1439
|
// If the end of the items array has been reached and a viable highlightable item hasn't
|
|
1344
1440
|
// been found, don't take any action
|
|
@@ -1375,6 +1471,38 @@ BMMenu.prototype = {
|
|
|
1375
1471
|
}
|
|
1376
1472
|
},
|
|
1377
1473
|
|
|
1474
|
+
/**
|
|
1475
|
+
* Invoked when the key sequence for a menu item is pressed.
|
|
1476
|
+
* @param event <KeyboardEvent> The event that triggered this action.
|
|
1477
|
+
* {
|
|
1478
|
+
* @param forKeyboardShortcut <BMKeyboardShortcut> The keyboard shortcut that was triggered.
|
|
1479
|
+
* }
|
|
1480
|
+
*/
|
|
1481
|
+
_selectMenuItemWithEvent(event, {forKeyboardShortcut: shortcut}) {
|
|
1482
|
+
event.preventDefault();
|
|
1483
|
+
const item = shortcut._menuItem;
|
|
1484
|
+
|
|
1485
|
+
// The item must not be a separator or disabled
|
|
1486
|
+
if (item._isSeparator || !item._enabled) {
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
if (!this._node) {
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
this._node.inert = true;
|
|
1495
|
+
this._node.style.pointerEvents = 'none';
|
|
1496
|
+
|
|
1497
|
+
// Otherwise highlight the item then send a return key to select it
|
|
1498
|
+
const index = this._items.indexOf(item);
|
|
1499
|
+
this.highlightedIndex = index;
|
|
1500
|
+
|
|
1501
|
+
setTimeout(() => {
|
|
1502
|
+
this.returnPressedWithEvent(event);
|
|
1503
|
+
}, 50);
|
|
1504
|
+
},
|
|
1505
|
+
|
|
1378
1506
|
/**
|
|
1379
1507
|
* Invoked when the return or spacebar key is pressed.
|
|
1380
1508
|
* @param event <KeyboardEvent> The event that triggered this action.
|
|
@@ -261,6 +261,32 @@ BMViewLayoutQueue.layoutQueue = function () {
|
|
|
261
261
|
|
|
262
262
|
// @endtype
|
|
263
263
|
|
|
264
|
+
// @type BMViewColorScheme
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Constants that describe the color scheme that a view should use when drawing itself.
|
|
268
|
+
*/
|
|
269
|
+
export var BMViewColorScheme = Object.freeze({ // <enum>
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Indicates that the view's color scheme should be based on the system color scheme.
|
|
273
|
+
*/
|
|
274
|
+
Auto: 'auto', // <enum>
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Indicates that the view should always use a dark color scheme regardless of the system color scheme setting.
|
|
278
|
+
*/
|
|
279
|
+
Dark: 'dark', // <enum>
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Indicates that the view should always use a light color scheme regardless of the system color scheme setting.
|
|
283
|
+
*/
|
|
284
|
+
Light: 'light', // <enum>
|
|
285
|
+
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// @endtype
|
|
289
|
+
|
|
264
290
|
// @type BMView
|
|
265
291
|
|
|
266
292
|
const BMViewDebug = NO;
|
|
@@ -1784,6 +1810,39 @@ BMView.prototype = BMExtend(BMView.prototype, {
|
|
|
1784
1810
|
|
|
1785
1811
|
// #endregion
|
|
1786
1812
|
|
|
1813
|
+
// #region Color Scheme
|
|
1814
|
+
|
|
1815
|
+
/**
|
|
1816
|
+
* The color scheme that this view should use.
|
|
1817
|
+
*/
|
|
1818
|
+
_colorScheme: BMViewColorScheme.Auto, // <BMViewColorScheme>
|
|
1819
|
+
|
|
1820
|
+
get colorScheme() {
|
|
1821
|
+
return this._colorScheme;
|
|
1822
|
+
},
|
|
1823
|
+
|
|
1824
|
+
set colorScheme(scheme) {
|
|
1825
|
+
const oldColorScheme = this._colorScheme;
|
|
1826
|
+
this._colorScheme = scheme;
|
|
1827
|
+
|
|
1828
|
+
this.colorSchemeDidChange(oldColorScheme);
|
|
1829
|
+
},
|
|
1830
|
+
|
|
1831
|
+
/**
|
|
1832
|
+
* @protected
|
|
1833
|
+
* Invoked by CoreUI whenever the color scheme that the view should use changes.
|
|
1834
|
+
*
|
|
1835
|
+
* Subclasses may use this method to perform any changes needed to support the requested color scheme.
|
|
1836
|
+
* Subclasses that override this method must invoke the superclass method at some point in their implementation.
|
|
1837
|
+
*
|
|
1838
|
+
* @param scheme <BMViewColorScheme> The previous color scheme.
|
|
1839
|
+
*/
|
|
1840
|
+
colorSchemeDidChange(scheme) {
|
|
1841
|
+
|
|
1842
|
+
},
|
|
1843
|
+
|
|
1844
|
+
// #endregion
|
|
1845
|
+
|
|
1787
1846
|
// #region Intrinsic Size
|
|
1788
1847
|
|
|
1789
1848
|
/**
|