@react-native-rethemed/core 0.1.0 → 0.1.2

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.
Files changed (104) hide show
  1. package/README.md +2 -0
  2. package/dist/color-mode-store.cjs +57 -0
  3. package/dist/color-mode-store.d.cts +11 -0
  4. package/dist/color-mode-store.d.mts +11 -0
  5. package/dist/color-mode-store.mjs +56 -0
  6. package/dist/config.cjs +26 -0
  7. package/dist/config.d.cts +8 -0
  8. package/dist/config.d.mts +8 -0
  9. package/dist/config.mjs +7 -0
  10. package/dist/create-themed-styles.cjs +31 -0
  11. package/dist/{esm/create-themed-styles.d.ts → create-themed-styles.d.cts} +4 -2
  12. package/dist/{cjs/create-themed-styles.d.ts → create-themed-styles.d.mts} +4 -2
  13. package/dist/create-themed-styles.mjs +31 -0
  14. package/dist/create-themed.cjs +93 -0
  15. package/dist/create-themed.d.cts +48 -0
  16. package/dist/create-themed.d.mts +48 -0
  17. package/dist/create-themed.mjs +93 -0
  18. package/dist/define-theme.cjs +15 -0
  19. package/dist/{esm/define-theme.d.ts → define-theme.d.cts} +3 -1
  20. package/dist/{cjs/define-theme.d.ts → define-theme.d.mts} +3 -1
  21. package/dist/define-theme.mjs +15 -0
  22. package/dist/extend-theme.cjs +109 -0
  23. package/dist/{esm/extend-theme.d.ts → extend-theme.d.cts} +3 -1
  24. package/dist/{cjs/extend-theme.d.ts → extend-theme.d.mts} +3 -1
  25. package/dist/extend-theme.mjs +109 -0
  26. package/dist/index.cjs +30 -0
  27. package/dist/index.d.cts +13 -0
  28. package/dist/index.d.mts +13 -0
  29. package/dist/index.mjs +9 -0
  30. package/dist/resolvers/color-resolver.cjs +23 -0
  31. package/dist/resolvers/color-resolver.d.cts +4 -0
  32. package/dist/resolvers/color-resolver.d.mts +4 -0
  33. package/dist/resolvers/color-resolver.mjs +23 -0
  34. package/dist/resolvers/line-height-resolver.cjs +17 -0
  35. package/dist/{esm/resolvers/line-height-resolver.d.ts → resolvers/line-height-resolver.d.cts} +3 -1
  36. package/dist/{cjs/resolvers/line-height-resolver.d.ts → resolvers/line-height-resolver.d.mts} +3 -1
  37. package/dist/resolvers/line-height-resolver.mjs +16 -0
  38. package/dist/resolvers/style-resolver.cjs +86 -0
  39. package/dist/resolvers/style-resolver.mjs +86 -0
  40. package/dist/semantic-colors.cjs +29 -0
  41. package/dist/{esm/semantic-colors.d.ts → semantic-colors.d.cts} +3 -1
  42. package/dist/{cjs/semantic-colors.d.ts → semantic-colors.d.mts} +3 -1
  43. package/dist/semantic-colors.mjs +28 -0
  44. package/dist/style-props.cjs +103 -0
  45. package/dist/{cjs/style-props.d.ts → style-props.d.cts} +2 -1
  46. package/dist/{esm/style-props.d.ts → style-props.d.mts} +2 -1
  47. package/dist/style-props.mjs +95 -0
  48. package/dist/text-tree.cjs +70 -0
  49. package/dist/{cjs/text-tree.d.ts → text-tree.d.cts} +4 -8
  50. package/dist/{esm/text-tree.d.ts → text-tree.d.mts} +4 -8
  51. package/dist/text-tree.mjs +66 -0
  52. package/dist/text-variants.cjs +25 -0
  53. package/dist/text-variants.mjs +25 -0
  54. package/dist/types.d.cts +280 -0
  55. package/dist/types.d.mts +280 -0
  56. package/package.json +17 -25
  57. package/dist/cjs/color-mode-store.d.ts +0 -32
  58. package/dist/cjs/color-mode-store.js +0 -64
  59. package/dist/cjs/config.d.ts +0 -14
  60. package/dist/cjs/config.js +0 -35
  61. package/dist/cjs/create-themed-styles.js +0 -37
  62. package/dist/cjs/create-themed.d.ts +0 -46
  63. package/dist/cjs/create-themed.js +0 -118
  64. package/dist/cjs/define-theme.js +0 -15
  65. package/dist/cjs/extend-theme.js +0 -118
  66. package/dist/cjs/index.d.ts +0 -4
  67. package/dist/cjs/index.js +0 -22
  68. package/dist/cjs/package.json +0 -1
  69. package/dist/cjs/resolvers/color-resolver.d.ts +0 -10
  70. package/dist/cjs/resolvers/color-resolver.js +0 -26
  71. package/dist/cjs/resolvers/line-height-resolver.js +0 -20
  72. package/dist/cjs/resolvers/style-resolver.d.ts +0 -21
  73. package/dist/cjs/resolvers/style-resolver.js +0 -104
  74. package/dist/cjs/semantic-colors.js +0 -32
  75. package/dist/cjs/style-props.js +0 -95
  76. package/dist/cjs/text-tree.js +0 -79
  77. package/dist/cjs/text-variants.d.ts +0 -22
  78. package/dist/cjs/text-variants.js +0 -29
  79. package/dist/cjs/types.d.ts +0 -281
  80. package/dist/cjs/types.js +0 -2
  81. package/dist/esm/color-mode-store.d.ts +0 -32
  82. package/dist/esm/color-mode-store.js +0 -59
  83. package/dist/esm/config.d.ts +0 -14
  84. package/dist/esm/config.js +0 -13
  85. package/dist/esm/create-themed-styles.js +0 -34
  86. package/dist/esm/create-themed.d.ts +0 -46
  87. package/dist/esm/create-themed.js +0 -115
  88. package/dist/esm/define-theme.js +0 -12
  89. package/dist/esm/extend-theme.js +0 -115
  90. package/dist/esm/index.d.ts +0 -4
  91. package/dist/esm/index.js +0 -3
  92. package/dist/esm/package.json +0 -1
  93. package/dist/esm/resolvers/color-resolver.d.ts +0 -10
  94. package/dist/esm/resolvers/color-resolver.js +0 -23
  95. package/dist/esm/resolvers/line-height-resolver.js +0 -16
  96. package/dist/esm/resolvers/style-resolver.d.ts +0 -21
  97. package/dist/esm/resolvers/style-resolver.js +0 -101
  98. package/dist/esm/semantic-colors.js +0 -28
  99. package/dist/esm/style-props.js +0 -92
  100. package/dist/esm/text-tree.js +0 -72
  101. package/dist/esm/text-variants.d.ts +0 -22
  102. package/dist/esm/text-variants.js +0 -26
  103. package/dist/esm/types.d.ts +0 -281
  104. package/dist/esm/types.js +0 -1
