neo.mjs 4.0.78 → 4.0.81

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.
@@ -42,6 +42,13 @@ class MainContainer extends ConfigurationViewport {
42
42
  labelText: 'disabled',
43
43
  listeners: {change: me.onConfigChange.bind(me, 'disabled')},
44
44
  style : {marginTop: '10px'}
45
+ }, {
46
+ module : TextField,
47
+ clearable: true,
48
+ labelText: 'error',
49
+ listeners: {change: me.onConfigChange.bind(me, 'error')},
50
+ reference: 'error-field',
51
+ value : me.exampleComponent.error
45
52
  }, {
46
53
  module : CheckBox,
47
54
  checked : me.exampleComponent.hideLabel,
@@ -157,7 +164,14 @@ class MainContainer extends ConfigurationViewport {
157
164
  labelWidth : 70,
158
165
  minLength : 3,
159
166
  value : 'Hello World',
160
- width : 200
167
+ width : 200,
168
+
169
+ listeners: {
170
+ change(value) {
171
+ this.down({reference: 'error-field'}).clear();
172
+ },
173
+ scope: this
174
+ }
161
175
  });
162
176
  }
163
177
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.0.78",
3
+ "version": "4.0.81",
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,7 +54,9 @@
54
54
  }
55
55
 
56
56
  &.label-inline {
57
+ display : block;
57
58
  font-size: 14px;
59
+ height : inherit;
58
60
  position : relative;
59
61
 
60
62
  &.neo-focus {
@@ -107,7 +109,7 @@
107
109
 
108
110
  .neo-label-wrapper {
109
111
  display : flex;
110
- height : 100%;
112
+ height : 27px;
111
113
  position: absolute;
112
114
  width : 100%;
113
115
 
@@ -191,6 +193,12 @@
191
193
  }
192
194
  }
193
195
 
196
+ .neo-textfield-error {
197
+ color : v(textfield-border-color-invalid);
198
+ font-size : 11px;
199
+ margin-top: .3em;
200
+ }
201
+
194
202
  .neo-textfield-input {
195
203
  background-color: v(textfield-input-background-color);
196
204
  border : 1px solid v(textfield-border-color);
@@ -68,6 +68,15 @@ class Base extends Component {
68
68
  reset(value) {
69
69
  this.value = value;
70
70
  }
71
+
72
+ /**
73
+ * Checks for client-side field errors
74
+ * @param {Boolean} silent=true
75
+ * @returns {Boolean} Returns true in case there are no client-side errors
76
+ */
77
+ validate(silent=true) {
78
+ return true;
79
+ }
71
80
  }
72
81
 
73
82
  /**
@@ -99,7 +99,7 @@ class Number extends Text {
99
99
  * @protected
100
100
  */
101
101
  afterSetMaxValue(value, oldValue) {
102
- this.updateValidationIndicators();
102
+ this.validate(); // silent
103
103
  this.changeInputElKey('max', value);
104
104
  }
105
105
 
@@ -110,7 +110,7 @@ class Number extends Text {
110
110
  * @protected
111
111
  */
112
112
  afterSetMinValue(value, oldValue) {
113
- this.updateValidationIndicators();
113
+ this.validate(); // silent
114
114
  this.changeInputElKey('min', value);
115
115
  }
116
116
 
@@ -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,6 +77,10 @@ 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
  */
@@ -136,7 +140,8 @@ class Text extends Base {
136
140
  _vdom:
137
141
  {cn: [
138
142
  {tag: 'label', cls: ['neo-textfield-label'], style: {}},
139
- {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}
140
145
  ]}
141
146
  }}
142
147
 
@@ -224,6 +229,16 @@ class Text extends Base {
224
229
  });
225
230
  }
226
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.updateError(value);
240
+ }
241
+
227
242
  /**
228
243
  * Triggered after the hideLabel config got changed
229
244
  * @param {Boolean} value
@@ -262,12 +277,12 @@ class Text extends Base {
262
277
 
263
278
  /**
264
279
  * Triggered after the inputPattern config got changed
265
- * @param {RegExp|null} value
280
+ * @param {RegExp|null} value
266
281
  * @param {RegExp|null} oldValue
267
282
  * @protected
268
283
  */
269
284
  afterSetInputPattern(value, oldValue) {
270
-
285
+
271
286
  }
272
287
 
273
288
  /**
@@ -395,7 +410,7 @@ class Text extends Base {
395
410
  * @protected
396
411
  */
397
412
  afterSetMaxLength(value, oldValue) {
398
- this.updateValidationIndicators();
413
+ this.validate(); // silent
399
414
  this.changeInputElKey('maxlength', value);
400
415
  }
401
416
 
