react-native-terra-ui 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.
Files changed (379) hide show
  1. package/README.md +70 -0
  2. package/lib/module/components/avatar/Avatar.js +121 -0
  3. package/lib/module/components/avatar/Avatar.js.map +1 -0
  4. package/lib/module/components/avatar/index.js +4 -0
  5. package/lib/module/components/avatar/index.js.map +1 -0
  6. package/lib/module/components/avatar/types.js +4 -0
  7. package/lib/module/components/avatar/types.js.map +1 -0
  8. package/lib/module/components/box/Box.js +49 -0
  9. package/lib/module/components/box/Box.js.map +1 -0
  10. package/lib/module/components/box/index.js +4 -0
  11. package/lib/module/components/box/index.js.map +1 -0
  12. package/lib/module/components/box/utils.js +95 -0
  13. package/lib/module/components/box/utils.js.map +1 -0
  14. package/lib/module/components/button/Button.js +281 -0
  15. package/lib/module/components/button/Button.js.map +1 -0
  16. package/lib/module/components/button/index.js +4 -0
  17. package/lib/module/components/button/index.js.map +1 -0
  18. package/lib/module/components/header/Header.js +25 -0
  19. package/lib/module/components/header/Header.js.map +1 -0
  20. package/lib/module/components/header/header-buttons.js +65 -0
  21. package/lib/module/components/header/header-buttons.js.map +1 -0
  22. package/lib/module/components/header/index.js +7 -0
  23. package/lib/module/components/header/index.js.map +1 -0
  24. package/lib/module/components/header/variants/LargeTitleHeader/index.js +335 -0
  25. package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -0
  26. package/lib/module/components/header/variants/TitleHeader/index.js +184 -0
  27. package/lib/module/components/header/variants/TitleHeader/index.js.map +1 -0
  28. package/lib/module/components/icon/Icon.js +53 -0
  29. package/lib/module/components/icon/Icon.js.map +1 -0
  30. package/lib/module/components/icon/index.js +4 -0
  31. package/lib/module/components/icon/index.js.map +1 -0
  32. package/lib/module/components/icon/utils.js +188 -0
  33. package/lib/module/components/icon/utils.js.map +1 -0
  34. package/lib/module/components/index.js +16 -0
  35. package/lib/module/components/index.js.map +1 -0
  36. package/lib/module/components/page-indicator/PageIndicator.js +49 -0
  37. package/lib/module/components/page-indicator/PageIndicator.js.map +1 -0
  38. package/lib/module/components/page-indicator/PageIndicatorRoot.js +24 -0
  39. package/lib/module/components/page-indicator/PageIndicatorRoot.js.map +1 -0
  40. package/lib/module/components/page-indicator/hooks/use-page-indicator-colors.js +24 -0
  41. package/lib/module/components/page-indicator/hooks/use-page-indicator-colors.js.map +1 -0
  42. package/lib/module/components/page-indicator/hooks/use-page-indicator-core.js +20 -0
  43. package/lib/module/components/page-indicator/hooks/use-page-indicator-core.js.map +1 -0
  44. package/lib/module/components/page-indicator/hooks/use-page-indicator-progress.js +68 -0
  45. package/lib/module/components/page-indicator/hooks/use-page-indicator-progress.js.map +1 -0
  46. package/lib/module/components/page-indicator/index.js +5 -0
  47. package/lib/module/components/page-indicator/index.js.map +1 -0
  48. package/lib/module/components/page-indicator/utils.js +127 -0
  49. package/lib/module/components/page-indicator/utils.js.map +1 -0
  50. package/lib/module/components/page-indicator/variants/DotIndicator/InactiveDot.js +50 -0
  51. package/lib/module/components/page-indicator/variants/DotIndicator/InactiveDot.js.map +1 -0
  52. package/lib/module/components/page-indicator/variants/DotIndicator/LoadingOrbit.js +165 -0
  53. package/lib/module/components/page-indicator/variants/DotIndicator/LoadingOrbit.js.map +1 -0
  54. package/lib/module/components/page-indicator/variants/DotIndicator/TravelingPill.js +60 -0
  55. package/lib/module/components/page-indicator/variants/DotIndicator/TravelingPill.js.map +1 -0
  56. package/lib/module/components/page-indicator/variants/DotIndicator/index.js +87 -0
  57. package/lib/module/components/page-indicator/variants/DotIndicator/index.js.map +1 -0
  58. package/lib/module/components/page-indicator/variants/DotIndicator/utils.js +28 -0
  59. package/lib/module/components/page-indicator/variants/DotIndicator/utils.js.map +1 -0
  60. package/lib/module/components/page-indicator/variants/PillIndicator/PillIndicatorDot.js +53 -0
  61. package/lib/module/components/page-indicator/variants/PillIndicator/PillIndicatorDot.js.map +1 -0
  62. package/lib/module/components/page-indicator/variants/PillIndicator/index.js +76 -0
  63. package/lib/module/components/page-indicator/variants/PillIndicator/index.js.map +1 -0
  64. package/lib/module/components/page-indicator/variants/PillIndicator/utils.js +47 -0
  65. package/lib/module/components/page-indicator/variants/PillIndicator/utils.js.map +1 -0
  66. package/lib/module/components/portal/PortalContext.js +20 -0
  67. package/lib/module/components/portal/PortalContext.js.map +1 -0
  68. package/lib/module/components/portal/PortalHost.js +23 -0
  69. package/lib/module/components/portal/PortalHost.js.map +1 -0
  70. package/lib/module/components/portal/PortalProvider.js +40 -0
  71. package/lib/module/components/portal/PortalProvider.js.map +1 -0
  72. package/lib/module/components/portal/index.js +6 -0
  73. package/lib/module/components/portal/index.js.map +1 -0
  74. package/lib/module/components/screen/Screen.js +100 -0
  75. package/lib/module/components/screen/Screen.js.map +1 -0
  76. package/lib/module/components/screen/ScreenContext.js +66 -0
  77. package/lib/module/components/screen/ScreenContext.js.map +1 -0
  78. package/lib/module/components/screen/ScreenFlatList.js +75 -0
  79. package/lib/module/components/screen/ScreenFlatList.js.map +1 -0
  80. package/lib/module/components/screen/ScreenScrollView.js +82 -0
  81. package/lib/module/components/screen/ScreenScrollView.js.map +1 -0
  82. package/lib/module/components/screen/index.js +7 -0
  83. package/lib/module/components/screen/index.js.map +1 -0
  84. package/lib/module/components/screen/utils.js +13 -0
  85. package/lib/module/components/screen/utils.js.map +1 -0
  86. package/lib/module/components/slot/Slot.js +38 -0
  87. package/lib/module/components/slot/Slot.js.map +1 -0
  88. package/lib/module/components/slot/index.js +10 -0
  89. package/lib/module/components/slot/index.js.map +1 -0
  90. package/lib/module/components/slot/utils.js +55 -0
  91. package/lib/module/components/slot/utils.js.map +1 -0
  92. package/lib/module/components/spinner/Spinner.js +132 -0
  93. package/lib/module/components/spinner/Spinner.js.map +1 -0
  94. package/lib/module/components/spinner/index.js +4 -0
  95. package/lib/module/components/spinner/index.js.map +1 -0
  96. package/lib/module/components/surface/Surface.js +74 -0
  97. package/lib/module/components/surface/Surface.js.map +1 -0
  98. package/lib/module/components/surface/index.js +4 -0
  99. package/lib/module/components/surface/index.js.map +1 -0
  100. package/lib/module/components/text/Text.js +67 -0
  101. package/lib/module/components/text/Text.js.map +1 -0
  102. package/lib/module/components/text/index.js +4 -0
  103. package/lib/module/components/text/index.js.map +1 -0
  104. package/lib/module/components/toast/Toast.js +350 -0
  105. package/lib/module/components/toast/Toast.js.map +1 -0
  106. package/lib/module/components/toast/ToastProvider.js +272 -0
  107. package/lib/module/components/toast/ToastProvider.js.map +1 -0
  108. package/lib/module/components/toast/index.js +5 -0
  109. package/lib/module/components/toast/index.js.map +1 -0
  110. package/lib/module/components/toast/parts/ToastAnimatedItem.js +168 -0
  111. package/lib/module/components/toast/parts/ToastAnimatedItem.js.map +1 -0
  112. package/lib/module/components/toast/types.js +4 -0
  113. package/lib/module/components/toast/types.js.map +1 -0
  114. package/lib/module/components/toast/utils/controller.js +19 -0
  115. package/lib/module/components/toast/utils/controller.js.map +1 -0
  116. package/lib/module/context/ThemeProvider.js +66 -0
  117. package/lib/module/context/ThemeProvider.js.map +1 -0
  118. package/lib/module/context/index.js +4 -0
  119. package/lib/module/context/index.js.map +1 -0
  120. package/lib/module/index.js +8 -0
  121. package/lib/module/index.js.map +1 -0
  122. package/lib/module/package.json +1 -0
  123. package/lib/module/theme/configure.js +152 -0
  124. package/lib/module/theme/configure.js.map +1 -0
  125. package/lib/module/theme/index.js +22 -0
  126. package/lib/module/theme/index.js.map +1 -0
  127. package/lib/module/theme/runtime.js +25 -0
  128. package/lib/module/theme/runtime.js.map +1 -0
  129. package/lib/module/theme/theme.js +121 -0
  130. package/lib/module/theme/theme.js.map +1 -0
  131. package/lib/module/theme/tokens/dark.js +109 -0
  132. package/lib/module/theme/tokens/dark.js.map +1 -0
  133. package/lib/module/theme/tokens/light.js +115 -0
  134. package/lib/module/theme/tokens/light.js.map +1 -0
  135. package/lib/module/theme/tokens/primitives.js +228 -0
  136. package/lib/module/theme/tokens/primitives.js.map +1 -0
  137. package/lib/module/theme/types.js +4 -0
  138. package/lib/module/theme/types.js.map +1 -0
  139. package/lib/module/types.js +2 -0
  140. package/lib/module/types.js.map +1 -0
  141. package/lib/module/utils/accent-utils.js +52 -0
  142. package/lib/module/utils/accent-utils.js.map +1 -0
  143. package/lib/module/utils/color-utils.js +53 -0
  144. package/lib/module/utils/color-utils.js.map +1 -0
  145. package/lib/module/utils/deep-merge.js +28 -0
  146. package/lib/module/utils/deep-merge.js.map +1 -0
  147. package/lib/module/utils/resolve-theme-color.js +20 -0
  148. package/lib/module/utils/resolve-theme-color.js.map +1 -0
  149. package/lib/module/utils/typography.js +13 -0
  150. package/lib/module/utils/typography.js.map +1 -0
  151. package/lib/module/utils/unflatten.js +35 -0
  152. package/lib/module/utils/unflatten.js.map +1 -0
  153. package/lib/typescript/package.json +1 -0
  154. package/lib/typescript/src/components/avatar/Avatar.d.ts +3 -0
  155. package/lib/typescript/src/components/avatar/Avatar.d.ts.map +1 -0
  156. package/lib/typescript/src/components/avatar/index.d.ts +3 -0
  157. package/lib/typescript/src/components/avatar/index.d.ts.map +1 -0
  158. package/lib/typescript/src/components/avatar/types.d.ts +30 -0
  159. package/lib/typescript/src/components/avatar/types.d.ts.map +1 -0
  160. package/lib/typescript/src/components/box/Box.d.ts +12 -0
  161. package/lib/typescript/src/components/box/Box.d.ts.map +1 -0
  162. package/lib/typescript/src/components/box/index.d.ts +4 -0
  163. package/lib/typescript/src/components/box/index.d.ts.map +1 -0
  164. package/lib/typescript/src/components/box/utils.d.ts +39 -0
  165. package/lib/typescript/src/components/box/utils.d.ts.map +1 -0
  166. package/lib/typescript/src/components/button/Button.d.ts +46 -0
  167. package/lib/typescript/src/components/button/Button.d.ts.map +1 -0
  168. package/lib/typescript/src/components/button/index.d.ts +3 -0
  169. package/lib/typescript/src/components/button/index.d.ts.map +1 -0
  170. package/lib/typescript/src/components/header/Header.d.ts +22 -0
  171. package/lib/typescript/src/components/header/Header.d.ts.map +1 -0
  172. package/lib/typescript/src/components/header/header-buttons.d.ts +16 -0
  173. package/lib/typescript/src/components/header/header-buttons.d.ts.map +1 -0
  174. package/lib/typescript/src/components/header/index.d.ts +7 -0
  175. package/lib/typescript/src/components/header/index.d.ts.map +1 -0
  176. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts +25 -0
  177. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -0
  178. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts +28 -0
  179. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts.map +1 -0
  180. package/lib/typescript/src/components/icon/Icon.d.ts +22 -0
  181. package/lib/typescript/src/components/icon/Icon.d.ts.map +1 -0
  182. package/lib/typescript/src/components/icon/index.d.ts +3 -0
  183. package/lib/typescript/src/components/icon/index.d.ts.map +1 -0
  184. package/lib/typescript/src/components/icon/utils.d.ts +4 -0
  185. package/lib/typescript/src/components/icon/utils.d.ts.map +1 -0
  186. package/lib/typescript/src/components/index.d.ts +14 -0
  187. package/lib/typescript/src/components/index.d.ts.map +1 -0
  188. package/lib/typescript/src/components/page-indicator/PageIndicator.d.ts +48 -0
  189. package/lib/typescript/src/components/page-indicator/PageIndicator.d.ts.map +1 -0
  190. package/lib/typescript/src/components/page-indicator/PageIndicatorRoot.d.ts +13 -0
  191. package/lib/typescript/src/components/page-indicator/PageIndicatorRoot.d.ts.map +1 -0
  192. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-colors.d.ts +14 -0
  193. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-colors.d.ts.map +1 -0
  194. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-core.d.ts +11 -0
  195. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-core.d.ts.map +1 -0
  196. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-progress.d.ts +19 -0
  197. package/lib/typescript/src/components/page-indicator/hooks/use-page-indicator-progress.d.ts.map +1 -0
  198. package/lib/typescript/src/components/page-indicator/index.d.ts +4 -0
  199. package/lib/typescript/src/components/page-indicator/index.d.ts.map +1 -0
  200. package/lib/typescript/src/components/page-indicator/utils.d.ts +36 -0
  201. package/lib/typescript/src/components/page-indicator/utils.d.ts.map +1 -0
  202. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/InactiveDot.d.ts +14 -0
  203. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/InactiveDot.d.ts.map +1 -0
  204. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/LoadingOrbit.d.ts +11 -0
  205. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/LoadingOrbit.d.ts.map +1 -0
  206. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/TravelingPill.d.ts +15 -0
  207. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/TravelingPill.d.ts.map +1 -0
  208. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/index.d.ts +32 -0
  209. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/index.d.ts.map +1 -0
  210. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/utils.d.ts +14 -0
  211. package/lib/typescript/src/components/page-indicator/variants/DotIndicator/utils.d.ts.map +1 -0
  212. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/PillIndicatorDot.d.ts +16 -0
  213. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/PillIndicatorDot.d.ts.map +1 -0
  214. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/index.d.ts +28 -0
  215. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/index.d.ts.map +1 -0
  216. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/utils.d.ts +21 -0
  217. package/lib/typescript/src/components/page-indicator/variants/PillIndicator/utils.d.ts.map +1 -0
  218. package/lib/typescript/src/components/portal/PortalContext.d.ts +19 -0
  219. package/lib/typescript/src/components/portal/PortalContext.d.ts.map +1 -0
  220. package/lib/typescript/src/components/portal/PortalHost.d.ts +7 -0
  221. package/lib/typescript/src/components/portal/PortalHost.d.ts.map +1 -0
  222. package/lib/typescript/src/components/portal/PortalProvider.d.ts +11 -0
  223. package/lib/typescript/src/components/portal/PortalProvider.d.ts.map +1 -0
  224. package/lib/typescript/src/components/portal/index.d.ts +6 -0
  225. package/lib/typescript/src/components/portal/index.d.ts.map +1 -0
  226. package/lib/typescript/src/components/screen/Screen.d.ts +53 -0
  227. package/lib/typescript/src/components/screen/Screen.d.ts.map +1 -0
  228. package/lib/typescript/src/components/screen/ScreenContext.d.ts +64 -0
  229. package/lib/typescript/src/components/screen/ScreenContext.d.ts.map +1 -0
  230. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts +26 -0
  231. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -0
  232. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts +36 -0
  233. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -0
  234. package/lib/typescript/src/components/screen/index.d.ts +9 -0
  235. package/lib/typescript/src/components/screen/index.d.ts.map +1 -0
  236. package/lib/typescript/src/components/screen/utils.d.ts +10 -0
  237. package/lib/typescript/src/components/screen/utils.d.ts.map +1 -0
  238. package/lib/typescript/src/components/slot/Slot.d.ts +17 -0
  239. package/lib/typescript/src/components/slot/Slot.d.ts.map +1 -0
  240. package/lib/typescript/src/components/slot/index.d.ts +8 -0
  241. package/lib/typescript/src/components/slot/index.d.ts.map +1 -0
  242. package/lib/typescript/src/components/slot/utils.d.ts +17 -0
  243. package/lib/typescript/src/components/slot/utils.d.ts.map +1 -0
  244. package/lib/typescript/src/components/spinner/Spinner.d.ts +18 -0
  245. package/lib/typescript/src/components/spinner/Spinner.d.ts.map +1 -0
  246. package/lib/typescript/src/components/spinner/index.d.ts +3 -0
  247. package/lib/typescript/src/components/spinner/index.d.ts.map +1 -0
  248. package/lib/typescript/src/components/surface/Surface.d.ts +31 -0
  249. package/lib/typescript/src/components/surface/Surface.d.ts.map +1 -0
  250. package/lib/typescript/src/components/surface/index.d.ts +3 -0
  251. package/lib/typescript/src/components/surface/index.d.ts.map +1 -0
  252. package/lib/typescript/src/components/text/Text.d.ts +23 -0
  253. package/lib/typescript/src/components/text/Text.d.ts.map +1 -0
  254. package/lib/typescript/src/components/text/index.d.ts +3 -0
  255. package/lib/typescript/src/components/text/index.d.ts.map +1 -0
  256. package/lib/typescript/src/components/toast/Toast.d.ts +71 -0
  257. package/lib/typescript/src/components/toast/Toast.d.ts.map +1 -0
  258. package/lib/typescript/src/components/toast/ToastProvider.d.ts +4 -0
  259. package/lib/typescript/src/components/toast/ToastProvider.d.ts.map +1 -0
  260. package/lib/typescript/src/components/toast/index.d.ts +5 -0
  261. package/lib/typescript/src/components/toast/index.d.ts.map +1 -0
  262. package/lib/typescript/src/components/toast/parts/ToastAnimatedItem.d.ts +18 -0
  263. package/lib/typescript/src/components/toast/parts/ToastAnimatedItem.d.ts.map +1 -0
  264. package/lib/typescript/src/components/toast/types.d.ts +62 -0
  265. package/lib/typescript/src/components/toast/types.d.ts.map +1 -0
  266. package/lib/typescript/src/components/toast/utils/controller.d.ts +5 -0
  267. package/lib/typescript/src/components/toast/utils/controller.d.ts.map +1 -0
  268. package/lib/typescript/src/context/ThemeProvider.d.ts +29 -0
  269. package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -0
  270. package/lib/typescript/src/context/index.d.ts +3 -0
  271. package/lib/typescript/src/context/index.d.ts.map +1 -0
  272. package/lib/typescript/src/index.d.ts +4 -0
  273. package/lib/typescript/src/index.d.ts.map +1 -0
  274. package/lib/typescript/src/theme/configure.d.ts +47 -0
  275. package/lib/typescript/src/theme/configure.d.ts.map +1 -0
  276. package/lib/typescript/src/theme/index.d.ts +11 -0
  277. package/lib/typescript/src/theme/index.d.ts.map +1 -0
  278. package/lib/typescript/src/theme/runtime.d.ts +7 -0
  279. package/lib/typescript/src/theme/runtime.d.ts.map +1 -0
  280. package/lib/typescript/src/theme/theme.d.ts +22 -0
  281. package/lib/typescript/src/theme/theme.d.ts.map +1 -0
  282. package/lib/typescript/src/theme/tokens/dark.d.ts +100 -0
  283. package/lib/typescript/src/theme/tokens/dark.d.ts.map +1 -0
  284. package/lib/typescript/src/theme/tokens/light.d.ts +106 -0
  285. package/lib/typescript/src/theme/tokens/light.d.ts.map +1 -0
  286. package/lib/typescript/src/theme/tokens/primitives.d.ts +212 -0
  287. package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -0
  288. package/lib/typescript/src/theme/types.d.ts +273 -0
  289. package/lib/typescript/src/theme/types.d.ts.map +1 -0
  290. package/lib/typescript/src/types.d.ts +4 -0
  291. package/lib/typescript/src/types.d.ts.map +1 -0
  292. package/lib/typescript/src/utils/accent-utils.d.ts +4 -0
  293. package/lib/typescript/src/utils/accent-utils.d.ts.map +1 -0
  294. package/lib/typescript/src/utils/color-utils.d.ts +11 -0
  295. package/lib/typescript/src/utils/color-utils.d.ts.map +1 -0
  296. package/lib/typescript/src/utils/deep-merge.d.ts +11 -0
  297. package/lib/typescript/src/utils/deep-merge.d.ts.map +1 -0
  298. package/lib/typescript/src/utils/resolve-theme-color.d.ts +12 -0
  299. package/lib/typescript/src/utils/resolve-theme-color.d.ts.map +1 -0
  300. package/lib/typescript/src/utils/typography.d.ts +6 -0
  301. package/lib/typescript/src/utils/typography.d.ts.map +1 -0
  302. package/lib/typescript/src/utils/unflatten.d.ts +12 -0
  303. package/lib/typescript/src/utils/unflatten.d.ts.map +1 -0
  304. package/package.json +137 -0
  305. package/src/components/avatar/Avatar.tsx +146 -0
  306. package/src/components/avatar/index.ts +8 -0
  307. package/src/components/avatar/types.ts +35 -0
  308. package/src/components/box/Box.tsx +59 -0
  309. package/src/components/box/index.ts +8 -0
  310. package/src/components/box/utils.ts +181 -0
  311. package/src/components/button/Button.tsx +313 -0
  312. package/src/components/button/index.ts +8 -0
  313. package/src/components/header/Header.ts +22 -0
  314. package/src/components/header/header-buttons.tsx +103 -0
  315. package/src/components/header/index.ts +11 -0
  316. package/src/components/header/variants/LargeTitleHeader/index.tsx +390 -0
  317. package/src/components/header/variants/TitleHeader/index.tsx +194 -0
  318. package/src/components/icon/Icon.tsx +74 -0
  319. package/src/components/icon/index.ts +2 -0
  320. package/src/components/icon/utils.tsx +147 -0
  321. package/src/components/index.ts +13 -0
  322. package/src/components/page-indicator/PageIndicator.tsx +100 -0
  323. package/src/components/page-indicator/PageIndicatorRoot.tsx +41 -0
  324. package/src/components/page-indicator/hooks/use-page-indicator-colors.ts +65 -0
  325. package/src/components/page-indicator/hooks/use-page-indicator-core.ts +34 -0
  326. package/src/components/page-indicator/hooks/use-page-indicator-progress.ts +122 -0
  327. package/src/components/page-indicator/index.ts +13 -0
  328. package/src/components/page-indicator/utils.ts +208 -0
  329. package/src/components/page-indicator/variants/DotIndicator/InactiveDot.tsx +70 -0
  330. package/src/components/page-indicator/variants/DotIndicator/LoadingOrbit.tsx +201 -0
  331. package/src/components/page-indicator/variants/DotIndicator/TravelingPill.tsx +80 -0
  332. package/src/components/page-indicator/variants/DotIndicator/index.tsx +145 -0
  333. package/src/components/page-indicator/variants/DotIndicator/utils.ts +28 -0
  334. package/src/components/page-indicator/variants/PillIndicator/PillIndicatorDot.tsx +107 -0
  335. package/src/components/page-indicator/variants/PillIndicator/index.tsx +149 -0
  336. package/src/components/page-indicator/variants/PillIndicator/utils.ts +63 -0
  337. package/src/components/portal/PortalContext.tsx +27 -0
  338. package/src/components/portal/PortalHost.tsx +20 -0
  339. package/src/components/portal/PortalProvider.tsx +44 -0
  340. package/src/components/portal/index.ts +5 -0
  341. package/src/components/screen/Screen.tsx +163 -0
  342. package/src/components/screen/ScreenContext.tsx +144 -0
  343. package/src/components/screen/ScreenFlatList.tsx +121 -0
  344. package/src/components/screen/ScreenScrollView.tsx +130 -0
  345. package/src/components/screen/index.ts +8 -0
  346. package/src/components/screen/utils.ts +17 -0
  347. package/src/components/slot/Slot.tsx +56 -0
  348. package/src/components/slot/index.ts +8 -0
  349. package/src/components/slot/utils.ts +61 -0
  350. package/src/components/spinner/Spinner.tsx +153 -0
  351. package/src/components/spinner/index.ts +2 -0
  352. package/src/components/surface/Surface.tsx +100 -0
  353. package/src/components/surface/index.ts +2 -0
  354. package/src/components/text/Text.tsx +115 -0
  355. package/src/components/text/index.ts +2 -0
  356. package/src/components/toast/Toast.tsx +477 -0
  357. package/src/components/toast/ToastProvider.tsx +403 -0
  358. package/src/components/toast/index.ts +26 -0
  359. package/src/components/toast/parts/ToastAnimatedItem.tsx +184 -0
  360. package/src/components/toast/types.ts +75 -0
  361. package/src/components/toast/utils/controller.ts +23 -0
  362. package/src/context/ThemeProvider.tsx +97 -0
  363. package/src/context/index.ts +2 -0
  364. package/src/index.tsx +6 -0
  365. package/src/theme/configure.ts +215 -0
  366. package/src/theme/index.ts +72 -0
  367. package/src/theme/runtime.ts +27 -0
  368. package/src/theme/theme.ts +152 -0
  369. package/src/theme/tokens/dark.ts +117 -0
  370. package/src/theme/tokens/light.ts +123 -0
  371. package/src/theme/tokens/primitives.ts +232 -0
  372. package/src/theme/types.ts +384 -0
  373. package/src/types.ts +1 -0
  374. package/src/utils/accent-utils.ts +58 -0
  375. package/src/utils/color-utils.ts +51 -0
  376. package/src/utils/deep-merge.ts +36 -0
  377. package/src/utils/resolve-theme-color.ts +27 -0
  378. package/src/utils/typography.ts +15 -0
  379. package/src/utils/unflatten.ts +36 -0
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Theme typing — the single source of truth for every consumer-facing and
3
+ * structural theme type. The token DATA (tokens/*.ts) is intentionally
4
+ * untyped (Figma-generated); these types describe the runtime theme that the
5
+ * data is unflattened into, plus the public configuration surface.
6
+ */
7
+ import type { ComponentType } from 'react';
8
+ import type { ImageStyle, StyleProp } from 'react-native';
9
+
10
+ import type { DeepPartial } from '#utils/deep-merge';
11
+
12
+ // ─── Scale keys (declared explicitly; token data is untyped) ────────────────
13
+
14
+ /** Spacing scale keys (dp, 4dp base unit). Read as `gap={3}` → string '3'. */
15
+ export type SpacingKey =
16
+ | '0'
17
+ | '1'
18
+ | '2'
19
+ | '3'
20
+ | '4'
21
+ | '5'
22
+ | '6'
23
+ | '7'
24
+ | '8'
25
+ | '9'
26
+ | '10'
27
+ | '12'
28
+ | '14'
29
+ | '16'
30
+ | '20'
31
+ | '24'
32
+ | '32';
33
+
34
+ /** Border-radius scale keys. */
35
+ export type RadiusKey =
36
+ | 'none'
37
+ | 'xs'
38
+ | 'sm'
39
+ | 'md'
40
+ | 'lg'
41
+ | 'xl'
42
+ | '2xl'
43
+ | '3xl'
44
+ | 'full';
45
+
46
+ /**
47
+ * The radius tokens offered as a component default. Excludes the extreme/rare
48
+ * steps (`xs`, `2xl`, `3xl`).
49
+ */
50
+ export type DefaultRadiusToken = 'sm' | 'md' | 'lg' | 'xl' | 'full';
51
+
52
+ /** Components whose default appearance can be configured. */
53
+ export type RadiusComponent = 'button' | 'surface';
54
+
55
+ // ─── Elevation ──────────────────────────────────────────────────────────────
56
+
57
+ /** Elevation preset — platform-aware shadow + Android elevation. */
58
+ export interface ElevationStyle {
59
+ shadowColor: string;
60
+ shadowOpacity: number;
61
+ shadowRadius: number;
62
+ shadowOffset: { width: number; height: number };
63
+ /** Android elevation. */
64
+ elevation: number;
65
+ }
66
+
67
+ export type ElevationKey = 'none' | 'sm' | 'md' | 'lg' | 'xl';
68
+
69
+ export type ElevationScale = Record<ElevationKey, ElevationStyle>;
70
+
71
+ // ─── Typography ──────────────────────────────────────────────────────────────
72
+
73
+ export type RoleTextVariant =
74
+ | 'display-lg'
75
+ | 'display-md'
76
+ | 'display-sm'
77
+ | 'headline-lg'
78
+ | 'headline-md'
79
+ | 'headline-sm'
80
+ | 'title-lg'
81
+ | 'title-md'
82
+ | 'title-sm'
83
+ | 'body-lg'
84
+ | 'body-md'
85
+ | 'body-sm'
86
+ | 'label-lg'
87
+ | 'label-md'
88
+ | 'label-sm'
89
+ | 'caption';
90
+
91
+ export type HeadingTextVariant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
92
+
93
+ export type TextVariant = RoleTextVariant | HeadingTextVariant;
94
+
95
+ export type FontWeightToken = 'regular' | 'medium' | 'semibold' | 'bold';
96
+
97
+ export interface TypeStyle {
98
+ fontSize: number;
99
+ lineHeight: number;
100
+ fontWeight: FontWeightToken;
101
+ /** Tracking, dp. */
102
+ letterSpacing: number;
103
+ /** Cap OS Dynamic Type scaling to protect layout. */
104
+ maxFontSizeMultiplier: number;
105
+ }
106
+
107
+ export interface Typography {
108
+ /**
109
+ * Weight token → font-family name. Defaults to the system font.
110
+ * For custom fonts, point each weight at its own family
111
+ * (e.g. { regular: 'Inter-Regular', semibold: 'Inter-SemiBold' }).
112
+ */
113
+ fonts: Record<FontWeightToken, string>;
114
+ variants: Record<RoleTextVariant, TypeStyle>;
115
+ }
116
+
117
+ // ─── Semantic color tier ─────────────────────────────────────────────────────
118
+
119
+ /**
120
+ * Flat color token map — keys are dotted paths matching the token schema
121
+ * (category prefix `color.` stripped). Accessed as `theme.color['text.default']`.
122
+ */
123
+ export interface ThemeColor {
124
+ // page background
125
+ background: string;
126
+ // surfaces
127
+ 'surface.default': string;
128
+ 'surface.raised': string;
129
+ 'surface.sunken': string;
130
+ 'surface.overlay': string;
131
+ 'surface.accent': string;
132
+ 'surface.accent.subtle': string;
133
+ // text / icons
134
+ 'text.default': string;
135
+ 'text.muted': string;
136
+ 'text.subtle': string;
137
+ 'text.disabled': string;
138
+ 'text.inverse': string;
139
+ 'text.link': string;
140
+ 'text.accent': string;
141
+ 'text.on-accent': string;
142
+ 'text.on-accent-subtle': string;
143
+ // borders
144
+ 'border.subtle': string;
145
+ 'border.default': string;
146
+ 'border.strong': string;
147
+ 'border.focus': string;
148
+ 'border.accent': string;
149
+ // interactive actions
150
+ 'action.bg.primary': string;
151
+ 'action.bg.primary.hover': string;
152
+ 'action.bg.primary.active': string;
153
+ 'action.bg.primary.disabled': string;
154
+ 'action.fg.primary': string;
155
+ 'action.bg.subtle': string;
156
+ 'action.bg.subtle.hover': string;
157
+ 'action.bg.subtle.active': string;
158
+ 'action.bg.subtle.disabled': string;
159
+ 'action.fg.subtle': string;
160
+ 'action.bg.neutral': string;
161
+ 'action.bg.neutral.hover': string;
162
+ 'action.bg.neutral.active': string;
163
+ 'action.bg.neutral.disabled': string;
164
+ 'action.fg.neutral': string;
165
+ // status — success
166
+ 'status.bg.success': string;
167
+ 'status.bg.success.subtle': string;
168
+ 'status.border.success': string;
169
+ 'status.border.success.subtle': string;
170
+ 'status.fg.success': string;
171
+ 'status.fg.success.subtle': string;
172
+ // status — warning
173
+ 'status.bg.warning': string;
174
+ 'status.bg.warning.subtle': string;
175
+ 'status.border.warning': string;
176
+ 'status.border.warning.subtle': string;
177
+ 'status.fg.warning': string;
178
+ 'status.fg.warning.subtle': string;
179
+ // status — danger
180
+ 'status.bg.danger': string;
181
+ 'status.bg.danger.subtle': string;
182
+ 'status.border.danger': string;
183
+ 'status.border.danger.subtle': string;
184
+ 'status.fg.danger': string;
185
+ 'status.fg.danger.subtle': string;
186
+ // status — info
187
+ 'status.bg.info': string;
188
+ 'status.bg.info.subtle': string;
189
+ 'status.border.info': string;
190
+ 'status.border.info.subtle': string;
191
+ 'status.fg.info': string;
192
+ 'status.fg.info.subtle': string;
193
+ }
194
+
195
+ // ─── Full theme ──────────────────────────────────────────────────────────────
196
+
197
+ /** State-layer opacities for disabled / pressed feedback. */
198
+ export interface OpacityTokens {
199
+ disabled: number;
200
+ pressed: number;
201
+ }
202
+
203
+ /** Screen-level layout tokens. */
204
+ export interface LayoutTokens {
205
+ screen: {
206
+ /** Margin between content and the screen edge (applied as container padding). */
207
+ margin: { x: number; y: number };
208
+ };
209
+ header: {
210
+ /** Height of the header bar (compact nav bar / collapsed large-title bar), dp. */
211
+ height: number;
212
+ };
213
+ }
214
+
215
+ /** The full resolved theme. `light` and `dark` are both `TerraTheme`. */
216
+ export interface TerraTheme {
217
+ color: ThemeColor;
218
+ spacing: Record<SpacingKey, number>;
219
+ radius: Record<RadiusKey, number>;
220
+ typography: Typography;
221
+ elevation: ElevationScale;
222
+ opacity: OpacityTokens;
223
+ layout: LayoutTokens;
224
+ }
225
+
226
+ // ─── Color token paths (component prop surface) ──────────────────────────────
227
+
228
+ export type BackgroundColorToken = 'background';
229
+ export type SurfaceColorToken = Extract<keyof ThemeColor, `surface.${string}`>;
230
+ export type TextColorToken = Extract<keyof ThemeColor, `text.${string}`>;
231
+ export type BorderColorToken = Extract<keyof ThemeColor, `border.${string}`>;
232
+ export type ActionColorToken = Extract<keyof ThemeColor, `action.${string}`>;
233
+ export type StatusColorToken = Extract<keyof ThemeColor, `status.${string}`>;
234
+
235
+ /** @deprecated Use {@link TextColorToken} — renamed to reflect the `text.*` token namespace. */
236
+ export type ContentColorToken = TextColorToken;
237
+
238
+ /**
239
+ * Any color value a component accepts:
240
+ * semantic token (`text.default`, `surface.raised`, `action.bg.primary`),
241
+ * or a raw CSS color literal (`#fff`, `rgb(...)`, `transparent`).
242
+ */
243
+ export type ColorToken =
244
+ | BackgroundColorToken
245
+ | SurfaceColorToken
246
+ | TextColorToken
247
+ | BorderColorToken
248
+ | ActionColorToken
249
+ | StatusColorToken
250
+ // literals last so token autocomplete still surfaces
251
+ | (string & {});
252
+
253
+ // ─── Configuration / accents ─────────────────────────────────────────────────
254
+
255
+ export type Scheme = 'light' | 'dark';
256
+
257
+ /** A hue shorthand per scheme — expands to primary + accent token patches. */
258
+ export interface AccentShorthand {
259
+ light: string;
260
+ dark: string;
261
+ }
262
+
263
+ /** A full partial-theme override per scheme. */
264
+ export interface AccentOverride {
265
+ light?: DeepPartial<TerraTheme>;
266
+ dark?: DeepPartial<TerraTheme>;
267
+ }
268
+
269
+ /** A named, runtime-switchable theme override. */
270
+ export type Accent = AccentShorthand | AccentOverride;
271
+
272
+ /** An accent input normalized to per-scheme partial-theme overrides. */
273
+ export interface NormalizedAccent {
274
+ light: DeepPartial<TerraTheme>;
275
+ dark: DeepPartial<TerraTheme>;
276
+ }
277
+
278
+ export interface TerraIconProps {
279
+ size?: number;
280
+ color?: string;
281
+ strokeWidth?: number;
282
+ }
283
+
284
+ export type TerraIconComponent = ComponentType<TerraIconProps>;
285
+
286
+ // ─── Image ───────────────────────────────────────────────────────────────────
287
+
288
+ export type TerraImageContentFit = 'cover' | 'contain' | 'fill';
289
+
290
+ export interface TerraImageProps {
291
+ source: { uri: string } | number;
292
+ style?: StyleProp<ImageStyle>;
293
+ accessibilityLabel?: string;
294
+ contentFit?: TerraImageContentFit;
295
+ onError?: () => void;
296
+ }
297
+
298
+ export type TerraImageComponent = ComponentType<TerraImageProps>;
299
+
300
+ declare global {
301
+ namespace TerraUI {
302
+ interface IconRegistry {}
303
+ }
304
+ }
305
+
306
+ export interface TerraIconRegistry extends TerraUI.IconRegistry {}
307
+
308
+ export type TerraSemanticIconName =
309
+ | 'navigation.back'
310
+ | 'navigation.forward'
311
+ | 'navigation.close'
312
+ | 'status.info'
313
+ | 'status.success'
314
+ | 'status.warning'
315
+ | 'status.danger'
316
+ | 'person';
317
+
318
+ export type TerraConfiguredIconName = keyof TerraIconRegistry & string;
319
+
320
+ export type TerraIconName = TerraSemanticIconName | TerraConfiguredIconName;
321
+
322
+ export type ThemeRadiusOverride = DeepPartial<TerraTheme['radius']> & {
323
+ /**
324
+ * Base corner radius in dp — the `lg` (×1) step. The rest of the scale is
325
+ * derived by fixed multipliers (`xs` ×0.25, `sm` ×0.5, `md` ×0.75,
326
+ * `xl` ×1.5, `2xl` ×2, `3xl` ×3); `none` (0) and `full` (9999) are
327
+ * constant. Per-token radius overrides still win over the derived value.
328
+ */
329
+ base?: number;
330
+ };
331
+
332
+ /** Theme override accepted at configure time. */
333
+ export type TerraThemeOverride = DeepPartial<Omit<TerraTheme, 'radius'>> & {
334
+ radius?: ThemeRadiusOverride;
335
+ };
336
+
337
+ /** Default props for the Button component. A per-instance prop still wins. */
338
+ export interface ButtonDefaults {
339
+ /** Default corner radius. Defaults to `'md'`. */
340
+ radius?: DefaultRadiusToken;
341
+ }
342
+
343
+ /** Default props for the Surface component. A per-instance prop still wins. */
344
+ export interface SurfaceDefaults {
345
+ /** Default corner radius. Defaults to `'md'`. */
346
+ radius?: DefaultRadiusToken;
347
+ /** Default drop-shadow depth (`'none'` = no shadow). Defaults to `'none'`. */
348
+ elevation?: ElevationKey;
349
+ }
350
+
351
+ /** Per-component default props applied at configure time. */
352
+ export interface ComponentDefaults {
353
+ button?: ButtonDefaults;
354
+ surface?: SurfaceDefaults;
355
+ }
356
+
357
+ export interface TerraConfig {
358
+ /** Scheme-agnostic token overrides, applied to both light and dark themes. */
359
+ shared?: TerraThemeOverride;
360
+ /** Per-scheme token overrides, applied after `shared`. */
361
+ schemes?: { light?: TerraThemeOverride; dark?: TerraThemeOverride };
362
+ /** Runtime-switchable named overrides (hue shorthand or full partial). */
363
+ accents?: Record<string, Accent>;
364
+ /**
365
+ * App-provided icon overrides. Semantic icons (`navigation.*`, `status.*`)
366
+ * fall back to the built-in defaults when omitted; app icons (`add`, etc.)
367
+ * must be registered here.
368
+ */
369
+ icons?: Partial<Record<TerraIconName, TerraIconComponent>>;
370
+ /**
371
+ * Custom image renderer (e.g. `expo-image`, `react-native-fast-image`).
372
+ * Defaults to React Native's built-in `Image` with `contentFit` mapped to
373
+ * `resizeMode`. Wrap third-party components to match `TerraImageProps`.
374
+ */
375
+ image?: TerraImageComponent;
376
+ /** Name of the accent (from `accents`) to apply by default. */
377
+ defaultAccent?: string;
378
+ /** Per-component default props (e.g. `{ button: { radius: 'full' } }`). */
379
+ components?: ComponentDefaults;
380
+ /** Follow the system color scheme. Default `true`. */
381
+ adaptiveThemes?: boolean;
382
+ /** Force a starting scheme (disables adaptive theming). */
383
+ initialScheme?: Scheme;
384
+ }
package/src/types.ts ADDED
@@ -0,0 +1 @@
1
+ export type Mutable<T> = { -readonly [K in keyof T]: T[K] };
@@ -0,0 +1,58 @@
1
+ import type {
2
+ Accent,
3
+ AccentShorthand,
4
+ NormalizedAccent,
5
+ TerraTheme,
6
+ } from '#theme/types';
7
+
8
+ import { readableOn, shade, withAlpha } from './color-utils';
9
+ import type { DeepPartial } from './deep-merge';
10
+
11
+ const isShorthand = (accent: Accent): accent is AccentShorthand =>
12
+ typeof (accent as AccentShorthand).light === 'string' ||
13
+ typeof (accent as AccentShorthand).dark === 'string';
14
+
15
+ /**
16
+ * Expands a single hue into a fuller per-scheme patch so primary AND subtle
17
+ * actions (plus accent text) all recolor consistently:
18
+ * - primary: solid hue with derived hover/active and a legible foreground,
19
+ * - subtle: soft translucent tint of the hue with the hue as foreground,
20
+ * - text.accent / text.link / text.on-accent.
21
+ *
22
+ * On `light` the hover/active darken; on `dark` they lighten.
23
+ */
24
+ function hueToPartial(
25
+ hue: string | undefined,
26
+ scheme: 'light' | 'dark'
27
+ ): DeepPartial<TerraTheme> {
28
+ if (!hue) return {};
29
+ const dir = scheme === 'light' ? -1 : 1;
30
+ const isLight = scheme === 'light';
31
+ const fg = readableOn(hue);
32
+ // Flat color keys to patch — deepMerge replaces string leaves directly.
33
+ const color = {
34
+ 'action.bg.primary': hue,
35
+ 'action.fg.primary': fg,
36
+ 'action.bg.primary.hover': shade(hue, dir * 0.12),
37
+ 'action.bg.primary.active': shade(hue, dir * 0.24),
38
+ 'action.bg.subtle': withAlpha(hue, isLight ? 0.12 : 0.2),
39
+ 'action.fg.subtle': hue,
40
+ 'action.bg.subtle.hover': withAlpha(hue, isLight ? 0.18 : 0.28),
41
+ 'action.bg.subtle.active': withAlpha(hue, isLight ? 0.24 : 0.36),
42
+ 'text.accent': hue,
43
+ 'text.link': hue,
44
+ 'text.on-accent': fg,
45
+ };
46
+ return { color } as unknown as DeepPartial<TerraTheme>;
47
+ }
48
+
49
+ /** Normalizes any accent input into per-scheme partial-theme overrides. */
50
+ export function normalizeAccent(accent: Accent): NormalizedAccent {
51
+ if (isShorthand(accent)) {
52
+ return {
53
+ light: hueToPartial(accent.light, 'light'),
54
+ dark: hueToPartial(accent.dark, 'dark'),
55
+ };
56
+ }
57
+ return { light: accent.light ?? {}, dark: accent.dark ?? {} };
58
+ }
@@ -0,0 +1,51 @@
1
+ /** Small color helpers for deriving accent shades from a single hue. */
2
+
3
+ interface RGB {
4
+ r: number;
5
+ g: number;
6
+ b: number;
7
+ }
8
+
9
+ const clamp = (n: number): number => Math.max(0, Math.min(255, Math.round(n)));
10
+
11
+ function parseHex(hex: string): RGB | null {
12
+ const hex6 = /^#?([0-9a-f]{6})$/i.exec(hex.trim())?.[1];
13
+ if (!hex6) return null;
14
+ const int = Number.parseInt(hex6, 16);
15
+ return { r: (int >> 16) & 255, g: (int >> 8) & 255, b: int & 255 };
16
+ }
17
+
18
+ const toHex = ({ r, g, b }: RGB): string =>
19
+ `#${[r, g, b].map((v) => clamp(v).toString(16).padStart(2, '0')).join('')}`;
20
+
21
+ /**
22
+ * Shifts a hex color toward black (negative `amount`) or white (positive),
23
+ * by a fraction in [-1, 1]. Returns the input unchanged if not a 6-digit hex.
24
+ */
25
+ export function shade(hex: string, amount: number): string {
26
+ const c = parseHex(hex);
27
+ if (!c) return hex;
28
+ const target = amount < 0 ? 0 : 255;
29
+ const t = Math.abs(amount);
30
+ return toHex({
31
+ r: c.r + (target - c.r) * t,
32
+ g: c.g + (target - c.g) * t,
33
+ b: c.b + (target - c.b) * t,
34
+ });
35
+ }
36
+
37
+ /** Returns an `rgba(...)` string for a hex color at the given alpha. */
38
+ export function withAlpha(hex: string, alpha: number): string {
39
+ const c = parseHex(hex);
40
+ if (!c) return hex;
41
+ return `rgba(${c.r}, ${c.g}, ${c.b}, ${alpha})`;
42
+ }
43
+
44
+ /** Picks black or white for legible text/icons on top of `hex`. */
45
+ export function readableOn(hex: string): string {
46
+ const c = parseHex(hex);
47
+ if (!c) return '#ffffff';
48
+ // Perceived luminance (0–1).
49
+ const luminance = (0.299 * c.r + 0.587 * c.g + 0.114 * c.b) / 255;
50
+ return luminance > 0.6 ? '#000000' : '#ffffff';
51
+ }
@@ -0,0 +1,36 @@
1
+ /** Recursively makes every property (and nested property) optional. */
2
+ export type DeepPartial<T> = T extends (infer U)[]
3
+ ? DeepPartial<U>[]
4
+ : T extends object
5
+ ? { [K in keyof T]?: DeepPartial<T[K]> }
6
+ : T;
7
+
8
+ const isPlainObject = (value: unknown): value is Record<string, unknown> =>
9
+ typeof value === 'object' &&
10
+ value !== null &&
11
+ !Array.isArray(value) &&
12
+ Object.getPrototypeOf(value) === Object.prototype;
13
+
14
+ /**
15
+ * Deep-merges `override` onto `base`, returning a new object.
16
+ * Plain objects merge recursively; all other values (and arrays) replace.
17
+ * Neither input is mutated.
18
+ */
19
+ export function deepMerge<T>(base: T, override?: DeepPartial<T>): T {
20
+ if (override === undefined) return base;
21
+ if (!isPlainObject(base) || !isPlainObject(override)) {
22
+ return (override as unknown as T) ?? base;
23
+ }
24
+
25
+ const result: Record<string, unknown> = { ...base };
26
+ for (const key of Object.keys(override)) {
27
+ const overrideValue = (override as Record<string, unknown>)[key];
28
+ if (overrideValue === undefined) continue;
29
+ const baseValue = (base as Record<string, unknown>)[key];
30
+ result[key] =
31
+ isPlainObject(baseValue) && isPlainObject(overrideValue)
32
+ ? deepMerge(baseValue, overrideValue as DeepPartial<typeof baseValue>)
33
+ : overrideValue;
34
+ }
35
+ return result as T;
36
+ }
@@ -0,0 +1,27 @@
1
+ import type { ColorToken, TerraTheme } from '#theme/types';
2
+
3
+ const isColorLiteral = (value: string): boolean =>
4
+ value.startsWith('#') ||
5
+ value.startsWith('rgb') ||
6
+ value.startsWith('hsl') ||
7
+ value === 'transparent' ||
8
+ value === 'currentColor';
9
+
10
+ /**
11
+ * Resolves a {@link ColorToken} to a concrete color string using the theme.
12
+ * Raw literals pass through unchanged.
13
+ *
14
+ * @example
15
+ * resolveThemeColor('text.default', theme) // → '#020618'
16
+ * resolveThemeColor('action.bg.primary', theme) // → '#009966'
17
+ * resolveThemeColor('#ff0000', theme) // → '#ff0000'
18
+ */
19
+ export function resolveThemeColor(
20
+ token: ColorToken | undefined,
21
+ theme: TerraTheme
22
+ ): string | undefined {
23
+ if (!token) return undefined;
24
+ if (isColorLiteral(token)) return token;
25
+ const value = (theme.color as unknown as Record<string, unknown>)[token];
26
+ return typeof value === 'string' ? value : undefined;
27
+ }
@@ -0,0 +1,15 @@
1
+ import type { FontWeightToken } from '#theme/types';
2
+
3
+ /** RN's sentinel for the platform default font (SF on iOS, Roboto on Android). */
4
+ export const SYSTEM_FONT = 'System';
5
+
6
+ /** Numeric fontWeight applied when a weight token maps to the system font. */
7
+ export const FONT_WEIGHT_VALUE: Record<
8
+ FontWeightToken,
9
+ '400' | '500' | '600' | '700'
10
+ > = {
11
+ regular: '400',
12
+ medium: '500',
13
+ semibold: '600',
14
+ bold: '700',
15
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Rebuilds a nested object from a flat map of dotted-path keys.
3
+ *
4
+ * @example
5
+ * unflatten({ 'a.b.c': 1, 'a.b.d': 2 }) // → { a: { b: { c: 1, d: 2 } } }
6
+ *
7
+ * Used to turn the flat, Figma-style token data (tokens/*.ts) back into the
8
+ * nested runtime theme shape that components and Unistyles consume. The caller
9
+ * is responsible for asserting the resulting shape (e.g. `as TerraTheme`).
10
+ */
11
+ export function unflatten<T = unknown>(flat: Record<string, unknown>): T {
12
+ const root: Record<string, unknown> = {};
13
+
14
+ for (const [path, value] of Object.entries(flat)) {
15
+ const segments = path.split('.');
16
+ let node = root;
17
+
18
+ for (let i = 0; i < segments.length - 1; i++) {
19
+ const seg = segments[i];
20
+ if (seg === undefined) continue;
21
+ const next = node[seg];
22
+ if (typeof next === 'object' && next !== null) {
23
+ node = next as Record<string, unknown>;
24
+ } else {
25
+ const created: Record<string, unknown> = {};
26
+ node[seg] = created;
27
+ node = created;
28
+ }
29
+ }
30
+
31
+ const leaf = segments[segments.length - 1];
32
+ if (leaf !== undefined) node[leaf] = value;
33
+ }
34
+
35
+ return root as T;
36
+ }