neo.mjs 5.4.9 → 5.4.11

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.4.9'
23
+ * @member {String} version='5.4.11'
24
24
  */
25
- version: '5.4.9'
25
+ version: '5.4.11'
26
26
  }
27
27
 
28
28
  /**
@@ -5,6 +5,10 @@ Neo.overwrites = {
5
5
  Text: {
6
6
  labelPosition_ : 'inline',
7
7
  showOptionalText_: true
8
+ },
9
+ ZipCode: {
10
+ maxLength: 5,
11
+ minLength: 5
8
12
  }
9
13
  }
10
14
  }
@@ -1,5 +1,5 @@
1
1
  import FormPageContainer from '../FormPageContainer.mjs';
2
- import TextField from '../../../../src/form/field/Text.mjs';
2
+ import ZipCodeField from '../../../../src/form/field/ZipCode.mjs';
3
3
 
4
4
  /**
5
5
  * @class Form.view.pages.Page11
@@ -16,13 +16,15 @@ class Page11 extends FormPageContainer {
16
16
  * @member {Object[]} items
17
17
  */
18
18
  items: [{
19
- module : TextField,
20
- labelText: 'Page 11 Field 1',
21
- name : 'page11field1'
19
+ module : ZipCodeField,
20
+ labelText: 'Munich',
21
+ name : 'page11.field1',
22
+ required : true,
23
+ value : '80796'
22
24
  }, {
23
- module : TextField,
25
+ module : ZipCodeField,
24
26
  labelText: 'Page 11 Field 2',
25
- name : 'page11field2'
27
+ name : 'page11.field2'
26
28
  }]
27
29
  }
28
30
  }
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.4.9'
23
+ * @member {String} version='5.4.11'
24
24
  */
25
- version: '5.4.9'
25
+ version: '5.4.11'
26
26
  }
27
27
 
28
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.4.9",
3
+ "version": "5.4.11",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -47,19 +47,19 @@
47
47
  "autoprefixer": "^10.4.14",
48
48
  "chalk": "^5.2.0",
49
49
  "clean-webpack-plugin": "^4.0.0",
50
- "commander": "^10.0.0",
50
+ "commander": "^10.0.1",
51
51
  "cssnano": "^6.0.0",
52
52
  "envinfo": "^7.8.1",
53
53
  "fs-extra": "^11.1.1",
54
54
  "highlightjs-line-numbers.js": "^2.8.0",
55
- "inquirer": "^9.1.5",
55
+ "inquirer": "^9.2.0",
56
56
  "neo-jsdoc": "^1.0.1",
57
57
  "neo-jsdoc-x": "^1.0.5",
58
- "postcss": "^8.4.21",
59
- "sass": "^1.61.0",
60
- "webpack": "^5.78.0",
61
- "webpack-cli": "^5.0.1",
62
- "webpack-dev-server": "4.13.2",
58
+ "postcss": "^8.4.23",
59
+ "sass": "^1.62.0",
60
+ "webpack": "^5.80.0",
61
+ "webpack-cli": "^5.0.2",
62
+ "webpack-dev-server": "4.13.3",
63
63
  "webpack-hook-plugin": "^1.0.7",
64
64
  "webpack-node-externals": "^3.0.0"
65
65
  },
@@ -16,7 +16,7 @@
16
16
  {"id": 12, "cardIndex": 8, "isHeader": false, "isValid": null, "name": "HiddenFields"},
17
17
  {"id": 13, "cardIndex": 9, "isHeader": false, "isValid": null, "name": "SelectFields"},
18
18
  {"id": 14, "cardIndex": null, "isHeader": true, "isValid": null, "name": "4. Optional data"},
19
- {"id": 15, "cardIndex": 10, "isHeader": false, "isValid": null, "name": "Page 11"},
19
+ {"id": 15, "cardIndex": 10, "isHeader": false, "isValid": null, "name": "ZipCodeFields"},
20
20
  {"id": 16, "cardIndex": 11, "isHeader": false, "isValid": null, "name": "Page 12"},
21
21
  {"id": 17, "cardIndex": 12, "isHeader": false, "isValid": null, "name": "Page 13"},
