Skip to content

Commit 8198cab

Browse files
tangjinzhouajuner
andauthored
refactor: transfer、tooltip (#4306)
* refactor(transfer): use composition api (#4135) * refactor(transfer): use composition api * fix: remove console * refactor(tooltip): use composition api (#4059) * refactor(tooltip): use composition api * chore: useConfigInject * fix: remove useless * style: format code * refactor: transfer * refactor: tooltip Co-authored-by: ajuner <[email protected]>
1 parent 16ee0dd commit 8198cab

33 files changed

+2017
-1490
lines changed

components/dropdown/dropdown.tsx

+9-4
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,15 @@ const Dropdown = defineComponent({
9292
const getPrefixCls = this.configProvider.getPrefixCls;
9393
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
9494
const child = getSlot(this)[0];
95-
const dropdownTrigger = cloneElement(child, {
96-
class: classNames(child?.props?.class, `${prefixCls}-trigger`),
97-
disabled,
98-
});
95+
const dropdownTrigger = cloneElement(
96+
child,
97+
Object.assign(
98+
{
99+
class: classNames(child?.props?.class, `${prefixCls}-trigger`),
100+
},
101+
disabled ? { disabled } : {},
102+
),
103+
);
99104
const triggerActions = disabled ? [] : typeof trigger === 'string' ? [trigger] : trigger;
100105
let alignPoint;
101106
if (triggerActions && triggerActions.indexOf('contextmenu') !== -1) {

components/locale-provider/__tests__/__snapshots__/index.test.js.snap

+408-204
Large diffs are not rendered by default.

components/slider/__tests__/index.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ describe('Slider', () => {
1919
await asyncExpect(() => {
2020
expect(document.body.innerHTML).toMatchSnapshot();
2121
wrapper.findAll('.ant-slider-handle')[0].trigger('mouseleave');
22-
}, 0);
22+
}, 100);
2323
await asyncExpect(() => {
2424
expect(document.body.innerHTML).toMatchSnapshot();
25-
}, 0);
25+
}, 100);
2626
});
2727
});

components/style/themes/default.less

+3
Original file line numberDiff line numberDiff line change
@@ -775,9 +775,12 @@
775775
// Transfer
776776
// ---
777777
@transfer-header-height: 40px;
778+
@transfer-item-height: @height-base;
778779
@transfer-disabled-bg: @disabled-bg;
779780
@transfer-list-height: 200px;
780781
@transfer-item-hover-bg: @item-hover-bg;
782+
@transfer-item-padding-vertical: 6px;
783+
@transfer-list-search-icon-top: 12px;
781784

782785
// Message
783786
// ---

components/tooltip/Tooltip.tsx

+136-121
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
import type { ExtractPropTypes, CSSProperties } from 'vue';
2-
import { defineComponent, inject } from 'vue';
2+
import { computed, watch } from 'vue';
3+
import { defineComponent, onMounted, ref } from 'vue';
34
import VcTooltip from '../vc-tooltip';
45
import classNames from '../_util/classNames';
5-
import getPlacements from './placements';
66
import PropTypes from '../_util/vue-types';
77
import { PresetColorTypes } from '../_util/colors';
8-
import {
9-
hasProp,
10-
getComponent,
11-
getStyle,
12-
filterEmpty,
13-
getSlot,
14-
isValidElement,
15-
} from '../_util/props-util';
8+
import warning from '../_util/warning';
9+
import { getPropsSlot, getStyle, filterEmpty, isValidElement } from '../_util/props-util';
1610
import { cloneElement } from '../_util/vnode';
17-
import { defaultConfigProvider } from '../config-provider';
11+
import type { triggerTypes, placementTypes } from './abstractTooltipProps';
1812
import abstractTooltipProps from './abstractTooltipProps';
13+
import useConfigInject from '../_util/hooks/useConfigInject';
14+
import getPlacements, { AdjustOverflow, PlacementsConfig } from './placements';
15+
16+
export { AdjustOverflow, PlacementsConfig };
17+
18+
export type TooltipPlacement = typeof placementTypes;
19+
20+
// https://github.com/react-component/tooltip
21+
// https://github.com/yiminghe/dom-align
22+
export interface TooltipAlignConfig {
23+
points?: [string, string];
24+
offset?: [number | string, number | string];
25+
targetOffset?: [number | string, number | string];
26+
overflow?: { adjustX: boolean; adjustY: boolean };
27+
useCssRight?: boolean;
28+
useCssBottom?: boolean;
29+
useCssTransform?: boolean;
30+
}
1931

