neo.mjs 5.11.1 → 5.12.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.
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.11.1'
23
+ * @member {String} version='5.12.1'
24
24
  */
25
- version: '5.11.1'
25
+ version: '5.12.1'
26
26
  }
27
27
 
28
28
  /**
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='5.11.1'
23
+ * @member {String} version='5.12.1'
24
24
  */
25
- version: '5.11.1'
25
+ version: '5.12.1'
26
26
  }
27
27
 
28
28
  /**
@@ -170,19 +170,33 @@ class MainContainer extends ConfigurationViewport {
170
170
  }];
171
171
  }
172
172
 
173
+ /**
174
+ * @returns {Neo.component.Base}
175
+ */
173
176
  createExampleComponent() {
174
177
  return Neo.create({
175
178
  module : Button,
176
179
  badgeText: 'Badge',
180
+ handler : data => console.log('button click =>', data.component.id),
177
181
  height : 50,
178
182
  iconCls : 'fa fa-home',
179
183
  text : 'Hello World',
180
184
  ui : 'primary',
181
185
  width : 150,
182
186
 
183
- handler: (data) => {
184
- console.log('button click =>', data.component.id);
185
- }
187
+ menu: [{
188
+ handler: data => console.log('menu item click =>', data.component.id),
189
+ iconCls: 'fa fa-home',
190
+ text : 'Item 1'
191
+ }, {
192
+ handler: data => console.log('menu item click =>', data.component.id),
193
+ iconCls: 'fa fa-user',
194
+ text : 'Item 2'
195
+ }, {
196
+ handler: data => console.log('menu item click =>', data.component.id),
197
+ iconCls: 'fa fa-play',
198
+ text : 'Item 3'
199
+ }]
186
200
 
187
201
  /*tooltips: [{
188
202
  text: 'Hello World Tooltip'
@@ -45,7 +45,7 @@ class MainContainer extends ConfigurationViewport {
45
45
  createExampleComponent() {
46
46
  return Neo.create({
47
47
  module : MenuList,
48
- displayField: 'name',
48
+ displayField: 'text',
49
49
  store : MainStore
50
50
  });
51
51
  }
@@ -17,48 +17,48 @@ class MainStore extends Store {
17
17
  data: [{
18
18
  iconCls: 'fa fa-user',
19
19
  id : 1,
20
- name : 'Item 1'
20
+ text : 'Item 1'
21
21
  }, {
22
22
  iconCls: 'fa fa-home',
23
23
  id : 2,
24
- name : 'Group 1',
24
+ text : 'Group 1',
25
25
  items : [{
26
26
  iconCls: 'fa fa-home',
27
27
  id : 6,
28
- name : 'Item 1'
28
+ text : 'Item 1'
29
29
  }, {
30
30
  iconCls: 'fa fa-home',
31
31
  id : 7,
32
- name : 'Item 2'
32
+ text : 'Item 2'
33
33
  }, {
34
34
  iconCls: 'fa fa-home',
35
35
  id : 8,
36
- name : 'Item 3'
36
+ text : 'Item 3'
37
37
  }]
38
38
  }, {
39
39
  iconCls: 'fa fa-cog',
40
40
  id : 3,
41
- name : 'Item 2'
41
+ text : 'Item 2'
42
42
  }, {
43
43
  iconCls: 'far fa-calendar',
44
44
  id : 4,
45
- name : 'Item 3'
45
+ text : 'Item 3'
46
46
  }, {
47
47
  iconCls: 'far fa-clock',
48
48
  id : 5,
49
- name : 'Group 2',
49
+ text : 'Group 2',
50
50
  items : [{
51
51
  iconCls: 'fa fa-clock',
52
52
  id : 9,
53
- name : 'Item 1'
53
+ text : 'Item 1'
54
54
  }, {
55
55
  iconCls: 'fa fa-clock',
56
56
  id : 10,
57
- name : 'Item 2'
57
+ text : 'Item 2'
58
58
  }, {
59
59
  iconCls: 'fa fa-clock',
60
60
  id : 11,
61
- name : 'Item 3'
61
+ text : 'Item 3'
62
62
  }]
63
63
  }]
64
64
  }
@@ -56,70 +56,70 @@ class MainContainer extends ConfigurationViewport {
56
56
  module: Menu,
57
57
 
58
58
  listConfig: {
59
- displayField: 'name'
59
+ displayField: 'text'
60
60
  },
61
61
 
62
62
  listItems: [{
63
63
  iconCls: 'fa fa-user',
64
64
  id : 1,
65
- name : 'Item 1'
65
+ text : 'Item 1'
66
66
  }, {
67
67
  iconCls: 'fa fa-home',
68
68
  id : 2,
69
- name : 'Group 1',
69
+ text : 'Group 1',
70
70
  items : [{
71
71
  iconCls: 'fa fa-home',
72
72
  id : 6,
73
- name : 'Item 1'
73
+ text : 'Item 1'
74
74
  }, {
75
75
  iconCls: 'fa fa-home',
76
76
  id : 7,
77
- name : 'Item 2'
77
+ text : 'Item 2'
78
78
  }, {
79
79
  iconCls: 'fa fa-home',
80
80
  id : 8,
81
- name : 'Item 3'
81
+ text : 'Item 3'
82
82
  }]
83
83
  }, {
84
84
  iconCls: 'fa fa-cog',
85
85
  id : 3,
86
- name : 'Item 2'
86
+ text : 'Item 2'
87
87
  }, {
88
88
  iconCls: 'far fa-calendar',
89
89
  id : 4,
90
- name : 'Item 3'
90
+ text : 'Item 3'
91
91
  }, {
92
92
  iconCls: 'far fa-clock',
93
93
  id : 5,
94
- name : 'Group 2',
94
+ text : 'Group 2',
95
95
  items : [{
96
96
  iconCls: 'fa fa-clock',
97
97
  id : 9,
98
- name : 'Item 1'
98
+ text : 'Item 1'
99
99
  }, {
100
100
  iconCls: 'fa fa-clock',
101
101
  id : 10,
102
- name : 'Item 2'
102
+ text : 'Item 2'
103
103
  }, {
104
104
  iconCls: 'fa fa-clock',
105
105
  id : 11,
106
- name : 'Group 1',
106
+ text : 'Group 1',
107
107
  items : [{
108
108
  iconCls: 'far fa-clock',
109
109
  id : 12,
110
- name : 'Item 1'
110
+ text : 'Item 1'
111
111
  }, {
112
112
  iconCls: 'far fa-clock',
113
113
  id : 13,
114
- name : 'Item 2'
114
+ text : 'Item 2'
115
115
  }, {
116
116
  iconCls: 'far fa-clock',
117
117
  id : 14,
118
- name : 'Item 3'
118
+ text : 'Item 3'
119
119
  }]
120
120
  }]
121
121
  }]
122
- });
122
+ })
123
123
  }
124
124
  }
125
125
 
@@ -1,3 +1,4 @@
1
+ import Button from '../../../src/button/Base.mjs';
1
2
  import CellColumnModel from '../../../src/selection/table/CellColumnModel.mjs';
2
3
  import CellColumnRowModel from '../../../src/selection/table/CellColumnRowModel.mjs';
3
4
  import CellModel from '../../../src/selection/table/CellModel.mjs';
@@ -78,15 +79,18 @@ class MainContainer extends ConfigurationViewport {
78
79
  valueLabelText: 'Cell & Column & Row'
79
80
  }, {
80
81
  module : Checkbox,
82
+ checked : me.exampleComponent.sortable,
81
83
  labelText: 'sortable',
82
84
  listeners: {change: me.onConfigChange.bind(me, 'sortable')},
83
- value : me.exampleComponent.sortable
85
+ style : {marginTop: '10px'}
84
86
  }];
85
87
  }
86
88
 
89
+ /**
90
+ * @returns {Neo.table.Container}
91
+ */
87
92
  createExampleComponent() {
88
93
  return Neo.create(TableContainer, {
89
- autoRender : false,
90
94
  id : 'myTableStoreContainer',
91
95
  selectionModel: CellModel,
92
96
  store : MainStore,
@@ -95,10 +99,31 @@ class MainContainer extends ConfigurationViewport {
95
99
  {dataField: 'firstname', text: 'Firstname'},
96
100
  {dataField: 'lastname', text: 'Lastname'},
97
101
  {dataField: 'githubId', text: 'Github Id'},
98
- {dataField: 'country', text: 'Country'}
102
+ {dataField: 'country', text: 'Country'},
103
+ {
104
+ text: 'Edit Action',
105
+ renderer: data => {
106
+ let button = Neo.create({
107
+ module : Button,
108
+ appName : this.appName,
109
+ handler : this.editButtonHandler,
110
+ parentId: 'myTableStoreContainer',
111
+ text : 'Edit'
112
+ });
113
+
114
+ return button.vdom
115
+ }
116
+ }
99
117
  ]
100
118
  });
101
119
  }
120
+
121
+ /**
122
+ * @param {Object} data
123
+ */
124
+ editButtonHandler(data) {
125
+ console.log(data)
126
+ }
102
127
  }
103
128
 
104
129
  Neo.applyClassConfig(MainContainer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "5.11.1",
3
+ "version": "5.12.1",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -55,9 +55,9 @@
55
55
  "inquirer": "^9.2.8",
56
56
  "neo-jsdoc": "^1.0.1",
57
57
  "neo-jsdoc-x": "^1.0.5",
58
- "postcss": "^8.4.26",
59
- "sass": "^1.63.6",
60
- "webpack": "^5.88.1",
58
+ "postcss": "^8.4.27",
59
+ "sass": "^1.64.1",
60
+ "webpack": "^5.88.2",
61
61
  "webpack-cli": "^5.1.4",
62
62
  "webpack-dev-server": "4.15.1",
63
63
  "webpack-hook-plugin": "^1.0.7",
@@ -236,12 +236,12 @@ const DefaultConfig = {
236
236
  useVdomWorker: true,
237
237
  /**
238
238
  * buildScripts/injectPackageVersion.mjs will update this value
239
- * @default '5.11.1'
239
+ * @default '5.12.1'
240
240
  * @memberOf! module:Neo
241
241
  * @name config.version
242
242
  * @type String
243
243
  */
244
- version: '5.11.1'
244
+ version: '5.12.1'
245
245
  };
246
246
 
247
247
  Object.assign(DefaultConfig, {
package/src/Main.mjs CHANGED
@@ -48,6 +48,7 @@ class Main extends core.Base {
48
48
  app: [
49
49
  'alert',
50
50
  'editRoute',
51
+ 'getByPath',
51
52
  'getWindowData',
52
53
  'redirectTo',
53
54
  'setNeoConfig',
@@ -150,6 +151,18 @@ class Main extends core.Base {
150
151
  window.location.hash = hashArr.join('&');
151
152
  }
152
153
 
154
+ /**
155
+ * Request specific accessible window attributes by path into the app worker.
156
+ * Keep in mind that this excludes anything DOM related or instances.
157
+ * Example: Neo.Main.getByPath({path: 'navigator.language'}).then(data => {})
158
+ * @param {Object} data
159
+ * @param {String} data.path
160
+ * @returns {*}
161
+ */
162
+ getByPath(data) {
163
+ return Neo.nsWithArrays(data.path)
164
+ }
165
+
153
166
  /**
154
167
  * window.screen is not spreadable
155
168
  * @returns {Object}
@@ -385,7 +398,7 @@ class Main extends core.Base {
385
398
  }
386
399
 
387
400
  /**
388
- * Change the location.hash value
401
+ * Change a Neo.config from the app worker
389
402
  * @param {Object} data
390
403
  * @param {String} data.key
391
404
  * @param {*} data.value
@@ -437,7 +450,7 @@ class Main extends core.Base {
437
450
  * @param {String} data.windowFeatures
438
451
  * @param {String} data.windowName
439
452
  * @return {Boolean}
440
- */
453
+ */
441
454
  windowOpen(data) {
442
455
  let openedWindow = window.open(data.url, data.windowName, data.windowFeatures),
443
456
  success = !!openedWindow;
@@ -78,6 +78,10 @@ class Base extends Component {
78
78
  * @member {String} iconPosition_='left'
79
79
  */
80
80
  iconPosition_: 'left',
81
+ /**
82
+ * @member {Object[]|null} menu_=null
83
+ */
84
+ menu_: null,
81
85
  /**
82
86
  * The pressed state of the Button
83
87
  * @member {Boolean} pressed_=false
@@ -182,6 +186,11 @@ class Base extends Component {
182
186
  click: value,
183
187
  scope: me.handlerScope || me
184
188
  });
189
+
190
+ me.menu && me.addDomListeners({
191
+ click: me.toggleMenu,
192
+ scope: me
193
+ })
185
194
  }
186
195
 
187
196
  /**
@@ -197,7 +206,7 @@ class Base extends Component {
197
206
  NeoArray.add( iconNode.cls, value);
198
207
 
199
208
  iconNode.removeDom = !value || value === '';
200
- this.update();
209
+ this.update()
201
210
  }
202
211
 
203
212
  /**
@@ -218,7 +227,7 @@ class Base extends Component {
218
227
  }
219
228
 
220
229
  iconNode.style.color = value;
221
- this.update();
230
+ this.update()
222
231
  }
223
232
 
224
233
  /**
@@ -236,6 +245,60 @@ class Base extends Component {
236
245
  this.cls = cls;
237
246
  }
238
247
 
248
+ /**
249
+ * Triggered after the menu config got changed
250
+ * @param {Object[]|null} value
251
+ * @param {Object[]|null} oldValue
252
+ * @protected
253
+ */
254
+ afterSetMenu(value, oldValue) {
255
+ if (value) {
256
+ import('../menu/List.mjs').then(module => {
257
+ let me = this;
258
+
259
+ me.menuList = Neo.create({
260
+ module : module.default,
261
+ appName : me.appName,
262
+ displayField: 'text',
263
+ floating : true,
264
+ hidden : true,
265
+ items : value,
266
+ parentId : me.id
267
+ });
268
+
269
+ me.vdom.cn.push(me.menuList.vdom)
270
+ })
271
+ }
272
+ }
273
+
274
+ /**
275
+ * Triggered after the mounted config got changed
276
+ * @param {Boolean} value
277
+ * @param {Boolean} oldValue
278
+ * @protected
279
+ */
280
+ afterSetMounted(value, oldValue) {
281
+ super.afterSetMounted(value, oldValue);
282
+
283
+ let me = this,
284
+ style;
285
+
286
+ if (value && me.menu) {
287
+ setTimeout(() => {
288
+ me.getDomRect().then(rect => {
289
+ style = me.menuList.style || {};
290
+
291
+ Object.assign(style, {
292
+ right: 0,
293
+ top : rect.height + 'px'
294
+ });
295
+
296
+ me.menuList.style = style
297
+ })
298
+ }, 50)
299
+ }
300
+ }
301
+
239
302
  /**
240
303
  * Triggered after the pressed config got changed
241
304
  * @param {Boolean} value
@@ -261,7 +324,7 @@ class Base extends Component {
261
324
  value && me.addDomListeners({
262
325
  click: me.changeRoute,
263
326
  scope: me
264
- });
327
+ })
265
328
  }
266
329
 
267
330
  /**
@@ -477,6 +540,23 @@ class Base extends Component {
477
540
  }
478
541
  }, rippleEffectDuration);
479
542
  }
543
+
544
+ /**
545
+ *
546
+ */
547
+ toggleMenu() {
548
+ let menuList = this.menuList,
549
+ hidden = !menuList.hidden;
550
+
551
+ menuList.hidden = hidden;
552
+
553
+ if (!hidden) {
554
+ setTimeout(() => {
555
+ console.log('focus'); // todo: does not activate the key nav
556
+ menuList.focus()
557
+ }, 500)
558
+ }
559
+ }
480
560
  }
481
561
 
482
562
  Neo.applyClassConfig(Base);
@@ -1106,14 +1106,11 @@ class Base extends CoreBase {
1106
1106
  * @param {String} id=this.id
1107
1107
  */
1108
1108
  focus(id=this.id) {
1109
- let me = this;
1110
-
1111
- // remote method access
1112
1109
  Neo.main.DomAccess.focus({
1113
- id: id || me.id
1110
+ id
1114
1111
  }).catch(err => {
1115
- console.log('Error attempting to receive focus for component', err, me);
1116
- });
1112
+ console.log('Error attempting to receive focus for component', err, this);
1113
+ })
1117
1114
  }
1118
1115
 
1119
1116
  /**
@@ -1191,7 +1188,7 @@ class Base extends CoreBase {
1191
1188
  getMountedParentId() {
1192
1189
  let parentId = this.parentId,
1193
1190
  parent = Neo.getComponent(parentId),
1194
- itemsRoot = parent?.getVdomItemsRoot();
1191
+ itemsRoot = parent?.getVdomItemsRoot?.();
1195
1192
 
1196
1193
  return itemsRoot ? itemsRoot.id : parentId
1197
1194
  }
@@ -17,31 +17,31 @@ class Video extends BaseComponent {
17
17
  */
18
18
  className: 'Neo.component.Video',
19
19
  /*
20
- * @member {String} ntype='neo-video'
20
+ * @member {String} ntype='video'
21
21
  * @protected
22
22
  */
23
23
  ntype: 'video',
24
24
  /*
25
- * @member {[String]} cls=['neo-video']
25
+ * @member {String[]} baseCls=['neo-video']
26
26
  */
27
27
  baseCls: ['neo-video'],
28
- /*
29
- * @member {String} url=null
30
- * @public
31
- */
32
- url_: null,
33
-
34
28
  /**
35
29
  * Current state of the video
36
- * @member {boolean} playing=false
30
+ * @member {Boolean} playing=false
37
31
  */
38
32
  playing_: false,
39
33
  /**
40
34
  * Type of the video
41
- * @member {boolean} type='video/mp4'
35
+ * @member {Boolean} type='video/mp4'
42
36
  */
43
37
  type: 'video/mp4',
44
-
38
+ /*
39
+ * @member {String} url=null
40
+ */
41
+ url_: null,
42
+ /**
43
+ * @member {Object} _vdom
44
+ */
45
45
  _vdom: {
46
46
  cn: [{
47
47
  flag: 'ghost',
@@ -64,17 +64,12 @@ class Video extends BaseComponent {
64
64
  }
65
65
  }
66
66
 
67
-
68
67
  /**
69
- * construct is earlier in component life cicle than init
70
- *
71
- * @param config
68
+ * @param {Object} config
72
69
  */
73
70
  construct(config) {
74
71
  super.construct(config);
75
72
 
76
- console.log(this);
77
-
78
73
  let me = this,
79
74
  domListeners = me.domListeners;
80
75
 
@@ -162,4 +157,4 @@ class Video extends BaseComponent {
162
157
 
163
158
  Neo.applyClassConfig(Video);
164
159
 
165
- export default Video;
160
+ export default Video;
@@ -86,12 +86,12 @@ class Fetch extends Base {
86
86
 
87
87
  /**
88
88
  * @param {Object|String} url
89
- * @param {Object} config
89
+ * @param {Object} config={}
90
90
  * @param {String} method
91
91
  * @param {Object} [data]
92
92
  * @returns {Promise<any>}
93
93
  */
94
- request(url, config, method, data) {
94
+ request(url, config={}, method, data) {
95
95
  if (!Neo.isString(url)) {
96
96
  config = url;
97
97
  url = config.url;
@@ -320,14 +320,7 @@ class Picker extends Text {
320
320
  * @param {Object} data
321
321
  */
322
322
  onInputClick(data) {
323
- let me = this;
324
-
325
- if (!me.editable) {
326
- me.togglePicker();
327
-
328
- // stay in sync to the trigger-click logic
329
- !me.pickerIsMounted && me.focus()
330
- }
323
+ !this.editable && this.togglePicker()
331
324
  }
332
325
 
333
326
  /**
@@ -981,10 +981,10 @@ class Text extends Base {
981
981
 
982
982
  /**
983
983
  * Calls focus() on the inputEl node instead
984
- * @param {String} id=this.id
984
+ * @param {String} id
985
985
  * @override
986
986
  */
987
- focus(id=this.id) {
987
+ focus(id) {
988
988
  super.focus(this.getInputElId())
989
989
  }
990
990
 
@@ -1442,21 +1442,19 @@ class Text extends Base {
1442
1442
  }
1443
1443
  }
1444
1444
 
1445
- if (required && isEmpty) {
1446
- me._error = me.errorTextRequired;
1447
- returnValue = false;
1448
- } else if (Neo.isNumber(maxLength) && valueLength > maxLength) {
1449
- if (required || !isEmpty) {
1450
- me._error = me.errorTextMaxLength(errorParam);
1445
+ if (isEmpty) {
1446
+ if (required) {
1447
+ me._error = me.errorTextRequired;
1451
1448
  returnValue = false;
1452
1449
  }
1453
- } else if (Neo.isNumber(minLength) && valueLength < minLength) {
1454
- if (required || !isEmpty) {
1450
+ } else {
1451
+ if (Neo.isNumber(maxLength) && valueLength > maxLength) {
1452
+ me._error = me.errorTextMaxLength(errorParam);
1453
+ returnValue = false;
1454
+ } else if (Neo.isNumber(minLength) && valueLength < minLength) {
1455
1455
  me._error = me.errorTextMinLength(errorParam);
1456
1456
  returnValue = false;
1457
- }
1458
- } else if (inputPattern && !inputPattern.test(value)) {
1459
- if (required || !isEmpty) {
1457
+ } else if (inputPattern && !inputPattern.test(value)) {
1460
1458
  me._error = me.errorTextInputPattern(errorParam);
1461
1459
  returnValue = false;
1462
1460
  }
@@ -127,12 +127,12 @@ class DeltaUpdates extends Base {
127
127
  startTag = `<!-- ${delta.id} -->`;
128
128
  reg = new RegExp(startTag + '[\\s\\S]*?<!-- \/neo-vtext -->');
129
129
 
130
- node.innerHTML = node.innerHTML.replace(reg, '');
130
+ node.innerHTML = node.innerHTML.replace(reg, '')
131
131
  } else {
132
132
  // console.warn('du_removeNode: dom node not found for id', delta.id);
133
133
  }
134
134
  } else {
135
- node.parentNode.removeChild(node);
135
+ node.remove()
136
136
  }
137
137
  }
138
138
 
@@ -105,7 +105,9 @@ class DomEvent extends Base {
105
105
  }
106
106
 
107
107
  if (!preventFire) {
108
- // console.log(Neo.get(id));
108
+ // multiple listeners would change the reference of data.component
109
+ data = Neo.clone(data, true, true);
110
+
109
111
  data.component = component;
110
112
  listener.fn.apply(listener.scope || globalThis, [data]);
111
113
 
package/src/menu/List.mjs CHANGED
@@ -96,7 +96,12 @@ class List extends BaseList {
96
96
  * We are applying a z-index style which is 1 number higher to each sub-menu
97
97
  * @member {Number} zIndex_=100
98
98
  */
99
- zIndex_: 100
99
+ zIndex_: 100,
100
+ /**
101
+ * @member {Object} _vdom
102
+ */
103
+ _vdom:
104
+ {tag: 'ul', tabIndex: -1, cn: []}
100
105
  }
101
106
 
102
107
  /**
@@ -138,6 +143,7 @@ class List extends BaseList {
138
143
  if (me.isRoot) {
139
144
  if (!value) {
140
145
  me.focusTimeoutId = setTimeout(() => {
146
+ console.log('unmount'); // todo: does not hide a top-level floating menu
141
147
  me[me.floating ? 'unmount' : 'hideSubMenu']();
142
148
  }, 20);
143
149
  } else {
@@ -305,26 +311,27 @@ class List extends BaseList {
305
311
 
306
312
  Object.assign(menuStyle, style);
307
313
 
308
- subMenu.setSilent({style: menuStyle});
314
+ subMenu.setSilent({style: menuStyle})
309
315
  } else {
310
316
  subMenuMap[subMenuMapId] = subMenu = Neo.create({
311
- module : List,
312
- appName : me.appName,
313
- floating : true,
314
- items : record.items,
315
- isRoot : false,
316
- parentId : Neo.apps[me.appName].mainView.id,
317
- parentIndex: store.indexOf(record),
318
- parentMenu : me,
317
+ module : List,
318
+ appName : me.appName,
319
+ displayField: me.displayField,
320
+ floating : true,
321
+ items : record.items,
322
+ isRoot : false,
323
+ parentId : Neo.apps[me.appName].mainView.id,
324
+ parentIndex : store.indexOf(record),
325
+ parentMenu : me,
319
326
  style,
320
- zIndex : me.zIndex + 1
321
- });
327
+ zIndex : me.zIndex + 1
328
+ })
322
329
  }
323
330
 
324
331
  me.activeSubMenu = subMenu;
325
332
  me.subMenuMap = subMenuMap;
326
333
 
327
- subMenu.render(true);
334
+ subMenu.render(true)
328
335
  });
329
336
  }
330
337
 
@@ -335,7 +342,7 @@ class List extends BaseList {
335
342
  this.selectionModel.deselectAll(true); // silent update
336
343
  this.hideSubMenu();
337
344
 
338
- super.unmount();
345
+ super.unmount()
339
346
  }
340
347
  }
341
348
 
@@ -28,7 +28,7 @@ class Model extends BaseModel {
28
28
  name: 'items', // optional
29
29
  type: 'Array'
30
30
  }, {
31
- name: 'name',
31
+ name: 'text',
32
32
  type: 'String'
33
33
  }]
34
34
  }
@@ -59,12 +59,10 @@ class View extends Component {
59
59
  i = 0,
60
60
  vdom = me.vdom,
61
61
  cellCls, cellId, config, column, dockLeftMargin, dockRightMargin, id, index, j, rendererOutput,
62
- record, rendererValue, selectedRows, trCls;
62
+ record, rendererType, rendererValue, selectedRows, trCls;
63
63
 
64
64
  me.recordVnodeMap = {}; // remove old data
65
65
 
66
- // console.log('createViewData', me.id, inputData);
67
-
68
66
  if (container.selectionModel.ntype === 'selection-table-rowmodel') {
69
67
  selectedRows = container.selectionModel.items || [];
70
68
  }
@@ -113,17 +111,29 @@ class View extends Component {
113
111
  value : rendererValue
114
112
  });
115
113
 
116
- cellCls = rendererOutput?.cls || ['neo-table-cell'];
117
-
118
- if (column.align !== 'left') {
119
- cellCls.push('neo-' + column.align);
114
+ cellCls = ['neo-table-cell'];
115
+ rendererType = Neo.typeOf(rendererOutput);
116
+
117
+ switch (rendererType) {
118
+ case 'Object': {
119
+ if (rendererOutput.cls && rendererOutput.html) {
120
+ cellCls.push(...rendererOutput.cls);
121
+ } else {
122
+ rendererOutput = [rendererOutput];
123
+ }
124
+ break;
125
+ }
126
+ case 'String': {
127
+ rendererOutput = {
128
+ cls : cellCls,
129
+ html: rendererOutput?.toString()
130
+ };
131
+ break;
132
+ }
120
133
  }
121
134
 
122
- if (!Neo.isObject(rendererOutput)) {
123
- rendererOutput = {
124
- cls : cellCls,
125
- html: rendererOutput?.toString()
126
- };
135
+ if (column.align !== 'left') {
136
+ cellCls.push('neo-' + column.align)
127
137
  }
128
138
 
129
139
  // todo: remove the else part as soon as all tables use stores (examples table)
@@ -134,14 +144,19 @@ class View extends Component {
134
144
  }
135
145
 
136
146
  config = {
137
- tag : 'td',
138
- id : cellId,
139
- cls : cellCls,
140
- innerHTML: rendererOutput.html || '',
141
- style : rendererOutput.style || {},
142
- tabIndex : '-1'
147
+ tag : 'td',
148
+ id : cellId,
149
+ cls : cellCls,
150
+ style : rendererOutput.style || {},
151
+ tabIndex: '-1'
143
152
  };
144
153
 
154
+ if (rendererType === 'String') {
155
+ config.innerHTML = rendererOutput.html || ''
156
+ } else {
157
+ config.cn = rendererOutput
158
+ }
159
+
145
160
  if (column.dock) {
146
161
  config.cls = ['neo-locked', ...config.cls || []];
147
162