neo.mjs 8.28.1 → 8.29.0

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='8.28.1'
23
+ * @member {String} version='8.29.0'
24
24
  */
25
- version: '8.28.1'
25
+ version: '8.29.0'
26
26
  }
27
27
 
28
28
  /**
@@ -16,7 +16,7 @@
16
16
  "@type": "Organization",
17
17
  "name": "Neo.mjs"
18
18
  },
19
- "datePublished": "2025-03-02",
19
+ "datePublished": "2025-03-03",
20
20
  "publisher": {
21
21
  "@type": "Organization",
22
22
  "name": "Neo.mjs"
@@ -107,7 +107,7 @@ class FooterContainer extends Container {
107
107
  }, {
108
108
  module: Component,
109
109
  cls : ['neo-version'],
110
- html : 'v8.28.1'
110
+ html : 'v8.29.0'
111
111
  }]
112
112
  }],
113
113
  /**
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.28.1'
23
+ * @member {String} version='8.29.0'
24
24
  */
25
- version: '8.28.1'
25
+ version: '8.29.0'
26
26
  }
27
27
 
28
28
  /**
@@ -1,4 +1,5 @@
1
1
  import BaseGridContainer from '../../../src/grid/Container.mjs';
2
+ import Button from '../../../src/button/Base.mjs';
2
3
  import MainStore from './MainStore.mjs';
3
4
 
4
5
  /**
@@ -45,11 +46,18 @@ class GridContainer extends BaseGridContainer {
45
46
  * @protected
46
47
  */
