Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support gen className by filename #62

Merged
merged 7 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/api/create-styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ createStyles 的第二个参数可以对生成的 className 做额外的控制
| 属性名 | 类型 | 描述 |
| ------------ | -------------- | ------------------------------ |
| hashPriority | `HashPriority` | 生成的 hash className 样式权重 |
| label | `string` | 添加后缀 |

### hashPriority

Expand All @@ -222,3 +223,11 @@ createStyles 的第二个参数可以对生成的 className 做额外的控制
控制生成的 className 的权重,默认为 `high`。

如果设为 `low`,生成 hash 的样式选择器会包裹 :where 选择器,以降低权重。一般来说在组件库的使用场景中可以用到,其他场景不建议使用。

### label

类型:`string`

类似 emotion 的 label。添加 label 后,将会在把 label 添加到后缀中。一般来说无需使用。

<code src="../demos/api/createStyles/label.tsx"></code>
15 changes: 15 additions & 0 deletions docs/demos/api/createStyles/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createStyles } from 'antd-style';

const useStyles = createStyles(
({ css }) => ({
text: css`
color: blue;
`,
}),
{ label: 'with-label' },
);

export default () => {
const { styles } = useStyles();
return <div className={styles.text}>赋予 with-label 标签</div>;
};
23 changes: 15 additions & 8 deletions src/core/createCSS.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { insertStyles } from '@/core/insertStyles';
import { ClassNameGenerator, ClassNamesUtil, HashPriority } from '@/types';
import { createHashStyleName, insertStyles, InternalClassNameOption } from '@/core/insertStyles';
import { ClassNameGenerator, ClassNamesUtil } from '@/types';
import { classnames, isReactCssResult, mergeCSS } from '@/utils';
import { EmotionCache } from '@emotion/css/create-instance';
import { serializeStyles } from '@emotion/serialize';

const createClassNameGenerator =
(cache: EmotionCache, hashPriority: HashPriority): ClassNameGenerator =>
(cache: EmotionCache, options: InternalClassNameOption): ClassNameGenerator =>
(...args) => {
const serialized = serializeStyles(args, cache.registered, undefined);
insertStyles(cache, serialized, false, hashPriority);
return `${cache.key}-${serialized.name}`;

insertStyles(cache, serialized, false, options);

return createHashStyleName(cache.key, serialized.name, options);
};

