orn-ui 0.2.9 → 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 +67 -52
  2. package/README.md +5 -9
  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 +197 -156
  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 +199 -158
  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 +223 -165
  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
@@ -0,0 +1,269 @@
1
+ import React, { createContext, useContext, useEffect, useLayoutEffect, useRef, useState } from 'react';
2
+ import { Modal, Platform, View, type ModalProps, type ViewStyle } from 'react-native';
3
+
4
+ /**
5
+ * NativeOverlay
6
+ * The native `Modal` every orn-ui overlay (Alert, BottomSheet, Modal, Select)
7
+ * goes through.
8
+ *
9
+ * Why: iOS presents a native modal from the root view controller and only one
10
+ * at a time. A second `<Modal>` that is not rendered inside the first one is
11
+ * silently ignored while the first is presented, and also while it is still
12
+ * being dismissed. In practice an Alert from `showAlert()` over an open
13
+ * BottomSheet never showed, and neither did one opened right after closing a
14
+ * sheet. Android opens a window per modal and never had the problem: there
15
+ * this is a plain `Modal`.
16
+ *
17
+ * iOS, when an overlay becomes visible:
18
+ * - Rendered inside another overlay (nested): plain native modal; iOS presents
19
+ * it from that one, which works.
20
+ * - Another overlay is presented and this one is not inside it: it is drawn
21
+ * as a layer inside the topmost presented overlay instead of presenting a
22
+ * second native modal. Its React context then comes from that overlay's
23
+ * position: a provider that wraps only this overlay doesn't reach it.
24
+ * - Another overlay is closing (exit animation or native dismissal): it waits
25
+ * until that one is gone, then presents.
26
+ */
27
+
28
+ export interface NativeOverlayProps
29
+ extends Pick<
30
+ ModalProps,
31
+ 'transparent' | 'animationType' | 'presentationStyle' | 'statusBarTranslucent' | 'onRequestClose' | 'hardwareAccelerated'
32
+ > {
33
+ /**
34
+ * The overlay is logically hidden but still mounted to play its exit
35
+ * animation: it stays on screen, but no other overlay may layer into it.
36
+ */
37
+ closing?: boolean;
38
+ /**
39
+ * A dialog (Alert) always ends up on top: whatever gets layered into it is
40
+ * drawn beneath its own content, and as a layer it is drawn after any
41
+ * non-dialog layer of the same host.
42
+ */
43
+ dialog?: boolean;
44
+ children: React.ReactNode;
45
+ }
46
+
47
+ type Mode = 'pending' | 'native' | 'layer' | 'wait';
48
+
49
+ interface Host {
50
+ id: number;
51
+ closing: boolean;
52
+ }
53
+
54
+ const fill: ViewStyle = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 };
55
+ /** After unmount, how long iOS may still be dismissing the native modal. */
56
+ const DISMISS_SETTLE_MS = 450;
57
+
58
+ // Module-level registry: overlays live in different React subtrees, and the
59
+ // constraint they share (one native presentation at a time) is global too.
60
+ const hosts: Host[] = [];
61
+ const layers = new Map<number, Map<number, { node: React.ReactNode; dialog: boolean }>>();
62
+ const ownerOf = new Map<number, number>();
63
+ let nextId = 1;
64
+
65
+ // Two channels, so publishing a layer (every render of a layered overlay)
66
+ // only re-renders that host's outlet, never the overlays themselves — which
67
+ // would publish again and loop.
68
+ const hostListeners = new Set<() => void>();
69
+ const layerListeners = new Map<number, Set<() => void>>();
70
+
71
+ /** The host stack changed: waiting/layered overlays re-evaluate. */
72
+ function notify() {
73
+ hostListeners.forEach((listener) => listener());
74
+ }
75
+
76
+ /** A host's layers changed: only its outlet re-renders. */
77
+ function notifyLayers(hostId: number) {
78
+ layerListeners.get(hostId)?.forEach((listener) => listener());
79
+ }
80
+
81
+ function useChannel(subscribe: (listener: () => void) => () => void) {
82
+ const [, setVersion] = useState(0);
83
+ useEffect(() => subscribe(() => setVersion((v) => v + 1)), [subscribe]);
84
+ }
85
+
86
+ const subscribeHosts = (listener: () => void) => {
87
+ hostListeners.add(listener);
88
+ return () => {
89
+ hostListeners.delete(listener);
90
+ };
91
+ };
92
+
93
+ function liveTop(): Host | undefined {
94
+ const top = hosts[hosts.length - 1];
95
+ return top && !top.closing ? top : undefined;
96
+ }
97
+
98
+ function decide(parentHost: number | null): Mode {
99
+ if (hosts.length === 0) return 'native';
100
+ const top = liveTop();
101
+ if (!top) return 'wait';
102
+ // Nested inside the topmost overlay: iOS can present it from there.
103
+ if (top.id === parentHost) return 'native';
104
+ return 'layer';
105
+ }
106
+
107
+ function unpublish(id: number) {
108
+ const owner = ownerOf.get(id);
109
+ if (owner === undefined) return;
110
+ layers.get(owner)?.delete(id);
111
+ ownerOf.delete(id);
112
+ notifyLayers(owner);
113
+ }
114
+
115
+ /** Takes the native slot right away, before any later overlay decides. */
116
+ function claim(id: number, closing: boolean) {
117
+ if (hosts.some((h) => h.id === id)) return;
118
+ hosts.push({ id, closing });
119
+ notify();
120
+ }
121
+
122
+ function removeHost(id: number) {
123
+ const index = hosts.findIndex((h) => h.id === id);
124
+ if (index < 0) return;
125
+ hosts.splice(index, 1);
126
+ notify();
127
+ }
128
+
129
+ /** Id of the native overlay this subtree is rendered in, if any. */
130
+ const HostContext = createContext<number | null>(null);
131
+
132
+ /** Draws, inside a native host, the layers other overlays put into it. */
133
+ function LayerOutlet({ hostId }: { hostId: number }) {
134
+ const [, setVersion] = useState(0);
135
+ // Layout effect + an immediate re-read: a layer may have been published in
136
+ // the same commit, before this outlet subscribed.
137
+ useLayoutEffect(() => {
138
+ const listener = () => setVersion((v) => v + 1);
139
+ if (!layerListeners.has(hostId)) layerListeners.set(hostId, new Set());
140
+ layerListeners.get(hostId)!.add(listener);
141
+ if (layers.get(hostId)?.size) listener();
142
+ return () => {
143
+ layerListeners.get(hostId)?.delete(listener);
144
+ };
145
+ }, [hostId]);
146
+ const own = layers.get(hostId);
147
+ if (!own || own.size === 0) return null;
148
+ // Dialogs last, so they are drawn on top of sheets and modals.
149
+ const ordered = [...own.entries()].sort(([, a], [, b]) => Number(a.dialog) - Number(b.dialog));
150
+ return (
151
+ <>
152
+ {ordered.map(([key, layer]) => (
153
+ <View key={key} style={fill} pointerEvents="box-none">
154
+ {layer.node}
155
+ </View>
156
+ ))}
157
+ </>
158
+ );
159
+ }
160
+
161
+ export function NativeOverlay({ closing = false, dialog = false, children, ...modalProps }: NativeOverlayProps) {
162
+ const ios = Platform.OS === 'ios';
163
+ const parentHost = useContext(HostContext);
164
+ const idRef = useRef(0);
165
+ if (idRef.current === 0) idRef.current = nextId++;
166
+ const id = idRef.current;
167
+ useChannel(subscribeHosts);
168
+
169
+ // Decided in a layout effect, not during render: layout effects run in tree
170
+ // order before paint, so when two overlays mount in the same commit the
171
+ // first one claims the native slot before the second one decides.
172
+ const [mode, setMode] = useState<Mode>(ios ? 'pending' : 'native');
173
+
174
+ useLayoutEffect(() => {
175
+ if (!ios) return;
176
+ if (mode === 'pending') {
177
+ const next = decide(parentHost);
178
+ if (next === 'native') claim(id, closing);
179
+ setMode(next);
180
+ return;
181
+ }
182
+ if (mode === 'wait' && !closing) {
183
+ const next = decide(parentHost);
184
+ if (next === 'native') claim(id, closing);
185
+ if (next !== 'wait') setMode(next);
186
+ }
187
+ // The host it layered into started closing or went away: move out.
188
+ if (mode === 'layer' && !closing) {
189
+ const owner = ownerOf.get(id);
190
+ const host = owner === undefined ? undefined : hosts.find((h) => h.id === owner);
191
+ if (owner !== undefined && (!host || host.closing)) {
192
+ unpublish(id);
193
+ const next = decide(parentHost);
194
+ if (next === 'native') claim(id, closing);
195
+ setMode(next);
196
+ }
197
+ }
198
+ });
199
+
200
+ // Native host bookkeeping.
201
+ useLayoutEffect(() => {
202
+ if (!ios || mode !== 'native') return;
203
+ const existing = hosts.find((h) => h.id === id);
204
+ if (!existing) hosts.push({ id, closing });
205
+ else if (existing.closing !== closing) existing.closing = closing;
206
+ else return;
207
+ notify();
208
+ }, [ios, mode, closing, id]);
209
+
210
+ // Layer publishing: every render, so prop changes reach the host.
211
+ useLayoutEffect(() => {
212
+ if (!ios || mode !== 'layer') return;
213
+ let owner = ownerOf.get(id);
214
+ if (owner === undefined) {
215
+ owner = liveTop()?.id;
216
+ // The host it chose started closing in the same commit (a sheet closed
217
+ // and an alert opened in one tick): decide again, usually to wait.
218
+ if (owner === undefined) {
219
+ const next = decide(parentHost);
220
+ if (next === 'native') claim(id, closing);
221
+ setMode(next);
222
+ return;
223
+ }
224
+ ownerOf.set(id, owner);
225
+ }
226
+ if (!layers.has(owner)) layers.set(owner, new Map());
227
+ layers.get(owner)!.set(id, { node: <HostContext.Provider value={owner}>{children}</HostContext.Provider>, dialog });
228
+ notifyLayers(owner);
229
+ });
230
+
231
+ // Unmount: a layer just leaves; a native host stays "closing" while iOS
232
+ // finishes dismissing it, so the next overlay doesn't present too early.
233
+ useEffect(
234
+ () => () => {
235
+ if (!ios) return;
236
+ unpublish(id);
237
+ const host = hosts.find((h) => h.id === id);
238
+ if (host) {
239
+ host.closing = true;
240
+ notify();
241
+ setTimeout(() => removeHost(id), DISMISS_SETTLE_MS);
242
+ }
243
+ },
244
+ [ios, id]
245
+ );
246
+
247
+ if (!ios || mode === 'native') {
248
+ return (
249
+ <Modal visible {...modalProps}>
250
+ <HostContext.Provider value={id}>
251
+ {/* A dialog host draws what was layered into it underneath itself. */}
252
+ {ios && dialog && <LayerOutlet hostId={id} />}
253
+ {children}
254
+ {ios && !dialog && <LayerOutlet hostId={id} />}
255
+ </HostContext.Provider>
256
+ </Modal>
257
+ );
258
+ }
259
+
260
+ // 'layer' renders inside the host; 'wait' and 'pending' render nothing yet.
261
+ return null;
262
+ }
263
+
264
+ /** Test-only: clears the registry between tests. */
265
+ export function __resetNativeOverlays() {
266
+ hosts.splice(0);
267
+ layers.clear();
268
+ ownerOf.clear();
269
+ }
@@ -1,30 +1,58 @@
1
- import React, { createContext, useContext, useMemo, useState, useCallback, useRef } from 'react';
2
- import { Appearance, useColorScheme } from 'react-native';
1
+ import React, { createContext, useContext, useMemo, useState, useCallback, useEffect } from 'react';
2
+ import { Appearance, useColorScheme, type ViewStyle } from 'react-native';
3
+ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
3
4
  import { defaultTheme } from './createTheme';
