react-native-terra-ui 0.7.2 → 0.8.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 (252) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -1
  3. package/lib/module/components/avatar/Avatar.js +20 -20
  4. package/lib/module/components/avatar/Avatar.js.map +1 -1
  5. package/lib/module/components/button/Button.js +11 -11
  6. package/lib/module/components/button/Button.js.map +1 -1
  7. package/lib/module/components/chip/Chip.js +32 -32
  8. package/lib/module/components/chip/Chip.js.map +1 -1
  9. package/lib/module/components/empty-state/EmptyState.js +3 -3
  10. package/lib/module/components/empty-state/EmptyState.js.map +1 -1
  11. package/lib/module/components/header/variants/LargeTitleHeader/index.js +30 -32
  12. package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -1
  13. package/lib/module/components/header/variants/TitleHeader/index.js +26 -18
  14. package/lib/module/components/header/variants/TitleHeader/index.js.map +1 -1
  15. package/lib/module/components/icon/Icon.js +3 -3
  16. package/lib/module/components/page-indicator/hooks/use-page-indicator-colors.js +2 -2
  17. package/lib/module/components/screen/Screen.js +63 -34
  18. package/lib/module/components/screen/Screen.js.map +1 -1
  19. package/lib/module/components/screen/ScreenContext.js +28 -9
  20. package/lib/module/components/screen/ScreenContext.js.map +1 -1
  21. package/lib/module/components/screen/ScreenFlatList.js +4 -162
  22. package/lib/module/components/screen/ScreenFlatList.js.map +1 -1
  23. package/lib/module/components/screen/ScreenList.js +81 -97
  24. package/lib/module/components/screen/ScreenList.js.map +1 -1
  25. package/lib/module/components/screen/ScreenScrollView.js +64 -115
  26. package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
  27. package/lib/module/components/screen/hooks/use-screen-ref.js +18 -0
  28. package/lib/module/components/screen/hooks/use-screen-ref.js.map +1 -0
  29. package/lib/module/components/screen/hooks/use-screen-scroll-handler.js +19 -0
  30. package/lib/module/components/screen/hooks/use-screen-scroll-handler.js.map +1 -0
  31. package/lib/module/components/screen/index.js.map +1 -1
  32. package/lib/module/components/screen/parts/ScreenFrame.js +47 -0
  33. package/lib/module/components/screen/parts/ScreenFrame.js.map +1 -0
  34. package/lib/module/components/screen/parts/ScreenHeaderAppearance.js +43 -0
  35. package/lib/module/components/screen/parts/ScreenHeaderAppearance.js.map +1 -0
  36. package/lib/module/components/screen/parts/ScreenPlaceholder.js +11 -13
  37. package/lib/module/components/screen/parts/ScreenPlaceholder.js.map +1 -1
  38. package/lib/module/components/screen/parts/ScreenSafeArea.android.js +27 -0
  39. package/lib/module/components/screen/parts/ScreenSafeArea.android.js.map +1 -0
  40. package/lib/module/components/screen/parts/ScreenSafeArea.js +26 -0
  41. package/lib/module/components/screen/parts/ScreenSafeArea.js.map +1 -0
  42. package/lib/module/components/screen/utils.js +18 -9
  43. package/lib/module/components/screen/utils.js.map +1 -1
  44. package/lib/module/components/spinner/Spinner.js +2 -2
  45. package/lib/module/components/text/Text.js +1 -1
  46. package/lib/module/components/toast/Toast.js +13 -13
  47. package/lib/module/components/toast/Toast.js.map +1 -1
  48. package/lib/module/components/toolbar/Toolbar.js +2 -2
  49. package/lib/module/context/ThemeProvider.js +22 -39
  50. package/lib/module/context/ThemeProvider.js.map +1 -1
  51. package/lib/module/context/index.js +1 -1
  52. package/lib/module/context/index.js.map +1 -1
  53. package/lib/module/theme/breakpoints.js +1 -1
  54. package/lib/module/theme/define-config.js +21 -0
  55. package/lib/module/theme/define-config.js.map +1 -0
  56. package/lib/module/theme/diagnostics.js +13 -0
  57. package/lib/module/theme/diagnostics.js.map +1 -0
  58. package/lib/module/theme/errors.js +15 -0
  59. package/lib/module/theme/errors.js.map +1 -0
  60. package/lib/module/theme/index.js +7 -1
  61. package/lib/module/theme/index.js.map +1 -1
  62. package/lib/module/theme/legacy-tokens.js +119 -0
  63. package/lib/module/theme/legacy-tokens.js.map +1 -0
  64. package/lib/module/theme/registry.js +122 -130
  65. package/lib/module/theme/registry.js.map +1 -1
  66. package/lib/module/theme/resolve-config.js +346 -0
  67. package/lib/module/theme/resolve-config.js.map +1 -0
  68. package/lib/module/theme/runtime.js +57 -12
  69. package/lib/module/theme/runtime.js.map +1 -1
  70. package/lib/module/theme/screen-margin.js +6 -14
  71. package/lib/module/theme/screen-margin.js.map +1 -1
  72. package/lib/module/theme/screen-padding.js +17 -0
  73. package/lib/module/theme/screen-padding.js.map +1 -0
  74. package/lib/module/theme/selection-store.js +75 -0
  75. package/lib/module/theme/selection-store.js.map +1 -0
  76. package/lib/module/theme/theme.js +81 -36
  77. package/lib/module/theme/theme.js.map +1 -1
  78. package/lib/module/theme/tokens/canonical-color-keys.js +102 -0
  79. package/lib/module/theme/tokens/canonical-color-keys.js.map +1 -0
  80. package/lib/module/theme/tokens/dark.js +72 -88
  81. package/lib/module/theme/tokens/dark.js.map +1 -1
  82. package/lib/module/theme/tokens/light.js +69 -83
  83. package/lib/module/theme/tokens/light.js.map +1 -1
  84. package/lib/module/theme/tokens/primitives.js +14 -14
  85. package/lib/module/theme/tokens/primitives.js.map +1 -1
  86. package/lib/module/theme/tokens/validate.js +238 -0
  87. package/lib/module/theme/tokens/validate.js.map +1 -0
  88. package/lib/module/theme/unistyles-adapter.js +77 -0
  89. package/lib/module/theme/unistyles-adapter.js.map +1 -0
  90. package/lib/module/utils/accent-generator.js +476 -0
  91. package/lib/module/utils/accent-generator.js.map +1 -0
  92. package/lib/module/utils/accent-utils.js +52 -35
  93. package/lib/module/utils/accent-utils.js.map +1 -1
  94. package/lib/module/utils/color-utils.js +224 -7
  95. package/lib/module/utils/color-utils.js.map +1 -1
  96. package/lib/module/utils/deep-merge.js +1 -1
  97. package/lib/module/utils/deep-merge.js.map +1 -1
  98. package/lib/module/utils/resolve-theme-color.js +2 -2
  99. package/lib/typescript/src/components/chip/types.d.ts +1 -1
  100. package/lib/typescript/src/components/empty-state/EmptyState.d.ts +1 -1
  101. package/lib/typescript/src/components/empty-state/EmptyState.d.ts.map +1 -1
  102. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts +6 -5
  103. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -1
  104. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts +11 -5
  105. package/lib/typescript/src/components/header/variants/TitleHeader/index.d.ts.map +1 -1
  106. package/lib/typescript/src/components/icon/Icon.d.ts +2 -2
  107. package/lib/typescript/src/components/screen/Screen.d.ts +45 -16
  108. package/lib/typescript/src/components/screen/Screen.d.ts.map +1 -1
  109. package/lib/typescript/src/components/screen/ScreenContext.d.ts +42 -26
  110. package/lib/typescript/src/components/screen/ScreenContext.d.ts.map +1 -1
  111. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts +5 -46
  112. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -1
  113. package/lib/typescript/src/components/screen/ScreenList.d.ts +62 -50
  114. package/lib/typescript/src/components/screen/ScreenList.d.ts.map +1 -1
  115. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts +18 -58
  116. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
  117. package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts +5 -0
  118. package/lib/typescript/src/components/screen/hooks/use-screen-ref.d.ts.map +1 -0
  119. package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts +53 -0
  120. package/lib/typescript/src/components/screen/hooks/use-screen-scroll-handler.d.ts.map +1 -0
  121. package/lib/typescript/src/components/screen/index.d.ts +2 -2
  122. package/lib/typescript/src/components/screen/index.d.ts.map +1 -1
  123. package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts +6 -0
  124. package/lib/typescript/src/components/screen/parts/ScreenFrame.d.ts.map +1 -0
  125. package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts +21 -0
  126. package/lib/typescript/src/components/screen/parts/ScreenHeaderAppearance.d.ts.map +1 -0
  127. package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts +6 -8
  128. package/lib/typescript/src/components/screen/parts/ScreenPlaceholder.d.ts.map +1 -1
  129. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts +7 -0
  130. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.android.d.ts.map +1 -0
  131. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts +6 -0
  132. package/lib/typescript/src/components/screen/parts/ScreenSafeArea.d.ts.map +1 -0
  133. package/lib/typescript/src/components/screen/types.d.ts +27 -32
  134. package/lib/typescript/src/components/screen/types.d.ts.map +1 -1
  135. package/lib/typescript/src/components/screen/utils.d.ts +9 -8
  136. package/lib/typescript/src/components/screen/utils.d.ts.map +1 -1
  137. package/lib/typescript/src/components/text/Text.d.ts +1 -1
  138. package/lib/typescript/src/components/text/Text.d.ts.map +1 -1
  139. package/lib/typescript/src/components/toolbar/Toolbar.d.ts +2 -2
  140. package/lib/typescript/src/context/ThemeProvider.d.ts +29 -12
  141. package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
  142. package/lib/typescript/src/context/index.d.ts +1 -1
  143. package/lib/typescript/src/context/index.d.ts.map +1 -1
  144. package/lib/typescript/src/theme/breakpoints.d.ts +1 -1
  145. package/lib/typescript/src/theme/define-config.d.ts +23 -0
  146. package/lib/typescript/src/theme/define-config.d.ts.map +1 -0
  147. package/lib/typescript/src/theme/diagnostics.d.ts +4 -0
  148. package/lib/typescript/src/theme/diagnostics.d.ts.map +1 -0
  149. package/lib/typescript/src/theme/errors.d.ts +10 -0
  150. package/lib/typescript/src/theme/errors.d.ts.map +1 -0
  151. package/lib/typescript/src/theme/index.d.ts +10 -2
  152. package/lib/typescript/src/theme/index.d.ts.map +1 -1
  153. package/lib/typescript/src/theme/legacy-tokens.d.ts +187 -0
  154. package/lib/typescript/src/theme/legacy-tokens.d.ts.map +1 -0
  155. package/lib/typescript/src/theme/registry.d.ts +12 -17
  156. package/lib/typescript/src/theme/registry.d.ts.map +1 -1
  157. package/lib/typescript/src/theme/resolve-config.d.ts +99 -0
  158. package/lib/typescript/src/theme/resolve-config.d.ts.map +1 -0
  159. package/lib/typescript/src/theme/runtime.d.ts +25 -4
  160. package/lib/typescript/src/theme/runtime.d.ts.map +1 -1
  161. package/lib/typescript/src/theme/screen-margin.d.ts +6 -14
  162. package/lib/typescript/src/theme/screen-margin.d.ts.map +1 -1
  163. package/lib/typescript/src/theme/screen-padding.d.ts +15 -0
  164. package/lib/typescript/src/theme/screen-padding.d.ts.map +1 -0
  165. package/lib/typescript/src/theme/selection-store.d.ts +41 -0
  166. package/lib/typescript/src/theme/selection-store.d.ts.map +1 -0
  167. package/lib/typescript/src/theme/theme.d.ts +54 -1
  168. package/lib/typescript/src/theme/theme.d.ts.map +1 -1
  169. package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts +95 -0
  170. package/lib/typescript/src/theme/tokens/canonical-color-keys.d.ts.map +1 -0
  171. package/lib/typescript/src/theme/tokens/dark.d.ts +56 -63
  172. package/lib/typescript/src/theme/tokens/dark.d.ts.map +1 -1
  173. package/lib/typescript/src/theme/tokens/light.d.ts +56 -71
  174. package/lib/typescript/src/theme/tokens/light.d.ts.map +1 -1
  175. package/lib/typescript/src/theme/tokens/primitives.d.ts +11 -10
  176. package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -1
  177. package/lib/typescript/src/theme/tokens/validate.d.ts +34 -0
  178. package/lib/typescript/src/theme/tokens/validate.d.ts.map +1 -0
  179. package/lib/typescript/src/theme/types.d.ts +166 -86
  180. package/lib/typescript/src/theme/types.d.ts.map +1 -1
  181. package/lib/typescript/src/theme/unistyles-adapter.d.ts +33 -0
  182. package/lib/typescript/src/theme/unistyles-adapter.d.ts.map +1 -0
  183. package/lib/typescript/src/utils/accent-generator.d.ts +103 -0
  184. package/lib/typescript/src/utils/accent-generator.d.ts.map +1 -0
  185. package/lib/typescript/src/utils/accent-utils.d.ts +15 -2
  186. package/lib/typescript/src/utils/accent-utils.d.ts.map +1 -1
  187. package/lib/typescript/src/utils/color-utils.d.ts +59 -2
  188. package/lib/typescript/src/utils/color-utils.d.ts.map +1 -1
  189. package/lib/typescript/src/utils/deep-merge.d.ts +1 -0
  190. package/lib/typescript/src/utils/deep-merge.d.ts.map +1 -1
  191. package/lib/typescript/src/utils/resolve-theme-color.d.ts +2 -2
  192. package/package.json +1 -1
  193. package/src/components/avatar/Avatar.tsx +20 -20
  194. package/src/components/button/Button.tsx +11 -11
  195. package/src/components/chip/Chip.tsx +32 -32
  196. package/src/components/chip/types.ts +1 -1
  197. package/src/components/empty-state/EmptyState.tsx +4 -4
  198. package/src/components/header/variants/LargeTitleHeader/index.tsx +31 -30
  199. package/src/components/header/variants/TitleHeader/index.tsx +33 -22
  200. package/src/components/icon/Icon.tsx +4 -4
  201. package/src/components/page-indicator/hooks/use-page-indicator-colors.ts +2 -2
  202. package/src/components/screen/Screen.tsx +89 -43
  203. package/src/components/screen/ScreenContext.tsx +48 -28
  204. package/src/components/screen/ScreenFlatList.tsx +5 -191
  205. package/src/components/screen/ScreenList.tsx +197 -175
  206. package/src/components/screen/ScreenScrollView.tsx +92 -167
  207. package/src/components/screen/hooks/use-screen-ref.ts +24 -0
  208. package/src/components/screen/hooks/use-screen-scroll-handler.ts +31 -0
  209. package/src/components/screen/index.ts +8 -2
  210. package/src/components/screen/parts/ScreenFrame.tsx +49 -0
  211. package/src/components/screen/parts/ScreenHeaderAppearance.tsx +52 -0
  212. package/src/components/screen/parts/ScreenPlaceholder.tsx +16 -16
  213. package/src/components/screen/parts/ScreenSafeArea.android.tsx +22 -0
  214. package/src/components/screen/parts/ScreenSafeArea.tsx +20 -0
  215. package/src/components/screen/types.ts +29 -32
  216. package/src/components/screen/utils.ts +24 -11
  217. package/src/components/spinner/Spinner.tsx +2 -2
  218. package/src/components/text/Text.tsx +2 -2
  219. package/src/components/toast/Toast.tsx +13 -13
  220. package/src/components/toolbar/Toolbar.tsx +4 -4
  221. package/src/context/ThemeProvider.tsx +47 -51
  222. package/src/context/index.ts +1 -1
  223. package/src/theme/breakpoints.ts +1 -1
  224. package/src/theme/define-config.ts +27 -0
  225. package/src/theme/diagnostics.ts +11 -0
  226. package/src/theme/errors.ts +14 -0
  227. package/src/theme/index.ts +40 -1
  228. package/src/theme/legacy-tokens.ts +227 -0
  229. package/src/theme/registry.ts +119 -137
  230. package/src/theme/resolve-config.ts +406 -0
  231. package/src/theme/runtime.ts +52 -14
  232. package/src/theme/screen-margin.ts +6 -25
  233. package/src/theme/screen-padding.ts +26 -0
  234. package/src/theme/selection-store.ts +76 -0
  235. package/src/theme/theme.ts +104 -39
  236. package/src/theme/tokens/canonical-color-keys.ts +107 -0
  237. package/src/theme/tokens/dark.ts +91 -98
  238. package/src/theme/tokens/light.ts +88 -93
  239. package/src/theme/tokens/primitives.ts +14 -14
  240. package/src/theme/tokens/validate.ts +271 -0
  241. package/src/theme/types.ts +184 -95
  242. package/src/theme/unistyles-adapter.ts +75 -0
  243. package/src/utils/accent-generator.ts +530 -0
  244. package/src/utils/accent-utils.ts +66 -39
  245. package/src/utils/color-utils.ts +225 -8
  246. package/src/utils/deep-merge.ts +1 -1
  247. package/src/utils/resolve-theme-color.ts +2 -2
  248. package/lib/module/components/screen/parts/BottomSafeArea.js +0 -62
  249. package/lib/module/components/screen/parts/BottomSafeArea.js.map +0 -1
  250. package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts +0 -30
  251. package/lib/typescript/src/components/screen/parts/BottomSafeArea.d.ts.map +0 -1
  252. package/src/components/screen/parts/BottomSafeArea.tsx +0 -59
