neo.mjs 3.2.2 → 3.2.3

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.
@@ -70,10 +70,10 @@ export default env => {
70
70
  content.appPath = content.appPath.replace(regexTopLevel, '');
71
71
 
72
72
  Object.assign(content, {
73
- basePath : basePath,
74
- environment : 'dist/development',
75
- mainPath : '../main.js',
76
- workerBasePath: workerBasePath
73
+ basePath,
74
+ environment: 'dist/development',
75
+ mainPath : '../main.js',
76
+ workerBasePath
77
77
  });
78
78
 
79
79
  fs.writeFileSync(outputPath, JSON.stringify(content, null, 4));
@@ -80,10 +80,10 @@ export default env => {
80
80
  content.appPath = content.appPath.replace(regexTopLevel, '');
81
81
 
82
82
  Object.assign(content, {
83
- basePath : basePath,
84
- environment : 'dist/development',
85
- mainPath : '../main.js',
86
- workerBasePath: workerBasePath
83
+ basePath,
84
+ environment: 'dist/development',
85
+ mainPath : '../main.js',
86
+ workerBasePath
87
87
  });
88
88
 
89
89
  fs.writeFileSync(outputPath, JSON.stringify(content, null, 4));
@@ -75,9 +75,9 @@ export default env => {
75
75
  content.appPath = content.appPath.replace(regexTopLevel, '');
76
76
 
77
77
  Object.assign(content, {
78
- basePath : basePath,
79
- mainPath : '../main.js',
80
- workerBasePath: workerBasePath
78
+ basePath,
79
+ mainPath: '../main.js',
80
+ workerBasePath
81
81
  });
82
82
 
83
83
  fs.writeFileSync(outputPath, JSON.stringify(content));
@@ -86,9 +86,9 @@ export default env => {
86
86
  content.appPath = content.appPath.replace(regexTopLevel, '');
87
87
 
88
88
  Object.assign(content, {
89
- basePath : basePath,
90
- mainPath : '../main.js',
91
- workerBasePath: workerBasePath
89
+ basePath,
90
+ mainPath: '../main.js',
91
+ workerBasePath
92
92
  });
93
93
 
94
94
  fs.writeFileSync(outputPath, JSON.stringify(content));
@@ -129,7 +129,7 @@ class ConfigurationViewport extends Viewport {
129
129
 
130
130
  /**
131
131
  * Override this method to create the components to show inside the configuration container
132
- * @returns {Neo.component.Base[]|null}
132
+ * @returns {Object[]|null}
133
133
  */
134
134
  createConfigurationComponents() {
135
135
  return null;
@@ -19,10 +19,20 @@ class List extends BaseList {
19
19
  * @member {String[]} cls=['neo-examples-list-animate','neo-list-container','neo-list']
20
20
  */
21
21
  cls: ['neo-examples-list-animate', 'neo-list-container', 'neo-list'],
22
+ /**
23
+ * Value in px
24
+ * @member {Number} itemHeight=200
25
+ */
26
+ itemHeight: 200,
22
27
  /**
23
28
  * @member {String} itemTagName='div'
24
29
  */
25
- itemTagName: 'div'
30
+ itemTagName: 'div',
31
+ /**
32
+ * Value in px
33
+ * @member {Number} itemWidth=300
34
+ */
35
+ itemWidth: 300
26
36
  }}
27
37
 
28
38
  /**
@@ -7,11 +7,10 @@ import Store from '../../../src/data/Store.mjs';
7
7
  */
8
8
  class MainStore extends Store {
9
9
  static getConfig() {return {
10
- className : 'Neo.examples.list.animate.MainStore',
11
- autoLoad : true,
12
- keyProperty: 'id',
13
- model : MainModel,
14
- url : '../../resources/examples/data/circleContacts.json',
10
+ className: 'Neo.examples.list.animate.MainStore',
11
+ autoLoad : true,
12
+ model : MainModel,
13
+ url : '../../resources/examples/data/circleContacts.json',
15
14
 
16
15
  filters: [{
17
16
  disabled : true,
@@ -0,0 +1,142 @@
1
+ import CheckBox from '../../../src/form/field/CheckBox.mjs';
2
+ import CircleList from '../../../src/list/Circle.mjs';
3
+ import ConfigurationViewport from '../../ConfigurationViewport.mjs';
4
+ import MainStore from './MainStore.mjs';
5
+ import NumberField from '../../../src/form/field/Number.mjs';
6
+ import Radio from '../../../src/form/field/Radio.mjs';
7
+ import TextField from '../../../src/form/field/Text.mjs';
8
+
9
+ /**
10
+ * @class Neo.examples.list.circle.MainContainer
11
+ * @extends Neo.examples.ConfigurationViewport
12
+ */
13
+ class MainContainer extends ConfigurationViewport {
14
+ static getConfig() {return {
15
+ className : 'Neo.examples.list.circle.MainContainer',
16
+ autoMount : true,
17
+ configItemLabelWidth: 130,
18
+ configItemWidth : 230,
19
+ layout : {ntype: 'hbox', align: 'stretch'}
20
+ }}
21
+
22
+ /**
23
+ * @returns {Object[]}
24
+ */
25
+ createConfigurationComponents() {
26
+ let me = this,
27
+ sorter = me.exampleComponent.store.sorters[0];
28
+
29
+ return [{
30
+ module : CheckBox,
31
+ checked : me.exampleComponent.disableSelection,
32
+ labelText: 'disableSelection',
33
+ listeners: {change: me.onConfigChange.bind(me, 'disableSelection')}
34
+ }, {
35
+ module : NumberField,
36
+ clearable: true,
37
+ labelText: 'height',
38
+ listeners: {change: me.onConfigChange.bind(me, 'height')},
39
+ maxValue : 1000,
40
+ minValue : 300,
41
+ stepSize : 5,
42
+ value : me.exampleComponent.height,
43
+ style : {marginTop: '10px'}
44
+ }, {
45
+ module : Radio,
46
+ checked : sorter.direction === 'ASC',
47
+ hideValueLabel: false,
48
+ labelText : 'Sort',
49
+ listeners : {change: me.changeSorting.bind(me, 'ASC')},
50
+ name : 'sort',
51
+ style : {marginTop: '10px'},
52
+ valueLabelText: 'ASC'
53
+ }, {
54
+ module : Radio,
55
+ checked : sorter.direction === 'DESC',
56
+ hideValueLabel: false,
57
+ labelText : '',
58
+ listeners : {change: me.changeSorting.bind(me, 'DESC')},
59
+ name : 'sort',
60
+ style : {marginTop: '5px'},
61
+ valueLabelText: 'DESC'
62
+ }, {
63
+ module : NumberField,
64
+ clearable: true,
65
+ labelText: 'width',
66
+ listeners: {change: me.onConfigChange.bind(me, 'width')},
67
+ maxValue : 1000,
68
+ minValue : 300,
69
+ stepSize : 5,
70
+ style : {marginTop: '10px'},
71
+ value : me.exampleComponent.width
72
+ }, {
73
+ module : TextField,
74
+ flex : 'none',
75
+ labelText: 'Group1 Name',
76
+ listeners: {change: me.onGroupNameChange.bind(me, 0)},
77
+ name : 'group1',
78
+ style : {marginTop: '10px'},
79
+ value : me.exampleComponent.store.getAt(0).name
80
+ }, {
81
+ module : TextField,
82
+ flex : 'none',
83
+ labelText: 'Group2 Name',
84
+ listeners: {change: me.onGroupNameChange.bind(me, 1)},
85
+ name : 'group2',
86
+ style : {marginTop: '10px'},
87
+ value : me.exampleComponent.store.getAt(1).name
88
+ }];
89
+ }
90
+
91
+ /**
92
+ * @param {String} direction
93
+ * @param {Object} data
94
+ */
95
+ changeSorting(direction, data) {
96
+ if (data.value) {
97
+ this.exampleComponent.store.sorters[0].direction = direction;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * @returns {Neo.component.Base}
103
+ */
104
+ createExampleComponent() {
105
+ let list = Neo.create({
106
+ module : CircleList,
107
+ animate: true,
108
+ height : 1000,
109
+ store : MainStore,
110
+ width : 1000
111
+ });
112
+
113
+ list.store.on('sort', this.onStoreSort, this);
114
+
115
+ return list;
116
+ }
117
+
118
+ /**
119
+ * @param {Number} index
120
+ * @param {Object} data
121
+ */
122
+ onGroupNameChange(index, data) {
123
+ this.exampleComponent.items[index].title = data.value;
124
+ }
125
+
126
+ /**
127
+ * @param {Object} data
128
+ */
129
+ onStoreSort(data) {
130
+ setTimeout(() => {
131
+ let me = this,
132
+ items = me.exampleComponent.items;
133
+
134
+ me.down({name: 'group1'}).value = items[0].title;
135
+ me.down({name: 'group2'}).value = items[1].title;
136
+ }, 10);
137
+ }
138
+ }
139
+
140
+ Neo.applyClassConfig(MainContainer);
141
+
142
+ export default MainContainer;
@@ -0,0 +1,33 @@
1
+ import Model from '../../../src/data/Model.mjs';
2
+
3
+ /**
4
+ * @class Neo.examples.list.circle.MainModel
5
+ * @extends Neo.data.Model
6
+ */
7
+ class MainModel extends Model {
8
+ static getConfig() {return {
9
+ /**
10
+ * @member {String} className='Neo.examples.list.circle.MainModel'
11
+ * @protected
12
+ */
13
+ className: 'Neo.examples.list.circle.MainModel',
14
+ /**
15
+ * @member {Object[]} fields
16
+ * @protected
17
+ */
18
+ fields: [{
19
+ name: 'id',
20
+ type: 'Integer'
21
+ }, {
22
+ name: 'name',
23
+ type: 'String'
24
+ }, {
25
+ name: 'url',
26
+ type: 'String'
27
+ }]
28
+ }}
29
+ }
30
+
31
+ Neo.applyClassConfig(MainModel);
32
+
33
+ export default MainModel;
@@ -0,0 +1,42 @@
1
+ import MainModel from './MainModel.mjs';
2
+ import Store from '../../../src/data/Store.mjs';
3
+
4
+ /**
5
+ * @class Neo.examples.list.circle.MainStore
6
+ * @extends Neo.data.Store
7
+ */
8
+ class MainStore extends Store {
9
+ static getConfig() {return {
10
+ /**
11
+ * @member {String} className='Neo.examples.list.circle.MainStore'
12
+ * @protected
13
+ */
14
+ className: 'Neo.examples.list.circle.MainStore',
15
+ /**
16
+ * @member {Object[]} data
17
+ */
18
+ data: [
19
+ {id: 1, name: 'Red', url: '../../resources/examples/data/circles/group1.json'},
20
+ {id: 2, name: 'Pink', url: '../../resources/examples/data/circles/group4.json'},
21
+ {id: 3, name: 'Orange', url: '../../resources/examples/data/circles/group3.json'},
22
+ {id: 4, name: 'Yellow', url: '../../resources/examples/data/circles/group1.json'},
23
+ {id: 5, name: 'Green', url: '../../resources/examples/data/circles/group2.json'},
24
+ {id: 6, name: 'Blue', url: '../../resources/examples/data/circles/group1.json'}
25
+ ],
26
+ /**
27
+ * @member {Neo.data.Model} model=MainModel
28
+ */
29
+ model: MainModel,
30
+ /**
31
+ * @member {Object[]} sorters
32
+ */
33
+ sorters: [{
34
+ property : 'name',
35
+ direction: 'ASC'
36
+ }]
37
+ }}
38
+ }
39
+
40
+ Neo.applyClassConfig(MainStore);
41
+
42
+ export default MainStore;
@@ -0,0 +1,7 @@
1
+ import MainContainer from './MainContainer.mjs';
2
+
3
+ export const onStart = () => Neo.app({
4
+ mainView: MainContainer,
5
+ name : 'Neo.examples.list.circle'
6
+ });
7
+
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE HTML>
2
+ <html>
3
+ <head>
4
+ <meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <meta charset="UTF-8">
6
+ <title>Neo CircleList</title>
7
+ </head>
8
+ <body>
9
+ <script src="../../../src/MicroLoader.mjs" type="module"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,7 @@
1
+ {
2
+ "appPath" : "examples/list/circle/app.mjs",
3
+ "basePath" : "../../../",
4
+ "environment" : "development",
5
+ "mainPath" : "./Main.mjs",
6
+ "mainThreadAddons": ["Stylesheet"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,18 @@
1
+ {
2
+ "success" : true,
3
+
4
+ "total" : 10,
5
+
6
+ "data" : [
7
+ {"id": 1, "firstname": "Linda", "lastname": "Kamen", "isOnline": false, "image": "ai_images/000022.jpg"},
8
+ {"id": 2, "firstname": "William", "lastname": "Horn", "isOnline": true, "image": "ai_images/000023.jpg"},
9
+ {"id": 3, "firstname": "Kimberly", "lastname": "Martin", "isOnline": false, "image": "ai_images/000024.jpg"},
10
+ {"id": 4, "firstname": "Maribel", "lastname": "Hermandez", "isOnline": true, "image": "ai_images/000025.jpg"},
11
+ {"id": 5, "firstname": "Keneth", "lastname": "Gilette", "isOnline": true, "image": "ai_images/000026.jpg"},
12
+ {"id": 6, "firstname": "Mark", "lastname": "Boerner", "isOnline": false, "image": "ai_images/000027.jpg"},
13
+ {"id": 7, "firstname": "Alicia", "lastname": "Baker", "isOnline": true, "image": "ai_images/000028.jpg"},
14
+ {"id": 8, "firstname": "Wesley", "lastname": "Kaplan", "isOnline": true, "image": "ai_images/000029.jpg"},
15
+ {"id": 9, "firstname": "Leroy", "lastname": "Marzano", "isOnline": false, "image": "ai_images/000030.jpg"},
16
+ {"id": 10, "firstname": "Lynn", "lastname": "Broughton", "isOnline": false, "image": "ai_images/000031.jpg"}
17
+ ]
18
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "success" : true,
3
+
4
+ "total" : 12,
5
+
6
+ "data" : [
7
+ {"id": 1, "firstname": "Leah", "lastname": "Weigle", "isOnline": false, "image": "ai_images/000032.jpg"},
8
+ {"id": 2, "firstname": "Teresita", "lastname": "Cisneros", "isOnline": true, "image": "ai_images/000033.jpg"},
9
+ {"id": 3, "firstname": "Anne", "lastname": "Brown", "isOnline": false, "image": "ai_images/000034.jpg"},
10
+ {"id": 4, "firstname": "Kim", "lastname": "Bryant", "isOnline": true, "image": "ai_images/000035.jpg"},
11
+ {"id": 5, "firstname": "Rose", "lastname": "Seale", "isOnline": true, "image": "ai_images/000036.jpg"},
12
+ {"id": 6, "firstname": "Joseph", "lastname": "Sabin", "isOnline": false, "image": "ai_images/000037.jpg"},
13
+ {"id": 7, "firstname": "Edward", "lastname": "Paine", "isOnline": true, "image": "ai_images/000038.jpg"},
14
+ {"id": 8, "firstname": "Shannon", "lastname": "Dison", "isOnline": true, "image": "ai_images/000039.jpg"},
15
+ {"id": 9, "firstname": "Tyler", "lastname": "Marlowe", "isOnline": false, "image": "ai_images/000040.jpg"},
16
+ {"id": 10, "firstname": "Mary", "lastname": "Thompson", "isOnline": false, "image": "ai_images/000041.jpg"},
17
+ {"id": 11, "firstname": "David", "lastname": "Maddy", "isOnline": false, "image": "ai_images/000042.jpg"},
18
+ {"id": 12, "firstname": "Anna", "lastname": "McDaniel", "isOnline": false, "image": "ai_images/000043.jpg"}
19
+ ]
20
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "success" : true,
3
+
4
+ "total" : 20,
5
+
6
+ "data" : [
7
+ {"id": 1, "firstname": "Susanne", "lastname": "Bosch", "isOnline": false, "image": "ai_images/000044.jpg"},
8
+ {"id": 2, "firstname": "Sarah", "lastname": "Baer", "isOnline": true, "image": "ai_images/000045.jpg"},
9
+ {"id": 3, "firstname": "Felix", "lastname": "Schwarz", "isOnline": false, "image": "ai_images/000046.jpg"},
10
+ {"id": 4, "firstname": "Lukas", "lastname": "Krause", "isOnline": true, "image": "ai_images/000047.jpg"},
11
+ {"id": 5, "firstname": "Frank", "lastname": "Schmitz", "isOnline": true, "image": "ai_images/000048.jpg"},
12
+ {"id": 6, "firstname": "Stefanie", "lastname": "Berg", "isOnline": false, "image": "ai_images/000049.jpg"},
13
+ {"id": 7, "firstname": "Anne", "lastname": "Fischer", "isOnline": true, "image": "ai_images/000050.jpg"},
14
+ {"id": 8, "firstname": "Tanja", "lastname": "Fenstermacher", "isOnline": true, "image": "ai_images/000051.jpg"},
15
+ {"id": 9, "firstname": "Ines", "lastname": "Meister", "isOnline": false, "image": "ai_images/000052.jpg"},
16
+ {"id": 10, "firstname": "Antje", "lastname": "Peters", "isOnline": false, "image": "ai_images/000053.jpg"},
17
+ {"id": 11, "firstname": "Stephan", "lastname": "Fleischer", "isOnline": false, "image": "ai_images/000054.jpg"},
18
+ {"id": 12, "firstname": "Annett", "lastname": "Fuerst", "isOnline": false, "image": "ai_images/000055.jpg"},
19
+ {"id": 13, "firstname": "Leon", "lastname": "Ritter", "isOnline": false, "image": "ai_images/000056.jpg"},
20
+ {"id": 14, "firstname": "Andrea", "lastname": "Biermann", "isOnline": false, "image": "ai_images/000057.jpg"},
21
+ {"id": 15, "firstname": "Wolfgang", "lastname": "Abend", "isOnline": false, "image": "ai_images/000058.jpg"},
22
+ {"id": 16, "firstname": "Ulrich", "lastname": "Zimmer", "isOnline": false, "image": "ai_images/000059.jpg"},
23
+ {"id": 17, "firstname": "Nicole", "lastname": "Herzog", "isOnline": false, "image": "ai_images/000060.jpg"},
24
+ {"id": 18, "firstname": "Felix", "lastname": "König", "isOnline": false, "image": "ai_images/000061.jpg"},
25
+ {"id": 19, "firstname": "Thorsten", "lastname": "Werfel", "isOnline": false, "image": "ai_images/000063.jpg"},
26
+ {"id": 20, "firstname": "Patrick", "lastname": "Wolf", "isOnline": false, "image": "ai_images/000064.jpg"}
27
+ ]
28
+ }
@@ -0,0 +1,25 @@
1
+ .neo-circle-list.neo-list {
2
+ background-color: v(list-item-background-color);
3
+
4
+ .neo-circle-component {
5
+ background-color: transparent;
6
+ border : none;
7
+
8
+ .neo-circle-center {
9
+ top: 50%;
10
+
11
+ .neo-circle-back {
12
+ background-color: rgba(62, 123, 134, 0.302);
13
+ }
14
+ }
15
+ }
16
+
17
+ .neo-list-item {
18
+ background-color: transparent;
19
+ padding : 0;
20
+
21
+ &.neo-selected {
22
+ background-color: v(list-item-background-color-hover);
23
+ }
24
+ }
25
+ }
@@ -47,7 +47,7 @@ class List extends ComponentList {
47
47
  */
48
48
  createItemContent(record, index) {
49
49
  let me = this,
50
- id = record[me.store.keyProperty],
50
+ id = record[me.getKeyProperty()],
51
51
  items = me.items || [],
52
52
  checkBox = items[index],
53
53
 
@@ -112,7 +112,7 @@ class List extends ComponentList {
112
112
 
113
113
  Object.assign(style, {
114
114
  left: `${listItemRect.right + 13}px`,
115
- top : `${listItemRect.top - 10}px`,
115
+ top : `${listItemRect.top - 10}px`
116
116
  });
117
117
 
118
118
  editCalendarContainer[mounted ? 'set' : 'setSilent']({
@@ -45,7 +45,7 @@ class Circle extends Component {
45
45
  */
46
46
  keys: {},
47
47
  /**
48
- * @member {Number} innerRadius_=60
48
+ * @member {Number} innerRadius_=100
49
49
  */
50
50
  innerRadius_: 100,
51
51
  /**
@@ -58,7 +58,7 @@ class Circle extends Component {
58
58
  */
59
59
  itemImagePath: null,
60
60
  /**
61
- * @member {Number} itemSize_=30
61
+ * @member {Number} itemSize_=60
62
62
  */
63
63
  itemSize_: 60,
64
64
  /**
@@ -96,9 +96,9 @@ class Circle extends Component {
96
96
  title_: 'Circle 1',
97
97
  /**
98
98
  * The url for the store to load the data
99
- * @member {String} url_='../resources/examples/data/ai_contacts.json'
99
+ * @member {String} url_='../resources/examples/data/circles/group1.json'
100
100
  */
101
- url_: '../../resources/examples/data/circleContacts.json',
101
+ url_: '../../resources/examples/data/circles/group1.json',
102
102
  /**
103
103
  * @member {Object} _vdom
104
104
  */
@@ -408,6 +408,7 @@ class Circle extends Component {
408
408
  let me = this,
409
409
  frontEl = me.getFrontEl(),
410
410
  itemPositions = me.calculateItemPositions(),
411
+ itemSize = me.itemSize,
411
412
  countItems = Math.min(me.store.getCount(), me.maxItems),
412
413
  i = startIndex,
413
414
  vdom = me.vdom;
@@ -418,18 +419,18 @@ class Circle extends Component {
418
419
  cls : ['neo-circle-item'],
419
420
  tabIndex: -1,
420
421
  style: {
421
- height: me.itemSize + 'px',
422
+ height: itemSize + 'px',
422
423
  left : itemPositions[i].left + 'px',
423
424
  top : itemPositions[i].top + 'px',
424
- width : me.itemSize + 'px'
425
+ width : itemSize + 'px'
425
426
  },
426
427
  cn: [{
427
428
  tag : 'img',
428
429
  cls : ['neo-circle-item-image'],
429
430
  src : me.itemImagePath + me.store.getAt(i).image,
430
431
  style: {
431
- height: me.itemSize + 'px',
432
- width : me.itemSize + 'px'
432
+ height: itemSize + 'px',
433
+ width : itemSize + 'px'
433
434
  }
434
435
  }]
435
436
  });
@@ -439,7 +440,7 @@ class Circle extends Component {
439
440
  }
440
441
 
441
442
  /**
442
- *
443
+ * @param {Object} data
443
444
  */
444
445
  expand(data) {
445
446
  let me = this;
@@ -452,7 +453,7 @@ class Circle extends Component {
452
453
  }
453
454
 
454
455
  /**
455
- * @param data
456
+ * @param {Object} data
456
457
  */
457
458
  expandItem(data) {
458
459
  let me = this,
@@ -586,10 +587,7 @@ class Circle extends Component {
586
587
 
587
588
  let me = this;
588
589
 
589
- if (me.selectionModel) {
590
- me.selectionModel.register(me);
591
- }
592
-
590
+ me.selectionModel?.register(me);
593
591
  me.loadData();
594
592
  }
595
593
 
@@ -318,10 +318,7 @@ class Gallery extends Component {
318
318
  afterSetSelectionModel(value, oldValue) {
319
319
  if (this.rendered) {
320
320
  value.register(this);
321
-
322
- if (oldValue) {
323
- oldValue.destroy();
324
- }
321
+ oldValue?.destroy();
325
322
  }
326
323
  }
327
324
 
package/src/core/Base.mjs CHANGED
@@ -29,7 +29,7 @@ class Base {
29
29
 
30
30
  /**
31
31
  * The return value will get applied to each class instance
32
- * @returns {Object} staticConfig
32
+ * @returns {Object} config
33
33
  * @tutorial 02_ClassSystem
34
34
  */
35
35
  static getConfig() {return {
@@ -212,11 +212,11 @@ class Store extends Base {
212
212
 
213
213
  Neo.Xhr.promiseJson({
214
214
  url: me.url
215
+ }).catch(err => {
216
+ console.log('Error for Neo.Xhr.request', err, me.id);
215
217
  }).then(data => {
216
218
  me.data = Array.isArray(data.json) ? data.json : data.json.data;
217
219
  // we do not need to fire a load event => onCollectionMutate()
218
- }).catch(err => {
219
- console.log('Error for Neo.Xhr.request', err, me.id);
220
220
  });
221
221
  }
222
222
 
package/src/list/Base.mjs CHANGED
@@ -61,11 +61,21 @@ class Base extends Component {
61
61
  * @member {String} itemCls='neo-list-item'
62
62
  */
63
63
  itemCls: 'neo-list-item',
64
+ /**
65
+ * Defaults to px
66
+ * @member {Number|null} itemHeight_=null
67
+ */
68
+ itemHeight_: null,
64
69
  /**
65
70
  * The type of the node / tag for each list item
66
71
  * @member {String} itemTagName='li'
67
72
  */
68
73
  itemTagName: 'li',
74
+ /**
75
+ * Defaults to px
76
+ * @member {Number|null} itemWidth_=null
77
+ */
78
+ itemWidth_: null,
69
79
  /**
70
80
  * Additional used keys for the selection model
71
81
  * @member {Object} keys
@@ -194,6 +204,7 @@ class Base extends Component {
194
204
  filter : 'onStoreFilter',
195
205
  load : 'onStoreLoad',
196
206
  recordChange: 'onStoreRecordChange',
207
+ sort : 'onStoreSort',
197
208
  scope : me
198
209
  });
199
210
 
@@ -247,6 +258,8 @@ class Base extends Component {
247
258
  createItem(record, index) {
248
259
  let me = this,
249
260
  cls = [me.itemCls],
261
+ hasItemHeight = me.itemHeight !== null,
262
+ hasItemWidth = me.itemWidth !== null,
250
263
  itemContent = me.createItemContent(record, index),
251
264
  itemId = me.getItemId(record[me.getKeyProperty()]),
252
265
  selectionModel = me.selectionModel,
@@ -261,7 +274,7 @@ class Base extends Component {
261
274
  item = {
262
275
  tag : me.itemTagName,
263
276
  cls : cls,
264
- id : me.getItemId(record[me.getKeyProperty(itemId)]),
277
+ id : itemId,
265
278
  tabIndex: -1
266
279
  };
267
280
 
@@ -285,6 +298,18 @@ class Base extends Component {
285
298
  }
286
299
  }
287
300
 
301
+ if (hasItemHeight || hasItemWidth) {
302
+ item.style = item.style || {};
303
+
304
+ if (hasItemHeight && !item.hasOwnProperty('height')) {
305
+ item.style.height = `${me.itemHeight}px`;
306
+ }
307
+
308
+ if (hasItemWidth && !item.hasOwnProperty('width')) {
309
+ item.style.width = `${me.itemWidth}px`;
310
+ }
311
+ }
312
+
288
313
  return item;
289
314
  }
290
315
 
@@ -320,19 +345,21 @@ class Base extends Component {
320
345
  vdom = me.vdom,
321
346
  listItem;
322
347
 
323
- vdom.cn = [];
324
-
325
- me.store.items.forEach((item, index) => {
326
- listItem = me.createItem(item, index);
327
- listItem && vdom.cn.push(listItem);
328
- });
348
+ if (!(me.animate && !me.getPlugin('animate'))) {
349
+ vdom.cn = [];
329
350
 
330
- if (silent) {
331
- me._vdom = vdom;
332
- } else {
333
- me.promiseVdomUpdate().then(() => {
334
- me.fire('createItems');
351
+ me.store.items.forEach((item, index) => {
352
+ listItem = me.createItem(item, index);
353
+ listItem && vdom.cn.push(listItem);
335
354
  });
355
+
356
+ if (silent) {
357
+ me._vdom = vdom;
358
+ } else {
359
+ me.promiseVdomUpdate().then(() => {
360
+ me.fire('createItems');
361
+ });
362
+ }
336
363
  }
337
364
  }
338
365
 
@@ -499,6 +526,16 @@ class Base extends Component {
499
526
  }
500
527
  }
501
528
 
529
+ /**
530
+ * @param {Object} data
531
+ * @param {Object[]} data.items
532
+ * @param {Object[]} data.previousItems
533
+ * @param {Neo.data.Store} data.scope
534
+ */
535
+ onStoreSort(data) {
536
+ this.createItems();
537
+ }
538
+
502
539
  /**
503
540
  * Convenience shortcut
504
541
  * @param {Number} index
package/src/list/Chip.mjs CHANGED
@@ -13,10 +13,10 @@ class Chip extends ComponentList {
13
13
  */
14
14
  className: 'Neo.list.Chip',
15
15
  /**
16
- * @member {String} ntype='chiplist'
16
+ * @member {String} ntype='chip-list'
17
17
  * @protected
18
18
  */
19
- ntype: 'chiplist',
19
+ ntype: 'chip-list',
20
20
  /**
21
21
  * @member {String[]} cls=['neo-chip-list','neo-list']
22
22
  */
@@ -70,7 +70,6 @@ class Chip extends ComponentList {
70
70
  */
71
71
  createItemContent(record, index) {
72
72
  let me = this,
73
- id = record[me.store.keyProperty],
74
73
  items = me.items || [],
75
74
  listItem = items[index],
76
75
 
@@ -0,0 +1,87 @@
1
+ import CircleComponent from '../component/Circle.mjs';
2
+ import Component from './Component.mjs';
3
+
4
+ /**
5
+ * @class Neo.list.Circle
6
+ * @extends Neo.list.Component
7
+ */
8
+ class Circle extends Component {
9
+ static getConfig() {return {
10
+ /**
11
+ * @member {String} className='Neo.list.Circle'
12
+ * @protected
13
+ */
14
+ className: 'Neo.list.Circle',
15
+ /**
16
+ * @member {String} ntype='circle-list'
17
+ * @protected
18
+ */
19
+ ntype: 'circle-list',
20
+ /**
21
+ * @member {String[]} cls=['neo-circle-list','neo-list']
22
+ */
23
+ cls: ['neo-circle-list', 'neo-list'],
24
+ /**
25
+ * @member {Object} itemDefaults
26
+ */
27
+ itemDefaults: {
28
+ module : CircleComponent
29
+ },
30
+ /**
31
+ * Defaults to px
32
+ * @member {Number|null} itemHeight=300
33
+ */
34
+ itemHeight: 300,
35
+ /**
36
+ * Defaults to px
37
+ * @member {Number|null} itemWidth=300
38
+ */
39
+ itemWidth: 300,
40
+ /**
41
+ * @member {String} urlField='url'
42
+ */
43
+ urlField: 'url'
44
+ }}
45
+
46
+ /**
47
+ * Override this method for custom renderers
48
+ * @param {Object} record
49
+ * @param {Number} index
50
+ * @returns {Object|Object[]|String} Either a config object to assign to the item, a vdom cn array or a html string
51
+ */
52
+ createItemContent(record, index) {
53
+ let me = this,
54
+ items = me.items || [],
55
+ listItem = items[index],
56
+
57
+ config = {
58
+ id : me.getComponentId(index),
59
+ title: record[me.displayField],
60
+ url : record[me.urlField]
61
+ };
62
+
63
+ if (listItem) {
64
+ listItem.setSilent(config);
65
+ } else {
66
+ items[index] = listItem = Neo.create({
67
+ appName : me.appName,
68
+ height : me.itemHeight,
69
+ innerRadius: me.itemHeight / 2 - 64,
70
+ itemSize : 40,
71
+ parentId : me.id,
72
+ tabIndex : -1,
73
+ width : me.itemWidth,
74
+ ...me.itemDefaults,
75
+ ...config
76
+ });
77
+ }
78
+
79
+ me.items = items;
80
+
81
+ return [listItem.vdom];
82
+ }
83
+ }
84
+
85
+ Neo.applyClassConfig(Circle);
86
+
87
+ export default Circle;
@@ -30,11 +30,9 @@ class Component extends Base {
30
30
  * @protected
31
31
  */
32
32
  afterSetAppName(value, oldValue) {
33
- let me = this;
34
-
35
33
  super.afterSetAppName(value, oldValue);
36
34
 
37
- value && me.items?.forEach(item => {
35
+ value && this.items?.forEach(item => {
38
36
  item.appName = value;
39
37
  });
40
38
  }
@@ -73,10 +71,43 @@ class Component extends Base {
73
71
  * @returns {String|Number} itemId
74
72
  */
75
73
  getItemRecordId(vnodeId) {
76
- let itemId = vnodeId.split('__')[1],
77
- store = this.store;
74
+ let itemId = vnodeId.split('__')[1];
75
+ return this.store.getAt(parseInt(itemId))[this.getKeyProperty()];
76
+ }
77
+
78
+ /**
79
+ * @param {Object} data
80
+ * @param {Object[]} data.items
81
+ * @param {Object[]} data.previousItems
82
+ * @param {Neo.data.Store} data.scope
83
+ */
84
+ onStoreSort(data) {
85
+ this.sortItems(data);
86
+ super.onStoreSort(data);
87
+ }
88
+
89
+ /**
90
+ * @param {Object} data
91
+ * @param {Object[]} data.items
92
+ * @param {Object[]} data.previousItems
93
+ * @param {Neo.data.Store} data.scope
94
+ */
95
+ sortItems(data) {
96
+ let me = this,
97
+ newItems = [],
98
+ fromIndex, key, previousKeys;
99
+
100
+ if (me.items) {
101
+ key = me.getKeyProperty();
102
+ previousKeys = data.previousItems.map(e => e[key]);
103
+
104
+ data.items.forEach(item => {
105
+ fromIndex = previousKeys.indexOf(item[key]);
106
+ newItems.push(me.items[fromIndex]);
107
+ });
78
108
 
79
- return store.getAt(parseInt(itemId))[store.model.keyProperty];
109
+ me.items = newItems;
110
+ }
80
111
  }
81
112
  }
82
113
 
@@ -27,21 +27,11 @@ class Animate extends Base {
27
27
  * @member {Number|null} columns=null
28
28
  */
29
29
  columns: null,
30
- /**
31
- * Value in px
32
- * @member {Number} itemHeight=200
33
- */
34
- itemHeight: 200,
35
30
  /**
36
31
  * Value in px
37
32
  * @member {Number} itemMargin=10
38
33
  */
39
34
  itemMargin: 10,
40
- /**
41
- * Value in px
42
- * @member {Number} itemWidth=300
43
- */
44
- itemWidth: 300,
45
35
  /**
46
36
  * @member {DOMRect|null} ownerRect=null
47
37
  */
@@ -78,14 +68,14 @@ class Animate extends Base {
78
68
  let me = this,
79
69
  owner = me.owner;
80
70
 
71
+ if (!owner.itemHeight || !owner.itemWidth) {
72
+ console.error('list.plugin.Animate requires fixed itemHeight and itemWidth values', owner);
73
+ }
74
+
81
75
  me.adjustCreateItem();
82
76
 
83
77
  owner.onStoreFilter = me.onStoreFilter.bind(me);
84
-
85
- owner.store.on({
86
- sort : me.onStoreSort,
87
- scope: me
88
- });
78
+ owner.onStoreSort = me.onStoreSort .bind(me);
89
79
 
90
80
  this.updateTransitionDetails(false);
91
81
  }
@@ -139,6 +129,7 @@ class Animate extends Base {
139
129
  */
140
130
  createItem(me, record, index) {
141
131
  let item = me.ownerCreateItem(record, index),
132
+ owner = me.owner,
142
133
  position = me.getItemPosition(record, index),
143
134
  style = item.style || {};
144
135
 
@@ -147,10 +138,10 @@ class Animate extends Base {
147
138
  }
148
139
 
149
140
  Object.assign(style, {
150
- height : `${me.itemHeight}px`,
141
+ height : `${owner.itemHeight}px`,
151
142
  position : 'absolute',
152
143
  transform: `translate(${position.x}px, ${position.y}px)`,
153
- width : `${me.itemWidth}px`
144
+ width : `${owner.itemWidth}px`
154
145
  });
155
146
 
156
147
  item.style = style;
@@ -167,9 +158,10 @@ class Animate extends Base {
167
158
  let me = this,
168
159
  column = index % me.columns,
169
160
  margin = me.itemMargin,
161
+ owner = me.owner,
170
162
  row = Math.floor(index / me.columns),
171
- x = column * (margin + me.itemWidth) + margin,
172
- y = row * (margin + me.itemHeight) + margin;
163
+ x = column * (margin + owner.itemWidth) + margin,
164
+ y = row * (margin + owner.itemHeight) + margin;
173
165
 
174
166
  return {x, y};
175
167
  }
@@ -186,7 +178,7 @@ class Animate extends Base {
186
178
  }
187
179
 
188
180
  let owner = this.owner,
189
- key = owner.store.keyProperty;
181
+ key = owner.getKeyProperty();
190
182
 
191
183
  return map.indexOf(owner.getItemId(obj.record[key]));
192
184
  }
@@ -195,14 +187,18 @@ class Animate extends Base {
195
187
  *
196
188
  */
197
189
  onOwnerMounted() {
198
- let me = this;
190
+ let me = this,
191
+ owner = me.owner;
199
192
 
200
- me.owner.getDomRect().then(rect => {
193
+ owner.getDomRect().then(rect => {
201
194
  Object.assign(me, {
202
- columns : Math.floor(rect.width / me.itemWidth),
195
+ columns : Math.floor(rect.width / owner.itemWidth),
203
196
  ownerRect: rect,
204
- rows : Math.floor(rect.height / me.itemHeight)
197
+ rows : Math.floor(rect.height / owner.itemHeight)
205
198
  });
199
+
200
+ // if the store got loaded before this plugin is ready, create the items now
201
+ owner.store.getCount() > 0 && owner.createItems();
206
202
  });
207
203
  }
208
204
 
@@ -216,7 +212,7 @@ class Animate extends Base {
216
212
  onStoreFilter(data) {
217
213
  let me = this,
218
214
  owner = me.owner,
219
- key = owner.store.keyProperty,
215
+ key = owner.getKeyProperty(),
220
216
  hasAddedItems = false,
221
217
  addedItems = [],
222
218
  movedItems = [],
@@ -326,19 +322,34 @@ class Animate extends Base {
326
322
  * @param {Neo.data.Store} data.scope
327
323
  */
328
324
  onStoreSort(data) {
329
- let me = this,
330
- hasChange = false,
331
- keyProperty = data.scope.keyProperty,
332
- owner = me.owner,
333
- newVdomCn = [],
334
- vdom = owner.vdom,
335
- vdomMap = vdom.cn.map(e => e.id),
336
- fromIndex, itemId;
337
-
338
- if (vdomMap.length > 0) {
325
+ let me = this;
326
+
327
+ if (Neo.list.Component && me.owner instanceof Neo.list.Component) {
328
+ me.sortComponentList(data);
329
+ } else {
330
+ me.sortBaseList(data);
331
+ }
332
+ }
333
+
334
+ /**
335
+ * @param {Object} data
336
+ * @param {Object[]} data.items
337
+ * @param {Object[]} data.previousItems
338
+ * @param {Neo.data.Store} data.scope
339
+ */
340
+ sortBaseList(data) {
341
+ let me = this,
342
+ hasChange = false,
343
+ owner = me.owner,
344
+ key = owner.getKeyProperty(),
345
+ newVdomCn = [],
346
+ previousKeys = data.previousItems.map(e => e[key]),
347
+ vdom = owner.vdom,
348
+ fromIndex;
349
+
350
+ if (vdom.cn.length > 0) {
339
351
  data.items.forEach((item, index) => {
340
- itemId = owner.getItemId(item[keyProperty]);
341
- fromIndex = vdomMap.indexOf(itemId);
352
+ fromIndex = previousKeys.indexOf(item[key]);
342
353
 
343
354
  newVdomCn.push(vdom.cn[fromIndex]);
344
355
 
@@ -360,6 +371,37 @@ class Animate extends Base {
360
371
  }
361
372
  }
362
373
 
374
+ /**
375
+ * @param {Object} data
376
+ * @param {Object[]} data.items
377
+ * @param {Object[]} data.previousItems
378
+ * @param {Neo.data.Store} data.scope
379
+ */
380
+ sortComponentList(data) {
381
+ let me = this,
382
+ owner = me.owner,
383
+ key = owner.getKeyProperty(),
384
+ previousKeys = data.previousItems.map(e => e[key]),
385
+ vdom = owner.vdom,
386
+ fromIndex, item, position;
387
+
388
+ owner.sortItems(data);
389
+
390
+ previousKeys = owner.items.map(e => owner.getItemRecordId(e[key]));
391
+
392
+ if (vdom.cn.length > 0) {
393
+ data.items.forEach((record, index) => {
394
+ fromIndex = previousKeys.indexOf(record[key]);
395
+ item = vdom.cn[fromIndex];
396
+ position = me.getItemPosition(record, index);
397
+
398
+ item.style.transform = `translate(${position.x}px, ${position.y}px)`;
399
+ });
400
+
401
+ owner.vdom = vdom;
402
+ }
403
+ }
404
+
363
405
  /**
364
406
  *
365
407
  */