neo.mjs 8.24.0 → 8.26.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.24.0'
23
+ * @member {String} version='8.26.0'
24
24
  */
25
- version: '8.24.0'
25
+ version: '8.26.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-02-24",
19
+ "datePublished": "2025-02-26",
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.24.0'
110
+ html : 'v8.26.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.24.0'
23
+ * @member {String} version='8.26.0'
24
24
  */
25
- version: '8.24.0'
25
+ version: '8.26.0'
26
26
  }
27
27
 
28
28
  /**
@@ -28,8 +28,9 @@ class ControlsContainer extends Container {
28
28
  handler: 'up.onControlsToggleButtonClick',
29
29
  iconCls: 'fas fa-bars'
30
30
  }, {
31
- module: TabContainer,
32
- cls : ['neo-examples-bigdata-controls-container-content'],
31
+ module : TabContainer,
32
+ cls : ['neo-examples-bigdata-controls-container-content'],
33
+ sortable: true,
33
34
 
34
35
  items: [{
35
36
  module: Container,
@@ -1,8 +1,6 @@
1
1
  import BaseGridContainer from '../../../src/grid/Container.mjs';
2
2
  import MainStore from './MainStore.mjs';
3
3
 
4
- import * as selection from '../../../src/selection/grid/_export.mjs';
5
-
6
4
  /**
7
5
  * @class Neo.examples.grid.bigData.GridContainer
8
6
  * @extends Neo.grid.Container
@@ -35,7 +33,6 @@ class GridContainer extends BaseGridContainer {
35
33
  * @member {Object} viewConfig
36
34
  */
