UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

1 lines 9.07 kB
{"version":3,"file":"themeVars.mjs","names":["antdTheme"],"sources":["../../src/static-css/themeVars.ts"],"sourcesContent":["import { existsSync, readdirSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport type { ThemeConfig } from 'antd';\nimport { theme as antdTheme } from 'antd';\n\nimport { createLobeAntdTheme } from '@/styles/theme/antdTheme';\n\nimport { hashCss } from './hash';\n\ntype ThemeAppearance = 'dark' | 'light';\n\nexport interface ThemeVarsCssOptions {\n /** selector activating an appearance; default matches next-themes' data-theme attribute */\n appearanceSelector?: (appearance: ThemeAppearance) => string;\n /** dark fixups for lobe-ui antdOverride primary-on-contrast rules */\n compatRules?: boolean;\n hrefTemplate?: (hash: string) => string;\n /** same theme factory the app hands to ConfigProvider/ThemeProvider */\n theme?: (appearance: ThemeAppearance) => ThemeConfig;\n}\n\nexport interface ThemeVarsCssPayload {\n css: string;\n hash: string;\n href: string;\n skippedComponents: string[];\n}\n\nconst require = createRequire(import.meta.url);\n\nconst unitless = new Set([\n 'fontWeightStrong',\n 'lineHeight',\n 'lineHeightHeading1',\n 'lineHeightHeading2',\n 'lineHeightHeading3',\n 'lineHeightHeading4',\n 'lineHeightHeading5',\n 'lineHeightLG',\n 'lineHeightSM',\n 'opacityImage',\n 'opacityLoading',\n 'zIndexBase',\n 'zIndexPopupBase',\n]);\n\nconst ignoredTokens = new Set(['motionBase', 'motionUnit']);\n\n// same kebab algorithm as antd-style's toKebabCase, so names match antd's emitted vars\nexport const toKebabCase = (str: string) =>\n str\n .replaceAll(/([a-z])([A-Z])/g, '$1-$2')\n .replaceAll(/([a-z])(\\d)/g, '$1-$2')\n .replaceAll(/(\\d)([A-Z])/g, '$1-$2')\n .replaceAll(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n\nconst defaultThemeFactory = (appearance: ThemeAppearance): ThemeConfig =>\n createLobeAntdTheme({ appearance });\n\nconst buildDesignToken = (\n themeFactory: (appearance: ThemeAppearance) => ThemeConfig,\n appearance: ThemeAppearance,\n) => {\n const themeConfig = themeFactory(appearance);\n return antdTheme.getDesignToken({\n ...themeConfig,\n algorithm: [\n appearance === 'dark' ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,\n themeConfig.algorithm ?? [],\n ].flat(),\n }) as unknown as Record<string, number | string>;\n};\n\nconst toDeclarations = (token: Record<string, number | string>) =>\n Object.entries(token)\n .filter(\n ([key, value]) =>\n !key.startsWith('_') &&\n !key.startsWith('screen') &&\n !key.includes('-') &&\n !ignoredTokens.has(key) &&\n (typeof value === 'string' || typeof value === 'number'),\n )\n .map(([key, value]) => {\n const cssValue =\n typeof value === 'number' && !unitless.has(key) ? `${value}px` : String(value);\n return `--ant-${toKebabCase(key)}: ${cssValue};`;\n })\n .join('\\n');\n\nconst loadAntdTokenModules = () => {\n const antdLibDir = path.join(path.dirname(require.resolve('antd/package.json')), 'lib');\n\n return readdirSync(antdLibDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .sort()\n .map((name) => ({ component: name, path: path.join(antdLibDir, name, 'style', 'token.js') }))\n .filter(({ path }) => existsSync(path));\n};\n\nconst buildDarkComponentVars = (tokens: {\n dark: Record<string, number | string>;\n light: Record<string, number | string>;\n}) => {\n const declarations: string[] = [];\n const skipped: string[] = [];\n\n for (const { component, path } of loadAntdTokenModules()) {\n try {\n const mod = require(path) as { prepareComponentToken?: unknown };\n const prepare = mod.prepareComponentToken;\n if (typeof prepare !== 'function') continue;\n\n const light = prepare(tokens.light) as Record<string, unknown>;\n const dark = prepare(tokens.dark) as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(dark)) {\n if (typeof value !== 'string' || light[key] === value) continue;\n declarations.push(`--ant-${component}-${toKebabCase(key)}:${value};`);\n }\n } catch {\n skipped.push(component);\n }\n }\n\n return { css: declarations.join(''), skipped };\n};\n\nconst readableOnPrimary = 'contrast-color(var(--ant-color-primary))';\n\nconst buildCompatRules = (darkSelector: string): string => {\n return [\n [\n `${darkSelector} .ant-btn-primary:not(:disabled)`,\n `${darkSelector} .ant-btn-primary:not(:disabled):hover`,\n `${darkSelector} .ant-btn-primary:not(:disabled):active`,\n ].join(',') + `{color:${readableOnPrimary} !important;}`,\n `${darkSelector} .ant-checkbox-inner:after{border-color:${readableOnPrimary} !important;}`,\n `${darkSelector} .ant-radio-wrapper .ant-radio-checked .ant-radio-inner:after{background:${readableOnPrimary};}`,\n ].join('\\n');\n};\n\nexport const buildThemeVarsCss = (options: ThemeVarsCssOptions = {}): ThemeVarsCssPayload => {\n const {\n theme = defaultThemeFactory,\n appearanceSelector = (appearance) => `html[data-theme='${appearance}']`,\n compatRules = true,\n hrefTemplate = (hash) => `/theme-vars.css?v=${hash}`,\n } = options;\n\n const tokens = {\n dark: buildDesignToken(theme, 'dark'),\n light: buildDesignToken(theme, 'light'),\n };\n\n const light = appearanceSelector('light');\n const dark = appearanceSelector('dark');\n const componentVars = buildDarkComponentVars(tokens);\n\n // antd v6 cssVar mode re-declares all --ant-* with SSR-light literals on\n // [class*='css-var-'] / .ant-app, which would shadow the html-level palettes\n const blocks = [\n [':root', `${light} [class*='css-var-']`, `${light} .ant-app`].join(',') +\n `{${toDeclarations(tokens.light)}}`,\n [dark, `${dark} [class*='css-var-']`, `${dark} .ant-app`].join(',') +\n `{${toDeclarations(tokens.dark)}}`,\n `${dark} [class*='css-var-']{${componentVars.css}}`,\n ];\n\n if (compatRules) blocks.push(buildCompatRules(dark));\n\n const css = blocks.join('\\n');\n const hash = hashCss(css);\n\n return { css, hash, href: hrefTemplate(hash), skippedComponents: componentVars.skipped };\n};\n"],"mappings":"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"}