@react-native-rethemed/core 0.1.0 → 0.1.1

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 +16 -24
  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
@@ -0,0 +1,28 @@
1
+ //#region src/semantic-colors.ts
2
+ /**
3
+ * A color of `semanticTokens.colors` (as opposed to a group of them): an
4
+ * object whose `light` or `dark` is a string. A group's values are objects,
5
+ * so a group may still name a token `light` or `dark` (Material UI's
6
+ * `primary.light`).
7
+ */
8
+ function isSchemeColor(node) {
9
+ if (typeof node !== "object" || node === null) return false;
10
+ const { light, dark } = node;
11
+ return typeof light === "string" || typeof dark === "string";
12
+ }
13
+ /**
14
+ * Visits every semantic color in definition order with its token name:
15
+ * `'group.token'` inside a group, or the bare name for a top-level color
16
+ * (`'primary'`, `'primary-foreground'`).
17
+ */
18
+ function walkSemanticColors(colors, visit) {
19
+ for (const [key, node] of Object.entries(colors ?? {})) {
20
+ if (isSchemeColor(node)) {
21
+ visit(key, node, void 0);
22
+ continue;
23
+ }
24
+ for (const [name, color] of Object.entries(node)) visit(`${key}.${name}`, color, key);
25
+ }
26
+ }
27
+ //#endregion
28
+ export { isSchemeColor, walkSemanticColors };
@@ -0,0 +1,103 @@
1
+ //#region src/style-props.ts
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
+ const COLOR_KEYS = [
8
+ "color",
9
+ "backgroundColor",
10
+ "borderColor",
11
+ "borderTopColor",
12
+ "borderBottomColor",
13
+ "borderLeftColor",
14
+ "borderRightColor",
15
+ "borderStartColor",
16
+ "borderEndColor",
17
+ "borderBlockColor",
18
+ "borderBlockStartColor",
19
+ "borderBlockEndColor",
20
+ "tintColor",
21
+ "overlayColor",
22
+ "shadowColor",
23
+ "outlineColor",
24
+ "textShadowColor",
25
+ "textDecorationColor"
26
+ ];
27
+ const RADIUS_KEYS = [
28
+ "borderRadius",
29
+ "borderTopLeftRadius",
30
+ "borderTopRightRadius",
31
+ "borderTopStartRadius",
32
+ "borderTopEndRadius",
33
+ "borderBottomLeftRadius",
34
+ "borderBottomRightRadius",
35
+ "borderBottomStartRadius",
36
+ "borderBottomEndRadius",
37
+ "borderStartStartRadius",
38
+ "borderStartEndRadius",
39
+ "borderEndStartRadius",
40
+ "borderEndEndRadius"
41
+ ];
42
+ const SPACING_KEYS = [
43
+ "padding",
44
+ "paddingTop",
45
+ "paddingBottom",
46
+ "paddingLeft",
47
+ "paddingRight",
48
+ "paddingHorizontal",
49
+ "paddingVertical",
50
+ "paddingStart",
51
+ "paddingEnd",
52
+ "paddingBlock",
53
+ "paddingBlockStart",
54
+ "paddingBlockEnd",
55
+ "paddingInline",
56
+ "paddingInlineStart",
57
+ "paddingInlineEnd",
58
+ "margin",
59
+ "marginTop",
60
+ "marginBottom",
61
+ "marginLeft",
62
+ "marginRight",
63
+ "marginHorizontal",
64
+ "marginVertical",
65
+ "marginStart",
66
+ "marginEnd",
67
+ "marginBlock",
68
+ "marginBlockStart",
69
+ "marginBlockEnd",
70
+ "marginInline",
71
+ "marginInlineStart",
72
+ "marginInlineEnd",
73
+ "gap",
74
+ "rowGap",
75
+ "columnGap"
76
+ ];
77
+ const FONT_SIZE_KEYS = ["fontSize"];
78
+ const FONT_WEIGHT_KEYS = ["fontWeight"];
79
+ const LINE_HEIGHT_KEYS = ["lineHeight"];
80
+ const LETTER_SPACING_KEYS = ["letterSpacing"];
81
+ /** Token or raw number, like the typography props. */
82
+ const Z_INDEX_KEYS = ["zIndex"];
83
+ /**
84
+ * The real RN style properties the virtual `shadow` prop expands into.
85
+ * Not resolved as a scale category itself — see `resolvers/style-resolver.ts`.
86
+ */
87
+ const SHADOW_STYLE_PROPS = [
88
+ "shadowColor",
89
+ "shadowOffset",
90
+ "shadowOpacity",
91
+ "shadowRadius",
92
+ "elevation"
93
+ ];
94
+ //#endregion
95
+ exports.COLOR_KEYS = COLOR_KEYS;
96
+ exports.FONT_SIZE_KEYS = FONT_SIZE_KEYS;
97
+ exports.FONT_WEIGHT_KEYS = FONT_WEIGHT_KEYS;
98
+ exports.LETTER_SPACING_KEYS = LETTER_SPACING_KEYS;
99
+ exports.LINE_HEIGHT_KEYS = LINE_HEIGHT_KEYS;
100
+ exports.RADIUS_KEYS = RADIUS_KEYS;
101
+ exports.SHADOW_STYLE_PROPS = SHADOW_STYLE_PROPS;
102
+ exports.SPACING_KEYS = SPACING_KEYS;
103
+ exports.Z_INDEX_KEYS = Z_INDEX_KEYS;
@@ -1,3 +1,4 @@
1
+ //#region src/style-props.d.ts
1
2
  /**
2
3
  * The RN style property names each token category resolves, grouped by
3
4
  * category. Kept as `const` arrays (not just types) because the resolvers
@@ -25,4 +26,4 @@ export type ZIndexKeys = (typeof Z_INDEX_KEYS)[number];
25
26
  * Not resolved as a scale category itself — see `resolvers/style-resolver.ts`.
26
27
  */
