orn-ui 0.2.10 → 0.3.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 (552) hide show
  1. package/AGENTS.md +66 -51
  2. package/README.md +3 -7
  3. package/lib/commonjs/atoms/Avatar.js +77 -5
  4. package/lib/commonjs/atoms/Avatar.js.map +1 -1
  5. package/lib/commonjs/atoms/Badge.js +17 -8
  6. package/lib/commonjs/atoms/Badge.js.map +1 -1
  7. package/lib/commonjs/atoms/Button.js +108 -39
  8. package/lib/commonjs/atoms/Button.js.map +1 -1
  9. package/lib/commonjs/atoms/Card.js +24 -2
  10. package/lib/commonjs/atoms/Card.js.map +1 -1
  11. package/lib/commonjs/atoms/Checkbox.js +41 -10
  12. package/lib/commonjs/atoms/Checkbox.js.map +1 -1
  13. package/lib/commonjs/atoms/Divider.js +30 -5
  14. package/lib/commonjs/atoms/Divider.js.map +1 -1
  15. package/lib/commonjs/atoms/EmptyState.js +58 -20
  16. package/lib/commonjs/atoms/EmptyState.js.map +1 -1
  17. package/lib/commonjs/atoms/Fab.js +32 -12
  18. package/lib/commonjs/atoms/Fab.js.map +1 -1
  19. package/lib/commonjs/atoms/Gradient.js +102 -36
  20. package/lib/commonjs/atoms/Gradient.js.map +1 -1
  21. package/lib/commonjs/atoms/IconButton.js +25 -4
  22. package/lib/commonjs/atoms/IconButton.js.map +1 -1
  23. package/lib/commonjs/atoms/Image.js +61 -25
  24. package/lib/commonjs/atoms/Image.js.map +1 -1
  25. package/lib/commonjs/atoms/Input.js +105 -17
  26. package/lib/commonjs/atoms/Input.js.map +1 -1
  27. package/lib/commonjs/atoms/KeyValueRow.js +37 -9
  28. package/lib/commonjs/atoms/KeyValueRow.js.map +1 -1
  29. package/lib/commonjs/atoms/PressableScale.js +25 -5
  30. package/lib/commonjs/atoms/PressableScale.js.map +1 -1
  31. package/lib/commonjs/atoms/ShinyText.js +29 -29
  32. package/lib/commonjs/atoms/Skeleton.js +28 -13
  33. package/lib/commonjs/atoms/Skeleton.js.map +1 -1
  34. package/lib/commonjs/atoms/Spinner.js +81 -22
  35. package/lib/commonjs/atoms/Spinner.js.map +1 -1
  36. package/lib/commonjs/atoms/Text.js +56 -5
  37. package/lib/commonjs/atoms/Text.js.map +1 -1
  38. package/lib/commonjs/atoms/Transition.js +46 -43
  39. package/lib/commonjs/atoms/Transition.js.map +1 -1
  40. package/lib/commonjs/atoms/index.js +6 -0
  41. package/lib/commonjs/atoms/index.js.map +1 -1
  42. package/lib/commonjs/atoms/inputValidation.js +56 -0
  43. package/lib/commonjs/atoms/inputValidation.js.map +1 -0
  44. package/lib/commonjs/icons/Icon.js +4 -4
  45. package/lib/commonjs/icons/defaultIcons.js +576 -24
  46. package/lib/commonjs/icons/defaultIcons.js.map +1 -1
  47. package/lib/commonjs/icons/index.js +6 -0
  48. package/lib/commonjs/icons/index.js.map +1 -1
  49. package/lib/commonjs/molecules/AvatarHeader.js +47 -14
  50. package/lib/commonjs/molecules/AvatarHeader.js.map +1 -1
  51. package/lib/commonjs/molecules/FormActions.js +25 -9
  52. package/lib/commonjs/molecules/FormActions.js.map +1 -1
  53. package/lib/commonjs/molecules/InfoRow.js +30 -14
  54. package/lib/commonjs/molecules/InfoRow.js.map +1 -1
  55. package/lib/commonjs/molecules/OptionCard.js +37 -22
  56. package/lib/commonjs/molecules/OptionCard.js.map +1 -1
  57. package/lib/commonjs/molecules/SegmentedControl.js +103 -14
  58. package/lib/commonjs/molecules/SegmentedControl.js.map +1 -1
  59. package/lib/commonjs/molecules/Stepper.js +61 -16
  60. package/lib/commonjs/molecules/Stepper.js.map +1 -1
  61. package/lib/commonjs/molecules/Steps.js +105 -41
  62. package/lib/commonjs/molecules/Steps.js.map +1 -1
  63. package/lib/commonjs/molecules/SymmetricGrid.js +26 -18
  64. package/lib/commonjs/molecules/SymmetricGrid.js.map +1 -1
  65. package/lib/commonjs/organisms/Alert.js +49 -35
  66. package/lib/commonjs/organisms/Alert.js.map +1 -1
  67. package/lib/commonjs/organisms/AlertProvider.js +10 -10
  68. package/lib/commonjs/organisms/BottomSheet.js +137 -85
  69. package/lib/commonjs/organisms/BottomSheet.js.map +1 -1
  70. package/lib/commonjs/organisms/Chart.js +174 -154
  71. package/lib/commonjs/organisms/Chart.js.map +1 -1
  72. package/lib/commonjs/organisms/DateField.js +36 -20
  73. package/lib/commonjs/organisms/DateField.js.map +1 -1
  74. package/lib/commonjs/organisms/DatePicker.js +56 -33
  75. package/lib/commonjs/organisms/DatePicker.js.map +1 -1
  76. package/lib/commonjs/organisms/List.js +62 -34
  77. package/lib/commonjs/organisms/List.js.map +1 -1
  78. package/lib/commonjs/organisms/Modal.js +120 -82
  79. package/lib/commonjs/organisms/Modal.js.map +1 -1
  80. package/lib/commonjs/organisms/NavigationBar.js +63 -24
  81. package/lib/commonjs/organisms/NavigationBar.js.map +1 -1
  82. package/lib/commonjs/organisms/OptionWheel.js +64 -64
  83. package/lib/commonjs/organisms/OptionWheel.js.map +1 -1
  84. package/lib/commonjs/organisms/ReorderableList.js +48 -27
  85. package/lib/commonjs/organisms/ReorderableList.js.map +1 -1
  86. package/lib/commonjs/organisms/Screen.js +68 -35
  87. package/lib/commonjs/organisms/Screen.js.map +1 -1
  88. package/lib/commonjs/organisms/SearchList.js +56 -26
  89. package/lib/commonjs/organisms/SearchList.js.map +1 -1
  90. package/lib/commonjs/organisms/Select.js +45 -24
  91. package/lib/commonjs/organisms/Select.js.map +1 -1
  92. package/lib/commonjs/organisms/Slides.js +36 -23
  93. package/lib/commonjs/organisms/Slides.js.map +1 -1
  94. package/lib/commonjs/organisms/ThemeToggle.js +10 -9
  95. package/lib/commonjs/organisms/ThemeToggle.js.map +1 -1
  96. package/lib/commonjs/organisms/Timeline.js +73 -56
  97. package/lib/commonjs/organisms/Timeline.js.map +1 -1
  98. package/lib/commonjs/organisms/Toast.js +46 -15
  99. package/lib/commonjs/organisms/Toast.js.map +1 -1
  100. package/lib/commonjs/organisms/ToastProvider.js +14 -10
  101. package/lib/commonjs/organisms/ToastProvider.js.map +1 -1
  102. package/lib/commonjs/organisms/Wizard.js +40 -15
  103. package/lib/commonjs/organisms/Wizard.js.map +1 -1
  104. package/lib/commonjs/organisms/chart/frame.js +25 -25
  105. package/lib/commonjs/organisms/chart/frame.js.map +1 -1
  106. package/lib/commonjs/organisms/chart/marks.js +42 -42
  107. package/lib/commonjs/organisms/chart/math.js +84 -85
  108. package/lib/commonjs/organisms/chart/math.js.map +1 -1
  109. package/lib/commonjs/organisms/chart/palette.js +28 -28
  110. package/lib/commonjs/organisms/imperativeBridge.js +5 -5
  111. package/lib/commonjs/organisms/imperativeBridge.js.map +1 -1
  112. package/lib/commonjs/organisms/useSlides.js +53 -21
  113. package/lib/commonjs/organisms/useSlides.js.map +1 -1
  114. package/lib/commonjs/safe-area/SafeAreaUIProvider.js +9 -66
  115. package/lib/commonjs/safe-area/SafeAreaUIProvider.js.map +1 -1
  116. package/lib/commonjs/safe-area/index.js.map +1 -1
  117. package/lib/commonjs/theme/KeyboardAvoidance.js +206 -0
  118. package/lib/commonjs/theme/KeyboardAvoidance.js.map +1 -0
  119. package/lib/commonjs/theme/NativeOverlay.js +263 -0
  120. package/lib/commonjs/theme/NativeOverlay.js.map +1 -0
  121. package/lib/commonjs/theme/UIProvider.js +86 -33
  122. package/lib/commonjs/theme/UIProvider.js.map +1 -1
  123. package/lib/commonjs/theme/colors.js +17 -17
  124. package/lib/commonjs/theme/colors.js.map +1 -1
  125. package/lib/commonjs/theme/createStyles.js +19 -16
  126. package/lib/commonjs/theme/createStyles.js.map +1 -1
  127. package/lib/commonjs/theme/createTheme.js +6 -6
  128. package/lib/commonjs/theme/index.js +6 -0
  129. package/lib/commonjs/theme/index.js.map +1 -1
  130. package/lib/commonjs/theme/insets.js +1 -1
  131. package/lib/commonjs/theme/labels.js +29 -1
  132. package/lib/commonjs/theme/labels.js.map +1 -1
  133. package/lib/commonjs/theme/palettes.js +25 -23
  134. package/lib/commonjs/theme/palettes.js.map +1 -1
  135. package/lib/commonjs/theme/tokens.js +28 -14
  136. package/lib/commonjs/theme/tokens.js.map +1 -1
  137. package/lib/commonjs/theme/useKeyboardField.js +36 -0
  138. package/lib/commonjs/theme/useKeyboardField.js.map +1 -0
  139. package/lib/commonjs/theme/useReduceMotion.js +31 -0
  140. package/lib/commonjs/theme/useReduceMotion.js.map +1 -0
  141. package/lib/module/atoms/Avatar.js +79 -8
  142. package/lib/module/atoms/Avatar.js.map +1 -1
  143. package/lib/module/atoms/Badge.js +17 -8
  144. package/lib/module/atoms/Badge.js.map +1 -1
  145. package/lib/module/atoms/Button.js +110 -41
  146. package/lib/module/atoms/Button.js.map +1 -1
  147. package/lib/module/atoms/Card.js +24 -2
  148. package/lib/module/atoms/Card.js.map +1 -1
  149. package/lib/module/atoms/Checkbox.js +42 -11
  150. package/lib/module/atoms/Checkbox.js.map +1 -1
  151. package/lib/module/atoms/Divider.js +31 -6
  152. package/lib/module/atoms/Divider.js.map +1 -1
  153. package/lib/module/atoms/EmptyState.js +58 -20
  154. package/lib/module/atoms/EmptyState.js.map +1 -1
  155. package/lib/module/atoms/Fab.js +33 -13
  156. package/lib/module/atoms/Fab.js.map +1 -1
  157. package/lib/module/atoms/Gradient.js +103 -37
  158. package/lib/module/atoms/Gradient.js.map +1 -1
  159. package/lib/module/atoms/IconButton.js +25 -4
  160. package/lib/module/atoms/IconButton.js.map +1 -1
  161. package/lib/module/atoms/Image.js +61 -25
  162. package/lib/module/atoms/Image.js.map +1 -1
  163. package/lib/module/atoms/Input.js +108 -20
  164. package/lib/module/atoms/Input.js.map +1 -1
  165. package/lib/module/atoms/KeyValueRow.js +37 -9
  166. package/lib/module/atoms/KeyValueRow.js.map +1 -1
  167. package/lib/module/atoms/PressableScale.js +25 -5
  168. package/lib/module/atoms/PressableScale.js.map +1 -1
  169. package/lib/module/atoms/ShinyText.js +29 -29
  170. package/lib/module/atoms/Skeleton.js +30 -13
  171. package/lib/module/atoms/Skeleton.js.map +1 -1
  172. package/lib/module/atoms/Spinner.js +82 -23
  173. package/lib/module/atoms/Spinner.js.map +1 -1
  174. package/lib/module/atoms/Text.js +56 -5
  175. package/lib/module/atoms/Text.js.map +1 -1
  176. package/lib/module/atoms/Transition.js +41 -42
  177. package/lib/module/atoms/Transition.js.map +1 -1
  178. package/lib/module/atoms/index.js +1 -1
  179. package/lib/module/atoms/index.js.map +1 -1
  180. package/lib/module/atoms/inputValidation.js +52 -0
  181. package/lib/module/atoms/inputValidation.js.map +1 -0
  182. package/lib/module/icons/Icon.js +4 -4
  183. package/lib/module/icons/defaultIcons.js +574 -24
  184. package/lib/module/icons/defaultIcons.js.map +1 -1
  185. package/lib/module/icons/index.js +1 -1
  186. package/lib/module/icons/index.js.map +1 -1
  187. package/lib/module/molecules/AvatarHeader.js +47 -14
  188. package/lib/module/molecules/AvatarHeader.js.map +1 -1
  189. package/lib/module/molecules/FormActions.js +25 -9
  190. package/lib/module/molecules/FormActions.js.map +1 -1
  191. package/lib/module/molecules/InfoRow.js +30 -14
  192. package/lib/module/molecules/InfoRow.js.map +1 -1
  193. package/lib/module/molecules/OptionCard.js +37 -22
  194. package/lib/module/molecules/OptionCard.js.map +1 -1
  195. package/lib/module/molecules/SegmentedControl.js +107 -18
  196. package/lib/module/molecules/SegmentedControl.js.map +1 -1
  197. package/lib/module/molecules/Stepper.js +63 -18
  198. package/lib/module/molecules/Stepper.js.map +1 -1
  199. package/lib/module/molecules/Steps.js +107 -43
  200. package/lib/module/molecules/Steps.js.map +1 -1
  201. package/lib/module/molecules/SymmetricGrid.js +26 -18
  202. package/lib/module/molecules/SymmetricGrid.js.map +1 -1
  203. package/lib/module/organisms/Alert.js +51 -37
  204. package/lib/module/organisms/Alert.js.map +1 -1
  205. package/lib/module/organisms/AlertProvider.js +10 -10
  206. package/lib/module/organisms/BottomSheet.js +142 -88
  207. package/lib/module/organisms/BottomSheet.js.map +1 -1
  208. package/lib/module/organisms/Chart.js +176 -156
  209. package/lib/module/organisms/Chart.js.map +1 -1
  210. package/lib/module/organisms/DateField.js +36 -20
  211. package/lib/module/organisms/DateField.js.map +1 -1
  212. package/lib/module/organisms/DatePicker.js +56 -33
  213. package/lib/module/organisms/DatePicker.js.map +1 -1
  214. package/lib/module/organisms/List.js +62 -34
  215. package/lib/module/organisms/List.js.map +1 -1
  216. package/lib/module/organisms/Modal.js +122 -84
  217. package/lib/module/organisms/Modal.js.map +1 -1
  218. package/lib/module/organisms/NavigationBar.js +64 -25
  219. package/lib/module/organisms/NavigationBar.js.map +1 -1
  220. package/lib/module/organisms/OptionWheel.js +64 -64
  221. package/lib/module/organisms/OptionWheel.js.map +1 -1
  222. package/lib/module/organisms/ReorderableList.js +48 -27
  223. package/lib/module/organisms/ReorderableList.js.map +1 -1
  224. package/lib/module/organisms/Screen.js +70 -37
  225. package/lib/module/organisms/Screen.js.map +1 -1
  226. package/lib/module/organisms/SearchList.js +56 -26
  227. package/lib/module/organisms/SearchList.js.map +1 -1
  228. package/lib/module/organisms/Select.js +46 -25
  229. package/lib/module/organisms/Select.js.map +1 -1
  230. package/lib/module/organisms/Slides.js +37 -24
  231. package/lib/module/organisms/Slides.js.map +1 -1
  232. package/lib/module/organisms/ThemeToggle.js +11 -10
  233. package/lib/module/organisms/ThemeToggle.js.map +1 -1
  234. package/lib/module/organisms/Timeline.js +73 -56
  235. package/lib/module/organisms/Timeline.js.map +1 -1
  236. package/lib/module/organisms/Toast.js +47 -16
  237. package/lib/module/organisms/Toast.js.map +1 -1
  238. package/lib/module/organisms/ToastProvider.js +15 -11
  239. package/lib/module/organisms/ToastProvider.js.map +1 -1
  240. package/lib/module/organisms/Wizard.js +41 -16
  241. package/lib/module/organisms/Wizard.js.map +1 -1
  242. package/lib/module/organisms/chart/frame.js +25 -25
  243. package/lib/module/organisms/chart/frame.js.map +1 -1
  244. package/lib/module/organisms/chart/marks.js +42 -42
  245. package/lib/module/organisms/chart/math.js +84 -85
  246. package/lib/module/organisms/chart/math.js.map +1 -1
  247. package/lib/module/organisms/chart/palette.js +28 -28
  248. package/lib/module/organisms/imperativeBridge.js +5 -5
  249. package/lib/module/organisms/imperativeBridge.js.map +1 -1
  250. package/lib/module/organisms/useSlides.js +53 -21
  251. package/lib/module/organisms/useSlides.js.map +1 -1
  252. package/lib/module/safe-area/SafeAreaUIProvider.js +10 -65
  253. package/lib/module/safe-area/SafeAreaUIProvider.js.map +1 -1
  254. package/lib/module/safe-area/index.js +1 -0
  255. package/lib/module/safe-area/index.js.map +1 -1
  256. package/lib/module/theme/KeyboardAvoidance.js +198 -0
  257. package/lib/module/theme/KeyboardAvoidance.js.map +1 -0
  258. package/lib/module/theme/NativeOverlay.js +257 -0
  259. package/lib/module/theme/NativeOverlay.js.map +1 -0
  260. package/lib/module/theme/UIProvider.js +88 -35
  261. package/lib/module/theme/UIProvider.js.map +1 -1
  262. package/lib/module/theme/colors.js +17 -17
  263. package/lib/module/theme/colors.js.map +1 -1
  264. package/lib/module/theme/createStyles.js +20 -16
  265. package/lib/module/theme/createStyles.js.map +1 -1
  266. package/lib/module/theme/createTheme.js +6 -6
  267. package/lib/module/theme/index.js +1 -1
  268. package/lib/module/theme/index.js.map +1 -1
  269. package/lib/module/theme/insets.js +1 -1
  270. package/lib/module/theme/labels.js +29 -1
  271. package/lib/module/theme/labels.js.map +1 -1
  272. package/lib/module/theme/palettes.js +25 -23
  273. package/lib/module/theme/palettes.js.map +1 -1
  274. package/lib/module/theme/tokens.js +27 -13
  275. package/lib/module/theme/tokens.js.map +1 -1
  276. package/lib/module/theme/useKeyboardField.js +33 -0
  277. package/lib/module/theme/useKeyboardField.js.map +1 -0
  278. package/lib/module/theme/useReduceMotion.js +28 -0
  279. package/lib/module/theme/useReduceMotion.js.map +1 -0
  280. package/lib/typescript/atoms/Avatar.d.ts +35 -5
  281. package/lib/typescript/atoms/Avatar.d.ts.map +1 -1
  282. package/lib/typescript/atoms/Badge.d.ts +14 -3
  283. package/lib/typescript/atoms/Badge.d.ts.map +1 -1
  284. package/lib/typescript/atoms/Button.d.ts +34 -3
  285. package/lib/typescript/atoms/Button.d.ts.map +1 -1
  286. package/lib/typescript/atoms/Card.d.ts +13 -2
  287. package/lib/typescript/atoms/Card.d.ts.map +1 -1
  288. package/lib/typescript/atoms/Checkbox.d.ts +26 -1
  289. package/lib/typescript/atoms/Checkbox.d.ts.map +1 -1
  290. package/lib/typescript/atoms/Divider.d.ts +18 -1
  291. package/lib/typescript/atoms/Divider.d.ts.map +1 -1
  292. package/lib/typescript/atoms/EmptyState.d.ts +30 -3
  293. package/lib/typescript/atoms/EmptyState.d.ts.map +1 -1
  294. package/lib/typescript/atoms/Fab.d.ts +24 -4
  295. package/lib/typescript/atoms/Fab.d.ts.map +1 -1
  296. package/lib/typescript/atoms/Gradient.d.ts +21 -15
  297. package/lib/typescript/atoms/Gradient.d.ts.map +1 -1
  298. package/lib/typescript/atoms/IconButton.d.ts +18 -4
  299. package/lib/typescript/atoms/IconButton.d.ts.map +1 -1
  300. package/lib/typescript/atoms/Image.d.ts +39 -17
  301. package/lib/typescript/atoms/Image.d.ts.map +1 -1
  302. package/lib/typescript/atoms/Input.d.ts +57 -7
  303. package/lib/typescript/atoms/Input.d.ts.map +1 -1
  304. package/lib/typescript/atoms/KeyValueRow.d.ts +16 -4
  305. package/lib/typescript/atoms/KeyValueRow.d.ts.map +1 -1
  306. package/lib/typescript/atoms/PressableScale.d.ts +12 -5
  307. package/lib/typescript/atoms/PressableScale.d.ts.map +1 -1
  308. package/lib/typescript/atoms/ShinyText.d.ts +17 -17
  309. package/lib/typescript/atoms/ShinyText.d.ts.map +1 -1
  310. package/lib/typescript/atoms/Skeleton.d.ts +12 -7
  311. package/lib/typescript/atoms/Skeleton.d.ts.map +1 -1
  312. package/lib/typescript/atoms/Spinner.d.ts +29 -1
  313. package/lib/typescript/atoms/Spinner.d.ts.map +1 -1
  314. package/lib/typescript/atoms/Text.d.ts +46 -0
  315. package/lib/typescript/atoms/Text.d.ts.map +1 -1
  316. package/lib/typescript/atoms/Transition.d.ts +19 -15
  317. package/lib/typescript/atoms/Transition.d.ts.map +1 -1
  318. package/lib/typescript/atoms/index.d.ts +3 -3
  319. package/lib/typescript/atoms/index.d.ts.map +1 -1
  320. package/lib/typescript/atoms/inputValidation.d.ts +29 -0
  321. package/lib/typescript/atoms/inputValidation.d.ts.map +1 -0
  322. package/lib/typescript/icons/Icon.d.ts +4 -4
  323. package/lib/typescript/icons/defaultIcons.d.ts +19 -2
  324. package/lib/typescript/icons/defaultIcons.d.ts.map +1 -1
  325. package/lib/typescript/icons/index.d.ts +2 -2
  326. package/lib/typescript/icons/index.d.ts.map +1 -1
  327. package/lib/typescript/icons/types.d.ts +13 -3
  328. package/lib/typescript/icons/types.d.ts.map +1 -1
  329. package/lib/typescript/molecules/AvatarHeader.d.ts +23 -4
  330. package/lib/typescript/molecules/AvatarHeader.d.ts.map +1 -1
  331. package/lib/typescript/molecules/FormActions.d.ts +21 -4
  332. package/lib/typescript/molecules/FormActions.d.ts.map +1 -1
  333. package/lib/typescript/molecules/InfoRow.d.ts +17 -3
  334. package/lib/typescript/molecules/InfoRow.d.ts.map +1 -1
  335. package/lib/typescript/molecules/OptionCard.d.ts +20 -5
  336. package/lib/typescript/molecules/OptionCard.d.ts.map +1 -1
  337. package/lib/typescript/molecules/SegmentedControl.d.ts +18 -2
  338. package/lib/typescript/molecules/SegmentedControl.d.ts.map +1 -1
  339. package/lib/typescript/molecules/Stepper.d.ts +23 -7
  340. package/lib/typescript/molecules/Stepper.d.ts.map +1 -1
  341. package/lib/typescript/molecules/Steps.d.ts +18 -4
  342. package/lib/typescript/molecules/Steps.d.ts.map +1 -1
  343. package/lib/typescript/molecules/SymmetricGrid.d.ts +15 -5
  344. package/lib/typescript/molecules/SymmetricGrid.d.ts.map +1 -1
  345. package/lib/typescript/organisms/Alert.d.ts +28 -2
  346. package/lib/typescript/organisms/Alert.d.ts.map +1 -1
  347. package/lib/typescript/organisms/AlertProvider.d.ts +10 -10
  348. package/lib/typescript/organisms/AlertProvider.d.ts.map +1 -1
  349. package/lib/typescript/organisms/BottomSheet.d.ts +20 -5
  350. package/lib/typescript/organisms/BottomSheet.d.ts.map +1 -1
  351. package/lib/typescript/organisms/Chart.d.ts +86 -75
  352. package/lib/typescript/organisms/Chart.d.ts.map +1 -1
  353. package/lib/typescript/organisms/DateField.d.ts +17 -3
  354. package/lib/typescript/organisms/DateField.d.ts.map +1 -1
  355. package/lib/typescript/organisms/DatePicker.d.ts +7 -11
  356. package/lib/typescript/organisms/DatePicker.d.ts.map +1 -1
  357. package/lib/typescript/organisms/List.d.ts +30 -3
  358. package/lib/typescript/organisms/List.d.ts.map +1 -1
  359. package/lib/typescript/organisms/Modal.d.ts +30 -3
  360. package/lib/typescript/organisms/Modal.d.ts.map +1 -1
  361. package/lib/typescript/organisms/NavigationBar.d.ts +26 -7
  362. package/lib/typescript/organisms/NavigationBar.d.ts.map +1 -1
  363. package/lib/typescript/organisms/OptionWheel.d.ts +20 -16
  364. package/lib/typescript/organisms/OptionWheel.d.ts.map +1 -1
  365. package/lib/typescript/organisms/ReorderableList.d.ts +20 -11
  366. package/lib/typescript/organisms/ReorderableList.d.ts.map +1 -1
  367. package/lib/typescript/organisms/Screen.d.ts +27 -8
  368. package/lib/typescript/organisms/Screen.d.ts.map +1 -1
  369. package/lib/typescript/organisms/SearchList.d.ts +46 -3
  370. package/lib/typescript/organisms/SearchList.d.ts.map +1 -1
  371. package/lib/typescript/organisms/Select.d.ts +26 -6
  372. package/lib/typescript/organisms/Select.d.ts.map +1 -1
  373. package/lib/typescript/organisms/Slides.d.ts +44 -26
  374. package/lib/typescript/organisms/Slides.d.ts.map +1 -1
  375. package/lib/typescript/organisms/ThemeToggle.d.ts +6 -2
  376. package/lib/typescript/organisms/ThemeToggle.d.ts.map +1 -1
  377. package/lib/typescript/organisms/Timeline.d.ts +26 -9
  378. package/lib/typescript/organisms/Timeline.d.ts.map +1 -1
  379. package/lib/typescript/organisms/Toast.d.ts +19 -4
  380. package/lib/typescript/organisms/Toast.d.ts.map +1 -1
  381. package/lib/typescript/organisms/ToastProvider.d.ts +8 -8
  382. package/lib/typescript/organisms/ToastProvider.d.ts.map +1 -1
  383. package/lib/typescript/organisms/Wizard.d.ts +24 -6
  384. package/lib/typescript/organisms/Wizard.d.ts.map +1 -1
  385. package/lib/typescript/organisms/chart/frame.d.ts +21 -21
  386. package/lib/typescript/organisms/chart/frame.d.ts.map +1 -1
  387. package/lib/typescript/organisms/chart/marks.d.ts +28 -28
  388. package/lib/typescript/organisms/chart/marks.d.ts.map +1 -1
  389. package/lib/typescript/organisms/chart/math.d.ts +69 -70
  390. package/lib/typescript/organisms/chart/math.d.ts.map +1 -1
  391. package/lib/typescript/organisms/chart/palette.d.ts +2 -2
  392. package/lib/typescript/organisms/chart/palette.d.ts.map +1 -1
  393. package/lib/typescript/organisms/imperativeBridge.d.ts +4 -4
  394. package/lib/typescript/organisms/useSlides.d.ts +8 -16
  395. package/lib/typescript/organisms/useSlides.d.ts.map +1 -1
  396. package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts +9 -7
  397. package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts.map +1 -1
  398. package/lib/typescript/safe-area/index.d.ts.map +1 -1
  399. package/lib/typescript/theme/KeyboardAvoidance.d.ts +62 -0
  400. package/lib/typescript/theme/KeyboardAvoidance.d.ts.map +1 -0
  401. package/lib/typescript/theme/NativeOverlay.d.ts +43 -0
  402. package/lib/typescript/theme/NativeOverlay.d.ts.map +1 -0
  403. package/lib/typescript/theme/UIProvider.d.ts +38 -20
  404. package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
  405. package/lib/typescript/theme/colors.d.ts +13 -13
  406. package/lib/typescript/theme/colors.d.ts.map +1 -1
  407. package/lib/typescript/theme/createStyles.d.ts +20 -14
  408. package/lib/typescript/theme/createStyles.d.ts.map +1 -1
  409. package/lib/typescript/theme/createTheme.d.ts +5 -5
  410. package/lib/typescript/theme/index.d.ts +1 -1
  411. package/lib/typescript/theme/index.d.ts.map +1 -1
  412. package/lib/typescript/theme/insets.d.ts +1 -1
  413. package/lib/typescript/theme/insets.d.ts.map +1 -1
  414. package/lib/typescript/theme/labels.d.ts +57 -2
  415. package/lib/typescript/theme/labels.d.ts.map +1 -1
  416. package/lib/typescript/theme/palettes.d.ts +25 -19
  417. package/lib/typescript/theme/palettes.d.ts.map +1 -1
  418. package/lib/typescript/theme/tokens.d.ts +15 -8
  419. package/lib/typescript/theme/tokens.d.ts.map +1 -1
  420. package/lib/typescript/theme/types.d.ts +7 -7
  421. package/lib/typescript/theme/types.d.ts.map +1 -1
  422. package/lib/typescript/theme/useKeyboardField.d.ts +17 -0
  423. package/lib/typescript/theme/useKeyboardField.d.ts.map +1 -0
  424. package/lib/typescript/theme/useReduceMotion.d.ts +7 -0
  425. package/lib/typescript/theme/useReduceMotion.d.ts.map +1 -0
  426. package/llms.txt +4 -4
  427. package/package.json +15 -14
  428. package/registry/alert-provider.json +4 -3
  429. package/registry/alert.json +3 -2
  430. package/registry/avatar-header.json +1 -1
  431. package/registry/avatar.json +3 -2
  432. package/registry/badge.json +1 -1
  433. package/registry/bottom-sheet.json +1 -1
  434. package/registry/button.json +3 -2
  435. package/registry/card.json +1 -1
  436. package/registry/chart.json +5 -5
  437. package/registry/checkbox.json +3 -2
  438. package/registry/core.json +31 -15
  439. package/registry/date-field.json +1 -1
  440. package/registry/date-picker.json +3 -2
  441. package/registry/divider.json +1 -1
  442. package/registry/empty-state.json +4 -2
  443. package/registry/fab.json +3 -2
  444. package/registry/form-actions.json +3 -2
  445. package/registry/gradient.json +1 -1
  446. package/registry/icon-button.json +3 -2
  447. package/registry/image.json +1 -1
  448. package/registry/index.json +79 -61
  449. package/registry/info-row.json +1 -1
  450. package/registry/input.json +5 -1
  451. package/registry/key-value-row.json +1 -1
  452. package/registry/list.json +3 -1
  453. package/registry/manifest.json +3 -1
  454. package/registry/modal.json +1 -1
  455. package/registry/navigation-bar.json +1 -1
  456. package/registry/option-card.json +3 -2
  457. package/registry/option-wheel.json +1 -1
  458. package/registry/pressable-scale.json +3 -2
  459. package/registry/reorderable-list.json +1 -1
  460. package/registry/screen.json +1 -1
  461. package/registry/search-list.json +7 -1
  462. package/registry/segmented-control.json +1 -1
  463. package/registry/select.json +1 -1
  464. package/registry/shiny-text.json +1 -1
  465. package/registry/skeleton.json +3 -2
  466. package/registry/slides.json +2 -2
  467. package/registry/spinner.json +1 -1
  468. package/registry/stepper.json +1 -1
  469. package/registry/steps.json +1 -1
  470. package/registry/symmetric-grid.json +1 -1
  471. package/registry/theme-toggle.json +1 -1
  472. package/registry/timeline.json +1 -1
  473. package/registry/title.json +1 -1
  474. package/registry/toast-provider.json +2 -2
  475. package/registry/toast.json +1 -1
  476. package/registry/transition.json +1 -1
  477. package/registry/wizard.json +1 -1
  478. package/src/atoms/Avatar.tsx +117 -26
  479. package/src/atoms/Badge.tsx +20 -9
  480. package/src/atoms/Button.tsx +102 -30
  481. package/src/atoms/Card.tsx +23 -3
  482. package/src/atoms/Checkbox.tsx +49 -12
  483. package/src/atoms/Divider.tsx +34 -4
  484. package/src/atoms/EmptyState.tsx +63 -16
  485. package/src/atoms/Fab.tsx +56 -9
  486. package/src/atoms/Gradient.tsx +92 -41
  487. package/src/atoms/IconButton.tsx +27 -4
  488. package/src/atoms/Image.tsx +74 -28
  489. package/src/atoms/Input.tsx +129 -19
  490. package/src/atoms/KeyValueRow.tsx +72 -28
  491. package/src/atoms/PressableScale.tsx +31 -7
  492. package/src/atoms/ShinyText.tsx +31 -31
  493. package/src/atoms/Skeleton.tsx +37 -17
  494. package/src/atoms/Spinner.tsx +87 -24
  495. package/src/atoms/Text.tsx +66 -6
  496. package/src/atoms/Transition.tsx +40 -44
  497. package/src/atoms/index.ts +3 -3
  498. package/src/atoms/inputValidation.ts +59 -0
  499. package/src/icons/Icon.tsx +4 -4
  500. package/src/icons/defaultIcons.tsx +445 -22
  501. package/src/icons/index.ts +2 -2
  502. package/src/icons/types.ts +26 -4
  503. package/src/molecules/AvatarHeader.tsx +88 -34
  504. package/src/molecules/FormActions.tsx +36 -6
  505. package/src/molecules/InfoRow.tsx +39 -12
  506. package/src/molecules/OptionCard.tsx +55 -20
  507. package/src/molecules/SegmentedControl.tsx +135 -15
  508. package/src/molecules/Stepper.tsx +73 -19
  509. package/src/molecules/Steps.tsx +121 -39
  510. package/src/molecules/SymmetricGrid.tsx +28 -12
  511. package/src/organisms/Alert.tsx +97 -26
  512. package/src/organisms/AlertProvider.tsx +13 -13
  513. package/src/organisms/BottomSheet.tsx +115 -43
  514. package/src/organisms/Chart.tsx +193 -164
  515. package/src/organisms/DateField.tsx +40 -15
  516. package/src/organisms/DatePicker.tsx +53 -32
  517. package/src/organisms/List.tsx +64 -15
  518. package/src/organisms/Modal.tsx +122 -63
  519. package/src/organisms/NavigationBar.tsx +73 -23
  520. package/src/organisms/OptionWheel.tsx +70 -66
  521. package/src/organisms/ReorderableList.tsx +49 -27
  522. package/src/organisms/Screen.tsx +79 -42
  523. package/src/organisms/SearchList.tsx +84 -20
  524. package/src/organisms/Select.tsx +63 -29
  525. package/src/organisms/Slides.tsx +63 -44
  526. package/src/organisms/ThemeToggle.tsx +15 -6
  527. package/src/organisms/Timeline.tsx +79 -62
  528. package/src/organisms/Toast.tsx +50 -15
  529. package/src/organisms/ToastProvider.tsx +17 -13
  530. package/src/organisms/Wizard.tsx +58 -21
  531. package/src/organisms/chart/frame.tsx +35 -35
  532. package/src/organisms/chart/marks.tsx +53 -53
  533. package/src/organisms/chart/math.ts +93 -94
  534. package/src/organisms/chart/palette.ts +28 -28
  535. package/src/organisms/imperativeBridge.ts +5 -5
  536. package/src/organisms/useSlides.ts +66 -31
  537. package/src/safe-area/SafeAreaUIProvider.tsx +9 -70
  538. package/src/safe-area/index.ts +1 -0
  539. package/src/theme/KeyboardAvoidance.tsx +216 -0
  540. package/src/theme/NativeOverlay.tsx +269 -0
  541. package/src/theme/UIProvider.tsx +109 -46
  542. package/src/theme/colors.ts +21 -21
  543. package/src/theme/createStyles.ts +23 -19
  544. package/src/theme/createTheme.ts +6 -6
  545. package/src/theme/index.ts +1 -1
  546. package/src/theme/insets.ts +1 -1
  547. package/src/theme/labels.ts +85 -2
  548. package/src/theme/palettes.ts +33 -25
  549. package/src/theme/tokens.ts +27 -13
  550. package/src/theme/types.ts +7 -7
  551. package/src/theme/useKeyboardField.ts +33 -0
  552. package/src/theme/useReduceMotion.ts +27 -0
