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
@@ -5,10 +5,13 @@ import { useAllowFontScaling, useColors, useLabels } from '../theme/UIProvider';
5
5
  import { Modal } from './Modal';
6
6
  import { DatePicker, type DatePickerProps, type DateRange } from './DatePicker';
7
7
  import { Button } from '../atoms/Button';
8
+ import { Icon } from '../icons/Icon';
8
9
 
9
10
  export interface DateFieldProps
10
11
  extends Pick<DatePickerProps, 'minDate' | 'maxDate' | 'monthNames' | 'weekdayNames' | 'firstDayOfWeek'> {
12
+ /** Text above the field; also its accessible name. */
11
13
  label?: string;
14
+ /** Shows an asterisk and says "required" to screen readers. @default false */
12
15
  required?: boolean;
13
16
  /**
14
17
  * 'single' picks one date; 'range' picks an interval with two taps.
@@ -23,8 +26,11 @@ export interface DateFieldProps
23
26
  range?: DateRange;
24
27
  /** Called in mode="range", both when setting the start and when closing the range. */
25
28
  onRangeChange?: (range: DateRange) => void;
29
+ /** Text while empty. @default labels.selectDate */
26
30
  placeholder?: string;
31
+ /** Error under the field (red border); announced to screen readers. */
27
32
  error?: string;
33
+ /** Dims the field and ignores taps. @default false */
28
34
  disabled?: boolean;
29
35
  /** Formats the date in the field. @default "Month D, YYYY" */
30
36
  format?: (date: Date) => string;
@@ -37,6 +43,7 @@ export interface DateFieldProps
37
43
  onClear?: () => void;
38
44
  /** Text for that button. @default the `clear` from `useLabels()` */
39
45
  clearLabel?: string;
46
+ /** Style of the outer wrapper (label, field and error). */
40
47
  containerStyle?: StyleProp<ViewStyle>;
41
48
  testID?: string;
42
49
  }
@@ -45,6 +52,13 @@ function defaultFormat(date: Date, monthNames: string[]): string {
45
52
  return `${monthNames[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`;
46
53
  }
47
54
 