27
28
  export declare const SHADOW_STYLE_PROPS: readonly ["shadowColor", "shadowOffset", "shadowOpacity", "shadowRadius", "elevation"];
28
- export type ShadowStyleProps = (typeof SHADOW_STYLE_PROPS)[number];
29
+ //#endregion
@@ -1,3 +1,4 @@
1
+ //#region src/style-props.d.ts
1
2
  /**
2
3
  * The RN style property names each token category resolves, grouped by
3
4
  * category. Kept as `const` arrays (not just types) because the resolvers
@@ -25,4 +26,4 @@ export type ZIndexKeys = (typeof Z_INDEX_KEYS)[number];
25
26
  * Not resolved as a scale category itself — see `resolvers/style-resolver.ts`.
26
27
  */
27
28
  export declare const SHADOW_STYLE_PROPS: readonly ["shadowColor", "shadowOffset", "shadowOpacity", "shadowRadius", "elevation"];
28
- export type ShadowStyleProps = (typeof SHADOW_STYLE_PROPS)[number];
29
+ //#endregion
@@ -0,0 +1,95 @@
1
+ //#region src/style-props.ts
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
+ const COLOR_KEYS = [
8
+ "color",
9
+ "backgroundColor",
10
+ "borderColor",
11
+ "borderTopColor",
12
+ "borderBottomColor",
13
+ "borderLeftColor",
14
+ "borderRightColor",
15
+ "borderStartColor",
16
+ "borderEndColor",
17
+ "borderBlockColor",
18
+ "borderBlockStartColor",
19
+ "borderBlockEndColor",
20
+ "tintColor",
21
+ "overlayColor",
22
+ "shadowColor",
23
+ "outlineColor",
24
+ "textShadowColor",
25
+ "textDecorationColor"
26
+ ];
27
+ const RADIUS_KEYS = [
28
+ "borderRadius",
29
+ "borderTopLeftRadius",
30
+ "borderTopRightRadius",
31
+ "borderTopStartRadius",
32
+ "borderTopEndRadius",
33
+ "borderBottomLeftRadius",
34
+ "borderBottomRightRadius",
35
+ "borderBottomStartRadius",
36
+ "borderBottomEndRadius",
37
+ "borderStartStartRadius",
38
+ "borderStartEndRadius",
39
+ "borderEndStartRadius",
40
+ "borderEndEndRadius"
41
+ ];
42
+ const SPACING_KEYS = [
43
+ "padding",
44
+ "paddingTop",
45
+ "paddingBottom",
46
+ "paddingLeft",
47
+ "paddingRight",
48
+ "paddingHorizontal",
49
+ "paddingVertical",
50
+ "paddingStart",
51
+ "paddingEnd",
52
+ "paddingBlock",
53
+ "paddingBlockStart",
54
+ "paddingBlockEnd",
55
+ "paddingInline",
56
+ "paddingInlineStart",
57
+ "paddingInlineEnd",
58
+ "margin",
59
+ "marginTop",
60
+ "marginBottom",
61
+ "marginLeft",
62
+ "marginRight",
63
+ "marginHorizontal",
64
+ "marginVertical",
65
+ "marginStart",
66
+ "marginEnd",
67
+ "marginBlock",
68
+ "marginBlockStart",
69
+ "marginBlockEnd",
70
+ "marginInline",
71
+ "marginInlineStart",
72
+ "marginInlineEnd",
73
+ "gap",
74
+ "rowGap",
75
+ "columnGap"
76
+ ];
77
+ const FONT_SIZE_KEYS = ["fontSize"];
78
+ const FONT_WEIGHT_KEYS = ["fontWeight"];
79
+ const LINE_HEIGHT_KEYS = ["lineHeight"];
80
+ const LETTER_SPACING_KEYS = ["letterSpacing"];
81
+ /** Token or raw number, like the typography props. */
82
+ const Z_INDEX_KEYS = ["zIndex"];
83
+ /**
84
+ * The real RN style properties the virtual `shadow` prop expands into.
85
+ * Not resolved as a scale category itself — see `resolvers/style-resolver.ts`.
86
+ */
87
+ const SHADOW_STYLE_PROPS = [
88
+ "shadowColor",
89
+ "shadowOffset",
90
+ "shadowOpacity",
91
+ "shadowRadius",
92
+ "elevation"
93
+ ];
94
+ //#endregion
95
+ export { COLOR_KEYS, FONT_SIZE_KEYS, FONT_WEIGHT_KEYS, LETTER_SPACING_KEYS, LINE_HEIGHT_KEYS, RADIUS_KEYS, SHADOW_STYLE_PROPS, SPACING_KEYS, Z_INDEX_KEYS };
@@ -0,0 +1,70 @@
1
+ //#region src/text-tree.ts
2
+ /** The fields a `semanticTokens.text` preset (leaf) may have. */
3
+ const TEXT_TOKEN_FIELDS = [
4
+ "fontSize",
5
+ "lineHeight",
6
+ "letterSpacing",
7
+ "fontWeight",
8
+ "textTransform",
9
+ "color"
10
+ ];
11
+ const isPrimitive = (value) => typeof value === "string" || typeof value === "number";
12
+ const isPresetField = (key) => TEXT_TOKEN_FIELDS.includes(key);
13
+ /**
14
+ * A node of `semanticTokens.text` is a **preset** (leaf) when it has any
15
+ * preset field (`fontSize`, …, `color`) or when every value is a primitive,
16
+ * and a **group** otherwise (`{ md: {...}, sm: {...} }`). The field check
17
+ * matters because `color` may itself be an object (`{ light, dark }`), so
18
+ * "all primitives" alone can't tell a preset from a group; preset field
19
+ * names are therefore reserved and can't name a group or preset. Mixed
20
+ * nodes are rejected by `@react-native-rethemed/cli codegen`.
21
+ */
22
+ function isTextPreset(node) {
23
+ return Object.keys(node).some(isPresetField) || Object.values(node).every(isPrimitive);
24
+ }
25
+ /**
26
+ * A preset `color` for one scheme: a string applies to both, an object picks
27
+ * `light` / `dark`, and a missing scheme yields `undefined` (no color).
28
+ */
29
+ function resolveTextColor(color, scheme) {
30
+ return typeof color === "object" && color !== null ? color[scheme] : color;
31
+ }
32
+ /**
33
+ * The text tree with every preset `color` resolved for `scheme`; a preset
34
+ * whose color doesn't cover the scheme loses its `color` key. Presets
35
+ * without `color` are returned as-is (same object).
36
+ */
37
+ function resolveTextTree(tree, scheme) {
38
+ const result = {};
39
+ for (const [key, node] of Object.entries(tree ?? {})) {
40
+ if (typeof node !== "object" || node === null) continue;
41
+ if (!isTextPreset(node)) result[key] = resolveTextTree(node, scheme);
42
+ else if (node.color === void 0) result[key] = node;
43
+ else {
44
+ const { color, ...rest } = node;
45
+ const resolved = resolveTextColor(color, scheme);
46
+ result[key] = resolved === void 0 ? rest : {
47
+ ...rest,
48
+ color: resolved
49
+ };
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Visits every preset in a text tree, depth-first in definition order,
56
+ * with its path (`['heading', 'display', 'lg']`).
57
+ */
58
+ function walkTextPresets(tree, visit, path = []) {
59
+ for (const [key, node] of Object.entries(tree ?? {})) {
60
+ if (typeof node !== "object" || node === null) continue;
61
+ if (isTextPreset(node)) visit([...path, key], node);
62
+ else walkTextPresets(node, visit, [...path, key]);
63
+ }
64
+ }
65
+ //#endregion
66
+ exports.TEXT_TOKEN_FIELDS = TEXT_TOKEN_FIELDS;
67
+ exports.isTextPreset = isTextPreset;
68
+ exports.resolveTextColor = resolveTextColor;
69
+ exports.resolveTextTree = resolveTextTree;
70
+ exports.walkTextPresets = walkTextPresets;
@@ -1,5 +1,6 @@
1
- import type { ColorScheme } from './resolvers/color-resolver';
2
- import type { TextColor, TextToken, TextTokenTree } from './types';
1
+ import { TextColor, TextToken, TextTokenTree } from "./types.cjs";
2
+ import { ColorScheme } from "./resolvers/color-resolver.cjs";
3
+ //#region src/text-tree.d.ts
3
4
  /** The fields a `semanticTokens.text` preset (leaf) may have. */
4
5
  export declare const TEXT_TOKEN_FIELDS: readonly ["fontSize", "lineHeight", "letterSpacing", "fontWeight", "textTransform", "color"];
5
6
  /**
@@ -17,14 +18,9 @@ export declare function isTextPreset(node: TextToken | TextTokenTree): node is T
17
18
  * `light` / `dark`, and a missing scheme yields `undefined` (no color).
18
19
  */
19
20
  export declare function resolveTextColor(color: TextColor | undefined, scheme: ColorScheme): string | undefined;
20
- /**
21
- * The text tree with every preset `color` resolved for `scheme`; a preset
22
- * whose color doesn't cover the scheme loses its `color` key. Presets
23
- * without `color` are returned as-is (same object).
24
- */
25
- export declare function resolveTextTree(tree: TextTokenTree | undefined, scheme: ColorScheme): TextTokenTree;
26
21
  /**
27
22
  * Visits every preset in a text tree, depth-first in definition order,
28
23
  * with its path (`['heading', 'display', 'lg']`).
29
24
  */
30
25
  export declare function walkTextPresets(tree: TextTokenTree | undefined, visit: (path: string[], preset: TextToken) => void, path?: string[]): void;
26
+ //#endregion
@@ -1,5 +1,6 @@
1
- import type { ColorScheme } from './resolvers/color-resolver.js';
2
- import type { TextColor, TextToken, TextTokenTree } from './types.js';
1
+ import { TextColor, TextToken, TextTokenTree } from "./types.mjs";
2
+ import { ColorScheme } from "./resolvers/color-resolver.mjs";
3
+ //#region src/text-tree.d.ts
3
4
  /** The fields a `semanticTokens.text` preset (leaf) may have. */
4
5
  export declare const TEXT_TOKEN_FIELDS: readonly ["fontSize", "lineHeight", "letterSpacing", "fontWeight", "textTransform", "color"];
5
6
  /**
@@ -17,14 +18,9 @@ export declare function isTextPreset(node: TextToken | TextTokenTree): node is T
17
18
  * `light` / `dark`, and a missing scheme yields `undefined` (no color).
18
19
  */
19
20
  export declare function resolveTextColor(color: TextColor | undefined, scheme: ColorScheme): string | undefined;
20
- /**
21
- * The text tree with every preset `color` resolved for `scheme`; a preset
22
- * whose color doesn't cover the scheme loses its `color` key. Presets
23
- * without `color` are returned as-is (same object).
24
- */
25
- export declare function resolveTextTree(tree: TextTokenTree | undefined, scheme: ColorScheme): TextTokenTree;
26
21
  /**
27
22
  * Visits every preset in a text tree, depth-first in definition order,
28
23
  * with its path (`['heading', 'display', 'lg']`).
29
24
  */
30
25
  export declare function walkTextPresets(tree: TextTokenTree | undefined, visit: (path: string[], preset: TextToken) => void, path?: string[]): void;
26
+ //#endregion
@@ -0,0 +1,66 @@
1
+ //#region src/text-tree.ts
2
+ /** The fields a `semanticTokens.text` preset (leaf) may have. */
3
+ const TEXT_TOKEN_FIELDS = [
4
+ "fontSize",
5
+ "lineHeight",
6
+ "letterSpacing",
7
+ "fontWeight",
8
+ "textTransform",
9
+ "color"
10
+ ];
11
+ const isPrimitive = (value) => typeof value === "string" || typeof value === "number";
12
+ const isPresetField = (key) => TEXT_TOKEN_FIELDS.includes(key);
13
+ /**
14
+ * A node of `semanticTokens.text` is a **preset** (leaf) when it has any
15
+ * preset field (`fontSize`, …, `color`) or when every value is a primitive,
16
+ * and a **group** otherwise (`{ md: {...}, sm: {...} }`). The field check
17
+ * matters because `color` may itself be an object (`{ light, dark }`), so
18
+ * "all primitives" alone can't tell a preset from a group; preset field
19
+ * names are therefore reserved and can't name a group or preset. Mixed
20
+ * nodes are rejected by `@react-native-rethemed/cli codegen`.
21
+ */
22
+ function isTextPreset(node) {
23
+ return Object.keys(node).some(isPresetField) || Object.values(node).every(isPrimitive);
24
+ }
25
+ /**
26
+ * A preset `color` for one scheme: a string applies to both, an object picks
27
+ * `light` / `dark`, and a missing scheme yields `undefined` (no color).
28
+ */
29
+ function resolveTextColor(color, scheme) {
30
+ return typeof color === "object" && color !== null ? color[scheme] : color;
31
+ }
32
+ /**
33
+ * The text tree with every preset `color` resolved for `scheme`; a preset
34
+ * whose color doesn't cover the scheme loses its `color` key. Presets
35
+ * without `color` are returned as-is (same object).
36
+ */
37
+ function resolveTextTree(tree, scheme) {
38
+ const result = {};
39
+ for (const [key, node] of Object.entries(tree ?? {})) {
40
+ if (typeof node !== "object" || node === null) continue;
41
+ if (!isTextPreset(node)) result[key] = resolveTextTree(node, scheme);
42
+ else if (node.color === void 0) result[key] = node;
43
+ else {
44
+ const { color, ...rest } = node;
45
+ const resolved = resolveTextColor(color, scheme);
46
+ result[key] = resolved === void 0 ? rest : {
47
+ ...rest,
48
+ color: resolved
49
+ };
50
+ }
51
+ }
52
+ return result;
53
+ }
54
+ /**
55
+ * Visits every preset in a text tree, depth-first in definition order,
56
+ * with its path (`['heading', 'display', 'lg']`).
57
+ */
58
+ function walkTextPresets(tree, visit, path = []) {
59
+ for (const [key, node] of Object.entries(tree ?? {})) {
60
+ if (typeof node !== "object" || node === null) continue;
61
+ if (isTextPreset(node)) visit([...path, key], node);
62
+ else walkTextPresets(node, visit, [...path, key]);
63
+ }
64
+ }
65
+ //#endregion
66
+ export { TEXT_TOKEN_FIELDS, isTextPreset, resolveTextColor, resolveTextTree, walkTextPresets };
@@ -0,0 +1,25 @@
1
+ const require_text_tree = require("./text-tree.cjs");
2
+ //#region src/text-variants.ts
3
+ /**
4
+ * Builds `themed.text.<path>(override?)` by walking whatever tree
5
+ * `config.semanticTokens.text` defines, at any depth — no hand-written
6
+ * per-variant code. Each preset merges with the caller's override (preset
7
+ * first, override wins) and runs through the same `resolve` as
8
+ * `themed.text()` itself, so presets referencing scale keys (e.g.
9
+ * `fontSize: 'lg'`) resolve exactly like caller-passed tokens.
10
+ *
11
+ * `tree` must already have its preset colors resolved for the scheme (see
12
+ * `resolveTextTree`), so a call only merges and resolves tokens.
13
+ *
14
+ * Typed loosely on purpose; the exact tree shape comes from the generated
15
+ * `themed.gen.ts`.
16
+ */
17
+ function createTextVariants(tree, resolve) {
18
+ const build = (tree) => Object.fromEntries(Object.entries(tree).filter(([, node]) => typeof node === "object" && node !== null).map(([key, node]) => [key, require_text_tree.isTextPreset(node) ? (override) => resolve({
19
+ ...node,
20
+ ...override
21
+ }) : build(node)]));
22
+ return build(tree);
23
+ }
24
+ //#endregion
25
+ exports.createTextVariants = createTextVariants;
@@ -0,0 +1,25 @@
1
+ import { isTextPreset } from "./text-tree.mjs";
2
+ //#region src/text-variants.ts
3
+ /**
4
+ * Builds `themed.text.<path>(override?)` by walking whatever tree
5
+ * `config.semanticTokens.text` defines, at any depth — no hand-written
6
+ * per-variant code. Each preset merges with the caller's override (preset
7
+ * first, override wins) and runs through the same `resolve` as
8
+ * `themed.text()` itself, so presets referencing scale keys (e.g.
9
+ * `fontSize: 'lg'`) resolve exactly like caller-passed tokens.
10
+ *
11
+ * `tree` must already have its preset colors resolved for the scheme (see
12
+ * `resolveTextTree`), so a call only merges and resolves tokens.
13
+ *
14
+ * Typed loosely on purpose; the exact tree shape comes from the generated
15
+ * `themed.gen.ts`.
16
+ */
17
+ function createTextVariants(tree, resolve) {
18
+ const build = (tree) => Object.fromEntries(Object.entries(tree).filter(([, node]) => typeof node === "object" && node !== null).map(([key, node]) => [key, isTextPreset(node) ? (override) => resolve({
19
+ ...node,
20
+ ...override
21
+ }) : build(node)]));
22
+ return build(tree);
23
+ }
24
+ //#endregion
25
+ export { createTextVariants };