mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-30 20:38:45 +08:00
212 lines
5.8 KiB
TypeScript
212 lines
5.8 KiB
TypeScript
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
|
|
|
|
import type { AliasToken } from '../theme/internal';
|
|
import type { TokenWithCommonCls } from '../theme/util/genComponentStyleHook';
|
|
import type { ArrowToken } from './roundedArrow';
|
|
import { genRoundedArrow } from './roundedArrow';
|
|
|
|
export const MAX_VERTICAL_CONTENT_RADIUS = 8;
|
|
|
|
export interface ArrowOffsetToken {
|
|
/** @internal */
|
|
arrowOffsetHorizontal: number;
|
|
/** @internal */
|
|
arrowOffsetVertical: number;
|
|
}
|
|
|
|
export function getArrowOffsetToken(options: {
|
|
contentRadius: number;
|
|
limitVerticalRadius?: boolean;
|
|
}): ArrowOffsetToken {
|
|
const { contentRadius, limitVerticalRadius } = options;
|
|
const arrowOffset = contentRadius > 12 ? contentRadius + 2 : 12;
|
|
const arrowOffsetVertical = limitVerticalRadius ? MAX_VERTICAL_CONTENT_RADIUS : arrowOffset;
|
|
return { arrowOffsetHorizontal: arrowOffset, arrowOffsetVertical };
|
|
}
|
|
|
|
function isInject(valid: boolean, code: CSSObject): CSSObject {
|
|
if (!valid) {
|
|
return {};
|
|
}
|
|
return code;
|
|
}
|
|
|
|
export default function getArrowStyle<
|
|
Token extends TokenWithCommonCls<AliasToken> & ArrowOffsetToken & ArrowToken,
|
|
>(
|
|
token: Token,
|
|
colorBg: string,
|
|
options?: {
|
|
arrowDistance?: number;
|
|
arrowPlacement?: {
|
|
left?: boolean;
|
|
right?: boolean;
|
|
top?: boolean;
|
|
bottom?: boolean;
|
|
};
|
|
},
|
|
): CSSInterpolation {
|
|
const { componentCls, boxShadowPopoverArrow, arrowOffsetVertical, arrowOffsetHorizontal } = token;
|
|
|
|
const {
|
|
arrowDistance = 0,
|
|
arrowPlacement = {
|
|
left: true,
|
|
right: true,
|
|
top: true,
|
|
bottom: true,
|
|
},
|
|
} = options || {};
|
|
|
|
return {
|
|
[componentCls]: {
|
|
// ============================ Basic ============================
|
|
[`${componentCls}-arrow`]: [
|
|
{
|
|
position: 'absolute',
|
|
zIndex: 1, // lift it up so the menu wouldn't cask shadow on it
|
|
display: 'block',
|
|
|
|
...genRoundedArrow(token, colorBg, boxShadowPopoverArrow),
|
|
|
|
'&:before': {
|
|
background: colorBg,
|
|
},
|
|
},
|
|
],
|
|
|
|
// ========================== Placement ==========================
|
|
// Here handle the arrow position and rotate stuff
|
|
// >>>>> Top
|
|
...isInject(!!arrowPlacement.top, {
|
|
[[
|
|
`&-placement-top > ${componentCls}-arrow`,
|
|
`&-placement-topLeft > ${componentCls}-arrow`,
|
|
`&-placement-topRight > ${componentCls}-arrow`,
|
|
].join(',')]: {
|
|
bottom: arrowDistance,
|
|
transform: 'translateY(100%) rotate(180deg)',
|
|
},
|
|
|
|
[`&-placement-top > ${componentCls}-arrow`]: {
|
|
left: {
|
|
_skip_check_: true,
|
|
value: '50%',
|
|
},
|
|
transform: 'translateX(-50%) translateY(100%) rotate(180deg)',
|
|
},
|
|
|
|
[`&-placement-topLeft > ${componentCls}-arrow`]: {
|
|
left: {
|
|
_skip_check_: true,
|
|
value: arrowOffsetHorizontal,
|
|
},
|
|
},
|
|
|
|
[`&-placement-topRight > ${componentCls}-arrow`]: {
|
|
right: {
|
|
_skip_check_: true,
|
|
value: arrowOffsetHorizontal,
|
|
},
|
|
},
|
|
}),
|
|
|
|
// >>>>> Bottom
|
|
...isInject(!!arrowPlacement.bottom, {
|
|
[[
|
|
`&-placement-bottom > ${componentCls}-arrow`,
|
|
`&-placement-bottomLeft > ${componentCls}-arrow`,
|
|
`&-placement-bottomRight > ${componentCls}-arrow`,
|
|
].join(',')]: {
|
|
top: arrowDistance,
|
|
transform: `translateY(-100%)`,
|
|
},
|
|
|
|
[`&-placement-bottom > ${componentCls}-arrow`]: {
|
|
left: {
|
|
_skip_check_: true,
|
|
value: '50%',
|
|
},
|
|
transform: `translateX(-50%) translateY(-100%)`,
|
|
},
|
|
|
|
[`&-placement-bottomLeft > ${componentCls}-arrow`]: {
|
|
left: {
|
|
_skip_check_: true,
|
|
value: arrowOffsetHorizontal,
|
|
},
|
|
},
|
|
|
|
[`&-placement-bottomRight > ${componentCls}-arrow`]: {
|
|
right: {
|
|
_skip_check_: true,
|
|
value: arrowOffsetHorizontal,
|
|
},
|
|
},
|
|
}),
|
|
|
|
// >>>>> Left
|
|
...isInject(!!arrowPlacement.left, {
|
|
[[
|
|
`&-placement-left > ${componentCls}-arrow`,
|
|
`&-placement-leftTop > ${componentCls}-arrow`,
|
|
`&-placement-leftBottom > ${componentCls}-arrow`,
|
|
].join(',')]: {
|
|
right: {
|
|
_skip_check_: true,
|
|
value: arrowDistance,
|
|
},
|
|
transform: 'translateX(100%) rotate(90deg)',
|
|
},
|
|
|
|
[`&-placement-left > ${componentCls}-arrow`]: {
|
|
top: {
|
|
_skip_check_: true,
|
|
value: '50%',
|
|
},
|
|
transform: 'translateY(-50%) translateX(100%) rotate(90deg)',
|
|
},
|
|
|
|
[`&-placement-leftTop > ${componentCls}-arrow`]: {
|
|
top: arrowOffsetVertical,
|
|
},
|
|
|
|
[`&-placement-leftBottom > ${componentCls}-arrow`]: {
|
|
bottom: arrowOffsetVertical,
|
|
},
|
|
}),
|
|
|
|
// >>>>> Right
|
|
...isInject(!!arrowPlacement.right, {
|
|
[[
|
|
`&-placement-right > ${componentCls}-arrow`,
|
|
`&-placement-rightTop > ${componentCls}-arrow`,
|
|
`&-placement-rightBottom > ${componentCls}-arrow`,
|
|
].join(',')]: {
|
|
left: {
|
|
_skip_check_: true,
|
|
value: arrowDistance,
|
|
},
|
|
transform: 'translateX(-100%) rotate(-90deg)',
|
|
},
|
|
|
|
[`&-placement-right > ${componentCls}-arrow`]: {
|
|
top: {
|
|
_skip_check_: true,
|
|
value: '50%',
|
|
},
|
|
transform: 'translateY(-50%) translateX(-100%) rotate(-90deg)',
|
|
},
|
|
|
|
[`&-placement-rightTop > ${componentCls}-arrow`]: {
|
|
top: arrowOffsetVertical,
|
|
},
|
|
|
|
[`&-placement-rightBottom > ${componentCls}-arrow`]: {
|
|
bottom: arrowOffsetVertical,
|
|
},
|
|
}),
|
|
},
|
|
};
|
|
}
|