@@ -1,104 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createStyleResolver = createStyleResolver;
4
- const semantic_colors_1 = require("../semantic-colors");
5
- const style_props_1 = require("../style-props");
6
- const line_height_resolver_1 = require("./line-height-resolver");
7
- /** Avoids float noise like `17.600000000000001` without pixel-snapping. */
8
- const round2 = (value) => Math.round(value * 100) / 100;
9
- const hasToken = (table, value) => (typeof value === 'string' || typeof value === 'number') &&
10
- Object.hasOwn(table, value);
11
- /**
12
- * Builds the resolver behind `themed.view()` / `text()` / `image()` for one
13
- * color scheme.
14
- *
15
- * Everything that doesn't depend on the input is done once here: a single
16
- * **prop → token table** lookup (`backgroundColor` → the primitive
17
- * `tokens.colors` plus the flattened `'group.token'` semantic colors for this
18
- * scheme, `padding` → `tokens.spacing`, …).
19
- * Each call then makes **one pass over the input's own keys** (usually a
20
- * handful), rather than scanning every token-aware prop name, and copies the
21
- * input at most once — or not at all when nothing is a token.
22
- *
23
- * Two props need the rest of the style, so they are applied after the pass:
24
- * - `lineHeight` tokens are ratios of the (resolved) `fontSize`, falling back
25
- * to `defaults.fontSize`;
26
- * - the virtual `shadow` prop expands last, so a preset wins over explicit
27
- * `shadow*` props, and the `shadow` key itself is removed.
28
- */
29
- function createStyleResolver(config, scheme) {
30
- const tokens = config.tokens ?? {};
31
- const byProp = Object.create(null);
32
- const register = (props, table) => {
33
- if (!table)
34
- return;
35
- for (const prop of props)
36
- byProp[prop] = table;
37
- };
38
- // Color props take both kinds of color token. Primitives (`'red.500'`)
39
- // go in first, so a semantic color with the same name wins (the CLI warns
40
- // about such collisions).
41
- const colors = { ...tokens.colors };
42
- (0, semantic_colors_1.walkSemanticColors)(config.semanticTokens?.colors, (token, color) => {
43
- colors[token] = color[scheme];
44
- });
45
- if (tokens.colors || config.semanticTokens?.colors) {
46
- register(style_props_1.COLOR_KEYS, colors);
47
- }
48
- register(style_props_1.RADIUS_KEYS, tokens.radii);
49
- register(style_props_1.SPACING_KEYS, tokens.spacing);
50
- register(style_props_1.FONT_SIZE_KEYS, tokens.fontSizes);
51
- register(style_props_1.FONT_WEIGHT_KEYS, tokens.fontWeights);
52
- register(style_props_1.LETTER_SPACING_KEYS, tokens.letterSpacings);
53
- register(style_props_1.Z_INDEX_KEYS, tokens.zIndices);
54
- const lineHeights = tokens.lineHeights;
55
- const shadows = tokens.shadows;
56
- const baseFontSize = (0, line_height_resolver_1.resolveBaseFontSize)(config);
57
- return function resolveStyle(input) {
58
- const source = input;
59
- let result = null;
60
- let lineHeightRatio;
61
- let shadowPreset;
62
- let hasShadow = false;
63
- for (const key in source) {
64
- const value = source[key];
65
- if (key === 'lineHeight') {
66
- if (lineHeights && hasToken(lineHeights, value)) {
67
- lineHeightRatio = lineHeights[value];
68
- }
69
- continue;
70
- }
71
- if (key === 'shadow') {
72
- if (shadows) {
73
- hasShadow = true;
74
- shadowPreset = hasToken(shadows, value)
75
- ? shadows[value]
76
- : undefined;
77
- }
78
- continue;
79
- }
80
- const table = byProp[key];
81
- if (table === undefined || !hasToken(table, value))
82
- continue;
83
- result ??= { ...source };
84
- result[key] = table[value];
85
- }
86
- if (lineHeightRatio !== undefined) {
87
- result ??= { ...source };
88
- const fontSize = typeof result.fontSize === 'number' ? result.fontSize : baseFontSize;
89
- result.lineHeight = round2(fontSize * lineHeightRatio);
90
- }
91
- if (hasShadow) {
92
- // Rebuild without `shadow` instead of `delete`, which would push the
93
- // object into V8/Hermes' slow dictionary mode.
94
- const base = result ?? source;
95
- const expanded = {};
96
- for (const key in base) {
97
- if (key !== 'shadow')
98
- expanded[key] = base[key];
99
- }
100
- result = shadowPreset ? Object.assign(expanded, shadowPreset) : expanded;
101
- }
102
- return result ?? source;
103
- };
104
- }
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isSchemeColor = isSchemeColor;
4
- exports.walkSemanticColors = walkSemanticColors;
5
- /**
6
- * A color of `semanticTokens.colors` (as opposed to a group of them): an
7
- * object whose `light` or `dark` is a string. A group's values are objects,
8
- * so a group may still name a token `light` or `dark` (Material UI's
9
- * `primary.light`).
10
- */
11
- function isSchemeColor(node) {
12
- if (typeof node !== 'object' || node === null)
13
- return false;
14
- const { light, dark } = node;
15
- return typeof light === 'string' || typeof dark === 'string';
16
- }
17
- /**
18
- * Visits every semantic color in definition order with its token name:
19
- * `'group.token'` inside a group, or the bare name for a top-level color
20
- * (`'primary'`, `'primary-foreground'`).
21
- */
22
- function walkSemanticColors(colors, visit) {
23
- for (const [key, node] of Object.entries(colors ?? {})) {
24
- if (isSchemeColor(node)) {
25
- visit(key, node, undefined);
26
- continue;
27
- }
28
- for (const [name, color] of Object.entries(node)) {
29
- visit(`${key}.${name}`, color, key);
30
- }
31
- }
32
- }
@@ -1,95 +0,0 @@
1
- "use strict";
2
- /**
3
- * The RN style property names each token category resolves, grouped by
4
- * category. Kept as `const` arrays (not just types) because the resolvers
5
- * need to iterate them at runtime.
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.SHADOW_STYLE_PROPS = exports.Z_INDEX_KEYS = exports.LETTER_SPACING_KEYS = exports.LINE_HEIGHT_KEYS = exports.FONT_WEIGHT_KEYS = exports.FONT_SIZE_KEYS = exports.SPACING_KEYS = exports.RADIUS_KEYS = exports.COLOR_KEYS = void 0;
9
- exports.COLOR_KEYS = [
10
- 'color',
11
- 'backgroundColor',
12
- 'borderColor',
13
- 'borderTopColor',
14
- 'borderBottomColor',
15
- 'borderLeftColor',
16
- 'borderRightColor',
17
- 'borderStartColor',
18
- 'borderEndColor',
19
- 'borderBlockColor',
20
- 'borderBlockStartColor',
21
- 'borderBlockEndColor',
22
- 'tintColor',
23
- 'overlayColor',
24
- 'shadowColor',
25
- 'outlineColor',
26
- 'textShadowColor',
27
- 'textDecorationColor',
28
- ];
29
- exports.RADIUS_KEYS = [
30
- 'borderRadius',
31
- 'borderTopLeftRadius',
32
- 'borderTopRightRadius',
33
- 'borderTopStartRadius',
34
- 'borderTopEndRadius',
35
- 'borderBottomLeftRadius',
36
- 'borderBottomRightRadius',
37
- 'borderBottomStartRadius',
38
- 'borderBottomEndRadius',
39
- 'borderStartStartRadius',
40
- 'borderStartEndRadius',
41
- 'borderEndStartRadius',
42
- 'borderEndEndRadius',
43
- ];
44
- exports.SPACING_KEYS = [
45
- 'padding',
46
- 'paddingTop',
47
- 'paddingBottom',
48
- 'paddingLeft',
49
- 'paddingRight',
50
- 'paddingHorizontal',
51
- 'paddingVertical',
52
- 'paddingStart',
53
- 'paddingEnd',
54
- 'paddingBlock',
55
- 'paddingBlockStart',
56
- 'paddingBlockEnd',
57
- 'paddingInline',
58
- 'paddingInlineStart',
59
- 'paddingInlineEnd',
60
- 'margin',
61
- 'marginTop',
62
- 'marginBottom',
63
- 'marginLeft',
64
- 'marginRight',
65
- 'marginHorizontal',
66
- 'marginVertical',
67
- 'marginStart',
68
- 'marginEnd',
69
- 'marginBlock',
70
- 'marginBlockStart',
71
- 'marginBlockEnd',
72
- 'marginInline',
73
- 'marginInlineStart',
74
- 'marginInlineEnd',
75
- 'gap',
76
- 'rowGap',
77
- 'columnGap',
78
- ];
79
- exports.FONT_SIZE_KEYS = ['fontSize'];
80
- exports.FONT_WEIGHT_KEYS = ['fontWeight'];
81
- exports.LINE_HEIGHT_KEYS = ['lineHeight'];
82
- exports.LETTER_SPACING_KEYS = ['letterSpacing'];
83
- /** Token or raw number, like the typography props. */
84
- exports.Z_INDEX_KEYS = ['zIndex'];
85
- /**
86
- * The real RN style properties the virtual `shadow` prop expands into.
87
- * Not resolved as a scale category itself — see `resolvers/style-resolver.ts`.
88
- */
89
- exports.SHADOW_STYLE_PROPS = [
90
- 'shadowColor',
91
- 'shadowOffset',
92
- 'shadowOpacity',
93
- 'shadowRadius',
94
- 'elevation',
95
- ];
@@ -1,79 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TEXT_TOKEN_FIELDS = void 0;
4
- exports.isTextPreset = isTextPreset;
5
- exports.resolveTextColor = resolveTextColor;
6
- exports.resolveTextTree = resolveTextTree;
7
- exports.walkTextPresets = walkTextPresets;
8
- /** The fields a `semanticTokens.text` preset (leaf) may have. */
9
- exports.TEXT_TOKEN_FIELDS = [
10
- 'fontSize',
11
- 'lineHeight',
12
- 'letterSpacing',
13
- 'fontWeight',
14
- 'textTransform',
15
- 'color',
16
- ];
17
- const isPrimitive = (value) => typeof value === 'string' || typeof value === 'number';
18
- const isPresetField = (key) => exports.TEXT_TOKEN_FIELDS.includes(key);
19
- /**
20
- * A node of `semanticTokens.text` is a **preset** (leaf) when it has any
21
- * preset field (`fontSize`, …, `color`) or when every value is a primitive,
22
- * and a **group** otherwise (`{ md: {...}, sm: {...} }`). The field check
23
- * matters because `color` may itself be an object (`{ light, dark }`), so
24
- * "all primitives" alone can't tell a preset from a group; preset field
25
- * names are therefore reserved and can't name a group or preset. Mixed
26
- * nodes are rejected by `@react-native-rethemed/cli codegen`.
27
- */
28
- function isTextPreset(node) {
29
- const keys = Object.keys(node);
30
- return keys.some(isPresetField) || Object.values(node).every(isPrimitive);
31
- }
32
- /**
33
- * A preset `color` for one scheme: a string applies to both, an object picks
34
- * `light` / `dark`, and a missing scheme yields `undefined` (no color).
35
- */
36
- function resolveTextColor(color, scheme) {
37
- return typeof color === 'object' && color !== null ? color[scheme] : color;
38
- }
39
- /**
40
- * The text tree with every preset `color` resolved for `scheme`; a preset
41
- * whose color doesn't cover the scheme loses its `color` key. Presets
42
- * without `color` are returned as-is (same object).
43
- */
44
- function resolveTextTree(tree, scheme) {
45
- const result = {};
46
- for (const [key, node] of Object.entries(tree ?? {})) {
47
- if (typeof node !== 'object' || node === null)
48
- continue;
49
- if (!isTextPreset(node)) {
50
- result[key] = resolveTextTree(node, scheme);
51
- }
52
- else if (node.color === undefined) {
53
- result[key] = node;
54
- }
55
- else {
56
- const { color, ...rest } = node;
57
- const resolved = resolveTextColor(color, scheme);
58
- result[key] =
59
- resolved === undefined ? rest : { ...rest, color: resolved };
60
- }
61
- }
62
- return result;
63
- }
64
- /**
65
- * Visits every preset in a text tree, depth-first in definition order,
66
- * with its path (`['heading', 'display', 'lg']`).
67
- */
68
- function walkTextPresets(tree, visit, path = []) {
69
- for (const [key, node] of Object.entries(tree ?? {})) {
70
- if (typeof node !== 'object' || node === null)
71
- continue;
72
- if (isTextPreset(node)) {
73
- visit([...path, key], node);
74
- }
75
- else {
76
- walkTextPresets(node, visit, [...path, key]);
77
- }
78
- }
79
- }
@@ -1,22 +0,0 @@
1
- import type { TextStyle } from 'react-native';
2
- import type { TextTokenTree } from './types';
3
- type TextVariant = (override?: object) => TextStyle;
4
- type TextVariantTree = {
5
- [key: string]: TextVariant | TextVariantTree;
6
- };
7
- /**
8
- * Builds `themed.text.<path>(override?)` by walking whatever tree
9
- * `config.semanticTokens.text` defines, at any depth — no hand-written
10
- * per-variant code. Each preset merges with the caller's override (preset
11
- * first, override wins) and runs through the same `resolve` as
12
- * `themed.text()` itself, so presets referencing scale keys (e.g.
13
- * `fontSize: 'lg'`) resolve exactly like caller-passed tokens.
14
- *
15
- * `tree` must already have its preset colors resolved for the scheme (see
16
- * `resolveTextTree`), so a call only merges and resolves tokens.
17
- *
18
- * Typed loosely on purpose; the exact tree shape comes from the generated
19
- * `themed.gen.ts`.
20
- */
21
- export declare function createTextVariants(tree: TextTokenTree, resolve: (input: object) => TextStyle): TextVariantTree;
22
- export {};
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTextVariants = createTextVariants;
4
- const text_tree_1 = require("./text-tree");
5
- /**
6
- * Builds `themed.text.<path>(override?)` by walking whatever tree
7
- * `config.semanticTokens.text` defines, at any depth — no hand-written
8
- * per-variant code. Each preset merges with the caller's override (preset
9
- * first, override wins) and runs through the same `resolve` as
10
- * `themed.text()` itself, so presets referencing scale keys (e.g.
11
- * `fontSize: 'lg'`) resolve exactly like caller-passed tokens.
12
- *
13
- * `tree` must already have its preset colors resolved for the scheme (see
14
- * `resolveTextTree`), so a call only merges and resolves tokens.
15
- *
16
- * Typed loosely on purpose; the exact tree shape comes from the generated
17
- * `themed.gen.ts`.
18
- */
19
- function createTextVariants(tree, resolve) {
20
- const build = (tree) => Object.fromEntries(Object.entries(tree)
21
- .filter(([, node]) => typeof node === 'object' && node !== null)
22
- .map(([key, node]) => [
23
- key,
24
- (0, text_tree_1.isTextPreset)(node)
25
- ? (override) => resolve({ ...node, ...override })
26
- : build(node),
27
- ]));
28
- return build(tree);
29
- }
@@ -1,281 +0,0 @@
1
- import type { ImageStyle, TextStyle, ViewStyle } from 'react-native';
2
- import type { ColorKeys, FontSizeKeys, FontWeightKeys, LetterSpacingKeys, LineHeightKeys, RadiusKeys, SpacingKeys, ZIndexKeys } from './style-props';
3
- /** One shadow preset — expands into these real RN style props. */
4
- export type ShadowToken = Pick<ViewStyle, 'shadowColor' | 'shadowOffset' | 'shadowOpacity' | 'shadowRadius' | 'elevation'>;
5
- /**
6
- * One `role`/`size` entry in `semanticTokens.text` (Material Design 3
7
- * type-scale shape). Each field is either a key of the matching primitive
8
- * scale in `tokens` (e.g. `fontSize: 'lg'`) or a raw value. References are
9
- * validated by `@react-native-rethemed/cli codegen` against the final config,
10
- * since a partial theme may reference keys supplied by another theme it is
11
- * later merged with.
12
- *
13
- * `color` is optional: type-scale packages (Material Design) leave it out,
14
- * while an app's own presets (`caption`, `link`, …) may set it.
15
- */
16
- export type TextToken = {
17
- /** A `tokens.fontSizes` key (`'lg'`) or a raw size (`18`). */
18
- fontSize?: string | number;
19
- /**
20
- * A `tokens.lineHeights` key (`'short'` — a ratio of `fontSize`) or a raw,
21
- * absolute line height (`24`).
22
- */
23
- lineHeight?: string | number;
24
- /** A `tokens.letterSpacings` key (`'wide'`) or a raw value (`0.15`). */
25
- letterSpacing?: string | number;
26
- /** A `tokens.fontWeights` key (`'semibold'`) or a raw RN weight (`'600'`). */
27
- fontWeight?: string | TextStyle['fontWeight'];
28
- /**
29
- * Optional case transform, passed through as-is (no token scale), e.g.
30
- * Material UI's `button` and `overline` styles.
31
- *
32
- * @example
33
- * button: { fontSize: 14, fontWeight: '500', textTransform: 'uppercase' }
34
- */
35
- textTransform?: TextStyle['textTransform'];
36
- /**
37
- * A raw color, the same in light and dark (`colors['gray.500']`), or
38
- * one per scheme. A scheme left out gets no color from the preset, so the
39
- * surrounding style (or React Native's default) applies there.
40
- *
41
- * @example
42
- * color: { light: colors['gray.950'], dark: colors.white }
43
- * color: { dark: colors.white } // light: no color from the preset
44
- */
45
- color?: TextColor;
46
- };
47
- /** One semantic color: its value in each scheme. */
48
- export type SchemeColor = {
49
- light: string;
50
- dark: string;
51
- };
52
- /**
53
- * `semanticTokens.colors`: groups of colors (`bg.default`) and top-level
54
- * colors (`primary`), in any mix. See `isSchemeColor` for how they are told
55
- * apart.
56
- */
57
- export type SemanticColors = Record<string, SchemeColor | Record<string, SchemeColor>>;
58
- /** `TextToken['color']`: one raw color, or one per scheme. */
59
- export type TextColor = string | {
60
- light?: string;
61
- dark?: string;
62
- };
63
- /**
64
- * `semanticTokens.text`: groups of any depth whose leaves are presets.
65
- * See `isTextPreset` for how leaves and groups are told apart.
66
- */
67
- export type TextTokenTree = {
68
- [key: string]: TextToken | TextTokenTree;
69
- };
70
- /**
71
- * The shape a theme package (or an app's local override) must satisfy.
72
- * `tokens` holds primitive values (the smallest design-system units);
73
- * `semanticTokens` holds role-named values built on top of them — the
74
- * scheme-dependent `colors` and the `text` type scale — mirroring Chakra
75
- * UI's `tokens` vs `semanticTokens` distinction.
76
- */
77
- export type ThemeConfig = {
78
- /**
79
- * Primitive, scheme-independent values. Keys are the token names used in
80
- * styles (`themed.view({ padding: 4 })`).
81
- */
82
- tokens?: {
83
- /**
84
- * Fixed colors, the same in light and dark. Color style props accept
85
- * them by name (`themed.view({ backgroundColor: 'red.500' })`) alongside
86
- * `semanticTokens.colors`; when both define a name, the semantic color
87
- * wins. Prefer semantic colors for anything that should follow the color
88
- * scheme. Also readable via `useThemed().tokens.colors`.
89
- *
90
- * @example
91
- * colors: { white: '#ffffff', 'gray.50': '#fafafa', 'gray.950': '#111111' }
92
- */
93
- colors?: Record<string, string>;
94
- /**
95
- * For `borderRadius` and every corner-radius variant.
96
- *
97
- * @example
98
- * radii: { none: 0, sm: 4, md: 6, lg: 8, full: 9999 }
99
- */
100
- radii?: Record<string, number>;
101
- /**
102
- * For `padding*`, `margin*`, `gap`, `rowGap` and `columnGap`. Numeric
103
- * keys are used as numbers: `themed.view({ padding: 4 })`.
104
- *
105
- * @example
106
- * spacing: { px: 1, 0: 0, 0.5: 2, 1: 4, 2: 8, 4: 16 }
107
- */
108
- spacing?: Record<string, number>;
109
- /**
110
- * For `fontSize`.
111
- *
112
- * @example
113
- * fontSizes: { sm: 14, md: 16, lg: 18, xl: 20 }
114
- */
115
- fontSizes?: Record<string, number>;
116
- /**
117
- * For `fontWeight`.
118
- *
119
- * @example
120
- * fontWeights: { normal: '400', medium: '500', semibold: '600', bold: '700' }
121
- */
122
- fontWeights?: Record<string, TextStyle['fontWeight']>;
123
- /**
124
- * For `lineHeight`, as **ratios of `fontSize`** (like CSS unitless
125
- * line-height). A token resolves to `fontSize × ratio`, using the
126
- * `fontSize` in the same style or else `defaults.fontSize`. A raw number
127
- * passed to `lineHeight` stays an absolute value, as in React Native.
128
- *
129
- * @example
130
- * lineHeights: { shorter: 1.25, short: 1.375, moderate: 1.5, tall: 1.625 }
131
- * // themed.text({ fontSize: 'lg', lineHeight: 'short' })
132
- * // → { fontSize: 18, lineHeight: 24.75 }
133
- */
134
- lineHeights?: Record<string, number>;
135
- /**
136
- * For `letterSpacing`, in points.
137
- *
138
- * @example
139
- * letterSpacings: { tight: -0.4, normal: 0, wide: 0.4 }
140
- */
141
- letterSpacings?: Record<string, number>;
142
- /**
143
- * For `zIndex`, which also accepts a raw number.
144
- *
145
- * @example
146
- * zIndices: { base: 0, dropdown: 1000, modal: 1400, toast: 1700 }
147
- * // themed.view({ zIndex: 'modal' }) → { zIndex: 1400 }
148
- */
149
- zIndices?: Record<string, number>;
150
- /**
151
- * Presets for the virtual `shadow` prop, which expands to these RN props.
152
- *
153
- * @example
154
- * shadows: {
155
- * sm: {
156
- * shadowColor: '#000000',
157
- * shadowOffset: { width: 0, height: 1 },
158
- * shadowOpacity: 0.1,
159
- * shadowRadius: 2,
160
- * elevation: 2,
161
- * },
162
- * }
163
- */
164
- shadows?: Record<string, ShadowToken>;
165
- };
166
- /** Role-named values built on top of `tokens`. */
167
- semanticTokens?: {
168
- /**
169
- * group -> token -> scheme, used in styles as `'group.token'`
170
- * (`themed.view({ backgroundColor: 'bg.subtle' })`), or token -> scheme
171
- * at the top level, used by its bare name (`'primary-foreground'`, as in
172
- * shadcn/ui). Switched with the current light/dark scheme. Takes
173
- * precedence over a `tokens.colors` entry with the same name.
174
- *
175
- * @example
176
- * colors: {
177
- * bg: {
178
- * default: { light: '#ffffff', dark: '#111111' },
179
- * subtle: { light: '#fafafa', dark: '#18181b' },
180
- * },
181
- * fg: {
182
- * default: { light: '#111111', dark: '#fafafa' },
183
- * },
184
- * // top level: themed.view({ backgroundColor: 'primary' })
185
- * primary: { light: '#171717', dark: '#e5e5e5' },
186
- * }
187
- */
188
- colors?: SemanticColors;
189
- /**
190
- * Typography presets, as a tree of any depth. A node whose values are
191
- * all primitives is a **preset** (`TextToken`); a node of objects is a
192
- * **group**. Each preset is called by its path:
193
- * `themed.text.<path>(override?)`. Fields reference `tokens` keys or
194
- * take raw values (see `TextToken`).
195
- *
196
- * @example
197
- * text: {
198
- * // role -> size (Material Design 3 style)
199
- * title: {
200
- * md: { fontSize: 'md', lineHeight: 'moderate', fontWeight: 'semibold' },
201
- * sm: { fontSize: 14, lineHeight: 20, fontWeight: '500' },
202
- * },
203
- * // flat: themed.text.caption()
204
- * caption: { fontSize: 'xs', lineHeight: 'short' },
205
- * // deeper: themed.text.heading.display.lg()
206
- * heading: { display: { lg: { fontSize: '4xl', fontWeight: 'bold' } } },
207
- * }
208
- */
209
- text?: TextTokenTree;
210
- };
211
- /** Theme-wide defaults. */
212
- defaults?: {
213
- /**
214
- * The base font size: a `tokens.fontSizes` key or a raw size. Used to
215
- * resolve a `lineHeight` token when the style has no `fontSize` of its
216
- * own. Falls back to 14 (React Native's default) when unset.
217
- *
218
- * @example
219
- * defaults: { fontSize: 'md' }
220
- * // with fontSizes.md = 16:
221
- * // themed.text({ lineHeight: 'short' }) → { lineHeight: 22 } (16 × 1.375)
222
- */
223
- fontSize?: string | number;
224
- };
225
- };
226
- /**
227
- * Exact token types for one theme. Written by
228
- * `@react-native-rethemed/cli codegen` from the evaluated config, never by
229
- * hand, so core never has to infer token names from literal types.
230
- */
231
- export type ThemedSchema = {
232
- /**
233
- * Every token-aware style prop (plus the virtual `shadow`). Each primitive
234
- * only picks the props its RN style type actually has — see `TokenizeStyle`.
235
- */
236
- style: object;
237
- /** `themed.text.<role>.<size>(override?)` */
238
- textVariants: object;
239
- /** `useThemed().tokens` */
240
- tokens: object;
241
- /** `useThemed().semanticTokens`, colors resolved for the current scheme. */
242
- semanticTokens: object;
243
- };
244
- /**
245
- * Swaps `Base`'s token-bearing props for the token-aware ones in `P`.
246
- * `Omit` + `Pick` only — one level, no recursion. `Pick` is homomorphic, so
247
- * the generated JSDoc (token tables) survives into editor hovers.
248
- *
249
- * Only props `Base` actually has are picked (e.g. no `color` on `View`); the
250
- * virtual `shadow` prop is kept when `Base` has real shadow props.
251
- */
252
- export type TokenizeStyle<Base, P> = Omit<Base, keyof P> & Pick<P, Extract<keyof P, keyof Base | ('shadowColor' extends keyof Base ? 'shadow' : never)>>;
253
- export type ThemedStyles<S extends ThemedSchema> = {
254
- /** Resolves token values in a `View` style. */
255
- view: (style: TokenizeStyle<ViewStyle, S['style']>) => ViewStyle;
256
- /** Resolves token values in an `Image` style. */
257
- image: (style: TokenizeStyle<ImageStyle, S['style']>) => ImageStyle;
258
- /**
259
- * Resolves token values in a `Text` style. Typography presets are
260
- * available as `themed.text.<role>.<size>(override?)`.
261
- */
262
- text: ((style?: TokenizeStyle<TextStyle, S['style']>) => TextStyle) & S['textVariants'];
263
- };
264
- type LooseTokenKeys = ColorKeys | RadiusKeys | SpacingKeys | FontSizeKeys | FontWeightKeys | LineHeightKeys | LetterSpacingKeys | ZIndexKeys | 'shadow';
265
- type LooseStyle = {
266
- [K in LooseTokenKeys]?: string | number;
267
- };
268
- /** Any path under `themed.text`, callable at the leaves. */
269
- type LooseTextVariants = {
270
- [key: string]: ((override?: TokenizeStyle<TextStyle, LooseStyle>) => TextStyle) & LooseTextVariants;
271
- };
272
- export type LooseSchema = {
273
- style: LooseStyle;
274
- textVariants: LooseTextVariants;
275
- tokens: NonNullable<ThemeConfig['tokens']>;
276
- semanticTokens: {
277
- colors: Record<string, string | Record<string, string>>;
278
- text: NonNullable<NonNullable<ThemeConfig['semanticTokens']>['text']>;
279
- };
280
- };
281
- export {};
package/dist/cjs/types.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,32 +0,0 @@
1
- export type ColorMode = 'light' | 'dark' | 'system';
2
- /**
3
- * Structural subset of `expo-secure-store` / `AsyncStorage`, so either can be
4
- * passed as-is without an adapter.
5
- */
6
- export type ColorModeStorage = {
7
- getItem: (key: string) => string | null | Promise<string | null>;
8
- setItem: (key: string, value: string) => void | Promise<void>;
9
- };
10
- export declare const isColorMode: (value: unknown) => value is ColorMode;
11
- /**
12
- * External store holding the uncontrolled color mode. One is created per
13
- * `createThemed()` call (never at module level) so independent instances
14
- * don't share state.
15
- */
16
- export declare function createColorModeStore(): {
17
- /**
18
- * Seeds the mode on first use only. Called during render so the very
19
- * first render already sees `defaultMode`; later calls (e.g. a changed
20
- * `defaultColorMode` prop) are ignored rather than overwriting the
21
- * current mode.
22
- */
23
- init(defaultMode: ColorMode): void;
24
- subscribe(listener: () => void): () => void;
25
- getSnapshot(): ColorMode;
26
- setMode(next: ColorMode): void;
27
- /** Returns `false` if rehydration already ran for this store. */
28
- beginHydration(): boolean;
29
- /** Applies a stored value unless it's malformed or the user already chose. */
30
- hydrate(saved: unknown): void;
31
- };
32
- export type ColorModeStore = ReturnType<typeof createColorModeStore>;