@apollo-design/theme 0.0.0-stage → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +140 -2
  2. package/dist/algorithms/compact.mjs +19 -0
  3. package/dist/algorithms/dark.mjs +36 -0
  4. package/dist/algorithms/default.mjs +28 -0
  5. package/dist/algorithms/palettes.mjs +123 -0
  6. package/dist/alias.mjs +169 -0
  7. package/dist/css-var.mjs +153 -0
  8. package/dist/get-design-token.mjs +42 -0
  9. package/dist/index.d.mts +360 -0
  10. package/dist/index.d.ts +360 -0
  11. package/dist/index.mjs +17 -0
  12. package/dist/merge-theme.mjs +21 -0
  13. package/dist/presets/default.css +108 -0
  14. package/dist/presets/default.d.mts +6 -0
  15. package/dist/presets/default.d.ts +6 -0
  16. package/dist/presets/default.mjs +3 -0
  17. package/dist/presets/material3.css +54 -0
  18. package/dist/presets/material3.d.mts +6 -0
  19. package/dist/presets/material3.d.ts +6 -0
  20. package/dist/presets/material3.mjs +71 -0
  21. package/dist/presets/mono.css +54 -0
  22. package/dist/presets/mono.d.mts +6 -0
  23. package/dist/presets/mono.d.ts +6 -0
  24. package/dist/presets/mono.mjs +41 -0
  25. package/dist/seed.mjs +74 -0
  26. package/dist/shared/color-map-token.mjs +97 -0
  27. package/dist/shared/common-map-token.mjs +14 -0
  28. package/dist/shared/control-height.mjs +9 -0
  29. package/dist/shared/font-map-token.mjs +36 -0
  30. package/dist/shared/font-sizes.mjs +27 -0
  31. package/dist/shared/get-alpha-color.mjs +28 -0
  32. package/dist/shared/radius.mjs +44 -0
  33. package/dist/shared/size-map-token.mjs +31 -0
  34. package/dist/shared/theme.DBaLDtcj.d.mts +358 -0
  35. package/dist/shared/theme.DBaLDtcj.d.ts +358 -0
  36. package/dist/tokens.css +146 -0
  37. package/dist/vue.mjs +113 -0
  38. package/package.json +52 -3
