neo.mjs 8.29.0 → 8.31.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 (37) hide show
  1. package/BACKERS.md +15 -15
  2. package/CONTRIBUTING.md +9 -9
  3. package/apps/ServiceWorker.mjs +2 -2
  4. package/apps/portal/index.html +1 -1
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/examples/ServiceWorker.mjs +2 -2
  7. package/examples/grid/animatedRowSorting/MainModel.mjs +40 -0
  8. package/examples/grid/animatedRowSorting/MainStore.mjs +36 -0
  9. package/examples/grid/animatedRowSorting/Viewport.mjs +87 -0
  10. package/examples/grid/animatedRowSorting/app.mjs +6 -0
  11. package/examples/grid/animatedRowSorting/index.html +11 -0
  12. package/examples/grid/animatedRowSorting/neo-config.json +8 -0
  13. package/examples/grid/bigData/GridContainer.mjs +3 -2
  14. package/examples/grid/bigData/MainModel.mjs +3 -2
  15. package/examples/grid/bigData/MainStore.mjs +3 -2
  16. package/package.json +3 -3
  17. package/resources/scss/src/component/Progress.scss +1 -1
  18. package/resources/scss/src/grid/column/Progress.scss +34 -0
  19. package/resources/scss/theme-dark/grid/column/Progress.scss +6 -0
  20. package/resources/scss/theme-light/grid/column/Progress.scss +6 -0
  21. package/resources/scss/theme-neo-light/grid/column/Progress.scss +6 -0
  22. package/src/DefaultConfig.mjs +2 -2
  23. package/src/collection/Base.mjs +2 -1
  24. package/src/component/Base.mjs +1 -1
  25. package/src/component/Progress.mjs +26 -5
  26. package/src/data/Store.mjs +12 -9
  27. package/src/grid/Container.mjs +45 -68
  28. package/src/grid/ScrollManager.mjs +1 -1
  29. package/src/grid/View.mjs +81 -1
  30. package/src/grid/column/Component.mjs +50 -8
  31. package/src/grid/column/Progress.mjs +42 -0
  32. package/src/grid/column/_export.mjs +2 -1
  33. package/src/grid/header/Button.mjs +1 -2
  34. package/src/grid/plugin/AnimateRows.mjs +234 -0
  35. package/src/list/plugin/Animate.mjs +16 -7
  36. package/src/vdom/Helper.mjs +1 -1
  37. package/src/worker/Manager.mjs +6 -8
