neo.mjs 5.2.2 → 5.2.4

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.2.2'
23
+ * @member {String} version='5.2.4'
24
24
  */
25
- version: '5.2.2'
25
+ version: '5.2.4'
26
26
  }
27
27
 
28
28
  /**
@@ -12,18 +12,23 @@ class Page5 extends FormPageContainer {
12
12
  * @protected
13
13
  */
14
14
  className: 'Form.view.pages.Page5',
15
+ /**
16
+ * @member {String} formGroup='page5'
17
+ */
18
+ formGroup: 'page5',
15
19
  /**
16
20
  * @member {Object[]} items
17
21
  */
18
22
  items: [{
19
23
  module : TextField,
20
24
  labelText: 'Page 5 Field 1',
21
- name : 'page5field1',
22
- required : true
25
+ name : 'field1',
26
+ required : true,
27
+ value : 'bar'
23
28
  }, {
24
29
  module : TextField,
25
30
  labelText: 'Page 5 Field 2',
26
- name : 'page5field2'
31
+ name : 'field2'
27
32
  }]
28
33
  }
29
34
  }
@@ -12,18 +12,22 @@ class Page6 extends FormPageContainer {
12
12
  * @protected
13
13
  */
14
14
  className: 'Form.view.pages.Page6',
15
+ /**
16
+ * @member {String} formGroup='page6'
17
+ */
18
+ formGroup: 'page6',
15
19
  /**
16
20
  * @member {Object[]} items
17
21
  */
18
22
  items: [{
19
23
  module : TextField,
20
24
  labelText: 'Page 6 Field 1',
21
- name : 'page6field1',
25
+ name : 'field1',
22
26
  required : true
23
27
  }, {
24
28
  module : TextField,
25
29
  labelText: 'Page 6 Field 2',
26
- name : 'page6field2'
30
+ name : 'field2'
27
31
  }]
28
32
  }
29
33
  }
@@ -1,3 +1,4 @@
1
+ import Fieldset from '../../../../src/form/Fieldset.mjs';
1
2
  import FormPageContainer from '../FormPageContainer.mjs';
2
3
  import TextField from '../../../../src/form/field/Text.mjs';
3
4
 
@@ -12,18 +13,47 @@ class Page7 extends FormPageContainer {
12
13
  * @protected
13
14
  */
14
15
  className: 'Form.view.pages.Page7',
16
+ /**
17
+ * @member {String} formGroup='page7'
18
+ */
19
+ formGroup: 'page7',
15
20
  /**
16
21
  * @member {Object[]} items
17
22
  */
18
23
  items: [{
19
- module : TextField,
20
- labelText: 'Page 7 Field 1',
21
- name : 'page7field1',
22
- required : true
24
+ module : Fieldset,
25
+ formGroup: 'persons[0]',
26
+ title : 'Fieldset 1',
27
+
28
+ items : [{
29
+ module : TextField,
30
+ labelText: 'Firstname',
31
+ name : 'firstname',
32
+ required : true,
33
+ value : 'John'
34
+ }, {
35
+ module : TextField,
36
+ labelText: 'Lastname',
37
+ name : 'lastname',
38
+ value : 'Doe'
39
+ }]
23
40
  }, {
24
- module : TextField,
25
- labelText: 'Page 7 Field 2',
26
- name : 'page7field2'
41
+ module : Fieldset,
42
+ formGroup: 'persons[1]',
43
+ title : 'Fieldset 2',
44
+
45
+ items : [{
46
+ module : TextField,
47
+ labelText: 'Firstname',
48
+ name : 'firstname',
49
+ required : true,
50
+ value : 'Jane'
51
+ }, {
52
+ module : TextField,
53
+ labelText: 'Lastname',
54
+ name : 'lastname',
55
+ value : 'Dough'
56
+ }]
27
57
  }]
28
58
  }
29
59
  }
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.2.2'
23
+ * @member {String} version='5.2.4'
24
24
  */
25
- version: '5.2.2'
25
+ version: '5.2.4'
26
26
  }
27
27
 
28
28
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.2.2",
3
+ "version": "5.2.4",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -10,7 +10,7 @@
10
10
  {"id": 6, "cardIndex": 3, "isHeader": false, "isValid": null, "name": "CheckBoxes"},
11
11
  {"id": 7, "cardIndex": 4, "isHeader": false, "isValid": null, "name": "Page 5"},
12
12
  {"id": 8, "cardIndex": 5, "isHeader": false, "isValid": null, "name": "Page 6"},
13
- {"id": 9, "cardIndex": 6, "isHeader": false, "isValid": null, "name": "Page 7"},
13
+ {"id": 9, "cardIndex": 6, "isHeader": false, "isValid": null, "name": "Fieldsets"},
14
14
  {"id": 10, "cardIndex": null, "isHeader": true, "isValid": null, "name": "3. More data"},
