blend-native 0.0.1-beta.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 (555) hide show
  1. package/README.md +404 -0
  2. package/lib/commonjs/a11y/announcement.js +42 -0
  3. package/lib/commonjs/a11y/announcement.js.map +1 -0
  4. package/lib/commonjs/a11y/useLiveRegion.js +37 -0
  5. package/lib/commonjs/a11y/useLiveRegion.js.map +1 -0
  6. package/lib/commonjs/adapters/cssStringAdapter.js +363 -0
  7. package/lib/commonjs/adapters/cssStringAdapter.js.map +1 -0
  8. package/lib/commonjs/adapters/optionalGradient.js +33 -0
  9. package/lib/commonjs/adapters/optionalGradient.js.map +1 -0
  10. package/lib/commonjs/adapters/surfaceStyle.js +159 -0
  11. package/lib/commonjs/adapters/surfaceStyle.js.map +1 -0
  12. package/lib/commonjs/components/Alert/Alert.js +130 -0
  13. package/lib/commonjs/components/Alert/Alert.js.map +1 -0
  14. package/lib/commonjs/components/Alert/AlertActions.js +74 -0
  15. package/lib/commonjs/components/Alert/AlertActions.js.map +1 -0
  16. package/lib/commonjs/components/Alert/AlertClose.js +48 -0
  17. package/lib/commonjs/components/Alert/AlertClose.js.map +1 -0
  18. package/lib/commonjs/components/Alert/AlertText.js +49 -0
  19. package/lib/commonjs/components/Alert/AlertText.js.map +1 -0
  20. package/lib/commonjs/components/Alert/alert.tokens.js +6 -0
  21. package/lib/commonjs/components/Alert/alert.tokens.js.map +1 -0
  22. package/lib/commonjs/components/Alert/alert.types.js +6 -0
  23. package/lib/commonjs/components/Alert/alert.types.js.map +1 -0
  24. package/lib/commonjs/components/Alert/alert.utils.js +80 -0
  25. package/lib/commonjs/components/Alert/alert.utils.js.map +1 -0
  26. package/lib/commonjs/components/Alert/index.js +51 -0
  27. package/lib/commonjs/components/Alert/index.js.map +1 -0
  28. package/lib/commonjs/components/Button/Button.js +125 -0
  29. package/lib/commonjs/components/Button/Button.js.map +1 -0
  30. package/lib/commonjs/components/Button/button.types.js +6 -0
  31. package/lib/commonjs/components/Button/button.types.js.map +1 -0
  32. package/lib/commonjs/components/Button/button.utils.js +129 -0
  33. package/lib/commonjs/components/Button/button.utils.js.map +1 -0
  34. package/lib/commonjs/components/Button/index.js +57 -0
  35. package/lib/commonjs/components/Button/index.js.map +1 -0
  36. package/lib/commonjs/components/Skeleton/Skeleton.js +154 -0
  37. package/lib/commonjs/components/Skeleton/Skeleton.js.map +1 -0
  38. package/lib/commonjs/components/Skeleton/index.js +20 -0
  39. package/lib/commonjs/components/Skeleton/index.js.map +1 -0
  40. package/lib/commonjs/components/Skeleton/skeleton.types.js +6 -0
  41. package/lib/commonjs/components/Skeleton/skeleton.types.js.map +1 -0
  42. package/lib/commonjs/components/Skeleton/skeleton.utils.js +45 -0
  43. package/lib/commonjs/components/Skeleton/skeleton.utils.js.map +1 -0
  44. package/lib/commonjs/components/Tag/Tag.js +161 -0
  45. package/lib/commonjs/components/Tag/Tag.js.map +1 -0
  46. package/lib/commonjs/components/Tag/index.js +33 -0
  47. package/lib/commonjs/components/Tag/index.js.map +1 -0
  48. package/lib/commonjs/components/Tag/tag.types.js +6 -0
  49. package/lib/commonjs/components/Tag/tag.types.js.map +1 -0
  50. package/lib/commonjs/components/Tag/tag.utils.js +69 -0
  51. package/lib/commonjs/components/Tag/tag.utils.js.map +1 -0
  52. package/lib/commonjs/components/TextInput/TextInput.js +138 -0
  53. package/lib/commonjs/components/TextInput/TextInput.js.map +1 -0
  54. package/lib/commonjs/components/TextInput/index.js +14 -0
  55. package/lib/commonjs/components/TextInput/index.js.map +1 -0
  56. package/lib/commonjs/components/TextInput/textInput.types.js +6 -0
  57. package/lib/commonjs/components/TextInput/textInput.types.js.map +1 -0
  58. package/lib/commonjs/components/TextInput/textInput.utils.js +40 -0
  59. package/lib/commonjs/components/TextInput/textInput.utils.js.map +1 -0
  60. package/lib/commonjs/components/shared/field/FieldFooter.js +51 -0
  61. package/lib/commonjs/components/shared/field/FieldFooter.js.map +1 -0
  62. package/lib/commonjs/components/shared/field/FieldLabels.js +67 -0
  63. package/lib/commonjs/components/shared/field/FieldLabels.js.map +1 -0
  64. package/lib/commonjs/components/shared/field/fieldState.js +37 -0
  65. package/lib/commonjs/components/shared/field/fieldState.js.map +1 -0
  66. package/lib/commonjs/components/shared/group.js +73 -0
  67. package/lib/commonjs/components/shared/group.js.map +1 -0
  68. package/lib/commonjs/index.js +256 -0
  69. package/lib/commonjs/index.js.map +1 -0
  70. package/lib/commonjs/motion/motion.js +128 -0
  71. package/lib/commonjs/motion/motion.js.map +1 -0
  72. package/lib/commonjs/motion/useReduceMotion.js +37 -0
  73. package/lib/commonjs/motion/useReduceMotion.js.map +1 -0
  74. package/lib/commonjs/overlay/portal.js +110 -0
  75. package/lib/commonjs/overlay/portal.js.map +1 -0
  76. package/lib/commonjs/overlay/positioning.js +122 -0
  77. package/lib/commonjs/overlay/positioning.js.map +1 -0
  78. package/lib/commonjs/overlay/safeAreaInsets.js +30 -0
  79. package/lib/commonjs/overlay/safeAreaInsets.js.map +1 -0
  80. package/lib/commonjs/overlay/sheet/BottomSheet.js +196 -0
  81. package/lib/commonjs/overlay/sheet/BottomSheet.js.map +1 -0
  82. package/lib/commonjs/overlay/sheet/sheetMath.js +60 -0
  83. package/lib/commonjs/overlay/sheet/sheetMath.js.map +1 -0
  84. package/lib/commonjs/overlay/toast/ToastOutlet.js +106 -0
  85. package/lib/commonjs/overlay/toast/ToastOutlet.js.map +1 -0
  86. package/lib/commonjs/overlay/toast/toastStore.js +76 -0
  87. package/lib/commonjs/overlay/toast/toastStore.js.map +1 -0
  88. package/lib/commonjs/overlay/useAnchoredPosition.js +85 -0
  89. package/lib/commonjs/overlay/useAnchoredPosition.js.map +1 -0
  90. package/lib/commonjs/package.json +1 -0
  91. package/lib/commonjs/primitives/Block.js +112 -0
  92. package/lib/commonjs/primitives/Block.js.map +1 -0
  93. package/lib/commonjs/primitives/Pressable.js +348 -0
  94. package/lib/commonjs/primitives/Pressable.js.map +1 -0
  95. package/lib/commonjs/primitives/PrimitiveInput.js +66 -0
  96. package/lib/commonjs/primitives/PrimitiveInput.js.map +1 -0
  97. package/lib/commonjs/primitives/Separator.js +55 -0
  98. package/lib/commonjs/primitives/Separator.js.map +1 -0
  99. package/lib/commonjs/primitives/Slot.js +78 -0
  100. package/lib/commonjs/primitives/Slot.js.map +1 -0
  101. package/lib/commonjs/primitives/Text.js +73 -0
  102. package/lib/commonjs/primitives/Text.js.map +1 -0
  103. package/lib/commonjs/primitives/pressFeedback.js +53 -0
  104. package/lib/commonjs/primitives/pressFeedback.js.map +1 -0
  105. package/lib/commonjs/primitives/textStyle.js +27 -0
  106. package/lib/commonjs/primitives/textStyle.js.map +1 -0
  107. package/lib/commonjs/primitives/tintSlot.js +45 -0
  108. package/lib/commonjs/primitives/tintSlot.js.map +1 -0
  109. package/lib/commonjs/primitives/touchTarget.js +64 -0
  110. package/lib/commonjs/primitives/touchTarget.js.map +1 -0
  111. package/lib/commonjs/theme/BlendNativeProvider.js +90 -0
  112. package/lib/commonjs/theme/BlendNativeProvider.js.map +1 -0
  113. package/lib/commonjs/theme/breakpoint.js +36 -0
  114. package/lib/commonjs/theme/breakpoint.js.map +1 -0
  115. package/lib/commonjs/theme/fonts.js +58 -0
  116. package/lib/commonjs/theme/fonts.js.map +1 -0
  117. package/lib/commonjs/theme/nativeTokenRegistry.js +44 -0
  118. package/lib/commonjs/theme/nativeTokenRegistry.js.map +1 -0
  119. package/lib/commonjs/theme/systemTheme.js +35 -0
  120. package/lib/commonjs/theme/systemTheme.js.map +1 -0
  121. package/lib/commonjs/theme/useNativeBreakpoint.js +33 -0
  122. package/lib/commonjs/theme/useNativeBreakpoint.js.map +1 -0
  123. package/lib/commonjs/theme/useNativeTokens.js +71 -0
  124. package/lib/commonjs/theme/useNativeTokens.js.map +1 -0
  125. package/lib/module/a11y/announcement.js +38 -0
  126. package/lib/module/a11y/announcement.js.map +1 -0
  127. package/lib/module/a11y/useLiveRegion.js +33 -0
  128. package/lib/module/a11y/useLiveRegion.js.map +1 -0
  129. package/lib/module/adapters/cssStringAdapter.js +352 -0
  130. package/lib/module/adapters/cssStringAdapter.js.map +1 -0
  131. package/lib/module/adapters/optionalGradient.js +29 -0
  132. package/lib/module/adapters/optionalGradient.js.map +1 -0
  133. package/lib/module/adapters/surfaceStyle.js +155 -0
  134. package/lib/module/adapters/surfaceStyle.js.map +1 -0
  135. package/lib/module/components/Alert/Alert.js +126 -0
  136. package/lib/module/components/Alert/Alert.js.map +1 -0
  137. package/lib/module/components/Alert/AlertActions.js +70 -0
  138. package/lib/module/components/Alert/AlertActions.js.map +1 -0
  139. package/lib/module/components/Alert/AlertClose.js +44 -0
  140. package/lib/module/components/Alert/AlertClose.js.map +1 -0
  141. package/lib/module/components/Alert/AlertText.js +45 -0
  142. package/lib/module/components/Alert/AlertText.js.map +1 -0
  143. package/lib/module/components/Alert/alert.tokens.js +4 -0
  144. package/lib/module/components/Alert/alert.tokens.js.map +1 -0
  145. package/lib/module/components/Alert/alert.types.js +4 -0
  146. package/lib/module/components/Alert/alert.types.js.map +1 -0
  147. package/lib/module/components/Alert/alert.utils.js +72 -0
  148. package/lib/module/components/Alert/alert.utils.js.map +1 -0
  149. package/lib/module/components/Alert/index.js +6 -0
  150. package/lib/module/components/Alert/index.js.map +1 -0
  151. package/lib/module/components/Button/Button.js +121 -0
  152. package/lib/module/components/Button/Button.js.map +1 -0
  153. package/lib/module/components/Button/button.types.js +4 -0
  154. package/lib/module/components/Button/button.types.js.map +1 -0
  155. package/lib/module/components/Button/button.utils.js +120 -0
  156. package/lib/module/components/Button/button.utils.js.map +1 -0
  157. package/lib/module/components/Button/index.js +5 -0
  158. package/lib/module/components/Button/index.js.map +1 -0
  159. package/lib/module/components/Skeleton/Skeleton.js +149 -0
  160. package/lib/module/components/Skeleton/Skeleton.js.map +1 -0
  161. package/lib/module/components/Skeleton/index.js +4 -0
  162. package/lib/module/components/Skeleton/index.js.map +1 -0
  163. package/lib/module/components/Skeleton/skeleton.types.js +4 -0
  164. package/lib/module/components/Skeleton/skeleton.types.js.map +1 -0
  165. package/lib/module/components/Skeleton/skeleton.utils.js +40 -0
  166. package/lib/module/components/Skeleton/skeleton.utils.js.map +1 -0
  167. package/lib/module/components/Tag/Tag.js +157 -0
  168. package/lib/module/components/Tag/Tag.js.map +1 -0
  169. package/lib/module/components/Tag/index.js +5 -0
  170. package/lib/module/components/Tag/index.js.map +1 -0
  171. package/lib/module/components/Tag/tag.types.js +4 -0
  172. package/lib/module/components/Tag/tag.types.js.map +1 -0
  173. package/lib/module/components/Tag/tag.utils.js +64 -0
  174. package/lib/module/components/Tag/tag.utils.js.map +1 -0
  175. package/lib/module/components/TextInput/TextInput.js +134 -0
  176. package/lib/module/components/TextInput/TextInput.js.map +1 -0
  177. package/lib/module/components/TextInput/index.js +4 -0
  178. package/lib/module/components/TextInput/index.js.map +1 -0
  179. package/lib/module/components/TextInput/textInput.types.js +4 -0
  180. package/lib/module/components/TextInput/textInput.types.js.map +1 -0
  181. package/lib/module/components/TextInput/textInput.utils.js +36 -0
  182. package/lib/module/components/TextInput/textInput.utils.js.map +1 -0
  183. package/lib/module/components/shared/field/FieldFooter.js +47 -0
  184. package/lib/module/components/shared/field/FieldFooter.js.map +1 -0
  185. package/lib/module/components/shared/field/FieldLabels.js +63 -0
  186. package/lib/module/components/shared/field/FieldLabels.js.map +1 -0
  187. package/lib/module/components/shared/field/fieldState.js +33 -0
  188. package/lib/module/components/shared/field/fieldState.js.map +1 -0
  189. package/lib/module/components/shared/group.js +68 -0
  190. package/lib/module/components/shared/group.js.map +1 -0
  191. package/lib/module/index.js +80 -0
  192. package/lib/module/index.js.map +1 -0
  193. package/lib/module/motion/motion.js +123 -0
  194. package/lib/module/motion/motion.js.map +1 -0
  195. package/lib/module/motion/useReduceMotion.js +33 -0
  196. package/lib/module/motion/useReduceMotion.js.map +1 -0
  197. package/lib/module/overlay/portal.js +104 -0
  198. package/lib/module/overlay/portal.js.map +1 -0
  199. package/lib/module/overlay/positioning.js +118 -0
  200. package/lib/module/overlay/positioning.js.map +1 -0
  201. package/lib/module/overlay/safeAreaInsets.js +27 -0
  202. package/lib/module/overlay/safeAreaInsets.js.map +1 -0
  203. package/lib/module/overlay/sheet/BottomSheet.js +190 -0
  204. package/lib/module/overlay/sheet/BottomSheet.js.map +1 -0
  205. package/lib/module/overlay/sheet/sheetMath.js +53 -0
  206. package/lib/module/overlay/sheet/sheetMath.js.map +1 -0
  207. package/lib/module/overlay/toast/ToastOutlet.js +101 -0
  208. package/lib/module/overlay/toast/ToastOutlet.js.map +1 -0
  209. package/lib/module/overlay/toast/toastStore.js +66 -0
  210. package/lib/module/overlay/toast/toastStore.js.map +1 -0
  211. package/lib/module/overlay/useAnchoredPosition.js +82 -0
  212. package/lib/module/overlay/useAnchoredPosition.js.map +1 -0
  213. package/lib/module/package.json +1 -0
  214. package/lib/module/primitives/Block.js +107 -0
  215. package/lib/module/primitives/Block.js.map +1 -0
  216. package/lib/module/primitives/Pressable.js +339 -0
  217. package/lib/module/primitives/Pressable.js.map +1 -0
  218. package/lib/module/primitives/PrimitiveInput.js +62 -0
  219. package/lib/module/primitives/PrimitiveInput.js.map +1 -0
  220. package/lib/module/primitives/Separator.js +50 -0
  221. package/lib/module/primitives/Separator.js.map +1 -0
  222. package/lib/module/primitives/Slot.js +69 -0
  223. package/lib/module/primitives/Slot.js.map +1 -0
  224. package/lib/module/primitives/Text.js +68 -0
  225. package/lib/module/primitives/Text.js.map +1 -0
  226. package/lib/module/primitives/pressFeedback.js +48 -0
  227. package/lib/module/primitives/pressFeedback.js.map +1 -0
  228. package/lib/module/primitives/textStyle.js +23 -0
  229. package/lib/module/primitives/textStyle.js.map +1 -0
  230. package/lib/module/primitives/tintSlot.js +42 -0
  231. package/lib/module/primitives/tintSlot.js.map +1 -0
  232. package/lib/module/primitives/touchTarget.js +58 -0
  233. package/lib/module/primitives/touchTarget.js.map +1 -0
  234. package/lib/module/theme/BlendNativeProvider.js +78 -0
  235. package/lib/module/theme/BlendNativeProvider.js.map +1 -0
  236. package/lib/module/theme/breakpoint.js +33 -0
  237. package/lib/module/theme/breakpoint.js.map +1 -0
  238. package/lib/module/theme/fonts.js +55 -0
  239. package/lib/module/theme/fonts.js.map +1 -0
  240. package/lib/module/theme/nativeTokenRegistry.js +40 -0
  241. package/lib/module/theme/nativeTokenRegistry.js.map +1 -0
  242. package/lib/module/theme/systemTheme.js +31 -0
  243. package/lib/module/theme/systemTheme.js.map +1 -0
  244. package/lib/module/theme/useNativeBreakpoint.js +24 -0
  245. package/lib/module/theme/useNativeBreakpoint.js.map +1 -0
  246. package/lib/module/theme/useNativeTokens.js +67 -0
  247. package/lib/module/theme/useNativeTokens.js.map +1 -0
  248. package/lib/typescript/commonjs/a11y/announcement.d.ts +26 -0
  249. package/lib/typescript/commonjs/a11y/announcement.d.ts.map +1 -0
  250. package/lib/typescript/commonjs/a11y/useLiveRegion.d.ts +17 -0
  251. package/lib/typescript/commonjs/a11y/useLiveRegion.d.ts.map +1 -0
  252. package/lib/typescript/commonjs/adapters/cssStringAdapter.d.ts +119 -0
  253. package/lib/typescript/commonjs/adapters/cssStringAdapter.d.ts.map +1 -0
  254. package/lib/typescript/commonjs/adapters/optionalGradient.d.ts +32 -0
  255. package/lib/typescript/commonjs/adapters/optionalGradient.d.ts.map +1 -0
  256. package/lib/typescript/commonjs/adapters/surfaceStyle.d.ts +75 -0
  257. package/lib/typescript/commonjs/adapters/surfaceStyle.d.ts.map +1 -0
  258. package/lib/typescript/commonjs/components/Alert/Alert.d.ts +14 -0
  259. package/lib/typescript/commonjs/components/Alert/Alert.d.ts.map +1 -0
  260. package/lib/typescript/commonjs/components/Alert/AlertActions.d.ts +13 -0
  261. package/lib/typescript/commonjs/components/Alert/AlertActions.d.ts.map +1 -0
  262. package/lib/typescript/commonjs/components/Alert/AlertClose.d.ts +22 -0
  263. package/lib/typescript/commonjs/components/Alert/AlertClose.d.ts.map +1 -0
  264. package/lib/typescript/commonjs/components/Alert/AlertText.d.ts +19 -0
  265. package/lib/typescript/commonjs/components/Alert/AlertText.d.ts.map +1 -0
  266. package/lib/typescript/commonjs/components/Alert/alert.tokens.d.ts +17 -0
  267. package/lib/typescript/commonjs/components/Alert/alert.tokens.d.ts.map +1 -0
  268. package/lib/typescript/commonjs/components/Alert/alert.types.d.ts +70 -0
  269. package/lib/typescript/commonjs/components/Alert/alert.types.d.ts.map +1 -0
  270. package/lib/typescript/commonjs/components/Alert/alert.utils.d.ts +58 -0
  271. package/lib/typescript/commonjs/components/Alert/alert.utils.d.ts.map +1 -0
  272. package/lib/typescript/commonjs/components/Alert/index.d.ts +7 -0
  273. package/lib/typescript/commonjs/components/Alert/index.d.ts.map +1 -0
  274. package/lib/typescript/commonjs/components/Button/Button.d.ts +22 -0
  275. package/lib/typescript/commonjs/components/Button/Button.d.ts.map +1 -0
  276. package/lib/typescript/commonjs/components/Button/button.types.d.ts +37 -0
  277. package/lib/typescript/commonjs/components/Button/button.types.d.ts.map +1 -0
  278. package/lib/typescript/commonjs/components/Button/button.utils.d.ts +98 -0
  279. package/lib/typescript/commonjs/components/Button/button.utils.d.ts.map +1 -0
  280. package/lib/typescript/commonjs/components/Button/index.d.ts +5 -0
  281. package/lib/typescript/commonjs/components/Button/index.d.ts.map +1 -0
  282. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +7 -0
  283. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts.map +1 -0
  284. package/lib/typescript/commonjs/components/Skeleton/index.d.ts +3 -0
  285. package/lib/typescript/commonjs/components/Skeleton/index.d.ts.map +1 -0
  286. package/lib/typescript/commonjs/components/Skeleton/skeleton.types.d.ts +25 -0
  287. package/lib/typescript/commonjs/components/Skeleton/skeleton.types.d.ts.map +1 -0
  288. package/lib/typescript/commonjs/components/Skeleton/skeleton.utils.d.ts +21 -0
  289. package/lib/typescript/commonjs/components/Skeleton/skeleton.utils.d.ts.map +1 -0
  290. package/lib/typescript/commonjs/components/Tag/Tag.d.ts +21 -0
  291. package/lib/typescript/commonjs/components/Tag/Tag.d.ts.map +1 -0
  292. package/lib/typescript/commonjs/components/Tag/index.d.ts +4 -0
  293. package/lib/typescript/commonjs/components/Tag/index.d.ts.map +1 -0
  294. package/lib/typescript/commonjs/components/Tag/tag.types.d.ts +56 -0
  295. package/lib/typescript/commonjs/components/Tag/tag.types.d.ts.map +1 -0
  296. package/lib/typescript/commonjs/components/Tag/tag.utils.d.ts +41 -0
  297. package/lib/typescript/commonjs/components/Tag/tag.utils.d.ts.map +1 -0
  298. package/lib/typescript/commonjs/components/TextInput/TextInput.d.ts +33 -0
  299. package/lib/typescript/commonjs/components/TextInput/TextInput.d.ts.map +1 -0
  300. package/lib/typescript/commonjs/components/TextInput/index.d.ts +3 -0
  301. package/lib/typescript/commonjs/components/TextInput/index.d.ts.map +1 -0
  302. package/lib/typescript/commonjs/components/TextInput/textInput.types.d.ts +45 -0
  303. package/lib/typescript/commonjs/components/TextInput/textInput.types.d.ts.map +1 -0
  304. package/lib/typescript/commonjs/components/TextInput/textInput.utils.d.ts +35 -0
  305. package/lib/typescript/commonjs/components/TextInput/textInput.utils.d.ts.map +1 -0
  306. package/lib/typescript/commonjs/components/shared/field/FieldFooter.d.ts +22 -0
  307. package/lib/typescript/commonjs/components/shared/field/FieldFooter.d.ts.map +1 -0
  308. package/lib/typescript/commonjs/components/shared/field/FieldLabels.d.ts +27 -0
  309. package/lib/typescript/commonjs/components/shared/field/FieldLabels.d.ts.map +1 -0
  310. package/lib/typescript/commonjs/components/shared/field/fieldState.d.ts +23 -0
  311. package/lib/typescript/commonjs/components/shared/field/fieldState.d.ts.map +1 -0
  312. package/lib/typescript/commonjs/components/shared/group.d.ts +50 -0
  313. package/lib/typescript/commonjs/components/shared/group.d.ts.map +1 -0
  314. package/lib/typescript/commonjs/index.d.ts +74 -0
  315. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  316. package/lib/typescript/commonjs/motion/motion.d.ts +121 -0
  317. package/lib/typescript/commonjs/motion/motion.d.ts.map +1 -0
  318. package/lib/typescript/commonjs/motion/useReduceMotion.d.ts +14 -0
  319. package/lib/typescript/commonjs/motion/useReduceMotion.d.ts.map +1 -0
  320. package/lib/typescript/commonjs/overlay/portal.d.ts +20 -0
  321. package/lib/typescript/commonjs/overlay/portal.d.ts.map +1 -0
  322. package/lib/typescript/commonjs/overlay/positioning.d.ts +65 -0
  323. package/lib/typescript/commonjs/overlay/positioning.d.ts.map +1 -0
  324. package/lib/typescript/commonjs/overlay/safeAreaInsets.d.ts +19 -0
  325. package/lib/typescript/commonjs/overlay/safeAreaInsets.d.ts.map +1 -0
  326. package/lib/typescript/commonjs/overlay/sheet/BottomSheet.d.ts +56 -0
  327. package/lib/typescript/commonjs/overlay/sheet/BottomSheet.d.ts.map +1 -0
  328. package/lib/typescript/commonjs/overlay/sheet/sheetMath.d.ts +32 -0
  329. package/lib/typescript/commonjs/overlay/sheet/sheetMath.d.ts.map +1 -0
  330. package/lib/typescript/commonjs/overlay/toast/ToastOutlet.d.ts +17 -0
  331. package/lib/typescript/commonjs/overlay/toast/ToastOutlet.d.ts.map +1 -0
  332. package/lib/typescript/commonjs/overlay/toast/toastStore.d.ts +45 -0
  333. package/lib/typescript/commonjs/overlay/toast/toastStore.d.ts.map +1 -0
  334. package/lib/typescript/commonjs/overlay/useAnchoredPosition.d.ts +40 -0
  335. package/lib/typescript/commonjs/overlay/useAnchoredPosition.d.ts.map +1 -0
  336. package/lib/typescript/commonjs/package.json +1 -0
  337. package/lib/typescript/commonjs/primitives/Block.d.ts +37 -0
  338. package/lib/typescript/commonjs/primitives/Block.d.ts.map +1 -0
  339. package/lib/typescript/commonjs/primitives/Pressable.d.ts +135 -0
  340. package/lib/typescript/commonjs/primitives/Pressable.d.ts.map +1 -0
  341. package/lib/typescript/commonjs/primitives/PrimitiveInput.d.ts +42 -0
  342. package/lib/typescript/commonjs/primitives/PrimitiveInput.d.ts.map +1 -0
  343. package/lib/typescript/commonjs/primitives/Separator.d.ts +28 -0
  344. package/lib/typescript/commonjs/primitives/Separator.d.ts.map +1 -0
  345. package/lib/typescript/commonjs/primitives/Slot.d.ts +48 -0
  346. package/lib/typescript/commonjs/primitives/Slot.d.ts.map +1 -0
  347. package/lib/typescript/commonjs/primitives/Text.d.ts +50 -0
  348. package/lib/typescript/commonjs/primitives/Text.d.ts.map +1 -0
  349. package/lib/typescript/commonjs/primitives/pressFeedback.d.ts +39 -0
  350. package/lib/typescript/commonjs/primitives/pressFeedback.d.ts.map +1 -0
  351. package/lib/typescript/commonjs/primitives/textStyle.d.ts +13 -0
  352. package/lib/typescript/commonjs/primitives/textStyle.d.ts.map +1 -0
  353. package/lib/typescript/commonjs/primitives/tintSlot.d.ts +10 -0
  354. package/lib/typescript/commonjs/primitives/tintSlot.d.ts.map +1 -0
  355. package/lib/typescript/commonjs/primitives/touchTarget.d.ts +43 -0
  356. package/lib/typescript/commonjs/primitives/touchTarget.d.ts.map +1 -0
  357. package/lib/typescript/commonjs/theme/BlendNativeProvider.d.ts +69 -0
  358. package/lib/typescript/commonjs/theme/BlendNativeProvider.d.ts.map +1 -0
  359. package/lib/typescript/commonjs/theme/breakpoint.d.ts +27 -0
  360. package/lib/typescript/commonjs/theme/breakpoint.d.ts.map +1 -0
  361. package/lib/typescript/commonjs/theme/fonts.d.ts +34 -0
  362. package/lib/typescript/commonjs/theme/fonts.d.ts.map +1 -0
  363. package/lib/typescript/commonjs/theme/nativeTokenRegistry.d.ts +34 -0
  364. package/lib/typescript/commonjs/theme/nativeTokenRegistry.d.ts.map +1 -0
  365. package/lib/typescript/commonjs/theme/systemTheme.d.ts +25 -0
  366. package/lib/typescript/commonjs/theme/systemTheme.d.ts.map +1 -0
  367. package/lib/typescript/commonjs/theme/useNativeBreakpoint.d.ts +17 -0
  368. package/lib/typescript/commonjs/theme/useNativeBreakpoint.d.ts.map +1 -0
  369. package/lib/typescript/commonjs/theme/useNativeTokens.d.ts +4 -0
  370. package/lib/typescript/commonjs/theme/useNativeTokens.d.ts.map +1 -0
  371. package/lib/typescript/module/a11y/announcement.d.ts +26 -0
  372. package/lib/typescript/module/a11y/announcement.d.ts.map +1 -0
  373. package/lib/typescript/module/a11y/useLiveRegion.d.ts +17 -0
  374. package/lib/typescript/module/a11y/useLiveRegion.d.ts.map +1 -0
  375. package/lib/typescript/module/adapters/cssStringAdapter.d.ts +119 -0
  376. package/lib/typescript/module/adapters/cssStringAdapter.d.ts.map +1 -0
  377. package/lib/typescript/module/adapters/optionalGradient.d.ts +32 -0
  378. package/lib/typescript/module/adapters/optionalGradient.d.ts.map +1 -0
  379. package/lib/typescript/module/adapters/surfaceStyle.d.ts +75 -0
  380. package/lib/typescript/module/adapters/surfaceStyle.d.ts.map +1 -0
  381. package/lib/typescript/module/components/Alert/Alert.d.ts +14 -0
  382. package/lib/typescript/module/components/Alert/Alert.d.ts.map +1 -0
  383. package/lib/typescript/module/components/Alert/AlertActions.d.ts +13 -0
  384. package/lib/typescript/module/components/Alert/AlertActions.d.ts.map +1 -0
  385. package/lib/typescript/module/components/Alert/AlertClose.d.ts +22 -0
  386. package/lib/typescript/module/components/Alert/AlertClose.d.ts.map +1 -0
  387. package/lib/typescript/module/components/Alert/AlertText.d.ts +19 -0
  388. package/lib/typescript/module/components/Alert/AlertText.d.ts.map +1 -0
  389. package/lib/typescript/module/components/Alert/alert.tokens.d.ts +17 -0
  390. package/lib/typescript/module/components/Alert/alert.tokens.d.ts.map +1 -0
  391. package/lib/typescript/module/components/Alert/alert.types.d.ts +70 -0
  392. package/lib/typescript/module/components/Alert/alert.types.d.ts.map +1 -0
  393. package/lib/typescript/module/components/Alert/alert.utils.d.ts +58 -0
  394. package/lib/typescript/module/components/Alert/alert.utils.d.ts.map +1 -0
  395. package/lib/typescript/module/components/Alert/index.d.ts +7 -0
  396. package/lib/typescript/module/components/Alert/index.d.ts.map +1 -0
  397. package/lib/typescript/module/components/Button/Button.d.ts +22 -0
  398. package/lib/typescript/module/components/Button/Button.d.ts.map +1 -0
  399. package/lib/typescript/module/components/Button/button.types.d.ts +37 -0
  400. package/lib/typescript/module/components/Button/button.types.d.ts.map +1 -0
  401. package/lib/typescript/module/components/Button/button.utils.d.ts +98 -0
  402. package/lib/typescript/module/components/Button/button.utils.d.ts.map +1 -0
  403. package/lib/typescript/module/components/Button/index.d.ts +5 -0
  404. package/lib/typescript/module/components/Button/index.d.ts.map +1 -0
  405. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +7 -0
  406. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts.map +1 -0
  407. package/lib/typescript/module/components/Skeleton/index.d.ts +3 -0
  408. package/lib/typescript/module/components/Skeleton/index.d.ts.map +1 -0
  409. package/lib/typescript/module/components/Skeleton/skeleton.types.d.ts +25 -0
  410. package/lib/typescript/module/components/Skeleton/skeleton.types.d.ts.map +1 -0
  411. package/lib/typescript/module/components/Skeleton/skeleton.utils.d.ts +21 -0
  412. package/lib/typescript/module/components/Skeleton/skeleton.utils.d.ts.map +1 -0
  413. package/lib/typescript/module/components/Tag/Tag.d.ts +21 -0
  414. package/lib/typescript/module/components/Tag/Tag.d.ts.map +1 -0
  415. package/lib/typescript/module/components/Tag/index.d.ts +4 -0
  416. package/lib/typescript/module/components/Tag/index.d.ts.map +1 -0
  417. package/lib/typescript/module/components/Tag/tag.types.d.ts +56 -0
  418. package/lib/typescript/module/components/Tag/tag.types.d.ts.map +1 -0
  419. package/lib/typescript/module/components/Tag/tag.utils.d.ts +41 -0
  420. package/lib/typescript/module/components/Tag/tag.utils.d.ts.map +1 -0
  421. package/lib/typescript/module/components/TextInput/TextInput.d.ts +33 -0
  422. package/lib/typescript/module/components/TextInput/TextInput.d.ts.map +1 -0
  423. package/lib/typescript/module/components/TextInput/index.d.ts +3 -0
  424. package/lib/typescript/module/components/TextInput/index.d.ts.map +1 -0
  425. package/lib/typescript/module/components/TextInput/textInput.types.d.ts +45 -0
  426. package/lib/typescript/module/components/TextInput/textInput.types.d.ts.map +1 -0
  427. package/lib/typescript/module/components/TextInput/textInput.utils.d.ts +35 -0
  428. package/lib/typescript/module/components/TextInput/textInput.utils.d.ts.map +1 -0
  429. package/lib/typescript/module/components/shared/field/FieldFooter.d.ts +22 -0
  430. package/lib/typescript/module/components/shared/field/FieldFooter.d.ts.map +1 -0
  431. package/lib/typescript/module/components/shared/field/FieldLabels.d.ts +27 -0
  432. package/lib/typescript/module/components/shared/field/FieldLabels.d.ts.map +1 -0
  433. package/lib/typescript/module/components/shared/field/fieldState.d.ts +23 -0
  434. package/lib/typescript/module/components/shared/field/fieldState.d.ts.map +1 -0
  435. package/lib/typescript/module/components/shared/group.d.ts +50 -0
  436. package/lib/typescript/module/components/shared/group.d.ts.map +1 -0
  437. package/lib/typescript/module/index.d.ts +74 -0
  438. package/lib/typescript/module/index.d.ts.map +1 -0
  439. package/lib/typescript/module/motion/motion.d.ts +121 -0
  440. package/lib/typescript/module/motion/motion.d.ts.map +1 -0
  441. package/lib/typescript/module/motion/useReduceMotion.d.ts +14 -0
  442. package/lib/typescript/module/motion/useReduceMotion.d.ts.map +1 -0
  443. package/lib/typescript/module/overlay/portal.d.ts +20 -0
  444. package/lib/typescript/module/overlay/portal.d.ts.map +1 -0
  445. package/lib/typescript/module/overlay/positioning.d.ts +65 -0
  446. package/lib/typescript/module/overlay/positioning.d.ts.map +1 -0
  447. package/lib/typescript/module/overlay/safeAreaInsets.d.ts +19 -0
  448. package/lib/typescript/module/overlay/safeAreaInsets.d.ts.map +1 -0
  449. package/lib/typescript/module/overlay/sheet/BottomSheet.d.ts +56 -0
  450. package/lib/typescript/module/overlay/sheet/BottomSheet.d.ts.map +1 -0
  451. package/lib/typescript/module/overlay/sheet/sheetMath.d.ts +32 -0
  452. package/lib/typescript/module/overlay/sheet/sheetMath.d.ts.map +1 -0
  453. package/lib/typescript/module/overlay/toast/ToastOutlet.d.ts +17 -0
  454. package/lib/typescript/module/overlay/toast/ToastOutlet.d.ts.map +1 -0
  455. package/lib/typescript/module/overlay/toast/toastStore.d.ts +45 -0
  456. package/lib/typescript/module/overlay/toast/toastStore.d.ts.map +1 -0
  457. package/lib/typescript/module/overlay/useAnchoredPosition.d.ts +40 -0
  458. package/lib/typescript/module/overlay/useAnchoredPosition.d.ts.map +1 -0
  459. package/lib/typescript/module/package.json +1 -0
  460. package/lib/typescript/module/primitives/Block.d.ts +37 -0
  461. package/lib/typescript/module/primitives/Block.d.ts.map +1 -0
  462. package/lib/typescript/module/primitives/Pressable.d.ts +135 -0
  463. package/lib/typescript/module/primitives/Pressable.d.ts.map +1 -0
  464. package/lib/typescript/module/primitives/PrimitiveInput.d.ts +42 -0
  465. package/lib/typescript/module/primitives/PrimitiveInput.d.ts.map +1 -0
  466. package/lib/typescript/module/primitives/Separator.d.ts +28 -0
  467. package/lib/typescript/module/primitives/Separator.d.ts.map +1 -0
  468. package/lib/typescript/module/primitives/Slot.d.ts +48 -0
  469. package/lib/typescript/module/primitives/Slot.d.ts.map +1 -0
  470. package/lib/typescript/module/primitives/Text.d.ts +50 -0
  471. package/lib/typescript/module/primitives/Text.d.ts.map +1 -0
  472. package/lib/typescript/module/primitives/pressFeedback.d.ts +39 -0
  473. package/lib/typescript/module/primitives/pressFeedback.d.ts.map +1 -0
  474. package/lib/typescript/module/primitives/textStyle.d.ts +13 -0
  475. package/lib/typescript/module/primitives/textStyle.d.ts.map +1 -0
  476. package/lib/typescript/module/primitives/tintSlot.d.ts +10 -0
  477. package/lib/typescript/module/primitives/tintSlot.d.ts.map +1 -0
  478. package/lib/typescript/module/primitives/touchTarget.d.ts +43 -0
  479. package/lib/typescript/module/primitives/touchTarget.d.ts.map +1 -0
  480. package/lib/typescript/module/theme/BlendNativeProvider.d.ts +69 -0
  481. package/lib/typescript/module/theme/BlendNativeProvider.d.ts.map +1 -0
  482. package/lib/typescript/module/theme/breakpoint.d.ts +27 -0
  483. package/lib/typescript/module/theme/breakpoint.d.ts.map +1 -0
  484. package/lib/typescript/module/theme/fonts.d.ts +34 -0
  485. package/lib/typescript/module/theme/fonts.d.ts.map +1 -0
  486. package/lib/typescript/module/theme/nativeTokenRegistry.d.ts +34 -0
  487. package/lib/typescript/module/theme/nativeTokenRegistry.d.ts.map +1 -0
  488. package/lib/typescript/module/theme/systemTheme.d.ts +25 -0
  489. package/lib/typescript/module/theme/systemTheme.d.ts.map +1 -0
  490. package/lib/typescript/module/theme/useNativeBreakpoint.d.ts +17 -0
  491. package/lib/typescript/module/theme/useNativeBreakpoint.d.ts.map +1 -0
  492. package/lib/typescript/module/theme/useNativeTokens.d.ts +4 -0
  493. package/lib/typescript/module/theme/useNativeTokens.d.ts.map +1 -0
  494. package/package.json +137 -0
  495. package/src/a11y/announcement.ts +41 -0
  496. package/src/a11y/useLiveRegion.ts +36 -0
  497. package/src/adapters/cssStringAdapter.ts +403 -0
  498. package/src/adapters/optionalGradient.ts +39 -0
  499. package/src/adapters/surfaceStyle.ts +209 -0
  500. package/src/components/Alert/Alert.tsx +167 -0
  501. package/src/components/Alert/AlertActions.tsx +98 -0
  502. package/src/components/Alert/AlertClose.tsx +53 -0
  503. package/src/components/Alert/AlertText.tsx +58 -0
  504. package/src/components/Alert/alert.tokens.ts +24 -0
  505. package/src/components/Alert/alert.types.ts +81 -0
  506. package/src/components/Alert/alert.utils.ts +94 -0
  507. package/src/components/Alert/index.ts +21 -0
  508. package/src/components/Button/Button.tsx +180 -0
  509. package/src/components/Button/button.types.ts +44 -0
  510. package/src/components/Button/button.utils.ts +213 -0
  511. package/src/components/Button/index.ts +12 -0
  512. package/src/components/Skeleton/Skeleton.tsx +196 -0
  513. package/src/components/Skeleton/index.ts +2 -0
  514. package/src/components/Skeleton/skeleton.types.ts +28 -0
  515. package/src/components/Skeleton/skeleton.utils.ts +56 -0
  516. package/src/components/Tag/Tag.tsx +204 -0
  517. package/src/components/Tag/index.ts +7 -0
  518. package/src/components/Tag/tag.types.ts +63 -0
  519. package/src/components/Tag/tag.utils.ts +82 -0
  520. package/src/components/TextInput/TextInput.tsx +165 -0
  521. package/src/components/TextInput/index.ts +2 -0
  522. package/src/components/TextInput/textInput.types.ts +54 -0
  523. package/src/components/TextInput/textInput.utils.ts +68 -0
  524. package/src/components/shared/field/FieldFooter.tsx +66 -0
  525. package/src/components/shared/field/FieldLabels.tsx +86 -0
  526. package/src/components/shared/field/fieldState.ts +39 -0
  527. package/src/components/shared/group.ts +72 -0
  528. package/src/index.ts +144 -0
  529. package/src/motion/motion.ts +115 -0
  530. package/src/motion/useReduceMotion.ts +36 -0
  531. package/src/overlay/portal.tsx +122 -0
  532. package/src/overlay/positioning.ts +196 -0
  533. package/src/overlay/safeAreaInsets.ts +36 -0
  534. package/src/overlay/sheet/BottomSheet.tsx +276 -0
  535. package/src/overlay/sheet/sheetMath.ts +58 -0
  536. package/src/overlay/toast/ToastOutlet.tsx +127 -0
  537. package/src/overlay/toast/toastStore.ts +96 -0
  538. package/src/overlay/useAnchoredPosition.ts +92 -0
  539. package/src/primitives/Block.tsx +129 -0
  540. package/src/primitives/Pressable.tsx +528 -0
  541. package/src/primitives/PrimitiveInput.tsx +87 -0
  542. package/src/primitives/Separator.tsx +65 -0
  543. package/src/primitives/Slot.tsx +94 -0
  544. package/src/primitives/Text.tsx +98 -0
  545. package/src/primitives/pressFeedback.ts +78 -0
  546. package/src/primitives/textStyle.ts +24 -0
  547. package/src/primitives/tintSlot.ts +44 -0
  548. package/src/primitives/touchTarget.ts +72 -0
  549. package/src/theme/BlendNativeProvider.tsx +147 -0
  550. package/src/theme/breakpoint.ts +38 -0
  551. package/src/theme/fonts.ts +63 -0
  552. package/src/theme/nativeTokenRegistry.ts +57 -0
  553. package/src/theme/systemTheme.ts +34 -0
  554. package/src/theme/useNativeBreakpoint.ts +27 -0
  555. package/src/theme/useNativeTokens.ts +99 -0
