Skip to content

Commit

Permalink
✨ feat: createInstance 方法支持声明自定义 token 默认值
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Feb 19, 2023
1 parent 06af341 commit 4122038
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/core/createCSS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { EmotionCache } from '@emotion/css/create-instance';
import { serializeStyles } from '@emotion/serialize';

const createClassNameGenerator =
(cache: EmotionCache, hashPriority: HashPriority = 'high'): ClassNameGenerator =>
(cache: EmotionCache, hashPriority: HashPriority): ClassNameGenerator =>
(...args) => {
const serialized = serializeStyles(args, cache.registered, undefined);
insertStyles(cache, serialized, false, hashPriority);
Expand Down
1 change: 1 addition & 0 deletions src/core/insertStyles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* istanbul ignore file */

// copied from https://github.com/emotion-js/emotion/blob/main/packages/utils/src/index.js
import type { HashPriority } from '@/types';
import type { EmotionCache } from '@emotion/css/create-instance';
Expand Down
8 changes: 2 additions & 6 deletions src/factories/createStyles/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { useMemo } from 'react';

import { createCSS, serializeCSS } from '@/core';
import { createUseTheme } from '@/factories/createUseTheme';
import type {
BaseReturnType,
CSSObject,
HashPriority,
ResponsiveUtil,
ReturnStyleToUse,
UseTheme,
} from '@/types';
import { isReactCssResult } from '@/utils';
import { EmotionCache } from '@emotion/css/create-instance';
Expand All @@ -18,8 +16,8 @@ import { ReturnStyles, StyleOrGetStyleFn } from './types';

interface CreateStylesFactory {
cache: EmotionCache;
styledUseTheme?: UseTheme;
hashPriority?: HashPriority;
useTheme: () => any;
}

export interface CreateStyleOptions {
Expand All @@ -30,16 +28,14 @@ export interface CreateStyleOptions {
* 创建样式基础写法
*/
export const createStylesFactory =
({ styledUseTheme, hashPriority, cache }: CreateStylesFactory) =>
({ hashPriority, cache, useTheme }: CreateStylesFactory) =>
<Props, Input extends BaseReturnType = BaseReturnType>(
styleOrGetStyle: StyleOrGetStyleFn<Input, Props>,
options?: CreateStyleOptions,
) => {
// 由于 toClassName 方法依赖了用户给 createStyle 传递的 hashPriority,所以需要在这里重新生成 cx 和 toClassName 方法
const { cx, css: toClassName } = createCSS(cache, options?.hashPriority || hashPriority);

const useTheme = createUseTheme(styledUseTheme);

// 返回 useStyles 方法,作为 hooks 使用
return (props?: Props): ReturnStyles<Input> => {
const theme = useTheme();
Expand Down
18 changes: 14 additions & 4 deletions src/factories/createThemeProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo, ReactElement } from 'react';
import { Context, memo, ReactElement } from 'react';

import { createUseTheme } from '@/factories/createUseTheme';
import { DEFAULT_THEME_PROVIDER, DEFAULT_USE_THEME } from '@/functions/setupStyled';
Expand All @@ -11,8 +11,14 @@ import { ThemeProviderProps } from './type';

export * from './type';

interface CreateThemeProviderOptions {
styledConfig?: StyledConfig;
CustomThemeContext: Context<any>;
prefixCls?: string;
}

export const createThemeProvider = (
styledConfig?: StyledConfig,
option: CreateThemeProviderOptions,
): (<T = any, S = any>(props: ThemeProviderProps<T, S>) => ReactElement | null) =>
memo(
({
Expand All @@ -37,7 +43,11 @@ export const createThemeProvider = (
defaultAppearance={defaultAppearance}
appearance={appearance}
onAppearanceChange={onAppearanceChange}
useTheme={createUseTheme(styled?.useTheme || styledConfig?.useTheme || DEFAULT_USE_THEME)}
useTheme={createUseTheme({
prefixCls: prefixCls || option.prefixCls,
styledUseTheme: styled?.useTheme || option.styledConfig?.useTheme || DEFAULT_USE_THEME,
CustomThemeContext: option.CustomThemeContext,
})}
>
<AntdProvider
prefixCls={prefixCls}
Expand All @@ -50,7 +60,7 @@ export const createThemeProvider = (
customToken={customToken}
customStylish={customStylish}
StyledThemeProvider={
styled?.ThemeProvider || styledConfig?.ThemeProvider || DEFAULT_THEME_PROVIDER
styled?.ThemeProvider || option.styledConfig?.ThemeProvider || DEFAULT_THEME_PROVIDER
}
>
{children}
Expand Down
29 changes: 22 additions & 7 deletions src/factories/createUseTheme.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
import { Theme, UseTheme } from '@/types';
import { useMemo } from 'react';
import { Context, useContext, useMemo } from 'react';

import { DEFAULT_USE_THEME } from '@/functions/setupStyled';
import { useAntdTheme } from '@/hooks/useAntdTheme';
import { useThemeMode } from '@/hooks/useThemeMode';

export const createUseTheme = (useDefaultTheme?: UseTheme) => (): Theme => {
interface CreateUseThemeOptions {
prefixCls?: string;
CustomThemeContext: Context<any>;
styledUseTheme?: UseTheme;
}

export const createUseTheme = (options: CreateUseThemeOptions) => (): Theme => {
const { prefixCls, styledUseTheme, CustomThemeContext } = options;
const antdTheme = useAntdTheme();
const themeState = useThemeMode();
const defaultTheme = useDefaultTheme ? useDefaultTheme() : DEFAULT_USE_THEME() || {};

const defaultCustomTheme = useContext(CustomThemeContext);

const styledTheme = styledUseTheme ? styledUseTheme() : DEFAULT_USE_THEME() || {};

const initTheme = useMemo<Theme>(
() => ({ ...antdTheme, ...themeState, prefixCls: 'ant' }),
[antdTheme, themeState],
() => ({
...antdTheme,
...themeState,
...defaultCustomTheme,
prefixCls: prefixCls || 'ant',
}),
[antdTheme, themeState, prefixCls, defaultCustomTheme],
);

// 如果是个空值,说明没有套 Provider,返回 antdTheme 的默认值
if (!defaultTheme || Object.keys(defaultTheme).length === 0) {
if (!styledTheme || Object.keys(styledTheme).length === 0) {
return initTheme;
}

return defaultTheme as Theme;
return styledTheme as Theme;
};
41 changes: 33 additions & 8 deletions src/functions/createInstance.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContext } from 'react';
import { createContext, useContext } from 'react';

import { createCSS, createEmotion, serializeCSS } from '@/core';

Expand All @@ -18,12 +18,21 @@ export interface CreateOptions<T> {
* @default ant-css
*/
key?: string;

/**
* 默认的组件 prefixCls
*/
prefixCls?: string;
/**
* 是否开启急速模式
*
* @default false
*/
speedy?: boolean;
/**
* 默认的自定义 Token
*/
defaultCustomToken?: T;
hashPriority?: HashPriority;

ThemeProvider?: Omit<ThemeProviderProps<T>, 'children'>;
Expand All @@ -37,36 +46,52 @@ export interface CreateOptions<T> {
export const createInstance = <T = any>(options: CreateOptions<T>) => {
const defaultKey = options.key || 'ant-css';

const styledUseTheme = options.styled?.useTheme as () => Theme;

const emotion = createEmotion({ key: defaultKey, speedy: options.speedy });

const { cache, injectGlobal, keyframes } = emotion;

const { cx } = createCSS(cache, options.hashPriority);

const useTheme = createUseTheme(styledUseTheme);
// ******* 下面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************* //

const CustomThemeContext = createContext<T>(
(options.defaultCustomToken ? options.defaultCustomToken : {}) as T,
);

const styledUseTheme = options.styled?.useTheme as () => Theme;

const useTheme = createUseTheme({
prefixCls: options?.prefixCls,
CustomThemeContext,
styledUseTheme,
});

const createStyles = createStylesFactory({
cache,
styledUseTheme,
hashPriority: options.hashPriority,
useTheme,
});

const createGlobalStyle = createGlobalStyleFactory(useTheme);

const createStylish = createStylishFactory(createStyles);

const ThemeProvider = createThemeProvider({
styledConfig: options.styled,
CustomThemeContext,
prefixCls: options.prefixCls,
});

// ******** 上面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************ //

const EmotionContext = createEmotionContext(emotion);

const StyleProvider = createStyleProvider(EmotionContext, {
speedy: options.speedy,
prefix: defaultKey,
});

const ThemeProvider = createThemeProvider(options.styled);

const useEmotion = () => useContext(EmotionContext);

return {
// ******************** //
// **** 样式生成相关 **** //
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// 等应用层完成迁移后,移除该导出
export { default as styled } from '@emotion/styled';
export * from './factories/createStyles/types';
export * from './factories/createThemeProvider/type';
export * from './functions';
export * from './hooks';
Expand Down
2 changes: 2 additions & 0 deletions src/utils/css.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* istanbul ignore file */

import { getRegisteredStyles, RegisteredCache } from '@emotion/utils';

/**
Expand Down

0 comments on commit 4122038

Please sign in to comment.