@@ -4,6 +4,8 @@ import {
4
4
  Animated,
5
5
  Pressable,
6
6
  Text,
7
+ View,
8
+ type Insets,
7
9
  type GestureResponderEvent,
8
10
  type StyleProp,
9
11
  type TextStyle,
@@ -12,6 +14,7 @@ import {
12
14
  import { createStyles } from '../theme/createStyles';
13
15
  import { useAllowFontScaling, useColors, useTheme } from '../theme/UIProvider';
14
16
  import { Icon } from '../icons/Icon';
17
+ import { useReduceMotion } from './Transition';
15
18
  import type { IconName } from '../icons/types';
16
19
 
17
20
  const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
@@ -20,20 +23,36 @@ export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'lin
20
23
  export type ButtonSize = 'sm' | 'md' | 'lg';
21
24
 
22
25
  export interface ButtonProps {
26
+ /** Visible label. Also the accessible name unless `accessibilityLabel` is set. */
23
27
  title: string;
28
+ /** Called on press. Not called while `disabled` or `loading`. */
24
29
  onPress: (e: GestureResponderEvent) => void;
30
+ /**
31
+ * Semantic style: `primary` is the filled focal action; the others step the visual weight down.
32
+ * @default 'primary'
33
+ */
25
34
  variant?: ButtonVariant;
35
+ /** Density: padding and font size. `sm` gets extra touch area through `hitSlop`. @default 'md' */
26
36
  size?: ButtonSize;
37
+ /** Shows a spinner over the hidden label (the width doesn't change) and blocks presses. @default false */
27
38
  loading?: boolean;
39
+ /** Paints the disabled colors and ignores presses. @default false */
28
40
  disabled?: boolean;
29
41
  style?: StyleProp<ViewStyle>;
42
+ /** Extra style for the label text. */
30
43
  textStyle?: StyleProp<TextStyle>;
44
+ /** Custom node to the left of the label. Takes precedence over `leftIconName`. */
31
45
  leftIcon?: React.ReactNode;
46
+ /** Custom node to the right of the label. Takes precedence over `rightIconName`. */
32
47
  rightIcon?: React.ReactNode;
48
+ /** Icon from the library's set to the left of the label, sized to match `size`. */
33
49
  leftIconName?: IconName;
50
+ /** Icon from the library's set to the right of the label, sized to match `size`. */
34
51
  rightIconName?: IconName;
52
+ /** Color of `leftIconName`/`rightIconName`. Defaults to the label color of the variant. */
35
53
  iconColor?: string;
36
54
  testID?: string;
55
+ /** What screen readers announce. @default title */
37
56
  accessibilityLabel?: string;
38
57
  }
39
58
 
@@ -46,11 +65,11 @@ const useStyles = createStyles((theme) => ({
46
65
  borderWidth: 0,
47
66
  },
48
67
  sm: { paddingVertical: theme.tokens.spacing.sm, paddingHorizontal: theme.tokens.spacing.md },
49
- md: { paddingVertical: theme.tokens.spacing.lg - 1, paddingHorizontal: theme.tokens.spacing.xl },
50
- lg: { paddingVertical: theme.tokens.spacing.lg + 2, paddingHorizontal: theme.tokens.spacing.xxl },
68
+ md: { paddingVertical: theme.tokens.spacing.lg, paddingHorizontal: theme.tokens.spacing.xl },
69
+ lg: { paddingVertical: theme.tokens.spacing.xl, paddingHorizontal: theme.tokens.spacing.xxl },
51
70
  link: { paddingVertical: theme.tokens.spacing.xs, paddingHorizontal: 0, justifyContent: 'flex-start' },
52
71
  outline: { borderWidth: 1 },
53
- filledShadow: { ...theme.tokens.shadow.md, shadowColor: '#000' },
72
+ filledShadow: theme.tokens.shadow.md,
54
73
  text: { fontWeight: theme.tokens.fontWeight.semibold, textAlign: 'center' },
55
74
  textSm: { fontSize: theme.tokens.fontSize.sm },
56
75
  textMd: { fontSize: theme.tokens.fontSize.lg },
@@ -58,15 +77,37 @@ const useStyles = createStyles((theme) => ({
58
77
  underline: { textDecorationLine: 'underline' },
59
78
  iconLeft: { marginRight: theme.tokens.spacing.sm },
60
79
  iconRight: { marginLeft: theme.tokens.spacing.sm },
80
+ // The label keeps taking its space (invisible) while loading: the button
81
+ // doesn't change width and the spinner is centered on top.
82
+ hidden: { opacity: 0 },
83
+ spinner: { position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, alignItems: 'center', justifyContent: 'center' },
61
84
  }));
62
85
 
86
+ /**
87
+ * Extra touch area for the sizes that fall below 44pt in height
88
+ * (Fitts): `sm` measures ~30pt and `link` ~27pt. hitSlop enlarges the area
89
+ * that receives the touch without changing how it looks.
90
+ */
91
+ function useHitSlop(size: ButtonSize, variant: ButtonVariant): Insets | undefined {
92
+ const theme = useTheme();
93
+ if (variant === 'link') {
94
+ const v = theme.tokens.spacing.md;
95
+ return { top: v, bottom: v, left: theme.tokens.spacing.sm, right: theme.tokens.spacing.sm };
96
+ }
97
+ if (size === 'sm') {
98
+ const v = theme.tokens.spacing.sm;
99
+ return { top: v, bottom: v };
100
+ }
101
+ return undefined;
102
+ }
103
+
63
104
  function resolveColors(variant: ButtonVariant, disabled: boolean, colors: ReturnType<typeof useColors>) {
64
105
  if (disabled) {
65
106
  return { background: colors.inputBackground, text: colors.textLight, border: 'transparent' };
66
107
  }
67
108
  switch (variant) {
68
- // Las variantes sin relleno pintan texto sobre el fondo de la pantalla:
69
- // van con el rol `*Text`. Las rellenas van con `on*` sobre el acento.
109
+ // The unfilled variants paint text over the screen background: they
110
+ // use the `*Text` role. The filled ones use `on*` over the accent.
70
111
  case 'outline':
71
112
  return { background: 'transparent', text: colors.primaryText, border: colors.primary };
72
113
  case 'ghost':
@@ -85,9 +126,24 @@ function resolveColors(variant: ButtonVariant, disabled: boolean, colors: Return
85
126
 
86
127
  /**
87
128
  * Button
88
- * Único componente de botón de la librería. `variant` decide el estilo
89
- * semántico, `size` la densidad. El feedback de "presionado" anima solo
90
- * `transform` (Animated.spring, useNativeDriver) — nunca opacity ni layout.
129
+ * The library's only button component. `variant` sets the semantic style,
130
+ * `size` the density. The "pressed" feedback animates only `transform`
131
+ * (Animated.spring, useNativeDriver) — never opacity or layout — and is
132
+ * skipped when Reduce Motion is on.
133
+ *
134
+ * Gestalt:
135
+ * - Focal point (Von Restorff): `primary` is the only one filled with the
136
+ * accent and a shadow; there should be one per screen or group. The other
137
+ * variants step the visual weight down (secondary → outline → ghost → link).
138
+ * - Similarity: all variants share shape, radius and typography, so a row of
139
+ * buttons reads as a single group of actions; only what conveys the
140
+ * hierarchy changes (fill, border, color).
141
+ * - Proximity: icon and label sit `spacing.sm` apart, much less than the
142
+ * padding, so they read as a single label.
143
+ *
144
+ * Fitts: `sm` and `link` are less than 44pt tall and make up for it with `hitSlop`.
145
+ * While `loading`, the label is invisible but keeps its space: the button
146
+ * doesn't change width (no layout jumps).
91
147
  */
92
148
  export const Button = memo(
93
149
  ({
@@ -112,6 +168,8 @@ export const Button = memo(
112
168
  const theme = useTheme();
113
169
  const allowFontScaling = useAllowFontScaling();
114
170
  const scale = useRef(new Animated.Value(1)).current;
171
+ const reduceMotion = useReduceMotion();
172
+ const hitSlop = useHitSlop(size, variant);
115
173
  const isDisabled = disabled || loading;
116
174
  const isFilled = variant === 'primary' || variant === 'secondary' || variant === 'destructive';
117
175
 
@@ -119,6 +177,7 @@ export const Button = memo(
119
177
  const effectiveIconColor = iconColor ?? resolved.text;
120
178
 
121
179
  const animateTo = (value: number) => {
180
+ if (reduceMotion) return;
122
181
  Animated.spring(scale, { toValue: value, useNativeDriver: true, speed: 50, bounciness: 6 }).start();
123
182
  };
124
183
 
@@ -129,7 +188,10 @@ export const Button = memo(
129
188
  variant === 'outline' && [styles.outline, { borderColor: resolved.border }],
130
189
  { backgroundColor: resolved.background },
131
190
  isFilled && !disabled && styles.filledShadow,
132
- { opacity: isDisabled ? 0.7 : 1 },
191
+ // Disabled is already marked by its colors (resolveColors); lowering the
192
+ // opacity on top of that left it almost invisible (figure and ground).
193
+ // Only `loading` dims it, to signal that the button is busy.
194
+ { opacity: loading && !disabled ? 0.7 : 1 },
133
195
  style,
134
196
  ];
135
197
 
@@ -144,11 +206,11 @@ export const Button = memo(
144
206
  const iconSize = size === 'sm' ? 16 : size === 'lg' ? 22 : 20;
145
207
 
146
208
  return (
147
- // El Pressable ES el contenedor animado, no un wrapper alrededor de uno.
148
- // Con un Animated.View interno, un `style` de layout (flex, width,
149
- // margin) caía en el hijo mientras el Pressable — que es quien ocupa
150
- // lugar en el layout del padre — quedaba sin él: el ancho colapsaba y
151
- // el label desaparecía (visible en los botones en fila del Alert).
209
+ // The Pressable IS the animated container, not a wrapper around one.
210
+ // With an inner Animated.View, a layout `style` (flex, width, margin)
211
+ // landed on the child while the Pressable — which is what takes up
212
+ // space in the parent's layout — was left without it: the width
213
+ // collapsed and the label disappeared (visible in the Alert's row of buttons).
152
214
  <AnimatedPressable
153
215
  onPress={onPress}
154
216
  onPressIn={() => {
@@ -158,28 +220,38 @@ export const Button = memo(
158
220
  if (!isDisabled) animateTo(1);
159
221
  }}
160
222
  disabled={isDisabled}
223
+ hitSlop={hitSlop}
161
224
  testID={testID}
162
225
  accessibilityRole="button"
163
226
  accessibilityLabel={accessibilityLabel ?? title}
164
227
  accessibilityState={{ disabled: isDisabled, busy: loading }}
165
228
  style={[containerStyle, { transform: [{ scale }] }]}
166
229
  >
167
- {loading ? (
168
- <ActivityIndicator size="small" color={resolved.text} />
169
- ) : (
170
- <>
171
- {leftIcon}
172
- {!leftIcon && leftIconName && (
173
- <Icon name={leftIconName} size={iconSize} color={effectiveIconColor} style={styles.iconLeft} />
174
- )}
175
- <Text allowFontScaling={allowFontScaling} style={labelStyle}>
176
- {title}
177
- </Text>
178
- {rightIcon}
179
- {!rightIcon && rightIconName && (
180
- <Icon name={rightIconName} size={iconSize} color={effectiveIconColor} style={styles.iconRight} />
181
- )}
182
- </>
230
+ {leftIcon ? <View style={[styles.iconLeft, loading && styles.hidden]}>{leftIcon}</View> : null}
231
+ {!leftIcon && leftIconName && (
232
+ <Icon
233
+ name={leftIconName}
234
+ size={iconSize}
235
+ color={effectiveIconColor}
236
+ style={[styles.iconLeft, loading && styles.hidden]}
237
+ />
238
+ )}
239
+ <Text allowFontScaling={allowFontScaling} style={[labelStyle, loading && styles.hidden]}>
240
+ {title}
241
+ </Text>
242
+ {rightIcon ? <View style={[styles.iconRight, loading && styles.hidden]}>{rightIcon}</View> : null}
243
+ {!rightIcon && rightIconName && (
244
+ <Icon
245
+ name={rightIconName}
246
+ size={iconSize}
247
+ color={effectiveIconColor}
248
+ style={[styles.iconRight, loading && styles.hidden]}
249
+ />
250
+ )}
251
+ {loading && (
252
+ <View style={styles.spinner} pointerEvents="none">
253
+ <ActivityIndicator size="small" color={resolved.text} />
254
+ </View>
183
255
  )}
184
256
  </AnimatedPressable>
185
257
  );
@@ -1,21 +1,41 @@
1
1
  import React, { memo } from 'react';
2
- import { View, type ViewProps, type ViewStyle } from 'react-native';
2
+ import { View, type StyleProp, type ViewProps, type ViewStyle } from 'react-native';
3
3
  import { createStyles } from '../theme/createStyles';
4
4
 
5
5
  export interface CardProps extends ViewProps {
6
+ /** Content of the card, inside its padding, background and border. */
6
7
  children: React.ReactNode;
7
- style?: ViewStyle;
8
+ style?: StyleProp<ViewStyle>;
8
9
  }
9
10
 
11
+ const CARD_BORDER_DARK = 1;
12
+
10
13
  const useStyles = createStyles((theme) => ({
11
14
  card: {
12
- backgroundColor: theme.colors.surface,
15
+ // surfaceRaised: lighter than surface in dark, so a card on a sheet or
16
+ // on another card still reads as a separate tile (figure and ground).
17
+ backgroundColor: theme.colors.surfaceRaised,
13
18
  borderRadius: theme.tokens.radius.xl,
14
19
  padding: theme.tokens.spacing.lg,
15
20
  ...theme.tokens.shadow.sm,
21
+ // In dark the shadow isn't visible and surface barely stands out from the
22
+ // background (or not at all, on another surface): a 1pt border restores
23
+ // the outline (figure and ground). A hairline was invisible.
24
+ ...(theme.scheme === 'dark' && { borderWidth: CARD_BORDER_DARK, borderColor: theme.colors.border }),
16
25
  },
17
26
  }));
18
27
 
28
+ /**
29
+ * Card
30
+ * Surface container: groups related content.
31
+ *
32
+ * Gestalt, common region: everything inside the same background and border
33
+ * reads as a group, even when other elements are nearby. Figure and ground:
34
+ * in light the shadow sets it apart; in dark (where the shadow isn't visible)
35
+ * a thin border does. The inner padding (`spacing.lg`) must be larger than the
36
+ * spacing between the elements inside, so the content reads as one block.
37
+ */
38
+
19
39
  export const Card = memo(({ children, style, ...props }: CardProps) => {
20
40
  const styles = useStyles();
21
41
  return (
@@ -1,20 +1,34 @@
1
1
  import React, { memo, useEffect, useRef } from 'react';
2
2
  import { Animated, Text, TouchableOpacity } from 'react-native';
3
3
  import { createStyles } from '../theme/createStyles';
4
- import { useAllowFontScaling, useColors } from '../theme/UIProvider';
4
+ import { useAllowFontScaling, useColors, useTheme } from '../theme/UIProvider';
5
5
  import { Icon } from '../icons/Icon';
6
+ import { onColor } from '../icons/defaultIcons';
7
+ import { useReduceMotion } from './Transition';
6
8
 
7
9
  export interface CheckboxProps {
10
+ /** Whether the box is checked (controlled). */
8
11
  value: boolean;
12
+ /** Called with the new value when the row is pressed. */
9
13
  onValueChange: (value: boolean) => void;
14
+ /** Text next to the box; the whole row is touchable. Also the accessible name. */
10
15
  label?: string;
16
+ /**
17
+ * Fill and border color when checked. The check turns black or white for contrast. @default
18
+ * colors.primary
19
+ */
11
20
  color?: string;
21
+ /** Dims the box and the label and ignores presses. */
12
22
  disabled?: boolean;
23
+ /** Effectively required without `label`: it is all a screen reader announces. */
24
+ accessibilityLabel?: string;
13
25
  testID?: string;
14
26
  }
15
27
 
16
28
  const useStyles = createStyles((theme) => ({
17
- container: { flexDirection: 'row', alignItems: 'center', marginBottom: theme.tokens.spacing.sm },
29
+ // 44pt tall: the whole row is the touch area (Fitts). Replaces the
30
+ // marginBottom that separated stacked checkboxes; now the row provides the room.
31
+ container: { flexDirection: 'row', alignItems: 'center', minHeight: 44 },
18
32
  box: {
19
33
  width: 24,
20
34
  height: 24,
@@ -22,31 +36,54 @@ const useStyles = createStyles((theme) => ({
22
36
  borderWidth: 2,
23
37
  justifyContent: 'center',
24
38
  alignItems: 'center',
25
- marginRight: theme.tokens.spacing.sm + 2,
39
+ marginRight: theme.tokens.spacing.md,
26
40
  },
27
41
  label: { fontSize: theme.tokens.fontSize.md, color: theme.colors.text },
42
+ labelDisabled: { color: theme.colors.textLight },
28
43
  }));
29
44
 
30
- export const Checkbox = memo(({ value, onValueChange, label, color, disabled, testID }: CheckboxProps) => {
45
+ /**
46
+ * Checkbox
47
+ * Box + optional label; the whole row is touchable.
48
+ *
49
+ * Gestalt:
50
+ * - Proximity: the box and its label sit `spacing.md` apart, less than the
51
+ * spacing between rows, so each label reads with its box.
52
+ * - Common region: the whole row is the touch area, not just the box, and it
53
+ * is at least 44pt tall (Fitts).
54
+ * - Figure and ground: when checked, the box fills with the accent and the
55
+ * check turns black or white depending on that fill (also with a custom `color`).
56
+ *
57
+ * `disabled` dims the box and the label (not just the box). The check
58
+ * animation is skipped with Reduce Motion.
59
+ */
60
+ export const Checkbox = memo(({ value, onValueChange, label, color, disabled, accessibilityLabel, testID }: CheckboxProps) => {
31
61
  const colors = useColors();
32
62
  const styles = useStyles();
33
63
  const allowFontScaling = useAllowFontScaling();
34
64
  const activeColor = color || colors.primary;
35
- // El check va encima del relleno: con `color` propio no sabemos qué tono
36
- // contrasta, así que ahí seguimos con blanco (decisión del consumidor).
37
- const checkColor = color ? colors.white : colors.onPrimary;
65
+ // The check sits on top of the fill: with a custom `color`, black or white is
66
+ // picked by luminance (a fixed white disappeared over light colors).
67
+ const checkColor = color ? onColor(color) : colors.onPrimary;
68
+ const theme = useTheme();
69
+ const reduceMotion = useReduceMotion();
38
70
  const progress = useRef(new Animated.Value(value ? 1 : 0)).current;
39
71
  const checkScale = useRef(new Animated.Value(value ? 1 : 0)).current;
40
72
 
41
73
  useEffect(() => {
42
- Animated.timing(progress, { toValue: value ? 1 : 0, duration: 150, useNativeDriver: false }).start();
74
+ if (reduceMotion) {
75
+ progress.setValue(value ? 1 : 0);
76
+ checkScale.setValue(value ? 1 : 0);
77
+ return;
78
+ }
79
+ Animated.timing(progress, { toValue: value ? 1 : 0, duration: theme.tokens.duration.fast, useNativeDriver: false }).start();
43
80
  Animated.spring(checkScale, {
44
81
  toValue: value ? 1 : 0,
45
82
  useNativeDriver: true,
46
83
  speed: 40,
47
84
  bounciness: 10,
48
85
  }).start();
49
- }, [value]);
86
+ }, [value, reduceMotion]);
50
87
 
51
88
  const backgroundColor = progress.interpolate({ inputRange: [0, 1], outputRange: [colors.surface, activeColor] });
52
89
  const borderColor = progress.interpolate({ inputRange: [0, 1], outputRange: [colors.border, activeColor] });
@@ -59,7 +96,7 @@ export const Checkbox = memo(({ value, onValueChange, label, color, disabled, te
59
96
  onPress={() => onValueChange(!value)}
60
97
  accessibilityRole="checkbox"
61
98
  accessibilityState={{ checked: value, disabled: !!disabled }}
62
- accessibilityLabel={label}
99
+ accessibilityLabel={accessibilityLabel ?? label}
63
100
  testID={testID}
64
101
  >
65
102
  <Animated.View style={[styles.box, { backgroundColor, borderColor, opacity: disabled ? 0.5 : 1 }]}>
@@ -67,8 +104,8 @@ export const Checkbox = memo(({ value, onValueChange, label, color, disabled, te
67
104
  <Icon name="check" size={16} color={checkColor} />
68
105
  </Animated.View>
69
106
  </Animated.View>
70
- {label && (
71
- <Text allowFontScaling={allowFontScaling} style={styles.label}>
107
+ {!!label && (
108
+ <Text allowFontScaling={allowFontScaling} style={[styles.label, disabled && styles.labelDisabled]}>
72
109
  {label}
73
110
  </Text>
74
111
  )}
@@ -1,14 +1,44 @@
1
1
  import React, { memo } from 'react';
2
2
  import { View, type StyleProp, type ViewStyle } from 'react-native';
3
- import { useColors } from '../theme/UIProvider';
3
+ import { useTheme } from '../theme/UIProvider';
4
+ import type { Tokens } from '../theme/tokens';
4
5
 
5
6
  export interface DividerProps {
7
+ /** `vertical` separates items in a row and stretches to the row's height. @default 'horizontal' */
8
+ orientation?: 'horizontal' | 'vertical';
9
+ /** Space on each side of the line, from the spacing scale. Unset, the line adds no margin. */
10
+ spacing?: keyof Tokens['spacing'];
6
11
  style?: StyleProp<ViewStyle>;
7
12
  testID?: string;
8
13
  }
9
14
 
10
- export const Divider = memo(({ style, testID }: DividerProps) => {
11
- const colors = useColors();
12
- return <View testID={testID} style={[{ height: 1, backgroundColor: colors.border, width: '100%' }, style]} />;
15
+ /**
16
+ * Divider
17
+ * 1pt line in `colors.border`.
18
+ *
19
+ * Gestalt: separates groups when proximity alone isn't enough (dense lists,
20
+ * rows spanning the whole screen). If spacing already separates the groups,
21
+ * prefer spacing: one line too many fragments what should read together.
22
+ * `spacing` takes its room from the token scale so the separation is the
23
+ * same across the whole app, instead of a different margin on each screen.
24
+ *
25
+ * It is decorative: it doesn't enter the accessibility tree.
26
+ */
27
+ export const Divider = memo(({ orientation = 'horizontal', spacing, style, testID }: DividerProps) => {
28
+ const theme = useTheme();
29
+ const gap = spacing ? theme.tokens.spacing[spacing] : 0;
30
+ const line: ViewStyle =
31
+ orientation === 'vertical'
32
+ ? { width: 1, alignSelf: 'stretch', marginHorizontal: gap }
33
+ : { height: 1, width: '100%', marginVertical: gap };
34
+ return (
35
+ <View
36
+ testID={testID}
37
+ accessible={false}
38
+ importantForAccessibility="no-hide-descendants"
39
+ accessibilityElementsHidden
40
+ style={[line, { backgroundColor: theme.colors.border }, style]}
41
+ />
42
+ );
13
43
  });
14
44
  Divider.displayName = 'Divider';
@@ -1,43 +1,80 @@
1
1
  import React, { memo } from 'react';
2
- import { Text, View, type ViewStyle } from 'react-native';
2
+ import { Text, View, type StyleProp, type ViewStyle } from 'react-native';
3
3
  import { createStyles } from '../theme/createStyles';
4
4
  import { useAllowFontScaling, useColors, useLabels } from '../theme/UIProvider';
5
5
  import { Icon } from '../icons/Icon';
6
6
  import type { IconName } from '../icons/types';
7
+ import { Button, type ButtonVariant } from './Button';
8
+
9
+ export interface EmptyStateAction {
10
+ label: string;
11
+ onPress: () => void;
12
+ /** @default 'primary' */
13
+ variant?: ButtonVariant;
14
+ }
7
15
 
8
16
  export interface EmptyStateProps {
17
+ /** Main line. @default labels.noResultsTitle */
9
18
  title?: string;
19
+ /** Supporting line under the title. @default labels.noResultsDescription */
10
20
  description?: string;
21
+ /** Built-in or custom icon name. Ignored when `icon` is passed. @default 'search' */
11
22
  iconName?: IconName;
23
+ /** Any node in place of the icon (an Image, an illustration). */
12
24
  icon?: React.ReactNode;
13
- style?: ViewStyle;
25
+ /** The next step, shown as a button under the text (e.g. "Add client"). */
26
+ action?: EmptyStateAction;
27
+ style?: StyleProp<ViewStyle>;
28
+ testID?: string;
14
29
  }
15
30
 
31
+ /** Icon size: the block's focal point without competing with the title. */
32
+ const ICON_SIZE = 48;
33
+ /** Minimum height: the block doesn't get squashed inside a short empty list. */
34
+ const MIN_HEIGHT = 200;
35
+
16
36
  const useStyles = createStyles((theme) => ({
17
37
  container: {
18
38
  flex: 1,
19
39
  justifyContent: 'center',
20
40
  alignItems: 'center',
21
- padding: theme.tokens.spacing.xxl - 4,
22
- minHeight: 200,
41
+ padding: theme.tokens.spacing.xl,
42
+ minHeight: MIN_HEIGHT,
23
43
  },
24
44
  title: {
25
45
  fontSize: theme.tokens.fontSize.lg,
26
46
  fontWeight: theme.tokens.fontWeight.semibold,
27
- color: theme.colors.textLight,
28
- marginTop: theme.tokens.spacing.md - 2,
47
+ lineHeight: theme.tokens.lineHeight.lg,
48
+ color: theme.colors.text,
49
+ marginTop: theme.tokens.spacing.md,
29
50
  textAlign: 'center',
30
51
  },
31
52
  description: {
32
53
  fontSize: theme.tokens.fontSize.md,
54
+ lineHeight: theme.tokens.lineHeight.md,
33
55
  color: theme.colors.textLight,
34
- marginTop: theme.tokens.spacing.xs + 1,
56
+ marginTop: theme.tokens.spacing.xs,
35
57
  textAlign: 'center',
36
58
  },
59
+ message: { alignItems: 'center' },
60
+ action: { marginTop: theme.tokens.spacing.lg },
37
61
  }));
38
62
 
63
+ /**
64
+ * EmptyState
65
+ * Centered icon + title + description for a list or screen with no data.
66
+ *
67
+ * Gestalt, proximity: title and description sit close together (`spacing.xs`)
68
+ * and the icon one step further (`spacing.md`), so they read as a message
69
+ * with its image and not as three loose pieces. Similarity: the title in
70
+ * `text` and the description in `textLight` mark the hierarchy. The action,
71
+ * if any, is set further apart (`spacing.lg`): it is the next step, not part
72
+ * of the message.
73
+ * The message is a single accessibility node (title and description together;
74
+ * the icon is decorative) and the button a separate, focusable one.
75
+ */
39
76
  export const EmptyState = memo(
40
- ({ title, description, iconName = 'search', icon, style }: EmptyStateProps) => {
77
+ ({ title, description, iconName = 'search', icon, action, style, testID }: EmptyStateProps) => {
41
78
  const colors = useColors();
42
79
  const styles = useStyles();
43
80
  const labels = useLabels();
@@ -45,14 +82,24 @@ export const EmptyState = memo(
45
82
  const resolvedTitle = title ?? labels.noResultsTitle;
46
83
  const resolvedDescription = description ?? labels.noResultsDescription;
47
84
  return (
48
- <View style={[styles.container, style]} accessible accessibilityRole="text">
49
- {icon ?? <Icon name={iconName} size={48} color={colors.textLight} />}
50
- <Text allowFontScaling={allowFontScaling} style={styles.title}>
51
- {resolvedTitle}
52
- </Text>
53
- <Text allowFontScaling={allowFontScaling} style={styles.description}>
54
- {resolvedDescription}
55
- </Text>
85
+ <View style={[styles.container, style]} testID={testID}>
86
+ <View style={styles.message} accessible accessibilityRole="text">
87
+ {icon ?? <Icon name={iconName} size={ICON_SIZE} color={colors.textLight} />}
88
+ <Text allowFontScaling={allowFontScaling} style={styles.title}>
89
+ {resolvedTitle}
90
+ </Text>
91
+ <Text allowFontScaling={allowFontScaling} style={styles.description}>
92
+ {resolvedDescription}
93
+ </Text>
94
+ </View>
95
+ {action && (
96
+ <Button
97
+ title={action.label}
98
+ onPress={action.onPress}
99
+ variant={action.variant ?? 'primary'}
100
+ style={styles.action}
101
+ />
102
+ )}
56
103
  </View>
57
104
  );
58
105
  }