neo.mjs 8.23.0 → 8.24.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.
- package/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/home/FeatureSection.mjs +4 -4
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/home/MainContainer.mjs +7 -7
- package/apps/portal/view/home/parts/MainNeo.mjs +35 -4
- package/examples/ServiceWorker.mjs +2 -2
- package/examples/component/magicmovetext/MainContainer.mjs +2 -0
- package/examples/grid/bigData/GridContainer.mjs +3 -0
- package/package.json +1 -1
- package/resources/scss/src/apps/portal/home/parts/MainNeo.scss +30 -0
- package/resources/scss/src/component/MagicMoveText.scss +9 -15
- package/src/DefaultConfig.mjs +2 -2
- package/src/component/MagicMoveText.mjs +228 -40
- package/src/grid/Container.mjs +77 -24
- package/src/grid/View.mjs +15 -18
- package/src/grid/header/Toolbar.mjs +1 -2
- package/src/selection/grid/CellModel.mjs +9 -9
package/apps/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -22,10 +22,10 @@ class FeatureSection extends Container {
|
|
22
22
|
*/
|
23
23
|
className: 'Portal.view.home.FeatureSection',
|
24
24
|
/**
|
25
|
-
* @member {String[]} baseCls=['portal-home-feature-section','neo-container']
|
25
|
+
* @member {String[]} baseCls=['portal-home-feature-section','portal-home-content-view','neo-container']
|
26
26
|
* @protected
|
27
27
|
*/
|
28
|
-
baseCls: ['portal-home-feature-section', 'neo-container'],
|
28
|
+
baseCls: ['portal-home-feature-section', 'portal-home-content-view', 'neo-container'],
|
29
29
|
/**
|
30
30
|
* If you want to use the LivePreview, use the config livePreviewCode.
|
31
31
|
* For custom content, use this config instead.
|
@@ -91,7 +91,7 @@ class FeatureSection extends Container {
|
|
91
91
|
}]
|
92
92
|
}, {
|
93
93
|
module : Container,
|
94
|
-
cls : 'portal-content-wrapper',
|
94
|
+
cls : ['portal-content-wrapper'],
|
95
95
|
layout : 'fit',
|
96
96
|
reference: 'portal-content-wrapper'
|
97
97
|
}]
|
@@ -125,7 +125,7 @@ class FeatureSection extends Container {
|
|
125
125
|
cls : ['page-live-preview'],
|
126
126
|
reference: 'live-preview',
|
127
127
|
value : this.livePreviewCode
|
128
|
-
}]
|
128
|
+
}];
|
129
129
|
|
130
130
|
this.getItem('portal-content-wrapper').items = value
|
131
131
|
}
|
@@ -6,8 +6,6 @@ import Helix from './parts/Helix.mjs';
|
|
6
6
|
import How from './parts/How.mjs';
|
7
7
|
import MainNeo from './parts/MainNeo.mjs';
|
8
8
|
|
9
|
-
// import References from './parts/References.mjs';
|
10
|
-
|
11
9
|
/**
|
12
10
|
* @class Portal.view.home.MainContainer
|
13
11
|
* @extends Neo.container.Base
|
@@ -28,9 +26,12 @@ class MainContainer extends Container {
|
|
28
26
|
*/
|
29
27
|
domListeners: [{
|
30
28
|
intersect(data) {
|
31
|
-
let id = data.path[
|
29
|
+
let id = data.path[0].id;
|
32
30
|
this.activePartsId = id;
|
33
|
-
|
31
|
+
|
32
|
+
this.items.forEach(item => {
|
33
|
+
item[item.id === id ? 'activate' : 'deactivate']?.()
|
34
|
+
})
|
34
35
|
},
|
35
36
|
scroll(event) {
|
36
37
|
if (event.target.cls.includes('portal-home-maincontainer')) {
|
@@ -54,7 +55,6 @@ class MainContainer extends Container {
|
|
54
55
|
Helix,
|
55
56
|
Colors,
|
56
57
|
How,
|
57
|
-
// References,
|
58
58
|
AfterMath
|
59
59
|
],
|
60
60
|
/**
|
@@ -85,9 +85,9 @@ class MainContainer extends Container {
|
|
85
85
|
Neo.main.addon.IntersectionObserver.register({
|
86
86
|
callback : 'isVisible',
|
87
87
|
id,
|
88
|
-
observe : ['.portal-content-
|
88
|
+
observe : ['.portal-home-content-view'],
|
89
89
|
root : `#${id}`,
|
90
|
-
threshold:
|
90
|
+
threshold: .6,
|
91
91
|
windowId
|
92
92
|
})
|
93
93
|
})
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import BaseContainer from './BaseContainer.mjs';
|
2
2
|
import Button from '../../../../../src/button/Base.mjs';
|
3
|
+
import MagicMoveText from '../../../../../src/component/MagicMoveText.mjs';
|
3
4
|
|
4
5
|
/**
|
5
6
|
* @class Portal.view.home.parts.MainNeo
|
@@ -33,10 +34,26 @@ class MainNeo extends BaseContainer {
|
|
33
34
|
tag : 'h1'
|
34
35
|
}]
|
35
36
|
}, {
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
module : MagicMoveText,
|
38
|
+
autoCycle: false,
|
39
|
+
cls : ['neo-h2'],
|
40
|
+
colorMove: '#3E63DD',
|
41
|
+
flex : 'none',
|
42
|
+
reference: 'magic-move',
|
43
|
+
|
44
|
+
cycleTexts: [
|
45
|
+
'Modern Enterprise JavaScript Framework',
|
46
|
+
'An Application Worker being the Orchestrator',
|
47
|
+
'Scalability',
|
48
|
+
'Extensibility',
|
49
|
+
'Performance',
|
50
|
+
'Declarative & Reactive Component Trees',
|
51
|
+
'Separated from Business Logic',
|
52
|
+
'View Controllers',
|
53
|
+
'State Providers',
|
54
|
+
'Clean Architectures',
|
55
|
+
'Multi Window Apps'
|
56
|
+
]
|
40
57
|
}, {
|
41
58
|
cls : ['neo-h3'],
|
42
59
|
flex: 'none',
|
@@ -66,6 +83,20 @@ class MainNeo extends BaseContainer {
|
|
66
83
|
}]
|
67
84
|
}]
|
68
85
|
}
|
86
|
+
|
87
|
+
/**
|
88
|
+
*
|
89
|
+
*/
|
90
|
+
activate() {
|
91
|
+
this.getItem('magic-move').autoCycle = true
|
92
|
+
}
|
93
|
+
|
94
|
+
/**
|
95
|
+
*
|
96
|
+
*/
|
97
|
+
deactivate() {
|
98
|
+
this.getItem('magic-move').autoCycle = false
|
99
|
+
}
|
69
100
|
}
|
70
101
|
|
71
102
|
export default Neo.setupClass(MainNeo);
|
@@ -1,6 +1,8 @@
|
|
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
|
+
|
4
6
|
/**
|
5
7
|
* @class Neo.examples.grid.bigData.GridContainer
|
6
8
|
* @extends Neo.grid.Container
|
@@ -33,6 +35,7 @@ class GridContainer extends BaseGridContainer {
|
|
33
35
|
* @member {Object} viewConfig
|
34
36
|
*/
|
35
37
|
viewConfig: {
|
38
|
+
selectionModel: selection.CellModel, // todo: remove after #6491 is resolved
|
36
39
|
bufferColumnRange: 3,
|
37
40
|
bufferRowRange : 5
|
38
41
|
}
|
package/package.json
CHANGED
@@ -27,6 +27,24 @@
|
|
27
27
|
min-width : 240px;
|
28
28
|
}
|
29
29
|
|
30
|
+
.neo-magic-move-text {
|
31
|
+
background-color: transparent;
|
32
|
+
color : #000;
|
33
|
+
font-size : 2.5rem;
|
34
|
+
height : 2em;
|
35
|
+
letter-spacing : -0.02em;
|
36
|
+
line-height : 1.2em;
|
37
|
+
width : 90%;
|
38
|
+
|
39
|
+
.neo-content {
|
40
|
+
font-size: 2.5rem;
|
41
|
+
}
|
42
|
+
|
43
|
+
.neo-measure-element-wrapper {
|
44
|
+
letter-spacing: -0.02em;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
30
48
|
.neo-github {
|
31
49
|
background-color: #fff;
|
32
50
|
}
|
@@ -79,6 +97,10 @@
|
|
79
97
|
margin: 1rem 2rem;
|
80
98
|
}
|
81
99
|
|
100
|
+
.neo-magic-move-text {
|
101
|
+
height: 3.5em;
|
102
|
+
}
|
103
|
+
|
82
104
|
.vector {
|
83
105
|
height: 17vw;
|
84
106
|
}
|
@@ -106,6 +128,14 @@
|
|
106
128
|
font-size: 1.15rem;
|
107
129
|
}
|
108
130
|
|
131
|
+
.neo-magic-move-text {
|
132
|
+
height: 3.5em;
|
133
|
+
|
134
|
+
.neo-content {
|
135
|
+
font-size: 2rem;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
109
139
|
.vector {
|
110
140
|
height: 70px;
|
111
141
|
width : 70px;
|
@@ -1,42 +1,36 @@
|
|
1
1
|
.neo-magic-move-text {
|
2
|
-
--neo-height : 100px;
|
3
2
|
--neo-transition-time: 500ms;
|
4
|
-
--neo-width : 450px;
|
5
3
|
|
6
|
-
align-items : center;
|
7
4
|
background-color: #000;
|
8
5
|
color : #fff;
|
9
|
-
display : flex;
|
10
6
|
font-size : 30px;
|
11
7
|
font-weight : bold;
|
12
|
-
height : var(--neo-height);
|
13
|
-
justify-content : center;
|
14
|
-
width : var(--neo-width);
|
15
8
|
|
16
9
|
.neo-content {
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
align-items : center;
|
11
|
+
display : flex;
|
12
|
+
height : 100%;
|
13
|
+
justify-content: center;
|
14
|
+
position : relative;
|
15
|
+
width : 100%;
|
20
16
|
|
21
|
-
|
17
|
+
.neo-char {
|
22
18
|
position : absolute;
|
23
19
|
transition:
|
24
20
|
color 0.2s ease-out,
|
25
21
|
left var(--neo-transition-time) ease-out,
|
26
|
-
opacity var(--neo-transition-time) ease-out
|
22
|
+
opacity var(--neo-transition-time) ease-out,
|
23
|
+
top var(--neo-transition-time) ease-out;
|
27
24
|
}
|
28
25
|
}
|
29
26
|
|
30
27
|
.neo-measure-element-wrapper {
|
31
28
|
align-items : center;
|
32
|
-
background-color: #000;
|
33
29
|
display : flex;
|
34
|
-
height : var(--neo-height);
|
35
30
|
justify-content: center;
|
36
31
|
left : -5000px;
|
37
32
|
position : absolute;
|
38
33
|
top : -5000px;
|
39
|
-
width : var(--neo-width);
|
40
34
|
}
|
41
35
|
|
42
36
|
.neo-measure-element {
|
package/src/DefaultConfig.mjs
CHANGED
@@ -263,12 +263,12 @@ const DefaultConfig = {
|
|
263
263
|
useVdomWorker: true,
|
264
264
|
/**
|
265
265
|
* buildScripts/injectPackageVersion.mjs will update this value
|
266
|
-
* @default '8.
|
266
|
+
* @default '8.24.0'
|
267
267
|
* @memberOf! module:Neo
|
268
268
|
* @name config.version
|
269
269
|
* @type String
|
270
270
|
*/
|
271
|
-
version: '8.
|
271
|
+
version: '8.24.0'
|
272
272
|
};
|
273
273
|
|
274
274
|
Object.assign(DefaultConfig, {
|
@@ -74,25 +74,98 @@ class MagicMoveText extends Component {
|
|
74
74
|
|
75
75
|
/**
|
76
76
|
* @member {Object[]} chars=[]
|
77
|
+
* @protected
|
77
78
|
*/
|
78
79
|
chars = []
|
80
|
+
/**
|
81
|
+
* @member {Object[]} charsVdom=[]
|
82
|
+
* @protected
|
83
|
+
*/
|
84
|
+
charsVdom = []
|
85
|
+
/**
|
86
|
+
* @member {Number} contentHeight=0
|
87
|
+
* @protected
|
88
|
+
*/
|
89
|
+
contentHeight = 0
|
90
|
+
/**
|
91
|
+
* @member {Number} contentWidth=0
|
92
|
+
* @protected
|
93
|
+
*/
|
94
|
+
contentWidth = 0
|
79
95
|
/**
|
80
96
|
* @member {Number} currentIndex=0
|
97
|
+
* @protected
|
81
98
|
*/
|
82
99
|
currentIndex = 0
|
100
|
+
/**
|
101
|
+
* We do not need the first event to trigger logic, since afterSetMounted() handles this
|
102
|
+
* @member {Boolean} initialResizeEvent=true
|
103
|
+
* @protected
|
104
|
+
*/
|
105
|
+
initialResizeEvent = true
|
83
106
|
/**
|
84
107
|
* @member {Number|null} intervalId=null
|
108
|
+
* @protected
|
85
109
|
*/
|
86
110
|
intervalId = null
|
111
|
+
/**
|
112
|
+
* Internal flag which gets set to true while the animated char transitions are running
|
113
|
+
* @member {Boolean} isTransitioning=false
|
114
|
+
* @protected
|
115
|
+
*/
|
116
|
+
isTransitioning = false
|
117
|
+
/**
|
118
|
+
* @member {Object} measureCache={}
|
119
|
+
* @protected
|
120
|
+
*/
|
121
|
+
measureCache = {}
|
87
122
|
/**
|
88
123
|
* @member {Object[]} previousChars=[]
|
124
|
+
* @protected
|
89
125
|
*/
|
90
126
|
previousChars = []
|
91
127
|
/**
|
92
128
|
* @member {Object} measureElement
|
129
|
+
* @protected
|
93
130
|
*/
|
94
131
|
get measureElement() {
|
95
|
-
return this.
|
132
|
+
return this.measureWrapper.cn[0]
|
133
|
+
}
|
134
|
+
/**
|
135
|
+
* @member {Object} measureElement
|
136
|
+
* @protected
|
137
|
+
*/
|
138
|
+
get measureWrapper() {
|
139
|
+
return this.vdom.cn[1]
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* @param {Object} config
|
144
|
+
*/
|
145
|
+
construct(config) {
|
146
|
+
super.construct(config);
|
147
|
+
|
148
|
+
let me = this;
|
149
|
+
|
150
|
+
me.addDomListeners({
|
151
|
+
resize: me.onResize,
|
152
|
+
scope : me
|
153
|
+
})
|
154
|
+
}
|
155
|
+
|
156
|
+
/**
|
157
|
+
* @param {Boolean} mounted
|
158
|
+
* @protected
|
159
|
+
*/
|
160
|
+
async addResizeObserver(mounted) {
|
161
|
+
let {id, windowId} = this,
|
162
|
+
ResizeObserver = await Neo.currentWorker.getAddon('ResizeObserver', windowId);
|
163
|
+
|
164
|
+
ResizeObserver[mounted ? 'register' : 'unregister']({id, windowId});
|
165
|
+
|
166
|
+
if (mounted) {
|
167
|
+
this.initialResizeEvent = true
|
168
|
+
}
|
96
169
|
}
|
97
170
|
|
98
171
|
/**
|
@@ -127,8 +200,12 @@ class MagicMoveText extends Component {
|
|
127
200
|
* @protected
|
128
201
|
*/
|
129
202
|
afterSetFontFamily(value, oldValue) {
|
130
|
-
|
131
|
-
|
203
|
+
let me = this;
|
204
|
+
|
205
|
+
me.measureCache = {};
|
206
|
+
|
207
|
+
me.vdom.style.fontFamily = value;
|
208
|
+
me.update()
|
132
209
|
}
|
133
210
|
|
134
211
|
/**
|
@@ -139,7 +216,17 @@ class MagicMoveText extends Component {
|
|
139
216
|
*/
|
140
217
|
afterSetMounted(value, oldValue) {
|
141
218
|
super.afterSetMounted(value, oldValue);
|
142
|
-
|
219
|
+
|
220
|
+
let me = this;
|
221
|
+
|
222
|
+
value && me.getDomRect().then(rect => {
|
223
|
+
me.contentHeight = rect.height;
|
224
|
+
me.contentWidth = rect.width;
|
225
|
+
|
226
|
+
me.autoCycle && me.startAutoCycle(value)
|
227
|
+
});
|
228
|
+
|
229
|
+
oldValue !== undefined && me.addResizeObserver(value)
|
143
230
|
}
|
144
231
|
|
145
232
|
/**
|
@@ -165,7 +252,7 @@ class MagicMoveText extends Component {
|
|
165
252
|
me.chars.push({name: char});
|
166
253
|
|
167
254
|
if (char === ' ') {
|
168
|
-
char = '
|
255
|
+
char = ' '
|
169
256
|
}
|
170
257
|
|
171
258
|
measureElement.cn.push({tag: 'span', html: char})
|
@@ -190,44 +277,132 @@ class MagicMoveText extends Component {
|
|
190
277
|
this.update()
|
191
278
|
}
|
192
279
|
|
280
|
+
/**
|
281
|
+
* @param {String[]} letters
|
282
|
+
* @returns {Object[]}
|
283
|
+
* @protected
|
284
|
+
*/
|
285
|
+
createCharsVdom(letters) {
|
286
|
+
let me = this,
|
287
|
+
{chars} = me,
|
288
|
+
charsContainer = [],
|
289
|
+
char;
|
290
|
+
|
291
|
+
letters.forEach((letter, index) => {
|
292
|
+
if (letter !== null) {
|
293
|
+
char = chars[index];
|
294
|
+
|
295
|
+
charsContainer.push({
|
296
|
+
cls : ['neo-char'],
|
297
|
+
html : char.name,
|
298
|
+
style: {color: me.colorFadeIn, left: char.left, opacity: 0, top: char.top}
|
299
|
+
})
|
300
|
+
}
|
301
|
+
});
|
302
|
+
|
303
|
+
return charsContainer
|
304
|
+
}
|
305
|
+
|
306
|
+
/**
|
307
|
+
* @protected
|
308
|
+
*/
|
309
|
+
cycleText() {
|
310
|
+
let me = this;
|
311
|
+
|
312
|
+
me.text = me.cycleTexts[me.currentIndex];
|
313
|
+
me.currentIndex = (me.currentIndex + 1) % me.cycleTexts.length
|
314
|
+
}
|
315
|
+
|
193
316
|
/**
|
194
317
|
* @returns {Promise<void>}
|
318
|
+
* @protected
|
195
319
|
*/
|
196
320
|
async measureChars() {
|
197
321
|
let me = this,
|
198
|
-
{measureElement} = me,
|
322
|
+
{measureCache, measureElement, measureWrapper, text} = me,
|
199
323
|
parentRect, rects;
|
200
324
|
|
201
|
-
|
325
|
+
if (measureCache[text]) {
|
326
|
+
rects = [...measureCache[text]];
|
327
|
+
parentRect = rects.shift()
|
328
|
+
} else {
|
329
|
+
measureWrapper.style = {
|
330
|
+
height: me.contentHeight + 'px',
|
331
|
+
width : me.contentWidth + 'px'
|
332
|
+
};
|
333
|
+
|
334
|
+
delete measureWrapper.removeDom;
|
202
335
|
|
203
|
-
|
204
|
-
|
336
|
+
await me.promiseUpdate();
|
337
|
+
await me.timeout(20);
|
205
338
|
|
206
|
-
|
207
|
-
|
339
|
+
rects = await me.getDomRect([measureWrapper.id, ...measureElement.cn.map(node => node.id)]);
|
340
|
+
parentRect = rects.shift();
|
341
|
+
|
342
|
+
measureCache[text] = [parentRect, ...rects]
|
343
|
+
}
|
208
344
|
|
209
345
|
rects.forEach((rect, index) => {
|
210
346
|
me.chars[index].left = `${rect.left - parentRect.left}px`;
|
211
347
|
me.chars[index].top = `${rect.top - parentRect.top }px`;
|
212
348
|
});
|
213
349
|
|
214
|
-
|
350
|
+
measureWrapper.removeDom = true;
|
215
351
|
await me.promiseUpdate()
|
216
352
|
}
|
217
353
|
|
354
|
+
/**
|
355
|
+
* @param {Object} data
|
356
|
+
* @returns {Promise<void>}
|
357
|
+
* @protected
|
358
|
+
*/
|
359
|
+
async onResize({rect}) {
|
360
|
+
let me = this;
|
361
|
+
|
362
|
+
me.contentHeight = rect.height;
|
363
|
+
me.contentWidth = rect.width;
|
364
|
+
|
365
|
+
me.measureCache = {};
|
366
|
+
|
367
|
+
|
368
|
+
if (!me.initialResizeEvent) {
|
369
|
+
if (!me.isTransitioning) {
|
370
|
+
await me.measureChars();
|
371
|
+
|
372
|
+
me.charsVdom = me.createCharsVdom(me.chars.map(char => char.name))
|
373
|
+
}
|
374
|
+
} else {
|
375
|
+
me.initialResizeEvent = false
|
376
|
+
}
|
377
|
+
}
|
378
|
+
|
379
|
+
/**
|
380
|
+
* @param {Object} a
|
381
|
+
* @param {Object} b
|
382
|
+
* @returns {Number}
|
383
|
+
* @protected
|
384
|
+
*/
|
385
|
+
sortCharacters(a, b) {
|
386
|
+
let deltaTop = parseFloat(a.style.top) - parseFloat(b.style.top);
|
387
|
+
|
388
|
+
if (deltaTop !== 0) {
|
389
|
+
return deltaTop
|
390
|
+
}
|
391
|
+
|
392
|
+
return parseFloat(a.style.left) - parseFloat(b.style.left)
|
393
|
+
}
|
394
|
+
|
218
395
|
/**
|
219
396
|
* @param {Boolean} start=true
|
397
|
+
* @protected
|
220
398
|
*/
|
221
399
|
startAutoCycle(start=true) {
|
222
400
|
let me = this;
|
223
401
|
|
224
402
|
if (start) {
|
225
|
-
me.intervalId = setInterval(()
|
226
|
-
me.text = me.cycleTexts[me.currentIndex];
|
227
|
-
me.currentIndex = (me.currentIndex + 1) % me.cycleTexts.length
|
228
|
-
}, me.autoCycleInterval)
|
403
|
+
me.intervalId = setInterval(me.cycleText.bind(me), me.autoCycleInterval);
|
229
404
|
|
230
|
-
me.
|
405
|
+
me.timeout(20).then(() => {me.cycleText()});
|
231
406
|
} else {
|
232
407
|
clearInterval(me.intervalId)
|
233
408
|
}
|
@@ -235,71 +410,84 @@ class MagicMoveText extends Component {
|
|
235
410
|
|
236
411
|
/**
|
237
412
|
* @returns {Promise<void>}
|
413
|
+
* @protected
|
238
414
|
*/
|
239
415
|
async updateChars() {
|
240
416
|
let me = this,
|
241
417
|
{chars, previousChars} = me,
|
242
|
-
charsContainer = me.vdom.cn[0]
|
418
|
+
charsContainer = me.vdom.cn[0],
|
243
419
|
letters = chars.map(char => char.name),
|
244
|
-
|
420
|
+
charNode, index;
|
421
|
+
|
422
|
+
me.isTransitioning = true;
|
423
|
+
|
424
|
+
if (me.charsVdom.length > 1) {
|
425
|
+
charsContainer.cn = me.charsVdom;
|
426
|
+
await me.promiseUpdate()
|
427
|
+
}
|
245
428
|
|
246
429
|
previousChars.forEach((previousChar, previousIndex) => {
|
247
430
|
index = letters.indexOf(previousChar.name);
|
248
431
|
|
249
432
|
if (index > -1) {
|
250
|
-
charNode = charsContainer[previousIndex];
|
433
|
+
charNode = charsContainer.cn[previousIndex];
|
434
|
+
|
435
|
+
Object.assign(charNode.style, {
|
436
|
+
color: me.colorMove,
|
437
|
+
left : chars[index].left,
|
438
|
+
top : chars[index].top
|
439
|
+
});
|
251
440
|
|
252
|
-
charNode.style.color = me.colorMove;
|
253
|
-
charNode.style.left = chars[index].left;
|
254
441
|
letters[index] = null
|
255
442
|
} else {
|
256
|
-
charNode = charsContainer[previousIndex];
|
443
|
+
charNode = charsContainer.cn[previousIndex];
|
257
444
|
|
258
445
|
charNode.flag = 'remove'
|
259
446
|
}
|
260
447
|
});
|
261
448
|
|
262
|
-
|
263
|
-
if (letter !== null) {
|
264
|
-
char = chars[index];
|
265
|
-
|
266
|
-
charsContainer.push({
|
267
|
-
html : char.name,
|
268
|
-
style: {color: me.colorFadeIn, left: char.left, opacity: 0, top: char.top}
|
269
|
-
})
|
270
|
-
}
|
271
|
-
});
|
449
|
+
charsContainer.cn.push(...me.createCharsVdom(letters));
|
272
450
|
|
273
451
|
await me.promiseUpdate();
|
274
452
|
|
275
|
-
charsContainer.forEach(charNode => {
|
453
|
+
charsContainer.cn.forEach(charNode => {
|
276
454
|
if (charNode.flag === 'remove') {
|
277
455
|
charNode.style.color = me.colorFadeOut;
|
278
456
|
charNode.style.opacity = 0
|
279
457
|
} else {
|
280
|
-
charNode.style.opacity
|
458
|
+
delete charNode.style.opacity
|
281
459
|
}
|
282
460
|
});
|
283
461
|
|
284
462
|
await me.promiseUpdate();
|
285
463
|
await me.timeout(me.transitionTime);
|
286
464
|
|
287
|
-
charsContainer.sort(
|
465
|
+
charsContainer.cn.sort(me.sortCharacters);
|
288
466
|
|
289
|
-
index = charsContainer.length - 1;
|
467
|
+
index = charsContainer.cn.length - 1;
|
290
468
|
|
291
469
|
for (; index >= 0; index--) {
|
292
|
-
charNode = charsContainer[index];
|
470
|
+
charNode = charsContainer.cn[index];
|
293
471
|
|
294
472
|
delete charNode.flag;
|
295
473
|
delete charNode.style.color;
|
296
474
|
|
297
475
|
if (charNode.style.opacity === 0) {
|
298
|
-
charsContainer.splice(index, 1)
|
476
|
+
charsContainer.cn.splice(index, 1)
|
299
477
|
}
|
300
478
|
}
|
301
479
|
|
302
|
-
await me.promiseUpdate()
|
480
|
+
await me.promiseUpdate();
|
481
|
+
await me.timeout(200);
|
482
|
+
|
483
|
+
me.charsVdom = [...charsContainer.cn];
|
484
|
+
|
485
|
+
charsContainer.cn.length = 0;
|
486
|
+
|
487
|
+
charsContainer.cn.push({html: me.text});
|
488
|
+
await me.promiseUpdate();
|
489
|
+
|
490
|
+
me.isTransitioning = false
|
303
491
|
}
|
304
492
|
}
|
305
493
|
|
package/src/grid/Container.mjs
CHANGED
@@ -197,6 +197,25 @@ class GridContainer extends BaseContainer {
|
|
197
197
|
})
|
198
198
|
}
|
199
199
|
|
200
|
+
/**
|
201
|
+
* @param {Boolean} mounted
|
202
|
+
* @protected
|
203
|
+
*/
|
204
|
+
async addResizeObserver(mounted) {
|
205
|
+
let me = this,
|
206
|
+
{windowId} = me,
|
207
|
+
ResizeObserver = await Neo.currentWorker.getAddon('ResizeObserver', windowId),
|
208
|
+
resizeParams = {id: me.id, windowId};
|
209
|
+
|
210
|
+
if (mounted) {
|
211
|
+
ResizeObserver.register(resizeParams);
|
212
|
+
await me.passSizeToView()
|
213
|
+
} else {
|
214
|
+
me.initialResizeEvent = true;
|
215
|
+
ResizeObserver.unregister(resizeParams)
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
200
219
|
/**
|
201
220
|
* Triggered after the cellEditing config got changed
|
202
221
|
* @param {Boolean} value
|
@@ -245,25 +264,6 @@ class GridContainer extends BaseContainer {
|
|
245
264
|
}
|
246
265
|
}
|
247
266
|
|
248
|
-
/**
|
249
|
-
* @param {Boolean} mounted
|
250
|
-
* @protected
|
251
|
-
*/
|
252
|
-
async addResizeObserver(mounted) {
|
253
|
-
let me = this,
|
254
|
-
{windowId} = me,
|
255
|
-
ResizeObserver = await Neo.currentWorker.getAddon('ResizeObserver', windowId),
|
256
|
-
resizeParams = {id: me.id, windowId};
|
257
|
-
|
258
|
-
if (mounted) {
|
259
|
-
ResizeObserver.register(resizeParams);
|
260
|
-
await me.passSizeToView()
|
261
|
-
} else {
|
262
|
-
me.initialResizeEvent = true;
|
263
|
-
ResizeObserver.unregister(resizeParams)
|
264
|
-
}
|
265
|
-
}
|
266
|
-
|
267
267
|
/**
|
268
268
|
* Triggered after the mounted config got changed
|
269
269
|
* @param {Boolean} value
|
@@ -537,16 +537,17 @@ class GridContainer extends BaseContainer {
|
|
537
537
|
* @param {Object} data.touches
|
538
538
|
*/
|
539
539
|
onScroll({scrollLeft, target, touches}) {
|
540
|
-
let me
|
540
|
+
let me = this,
|
541
|
+
{view} = me,
|
541
542
|
deltaY, lastTouchY;
|
542
543
|
|
543
544
|
// We must ignore events for grid-scrollbar
|
544
545
|
if (target.id.includes('grid-container')) {
|
545
546
|
me.headerToolbar.scrollLeft = scrollLeft;
|
546
|
-
|
547
|
+
view.scrollPosition = {x: scrollLeft, y: view.scrollPosition.y};
|
547
548
|
|
548
549
|
if (touches) {
|
549
|
-
if (!
|
550
|
+
if (!view.isTouchMoveOwner) {
|
550
551
|
me.isTouchMoveOwner = true
|
551
552
|
}
|
552
553
|
|
@@ -556,8 +557,8 @@ class GridContainer extends BaseContainer {
|
|
556
557
|
|
557
558
|
deltaY !== 0 && Neo.main.DomAccess.scrollTo({
|
558
559
|
direction: 'top',
|
559
|
-
id :
|
560
|
-
value :
|
560
|
+
id : view.vdom.id,
|
561
|
+
value : view.scrollPosition.y + deltaY
|
561
562
|
})
|
562
563
|
|
563
564
|
me.lastTouchY = lastTouchY
|
@@ -657,6 +658,58 @@ class GridContainer extends BaseContainer {
|
|
657
658
|
}
|
658
659
|
})
|
659
660
|
}
|
661
|
+
|
662
|
+
/**
|
663
|
+
* Used for keyboard navigation (selection models)
|
664
|
+
* @param {Number} index
|
665
|
+
* @param {Number} step
|
666
|
+
*/
|
667
|
+
scrollByColumns(index, step) {
|
668
|
+
let me = this,
|
669
|
+
{view} = me,
|
670
|
+
{columnPositions, containerWidth, mountedColumns, visibleColumns} = view,
|
671
|
+
countColumns = columnPositions.getCount(),
|
672
|
+
newIndex = index + step,
|
673
|
+
column, mounted, scrollPosition, visible;
|
674
|
+
|
675
|
+
if (newIndex >= countColumns) {
|
676
|
+
newIndex %= countColumns;
|
677
|
+
step = newIndex - index
|
678
|
+
}
|
679
|
+
|
680
|
+
while (newIndex < 0) {
|
681
|
+
newIndex += countColumns;
|
682
|
+
step += countColumns
|
683
|
+
}
|
684
|
+
|
685
|
+
mounted = newIndex >= mountedColumns[0] && newIndex <= mountedColumns[1];
|
686
|
+
|
687
|
+
// Not using >= or <=, since the first / last column might not be fully visible
|
688
|
+
visible = newIndex > visibleColumns[0] && newIndex < visibleColumns[1];
|
689
|
+
|
690
|
+
if (!visible) {
|
691
|
+
// Leaving the mounted area will re-calculate the visibleColumns for us
|
692
|
+
if (mounted) {
|
693
|
+
visibleColumns[0] += step;
|
694
|
+
visibleColumns[1] += step
|
695
|
+
}
|
696
|
+
|
697
|
+
column = columnPositions.getAt(newIndex);
|
698
|
+
|
699
|
+
if (step < 0) {
|
700
|
+
scrollPosition = column.x
|
701
|
+
} else {
|
702
|
+
scrollPosition = column.x - containerWidth + column.width
|
703
|
+
}
|
704
|
+
|
705
|
+
Neo.main.DomAccess.scrollTo({
|
706
|
+
direction: 'left',
|
707
|
+
id : me.id,
|
708
|
+
value : scrollPosition,
|
709
|
+
windowId : me.windowId
|
710
|
+
})
|
711
|
+
}
|
712
|
+
}
|
660
713
|
}
|
661
714
|
|
662
715
|
export default Neo.setupClass(GridContainer);
|
package/src/grid/View.mjs
CHANGED
@@ -142,9 +142,9 @@ class GridView extends Component {
|
|
142
142
|
* @member {Object} _vdom
|
143
143
|
*/
|
144
144
|
_vdom:
|
145
|
-
|
146
|
-
|
147
|
-
|
145
|
+
{tabIndex: '-1', cn: [
|
146
|
+
{cn: []}
|
147
|
+
]}
|
148
148
|
}
|
149
149
|
|
150
150
|
/**
|
@@ -314,7 +314,7 @@ class GridView extends Component {
|
|
314
314
|
* @protected
|
315
315
|
*/
|
316
316
|
afterSetMountedColumns(value, oldValue) {
|
317
|
-
oldValue
|
317
|
+
oldValue && this.createViewData()
|
318
318
|
}
|
319
319
|
|
320
320
|
/**
|
@@ -1036,18 +1036,18 @@ class GridView extends Component {
|
|
1036
1036
|
*/
|
1037
1037
|
updateMountedAndVisibleColumns() {
|
1038
1038
|
let me = this,
|
1039
|
-
{bufferColumnRange, columnPositions, visibleColumns} = me,
|
1040
|
-
{x}
|
1041
|
-
i
|
1042
|
-
|
1043
|
-
endIndex
|
1039
|
+
{bufferColumnRange, columnPositions, mountedColumns, visibleColumns} = me,
|
1040
|
+
{x} = me.scrollPosition,
|
1041
|
+
i = 0,
|
1042
|
+
countColumns = columnPositions.getCount(),
|
1043
|
+
endIndex = countColumns - 1,
|
1044
1044
|
column, startIndex;
|
1045
1045
|
|
1046
|
-
if (
|
1046
|
+
if (countColumns < 1) {
|
1047
1047
|
return
|
1048
1048
|
}
|
1049
1049
|
|
1050
|
-
for (; i <
|
1050
|
+
for (; i < countColumns; i++) {
|
1051
1051
|
column = columnPositions.getAt(i);
|
1052
1052
|
|
1053
1053
|
if (x >= column.x && x <= column.x + column.width) {
|
@@ -1060,15 +1060,12 @@ class GridView extends Component {
|
|
1060
1060
|
}
|
1061
1061
|
}
|
1062
1062
|
|
1063
|
-
|
1064
|
-
|
1065
|
-
me.visibleColumns[1] < 1 // initial call
|
1066
|
-
) {
|
1067
|
-
visibleColumns[0] = startIndex;
|
1068
|
-
visibleColumns[1] = endIndex;
|
1063
|
+
visibleColumns[0] = startIndex; // update the array inline
|
1064
|
+
visibleColumns[1] = endIndex;
|
1069
1065
|
|
1070
|
-
|
1066
|
+
if (visibleColumns[0] <= mountedColumns[0] || visibleColumns[1] >= mountedColumns[1]) {
|
1071
1067
|
startIndex = Math.max(0, visibleColumns[0] - bufferColumnRange);
|
1068
|
+
endIndex = Math.min(countColumns - 1, visibleColumns[1] + bufferColumnRange);
|
1072
1069
|
|
1073
1070
|
me.mountedColumns = [startIndex, endIndex]
|
1074
1071
|
}
|
@@ -235,10 +235,9 @@ class Toolbar extends BaseToolbar {
|
|
235
235
|
|
236
236
|
/**
|
237
237
|
* @param {Number} index
|
238
|
-
* @param {DOMRect} itemRect
|
239
238
|
* @returns {Promise<void>}
|
240
239
|
*/
|
241
|
-
async scrollToIndex(index
|
240
|
+
async scrollToIndex(index) {
|
242
241
|
await Neo.main.DomAccess.scrollIntoView({
|
243
242
|
delay : 125,
|
244
243
|
id : this.items[index].id,
|
@@ -85,7 +85,7 @@ class CellModel extends BaseModel {
|
|
85
85
|
let me = this,
|
86
86
|
{dataFields, view} = me,
|
87
87
|
{store} = view,
|
88
|
-
currentColumn, newIndex, record;
|
88
|
+
currentColumn, currentIndex, newIndex, record;
|
89
89
|
|
90
90
|
if (me.hasSelection()) {
|
91
91
|
currentColumn = view.getDataField(me.items[0]);
|
@@ -95,13 +95,16 @@ class CellModel extends BaseModel {
|
|
95
95
|
record = store.getAt(0)
|
96
96
|
}
|
97
97
|
|
98
|
-
|
98
|
+
currentIndex = dataFields.indexOf(currentColumn);
|
99
|
+
newIndex = (currentIndex + step) % dataFields.length;
|
99
100
|
|
100
101
|
while (newIndex < 0) {
|
101
102
|
newIndex += dataFields.length
|
102
103
|
}
|
103
104
|
|
104
|
-
me.select(view.getCellId(record, dataFields[newIndex]))
|
105
|
+
me.select(view.getCellId(record, dataFields[newIndex]));
|
106
|
+
|
107
|
+
view.parent.scrollByColumns(currentIndex, step)
|
105
108
|
}
|
106
109
|
|
107
110
|
/**
|
@@ -112,10 +115,10 @@ class CellModel extends BaseModel {
|
|
112
115
|
{view} = me,
|
113
116
|
{store} = view,
|
114
117
|
currentIndex = 0,
|
115
|
-
dataField, newIndex
|
118
|
+
dataField, newIndex;
|
116
119
|
|
117
120
|
if (me.hasSelection()) {
|
118
|
-
currentIndex = store.indexOf(view.
|
121
|
+
currentIndex = store.indexOf(view.getRecord(me.items[0]));
|
119
122
|
dataField = view.getDataField(me.items[0])
|
120
123
|
} else {
|
121
124
|
dataField = me.dataFields[0]
|
@@ -127,10 +130,7 @@ class CellModel extends BaseModel {
|
|
127
130
|
newIndex += store.getCount()
|
128
131
|
}
|
129
132
|
|
130
|
-
|
131
|
-
|
132
|
-
me.select(view.getCellId(record, dataField));
|
133
|
-
|
133
|
+
me.select(view.getCellId(store.getAt(newIndex), dataField));
|
134
134
|
view.scrollByRows(currentIndex, step)
|
135
135
|
}
|
136
136
|
|