Skip to content

Commit

Permalink
✨ feat: support gen className by label (#62)
Browse files Browse the repository at this point in the history
* feat: support gen className by filename

* 增加注释

* ♻️ refactor: 统一 className options

* ♻️ refactor: filename 重构为 __BABEL_FILE_NAME__ ,作为内部 api

* ✨ feat: support label

---------

Co-authored-by: arvinxx <arvinx@foxmail.com>
  • Loading branch information
chenshuai2144 and arvinxx committed Jun 5, 2023
1 parent a9fc065 commit d28b19d
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 22 deletions.
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';

0 comments on commit d28b19d

Please sign in to comment.