feat: add theme and style

This commit is contained in:
2023-03-02 07:16:36 +08:00
parent 7b58fb84eb
commit 8ab55b28fe
52 changed files with 3836 additions and 5 deletions

View File

@ -0,0 +1,56 @@
/* eslint-disable import/prefer-default-export */
import type { CSSInterpolation, CSSObject } from '@antd-tiny-vue/cssinjs'
import type { DerivativeToken, FullToken } from '../theme/internal'
import type { OverrideComponent } from '../theme/util/genComponentStyleHook'
function compactItemVerticalBorder(token: DerivativeToken, parentCls: string): CSSObject {
return {
// border collapse
[`&-item:not(${parentCls}-last-item)`]: {
marginBottom: -token.lineWidth
},
'&-item': {
'&:hover,&:focus,&:active': {
zIndex: 2
},
'&[disabled]': {
zIndex: 0
}
}
}
}
function compactItemBorderVerticalRadius(prefixCls: string, parentCls: string): CSSObject {
return {
[`&-item:not(${parentCls}-first-item):not(${parentCls}-last-item)`]: {
borderRadius: 0
},
[`&-item${parentCls}-first-item:not(${parentCls}-last-item)`]: {
[`&, &${prefixCls}-sm, &${prefixCls}-lg`]: {
borderEndEndRadius: 0,
borderEndStartRadius: 0
}
},
[`&-item${parentCls}-last-item:not(${parentCls}-first-item)`]: {
[`&, &${prefixCls}-sm, &${prefixCls}-lg`]: {
borderStartStartRadius: 0,
borderStartEndRadius: 0
}
}
}
}
export function genCompactItemVerticalStyle<T extends OverrideComponent>(token: FullToken<T>): CSSInterpolation {
const compactCls = `${token.componentCls}-compact-vertical`
return {
[compactCls]: {
...compactItemVerticalBorder(token, compactCls),
...compactItemBorderVerticalRadius(token.componentCls, compactCls)
}
}
}

View File

@ -0,0 +1,90 @@
/* eslint-disable import/prefer-default-export */
import type { CSSInterpolation, CSSObject } from '@antd-tiny-vue/cssinjs'
import type { DerivativeToken, FullToken } from '../theme/internal'
import type { OverrideComponent } from '../theme/util/genComponentStyleHook'
interface CompactItemOptions {
focus?: boolean
/**
* Some component borders are implemented on child elements
* like `Select`
*/
borderElCls?: string
/**
* Some components have special `focus` className especially with popovers
* like `Select` and `DatePicker`
*/
focusElCls?: string
}
// handle border collapse
function compactItemBorder(token: DerivativeToken, parentCls: string, options: CompactItemOptions): CSSObject {
const { focusElCls, focus, borderElCls } = options
const childCombinator = borderElCls ? '> *' : ''
const hoverEffects = ['hover', focus ? 'focus' : null, 'active']
.filter(Boolean)
.map(n => `&:${n} ${childCombinator}`)
.join(',')
return {
[`&-item:not(${parentCls}-last-item)`]: {
marginInlineEnd: -token.lineWidth
},
'&-item': {
[hoverEffects]: {
zIndex: 2
},
...(focusElCls
? {
[`&${focusElCls}`]: {
zIndex: 2
}
}
: {}),
[`&[disabled] ${childCombinator}`]: {
zIndex: 0
}
}
}
}
// handle border-radius
function compactItemBorderRadius(prefixCls: string, parentCls: string, options: CompactItemOptions): CSSObject {
const { borderElCls } = options
const childCombinator = borderElCls ? `> ${borderElCls}` : ''
return {
[`&-item:not(${parentCls}-first-item):not(${parentCls}-last-item) ${childCombinator}`]: {
borderRadius: 0
},
[`&-item:not(${parentCls}-last-item)${parentCls}-first-item`]: {
[`& ${childCombinator}, &${prefixCls}-sm ${childCombinator}, &${prefixCls}-lg ${childCombinator}`]: {
borderStartEndRadius: 0,
borderEndEndRadius: 0
}
},
[`&-item:not(${parentCls}-first-item)${parentCls}-last-item`]: {
[`& ${childCombinator}, &${prefixCls}-sm ${childCombinator}, &${prefixCls}-lg ${childCombinator}`]: {
borderStartStartRadius: 0,
borderEndStartRadius: 0
}
}
}
}
export function genCompactItemStyle<T extends OverrideComponent>(token: FullToken<T>, options: CompactItemOptions = { focus: true }): CSSInterpolation {
const { componentCls } = token
const compactCls = `${componentCls}-compact`
return {
[compactCls]: {
...compactItemBorder(token, compactCls, options),
...compactItemBorderRadius(componentCls, compactCls, options)
}
}
}