4
5
  import { defaultLabels, type Labels } from './labels';
5
- import { zeroInsets, type EdgeInsets } from './insets';
6
+ import type { EdgeInsets } from './insets';
6
7
  import type { Theme, ThemePair } from './types';
7
8
  import { renderDefaultIcon } from '../icons/defaultIcons';
8
9
  import type { IconRenderer } from '../icons/types';
10
+ import { KeyboardHandled, KeyboardPanArea } from './KeyboardAvoidance';
9
11
 
10
12
  export type ThemeMode = 'system' | 'light' | 'dark';
11
13
 
12
14
  /**
13
- * Un `<Modal>`/`<BottomSheet>` nativo abre su propia ventana (en Android
14
- * siempre; en iOS según `presentationStyle`), así que los insets medidos en
15
- * la raíz de la app pueden no valer ahí adentro. Este boundary es el punto de
16
- * inyección: el default sólo repite los insets ambientes (comportamiento de
17
- * siempre, cero deps), pero `SafeAreaUIProvider` lo reemplaza por uno que
18
- * monta un `<SafeAreaProvider>` nuevo y remide dentro de esa ventana.
15
+ * A native `<Modal>`/`<BottomSheet>` opens its own window (always on Android;
16
+ * on iOS depending on `presentationStyle`), so the insets measured at the app
17
+ * root may not hold in there. The boundary mounts a new `<SafeAreaProvider>`
18
+ * inside that window and re-measures; until the first measurement arrives it
19
+ * repeats the ambient insets.
19
20
  */
