@oxyhq/bloom 0.82.0 → 0.84.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/theme/color-policy.js +25 -3
- package/lib/commonjs/theme/color-policy.js.map +1 -1
- package/lib/commonjs/theme/color-presets.js +47 -16
- package/lib/commonjs/theme/color-presets.js.map +1 -1
- package/lib/commonjs/theme/index.js +12 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/module/theme/color-policy.js +25 -3
- package/lib/module/theme/color-policy.js.map +1 -1
- package/lib/module/theme/color-presets.js +46 -15
- package/lib/module/theme/color-presets.js.map +1 -1
- package/lib/module/theme/index.js +1 -1
- package/lib/module/theme/index.js.map +1 -1
- package/lib/typescript/commonjs/theme/color-policy.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/color-presets.d.ts +37 -2
- package/lib/typescript/commonjs/theme/color-presets.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme/index.d.ts +2 -2
- package/lib/typescript/commonjs/theme/index.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-policy.d.ts.map +1 -1
- package/lib/typescript/module/theme/color-presets.d.ts +37 -2
- package/lib/typescript/module/theme/color-presets.d.ts.map +1 -1
- package/lib/typescript/module/theme/index.d.ts +2 -2
- package/lib/typescript/module/theme/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/theme.test.ts +2 -2
- package/src/theme/__tests__/__fixtures__/golden-resolved-tokens.json +290 -290
- package/src/theme/__tests__/__snapshots__/visual-gallery.test.tsx.snap +154 -154
- package/src/theme/__tests__/color-preset-gates.test.ts +50 -0
- package/src/theme/__tests__/policy-legibility.test.ts +24 -11
- package/src/theme/color-policy.ts +32 -3
- package/src/theme/color-presets.ts +66 -14
- package/src/theme/index.ts +3 -1
|
@@ -31,6 +31,20 @@ export type AppColorName =
|
|
|
31
31
|
* maps those roles onto Bloom's canonical token names. A user-picked colour
|
|
32
32
|
* flows through the identical path — a preset is just a fixed seed.
|
|
33
33
|
*/
|
|
34
|
+
/**
|
|
35
|
+
* Why a preset is not offered to every user. Absent means it is.
|
|
36
|
+
*
|
|
37
|
+
* The two are NOT interchangeable and must not collapse back into one list: a
|
|
38
|
+
* `handle` preset belongs to a specific account and cannot be bought, while a
|
|
39
|
+
* `premium` one is exactly what is bought. Conflating them is how the picker
|
|
40
|
+
* came to offer both of Oxy's reserved brand colours to everybody.
|
|
41
|
+
*/
|
|
42
|
+
export type ColorPresetGate =
|
|
43
|
+
/** Reserved for the account whose brand it is — not purchasable. */
|
|
44
|
+
| 'handle'
|
|
45
|
+
/** Sold with a subscription. */
|
|
46
|
+
| 'premium';
|
|
47
|
+
|
|
34
48
|
export interface AppColorPreset {
|
|
35
49
|
name: AppColorName;
|
|
36
50
|
/** The brand seed colour, `#rrggbb`. Also the value the colour picker matches. */
|
|
@@ -51,6 +65,24 @@ export interface AppColorPreset {
|
|
|
51
65
|
* {@link AppColorPreset.secondaryHex} for the tertiary palette.
|
|
52
66
|
*/
|
|
53
67
|
tertiaryHex?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Force the fill to a tone a WHITE label fits, in BOTH modes — overriding the
|
|
70
|
+
* budget that otherwise lets an already-light seed keep its own tone in dark
|
|
71
|
+
* and take a black label.
|
|
72
|
+
*
|
|
73
|
+
* It has to be declared, because it cannot be derived: `yellow` (seed tone 86)
|
|
74
|
+
* wants to come down to a deep gold with white on it, and `faircoin` (tone 90)
|
|
75
|
+
* wants to stay a bright lime with black on it. Two seeds four tones apart,
|
|
76
|
+
* opposite answers — nothing in the hex distinguishes them, only what the brand
|
|
77
|
+
* is for.
|
|
78
|
+
*/
|
|
79
|
+
label?: 'white';
|
|
80
|
+
/**
|
|
81
|
+
* Who may pick this preset. Absent = everyone. Bloom only DECLARES the gate;
|
|
82
|
+
* whether a given viewer satisfies it is the consuming app's question, since
|
|
83
|
+
* only the app knows who is signed in and what they pay for.
|
|
84
|
+
*/
|
|
85
|
+
gate?: ColorPresetGate;
|
|
54
86
|
}
|
|
55
87
|
|
|
56
88
|
/**
|
|
@@ -63,19 +95,16 @@ export type PresetTokens = Record<string, string>;
|
|
|
63
95
|
|
|
64
96
|
export const APP_COLOR_NAMES: readonly AppColorName[] = ['teal', 'blue', 'green', 'yellow', 'red', 'purple', 'pink', 'sky', 'orange', 'mint', 'oxy', 'faircoin', 'pumpkin', 'gray', 'brown', 'peach', 'rose', 'mono'];
|
|
65
97
|
|
|
66
|
-
/** Premium-exclusive presets, hidden from the standard color picker. */
|
|
67
|
-
export const PREMIUM_COLOR_NAMES: readonly AppColorName[] = ['oxy', 'faircoin'];
|
|
68
|
-
|
|
69
98
|
export const HEX_TO_APP_COLOR: Record<string, AppColorName> = {
|
|
70
99
|
'#005c67': 'teal',
|
|
71
|
-
'#
|
|
100
|
+
'#1d9bf0': 'blue',
|
|
72
101
|
'#10b981': 'green',
|
|
73
|
-
'#
|
|
102
|
+
'#ffd400': 'yellow',
|
|
74
103
|
'#ef4444': 'red',
|
|
75
104
|
'#b866ff': 'purple',
|
|
76
|
-
'#
|
|
105
|
+
'#f91880': 'pink',
|
|
77
106
|
'#03a9f4': 'sky',
|
|
78
|
-
'#
|
|
107
|
+
'#ff7a00': 'orange',
|
|
79
108
|
'#14b8a6': 'mint',
|
|
80
109
|
'#c46ede': 'oxy',
|
|
81
110
|
'#9ffb50': 'faircoin',
|
|
@@ -99,12 +128,12 @@ export function hexToAppColorName(hex: string): AppColorName {
|
|
|
99
128
|
*/
|
|
100
129
|
export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
|
|
101
130
|
teal: { name: 'teal', hex: '#005c67', variant: 'vivid' },
|
|
102
|
-
blue: { name: 'blue', hex: '#
|
|
131
|
+
blue: { name: 'blue', hex: '#1d9bf0', variant: 'vivid' },
|
|
103
132
|
green: { name: 'green', hex: '#10b981', variant: 'vivid' },
|
|
104
|
-
yellow: { name: 'yellow', hex: '#
|
|
133
|
+
yellow: { name: 'yellow', hex: '#ffd400', variant: 'vivid', label: 'white' },
|
|
105
134
|
red: { name: 'red', hex: '#ef4444', variant: 'vivid' },
|
|
106
135
|
purple: { name: 'purple', hex: '#b866ff', variant: 'vivid' },
|
|
107
|
-
pink: { name: 'pink', hex: '#
|
|
136
|
+
pink: { name: 'pink', hex: '#f91880', variant: 'vivid' },
|
|
108
137
|
sky: { name: 'sky', hex: '#03a9f4', variant: 'vivid' },
|
|
109
138
|
// Deliberately NOT Tailwind's orange-500 (`#f97316`). That seed sits at HCT hue
|
|
110
139
|
// 46, which reads as orange only because it is also light: at hue 46 the sRGB
|
|
@@ -112,10 +141,10 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
|
|
|
112
141
|
// the brand fill resolved to `rgb(177 76 0)` — a brown. Hue 34 carries a chroma
|
|
113
142
|
// of 84 at that same tone, with the same white label and the same contrast
|
|
114
143
|
// headroom, so the fill reads as orange instead of paying for the hue twice.
|
|
115
|
-
orange: { name: 'orange', hex: '#
|
|
144
|
+
orange: { name: 'orange', hex: '#ff7a00', variant: 'vivid' },
|
|
116
145
|
mint: { name: 'mint', hex: '#14b8a6', variant: 'vivid' },
|
|
117
|
-
oxy: { name: 'oxy', hex: '#c46ede', variant: 'vivid' },
|
|
118
|
-
faircoin: { name: 'faircoin', hex: '#9ffb50', variant: 'vivid' },
|
|
146
|
+
oxy: { name: 'oxy', hex: '#c46ede', variant: 'vivid', gate: 'handle' },
|
|
147
|
+
faircoin: { name: 'faircoin', hex: '#9ffb50', variant: 'vivid', gate: 'handle' },
|
|
119
148
|
pumpkin: { name: 'pumpkin', hex: '#ff9800', variant: 'vivid' },
|
|
120
149
|
gray: { name: 'gray', hex: '#607d8b', variant: 'vivid' },
|
|
121
150
|
brown: { name: 'brown', hex: '#813519', variant: 'vivid' },
|
|
@@ -127,5 +156,28 @@ export const APP_COLOR_PRESETS: Record<AppColorName, AppColorPreset> = {
|
|
|
127
156
|
* seed with none, so a user who picks a grey in the colour wheel lands here too
|
|
128
157
|
* rather than on a nearly-grey approximation.
|
|
129
158
|
*/
|
|
130
|
-
mono: { name: 'mono', hex: '#000000', variant: 'monochrome' },
|
|
159
|
+
mono: { name: 'mono', hex: '#000000', variant: 'monochrome', gate: 'premium' },
|
|
131
160
|
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The three gate groups, DERIVED from the presets rather than listed again, so a
|
|
164
|
+
* preset cannot be gated in one place and offered in another. Together they
|
|
165
|
+
* partition {@link APP_COLOR_NAMES} exactly — asserted in
|
|
166
|
+
* `__tests__/color-preset-gates.test.ts`, since a preset silently missing from
|
|
167
|
+
* every group would simply vanish from a picker with no error anywhere.
|
|
168
|
+
*
|
|
169
|
+
* A consumer builds its visible list from these; it must NOT start from
|
|
170
|
+
* `APP_COLOR_NAMES` and add the unlocked ones, which yields the gated presets to
|
|
171
|
+
* everybody and duplicates whatever the viewer did unlock.
|
|
172
|
+
*/
|
|
173
|
+
const namesGatedBy = (gate: ColorPresetGate | undefined): readonly AppColorName[] =>
|
|
174
|
+
APP_COLOR_NAMES.filter((name) => APP_COLOR_PRESETS[name].gate === gate);
|
|
175
|
+
|
|
176
|
+
/** Available to every user, signed in or not. */
|
|
177
|
+
export const FREE_COLOR_NAMES: readonly AppColorName[] = namesGatedBy(undefined);
|
|
178
|
+
|
|
179
|
+
/** Reserved for the account whose brand it is (`oxy`, `faircoin`) — not for sale. */
|
|
180
|
+
export const HANDLE_COLOR_NAMES: readonly AppColorName[] = namesGatedBy('handle');
|
|
181
|
+
|
|
182
|
+
/** Sold with a subscription. */
|
|
183
|
+
export const PREMIUM_COLOR_NAMES: readonly AppColorName[] = namesGatedBy('premium');
|
package/src/theme/index.ts
CHANGED
|
@@ -40,9 +40,11 @@ export type {
|
|
|
40
40
|
export { useNavigationTheme } from './use-navigation-theme';
|
|
41
41
|
export type { NavigationTheme, NavigationThemeFont } from './use-navigation-theme';
|
|
42
42
|
export type { Theme, ThemeColors, ThemeMode, ThemeGradient, ThemeGradients } from './types';
|
|
43
|
-
export type { AppColorName, AppColorPreset, PresetTokens } from './color-presets';
|
|
43
|
+
export type { AppColorName, AppColorPreset, ColorPresetGate, PresetTokens } from './color-presets';
|
|
44
44
|
export {
|
|
45
45
|
APP_COLOR_NAMES,
|
|
46
|
+
FREE_COLOR_NAMES,
|
|
47
|
+
HANDLE_COLOR_NAMES,
|
|
46
48
|
PREMIUM_COLOR_NAMES,
|
|
47
49
|
APP_COLOR_PRESETS,
|
|
48
50
|
HEX_TO_APP_COLOR,
|