@oxyhq/bloom 0.84.0 → 0.86.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/lib/commonjs/design-tokens/index.js +14 -0
- package/lib/commonjs/design-tokens/index.js.map +1 -1
- package/lib/commonjs/theme/color-scope/seed-scope.js +49 -16
- package/lib/commonjs/theme/color-scope/seed-scope.js.map +1 -1
- package/lib/commonjs/theme/color-scope/style-builder.js +2 -17
- package/lib/commonjs/theme/color-scope/style-builder.js.map +1 -1
- package/lib/module/design-tokens/index.js +19 -0
- package/lib/module/design-tokens/index.js.map +1 -1
- package/lib/module/theme/color-scope/seed-scope.js +48 -16
- package/lib/module/theme/color-scope/seed-scope.js.map +1 -1
- package/lib/module/theme/color-scope/style-builder.js +3 -18
- package/lib/module/theme/color-scope/style-builder.js.map +1 -1
- package/lib/typescript/commonjs/design-tokens/index.d.ts +6 -0
- package/lib/typescript/commonjs/design-tokens/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/seed-scope.d.ts +9 -0
- package/lib/typescript/commonjs/theme/color-scope/seed-scope.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-scope/style-builder.d.ts.map +1 -1
- package/lib/typescript/module/design-tokens/index.d.ts +6 -0
- package/lib/typescript/module/design-tokens/index.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/seed-scope.d.ts +9 -0
- package/lib/typescript/module/theme/color-scope/seed-scope.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-scope/style-builder.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/design-tokens.test.ts +153 -2
- package/src/design-tokens/index.ts +21 -0
- package/src/theme/color-scope/seed-scope.ts +48 -16
- package/src/theme/color-scope/style-builder.ts +3 -18
|
@@ -81,8 +81,22 @@ Object.defineProperty(exports, "bloomThemeCss", {
|
|
|
81
81
|
return _themeCss.bloomThemeCss;
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
|
+
Object.defineProperty(exports, "buildSeedScopeVars", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _seedScope.buildSeedScopeVars;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, "getPresetVars", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _presetVars.getPresetVars;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
84
96
|
var _tailwindPreset = require("./tailwind-preset.js");
|
|
85
97
|
var _themeCss = require("./theme-css.js");
|
|
98
|
+
var _presetVars = require("../theme/preset-vars.js");
|
|
99
|
+
var _seedScope = require("../theme/color-scope/seed-scope.js");
|
|
86
100
|
var _colorRoles = require("./color-roles.js");
|
|
87
101
|
var _scales = require("./scales.js");
|
|
88
102
|
var _shadows = require("./shadows");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_tailwindPreset","require","_themeCss","_colorRoles","_scales","_shadows"],"sourceRoot":"../../../src","sources":["design-tokens/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_tailwindPreset","require","_themeCss","_presetVars","_seedScope","_colorRoles","_scales","_shadows"],"sourceRoot":"../../../src","sources":["design-tokens/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,IAAAA,eAAA,GAAAC,OAAA;AAMA,IAAAC,SAAA,GAAAD,OAAA;AAgBA,IAAAE,WAAA,GAAAF,OAAA;AAEA,IAAAG,UAAA,GAAAH,OAAA;AAGA,IAAAI,WAAA,GAAAJ,OAAA;AAOA,IAAAK,OAAA,GAAAL,OAAA;AASA,IAAAM,QAAA,GAAAN,OAAA","ignoreList":[]}
|
|
@@ -5,9 +5,56 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.buildSeedScopeVars = buildSeedScopeVars;
|
|
7
7
|
exports.roleColorsToPresetTokens = roleColorsToPresetTokens;
|
|
8
|
+
exports.withScopeAliases = withScopeAliases;
|
|
8
9
|
var _index = require("../color-engine/index.js");
|
|
9
10
|
var _colorPolicy = require("../color-policy.js");
|
|
10
|
-
var
|
|
11
|
+
var _colorRoles = require("../../design-tokens/color-roles.js");
|
|
12
|
+
/**
|
|
13
|
+
* Every alias `theme.css` declares at `:root` as a reference to a canonical
|
|
14
|
+
* token, keyed by the alias name. `--color-divider` is one of these and does not
|
|
15
|
+
* come from the role maps, so it is named here.
|
|
16
|
+
*
|
|
17
|
+
* An alias declared at the document root substitutes THERE, so a subtree that
|
|
18
|
+
* overrides `--foreground` cannot move a `--color-text: var(--foreground)` the
|
|
19
|
+
* root already computed — the subtree keeps painting the app-wide palette while
|
|
20
|
+
* every canonical token around it says otherwise. Re-declaring each alias inside
|
|
21
|
+
* the scope, against the scope's own values, is what closes that.
|
|
22
|
+
*
|
|
23
|
+
* An alias whose value is a literal (`--color-destructive-foreground: #ffffff`)
|
|
24
|
+
* is unaffected and deliberately absent.
|
|
25
|
+
*/
|
|
26
|
+
const SCOPED_ALIASES = {
|
|
27
|
+
..._colorRoles.FILL_ROLES,
|
|
28
|
+
..._colorRoles.TEXT_ROLES,
|
|
29
|
+
..._colorRoles.BORDER_ROLES,
|
|
30
|
+
divider: 'var(--border)'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Give a resolved token map the `--color-x` alias layer, so utilities resolve
|
|
35
|
+
* against the scope instead of the document root.
|
|
36
|
+
*
|
|
37
|
+
* Shared by both scope builders — the preset path (`buildScopeVars`) and the
|
|
38
|
+
* seed path (`buildSeedScopeVars`) — because a gap here is invisible until a
|
|
39
|
+
* scoped page paints the wrong colour in one mode only.
|
|
40
|
+
*/
|
|
41
|
+
function withScopeAliases(tokens) {
|
|
42
|
+
const vars = {
|
|
43
|
+
...tokens
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Policy tokens live outside the canonical set, so alias every token present.
|
|
47
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
48
|
+
vars[`--color-${key.slice(2)}`] = value;
|
|
49
|
+
}
|
|
50
|
+
for (const [alias, reference] of Object.entries(SCOPED_ALIASES)) {
|
|
51
|
+
const canonical = /^var\(--(.+)\)$/.exec(reference)?.[1];
|
|
52
|
+
const resolved = canonical === undefined ? undefined : tokens[`--${canonical}`];
|
|
53
|
+
if (resolved !== undefined) vars[`--color-${alias}`] = resolved;
|
|
54
|
+
}
|
|
55
|
+
return vars;
|
|
56
|
+
}
|
|
57
|
+
|
|
11
58
|
/**
|
|
12
59
|
* The canonical role → token assignment, sourced from an arbitrary seed's role
|
|
13
60
|
* set instead of a named preset.
|
|
@@ -101,20 +148,6 @@ function buildSeedScopeVars(options) {
|
|
|
101
148
|
tertiary: options.tertiarySeed
|
|
102
149
|
})
|
|
103
150
|
};
|
|
104
|
-
|
|
105
|
-
...tokens
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Policy tokens live outside CANONICAL_TOKENS, so alias every token present.
|
|
109
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
110
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
111
|
-
}
|
|
112
|
-
for (const token of _tokenRegistry.CANONICAL_TOKENS) {
|
|
113
|
-
const value = tokens[`--${token}`];
|
|
114
|
-
if (value !== undefined) {
|
|
115
|
-
vars[`--color-${token}`] = value;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return vars;
|
|
151
|
+
return withScopeAliases(tokens);
|
|
119
152
|
}
|
|
120
153
|
//# sourceMappingURL=seed-scope.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_index","require","_colorPolicy","
|
|
1
|
+
{"version":3,"names":["_index","require","_colorPolicy","_colorRoles","SCOPED_ALIASES","FILL_ROLES","TEXT_ROLES","BORDER_ROLES","divider","withScopeAliases","tokens","vars","key","value","Object","entries","slice","alias","reference","canonical","exec","resolved","undefined","roleColorsToPresetTokens","r","background","onBackground","surfaceContainerLow","onSurface","surfaceContainer","primary","onPrimary","secondaryContainer","onSecondaryContainer","tertiaryContainer","onTertiaryContainer","surfaceContainerHigh","onSurfaceVariant","error","outlineVariant","surfaceContainerLowest","secondary","tertiary","primaryContainer","buildSeedScopeVars","options","roles","generateRoleColors","seed","variant","isColourlessSeed","isDark","mode","contrastLevel","secondarySeed","tertiarySeed","buildPolicyTokens"],"sourceRoot":"../../../../src","sources":["theme/color-scope/seed-scope.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,6 +8,7 @@ exports.buildScopeVars = buildScopeVars;
|
|
|
8
8
|
exports.getVariableContextProvider = getVariableContextProvider;
|
|
9
9
|
var _reactNative = require("react-native");
|
|
10
10
|
var _tokenRegistry = require("../token-registry.js");
|
|
11
|
+
var _seedScope = require("./seed-scope.js");
|
|
11
12
|
/**
|
|
12
13
|
* The optional-peer boundary for `nativewind`.
|
|
13
14
|
*
|
|
@@ -120,23 +121,7 @@ function warnScopeInert(detail) {
|
|
|
120
121
|
* the document root and would otherwise keep pointing at the app-wide preset.
|
|
121
122
|
*/
|
|
122
123
|
function buildScopeVars(colorPreset, mode, accents) {
|
|
123
|
-
|
|
124
|
-
const vars = {
|
|
125
|
-
...tokens
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// Policy tokens live outside CANONICAL_TOKENS, so give every token present a
|
|
129
|
-
// `--color-*` alias; NativeWind resolves its utilities through those.
|
|
130
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
131
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
132
|
-
}
|
|
133
|
-
for (const token of _tokenRegistry.CANONICAL_TOKENS) {
|
|
134
|
-
const value = tokens[`--${token}`];
|
|
135
|
-
if (value !== undefined) {
|
|
136
|
-
vars[`--color-${token}`] = value;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return vars;
|
|
124
|
+
return (0, _seedScope.withScopeAliases)((0, _tokenRegistry.getResolvedTokens)(colorPreset, mode, accents));
|
|
140
125
|
}
|
|
141
126
|
|
|
142
127
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_tokenRegistry","nativeWindModule","unavailableReason","hasWarned","loadNativeWindVars","undefined","loaded","vars","error","Error","message","String","warnScopeInert","detail","process","env","NODE_ENV","console","warn","buildScopeVars","colorPreset","mode","accents","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_tokenRegistry","_seedScope","nativeWindModule","unavailableReason","hasWarned","loadNativeWindVars","undefined","loaded","vars","error","Error","message","String","warnScopeInert","detail","process","env","NODE_ENV","console","warn","buildScopeVars","colorPreset","mode","accents","withScopeAliases","getResolvedTokens","getVariableContextProvider","Platform","OS","module","VariableContextProvider","buildNativePresetStyle"],"sourceRoot":"../../../../src","sources":["theme/color-scope/style-builder.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* `p-space-8`, `rounded-radius-20`, `text-body`, `font-body`, `shadow-s`).
|
|
11
11
|
* - `bloomThemeCss` / `bloomThemeBlock` — the Tailwind v4 `@theme` equivalent
|
|
12
12
|
* for CSS-configured web apps.
|
|
13
|
+
* - `getPresetVars` / `buildSeedScopeVars` — the resolved token VALUES behind
|
|
14
|
+
* that alias layer, for a named preset or an arbitrary brand seed.
|
|
13
15
|
* - The raw token maps (`FILL_ROLES`, `TEXT_ROLES`, `BORDER_ROLES`, `SPACING`,
|
|
14
16
|
* `RADIUS`, `TYPOGRAPHY`, `SHADOW_BOX`) for direct programmatic use.
|
|
15
17
|
* - `bloomShadowStyle` — platform-correct shadow style object (web box-shadow /
|
|
@@ -21,6 +23,23 @@
|
|
|
21
23
|
|
|
22
24
|
export { bloomTailwindPreset } from "./tailwind-preset.js";
|
|
23
25
|
export { bloomThemeCss, bloomThemeBlock } from "./theme-css.js";
|
|
26
|
+
|
|
27
|
+
/* The resolved counterpart of `bloomThemeCss()`. That emits the alias layer
|
|
28
|
+
* (`--color-x: var(--x)`); these resolve `--x` itself, so a build script can
|
|
29
|
+
* write a static `:root` / `.dark` block and a prerendered page paints the real
|
|
30
|
+
* theme before `BloomThemeProvider` runs — instead of a hand-written palette
|
|
31
|
+
* that drifts from the preset it claims to mirror.
|
|
32
|
+
*
|
|
33
|
+
* `getPresetVars` returns the canonical tokens alone, which is all a document
|
|
34
|
+
* root needs. `buildSeedScopeVars` also returns the `--color-x` aliases, which a
|
|
35
|
+
* SCOPED block (a brand section, a forced-dark region) does need: a `--color-x`
|
|
36
|
+
* alias substitutes where it is declared, so overriding `--x` on a subtree does
|
|
37
|
+
* not move an alias declared at `:root`.
|
|
38
|
+
*
|
|
39
|
+
* Both are pure — no React, no react-native — so they run in a plain node/bun
|
|
40
|
+
* build script as well as in an app. */
|
|
41
|
+
export { getPresetVars } from "../theme/preset-vars.js";
|
|
42
|
+
export { buildSeedScopeVars } from "../theme/color-scope/seed-scope.js";
|
|
24
43
|
export { FILL_ROLES, TEXT_ROLES, BORDER_ROLES } from "./color-roles.js";
|
|
25
44
|
export { SPACING, RADIUS, BORDER_WIDTH, TYPOGRAPHY, FONT_FAMILY_VARS } from "./scales.js";
|
|
26
45
|
export { SHADOW_BOX, bloomShadowStyle } from './shadows';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["bloomTailwindPreset","bloomThemeCss","bloomThemeBlock","FILL_ROLES","TEXT_ROLES","BORDER_ROLES","SPACING","RADIUS","BORDER_WIDTH","TYPOGRAPHY","FONT_FAMILY_VARS","SHADOW_BOX","bloomShadowStyle"],"sourceRoot":"../../../src","sources":["design-tokens/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,mBAAmB,QAAQ,sBAAmB;AAMvD,SAASC,aAAa,EAAEC,eAAe,QAAQ,gBAAa;
|
|
1
|
+
{"version":3,"names":["bloomTailwindPreset","bloomThemeCss","bloomThemeBlock","getPresetVars","buildSeedScopeVars","FILL_ROLES","TEXT_ROLES","BORDER_ROLES","SPACING","RADIUS","BORDER_WIDTH","TYPOGRAPHY","FONT_FAMILY_VARS","SHADOW_BOX","bloomShadowStyle"],"sourceRoot":"../../../src","sources":["design-tokens/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,mBAAmB,QAAQ,sBAAmB;AAMvD,SAASC,aAAa,EAAEC,eAAe,QAAQ,gBAAa;;AAE5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,aAAa,QAAQ,yBAAsB;AAEpD,SAASC,kBAAkB,QAAQ,oCAAiC;AAGpE,SACEC,UAAU,EACVC,UAAU,EACVC,YAAY,QACP,kBAAe;AAGtB,SACEC,OAAO,EACPC,MAAM,EACNC,YAAY,EACZC,UAAU,EACVC,gBAAgB,QACX,aAAU;AAGjB,SAASC,UAAU,EAAEC,gBAAgB,QAAQ,WAAW","ignoreList":[]}
|
|
@@ -2,7 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
import { generateRoleColors } from "../color-engine/index.js";
|
|
4
4
|
import { buildPolicyTokens, isColourlessSeed } from "../color-policy.js";
|
|
5
|
-
import {
|
|
5
|
+
import { BORDER_ROLES, FILL_ROLES, TEXT_ROLES } from "../../design-tokens/color-roles.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Every alias `theme.css` declares at `:root` as a reference to a canonical
|
|
9
|
+
* token, keyed by the alias name. `--color-divider` is one of these and does not
|
|
10
|
+
* come from the role maps, so it is named here.
|
|
11
|
+
*
|
|
12
|
+
* An alias declared at the document root substitutes THERE, so a subtree that
|
|
13
|
+
* overrides `--foreground` cannot move a `--color-text: var(--foreground)` the
|
|
14
|
+
* root already computed — the subtree keeps painting the app-wide palette while
|
|
15
|
+
* every canonical token around it says otherwise. Re-declaring each alias inside
|
|
16
|
+
* the scope, against the scope's own values, is what closes that.
|
|
17
|
+
*
|
|
18
|
+
* An alias whose value is a literal (`--color-destructive-foreground: #ffffff`)
|
|
19
|
+
* is unaffected and deliberately absent.
|
|
20
|
+
*/
|
|
21
|
+
const SCOPED_ALIASES = {
|
|
22
|
+
...FILL_ROLES,
|
|
23
|
+
...TEXT_ROLES,
|
|
24
|
+
...BORDER_ROLES,
|
|
25
|
+
divider: 'var(--border)'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Give a resolved token map the `--color-x` alias layer, so utilities resolve
|
|
30
|
+
* against the scope instead of the document root.
|
|
31
|
+
*
|
|
32
|
+
* Shared by both scope builders — the preset path (`buildScopeVars`) and the
|
|
33
|
+
* seed path (`buildSeedScopeVars`) — because a gap here is invisible until a
|
|
34
|
+
* scoped page paints the wrong colour in one mode only.
|
|
35
|
+
*/
|
|
36
|
+
export function withScopeAliases(tokens) {
|
|
37
|
+
const vars = {
|
|
38
|
+
...tokens
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Policy tokens live outside the canonical set, so alias every token present.
|
|
42
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
43
|
+
vars[`--color-${key.slice(2)}`] = value;
|
|
44
|
+
}
|
|
45
|
+
for (const [alias, reference] of Object.entries(SCOPED_ALIASES)) {
|
|
46
|
+
const canonical = /^var\(--(.+)\)$/.exec(reference)?.[1];
|
|
47
|
+
const resolved = canonical === undefined ? undefined : tokens[`--${canonical}`];
|
|
48
|
+
if (resolved !== undefined) vars[`--color-${alias}`] = resolved;
|
|
49
|
+
}
|
|
50
|
+
return vars;
|
|
51
|
+
}
|
|
6
52
|
|
|
7
53
|
/**
|
|
8
54
|
* The canonical role → token assignment, sourced from an arbitrary seed's role
|
|
@@ -97,20 +143,6 @@ export function buildSeedScopeVars(options) {
|
|
|
97
143
|
tertiary: options.tertiarySeed
|
|
98
144
|
})
|
|
99
145
|
};
|
|
100
|
-
|
|
101
|
-
...tokens
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Policy tokens live outside CANONICAL_TOKENS, so alias every token present.
|
|
105
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
106
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
107
|
-
}
|
|
108
|
-
for (const token of CANONICAL_TOKENS) {
|
|
109
|
-
const value = tokens[`--${token}`];
|
|
110
|
-
if (value !== undefined) {
|
|
111
|
-
vars[`--color-${token}`] = value;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return vars;
|
|
146
|
+
return withScopeAliases(tokens);
|
|
115
147
|
}
|
|
116
148
|
//# sourceMappingURL=seed-scope.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["generateRoleColors","buildPolicyTokens","isColourlessSeed","
|
|
1
|
+
{"version":3,"names":["generateRoleColors","buildPolicyTokens","isColourlessSeed","BORDER_ROLES","FILL_ROLES","TEXT_ROLES","SCOPED_ALIASES","divider","withScopeAliases","tokens","vars","key","value","Object","entries","slice","alias","reference","canonical","exec","resolved","undefined","roleColorsToPresetTokens","r","background","onBackground","surfaceContainerLow","onSurface","surfaceContainer","primary","onPrimary","secondaryContainer","onSecondaryContainer","tertiaryContainer","onTertiaryContainer","surfaceContainerHigh","onSurfaceVariant","error","outlineVariant","surfaceContainerLowest","secondary","tertiary","primaryContainer","buildSeedScopeVars","options","roles","seed","variant","isDark","mode","contrastLevel","secondarySeed","tertiarySeed"],"sourceRoot":"../../../../src","sources":["theme/color-scope/seed-scope.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { Platform } from 'react-native';
|
|
4
|
-
import {
|
|
4
|
+
import { getResolvedTokens } from "../token-registry.js";
|
|
5
|
+
import { withScopeAliases } from "./seed-scope.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* The optional-peer boundary for `nativewind`.
|
|
@@ -115,23 +116,7 @@ function warnScopeInert(detail) {
|
|
|
115
116
|
* the document root and would otherwise keep pointing at the app-wide preset.
|
|
116
117
|
*/
|
|
117
118
|
export function buildScopeVars(colorPreset, mode, accents) {
|
|
118
|
-
|
|
119
|
-
const vars = {
|
|
120
|
-
...tokens
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// Policy tokens live outside CANONICAL_TOKENS, so give every token present a
|
|
124
|
-
// `--color-*` alias; NativeWind resolves its utilities through those.
|
|
125
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
126
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
127
|
-
}
|
|
128
|
-
for (const token of CANONICAL_TOKENS) {
|
|
129
|
-
const value = tokens[`--${token}`];
|
|
130
|
-
if (value !== undefined) {
|
|
131
|
-
vars[`--color-${token}`] = value;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return vars;
|
|
119
|
+
return withScopeAliases(getResolvedTokens(colorPreset, mode, accents));
|
|
135
120
|
}
|
|
136
121
|
|
|
137
122
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","
|
|
1
|
+
{"version":3,"names":["Platform","getResolvedTokens","withScopeAliases","nativeWindModule","unavailableReason","hasWarned","loadNativeWindVars","undefined","require","loaded","vars","error","Error","message","String","warnScopeInert","detail","process","env","NODE_ENV","console","warn","buildScopeVars","colorPreset","mode","accents","getVariableContextProvider","OS","module","VariableContextProvider","buildNativePresetStyle"],"sourceRoot":"../../../../src","sources":["theme/color-scope/style-builder.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* `p-space-8`, `rounded-radius-20`, `text-body`, `font-body`, `shadow-s`).
|
|
9
9
|
* - `bloomThemeCss` / `bloomThemeBlock` — the Tailwind v4 `@theme` equivalent
|
|
10
10
|
* for CSS-configured web apps.
|
|
11
|
+
* - `getPresetVars` / `buildSeedScopeVars` — the resolved token VALUES behind
|
|
12
|
+
* that alias layer, for a named preset or an arbitrary brand seed.
|
|
11
13
|
* - The raw token maps (`FILL_ROLES`, `TEXT_ROLES`, `BORDER_ROLES`, `SPACING`,
|
|
12
14
|
* `RADIUS`, `TYPOGRAPHY`, `SHADOW_BOX`) for direct programmatic use.
|
|
13
15
|
* - `bloomShadowStyle` — platform-correct shadow style object (web box-shadow /
|
|
@@ -19,6 +21,10 @@
|
|
|
19
21
|
export { bloomTailwindPreset } from './tailwind-preset';
|
|
20
22
|
export type { TailwindPreset, TailwindPresetThemeExtend, } from './tailwind-preset';
|
|
21
23
|
export { bloomThemeCss, bloomThemeBlock } from './theme-css';
|
|
24
|
+
export { getPresetVars } from '../theme/preset-vars';
|
|
25
|
+
export type { ExplicitAccents } from '../theme/preset-vars';
|
|
26
|
+
export { buildSeedScopeVars } from '../theme/color-scope/seed-scope';
|
|
27
|
+
export type { SeedScopeOptions } from '../theme/color-scope/seed-scope';
|
|
22
28
|
export { FILL_ROLES, TEXT_ROLES, BORDER_ROLES, } from './color-roles';
|
|
23
29
|
export type { FillRole, TextRole, BorderRole } from './color-roles';
|
|
24
30
|
export { SPACING, RADIUS, BORDER_WIDTH, TYPOGRAPHY, FONT_FAMILY_VARS, } from './scales';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/design-tokens/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/design-tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EACV,cAAc,EACd,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgB7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EACL,OAAO,EACP,MAAM,EACN,YAAY,EACZ,UAAU,EACV,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { type RoleColors, type SchemeVariant } from '../color-engine';
|
|
2
|
+
/**
|
|
3
|
+
* Give a resolved token map the `--color-x` alias layer, so utilities resolve
|
|
4
|
+
* against the scope instead of the document root.
|
|
5
|
+
*
|
|
6
|
+
* Shared by both scope builders — the preset path (`buildScopeVars`) and the
|
|
7
|
+
* seed path (`buildSeedScopeVars`) — because a gap here is invisible until a
|
|
8
|
+
* scoped page paints the wrong colour in one mode only.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withScopeAliases(tokens: Record<string, string>): Record<string, string>;
|
|
2
11
|
/**
|
|
3
12
|
* The canonical role → token assignment, sourced from an arbitrary seed's role
|
|
4
13
|
* set instead of a named preset.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-scope.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/seed-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"seed-scope.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/seed-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAyB1F;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAevF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4C9E;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBpF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-builder.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/style-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"style-builder.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/style-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA8CtD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG,KAAK,CAAC,aAAa,CAAC;IACjE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC,CAAC;AAkEH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,YAAY,EACzB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,eAAe,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,IAAI,gCAAgC,GAAG,IAAI,CAepF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,YAAY,EACzB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,SAAS,CAAC,SAAS,CAAC,CAQtB"}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* `p-space-8`, `rounded-radius-20`, `text-body`, `font-body`, `shadow-s`).
|
|
9
9
|
* - `bloomThemeCss` / `bloomThemeBlock` — the Tailwind v4 `@theme` equivalent
|
|
10
10
|
* for CSS-configured web apps.
|
|
11
|
+
* - `getPresetVars` / `buildSeedScopeVars` — the resolved token VALUES behind
|
|
12
|
+
* that alias layer, for a named preset or an arbitrary brand seed.
|
|
11
13
|
* - The raw token maps (`FILL_ROLES`, `TEXT_ROLES`, `BORDER_ROLES`, `SPACING`,
|
|
12
14
|
* `RADIUS`, `TYPOGRAPHY`, `SHADOW_BOX`) for direct programmatic use.
|
|
13
15
|
* - `bloomShadowStyle` — platform-correct shadow style object (web box-shadow /
|
|
@@ -19,6 +21,10 @@
|
|
|
19
21
|
export { bloomTailwindPreset } from './tailwind-preset';
|
|
20
22
|
export type { TailwindPreset, TailwindPresetThemeExtend, } from './tailwind-preset';
|
|
21
23
|
export { bloomThemeCss, bloomThemeBlock } from './theme-css';
|
|
24
|
+
export { getPresetVars } from '../theme/preset-vars';
|
|
25
|
+
export type { ExplicitAccents } from '../theme/preset-vars';
|
|
26
|
+
export { buildSeedScopeVars } from '../theme/color-scope/seed-scope';
|
|
27
|
+
export type { SeedScopeOptions } from '../theme/color-scope/seed-scope';
|
|
22
28
|
export { FILL_ROLES, TEXT_ROLES, BORDER_ROLES, } from './color-roles';
|
|
23
29
|
export type { FillRole, TextRole, BorderRole } from './color-roles';
|
|
24
30
|
export { SPACING, RADIUS, BORDER_WIDTH, TYPOGRAPHY, FONT_FAMILY_VARS, } from './scales';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/design-tokens/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/design-tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EACV,cAAc,EACd,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAgB7D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEpE,OAAO,EACL,OAAO,EACP,MAAM,EACN,YAAY,EACZ,UAAU,EACV,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { type RoleColors, type SchemeVariant } from '../color-engine';
|
|
2
|
+
/**
|
|
3
|
+
* Give a resolved token map the `--color-x` alias layer, so utilities resolve
|
|
4
|
+
* against the scope instead of the document root.
|
|
5
|
+
*
|
|
6
|
+
* Shared by both scope builders — the preset path (`buildScopeVars`) and the
|
|
7
|
+
* seed path (`buildSeedScopeVars`) — because a gap here is invisible until a
|
|
8
|
+
* scoped page paints the wrong colour in one mode only.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withScopeAliases(tokens: Record<string, string>): Record<string, string>;
|
|
2
11
|
/**
|
|
3
12
|
* The canonical role → token assignment, sourced from an arbitrary seed's role
|
|
4
13
|
* set instead of a named preset.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-scope.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/seed-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"seed-scope.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/seed-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAyB1F;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAevF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4C9E;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBpF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-builder.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/style-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"style-builder.d.ts","sourceRoot":"","sources":["../../../../../src/theme/color-scope/style-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA8CtD;;;;;GAKG;AACH,MAAM,MAAM,gCAAgC,GAAG,KAAK,CAAC,aAAa,CAAC;IACjE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC,CAAC;AAkEH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,YAAY,EACzB,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,eAAe,GACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAExB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,IAAI,gCAAgC,GAAG,IAAI,CAepF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,YAAY,EACzB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,SAAS,CAAC,SAAS,CAAC,CAQtB"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { dirname, join, relative } from 'node:path';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
bloomTailwindPreset,
|
|
6
6
|
bloomThemeCss,
|
|
7
7
|
bloomThemeBlock,
|
|
8
|
+
getPresetVars,
|
|
9
|
+
buildSeedScopeVars,
|
|
8
10
|
FILL_ROLES,
|
|
9
11
|
TEXT_ROLES,
|
|
10
12
|
BORDER_ROLES,
|
|
@@ -16,6 +18,8 @@ import {
|
|
|
16
18
|
SHADOW_BOX,
|
|
17
19
|
bloomShadowStyle,
|
|
18
20
|
} from '../design-tokens';
|
|
21
|
+
import { APP_COLOR_PRESETS } from '../theme/color-presets';
|
|
22
|
+
import { buildScopeVars } from '../theme/color-scope/style-builder';
|
|
19
23
|
import { CANONICAL_TOKENS } from '../theme/token-registry';
|
|
20
24
|
|
|
21
25
|
describe('design-tokens color roles', () => {
|
|
@@ -190,3 +194,150 @@ describe('design-tokens shadow style (web default)', () => {
|
|
|
190
194
|
expect(style).toHaveProperty('boxShadow', SHADOW_BOX.m);
|
|
191
195
|
});
|
|
192
196
|
});
|
|
197
|
+
|
|
198
|
+
describe('design-tokens resolved token values', () => {
|
|
199
|
+
it('getPresetVars resolves a preset to canonical tokens only', () => {
|
|
200
|
+
const vars = getPresetVars('oxy', 'dark');
|
|
201
|
+
expect(vars['--background']).toMatch(/^rgb/);
|
|
202
|
+
// A document root needs the canonical tokens alone — the `--color-x` alias
|
|
203
|
+
// layer comes from theme.css / bloomThemeCss().
|
|
204
|
+
expect(Object.keys(vars).some((k) => k.startsWith('--color-'))).toBe(false);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('buildSeedScopeVars also emits the --color-x aliases a scope needs', () => {
|
|
208
|
+
const vars = buildSeedScopeVars({ seed: '#7c5aed', mode: 'dark' });
|
|
209
|
+
// Every canonical token gets a same-named alias. The role vocabulary
|
|
210
|
+
// (`--color-fill` → `--card`) is checked against theme.css further down,
|
|
211
|
+
// where the mapping comes from rather than being restated here.
|
|
212
|
+
const canonical = Object.keys(vars).filter((k) => !k.startsWith('--color-'));
|
|
213
|
+
expect(canonical.length).toBeGreaterThan(0);
|
|
214
|
+
for (const token of canonical) {
|
|
215
|
+
expect(vars[`--color-${token.slice(2)}`]).toBe(vars[token]);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("a preset's own seed reproduces that preset exactly", () => {
|
|
220
|
+
// What lets a consumer theme a brand scope and the document root through one
|
|
221
|
+
// code path: the seed form is not an approximation of the preset form.
|
|
222
|
+
const preset = APP_COLOR_PRESETS.oxy;
|
|
223
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
224
|
+
const fromPreset = getPresetVars('oxy', mode);
|
|
225
|
+
const fromSeed = buildSeedScopeVars({
|
|
226
|
+
seed: preset.hex,
|
|
227
|
+
mode,
|
|
228
|
+
variant: preset.variant,
|
|
229
|
+
});
|
|
230
|
+
for (const [token, value] of Object.entries(fromPreset)) {
|
|
231
|
+
expect(fromSeed[token]).toBe(value);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
describe('a scope re-declares every alias theme.css points at a token', () => {
|
|
238
|
+
/* The failure this guards is silent and mode-dependent: a scope overrides
|
|
239
|
+
* `--foreground`, but `--color-text: var(--foreground)` was computed at the
|
|
240
|
+
* document root, so `text-text` inside the scope keeps painting the app-wide
|
|
241
|
+
* colour. It looks correct in whichever mode the root happens to match.
|
|
242
|
+
*
|
|
243
|
+
* The list is read out of `bloomThemeCss()` rather than written here, so an
|
|
244
|
+
* alias added there is covered the day it lands. */
|
|
245
|
+
const rootAliases = bloomThemeCss()
|
|
246
|
+
.split('\n')
|
|
247
|
+
.map((line) => /^\s*--color-([a-z0-9-]+):\s*var\(--([a-z0-9-]+)\);\s*$/.exec(line))
|
|
248
|
+
.filter((match): match is RegExpExecArray => match !== null)
|
|
249
|
+
.map((match) => ({ alias: match[1] as string, canonical: match[2] as string }))
|
|
250
|
+
|
|
251
|
+
it('covers a meaningful number of aliases', () => {
|
|
252
|
+
// A regex that stopped matching would otherwise leave every case below
|
|
253
|
+
// passing over an empty list.
|
|
254
|
+
expect(rootAliases.length).toBeGreaterThan(20)
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
for (const [label, scope] of [
|
|
258
|
+
['seed', buildSeedScopeVars({ seed: '#7c5aed', mode: 'dark' })],
|
|
259
|
+
['preset', buildScopeVars('faircoin', 'dark')],
|
|
260
|
+
] as const) {
|
|
261
|
+
it(`resolves them against the scope's own tokens (${label})`, () => {
|
|
262
|
+
const wrong = rootAliases
|
|
263
|
+
.filter(({ canonical }) => scope[`--${canonical}`] !== undefined)
|
|
264
|
+
.filter(({ alias, canonical }) => scope[`--color-${alias}`] !== scope[`--${canonical}`])
|
|
265
|
+
.map(({ alias, canonical }) => `--color-${alias} != --${canonical}`)
|
|
266
|
+
expect(wrong).toEqual([])
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
describe('design-tokens entry stays free of react / react-native', () => {
|
|
272
|
+
/* Build scripts import this entry from plain node/bun to emit a static theme
|
|
273
|
+
* stylesheet (see the export's doc comment). A `react-native` import anywhere
|
|
274
|
+
* in its transitive graph makes that throw at import time — in the CONSUMER's
|
|
275
|
+
* build, with a parse error inside node_modules and nothing pointing back
|
|
276
|
+
* here. Jest cannot catch it by importing the module: this suite runs in the
|
|
277
|
+
* RN preset, where both packages resolve. So walk the graph statically. */
|
|
278
|
+
const SOURCE_ROOT = join(__dirname, '..');
|
|
279
|
+
/* Captures the clause of every `import`/`export … from '…'`, so a type-only
|
|
280
|
+
* one can be told apart from a value one. `import { type ViewStyle } from
|
|
281
|
+
* 'react-native'` is erased by the compiler and is FINE here; a value import
|
|
282
|
+
* of the same module is not. A scanner blind to the difference reports the
|
|
283
|
+
* shipped `shadows.ts` as a violation. */
|
|
284
|
+
const IMPORT_RE = /(?:import|export)\s+([\s\S]*?)\s*from\s*['"]([^'"]+)['"]/g;
|
|
285
|
+
|
|
286
|
+
function isValueImport(clause: string): boolean {
|
|
287
|
+
const trimmed = clause.trim();
|
|
288
|
+
if (trimmed.startsWith('type ') || trimmed === 'type') return false;
|
|
289
|
+
const named = /^\{([\s\S]*)\}$/.exec(trimmed)?.[1];
|
|
290
|
+
if (named === undefined) return true; // default or namespace import — always a value
|
|
291
|
+
return named
|
|
292
|
+
.split(',')
|
|
293
|
+
.map((specifier) => specifier.trim())
|
|
294
|
+
.filter(Boolean)
|
|
295
|
+
.some((specifier) => !specifier.startsWith('type '));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function resolve(specifier: string, fromFile: string): string | null {
|
|
299
|
+
const base = join(dirname(fromFile), specifier);
|
|
300
|
+
for (const candidate of [
|
|
301
|
+
base,
|
|
302
|
+
`${base}.ts`,
|
|
303
|
+
`${base}.tsx`,
|
|
304
|
+
join(base, 'index.ts'),
|
|
305
|
+
join(base, 'index.tsx'),
|
|
306
|
+
]) {
|
|
307
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const entry = join(SOURCE_ROOT, 'design-tokens', 'index.ts');
|
|
313
|
+
const visited = new Set<string>();
|
|
314
|
+
const offenders: string[] = [];
|
|
315
|
+
const queue = [entry];
|
|
316
|
+
|
|
317
|
+
for (let file = queue.pop(); file !== undefined; file = queue.pop()) {
|
|
318
|
+
if (visited.has(file)) continue;
|
|
319
|
+
visited.add(file);
|
|
320
|
+
const source = readFileSync(file, 'utf8');
|
|
321
|
+
for (const match of source.matchAll(IMPORT_RE)) {
|
|
322
|
+
const [, clause = '', specifier = ''] = match;
|
|
323
|
+
if (!isValueImport(clause)) continue;
|
|
324
|
+
if (specifier === 'react' || specifier === 'react-native' || specifier.startsWith('react-native/')) {
|
|
325
|
+
offenders.push(`${relative(SOURCE_ROOT, file)} imports ${specifier}`);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (!specifier.startsWith('.')) continue;
|
|
329
|
+
const resolved = resolve(specifier, file);
|
|
330
|
+
if (resolved) queue.push(resolved);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
it('imports neither react nor react-native anywhere in its graph', () => {
|
|
335
|
+
expect(offenders).toEqual([]);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('actually walked the graph', () => {
|
|
339
|
+
// Without a floor, a resolver that silently returns null for everything
|
|
340
|
+
// would report a clean graph of one file.
|
|
341
|
+
expect(visited.size).toBeGreaterThan(8);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
* `p-space-8`, `rounded-radius-20`, `text-body`, `font-body`, `shadow-s`).
|
|
9
9
|
* - `bloomThemeCss` / `bloomThemeBlock` — the Tailwind v4 `@theme` equivalent
|
|
10
10
|
* for CSS-configured web apps.
|
|
11
|
+
* - `getPresetVars` / `buildSeedScopeVars` — the resolved token VALUES behind
|
|
12
|
+
* that alias layer, for a named preset or an arbitrary brand seed.
|
|
11
13
|
* - The raw token maps (`FILL_ROLES`, `TEXT_ROLES`, `BORDER_ROLES`, `SPACING`,
|
|
12
14
|
* `RADIUS`, `TYPOGRAPHY`, `SHADOW_BOX`) for direct programmatic use.
|
|
13
15
|
* - `bloomShadowStyle` — platform-correct shadow style object (web box-shadow /
|
|
@@ -25,6 +27,25 @@ export type {
|
|
|
25
27
|
|
|
26
28
|
export { bloomThemeCss, bloomThemeBlock } from './theme-css';
|
|
27
29
|
|
|
30
|
+
/* The resolved counterpart of `bloomThemeCss()`. That emits the alias layer
|
|
31
|
+
* (`--color-x: var(--x)`); these resolve `--x` itself, so a build script can
|
|
32
|
+
* write a static `:root` / `.dark` block and a prerendered page paints the real
|
|
33
|
+
* theme before `BloomThemeProvider` runs — instead of a hand-written palette
|
|
34
|
+
* that drifts from the preset it claims to mirror.
|
|
35
|
+
*
|
|
36
|
+
* `getPresetVars` returns the canonical tokens alone, which is all a document
|
|
37
|
+
* root needs. `buildSeedScopeVars` also returns the `--color-x` aliases, which a
|
|
38
|
+
* SCOPED block (a brand section, a forced-dark region) does need: a `--color-x`
|
|
39
|
+
* alias substitutes where it is declared, so overriding `--x` on a subtree does
|
|
40
|
+
* not move an alias declared at `:root`.
|
|
41
|
+
*
|
|
42
|
+
* Both are pure — no React, no react-native — so they run in a plain node/bun
|
|
43
|
+
* build script as well as in an app. */
|
|
44
|
+
export { getPresetVars } from '../theme/preset-vars';
|
|
45
|
+
export type { ExplicitAccents } from '../theme/preset-vars';
|
|
46
|
+
export { buildSeedScopeVars } from '../theme/color-scope/seed-scope';
|
|
47
|
+
export type { SeedScopeOptions } from '../theme/color-scope/seed-scope';
|
|
48
|
+
|
|
28
49
|
export {
|
|
29
50
|
FILL_ROLES,
|
|
30
51
|
TEXT_ROLES,
|
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
import { generateRoleColors, type RoleColors, type SchemeVariant } from '../color-engine';
|
|
2
2
|
import { buildPolicyTokens, isColourlessSeed } from '../color-policy';
|
|
3
|
-
import {
|
|
3
|
+
import { BORDER_ROLES, FILL_ROLES, TEXT_ROLES } from '../../design-tokens/color-roles';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Every alias `theme.css` declares at `:root` as a reference to a canonical
|
|
7
|
+
* token, keyed by the alias name. `--color-divider` is one of these and does not
|
|
8
|
+
* come from the role maps, so it is named here.
|
|
9
|
+
*
|
|
10
|
+
* An alias declared at the document root substitutes THERE, so a subtree that
|
|
11
|
+
* overrides `--foreground` cannot move a `--color-text: var(--foreground)` the
|
|
12
|
+
* root already computed — the subtree keeps painting the app-wide palette while
|
|
13
|
+
* every canonical token around it says otherwise. Re-declaring each alias inside
|
|
14
|
+
* the scope, against the scope's own values, is what closes that.
|
|
15
|
+
*
|
|
16
|
+
* An alias whose value is a literal (`--color-destructive-foreground: #ffffff`)
|
|
17
|
+
* is unaffected and deliberately absent.
|
|
18
|
+
*/
|
|
19
|
+
const SCOPED_ALIASES: Readonly<Record<string, string>> = {
|
|
20
|
+
...FILL_ROLES,
|
|
21
|
+
...TEXT_ROLES,
|
|
22
|
+
...BORDER_ROLES,
|
|
23
|
+
divider: 'var(--border)',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Give a resolved token map the `--color-x` alias layer, so utilities resolve
|
|
28
|
+
* against the scope instead of the document root.
|
|
29
|
+
*
|
|
30
|
+
* Shared by both scope builders — the preset path (`buildScopeVars`) and the
|
|
31
|
+
* seed path (`buildSeedScopeVars`) — because a gap here is invisible until a
|
|
32
|
+
* scoped page paints the wrong colour in one mode only.
|
|
33
|
+
*/
|
|
34
|
+
export function withScopeAliases(tokens: Record<string, string>): Record<string, string> {
|
|
35
|
+
const vars: Record<string, string> = { ...tokens };
|
|
36
|
+
|
|
37
|
+
// Policy tokens live outside the canonical set, so alias every token present.
|
|
38
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
39
|
+
vars[`--color-${key.slice(2)}`] = value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const [alias, reference] of Object.entries(SCOPED_ALIASES)) {
|
|
43
|
+
const canonical = /^var\(--(.+)\)$/.exec(reference)?.[1];
|
|
44
|
+
const resolved = canonical === undefined ? undefined : tokens[`--${canonical}`];
|
|
45
|
+
if (resolved !== undefined) vars[`--color-${alias}`] = resolved;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return vars;
|
|
49
|
+
}
|
|
4
50
|
|
|
5
51
|
/**
|
|
6
52
|
* The canonical role → token assignment, sourced from an arbitrary seed's role
|
|
@@ -121,19 +167,5 @@ export function buildSeedScopeVars(options: SeedScopeOptions): Record<string, st
|
|
|
121
167
|
tertiary: options.tertiarySeed,
|
|
122
168
|
}),
|
|
123
169
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// Policy tokens live outside CANONICAL_TOKENS, so alias every token present.
|
|
127
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
128
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
for (const token of CANONICAL_TOKENS) {
|
|
132
|
-
const value = tokens[`--${token}`];
|
|
133
|
-
if (value !== undefined) {
|
|
134
|
-
vars[`--color-${token}`] = value;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return vars;
|
|
170
|
+
return withScopeAliases(tokens);
|
|
139
171
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import { Platform, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getResolvedTokens } from '../token-registry';
|
|
5
5
|
import type { AppColorName } from '../color-presets';
|
|
6
6
|
import type { ExplicitAccents } from '../preset-vars';
|
|
7
|
+
import { withScopeAliases } from './seed-scope';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* The optional-peer boundary for `nativewind`.
|
|
@@ -138,23 +139,7 @@ export function buildScopeVars(
|
|
|
138
139
|
mode: 'light' | 'dark',
|
|
139
140
|
accents?: ExplicitAccents,
|
|
140
141
|
): Record<string, string> {
|
|
141
|
-
|
|
142
|
-
const vars: Record<string, string> = { ...tokens };
|
|
143
|
-
|
|
144
|
-
// Policy tokens live outside CANONICAL_TOKENS, so give every token present a
|
|
145
|
-
// `--color-*` alias; NativeWind resolves its utilities through those.
|
|
146
|
-
for (const [key, value] of Object.entries(tokens)) {
|
|
147
|
-
vars[`--color-${key.slice(2)}`] = value;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
for (const token of CANONICAL_TOKENS) {
|
|
151
|
-
const value = tokens[`--${token}`];
|
|
152
|
-
if (value !== undefined) {
|
|
153
|
-
vars[`--color-${token}`] = value;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return vars;
|
|
142
|
+
return withScopeAliases(getResolvedTokens(colorPreset, mode, accents));
|
|
158
143
|
}
|
|
159
144
|
|
|
160
145
|
/**
|