neo.mjs 8.0.0-alpha.1 → 8.0.0-beta.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/.github/CODING_GUIDELINES.md +5 -5
- package/.github/CONCEPT.md +10 -10
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/covid/view/MainContainer.mjs +14 -14
- package/apps/covid/view/TableContainer.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/ViewportController.mjs +2 -2
- package/apps/portal/view/examples/TabContainer.mjs +11 -11
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/home/parts/MainNeo.mjs +6 -2
- package/apps/realworld/view/article/CreateComponent.mjs +1 -1
- package/apps/realworld2/view/HomeContainer.mjs +7 -7
- package/apps/sharedcovid/view/MainContainer.mjs +17 -17
- package/apps/sharedcovid/view/TableContainer.mjs +2 -2
- package/buildScripts/createApp.mjs +2 -2
- package/buildScripts/createClass.mjs +4 -6
- package/docs/app/view/ContentTabContainer.mjs +1 -1
- package/docs/app/view/MainContainer.mjs +3 -3
- package/docs/app/view/MainContainerController.mjs +9 -9
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/component/mwc/buttons/MainContainer.mjs +2 -2
- package/examples/component/mwc/textFields/MainContainer.mjs +2 -2
- package/examples/fields/MainContainer.mjs +197 -228
- package/examples/preloadingAssets/view/MainContainer.mjs +2 -2
- package/examples/tab/container/MainContainer.mjs +7 -9
- package/examples/tabs/MainContainer.mjs +3 -3
- package/examples/tabs/MainContainer2.mjs +4 -4
- package/examples/videoMove/MainContainer.mjs +14 -7
- package/examples/viewport/MainContainer.mjs +3 -3
- package/package.json +6 -6
- package/resources/data/deck/learnneo/pages/benefits/FormsEngine.md +13 -13
- package/resources/data/deck/learnneo/pages/benefits/Speed.md +5 -4
- package/resources/data/deck/training/pages/2022-12-27T21-55-23-144Z.md +2 -2
- package/resources/data/deck/training/pages/2022-12-28T17-11-34-653Z.md +6 -6
- package/resources/data/deck/training/pages/2022-12-29T18-36-08-226Z.md +2 -2
- package/resources/data/deck/training/pages/2022-12-29T18-36-56-893Z.md +2 -2
- package/resources/data/deck/training/pages/2022-12-29T20-37-08-919Z.md +2 -2
- package/resources/data/deck/training/pages/2022-12-29T20-37-20-344Z.md +2 -2
- package/resources/data/deck/training/pages/2023-01-01T21-11-58-025Z.md +3 -3
- package/resources/data/deck/training/pages/2023-01-16T20-24-09-690Z.md +4 -4
- package/resources/data/deck/training/pages/2023-02-05T17-44-53-815Z.md +3 -3
- package/resources/data/deck/training/pages/2023-02-05T17-45-40-114Z.md +1 -1
- package/resources/scss/src/calendar/view/week/Component.scss +6 -0
- package/resources/scss/src/component/DateSelector.scss +1 -0
- package/src/DefaultConfig.mjs +2 -2
- package/src/calendar/view/MainContainer.mjs +4 -1
- package/src/calendar/view/SettingsContainer.mjs +13 -28
- package/src/calendar/view/YearComponent.mjs +0 -3
- package/src/calendar/view/calendars/ColorsList.mjs +5 -0
- package/src/calendar/view/calendars/List.mjs +8 -0
- package/src/code/LivePreview.mjs +10 -10
- package/src/component/Base.mjs +88 -55
- package/src/container/Base.mjs +2 -2
- package/src/form/field/Text.mjs +1 -1
- package/src/form/field/Time.mjs +5 -3
- package/src/form/field/trigger/Time.mjs +2 -1
- package/src/layout/Card.mjs +10 -6
- package/src/layout/Cube.mjs +15 -4
- package/src/list/Base.mjs +7 -1
- package/src/list/Color.mjs +3 -3
- package/src/main/DomEvents.mjs +1 -1
- package/src/main/DomUtils.mjs +39 -36
- package/src/tab/Container.mjs +3 -5
- package/src/toolbar/Base.mjs +26 -8
- package/src/util/VNode.mjs +6 -8
- package/src/vdom/Helper.mjs +19 -6
package/src/component/Base.mjs
CHANGED
@@ -208,10 +208,10 @@ class Base extends CoreBase {
|
|
208
208
|
isLoading_: false,
|
209
209
|
/**
|
210
210
|
* Internal flag which will get set to true while an update request (worker messages) is in progress
|
211
|
-
* @member {Boolean}
|
211
|
+
* @member {Boolean} isVdomUpdating_=false
|
212
212
|
* @protected
|
213
213
|
*/
|
214
|
-
|
214
|
+
isVdomUpdating_: false,
|
215
215
|
/**
|
216
216
|
* Using the keys config will create an instance of Neo.util.KeyNavigation.
|
217
217
|
* @see {@link Neo.util.KeyNavigation KeyNavigation}
|
@@ -404,6 +404,11 @@ class Base extends CoreBase {
|
|
404
404
|
* @member {String[]} childUpdateCache=[]
|
405
405
|
*/
|
406
406
|
childUpdateCache = []
|
407
|
+
/**
|
408
|
+
* Stores the updateDepth while an update is running to enable checks for parent update collisions
|
409
|
+
* @member {Number|null} currentUpdateDepth=null
|
410
|
+
*/
|
411
|
+
currentUpdateDepth = null
|
407
412
|
/**
|
408
413
|
* @member {Function[]} resolveUpdateCache=[]
|
409
414
|
*/
|
@@ -732,13 +737,13 @@ class Base extends CoreBase {
|
|
732
737
|
* @protected
|
733
738
|
*/
|
734
739
|
afterSetIsLoading(value, oldValue) {
|
735
|
-
if (
|
740
|
+
if (value || oldValue !== undefined) {
|
736
741
|
let me = this,
|
737
742
|
{cls, vdom} = me,
|
738
743
|
maskIndex;
|
739
744
|
|
740
745
|
if (oldValue !== undefined && vdom.cn) {
|
741
|
-
maskIndex = vdom.cn.
|
746
|
+
maskIndex = vdom.cn.findLastIndex(c => c.cls?.includes('neo-load-mask'));
|
742
747
|
|
743
748
|
// Remove the load mask
|
744
749
|
if (maskIndex !== -1) {
|
@@ -747,19 +752,11 @@ class Base extends CoreBase {
|
|
747
752
|
}
|
748
753
|
|
749
754
|
if (value) {
|
750
|
-
vdom.cn
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
cls: me.loadingSpinnerCls
|
756
|
-
}, {
|
757
|
-
cls : ['neo-loading-message'],
|
758
|
-
html : value,
|
759
|
-
removeDom: !Neo.isString(value)
|
760
|
-
}]
|
761
|
-
}]
|
762
|
-
})
|
755
|
+
if (!vdom.cn) {
|
756
|
+
vdom.cn = []
|
757
|
+
}
|
758
|
+
|
759
|
+
vdom.cn.push(me.createLoadingMask(value))
|
763
760
|
}
|
764
761
|
|
765
762
|
NeoArray.toggle(cls, 'neo-masked', value);
|
@@ -767,6 +764,16 @@ class Base extends CoreBase {
|
|
767
764
|
}
|
768
765
|
}
|
769
766
|
|
767
|
+
/**
|
768
|
+
* Triggered after the isVdomUpdating config got changed
|
769
|
+
* @param {Number|null} value
|
770
|
+
* @param {Number|null} oldValue
|
771
|
+
* @protected
|
772
|
+
*/
|
773
|
+
afterSetIsVdomUpdating(value, oldValue) {
|
774
|
+
this.currentUpdateDepth = value ? this.updateDepth : null
|
775
|
+
}
|
776
|
+
|
770
777
|
/**
|
771
778
|
* Triggered after the maxHeight config got changed
|
772
779
|
* @param {Number|String|null} value
|
@@ -1388,6 +1395,28 @@ class Base extends CoreBase {
|
|
1388
1395
|
me.update()
|
1389
1396
|
}
|
1390
1397
|
|
1398
|
+
/**
|
1399
|
+
* Override this method in case you need different mask markups.
|
1400
|
+
* The removal logic relies on the top level node having the cls 'neo-load-mask'
|
1401
|
+
* @param {Boolean|String} loadingMessage
|
1402
|
+
* @returns {Object} vdom
|
1403
|
+
*/
|
1404
|
+
createLoadingMask(loadingMessage) {
|
1405
|
+
return {
|
1406
|
+
cls: ['neo-load-mask'],
|
1407
|
+
cn : [{
|
1408
|
+
cls: ['neo-load-mask-body'],
|
1409
|
+
cn : [{
|
1410
|
+
cls: this.loadingSpinnerCls
|
1411
|
+
}, {
|
1412
|
+
cls : ['neo-loading-message'],
|
1413
|
+
html : loadingMessage,
|
1414
|
+
removeDom: !Neo.isString(loadingMessage)
|
1415
|
+
}]
|
1416
|
+
}]
|
1417
|
+
}
|
1418
|
+
}
|
1419
|
+
|
1391
1420
|
/**
|
1392
1421
|
* Creates the tooltip instances
|
1393
1422
|
* @param {Object|String} value
|
@@ -1830,6 +1859,16 @@ class Base extends CoreBase {
|
|
1830
1859
|
return this.vnode
|
1831
1860
|
}
|
1832
1861
|
|
1862
|
+
/**
|
1863
|
+
* Checks if a given updateDepth & distance would result in an update collision
|
1864
|
+
* @param {Number} updateDepth
|
1865
|
+
* @param {Number} distance
|
1866
|
+
* @returns {Boolean}
|
1867
|
+
*/
|
1868
|
+
hasUpdateCollision(updateDepth, distance) {
|
1869
|
+
return updateDepth === -1 ? true : distance < updateDepth
|
1870
|
+
}
|
1871
|
+
|
1833
1872
|
/**
|
1834
1873
|
* Hide the component.
|
1835
1874
|
* hideMode: 'removeDom' uses vdom removeDom.
|
@@ -1844,6 +1883,7 @@ class Base extends CoreBase {
|
|
1844
1883
|
let removeFn = function () {
|
1845
1884
|
if (me.parentId !== 'document.body') {
|
1846
1885
|
me.vdom.removeDom = true;
|
1886
|
+
me.parent.updateDepth = 2;
|
1847
1887
|
me.parent.update()
|
1848
1888
|
} else {
|
1849
1889
|
me.unmount()
|
@@ -1889,29 +1929,35 @@ class Base extends CoreBase {
|
|
1889
1929
|
* Checks for vdom updates inside the parent chain and if found.
|
1890
1930
|
* Registers the component for a vdom update once done.
|
1891
1931
|
* @param {String} parentId=this.parentId
|
1892
|
-
* @param {Function} [resolve]
|
1932
|
+
* @param {Function} [resolve] Gets passed by updateVdom()
|
1933
|
+
* @param {Number} distance=1 Distance inside the component tree
|
1893
1934
|
* @returns {Boolean}
|
1894
1935
|
*/
|
1895
|
-
|
1936
|
+
isParentUpdating(parentId=this.parentId, resolve, distance=1) {
|
1896
1937
|
if (parentId !== 'document.body') {
|
1897
1938
|
let me = this,
|
1898
1939
|
parent = Neo.getComponent(parentId);
|
1899
1940
|
|
1900
1941
|
if (parent) {
|
1901
1942
|
if (parent.isVdomUpdating) {
|
1902
|
-
if (
|
1903
|
-
|
1904
|
-
|
1943
|
+
if (me.hasUpdateCollision(parent.currentUpdateDepth, distance)) {
|
1944
|
+
if (Neo.config.logVdomUpdateCollisions) {
|
1945
|
+
console.warn('vdom parent update conflict with:', parent, 'for:', me)
|
1946
|
+
}
|
1905
1947
|
|
1906
|
-
|
1948
|
+
NeoArray.add(parent.childUpdateCache, me.id);
|
1907
1949
|
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
1950
|
+
// Adding the resolve fn to its own cache, since the parent will trigger
|
1951
|
+
// a new update() directly on this cmp
|
1952
|
+
resolve && me.resolveUpdateCache.push(resolve);
|
1953
|
+
return true
|
1954
|
+
}
|
1955
|
+
|
1956
|
+
// If an update is running and does not have a collision, we do not need to check further parents
|
1957
|
+
return false
|
1914
1958
|
}
|
1959
|
+
|
1960
|
+
return me.isParentUpdating(parent.parentId, resolve, distance+1)
|
1915
1961
|
}
|
1916
1962
|
}
|
1917
1963
|
|
@@ -2022,22 +2068,24 @@ class Base extends CoreBase {
|
|
2022
2068
|
* Checks the needsVdomUpdate config inside the parent tree
|
2023
2069
|
* @param {String} parentId=this.parentId
|
2024
2070
|
* @param {Function} [resolve] gets passed by updateVdom()
|
2071
|
+
* @param {Number} distance=1 Distance inside the component tree
|
2025
2072
|
* @returns {Boolean}
|
2026
2073
|
*/
|
2027
|
-
needsParentUpdate(parentId=this.parentId, resolve) {
|
2074
|
+
needsParentUpdate(parentId=this.parentId, resolve, distance=1) {
|
2028
2075
|
if (parentId !== 'document.body') {
|
2029
2076
|
let me = this,
|
2030
2077
|
parent = Neo.getComponent(parentId);
|
2031
2078
|
|
2032
2079
|
if (parent) {
|
2033
|
-
|
2080
|
+
// We are checking for parent.updateDepth, since we care about the depth of the next update cycle
|
2081
|
+
if (parent.needsVdomUpdate && me.hasUpdateCollision(parent.updateDepth, distance)) {
|
2034
2082
|
parent.resolveUpdateCache.push(...me.resolveUpdateCache);
|
2035
2083
|
resolve && parent.resolveUpdateCache.push(resolve);
|
2036
2084
|
me.resolveUpdateCache = [];
|
2037
2085
|
return true
|
2038
|
-
} else {
|
2039
|
-
return me.needsParentUpdate(parent.parentId)
|
2040
2086
|
}
|
2087
|
+
|
2088
|
+
return me.needsParentUpdate(parent.parentId, resolve, distance+1)
|
2041
2089
|
}
|
2042
2090
|
}
|
2043
2091
|
|
@@ -2148,7 +2196,7 @@ class Base extends CoreBase {
|
|
2148
2196
|
* @param {Neo.vdom.VNode} vnode= this.vnode
|
2149
2197
|
* @returns {Promise<any>}
|
2150
2198
|
*/
|
2151
|
-
promiseUpdate(vdom
|
2199
|
+
promiseUpdate(vdom=this.vdom, vnode=this.vnode) {
|
2152
2200
|
return new Promise((resolve, reject) => {
|
2153
2201
|
this.updateVdom(vdom, vnode, resolve, reject)
|
2154
2202
|
})
|
@@ -2349,6 +2397,7 @@ class Base extends CoreBase {
|
|
2349
2397
|
if (me.silentVdomUpdate) {
|
2350
2398
|
me.needsVdomUpdate = true
|
2351
2399
|
} else if (me.parentId !== 'document.body') {
|
2400
|
+
me.parent.updateDepth = 2;
|
2352
2401
|
me.parent.update()
|
2353
2402
|
} else {
|
2354
2403
|
!me.mounted && me.render(true)
|
@@ -2398,7 +2447,7 @@ class Base extends CoreBase {
|
|
2398
2447
|
|
2399
2448
|
// we need one separate iteration first to ensure all wrapper nodes get registered
|
2400
2449
|
childComponents.forEach(component => {
|
2401
|
-
childVnode = VNodeUtil.
|
2450
|
+
childVnode = VNodeUtil.find(me.vnode, component.vdom.id)?.vnode;
|
2402
2451
|
|
2403
2452
|
if (childVnode) {
|
2404
2453
|
map[component.id] = childVnode;
|
@@ -2486,7 +2535,7 @@ class Base extends CoreBase {
|
|
2486
2535
|
updateCls(cls, oldCls, id=this.id) {
|
2487
2536
|
let me = this,
|
2488
2537
|
{vnode} = me,
|
2489
|
-
vnodeTarget = vnode && VNodeUtil.
|
2538
|
+
vnodeTarget = vnode && VNodeUtil.find(me.vnode, {id})?.vnode;
|
2490
2539
|
|
2491
2540
|
if (vnode && !Neo.isEqual(cls, oldCls)) {
|
2492
2541
|
if (vnodeTarget) {
|
@@ -2518,7 +2567,7 @@ class Base extends CoreBase {
|
|
2518
2567
|
|
2519
2568
|
if (delta) {
|
2520
2569
|
vdom = VDomUtil.find(me.vdom, id);
|
2521
|
-
vnode = me.vnode && VNodeUtil.
|
2570
|
+
vnode = me.vnode && VNodeUtil.find(me.vnode, id);
|
2522
2571
|
|
2523
2572
|
if (!me.hasUnmountedVdomChanges) {
|
2524
2573
|
me.hasUnmountedVdomChanges = !me.mounted && me.hasBeenMounted
|
@@ -2569,24 +2618,8 @@ class Base extends CoreBase {
|
|
2569
2618
|
{app, mounted, parentId} = me,
|
2570
2619
|
listenerId;
|
2571
2620
|
|
2572
|
-
// It is important to keep the vdom tree stable to ensure that containers do not lose the references to their
|
2573
|
-
// child vdom trees. The if case should not happen, but in case it does, keeping the reference and merging
|
2574
|
-
// the content over seems to be the best strategy
|
2575
|
-
if (me._vdom !== vdom) {
|
2576
|
-
Logger.warn('vdom got replaced for: ' + me.id + '. Copying the content into the reference holder object');
|
2577
|
-
|
2578
|
-
Object.keys(me._vdom).forEach(key => {
|
2579
|
-
delete me._vdom[key]
|
2580
|
-
});
|
2581
|
-
|
2582
|
-
vdom = Object.assign(me._vdom, vdom)
|
2583
|
-
}
|
2584
|
-
|
2585
|
-
if (resolve && me.isVdomUpdating) {
|
2586
|
-
me.resolveUpdateCache.push(resolve)
|
2587
|
-
}
|
2588
|
-
|
2589
2621
|
if (me.isVdomUpdating || me.silentVdomUpdate) {
|
2622
|
+
resolve && me.resolveUpdateCache.push(resolve);
|
2590
2623
|
me.needsVdomUpdate = true
|
2591
2624
|
} else {
|
2592
2625
|
if (!mounted && me.isConstructed && !me.hasRenderingListener && app?.rendering === true) {
|
@@ -2606,7 +2639,7 @@ class Base extends CoreBase {
|
|
2606
2639
|
|
2607
2640
|
if (
|
2608
2641
|
!me.needsParentUpdate(parentId, resolve)
|
2609
|
-
&& !me.
|
2642
|
+
&& !me.isParentUpdating(parentId, resolve)
|
2610
2643
|
&& mounted
|
2611
2644
|
&& vnode
|
2612
2645
|
) {
|
package/src/container/Base.mjs
CHANGED
@@ -168,7 +168,7 @@ class Base extends Component {
|
|
168
168
|
if (oldValue !== undefined) {
|
169
169
|
super.afterSetMounted(value, oldValue);
|
170
170
|
|
171
|
-
for (let i = 0, {
|
171
|
+
for (let i = 0, {items} = this, {length} = items; i < length; i++) {
|
172
172
|
if (!items[i].vdom.removeDom) {
|
173
173
|
items[i].mounted = value
|
174
174
|
}
|
@@ -500,7 +500,7 @@ class Base extends Component {
|
|
500
500
|
/**
|
501
501
|
* Inserts an item or array of items at a specific index
|
502
502
|
* @param {Number} index
|
503
|
-
* @param {Object
|
503
|
+
* @param {Array|Object} item
|
504
504
|
* @param {Boolean} [silent=false]
|
505
505
|
* @returns {Neo.component.Base|Neo.component.Base[]}
|
506
506
|
*/
|
package/src/form/field/Text.mjs
CHANGED
@@ -1356,7 +1356,7 @@ class Text extends Base {
|
|
1356
1356
|
let me = this,
|
1357
1357
|
oldValue = me.value,
|
1358
1358
|
inputValue = data.value,
|
1359
|
-
vnode = VNodeUtil.
|
1359
|
+
vnode = VNodeUtil.find(me.vnode, {nodeName: 'input'});
|
1360
1360
|
|
1361
1361
|
if (vnode) {
|
1362
1362
|
// Update the current state (modified DOM by the user) to enable the delta-updates logic.
|
package/src/form/field/Time.mjs
CHANGED
@@ -101,9 +101,11 @@ class Time extends Picker {
|
|
101
101
|
});
|
102
102
|
|
103
103
|
me.list = Neo.create({
|
104
|
-
module
|
105
|
-
displayField: 'value',
|
106
|
-
|
104
|
+
module : List,
|
105
|
+
displayField : 'value',
|
106
|
+
itemsFocusable: false,
|
107
|
+
navigator : {eventSource: me.getInputElId()},
|
108
|
+
store : me.collection,
|
107
109
|
...me.listConfig
|
108
110
|
});
|
109
111
|
|
package/src/layout/Card.mjs
CHANGED
@@ -201,14 +201,14 @@ class Card extends Base {
|
|
201
201
|
item.className = proto.className;
|
202
202
|
item.module = module;
|
203
203
|
|
204
|
-
me.applyChildAttributes(item, index);
|
205
|
-
|
206
204
|
delete item.isLoading;
|
207
205
|
delete item.vdom;
|
208
206
|
|
209
207
|
items[index] = item = Neo.create(item);
|
210
208
|
|
211
|
-
|
209
|
+
me.applyChildAttributes(item, index);
|
210
|
+
|
211
|
+
container.getVdomItemsRoot().cn[index] = item.createVdomReference();
|
212
212
|
|
213
213
|
container.fire('cardLoaded', {item});
|
214
214
|
|
@@ -253,13 +253,15 @@ class Card extends Base {
|
|
253
253
|
|
254
254
|
vdom.cn = [
|
255
255
|
{cls: ['neo-relative'], cn: [
|
256
|
-
{cls: ['neo-animation-wrapper'], style, cn: [card.
|
256
|
+
{cls: ['neo-animation-wrapper'], style, cn: [card.createVdomReference()]}
|
257
257
|
]}
|
258
258
|
];
|
259
259
|
|
260
260
|
animationWrapper = vdom.cn[0].cn[0];
|
261
261
|
|
262
|
-
animationWrapper.cn[slideIn ? 'unshift' : 'push'](oldCard.
|
262
|
+
animationWrapper.cn[slideIn ? 'unshift' : 'push'](oldCard.createVdomReference());
|
263
|
+
|
264
|
+
container.updateDepth = -1;
|
263
265
|
|
264
266
|
await container.promiseUpdate();
|
265
267
|
|
@@ -274,11 +276,13 @@ class Card extends Base {
|
|
274
276
|
vdom.cn = [];
|
275
277
|
|
276
278
|
container.items.forEach(item => {
|
277
|
-
vdom.cn.push(item.
|
279
|
+
vdom.cn.push(item.createVdomReference())
|
278
280
|
});
|
279
281
|
|
280
282
|
oldCard.vdom.removeDom = true;
|
281
283
|
|
284
|
+
container.updateDepth = -1;
|
285
|
+
|
282
286
|
await container.promiseUpdate()
|
283
287
|
}
|
284
288
|
}
|
package/src/layout/Cube.mjs
CHANGED
@@ -144,6 +144,7 @@ class Cube extends Card {
|
|
144
144
|
|
145
145
|
if (Neo.typeOf(item.module) === 'Function') {
|
146
146
|
await me.loadModule(item, value);
|
147
|
+
container.updateDepth = -1;
|
147
148
|
container.update();
|
148
149
|
|
149
150
|
await me.timeout(100) // wait for the view to get painted first
|
@@ -276,6 +277,14 @@ class Cube extends Card {
|
|
276
277
|
}
|
277
278
|
}
|
278
279
|
|
280
|
+
/**
|
281
|
+
* @protected
|
282
|
+
*/
|
283
|
+
applyRenderAttributes() {
|
284
|
+
this.container.updateDepth = -1;
|
285
|
+
super.applyRenderAttributes()
|
286
|
+
}
|
287
|
+
|
279
288
|
/**
|
280
289
|
*
|
281
290
|
*/
|
@@ -299,9 +308,9 @@ class Cube extends Card {
|
|
299
308
|
vdom.cn = container.getVdomItemsRoot().cn;
|
300
309
|
|
301
310
|
if (me.hideInactiveCardsOnDestroy) {
|
302
|
-
|
311
|
+
container.items.forEach((item, index) => {
|
303
312
|
if (index < 6 && index !== me.activeIndex) {
|
304
|
-
item.removeDom = true
|
313
|
+
item.vdom.removeDom = true
|
305
314
|
}
|
306
315
|
})
|
307
316
|
}
|
@@ -309,6 +318,7 @@ class Cube extends Card {
|
|
309
318
|
// override
|
310
319
|
container.getVdomItemsRoot = me.#cachedVdomItemsRoot;
|
311
320
|
|
321
|
+
container.updateDepth = -1;
|
312
322
|
container.update();
|
313
323
|
|
314
324
|
super.destroy(...args)
|
@@ -336,12 +346,13 @@ class Cube extends Card {
|
|
336
346
|
|
337
347
|
me.timeout(50).then(() => {
|
338
348
|
// Important when switching from a card layout to this one
|
339
|
-
container.
|
349
|
+
container.items.forEach((item, index) => {
|
340
350
|
if (index < 6) {
|
341
|
-
delete
|
351
|
+
delete item.vdom.removeDom
|
342
352
|
}
|
343
353
|
});
|
344
354
|
|
355
|
+
container.updateDepth = -1;
|
345
356
|
container.update()
|
346
357
|
})
|
347
358
|
}
|
package/src/list/Base.mjs
CHANGED
@@ -125,7 +125,12 @@ class Base extends Component {
|
|
125
125
|
*/
|
126
126
|
selectionModel_: null,
|
127
127
|
/**
|
128
|
-
* Set this to true in case a
|
128
|
+
* Set this to true in case a keyboard navigation should immediately select the focussed item
|
129
|
+
* @member {Boolean} selectOnFocus=false
|
130
|
+
*/
|
131
|
+
selectOnFocus: false,
|
132
|
+
/**
|
133
|
+
* Set this to true in case a select event should only update _vdom (e.g. when used inside a form.field.ComboBox
|
129
134
|
* @member {Boolean} silentSelect=false
|
130
135
|
*/
|
131
136
|
silentSelect: false,
|
@@ -298,6 +303,7 @@ class Base extends Component {
|
|
298
303
|
if (!me.hasNavigator) {
|
299
304
|
me.navigator = {
|
300
305
|
appName : me.appName,
|
306
|
+
autoClick : me.selectOnFocus,
|
301
307
|
id : me.id,
|
302
308
|
keepFocusIndex: me.keepFocusIndex,
|
303
309
|
selector : `.${me.itemCls}:not(.neo-disabled,.neo-list-header)`,
|
package/src/list/Color.mjs
CHANGED
@@ -22,13 +22,13 @@ class Color extends Base {
|
|
22
22
|
baseCls: ['neo-color-list', 'neo-list'],
|
23
23
|
/**
|
24
24
|
* The data.Model field which contains the color value
|
25
|
-
* @member {String}
|
25
|
+
* @member {String} colorField_='name'
|
26
26
|
*/
|
27
|
-
|
27
|
+
colorField_: 'name',
|
28
28
|
/**
|
29
29
|
* Override the formatter to apply a custom background-color styling.
|
30
30
|
* E.g. using CSS vars for different themes
|
31
|
-
* @member {Function}
|
31
|
+
* @member {Function} colorFormatter=(scope,data)=>data[scope.colorField]
|
32
32
|
*/
|
33
33
|
colorFormatter: (scope,data) => data[scope.colorField]
|
34
34
|
}
|
package/src/main/DomEvents.mjs
CHANGED
package/src/main/DomUtils.mjs
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
import Base from '../core/Base.mjs';
|
2
2
|
|
3
3
|
const focusableTags = {
|
4
|
-
BODY
|
5
|
-
BUTTON
|
6
|
-
EMBED
|
7
|
-
IFRAME
|
8
|
-
INPUT
|
9
|
-
OBJECT
|
10
|
-
SELECT
|
11
|
-
TEXTAREA
|
4
|
+
BODY : 1,
|
5
|
+
BUTTON : 1,
|
6
|
+
EMBED : 1,
|
7
|
+
IFRAME : 1,
|
8
|
+
INPUT : 1,
|
9
|
+
OBJECT : 1,
|
10
|
+
SELECT : 1,
|
11
|
+
TEXTAREA: 1
|
12
12
|
};
|
13
13
|
|
14
14
|
/**
|
15
|
-
* @class Neo.main.DomUtils
|
15
|
+
* @class Neo.main.DomUtils
|
16
16
|
* @extends Neo.core.Base
|
17
17
|
* @singleton
|
18
18
|
*/
|
19
|
-
|
19
|
+
class DomUtils extends Base {
|
20
20
|
static config = {
|
21
21
|
/**
|
22
22
|
* @member {String} className='Neo.main.DomUtils'
|
@@ -31,42 +31,21 @@ export default class DomUtils extends Base {
|
|
31
31
|
* @param {HTMLElement} el The element to start from.
|
32
32
|
* @param {Function} filterFn A function which returns `true` when the desired element is reached.
|
33
33
|
* @param {HTMLElement} [limit] The element to stop at. This is *not* considered for matching.
|
34
|
-
* @returns {
|
34
|
+
* @returns {HTMLElement}
|
35
35
|
*/
|
36
36
|
static closest(el, filterFn, limit = document.body) {
|
37
37
|
while (el?.nodeType === Node.ELEMENT_NODE && el !== limit) {
|
38
38
|
if (filterFn(el)) {
|
39
|
-
return el
|
39
|
+
return el
|
40
40
|
}
|
41
|
-
el = el.parentNode;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
/**
|
46
|
-
* Analogous to the `HTMLElement` `querySelectorAll` method. Searches the passed element
|
47
|
-
* and all descendants for all elements for which the passed `filterFn` returns `true`.
|
48
|
-
* @param {HTMLElement} el The element to start from.
|
49
|
-
* @param {Function} filterFn A function which returns `true` when a desired element is reached.
|
50
|
-
* @returns {HTMLElement[]} An array of matching elements
|
51
|
-
*/
|
52
|
-
static queryAll(el, filterFn) {
|
53
|
-
return [el, ...el.querySelectorAll('*')].filter(filterFn);
|
54
|
-
}
|
55
41
|
|
56
|
-
|
57
|
-
|
58
|
-
* and all descendants for the first element for which the passed `filterFn` returns `true`.
|
59
|
-
* @param {HTMLElement} el The element to start from.
|
60
|
-
* @param {Function} filterFn A function which returns `true` when the desired element is reached.
|
61
|
-
* @returns {HTMLElement} The first matching element
|
62
|
-
*/
|
63
|
-
static query(el, filterFn) {
|
64
|
-
return [el, ...el.querySelectorAll('*')].find(filterFn);
|
42
|
+
el = el.parentNode
|
43
|
+
}
|
65
44
|
}
|
66
45
|
|
67
46
|
static isFocusable(e) {
|
68
47
|
// May be used as a scopeless callback, so use "DomUtils", not "this"
|
69
|
-
return DomUtils.isTabbable(e) || Number(e.getAttribute('tabIndex')) < 0
|
48
|
+
return DomUtils.isTabbable(e) || Number(e.getAttribute('tabIndex')) < 0
|
70
49
|
}
|
71
50
|
|
72
51
|
static isTabbable(e) {
|
@@ -86,4 +65,28 @@ export default class DomUtils extends Base {
|
|
86
65
|
(tabIndex != null && Number(tabIndex) >= 0) ||
|
87
66
|
e.contentEditable === 'true'
|
88
67
|
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Analogous to the `HTMLElement` `querySelector` method. Searches the passed element
|
71
|
+
* and all descendants for the first element for which the passed `filterFn` returns `true`.
|
72
|
+
* @param {HTMLElement} el The element to start from.
|
73
|
+
* @param {Function} filterFn A function which returns `true` when the desired element is reached.
|
74
|
+
* @returns {HTMLElement} The first matching element
|
75
|
+
*/
|
76
|
+
static query(el, filterFn) {
|
77
|
+
return [el, ...el.querySelectorAll('*')].find(filterFn);
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* Analogous to the `HTMLElement` `querySelectorAll` method. Searches the passed element
|
82
|
+
* and all descendants for all elements for which the passed `filterFn` returns `true`.
|
83
|
+
* @param {HTMLElement} el The element to start from.
|
84
|
+
* @param {Function} filterFn A function which returns `true` when a desired element is reached.
|
85
|
+
* @returns {HTMLElement[]} An array of matching elements
|
86
|
+
*/
|
87
|
+
static queryAll(el, filterFn) {
|
88
|
+
return [el, ...el.querySelectorAll('*')].filter(filterFn)
|
89
|
+
}
|
89
90
|
}
|
91
|
+
|
92
|
+
export default Neo.setupClass(DomUtils);
|
package/src/tab/Container.mjs
CHANGED
@@ -243,7 +243,7 @@ class Container extends BaseContainer {
|
|
243
243
|
});
|
244
244
|
|
245
245
|
items.forEach((item, index) => {
|
246
|
-
tabButtons.push(me.getTabButtonConfig(item.
|
246
|
+
tabButtons.push(me.getTabButtonConfig(item.header, index));
|
247
247
|
|
248
248
|
if (!(item instanceof Neo.component.Base)) {
|
249
249
|
item = {flex: 1, ...me.itemDefaults, isTab: true, ...item}
|
@@ -410,7 +410,7 @@ class Container extends BaseContainer {
|
|
410
410
|
cardContainer = me.getCardContainer(),
|
411
411
|
tabBar = me.getTabBar(),
|
412
412
|
hasItem = false,
|
413
|
-
i, len, returnArray, superItem, tab
|
413
|
+
i, len, returnArray, superItem, tab;
|
414
414
|
|
415
415
|
if (Array.isArray(item)) {
|
416
416
|
i = 0;
|
@@ -441,9 +441,7 @@ class Container extends BaseContainer {
|
|
441
441
|
}
|
442
442
|
|
443
443
|
if (!hasItem) {
|
444
|
-
|
445
|
-
|
446
|
-
tab = tabBar.insert(index, me.getTabButtonConfig(tabButtonConfig, index));
|
444
|
+
tab = tabBar.insert(index, me.getTabButtonConfig(item.header, index));
|
447
445
|
|
448
446
|
// todo: non index based matching of tab buttons and cards
|
449
447
|
i = 0;
|