neo.mjs 8.13.0 → 8.14.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.
Files changed (34) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/portal/index.html +1 -1
  3. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  4. package/apps/realworld2/view/article/PreviewList.mjs +2 -2
  5. package/examples/ServiceWorker.mjs +2 -2
  6. package/examples/grid/nestedRecordFields/Viewport.mjs +27 -4
  7. package/examples/table/container/MainContainer.mjs +4 -4
  8. package/examples/table/covid/Util.mjs +1 -1
  9. package/examples/table/nestedRecordFields/Viewport.mjs +2 -2
  10. package/package.json +2 -2
  11. package/resources/scss/src/draggable/DragProxyComponent.scss +4 -1
  12. package/resources/scss/src/draggable/grid/header/toolbar/SortZone.scss +25 -2
  13. package/src/DefaultConfig.mjs +2 -2
  14. package/src/Neo.mjs +1 -1
  15. package/src/calendar/view/YearComponent.mjs +2 -2
  16. package/src/calendar/view/month/Component.mjs +1 -1
  17. package/src/calendar/view/week/EventDragZone.mjs +32 -29
  18. package/src/calendar/view/week/plugin/DragDrop.mjs +21 -21
  19. package/src/component/Base.mjs +29 -61
  20. package/src/component/DateSelector.mjs +1 -1
  21. package/src/component/Gallery.mjs +1 -1
  22. package/src/component/Helix.mjs +1 -1
  23. package/src/data/Model.mjs +0 -8
  24. package/src/draggable/DragZone.mjs +11 -5
  25. package/src/draggable/grid/header/toolbar/SortZone.mjs +111 -0
  26. package/src/draggable/list/DragZone.mjs +2 -2
  27. package/src/draggable/tab/header/toolbar/SortZone.mjs +2 -2
  28. package/src/draggable/toolbar/DragZone.mjs +3 -3
  29. package/src/draggable/toolbar/SortZone.mjs +2 -2
  30. package/src/draggable/tree/DragZone.mjs +2 -2
  31. package/src/grid/Container.mjs +2 -18
  32. package/src/grid/View.mjs +41 -24
  33. package/src/grid/header/Toolbar.mjs +4 -8
  34. package/src/selection/grid/RowModel.mjs +2 -2
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.13.0'
23
+ * @member {String} version='8.14.0'
24
24
  */
25
- version: '8.13.0'
25
+ version: '8.14.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-01-30",
19
+ "datePublished": "2025-02-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.13.0'
110
+ html : 'v8.14.0'
111
111
  }]
112
112
  }],
113
113
  /**
@@ -46,8 +46,8 @@ class PreviewList extends List {
46
46
 
47
47
  if (!silent) {
48
48
  me.promiseUpdate().then(() => {
49
- me.fire('createItems');
50
- });
49
+ me.fire('createItems')
50
+ })
51
51
  }
52
52
  }
53
53
  }
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='8.13.0'
23
+ * @member {String} version='8.14.0'
24
24
  */
25
- version: '8.13.0'
25
+ version: '8.14.0'
26
26
  }
27
27
 
28
28
  /**
@@ -32,13 +32,19 @@ class Viewport extends BaseViewport {
32
32
  style : {marginBottom: '1em'},
33
33
 
34
34
  items: ['->', {
35
+ handler: 'up.onSwitchDragModeButtonClick',
36
+ iconCls: 'far fa-square',
37
+ style : {marginRight: '1em'},
38
+ text : 'Drag column headers only'
39
+ }, {
35
40
  handler: 'up.onSwitchThemeButtonClick',
36
41
  iconCls: 'fas fa-sun',
37
42
  text : 'Light Theme'
38
43
  }]
39
44
  }, {
40
- module: GridContainer,
41
- bind : {store : 'stores.mainStore'},
45
+ module : GridContainer,
46
+ bind : {store : 'stores.mainStore'},
47
+ reference: 'grid',
42
48
 
43
49
  columnDefaults: {
44
50
  width: 200
@@ -108,10 +114,10 @@ class Viewport extends BaseViewport {
108
114
  /**
109
115
  * @param {Object} data
110
116
  */
