handsontable 0.0.0-next-ff10728-20250410 → 0.0.0-next-d9b3885-20250415
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.
Potentially problematic release.
This version of handsontable might be problematic. Click here for more details.
- package/3rdparty/walkontable/src/cell/range.js +14 -0
- package/3rdparty/walkontable/src/cell/range.mjs +14 -0
- package/3rdparty/walkontable/src/renderer/rowHeaders.js +4 -1
- package/3rdparty/walkontable/src/renderer/rowHeaders.mjs +4 -1
- package/3rdparty/walkontable/src/selection/border/border.js +5 -0
- package/3rdparty/walkontable/src/selection/border/border.mjs +5 -0
- package/3rdparty/walkontable/src/table/mixin/stickyColumnsStart.js +3 -4
- package/3rdparty/walkontable/src/table/mixin/stickyColumnsStart.mjs +3 -4
- package/3rdparty/walkontable/src/table/mixin/stickyRowsBottom.js +8 -10
- package/3rdparty/walkontable/src/table/mixin/stickyRowsBottom.mjs +8 -10
- package/3rdparty/walkontable/src/table/mixin/stickyRowsTop.js +3 -4
- package/3rdparty/walkontable/src/table/mixin/stickyRowsTop.mjs +3 -4
- package/3rdparty/walkontable/src/table.js +5 -2
- package/3rdparty/walkontable/src/table.mjs +5 -2
- package/CHANGELOG.md +39 -0
- package/base.js +2 -2
- package/base.mjs +2 -2
- package/core/focusCatcher/focusDetector.js +1 -1
- package/core/focusCatcher/focusDetector.mjs +2 -2
- package/core/hooks/constants.js +266 -0
- package/core/hooks/constants.mjs +266 -0
- package/core/hooks/index.d.ts +1 -0
- package/core.d.ts +0 -1
- package/core.js +71 -25
- package/core.mjs +72 -26
- package/dataMap/dataMap.js +0 -7
- package/dataMap/dataMap.mjs +0 -7
- package/dataMap/metaManager/metaSchema.js +28 -0
- package/dataMap/metaManager/metaSchema.mjs +28 -0
- package/dist/handsontable.css +3 -3
- package/dist/handsontable.full.css +3 -3
- package/dist/handsontable.full.js +1375 -350
- package/dist/handsontable.full.min.css +3 -3
- package/dist/handsontable.full.min.js +17 -17
- package/dist/handsontable.js +1375 -350
- package/dist/handsontable.min.css +3 -3
- package/dist/handsontable.min.js +18 -18
- package/editorManager.js +1 -7
- package/editorManager.mjs +1 -7
- package/editors/autocompleteEditor/autocompleteEditor.js +14 -4
- package/editors/autocompleteEditor/autocompleteEditor.mjs +14 -4
- package/editors/textEditor/textEditor.js +1 -1
- package/editors/textEditor/textEditor.mjs +2 -2
- package/helpers/browser.js +1 -1
- package/helpers/browser.mjs +1 -1
- package/helpers/dom/element.js +2 -2
- package/helpers/dom/element.mjs +1 -1
- package/helpers/mixed.js +2 -2
- package/helpers/mixed.mjs +2 -2
- package/helpers/object.js +3 -0
- package/helpers/object.mjs +3 -0
- package/package.json +1 -1
- package/plugins/autoColumnSize/autoColumnSize.js +48 -1
- package/plugins/autoColumnSize/autoColumnSize.mjs +48 -1
- package/plugins/autoRowSize/autoRowSize.js +46 -6
- package/plugins/autoRowSize/autoRowSize.mjs +46 -6
- package/plugins/bindRowsWithHeaders/bindRowsWithHeaders.js +13 -0
- package/plugins/bindRowsWithHeaders/bindRowsWithHeaders.mjs +13 -0
- package/plugins/collapsibleColumns/collapsibleColumns.js +31 -0
- package/plugins/collapsibleColumns/collapsibleColumns.mjs +31 -0
- package/plugins/columnSorting/columnSorting.js +0 -4
- package/plugins/columnSorting/columnSorting.mjs +0 -4
- package/plugins/columnSummary/columnSummary.js +33 -0
- package/plugins/columnSummary/columnSummary.mjs +33 -0
- package/plugins/comments/comments.js +54 -0
- package/plugins/comments/comments.mjs +54 -0
- package/plugins/contextMenu/menu/defaultShortcutsList.js +2 -2
- package/plugins/contextMenu/menu/defaultShortcutsList.mjs +2 -2
- package/plugins/contextMenu/menu/menu.js +1 -0
- package/plugins/contextMenu/menu/menu.mjs +1 -0
- package/plugins/contextMenu/menu/positioner.js +10 -2
- package/plugins/contextMenu/menu/positioner.mjs +10 -2
- package/plugins/copyPaste/copyPaste.js +12 -15
- package/plugins/copyPaste/copyPaste.mjs +13 -16
- package/plugins/copyPaste/pasteEvent.js +3 -0
- package/plugins/copyPaste/pasteEvent.mjs +3 -0
- package/plugins/dropdownMenu/dropdownMenu.js +15 -0
- package/plugins/dropdownMenu/dropdownMenu.mjs +15 -0
- package/plugins/exportFile/exportFile.js +58 -0
- package/plugins/exportFile/exportFile.mjs +58 -0
- package/plugins/filters/filters.js +99 -24
- package/plugins/filters/filters.mjs +99 -24
- package/plugins/filters/ui/multipleSelect.js +7 -1
- package/plugins/filters/ui/multipleSelect.mjs +7 -1
- package/plugins/hiddenColumns/hiddenColumns.js +65 -1
- package/plugins/hiddenColumns/hiddenColumns.mjs +65 -1
- package/plugins/hiddenRows/hiddenRows.js +65 -1
- package/plugins/hiddenRows/hiddenRows.mjs +65 -1
- package/plugins/manualColumnResize/manualColumnResize.js +4 -6
- package/plugins/manualColumnResize/manualColumnResize.mjs +4 -6
- package/plugins/manualRowResize/manualRowResize.js +4 -6
- package/plugins/manualRowResize/manualRowResize.mjs +4 -6
- package/plugins/mergeCells/mergeCells.js +26 -29
- package/plugins/mergeCells/mergeCells.mjs +26 -29
- package/plugins/mergeCells/renderer.js +15 -0
- package/plugins/mergeCells/renderer.mjs +15 -0
- package/plugins/mergeCells/utils.js +31 -0
- package/plugins/mergeCells/utils.mjs +27 -0
- package/plugins/nestedHeaders/nestedHeaders.js +25 -0
- package/plugins/nestedHeaders/nestedHeaders.mjs +25 -0
- package/plugins/nestedRows/data/dataManager.js +2 -2
- package/plugins/nestedRows/data/dataManager.mjs +2 -2
- package/plugins/stretchColumns/stretchColumns.js +13 -0
- package/plugins/stretchColumns/stretchColumns.mjs +13 -0
- package/plugins/trimRows/trimRows.js +61 -0
- package/plugins/trimRows/trimRows.mjs +61 -0
- package/plugins/undoRedo/actions/removeColumn.js +19 -14
- package/plugins/undoRedo/actions/removeColumn.mjs +19 -14
- package/plugins/undoRedo/actions/removeRow.js +12 -4
- package/plugins/undoRedo/actions/removeRow.mjs +12 -4
- package/selection/selection.js +3 -1
- package/selection/selection.mjs +3 -1
- package/styles/handsontable.css +14 -15
- 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 +5 -8
- package/tableView.mjs +5 -8
- package/utils/ghostTable.js +3 -0
- package/utils/ghostTable.mjs +3 -0
|
@@ -102,6 +102,37 @@ const actionDictionary = new Map([['collapse', {
|
|
|
102
102
|
* />
|
|
103
103
|
* ```
|
|
104
104
|
* :::
|
|
105
|
+
*
|
|
106
|
+
* ::: only-for angular
|
|
107
|
+
* ```ts
|
|
108
|
+
* // Enable the collapsibleColumns plugin
|
|
109
|
+
* settings = {
|
|
110
|
+
* data: generateDataObj(),
|
|
111
|
+
* colHeaders: true,
|
|
112
|
+
* rowHeaders: true,
|
|
113
|
+
* nestedHeaders: true,
|
|
114
|
+
* // enable plugin
|
|
115
|
+
* collapsibleColumns: true,
|
|
116
|
+
* };
|
|
117
|
+
*
|
|
118
|
+
* // Or enable and configure specific collapsible columns
|
|
119
|
+
* settings = {
|
|
120
|
+
* data: generateDataObj(),
|
|
121
|
+
* colHeaders: true,
|
|
122
|
+
* rowHeaders: true,
|
|
123
|
+
* nestedHeaders: true,
|
|
124
|
+
* // enable and configure which columns can be collapsed
|
|
125
|
+
* collapsibleColumns: [
|
|
126
|
+
* { row: -4, col: 1, collapsible: true },
|
|
127
|
+
* { row: -3, col: 5, collapsible: true },
|
|
128
|
+
* ],
|
|
129
|
+
* };
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* ```html
|
|
133
|
+
* <hot-table [settings]="settings"></hot-table>
|
|
134
|
+
* ```
|
|
135
|
+
* :::
|
|
105
136
|
*/
|
|
106
137
|
var _collapsedColumnsMap = /*#__PURE__*/new WeakMap();
|
|
107
138
|
var _CollapsibleColumns_brand = /*#__PURE__*/new WeakSet();
|
|
@@ -304,10 +304,6 @@ class ColumnSorting extends _base.BasePlugin {
|
|
|
304
304
|
this.hot.runHooks('afterColumnSort', currentSortConfig, sortPossible ? destinationSortConfigs : currentSortConfig, sortPossible);
|
|
305
305
|
if (sortPossible) {
|
|
306
306
|
this.hot.render();
|
|
307
|
-
// TODO: Workaround? This triggers fast redraw. One test won't pass after removal.
|
|
308
|
-
// It should be refactored / described.
|
|
309
|
-
this.hot.forceFullRender = false;
|
|
310
|
-
this.hot.view.render();
|
|
311
307
|
}
|
|
312
308
|
}
|
|
313
309
|
|
|
@@ -301,10 +301,6 @@ export class ColumnSorting extends BasePlugin {
|
|
|
301
301
|
this.hot.runHooks('afterColumnSort', currentSortConfig, sortPossible ? destinationSortConfigs : currentSortConfig, sortPossible);
|
|
302
302
|
if (sortPossible) {
|
|
303
303
|
this.hot.render();
|
|
304
|
-
// TODO: Workaround? This triggers fast redraw. One test won't pass after removal.
|
|
305
|
-
// It should be refactored / described.
|
|
306
|
-
this.hot.forceFullRender = false;
|
|
307
|
-
this.hot.view.render();
|
|
308
304
|
}
|
|
309
305
|
}
|
|
310
306
|
|
|
@@ -104,6 +104,39 @@ const PLUGIN_PRIORITY = exports.PLUGIN_PRIORITY = 220;
|
|
|
104
104
|
* />
|
|
105
105
|
* ```
|
|
106
106
|
* :::
|
|
107
|
+
*
|
|
108
|
+
* ::: only-for angular
|
|
109
|
+
* ```ts
|
|
110
|
+
* settings = {
|
|
111
|
+
* data: getData(),
|
|
112
|
+
* colHeaders: true,
|
|
113
|
+
* rowHeaders: true,
|
|
114
|
+
* columnSummary: [
|
|
115
|
+
* {
|
|
116
|
+
* type: "min",
|
|
117
|
+
* destinationRow: 4,
|
|
118
|
+
* destinationColumn: 1,
|
|
119
|
+
* },
|
|
120
|
+
* {
|
|
121
|
+
* type: "max",
|
|
122
|
+
* destinationRow: 0,
|
|
123
|
+
* destinationColumn: 3,
|
|
124
|
+
* reversedRowCoords: true,
|
|
125
|
+
* },
|
|
126
|
+
* {
|
|
127
|
+
* type: "sum",
|
|
128
|
+
* destinationRow: 4,
|
|
129
|
+
* destinationColumn: 5,
|
|
130
|
+
* forceNumeric: true,
|
|
131
|
+
* },
|
|
132
|
+
* ],
|
|
133
|
+
* };
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* ```html
|
|
137
|
+
* <hot-table [settings]="settings"></hot-table>
|
|
138
|
+
* ```
|
|
139
|
+
* :::
|
|
107
140
|
*/
|
|
108
141
|
var _ColumnSummary_brand = /*#__PURE__*/new WeakSet();
|
|
109
142
|
class ColumnSummary extends _base.BasePlugin {
|
|
@@ -100,6 +100,39 @@ export const PLUGIN_PRIORITY = 220;
|
|
|
100
100
|
* />
|
|
101
101
|
* ```
|
|
102
102
|
* :::
|
|
103
|
+
*
|
|
104
|
+
* ::: only-for angular
|
|
105
|
+
* ```ts
|
|
106
|
+
* settings = {
|
|
107
|
+
* data: getData(),
|
|
108
|
+
* colHeaders: true,
|
|
109
|
+
* rowHeaders: true,
|
|
110
|
+
* columnSummary: [
|
|
111
|
+
* {
|
|
112
|
+
* type: "min",
|
|
113
|
+
* destinationRow: 4,
|
|
114
|
+
* destinationColumn: 1,
|
|
115
|
+
* },
|
|
116
|
+
* {
|
|
117
|
+
* type: "max",
|
|
118
|
+
* destinationRow: 0,
|
|
119
|
+
* destinationColumn: 3,
|
|
120
|
+
* reversedRowCoords: true,
|
|
121
|
+
* },
|
|
122
|
+
* {
|
|
123
|
+
* type: "sum",
|
|
124
|
+
* destinationRow: 4,
|
|
125
|
+
* destinationColumn: 5,
|
|
126
|
+
* forceNumeric: true,
|
|
127
|
+
* },
|
|
128
|
+
* ],
|
|
129
|
+
* };
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* ```html
|
|
133
|
+
* <hot-table [settings]="settings"></hot-table>
|
|
134
|
+
* ```
|
|
135
|
+
* :::
|
|
103
136
|
*/
|
|
104
137
|
var _ColumnSummary_brand = /*#__PURE__*/new WeakSet();
|
|
105
138
|
export class ColumnSummary extends BasePlugin {
|
|
@@ -121,6 +121,59 @@ const SHORTCUTS_CONTEXT_NAME = `plugin:${PLUGIN_KEY}`;
|
|
|
121
121
|
* commentsPlugin.removeComment();
|
|
122
122
|
* ```
|
|
123
123
|
* :::
|
|
124
|
+
*
|
|
125
|
+
* ::: only-for angular
|
|
126
|
+
* ```ts
|
|
127
|
+
* import { AfterViewInit, Component, ViewChild } from "@angular/core";
|
|
128
|
+
* import {
|
|
129
|
+
* GridSettings,
|
|
130
|
+
* HotTableModule,
|
|
131
|
+
* HotTableComponent,
|
|
132
|
+
* } from "@handsontable/angular-wrapper";
|
|
133
|
+
*
|
|
134
|
+
* `@Component`({
|
|
135
|
+
* selector: "app-example",
|
|
136
|
+
* standalone: true,
|
|
137
|
+
* imports: [HotTableModule],
|
|
138
|
+
* template: ` <div class="ht-theme-main">
|
|
139
|
+
* <hot-table [settings]="gridSettings" />
|
|
140
|
+
* </div>`,
|
|
141
|
+
* })
|
|
142
|
+
* export class ExampleComponent implements AfterViewInit {
|
|
143
|
+
* `@ViewChild`(HotTableComponent, { static: false })
|
|
144
|
+
* readonly hotTable!: HotTableComponent;
|
|
145
|
+
*
|
|
146
|
+
* readonly gridSettings = <GridSettings>{
|
|
147
|
+
* data: this.getData(),
|
|
148
|
+
* comments: true,
|
|
149
|
+
* cell: [
|
|
150
|
+
* { row: 1, col: 1, comment: { value: "Foo" } },
|
|
151
|
+
* { row: 2, col: 2, comment: { value: "Bar" } },
|
|
152
|
+
* ],
|
|
153
|
+
* };
|
|
154
|
+
*
|
|
155
|
+
* ngAfterViewInit(): void {
|
|
156
|
+
* // Access to plugin instance:
|
|
157
|
+
* const hot = this.hotTable.hotInstance;
|
|
158
|
+
* const commentsPlugin = hot.getPlugin("comments");
|
|
159
|
+
*
|
|
160
|
+
* // Manage comments programmatically:
|
|
161
|
+
* commentsPlugin.setCommentAtCell(1, 6, "Comment contents");
|
|
162
|
+
* commentsPlugin.showAtCell(1, 6);
|
|
163
|
+
* commentsPlugin.removeCommentAtCell(1, 6);
|
|
164
|
+
*
|
|
165
|
+
* // You can also set range once and use proper methods:
|
|
166
|
+
* commentsPlugin.setRange({ from: { row: 1, col: 6 } });
|
|
167
|
+
* commentsPlugin.setComment("Comment contents");
|
|
168
|
+
* commentsPlugin.show();
|
|
169
|
+
* }
|
|
170
|
+
*
|
|
171
|
+
* private getData(): any[] {
|
|
172
|
+
* // get some data
|
|
173
|
+
* }
|
|
174
|
+
* }
|
|
175
|
+
* ```
|
|
176
|
+
* :::
|
|
124
177
|
*/
|
|
125
178
|
var _editor = /*#__PURE__*/new WeakMap();
|
|
126
179
|
var _displaySwitch = /*#__PURE__*/new WeakMap();
|
|
@@ -234,6 +287,7 @@ class Comments extends _base.BasePlugin {
|
|
|
234
287
|
this.addHook('afterScroll', () => _assertClassBrand(_Comments_brand, this, _onAfterScroll).call(this));
|
|
235
288
|
this.addHook('afterBeginEditing', () => this.hide());
|
|
236
289
|
this.addHook('afterDocumentKeyDown', event => _assertClassBrand(_Comments_brand, this, _onAfterDocumentKeyDown).call(this, event));
|
|
290
|
+
this.addHook('beforeCompositionStart', event => _assertClassBrand(_Comments_brand, this, _onAfterDocumentKeyDown).call(this, event));
|
|
237
291
|
this.addHook('afterSetTheme', function () {
|
|
238
292
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
239
293
|
args[_key2] = arguments[_key2];
|
|
@@ -117,6 +117,59 @@ const SHORTCUTS_CONTEXT_NAME = `plugin:${PLUGIN_KEY}`;
|
|
|
117
117
|
* commentsPlugin.removeComment();
|
|
118
118
|
* ```
|
|
119
119
|
* :::
|
|
120
|
+
*
|
|
121
|
+
* ::: only-for angular
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { AfterViewInit, Component, ViewChild } from "@angular/core";
|
|
124
|
+
* import {
|
|
125
|
+
* GridSettings,
|
|
126
|
+
* HotTableModule,
|
|
127
|
+
* HotTableComponent,
|
|
128
|
+
* } from "@handsontable/angular-wrapper";
|
|
129
|
+
*
|
|
130
|
+
* `@Component`({
|
|
131
|
+
* selector: "app-example",
|
|
132
|
+
* standalone: true,
|
|
133
|
+
* imports: [HotTableModule],
|
|
134
|
+
* template: ` <div class="ht-theme-main">
|
|
135
|
+
* <hot-table [settings]="gridSettings" />
|
|
136
|
+
* </div>`,
|
|
137
|
+
* })
|
|
138
|
+
* export class ExampleComponent implements AfterViewInit {
|
|
139
|
+
* `@ViewChild`(HotTableComponent, { static: false })
|
|
140
|
+
* readonly hotTable!: HotTableComponent;
|
|
141
|
+
*
|
|
142
|
+
* readonly gridSettings = <GridSettings>{
|
|
143
|
+
* data: this.getData(),
|
|
144
|
+
* comments: true,
|
|
145
|
+
* cell: [
|
|
146
|
+
* { row: 1, col: 1, comment: { value: "Foo" } },
|
|
147
|
+
* { row: 2, col: 2, comment: { value: "Bar" } },
|
|
148
|
+
* ],
|
|
149
|
+
* };
|
|
150
|
+
*
|
|
151
|
+
* ngAfterViewInit(): void {
|
|
152
|
+
* // Access to plugin instance:
|
|
153
|
+
* const hot = this.hotTable.hotInstance;
|
|
154
|
+
* const commentsPlugin = hot.getPlugin("comments");
|
|
155
|
+
*
|
|
156
|
+
* // Manage comments programmatically:
|
|
157
|
+
* commentsPlugin.setCommentAtCell(1, 6, "Comment contents");
|
|
158
|
+
* commentsPlugin.showAtCell(1, 6);
|
|
159
|
+
* commentsPlugin.removeCommentAtCell(1, 6);
|
|
160
|
+
*
|
|
161
|
+
* // You can also set range once and use proper methods:
|
|
162
|
+
* commentsPlugin.setRange({ from: { row: 1, col: 6 } });
|
|
163
|
+
* commentsPlugin.setComment("Comment contents");
|
|
164
|
+
* commentsPlugin.show();
|
|
165
|
+
* }
|
|
166
|
+
*
|
|
167
|
+
* private getData(): any[] {
|
|
168
|
+
* // get some data
|
|
169
|
+
* }
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
* :::
|
|
120
173
|
*/
|
|
121
174
|
var _editor = /*#__PURE__*/new WeakMap();
|
|
122
175
|
var _displaySwitch = /*#__PURE__*/new WeakMap();
|
|
@@ -230,6 +283,7 @@ export class Comments extends BasePlugin {
|
|
|
230
283
|
this.addHook('afterScroll', () => _assertClassBrand(_Comments_brand, this, _onAfterScroll).call(this));
|
|
231
284
|
this.addHook('afterBeginEditing', () => this.hide());
|
|
232
285
|
this.addHook('afterDocumentKeyDown', event => _assertClassBrand(_Comments_brand, this, _onAfterDocumentKeyDown).call(this, event));
|
|
286
|
+
this.addHook('beforeCompositionStart', event => _assertClassBrand(_Comments_brand, this, _onAfterDocumentKeyDown).call(this, event));
|
|
233
287
|
this.addHook('afterSetTheme', function () {
|
|
234
288
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
235
289
|
args[_key2] = arguments[_key2];
|
|
@@ -39,7 +39,7 @@ function createDefaultShortcutsList(menu) {
|
|
|
39
39
|
keys: [['ArrowUp']],
|
|
40
40
|
callback: () => menu.getNavigator().toPreviousItem()
|
|
41
41
|
}, {
|
|
42
|
-
keys: [['ArrowRight']],
|
|
42
|
+
keys: [[hot.isRtl() ? 'ArrowLeft' : 'ArrowRight']],
|
|
43
43
|
callback: () => {
|
|
44
44
|
const selection = hotMenu.getSelectedLast();
|
|
45
45
|
if (selection) {
|
|
@@ -50,7 +50,7 @@ function createDefaultShortcutsList(menu) {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}, {
|
|
53
|
-
keys: [['ArrowLeft']],
|
|
53
|
+
keys: [[hot.isRtl() ? 'ArrowRight' : 'ArrowLeft']],
|
|
54
54
|
callback: () => {
|
|
55
55
|
const selection = hotMenu.getSelectedLast();
|
|
56
56
|
if (selection && menu.isSubMenu()) {
|
|
@@ -35,7 +35,7 @@ export function createDefaultShortcutsList(menu) {
|
|
|
35
35
|
keys: [['ArrowUp']],
|
|
36
36
|
callback: () => menu.getNavigator().toPreviousItem()
|
|
37
37
|
}, {
|
|
38
|
-
keys: [['ArrowRight']],
|
|
38
|
+
keys: [[hot.isRtl() ? 'ArrowLeft' : 'ArrowRight']],
|
|
39
39
|
callback: () => {
|
|
40
40
|
const selection = hotMenu.getSelectedLast();
|
|
41
41
|
if (selection) {
|
|
@@ -46,7 +46,7 @@ export function createDefaultShortcutsList(menu) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}, {
|
|
49
|
-
keys: [['ArrowLeft']],
|
|
49
|
+
keys: [[hot.isRtl() ? 'ArrowRight' : 'ArrowLeft']],
|
|
50
50
|
callback: () => {
|
|
51
51
|
const selection = hotMenu.getSelectedLast();
|
|
52
52
|
if (selection && menu.isSubMenu()) {
|
|
@@ -293,6 +293,7 @@ class Menu {
|
|
|
293
293
|
layoutDirection: this.hot.isRtl() ? 'rtl' : 'ltr',
|
|
294
294
|
ariaTags: false,
|
|
295
295
|
themeName: this.hot.getCurrentThemeName(),
|
|
296
|
+
beforeRefreshDimensions: () => false,
|
|
296
297
|
beforeOnCellMouseOver: (event, coords) => {
|
|
297
298
|
_classPrivateFieldGet(_navigator, this).setCurrentPage(coords.row);
|
|
298
299
|
},
|
|
@@ -289,6 +289,7 @@ export class Menu {
|
|
|
289
289
|
layoutDirection: this.hot.isRtl() ? 'rtl' : 'ltr',
|
|
290
290
|
ariaTags: false,
|
|
291
291
|
themeName: this.hot.getCurrentThemeName(),
|
|
292
|
+
beforeRefreshDimensions: () => false,
|
|
292
293
|
beforeOnCellMouseOver: (event, coords) => {
|
|
293
294
|
_classPrivateFieldGet(_navigator, this).setCurrentPage(coords.row);
|
|
294
295
|
},
|
|
@@ -143,7 +143,11 @@ class Positioner {
|
|
|
143
143
|
setPositionAboveCursor() {
|
|
144
144
|
let top = _classPrivateFieldGet(_offset, this).above + _classPrivateFieldGet(_cursor, this).top - _classPrivateFieldGet(_container, this).offsetHeight;
|
|
145
145
|
if (_classPrivateFieldGet(_parentContainer, this)) {
|
|
146
|
-
|
|
146
|
+
const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView;
|
|
147
|
+
const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master'));
|
|
148
|
+
const paddingTop = Number.parseInt(style.paddingTop, 10);
|
|
149
|
+
const borderTop = Number.parseInt(style.borderTop, 10);
|
|
150
|
+
top = _classPrivateFieldGet(_cursor, this).top + _classPrivateFieldGet(_cursor, this).cellHeight - _classPrivateFieldGet(_container, this).scrollHeight + paddingTop + borderTop;
|
|
147
151
|
}
|
|
148
152
|
_classPrivateFieldGet(_container, this).style.top = `${top}px`;
|
|
149
153
|
}
|
|
@@ -154,7 +158,11 @@ class Positioner {
|
|
|
154
158
|
setPositionBelowCursor() {
|
|
155
159
|
let top = _classPrivateFieldGet(_offset, this).below + _classPrivateFieldGet(_cursor, this).top + 1;
|
|
156
160
|
if (_classPrivateFieldGet(_parentContainer, this)) {
|
|
157
|
-
|
|
161
|
+
const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView;
|
|
162
|
+
const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master'));
|
|
163
|
+
const paddingTop = Number.parseInt(style.paddingTop, 10);
|
|
164
|
+
const borderTop = Number.parseInt(style.borderTop, 10);
|
|
165
|
+
top = _classPrivateFieldGet(_cursor, this).top - paddingTop - borderTop - 1;
|
|
158
166
|
}
|
|
159
167
|
_classPrivateFieldGet(_container, this).style.top = `${top}px`;
|
|
160
168
|
}
|
|
@@ -140,7 +140,11 @@ export class Positioner {
|
|
|
140
140
|
setPositionAboveCursor() {
|
|
141
141
|
let top = _classPrivateFieldGet(_offset, this).above + _classPrivateFieldGet(_cursor, this).top - _classPrivateFieldGet(_container, this).offsetHeight;
|
|
142
142
|
if (_classPrivateFieldGet(_parentContainer, this)) {
|
|
143
|
-
|
|
143
|
+
const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView;
|
|
144
|
+
const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master'));
|
|
145
|
+
const paddingTop = Number.parseInt(style.paddingTop, 10);
|
|
146
|
+
const borderTop = Number.parseInt(style.borderTop, 10);
|
|
147
|
+
top = _classPrivateFieldGet(_cursor, this).top + _classPrivateFieldGet(_cursor, this).cellHeight - _classPrivateFieldGet(_container, this).scrollHeight + paddingTop + borderTop;
|
|
144
148
|
}
|
|
145
149
|
_classPrivateFieldGet(_container, this).style.top = `${top}px`;
|
|
146
150
|
}
|
|
@@ -151,7 +155,11 @@ export class Positioner {
|
|
|
151
155
|
setPositionBelowCursor() {
|
|
152
156
|
let top = _classPrivateFieldGet(_offset, this).below + _classPrivateFieldGet(_cursor, this).top + 1;
|
|
153
157
|
if (_classPrivateFieldGet(_parentContainer, this)) {
|
|
154
|
-
|
|
158
|
+
const rootWindow = _classPrivateFieldGet(_parentContainer, this).ownerDocument.defaultView;
|
|
159
|
+
const style = rootWindow.getComputedStyle(_classPrivateFieldGet(_parentContainer, this).querySelector('.ht_master'));
|
|
160
|
+
const paddingTop = Number.parseInt(style.paddingTop, 10);
|
|
161
|
+
const borderTop = Number.parseInt(style.borderTop, 10);
|
|
162
|
+
top = _classPrivateFieldGet(_cursor, this).top - paddingTop - borderTop - 1;
|
|
155
163
|
}
|
|
156
164
|
_classPrivateFieldGet(_container, this).style.top = `${top}px`;
|
|
157
165
|
}
|
|
@@ -256,6 +256,9 @@ class CopyPaste extends _base.BasePlugin {
|
|
|
256
256
|
return _assertClassBrand(_CopyPaste_brand, _this, _onAfterSelection).call(_this, ...args);
|
|
257
257
|
});
|
|
258
258
|
this.addHook('afterSelectionEnd', () => _assertClassBrand(_CopyPaste_brand, this, _onAfterSelectionEnd).call(this));
|
|
259
|
+
|
|
260
|
+
// Events are attached to the document, not the root table element - as it should,
|
|
261
|
+
// for Chrome 133 and lower to copy/paste/cut work properly (#dev-2277).
|
|
259
262
|
this.eventManager.addEventListener(this.hot.rootDocument, 'copy', function () {
|
|
260
263
|
return _this.onCopy(...arguments);
|
|
261
264
|
});
|
|
@@ -562,12 +565,10 @@ class CopyPaste extends _base.BasePlugin {
|
|
|
562
565
|
* @private
|
|
563
566
|
*/
|
|
564
567
|
onCopy(event) {
|
|
565
|
-
|
|
568
|
+
const eventTarget = event.composedPath()[0];
|
|
566
569
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
567
|
-
const isHotInput =
|
|
568
|
-
|
|
569
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
570
|
-
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
570
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
571
|
+
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !(0, _element.isInternalElement)(eventTarget, this.hot.rootElement))) {
|
|
571
572
|
return;
|
|
572
573
|
}
|
|
573
574
|
event.preventDefault();
|
|
@@ -597,12 +598,10 @@ class CopyPaste extends _base.BasePlugin {
|
|
|
597
598
|
* @private
|
|
598
599
|
*/
|
|
599
600
|
onCut(event) {
|
|
600
|
-
|
|
601
|
+
const eventTarget = event.composedPath()[0];
|
|
601
602
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
602
|
-
const isHotInput =
|
|
603
|
-
|
|
604
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
605
|
-
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
603
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
604
|
+
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || (0, _element.isHTMLElement)(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !(0, _element.isInternalElement)(eventTarget, this.hot.rootElement))) {
|
|
606
605
|
return;
|
|
607
606
|
}
|
|
608
607
|
event.preventDefault();
|
|
@@ -631,12 +630,10 @@ class CopyPaste extends _base.BasePlugin {
|
|
|
631
630
|
* @private
|
|
632
631
|
*/
|
|
633
632
|
onPaste(event) {
|
|
634
|
-
|
|
633
|
+
const eventTarget = event.composedPath()[0];
|
|
635
634
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
636
|
-
const isHotInput =
|
|
637
|
-
|
|
638
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
639
|
-
if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || (0, _element.isHTMLElement)(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
635
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
636
|
+
if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || (0, _element.isHTMLElement)(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !(0, _element.isInternalElement)(eventTarget, this.hot.rootElement))) {
|
|
640
637
|
return;
|
|
641
638
|
}
|
|
642
639
|
event.preventDefault();
|
|
@@ -17,7 +17,7 @@ import { Hooks } from "../../core/hooks/index.mjs";
|
|
|
17
17
|
import { stringify, parse } from "../../3rdparty/SheetClip/index.mjs";
|
|
18
18
|
import { arrayEach } from "../../helpers/array.mjs";
|
|
19
19
|
import { sanitize } from "../../helpers/string.mjs";
|
|
20
|
-
import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent, isHTMLElement } from "../../helpers/dom/element.mjs";
|
|
20
|
+
import { removeContentEditableFromElementAndDeselect, runWithSelectedContendEditableElement, makeElementContentEditableAndSelectItsContent, isHTMLElement, isInternalElement } from "../../helpers/dom/element.mjs";
|
|
21
21
|
import { isSafari } from "../../helpers/browser.mjs";
|
|
22
22
|
import copyItem from "./contextMenuItem/copy.mjs";
|
|
23
23
|
import copyColumnHeadersOnlyItem from "./contextMenuItem/copyColumnHeadersOnly.mjs";
|
|
@@ -252,6 +252,9 @@ export class CopyPaste extends BasePlugin {
|
|
|
252
252
|
return _assertClassBrand(_CopyPaste_brand, _this, _onAfterSelection).call(_this, ...args);
|
|
253
253
|
});
|
|
254
254
|
this.addHook('afterSelectionEnd', () => _assertClassBrand(_CopyPaste_brand, this, _onAfterSelectionEnd).call(this));
|
|
255
|
+
|
|
256
|
+
// Events are attached to the document, not the root table element - as it should,
|
|
257
|
+
// for Chrome 133 and lower to copy/paste/cut work properly (#dev-2277).
|
|
255
258
|
this.eventManager.addEventListener(this.hot.rootDocument, 'copy', function () {
|
|
256
259
|
return _this.onCopy(...arguments);
|
|
257
260
|
});
|
|
@@ -558,12 +561,10 @@ export class CopyPaste extends BasePlugin {
|
|
|
558
561
|
* @private
|
|
559
562
|
*/
|
|
560
563
|
onCopy(event) {
|
|
561
|
-
|
|
564
|
+
const eventTarget = event.composedPath()[0];
|
|
562
565
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
563
|
-
const isHotInput =
|
|
564
|
-
|
|
565
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
566
|
-
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
566
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
567
|
+
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCopy, this) || this.isEditorOpened() || isHTMLElement(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !isInternalElement(eventTarget, this.hot.rootElement))) {
|
|
567
568
|
return;
|
|
568
569
|
}
|
|
569
570
|
event.preventDefault();
|
|
@@ -593,12 +594,10 @@ export class CopyPaste extends BasePlugin {
|
|
|
593
594
|
* @private
|
|
594
595
|
*/
|
|
595
596
|
onCut(event) {
|
|
596
|
-
|
|
597
|
+
const eventTarget = event.composedPath()[0];
|
|
597
598
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
598
|
-
const isHotInput =
|
|
599
|
-
|
|
600
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
601
|
-
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
599
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
600
|
+
if (!this.hot.isListening() && !_classPrivateFieldGet(_isTriggeredByCut, this) || this.isEditorOpened() || isHTMLElement(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !isInternalElement(eventTarget, this.hot.rootElement))) {
|
|
602
601
|
return;
|
|
603
602
|
}
|
|
604
603
|
event.preventDefault();
|
|
@@ -627,12 +626,10 @@ export class CopyPaste extends BasePlugin {
|
|
|
627
626
|
* @private
|
|
628
627
|
*/
|
|
629
628
|
onPaste(event) {
|
|
630
|
-
|
|
629
|
+
const eventTarget = event.composedPath()[0];
|
|
631
630
|
const focusedElement = this.hot.getFocusManager().getRefocusElement();
|
|
632
|
-
const isHotInput =
|
|
633
|
-
|
|
634
|
-
const TD = selectedCell ? this.hot.getCell(selectedCell.row, selectedCell.col, true) : null;
|
|
635
|
-
if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || isHTMLElement(event.target) && (isHotInput && event.target !== focusedElement || !isHotInput && event.target !== this.hot.rootDocument.body && TD !== event.target)) {
|
|
631
|
+
const isHotInput = eventTarget === null || eventTarget === void 0 ? void 0 : eventTarget.hasAttribute('data-hot-input');
|
|
632
|
+
if (!this.hot.isListening() || this.isEditorOpened() || !this.hot.getSelected() || isHTMLElement(eventTarget) && (isHotInput && eventTarget !== focusedElement || !isHotInput && eventTarget !== this.hot.rootDocument.body && !isInternalElement(eventTarget, this.hot.rootElement))) {
|
|
636
633
|
return;
|
|
637
634
|
}
|
|
638
635
|
event.preventDefault();
|
|
@@ -80,6 +80,21 @@ const SHORTCUTS_GROUP = PLUGIN_KEY;
|
|
|
80
80
|
* />
|
|
81
81
|
* ```
|
|
82
82
|
* :::
|
|
83
|
+
*
|
|
84
|
+
* ::: only-for angular
|
|
85
|
+
* ```ts
|
|
86
|
+
* settings = {
|
|
87
|
+
* data: data,
|
|
88
|
+
* comments: true,
|
|
89
|
+
* // enable and configure dropdown menu
|
|
90
|
+
* dropdownMenu: ["remove_col", "---------", "make_read_only", "alignment"],
|
|
91
|
+
* };
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* ```html
|
|
95
|
+
* <hot-table [settings]="settings"></hot-table>
|
|
96
|
+
* ```
|
|
97
|
+
* :::
|
|
83
98
|
*/
|
|
84
99
|
var _isButtonClicked = /*#__PURE__*/new WeakMap();
|
|
85
100
|
var _DropdownMenu_brand = /*#__PURE__*/new WeakSet();
|
|
@@ -77,6 +77,21 @@ const SHORTCUTS_GROUP = PLUGIN_KEY;
|
|
|
77
77
|
* />
|
|
78
78
|
* ```
|
|
79
79
|
* :::
|
|
80
|
+
*
|
|
81
|
+
* ::: only-for angular
|
|
82
|
+
* ```ts
|
|
83
|
+
* settings = {
|
|
84
|
+
* data: data,
|
|
85
|
+
* comments: true,
|
|
86
|
+
* // enable and configure dropdown menu
|
|
87
|
+
* dropdownMenu: ["remove_col", "---------", "make_read_only", "alignment"],
|
|
88
|
+
* };
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* ```html
|
|
92
|
+
* <hot-table [settings]="settings"></hot-table>
|
|
93
|
+
* ```
|
|
94
|
+
* :::
|
|
80
95
|
*/
|
|
81
96
|
var _isButtonClicked = /*#__PURE__*/new WeakMap();
|
|
82
97
|
var _DropdownMenu_brand = /*#__PURE__*/new WeakSet();
|
|
@@ -87,6 +87,64 @@ const PLUGIN_PRIORITY = exports.PLUGIN_PRIORITY = 240;
|
|
|
87
87
|
* });
|
|
88
88
|
* ```
|
|
89
89
|
* :::
|
|
90
|
+
*
|
|
91
|
+
* ::: only-for angular
|
|
92
|
+
* ```ts
|
|
93
|
+
* import { AfterViewInit, Component, ViewChild } from "@angular/core";
|
|
94
|
+
* import {
|
|
95
|
+
* GridSettings,
|
|
96
|
+
* HotTableModule,
|
|
97
|
+
* HotTableComponent,
|
|
98
|
+
* } from "@handsontable/angular-wrapper";
|
|
99
|
+
*
|
|
100
|
+
* `@Component`({
|
|
101
|
+
* selector: "app-example",
|
|
102
|
+
* standalone: true,
|
|
103
|
+
* imports: [HotTableModule],
|
|
104
|
+
* template: ` <div class="ht-theme-main">
|
|
105
|
+
* <hot-table [settings]="gridSettings" />
|
|
106
|
+
* </div>`,
|
|
107
|
+
* })
|
|
108
|
+
* export class ExampleComponent implements AfterViewInit {
|
|
109
|
+
* `@ViewChild`(HotTableComponent, { static: false })
|
|
110
|
+
* readonly hotTable!: HotTableComponent;
|
|
111
|
+
*
|
|
112
|
+
* readonly gridSettings = <GridSettings>{
|
|
113
|
+
* data: this.getData(),
|
|
114
|
+
* };
|
|
115
|
+
*
|
|
116
|
+
* ngAfterViewInit(): void {
|
|
117
|
+
* // Access to plugin instance:
|
|
118
|
+
* const hot = this.hotTable.hotInstance;
|
|
119
|
+
* // Access to exportFile plugin instance
|
|
120
|
+
* const exportPlugin = hot.getPlugin("exportFile");
|
|
121
|
+
*
|
|
122
|
+
* // Export as a string
|
|
123
|
+
* exportPlugin.exportAsString("csv");
|
|
124
|
+
*
|
|
125
|
+
* // Export as a blob object
|
|
126
|
+
* exportPlugin.exportAsBlob("csv");
|
|
127
|
+
*
|
|
128
|
+
* // Export to downloadable file (named: MyFile.csv)
|
|
129
|
+
* exportPlugin.downloadFile("csv", { filename: "MyFile" });
|
|
130
|
+
*
|
|
131
|
+
* // Export as a string (with specified data range):
|
|
132
|
+
* exportPlugin.exportAsString("csv", {
|
|
133
|
+
* exportHiddenRows: true, // default false
|
|
134
|
+
* exportHiddenColumns: true, // default false
|
|
135
|
+
* columnHeaders: true, // default false
|
|
136
|
+
* rowHeaders: true, // default false
|
|
137
|
+
* columnDelimiter: ";", // default ','
|
|
138
|
+
* range: [1, 1, 6, 6], // [startRow, endRow, startColumn, endColumn]
|
|
139
|
+
* });
|
|
140
|
+
* }
|
|
141
|
+
*
|
|
142
|
+
* private getData(): any[] {
|
|
143
|
+
* // get some data
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
* ```
|
|
147
|
+
* :::
|
|
90
148
|
*/
|
|
91
149
|
class ExportFile extends _base.BasePlugin {
|
|
92
150
|
static get PLUGIN_KEY() {
|