diff --git a/src/functions/createStyish.ts b/src/functions/createStyish.ts index 8bf4fdec..24cb6f9d 100644 --- a/src/functions/createStyish.ts +++ b/src/functions/createStyish.ts @@ -6,9 +6,9 @@ import { createStyles, StyleOrGetStyleFn } from './createStyles'; /** * 业务应用中创建复合通用样式的进阶 */ -export function createStylish( +export const createStylish = ( cssStyleOrGetCssStyleFn: StyleOrGetStyleFn, -) { +): ((props?: Props) => ReturnStyleToUse) => { const useStyles = createStyles(cssStyleOrGetCssStyleFn); return (props?: Props): ReturnStyleToUse => { @@ -16,4 +16,4 @@ export function createStylish( return styles; }; -} +}; diff --git a/src/functions/createStyles.ts b/src/functions/createStyles.ts index c63895b1..08d95248 100644 --- a/src/functions/createStyles.ts +++ b/src/functions/createStyles.ts @@ -3,6 +3,7 @@ import { useMemo } from 'react'; import { useEmotion, useTheme } from '@/hooks'; import type { CommonStyleUtils, + EmotionCX, FullStylish, FullToken, ReturnStyleToUse, @@ -10,8 +11,10 @@ import type { Theme, ThemeAppearance, } from '@/types'; +import { isReactCssResult } from '@/utils'; import { type CSSObject } from './css'; +import { reactCss } from './react'; export interface CreateStylesTheme extends CommonStyleUtils { token: FullToken; @@ -61,8 +64,12 @@ export const createStyles = if (styleOrGetStyleFn instanceof Function) { const { stylish, appearance, isDarkMode, prefixCls, ...token } = theme; + // 由于使用了 reactCss 作为基础样式工具,因此在使用 cx 级联 className 时需要使用特殊处理的 cx,要将 reactCss 的产出转为 css 产物 + const reactCx: EmotionCX = (...classNames) => + cx(...classNames.map((c) => (isReactCssResult(c) ? css(c) : c))); + tempStyles = styleOrGetStyleFn( - { token, stylish, appearance, cx, css, isDarkMode, prefixCls }, + { token, stylish, appearance, cx: reactCx, css: reactCss, isDarkMode, prefixCls }, props!, ) as any; } @@ -72,15 +79,24 @@ export const createStyles = } if (typeof tempStyles === 'object') { - tempStyles = Object.fromEntries( - Object.entries(tempStyles).map(([key, value]) => { - if (typeof value === 'object') { - return [key, css(value as CSSObject)]; - } + // 判断是否是直接用 reactCSS 生成的 + if (isReactCssResult(tempStyles)) { + tempStyles = css(tempStyles) as any; + } else { + // 不是的话就是直接是 css object,需要转换了 + tempStyles = Object.fromEntries( + Object.entries(tempStyles).map(([key, value]) => { + // 这里有可能是 x:{ color:red } 也可能是 c:reactCss`color:red`; + // 但无论哪种,都可以直接用 css 包一下转换掉 + if (typeof value === 'object') { + return [key, css(value as CSSObject)]; + } - return [key, value]; - }), - ) as any; + // 这里只可能是 c: css`color:red`; css 直接来自 antd-style + return [key, value]; + }), + ) as any; + } } return tempStyles; diff --git a/src/types/function.ts b/src/types/function.ts new file mode 100644 index 00000000..61b61135 --- /dev/null +++ b/src/types/function.ts @@ -0,0 +1,56 @@ +import { ClassNamesArg } from '@emotion/css/create-instance'; +import { CSSInterpolation, SerializedStyles } from '@emotion/serialize'; +import { ThemeConfig } from 'antd/es/config-provider/context'; + +import { ThemeAppearance } from './appearance'; +import type { AntdStylish, AntdToken, AppearanceState, FullToken } from './theme'; + +export interface EmotionReactCss { + (template: TemplateStringsArray, ...args: Array): SerializedStyles; + (...args: Array): SerializedStyles; +} +export type EmotionCX = (...classNames: ClassNamesArg[]) => string; + +export interface CommonStyleUtils { + cx: EmotionCX; + css: EmotionReactCss; +} + +/** + * 获取 antd theme 配置 + */ +export type GetAntdThemeConfig = (appearance: ThemeAppearance) => ThemeConfig | undefined; + +export interface AntdStylishParams extends AppearanceState { + token: AntdToken; + css: EmotionReactCss; +} + +/** + * 创建 antd stylish 配置 + */ +export type GetAntdStylish = (theme: AntdStylishParams) => { + [T in keyof AntdStylish]: SerializedStyles; +}; + +export interface CustomTokenParams extends AppearanceState { + token: AntdToken; +} + +/** + * 创建 自定义 token + */ +export type GetCustomToken = (theme: CustomTokenParams) => T; + +export interface CustomStylishParams extends AppearanceState { + token: FullToken; + stylish: AntdStylish; + css: EmotionReactCss; +} + +/** + * 创建 自定义 stylish + */ +export type GetCustomStylish = (theme: CustomStylishParams) => { + [T in keyof S]: SerializedStyles; +}; diff --git a/src/types/index.ts b/src/types/index.ts index 381c1b08..bdccd488 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,5 +1,6 @@ export * from './appearance'; export * from './css'; +export * from './function'; export * from './genericUtils'; export * from './styled'; export * from './theme'; diff --git a/src/types/theme.ts b/src/types/theme.ts index c2d98d7e..7ebc3e97 100644 --- a/src/types/theme.ts +++ b/src/types/theme.ts @@ -1,20 +1,7 @@ -import { ThemeConfig } from 'antd/es/config-provider/context'; import { AliasToken } from 'antd/es/theme/interface'; -import { Emotion } from '@/functions'; -import { CSSInterpolation, SerializedStyles } from '@emotion/serialize'; import { ThemeAppearance, ThemeMode } from './appearance'; -export interface EmotionReactCss { - (template: TemplateStringsArray, ...args: Array): SerializedStyles; - (...args: Array): SerializedStyles; -} - -export interface CommonStyleUtils { - cx: Emotion['cx']; - css: Emotion['css']; -} - export interface ThemeContextState { appearance: ThemeAppearance; themeMode: ThemeMode; @@ -22,16 +9,8 @@ export interface ThemeContextState { } export type AppearanceState = Omit; -export type AntdToken = AliasToken; -export interface AntdStylishParams extends AppearanceState { - token: AntdToken; - css: EmotionReactCss; -} - -export type GetAntdStylish = (theme: AntdStylishParams) => { - [T in keyof AntdStylish]: SerializedStyles; -}; +export type AntdToken = AliasToken; /** * 一组统一封装好的 antd 标准样式 @@ -43,24 +22,6 @@ export interface AntdStylish { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CustomToken {} -export interface CustomTokenParams extends AppearanceState { - token: AntdToken; -} - -export type GetCustomToken = (theme: CustomTokenParams) => T; - -export interface CustomStylishParams extends AppearanceState { - token: FullToken; - stylish: AntdStylish; - css: EmotionReactCss; -} - -export type GetCustomStylish = (theme: CustomStylishParams) => { - [T in keyof S]: SerializedStyles; -}; - -export type GetAntdThemeConfig = (appearance: ThemeAppearance) => ThemeConfig | undefined; - // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CustomStylish {} @@ -78,6 +39,8 @@ export interface FullToken extends AntdToken, CustomToken {} export interface Theme extends FullToken, ThemeContextState { stylish: FullStylish; - + /** + * antd 组件的 prefixCls + */ prefixCls: string; } diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 00000000..c303f48f --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,14 @@ +/** + * 判断是否是 ReactCss 的编译产物 + * @param params + */ +export const isReactCssResult = (params: any) => { + return ( + typeof params === 'object' && + 'styles' in params && + 'name' in params && + 'map' in params && + 'next' in params && + 'toString' in params + ); +};