Skip to content

Commit

Permalink
✨ feat: 新增 createInstance 方法,并用 createInstance 重构相关功能导出
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Feb 17, 2023
1 parent 0bd05a4 commit 39a05ae
Show file tree
Hide file tree
Showing 36 changed files with 472 additions and 310 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"@emotion/react": "^11",
"@emotion/serialize": "^1",
"@emotion/styled": "^11",
"@emotion/utils": "^1",
"use-merge-value": "^1"
},
"devDependencies": {
Expand Down
53 changes: 0 additions & 53 deletions src/containers/StyleProvider/index.tsx

This file was deleted.

51 changes: 0 additions & 51 deletions src/containers/ThemeProvider/index.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions src/containers/index.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/context/EmotionContext.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/context/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './EmotionContext';
export * from './ThemeModeContext';
15 changes: 15 additions & 0 deletions src/core/createCX.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ClassNamesUtil } from '@/types';
import { isReactCssResult } from '@/utils';
import { Emotion } from '@emotion/css/create-instance';

export const createCX =
(css: Emotion['css'], cx: Emotion['cx']): ClassNamesUtil =>
(...classNames) => {
return cx(
...(classNames.map((c) =>
// 由于使用了 reactCss 作为基础样式工具,因此在使用 cx 级联 className 时需要使用特殊处理的 cx
// 要将 reactCss 的产出转为 css 产物
isReactCssResult(c) ? css(c) : c,
) as any[]),
);
};
17 changes: 17 additions & 0 deletions src/core/createClassNameGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { insertStyles } from '@/core/insertStyles';
import { HashPriority } from '@/types';
import { Emotion, EmotionCache } from '@emotion/css/create-instance';
import { serializeStyles } from '@emotion/serialize';

/**
* 样式名称生成器 用于序列化的样式转换生成 className
* @param cache
* @param hashPriority
*/
export const createClassNameGenerator =
(cache: EmotionCache, hashPriority: HashPriority = 'high'): Emotion['css'] =>
(...args) => {
const serialized = serializeStyles(args, cache.registered, undefined);
insertStyles(cache, serialized, false, hashPriority);
return `${cache.key}-${serialized.name}`;
};
1 change: 1 addition & 0 deletions src/core/createEmotion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as createEmotion, type Emotion } from '@emotion/css/create-instance';
11 changes: 11 additions & 0 deletions src/core/createSerializeStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CSSInterpolation, SerializedStyles, serializeStyles } from '@emotion/serialize';

export interface SerializeCSS {
(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): SerializedStyles;
(...args: Array<CSSInterpolation>): SerializedStyles;
}
/**
* 提供给 createStyles 方法,用于将用户写入的 css 字符串序列化成特定结构的样式对象
* @param args
*/
export const serializeCSS: SerializeCSS = (...args) => serializeStyles(args);
2 changes: 0 additions & 2 deletions src/core/engine.ts

This file was deleted.

7 changes: 7 additions & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { ThemeProvider as PedestalProvider, useTheme } from '@emotion/react';
export { default as styled } from '@emotion/styled';
//
export * from './createClassNameGenerator';
export * from './createCX';
export * from './createEmotion';
export { serializeCSS, type SerializeCSS } from './createSerializeStyles';
32 changes: 8 additions & 24 deletions src/utils/insertStyles.ts → src/core/insertStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,17 @@
import type { HashPriority } from '@/types';
import type { EmotionCache } from '@emotion/css/create-instance';
import type { SerializedStyles } from '@emotion/serialize';
import { registerStyles } from '@emotion/utils';

const isBrowser = typeof document !== 'undefined';

