handsontable 15.0.1-next-ab94a4c-20250207 → 15.1.0-next-dfdf994-20250206
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/3rdparty/walkontable/src/index.js +2 -0
- package/3rdparty/walkontable/src/index.mjs +2 -1
- package/3rdparty/walkontable/src/overlays.js +2 -39
- package/3rdparty/walkontable/src/overlays.mjs +2 -39
- package/3rdparty/walkontable/src/renderer/_base.js +3 -4
- package/3rdparty/walkontable/src/renderer/_base.mjs +2 -2
- package/3rdparty/walkontable/src/renderer/cells.js +7 -11
- package/3rdparty/walkontable/src/renderer/cells.mjs +6 -9
- package/3rdparty/walkontable/src/renderer/colGroup.js +6 -7
- package/3rdparty/walkontable/src/renderer/colGroup.mjs +5 -5
- package/3rdparty/walkontable/src/renderer/columnHeaders.js +4 -5
- package/3rdparty/walkontable/src/renderer/columnHeaders.mjs +3 -3
- package/3rdparty/walkontable/src/renderer/index.js +18 -19
- package/3rdparty/walkontable/src/renderer/index.mjs +6 -6
- package/3rdparty/walkontable/src/renderer/rowHeaders.js +6 -7
- package/3rdparty/walkontable/src/renderer/rowHeaders.mjs +5 -5
- package/3rdparty/walkontable/src/renderer/rows.js +23 -11
- package/3rdparty/walkontable/src/renderer/rows.mjs +23 -10
- package/3rdparty/walkontable/src/renderer/table.js +1 -1
- package/3rdparty/walkontable/src/renderer/table.mjs +1 -1
- package/3rdparty/walkontable/src/selection/border/border.js +10 -2
- package/3rdparty/walkontable/src/selection/border/border.mjs +10 -2
- package/3rdparty/walkontable/src/utils/nodesPool.js +21 -6
- package/3rdparty/walkontable/src/utils/nodesPool.mjs +21 -6
- package/3rdparty/walkontable/src/utils/orderView/index.js +4 -5
- package/3rdparty/walkontable/src/utils/orderView/index.mjs +2 -2
- package/3rdparty/walkontable/src/utils/orderView/sharedView.js +3 -4
- package/3rdparty/walkontable/src/utils/orderView/sharedView.mjs +2 -2
- package/3rdparty/walkontable/src/utils/orderView/view.js +60 -76
- package/3rdparty/walkontable/src/utils/orderView/view.mjs +59 -74
- package/3rdparty/walkontable/src/utils/orderView/viewDiffer/index.js +138 -0
- package/3rdparty/walkontable/src/utils/orderView/viewDiffer/index.mjs +135 -0
- package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.js +72 -0
- package/3rdparty/walkontable/src/utils/orderView/viewDiffer/viewOrder.mjs +68 -0
- package/3rdparty/walkontable/src/utils/orderView/viewSize.js +1 -1
- package/3rdparty/walkontable/src/utils/orderView/viewSize.mjs +1 -1
- package/3rdparty/walkontable/src/utils/orderView/viewSizeSet.js +4 -5
- package/3rdparty/walkontable/src/utils/orderView/viewSizeSet.mjs +3 -3
- package/CHANGELOG.md +51 -2
- package/README.md +3 -3
- package/base.js +2 -2
- package/base.mjs +2 -2
- package/cellTypes/dropdownType/dropdownType.js +4 -2
- package/cellTypes/dropdownType/dropdownType.mjs +4 -2
- package/core.js +39 -38
- package/core.mjs +36 -35
- package/dataMap/dataMap.js +8 -0
- package/dataMap/dataMap.mjs +8 -0
- package/dataMap/dataSource.js +4 -0
- package/dataMap/dataSource.mjs +4 -0
- package/dataMap/metaManager/lazyFactoryMap.js +8 -5
- package/dataMap/metaManager/lazyFactoryMap.mjs +8 -5
- package/dataMap/metaManager/metaSchema.js +24 -9
- package/dataMap/metaManager/metaSchema.mjs +24 -9
- package/dist/handsontable.css +6 -2
- package/dist/handsontable.full.css +6 -2
- package/dist/handsontable.full.js +8026 -6927
- package/dist/handsontable.full.min.css +3 -3
- package/dist/handsontable.full.min.js +530 -528
- package/dist/handsontable.js +3833 -2914
- package/dist/handsontable.min.css +3 -3
- package/dist/handsontable.min.js +35 -33
- package/editors/autocompleteEditor/autocompleteEditor.js +1 -3
- package/editors/autocompleteEditor/autocompleteEditor.mjs +1 -3
- package/editors/dateEditor/dateEditor.js +4 -0
- package/editors/dateEditor/dateEditor.mjs +4 -0
- package/editors/dropdownEditor/dropdownEditor.js +3 -16
- package/editors/dropdownEditor/dropdownEditor.mjs +3 -16
- package/editors/handsontableEditor/handsontableEditor.js +4 -4
- package/editors/handsontableEditor/handsontableEditor.mjs +4 -4
- package/focusManager.js +1 -1
- package/focusManager.mjs +1 -1
- package/helpers/dom/element.d.ts +0 -1
- package/helpers/mixed.js +2 -2
- package/helpers/mixed.mjs +2 -2
- package/helpers/object.js +4 -0
- package/helpers/object.mjs +4 -0
- package/package.json +2 -2
- package/plugins/base/base.js +0 -7
- package/plugins/base/base.mjs +0 -7
- package/plugins/comments/comments.js +12 -3
- package/plugins/comments/comments.mjs +12 -3
- package/plugins/contextMenu/contextMenu.js +2 -7
- package/plugins/contextMenu/contextMenu.mjs +2 -7
- package/plugins/contextMenu/menu/menu.js +2 -2
- package/plugins/contextMenu/menu/menu.mjs +2 -2
- package/plugins/contextMenu/predefinedItems/clearColumn.js +15 -4
- package/plugins/contextMenu/predefinedItems/clearColumn.mjs +15 -4
- package/plugins/copyPaste/copyPaste.js +6 -12
- package/plugins/copyPaste/copyPaste.mjs +6 -12
- package/plugins/filters/conditionCollection.js +8 -7
- package/plugins/filters/conditionCollection.mjs +8 -7
- package/plugins/filters/filters.js +26 -16
- package/plugins/filters/filters.mjs +26 -16
- package/plugins/filters/utils.js +7 -24
- package/plugins/filters/utils.mjs +7 -24
- package/plugins/hiddenColumns/hiddenColumns.js +1 -3
- package/plugins/hiddenColumns/hiddenColumns.mjs +1 -3
- package/plugins/hiddenRows/hiddenRows.js +1 -3
- package/plugins/hiddenRows/hiddenRows.mjs +1 -3
- package/plugins/manualRowMove/manualRowMove.js +1 -1
- package/plugins/manualRowMove/manualRowMove.mjs +1 -1
- package/plugins/mergeCells/calculations/autofill.js +60 -44
- package/plugins/mergeCells/calculations/autofill.mjs +60 -44
- package/plugins/mergeCells/cellsCollection.js +25 -8
- package/plugins/mergeCells/cellsCollection.mjs +25 -8
- package/plugins/mergeCells/mergeCells.js +15 -16
- package/plugins/mergeCells/mergeCells.mjs +15 -16
- package/plugins/nestedHeaders/nestedHeaders.js +6 -1
- package/plugins/nestedHeaders/nestedHeaders.mjs +6 -1
- package/plugins/nestedHeaders/stateManager/index.js +1 -2
- package/plugins/nestedHeaders/stateManager/index.mjs +1 -2
- package/plugins/nestedHeaders/utils/ghostTable.js +4 -0
- package/plugins/nestedHeaders/utils/ghostTable.mjs +4 -0
- package/plugins/nestedRows/utils/rowMoveController.js +1 -6
- package/plugins/nestedRows/utils/rowMoveController.mjs +1 -6
- package/plugins/undoRedo/actions/_base.js +19 -0
- package/plugins/undoRedo/actions/_base.mjs +15 -0
- package/plugins/undoRedo/actions/cellAlignment.js +85 -0
- package/plugins/undoRedo/actions/cellAlignment.mjs +81 -0
- package/plugins/undoRedo/actions/columnMove.js +84 -0
- package/plugins/undoRedo/actions/columnMove.mjs +80 -0
- package/plugins/undoRedo/actions/columnSort.js +73 -0
- package/plugins/undoRedo/actions/columnSort.mjs +69 -0
- package/plugins/undoRedo/actions/createColumn.js +60 -0
- package/plugins/undoRedo/actions/createColumn.mjs +56 -0
- package/plugins/undoRedo/actions/createRow.js +65 -0
- package/plugins/undoRedo/actions/createRow.mjs +61 -0
- package/plugins/undoRedo/actions/dataChange.js +123 -0
- package/plugins/undoRedo/actions/dataChange.mjs +119 -0
- package/plugins/undoRedo/actions/filters.js +66 -0
- package/plugins/undoRedo/actions/filters.mjs +62 -0
- package/plugins/undoRedo/actions/index.js +27 -0
- package/plugins/undoRedo/actions/index.mjs +23 -0
- package/plugins/undoRedo/actions/mergeCells.js +63 -0
- package/plugins/undoRedo/actions/mergeCells.mjs +59 -0
- package/plugins/undoRedo/actions/removeColumn.js +176 -0
- package/plugins/undoRedo/actions/removeColumn.mjs +172 -0
- package/plugins/undoRedo/actions/removeRow.js +119 -0
- package/plugins/undoRedo/actions/removeRow.mjs +115 -0
- package/plugins/undoRedo/actions/rowMove.js +84 -0
- package/plugins/undoRedo/actions/rowMove.mjs +80 -0
- package/plugins/undoRedo/actions/unmergeCells.js +56 -0
- package/plugins/undoRedo/actions/unmergeCells.mjs +52 -0
- package/plugins/undoRedo/index.js +3 -4
- package/plugins/undoRedo/index.mjs +1 -2
- package/plugins/undoRedo/undoRedo.js +277 -879
- package/plugins/undoRedo/undoRedo.mjs +277 -880
- package/plugins/undoRedo/utils.js +37 -0
- package/plugins/undoRedo/utils.mjs +33 -0
- package/renderers/checkboxRenderer/checkboxRenderer.js +8 -1
- package/renderers/checkboxRenderer/checkboxRenderer.mjs +8 -1
- package/shortcutContexts/commands/moveCellSelection/downByViewportHeight.js +1 -0
- package/shortcutContexts/commands/moveCellSelection/downByViewportHeight.mjs +1 -0
- package/shortcutContexts/commands/moveCellSelection/upByViewportHeight.js +2 -1
- package/shortcutContexts/commands/moveCellSelection/upByViewportHeight.mjs +2 -1
- package/styles/handsontable.css +75 -103
- package/styles/handsontable.min.css +3 -3
- package/styles/ht-theme-horizon.css +2 -2
- package/styles/ht-theme-horizon.min.css +2 -2
- package/styles/ht-theme-main.css +2 -2
- package/styles/ht-theme-main.min.css +2 -2
- package/tableView.js +17 -1
- package/tableView.mjs +17 -1
- package/utils/autoResize.js +1 -1
- package/utils/autoResize.mjs +1 -1
- package/utils/parseTable.js +1 -1
- package/utils/parseTable.mjs +1 -1
- package/validators/dateValidator/dateValidator.js +1 -1
- package/validators/dateValidator/dateValidator.mjs +1 -1
@@ -3,8 +3,8 @@ import "core-js/modules/es.array.push.js";
|
|
3
3
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
4
4
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
5
5
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
6
|
-
import {
|
7
|
-
import
|
6
|
+
import { ViewSizeSet } from "./viewSizeSet.mjs";
|
7
|
+
import { ViewDiffer } from "./viewDiffer/index.mjs";
|
8
8
|
/**
|
9
9
|
* Executive model for each table renderer. It's responsible for injecting DOM nodes in a
|
10
10
|
* specified order and adjusting the number of elements in the root node.
|
@@ -13,8 +13,8 @@ import ViewSizeSet from "./viewSizeSet.mjs";
|
|
13
13
|
*
|
14
14
|
* @class {OrderView}
|
15
15
|
*/
|
16
|
-
export
|
17
|
-
constructor(rootNode, nodesPool
|
16
|
+
export class OrderView {
|
17
|
+
constructor(rootNode, nodesPool) {
|
18
18
|
/**
|
19
19
|
* The root node to manage with.
|
20
20
|
*
|
@@ -24,7 +24,7 @@ export default class OrderView {
|
|
24
24
|
/**
|
25
25
|
* Factory for newly created DOM elements.
|
26
26
|
*
|
27
|
-
* @type {
|
27
|
+
* @type {function(number): HTMLElement}
|
28
28
|
*/
|
29
29
|
_defineProperty(this, "nodesPool", void 0);
|
30
30
|
/**
|
@@ -34,26 +34,35 @@ export default class OrderView {
|
|
34
34
|
*/
|
35
35
|
_defineProperty(this, "sizeSet", new ViewSizeSet());
|
36
36
|
/**
|
37
|
-
*
|
37
|
+
* The list of DOM elements which are rendered for this render cycle.
|
38
38
|
*
|
39
|
-
* @type {
|
39
|
+
* @type {HTMLElement[]}
|
40
40
|
*/
|
41
|
-
_defineProperty(this, "
|
41
|
+
_defineProperty(this, "collectedNodes", []);
|
42
42
|
/**
|
43
|
-
* The
|
43
|
+
* The differ which calculates the differences between current and next view. It generates
|
44
|
+
* commands that are processed by the OrderView (see `applyCommand` method).
|
44
45
|
*
|
45
|
-
* @type {
|
46
|
+
* @type {ViewDiffer}
|
46
47
|
*/
|
47
|
-
_defineProperty(this, "
|
48
|
+
_defineProperty(this, "viewDiffer", new ViewDiffer(this.sizeSet));
|
48
49
|
/**
|
49
|
-
* The list of
|
50
|
+
* The list of render commands to execute. The command is an array with the following
|
51
|
+
* structure: [
|
52
|
+
* [
|
53
|
+
* 'prepend' | 'append' | 'insert_before' | 'replace' | 'remove', // command name
|
54
|
+
* 10, // processed node index
|
55
|
+
* 9, // previous node index (only for 'insert_before' and 'replace' commands)
|
56
|
+
* 8 // node index to remove (only for 'insert_before' command)
|
57
|
+
* ],
|
58
|
+
* ...
|
59
|
+
* ].
|
50
60
|
*
|
51
|
-
* @type {
|
61
|
+
* @type {Array[]}
|
52
62
|
*/
|
53
|
-
_defineProperty(this, "
|
63
|
+
_defineProperty(this, "leads", []);
|
54
64
|
this.rootNode = rootNode;
|
55
65
|
this.nodesPool = nodesPool;
|
56
|
-
this.childNodeType = childNodeType.toUpperCase();
|
57
66
|
}
|
58
67
|
|
59
68
|
/**
|
@@ -112,30 +121,38 @@ export default class OrderView {
|
|
112
121
|
}
|
113
122
|
|
114
123
|
/**
|
115
|
-
*
|
124
|
+
* Applies the commands generated by the differ into the specific DOM operations.
|
116
125
|
*
|
117
|
-
* @
|
126
|
+
* @param {Array} command The command to apply.
|
118
127
|
*/
|
119
|
-
|
128
|
+
applyCommand(command) {
|
120
129
|
const {
|
121
|
-
rootNode
|
122
|
-
sizeSet
|
130
|
+
rootNode
|
123
131
|
} = this;
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
132
|
+
const [name, nodeIndex, nodePrevIndex, nodeIndexToRemove] = command;
|
133
|
+
const node = this.nodesPool(nodeIndex);
|
134
|
+
this.collectedNodes.push(node);
|
135
|
+
switch (name) {
|
136
|
+
case 'prepend':
|
137
|
+
rootNode.insertBefore(node, rootNode.firstChild);
|
138
|
+
break;
|
139
|
+
case 'append':
|
140
|
+
rootNode.appendChild(node);
|
141
|
+
break;
|
142
|
+
case 'insert_before':
|
143
|
+
rootNode.insertBefore(node, this.nodesPool(nodePrevIndex));
|
144
|
+
// To keep the constant length of child nodes (after inserting a node) remove the last child.
|
145
|
+
rootNode.removeChild(this.nodesPool(nodeIndexToRemove));
|
146
|
+
break;
|
147
|
+
case 'replace':
|
148
|
+
rootNode.replaceChild(node, this.nodesPool(nodePrevIndex));
|
149
|
+
break;
|
150
|
+
case 'remove':
|
151
|
+
rootNode.removeChild(node);
|
152
|
+
break;
|
153
|
+
default:
|
154
|
+
break;
|
137
155
|
}
|
138
|
-
return childElementCount;
|
139
156
|
}
|
140
157
|
|
141
158
|
/**
|
@@ -144,30 +161,7 @@ export default class OrderView {
|
|
144
161
|
*/
|
145
162
|
start() {
|
146
163
|
this.collectedNodes.length = 0;
|
147
|
-
this.
|
148
|
-
const {
|
149
|
-
rootNode,
|
150
|
-
sizeSet
|
151
|
-
} = this;
|
152
|
-
const isShared = this.isSharedViewSet();
|
153
|
-
const {
|
154
|
-
nextSize
|
155
|
-
} = sizeSet.getViewSize();
|
156
|
-
let childElementCount = this.getRenderedChildCount();
|
157
|
-
while (childElementCount < nextSize) {
|
158
|
-
const newNode = this.nodesPool();
|
159
|
-
if (!isShared || isShared && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {
|
160
|
-
rootNode.appendChild(newNode);
|
161
|
-
} else {
|
162
|
-
rootNode.insertBefore(newNode, rootNode.firstChild);
|
163
|
-
}
|
164
|
-
childElementCount += 1;
|
165
|
-
}
|
166
|
-
const isSharedPlacedOnTop = isShared && sizeSet.isPlaceOn(WORKING_SPACE_TOP);
|
167
|
-
while (childElementCount > nextSize) {
|
168
|
-
rootNode.removeChild(isSharedPlacedOnTop ? rootNode.firstChild : rootNode.lastChild);
|
169
|
-
childElementCount -= 1;
|
170
|
-
}
|
164
|
+
this.leads = this.viewDiffer.diff();
|
171
165
|
}
|
172
166
|
|
173
167
|
/**
|
@@ -175,27 +169,18 @@ export default class OrderView {
|
|
175
169
|
* This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements).
|
176
170
|
*/
|
177
171
|
render() {
|
178
|
-
|
179
|
-
|
180
|
-
sizeSet
|
181
|
-
} = this;
|
182
|
-
let visualIndex = this.visualIndex;
|
183
|
-
if (this.isSharedViewSet() && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {
|
184
|
-
visualIndex += sizeSet.sharedSize.nextSize;
|
172
|
+
if (this.leads.length > 0) {
|
173
|
+
this.applyCommand(this.leads.shift());
|
185
174
|
}
|
186
|
-
let node = rootNode.childNodes[visualIndex];
|
187
|
-
if (node.tagName !== this.childNodeType) {
|
188
|
-
const newNode = this.nodesPool();
|
189
|
-
rootNode.replaceChild(newNode, node);
|
190
|
-
node = newNode;
|
191
|
-
}
|
192
|
-
this.collectedNodes.push(node);
|
193
|
-
this.visualIndex += 1;
|
194
175
|
}
|
195
176
|
|
196
177
|
/**
|
197
178
|
* Ends the render process.
|
198
179
|
* This method has to be called only once (at the end) for the render cycle.
|
199
180
|
*/
|
200
|
-
end() {
|
181
|
+
end() {
|
182
|
+
while (this.leads.length > 0) {
|
183
|
+
this.applyCommand(this.leads.shift());
|
184
|
+
}
|
185
|
+
}
|
201
186
|
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
exports.__esModule = true;
|
4
|
+
require("core-js/modules/es.error.cause.js");
|
5
|
+
require("core-js/modules/es.array.push.js");
|
6
|
+
var _constants = require("../constants");
|
7
|
+
var _viewOrder = require("./viewOrder");
|
8
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
9
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
10
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint-disable jsdoc/require-description-complete-sentence */
|
11
|
+
/**
|
12
|
+
* A class which is responsible for generating commands/leads which has to be executed
|
13
|
+
* to achieve new DOM nodes order.
|
14
|
+
*
|
15
|
+
* @class {ViewDiffer}
|
16
|
+
*/
|
17
|
+
class ViewDiffer {
|
18
|
+
constructor(sizeSet) {
|
19
|
+
_defineProperty(this, "sizeSet", void 0);
|
20
|
+
this.sizeSet = sizeSet;
|
21
|
+
}
|
22
|
+
|
23
|
+
/**
|
24
|
+
* A method which generates commands/leads which has to be executed to achieve new DOM
|
25
|
+
* nodes order based on new offset and view size.
|
26
|
+
*
|
27
|
+
* For example, if current order looks like this (offset = 0, viewSize = 1):
|
28
|
+
* <body> (root node)
|
29
|
+
* └ <tr> (row 0)
|
30
|
+
* and next order should look like this (offset: 0, viewSize = 5):
|
31
|
+
* <body> (root node)
|
32
|
+
* ├ <tr> (row 0)
|
33
|
+
* ├ <tr> (row 1)
|
34
|
+
* ├ <tr> (row 2)
|
35
|
+
* ├ <tr> (row 3)
|
36
|
+
* └ <tr> (row 4)
|
37
|
+
* the generated commands/leads will look like this:
|
38
|
+
* <body> (root node)
|
39
|
+
* ├ <tr> (none, do nothing, leave as it is)
|
40
|
+
* ├ <tr> (append this element at index 1)
|
41
|
+
* ├ <tr> (append this element at index 2)
|
42
|
+
* ├ <tr> (append this element at index 3)
|
43
|
+
* └ <tr> (append this element at index 4)
|
44
|
+
*
|
45
|
+
* @returns {Array[]} Returns an array with generated commands/leads.
|
46
|
+
*/
|
47
|
+
diff() {
|
48
|
+
const {
|
49
|
+
sizeSet
|
50
|
+
} = this;
|
51
|
+
const {
|
52
|
+
currentSize: currentViewSize,
|
53
|
+
nextSize: nextViewSize
|
54
|
+
} = sizeSet.getViewSize();
|
55
|
+
let maxSize = Math.max(nextViewSize, currentViewSize);
|
56
|
+
if (maxSize === 0) {
|
57
|
+
return [];
|
58
|
+
}
|
59
|
+
const {
|
60
|
+
currentOffset,
|
61
|
+
nextOffset
|
62
|
+
} = sizeSet.getViewSize();
|
63
|
+
|
64
|
+
// @TODO(perf-tip): Creating an array (createRange) is not necessary it would be enough to generate
|
65
|
+
// commands based on numeric values.
|
66
|
+
const currentViewOrder = new _viewOrder.ViewOrder(currentOffset, currentViewSize);
|
67
|
+
const nextViewOrder = new _viewOrder.ViewOrder(nextOffset, nextViewSize);
|
68
|
+
const leads = [];
|
69
|
+
for (let i = 0; i < maxSize; i++) {
|
70
|
+
const currentIndex = currentViewOrder.get(i);
|
71
|
+
const nextIndex = nextViewOrder.get(i);
|
72
|
+
|
73
|
+
// Current index exceeds the next DOM index so it is necessary to generate a "remove" command
|
74
|
+
// to achieve new order.
|
75
|
+
if (nextIndex === -1) {
|
76
|
+
leads.push(['remove', currentIndex]);
|
77
|
+
|
78
|
+
// Next index exceeds the current DOM index so it is necessary to generate a "append" command
|
79
|
+
// to achieve new order.
|
80
|
+
} else if (currentIndex === -1) {
|
81
|
+
// Check what command should be generated (depends on if this work as a shared root node
|
82
|
+
// and in what position or not)
|
83
|
+
if (!sizeSet.isShared() || sizeSet.isShared() && sizeSet.isPlaceOn(_constants.WORKING_SPACE_BOTTOM)) {
|
84
|
+
/**
|
85
|
+
* If the differ has only one root node to manage with, the "append" command is generated.
|
86
|
+
*
|
87
|
+
* For example:
|
88
|
+
* ┌─────────── <body> (root node)
|
89
|
+
* │ <tr>
|
90
|
+
* │ <tr>
|
91
|
+
* (managed by one <tr>
|
92
|
+
* differ - TRs) <tr>
|
93
|
+
* │ <tr>
|
94
|
+
* └─────────── <tr> <--- Generates "append" command (which later executes `rootNode.appendChild(node)`)
|
95
|
+
*/
|
96
|
+
leads.push(['append', nextIndex]);
|
97
|
+
} else {
|
98
|
+
/**
|
99
|
+
* If the differ is sharing root node, the "prepend" command is generated.
|
100
|
+
*
|
101
|
+
* For example:
|
102
|
+
* ┌─────────── <tr> (root node, shared between two differs)
|
103
|
+
* (first differ) <th> <--- Generates "prepend" command (which later executes `rootNode.insertBefore(...)`)
|
104
|
+
* ├─────────── <td>
|
105
|
+
* │ <td>
|
106
|
+
* (second differ <td>
|
107
|
+
* - TDs) <td>
|
108
|
+
* │ <td>
|
109
|
+
* └─────────── <td>
|
110
|
+
*/
|
111
|
+
leads.push(['prepend', nextIndex]);
|
112
|
+
}
|
113
|
+
} else if (nextIndex > currentIndex) {
|
114
|
+
// This emulates DOM behavior when we try to append (or replace) an element which is already
|
115
|
+
// mounted. The old index in the array has to be popped out indicating that an element was
|
116
|
+
// moved to a different position.
|
117
|
+
if (currentViewOrder.has(nextIndex)) {
|
118
|
+
currentViewOrder.remove(nextIndex);
|
119
|
+
|
120
|
+
// Decrease loop size to prevent generating "remove" leads. "remove" leads are necessary only for nodes
|
121
|
+
// which are not mounted in current DOM order.
|
122
|
+
if (nextViewSize <= currentViewOrder.length) {
|
123
|
+
maxSize -= 1;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
leads.push(['replace', nextIndex, currentIndex]);
|
127
|
+
} else if (nextIndex < currentIndex) {
|
128
|
+
const indexToRemove = currentViewOrder.prepend(nextIndex);
|
129
|
+
leads.push(['insert_before', nextIndex, currentIndex, indexToRemove]);
|
130
|
+
} else {
|
131
|
+
// for the same current and next indexes do nothing.
|
132
|
+
leads.push(['none', nextIndex]);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return leads;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
exports.ViewDiffer = ViewDiffer;
|
@@ -0,0 +1,135 @@
|
|
1
|
+
import "core-js/modules/es.error.cause.js";
|
2
|
+
import "core-js/modules/es.array.push.js";
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
6
|
+
/* eslint-disable jsdoc/require-description-complete-sentence */
|
7
|
+
import { WORKING_SPACE_BOTTOM } from "../constants.mjs";
|
8
|
+
import { ViewOrder } from "./viewOrder.mjs";
|
9
|
+
/**
|
10
|
+
* A class which is responsible for generating commands/leads which has to be executed
|
11
|
+
* to achieve new DOM nodes order.
|
12
|
+
*
|
13
|
+
* @class {ViewDiffer}
|
14
|
+
*/
|
15
|
+
export class ViewDiffer {
|
16
|
+
constructor(sizeSet) {
|
17
|
+
_defineProperty(this, "sizeSet", void 0);
|
18
|
+
this.sizeSet = sizeSet;
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* A method which generates commands/leads which has to be executed to achieve new DOM
|
23
|
+
* nodes order based on new offset and view size.
|
24
|
+
*
|
25
|
+
* For example, if current order looks like this (offset = 0, viewSize = 1):
|
26
|
+
* <body> (root node)
|
27
|
+
* └ <tr> (row 0)
|
28
|
+
* and next order should look like this (offset: 0, viewSize = 5):
|
29
|
+
* <body> (root node)
|
30
|
+
* ├ <tr> (row 0)
|
31
|
+
* ├ <tr> (row 1)
|
32
|
+
* ├ <tr> (row 2)
|
33
|
+
* ├ <tr> (row 3)
|
34
|
+
* └ <tr> (row 4)
|
35
|
+
* the generated commands/leads will look like this:
|
36
|
+
* <body> (root node)
|
37
|
+
* ├ <tr> (none, do nothing, leave as it is)
|
38
|
+
* ├ <tr> (append this element at index 1)
|
39
|
+
* ├ <tr> (append this element at index 2)
|
40
|
+
* ├ <tr> (append this element at index 3)
|
41
|
+
* └ <tr> (append this element at index 4)
|
42
|
+
*
|
43
|
+
* @returns {Array[]} Returns an array with generated commands/leads.
|
44
|
+
*/
|
45
|
+
diff() {
|
46
|
+
const {
|
47
|
+
sizeSet
|
48
|
+
} = this;
|
49
|
+
const {
|
50
|
+
currentSize: currentViewSize,
|
51
|
+
nextSize: nextViewSize
|
52
|
+
} = sizeSet.getViewSize();
|
53
|
+
let maxSize = Math.max(nextViewSize, currentViewSize);
|
54
|
+
if (maxSize === 0) {
|
55
|
+
return [];
|
56
|
+
}
|
57
|
+
const {
|
58
|
+
currentOffset,
|
59
|
+
nextOffset
|
60
|
+
} = sizeSet.getViewSize();
|
61
|
+
|
62
|
+
// @TODO(perf-tip): Creating an array (createRange) is not necessary it would be enough to generate
|
63
|
+
// commands based on numeric values.
|
64
|
+
const currentViewOrder = new ViewOrder(currentOffset, currentViewSize);
|
65
|
+
const nextViewOrder = new ViewOrder(nextOffset, nextViewSize);
|
66
|
+
const leads = [];
|
67
|
+
for (let i = 0; i < maxSize; i++) {
|
68
|
+
const currentIndex = currentViewOrder.get(i);
|
69
|
+
const nextIndex = nextViewOrder.get(i);
|
70
|
+
|
71
|
+
// Current index exceeds the next DOM index so it is necessary to generate a "remove" command
|
72
|
+
// to achieve new order.
|
73
|
+
if (nextIndex === -1) {
|
74
|
+
leads.push(['remove', currentIndex]);
|
75
|
+
|
76
|
+
// Next index exceeds the current DOM index so it is necessary to generate a "append" command
|
77
|
+
// to achieve new order.
|
78
|
+
} else if (currentIndex === -1) {
|
79
|
+
// Check what command should be generated (depends on if this work as a shared root node
|
80
|
+
// and in what position or not)
|
81
|
+
if (!sizeSet.isShared() || sizeSet.isShared() && sizeSet.isPlaceOn(WORKING_SPACE_BOTTOM)) {
|
82
|
+
/**
|
83
|
+
* If the differ has only one root node to manage with, the "append" command is generated.
|
84
|
+
*
|
85
|
+
* For example:
|
86
|
+
* ┌─────────── <body> (root node)
|
87
|
+
* │ <tr>
|
88
|
+
* │ <tr>
|
89
|
+
* (managed by one <tr>
|
90
|
+
* differ - TRs) <tr>
|
91
|
+
* │ <tr>
|
92
|
+
* └─────────── <tr> <--- Generates "append" command (which later executes `rootNode.appendChild(node)`)
|
93
|
+
*/
|
94
|
+
leads.push(['append', nextIndex]);
|
95
|
+
} else {
|
96
|
+
/**
|
97
|
+
* If the differ is sharing root node, the "prepend" command is generated.
|
98
|
+
*
|
99
|
+
* For example:
|
100
|
+
* ┌─────────── <tr> (root node, shared between two differs)
|
101
|
+
* (first differ) <th> <--- Generates "prepend" command (which later executes `rootNode.insertBefore(...)`)
|
102
|
+
* ├─────────── <td>
|
103
|
+
* │ <td>
|
104
|
+
* (second differ <td>
|
105
|
+
* - TDs) <td>
|
106
|
+
* │ <td>
|
107
|
+
* └─────────── <td>
|
108
|
+
*/
|
109
|
+
leads.push(['prepend', nextIndex]);
|
110
|
+
}
|
111
|
+
} else if (nextIndex > currentIndex) {
|
112
|
+
// This emulates DOM behavior when we try to append (or replace) an element which is already
|
113
|
+
// mounted. The old index in the array has to be popped out indicating that an element was
|
114
|
+
// moved to a different position.
|
115
|
+
if (currentViewOrder.has(nextIndex)) {
|
116
|
+
currentViewOrder.remove(nextIndex);
|
117
|
+
|
118
|
+
// Decrease loop size to prevent generating "remove" leads. "remove" leads are necessary only for nodes
|
119
|
+
// which are not mounted in current DOM order.
|
120
|
+
if (nextViewSize <= currentViewOrder.length) {
|
121
|
+
maxSize -= 1;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
leads.push(['replace', nextIndex, currentIndex]);
|
125
|
+
} else if (nextIndex < currentIndex) {
|
126
|
+
const indexToRemove = currentViewOrder.prepend(nextIndex);
|
127
|
+
leads.push(['insert_before', nextIndex, currentIndex, indexToRemove]);
|
128
|
+
} else {
|
129
|
+
// for the same current and next indexes do nothing.
|
130
|
+
leads.push(['none', nextIndex]);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
return leads;
|
134
|
+
}
|
135
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
exports.__esModule = true;
|
4
|
+
require("core-js/modules/es.error.cause.js");
|
5
|
+
require("core-js/modules/es.array.unshift.js");
|
6
|
+
require("core-js/modules/esnext.iterator.map.js");
|
7
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
8
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
9
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
10
|
+
/**
|
11
|
+
* The view order is a list of indexes that represent the order of the rendered elements.
|
12
|
+
*
|
13
|
+
* @class {ViewOrder}
|
14
|
+
*/
|
15
|
+
class ViewOrder {
|
16
|
+
constructor(viewOffset, viewSize) {
|
17
|
+
_defineProperty(this, "order", []);
|
18
|
+
this.order = [...Array(viewSize).keys()].map(i => viewOffset + i);
|
19
|
+
}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* The length of the view order.
|
23
|
+
*
|
24
|
+
* @returns {number}
|
25
|
+
*/
|
26
|
+
get length() {
|
27
|
+
return this.order.length;
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Checks if the view order contains the offset index.
|
32
|
+
*
|
33
|
+
* @param {number} offsetIndex The offset index.
|
34
|
+
* @returns {boolean}
|
35
|
+
*/
|
36
|
+
has(offsetIndex) {
|
37
|
+
return this.order.indexOf(offsetIndex) > -1;
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Gets the offset index at the given zero-based index. If the index
|
42
|
+
* is out of bounds, -1 is returned.
|
43
|
+
*
|
44
|
+
* @param {number} zeroBasedIndex The zero-based index.
|
45
|
+
* @returns {number}
|
46
|
+
*/
|
47
|
+
get(zeroBasedIndex) {
|
48
|
+
return zeroBasedIndex < this.order.length ? this.order[zeroBasedIndex] : -1;
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Removes the offset index from the view order.
|
53
|
+
*
|
54
|
+
* @param {number} offsetIndex The offset index.
|
55
|
+
*/
|
56
|
+
remove(offsetIndex) {
|
57
|
+
this.order.splice(this.order.indexOf(offsetIndex), 1);
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Prepends the offset index to the view order. To keep the order length constant,
|
62
|
+
* the last offset index is removed.
|
63
|
+
*
|
64
|
+
* @param {number} offsetIndex The offset index.
|
65
|
+
* @returns {number}
|
66
|
+
*/
|
67
|
+
prepend(offsetIndex) {
|
68
|
+
this.order.unshift(offsetIndex);
|
69
|
+
return this.order.pop();
|
70
|
+
}
|
71
|
+
}
|
72
|
+
exports.ViewOrder = ViewOrder;
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import "core-js/modules/es.error.cause.js";
|
2
|
+
import "core-js/modules/es.array.unshift.js";
|
3
|
+
import "core-js/modules/esnext.iterator.map.js";
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
6
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
7
|
+
/**
|
8
|
+
* The view order is a list of indexes that represent the order of the rendered elements.
|
9
|
+
*
|
10
|
+
* @class {ViewOrder}
|
11
|
+
*/
|
12
|
+
export class ViewOrder {
|
13
|
+
constructor(viewOffset, viewSize) {
|
14
|
+
_defineProperty(this, "order", []);
|
15
|
+
this.order = [...Array(viewSize).keys()].map(i => viewOffset + i);
|
16
|
+
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* The length of the view order.
|
20
|
+
*
|
21
|
+
* @returns {number}
|
22
|
+
*/
|
23
|
+
get length() {
|
24
|
+
return this.order.length;
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Checks if the view order contains the offset index.
|
29
|
+
*
|
30
|
+
* @param {number} offsetIndex The offset index.
|
31
|
+
* @returns {boolean}
|
32
|
+
*/
|
33
|
+
has(offsetIndex) {
|
34
|
+
return this.order.indexOf(offsetIndex) > -1;
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Gets the offset index at the given zero-based index. If the index
|
39
|
+
* is out of bounds, -1 is returned.
|
40
|
+
*
|
41
|
+
* @param {number} zeroBasedIndex The zero-based index.
|
42
|
+
* @returns {number}
|
43
|
+
*/
|
44
|
+
get(zeroBasedIndex) {
|
45
|
+
return zeroBasedIndex < this.order.length ? this.order[zeroBasedIndex] : -1;
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Removes the offset index from the view order.
|
50
|
+
*
|
51
|
+
* @param {number} offsetIndex The offset index.
|
52
|
+
*/
|
53
|
+
remove(offsetIndex) {
|
54
|
+
this.order.splice(this.order.indexOf(offsetIndex), 1);
|
55
|
+
}
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Prepends the offset index to the view order. To keep the order length constant,
|
59
|
+
* the last offset index is removed.
|
60
|
+
*
|
61
|
+
* @param {number} offsetIndex The offset index.
|
62
|
+
* @returns {number}
|
63
|
+
*/
|
64
|
+
prepend(offsetIndex) {
|
65
|
+
this.order.unshift(offsetIndex);
|
66
|
+
return this.order.pop();
|
67
|
+
}
|
68
|
+
}
|
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
exports.__esModule = true;
|
4
4
|
require("core-js/modules/es.error.cause.js");
|
5
|
-
var _viewSize =
|
5
|
+
var _viewSize = require("./viewSize");
|
6
6
|
var _constants = require("./constants");
|
7
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
8
7
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
9
8
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
10
9
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
@@ -31,7 +30,7 @@ class ViewSizeSet {
|
|
31
30
|
*
|
32
31
|
* @type {ViewSize}
|
33
32
|
*/
|
34
|
-
_defineProperty(this, "size", new _viewSize.
|
33
|
+
_defineProperty(this, "size", new _viewSize.ViewSize());
|
35
34
|
/**
|
36
35
|
* Defines if this instance shares its size with another instance. If it's in the shared
|
37
36
|
* mode it defines what space it occupies ('top' or 'bottom').
|
@@ -81,7 +80,7 @@ class ViewSizeSet {
|
|
81
80
|
* @returns {boolean}
|
82
81
|
*/
|
83
82
|
isShared() {
|
84
|
-
return this.sharedSize
|
83
|
+
return this.sharedSize !== null;
|
85
84
|
}
|
86
85
|
|
87
86
|
/**
|
@@ -116,4 +115,4 @@ class ViewSizeSet {
|
|
116
115
|
this.sharedSize = viewSize.getViewSize();
|
117
116
|
}
|
118
117
|
}
|
119
|
-
exports.
|
118
|
+
exports.ViewSizeSet = ViewSizeSet;
|