const createCX =
Expand All @@ -25,10 +27,15 @@ const createCX =
/**
* CSS相关方法生成器 用于序列化的样式转换生成 className
* @param cache
* @param hashPriority
* @param options
*/
export const createCSS = (cache: EmotionCache, hashPriority: HashPriority = 'high') => {
const css = createClassNameGenerator(cache, hashPriority);
export const createCSS = (cache: EmotionCache, options: InternalClassNameOption) => {
const css = createClassNameGenerator(cache, {
hashPriority: options.hashPriority || 'high',
label: options.label,
__BABEL_FILE_NAME__: options.__BABEL_FILE_NAME__,
});

const cx = createCX(cache, css);

return { css, cx };
Expand Down
32 changes: 28 additions & 4 deletions src/core/insertStyles.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
// copied from https://github.com/emotion-js/emotion/blob/main/packages/utils/src/index.js
import type { HashPriority } from '@/types';
import { ClassNameGeneratorOption } 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';

export interface InternalClassNameOption extends ClassNameGeneratorOption {
/**
* 用于生成 className 的文件名,用于 babel 插件使用,不对用户透出
*/
__BABEL_FILE_NAME__?: string;
}

export const createHashStyleName = (
cacheKey: string,
hash: string,
options?: InternalClassNameOption,
) => {
const fileName = options?.__BABEL_FILE_NAME__;
const label = options?.label;

const babelSuffix = fileName ? `__${fileName}` : '';
const labelSuffix = label ? `__${label}` : '';

const prefix = `${cacheKey}-${hash}`;

return prefix + labelSuffix + babelSuffix;
};

/**
* 向浏览器插入样式表
* @param cache
* @param serialized
* @param isStringTag
* @param hashPriority
* @param options
*/
export const insertStyles = (
cache: EmotionCache,
serialized: SerializedStyles,
isStringTag: boolean,
hashPriority: HashPriority = 'high',
options: InternalClassNameOption,
) => {
const hashPriority = options.hashPriority || 'high';
registerStyles(cache, serialized, isStringTag);

const hashClassName = `.${cache.key}-${serialized.name}`;
const hashClassName = `.${createHashStyleName(cache.key, serialized.name, options)}`;

const hashSelector = hashPriority === 'low' ? `:where(${hashClassName})` : hashClassName;

Expand Down
15 changes: 8 additions & 7 deletions src/factories/createStyles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { Emotion, createCSS, serializeCSS } from '@/core';
import type {
BaseReturnType,
CSSObject,
ClassNameGeneratorOption,
HashPriority,
ResponsiveUtil,
ReturnStyleToUse,
} from '@/types';
import { isReactCssResult } from '@/utils';

import { InternalClassNameOption } from '@/core/insertStyles';
import { convertResponsiveStyleToString, useMediaQueryMap } from './response';
import { ReturnStyles, StyleOrGetStyleFn } from './types';

Expand All @@ -19,26 +21,25 @@ interface CreateStylesFactory {
useTheme: () => any;
}

export interface CreateStyleOptions {
hashPriority?: HashPriority;
}

/**
* 创建样式基础写法
*/
export const createStylesFactory =
({ hashPriority, useTheme, EmotionContext }: CreateStylesFactory) =>
<Props, Input extends BaseReturnType = BaseReturnType>(
styleOrGetStyle: StyleOrGetStyleFn<Input, Props>,
options?: CreateStyleOptions,
options?: ClassNameGeneratorOption,
) => {
// 返回 useStyles 方法,作为 hooks 使用
return (props?: Props): ReturnStyles<Input> => {
const theme = useTheme();

const { cache } = useContext(EmotionContext);
// 由于 toClassName 方法依赖了用户给 createStyle 传递的 hashPriority,所以需要在这里重新生成 cx 和 toClassName 方法
const { cx, css: toClassName } = createCSS(cache, options?.hashPriority || hashPriority);
const { cx, css: toClassName } = createCSS(cache, {
hashPriority: options?.hashPriority || hashPriority,
label: options?.label,
__BABEL_FILE_NAME__: (options as InternalClassNameOption)?.__BABEL_FILE_NAME__,
});

const responsiveMap = useMediaQueryMap();

Expand Down
3 changes: 1 addition & 2 deletions src/functions/createInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ export const createInstance = <T = any>(options: CreateOptions<T>) => {
speedy: internalOptions.speedy,
container: internalOptions.container,
});

const EmotionContext = createEmotionContext(emotion);

const StyleProvider = createStyleProvider(EmotionContext);
Expand Down Expand Up @@ -109,7 +108,7 @@ export const createInstance = <T = any>(options: CreateOptions<T>) => {
});

// ******** 上面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************ //
const { cx } = createCSS(emotion.cache, internalOptions.hashPriority);
const { cx } = createCSS(emotion.cache, { hashPriority: internalOptions.hashPriority });
const { injectGlobal, keyframes } = emotion;

return {
Expand Down
5 changes: 5 additions & 0 deletions src/types/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ export type { SerializedStyles } from '@emotion/serialize';

export type ClassNameGenerator = Emotion['css'];

export interface ClassNameGeneratorOption {
label?: string;
hashPriority?: HashPriority;
}

/**
* @title CSS 工具函数
* @param template - 模板字符串数组
Expand Down
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export * from './css';
export * from './function';
export * from './genericUtils';
export * from './response';
export * from './styled';
export * from './styleManager';
export * from './styled';
export * from './theme';