37
35
  viewConfig: {
38
- selectionModel: selection.CellModel, // todo: remove after #6491 is resolved
39
36
  bufferColumnRange: 3,
40
37
  bufferRowRange : 5
41
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo.mjs",
3
- "version": "8.24.0",
3
+ "version": "8.26.0",
4
4
  "description": "The webworkers driven UI framework",
5
5
  "type": "module",
6
6
  "repository": {
@@ -62,7 +62,7 @@
62
62
  "neo-jsdoc": "1.0.1",
63
63
  "neo-jsdoc-x": "1.0.5",
64
64
  "postcss": "^8.5.3",
65
- "sass": "^1.85.0",
65
+ "sass": "^1.85.1",
66
66
  "siesta-lite": "5.5.2",
67
67
  "url": "^0.11.4",
68
68
  "webpack": "^5.98.0",
@@ -106,9 +106,9 @@
106
106
  }
107
107
 
108
108
  &:active {
109
- background-color: var(--button-background-color-active) !important;
110
- background-image: none !important;
111
- border : var(--button-border-active) !important;
109
+ background-color: var(--button-background-color-active);
110
+ background-image: none;
111
+ border : var(--button-border-active);
112
112
 
113
113
  .neo-button-glyph {
114
114
  color: var(--button-glyph-color-active);
@@ -0,0 +1,21 @@
1
+ .neo-grid-vertical-scrollbar {
2
+ bottom : 1px;
3
+ opacity : 0;
4
+ overflow-y: scroll;
5
+ position : absolute;
6
+ right : 0;
7
+ top : 31px; // header-toolbar height
8
+ transition: opacity 1s ease-out;
9
+ width : 16px;
10
+ z-index : 2;
11
+
12
+ &:hover {
13
+ opacity: 1;
14
+ }
15
+ }
16
+
17
+ .neo-grid-wrapper:has(.neo-grid-view.neo-is-scrolling) {
18
+ .neo-grid-vertical-scrollbar {
19
+ opacity: 1;
20
+ }
21
+ }
@@ -31,9 +31,4 @@
31
31
  border : var(--tab-container-content-border);
32
32
  overflow: hidden;
33
33
  }
34
-
35
- .neo-tab-header-toolbar {
36
- background-color: transparent;
37
- padding : 0;
38
- }
39
34
  }
@@ -263,12 +263,12 @@ const DefaultConfig = {
263
263
  useVdomWorker: true,
264
264
  /**
265
265
  * buildScripts/injectPackageVersion.mjs will update this value
266
- * @default '8.24.0'
266
+ * @default '8.26.0'
267
267
  * @memberOf! module:Neo
268
268
  * @name config.version
269
269
  * @type String
270
270
  */
271
- version: '8.24.0'
271
+ version: '8.26.0'
272
272
  };
273
273
 
274
274
  Object.assign(DefaultConfig, {
@@ -2401,7 +2401,7 @@ class Component extends Base {
2401
2401
  /**
2402
2402
  * Change multiple configs at once, ensuring that all afterSet methods get all new assigned values
2403
2403
  * @param {Object} values={}
2404
- * @param {Boolean} [silent=false]
2404
+ * @param {Boolean} silent=false
2405
2405
  * @returns {Promise<*>}
2406
2406
  */
2407
2407
  set(values={}, silent=false) {
@@ -18,6 +18,10 @@ class SortZone extends BaseSortZone {
18
18
  * @protected
19
19
  */
20
20
  ntype: 'grid-header-toolbar-sortzone',
21
+ /**
22
+ * @member {Boolean} adjustItemRectsToParent=false
23
+ */
24
+ adjustItemRectsToParent: false,
21
25
  /**
22
26
  * @member {String|null} itemMargin='1px'
23
27
  * @protected
@@ -96,7 +100,7 @@ class SortZone extends BaseSortZone {
96
100
  mounted() {
97
101
  Neo.main.DomAccess.scrollTo({
98
102
  id : viewWrapperId,
99
- value : view.scrollPosition.y,
103
+ value : view.scrollTop,
100
104
  windowId: this.windowId
101
105
  })
102
106
  }
@@ -17,6 +17,13 @@ class SortZone extends DragZone {
17
17
  * @protected
18
18
  */
19
19
  ntype: 'toolbar-sortzone',
20
+ /**
21
+ * Depending on the parent structure using position absolute and relative, it can be needed to subtract
22
+ * the x & y parent rect values from the item rects.
23
+ * For tab.header.Toolbar it is needed, for grid.header.Toolbar it is not
24
+ * @member {Boolean} adjustItemRectsToParent=true
25
+ */
26
+ adjustItemRectsToParent: true,
20
27
  /**
21
28
  * @member {Boolean} alwaysFireDragMove=true
22
29
  */
@@ -161,22 +168,25 @@ class SortZone extends DragZone {
161
168
  return
162
169
  }
163
170
 
164
- let me = this,
165
- index = me.currentIndex,
166
- {itemRects} = me,
167
- maxItems = itemRects.length - 1,
168
- reversed = me.reversedLayoutDirection,
171
+ let me = this,
172
+ {clientX, clientY} = data,
173
+ index = me.currentIndex,
174
+ {itemRects} = me,
175
+ maxItems = itemRects.length - 1,
176
+ ownerX = me.adjustItemRectsToParent ? me.ownerRect.x : 0,
177
+ ownerY = me.adjustItemRectsToParent ? me.ownerRect.y : 0,
178
+ reversed = me.reversedLayoutDirection,
169
179
  delta, isOverDragging, isOverDraggingEnd, isOverDraggingStart, itemHeightOrWidth, moveFactor;
170
180
 
171
181
  if (me.sortDirection === 'horizontal') {
172
- delta = data.clientX + me.scrollLeft - me.offsetX - itemRects[index].left;
173
- isOverDraggingEnd = data.clientX > me.boundaryContainerRect.right;
174
- isOverDraggingStart = data.clientX < me.boundaryContainerRect.left;
182
+ delta = clientX - ownerX + me.scrollLeft - me.offsetX - itemRects[index].left;
183
+ isOverDraggingEnd = clientX > me.boundaryContainerRect.right;
184
+ isOverDraggingStart = clientX < me.boundaryContainerRect.left;
175
185
  itemHeightOrWidth = 'width'
176
186
  } else {
177
- delta = data.clientY + me.scrollTop - me.offsetY - itemRects[index].top;
178
- isOverDraggingEnd = data.clientY > me.boundaryContainerRect.bottom;
179
- isOverDraggingStart = data.clientY < me.boundaryContainerRect.top;
187
+ delta = clientY - ownerY + me.scrollTop - me.offsetY - itemRects[index].top;
188
+ isOverDraggingEnd = clientY > me.boundaryContainerRect.bottom;
189
+ isOverDraggingStart = clientY < me.boundaryContainerRect.top;
180
190
  itemHeightOrWidth = 'height'
181
191
  }
182
192
 
@@ -243,11 +253,11 @@ class SortZone extends DragZone {
243
253
  Object.assign(me, {
244
254
  currentIndex : index,
245
255
  dragElement : VDomUtil.find(owner.vdom, button.id).vdom,
246
- dragProxyConfig : {...me.dragProxyConfig, cls : [...owner.cls]},
256
+ dragProxyConfig : {...me.dragProxyConfig, cls: [...owner.cls]},
247
257
  indexMap : indexMap,
248
- ownerStyle : {height: ownerStyle.height, width : ownerStyle.width},
258
+ ownerStyle : {height: ownerStyle.height, width: ownerStyle.width},
249
259
  reversedLayoutDirection: layout.direction === 'column-reverse' || layout.direction === 'row-reverse',
250
- sortDirection : owner.layout.ntype === 'layout-vbox' ? 'vertical' : 'horizontal',
260
+ sortDirection : layout.direction.includes('row') ? 'horizontal' : 'vertical',
251
261
  startIndex : index
252
262
  });
253
263
 
@@ -273,6 +283,12 @@ class SortZone extends DragZone {
273
283
  owner.style = ownerStyle;
274
284
 
275
285
  itemRects.shift();
286
+
287
+ me.adjustItemRectsToParent && itemRects.forEach(rect => {
288
+ rect.x -= me.ownerRect.x;
289
+ rect.y -= me.ownerRect.y
290
+ });
291
+
276
292
  me.itemRects = itemRects;
277
293
 
278
294
  owner.items.forEach((item, index) => {
@@ -1,9 +1,10 @@
1
- import BaseContainer from '../container/Base.mjs';
2
- import ClassSystemUtil from '../util/ClassSystem.mjs';
3
- import GridScrollbar from './Scrollbar.mjs';
4
- import GridView from './View.mjs';
5
- import Store from '../data/Store.mjs';
6
- import * as header from './header/_export.mjs';
1
+ import BaseContainer from '../container/Base.mjs';
2
+ import ClassSystemUtil from '../util/ClassSystem.mjs';
3
+ import GridView from './View.mjs';
4
+ import ScrollManager from './ScrollManager.mjs';
5
+ import Store from '../data/Store.mjs';
6
+ import VerticalScrollbar from './VerticalScrollbar.mjs';
7
+ import * as header from './header/_export.mjs';
7
8
 
8
9
  /**
9
10
  * @class Neo.grid.Container
@@ -119,17 +120,10 @@ class GridContainer extends BaseContainer {
119
120
  */
120
121
  initialResizeEvent = true
121
122
  /**
122
- * Flag for identifying the ownership of a touchmove operation
123
- * @member {Boolean} isTouchMoveOwner=false
123
+ * @member {Neo.grid.ScrollManager|null} scrollManager=null
124
124
  * @protected
125
125
  */
126
- isTouchMoveOwner = false
127
- /**
128
- * Storing touchmove position for mobile envs
129
- * @member {Number} lastTouchY=0
130
- * @protected
131
- */
132
- lastTouchY = 0
126
+ scrollManager = null
133
127
 
134
128
  /**
135
129
  * Convenience method to access the Neo.grid.header.Toolbar
@@ -176,7 +170,7 @@ class GridContainer extends BaseContainer {
176
170
  }];
177
171
 
178
172
  me.scrollbar = Neo.create({
179
- module : GridScrollbar,
173
+ module : VerticalScrollbar,
180
174
  appName,
181
175
  parentId: me.id,
182
176
  rowHeight,
@@ -192,7 +186,6 @@ class GridContainer extends BaseContainer {
192
186
 
193
187
  me.addDomListeners({
194
188
  resize: me.onResize,
195
- scroll: me.onScroll,
196
189
  scope : me
197
190
  })
198
191
  }
@@ -475,6 +468,8 @@ class GridContainer extends BaseContainer {
475
468
  destroy(...args) {
476
469
  let me = this;
477
470
 
471
+ me.scrollManager.destroy();
472
+
478
473
  me.mounted && Neo.main.addon.ResizeObserver.unregister({
479
474
  id : me.id,
480
475
  windowId: me.windowId
@@ -513,6 +508,21 @@ class GridContainer extends BaseContainer {
513
508
  return `${this.id}__wrapper`
514
509
  }
515
510
 
511
+ /**
512
+ *
513
+ */
514
+ onConstructed() {
515
+ super.onConstructed();
516
+
517
+ let me = this;
518
+
519
+ me.scrollManager = Neo.create({
520
+ module : ScrollManager,
521
+ gridContainer: me,
522
+ gridView : me.view
523
+ })
524
+ }
525
+
516
526
  /**
517
527
  * @param {Object} data
518
528
  */
@@ -530,44 +540,6 @@ class GridContainer extends BaseContainer {
530
540
  }
531
541
  }
532
542
 
533
- /**
534
- * @param {Object} data
535
- * @param {Number} data.scrollLeft
536
- * @param {Object} data.target
537
- * @param {Object} data.touches
538
- */
539
- onScroll({scrollLeft, target, touches}) {
540
- let me = this,
541
- {view} = me,
542
- deltaY, lastTouchY;
543
-
544
- // We must ignore events for grid-scrollbar
545
- if (target.id.includes('grid-container')) {
546
- me.headerToolbar.scrollLeft = scrollLeft;
547
- view.scrollPosition = {x: scrollLeft, y: view.scrollPosition.y};
548
-
549
- if (touches) {
550
- if (!view.isTouchMoveOwner) {
551
- me.isTouchMoveOwner = true
552
- }
553
-
554
- if (me.isTouchMoveOwner) {
555
- lastTouchY = touches.lastTouch.clientY - touches.firstTouch.clientY;
556
- deltaY = me.lastTouchY - lastTouchY;
557
-
558
- deltaY !== 0 && Neo.main.DomAccess.scrollTo({
559
- direction: 'top',
560
- id : view.vdom.id,
561
- value : view.scrollPosition.y + deltaY
562
- })
563
-
564
- me.lastTouchY = lastTouchY
565
- }
566
- }
567
-
568
- }
569
- }
570
-
571
543
  /**
572
544
  * @param {Object} opts
573
545
  * @param {String} opts.direction
@@ -670,7 +642,7 @@ class GridContainer extends BaseContainer {
670
642
  {columnPositions, containerWidth, mountedColumns, visibleColumns} = view,
671
643
  countColumns = columnPositions.getCount(),
672
644
  newIndex = index + step,
673
- column, mounted, scrollPosition, visible;
645
+ column, mounted, scrollLeft, visible;
674
646
 
675
647
  if (newIndex >= countColumns) {
676
648
  newIndex %= countColumns;
@@ -697,15 +669,15 @@ class GridContainer extends BaseContainer {
697
669
  column = columnPositions.getAt(newIndex);
698
670
 
699
671
  if (step < 0) {
700
- scrollPosition = column.x
672
+ scrollLeft = column.x
701
673
  } else {
702
- scrollPosition = column.x - containerWidth + column.width
674
+ scrollLeft = column.x - containerWidth + column.width
703
675
  }
704
676
 
705
677
  Neo.main.DomAccess.scrollTo({
706
678
  direction: 'left',
707
679
  id : me.id,
708
- value : scrollPosition,
680
+ value : scrollLeft,
709
681
  windowId : me.windowId
710
682
  })
711
683
  }
@@ -0,0 +1,179 @@
1
+ import Base from '../core/Base.mjs';
2
+
3
+ /**
4
+ * @class Neo.grid.ScrollManager
5
+ * @extends Neo.core.Base
6
+ */
7
+ class ScrollManager extends Base {
8
+ static config = {
9
+ /**
10
+ * @member {String} className='Neo.grid.ScrollManager'
11
+ * @protected
12
+ */
13
+ className: 'Neo.grid.ScrollManager',
14
+ /**
15
+ * @member {Number} scrollLeft_=0
16
+ * @protected
17
+ */
18
+ scrollLeft_: 0,
19
+ /**
20
+ * @member {Number} scrollTop_=0
21
+ * @protected
22
+ */
23
+ scrollTop_: 0
24
+ }
25
+
26
+ /**
27
+ * @member {Neo.grid.Container|null} gridContainer=null
28
+ * @protected
29
+ */
30
+ gridContainer = null
31
+ /**
32
+ * @member {Neo.grid.View|null} gridView=null
33
+ * @protected
34
+ */
35
+ gridView = null
36
+ /**
37
+ * Storing touchmove position for mobile envs
38
+ * @member {Number} lastTouchX=0
39
+ * @protected
40
+ */
41
+ lastTouchX = 0
42
+ /**
43
+ * Storing touchmove position for mobile envs
44
+ * @member {Number} lastTouchY=0
45
+ * @protected
46
+ */
47
+ lastTouchY = 0
48
+ /**
49
+ * @member {Number|null}} scrollTimeoutId=null
50
+ * @protected
51
+ */
52
+ scrollTimeoutId = null
53
+ /**
54
+ * Flag for identifying the ownership of a touchmove operation
55
+ * @member {'container'|'view'|null} touchMoveOwner=null
56
+ * @protected
57
+ */
58
+ touchMoveOwner = null
59
+
60
+ /**
61
+ * @param {Object} config
62
+ */
63
+ construct(config) {
64
+ super.construct(config);
65
+
66
+ let me = this;
67
+
68
+ me.gridContainer.addDomListeners({
69
+ scroll: me.onContainerScroll,
70
+ scope : me
71
+ });
72
+
73
+ me.gridView.addDomListeners({
74
+ scroll : me.onViewScroll,
75
+ touchcancel: me.onTouchCancel,
76
+ touchend : me.onTouchEnd,
77
+ scope : me
78
+ })
79
+ }
80
+
81
+ /**
82
+ * @param {Object} data
83
+ * @param {Number} data.scrollLeft
84
+ * @param {Object} data.target
85
+ * @param {Object} data.touches
86
+ */
87
+ onContainerScroll({scrollLeft, target, touches}) {
88
+ let me = this,
89
+ view = me.gridView,
90
+ deltaY, lastTouchY;
91
+
92
+ // We must ignore events for grid-scrollbar
93
+ if (target.id.includes('grid-container')) {
94
+ me .scrollLeft = scrollLeft;
95
+ view.scrollLeft = scrollLeft;
96
+
97
+ me.gridContainer.headerToolbar.scrollLeft = scrollLeft;
98
+
99
+ if (touches) {
100
+ if (me.touchMoveOwner !== 'view') {
101
+ me.touchMoveOwner = 'container'
102
+ }
103
+
104
+ if (me.touchMoveOwner === 'container') {
105
+ lastTouchY = touches.lastTouch.clientY - touches.firstTouch.clientY;
106
+ deltaY = me.lastTouchY - lastTouchY;
107
+
108
+ deltaY !== 0 && Neo.main.DomAccess.scrollTo({
109
+ direction: 'top',
110
+ id : view.vdom.id,
111
+ value : me.scrollTop + deltaY
112
+ })
113
+
114
+ me.lastTouchY = lastTouchY
115
+ }
116
+ }
117
+ }
118
+ }
119
+
120
+ /**
121
+ * @param {Object} data
122
+ */
123
+ onTouchCancel(data) {
124
+ this.onTouchEnd(data)
125
+ }
126
+
127
+ /**
128
+ * @param {Object} data
129
+ */
130
+ onTouchEnd(data) {
131
+ let me = this;
132
+
133
+ me.touchMoveOwner = null;
134
+ me.lastTouchX = 0;
135
+ me.lastTouchY = 0
136
+ }
137
+
138
+ /**
139
+ * Only triggers for vertical scrolling
140
+ * @param {Object} data
141
+ * @protected
142
+ */
143
+ onViewScroll({scrollTop, touches}) {
144
+ let me = this,
145
+ view = me.gridView,
146
+ deltaX, lastTouchX;
147
+
148
+ me.scrollTop = scrollTop;
149
+
150
+ me.scrollTimeoutId && clearTimeout(me.scrollTimeoutId);
151
+
152
+ me.scrollTimeoutId = setTimeout(() => {
153
+ view.isScrolling = false
154
+ }, 30);
155
+
156
+ view.set({isScrolling: true, scrollTop});
157
+
158
+ if (touches) {
159
+ if (me.touchMoveOwner !== 'container') {
160
+ me.touchMoveOwner = 'view'
161
+ }
162
+
163
+ if (me.touchMoveOwner === 'view') {
164
+ lastTouchX = touches.lastTouch.clientX - touches.firstTouch.clientX;
165
+ deltaX = me.lastTouchX - lastTouchX;
166
+
167
+ deltaX !== 0 && Neo.main.DomAccess.scrollTo({
168
+ direction: 'left',
169
+ id : me.gridContainer.id,
170
+ value : me.scrollLeft + deltaX
171
+ })
172
+
173
+ me.lastTouchX = lastTouchX
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ export default Neo.setupClass(ScrollManager);
@@ -1,26 +1,28 @@
1
1
  import Component from '../component/Base.mjs';
2
2
 
3
3
  /**
4
- * @class Neo.grid.Scrollbar
4
+ * We do not want to use the default scrollbar for vertical scrolling, since it would show up at the right edge
5
+ * of the last column. Instead, we want to show it at the right edge of the container (always visible when scrolling).
6
+ * @class Neo.grid.VerticalScrollbar
5
7
  * @extends Neo.component.Base
6
8
  */
7
- class GridScrollbar extends Component {
9
+ class VerticalScrollbar extends Component {
8
10
  static config = {
9
11
  /**
10
- * @member {String} className='Neo.grid.Scrollbar'
12
+ * @member {String} className='Neo.grid.VerticalScrollbar'
11
13
  * @protected
12
14
  */
13
- className: 'Neo.grid.Scrollbar',
15
+ className: 'Neo.grid.VerticalScrollbar',
14
16
  /**
15
- * @member {String} ntype='grid-scrollbar'
17
+ * @member {String} ntype='grid-vertical-scrollbar'
16
18
  * @protected
17
19
  */
18
- ntype: 'grid-scrollbar',
20
+ ntype: 'grid-vertical-scrollbar',
19
21
  /**
20
- * @member {String[]} baseCls=['neo-grid-scrollbar']
22
+ * @member {String[]} baseCls=['neo-grid-vertical-scrollbar']
21
23
  * @protected
22
24
  */
23
- baseCls: ['neo-grid-scrollbar'],
25
+ baseCls: ['neo-grid-vertical-scrollbar'],
24
26
  /**
25
27
  * Number in px
26
28
  * @member {Number} rowHeight_=0
@@ -116,4 +118,4 @@ class GridScrollbar extends Component {
116
118
  }
117
119
  }
118
120
 
119
- export default Neo.setupClass(GridScrollbar);
121
+ export default Neo.setupClass(VerticalScrollbar);
package/src/grid/View.mjs CHANGED
@@ -103,9 +103,15 @@ class GridView extends Component {
103
103
  */
104
104
  rowHeight_: 0,
105
105
  /**
106
- * @member {Object} scrollPosition_={x:0,y:0}
106
+ * @member {Number} scrollLeft_=0
107
+ * @protected
108
+ */
109
+ scrollLeft_: 0,
110
+ /**
111
+ * @member {Number} scrollTop_=0
112
+ * @protected
107
113
  */
108
- scrollPosition_: {x: 0, y: 0},
114
+ scrollTop_: 0,
109
115
  /**
110
116
  * @member {Neo.selection.Model} selectionModel_=null
111
117
  */
@@ -142,28 +148,11 @@ class GridView extends Component {
142
148
  * @member {Object} _vdom
143
149
  */
144
150
  _vdom:
145
- {tabIndex: '-1', cn: [
146
- {cn: []}
147
- ]}
151
+ {tabIndex: '-1', cn: [
152
+ {cn: []}
153
+ ]}
148
154
  }
149
155
 
150
- /**
151
- * Flag for identifying the ownership of a touchmove operation
152
- * @member {Boolean} isTouchMoveOwner=false
153
- * @protected
154
- */
155
- isTouchMoveOwner = false
156
- /**
157
- * Storing touchmove position for mobile envs
158
- * @member {Number} lastTouchX=0
159
- * @protected
160
- */
161
- lastTouchX = 0
162
- /**
163
- * @member {Number|null}} scrollTimeoutId=null
164
- */
165
- scrollTimeoutId = null
166
-
167
156
  /**
168
157
  * @member {String[]} selectedRows
169
158
  */
@@ -199,11 +188,6 @@ class GridView extends Component {
199
188
  let me = this;
200
189
 
201
190
  me.addDomListeners([{
202
- scroll : me.onScroll,
203
- touchcancel: me.onTouchCancel,
204
- touchend : me.onTouchEnd,
205
- scope : me
206
- }, {
207
191
  click : me.onCellClick,
208
192
  dblclick: me.onCellDoubleClick,
209
193
  delegate: '.neo-grid-cell',
@@ -328,29 +312,31 @@ class GridView extends Component {
328
312
  }
329
313
 
330
314
  /**
331
- * Triggered after the scrollPosition config got changed
332
- * @param {Object} value
333
- * @param {Object} oldValue
315
+ * Triggered after the scrollLeft config got changed
316
+ * @param {Number} value
317
+ * @param {Number} oldValue
318
+ * @protected
319
+ */
320
+ afterSetScrollLeft(value, oldValue) {
321
+ this.updateMountedAndVisibleColumns()
322
+ }
323
+
324
+ /**
325
+ * Triggered after the scrollTop config got changed
326
+ * @param {Number} value
327
+ * @param {Number} oldValue
334
328
  * @protected
335
329
  */
336
- afterSetScrollPosition(value, oldValue) {
330
+ afterSetScrollTop(value, oldValue) {
337
331
  let me = this,
338
332
  {bufferRowRange} = me,
339
- newStartIndex;
333
+ newStartIndex = Math.floor(value / me.rowHeight);
340
334
 
341
- if (value.x !== oldValue?.x) {
342
- me.updateMountedAndVisibleColumns()
343
- }
344
-
345
- if (value.y !== oldValue?.y) {
346
- newStartIndex = Math.floor(value.y / me.rowHeight);
347
-
348
- if (Math.abs(me.startIndex - newStartIndex) >= bufferRowRange) {
349
- me.startIndex = newStartIndex
350
- } else {
351
- me.visibleRows[0] = newStartIndex;
352
- me.visibleRows[1] = newStartIndex + me.availableRows
353
- }
335
+ if (Math.abs(me.startIndex - newStartIndex) >= bufferRowRange) {
336
+ me.startIndex = newStartIndex
337
+ } else {
338
+ me.visibleRows[0] = newStartIndex;
339
+ me.visibleRows[1] = newStartIndex + me.availableRows
354
340
  }
355
341
  }
356
342
 
@@ -861,46 +847,6 @@ class GridView extends Component {
861
847
  this.fireRowEvent(data, 'rowDoubleClick')
862
848
  }
863
849
 
864
- /**
865
- * Only triggers for vertical scrolling
866
- * @param {Object} data
867
- * @protected
868
- */
869
- onScroll({scrollTop, touches}) {
870
- let me = this,
871
- deltaX, lastTouchX;
872
-
873
- me.scrollTimeoutId && clearTimeout(me.scrollTimeoutId);
874
-
875
- me.scrollTimeoutId = setTimeout(() => {
876
- me.isScrolling = false
877
- }, 30);
878
-
879
- me.set({
880
- isScrolling : true,
881
- scrollPosition: {x: me.scrollPosition.x, y: scrollTop}
882
- });
883
-
884
- if (touches) {
885
- if (!me.parent.isTouchMoveOwner) {
886
- me.isTouchMoveOwner = true
887
- }
888
-
889
- if (me.isTouchMoveOwner) {
890
- lastTouchX = touches.lastTouch.clientX - touches.firstTouch.clientX;
891
- deltaX = me.lastTouchX - lastTouchX;
892
-
893
- deltaX !== 0 && Neo.main.DomAccess.scrollTo({
894
- direction: 'left',
895
- id : me.parent.id,
896
- value : me.scrollPosition.x + deltaX
897
- })
898
-
899
- me.lastTouchX = lastTouchX
900
- }
901
- }
902
- }
903
-
904
850
  /**
905
851
  * Gets triggered after changing the value of a record field.
906
852
  * E.g. myRecord.foo = 'bar';
@@ -954,34 +900,6 @@ class GridView extends Component {
954
900
  needsUpdate && me.update()
955
901
  }
956
902
 
957
- /**
958
- * @param {Object} data
959
- */
960
- onTouchCancel(data) {
961
- let me = this,
962
- {parent} = me;
963
-
964
- me.isTouchMoveOwner = false;
965
- me.lastTouchX = 0;
966
-
967
- parent.isTouchMoveOwner = false;
968
- parent.lastTouchY = 0
969
- }
970
-
971
- /**
972
- * @param {Object} data
973
- */
974
- onTouchEnd(data) {
975
- let me = this,
976
- {parent} = me;
977
-
978
- me.isTouchMoveOwner = false;
979
- me.lastTouchX = 0;
980
-
981
- parent.isTouchMoveOwner = false;
982
- parent.lastTouchY = 0
983
- }
984
-
985
903
  /**
986
904
  * Used for keyboard navigation (selection models)
987
905
  * @param {Number} index
@@ -992,7 +910,7 @@ class GridView extends Component {
992
910
  {mountedRows, visibleRows} = me,
993
911
  countRecords = me.store.getCount(),
994
912
  newIndex = index + step,
995
- lastRowGap, mounted, scrollPosition, visible;
913
+ lastRowGap, mounted, scrollTop, visible;
996
914
 
997
915
  if (newIndex >= countRecords) {
998
916
  newIndex %= countRecords;
@@ -1017,15 +935,15 @@ class GridView extends Component {
1017
935
  }
1018
936
 
1019
937
  if (step < 0) {
1020
- scrollPosition = newIndex * me.rowHeight
938
+ scrollTop = newIndex * me.rowHeight
1021
939
  } else {
1022
- lastRowGap = me.rowHeight - (me.availableHeight % me.rowHeight);
1023
- scrollPosition = (newIndex - me.availableRows) * me.rowHeight + lastRowGap
940
+ lastRowGap = me.rowHeight - (me.availableHeight % me.rowHeight);
941
+ scrollTop = (newIndex - me.availableRows) * me.rowHeight + lastRowGap
1024
942
  }
1025
943
 
1026
944
  Neo.main.DomAccess.scrollTo({
1027
945
  id : me.vdom.id,
1028
- value : scrollPosition,
946
+ value : scrollTop,
1029
947
  windowId: me.windowId
1030
948
  })
1031
949
  }
@@ -1037,10 +955,10 @@ class GridView extends Component {
1037
955
  updateMountedAndVisibleColumns() {
1038
956
  let me = this,
1039
957
  {bufferColumnRange, columnPositions, mountedColumns, visibleColumns} = me,
1040
- {x} = me.scrollPosition,
1041
958
  i = 0,
1042
959
  countColumns = columnPositions.getCount(),
1043
960
  endIndex = countColumns - 1,
961
+ x = me.scrollLeft,
1044
962
  column, startIndex;
1045
963
 
1046
964
  if (countColumns < 1) {
@@ -154,6 +154,37 @@ class Layout extends Base {
154
154
  container.wrapperCls = wrapperCls
155
155
  }
156
156
  }
157
+
158
+ /**
159
+ * Change multiple configs at once, ensuring that all afterSet methods get all new assigned values
160
+ * @param {Object} values={}
161
+ * @param {Boolean} silent=false
162
+ * @returns {Promise<*>}
163
+ */
164
+ set(values={}, silent=false) {
165
+ let me = this,
166
+ {container} = me;
167
+
168
+ container.silentVdomUpdate = true;
169
+
170
+ super.set(values);
171
+
172
+ container.silentVdomUpdate = false;
173
+
174
+ if (silent || !container.needsVdomUpdate) {
175
+ return Promise.resolve()
176
+ } else {
177
+ return container.promiseUpdate()
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Convenience shortcut calling set() with the silent flag
183
+ * @param {Object} values={}
184
+ */
185
+ setSilent(values={}) {
186
+ return this.set(values, true)
187
+ }
157
188
  }
158
189
 
159
190
  export default Neo.setupClass(Layout);
@@ -248,18 +248,10 @@ class Flexbox extends Base {
248
248
 
249
249
  NeoArray.remove(wrapperCls, prefix + 'container');
250
250
 
251
- if (me.align) {
252
- NeoArray.remove(wrapperCls, prefix + 'align-' + me.align)
253
- }
254
- if (me.direction) {
255
- NeoArray.remove(wrapperCls, prefix + 'direction-' + me.direction)
256
- }
257
- if (me.pack) {
258
- NeoArray.remove(wrapperCls, prefix + 'pack-' + me.pack)
259
- }
260
- if (me.wrap) {
261
- NeoArray.remove(wrapperCls, prefix + 'wrap-' + me.wrap)
262
- }
251
+ me.align && NeoArray.remove(wrapperCls, prefix + 'align-' + me.align);
252
+ me.direction && NeoArray.remove(wrapperCls, prefix + 'direction-' + me.direction);
253
+ me.pack && NeoArray.remove(wrapperCls, prefix + 'pack-' + me.pack);
254
+ me.wrap && NeoArray.remove(wrapperCls, prefix + 'wrap-' + me.wrap);
263
255
 
264
256
  container.wrapperCls = wrapperCls
265
257
  }
@@ -188,12 +188,14 @@ class Container extends BaseContainer {
188
188
 
189
189
  NeoArray.remove(cls, 'neo-' + oldValue);
190
190
  NeoArray.add(cls, 'neo-' + value);
191
- me.cls = cls;
191
+ me.setSilent({cls});
192
192
 
193
193
  if (me.rendered) {
194
- me.layout = me.getLayoutConfig();
195
- me.getTabBar().dock = value;
196
- me.getTabStrip().cls = ['neo-tab-strip', 'neo-dock-' + value];
194
+ me.layout.setSilent(me.getLayoutConfig());
195
+ me.getTabBar().setSilent({dock: value});
196
+ me.getTabStrip().setSilent({cls: ['neo-tab-strip', 'neo-dock-' + value]});
197
+
198
+ me.updateDepth = 2;
197
199
 
198
200
  me.fire('tabBarPositionChange', {
199
201
  component: me,
@@ -201,6 +203,8 @@ class Container extends BaseContainer {
201
203
  value
202
204
  })
203
205
  }
206
+
207
+ me.update()
204
208
  }
205
209
 
206
210
  /**
@@ -322,32 +326,30 @@ class Container extends BaseContainer {
322
326
  * @protected
323
327
  */
324
328
  getLayoutConfig() {
325
- const layoutMap = {
326
- 'bottom': {
327
- ntype: 'vbox',
328
- align: 'stretch',
329
+ let layoutMap = {
330
+ bottom: {
331
+ align : 'stretch',
329
332
  direction: 'column-reverse',
330
- pack: 'start'
333
+ pack : 'start'
331
334
  },
332
- 'left': {
333
- ntype: 'hbox',
334
- align: 'stretch',
335
+ left: {
336
+ align : 'stretch',
335
337
  direction: 'row',
336
- pack: 'start'
338
+ pack : 'start'
337
339
  },
338
- 'right': {
339
- ntype: 'hbox',
340
- align: 'stretch',
340
+ right: {
341
+ align : 'stretch',
341
342
  direction: 'row-reverse',
342
- pack: 'start'
343
+ pack : 'start'
343
344
  },
344
- 'top': {
345
- ntype: 'vbox',
346
- align: 'stretch'
345
+ top: {
346
+ align : 'stretch',
347
+ direction: 'column',
348
+ pack : 'start'
347
349
  }
348
350
  };
349
351
 
350
- return layoutMap[this.tabBarPosition] || null;
352
+ return layoutMap[this.tabBarPosition] || null
351
353
  }
352
354
 
353
355
  /**
@@ -505,7 +507,7 @@ class Container extends BaseContainer {
505
507
  *
506
508
  */
507
509
  onConstructed() {
508
- this.layout = this.getLayoutConfig(); // silent update
510
+ this.layout = {ntype: 'flexbox', ...this.getLayoutConfig()};
509
511
  super.onConstructed()
510
512
  }
511
513
 
@@ -96,14 +96,13 @@ class Toolbar extends BaseToolbar {
96
96
  case 'bottom':
97
97
  case 'top':
98
98
  layoutConfig = {
99
- ntype: 'hbox',
100
- align: 'center',
101
- pack : 'start'
99
+ align : 'center',
100
+ direction: 'row',
101
+ pack : 'start'
102
102
  };
103
103
  break
104
104
  case 'left':
105
105
  layoutConfig = {
106
- ntype : 'vbox',
107
106
  align : 'center',
108
107
  direction: 'column-reverse',
109
108
  pack : 'end'
@@ -111,7 +110,6 @@ class Toolbar extends BaseToolbar {
111
110
  break
112
111
  case 'right':
113
112
  layoutConfig = {
114
- ntype : 'vbox',
115
113
  align : 'center',
116
114
  direction: 'column',
117
115
  pack : 'start'
@@ -42,12 +42,13 @@ class Toolbar extends Container {
42
42
  ntype: 'button'
43
43
  },
44
44
  /**
45
- * @member {Object} layout={ntype: 'hbox', align: 'center', pack : 'start'}
45
+ * @member {Object} layout={ntype:'flexbox',align:'center',direction: 'row', pack:'start'}
46
46
  */
47
47
  layout: {
48
- ntype: 'hbox',
49
- align: 'center',
50
- pack : 'start'
48
+ ntype : 'flexbox',
49
+ align : 'center',
50
+ direction: 'row',
51
+ pack : 'start'
51
52
  },
52
53
  /**
53
54
  * @member {Boolean} sortable_=false
@@ -84,16 +85,26 @@ class Toolbar extends Container {
84
85
  * @protected
85
86
  */
86
87
  afterSetDock(value, oldValue) {
88
+ if (!value && !oldValue) {
89
+ return
90
+ }
91
+
87
92
  let me = this,
88
93
  {cls} = me,
89
- dockPositions = me.getStaticConfig('dockPositions');
94
+ dockPositions = me.getStaticConfig('dockPositions'),
95
+ layoutConfig = me.getLayoutConfig();
90
96
 
91
97
  dockPositions.forEach(key => {
92
- key !== null && NeoArray[key === value ? 'add' : 'remove'](cls, 'neo-dock-' + key)
98
+ key !== null && NeoArray.toggle(cls, 'neo-dock-' + key, key === value)
93
99
  });
94
100
 
95
- me.cls = cls;
96
- me.layout = me.getLayoutConfig()
101
+ if (!me.layout) {
102
+ layoutConfig.ntype = 'flexbox';
103
+ me.set({cls, layout: layoutConfig})
104
+ } else {
105
+ me.layout.set(layoutConfig);
106
+ me.cls = cls;
107
+ }
97
108
  }
98
109
 
99
110
  /**
@@ -170,14 +181,13 @@ class Toolbar extends Container {
170
181
  case 'bottom':
171
182
  case 'top':
172
183
  layoutConfig = {
173
- ntype: 'hbox',
174
- align: 'center',
175
- pack : 'start'
184
+ align : 'center',
185
+ direction: 'row',
186
+ pack : 'start'
176
187
  };
177
188
  break
178
189
  case 'left':
179
190
  layoutConfig = {
180
- ntype : 'vbox',
181
191
  align : 'center',
182
192
  direction: 'column-reverse',
183
193
  pack : 'start'
@@ -185,7 +195,6 @@ class Toolbar extends Container {
185
195
  break
186
196
  case 'right':
187
197
  layoutConfig = {
188
- ntype : 'vbox',
189
198
  align : 'center',
190
199
  direction: 'column',
191
200
  pack : 'start'
@@ -281,7 +281,10 @@ class Helper extends Base {
281
281
  }
282
282
 
283
283
  // Same node, continue recursively
284
- if (childNode && childNode.id === oldChildNode?.id) {
284
+ if (childNode && oldChildNode && (
285
+ childNode.id === oldChildNode.id ||
286
+ (childNode.componentId && childNode.componentId === oldChildNode.componentId))
287
+ ) {
285
288
  me.createDeltas({deltas, oldVnode: oldChildNode, oldVnodeMap, vnode: childNode, vnodeMap});
286
289
  continue
287
290
  }
@@ -1,21 +0,0 @@
1
- .neo-grid-scrollbar {
2
- bottom : 1px;
3
- opacity : 0;
4
- overflow-y : scroll;
5
- position : absolute;
6
- right : 0;
7
- top : 31px; // header-toolbar height
8
- transition : opacity 1s ease-out;
9
- width : 16px;
10
- z-index : 2;
11
-
12
- &:hover {
13
- opacity: 1;
14
- }
15
- }
16
-
17
- .neo-grid-wrapper:has(.neo-grid-view.neo-is-scrolling) {
18
- .neo-grid-scrollbar {
19
- opacity: 1;
20
- }
21
- }