@@ -9,70 +9,78 @@ import Animated, {
9
9
  useSharedValue,
10
10
  } from "react-native-reanimated";
11
11
 
12
- import type { ScreenMargins } from "./types";
12
+ import type { ScreenContentPadding, ScreenSafeArea } from "./types";
13
13
 
14
+ /** Internal animated ref shared by the screen's primary scroll container. */
14
15
  export type ScreenScrollRef = AnimatedRef<Animated.ScrollView>;
15
16
 
16
- /** `PortalHost` name shared by `Screen.ScrollView` / `Screen.FlatList` and header variants that portal content into them. */
17
+ /** Local portal target for scrollable header content. */
17
18
  export const SCREEN_HEADER_PORTAL_HOST = "screen-header";
18
19
 
20
+ /** Shared configuration and UI-thread scroll values returned by `useScreen`. */
19
21
  export interface ScreenContextValue {
20
22
  /**
21
- * Which axes scroll containers pad with `layout.screen.margin`.
22
- * Overridable per `Screen.ScrollView` / `Screen.FlatList` / `Screen.List`
23
- * via their own `margins` prop.
23
+ * Which axes scroll containers pad with `layout.screen.padding`.
24
+ * Each scroll container can override this with its own `contentPadding` prop.
24
25
  */
25
- margins: ScreenMargins;
26
+ contentPadding: ScreenContentPadding;
27
+ /** Safe-area policy applied by the root; descendants must not reapply it. */
28
+ safeArea: ScreenSafeArea;
29
+ /** @deprecated Use contentPadding. */
30
+ margins: ScreenContentPadding;
26
31
  /** Whether a `Screen.Header` is present. Used by scroll containers to add top inset. */
27
32
  hasHeader: boolean;
28
- /**
29
- * Live vertical scroll offset of the screen's scroll container, driven by
30
- * `Screen.ScrollView` / `Screen.FlatList`. Headers (and consumer UI) read it
31
- * to animate on scroll.
32
- */
33
+ /** Vertical scroll offset, updated on the UI thread for header animations. */
33
34
  scrollY: SharedValue<number>;
34
35
  /**
35
- * Scroll distance (px) over which the active header collapses — measured by
36
- * the header (e.g. large-title portal height, parallax hero height). `0`
37
- * disables snap and collapse-range animations (`Header.Title` screens).
36
+ * Optional collapse distance for custom headers. Set via setHeaderCollapseHeight.
37
+ * Built-in headers derive their animation range from the theme.
38
38
  */
39
39
  headerCollapseHeight: SharedValue<number>;
40
40
  /**
41
- * Native `snapToOffsets` for the scroll container. `[0, height]` when a
42
- * collapsible header is active; `undefined` otherwise.
41
+ * Native list snap offsets set by setHeaderCollapseHeight. Undefined by default.
42
+ * For Screen.ScrollView, pass these explicitly as snapToOffsets.
43
43
  */
44
44
  headerSnapOffsets: number[] | undefined;
45
- /** Updates collapse height for animations and native snap offsets. */
45
+ /** Rounds the height and sets `[0, height]` snap offsets; nonpositive heights clear snapping. */
46
46
  setHeaderCollapseHeight: (height: number) => void;
47
- /** Shared scroll container ref — bound by `Screen.ScrollView` / `Screen.FlatList`. */
47
+ /**
48
+ * Ref bound by ScrollView and FlatList containers, including `Screen.List`
49
+ * with FlatList. Custom list implementations do not bind this ref.
50
+ * Its declared ScrollView type does not expose FlatList-specific methods.
51
+ */
48
52
  scrollRef: ScreenScrollRef;
49
53
  /** Scroll handler that mirrors offset into `scrollY`. */
50
54
  scrollHandler: ScrollHandlerProcessed<Record<string, unknown>>;
51
55
 
56
+ /** Resolved background color shared with scroll containers. */
52
57
  background?: string;
53
58
  }