package/README.md CHANGED
@@ -1,3 +1,141 @@
1
- # Temporary Holding Version
1
+ # @apollo-design/theme
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Apollo 的 L0 设计令牌包:Seed → Map → Alias 派生、CSS 变量转换与 Vue 主题上下文。规范来源见 [AGENTS.md](../../AGENTS.md) 和 [ARCHITECTURE.md](../../ARCHITECTURE.md);历史 Ant Design 对照保留为回归证据。
4
+
5
+ 运行依赖为 `@apollo-design/utils`,Vue 是 peer dependency。`@ant-design/colors` / `@ant-design/fast-color` 仅作为开发对照工具,不进入发布运行图。基础包不依赖 UI。
6
+
7
+ ## 预设与明暗
8
+
9
+ ```vue
10
+ <script setup lang="ts">
11
+ import { ConfigProvider } from '@apollo-design/ui';
12
+ import { monoPreset } from '@apollo-design/theme/presets/mono';
13
+ </script>
14
+
15
+ <template>
16
+ <ConfigProvider :theme="{ preset: monoPreset, mode: 'system' }">
17
+ <App />
18
+ </ConfigProvider>
19
+ </template>
20
+ ```
21
+
22
+ 预设是 `ThemePreset` 数据对象,与 `mode: 'light' | 'dark' | 'system'` 独立。三个内置入口分别是 `presets/default`(`defaultPreset`)、`presets/mono`(`monoPreset`)和 `presets/material3`(`material3Preset`);每个入口也有 default 导出。根入口不汇总预设,因此单独使用 Mono 不引入另外两套预设。Material 3 是色彩、排版、形状、表面与阴影的启发式预设,保留 Apollo 的组件结构、交互和无障碍契约。
23
+
24
+ 用户预设使用同一公开 API,无需注册名称或主题 resolver:
25
+
26
+ ```ts
27
+ import { getDesignToken, type ThemePreset } from '@apollo-design/theme';
28
+
29
+ const brand: ThemePreset = {
30
+ name: 'brand',
31
+ token: { fontSize: 16, borderRadius: 6 },
32
+ light: { token: { colorPrimary: '#006b60', colorBgBase: '#f8fffc' } },
33
+ dark: { token: { colorPrimary: '#1a786d', colorBgBase: '#0b1715' } },
34
+ };
35
+ const token = getDesignToken({ preset: brand, mode: 'dark', token: { fontSize: 18 } });
36
+ ```
37
+
38
+ 派生顺序为默认 Seed → preset.token → preset 当前 light/dark.token → 用户 token 中的 Seed → 算法 → 用户 Alias 覆盖;`components` 留给 UI 按最终组件覆盖消费。修改主色同时改变 hover/active 等色板,修改字号同时改变派生排版。`ThemePresetScheme.algorithm` 可定义该预设的真实派生规则,显式 `ThemeConfig.algorithm` 仍是完整算法链并优先于预设算法。已知 default/dark/compact 算法也决定选用预设的亮暗分支;局部显式 algorithm 不被外层 mode 覆盖,局部显式 mode 则替代继承的 algorithm。
39
+
40
+ `getDesignToken({mode:'system'})` 是确定性的服务端亮色;已知请求偏好时可传第二参数 `'dark'` 或 `'light'`。Vue 中的活跃 Provider 在 mounted 后读取并监听系统偏好,切换 mode 或卸载时释放监听。组件外的 `createThemeContext()` 不持有浏览器生命周期;应传入实际 light/dark 或自行更新 config。
41
+
42
+ `ConfigProvider` 在有显式主题来源时向业务根和浮层投影完整变量,使用 Mono 或自定义预设无需同时引入默认 `tokens.css`。仍需按所选导入方式引入 UI 结构 CSS。
43
+
44
+ ## 静态样式
45
+
46
+ ```ts
47
+ import '@apollo-design/theme/tokens.css';
48
+ import '@apollo-design/ui/style.css';
49
+ ```
50
+
51
+ `tokens.css` 提供默认、`[data-apollo-theme="dark"]`、`[data-apollo-theme="compact"]`、`[data-apollo-theme="dark-compact"]` 四套变量。组件规则使用默认 `--apollo-*` 名称。自定义变量前缀需要对应样式消费;DOM 类名前缀由 UI 的 `ConfigProvider.prefixCls` 配置。
52
+
53
+ 每个预设另有独立的可选静态资源 `@apollo-design/theme/presets/default.css`、`mono.css`、`material3.css`,均由相同的 `getDesignToken` / `getCSSVarDeclarations` 生成,不导入其它预设或旧变量表。给全局或局部变量根显式设置 `data-apollo-preset="mono"` 与 `data-apollo-theme="light|dark|system"`;后代继承这些变量。system 的静态资源通过 prefers-color-scheme 媒体查询选择暗色,可在 JS 启动前配置 HTML 属性。自定义预设的 SSR/CSS 也用 `getCSSVarDeclarations(getDesignToken(...))` 输出,无需另一张手写色表。静态变量表服务于 CSS/首屏;需要组件级覆盖及 JS Token 消费时,Provider 使用同一 preset/mode。
54
+
55
+ ## 纯函数派生
56
+
57
+ ```ts
58
+ import { compactAlgorithm, darkAlgorithm, getDesignToken } from '@apollo-design/theme';
59
+
60
+ const token = getDesignToken({
61
+ algorithm: [darkAlgorithm, compactAlgorithm],
62
+ token: { colorPrimary: '#6455ff', fontSize: 16, colorPrimaryBg: '#101030' },
63
+ });
64
+ ```
65
+
66
+ `getDesignToken()` 默认使用 `defaultAlgorithm`;`algorithm: []` 也得到完整默认令牌。非空数组按顺序把前一算法的 Map 结果传给后一算法。已知 Seed/Map/Alias 键遵守各自值类型,未知扩展接受 string/number/boolean。显式 `undefined` 等同省略;`0`、`false` 和有语义的空串保留。`components` 由 UI 消费,本函数不把组件覆盖混入 Alias。
67
+
68
+ 颜色派生使用 utils.Color 支持的具体色值,如 hex、rgb/rgba、hsl/hsla、hsv/hsva;不是浏览器的完整 CSS 颜色解析器,不解析颜色名称、`var()` 或 `color-mix()`。`colorLink: ''` 有明确的回退语义;预设色空串会报颜色解析错误。数值按各 Token 语义配置:常规正字号及小数字号保留派生精度;零、极小、负字号和非有限数不自动归一化,仍可能生成无效数值,不属于支持的字号输入域。允许零的尺寸、关闭动效等有效值不被当作缺省。
69
+
70
+ 源级派生函数不访问 DOM,也不导入 Vue。公共根入口同时导出 Vue 绑定,仍需已声明的 Vue peer;没有未声明的纯函数子路径。
71
+
72
+ ## Vue 上下文与 Provider
73
+
74
+ ```vue
75
+ <script setup lang="ts">
76
+ import { ThemeProvider } from '@apollo-design/theme';
77
+ </script>
78
+
79
+ <template>
80
+ <ThemeProvider :theme="{ token: { colorPrimary: '#6455ff' } }" inject-css-var>
81
+ <App />
82
+ </ThemeProvider>
83
+ </template>
84
+ ```
85
+
86
+ | Prop | 类型 | 默认 | 行为 |
87
+ | --- | --- | --- | --- |
88
+ | theme | ThemeConfig | `{}` | 当前配置;后续整值或深层 prop 更新恢复 prop 的权威值 |
89
+ | injectCssVar | boolean | false | 挂载后把当前有效 Token 写入目标;支持动态启停 |
90
+ | target | HTMLElement \| SVGElement \| null | 客户端 document.documentElement | 变量目标;null/省略均回落到文档根,支持原生模板 DOM 引用;切换时释放旧目标 |
91
+
92
+ Provider 保持 renderless,只有默认槽,无自定义 Emits、v-model 或 Expose。DOM attrs/listeners 放在业务元素上;Provider 不隐式转发给多根槽或变量 target。条件槽正常更新,主题切换不重挂业务子树。SSR 只提供数据,DOM 注入在 mounted 后执行;卸载释放自己的 scope。
93
+
94
+ `ThemeProvider` 保留既有默认:`theme={}` 是显式重置,不继承父主题,CSS 变量前缀也沿用本地默认;设置 `theme.inherit: true` 才合并最近的原始配置。UI `ConfigProvider` 保留默认继承,`theme.inherit: false` 才重置,并保留父 CSS 变量前缀。这两个边界都调用 `mergeThemeConfig(parent, own)`,不把已派生的父 Alias 当作子预设输入;token 按键合并,components 按组件与键合并。重置后预设、明暗、用户 token 与组件覆盖从本地开始。
95
+
96
+ 在组件 setup 中调用 `useTheme()` 或 `useToken()`。`useTheme().config` 是可写深层 Ref,`token` 是随有效配置更新的 ComputedRef:
97
+
98
+ ```ts
99
+ const theme = useTheme();
100
+ theme.config.value = { token: { fontSize: 18 } };
101
+ theme.config.value.token = { ...theme.config.value.token, fontSize: 20 };
102
+ ```
103
+
104
+ 也可通过 `config.value.token` / `components` 的代理对象原位更新。`createThemeContext(config)` 使用 Vue ref 语义;修改外部原始对象不会绕过 Vue 自动触发响应,使用 `config.value`、传入 reactive 对象或整值替换。Provider 的本地可写配置与输入 props 隔离,后续 prop 更新会覆盖本地运行修改。保证的是 Ref.value 更新;不承诺重绑 Ref 容器、修改计算结果或改变导出默认对象来更新现存缓存。
105
+
106
+ 最近的显式主题上下文优先。无 Provider 时,同一 Vue app 共享惰性默认 context,不同 app 隔离;SSR 每个请求创建自己的 app,复用同一个 app 则仍是同一份上下文。确需跨 app 共享时显式 provide 同一个 `createThemeContext()` 结果。
107
+
108
+ `sourceActive` 是可选只读来源元数据:无源默认 context 为空配置时是 false,写入非空配置后为 true,清空恢复 false;显式 ThemeProvider 即使 `{}` 也为 true。旧自定义 context 不带此字段仍视作显式来源。UI writer 需要区分无源 CSS 主题与显式默认主题。
109
+
110
+ ## CSS 变量 API
111
+
112
+ - `token2CSSVar(name, prefix?)`:稳定的 Token → CSS 变量命名,默认前缀 apollo,空前缀也受支持。
113
+ - `transformToken(token, prefix?)`:返回 `{ vars, refs }`;只处理 string/number,保留断点原值,单位表字段不加 px,忽略派生配置字段。
114
+ - `getCSSVarDeclarations(token, { prefix?, selector? })`:无 DOM 静态规则,默认 selector 为 `:root`。
115
+ - `createCSSVarScope(el, prefix?)`:`apply(token)` / `remove()` / `keys`;重复 apply 释放已消失的键,keys 是快照,remove 可重复且之后可再 apply。
116
+ - `applyCSSVar(el, token, prefix?)` / `injectTokenCssVar(...)`:一次性加法写入,无 owner 注册、无回收句柄;后续未包含的键不自动删除。
117
+
118
+ 同目标同变量由最近一次 apply 的活跃 scope 提供;释放后恢复其他活跃 scope 或原有 inline 值及 priority。不同目标/前缀独立。外部直接写入不同值或 priority 后,scope 清理保留该外部写入;CSSOM 无法区分完全相同值的普通外部写入。一次性 API 明确交出所有权,即使写入相同值也可在 scope 清理后保留。
119
+
120
+ ## 全部根导出
121
+
122
+ | 分类 | 导出 |
123
+ | --- | --- |
124
+ | 派生/算法 | getDesignToken, formatToken, algorithms, defaultAlgorithm, darkAlgorithm, compactAlgorithm, mergeThemeConfig |
125
+ | 默认值/预设色 | defaultSeedToken, defaultPresetColors, PresetColors |
126
+ | 共享派生函数 | genColorMapToken, genCommonMapToken, genControlHeight, genFontMapToken, genFontSizes, getLineHeight, getAlphaColor, genRadius, genCompactSizeMapToken, genSizeMapToken |
127
+ | CSS | DEFAULT_CSS_VAR_PREFIX, UNITLESS, IGNORE, PRESERVE, token2CSSVar, transformToken, getCSSVarDeclarations, createCSSVarScope, applyCSSVar |
128
+ | Vue | ThemeContextKey, createThemeContext, ThemeProvider, useTheme, useToken, injectTokenCssVar |
129
+ | 输入/主题类型 | SeedToken, MappingAlgorithm, ThemeConfig, ThemeContext, DerivativeTokenWithOverride, ThemePreset, ThemePresetScheme, ThemeMode, ThemeAppearance, ThemeTokenOverrides |
130
+ | Map 类型 | ColorMapToken, ColorNeutralMapToken, ColorPalette, FontMapToken, SizeMapToken, HeightMapToken, StyleMapToken, CommonMapToken, MapToken |
131
+ | 其他类型 | AliasToken, GlobalToken, ComponentTokenMap, PresetColorKey, PresetColorType, PresetColorPalettes, TransformResult, CSSVarScope |
132
+
133
+ `ThemeConfig` 包含 token、algorithm、cssVarPrefix、components、preset、mode 与 inherit。预设值从上述独立子入口导入。无消费的 `theme.prefixCls` 已移除;迁移与既有错误输入修正见 [Theme 契约迁移](../../docs/migrations/theme-foundation-contracts.md)。
134
+
135
+ ## 验证
136
+
137
+ 完整范围、失败复现、源回归和未验证边界见 [Theme 基础包审计](../../docs/audit/2026-10-29-theme-foundation-contract-audit.md)。包测试与类型检查遵循 [TESTING.md](../../TESTING.md);浏览器回归入口是 `node tests/browser/theme-foundation.mjs`,支持已冻结产物的 `THEME_FOUNDATION_MODE=published`,自身不构建包。
138
+
139
+ 变量目标也可为原生SVGElement;createCSSVarScope/applyCSSVar/injectTokenCssVar使用同一目标类型,保留原有style变量写入行为。
140
+
141
+ CSS变量转换/静态声明与scope/一次性写入接受`Partial<AliasToken>`,使原本已有效的部分变量操作具有准确声明;已知字段类型保持精确。scope.apply缺失字段仅释放自己的旧写入,一次性apply保持加法语义,原有所有权与原生覆盖规则不分叉。
@@ -0,0 +1,19 @@
1
+ import { genControlHeight } from '../shared/control-height.mjs';
2
+ import genFontMapToken from '../shared/font-map-token.mjs';
3
+ import { genCompactSizeMapToken } from '../shared/size-map-token.mjs';
4
+ import defaultAlgorithm from './default.mjs';
5
+
6
+ function compactAlgorithm(token, mapToken) {
7
+ const mergedMapToken = mapToken ?? defaultAlgorithm(token);
8
+ const fontSize = mergedMapToken.fontSizeSM;
9
+ const controlHeight = mergedMapToken.controlHeight - 4;
10
+ return {
11
+ ...mergedMapToken,
12
+ ...genCompactSizeMapToken(mapToken ?? token),
13
+ ...genFontMapToken(fontSize),
14
+ controlHeight,
15
+ ...genControlHeight(controlHeight)
16
+ };
17
+ }
18
+
19
+ export { compactAlgorithm as default };
@@ -0,0 +1,36 @@
1
+ import { generatePalette } from '@apollo-design/utils';
2
+ import { PresetColors, DARK_PALETTE_BASE } from '../seed.mjs';
3
+ import genColorMapToken from '../shared/color-map-token.mjs';
4
+ import defaultAlgorithm from './default.mjs';
5
+ import { genPresetColorPalettes, generateNeutralColorPalettesDark, generateColorPalettesDark } from './palettes.mjs';
6
+
7
+ function darkAlgorithm(token, mapToken) {
8
+ const colorPalettes = genPresetColorPalettes(
9
+ token,
10
+ (base) => generatePalette(base, { theme: "dark", backgroundColor: DARK_PALETTE_BASE })
11
+ );
12
+ const mergedMapToken = mapToken ?? defaultAlgorithm(token);
13
+ const colorMapToken = genColorMapToken(token, {
14
+ generateColorPalettes: generateColorPalettesDark,
15
+ generateNeutralColorPalettes: generateNeutralColorPalettesDark
16
+ });
17
+ const presetColorHoverActiveTokens = {};
18
+ for (const colorKey of PresetColors) {
19
+ const colorBase = token[colorKey];
20
+ if (colorBase) {
21
+ const colorPalette = generateColorPalettesDark(colorBase);
22
+ presetColorHoverActiveTokens[`${colorKey}Hover`] = colorPalette[7];
23
+ presetColorHoverActiveTokens[`${colorKey}Active`] = colorPalette[5];
24
+ }
25
+ }
26
+ return {
27
+ ...mergedMapToken,
28
+ ...colorPalettes,
29
+ ...colorMapToken,
30
+ ...presetColorHoverActiveTokens,
31
+ colorPrimaryBg: colorMapToken.colorPrimaryBorder,
32
+ colorPrimaryBgHover: colorMapToken.colorPrimaryBorderHover
33
+ };
34
+ }
35
+
36
+ export { darkAlgorithm as default };
@@ -0,0 +1,28 @@
1
+ import { generatePalette } from '@apollo-design/utils';
2
+ import genColorMapToken from '../shared/color-map-token.mjs';
3
+ import { genCommonMapToken } from '../shared/common-map-token.mjs';
4
+ import { genControlHeight } from '../shared/control-height.mjs';
5
+ import genFontMapToken from '../shared/font-map-token.mjs';
6
+ import { genSizeMapToken } from '../shared/size-map-token.mjs';
7
+ import { genPresetColorPalettes, generateNeutralColorPalettes, generateColorPalettes } from './palettes.mjs';
8
+
9
+ function defaultAlgorithm(token) {
10
+ const colorPalettes = genPresetColorPalettes(
11
+ token,
12
+ (base) => generatePalette(base)
13
+ );
14
+ return {
15
+ ...token,
16
+ ...colorPalettes,
17
+ ...genColorMapToken(token, {
18
+ generateColorPalettes,
19
+ generateNeutralColorPalettes
20
+ }),
21
+ ...genFontMapToken(token.fontSize),
22
+ ...genSizeMapToken(token),
23
+ ...genControlHeight(token.controlHeight),
24
+ ...genCommonMapToken(token)
25
+ };
26
+ }
27
+
28
+ export { defaultAlgorithm as default };
@@ -0,0 +1,123 @@
1
+ import { generatePalette, Color } from '@apollo-design/utils';
2
+ import { defaultPresetColors, DARK_PALETTE_BASE } from '../seed.mjs';
3
+
4
+ const getSolidColor = (baseColor, brightness) => new Color(baseColor).darken(brightness).toHexString();
5
+ const getSolidColorDark = (baseColor, brightness) => new Color(baseColor).lighten(brightness).toHexString();
6
+ const getAlphaColor = (baseColor, alpha) => new Color(baseColor).setAlpha(alpha).toRgbString();
7
+ const generateColorPalettes = (baseColor) => {
8
+ const colors = generatePalette(baseColor);
9
+ return {
10
+ 1: colors[0],
11
+ 2: colors[1],
12
+ 3: colors[2],
13
+ 4: colors[3],
14
+ 5: colors[4],
15
+ 6: colors[5],
16
+ 7: colors[6],
17
+ 8: colors[4],
18
+ 9: colors[5],
19
+ 10: colors[6]
20
+ };
21
+ };
22
+ const generateColorPalettesDark = (baseColor) => {
23
+ const colors = generatePalette(baseColor, {
24
+ theme: "dark",
25
+ backgroundColor: DARK_PALETTE_BASE
26
+ });
27
+ return {
28
+ 1: colors[0],
29
+ 2: colors[1],
30
+ 3: colors[2],
31
+ 4: colors[3],
32
+ 5: colors[6],
33
+ 6: colors[5],
34
+ 7: colors[4],
35
+ 8: colors[6],
36
+ 9: colors[5],
37
+ 10: colors[4]
38
+ };
39
+ };
40
+ const generateNeutralColorPalettes = (bgBaseColor, textBaseColor, shadowColor) => {
41
+ const colorBgBase = bgBaseColor || "#fff";
42
+ const colorTextBase = textBaseColor || "#000";
43
+ const colorShadow = shadowColor || "#000";
44
+ return {
45
+ colorBgBase,
46
+ colorTextBase,
47
+ colorShadow,
48
+ colorText: getAlphaColor(colorTextBase, 0.88),
49
+ colorTextSecondary: getAlphaColor(colorTextBase, 0.65),
50
+ colorTextTertiary: getAlphaColor(colorTextBase, 0.45),
51
+ colorTextQuaternary: getAlphaColor(colorTextBase, 0.25),
52
+ colorFill: getAlphaColor(colorTextBase, 0.15),
53
+ colorFillSecondary: getAlphaColor(colorTextBase, 0.06),
54
+ colorFillTertiary: getAlphaColor(colorTextBase, 0.04),
55
+ colorFillQuaternary: getAlphaColor(colorTextBase, 0.02),
56
+ colorBgSolid: getAlphaColor(colorTextBase, 1),
57
+ colorBgSolidHover: getAlphaColor(colorTextBase, 0.75),
58
+ colorBgSolidActive: getAlphaColor(colorTextBase, 0.95),
59
+ colorBgLayout: getSolidColor(colorBgBase, 4),
60
+ colorBgContainer: getSolidColor(colorBgBase, 0),
61
+ colorBgElevated: getSolidColor(colorBgBase, 0),
62
+ colorBgSpotlight: getAlphaColor(colorTextBase, 0.85),
63
+ colorBgBlur: "transparent",
64
+ colorBorder: getSolidColor(colorBgBase, 15),
65
+ colorBorderDisabled: getSolidColor(colorBgBase, 15),
66
+ colorBorderSecondary: getSolidColor(colorBgBase, 6)
67
+ };
68
+ };
69
+ const generateNeutralColorPalettesDark = (bgBaseColor, textBaseColor, shadowColor) => {
70
+ const colorBgBase = bgBaseColor || "#000";
71
+ const colorTextBase = textBaseColor || "#fff";
72
+ const colorShadow = shadowColor || "rgba(255, 255, 255, 0.2)";
73
+ return {
74
+ colorBgBase,
75
+ colorTextBase,
76
+ colorShadow,
77
+ colorText: getAlphaColor(colorTextBase, 0.85),
78
+ colorTextSecondary: getAlphaColor(colorTextBase, 0.65),
79
+ colorTextTertiary: getAlphaColor(colorTextBase, 0.45),
80
+ colorTextQuaternary: getAlphaColor(colorTextBase, 0.25),
81
+ colorFill: getAlphaColor(colorTextBase, 0.18),
82
+ colorFillSecondary: getAlphaColor(colorTextBase, 0.12),
83
+ colorFillTertiary: getAlphaColor(colorTextBase, 0.08),
84
+ colorFillQuaternary: getAlphaColor(colorTextBase, 0.04),
85
+ colorBgSolid: getAlphaColor(colorTextBase, 0.95),
86
+ colorBgSolidHover: getAlphaColor(colorTextBase, 1),
87
+ colorBgSolidActive: getAlphaColor(colorTextBase, 0.9),
88
+ colorBgElevated: getSolidColorDark(colorBgBase, 12),
89
+ colorBgContainer: getSolidColorDark(colorBgBase, 8),
90
+ colorBgLayout: getSolidColorDark(colorBgBase, 0),
91
+ colorBgSpotlight: getSolidColorDark(colorBgBase, 26),
92
+ colorBgBlur: getAlphaColor(colorTextBase, 0.04),
93
+ colorBorder: getSolidColorDark(colorBgBase, 26),
94
+ colorBorderDisabled: getSolidColorDark(colorBgBase, 26),
95
+ colorBorderSecondary: getSolidColorDark(colorBgBase, 19)
96
+ };
97
+ };
98
+ function genPresetColorPalettes(seed, generateFn) {
99
+ const out = {};
100
+ for (const colorKey of Object.keys(defaultPresetColors)) {
101
+ const colors = generateFn(seed[colorKey]);
102
+ const [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10] = colors;
103
+ const ranked = [
104
+ [1, c1],
105
+ [2, c2],
106
+ [3, c3],
107
+ [4, c4],
108
+ [5, c5],
109
+ [6, c6],
110
+ [7, c7],
111
+ [8, c8],
112
+ [9, c9],
113
+ [10, c10]
114
+ ];
115
+ for (const [rank, color] of ranked) {
116
+ out[`${colorKey}-${rank}`] = color;
117
+ out[`${colorKey}${rank}`] = color;
118
+ }
119
+ }
120
+ return out;
121
+ }
122
+
123
+ export { genPresetColorPalettes, generateColorPalettes, generateColorPalettesDark, generateNeutralColorPalettes, generateNeutralColorPalettesDark, getAlphaColor, getSolidColor, getSolidColorDark };
package/dist/alias.mjs ADDED
@@ -0,0 +1,169 @@
1
+ import { Color } from '@apollo-design/utils';
2
+ import { defaultSeedToken } from './seed.mjs';
3
+ import getAlphaColor from './shared/get-alpha-color.mjs';
4
+
5
+ function formatToken(derivativeToken) {
6
+ const { override, ...restToken } = derivativeToken;
7
+ const overrideTokens = Object.fromEntries(
8
+ Object.entries(override ?? {}).filter(
9
+ ([key, value]) => value !== void 0 && !Object.hasOwn(defaultSeedToken, key)
10
+ )
11
+ );
12
+ const mergedToken = { ...restToken, ...overrideTokens };
13
+ const shadowBaseColor = new Color(mergedToken.colorShadow);
14
+ const shadowBaseAlpha = shadowBaseColor.a;
15
+ const getShadowColor = (alpha) => shadowBaseColor.clone().setAlpha(shadowBaseAlpha * alpha).toRgbString();
16
+ const screenXS = 480;
17
+ const screenSM = 576;
18
+ const screenMD = 768;
19
+ const screenLG = 992;
20
+ const screenXL = 1200;
21
+ const screenXXL = 1600;
22
+ const screenXXXL = 1920;
23
+ if (mergedToken.motion === false) {
24
+ const fastDuration = "0s";
25
+ mergedToken.motionDurationFast = fastDuration;
26
+ mergedToken.motionDurationMid = fastDuration;
27
+ mergedToken.motionDurationSlow = fastDuration;
28
+ }
29
+ const aliasToken = {
30
+ ...mergedToken,
31
+ // ============== 背景 ==============
32
+ colorFillContent: mergedToken.colorFillSecondary,
33
+ colorFillContentHover: mergedToken.colorFill,
34
+ colorFillAlter: mergedToken.colorFillQuaternary,
35
+ colorBgContainerDisabled: mergedToken.colorFillTertiary,
36
+ // ============== 分割线 ==============
37
+ colorBorderBg: mergedToken.colorBgContainer,
38
+ colorSplit: getAlphaColor(mergedToken.colorBorderSecondary, mergedToken.colorBgContainer),
39
+ // ============== 文本 ==============
40
+ colorTextPlaceholder: mergedToken.colorTextQuaternary,
41
+ colorTextDisabled: mergedToken.colorTextQuaternary,
42
+ colorTextHeading: mergedToken.colorText,
43
+ colorTextLabel: mergedToken.colorTextSecondary,
44
+ colorTextDescription: mergedToken.colorTextTertiary,
45
+ colorTextLightSolid: mergedToken.colorWhite,
46
+ colorHighlight: mergedToken.colorError,
47
+ colorBgTextHover: mergedToken.colorFillSecondary,
48
+ colorBgTextActive: mergedToken.colorFill,
49
+ colorIcon: mergedToken.colorTextTertiary,
50
+ colorIconHover: mergedToken.colorText,
51
+ colorErrorOutline: getAlphaColor(mergedToken.colorErrorBg, mergedToken.colorBgContainer),
52
+ colorWarningOutline: getAlphaColor(mergedToken.colorWarningBg, mergedToken.colorBgContainer),
53
+ colorErrorAffix: mergedToken.colorError,
54
+ colorWarningAffix: mergedToken.colorWarning,
55
+ // 字体
56
+ fontSizeIcon: mergedToken.fontSizeSM,
57
+ // 线
58
+ lineWidthFocus: mergedToken.focusOutline === false ? 0 : mergedToken.lineWidth * 3,
59
+ // 控件
60
+ controlOutlineWidth: mergedToken.lineWidth * 2,
61
+ controlInteractiveSize: mergedToken.controlHeight / 2,
62
+ controlItemBgHover: mergedToken.colorFillTertiary,
63
+ controlItemBgActive: mergedToken.colorPrimaryBg,
64
+ controlItemBgActiveHover: mergedToken.colorPrimaryBgHover,
65
+ controlItemBgActiveDisabled: mergedToken.colorFill,
66
+ controlTmpOutline: mergedToken.colorFillQuaternary,
67
+ controlOutline: getAlphaColor(mergedToken.colorPrimaryBg, mergedToken.colorBgContainer),
68
+ fontWeightStrong: 600,
69
+ opacityLoading: 0.65,
70
+ linkDecoration: "none",
71
+ linkHoverDecoration: "none",
72
+ linkFocusDecoration: "none",
73
+ controlPaddingHorizontal: 12,
74
+ controlPaddingHorizontalSM: 8,
75
+ // 间距(全部映射到 size 梯度)
76
+ paddingXXS: mergedToken.sizeXXS,
77
+ paddingXS: mergedToken.sizeXS,
78
+ paddingSM: mergedToken.sizeSM,
79
+ padding: mergedToken.size,
80
+ paddingMD: mergedToken.sizeMD,
81
+ paddingLG: mergedToken.sizeLG,
82
+ paddingXL: mergedToken.sizeXL,
83
+ paddingContentHorizontalLG: mergedToken.sizeLG,
84
+ paddingContentVerticalLG: mergedToken.sizeMS,
85
+ paddingContentHorizontal: mergedToken.sizeMS,
86
+ paddingContentVertical: mergedToken.sizeSM,
87
+ paddingContentHorizontalSM: mergedToken.size,
88
+ paddingContentVerticalSM: mergedToken.sizeXS,
89
+ marginXXS: mergedToken.sizeXXS,
90
+ marginXS: mergedToken.sizeXS,
91
+ marginSM: mergedToken.sizeSM,
92
+ margin: mergedToken.size,
93
+ marginMD: mergedToken.sizeMD,
94
+ marginLG: mergedToken.sizeLG,
95
+ marginXL: mergedToken.sizeXL,
96
+ marginXXL: mergedToken.sizeXXL,
97
+ boxShadow: `
98
+ 0 6px 16px 0 ${getShadowColor(0.08)},
99
+ 0 3px 6px -4px ${getShadowColor(0.12)},
100
+ 0 9px 28px 8px ${getShadowColor(0.05)}
101
+ `,
102
+ boxShadowSecondary: `
103
+ 0 6px 16px 0 ${getShadowColor(0.08)},
104
+ 0 3px 6px -4px ${getShadowColor(0.12)},
105
+ 0 9px 28px 8px ${getShadowColor(0.05)}
106
+ `,
107
+ boxShadowTertiary: `
108
+ 0 1px 2px 0 ${getShadowColor(0.05)},
109
+ 0 1px 6px -1px ${getShadowColor(0.03)},
110
+ 0 2px 4px 0 ${getShadowColor(0.03)}
111
+ `,
112
+ screenXS,
113
+ screenXSMin: screenXS,
114
+ screenXSMax: screenSM - 1,
115
+ screenSM,
116
+ screenSMMin: screenSM,
117
+ screenSMMax: screenMD - 1,
118
+ screenMD,
119
+ screenMDMin: screenMD,
120
+ screenMDMax: screenLG - 1,
121
+ screenLG,
122
+ screenLGMin: screenLG,
123
+ screenLGMax: screenXL - 1,
124
+ screenXL,
125
+ screenXLMin: screenXL,
126
+ screenXLMax: screenXXL - 1,
127
+ screenXXL,
128
+ screenXXLMin: screenXXL,
129
+ screenXXLMax: screenXXXL - 1,
130
+ screenXXXL,
131
+ screenXXXLMin: screenXXXL,
132
+ boxShadowPopoverArrow: `2px 2px 5px ${getShadowColor(0.05)}`,
133
+ dropShadowPopover: `drop-shadow(0 6px 16px ${getShadowColor(0.08)}) drop-shadow(0 3px 6px ${getShadowColor(0.12)}) drop-shadow(0 9px 28px ${getShadowColor(0.05)})`,
134
+ boxShadowCard: `
135
+ 0 1px 2px -2px ${getShadowColor(0.16)},
136
+ 0 3px 6px 0 ${getShadowColor(0.12)},
137
+ 0 5px 12px 4px ${getShadowColor(0.09)}
138
+ `,
139
+ boxShadowDrawerRight: `
140
+ -6px 0 16px 0 ${getShadowColor(0.08)},
141
+ -3px 0 6px -4px ${getShadowColor(0.12)},
142
+ -9px 0 28px 8px ${getShadowColor(0.05)}
143
+ `,
144
+ boxShadowDrawerLeft: `
145
+ 6px 0 16px 0 ${getShadowColor(0.08)},
146
+ 3px 0 6px -4px ${getShadowColor(0.12)},
147
+ 9px 0 28px 8px ${getShadowColor(0.05)}
148
+ `,
149
+ boxShadowDrawerUp: `
150
+ 0 6px 16px 0 ${getShadowColor(0.08)},
151
+ 0 3px 6px -4px ${getShadowColor(0.12)},
152
+ 0 9px 28px 8px ${getShadowColor(0.05)}
153
+ `,
154
+ boxShadowDrawerDown: `
155
+ 0 -6px 16px 0 ${getShadowColor(0.08)},
156
+ 0 -3px 6px -4px ${getShadowColor(0.12)},
157
+ 0 -9px 28px 8px ${getShadowColor(0.05)}
158
+ `,
159
+ boxShadowTabsOverflowLeft: `inset 10px 0 8px -8px ${getShadowColor(0.08)}`,
160
+ boxShadowTabsOverflowRight: `inset -10px 0 8px -8px ${getShadowColor(0.08)}`,
161
+ boxShadowTabsOverflowTop: `inset 0 10px 8px -8px ${getShadowColor(0.08)}`,
162
+ boxShadowTabsOverflowBottom: `inset 0 -10px 8px -8px ${getShadowColor(0.08)}`,
163
+ // 非 Seed 的 override 最后生效
164
+ ...overrideTokens
165
+ };
166
+ return aliasToken;
167
+ }
168
+
169
+ export { formatToken as default };
@@ -0,0 +1,153 @@
1
+ const DEFAULT_CSS_VAR_PREFIX = "apollo";
2
+ const UNITLESS = {
3
+ lineHeight: true,
4
+ lineHeightSM: true,
5
+ lineHeightLG: true,
6
+ lineHeightHeading1: true,
7
+ lineHeightHeading2: true,
8
+ lineHeightHeading3: true,
9
+ lineHeightHeading4: true,
10
+ lineHeightHeading5: true,
11
+ opacityLoading: true,
12
+ fontWeightStrong: true,
13
+ zIndexPopupBase: true,
14
+ zIndexBase: true,
15
+ opacityImage: true
16
+ };
17
+ const IGNORE = {
18
+ motionBase: true,
19
+ motionUnit: true
20
+ };
21
+ const PRESERVE = {
22
+ screenXS: true,
23
+ screenXSMin: true,
24
+ screenXSMax: true,
25
+ screenSM: true,
26
+ screenSMMin: true,
27
+ screenSMMax: true,
28
+ screenMD: true,
29
+ screenMDMin: true,
30
+ screenMDMax: true,
31
+ screenLG: true,
32
+ screenLGMin: true,
33
+ screenLGMax: true,
34
+ screenXL: true,
35
+ screenXLMin: true,
36
+ screenXLMax: true,
37
+ screenXXL: true,
38
+ screenXXLMin: true,
39
+ screenXXLMax: true,
40
+ screenXXXL: true,
41
+ screenXXXLMin: true
42
+ };
43
+ function token2CSSVar(token, prefix = DEFAULT_CSS_VAR_PREFIX) {
44
+ return `--${prefix ? `${prefix}-` : ""}${token}`.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, "$1-$2").replace(/([a-z])([A-Z0-9])/g, "$1-$2").toLowerCase();
45
+ }
46
+ function transformToken(token, prefix = DEFAULT_CSS_VAR_PREFIX) {
47
+ const vars = {};
48
+ const refs = [];
49
+ for (const [key, value] of Object.entries(token)) {
50
+ if (typeof value !== "string" && typeof value !== "number") continue;
51
+ if (Object.hasOwn(PRESERVE, key)) {
52
+ refs.push([key, value]);
53
+ continue;
54
+ }
55
+ if (!Object.hasOwn(IGNORE, key)) {
56
+ const cssVar = token2CSSVar(key, prefix);
57
+ vars[cssVar] = typeof value === "number" && !Object.hasOwn(UNITLESS, key) ? `${value}px` : String(value);
58
+ refs.push([key, `var(${cssVar})`]);
59
+ }
60
+ }
61
+ return { vars, refs: Object.fromEntries(refs) };
62
+ }
63
+ function getCSSVarDeclarations(token, options = {}) {
64
+ const { vars } = transformToken(token, options.prefix ?? DEFAULT_CSS_VAR_PREFIX);
65
+ const selector = options.selector ?? ":root";
66
+ const body = Object.entries(vars).map(([k, v]) => `${k}:${v};`).join("");
67
+ return `${selector}{${body}}`;
68
+ }
69
+ const ownedVariables = /* @__PURE__ */ new WeakMap();
70
+ function readInline(el, name) {
71
+ return { value: el.style.getPropertyValue(name), priority: el.style.getPropertyPriority(name) };
72
+ }
73
+ function sameInline(first, second) {
74
+ return first.value === second.value && first.priority === second.priority;
75
+ }
76
+ function writeInline(el, name, inline) {
77
+ if (inline.value) el.style.setProperty(name, inline.value, inline.priority);
78
+ else el.style.removeProperty(name);
79
+ }
80
+ function claimVariable(el, name, owner, value) {
81
+ let variables = ownedVariables.get(el);
82
+ if (!variables) {
83
+ variables = /* @__PURE__ */ new Map();
84
+ ownedVariables.set(el, variables);
85
+ }
86
+ const current = readInline(el, name);
87
+ let variable = variables.get(name);
88
+ if (!variable) {
89
+ variable = { base: current, lastWritten: current, visible: false, owners: /* @__PURE__ */ new Map() };
90
+ variables.set(name, variable);
91
+ } else if (!variable.visible || !sameInline(current, variable.lastWritten)) {
92
+ variable.base = current;
93
+ }
94
+ variable.owners.delete(owner);
95
+ variable.owners.set(owner, value);
96
+ writeInline(el, name, { value, priority: "" });
97
+ variable.lastWritten = readInline(el, name);
98
+ variable.visible = true;
99
+ }
100
+ function releaseVariable(el, name, owner) {
101
+ const variables = ownedVariables.get(el);
102
+ const variable = variables?.get(name);
103
+ if (!variables || !variable?.owners.delete(owner)) return;
104
+ const current = readInline(el, name);
105
+ if (variable.visible && sameInline(current, variable.lastWritten)) {
106
+ const previous = Array.from(variable.owners.values()).at(-1);
107
+ const next = previous === void 0 ? variable.base : { value: previous, priority: "" };
108
+ if (!sameInline(current, next)) writeInline(el, name, next);
109
+ variable.lastWritten = readInline(el, name);
110
+ variable.visible = variable.owners.size > 0;
111
+ } else {
112
+ variable.base = current;
113
+ variable.visible = false;
114
+ }
115
+ if (variable.owners.size === 0) variables.delete(name);
116
+ if (variables.size === 0) ownedVariables.delete(el);
117
+ }
118
+ function createCSSVarScope(el, prefix = DEFAULT_CSS_VAR_PREFIX) {
119
+ const owner = Symbol("css-variable-scope");
120
+ let written = [];
121
+ return {
122
+ apply(token) {
123
+ const { vars } = transformToken(token, prefix);
124
+ for (const name of written) {
125
+ if (!Object.hasOwn(vars, name)) releaseVariable(el, name, owner);
126
+ }
127
+ for (const [name, value] of Object.entries(vars)) {
128
+ claimVariable(el, name, owner, value);
129
+ }
130
+ written = Object.keys(vars);
131
+ },
132
+ remove() {
133
+ for (const name of written) releaseVariable(el, name, owner);
134
+ written = [];
135
+ },
136
+ get keys() {
137
+ return [...written];
138
+ }
139
+ };
140
+ }
141
+ function applyCSSVar(el, token, prefix = DEFAULT_CSS_VAR_PREFIX) {
142
+ for (const [name, value] of Object.entries(transformToken(token, prefix).vars)) {
143
+ el.style.setProperty(name, value);
144
+ const variable = ownedVariables.get(el)?.get(name);
145
+ if (variable) {
146
+ variable.base = readInline(el, name);
147
+ variable.lastWritten = variable.base;
148
+ variable.visible = false;
149
+ }
150
+ }
151
+ }
152
+
153
+ export { DEFAULT_CSS_VAR_PREFIX, IGNORE, PRESERVE, UNITLESS, applyCSSVar, createCSSVarScope, getCSSVarDeclarations, token2CSSVar, transformToken };