neo.mjs 4.0.76 → 4.0.79

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.0.76",
3
+ "version": "4.0.79",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -50,12 +50,12 @@
50
50
  "envinfo": "^7.8.1",
51
51
  "fs-extra": "^10.1.0",
52
52
  "highlightjs-line-numbers.js": "^2.8.0",
53
- "inquirer": "^9.0.1",
53
+ "inquirer": "^9.0.2",
54
54
  "neo-jsdoc": "^1.0.1",
55
55
  "neo-jsdoc-x": "^1.0.4",
56
56
  "postcss": "^8.4.14",
57
- "sass": "^1.53.0",
58
- "webpack": "^5.73.0",
57
+ "sass": "^1.54.0",
58
+ "webpack": "^5.74.0",
59
59
  "webpack-cli": "^4.10.0",
60
60
  "webpack-dev-server": "4.9.3",
61
61
  "webpack-hook-plugin": "^1.0.7",
@@ -54,6 +54,7 @@
54
54
  }
55
55
 
56
56
  &.label-inline {
57
+ display : block;
57
58
  font-size: 14px;
58
59
  position : relative;
59
60
 
@@ -191,6 +192,12 @@
191
192
  }
192
193
  }
193
194
 
195
+ .neo-textfield-error {
196
+ color : v(textfield-border-color-invalid);
197
+ font-size : 11px;
198
+ margin-top: .3em;
199
+ }
200
+
194
201
  .neo-textfield-input {
195
202
  background-color: v(textfield-input-background-color);
196
203
  border : 1px solid v(textfield-border-color);
@@ -410,7 +410,7 @@ class Base extends CoreBase {
410
410
  app.un('mounted', listenerId);
411
411
 
412
412
  setTimeout(() => {
413
- me.updateVdom(me.vdom, me.vnode);
413
+ me.vnode && me.updateVdom(me.vdom, me.vnode);
414
414
  }, 50);
415
415
  });
