@pickle-ui/react 1.0.0-beta.7 → 1.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -10
- package/dist/components/Alert.d.ts +4 -6
- package/dist/components/Alert.d.ts.map +1 -1
- package/dist/components/Alert.js +4 -6
- package/dist/components/Alert.js.map +1 -1
- package/dist/components/_internal/VisuallyHiddenInput.d.ts.map +1 -1
- package/dist/components/_internal/VisuallyHiddenInput.js +24 -42
- package/dist/components/_internal/VisuallyHiddenInput.js.map +1 -1
- package/dist/components/form/Form.context.d.ts.map +1 -1
- package/dist/components/form/Form.context.js +2 -3
- package/dist/components/form/Form.context.js.map +1 -1
- package/dist/components/form/FormField.js +2 -2
- package/dist/components/form/FormField.js.map +1 -1
- package/dist/components/form/Input.d.ts.map +1 -1
- package/dist/components/form/Input.js +22 -7
- package/dist/components/form/Input.js.map +1 -1
- package/dist/components/form/Slider.d.ts +1 -1
- package/dist/components/form/Slider.d.ts.map +1 -1
- package/dist/entries/theme.d.ts +2 -2
- package/dist/entries/theme.d.ts.map +1 -1
- package/dist/entries/theme.js +1 -1
- package/dist/entries/theme.js.map +1 -1
- package/dist/hooks/use-lazy-ref.d.ts.map +1 -1
- package/dist/hooks/use-lazy-ref.js +3 -4
- package/dist/hooks/use-lazy-ref.js.map +1 -1
- package/dist/lib/compose-refs.d.ts +0 -8
- package/dist/lib/compose-refs.d.ts.map +1 -1
- package/dist/lib/compose-refs.js +6 -19
- package/dist/lib/compose-refs.js.map +1 -1
- package/package.json +3 -3
- package/src/base.css +7 -25
- package/src/components/Alert.tsx +4 -6
- package/src/components/_internal/VisuallyHiddenInput.tsx +33 -51
- package/src/components/form/ColorPickerPrimitive.tsx +1 -1
- package/src/components/form/Form.context.ts +2 -3
- package/src/components/form/FormField.tsx +2 -2
- package/src/components/form/Input.tsx +65 -28
- package/src/components/form/RadioGroup.test.tsx +1 -3
- package/src/components/form/Slider.tsx +1 -1
- package/src/entries/theme.ts +2 -2
- package/src/hooks/use-lazy-ref.ts +3 -5
- package/src/lib/color.test.ts +1 -3
- package/src/lib/compose-refs.ts +7 -19
- package/dist/lib/theme.d.ts +0 -40
- package/dist/lib/theme.d.ts.map +0 -1
- package/dist/lib/theme.js +0 -82
- package/dist/lib/theme.js.map +0 -1
- package/src/lib/theme.test.ts +0 -64
- package/src/lib/theme.ts +0 -143
package/src/lib/theme.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Theme generator: derives Pickle's brand-dependent tokens from a single
|
|
3
|
-
* primary color so consumers can theme the library without hand-writing CSS
|
|
4
|
-
* variables. Tokens that do not depend on the brand (neutrals, status colors)
|
|
5
|
-
* keep the values from `@pickle-ui/react/theme.css`.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
clampChroma,
|
|
10
|
-
converter,
|
|
11
|
-
formatCss,
|
|
12
|
-
type Oklch,
|
|
13
|
-
parse,
|
|
14
|
-
wcagContrast,
|
|
15
|
-
} from 'culori';
|
|
16
|
-
|
|
17
|
-
type Theme = {
|
|
18
|
-
dark: ThemeVariables;
|
|
19
|
-
light: ThemeVariables;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
type ThemeCssOptions = {
|
|
23
|
-
darkSelector?: string;
|
|
24
|
-
lightSelector?: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type ThemeFonts = {
|
|
28
|
-
heading?: string;
|
|
29
|
-
mono?: string;
|
|
30
|
-
sans?: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
type ThemeOptions = {
|
|
34
|
-
/** Font stacks, written to `--font-sans`, `--font-heading` and `--font-mono`. */
|
|
35
|
-
fonts?: ThemeFonts;
|
|
36
|
-
/** Brand color in any CSS notation (hex, rgb, hsl, oklch, …). */
|
|
37
|
-
primary: string;
|
|
38
|
-
/** Brand color for the dark scheme. Defaults to a lighter version of `primary`. */
|
|
39
|
-
primaryDark?: string;
|
|
40
|
-
/** Base radius, e.g. `'0.5rem'`. Every `rounded-*` scale derives from it. */
|
|
41
|
-
radius?: string;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
type ThemeVariables = Record<`--${string}`, string>;
|
|
45
|
-
|
|
46
|
-
const toOklch = converter('oklch');
|
|
47
|
-
|
|
48
|
-
const LIGHT_FOREGROUND: Oklch = { c: 0, h: 0, l: 1, mode: 'oklch' };
|
|
49
|
-
const DARK_FOREGROUND: Oklch = { c: 0.006, h: 285.9, l: 0.21, mode: 'oklch' };
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Build the light and dark token sets for a brand color. Apply the result
|
|
53
|
-
* with `themeToCss` in a stylesheet, or spread `theme.light` / `theme.dark`
|
|
54
|
-
* as the `style` of a wrapper element.
|
|
55
|
-
*/
|
|
56
|
-
export function createTheme(options: ThemeOptions): Theme {
|
|
57
|
-
const primary = parseColor(options.primary, 'primary');
|
|
58
|
-
const primaryDark = options.primaryDark
|
|
59
|
-
? parseColor(options.primaryDark, 'primaryDark')
|
|
60
|
-
: lightenForDark(primary);
|
|
61
|
-
const shared = sharedVariables(options);
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
dark: { ...shared, ...brandVariables(primaryDark) },
|
|
65
|
-
light: { ...shared, ...brandVariables(primary) },
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Serialize a theme as CSS rules for the light and dark selectors. */
|
|
70
|
-
export function themeToCss(
|
|
71
|
-
theme: Theme,
|
|
72
|
-
{ darkSelector = '.dark', lightSelector = ':root' }: ThemeCssOptions = {},
|
|
73
|
-
): string {
|
|
74
|
-
const block = (selector: string, variables: ThemeVariables) =>
|
|
75
|
-
`${selector} {\n${Object.entries(variables)
|
|
76
|
-
.map(([name, value]) => ` ${name}: ${value};`)
|
|
77
|
-
.join('\n')}\n}`;
|
|
78
|
-
|
|
79
|
-
return `${block(lightSelector, theme.light)}\n\n${block(darkSelector, theme.dark)}\n`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function brandVariables(primary: Oklch): ThemeVariables {
|
|
83
|
-
const foreground = foregroundFor(primary);
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
'--primary': format(primary),
|
|
87
|
-
'--primary-foreground': format(foreground),
|
|
88
|
-
'--ring': format({ ...primary, c: primary.c * 0.6 }),
|
|
89
|
-
'--sidebar-primary': format(primary),
|
|
90
|
-
'--sidebar-primary-foreground': format(foreground),
|
|
91
|
-
'--sidebar-ring': format({ ...primary, c: primary.c * 0.6 }),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** White or near-black, whichever reads better on the given fill. */
|
|
96
|
-
function foregroundFor(fill: Oklch) {
|
|
97
|
-
return wcagContrast(fill, LIGHT_FOREGROUND) >=
|
|
98
|
-
wcagContrast(fill, DARK_FOREGROUND)
|
|
99
|
-
? LIGHT_FOREGROUND
|
|
100
|
-
: DARK_FOREGROUND;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function format(color: Oklch) {
|
|
104
|
-
return formatCss(clampChroma(color, 'oklch'));
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Lift a brand color so it stays vivid on dark surfaces. */
|
|
108
|
-
function lightenForDark(color: Oklch): Oklch {
|
|
109
|
-
return {
|
|
110
|
-
...color,
|
|
111
|
-
c: color.c * 0.92,
|
|
112
|
-
l: Math.min(Math.max(color.l + 0.12, 0.6), 0.85),
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function parseColor(value: string, name: string): Oklch {
|
|
117
|
-
const color = parse(value);
|
|
118
|
-
|
|
119
|
-
if (!color) {
|
|
120
|
-
throw new Error(`createTheme: ${name} is not a valid CSS color: ${value}`);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return toOklch(color);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function sharedVariables({ fonts, radius }: ThemeOptions): ThemeVariables {
|
|
127
|
-
const variables: ThemeVariables = {};
|
|
128
|
-
|
|
129
|
-
if (radius) variables['--radius'] = radius;
|
|
130
|
-
if (fonts?.sans) variables['--font-sans'] = fonts.sans;
|
|
131
|
-
if (fonts?.heading) variables['--font-heading'] = fonts.heading;
|
|
132
|
-
if (fonts?.mono) variables['--font-mono'] = fonts.mono;
|
|
133
|
-
|
|
134
|
-
return variables;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export type {
|
|
138
|
-
Theme,
|
|
139
|
-
ThemeCssOptions,
|
|
140
|
-
ThemeFonts,
|
|
141
|
-
ThemeOptions,
|
|
142
|
-
ThemeVariables,
|
|
143
|
-
};
|