ant-design-vue/components/vc-select/SelectTrigger.tsx

194 lines
5.6 KiB
Vue
Raw Normal View History

2020-09-30 16:21:04 +08:00
import Trigger from '../vc-trigger';
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
2021-12-16 17:20:18 +08:00
import type { CSSProperties } from 'vue';
import { computed, ref, defineComponent } from 'vue';
2021-12-16 17:20:18 +08:00
import type { VueNode } from '../_util/type';
import type { DropdownRender, Placement, RenderDOMFunc } from './BaseSelect';
2020-09-30 16:21:04 +08:00
const getBuiltInPlacements = (adjustX: number) => {
2020-09-30 16:21:04 +08:00
return {
bottomLeft: {
points: ['tl', 'bl'],
offset: [0, 4],
overflow: {
adjustX,
adjustY: 1,
},
},
bottomRight: {
points: ['tr', 'br'],
offset: [0, 4],
overflow: {
adjustX,
adjustY: 1,
},
},
topLeft: {
points: ['bl', 'tl'],
offset: [0, -4],
overflow: {
adjustX,
adjustY: 1,
},
},
topRight: {
points: ['br', 'tr'],
offset: [0, -4],
overflow: {
adjustX,
adjustY: 1,
},
},
};
};
const getAdjustX = (
adjustXDependencies: Pick<SelectTriggerProps, 'autoAdjustOverflow' | 'dropdownMatchSelectWidth'>,
) => {
const { autoAdjustOverflow, dropdownMatchSelectWidth } = adjustXDependencies;
if (!!autoAdjustOverflow) return 1;
// Enable horizontal overflow auto-adjustment when a custom dropdown width is provided
return typeof dropdownMatchSelectWidth !== 'number' ? 0 : 1;
};
export interface RefTriggerProps {
getPopupElement: () => HTMLDivElement;
}
2020-10-03 15:54:52 +08:00
export interface SelectTriggerProps {
prefixCls: string;
disabled: boolean;
visible: boolean;
2021-12-16 17:20:18 +08:00
popupElement: VueNode;
2020-10-03 15:54:52 +08:00
animation?: string;
transitionName?: string;
containerWidth: number;
2021-11-03 16:22:02 +08:00
placement?: Placement;
2020-10-03 15:54:52 +08:00
dropdownStyle: CSSProperties;
dropdownClassName: string;
direction: string;
dropdownMatchSelectWidth?: boolean | number;
2020-11-23 16:39:09 +08:00
dropdownRender?: DropdownRender;
2020-10-03 15:54:52 +08:00
getPopupContainer?: RenderDOMFunc;
dropdownAlign: object;
empty: boolean;
autoAdjustOverflow?: boolean;
2020-10-07 22:49:01 +08:00
getTriggerDOMNode: () => any;
onPopupVisibleChange?: (visible: boolean) => void;
onPopupMouseEnter: () => void;
2020-10-03 15:54:52 +08:00
}
2021-04-09 11:00:41 +08:00
2020-10-10 17:01:39 +08:00
const SelectTrigger = defineComponent<SelectTriggerProps, { popupRef: any }>({
2020-09-30 16:21:04 +08:00
name: 'SelectTrigger',
inheritAttrs: false,
props: {
dropdownAlign: PropTypes.object,
visible: PropTypes.looseBool,
disabled: PropTypes.looseBool,
dropdownClassName: PropTypes.string,
dropdownStyle: PropTypes.object,
placement: PropTypes.string,
empty: PropTypes.looseBool,
autoAdjustOverflow: PropTypes.looseBool,
prefixCls: PropTypes.string,
popupClassName: PropTypes.string,
animation: PropTypes.string,
transitionName: PropTypes.string,
getPopupContainer: PropTypes.func,
dropdownRender: PropTypes.func,
containerWidth: PropTypes.number,
dropdownMatchSelectWidth: PropTypes.oneOfType([Number, Boolean]).def(true),
popupElement: PropTypes.any,
direction: PropTypes.string,
getTriggerDOMNode: PropTypes.func,
onPopupVisibleChange: PropTypes.func,
onPopupMouseEnter: PropTypes.func,
} as any,
setup(props, { slots, attrs, expose }) {
const builtInPlacements = computed(() => {
const { autoAdjustOverflow, dropdownMatchSelectWidth } = props;
return getBuiltInPlacements(
getAdjustX({
autoAdjustOverflow,
dropdownMatchSelectWidth,
}),
);
});
const popupRef = ref();
expose({
getPopupElement: () => {
return popupRef.value;
},
});
return () => {
const { empty = false, ...restProps } = { ...props, ...attrs };
const {
visible,
dropdownAlign,
prefixCls,
popupElement,
dropdownClassName,
dropdownStyle,
direction = 'ltr',
placement,
dropdownMatchSelectWidth,
containerWidth,
dropdownRender,
animation,
transitionName,
getPopupContainer,
getTriggerDOMNode,
onPopupVisibleChange,
onPopupMouseEnter,
} = restProps as SelectTriggerProps;
const dropdownPrefixCls = `${prefixCls}-dropdown`;
2020-09-30 16:21:04 +08:00
let popupNode = popupElement;
if (dropdownRender) {
popupNode = dropdownRender({ menuNode: popupElement, props });
}
2020-10-08 22:51:09 +08:00
const mergedTransitionName = animation ? `${dropdownPrefixCls}-${animation}` : transitionName;
2020-10-08 22:51:09 +08:00
const popupStyle = { minWidth: `${containerWidth}px`, ...dropdownStyle };
2020-09-30 16:21:04 +08:00
if (typeof dropdownMatchSelectWidth === 'number') {
popupStyle.width = `${dropdownMatchSelectWidth}px`;
} else if (dropdownMatchSelectWidth) {
popupStyle.width = `${containerWidth}px`;
}
return (
<Trigger
{...props}
showAction={onPopupVisibleChange ? ['click'] : []}
hideAction={onPopupVisibleChange ? ['click'] : []}
popupPlacement={placement || (direction === 'rtl' ? 'bottomRight' : 'bottomLeft')}
builtinPlacements={builtInPlacements.value}
prefixCls={dropdownPrefixCls}
popupTransitionName={mergedTransitionName}
popupAlign={dropdownAlign}
popupVisible={visible}
getPopupContainer={getPopupContainer}
popupClassName={classNames(dropdownClassName, {
[`${dropdownPrefixCls}-empty`]: empty,
})}
popupStyle={popupStyle}
getTriggerDOMNode={getTriggerDOMNode}
onPopupVisibleChange={onPopupVisibleChange}
v-slots={{
default: slots.default,
popup: () => (
<div ref={popupRef} onMouseenter={onPopupMouseEnter}>
{popupNode}
</div>
),
}}
></Trigger>
);
};
2020-09-30 16:21:04 +08:00
},
2020-10-03 15:54:52 +08:00
});
2021-04-09 11:00:41 +08:00
2020-10-03 15:54:52 +08:00
export default SelectTrigger;