diff --git a/components/_util/responsiveObserver.ts b/components/_util/responsiveObserver.ts index 578cfac170..be7dea6f41 100644 --- a/components/_util/responsiveObserver.ts +++ b/components/_util/responsiveObserver.ts @@ -1,6 +1,6 @@ import React from 'react'; -import type { GlobalToken } from '../theme/interface'; +import type { GlobalToken } from '../theme/internal'; import { useToken } from '../theme/internal'; export type Breakpoint = 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs'; diff --git a/components/_util/wave/interface.ts b/components/_util/wave/interface.ts index 171f91e7ac..952d98ffe6 100644 --- a/components/_util/wave/interface.ts +++ b/components/_util/wave/interface.ts @@ -1,5 +1,5 @@ import { defaultPrefixCls } from '../../config-provider'; -import type { GlobalToken } from '../../theme'; +import type { GlobalToken } from '../../theme/internal'; export const TARGET_CLS = `${defaultPrefixCls}-wave-target`; diff --git a/components/badge/style/index.ts b/components/badge/style/index.ts index ab785e6647..620ffaf4d2 100644 --- a/components/badge/style/index.ts +++ b/components/badge/style/index.ts @@ -1,9 +1,13 @@ import { Keyframes, unit } from '@ant-design/cssinjs'; import { resetComponent } from '../../style'; -import type { FullToken, GenerateStyle } from '../../theme/internal'; +import type { + FullToken, + GenerateStyle, + GenStyleFn, + GetDefaultToken, +} from '../../theme/internal'; import { genPresetColor, genStyleHooks, mergeToken } from '../../theme/internal'; -import type { GenStyleFn, GetDefaultToken } from '../../theme/util/genComponentStyleHook'; /** Component only token. Which will handle additional calculation of alias token */ export interface ComponentToken { diff --git a/components/button/style/token.ts b/components/button/style/token.ts index 9f70f2e667..6eb33b3149 100644 --- a/components/button/style/token.ts +++ b/components/button/style/token.ts @@ -1,8 +1,11 @@ import type { CSSProperties } from 'react'; -import type { FullToken, GetDefaultToken } from '../../theme/internal'; +import type { + FullToken, + GetDefaultToken, + GenStyleFn, +} from '../../theme/internal'; import { getLineHeight, mergeToken } from '../../theme/internal'; -import type { GenStyleFn } from '../../theme/util/genComponentStyleHook'; /** Component only token. Which will handle additional calculation of alias token */ export interface ComponentToken { diff --git a/components/cascader/style/index.ts b/components/cascader/style/index.ts index 7b03acd1a1..a974def860 100644 --- a/components/cascader/style/index.ts +++ b/components/cascader/style/index.ts @@ -1,8 +1,7 @@ import type { CSSProperties } from 'react'; import { genCompactItemStyle } from '../../style/compact-item'; -import type { GlobalToken } from '../../theme'; -import type { FullToken, GenerateStyle } from '../../theme/internal'; +import type { FullToken, GenerateStyle, GlobalToken } from '../../theme/internal'; import { genStyleHooks } from '../../theme/internal'; import getColumnsStyle from './columns'; diff --git a/components/config-provider/__tests__/theme.test.tsx b/components/config-provider/__tests__/theme.test.tsx index 441f1c9032..11f66c7674 100644 --- a/components/config-provider/__tests__/theme.test.tsx +++ b/components/config-provider/__tests__/theme.test.tsx @@ -7,7 +7,7 @@ import { Button, InputNumber, Select } from '../..'; import { resetWarned } from '../../_util/warning'; import { render } from '../../../tests/utils'; import theme from '../../theme'; -import type { GlobalToken } from '../../theme'; +import type { GlobalToken } from '../../theme/internal'; import { useToken } from '../../theme/internal'; const { defaultAlgorithm, darkAlgorithm, compactAlgorithm } = theme; diff --git a/components/date-picker/style/token.ts b/components/date-picker/style/token.ts index 2483c7cc96..44cb3cee05 100644 --- a/components/date-picker/style/token.ts +++ b/components/date-picker/style/token.ts @@ -5,12 +5,12 @@ import { initComponentToken } from '../../input/style/token'; import type { MultipleSelectorToken, SelectorToken } from '../../select/style/token'; import type { ArrowToken } from '../../style/roundedArrow'; import { getArrowToken } from '../../style/roundedArrow'; -import type { GlobalToken } from '../../theme/interface'; import type { + GlobalToken, FullToken, GetDefaultToken, TokenWithCommonCls, -} from '../../theme/util/genComponentStyleHook'; +} from '../../theme/internal'; export interface PanelComponentToken extends MultipleSelectorToken { /** diff --git a/components/form/style/index.ts b/components/form/style/index.ts index 6680fee2bd..d3eaeba7d9 100644 --- a/components/form/style/index.ts +++ b/components/form/style/index.ts @@ -4,9 +4,14 @@ import { unit } from '@ant-design/cssinjs'; import { resetComponent } from '../../style'; import { genCollapseMotion, zoomIn } from '../../style/motion'; -import type { AliasToken, FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal'; +import type { + AliasToken, + FullToken, + GenerateStyle, + GetDefaultToken, + GenStyleFn, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { GenStyleFn } from '../../theme/util/genComponentStyleHook'; import genFormValidateMotionStyle from './explain'; export interface ComponentToken { diff --git a/components/modal/style/index.ts b/components/modal/style/index.ts index bcd2882608..10a1d139de 100644 --- a/components/modal/style/index.ts +++ b/components/modal/style/index.ts @@ -3,10 +3,15 @@ import { unit } from '@ant-design/cssinjs'; import { genFocusStyle, resetComponent } from '../../style'; import { initFadeMotion, initZoomMotion } from '../../style/motion'; -import type { GlobalToken } from '../../theme'; -import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal'; +import type { + AliasToken, + FullToken, + GenerateStyle, + GlobalToken, + GenStyleFn, + TokenWithCommonCls, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { GenStyleFn, TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; /** Component only token. Which will handle additional calculation of alias token */ export interface ComponentToken { diff --git a/components/notification/style/index.ts b/components/notification/style/index.ts index 2bbc3356ab..4a9cb8dc16 100644 --- a/components/notification/style/index.ts +++ b/components/notification/style/index.ts @@ -3,9 +3,13 @@ import { Keyframes, unit } from '@ant-design/cssinjs'; import { CONTAINER_MAX_OFFSET } from '../../_util/hooks/useZIndex'; import { genFocusStyle, resetComponent } from '../../style'; -import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal'; +import type { + AliasToken, + FullToken, + GenerateStyle, + GenStyleFn, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { GenStyleFn } from '../../theme/util/genComponentStyleHook'; import genNotificationPlacementStyle from './placement'; import genStackStyle from './stack'; diff --git a/components/pagination/style/bordered.ts b/components/pagination/style/bordered.ts index 2275d547c6..3f192726c7 100644 --- a/components/pagination/style/bordered.ts +++ b/components/pagination/style/bordered.ts @@ -3,7 +3,7 @@ import { unit } from '@ant-design/cssinjs'; import type { PaginationToken } from '.'; import { prepareComponentToken, prepareToken } from '.'; import type { GenerateStyle } from '../../theme/interface'; -import { genSubStyleComponent } from '../../theme/util/genComponentStyleHook'; +import { genSubStyleComponent } from '../../theme/internal'; const genBorderedStyle: GenerateStyle = (token) => { const { componentCls } = token; diff --git a/components/pagination/style/index.ts b/components/pagination/style/index.ts index e091dcc330..6079ea5c0b 100644 --- a/components/pagination/style/index.ts +++ b/components/pagination/style/index.ts @@ -1,6 +1,5 @@ import { unit } from '@ant-design/cssinjs'; import type { CSSObject } from '@ant-design/cssinjs'; -import type { GenStyleFn } from 'antd/es/theme/util/genComponentStyleHook'; import { genBasicInputStyle, @@ -11,7 +10,12 @@ import { import type { SharedComponentToken, SharedInputToken } from '../../input/style/token'; import { genBaseOutlinedStyle, genDisabledStyle } from '../../input/style/variants'; import { genFocusOutline, genFocusStyle, resetComponent } from '../../style'; -import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal'; +import type { + FullToken, + GenerateStyle, + GetDefaultToken, + GenStyleFn, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; export interface ComponentToken { diff --git a/components/select/style/multiple.ts b/components/select/style/multiple.ts index 4eeebacc41..25897936bd 100644 --- a/components/select/style/multiple.ts +++ b/components/select/style/multiple.ts @@ -3,8 +3,7 @@ import { unit } from '@ant-design/cssinjs'; import { resetIcon } from '../../style'; import { mergeToken } from '../../theme/internal'; -import type { AliasToken } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../../theme/internal'; import type { SelectToken } from './token'; type SelectItemToken = Pick< diff --git a/components/select/style/token.ts b/components/select/style/token.ts index de89197582..2fde549fa8 100644 --- a/components/select/style/token.ts +++ b/components/select/style/token.ts @@ -1,5 +1,5 @@ import type { CSSProperties } from 'react'; -import type { FullToken, GetDefaultToken } from 'antd/es/theme/util/genComponentStyleHook'; +import type { FullToken, GetDefaultToken } from 'antd/es/theme/internal'; export interface MultipleSelectorToken { /** diff --git a/components/skeleton/style/index.ts b/components/skeleton/style/index.ts index 934202d802..efafbbd8db 100644 --- a/components/skeleton/style/index.ts +++ b/components/skeleton/style/index.ts @@ -1,9 +1,13 @@ import type { CSSObject } from '@ant-design/cssinjs'; import { Keyframes, unit } from '@ant-design/cssinjs'; -import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal'; +import type { + FullToken, + GenerateStyle, + GetDefaultToken, + CSSUtil, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { CSSUtil } from '../../theme/util/genComponentStyleHook'; export type ComponentToken = { /** @deprecated use gradientFromColor instead. */ diff --git a/components/style/compact-item-vertical.ts b/components/style/compact-item-vertical.ts index 8d6125f67a..a57e68061d 100644 --- a/components/style/compact-item-vertical.ts +++ b/components/style/compact-item-vertical.ts @@ -1,8 +1,12 @@ /* eslint-disable import/prefer-default-export */ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs'; -import type { AliasToken, FullToken } from '../theme/internal'; -import type { CSSUtil, OverrideComponent } from '../theme/util/genComponentStyleHook'; +import type { + AliasToken, + FullToken, + OverrideComponent, + CSSUtil, +} from '../theme/internal'; function compactItemVerticalBorder(token: AliasToken & CSSUtil, parentCls: string): CSSObject { return { diff --git a/components/style/compact-item.ts b/components/style/compact-item.ts index 7f5e94f8fd..c1ff882e63 100644 --- a/components/style/compact-item.ts +++ b/components/style/compact-item.ts @@ -1,8 +1,12 @@ /* eslint-disable import/prefer-default-export */ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs'; -import type { AliasToken, FullToken } from '../theme/internal'; -import type { CSSUtil, OverrideComponent } from '../theme/util/genComponentStyleHook'; +import type { + AliasToken, + FullToken, + OverrideComponent, + CSSUtil, +} from '../theme/internal'; interface CompactItemOptions { focus?: boolean; diff --git a/components/style/index.tsx b/components/style/index.tsx index 633abf3310..04ae8ba623 100644 --- a/components/style/index.tsx +++ b/components/style/index.tsx @@ -2,7 +2,7 @@ import { unit } from '@ant-design/cssinjs'; import type { CSSObject } from '@ant-design/cssinjs'; -import type { AliasToken, DerivativeToken } from '../theme/internal'; +import type { AliasToken } from '../theme/internal'; export { operationUnit } from './operationUnit'; @@ -13,7 +13,7 @@ export const textEllipsis: CSSObject = { }; export const resetComponent = ( - token: DerivativeToken, + token: AliasToken, needInheritFontFamily = false, ): CSSObject => ({ boxSizing: 'border-box', @@ -66,7 +66,7 @@ export const clearFix = (): CSSObject => ({ }, }); -export const genLinkStyle = (token: DerivativeToken): CSSObject => ({ +export const genLinkStyle = (token: AliasToken): CSSObject => ({ a: { color: token.colorLink, textDecoration: token.linkDecoration, @@ -103,7 +103,7 @@ export const genLinkStyle = (token: DerivativeToken): CSSObject => ({ }); export const genCommonStyle = ( - token: DerivativeToken, + token: AliasToken, componentPrefixCls: string, rootCls?: string, resetFont?: boolean, @@ -144,7 +144,7 @@ export const genFocusOutline = (token: AliasToken): CSSObject => ({ transition: 'outline-offset 0s, outline 0s', }); -export const genFocusStyle = (token: DerivativeToken): CSSObject => ({ +export const genFocusStyle = (token: AliasToken): CSSObject => ({ '&:focus-visible': { ...genFocusOutline(token), }, diff --git a/components/style/motion/collapse.ts b/components/style/motion/collapse.ts index 38c4fcf191..37cf3c53ce 100644 --- a/components/style/motion/collapse.ts +++ b/components/style/motion/collapse.ts @@ -1,5 +1,4 @@ -import type { AliasToken, GenerateStyle } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, GenerateStyle, TokenWithCommonCls } from '../../theme/internal'; const genCollapseMotion: GenerateStyle> = (token) => ({ [token.componentCls]: { diff --git a/components/style/motion/fade.ts b/components/style/motion/fade.ts index 547ecf2f5e..f364f3062e 100644 --- a/components/style/motion/fade.ts +++ b/components/style/motion/fade.ts @@ -1,8 +1,7 @@ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { Keyframes } from '@ant-design/cssinjs'; -import type { AliasToken } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../../theme/internal'; import { initMotion } from './motion'; export const fadeIn = new Keyframes('antFadeIn', { diff --git a/components/style/motion/move.ts b/components/style/motion/move.ts index 3159f3c79a..130add57b2 100644 --- a/components/style/motion/move.ts +++ b/components/style/motion/move.ts @@ -1,8 +1,7 @@ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { Keyframes } from '@ant-design/cssinjs'; -import type { AliasToken } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../../theme/internal'; import { initMotion } from './motion'; export const moveDownIn = new Keyframes('antMoveDownIn', { diff --git a/components/style/motion/slide.ts b/components/style/motion/slide.ts index 419aaca0c5..65b96ef051 100644 --- a/components/style/motion/slide.ts +++ b/components/style/motion/slide.ts @@ -1,8 +1,7 @@ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { Keyframes } from '@ant-design/cssinjs'; -import type { AliasToken } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../../theme/internal'; import { initMotion } from './motion'; export const slideUpIn = new Keyframes('antSlideUpIn', { diff --git a/components/style/motion/zoom.ts b/components/style/motion/zoom.ts index a1a6446d87..3be47af4ce 100644 --- a/components/style/motion/zoom.ts +++ b/components/style/motion/zoom.ts @@ -1,8 +1,7 @@ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { Keyframes } from '@ant-design/cssinjs'; -import type { AliasToken } from '../../theme/internal'; -import type { TokenWithCommonCls } from '../../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../../theme/internal'; import { initMotion } from './motion'; export const zoomIn = new Keyframes('antZoomIn', { diff --git a/components/style/operationUnit.ts b/components/style/operationUnit.ts index 1ba44e897a..055b43c7fa 100644 --- a/components/style/operationUnit.ts +++ b/components/style/operationUnit.ts @@ -1,9 +1,9 @@ import type { CSSObject } from '@ant-design/cssinjs'; -import type { DerivativeToken } from '../theme/internal'; +import type { AliasToken } from '../theme/internal'; // eslint-disable-next-line import/prefer-default-export -export const operationUnit = (token: DerivativeToken): CSSObject => ({ +export const operationUnit = (token: AliasToken): 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, diff --git a/components/style/placementArrow.ts b/components/style/placementArrow.ts index 1d65848b15..38e830416b 100644 --- a/components/style/placementArrow.ts +++ b/components/style/placementArrow.ts @@ -1,7 +1,6 @@ import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs'; -import type { AliasToken } from '../theme/internal'; -import type { TokenWithCommonCls } from '../theme/util/genComponentStyleHook'; +import type { AliasToken, TokenWithCommonCls } from '../theme/internal'; import type { ArrowToken } from './roundedArrow'; import { genRoundedArrow } from './roundedArrow'; diff --git a/components/style/roundedArrow.ts b/components/style/roundedArrow.ts index d8cb725056..7e0896c821 100644 --- a/components/style/roundedArrow.ts +++ b/components/style/roundedArrow.ts @@ -1,8 +1,7 @@ /* eslint-disable import/prefer-default-export */ import type { CSSObject } from '@ant-design/cssinjs'; import { unit } from '@ant-design/cssinjs'; -import type { CSSUtil } from 'antd/es/theme/util/genComponentStyleHook'; - +import type { CSSUtil } from '../theme/internal'; import type { AliasToken } from '../theme/interface'; export interface ArrowToken { diff --git a/components/tag/style/index.ts b/components/tag/style/index.ts index 547f5eddeb..90ea37ed1c 100644 --- a/components/tag/style/index.ts +++ b/components/tag/style/index.ts @@ -4,9 +4,12 @@ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { TinyColor } from '@ctrl/tinycolor'; import { resetComponent } from '../../style'; -import type { FullToken } from '../../theme/internal'; +import type { + FullToken, + GetDefaultToken, + GenStyleFn, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { GenStyleFn, GetDefaultToken } from '../../theme/util/genComponentStyleHook'; export interface ComponentToken { /** diff --git a/components/theme/__tests__/util.test.tsx b/components/theme/__tests__/util.test.tsx index 85bd763d74..45741d15ba 100644 --- a/components/theme/__tests__/util.test.tsx +++ b/components/theme/__tests__/util.test.tsx @@ -1,5 +1,4 @@ import getAlphaColor from '../util/getAlphaColor'; -import genMaxMin from '../util/maxmin'; describe('util', () => { describe('getAlphaColor', () => { @@ -7,34 +6,4 @@ describe('util', () => { expect(getAlphaColor('rgba(0, 0, 0, 0.5)', 'rgba(255, 255, 255)')).toBe('rgba(0, 0, 0, 0.5)'); }); }); - - describe('maxmin', () => { - const cases = [ - { - values: [1, 2, 3], - js: { - max: 3, - min: 1, - }, - css: { - max: 'max(1px,2px,3px)', - min: 'min(1px,2px,3px)', - }, - }, - ]; - - cases.forEach(({ values, js, css }, index) => { - it(`js maxmin ${index + 1}`, () => { - const { max, min } = genMaxMin('js'); - expect(max(...values)).toEqual(js.max); - expect(min(...values)).toEqual(js.min); - }); - - it(`css maxmin ${index + 1}`, () => { - const { max, min } = genMaxMin('css'); - expect(max(...values)).toEqual(css.max); - expect(min(...values)).toEqual(css.min); - }); - }); - }); }); diff --git a/components/theme/interface/cssinjs-utils.ts b/components/theme/interface/cssinjs-utils.ts new file mode 100644 index 0000000000..076acb9091 --- /dev/null +++ b/components/theme/interface/cssinjs-utils.ts @@ -0,0 +1,25 @@ +import type { + GlobalToken as GlobalTokenTypeUtil, + OverrideTokenMap as OverrideTokenTypeUtil, + FullToken as FullTokenTypeUtil, + GetDefaultToken as GetDefaultTokenTypeUtil, + GenStyleFn as GenStyleFnTypeUtil, + TokenMapKey, +} from '@ant-design/cssinjs-utils'; + +import type { AliasToken } from './alias'; +import type { ComponentTokenMap } from './components'; + + +/** Final token which contains the components level override */ +export type GlobalToken = GlobalTokenTypeUtil; + +export type OverrideToken = OverrideTokenTypeUtil; + +export type OverrideComponent = TokenMapKey; + +export type FullToken> = FullTokenTypeUtil; + +export type GetDefaultToken> = GetDefaultTokenTypeUtil; + +export type GenStyleFn> = GenStyleFnTypeUtil; diff --git a/components/theme/interface/index.ts b/components/theme/interface/index.ts index 79c2e2e16a..7628211f70 100644 --- a/components/theme/interface/index.ts +++ b/components/theme/interface/index.ts @@ -2,18 +2,19 @@ import type { CSSInterpolation, DerivativeFunc } from '@ant-design/cssinjs'; import type { AnyObject } from '../../_util/type'; import type { AliasToken } from './alias'; -import type { ComponentTokenMap } from './components'; import type { MapToken } from './maps'; import type { SeedToken } from './seeds'; export type MappingAlgorithm = DerivativeFunc; -export type OverrideToken = { - [key in keyof ComponentTokenMap]: Partial & Partial; -}; - -/** Final token which contains the components level override */ -export type GlobalToken = AliasToken & ComponentTokenMap; +export type { + GlobalToken, + OverrideToken, + FullToken, + OverrideComponent, + GetDefaultToken, + GenStyleFn, +} from './cssinjs-utils'; export type { AliasToken } from './alias'; export type { ComponentTokenMap } from './components'; diff --git a/components/theme/internal.ts b/components/theme/internal.ts index 1fa1e2c6ee..13835f345c 100644 --- a/components/theme/internal.ts +++ b/components/theme/internal.ts @@ -1,4 +1,10 @@ -import { genCalc as calc, useStyleRegister } from '@ant-design/cssinjs'; +import { useStyleRegister } from '@ant-design/cssinjs'; +import { + genCalc as calc, + mergeToken, + statisticToken, + statistic, +} from '@ant-design/cssinjs-utils'; import type { AliasToken, @@ -6,27 +12,34 @@ import type { PresetColorKey, PresetColorType, SeedToken, + GlobalToken, UseComponentStyleResult, + FullToken, + GetDefaultToken, + OverrideComponent, + GenStyleFn, } from './interface'; import { PresetColors } from './interface'; import { getLineHeight } from './themes/shared/genFontSizes'; import useToken from './useToken'; -import type { FullToken, GetDefaultToken } from './util/genComponentStyleHook'; -import genComponentStyleHook, { +import { + genComponentStyleHook, genStyleHooks, genSubStyleComponent, -} from './util/genComponentStyleHook'; +} from './util/genStyleUtils'; import genPresetColor from './util/genPresetColor'; -import statisticToken, { merge as mergeToken } from './util/statistic'; import useResetIconStyle from './util/useResetIconStyle'; +export type { CSSUtil, TokenWithCommonCls } from '@ant-design/cssinjs-utils'; + export { DesignTokenContext, defaultConfig } from './context'; export { - PresetColors, + // generators genComponentStyleHook, genSubStyleComponent, genPresetColor, genStyleHooks, + // utils mergeToken, statisticToken, calc, @@ -35,16 +48,20 @@ export { useResetIconStyle, useStyleRegister, useToken, + // constant + PresetColors, + statistic, }; export type { AliasToken, - // FIXME: Remove this type - AliasToken as DerivativeToken, FullToken, + OverrideComponent, GenerateStyle, PresetColorKey, PresetColorType, SeedToken, UseComponentStyleResult, GetDefaultToken, + GlobalToken, + GenStyleFn, }; diff --git a/components/theme/useToken.ts b/components/theme/useToken.ts index ef2fa912eb..de4a4405a9 100644 --- a/components/theme/useToken.ts +++ b/components/theme/useToken.ts @@ -5,7 +5,7 @@ import { useCacheToken } from '@ant-design/cssinjs'; import version from '../version'; import type { DesignTokenProviderProps } from './context'; import { defaultTheme, DesignTokenContext } from './context'; -import type { AliasToken, GlobalToken, MapToken, SeedToken } from './interface'; +import type { AliasToken, GlobalToken, SeedToken } from './interface'; import defaultSeedToken from './themes/seed'; import formatToken from './util/alias'; @@ -111,7 +111,7 @@ export const getComputedToken = ( // ================================== Hook ================================== export default function useToken(): [ - theme: Theme, + theme: Theme, token: GlobalToken, hashId: string, realToken: GlobalToken, diff --git a/components/theme/util/genComponentStyleHook.tsx b/components/theme/util/genComponentStyleHook.tsx deleted file mode 100644 index 8264b8ac78..0000000000 --- a/components/theme/util/genComponentStyleHook.tsx +++ /dev/null @@ -1,450 +0,0 @@ -/* eslint-disable no-redeclare */ -import type { ComponentType, FC, ReactElement } from 'react'; -import React, { useContext } from 'react'; -import type { AbstractCalculator, CSSInterpolation } from '@ant-design/cssinjs'; -import { genCalc, token2CSSVar, useCSSVarRegister, useStyleRegister } from '@ant-design/cssinjs'; -import { warning } from 'rc-util'; - -import useUniqueMemo from '../../_util/hooks/useUniqueMemo'; -import { ConfigContext } from '../../config-provider/context'; -import { genCommonStyle, genLinkStyle } from '../../style'; -import type { - AliasToken, - ComponentTokenMap, - GlobalToken, - OverrideToken, - UseComponentStyleResult, -} from '../interface'; -import useToken, { ignore, unitless } from '../useToken'; -import genMaxMin from './maxmin'; -import statisticToken, { merge as mergeToken } from './statistic'; -import useResetIconStyle from './useResetIconStyle'; - -export type OverrideTokenWithoutDerivative = ComponentTokenMap; -export type OverrideComponent = keyof OverrideTokenWithoutDerivative; -export type GlobalTokenWithComponent = GlobalToken & - ComponentTokenMap[C]; - -type ComponentToken = Exclude; -type ComponentTokenKey = keyof ComponentToken; - -export interface StyleInfo { - hashId: string; - prefixCls: string; - rootPrefixCls: string; - iconPrefixCls: string; -} - -export type CSSUtil = { - calc: (number: any) => AbstractCalculator; - max: (...values: (number | string)[]) => number | string; - min: (...values: (number | string)[]) => number | string; -}; - -export type TokenWithCommonCls = T & { - /** Wrap component class with `.` prefix */ - componentCls: string; - /** Origin prefix which do not have `.` prefix */ - prefixCls: string; - /** Wrap icon class with `.` prefix */ - iconCls: string; - /** Wrap ant prefixCls class with `.` prefix */ - antCls: string; -} & CSSUtil; - -export type FullToken = TokenWithCommonCls< - GlobalTokenWithComponent ->; - -export type GenStyleFn = ( - token: FullToken, - info: StyleInfo, -) => CSSInterpolation; - -export type GetDefaultToken = - | null - | OverrideTokenWithoutDerivative[C] - | (( - token: AliasToken & Partial, - ) => OverrideTokenWithoutDerivative[C]); - -const getDefaultComponentToken = ( - component: C, - token: GlobalToken, - getDefaultToken: GetDefaultToken, -) => { - if (typeof getDefaultToken === 'function') { - return getDefaultToken(mergeToken(token, token[component] ?? {})); - } - return getDefaultToken ?? {}; -}; - -const getComponentToken = ( - component: C, - token: GlobalToken, - defaultToken: OverrideTokenWithoutDerivative[C], - options?: { - deprecatedTokens?: [ComponentTokenKey, ComponentTokenKey][]; - }, -) => { - const customToken = { ...(token[component] as ComponentToken) }; - if (options?.deprecatedTokens) { - const { deprecatedTokens } = options; - deprecatedTokens.forEach(([oldTokenKey, newTokenKey]) => { - if (process.env.NODE_ENV !== 'production') { - warning( - !customToken?.[oldTokenKey], - `Component Token \`${String( - oldTokenKey, - )}\` of ${component} is deprecated. Please use \`${String(newTokenKey)}\` instead.`, - ); - } - - // Should wrap with `if` clause, or there will be `undefined` in object. - if (customToken?.[oldTokenKey] || customToken?.[newTokenKey]) { - customToken[newTokenKey] ??= customToken?.[oldTokenKey]; - } - }); - } - const mergedToken: any = { ...defaultToken, ...customToken }; - - // Remove same value as global token to minimize size - Object.keys(mergedToken).forEach((key) => { - if (mergedToken[key] === token[key as keyof GlobalToken]) { - delete mergedToken[key]; - } - }); - - return mergedToken; -}; - -const getCompVarPrefix = (component: string, prefix?: string) => - `${[ - prefix, - component.replace(/([A-Z]+)([A-Z][a-z]+)/g, '$1-$2').replace(/([a-z])([A-Z])/g, '$1-$2'), - ] - .filter(Boolean) - .join('-')}`; - -export default function genComponentStyleHook( - componentName: C | [C, string], - styleFn: GenStyleFn, - getDefaultToken?: GetDefaultToken, - options: { - resetStyle?: boolean; - resetFont?: boolean; - // Deprecated token key map [["oldTokenKey", "newTokenKey"], ["oldTokenKey", "newTokenKey"]] - deprecatedTokens?: [ComponentTokenKey, ComponentTokenKey][]; - /** - * Only use component style in client side. Ignore in SSR. - */ - clientOnly?: boolean; - /** - * Set order of component style. Default is -999. - */ - order?: number; - injectStyle?: boolean; - unitless?: { - [key in ComponentTokenKey]: boolean; - }; - } = {}, -) { - const cells = (Array.isArray(componentName) ? componentName : [componentName, componentName]) as [ - C, - string, - ]; - - const [component] = cells; - const concatComponent = cells.join('-'); - - // Return new style hook - return (prefixCls: string, rootCls: string = prefixCls): UseComponentStyleResult => { - const [theme, realToken, hashId, token, cssVar] = useToken(); - const { getPrefixCls, iconPrefixCls, csp } = useContext(ConfigContext); - const rootPrefixCls = getPrefixCls(); - - const type = cssVar ? 'css' : 'js'; - - // Use unique memo to share the result across all instances - const calc = useUniqueMemo(() => { - const unitlessCssVar = new Set(); - if (cssVar) { - Object.keys(options.unitless || {}).forEach((key) => { - // Some component proxy the AliasToken (e.g. Image) and some not (e.g. Modal) - // We should both pass in `unitlessCssVar` to make sure the CSSVar can be unitless. - unitlessCssVar.add(token2CSSVar(key, cssVar.prefix)); - unitlessCssVar.add(token2CSSVar(key, getCompVarPrefix(component, cssVar.prefix))); - }); - } - - return genCalc(type, unitlessCssVar); - }, [type, component, cssVar?.prefix]); - const { max, min } = genMaxMin(type); - - // Shared config - const sharedConfig: Omit[0], 'path'> = { - theme, - token, - hashId, - nonce: () => csp?.nonce!, - clientOnly: options.clientOnly, - layer: { - name: 'antd', - }, - - // antd is always at top of styles - order: options.order || -999, - }; - - // Generate style for all a tags in antd component. - useStyleRegister( - { ...sharedConfig, clientOnly: false, path: ['Shared', rootPrefixCls] }, - () => [ - { - // Link - '&': genLinkStyle(token), - }, - ], - ); - - // Generate style for icons - useResetIconStyle(iconPrefixCls, csp); - - const wrapSSR = useStyleRegister( - { ...sharedConfig, path: [concatComponent, prefixCls, iconPrefixCls] }, - () => { - if (options.injectStyle === false) { - return []; - } - - const { token: proxyToken, flush } = statisticToken(token); - - const defaultComponentToken = getDefaultComponentToken( - component, - realToken, - getDefaultToken, - ); - - const componentCls = `.${prefixCls}`; - const componentToken = getComponentToken(component, realToken, defaultComponentToken, { - deprecatedTokens: options.deprecatedTokens, - }); - - if (cssVar) { - Object.keys(defaultComponentToken).forEach((key) => { - defaultComponentToken[key] = `var(${token2CSSVar( - key, - getCompVarPrefix(component, cssVar.prefix), - )})`; - }); - } - const mergedToken = mergeToken< - TokenWithCommonCls> - >( - proxyToken, - { - componentCls, - prefixCls, - iconCls: `.${iconPrefixCls}`, - antCls: `.${rootPrefixCls}`, - calc, - // @ts-ignore - max, - // @ts-ignore - min, - }, - cssVar ? defaultComponentToken : componentToken, - ); - - const styleInterpolation = styleFn(mergedToken as unknown as FullToken, { - hashId, - prefixCls, - rootPrefixCls, - iconPrefixCls, - }); - flush(component, componentToken); - return [ - options.resetStyle === false - ? null - : genCommonStyle(mergedToken, prefixCls, rootCls, options.resetFont), - styleInterpolation, - ]; - }, - ); - - return [wrapSSR as any, hashId]; - }; -} - -export interface SubStyleComponentProps { - prefixCls: string; - rootCls?: string; -} - -// Get from second argument -type RestParameters = T extends [any, ...infer Rest] ? Rest : never; - -export const genSubStyleComponent: ( - componentName: [C, string], - ...args: RestParameters>> -) => ComponentType = (componentName, styleFn, getDefaultToken, options) => { - const useStyle = genComponentStyleHook(componentName, styleFn, getDefaultToken, { - resetStyle: false, - - // Sub Style should default after root one - order: -998, - ...options, - }); - - const StyledComponent: ComponentType = ({ - prefixCls, - rootCls = prefixCls, - }: SubStyleComponentProps) => { - useStyle(prefixCls, rootCls); - return null; - }; - - if (process.env.NODE_ENV !== 'production') { - StyledComponent.displayName = `SubStyle_${ - Array.isArray(componentName) ? componentName.join('.') : componentName - }`; - } - - return StyledComponent; -}; - -export type CSSVarRegisterProps = { - rootCls: string; - component: string; - cssVar: { - prefix?: string; - key?: string; - }; -}; - -const genCSSVarRegister = ( - component: C, - getDefaultToken: GetDefaultToken | undefined, - options: { - unitless?: { - [key in ComponentTokenKey]: boolean; - }; - deprecatedTokens?: [ComponentTokenKey, ComponentTokenKey][]; - injectStyle?: boolean; - prefixToken: (key: string) => string; - }, -) => { - const { unitless: compUnitless, injectStyle = true, prefixToken } = options; - - const CSSVarRegister: FC = ({ rootCls, cssVar }) => { - const [, realToken] = useToken(); - useCSSVarRegister( - { - path: [component], - prefix: cssVar.prefix, - key: cssVar?.key!, - unitless: compUnitless, - ignore, - token: realToken, - scope: rootCls, - }, - () => { - const defaultToken = getDefaultComponentToken(component, realToken, getDefaultToken); - const componentToken = getComponentToken(component, realToken, defaultToken, { - deprecatedTokens: options?.deprecatedTokens, - }); - Object.keys(defaultToken).forEach((key) => { - componentToken[prefixToken(key)] = componentToken[key]; - delete componentToken[key]; - }); - return componentToken; - }, - ); - return null; - }; - - const useCSSVar = (rootCls: string) => { - const [, , , , cssVar] = useToken(); - - return [ - (node: ReactElement): ReactElement => - injectStyle && cssVar ? ( - <> - - {node} - - ) : ( - node - ), - cssVar?.key, - ] as const; - }; - - return useCSSVar; -}; - -export const genStyleHooks = ( - component: C | [C, string], - styleFn: GenStyleFn, - getDefaultToken?: GetDefaultToken, - options?: { - resetStyle?: boolean; - resetFont?: boolean; - deprecatedTokens?: [ComponentTokenKey, ComponentTokenKey][]; - /** - * Component tokens that do not need unit. - */ - unitless?: { - [key in ComponentTokenKey]: boolean; - }; - /** - * Only use component style in client side. Ignore in SSR. - */ - clientOnly?: boolean; - /** - * Set order of component style. - * @default -999 - */ - order?: number; - /** - * Whether generate styles - * @default true - */ - injectStyle?: boolean; - }, -) => { - const componentName = Array.isArray(component) ? component[0] : component; - - function prefixToken(key: string) { - return `${componentName}${key.slice(0, 1).toUpperCase()}${key.slice(1)}`; - } - - // Fill unitless - const originUnitless = options?.unitless || {}; - const compUnitless: any = { - ...unitless, - [prefixToken('zIndexPopup')]: true, - }; - Object.keys(originUnitless).forEach((key) => { - compUnitless[prefixToken(key)] = originUnitless[key as keyof ComponentTokenKey]; - }); - - // Options - const mergedOptions = { - ...options, - unitless: compUnitless, - prefixToken, - }; - - // Hooks - const useStyle = genComponentStyleHook(component, styleFn, getDefaultToken, mergedOptions); - - const useCSSVar = genCSSVarRegister(componentName, getDefaultToken, mergedOptions); - - return (prefixCls: string, rootCls: string = prefixCls) => { - const [, hashId] = useStyle(prefixCls, rootCls); - const [wrapCSSVar, cssVarCls] = useCSSVar(rootCls); - - return [wrapCSSVar, hashId, cssVarCls] as const; - }; -}; diff --git a/components/theme/util/genPresetColor.ts b/components/theme/util/genPresetColor.ts index 11e8ab6769..ec9dbe4ee8 100644 --- a/components/theme/util/genPresetColor.ts +++ b/components/theme/util/genPresetColor.ts @@ -2,8 +2,7 @@ import type { CSSObject } from '@ant-design/cssinjs'; import { PresetColors } from '../interface'; -import type { AliasToken, PresetColorKey } from '../internal'; -import type { TokenWithCommonCls } from './genComponentStyleHook'; +import type { AliasToken, PresetColorKey, TokenWithCommonCls } from '../internal'; interface CalcColor { /** token[`${colorKey}-1`] */ diff --git a/components/theme/util/genStyleUtils.ts b/components/theme/util/genStyleUtils.ts new file mode 100644 index 0000000000..0df9d45b2c --- /dev/null +++ b/components/theme/util/genStyleUtils.ts @@ -0,0 +1,63 @@ +import { useContext } from 'react'; +import { genStyleUtils } from '@ant-design/cssinjs-utils'; + +import { ConfigContext } from '../../config-provider/context'; +import { genCommonStyle, genLinkStyle } from '../../style'; +import type { + AliasToken, + ComponentTokenMap, + SeedToken, +} from '../interface'; + +import localUseToken, { unitless } from '../useToken'; +import useResetIconStyle from './useResetIconStyle'; + +export const { + genStyleHooks, + genComponentStyleHook, + genSubStyleComponent, +} = genStyleUtils< + ComponentTokenMap, + AliasToken, + SeedToken +>({ + usePrefix: () => { + const { getPrefixCls, iconPrefixCls } = useContext(ConfigContext); + + const rootPrefixCls = getPrefixCls(); + + return { + rootPrefixCls, + iconPrefixCls, + } + }, + useToken: () => { + const [theme, realToken, hashId, token, cssVar] = localUseToken(); + + return { + theme, + realToken, + hashId, + token, + cssVar, + }; + }, + useCSP: () => { + const { csp, iconPrefixCls } = useContext(ConfigContext); + + // Generate style for icons + useResetIconStyle(iconPrefixCls, csp); + + return csp ?? {}; + }, + getResetStyles: (token) => + [ + { + // Link + '&': genLinkStyle(token), + }, + ] + , + getCommonStyle: genCommonStyle, + getCompUnitless: () => unitless as any, +}) diff --git a/components/theme/util/maxmin.ts b/components/theme/util/maxmin.ts deleted file mode 100644 index 44769b4e56..0000000000 --- a/components/theme/util/maxmin.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { unit } from '@ant-design/cssinjs'; - -export default function genMaxMin(type: 'css' | 'js') { - if (type === 'js') { - return { - max: Math.max, - min: Math.min, - }; - } - return { - max: (...args: (string | number)[]) => `max(${args.map((value) => unit(value)).join(',')})`, - min: (...args: (string | number)[]) => `min(${args.map((value) => unit(value)).join(',')})`, - }; -} diff --git a/components/theme/util/statistic.ts b/components/theme/util/statistic.ts deleted file mode 100644 index b76bc0e01b..0000000000 --- a/components/theme/util/statistic.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { AnyObject } from '../../_util/type'; - -declare const CSSINJS_STATISTIC: any; - -const enableStatistic = - process.env.NODE_ENV !== 'production' || typeof CSSINJS_STATISTIC !== 'undefined'; -let recording = true; - -/** - * This function will do as `Object.assign` in production. But will use Object.defineProperty:get to - * pass all value access in development. To support statistic field usage with alias token. - */ -export function merge(...objs: Partial[]): T { - /* istanbul ignore next */ - if (!enableStatistic) { - return Object.assign({}, ...objs); - } - - recording = false; - - const ret = {} as T; - - objs.forEach((obj) => { - const keys = Object.keys(obj); - - keys.forEach((key) => { - Object.defineProperty(ret, key, { - configurable: true, - enumerable: true, - get: () => (obj as any)[key], - }); - }); - }); - - recording = true; - return ret; -} - -/** @internal Internal Usage. Not use in your production. */ -export const statistic: Record< - string, - { global: string[]; component: Record } -> = {}; - -/** @internal Internal Usage. Not use in your production. */ -// eslint-disable-next-line camelcase -export const _statistic_build_: typeof statistic = {}; - -/* istanbul ignore next */ -function noop() {} - -/** Statistic token usage case. Should use `merge` function if you do not want spread record. */ -const statisticToken = (token: T) => { - let tokenKeys: Set | undefined; - let proxy = token; - let flush: (componentName: string, componentToken: Record) => void = - noop; - - if (enableStatistic && typeof Proxy !== 'undefined') { - tokenKeys = new Set(); - - proxy = new Proxy(token, { - get(obj: any, prop: any) { - if (recording) { - tokenKeys!.add(prop); - } - return obj[prop]; - }, - }); - - flush = (componentName, componentToken) => { - statistic[componentName] = { - global: Array.from(tokenKeys!), - component: { - ...statistic[componentName]?.component, - ...componentToken, - }, - }; - }; - } - - return { token: proxy, keys: tokenKeys, flush }; -}; - -export default statisticToken; diff --git a/components/tree-select/style/index.ts b/components/tree-select/style/index.ts index c4a7bfa024..626b1b2d47 100644 --- a/components/tree-select/style/index.ts +++ b/components/tree-select/style/index.ts @@ -1,9 +1,14 @@ import { unit } from '@ant-design/cssinjs'; import { getStyle as getCheckboxStyle } from '../../checkbox/style'; -import type { AliasToken, FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal'; +import type { + AliasToken, + FullToken, + GenerateStyle, + GetDefaultToken, + CSSUtil, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { CSSUtil } from '../../theme/util/genComponentStyleHook'; import type { TreeSharedToken } from '../../tree/style'; import { genTreeStyle, initComponentToken } from '../../tree/style'; diff --git a/components/tree/style/index.ts b/components/tree/style/index.ts index edf399bb47..5602394b92 100644 --- a/components/tree/style/index.ts +++ b/components/tree/style/index.ts @@ -4,9 +4,13 @@ import { Keyframes, unit } from '@ant-design/cssinjs'; import { getStyle as getCheckboxStyle } from '../../checkbox/style'; import { genFocusOutline, resetComponent } from '../../style'; import { genCollapseMotion } from '../../style/motion'; -import type { AliasToken, DerivativeToken, FullToken, GetDefaultToken } from '../../theme/internal'; +import type { + AliasToken, + FullToken, + GetDefaultToken, + CSSUtil, +} from '../../theme/internal'; import { genStyleHooks, mergeToken } from '../../theme/internal'; -import type { CSSUtil } from '../../theme/util/genComponentStyleHook'; export interface TreeSharedToken { /** @@ -50,7 +54,7 @@ const treeNodeFX = new Keyframes('ant-tree-node-fx-do-not-use', { }); // ============================== Switch ============================== -const getSwitchStyle = (prefixCls: string, token: DerivativeToken): CSSObject => ({ +const getSwitchStyle = (prefixCls: string, token: AliasToken): CSSObject => ({ [`.${prefixCls}-switcher-icon`]: { display: 'inline-block', fontSize: 10, @@ -63,7 +67,7 @@ const getSwitchStyle = (prefixCls: string, token: DerivativeToken): CSSObject => }); // =============================== Drop =============================== -const getDropIndicatorStyle = (prefixCls: string, token: DerivativeToken) => ({ +const getDropIndicatorStyle = (prefixCls: string, token: AliasToken) => ({ [`.${prefixCls}-drop-indicator`]: { position: 'absolute', // it should displayed over the following node diff --git a/package.json b/package.json index dc6b10b1d2..fae70a93ff 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "dependencies": { "@ant-design/colors": "^7.1.0", "@ant-design/cssinjs": "^1.21.0", + "@ant-design/cssinjs-utils": "^1.0.3", "@ant-design/icons": "^5.4.0", "@ant-design/react-slick": "~1.1.2", "@babel/runtime": "^7.24.8", diff --git a/scripts/collect-token-statistic.ts b/scripts/collect-token-statistic.ts index 8271758d57..da4df06cd6 100644 --- a/scripts/collect-token-statistic.ts +++ b/scripts/collect-token-statistic.ts @@ -5,9 +5,8 @@ import cliProgress from 'cli-progress'; import fs from 'fs-extra'; import ReactDOMServer from 'react-dom/server'; -import { DesignTokenContext } from '../components/theme/internal'; +import { DesignTokenContext, statistic } from '../components/theme/internal'; import seedToken from '../components/theme/themes/seed'; -import { statistic } from '../components/theme/util/statistic'; import { generateCssinjs, styleFiles } from './generate-cssinjs'; console.log(`🪄 Collecting token statistics...`);