@douyinfe/semi-ui 2.7.1 → 2.8.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.
- 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 +25 -16
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +654 -309
- 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/inputNumber/_story/inputNumber.stories.js +4 -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/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 +64 -26
- 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/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 +64 -26
- package/notification/useNotification/index.tsx +1 -1
- package/package.json +10 -10
- package/popover/_story/popover.stories.js +75 -1
- package/popover/index.tsx +24 -8
- package/select/__test__/select.test.js +16 -0
- package/tooltip/index.tsx +71 -21
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import Popover from '../index';
|
|
4
4
|
import { strings } from '@douyinfe/semi-foundation/tooltip/constants';
|
|
5
|
-
import { Button, Input, Table, IconButton, Modal, Tag } from '@douyinfe/semi-ui';
|
|
5
|
+
import { Button, Input, Table, IconButton, Modal, Tag, Space } from '@douyinfe/semi-ui';
|
|
6
6
|
import SelectInPopover from './SelectInPopover';
|
|
7
7
|
import BtnClose from './BtnClose';
|
|
8
8
|
import PopRight from './PopRight';
|
|
@@ -572,3 +572,77 @@ export const ArrowPointAtCenterDemo = () => <ArrowPointAtCenter />;
|
|
|
572
572
|
ArrowPointAtCenterDemo.story = {
|
|
573
573
|
name: 'arrow point at center'
|
|
574
574
|
}
|
|
575
|
+
|
|
576
|
+
export const A11yKeyboard = () => {
|
|
577
|
+
const [visible, setVisible] = React.useState(false);
|
|
578
|
+
const popStyle = { height: 200, width: 200 };
|
|
579
|
+
|
|
580
|
+
const renderContent = ({ initialFocusRef }) => {
|
|
581
|
+
return (
|
|
582
|
+
<div style={popStyle} data-cy="pop">
|
|
583
|
+
<button data-cy="pop-focusable-first">first focusable</button>
|
|
584
|
+
<a href="https://semi.design">link</a>
|
|
585
|
+
{/* <input ref={initialFocusRef} placeholder="init focus" /> */}
|
|
586
|
+
<input placeholder="" defaultValue="semi" />
|
|
587
|
+
<a href="https://semi.design">link2</a>
|
|
588
|
+
<button data-cy="pop-focusable-last">last focusable</button>
|
|
589
|
+
</div>
|
|
590
|
+
);
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
const noFocusableContent = (
|
|
594
|
+
<div style={popStyle}>没有可聚焦元素</div>
|
|
595
|
+
);
|
|
596
|
+
|
|
597
|
+
const initFocusContent = ({ initialFocusRef }) => {
|
|
598
|
+
return (
|
|
599
|
+
<div style={popStyle} data-cy="pop">
|
|
600
|
+
<button data-cy="pop-focusable-first">first focusable</button>
|
|
601
|
+
<input placeholder="" defaultValue="semi" ref={initialFocusRef} data-cy="initial-focus-input" />
|
|
602
|
+
<button data-cy="pop-focusable-last">last focusable</button>
|
|
603
|
+
</div>
|
|
604
|
+
);
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
return (
|
|
608
|
+
<div style={{ paddingLeft: 100, paddingTop: 100 }}>
|
|
609
|
+
<Space spacing={100}>
|
|
610
|
+
<Popover content={renderContent} trigger="click" motion={false}>
|
|
611
|
+
<Button data-cy="click">click</Button>
|
|
612
|
+
</Popover>
|
|
613
|
+
<Popover content={renderContent} trigger="hover">
|
|
614
|
+
<span data-cy="hover">hover</span>
|
|
615
|
+
</Popover>
|
|
616
|
+
<Popover content={renderContent} trigger="focus">
|
|
617
|
+
<Input data-cy="focus" defaultValue="focus" style={{ width: 150 }} />
|
|
618
|
+
</Popover>
|
|
619
|
+
<Popover
|
|
620
|
+
content={renderContent}
|
|
621
|
+
trigger="custom"
|
|
622
|
+
visible={visible}
|
|
623
|
+
onEscKeyDown={() => {
|
|
624
|
+
console.log('esc key down');
|
|
625
|
+
setVisible(false);
|
|
626
|
+
}}
|
|
627
|
+
>
|
|
628
|
+
<Button onClick={() => setVisible(!visible)} data-cy="custom">
|
|
629
|
+
custom trigger + click me toggle show
|
|
630
|
+
</Button>
|
|
631
|
+
</Popover>
|
|
632
|
+
<Popover content={noFocusableContent} trigger="click" data-cy="click-pop-contains-no-focusable">
|
|
633
|
+
<Button>pop内没有可聚焦元素</Button>
|
|
634
|
+
</Popover>
|
|
635
|
+
<Popover content={initFocusContent} trigger="click" motion={false}>
|
|
636
|
+
<Button data-cy="initial-focus">custom initialFocus</Button>
|
|
637
|
+
</Popover>
|
|
638
|
+
<Popover content={renderContent} trigger="click" motion={false} closeOnEsc={false}>
|
|
639
|
+
<Button data-cy="closeOnEsc-false">closeOnEsc=false</Button>
|
|
640
|
+
</Popover>
|
|
641
|
+
<Popover content={renderContent} trigger="click" motion={false} returnFocusOnClose={false}>
|
|
642
|
+
<Button data-cy="returnFocusOnClose-false">returnFocusOnClose=false</Button>
|
|
643
|
+
</Popover>
|
|
644
|
+
</Space>
|
|
645
|
+
</div>
|
|
646
|
+
);
|
|
647
|
+
};
|
|
648
|
+
A11yKeyboard.storyName = "a11y keyboard and focus";
|
package/popover/index.tsx
CHANGED
|
@@ -3,12 +3,12 @@ import classNames from 'classnames';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import ConfigContext from '../configProvider/context';
|
|
5
5
|
import { cssClasses, strings, numbers } from '@douyinfe/semi-foundation/popover/constants';
|
|
6
|
-
import Tooltip, { ArrowBounding, Position, Trigger } from '../tooltip/index';
|
|
6
|
+
import Tooltip, { ArrowBounding, Position, TooltipProps, Trigger, RenderContentProps } from '../tooltip/index';
|
|
7
7
|
import Arrow from './Arrow';
|
|
8
8
|
import '@douyinfe/semi-foundation/popover/popover.scss';
|
|
9
9
|
import { BaseProps } from '../_base/baseComponent';
|
|
10
10
|
import { Motion } from '../_base/base';
|
|
11
|
-
import { noop } from 'lodash';
|
|
11
|
+
import { isFunction, noop } from 'lodash';
|
|
12
12
|
|
|
13
13
|
export { ArrowProps } from './Arrow';
|
|
14
14
|
declare interface ArrowStyle {
|
|
@@ -19,7 +19,7 @@ declare interface ArrowStyle {
|
|
|
19
19
|
|
|
20
20
|
export interface PopoverProps extends BaseProps {
|
|
21
21
|
children?: React.ReactNode;
|
|
22
|
-
content?:
|
|
22
|
+
content?: TooltipProps['content'];
|
|
23
23
|
visible?: boolean;
|
|
24
24
|
autoAdjustOverflow?: boolean;
|
|
25
25
|
motion?: Motion;
|
|
@@ -40,6 +40,10 @@ export interface PopoverProps extends BaseProps {
|
|
|
40
40
|
rePosKey?: string | number;
|
|
41
41
|
getPopupContainer?: () => HTMLElement;
|
|
42
42
|
zIndex?: number;
|
|
43
|
+
closeOnEsc?: TooltipProps['closeOnEsc'];
|
|
44
|
+
guardFocus?: TooltipProps['guardFocus'];
|
|
45
|
+
returnFocusOnClose?: TooltipProps['returnFocusOnClose'];
|
|
46
|
+
onEscKeyDown?: TooltipProps['onEscKeyDown'];
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export interface PopoverState {
|
|
@@ -52,7 +56,7 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
52
56
|
static contextType = ConfigContext;
|
|
53
57
|
static propTypes = {
|
|
54
58
|
children: PropTypes.node,
|
|
55
|
-
content: PropTypes.node,
|
|
59
|
+
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
56
60
|
visible: PropTypes.bool,
|
|
57
61
|
autoAdjustOverflow: PropTypes.bool,
|
|
58
62
|
motion: PropTypes.oneOfType([PropTypes.bool, PropTypes.object, PropTypes.func]),
|
|
@@ -76,6 +80,7 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
76
80
|
arrowPointAtCenter: PropTypes.bool,
|
|
77
81
|
arrowBounding: PropTypes.object,
|
|
78
82
|
prefixCls: PropTypes.string,
|
|
83
|
+
guardFocus: PropTypes.bool,
|
|
79
84
|
};
|
|
80
85
|
|
|
81
86
|
static defaultProps = {
|
|
@@ -90,9 +95,13 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
90
95
|
position: 'bottom',
|
|
91
96
|
prefixCls: cssClasses.PREFIX,
|
|
92
97
|
onClickOutSide: noop,
|
|
98
|
+
onEscKeyDown: noop,
|
|
99
|
+
closeOnEsc: true,
|
|
100
|
+
returnFocusOnClose: true,
|
|
101
|
+
guardFocus: true,
|
|
93
102
|
};
|
|
94
103
|
|
|
95
|
-
renderPopCard() {
|
|
104
|
+
renderPopCard = ({ initialFocusRef }: { initialFocusRef: RenderContentProps['initialFocusRef'] }) => {
|
|
96
105
|
const { content, contentClassName, prefixCls } = this.props;
|
|
97
106
|
const { direction } = this.context;
|
|
98
107
|
const popCardCls = classNames(
|
|
@@ -102,13 +111,20 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
102
111
|
[`${prefixCls}-rtl`]: direction === 'rtl',
|
|
103
112
|
}
|
|
104
113
|
);
|
|
114
|
+
const contentNode = this.renderContentNode({ initialFocusRef, content });
|
|
105
115
|
return (
|
|
106
116
|
<div className={popCardCls}>
|
|
107
|
-
<div className={`${prefixCls}-content`}>{
|
|
117
|
+
<div className={`${prefixCls}-content`}>{contentNode}</div>
|
|
108
118
|
</div>
|
|
109
119
|
);
|
|
110
120
|
}
|
|
111
121
|
|
|
122
|
+
renderContentNode = (props: { content: TooltipProps['content'], initialFocusRef: RenderContentProps['initialFocusRef'] }) => {
|
|
123
|
+
const { initialFocusRef, content } = props;
|
|
124
|
+
const contentProps = { initialFocusRef };
|
|
125
|
+
return !isFunction(content) ? content : content(contentProps);
|
|
126
|
+
};
|
|
127
|
+
|
|
112
128
|
render() {
|
|
113
129
|
const {
|
|
114
130
|
children,
|
|
@@ -122,7 +138,6 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
122
138
|
...attr
|
|
123
139
|
} = this.props;
|
|
124
140
|
let { spacing } = this.props;
|
|
125
|
-
const popContent = this.renderPopCard();
|
|
126
141
|
|
|
127
142
|
const arrowProps = {
|
|
128
143
|
position,
|
|
@@ -141,11 +156,12 @@ class Popover extends React.PureComponent<PopoverProps, PopoverState> {
|
|
|
141
156
|
|
|
142
157
|
return (
|
|
143
158
|
<Tooltip
|
|
159
|
+
guardFocus
|
|
144
160
|
{...(attr as any)}
|
|
145
161
|
trigger={trigger}
|
|
146
162
|
position={position}
|
|
147
163
|
style={style}
|
|
148
|
-
content={
|
|
164
|
+
content={this.renderPopCard}
|
|
149
165
|
prefixCls={prefixCls}
|
|
150
166
|
spacing={spacing}
|
|
151
167
|
showArrow={arrow}
|
|
@@ -504,6 +504,22 @@ describe('Select', () => {
|
|
|
504
504
|
expect(optionList.at(0).text()).toEqual('Abc');
|
|
505
505
|
});
|
|
506
506
|
|
|
507
|
+
it('filter = true,label includes regex special character and key it at first', () => {
|
|
508
|
+
let props = {
|
|
509
|
+
filter: true,
|
|
510
|
+
optionList: [{label: 'label++',value: ''}]
|
|
511
|
+
};
|
|
512
|
+
const select = getSelect(props);
|
|
513
|
+
// click to show input
|
|
514
|
+
select.find(`.${BASE_CLASS_PREFIX}-select`).simulate('click', {});
|
|
515
|
+
let inputValue = '+';
|
|
516
|
+
let event = { target: { value: inputValue } };
|
|
517
|
+
select.find('input').simulate('change', event);
|
|
518
|
+
let optionList = select.find(`.${BASE_CLASS_PREFIX}-select-option-list`).children();
|
|
519
|
+
expect(optionList.length).toEqual(1);
|
|
520
|
+
expect(optionList.at(0).text()).toEqual('label++');
|
|
521
|
+
});
|
|
522
|
+
|
|
507
523
|
it('filter = custom function', () => {
|
|
508
524
|
let customFilter = (sugInput, option) => {
|
|
509
525
|
return option.label == 'Hotsoon';
|
package/tooltip/index.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import React, { isValidElement, cloneElement } from 'react';
|
|
|
3
3
|
import ReactDOM from 'react-dom';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
|
-
import { throttle, noop, get, omit, each, isEmpty } from 'lodash';
|
|
6
|
+
import { throttle, noop, get, omit, each, isEmpty, isFunction } from 'lodash';
|
|
7
7
|
|
|
8
8
|
import { BASE_CLASS_PREFIX } from '@douyinfe/semi-foundation/base/constants';
|
|
9
9
|
import warning from '@douyinfe/semi-foundation/utils/warning';
|
|
@@ -17,7 +17,7 @@ import '@douyinfe/semi-foundation/tooltip/tooltip.scss';
|
|
|
17
17
|
|
|
18
18
|
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
19
19
|
import { isHTMLElement } from '../_base/reactUtils';
|
|
20
|
-
import { stopPropagation } from '../_utils';
|
|
20
|
+
import { getActiveElement, getFocusableElements, stopPropagation } from '../_utils';
|
|
21
21
|
import Portal from '../_portal/index';
|
|
22
22
|
import ConfigContext from '../configProvider/context';
|
|
23
23
|
import TriangleArrow from './TriangleArrow';
|
|
@@ -36,6 +36,12 @@ export interface ArrowBounding {
|
|
|
36
36
|
height?: number;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export interface RenderContentProps {
|
|
40
|
+
initialFocusRef?: React.RefObject<HTMLElement>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type RenderContent = (props: RenderContentProps) => React.ReactNode;
|
|
44
|
+
|
|
39
45
|
export interface TooltipProps extends BaseProps {
|
|
40
46
|
children?: React.ReactNode;
|
|
41
47
|
motion?: Motion;
|
|
@@ -49,7 +55,7 @@ export interface TooltipProps extends BaseProps {
|
|
|
49
55
|
clickToHide?: boolean;
|
|
50
56
|
visible?: boolean;
|
|
51
57
|
style?: React.CSSProperties;
|
|
52
|
-
content?: React.ReactNode;
|
|
58
|
+
content?: React.ReactNode | RenderContent;
|
|
53
59
|
prefixCls?: string;
|
|
54
60
|
onVisibleChange?: (visible: boolean) => void;
|
|
55
61
|
onClickOutSide?: (e: React.MouseEvent) => void;
|
|
@@ -65,6 +71,10 @@ export interface TooltipProps extends BaseProps {
|
|
|
65
71
|
stopPropagation?: boolean;
|
|
66
72
|
clickTriggerToHide?: boolean;
|
|
67
73
|
wrapperClassName?: string;
|
|
74
|
+
closeOnEsc?: boolean;
|
|
75
|
+
guardFocus?: boolean;
|
|
76
|
+
returnFocusOnClose?: boolean;
|
|
77
|
+
onEscKeyDown?: (e: React.KeyboardEvent) => void;
|
|
68
78
|
}
|
|
69
79
|
interface TooltipState {
|
|
70
80
|
visible: boolean;
|
|
@@ -108,7 +118,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
108
118
|
clickTriggerToHide: PropTypes.bool,
|
|
109
119
|
visible: PropTypes.bool,
|
|
110
120
|
style: PropTypes.object,
|
|
111
|
-
content: PropTypes.node,
|
|
121
|
+
content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
112
122
|
prefixCls: PropTypes.string,
|
|
113
123
|
onVisibleChange: PropTypes.func,
|
|
114
124
|
onClickOutSide: PropTypes.func,
|
|
@@ -123,6 +133,8 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
123
133
|
// private
|
|
124
134
|
role: PropTypes.string,
|
|
125
135
|
wrapWhenSpecial: PropTypes.bool, // when trigger has special status such as "disabled" or "loading", wrap span
|
|
136
|
+
guardFocus: PropTypes.bool,
|
|
137
|
+
returnFocusOnClose: PropTypes.bool,
|
|
126
138
|
};
|
|
127
139
|
|
|
128
140
|
static defaultProps = {
|
|
@@ -143,11 +155,16 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
143
155
|
showArrow: true,
|
|
144
156
|
wrapWhenSpecial: true,
|
|
145
157
|
zIndex: numbers.DEFAULT_Z_INDEX,
|
|
158
|
+
closeOnEsc: false,
|
|
159
|
+
guardFocus: false,
|
|
160
|
+
returnFocusOnClose: false,
|
|
161
|
+
onEscKeyDown: noop,
|
|
146
162
|
};
|
|
147
163
|
|
|
148
164
|
eventManager: Event;
|
|
149
165
|
triggerEl: React.RefObject<unknown>;
|
|
150
|
-
containerEl: React.RefObject<
|
|
166
|
+
containerEl: React.RefObject<HTMLDivElement>;
|
|
167
|
+
initialFocusRef: React.RefObject<HTMLElement>;
|
|
151
168
|
clickOutsideHandler: any;
|
|
152
169
|
resizeHandler: any;
|
|
153
170
|
isWrapped: boolean;
|
|
@@ -155,6 +172,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
155
172
|
scrollHandler: any;
|
|
156
173
|
getPopupContainer: () => HTMLElement;
|
|
157
174
|
containerPosition: string;
|
|
175
|
+
foundation: TooltipFoundation;
|
|
158
176
|
|
|
159
177
|
constructor(props: TooltipProps) {
|
|
160
178
|
super(props);
|
|
@@ -180,6 +198,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
180
198
|
this.eventManager = new Event();
|
|
181
199
|
this.triggerEl = React.createRef();
|
|
182
200
|
this.containerEl = React.createRef();
|
|
201
|
+
this.initialFocusRef = React.createRef();
|
|
183
202
|
this.clickOutsideHandler = null;
|
|
184
203
|
this.resizeHandler = null;
|
|
185
204
|
this.isWrapped = false; // Identifies whether a span element is wrapped
|
|
@@ -197,7 +216,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
197
216
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
198
217
|
// @ts-ignore
|
|
199
218
|
off: (...args: any[]) => this.eventManager.off(...args),
|
|
200
|
-
insertPortal: (content:
|
|
219
|
+
insertPortal: (content: TooltipProps['content'], { position, ...containerStyle }: { position: Position }) => {
|
|
201
220
|
this.setState(
|
|
202
221
|
{
|
|
203
222
|
isInsert: true,
|
|
@@ -223,6 +242,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
223
242
|
click: 'onClick',
|
|
224
243
|
focus: 'onFocus',
|
|
225
244
|
blur: 'onBlur',
|
|
245
|
+
keydown: 'onKeyDown'
|
|
226
246
|
}),
|
|
227
247
|
registerTriggerEvent: (triggerEventSet: Record<string, any>) => {
|
|
228
248
|
this.setState({ triggerEventSet });
|
|
@@ -236,12 +256,8 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
236
256
|
// eslint-disable-next-line
|
|
237
257
|
// It may be a React component or an html element
|
|
238
258
|
// 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
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const realDomNode = ReactDOM.findDOMNode(this.triggerEl.current as React.ReactInstance);
|
|
242
|
-
(this.triggerEl as any).current = realDomNode;
|
|
243
|
-
triggerDOM = realDomNode;
|
|
244
|
-
}
|
|
259
|
+
const triggerDOM = this.adapter.getTriggerNode();
|
|
260
|
+
(this.triggerEl as any).current = triggerDOM;
|
|
245
261
|
return triggerDOM && (triggerDOM as Element).getBoundingClientRect();
|
|
246
262
|
},
|
|
247
263
|
// Gets the outer size of the specified container
|
|
@@ -317,7 +333,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
317
333
|
let el = this.triggerEl && this.triggerEl.current;
|
|
318
334
|
let popupEl = this.containerEl && this.containerEl.current;
|
|
319
335
|
el = ReactDOM.findDOMNode(el as React.ReactInstance);
|
|
320
|
-
popupEl = ReactDOM.findDOMNode(popupEl as React.ReactInstance);
|
|
336
|
+
popupEl = ReactDOM.findDOMNode(popupEl as React.ReactInstance) as HTMLDivElement;
|
|
321
337
|
if (
|
|
322
338
|
(el && !(el as any).contains(e.target) && popupEl && !(popupEl as any).contains(e.target)) ||
|
|
323
339
|
this.props.clickTriggerToHide
|
|
@@ -363,10 +379,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
363
379
|
if (!this.mounted) {
|
|
364
380
|
return false;
|
|
365
381
|
}
|
|
366
|
-
|
|
367
|
-
if (!isHTMLElement(this.triggerEl.current)) {
|
|
368
|
-
triggerDOM = ReactDOM.findDOMNode(this.triggerEl.current as React.ReactInstance);
|
|
369
|
-
}
|
|
382
|
+
const triggerDOM = this.adapter.getTriggerNode();
|
|
370
383
|
const isRelativeScroll = e.target.contains(triggerDOM);
|
|
371
384
|
if (isRelativeScroll) {
|
|
372
385
|
const scrollPos = { x: e.target.scrollLeft, y: e.target.scrollTop };
|
|
@@ -392,6 +405,29 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
392
405
|
}
|
|
393
406
|
},
|
|
394
407
|
getContainerPosition: () => this.containerPosition,
|
|
408
|
+
getContainer: () => this.containerEl && this.containerEl.current,
|
|
409
|
+
getTriggerNode: () => {
|
|
410
|
+
let triggerDOM = this.triggerEl.current;
|
|
411
|
+
if (!isHTMLElement(this.triggerEl.current)) {
|
|
412
|
+
triggerDOM = ReactDOM.findDOMNode(this.triggerEl.current as React.ReactInstance);
|
|
413
|
+
}
|
|
414
|
+
return triggerDOM as Element;
|
|
415
|
+
},
|
|
416
|
+
getFocusableElements: (node: HTMLDivElement) => {
|
|
417
|
+
return getFocusableElements(node);
|
|
418
|
+
},
|
|
419
|
+
getActiveElement: () => {
|
|
420
|
+
return getActiveElement();
|
|
421
|
+
},
|
|
422
|
+
setInitialFocus: () => {
|
|
423
|
+
const focusRefNode = get(this, 'initialFocusRef.current');
|
|
424
|
+
if (focusRefNode && 'focus' in focusRefNode) {
|
|
425
|
+
focusRefNode.focus();
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
notifyEscKeydown: (event: React.KeyboardEvent) => {
|
|
429
|
+
this.props.onEscKeyDown(event);
|
|
430
|
+
}
|
|
395
431
|
};
|
|
396
432
|
}
|
|
397
433
|
|
|
@@ -491,9 +527,21 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
491
527
|
}
|
|
492
528
|
};
|
|
493
529
|
|
|
530
|
+
handlePortalInnerKeyDown = (e: React.KeyboardEvent) => {
|
|
531
|
+
this.foundation.handleContainerKeydown(e);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
renderContentNode = (content: TooltipProps['content']) => {
|
|
535
|
+
const contentProps = {
|
|
536
|
+
initialFocusRef: this.initialFocusRef
|
|
537
|
+
};
|
|
538
|
+
return !isFunction(content) ? content : content(contentProps);
|
|
539
|
+
};
|
|
540
|
+
|
|
494
541
|
renderPortal = () => {
|
|
495
542
|
const { containerStyle = {}, visible, portalEventSet, placement, transitionState, id, isPositionUpdated } = this.state;
|
|
496
543
|
const { prefixCls, content, showArrow, style, motion, role, zIndex } = this.props;
|
|
544
|
+
const contentNode = this.renderContentNode(content);
|
|
497
545
|
const { className: propClassName } = this.props;
|
|
498
546
|
const direction = this.context.direction;
|
|
499
547
|
const className = classNames(propClassName, {
|
|
@@ -524,7 +572,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
524
572
|
x-placement={placement}
|
|
525
573
|
id={id}
|
|
526
574
|
>
|
|
527
|
-
{
|
|
575
|
+
{contentNode}
|
|
528
576
|
{icon}
|
|
529
577
|
</div>
|
|
530
578
|
) :
|
|
@@ -533,7 +581,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
533
581
|
</TooltipTransition>
|
|
534
582
|
) : (
|
|
535
583
|
<div className={className} {...portalEventSet} x-placement={placement} style={{ visibility: motion ? undefined : 'visible', ...style }}>
|
|
536
|
-
{
|
|
584
|
+
{contentNode}
|
|
537
585
|
{icon}
|
|
538
586
|
</div>
|
|
539
587
|
);
|
|
@@ -546,6 +594,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
546
594
|
style={portalInnerStyle}
|
|
547
595
|
ref={this.setContainerEl}
|
|
548
596
|
onClick={this.handlePortalInnerClick}
|
|
597
|
+
onKeyDown={this.handlePortalInnerKeyDown}
|
|
549
598
|
>
|
|
550
599
|
{inner}
|
|
551
600
|
</div>
|
|
@@ -587,7 +636,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
587
636
|
|
|
588
637
|
render() {
|
|
589
638
|
const { isInsert, triggerEventSet, visible, id } = this.state;
|
|
590
|
-
const { wrapWhenSpecial, role } = this.props;
|
|
639
|
+
const { wrapWhenSpecial, role, trigger } = this.props;
|
|
591
640
|
let { children } = this.props;
|
|
592
641
|
const childrenStyle = { ...get(children, 'props.style') };
|
|
593
642
|
const extraStyle: React.CSSProperties = {};
|
|
@@ -648,6 +697,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
648
697
|
ref.current = node;
|
|
649
698
|
}
|
|
650
699
|
},
|
|
700
|
+
tabIndex: trigger === 'hover' ? 0 : undefined, // a11y keyboard
|
|
651
701
|
});
|
|
652
702
|
|
|
653
703
|
// 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
|
|
@@ -661,4 +711,4 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
661
711
|
}
|
|
662
712
|
}
|
|
663
713
|
|
|
664
|
-
export { Position };
|
|
714
|
+
export { Position };
|