neo.mjs 4.3.0 → 4.3.1

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.
@@ -65,6 +65,7 @@ class MainContainer extends Viewport {
65
65
  tabButtonConfig: {
66
66
  editRoute: false,
67
67
  iconCls : 'fa fa-rss',
68
+ reference: 'blog-header-button',
68
69
  route : 'mainview=blog',
69
70
  text : 'Blog'
70
71
  }
@@ -42,6 +42,13 @@ class MainContainerController extends ComponentController {
42
42
  return this.getReference(this.mainTabs[tabIndex]);
43
43
  }
44
44
 
45
+ /**
46
+ * @param {Object[]} records
47
+ */
48
+ onBlogPostStoreLoad(records) {
49
+ this.getReference('blog-header-button').badgeText = records.length + ''
50
+ }
51
+
45
52
  /**
46
53
  *
47
54
  */
@@ -24,15 +24,39 @@ class List extends BaseList {
24
24
  */
25
25
  className: 'Website.view.blog.List',
26
26
  /**
27
- * @member {String[]} cls=['website-blog-list','neo-list-container','neo-list']
27
+ * @member {String[]} cls=['website-blog-list','neo-list']
28
28
  */
29
- cls: ['website-blog-list', 'neo-list-container', 'neo-list'],
29
+ cls: ['website-blog-list', 'neo-list'],
30
30
  /**
31
31
  * @member {Neo.data.Store} store=BlogPosts
32
32
  */
33
- store: BlogPosts
33
+ store: BlogPosts,
34
+ /**
35
+ * @member {Boolean} useWrapperNode=true
36
+ */
37
+ useWrapperNode: true,
38
+ /**
39
+ * @member {Object} _vdom
40
+ */
41
+ _vdom:
42
+ {cn: [
43
+ {tag: 'ul', cn: []}
44
+ ]}
34
45
  }}
35
46
 
47
+ /**
48
+ * @param {Neo.data.Store} value
49
+ * @param {Neo.data.Store} oldValue
50
+ */
51
+ afterSetStore(value, oldValue) {
52
+ super.afterSetStore(value, oldValue);
53
+
54
+ value.on({
55
+ load : 'onBlogPostStoreLoad',
56
+ scope: this.getController()
57
+ });
58
+ }
59
+
36
60
  /**
37
61
  * @param {Object} record
38
62
  */
@@ -131,6 +155,20 @@ class List extends BaseList {
131
155
 
132
156
  me.vdom = vdom;
133
157
  }
158
+
159
+ /**
160
+ * @returns {Object}
161
+ */
162
+ getVdomRoot() {
163
+ return this.vdom.cn[0];
164
+ }
165
+
166
+ /**
167
+ * @returns {Object}
168
+ */
169
+ getVnodeRoot() {
170
+ return this.vnode.childNodes[0];
171
+ }
134
172
  }
135
173
 
136
174
  Neo.applyClassConfig(List);
@@ -23,9 +23,9 @@ class List extends BaseList {
23
23
  */
24
24
  className: 'Website.view.examples.List',
25
25
  /**
26
- * @member {String[]} cls=['website-examples-list','neo-list-container','neo-list']
26
+ * @member {String[]} cls=['website-examples-list','neo-list']
27
27
  */
28
- cls: ['website-examples-list', 'neo-list-container', 'neo-list'],
28
+ cls: ['website-examples-list', 'neo-list'],
29
29
  /**
30
30
  * @member {Neo.data.Store} store=Examples
31
31
  */
@@ -33,7 +33,18 @@ class List extends BaseList {
33
33
  /**
34
34
  * @member {String|null} storeUrl_=null
35
35
  */
36
- storeUrl_: null
36
+ storeUrl_: null,
37
+ /**
38
+ * @member {Boolean} useWrapperNode=true
39
+ */
40
+ useWrapperNode: true,
41
+ /**
42
+ * @member {Object} _vdom
43
+ */
44
+ _vdom:
45
+ {cn: [
46
+ {tag: 'ul', cn: []}
47
+ ]}
37
48
  }}
38
49
 
39
50
  /**
@@ -96,6 +107,20 @@ class List extends BaseList {
96
107
  ]}
97
108
  ];
98
109
  }
110
+
111
+ /**
112
+ * @returns {Object}
113
+ */
114
+ getVdomRoot() {
115
+ return this.vdom.cn[0];
116
+ }
117
+
118
+ /**
119
+ * @returns {Object}
120
+ */
121
+ getVnodeRoot() {
122
+ return this.vnode.childNodes[0];
123
+ }
99
124
  }
100
125
 
101
126
  Neo.applyClassConfig(List);