139
components/style/index.ts Normal file
View File

@ -0,0 +1,139 @@
/* eslint-disable import/prefer-default-export */
import type { CSSObject } from '@antd-tiny-vue/cssinjs'
import type { DerivativeToken } from '../theme/internal'
export { operationUnit } from './operationUnit'
export { roundedArrow } from './roundedArrow'
export { genPresetColor } from './presetColor'
export const textEllipsis: CSSObject = {
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis'
}
export const resetComponent = (token: DerivativeToken): CSSObject => ({
boxSizing: 'border-box',
margin: 0,
padding: 0,
color: token.colorText,
fontSize: token.fontSize,
// font-variant: @font-variant-base;
lineHeight: token.lineHeight,
listStyle: 'none',
// font-feature-settings: @font-feature-settings-base;
fontFamily: token.fontFamily
})
export const resetIcon = (): CSSObject => ({
display: 'inline-flex',
alignItems: 'center',
color: 'inherit',
fontStyle: 'normal',
lineHeight: 0,
textAlign: 'center',
textTransform: 'none',
// for SVG icon, see https://blog.prototypr.io/align-svg-icons-to-text-and-say-goodbye-to-font-icons-d44b3d7b26b4
verticalAlign: '-0.125em',
textRendering: 'optimizeLegibility',
'-webkit-font-smoothing': 'antialiased',
'-moz-osx-font-smoothing': 'grayscale',
'> *': {
lineHeight: 1
},
svg: {
display: 'inline-block'
}
})
export const clearFix = (): CSSObject => ({
// https://github.com/ant-design/ant-design/issues/21301#issuecomment-583955229
'&::before': {
display: 'table',
content: '""'
},
'&::after': {
// https://github.com/ant-design/ant-design/issues/21864
display: 'table',
clear: 'both',
content: '""'
}
})
export const genLinkStyle = (token: DerivativeToken): CSSObject => ({
a: {
color: token.colorLink,
textDecoration: token.linkDecoration,
backgroundColor: 'transparent', // remove the gray background on active links in IE 10.
outline: 'none',
cursor: 'pointer',
transition: `color ${token.motionDurationSlow}`,
'-webkit-text-decoration-skip': 'objects', // remove gaps in links underline in iOS 8+ and Safari 8+.
'&:hover': {
color: token.colorLinkHover
},
'&:active': {
color: token.colorLinkActive
},
[`&:active,
&:hover`]: {
textDecoration: token.linkHoverDecoration,
outline: 0
},
// https://github.com/ant-design/ant-design/issues/22503
'&:focus': {
textDecoration: token.linkFocusDecoration,
outline: 0
},
'&[disabled]': {
color: token.colorTextDisabled,
cursor: 'not-allowed'
}
}
})
export const genCommonStyle = (token: DerivativeToken, componentPrefixCls: string): CSSObject => {
const { fontFamily, fontSize } = token
const rootPrefixSelector = `[class^="${componentPrefixCls}"], [class*=" ${componentPrefixCls}"]`
return {
[rootPrefixSelector]: {
fontFamily,
fontSize,
boxSizing: 'border-box',
'&::before, &::after': {
boxSizing: 'border-box'
},
[rootPrefixSelector]: {
boxSizing: 'border-box',
'&::before, &::after': {
boxSizing: 'border-box'
}
}
}
}
}
export const genFocusOutline = (token: DerivativeToken): CSSObject => ({
outline: `${token.lineWidth * 4}px solid ${token.colorPrimaryBorder}`,
outlineOffset: 1,
transition: 'outline-offset 0s, outline 0s'
})
export const genFocusStyle = (token: DerivativeToken): CSSObject => ({
'&:focus-visible': {
...genFocusOutline(token)
}
})

View File