@@ -0,0 +1,234 @@
1
+ import Base from '../../plugin/Base.mjs';
2
+ import CssUtil from '../../util/Css.mjs';
3
+ import NeoArray from '../../util/Array.mjs';
4
+
5
+ /**
6
+ * @class Neo.grid.plugin.AnimateRows
7
+ * @extends Neo.plugin.Base
8
+ */
9
+ class AnimateRows extends Base {
10
+ /**
11
+ * Valid values for transitionEasing
12
+ * @member {String[]} transitionEasings=['ease','ease-in','ease-out','ease-in-out','linear']
13
+ * @protected
14
+ * @static
15
+ */
16
+ static transitionEasings = ['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear']
17
+
18
+ static config = {
19
+ /**
20
+ * @member {String} className='Neo.grid.plugin.AnimateRows'
21
+ * @protected
22
+ */
23
+ className: 'Neo.grid.plugin.AnimateRows',
24
+ /**
25
+ * @member {String} ntype='plugin-grid-animate-rows'
26
+ * @protected
27
+ */
28
+ ntype: 'plugin-grid-animate-rows',
29
+ /**
30
+ * Time in ms. Please ensure to match the CSS based value, in case you change the default.
31
+ * @member {Number} transitionDuration_=500
32
+ */
33
+ transitionDuration_: 500,
34
+ /**
35
+ * The easing used for fadeIn, fadeOut and position changes.
36
+ * Valid values: 'ease','ease-in','ease-out','ease-in-out','linear'
37
+ * @member {String} transitionEasing_='ease-out'
38
+ */
39
+ transitionEasing_: 'ease-out'
40
+ }
41
+
42
+ /**
43
+ * The id of the setTimeout() call which gets triggered after a transition is done.
44
+ * @member {Number|null} transitionTimeoutId=null
45
+ * @protected
46
+ */
47
+ transitionTimeoutId = null
48
+
49
+ /**
50
+ * @param {Object} config
51
+ */
52
+ construct(config) {
53
+ super.construct(config);
54
+
55
+ let me = this,
56
+ {owner} = me,
57
+ {store} = owner;
58
+
59
+ // Remove the previous view listeners
60
+ owner.store = null;
61
+
62
+ owner.onStoreFilter = me.onStoreFilter.bind(me);
63
+ owner.onStoreLoad = me.onStoreLoad .bind(me);
64
+
65
+ // Add the re-bound listeners
66
+ owner.store = store;
67
+
68
+ me.updateTransitionDetails()
69
+ }
70
+
71
+ /**
72
+ * Triggered after the transitionDuration config got changed.
73
+ * @param {Number} value
74
+ * @param {Number} oldValue
75
+ * @protected
76
+ */
77
+ afterSetTransitionDuration(value, oldValue) {
78
+ this.isConstructed && this.updateTransitionDetails(Neo.isNumber(oldValue))
79
+ }
80
+
81
+ /**
82
+ * Triggered after the transitionEasing config got changed.
83
+ * @param {String} value
84
+ * @param {String} oldValue
85
+ * @protected
86
+ */
87
+ afterSetTransitionEasing(value, oldValue) {
88
+ this.isConstructed && this.updateTransitionDetails(!!oldValue)
89
+ }
90
+
91
+ /**
92
+ * Triggered before the transitionEasing config gets changed
93
+ * @param {String} value
94
+ * @param {String} oldValue
95
+ * @protected
96
+ */
97
+ beforeSetTransitionEasing(value, oldValue) {
98
+ return this.beforeSetEnumValue(value, oldValue, 'transitionEasing')
99
+ }
100
+
101
+ /**
102
+ * @param {Object} args
103
+ */
104
+ destroy(...args) {
105
+ CssUtil.deleteRules(this.appName, `#${this.owner.id} .neo-grid-row`);
106
+ super.destroy(...args)
107
+ }
108
+
109
+ /**
110
+ * @param {Object} data
111
+ * @param {Boolean} data.isFiltered
112
+ * @param {Object[]} data.items
113
+ * @param {Object[]} data.oldItems
114
+ * @param {Neo.data.Store} data.scope
115
+ */
116
+ onStoreFilter(data) {
117
+ this.updateView()
118
+ }
119
+
120
+ /**
121
+ * @param {Object[]} data
122
+ * @protected
123
+ */
124
+ onStoreLoad(data) {
125
+ this.updateView()
126
+ }
127
+
128
+ /**
129
+ * We do not want to apply the style to each list item itself,
130
+ * so we are using Neo.util.Css
131
+ * @param {Boolean} deleteRule=false
132
+ * @protected
133
+ */
134
+ async updateTransitionDetails(deleteRule=false) {
135
+ let me = this,
136
+ duration = me.transitionDuration,
137
+ easing = me.transitionEasing,
138
+ {id} = me.owner;
139
+
140
+ if (deleteRule) {
141
+ await CssUtil.deleteRules(me.appName, `#${id} .neo-grid-row`)
142
+ }
143
+
144
+ CssUtil.insertRules(me.appName, [
145
+ `#${id} .neo-grid-row {`,
146
+ 'transition:',
147
+ `background-color ${duration}ms ${easing},`,
148
+ `opacity ${duration}ms ${easing},`,
149
+ `transform ${duration}ms ${easing}`,
150
+ '}'
151
+ ].join(''))
152
+ }
153
+
154
+ /**
155
+ *
156
+ */
157
+ updateView() {
158
+ let me = this,
159
+ {owner} = me,
160
+ {mountedRows} = owner,
161
+ addedRows = [],
162
+ hasChange = false,
163
+ map = {},
164
+ rowsContainer = owner.getVdomRoot().cn,
165
+ id, mapItem, record, row, rowIndex, transform;
166
+
167
+ rowsContainer.forEach(row => {
168
+ map[row.id] = row
169
+ });
170
+
171
+ // Creates the new start & end indexes inside mountedRows
172
+ owner.updateMountedAndVisibleRows();
173
+
174
+ for (rowIndex=mountedRows[0]; rowIndex < mountedRows[1]; rowIndex++) {
175
+ record = owner.store.getAt(rowIndex);
176
+ id = owner.getRowId(record, rowIndex)
177
+ mapItem = map[id];
178
+
179
+ if (mapItem) {
180
+ // Inside the map (previous state) & vdom => move OP
181
+ transform = `translate(0px, ${rowIndex * owner.rowHeight}px)`;
182
+
183
+ if (mapItem.style.transform !== transform) {
184
+ mapItem.style.opacity = .9; // slightly less than 1 to see visual overlays while moving
185
+ mapItem.style.transform = transform;
186
+ NeoArray.toggle(mapItem.cls, 'neo-even', rowIndex % 2 !== 0);
187
+ hasChange = true
188
+ }
189
+
190
+ delete map[id]
191
+ } else {
192
+ // Inside the vdom, but not the map => insert OP
193
+ row = owner.createRow({record, rowIndex});
194
+
195
+ row.style.opacity = 0;
196
+
197
+ addedRows .push(row);
198
+ rowsContainer.push(row);
199
+
200
+ owner.updateDepth = -1; // Added rows might contain components
201
+ hasChange = true
202
+ }
203
+ }
204
+
205
+ // Only rows which need to get removed are still inside the map
206
+ Object.values(map).forEach(row => {
207
+ row.style.opacity = 0;
208
+ hasChange = true
209
+ });
210
+
211
+ if (hasChange) {
212
+ clearTimeout(me.transitionTimeoutId);
213
+
214
+ owner.promiseUpdate().then(() => {
215
+ if (addedRows.length > 0) {
216
+ // Added rows need a 2nd DOM update to change the opacity from 0 to 1.
217
+ // If we added them with 1 directly, there would not be a fade-in transition.
218
+ addedRows.forEach(row => {
219
+ row.style.opacity = 1
220
+ });
221
+
222
+ owner.update()
223
+ }
224
+ });
225
+
226
+ me.transitionTimeoutId = setTimeout(() => {
227
+ me.transitionTimeoutId = null;
228
+ owner.createViewData()
229
+ }, me.transitionDuration)
230
+ }
231
+ }
232
+ }
233
+
234
+ export default Neo.setupClass(AnimateRows);
@@ -80,7 +80,7 @@ class Animate extends Base {
80
80
  owner.onStoreFilter = me.onStoreFilter.bind(me);
81
81
  owner.onStoreSort = me.onStoreSort .bind(me);
82
82
 
83
- this.updateTransitionDetails(false)
83
+ this.updateTransitionDetails()
84
84
  }
