@oxyhq/bloom 0.87.0 → 0.88.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/NOTICE +1 -1
- package/README.md +1 -1
- package/lib/commonjs/bottom-sheet/BottomSheetBase.js +7 -12
- package/lib/commonjs/bottom-sheet/BottomSheetBase.js.map +1 -1
- package/lib/commonjs/button/Button.web.js +2 -6
- package/lib/commonjs/button/Button.web.js.map +1 -1
- package/lib/commonjs/connection-dots/ConnectionDots.web.js +2 -6
- package/lib/commonjs/connection-dots/ConnectionDots.web.js.map +1 -1
- package/lib/commonjs/design-tokens/index.js +19 -0
- package/lib/commonjs/design-tokens/index.js.map +1 -1
- package/lib/commonjs/design-tokens/tokens-json.js +149 -0
- package/lib/commonjs/design-tokens/tokens-json.js.map +1 -0
- package/lib/commonjs/design-tokens/tokens.json +6681 -0
- package/lib/commonjs/dialog/Dialog.web.js +2 -6
- package/lib/commonjs/dialog/Dialog.web.js.map +1 -1
- package/lib/commonjs/fab/Fab.web.js +2 -6
- package/lib/commonjs/fab/Fab.web.js.map +1 -1
- package/lib/commonjs/fonts/apply-font-faces.web.js +8 -10
- package/lib/commonjs/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/commonjs/frosted-icon-button/FrostedIconButton.web.js +2 -6
- package/lib/commonjs/frosted-icon-button/FrostedIconButton.web.js.map +1 -1
- package/lib/commonjs/loading/SpinnerIcon.web.js +2 -6
- package/lib/commonjs/loading/SpinnerIcon.web.js.map +1 -1
- package/lib/commonjs/overlay/index.js +102 -24
- package/lib/commonjs/overlay/index.js.map +1 -1
- package/lib/commonjs/styles/adopt-style-sheet.js +126 -0
- package/lib/commonjs/styles/adopt-style-sheet.js.map +1 -0
- package/lib/module/bottom-sheet/BottomSheetBase.js +7 -12
- package/lib/module/bottom-sheet/BottomSheetBase.js.map +1 -1
- package/lib/module/button/Button.web.js +2 -6
- package/lib/module/button/Button.web.js.map +1 -1
- package/lib/module/connection-dots/ConnectionDots.web.js +2 -6
- package/lib/module/connection-dots/ConnectionDots.web.js.map +1 -1
- package/lib/module/design-tokens/index.js +5 -0
- package/lib/module/design-tokens/index.js.map +1 -1
- package/lib/module/design-tokens/tokens-json.js +144 -0
- package/lib/module/design-tokens/tokens-json.js.map +1 -0
- package/lib/module/design-tokens/tokens.json +6681 -0
- package/lib/module/dialog/Dialog.web.js +2 -6
- package/lib/module/dialog/Dialog.web.js.map +1 -1
- package/lib/module/fab/Fab.web.js +2 -6
- package/lib/module/fab/Fab.web.js.map +1 -1
- package/lib/module/fonts/apply-font-faces.web.js +8 -10
- package/lib/module/fonts/apply-font-faces.web.js.map +1 -1
- package/lib/module/frosted-icon-button/FrostedIconButton.web.js +2 -6
- package/lib/module/frosted-icon-button/FrostedIconButton.web.js.map +1 -1
- package/lib/module/loading/SpinnerIcon.web.js +2 -6
- package/lib/module/loading/SpinnerIcon.web.js.map +1 -1
- package/lib/module/overlay/index.js +103 -25
- package/lib/module/overlay/index.js.map +1 -1
- package/lib/module/styles/adopt-style-sheet.js +121 -0
- package/lib/module/styles/adopt-style-sheet.js.map +1 -0
- package/lib/typescript/commonjs/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
- package/lib/typescript/commonjs/button/Button.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/connection-dots/ConnectionDots.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/design-tokens/index.d.ts +2 -0
- package/lib/typescript/commonjs/design-tokens/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/design-tokens/tokens-json.d.ts +85 -0
- package/lib/typescript/commonjs/design-tokens/tokens-json.d.ts.map +1 -0
- package/lib/typescript/commonjs/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/fab/Fab.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts +5 -3
- package/lib/typescript/commonjs/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/frosted-icon-button/FrostedIconButton.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/loading/SpinnerIcon.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/overlay/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/styles/adopt-style-sheet.d.ts +22 -0
- package/lib/typescript/commonjs/styles/adopt-style-sheet.d.ts.map +1 -0
- package/lib/typescript/module/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
- package/lib/typescript/module/button/Button.web.d.ts.map +1 -1
- package/lib/typescript/module/connection-dots/ConnectionDots.web.d.ts.map +1 -1
- package/lib/typescript/module/design-tokens/index.d.ts +2 -0
- package/lib/typescript/module/design-tokens/index.d.ts.map +1 -1
- package/lib/typescript/module/design-tokens/tokens-json.d.ts +85 -0
- package/lib/typescript/module/design-tokens/tokens-json.d.ts.map +1 -0
- package/lib/typescript/module/dialog/Dialog.web.d.ts.map +1 -1
- package/lib/typescript/module/fab/Fab.web.d.ts.map +1 -1
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts +5 -3
- package/lib/typescript/module/fonts/apply-font-faces.web.d.ts.map +1 -1
- package/lib/typescript/module/frosted-icon-button/FrostedIconButton.web.d.ts.map +1 -1
- package/lib/typescript/module/loading/SpinnerIcon.web.d.ts.map +1 -1
- package/lib/typescript/module/overlay/index.d.ts.map +1 -1
- package/lib/typescript/module/styles/adopt-style-sheet.d.ts +22 -0
- package/lib/typescript/module/styles/adopt-style-sheet.d.ts.map +1 -0
- package/package.json +4 -2
- package/src/__tests__/adopt-style-sheet.node.test.ts +21 -0
- package/src/__tests__/adopt-style-sheet.test.ts +165 -0
- package/src/__tests__/apply-font-faces.test.ts +32 -0
- package/src/__tests__/design-tokens-json.test.ts +112 -0
- package/src/__tests__/exports-map-contract.test.ts +5 -1
- package/src/__tests__/support/constructed-style-sheets.ts +68 -0
- package/src/bottom-sheet/BottomSheetBase.tsx +10 -14
- package/src/button/Button.web.tsx +2 -6
- package/src/connection-dots/ConnectionDots.web.tsx +2 -6
- package/src/design-tokens/index.ts +16 -0
- package/src/design-tokens/tokens-json.ts +214 -0
- package/src/design-tokens/tokens.json +6681 -0
- package/src/dialog/Dialog.stories.tsx +37 -0
- package/src/dialog/Dialog.web.tsx +2 -6
- package/src/fab/Fab.web.tsx +2 -6
- package/src/fonts/apply-font-faces.web.ts +11 -11
- package/src/frosted-icon-button/FrostedIconButton.web.tsx +2 -6
- package/src/loading/SpinnerIcon.web.tsx +2 -6
- package/src/overlay/index.tsx +123 -24
- package/src/styles/adopt-style-sheet.ts +131 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The machine-readable form of every Bloom design token, in W3C Design Tokens
|
|
3
|
+
* (DTCG) format.
|
|
4
|
+
*
|
|
5
|
+
* The CSS artifacts next to this file (`theme.css`, `bloomThemeCss()`) are the
|
|
6
|
+
* ALIAS layer and only make sense to a browser. A consumer that is not a
|
|
7
|
+
* browser — Astro codegens `SkColor` tables for Chromium's native UI so the
|
|
8
|
+
* toolbar and the WebUI pages cannot disagree about what "primary" is — needs
|
|
9
|
+
* the RESOLVED values, for every preset and both schemes, in a format it can
|
|
10
|
+
* read without running Bloom's colour engine. That is this file.
|
|
11
|
+
*
|
|
12
|
+
* Same single source as everything else: `getResolvedTokens`, i.e. the colour
|
|
13
|
+
* engine. `tokens.json` is generated from it by
|
|
14
|
+
* `scripts/generate-design-tokens-json.ts`, and
|
|
15
|
+
* `src/__tests__/design-tokens-json.test.ts` fails if the checked-in file is
|
|
16
|
+
* not byte-identical to a fresh render — so the JSON, the CSS and the runtime
|
|
17
|
+
* palette cannot drift from each other.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
APP_COLOR_NAMES,
|
|
22
|
+
APP_COLOR_PRESETS,
|
|
23
|
+
type AppColorName,
|
|
24
|
+
} from '../theme/color-presets';
|
|
25
|
+
import { getResolvedTokens } from '../theme/token-registry';
|
|
26
|
+
import {
|
|
27
|
+
BORDER_WIDTH,
|
|
28
|
+
RADIUS,
|
|
29
|
+
SPACING,
|
|
30
|
+
TYPOGRAPHY,
|
|
31
|
+
type TypeRoleName,
|
|
32
|
+
} from './scales';
|
|
33
|
+
|
|
34
|
+
/** One DTCG token. `$type` is inherited from the nearest group that declares it. */
|
|
35
|
+
export interface DesignToken {
|
|
36
|
+
$value: string | number;
|
|
37
|
+
$type?: string;
|
|
38
|
+
$description?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Bloom-specific metadata on a preset group, namespaced per the DTCG `$extensions` rule. */
|
|
42
|
+
export interface PresetExtensions {
|
|
43
|
+
'so.oxy.bloom': {
|
|
44
|
+
/** The brand seed the engine derived the whole palette from. */
|
|
45
|
+
seed: string;
|
|
46
|
+
/** The tonal scheme variant used with that seed. */
|
|
47
|
+
variant: string;
|
|
48
|
+
/** Who may pick the preset; absent means everyone. */
|
|
49
|
+
gate?: string;
|
|
50
|
+
/** Present when the preset forces a white label in both schemes. */
|
|
51
|
+
label?: string;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface PresetGroup {
|
|
56
|
+
$description: string;
|
|
57
|
+
$extensions: PresetExtensions;
|
|
58
|
+
light: Record<string, DesignToken>;
|
|
59
|
+
dark: Record<string, DesignToken>;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface BloomDesignTokens {
|
|
63
|
+
$description: string;
|
|
64
|
+
color: { $type: 'color'; $description: string } & Record<string, unknown>;
|
|
65
|
+
spacing: { $type: 'dimension'; $description: string } & Record<string, unknown>;
|
|
66
|
+
radius: { $type: 'dimension'; $description: string } & Record<string, unknown>;
|
|
67
|
+
borderWidth: { $type: 'dimension'; $description: string } & Record<string, unknown>;
|
|
68
|
+
typography: { $description: string } & Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const FILE_DESCRIPTION = [
|
|
72
|
+
'Bloom design tokens, resolved. W3C Design Tokens Community Group format.',
|
|
73
|
+
'SHAPE CONTRACT (consumers codegen against this — additions are additive, existing paths do not move):',
|
|
74
|
+
'color.<preset>.<scheme>.<token> — <preset> is a Bloom AppColorName, <scheme> is "light" or "dark",',
|
|
75
|
+
'and <token> is the CSS custom property Bloom writes on the document root with its leading "--" removed,',
|
|
76
|
+
'so color.oxy.dark.card carries the value of --card under the oxy preset in dark.',
|
|
77
|
+
'Every colour $value is an sRGB hex string: "#rrggbb", or "#rrggbbaa" when the token carries alpha',
|
|
78
|
+
'(the -subtle family does). spacing/radius/borderWidth are DTCG dimensions with a px unit in the string.',
|
|
79
|
+
'typography.<role> is a group of fontSize (dimension), lineHeight (dimension) and fontWeight (number);',
|
|
80
|
+
'font FAMILIES are deliberately absent — they resolve to CSS variables a non-browser consumer cannot use.',
|
|
81
|
+
'Shadows are absent for the same reason: Bloom ships them as a platform-forked style object (bloomShadowStyle),',
|
|
82
|
+
'not as a value.',
|
|
83
|
+
'AUTO-GENERATED by scripts/generate-design-tokens-json.ts from Bloom’s colour engine — do not edit.',
|
|
84
|
+
].join(' ');
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Turn one resolved token value into an sRGB hex string.
|
|
88
|
+
*
|
|
89
|
+
* The engine emits exactly two forms — `rgb(r g b)` for opaque tokens and
|
|
90
|
+
* `rgba(r, g, b, a)` for the translucent `-subtle` family. Anything else is a
|
|
91
|
+
* change in the engine's output that this file has not been taught about, and
|
|
92
|
+
* throwing at generation time is the only way that surfaces: a silently
|
|
93
|
+
* passed-through CSS string would end up in a C++ colour table as garbage.
|
|
94
|
+
*/
|
|
95
|
+
export function resolvedColorToHex(value: string): string {
|
|
96
|
+
const channels = /^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)\s*(?:[,/]\s*([\d.]+%?)\s*)?\)$/.exec(
|
|
97
|
+
value,
|
|
98
|
+
);
|
|
99
|
+
if (!channels) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Bloom token value is not an rgb()/rgba() colour: ${JSON.stringify(value)}`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const [, red = '0', green = '0', blue = '0', alpha] = channels;
|
|
106
|
+
const byte = (channel: string): string =>
|
|
107
|
+
Math.round(Number(channel)).toString(16).padStart(2, '0');
|
|
108
|
+
const hex = `#${byte(red)}${byte(green)}${byte(blue)}`;
|
|
109
|
+
|
|
110
|
+
if (alpha === undefined) return hex;
|
|
111
|
+
const fraction = alpha.endsWith('%')
|
|
112
|
+
? Number(alpha.slice(0, -1)) / 100
|
|
113
|
+
: Number(alpha);
|
|
114
|
+
if (fraction >= 1) return hex;
|
|
115
|
+
return `${hex}${byte(String(fraction * 255))}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function schemeTokens(
|
|
119
|
+
preset: AppColorName,
|
|
120
|
+
scheme: 'light' | 'dark',
|
|
121
|
+
): Record<string, DesignToken> {
|
|
122
|
+
const tokens: Record<string, DesignToken> = {};
|
|
123
|
+
for (const [property, value] of Object.entries(getResolvedTokens(preset, scheme))) {
|
|
124
|
+
tokens[property.replace(/^--/, '')] = { $value: resolvedColorToHex(value) };
|
|
125
|
+
}
|
|
126
|
+
return tokens;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function colorGroup(): BloomDesignTokens['color'] {
|
|
130
|
+
const group: Record<string, unknown> = {
|
|
131
|
+
$type: 'color',
|
|
132
|
+
$description:
|
|
133
|
+
'One group per Bloom colour preset, each with a light and a dark scheme. Token names match the CSS custom properties without the leading "--".',
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
for (const name of APP_COLOR_NAMES) {
|
|
137
|
+
const preset = APP_COLOR_PRESETS[name];
|
|
138
|
+
const extensions: PresetExtensions = {
|
|
139
|
+
'so.oxy.bloom': { seed: preset.hex, variant: preset.variant },
|
|
140
|
+
};
|
|
141
|
+
if (preset.gate) extensions['so.oxy.bloom'].gate = preset.gate;
|
|
142
|
+
if (preset.label) extensions['so.oxy.bloom'].label = preset.label;
|
|
143
|
+
|
|
144
|
+
group[name] = {
|
|
145
|
+
$description: `Derived by Bloom’s colour engine from seed ${preset.hex} (${preset.variant}).`,
|
|
146
|
+
$extensions: extensions,
|
|
147
|
+
light: schemeTokens(name, 'light'),
|
|
148
|
+
dark: schemeTokens(name, 'dark'),
|
|
149
|
+
} satisfies PresetGroup;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return group as BloomDesignTokens['color'];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function dimensionGroup(
|
|
156
|
+
description: string,
|
|
157
|
+
scale: Record<string, number>,
|
|
158
|
+
): BloomDesignTokens['spacing'] {
|
|
159
|
+
const group: Record<string, unknown> = {
|
|
160
|
+
$type: 'dimension',
|
|
161
|
+
$description: description,
|
|
162
|
+
};
|
|
163
|
+
for (const [key, value] of Object.entries(scale)) {
|
|
164
|
+
group[key] = { $value: `${value}px` } satisfies DesignToken;
|
|
165
|
+
}
|
|
166
|
+
return group as BloomDesignTokens['spacing'];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function typographyGroup(): BloomDesignTokens['typography'] {
|
|
170
|
+
const group: Record<string, unknown> = {
|
|
171
|
+
$description:
|
|
172
|
+
'One group per type role. Sizes and line-heights are px dimensions; weights are DTCG numeric font weights.',
|
|
173
|
+
};
|
|
174
|
+
for (const name of Object.keys(TYPOGRAPHY) as TypeRoleName[]) {
|
|
175
|
+
const role = TYPOGRAPHY[name];
|
|
176
|
+
group[name] = {
|
|
177
|
+
fontSize: { $type: 'dimension', $value: `${role.size}px` },
|
|
178
|
+
lineHeight: { $type: 'dimension', $value: `${role.lineHeight}px` },
|
|
179
|
+
fontWeight: { $type: 'fontWeight', $value: Number(role.weight) },
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return group as BloomDesignTokens['typography'];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The whole token file, as a plain object. */
|
|
186
|
+
export function bloomDesignTokens(): BloomDesignTokens {
|
|
187
|
+
return {
|
|
188
|
+
$description: FILE_DESCRIPTION,
|
|
189
|
+
color: colorGroup(),
|
|
190
|
+
spacing: dimensionGroup(
|
|
191
|
+
'The Oxy spacing scale. Same keys as the Tailwind/NativeWind utilities (p-space-8, gap-space-20, px-screen-margin).',
|
|
192
|
+
SPACING,
|
|
193
|
+
),
|
|
194
|
+
radius: dimensionGroup(
|
|
195
|
+
'The corner-radius scale. Same keys as the rounded-radius-* utilities; radius-max is the pill/circle sentinel.',
|
|
196
|
+
RADIUS,
|
|
197
|
+
),
|
|
198
|
+
borderWidth: dimensionGroup(
|
|
199
|
+
'Border widths. hairline is the 0.5px rule that pairs with the border-image colour role.',
|
|
200
|
+
BORDER_WIDTH,
|
|
201
|
+
),
|
|
202
|
+
typography: typographyGroup(),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* The exact bytes of `design-tokens/tokens.json`.
|
|
208
|
+
*
|
|
209
|
+
* Both the generator script and the drift test call this, so neither can be
|
|
210
|
+
* right about the file while the other is wrong.
|
|
211
|
+
*/
|
|
212
|
+
export function renderBloomTokensJson(): string {
|
|
213
|
+
return `${JSON.stringify(bloomDesignTokens(), null, 2)}\n`;
|
|
214
|
+
}
|