@douyinfe/semi-ui 2.7.0-beta.0 → 2.8.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/_base/_story/index.stories.js +2 -6
  2. package/_portal/_story/portal.stories.js +1 -5
  3. package/_utils/hooks/usePrevFocus.ts +1 -0
  4. package/_utils/index.ts +29 -1
  5. package/datePicker/_story/v2/FixDefaultPickerValue.jsx +31 -0
  6. package/datePicker/_story/v2/InsetInput.jsx +1 -1
  7. package/datePicker/_story/v2/index.js +1 -0
  8. package/datePicker/monthsGrid.tsx +3 -13
  9. package/dist/css/semi.css +30 -21
  10. package/dist/css/semi.min.css +1 -1
  11. package/dist/umd/semi-ui.js +627 -287
  12. package/dist/umd/semi-ui.js.map +1 -1
  13. package/dist/umd/semi-ui.min.js +1 -1
  14. package/dist/umd/semi-ui.min.js.map +1 -1
  15. package/form/hooks/useFormApi.tsx +3 -2
  16. package/input/_story/input.stories.js +10 -1
  17. package/inputNumber/_story/inputNumber.stories.js +4 -0
  18. package/lib/cjs/_utils/hooks/usePrevFocus.js +1 -0
  19. package/lib/cjs/_utils/index.d.ts +3 -1
  20. package/lib/cjs/_utils/index.js +25 -1
  21. package/lib/cjs/datePicker/monthsGrid.js +11 -19
  22. package/lib/cjs/form/hooks/useFormApi.d.ts +2 -1
  23. package/lib/cjs/modal/useModal/HookModal.js +2 -0
  24. package/lib/cjs/notification/useNotification/index.js +1 -1
  25. package/lib/cjs/popover/index.d.ts +18 -3
  26. package/lib/cjs/popover/index.js +53 -23
  27. package/lib/cjs/radio/radioGroup.js +6 -0
  28. package/lib/cjs/select/index.js +5 -2
  29. package/lib/cjs/tag/group.d.ts +2 -0
  30. package/lib/cjs/tag/group.js +4 -2
  31. package/lib/cjs/tooltip/index.d.ts +22 -4
  32. package/lib/cjs/tooltip/index.js +65 -27
  33. package/lib/cjs/tree/nodeList.js +1 -0
  34. package/lib/cjs/treeSelect/index.js +4 -0
  35. package/lib/es/_utils/hooks/usePrevFocus.js +2 -0
  36. package/lib/es/_utils/index.d.ts +3 -1
  37. package/lib/es/_utils/index.js +18 -0
  38. package/lib/es/datePicker/monthsGrid.js +11 -19
  39. package/lib/es/form/hooks/useFormApi.d.ts +2 -1
  40. package/lib/es/modal/useModal/HookModal.js +2 -0
  41. package/lib/es/notification/useNotification/index.js +2 -1
  42. package/lib/es/popover/index.d.ts +18 -3
  43. package/lib/es/popover/index.js +52 -23
  44. package/lib/es/radio/radioGroup.js +6 -0
  45. package/lib/es/select/index.js +5 -2
  46. package/lib/es/tag/group.d.ts +2 -0
  47. package/lib/es/tag/group.js +4 -2
  48. package/lib/es/tooltip/index.d.ts +22 -4
  49. package/lib/es/tooltip/index.js +65 -27
  50. package/lib/es/tree/nodeList.js +1 -0
  51. package/lib/es/treeSelect/index.js +4 -0
  52. package/modal/_story/modal.stories.js +93 -1
  53. package/modal/useModal/HookModal.tsx +1 -0
  54. package/notification/_story/useNotification/index.jsx +21 -7
  55. package/notification/useNotification/index.tsx +1 -1
  56. package/package.json +9 -9
  57. package/popover/_story/popover.stories.js +75 -1
  58. package/popover/index.tsx +24 -8
  59. package/radio/__test__/radioGroup.test.jsx +9 -1
  60. package/radio/_story/radio.stories.js +22 -1
  61. package/radio/radioGroup.tsx +9 -0
  62. package/select/_story/select.stories.js +73 -2
  63. package/select/index.tsx +5 -3
  64. package/table/_story/v2/FixedMemoryLeak/index.jsx +33 -0
  65. package/table/_story/v2/index.js +2 -1
  66. package/tag/group.tsx +5 -3
  67. package/toast/_story/toast.stories.js +41 -0
  68. package/tooltip/index.tsx +72 -22
  69. package/tree/nodeList.tsx +1 -0
  70. package/treeSelect/index.tsx +3 -0
