react-native-terra-ui 0.7.2 → 0.8.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.
Files changed (252) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -1
  3. package/lib/module/components/avatar/Avatar.js +20 -20
  4. package/lib/module/components/avatar/Avatar.js.map +1 -1
  5. package/lib/module/components/button/Button.js +11 -11
  6. package/lib/module/components/button/Button.js.map +1 -1
  7. package/lib/module/components/chip/Chip.js +32 -32
  8. package/lib/module/components/chip/Chip.js.map +1 -1
  9. package/lib/module/components/empty-state/EmptyState.js +3 -3
  10. package/lib/module/components/empty-state/EmptyState.js.map +1 -1
  11. package/lib/module/components/header/variants/LargeTitleHeader/index.js +30 -32
  12. package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -1
  13. package/lib/module/components/header/variants/TitleHeader/index.js +26 -18
  14. package/lib/module/components/header/variants/TitleHeader/index.js.map +1 -1
  15. package/lib/module/components/icon/Icon.js +3 -3
  16. package/lib/module/components/page-indicator/hooks/use-page-indicator-colors.js +2 -2
  17. package/lib/module/components/screen/Screen.js +63 -34
  18. package/lib/module/components/screen/Screen.js.map +1 -1
  19. package/lib/module/components/screen/ScreenContext.js +28 -9
  20. package/lib/module/components/screen/ScreenContext.js.map +1 -1
  21. package/lib/module/components/screen/ScreenFlatList.js +4 -162
  22. package/lib/module/components/screen/ScreenFlatList.js.map +1 -1
  23. package/lib/module/components/screen/ScreenList.js +81 -97
  24. package/lib/module/components/screen/ScreenList.js.map +1 -1
  25. package/lib/module/components/screen/ScreenScrollView.js +64 -115
  26. package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
  27. package/lib/module/components/screen/hooks/use-screen-ref.js +18 -0
  28. package/lib/module/components/screen/hooks/use-screen-ref.js.map +1 -0
  29. package/lib/module/components/screen/hooks/use-screen-scroll-handler.js +19 -0
  30. package/lib/module/components/screen/hooks/use-screen-scroll-handler.js.map +1 -0
  31. package/lib/module/components/screen/index.js.map +1 -1
  32. package/lib/module/components/screen/parts/ScreenFrame.js +47 -0
  33. package/lib/module/components/screen/parts/ScreenFrame.js.map +1 -0
  34. package/lib/module/components/screen/parts/ScreenHeaderAppearance.js +43 -0
  35. package/lib/module/components/screen/parts/ScreenHeaderAppearance.js.map +1 -0
  36. package/lib/module/components/screen/parts/ScreenPlaceholder.js +11 -13
  37. package/lib/module/components/screen/parts/ScreenPlaceholder.js.map +1 -1
  38. package/lib/module/components/screen/parts/ScreenSafeArea.android.js +27 -0
  39. package/lib/module/components/screen/parts/ScreenSafeArea.android.js.map +1 -0
  40. package/lib/module/components/screen/parts/ScreenSafeArea.js +26 -0
  41. package/lib/module/components/screen/parts/ScreenSafeArea.js.map +1 -0
  42. package/lib/module/components/screen/utils.js +18 -9
  43. package/lib/module/components/screen/utils.js.map +1 -1
  44. package/lib/module/components/spinner/Spinner.js +2 -2
  45. package/lib/module/components/text/Text.js +1 -1
  46. package/lib/module/components/toast/Toast.js +13 -13
  47. package/lib/module/components/toast/Toast.js.map +1 -1
  48. package/lib/module/components/toolbar/Toolbar.js +2 -2
  49. package/lib/module/context/ThemeProvider.js +22 -39
  50. package/lib/module/context/ThemeProvider.js.map +1 -1
  51. package/lib/module/context/index.js +1 -1
  52. package/lib/module/context/index.js.map +1 -1
  53. package/lib/module/theme/breakpoints.js +1 -1
  54. package/lib/module/theme/define-config.js +21 -0
  55. package/lib/module/theme/define-config.js.map +1 -0
  56. package/lib/module/theme/diagnostics.js +13 -0
  57. package/lib/module/theme/diagnostics.js.map +1 -0
  58. package/lib/module/theme/errors.js +15 -0
  59. package/lib/module/theme/errors.js.map +1 -0
  60. package/lib/module/theme/index.js +7 -1
  61. package/lib/module/theme/index.js.map +1 -1
  62. package/lib/module/theme/legacy-tokens.js +119 -0
  63. package/lib/module/theme/legacy-tokens.js.map +1 -0
  64. package/lib/module/theme/registry.js +122 -130
  65. package/lib/module/theme/registry.js.map +1 -1
  66. package/lib/module/theme/resolve-config.js +346 -0
  67. package/lib/module/theme/resolve-config.js.map +1 -0
  68. package/lib/module/theme/runtime.js +57 -12
  69. package/lib/module/theme/runtime.js.map +1 -1
  70. package/lib/module/theme/screen-margin.js +6 -14
  71. package/lib/module/theme/screen-margin.js.map +1 -1
  72. package/lib/module/theme/screen-padding.js +17 -0
  73. package/lib/module/theme/screen-padding.js.map +1 -0
  74. package/lib/module/theme/selection-store.js +75 -0
  75. package/lib/module/theme/selection-store.js.map +1 -0
  76. package/lib/module/theme/theme.js +81 -36
  77. package/lib/module/theme/theme.js.map +1 -1
  78. package/lib/module/theme/tokens/canonical-color-keys.js +102 -0
  79. package/lib/module/theme/tokens/canonical-color-keys.js.map +1 -0
  80. package/lib/module/theme/tokens/dark.js +72 -88
  81. package/lib/module/theme/tokens/dark.js.map +1 -1
  82. package/lib/module/theme/tokens/light.js +69 -83
  83. package/lib/module/theme/tokens/light.js.map +1 -1
  84. package/lib/module/theme/tokens/primitives.js +14 -14
  85. package/lib/module/theme/tokens/primitives.js.map +1 -1
  86. package/lib/module/theme/tokens/validate.js +238 -0
  87. package/lib/module/theme/tokens/validate.js.map +1 -0
  88. package/lib/module/theme/unistyles-adapter.js +77 -0
  89. package/lib/module/theme/unistyles-adapter.js.map +1 -0
  90. package/lib/module/utils/accent-generator.js +476 -0
  91. package/lib/module/utils/accent-generator.js.map +1 -0
  92. package/lib/module/utils/accent-utils.js +52 -35
  93. package/lib/module/utils/accent-utils.js.map +1 -1
  94. package/lib/module/utils/color-utils.js +224 -7
  95. package/lib/module/utils/color-utils.js.map +1 -1
  96. package/lib/module/utils/deep-merge.js +1 -1
  97. package/lib/module/utils/deep-merge.js.map +1 -1
  98. package/lib/module/utils/resolve-theme-color.js +2 -2
  99. package/lib/typescript/src/components/chip/types.d.ts +1 -1
  100. package/lib/typescript/src/components/empty-state/EmptyState.d.ts +1 -1
  101. package/lib/typescript/src/components/empty-state/EmptyState.d.ts.map +1 -1
  102. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts +6 -5
  103. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -1
  104. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts +11 -5
  105. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts.map +1 -1
  106. package/lib/typescript/src/components/icon/Icon.d.ts +2 -2
  107. package/lib/typescript/src/components/screen/Screen.d.ts +45 -16
  108. package/lib/typescript/src/components/screen/Screen.d.ts.map +1 -1
  109. package/lib/typescript/src/components/screen/ScreenContext.d.ts +42 -26
  110. package/lib/typescript/src/components/screen/ScreenContext.d.ts.map +1 -1
  111. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts +5 -46
  112. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -1
  113. package/lib/typescript/src/components/screen/ScreenList.d.ts +62 -50
  114. package/lib/typescript/src/components/screen/ScreenList.d.ts.map +1 -1
  115. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts +18 -58
  116. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
  117. package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts +5 -0
  118. package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts.map +1 -0
  119. package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts +53 -0
  120. package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts.map +1 -0
  121. package/lib/typescript/src/components/screen/index.d.ts +2 -2
  122. package/lib/typescript/src/components/screen/index.d.ts.map +1 -1
  123. package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts +6 -0
  124. package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts.map +1 -0
  125. package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts +21 -0
  126. package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts.map +1 -0
  127. package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts +6 -8
  128. package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts.map +1 -1
  129. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts +7 -0
  130. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts.map +1 -0
  131. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts +6 -0
  132. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts.map +1 -0
  133. package/lib/typescript/src/components/screen/types.d.ts +27 -32
  134. package/lib/typescript/src/components/screen/types.d.ts.map +1 -1
  135. package/lib/typescript/src/components/screen/utils.d.ts +9 -8
  136. package/lib/typescript/src/components/screen/utils.d.ts.map +1 -1
  137. package/lib/typescript/src/components/text/Text.d.ts +1 -1
  138. package/lib/typescript/src/components/text/Text.d.ts.map +1 -1
  139. package/lib/typescript/src/components/toolbar/Toolbar.d.ts +2 -2
  140. package/lib/typescript/src/context/ThemeProvider.d.ts +29 -12
  141. package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
  142. package/lib/typescript/src/context/index.d.ts +1 -1
  143. package/lib/typescript/src/context/index.d.ts.map +1 -1
  144. package/lib/typescript/src/theme/breakpoints.d.ts +1 -1
  145. package/lib/typescript/src/theme/define-config.d.ts +23 -0
  146. package/lib/typescript/src/theme/define-config.d.ts.map +1 -0
  147. package/lib/typescript/src/theme/diagnostics.d.ts +4 -0
  148. package/lib/typescript/src/theme/diagnostics.d.ts.map +1 -0
  149. package/lib/typescript/src/theme/errors.d.ts +10 -0
  150. package/lib/typescript/src/theme/errors.d.ts.map +1 -0
  151. package/lib/typescript/src/theme/index.d.ts +10 -2
  152. package/lib/typescript/src/theme/index.d.ts.map +1 -1
  153. package/lib/typescript/src/theme/legacy-tokens.d.ts +187 -0
  154. package/lib/typescript/src/theme/legacy-tokens.d.ts.map +1 -0
  155. package/lib/typescript/src/theme/registry.d.ts +12 -17
  156. package/lib/typescript/src/theme/registry.d.ts.map +1 -1
  157. package/lib/typescript/src/theme/resolve-config.d.ts +99 -0
  158. package/lib/typescript/src/theme/resolve-config.d.ts.map +1 -0
  159. package/lib/typescript/src/theme/runtime.d.ts +25 -4
  160. package/lib/typescript/src/theme/runtime.d.ts.map +1 -1
  161. package/lib/typescript/src/theme/screen-margin.d.ts +6 -14
  162. package/lib/typescript/src/theme/screen-margin.d.ts.map +1 -1
  163. package/lib/typescript/src/theme/screen-padding.d.ts +15 -0
  164. package/lib/typescript/src/theme/screen-padding.d.ts.map +1 -0
  165. package/lib/typescript/src/theme/selection-store.d.ts +41 -0
  166. package/lib/typescript/src/theme/selection-store.d.ts.map +1 -0
  167. package/lib/typescript/src/theme/theme.d.ts +54 -1
  168. package/lib/typescript/src/theme/theme.d.ts.map +1 -1
  169. package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts +95 -0
  170. package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts.map +1 -0
  171. package/lib/typescript/src/theme/tokens/dark.d.ts +56 -63
  172. package/lib/typescript/src/theme/tokens/dark.d.ts.map +1 -1
  173. package/lib/typescript/src/theme/tokens/light.d.ts +56 -71
  174. package/lib/typescript/src/theme/tokens/light.d.ts.map +1 -1
  175. package/lib/typescript/src/theme/tokens/primitives.d.ts +11 -10
  176. package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -1
  177. package/lib/typescript/src/theme/tokens/validate.d.ts +34 -0
  178. package/lib/typescript/src/theme/tokens/validate.d.ts.map +1 -0
  179. package/lib/typescript/src/theme/types.d.ts +166 -86
  180. package/lib/typescript/src/theme/types.d.ts.map +1 -1
  181. package/lib/typescript/src/theme/unistyles-adapter.d.ts +33 -0
  182. package/lib/typescript/src/theme/unistyles-adapter.d.ts.map +1 -0
  183. package/lib/typescript/src/utils/accent-generator.d.ts +103 -0
  184. package/lib/typescript/src/utils/accent-generator.d.ts.map +1 -0
  185. package/lib/typescript/src/utils/accent-utils.d.ts +15 -2
  186. package/lib/typescript/src/utils/accent-utils.d.ts.map +1 -1
  187. package/lib/typescript/src/utils/color-utils.d.ts +59 -2
  188. package/lib/typescript/src/utils/color-utils.d.ts.map +1 -1
  189. package/lib/typescript/src/utils/deep-merge.d.ts +1 -0
  190. package/lib/typescript/src/utils/deep-merge.d.ts.map +1 -1
  191. package/lib/typescript/src/utils/resolve-theme-color.d.ts +2 -2
  192. package/package.json +1 -1
  193. package/src/components/avatar/Avatar.tsx +20 -20
  194. package/src/components/button/Button.tsx +11 -11
  195. package/src/components/chip/Chip.tsx +32 -32
  196. package/src/components/chip/types.ts +1 -1
  197. package/src/components/empty-state/EmptyState.tsx +4 -4
  198. package/src/components/header/variants/LargeTitleHeader/index.tsx +31 -30
  199. package/src/components/header/variants/TitleHeader/index.tsx +33 -22
  200. package/src/components/icon/Icon.tsx +4 -4
  201. package/src/components/page-indicator/hooks/use-page-indicator-colors.ts +2 -2
  202. package/src/components/screen/Screen.tsx +89 -43
  203. package/src/components/screen/ScreenContext.tsx +48 -28
  204. package/src/components/screen/ScreenFlatList.tsx +5 -191
  205. package/src/components/screen/ScreenList.tsx +197 -175
  206. package/src/components/screen/ScreenScrollView.tsx +92 -167
  207. package/src/components/screen/hooks/use-screen-ref.ts +24 -0
  208. package/src/components/screen/hooks/use-screen-scroll-handler.ts +31 -0
  209. package/src/components/screen/index.ts +8 -2
  210. package/src/components/screen/parts/ScreenFrame.tsx +49 -0
  211. package/src/components/screen/parts/ScreenHeaderAppearance.tsx +52 -0
  212. package/src/components/screen/parts/ScreenPlaceholder.tsx +16 -16
  213. package/src/components/screen/parts/ScreenSafeArea.android.tsx +22 -0
  214. package/src/components/screen/parts/ScreenSafeArea.tsx +20 -0
  215. package/src/components/screen/types.ts +29 -32
  216. package/src/components/screen/utils.ts +24 -11
  217. package/src/components/spinner/Spinner.tsx +2 -2
  218. package/src/components/text/Text.tsx +2 -2
  219. package/src/components/toast/Toast.tsx +13 -13
  220. package/src/components/toolbar/Toolbar.tsx +4 -4
  221. package/src/context/ThemeProvider.tsx +47 -51
  222. package/src/context/index.ts +1 -1
  223. package/src/theme/breakpoints.ts +1 -1
  224. package/src/theme/define-config.ts +27 -0
  225. package/src/theme/diagnostics.ts +11 -0
  226. package/src/theme/errors.ts +14 -0
  227. package/src/theme/index.ts +40 -1
  228. package/src/theme/legacy-tokens.ts +227 -0
  229. package/src/theme/registry.ts +119 -137
  230. package/src/theme/resolve-config.ts +406 -0
  231. package/src/theme/runtime.ts +52 -14
  232. package/src/theme/screen-margin.ts +6 -25
  233. package/src/theme/screen-padding.ts +26 -0
  234. package/src/theme/selection-store.ts +76 -0
  235. package/src/theme/theme.ts +104 -39
  236. package/src/theme/tokens/canonical-color-keys.ts +107 -0
  237. package/src/theme/tokens/dark.ts +91 -98
  238. package/src/theme/tokens/light.ts +88 -93
  239. package/src/theme/tokens/primitives.ts +14 -14
  240. package/src/theme/tokens/validate.ts +271 -0
  241. package/src/theme/types.ts +184 -95
  242. package/src/theme/unistyles-adapter.ts +75 -0
  243. package/src/utils/accent-generator.ts +530 -0
  244. package/src/utils/accent-utils.ts +66 -39
  245. package/src/utils/color-utils.ts +225 -8
  246. package/src/utils/deep-merge.ts +1 -1
  247. package/src/utils/resolve-theme-color.ts +2 -2
  248. package/lib/module/components/screen/parts/BottomSafeArea.js +0 -62
  249. package/lib/module/components/screen/parts/BottomSafeArea.js.map +0 -1
  250. package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts +0 -30
  251. package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts.map +0 -1
  252. package/src/components/screen/parts/BottomSafeArea.tsx +0 -59
