/* eslint-disable no-redeclare */ import type { CSSInterpolation } from '@ant-design/cssinjs'; import { useStyleRegister } from '@ant-design/cssinjs'; import { warning } from 'rc-util'; import { useContext } from 'react'; import { ConfigContext } from '../../config-provider/context'; import { genCommonStyle, genLinkStyle } from '../../style'; import type { ComponentTokenMap, GlobalToken, OverrideToken, UseComponentStyleResult, } from '../interface'; import useToken from '../useToken'; import statisticToken, { merge as mergeToken } from './statistic'; export type OverrideTokenWithoutDerivative = ComponentTokenMap; export type OverrideComponent = keyof OverrideTokenWithoutDerivative; export type GlobalTokenWithComponent = GlobalToken & ComponentTokenMap[ComponentName]; type ComponentToken = Exclude< OverrideToken[ComponentName], undefined >; type ComponentTokenKey = keyof ComponentToken; export interface StyleInfo { hashId: string; prefixCls: string; rootPrefixCls: string; iconPrefixCls: string; overrideComponentToken: ComponentTokenMap[ComponentName]; } 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; }; export type FullToken = TokenWithCommonCls< GlobalTokenWithComponent >; export default function genComponentStyleHook( component: ComponentName, styleFn: (token: FullToken, info: StyleInfo) => CSSInterpolation, getDefaultToken?: | OverrideTokenWithoutDerivative[ComponentName] | ((token: GlobalToken) => OverrideTokenWithoutDerivative[ComponentName]), options?: { resetStyle?: boolean; // Deprecated token key map [["oldTokenKey", "newTokenKey"], ["oldTokenKey", "newTokenKey"]] deprecatedTokens?: [ComponentTokenKey, ComponentTokenKey][]; /** * Only use component style in client side. Ignore in SSR. */ clientOnly?: boolean; }, ) { return (prefixCls: string): UseComponentStyleResult => { const [theme, token, hashId] = useToken(); const { getPrefixCls, iconPrefixCls, csp } = useContext(ConfigContext); const rootPrefixCls = getPrefixCls(); // Shared config const sharedConfig: Omit[0], 'path'> = { theme, token, hashId, nonce: () => csp?.nonce!, clientOnly: options?.clientOnly, // antd is always at top of styles order: -999, }; // Generate style for all a tags in antd component. useStyleRegister( { ...sharedConfig, clientOnly: false, path: ['Shared', rootPrefixCls] }, () => [ { // Link '&': genLinkStyle(token), }, ], ); return [ useStyleRegister({ ...sharedConfig, path: [component, prefixCls, iconPrefixCls] }, () => { const { token: proxyToken, flush } = statisticToken(token); const customComponentToken = { ...(token[component] as ComponentToken) }; if (options?.deprecatedTokens) { const { deprecatedTokens } = options; deprecatedTokens.forEach(([oldTokenKey, newTokenKey]) => { if (process.env.NODE_ENV !== 'production') { warning( !customComponentToken?.[oldTokenKey], `The token '${String(oldTokenKey)}' of ${component} had deprecated, use '${String( newTokenKey, )}' instead.`, ); } // Should wrap with `if` clause, or there will be `undefined` in object. if (customComponentToken?.[oldTokenKey] || customComponentToken?.[newTokenKey]) { customComponentToken[newTokenKey] ??= customComponentToken?.[oldTokenKey]; } }); } const defaultComponentToken = typeof getDefaultToken === 'function' ? getDefaultToken(mergeToken(proxyToken, customComponentToken ?? {})) : getDefaultToken; const mergedComponentToken = { ...defaultComponentToken, ...customComponentToken }; const componentCls = `.${prefixCls}`; const mergedToken = mergeToken< TokenWithCommonCls> >( proxyToken, { componentCls, prefixCls, iconCls: `.${iconPrefixCls}`, antCls: `.${rootPrefixCls}`, }, mergedComponentToken, ); const styleInterpolation = styleFn(mergedToken as unknown as FullToken, { hashId, prefixCls, rootPrefixCls, iconPrefixCls, overrideComponentToken: customComponentToken as any, }); flush(component, mergedComponentToken); return [ options?.resetStyle === false ? null : genCommonStyle(token, prefixCls), styleInterpolation, ]; }), hashId, ]; }; }