47
48
  afterSetAmountColumns(value, oldValue) {
48
- let i = 4,
49
+ let i = 6,
49
50
  columns = [
50
- {dataField: 'id', text: '#', width: 60, renderer({record, store}) {return store.indexOf(record) + 1}},
51
+ {type: 'index', dataField: 'id', text: '#', width: 60},
51
52
  {cellAlign: 'left', dataField: 'firstname', defaultSortDirection: 'ASC', text: 'Firstname', width: 150},
52
- {cellAlign: 'left', dataField: 'lastname', defaultSortDirection: 'ASC', text: 'Lastname', width: 150}
53
+ {cellAlign: 'left', dataField: 'lastname', defaultSortDirection: 'ASC', text: 'Lastname', width: 150},
54
+ {cellAlign: 'left', dataField: 'countAction', text: 'Increase Counter', width: 150, component: ({record}) => ({
55
+ module: Button,
56
+ handler() {record.counter++},
57
+ text : record.firstname + ' ++',
58
+ width : 130
59
+ })},
60
+ {type: 'animatedChange', dataField: 'counter', text: 'Counter'}
53
61
  ];
54
62
 
55
63
  for (; i <= value; i++) {
@@ -24,9 +24,11 @@ class MainModel extends Model {
24
24
  * @protected
25
25
  */
26
26
  afterSetAmountColumns(value, oldValue) {
27
- let i = 4,
27
+ let i = 6,
28
28
  fields = [
29
29
  {name: 'id', type: 'Int'},
30
+ {name: 'countAction'},
31
+ {name: 'counter', type: 'Int'},
30
32
  {name: 'firstname', type: 'String'},
31
33
  {name: 'lastname', type: 'String'}
32
34
  ];
@@ -113,9 +113,10 @@ class MainStore extends Store {
113
113
  column, record;
114
114
 
115
115
  for (; row < amountRows; row++) {
116
- column = 4;
116
+ column = 5;
117
117
  record = {
118
118
  id : row + 1,
119
+ counter : Math.round(Math.random() * 100),
119
120
  firstname: me.firstnames[Math.floor(Math.random() * amountFirstnames)],
120
121
  lastname : me.lastnames[ Math.floor(Math.random() * amountLastnames)]
121
122
  };
@@ -43,7 +43,7 @@ class Viewport extends BaseViewport {
43
43
  }]
44
44
  }, {
45
45
  module : GridContainer,
46
- bind : {store : 'stores.mainStore'},
46
+ bind : {store: 'stores.mainStore'},
47
47
  reference: 'grid',
48
48
 
49
49
  columnDefaults: {
@@ -55,7 +55,11 @@ class Viewport extends BaseViewport {
55
55
  {dataField: 'user.lastname', text: 'Lastname'},
56
56
  {dataField: 'githubId', text: 'Github Id'},
57
57
  {dataField: 'country', text: 'Country', renderer: 'up.countryRenderer'},
58
- {dataField: 'edit', text: 'Edit Action', renderer: 'up.editRenderer'}
58
+ {dataField: 'edit', text: 'Edit Action', component: {
59
+ module : Button,
60
+ handler: 'up.editButtonHandler',
61
+ text : 'Edit'
62
+ }}
59
63
  ],
60
64
 
61
65
  viewConfig: {
@@ -72,8 +76,8 @@ class Viewport extends BaseViewport {
72
76
  /**
73
77
  * @param {Object} data
74
78
  */
75
- countryRenderer({record}) {
76
- let countryStore = this.getStateProvider().getStore('countries');
79
+ countryRenderer({gridContainer, record}) {
80
+ let countryStore = gridContainer.getStateProvider().getStore('countries');
77
81
 
78
82
  if (countryStore.getCount() > 0) {
79
83
  return countryStore.get(record.country).name
@@ -111,28 +115,6 @@ class Viewport extends BaseViewport {
111
115
  }
112
116
  }
113
117
 
114
- /**
115
- * @param {Object} data
116
- */
117
- editRenderer({column, gridContainer, record, rowIndex}) {
118
- let me = this,
119
- {appName, windowId} = me,
120
- widgetId = `${column.id}-widget-${rowIndex}`,
121
- button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create({
122
- module : Button,
123
- appName,
124
- handler : 'up.editButtonHandler',
125
- parentId: gridContainer.id,
126
- record,
127
- text : 'Edit',
128
- windowId
129
- }));
130
-
131
- me.view.updateDepth = -1;
132
-
133
- return button.createVdomReference()
134
- }
135
-
136
118
  /**
137
119
  * @param {Object} data
138
120
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "8.28.1",
3
+ "version": "8.29.0",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,15 @@
1
+ @keyframes grid-animated-cell {
2
+ 50% {background-color:var(--button-ripple-background-color);}
3
+ }
4
+
5
+ .neo-grid-container {
6
+ .neo-grid-row, .neo-grid-row.neo-even {
7
+ .neo-grid-cell {
8
+ &.neo-animated {
9
+ animation-name : grid-animated-cell;
10
+ animation-duration : .4s;
11
+ animation-timing-function: ease-in-out;
12
+ }
13
+ }
14
+ }
15
+ }
@@ -263,12 +263,12 @@ const DefaultConfig = {
263
263
  useVdomWorker: true,
264
264
  /**
265
265
  * buildScripts/injectPackageVersion.mjs will update this value
266
- * @default '8.28.1'
266
+ * @default '8.29.0'
267
267
  * @memberOf! module:Neo
268
268
  * @name config.version
269
269
  * @type String
270
270
  */
271
- version: '8.28.1'
271
+ version: '8.29.0'
272
272
  };
273
273
 
274
274
  Object.assign(DefaultConfig, {
@@ -67,6 +67,11 @@ class Observable extends Base {
67
67
  delete name.once
68
68
  }
69
69
 
70
+ if (name.hasOwnProperty('order')) {
71
+ order = name.order;
72
+ delete name.order
73
+ }
74
+
70
75
  if (name.hasOwnProperty('scope')) {
71
76
  scope = name.scope;
72
77
  delete name.scope
@@ -74,9 +79,9 @@ class Observable extends Base {
74
79
 
75
80
  Object.entries(name).forEach(([key, value]) => {
76
81
  if (Neo.isObject(value)) {
77
- me.addListener(key, {delay, once, scope, ...value})
82
+ me.addListener(key, {delay, once, order, scope, ...value})
78
83
  } else {
79
- me.addListener(key, {delay, fn: value, once, scope})
84
+ me.addListener(key, {delay, fn: value, once, order, scope})
80
85
  }
81
86
  })
82
87
  } else if (optsType === 'object') {
@@ -115,9 +115,7 @@ class SortZone extends BaseSortZone {
115
115
  */
116
116
  moveTo(fromIndex, toIndex) {
117
117
  super.moveTo(fromIndex, toIndex);
118
-
119
- // It is crucial to use _columns to not get a shallow copy
120
- NeoArray.move(this.owner.parent._columns, fromIndex, toIndex);
118
+ this.owner.parent.columns.move(fromIndex, toIndex)
121
119
  }
122
120
 
123
121
  /**
@@ -1,9 +1,11 @@
1
1
  import BaseContainer from '../container/Base.mjs';
2
2
  import ClassSystemUtil from '../util/ClassSystem.mjs';
3
+ import Collection from '../collection/Base.mjs';
3
4
  import GridView from './View.mjs';
4
5
  import ScrollManager from './ScrollManager.mjs';
5
6
  import Store from '../data/Store.mjs';
6
7
  import VerticalScrollbar from './VerticalScrollbar.mjs';
8
+ import * as column from './column/_export.mjs';
7
9
  import * as header from './header/_export.mjs';
8
10
 
9
11
  /**
@@ -11,6 +13,17 @@ import * as header from './header/_export.mjs';
11
13
  * @extends Neo.container.Base
12
14
  */
13
15
  class GridContainer extends BaseContainer {
16
+ /**
17
+ * @member {Object} columnTypes
18
+ * @protected
19
+ * @static
20
+ */
21
+ static columnTypes = {
22
+ animatedChange: column.AnimatedChange,
23
+ column : column.Base,
24
+ component : column.Component,
25
+ index : column.Index
26
+ }
14
27
  /**
15
28
  * @member {Object} delayable
16
29
  * @protected
@@ -182,7 +195,7 @@ class GridContainer extends BaseContainer {
182
195
 
183
196
  me.vdom.id = me.getWrapperId();
184
197
 
185
- me.createColumns(me.columns);
198
+ me._columns = me.createColumns(me.columns);
186
199
 
187
200
  me.addDomListeners({
188
201
  resize: me.onResize,
@@ -235,19 +248,15 @@ class GridContainer extends BaseContainer {
235
248
 
236
249
  /**
237
250
  * Triggered after the columns config got changed
238
- * @param {Object[]|null} value
239
- * @param {Object[]|null} oldValue
251
+ * @param {Neo.collection.Base|null} value
252
+ * @param {Object[]|Neo.collection.Base|null} oldValue
240
253
  * @protected
241
254
  */
242
255
  async afterSetColumns(value, oldValue) {
243
- if (oldValue?.length > 0) {
244
- let me = this,
245
- {headerToolbar} = me;
256
+ if (oldValue?.getCount?.() > 0) {
257
+ let me = this;
246
258
 
247
- if (headerToolbar) {
248
- headerToolbar.items = value;
249
- headerToolbar.createItems()
250
- }
259
+ me.headerToolbar?.createItems()
251
260
 
252
261
  await me.timeout(50);
253
262
 
@@ -413,41 +422,57 @@ class GridContainer extends BaseContainer {
413
422
  createColumns(columns) {
414
423
  let me = this,
415
424
  {columnDefaults} = me,
425
+ headerButtons = [],
416
426
  sorters = me.store?.sorters,
417
- renderer;
418
-
419
- if (!columns || !columns.length) {
420
- Neo.logError('Attempting to create a grid.Container without defined columns', me.id);
421
- }
427
+ columnClass, renderer;
422
428
 
423
- columns.forEach(column => {
429
+ columns?.forEach((column, index) => {
424
430
  renderer = column.renderer;
425
431
 
426
432
  columnDefaults && Neo.assignDefaults(column, columnDefaults);
427
433
 
428
- if (column.dock && !column.width) {
429
- Neo.logError('Attempting to create a docked column without a defined width', column, me.id);
430
- }
431
-
432
434
  if (renderer && Neo.isString(renderer) && me[renderer]) {
433
435
  column.renderer = me[renderer]
434
436
  }
435
437
 
436
- if (sorters?.[0]) {
437
- if (column.dataField === sorters[0].property) {
438
- column.isSorted = sorters[0].direction
439
- }
438
+ if (sorters?.[0] && column.dataField === sorters[0].property) {
439
+ column.isSorted = sorters[0].direction
440
440
  }
441
441
 
442
442
  column.listeners = {
443
443
  sort : me.onSortColumn,
444
444
  scope: me
445
+ };
446
+
447
+ headerButtons.push(column);
448
+
449
+ if (column.component && !column.type) {
450
+ column.type = 'component'
445
451
  }
452
+
453
+ columnClass = me.constructor.columnTypes[column.type || 'column'];
454
+ delete column.type;
455
+
456
+ columns[index] = Neo.create(columnClass, {
457
+ parent : me,
458
+ windowId: me.windowId,
459
+ ...column
460
+ })
446
461
  });
447
462
 
448
- me.items[0].items = columns;
463
+ me.items[0].items = headerButtons;
449
464
 
450
- return columns
465
+ if (Neo.typeOf(me._columns) === 'NeoInstance') {
466
+ me._columns.clear();
467
+ me._columns.add(columns);
468
+
469
+ return me._columns
470
+ }
471
+
472
+ return Neo.create(Collection, {
473
+ keyProperty: 'dataField',
474
+ items : columns
475
+ })
451
476
  }
452
477
 
453
478
  /**
package/src/grid/View.mjs CHANGED
@@ -388,7 +388,7 @@ class GridView extends Component {
388
388
  fieldValue = ''
389
389
  }
390
390
 
391
- rendererOutput = column.renderer.call(column.rendererScope || gridContainer, {
391
+ rendererOutput = column.renderer.call(column.rendererScope || column, {
392
392
  column,
393
393
  columnIndex,
394
394
  dataField,
@@ -512,7 +512,7 @@ class GridView extends Component {
512
512
  let me = this,
513
513
  {mountedColumns, selectedRows} = me,
514
514
  gridContainer = me.parent,
515
- columns = gridContainer.headerToolbar.items,
515
+ {columns} = gridContainer,
516
516
  id = me.getRowId(record, rowIndex),
517
517
  rowCls = me.getRowClass(record, rowIndex),
518
518
  config, column, columnPosition, gridRow, i;
@@ -544,7 +544,7 @@ class GridView extends Component {
544
544
  };
545
545
 
546
546
  for (i=mountedColumns[0]; i <= mountedColumns[1]; i++) {
547
- column = columns[i];
547
+ column = columns.getAt(i);
548
548
  config = me.applyRendererOutput({column, columnIndex: i, record, rowIndex});
549
549
 
550
550
  if (column.dock) {
@@ -661,17 +661,11 @@ class GridView extends Component {
661
661
  * @returns {Object|Number|null}
662
662
  */
663
663
  getColumn(field, returnIndex=false) {
664
- let columns = this.parent.headerToolbar.items,
665
- i = 0,
666
- len = columns.length,
667
- column;
664
+ let {columns} = this.parent,
665
+ column = columns.get(field);
668
666
 
669
- for (; i < len; i++) {
670
- column = columns[i];
671
-
672
- if (column.dataField === field) {
673
- return returnIndex ? i : column
674
- }
667
+ if (column) {
668
+ return returnIndex ? columns.indexOf(column) : column
675
669
  }
676
670
 
677
671
  return null
@@ -856,51 +850,42 @@ class GridView extends Component {
856
850
  }
857
851
 
858
852
  /**
859
- * Gets triggered after changing the value of a record field.
860
- * E.g. myRecord.foo = 'bar';
861
- * @param {Object} opts
862
- * @param {Object[]} opts.fields Each field object contains the keys: name, oldValue, value
863
- * @param {Neo.data.Model} opts.model The model instance of the changed record
864
- * @param {Object} opts.record
853
+ * @param {Object} data
854
+ * @param {Object[]} data.fields Each field object contains the keys: name, oldValue, value
855
+ * @param {Neo.data.Model} data.model The model instance of the changed record
856
+ * @param {Object} data.record
865
857
  */
866
858
  onStoreRecordChange({fields, record}) {
867
- let me = this,
868
- fieldNames = fields.map(field => field.name),
869
- needsUpdate = false,
870
- rowIndex = me.store.indexOf(record),
871
- {selectionModel, vdom} = me,
872
- cellId, cellNode, cellStyle, cellVdom, column, columnIndex;
859
+ let me = this,
860
+ fieldNames = fields.map(field => field.name),
861
+ needsUpdate = false,
862
+ rowIndex = me.store.indexOf(record),
863
+ {selectionModel} = me,
864
+ column, needsCellUpdate;
873
865
 
874
866
  if (fieldNames.includes(me.colspanField)) {
875
867
  me.vdom.cn[rowIndex] = me.createRow({record, rowIndex});
876
868
  me.update()
877
869
  } else {
870
+ for (column of me.parent.columns.items) {
871
+ if (
872
+ column instanceof Neo.grid.column.Component &&
873
+ Neo.typeOf(column.component === 'Function') &&
874
+ !fieldNames.includes(column.dataField)
875
+ ) {
876
+ needsCellUpdate = me.updateCellNode(record, column.dataField);
877
+ needsUpdate = needsUpdate || needsCellUpdate
878
+ }
879
+ }
880
+
878
881
  fields.forEach(field => {
879
882
  if (field.name === me.selectedRecordField) {
880
883
  if (selectionModel.ntype === 'selection-grid-rowmodel') {
881
884
  selectionModel[field.value ? 'select' : 'deselect'](me.getRowId(record))
882
885
  }
883
886
  } else {
884
- cellId = me.getCellId(record, field.name);
885
- cellNode = VDomUtil.find(vdom, cellId);
886
-
887
- // The vdom might not exist yet => nothing to do in this case
888
- if (cellNode?.vdom) {
889
- cellStyle = cellNode.vdom.style;
890
- column = me.getColumn(field.name);
891
- columnIndex = cellNode.index;
892
- cellVdom = me.applyRendererOutput({cellId, column, columnIndex, record, rowIndex});
893
- needsUpdate = true;
894
-
895
- // The cell-positioning logic happens outside applyRendererOutput()
896
- // We need to preserve these styles
897
- Object.assign(cellVdom.style, {
898
- left : cellStyle.left,
899
- width: cellStyle.width
900
- });
901
-
902
- cellNode.parentNode.cn[columnIndex] = cellVdom
903
- }
887
+ needsCellUpdate = me.updateCellNode(record, field.name);
888
+ needsUpdate = needsUpdate || needsCellUpdate
904
889
  }
905
890
  })
906
891
  }
@@ -957,6 +942,41 @@ class GridView extends Component {
957
942
  }
958
943
  }
959
944
 
945
+ /**
946
+ * Update the cell vdom silently
947
+ * @param {Record} record
948
+ * @param {String} dataField
949
+ * @returns {Boolean} true in case the view needs an update
950
+ */
951
+ updateCellNode(record, dataField) {
952
+ let me = this,
953
+ cellId = me.getCellId(record, dataField),
954
+ cellNode = VDomUtil.find(me.vdom, cellId),
955
+ needsUpdate = false,
956
+ rowIndex = me.store.indexOf(record),
957
+ cellStyle, cellVdom, column, columnIndex;
958
+
959
+ // The vdom might not exist yet => nothing to do in this case
960
+ if (cellNode?.vdom) {
961
+ cellStyle = cellNode.vdom.style;
962
+ column = me.getColumn(dataField);
963
+ columnIndex = cellNode.index;
964
+ cellVdom = me.applyRendererOutput({cellId, column, columnIndex, record, rowIndex});
965
+ needsUpdate = true;
966
+
967
+ // The cell-positioning logic happens outside applyRendererOutput()
968
+ // We need to preserve these styles
969
+ Object.assign(cellVdom.style, {
970
+ left : cellStyle.left,
971
+ width: cellStyle.width
972
+ });
973
+
974
+ cellNode.parentNode.cn[columnIndex] = cellVdom
975
+ }
976
+
977
+ return needsUpdate
978
+ }
979
+
960
980
  /**
961
981
  *
962
982
  */
@@ -1013,7 +1033,7 @@ class GridView extends Component {
1013
1033
  endIndex = Math.min(countRecords, endIndex + bufferRowRange);
1014
1034
 
1015
1035
  me.mountedRows[0] = startIndex; // update the array inline
1016
- me.mountedRows[1] = endIndex;
1036
+ me.mountedRows[1] = endIndex
1017
1037
  }
1018
1038
 
1019
1039
  /**
@@ -0,0 +1,78 @@
1
+ import Column from './Base.mjs';
2
+ import NeoArray from '../../util/Array.mjs';
3
+ import VdomUtil from '../../util/VDom.mjs';
4
+
5
+ /**
6
+ * @class Neo.grid.column.AnimatedChange
7
+ * @extends Neo.grid.column.Base
8
+ */
9
+ class AnimatedChange extends Column {
10
+ static config = {
11
+ /**
12
+ * @member {String} className='Neo.grid.column.AnimatedChange'
13
+ * @protected
14
+ */
15
+ className: 'Neo.grid.column.AnimatedChange',
16
+ /**
17
+ * @member {String} animationCls='neo-animated'
18
+ */
19
+ animationCls: 'neo-animated',
20
+ /**
21
+ * @member {String} type='animatedChange'
22
+ * @protected
23
+ */
24
+ type: 'animatedChange'
25
+ }
26
+
27
+ /**
28
+ * @param {Object} config
29
+ */
30
+ construct(config) {
31
+ super.construct(config);
32
+
33
+ let me = this;
34
+
35
+ me.parent.store.on({
36
+ recordChange: me.onRecordChange,
37
+ scope : me
38
+ })
39
+ }
40
+
41
+ /**
42
+ * Override as needed for dynamic record-based animation classes
43
+ * @param {Record} record
44
+ * @returns {String}
45
+ */
46
+ getAnimationCls(record) {
47
+ return this.animationCls
48
+ }
49
+
50
+ /**
51
+ * @param {Object} data
52
+ * @param {Object[]} data.fields Each field object contains the keys: name, oldValue, value
53
+ * @param {Neo.data.Model} data.model The model instance of the changed record
54
+ * @param {Object} data.record
55
+ */
56
+ onRecordChange({fields, record}) {
57
+ let me = this,
58
+ {view} = me.parent,
59
+ cellId, field, node;
60
+
61
+ for (field of fields) {
62
+ if (field.name === me.dataField) {
63
+ cellId = view.getCellId(record, me.dataField);
64
+ node = VdomUtil.find(view.vdom, cellId)?.vdom;
65
+
66
+ NeoArray.add(node.cls, me.getAnimationCls(record));
67
+
68
+ // This will trigger a 2nd view update, after grid.View: onStoreRecordChange()
69
+ // It is crucial to restart the keyframe based animation
70
+ // => The previous update call will remove the last animationCls
71
+ view.update();
72
+ break
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ export default Neo.setupClass(AnimatedChange);
@@ -0,0 +1,81 @@
1
+ import Base from '../../core/Base.mjs';
2
+ import {resolveCallback} from '../../util/Function.mjs';
3
+
4
+ /**
5
+ * @class Neo.grid.column.Base
6
+ * @extends Neo.core.Base
7
+ */
8
+ class Column extends Base {
9
+ static config = {
10
+ /**
11
+ * @member {String} className='Neo.grid.column.Base'
12
+ * @protected
13
+ */
14
+ className: 'Neo.grid.column.Base',
15
+ /**
16
+ * @member {String|null} dataField=null
17
+ */
18
+ dataField: null,
19
+ /**
20
+ * @member {Neo.grid.Container|null} parent=null
21
+ */
22
+ parent: null,
23
+ /**
24
+ * @member {Function|String|null} renderer_='cellRenderer'
25
+ */
26
+ renderer_: 'cellRenderer',
27
+ /**
28
+ * Scope to execute the column renderer.
29
+ * Defaults to the column instance
30
+ * @member {Neo.core.Base|null} rendererScope=null
31
+ */
32
+ rendererScope: null,
33
+ /**
34
+ * @member {String} type='column'
35
+ * @protected
36
+ */
37
+ type: 'column',
38
+ /**
39
+ * @member {Number|null} windowId_=null
40
+ */
41
+ windowId_: null
42
+ }
43
+
44
+ /**
45
+ * Triggered after the windowId config got changed
46
+ * @param {Number} value
47
+ * @param {Number|null} oldValue
48
+ * @protected
49
+ */
50
+ afterSetWindowId(value, oldValue) {
51
+ value && Neo.currentWorker.insertThemeFiles(value, this.__proto__)
52
+ }
53
+
54
+ /**
55
+ * Triggered before the renderer config gets changed
56
+ * @param {Function|String|null} value
57
+ * @param {Function|String|null} oldValue
58
+ * @protected
59
+ */
60
+ beforeSetRenderer(value, oldValue) {
61
+ return resolveCallback(value, this).fn
62
+ }
63
+
64
+ /**
65
+ * @param {Object} data
66
+ * @param {Neo.button.Base} data.column
67
+ * @param {Number} data.columnIndex
68
+ * @param {String} data.dataField
69
+ * @param {Neo.grid.Container} data.gridContainer
70
+ * @param {Object} data.record
71
+ * @param {Number} data.rowIndex
72
+ * @param {Neo.data.Store} data.store
73
+ * @param {Number|String} data.value
74
+ * @returns {*}
75
+ */
76
+ cellRenderer(data) {
77
+ return data.value
78
+ }
79
+ }
80
+
81
+ export default Neo.setupClass(Column);
@@ -0,0 +1,79 @@
1
+ import Button from '../../button/Base.mjs';
2
+ import Column from './Base.mjs';
3
+
4
+ /**
5
+ * @class Neo.grid.column.Component
6
+ * @extends Neo.grid.column.Base
7
+ */
8
+ class Component extends Column {
9
+ static config = {
10
+ /**
11
+ * @member {String} className='Neo.grid.column.Component'
12
+ * @protected
13
+ */
14
+ className: 'Neo.grid.column.Component',
15
+ /**
16
+ * @member {Function|Object|null} component=null
17
+ */
18
+ component: null,
19
+ /**
20
+ * @member {String} type='component'
21
+ * @protected
22
+ */
23
+ type: 'component'
24
+ }
25
+
26
+ /**
27
+ * @member {Map} map=new Map()
28
+ * @protected
29
+ */
30
+ map = new Map()
31
+
32
+ /**
33
+ * @param {Object} data
34
+ * @param {Neo.button.Base} data.column
35
+ * @param {Number} data.columnIndex
36
+ * @param {String} data.dataField
37
+ * @param {Neo.grid.Container} data.gridContainer
38
+ * @param {Object} data.record
39
+ * @param {Number} data.rowIndex
40
+ * @param {Neo.data.Store} data.store
41
+ * @param {Number|String} data.value
42
+ * @returns {*}
43
+ */
44
+ cellRenderer(data) {
45
+ let {gridContainer, rowIndex} = data,
46
+ {appName, view, windowId} = gridContainer,
47
+ me = this,
48
+ id = `${me.id}-component-${rowIndex % (view.availableRows + 2 * view.bufferRowRange)}`,
49
+ component = me.map.get(id),
50
+ componentConfig = me.component;
51
+
52
+ if (Neo.typeOf(componentConfig) === 'Function') {
53
+ componentConfig = componentConfig(data)
54
+ }
55
+
56
+ if (component) {
57
+ delete componentConfig.className;
58
+ delete componentConfig.module;
59
+ delete componentConfig.ntype;
60
+
61
+ component.set(componentConfig)
62
+ } else {
63
+ component = Neo.create({
64
+ ...componentConfig,
65
+ appName,
66
+ id,
67
+ windowId
68
+ });
69
+
70
+ me.map.set(id, component)
71
+ }
72
+
73
+ view.updateDepth = -1;
74
+
75
+ return component.createVdomReference()
76
+ }
77
+ }
78
+
79
+ export default Neo.setupClass(Component);
@@ -0,0 +1,42 @@
1
+ import Column from './Base.mjs';
2
+
3
+ /**
4
+ * @class Neo.grid.column.Index
5
+ * @extends Neo.grid.column.Base
6
+ */
7
+ class Index extends Column {
8
+ static config = {
9
+ /**
10
+ * @member {String} className='Neo.grid.column.Index'
11
+ * @protected
12
+ */
13
+ className: 'Neo.grid.column.Index',
14
+ /**
15
+ * @member {String} type='index'
16
+ * @protected
17
+ */
18
+ type: 'index',
19
+ /**
20
+ * @member {Boolean} zeroBased=false
21
+ */
22
+ zeroBased: false
23
+ }
24
+
25
+ /**
26
+ * @param {Object} data
27
+ * @param {Neo.button.Base} data.column
28
+ * @param {Number} data.columnIndex
29
+ * @param {String} data.dataField
30
+ * @param {Neo.grid.Container} data.gridContainer
31
+ * @param {Object} data.record
32
+ * @param {Number} data.rowIndex
33
+ * @param {Neo.data.Store} data.store
34
+ * @param {Number|String} data.value
35
+ * @returns {*}
36
+ */
37
+ cellRenderer({rowIndex}) {
38
+ return rowIndex + (this.zeroBased ? 0 : 1)
39
+ }
40
+ }
41
+
42
+ export default Neo.setupClass(Index);
@@ -0,0 +1,6 @@
1
+ import AnimatedChange from './AnimatedChange.mjs';
2
+ import Base from './Base.mjs';
3
+ import Component from './Component.mjs';
4
+ import Index from './Index.mjs';
5
+
6
+ export {AnimatedChange, Base, Component, Index};
@@ -1,7 +1,6 @@
1
- import BaseButton from '../../button/Base.mjs';
2
- import NeoArray from '../../util/Array.mjs';
3
- import TextField from '../../form/field/Text.mjs';
4
- import {resolveCallback} from '../../util/Function.mjs';
1
+ import BaseButton from '../../button/Base.mjs';
2
+ import NeoArray from '../../util/Array.mjs';
3
+ import TextField from '../../form/field/Text.mjs';
5
4
 
6
5
  /**
7
6
  * @class Neo.grid.header.Button
@@ -72,16 +71,6 @@ class Button extends BaseButton {
72
71
  * @protected
73
72
  */
74
73
  isSorted_: null,
75
- /**
76
- * @member {Function|String|null} renderer_='cellRenderer'
77
- */
78
- renderer_: 'cellRenderer',
79
- /**
80
- * Scope to execute the column renderer.
81
- * Defaults to the matching grid.Container
82
- * @member {Neo.core.Base|null} rendererScope=null
83
- */
84
- rendererScope: null,
85
74
  /**
86
75
  * @member {String} role='columnheader'
87
76
  */
@@ -217,32 +206,6 @@ class Button extends BaseButton {
217
206
  return this.beforeSetEnumValue(value, oldValue, 'cellAlign', 'cellAlignValues')
218
207
  }
219
208
 
220
- /**
221
- * Triggered before the renderer config gets changed
222
- * @param {Function|String|null} value
223
- * @param {Function|String|null} oldValue
224
- * @protected
225
- */
226
- beforeSetRenderer(value, oldValue) {
227
- return resolveCallback(value, this).fn
228
- }
229
-
230
- /**
231
- * @param {Object} data
232
- * @param {Neo.button.Base} data.column
233
- * @param {Number} data.columnIndex
234
- * @param {String} data.dataField
235
- * @param {Neo.grid.Container} data.gridContainer
236
- * @param {Object} data.record
237
- * @param {Number} data.rowIndex
238
- * @param {Neo.data.Store} data.store
239
- * @param {Number|String} data.value
240
- * @returns {*}
241
- */
242
- cellRenderer(data) {
243
- return data.value
244
- }
245
-
246
209
  /**
247
210
  *
248
211
  */
@@ -20,7 +20,7 @@ class BaseModel extends Model {
20
20
  * @member {String[]} dataFields
21
21
  */
22
22
  get dataFields() {
23
- return this.view.parent.columns.map(column => column.dataField)
23
+ return this.view.parent.columns.items.map(column => column.dataField)
24
24
  }
25
25
 
26
26
  /**