@ankhorage/surface 5.0.0 → 6.0.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 (313) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -3
  3. package/dist/components/field/Field.d.ts +1 -0
  4. package/dist/components/field/Field.d.ts.map +1 -1
  5. package/dist/components/field/Field.js +5 -4
  6. package/dist/components/field/Field.js.map +1 -1
  7. package/dist/components/list-item/ListItem.d.ts +1 -0
  8. package/dist/components/list-item/ListItem.d.ts.map +1 -1
  9. package/dist/components/list-item/ListItem.js +13 -12
  10. package/dist/components/list-item/ListItem.js.map +1 -1
  11. package/dist/components/switch/Switch.d.ts +1 -0
  12. package/dist/components/switch/Switch.d.ts.map +1 -1
  13. package/dist/components/switch/Switch.js +10 -13
  14. package/dist/components/switch/Switch.js.map +1 -1
  15. package/dist/{layout → core/responsive}/Show.d.ts +2 -1
  16. package/dist/core/responsive/Show.d.ts.map +1 -0
  17. package/dist/{layout → core/responsive}/Show.js +3 -1
  18. package/dist/core/responsive/Show.js.map +1 -0
  19. package/dist/core/responsive/index.d.ts +1 -0
  20. package/dist/core/responsive/index.d.ts.map +1 -1
  21. package/dist/core/responsive/index.js +1 -0
  22. package/dist/core/responsive/index.js.map +1 -1
  23. package/dist/features/app-bar/adapters/inbound/AppBar.d.ts +5 -0
  24. package/dist/features/app-bar/adapters/inbound/AppBar.d.ts.map +1 -0
  25. package/dist/features/app-bar/adapters/inbound/AppBar.js +40 -0
  26. package/dist/features/app-bar/adapters/inbound/AppBar.js.map +1 -0
  27. package/dist/features/app-bar/public.d.ts +3 -0
  28. package/dist/features/app-bar/public.d.ts.map +1 -0
  29. package/dist/features/app-bar/public.js +2 -0
  30. package/dist/features/app-bar/public.js.map +1 -0
  31. package/dist/features/badge/adapters/inbound/Badge.js +3 -3
  32. package/dist/features/badge/adapters/inbound/Badge.js.map +1 -1
  33. package/dist/features/button/adapters/inbound/Button.js +8 -8
  34. package/dist/features/button/adapters/inbound/Button.js.map +1 -1
  35. package/dist/features/button/adapters/inbound/IconButton.js +3 -3
  36. package/dist/features/button/adapters/inbound/IconButton.js.map +1 -1
  37. package/dist/features/form/checkbox/adapters/inbound/Checkbox.js +7 -7
  38. package/dist/features/form/checkbox/adapters/inbound/Checkbox.js.map +1 -1
  39. package/dist/features/form/radio/adapters/inbound/Radio.js +8 -8
  40. package/dist/features/form/radio/adapters/inbound/Radio.js.map +1 -1
  41. package/dist/features/layout/adapters/inbound/Divider.js +2 -2
  42. package/dist/features/layout/adapters/inbound/Divider.js.map +1 -1
  43. package/dist/features/layout/adapters/inbound/Grid.d.ts.map +1 -1
  44. package/dist/features/layout/adapters/inbound/Grid.js +7 -9
  45. package/dist/features/layout/adapters/inbound/Grid.js.map +1 -1
  46. package/dist/features/layout/adapters/inbound/ScrollView.d.ts +5 -0
  47. package/dist/features/layout/adapters/inbound/ScrollView.d.ts.map +1 -0
  48. package/dist/features/layout/adapters/inbound/ScrollView.js +69 -0
  49. package/dist/features/layout/adapters/inbound/ScrollView.js.map +1 -0
  50. package/dist/features/layout/adapters/inbound/View.d.ts +5 -0
  51. package/dist/features/layout/adapters/inbound/View.d.ts.map +1 -0
  52. package/dist/features/layout/adapters/inbound/View.js +17 -0
  53. package/dist/features/layout/adapters/inbound/View.js.map +1 -0
  54. package/dist/features/layout/public.d.ts +3 -4
  55. package/dist/features/layout/public.d.ts.map +1 -1
  56. package/dist/features/layout/public.js +2 -3
  57. package/dist/features/layout/public.js.map +1 -1
  58. package/dist/{components/modal → features/modal/adapters/inbound}/Modal.d.ts +2 -1
  59. package/dist/features/modal/adapters/inbound/Modal.d.ts.map +1 -0
  60. package/dist/features/modal/adapters/inbound/Modal.js +51 -0
  61. package/dist/features/modal/adapters/inbound/Modal.js.map +1 -0
  62. package/dist/features/modal/public.d.ts +3 -0
  63. package/dist/features/modal/public.d.ts.map +1 -0
  64. package/dist/features/modal/public.js +2 -0
  65. package/dist/features/modal/public.js.map +1 -0
  66. package/dist/features/popover-menu/adapters/inbound/PopoverMenu.d.ts.map +1 -1
  67. package/dist/features/popover-menu/adapters/inbound/PopoverMenu.js +11 -12
  68. package/dist/features/popover-menu/adapters/inbound/PopoverMenu.js.map +1 -1
  69. package/dist/features/surface/adapters/inbound/Surface.d.ts +1 -1
  70. package/dist/features/surface/adapters/inbound/Surface.d.ts.map +1 -1
  71. package/dist/features/surface/adapters/inbound/Surface.js +3 -3
  72. package/dist/features/surface/adapters/inbound/Surface.js.map +1 -1
  73. package/dist/features/tabs/adapters/inbound/Tab.d.ts +5 -0
  74. package/dist/features/tabs/adapters/inbound/Tab.d.ts.map +1 -0
  75. package/dist/features/tabs/adapters/inbound/Tab.js +33 -0
  76. package/dist/features/tabs/adapters/inbound/Tab.js.map +1 -0
  77. package/dist/features/tabs/adapters/inbound/TabList.d.ts +5 -0
  78. package/dist/features/tabs/adapters/inbound/TabList.d.ts.map +1 -0
  79. package/dist/features/tabs/adapters/inbound/TabList.js +40 -0
  80. package/dist/features/tabs/adapters/inbound/TabList.js.map +1 -0
  81. package/dist/features/tabs/adapters/inbound/TabPanel.d.ts +5 -0
  82. package/dist/features/tabs/adapters/inbound/TabPanel.d.ts.map +1 -0
  83. package/dist/features/tabs/adapters/inbound/TabPanel.js +14 -0
  84. package/dist/features/tabs/adapters/inbound/TabPanel.js.map +1 -0
  85. package/dist/features/tabs/adapters/inbound/Tabs.d.ts +5 -0
  86. package/dist/features/tabs/adapters/inbound/Tabs.d.ts.map +1 -0
  87. package/dist/features/tabs/adapters/inbound/Tabs.js +12 -0
  88. package/dist/features/tabs/adapters/inbound/Tabs.js.map +1 -0
  89. package/dist/features/tabs/composition/TabsContext.d.ts +4 -0
  90. package/dist/features/tabs/composition/TabsContext.d.ts.map +1 -0
  91. package/dist/features/tabs/composition/TabsContext.js +3 -0
  92. package/dist/features/tabs/composition/TabsContext.js.map +1 -0
  93. package/dist/features/tabs/composition/useTabRegistration.d.ts +7 -0
  94. package/dist/features/tabs/composition/useTabRegistration.d.ts.map +1 -0
  95. package/dist/features/tabs/composition/useTabRegistration.js +20 -0
  96. package/dist/features/tabs/composition/useTabRegistration.js.map +1 -0
  97. package/dist/features/tabs/composition/useTabsContext.d.ts +4 -0
  98. package/dist/features/tabs/composition/useTabsContext.d.ts.map +1 -0
  99. package/dist/{components/tabs/context.js → features/tabs/composition/useTabsContext.js} +4 -4
  100. package/dist/features/tabs/composition/useTabsContext.js.map +1 -0
  101. package/dist/features/tabs/composition/useTabsController.d.ts +4 -0
  102. package/dist/features/tabs/composition/useTabsController.d.ts.map +1 -0
  103. package/dist/features/tabs/composition/useTabsController.js +43 -0
  104. package/dist/features/tabs/composition/useTabsController.js.map +1 -0
  105. package/dist/features/tabs/public.d.ts +6 -0
  106. package/dist/features/tabs/public.d.ts.map +1 -0
  107. package/dist/features/tabs/public.js +5 -0
  108. package/dist/features/tabs/public.js.map +1 -0
  109. package/dist/features/tabs/utils/resolveNextTabValue.d.ts +4 -0
  110. package/dist/features/tabs/utils/resolveNextTabValue.d.ts.map +1 -0
  111. package/dist/{components/tabs/navigation.js → features/tabs/utils/resolveNextTabValue.js} +10 -13
  112. package/dist/features/tabs/utils/resolveNextTabValue.js.map +1 -0
  113. package/dist/features/tabs/utils/resolveTabElementId.d.ts +3 -0
  114. package/dist/features/tabs/utils/resolveTabElementId.d.ts.map +1 -0
  115. package/dist/features/tabs/utils/resolveTabElementId.js +10 -0
  116. package/dist/features/tabs/utils/resolveTabElementId.js.map +1 -0
  117. package/dist/features/toast/adapters/inbound/Toast.js +5 -5
  118. package/dist/features/toast/adapters/inbound/Toast.js.map +1 -1
  119. package/dist/features/toast/adapters/inbound/ToastProvider.js +3 -3
  120. package/dist/features/toast/adapters/inbound/ToastProvider.js.map +1 -1
  121. package/dist/index.d.ts +8 -7
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +4 -4
  124. package/dist/index.js.map +1 -1
  125. package/dist/primitives/button-base/ButtonBase.d.ts +1 -0
  126. package/dist/primitives/button-base/ButtonBase.d.ts.map +1 -1
  127. package/dist/primitives/button-base/ButtonBase.js +6 -5
  128. package/dist/primitives/button-base/ButtonBase.js.map +1 -1
  129. package/dist/primitives/button-base/types.d.ts +2 -2
  130. package/dist/primitives/button-base/types.d.ts.map +1 -1
  131. package/dist/primitives/button-base/types.js.map +1 -1
  132. package/dist/types/app-bar.d.ts +12 -0
  133. package/dist/types/app-bar.d.ts.map +1 -0
  134. package/dist/types/app-bar.js +2 -0
  135. package/dist/types/app-bar.js.map +1 -0
  136. package/dist/types/layout.d.ts +15 -17
  137. package/dist/types/layout.d.ts.map +1 -1
  138. package/dist/types/layout.js.map +1 -1
  139. package/dist/{components/modal/types.d.ts → types/modal.d.ts} +2 -2
  140. package/dist/types/modal.d.ts.map +1 -0
  141. package/dist/types/modal.js +2 -0
  142. package/dist/types/modal.js.map +1 -0
  143. package/dist/types/surface.d.ts +2 -2
  144. package/dist/types/surface.d.ts.map +1 -1
  145. package/dist/types/surface.js.map +1 -1
  146. package/dist/types/tabs.d.ts +43 -0
  147. package/dist/types/tabs.d.ts.map +1 -0
  148. package/dist/types/tabs.js +2 -0
  149. package/dist/types/tabs.js.map +1 -0
  150. package/dist/utils/resolveViewStyles.d.ts +7 -0
  151. package/dist/utils/resolveViewStyles.d.ts.map +1 -0
  152. package/dist/utils/{resolveBoxStyles.js → resolveViewStyles.js} +11 -4
  153. package/dist/utils/resolveViewStyles.js.map +1 -0
  154. package/package.json +1 -1
  155. package/src/components/field/Field.tsx +5 -4
  156. package/src/components/list-item/ListItem.tsx +17 -13
  157. package/src/components/switch/Switch.tsx +10 -15
  158. package/src/{layout → core/responsive}/Show.tsx +4 -1
  159. package/src/core/responsive/index.ts +1 -0
  160. package/src/features/app-bar/adapters/inbound/AppBar.tsx +69 -0
  161. package/src/features/app-bar/public.ts +2 -0
  162. package/src/features/badge/adapters/inbound/Badge.tsx +3 -3
  163. package/src/features/button/adapters/inbound/Button.tsx +8 -8
  164. package/src/features/button/adapters/inbound/IconButton.tsx +3 -3
  165. package/src/features/form/checkbox/adapters/inbound/Checkbox.tsx +7 -7
  166. package/src/features/form/radio/adapters/inbound/Radio.tsx +8 -8
  167. package/src/features/layout/adapters/inbound/Divider.tsx +2 -2
  168. package/src/features/layout/adapters/inbound/Grid.tsx +12 -14
  169. package/src/features/layout/adapters/inbound/ScrollView.tsx +102 -0
  170. package/src/features/layout/adapters/inbound/{Box.tsx → View.tsx} +9 -9
  171. package/src/features/layout/public.ts +3 -10
  172. package/src/features/modal/adapters/inbound/Modal.tsx +77 -0
  173. package/src/features/modal/public.ts +2 -0
  174. package/src/features/popover-menu/adapters/inbound/PopoverMenu.tsx +11 -14
  175. package/src/features/surface/adapters/inbound/Surface.tsx +3 -3
  176. package/src/features/tabs/adapters/inbound/Tab.tsx +67 -0
  177. package/src/features/tabs/adapters/inbound/TabList.tsx +47 -0
  178. package/src/{components/tabs → features/tabs/adapters/inbound}/TabPanel.tsx +6 -10
  179. package/src/features/tabs/adapters/inbound/Tabs.tsx +17 -0
  180. package/src/features/tabs/composition/TabsContext.tsx +5 -0
  181. package/src/features/tabs/composition/useTabRegistration.ts +27 -0
  182. package/src/features/tabs/composition/useTabsContext.ts +13 -0
  183. package/src/features/tabs/composition/useTabsController.ts +55 -0
  184. package/src/features/tabs/public.ts +5 -0
  185. package/src/{components/tabs/navigation.test.ts → features/tabs/utils/resolveNextTabValue.test.ts} +2 -2
  186. package/src/features/tabs/utils/resolveNextTabValue.ts +24 -0
  187. package/src/features/tabs/utils/resolveTabElementId.test.ts +19 -0
  188. package/src/features/tabs/utils/resolveTabElementId.ts +14 -0
  189. package/src/features/toast/adapters/inbound/Toast.tsx +5 -5
  190. package/src/features/toast/adapters/inbound/ToastProvider.tsx +3 -3
  191. package/src/index.test.ts +14 -38
  192. package/src/index.ts +8 -13
  193. package/src/primitives/button-base/ButtonBase.tsx +6 -8
  194. package/src/primitives/button-base/types.ts +2 -2
  195. package/src/types/app-bar.ts +13 -0
  196. package/src/types/layout.ts +25 -20
  197. package/src/{components/modal/types.ts → types/modal.ts} +1 -1
  198. package/src/types/surface.ts +2 -2
  199. package/src/types/tabs.ts +51 -0
  200. package/src/utils/resolveViewStyles.test.ts +71 -0
  201. package/src/utils/{resolveBoxStyles.ts → resolveViewStyles.ts} +16 -9
  202. package/src/webAcceptance.test.tsx +8 -9
  203. package/dist/components/modal/Modal.d.ts.map +0 -1
  204. package/dist/components/modal/Modal.js +0 -59
  205. package/dist/components/modal/Modal.js.map +0 -1
  206. package/dist/components/modal/index.d.ts +0 -3
  207. package/dist/components/modal/index.d.ts.map +0 -1
  208. package/dist/components/modal/index.js +0 -2
  209. package/dist/components/modal/index.js.map +0 -1
  210. package/dist/components/modal/types.d.ts.map +0 -1
  211. package/dist/components/modal/types.js +0 -2
  212. package/dist/components/modal/types.js.map +0 -1
  213. package/dist/components/tabs/Tab.d.ts +0 -4
  214. package/dist/components/tabs/Tab.d.ts.map +0 -1
  215. package/dist/components/tabs/Tab.js +0 -48
  216. package/dist/components/tabs/Tab.js.map +0 -1
  217. package/dist/components/tabs/TabList.d.ts +0 -4
  218. package/dist/components/tabs/TabList.d.ts.map +0 -1
  219. package/dist/components/tabs/TabList.js +0 -37
  220. package/dist/components/tabs/TabList.js.map +0 -1
  221. package/dist/components/tabs/TabPanel.d.ts +0 -4
  222. package/dist/components/tabs/TabPanel.d.ts.map +0 -1
  223. package/dist/components/tabs/TabPanel.js +0 -16
  224. package/dist/components/tabs/TabPanel.js.map +0 -1
  225. package/dist/components/tabs/Tabs.d.ts +0 -4
  226. package/dist/components/tabs/Tabs.d.ts.map +0 -1
  227. package/dist/components/tabs/Tabs.js +0 -54
  228. package/dist/components/tabs/Tabs.js.map +0 -1
  229. package/dist/components/tabs/a11y.d.ts +0 -3
  230. package/dist/components/tabs/a11y.d.ts.map +0 -1
  231. package/dist/components/tabs/a11y.js +0 -13
  232. package/dist/components/tabs/a11y.js.map +0 -1
  233. package/dist/components/tabs/context.d.ts +0 -20
  234. package/dist/components/tabs/context.d.ts.map +0 -1
  235. package/dist/components/tabs/context.js.map +0 -1
  236. package/dist/components/tabs/index.d.ts +0 -6
  237. package/dist/components/tabs/index.d.ts.map +0 -1
  238. package/dist/components/tabs/index.js +0 -5
  239. package/dist/components/tabs/index.js.map +0 -1
  240. package/dist/components/tabs/navigation.d.ts +0 -3
  241. package/dist/components/tabs/navigation.d.ts.map +0 -1
  242. package/dist/components/tabs/navigation.js.map +0 -1
  243. package/dist/components/tabs/types.d.ts +0 -26
  244. package/dist/components/tabs/types.d.ts.map +0 -1
  245. package/dist/components/tabs/types.js +0 -2
  246. package/dist/components/tabs/types.js.map +0 -1
  247. package/dist/features/layout/adapters/inbound/Box.d.ts +0 -5
  248. package/dist/features/layout/adapters/inbound/Box.d.ts.map +0 -1
  249. package/dist/features/layout/adapters/inbound/Box.js +0 -17
  250. package/dist/features/layout/adapters/inbound/Box.js.map +0 -1
  251. package/dist/features/layout/adapters/inbound/Container.d.ts +0 -5
  252. package/dist/features/layout/adapters/inbound/Container.d.ts.map +0 -1
  253. package/dist/features/layout/adapters/inbound/Container.js +0 -28
  254. package/dist/features/layout/adapters/inbound/Container.js.map +0 -1
  255. package/dist/features/layout/adapters/inbound/Stack.d.ts +0 -5
  256. package/dist/features/layout/adapters/inbound/Stack.d.ts.map +0 -1
  257. package/dist/features/layout/adapters/inbound/Stack.js +0 -27
  258. package/dist/features/layout/adapters/inbound/Stack.js.map +0 -1
  259. package/dist/layout/AppBar.d.ts +0 -13
  260. package/dist/layout/AppBar.d.ts.map +0 -1
  261. package/dist/layout/AppBar.js +0 -30
  262. package/dist/layout/AppBar.js.map +0 -1
  263. package/dist/layout/Center.d.ts +0 -7
  264. package/dist/layout/Center.d.ts.map +0 -1
  265. package/dist/layout/Center.js +0 -12
  266. package/dist/layout/Center.js.map +0 -1
  267. package/dist/layout/Inline.d.ts +0 -5
  268. package/dist/layout/Inline.d.ts.map +0 -1
  269. package/dist/layout/Inline.js +0 -6
  270. package/dist/layout/Inline.js.map +0 -1
  271. package/dist/layout/ScrollArea.d.ts +0 -9
  272. package/dist/layout/ScrollArea.d.ts.map +0 -1
  273. package/dist/layout/ScrollArea.js +0 -52
  274. package/dist/layout/ScrollArea.js.map +0 -1
  275. package/dist/layout/Show.d.ts.map +0 -1
  276. package/dist/layout/Show.js.map +0 -1
  277. package/dist/layout/Spacer.d.ts +0 -9
  278. package/dist/layout/Spacer.d.ts.map +0 -1
  279. package/dist/layout/Spacer.js +0 -12
  280. package/dist/layout/Spacer.js.map +0 -1
  281. package/dist/layout/Template.d.ts +0 -18
  282. package/dist/layout/Template.d.ts.map +0 -1
  283. package/dist/layout/Template.js +0 -36
  284. package/dist/layout/Template.js.map +0 -1
  285. package/dist/layout/index.d.ts +0 -15
  286. package/dist/layout/index.d.ts.map +0 -1
  287. package/dist/layout/index.js +0 -8
  288. package/dist/layout/index.js.map +0 -1
  289. package/dist/utils/resolveBoxStyles.d.ts +0 -7
  290. package/dist/utils/resolveBoxStyles.d.ts.map +0 -1
  291. package/dist/utils/resolveBoxStyles.js.map +0 -1
  292. package/src/components/modal/Modal.tsx +0 -96
  293. package/src/components/modal/index.ts +0 -2
  294. package/src/components/tabs/Tab.tsx +0 -89
  295. package/src/components/tabs/TabList.tsx +0 -51
  296. package/src/components/tabs/Tabs.tsx +0 -67
  297. package/src/components/tabs/a11y.test.ts +0 -15
  298. package/src/components/tabs/a11y.ts +0 -15
  299. package/src/components/tabs/context.tsx +0 -31
  300. package/src/components/tabs/index.ts +0 -5
  301. package/src/components/tabs/navigation.ts +0 -32
  302. package/src/components/tabs/types.ts +0 -30
  303. package/src/features/layout/adapters/inbound/Container.tsx +0 -43
  304. package/src/features/layout/adapters/inbound/Stack.test.ts +0 -13
  305. package/src/features/layout/adapters/inbound/Stack.tsx +0 -44
  306. package/src/layout/AppBar.tsx +0 -60
  307. package/src/layout/Center.tsx +0 -22
  308. package/src/layout/Inline.tsx +0 -9
  309. package/src/layout/ScrollArea.tsx +0 -116
  310. package/src/layout/Spacer.tsx +0 -22
  311. package/src/layout/Template.tsx +0 -86
  312. package/src/layout/index.ts +0 -14
  313. package/src/utils/resolveBoxStyles.test.ts +0 -54
