@revolist/revogrid 3.6.14 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/custom-element/filter.button.js +2 -2
  2. package/custom-element/revo-grid.js +6 -1
  3. package/custom-element/revogr-clipboard.js +6 -2
  4. package/custom-element/revogr-edit2.js +13 -8
  5. package/custom-element/revogr-filter-panel.js +10 -3
  6. package/custom-element/revogr-header2.js +5 -4
  7. package/custom-element/revogr-overlay-selection2.js +2 -2
  8. package/custom-element/revogr-row-headers2.js +5 -2
  9. package/dist/cjs/{debounce-6cea2774.js → debounce-f5e62c5a.js} +2 -2
  10. package/dist/cjs/revo-grid_11.cjs.entry.js +30 -16
  11. package/dist/cjs/revogr-clipboard.cjs.entry.js +6 -2
  12. package/dist/cjs/revogr-filter-panel.cjs.entry.js +11 -4
  13. package/dist/collection/components/clipboard/revogr-clipboard.js +6 -2
  14. package/dist/collection/components/header/headerRenderer.js +3 -3
  15. package/dist/collection/components/overlay/editors/text.js +4 -4
  16. package/dist/collection/components/overlay/keyboard.service.js +2 -2
  17. package/dist/collection/components/rowHeaders/revogr-row-headers.js +5 -2
  18. package/dist/collection/plugins/filter/filter.button.js +2 -2
  19. package/dist/collection/plugins/filter/filter.plugin.js +6 -1
  20. package/dist/collection/plugins/filter/filter.pop.js +11 -4
  21. package/dist/collection/plugins/sorting/sorting.sign.js +2 -1
  22. package/dist/collection/utils/keyCodes.js +6 -0
  23. package/dist/collection/utils/keyCodes.utils.js +8 -1
  24. package/dist/esm/{debounce-e4e6dd45.js → debounce-0e5b22a1.js} +2 -2
  25. package/dist/esm/revo-grid_11.entry.js +30 -16
  26. package/dist/esm/revogr-clipboard.entry.js +6 -2
  27. package/dist/esm/revogr-filter-panel.entry.js +11 -4
  28. package/dist/esm-es5/{debounce-e4e6dd45.js → debounce-0e5b22a1.js} +1 -1
  29. package/dist/esm-es5/revo-grid_11.entry.js +1 -1
  30. package/dist/esm-es5/revogr-clipboard.entry.js +1 -1
  31. package/dist/esm-es5/revogr-filter-panel.entry.js +2 -2
  32. package/dist/revo-grid/debounce-0f0160a3.js +4 -0
  33. package/dist/revo-grid/{debounce-5a33c710.system.js → debounce-8d28735f.system.js} +1 -1
  34. package/dist/revo-grid/revo-grid_11.entry.js +1 -1
  35. package/dist/revo-grid/revo-grid_11.system.entry.js +1 -1
  36. package/dist/revo-grid/revogr-clipboard.entry.js +1 -1
  37. package/dist/revo-grid/revogr-clipboard.system.entry.js +2 -2
  38. package/dist/revo-grid/revogr-filter-panel.entry.js +1 -1
  39. package/dist/revo-grid/revogr-filter-panel.system.entry.js +1 -1
  40. package/dist/types/components/clipboard/revogr-clipboard.d.ts +1 -0
  41. package/dist/types/plugins/filter/filter.button.d.ts +1 -1
  42. package/dist/types/plugins/filter/filter.plugin.d.ts +4 -0
  43. package/dist/types/utils/keyCodes.d.ts +5 -0
  44. package/dist/types/utils/keyCodes.utils.d.ts +2 -0
  45. package/package.json +3 -3
  46. package/readme.md +9 -0
  47. package/dist/revo-grid/debounce-726bdadb.js +0 -4
@@ -23,8 +23,8 @@ const TrashButton = () => {
23
23
  h("svg", { class: "trash-img", viewBox: "0 0 24 24" },
24
24
  h("path", { fill: "currentColor", d: "M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" }))));
25
25
  };
26
- const AndOrButton = ({ isAnd }) => {
27
- return h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, isAnd ? 'and' : 'or');
26
+ const AndOrButton = ({ text }) => {
27
+ return h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, text);
28
28
  };