@@ -406,7 +421,7 @@ class Text extends Base {
406
421
  * @protected
407
422
  */
408
423
  afterSetMinLength(value, oldValue) {
409
- this.updateValidationIndicators();
424
+ this.validate(); // silent
410
425
  this.changeInputElKey('minlength', value);
411
426
  }
412
427
 
@@ -459,7 +474,7 @@ class Text extends Base {
459
474
  * @protected
460
475
  */
461
476
  afterSetRequired(value, oldValue) {
462
- this.updateValidationIndicators();
477
+ this.validate(); // silent
463
478
  this.changeInputElKey('required', value ? value : null);
464
479
  }
465
480
 
@@ -550,12 +565,12 @@ class Text extends Base {
550
565
 
551
566
  me.getInputEl().value = value;
552
567
 
553
- if (!!value !== !!oldValue) { // change from empty to non empty
568
+ if (!!value !== !!oldValue) { // change from empty to non-empty
554
569
  NeoArray[value && value.toString().length > 0 ? 'add' : 'remove'](me._cls, 'neo-has-content');
555
570
  }
556
571
 
557
572
  NeoArray[me.originalConfig.value !== value ? 'add' : 'remove'](me._cls, 'neo-is-dirty');
558
- me.updateValidationIndicators();
573
+ me.validate(); // silent
559
574
 
560
575
  me.vdom = vdom;
561
576
 
@@ -830,23 +845,7 @@ class Text extends Base {
830
845
  * @returns {Boolean}
831
846
  */
832
847
  isValid() {
833
- let me = this,
834
- value = me.value,
835
- valueLength = value?.toString().length;
836
-
837
- if (me.required && (!value || valueLength < 1)) {
838
- return false;
839
- }
840
-
841
- if (Neo.isNumber(me.maxLength) && valueLength > me.maxLength) {
842
- return false;
843
- }
844
-
845
- if (Neo.isNumber(me.minLength) && valueLength < me.minLength) {
846
- return false;
847
- }
848
-
849
- return super.isValid();
848
+ return this.error?.length > 0 ? false : super.isValid();
850
849
  }
851
850
 
852
851
  /**
@@ -899,7 +898,7 @@ class Text extends Base {
899
898
  centerBorderEl = me.getCenterBorderEl(), // labelPosition: 'inline'
900
899
  vdom = me.vdom;
901
900
 
902
- me.updateValidationIndicators();
901
+ me.validate(); // silent
903
902
 
904
903
  NeoArray.remove(me._cls, 'neo-focus');
905
904
 
@@ -925,7 +924,7 @@ class Text extends Base {
925
924
  vnode.vnode.attributes.value = value;
926
925
  }
927
926
 
928
- if (me.inputPattern && !me.inputPattern.test(value) ) {
927
+ if (me.inputPattern && !me.inputPattern.test(value) ) {
929
928
  me.afterSetValue(oldValue, value);
930
929
  } else if (value !== oldValue) {
931
930
  me.value = value;
@@ -997,6 +996,36 @@ class Text extends Base {
997
996
  });
998
997
  }
999
998
 
999
+ /**
1000
+ @param {String|null} value
1001
+ @param {Boolean} silent=false
1002
+ */
1003
+ updateError(value, silent=false) {
1004
+ let me = this,
1005
+ vdom = me.vdom,
1006
+ errorNode, isValid;
1007
+
1008
+ if (!(me.validBeforeMount && !me.mounted)) {
1009
+ isValid = !value || value === '';
1010
+
1011
+ NeoArray[!isValid ? 'add' : 'remove'](me._cls, 'neo-invalid');
1012
+
1013
+ errorNode = VDomUtil.findVdomChild(this.vdom, {cls: 'neo-textfield-error'}).vdom;
1014
+
1015
+ if (!isValid) {
1016
+ errorNode.html = me.error;
1017
+ } else {
1018
+ delete errorNode.html;
1019
+ }
1020
+
1021
+ errorNode.removeDom = isValid;
1022
+
1023
+ if (!silent) {
1024
+ me.vdom = vdom;
1025
+ }
1026
+ }
1027
+ }
1028
+
1000
1029
  /**
1001
1030
  * Calculates the new inputWidth based on the labelWidth & total width
1002
1031
  * @protected
@@ -1037,19 +1066,43 @@ class Text extends Base {
1037
1066
  }
1038
1067
 
1039
1068
  /**
1069
+ * Checks for client-side field errors
1040
1070
  * @param {Boolean} silent=true
1071
+ * @returns {Boolean} Returns true in case there are no client-side errors
1041
1072
  */
1042
- updateValidationIndicators(silent=true) {
1043
- let me = this,
1044
- vdom = me.vdom;
1045
-
1046
- if (!(me.validBeforeMount && !me.mounted)) {
1047
- NeoArray[!me.isValid() ? 'add' : 'remove'](me._cls, 'neo-invalid');
1048
-
1049
- if (!silent) {
1050
- me.vdom = vdom;
1073
+ validate(silent=true) {
1074
+ let me = this,
1075
+ errorField = silent ? '_error' : 'error',
1076
+ maxLength = me.maxLength,
1077
+ minLength = me.minLength,
1078
+ required = me.required,
1079
+ returnValue = true,
1080
+ value = me.value,
1081
+ valueLength = value?.toString().length,
1082
+ isEmpty = !value || valueLength < 1;
1083
+
1084
+ if (required && isEmpty) {
1085
+ me[errorField] = 'Required';
1086
+ returnValue = false;
1087
+ } else if (Neo.isNumber(maxLength) && valueLength > maxLength) {
1088
+ if (required || !isEmpty) {
1089
+ me[errorField] = `Max length violation: ${valueLength} / ${maxLength}`;
1090
+ returnValue = false;
1091
+ }
1092
+ } else if (Neo.isNumber(minLength) && valueLength < minLength) {
1093
+ if (required || !isEmpty) {
1094
+ me[errorField] = `Min length violation: ${valueLength} / ${minLength}`;
1095
+ returnValue = false;
1051
1096
  }
1052
1097
  }
1098
+
1099
+ if (returnValue) {
1100
+ me[errorField] = null;
1101
+ }
1102
+
1103
+ silent && me.updateError(me[errorField], true);
1104
+
1105
+ return !returnValue ? false : super.validate(silent);
1053
1106
  }
1054
1107
  }
1055
1108