111
- editRenderer({column, gridContainer, index, record}) {
117
+ editRenderer({column, gridContainer, record, rowIndex}) {
112
118
  let me = this,
113
119
  {appName, windowId} = me,
114
- widgetId = `${column.id}-widget-${index}`,
120
+ widgetId = `${column.id}-widget-${rowIndex}`,
115
121
  button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create({
116
122
  module : Button,
117
123
  appName,
@@ -127,6 +133,23 @@ class Viewport extends BaseViewport {
127
133
  return button.createVdomReference()
128
134
  }
129
135
 
136
+ /**
137
+ * @param {Object} data
138
+ */
139
+ onSwitchDragModeButtonClick(data) {
140
+ let button = data.component,
141
+ grid = this.getReference('grid'),
142
+ {sortZone} = grid.headerToolbar;
143
+
144
+ if (button.iconCls === 'fas fa-check') {
145
+ button.set({iconCls: 'far fa-square'});
146
+ sortZone.moveColumnContent = true
147
+ } else {
148
+ button.set({iconCls: 'fas fa-check'});
149
+ sortZone.moveColumnContent = false
150
+ }
151
+ }
152
+
130
153
  /**
131
154
  * @param {Object} data
132
155
  */
@@ -127,10 +127,10 @@ class MainContainer extends ConfigurationViewport {
127
127
  {
128
128
  dataField: 'edit',
129
129
  text : 'Edit Action',
130
- renderer({column, index}) {
130
+ renderer({column, rowIndex}) {
131
131
  const
132
132
  me = this,
133
- widgetId = `${column.id}-widget-${index}`,
133
+ widgetId = `${column.id}-widget-${rowIndex}`,
134
134
  button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create({
135
135
  module : Button,
136
136
  appName : me.appName,
@@ -146,10 +146,10 @@ class MainContainer extends ConfigurationViewport {
146
146
  }, {
147
147
  dataField: 'menu',
148
148
  text : 'Menu',
149
- renderer({column, record, index}) {
149
+ renderer({column, record, rowIndex}) {
150
150
  const
151
151
  me = this,
152
- widgetId = `${column.id}-widget-${index}`,
152
+ widgetId = `${column.id}-widget-${rowIndex}`,
153
153
  button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create('Neo.button.Base', {
154
154
  ntype : 'button',
155
155
  appName : me.appName,
@@ -133,7 +133,7 @@ class Util extends Base {
133
133
  imageName = map[imageName] || imageName;
134
134
 
135
135
  if (Neo.config.isGitHubPages) {
136
- let path = `../../../../resources/images/flaticon/country_flags/png/${imageName}.png`;
136
+ let path = `../../../../resources_pub/images/flaticon/country_flags/png/${imageName}.png`;
137
137
 
138
138
  if (Neo.config.environment !== 'development') {
139
139
  path = `../../${path}`
@@ -104,10 +104,10 @@ class Viewport extends BaseViewport {
104
104
  /**
105
105
  * @param {Object} data
106
106
  */
107
- editRenderer({column, index, record, tableContainer}) {
107
+ editRenderer({column, record, rowIndex, tableContainer}) {
108
108
  let me = this,
109
109
  {appName, windowId} = me,
110
- widgetId = `${column.id}-widget-${index}`,
110
+ widgetId = `${column.id}-widget-${rowIndex}`,
111
111
  button = (column.widgetMap || (column.widgetMap = {}))[widgetId] || (column.widgetMap[widgetId] = Neo.create({
112
112
  module : Button,
113
113
  appName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "8.13.0",
3
+ "version": "8.14.0",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -54,7 +54,7 @@
54
54
  "envinfo": "^7.14.0",
55
55
  "fs-extra": "^11.3.0",
56
56
  "highlightjs-line-numbers.js": "^2.9.0",
57
- "inquirer": "^12.3.3",
57
+ "inquirer": "^12.4.1",
58
58
  "marked": "^15.0.6",
59
59
  "monaco-editor": "0.50.0",
60
60
  "neo-jsdoc": "1.0.1",
@@ -1,9 +1,11 @@
1
1
  body:has(.neo-is-dragging) {
2
- cursor: move !important;
2
+ cursor : move !important;
3
+ user-select: none !important;
3
4
 
4
5
  // We can not put pointer-events: none on the same level as cursor, since it prevents cursor changes
5
6
  * {
6
7
  pointer-events: none !important;
8
+ user-select : none !important;
7
9
  }
8
10
  }
9
11
 
@@ -13,6 +15,7 @@ body:has(.neo-is-dragging) {
13
15
  transform : none !important;
14
16
  transition-duration: 0ms;
15
17
  transition-property: none;
18
+ user-select : none !important;
16
19
  will-change : left, top;
17
20
  z-index : 1000;
18
21
 
@@ -1,5 +1,22 @@
1
- .neo-grid-header-toolbar {
2
- &.neo-dragproxy {
1
+ .neo-grid-container {
2
+ &:has(.neo-is-dragging) {
3
+ .neo-grid-cell {
4
+ opacity : .8;
5
+ transition: left 200ms ease-out;
6
+
7
+ &:last-child {
8
+ border-right-width : 1px;
9
+ }
10
+ }
11
+ }
12
+ }
13
+
14
+ .neo-dragproxy {
15
+ .neo-grid-container {
16
+ border: none;
17
+ }
18
+
19
+ .neo-grid-header-toolbar {
3
20
  height: 30px !important; // Hack to increase the height by the border-bottom height (29 + 1)
4
21
 
5
22
  .neo-button {
@@ -7,6 +24,12 @@
7
24
  }
8
25
  }
9
26
 
27
+ .neo-grid-row {
28
+ position: unset;
29
+ }
30
+ }
31
+
32
+ .neo-grid-header-toolbar {
10
33
  &.neo-is-dragging {
11
34
  .neo-button {
12
35
  border-right: 1px solid var(--grid-container-border-color); // Would be missing for the last button otherwise
@@ -262,12 +262,12 @@ const DefaultConfig = {
262
262
  useVdomWorker: true,
263
263
  /**
264
264
  * buildScripts/injectPackageVersion.mjs will update this value
265
- * @default '8.13.0'
265
+ * @default '8.14.0'
266
266
  * @memberOf! module:Neo
267
267
  * @name config.version
268
268
  * @type String
269
269
  */
270
- version: '8.13.0'
270
+ version: '8.14.0'
271
271
  };
272
272
 
273
273
  Object.assign(DefaultConfig, {
package/src/Neo.mjs CHANGED
@@ -701,7 +701,7 @@ function autoGenerateGetSet(proto, key) {
701
701
  // every set call has to delete the matching symbol
702
702
  delete me[configSymbol][key];
703
703
 
704
- if (key !== 'items') {
704
+ if (key !== 'items' && key !== 'vnode') {
705
705
  value = Neo.clone(value, true, true)
706
706
  }
707
707
 
@@ -509,7 +509,7 @@ class YearComponent extends Component {
509
509
  vdom.cn[1].cn[0].cn[scrollFromTop ? 'unshift' : 'push'](vdom.cn[0]);
510
510
  vdom.cn.splice(0, 1);
511
511
 
512
- me.promiseUpdate(vdom).then(() => {
512
+ me.promiseUpdate().then(() => {
513
513
  y = scrollFromTop ? -data.height : 0;
514
514
  vdom.cn[0].cn[0].style.transform = `translateY(${y}px)`;
515
515
  me.update();
@@ -779,7 +779,7 @@ class YearComponent extends Component {
779
779
 
780
780
  me.isUpdating = true;
781
781
 
782
- me.promiseUpdate(me.vdom).then(() => {
782
+ me.promiseUpdate().then(() => {
783
783
  me.isUpdating = false
784
784
  })
785
785
  }
@@ -689,7 +689,7 @@ class Component extends BaseComponent {
689
689
  week.header && container.cn.unshift(week.header)
690
690
  }
691
691
 
692
- me.promiseUpdate(me.vdom).then(() => {
692
+ me.promiseUpdate().then(() => {
693
693
  Neo.main.DomAccess.scrollTo({
694
694
  direction: 'top',
695
695
  id : me.vdom.cn[1].id,
@@ -156,8 +156,10 @@ class EventDragZone extends DragZone {
156
156
 
157
157
  /**
158
158
  * @param {Object} data
159
+ * @param {Boolean} createComponent=true
160
+ * @returns {Object|Neo.draggable.DragProxyComponent}
159
161
  */
160
- createDragProxy(data) {
162
+ async createDragProxy(data, createComponent=true) {
161
163
  let me = this,
162
164
  component = Neo.getComponent(me.getDragElementRoot().id) || me.owner,
163
165
  vdom = me.dragProxyConfig?.vdom,
@@ -199,7 +201,11 @@ class EventDragZone extends DragZone {
199
201
  width : `${data.width}px`
200
202
  });
201
203
 
202
- me.dragProxy = Neo.create(config)
204
+ if (createComponent) {
205
+ return me.dragProxy = Neo.create(config)
206
+ }
207
+
208
+ return config
203
209
  }
204
210
 
205
211
  /**
@@ -491,35 +497,32 @@ class EventDragZone extends DragZone {
491
497
  /**
492
498
  * @param {Object} data
493
499
  */
494
- dragStart(data) {
495
- let me = this,
496
- eventDuration, offsetX, offsetY;
497
-
498
- me.owner.getDomRect([me.getDragElementRoot().id, data.path[1].id]).then(rects => {
499
- eventDuration = (me.eventRecord.endDate - me.eventRecord.startDate) / 60 / 1000;
500
- offsetX = data.clientX - rects[0].left;
500
+ async dragStart(data) {
501
+ let me = this,
502
+ rects = await me.owner.getDomRect([me.getDragElementRoot().id, data.path[1].id]),
503
+ eventDuration = (me.eventRecord.endDate - me.eventRecord.startDate) / 60 / 1000,
504
+ offsetX = data.clientX - rects[0].left,
501
505
  offsetY = data.clientY - rects[0].top;
502
506
 
503
- Object.assign(me, {
504
- columnHeight : rects[1].height,
505
- columnTop : rects[1].top,
506
- dragElementRect: rects[0],
507
- eventDuration : Math.round(eventDuration / me.intervalSize) * me.intervalSize,
508
- offsetX,
509
- offsetY
510
- });
511
-
512
- me.createDragProxy(rects[0]);
513
-
514
- me.fire('dragStart', {
515
- dragElementRect: rects[0],
516
- id : me.id,
517
- offsetX,
518
- offsetY
519
- });
520
-
521
- me.dragMove(data)
522
- })
507
+ Object.assign(me, {
508
+ columnHeight : rects[1].height,
509
+ columnTop : rects[1].top,
510
+ dragElementRect: rects[0],
511
+ eventDuration : Math.round(eventDuration / me.intervalSize) * me.intervalSize,
512
+ offsetX,
513
+ offsetY
514
+ });
515
+
516
+ await me.createDragProxy(rects[0]);
517
+
518
+ me.fire('dragStart', {
519
+ dragElementRect: rects[0],
520
+ id : me.id,
521
+ offsetX,
522
+ offsetY
523
+ });
524
+
525
+ me.dragMove(data)
523
526
  }
524
527
 
525
528
  /**
@@ -175,7 +175,7 @@ class DragDrop extends Base {
175
175
  /**
176
176
  * @param {Object} data
177
177
  */
178
- onColumnDragStart(data) {
178
+ async onColumnDragStart(data) {
179
179
  let me = this;
180
180
 
181
181
  if (me.isActiveCalendar() && me.isTopLevelColumn(data.targetPath)) {
@@ -214,26 +214,26 @@ class DragDrop extends Base {
214
214
  me[newRecordSymbol] = record;
215
215
 
216
216
  // wait until the new event got mounted
217
- me.timeout(50).then(() => {
218
- eventId = owner.getEventId(record.id);
219
- dragElement = VDomUtil.find(owner.vdom, eventId).vdom;
220
-
221
- eventDragZone = me.getEventDragZone({
222
- dragElement,
223
- enableResizingAcrossOppositeEdge: true,
224
- eventRecord : record,
225
- proxyParentId : data.path[0].id
226
- });
227
-
228
- owner.getPlugin(me.resizablePluginType).onDragStart(data);
229
- eventDragZone.dragStart(data);
230
-
231
- me.timeout(50).then(() => {
232
- me.isDragging && Neo.applyDeltas(me.appName, {
233
- id : eventId,
234
- style: {opacity: 0}
235
- })
236
- })
217
+ await me.timeout(50);
218
+
219
+ eventId = owner.getEventId(record.id);
220
+ dragElement = VDomUtil.find(owner.vdom, eventId).vdom;
221
+
222
+ eventDragZone = me.getEventDragZone({
223
+ dragElement,
224
+ enableResizingAcrossOppositeEdge: true,
225
+ eventRecord : record,
226
+ proxyParentId : data.path[0].id
227
+ });
228
+
229
+ owner.getPlugin(me.resizablePluginType).onDragStart(data);
230
+ await eventDragZone.dragStart(data);
231
+
232
+ await me.timeout(50);
233
+
234
+ me.isDragging && Neo.applyDeltas(me.appName, {
235
+ id : eventId,
236
+ style: {opacity: 0}
237
237
  })
238
238
  }
239
239
  }
@@ -488,7 +488,7 @@ class Component extends Base {
488
488
  * @param {String} value
489
489
  */
490
490
  addCls(value) {
491
- let cls = this.cls;
491
+ let {cls} = this;
492
492
 
493
493
  NeoArray.add(cls, value);
494
494
  this.cls = cls
@@ -526,6 +526,17 @@ class Component extends Base {
526
526
  return this.style = Object.assign(this.style, value)
527
527
  }
528
528
 
529
+ /**
530
+ * Add a new wrapperCls to the top level node
531
+ * @param {String} value
532
+ */
533
+ addWrapperCls(value) {
534
+ let {wrapperCls} = this;
535
+
536
+ NeoArray.add(wrapperCls, value);
537
+ this.wrapperCls = wrapperCls
538
+ }
539
+
529
540
  /**
530
541
  * Triggered after the appName config got changed
531
542
  * @param {String|null} value
@@ -560,11 +571,7 @@ class Component extends Base {
560
571
  vdom.cls = cls
561
572
  }
562
573
 
563
- if (me.isVdomUpdating || me.silentVdomUpdate) {
564
- me.needsVdomUpdate = true
565
- } else if (me.mounted && me.vnode) {
566
- me.updateCls(value, oldValue, vdomRoot.id)
567
- }
574
+ me.update()
568
575
  }
569
576
 
570
577
  /**
@@ -1038,7 +1045,7 @@ class Component extends Base {
1038
1045
  * @protected
1039
1046
  */
1040
1047
  afterSetVdom(value, oldValue) {
1041
- this.updateVdom(value)
1048
+ this.updateVdom()
1042
1049
  }
1043
1050
 
1044
1051
  /**
@@ -1098,9 +1105,9 @@ class Component extends Base {
1098
1105
  value = value || [];
1099
1106
 
1100
1107
  let me = this,
1101
- vdom = me.vdom,
1108
+ {vdom} = me,
1102
1109
  vdomRoot = me.getVdomRoot(),
1103
- cls = me.vdom?.cls || [];
1110
+ cls = vdom.cls || [];
1104
1111
 
1105
1112
  if (vdom === vdomRoot) {
1106
1113
  // we need to merge changes
@@ -1114,9 +1121,7 @@ class Component extends Base {
1114
1121
  oldValue && NeoArray.remove(cls, oldValue);
1115
1122
  NeoArray.add(cls, value);
1116
1123
 
1117
- if (vdom) {
1118
- vdom.cls = cls
1119
- }
1124
+ vdom.cls = cls
1120
1125
  }
1121
1126
 
1122
1127
  me.update()
@@ -1545,15 +1550,14 @@ class Component extends Base {
1545
1550
 
1546
1551
  /**
1547
1552
  * Internal method to send update requests to the vdom worker
1548
- * @param {Object} vdom
1549
- * @param {Neo.vdom.VNode} vnode
1550
1553
  * @param {function} [resolve] used by promiseUpdate()
1551
1554
  * @param {function} [reject] used by promiseUpdate()
1552
1555
  * @private
1553
1556
  */
1554
- #executeVdomUpdate(vdom, vnode, resolve, reject) {
1555
- let me = this,
1556
- opts = {},
1557
+ #executeVdomUpdate(resolve, reject) {
1558
+ let me = this,
1559
+ {vdom, vnode} = me,
1560
+ opts = {},
1557
1561
  deltas;
1558
1562
 
1559
1563
  if (currentWorker.isSharedWorker) {
@@ -1576,8 +1580,6 @@ class Component extends Base {
1576
1580
 
1577
1581
  Neo.vdom.Helper.update(opts).catch(err => {
1578
1582
  me.isVdomUpdating = false;
1579
- console.log('Error attempting to update component dom', err, me);
1580
-
1581
1583
  reject?.()
1582
1584
  }).then(data => {
1583
1585
  me.isVdomUpdating = false;
@@ -2197,8 +2199,6 @@ class Component extends Base {
2197
2199
  me._rendered = true; // silent update
2198
2200
  me.fire('rendered', me.id);
2199
2201
 
2200
- // console.log('rendered: ' + me.appName + ' ' + me.id, me);
2201
-
2202
2202
  if (autoMount) {
2203
2203
  me.mounted = true;
2204
2204
 
@@ -2212,13 +2212,11 @@ class Component extends Base {
2212
2212
 
2213
2213
  /**
2214
2214
  * Promise based vdom update
2215
- * @param {Object} vdom=this.vdom
2216
- * @param {Neo.vdom.VNode} vnode= this.vnode
2217
2215
  * @returns {Promise<any>}
2218
2216
  */
2219
- promiseUpdate(vdom=this.vdom, vnode=this.vnode) {
2217
+ promiseUpdate() {
2220
2218
  return new Promise((resolve, reject) => {
2221
- this.updateVdom(vdom, vnode, resolve, reject)
2219
+ this.updateVdom(resolve, reject)
2222
2220
  })
2223
2221
  }
2224
2222
 
@@ -2586,34 +2584,6 @@ class Component extends Base {
2586
2584
  this.afterSetVdom(this.vdom, null)
2587
2585
  }
2588
2586
 
2589
- /**
2590
- * Delta updates for the cls config. Gets called after the cls config gets changed in case the component is mounted.
2591
- * @param {String[]} cls
2592
- * @param {String[]} oldCls
2593
- * @param {String} id=this.id
2594
- * @protected
2595
- */
2596
- updateCls(cls, oldCls, id=this.id) {
2597
- let me = this,
2598
- {vnode} = me,
2599
- vnodeTarget = vnode && VNodeUtil.find(me.vnode, {id})?.vnode;
2600
-
2601
- if (vnode && !Neo.isEqual(cls, oldCls)) {
2602
- if (vnodeTarget) {
2603
- vnodeTarget.className = cls; // keep the vnode in sync
2604
- me.vnode = vnode;
2605
- }
2606
-
2607
- Neo.applyDeltas(me.appName, {
2608
- id,
2609
- cls: {
2610
- add : NeoArray.difference(cls, oldCls),
2611
- remove: NeoArray.difference(oldCls, cls)
2612
- }
2613
- })
2614
- }
2615
- }
2616
-
2617
2587
  /**
2618
2588
  * Creates the style deltas for newValue & oldValue and applies them directly to the DOM.
2619
2589
  * @param {Object|String} value
@@ -2668,15 +2638,13 @@ class Component extends Base {
2668
2638
 
2669
2639
  /**
2670
2640
  * Gets called after the vdom config gets changed in case the component is already mounted (delta updates).
2671
- * @param {Object} vdom=this.vdom
2672
- * @param {Neo.vdom.VNode} vnode=this.vnode
2673
2641
  * @param {function} [resolve] used by promiseUpdate()
2674
2642
  * @param {function} [reject] used by promiseUpdate()
2675
2643
  * @protected
2676
2644
  */
2677
- updateVdom(vdom=this.vdom, vnode=this.vnode, resolve, reject) {
2678
- let me = this,
2679
- {app, mounted, parentId} = me,
2645
+ updateVdom(resolve, reject) {
2646
+ let me = this,
2647
+ {app, mounted, parentId, vnode} = me,
2680
2648
  listenerId;
2681
2649
 
2682
2650
  if (me.isVdomUpdating || me.silentVdomUpdate) {
@@ -2690,7 +2658,7 @@ class Component extends Base {
2690
2658
  app.un('mounted', listenerId);
2691
2659
 
2692
2660
  me.timeout(50).then(() => {
2693
- me.vnode && me.updateVdom(me.vdom, me.vnode, resolve, reject)
2661
+ me.vnode && me.updateVdom(resolve, reject)
2694
2662
  })
2695
2663
  })
2696
2664
  } else {
@@ -2707,10 +2675,10 @@ class Component extends Base {
2707
2675
  // Verify that the critical rendering path => CSS files for the new tree is in place
2708
2676
  if (currentWorker.countLoadingThemeFiles !== 0) {
2709
2677
  currentWorker.on('themeFilesLoaded', function() {
2710
- me.updateVdom(vdom, vnode, resolve, reject)
2678
+ me.updateVdom(resolve, reject)
2711
2679
  }, me, {once: true})
2712
2680
  } else {
2713
- me.#executeVdomUpdate(vdom, vnode, resolve, reject)
2681
+ me.#executeVdomUpdate(resolve, reject)
2714
2682
  }
2715
2683
  }
2716
2684
  }
@@ -547,7 +547,7 @@ class DateSelector extends Component {
547
547
  vdom.cn[2].cn[0].cn[scrollFromTop ? 'unshift' : 'push'](vdom.cn[1]);
548
548
  vdom.cn.splice(1, 1);
549
549
 
550
- me.promiseUpdate(vdom).then(() => {
550
+ me.promiseUpdate().then(() => {
551
551
  y = scrollFromTop ? -data.height : 0;
552
552
  vdom.cn[1].cn[0].style.transform = `translateY(${y}px)`;
553
553
  me.update();
@@ -441,7 +441,7 @@ class Gallery extends Component {
441
441
  itemsRoot.cn.push(vdomItem)
442
442
  }
443
443
 
444
- me.promiseUpdate(vdom).then(() => {
444
+ me.promiseUpdate().then(() => {
445
445
  me[itemsMounted] = true
446
446
  })
447
447
  }
@@ -597,7 +597,7 @@ class Helix extends Component {
597
597
 
598
598
  me[lockWheel] = true;
599
599
 
600
- me.promiseUpdate(vdom).then(() => {
600
+ me.promiseUpdate().then(() => {
601
601
  me[itemsMounted] = true;
602
602
  me.fire('itemsMounted');
603
603
 
@@ -50,14 +50,6 @@ class Model extends Base {
50
50
  */
51
51
  hasNestedFields = false
52
52
 
53
- /**
54
- * @param {Object} config
55
- */
56
- construct(config) {
57
- super.construct(config);
58
- RecordFactory.createRecordClass(this)
59
- }
60
-
61
53
  /**
62
54
  Triggered after the fields config got changed
63
55
  * @param {Object[]|null} value
@@ -184,9 +184,11 @@ class DragZone extends Base {
184
184
  }
185
185
 
186
186
  /**
187
- * @param {Object} data
187
+ * @param {Object} data
188
+ * @param {Boolean} createComponent=true
189
+ * @returns {Object|Neo.draggable.DragProxyComponent}
188
190
  */
189
- createDragProxy(data) {
191
+ async createDragProxy(data, createComponent=true) {
190
192
  let me = this,
191
193
  component = Neo.getComponent(me.getDragElementRoot().id) || me.owner,
192
194
  rect = me.dragElementRect,
@@ -228,7 +230,11 @@ class DragZone extends Base {
228
230
  width : `${data.width}px`
229
231
  });
230
232
 
231
- me.dragProxy = Neo.create(config)
233
+ if (createComponent) {
234
+ return me.dragProxy = Neo.create(config)
235
+ }
236
+
237
+ return config
232
238
  }
233
239
 
234
240
  /**
@@ -304,7 +310,7 @@ class DragZone extends Base {
304
310
  /**
305
311
  * @param {Object} data
306
312
  */
307
- dragStart(data) {
313
+ async dragStart(data) {
308
314
  let me = this,
309
315
  {appName, owner, windowId} = me,
310
316
  {cls} = owner,
@@ -331,7 +337,7 @@ class DragZone extends Base {
331
337
  offsetY
332
338
  });
333
339
 
334
- me.createDragProxy(rect);
340
+ await me.createDragProxy(rect);
335
341
 
336
342
  me.fire('dragStart', {
337
343
  clientX : data.clientX,
@@ -1,5 +1,6 @@
1
1
  import BaseSortZone from '../../../toolbar/SortZone.mjs';
2
2
  import NeoArray from '../../../../util/Array.mjs';
3
+ import VdomUtil from '../../../../util/VDom.mjs';
3
4
 
4
5
  /**
5
6
  * @class Neo.draggable.grid.header.toolbar.SortZone
@@ -22,6 +23,10 @@ class SortZone extends BaseSortZone {
22
23
  * @protected
23
24
  */
24
25
  itemMargin: '1px',
26
+ /**
27
+ * @member {Boolean} moveColumnContent=true
28
+ */
29
+ moveColumnContent: true,
25
30
  /**
26
31
  * @member {Boolean} moveVertical=false
27
32
  */
@@ -37,6 +42,59 @@ class SortZone extends BaseSortZone {
37
42
  rect.y = rect.y - parentRect.y - 1
38
43
  }
39
44
 
45
+ /**
46
+ * @param {Object} data
47
+ * @param {Boolean} createComponent=true
48
+ * @returns {Object|Neo.draggable.DragProxyComponent}
49
+ */
50
+ async createDragProxy(data, createComponent=true) {
51
+ if (!this.moveColumnContent) {
52
+ return await super.createDragProxy(data, createComponent)
53
+ }
54
+
55
+ let me = this,
56
+ grid = me.owner.parent,
57
+ {view} = grid,
58
+ gridRows = view.getVdomRoot().cn,
59
+ columnIndex = me.dragElement['aria-colindex'] - 1,
60
+ {dataField} = view.columnPositions[columnIndex],
61
+ cells = view.getColumnCells(dataField),
62
+ rows = [],
63
+ config = await super.createDragProxy(data, false),
64
+ rect = await grid.getDomRect(),
65
+ row;
66
+
67
+ config.cls = ['neo-grid-wrapper', me.owner.getTheme()];
68
+
69
+ config.style.height = rect.height + 'px';
70
+
71
+ cells.forEach((cell, index) => {
72
+ row = VdomUtil.clone({cls: gridRows[index].cls, cn: [cell]}); // clone to remove ids
73
+
74
+ row.style = {
75
+ height: view.rowHeight + 'px'
76
+ };
77
+
78
+ delete row.cn[0].style.left;
79
+
80
+ rows.push(row)
81
+ });
82
+
83
+ config.vdom =
84
+ {cn: [
85
+ {cls: ['neo-grid-container'], cn: [
86
+ {...config.vdom, cls: ['neo-grid-header-toolbar', 'neo-toolbar']},
87
+ {cls: ['neo-grid-view'], cn: rows}
88
+ ]}
89
+ ]};
90
+
91
+ if (createComponent) {
92
+ return me.dragProxy = Neo.create(config)
93
+ }
94
+
95
+ return config
96
+ }
97
+
40
98
  /**
41
99
  * @param {Number} fromIndex
42
100
  * @param {Number} toIndex
@@ -69,6 +127,59 @@ class SortZone extends BaseSortZone {
69
127
 
70
128
  owner.parent.view.createViewData()
71
129
  }
130
+
131
+ /**
132
+ * @param {Object} data
133
+ */
134
+ async onDragStart(data) {
135
+ await super.onDragStart(data);
136
+
137
+ if (this.moveColumnContent) {
138
+ let me = this,
139
+ {view} = me.owner.parent,
140
+ columnIndex = me.dragElement['aria-colindex'] - 1,
141
+ {dataField} = view.columnPositions[columnIndex],
142
+ cells = view.getColumnCells(dataField);
143
+
144
+ cells.forEach(cell => {
145
+ cell.style.display = 'none'
146
+ });
147
+
148
+ view.update()
149
+ }
150
+ }
151
+
152
+ /**
153
+ * @param {Number} index1
154
+ * @param {Number} index2
155
+ */
156
+ switchItems(index1, index2) {
157
+ if (this.moveColumnContent) {
158
+ let {view} = this.owner.parent,
159
+ columnPositions = view._columnPositions, // no clone
160
+ column1Cells = view.getColumnCells(columnPositions[index1].dataField),
161
+ column2Cells = view.getColumnCells(columnPositions[index2].dataField),
162
+ x;
163
+
164
+ x = columnPositions[index1].x;
165
+ columnPositions[index1].x = columnPositions[index2].x;
166
+ columnPositions[index2].x = x;
167
+
168
+ NeoArray.move(columnPositions, index1, index2);
169
+
170
+ column1Cells.forEach(node => {
171
+ node.style.left = columnPositions[index2].x + 'px'
172
+ });
173
+
174
+ column2Cells.forEach(node => {
175
+ node.style.left = columnPositions[index1].x + 'px'
176
+ });
177
+
178
+ view.update()
179
+ }
180
+
181
+ super.switchItems(index1, index2);
182
+ }
72
183
  }
73
184
 
74
185
  export default Neo.setupClass(SortZone);
@@ -114,12 +114,12 @@ class DragZone extends BaseDragZone {
114
114
  /**
115
115
  * @param {Object} data
116
116
  */
117
- onDragStart(data) {
117
+ async onDragStart(data) {
118
118
  let me = this;
119
119
 
120
120
  if (me.owner.draggable) {
121
121
  me.dragElement = VDomUtil.find(me.owner.vdom, data.path[0].id).vdom;
122
- me.dragStart(data)
122
+ await me.dragStart(data)
123
123
  }
124
124
  }
125
125
 
@@ -53,7 +53,7 @@ class SortZone extends BaseSortZone {
53
53
  /**
54
54
  * @param {Object} data
55
55
  */
56
- onDragStart(data) {
56
+ async onDragStart(data) {
57
57
  let me = this,
58
58
  {owner} = me,
59
59
  cls = owner.cls || [];
@@ -61,7 +61,7 @@ class SortZone extends BaseSortZone {
61
61
  NeoArray.add(cls, 'neo-no-animation');
62
62
  owner.cls = cls;
63
63
 
64
- super.onDragStart(data)
64
+ await super.onDragStart(data)
65
65
  }
66
66
  }
67
67
 
@@ -52,7 +52,7 @@ class DragZone extends BaseDragZone {
52
52
  owner.items.forEach(item => {
53
53
  wrapperCls = item.wrapperCls || [];
54
54
 
55
- NeoArray[draggable ? 'add' : 'remove'](wrapperCls, 'neo-draggable');
55
+ NeoArray.toggle(wrapperCls, 'neo-draggable', draggable);
56
56
  item.wrapperCls = wrapperCls
57
57
  })
58
58
  }
@@ -88,12 +88,12 @@ class DragZone extends BaseDragZone {
88
88
  /**
89
89
  * @param {Object} data
90
90
  */
91
- onDragStart(data) {
91
+ async onDragStart(data) {
92
92
  let me = this;
93
93
 
94
94
  if (me.owner.draggable) {
95
95
  me.dragElement = VDomUtil.find(me.owner.vdom, data.path[0].id).vdom;
96
- me.dragStart(data)
96
+ await me.dragStart(data)
97
97
  }
98
98
  }
99
99
 
@@ -178,7 +178,7 @@ class SortZone extends DragZone {
178
178
  /**
179
179
  * @param {Object} data
180
180
  */
181
- onDragStart(data) {
181
+ async onDragStart(data) {
182
182
  let me = this,
183
183
  button = Neo.getComponent(data.path[0].id),
184
184
  {owner} = me,
@@ -202,7 +202,7 @@ class SortZone extends DragZone {
202
202
  startIndex : index
203
203
  });
204
204
 
205
- me.dragStart(data); // we do not want to trigger the super class call here
205
+ await me.dragStart(data); // we do not want to trigger the super class call here
206
206
 
207
207
  owner.items.forEach((item, index) => {
208
208
  indexMap[index] = index;
@@ -81,7 +81,7 @@ class DragZone extends BaseDragZone {
81
81
  /**
82
82
  * @param {Object} data
83
83
  */
84
- onDragStart(data) {
84
+ async onDragStart(data) {
85
85
  let me = this;
86
86
 
87
87
  if (me.owner.draggable) {
@@ -91,7 +91,7 @@ class DragZone extends BaseDragZone {
91
91
  cn : [VDomUtil.find(me.owner.vdom, data.path[0].id).vdom]
92
92
  };
93
93
 
94
- me.dragStart(data)
94
+ await me.dragStart(data)
95
95
  }
96
96
  }
97
97
  }
@@ -70,11 +70,6 @@ class GridContainer extends BaseContainer {
70
70
  * @member {Number} rowHeight_=32
71
71
  */
72
72
  rowHeight_: 32,
73
- /**
74
- * @member {String|null} scrollbarId_=null
75
- * @protected
76
- */
77
- scrollbarId_: null,
78
73
  /**
79
74
  * @member {Boolean} showHeaderFilters_=false
80
75
  */
@@ -125,14 +120,6 @@ class GridContainer extends BaseContainer {
125
120
  return Neo.getComponent(this.headerToolbarId) || Neo.get(this.headerToolbarId)
126
121
  }
127
122
 
128
- /**
129
- * Convenience method to access the Neo.grid.Scrollbar
130
- * @returns {Neo.grid.Scrollbar|null}
131
- */
132
- get scrollbar() {
133
- return Neo.getComponent(this.scrollbarId) || Neo.get(this.scrollbarId)
134
- }
135
-
136
123
  /**
137
124
  * Convenience method to access the Neo.grid.View
138
125
  * @returns {Neo.grid.View|null}
@@ -151,20 +138,17 @@ class GridContainer extends BaseContainer {
151
138
  {rowHeight, store} = me;
152
139
 
153
140
  me.headerToolbarId = Neo.getId('grid-header-toolbar');
154
- me.scrollbarId = Neo.getId('grid-scrollbar');
155
141
  me.viewId = Neo.getId('grid-view');
156
142
 
157
143
  me.items = [{
158
144
  module : header.Toolbar,
159
- gridContainer : me,
160
145
  id : me.headerToolbarId,
161
146
  showHeaderFilters: me.showHeaderFilters,
162
147
  sortable : me.sortable,
163
148
  ...me.headerToolbarConfig
164
149
  }, {
165
- module : GridView,
166
- containerId: me.id,
167
- id : me.viewId,
150
+ module: GridView,
151
+ id : me.viewId,
168
152
  rowHeight,
169
153
  store,
170
154
  ...me.viewConfig
package/src/grid/View.mjs CHANGED
@@ -57,11 +57,6 @@ class GridView extends Component {
57
57
  * @member {String} colspanField='colspan'
58
58
  */
59
59
  colspanField: 'colspan',
60
- /**
61
- * @member {String|null} containerId=null
62
- * @protected
63
- */
64
- containerId: null,
65
60
  /**
66
61
  * Internal flag. Gets calculated after mounting grid.View rows
67
62
  * @member {Number} containerWidth_=0
@@ -139,13 +134,6 @@ class GridView extends Component {
139
134
  */
140
135
  scrollTimeoutId = null
141
136
 
142
- /**
143
- * @member {Neo.grid.Container|null} gridContainer
144
- */
145
- get gridContainer() {
146
- return Neo.getComponent(this.containerId)
147
- }
148
-
149
137
  /**
150
138
  * @member {String[]} selectedRows
151
139
  */
@@ -496,11 +484,12 @@ class GridView extends Component {
496
484
  rowIndex = this.store.indexOf(record)
497
485
  }
498
486
 
499
- let me = this,
500
- {bufferColumnRange, gridContainer, selectedRows, visibleColumns} = me,
501
- columns = gridContainer.items[0].items,
502
- id = me.getRowId(record, rowIndex),
503
- trCls = me.getTrClass(record, rowIndex),
487
+ let me = this,
488
+ {bufferColumnRange, selectedRows, visibleColumns} = me,
489
+ gridContainer = me.parent,
490
+ columns = gridContainer.headerToolbar.items,
491
+ id = me.getRowId(record, rowIndex),
492
+ trCls = me.getTrClass(record, rowIndex),
504
493
  config, column, endIndex, gridRow, i, startIndex;
505
494
 
506
495
  if (rowIndex % 2 !== 0) {
@@ -602,7 +591,7 @@ class GridView extends Component {
602
591
  dataField = me.getCellDataField(id),
603
592
  record = me.getRecord(id);
604
593
 
605
- me.gridContainer.fire(eventName, {data, dataField, record, view: me})
594
+ me.parent.fire(eventName, {data, dataField, record, view: me})
606
595
  }
607
596
 
608
597
  /**
@@ -614,7 +603,7 @@ class GridView extends Component {
614
603
  id = data.currentTarget,
615
604
  record = me.getRecord(id);
616
605
 
617
- me.gridContainer.fire(eventName, {data, record, view: me})
606
+ me.parent.fire(eventName, {data, record, view: me})
618
607
  }
619
608
 
620
609
  /**
@@ -641,10 +630,9 @@ class GridView extends Component {
641
630
  * @returns {Object|Number|null}
642
631
  */
643
632
  getColumn(field, returnIndex=false) {
644
- let {gridContainer} = this,
645
- columns = gridContainer.headerToolbar.items,
646
- i = 0,
647
- len = columns.length,
633
+ let columns = this.parent.headerToolbar.items,
634
+ i = 0,
635
+ len = columns.length,
648
636
  column;
649
637
 
650
638
  for (; i < len; i++) {
@@ -658,6 +646,35 @@ class GridView extends Component {
658
646
  return null
659
647
  }
660
648
 
649
+ /**
650
+ * Get all painted column cells (visible + buffer range)
651
+ * @param {String} dataField
652
+ * @returns {Object[]}
653
+ */
654
+ getColumnCells(dataField) {
655
+ let me = this,
656
+ cells = [],
657
+ vdomRoot = me.getVdomRoot(),
658
+ firstRow = vdomRoot.cn[0],
659
+ i = 0,
660
+ len = firstRow.cn.length,
661
+ columnIndex;
662
+
663
+ // Columns might get moved via drag&drop, so let's check for the current match
664
+ for (; i < len; i++) {
665
+ if (dataField === me.getDataField(firstRow.cn[i].id)) {
666
+ columnIndex = i;
667
+ break;
668
+ }
669
+ }
670
+
671
+ vdomRoot.cn.forEach(row => {
672
+ cells.push(row.cn[columnIndex])
673
+ });
674
+
675
+ return cells
676
+ }
677
+
661
678
  /**
662
679
  * @param {String} cellId
663
680
  * @returns {String}
@@ -819,7 +836,7 @@ class GridView extends Component {
819
836
  let me = this,
820
837
  fieldNames = fields.map(field => field.name),
821
838
  needsUpdate = false,
822
- {gridContainer} = me,
839
+ gridContainer = me.parent,
823
840
  rowIndex = me.store.indexOf(record),
824
841
  {selectionModel, vdom} = me,
825
842
  cellId, cellNode, cellStyle, cellVdom, column, columnIndex;
@@ -1,5 +1,4 @@
1
1
  import BaseToolbar from '../../toolbar/Base.mjs';
2
- import NeoArray from '../../util/Array.mjs';
3
2
 
4
3
  /**
5
4
  * @class Neo.grid.header.Toolbar
@@ -25,10 +24,6 @@ class Toolbar extends BaseToolbar {
25
24
  * @member {Boolean} draggable_=true
26
25
  */
27
26
  draggable_: true,
28
- /**
29
- * @member {Neo.grid.Container|null} gridContainer=null
30
- */
31
- gridContainer: null,
32
27
  /**
33
28
  * @member {Object} itemDefaults={ntype: 'grid-header-button'}
34
29
  */
@@ -188,9 +183,10 @@ class Toolbar extends BaseToolbar {
188
183
  */
189
184
  async passSizeToView(silent=false) {
190
185
  let me = this,
191
- rects = await me.getDomRect(me.items.map(item => item.id)),
186
+ {items} = me,
187
+ rects = await me.getDomRect(items.map(item => item.id)),
192
188
  lastItem = rects[rects.length - 1],
193
- columnPositions = rects.map(item => ({width: item.width, x: item.x - rects[0].x})),
189
+ columnPositions = rects.map((item, index) => ({dataField: items[index].dataField, width: item.width, x: item.x - rects[0].x})),
194
190
  i = 1,
195
191
  len = columnPositions.length,
196
192
  layoutFinished = true;
@@ -208,7 +204,7 @@ class Toolbar extends BaseToolbar {
208
204
  await me.timeout(100);
209
205
  await me.passSizeToView(silent)
210
206
  } else {
211
- me.gridContainer.view[silent ? 'setSilent' : 'set']({
207
+ me.parent.view[silent ? 'setSilent' : 'set']({
212
208
  availableWidth: lastItem.x + lastItem.width - rects[0].x,
213
209
  columnPositions
214
210
  })
@@ -29,7 +29,7 @@ class RowModel extends BaseModel {
29
29
  addDomListener() {
30
30
  let me = this;
31
31
 
32
- me.view.gridContainer.on('rowClick', me.onRowClick, me)
32
+ me.view.parent.on('rowClick', me.onRowClick, me)
33
33
  }
34
34
 
35
35
  /**
@@ -38,7 +38,7 @@ class RowModel extends BaseModel {
38
38
  destroy(...args) {
39
39
  let me = this;
40
40
 
41
- me.view.gridContainer.un('rowClick', me.onRowClick, me);
41
+ me.view.parent.un('rowClick', me.onRowClick, me);
42
42
 
43
43
  super.destroy(...args)
44
44
  }