@ -0,0 +1,24 @@
import type { AliasToken, GenerateStyle } from '../../theme/internal'
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'
const genCollapseMotion: GenerateStyle<TokenWithCommonCls<AliasToken>> = token => ({
[token.componentCls]: {
// For common/openAnimation
[`${token.antCls}-motion-collapse-legacy`]: {
overflow: 'hidden',
'&-active': {
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`
}
},
[`${token.antCls}-motion-collapse`]: {
overflow: 'hidden',
transition: `height ${token.motionDurationMid} ${token.motionEaseInOut},
opacity ${token.motionDurationMid} ${token.motionEaseInOut} !important`
}
}
})
export default genCollapseMotion

View File

@ -0,0 +1,46 @@
import type { CSSInterpolation } from '@antd-tiny-vue/cssinjs'
import { Keyframes } from '@antd-tiny-vue/cssinjs'
import type { AliasToken } from '../../theme/internal'
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'
import { initMotion } from './motion'
export const fadeIn = new Keyframes('antFadeIn', {
'0%': {
opacity: 0
},
'100%': {
opacity: 1
}
})
export const fadeOut = new Keyframes('antFadeOut', {
'0%': {
opacity: 1
},
'100%': {
opacity: 0
}
})
export const initFadeMotion = (token: TokenWithCommonCls<AliasToken>, sameLevel = false): CSSInterpolation => {
const { antCls } = token
const motionCls = `${antCls}-fade`
const sameLevelPrefix = sameLevel ? '&' : ''
return [
initMotion(motionCls, fadeIn, fadeOut, token.motionDurationMid, sameLevel),
{
[`
${sameLevelPrefix}${motionCls}-enter,
${sameLevelPrefix}${motionCls}-appear
`]: {
opacity: 0,
animationTimingFunction: 'linear'
},
[`${sameLevelPrefix}${motionCls}-leave`]: {
animationTimingFunction: 'linear'
}
}
]
}

View File

@ -0,0 +1,44 @@
import { fadeIn, fadeOut, initFadeMotion } from './fade'
import { initMoveMotion, moveDownIn, moveDownOut, moveLeftIn, moveLeftOut, moveRightIn, moveRightOut, moveUpIn, moveUpOut } from './move'
import { initSlideMotion, slideDownIn, slideDownOut, slideLeftIn, slideLeftOut, slideRightIn, slideRightOut, slideUpIn, slideUpOut } from './slide'
import { initZoomMotion, zoomBigIn, zoomBigOut, zoomDownIn, zoomDownOut, zoomIn, zoomLeftIn, zoomLeftOut, zoomOut, zoomRightIn, zoomRightOut, zoomUpIn, zoomUpOut } from './zoom'
import genCollapseMotion from './collapse'
export {
initSlideMotion,
slideUpIn,
slideUpOut,
slideDownIn,
slideDownOut,
slideLeftIn,
slideLeftOut,
slideRightIn,
slideRightOut,
zoomOut,
zoomIn,
zoomBigIn,
zoomLeftOut,
zoomBigOut,
zoomLeftIn,
zoomRightIn,
zoomUpIn,
zoomRightOut,
zoomUpOut,
zoomDownIn,
zoomDownOut,
initZoomMotion,
fadeIn,
fadeOut,
initFadeMotion,
moveRightOut,
moveRightIn,
moveLeftOut,
moveLeftIn,
moveDownOut,
moveDownIn,
moveUpIn,
moveUpOut,
initMoveMotion,
genCollapseMotion
}

View File

@ -0,0 +1,46 @@
/* eslint-disable import/prefer-default-export */
import type { CSSObject, Keyframes } from '@antd-tiny-vue/cssinjs'
const initMotionCommon = (duration: string): CSSObject => ({
animationDuration: duration,
animationFillMode: 'both'
})
// FIXME: origin less code seems same as initMotionCommon. Maybe we can safe remove
const initMotionCommonLeave = (duration: string): CSSObject => ({
animationDuration: duration,
animationFillMode: 'both'
})
export const initMotion = (motionCls: string, inKeyframes: Keyframes, outKeyframes: Keyframes, duration: string, sameLevel = false): CSSObject => {
const sameLevelPrefix = sameLevel ? '&' : ''
return {
[`
${sameLevelPrefix}${motionCls}-enter,
${sameLevelPrefix}${motionCls}-appear
`]: {
...initMotionCommon(duration),
animationPlayState: 'paused'
},
[`${sameLevelPrefix}${motionCls}-leave`]: {
...initMotionCommonLeave(duration),
animationPlayState: 'paused'
},
[`
${sameLevelPrefix}${motionCls}-enter${motionCls}-enter-active,
${sameLevelPrefix}${motionCls}-appear${motionCls}-appear-active
`]: {
animationName: inKeyframes,
animationPlayState: 'running'
},
[`${sameLevelPrefix}${motionCls}-leave${motionCls}-leave-active`]: {
animationName: outKeyframes,
animationPlayState: 'running',
pointerEvents: 'none'
}
}
}

View File

@ -0,0 +1,160 @@
import type { CSSInterpolation } from '@antd-tiny-vue/cssinjs'
import { Keyframes } from '@antd-tiny-vue/cssinjs'
import type { AliasToken } from '../../theme/internal'
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'
import { initMotion } from './motion'
export const moveDownIn = new Keyframes('antMoveDownIn', {
'0%': {
transform: 'translate3d(0, 100%, 0)',
transformOrigin: '0 0',
opacity: 0
},
'100%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
}
})
export const moveDownOut = new Keyframes('antMoveDownOut', {
'0%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
},
'100%': {
transform: 'translate3d(0, 100%, 0)',
transformOrigin: '0 0',
opacity: 0
}
})
export const moveLeftIn = new Keyframes('antMoveLeftIn', {
'0%': {
transform: 'translate3d(-100%, 0, 0)',
transformOrigin: '0 0',
opacity: 0
},
'100%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
}
})
export const moveLeftOut = new Keyframes('antMoveLeftOut', {
'0%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
},
'100%': {
transform: 'translate3d(-100%, 0, 0)',
transformOrigin: '0 0',
opacity: 0
}
})
export const moveRightIn = new Keyframes('antMoveRightIn', {
'0%': {
transform: 'translate3d(100%, 0, 0)',
transformOrigin: '0 0',
opacity: 0
},
'100%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
}
})
export const moveRightOut = new Keyframes('antMoveRightOut', {
'0%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
},
'100%': {
transform: 'translate3d(100%, 0, 0)',
transformOrigin: '0 0',
opacity: 0
}
})
export const moveUpIn = new Keyframes('antMoveUpIn', {
'0%': {
transform: 'translate3d(0, -100%, 0)',
transformOrigin: '0 0',
opacity: 0
},
'100%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
}
})
export const moveUpOut = new Keyframes('antMoveUpOut', {
'0%': {
transform: 'translate3d(0, 0, 0)',
transformOrigin: '0 0',
opacity: 1
},
'100%': {
transform: 'translate3d(0, -100%, 0)',
transformOrigin: '0 0',
opacity: 0
}
})
type MoveMotionTypes = 'move-up' | 'move-down' | 'move-left' | 'move-right'
const moveMotion: Record<MoveMotionTypes, { inKeyframes: Keyframes; outKeyframes: Keyframes }> = {
'move-up': {
inKeyframes: moveUpIn,
outKeyframes: moveUpOut
},
'move-down': {
inKeyframes: moveDownIn,
outKeyframes: moveDownOut
},
'move-left': {
inKeyframes: moveLeftIn,
outKeyframes: moveLeftOut
},
'move-right': {
inKeyframes: moveRightIn,
outKeyframes: moveRightOut
}
}
export const initMoveMotion = (token: TokenWithCommonCls<AliasToken>, motionName: MoveMotionTypes): CSSInterpolation => {
const { antCls } = token
const motionCls = `${antCls}-${motionName}`
const { inKeyframes, outKeyframes } = moveMotion[motionName]
return [
initMotion(motionCls, inKeyframes, outKeyframes, token.motionDurationMid),
{
[`
${motionCls}-enter,
${motionCls}-appear
`]: {
opacity: 0,
animationTimingFunction: token.motionEaseOutCirc
},
[`${motionCls}-leave`]: {
animationTimingFunction: token.motionEaseInOutCirc
}
}
]
}

View File

@ -0,0 +1,163 @@
import type { CSSInterpolation } from '@antd-tiny-vue/cssinjs'
import { Keyframes } from '@antd-tiny-vue/cssinjs'
import type { AliasToken } from '../../theme/internal'
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'
import { initMotion } from './motion'
export const slideUpIn = new Keyframes('antSlideUpIn', {
'0%': {
transform: 'scaleY(0.8)',
transformOrigin: '0% 0%',
opacity: 0
},
'100%': {
transform: 'scaleY(1)',
transformOrigin: '0% 0%',
opacity: 1
}
})
export const slideUpOut = new Keyframes('antSlideUpOut', {
'0%': {
transform: 'scaleY(1)',
transformOrigin: '0% 0%',
opacity: 1
},
'100%': {
transform: 'scaleY(0.8)',
transformOrigin: '0% 0%',
opacity: 0
}
})
export const slideDownIn = new Keyframes('antSlideDownIn', {
'0%': {
transform: 'scaleY(0.8)',
transformOrigin: '100% 100%',
opacity: 0
},
'100%': {
transform: 'scaleY(1)',
transformOrigin: '100% 100%',
opacity: 1
}
})
export const slideDownOut = new Keyframes('antSlideDownOut', {
'0%': {
transform: 'scaleY(1)',
transformOrigin: '100% 100%',
opacity: 1
},
'100%': {
transform: 'scaleY(0.8)',
transformOrigin: '100% 100%',
opacity: 0
}
})
export const slideLeftIn = new Keyframes('antSlideLeftIn', {
'0%': {
transform: 'scaleX(0.8)',
transformOrigin: '0% 0%',
opacity: 0
},
'100%': {
transform: 'scaleX(1)',
transformOrigin: '0% 0%',
opacity: 1
}
})
export const slideLeftOut = new Keyframes('antSlideLeftOut', {
'0%': {
transform: 'scaleX(1)',
transformOrigin: '0% 0%',
opacity: 1
},
'100%': {
transform: 'scaleX(0.8)',
transformOrigin: '0% 0%',
opacity: 0
}
})
export const slideRightIn = new Keyframes('antSlideRightIn', {
'0%': {
transform: 'scaleX(0.8)',
transformOrigin: '100% 0%',
opacity: 0
},
'100%': {
transform: 'scaleX(1)',
transformOrigin: '100% 0%',
opacity: 1
}
})
export const slideRightOut = new Keyframes('antSlideRightOut', {
'0%': {
transform: 'scaleX(1)',
transformOrigin: '100% 0%',
opacity: 1
},
'100%': {
transform: 'scaleX(0.8)',
transformOrigin: '100% 0%',
opacity: 0
}
})
type SlideMotionTypes = 'slide-up' | 'slide-down' | 'slide-left' | 'slide-right'
const slideMotion: Record<SlideMotionTypes, { inKeyframes: Keyframes; outKeyframes: Keyframes }> = {
'slide-up': {
inKeyframes: slideUpIn,
outKeyframes: slideUpOut
},
'slide-down': {
inKeyframes: slideDownIn,
outKeyframes: slideDownOut
},
'slide-left': {
inKeyframes: slideLeftIn,
outKeyframes: slideLeftOut
},
'slide-right': {
inKeyframes: slideRightIn,
outKeyframes: slideRightOut
}
}
export const initSlideMotion = (token: TokenWithCommonCls<AliasToken>, motionName: SlideMotionTypes): CSSInterpolation => {
const { antCls } = token
const motionCls = `${antCls}-${motionName}`
const { inKeyframes, outKeyframes } = slideMotion[motionName]
return [
initMotion(motionCls, inKeyframes, outKeyframes, token.motionDurationMid),
{
[`
${motionCls}-enter,
${motionCls}-appear
`]: {
transform: 'scale(0)',
transformOrigin: '0% 0%',
opacity: 0,
animationTimingFunction: token.motionEaseOutQuint
},
[`${motionCls}-leave`]: {
animationTimingFunction: token.motionEaseInQuint
}
}
]
}

View File

@ -0,0 +1,215 @@
import type { CSSInterpolation } from '@antd-tiny-vue/cssinjs'
import { Keyframes } from '@antd-tiny-vue/cssinjs'
import type { AliasToken } from '../../theme/internal'
import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'
import { initMotion } from './motion'
export const zoomIn = new Keyframes('antZoomIn', {
'0%': {
transform: 'scale(0.2)',
opacity: 0
},
'100%': {
transform: 'scale(1)',
opacity: 1
}
})
export const zoomOut = new Keyframes('antZoomOut', {
'0%': {
transform: 'scale(1)'
},
'100%': {
transform: 'scale(0.2)',
opacity: 0
}
})
export const zoomBigIn = new Keyframes('antZoomBigIn', {
'0%': {
transform: 'scale(0.8)',
opacity: 0
},
'100%': {
transform: 'scale(1)',
opacity: 1
}
})
export const zoomBigOut = new Keyframes('antZoomBigOut', {
'0%': {
transform: 'scale(1)'
},
'100%': {
transform: 'scale(0.8)',
opacity: 0
}
})
export const zoomUpIn = new Keyframes('antZoomUpIn', {
'0%': {
transform: 'scale(0.8)',
transformOrigin: '50% 0%',
opacity: 0
},
'100%': {
transform: 'scale(1)',
transformOrigin: '50% 0%'
}
})
export const zoomUpOut = new Keyframes('antZoomUpOut', {
'0%': {
transform: 'scale(1)',
transformOrigin: '50% 0%'
},
'100%': {
transform: 'scale(0.8)',
transformOrigin: '50% 0%',
opacity: 0
}
})
export const zoomLeftIn = new Keyframes('antZoomLeftIn', {
'0%': {
transform: 'scale(0.8)',
transformOrigin: '0% 50%',
opacity: 0
},
'100%': {
transform: 'scale(1)',
transformOrigin: '0% 50%'
}
})
export const zoomLeftOut = new Keyframes('antZoomLeftOut', {
'0%': {
transform: 'scale(1)',
transformOrigin: '0% 50%'
},
'100%': {
transform: 'scale(0.8)',
transformOrigin: '0% 50%',
opacity: 0
}
})
export const zoomRightIn = new Keyframes('antZoomRightIn', {
'0%': {
transform: 'scale(0.8)',
transformOrigin: '100% 50%',
opacity: 0
},
'100%': {
transform: 'scale(1)',
transformOrigin: '100% 50%'
}
})
export const zoomRightOut = new Keyframes('antZoomRightOut', {
'0%': {
transform: 'scale(1)',
transformOrigin: '100% 50%'
},
'100%': {
transform: 'scale(0.8)',
transformOrigin: '100% 50%',
opacity: 0
}
})
export const zoomDownIn = new Keyframes('antZoomDownIn', {
'0%': {
transform: 'scale(0.8)',
transformOrigin: '50% 100%',
opacity: 0
},
'100%': {
transform: 'scale(1)',
transformOrigin: '50% 100%'
}
})
export const zoomDownOut = new Keyframes('antZoomDownOut', {
'0%': {
transform: 'scale(1)',
transformOrigin: '50% 100%'
},
'100%': {
transform: 'scale(0.8)',
transformOrigin: '50% 100%',
opacity: 0
}
})
type ZoomMotionTypes = 'zoom' | 'zoom-big' | 'zoom-big-fast' | 'zoom-left' | 'zoom-right' | 'zoom-up' | 'zoom-down'
const zoomMotion: Record<ZoomMotionTypes, { inKeyframes: Keyframes; outKeyframes: Keyframes }> = {
zoom: {
inKeyframes: zoomIn,
outKeyframes: zoomOut
},
'zoom-big': {
inKeyframes: zoomBigIn,
outKeyframes: zoomBigOut
},
'zoom-big-fast': {
inKeyframes: zoomBigIn,
outKeyframes: zoomBigOut
},
'zoom-left': {
inKeyframes: zoomLeftIn,
outKeyframes: zoomLeftOut
},
'zoom-right': {
inKeyframes: zoomRightIn,
outKeyframes: zoomRightOut
},
'zoom-up': {
inKeyframes: zoomUpIn,
outKeyframes: zoomUpOut
},
'zoom-down': {
inKeyframes: zoomDownIn,
outKeyframes: zoomDownOut
}
}
export const initZoomMotion = (token: TokenWithCommonCls<AliasToken>, motionName: ZoomMotionTypes): CSSInterpolation => {
const { antCls } = token
const motionCls = `${antCls}-${motionName}`
const { inKeyframes, outKeyframes } = zoomMotion[motionName]
return [
initMotion(motionCls, inKeyframes, outKeyframes, motionName === 'zoom-big-fast' ? token.motionDurationFast : token.motionDurationMid),
{
[`
${motionCls}-enter,
${motionCls}-appear
`]: {
transform: 'scale(0)',
opacity: 0,
animationTimingFunction: token.motionEaseOutCirc,
'&-prepare': {
transform: 'none'
}
},
[`${motionCls}-leave`]: {
animationTimingFunction: token.motionEaseInOutCirc
}
}
]
}

View File

@ -0,0 +1,21 @@
import type { CSSObject } from '@antd-tiny-vue/cssinjs'
import type { DerivativeToken } from '../theme/internal'
// eslint-disable-next-line import/prefer-default-export
export const operationUnit = (token: DerivativeToken): CSSObject => ({
// FIXME: This use link but is a operation unit. Seems should be a colorPrimary.
// And Typography use this to generate link style which should not do this.
color: token.colorLink,
textDecoration: 'none',
outline: 'none',
cursor: 'pointer',
transition: `color ${token.motionDurationSlow}`,
'&:focus, &:hover': {
color: token.colorLinkHover
},
'&:active': {
color: token.colorLinkActive
}
})

View File

@ -0,0 +1,191 @@
import type { CSSInterpolation, CSSObject } from '@antd-tiny-vue/cssinjs'
import type { AliasToken } from '../theme/internal'
import type { TokenWithCommonCls } from '../theme/util/genComponentStyleHook'
import { roundedArrow } from './roundedArrow'
export const MAX_VERTICAL_CONTENT_RADIUS = 8
export function getArrowOffset(options: { contentRadius: number; limitVerticalRadius?: boolean }) {
const maxVerticalContentRadius = MAX_VERTICAL_CONTENT_RADIUS
const { contentRadius, limitVerticalRadius } = options
const dropdownArrowOffset = contentRadius > 12 ? contentRadius + 2 : 12
const dropdownArrowOffsetVertical = limitVerticalRadius ? maxVerticalContentRadius : dropdownArrowOffset
return { dropdownArrowOffset, dropdownArrowOffsetVertical }
}
function isInject(valid: boolean, code: CSSObject): CSSObject {
if (!valid) return {}
return code
}
export default function getArrowStyle<Token extends TokenWithCommonCls<AliasToken>>(
token: Token,
options: {
colorBg: string
showArrowCls?: string
contentRadius?: number
limitVerticalRadius?: boolean
arrowDistance?: number
arrowPlacement?: {
left?: boolean
right?: boolean
top?: boolean
bottom?: boolean
}
}
): CSSInterpolation {
const { componentCls, sizePopupArrow, borderRadiusXS, borderRadiusOuter, boxShadowPopoverArrow } = token
const {
colorBg,
contentRadius = token.borderRadiusLG,
limitVerticalRadius,
arrowDistance = 0,
arrowPlacement = {
left: true,
right: true,
top: true,
bottom: true
}
} = options
const { dropdownArrowOffsetVertical, dropdownArrowOffset } = getArrowOffset({
contentRadius,
limitVerticalRadius
})
return {
[componentCls]: {
// ============================ Basic ============================
[`${componentCls}-arrow`]: [
{
position: 'absolute',
zIndex: 1, // lift it up so the menu wouldn't cask shadow on it
display: 'block',
...roundedArrow(sizePopupArrow, borderRadiusXS, borderRadiusOuter, 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: dropdownArrowOffset
}
},
[`&-placement-topRight ${componentCls}-arrow`]: {
right: {
_skip_check_: true,
value: dropdownArrowOffset
}
}
}),
// >>>>> 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: dropdownArrowOffset
}
},
[`&-placement-bottomRight ${componentCls}-arrow`]: {
right: {
_skip_check_: true,
value: dropdownArrowOffset
}
}
}),
// >>>>> 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: dropdownArrowOffsetVertical
},
[`&-placement-leftBottom ${componentCls}-arrow`]: {
bottom: dropdownArrowOffsetVertical
}
}),
// >>>>> 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: dropdownArrowOffsetVertical
},
[`&-placement-rightBottom ${componentCls}-arrow`]: {
bottom: dropdownArrowOffsetVertical
}
})
}
}
}

View File

@ -0,0 +1,32 @@
/* eslint-disable import/prefer-default-export */
import type { CSSObject } from '@antd-tiny-vue/cssinjs'
import type { AliasToken, PresetColorKey } from '../theme/internal'
import { PresetColors } from '../theme/internal'
import type { TokenWithCommonCls } from '../theme/util/genComponentStyleHook'
interface CalcColor {
/** token[`${colorKey}-1`] */
lightColor: string
/** token[`${colorKey}-3`] */
lightBorderColor: string
/** token[`${colorKey}-6`] */
darkColor: string
/** token[`${colorKey}-7`] */
textColor: string
}
type GenCSS = (colorKey: PresetColorKey, calcColor: CalcColor) => CSSObject
export function genPresetColor<Token extends TokenWithCommonCls<AliasToken>>(token: Token, genCss: GenCSS): CSSObject {
return PresetColors.reduce((prev: CSSObject, colorKey: PresetColorKey) => {
const lightColor = token[`${colorKey}-1`]
const lightBorderColor = token[`${colorKey}-3`]
const darkColor = token[`${colorKey}-6`]
const textColor = token[`${colorKey}-7`]
return {
...prev,
...genCss(colorKey, { lightColor, lightBorderColor, darkColor, textColor })
}
}, {} as CSSObject)
}

253
components/style/reset.css Normal file
View File

@ -0,0 +1,253 @@
/* stylelint-disable */
html,
body {
width: 100%;
height: 100%;
}
input::-ms-clear,
input::-ms-reveal {
display: none;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: sans-serif;
line-height: 1.15;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-ms-overflow-style: scrollbar;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
@-ms-viewport {
width: device-width;
}
body {
margin: 0;
}
[tabindex='-1']:focus {
outline: none;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 0;
margin-bottom: 0.5em;
font-weight: 500;
}
p {
margin-top: 0;
margin-bottom: 1em;
}
abbr[title],
abbr[data-original-title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline;
text-decoration: underline dotted;
border-bottom: 0;
cursor: help;
}
address {
margin-bottom: 1em;
font-style: normal;
line-height: inherit;
}
input[type='text'],
input[type='password'],
input[type='number'],
textarea {
-webkit-appearance: none;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1em;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 500;
}
dd {
margin-bottom: 0.5em;
margin-left: 0;
}
blockquote {
margin: 0 0 1em;
}
dfn {
font-style: italic;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 80%;
}
sub,
sup {
position: relative;
font-size: 75%;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
pre,
code,
kbd,
samp {
font-size: 1em;
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
}
pre {
margin-top: 0;
margin-bottom: 1em;
overflow: auto;
}
figure {
margin: 0 0 1em;
}
img {
vertical-align: middle;
border-style: none;
}
a,
area,
button,
[role='button'],
input:not([type='range']),
label,
select,
summary,
textarea {
touch-action: manipulation;
}
table {
border-collapse: collapse;
}
caption {
padding-top: 0.75em;
padding-bottom: 0.3em;
text-align: left;
caption-side: bottom;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
color: inherit;
font-size: inherit;
font-family: inherit;
line-height: inherit;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
html [type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type='radio'],
input[type='checkbox'] {
box-sizing: border-box;
padding: 0;
}
input[type='date'],
input[type='time'],
input[type='datetime-local'],
input[type='month'] {
-webkit-appearance: listbox;
}
textarea {
overflow: auto;
resize: vertical;
}
fieldset {
min-width: 0;
margin: 0;
padding: 0;
border: 0;
}
legend {
display: block;
width: 100%;
max-width: 100%;
margin-bottom: 0.5em;
padding: 0;
color: inherit;
font-size: 1.5em;
line-height: inherit;
white-space: normal;
}
progress {
vertical-align: baseline;
}
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
height: auto;
}
[type='search'] {
outline-offset: -2px;
-webkit-appearance: none;
}
[type='search']::-webkit-search-cancel-button,
[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none !important;
}
mark {
padding: 0.2em;
background-color: #feffe6;
}

View File

@ -0,0 +1,57 @@
/* eslint-disable import/prefer-default-export */
import type { CSSObject } from '@antd-tiny-vue/cssinjs'
export const roundedArrow = (width: number, innerRadius: number, outerRadius: number, bgColor: string, boxShadow: string): CSSObject => {
const unitWidth = width / 2
const ax = 0
const ay = unitWidth
const bx = (outerRadius * 1) / Math.sqrt(2)
const by = unitWidth - outerRadius * (1 - 1 / Math.sqrt(2))
const cx = unitWidth - innerRadius * (1 / Math.sqrt(2))
const cy = outerRadius * (Math.sqrt(2) - 1) + innerRadius * (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) + outerRadius * (Math.sqrt(2) - 2)
return {
pointerEvents: 'none',
width,
height: width,
overflow: 'hidden',
'&::before': {
position: 'absolute',
bottom: 0,
insetInlineStart: 0,
width,
height: width / 2,
background: bgColor,
clipPath: `path('M ${ax} ${ay} A ${outerRadius} ${outerRadius} 0 0 0 ${bx} ${by} L ${cx} ${cy} A ${innerRadius} ${innerRadius} 0 0 1 ${dx} ${dy} L ${ex} ${ey} A ${outerRadius} ${outerRadius} 0 0 0 ${fx} ${fy} Z')`,
content: '""'
},
'&::after': {
content: '""',
position: 'absolute',
width: shadowWidth,
height: shadowWidth,
bottom: 0,
insetInline: 0,
margin: 'auto',
borderRadius: {
_skip_check_: true,
value: `0 0 ${innerRadius}px 0`
},
transform: 'translateY(50%) rotate(-135deg)',
boxShadow,
zIndex: 0,
background: 'transparent'
}
}
}