@vvedantb/native-ui 0.17.2 → 0.18.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 (220) hide show
  1. package/dist/AlertDialog.jsx +123 -0
  2. package/dist/AmbientBackground.jsx +73 -0
  3. package/dist/ArtifactList.jsx +59 -0
  4. package/dist/Avatar.jsx +285 -0
  5. package/dist/Badge.jsx +154 -0
  6. package/dist/BottomSheetContainer.jsx +208 -0
  7. package/dist/BulkActionBar.jsx +717 -0
  8. package/dist/Button.jsx +344 -0
  9. package/dist/CaptureButton.jsx +104 -0
  10. package/dist/Card.jsx +371 -0
  11. package/dist/Checkbox.jsx +177 -0
  12. package/dist/Chip.jsx +79 -0
  13. package/dist/ColorSwatches.jsx +159 -0
  14. package/dist/ConfirmDialog.jsx +157 -0
  15. package/dist/DateTimeField.jsx +204 -0
  16. package/dist/Dialog.jsx +614 -0
  17. package/dist/DividedList.jsx +120 -0
  18. package/dist/DropdownMenu.jsx +849 -0
  19. package/dist/EmptyState.jsx +434 -0
  20. package/dist/ExpoWebRoot.jsx +134 -0
  21. package/dist/FloatingFAB.jsx +95 -0
  22. package/dist/FloatingSurface.jsx +226 -0
  23. package/dist/FloatingTabBar.jsx +403 -0
  24. package/dist/HeaderIconButton.jsx +53 -0
  25. package/dist/IconButton.jsx +157 -0
  26. package/dist/Input.jsx +96 -0
  27. package/dist/Label.jsx +96 -0
  28. package/dist/LabeledSwitchRow.jsx +170 -0
  29. package/dist/LiquidGlass.jsx +2 -0
  30. package/dist/ListRow.jsx +281 -0
  31. package/dist/LoadingState.jsx +205 -0
  32. package/dist/PageIndicator.jsx +128 -0
  33. package/dist/PageTitle.jsx +205 -0
  34. package/dist/Pager.jsx +105 -0
  35. package/dist/PasswordInput.jsx +120 -0
  36. package/dist/PillTabs.jsx +300 -0
  37. package/dist/PinnedBotTile.jsx +212 -0
  38. package/dist/Progress.jsx +147 -0
  39. package/dist/SafeAreaContainer.jsx +38 -0
  40. package/dist/ScreenContainer.jsx +117 -0
  41. package/dist/SearchInput.jsx +150 -0
  42. package/dist/SectionLabel.jsx +128 -0
  43. package/dist/Select.jsx +223 -0
  44. package/dist/Separator.jsx +95 -0
  45. package/dist/Sheet.jsx +343 -0
  46. package/dist/SheetRow.jsx +198 -0
  47. package/dist/Skeleton.jsx +311 -0
  48. package/dist/Spinner.jsx +195 -0
  49. package/dist/StackPageHeader.jsx +160 -0
  50. package/dist/StatGrid.jsx +74 -0
  51. package/dist/StatusDot.jsx +129 -0
  52. package/dist/SurfaceRow.jsx +143 -0
  53. package/dist/SwipeableRow.jsx +50 -0
  54. package/dist/Switch.jsx +130 -0
  55. package/dist/Tabs.jsx +385 -0
  56. package/dist/Textarea.jsx +103 -0
  57. package/dist/ThemeToggle.jsx +78 -0
  58. package/dist/Toast.jsx +396 -0
  59. package/dist/ai/activity-step-detail.jsx +179 -0
  60. package/dist/ai/activity-step-label.js +816 -0
  61. package/dist/ai/activity-step-types.js +14 -0
  62. package/dist/ai/activity-step.jsx +98 -0
  63. package/dist/ai/activity-tasks-utils.js +172 -0
  64. package/dist/ai/activity-timeline.js +47 -0
  65. package/dist/ai/attachments.jsx +258 -0
  66. package/dist/ai/card-button.jsx +188 -0
  67. package/dist/ai/chain-of-thought.jsx +459 -0
  68. package/dist/ai/chat-jump-rail.jsx +57 -0
  69. package/dist/ai/chat-text.js +44 -0
  70. package/dist/ai/chat-thread.jsx +135 -0
  71. package/dist/ai/choice-question.jsx +925 -0
  72. package/dist/ai/code-block.jsx +574 -0
  73. package/dist/ai/collapsible.jsx +275 -0
  74. package/dist/ai/conversation.jsx +723 -0
  75. package/dist/ai/file-chip.jsx +198 -0
  76. package/dist/ai/icon-button.jsx +179 -0
  77. package/dist/ai/index.js +37 -0
  78. package/dist/ai/message-action-sheet.jsx +408 -0
  79. package/dist/ai/message-quote.jsx +241 -0
  80. package/dist/ai/message.jsx +739 -0
  81. package/dist/ai/prompt-input-menu.jsx +365 -0
  82. package/dist/ai/prompt-input.jsx +626 -0
  83. package/dist/ai/reasoning.jsx +446 -0
  84. package/dist/ai/reply-quote-chip.jsx +278 -0
  85. package/dist/ai/response-text.jsx +130 -0
  86. package/dist/ai/shimmer.jsx +149 -0
  87. package/dist/ai/sources.jsx +260 -0
  88. package/dist/ai/subagent-cards.jsx +645 -0
  89. package/dist/ai/suggestion.jsx +186 -0
  90. package/dist/ai/tool-approval-card.jsx +359 -0
  91. package/dist/ai/trace.jsx +728 -0
  92. package/dist/ai/unified-diff.jsx +280 -0
  93. package/dist/ai/use-streaming-disclosure.js +70 -0
  94. package/dist/auth/AuthProviders.jsx +27 -0
  95. package/dist/auth/AuthScreen.jsx +292 -0
  96. package/dist/auth/GoogleSignInButton.jsx +188 -0
  97. package/dist/auth/SecondFactorScreen.jsx +133 -0
  98. package/dist/auth/SignInScreen.jsx +482 -0
  99. package/dist/auth/authErrors.js +131 -0
  100. package/dist/auth/index.js +11 -0
  101. package/dist/auth/totp.js +378 -0
  102. package/dist/blur.js +36 -0
  103. package/dist/brand/AppIcons.jsx +118 -0
  104. package/dist/brand/AppMark.jsx +128 -0
  105. package/dist/brand/AppWordmark.jsx +138 -0
  106. package/dist/brand/GoogleMark.jsx +71 -0
  107. package/dist/brand/ProviderIcon.jsx +192 -0
  108. package/dist/brand/familyApps.js +33 -0
  109. package/dist/brand/index.js +11 -0
  110. package/dist/brand/svg.js +252 -0
  111. package/dist/brand/vProAppBenefits.js +19 -0
  112. package/dist/cn.js +5 -0
  113. package/dist/colors.js +15 -0
  114. package/dist/configureTheme.js +72 -0
  115. package/dist/controlStyles.js +520 -0
  116. package/dist/definiteSize.js +12 -0
  117. package/dist/dialogLayout.js +18 -0
  118. package/dist/entries/ai.js +4 -0
  119. package/dist/entries/ambient.js +3 -0
  120. package/dist/entries/auth.js +5 -0
  121. package/dist/entries/bottom-sheet.js +2 -0
  122. package/dist/entries/brand.js +2 -0
  123. package/dist/entries/button.js +2 -0
  124. package/dist/entries/date-time.js +3 -0
  125. package/dist/entries/expo-router.js +4 -0
  126. package/dist/entries/expo-web-root.js +3 -0
  127. package/dist/entries/floating.js +7 -0
  128. package/dist/entries/gesture-handler.js +4 -0
  129. package/dist/entries/keyboard-controller.js +4 -0
  130. package/dist/entries/layout.js +16 -0
  131. package/dist/entries/markdown.js +4 -0
  132. package/dist/entries/marketing.js +3 -0
  133. package/dist/entries/page-title.js +7 -0
  134. package/dist/entries/password-input.js +3 -0
  135. package/dist/entries/primitives.js +57 -0
  136. package/dist/entries/search-input.js +3 -0
  137. package/dist/entries/tab-bar.js +4 -0
  138. package/dist/entries/theme.js +7 -0
  139. package/dist/entries/toast.js +5 -0
  140. package/dist/entries/video.js +3 -0
  141. package/dist/entries/webview.js +4 -0
  142. package/dist/examples/AiChatGallery.jsx +509 -0
  143. package/dist/examples/ParityGallery.jsx +1307 -0
  144. package/dist/floating.js +62 -0
  145. package/dist/glassBlur.jsx +145 -0
  146. package/dist/gradient.js +17 -0
  147. package/dist/haptics.js +44 -0
  148. package/dist/highlight.js +382 -0
  149. package/dist/index.js +85 -0
  150. package/dist/initials.js +4 -0
  151. package/dist/loadingGrid.js +81 -0
  152. package/dist/markdown/Markdown.jsx +515 -0
  153. package/dist/markdown/MarkdownTable.jsx +443 -0
  154. package/dist/markdown/tableText.js +68 -0
  155. package/dist/marketing/PricingModal.jsx +608 -0
  156. package/dist/marketing/UpgradeToProCard.jsx +164 -0
  157. package/dist/marketing/pricing.js +34 -0
  158. package/dist/media/ImageGallery.jsx +580 -0
  159. package/dist/media/MediaCard.jsx +162 -0
  160. package/dist/media/imageGrid.js +54 -0
  161. package/dist/motion.js +33 -0
  162. package/dist/pagerSwipe.js +104 -0
  163. package/dist/palette.js +104 -0
  164. package/dist/primitives/button.jsx +127 -0
  165. package/dist/primitives/card.jsx +249 -0
  166. package/dist/primitives/icon.jsx +37 -0
  167. package/dist/primitives/input.jsx +56 -0
  168. package/dist/primitives/keyboard-controller.jsx +207 -0
  169. package/dist/primitives/keyboard-parts.jsx +75 -0
  170. package/dist/primitives/native-only-animated-view.jsx +68 -0
  171. package/dist/primitives/overlay.jsx +391 -0
  172. package/dist/primitives/pager-gesture.jsx +131 -0
  173. package/dist/primitives/select-host.jsx +103 -0
  174. package/dist/primitives/select.jsx +555 -0
  175. package/dist/primitives/sheet-drag.jsx +420 -0
  176. package/dist/primitives/sheet-gesture.jsx +219 -0
  177. package/dist/primitives/swipe-row-gesture.jsx +341 -0
  178. package/dist/primitives/switch.jsx +105 -0
  179. package/dist/primitives/text.jsx +145 -0
  180. package/dist/primitives/toast-drag-gesture.jsx +94 -0
  181. package/dist/primitives/use-controllable-state.js +40 -0
  182. package/dist/primitives/web-click-guard.js +69 -0
  183. package/dist/push.js +166 -0
  184. package/dist/relativeTime.js +70 -0
  185. package/dist/router/RouterStackPageHeader.jsx +53 -0
  186. package/dist/selectA11y.js +32 -0
  187. package/dist/settings/MoreFromProjectV.jsx +168 -0
  188. package/dist/settings/SettingsEmptyState.jsx +102 -0
  189. package/dist/settings/SettingsField.jsx +49 -0
  190. package/dist/settings/SettingsSection.jsx +101 -0
  191. package/dist/settings/SettingsStack.jsx +17 -0
  192. package/dist/settings/SettingsToggleRow.jsx +163 -0
  193. package/dist/settings/projectVMobileApps.js +126 -0
  194. package/dist/settings/relaxedSizeStyle.js +11 -0
  195. package/dist/sheetDrag.js +76 -0
  196. package/dist/svgA11y.js +46 -0
  197. package/dist/swipeRow.js +161 -0
  198. package/dist/tabBarRoutes.js +41 -0
  199. package/dist/tabIndicator.js +139 -0
  200. package/dist/tailwind-preset.cjs +255 -0
  201. package/dist/tailwind-preset.d.cts +55 -0
  202. package/dist/theme.jsx +62 -0
  203. package/dist/toastChrome.js +110 -0
  204. package/dist/toastDrag.js +51 -0
  205. package/dist/toastStore.js +54 -0
  206. package/dist/tokens.js +70 -0
  207. package/dist/typography.js +40 -0
  208. package/dist/useReduceMotion.js +32 -0
  209. package/dist/useReduceTransparency.js +27 -0
  210. package/dist/useScheme.js +15 -0
  211. package/dist/video/InlineVideo.jsx +115 -0
  212. package/dist/webview/HtmlView.jsx +169 -0
  213. package/dist/webview/HtmlView.web.jsx +63 -0
  214. package/dist/webview/htmlView.js +43 -0
  215. package/package.json +70 -33
  216. package/src/DropdownMenu.tsx +28 -16
  217. package/src/FloatingTabBar.tsx +78 -41
  218. package/src/ai/conversation.tsx +12 -8
  219. package/src/glassBlur.tsx +47 -22
  220. package/src/primitives/swipe-row-gesture.tsx +11 -2
