neo.mjs 5.13.5 → 5.13.7

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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.13.5'
23
+ * @member {String} version='5.13.7'
24
24
  */
25
- version: '5.13.5'
25
+ version: '5.13.7'
26
26
  }
27
27
 
28
28
  /**
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.13.5'
23
+ * @member {String} version='5.13.7'
24
24
  */
25
- version: '5.13.5'
25
+ version: '5.13.7'
26
26
  }
27
27
 
28
28
  /**
@@ -131,7 +131,6 @@ class MainContainer extends ConfigurationViewport {
131
131
  createExampleComponent() {
132
132
  return Neo.create({
133
133
  module : SelectField,
134
- displayField : 'name',
135
134
  labelPosition: 'inline',
136
135
  labelText : 'US States',
137
136
  labelWidth : 80,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.13.5",
3
+ "version": "5.13.7",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -111,6 +111,15 @@ const DefaultConfig = {
111
111
  * @type Boolean
112
112
  */
113
113
  logDeltaUpdates: false,
114
+ /**
115
+ * true will log console warnings, in case a component tries to update() while a parent update is running.
116
+ * A parent update results in a short delay, so you might want to resolve these collisions.
117
+ * @default false
118
+ * @memberOf! module:Neo
119
+ * @name config.logVdomUpdateCollisions
120
+ * @type Boolean
121
+ */
122
+ logVdomUpdateCollisions: false,
114
123
  /**
115
124
  * Add addons for the main thread
116
125
  * ./src/main/addon/ contains all framework related options.
@@ -236,12 +245,12 @@ const DefaultConfig = {
236
245
  useVdomWorker: true,
237
246
  /**
238
247
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '5.13.5'
248
+ * @default '5.13.7'
240
249
  * @memberOf! module:Neo
241
250
  * @name config.version
242
251
  * @type String
243
252
  */
244
- version: '5.13.5'
253
+ version: '5.13.7'
245
254
  };
246
255
 
