import type { CSSObject } from '@ant-design/cssinjs'; import { unit } from '@ant-design/cssinjs'; import type { AliasToken } from '../theme/interface'; import type { CSSUtil } from '../theme/internal'; export interface ArrowToken { /** @internal */ arrowShadowWidth: number; /** @internal */ arrowPath: string; /** @internal */ arrowPolygon: string; } export function getArrowToken(token: AliasToken): ArrowToken { const { sizePopupArrow, borderRadiusXS, borderRadiusOuter } = token; const unitWidth = sizePopupArrow / 2; const ax = 0; const ay = unitWidth; const bx = (borderRadiusOuter * 1) / Math.sqrt(2); const by = unitWidth - borderRadiusOuter * (1 - 1 / Math.sqrt(2)); const cx = unitWidth - borderRadiusXS * (1 / Math.sqrt(2)); const cy = borderRadiusOuter * (Math.sqrt(2) - 1) + borderRadiusXS * (1 / Math.sqrt(2)); const dx = 2 * unitWidth - cx; const dy = cy; const ex = 2 * unitWidth - bx; const ey = by; const fx = 2 * unitWidth - ax; const fy = ay; const shadowWidth = unitWidth * Math.sqrt(2) + borderRadiusOuter * (Math.sqrt(2) - 2); const polygonOffset = borderRadiusOuter * (Math.sqrt(2) - 1); const arrowPolygon = `polygon(${polygonOffset}px 100%, 50% ${polygonOffset}px, ${ 2 * unitWidth - polygonOffset }px 100%, ${polygonOffset}px 100%)`; const arrowPath = `path('M ${ax} ${ay} A ${borderRadiusOuter} ${borderRadiusOuter} 0 0 0 ${bx} ${by} L ${cx} ${cy} A ${borderRadiusXS} ${borderRadiusXS} 0 0 1 ${dx} ${dy} L ${ex} ${ey} A ${borderRadiusOuter} ${borderRadiusOuter} 0 0 0 ${fx} ${fy} Z')`; return { arrowShadowWidth: shadowWidth, arrowPath, arrowPolygon, }; } export const genRoundedArrow = ( token: T, bgColor: string, boxShadow: string, ): CSSObject => { const { sizePopupArrow, arrowPolygon, arrowPath, arrowShadowWidth, borderRadiusXS, calc } = token; return { pointerEvents: 'none', width: sizePopupArrow, height: sizePopupArrow, overflow: 'hidden', '&::before': { position: 'absolute', bottom: 0, insetInlineStart: 0, width: sizePopupArrow, height: calc(sizePopupArrow).div(2).equal(), background: bgColor, clipPath: { _multi_value_: true, value: [arrowPolygon, arrowPath], }, content: '""', }, '&::after': { content: '""', position: 'absolute', width: arrowShadowWidth, height: arrowShadowWidth, bottom: 0, insetInline: 0, margin: 'auto', borderRadius: { _skip_check_: true, value: `0 0 ${unit(borderRadiusXS)} 0`, }, transform: 'translateY(50%) rotate(-135deg)', boxShadow, zIndex: 0, background: 'transparent', }, }; };