@@ -9,6 +9,7 @@ import type { ImageStyle, StyleProp } from "react-native";
9
9
 
10
10
  import type { DeepPartial } from "#utils/deep-merge";
11
11
  import type { BreakpointName } from "./breakpoints";
12
+ import type { LegacyThemeColor } from "./legacy-tokens";
12
13
 
13
14
  // ─── Scale keys (declared explicitly; token data is untyped) ────────────────
14
15
 
@@ -120,109 +121,148 @@ export interface Typography {
120
121
 
121
122
  /**
122
123
  * Flat color token map — keys are dotted paths matching the token schema
123
- * (category prefix `color.` stripped). Accessed as `theme.color['text.default']`.
124
+ * (category prefix `color.` stripped). Accessed as `theme.color['text.primary']`.
124
125
  */
125
- export interface ThemeColor {
126
+ export interface CanonicalThemeColor {
126
127
  // page background
127
- background: string;
128
+ "surface.canvas": string;
128
129
  // shadow color (used as elevation.*.shadowColor)
129
130
  shadow: string;
130
131
  // surfaces
131
132
  "surface.default": string;
132
133
  "surface.raised": string;
133
134
  "surface.sunken": string;
134
- "surface.overlay": string;
135
- "surface.accent": string;
136
- "surface.accent.subtle": string;
135
+ backdrop: string;
137
136
  // text / icons
138
- "text.default": string;
139
- "text.muted": string;
140
- "text.subtle": string;
137
+ "text.primary": string;
138
+ "text.secondary": string;
139
+ "text.tertiary": string;
141
140
  "text.disabled": string;
142
141
  "text.inverse": string;
143
142
  "text.link": string;
144
- "text.accent": string;
145
- "text.on-accent": string;
146
- "text.on-accent-subtle": string;
143
+ "accent.text": string;
147
144
  // borders
148
145
  "border.subtle": string;
149
146
  "border.default": string;
150
147
  "border.strong": string;
151
- "border.focus": string;
152
- "border.accent": string;
153
- // interactive actions
154
- "action.bg.primary": string;
155
- "action.bg.primary.hover": string;
156
- "action.bg.primary.active": string;
157
- "action.bg.primary.disabled": string;
158
- "action.fg.primary": string;
159
- "action.bg.primary.subtle": string;
160
- "action.bg.primary.subtle.hover": string;
161
- "action.bg.primary.subtle.active": string;
162
- "action.bg.primary.subtle.disabled": string;
163
- "action.fg.primary.subtle": string;
164
- "action.bg.secondary": string;
165
- "action.fg.secondary": string;
166
- "action.bg.secondary.subtle": string;
167
- "action.bg.secondary.subtle.hover": string;
168
- "action.bg.secondary.subtle.active": string;
169
- "action.bg.secondary.subtle.disabled": string;
170
- "action.fg.secondary.subtle": string;
148
+ "focus.ring": string;
149
+ "accent.border": string;
150
+ // accent and neutral families
151
+ "accent.solid.bg": string;
152
+ "accent.solid.bg.hover": string;
153
+ "accent.solid.bg.pressed": string;
154
+ "accent.solid.bg.disabled": string;
155
+ "accent.solid.fg": string;
156
+ "accent.soft.bg": string;
157
+ "accent.soft.bg.hover": string;
158
+ "accent.soft.bg.pressed": string;
159
+ "accent.soft.bg.disabled": string;
160
+ "accent.soft.fg": string;
161
+ "neutral.solid.bg": string;
162
+ "neutral.solid.fg": string;
163
+ "neutral.soft.bg": string;
164
+ "neutral.soft.bg.hover": string;
165
+ "neutral.soft.bg.pressed": string;
166
+ "neutral.soft.bg.disabled": string;
167
+ "neutral.soft.fg": string;
171
168
  // status — success
172
- "status.success": string;
173
- "status.success.bg": string;
174
- "status.success.bg.subtle": string;
175
- "status.success.border": string;
176
- "status.success.border.subtle": string;
177
- "status.success.fg": string;
178
- "status.success.fg.subtle": string;
169
+ "success.text": string;
170
+ "success.solid.bg": string;
171
+ "success.soft.bg": string;
172
+ "success.solid.border": string;
173
+ "success.soft.border": string;
174
+ "success.solid.fg": string;
175
+ "success.soft.fg": string;
179
176
  // status — warning
180
- "status.warning": string;
181
- "status.warning.bg": string;
182
- "status.warning.bg.subtle": string;
183
- "status.warning.border": string;
184
- "status.warning.border.subtle": string;
185
- "status.warning.fg": string;
186
- "status.warning.fg.subtle": string;
177
+ "warning.text": string;
178
+ "warning.solid.bg": string;
179
+ "warning.soft.bg": string;
180
+ "warning.solid.border": string;
181
+ "warning.soft.border": string;
182
+ "warning.solid.fg": string;
183
+ "warning.soft.fg": string;
187
184
  // status — danger
188
- "status.danger": string;
189
- "status.danger.bg": string;
190
- "status.danger.bg.subtle": string;
191
- "status.danger.border": string;
192
- "status.danger.border.subtle": string;
193
- "status.danger.fg": string;
194
- "status.danger.fg.subtle": string;
185
+ "danger.text": string;
186
+ "danger.solid.bg": string;
187
+ "danger.soft.bg": string;
188
+ "danger.solid.border": string;
189
+ "danger.soft.border": string;
190
+ "danger.solid.fg": string;
191
+ "danger.soft.fg": string;
195
192
  // status — info
196
- "status.info": string;
197
- "status.info.bg": string;
198
- "status.info.bg.subtle": string;
199
- "status.info.border": string;
200
- "status.info.border.subtle": string;
201
- "status.info.fg": string;
202
- "status.info.fg.subtle": string;
193
+ "info.text": string;
194
+ "info.solid.bg": string;
195
+ "info.soft.bg": string;
196
+ "info.solid.border": string;
197
+ "info.soft.border": string;
198
+ "info.solid.fg": string;
199
+ "info.soft.fg": string;
203
200
  }
204
201
 
202
+ declare global {
203
+ namespace TerraUI {
204
+ /**
205
+ * Augment to declare app-specific semantic color keys. Declared keys become
206
+ * valid in `shared` / `schemes` / accent overrides, `theme.color`, and
207
+ * component color props. Keys must not collide with built-in canonical or
208
+ * deprecated names. Type augmentation alone cannot prove a value exists at
209
+ * runtime — provide every declared color through `shared` or both `schemes`.
210
+ *
211
+ * @example
212
+ * declare global {
213
+ * namespace TerraUI {
214
+ * interface ColorRegistry {
215
+ * "brand.highlight": string;
216
+ * }
217
+ * }
218
+ * }
219
+ */
220
+ interface ColorRegistry {}
221
+ }
222
+ }
223
+
224
+ export interface TerraColorRegistry extends TerraUI.ColorRegistry {}
225
+
226
+ /** App-declared custom color names (see {@link TerraUI.ColorRegistry}). */
227
+ export type TerraCustomColorName = keyof TerraColorRegistry & string;
228
+
229
+ /**
230
+ * Custom color keys that collide with a built-in canonical or deprecated name.
231
+ * Resolves to `never` for a valid registry; apps can assert
232
+ * `const ok: TerraColorRegistryCollision extends never ? true : never = true`.
233
+ */
234
+ export type TerraColorRegistryCollision = Extract<
235
+ keyof TerraUI.ColorRegistry,
236
+ keyof CanonicalThemeColor | keyof LegacyThemeColor
237
+ >;
238
+
239
+ export interface ThemeColor extends CanonicalThemeColor, LegacyThemeColor, TerraColorRegistry {}
240
+
205
241
  // ─── Full theme ──────────────────────────────────────────────────────────────
206
242
 
207
- /** State-layer opacities for disabled / pressed feedback. */
243
+ /** Component opacity multipliers for disabled / pressed feedback. */
208
244
  export interface OpacityTokens {
209
245
  disabled: number;
210
246
  pressed: number;
211
247
  }
212
248
 
249
+ export interface ScreenPaddingTokens {
250
+ x: Record<BreakpointName, number>;
251
+ y: Record<BreakpointName, number>;
252
+ }
253
+
213
254
  /** Screen-level layout tokens. */
214
255
  export interface LayoutTokens {
215
256
  screen: {
216
257
  /**
217
- * Margin between content and the screen edge (applied as container
218
- * padding). Both axes scale with the viewport breakpoint — resolve with
219
- * `resolveBreakpointValue(theme.layout.screen.margin.x, rt.breakpoint)`
258
+ * Internal space between content and the screen edge. Both axes scale with
259
+ * the viewport breakpoint — resolve with
260
+ * `resolveBreakpointValue(theme.layout.screen.padding.x, rt.breakpoint)`
220
261
  * (same for `y`).
221
262
  */
222
- margin: {
223
- x: Record<BreakpointName, number>;
224
- y: Record<BreakpointName, number>;
225
- };
263
+ padding: ScreenPaddingTokens;
264
+ /** @deprecated Use `padding`. */
265
+ margin: ScreenPaddingTokens;
226
266
  };
227
267
  header: {
228
268
  /** Height of the header bar (compact nav bar / collapsed large-title bar), dp. */
@@ -243,51 +283,82 @@ export interface TerraTheme {
243
283
 
244
284
  // ─── Color token paths (component prop surface) ──────────────────────────────
245
285
 
246
- export type BackgroundColorToken = "background";
286
+ export type BackgroundColorToken = "surface.canvas" | "background";
247
287
  export type SurfaceColorToken = Extract<keyof ThemeColor, `surface.${string}`>;
248
288
  export type TextColorToken = Extract<keyof ThemeColor, `text.${string}`>;
249
289
  export type BorderColorToken = Extract<keyof ThemeColor, `border.${string}`>;
250
- export type ActionColorToken = Extract<keyof ThemeColor, `action.${string}`>;
251
- export type StatusColorToken = Extract<keyof ThemeColor, `status.${string}`>;
290
+ export type AccentColorToken = Extract<keyof CanonicalThemeColor, `accent.${string}`>;
291
+ export type NeutralColorToken = Extract<keyof CanonicalThemeColor, `neutral.${string}`>;
292
+ /** @deprecated Prefer AccentColorToken or NeutralColorToken. */
293
+ export type ActionColorToken =
294
+ | AccentColorToken
295
+ | NeutralColorToken
296
+ | Extract<keyof ThemeColor, `action.${string}`>;
297
+ export type StatusColorToken = Extract<
298
+ keyof ThemeColor,
299
+ `${"success" | "warning" | "danger" | "info"}.${string}` | `status.${string}`
300
+ >;
252
301
 
253
302
  /** @deprecated Use {@link TextColorToken} — renamed to reflect the `text.*` token namespace. */
254
303
  export type ContentColorToken = TextColorToken;
255
304
 
256
305
  /**
257
306
  * Any color value a component accepts:
258
- * semantic token (`text.default`, `surface.raised`, `action.bg.primary`),
307
+ * semantic token (`text.primary`, `surface.raised`, `accent.solid.bg`),
259
308
  * or a raw CSS color literal (`#fff`, `rgb(...)`, `transparent`).
260
309
  */
261
- export type ColorToken =
262
- | BackgroundColorToken
263
- | SurfaceColorToken
264
- | TextColorToken
265
- | BorderColorToken
266
- | ActionColorToken
267
- | StatusColorToken
268
- // literals last so token autocomplete still surfaces
269
- | (string & {});
310
+ export type ColorToken = keyof ThemeColor | (string & {});
270
311
 
271
312
  // ─── Configuration / accents ─────────────────────────────────────────────────
272
313
 
273
314
  export type Scheme = "light" | "dark";
274
315
 
275
- /** A hue shorthand per scheme — expands to primary + accent token patches. */
276
- export interface AccentShorthand {
277
- light: string;
278
- dark: string;
279
- }
316
+ /**
317
+ * How the active scheme is chosen. `system` follows the OS appearance;
318
+ * `light` / `dark` pin a scheme and stop following the system.
319
+ */
320
+ export type ThemeMode = "system" | "light" | "dark";
280
321
 
281
- /** A full partial-theme override per scheme. */
282
- export interface AccentOverride {
283
- light?: DeepPartial<TerraTheme>;
284
- dark?: DeepPartial<TerraTheme>;
322
+ /**
323
+ * A seed-generated accent with local exceptions. The seed is a starting color
324
+ * for the accent family, not a promise that `accent.solid.bg` equals it — pin
325
+ * `accent.solid.bg` in `overrides` when an exact fill is required.
326
+ */
327
+ export interface AccentSeed {
328
+ /** Opaque six-digit sRGB hex (`#rrggbb`). Other formats are rejected at configure time. */
329
+ seed: string;
330
+ /**
331
+ * Flat semantic color patch applied after generation. Within the patch a
332
+ * canonical name beats its deprecated alias; across layers an explicit
333
+ * override beats every generated value.
334
+ */
335
+ overrides?: Partial<ThemeColor>;
285
336
  }
286
337
 
287
- /** A named, runtime-switchable theme override. */
288
- export type Accent = AccentShorthand | AccentOverride;
338
+ /**
339
+ * One scheme's accent input:
340
+ * - a color string — equivalent to `{ seed: value }`;
341
+ * - `{ seed, overrides }` — generation with explicit exceptions;
342
+ * - a full {@link TerraThemeOverride} — skips generation (expert path).
343
+ */
344
+ export type AccentSchemeInput = string | AccentSeed | TerraThemeOverride;
345
+
346
+ /**
347
+ * A named, runtime-switchable overlay on each scheme. A missing scheme leaves
348
+ * that scheme unmodified; the other scheme's seed is never copied implicitly.
349
+ */
350
+ export type Accent = Partial<Record<Scheme, AccentSchemeInput>>;
351
+
352
+ /** @deprecated Use {@link Accent} — a color string per scheme. */
353
+ export type AccentShorthand = Record<Scheme, string>;
354
+
355
+ /** @deprecated Use {@link Accent} — a {@link TerraThemeOverride} per scheme. */
356
+ export type AccentOverride = Partial<Record<Scheme, TerraThemeOverride>>;
289
357
 
290
- /** An accent input normalized to per-scheme partial-theme overrides. */
358
+ /**
359
+ * The compatibility output of `normalizeAccent`: per-scheme partial-theme
360
+ * overrides generated against the default themes.
361
+ */
291
362
  export interface NormalizedAccent {
292
363
  light: DeepPartial<TerraTheme>;
293
364
  dark: DeepPartial<TerraTheme>;
@@ -422,8 +493,26 @@ export interface TerraConfig {
422
493
  defaultAccent?: string;
423
494
  /** Per-component default props (e.g. `{ button: { radius: 'full' } }`). */
424
495
  components?: ComponentDefaults;
425
- /** Follow the system color scheme. Default `true`. */
496
+ /**
497
+ * Initial theme mode. `system` follows the OS appearance; `light` / `dark`
498
+ * pin a scheme. Wins over the deprecated `initialScheme` / `adaptiveThemes`
499
+ * when supplied. Defaults to `system`.
500
+ */
501
+ mode?: ThemeMode;
502
+ /** @deprecated Use `mode`. Follow the system color scheme. Default `true`. */
426
503
  adaptiveThemes?: boolean;
427
- /** Force a starting scheme (disables adaptive theming). */
504
+ /** @deprecated Use `mode`. Force a starting scheme (disables adaptive theming). */
428
505
  initialScheme?: Scheme;
429
506
  }
507
+
508
+ /** The subset of {@link TerraConfig} that affects resolved theme tokens. */
509
+ export type TerraThemeInput = Pick<TerraConfig, "shared" | "schemes" | "accents" | "defaultAccent">;
510
+
511
+ /** Options for pure theme creation. */
512
+ export interface CreateTerraThemesOptions {
513
+ /**
514
+ * Accent to overlay. Omitted → `defaultAccent`; `null` → the base themes
515
+ * with no accent. An unknown name throws.
516
+ */
517
+ accent?: string | null;
518
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * The only module under `theme/` that talks to `react-native-unistyles`.
3
+ * Three narrow operations: configure once, replace the registered themes,
4
+ * apply a theme mode. Nothing here reads or writes Terra's own state —
5
+ * `registry.ts` / `runtime.ts` decide what to publish and when.
6
+ */
7
+ import { StyleSheet, UnistylesRuntime } from "react-native-unistyles";
8
+
9
+ import { breakpoints } from "./breakpoints";
10
+ import type { Scheme, TerraTheme, ThemeMode } from "./types";
11
+
12
+ let configured = false;
13
+
14
+ /** Whether `StyleSheet.configure` has run in this app. Exposed for tests. */
15
+ export const hasConfiguredUnistyles = (): boolean => configured;
16
+
17
+ /**
18
+ * Maps a Terra theme mode onto Unistyles startup settings: `system` follows the
19
+ * OS appearance; a scheme pins the starting theme (adaptive off).
20
+ */
21
+ const settingsFor = (mode: ThemeMode) =>
22
+ mode === "system" ? { adaptiveThemes: true as const } : { initialTheme: mode };
23
+
24
+ /**
25
+ * Registers themes, settings and breakpoints with Unistyles. This is a one-time
26
+ * startup call per app: calling `StyleSheet.configure` again leaves the themes
27
+ * it already registered in place, so a second call here is a programming error.
28
+ * Once configured, replace themes with {@link updateThemes} and change the mode
29
+ * with {@link applyMode} instead.
30
+ */
31
+ export function configureUnistyles({
32
+ themes,
33
+ mode,
34
+ }: {
35
+ themes: Record<Scheme, TerraTheme>;
36
+ mode: ThemeMode;
37
+ }): void {
38
+ if (configured) {
39
+ throw new Error(
40
+ "[react-native-terra-ui] configureUnistyles() was called twice; use updateThemes()/applyMode() after the first configure."
41
+ );
42
+ }
43
+ StyleSheet.configure({ themes, settings: settingsFor(mode), breakpoints });
44
+ configured = true;
45
+ }
46
+
47
+ /**
48
+ * Replaces both registered themes.
49
+ *
50
+ * NOT an atomic transaction: Unistyles exposes one `updateTheme` per scheme, so
51
+ * `light` is replaced first, then `dark`. If the second call throws, the native
52
+ * runtime holds the new `light` theme and the previous `dark` theme. Callers
53
+ * publish registry/selection state only after this returns, so on a throw Terra
54
+ * still reports the previous selection; calling the same command again with the
55
+ * previous selection (e.g. `applyAccent(getCurrentAccent() ?? null)`) rewrites
56
+ * both themes and restores consistency. No automatic rollback is attempted.
57
+ */
58
+ export function updateThemes(themes: Record<Scheme, TerraTheme>): void {
59
+ UnistylesRuntime.updateTheme("light", () => themes.light);
60
+ UnistylesRuntime.updateTheme("dark", () => themes.dark);
61
+ }
62
+
63
+ /**
64
+ * Applies a theme mode to the live runtime: `system` re-enables adaptive
65
+ * theming; a scheme disables it (so the next OS appearance change does not
66
+ * override the choice) and then selects that scheme.
67
+ */
68
+ export function applyMode(mode: ThemeMode): void {
69
+ if (mode === "system") {
70
+ UnistylesRuntime.setAdaptiveThemes(true);
71
+ return;
72
+ }
73
+ UnistylesRuntime.setAdaptiveThemes(false);
74
+ UnistylesRuntime.setTheme(mode);
75
+ }