@@ -1,96 +0,0 @@
1
- import React from 'react';
2
- import { Pressable, View } from 'react-native';
3
-
4
- import { Surface } from '../../features/surface/public';
5
- import { FocusScope } from '../../internal/focus/FocusScope';
6
- import { Portal } from '../../internal/overlay/Portal';
7
- import { resolvePointerEvents } from '../../internal/resolvePointerEvents';
8
- import { resolveOverlayAnimation } from '../../internal/resolvers';
9
- import { Center } from '../../layout';
10
- import { useTheme } from '../../theme/ThemeContext';
11
- import type { ModalProps } from './types';
12
-
13
- const boxNonePointerEvents = resolvePointerEvents('box-none');
14
-
15
- export function Modal({
16
- visible,
17
- onDismiss,
18
- children,
19
- closeOnBackdrop = true,
20
- interactionPolicy = 'enabled',
21
- testID,
22
- }: ModalProps) {
23
- const { theme } = useTheme();
24
- const animation = resolveOverlayAnimation('modal');
25
- const passive = interactionPolicy === 'passive';
26
-
27
- if (!visible) {
28
- return null;
29
- }
30
-
31
- return (
32
- <Portal layer="modal" visible={visible}>
33
- <View
34
- {...boxNonePointerEvents.props}
35
- style={[
36
- boxNonePointerEvents.style,
37
- {
38
- bottom: 0,
39
- left: 0,
40
- position: 'absolute',
41
- right: 0,
42
- top: 0,
43
- },
44
- ]}
45
- >
46
- <Pressable
47
- onPress={passive ? undefined : closeOnBackdrop ? onDismiss : undefined}
48
- style={{
49
- backgroundColor: theme.semantics.neutral.text,
50
- bottom: 0,
51
- left: 0,
52
- opacity: animation.backdropOpacity,
53
- position: 'absolute',
54
- right: 0,
55
- top: 0,
56
- }}
57
- testID={testID ? `${testID}-backdrop` : undefined}
58
- />
59
- <FocusScope
60
- active={visible}
61
- onEscape={passive ? undefined : onDismiss}
62
- testID={testID ? `${testID}-focus` : undefined}
63
- >
64
- <Center
65
- p="l"
66
- style={{
67
- flex: 1,
68
- }}
69
- >
70
- <View
71
- accessible
72
- accessibilityViewIsModal
73
- style={{
74
- maxWidth: 560,
75
- width: '100%',
76
- }}
77
- >
78
- <Surface
79
- p="l"
80
- style={{
81
- shadowOpacity: 0.14,
82
- shadowRadius: 18,
83
- shadowOffset: { width: 0, height: 8 },
84
- }}
85
- testID={testID}
86
- variant="raised"
87
- >
88
- {children}
89
- </Surface>
90
- </View>
91
- </Center>
92
- </FocusScope>
93
- </View>
94
- </Portal>
95
- );
96
- }
@@ -1,2 +0,0 @@
1
- export { Modal } from './Modal';
2
- export type { ModalProps } from './types';
@@ -1,89 +0,0 @@
1
- import React from 'react';
2
- import { Pressable } from 'react-native';
3
-
4
- import { Box } from '../../features/layout/public';
5
- import { Text } from '../../features/typography/public';
6
- import { useTheme } from '../../theme/ThemeContext';
7
- import { useTabsContext } from './context';
8
- import type { TabProps } from './types';
9
-
10
- export function Tab({
11
- value,
12
- children,
13
- disabled = false,
14
- interactionPolicy = 'enabled',
15
- testID,
16
- }: TabProps) {
17
- const { theme } = useTheme();
18
- const {
19
- activeValue,
20
- getPanelId,
21
- getTabId,
22
- registerTab,
23
- setActiveValue,
24
- setFocusedValue,
25
- unregisterTab,
26
- } = useTabsContext();
27
- const pressableRef = React.useRef<React.ElementRef<typeof Pressable> | null>(null);
28
- const selected = activeValue === value;
29
- const tabId = getTabId(value);
30
- const panelId = getPanelId(value);
31
- const passive = interactionPolicy === 'passive';
32
-
33
- React.useEffect(() => {
34
- registerTab({
35
- disabled,
36
- focus: () => {
37
- const focusable = pressableRef.current as unknown as {
38
- focus?: (() => void) | undefined;
39
- } | null;
40
- focusable?.focus?.();
41
- },
42
- value,
43
- });
44
-
45
- return () => {
46
- unregisterTab(value);
47
- };
48
- }, [disabled, registerTab, unregisterTab, value]);
49
-
50
- return (
51
- <Pressable
52
- accessibilityLabel={undefined}
53
- accessibilityRole="tab"
54
- accessibilityState={{ disabled, selected }}
55
- nativeID={tabId}
56
- aria-controls={panelId}
57
- disabled={disabled}
58
- onFocus={() => setFocusedValue(value)}
59
- onBlur={() => setFocusedValue(undefined)}
60
- onPress={
61
- passive
62
- ? undefined
63
- : () => {
64
- if (!disabled) {
65
- setActiveValue(value);
66
- }
67
- }
68
- }
69
- ref={pressableRef}
70
- testID={testID}
71
- >
72
- <Box
73
- px="m"
74
- py="s"
75
- style={{
76
- borderBottomColor: selected
77
- ? theme.semantics.action.primary.base
78
- : theme.semantics.border.default,
79
- borderBottomWidth: 2,
80
- opacity: disabled ? 0.64 : 1,
81
- }}
82
- >
83
- <Text color={selected ? 'primary' : undefined} variant="label" weight="medium">
84
- {children}
85
- </Text>
86
- </Box>
87
- </Pressable>
88
- );
89
- }
@@ -1,51 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Box } from '../../features/layout/public';
4
- import { useFocusManager } from '../../internal/focus/useFocusManager';
5
- import { useTabsContext } from './context';
6
- import { resolveNextTabValue } from './navigation';
7
- import type { TabListProps } from './types';
8
-
9
- export function TabList({ children, testID }: TabListProps) {
10
- const { bindKeydown } = useFocusManager();
11
- const { focusedValue, setActiveValue, tabs } = useTabsContext();
12
-
13
- React.useEffect(() => {
14
- if (!focusedValue) {
15
- return undefined;
16
- }
17
-
18
- return bindKeydown((event) => {
19
- const nextValue =
20
- event.key === 'ArrowLeft' ||
21
- event.key === 'ArrowRight' ||
22
- event.key === 'ArrowUp' ||
23
- event.key === 'ArrowDown' ||
24
- event.key === 'Home' ||
25
- event.key === 'End'
26
- ? resolveNextTabValue(tabs, focusedValue, event.key)
27
- : undefined;
28
-
29
- if (!nextValue) {
30
- return;
31
- }
32
-
33
- event.preventDefault();
34
- const nextTab = tabs.find((tab) => tab.value === nextValue);
35
- nextTab?.focus();
36
- setActiveValue(nextValue);
37
- });
38
- }, [bindKeydown, focusedValue, setActiveValue, tabs]);
39
-
40
- return (
41
- <Box
42
- accessibilityRole="tablist"
43
- style={{
44
- flexDirection: 'row',
45
- }}
46
- testID={testID}
47
- >
48
- {children}
49
- </Box>
50
- );
51
- }
@@ -1,67 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Box } from '../../features/layout/public';
4
- import { useControllableState } from '../../internal/useControllableState';
5
- import { getTabId as resolveTabId, getTabPanelId as resolveTabPanelId } from './a11y';
6
- import { type TabRegistration, TabsContext } from './context';
7
- import type { TabsProps } from './types';
8
-
9
- export function Tabs({ children, value, defaultValue, onValueChange, testID }: TabsProps) {
10
- const [activeValue, setActiveValue] = useControllableState<string | undefined>({
11
- value,
12
- defaultValue,
13
- onChange: (nextValue) => {
14
- if (nextValue !== undefined) {
15
- onValueChange?.(nextValue);
16
- }
17
- },
18
- });
19
- const [focusedValue, setFocusedValue] = React.useState<string | undefined>(undefined);
20
- const [tabs, setTabs] = React.useState<TabRegistration[]>([]);
21
-
22
- const registerTab = React.useCallback((tab: TabRegistration) => {
23
- setTabs((current) => {
24
- return current.some((entry) => entry.value === tab.value)
25
- ? current.map((entry) => (entry.value === tab.value ? tab : entry))
26
- : [...current, tab];
27
- });
28
- }, []);
29
-
30
- const unregisterTab = React.useCallback((valueToRemove: string) => {
31
- setTabs((current) => current.filter((entry) => entry.value !== valueToRemove));
32
- }, []);
33
-
34
- React.useEffect(() => {
35
- if (activeValue !== undefined) {
36
- return;
37
- }
38
-
39
- const firstEnabledTab = tabs.find((entry) => !entry.disabled);
40
- if (firstEnabledTab) {
41
- setActiveValue(firstEnabledTab.value);
42
- }
43
- }, [activeValue, setActiveValue, tabs]);
44
-
45
- const contextValue = React.useMemo(
46
- () => ({
47
- activeValue,
48
- focusedValue,
49
- getPanelId: (tabValue: string) => resolveTabPanelId(testID, tabValue),
50
- getTabId: (tabValue: string) => resolveTabId(testID, tabValue),
51
- registerTab,
52
- setActiveValue: (nextValue: string) => {
53
- setActiveValue(nextValue);
54
- },
55
- setFocusedValue,
56
- tabs,
57
- unregisterTab,
58
- }),
59
- [activeValue, focusedValue, registerTab, setActiveValue, tabs, testID, unregisterTab],
60
- );
61
-
62
- return (
63
- <TabsContext value={contextValue}>
64
- <Box testID={testID}>{children}</Box>
65
- </TabsContext>
66
- );
67
- }
@@ -1,15 +0,0 @@
1
- import { describe, expect, it } from 'bun:test';
2
-
3
- import { getTabId, getTabPanelId } from './a11y';
4
-
5
- describe('tabs accessibility ids', () => {
6
- it('creates stable ids from tab values', () => {
7
- expect(getTabId(undefined, 'Account Settings')).toBe('tabs-tab-Account-Settings');
8
- expect(getTabPanelId(undefined, 'Account Settings')).toBe('tabs-panel-Account-Settings');
9
- });
10
-
11
- it('namespaces ids by tabs testID when provided', () => {
12
- expect(getTabId('settings', 'billing')).toBe('settings-tabs-tab-billing');
13
- expect(getTabPanelId('settings', 'billing')).toBe('settings-tabs-panel-billing');
14
- });
15
- });
@@ -1,15 +0,0 @@
1
- function sanitizeTabValue(value: string): string {
2
- return value.trim().replace(/[^a-zA-Z0-9_-]+/g, '-');
3
- }
4
-
5
- function createTabsIdBase(testID: string | undefined): string {
6
- return testID ? `${testID}-tabs` : 'tabs';
7
- }
8
-
9
- export function getTabId(testID: string | undefined, value: string): string {
10
- return `${createTabsIdBase(testID)}-tab-${sanitizeTabValue(value)}`;
11
- }
12
-
13
- export function getTabPanelId(testID: string | undefined, value: string): string {
14
- return `${createTabsIdBase(testID)}-panel-${sanitizeTabValue(value)}`;
15
- }
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
-
3
- export interface TabRegistration {
4
- disabled: boolean;
5
- focus: () => void;
6
- value: string;
7
- }
8
-
9
- export interface TabsContextValue {
10
- activeValue: string | undefined;
11
- focusedValue: string | undefined;
12
- getPanelId: (value: string) => string;
13
- getTabId: (value: string) => string;
14
- registerTab: (tab: TabRegistration) => void;
15
- setActiveValue: (value: string) => void;
16
- setFocusedValue: (value: string | undefined) => void;
17
- tabs: TabRegistration[];
18
- unregisterTab: (value: string) => void;
19
- }
20
-
21
- export const TabsContext = React.createContext<TabsContextValue | null>(null);
22
-
23
- export function useTabsContext(): TabsContextValue {
24
- const value = React.use(TabsContext);
25
-
26
- if (!value) {
27
- throw new Error('Tabs components must be used within <Tabs>.');
28
- }
29
-
30
- return value;
31
- }
@@ -1,5 +0,0 @@
1
- export { Tab } from './Tab';
2
- export { TabList } from './TabList';
3
- export { TabPanel } from './TabPanel';
4
- export { Tabs } from './Tabs';
5
- export type { TabListProps, TabPanelProps, TabProps, TabsProps } from './types';
@@ -1,32 +0,0 @@
1
- import type { TabRegistration } from './context';
2
-
3
- export function resolveNextTabValue(
4
- tabs: TabRegistration[],
5
- currentValue: string | undefined,
6
- key: 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'ArrowDown' | 'Home' | 'End',
7
- ): string | undefined {
8
- const enabledTabs = tabs.filter((tab) => !tab.disabled);
9
- if (enabledTabs.length === 0) {
10
- return undefined;
11
- }
12
-
13
- if (key === 'Home') {
14
- return enabledTabs[0]?.value;
15
- }
16
-
17
- if (key === 'End') {
18
- return enabledTabs[enabledTabs.length - 1]?.value;
19
- }
20
-
21
- const currentIndex = enabledTabs.findIndex((tab) => tab.value === currentValue);
22
- if (currentIndex === -1) {
23
- return enabledTabs[0]?.value;
24
- }
25
-
26
- const nextIndex =
27
- key === 'ArrowLeft' || key === 'ArrowUp'
28
- ? (currentIndex - 1 + enabledTabs.length) % enabledTabs.length
29
- : (currentIndex + 1) % enabledTabs.length;
30
-
31
- return enabledTabs[nextIndex]?.value;
32
- }
@@ -1,30 +0,0 @@
1
- import type React from 'react';
2
-
3
- import type { InteractionPolicy } from '../../interactionPolicy';
4
-
5
- export interface TabsProps {
6
- children?: React.ReactNode;
7
- value?: string;
8
- defaultValue?: string;
9
- onValueChange?: ((value: string) => void) | undefined;
10
- testID?: string;
11
- }
12
-
13
- export interface TabListProps {
14
- children?: React.ReactNode;
15
- testID?: string;
16
- }
17
-
18
- export interface TabProps {
19
- value: string;
20
- children?: React.ReactNode;
21
- disabled?: boolean;
22
- interactionPolicy?: InteractionPolicy;
23
- testID?: string;
24
- }
25
-
26
- export interface TabPanelProps {
27
- value: string;
28
- children?: React.ReactNode;
29
- testID?: string;
30
- }
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { StyleSheet, View, type ViewStyle } from 'react-native';
3
-
4
- import { resolveResponsive, useResponsiveRuntime } from '../../../../core/responsive';
5
- import { useTheme } from '../../../../theme/ThemeContext';
6
- import type { ContainerProps } from '../../../../types/layout';
7
- import { resolveSpacing } from '../../../../utils/resolveSpacing';
8
- import { Box } from './Box';
9
-
10
- /*** Centers responsive content inside a configurable maximum width. */
11
- export function Container({
12
- children,
13
- maxWidth = { base: Number.MAX_SAFE_INTEGER, lg: 1120 },
14
- px = { base: 16, md: 24, lg: 32 },
15
- ...props
16
- }: ContainerProps) {
17
- const { theme } = useTheme();
18
- const { breakpoint } = useResponsiveRuntime();
19
- const activeMaxWidth = resolveResponsive(maxWidth, breakpoint);
20
- const activePx = resolveSpacing(theme, resolveResponsive(px, breakpoint));
21
-
22
- return (
23
- <Box {...props} width="100%" style={[styles.fullWidth, props.style]}>
24
- <View style={resolveContainerStyle(activeMaxWidth, activePx)}>{children}</View>
25
- </Box>
26
- );
27
- }
28
-
29
- /*** Resolves centered responsive Container dimensions and padding. */
30
- function resolveContainerStyle(
31
- maxWidth: number | undefined,
32
- horizontalPadding: number | undefined,
33
- ): ViewStyle {
34
- return {
35
- alignSelf: 'center',
36
- maxWidth,
37
- paddingLeft: horizontalPadding,
38
- paddingRight: horizontalPadding,
39
- width: '100%',
40
- };
41
- }
42
-
43
- const styles = StyleSheet.create({ fullWidth: { width: '100%' } });
@@ -1,13 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
-
3
- import { describe, expect, it } from 'bun:test';
4
-
5
- describe('Stack layout contract', () => {
6
- it('keeps authored children as direct flex items and applies spacing through gap', async () => {
7
- const source = await readFile(new URL('./Stack.tsx', import.meta.url), 'utf8');
8
- expect(source).toContain('gap: activeGap');
9
- expect(source).toContain('{children}');
10
- expect(source).not.toContain("from 'react-native'");
11
- expect(source).not.toContain('React.Children');
12
- });
13
- });
@@ -1,44 +0,0 @@
1
- import type React from 'react';
2
-
3
- import { resolveResponsive, useResponsiveRuntime } from '../../../../core/responsive';
4
- import { useTheme } from '../../../../theme/ThemeContext';
5
- import type { StackProps } from '../../../../types/layout';
6
- import { resolveSpacing } from '../../../../utils/resolveSpacing';
7
- import { Box } from './Box';
8
-
9
- /*** Stacks authored children directly along a responsive flex direction. */
10
- export function Stack({
11
- children,
12
- direction = 'column',
13
- gap = 0,
14
- align,
15
- justify,
16
- wrap,
17
- ...props
18
- }: StackProps) {
19
- const { theme } = useTheme();
20
- const { breakpoint } = useResponsiveRuntime();
21
- const activeDirection = resolveResponsive(direction, breakpoint) ?? 'column';
22
- const activeGap = resolveSpacing(theme, resolveResponsive(gap, breakpoint)) ?? 0;
23
- const activeAlign = resolveResponsive(align, breakpoint);
24
- const activeJustify = resolveResponsive(justify, breakpoint);
25
- const activeWrap = resolveResponsive(wrap, breakpoint);
26
-
27
- return (
28
- <Box
29
- {...props}
30
- style={[
31
- {
32
- flexDirection: activeDirection,
33
- gap: activeGap,
34
- alignItems: activeAlign,
35
- justifyContent: activeJustify,
36
- flexWrap: activeWrap,
37
- },
38
- props.style,
39
- ]}
40
- >
41
- {children}
42
- </Box>
43
- );
44
- }
@@ -1,60 +0,0 @@
1
- import React from 'react';
2
- import { type StyleProp, View, type ViewStyle } from 'react-native';
3
- import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
4
-
5
- import { Box, type BoxProps, Divider } from '../features/layout/public';
6
- import { useTheme } from '../theme/ThemeContext';
7
-
8
- export interface AppBarProps extends Omit<BoxProps, 'children'> {
9
- leading?: React.ReactNode;
10
- trailing?: React.ReactNode;
11
- children?: React.ReactNode;
12
- safeAreaTop?: boolean;
13
- divider?: boolean;
14
- contentStyle?: StyleProp<ViewStyle>;
15
- }
16
-
17
- export function AppBar({
18
- leading,
19
- trailing,
20
- children,
21
- safeAreaTop = true,
22
- divider = false,
23
- contentStyle,
24
- bg,
25
- style,
26
- ...props
27
- }: AppBarProps) {
28
- const { theme } = useTheme();
29
- const insets = React.use(SafeAreaInsetsContext);
30
- const topInset = safeAreaTop ? (insets?.top ?? 0) : 0;
31
- const safeAreaStyle: ViewStyle | undefined =
32
- topInset === 0 ? undefined : { paddingTop: topInset };
33
-
34
- return (
35
- <Box {...props} bg={bg ?? theme.semantics.surface.default} style={style}>
36
- <View style={safeAreaStyle}>
37
- <View
38
- style={[
39
- {
40
- minHeight: 56,
41
- flexDirection: 'row',
42
- alignItems: 'center',
43
- paddingHorizontal: theme.spacing.m,
44
- },
45
- contentStyle,
46
- ]}
47
- >
48
- {leading ? (
49
- <View style={{ marginRight: theme.spacing.s, flexShrink: 0 }}>{leading}</View>
50
- ) : null}
51
- <View style={{ flex: 1, minWidth: 0 }}>{children}</View>
52
- {trailing ? (
53
- <View style={{ marginLeft: theme.spacing.s, flexShrink: 0 }}>{trailing}</View>
54
- ) : null}
55
- </View>
56
- {divider ? <Divider color={theme.semantics.neutral.divider} thickness={1} /> : null}
57
- </View>
58
- </Box>
59
- );
60
- }
@@ -1,22 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Box, type BoxProps } from '../features/layout/public';
4
-
5
- export interface CenterProps extends BoxProps {
6
- axis?: 'horizontal' | 'vertical' | 'both';
7
- }
8
-
9
- export function Center({ axis = 'both', style, ...props }: CenterProps) {
10
- return (
11
- <Box
12
- {...props}
13
- style={[
14
- {
15
- alignItems: axis === 'both' || axis === 'horizontal' ? 'center' : undefined,
16
- justifyContent: axis === 'both' || axis === 'vertical' ? 'center' : undefined,
17
- },
18
- style,
19
- ]}
20
- />
21
- );
22
- }
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Stack, type StackProps } from '../features/layout/public';
4
-
5
- export type InlineProps = Omit<StackProps, 'direction'>;
6
-
7
- export function Inline({ wrap = 'wrap', align = 'center', ...props }: InlineProps) {
8
- return <Stack {...props} align={align} direction="row" wrap={wrap} />;
9
- }