@revolist/revogrid 4.10.31 → 4.10.32

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 (79) hide show
  1. package/dist/cjs/{sorting.plugin-13a26a98.js → column.drag.plugin-e7ee8105.js} +790 -749
  2. package/dist/cjs/column.drag.plugin-e7ee8105.js.map +1 -0
  3. package/dist/cjs/{column.service-f869b692.js → column.service-905483c3.js} +3 -2
  4. package/dist/cjs/column.service-905483c3.js.map +1 -0
  5. package/dist/cjs/{header-cell-renderer-131f117c.js → header-cell-renderer-64a361f7.js} +2 -2
  6. package/dist/cjs/{header-cell-renderer-131f117c.js.map → header-cell-renderer-64a361f7.js.map} +1 -1
  7. package/dist/cjs/index.cjs.js +26 -25
  8. package/dist/cjs/index.cjs.js.map +1 -1
  9. package/dist/cjs/loader.cjs.js +1 -1
  10. package/dist/cjs/revo-grid.cjs.entry.js +41 -35
  11. package/dist/cjs/revo-grid.cjs.entry.js.map +1 -1
  12. package/dist/cjs/revo-grid.cjs.js +1 -1
  13. package/dist/cjs/revogr-attribution_7.cjs.entry.js +1 -1
  14. package/dist/cjs/revogr-data_4.cjs.entry.js +2 -2
  15. package/dist/collection/components/revoGrid/revo-grid.js +49 -0
  16. package/dist/collection/components/revoGrid/revo-grid.js.map +1 -1
  17. package/dist/collection/plugins/groupingRow/grouping.row.plugin.js +12 -1
  18. package/dist/collection/plugins/groupingRow/grouping.row.plugin.js.map +1 -1
  19. package/dist/collection/plugins/groupingRow/grouping.service.js +2 -1
  20. package/dist/collection/plugins/groupingRow/grouping.service.js.map +1 -1
  21. package/dist/collection/plugins/sorting/sorting.func.js +13 -2
  22. package/dist/collection/plugins/sorting/sorting.func.js.map +1 -1
  23. package/dist/collection/plugins/sorting/sorting.plugin.js +29 -8
  24. package/dist/collection/plugins/sorting/sorting.plugin.js.map +1 -1
  25. package/dist/collection/plugins/sorting/sorting.types.js.map +1 -1
  26. package/dist/collection/serve/controller.js +6 -6
  27. package/dist/collection/types/events.js +1 -0
  28. package/dist/collection/types/events.js.map +1 -1
  29. package/dist/esm/{sorting.plugin-a1ed0f51.js → column.drag.plugin-6ed6cd8d.js} +792 -751
  30. package/dist/esm/column.drag.plugin-6ed6cd8d.js.map +1 -0
  31. package/dist/esm/{column.service-6b4e24b4.js → column.service-7a47e6d0.js} +3 -2
  32. package/dist/esm/column.service-7a47e6d0.js.map +1 -0
  33. package/dist/esm/{header-cell-renderer-d44bd756.js → header-cell-renderer-f46a8010.js} +2 -2
  34. package/dist/esm/{header-cell-renderer-d44bd756.js.map → header-cell-renderer-f46a8010.js.map} +1 -1
  35. package/dist/esm/index.js +5 -4
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/loader.js +1 -1
  38. package/dist/esm/revo-grid.entry.js +9 -3
  39. package/dist/esm/revo-grid.entry.js.map +1 -1
  40. package/dist/esm/revo-grid.js +1 -1
  41. package/dist/esm/revogr-attribution_7.entry.js +1 -1
  42. package/dist/esm/revogr-data_4.entry.js +2 -2
  43. package/dist/revo-grid/column.drag.plugin-6ed6cd8d.js +5 -0
  44. package/dist/revo-grid/column.drag.plugin-6ed6cd8d.js.map +1 -0
  45. package/dist/revo-grid/{column.service-6b4e24b4.js → column.service-7a47e6d0.js} +2 -2
  46. package/dist/revo-grid/column.service-7a47e6d0.js.map +1 -0
  47. package/dist/revo-grid/{header-cell-renderer-d44bd756.js → header-cell-renderer-f46a8010.js} +2 -2
  48. package/dist/revo-grid/index.esm.js +1 -1
  49. package/dist/revo-grid/index.esm.js.map +1 -1
  50. package/dist/revo-grid/revo-grid.entry.js +1 -1
  51. package/dist/revo-grid/revo-grid.entry.js.map +1 -1
  52. package/dist/revo-grid/revo-grid.esm.js +1 -1
  53. package/dist/revo-grid/revo-grid.esm.js.map +1 -1
  54. package/dist/revo-grid/revogr-attribution_7.entry.js +1 -1
  55. package/dist/revo-grid/revogr-data_4.entry.js +1 -1
  56. package/dist/types/components/revoGrid/revo-grid.d.ts +11 -0
  57. package/dist/types/components.d.ts +15 -0
  58. package/dist/types/plugins/groupingRow/grouping.row.plugin.d.ts +1 -0
  59. package/dist/types/plugins/groupingRow/grouping.service.d.ts +4 -3
  60. package/dist/types/plugins/sorting/sorting.plugin.d.ts +3 -3
  61. package/dist/types/plugins/sorting/sorting.types.d.ts +7 -0
  62. package/dist/types/types/events.d.ts +1 -1
  63. package/hydrate/index.js +61 -12
  64. package/hydrate/index.mjs +61 -12
  65. package/package.json +1 -1
  66. package/standalone/column.service.js +2 -1
  67. package/standalone/column.service.js.map +1 -1
  68. package/standalone/index.js +1 -0
  69. package/standalone/index.js.map +1 -1
  70. package/standalone/revo-grid.js +797 -748
  71. package/standalone/revo-grid.js.map +1 -1
  72. package/dist/cjs/column.service-f869b692.js.map +0 -1
  73. package/dist/cjs/sorting.plugin-13a26a98.js.map +0 -1
  74. package/dist/esm/column.service-6b4e24b4.js.map +0 -1
  75. package/dist/esm/sorting.plugin-a1ed0f51.js.map +0 -1
  76. package/dist/revo-grid/column.service-6b4e24b4.js.map +0 -1
  77. package/dist/revo-grid/sorting.plugin-a1ed0f51.js +0 -5
  78. package/dist/revo-grid/sorting.plugin-a1ed0f51.js.map +0 -1
  79. /package/dist/revo-grid/{header-cell-renderer-d44bd756.js.map → header-cell-renderer-f46a8010.js.map} +0 -0
@@ -3,13 +3,13 @@
3
3
  */
4
4
  'use strict';
5
5
 
6
- const column_service = require('./column.service-f869b692.js');
6
+ const column_service = require('./column.service-905483c3.js');
7
7
  const dimension_helpers = require('./dimension.helpers-1927ad24.js');
8
8
  const viewport_store = require('./viewport.store-69b45f22.js');
9
9
  const index = require('./index-10d10c55.js');
10
10
  const filter_button = require('./filter.button-b8debe72.js');
11
11
  const debounce = require('./debounce-ec7a04b4.js');
12
- const headerCellRenderer = require('./header-cell-renderer-131f117c.js');
12
+ const headerCellRenderer = require('./header-cell-renderer-64a361f7.js');
13
13
 
