neo.mjs 5.15.1 → 5.15.3
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/apps/ServiceWorker.mjs +2 -2
- package/apps/realworld2/view/article/PreviewList.mjs +1 -1
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +4 -1
- package/src/calendar/view/MainContainer.mjs +2 -2
- package/src/calendar/view/SettingsContainer.mjs +2 -2
- package/src/calendar/view/YearComponent.mjs +2 -2
- package/src/calendar/view/month/Component.mjs +1 -1
- package/src/calendar/view/week/Component.mjs +1 -1
- package/src/component/Base.mjs +140 -113
- package/src/component/Circle.mjs +2 -2
- package/src/component/DateSelector.mjs +3 -3
- package/src/component/Gallery.mjs +1 -1
- package/src/component/Helix.mjs +1 -1
- package/src/container/Base.mjs +1 -1
- package/src/container/_export.mjs +1 -2
- package/src/data/connection/_export.mjs +3 -3
- package/src/form/field/Date.mjs +1 -1
- package/src/form/field/Text.mjs +45 -43
- package/src/form/field/ZipCode.mjs +8 -6
- package/src/grid/View.mjs +1 -1
- package/src/list/Base.mjs +1 -1
- package/src/main/mixin/DeltaUpdates.mjs +5 -3
- package/src/table/View.mjs +1 -1
package/apps/ServiceWorker.mjs
CHANGED
package/package.json
CHANGED
package/src/DefaultConfig.mjs
CHANGED
@@ -245,12 +245,12 @@ const DefaultConfig = {
|
|
245
245
|
useVdomWorker: true,
|
246
246
|
/**
|
247
247
|
* buildScripts/injectPackageVersion.mjs will update this value
|
248
|
-
* @default '5.15.
|
248
|
+
* @default '5.15.3'
|
249
249
|
* @memberOf! module:Neo
|
250
250
|
* @name config.version
|
251
251
|
* @type String
|
252
252
|
*/
|
253
|
-
version: '5.15.
|
253
|
+
version: '5.15.3'
|
254
254
|
};
|
255
255
|
|
256
256
|
Object.assign(DefaultConfig, {
|
package/src/Neo.mjs
CHANGED
@@ -645,7 +645,10 @@ function autoGenerateGetSet(proto, key) {
|
|
645
645
|
me[_key] = value;
|
646
646
|
}
|
647
647
|
|
648
|
-
if (
|
648
|
+
if (
|
649
|
+
(key === 'vnode' && value !== oldValue) || // vnode trees can be huge, avoid a deep comparison
|
650
|
+
!Neo.isEqual(value, oldValue)
|
651
|
+
) {
|
649
652
|
me[afterSet]?.(value, oldValue);
|
650
653
|
me.afterSetConfig?.(key, value, oldValue);
|
651
654
|
}
|
@@ -261,7 +261,7 @@ class MainContainer extends Container {
|
|
261
261
|
if (value) {
|
262
262
|
delete sideBar.vdom.removeDom;
|
263
263
|
|
264
|
-
me.
|
264
|
+
me.promiseUpdate().then(() => {
|
265
265
|
sideBar.mounted = true;
|
266
266
|
|
267
267
|
setTimeout(() => {
|
@@ -274,7 +274,7 @@ class MainContainer extends Container {
|
|
274
274
|
sideBar._style = style; // silent update
|
275
275
|
sideBar._vdom.style = style; // silent update
|
276
276
|
|
277
|
-
me.
|
277
|
+
me.promiseUpdate().then(() => {
|
278
278
|
setTimeout(() => {
|
279
279
|
sideBar.vdom.removeDom = true;
|
280
280
|
sideBar.update();
|
@@ -57,7 +57,7 @@ class SettingsContainer extends Container {
|
|
57
57
|
me._style = style; // silent update
|
58
58
|
me._vdom.style = style; // silent update
|
59
59
|
|
60
|
-
Neo.getComponent(me.parentId).
|
60
|
+
Neo.getComponent(me.parentId).promiseUpdate().then(() => {
|
61
61
|
setTimeout(() => {
|
62
62
|
me.collapsed = true;
|
63
63
|
|
@@ -145,7 +145,7 @@ class SettingsContainer extends Container {
|
|
145
145
|
|
146
146
|
delete me.vdom.removeDom;
|
147
147
|
|
148
|
-
Neo.getComponent(me.parentId).
|
148
|
+
Neo.getComponent(me.parentId).promiseUpdate().then(() => {
|
149
149
|
me.collapsed = false;
|
150
150
|
me.mounted = true;
|
151
151
|
|
@@ -512,7 +512,7 @@ class YearComponent extends Component {
|
|
512
512
|
vdom.cn[1].cn[0].cn[scrollFromTop ? 'unshift' : 'push'](vdom.cn[0]);
|
513
513
|
vdom.cn.splice(0, 1);
|
514
514
|
|
515
|
-
me.
|
515
|
+
me.promiseUpdate(vdom).then(() => {
|
516
516
|
y = scrollFromTop ? -data.height : 0;
|
517
517
|
vdom.cn[0].cn[0].style.transform = `translateY(${y}px)`;
|
518
518
|
me.update();
|
@@ -783,7 +783,7 @@ class YearComponent extends Component {
|
|
783
783
|
|
784
784
|
me.isUpdating = true;
|
785
785
|
|
786
|
-
me.
|
786
|
+
me.promiseUpdate(me.vdom).then(() => {
|
787
787
|
me.isUpdating = false;
|
788
788
|
});
|
789
789
|
}
|
@@ -689,7 +689,7 @@ class Component extends BaseComponent {
|
|
689
689
|
week.header && container.cn.unshift(week.header);
|
690
690
|
}
|
691
691
|
|
692
|
-
me.
|
692
|
+
me.promiseUpdate(me.vdom).then(() => {
|
693
693
|
Neo.main.DomAccess.scrollTo({
|
694
694
|
direction: 'top',
|
695
695
|
id : me.vdom.cn[1].id,
|
@@ -805,7 +805,7 @@ class Component extends BaseComponent {
|
|
805
805
|
if (scrollValue) {
|
806
806
|
me.isUpdating = true;
|
807
807
|
|
808
|
-
me.
|
808
|
+
me.promiseUpdate().then(() => {
|
809
809
|
Neo.main.DomAccess.scrollBy({
|
810
810
|
direction: 'left',
|
811
811
|
id : me.getScrollContainer().id,
|
package/src/component/Base.mjs
CHANGED
@@ -313,6 +313,11 @@ class Base extends CoreBase {
|
|
313
313
|
*/
|
314
314
|
childUpdateCache = []
|
315
315
|
|
316
|
+
/**
|
317
|
+
* @member {Function[]} resolveUpdateCache=[]
|
318
|
+
*/
|
319
|
+
resolveUpdateCache = []
|
320
|
+
|
316
321
|
/**
|
317
322
|
* Apply component based listeners
|
318
323
|
* @member {Object} listeners={}
|
@@ -635,6 +640,8 @@ class Base extends CoreBase {
|
|
635
640
|
}, 100)
|
636
641
|
}
|
637
642
|
|
643
|
+
me.doResolveUpdateCache();
|
644
|
+
|
638
645
|
me.fire('mounted', me.id)
|
639
646
|
}
|
640
647
|
}
|
@@ -709,45 +716,7 @@ class Base extends CoreBase {
|
|
709
716
|
* @protected
|
710
717
|
*/
|
711
718
|
afterSetVdom(value, oldValue) {
|
712
|
-
|
713
|
-
app = Neo.apps[me.appName],
|
714
|
-
vdom = value,
|
715
|
-
listenerId;
|
716
|
-
|
717
|
-
// It is important to keep the vdom tree stable to ensure that containers do not lose the references to their
|
718
|
-
// child vdom trees. The if case should not happen, but in case it does, keeping the reference and merging
|
719
|
-
// the content over seems to be the best strategy
|
720
|
-
if (me._vdom !== vdom) {
|
721
|
-
Logger.warn('vdom got replaced for: ' + me.id + '. Copying the content into the reference holder object');
|
722
|
-
|
723
|
-
Object.keys(me._vdom).forEach(key => {
|
724
|
-
delete me._vdom[key]
|
725
|
-
});
|
726
|
-
|
727
|
-
vdom = Object.assign(me._vdom, vdom)
|
728
|
-
}
|
729
|
-
|
730
|
-
if (!me.needsParentUpdate()) {
|
731
|
-
if (me.silentVdomUpdate) {
|
732
|
-
me.needsVdomUpdate = true
|
733
|
-
} else {
|
734
|
-
if (!me.mounted && me.isConstructed && !me.hasRenderingListener && app?.rendering === true) {
|
735
|
-
me.hasRenderingListener = true;
|
736
|
-
|
737
|
-
listenerId = app.on('mounted', () => {
|
738
|
-
app.un('mounted', listenerId);
|
739
|
-
|
740
|
-
setTimeout(() => {
|
741
|
-
me.vnode && me.updateVdom(me.vdom, me.vnode)
|
742
|
-
}, 50)
|
743
|
-
});
|
744
|
-
} else if (me.mounted && me.vnode && !me.isParentVdomUpdating()) {
|
745
|
-
me.updateVdom(vdom, me.vnode)
|
746
|
-
}
|
747
|
-
}
|
748
|
-
}
|
749
|
-
|
750
|
-
me.hasUnmountedVdomChanges = !me.mounted && me.hasBeenMounted
|
719
|
+
this.updateVdom(value)
|
751
720
|
}
|
752
721
|
|
753
722
|
/**
|
@@ -1097,6 +1066,14 @@ class Base extends CoreBase {
|
|
1097
1066
|
super.destroy()
|
1098
1067
|
}
|
1099
1068
|
|
1069
|
+
/**
|
1070
|
+
* Triggers all stored resolve() callbacks
|
1071
|
+
*/
|
1072
|
+
doResolveUpdateCache() {
|
1073
|
+
this.resolveUpdateCache.forEach(item => item());
|
1074
|
+
this.resolveUpdateCache = [];
|
1075
|
+
}
|
1076
|
+
|
1100
1077
|
/**
|
1101
1078
|
* Convenience shortcut for Neo.manager.Component.down
|
1102
1079
|
* @param {Object|String} config
|
@@ -1107,6 +1084,55 @@ class Base extends CoreBase {
|
|
1107
1084
|
return ComponentManager.down(this, config, returnFirstMatch)
|
1108
1085
|
}
|
1109
1086
|
|
1087
|
+
/**
|
1088
|
+
* Internal method to send update requests to the vdom worker
|
1089
|
+
* @param {Object} vdom
|
1090
|
+
* @param {Neo.vdom.VNode} vnode
|
1091
|
+
* @param {function} [resolve] used by promiseUpdate()
|
1092
|
+
* @param {function} [reject] used by promiseUpdate()
|
1093
|
+
* @private
|
1094
|
+
*/
|
1095
|
+
#executeVdomUpdate(vdom, vnode, resolve, reject) {
|
1096
|
+
let me = this,
|
1097
|
+
opts = {vdom, vnode},
|
1098
|
+
deltas;
|
1099
|
+
|
1100
|
+
me.isVdomUpdating = true;
|
1101
|
+
|
1102
|
+
// we can not set the config directly => it could already be false,
|
1103
|
+
// and we still want to pass it further into subtrees
|
1104
|
+
me._needsVdomUpdate = false;
|
1105
|
+
me.afterSetNeedsVdomUpdate?.(false, true)
|
1106
|
+
|
1107
|
+
if (Neo.currentWorker.isSharedWorker) {
|
1108
|
+
opts.appName = me.appName
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
Neo.vdom.Helper.update(opts).catch(err => {
|
1112
|
+
console.log('Error attempting to update component dom', err, me);
|
1113
|
+
me.isVdomUpdating = false;
|
1114
|
+
|
1115
|
+
reject?.()
|
1116
|
+
}).then(data => {
|
1117
|
+
// checking if the component got destroyed before the update cycle is done
|
1118
|
+
if (me.id) {
|
1119
|
+
// console.log('Component vnode updated', data);
|
1120
|
+
me.vnode = data.vnode;
|
1121
|
+
me.isVdomUpdating = false;
|
1122
|
+
|
1123
|
+
deltas = data.deltas;
|
1124
|
+
|
1125
|
+
if (!Neo.config.useVdomWorker && deltas.length > 0) {
|
1126
|
+
Neo.applyDeltas(me.appName, deltas).then(() => {
|
1127
|
+
me.resolveVdomUpdate(resolve)
|
1128
|
+
})
|
1129
|
+
} else {
|
1130
|
+
me.resolveVdomUpdate(resolve)
|
1131
|
+
}
|
1132
|
+
}
|
1133
|
+
})
|
1134
|
+
}
|
1135
|
+
|
1110
1136
|
/**
|
1111
1137
|
* Calls focus() on the top level DOM node of this component or on a given node via id
|
1112
1138
|
* @param {String} id=this.id
|
@@ -1382,11 +1408,13 @@ class Base extends CoreBase {
|
|
1382
1408
|
}
|
1383
1409
|
|
1384
1410
|
/**
|
1385
|
-
* Checks for vdom updates inside the parent chain and if found
|
1411
|
+
* Checks for vdom updates inside the parent chain and if found.
|
1412
|
+
* Registers the component for a vdom update once done.
|
1386
1413
|
* @param {String} parentId=this.parentId
|
1414
|
+
* @param {Function} [resolve] gets passed by updateVdom()
|
1387
1415
|
* @returns {Boolean}
|
1388
1416
|
*/
|
1389
|
-
isParentVdomUpdating(parentId=this.parentId) {
|
1417
|
+
isParentVdomUpdating(parentId=this.parentId, resolve) {
|
1390
1418
|
if (parentId !== 'document.body') {
|
1391
1419
|
let me = this,
|
1392
1420
|
parent = Neo.getComponent(parentId);
|
@@ -1398,6 +1426,10 @@ class Base extends CoreBase {
|
|
1398
1426
|
}
|
1399
1427
|
|
1400
1428
|
NeoArray.add(parent.childUpdateCache, me.id);
|
1429
|
+
|
1430
|
+
// Adding the resolve fn to its own cache, since the parent will trigger
|
1431
|
+
// a new update() directly on this cmp
|
1432
|
+
resolve && me.resolveUpdateCache.push(resolve)
|
1401
1433
|
return true
|
1402
1434
|
} else {
|
1403
1435
|
return me.isParentVdomUpdating(parent.parentId)
|
@@ -1489,15 +1521,19 @@ class Base extends CoreBase {
|
|
1489
1521
|
/**
|
1490
1522
|
* Checks the needsVdomUpdate config inside the parent tree
|
1491
1523
|
* @param {String} parentId=this.parentId
|
1524
|
+
* @param {Function} [resolve] gets passed by updateVdom()
|
1492
1525
|
* @returns {Boolean}
|
1493
1526
|
*/
|
1494
|
-
needsParentUpdate(parentId=this.parentId) {
|
1527
|
+
needsParentUpdate(parentId=this.parentId, resolve) {
|
1495
1528
|
if (parentId !== 'document.body') {
|
1496
1529
|
let me = this,
|
1497
1530
|
parent = Neo.getComponent(parentId);
|
1498
1531
|
|
1499
1532
|
if (parent) {
|
1500
1533
|
if (parent.needsVdomUpdate) {
|
1534
|
+
parent.resolveUpdateCache.push(...me.resolveUpdateCache);
|
1535
|
+
resolve && parent.resolveUpdateCache.push(resolve);
|
1536
|
+
me.resolveUpdateCache = [];
|
1501
1537
|
return true
|
1502
1538
|
} else {
|
1503
1539
|
return me.needsParentUpdate(parent.parentId)
|
@@ -1596,35 +1632,9 @@ class Base extends CoreBase {
|
|
1596
1632
|
* @param {Neo.vdom.VNode} [vnode= this.vnode]
|
1597
1633
|
* @returns {Promise<any>}
|
1598
1634
|
*/
|
1599
|
-
|
1600
|
-
let me = this,
|
1601
|
-
_vdom = me.vdom;
|
1602
|
-
|
1603
|
-
// todo: updateVdom() should handle this
|
1604
|
-
// It is important to keep the vdom tree stable to ensure that containers do not lose the references to their
|
1605
|
-
// child vdom trees. The if case should not happen, but in case it does, keeping the reference and merging
|
1606
|
-
// the content over seems to be the best strategy
|
1607
|
-
if (_vdom !== vdom) {
|
1608
|
-
Logger.warn('vdom got replaced for: ' + me.id + '. Copying the content into the reference holder object');
|
1609
|
-
|
1610
|
-
Object.keys(_vdom).forEach(key => {
|
1611
|
-
delete _vdom[key];
|
1612
|
-
});
|
1613
|
-
|
1614
|
-
vdom = Object.assign(me._vdom, vdom)
|
1615
|
-
}
|
1616
|
-
|
1617
|
-
if (me.silentVdomUpdate) {
|
1618
|
-
return Promise.resolve()
|
1619
|
-
}
|
1620
|
-
|
1635
|
+
promiseUpdate(vdom=this.vdom, vnode=this.vnode) {
|
1621
1636
|
return new Promise((resolve, reject) => {
|
1622
|
-
|
1623
|
-
me.updateVdom(vdom, vnode, resolve, reject)
|
1624
|
-
} else {
|
1625
|
-
me.update();
|
1626
|
-
resolve()
|
1627
|
-
}
|
1637
|
+
this.updateVdom(vdom, vnode, resolve, reject)
|
1628
1638
|
})
|
1629
1639
|
}
|
1630
1640
|
|
@@ -1716,6 +1726,9 @@ class Base extends CoreBase {
|
|
1716
1726
|
|
1717
1727
|
delete me.vdom.removeDom;
|
1718
1728
|
|
1729
|
+
me._needsVdomUpdate = false;
|
1730
|
+
me.afterSetNeedsVdomUpdate?.(false, true)
|
1731
|
+
|
1719
1732
|
Neo.vdom.Helper.create({
|
1720
1733
|
appName : me.appName,
|
1721
1734
|
autoMount,
|
@@ -1739,11 +1752,14 @@ class Base extends CoreBase {
|
|
1739
1752
|
resolveVdomUpdate(resolve) {
|
1740
1753
|
let me = this;
|
1741
1754
|
|
1755
|
+
me.doResolveUpdateCache();
|
1756
|
+
|
1742
1757
|
resolve?.();
|
1743
1758
|
|
1744
1759
|
if (me.needsVdomUpdate) {
|
1745
1760
|
me.childUpdateCache = []; // if a new update is scheduled, we can clear the cache => these updates are included
|
1746
|
-
|
1761
|
+
|
1762
|
+
me.update()
|
1747
1763
|
} else {
|
1748
1764
|
[...me.childUpdateCache].forEach(id => {
|
1749
1765
|
Neo.getComponent(id)?.update();
|
@@ -1776,7 +1792,7 @@ class Base extends CoreBase {
|
|
1776
1792
|
return Promise.resolve()
|
1777
1793
|
}
|
1778
1794
|
|
1779
|
-
return me.
|
1795
|
+
return me.promiseUpdate()
|
1780
1796
|
}
|
1781
1797
|
}
|
1782
1798
|
|
@@ -1975,11 +1991,12 @@ class Base extends CoreBase {
|
|
1975
1991
|
updateStyle(value, oldValue, id=this.id) {
|
1976
1992
|
let me = this,
|
1977
1993
|
delta = Style.compareStyles(value, oldValue),
|
1978
|
-
|
1979
|
-
vnode = me.vnode && VNodeUtil.findChildVnode(me.vnode, id),
|
1980
|
-
opts, vnodeStyle;
|
1994
|
+
opts, vdom, vnode, vnodeStyle;
|
1981
1995
|
|
1982
1996
|
if (delta) {
|
1997
|
+
vdom = VDomUtil.findVdomChild(me.vdom, id);
|
1998
|
+
vnode = me.vnode && VNodeUtil.findChildVnode(me.vnode, id);
|
1999
|
+
|
1983
2000
|
if (!me.hasUnmountedVdomChanges) {
|
1984
2001
|
me.hasUnmountedVdomChanges = !me.mounted && me.hasBeenMounted
|
1985
2002
|
}
|
@@ -2018,55 +2035,65 @@ class Base extends CoreBase {
|
|
2018
2035
|
|
2019
2036
|
/**
|
2020
2037
|
* Gets called after the vdom config gets changed in case the component is already mounted (delta updates).
|
2021
|
-
* @param {Object} vdom
|
2022
|
-
* @param {Neo.vdom.VNode} vnode
|
2023
|
-
* @param {function} [resolve] used by
|
2024
|
-
* @param {function} [reject] used by
|
2038
|
+
* @param {Object} vdom=this.vdom
|
2039
|
+
* @param {Neo.vdom.VNode} vnode=this.vnode
|
2040
|
+
* @param {function} [resolve] used by promiseUpdate()
|
2041
|
+
* @param {function} [reject] used by promiseUpdate()
|
2025
2042
|
* @protected
|
2026
2043
|
*/
|
2027
|
-
updateVdom(vdom, vnode, resolve, reject) {
|
2028
|
-
let me
|
2029
|
-
|
2044
|
+
updateVdom(vdom=this.vdom, vnode=this.vnode, resolve, reject) {
|
2045
|
+
let me = this,
|
2046
|
+
app = Neo.apps[me.appName],
|
2047
|
+
mounted = me.mounted,
|
2048
|
+
listenerId;
|
2030
2049
|
|
2031
|
-
//
|
2032
|
-
//
|
2050
|
+
// It is important to keep the vdom tree stable to ensure that containers do not lose the references to their
|
2051
|
+
// child vdom trees. The if case should not happen, but in case it does, keeping the reference and merging
|
2052
|
+
// the content over seems to be the best strategy
|
2053
|
+
if (me._vdom !== vdom) {
|
2054
|
+
Logger.warn('vdom got replaced for: ' + me.id + '. Copying the content into the reference holder object');
|
2055
|
+
|
2056
|
+
Object.keys(me._vdom).forEach(key => {
|
2057
|
+
delete me._vdom[key]
|
2058
|
+
});
|
2033
2059
|
|
2034
|
-
|
2060
|
+
vdom = Object.assign(me._vdom, vdom)
|
2061
|
+
}
|
2062
|
+
|
2063
|
+
if (resolve && me.isVdomUpdating) {
|
2064
|
+
me.resolveUpdateCache.push(resolve)
|
2065
|
+
}
|
2066
|
+
|
2067
|
+
if (me.isVdomUpdating || me.silentVdomUpdate) {
|
2035
2068
|
me.needsVdomUpdate = true
|
2036
2069
|
} else {
|
2037
|
-
me.
|
2038
|
-
|
2070
|
+
if (!mounted && me.isConstructed && !me.hasRenderingListener && app?.rendering === true) {
|
2071
|
+
me.hasRenderingListener = true;
|
2039
2072
|
|
2040
|
-
|
2073
|
+
listenerId = app.on('mounted', () => {
|
2074
|
+
app.un('mounted', listenerId);
|
2041
2075
|
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
2048
|
-
|
2076
|
+
me.timeout(50).then(() => {
|
2077
|
+
me.vnode && me.updateVdom(me.vdom, me.vnode, resolve, reject)
|
2078
|
+
})
|
2079
|
+
})
|
2080
|
+
} else {
|
2081
|
+
if (resolve && (!mounted || !vnode)) {
|
2082
|
+
me.resolveUpdateCache.push(resolve)
|
2083
|
+
}
|
2049
2084
|
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
me
|
2057
|
-
|
2058
|
-
deltas = data.deltas;
|
2059
|
-
|
2060
|
-
if (!Neo.config.useVdomWorker && deltas.length > 0) {
|
2061
|
-
Neo.applyDeltas(me.appName, deltas).then(() => {
|
2062
|
-
me.resolveVdomUpdate(resolve)
|
2063
|
-
})
|
2064
|
-
} else {
|
2065
|
-
me.resolveVdomUpdate(resolve)
|
2066
|
-
}
|
2085
|
+
if (
|
2086
|
+
mounted
|
2087
|
+
&& vnode
|
2088
|
+
&& !me.needsParentUpdate(me.parentId, resolve)
|
2089
|
+
&& !me.isParentVdomUpdating(me.parentId, resolve)
|
2090
|
+
) {
|
2091
|
+
me.#executeVdomUpdate(vdom, vnode, resolve, reject)
|
2067
2092
|
}
|
2068
|
-
}
|
2093
|
+
}
|
2069
2094
|
}
|
2095
|
+
|
2096
|
+
me.hasUnmountedVdomChanges = !mounted && me.hasBeenMounted
|
2070
2097
|
}
|
2071
2098
|
}
|
2072
2099
|
|
package/src/component/Circle.mjs
CHANGED
@@ -255,7 +255,7 @@ class Circle extends Component {
|
|
255
255
|
me.createItems(oldValue, true);
|
256
256
|
me.updateItemPositions(true);
|
257
257
|
|
258
|
-
me.
|
258
|
+
me.promiseUpdate().then(() => {
|
259
259
|
if (!me.collapsed) {
|
260
260
|
me.updateItemOpacity(1, true, oldValue);
|
261
261
|
me.update();
|
@@ -720,7 +720,7 @@ class Circle extends Component {
|
|
720
720
|
|
721
721
|
me.circleCenterHasTransitionCls = false;
|
722
722
|
|
723
|
-
me.
|
723
|
+
me.promiseUpdate().then(() => {
|
724
724
|
me.updateItemAngle(true);
|
725
725
|
circleCenterEl.style.transform = transform;
|
726
726
|
me.update();
|
@@ -447,7 +447,7 @@ class DateSelector extends Component {
|
|
447
447
|
vdom.cn[2].cn[0].cn[slideDirection === 'right'? 'unshift' : 'push'](vdom.cn[1]);
|
448
448
|
vdom.cn.splice(1, 1);
|
449
449
|
|
450
|
-
me.
|
450
|
+
me.promiseUpdate().then(() => {
|
451
451
|
me.changeMonthTransitionCallback({data: data[0], slideDirection: slideDirection});
|
452
452
|
me.updateHeaderMonthTransitionCallback(headerMonthOpts);
|
453
453
|
me.update();
|
@@ -533,7 +533,7 @@ class DateSelector extends Component {
|
|
533
533
|
vdom.cn[2].cn[0].cn[scrollFromTop ? 'unshift' : 'push'](vdom.cn[1]);
|
534
534
|
vdom.cn.splice(1, 1);
|
535
535
|
|
536
|
-
me.
|
536
|
+
me.promiseUpdate(vdom).then(() => {
|
537
537
|
y = scrollFromTop ? -data.height : 0;
|
538
538
|
vdom.cn[1].cn[0].style.transform = `translateY(${y}px)`;
|
539
539
|
me.update();
|
@@ -844,7 +844,7 @@ class DateSelector extends Component {
|
|
844
844
|
|
845
845
|
me.isUpdating = true;
|
846
846
|
|
847
|
-
me.
|
847
|
+
me.promiseUpdate(me.vdom).then(() => {
|
848
848
|
me.isUpdating = false;
|
849
849
|
});
|
850
850
|
}
|
package/src/component/Helix.mjs
CHANGED
package/src/container/Base.mjs
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
2
|
-
import Xhr
|
1
|
+
import WebSocket from './WebSocket.mjs';
|
2
|
+
import Xhr from './Xhr.mjs';
|
3
3
|
|
4
|
-
export {
|
4
|
+
export {WebSocket, Xhr};
|
package/src/form/field/Date.mjs
CHANGED
package/src/form/field/Text.mjs
CHANGED
@@ -23,7 +23,7 @@ class Text extends Base {
|
|
23
23
|
* @protected
|
24
24
|
* @static
|
25
25
|
*/
|
26
|
-
static labelPositions
|
26
|
+
static labelPositions = ['bottom', 'inline', 'left', 'right', 'top']
|
27
27
|
|
28
28
|
static config = {
|
29
29
|
/**
|
@@ -220,14 +220,18 @@ class Text extends Base {
|
|
220
220
|
* @member {Object} _vdom
|
221
221
|
*/
|
222
222
|
_vdom:
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
223
|
+
{
|
224
|
+
cn: [
|
225
|
+
{tag: 'label', cls: [], style: {}},
|
226
|
+
{tag: 'label', cls: []},
|
227
|
+
{tag: 'input', cls: ['neo-textfield-input'], flag: 'neo-real-input', style: {}},
|
228
|
+
{
|
229
|
+
cls: ['neo-textfield-error-wrapper'], removeDom: true, cn: [
|
230
|
+
{cls: ['neo-textfield-error']}
|
231
|
+
]
|
232
|
+
}
|
233
|
+
]
|
234
|
+
}
|
231
235
|
}
|
232
236
|
|
233
237
|
/**
|
@@ -246,9 +250,9 @@ class Text extends Base {
|
|
246
250
|
let me = this;
|
247
251
|
|
248
252
|
me.addDomListeners([
|
249
|
-
{input
|
250
|
-
{mouseenter: me.onMouseEnter,
|
251
|
-
{mouseleave: me.onMouseLeave,
|
253
|
+
{input: me.onInputValueChange, scope: me},
|
254
|
+
{mouseenter: me.onMouseEnter, scope: me},
|
255
|
+
{mouseleave: me.onMouseLeave, scope: me}
|
252
256
|
]);
|
253
257
|
}
|
254
258
|
|
@@ -530,7 +534,7 @@ class Text extends Base {
|
|
530
534
|
delete me.getCenterBorderEl()?.width;
|
531
535
|
}
|
532
536
|
|
533
|
-
me.
|
537
|
+
me.promiseUpdate().then(() => {
|
534
538
|
me.updateCenterBorderElWidth(isEmpty)
|
535
539
|
})
|
536
540
|
} else {
|
@@ -637,7 +641,7 @@ class Text extends Base {
|
|
637
641
|
* @protected
|
638
642
|
*/
|
639
643
|
afterSetReadOnly(value, oldValue) {
|
640
|
-
let me
|
644
|
+
let me = this,
|
641
645
|
cls = me.cls;
|
642
646
|
|
643
647
|
NeoArray[value ? 'add' : 'remove'](cls, 'neo-readonly');
|
@@ -663,7 +667,7 @@ class Text extends Base {
|
|
663
667
|
|
664
668
|
me.validate(false);
|
665
669
|
me.changeInputElKey('required', value ? value : null);
|
666
|
-
me.labelText
|
670
|
+
me.labelText = me.labelText; // apply the optional text if needed
|
667
671
|
|
668
672
|
me.silentVdomUpdate = false;
|
669
673
|
|
@@ -753,10 +757,10 @@ class Text extends Base {
|
|
753
757
|
});
|
754
758
|
|
755
759
|
postTriggers.sort((a, b) => b.weight - a.weight); // DESC
|
756
|
-
preTriggers
|
760
|
+
preTriggers.sort((a, b) => a.weight - b.weight); // ASC
|
757
761
|
|
758
762
|
postTriggers = postTriggers.map(a => a.vdom);
|
759
|
-
preTriggers = preTriggers
|
763
|
+
preTriggers = preTriggers.map(a => a.vdom);
|
760
764
|
|
761
765
|
if (inputEl.tag === 'input') {
|
762
766
|
// wrap the input tag
|
@@ -774,13 +778,13 @@ class Text extends Base {
|
|
774
778
|
} else {
|
775
779
|
if (inputEl.tag !== 'input') {
|
776
780
|
// replacing the input wrapper div with the input tag
|
777
|
-
width
|
778
|
-
vdom.cn[2]
|
781
|
+
width = inputEl.width;
|
782
|
+
vdom.cn[2] = me.getInputEl();
|
779
783
|
vdom.cn[2].width = width;
|
780
784
|
}
|
781
785
|
}
|
782
786
|
|
783
|
-
me.
|
787
|
+
me.promiseUpdate().then(() => {
|
784
788
|
me.updateTriggerVnodes()
|
785
789
|
})
|
786
790
|
}
|
@@ -807,7 +811,7 @@ class Text extends Base {
|
|
807
811
|
cls = me.cls;
|
808
812
|
|
809
813
|
NeoArray[me.hasContent() ? 'add' : 'remove'](cls, 'neo-has-content');
|
810
|
-
NeoArray[isDirty
|
814
|
+
NeoArray[isDirty ? 'add' : 'remove'](cls, 'neo-is-dirty');
|
811
815
|
me.cls = cls;
|
812
816
|
|
813
817
|
me.silentVdomUpdate = false;
|
@@ -1242,7 +1246,7 @@ class Text extends Base {
|
|
1242
1246
|
vnode.vnode.attributes.value = value;
|
1243
1247
|
}
|
1244
1248
|
|
1245
|
-
|
1249
|
+
me.value = me.inputValueAdjustor(value)
|
1246
1250
|
}
|
1247
1251
|
|
1248
1252
|
/**
|
@@ -1278,7 +1282,7 @@ class Text extends Base {
|
|
1278
1282
|
* @param {Array} [triggerSource] pass a shallow copy of this.triggers
|
1279
1283
|
* @returns {Boolean} true in case a trigger was found & removed
|
1280
1284
|
*/
|
1281
|
-
removeTrigger(type, silent=false, triggerSource) {
|
1285
|
+
removeTrigger(type, silent = false, triggerSource) {
|
1282
1286
|
let me = this,
|
1283
1287
|
hasMatch = false,
|
1284
1288
|
triggers = triggerSource || me.triggers || [],
|
@@ -1308,7 +1312,7 @@ class Text extends Base {
|
|
1308
1312
|
* You can optionally pass a new value, which will adjust the originalConfig.value if needed.
|
1309
1313
|
* @param {String|null} [value=null]
|
1310
1314
|
*/
|
1311
|
-
reset(value=null) {
|
1315
|
+
reset(value = null) {
|
1312
1316
|
let me = this;
|
1313
1317
|
|
1314
1318
|
if (me.clearToOriginalValue) {
|
@@ -1331,7 +1335,7 @@ class Text extends Base {
|
|
1331
1335
|
* @param {Boolean} [silent=false] true to get the value, but not apply it to the DOM
|
1332
1336
|
* @protected
|
1333
1337
|
*/
|
1334
|
-
updateCenterBorderElWidth(silent=false) {
|
1338
|
+
updateCenterBorderElWidth(silent = false) {
|
1335
1339
|
let me = this;
|
1336
1340
|
|
1337
1341
|
me.mounted && me.getDomRect(me.getCenterBorderEl().id).then(data => {
|
@@ -1348,7 +1352,7 @@ class Text extends Base {
|
|
1348
1352
|
@param {String|null} value
|
1349
1353
|
@param {Boolean} silent=false
|
1350
1354
|
*/
|
1351
|
-
updateError(value, silent=false) {
|
1355
|
+
updateError(value, silent = false) {
|
1352
1356
|
let me = this,
|
1353
1357
|
cls = me.cls,
|
1354
1358
|
errorNode, errorWrapper;
|
@@ -1394,9 +1398,9 @@ class Text extends Base {
|
|
1394
1398
|
* todo: this could be handled by component.Base
|
1395
1399
|
*/
|
1396
1400
|
updateTriggerVnodes() {
|
1397
|
-
let me
|
1398
|
-
triggerRoot
|
1399
|
-
childNodes
|
1401
|
+
let me = this,
|
1402
|
+
triggerRoot = me.vnode?.childNodes[1],
|
1403
|
+
childNodes = triggerRoot?.childNodes || [],
|
1400
1404
|
trigger;
|
1401
1405
|
|
1402
1406
|
childNodes.forEach(vnode => {
|
@@ -1415,7 +1419,7 @@ class Text extends Base {
|
|
1415
1419
|
* @param {Boolean} silent=true
|
1416
1420
|
* @returns {Boolean} Returns true in case there are no client-side errors
|
1417
1421
|
*/
|
1418
|
-
validate(silent=true) {
|
1422
|
+
validate(silent = true) {
|
1419
1423
|
let me = this,
|
1420
1424
|
maxLength = me.maxLength,
|
1421
1425
|
minLength = me.minLength,
|
@@ -1433,30 +1437,28 @@ class Text extends Base {
|
|
1433
1437
|
me.clean = false;
|
1434
1438
|
}
|
1435
1439
|
|
1436
|
-
if (Neo.isFunction(me.validator)) {
|
1437
|
-
errorText = me.validator(me);
|
1438
|
-
|
1439
|
-
if (errorText !== true) {
|
1440
|
-
me._error = errorText;
|
1441
|
-
returnValue = false;
|
1442
|
-
}
|
1443
|
-
}
|
1444
|
-
|
1445
1440
|
if (isEmpty) {
|
1446
1441
|
if (required) {
|
1447
|
-
me._error
|
1442
|
+
me._error = me.errorTextRequired;
|
1448
1443
|
returnValue = false;
|
1449
1444
|
}
|
1450
1445
|
} else {
|
1451
1446
|
if (Neo.isNumber(maxLength) && valueLength > maxLength) {
|
1452
|
-
me._error
|
1447
|
+
me._error = me.errorTextMaxLength(errorParam);
|
1453
1448
|
returnValue = false;
|
1454
1449
|
} else if (Neo.isNumber(minLength) && valueLength < minLength) {
|
1455
|
-
me._error
|
1450
|
+
me._error = me.errorTextMinLength(errorParam);
|
1456
1451
|
returnValue = false;
|
1457
1452
|
} else if (inputPattern && !inputPattern.test(value)) {
|
1458
|
-
me._error
|
1453
|
+
me._error = me.errorTextInputPattern(errorParam);
|
1459
1454
|
returnValue = false;
|
1455
|
+
} else if (Neo.isFunction(me.validator)) {
|
1456
|
+
errorText = me.validator(me);
|
1457
|
+
|
1458
|
+
if (errorText !== true) {
|
1459
|
+
me._error = errorText;
|
1460
|
+
returnValue = false;
|
1461
|
+
}
|
1460
1462
|
}
|
1461
1463
|
}
|
1462
1464
|
|
@@ -13,6 +13,8 @@ class ZipCode extends Text {
|
|
13
13
|
* @static
|
14
14
|
*/
|
15
15
|
static countryCodes = {
|
16
|
+
AT: /^\d{4}$/,
|
17
|
+
CH: /^\d{4}$/,
|
16
18
|
DE: /^(?!01000|99999)(0[1-9]\d{3}|[1-9]\d{4})$/
|
17
19
|
}
|
18
20
|
|
@@ -40,12 +42,12 @@ class ZipCode extends Text {
|
|
40
42
|
* The data.Model field inside the related country field which provides the country code (e.g. 'DE')
|
41
43
|
* @member {String} countryKeyProperty='id'
|
42
44
|
*/
|
43
|
-
countryKeyProperty:
|
45
|
+
countryKeyProperty: "id",
|
44
46
|
/**
|
45
47
|
* data passes inputPattern, maxLength, minLength & valueLength properties
|
46
|
-
* @member {Function} errorTextInputPattern=data
|
48
|
+
* @member {Function} errorTextInputPattern=data=>'Not a valid zip code'
|
47
49
|
*/
|
48
|
-
errorTextInputPattern: data =>
|
50
|
+
errorTextInputPattern: (data) => 'Not a valid zip code'
|
49
51
|
}
|
50
52
|
|
51
53
|
/**
|
@@ -59,7 +61,7 @@ class ZipCode extends Text {
|
|
59
61
|
|
60
62
|
me.inputPattern = ZipCode.countryCodes[value] || null;
|
61
63
|
|
62
|
-
oldValue !== undefined && me.value && !me.clean && me.validate(false)
|
64
|
+
oldValue !== undefined && me.value && !me.clean && me.validate(false)
|
63
65
|
}
|
64
66
|
|
65
67
|
/**
|
@@ -99,14 +101,14 @@ class ZipCode extends Text {
|
|
99
101
|
return me.up().getReference(value)
|
100
102
|
}
|
101
103
|
|
102
|
-
return value
|
104
|
+
return value
|
103
105
|
}
|
104
106
|
|
105
107
|
/**
|
106
108
|
* @param {Object} data
|
107
109
|
*/
|
108
110
|
onCountryFieldChange(data) {
|
109
|
-
this.countryCode = data.record?.[this.countryKeyProperty] || null
|
111
|
+
this.countryCode = data.record?.[this.countryKeyProperty] || null
|
110
112
|
}
|
111
113
|
}
|
112
114
|
|
package/src/grid/View.mjs
CHANGED
@@ -150,7 +150,7 @@ class View extends Component {
|
|
150
150
|
container.dockLeftMargin = dockLeftMargin;
|
151
151
|
container.dockRightMargin = dockRightMargin;
|
152
152
|
|
153
|
-
me.
|
153
|
+
me.promiseUpdate().then(() => {
|
154
154
|
if (selectedRows?.length > 0) {
|
155
155
|
// this logic only works for selection.table.RowModel
|
156
156
|
Neo.main.DomAccess.scrollToTableRow({id: selectedRows[0]});
|
package/src/list/Base.mjs
CHANGED
@@ -215,12 +215,14 @@ class DeltaUpdates extends Base {
|
|
215
215
|
case 'style':
|
216
216
|
if (Neo.isObject(value)) {
|
217
217
|
Object.entries(value).forEach(([key, val]) => {
|
218
|
+
let important;
|
219
|
+
|
218
220
|
if (Neo.isString(val) && val.includes('!important')) {
|
219
221
|
val = val.replace('!important', '').trim();
|
220
|
-
|
221
|
-
} else {
|
222
|
-
node.style[Neo.decamel(key)] = val;
|
222
|
+
important = 'important';
|
223
223
|
}
|
224
|
+
|
225
|
+
node.style.setProperty(Neo.decamel(key), val, important);
|
224
226
|
});
|
225
227
|
}
|
226
228
|
break;
|
package/src/table/View.mjs
CHANGED
@@ -214,7 +214,7 @@ class View extends Component {
|
|
214
214
|
container.dockLeftMargin = dockLeftMargin;
|
215
215
|
container.dockRightMargin = dockRightMargin;
|
216
216
|
|
217
|
-
me.
|
217
|
+
me.promiseUpdate().then(() => {
|
218
218
|
if (selectedRows?.length > 0) {
|
219
219
|
// this logic only works for selection.table.RowModel
|
220
220
|
Neo.main.DomAccess.scrollToTableRow({id: selectedRows[0]});
|