diff --git a/docs/api/create-styles.md b/docs/api/create-styles.md index b4aa5653..956a8583 100644 --- a/docs/api/create-styles.md +++ b/docs/api/create-styles.md @@ -214,6 +214,7 @@ createStyles 的第二个参数可以对生成的 className 做额外的控制 | 属性名 | 类型 | 描述 | | ------------ | -------------- | ------------------------------ | | hashPriority | `HashPriority` | 生成的 hash className 样式权重 | +| label | `string` | 添加后缀 | ### hashPriority @@ -222,3 +223,11 @@ createStyles 的第二个参数可以对生成的 className 做额外的控制 控制生成的 className 的权重,默认为 `high`。 如果设为 `low`,生成 hash 的样式选择器会包裹 :where 选择器,以降低权重。一般来说在组件库的使用场景中可以用到,其他场景不建议使用。 + +### label + +类型:`string` + +类似 emotion 的 label。添加 label 后,将会在把 label 添加到后缀中。一般来说无需使用。 + + diff --git a/docs/demos/api/createStyles/label.tsx b/docs/demos/api/createStyles/label.tsx new file mode 100644 index 00000000..516bed54 --- /dev/null +++ b/docs/demos/api/createStyles/label.tsx @@ -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
赋予 with-label 标签
; +}; diff --git a/src/core/createCSS.ts b/src/core/createCSS.ts index 32996a88..ca3344b6 100644 --- a/src/core/createCSS.ts +++ b/src/core/createCSS.ts @@ -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 = @@ -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 }; diff --git a/src/core/insertStyles.ts b/src/core/insertStyles.ts index ae72412c..08227711 100644 --- a/src/core/insertStyles.ts +++ b/src/core/insertStyles.ts @@ -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; diff --git a/src/factories/createStyles/index.ts b/src/factories/createStyles/index.ts index d9b72109..33b8669c 100644 --- a/src/factories/createStyles/index.ts +++ b/src/factories/createStyles/index.ts @@ -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'; @@ -19,10 +21,6 @@ interface CreateStylesFactory { useTheme: () => any; } -export interface CreateStyleOptions { - hashPriority?: HashPriority; -} - /** * 创建样式基础写法 */ @@ -30,15 +28,18 @@ export const createStylesFactory = ({ hashPriority, useTheme, EmotionContext }: CreateStylesFactory) => ( styleOrGetStyle: StyleOrGetStyleFn, - options?: CreateStyleOptions, + options?: ClassNameGeneratorOption, ) => { // 返回 useStyles 方法,作为 hooks 使用 return (props?: Props): ReturnStyles => { 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(); diff --git a/src/functions/createInstance.ts b/src/functions/createInstance.ts index 64d6313c..484b91d2 100644 --- a/src/functions/createInstance.ts +++ b/src/functions/createInstance.ts @@ -68,7 +68,6 @@ export const createInstance = (options: CreateOptions) => { speedy: internalOptions.speedy, container: internalOptions.container, }); - const EmotionContext = createEmotionContext(emotion); const StyleProvider = createStyleProvider(EmotionContext); @@ -109,7 +108,7 @@ export const createInstance = (options: CreateOptions) => { }); // ******** 上面这些都和主题相关,如果做了任何改动,都需要排查一遍 ************ // - const { cx } = createCSS(emotion.cache, internalOptions.hashPriority); + const { cx } = createCSS(emotion.cache, { hashPriority: internalOptions.hashPriority }); const { injectGlobal, keyframes } = emotion; return { diff --git a/src/types/css.ts b/src/types/css.ts index 5c875adb..bbe45ab9 100644 --- a/src/types/css.ts +++ b/src/types/css.ts @@ -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 - 模板字符串数组 diff --git a/src/types/index.ts b/src/types/index.ts index d199708b..399d9a4e 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -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';