@kdcloudjs/table 1.1.4 → 1.1.5-canary.10

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 (89) hide show
  1. package/dist/@kdcloudjs/table.css +1 -1
  2. package/dist/@kdcloudjs/table.js +905 -346
  3. package/dist/@kdcloudjs/table.js.map +1 -1
  4. package/dist/@kdcloudjs/table.min.css +1 -1
  5. package/dist/@kdcloudjs/table.min.js +10 -9
  6. package/dist/@kdcloudjs/table.min.js.map +1 -1
  7. package/es/table/base/html-table.js +1 -1
  8. package/es/table/base/styles.d.ts +11 -2
  9. package/es/table/base/styles.js +19 -8
  10. package/es/table/base/table.d.ts +3 -1
  11. package/es/table/base/table.js +35 -56
  12. package/es/table/base/utils.d.ts +7 -0
  13. package/es/table/base/utils.js +36 -2
  14. package/es/table/common-views.js +1 -1
  15. package/es/table/pipeline/features/colGroupExtendable.d.ts +8 -0
  16. package/es/table/pipeline/features/colGroupExtendable.js +105 -0
  17. package/es/table/pipeline/features/columnDrag.js +5 -4
  18. package/es/table/pipeline/features/columnFilter.d.ts +8 -2
  19. package/es/table/pipeline/features/columnFilter.js +43 -19
  20. package/es/table/pipeline/features/columnResizeWidth.js +1 -1
  21. package/es/table/pipeline/features/contextMenu.d.ts +5 -1
  22. package/es/table/pipeline/features/contextMenu.js +18 -28
  23. package/es/table/pipeline/features/filter/DefaultFilterContent.js +27 -7
  24. package/es/table/pipeline/features/filter/DefaultFilterIcon.d.ts +5 -0
  25. package/es/table/pipeline/features/filter/DefaultFilterIcon.js +20 -0
  26. package/es/table/pipeline/features/filter/Filter.d.ts +5 -2
  27. package/es/table/pipeline/features/filter/Filter.js +65 -37
  28. package/es/table/pipeline/features/filter/FilterPanel.d.ts +2 -1
  29. package/es/table/pipeline/features/filter/FilterPanel.js +40 -21
  30. package/es/table/pipeline/features/filter/util.js +4 -4
  31. package/es/table/pipeline/features/footerDataSource.d.ts +9 -0
  32. package/es/table/pipeline/features/footerDataSource.js +25 -0
  33. package/es/table/pipeline/features/index.d.ts +2 -0
  34. package/es/table/pipeline/features/index.js +3 -1
  35. package/es/table/pipeline/features/multiSelect.js +7 -2
  36. package/es/table/pipeline/features/rangeSelection.d.ts +1 -1
  37. package/es/table/pipeline/features/rangeSelection.js +180 -30
  38. package/es/table/pipeline/features/singleSelect.js +4 -0
  39. package/es/table/pipeline/features/treeMode.d.ts +2 -0
  40. package/es/table/pipeline/features/treeMode.js +20 -21
  41. package/es/table/pipeline/pipeline.d.ts +1 -1
  42. package/es/table/pipeline/pipeline.js +4 -9
  43. package/es/table/utils/element.d.ts +1 -0
  44. package/es/table/utils/element.js +4 -0
  45. package/es/table/utils/keyCode.d.ts +5 -0
  46. package/es/table/utils/keyCode.js +5 -0
  47. package/es/table/utils/mergeCellProps.js +2 -6
  48. package/lib/table/base/html-table.js +1 -1
  49. package/lib/table/base/styles.d.ts +11 -2
  50. package/lib/table/base/styles.js +19 -8
  51. package/lib/table/base/table.d.ts +3 -1
  52. package/lib/table/base/table.js +35 -56
  53. package/lib/table/base/utils.d.ts +7 -0
  54. package/lib/table/base/utils.js +43 -2
  55. package/lib/table/common-views.js +1 -1
  56. package/lib/table/pipeline/features/colGroupExtendable.d.ts +8 -0
  57. package/lib/table/pipeline/features/colGroupExtendable.js +126 -0
  58. package/lib/table/pipeline/features/columnDrag.js +5 -4
  59. package/lib/table/pipeline/features/columnFilter.d.ts +8 -2
  60. package/lib/table/pipeline/features/columnFilter.js +41 -19
  61. package/lib/table/pipeline/features/columnResizeWidth.js +1 -1
  62. package/lib/table/pipeline/features/contextMenu.d.ts +5 -1
  63. package/lib/table/pipeline/features/contextMenu.js +17 -28
  64. package/lib/table/pipeline/features/filter/DefaultFilterContent.js +28 -6
  65. package/lib/table/pipeline/features/filter/DefaultFilterIcon.d.ts +5 -0
  66. package/lib/table/pipeline/features/filter/DefaultFilterIcon.js +30 -0
  67. package/lib/table/pipeline/features/filter/Filter.d.ts +5 -2
  68. package/lib/table/pipeline/features/filter/Filter.js +68 -37
  69. package/lib/table/pipeline/features/filter/FilterPanel.d.ts +2 -1
  70. package/lib/table/pipeline/features/filter/FilterPanel.js +42 -20
  71. package/lib/table/pipeline/features/filter/util.js +4 -4
  72. package/lib/table/pipeline/features/footerDataSource.d.ts +9 -0
  73. package/lib/table/pipeline/features/footerDataSource.js +41 -0
  74. package/lib/table/pipeline/features/index.d.ts +2 -0
  75. package/lib/table/pipeline/features/index.js +23 -1
  76. package/lib/table/pipeline/features/multiSelect.js +6 -1
  77. package/lib/table/pipeline/features/rangeSelection.d.ts +1 -1
  78. package/lib/table/pipeline/features/rangeSelection.js +183 -32
  79. package/lib/table/pipeline/features/singleSelect.js +4 -0
  80. package/lib/table/pipeline/features/treeMode.d.ts +2 -0
  81. package/lib/table/pipeline/features/treeMode.js +21 -23
  82. package/lib/table/pipeline/pipeline.d.ts +1 -1
  83. package/lib/table/pipeline/pipeline.js +4 -9
  84. package/lib/table/utils/element.d.ts +1 -0
  85. package/lib/table/utils/element.js +6 -0
  86. package/lib/table/utils/keyCode.d.ts +5 -0
  87. package/lib/table/utils/keyCode.js +12 -0
  88. package/lib/table/utils/mergeCellProps.js +2 -6
  89. package/package.json +3 -3