247
256
  Object.assign(DefaultConfig, {
@@ -308,6 +308,11 @@ class Base extends CoreBase {
308
308
  _vdom: {}
309
309
  }
310
310
 
311
+ /**
312
+ * @member {String[]} childUpdateCache=[]
313
+ */
314
+ childUpdateCache = []
315
+
311
316
  /**
312
317
  * Apply component based listeners
313
318
  * @member {Object} listeners={}
@@ -735,8 +740,8 @@ class Base extends CoreBase {
735
740
  me.vnode && me.updateVdom(me.vdom, me.vnode);
736
741
  }, 50);
737
742
  });
738
- } else if (me.mounted) {
739
- me.vnode && me.updateVdom(vdom, me.vnode);
743
+ } else if (me.mounted && me.vnode && !me.isParentVdomUpdating()) {
744
+ me.updateVdom(vdom, me.vnode);
740
745
  }
741
746
 
742
747
  me.hasUnmountedVdomChanges = !me.mounted && me.hasBeenMounted;
@@ -1375,6 +1380,33 @@ class Base extends CoreBase {
1375
1380
  me.getModel() ?.parseConfig(me);
1376
1381
  }
1377
1382
 
1383
+ /**
1384
+ * Checks for vdom updates inside the parent chain and if found, registers the component for a vdom update once done
1385
+ * @param {String} parentId=this.parentId
1386
+ * @returns {Boolean}
1387
+ */
1388
+ isParentVdomUpdating(parentId=this.parentId) {
1389
+ if (parentId !== 'document.body') {
1390
+ let me = this,
1391
+ parent = Neo.getComponent(parentId);
1392
+
1393
+ if (parent) {
1394
+ if (parent.isVdomUpdating) {
1395
+ if (Neo.config.logVdomUpdateCollisions) {
1396
+ console.warn('vdom parent update conflict with:', parent, 'for:', me)
1397
+ }
1398
+
1399
+ NeoArray.add(parent.childUpdateCache, me.id);
1400
+ return true
1401
+ } else {
1402
+ return me.isParentVdomUpdating(parent.parentId)
1403
+ }
1404
+ }
1405
+ }
1406
+
1407
+ return false
1408
+ }
1409
+
1378
1410
  /**
1379
1411
  * Override this method to change the order configs are applied to this instance.
1380
1412
  * @param {Object} config
@@ -1676,6 +1708,28 @@ class Base extends CoreBase {
1676
1708
  }
1677
1709
  }
1678
1710
 
1711
+ /**
1712
+ * Internal helper fn to resolve the Promise for updateVdom()
1713
+ * @param {Function|undefined} resolve
1714
+ * @protected
1715
+ */
1716
+ resolveVdomUpdate(resolve) {
1717
+ let me = this;
1718
+
1719
+ resolve?.();
1720
+
1721
+ if (me.needsVdomUpdate) {
1722
+ me.childUpdateCache = []; // if a new update is scheduled, we can clear the cache => these updates are included
1723
+ me.needsVdomUpdate = false;
1724
+ me.vdom = me.vdom // trigger the next update cycle
1725
+ } else {
1726
+ [...me.childUpdateCache].forEach(id => {
1727
+ Neo.getComponent(id)?.update();
1728
+ NeoArray.remove(me.childUpdateCache, id)
1729
+ })
1730
+ }
1731
+ }
1732
+
1679
1733
  /**
1680
1734
  * Change multiple configs at once, ensuring that all afterSet methods get all new assigned values
1681
1735
  * @param {Object} values={}
@@ -1968,7 +2022,7 @@ class Base extends CoreBase {
1968
2022
  console.log('Error attempting to update component dom', err, me);
1969
2023
  me.isVdomUpdating = false;
1970
2024
 
1971
- reject?.();
2025
+ reject?.()
1972
2026
  }).then(data => {
1973
2027
  // console.log('Component vnode updated', data);
1974
2028
  me.vnode = data.vnode;
@@ -1978,20 +2032,10 @@ class Base extends CoreBase {
1978
2032
 
1979
2033
  if (!Neo.config.useVdomWorker && deltas.length > 0) {
1980
2034
  Neo.applyDeltas(me.appName, deltas).then(() => {
1981
- resolve?.();
1982
-
1983
- if (me.needsVdomUpdate) {
1984
- me.needsVdomUpdate = false;
1985
- me.vdom = me.vdom;
1986
- }
2035
+ me.resolveVdomUpdate(resolve)
1987
2036
  });
1988
2037
  } else {
1989
- resolve?.();
1990
-
1991
- if (me.needsVdomUpdate) {
1992
- me.needsVdomUpdate = false;
1993
- me.vdom = me.vdom;
1994
- }
2038
+ me.resolveVdomUpdate(resolve)
1995
2039
  }
1996
2040
  })
1997
2041
  }
@@ -31,22 +31,35 @@ class Container extends BaseContainer {
31
31
  }
32
32
 
33
33
  /**
34
- * Helper function used by setValues() which wraps the leaves of a tree structure into a new property
34
+ * Helper function used by setValues() which wraps the leaves of a tree structure into a new property.
35
+ * The logic assumes that field config values must not be objects (separation between the key & value realm).
35
36
  * @param {Object} values
36
37
  * @param {String} configName
37
38
  */
38
39
  static adjustTreeLeaves(values={}, configName) {
39
- let type;
40
+ let assign,type;
40
41
 
41
42
  Object.entries(values).forEach(([key, value]) => {
42
- type = Neo.typeOf(value);
43
+ assign = true;
44
+ type = Neo.typeOf(value);
43
45
 
44
46
  if (type === 'Array') {
45
- value.forEach(item => this.adjustTreeLeaves(item, configName))
47
+ value.forEach(item => {
48
+ if (Neo.typeOf(item) === 'Object') {
49
+ this.adjustTreeLeaves(item, configName)
50
+ }
51
+ })
46
52
  } else if (type === 'Object') {
53
+ assign = false;
47
54
  this.adjustTreeLeaves(value, configName)
48
- } else {
49
- values[key] = {[configName]: value}
55
+ }
56
+
57
+ if (assign) {
58
+ if (key === configName) {
59
+ values[key] = value
60
+ } else {
61
+ values[key] = {[configName]: value}
62
+ }
50
63
  }
51
64
  })
52
65
  }
@@ -59,13 +72,13 @@ class Container extends BaseContainer {
59
72
  findNotLoadedModules(parent=this, modules=[]) {
60
73
  parent.items.forEach(item => {
61
74
  if (Neo.typeOf(item.module) === 'Function' && !item.isLoading) {
62
- modules.push({item, parent});
75
+ modules.push({item, parent})
63
76
  } else {
64
- item.items && this.findNotLoadedModules(item, modules);
77
+ item.items && this.findNotLoadedModules(item, modules)
65
78
  }
66
79
  });
67
80
 
68
- return modules;
81
+ return modules
69
82
  }
70
83
 
71
84
  /**
@@ -82,12 +95,12 @@ class Container extends BaseContainer {
82
95
  for (field of fields) {
83
96
  if (field instanceof BaseField) {
84
97
  if (field.name === name || field.id === name) {
85
- return field;
98
+ return field
86
99
  }
87
100
  }
88
101
  }
89
102
 
90
- return null;
103
+ return null
91
104
  }
92
105
 
93
106
  /**
@@ -99,7 +112,7 @@ class Container extends BaseContainer {
99
112
 
100
113
  path.push(field.name || field.id);
101
114
 
102
- return path.join('.');
115
+ return path.join('.')
103
116
  }
104
117
 
105
118
  /**
@@ -111,10 +124,10 @@ class Container extends BaseContainer {
111
124
  await this.loadModules();
112
125
 
113
126
  ComponentManager.getChildComponents(this).forEach(item => {
114
- item instanceof BaseField && fields.push(item);
127
+ item instanceof BaseField && fields.push(item)
115
128
  });
116
129
 
117
- return fields;
130
+ return fields
118
131
  }
119
132
 
120
133
  /**
@@ -140,7 +153,7 @@ class Container extends BaseContainer {
140
153
  ns = Neo.nsWithArrays(nsArray, true, values);
141
154
  } else {
142
155
  key = item.id;
143
- ns = values;
156
+ ns = values
144
157
  }
145
158
 
146
159
  /*
@@ -161,7 +174,7 @@ class Container extends BaseContainer {
161
174
  }
162
175
  });
163
176
 
164
- return values;
177
+ return values
165
178
  }
166
179
 
167
180
  /**
@@ -175,11 +188,11 @@ class Container extends BaseContainer {
175
188
 
176
189
  for (; i < len; i++) {
177
190
  if (!fields[i].isValid()) {
178
- return false;
191
+ return false
179
192
  }
180
193
  }
181
194
 
182
- return true;
195
+ return true
183
196
  }
184
197
 
185
198
  /**
@@ -197,7 +210,7 @@ class Container extends BaseContainer {
197
210
 
198
211
  modules = await Promise.all(promises);
199
212
 
200
- return modules;
213
+ return modules
201
214
  }
202
215
 
203
216
  /**
@@ -214,7 +227,7 @@ class Container extends BaseContainer {
214
227
  path = me.getFieldPath(item);
215
228
  value = Neo.nsWithArrays(path, false, values);
216
229
 
217
- item.reset(path ? value : null);
230
+ item.reset(path ? value : null)
218
231
  })
219
232
  }
220
233
 
@@ -234,7 +247,7 @@ class Container extends BaseContainer {
234
247
 
235
248
  if (fieldConfigs) {
236
249
  if (suspendEvents) {
237
- item.suspendEvents = true;
250
+ item.suspendEvents = true
238
251
  }
239
252
 
240
253
  isCheckBox = Neo.form.field?.CheckBox && item instanceof Neo.form.field.CheckBox;
@@ -259,7 +272,7 @@ class Container extends BaseContainer {
259
272
  item.set(fieldConfigs)
260
273
 
261
274
  if (suspendEvents) {
262
- delete item.suspendEvents;
275
+ delete item.suspendEvents
263
276
  }
264
277
  }
265
278
  })
@@ -290,11 +303,11 @@ class Container extends BaseContainer {
290
303
  validField = item.validate?.(false);
291
304
 
292
305
  if (!validField) {
293
- isValid = false;
306
+ isValid = false
294
307
  }
295
308
  });
296
309
 
297
- return isValid;
310
+ return isValid
298
311
  }
299
312
  }
300
313