@douyinfe/semi-ui 2.7.0 → 2.8.0-beta.1
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.
- package/_base/_story/index.stories.js +2 -6
- package/_portal/_story/portal.stories.js +1 -5
- package/_utils/hooks/usePrevFocus.ts +1 -0
- package/_utils/index.ts +29 -1
- package/datePicker/_story/v2/FixDefaultPickerValue.jsx +31 -0
- package/datePicker/_story/v2/InsetInput.jsx +1 -1
- package/datePicker/_story/v2/index.js +1 -0
- package/datePicker/monthsGrid.tsx +3 -13
- package/dist/css/semi.css +30 -21
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +608 -284
- package/dist/umd/semi-ui.js.map +1 -1
- package/dist/umd/semi-ui.min.js +1 -1
- package/dist/umd/semi-ui.min.js.map +1 -1
- package/input/_story/input.stories.js +10 -1
- package/inputNumber/_story/inputNumber.stories.js +4 -0
- package/lib/cjs/_utils/hooks/usePrevFocus.js +1 -0
- package/lib/cjs/_utils/index.d.ts +3 -1
- package/lib/cjs/_utils/index.js +25 -1
- package/lib/cjs/datePicker/monthsGrid.js +11 -19
- package/lib/cjs/modal/useModal/HookModal.js +2 -0
- package/lib/cjs/notification/useNotification/index.js +1 -1
- package/lib/cjs/popover/index.d.ts +18 -3
- package/lib/cjs/popover/index.js +53 -23
- package/lib/cjs/tooltip/index.d.ts +22 -4
- package/lib/cjs/tooltip/index.js +65 -27
- package/lib/es/_utils/hooks/usePrevFocus.js +2 -0
- package/lib/es/_utils/index.d.ts +3 -1
- package/lib/es/_utils/index.js +18 -0
- package/lib/es/datePicker/monthsGrid.js +11 -19
- package/lib/es/modal/useModal/HookModal.js +2 -0
- package/lib/es/notification/useNotification/index.js +2 -1
- package/lib/es/popover/index.d.ts +18 -3
- package/lib/es/popover/index.js +52 -23
- package/lib/es/tooltip/index.d.ts +22 -4
- package/lib/es/tooltip/index.js +65 -27
- package/modal/_story/modal.stories.js +93 -1
- package/modal/useModal/HookModal.tsx +1 -0
- package/notification/_story/useNotification/index.jsx +21 -7
- package/notification/useNotification/index.tsx +1 -1
- package/package.json +9 -9
- package/popover/_story/popover.stories.js +75 -1
- package/popover/index.tsx +24 -8
- package/select/__test__/select.test.js +16 -0
- package/table/_story/v2/FixedMemoryLeak/index.jsx +33 -0
- package/table/_story/v2/index.js +2 -1
- package/toast/_story/toast.stories.js +41 -0
- package/tooltip/index.tsx +72 -22
package/lib/es/_utils/index.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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-
|
|
642
|
+
"x-insetinput": insetInput ? "true" : "false",
|
|
651
643
|
ref: current => this.cacheRefCurrent('monthGrid', current)
|
|
652
644
|
}, content);
|
|
653
645
|
}
|
|
@@ -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?:
|
|
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(
|
|
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;
|
package/lib/es/popover/index.js
CHANGED
|
@@ -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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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({
|
|
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:
|
|
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;
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Event from '@douyinfe/semi-foundation/lib/es/utils/Event';
|
|
4
4
|
import { ArrayElement } from '@douyinfe/semi-foundation/lib/es/utils/type';
|
|
5
|
-
import { TooltipAdapter, Position } from '@douyinfe/semi-foundation/lib/es/tooltip/foundation';
|
|
5
|
+
import TooltipFoundation, { TooltipAdapter, Position } from '@douyinfe/semi-foundation/lib/es/tooltip/foundation';
|
|
6
6
|
import { strings } from '@douyinfe/semi-foundation/lib/es/tooltip/constants';
|
|
7
7
|
import '@douyinfe/semi-foundation/lib/es/tooltip/tooltip.css';
|
|
8
8
|
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
@@ -15,6 +15,10 @@ export interface ArrowBounding {
|
|
|
15
15
|
width?: number;
|
|
16
16
|
height?: number;
|
|
17
17
|
}
|
|
18
|
+
export interface RenderContentProps {
|
|
19
|
+
initialFocusRef?: React.RefObject<HTMLElement>;
|
|
20
|
+
}
|
|
21
|
+
export declare type RenderContent = (props: RenderContentProps) => React.ReactNode;
|
|
18
22
|
export interface TooltipProps extends BaseProps {
|
|
19
23
|
children?: React.ReactNode;
|
|
20
24
|
motion?: Motion;
|
|
@@ -28,7 +32,7 @@ export interface TooltipProps extends BaseProps {
|
|
|
28
32
|
clickToHide?: boolean;
|
|
29
33
|
visible?: boolean;
|
|
30
34
|
style?: React.CSSProperties;
|
|
31
|
-
content?: React.ReactNode;
|
|
35
|
+
content?: React.ReactNode | RenderContent;
|
|
32
36
|
prefixCls?: string;
|
|
33
37
|
onVisibleChange?: (visible: boolean) => void;
|
|
34
38
|
onClickOutSide?: (e: React.MouseEvent) => void;
|
|
@@ -44,6 +48,10 @@ export interface TooltipProps extends BaseProps {
|
|
|
44
48
|
stopPropagation?: boolean;
|
|
45
49
|
clickTriggerToHide?: boolean;
|
|
46
50
|
wrapperClassName?: string;
|
|
51
|
+
closeOnEsc?: boolean;
|
|
52
|
+
guardFocus?: boolean;
|
|
53
|
+
returnFocusOnClose?: boolean;
|
|
54
|
+
onEscKeyDown?: (e: React.KeyboardEvent) => void;
|
|
47
55
|
}
|
|
48
56
|
interface TooltipState {
|
|
49
57
|
visible: boolean;
|
|
@@ -97,6 +105,8 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
97
105
|
stopPropagation: PropTypes.Requireable<boolean>;
|
|
98
106
|
role: PropTypes.Requireable<string>;
|
|
99
107
|
wrapWhenSpecial: PropTypes.Requireable<boolean>;
|
|
108
|
+
guardFocus: PropTypes.Requireable<boolean>;
|
|
109
|
+
returnFocusOnClose: PropTypes.Requireable<boolean>;
|
|
100
110
|
};
|
|
101
111
|
static defaultProps: {
|
|
102
112
|
arrowBounding: {
|
|
@@ -121,10 +131,15 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
121
131
|
showArrow: boolean;
|
|
122
132
|
wrapWhenSpecial: boolean;
|
|
123
133
|
zIndex: 1060;
|
|
134
|
+
closeOnEsc: boolean;
|
|
135
|
+
guardFocus: boolean;
|
|
136
|
+
returnFocusOnClose: boolean;
|
|
137
|
+
onEscKeyDown: (...args: any[]) => void;
|
|
124
138
|
};
|
|
125
139
|
eventManager: Event;
|
|
126
140
|
triggerEl: React.RefObject<unknown>;
|
|
127
|
-
containerEl: React.RefObject<
|
|
141
|
+
containerEl: React.RefObject<HTMLDivElement>;
|
|
142
|
+
initialFocusRef: React.RefObject<HTMLElement>;
|
|
128
143
|
clickOutsideHandler: any;
|
|
129
144
|
resizeHandler: any;
|
|
130
145
|
isWrapped: boolean;
|
|
@@ -132,6 +147,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
132
147
|
scrollHandler: any;
|
|
133
148
|
getPopupContainer: () => HTMLElement;
|
|
134
149
|
containerPosition: string;
|
|
150
|
+
foundation: TooltipFoundation;
|
|
135
151
|
constructor(props: TooltipProps);
|
|
136
152
|
setContainerEl: (node: HTMLDivElement) => {
|
|
137
153
|
current: HTMLDivElement;
|
|
@@ -142,10 +158,12 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
142
158
|
isSpecial: (elem: React.ReactNode | HTMLElement | any) => boolean | "disabled" | "loading";
|
|
143
159
|
didLeave: () => void;
|
|
144
160
|
/** for transition - end */
|
|
145
|
-
rePosition():
|
|
161
|
+
rePosition(): Record<string, string | number>;
|
|
146
162
|
componentDidUpdate(prevProps: TooltipProps, prevState: TooltipState): void;
|
|
147
163
|
renderIcon: () => any;
|
|
148
164
|
handlePortalInnerClick: (e: React.MouseEvent) => void;
|
|
165
|
+
handlePortalInnerKeyDown: (e: React.KeyboardEvent) => void;
|
|
166
|
+
renderContentNode: (content: TooltipProps['content']) => React.ReactNode;
|
|
149
167
|
renderPortal: () => JSX.Element;
|
|
150
168
|
wrapSpan: (elem: React.ReactNode | React.ReactElement) => JSX.Element;
|
|
151
169
|
mergeEvents: (rawEvents: Record<string, any>, events: Record<string, any>) => {};
|
package/lib/es/tooltip/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _isFunction from "lodash/isFunction";
|
|
1
2
|
import _isEmpty from "lodash/isEmpty";
|
|
2
3
|
import _each from "lodash/each";
|
|
3
4
|
import _omit from "lodash/omit";
|
|
@@ -37,7 +38,7 @@ import { getUuidShort } from '@douyinfe/semi-foundation/lib/es/utils/uuid';
|
|
|
37
38
|
import '@douyinfe/semi-foundation/lib/es/tooltip/tooltip.css';
|
|
38
39
|
import BaseComponent from '../_base/baseComponent';
|
|
39
40
|
import { isHTMLElement } from '../_base/reactUtils';
|
|
40
|
-
import { stopPropagation } from '../_utils';
|
|
41
|
+
import { getActiveElement, getFocusableElements, stopPropagation } from '../_utils';
|
|
41
42
|
import Portal from '../_portal/index';
|
|
42
43
|
import ConfigContext from '../configProvider/context';
|
|
43
44
|
import TriangleArrow from './TriangleArrow';
|
|
@@ -137,6 +138,17 @@ export default class Tooltip extends BaseComponent {
|
|
|
137
138
|
}
|
|
138
139
|
};
|
|
139
140
|
|
|
141
|
+
this.handlePortalInnerKeyDown = e => {
|
|
142
|
+
this.foundation.handleContainerKeydown(e);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
this.renderContentNode = content => {
|
|
146
|
+
const contentProps = {
|
|
147
|
+
initialFocusRef: this.initialFocusRef
|
|
148
|
+
};
|
|
149
|
+
return !_isFunction(content) ? content : content(contentProps);
|
|
150
|
+
};
|
|
151
|
+
|
|
140
152
|
this.renderPortal = () => {
|
|
141
153
|
const {
|
|
142
154
|
containerStyle = {},
|
|
@@ -156,6 +168,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
156
168
|
role,
|
|
157
169
|
zIndex
|
|
158
170
|
} = this.props;
|
|
171
|
+
const contentNode = this.renderContentNode(content);
|
|
159
172
|
const {
|
|
160
173
|
className: propClassName
|
|
161
174
|
} = this.props;
|
|
@@ -193,7 +206,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
193
206
|
role: role,
|
|
194
207
|
"x-placement": placement,
|
|
195
208
|
id: id
|
|
196
|
-
}),
|
|
209
|
+
}), contentNode, icon);
|
|
197
210
|
} : null) : /*#__PURE__*/React.createElement("div", _Object$assign({
|
|
198
211
|
className: className
|
|
199
212
|
}, portalEventSet, {
|
|
@@ -201,7 +214,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
201
214
|
style: _Object$assign({
|
|
202
215
|
visibility: motion ? undefined : 'visible'
|
|
203
216
|
}, style)
|
|
204
|
-
}),
|
|
217
|
+
}), contentNode, icon);
|
|
205
218
|
return /*#__PURE__*/React.createElement(Portal, {
|
|
206
219
|
getPopupContainer: this.props.getPopupContainer,
|
|
207
220
|
style: {
|
|
@@ -211,7 +224,8 @@ export default class Tooltip extends BaseComponent {
|
|
|
211
224
|
className: "".concat(BASE_CLASS_PREFIX, "-portal-inner"),
|
|
212
225
|
style: portalInnerStyle,
|
|
213
226
|
ref: this.setContainerEl,
|
|
214
|
-
onClick: this.handlePortalInnerClick
|
|
227
|
+
onClick: this.handlePortalInnerClick,
|
|
228
|
+
onKeyDown: this.handlePortalInnerKeyDown
|
|
215
229
|
}, inner));
|
|
216
230
|
};
|
|
217
231
|
|
|
@@ -279,6 +293,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
279
293
|
this.eventManager = new Event();
|
|
280
294
|
this.triggerEl = /*#__PURE__*/React.createRef();
|
|
281
295
|
this.containerEl = /*#__PURE__*/React.createRef();
|
|
296
|
+
this.initialFocusRef = /*#__PURE__*/React.createRef();
|
|
282
297
|
this.clickOutsideHandler = null;
|
|
283
298
|
this.resizeHandler = null;
|
|
284
299
|
this.isWrapped = false; // Identifies whether a span element is wrapped
|
|
@@ -330,7 +345,8 @@ export default class Tooltip extends BaseComponent {
|
|
|
330
345
|
mouseOver: 'onMouseOver',
|
|
331
346
|
click: 'onClick',
|
|
332
347
|
focus: 'onFocus',
|
|
333
|
-
blur: 'onBlur'
|
|
348
|
+
blur: 'onBlur',
|
|
349
|
+
keydown: 'onKeyDown'
|
|
334
350
|
}),
|
|
335
351
|
registerTriggerEvent: triggerEventSet => {
|
|
336
352
|
this.setState({
|
|
@@ -348,14 +364,8 @@ export default class Tooltip extends BaseComponent {
|
|
|
348
364
|
// eslint-disable-next-line
|
|
349
365
|
// It may be a React component or an html element
|
|
350
366
|
// 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
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (!isHTMLElement(this.triggerEl.current)) {
|
|
354
|
-
const realDomNode = ReactDOM.findDOMNode(this.triggerEl.current);
|
|
355
|
-
this.triggerEl.current = realDomNode;
|
|
356
|
-
triggerDOM = realDomNode;
|
|
357
|
-
}
|
|
358
|
-
|
|
367
|
+
const triggerDOM = this.adapter.getTriggerNode();
|
|
368
|
+
this.triggerEl.current = triggerDOM;
|
|
359
369
|
return triggerDOM && triggerDOM.getBoundingClientRect();
|
|
360
370
|
},
|
|
361
371
|
// Gets the outer size of the specified container
|
|
@@ -422,7 +432,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
422
432
|
willUpdateStates.visible = visible;
|
|
423
433
|
}
|
|
424
434
|
|
|
425
|
-
this.setState(willUpdateStates, () => {
|
|
435
|
+
this.mounted && this.setState(willUpdateStates, () => {
|
|
426
436
|
cb();
|
|
427
437
|
});
|
|
428
438
|
},
|
|
@@ -492,12 +502,7 @@ export default class Tooltip extends BaseComponent {
|
|
|
492
502
|
return false;
|
|
493
503
|
}
|
|
494
504
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
if (!isHTMLElement(this.triggerEl.current)) {
|
|
498
|
-
triggerDOM = ReactDOM.findDOMNode(this.triggerEl.current);
|
|
499
|
-
}
|
|
500
|
-
|
|
505
|
+
const triggerDOM = this.adapter.getTriggerNode();
|
|
501
506
|
const isRelativeScroll = e.target.contains(triggerDOM);
|
|
502
507
|
|
|
503
508
|
if (isRelativeScroll) {
|
|
@@ -528,7 +533,33 @@ export default class Tooltip extends BaseComponent {
|
|
|
528
533
|
this.containerPosition = position;
|
|
529
534
|
}
|
|
530
535
|
},
|
|
531
|
-
getContainerPosition: () => this.containerPosition
|
|
536
|
+
getContainerPosition: () => this.containerPosition,
|
|
537
|
+
getContainer: () => this.containerEl && this.containerEl.current,
|
|
538
|
+
getTriggerNode: () => {
|
|
539
|
+
let triggerDOM = this.triggerEl.current;
|
|
540
|
+
|
|
541
|
+
if (!isHTMLElement(this.triggerEl.current)) {
|
|
542
|
+
triggerDOM = ReactDOM.findDOMNode(this.triggerEl.current);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return triggerDOM;
|
|
546
|
+
},
|
|
547
|
+
getFocusableElements: node => {
|
|
548
|
+
return getFocusableElements(node);
|
|
549
|
+
},
|
|
550
|
+
getActiveElement: () => {
|
|
551
|
+
return getActiveElement();
|
|
552
|
+
},
|
|
553
|
+
setInitialFocus: () => {
|
|
554
|
+
const focusRefNode = _get(this, 'initialFocusRef.current');
|
|
555
|
+
|
|
556
|
+
if (focusRefNode && 'focus' in focusRefNode) {
|
|
557
|
+
focusRefNode.focus();
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
notifyEscKeydown: event => {
|
|
561
|
+
this.props.onEscKeyDown(event);
|
|
562
|
+
}
|
|
532
563
|
});
|
|
533
564
|
}
|
|
534
565
|
|
|
@@ -570,7 +601,8 @@ export default class Tooltip extends BaseComponent {
|
|
|
570
601
|
} = this.state;
|
|
571
602
|
const {
|
|
572
603
|
wrapWhenSpecial,
|
|
573
|
-
role
|
|
604
|
+
role,
|
|
605
|
+
trigger
|
|
574
606
|
} = this.props;
|
|
575
607
|
let {
|
|
576
608
|
children
|
|
@@ -630,7 +662,8 @@ export default class Tooltip extends BaseComponent {
|
|
|
630
662
|
} else if (ref && typeof ref === 'object') {
|
|
631
663
|
ref.current = node;
|
|
632
664
|
}
|
|
633
|
-
}
|
|
665
|
+
},
|
|
666
|
+
tabIndex: trigger === 'hover' ? 0 : undefined
|
|
634
667
|
})); // 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
|
|
635
668
|
// So if the user adds ref to the content, you need to use callback ref: https://github.com/facebook/react/issues/8873
|
|
636
669
|
|
|
@@ -655,7 +688,7 @@ Tooltip.propTypes = {
|
|
|
655
688
|
clickTriggerToHide: PropTypes.bool,
|
|
656
689
|
visible: PropTypes.bool,
|
|
657
690
|
style: PropTypes.object,
|
|
658
|
-
content: PropTypes.node,
|
|
691
|
+
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
659
692
|
prefixCls: PropTypes.string,
|
|
660
693
|
onVisibleChange: PropTypes.func,
|
|
661
694
|
onClickOutSide: PropTypes.func,
|
|
@@ -669,8 +702,9 @@ Tooltip.propTypes = {
|
|
|
669
702
|
stopPropagation: PropTypes.bool,
|
|
670
703
|
// private
|
|
671
704
|
role: PropTypes.string,
|
|
672
|
-
wrapWhenSpecial: PropTypes.bool
|
|
673
|
-
|
|
705
|
+
wrapWhenSpecial: PropTypes.bool,
|
|
706
|
+
guardFocus: PropTypes.bool,
|
|
707
|
+
returnFocusOnClose: PropTypes.bool
|
|
674
708
|
};
|
|
675
709
|
Tooltip.defaultProps = {
|
|
676
710
|
arrowBounding: numbers.ARROW_BOUNDING,
|
|
@@ -689,5 +723,9 @@ Tooltip.defaultProps = {
|
|
|
689
723
|
spacing: numbers.SPACING,
|
|
690
724
|
showArrow: true,
|
|
691
725
|
wrapWhenSpecial: true,
|
|
692
|
-
zIndex: numbers.DEFAULT_Z_INDEX
|
|
726
|
+
zIndex: numbers.DEFAULT_Z_INDEX,
|
|
727
|
+
closeOnEsc: false,
|
|
728
|
+
guardFocus: false,
|
|
729
|
+
returnFocusOnClose: false,
|
|
730
|
+
onEscKeyDown: _noop
|
|
693
731
|
};
|