neo.mjs 8.43.1 → 9.0.1

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 (48) hide show
  1. package/apps/ServiceWorker.mjs +2 -2
  2. package/apps/colors/view/ViewportController.mjs +2 -6
  3. package/apps/portal/index.html +1 -1
  4. package/apps/portal/view/ViewportController.mjs +5 -6
  5. package/apps/portal/view/home/FooterContainer.mjs +1 -1
  6. package/apps/portal/view/learn/ContentComponent.mjs +5 -5
  7. package/apps/portal/view/learn/MainContainerController.mjs +0 -23
  8. package/apps/sharedcovid/view/MainContainerController.mjs +4 -13
  9. package/examples/ServiceWorker.mjs +2 -2
  10. package/examples/button/base/MainContainer.mjs +9 -1
  11. package/examples/component/multiWindowCoronaGallery/ViewportController.mjs +4 -11
  12. package/examples/component/multiWindowHelix/ViewportController.mjs +1 -7
  13. package/package.json +5 -5
  14. package/src/DefaultConfig.mjs +2 -2
  15. package/src/button/Base.mjs +28 -7
  16. package/src/component/Base.mjs +43 -86
  17. package/src/component/wrapper/AmChart.mjs +4 -3
  18. package/src/container/Base.mjs +15 -3
  19. package/src/controller/Component.mjs +4 -106
  20. package/src/core/Base.mjs +15 -2
  21. package/src/core/Observable.mjs +9 -11
  22. package/src/data/Model.mjs +9 -0
  23. package/src/data/RecordFactory.mjs +1 -1
  24. package/src/form/field/Text.mjs +3 -1
  25. package/src/grid/Container.mjs +2 -4
  26. package/src/grid/View.mjs +37 -45
  27. package/src/grid/column/AnimatedChange.mjs +1 -1
  28. package/src/grid/column/Component.mjs +14 -5
  29. package/src/grid/header/Button.mjs +6 -17
  30. package/src/layout/Base.mjs +3 -2
  31. package/src/layout/Cube.mjs +41 -37
  32. package/src/main/DomEvents.mjs +26 -1
  33. package/src/manager/DomEvent.mjs +21 -22
  34. package/src/selection/Model.mjs +14 -11
  35. package/src/selection/grid/BaseModel.mjs +155 -2
  36. package/src/selection/grid/CellColumnModel.mjs +7 -11
  37. package/src/selection/grid/CellColumnRowModel.mjs +7 -11
  38. package/src/selection/grid/CellModel.mjs +5 -4
  39. package/src/selection/grid/CellRowModel.mjs +22 -30
  40. package/src/selection/grid/ColumnModel.mjs +7 -11
  41. package/src/selection/grid/RowModel.mjs +21 -35
  42. package/src/state/Provider.mjs +3 -8
  43. package/src/tab/Container.mjs +17 -1
  44. package/src/table/Container.mjs +38 -91
  45. package/src/table/View.mjs +51 -3
  46. package/src/table/header/Button.mjs +7 -18
  47. package/src/util/Function.mjs +3 -1
  48. package/src/util/VDom.mjs +4 -4
@@ -1,6 +1,5 @@
1
1
  import Base from './Base.mjs';
2
2
  import {resolveCallback} from '../util/Function.mjs';
3
- import Logger from '../util/Logger.mjs';
4
3
 
5
4
  /**
6
5
  * @class Neo.controller.Component
@@ -70,17 +69,18 @@ class Component extends Base {
70
69
 
71
70
  /**
72
71
  * @param {String} handlerName
73
- * @param {Neo.component.Base} [component]
72
+ * @param {Neo.component.Base|null} [component]
74
73
  * @returns {Neo.controller.Component|Boolean|null}
75
74
  */