416
416
  } else if (me.mounted) {
@@ -1567,24 +1567,22 @@ class Base extends CoreBase {
1567
1567
 
1568
1568
  // keep the vnode parent tree in sync
1569
1569
  ComponentManager.getParents(me).forEach((component, index) => {
1570
- if (component._vnode) {
1571
- if (!me.vnode) {
1572
- if (index === 0 && !VNodeUtil.removeChildVnode(component.vnode, me.id)) {
1573
- // This can fail, in case the vnode is already removed (not an issue, better safe than sorry)
1574
- // console.warn('syncVnodeTree: Could not remove the parent vnode for', me.id, component);
1575
- }
1570
+ if (!me.vnode) {
1571
+ if (index === 0 && !VNodeUtil.removeChildVnode(component.vnode, me.id)) {
1572
+ // This can fail, in case the vnode is already removed (not an issue, better safe than sorry)
1573
+ // console.warn('syncVnodeTree: Could not remove the parent vnode for', me.id, component);
1576
1574
  }
1575
+ }
1577
1576
 
1578
- // check for dynamically rendered components which get inserted into the component tree
1579
- else if (index === 0 && me.vnode.outerHTML) {
1580
- // console.log('dyn item', me.vnode, me.parentIndex);
1581
- component.vnode.childNodes.splice(me.parentIndex || 0, 0, me.vnode);
1582
- }
1577
+ // check for dynamically rendered components which get inserted into the component tree
1578
+ else if (index === 0 && me.vnode.outerHTML) {
1579
+ // console.log('dyn item', me.vnode, me.parentIndex);
1580
+ component.vnode.childNodes.splice(me.parentIndex || 0, 0, me.vnode);
1581
+ }
1583
1582
 
1584
- else if (!VNodeUtil.replaceChildVnode(component.vnode, me.vnode.id, me.vnode)) {
1585
- // todo: can happen for dynamically inserted container items
1586
- // console.warn('syncVnodeTree: Could not replace the parent vnode for', me.vnode.id, component);
1587
- }
1583
+ else if (!VNodeUtil.replaceChildVnode(component.vnode, me.vnode.id, me.vnode)) {
1584
+ // todo: can happen for dynamically inserted container items
1585
+ // console.warn('syncVnodeTree: Could not replace the parent vnode for', me.vnode.id, component);
1588
1586
  }
1589
1587
  });
1590
1588
 
@@ -261,7 +261,7 @@ class Select extends Picker {
261
261
 
262
262
  if (record) {
263
263
  me.record = record;
264
- return record[me.displayField];
264
+ return record[displayField];
265
265
  }
266
266
  }
267
267
 
@@ -77,10 +77,18 @@ class Text extends Base {
77
77
  * @member {String[]} cls=['neo-textfield']
78
78
  */
79
79
  cls: ['neo-textfield'],
80
+ /**
81
+ * @member {String|null} error_=null
82
+ */
83
+ error_: null,
80
84
  /**
81
85
  * @member {Boolean} hideLabel_=false
82
86
  */
83
87
  hideLabel_: false,
88
+ /**
89
+ * @member {RegExp|null} inputPattern=null
90
+ */
91
+ inputPattern_: null,
84
92
  /**
85
93
  * @member {String} inputType_='text'
86
94
  */
@@ -132,7 +140,8 @@ class Text extends Base {
132
140
  _vdom:
133
141
  {cn: [
134
142
  {tag: 'label', cls: ['neo-textfield-label'], style: {}},
135
- {tag: 'input', cls: ['neo-textfield-input'], flag: 'neo-real-input', style: {}}
143
+ {tag: 'input', cls: ['neo-textfield-input'], flag: 'neo-real-input', style: {}},
144
+ {cls: ['neo-textfield-error'], removeDom: true}
136
145
  ]}
137
146
  }}
138
147
 
@@ -220,6 +229,16 @@ class Text extends Base {
220
229
  });
221
230
  }
222
231
 
232
+ /**
233
+ * Triggered after the error config got changed
234
+ * @param {String|null} value
235
+ * @param {String|null} oldValue
236
+ * @protected
237
+ */
238
+ afterSetError(value, oldValue) {
239
+ this.updateValidationIndicators(false);
240
+ }
241
+
223
242
  /**
224
243
  * Triggered after the hideLabel config got changed
225
244
  * @param {Boolean} value
@@ -256,6 +275,16 @@ class Text extends Base {
256
275
  super.afterSetId(value, oldValue);
257
276
  }
258
277
 
278
+ /**
279
+ * Triggered after the inputPattern config got changed
280
+ * @param {RegExp|null} value
281
+ * @param {RegExp|null} oldValue
282
+ * @protected
283
+ */
284
+ afterSetInputPattern(value, oldValue) {
285
+
286
+ }
287
+
259
288
  /**
260
289
  * Triggered after the inputType config got changed
261
290
  * @param {String} value
@@ -536,7 +565,7 @@ class Text extends Base {
536
565
 
537
566
  me.getInputEl().value = value;
538
567
 
539
- if (!!value !== !!oldValue) { // change from empty to non empty
568
+ if (!!value !== !!oldValue) { // change from empty to non-empty
540
569
  NeoArray[value && value.toString().length > 0 ? 'add' : 'remove'](me._cls, 'neo-has-content');
541
570
  }
542
571
 
@@ -817,18 +846,23 @@ class Text extends Base {
817
846
  */
818
847
  isValid() {
819
848
  let me = this,
849
+ maxLength = me.maxLength,
850
+ minLength = me.minLength,
820
851
  value = me.value,
821
852
  valueLength = value?.toString().length;
822
853
 
823
854
  if (me.required && (!value || valueLength < 1)) {
855
+ me._error = 'Required';
824
856
  return false;
825
857
  }
826
858
 
827
- if (Neo.isNumber(me.maxLength) && valueLength > me.maxLength) {
859
+ if (Neo.isNumber(maxLength) && valueLength > maxLength) {
860
+ me._error = `Max length violation: ${valueLength} / ${maxLength}`;
828
861
  return false;
829
862
  }
830
863
 
831
- if (Neo.isNumber(me.minLength) && valueLength < me.minLength) {
864
+ if (Neo.isNumber(minLength) && valueLength < minLength) {
865
+ me._error = `Min length violation: ${valueLength} / ${minLength}`;
832
866
  return false;
833
867
  }
834
868
 
@@ -911,7 +945,9 @@ class Text extends Base {
911
945
  vnode.vnode.attributes.value = value;
912
946
  }
913
947
 
914
- if (value !== oldValue) {
948
+ if (me.inputPattern && !me.inputPattern.test(value) ) {
949
+ me.afterSetValue(oldValue, value);
950
+ } else if (value !== oldValue) {
915
951
  me.value = value;
916
952
  }
917
953
  }
@@ -1025,10 +1061,18 @@ class Text extends Base {
1025
1061
  */
1026
1062
  updateValidationIndicators(silent=true) {
1027
1063
  let me = this,
1028
- vdom = me.vdom;
1064
+ vdom = me.vdom,
1065
+ errorNode, isValid;
1029
1066
 
1030
1067
  if (!(me.validBeforeMount && !me.mounted)) {
1031
- NeoArray[!me.isValid() ? 'add' : 'remove'](me._cls, 'neo-invalid');
1068
+ isValid = me.isValid();
1069
+
1070
+ NeoArray[!isValid ? 'add' : 'remove'](me._cls, 'neo-invalid');
1071
+
1072
+ errorNode = VDomUtil.findVdomChild(this.vdom, {cls: 'neo-textfield-error'}).vdom;
1073
+
1074
+ errorNode.html = me.error;
1075
+ errorNode.removeDom = isValid;
1032
1076
 
1033
1077
  if (!silent) {
1034
1078
  me.vdom = vdom;
@@ -13,11 +13,6 @@ class Focus extends CoreBase {
13
13
  * @protected
14
14
  */
15
15
  className: 'Neo.manager.Focus',
16
- /**
17
- * @member {Boolean} singleton=true
18
- * @protected
19
- */
20
- singleton: true,
21
16
  /**
22
17
  * An array containing opts objects.
23
18
  * opts.componentPath
@@ -47,7 +42,12 @@ class Focus extends CoreBase {
47
42
  * The maximum amount of items stored inside the history array
48
43
  * @member {Number} maxHistoryLength=20
49
44
  */
50
- maxHistoryLength: 20
45
+ maxHistoryLength: 20,
46
+ /**
47
+ * @member {Boolean} singleton=true
48
+ * @protected
49
+ */
50
+ singleton: true
51
51
  }}
52
52
 
53
53
  /**
@@ -167,9 +167,6 @@ class Helper extends Base {
167
167
  // use case: calendar week view => move an event into a column on the right side
168
168
 
169
169
  if (movedNode) {
170
-
171
- // todo: check if there is a real index change
172
-
173
170
  deltas.push({
174
171
  action: 'moveNode',
175
172
  id : oldVnode.id,
@@ -786,8 +783,8 @@ class Helper extends Base {
786
783
  * @returns {Object|Promise<Object>}
787
784
  */
788
785
  update(opts) {
789
- let me = this,
790
- node = me.parseHelper(opts.vdom),
786
+ let me = this,
787
+ node = me.parseHelper(opts.vdom),
791
788
 
792
789
  deltas = me.createDeltas({
793
790
  newVnode: node,