20
21
  export interface ModalSafeAreaBoundaryProps {
21
22
  children: (insets: EdgeInsets) => React.ReactNode;
22
23
  }
23
24
  export type ModalSafeAreaBoundaryComponent = React.ComponentType<ModalSafeAreaBoundaryProps>;
24
25
 
25
- function DefaultModalSafeAreaBoundary({ children }: ModalSafeAreaBoundaryProps) {
26
- const insets = useInsets();
27
- return <>{children(insets)}</>;
26
+ const probeStyle: ViewStyle = { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 };
27
+
28
+ function sameInsets(a: EdgeInsets, b: EdgeInsets) {
29
+ return a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;
30
+ }
31
+
32
+ function InsetsProbe({ onMeasure }: { onMeasure: (insets: EdgeInsets) => void }) {
33
+ const insets = useSafeAreaInsets();
34
+ useEffect(() => {
35
+ onMeasure(insets);
36
+ }, [insets, onMeasure]);
37
+ return null;
38
+ }
39
+
40
+ function RemeasuringModalSafeAreaBoundary({ children }: ModalSafeAreaBoundaryProps) {
41
+ const ambient = useInsets();
42
+ const [measured, setMeasured] = useState<EdgeInsets | null>(null);
43
+ const onMeasure = useCallback(
44
+ (next: EdgeInsets) => setMeasured((prev) => (prev && sameInsets(prev, next) ? prev : next)),
45
+ []
46
+ );
47
+
48
+ return (
49
+ <>
50
+ <SafeAreaProvider style={probeStyle} pointerEvents="none">
51
+ <InsetsProbe onMeasure={onMeasure} />
52
+ </SafeAreaProvider>
53
+ {children(measured ?? ambient)}
54
+ </>
55
+ );
28
56
  }
29
57
 
30
58
  interface UIContextValue {
@@ -51,38 +79,79 @@ export interface UIProviderProps {
51
79
  onModeChange?: (mode: ThemeMode) => void;
52
80
  /** Icon renderer. Defaults to the included zero-dep glyphs. */
53
81
  icons?: IconRenderer;
54
- /** Safe area insets (from useSafeAreaInsets()). Defaults to {0,0,0,0}. */
82
+ /**
83
+ * Overrides the measured safe area insets. Leave it out: the provider
84
+ * measures them itself with react-native-safe-area-context.
85
+ */
55
86
  insets?: EdgeInsets;
56
87
  labels?: Partial<Labels>;
57
- /** @default false, for parity with the rest of the library (accessibility first). */
88
+ /**
89
+ * Lets every orn-ui text follow the system font size (Dynamic Type / Android
90
+ * font scale). Opt-in: layouts are tuned for the default size, so turn it on
91
+ * only after checking your screens at large sizes.
92
+ * @default false
93
+ */
58
94
  allowFontScaling?: boolean;
59
95
  /**
60
- * Source of insets used by `Modal`/`BottomSheet` for their own native
61
- * window. Don't pass this by hand — `SafeAreaUIProvider` wires it up itself.
62
- * @default repeats the ambient insets (behavior without safe-area-context)
96
+ * Mounts a `<SafeAreaProvider>` around the app. Pass `false` only if the app
97
+ * already mounts one above (e.g. expo-router does): insets are then read
98
+ * from that one.
99
+ * @default true
100
+ */
101
+ mountSafeAreaProvider?: boolean;
102
+ /**
103
+ * Keeps the focused Input visible above the keyboard by moving the whole app
104
+ * up just enough (like Android's adjustPan, on both platforms), with no
105
+ * Screen or ScrollView needed. Only the root provider does it. Turn it off if
106
+ * your app already handles the keyboard its own way.
107
+ * @default true
63
108
  */
64
- ModalSafeAreaBoundary?: ModalSafeAreaBoundaryComponent;
109
+ keyboardAvoidance?: boolean;
110
+ }
111
+
112
+ interface UIProviderBaseProps extends Omit<UIProviderProps, 'insets' | 'mountSafeAreaProvider'> {
113
+ insets: EdgeInsets;
65
114
  }
66
115
 
67
116
  /**
68
117
  * UIProvider
69
- * Único punto de entrada de la librería: resuelve el theme activo (sistema u
70
- * override manual), e inyecta íconos, insets y textos por defecto a todo el
71
- * árbol. No persiste el modo — si el consumidor quiere recordar la preferencia
72
- * entre sesiones, controla `mode`/`onModeChange` y persiste donde prefiera.
118
+ * The library's single entry point: resolves the active theme (system or
119
+ * manual override), measures the safe area insets (react-native-safe-area-context,
120
+ * a required peer) and injects icons, insets and default texts into the whole
121
+ * tree. It doesn't persist the mode — if the consumer wants to remember the
122
+ * preference across sessions, it controls `mode`/`onModeChange` and persists
123
+ * wherever it prefers.
73
124
  */
74
- export function UIProvider({
125
+ export function UIProvider({ mountSafeAreaProvider = true, ...props }: UIProviderProps) {
126
+ if (!mountSafeAreaProvider) return <MeasuredUIProvider {...props} />;
127
+ return (
128
+ <SafeAreaProvider>
129
+ <MeasuredUIProvider {...props} />
130
+ </SafeAreaProvider>
131
+ );
132
+ }
133
+
134
+ function MeasuredUIProvider({ insets: override, ...rest }: Omit<UIProviderProps, 'mountSafeAreaProvider'>) {
135
+ const measured = useSafeAreaInsets();
136
+ return <UIProviderBase insets={override ?? measured} {...rest} />;
137
+ }
138
+
139
+ function UIProviderBase({
75
140
  children,
76
141
  theme = defaultTheme,
77
142
  defaultMode = 'system',
78
143
  mode: controlledMode,
79
144
  onModeChange,
80
145
  icons = renderDefaultIcon,
81
- insets = zeroInsets,
146
+ insets,
82
147
  labels: labelOverrides,
83
148
  allowFontScaling = false,
84
- ModalSafeAreaBoundary = DefaultModalSafeAreaBoundary,
85
- }: UIProviderProps) {
149
+ keyboardAvoidance = true,
150
+ }: UIProviderBaseProps) {
151
+ // Only the root provider shifts the app: a nested one (a modal with its own
152
+ // provider, a test) wraps nothing and doesn't change the layout.
153
+ const isRoot = useContext(UIContext) === undefined;
154
+ const ModalSafeAreaBoundary = RemeasuringModalSafeAreaBoundary;
86
155
  const systemScheme = useColorScheme();
87
156
  const [uncontrolledMode, setUncontrolledMode] = useState<ThemeMode>(defaultMode);
88
157
  const isControlled = controlledMode !== undefined;
@@ -96,23 +165,6 @@ export function UIProvider({
96
165
  [isControlled, onModeChange]
97
166
  );
98
167
 
99
- // Por instancia, no por módulo: dos `<UIProvider>` en el mismo árbol (tests,
100
- // un modal con su propio provider) avisan cada uno si le faltan insets, en
101
- // vez de que el segundo se calle porque el primero ya avisó una vez.
102
- const warnedAboutInsets = useRef(false);
103
-
104
- // Olvidar `insets` no rompe nada visible al montar: el default de ceros
105
- // recién se nota cuando abrís un Modal `full` (se mete abajo del notch) o un
106
- // BottomSheet (queda pegado a la barra de gestos). El aviso llega antes.
107
- if (__DEV__ && insets === zeroInsets && !warnedAboutInsets.current) {
108
- warnedAboutInsets.current = true;
109
- console.warn(
110
- 'orn-ui: <UIProvider> sin `insets`, se usan {top:0,bottom:0,left:0,right:0}. ' +
111
- 'Los modales y el Screen quedan sin safe area. Pasá `insets={useSafeAreaInsets()}` ' +
112
- "o usá <SafeAreaUIProvider> de 'orn-ui/safe-area', que lo cablea solo."
113
- );
114
- }
115
-
116
168
  const scheme: 'light' | 'dark' =
117
169
  mode === 'system' ? (systemScheme === 'dark' ? 'dark' : 'light') : mode;
118
170
 
@@ -137,7 +189,18 @@ export function UIProvider({
137
189
  [resolvedTheme, mode, setMode, icons, insets, labels, allowFontScaling, ModalSafeAreaBoundary]
138
190
  );
139
191
 
140
- return <UIContext.Provider value={value}>{children}</UIContext.Provider>;
192
+ let content = children;
193
+ if (isRoot) {
194
+ content = keyboardAvoidance ? (
195
+ <KeyboardPanArea margin={resolvedTheme.tokens.spacing.md} topLimit={insets.top}>
196
+ {children}
197
+ </KeyboardPanArea>
198
+ ) : (
199
+ <KeyboardHandled>{children}</KeyboardHandled>
200
+ );
201
+ }
202
+
203
+ return <UIContext.Provider value={value}>{content}</UIContext.Provider>;
141
204
  }
142
205
 
143
206
  function useUIContext(): UIContextValue {
@@ -177,10 +240,10 @@ export function useAllowFontScaling(): boolean {
177
240
  return useUIContext().allowFontScaling;
178
241
  }
179
242
 
180
- /** Interno: lo consumen `Modal`/`BottomSheet` para remedir insets dentro de su propia ventana nativa. */
243
+ /** Internal: consumed by `Modal`/`BottomSheet` to re-measure insets inside their own native window. */
181
244
  export function useModalSafeAreaBoundary(): ModalSafeAreaBoundaryComponent {
182
245
  return useUIContext().ModalSafeAreaBoundary;
183
246
  }
184
247
 
185
- /** Re-exportado para que tests/consumidores puedan simular cambios de sistema sin RN real. */
248
+ /** Re-exported so tests/consumers can simulate system changes without real RN. */
186
249
  export const __testUtils = { Appearance };
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Utilidades de color sin dependencias, usadas para derivar una familia de
3
- * roles (relleno / encima / tenue / legible) a partir de un solo hex de marca.
2
+ * Dependency-free color utilities, used to derive a family of roles
3
+ * (fill / on-top / soft / readable) from a single brand hex.
4
4
  */
5
5
 
6
- /** Contraste mínimo AA para texto normal. */
6
+ /** Minimum AA contrast for normal text. */
7
7
  export const AA_CONTRAST = 4.5;
8
8
 
9
9
  export interface Rgb {
@@ -18,15 +18,15 @@ export interface Hsl {
18
18
  l: number;
19
19
  }
20
20
 
21
- /** Roles que necesita un acento del theme, en un esquema concreto. */
21
+ /** Roles a theme accent needs, in a given scheme. */
22
22
  export interface AccentRoles {
23
- /** Relleno pleno: fondo de botón, círculo del paso actual. */
23
+ /** Solid fill: button background, current step's circle. */
24
24
  base: string;
25
- /** Texto/ícono que va encima del relleno. */
25
+ /** Text/icon placed on top of the fill. */
26
26
  on: string;
27
- /** Fondo tenue: badges, pill del indicador activo. */
27
+ /** Subtle background: badges, active indicator pill. */
28
28
  soft: string;
29
- /** El acento legible sobre `surface`: labels, links. */
29
+ /** The accent legible on `surface`: labels, links. */
30
30
  text: string;
31
31
  }
32
32
 
@@ -35,7 +35,7 @@ const HEX = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i;
35
35
  export function hexToRgb(hex: string): Rgb {
36
36
  const match = HEX.exec(hex.trim());
37
37
  if (!match) {
38
- throw new Error(`orn-ui: se esperaba un color hex como "#7c3aed", se recibió "${hex}".`);
38
+ throw new Error(`orn-ui: expected a hex color like "#7c3aed", got "${hex}".`);
39
39
  }
40
40
  const digits = match[1]!;
41
41
  const full = digits.length === 3 ? digits.replace(/./g, (c) => c + c) : digits;
@@ -100,13 +100,13 @@ function channelLuminance(value: number) {
100
100
  return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
101
101
  }
102
102
 
103
- /** Luminancia relativa WCAG de un hex. */
103
+ /** WCAG relative luminance of a hex. */
104
104
  export function luminance(hex: string): number {
105
105
  const { r, g, b } = hexToRgb(hex);
106
106
  return 0.2126 * channelLuminance(r) + 0.7152 * channelLuminance(g) + 0.0722 * channelLuminance(b);
107
107
  }
108
108
 
109
- /** Ratio de contraste WCAG entre dos hex: 1 (igual) a 21 (blanco sobre negro). */
109
+ /** WCAG contrast ratio between two hexes: 1 (equal) to 21 (white on black). */
110
110
  export function contrast(a: string, b: string): number {
111
111
  const la = luminance(a);
112
112
  const lb = luminance(b);
@@ -114,8 +114,8 @@ export function contrast(a: string, b: string): number {
114
114
  }
115
115
 
116
116
  /**
117
- * Blanco si alcanza el contraste AA —es lo que se espera encima de un relleno
118
- * de color— y si no, el extremo que más contraste dé.
117
+ * White if it reaches AA contrast —which is what you expect on top of a color
118
+ * fill— and otherwise whichever extreme gives the most contrast.
119
119
  */
120
120
  function bestOnColor(background: string, light: string, dark: string): string {
121
121
  if (contrast(background, light) >= AA_CONTRAST) return light;
@@ -123,9 +123,9 @@ function bestOnColor(background: string, light: string, dark: string): string {
123
123
  }
124
124
 
125
125
  /**
126
- * Mueve la luminosidad del tono hasta alcanzar el contraste pedido contra
127
- * `against`. Si ni el extremo llega —un amarillo puro sobre blanco, por
128
- * ejemplo— devuelve el más contrastado que encontró en el camino.
126
+ * Shifts the hue's lightness until it reaches the requested contrast against
127
+ * `against`. If not even the extreme gets there —pure yellow on white, for
128
+ * example— it returns the most contrasting one found along the way.
129
129
  */
130
130
  function reachContrast(hsl: Hsl, against: string, target: number, direction: 'darker' | 'lighter'): string {
131
131
  const step = direction === 'darker' ? -0.02 : 0.02;
@@ -146,9 +146,9 @@ function reachContrast(hsl: Hsl, against: string, target: number, direction: 'da
146
146
  }
147
147
 
148
148
  /**
149
- * Deriva los cuatro roles de un acento a partir de un hex, para un esquema.
150
- * `surface` es el fondo sobre el que tiene que leerse el rol `text`, así que
151
- * cada esquema pasa el suyo.
149
+ * Derives an accent's four roles from a hex, for one scheme.
150
+ * `surface` is the background the `text` role has to be read on, so each
151
+ * scheme passes its own.
152
152
  */
153
153
  export function deriveAccent(hex: string, scheme: 'light' | 'dark', surface: string): AccentRoles {
154
154
  const hsl = toHsl(hex);
@@ -163,8 +163,8 @@ export function deriveAccent(hex: string, scheme: 'light' | 'dark', surface: str
163
163
  };
164
164
  }
165
165
 
166
- // En oscuro el acento sube de luminosidad y lo que va encima baja: un
167
- // #004cef sobre #1e1e1e no se distingue del fondo.
166
+ // In dark the accent goes up in lightness and what sits on top goes down: a
167
+ // #004cef over #1e1e1e can't be told apart from the background.
168
168
  const base = toHex({ ...hsl, l: 0.72 });
169
169
  return {
170
170
  base,
@@ -1,26 +1,30 @@
1
- import { StyleSheet } from 'react-native';
1
+ import { StyleSheet, type ImageStyle, type TextStyle, type ViewStyle } from 'react-native';
2
2
  import { useTheme } from './UIProvider';
3
3
  import type { Theme } from './types';
4
4
 
5
5
  /**
6
6
  * createStyles(factory)
7
- * Devuelve un hook useStyles() que memoiza el StyleSheet resultante por
8
- * theme (WeakMap<Theme, Styles>), no por instancia de componente. Todas las
9
- * filas de una lista comparten el mismo objeto de estilos: sin esto, N filas
10
- * ⇒ N StyleSheet.create() por render, que es lo que hacía cada componente
11
- * de la app original con `useMemo(() => createStyles(colors), [colors])`.
7
+ * Returns a useStyles() hook that memoizes the resulting StyleSheet per
8
+ * theme (WeakMap<Theme, Styles>), not per component instance. All rows of a
9
+ * list share the same styles object: without this, N rows ⇒ N
10
+ * StyleSheet.create() per render, which is what every component of the
11
+ * original app did with `useMemo(() => createStyles(colors), [colors])`.
12
12
  *
13
- * La cache vive en el closure del factory (una WeakMap por llamada a
14
- * createStyles, es decir, una por componente), así que temas de distintos
15
- * <UIProvider> en el mismo árbol no colisionan entre sí.
13
+ * The cache lives in the factory's closure (one WeakMap per createStyles
14
+ * call, i.e. one per component), so themes from different <UIProvider>s in
15
+ * the same tree don't collide with each other.
16
16
  *
17
- * El tipo de `factory` sigue el patrón oficial de RN para StyleSheet
18
- * tipados (`T extends StyleSheet.NamedStyles<T> | StyleSheet.NamedStyles<any>`):
19
- * es lo que le da contexto a TS para inferir literales ('row', 'center', ...)
20
- * en vez de ensancharlos a `string` dentro del objeto devuelto.
17
+ * The `factory` type follows RN's pattern for typed StyleSheets
18
+ * (`T extends NamedStyles<T> | NamedStyles<any>`): it is what gives TS the
19
+ * context to infer literals ('row', 'center', ...) instead of widening them
20
+ * to `string` inside the returned object. `NamedStyles` is declared here:
21
+ * react-native 0.88's generated types (Expo SDK 58) no longer export
22
+ * `StyleSheet.NamedStyles`.
21
23
  */
22
- export function createStyles<T extends StyleSheet.NamedStyles<T> | StyleSheet.NamedStyles<any>>(
23
- factory: (theme: Theme) => T | StyleSheet.NamedStyles<T>
24
+ type NamedStyles<T> = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle };
25
+
26
+ export function createStyles<T extends NamedStyles<T> | NamedStyles<any>>(
27
+ factory: (theme: Theme) => T | NamedStyles<T>
24
28
  ): () => T {
25
29
  const cache = new WeakMap<Theme, T>();
26
30
 
@@ -28,10 +32,10 @@ export function createStyles<T extends StyleSheet.NamedStyles<T> | StyleSheet.Na
28
32
  const theme = useTheme();
29
33
  let styles = cache.get(theme);
30
34
  if (!styles) {
31
- // El cast es seguro: StyleSheet.create<T>(...) con el mismo T del
32
- // factory siempre devuelve T; TS no puede probarlo por sí solo dentro
33
- // de un cuerpo genérico (T podría "instanciarse" con un subtipo no
34
- // relacionado desde su punto de vista, aunque en runtime es el mismo).
35
+ // The cast is safe: StyleSheet.create<T>(...) with the factory's same T
36
+ // always returns T; TS can't prove it on its own inside a generic body
37
+ // (T could be "instantiated" with an unrelated subtype from its point
38
+ // of view, even though at runtime it is the same).
35
39
  styles = StyleSheet.create(factory(theme)) as T;
36
40
  cache.set(theme, styles);
37
41
  }