29
29
  function isFilterBtn(e) {
30
30
  if (e.classList.contains(FILTER_BUTTON_CLASS)) {
@@ -1123,7 +1123,12 @@ class FilterPlugin extends BasePlugin {
1123
1123
  const buttonPos = el.getBoundingClientRect();
1124
1124
  const prop = e.detail.prop;
1125
1125
  this.pop.filterTypes = this.getColumnFilter(e.detail.filter);
1126
- this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: buttonPos.x - gridPos.x, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
1126
+ this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: -9999, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
1127
+ // fix filter dialog is out of view
1128
+ setTimeout(async () => {
1129
+ const { width } = this.pop.getBoundingClientRect();
1130
+ this.pop.style.left = Math.min(buttonPos.x - gridPos.x, gridPos.width - width - 20) + 'px';
1131
+ });
1127
1132
  }
1128
1133
  getColumnFilter(type) {
1129
1134
  let filterType = 'string';
@@ -13,8 +13,9 @@ const Clipboard = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
13
13
  onPaste(e) {
14
14
  const clipboardData = this.getData(e);
15
15
  const isHTML = clipboardData.types.indexOf('text/html') > -1;
16
- const data = isHTML ? clipboardData.getData('text/html') : clipboardData.getData('text');
17
- const parsedData = isHTML ? this.htmlParse(data) : this.textParse(data);
16
+ const canBeParsedAsHtml = isHTML ? this.canBeParsedAsHTML(clipboardData.getData('text/html')) : false;
17
+ const data = canBeParsedAsHtml ? clipboardData.getData('text/html') : clipboardData.getData('text');
18
+ const parsedData = canBeParsedAsHtml ? this.htmlParse(data) : this.textParse(data);
18
19
  this.pasteRegion.emit(parsedData);
19
20
  e.preventDefault();
20
21
  }
@@ -44,6 +45,9 @@ const Clipboard = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
44
45
  }
45
46
  return result;
46
47
  }
48
+ canBeParsedAsHTML(data) {
49
+ return document.createRange().createContextualFragment(data).querySelector('table') !== null;
50
+ }
47
51
  getData(e) {
48
52
  var _a;
49
53
  return e.clipboardData || ((_a = window) === null || _a === void 0 ? void 0 : _a.clipboardData);
@@ -103,6 +103,11 @@ var codesLetter;
103
103
  codesLetter["ARROW_DOWN"] = "ArrowDown";
104
104
  codesLetter["SHIFT"] = "Shift";
105
105
  })(codesLetter || (codesLetter = {}));
106
+ var keyValues;
107
+ (function (keyValues) {
108
+ keyValues["ENTER"] = "Enter";
109
+ keyValues["TAB"] = "Tab";
110
+ })(keyValues || (keyValues = {}));
106
111
  const KeyCodesEnum = codes;
107
112
 
108
113
  var osPlatform;