22
22
  {"id": 18, "cardIndex": 13, "isHeader": false, "isValid": null, "name": "Page 14"}
@@ -237,12 +237,12 @@ const DefaultConfig = {
237
237
  useVdomWorker: true,
238
238
  /**
239
239
  * buildScripts/injectPackageVersion.mjs will update this value
240
- * @default '5.4.9'
240
+ * @default '5.4.11'
241
241
  * @memberOf! module:Neo
242
242
  * @name config.version
243
243
  * @type String
244
244
  */
245
- version: '5.4.9'
245
+ version: '5.4.11'
246
246
  };
247
247
 
248
248
  Object.assign(DefaultConfig, {
@@ -259,11 +259,11 @@ class Base extends CoreBase {
259
259
  */
260
260
  role_: null,
261
261
  /**
262
- * Set this to true for bulk updates.
263
- * Ensure to set it back to false afterwards.
264
- * @member {Boolean} silentVdomUpdate=false
262
+ * Set this to true for bulk updates. Ensure to set it back to false afterwards.
263
+ * Internally the value will get saved as a number to ensure that child methods won't stop the silent mode too early.
264
+ * @member {Boolean} silentVdomUpdate_=false
265
265
  */
266
- silentVdomUpdate: false,
266
+ silentVdomUpdate_: false,
267
267
  /**
268
268
  * Style attributes added to this vdom root. see: getVdomRoot()
269
269
  * @member {Object} style_=null
@@ -982,6 +982,21 @@ class Base extends CoreBase {
982
982
  return value;
983
983
  }
984
984
 
985
+ /**
986
+ * Triggered before the silentVdomUpdate config gets changed.
987
+ * @param {Boolean} value
988
+ * @param {Boolean} oldValue
989
+ * @returns {Number}
990
+ * @protected
991
+ */
992
+ beforeSetSilentVdomUpdate(value, oldValue) {
993
+ if (value === true) {
994
+ return Neo.isNumber(oldValue) ? (oldValue + 1) : 1
995
+ }
996
+
997
+ return (Neo.isNumber(oldValue) && oldValue > 0) ? (oldValue - 1) : 0
998
+ }
999
+
985
1000
  /**
986
1001
  * Changes the value of a vdom object attribute or removes it in case it has no value
987
1002
  * @param {String} key
@@ -0,0 +1,30 @@
1
+ import Text from './Text.mjs';
2
+
3
+ /**
4
+ * An extended form.field.Text which uses an input type 'tel'
5
+ * @class Neo.form.field.Phone
6
+ * @extends Neo.form.field.Text
7
+ */
8
+ class Phone extends Text {
9
+ static config = {
10
+ /**
11
+ * @member {String} className='Neo.form.field.Phone'
12
+ * @protected
13
+ */
14
+ className: 'Neo.form.field.Phone',
15
+ /**
16
+ * @member {String} ntype='phonefield'
17
+ * @protected
18
+ */
19
+ ntype: 'phonefield',
20
+ /**
21
+ * Value for the inputType_ textfield config
22
+ * @member {String} inputType='tel'
23
+ */
24
+ inputType: 'tel'
25
+ }
26
+ }
27
+
28
+ Neo.applyClassConfig(Phone);
29
+
30
+ export default Phone;
@@ -93,6 +93,13 @@ class Picker extends Text {
93
93
  }]
94
94
  }
95
95
 
96
+ /**
97
+ * Internal flag to prevent showing a picker multiple times
98
+ * @member {Boolean} pickerIsMounting=false
99
+ * @protected
100
+ */
101
+ pickerIsMounting = false
102
+
96
103
  /**
97
104
  * @param {Object} config
98
105
  */
@@ -267,7 +274,7 @@ class Picker extends Text {
267
274
  * @param {Object} data
268
275
  * @protected
269
276
  */
270
- onFocusEnter(data) {
277
+ onFocusEnter(data) {console.log('onFocusEnter')
271
278
  super.onFocusEnter(data);
272
279
 
273
280
  let me = this;
@@ -279,7 +286,7 @@ class Picker extends Text {
279
286
  * @param {Object} data
280
287
  * @protected
281
288
  */
282
- onFocusLeave(data) {
289
+ onFocusLeave(data) {console.log('onFocusLeave')
283
290
  let me = this,
284
291
  insidePicker = false,
285
292
  item;
@@ -300,7 +307,7 @@ class Picker extends Text {
300
307
  /**
301
308
  * @param {Object} data
302
309
  */
303
- onInputClick(data) {
310
+ onInputClick(data) {console.log('onInputClick')
304
311
  let me = this;
305
312
 
306
313
  if (!me.editable) {
@@ -346,16 +353,21 @@ class Picker extends Text {
346
353
  picker = me.getPicker(),
347
354
  listenerId;
348
355
 
349
- me.applyClientRects(true);
356
+ if (!me.pickerIsMounting) {
357
+ me.pickerIsMounting = true;
350
358
 
351
- listenerId = picker.on('mounted', () => {
352
- picker.un('mounted', listenerId);
359
+ me.applyClientRects(true);
353
360
 
354
- me.pickerIsMounted = true;
355
- callback?.apply(callbackScope || me);
356
- });
361
+ listenerId = picker.on('mounted', () => {
362
+ picker.un('mounted', listenerId);
363
+
364
+ me.pickerIsMounting = false;
365
+ me.pickerIsMounted = true;
366
+ callback?.apply(callbackScope || me);
367
+ });
357
368
 
358
- picker.render(true);
369
+ picker.render(true);
370
+ }
359
371
  }
360
372
 
361
373
  /**
@@ -74,12 +74,17 @@ class Text extends Base {
74
74
  */
75
75
  error_: null,
76
76
  /**
77
- * data passes maxLength, minLength & valueLength properties
77
+ * data passes inputPattern, maxLength, minLength & valueLength properties
78
+ * @member {Function} errorTextInputPattern=data=>`Input pattern violation: ${data.inputPattern}`
79
+ */
80
+ errorTextInputPattern: data => `Input pattern violation: ${data.inputPattern}`,
81
+ /**
82
+ * data passes inputPattern, maxLength, minLength & valueLength properties
78
83
  * @member {Function} errorTextMaxLength=data=>`Max length violation: ${valueLength} / ${maxLength}`
79
84
  */
80
85
  errorTextMaxLength: data => `Max length violation: ${data.valueLength} / ${data.maxLength}`,
81
86
  /**
82
- * data passes maxLength, minLength & valueLength properties
87
+ * data passes inputPattern, maxLength, minLength & valueLength properties
83
88
  * @member {Function} errorTextMinLength=data=>`Min length violation: ${data.valueLength} / ${data.minLength}`
84
89
  */
85
90
  errorTextMinLength: data => `Min length violation: ${data.valueLength} / ${data.minLength}`,
@@ -92,7 +97,7 @@ class Text extends Base {
92
97
  */
93
98
  hideLabel_: false,
94
99
  /**
95
- * @member {RegExp|null} inputPattern=null
100
+ * @member {RegExp|null} inputPattern_=null
96
101
  */
97
102
  inputPattern_: null,
98
103
  /**
@@ -330,7 +335,12 @@ class Text extends Base {
330
335
  * @protected
331
336
  */
332
337
  afterSetInputPattern(value, oldValue) {
338
+ if (value) {
339
+ value = value.toString();
340
+ value = value.substring(1, value.length - 1);
341
+ }
333
342
 
343
+ this.changeInputElKey('pattern', value);
334
344
  }
335
345
 
336
346
  /**
@@ -1128,21 +1138,16 @@ class Text extends Base {
1128
1138
  * @protected
1129
1139
  */
1130
1140
  onInputValueChange(data) {
1131
- let me = this,
1132
- value = data.value,
1133
- oldValue = me.value,
1134
- vnode = VNodeUtil.findChildVnode(me.vnode, {nodeName: 'input'});
1141
+ let me = this,
1142
+ value = data.value,
1143
+ vnode = VNodeUtil.findChildVnode(me.vnode, {nodeName: 'input'});
1135
1144
 
1136
1145
  if (vnode) {
1137
1146
  // required for validation -> revert a wrong user input
1138
1147
  vnode.vnode.attributes.value = value;
1139
1148
  }
1140
1149
 
1141
- if (me.inputPattern && !me.inputPattern.test(value) ) {
1142
- me.afterSetValue(oldValue, value);
1143
- } else if (value !== oldValue) {
1144
- me.value = value;
1145
- }
1150
+ me.value = value;
1146
1151
  }
1147
1152
 
1148
1153
  /**
@@ -1259,7 +1264,7 @@ class Text extends Base {
1259
1264
  isValid = !value || value === '';
1260
1265
 
1261
1266
  NeoArray[!isValid ? 'add' : 'remove'](cls, 'neo-invalid');
1262
- me[silent ? '_cls' : 'cls'] = cls;
1267
+ me.cls = cls;
1263
1268
 
1264
1269
  errorNode = VDomUtil.findVdomChild(me.vdom, {cls: 'neo-textfield-error'}).vdom;
1265
1270
 
@@ -1319,16 +1324,17 @@ class Text extends Base {
1319
1324
  * @returns {Boolean} Returns true in case there are no client-side errors
1320
1325
  */
1321
1326
  validate(silent=true) {
1322
- let me = this,
1323
- errorField = silent ? '_error' : 'error',
1324
- maxLength = me.maxLength,
1325
- minLength = me.minLength,
1326
- required = me.required,
1327
- returnValue = true,
1328
- value = me.value,
1329
- valueLength = value?.toString().length,
1330
- isEmpty = value !== 0 && (!value || valueLength < 1),
1331
- errorParam = {maxLength, minLength, valueLength},
1327
+ let me = this,
1328
+ errorField = silent ? '_error' : 'error',
1329
+ maxLength = me.maxLength,
1330
+ minLength = me.minLength,
1331
+ required = me.required,
1332
+ returnValue = true,
1333
+ value = me.value,
1334
+ valueLength = value?.toString().length,
1335
+ inputPattern = me.inputPattern,
1336
+ isEmpty = value !== 0 && (!value || valueLength < 1),
1337
+ errorParam = {inputPattern, maxLength, minLength, valueLength},
1332
1338
  errorText;
1333
1339
 
1334
1340
  if (!silent) {
@@ -1343,7 +1349,9 @@ class Text extends Base {
1343
1349
  me[errorField] = errorText;
1344
1350
  returnValue = false;
1345
1351
  }
1346
- } else if (required && isEmpty) {
1352
+ }
1353
+
1354
+ if (required && isEmpty) {
1347
1355
  me[errorField] = me.errorTextRequired;
1348
1356
  returnValue = false;
1349
1357
  } else if (Neo.isNumber(maxLength) && valueLength > maxLength) {
@@ -1356,6 +1364,11 @@ class Text extends Base {
1356
1364
  me[errorField] = me.errorTextMinLength(errorParam);
1357
1365
  returnValue = false;
1358
1366
  }
1367
+ } else if (inputPattern && !inputPattern.test(value)) {
1368
+ if (required || !isEmpty) {
1369
+ me[errorField] = me.errorTextInputPattern(errorParam);
1370
+ returnValue = false;
1371
+ }
1359
1372
  }
1360
1373
 
1361
1374
  if (returnValue) {
@@ -0,0 +1,26 @@
1
+ import Text from './Text.mjs';
2
+
3
+ /**
4
+ * An extended form.field.Text which uses an input pattern to limit the amount of character which users can enter.
5
+ * The first version will only support numbers. Feel free to open feature requests.
6
+ * @class Neo.form.field.ZipCode
7
+ * @extends Neo.form.field.Text
8
+ */
9
+ class ZipCode extends Text {
10
+ static config = {
11
+ /**
12
+ * @member {String} className='Neo.form.field.ZipCode'
13
+ * @protected
14
+ */
15
+ className: 'Neo.form.field.ZipCode',
16
+ /**
17
+ * @member {String} ntype='zipcodefield'
18
+ * @protected
19
+ */
20
+ ntype: 'zipcodefield'
21
+ }
22
+ }
23
+
24
+ Neo.applyClassConfig(ZipCode);
25
+
26
+ export default ZipCode;