55
+ const DISABLED_OPACITY = 0.5;
56
+ const PRESSED_OPACITY = 0.7;
57
+ /** Same box as Input, so a form reads as one column of identical fields. */
58
+ const FIELD_MIN_HEIGHT = 50;
59
+ const FIELD_BORDER = 2;
60
+ const CHEVRON_SIZE = 20;
61
+
48
62
  const useStyles = createStyles((theme) => ({
49
63
  container: { marginBottom: theme.tokens.spacing.lg, width: '100%', gap: theme.tokens.spacing.sm },
50
64
  label: { fontSize: theme.tokens.fontSize.md, fontWeight: theme.tokens.fontWeight.medium, color: theme.colors.text },
@@ -55,12 +69,13 @@ const useStyles = createStyles((theme) => ({
55
69
  justifyContent: 'space-between',
56
70
  backgroundColor: theme.colors.inputBackground,
57
71
  borderRadius: theme.tokens.radius.lg,
58
- borderWidth: 2,
72
+ borderWidth: FIELD_BORDER,
59
73
  borderColor: theme.colors.border,
60
- minHeight: 50,
74
+ minHeight: FIELD_MIN_HEIGHT,
61
75
  paddingHorizontal: theme.tokens.spacing.lg,
62
76
  },
63
77
  fieldError: { borderColor: theme.colors.error },
78
+ fieldDisabled: { opacity: DISABLED_OPACITY },
64
79
  fieldText: { fontSize: theme.tokens.fontSize.lg, color: theme.colors.text },
65
80
  placeholder: { color: theme.colors.textLight },
66
81
  errorText: { fontSize: theme.tokens.fontSize.sm, color: theme.colors.errorText },
@@ -68,9 +83,17 @@ const useStyles = createStyles((theme) => ({
68
83
 
69
84
  /**
70
85
  * DateField
71
- * Campo de fecha: se ve como un Input, abre un `DatePicker` en un Modal al
72
- * tocarlo. Sin picker nativo del sistema, así que se ve y se comporta igual
73
- * en iOS y Android.
86
+ * Date field: looks like an Input, opens a `DatePicker` in a Modal when
87
+ * tapped. No native system picker, so it looks and behaves the same on iOS
88
+ * and Android.
89
+ *
90
+ * Gestalt, similarity (and Jakob's law): same box, border, height and label
91
+ * as Input, and the same chevron as Select, so in a form it reads as one more
92
+ * field; only the chevron says it opens something. Proximity: label, field
93
+ * and error stack tight, as one unit.
94
+ *
95
+ * Accessibility: the name includes the label, "required" and the chosen date;
96
+ * the error is a hint; `expanded` tells whether the calendar is open.
74
97
  */
75
98
  export const DateField = memo(
76
99
  ({
@@ -81,7 +104,7 @@ export const DateField = memo(
81
104
  onChange,
82
105
  range,
83
106
  onRangeChange,
84
- placeholder = 'Select a date',
107
+ placeholder,
85
108
  error,
86
109
  disabled = false,
87
110
  format,
@@ -100,12 +123,13 @@ export const DateField = memo(
100
123
  const [open, setOpen] = useState(false);
101
124
 
102
125
  const months = monthNames ?? labels.months;
126
+ const emptyText = placeholder ?? labels.selectDate;
103
127
  const isRange = mode === 'range';
104
128
 
105
129
  const formatDate = (date: Date) => (format ? format(date) : defaultFormat(date, months));
106
130
 
107
- // El calendario se cierra solo cuando ya no falta nada por elegir: en
108
- // rango, recién cuando el segundo toque cierra el intervalo.
131
+ // The calendar closes on its own only once there is nothing left to pick:
132
+ // in range mode, only when the second tap closes the interval.
109
133
  const handleChange = useCallback(
110
134
  (date: Date) => {
111
135
  onChange?.(date);
@@ -128,7 +152,7 @@ export const DateField = memo(
128
152
  }, [onClear]);
129
153
 
130
154
  const hasValue = isRange ? !!range?.start : !!value;
131
- let display = placeholder;
155
+ let display = emptyText;
132
156
  if (isRange && range?.start) {
133
157
  display = range.end ? `${formatDate(range.start)} — ${formatDate(range.end)}` : formatDate(range.start);
134
158
  } else if (!isRange && value) {
@@ -145,20 +169,21 @@ export const DateField = memo(
145
169
  )}
146
170
 
147
171
  <TouchableOpacity
148
- style={[styles.field, !!error && styles.fieldError, disabled && { opacity: 0.5 }]}
172
+ style={[styles.field, !!error && styles.fieldError, disabled && styles.fieldDisabled]}
149
173
  onPress={() => setOpen(true)}
150
174
  disabled={disabled}
151
- activeOpacity={0.7}
175
+ activeOpacity={PRESSED_OPACITY}
152
176
  accessibilityRole="button"
153
- accessibilityLabel={hasValue ? `${label ?? placeholder}, ${display}` : (label ?? placeholder)}
177
+ accessibilityLabel={[label ?? emptyText, required ? labels.required : null, hasValue ? display : null]
178
+ .filter(Boolean)
179
+ .join(', ')}
180
+ accessibilityHint={error || undefined}
154
181
  accessibilityState={{ disabled, expanded: open }}
155
182
  >
156
183
  <Text allowFontScaling={allowFontScaling} style={[styles.fieldText, !hasValue && styles.placeholder]}>
157
184
  {display}
158
185
  </Text>
159
- <Text allowFontScaling={allowFontScaling} style={{ color: colors.textLight }}>
160
- {'▾'}
161
- </Text>
186
+ <Icon name="chevron-down" size={CHEVRON_SIZE} color={colors.textLight} />
162
187
  </TouchableOpacity>
163
188
 
164
189
  {!!error && (
@@ -9,12 +9,12 @@ export const DEFAULT_MONTH_NAMES = [
9
9
  'July', 'August', 'September', 'October', 'November', 'December',
10
10
  ];
11
11
 
12
- /** Índice 0 = domingo, para alinear con Date.getDay(). */
12
+ /** Index 0 = Sunday, to line up with Date.getDay(). */
13
13
  export const DEFAULT_WEEKDAY_NAMES = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
14
14
 
15
15
  export interface DateRange {
16
16
  start: Date;
17
- /** Falta mientras el rango está a medio elegir (sólo se tocó el inicio). */
17
+ /** Missing while the range is half-picked (only the start was tapped). */
18
18
  end?: Date;
19
19
  }
20
20
 
@@ -32,7 +32,9 @@ export interface DatePickerProps {
32
32
  range?: DateRange;
33
33
  /** Called in mode="range", both when setting the start and when closing the range. */
34
34
  onRangeChange?: (range: DateRange) => void;
35
+ /** Earliest selectable day; earlier days are dimmed and the back arrow stops there. */
35
36
  minDate?: Date;
37
+ /** Latest selectable day; later days are dimmed and the forward arrow stops there. */
36
38
  maxDate?: Date;
37
39
  /** Month shown on open if there's no `value`. @default today */
38
40
  defaultMonth?: Date;
@@ -52,7 +54,7 @@ function startOfDay(d: Date): Date {
52
54
  return new Date(d.getFullYear(), d.getMonth(), d.getDate());
53
55
  }
54
56
 
55
- /** Timestamp del día, para comparar sin volver a crear Date en cada celda. */
57
+ /** The day's timestamp, to compare without creating a Date again in each cell. */
56
58
  function dayTime(d: Date): number {
57
59
  return startOfDay(d).getTime();
58
60
  }
@@ -61,21 +63,21 @@ function dayTimeOf(d: Date | undefined): number | undefined {
61
63
  return d ? dayTime(d) : undefined;
62
64
  }
63
65
 
64
- /** Milisegundos que faltan para la próxima medianoche local. */
66
+ /** Milliseconds left until the next local midnight. */
65
67
  function msUntilNextMidnight(from: Date): number {
66
68
  const next = new Date(from.getFullYear(), from.getMonth(), from.getDate() + 1);
67
69
  return next.getTime() - from.getTime();
68
70
  }
69
71
 
70
- /** Número de mes absoluto (año * 12 + mes), para comparar meses con un `<`. */
72
+ /** Absolute month number (year * 12 + month), to compare months with a `<`. */
71
73
  function monthIndex(d: Date): number {
72
74
  return d.getFullYear() * 12 + d.getMonth();
73
75
  }
74
76
 
75
77
  /**
76
- * Devuelve la grilla del mes: 6 filas de 7 celdas. Las celdas fuera del mes
77
- * son null, así el layout no salta de alto entre meses (un mes puede
78
- * necesitar 4, 5 o 6 filas según en qué día caiga el 1).
78
+ * Returns the month grid: 6 rows of 7 cells. Cells outside the month are
79
+ * null, so the layout doesn't jump in height between months (a month can
80
+ * need 4, 5 or 6 rows depending on which day the 1st falls on).
79
81
  */
80
82
  export function buildMonthGrid(year: number, month: number, firstDayOfWeek: 0 | 1): (Date | null)[][] {
81
83
  const first = new Date(year, month, 1);
@@ -92,9 +94,16 @@ export function buildMonthGrid(year: number, month: number, firstDayOfWeek: 0 |
92
94
  return rows;
93
95
  }
94
96
 
97
+ /** Drawn size of a day; hitSlop takes the touch target to 44pt (Fitts). */
98
+ const DAY_SIZE = 36;
99
+ const MIN_TOUCH = 44;
100
+ const DAY_HIT_SLOP = (MIN_TOUCH - DAY_SIZE) / 2;
101
+ const DAY_HIT = { top: DAY_HIT_SLOP, bottom: DAY_HIT_SLOP, left: DAY_HIT_SLOP, right: DAY_HIT_SLOP };
102
+
95
103
  const useStyles = createStyles((theme) => ({
96
104
  container: {
97
- backgroundColor: theme.colors.surface,
105
+ // Raised, like Card: in dark the calendar reads as a panel, not only as a border.
106
+ backgroundColor: theme.colors.surfaceRaised,
98
107
  borderRadius: theme.tokens.radius.lg,
99
108
  borderWidth: 1,
100
109
  borderColor: theme.colors.border,
@@ -113,12 +122,12 @@ const useStyles = createStyles((theme) => ({
113
122
  },
114
123
  row: { flexDirection: 'row' },
115
124
  cell: { flex: 1, aspectRatio: 1, alignItems: 'center', justifyContent: 'center' },
116
- dayButton: { width: 36, height: 36, borderRadius: 18, alignItems: 'center', justifyContent: 'center' },
125
+ dayButton: { width: DAY_SIZE, height: DAY_SIZE, borderRadius: DAY_SIZE / 2, alignItems: 'center', justifyContent: 'center' },
117
126
  dayText: { fontSize: theme.tokens.fontSize.md, color: theme.colors.text },
118
127
  daySelected: { backgroundColor: theme.colors.primary },
119
128
  dayTextSelected: { color: theme.colors.onPrimary, fontWeight: theme.tokens.fontWeight.bold },
120
- // El resaltado del tramo intermedio va en la celda (cuadrada, sin gaps) y
121
- // no en el botón redondo, así la barra del rango se ve continua.
129
+ // The highlight of the in-between stretch goes on the cell (square, no gaps)
130
+ // and not on the round button, so the range bar looks continuous.
122
131
  cellInRange: { backgroundColor: theme.colors.primarySoft },
123
132
  cellRangeStart: { borderTopLeftRadius: 18, borderBottomLeftRadius: 18 },
124
133
  cellRangeEnd: { borderTopRightRadius: 18, borderBottomRightRadius: 18 },
@@ -144,8 +153,8 @@ interface DayCellProps {
144
153
  }
145
154
 
146
155
  /**
147
- * Una celda del calendario. Va memoizada aparte porque el mes entero son 42
148
- * celdas: sin esto, cualquier render del padre reconcilia las 42.
156
+ * A calendar cell. It is memoized separately because the whole month is 42
157
+ * cells: without this, any parent render reconciles all 42.
149
158
  */
150
159
  const DayCell = memo(
151
160
  ({
@@ -173,7 +182,8 @@ const DayCell = memo(
173
182
  style={[styles.dayButton, selected && styles.daySelected, !selected && isToday && styles.dayToday]}
174
183
  onPress={() => onPress(day)}
175
184
  disabled={disabled}
176
- activeOpacity={0.7}
185
+ activeOpacity={PRESSED_OPACITY}
186
+ hitSlop={DAY_HIT}
177
187
  accessibilityRole="button"
178
188
  accessibilityLabel={label}
179
189
  accessibilityState={{ selected, disabled }}
@@ -197,10 +207,21 @@ DayCell.displayName = 'DayCell';
197
207
 
198
208
  /**
199
209
  * DatePicker
200
- * Calendario mensual dibujado con View/Text puros — sin
201
- * @react-native-community/datetimepicker ni ningún picker nativo, para
202
- * mantener la librería en cero dependencias y verse igual en iOS y Android.
210
+ * Monthly calendar drawn with plain View/Text — without
211
+ * @react-native-community/datetimepicker or any native picker, to keep the
212
+ * library at zero dependencies and look the same on iOS and Android.
213
+ *
214
+ * Gestalt, common region and alignment: 6 rows of 7 cells always (the grid
215
+ * never jumps between months), weekdays aligned over their column. Similarity:
216
+ * every day is the same circle; state changes only fill and color (selected
217
+ * filled, today outlined, out of range dimmed). Continuity: a range is one
218
+ * band from start to end, not separate dots. Fitts: each day reaches a 44pt touch target (36pt circle + hitSlop).
219
+ *
220
+ * Accessibility: the month is a header, each day reads its full date, and the
221
+ * arrows' names come from `labels` (`previousMonth`, `nextMonth`).
203
222
  */
223
+ const PRESSED_OPACITY = 0.7;
224
+
204
225
  export const DatePicker = memo(
205
226
  ({
206
227
  mode = 'single',
@@ -232,8 +253,8 @@ export const DatePicker = memo(
232
253
  onChange?.(day);
233
254
  return;
234
255
  }
235
- // Primer toque (o rango ya cerrado, o toque antes del inicio): arranca
236
- // un rango nuevo. Segundo toque en adelante: lo cierra.
256
+ // First tap (or range already closed, or a tap before the start): starts
257
+ // a new range. Second tap onward: closes it.
237
258
  if (!range?.start || range.end || dayTime(day) < dayTime(range.start)) {
238
259
  onRangeChange?.({ start: day });
239
260
  } else {
@@ -248,8 +269,8 @@ export const DatePicker = memo(
248
269
  () => new Date((anchor ?? new Date()).getFullYear(), (anchor ?? new Date()).getMonth(), 1)
249
270
  );
250
271
 
251
- // La fecha elegida puede cambiar desde afuera (uso controlado): sin esto,
252
- // el calendario se quedaba clavado en el mes con el que montó.
272
+ // The selected date can change from outside (controlled use): without this,
273
+ // the calendar stayed stuck on the month it mounted with.
253
274
  const anchorMonth = anchor ? monthIndex(anchor) : undefined;
254
275
  const lastAnchorMonth = useRef(anchorMonth);
255
276
  useEffect(() => {
@@ -258,8 +279,8 @@ export const DatePicker = memo(
258
279
  setVisibleMonth(new Date(Math.floor(anchorMonth / 12), anchorMonth % 12, 1));
259
280
  }, [anchorMonth]);
260
281
 
261
- // "Hoy" se recalcula en la próxima medianoche: una app que queda abierta
262
- // toda la noche marcaba el día anterior.
282
+ // "Today" is recalculated at the next midnight: an app left open all
283
+ // night marked the previous day.
263
284
  const [todayTs, setTodayTs] = useState(() => dayTime(new Date()));
264
285
  useEffect(() => {
265
286
  const timer = setTimeout(() => setTodayTs(dayTime(new Date())), msUntilNextMidnight(new Date()));
@@ -276,8 +297,8 @@ export const DatePicker = memo(
276
297
  [weekdays, firstDayOfWeek]
277
298
  );
278
299
 
279
- // Los límites se resuelven una vez y no 42 veces por render: comparar
280
- // timestamps sale gratis, crear un Date por celda no.
300
+ // The limits are resolved once and not 42 times per render: comparing
301
+ // timestamps is free, creating a Date per cell isn't.
281
302
  const bounds = useMemo(
282
303
  () => ({
283
304
  min: dayTimeOf(minDate),
@@ -296,8 +317,8 @@ export const DatePicker = memo(
296
317
  return next;
297
318
  });
298
319
 
299
- // Un mes entero fuera de los límites no tiene nada que elegir: la flecha
300
- // que lleva ahí se apaga en vez de dejar navegar al vacío.
320
+ // A month entirely outside the limits has nothing to pick: the arrow
321
+ // leading there turns off instead of letting you navigate into the void.
301
322
  const visibleIndex = monthIndex(visibleMonth);
302
323
  const canGoBack = !minDate || visibleIndex > monthIndex(minDate);
303
324
  const canGoForward = !maxDate || visibleIndex < monthIndex(maxDate);
@@ -309,7 +330,7 @@ export const DatePicker = memo(
309
330
  <View style={styles.header}>
310
331
  <IconButton
311
332
  iconName="chevron-left"
312
- accessibilityLabel="Previous month"
333
+ accessibilityLabel={labels.previousMonth}
313
334
  disabled={!canGoBack}
314
335
  onPress={() => shiftMonth(-1)}
315
336
  />
@@ -318,7 +339,7 @@ export const DatePicker = memo(
318
339
  </Text>
319
340
  <IconButton
320
341
  iconName="chevron-right"
321
- accessibilityLabel="Next month"
342
+ accessibilityLabel={labels.nextMonth}
322
343
  disabled={!canGoForward}
323
344
  onPress={() => shiftMonth(1)}
324
345
  />
@@ -351,8 +372,8 @@ export const DatePicker = memo(
351
372
  day={day}
352
373
  label={`${months[day.getMonth()]} ${day.getDate()}, ${day.getFullYear()}`}
353
374
  selected={selected}
354
- // Un día fuera de los límites no se pinta como parte del
355
- // rango: se ve deshabilitado, y eso es lo que es.
375
+ // A day outside the limits isn't painted as part of the
376
+ // range: it looks disabled, and that is what it is.
356
377
  inRange={between && !disabled}
357
378
  isRangeStart={!!closed && isStart && !disabled}
358
379
  isRangeEnd={isEnd && !disabled}
@@ -8,18 +8,24 @@ import { Spinner } from '../atoms/Spinner';
8
8
  import type { IconName } from '../icons/types';
9
9
 
10
10
  export interface ListProps<T> {
11
+ /** Items to render. */
11
12
  data: T[];
13
+ /** Stable key per item. */
12
14
  keyExtractor: (item: T, index: number) => string;
15
+ /** Renders each row (same as FlatList's `renderItem`). */
13
16
  renderItem: FlatListProps<T>['renderItem'];
14
17
 
15
18
  /** Initial load: while true and there's no data, placeholders are shown. */
16
19
  isLoading: boolean;
17
20
  /** Reload with data already on screen (pull-to-refresh). @default false */
18
21
  isRefreshing?: boolean;
22
+ /** Shows a spinner in the footer while the next page loads. @default false */
19
23
  isLoadingMore?: boolean;
20
24
  /** Controlled by the consumer: while false, a fullscreen spinner is shown. @default true */
21
25
  isReady?: boolean;
26
+ /** Text of the fullscreen spinner shown while `isReady` is false. @default labels.loading */
22
27
  loadingText?: string;
28
+ /** Text of the footer spinner shown with `isLoadingMore`. @default labels.loadingMore */
23
29
  loadingMoreText?: string;
24
30
 
25
31
  /** Ghost rows for the initial load. @default 6 */
@@ -27,22 +33,33 @@ export interface ListProps<T> {
27
33
  /** Custom placeholder, to match the real shape of the item. */
28
34
  renderSkeletonItem?: () => React.ReactElement;
29
35
 
36
+ /** Called when scrolling gets close to the end (to load the next page). */
30
37
  onEndReached?: () => void;
38
+ /** How close to the end `onEndReached` fires, in visible lengths of the list. @default 0.3 */
31
39
  onEndReachedThreshold?: number;
40
+ /** Enables pull-to-refresh and is called when the user pulls. */
32
41
  onRefresh?: () => void;
33
42
 
43
+ /** Title of the empty state. @default labels.noResultsTitle */
34
44
  emptyTitle?: string;
45
+ /** Supporting line of the empty state. @default labels.noResultsDescription */
35
46
  emptyDescription?: string;
47
+ /** Icon of the empty state. @default 'search' */
36
48
  emptyIconName?: IconName;
37
49
 
50
+ /** Rendered above the items, inside the scroll. */
38
51
  ListHeaderComponent?: FlatListProps<T>['ListHeaderComponent'];
52
+ /** Rendered below the items, before the pagination loader. */
39
53
  ListFooterComponent?: FlatListProps<T>['ListFooterComponent'];
40
54
 
55
+ /** Style of the list's content container (also used by the skeleton). */
41
56
  contentContainerStyle?: ViewStyle;
57
+ /** Style of the outer wrapper. */
42
58
  containerStyle?: ViewStyle;
43
59
 
44
60
  /** List component to use (FlashList, etc). @default FlatList */
45
61
  ListComponent?: React.ComponentType<any>;
62
+ /** Extra props passed to `ListComponent`; they override the ones set here. */
46
63
  listProps?: Record<string, unknown>;
47
64
  }
48
65
 
@@ -56,14 +73,33 @@ const useStyles = createStyles((theme) => ({
56
73
  gap: theme.tokens.spacing.md,
57
74
  padding: theme.tokens.spacing.md,
58
75
  },
59
- skeletonText: { flex: 1, gap: theme.tokens.spacing.sm },
76
+ skeletonText: { flex: 1 },
77
+ empty: { marginTop: theme.tokens.spacing.xxxl },
60
78
  }));
61
79
 
80
+ /** Same as Avatar's default size: the placeholder row matches a typical avatar row. */
81
+ const SKELETON_AVATAR = 44;
82
+
83
+ function renderHeader(Header: ListProps<unknown>['ListHeaderComponent']) {
84
+ if (!Header) return null;
85
+ return typeof Header === 'function' ? <Header /> : (Header as React.ReactElement);
86
+ }
87
+
62
88
  /**
63
89
  * List
64
- * Lista con estados de carga/paginación/vacío resueltos, sin atarse a
65
- * expo-router ni a FlashList: `ListComponent` permite inyectar cualquiera
66
- * (por defecto FlatList del propio React Native).
90
+ * List with loading/pagination/empty states handled, without being tied to
91
+ * expo-router or FlashList: `ListComponent` lets you inject any of them
92
+ * (React Native's own FlatList by default).
93
+ *
94
+ * Design:
95
+ * - Continuity (Gestalt): the first load shows placeholders shaped like the
96
+ * rows and keeps `ListHeaderComponent` in place, so nothing jumps when the
97
+ * data arrives.
98
+ * - Doherty threshold: every wait has immediate feedback (placeholders,
99
+ * pull-to-refresh spinner, footer loader while paging), and "no results"
100
+ * only appears once it is known there is nothing.
101
+ * - Jakob's law: the native pull-to-refresh and infinite scroll people
102
+ * already know from other apps.
67
103
  */
68
104
  export function List<T>({
69
105
  data,
@@ -98,8 +134,8 @@ export function List<T>({
98
134
 
99
135
  const isInitialLoading = isLoading && data.length === 0;
100
136
 
101
- // El footer propio y el loader de paginación conviven: antes el primero
102
- // tapaba al segundo y la lista dejaba de avisar que estaba trayendo más.
137
+ // The custom footer and the pagination loader coexist: previously the first
138
+ // covered the second and the list stopped signaling it was fetching more.
103
139
  const renderFooter = useCallback(() => {
104
140
  const custom =
105
141
  typeof ListFooterComponent === 'function' ? (
@@ -120,16 +156,16 @@ export function List<T>({
120
156
  );
121
157
  }, [isLoadingMore, resolvedLoadingMoreText, ListFooterComponent, styles.footerLoader]);
122
158
 
123
- // Vacío sólo cuando ya se sabe que no hay nada: durante la carga inicial se
124
- // muestran placeholders, no "sin resultados".
159
+ // Empty only once it is known there is nothing: during the initial load
160
+ // placeholders are shown, not "no results".
125
161
  const renderEmpty = useCallback(() => {
126
162
  if (isLoading || isRefreshing) return null;
127
- return <EmptyState title={emptyTitle} description={emptyDescription} iconName={emptyIconName} style={{ marginTop: 50 }} />;
128
- }, [isLoading, isRefreshing, emptyTitle, emptyDescription, emptyIconName]);
163
+ return <EmptyState title={emptyTitle} description={emptyDescription} iconName={emptyIconName} style={styles.empty} />;
164
+ }, [isLoading, isRefreshing, emptyTitle, emptyDescription, emptyIconName, styles.empty]);
129
165
 
130
166
  if (!isReady) {
131
167
  return (
132
- <View style={styles.container}>
168
+ <View style={[styles.container, containerStyle]}>
133
169
  <Spinner text={resolvedLoadingText} />
134
170
  </View>
135
171
  );
@@ -137,22 +173,35 @@ export function List<T>({
137
173
 
138
174
  if (isInitialLoading) {
139
175
  return (
140
- <View style={[styles.container, containerStyle]} testID="list-skeleton">
176
+ <View style={[styles.container, containerStyle]}>
141
177
  <View style={[styles.listContent, contentContainerStyle]}>
178
+ {/* Same padding as the loaded list, and outside the group below so it
179
+ stays reachable (a search field above the list, say). */}
180
+ {renderHeader(ListHeaderComponent as ListProps<unknown>['ListHeaderComponent'])}
181
+ <View
182
+ testID="list-skeleton"
183
+ // The placeholders themselves are hidden from screen readers: the
184
+ // group announces that the list is loading instead of silence.
185
+ accessible
186
+ accessibilityRole="progressbar"
187
+ accessibilityLabel={resolvedLoadingText}
188
+ accessibilityState={{ busy: true }}
189
+ >
142
190
  {Array.from({ length: skeletonCount }, (_, i) => (
143
191
  <React.Fragment key={i}>
144
192
  {renderSkeletonItem?.() ?? (
145
193
  <View style={styles.skeletonRow}>
146
- <Skeleton variant="circle" width={40} />
194
+ <Skeleton variant="circle" width={SKELETON_AVATAR} />
147
195
  <View style={styles.skeletonText}>
148
- <Skeleton width="60%" height={14} />
149
- <Skeleton width="35%" height={12} />
196
+ <Skeleton variant="text" width="60%" />
197
+ <Skeleton variant="text" width="35%" />
150
198
  </View>
151
199
  </View>
152
200
  )}
153
201
  </React.Fragment>
154
202
  ))}
155
203
  </View>
204
+ </View>
156
205
  </View>
157
206
  );
158
207
  }