14
14
  /**
15
15
  * Plugin which recalculates realSize on changes of sizes, originItemSize and count
@@ -1626,838 +1626,879 @@ function processDoubleConversionTrimmed(initiallyTrimed, firstLevelMap, secondLe
1626
1626
  return trimemedOptionsToUpgrade;
1627
1627
  }
1628
1628
 
1629
- class GroupingRowPlugin extends BasePlugin {
1630
- getStore(type = column_service.GROUPING_ROW_TYPE) {
1631
- return this.providers.data.stores[type].store;
1632
- }
1633
- constructor(revogrid, providers) {
1634
- super(revogrid, providers);
1635
- this.revogrid = revogrid;
1636
- this.providers = providers;
1637
- }
1638
- // befoce cell focus
1639
- onFocus(e) {
1640
- if (column_service.isGrouping(e.detail.model)) {
1641
- e.preventDefault();
1642
- }
1629
+ /** `Object#toString` result references. */
1630
+ var stringTag = '[object String]';
1631
+
1632
+ /**
1633
+ * Checks if `value` is classified as a `String` primitive or object.
1634
+ *
1635
+ * @static
1636
+ * @since 0.1.0
1637
+ * @memberOf _
1638
+ * @category Lang
1639
+ * @param {*} value The value to check.
1640
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
1641
+ * @example
1642
+ *
1643
+ * _.isString('abc');
1644
+ * // => true
1645
+ *
1646
+ * _.isString(1);
1647
+ * // => false
1648
+ */
1649
+ function isString(value) {
1650
+ return typeof value == 'string' ||
1651
+ (!dimension_helpers.isArray(value) && debounce.isObjectLike(value) && debounce.baseGetTag(value) == stringTag);
1652
+ }
1653
+
1654
+ /**
1655
+ * Gets the size of an ASCII `string`.
1656
+ *
1657
+ * @private
1658
+ * @param {string} string The string inspect.
1659
+ * @returns {number} Returns the string size.
1660
+ */
1661
+ var asciiSize = dimension_helpers.baseProperty('length');
1662
+
1663
+ const asciiSize$1 = asciiSize;
1664
+
1665
+ /** Used to compose unicode character classes. */
1666
+ var rsAstralRange$1 = '\\ud800-\\udfff',
1667
+ rsComboMarksRange$1 = '\\u0300-\\u036f',
1668
+ reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f',
1669
+ rsComboSymbolsRange$1 = '\\u20d0-\\u20ff',
1670
+ rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1,
1671
+ rsVarRange$1 = '\\ufe0e\\ufe0f';
1672
+
1673
+ /** Used to compose unicode capture groups. */
1674
+ var rsZWJ$1 = '\\u200d';
1675
+
1676
+ /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
1677
+ var reHasUnicode = RegExp('[' + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + ']');
1678
+
1679
+ /**
1680
+ * Checks if `string` contains Unicode symbols.
1681
+ *
1682
+ * @private
1683
+ * @param {string} string The string to inspect.
1684
+ * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1685
+ */
1686
+ function hasUnicode(string) {
1687
+ return reHasUnicode.test(string);
1688
+ }
1689
+
1690
+ /** Used to compose unicode character classes. */
1691
+ var rsAstralRange = '\\ud800-\\udfff',
1692
+ rsComboMarksRange = '\\u0300-\\u036f',
1693
+ reComboHalfMarksRange = '\\ufe20-\\ufe2f',
1694
+ rsComboSymbolsRange = '\\u20d0-\\u20ff',
1695
+ rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
1696
+ rsVarRange = '\\ufe0e\\ufe0f';
1697
+
1698
+ /** Used to compose unicode capture groups. */
1699
+ var rsAstral = '[' + rsAstralRange + ']',
1700
+ rsCombo = '[' + rsComboRange + ']',
1701
+ rsFitz = '\\ud83c[\\udffb-\\udfff]',
1702
+ rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
1703
+ rsNonAstral = '[^' + rsAstralRange + ']',
1704
+ rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
1705
+ rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
1706
+ rsZWJ = '\\u200d';
1707
+
1708
+ /** Used to compose unicode regexes. */
1709
+ var reOptMod = rsModifier + '?',
1710
+ rsOptVar = '[' + rsVarRange + ']?',
1711
+ rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
1712
+ rsSeq = rsOptVar + reOptMod + rsOptJoin,
1713
+ rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
1714
+
1715
+ /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
1716
+ var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
1717
+
1718
+ /**
1719
+ * Gets the size of a Unicode `string`.
1720
+ *
1721
+ * @private
1722
+ * @param {string} string The string inspect.
1723
+ * @returns {number} Returns the string size.
1724
+ */
1725
+ function unicodeSize(string) {
1726
+ var result = reUnicode.lastIndex = 0;
1727
+ while (reUnicode.test(string)) {
1728
+ ++result;
1729
+ }
1730
+ return result;
1731
+ }
1732
+
1733
+ /**
1734
+ * Gets the number of symbols in `string`.
1735
+ *
1736
+ * @private
1737
+ * @param {string} string The string to inspect.
1738
+ * @returns {number} Returns the string size.
1739
+ */
1740
+ function stringSize(string) {
1741
+ return hasUnicode(string)
1742
+ ? unicodeSize(string)
1743
+ : asciiSize$1(string);
1744
+ }
1745
+
1746
+ /** `Object#toString` result references. */
1747
+ var mapTag = '[object Map]',
1748
+ setTag = '[object Set]';
1749
+
1750
+ /**
1751
+ * Gets the size of `collection` by returning its length for array-like
1752
+ * values or the number of own enumerable string keyed properties for objects.
1753
+ *
1754
+ * @static
1755
+ * @memberOf _
1756
+ * @since 0.1.0
1757
+ * @category Collection
1758
+ * @param {Array|Object|string} collection The collection to inspect.
1759
+ * @returns {number} Returns the collection size.
1760
+ * @example
1761
+ *
1762
+ * _.size([1, 2, 3]);
1763
+ * // => 3
1764
+ *
1765
+ * _.size({ 'a': 1, 'b': 2 });
1766
+ * // => 2
1767
+ *
1768
+ * _.size('pebbles');
1769
+ * // => 7
1770
+ */
1771
+ function size(collection) {
1772
+ if (collection == null) {
1773
+ return 0;
1774
+ }
1775
+ if (dimension_helpers.isArrayLike(collection)) {
1776
+ return isString(collection) ? stringSize(collection) : collection.length;
1777
+ }
1778
+ var tag = dimension_helpers.getTag(collection);
1779
+ if (tag == mapTag || tag == setTag) {
1780
+ return collection.size;
1781
+ }
1782
+ return dimension_helpers.baseKeys(collection).length;
1783
+ }
1784
+
1785
+ function sortIndexByItems(indexes, source, sortingFunc = {}) {
1786
+ // if no sorting - return unsorted indexes
1787
+ if (Object.entries(sortingFunc).length === 0) {
1788
+ // Unsorted indexes
1789
+ return [...Array(indexes.length).keys()];
1643
1790
  }
1644
- // expand event triggered
1645
- onExpand({ virtualIndex }) {
1646
- const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
1647
- let newTrimmed = this.getStore().get('trimmed')[TRIMMED_GROUPING];
1648
- let i = dimension_helpers.getPhysical(this.getStore(), virtualIndex);
1649
- const isExpanded = column_service.getExpanded(source[i]);
1650
- if (!isExpanded) {
1651
- const { trimmed, items } = doExpand(virtualIndex, source, this.getStore().get('items'));
1652
- newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
1653
- if (items) {
1654
- dimension_helpers.setItems(this.getStore(), items);
1791
+ //
1792
+ /**
1793
+ * go through all indexes and align in new order
1794
+ * performs a multi-level sorting by applying multiple comparison functions to determine the order of the items based on different properties.
1795
+ */
1796
+ return indexes.sort((a, b) => {
1797
+ const itemA = source[a];
1798
+ const itemB = source[b];
1799
+ for (const [prop, cmp] of Object.entries(sortingFunc)) {
1800
+ if (column_service.isGrouping(itemA)) {
1801
+ if (itemA['__rvgr-prop'] !== prop) {
1802
+ return 0;
1803
+ }
1655
1804
  }
1656
- }
1657
- else {
1658
- const { trimmed } = doCollapse(i, source);
1659
- newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
1660
- this.revogrid.clearFocus();
1661
- }
1662
- this.getStore().set('source', source);
1663
- this.revogrid.addTrimmed(newTrimmed, TRIMMED_GROUPING);
1664
- }
1665
- setColumnGrouping(cols) {
1666
- // if 0 column as holder
1667
- if (cols === null || cols === void 0 ? void 0 : cols.length) {
1668
- cols[0][column_service.PSEUDO_GROUP_COLUMN] = true;
1669
- return true;
1670
- }
1671
- return false;
1672
- }
1673
- setColumns({ columns }) {
1674
- for (let type of columnTypes) {
1675
- if (this.setColumnGrouping(columns[type])) {
1676
- break;
1805
+ if (column_service.isGrouping(itemB)) {
1806
+ if (itemB['__rvgr-prop'] !== prop) {
1807
+ return 0;
1808
+ }
1677
1809
  }
1678
- }
1679
- }
1680
- // evaluate drag between groups
1681
- onDrag(e) {
1682
- const { from, to } = e.detail;
1683
- const isDown = to - from >= 0;
1684
- const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
1685
- const items = this.getStore().get('items');
1686
- let i = isDown ? from : to;
1687
- const end = isDown ? to : from;
1688
- for (; i < end; i++) {
1689
- const model = source[items[i]];
1690
- const isGroup = column_service.isGrouping(model);
1691
- if (isGroup) {
1692
- e.preventDefault();
1693
- return;
1810
+ /**
1811
+ * If the comparison function returns a non-zero value (sorted), it means that the items should be sorted based on the given property. In such a case, the function immediately returns the sorted value, indicating the order in which the items should be arranged.
1812
+ * If none of the comparison functions result in a non-zero value, indicating that the items are equal or should remain in the same order, the function eventually returns 0.
1813
+ */
1814
+ const sorted = cmp === null || cmp === void 0 ? void 0 : cmp(prop, itemA, itemB);
1815
+ if (sorted) {
1816
+ return sorted;
1694
1817
  }
1695
1818
  }
1819
+ return 0;
1820
+ });
1821
+ }
1822
+
1823
+ /**
1824
+ * Lifecycle
1825
+ * 1. @event `beforesorting` - Triggered when sorting just starts. Nothing has happened yet. This can be triggered from a column or from the source. If the type is from rows, the column will be undefined.
1826
+ * 2. @method `updateColumnSorting` - Updates the column sorting icon on the grid and the column itself, but the data remains untouched.
1827
+ * 3. @event `beforesortingapply` - Triggered before the sorting data is applied to the data source. You can prevent this event, and the data will not be sorted. This event is only called from a column sorting click.
1828
+ * 4. @event `aftersortingapply` - Triggered after sorting has been applied and completed. This event occurs for both row and column sorting.
1829
+ *
1830
+ * Note: If you prevent an event, it will not proceed to the subsequent steps.
1831
+ */
1832
+ class SortingPlugin extends BasePlugin {
1833
+ runSorting(order, comparison, ignoreViewportUpdate) {
1834
+ var _a;
1835
+ this.sort(order, comparison, undefined, ignoreViewportUpdate);
1836
+ (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
1837
+ this.sortingPromise = null;
1696
1838
  }
1697
- beforeTrimmedApply(trimmed, type) {
1698
- /** Before filter apply remove grouping filtering */
1699
- if (type === FILTER_TRIMMED_TYPE) {
1700
- const source = this.getStore().get('source');
1701
- for (let index in trimmed) {
1702
- if (trimmed[index] && column_service.isGrouping(source[index])) {
1703
- trimmed[index] = false;
1839
+ constructor(revogrid, providers, config) {
1840
+ super(revogrid, providers);
1841
+ this.revogrid = revogrid;
1842
+ this.sortingPromise = null;
1843
+ this.postponeSort = debounce.debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
1844
+ const setConfig = (cfg) => {
1845
+ var _a;
1846
+ if (cfg) {
1847
+ const sortingFunc = {};
1848
+ const order = {};
1849
+ (_a = cfg.columns) === null || _a === void 0 ? void 0 : _a.forEach(col => {
1850
+ sortingFunc[col.prop] = this.getComparer(col, col.order);
1851
+ order[col.prop] = col.order;
1852
+ });
1853
+ // // set sorting
1854
+ this.sorting = order;
1855
+ this.sortingFunc = sortingFunc;
1856
+ }
1857
+ };
1858
+ setConfig(config);
1859
+ this.addEventListener('sortingconfigchanged', ({ detail }) => {
1860
+ config = detail;
1861
+ setConfig(detail);
1862
+ this.startSorting(this.sorting, this.sortingFunc);
1863
+ });
1864
+ this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
1865
+ // if sorting was provided - sort data
1866
+ if (!!this.sorting && this.sortingFunc) {
1867
+ const beforeEvent = this.emit('beforesorting', { type });
1868
+ if (beforeEvent.defaultPrevented) {
1869
+ return;
1704
1870
  }
1871
+ this.startSorting(this.sorting, this.sortingFunc);
1705
1872
  }
1706
- }
1707
- }
1708
- // subscribe to grid events to process them accordingly
1709
- subscribe() {
1710
- /** if grouping present and new data source arrived */
1711
- this.addEventListener('beforesourceset', ({ detail }) => {
1712
- var _a, _b, _c;
1713
- if (!(((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length) && ((_c = detail === null || detail === void 0 ? void 0 : detail.source) === null || _c === void 0 ? void 0 : _c.length))) {
1873
+ });
1874
+ this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
1875
+ // if config provided - do nothing, read from config
1876
+ if (config) {
1714
1877
  return;
1715
1878
  }
1716
- this.onDataSet(detail);
1879
+ const columns = this.providers.column.getColumns();
1880
+ const sortingFunc = {};
1881
+ for (let prop in order) {
1882
+ const cmp = this.getComparer(column_service.getColumnByProp(columns, prop), order[prop]);
1883
+ sortingFunc[prop] = cmp;
1884
+ }
1885
+ // set sorting
1886
+ this.sorting = order;
1887
+ this.sortingFunc = order && sortingFunc;
1717
1888
  });
1718
- this.addEventListener('beforecolumnsset', ({ detail }) => this.setColumns(detail));
1719
- /**
1720
- * filter applied need to clear grouping and apply again
1721
- * based on new results can be new grouping
1722
- */
1723
- this.addEventListener('beforetrimmed', ({ detail: { trimmed, trimmedType } }) => this.beforeTrimmedApply(trimmed, trimmedType));
1724
- /**
1725
- * sorting applied need to clear grouping and apply again
1726
- * based on new results whole grouping order will changed
1727
- */
1728
- this.addEventListener('aftersortingapply', () => {
1889
+ this.addEventListener('beforeheaderclick', (e) => {
1729
1890
  var _a, _b;
1730
- if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
1891
+ if (e.defaultPrevented) {
1731
1892
  return;
1732
1893
  }
1733
- this.doSourceUpdate(Object.assign({}, this.options));
1894
+ if (!e.detail.column.sortable) {
1895
+ return;
1896
+ }
1897
+ this.headerclick(e.detail.column, e.detail.index, (_b = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.originalEvent) === null || _b === void 0 ? void 0 : _b.shiftKey);
1734
1898
  });
1735
- /**
1736
- * Apply logic for focus inside of grouping
1737
- * We can't focus on grouping rows, navigation only inside of groups for now
1738
- */
1739
- this.addEventListener('beforecellfocus', e => this.onFocus(e));
1740
- /**
1741
- * Prevent rgRow drag outside the group
1742
- */
1743
- this.addEventListener('roworderchanged', e => this.onDrag(e));
1744
- /**
1745
- * When grouping expand icon was clicked
1746
- */
1747
- this.addEventListener('groupexpandclick', e => this.onExpand(e.detail));
1748
1899
  }
1749
- /**
1750
- * Starts global source update with group clearing and applying new one
1751
- * Initiated when need to reapply grouping
1752
- */
1753
- doSourceUpdate(options) {
1754
- var _a;
1755
- /**
1756
- * Get source without grouping
1757
- * @param newOldIndexMap - provides us mapping with new indexes vs old indexes, we would use it for trimmed mapping
1758
- */
1759
- const { source, prevExpanded, oldNewIndexes } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
1760
- const expanded = Object.assign({ prevExpanded }, options);
1761
- /**
1762
- * Group again
1763
- * @param oldNewIndexMap - provides us mapping with new indexes vs old indexes
1764
- */
1765
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup, } = column_service.gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], expanded);
1766
- const customRenderer = options === null || options === void 0 ? void 0 : options.groupLabelTemplate;
1767
- // setup source
1768
- this.providers.data.setData(sourceWithGroups, column_service.GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, { depth, customRenderer }, true);
1769
- this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, oldNewIndexMap);
1900
+ startSorting(order, sortingFunc, ignoreViewportUpdate) {
1901
+ if (!this.sortingPromise) {
1902
+ // add job before render
1903
+ this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
1904
+ this.sortingPromise = resolve;
1905
+ }));
1906
+ }
1907
+ this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
1770
1908
  }
1771
- /**
1772
- * Apply grouping on data set
1773
- * Clear grouping from source
1774
- * If source came from other plugin
1775
- */
1776
- onDataSet(data) {
1909
+ getComparer(column, order) {
1777
1910
  var _a, _b;
1778
- let preservedExpanded = {};
1779
- if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.preserveGroupingOnUpdate) !== false) {
1780
- let { prevExpanded } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
1781
- preservedExpanded = prevExpanded;
1911
+ const cellCmp = ((_a = column === null || column === void 0 ? void 0 : column.cellCompare) === null || _a === void 0 ? void 0 : _a.bind({ order })) || ((_b = this.defaultCellCompare) === null || _b === void 0 ? void 0 : _b.bind({ column, order }));
1912
+ if (order == 'asc') {
1913
+ return cellCmp;
1782
1914
  }
1783
- const source = data.source.filter(s => !column_service.isGrouping(s));
1784
- const options = Object.assign(Object.assign({}, (this.revogrid.grouping || {})), { prevExpanded: preservedExpanded });
1785
- const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup, } = column_service.gatherGrouping(source, ((_b = this.options) === null || _b === void 0 ? void 0 : _b.props) || [], options);
1786
- data.source = sourceWithGroups;
1787
- this.providers.data.setGrouping({ depth });
1788
- this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexMap);
1915
+ if (order == 'desc') {
1916
+ return this.descCellCompare(cellCmp);
1917
+ }
1918
+ return undefined;
1789
1919
  }
1790
1920
  /**
1791
- * Externam call to apply grouping. Called by revogrid when prop changed.
1921
+ * Apply sorting to data on header click
1922
+ * If additive - add to existing sorting, multiple columns can be sorted
1792
1923
  */
1793
- setGrouping(options) {
1924
+ headerclick(column, index, additive) {
1794
1925
  var _a, _b;
1795
- // unsubscribe from all events when group applied
1796
- this.clearSubscriptions();
1797
- this.options = options;
1798
- // clear props, no grouping exists
1799
- if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
1800
- this.clearGrouping();
1926
+ let order = this.getNextOrder(column.order);
1927
+ const beforeEvent = this.emit('beforesorting', { column, order, additive });
1928
+ if (beforeEvent.defaultPrevented) {
1801
1929
  return;
1802
1930
  }
1803
- // props exist and source inited
1804
- const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
1805
- if (source.length) {
1806
- this.doSourceUpdate(Object.assign({}, options));
1931
+ order = beforeEvent.detail.order;
1932
+ const newCol = this.providers.column.updateColumnSorting(beforeEvent.detail.column, index, order, additive);
1933
+ // apply sort data
1934
+ const beforeApplyEvent = this.emit('beforesortingapply', {
1935
+ column: newCol,
1936
+ order,
1937
+ additive,
1938
+ });
1939
+ if (beforeApplyEvent.defaultPrevented) {
1940
+ return;
1807
1941
  }
1808
- // props exist and columns inited
1809
- for (let t of columnTypes) {
1810
- if (this.setColumnGrouping(this.providers.column.getColumns(t))) {
1811
- this.providers.column.refreshByType(t);
1812
- break;
1942
+ const cmp = this.getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
1943
+ if (beforeApplyEvent.detail.additive && this.sorting) {
1944
+ const sorting = {};
1945
+ const sortingFunc = {};
1946
+ this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
1947
+ // extend sorting function with new sorting for multiple columns sorting
1948
+ this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
1949
+ if (column.prop in sorting && size(sorting) > 1 && order === undefined) {
1950
+ delete sorting[column.prop];
1951
+ delete sortingFunc[column.prop];
1952
+ }
1953
+ else {
1954
+ sorting[column.prop] = order;
1955
+ sortingFunc[column.prop] = cmp;
1813
1956
  }
1814
1957
  }
1815
- // if has any grouping subscribe to events again
1816
- this.subscribe();
1817
- }
1818
- // clear grouping
1819
- clearGrouping() {
1820
- // clear columns
1821
- columnTypes.forEach(t => {
1822
- const cols = this.providers.column.getColumns(t);
1823
- let deleted = false;
1824
- cols.forEach(c => {
1825
- if (column_service.isGroupingColumn(c)) {
1826
- delete c[column_service.PSEUDO_GROUP_COLUMN];
1827
- deleted = true;
1828
- }
1829
- });
1830
- // if column store had grouping clear and refresh
1831
- if (deleted) {
1832
- this.providers.column.refreshByType(t);
1958
+ else {
1959
+ if (order) {
1960
+ // reset sorting
1961
+ this.sorting = { [column.prop]: order };
1962
+ this.sortingFunc = { [column.prop]: cmp };
1963
+ }
1964
+ else {
1965
+ (_a = this.sorting) === null || _a === void 0 ? true : delete _a[column.prop];
1966
+ (_b = this.sortingFunc) === null || _b === void 0 ? true : delete _b[column.prop];
1833
1967
  }
1834
- });
1835
- // clear rows
1836
- const { source, oldNewIndexes } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
1837
- this.providers.data.setData(source, column_service.GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, undefined, true);
1838
- this.updateTrimmed(undefined, undefined, oldNewIndexes);
1839
- }
1840
- updateTrimmed(trimmedGroup = {}, _childrenByGroup = {}, firstLevelMap = {}, secondLevelMap) {
1841
- // map previously trimmed data
1842
- const trimemedOptionsToUpgrade = processDoubleConversionTrimmed(this.getStore().get('trimmed'), firstLevelMap, secondLevelMap);
1843
- for (let type in trimemedOptionsToUpgrade) {
1844
- this.revogrid.addTrimmed(trimemedOptionsToUpgrade[type], type);
1845
1968
  }
1846
- // const emptyGroups = this.filterOutEmptyGroups(trimemedOptionsToUpgrade, childrenByGroup);
1847
- // setup trimmed data for grouping
1848
- this.revogrid.addTrimmed(Object.assign({}, trimmedGroup), TRIMMED_GROUPING);
1849
- }
1850
- }
1851
-
1852
- const COLUMN_DRAG_CLASS = 'column-drag-start';
1853
- class ColumnOrderHandler {
1854
- constructor() {
1855
- this.offset = 0;
1969
+ this.startSorting(this.sorting, this.sortingFunc);
1856
1970
  }
1857
- renderAutoscroll(_, parent) {
1858
- if (!parent) {
1859
- return;
1971
+ /**
1972
+ * Sort items by sorting function
1973
+ * @requires proxyItems applied to row store
1974
+ * @requires source applied to row store
1975
+ *
1976
+ * @param sorting - per column sorting
1977
+ * @param data - this.stores['rgRow'].store.get('source')
1978
+ */
1979
+ sort(sorting, sortingFunc, types = rowTypes, ignoreViewportUpdate = false) {
1980
+ // if no sorting - reset
1981
+ if (!Object.keys(sorting || {}).length) {
1982
+ for (let type of types) {
1983
+ const storeService = this.providers.data.stores[type];
1984
+ // row data
1985
+ const source = storeService.store.get('source');
1986
+ // row indexes
1987
+ const proxyItems = storeService.store.get('proxyItems');
1988
+ // row indexes
1989
+ const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
1990
+ this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
1991
+ storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
1992
+ }
1860
1993
  }
1861
- this.autoscrollEl = document.createElement('div');
1862
- this.autoscrollEl.classList.add('drag-auto-scroll-y');
1863
- parent.appendChild(this.autoscrollEl);
1864
- }
1865
- autoscroll(pos, dataContainerSize, direction = 'translateX') {
1866
- if (!this.autoscrollEl) {
1867
- return;
1994
+ else {
1995
+ for (let type of types) {
1996
+ const storeService = this.providers.data.stores[type];
1997
+ // row data
1998
+ const source = storeService.store.get('source');
1999
+ // row indexes
2000
+ const proxyItems = storeService.store.get('proxyItems');
2001
+ const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
2002
+ // take row indexes before trim applied and proxy items
2003
+ const prevItems = storeService.store.get('items');
2004
+ storeService.setData({
2005
+ proxyItems: newItemsOrder,
2006
+ source: [...source],
2007
+ });
2008
+ // take currently visible row indexes
2009
+ const newItems = storeService.store.get('items');
2010
+ if (!ignoreViewportUpdate) {
2011
+ this.providers.dimension
2012
+ .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
2013
+ }
2014
+ }
1868
2015
  }
1869
- const helperOffset = 10;
1870
- // calculate current y position inside of the grid active holder
1871
- // 3 - size of element + border
1872
- const maxScroll = Math.min(pos + helperOffset, dataContainerSize - 3);
1873
- this.autoscrollEl.style.transform = `${direction}(${maxScroll}px)`;
1874
- this.autoscrollEl.scrollIntoView({
1875
- block: 'nearest',
1876
- inline: 'nearest',
1877
- });
2016
+ this.emit('aftersortingapply');
1878
2017
  }
1879
- start(e, { dataEl, gridRect, scrollEl, gridEl }, dir = 'left') {
1880
- gridEl.classList.add(COLUMN_DRAG_CLASS);
1881
- const scrollContainerRect = scrollEl.getBoundingClientRect();
1882
- if (scrollContainerRect) {
1883
- this.offset = scrollContainerRect[dir] - gridRect[dir];
1884
- }
1885
- this.renderAutoscroll(e, dataEl);
2018
+ defaultCellCompare(prop, a, b) {
2019
+ const aRaw = this.column ? column_service.getCellRaw(a, this.column) : a === null || a === void 0 ? void 0 : a[prop];
2020
+ const bRaw = this.column ? column_service.getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
2021
+ const av = aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
2022
+ const bv = bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
2023
+ return av == bv ? 0 : av > bv ? 1 : -1;
1886
2024
  }
1887
- stop(gridEl) {
1888
- var _a;
1889
- gridEl.classList.remove(COLUMN_DRAG_CLASS);
1890
- if (this.element) {
1891
- this.element.hidden = true;
1892
- }
1893
- this.offset = 0;
1894
- (_a = this.autoscrollEl) === null || _a === void 0 ? void 0 : _a.remove();
1895
- this.autoscrollEl = undefined;
2025
+ descCellCompare(cmp) {
2026
+ return (prop, a, b) => {
2027
+ return -1 * cmp(prop, a, b);
2028
+ };
1896
2029
  }
1897
- showHandler(pos, size, direction = 'translateX') {
1898
- if (!this.element) {
1899
- return;
1900
- }
1901
- // do not allow overcross top of the scrollable area, header excluded
1902
- if (this.offset) {
1903
- pos = Math.max(pos, this.offset);
2030
+ getNextOrder(currentOrder) {
2031
+ switch (currentOrder) {
2032
+ case undefined:
2033
+ return 'asc';
2034
+ case 'asc':
2035
+ return 'desc';
2036
+ case 'desc':
2037
+ return undefined;
1904
2038
  }
1905
- // can not be bigger then grid end
1906
- pos = Math.min(pos, size);
1907
- this.element.style.transform = `${direction}(${pos}px)`;
1908
- this.element.hidden = false;
1909
- }
1910
- render() {
1911
- const el = this.element = document.createElement('div');
1912
- el.classList.add('drag-position-y');
1913
- el.hidden = true;
1914
- return el;
1915
2039
  }
1916
2040
  }
1917
2041
 
1918
- /**
1919
- * Plugin for column manual move
1920
- */
1921
- const COLUMN_CLICK = headerCellRenderer.ON_COLUMN_CLICK;
1922
- const MOVE = 'columndragmousemove';
1923
- const DRAG_END = 'columndragend';
1924
- const BEFORE_DRAG_END = 'beforecolumndragend';
1925
- // use this event subscription to drop D&D for particular columns
1926
- const DRAG_START = 'columndragstart';
1927
- class ColumnMovePlugin extends BasePlugin {
2042
+ class GroupingRowPlugin extends BasePlugin {
2043
+ getStore(type = column_service.GROUPING_ROW_TYPE) {
2044
+ return this.providers.data.stores[type].store;
2045
+ }
1928
2046
  constructor(revogrid, providers) {
1929
2047
  super(revogrid, providers);
1930
2048
  this.revogrid = revogrid;
1931
2049
  this.providers = providers;
1932
- this.moveFunc = debounce.debounce((e) => this.doMove(e), 5);
1933
- this.staticDragData = null;
1934
- this.dragData = null;
1935
- this.localSubscriptions = {};
1936
- this.orderUi = new ColumnOrderHandler();
1937
- revogrid.appendChild(this.orderUi.render());
1938
- revogrid.classList.add('column-draggable');
1939
- // Register events
1940
- this.localSubscriptions['mouseleave'] = {
1941
- target: document,
1942
- callback: (e) => this.onMouseOut(e),
1943
- };
1944
- this.localSubscriptions['mouseup'] = {
1945
- target: document,
1946
- callback: (e) => this.onMouseUp(e),
1947
- };
1948
- this.localSubscriptions['mousemove'] = {
1949
- target: document,
1950
- callback: (e) => this.move(e),
1951
- };
1952
- this.addEventListener(COLUMN_CLICK, ({ detail }) => this.dragStart(detail));
1953
- }
1954
- dragStart({ event, data }) {
1955
- if (event.defaultPrevented) {
1956
- return;
1957
- }
1958
- const { defaultPrevented } = headerCellRenderer.dispatch(this.revogrid, DRAG_START, data);
1959
- // check if allowed to drag particulat column
1960
- if (defaultPrevented) {
1961
- return;
1962
- }
1963
- this.clearOrder();
1964
- const { mouseleave, mouseup, mousemove } = this.localSubscriptions;
1965
- mouseleave.target.addEventListener('mouseleave', mouseleave.callback);
1966
- mouseup.target.addEventListener('mouseup', mouseup.callback);
1967
- const dataEl = event.target.closest('revogr-header');
1968
- const scrollEl = event.target.closest('revogr-viewport-scroll');
1969
- if (!dataEl || !scrollEl) {
1970
- return;
1971
- }
1972
- // no grouping drag and no row header column drag
1973
- if (column_service.isColGrouping(data) || data.providers.type === 'rowHeaders') {
1974
- return;
1975
- }
1976
- const cols = this.getDimension(data.pin || 'rgCol');
1977
- const gridRect = this.revogrid.getBoundingClientRect();
1978
- const elRect = dataEl.getBoundingClientRect();
1979
- const startItem = dimension_helpers.getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left));
1980
- this.staticDragData = {
1981
- startPos: event.x,
1982
- startItem,
1983
- data,
1984
- dataEl,
1985
- scrollEl,
1986
- gridEl: this.revogrid,
1987
- cols,
1988
- };
1989
- this.dragData = this.getData(this.staticDragData);
1990
- mousemove.target.addEventListener('mousemove', mousemove.callback);
1991
- this.orderUi.start(event, Object.assign(Object.assign({}, this.dragData), this.staticDragData));
1992
2050
  }
1993
- doMove(e) {
1994
- if (!this.staticDragData) {
1995
- return;
1996
- }
1997
- const dragData = (this.dragData = this.getData(this.staticDragData));
1998
- if (!dragData) {
1999
- return;
2000
- }
2001
- const start = this.staticDragData.startPos;
2002
- if (Math.abs(start - e.x) > 10) {
2003
- const x = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2004
- const rgCol = dimension_helpers.getItemByPosition(this.staticDragData.cols, x);
2005
- this.orderUi.autoscroll(x, dragData.elRect.width);
2006
- // prevent position change if out of bounds
2007
- if (rgCol.itemIndex >= this.staticDragData.cols.count) {
2008
- return;
2009
- }
2010
- this.orderUi.showHandler(rgCol.end + dragData.scrollOffset, dragData.gridRect.width);
2051
+ // befoce cell focus
2052
+ onFocus(e) {
2053
+ if (column_service.isGrouping(e.detail.model)) {
2054
+ e.preventDefault();
2011
2055
  }
2012
2056
  }
2013
- move(e) {
2014
- headerCellRenderer.dispatch(this.revogrid, MOVE, e);
2015
- // then do move
2016
- this.moveFunc(e);
2017
- }
2018
- onMouseOut(_) {
2019
- this.clearOrder();
2020
- }
2021
- onMouseUp(e) {
2022
- // apply new positions
2023
- if (this.dragData && this.staticDragData) {
2024
- let relativePos = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2025
- if (relativePos < 0) {
2026
- relativePos = 0;
2027
- }
2028
- const newPosition = dimension_helpers.getItemByPosition(this.staticDragData.cols, relativePos);
2029
- const store = this.providers.column.stores[this.dragData.type].store;
2030
- const newItems = [...store.get('items')];
2031
- // prevent position change if needed
2032
- const { defaultPrevented: stopDrag } = headerCellRenderer.dispatch(this.revogrid, BEFORE_DRAG_END, Object.assign(Object.assign({}, this.staticDragData), { startPosition: this.staticDragData.startItem, newPosition, newItem: store.get('source')[newItems[this.staticDragData.startItem.itemIndex]] }));
2033
- if (!stopDrag) {
2034
- const prevItems = [...newItems];
2035
- // todo: if move item out of group remove item from group
2036
- const toMove = newItems.splice(this.staticDragData.startItem.itemIndex, 1);
2037
- newItems.splice(newPosition.itemIndex, 0, ...toMove);
2038
- store.set('items', newItems);
2039
- this.providers.dimension.updateSizesPositionByNewDataIndexes(this.dragData.type, newItems, prevItems);
2057
+ // expand event triggered
2058
+ onExpand({ virtualIndex }) {
2059
+ const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
2060
+ let newTrimmed = this.getStore().get('trimmed')[TRIMMED_GROUPING];
2061
+ let i = dimension_helpers.getPhysical(this.getStore(), virtualIndex);
2062
+ const isExpanded = column_service.getExpanded(source[i]);
2063
+ if (!isExpanded) {
2064
+ const { trimmed, items } = doExpand(virtualIndex, source, this.getStore().get('items'));
2065
+ newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
2066
+ if (items) {
2067
+ dimension_helpers.setItems(this.getStore(), items);
2040
2068
  }
2041
- headerCellRenderer.dispatch(this.revogrid, DRAG_END, this.dragData);
2042
2069
  }
2043
- this.clearOrder();
2044
- }
2045
- clearLocalSubscriptions() {
2046
- forEach(this.localSubscriptions, ({ target, callback }, key) => target.removeEventListener(key, callback));
2047
- }
2048
- clearOrder() {
2049
- this.staticDragData = null;
2050
- this.dragData = null;
2051
- this.clearLocalSubscriptions();
2052
- this.orderUi.stop(this.revogrid);
2053
- }
2054
- /**
2055
- * Clearing subscription
2056
- */
2057
- clearSubscriptions() {
2058
- super.clearSubscriptions();
2059
- this.clearLocalSubscriptions();
2070
+ else {
2071
+ const { trimmed } = doCollapse(i, source);
2072
+ newTrimmed = Object.assign(Object.assign({}, newTrimmed), trimmed);
2073
+ this.revogrid.clearFocus();
2074
+ }
2075
+ this.getStore().set('source', source);
2076
+ this.revogrid.addTrimmed(newTrimmed, TRIMMED_GROUPING);
2060
2077
  }
2061
- getData({ gridEl, dataEl, data, }) {
2062
- const gridRect = gridEl.getBoundingClientRect();
2063
- const elRect = dataEl.getBoundingClientRect();
2064
- const scrollOffset = elRect.left - gridRect.left;
2065
- return {
2066
- elRect,
2067
- gridRect,
2068
- type: data.pin || 'rgCol',
2069
- scrollOffset,
2070
- };
2078
+ setColumnGrouping(cols) {
2079
+ // if 0 column as holder
2080
+ if (cols === null || cols === void 0 ? void 0 : cols.length) {
2081
+ cols[0][column_service.PSEUDO_GROUP_COLUMN] = true;
2082
+ return true;
2083
+ }
2084
+ return false;
2071
2085
  }
2072
- getDimension(type) {
2073
- return this.providers.dimension.stores[type].getCurrentState();
2086
+ setColumns({ columns }) {
2087
+ for (let type of columnTypes) {
2088
+ if (this.setColumnGrouping(columns[type])) {
2089
+ break;
2090
+ }
2091
+ }
2074
2092
  }
2075
- }
2076
- function getLeftRelative(absoluteX, gridPos, offset) {
2077
- return absoluteX - gridPos - offset;
2078
- }
2079
-
2080
- /** `Object#toString` result references. */
2081
- var stringTag = '[object String]';
2082
-
2083
- /**
2084
- * Checks if `value` is classified as a `String` primitive or object.
2085
- *
2086
- * @static
2087
- * @since 0.1.0
2088
- * @memberOf _
2089
- * @category Lang
2090
- * @param {*} value The value to check.
2091
- * @returns {boolean} Returns `true` if `value` is a string, else `false`.
2092
- * @example
2093
- *
2094
- * _.isString('abc');
2095
- * // => true
2096
- *
2097
- * _.isString(1);
2098
- * // => false
2099
- */
2100
- function isString(value) {
2101
- return typeof value == 'string' ||
2102
- (!dimension_helpers.isArray(value) && debounce.isObjectLike(value) && debounce.baseGetTag(value) == stringTag);
2103
- }
2104
-
2105
- /**
2106
- * Gets the size of an ASCII `string`.
2107
- *
2108
- * @private
2109
- * @param {string} string The string inspect.
2110
- * @returns {number} Returns the string size.
2111
- */
2112
- var asciiSize = dimension_helpers.baseProperty('length');
2113
-
2114
- const asciiSize$1 = asciiSize;
2115
-
2116
- /** Used to compose unicode character classes. */
2117
- var rsAstralRange$1 = '\\ud800-\\udfff',
2118
- rsComboMarksRange$1 = '\\u0300-\\u036f',
2119
- reComboHalfMarksRange$1 = '\\ufe20-\\ufe2f',
2120
- rsComboSymbolsRange$1 = '\\u20d0-\\u20ff',
2121
- rsComboRange$1 = rsComboMarksRange$1 + reComboHalfMarksRange$1 + rsComboSymbolsRange$1,
2122
- rsVarRange$1 = '\\ufe0e\\ufe0f';
2123
-
2124
- /** Used to compose unicode capture groups. */
2125
- var rsZWJ$1 = '\\u200d';
2126
-
2127
- /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
2128
- var reHasUnicode = RegExp('[' + rsZWJ$1 + rsAstralRange$1 + rsComboRange$1 + rsVarRange$1 + ']');
2129
-
2130
- /**
2131
- * Checks if `string` contains Unicode symbols.
2132
- *
2133
- * @private
2134
- * @param {string} string The string to inspect.
2135
- * @returns {boolean} Returns `true` if a symbol is found, else `false`.
2136
- */
2137
- function hasUnicode(string) {
2138
- return reHasUnicode.test(string);
2139
- }
2140
-
2141
- /** Used to compose unicode character classes. */
2142
- var rsAstralRange = '\\ud800-\\udfff',
2143
- rsComboMarksRange = '\\u0300-\\u036f',
2144
- reComboHalfMarksRange = '\\ufe20-\\ufe2f',
2145
- rsComboSymbolsRange = '\\u20d0-\\u20ff',
2146
- rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
2147
- rsVarRange = '\\ufe0e\\ufe0f';
2148
-
2149
- /** Used to compose unicode capture groups. */
2150
- var rsAstral = '[' + rsAstralRange + ']',
2151
- rsCombo = '[' + rsComboRange + ']',
2152
- rsFitz = '\\ud83c[\\udffb-\\udfff]',
2153
- rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
2154
- rsNonAstral = '[^' + rsAstralRange + ']',
2155
- rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
2156
- rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
2157
- rsZWJ = '\\u200d';
2158
-
2159
- /** Used to compose unicode regexes. */
2160
- var reOptMod = rsModifier + '?',
2161
- rsOptVar = '[' + rsVarRange + ']?',
2162
- rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
2163
- rsSeq = rsOptVar + reOptMod + rsOptJoin,
2164
- rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
2165
-
2166
- /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
2167
- var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
2168
-
2169
- /**
2170
- * Gets the size of a Unicode `string`.
2171
- *
2172
- * @private
2173
- * @param {string} string The string inspect.
2174
- * @returns {number} Returns the string size.
2175
- */
2176
- function unicodeSize(string) {
2177
- var result = reUnicode.lastIndex = 0;
2178
- while (reUnicode.test(string)) {
2179
- ++result;
2180
- }
2181
- return result;
2182
- }
2183
-
2184
- /**
2185
- * Gets the number of symbols in `string`.
2186
- *
2187
- * @private
2188
- * @param {string} string The string to inspect.
2189
- * @returns {number} Returns the string size.
2190
- */
2191
- function stringSize(string) {
2192
- return hasUnicode(string)
2193
- ? unicodeSize(string)
2194
- : asciiSize$1(string);
2195
- }
2196
-
2197
- /** `Object#toString` result references. */
2198
- var mapTag = '[object Map]',
2199
- setTag = '[object Set]';
2200
-
2201
- /**
2202
- * Gets the size of `collection` by returning its length for array-like
2203
- * values or the number of own enumerable string keyed properties for objects.
2204
- *
2205
- * @static
2206
- * @memberOf _
2207
- * @since 0.1.0
2208
- * @category Collection
2209
- * @param {Array|Object|string} collection The collection to inspect.
2210
- * @returns {number} Returns the collection size.
2211
- * @example
2212
- *
2213
- * _.size([1, 2, 3]);
2214
- * // => 3
2215
- *
2216
- * _.size({ 'a': 1, 'b': 2 });
2217
- * // => 2
2218
- *
2219
- * _.size('pebbles');
2220
- * // => 7
2221
- */
2222
- function size(collection) {
2223
- if (collection == null) {
2224
- return 0;
2225
- }
2226
- if (dimension_helpers.isArrayLike(collection)) {
2227
- return isString(collection) ? stringSize(collection) : collection.length;
2228
- }
2229
- var tag = dimension_helpers.getTag(collection);
2230
- if (tag == mapTag || tag == setTag) {
2231
- return collection.size;
2232
- }
2233
- return dimension_helpers.baseKeys(collection).length;
2234
- }
2235
-
2236
- function sortIndexByItems(indexes, source, sortingFunc = {}) {
2237
- // if no sorting - return unsorted indexes
2238
- if (Object.entries(sortingFunc).length === 0) {
2239
- // Unsorted indexes
2240
- return [...Array(indexes.length).keys()];
2093
+ // evaluate drag between groups
2094
+ onDrag(e) {
2095
+ const { from, to } = e.detail;
2096
+ const isDown = to - from >= 0;
2097
+ const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
2098
+ const items = this.getStore().get('items');
2099
+ let i = isDown ? from : to;
2100
+ const end = isDown ? to : from;
2101
+ for (; i < end; i++) {
2102
+ const model = source[items[i]];
2103
+ const isGroup = column_service.isGrouping(model);
2104
+ if (isGroup) {
2105
+ e.preventDefault();
2106
+ return;
2107
+ }
2108
+ }
2241
2109
  }
2242
- //
2243
- /**
2244
- * go through all indexes and align in new order
2245
- * performs a multi-level sorting by applying multiple comparison functions to determine the order of the items based on different properties.
2246
- */
2247
- return indexes.sort((a, b) => {
2248
- for (const [prop, cmp] of Object.entries(sortingFunc)) {
2249
- const itemA = source[a];
2250
- const itemB = source[b];
2251
- /**
2252
- * If the comparison function returns a non-zero value (sorted), it means that the items should be sorted based on the given property. In such a case, the function immediately returns the sorted value, indicating the order in which the items should be arranged.
2253
- * If none of the comparison functions result in a non-zero value, indicating that the items are equal or should remain in the same order, the function eventually returns 0.
2254
- */
2255
- const sorted = cmp === null || cmp === void 0 ? void 0 : cmp(prop, itemA, itemB);
2256
- if (sorted) {
2257
- return sorted;
2110
+ beforeTrimmedApply(trimmed, type) {
2111
+ /** Before filter apply remove grouping filtering */
2112
+ if (type === FILTER_TRIMMED_TYPE) {
2113
+ const source = this.getStore().get('source');
2114
+ for (let index in trimmed) {
2115
+ if (trimmed[index] && column_service.isGrouping(source[index])) {
2116
+ trimmed[index] = false;
2117
+ }
2258
2118
  }
2259
2119
  }
2260
- return 0;
2261
- });
2262
- }
2263
-
2264
- /**
2265
- * Lifecycle
2266
- * 1. @event `beforesorting` - Triggered when sorting just starts. Nothing has happened yet. This can be triggered from a column or from the source. If the type is from rows, the column will be undefined.
2267
- * 2. @method `updateColumnSorting` - Updates the column sorting icon on the grid and the column itself, but the data remains untouched.
2268
- * 3. @event `beforesortingapply` - Triggered before the sorting data is applied to the data source. You can prevent this event, and the data will not be sorted. This event is only called from a column sorting click.
2269
- * 4. @event `aftersortingapply` - Triggered after sorting has been applied and completed. This event occurs for both row and column sorting.
2270
- *
2271
- * Note: If you prevent an event, it will not proceed to the subsequent steps.
2272
- */
2273
- class SortingPlugin extends BasePlugin {
2274
- runSorting(order, comparison, ignoreViewportUpdate) {
2275
- var _a;
2276
- this.sort(order, comparison, undefined, ignoreViewportUpdate);
2277
- (_a = this.sortingPromise) === null || _a === void 0 ? void 0 : _a.call(this);
2278
- this.sortingPromise = null;
2279
2120
  }
2280
- constructor(revogrid, providers) {
2281
- super(revogrid, providers);
2282
- this.revogrid = revogrid;
2283
- this.sortingPromise = null;
2284
- this.postponeSort = debounce.debounce((order, comparison, ignoreViewportUpdate) => this.runSorting(order, comparison, ignoreViewportUpdate), 50);
2285
- this.addEventListener('beforeanysource', ({ detail: { type }, }) => {
2286
- // if sorting was provided - sort data
2287
- if (!!this.sorting && this.sortingFunc) {
2288
- const beforeEvent = this.emit('beforesorting', { type });
2289
- if (beforeEvent.defaultPrevented) {
2290
- return;
2291
- }
2292
- this.startSorting(this.sorting, this.sortingFunc);
2121
+ isSortingRunning() {
2122
+ const sortingPlugin = this.providers.plugins.getByClass(SortingPlugin);
2123
+ return !!(sortingPlugin === null || sortingPlugin === void 0 ? void 0 : sortingPlugin.sortingPromise);
2124
+ }
2125
+ // subscribe to grid events to process them accordingly
2126
+ subscribe() {
2127
+ /** if grouping present and new data source arrived */
2128
+ this.addEventListener('beforesourceset', ({ detail }) => {
2129
+ var _a, _b, _c;
2130
+ if (!(((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length) && ((_c = detail === null || detail === void 0 ? void 0 : detail.source) === null || _c === void 0 ? void 0 : _c.length))) {
2131
+ return;
2293
2132
  }
2294
- });
2295
- this.addEventListener('aftercolumnsset', ({ detail: { order }, }) => {
2296
- const columns = this.providers.column.getColumns();
2297
- const sortingFunc = {};
2298
- for (let prop in order) {
2299
- const cmp = this.getComparer(column_service.getColumnByProp(columns, prop), order[prop]);
2300
- sortingFunc[prop] = cmp;
2133
+ // if sorting is running don't apply grouping, wait for sorting, then it'll apply in @aftersortingapply
2134
+ if (this.isSortingRunning()) {
2135
+ return;
2301
2136
  }
2302
- this.startSorting(order, sortingFunc, true);
2137
+ this.onDataSet(detail);
2303
2138
  });
2304
- this.addEventListener('beforeheaderclick', (e) => {
2139
+ this.addEventListener('beforecolumnsset', ({ detail }) => {
2140
+ this.setColumns(detail);
2141
+ });
2142
+ /**
2143
+ * filter applied need to clear grouping and apply again
2144
+ * based on new results can be new grouping
2145
+ */
2146
+ this.addEventListener('beforetrimmed', ({ detail: { trimmed, trimmedType } }) => this.beforeTrimmedApply(trimmed, trimmedType));
2147
+ /**
2148
+ * sorting applied need to clear grouping and apply again
2149
+ * based on new results whole grouping order will changed
2150
+ */
2151
+ this.addEventListener('aftersortingapply', () => {
2305
2152
  var _a, _b;
2306
- if (e.defaultPrevented) {
2153
+ if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
2307
2154
  return;
2308
2155
  }
2309
- if (!e.detail.column.sortable) {
2310
- return;
2156
+ this.doSourceUpdate(Object.assign({}, this.options));
2157
+ });
2158
+ /**
2159
+ * Apply logic for focus inside of grouping
2160
+ * We can't focus on grouping rows, navigation only inside of groups for now
2161
+ */
2162
+ this.addEventListener('beforecellfocus', e => this.onFocus(e));
2163
+ /**
2164
+ * Prevent rgRow drag outside the group
2165
+ */
2166
+ this.addEventListener('roworderchanged', e => this.onDrag(e));
2167
+ /**
2168
+ * When grouping expand icon was clicked
2169
+ */
2170
+ this.addEventListener('groupexpandclick', e => this.onExpand(e.detail));
2171
+ }
2172
+ /**
2173
+ * Starts global source update with group clearing and applying new one
2174
+ * Initiated when need to reapply grouping
2175
+ */
2176
+ doSourceUpdate(options) {
2177
+ var _a;
2178
+ /**
2179
+ * Get source without grouping
2180
+ * @param newOldIndexMap - provides us mapping with new indexes vs old indexes, we would use it for trimmed mapping
2181
+ */
2182
+ const { source, prevExpanded, oldNewIndexes } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
2183
+ const expanded = Object.assign({ prevExpanded }, options);
2184
+ /**
2185
+ * Group again
2186
+ * @param oldNewIndexMap - provides us mapping with new indexes vs old indexes
2187
+ */
2188
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup, } = column_service.gatherGrouping(source, ((_a = this.options) === null || _a === void 0 ? void 0 : _a.props) || [], expanded);
2189
+ const customRenderer = options === null || options === void 0 ? void 0 : options.groupLabelTemplate;
2190
+ // setup source
2191
+ this.providers.data.setData(sourceWithGroups, column_service.GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, { depth, customRenderer }, true);
2192
+ this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexes !== null && oldNewIndexes !== void 0 ? oldNewIndexes : {}, oldNewIndexMap);
2193
+ }
2194
+ /**
2195
+ * Apply grouping on data set
2196
+ * Clear grouping from source
2197
+ * If source came from other plugin
2198
+ */
2199
+ onDataSet(data) {
2200
+ var _a, _b;
2201
+ let preservedExpanded = {};
2202
+ if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.preserveGroupingOnUpdate) !== false) {
2203
+ let { prevExpanded } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
2204
+ preservedExpanded = prevExpanded;
2205
+ }
2206
+ const source = data.source.filter(s => !column_service.isGrouping(s));
2207
+ const options = Object.assign(Object.assign({}, (this.revogrid.grouping || {})), { prevExpanded: preservedExpanded });
2208
+ const { sourceWithGroups, depth, trimmed, oldNewIndexMap, childrenByGroup, } = column_service.gatherGrouping(source, ((_b = this.options) === null || _b === void 0 ? void 0 : _b.props) || [], options);
2209
+ data.source = sourceWithGroups;
2210
+ this.providers.data.setGrouping({ depth });
2211
+ this.updateTrimmed(trimmed, childrenByGroup, oldNewIndexMap);
2212
+ }
2213
+ /**
2214
+ * Externam call to apply grouping. Called by revogrid when prop changed.
2215
+ */
2216
+ setGrouping(options) {
2217
+ var _a, _b;
2218
+ // unsubscribe from all events when group applied
2219
+ this.clearSubscriptions();
2220
+ this.options = options;
2221
+ // clear props, no grouping exists
2222
+ if (!((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.length)) {
2223
+ this.clearGrouping();
2224
+ return;
2225
+ }
2226
+ // props exist and source inited
2227
+ const { source } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'));
2228
+ if (source.length) {
2229
+ this.doSourceUpdate(Object.assign({}, options));
2230
+ }
2231
+ // props exist and columns inited
2232
+ for (let t of columnTypes) {
2233
+ if (this.setColumnGrouping(this.providers.column.getColumns(t))) {
2234
+ this.providers.column.refreshByType(t);
2235
+ break;
2311
2236
  }
2312
- this.headerclick(e.detail.column, e.detail.index, (_b = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.originalEvent) === null || _b === void 0 ? void 0 : _b.shiftKey);
2237
+ }
2238
+ // if has any grouping subscribe to events again
2239
+ this.subscribe();
2240
+ }
2241
+ // clear grouping
2242
+ clearGrouping() {
2243
+ // clear columns
2244
+ columnTypes.forEach(t => {
2245
+ const cols = this.providers.column.getColumns(t);
2246
+ let deleted = false;
2247
+ cols.forEach(c => {
2248
+ if (column_service.isGroupingColumn(c)) {
2249
+ delete c[column_service.PSEUDO_GROUP_COLUMN];
2250
+ deleted = true;
2251
+ }
2252
+ });
2253
+ // if column store had grouping clear and refresh
2254
+ if (deleted) {
2255
+ this.providers.column.refreshByType(t);
2256
+ }
2257
+ });
2258
+ // clear rows
2259
+ const { source, oldNewIndexes } = column_service.getSource(this.getStore().get('source'), this.getStore().get('proxyItems'), true);
2260
+ this.providers.data.setData(source, column_service.GROUPING_ROW_TYPE, this.revogrid.disableVirtualY, undefined, true);
2261
+ this.updateTrimmed(undefined, undefined, oldNewIndexes);
2262
+ }
2263
+ updateTrimmed(trimmedGroup = {}, _childrenByGroup = {}, firstLevelMap = {}, secondLevelMap) {
2264
+ // map previously trimmed data
2265
+ const trimemedOptionsToUpgrade = processDoubleConversionTrimmed(this.getStore().get('trimmed'), firstLevelMap, secondLevelMap);
2266
+ for (let type in trimemedOptionsToUpgrade) {
2267
+ this.revogrid.addTrimmed(trimemedOptionsToUpgrade[type], type);
2268
+ }
2269
+ // const emptyGroups = this.filterOutEmptyGroups(trimemedOptionsToUpgrade, childrenByGroup);
2270
+ // setup trimmed data for grouping
2271
+ this.revogrid.addTrimmed(Object.assign({}, trimmedGroup), TRIMMED_GROUPING);
2272
+ }
2273
+ }
2274
+
2275
+ const COLUMN_DRAG_CLASS = 'column-drag-start';
2276
+ class ColumnOrderHandler {
2277
+ constructor() {
2278
+ this.offset = 0;
2279
+ }
2280
+ renderAutoscroll(_, parent) {
2281
+ if (!parent) {
2282
+ return;
2283
+ }
2284
+ this.autoscrollEl = document.createElement('div');
2285
+ this.autoscrollEl.classList.add('drag-auto-scroll-y');
2286
+ parent.appendChild(this.autoscrollEl);
2287
+ }
2288
+ autoscroll(pos, dataContainerSize, direction = 'translateX') {
2289
+ if (!this.autoscrollEl) {
2290
+ return;
2291
+ }
2292
+ const helperOffset = 10;
2293
+ // calculate current y position inside of the grid active holder
2294
+ // 3 - size of element + border
2295
+ const maxScroll = Math.min(pos + helperOffset, dataContainerSize - 3);
2296
+ this.autoscrollEl.style.transform = `${direction}(${maxScroll}px)`;
2297
+ this.autoscrollEl.scrollIntoView({
2298
+ block: 'nearest',
2299
+ inline: 'nearest',
2313
2300
  });
2314
2301
  }
2315
- startSorting(order, sortingFunc, ignoreViewportUpdate) {
2316
- if (!this.sortingPromise) {
2317
- // add job before render
2318
- this.revogrid.jobsBeforeRender.push(new Promise(resolve => {
2319
- this.sortingPromise = resolve;
2320
- }));
2302
+ start(e, { dataEl, gridRect, scrollEl, gridEl }, dir = 'left') {
2303
+ gridEl.classList.add(COLUMN_DRAG_CLASS);
2304
+ const scrollContainerRect = scrollEl.getBoundingClientRect();
2305
+ if (scrollContainerRect) {
2306
+ this.offset = scrollContainerRect[dir] - gridRect[dir];
2307
+ }
2308
+ this.renderAutoscroll(e, dataEl);
2309
+ }
2310
+ stop(gridEl) {
2311
+ var _a;
2312
+ gridEl.classList.remove(COLUMN_DRAG_CLASS);
2313
+ if (this.element) {
2314
+ this.element.hidden = true;
2315
+ }
2316
+ this.offset = 0;
2317
+ (_a = this.autoscrollEl) === null || _a === void 0 ? void 0 : _a.remove();
2318
+ this.autoscrollEl = undefined;
2319
+ }
2320
+ showHandler(pos, size, direction = 'translateX') {
2321
+ if (!this.element) {
2322
+ return;
2323
+ }
2324
+ // do not allow overcross top of the scrollable area, header excluded
2325
+ if (this.offset) {
2326
+ pos = Math.max(pos, this.offset);
2327
+ }
2328
+ // can not be bigger then grid end
2329
+ pos = Math.min(pos, size);
2330
+ this.element.style.transform = `${direction}(${pos}px)`;
2331
+ this.element.hidden = false;
2332
+ }
2333
+ render() {
2334
+ const el = this.element = document.createElement('div');
2335
+ el.classList.add('drag-position-y');
2336
+ el.hidden = true;
2337
+ return el;
2338
+ }
2339
+ }
2340
+
2341
+ /**
2342
+ * Plugin for column manual move
2343
+ */
2344
+ const COLUMN_CLICK = headerCellRenderer.ON_COLUMN_CLICK;
2345
+ const MOVE = 'columndragmousemove';
2346
+ const DRAG_END = 'columndragend';
2347
+ const BEFORE_DRAG_END = 'beforecolumndragend';
2348
+ // use this event subscription to drop D&D for particular columns
2349
+ const DRAG_START = 'columndragstart';
2350
+ class ColumnMovePlugin extends BasePlugin {
2351
+ constructor(revogrid, providers) {
2352
+ super(revogrid, providers);
2353
+ this.revogrid = revogrid;
2354
+ this.providers = providers;
2355
+ this.moveFunc = debounce.debounce((e) => this.doMove(e), 5);
2356
+ this.staticDragData = null;
2357
+ this.dragData = null;
2358
+ this.localSubscriptions = {};
2359
+ this.orderUi = new ColumnOrderHandler();
2360
+ revogrid.appendChild(this.orderUi.render());
2361
+ revogrid.classList.add('column-draggable');
2362
+ // Register events
2363
+ this.localSubscriptions['mouseleave'] = {
2364
+ target: document,
2365
+ callback: (e) => this.onMouseOut(e),
2366
+ };
2367
+ this.localSubscriptions['mouseup'] = {
2368
+ target: document,
2369
+ callback: (e) => this.onMouseUp(e),
2370
+ };
2371
+ this.localSubscriptions['mousemove'] = {
2372
+ target: document,
2373
+ callback: (e) => this.move(e),
2374
+ };
2375
+ this.addEventListener(COLUMN_CLICK, ({ detail }) => this.dragStart(detail));
2376
+ }
2377
+ dragStart({ event, data }) {
2378
+ if (event.defaultPrevented) {
2379
+ return;
2321
2380
  }
2322
- this.postponeSort(order, sortingFunc, ignoreViewportUpdate);
2323
- }
2324
- getComparer(column, order) {
2325
- var _a, _b;
2326
- const cellCmp = ((_a = column === null || column === void 0 ? void 0 : column.cellCompare) === null || _a === void 0 ? void 0 : _a.bind({ order })) || ((_b = this.defaultCellCompare) === null || _b === void 0 ? void 0 : _b.bind({ column }));
2327
- if (order == 'asc') {
2328
- return cellCmp;
2381
+ const { defaultPrevented } = headerCellRenderer.dispatch(this.revogrid, DRAG_START, data);
2382
+ // check if allowed to drag particulat column
2383
+ if (defaultPrevented) {
2384
+ return;
2329
2385
  }
2330
- if (order == 'desc') {
2331
- return this.descCellCompare(cellCmp);
2386
+ this.clearOrder();
2387
+ const { mouseleave, mouseup, mousemove } = this.localSubscriptions;
2388
+ mouseleave.target.addEventListener('mouseleave', mouseleave.callback);
2389
+ mouseup.target.addEventListener('mouseup', mouseup.callback);
2390
+ const dataEl = event.target.closest('revogr-header');
2391
+ const scrollEl = event.target.closest('revogr-viewport-scroll');
2392
+ if (!dataEl || !scrollEl) {
2393
+ return;
2332
2394
  }
2333
- return undefined;
2395
+ // no grouping drag and no row header column drag
2396
+ if (column_service.isColGrouping(data) || data.providers.type === 'rowHeaders') {
2397
+ return;
2398
+ }
2399
+ const cols = this.getDimension(data.pin || 'rgCol');
2400
+ const gridRect = this.revogrid.getBoundingClientRect();
2401
+ const elRect = dataEl.getBoundingClientRect();
2402
+ const startItem = dimension_helpers.getItemByPosition(cols, getLeftRelative(event.x, gridRect.left, elRect.left - gridRect.left));
2403
+ this.staticDragData = {
2404
+ startPos: event.x,
2405
+ startItem,
2406
+ data,
2407
+ dataEl,
2408
+ scrollEl,
2409
+ gridEl: this.revogrid,
2410
+ cols,
2411
+ };
2412
+ this.dragData = this.getData(this.staticDragData);
2413
+ mousemove.target.addEventListener('mousemove', mousemove.callback);
2414
+ this.orderUi.start(event, Object.assign(Object.assign({}, this.dragData), this.staticDragData));
2334
2415
  }
2335
- /**
2336
- * Apply sorting to data on header click
2337
- * If additive - add to existing sorting, multiple columns can be sorted
2338
- */
2339
- headerclick(column, index, additive) {
2340
- var _a, _b;
2341
- let order = this.getNextOrder(column.order);
2342
- const beforeEvent = this.emit('beforesorting', { column, order, additive });
2343
- if (beforeEvent.defaultPrevented) {
2416
+ doMove(e) {
2417
+ if (!this.staticDragData) {
2344
2418
  return;
2345
2419
  }
2346
- order = beforeEvent.detail.order;
2347
- const newCol = this.providers.column.updateColumnSorting(beforeEvent.detail.column, index, order, additive);
2348
- // apply sort data
2349
- const beforeApplyEvent = this.emit('beforesortingapply', {
2350
- column: newCol,
2351
- order,
2352
- additive,
2353
- });
2354
- if (beforeApplyEvent.defaultPrevented) {
2420
+ const dragData = (this.dragData = this.getData(this.staticDragData));
2421
+ if (!dragData) {
2355
2422
  return;
2356
2423
  }
2357
- const cmp = this.getComparer(beforeApplyEvent.detail.column, beforeApplyEvent.detail.order);
2358
- if (beforeApplyEvent.detail.additive && this.sorting) {
2359
- const sorting = {};
2360
- const sortingFunc = {};
2361
- this.sorting = Object.assign(Object.assign({}, this.sorting), sorting);
2362
- // extend sorting function with new sorting for multiple columns sorting
2363
- this.sortingFunc = Object.assign(Object.assign({}, this.sortingFunc), sortingFunc);
2364
- if (column.prop in sorting && size(sorting) > 1 && order === undefined) {
2365
- delete sorting[column.prop];
2366
- delete sortingFunc[column.prop];
2367
- }
2368
- else {
2369
- sorting[column.prop] = order;
2370
- sortingFunc[column.prop] = cmp;
2424
+ const start = this.staticDragData.startPos;
2425
+ if (Math.abs(start - e.x) > 10) {
2426
+ const x = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2427
+ const rgCol = dimension_helpers.getItemByPosition(this.staticDragData.cols, x);
2428
+ this.orderUi.autoscroll(x, dragData.elRect.width);
2429
+ // prevent position change if out of bounds
2430
+ if (rgCol.itemIndex >= this.staticDragData.cols.count) {
2431
+ return;
2371
2432
  }
2433
+ this.orderUi.showHandler(rgCol.end + dragData.scrollOffset, dragData.gridRect.width);
2372
2434
  }
2373
- else {
2374
- if (order) {
2375
- // reset sorting
2376
- this.sorting = { [column.prop]: order };
2377
- this.sortingFunc = { [column.prop]: cmp };
2435
+ }
2436
+ move(e) {
2437
+ headerCellRenderer.dispatch(this.revogrid, MOVE, e);
2438
+ // then do move
2439
+ this.moveFunc(e);
2440
+ }
2441
+ onMouseOut(_) {
2442
+ this.clearOrder();
2443
+ }
2444
+ onMouseUp(e) {
2445
+ // apply new positions
2446
+ if (this.dragData && this.staticDragData) {
2447
+ let relativePos = getLeftRelative(e.x, this.dragData.gridRect.left, this.dragData.scrollOffset);
2448
+ if (relativePos < 0) {
2449
+ relativePos = 0;
2378
2450
  }
2379
- else {
2380
- (_a = this.sorting) === null || _a === void 0 ? true : delete _a[column.prop];
2381
- (_b = this.sortingFunc) === null || _b === void 0 ? true : delete _b[column.prop];
2451
+ const newPosition = dimension_helpers.getItemByPosition(this.staticDragData.cols, relativePos);
2452
+ const store = this.providers.column.stores[this.dragData.type].store;
2453
+ const newItems = [...store.get('items')];
2454
+ // prevent position change if needed
2455
+ const { defaultPrevented: stopDrag } = headerCellRenderer.dispatch(this.revogrid, BEFORE_DRAG_END, Object.assign(Object.assign({}, this.staticDragData), { startPosition: this.staticDragData.startItem, newPosition, newItem: store.get('source')[newItems[this.staticDragData.startItem.itemIndex]] }));
2456
+ if (!stopDrag) {
2457
+ const prevItems = [...newItems];
2458
+ // todo: if move item out of group remove item from group
2459
+ const toMove = newItems.splice(this.staticDragData.startItem.itemIndex, 1);
2460
+ newItems.splice(newPosition.itemIndex, 0, ...toMove);
2461
+ store.set('items', newItems);
2462
+ this.providers.dimension.updateSizesPositionByNewDataIndexes(this.dragData.type, newItems, prevItems);
2382
2463
  }
2464
+ headerCellRenderer.dispatch(this.revogrid, DRAG_END, this.dragData);
2383
2465
  }
2384
- this.startSorting(this.sorting, this.sortingFunc);
2466
+ this.clearOrder();
2467
+ }
2468
+ clearLocalSubscriptions() {
2469
+ forEach(this.localSubscriptions, ({ target, callback }, key) => target.removeEventListener(key, callback));
2470
+ }
2471
+ clearOrder() {
2472
+ this.staticDragData = null;
2473
+ this.dragData = null;
2474
+ this.clearLocalSubscriptions();
2475
+ this.orderUi.stop(this.revogrid);
2385
2476
  }
2386
2477
  /**
2387
- * Sort items by sorting function
2388
- * @requires proxyItems applied to row store
2389
- * @requires source applied to row store
2390
- *
2391
- * @param sorting - per column sorting
2392
- * @param data - this.stores['rgRow'].store.get('source')
2478
+ * Clearing subscription
2393
2479
  */
2394
- sort(sorting, sortingFunc, types = rowTypes, ignoreViewportUpdate = false) {
2395
- // if no sorting - reset
2396
- if (!Object.keys(sorting || {}).length) {
2397
- this.sorting = undefined;
2398
- this.sortingFunc = undefined;
2399
- for (let type of types) {
2400
- const storeService = this.providers.data.stores[type];
2401
- // row data
2402
- const source = storeService.store.get('source');
2403
- // row indexes
2404
- const proxyItems = storeService.store.get('proxyItems');
2405
- // row indexes
2406
- const newItemsOrder = Array.from({ length: source.length }, (_, i) => i); // recover indexes range(0, source.length)
2407
- this.providers.dimension.updateSizesPositionByNewDataIndexes(type, newItemsOrder, proxyItems);
2408
- storeService.setData({ proxyItems: newItemsOrder, source: [...source], });
2409
- }
2410
- }
2411
- else {
2412
- // set sorting
2413
- this.sorting = sorting;
2414
- this.sortingFunc = sortingFunc;
2415
- for (let type of types) {
2416
- const storeService = this.providers.data.stores[type];
2417
- // row data
2418
- const source = storeService.store.get('source');
2419
- // row indexes
2420
- const proxyItems = storeService.store.get('proxyItems');
2421
- const newItemsOrder = sortIndexByItems([...proxyItems], source, sortingFunc);
2422
- // take row indexes before trim applied and proxy items
2423
- const prevItems = storeService.store.get('items');
2424
- storeService.setData({
2425
- proxyItems: newItemsOrder,
2426
- source: [...source],
2427
- });
2428
- // take currently visible row indexes
2429
- const newItems = storeService.store.get('items');
2430
- if (!ignoreViewportUpdate) {
2431
- this.providers.dimension
2432
- .updateSizesPositionByNewDataIndexes(type, newItems, prevItems);
2433
- }
2434
- }
2435
- }
2436
- this.emit('aftersortingapply');
2437
- }
2438
- defaultCellCompare(prop, a, b) {
2439
- const aRaw = this.column ? column_service.getCellRaw(a, this.column) : a === null || a === void 0 ? void 0 : a[prop];
2440
- const bRaw = this.column ? column_service.getCellRaw(b, this.column) : b === null || b === void 0 ? void 0 : b[prop];
2441
- const av = aRaw === null || aRaw === void 0 ? void 0 : aRaw.toString().toLowerCase();
2442
- const bv = bRaw === null || bRaw === void 0 ? void 0 : bRaw.toString().toLowerCase();
2443
- return av == bv ? 0 : av > bv ? 1 : -1;
2480
+ clearSubscriptions() {
2481
+ super.clearSubscriptions();
2482
+ this.clearLocalSubscriptions();
2444
2483
  }
2445
- descCellCompare(cmp) {
2446
- return (prop, a, b) => {
2447
- return -1 * cmp(prop, a, b);
2484
+ getData({ gridEl, dataEl, data, }) {
2485
+ const gridRect = gridEl.getBoundingClientRect();
2486
+ const elRect = dataEl.getBoundingClientRect();
2487
+ const scrollOffset = elRect.left - gridRect.left;
2488
+ return {
2489
+ elRect,
2490
+ gridRect,
2491
+ type: data.pin || 'rgCol',
2492
+ scrollOffset,
2448
2493
  };
2449
2494
  }
2450
- getNextOrder(currentOrder) {
2451
- switch (currentOrder) {
2452
- case undefined:
2453
- return 'asc';
2454
- case 'asc':
2455
- return 'desc';
2456
- case 'desc':
2457
- return undefined;
2458
- }
2495
+ getDimension(type) {
2496
+ return this.providers.dimension.stores[type].getCurrentState();
2459
2497
  }
2460
2498
  }
2499
+ function getLeftRelative(absoluteX, gridPos, offset) {
2500
+ return absoluteX - gridPos - offset;
2501
+ }
2461
2502
 
2462
2503
  exports.AutoSizeColumnPlugin = AutoSizeColumnPlugin;
2463
2504
  exports.BasePlugin = BasePlugin;
@@ -2482,4 +2523,4 @@ exports.isRowType = isRowType;
2482
2523
  exports.isStretchPlugin = isStretchPlugin;
2483
2524
  exports.rowTypes = rowTypes;
2484
2525
 
2485
- //# sourceMappingURL=sorting.plugin-13a26a98.js.map
2526
+ //# sourceMappingURL=column.drag.plugin-e7ee8105.js.map