const registerStyles = (
cache: EmotionCache,
serialized: SerializedStyles,
isStringTag: boolean,
) => {
let className = `${cache.key}-${serialized.name}`;
if (
// we only need to add the styles to the registered cache if the
// class name could be used further down
// the tree but if it's a string tag, we know it won't
// so we don't have to add it to registered cache.
// this improves memory usage since we can avoid storing the whole style string
(isStringTag === false ||
// we need to always store it if we're in compat mode and
// in node since emotion-server relies on whether a style is in
// the registered cache to know whether a style is global or not
// also, note that this check will be dead code eliminated in the browser
(isBrowser === false && cache.compat !== undefined)) &&
cache.registered[className] === undefined
) {
cache.registered[className] = serialized.styles;
}
};

/**
* 向浏览器插入样式表
* @param cache
* @param serialized
* @param isStringTag
* @param hashPriority
*/
export const insertStyles = (
cache: EmotionCache,
serialized: SerializedStyles,
Expand Down
5 changes: 5 additions & 0 deletions src/factories/createEmotionContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createContext } from 'react';

import { Emotion } from '@/core';

export const createEmotionContext = (emotion: Emotion) => createContext<Emotion>(emotion);
20 changes: 20 additions & 0 deletions src/factories/createGlobalStyle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Global } from '@emotion/react';
import { serializeStyles } from '@emotion/serialize';
import { memo } from 'react';

import { CSSStyle, Theme } from '@/types';

export interface GlobalTheme {
theme: Theme;
}

/**
* 创建全局样式
*/
export const createGlobalStyleFactory =
(useTheme: () => Theme) =>
(...styles: CSSStyle<GlobalTheme>) =>
memo((props) => {
const theme = useTheme();
return <Global styles={serializeStyles(styles, undefined, { ...props, theme })} />;
});
21 changes: 21 additions & 0 deletions src/factories/createStyish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { BaseReturnType, ReturnStyleToUse } from '@/types';
import { StyleOrGetStyleFn } from './createStyles/types';

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

/**
* 业务应用中创建复合通用样式的进阶
*/
export const createStylishFactory =
(createStyles: any) =>
<Props, Styles extends BaseReturnType>(
cssStyleOrGetCssStyleFn: StyleOrGetStyleFn<Styles, Props>,
): ((props?: Props) => ReturnStyleToUse<Styles>) => {
const useStyles = createStyles(cssStyleOrGetCssStyleFn);

return (props?: Props): ReturnStyleToUse<Styles> => {
const { styles } = useStyles(props);

return styles;
};
};
60 changes: 60 additions & 0 deletions src/factories/createStyleProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { createEmotion, Emotion } from '@/core/createEmotion';
import { StylisPlugin } from '@emotion/cache';
import { Context, FC, memo, ReactNode, useEffect, useMemo } from 'react';

export interface StyleProviderProps {
prefix: string;

nonce?: string;
stylisPlugins?: StylisPlugin[];
container?: HTMLElement;
/**
* 开启极速模式,极速模式下不会插入真实的样式 style
* @default false
*/
speedy?: boolean;
insertionPoint?: HTMLElement;

/**
* 获取到 emotion 实例
* @param emotion
*/
getEmotionInstance?: (emotion: Emotion) => void;
children: ReactNode;
}

interface DefaultProps {
prefix: string;
speedy?: boolean;
}

export const createStyleProvider = (
EmotionContext: Context<Emotion>,
defaultProps?: DefaultProps,
): FC<StyleProviderProps> =>
memo(
({
children,
prefix = defaultProps?.prefix || 'ant-css',
speedy = defaultProps?.speedy,
getEmotionInstance,

...emotionOptions
}) => {
const emotion = useMemo(() => {
const defaultSpeedy = process.env.NODE_ENV === 'development';

return createEmotion({
speedy: speedy ?? defaultSpeedy,
key: prefix,
...emotionOptions,
});
}, [prefix, speedy, emotionOptions]);

useEffect(() => {
getEmotionInstance?.(emotion);
}, [emotion]);

return <EmotionContext.Provider value={emotion}>{children}</EmotionContext.Provider>;
},
);
Loading

0 comments on commit 39a05ae

Please sign in to comment.