76
75
  getHandlerScope(handlerName, component) {
77
76
  let me = this,
78
- {parent} = me;
77
+ {parent} = me,
78
+ handlerCb;
79
79
 
80
80
  if (component) {
81
81
  // Look for ths function *name* first in the Component itself.
82
82
  // If we find it, return true so calling code knows not to continue to search.
83
- const handlerCb = resolveCallback(handlerName, component);
83
+ handlerCb = resolveCallback(handlerName, component);
84
84
 
85
85
  // Handler fn is resolved in the Component or its own parent chain.
86
86
  // Return a status indicating that we do not need an early binding
@@ -162,108 +162,6 @@ class Component extends Base {
162
162
  */
163
163
  onComponentConstructed() {}
164
164
 
165
- /**
166
- * @param {Neo.component.Base} component=this.component
167
- */
168
- parseConfig(component=this.component) {
169
- let me = this,
170
- {handler, listeners, reference, renderer, validator} = component,
171
- eventHandler, handlerScope;
172
-
173
- if (handler && Neo.isString(handler)) {
174
- handlerScope = me.getHandlerScope(handler, component);
175
-
176
- // If the handler name was not resolved in the Component itself, bind it
177
- if (handlerScope !== true) {
178
- component.handler = handlerScope[handler].bind(component.handlerScope || handlerScope);
179
- }
180
- }
181
-
182
- listeners && Object.entries(listeners).forEach(([key, value]) => {
183
- if (key !== 'scope' && key !== 'delegate') {
184
- if (Neo.isString(value)) {
185
- eventHandler = value;
186
- handlerScope = me.getHandlerScope(eventHandler, component);
187
-
188
- if (!handlerScope) {
189
- Logger.logError('Unknown event handler for', eventHandler, component)
190
- } else if (handlerScope !== true) {
191
- listeners[key] = {};
192
- listeners[key].fn = handlerScope[eventHandler].bind(handlerScope)
193
- }
194
- } else {
195
- value?.forEach?.(listener => {
196
- if (Neo.isObject(listener) && listener.hasOwnProperty('fn') && Neo.isString(listener.fn)) {
197
- eventHandler = listener.fn;
198
- handlerScope = me.getHandlerScope(eventHandler, component);
199
-
200
- if (!handlerScope) {
201
- console.error('Unknown event handler for', eventHandler, component)
202
- } else if (handlerScope !== true) {
203
- listener.fn = handlerScope[eventHandler].bind(handlerScope)
204
- }
205
- }
206
- })
207
- }
208
- }
209
- });
210
-
211
- if (renderer && Neo.isString(renderer)) {
212
- handlerScope = me.getHandlerScope(renderer);
213
-
214
- if (handlerScope) {
215
- component.renderer = handlerScope[renderer].bind(handlerScope)
216
- }
217
- }
218
-
219
- if (validator && Neo.isString(validator)) {
220
- handlerScope = me.getHandlerScope(validator);
221
-
222
- if (!handlerScope) {
223
- Logger.logError('Unknown validator for', component.id, component)
224
- } else {
225
- component.validator = handlerScope[validator].bind(handlerScope)
226
- }
227
- }
228
-
229
- if (reference) {
230
- me.references[reference] = component
231
- }
232
- }
233
-
234
- /**
235
- * @param {Neo.component.Base} component=this.component
236
- */
237
- parseDomListeners(component=this.component) {
238
- let me = this,
239
- {domListeners} = component,
240
- eventHandler, scope;
241
-
242
- domListeners?.forEach(domListener => {
243
- Object.entries(domListener).forEach(([key, value]) => {
244
- eventHandler = null;
245
-
246
- if (key !== 'scope' && key !== 'delegate') {
247
- if (Neo.isString(value)) {
248
- eventHandler = value;
249
- } else if (Neo.isObject(value) && value.hasOwnProperty('fn') && Neo.isString(value.fn)) {
250
- eventHandler = value.fn;
251
- }
252
-
253
- if (eventHandler) {
254
- scope = me.getHandlerScope(eventHandler);
255
-
256
- // There can be string based listeners like 'up.onClick', which will resolved inside manager.DomEvents
257
- // => Do nothing in case there is no match inside the controller hierarchy.
258
- if (scope) {
259
- domListener[key] = scope[eventHandler].bind(scope)
260
- }
261
- }
262
- }
263
- })
264
- })
265
- }
266
-
267
165
  /**
268
166
  * Will get called by component.Base: destroy() in case the component has a reference config
269
167
  * @param {Neo.component.Base} component
package/src/core/Base.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import {buffer, debounce, intercept, throttle} from '../util/Function.mjs';
2
- import IdGenerator from './IdGenerator.mjs'
1
+ import {buffer, debounce, intercept, resolveCallback, throttle} from '../util/Function.mjs';
2
+ import IdGenerator from './IdGenerator.mjs'
3
3
 
4
4
  const configSymbol = Symbol.for('configSymbol'),
5
5
  forceAssignConfigs = Symbol('forceAssignConfigs'),
@@ -255,6 +255,19 @@ class Base {
255
255
  return value
256
256
  }
257
257
 
258
+ /**
259
+ * @param {String} fn The name of a function to find in the passed scope object.
260
+ * @param {Object} originName The name of the method inside the originScope.
261
+ * @param {Object} scope The scope to find the function in if it is specified as a string.
262
+ * @param {Object} originScope=this The scope where the function is located.
263
+ */
264
+ bindCallback(fn, originName, scope=this, originScope=this) {
265
+ if (fn && Neo.isString(fn)) {
266
+ const handler = resolveCallback(fn, scope);
267
+ originScope[originName] = handler.fn.bind(handler.scope)
268
+ }
269
+ }
270
+
258
271
  /**
259
272
  * From within an overwrite, a method can call a parent method, by using callOverwritten.
260
273
  *
@@ -101,14 +101,12 @@ class Observable extends Base {
101
101
  }
102
102
 
103
103
  if (!nameObject) {
104
- eventConfig = {
105
- data,
106
- delay,
107
- fn: listener,
108
- id: eventId || Neo.getId('event'),
109
- once,
110
- scope
111
- };
104
+ eventConfig = {fn: listener, id: eventId || Neo.getId('event')};
105
+
106
+ if (data) {eventConfig.data = data}
107
+ if (delay > 0) {eventConfig.delay = delay}
108
+ if (once) {eventConfig.once = once}
109
+ if (scope) {eventConfig.scope = scope}
112
110
 
113
111
  if (existing = me.listeners?.[name]) {
114
112
  existing.forEach(cfg => {
@@ -137,9 +135,9 @@ class Observable extends Base {
137
135
  /**
138
136
  * Call the passed function, or a function by *name* which exists in the passed scope's
139
137
  * or this component's ownership chain.
140
- * @param {Function|String} fn A function, or the name of a function to find in the passed scope object/
141
- * @param {Object} scope The scope to find the function in if it is specified as a string.
142
- * @param {Array} args Arguments to pass to the callback.
138
+ * @param {Function|String} fn A function, or the name of a function to find in the passed scope object.
139
+ * @param {Object} scope The scope to find the function in if it is specified as a string.
140
+ * @param {Array} args Arguments to pass to the callback.
143
141
  */
144
142
  callback(fn, scope=this, args) {
145
143
  if (fn) {
@@ -86,6 +86,15 @@ class Model extends Base {
86
86
  return this.fieldsMap.get(name) || null
87
87
  }
88
88
 
89
+ /**
90
+ * Finds a field type by a given field name
91
+ * @param {String} name
92
+ * @returns {String|null} The lowercase field type or null if no match was found
93
+ */
94
+ getFieldType(name) {
95
+ return this.getField(name)?.type?.toLowerCase() || null
96
+ }
97
+
89
98
  /**
90
99
  * @param {Object[]} fields
91
100
  * @param {Boolean} isRoot=true
@@ -233,7 +233,7 @@ class RecordFactory extends Base {
233
233
  * @returns {Object}
234
234
  */
235
235
  toJSON() {
236
- return this[dataSymbol]
236
+ return structuredClone(this[dataSymbol])
237
237
  }
238
238
  };
239
239
 
@@ -1600,7 +1600,9 @@ class Text extends Field {
1600
1600
  } else if (inputPattern && !inputPattern.test(value)) {
1601
1601
  me._error = me.errorTextInputPattern(errorParam);
1602
1602
  returnValue = false
1603
- } else if (Neo.isFunction(me.validator)) {
1603
+ } else if (me.validator) {
1604
+ me.bindCallback(me.validator, 'validator');
1605
+
1604
1606
  errorText = me.validator(me);
1605
1607
 
1606
1608
  if (errorText !== true) {
@@ -459,9 +459,7 @@ class GridContainer extends BaseContainer {
459
459
  parent : me,
460
460
  windowId: me.windowId,
461
461
  ...column
462
- });
463
-
464
- me.getController()?.parseConfig(columns[index])
462
+ })
465
463
  });
466
464
 
467
465
  me.items[0].items = headerButtons;
@@ -563,7 +561,7 @@ class GridContainer extends BaseContainer {
563
561
 
564
562
  me.store.sort(opts);
565
563
  me.removeSortingCss(opts.property);
566
- me.view.onStoreLoad()
564
+ opts.direction && me.view.onStoreLoad()
567
565
  }
568
566
 
569
567
  /**
package/src/grid/View.mjs CHANGED
@@ -181,10 +181,6 @@ class GridView extends Component {
181
181
  get selectedRows() {
182
182
  let {selectionModel} = this;
183
183
 
184
- if (selectionModel.ntype === 'selection-grid-rowmodel') {
185
- return selectionModel.items
186
- }
187
-
188
184
  if (selectionModel.ntype?.includes('row')) {
189
185
  return selectionModel.selectedRows
190
186
  }
@@ -450,6 +446,8 @@ class GridView extends Component {
450
446
  column.rendererScope = column;
451
447
  }
452
448
 
449
+ me.bindCallback(column.renderer, 'renderer', column.rendererScope || me, column);
450
+
453
451
  rendererOutput = column.renderer.call(column.rendererScope || me, {
454
452
  column,
455
453
  columnIndex,
@@ -496,7 +494,7 @@ class GridView extends Component {
496
494
  }
497
495
 
498
496
  if (!cellId) {
499
- cellId = me.getCellId(record, column.dataField)
497
+ cellId = me.getCellId(rowIndex, column.dataField)
500
498
  }
501
499
 
502
500
  if (selectedCells.includes(cellId)) {
@@ -575,7 +573,8 @@ class GridView extends Component {
575
573
  {mountedColumns, selectedRows} = me,
576
574
  gridContainer = me.parent,
577
575
  {columns} = gridContainer,
578
- id = me.getRowId(record, rowIndex),
576
+ id = me.getRowId(rowIndex),
577
+ recordId = record[me.store.getKeyProperty()],
579
578
  rowCls = me.getRowClass(record, rowIndex),
580
579
  config, column, columnPosition, gridRow, i;
581
580
 
@@ -584,12 +583,7 @@ class GridView extends Component {
584
583
  }
585
584
 
586
585
  if (selectedRows && record[me.selectedRecordField]) {
587
- NeoArray.add(selectedRows, id)
588
- }
589
-
590
- if (selectedRows?.includes(id)) {
591
- rowCls.push('neo-selected');
592
- gridContainer.fire('select', {record})
586
+ NeoArray.add(selectedRows, recordId)
593
587
  }
594
588
 
595
589
  gridRow = {
@@ -597,6 +591,7 @@ class GridView extends Component {
597
591
  'aria-rowindex': rowIndex + 2, // header row => 1, first body row => 2
598
592
  cls : rowCls,
599
593
  cn : [],
594
+ data : {recordId},
600
595
  role : 'row',
601
596
 
602
597
  style: {
@@ -605,6 +600,12 @@ class GridView extends Component {
605
600
  }
606
601
  };
607
602
 
603
+ if (selectedRows?.includes(recordId)) {
604
+ rowCls.push('neo-selected');
605
+ gridRow['aria-selected'] = true;
606
+ gridContainer.fire('select', {record})
607
+ }
608
+
608
609
  for (i=mountedColumns[0]; i <= mountedColumns[1]; i++) {
609
610
  column = columns.getAt(i);
610
611
  config = me.applyRendererOutput({column, columnIndex: i, record, rowIndex});
@@ -709,12 +710,12 @@ class GridView extends Component {
709
710
  }
710
711
 
711
712
  /**
712
- * @param {Object} record
713
+ * @param {Number} rowIndex
713
714
  * @param {String} dataField
714
715
  * @returns {String}
715
716
  */
716
- getCellId(record, dataField) {
717
- return this.id + '__' + record[this.store.getKeyProperty()] + '__' + dataField
717
+ getCellId(rowIndex, dataField) {
718
+ return this.getRowId(rowIndex) + '__' + dataField
718
719
  }
719
720
 
720
721
  /**
@@ -803,36 +804,23 @@ class GridView extends Component {
803
804
  return null
804
805
  }
805
806
 
806
- /**
807
- * @param {String} cellId
808
- * @returns {Record}
809
- */
810
- getRecordByCellId(cellId) {
811
- let recordId = cellId.split('__')[1],
812
- {store} = this,
813
- keyType = store.getKeyType();
814
-
815
- if (keyType === 'int' || keyType === 'integer') {
816
- recordId = parseInt(recordId)
817
- }
818
-
819
- return store.get(recordId)
820
- }
821
-
822
807
  /**
823
808
  * @param {String} rowId
824
- * @returns {Record}
809
+ * @returns {Record|null}
825
810
  */
826
811
  getRecordByRowId(rowId) {
827
- let recordId = rowId.split('__')[2],
828
- {store} = this,
829
- keyType = store.getKeyType();
812
+ let me = this,
813
+ node = me.getVdomChild(rowId),
814
+ rowIndex = node['aria-rowindex'];
815
+
816
+ if (Neo.isNumber(rowIndex)) {
817
+ // aria-rowindex is 1 based & also includes the header
818
+ rowIndex -= 2;
830
819
 
831
- if (keyType === 'int' || keyType === 'integer') {
832
- recordId = parseInt(recordId)
820
+ return me.store.getAt(rowIndex)
833
821
  }
834
822
 
835
- return store.get(recordId)
823
+ return null
836
824
  }
837
825
 
838
826
  /**
@@ -846,11 +834,13 @@ class GridView extends Component {
846
834
  }
847
835
 
848
836
  /**
849
- * @param {Object} record
837
+ * @param {Number} rowIndex
850
838
  * @returns {String}
851
839
  */
852
- getRowId(record) {
853
- return `${this.id}__tr__${record[this.store.getKeyProperty()]}`
840
+ getRowId(rowIndex) {
841
+ let me = this;
842
+
843
+ return `${me.id}__row-${rowIndex % (me.availableRows + 2 * me.bufferRowRange)}`
854
844
  }
855
845
 
856
846
  /**
@@ -951,7 +941,7 @@ class GridView extends Component {
951
941
  needsUpdate = false,
952
942
  rowIndex = me.store.indexOf(record),
953
943
  {selectionModel} = me,
954
- column, needsCellUpdate;
944
+ column, needsCellUpdate, recordId;
955
945
 
956
946
  if (fieldNames.includes(me.colspanField)) {
957
947
  me.vdom.cn[rowIndex] = me.createRow({record, rowIndex});
@@ -971,7 +961,9 @@ class GridView extends Component {
971
961
  fields.forEach(field => {
972
962
  if (field.name === me.selectedRecordField) {
973
963
  if (selectionModel.ntype === 'selection-grid-rowmodel') {
974
- selectionModel[field.value ? 'select' : 'deselect'](me.getRowId(record))
964
+ recordId = record[me.store.getKeyProperty()];
965
+
966
+ selectionModel[field.value ? 'selectRow' : 'deselectRow'](recordId)
975
967
  }
976
968
  } else {
977
969
  needsCellUpdate = me.updateCellNode(record, field.name);
@@ -1040,10 +1032,10 @@ class GridView extends Component {
1040
1032
  */
1041
1033
  updateCellNode(record, dataField) {
1042
1034
  let me = this,
1043
- cellId = me.getCellId(record, dataField),
1035
+ rowIndex = me.store.indexOf(record),
1036
+ cellId = me.getCellId(rowIndex, dataField),
1044
1037
  cellNode = VDomUtil.find(me.vdom, cellId),
1045
1038
  needsUpdate = false,
1046
- rowIndex = me.store.indexOf(record),
1047
1039
  cellStyle, cellVdom, column, columnIndex;
1048
1040
 
1049
1041
  // The vdom might not exist yet => nothing to do in this case
@@ -63,7 +63,7 @@ class AnimatedChange extends Column {
63
63
  // Wait for the next animation frame
64
64
  await me.timeout(20);
65
65
 
66
- cellId = view.getCellId(record, me.dataField);
66
+ cellId = view.getCellId(me.parent.store.indexOf(record), me.dataField);
67
67
  node = VdomUtil.find(view.vdom, cellId)?.vdom;
68
68
 
69
69
  if (node) {
@@ -38,7 +38,12 @@ class Component extends Column {
38
38
  * @member {String} type='component'
39
39
  * @protected
40
40
  */
41
- type: 'component'
41
+ type: 'component',
42
+ /**
43
+ * Set this config to true, in case you want to use 'bind' inside your cell based component.
44
+ * @member {Boolean} useBindings=false
45
+ */
46
+ useBindings: false
42
47
  }
43
48
 
44
49
  /**
@@ -104,13 +109,17 @@ class Component extends Column {
104
109
  windowId
105
110
  });
106
111
 
112
+ // We need to ensure that wrapped components always get the same index-based id.
113
+ if (!component.vdom.id) {
114
+ component.vdom.id = id + '__wrapper'
115
+ }
116
+
107
117
  me.map.set(id, component)
108
118
  }
109
119
 
110
- // The componentConfig can contain bindings into a view controller, e.g. a button handler = 'editButtonHandler'
111
- // componentConfig.set(component) can revert these, so we need a parseConfig() for each change.
112
- view.getController() ?.parseConfig(component);
113
- view.getStateProvider()?.parseConfig(component);
120
+ if (me.useBindings) {
121
+ view.getStateProvider()?.parseConfig(component)
122
+ }
114
123
 
115
124
  view.updateDepth = -1;
116
125
 
@@ -176,21 +176,7 @@ class Button extends BaseButton {
176
176
  let me = this,
177
177
  {cls} = me;
178
178
 
179
- if (value) {
180
- NeoArray.remove(cls, 'neo-sort-hidden');
181
-
182
- me.addDomListeners({
183
- click: me.onButtonClick,
184
- scope: me
185
- })
186
- } else {
187
- NeoArray.add(cls, 'neo-sort-hidden');
188
-
189
- me.removeDomListeners({
190
- click: me.onButtonClick,
191
- scope: me
192
- })
193
- }
179
+ NeoArray.toggle(cls, 'neo-sort-hidden', !value);
194
180
 
195
181
  me.cls = cls;
196
182
  me.update()
@@ -215,9 +201,10 @@ class Button extends BaseButton {
215
201
  }
216
202
 
217
203
  /**
204
+ * @param {Object} data
218
205
  * @protected
219
206
  */
220
- onButtonClick() {
207
+ onClick(data) {
221
208
  let me = this,
222
209
  map;
223
210
 
@@ -235,7 +222,9 @@ class Button extends BaseButton {
235
222
  }
236
223
  }
237
224
 
238
- me.isSorted = map[me.isSorted + '']
225
+ me.isSorted = map[me.isSorted + ''];
226
+
227
+ super.onClick(data)
239
228
  }
240
229
 
241
230
  /**
@@ -77,9 +77,10 @@ class Layout extends Base {
77
77
  applyChildAttributes(item, index) {}
78
78
 
79
79
  /**
80
+ * @param {Boolean} silent=false
80
81
  * @protected
81
82
  */
82
- applyRenderAttributes() {
83
+ applyRenderAttributes(silent=false) {
83
84
  let me = this,
84
85
  {container, containerCls} = me,
85
86
  {wrapperCls} = container;
@@ -91,7 +92,7 @@ class Layout extends Base {
91
92
 
92
93
  NeoArray.add(wrapperCls, containerCls);
93
94
 
94
- container.wrapperCls = wrapperCls
95
+ container[silent ? 'setSilent' : 'set']({wrapperCls})
95
96
  }
96
97
  }
97
98
 
@@ -286,44 +286,15 @@ class Cube extends Card {
286
286
  }
287
287
 
288
288
  /**
289
- *
289
+ * @returns {String}
290
290
  */
291
- destroy(...args) {
292
- let me = this,
293
- {container} = me,
294
- {style, vdom} = container;
295
-
296
- Object.assign(style, {
297
- '--perspective': null,
298
- '--rot-x' : null,
299
- '--rot-y' : null,
300
- '--rot-z' : null,
301
- '--side-x' : null,
302
- '--side-y' : null,
303
- '--side-z' : null
304
- });
305
-
306
- container.style = style;
307
-
308
- vdom.cn = container.getVdomItemsRoot().cn;
309
-
310
- if (me.hideInactiveCardsOnDestroy) {
311
- container.items.forEach((item, index) => {
312
- if (index < 6 && index !== me.activeIndex) {
313
- item.vdom.removeDom = true
314
- }
315
- })
316
- }
317
-
318
- // override
319
- container.getVdomItemsRoot = me.#cachedVdomItemsRoot;
320
-
321
- container.updateDepth = -1;
322
- container.update();
323
-
324
- super.destroy(...args)
291
+ getPlaneId() {
292
+ return this.id + '__plane'
325
293
  }
326
294
 
295
+ /**
296
+ *
297
+ */
327
298
  nestVdom() {
328
299
  let me = this,
329
300
  {container} = me,
@@ -331,7 +302,7 @@ class Cube extends Card {
331
302
  {cn} = vdom;
332
303
 
333
304
  vdom.cn = [
334
- {cls: ['neo-plane'], cn: [
305
+ {cls: ['neo-plane'], id: me.getPlaneId(), cn: [
335
306
  {cls: ['neo-box'], cn}
336
307
  ]}
337
308
  ];
@@ -394,7 +365,40 @@ class Cube extends Card {
394
365
  */
395
366
  removeRenderAttributes() {
396
367
  super.removeRenderAttributes();
397
- this.container.removeCls('neo-animate')
368
+
369
+ let me = this,
370
+ {container} = me,
371
+ {cls, style, vdom} = container;
372
+
373
+ NeoArray.remove(cls, 'neo-animate');
374
+
375
+ Object.assign(style, {
376
+ '--perspective': null,
377
+ '--rot-x' : null,
378
+ '--rot-y' : null,
379
+ '--rot-z' : null,
380
+ '--side-x' : null,
381
+ '--side-y' : null,
382
+ '--side-z' : null
383
+ });
384
+
385
+ container.set({cls, style});
386
+
387
+ vdom.cn = container.getVdomItemsRoot().cn;
388
+
389
+ if (me.hideInactiveCardsOnDestroy) {
390
+ container.items.forEach((item, index) => {
391
+ if (index < 6 && index !== me.activeIndex) {
392
+ item.vdom.removeDom = true
393
+ }
394
+ })
395
+ }
396
+
397
+ // override
398
+ container.getVdomItemsRoot = me.#cachedVdomItemsRoot;
399
+
400
+ container.updateDepth = -1;
401
+ container.update();
398
402
  }
399
403
 
400
404
  /**