2032
const splitObject = (obj: any, keys: string[]) => {
2133
const picked = {};
@@ -37,59 +49,70 @@ const tooltipProps = {
3749
title: PropTypes.VNodeChild,
3850
};
3951

52+
export type TriggerTypes = typeof triggerTypes[number];
53+
54+
export type PlacementTypes = typeof placementTypes[number];
55+
4056
export type TooltipProps = Partial<ExtractPropTypes<typeof tooltipProps>>;
4157

4258
export default defineComponent({
4359
name: 'ATooltip',
4460
inheritAttrs: false,
4561
props: tooltipProps,
4662
emits: ['update:visible', 'visibleChange'],
47-
setup() {
48-
return {
49-
configProvider: inject('configProvider', defaultConfigProvider),
50-
};
51-
},
52-
data() {
53-
return {
54-
sVisible: !!this.$props.visible || !!this.$props.defaultVisible,
63+
setup(props, { slots, emit, attrs, expose }) {
64+
const { prefixCls, getTargetContainer } = useConfigInject('tooltip', props);
65+
66+
const visible = ref(false);
67+
68+
const tooltip = ref();
69+
70+
onMounted(() => {
71+
warning(
72+
!('default-visible' in attrs) || !('defaultVisible' in attrs),
73+
'Tooltip',
74+
`'defaultVisible' is deprecated, please use 'v-model:visible'`,
75+
);
76+
});
77+
watch(
78+
() => props.visible,
79+
val => {
80+
visible.value = !!val;
81+
},
82+
{ immediate: true },
83+
);
84+
85+
const isNoTitle = () => {
86+
const title = getPropsSlot(slots, props, 'title');
87+
return !title && title !== 0;
5588
};
56-
},
57-
watch: {
58-
visible(val) {
59-
this.sVisible = val;
60-
},
61-
},
62-
methods: {
63-
handleVisibleChange(visible: boolean) {
64-
if (!hasProp(this, 'visible')) {
65-
this.sVisible = this.isNoTitle() ? false : visible;
66-
}
67-
if (!this.isNoTitle()) {
68-
this.$emit('update:visible', visible);
69-
this.$emit('visibleChange', visible);
89+
90+
const handleVisibleChange = (val: boolean) => {
91+
visible.value = isNoTitle() ? false : val;
92+
if (!isNoTitle()) {
93+
emit('update:visible', val);
94+
emit('visibleChange', val);
7095
}
71-
},
96+
};
7297

73-
getPopupDomNode() {
74-
return (this.$refs.tooltip as any).getPopupDomNode();
75-
},
98+
const getPopupDomNode = () => {
99+
return tooltip.value.getPopupDomNode();
100+
};
76101

77-
getPlacements() {
78-
const { builtinPlacements, arrowPointAtCenter, autoAdjustOverflow } = this.$props;
102+
expose({ getPopupDomNode, visible });
103+
104+
const tooltipPlacements = computed(() => {
105+
const { builtinPlacements, arrowPointAtCenter, autoAdjustOverflow } = props;
79106
return (
80107
builtinPlacements ||
81108
getPlacements({
82109
arrowPointAtCenter,
83-
verticalArrowShift: 8,
84110
autoAdjustOverflow,
85111
})
86112
);
87-
},
113+
});
88114

89-
// Fix Tooltip won't hide at disabled button
90-
// mouse events don't trigger at disabled button in Chrome
91-
// https://github.com/react-component/tooltip/issues/18
92-
getDisabledCompatibleChildren(ele: any) {
115+
const getDisabledCompatibleChildren = (ele: any) => {
93116
if (
94117
((typeof ele.type === 'object' &&
95118
(ele.type.__ANT_BUTTON === true ||
@@ -128,27 +151,22 @@ export default defineComponent({
128151
},
129152
true,
130153
);
131-
return <span style={spanStyle}>{child}</span>;
154+
return (
155+
<span style={spanStyle} class={`${prefixCls}-disabled-compatible-wrapper`}>
156+
{child}
157+
</span>
158+
);
132159
}
133160
return ele;
134-
},
135-
136-
isNoTitle() {
137-
const title = getComponent(this, 'title');
138-
return !title && title !== 0;
139-
},
161+
};
140162

141-
getOverlay() {
142-
const title = getComponent(this, 'title');
143-
if (title === 0) {
144-
return title;
145-
}
146-
return title || '';
147-
},
163+
const getOverlay = () => {
164+
const title = getPropsSlot(slots, props, 'title');
165+
return title ?? '';
166+
};
148167

149-
// 动态设置动画点
150-
onPopupAlign(domNode: HTMLElement, align: any) {
151-
const placements = this.getPlacements();
168+
const onPopupAlign = (domNode: HTMLElement, align: any) => {
169+
const placements = tooltipPlacements.value;
152170
// 当前返回的位置
153171
const placement = Object.keys(placements).filter(
154172
key =>
@@ -175,67 +193,64 @@ export default defineComponent({
175193
transformOrigin.left = `${-align.offset[0]}px`;
176194
}
177195
domNode.style.transformOrigin = `${transformOrigin.left} ${transformOrigin.top}`;
178-
},
179-
},
196+
};
180197

181-
render() {
182-
const { $props, $data, $attrs } = this;
183-
const {
184-
prefixCls: customizePrefixCls,
185-
openClassName,
186-
getPopupContainer,
187-
color,
188-
overlayClassName,
189-
} = $props;
190-
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
191-
const getPrefixCls = this.configProvider.getPrefixCls;
192-
const prefixCls = getPrefixCls('tooltip', customizePrefixCls);
193-
let children = this.children || filterEmpty(getSlot(this));
194-
children = children.length === 1 ? children[0] : children;
195-
let sVisible = $data.sVisible;
196-
// Hide tooltip when there is no title
197-
if (!hasProp(this, 'visible') && this.isNoTitle()) {
198-
sVisible = false;
199-
}
200-
if (!children) {
201-
return null;
202-
}
203-
const child = this.getDisabledCompatibleChildren(
204-
isValidElement(children) ? children : <span>{children}</span>,
205-
);
206-
const childCls = classNames({
207-
[openClassName || `${prefixCls}-open`]: sVisible,
208-
[child.props && child.props.class]: child.props && child.props.class,
209-
});
210-
const customOverlayClassName = classNames(overlayClassName, {
211-
[`${prefixCls}-${color}`]: color && PresetColorRegex.test(color),
212-
});
213-
let formattedOverlayInnerStyle: CSSProperties;
214-
let arrowContentStyle: CSSProperties;
215-
if (color && !PresetColorRegex.test(color)) {
216-
formattedOverlayInnerStyle = { backgroundColor: color };
217-
arrowContentStyle = { backgroundColor: color };
218-
}
198+
return () => {
199+
const { openClassName, getPopupContainer, color, overlayClassName } = props;
200+
let children = filterEmpty(slots.default?.()) ?? null;
201+
children = children.length === 1 ? children[0] : children;
219202

220-
const vcTooltipProps = {
221-
...$attrs,
222-
...$props,
223-
prefixCls,
224-
getTooltipContainer: getPopupContainer || getContextPopupContainer,
225-
builtinPlacements: this.getPlacements(),
226-
overlay: this.getOverlay(),
227-
visible: sVisible,
228-
ref: 'tooltip',
229-
overlayClassName: customOverlayClassName,
230-
overlayInnerStyle: formattedOverlayInnerStyle,
231-
arrowContent: <span class={`${prefixCls}-arrow-content`} style={arrowContentStyle}></span>,
232-
onVisibleChange: this.handleVisibleChange,
233-
onPopupAlign: this.onPopupAlign,
203+
let tempVisible = visible.value;
204+
// Hide tooltip when there is no title
205+
if (props.visible === undefined && isNoTitle()) {
206+
tempVisible = false;
207+
}
208+
if (!children) {
209+
return null;
210+
}
211+
const child = getDisabledCompatibleChildren(
212+
isValidElement(children) ? children : <span>{children}</span>,
213+
);
214+
const childCls = classNames({
215+
[openClassName || `${prefixCls.value}-open`]: true,
216+
[child.props && child.props.class]: child.props && child.props.class,
217+
});
218+
const customOverlayClassName = classNames(overlayClassName, {
219+
[`${prefixCls.value}-${color}`]: color && PresetColorRegex.test(color),
220+
});
221+
let formattedOverlayInnerStyle: CSSProperties;
222+
let arrowContentStyle: CSSProperties;
223+
if (color && !PresetColorRegex.test(color)) {
224+
formattedOverlayInnerStyle = { backgroundColor: color };
225+
arrowContentStyle = { backgroundColor: color };
226+
}
227+
228+
const vcTooltipProps = {
229+
...attrs,
230+
...props,
231+
prefixCls: prefixCls.value,
232+
getTooltipContainer: getPopupContainer || getTargetContainer.value,
233+
builtinPlacements: tooltipPlacements.value,
234+
overlay: getOverlay(),
235+
visible: tempVisible,
236+
ref: tooltip,
237+
overlayClassName: customOverlayClassName,
238+
overlayInnerStyle: formattedOverlayInnerStyle,
239+
onVisibleChange: handleVisibleChange,
240+
onPopupAlign,
241+
};
242+
return (
243+
<VcTooltip
244+
{...vcTooltipProps}
245+
v-slots={{
246+
arrowContent: () => (
247+
<span class={`${prefixCls.value}-arrow-content`} style={arrowContentStyle}></span>
248+
),
249+
}}
250+
>
251+
{visible.value ? cloneElement(child, { class: childCls }) : child}
252+
</VcTooltip>
253+
);
234254
};
235-
return (
236-
<VcTooltip {...vcTooltipProps}>
237-
{sVisible ? cloneElement(child, { class: childCls }) : child}
238-
</VcTooltip>
239-
);
240255
},
241256
});

0 commit comments

Comments
 (0)