@stapel/tokens-antd 0.2.0 → 0.4.0
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.
- package/README.md +35 -24
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -20
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +66 -23
package/README.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
# @stapel/tokens-antd
|
|
2
2
|
|
|
3
|
-
The Ant Design leg of the **token bridge** (frontend-guidelines §2.4;
|
|
4
|
-
decision §38 T3). It projects `@stapel/tokens`
|
|
5
|
-
`ConfigProvider` theme — so integrating a
|
|
6
|
-
already carries the user's theme,
|
|
3
|
+
The Ant Design leg of the **token bridge** (§68; frontend-guidelines §2.4;
|
|
4
|
+
owner decision §38 T3). It projects `@stapel/tokens`' neutral colour roles
|
|
5
|
+
onto an Ant Design `ConfigProvider` theme — so integrating a
|
|
6
|
+
`@stapel/*-react` pair's default skin already carries the user's theme,
|
|
7
|
+
light and dark.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
|
|
9
|
+
The §68 neutral role dictionary IS the bridge vocabulary — a role name
|
|
10
|
+
(`brand`, `surface-raised`, `text-muted`, …) is both the CSS var suffix
|
|
11
|
+
(`--stapel-brand`) and the exact key this package reads off `@stapel/tokens`'
|
|
12
|
+
`colors` object. There is no separate role→role indirection table (the old
|
|
13
|
+
`bridgeColorRoles` map is gone) — this package only renames roles to antd's
|
|
14
|
+
flat token field names and picks the `light`/`dark` half; it holds no colour
|
|
15
|
+
decisions of its own, so it and `@stapel/tokens-mui` cannot drift.
|
|
13
16
|
|
|
14
17
|
## Usage
|
|
15
18
|
|
|
@@ -34,20 +37,28 @@ import { toAntdThemeConfig } from "@stapel/tokens-antd";
|
|
|
34
37
|
</ConfigProvider>;
|
|
35
38
|
```
|
|
36
39
|
|
|
37
|
-
## The mapping (frontend-guidelines §2.4)
|
|
38
|
-
|
|
39
|
-
| `@stapel/tokens` role |
|
|
40
|
-
| --- | --- |
|
|
41
|
-
| `brand` | `
|
|
42
|
-
| `success`
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
|
|
|
51
|
-
|
|
|
40
|
+
## The mapping (§68; frontend-guidelines §2.4)
|
|
41
|
+
|
|
42
|
+
| `@stapel/tokens` role | antd `theme.token` |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `brand` | `colorPrimary` |
|
|
45
|
+
| `success` / `warning` / `error` / `info` | `colorSuccess` / `colorWarning` / `colorError` / `colorInfo` |
|
|
46
|
+
| `text` | `colorText` |
|
|
47
|
+
| `text-muted` | `colorTextSecondary` |
|
|
48
|
+
| `text-subtle` | `colorTextTertiary` |
|
|
49
|
+
| `surface` | `colorBgLayout` |
|
|
50
|
+
| `surface-raised` | `colorBgContainer` |
|
|
51
|
+
| `surface-overlay` | `colorBgElevated` |
|
|
52
|
+
| `border` | `colorBorder` |
|
|
53
|
+
| `border-subtle` | `colorBorderSecondary` |
|
|
54
|
+
| `link` / `link-hover` | `colorLink` / `colorLinkHover` |
|
|
55
|
+
| radius `md` | `borderRadius` |
|
|
56
|
+
| font-size `md` | `fontSize` |
|
|
57
|
+
|
|
58
|
+
Every field above is resolved by reading the host's **live**
|
|
59
|
+
`--stapel-<role>` CSS custom property off `document.documentElement` at call
|
|
60
|
+
time (falling back to the compiled-in default only with no DOM — SSR/tests) —
|
|
61
|
+
so a host's customized brand colour flows through even to antd's seed-token
|
|
62
|
+
colour derivation (hover/active shades), not just its own light/dark mode.
|
|
52
63
|
|
|
53
64
|
`antd` is a peer dependency — the consuming app brings its own copy.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { ThemeConfig } from "antd";
|
|
2
|
-
/** Light or dark — the half of every
|
|
2
|
+
/** Light or dark — the half of every role's `{light,dark}` pair. */
|
|
3
3
|
export type ThemeMode = "light" | "dark";
|
|
4
4
|
/** The flat antd token map (`ThemeConfig["token"]`), never undefined. */
|
|
5
5
|
export type AntdThemeToken = NonNullable<ThemeConfig["token"]>;
|
|
6
6
|
/**
|
|
7
|
-
* `@stapel/tokens`
|
|
8
|
-
* Pure: same `mode` in, same object out; reads no globals
|
|
7
|
+
* `@stapel/tokens` §68 roles → antd `theme.token` (frontend-guidelines §2.4
|
|
8
|
+
* table). Pure: same `mode` in, same object out; reads no globals besides the
|
|
9
|
+
* live CSS custom properties documented on {@link readLiveCssVar}.
|
|
9
10
|
*/
|
|
10
11
|
export declare function toAntdTheme(mode: ThemeMode): AntdThemeToken;
|
|
11
12
|
/**
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAYxC,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AA6CzC,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;AAE/D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc,CAqB3D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,WAAW,CAM9D"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@stapel/tokens-antd` — the Ant Design leg of the token bridge
|
|
3
|
-
*
|
|
4
|
-
* neutral role
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* `@stapel/tokens-antd` — the Ant Design leg of the token bridge (§68;
|
|
3
|
+
* frontend-guidelines §2.4, owner decision §38 T3). It translates the ONE
|
|
4
|
+
* neutral colour-role dictionary in `@stapel/tokens` (§68 — `surface`,
|
|
5
|
+
* `brand`, `text-muted`, `success-bg`, …) straight into Ant Design's flat
|
|
6
|
+
* `ConfigProvider` theme token: a role name IS the antd mapping's input, no
|
|
7
|
+
* separate role→role indirection table (that table — `bridgeColorRoles` —
|
|
8
|
+
* is gone; §68 Ф1 "алиас-слой совместимости не делать"). The mapping table
|
|
9
|
+
* below (role → antd field) is the ONE place this decision lives; both this
|
|
10
|
+
* file and `@stapel/tokens-mui` read the same `colors` object so they cannot
|
|
11
|
+
* silently diverge on what a role visually means.
|
|
9
12
|
*
|
|
10
13
|
* ```tsx
|
|
11
14
|
* import { toAntdTheme } from "@stapel/tokens-antd";
|
|
@@ -21,31 +24,71 @@
|
|
|
21
24
|
* and spread it directly: `<ConfigProvider theme={toAntdThemeConfig(mode)}>`.
|
|
22
25
|
*/
|
|
23
26
|
import { theme as antdTheme } from "antd";
|
|
24
|
-
import {
|
|
25
|
-
/**
|
|
27
|
+
import { bridgeFontSizeRole, bridgeRadiusRole, colors, cssVar, fontFamily, fontSize, radii, } from "@stapel/tokens";
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a neutral colour role to a real hex for `mode` (owner audit
|
|
30
|
+
* 2026-07-17, §54 theme-bridge root cause): a host that customizes its OWN
|
|
31
|
+
* brand colour does so exactly as `@stapel/tokens`' README prescribes — copy
|
|
32
|
+
* `theme.default.json` to `stapel.theme.json`, edit the `ramps`, run
|
|
33
|
+
* `stapel-tokens` (`pnpm gen:tokens`) — which regenerates THAT HOST's
|
|
34
|
+
* `tokens.css` custom properties (`--stapel-<role>`). It does NOT and CANNOT
|
|
35
|
+
* change this published package's own compiled-in `colors` object — that
|
|
36
|
+
* snapshot is frozen at `@stapel/tokens`' OWN publish time to `@stapel/tokens`'
|
|
37
|
+
* OWN default theme, forever, regardless of what any host does. Feeding
|
|
38
|
+
* `colors` straight into antd's `ConfigProvider` (the previous implementation)
|
|
39
|
+
* is why every default skin rendered Stapel's stock brand colour instead of
|
|
40
|
+
* the host's, no matter how correctly the host had customized its tokens: the
|
|
41
|
+
* bridge was never wired to read them.
|
|
42
|
+
*
|
|
43
|
+
* The fix reads the LIVE `--stapel-<role>` custom property off
|
|
44
|
+
* `document.documentElement` at call time — the exact value the host's own
|
|
45
|
+
* (re)generated `tokens.css` sets, already resolved through whichever
|
|
46
|
+
* `data-theme` is active — and falls back to the static default only where
|
|
47
|
+
* there is no DOM to read (SSR, tests, a host that never loaded
|
|
48
|
+
* `tokens.css`). This is the one change that makes "the skin takes its theme
|
|
49
|
+
* from the bridge automatically" (the doc comment on every default skin)
|
|
50
|
+
* literally true for a host's brand colour, not just its light/dark mode.
|
|
51
|
+
*/
|
|
52
|
+
function readLiveCssVar(name, fallback) {
|
|
53
|
+
if (typeof document === "undefined")
|
|
54
|
+
return fallback;
|
|
55
|
+
// `getPropertyValue` wants the BARE custom-property name (`--stapel-x`);
|
|
56
|
+
// `cssVar()` deliberately returns the `var(--stapel-x)` wrapper for
|
|
57
|
+
// embedding in a CSS value, which `getPropertyValue` would never match —
|
|
58
|
+
// stripped back off here rather than duplicating the `--stapel-` prefix.
|
|
59
|
+
const propertyName = cssVar(name).slice("var(".length, -1);
|
|
60
|
+
const value = getComputedStyle(document.documentElement)
|
|
61
|
+
.getPropertyValue(propertyName)
|
|
62
|
+
.trim();
|
|
63
|
+
return value.length > 0 ? value : fallback;
|
|
64
|
+
}
|
|
65
|
+
/** Resolve a §68 colour role to its hex for `mode`, preferring the host's
|
|
66
|
+
* live CSS custom property over the compiled-in default. */
|
|
26
67
|
function role(name, mode) {
|
|
27
|
-
return colors[
|
|
68
|
+
return readLiveCssVar(name, colors[name][mode]);
|
|
28
69
|
}
|
|
29
70
|
/**
|
|
30
|
-
* `@stapel/tokens`
|
|
31
|
-
* Pure: same `mode` in, same object out; reads no globals
|
|
71
|
+
* `@stapel/tokens` §68 roles → antd `theme.token` (frontend-guidelines §2.4
|
|
72
|
+
* table). Pure: same `mode` in, same object out; reads no globals besides the
|
|
73
|
+
* live CSS custom properties documented on {@link readLiveCssVar}.
|
|
32
74
|
*/
|
|
33
75
|
export function toAntdTheme(mode) {
|
|
34
76
|
return {
|
|
35
77
|
colorPrimary: role("brand", mode),
|
|
36
78
|
colorLink: role("link", mode),
|
|
37
|
-
colorLinkHover: role("
|
|
79
|
+
colorLinkHover: role("link-hover", mode),
|
|
38
80
|
colorSuccess: role("success", mode),
|
|
39
81
|
colorWarning: role("warning", mode),
|
|
40
|
-
colorError: role("
|
|
82
|
+
colorError: role("error", mode),
|
|
41
83
|
colorInfo: role("info", mode),
|
|
42
|
-
colorText: role("
|
|
43
|
-
colorTextSecondary: role("
|
|
44
|
-
|
|
45
|
-
colorBgLayout: role("
|
|
46
|
-
|
|
84
|
+
colorText: role("text", mode),
|
|
85
|
+
colorTextSecondary: role("text-muted", mode),
|
|
86
|
+
colorTextTertiary: role("text-subtle", mode),
|
|
87
|
+
colorBgLayout: role("surface", mode),
|
|
88
|
+
colorBgContainer: role("surface-raised", mode),
|
|
89
|
+
colorBgElevated: role("surface-overlay", mode),
|
|
47
90
|
colorBorder: role("border", mode),
|
|
48
|
-
colorBorderSecondary: role("
|
|
91
|
+
colorBorderSecondary: role("border-subtle", mode),
|
|
49
92
|
borderRadius: radii[bridgeRadiusRole],
|
|
50
93
|
fontSize: fontSize[bridgeFontSizeRole].fontSize,
|
|
51
94
|
fontFamily: fontFamily.sans,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,MAAM,EACN,MAAM,EACN,UAAU,EACV,QAAQ,EACR,KAAK,GACN,MAAM,gBAAgB,CAAC;AAMxB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAS,cAAc,CAAC,IAAmB,EAAE,QAAgB;IAC3D,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,QAAQ,CAAC;IACrD,yEAAyE;IACzE,oEAAoE;IACpE,yEAAyE;IACzE,yEAAyE;IACzE,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC;SACrD,gBAAgB,CAAC,YAAY,CAAC;SAC9B,IAAI,EAAE,CAAC;IACV,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC7C,CAAC;AAED;4DAC4D;AAC5D,SAAS,IAAI,CAAC,IAAmB,EAAE,IAAe;IAChD,OAAO,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAKD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAe;IACzC,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC;QACjC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;QAC7B,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC;QACxC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;QACnC,YAAY,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;QACnC,UAAU,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC;QAC/B,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;QAC7B,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;QAC7B,kBAAkB,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC;QAC5C,iBAAiB,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC;QAC5C,aAAa,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;QACpC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC;QAC9C,eAAe,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC;QAC9C,WAAW,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC;QACjC,oBAAoB,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC;QACjD,YAAY,EAAE,KAAK,CAAC,gBAAgB,CAAC;QACrC,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC,QAAQ;QAC/C,UAAU,EAAE,UAAU,CAAC,IAAI;KAC5B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAe;IAC/C,OAAO;QACL,SAAS,EACP,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,gBAAgB;QACxE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC;KACzB,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stapel/tokens-antd",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Token bridge (frontend-guidelines §2.4, §38 T3): projects @stapel/tokens
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Token bridge (§68 neutral colour-role dictionary; frontend-guidelines §2.4, §38 T3): projects @stapel/tokens' roles (surface, brand, text-muted, success-bg, ...) onto an Ant Design ConfigProvider theme. `toAntdTheme(mode)` → theme.token; `toAntdThemeConfig(mode)` → the full ThemeConfig (algorithm + token). Pure functions reading the same `colors` object as @stapel/tokens-mui, so they cannot diverge. Not components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"antd": ">=5.20.0 <7"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@stapel/tokens": "^0.
|
|
38
|
+
"@stapel/tokens": "^0.5.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@size-limit/preset-small-lib": "^11.2.0",
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@stapel/tokens-antd` — the Ant Design leg of the token bridge
|
|
3
|
-
*
|
|
4
|
-
* neutral role
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* `@stapel/tokens-antd` — the Ant Design leg of the token bridge (§68;
|
|
3
|
+
* frontend-guidelines §2.4, owner decision §38 T3). It translates the ONE
|
|
4
|
+
* neutral colour-role dictionary in `@stapel/tokens` (§68 — `surface`,
|
|
5
|
+
* `brand`, `text-muted`, `success-bg`, …) straight into Ant Design's flat
|
|
6
|
+
* `ConfigProvider` theme token: a role name IS the antd mapping's input, no
|
|
7
|
+
* separate role→role indirection table (that table — `bridgeColorRoles` —
|
|
8
|
+
* is gone; §68 Ф1 "алиас-слой совместимости не делать"). The mapping table
|
|
9
|
+
* below (role → antd field) is the ONE place this decision lives; both this
|
|
10
|
+
* file and `@stapel/tokens-mui` read the same `colors` object so they cannot
|
|
11
|
+
* silently diverge on what a role visually means.
|
|
9
12
|
*
|
|
10
13
|
* ```tsx
|
|
11
14
|
* import { toAntdTheme } from "@stapel/tokens-antd";
|
|
@@ -23,47 +26,87 @@
|
|
|
23
26
|
import { theme as antdTheme } from "antd";
|
|
24
27
|
import type { ThemeConfig } from "antd";
|
|
25
28
|
import {
|
|
26
|
-
bridgeColorRoles,
|
|
27
29
|
bridgeFontSizeRole,
|
|
28
30
|
bridgeRadiusRole,
|
|
29
31
|
colors,
|
|
32
|
+
cssVar,
|
|
30
33
|
fontFamily,
|
|
31
34
|
fontSize,
|
|
32
35
|
radii,
|
|
33
36
|
} from "@stapel/tokens";
|
|
34
|
-
import type {
|
|
37
|
+
import type { CoreTokenName } from "@stapel/tokens";
|
|
35
38
|
|
|
36
|
-
/** Light or dark — the half of every
|
|
39
|
+
/** Light or dark — the half of every role's `{light,dark}` pair. */
|
|
37
40
|
export type ThemeMode = "light" | "dark";
|
|
38
41
|
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Resolve a neutral colour role to a real hex for `mode` (owner audit
|
|
44
|
+
* 2026-07-17, §54 theme-bridge root cause): a host that customizes its OWN
|
|
45
|
+
* brand colour does so exactly as `@stapel/tokens`' README prescribes — copy
|
|
46
|
+
* `theme.default.json` to `stapel.theme.json`, edit the `ramps`, run
|
|
47
|
+
* `stapel-tokens` (`pnpm gen:tokens`) — which regenerates THAT HOST's
|
|
48
|
+
* `tokens.css` custom properties (`--stapel-<role>`). It does NOT and CANNOT
|
|
49
|
+
* change this published package's own compiled-in `colors` object — that
|
|
50
|
+
* snapshot is frozen at `@stapel/tokens`' OWN publish time to `@stapel/tokens`'
|
|
51
|
+
* OWN default theme, forever, regardless of what any host does. Feeding
|
|
52
|
+
* `colors` straight into antd's `ConfigProvider` (the previous implementation)
|
|
53
|
+
* is why every default skin rendered Stapel's stock brand colour instead of
|
|
54
|
+
* the host's, no matter how correctly the host had customized its tokens: the
|
|
55
|
+
* bridge was never wired to read them.
|
|
56
|
+
*
|
|
57
|
+
* The fix reads the LIVE `--stapel-<role>` custom property off
|
|
58
|
+
* `document.documentElement` at call time — the exact value the host's own
|
|
59
|
+
* (re)generated `tokens.css` sets, already resolved through whichever
|
|
60
|
+
* `data-theme` is active — and falls back to the static default only where
|
|
61
|
+
* there is no DOM to read (SSR, tests, a host that never loaded
|
|
62
|
+
* `tokens.css`). This is the one change that makes "the skin takes its theme
|
|
63
|
+
* from the bridge automatically" (the doc comment on every default skin)
|
|
64
|
+
* literally true for a host's brand colour, not just its light/dark mode.
|
|
65
|
+
*/
|
|
66
|
+
function readLiveCssVar(name: CoreTokenName, fallback: string): string {
|
|
67
|
+
if (typeof document === "undefined") return fallback;
|
|
68
|
+
// `getPropertyValue` wants the BARE custom-property name (`--stapel-x`);
|
|
69
|
+
// `cssVar()` deliberately returns the `var(--stapel-x)` wrapper for
|
|
70
|
+
// embedding in a CSS value, which `getPropertyValue` would never match —
|
|
71
|
+
// stripped back off here rather than duplicating the `--stapel-` prefix.
|
|
72
|
+
const propertyName = cssVar(name).slice("var(".length, -1);
|
|
73
|
+
const value = getComputedStyle(document.documentElement)
|
|
74
|
+
.getPropertyValue(propertyName)
|
|
75
|
+
.trim();
|
|
76
|
+
return value.length > 0 ? value : fallback;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Resolve a §68 colour role to its hex for `mode`, preferring the host's
|
|
80
|
+
* live CSS custom property over the compiled-in default. */
|
|
81
|
+
function role(name: CoreTokenName, mode: ThemeMode): string {
|
|
82
|
+
return readLiveCssVar(name, colors[name][mode]);
|
|
42
83
|
}
|
|
43
84
|
|
|
44
85
|
/** The flat antd token map (`ThemeConfig["token"]`), never undefined. */
|
|
45
86
|
export type AntdThemeToken = NonNullable<ThemeConfig["token"]>;
|
|
46
87
|
|
|
47
88
|
/**
|
|
48
|
-
* `@stapel/tokens`
|
|
49
|
-
* Pure: same `mode` in, same object out; reads no globals
|
|
89
|
+
* `@stapel/tokens` §68 roles → antd `theme.token` (frontend-guidelines §2.4
|
|
90
|
+
* table). Pure: same `mode` in, same object out; reads no globals besides the
|
|
91
|
+
* live CSS custom properties documented on {@link readLiveCssVar}.
|
|
50
92
|
*/
|
|
51
93
|
export function toAntdTheme(mode: ThemeMode): AntdThemeToken {
|
|
52
94
|
return {
|
|
53
95
|
colorPrimary: role("brand", mode),
|
|
54
96
|
colorLink: role("link", mode),
|
|
55
|
-
colorLinkHover: role("
|
|
97
|
+
colorLinkHover: role("link-hover", mode),
|
|
56
98
|
colorSuccess: role("success", mode),
|
|
57
99
|
colorWarning: role("warning", mode),
|
|
58
|
-
colorError: role("
|
|
100
|
+
colorError: role("error", mode),
|
|
59
101
|
colorInfo: role("info", mode),
|
|
60
|
-
colorText: role("
|
|
61
|
-
colorTextSecondary: role("
|
|
62
|
-
|
|
63
|
-
colorBgLayout: role("
|
|
64
|
-
|
|
102
|
+
colorText: role("text", mode),
|
|
103
|
+
colorTextSecondary: role("text-muted", mode),
|
|
104
|
+
colorTextTertiary: role("text-subtle", mode),
|
|
105
|
+
colorBgLayout: role("surface", mode),
|
|
106
|
+
colorBgContainer: role("surface-raised", mode),
|
|
107
|
+
colorBgElevated: role("surface-overlay", mode),
|
|
65
108
|
colorBorder: role("border", mode),
|
|
66
|
-
colorBorderSecondary: role("
|
|
109
|
+
colorBorderSecondary: role("border-subtle", mode),
|
|
67
110
|
borderRadius: radii[bridgeRadiusRole],
|
|
68
111
|
fontSize: fontSize[bridgeFontSizeRole].fontSize,
|
|
69
112
|
fontFamily: fontFamily.sans,
|