@@ -0,0 +1,391 @@
1
+ import { c as _c } from "react/compiler-runtime";
2
+ import * as Slot from "@rn-primitives/slot";
3
+ import { createContext, Fragment, useContext, useEffect, useState } from "react";
4
+ import { Modal, Pressable, StyleSheet, View } from "react-native";
5
+ import Animated from "react-native-reanimated";
6
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
7
+ import { palette } from "../palette";
8
+ import { KeyboardAvoidingView, KeyboardLiftContext } from "./keyboard-parts";
9
+ import { useReduceMotion } from "../useReduceMotion";
10
+ import { useScheme } from "../useScheme";
11
+ import { SheetDragProvider, SheetGestureContext, slideSheetIn, slideSheetOut, useSheetBackdropStyle, useSheetDragState } from "./sheet-drag";
12
+ import { useControllableState } from "./use-controllable-state";
13
+ const OverlayContext = createContext(null);
14
+ export function useOverlay(part) {
15
+ const context = useContext(OverlayContext);
16
+ if (!context) {
17
+ throw new Error(`${part} must be inside its Dialog, AlertDialog or Sheet root.`);
18
+ }
19
+ return context;
20
+ }
21
+ /** Root shared by `Dialog`, `AlertDialog` and `Sheet`: holds the open state, renders no view. */
22
+ export function OverlayRoot(t0) {
23
+ const $ = _c(10);
24
+ const {
25
+ open,
26
+ defaultOpen: t1,
27
+ onOpenChange,
28
+ children
29
+ } = t0;
30
+ const defaultOpen = t1 === undefined ? false : t1;
31
+ let t2;
32
+ if ($[0] !== defaultOpen || $[1] !== onOpenChange || $[2] !== open) {
33
+ t2 = {
34
+ value: open,
35
+ defaultValue: defaultOpen,
36
+ onChange: onOpenChange
37
+ };
38
+ $[0] = defaultOpen;
39
+ $[1] = onOpenChange;
40
+ $[2] = open;
41
+ $[3] = t2;
42
+ } else {
43
+ t2 = $[3];
44
+ }
45
+ const [value, setValue] = useControllableState(t2);
46
+ let t3;
47
+ if ($[4] !== setValue || $[5] !== value) {
48
+ t3 = {
49
+ open: value,
50
+ setOpen: setValue
51
+ };
52
+ $[4] = setValue;
53
+ $[5] = value;
54
+ $[6] = t3;
55
+ } else {
56
+ t3 = $[6];
57
+ }
58
+ let t4;
59
+ if ($[7] !== children || $[8] !== t3) {
60
+ t4 = <OverlayContext.Provider value={t3}>{children}</OverlayContext.Provider>;
61
+ $[7] = children;
62
+ $[8] = t3;
63
+ $[9] = t4;
64
+ } else {
65
+ t4 = $[9];
66
+ }
67
+ return t4;
68
+ }
69
+ function OverlayPressable(t0) {
70
+ const $ = _c(14);
71
+ let asChild;
72
+ let next;
73
+ let onPress;
74
+ let part;
75
+ let props;
76
+ if ($[0] !== t0) {
77
+ ({
78
+ asChild,
79
+ next,
80
+ part,
81
+ onPress,
82
+ ...props
83
+ } = t0);
84
+ $[0] = t0;
85
+ $[1] = asChild;
86
+ $[2] = next;
87
+ $[3] = onPress;
88
+ $[4] = part;
89
+ $[5] = props;
90
+ } else {
91
+ asChild = $[1];
92
+ next = $[2];
93
+ onPress = $[3];
94
+ part = $[4];
95
+ props = $[5];
96
+ }
97
+ const {
98
+ setOpen
99
+ } = useOverlay(part);
100
+ const Component = asChild ? Slot.Pressable : Pressable;
101
+ let t1;
102
+ if ($[6] !== next || $[7] !== onPress || $[8] !== setOpen) {
103
+ t1 = event => {
104
+ onPress?.(event);
105
+ setOpen(next);
106
+ };
107
+ $[6] = next;
108
+ $[7] = onPress;
109
+ $[8] = setOpen;
110
+ $[9] = t1;
111
+ } else {
112
+ t1 = $[9];
113
+ }
114
+ let t2;
115
+ if ($[10] !== Component || $[11] !== props || $[12] !== t1) {
116
+ t2 = <Component accessibilityRole="button" {...props} onPress={t1} />;
117
+ $[10] = Component;
118
+ $[11] = props;
119
+ $[12] = t1;
120
+ $[13] = t2;
121
+ } else {
122
+ t2 = $[13];
123
+ }
124
+ return t2;
125
+ }
126
+ export function OverlayTrigger(props) {
127
+ const $ = _c(2);
128
+ let t0;
129
+ if ($[0] !== props) {
130
+ t0 = <OverlayPressable {...props} next={true} />;
131
+ $[0] = props;
132
+ $[1] = t0;
133
+ } else {
134
+ t0 = $[1];
135
+ }
136
+ return t0;
137
+ }
138
+ export function OverlayClose(props) {
139
+ const $ = _c(2);
140
+ let t0;
141
+ if ($[0] !== props) {
142
+ t0 = <OverlayPressable {...props} next={false} />;
143
+ $[0] = props;
144
+ $[1] = t0;
145
+ } else {
146
+ t0 = $[1];
147
+ }
148
+ return t0;
149
+ }
150
+
151
+ /**
152
+ * RN `Modal` with a tinted backdrop, safe-area padding and keyboard avoidance
153
+ * (`KeyboardAvoidingView`: frame by frame with `KeyboardControllerProvider`).
154
+ * `placement="center"` centres the child (dialogs) inside the insets on every
155
+ * side, and the `Modal` fades in and out. `"bottom"` pins it to the bottom
156
+ * edge (sheets), which pad their own bottom inset: the sheet slides up on
157
+ * open and back down on close, however it closes, and may be dragged down to
158
+ * close (`SheetDragView`); the backdrop fades with the sheet's position. The
159
+ * `Modal` stays up until the sheet is out of sight. The backdrop closes the
160
+ * overlay only when `dismissible`; Android back and the VoiceOver escape
161
+ * gesture always close it, as Escape does on the web. With Reduce Motion on,
162
+ * overlays appear and leave in place. With the Gesture Handler parts
163
+ * (`GestureHandlerProvider`), the content sits in its own root view: on
164
+ * Android a `Modal` is a separate root, and without one there every gesture
165
+ * in it silently does nothing.
166
+ */
167
+ export function OverlayModal(t0) {
168
+ const $ = _c(20);
169
+ const {
170
+ part,
171
+ placement,
172
+ dismissible,
173
+ onShow,
174
+ children
175
+ } = t0;
176
+ const {
177
+ open,
178
+ setOpen
179
+ } = useOverlay(part);
180
+ const reduceMotion = useReduceMotion();
181
+ const slides = placement === "bottom" && !reduceMotion;
182
+ const [shown, setShown] = useState(open);
183
+ if (open && !shown) {
184
+ setShown(true);
185
+ }
186
+ if (!open && shown && !slides) {
187
+ setShown(false);
188
+ }
189
+ let t1;
190
+ if ($[0] !== setOpen) {
191
+ t1 = () => setOpen(false);
192
+ $[0] = setOpen;
193
+ $[1] = t1;
194
+ } else {
195
+ t1 = $[1];
196
+ }
197
+ const close = t1;
198
+ const ModalRoot = useContext(SheetGestureContext)?.ModalRoot ?? Fragment;
199
+ const t2 = slides || reduceMotion ? "none" : "fade";
200
+ let t3;
201
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
202
+ t3 = () => setShown(false);
203
+ $[2] = t3;
204
+ } else {
205
+ t3 = $[2];
206
+ }
207
+ let t4;
208
+ if ($[3] !== children || $[4] !== close || $[5] !== dismissible || $[6] !== open || $[7] !== part || $[8] !== placement || $[9] !== slides) {
209
+ t4 = <OverlayModalBody placement={placement} dismissible={dismissible} open={open} slides={slides} close={close} onHidden={t3} part={part}>{children}</OverlayModalBody>;
210
+ $[3] = children;
211
+ $[4] = close;
212
+ $[5] = dismissible;
213
+ $[6] = open;
214
+ $[7] = part;
215
+ $[8] = placement;
216
+ $[9] = slides;
217
+ $[10] = t4;
218
+ } else {
219
+ t4 = $[10];
220
+ }
221
+ let t5;
222
+ if ($[11] !== ModalRoot || $[12] !== t4) {
223
+ t5 = <ModalRoot>{t4}</ModalRoot>;
224
+ $[11] = ModalRoot;
225
+ $[12] = t4;
226
+ $[13] = t5;
227
+ } else {
228
+ t5 = $[13];
229
+ }
230
+ let t6;
231
+ if ($[14] !== close || $[15] !== onShow || $[16] !== shown || $[17] !== t2 || $[18] !== t5) {
232
+ t6 = <Modal visible={shown} transparent={true} animationType={t2} statusBarTranslucent={true} onRequestClose={close} onShow={onShow}>{t5}</Modal>;
233
+ $[14] = close;
234
+ $[15] = onShow;
235
+ $[16] = shown;
236
+ $[17] = t2;
237
+ $[18] = t5;
238
+ $[19] = t6;
239
+ } else {
240
+ t6 = $[19];
241
+ }
242
+ return t6;
243
+ }
244
+
245
+ /** The `Modal`'s content: mounted with each opening, so a sheet starts below the screen (or at rest). */
246
+ function OverlayModalBody(t0) {
247
+ const $ = _c(37);
248
+ const {
249
+ part,
250
+ placement,
251
+ dismissible,
252
+ open,
253
+ slides,
254
+ close,
255
+ onHidden,
256
+ children
257
+ } = t0;
258
+ const scheme = useScheme();
259
+ const insets = useSafeAreaInsets();
260
+ const drag = useSheetDragState(close, slides);
261
+ const backdropStyle = useSheetBackdropStyle(drag);
262
+ let t1;
263
+ if ($[0] !== drag || $[1] !== onHidden || $[2] !== open || $[3] !== slides) {
264
+ t1 = () => {
265
+ if (!slides) {
266
+ return;
267
+ }
268
+ if (open) {
269
+ slideSheetIn(drag);
270
+ } else {
271
+ slideSheetOut(drag, onHidden);
272
+ }
273
+ };
274
+ $[0] = drag;
275
+ $[1] = onHidden;
276
+ $[2] = open;
277
+ $[3] = slides;
278
+ $[4] = t1;
279
+ } else {
280
+ t1 = $[4];
281
+ }
282
+ let t2;
283
+ if ($[5] !== open || $[6] !== slides) {
284
+ t2 = [open, slides];
285
+ $[5] = open;
286
+ $[6] = slides;
287
+ $[7] = t2;
288
+ } else {
289
+ t2 = $[7];
290
+ }
291
+ useEffect(t1, t2);
292
+ const t3 = palette.backdrop[scheme];
293
+ let t4;
294
+ if ($[8] !== t3) {
295
+ t4 = {
296
+ backgroundColor: t3
297
+ };
298
+ $[8] = t3;
299
+ $[9] = t4;
300
+ } else {
301
+ t4 = $[9];
302
+ }
303
+ let t5;
304
+ if ($[10] !== backdropStyle || $[11] !== t4) {
305
+ t5 = [StyleSheet.absoluteFill, t4, backdropStyle];
306
+ $[10] = backdropStyle;
307
+ $[11] = t4;
308
+ $[12] = t5;
309
+ } else {
310
+ t5 = $[12];
311
+ }
312
+ const t6 = `${part}-backdrop`;
313
+ const t7 = !dismissible;
314
+ let t8;
315
+ if ($[13] !== close || $[14] !== dismissible || $[15] !== t6 || $[16] !== t7) {
316
+ t8 = <Pressable testID={t6} accessible={dismissible} accessibilityRole="button" accessibilityLabel="Close" disabled={t7} onPress={close} style={StyleSheet.absoluteFill} />;
317
+ $[13] = close;
318
+ $[14] = dismissible;
319
+ $[15] = t6;
320
+ $[16] = t7;
321
+ $[17] = t8;
322
+ } else {
323
+ t8 = $[17];
324
+ }
325
+ let t9;
326
+ if ($[18] !== t5 || $[19] !== t8) {
327
+ t9 = <Animated.View pointerEvents="box-none" style={t5}>{t8}</Animated.View>;
328
+ $[18] = t5;
329
+ $[19] = t8;
330
+ $[20] = t9;
331
+ } else {
332
+ t9 = $[20];
333
+ }
334
+ let t10;
335
+ if ($[21] !== insets.bottom || $[22] !== insets.left || $[23] !== insets.right || $[24] !== insets.top || $[25] !== placement) {
336
+ t10 = [styles.fill, placement === "bottom" ? {
337
+ justifyContent: "flex-end",
338
+ paddingTop: insets.top + 16,
339
+ paddingLeft: insets.left,
340
+ paddingRight: insets.right
341
+ } : {
342
+ justifyContent: "center",
343
+ paddingTop: insets.top + 16,
344
+ paddingBottom: insets.bottom + 16,
345
+ paddingLeft: insets.left + 16,
346
+ paddingRight: insets.right + 16
347
+ }];
348
+ $[21] = insets.bottom;
349
+ $[22] = insets.left;
350
+ $[23] = insets.right;
351
+ $[24] = insets.top;
352
+ $[25] = placement;
353
+ $[26] = t10;
354
+ } else {
355
+ t10 = $[26];
356
+ }
357
+ let t11;
358
+ if ($[27] !== children || $[28] !== close || $[29] !== t10) {
359
+ t11 = <View pointerEvents="box-none" onAccessibilityEscape={close} style={t10}>{children}</View>;
360
+ $[27] = children;
361
+ $[28] = close;
362
+ $[29] = t10;
363
+ $[30] = t11;
364
+ } else {
365
+ t11 = $[30];
366
+ }
367
+ let t12;
368
+ if ($[31] !== t11 || $[32] !== t9) {
369
+ t12 = <KeyboardAvoidingView style={styles.fill}><KeyboardLiftContext.Provider value={false}>{t9}{t11}</KeyboardLiftContext.Provider></KeyboardAvoidingView>;
370
+ $[31] = t11;
371
+ $[32] = t9;
372
+ $[33] = t12;
373
+ } else {
374
+ t12 = $[33];
375
+ }
376
+ let t13;
377
+ if ($[34] !== drag || $[35] !== t12) {
378
+ t13 = <SheetDragProvider value={drag}>{t12}</SheetDragProvider>;
379
+ $[34] = drag;
380
+ $[35] = t12;
381
+ $[36] = t13;
382
+ } else {
383
+ t13 = $[36];
384
+ }
385
+ return t13;
386
+ }
387
+ const styles = StyleSheet.create({
388
+ fill: {
389
+ flex: 1
390
+ }
391
+ });
@@ -0,0 +1,131 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { StyleSheet, View } from "react-native";
3
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
+ import Animated, { cancelAnimation, ReduceMotion, runOnJS, useAnimatedStyle, useSharedValue, withSpring, withTiming } from "react-native-reanimated";
5
+ import { selectionHaptic } from "../haptics";
6
+ import { InsidePagerContext } from "../Pager";
7
+ import { PAGER_ACTIVE_OFFSET_X, PAGER_FAIL_OFFSET_Y, pagerPosition, pagerSettle, pagesBetween } from "../pagerSwipe";
8
+ import { useWebClickGuard } from "./web-click-guard";
9
+
10
+ // The pager on Gesture Handler: the track phase and the release run as
11
+ // worklets on the UI thread, so the pages never lag the finger. The rules are
12
+ // plain worklets in `pagerSwipe`.
13
+
14
+ /** The release: springs on at the finger's speed, no bounce (an overshoot would flash the next page's edge). */
15
+ const PAGER_SPRING = {
16
+ duration: 250,
17
+ dampingRatio: 1,
18
+ reduceMotion: ReduceMotion.System
19
+ };
20
+
21
+ /** A page set from outside (a tab press) slides there; at once with Reduce Motion. */
22
+ const PAGER_SLIDE = {
23
+ duration: 220,
24
+ reduceMotion: ReduceMotion.System
25
+ };
26
+ export function GesturePager({
27
+ index,
28
+ count,
29
+ onIndexChange,
30
+ progress,
31
+ renderPage
32
+ }) {
33
+ const width = useSharedValue(0);
34
+ // Where the pages were when the finger caught them, and the finger's travel then.
35
+ const start = useSharedValue(0);
36
+ const startX = useSharedValue(0);
37
+ const [mounted, setMounted] = useState(() => new Set([index]));
38
+ const [shown, setShown] = useState(index);
39
+ // A page reached from outside is drawn from then on, with every page the
40
+ // slide there passes, so it never crosses a blank page.
41
+ if (shown !== index) {
42
+ setShown(index);
43
+ setMounted(new Set([...mounted, ...pagesBetween(shown, index)]));
44
+ }
45
+ // The page a swipe settled on, until the new `index` comes back: that one must not stop the spring.
46
+ const settling = useRef(null);
47
+ // A page set from outside slides there. An effect: a shared value is never
48
+ // written in render.
49
+ useEffect(() => {
50
+ const fromSwipe = settling.current === index;
51
+ settling.current = null;
52
+ if (fromSwipe) return;
53
+ progress.set(withTiming(index, PAGER_SLIDE));
54
+ }, [index, progress]);
55
+ const webClicks = useWebClickGuard();
56
+ const dragStarted = () => {
57
+ webClicks.swallowNext();
58
+ // Both neighbours, so the finger finds a page there.
59
+ setMounted(current => new Set([...current, index - 1, index + 1].filter(page => page >= 0 && page < count)));
60
+ };
61
+ const settled = page_0 => {
62
+ settling.current = page_0;
63
+ selectionHaptic();
64
+ onIndexChange(page_0);
65
+ };
66
+
67
+ // Built on each render (for `index` and `count`): the detector keeps the
68
+ // same handler, and a drag in flight, and only takes the new config.
69
+ const pan = Gesture.Pan().enabled(count > 1)
70
+ // Clearly sideways only: a vertical drag is the page's scroll, and a row swipe starts sooner.
71
+ .activeOffsetX([-PAGER_ACTIVE_OFFSET_X, PAGER_ACTIVE_OFFSET_X]).failOffsetY([-PAGER_FAIL_OFFSET_Y, PAGER_FAIL_OFFSET_Y]).onStart(event => {
72
+ cancelAnimation(progress);
73
+ start.set(progress.get());
74
+ // Count from here, so the pages do not jump by the slop the drag needed to start.
75
+ startX.set(event.translationX);
76
+ runOnJS(dragStarted)();
77
+ })
78
+ // Track phase: one shared value write per frame, on the UI thread.
79
+ .onUpdate(event_0 => {
80
+ progress.set(pagerPosition(start.get(), event_0.translationX - startX.get(), width.get(), count));
81
+ }).onEnd(event_1 => {
82
+ const pageWidth = width.get();
83
+ const target = pagerSettle(progress.get(), event_1.velocityX, pageWidth, Math.round(start.get()), count);
84
+ // The finger's speed in pages per second, the unit of `progress`.
85
+ const velocity = pageWidth > 0 ? -event_1.velocityX / pageWidth : 0;
86
+ progress.set(withSpring(target, {
87
+ ...PAGER_SPRING,
88
+ velocity
89
+ }));
90
+ if (target !== index) runOnJS(settled)(target);
91
+ });
92
+ const trackStyle = useAnimatedStyle(() => ({
93
+ transform: [{
94
+ translateX: `${-progress.get() * 100 / count}%`
95
+ }]
96
+ }));
97
+ return <InsidePagerContext.Provider value>
98
+ <View style={styles.clip} onLayout={event_2 => width.set(event_2.nativeEvent.layout.width)}>
99
+ <GestureDetector gesture={pan}>
100
+ <Animated.View style={[styles.fill, {
101
+ width: `${count * 100}%`
102
+ }, trackStyle]}>
103
+ <View ref={webClicks.ref} style={styles.track}>
104
+ {Array.from({
105
+ length: count
106
+ }, (_, page_1) => <View key={page_1}
107
+ // Off-screen pages are hidden from screen readers; the tabs above switch pages for them.
108
+ accessibilityElementsHidden={page_1 !== index} importantForAccessibility={page_1 === index ? "auto" : "no-hide-descendants"} style={{
109
+ width: `${100 / count}%`
110
+ }}>
111
+ {mounted.has(page_1) ? renderPage(page_1) : null}
112
+ </View>)}
113
+ </View>
114
+ </Animated.View>
115
+ </GestureDetector>
116
+ </View>
117
+ </InsidePagerContext.Provider>;
118
+ }
119
+ const styles = StyleSheet.create({
120
+ clip: {
121
+ flex: 1,
122
+ overflow: "hidden"
123
+ },
124
+ fill: {
125
+ flex: 1
126
+ },
127
+ track: {
128
+ flex: 1,
129
+ flexDirection: "row"
130
+ }
131
+ });
@@ -0,0 +1,103 @@
1
+ import { c as _c } from "react/compiler-runtime";
2
+ import * as SelectPrimitive from "@rn-primitives/select";
3
+ import * as React from "react";
4
+ import { Modal, Platform, View } from "react-native";
5
+ import { FullWindowOverlay } from "react-native-screens";
6
+ import { useReduceMotion } from "../useReduceMotion";
7
+
8
+ /**
9
+ * Where `SelectContent` draws its options.
10
+ *
11
+ * - Android: a transparent RN `Modal` with a full-size `box-none` host, as
12
+ * `DropdownMenuContent` and `OverlayModal` use. The Modal is its own window,
13
+ * so options sit above an absolute tab bar or glass layer. `SelectContent`
14
+ * renders this host without a Portal, because a Modal inside a portal mounts
15
+ * empty. With no Portal there is no `open` gate from the primitive, so the
16
+ * host mounts the Modal only while the Select is open. Android back closes it.
17
+ * - iOS: `FullWindowOverlay`, which sits above native navigation chrome.
18
+ * - Web: no wrapper. Radix owns the layering.
19
+ *
20
+ * `Platform.OS` is read at render, not at import, so a test can switch it.
21
+ */
22
+ export function SelectHost(t0) {
23
+ const $ = _c(15);
24
+ const {
25
+ children
26
+ } = t0;
27
+ const {
28
+ open,
29
+ onOpenChange,
30
+ setTriggerPosition,
31
+ setContentLayout
32
+ } = SelectPrimitive.useRootContext();
33
+ const reduceMotion = useReduceMotion();
34
+ if (Platform.OS === "ios") {
35
+ let t1;
36
+ if ($[0] !== children) {
37
+ t1 = <FullWindowOverlay>{children}</FullWindowOverlay>;
38
+ $[0] = children;
39
+ $[1] = t1;
40
+ } else {
41
+ t1 = $[1];
42
+ }
43
+ return t1;
44
+ }
45
+ if (Platform.OS !== "android") {
46
+ let t1;
47
+ if ($[2] !== children) {
48
+ t1 = <>{children}</>;
49
+ $[2] = children;
50
+ $[3] = t1;
51
+ } else {
52
+ t1 = $[3];
53
+ }
54
+ return t1;
55
+ }
56
+ if (!open) {
57
+ return null;
58
+ }
59
+ let t1;
60
+ if ($[4] !== onOpenChange || $[5] !== setContentLayout || $[6] !== setTriggerPosition) {
61
+ t1 = () => {
62
+ setTriggerPosition(null);
63
+ setContentLayout(null);
64
+ onOpenChange(false);
65
+ };
66
+ $[4] = onOpenChange;
67
+ $[5] = setContentLayout;
68
+ $[6] = setTriggerPosition;
69
+ $[7] = t1;
70
+ } else {
71
+ t1 = $[7];
72
+ }
73
+ const close = t1;
74
+ const t2 = reduceMotion ? "none" : "fade";
75
+ let t3;
76
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
77
+ t3 = {
78
+ flex: 1
79
+ };
80
+ $[8] = t3;
81
+ } else {
82
+ t3 = $[8];
83
+ }
84
+ let t4;
85
+ if ($[9] !== children) {
86
+ t4 = <View style={t3} pointerEvents="box-none" testID="SelectContent-host">{children}</View>;
87
+ $[9] = children;
88
+ $[10] = t4;
89
+ } else {
90
+ t4 = $[10];
91
+ }
92
+ let t5;
93
+ if ($[11] !== close || $[12] !== t2 || $[13] !== t4) {
94
+ t5 = <Modal visible={true} transparent={true} statusBarTranslucent={true} animationType={t2} onRequestClose={close}>{t4}</Modal>;
95
+ $[11] = close;
96
+ $[12] = t2;
97
+ $[13] = t4;
98
+ $[14] = t5;
99
+ } else {
100
+ t5 = $[14];
101
+ }
102
+ return t5;
103
+ }