Skip to content

Commit

Permalink
♻️ fix: 重构类型定义,使用入参更加准确
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Jan 25, 2023
1 parent 7658d7c commit 6c94ae6
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 25 deletions.
4 changes: 2 additions & 2 deletions src/functions/createStyish.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ReturnStyleToUse, StyleInputType } from '@/types';
import { BaseReturnType, ReturnStyleToUse } from '@/types';
import { createStyles, StyleOrGetStyleFn } from './createStyles';

// FIXME: 需要考虑如何将 createStylish 和 ThemeProvider 中的 customStylish 方法整合在一起,现在是割裂的两个方法

/**
* 业务应用中创建复合通用样式的进阶
*/
export const createStylish = <Props, Styles extends StyleInputType>(
export const createStylish = <Props, Styles extends BaseReturnType>(
cssStyleOrGetCssStyleFn: StyleOrGetStyleFn<Styles, Props>,
): ((props?: Props) => ReturnStyleToUse<Styles>) => {
const useStyles = createStyles(cssStyleOrGetCssStyleFn);
Expand Down
25 changes: 17 additions & 8 deletions src/functions/createStyles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,63 @@ import { useMemo } from 'react';

import { useEmotion, useTheme } from '@/hooks';
import type {
BaseReturnType,
CommonStyleUtils,
CSSObject,
EmotionCX,
FullStylish,
FullToken,
ResponsiveStyleUtil,
ReturnStyleToUse,
StyleInputType,
Theme,
ThemeAppearance,
UtilReactCss,
} from '@/types';
import { isReactCssResult } from '@/utils';

import { convertResponsiveStyleToString, useResponsiveMap } from './response';

import { type CSSObject } from '../css';
import { reactCss } from '../react';

export interface CreateStylesTheme extends CommonStyleUtils {
/**
* 用户书写样式时使用的第一个参数
*/
export interface CreateStylesTheme extends Omit<CommonStyleUtils, 'css'> {
token: FullToken;
stylish: FullStylish;
appearance: ThemeAppearance;
isDarkMode: boolean;
prefixCls: string;
css: UtilReactCss;
}

/**
* 最终返回 styles 对象的类型定义
*/
export interface ReturnStyles<T extends StyleInputType> extends Pick<CommonStyleUtils, 'cx'> {
export interface ReturnStyles<T extends BaseReturnType> extends Pick<CommonStyleUtils, 'cx'> {
styles: ReturnStyleToUse<T>;
theme: Omit<Theme, 'prefixCls'>;
prefixCls: string;
}

// 获取样式
export type GetStyleFn<Input extends StyleInputType, Props> = (
export type GetStyleFn<Input extends BaseReturnType, Props> = (
theme: CreateStylesTheme,
props: Props,
) => Input;

/**
* 创建样式的函数或者对象
*/
export type StyleOrGetStyleFn<Input extends StyleInputType, Props> =
export type StyleOrGetStyleFn<Input extends BaseReturnType, Props> =
| Input
| GetStyleFn<Input, Props>;

/**
* 业务应用中创建样式基础写法
* 创建样式基础写法
*/
export const createStyles =
<Props, Input extends StyleInputType = StyleInputType>(
<Props, Input extends BaseReturnType = BaseReturnType>(
styleOrGetStyle: StyleOrGetStyleFn<Input, Props>,
) =>
(props?: Props): ReturnStyles<Input> => {
Expand All @@ -73,8 +78,11 @@ export const createStyles =
cx(...classNames.map((c) => (isReactCssResult(c) ? css(c) : c)));

// 创建响应式断点选择器的工具函数
// @ts-ignore
const responsive: ResponsiveStyleUtil = (styles) =>
convertResponsiveStyleToString(styles, responsiveMap);
// 并赋予其相应的断点工具
Object.assign(responsive, responsiveMap);

tempStyles = styleOrGetStyle(
{
Expand All @@ -85,6 +93,7 @@ export const createStyles =
prefixCls,
// 工具函数们
cx: reactCx,
// @ts-ignore
css: reactCss,
r: responsive,
},
Expand Down
7 changes: 3 additions & 4 deletions src/functions/createStyles/response.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { reactCss } from '@/functions/react';
import { useAntdToken } from '@/hooks';
import type { Breakpoint, ResponsiveKey, ResponsiveMap } from '@/types';
import type { Breakpoint, BreakpointMapParams, CSSObject, ResponsiveMap } from '@/types';
import { isReactCssResult } from '@/utils';
import type { SerializedStyles } from '@emotion/react';
import type { CSSObject } from '@emotion/serialize';
import { useMemo } from 'react';

export const useResponsiveMap = (): ResponsiveMap => {
Expand Down Expand Up @@ -37,12 +36,12 @@ export const useResponsiveMap = (): ResponsiveMap => {
* @param map
*/
export const convertResponsiveStyleToString = (
obj: Partial<Record<ResponsiveKey, SerializedStyles | CSSObject>>,
obj: BreakpointMapParams,
map: ResponsiveMap,
): any => {
return Object.entries(obj)
.map(([key, value]) => {
let str: SerializedStyles | CSSObject = value;
let str = value as SerializedStyles | CSSObject;

if (!isReactCssResult(value)) {
str = reactCss(value);
Expand Down
2 changes: 1 addition & 1 deletion src/functions/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ export const {
getRegisteredStyles,
cache,
} = emotion;
export { type CSSObject } from '@emotion/css';

export type { Emotion } from '@emotion/css/create-instance';
export { createEmotion };
2 changes: 2 additions & 0 deletions src/types/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ import { Theme } from '@/types/theme';
import { Interpolation } from '@emotion/styled';

export type CSSStyle<T = Theme> = Array<TemplateStringsArray | Interpolation<T>>;

export { type CSSObject } from '@emotion/css';
17 changes: 13 additions & 4 deletions src/types/function.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ClassNamesArg } from '@emotion/css/create-instance';
import { CSSInterpolation, CSSObject, SerializedStyles } from '@emotion/serialize';
import { CSSInterpolation, SerializedStyles } from '@emotion/serialize';
import { ThemeConfig } from 'antd/es/config-provider/context';

import { AtomInputType } from 'antd-style/src';
import { ThemeAppearance } from './appearance';
import { ResponsiveKey } from './response';
import type { AntdStylish, AntdToken, AppearanceState, FullToken } from './theme';
Expand All @@ -10,11 +11,19 @@ export interface EmotionReactCss {
(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): SerializedStyles;
(...args: Array<CSSInterpolation>): SerializedStyles;
}

export interface UtilReactCss {
(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): string;
(...args: Array<CSSInterpolation>): string;
}

export type EmotionCX = (...classNames: ClassNamesArg[]) => string;

export type ResponsiveStyleUtil = (
breakpoints: Partial<Record<ResponsiveKey, CSSObject | SerializedStyles>>,
) => any;
export type BreakpointMapParams = Partial<Record<ResponsiveKey, AtomInputType>>;

export interface ResponsiveStyleUtil extends Record<ResponsiveKey, string> {
(breakpoints: BreakpointMapParams): any;
}

export interface CommonStyleUtils {
cx: EmotionCX;
Expand Down
22 changes: 16 additions & 6 deletions src/types/genericUtils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { CSSObject } from '@emotion/css';
import { CSSObject } from './css';

type StyleObject = Record<string, CSSObject | string>;
/**
* 任何一组样式,最基础的入参就只有 string
*/

export type AtomInputType = string | CSSObject;

/**
* 所有用户的可能的入参类型
* getStyle 函数的的基础出参类型,我们需要将为这个类型提供准确定义,进而为开发者用户提供精准的类型提示
*
* 其中用户输入的原子级样式类型有
* CSSObject : { color: "red" }
* string : css` color: red; `
*/
export type StyleInputType = string | CSSObject | StyleObject;
export type BaseReturnType = KVObject | AtomInputType;

type KVObject = Record<string, CSSObject | string>;

type StyleObjectOnly<T extends StyleInputType> = T extends string ? never : T;
type StyleObjectOnly<T extends BaseReturnType> = T extends string ? never : T;

/**
* 根据用户输入的样式对象,导出可以给用户使用消费的类型泛型
Expand All @@ -23,6 +33,6 @@ type DefinitionToResult<T, K extends keyof T = keyof T> = {
* 譬如用户输入为 { a: css`color: red;`, b: { color: 'red' }
* 输出的类型泛型为 { a:string; b:string }
*/
export type ReturnStyleToUse<T extends StyleInputType> = T extends string
export type ReturnStyleToUse<T extends BaseReturnType> = T extends string
? T
: DefinitionToResult<StyleObjectOnly<T>>;

0 comments on commit 6c94ae6

Please sign in to comment.