15
15
  {"id": 11, "cardIndex": 7, "isHeader": false, "isValid": null, "name": "Page 8"},
16
16
  {"id": 12, "cardIndex": 8, "isHeader": false, "isValid": null, "name": "Page 9"},
@@ -100,7 +100,7 @@
100
100
  &:active {
101
101
  background-color: v(button-background-color-active) !important;
102
102
  background-image: none !important;
103
- border : v(button-border-active);
103
+ border : v(button-border-active) !important;
104
104
 
105
105
  .neo-button-glyph {
106
106
  color: v(button-glyph-color-active);
@@ -237,12 +237,12 @@ const DefaultConfig = {
237
237
  useVdomWorker: true,
238
238
  /**
239
239
  * buildScripts/injectPackageVersion.mjs will update this value
240
- * @default '5.2.2'
240
+ * @default '5.2.4'
241
241
  * @memberOf! module:Neo
242
242
  * @name config.version
243
243
  * @type String
244
244
  */
245
- version: '5.2.2'
245
+ version: '5.2.4'
246
246
  };
247
247
 
248
248
  Object.assign(DefaultConfig, {
package/src/Neo.mjs CHANGED
@@ -411,12 +411,43 @@ Neo = globalThis.Neo = Object.assign({
411
411
  if (create && !prev[current]) {
412
412
  prev[current] = {};
413
413
  }
414
+
414
415
  if (prev) {
415
416
  return prev[current];
416
417
  }
417
418
  }, scope || globalThis);
418
419
  },
419
420
 
421
+ /**
422
+ * Extended version of Neo.ns() which supports mapping into arrays.
423
+ * @memberOf module:Neo
424
+ * @param {Array|String} names The class name string containing dots or an Array of the string parts
425
+ * @param {Boolean} [create] Set create to true to create empty objects for non-existing parts
426
+ * @param {Object} [scope] Set a different starting point as globalThis
427
+ * @returns {Object} reference to the toplevel namespace
428
+ */
429
+ nsWithArrays(names, create, scope) {
430
+ names = Array.isArray(names) ? names : names.split('.');
431
+
432
+ return names.reduce((prev, current) => {
433
+ if (create && !prev[current]) {
434
+ if (current.endsWith(']')) {
435
+ return createArrayNs(true, current, prev);
436
+ }
437
+
438
+ prev[current] = {};
439
+ }
440
+
441
+ if (prev) {
442
+ if (current.endsWith(']')) {
443
+ return createArrayNs(false, current, prev);
444
+ }
445
+
446
+ return prev[current];
447
+ }
448
+ }, scope || globalThis);
449
+ },
450
+
420
451
  /**
421
452
  * Creates instances of Neo classes using their ntype instead of the class name
422
453
  * @example
@@ -439,6 +470,7 @@ Neo = globalThis.Neo = Object.assign({
439
470
  ntype(ntype, config) {
440
471
  if (typeof ntype === 'object') {
441
472
  config = ntype;
473
+
442
474
  if (!config.ntype) {
443
475
  throw new Error('Class defined with object configuration missing ntype property. ' + config.ntype);
444
476
  }
@@ -450,6 +482,7 @@ Neo = globalThis.Neo = Object.assign({
450
482
  if (!className) {
451
483
  throw new Error('ntype ' + ntype + ' does not exist');
452
484
  }
485
+
453
486
  return Neo.create(className, config);
454
487
  },
455
488
 
@@ -492,7 +525,10 @@ const ignoreMixin = [
492
525
  'ntype',
493
526
  'observable',
494
527
  'registerToGlobalNs'
495
- ];
528
+ ],
529
+
530
+ charsRegex = /\d+/g,
531
+ extractArraysRegex = /^(\w+)\s*((?:\[\s*\d+\s*\]\s*)*)$/;
496
532
 
497
533
  /**
498
534
  * @param {Neo.core.Base} cls
@@ -519,6 +555,7 @@ function applyMixins(cls, mixins) {
519
555
  if (!exists(mixin)) {
520
556
  throw new Error('Attempting to mixin an undefined class: ' + mixin + ', ' + cls.prototype.className);
521
557
  }
558
+
522
559
  mixinCls = Neo.ns(mixin);
523
560
  mixinProto = mixinCls.prototype;
524
561
  }
@@ -619,6 +656,37 @@ function autoGenerateGetSet(proto, key) {
619
656
  Object.defineProperty(proto, key, Neo[getSetCache][key]);
620
657
  }
621
658
 
659
+ /**
660
+ * @param {Boolean} create
661
+ * @param {Object} current
662
+ * @param {Object} prev
663
+ * @returns {Object}
664
+ */
665
+ function createArrayNs(create, current, prev) {
666
+ let arrDetails = parseArrayFromString(current),
667
+ i = 1,
668
+ len = arrDetails.length,
669
+ arrItem, arrRoot;
670
+
671
+ if (create) {
672
+ prev[arrDetails[0]] = arrRoot = prev[arrDetails[0]] || [];
673
+ } else {
674
+ arrRoot = prev[arrDetails[0]];
675
+ }
676
+
677
+ for (; i < len; i++) {
678
+ arrItem = parseInt(arrDetails[i]);
679
+
680
+ if (create) {
681
+ arrRoot[arrItem] = arrRoot[arrItem] || {};
682
+ }
683
+
684
+ arrRoot = arrRoot[arrItem];
685
+ }
686
+
687
+ return arrRoot;
688
+ }
689
+
622
690
  /**
623
691
  * Checks if the class name exists inside the Neo or app namespace
624
692
  * @param {String} className
@@ -646,6 +714,7 @@ function mixinProperty(proto, mixinProto) {
646
714
  if (~ignoreMixin.indexOf(key)) {
647
715
  return;
648
716
  }
717
+
649
718
  if (proto[key]?._from) {
650
719
  if (mixinProto.className === proto[key]._from) {
651
720
  console.warn('Mixin set multiple times or already defined on a Base Class', proto.className, mixinProto.className, key);
@@ -677,6 +746,17 @@ function mixReduce(mixinCls) {
677
746
  };
678
747
  }
679
748
 
749
+ /**
750
+ * @param {String} str
751
+ * @returns {Function}
752
+ * @private
753
+ */
754
+ function parseArrayFromString(str) {
755
+ return (extractArraysRegex.exec(str) || [null]).slice(1).reduce(
756
+ (fun, args) => [fun].concat(args.match(charsRegex))
757
+ );
758
+ }
759
+
680
760
  Neo.config = Neo.config || {};
681
761
 
682
762
  Neo.assignDefaults(Neo.config, DefaultConfig);
@@ -90,15 +90,21 @@ class Container extends BaseContainer {
90
90
  async getValues() {
91
91
  let fields = await this.getFields(),
92
92
  values = {},
93
- key, ns, nsArray, value;
93
+ itemName, key, ns, nsArray, value;
94
94
 
95
95
  fields.forEach(item => {
96
96
  value = item.getValue();
97
97
 
98
98
  if (item.name) {
99
- nsArray = item.name.split('.');
99
+ itemName = item.name;
100
+
101
+ if (item.formGroup) {
102
+ itemName = item.formGroup + '.' + itemName;
103
+ }
104
+
105
+ nsArray = itemName.split('.');
100
106
  key = nsArray.pop();
101
- ns = Neo.ns(nsArray, true, values);
107
+ ns = Neo.nsWithArrays(nsArray, true, values);
102
108
  } else {
103
109
  key = item.id;
104
110
  ns = values;
@@ -1,4 +1,5 @@
1
- import Component from '../../component/Base.mjs';
1
+ import Component from '../../component/Base.mjs';
2
+ import ComponentManager from '../../manager/Component.mjs';
2
3
 
3
4
  /**
4
5
  * Abstract base class for form fields
@@ -17,12 +18,24 @@ class Base extends Component {
17
18
  * @protected
18
19
  */
19
20
  ntype: 'basefield',
21
+ /**
22
+ * Form groups can get set on any parent component level.
23
+ * An alternative way for using dots in field names.
24
+ * @member {String|null} formGroup_=null
25
+ */
26
+ formGroup_: null,
20
27
  /**
21
28
  * @member {*} value_=null
22
29
  */
23
30
  value_: null
24
31
  }
25
32
 
33
+ /**
34
+ * An internal cache for formGroups of all parent levels
35
+ * @member {String|null} formGroupString=null
36
+ */
37
+ formGroupString = null
38
+
26
39
  /**
27
40
  * Triggered after the value config got changed
28
41
  * @param {*} value
@@ -34,6 +47,34 @@ class Base extends Component {
34
47
  }
35
48
  }
36
49
 
50
+ /**
51
+ * Triggered when accessing the formGroup config
52
+ * @param {String|null} value
53
+ * @returns {String|null} parents
54
+ * @protected
55
+ */
56
+ beforeGetFormGroup(value) {
57
+ let me = this,
58
+ group = [],
59
+ returnValue;
60
+
61
+ if (me.formGroupString) {
62
+ return me.formGroupString;
63
+ }
64
+
65
+ value && group.push(value);
66
+
67
+ ComponentManager.getParents(me).forEach(parent => {
68
+ parent.formGroup && group.unshift(parent.formGroup)
69
+ });
70
+
71
+ returnValue = group.join('.');
72
+
73
+ me.formGroupString = returnValue;
74
+
75
+ return returnValue;
76
+ }
77
+
37
78
  /**
38
79
  * Override this method as needed
39
80
  * @param {*} value