@@ -24,6 +24,8 @@ var _assign = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-sta
24
24
 
25
25
  var _setTimeout2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set-timeout"));
26
26
 
27
+ var _isFunction2 = _interopRequireDefault(require("lodash/isFunction"));
28
+
27
29
  var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
28
30
 
29
31
  var _each2 = _interopRequireDefault(require("lodash/each"));
@@ -185,6 +187,17 @@ class Tooltip extends _baseComponent.default {
185
187
  }
186
188
  };
187
189
 
190
+ this.handlePortalInnerKeyDown = e => {
191
+ this.foundation.handleContainerKeydown(e);
192
+ };
193
+
194
+ this.renderContentNode = content => {
195
+ const contentProps = {
196
+ initialFocusRef: this.initialFocusRef
197
+ };
198
+ return !(0, _isFunction2.default)(content) ? content : content(contentProps);
199
+ };
200
+
188
201
  this.renderPortal = () => {
189
202
  const {
190
203
  containerStyle = {},
@@ -204,6 +217,7 @@ class Tooltip extends _baseComponent.default {
204
217
  role,
205
218
  zIndex
206
219
  } = this.props;
220
+ const contentNode = this.renderContentNode(content);
207
221
  const {
208
222
  className: propClassName
209
223
  } = this.props;
@@ -238,7 +252,7 @@ class Tooltip extends _baseComponent.default {
238
252
  role: role,
239
253
  "x-placement": placement,
240
254
  id: id
241
- }), content, icon);
255
+ }), contentNode, icon);
242
256
  } : null) : /*#__PURE__*/_react.default.createElement("div", (0, _assign.default)({
243
257
  className: className
244
258
  }, portalEventSet, {
@@ -246,7 +260,7 @@ class Tooltip extends _baseComponent.default {
246
260
  style: (0, _assign.default)({
247
261
  visibility: motion ? undefined : 'visible'
248
262
  }, style)
249
- }), content, icon);
263
+ }), contentNode, icon);
250
264
  return /*#__PURE__*/_react.default.createElement(_index.default, {
251
265
  getPopupContainer: this.props.getPopupContainer,
252
266
  style: {
@@ -256,7 +270,8 @@ class Tooltip extends _baseComponent.default {
256
270
  className: "".concat(_constants.BASE_CLASS_PREFIX, "-portal-inner"),
257
271
  style: portalInnerStyle,
258
272
  ref: this.setContainerEl,
259
- onClick: this.handlePortalInnerClick
273
+ onClick: this.handlePortalInnerClick,
274
+ onKeyDown: this.handlePortalInnerKeyDown
260
275
  }, inner));
261
276
  };
262
277
 
@@ -319,6 +334,7 @@ class Tooltip extends _baseComponent.default {
319
334
  this.eventManager = new _Event.default();
320
335
  this.triggerEl = /*#__PURE__*/_react.default.createRef();
321
336
  this.containerEl = /*#__PURE__*/_react.default.createRef();
337
+ this.initialFocusRef = /*#__PURE__*/_react.default.createRef();
322
338
  this.clickOutsideHandler = null;
323
339
  this.resizeHandler = null;
324
340
  this.isWrapped = false; // Identifies whether a span element is wrapped
@@ -370,7 +386,8 @@ class Tooltip extends _baseComponent.default {
370
386
  mouseOver: 'onMouseOver',
371
387
  click: 'onClick',
372
388
  focus: 'onFocus',
373
- blur: 'onBlur'
389
+ blur: 'onBlur',
390
+ keydown: 'onKeyDown'
374
391
  }),
