@react-native-rethemed/radix-ui-tokens 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 manato
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # @react-native-rethemed/radix-ui-tokens
2
+
3
+ Radix UI Themes tokens (Radix Colors scales, typography, radii, shadows) for React Native, ready for [react-native-rethemed](https://github.com/manakuro/react-native-rethemed).
4
+
5
+ Radix Themes configured like `<Theme>`: accent / gray scales (12 steps + alpha) for light and dark, panel colors, space, radius, the Text / Heading presets and shadows.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install @react-native-rethemed/core @react-native-rethemed/radix-ui-tokens
11
+ npm install --save-dev @react-native-rethemed/cli
12
+ ```
13
+
14
+ `react` and `react-native` are peer dependencies of `@react-native-rethemed/core`.
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ // src/theme/theme.ts
20
+ import { createRadixUiTheme } from '@react-native-rethemed/radix-ui-tokens';
21
+
22
+ // Like <Theme accentColor="crimson" grayColor="auto" radius="large">
23
+ export const themeConfig = createRadixUiTheme({
24
+ accentColor: 'crimson',
25
+ radius: 'large',
26
+ colors: ['green', 'red'], // extra scales for status colors
27
+ });
28
+
29
+ // themed.view({ backgroundColor: 'accent.9', padding: 3 })
30
+ // themed.text.heading['4']({ color: 'gray.12' })
31
+ ```
32
+
33
+ Then generate the typed bindings (and the token reference for AI agents):
34
+
35
+ ```sh
36
+ npx @react-native-rethemed/cli codegen src/theme/theme.ts --docs docs/themed.md
37
+ ```
38
+
39
+ and use them in components:
40
+
41
+ ```tsx
42
+ import { useThemed } from './theme/themed.gen';
43
+
44
+ const { themed } = useThemed();
45
+ ```
46
+
47
+ See the [main README](https://github.com/manakuro/react-native-rethemed#readme) for the full setup (`ThemedProvider`, color mode, `extendTheme`).
48
+
49
+ ## Exports
50
+
51
+ | Export | Description |
52
+ | --- | --- |
53
+ | `createRadixUiTheme(options)` | Builds a theme from `accentColor`, `grayColor`, `radius`, `scaling` and extra `colors` |
54
+ | `radixUiTheme` | `createRadixUiTheme()` with Radix's defaults |
55
+ | `getMatchingGrayColor(accent)` | The gray `grayColor: 'auto'` picks |
56
+ | `scales` | Every Radix color scale |
57
+ | `fontWeights` | Font weights |
58
+
59
+ [`example/`](https://github.com/manakuro/react-native-rethemed/tree/main/packages/react-native-rethemed/radix-ui/example) shows what the CLI generates for `radixUiTheme` (`themed.gen.ts`, `themed.md`).
60
+
61
+ ## License
62
+
63
+ MIT. Token values are converted from [Radix Themes](https://github.com/radix-ui/themes) (MIT).
@@ -0,0 +1,2 @@
1
+ export { type AccentColor, createRadixUiTheme, type GrayColor, getMatchingGrayColor, type Radius, type RadixUiThemeOptions, radixUiTheme, type ScaleName, type Scaling, } from './theme';
2
+ export { fontWeights, scales } from './tokens.gen';
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scales = exports.fontWeights = exports.radixUiTheme = exports.getMatchingGrayColor = exports.createRadixUiTheme = void 0;
4
+ var theme_1 = require("./theme");
5
+ Object.defineProperty(exports, "createRadixUiTheme", { enumerable: true, get: function () { return theme_1.createRadixUiTheme; } });
6
+ Object.defineProperty(exports, "getMatchingGrayColor", { enumerable: true, get: function () { return theme_1.getMatchingGrayColor; } });
7
+ Object.defineProperty(exports, "radixUiTheme", { enumerable: true, get: function () { return theme_1.radixUiTheme; } });
8
+ var tokens_gen_1 = require("./tokens.gen");
9
+ Object.defineProperty(exports, "fontWeights", { enumerable: true, get: function () { return tokens_gen_1.fontWeights; } });
10
+ Object.defineProperty(exports, "scales", { enumerable: true, get: function () { return tokens_gen_1.scales; } });
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,53 @@
1
+ import { type ThemeConfig } from '@react-native-rethemed/core/config';
2
+ import { radiusFactors, scales, scalings } from './tokens.gen';
3
+ /** Every Radix color scale. */
4
+ export type ScaleName = keyof typeof scales;
5
+ /** `<Theme accentColor>`: every scale except the five tinted grays. */
6
+ export type AccentColor = Exclude<ScaleName, 'mauve' | 'slate' | 'sage' | 'olive' | 'sand'>;
7
+ /** `<Theme grayColor>`. `auto` picks the gray that matches the accent. */
8
+ export type GrayColor = 'auto' | Extract<ScaleName, 'gray' | 'mauve' | 'slate' | 'sage' | 'olive' | 'sand'>;
9
+ export type Radius = keyof typeof radiusFactors;
10
+ export type Scaling = keyof typeof scalings;
11
+ export type RadixUiThemeOptions = {
12
+ /** Default `indigo`. */
13
+ accentColor?: AccentColor;
14
+ /** Default `auto`. */
15
+ grayColor?: GrayColor;
16
+ /** Default `medium`. */
17
+ radius?: Radius;
18
+ /** Default `100%`. */
19
+ scaling?: Scaling;
20
+ /**
21
+ * More scales to use by name (`'red.9'`, `'green.a3'`), e.g. for status
22
+ * colors. `accent`, `gray` and `color` are always included; every scale
23
+ * would add ~870 colors to the generated types, so pick what you use.
24
+ */
25
+ colors?: Exclude<ScaleName, 'gray'>[];
26
+ };
27
+ /**
28
+ * The gray `grayColor: 'auto'` picks for an accent, as Radix Themes'
29
+ * `getMatchingGrayColor` does.
30
+ */
31
+ export declare function getMatchingGrayColor(accentColor: AccentColor): Exclude<GrayColor, 'auto'>;
32
+ /**
33
+ * A Radix Themes theme, configured like `<Theme>`:
34
+ *
35
+ * ```ts
36
+ * createRadixUiTheme({ accentColor: 'blue', radius: 'large', colors: ['red'] })
37
+ * ```
38
+ *
39
+ * - `semanticTokens.colors`: `accent` and `gray` (each `1`–`12`, `a1`–`a12`,
40
+ * `contrast`, `surface`, `indicator`, `track`), `color` (`background`,
41
+ * `panel-solid`, `panel-translucent`, `surface`, `overlay`), plus the
42
+ * scales in `colors`. Every one switches with light/dark.
43
+ * - `spacing` (`1`–`9`), `fontSizes` (`1`–`9`) and `radii` (`1`–`6`,
44
+ * `full`) follow `scaling` and `radius`.
45
+ * - Text presets: `themed.text.text[3]()` is `<Text size="3">` and
46
+ * `themed.text.heading[3]()` is `<Heading size="3">` (bold, tighter line
47
+ * height), both with Radix's letter spacing.
48
+ * - `shadows` `2`–`6`: one layer each, light-mode values; `1` is inset and
49
+ * left out.
50
+ */
51
+ export declare function createRadixUiTheme(options?: RadixUiThemeOptions): ThemeConfig;
52
+ /** Radix Themes' defaults: `indigo` accent, `slate` gray, `medium` radius, `100%` scaling. */
53
+ export declare const radixUiTheme: ThemeConfig;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.radixUiTheme = void 0;
4
+ exports.getMatchingGrayColor = getMatchingGrayColor;
5
+ exports.createRadixUiTheme = createRadixUiTheme;
6
+ const config_1 = require("@react-native-rethemed/core/config");
7
+ const tokens_gen_1 = require("./tokens.gen");
8
+ /**
9
+ * The gray `grayColor: 'auto'` picks for an accent, as Radix Themes'
10
+ * `getMatchingGrayColor` does.
11
+ */
12
+ function getMatchingGrayColor(accentColor) {
13
+ switch (accentColor) {
14
+ case 'tomato':
15
+ case 'red':
16
+ case 'ruby':
17
+ case 'crimson':
18
+ case 'pink':
19
+ case 'plum':
20
+ case 'purple':
21
+ case 'violet':
22
+ return 'mauve';
23
+ case 'iris':
24
+ case 'indigo':
25
+ case 'blue':
26
+ case 'sky':
27
+ case 'cyan':
28
+ return 'slate';
29
+ case 'teal':
30
+ case 'jade':
31
+ case 'mint':
32
+ case 'green':
33
+ return 'sage';
34
+ case 'grass':
35
+ case 'lime':
36
+ return 'olive';
37
+ case 'yellow':
38
+ case 'amber':
39
+ case 'orange':
40
+ case 'brown':
41
+ case 'gold':
42
+ case 'bronze':
43
+ return 'sand';
44
+ case 'gray':
45
+ return 'gray';
46
+ }
47
+ }
48
+ const round = (n, digits = 2) => {
49
+ const factor = 10 ** digits;
50
+ return Math.round(n * factor) / factor;
51
+ };
52
+ const scaled = (table, factor) => Object.fromEntries(Object.entries(table).map(([key, value]) => [key, round(value * factor)]));
53
+ /** `'gray.a2'` → that step of the theme's gray in `scheme`; hex as-is. */
54
+ function grayRef(value, gray, scheme) {
55
+ return value.startsWith('gray.') ? gray[value.slice(5)][scheme] : value;
56
+ }
57
+ /** `#rrggbbaa` → `{ color: '#rrggbb', opacity }`. */
58
+ function splitAlpha(hex) {
59
+ if (hex.length !== 9)
60
+ return { color: hex, opacity: 1 };
61
+ return {
62
+ color: hex.slice(0, 7),
63
+ opacity: round(Number.parseInt(hex.slice(7), 16) / 255, 3),
64
+ };
65
+ }
66
+ /** Android elevation per shadow level; CSS has none, so picked by hand. */
67
+ const SHADOW_ELEVATIONS = {
68
+ 2: 2,
69
+ 3: 4,
70
+ 4: 8,
71
+ 5: 12,
72
+ 6: 16,
73
+ };
74
+ /**
75
+ * A Radix Themes theme, configured like `<Theme>`:
76
+ *
77
+ * ```ts
78
+ * createRadixUiTheme({ accentColor: 'blue', radius: 'large', colors: ['red'] })
79
+ * ```
80
+ *
81
+ * - `semanticTokens.colors`: `accent` and `gray` (each `1`–`12`, `a1`–`a12`,
82
+ * `contrast`, `surface`, `indicator`, `track`), `color` (`background`,
83
+ * `panel-solid`, `panel-translucent`, `surface`, `overlay`), plus the
84
+ * scales in `colors`. Every one switches with light/dark.
85
+ * - `spacing` (`1`–`9`), `fontSizes` (`1`–`9`) and `radii` (`1`–`6`,
86
+ * `full`) follow `scaling` and `radius`.
87
+ * - Text presets: `themed.text.text[3]()` is `<Text size="3">` and
88
+ * `themed.text.heading[3]()` is `<Heading size="3">` (bold, tighter line
89
+ * height), both with Radix's letter spacing.
90
+ * - `shadows` `2`–`6`: one layer each, light-mode values; `1` is inset and
91
+ * left out.
92
+ */
93
+ function createRadixUiTheme(options = {}) {
94
+ const { accentColor = 'indigo', grayColor = 'auto', radius = 'medium', scaling = '100%', colors = [], } = options;
95
+ const factor = tokens_gen_1.scalings[scaling];
96
+ const gray = tokens_gen_1.scales[grayColor === 'auto' ? getMatchingGrayColor(accentColor) : grayColor];
97
+ const sizes = tokens_gen_1.fontSizes;
98
+ const spacingsEm = tokens_gen_1.letterSpacings;
99
+ const preset = (size, lineHeight, extraEm = 0) => {
100
+ const fontSize = round(sizes[size] * factor);
101
+ return {
102
+ fontSize,
103
+ lineHeight: round(lineHeight * factor),
104
+ letterSpacing: round((spacingsEm[size] + extraEm) * fontSize, 3),
105
+ };
106
+ };
107
+ return (0, config_1.defineTheme)({
108
+ tokens: {
109
+ spacing: scaled(tokens_gen_1.space, factor),
110
+ radii: {
111
+ ...scaled(tokens_gen_1.radii, factor * tokens_gen_1.radiusFactors[radius]),
112
+ full: tokens_gen_1.radiusFull[radius],
113
+ },
114
+ fontSizes: scaled(tokens_gen_1.fontSizes, factor),
115
+ fontWeights: tokens_gen_1.fontWeights,
116
+ shadows: Object.fromEntries(Object.entries(tokens_gen_1.shadows).map(([key, layer]) => {
117
+ const { color, opacity } = splitAlpha(grayRef(layer.color, gray, 'light'));
118
+ return [
119
+ key,
120
+ {
121
+ shadowColor: color,
122
+ shadowOffset: { width: layer.x, height: layer.y },
123
+ shadowOpacity: opacity,
124
+ shadowRadius: layer.blur / 2,
125
+ elevation: SHADOW_ELEVATIONS[key],
126
+ },
127
+ ];
128
+ })),
129
+ },
130
+ semanticTokens: {
131
+ colors: {
132
+ accent: tokens_gen_1.scales[accentColor],
133
+ gray,
134
+ color: Object.fromEntries(Object.entries(tokens_gen_1.backgroundColors).map(([key, value]) => [
135
+ key,
136
+ {
137
+ light: grayRef(value.light, gray, 'light'),
138
+ dark: grayRef(value.dark, gray, 'dark'),
139
+ },
140
+ ])),
141
+ ...Object.fromEntries(colors.map((name) => [name, tokens_gen_1.scales[name]])),
142
+ },
143
+ text: {
144
+ text: Object.fromEntries(Object.entries(tokens_gen_1.lineHeights).map(([size, lineHeight]) => [
145
+ size,
146
+ preset(size, lineHeight),
147
+ ])),
148
+ heading: Object.fromEntries(Object.entries(tokens_gen_1.headingLineHeights).map(([size, lineHeight]) => [
149
+ size,
150
+ {
151
+ ...preset(size, lineHeight, tokens_gen_1.headingLetterSpacing),
152
+ fontWeight: 'bold',
153
+ },
154
+ ])),
155
+ },
156
+ },
157
+ defaults: { fontSize: '3' },
158
+ });
159
+ }
160
+ /** Radix Themes' defaults: `indigo` accent, `slate` gray, `medium` radius, `100%` scaling. */
161
+ exports.radixUiTheme = createRadixUiTheme();