85
85
 
86
86
  /**
@@ -152,6 +152,14 @@ class Animate extends Base {
152
152
  return item
153
153
  }
154
154
 
155
+ /**
156
+ * @param {Object} args
157
+ */
158
+ destroy(...args) {
159
+ CssUtil.deleteRules(this.appName, `#${this.owner.id} .neo-list-item`);
160
+ super.destroy(...args)
161
+ }
162
+
155
163
  /**
156
164
  * @param {Object} record
157
165
  * @param {Number} index
@@ -412,18 +420,19 @@ class Animate extends Base {
412
420
  }
413
421
 
414
422
  /**
415
- * We do not want to apply the style to each list item itself,
416
- * so we are using Neo.util.Css
417
- * @param {Boolean} deleteRule
423
+ * We do not want to apply the style to each list item itself, so we are using Neo.util.Css
424
+ * @param {Boolean} deleteRule=false
418
425
  * @protected
419
426
  */
420
- updateTransitionDetails(deleteRule) {
427
+ async updateTransitionDetails(deleteRule=false) {
421
428
  let me = this,
422
429
  duration = me.transitionDuration,
423
430
  easing = me.transitionEasing,
424
- id = me.owner.id;
431
+ {id} = me.owner;
425
432
 
426
- deleteRule && CssUtil.deleteRules(me.appName, `#${id} .neo-list-item`);
433
+ if (deleteRule) {
434
+ await CssUtil.deleteRules(me.appName, `#${id} .neo-list-item`)
435
+ }
427
436
 
428
437
  CssUtil.insertRules(me.appName, [
429
438
  `#${id} .neo-list-item {`,
@@ -250,7 +250,7 @@ class Helper extends Base {
250
250
  return deltas
251
251
  }
252
252
 
253
- if (vnodeId !== oldVnodeId) {
253
+ if (vnodeId !== oldVnodeId && vnode.componentId !== oldVnode.componentId) {
254
254
  throw new Error(`createDeltas() must get called for the same node. ${vnodeId}, ${oldVnodeId}`);
255
255
  }
256
256
 
@@ -295,18 +295,16 @@ class Manager extends Base {
295
295
 
296
296
  /**
297
297
  * Handler method for worker message events
298
- * @param {Object} e
298
+ * @param {Object} event
299
299
  */
300
- onWorkerMessage(e) {
300
+ onWorkerMessage(event) {
301
301
  let me = this,
302
- {data} = e,
302
+ {data} = event,
303
303
  transfer = null,
304
304
  promise;
305
305
 
306
306
  const {action, destination: dest, replyId} = data;
307
307
 
308
- // console.log('Main: Incoming Worker message: ' + data.origin + ':' + action, data);
309
-
310
308
  me.fire('message:'+action, data);
311
309
 
312
310
  if (action === 'reply') {
@@ -317,14 +315,14 @@ class Manager extends Base {
317
315
  data.data.autoMount && me.fire('automount', data);
318
316
  data.data.updateVdom && me.fire('updateVdom', data);
319
317
 
320
- // we want to delay the message until the rendering queue has processed it
321
- // see: https://github.com/neomjs/neo/issues/2864
318
+ // We want to delay the message until the rendering queue has processed it
319
+ // See: https://github.com/neomjs/neo/issues/2864
322
320
  me.promiseForwardMessage(data).then(msgData => {
323
321
  me.sendMessage(msgData.destination, msgData)
324
322
  })
325
323
  }
326
324
  } else {
327
- if (data.destination === 'main') {
325
+ if (dest === 'main') {
328
326
  data = data.data
329
327
  }
330
328