375
392
  registerTriggerEvent: triggerEventSet => {
376
393
  this.setState({
@@ -388,15 +405,8 @@ class Tooltip extends _baseComponent.default {
388
405
  // eslint-disable-next-line
389
406
  // It may be a React component or an html element
390
407
  // There is no guarantee that triggerE l.current can get the real dom, so call findDOMNode to ensure that you can get the real dom
391
- let triggerDOM = this.triggerEl.current;
392
-
393
- if (!(0, _reactUtils.isHTMLElement)(this.triggerEl.current)) {
394
- const realDomNode = _reactDom.default.findDOMNode(this.triggerEl.current);
395
-
396
- this.triggerEl.current = realDomNode;
397
- triggerDOM = realDomNode;
398
- }
399
-
408
+ const triggerDOM = this.adapter.getTriggerNode();
409
+ this.triggerEl.current = triggerDOM;
400
410
  return triggerDOM && triggerDOM.getBoundingClientRect();
401
411
  },
402
412
  // Gets the outer size of the specified container
@@ -463,7 +473,7 @@ class Tooltip extends _baseComponent.default {
463
473
  willUpdateStates.visible = visible;
464
474
  }
465
475
 
466
- this.setState(willUpdateStates, () => {
476
+ this.mounted && this.setState(willUpdateStates, () => {
467
477
  cb();
468
478
  });
469
479
  },
@@ -533,12 +543,7 @@ class Tooltip extends _baseComponent.default {
533
543
  return false;
534
544
  }
535
545
 
536
- let triggerDOM = this.triggerEl.current;
537
-
538
- if (!(0, _reactUtils.isHTMLElement)(this.triggerEl.current)) {
539
- triggerDOM = _reactDom.default.findDOMNode(this.triggerEl.current);
540
- }
541
-
546
+ const triggerDOM = this.adapter.getTriggerNode();
542
547
  const isRelativeScroll = e.target.contains(triggerDOM);
543
548
 
544
549
  if (isRelativeScroll) {
@@ -569,7 +574,33 @@ class Tooltip extends _baseComponent.default {
569
574
  this.containerPosition = position;
570
575
  }
571
576
  },
572
- getContainerPosition: () => this.containerPosition
577
+ getContainerPosition: () => this.containerPosition,
578
+ getContainer: () => this.containerEl && this.containerEl.current,
579
+ getTriggerNode: () => {
580
+ let triggerDOM = this.triggerEl.current;
581
+
582
+ if (!(0, _reactUtils.isHTMLElement)(this.triggerEl.current)) {
583
+ triggerDOM = _reactDom.default.findDOMNode(this.triggerEl.current);
584
+ }
585
+
586
+ return triggerDOM;
587
+ },
588
+ getFocusableElements: node => {
589
+ return (0, _utils.getFocusableElements)(node);
590
+ },
591
+ getActiveElement: () => {
592
+ return (0, _utils.getActiveElement)();
593
+ },
594
+ setInitialFocus: () => {
595
+ const focusRefNode = (0, _get2.default)(this, 'initialFocusRef.current');
596
+
597
+ if (focusRefNode && 'focus' in focusRefNode) {
598
+ focusRefNode.focus();
599
+ }
600
+ },
601
+ notifyEscKeydown: event => {
602
+ this.props.onEscKeyDown(event);
603
+ }
573
604
  });
574
605
  }
575
606
 
@@ -611,7 +642,8 @@ class Tooltip extends _baseComponent.default {
611
642
  } = this.state;
612
643
  const {
613
644
  wrapWhenSpecial,
614
- role
645
+ role,
646
+ trigger
615
647
  } = this.props;
616
648
  let {
617
649
  children
@@ -669,7 +701,8 @@ class Tooltip extends _baseComponent.default {
669
701
  } else if (ref && typeof ref === 'object') {
670
702
  ref.current = node;
671
703
  }
672
- }
704
+ },
705
+ tabIndex: trigger === 'hover' ? 0 : undefined
673
706
  })); // If you do not add a layer of div, in order to bind the events and className in the tooltip, you need to cloneElement children, but this time it may overwrite the children's original ref reference
674
707
  // So if the user adds ref to the content, you need to use callback ref: https://github.com/facebook/react/issues/8873
675
708
 
@@ -697,7 +730,7 @@ Tooltip.propTypes = {
697
730
  clickTriggerToHide: _propTypes.default.bool,
698
731
  visible: _propTypes.default.bool,
699
732
  style: _propTypes.default.object,
700
- content: _propTypes.default.node,
733
+ content: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]),
701
734
  prefixCls: _propTypes.default.string,
702
735
  onVisibleChange: _propTypes.default.func,
703
736
  onClickOutSide: _propTypes.default.func,