@@ -0,0 +1,122 @@
1
+ import React, {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useId,
7
+ useMemo,
8
+ useState,
9
+ } from 'react'
10
+ import { StyleSheet, View } from 'react-native'
11
+
12
+ /**
13
+ * Portal — layered rendering above the app's content.
14
+ *
15
+ * The native replacement for web's `createPortal`/Radix `Portal`: overlay
16
+ * components (modal, menu, popover, tooltip, snackbar) mount their surface
17
+ * through `<Portal>` and it renders in an absolute-fill layer that
18
+ * `BlendNativeProvider` places *after* the app's children, so it paints on
19
+ * top regardless of where in the tree the overlay was opened.
20
+ *
21
+ * Layers stack in mount order — the overlay opened last paints on top,
22
+ * which matches how web portals appended to `document.body` behave.
23
+ *
24
+ * The provider must sit at a screen-filling root (the usual place for a
25
+ * theme provider): the layers are absolutely positioned siblings of the
26
+ * app's children, so they cover exactly what the provider's parent covers.
27
+ *
28
+ * With no provider mounted, `<Portal>` renders its children in place — an
29
+ * overlay degrades to inline rendering rather than disappearing.
30
+ */
31
+
32
+ type PortalNode = { key: string; node: React.ReactNode }
33
+
34
+ type PortalRegistry = {
35
+ mount: (key: string, node: React.ReactNode) => void
36
+ unmount: (key: string) => void
37
+ }
38
+
39
+ const PortalRegistryContext = createContext<PortalRegistry | null>(null)
40
+
41
+ let warnedNoProvider = false
42
+
43
+ export type PortalProps = { children?: React.ReactNode }
44
+
45
+ /** Renders `children` into the provider's overlay layer. */
46
+ export function Portal({ children }: PortalProps) {
47
+ const registry = useContext(PortalRegistryContext)
48
+ const key = useId()
49
+
50
+ useEffect(() => {
51
+ if (!registry) return
52
+ registry.mount(key, children)
53
+ return () => registry.unmount(key)
54
+ }, [registry, key, children])
55
+
56
+ // In an effect, not during render — warning inline would be a
57
+ // render-phase side effect (breaks under StrictMode double-render, the
58
+ // same class of bug Pressable's parse memoisation fixed).
59
+ useEffect(() => {
60
+ if (registry || warnedNoProvider) return
61
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
62
+ warnedNoProvider = true
63
+ console.warn(
64
+ '[blend-native] <Portal> used without BlendNativeProvider — ' +
65
+ 'rendering inline. Overlays will not layer above the app.'
66
+ )
67
+ }
68
+ }, [registry])
69
+
70
+ if (!registry) return <>{children}</>
71
+
72
+ return null
73
+ }
74
+
75
+ Portal.displayName = 'Portal'
76
+
77
+ /**
78
+ * Internal — wraps the app's children with the portal registry and renders
79
+ * the mounted layers after them. Used by `BlendNativeProvider`; not public.
80
+ */
81
+ export function PortalArea({ children }: { children?: React.ReactNode }) {
82
+ const [portals, setPortals] = useState<PortalNode[]>([])
83
+
84
+ const mount = useCallback((key: string, node: React.ReactNode) => {
85
+ setPortals((current) => {
86
+ const existing = current.findIndex((p) => p.key === key)
87
+ if (existing === -1) return [...current, { key, node }]
88
+ // Re-mount with new content keeps its layer position.
89
+ const next = current.slice()
90
+ next[existing] = { key, node }
91
+ return next
92
+ })
93
+ }, [])
94
+
95
+ const unmount = useCallback((key: string) => {
96
+ setPortals((current) => current.filter((p) => p.key !== key))
97
+ }, [])
98
+
99
+ const registry = useMemo<PortalRegistry>(
100
+ () => ({ mount, unmount }),
101
+ [mount, unmount]
102
+ )
103
+
104
+ return (
105
+ <PortalRegistryContext.Provider value={registry}>
106
+ {children}
107
+ {portals.map(({ key, node }) => (
108
+ <View
109
+ key={key}
110
+ style={StyleSheet.absoluteFill}
111
+ // Touches fall through empty layer area to the app;
112
+ // the overlay's own views still receive theirs.
113
+ pointerEvents="box-none"
114
+ >
115
+ {node}
116
+ </View>
117
+ ))}
118
+ </PortalRegistryContext.Provider>
119
+ )
120
+ }
121
+
122
+ PortalArea.displayName = 'PortalArea'
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Anchored-overlay positioning.
3
+ *
4
+ * The native replacement for what Radix/floating-ui do on web: place a
5
+ * floating box (menu, popover, tooltip, select list) against an anchor
6
+ * rect, flipping to the opposite side when space runs out and clamping
7
+ * into the viewport.
8
+ *
9
+ * Pure and RN-free — rects in, a position out — so the whole placement
10
+ * matrix is unit-testable under vitest. `useAnchoredPosition` layers the
11
+ * measurement plumbing on top.
12
+ */
13
+
14
+ export type Rect = { x: number; y: number; width: number; height: number }
15
+ export type Size = { width: number; height: number }
16
+
17
+ /** Which side of the anchor the content prefers. */
18
+ export type Placement = 'top' | 'bottom' | 'left' | 'right'
19
+
20
+ /** Alignment along the anchor's other axis. */
21
+ export type Alignment = 'start' | 'center' | 'end'
22
+
23
+ export type AnchoredPositionInput = {
24
+ /** The anchor's rect in window coordinates (`measureInWindow`). */
25
+ anchor: Rect
26
+ /** The floating content's measured size. */
27
+ content: Size
28
+ /** The window size (`useWindowDimensions`). */
29
+ viewport: Size
30
+ placement?: Placement
31
+ alignment?: Alignment
32
+ /** Gap between anchor and content, in points. */
33
+ offset?: number
34
+ /** Minimum distance kept from every viewport edge, in points. */
35
+ viewportPadding?: number
36
+ }
37
+
38
+ export type AnchoredPosition = {
39
+ x: number
40
+ y: number
41
+ /** The placement actually used, after any flip. */
42
+ placement: Placement
43
+ /**
44
+ * Space available for the content on the resolved side, after padding.
45
+ * Callers cap scrollable content (menus, select lists) with these so a
46
+ * long list scrolls instead of overflowing the screen.
47
+ */
48
+ maxHeight: number
49
+ maxWidth: number
50
+ }
51
+
52
+ const opposite: Record<Placement, Placement> = {
53
+ top: 'bottom',
54
+ bottom: 'top',
55
+ left: 'right',
56
+ right: 'left',
57
+ }
58
+
59
+ /** Space between the anchor and the viewport edge on one side. */
60
+ function spaceOn(
61
+ side: Placement,
62
+ anchor: Rect,
63
+ viewport: Size,
64
+ offset: number,
65
+ padding: number
66
+ ): number {
67
+ switch (side) {
68
+ case 'top':
69
+ return anchor.y - offset - padding
70
+ case 'bottom':
71
+ return (
72
+ viewport.height - (anchor.y + anchor.height) - offset - padding
73
+ )
74
+ case 'left':
75
+ return anchor.x - offset - padding
76
+ case 'right':
77
+ return viewport.width - (anchor.x + anchor.width) - offset - padding
78
+ }
79
+ }
80
+
81
+ const clamp = (value: number, min: number, max: number) =>
82
+ // A viewport smaller than the padding produces min > max; the lower
83
+ // bound wins so content pins to the leading edge instead of NaN-ing.
84
+ Math.max(min, Math.min(value, Math.max(min, max)))
85
+
86
+ /**
87
+ * Compute where to place floating content against an anchor.
88
+ *
89
+ * - **Flip**: when the preferred side cannot fit the content but the
90
+ * opposite side can fit more of it, the placement flips.
91
+ * - **Clamp**: the cross-axis position shifts to keep the content inside
92
+ * the viewport padding (matching floating-ui's `shift`).
93
+ * - **Cap**: `maxHeight`/`maxWidth` report the space actually available on
94
+ * the resolved side, so scrollable content can cap itself.
95
+ */
96
+ export function computeAnchoredPosition(
97
+ input: AnchoredPositionInput
98
+ ): AnchoredPosition {
99
+ const {
100
+ anchor,
101
+ content,
102
+ viewport,
103
+ placement: preferred = 'bottom',
104
+ alignment = 'start',
105
+ offset = 8,
106
+ viewportPadding = 8,
107
+ } = input
108
+
109
+ const preferredSpace = spaceOn(
110
+ preferred,
111
+ anchor,
112
+ viewport,
113
+ offset,
114
+ viewportPadding
115
+ )
116
+ const isVertical = preferred === 'top' || preferred === 'bottom'
117
+ const needed = isVertical ? content.height : content.width
118
+
119
+ let placement = preferred
120
+ if (needed > preferredSpace) {
121
+ const other = spaceOn(
122
+ opposite[preferred],
123
+ anchor,
124
+ viewport,
125
+ offset,
126
+ viewportPadding
127
+ )
128
+ if (other > preferredSpace) placement = opposite[preferred]
129
+ }
130
+
131
+ // ---- Main axis ------------------------------------------------------
132
+ let x = 0
133
+ let y = 0
134
+ switch (placement) {
135
+ case 'top':
136
+ y = anchor.y - offset - content.height
137
+ break
138
+ case 'bottom':
139
+ y = anchor.y + anchor.height + offset
140
+ break
141
+ case 'left':
142
+ x = anchor.x - offset - content.width
143
+ break
144
+ case 'right':
145
+ x = anchor.x + anchor.width + offset
146
+ break
147
+ }
148
+
149
+ // ---- Cross axis -----------------------------------------------------
150
+ const alignAlong = (
151
+ anchorStart: number,
152
+ anchorLength: number,
153
+ contentLength: number
154
+ ) => {
155
+ if (alignment === 'start') return anchorStart
156
+ if (alignment === 'end')
157
+ return anchorStart + anchorLength - contentLength
158
+ return anchorStart + (anchorLength - contentLength) / 2
159
+ }
160
+
161
+ if (placement === 'top' || placement === 'bottom') {
162
+ x = alignAlong(anchor.x, anchor.width, content.width)
163
+ } else {
164
+ y = alignAlong(anchor.y, anchor.height, content.height)
165
+ }
166
+
167
+ // ---- Keep inside the viewport ---------------------------------------
168
+ x = clamp(
169
+ x,
170
+ viewportPadding,
171
+ viewport.width - viewportPadding - content.width
172
+ )
173
+ y = clamp(
174
+ y,
175
+ viewportPadding,
176
+ viewport.height - viewportPadding - content.height
177
+ )
178
+
179
+ const available = spaceOn(
180
+ placement,
181
+ anchor,
182
+ viewport,
183
+ offset,
184
+ viewportPadding
185
+ )
186
+ const maxHeight =
187
+ placement === 'top' || placement === 'bottom'
188
+ ? Math.max(0, available)
189
+ : Math.max(0, viewport.height - 2 * viewportPadding)
190
+ const maxWidth =
191
+ placement === 'left' || placement === 'right'
192
+ ? Math.max(0, available)
193
+ : Math.max(0, viewport.width - 2 * viewportPadding)
194
+
195
+ return { x, y, placement, maxHeight, maxWidth }
196
+ }
@@ -0,0 +1,36 @@
1
+ import React, { createContext } from 'react'
2
+
3
+ /**
4
+ * Optional `react-native-safe-area-context` integration, shared by every
5
+ * overlay that must respect the home indicator or notch (BottomSheet, the
6
+ * toast outlet).
7
+ *
8
+ * `useContext` needs *a* context unconditionally, so when the optional peer
9
+ * is absent — or its provider is not mounted — a null-valued fallback
10
+ * stands in and insets resolve to zero. Same probe pattern as
11
+ * expo-linear-gradient.
12
+ */
13
+
14
+ export type EdgeInsets = {
15
+ top: number
16
+ bottom: number
17
+ left: number
18
+ right: number
19
+ }
20
+
21
+ const FallbackInsetsContext = createContext<EdgeInsets | null>(null)
22
+
23
+ export let SafeAreaInsetsContext: React.Context<EdgeInsets | null> =
24
+ FallbackInsetsContext
25
+ try {
26
+ if (typeof require === 'function') {
27
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
28
+ const safeArea = require('react-native-safe-area-context') as {
29
+ SafeAreaInsetsContext?: React.Context<EdgeInsets | null>
30
+ }
31
+ SafeAreaInsetsContext =
32
+ safeArea.SafeAreaInsetsContext ?? FallbackInsetsContext
33
+ }
34
+ } catch {
35
+ SafeAreaInsetsContext = FallbackInsetsContext
36
+ }
@@ -0,0 +1,276 @@
1
+ import React, { useCallback, useContext, useEffect, useState } from 'react'
2
+ import {
3
+ BackHandler,
4
+ Pressable,
5
+ StyleSheet,
6
+ useWindowDimensions,
7
+ View,
8
+ type LayoutChangeEvent,
9
+ type ViewStyle,
10
+ } from 'react-native'
11
+ import Animated, {
12
+ Easing,
13
+ runOnJS,
14
+ useAnimatedStyle,
15
+ useSharedValue,
16
+ withSpring,
17
+ withTiming,
18
+ } from 'react-native-reanimated'
19
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler'
20
+ import { Portal } from '../portal'
21
+ import { SafeAreaInsetsContext } from '../safeAreaInsets'
22
+ import { MOTION_DURATION, MOTION_EASING } from '../../motion/motion'
23
+ import { useReduceMotion } from '../../motion/useReduceMotion'
24
+ import {
25
+ clampSheetDrag,
26
+ resolveSheetMaxHeight,
27
+ shouldDismissSheet,
28
+ SHEET_MAX_HEIGHT_FRACTION,
29
+ } from './sheetMath'
30
+
31
+ /**
32
+ * BottomSheet — the gesture-driven sheet foundation.
33
+ *
34
+ * The native replacement for `vaul` and the phone presentation web already
35
+ * prescribes in its Mobile* variants (mobileModalV2, MobileSingleSelectV2,
36
+ * MobilePopoverV2): DrawerV2 and the phone modes of Select/Menu/Modal
37
+ * compose this primitive and pass their token values in — the sheet itself
38
+ * carries structure and physics, not design decisions, which is why its
39
+ * colour props have plain defaults instead of token lookups.
40
+ *
41
+ * Controlled: `open` drives it; every dismiss route (drag, backdrop, the
42
+ * Android back button) calls `onClose` and the owner flips `open` — the
43
+ * exit animation runs, then the sheet unmounts from the portal layer.
44
+ *
45
+ * Requirements: `react-native-reanimated` and `react-native-gesture-handler`
46
+ * (required peers), and a `GestureHandlerRootView` at the app root — apps
47
+ * using react-navigation already have one. `react-native-safe-area-context`
48
+ * is optional: with it (and its provider) mounted, the sheet pads itself
49
+ * past the home indicator; without it the bottom inset is 0.
50
+ *
51
+ * Reduce-motion: the slide collapses to a fade (`useReduceMotion`).
52
+ */
53
+
54
+ export type BottomSheetProps = {
55
+ /** Whether the sheet is presented. */
56
+ open: boolean
57
+ /** Called whenever the sheet asks to close; the owner flips `open`. */
58
+ onClose: () => void
59
+ children?: React.ReactNode
60
+ /** Cap on sheet height as a fraction of the window. Default 0.9. */
61
+ maxHeightFraction?: number
62
+ /** Backdrop fill. Defaults to 50% black. */
63
+ backdropColor?: string
64
+ /** Sheet surface colour. Component layers pass their token value. */
65
+ backgroundColor?: string
66
+ /** Radius of the two top corners. */
67
+ topRadius?: number
68
+ /** Show the drag handle. Default true. */
69
+ showHandle?: boolean
70
+ handleColor?: string
71
+ /** Allow drag-down to dismiss. Default true. */
72
+ dragToDismiss?: boolean
73
+ /** Dismiss when the backdrop is pressed. Default true. */
74
+ dismissOnBackdropPress?: boolean
75
+ accessibilityLabel?: string
76
+ testID?: string
77
+ /** Style escape hatch for the sheet surface. */
78
+ style?: ViewStyle
79
+ }
80
+
81
+ const ENTER = {
82
+ duration: MOTION_DURATION.slow,
83
+ easing: Easing.bezier(...MOTION_EASING.decelerate),
84
+ }
85
+ const EXIT = {
86
+ duration: MOTION_DURATION.normal,
87
+ easing: Easing.bezier(...MOTION_EASING.accelerate),
88
+ }
89
+
90
+ export function BottomSheet({
91
+ open,
92
+ onClose,
93
+ children,
94
+ maxHeightFraction = SHEET_MAX_HEIGHT_FRACTION,
95
+ backdropColor = 'rgba(0, 0, 0, 0.5)',
96
+ backgroundColor = '#FFFFFF',
97
+ topRadius = 16,
98
+ showHandle = true,
99
+ handleColor = 'rgba(0, 0, 0, 0.2)',
100
+ dragToDismiss = true,
101
+ dismissOnBackdropPress = true,
102
+ accessibilityLabel,
103
+ testID,
104
+ style,
105
+ }: BottomSheetProps) {
106
+ // Mounted outlives `open` by one exit animation.
107
+ const [mounted, setMounted] = useState(open)
108
+ const progress = useSharedValue(0)
109
+ const dragY = useSharedValue(0)
110
+ const sheetHeight = useSharedValue(0)
111
+ const window = useWindowDimensions()
112
+ const insets = useContext(SafeAreaInsetsContext)
113
+ const reduceMotion = useReduceMotion()
114
+
115
+ const unmount = useCallback(() => setMounted(false), [])
116
+
117
+ useEffect(() => {
118
+ if (open) {
119
+ setMounted(true)
120
+ progress.value = withTiming(1, ENTER)
121
+ } else {
122
+ // Drag offset folds into the exit so a gesture-dismissed sheet
123
+ // continues downward from wherever the finger left it.
124
+ dragY.value = withTiming(0, EXIT)
125
+ progress.value = withTiming(0, EXIT, (finished) => {
126
+ if (finished) runOnJS(unmount)()
127
+ })
128
+ }
129
+ }, [open, progress, dragY, unmount])
130
+
131
+ // Android hardware back closes the sheet instead of the screen.
132
+ useEffect(() => {
133
+ if (!open) return
134
+ const subscription = BackHandler.addEventListener(
135
+ 'hardwareBackPress',
136
+ () => {
137
+ onClose()
138
+ return true
139
+ }
140
+ )
141
+ return () => subscription.remove()
142
+ }, [open, onClose])
143
+
144
+ const onSheetLayout = useCallback(
145
+ (event: LayoutChangeEvent) => {
146
+ sheetHeight.value = event.nativeEvent.layout.height
147
+ },
148
+ [sheetHeight]
149
+ )
150
+
151
+ const pan = Gesture.Pan()
152
+ .enabled(dragToDismiss)
153
+ .onChange((event) => {
154
+ dragY.value = clampSheetDrag(event.translationY)
155
+ })
156
+ .onEnd((event) => {
157
+ if (
158
+ shouldDismissSheet(
159
+ event.translationY,
160
+ event.velocityY,
161
+ sheetHeight.value
162
+ )
163
+ ) {
164
+ runOnJS(onClose)()
165
+ } else {
166
+ dragY.value = withSpring(0, { damping: 22, stiffness: 320 })
167
+ }
168
+ })
169
+
170
+ const windowHeight = window.height
171
+ const sheetStyle = useAnimatedStyle(() => {
172
+ if (reduceMotion) {
173
+ return {
174
+ opacity: progress.value,
175
+ transform: [{ translateY: dragY.value }],
176
+ }
177
+ }
178
+ // Until the first layout lands, the full window height keeps the
179
+ // sheet parked off-screen instead of flashing in place.
180
+ const height = sheetHeight.value || windowHeight
181
+ return {
182
+ opacity: 1,
183
+ transform: [
184
+ { translateY: (1 - progress.value) * height + dragY.value },
185
+ ],
186
+ }
187
+ }, [reduceMotion, windowHeight])
188
+
189
+ const backdropStyle = useAnimatedStyle(() => ({
190
+ opacity: progress.value,
191
+ }))
192
+
193
+ if (!mounted) return null
194
+
195
+ const maxHeight = resolveSheetMaxHeight(
196
+ windowHeight,
197
+ insets?.top ?? 0,
198
+ maxHeightFraction
199
+ )
200
+
201
+ return (
202
+ <Portal>
203
+ <Animated.View
204
+ style={[
205
+ StyleSheet.absoluteFill,
206
+ { backgroundColor: backdropColor },
207
+ backdropStyle,
208
+ ]}
209
+ testID={testID ? `${testID}-backdrop` : undefined}
210
+ // The sheet is the modal surface; VoiceOver skips the
211
+ // backdrop (it could not reach it past
212
+ // accessibilityViewIsModal anyway).
213
+ accessible={false}
214
+ importantForAccessibility="no-hide-descendants"
215
+ >
216
+ <Pressable
217
+ style={StyleSheet.absoluteFill}
218
+ onPress={dismissOnBackdropPress ? onClose : undefined}
219
+ />
220
+ </Animated.View>
221
+
222
+ <GestureDetector gesture={pan}>
223
+ <Animated.View
224
+ onLayout={onSheetLayout}
225
+ accessibilityViewIsModal
226
+ accessibilityLabel={accessibilityLabel}
227
+ testID={testID}
228
+ style={[
229
+ styles.sheet,
230
+ {
231
+ maxHeight,
232
+ backgroundColor,
233
+ borderTopLeftRadius: topRadius,
234
+ borderTopRightRadius: topRadius,
235
+ paddingBottom: insets?.bottom ?? 0,
236
+ },
237
+ sheetStyle,
238
+ style,
239
+ ]}
240
+ >
241
+ {showHandle ? (
242
+ <View
243
+ style={[
244
+ styles.handle,
245
+ { backgroundColor: handleColor },
246
+ ]}
247
+ />
248
+ ) : null}
249
+ {children}
250
+ </Animated.View>
251
+ </GestureDetector>
252
+ </Portal>
253
+ )
254
+ }
255
+
256
+ BottomSheet.displayName = 'BottomSheet'
257
+
258
+ const styles = StyleSheet.create({
259
+ sheet: {
260
+ position: 'absolute',
261
+ left: 0,
262
+ right: 0,
263
+ bottom: 0,
264
+ overflow: 'hidden',
265
+ },
266
+ handle: {
267
+ alignSelf: 'center',
268
+ width: 36,
269
+ height: 4,
270
+ borderRadius: 2,
271
+ marginTop: 8,
272
+ marginBottom: 4,
273
+ },
274
+ })
275
+
276
+ export default BottomSheet
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Bottom-sheet gesture arithmetic.
3
+ *
4
+ * Pure and RN-free (the `theme/breakpoint.ts` pattern) so the dismiss
5
+ * decision — the part of a sheet that feels wrong when it is wrong — is
6
+ * unit-testable under vitest. `BottomSheet` wires these into the pan
7
+ * gesture; they also run as Reanimated worklets, so nothing here may close
8
+ * over module state.
9
+ */
10
+
11
+ /** Dragging past this fraction of the sheet's height dismisses on release. */
12
+ export const SHEET_DISMISS_FRACTION = 0.25
13
+
14
+ /** A downward fling at or above this velocity (pt/s) dismisses regardless. */
15
+ export const SHEET_DISMISS_VELOCITY = 800
16
+
17
+ /** Default cap: a sheet covers at most this fraction of the window. */
18
+ export const SHEET_MAX_HEIGHT_FRACTION = 0.9
19
+
20
+ /**
21
+ * The sheet follows the finger downward only — upward drag is pinned so the
22
+ * sheet feels anchored rather than lifting off its resting position.
23
+ */
24
+ export function clampSheetDrag(translationY: number): number {
25
+ 'worklet'
26
+ return Math.max(0, translationY)
27
+ }
28
+
29
+ /**
30
+ * Whether a released drag should dismiss the sheet: past the distance
31
+ * threshold, or a genuine downward fling. An upward fling never dismisses,
32
+ * whatever distance was covered first.
33
+ */
34
+ export function shouldDismissSheet(
35
+ translationY: number,
36
+ velocityY: number,
37
+ sheetHeight: number
38
+ ): boolean {
39
+ 'worklet'
40
+ if (velocityY <= -SHEET_DISMISS_VELOCITY) return false
41
+ if (velocityY >= SHEET_DISMISS_VELOCITY) return translationY > 0
42
+ return (
43
+ sheetHeight > 0 && translationY >= sheetHeight * SHEET_DISMISS_FRACTION
44
+ )
45
+ }
46
+
47
+ /**
48
+ * The tallest a sheet may grow: the capped fraction of the window, minus
49
+ * whatever top inset (status bar / notch) must stay visible above it.
50
+ */
51
+ export function resolveSheetMaxHeight(
52
+ windowHeight: number,
53
+ topInset: number = 0,
54
+ maxHeightFraction: number = SHEET_MAX_HEIGHT_FRACTION
55
+ ): number {
56
+ const capped = windowHeight * maxHeightFraction
57
+ return Math.max(0, Math.min(capped, windowHeight - topInset))
58
+ }