@@ -17,10 +17,15 @@ class TabContainer extends Container {
17
17
  */
18
18
  activeIndex: 2,
19
19
  /**
20
- * @member {Array} items
20
+ * @member {Object} itemDefaults
21
+ */
22
+ itemDefaults: {
23
+ module: List
24
+ },
25
+ /**
26
+ * @member {Object[]} items
21
27
  */
22
28
  items: [{
23
- module : List,
24
29
  reference : 'examples-devmode-list',
25
30
  storeUrl : '../../apps/website/data/examples_devmode.json',
26
31
  tabButtonConfig: {
@@ -29,7 +34,6 @@ class TabContainer extends Container {
29
34
  text : 'DevMode'
30
35
  }
31
36
  }, {
32
- module : List,
33
37
  reference : 'examples-dist-dev-list',
34
38
  storeUrl : '../../apps/website/data/examples_dist_dev.json',
35
39
  tabButtonConfig: {
@@ -38,7 +42,6 @@ class TabContainer extends Container {
38
42
  text : 'dist/dev'
39
43
  }
40
44
  }, {
41
- module : List,
42
45
  reference : 'examples-dist-prod-list',
43
46
  storeUrl : '../../apps/website/data/examples_dist_prod.json',
44
47
  tabButtonConfig: {
@@ -261,6 +261,7 @@ if (programOpts.info) {
261
261
  default: 'Custom',
262
262
  choices: [
263
263
  'Custom',
264
+ 'Boolean',
264
265
  'Object',
265
266
  'Object[]',
266
267
  'Number',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,4 +1,4 @@
1
- .website-blog-list.neo-list-container.neo-list {
1
+ .website-blog-list.neo-list {
2
2
  transition: padding v(website-transition-duration) ease-out;
3
3
 
4
4
  .neo-list-item {
@@ -180,4 +180,4 @@
180
180
  width : 44px;
181
181
  }
182
182
  }
183
- }
183
+ }
@@ -1,4 +1,4 @@
1
- .website-examples-list.neo-list-container.neo-list {
1
+ .website-examples-list.neo-list {
2
2
  transition: padding v(website-transition-duration) ease-out;
3
3
 
4
4
  .neo-list-item {
@@ -154,4 +154,4 @@
154
154
  margin-top: 20px;
155
155
  }
156
156
  }
157
- }
157
+ }
@@ -1,4 +1,6 @@
1
1
  .neo-calendars-colors-list {
2
+ overflow: visible;
3
+
2
4
  &:focus {
3
5
  outline: none;
4
6
  }
@@ -7,11 +9,12 @@
7
9
  border-radius: 50%;
8
10
  display : inline-block;
9
11
  height : 1.5em;
10
- margin-right : 0.3em;
12
+ margin : 0.3em 0.3em 0.3em 0;
13
+ transition : box-shadow .2s;
11
14
  width : 1.5em;
12
15
 
13
16
  &.neo-selected {
14
- box-shadow: 0 0 0 3px currentColor;
17
+ box-shadow: 0 0 0 0.25em currentColor;
15
18
  }
16
19
  }
17
20
  }
@@ -1,16 +1,12 @@
1
1
  .neo-layout-card {
2
2
  display : flex;
3
3
  align-items: stretch;
4
- }
5
-
6
- .neo-layout-card-item {
7
- flex: 1 0 100%;
8
4
 
9
- &.active-item {
5
+ > * {
6
+ flex: 1 0 100%;
10
7
 
8
+ &.neo-inactive-item {
9
+ display: none !important;
10
+ }
11
11
  }
12
-
13
- &.inactive-item {
14
- display: none !important;
15
- }
16
- }
12
+ }
@@ -1,7 +1,8 @@
1
- .neo-list-container {
1
+ .neo-list-wrapper {
2
2
  background-color: v(list-container-background-color);
3
3
  border : v(list-container-border);
4
- overflow : auto;
4
+ overflow : hidden;
5
+ position : relative;
5
6
  }
6
7
 
7
8
  .neo-list {
@@ -12,6 +13,7 @@
12
13
  margin-inline-start : 0;
13
14
  margin-inline-end : 0;
14
15
  padding-inline-start: 0;
16
+ overflow : auto;
15
17
 
16
18
  &.neo-use-checkicons {
17
19
  .neo-list-item:before {
@@ -28,6 +30,12 @@
28
30
  }
29
31
  }
30
32
 
33
+ &.neo-use-wrapper-node {
34
+ height : 100%;
35
+ position: absolute;
36
+ width : 100%;
37
+ }
38
+
31
39
  .neo-list-item {
32
40
  background-color: v(list-item-background-color);
33
41
  cursor : pointer;
@@ -51,4 +59,4 @@
51
59
  color: v(list-item-highlight-search-color);
52
60
  }
53
61
  }
54
- }
62
+ }
@@ -29,7 +29,8 @@
29
29
  }
30
30
 
31
31
  .neo-tab-content-container {
32
- border: v(tab-container-content-border);
32
+ border : v(tab-container-content-border);
33
+ overflow: hidden;
33
34
  }
34
35
 
35
36
  .neo-tab-header-toolbar {
@@ -1,5 +1,6 @@
1
1
  .neo-table-wrapper {
2
2
  overflow: auto;
3
+ position: relative;
3
4
  height : 100%;
4
5
  }
5
6
 
@@ -12,6 +13,7 @@
12
13
  font-weight : 400;
13
14
  line-height : 19px;
14
15
  overflow : auto;
16
+ position : absolute;
15
17
 
16
18
  tr {
17
19
  height : 32px !important;
@@ -118,4 +120,4 @@
118
120
  }
119
121
  }
120
122
 
121
- #myTableContainer ::-webkit-scrollbar-track:horizontal {margin-left: 400px;}
123
+ #myTableContainer ::-webkit-scrollbar-track:horizontal {margin-left: 400px;}
@@ -4,6 +4,16 @@
4
4
  display : flex;
5
5
  position: relative;
6
6
 
7
+ .neo-list {
8
+ overflow: visible;
9
+ }
10
+
11
+ .neo-list-container {
12
+ background-color: v(list-container-background-color);
13
+ border : v(list-container-border);
14
+ overflow : auto;
15
+ }
16
+
7
17
  .neo-list-folder {
8
18
  + .neo-list {
9
19
  display: none;
@@ -85,4 +95,4 @@
85
95
  content: "\f07c";
86
96
  }
87
97
  }
88
- }
98
+ }
@@ -21,6 +21,10 @@ class ColorsList extends List {
21
21
  * @member {String[]} cls=['neo-calendars-colors-list','neo-list']
22
22
  */
23
23
  cls: ['neo-calendars-colors-list', 'neo-list'],
24
+ /**
25
+ * @member {Boolean} useWrapperNode=false
26
+ */
27
+ useWrapperNode: false,
24
28
  /**
25
29
  * The list gets used as a form field, so we are adjusting the selection based on this config
26
30
  * @member {String} value_=null
@@ -63,6 +67,20 @@ class ColorsList extends List {
63
67
  }};
64
68
  }
65
69
 
70
+ /**
71
+ * @returns {Object}
72
+ */
73
+ getVdomRoot() {
74
+ return this.vdom;
75
+ }
76
+
77
+ /**
78
+ * @returns {Object}
79
+ */
80
+ getVnodeRoot() {
81
+ return this.vnode;
82
+ }
83
+
66
84
  /**
67
85
  *
68
86
  */
@@ -64,9 +64,7 @@ class EditContainer extends FormContainer {
64
64
  afterSetMounted(value, oldValue) {
65
65
  super.afterSetMounted(value, oldValue);
66
66
 
67
- if (value) {
68
- this.getField('name').focus();
69
- }
67
+ value && this.getField('name').focus();
70
68
  }
71
69
 
72
70
  /**
@@ -117,12 +115,12 @@ class EditContainer extends FormContainer {
117
115
 
118
116
  if (record) {
119
117
  me.colorsList = Neo.create({
120
- module : ColorsList,
121
- appName : me.appName,
122
- listeners: {change: me.onColorChange, scope: me},
123
- parentId : me.parentId,
124
- style : {marginTop: '0.5em'},
125
- value : record.color,
118
+ module : ColorsList,
119
+ appName : me.appName,
120
+ listeners : {change: me.onColorChange, scope: me},
121
+ parentId : me.parentId,
122
+ value : record.color,
123
+ wrapperStyle: {marginTop: '0.2em'},
126
124
  ...me.colorsListConfig
127
125
  });
128
126
 
@@ -75,6 +75,11 @@ class Base extends CoreBase {
75
75
  * @member {Object|null} bind=null
76
76
  */
77
77
  bind: null,
78
+ /**
79
+ * CSS selectors to apply to the root level node of this component
80
+ * @member {String[]} cls_=null
81
+ */
82
+ cls_: null,
78
83
  /**
79
84
  * manager.Focus will change this flag on focusin & out dom events
80
85
  * @member {Boolean} containsFocus_=false
@@ -271,6 +276,10 @@ class Base extends CoreBase {
271
276
  * @member {Number|String|null} width_=null
272
277
  */
273
278
  width_: null,
279
+ /**
280
+ * @member {String[]|null} wrapperCls_=null
281
+ */
282
+ wrapperCls_: null,
274
283
  /**
275
284
  * Top level style attributes. Useful in case getVdomRoot() does not point to the top level DOM node.
276
285
  * @member {Object|null} wrapperStyle_=null
@@ -283,44 +292,6 @@ class Base extends CoreBase {
283
292
  _vdom: {}
284
293
  }}
285
294
 
286
- /**
287
- * CSS selectors to apply to the top level node of this component
288
- * @member {String[]} cls=[]
289
- */
290
- get cls() {
291
- return this._cls ? Neo.clone(this._cls) : [];
292
- }
293
- set cls(value) {
294
- value = value ? value : [];
295
-
296
- let me = this,
297
- vdom = me.vdom,
298
- vdomRoot = me.getVdomRoot(),
299
- oldCls;
300
-
301
- if (typeof value === 'string') {
302
- value = value.split('');
303
- }
304
-
305
- if (me.mounted) {
306
- oldCls = Neo.clone(me._cls);
307
- }
308
-
309
- me._cls = value;
310
-
311
- if (vdomRoot) {
312
- vdomRoot.cls = [...value];
313
- }
314
-
315
- me._vdom = vdom; // silent update
316
-
317
- if (me.silentVdomUpdate) {
318
- me.needsVdomUpdate = true;
319
- } else if (me.mounted) {
320
- me.updateCls(value, oldCls);
321
- }
322
- }
323
-
324
295
  /**
325
296
  * Apply component based listeners
326
297
  * @member {Object} listeners={}
@@ -375,16 +346,11 @@ class Base extends CoreBase {
375
346
  return this._vdom;
376
347
  }
377
348
  set vdom(value) {
378
- let me = this,
379
- app = Neo.apps[me.appName],
380
- vdom = value,
381
- vdomRoot = me.getVdomRoot(),
349
+ let me = this,
350
+ app = Neo.apps[me.appName],
351
+ vdom = value,
382
352
  listenerId;
383
353
 
384
- if (vdomRoot && me.cls) {
385
- vdomRoot.cls = me.cls;
386
- }
387
-
388
354
  // It is important to keep the vdom tree stable to ensure that containers do not lose the references to their
389
355
  // child vdom trees. The if case should not happen, but in case it does, keeping the reference and merging
390
356
  // the content over seems to be the best strategy
@@ -474,6 +440,38 @@ class Base extends CoreBase {
474
440
  value && Neo.currentWorker.insertThemeFiles(value, this.__proto__);
475
441
  }
476
442
 
443
+ /**
444
+ * Triggered after the cls config got changed
445
+ * @param {String[]|null} value
446
+ * @param {String[]|null} oldValue
447
+ * @protected
448
+ */
449
+ afterSetCls(value, oldValue) {
450
+ oldValue = oldValue ? oldValue : [];
451
+ value = value ? value : [];
452
+
453
+ let me = this,
454
+ vdom = me.vdom,
455
+ vdomRoot = me.getVdomRoot(),
456
+ cls;
457
+
458
+ if (vdom !== vdomRoot) {
459
+ // we are using a wrapper node
460
+ vdomRoot.cls = [...value];
461
+ } else {
462
+ // we need to merge changes
463
+ cls = [...me.wrapperCls, ...value];
464
+ NeoArray.remove(cls, NeoArray.difference(oldValue, value));
465
+ vdom.cls = cls;
466
+ }
467
+
468
+ if (me.isVdomUpdating || me.silentVdomUpdate) {
469
+ me.needsVdomUpdate = true;
470
+ } else if (me.mounted) {
471
+ me.updateCls(value, oldValue, vdomRoot.id);
472
+ }
473
+ }
474
+
477
475
  /**
478
476
  * Triggered after any config got changed
479
477
  * @param {String} key
@@ -709,6 +707,39 @@ class Base extends CoreBase {
709
707
  this.changeVdomRootKey('width', value);
710
708
  }
711
709
 
710
+ /**
711
+ * Triggered after the wrapperCls config got changed
712
+ * @param {String[]|null} value
713
+ * @param {String[]|null} oldValue
714
+ * @protected
715
+ */
716
+ afterSetWrapperCls(value, oldValue) {
717
+ let me = this,
718
+ vdom = me.vdom,
719
+ vdomRoot = me.getVdomRoot(),
720
+ cls = me.vdom?.cls || [];
721
+
722
+ if (vdom === vdomRoot) {
723
+ // we are not using a wrapper => cls & wrapperCls share the same node
724
+ me.afterSetCls(me._cls, me._cls);
725
+ } else {
726
+ value = value ? value : [];
727
+
728
+ oldValue && NeoArray.remove(cls, oldValue);
729
+ NeoArray.add(cls, value);
730
+
731
+ if (vdom) {
732
+ vdom.cls = cls;
733
+ }
734
+
735
+ if (me.isVdomUpdating || me.silentVdomUpdate) {
736
+ me.needsVdomUpdate = true;
737
+ } else if (me.mounted) {
738
+ me.updateCls(value, oldValue);
739
+ }
740
+ }
741
+ }
742
+
712
743
  /**
713
744
  * Triggered after the wrapperStyle config got changed
714
745
  * @param {Object} value
@@ -729,6 +760,15 @@ class Base extends CoreBase {
729
760
  }
730
761
  }
731
762
 
763
+ /**
764
+ * Triggered when accessing the cls config
765
+ * @param {String[]|null} value
766
+ * @protected
767
+ */
768
+ beforeGetCls(value) {
769
+ return value ? [...value]: [];
770
+ }
771
+
732
772
  /**
733
773
  * Triggered when accessing the data config
734
774
  * Convenience shortcut which is expensive to use,
@@ -740,6 +780,15 @@ class Base extends CoreBase {
740
780
  return this.getModel().getHierarchyData();
741
781
  }
742
782
 
783
+ /**
784
+ * Triggered when accessing the wrapperCls config
785
+ * @param {String[]|null} value
786
+ * @protected
787
+ */
788
+ beforeGetWrapperCls(value) {
789
+ return value ? [...value]: [];
790
+ }
791
+
743
792
  /**
744
793
  * Triggered when accessing the wrapperStyle config
745
794
  * @param {Object} value
@@ -1198,13 +1247,11 @@ class Base extends CoreBase {
1198
1247
  // avoid any interference on prototype level
1199
1248
  // does not clone existing Neo instances
1200
1249
  me._vdom = Neo.clone(vdom, true, true);
1201
- me.cls = config.cls;
1202
1250
 
1203
1251
  me[Neo.isEmpty(config.style) ? '_style' : 'style'] = config.style;
1204
1252
 
1205
1253
  me.wrapperStyle = Neo.clone(config.wrapperStyle, false);
1206
1254
 
1207
- delete config.cls;
1208
1255
  delete config.style;
1209
1256
  delete config._vdom;
1210
1257
  delete config.vdom;
@@ -1648,28 +1695,30 @@ class Base extends CoreBase {
1648
1695
 
1649
1696
  /**
1650
1697
  * Delta updates for the cls config. Gets called after the cls config gets changed in case the component is mounted.
1651
- * @param {Array} cls
1652
- * @param {Array} oldCls
1698
+ * @param {String[]} cls
1699
+ * @param {String[]} oldCls
1700
+ * @param {String} id=this.id
1653
1701
  * @protected
1654
1702
  */
1655
- updateCls(cls, oldCls) {
1656
- let me = this,
1657
- vnode = me.vnode,
1703
+ updateCls(cls, oldCls, id=this.id) {
1704
+ let me = this,
1705
+ vnode = me.vnode,
1706
+ vnodeTarget = VNodeUtil.findChildVnode(me.vnode, {id})?.vnode,
1658
1707
  opts;
1659
1708
 
1660
1709
  if (!Neo.isEqual(cls, oldCls)) {
1661
- if (vnode) {
1662
- vnode.className = cls; // keep the vnode in sync
1710
+ if (vnodeTarget) {
1711
+ vnodeTarget.className = cls; // keep the vnode in sync
1663
1712
  me.vnode = vnode;
1664
1713
  }
1665
1714
 
1666
1715
  opts = {
1667
1716
  action: 'updateDom',
1668
1717
  deltas: [{
1669
- id : me.id,
1718
+ id,
1670
1719
  cls: {
1671
- add : Neo.util.Array.difference(cls, oldCls),
1672
- remove: Neo.util.Array.difference(oldCls, cls)
1720
+ add : NeoArray.difference(cls, oldCls),
1721
+ remove: NeoArray.difference(oldCls, cls)
1673
1722
  }
1674
1723
  }]
1675
1724
  };
@@ -44,33 +44,31 @@ class Base extends CoreBase {
44
44
  * @protected
45
45
  */
46
46
  afterSetAppName(value, oldValue) {
47
- if (value) {
48
- Neo.currentWorker.insertThemeFiles(value, this.__proto__);
49
- }
47
+ value && Neo.currentWorker.insertThemeFiles(value, this.__proto__);
50
48
  }
51
49
 
52
50
  /**
53
- * Placeholder Method
51
+ * Placeholder method
54
52
  * @param {Neo.component.Base} item
55
53
  * @protected
56
54
  */
57
55
  applyChildAttributes(item) {}
58
56
 
59
57
  /**
60
- * Placeholder Method
58
+ * Placeholder method
61
59
  * @protected
62
60
  */
63
61
  applyRenderAttributes() {}
64
62
 
65
63
  /**
66
- * Placeholder Method
64
+ * Placeholder method
67
65
  * @param {Neo.component.Base} item
68
66
  * @protected
69
67
  */
70
68
  removeChildAttributes(item) {}
71
69
 
72
70
  /**
73
- * Placeholder Method
71
+ * Placeholder method
74
72
  * @protected
75
73
  */
76
74
  removeRenderAttributes() {}
@@ -9,16 +9,16 @@ class Card extends Base {
9
9
  static getStaticConfig() {return {
10
10
  /*
11
11
  * The name of the CSS class for an active item inside the card layout
12
- * @member activeItemCls
12
+ * @member {String} activeItemCls='neo-active-item'
13
13
  * @static
14
14
  */
15
- activeItemCls: 'active-item',
15
+ activeItemCls: 'neo-active-item',
16
16
  /*
17
17
  * The name of the CSS class for an inactive item inside the card layout
18
- * @member inactiveItemCls
18
+ * @member {String} inactiveItemCls='neo-inactive-item'
19
19
  * @static
20
20
  */
21
- inactiveItemCls: 'inactive-item',
21
+ inactiveItemCls: 'neo-inactive-item',
22
22
  /*
23
23
  * The name of the CSS class for an item inside the card layout
24
24
  * @member itemCls
@@ -67,7 +67,7 @@ class Card extends Base {
67
67
  sCfg = me.getStaticConfig(),
68
68
  needsUpdate = false,
69
69
  removeInactiveCards = me.removeInactiveCards,
70
- cls, i, isActiveIndex, item, items, len, module, proto, vdom;
70
+ i, isActiveIndex, item, items, len, module, proto, vdom, wrapperCls;
71
71
 
72
72
  if (Neo.isNumber(value) && container) {
73
73
  items = container.items;
@@ -94,35 +94,32 @@ class Card extends Base {
94
94
  module = item.module;
95
95
 
96
96
  if (isActiveIndex && !module?.isClass && Neo.isFunction(module)) {
97
- module = await module();
98
- module = module.default;
99
- proto = module.prototype;
100
- cls = item.cls || proto.constructor.config.cls || [];
97
+ module = await module();
98
+ module = module.default;
99
+ proto = module.prototype;
100
+ wrapperCls = item.wrapperCls || proto.constructor.config.wrapperCls || [];
101
101
 
102
- item.className = proto.className;
103
- item.cls = [...cls, sCfg.itemCls]
104
- item.module = module;
102
+ item.className = proto.className;
103
+ item.wrapperCls = [...wrapperCls, sCfg.itemCls];
104
+ item.module = module;
105
105
 
106
106
  delete item.vdom;
107
107
 
108
108
  items[i] = item = Neo.create(item);
109
109
 
110
- container.fire('cardLoaded', {
111
- item: item
112
- });
110
+ container.fire('cardLoaded', {item});
113
111
 
114
112
  vdom.cn[i] = item.vdom;
115
113
  }
116
114
 
117
115
  if (item instanceof Neo.core.Base) {
118
- cls = item.cls;
116
+ wrapperCls = item.wrapperCls;
119
117
 
120
- NeoArray.remove(cls, isActiveIndex ? sCfg.inactiveItemCls : sCfg.activeItemCls);
121
- NeoArray.add( cls, isActiveIndex ? sCfg.activeItemCls : sCfg.inactiveItemCls);
118
+ NeoArray.remove(wrapperCls, isActiveIndex ? sCfg.inactiveItemCls : sCfg.activeItemCls);
119
+ NeoArray.add( wrapperCls, isActiveIndex ? sCfg.activeItemCls : sCfg.inactiveItemCls);
122
120
 
123
121
  if (removeInactiveCards || needsUpdate) {
124
- item._cls = cls; // silent update
125
- item.getVdomRoot().cls = cls;
122
+ item.wrapperCls = wrapperCls;
126
123
 
127
124
  if (isActiveIndex) {
128
125
  delete item.vdom.removeDom;
@@ -132,7 +129,7 @@ class Card extends Base {
132
129
  item.vdom.removeDom = true;
133
130
  }
134
131
  } else {
135
- item.cls = cls;
132
+ item.wrapperCls = wrapperCls;
136
133
  }
137
134
  }
138
135
  }
@@ -153,18 +150,18 @@ class Card extends Base {
153
150
  let me = this,
154
151
  isActiveIndex = me.activeIndex === index,
155
152
  sCfg = me.getStaticConfig(),
156
- childCls = item.cls,
153
+ childCls = item.wrapperCls,
157
154
  vdom = item.vdom;
158
155
 
159
156
  NeoArray.add(childCls, sCfg.itemCls);
160
157
  NeoArray.add(childCls, isActiveIndex ? sCfg.activeItemCls : sCfg.inactiveItemCls);
161
158
 
162
159
  if (!keepInDom && me.removeInactiveCards) {
163
- item._cls = childCls; // silent update
164
- vdom.removeDom = !isActiveIndex;
160
+ item.wrapperCls = childCls;
161
+ vdom.removeDom = !isActiveIndex;
165
162
  item.vdom = vdom;
166
163
  } else {
167
- item.cls = childCls;
164
+ item.wrapperCls = childCls;
168
165
  }
169
166
  }
170
167
 
@@ -172,17 +169,17 @@ class Card extends Base {
172
169
  * Applies CSS classes to the container this layout is bound to
173
170
  */
174
171
  applyRenderAttributes() {
175
- let me = this,
176
- container = Neo.getComponent(me.containerId),
177
- cls = container?.cls || [];
172
+ let me = this,
173
+ container = Neo.getComponent(me.containerId),
174
+ wrapperCls = container?.wrapperCls || [];
178
175
 
179
176
  if (!container) {
180
177
  Neo.logError('layout.Card: applyRenderAttributes -> container not yet created', me.containerId);
181
178
  }
182
179
 
183
- NeoArray.add(cls, 'neo-layout-card');
180
+ NeoArray.add(wrapperCls, 'neo-layout-card');
184
181
 
185
- container.cls = cls;
182
+ container.wrapperCls = wrapperCls;
186
183
  }
187
184
 
188
185
  /**
@@ -190,17 +187,17 @@ class Card extends Base {
190
187
  * Gets called when switching to a different layout.
191
188
  */
192
189
  removeRenderAttributes() {
193
- let me = this,
194
- container = Neo.getComponent(me.containerId),
195
- cls = container?.cls || [];
190
+ let me = this,
191
+ container = Neo.getComponent(me.containerId),
192
+ wrapperCls = container?.wrapperCls || [];
196
193
 
197
194
  if (!container) {
198
195
  Neo.logError('layout.Card: removeRenderAttributes -> container not yet created', me.containerId);
199
196
  }
200
197
 
201
- NeoArray.remove(cls, 'neo-layout-card');
198
+ NeoArray.remove(wrapperCls, 'neo-layout-card');
202
199
 
203
- container.cls = cls;
200
+ container.wrapperCls = wrapperCls;
204
201
  }
205
202
  }
206
203
 
@@ -26,7 +26,7 @@ class Fit extends Base {
26
26
  */
27
27
  applyChildAttributes(child, index) {
28
28
  if (!child.ignoreLayout) {
29
- child.cls = NeoArray.union(child.cls, 'neo-layout-fit-item');
29
+ child.wrapperCls = NeoArray.union(child.wrapperCls, 'neo-layout-fit-item');
30
30
  }
31
31
  }
32
32
 
@@ -34,17 +34,17 @@ class Fit extends Base {
34
34
  * Applies CSS classes to the container this layout is bound to
35
35
  */
36
36
  applyRenderAttributes() {
37
- let me = this,
38
- container = Neo.getComponent(me.containerId),
39
- cls = container?.cls || [];
37
+ let me = this,
38
+ container = Neo.getComponent(me.containerId),
39
+ wrapperCls = container?.wrapperCls || [];
40
40
 
41
41
  if (!container) {
42
42
  Neo.logError('layout.Fit: applyRenderAttributes -> container not yet created', me.containerId);
43
43
  }
44
44
 
45
- NeoArray.add(cls, 'neo-layout-fit');
45
+ NeoArray.add(wrapperCls, 'neo-layout-fit');
46
46
 
47
- container.cls = cls;
47
+ container.wrapperCls = wrapperCls;
48
48
  }
49
49
 
50
50
  /**
@@ -52,17 +52,17 @@ class Fit extends Base {
52
52
  * Gets called when switching to a different layout.
53
53
  */
54
54
  removeRenderAttributes() {
55
- let me = this,
56
- container = Neo.getComponent(me.containerId),
57
- cls = container?.cls || [];
55
+ let me = this,
56
+ container = Neo.getComponent(me.containerId),
57
+ wrapperCls = container?.wrapperCls || [];
58
58
 
59
59
  if (!container) {
60
60
  Neo.logError('layout.Fit: removeRenderAttributes -> container not yet created', me.containerId);
61
61
  }
62
62
 
63
- NeoArray.remove(cls, 'neo-layout-fit');
63
+ NeoArray.remove(wrapperCls, 'neo-layout-fit');
64
64
 
65
- container.cls = cls;
65
+ container.wrapperCls = wrapperCls;
66
66
  }
67
67
  }
68
68
 
@@ -130,31 +130,23 @@ class Flexbox extends Base {
130
130
  * Applies CSS classes to the container this layout is bound to
131
131
  */
132
132
  applyRenderAttributes() {
133
- let me = this,
134
- container = Neo.getComponent(me.containerId),
135
- prefix = me.prefix,
136
- cls = container?.cls || [];
133
+ let me = this,
134
+ container = Neo.getComponent(me.containerId),
135
+ prefix = me.prefix,
136
+ wrapperCls = container?.wrapperCls || [];
137
137
 
138
138
  if (!container) {
139
139
  Neo.logError('layout.Flexbox: applyRenderAttributes -> container not yet created', me.containerId);
140
140
  }
141
141
 
142
- NeoArray.add(cls, prefix + 'container');
142
+ NeoArray.add(wrapperCls, prefix + 'container');
143
143
 
144
- if (me.align) {
145
- NeoArray.add(cls, prefix + 'align-' + me.align);
146
- }
147
- if (me.direction) {
148
- NeoArray.add(cls, prefix + 'direction-' + me.direction);
149
- }
150
- if (me.pack) {
151
- NeoArray.add(cls, prefix + 'pack-' + me.pack);
152
- }
153
- if (me.wrap) {
154
- NeoArray.add(cls, prefix + 'wrap-' + me.wrap);
155
- }
144
+ me.align && NeoArray.add(wrapperCls, prefix + 'align-' + me.align);
145
+ me.direction && NeoArray.add(wrapperCls, prefix + 'direction-' + me.direction);
146
+ me.pack && NeoArray.add(wrapperCls, prefix + 'pack-' + me.pack);
147
+ me.wrap && NeoArray.add(wrapperCls, prefix + 'wrap-' + me.wrap);
156
148
 
157
- container.cls = cls;
149
+ container.wrapperCls = wrapperCls;
158
150
  }
159
151
 
160
152
  /**
@@ -220,31 +212,31 @@ class Flexbox extends Base {
220
212
  * @protected
221
213
  */
222
214
  removeRenderAttributes() {
223
- let me = this,
224
- container = Neo.getComponent(me.containerId),
225
- prefix = me.prefix,
226
- cls = container?.cls || [];
215
+ let me = this,
216
+ container = Neo.getComponent(me.containerId),
217
+ prefix = me.prefix,
218
+ wrapperCls = container?.wrapperCls || [];
227
219
 
228
220
  if (!container) {
229
221
  Neo.logError('layout.Flexbox: removeRenderAttributes -> container not yet created', me.containerId);
230
222
  }
231
223
 
232
- NeoArray.remove(cls, prefix + 'container');
224
+ NeoArray.remove(wrapperCls, prefix + 'container');
233
225
 
234
226
  if (me.align) {
235
- NeoArray.remove(cls, prefix + 'align-' + me.align);
227
+ NeoArray.remove(wrapperCls, prefix + 'align-' + me.align);
236
228
  }
237
229
  if (me.direction) {
238
- NeoArray.remove(cls, prefix + 'direction-' + me.direction);
230
+ NeoArray.remove(wrapperCls, prefix + 'direction-' + me.direction);
239
231
  }
240
232
  if (me.pack) {
241
- NeoArray.remove(cls, prefix + 'pack-' + me.pack);
233
+ NeoArray.remove(wrapperCls, prefix + 'pack-' + me.pack);
242
234
  }
243
235
  if (me.wrap) {
244
- NeoArray.remove(cls, prefix + 'wrap-' + me.wrap);
236
+ NeoArray.remove(wrapperCls, prefix + 'wrap-' + me.wrap);
245
237
  }
246
238
 
247
- container.cls = cls;
239
+ container.wrapperCls = wrapperCls;
248
240
  }
249
241
 
250
242
  /**
@@ -268,26 +260,26 @@ class Flexbox extends Base {
268
260
  }
269
261
 
270
262
  /**
271
- * Updates the Container CSS cls
263
+ * Updates the Container CSS wrapperCls
272
264
  * @param {String|null} value
273
265
  * @param {String|null} oldValue
274
266
  * @param {String} propertyName
275
267
  * @protected
276
268
  */
277
269
  updateInputValue(value, oldValue, propertyName) {
278
- let me = this,
279
- container = Neo.getComponent(me.containerId),
280
- prefix = me.prefix,
281
- cls = container?.cls;
270
+ let me = this,
271
+ container = Neo.getComponent(me.containerId),
272
+ prefix = me.prefix,
273
+ wrapperCls = container?.wrapperCls;
282
274
 
283
275
  if (container?.rendered) {
284
- NeoArray.remove(cls, prefix + propertyName + '-' + oldValue);
276
+ NeoArray.remove(wrapperCls, prefix + propertyName + '-' + oldValue);
285
277
 
286
278
  if (value !== null) {
287
- NeoArray.add(cls, prefix + propertyName + '-' + value);
279
+ NeoArray.add(wrapperCls, prefix + propertyName + '-' + value);
288
280
  }
289
281
 
290
- container.cls = cls;
282
+ container.wrapperCls = wrapperCls;
291
283
  }
292
284
  }
293
285
  }
@@ -25,7 +25,7 @@ class HBox extends Flexbox {
25
25
 
26
26
  /**
27
27
  * Applies the flex value to an item of the container this layout is bound to
28
- * @param {Object} item
28
+ * @param {Neo.component.Base} item
29
29
  */
30
30
  applyChildAttributes(item) {
31
31
  // Do not apply flex if fixed width
@@ -25,7 +25,7 @@ class VBox extends Flexbox {
25
25
 
26
26
  /**
27
27
  * Applies the flex value to an item of the container this layout is bound to
28
- * @param {Object} item
28
+ * @param {Neo.component.Base} item
29
29
  */
30
30
  applyChildAttributes(item) {
31
31
  // Do not apply flex if fixed height
package/src/list/Base.mjs CHANGED
@@ -30,9 +30,9 @@ class Base extends Component {
30
30
  */
31
31
  autoDestroyStore: true,
32
32
  /**
33
- * @member {String[]} cls=['neo-list-container','neo-list']
33
+ * @member {String[]} cls=['neo-list']
34
34
  */
35
- cls: ['neo-list-container', 'neo-list'],
35
+ cls: ['neo-list'],
36
36
  /**
37
37
  * @member {Boolean} disableSelection_=false
38
38
  */
@@ -106,7 +106,11 @@ class Base extends Component {
106
106
  */
107
107
  useCheckBoxes_: false,
108
108
  /**
109
- * @member {Object} _vdom={tag:'ul',cn:[]}
109
+ * @member {Boolean} useWrapperNode_=false
110
+ */
111
+ useWrapperNode_: false,
112
+ /**
113
+ * @member {Object} _vdom
110
114
  */
111
115
  _vdom:
112
116
  {tag: 'ul', cn: []}
@@ -223,6 +227,24 @@ class Base extends Component {
223
227
  me.cls = cls;
224
228
  }
225
229
 
230
+ /**
231
+ * Triggered after the useWrapperNode config got changed
232
+ * @param {Boolean} value
233
+ * @param {Boolean} oldValue
234
+ * @protected
235
+ */
236
+ afterSetUseWrapperNode(value, oldValue) {
237
+ let me = this,
238
+ cls = me.cls,
239
+ wrapperCls = me.wrapperCls;
240
+
241
+ NeoArray[value ? 'add' : 'remove'](cls, 'neo-use-wrapper-node');
242
+ NeoArray[value ? 'add' : 'remove'](wrapperCls, 'neo-list-wrapper');
243
+
244
+ me.wrapperCls = wrapperCls;
245
+ me.cls = cls;
246
+ }
247
+
226
248
  /**
227
249
  * Triggered before the selectionModel config gets changed.
228
250
  * @param {Neo.selection.Model} value
@@ -271,7 +293,7 @@ class Base extends Component {
271
293
 
272
294
  item = {
273
295
  tag : me.itemTagName,
274
- cls : cls,
296
+ cls,
275
297
  id : itemId,
276
298
  tabIndex: -1
277
299
  };
@@ -341,7 +363,7 @@ class Base extends Component {
341
363
  */
342
364
  createItems(silent=false) {
343
365
  let me = this,
344
- vdom = me.vdom,
366
+ vdom = me.getVdomRoot(),
345
367
  listItem;
346
368
 
347
369
  if (!(me.animate && !me.getPlugin('animate'))) {
@@ -157,7 +157,7 @@ class Container extends BaseContainer {
157
157
  afterSetPlain(value, oldValue) {
158
158
  let me = this,
159
159
  baseCls = me.baseCls,
160
- cls = me.cls || [];
160
+ cls = me.cls;
161
161
 
162
162
  NeoArray[value ? 'unshift' : 'remove'](cls, baseCls + '-plain');
163
163
  me.cls = cls;
@@ -135,7 +135,7 @@ class Container extends BaseContainer {
135
135
  ...me.viewConfig
136
136
  }];
137
137
 
138
- me.vdom.id = me.id + 'wrapper';
138
+ me.vdom.id = me.getWrapperId();
139
139
 
140
140
  me.createColumns(me.columns);
141
141
  }
@@ -179,14 +179,15 @@ class Container extends BaseContainer {
179
179
  */
180
180
  applyCustomScrollbarsCss() {
181
181
  let me = this,
182
+ id = me.getWrapperId(),
182
183
  cssRules = [];
183
184
 
184
185
  if (me.dockLeftMargin) {
185
- cssRules.push('#' + me.id + 'wrapper' + '::-webkit-scrollbar-track:horizontal {margin-left: ' + me.dockLeftMargin + 'px;}');
186
+ cssRules.push('#' + id + '::-webkit-scrollbar-track:horizontal {margin-left: ' + me.dockLeftMargin + 'px;}');
186
187
  }
187
188
 
188
189
  if (me.dockRightMargin) {
189
- cssRules.push('#' + me.id + 'wrapper' + '::-webkit-scrollbar-track:horizontal {margin-right: ' + me.dockRightMargin + 'px;}');
190
+ cssRules.push('#' + id + '::-webkit-scrollbar-track:horizontal {margin-right: ' + me.dockRightMargin + 'px;}');
190
191
  }
191
192
  if (cssRules.length > 0) {
192
193
  Css.insertRules(cssRules);
@@ -368,6 +369,13 @@ class Container extends BaseContainer {
368
369
  return this.vnode.childNodes[0];
369
370
  }
370
371
 
372
+ /**
373
+ * @returns {String}
374
+ */
375
+ getWrapperId() {
376
+ return `${this.id}__wrapper`;
377
+ }
378
+
371
379
  /**
372
380
  * @param {Number} countRows
373
381
  */
package/src/tree/List.mjs CHANGED
@@ -47,6 +47,10 @@ class Tree extends Base {
47
47
  * @member {Object} dragZoneConfig=null
48
48
  */
49
49
  sortZoneConfig: null,
50
+ /**
51
+ * @member {String[]} wrapperCls=[]
52
+ */
53
+ wrapperCls: [],
50
54
  /**
51
55
  * @member {Object} _vdom
52
56
  */