54
59
 
55
60
  export const ScreenContext = createContext<ScreenContextValue | null>(null);
56
61
 
62
+ /** Internal provider inputs resolved by the Screen root. */
57
63
  export interface ScreenScrollProviderProps {
58
64
  children: ReactNode;
59
- /** Which axes scroll containers pad with `layout.screen.margin`. Default `'all'`. */
60
- margins?: ScreenMargins;
65
+ /** Which axes scroll containers pad with `layout.screen.padding`. Default `'all'`. */
66
+ contentPadding?: ScreenContentPadding;
67
+ safeArea?: ScreenSafeArea;
61
68
  /** Whether a `Screen.Header` child is present. Default false. */
62
69
  hasHeader?: boolean;
63
70
 
71
+ /** Resolved background color shared with scroll containers. */
64
72
  background?: string;
65
73
  }
66
74
 
67
75
  /**
68
76
  * Owns the screen's shared scroll ref, offset, snap offsets, and header collapse
69
- * metrics. Header variants call {@link ScreenContextValue.setHeaderCollapseHeight};
70
- * scroll containers bind the ref via {@link useScreen}.
77
+ * metrics. Scroll containers bind the ref via {@link useScreen}.
71
78
  */
72
79
  export function ScreenScrollProvider({
73
80
  background = "transparent",
74
81
  children,
75
- margins = "all",
82
+ contentPadding = "all",
83
+ safeArea = "auto",
76
84
  hasHeader = false,
77
85
  }: ScreenScrollProviderProps) {
78
86
  const scrollY = useSharedValue(0);
@@ -98,7 +106,9 @@ export function ScreenScrollProvider({
98
106
  const value = useMemo<ScreenContextValue>(
99
107
  () => ({
100
108
  background,
101
- margins,
109
+ contentPadding,
110
+ safeArea,
111
+ margins: contentPadding,
102
112
  hasHeader,
103
113
  scrollY,
104
114
  headerCollapseHeight,
@@ -109,7 +119,8 @@ export function ScreenScrollProvider({
109
119
  }),
110
120
  [
111
121
  background,
112
- margins,
122
+ contentPadding,
123
+ safeArea,
113
124
  hasHeader,
114
125
  scrollY,
115
126
  headerCollapseHeight,
@@ -124,14 +135,23 @@ export function ScreenScrollProvider({
124
135
  }
125
136
 
126
137
  /**
127
- * Access the enclosing `Screen`'s shared scroll state, ref, and snap offsets.
138
+ * Reads the nearest `Screen`'s configuration, shared scroll state, and ref.
139
+ * Read `scrollY.value` in Reanimated worklets to animate without React renders.
140
+ * The ref belongs to the primary scroll container, not the screen root.
128
141
  *
129
142
  * @example
130
143
  * ```tsx
131
- * const { scrollY, scrollRef, headerSnapOffsets } = useScreen();
144
+ * function FadingContent() {
145
+ * const { scrollY } = useScreen();
146
+ * const style = useAnimatedStyle(() => ({
147
+ * opacity: interpolate(scrollY.value, [0, 100], [1, 0], "clamp"),
148
+ * }));
149
+ * return <Animated.View style={style}>{content}</Animated.View>;
150
+ * }
132
151
  * ```
133
152
  *
134
- * @throws if called outside a `Screen`.
153
+ * @returns The nearest Screen's configuration and scroll state.
154
+ * @throws Error when called outside a Screen provider.
135
155
  */
136
156
  export function useScreen(): ScreenContextValue {
137
157
  const context = useContext(ScreenContext);
@@ -1,192 +1,6 @@
1
- import { type FlatListProps, type NativeScrollEvent, type NativeSyntheticEvent, View } from "react-native";
1
+ import { ScreenList, type ScreenListProps } from "./ScreenList";
2
2
 
3
- import Animated, {
4
- type AnimatedRef,
5
- useAnimatedScrollHandler,
6
- useComposedEventHandler,
7
- } from "react-native-reanimated";
8
- import { StyleSheet } from "react-native-unistyles";
9
-
10
- import { resolveScreenMargin } from "#theme/screen-margin";
11
- import { PortalHost } from "../portal";
12
- import { BottomSafeArea } from "./parts/BottomSafeArea";
13
- import { renderScreenPlaceholder } from "./parts/ScreenPlaceholder";
14
- import { SCREEN_HEADER_PORTAL_HOST, useScreen } from "./ScreenContext";
15
- import type { ScreenMargins, ScreenScrollableProps } from "./types";
16
- import { hasXMargin, hasYMargin, renderListHeader } from "./utils";
17
-
18
- /**
19
- * @deprecated Use {@link ScreenListProps} (`Screen.List`) instead —
20
- * `Screen.List` renders `FlatList` by default and binds the screen's shared
21
- * scroll ref exactly as `Screen.FlatList` does, but also lets a screen swap in
22
- * any other FlatList-shaped list (e.g. `FlashList`) via its `as` prop.
23
- */
24
- export interface ScreenFlatListProps<T>
25
- extends Omit<FlatListProps<T>, "CellRendererComponent" | "horizontal">,
26
- ScreenScrollableProps {
27
- /**
28
- * Extra bottom padding on the list content — clearance for a tab bar or home
29
- * indicator. Defaults to the `layout.screen.margin.y` token when margins are
30
- * enabled, otherwise `0`.
31
- */
32
- bottomInset?: number;
33
- }
34
-
35
- /**
36
- * `FlatList` variant of `Screen.ScrollView`: binds the screen's shared scroll
37
- * ref, mirrors offset into `scrollY`, hosts the portal target above the list,
38
- * and applies token-driven content padding.
39
- *
40
- * Shares `loading` / `LoadingComponent` / `EmptyComponent` / `margins` /
41
- * `horizontal` with `Screen.ScrollView`, so a screen can swap one container for
42
- * another without relearning its API.
43
- *
44
- * @deprecated Use {@link ScreenList} (`Screen.List`) instead — it renders
45
- * `FlatList` by default and behaves identically, but also accepts an `as`
46
- * prop for swapping in another list implementation later without changing
47
- * the surrounding API.
48
- *
49
- * @example
50
- * ```tsx
51
- * <Screen.FlatList data={items} renderItem={({ item }) => <Row item={item} />} />
52
- * ```
53
- *
54
- * @example Loading and empty placeholders
55
- * ```tsx
56
- * <Screen.FlatList
57
- * data={items}
58
- * loading={isLoading}
59
- * EmptyComponent={<EmptyState icon="status.info" title="Nothing yet" fill />}
60
- * renderItem={({ item }) => <Row item={item} />}
61
- * />
62
- * ```
63
- */
64
- export function ScreenFlatList<T>({
65
- data,
66
- style,
67
- contentContainerStyle,
68
- ListHeaderComponent,
69
- ListFooterComponent,
70
- ListEmptyComponent,
71
- horizontal = false,
72
- loading = false,
73
- LoadingComponent,
74
- EmptyComponent,
75
- margins,
76
- bottomInset,
77
- onScroll,
78
- ...rest
79
- }: ScreenFlatListProps<T>) {
80
- const {
81
- background,
82
- scrollRef,
83
- scrollHandler,
84
- headerSnapOffsets,
85
- margins: screenMargins,
86
- hasHeader,
87
- } = useScreen();
88
-
89
- const resolvedMargins = margins ?? screenMargins;
90
- // The placeholder rides in on `ListEmptyComponent` rather than replacing the
91
- // list, so the header portal, scroll binding and snap offsets all stay put.
92
- // While loading the list is fed an empty `data` so that slot is the one that
93
- // renders.
94
- const placeholder = renderScreenPlaceholder({
95
- loading,
96
- LoadingComponent,
97
- EmptyComponent,
98
- isEmpty: !data || data.length === 0,
99
- });
100
-
101
- const jsScrollHandler = useAnimatedScrollHandler(
102
- (event) => {
103
- if (onScroll) onScroll(event as unknown as NativeSyntheticEvent<NativeScrollEvent>);
104
- },
105
- [onScroll]
106
- );
107
-
108
- const composedHandler = useComposedEventHandler([scrollHandler, jsScrollHandler]);
109
-
110
- // A caller naming its own `bottomInset` has taken the bottom over entirely,
111
- // and a horizontal list has no bottom edge to clear.
112
- const needsBottomSafeArea = bottomInset === undefined && !horizontal;
113
-
114
- const footerComponent = (
115
- <>
116
- {renderListHeader(ListFooterComponent)}
117
- {needsBottomSafeArea ? <BottomSafeArea /> : null}
118
- </>
119
- );
120
-
121
- const headerComponent = (
122
- <>
123
- {/* `headerWrapper`'s negative margin cancels the list's inherited
124
- content padding for the portaled header (`LargeTitlePortalContent`
125
- etc. manage their own horizontal padding) — a caller's own
126
- `ListHeaderComponent` has no such self-padding, so it stays outside
127
- this wrapper and gets the list's normal item padding instead. */}
128
- <View style={styles.headerWrapper(resolvedMargins)}>
129
- <PortalHost name={SCREEN_HEADER_PORTAL_HOST} />
130
- </View>
131
- {renderListHeader(ListHeaderComponent)}
132
- </>
133
- );
134
-
135
- return (
136
- <Animated.FlatList
137
- ref={scrollRef as unknown as AnimatedRef<Animated.FlatList<T>>}
138
- data={loading ? [] : data}
139
- style={[{ backgroundColor: background }, style]}
140
- horizontal={horizontal}
141
- contentInsetAdjustmentBehavior={hasHeader ? "never" : undefined}
142
- contentContainerStyle={[styles.content(resolvedMargins, hasHeader, bottomInset), contentContainerStyle]}
143
- ListHeaderComponent={headerComponent}
144
- ListFooterComponent={footerComponent}
145
- ListEmptyComponent={placeholder ?? ListEmptyComponent}
146
- showsVerticalScrollIndicator={false}
147
- scrollEventThrottle={16}
148
- snapToOffsets={headerSnapOffsets}
149
- {...rest}
150
- onScroll={composedHandler}
151
- />
152
- );
153
- }
154
-
155
- // `resolveScreenMargin` is called *inside* each dynamic function below, not
156
- // hoisted to the factory's top level — the Babel plugin only attributes a
157
- // runtime dependency (here, breakpoint) to a style key when the `rt`/
158
- // `runtime` read it derives from sits inside that key's own value. Hoisting
159
- // it would silently drop the dependency, so the margin would freeze at
160
- // whatever breakpoint was active on mount and never update on rotation.
161
- const styles = StyleSheet.create((theme, runtime) => ({
162
- scrollContent: {
163
- flexGrow: 1,
164
- },
165
- content: (margins: ScreenMargins, hasHeader: boolean, bottomInset: number | undefined) => {
166
- const { x: marginX, y: marginY } = resolveScreenMargin(theme, runtime.breakpoint);
167
- return {
168
- flexGrow: 1,
169
- // The header is absolutely positioned, so the list reserves its full
170
- // height — bar plus top safe area. This assumes the scroll view does not
171
- // also get UIKit's automatic inset adjustment: on a native tab screen
172
- // that means `disableAutomaticContentInsets` on the tab, or the two
173
- // insets are counted twice.
174
- paddingTop:
175
- (hasHeader ? theme.layout.header.height + runtime.insets.top : 0) +
176
- (hasYMargin(margins) ? marginY : 0),
177
- paddingHorizontal: hasXMargin(margins) ? marginX : 0,
178
- // The safe area is `BottomSafeArea`'s job; counting it here as well
179
- // would leave a gap the height of the gesture bar.
180
- paddingBottom: bottomInset ?? (hasYMargin(margins) ? marginY : 0),
181
- };
182
- },
183
- safeArea: {
184
- height: runtime.insets.top,
185
- },
186
- headerWrapper: (margins: ScreenMargins) => {
187
- const { x: marginX } = resolveScreenMargin(theme, runtime.breakpoint);
188
- return {
189
- marginHorizontal: hasXMargin(margins) ? -marginX : 0,
190
- };
191
- },
192
- }));
3
+ /** @deprecated Use ScreenListProps. */
4
+ export type ScreenFlatListProps<T> = ScreenListProps<T>;
5
+ /** @deprecated Use Screen.List, which exposes the same native FlatList and ref. */
6
+ export const ScreenFlatList: typeof ScreenList = ScreenList;