@oxyhq/bloom 0.84.0 → 0.85.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/module/design-tokens/index.js +19 -0
- package/lib/module/design-tokens/index.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/module/design-tokens/index.d.ts +6 -0
- package/lib/typescript/module/design-tokens/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/design-tokens.test.ts +115 -2
- package/src/design-tokens/index.ts +21 -0
|
@@ -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":[]}
|
|
@@ -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":[]}
|
|
@@ -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"}
|
|
@@ -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"}
|
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,7 @@ import {
|
|
|
16
18
|
SHADOW_BOX,
|
|
17
19
|
bloomShadowStyle,
|
|
18
20
|
} from '../design-tokens';
|
|
21
|
+
import { APP_COLOR_PRESETS } from '../theme/color-presets';
|
|
19
22
|
import { CANONICAL_TOKENS } from '../theme/token-registry';
|
|
20
23
|
|
|
21
24
|
describe('design-tokens color roles', () => {
|
|
@@ -190,3 +193,113 @@ describe('design-tokens shadow style (web default)', () => {
|
|
|
190
193
|
expect(style).toHaveProperty('boxShadow', SHADOW_BOX.m);
|
|
191
194
|
});
|
|
192
195
|
});
|
|
196
|
+
|
|
197
|
+
describe('design-tokens resolved token values', () => {
|
|
198
|
+
it('getPresetVars resolves a preset to canonical tokens only', () => {
|
|
199
|
+
const vars = getPresetVars('oxy', 'dark');
|
|
200
|
+
expect(vars['--background']).toMatch(/^rgb/);
|
|
201
|
+
// A document root needs the canonical tokens alone — the `--color-x` alias
|
|
202
|
+
// layer comes from theme.css / bloomThemeCss().
|
|
203
|
+
expect(Object.keys(vars).some((k) => k.startsWith('--color-'))).toBe(false);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('buildSeedScopeVars also emits the --color-x aliases a scope needs', () => {
|
|
207
|
+
const vars = buildSeedScopeVars({ seed: '#7c5aed', mode: 'dark' });
|
|
208
|
+
const aliases = Object.keys(vars).filter((k) => k.startsWith('--color-'));
|
|
209
|
+
expect(aliases.length).toBeGreaterThan(0);
|
|
210
|
+
for (const alias of aliases) {
|
|
211
|
+
expect(vars[alias]).toBe(vars[alias.replace('--color-', '--')]);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("a preset's own seed reproduces that preset exactly", () => {
|
|
216
|
+
// What lets a consumer theme a brand scope and the document root through one
|
|
217
|
+
// code path: the seed form is not an approximation of the preset form.
|
|
218
|
+
const preset = APP_COLOR_PRESETS.oxy;
|
|
219
|
+
for (const mode of ['light', 'dark'] as const) {
|
|
220
|
+
const fromPreset = getPresetVars('oxy', mode);
|
|
221
|
+
const fromSeed = buildSeedScopeVars({
|
|
222
|
+
seed: preset.hex,
|
|
223
|
+
mode,
|
|
224
|
+
variant: preset.variant,
|
|
225
|
+
});
|
|
226
|
+
for (const [token, value] of Object.entries(fromPreset)) {
|
|
227
|
+
expect(fromSeed[token]).toBe(value);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('design-tokens entry stays free of react / react-native', () => {
|
|
234
|
+
/* Build scripts import this entry from plain node/bun to emit a static theme
|
|
235
|
+
* stylesheet (see the export's doc comment). A `react-native` import anywhere
|
|
236
|
+
* in its transitive graph makes that throw at import time — in the CONSUMER's
|
|
237
|
+
* build, with a parse error inside node_modules and nothing pointing back
|
|
238
|
+
* here. Jest cannot catch it by importing the module: this suite runs in the
|
|
239
|
+
* RN preset, where both packages resolve. So walk the graph statically. */
|
|
240
|
+
const SOURCE_ROOT = join(__dirname, '..');
|
|
241
|
+
/* Captures the clause of every `import`/`export … from '…'`, so a type-only
|
|
242
|
+
* one can be told apart from a value one. `import { type ViewStyle } from
|
|
243
|
+
* 'react-native'` is erased by the compiler and is FINE here; a value import
|
|
244
|
+
* of the same module is not. A scanner blind to the difference reports the
|
|
245
|
+
* shipped `shadows.ts` as a violation. */
|
|
246
|
+
const IMPORT_RE = /(?:import|export)\s+([\s\S]*?)\s*from\s*['"]([^'"]+)['"]/g;
|
|
247
|
+
|
|
248
|
+
function isValueImport(clause: string): boolean {
|
|
249
|
+
const trimmed = clause.trim();
|
|
250
|
+
if (trimmed.startsWith('type ') || trimmed === 'type') return false;
|
|
251
|
+
const named = /^\{([\s\S]*)\}$/.exec(trimmed)?.[1];
|
|
252
|
+
if (named === undefined) return true; // default or namespace import — always a value
|
|
253
|
+
return named
|
|
254
|
+
.split(',')
|
|
255
|
+
.map((specifier) => specifier.trim())
|
|
256
|
+
.filter(Boolean)
|
|
257
|
+
.some((specifier) => !specifier.startsWith('type '));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function resolve(specifier: string, fromFile: string): string | null {
|
|
261
|
+
const base = join(dirname(fromFile), specifier);
|
|
262
|
+
for (const candidate of [
|
|
263
|
+
base,
|
|
264
|
+
`${base}.ts`,
|
|
265
|
+
`${base}.tsx`,
|
|
266
|
+
join(base, 'index.ts'),
|
|
267
|
+
join(base, 'index.tsx'),
|
|
268
|
+
]) {
|
|
269
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;
|
|
270
|
+
}
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const entry = join(SOURCE_ROOT, 'design-tokens', 'index.ts');
|
|
275
|
+
const visited = new Set<string>();
|
|
276
|
+
const offenders: string[] = [];
|
|
277
|
+
const queue = [entry];
|
|
278
|
+
|
|
279
|
+
for (let file = queue.pop(); file !== undefined; file = queue.pop()) {
|
|
280
|
+
if (visited.has(file)) continue;
|
|
281
|
+
visited.add(file);
|
|
282
|
+
const source = readFileSync(file, 'utf8');
|
|
283
|
+
for (const match of source.matchAll(IMPORT_RE)) {
|
|
284
|
+
const [, clause = '', specifier = ''] = match;
|
|
285
|
+
if (!isValueImport(clause)) continue;
|
|
286
|
+
if (specifier === 'react' || specifier === 'react-native' || specifier.startsWith('react-native/')) {
|
|
287
|
+
offenders.push(`${relative(SOURCE_ROOT, file)} imports ${specifier}`);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (!specifier.startsWith('.')) continue;
|
|
291
|
+
const resolved = resolve(specifier, file);
|
|
292
|
+
if (resolved) queue.push(resolved);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
it('imports neither react nor react-native anywhere in its graph', () => {
|
|
297
|
+
expect(offenders).toEqual([]);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('actually walked the graph', () => {
|
|
301
|
+
// Without a floor, a resolver that silently returns null for everything
|
|
302
|
+
// would report a clean graph of one file.
|
|
303
|
+
expect(visited.size).toBeGreaterThan(8);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
@@ -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,
|