@@ -282,11 +287,11 @@ function isCtrlKey(code, platform) {
282
287
  function isClear(code) {
283
288
  return codesLetter.BACKSPACE === code || codesLetter.DELETE === code;
284
289
  }
285
- function isTab(code) {
286
- return codesLetter.TAB === code;
290
+ function isTabKeyValue(key) {
291
+ return keyValues.TAB === key;
287
292
  }
288
- function isEnterKey(code) {
289
- return code === codesLetter.ENTER || code === codesLetter.ENTER_NUM;
293
+ function isEnterKeyValue(key) {
294
+ return keyValues.ENTER === key;
290
295
  }
291
296
 
292
297
  class TextEditor {
@@ -304,8 +309,8 @@ class TextEditor {
304
309
  }
305
310
  }
306
311
  onKeyDown(e) {
307
- const isEnter = isEnterKey(e.code);
308
- const isKeyTab = isTab(e.code);
312
+ const isEnter = isEnterKeyValue(e.key);
313
+ const isKeyTab = isTabKeyValue(e.key);
309
314
  if ((isKeyTab || isEnter) && e.target && this.saveCallback && !e.isComposing) {
310
315
  // blur is needed to avoid autoscroll
311
316
  this.editInput.blur();
@@ -316,7 +321,7 @@ class TextEditor {
316
321
  // required
317
322
  render() {
318
323
  var _a;
319
- return (h("input", { type: "text", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
324
+ return (h("input", { type: "text", enterkeyhint: "enter", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
320
325
  this.editInput = el;
321
326
  }, onKeyDown: e => this.onKeyDown(e) }));
322
327
  }
@@ -403,4 +408,4 @@ function defineCustomElement() {
403
408
  }
404
409
  defineCustomElement();
405
410
 
406
- export { Edit as E, isCtrlKey as a, isClear as b, codesLetter as c, defineCustomElement as d, isEnterKey as e, isLetterKey as f, isString_1 as i };
411
+ export { Edit as E, isCtrlKey as a, isClear as b, codesLetter as c, defineCustomElement as d, isEnterKeyValue as e, isLetterKey as f, isString_1 as i };
@@ -43,6 +43,10 @@ const FilterPanel = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
43
43
  save: 'Save',
44
44
  reset: 'Reset',
45
45
  cancel: 'Close',
46
+ add: 'Add more condition...',
47
+ placeholder: 'Enter value...',
48
+ and: 'and',
49
+ or: 'or',
46
50
  };
47
51
  this.isFilterIdSet = false;
48
52
  this.filterId = 0;
@@ -89,7 +93,8 @@ const FilterPanel = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
89
93
  const options = [];
90
94
  const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
91
95
  if (!isDefaultTypeRemoved) {
92
- options.push(h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? 'Add more condition...' : this.filterNames[defaultType]));
96
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
97
+ options.push(h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? capts.add : this.filterNames[defaultType]));
93
98
  }
94
99
  for (let gIndex in this.filterTypes) {
95
100
  options.push(...this.filterTypes[gIndex].map(k => (h("option", { value: k, selected: type === k }, this.filterNames[k]))));
@@ -103,7 +108,8 @@ const FilterPanel = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
103
108
  return '';
104
109
  if (this.filterEntities[currentFilter[index].type].extra !== 'input')
105
110
  return '';
106
- return (h("input", { id: `filter-input-${currentFilter[index].id}`, placeholder: "Enter value...", type: "text", value: currentFilter[index].value, onInput: this.onUserInput.bind(this, index, prop), onKeyDown: e => this.onKeyDown(e) }));
111
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
112
+ return (h("input", { id: `filter-input-${currentFilter[index].id}`, placeholder: capts.placeholder, type: "text", value: currentFilter[index].value, onInput: this.onUserInput.bind(this, index, prop), onKeyDown: e => this.onKeyDown(e) }));
107
113
  }
108
114
  getFilterItemsList() {
109
115
  var _a;
@@ -111,11 +117,12 @@ const FilterPanel = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
111
117
  if (!(prop || prop === 0))
112
118
  return '';
113
119
  const propFilters = this.filterItems[prop] || [];
120
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
114
121
  return (h("div", { key: this.filterId }, propFilters.map((d, index) => {
115
122
  let andOrButton;
116
123
  // hide toggle button if there is only one filter and the last one
117
124
  if (index !== this.filterItems[prop].length - 1) {
118
- andOrButton = (h("div", { onClick: () => this.toggleFilterAndOr(d.id) }, h(AndOrButton, { isAnd: d.relation === 'and' })));
125
+ andOrButton = (h("div", { onClick: () => this.toggleFilterAndOr(d.id) }, h(AndOrButton, { text: d.relation === 'and' ? capts.and : capts.or })));
119
126
  }
120
127
  return (h("div", { key: d.id, class: FILTER_LIST_CLASS }, h("div", { class: { 'select-input': true } }, h("select", { class: "select-css select-filter", onChange: e => this.onFilterTypeChange(e, prop, index) }, this.renderSelectOptions(this.filterItems[prop][index].type, true)), h("div", { class: FILTER_LIST_CLASS_ACTION }, andOrButton), h("div", { onClick: () => this.onRemoveFilter(d.id) }, h(TrashButton, null))), h("div", null, this.renderExtra(prop, index))));
121
128
  }), propFilters.length > 0 ? h("div", { class: "add-filter-divider" }) : ''));
@@ -155,7 +155,8 @@ var keyBy = _createAggregator(function(result, value, key) {
155
155
  var keyBy_1 = keyBy;
156
156
 
157
157
  const SortingSign = ({ column }) => {
158
- return h("i", { class: column.order });
158
+ var _a;
159
+ return h("i", { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' });
159
160
  };
160
161
 
161
162
  var ResizeEvents;
@@ -434,7 +435,7 @@ const HeaderCellRenderer = ({ data, props }, children) => {
434
435
  };
435
436
 
436
437
  const HeaderRenderer = (p) => {
437
- var _a, _b, _c, _d, _e, _f;
438
+ var _a, _b, _c, _d, _e;
438
439
  const cellClass = {
439
440
  [HEADER_CLASS]: true,
440
441
  [HEADER_SORTABLE_CLASS]: !!((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable),
@@ -469,8 +470,8 @@ const HeaderRenderer = (p) => {
469
470
  }
470
471
  }
471
472
  return (h(HeaderCellRenderer, { data: p.data, props: dataProps },
472
- ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) ? h(SortingSign, { column: p.data }) : '',
473
- p.canFilter && ((_f = p.data) === null || _f === void 0 ? void 0 : _f.filter) !== false ? h(FilterButton, { column: p.data }) : ''));
473
+ h(SortingSign, { column: p.data }),
474
+ p.canFilter && ((_e = p.data) === null || _e === void 0 ? void 0 : _e.filter) !== false ? h(FilterButton, { column: p.data }) : ''));
474
475
  };
475
476
 
476
477
  const GroupHeaderRenderer = (p) => {
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { h, proxyCustomElement, HTMLElement, createEvent, Host } from '@stencil/core/internal/client';
5
5
  import { n as getRange, C as ColumnService, o as isRangeSingleCell } from './columnService.js';
6
- import { a as isCtrlKey, c as codesLetter, b as isClear, e as isEnterKey, f as isLetterKey, d as defineCustomElement$2 } from './revogr-edit2.js';
6
+ import { a as isCtrlKey, c as codesLetter, b as isClear, e as isEnterKeyValue, f as isLetterKey, d as defineCustomElement$2 } from './revogr-edit2.js';
7
7
  import { E as EDIT_INPUT_WR, C as CELL_HANDLER_CLASS, S as SELECTION_BORDER_CLASS } from './consts.js';
8
8
  import { a as getCoordinate, i as isAfterLast, b as isBeforeFirst, c as getCell, d as getCurrentCell, g as getElStyle } from './selection.utils.js';
9
9
  import { t as timeout } from './utils.js';
@@ -89,7 +89,7 @@ class KeyboardService {
89
89
  return;
90
90
  }
91
91
  // pressed enter
92
- if (isEnterKey(e.code)) {
92
+ if (isEnterKeyValue(e.key)) {
93
93
  this.sv.doEdit();
94
94
  return;
95
95
  }
@@ -401,10 +401,13 @@ const RevogrRowHeaders = /*@__PURE__*/ proxyCustomElement(class extends HTMLElem
401
401
  /** render viewports rows */
402
402
  let totalLength = 1;
403
403
  for (let data of this.dataPorts) {
404
- const itemCount = data.dataStore.get('items').length;
404
+ const items = data.dataStore.get('items');
405
+ const itemCount = items.length;
406
+ const source = data.dataStore.get('source');
407
+ const visibleSourceItems = items.map(v => source[v]); // from src/store/dataSource/data.store.ts
405
408
  // initiate row data
406
409
  const dataStore = new DataStore(data.type);
407
- dataStore.updateData(data.dataStore.get('source'));
410
+ dataStore.updateData(visibleSourceItems);
408
411
  // initiate column data
409
412
  const colData = new DataStore('colPinStart');
410
413
  const column = Object.assign({ cellTemplate: RowHeaderRender(totalLength) }, this.rowHeaderColumn);
@@ -340,8 +340,8 @@ const TrashButton = () => {
340
340
  index.h("svg", { class: "trash-img", viewBox: "0 0 24 24" },
341
341
  index.h("path", { fill: "currentColor", d: "M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" }))));
342
342
  };
343
- const AndOrButton = ({ isAnd }) => {
344
- return index.h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, isAnd ? 'and' : 'or');
343
+ const AndOrButton = ({ text }) => {
344
+ return index.h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, text);
345
345
  };
346
346
  function isFilterBtn(e) {
347
347
  if (e.classList.contains(FILTER_BUTTON_CLASS)) {
@@ -6,7 +6,7 @@
6
6
  Object.defineProperty(exports, '__esModule', { value: true });
7
7
 
8
8
  const index = require('./index-cb904e00.js');
9
- const debounce$1 = require('./debounce-6cea2774.js');
9
+ const debounce$1 = require('./debounce-f5e62c5a.js');
10
10
 
11
11
  class ThemeCompact {
12
12
  constructor() {
@@ -5346,7 +5346,12 @@ class FilterPlugin extends BasePlugin {
5346
5346
  const buttonPos = el.getBoundingClientRect();
5347
5347
  const prop = e.detail.prop;
5348
5348
  this.pop.filterTypes = this.getColumnFilter(e.detail.filter);
5349
- this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: buttonPos.x - gridPos.x, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
5349
+ this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: -9999, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
5350
+ // fix filter dialog is out of view
5351
+ setTimeout(async () => {
5352
+ const { width } = this.pop.getBoundingClientRect();
5353
+ this.pop.style.left = Math.min(buttonPos.x - gridPos.x, gridPos.width - width - 20) + 'px';
5354
+ });
5350
5355
  }
5351
5356
  getColumnFilter(type) {
5352
5357
  let filterType = 'string';
@@ -25962,6 +25967,11 @@ var codesLetter;
25962
25967
  codesLetter["ARROW_DOWN"] = "ArrowDown";
25963
25968
  codesLetter["SHIFT"] = "Shift";
25964
25969
  })(codesLetter || (codesLetter = {}));
25970
+ var keyValues;
25971
+ (function (keyValues) {
25972
+ keyValues["ENTER"] = "Enter";
25973
+ keyValues["TAB"] = "Tab";
25974
+ })(keyValues || (keyValues = {}));
25965
25975
  const KeyCodesEnum = codes;
25966
25976
 
25967
25977
  var osPlatform;
@@ -26141,11 +26151,11 @@ function isCtrlKey(code, platform) {
26141
26151
  function isClear(code) {
26142
26152
  return codesLetter.BACKSPACE === code || codesLetter.DELETE === code;
26143
26153
  }
26144
- function isTab(code) {
26145
- return codesLetter.TAB === code;
26154
+ function isTabKeyValue(key) {
26155
+ return keyValues.TAB === key;
26146
26156
  }
26147
- function isEnterKey(code) {
26148
- return code === codesLetter.ENTER || code === codesLetter.ENTER_NUM;
26157
+ function isEnterKeyValue(key) {
26158
+ return keyValues.ENTER === key;
26149
26159
  }
26150
26160
 
26151
26161
  class TextEditor {
@@ -26163,8 +26173,8 @@ class TextEditor {
26163
26173
  }
26164
26174
  }
26165
26175
  onKeyDown(e) {
26166
- const isEnter = isEnterKey(e.code);
26167
- const isKeyTab = isTab(e.code);
26176
+ const isEnter = isEnterKeyValue(e.key);
26177
+ const isKeyTab = isTabKeyValue(e.key);
26168
26178
  if ((isKeyTab || isEnter) && e.target && this.saveCallback && !e.isComposing) {
26169
26179
  // blur is needed to avoid autoscroll
26170
26180
  this.editInput.blur();
@@ -26175,7 +26185,7 @@ class TextEditor {
26175
26185
  // required
26176
26186
  render() {
26177
26187
  var _a;
26178
- return (index.h("input", { type: "text", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
26188
+ return (index.h("input", { type: "text", enterkeyhint: "enter", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
26179
26189
  this.editInput = el;
26180
26190
  }, onKeyDown: e => this.onKeyDown(e) }));
26181
26191
  }
@@ -26484,7 +26494,8 @@ var keyBy = _createAggregator(function(result, value, key) {
26484
26494
  var keyBy_1 = keyBy;
26485
26495
 
26486
26496
  const SortingSign = ({ column }) => {
26487
- return index.h("i", { class: column.order });
26497
+ var _a;
26498
+ return index.h("i", { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' });
26488
26499
  };
26489
26500
 
26490
26501
  var ResizeEvents;
@@ -26763,7 +26774,7 @@ const HeaderCellRenderer = ({ data, props }, children) => {
26763
26774
  };
26764
26775
 
26765
26776
  const HeaderRenderer = (p) => {
26766
- var _a, _b, _c, _d, _e, _f;
26777
+ var _a, _b, _c, _d, _e;
26767
26778
  const cellClass = {
26768
26779
  [HEADER_CLASS]: true,
26769
26780
  [HEADER_SORTABLE_CLASS]: !!((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable),
@@ -26798,8 +26809,8 @@ const HeaderRenderer = (p) => {
26798
26809
  }
26799
26810
  }
26800
26811
  return (index.h(HeaderCellRenderer, { data: p.data, props: dataProps },
26801
- ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) ? index.h(SortingSign, { column: p.data }) : '',
26802
- p.canFilter && ((_f = p.data) === null || _f === void 0 ? void 0 : _f.filter) !== false ? index.h(debounce$1.FilterButton, { column: p.data }) : ''));
26812
+ index.h(SortingSign, { column: p.data }),
26813
+ p.canFilter && ((_e = p.data) === null || _e === void 0 ? void 0 : _e.filter) !== false ? index.h(debounce$1.FilterButton, { column: p.data }) : ''));
26803
26814
  };
26804
26815
 
26805
26816
  const GroupHeaderRenderer = (p) => {
@@ -27126,7 +27137,7 @@ class KeyboardService {
27126
27137
  return;
27127
27138
  }
27128
27139
  // pressed enter
27129
- if (isEnterKey(e.code)) {
27140
+ if (isEnterKeyValue(e.key)) {
27130
27141
  this.sv.doEdit();
27131
27142
  return;
27132
27143
  }
@@ -27751,10 +27762,13 @@ const RevogrRowHeaders = class {
27751
27762
  /** render viewports rows */
27752
27763
  let totalLength = 1;
27753
27764
  for (let data of this.dataPorts) {
27754
- const itemCount = data.dataStore.get('items').length;
27765
+ const items = data.dataStore.get('items');
27766
+ const itemCount = items.length;
27767
+ const source = data.dataStore.get('source');
27768
+ const visibleSourceItems = items.map(v => source[v]); // from src/store/dataSource/data.store.ts
27755
27769
  // initiate row data
27756
27770
  const dataStore = new DataStore(data.type);
27757
- dataStore.updateData(data.dataStore.get('source'));
27771
+ dataStore.updateData(visibleSourceItems);
27758
27772
  // initiate column data
27759
27773
  const colData = new DataStore('colPinStart');
27760
27774
  const column = Object.assign({ cellTemplate: RowHeaderRender(totalLength) }, this.rowHeaderColumn);
@@ -16,8 +16,9 @@ const Clipboard = class {
16
16
  onPaste(e) {
17
17
  const clipboardData = this.getData(e);
18
18
  const isHTML = clipboardData.types.indexOf('text/html') > -1;
19
- const data = isHTML ? clipboardData.getData('text/html') : clipboardData.getData('text');
20
- const parsedData = isHTML ? this.htmlParse(data) : this.textParse(data);
19
+ const canBeParsedAsHtml = isHTML ? this.canBeParsedAsHTML(clipboardData.getData('text/html')) : false;
20
+ const data = canBeParsedAsHtml ? clipboardData.getData('text/html') : clipboardData.getData('text');
21
+ const parsedData = canBeParsedAsHtml ? this.htmlParse(data) : this.textParse(data);
21
22
  this.pasteRegion.emit(parsedData);
22
23
  e.preventDefault();
23
24
  }
@@ -47,6 +48,9 @@ const Clipboard = class {
47
48
  }
48
49
  return result;
49
50
  }
51
+ canBeParsedAsHTML(data) {
52
+ return document.createRange().createContextualFragment(data).querySelector('table') !== null;
53
+ }
50
54
  getData(e) {
51
55
  var _a;
52
56
  return e.clipboardData || ((_a = window) === null || _a === void 0 ? void 0 : _a.clipboardData);
@@ -6,7 +6,7 @@
6
6
  Object.defineProperty(exports, '__esModule', { value: true });
7
7
 
8
8
  const index = require('./index-cb904e00.js');
9
- const debounce = require('./debounce-6cea2774.js');
9
+ const debounce = require('./debounce-f5e62c5a.js');
10
10
 
11
11
  const RevoButton = (props, children) => {
12
12
  return (index.h("button", Object.assign({}, props, { class: Object.assign(Object.assign({}, (typeof props.class === 'object' ? props.class : props.class ? { [props.class]: true } : '')), { ['revo-button']: true }) }), children));
@@ -45,6 +45,10 @@ const FilterPanel = class {
45
45
  save: 'Save',
46
46
  reset: 'Reset',
47
47
  cancel: 'Close',
48
+ add: 'Add more condition...',
49
+ placeholder: 'Enter value...',
50
+ and: 'and',
51
+ or: 'or',
48
52
  };
49
53
  this.isFilterIdSet = false;
50
54
  this.filterId = 0;
@@ -91,7 +95,8 @@ const FilterPanel = class {
91
95
  const options = [];
92
96
  const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
93
97
  if (!isDefaultTypeRemoved) {
94
- options.push(index.h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? 'Add more condition...' : this.filterNames[defaultType]));
98
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
99
+ options.push(index.h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? capts.add : this.filterNames[defaultType]));
95
100
  }
96
101
  for (let gIndex in this.filterTypes) {
97
102
  options.push(...this.filterTypes[gIndex].map(k => (index.h("option", { value: k, selected: type === k }, this.filterNames[k]))));
@@ -105,7 +110,8 @@ const FilterPanel = class {
105
110
  return '';
106
111
  if (this.filterEntities[currentFilter[index$1].type].extra !== 'input')
107
112
  return '';
108
- return (index.h("input", { id: `filter-input-${currentFilter[index$1].id}`, placeholder: "Enter value...", type: "text", value: currentFilter[index$1].value, onInput: this.onUserInput.bind(this, index$1, prop), onKeyDown: e => this.onKeyDown(e) }));
113
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
114
+ return (index.h("input", { id: `filter-input-${currentFilter[index$1].id}`, placeholder: capts.placeholder, type: "text", value: currentFilter[index$1].value, onInput: this.onUserInput.bind(this, index$1, prop), onKeyDown: e => this.onKeyDown(e) }));
109
115
  }
110
116
  getFilterItemsList() {
111
117
  var _a;
@@ -113,11 +119,12 @@ const FilterPanel = class {
113
119
  if (!(prop || prop === 0))
114
120
  return '';
115
121
  const propFilters = this.filterItems[prop] || [];
122
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
116
123
  return (index.h("div", { key: this.filterId }, propFilters.map((d, index$1) => {
117
124
  let andOrButton;
118
125
  // hide toggle button if there is only one filter and the last one
119
126
  if (index$1 !== this.filterItems[prop].length - 1) {
120
- andOrButton = (index.h("div", { onClick: () => this.toggleFilterAndOr(d.id) }, index.h(debounce.AndOrButton, { isAnd: d.relation === 'and' })));
127
+ andOrButton = (index.h("div", { onClick: () => this.toggleFilterAndOr(d.id) }, index.h(debounce.AndOrButton, { text: d.relation === 'and' ? capts.and : capts.or })));
121
128
  }
122
129
  return (index.h("div", { key: d.id, class: FILTER_LIST_CLASS }, index.h("div", { class: { 'select-input': true } }, index.h("select", { class: "select-css select-filter", onChange: e => this.onFilterTypeChange(e, prop, index$1) }, this.renderSelectOptions(this.filterItems[prop][index$1].type, true)), index.h("div", { class: FILTER_LIST_CLASS_ACTION }, andOrButton), index.h("div", { onClick: () => this.onRemoveFilter(d.id) }, index.h(debounce.TrashButton, null))), index.h("div", null, this.renderExtra(prop, index$1))));
123
130
  }), propFilters.length > 0 ? index.h("div", { class: "add-filter-divider" }) : ''));
@@ -6,8 +6,9 @@ export class Clipboard {
6
6
  onPaste(e) {
7
7
  const clipboardData = this.getData(e);
8
8
  const isHTML = clipboardData.types.indexOf('text/html') > -1;
9
- const data = isHTML ? clipboardData.getData('text/html') : clipboardData.getData('text');
10
- const parsedData = isHTML ? this.htmlParse(data) : this.textParse(data);
9
+ const canBeParsedAsHtml = isHTML ? this.canBeParsedAsHTML(clipboardData.getData('text/html')) : false;
10
+ const data = canBeParsedAsHtml ? clipboardData.getData('text/html') : clipboardData.getData('text');
11
+ const parsedData = canBeParsedAsHtml ? this.htmlParse(data) : this.textParse(data);
11
12
  this.pasteRegion.emit(parsedData);
12
13
  e.preventDefault();
13
14
  }
@@ -37,6 +38,9 @@ export class Clipboard {
37
38
  }
38
39
  return result;
39
40
  }
41
+ canBeParsedAsHTML(data) {
42
+ return document.createRange().createContextualFragment(data).querySelector('table') !== null;
43
+ }
40
44
  getData(e) {
41
45
  var _a;
42
46
  return e.clipboardData || ((_a = window) === null || _a === void 0 ? void 0 : _a.clipboardData);
@@ -7,7 +7,7 @@ import { SortingSign } from '../../plugins/sorting/sorting.sign';
7
7
  import { DATA_COL, FOCUS_CLASS, HEADER_CLASS, HEADER_SORTABLE_CLASS, MIN_COL_SIZE } from '../../utils/consts';
8
8
  import { HeaderCellRenderer } from './headerCellRenderer';
9
9
  const HeaderRenderer = (p) => {
10
- var _a, _b, _c, _d, _e, _f;
10
+ var _a, _b, _c, _d, _e;
11
11
  const cellClass = {
12
12
  [HEADER_CLASS]: true,
13
13
  [HEADER_SORTABLE_CLASS]: !!((_a = p.data) === null || _a === void 0 ? void 0 : _a.sortable),
@@ -42,7 +42,7 @@ const HeaderRenderer = (p) => {
42
42
  }
43
43
  }
44
44
  return (h(HeaderCellRenderer, { data: p.data, props: dataProps },
45
- ((_e = p.data) === null || _e === void 0 ? void 0 : _e.order) ? h(SortingSign, { column: p.data }) : '',
46
- p.canFilter && ((_f = p.data) === null || _f === void 0 ? void 0 : _f.filter) !== false ? h(FilterButton, { column: p.data }) : ''));
45
+ h(SortingSign, { column: p.data }),
46
+ p.canFilter && ((_e = p.data) === null || _e === void 0 ? void 0 : _e.filter) !== false ? h(FilterButton, { column: p.data }) : ''));
47
47
  };
48
48
  export default HeaderRenderer;
@@ -2,7 +2,7 @@
2
2
  * Built by Revolist
3
3
  */
4
4
  import { h } from '@stencil/core';
5
- import { isEnterKey, isTab } from '../../../utils/keyCodes.utils';
5
+ import { isEnterKeyValue, isTabKeyValue } from '../../../utils/keyCodes.utils';
6
6
  import { timeout } from '../../../utils/utils';
7
7
  export class TextEditor {
8
8
  constructor(column, saveCallback) {
@@ -19,8 +19,8 @@ export class TextEditor {
19
19
  }
20
20
  }
21
21
  onKeyDown(e) {
22
- const isEnter = isEnterKey(e.code);
23
- const isKeyTab = isTab(e.code);
22
+ const isEnter = isEnterKeyValue(e.key);
23
+ const isKeyTab = isTabKeyValue(e.key);
24
24
  if ((isKeyTab || isEnter) && e.target && this.saveCallback && !e.isComposing) {
25
25
  // blur is needed to avoid autoscroll
26
26
  this.editInput.blur();
@@ -31,7 +31,7 @@ export class TextEditor {
31
31
  // required
32
32
  render() {
33
33
  var _a;
34
- return (h("input", { type: "text", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
34
+ return (h("input", { type: "text", enterkeyhint: "enter", value: ((_a = this.editCell) === null || _a === void 0 ? void 0 : _a.val) || '', ref: el => {
35
35
  this.editInput = el;
36
36
  }, onKeyDown: e => this.onKeyDown(e) }));
37
37
  }
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { getRange } from '../../store/selection/selection.helpers';
5
5
  import { codesLetter } from '../../utils/keyCodes';
6
- import { isClear, isCtrlKey, isEnterKey, isLetterKey } from '../../utils/keyCodes.utils';
6
+ import { isClear, isCtrlKey, isEnterKeyValue, isLetterKey } from '../../utils/keyCodes.utils';
7
7
  import { timeout } from '../../utils/utils';
8
8
  import { getCoordinate, isAfterLast, isBeforeFirst } from './selection.utils';
9
9
  export class KeyboardService {
@@ -43,7 +43,7 @@ export class KeyboardService {
43
43
  return;
44
44
  }
45
45
  // pressed enter
46
- if (isEnterKey(e.code)) {
46
+ if (isEnterKeyValue(e.key)) {
47
47
  this.sv.doEdit();
48
48
  return;
49
49
  }
@@ -16,10 +16,13 @@ export class RevogrRowHeaders {
16
16
  /** render viewports rows */
17
17
  let totalLength = 1;
18
18
  for (let data of this.dataPorts) {
19
- const itemCount = data.dataStore.get('items').length;
19
+ const items = data.dataStore.get('items');
20
+ const itemCount = items.length;
21
+ const source = data.dataStore.get('source');
22
+ const visibleSourceItems = items.map(v => source[v]); // from src/store/dataSource/data.store.ts
20
23
  // initiate row data
21
24
  const dataStore = new DataStore(data.type);
22
- dataStore.updateData(data.dataStore.get('source'));
25
+ dataStore.updateData(visibleSourceItems);
23
26
  // initiate column data
24
27
  const colData = new DataStore('colPinStart');
25
28
  const column = Object.assign({ cellTemplate: RowHeaderRender(totalLength) }, this.rowHeaderColumn);
@@ -22,8 +22,8 @@ export const TrashButton = () => {
22
22
  h("svg", { class: "trash-img", viewBox: "0 0 24 24" },
23
23
  h("path", { fill: "currentColor", d: "M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" }))));
24
24
  };
25
- export const AndOrButton = ({ isAnd }) => {
26
- return h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, isAnd ? 'and' : 'or');
25
+ export const AndOrButton = ({ text }) => {
26
+ return h("button", { class: { [AND_OR_BUTTON]: true, 'light revo-button': true } }, text);
27
27
  };
28
28
  export function isFilterBtn(e) {
29
29
  if (e.classList.contains(FILTER_BUTTON_CLASS)) {
@@ -109,7 +109,12 @@ export default class FilterPlugin extends BasePlugin {
109
109
  const buttonPos = el.getBoundingClientRect();
110
110
  const prop = e.detail.prop;
111
111
  this.pop.filterTypes = this.getColumnFilter(e.detail.filter);
112
- this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: buttonPos.x - gridPos.x, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
112
+ this.pop.show(Object.assign(Object.assign({}, this.filterCollection[prop]), { x: -9999, y: buttonPos.y - gridPos.y + buttonPos.height, prop }));
113
+ // fix filter dialog is out of view
114
+ setTimeout(async () => {
115
+ const { width } = this.pop.getBoundingClientRect();
116
+ this.pop.style.left = Math.min(buttonPos.x - gridPos.x, gridPos.width - width - 20) + 'px';
117
+ });
113
118
  }
114
119
  getColumnFilter(type) {
115
120
  let filterType = 'string';
@@ -16,6 +16,10 @@ export class FilterPanel {
16
16
  save: 'Save',
17
17
  reset: 'Reset',
18
18
  cancel: 'Close',
19
+ add: 'Add more condition...',
20
+ placeholder: 'Enter value...',
21
+ and: 'and',
22
+ or: 'or',
19
23
  };
20
24
  this.isFilterIdSet = false;
21
25
  this.filterId = 0;
@@ -62,7 +66,8 @@ export class FilterPanel {
62
66
  const options = [];
63
67
  const prop = (_a = this.changes) === null || _a === void 0 ? void 0 : _a.prop;
64
68
  if (!isDefaultTypeRemoved) {
65
- options.push(h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? 'Add more condition...' : this.filterNames[defaultType]));
69
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
70
+ options.push(h("option", { selected: this.currentFilterType === defaultType, value: defaultType }, prop && this.filterItems[prop] && this.filterItems[prop].length > 0 ? capts.add : this.filterNames[defaultType]));
66
71
  }
67
72
  for (let gIndex in this.filterTypes) {
68
73
  options.push(...this.filterTypes[gIndex].map(k => (h("option", { value: k, selected: type === k }, this.filterNames[k]))));
@@ -76,7 +81,8 @@ export class FilterPanel {
76
81
  return '';
77
82
  if (this.filterEntities[currentFilter[index].type].extra !== 'input')
78
83
  return '';
79
- return (h("input", { id: `filter-input-${currentFilter[index].id}`, placeholder: "Enter value...", type: "text", value: currentFilter[index].value, onInput: this.onUserInput.bind(this, index, prop), onKeyDown: e => this.onKeyDown(e) }));
84
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
85
+ return (h("input", { id: `filter-input-${currentFilter[index].id}`, placeholder: capts.placeholder, type: "text", value: currentFilter[index].value, onInput: this.onUserInput.bind(this, index, prop), onKeyDown: e => this.onKeyDown(e) }));
80
86
  }
81
87
  getFilterItemsList() {
82
88
  var _a;
@@ -84,13 +90,14 @@ export class FilterPanel {
84
90
  if (!(prop || prop === 0))
85
91
  return '';
86
92
  const propFilters = this.filterItems[prop] || [];
93
+ const capts = Object.assign(this.filterCaptionsInternal, this.filterCaptions);
87
94
  return (h("div", { key: this.filterId },
88
95
  propFilters.map((d, index) => {
89
96
  let andOrButton;
90
97
  // hide toggle button if there is only one filter and the last one
91
98
  if (index !== this.filterItems[prop].length - 1) {
92
99
  andOrButton = (h("div", { onClick: () => this.toggleFilterAndOr(d.id) },
93
- h(AndOrButton, { isAnd: d.relation === 'and' })));
100
+ h(AndOrButton, { text: d.relation === 'and' ? capts.and : capts.or })));
94
101
  }
95
102
  return (h("div", { key: d.id, class: FILTER_LIST_CLASS },
96
103
  h("div", { class: { 'select-input': true } },
@@ -374,7 +381,7 @@ export class FilterPanel {
374
381
  "mutable": false,
375
382
  "complexType": {
376
383
  "original": "FilterCaptions | undefined",
377
- "resolved": "{ title: string; save: string; reset: string; cancel: string; }",
384
+ "resolved": "{ title: string; save: string; reset: string; cancel: string; add: string; placeholder: string; and: string; or: string; }",
378
385
  "references": {
379
386
  "FilterCaptions": {
380
387
  "location": "import",
@@ -5,5 +5,6 @@ import { h } from '@stencil/core';
5
5
  export const FILTER_BUTTON_CLASS = 'rv-filter';
6
6
  export const FILTER_BUTTON_ACTIVE = 'active';
7
7
  export const SortingSign = ({ column }) => {
8
- return h("i", { class: column.order });
8
+ var _a;
9
+ return h("i", { class: (_a = column === null || column === void 0 ? void 0 : column.order) !== null && _a !== void 0 ? _a : 'sort-off' });
9
10
  };