@@ -12,9 +12,15 @@ export interface FilterFeatureOptions {
12
12
  keepDataSource?: boolean;
13
13
  /** 过滤模式。单列过滤 single,多列过滤 multiple,默认为多选 */
14
14
  mode?: 'single' | 'multiple';
15
- /**过滤图标 */
16
- filterIcon?: ReactNode;
15
+ /** 过滤图标 */
16
+ filterIcon?: ReactNode | ((filtered: boolean) => ReactNode);
17
17
  /** 是否对触发弹出过滤面板 的 click 事件调用 event.stopPropagation() */
18
18
  stopClickEventPropagation?: boolean;
19
+ /** 是否对按ESC键时关闭面板的 keydown 事件调用 event.stopPropagation() */
20
+ stopESCKeyDownEventPropagation?: boolean;
21
+ /** 是否隐藏过滤面板的header区域 */
22
+ hideFilterPopupHeader?: boolean;
23
+ /** 指定过滤面板渲染的父节点 */
24
+ getPopupParent?: (triggerElement: HTMLElement) => HTMLElement;
19
25
  }
20
26
  export declare function filter(opts?: FilterFeatureOptions): (pipeline: TablePipeline) => TablePipeline;
@@ -28,7 +28,10 @@ export function filter() {
28
28
  keepDataSource = opts.keepDataSource,
29
29
  mode = opts.mode,
30
30
  filterIcon = opts.filterIcon,
31
- stopClickEventPropagation = opts.stopClickEventPropagation;
31
+ stopClickEventPropagation = opts.stopClickEventPropagation,
32
+ stopESCKeyDownEventPropagation = opts.stopESCKeyDownEventPropagation,
33
+ hideFilterPopupHeader = opts.hideFilterPopupHeader,
34
+ getPopupParent = opts.getPopupParent;
32
35
  var inputFilters = (_b = (_a = filters !== null && filters !== void 0 ? filters : pipeline.getStateAtKey(stateKey)) !== null && _a !== void 0 ? _a : defaultFilters) !== null && _b !== void 0 ? _b : [];
33
36
  inputFilters = mode === 'single' ? _sliceInstanceProperty(inputFilters).call(inputFilters, 0, 1) : inputFilters;
34
37
  var inputFiltersMap = new _Map(_mapInstanceProperty(inputFilters).call(inputFilters, function (filterItem) {
@@ -39,7 +42,7 @@ export function filter() {
39
42
  return _mapInstanceProperty(columns).call(columns, dfs);
40
43
 
41
44
  function dfs(col) {
42
- var _a, _b, _c, _d, _e;
45
+ var _a, _b, _c, _d, _e, _f, _g;
43
46
 
44
47
  var result = _extends({}, col);
45
48
 
@@ -81,18 +84,20 @@ export function filter() {
81
84
  };
82
85
 
83
86
  var filterPanel = (_d = col.features) === null || _d === void 0 ? void 0 : _d.filterPanel;
84
- result.title = _concatInstanceProperty(_context = []).call(_context, _toConsumableArray(_concatInstanceProperty(_context2 = []).call(_context2, (_e = result.title) !== null && _e !== void 0 ? _e : [internals.safeRenderHeader(_extends(_extends({}, col), {
85
- title: null
86
- }))])), [/*#__PURE__*/React.createElement(Filter, {
87
+ var colFilterIcon = (_f = (_e = col.features) === null || _e === void 0 ? void 0 : _e.filterIcon) !== null && _f !== void 0 ? _f : filterIcon;
88
+ result.title = _concatInstanceProperty(_context = []).call(_context, _toConsumableArray(_concatInstanceProperty(_context2 = []).call(_context2, (_g = result.title) !== null && _g !== void 0 ? _g : [internals.safeRenderHeader(_extends({}, col))])), [/*#__PURE__*/React.createElement(Filter, {
87
89
  key: "filter",
88
90
  FilterPanelContent: filterPanel,
89
- filterIcon: filterIcon,
91
+ filterIcon: colFilterIcon,
90
92
  filterModel: inputFiltersMap.get(col.code),
91
93
  setFilterModel: handleFilterChanged,
92
94
  setFilter: setFilter,
93
95
  isFilterActive: filterActive,
94
96
  className: cx((_cx = {}, _defineProperty(_cx, Classes.tableFilterTrigger, true), _defineProperty(_cx, "active", filterActive), _cx)),
95
- stopClickEventPropagation: stopClickEventPropagation
97
+ stopClickEventPropagation: stopClickEventPropagation,
98
+ stopESCKeyDownEventPropagation: stopESCKeyDownEventPropagation,
99
+ hideFilterPopupHeader: hideFilterPopupHeader,
100
+ getPopupParent: getPopupParent
96
101
  })]); // result.headerCellProps = mergeCellProps(col.headerCellProps, {
97
102
  // style: {
98
103
  // paddingRight: '18px'
@@ -134,8 +139,8 @@ export function filter() {
134
139
  return [item.key, _extends({}, item)];
135
140
  }));
136
141
 
137
- function isMatchedFilterCondition(record, rowIndex) {
138
- return !filtersKeys.some(function (key) {
142
+ function isMatchedFilterCondition(record) {
143
+ return filtersKeys.every(function (key) {
139
144
  var _a, _b;
140
145
 
141
146
  var filterItem = inputFiltersMap.get(key);
@@ -149,24 +154,43 @@ export function filter() {
149
154
  } else {
150
155
  console.warn("\u5217[".concat(key, "]\u672A\u914D\u7F6E\u7B5B\u9009\u51FD\u6570\uFF0C\u8BF7\u8BBE\u7F6E column.features.filterable \u6765\u4F5C\u4E3A\u8BE5\u5217\u7684\u7B5B\u9009\u51FD\u6570, \u76EE\u524D\u4F7F\u7528\u9ED8\u8BA4\u5305\u542B\u7B5B\u9009\u51FD\u6570"));
151
156
  comparisonFn = _filterInstanceProperty(defaultFilterOptionsMap.get('contain'));
152
- } // 不符合过滤条件,退出循环
157
+ }
153
158
 
154
-
155
- return !comparisonFn(_filterInstanceProperty(filterItem), filterItem)(internals.safeGetValue(columnsMap.get(key), record, rowIndex), record);
159
+ return comparisonFn(_filterInstanceProperty(filterItem), filterItem)(internals.safeGetValue(columnsMap.get(key), record, -1), record);
156
160
  });
157
161
  }
158
162
 
159
- return dataSource.reduce(function (pre, record, rowIndex) {
160
- if (isMatchedFilterCondition(record, rowIndex)) {
161
- return _concatInstanceProperty(pre).call(pre, [record]);
162
- }
163
-
164
- return pre;
165
- }, []);
163
+ return layeredFilter(dataSource, isMatchedFilterCondition);
166
164
  }
167
165
 
168
166
  pipeline.dataSource(processDataSource(dataSource));
169
167
  pipeline.columns(processColumns(columns));
170
168
  return pipeline;
171
169
  };
170
+ }
171
+
172
+ function layeredFilter(array, matchFn) {
173
+ return dfs(array);
174
+
175
+ function dfs(rows) {
176
+ var _context6;
177
+
178
+ var parentMatched = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
179
+ return _filterInstanceProperty(_context6 = _mapInstanceProperty(rows).call(rows, function (row) {
180
+ var currentMatched = matchFn(row);
181
+
182
+ if (isLeafNode(row)) {
183
+ return (parentMatched || currentMatched) && _extends({}, row);
184
+ }
185
+
186
+ var children = row.children;
187
+
188
+ var rowAfterFilterChildren = _extends(_extends({}, row), {
189
+ children: dfs(children, parentMatched || currentMatched)
190
+ });
191
+
192
+ var matchedByChildren = !isLeafNode(rowAfterFilterChildren);
193
+ return (parentMatched || currentMatched || matchedByChildren) && rowAfterFilterChildren;
194
+ })).call(_context6, Boolean);
195
+ }
172
196
  }
@@ -12,7 +12,7 @@ import * as op from 'rxjs/operators';
12
12
  import { mergeCellProps, collectNodes, makeRecursiveMapper, isGroupColumn } from '../../utils';
13
13
  import { internals } from '../../internals';
14
14
  import { Classes } from '../../base/styles';
15
- var TableHeaderCellResize = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: absolute;\n top: 0;\n right: -5px;\n height: 100%;\n width: 10px;\n cursor: ew-resize;\n display: flex;\n flex-direction: column;\n align-items: center;\n z-index:1;\n\n &:after {\n content: \"\";\n position: absolute;\n display: block;\n left: calc(50% - 1px);\n width: 1px;\n height: calc(100% - 14px);\n top: 7px;\n background-color: var(--border-color);\n }\n"])));
15
+ var TableHeaderCellResize = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n position: absolute;\n top: 0;\n right: -5px;\n height: 100%;\n width: 10px;\n cursor: ew-resize;\n display: flex;\n flex-direction: column;\n align-items: center;\n z-index:1;\n\n &:after {\n content: \"\";\n position: absolute;\n display: block;\n left: calc(50% - 1px);\n width: 1px;\n height: calc(100% - 14px);\n top: 7px;\n }\n"])));
16
16
  var TableHeaderGroupCellResize = styled(TableHeaderCellResize)(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n &:after {\n height: 100%;\n top: 0;\n }\n"])));
17
17
 
18
18
  function clamp(min, x, max) {
@@ -1,14 +1,18 @@
1
1
  import { TablePipeline } from '../pipeline';
2
2
  interface ContextMenuItem {
3
+ key?: string;
3
4
  name: string;
4
- action: () => {};
5
+ action: () => void;
5
6
  disabled?: boolean;
7
+ className?: string;
6
8
  }
7
9
  export interface ContextMenuFeatureOptions {
8
10
  /** 获得自定义菜单 */
9
11
  getContextMenuItems?: (params: any) => ContextMenuItem[];
10
12
  /** 弹出框的父容器 */
11
13
  popupParent?: HTMLElement;
14
+ /** 右键菜单className */
15
+ menuClassName?: string;
12
16
  }
13
17
  export declare function contextMenu(opts?: ContextMenuFeatureOptions): (pipeline: TablePipeline) => TablePipeline;
14
18
  export {};
@@ -10,12 +10,12 @@ import { ContextMenuStyleWrap } from '../../common-views';
10
10
  import { copyDataToClipboard, executeOnTempElement, console, getEventPath, isElementInEventPath, getTargetEleInEventPath } from '../../utils';
11
11
  import { findByTree } from '../../utils/others';
12
12
  import { internals } from '../../internals';
13
- import { Classes, MenuClasses } from '../../base/styles';
14
- var stateKey = 'contextMenu';
13
+ import { MenuClasses } from '../../base/styles';
15
14
  export function contextMenu() {
16
15
  var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
17
16
  return function step(pipeline) {
18
17
  var popupParent = opts.popupParent || document.body;
18
+ var menuClassName = opts.menuClassName;
19
19
  var menuHelper = new MenuHelper();
20
20
 
21
21
  var addPopup = function addPopup(menu) {
@@ -48,13 +48,11 @@ export function contextMenu() {
48
48
  };
49
49
 
50
50
  var onContextMenu = function onContextMenu(e) {
51
- if (suppressShowContextMenu(e)) {
52
- return;
51
+ if (canShowContextMenu(e, pipeline)) {
52
+ e.preventDefault();
53
+ e.stopPropagation();
54
+ showContextMenu(e);
53
55
  }
54
-
55
- e.preventDefault();
56
- e.stopPropagation();
57
- showContextMenu(e);
58
56
  };
59
57
 
60
58
  pipeline.addTableProps({
@@ -124,7 +122,8 @@ export function contextMenu() {
124
122
  options: options,
125
123
  hideContextMenu: hideContextMenu,
126
124
  position: position,
127
- getPopupParent: getPopupParent
125
+ getPopupParent: getPopupParent,
126
+ className: menuClassName
128
127
  });
129
128
 
130
129
  var _hidePopup = addPopup(menu);
@@ -157,7 +156,8 @@ function getMenuItemKey(_ref) {
157
156
  }
158
157
 
159
158
  function Menu(props) {
160
- var _props$options = props.options,
159
+ var className = props.className,
160
+ _props$options = props.options,
161
161
  options = _props$options === void 0 ? [] : _props$options,
162
162
  hideContextMenu = props.hideContextMenu,
163
163
  position = props.position,
@@ -178,7 +178,7 @@ function Menu(props) {
178
178
  }
179
179
  }, [position]);
180
180
  return /*#__PURE__*/React.createElement(ContextMenuStyleWrap, {
181
- className: MenuClasses.menu,
181
+ className: cx(MenuClasses.menu, className),
182
182
  ref: menuRef,
183
183
  style: {
184
184
  left: position.x,
@@ -194,6 +194,7 @@ function Menu(props) {
194
194
  }),
195
195
  name: item.name,
196
196
  action: item.action,
197
+ className: item.className,
197
198
  disabled: item.disabled,
198
199
  hideContextMenu: hideContextMenu
199
200
  });
@@ -203,6 +204,7 @@ function Menu(props) {
203
204
  function MenuItem(props) {
204
205
  var name = props.name,
205
206
  action = props.action,
207
+ className = props.className,
206
208
  disabled = props.disabled,
207
209
  hideContextMenu = props.hideContextMenu;
208
210
  var itemRef = useRef();
@@ -243,7 +245,7 @@ function MenuItem(props) {
243
245
  };
244
246
 
245
247
  return /*#__PURE__*/React.createElement("div", {
246
- className: cx(MenuClasses.menuOption, _defineProperty({}, MenuClasses.menuOptionDisable, disabled)),
248
+ className: cx(MenuClasses.menuOption, className, _defineProperty({}, MenuClasses.menuOptionDisable, disabled)),
247
249
  ref: itemRef,
248
250
  onClick: handleClick,
249
251
  onMouseEnter: handleMouseEnter,
@@ -387,24 +389,12 @@ function isElementInsideTheFooter(ele) {
387
389
  }
388
390
 
389
391
  return false;
390
- } // 禁止弹出右键菜单
391
-
392
-
393
- function suppressShowContextMenu(e) {
394
- var path = getEventPath(e.nativeEvent);
395
- var pointIndex = 0;
396
-
397
- while (pointIndex < path.length) {
398
- var ele = path[pointIndex];
399
-
400
- if (ele.classList.contains(Classes.tableBody) || ele.classList.contains(Classes.tableFooter)) {
401
- return false;
402
- }
392
+ }
403
393
 
404
- pointIndex++;
405
- }
394
+ function canShowContextMenu(e, pipeline) {
395
+ var _a, _b;
406
396
 
407
- return true;
397
+ return ((_a = pipeline.ref.current.domHelper) === null || _a === void 0 ? void 0 : _a.tableBody.contains(e.target)) || ((_b = pipeline.ref.current.domHelper) === null || _b === void 0 ? void 0 : _b.tableFooter.contains(e.target));
408
398
  } // 默认选项
409
399
 
410
400
 
@@ -6,11 +6,12 @@ var _templateObject;
6
6
 
7
7
  import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
8
8
  import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
9
- import React, { useEffect } from 'react';
9
+ import React, { useEffect, useRef } from 'react';
10
10
  import styled from 'styled-components';
11
11
  import cx from 'classnames';
12
12
  import { DEFAULT_FILTER_OPTIONS } from './util';
13
13
  import { Classes, ButtonCSS } from '../../../base/styles';
14
+ import KeyCode from '../../../utils/keyCode';
14
15
  var DefaultFilterContentStyle = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: flex;\n flex-direction: column;\n background-color: #ffffff;\n border-radius: 2px;\n width: 100%;\n\n ", "\n .filter-option-list {\n display: flex;\n flex-direction: column;\n margin-top: 8px;\n ul {\n margin: 0;\n padding: 0;\n li {\n display: flex;\n position: relative;\n flex-shrink: 0;\n height: 32px;\n align-items: center;\n border-radius: 2px;\n font-size: 12px;\n color: var(--color);\n padding: 0 12px;\n overflow: hidden;\n cursor: pointer;\n &:hover{\n background-color: var(--primary-color-level1);\n }\n }\n li.active{\n background-color: var(--primary-color-level1);\n }\n }\n }\n\n .filter-search {\n display: flex;\n padding: 6px 12px;\n\n .filter-search-inner {\n width: 100%;\n font-size: 12px;\n color: #333333;\n height: 28px;\n line-height: 28px;\n padding: 0 8px;\n outline: none;\n background-color: #FAFAFA;\n border-radius: 2px;\n border: 1px solid var(--strong-border-color);\n &:hover{\n border-color: var(--primary-color)\n } \n &:focus{\n border-color: var(--primary-color)\n } \n }\n }\n\n .filter-footer {\n display: flex;\n flex-direction: row;\n padding: 8px 12px;\n justify-content: space-between;\n\n .filter-btn {\n text-align: center;\n font-size: 12px;\n width: 60px;\n height: 24px;\n line-height: 24px;\n }\n \n }\n"])), ButtonCSS);
15
16
 
16
17
  function DefaultFilterContent(_ref) {
@@ -25,11 +26,12 @@ function DefaultFilterContent(_ref) {
25
26
  selectedValue = _React$useState2[0],
26
27
  setSelectedValue = _React$useState2[1];
27
28
 
28
- var _React$useState3 = React.useState((filterModel === null || filterModel === void 0 ? void 0 : _filterInstanceProperty(filterModel)) || ''),
29
+ var _React$useState3 = React.useState((filterModel === null || filterModel === void 0 ? void 0 : _filterInstanceProperty(filterModel)) || []),
29
30
  _React$useState4 = _slicedToArray(_React$useState3, 2),
30
31
  innerValue = _React$useState4[0],
31
32
  setInnerValue = _React$useState4[1];
32
33
 
34
+ var inputRef = useRef();
33
35
  var handleClick = React.useCallback(function (option) {
34
36
  setSelectedValue(option.key);
35
37
  }, []);
@@ -42,15 +44,31 @@ function DefaultFilterContent(_ref) {
42
44
  var confirm = function confirm() {
43
45
  hidePanel();
44
46
  setFilterModel({
45
- filter: [innerValue],
47
+ filter: innerValue,
46
48
  filterCondition: selectedValue
47
49
  });
48
50
  };
49
51
 
52
+ var handleKeyDown = function handleKeyDown(e) {
53
+ if (e.keyCode === KeyCode.ENTER) {
54
+ confirm();
55
+ }
56
+ };
57
+
50
58
  useEffect(function () {
51
59
  setSelectedValue((filterModel === null || filterModel === void 0 ? void 0 : filterModel.filterCondition) || 'contain');
52
- setInnerValue((filterModel === null || filterModel === void 0 ? void 0 : _filterInstanceProperty(filterModel)) || '');
60
+ setInnerValue((filterModel === null || filterModel === void 0 ? void 0 : _filterInstanceProperty(filterModel)) || []);
53
61
  }, [filterModel]);
62
+ useEffect(function () {
63
+ // 兼容设置焦点后发生滚动
64
+ setTimeout(function () {
65
+ var _a;
66
+
67
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus({
68
+ preventScroll: true
69
+ });
70
+ });
71
+ }, []);
54
72
  return /*#__PURE__*/React.createElement(DefaultFilterContentStyle, null, /*#__PURE__*/React.createElement("div", {
55
73
  className: 'filter-option-list'
56
74
  }, /*#__PURE__*/React.createElement("ul", null, _mapInstanceProperty(DEFAULT_FILTER_OPTIONS).call(DEFAULT_FILTER_OPTIONS, function (option, index) {
@@ -69,10 +87,12 @@ function DefaultFilterContent(_ref) {
69
87
  className: 'filter-search'
70
88
  }, /*#__PURE__*/React.createElement("input", {
71
89
  className: 'filter-search-inner',
72
- value: innerValue,
90
+ value: innerValue[0],
73
91
  onChange: function onChange(e) {
74
- setInnerValue(e.target.value);
75
- }
92
+ setInnerValue([e.target.value]);
93
+ },
94
+ onKeyDown: handleKeyDown,
95
+ ref: inputRef
76
96
  })), /*#__PURE__*/React.createElement("div", {
77
97
  className: 'filter-footer'
78
98
  }, /*#__PURE__*/React.createElement("button", {
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export default function DefaultFilterIcon({ width, height }: {
3
+ width: string | number;
4
+ height: string | number;
5
+ }): JSX.Element;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ export default function DefaultFilterIcon(_ref) {
3
+ var width = _ref.width,
4
+ height = _ref.height;
5
+ return /*#__PURE__*/React.createElement("svg", {
6
+ width: width,
7
+ height: height,
8
+ style: {
9
+ verticalAlign: 'middle'
10
+ },
11
+ viewBox: "0 0 1024 1024",
12
+ focusable: "false",
13
+ "data-icon": "filter",
14
+ fill: "currentColor",
15
+ version: "1.1",
16
+ xmlns: "http://www.w3.org/2000/svg"
17
+ }, /*#__PURE__*/React.createElement("path", {
18
+ d: "M891.448889 159.573333L626.460444 460.231111v443.221333c0 32.881778-25.429333 63.658667-55.864888 63.658667l-170.268445-172.942222V456.419556L132.266667 159.857778A59.619556 59.619556 0 0 1 173.511111 56.888889h676.977778c32.995556 0 59.733333 26.680889 59.733333 59.562667 0 17.066667-7.224889 32.312889-18.773333 43.121777z"
19
+ }));
20
+ }
@@ -6,12 +6,15 @@ interface FilterProps {
6
6
  size?: number;
7
7
  isFilterActive: boolean;
8
8
  FilterPanelContent?: FilterPanelType;
9
- filterIcon?: ReactNode;
9
+ filterIcon?: ReactNode | ((filtered: boolean) => ReactNode);
10
10
  setFilterModel: DefaultFilterPanelProps['setFilterModel'];
11
11
  filterModel: DefaultFilterPanelProps['filterModel'];
12
12
  setFilter: CustomeFilterPanelProps['setFilter'];
13
13
  onClick?: (e: React.MouseEvent) => any;
14
14
  stopClickEventPropagation?: boolean;
15
+ stopESCKeyDownEventPropagation?: boolean;
16
+ hideFilterPopupHeader?: boolean;
17
+ getPopupParent?: (triggerElement: HTMLElement) => HTMLElement;
15
18
  }
16
- declare function Filter({ size, style, className, FilterPanelContent, filterIcon, setFilter, setFilterModel, filterModel, isFilterActive, stopClickEventPropagation }: FilterProps): JSX.Element;
19
+ declare function Filter({ size, style, className, FilterPanelContent, filterIcon, setFilter, setFilterModel, filterModel, isFilterActive, stopClickEventPropagation, stopESCKeyDownEventPropagation, hideFilterPopupHeader, getPopupParent }: FilterProps): JSX.Element;
17
20
  export default Filter;
@@ -7,29 +7,30 @@ var _templateObject;
7
7
  import React, { useEffect } from 'react';
8
8
  import { createPortal } from 'react-dom';
9
9
  import styled from 'styled-components';
10
+ import cx from 'classnames';
10
11
  import { Classes } from '../../../base/styles';
11
12
  import FilterPanel from './FilterPanel';
12
13
  import DefaultFilterContent from './DefaultFilterContent';
14
+ import DefaultFilterIcon from './DefaultFilterIcon';
13
15
  import { calculatePopupRelative } from '../../../utils';
14
16
  import { addResizeObserver } from '../../../base/utils';
15
- import cx from 'classnames';
16
- var HEADER_ICON_OFFSET_Y = 6 + 1; // padding-top + border
17
+ import KeyCode from '../../../utils/keyCode';
18
+ var HEADER_ICON_OFFSET_Y = 8 + 1; // padding-top + border
17
19
 
18
20
  var HEADER_ICON_OFFSET_X = 16 + 1; // padding-left+ border
19
21
 
20
- var FilterIconSpanStyle = styled.span(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n // position: absolute;\n // right: 4px;\n // cursor: pointer;\n // transform: translateY(-50%);\n // top: 50%;\n // height: 12px; \n"])));
22
+ var FilterIconSpanStyle = styled.span(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n // position: absolute;\n // right: 4px;\n // cursor: pointer;\n // transform: translateY(-50%);\n // top: 50%;\n // height: 12px; \n > .", " {\n display: flex\n }\n"])), Classes.filterIcon);
21
23
 
22
24
  function Panel(_ref) {
23
25
  var ele = _ref.ele,
24
26
  filterIcon = _ref.filterIcon,
25
27
  hidePanel = _ref.hidePanel,
26
- renderPanelContent = _ref.renderPanelContent;
28
+ renderPanelContent = _ref.renderPanelContent,
29
+ hideFilterPopupHeader = _ref.hideFilterPopupHeader,
30
+ popupParent = _ref.popupParent;
27
31
  var filterPanelRef = React.useRef(null);
28
32
 
29
- var _React$useState = React.useState(calculatePopupRelative(ele, document.body, {
30
- x: HEADER_ICON_OFFSET_X,
31
- y: HEADER_ICON_OFFSET_Y
32
- })),
33
+ var _React$useState = React.useState(calculatePopupRelative(ele, popupParent, _getPanelOffset(ele, hideFilterPopupHeader))),
33
34
  _React$useState2 = _slicedToArray(_React$useState, 2),
34
35
  position = _React$useState2[0],
35
36
  setPosition = _React$useState2[1];
@@ -40,10 +41,7 @@ function Panel(_ref) {
40
41
  };
41
42
 
42
43
  var handleFilterPanelResize = function handleFilterPanelResize(resize) {
43
- setPosition(calculatePopupRelative(ele, document.body, {
44
- x: HEADER_ICON_OFFSET_X,
45
- y: HEADER_ICON_OFFSET_Y
46
- }));
44
+ setPosition(calculatePopupRelative(ele, popupParent, _getPanelOffset(ele, hideFilterPopupHeader)));
47
45
  };
48
46
 
49
47
  useEffect(function () {
@@ -58,7 +56,8 @@ function Panel(_ref) {
58
56
  style: style,
59
57
  onClose: hidePanel,
60
58
  position: position,
61
- filterIcon: filterIcon
59
+ filterIcon: filterIcon,
60
+ hideFilterPopupHeader: hideFilterPopupHeader
62
61
  }, renderPanelContent()));
63
62
  }
64
63
 
@@ -75,7 +74,10 @@ function Filter(_ref2) {
75
74
  setFilterModel = _ref2.setFilterModel,
76
75
  filterModel = _ref2.filterModel,
77
76
  isFilterActive = _ref2.isFilterActive,
78
- stopClickEventPropagation = _ref2.stopClickEventPropagation;
77
+ stopClickEventPropagation = _ref2.stopClickEventPropagation,
78
+ stopESCKeyDownEventPropagation = _ref2.stopESCKeyDownEventPropagation,
79
+ hideFilterPopupHeader = _ref2.hideFilterPopupHeader,
80
+ getPopupParent = _ref2.getPopupParent;
79
81
 
80
82
  var _React$useState3 = React.useState(false),
81
83
  _React$useState4 = _slicedToArray(_React$useState3, 2),
@@ -83,15 +85,12 @@ function Filter(_ref2) {
83
85
  setShowPanel = _React$useState4[1];
84
86
 
85
87
  var iconRef = React.useRef(null);
88
+ var iconWrapRef = React.useRef();
86
89
 
87
90
  var hidePanel = function hidePanel() {
88
91
  return setShowPanel(false);
89
92
  };
90
93
 
91
- var handleMouseDown = function handleMouseDown(e) {
92
- e.stopPropagation(); // 阻止触发拖拽
93
- };
94
-
95
94
  var renderPanelContent = function renderPanelContent() {
96
95
  if (FilterPanelContent) {
97
96
  return /*#__PURE__*/React.createElement(FilterPanelContent, {
@@ -111,38 +110,67 @@ function Filter(_ref2) {
111
110
  };
112
111
 
113
112
  var handleIconClick = function handleIconClick(e) {
113
+ // 只有当icon区域点击会触发面板展开
114
+ // 防止 createPortal 区域的点击触发该事件
115
+ if (e.currentTarget.contains(e.target)) {
116
+ setShowPanel(true);
117
+ }
118
+
114
119
  if (stopClickEventPropagation) {
115
120
  e.stopPropagation();
116
121
  }
122
+ };
117
123
 
118
- setShowPanel(true);
124
+ var handleKeyDown = function handleKeyDown(e) {
125
+ if (e.keyCode === KeyCode.ESC) {
126
+ if (e.currentTarget.contains(e.target)) {
127
+ setShowPanel(false);
128
+ }
129
+
130
+ if (stopESCKeyDownEventPropagation) {
131
+ e.stopPropagation();
132
+ }
133
+ }
119
134
  };
120
135
 
121
136
  var iconClassName = cx((_cx = {}, _defineProperty(_cx, className, true), _defineProperty(_cx, 'filter-panel-open', showPanel), _cx));
137
+ var displayFilterIcon = typeof filterIcon === 'function' ? filterIcon(isFilterActive) : filterIcon;
138
+ var popupParent = (getPopupParent === null || getPopupParent === void 0 ? void 0 : getPopupParent(iconWrapRef.current)) || document.body;
122
139
  return /*#__PURE__*/React.createElement(FilterIconSpanStyle, {
123
140
  style: style,
124
141
  className: iconClassName,
125
- onMouseDown: handleMouseDown,
126
- ref: iconRef
142
+ onClick: handleIconClick,
143
+ onKeyDown: handleKeyDown,
144
+ ref: iconWrapRef,
145
+ tabIndex: -1
127
146
  }, /*#__PURE__*/React.createElement("span", {
128
- className: Classes.filterIcon,
129
- onClick: handleIconClick
130
- }, filterIcon || /*#__PURE__*/React.createElement("svg", {
147
+ ref: iconRef,
148
+ className: Classes.filterIcon
149
+ }, displayFilterIcon || /*#__PURE__*/React.createElement(DefaultFilterIcon, {
131
150
  width: size,
132
- height: size,
133
- viewBox: "64 64 896 896",
134
- focusable: "false",
135
- "data-icon": "filter",
136
- fill: "currentColor",
137
- "aria-hidden": "true"
138
- }, /*#__PURE__*/React.createElement("path", {
139
- d: "M349 838c0 17.7 14.2 32 31.8 32h262.4c17.6 0 31.8-14.3\n 31.8-32V642H349v196zm531.1-684H143.9c-24.5 0-39.8 26.7-27.5\n 48l221.3 376h348.8l221.3-376c12.1-21.3-3.2-48-27.7-48z"
140
- }))), showPanel && /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(Panel, {
141
- ele: iconRef.current,
142
- filterIcon: filterIcon,
151
+ height: size
152
+ })), showPanel && /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement(Panel, {
153
+ ele: hideFilterPopupHeader ? iconWrapRef.current : iconRef.current,
154
+ filterIcon: displayFilterIcon,
143
155
  hidePanel: hidePanel,
144
- renderPanelContent: renderPanelContent
145
- }), document.body));
156
+ renderPanelContent: renderPanelContent,
157
+ hideFilterPopupHeader: hideFilterPopupHeader,
158
+ popupParent: popupParent
159
+ }), popupParent));
160
+ }
161
+
162
+ function _getPanelOffset(ele, hideFilterPopupHeader) {
163
+ if (hideFilterPopupHeader) {
164
+ return {
165
+ x: 0,
166
+ y: 0 - ele.offsetHeight
167
+ };
168
+ }
169
+
170
+ return {
171
+ x: HEADER_ICON_OFFSET_X,
172
+ y: HEADER_ICON_OFFSET_Y
173
+ };
146
174
  }
147
175
 
148
176
  export default Filter;
@@ -10,11 +10,12 @@ export interface FilterPanel {
10
10
  filterIcon: ReactNode;
11
11
  children?: ReactNode;
12
12
  }
13
- declare function FilterPanel({ style, children, position, filterIcon, onClose }: {
13
+ declare function FilterPanel({ style, children, position, filterIcon, onClose, hideFilterPopupHeader }: {
14
14
  style: any;
15
15
  children: any;
16
16
  position: any;
17
17
  filterIcon: any;
18
18
  onClose: any;
19
+ hideFilterPopupHeader: any;
19
20
  }): JSX.Element;
20
21
  export default FilterPanel;