@@ -711,8 +744,9 @@ Tooltip.propTypes = {
711
744
  stopPropagation: _propTypes.default.bool,
712
745
  // private
713
746
  role: _propTypes.default.string,
714
- wrapWhenSpecial: _propTypes.default.bool // when trigger has special status such as "disabled" or "loading", wrap span
715
-
747
+ wrapWhenSpecial: _propTypes.default.bool,
748
+ guardFocus: _propTypes.default.bool,
749
+ returnFocusOnClose: _propTypes.default.bool
716
750
  };
717
751
  Tooltip.defaultProps = {
718
752
  arrowBounding: _constants2.numbers.ARROW_BOUNDING,
@@ -731,5 +765,9 @@ Tooltip.defaultProps = {
731
765
  spacing: _constants2.numbers.SPACING,
732
766
  showArrow: true,
733
767
  wrapWhenSpecial: true,
734
- zIndex: _constants2.numbers.DEFAULT_Z_INDEX
768
+ zIndex: _constants2.numbers.DEFAULT_Z_INDEX,
769
+ closeOnEsc: false,
770
+ guardFocus: false,
771
+ returnFocusOnClose: false,
772
+ onEscKeyDown: _noop2.default
735
773
  };
@@ -49,6 +49,7 @@ class NodeList extends _react.PureComponent {
49
49
  super(props);
50
50
 
51
51
  this.onMotionEnd = () => {
52
+ typeof this.props.onMotionEnd === 'function' && this.props.onMotionEnd();
52
53
  this.setState({
53
54
  transitionNodes: []
54
55
  });
@@ -955,6 +955,10 @@ class TreeSelect extends _baseComponent.default {
955
955
  this.clickOutsideHandler = null;
956
956
  this.foundation = new _foundation.default(this.adapter);
957
957
  this.treeSelectID = (0, _slice.default)(_context2 = Math.random().toString(36)).call(_context2, 2);
958
+
959
+ this.onMotionEnd = () => {
960
+ this.adapter.rePositionDropdown();
961
+ };
958
962
  } // eslint-disable-next-line max-lines-per-function
959
963
 
960
964
 
@@ -2,6 +2,8 @@ import _isFunction from "lodash/isFunction";
2
2
  import _get from "lodash/get";
3
3
  import { useState, useEffect } from 'react';
4
4
  import { getActiveElement } from '../index';
5
+
6
+ /* istanbul ignore next */
5
7
  export function usePrevFocus() {
6
8
  const [prevFocusElement, setPrevFocus] = useState(getActiveElement());
7
9
  useEffect(() => {
@@ -67,4 +67,6 @@ export interface HighLightTextHTMLChunk {
67
67
  * @returns boolean
68
68
  */
69
69
  export declare const isSemiIcon: (icon: any) => boolean;
70
- export declare function getActiveElement(): HTMLElement;
70
+ export declare function getActiveElement(): HTMLElement | null;
71
+ export declare function isNodeContainsFocus(node: HTMLElement): boolean;
72
+ export declare function getFocusableElements(node: HTMLElement): HTMLElement[];
@@ -6,6 +6,7 @@ import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
6
6
  import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
7
7
  import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
8
8
  import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
9
+ import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
9
10
 
10
11
  /* eslint-disable max-len */
11
12
 
@@ -13,6 +14,7 @@ import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance
13
14
  import React from 'react';
14
15
  import warning from '@douyinfe/semi-foundation/lib/es/utils/warning';
15
16
  import { findAll } from '@douyinfe/semi-foundation/lib/es/utils/getHighlight';
17
+ import { isHTMLElement } from '@douyinfe/semi-foundation/lib/es/utils/dom';
16
18
  /**
17
19
  * stop propagation
18
20
  *
@@ -168,4 +170,20 @@ export const registerMediaQuery = (media, _ref2) => {
168
170
  export const isSemiIcon = icon => /*#__PURE__*/React.isValidElement(icon) && _get(icon.type, 'elementType') === 'Icon';
169
171
  export function getActiveElement() {
170
172
  return document ? document.activeElement : null;
173
+ }
174
+ export function isNodeContainsFocus(node) {
175
+ const activeElement = getActiveElement();
176
+ return activeElement === node || node.contains(activeElement);
177
+ }
178
+ export function getFocusableElements(node) {
179
+ if (!isHTMLElement(node)) {
180
+ return [];
181
+ }
182
+
183
+ const focusableSelectorsList = ["input:not([disabled]):not([tabindex='-1'])", "textarea:not([disabled]):not([tabindex='-1'])", "button:not([disabled]):not([tabindex='-1'])", "a[href]:not([tabindex='-1'])", "select:not([disabled]):not([tabindex='-1'])", "area[href]:not([tabindex='-1'])", "iframe:not([tabindex='-1'])", "object:not([tabindex='-1'])", "*[tabindex]:not([tabindex='-1'])", "*[contenteditable]:not([tabindex='-1'])"];
184
+ const focusableSelectorsStr = focusableSelectorsList.join(','); // we are not filtered elements which are invisible
185
+
186
+ const focusableElements = _Array$from(node.querySelectorAll(focusableSelectorsStr));
187
+
188
+ return focusableElements;
171
189
  }
@@ -1,7 +1,6 @@
1
1
  import _stubFalse from "lodash/stubFalse";
2
2
  import _noop from "lodash/noop";
3
3
  import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
4
- import _Array$isArray from "@babel/runtime-corejs3/core-js-stable/array/is-array";
5
4
  import _Set from "@babel/runtime-corejs3/core-js-stable/set";
6
5
  import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
7
6
  import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
@@ -19,7 +18,7 @@ import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/ins
19
18
  import React from 'react';
20
19
  import classnames from 'classnames';
21
20
  import PropTypes from 'prop-types';
22
- import { format as formatFn, addMonths, isSameDay } from 'date-fns';
21
+ import { format as formatFn, isSameDay } from 'date-fns';
23
22
  import MonthsGridFoundation from '@douyinfe/semi-foundation/lib/es/datePicker/monthsGridFoundation';
24
23
  import { strings, numbers, cssClasses } from '@douyinfe/semi-foundation/lib/es/datePicker/constants';
25
24
  import { compatiableParse } from '@douyinfe/semi-foundation/lib/es/datePicker/_utils/parser';
@@ -30,6 +29,7 @@ import Combobox from '../timePicker/Combobox';
30
29
  import YearAndMonth from './yearAndMonth';
31
30
  import { IconClock, IconCalendar } from '@douyinfe/semi-icons';
32
31
  import { getDefaultFormatTokenByType } from '@douyinfe/semi-foundation/lib/es/datePicker/_utils/getDefaultFormatToken';
32
+ import getDefaultPickerDate from '@douyinfe/semi-foundation/lib/es/datePicker/_utils/getDefaultPickerDate';
33
33
  const prefixCls = cssClasses.PREFIX;
34
34
  export default class MonthsGrid extends BaseComponent {
35
35
  constructor(props) {
@@ -132,23 +132,15 @@ export default class MonthsGrid extends BaseComponent {
132
132
  return this.foundation.getYAMOpenType();
133
133
  };
134
134
 
135
- let nowDate = _Array$isArray(props.defaultPickerValue) ? props.defaultPickerValue[0] : props.defaultPickerValue;
136
135
  const validFormat = props.format || getDefaultFormatTokenByType(props.type);
137
-
138
- if (!nowDate) {
139
- nowDate = new Date();
140
- } else {
141
- nowDate = compatiableParse(nowDate, validFormat, undefined, props.dateFnsLocale);
142
- }
143
-
144
- let nextDate = _Array$isArray(props.defaultPickerValue) ? props.defaultPickerValue[1] : undefined;
145
-
146
- if (!nextDate) {
147
- nextDate = addMonths(nowDate, 1);
148
- } else {
149
- nextDate = compatiableParse(nextDate, validFormat, undefined, props.dateFnsLocale);
150
- }
151
-
136
+ const {
137
+ nowDate,
138
+ nextDate
139
+ } = getDefaultPickerDate({
140
+ defaultPickerValue: props.defaultPickerValue,
141
+ format: validFormat,
142
+ dateFnsLocale: props.dateFnsLocale
143
+ });
152
144
  const dateState = {
153
145
  // Direct use of full date string storage, mainly considering the month rendering comparison to save a conversion
154
146
  // The selected value for single or multiple selection, full date string, eg. {'2019-10-01', '2019-10-02'}
@@ -647,7 +639,7 @@ export default class MonthsGrid extends BaseComponent {
647
639
  className: monthGridCls,
648
640
  "x-type": type,
649
641
  "x-panel-yearandmonth-open-type": yearOpenType,
650
- "x-insetInput": insetInput ? "true" : "false",
642
+ "x-insetinput": insetInput ? "true" : "false",
651
643
  ref: current => this.cacheRefCurrent('monthGrid', current)
652
644
  }, content);
653
645
  }
@@ -1 +1,2 @@
1
- export default function useFormApi(): import("@douyinfe/semi-foundation/lib/es/form/interface").BaseFormApi<any>;
1
+ import { BaseFormApi } from '@douyinfe/semi-foundation/lib/es/form/interface';
2
+ export default function useFormApi<T extends Record<string, any> = any>(): BaseFormApi<T>;
@@ -39,6 +39,8 @@ const HookModal = (_a, ref) => {
39
39
  const {
40
40
  motion
41
41
  } = props;
42
+ /* istanbul ignore next */
43
+
42
44
  const mergedMotion = typeof motion === 'undefined' || motion ? _Object$assign(_Object$assign({}, motion), {
43
45
  didLeave: function () {
44
46
  const didLeave = _get(props.motion, 'didLeave');
@@ -80,9 +80,10 @@ function usePatchElement() {
80
80
  export default function useNotification() {
81
81
  const [elements, patchElement] = usePatchElement();
82
82
  const noticeRef = new _Map();
83
- const id = getUuid('semi_notice_');
84
83
 
85
84
  const addNotice = config => {
85
+ const id = getUuid('semi_notice_');
86
+
86
87
  const mergeConfig = _Object$assign(_Object$assign({}, config), {
87
88
  id
88
89
  }); // eslint-disable-next-line prefer-const
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { ArrowBounding, Position, Trigger } from '../tooltip/index';
3
+ import { ArrowBounding, Position, TooltipProps, Trigger, RenderContentProps } from '../tooltip/index';
4
4
  import '@douyinfe/semi-foundation/lib/es/popover/popover.css';
5
5
  import { BaseProps } from '../_base/baseComponent';
6
6
  import { Motion } from '../_base/base';
@@ -12,7 +12,7 @@ declare interface ArrowStyle {
12
12
  }
13
13
  export interface PopoverProps extends BaseProps {
14
14
  children?: React.ReactNode;
15
- content?: React.ReactNode;
15
+ content?: TooltipProps['content'];
16
16
  visible?: boolean;
17
17
  autoAdjustOverflow?: boolean;
18
18
  motion?: Motion;
@@ -33,6 +33,10 @@ export interface PopoverProps extends BaseProps {
33
33
  rePosKey?: string | number;
34
34
  getPopupContainer?: () => HTMLElement;
35
35
  zIndex?: number;
36
+ closeOnEsc?: TooltipProps['closeOnEsc'];
37
+ guardFocus?: TooltipProps['guardFocus'];
38
+ returnFocusOnClose?: TooltipProps['returnFocusOnClose'];
39
+ onEscKeyDown?: TooltipProps['onEscKeyDown'];
36
40
  }
37
41
  export interface PopoverState {
38
42
  popConfirmVisible: boolean;
@@ -64,6 +68,7 @@ declare class Popover extends React.PureComponent<PopoverProps, PopoverState> {
64
68
  arrowPointAtCenter: PropTypes.Requireable<boolean>;
65
69
  arrowBounding: PropTypes.Requireable<object>;
66
70
  prefixCls: PropTypes.Requireable<string>;
71
+ guardFocus: PropTypes.Requireable<boolean>;
67
72
  };
68
73
  static defaultProps: {
69
74
  arrowBounding: {
@@ -82,8 +87,18 @@ declare class Popover extends React.PureComponent<PopoverProps, PopoverState> {
82
87
  position: string;
83
88
  prefixCls: string;
84
89
  onClickOutSide: (...args: any[]) => void;
90
+ onEscKeyDown: (...args: any[]) => void;
91
+ closeOnEsc: boolean;
92
+ returnFocusOnClose: boolean;
93
+ guardFocus: boolean;
85
94
  };
86
- renderPopCard(): JSX.Element;
95
+ renderPopCard: ({ initialFocusRef }: {
96
+ initialFocusRef: RenderContentProps['initialFocusRef'];
97
+ }) => JSX.Element;
98
+ renderContentNode: (props: {
99
+ content: TooltipProps['content'];
100
+ initialFocusRef: RenderContentProps['initialFocusRef'];
101
+ }) => React.ReactNode;
87
102
  render(): JSX.Element;
88
103
  }
89
104
  export default Popover;
@@ -1,4 +1,5 @@
1
1
  import _noop from "lodash/noop";
2
+ import _isFunction from "lodash/isFunction";
2
3
  import _indexOfInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/index-of";
3
4
  import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols";
4
5
  import _Object$assign from "@babel/runtime-corejs3/core-js-stable/object/assign";
@@ -26,23 +27,45 @@ const positionSet = strings.POSITION_SET;
26
27
  const triggerSet = strings.TRIGGER_SET;
27
28
 
28
29
  class Popover extends React.PureComponent {
29
- renderPopCard() {
30
- const {
31
- content,
32
- contentClassName,
33
- prefixCls
34
- } = this.props;
35
- const {
36
- direction
37
- } = this.context;
38
- const popCardCls = classNames(prefixCls, contentClassName, {
39
- ["".concat(prefixCls, "-rtl")]: direction === 'rtl'
40
- });
41
- return /*#__PURE__*/React.createElement("div", {
42
- className: popCardCls
43
- }, /*#__PURE__*/React.createElement("div", {
44
- className: "".concat(prefixCls, "-content")
45
- }, content));
30
+ constructor() {
31
+ super(...arguments);
32
+
33
+ this.renderPopCard = _ref => {
34
+ let {
35
+ initialFocusRef
36
+ } = _ref;
37
+ const {
38
+ content,
39
+ contentClassName,
40
+ prefixCls
41
+ } = this.props;
42
+ const {
43
+ direction
44
+ } = this.context;
45
+ const popCardCls = classNames(prefixCls, contentClassName, {
46
+ ["".concat(prefixCls, "-rtl")]: direction === 'rtl'
47
+ });
48
+ const contentNode = this.renderContentNode({
49
+ initialFocusRef,
50
+ content
51
+ });
52
+ return /*#__PURE__*/React.createElement("div", {
53
+ className: popCardCls
54
+ }, /*#__PURE__*/React.createElement("div", {
55
+ className: "".concat(prefixCls, "-content")
56
+ }, contentNode));
57
+ };
58
+
59
+ this.renderContentNode = props => {
60
+ const {
61
+ initialFocusRef,
62
+ content
63
+ } = props;
64
+ const contentProps = {
65
+ initialFocusRef
66
+ };
67
+ return !_isFunction(content) ? content : content(contentProps);
68
+ };
46
69
  }
47
70
 
48
71
  render() {
@@ -62,7 +85,6 @@ class Popover extends React.PureComponent {
62
85
  let {
63
86
  spacing
64
87
  } = this.props;
65
- const popContent = this.renderPopCard();
66
88
  const arrowProps = {
67
89
  position,
68
90
  className: '',
@@ -76,11 +98,13 @@ class Popover extends React.PureComponent {
76
98
  }
77
99
 
78
100
  const role = trigger === 'click' || trigger === 'custom' ? 'dialog' : 'tooltip';
79
- return /*#__PURE__*/React.createElement(Tooltip, _Object$assign({}, attr, {
101
+ return /*#__PURE__*/React.createElement(Tooltip, _Object$assign({
102
+ guardFocus: true
103
+ }, attr, {
80
104
  trigger: trigger,
81
105
  position: position,
82
106
  style: style,
83
- content: popContent,
107
+ content: this.renderPopCard,
84
108
  prefixCls: prefixCls,
85
109
  spacing: spacing,
86
110
  showArrow: arrow,
@@ -94,7 +118,7 @@ class Popover extends React.PureComponent {
94
118
  Popover.contextType = ConfigContext;
95
119
  Popover.propTypes = {
96
120
  children: PropTypes.node,
97
- content: PropTypes.node,
121
+ content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
98
122
  visible: PropTypes.bool,
99
123
  autoAdjustOverflow: PropTypes.bool,
100
124
  motion: PropTypes.oneOfType([PropTypes.bool, PropTypes.object, PropTypes.func]),
@@ -117,7 +141,8 @@ Popover.propTypes = {
117
141
  }),
118
142
  arrowPointAtCenter: PropTypes.bool,
119
143
  arrowBounding: PropTypes.object,
120
- prefixCls: PropTypes.string
144
+ prefixCls: PropTypes.string,
145
+ guardFocus: PropTypes.bool
121
146
  };
122
147
  Popover.defaultProps = {
123
148
  arrowBounding: numbers.ARROW_BOUNDING,
@@ -130,6 +155,10 @@ Popover.defaultProps = {
130
155
  okText: 'Yes',
131
156
  position: 'bottom',
132
157
  prefixCls: cssClasses.PREFIX,
133
- onClickOutSide: _noop
158
+ onClickOutSide: _noop,
159
+ onEscKeyDown: _noop,
160
+ closeOnEsc: true,
161
+ returnFocusOnClose: true,
162
+ guardFocus: true
134
163
  };
135
164
  export default Popover;
@@ -32,6 +32,12 @@ class RadioGroup extends BaseComponent {
32
32
  }
33
33
 
34
34
  componentDidUpdate(prevProps) {
35
+ if (typeof prevProps.value === 'number' && isNaN(prevProps.value) && typeof this.props.value === 'number' && isNaN(this.props.value)) {
36
+ // `NaN === NaN` returns false, and this will fail the next if check
37
+ // therefore triggering an infinite loop
38
+ return;
39
+ }
40
+
35
41
  if (prevProps.value !== this.props.value) {
36
42
  this.foundation.handlePropValueChange(this.props.value);
37
43
  }
@@ -688,7 +688,9 @@ class Select extends BaseComponent {
688
688
  });
689
689
  }
690
690
 
691
- const tags = _mapInstanceProperty(selectedItems).call(selectedItems, (item, i) => {
691
+ const mapItems = maxTagCount ? _sliceInstanceProperty(selectedItems).call(selectedItems, 0, maxTagCount) : selectedItems; // no need to render rest tag when maxTagCount is setting
692
+
693
+ const tags = _mapInstanceProperty(mapItems).call(mapItems, (item, i) => {
692
694
  const label = item[0];
693
695
  const {
694
696
  value
@@ -747,12 +749,13 @@ class Select extends BaseComponent {
747
749
  const placeholderText = placeholder && !inputValue ? /*#__PURE__*/React.createElement("span", {
748
750
  className: spanCls
749
751
  }, placeholder) : null;
750
- const n = tags.length > maxTagCount ? maxTagCount : undefined;
752
+ const n = selectedItems.length > maxTagCount ? maxTagCount : undefined;
751
753
  const NotOneLine = !maxTagCount; // Multiple lines (that is, do not set maxTagCount), do not use TagGroup, directly traverse with Tag, otherwise Input cannot follow the correct position
752
754
 
753
755
  const tagContent = NotOneLine ? tags : /*#__PURE__*/React.createElement(TagGroup, {
754
756
  tagList: tags,
755
757
  maxTagCount: n,
758
+ restCount: maxTagCount ? selectedItems.length - maxTagCount : undefined,
756
759
  size: "large",
757
760
  mode: "custom"
758
761
  });
@@ -7,6 +7,7 @@ export interface TagGroupProps {
7
7
  style?: React.CSSProperties;
8
8
  className?: string;
9
9
  maxTagCount?: number;
10
+ restCount?: number;
10
11
  tagList?: (TagProps | React.ReactNode)[];
11
12
  size?: 'small' | 'large';
12
13
  showPopover?: boolean;
@@ -26,6 +27,7 @@ export default class TagGroup extends PureComponent<TagGroupProps> {
26
27
  style: PropTypes.Requireable<object>;
27
28
  className: PropTypes.Requireable<string>;
28
29
  maxTagCount: PropTypes.Requireable<number>;
30
+ restCount: PropTypes.Requireable<number>;
29
31
  tagList: PropTypes.Requireable<any[]>;
30
32
  size: PropTypes.Requireable<string>;
31
33
  mode: PropTypes.Requireable<string>;
@@ -46,9 +46,10 @@ export default class TagGroup extends PureComponent {
46
46
  renderMergeTags(tags) {
47
47
  const {
48
48
  maxTagCount,
49
- tagList
49
+ tagList,
50
+ restCount
50
51
  } = this.props;
51
- const n = tagList.length - maxTagCount;
52
+ const n = restCount ? restCount : tagList.length - maxTagCount;
52
53
  let renderTags = tags;
53
54
 
54
55
  const normalTags = _sliceInstanceProperty(tags).call(tags, 0, maxTagCount);
@@ -128,6 +129,7 @@ TagGroup.propTypes = {
128
129
  style: PropTypes.object,
129
130
  className: PropTypes.string,
130
131
  maxTagCount: PropTypes.number,
132
+ restCount: PropTypes.number,
131
133
  tagList: PropTypes.array,
132
134
  size: PropTypes.oneOf(tagSize),
133
135
  mode: PropTypes.string,