@sincpro/mobile-ui 1.0.1 → 2.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 (168) hide show
  1. package/README.md +701 -231
  2. package/dist/Actions/Actions.Button.d.ts +15 -12
  3. package/dist/Actions/Actions.Button.js +25 -14
  4. package/dist/Actions/Actions.Dock.d.ts +20 -0
  5. package/dist/Actions/Actions.Dock.js +89 -0
  6. package/dist/Actions/Actions.FAB.d.ts +2 -1
  7. package/dist/Actions/Actions.FAB.js +5 -3
  8. package/dist/Actions/Actions.FilterButton.d.ts +10 -2
  9. package/dist/Actions/Actions.FilterButton.js +21 -6
  10. package/dist/Actions/Actions.IconButton.d.ts +4 -2
  11. package/dist/Actions/Actions.IconButton.js +7 -3
  12. package/dist/Actions/index.d.ts +6 -2
  13. package/dist/Actions/index.js +4 -1
  14. package/dist/Dialog/BottomSheet/BottomSheet.Root.js +22 -34
  15. package/dist/Dialog/Dialog.ActionSheet.d.ts +2 -1
  16. package/dist/Dialog/Dialog.ActionSheet.js +17 -21
  17. package/dist/Dialog/Dialog.Confirmation.js +8 -6
  18. package/dist/Dialog/Dialog.EditValue.js +3 -1
  19. package/dist/Dialog/Dialog.NativeSheet.d.ts +10 -0
  20. package/dist/Dialog/Dialog.NativeSheet.js +21 -0
  21. package/dist/Dialog/Dialog.Sheet.d.ts +5 -1
  22. package/dist/Dialog/Dialog.Sheet.js +30 -31
  23. package/dist/Display/Display.Accordion.js +7 -3
  24. package/dist/Display/Display.AmountSummary.d.ts +28 -0
  25. package/dist/Display/Display.AmountSummary.js +25 -0
  26. package/dist/Display/Display.Carousel.d.ts +27 -4
  27. package/dist/Display/Display.Carousel.js +112 -12
  28. package/dist/Display/Display.CopyableText.d.ts +9 -2
  29. package/dist/Display/Display.CopyableText.js +75 -7
  30. package/dist/Display/Display.ExpoImage.d.ts +8 -0
  31. package/dist/Display/Display.ExpoImage.js +15 -0
  32. package/dist/Display/Display.Icon.js +2 -1
  33. package/dist/Display/Display.Image.d.ts +10 -6
  34. package/dist/Display/Display.Image.js +39 -6
  35. package/dist/Display/Display.KeyValue.d.ts +11 -4
  36. package/dist/Display/Display.KeyValue.js +6 -4
  37. package/dist/Display/Display.ListGroup.d.ts +23 -0
  38. package/dist/Display/Display.ListGroup.js +17 -0
  39. package/dist/Display/Display.ListItem.d.ts +15 -2
  40. package/dist/Display/Display.ListItem.js +25 -8
  41. package/dist/Display/Display.Logo.d.ts +2 -2
  42. package/dist/Display/Display.Logo.js +3 -2
  43. package/dist/Display/Display.MediaCard.d.ts +2 -2
  44. package/dist/Display/Display.MediaEmbed.d.ts +2 -2
  45. package/dist/Display/Display.ProductCard.d.ts +2 -2
  46. package/dist/Display/Display.SectionHeader.d.ts +11 -1
  47. package/dist/Display/Display.SectionHeader.js +11 -2
  48. package/dist/Display/Display.Story.d.ts +3 -3
  49. package/dist/Display/Display.Story.js +5 -4
  50. package/dist/Display/Display.StoryTray.d.ts +4 -4
  51. package/dist/Display/Display.StoryTray.js +3 -2
  52. package/dist/Display/Display.StoryViewer.d.ts +3 -3
  53. package/dist/Display/Display.StoryViewer.js +6 -3
  54. package/dist/Display/Display.SwipeableRow.d.ts +3 -1
  55. package/dist/Display/Display.SwipeableRow.js +3 -3
  56. package/dist/Display/index.d.ts +13 -0
  57. package/dist/Display/index.js +6 -0
  58. package/dist/Feedback/Feedback.Banner.js +1 -1
  59. package/dist/Feedback/Feedback.DomainSplashScreen.d.ts +13 -4
  60. package/dist/Feedback/Feedback.DomainSplashScreen.js +68 -53
  61. package/dist/Feedback/Feedback.EmptyState.d.ts +2 -2
  62. package/dist/Feedback/Feedback.EmptyState.js +3 -2
  63. package/dist/Feedback/Feedback.Error.d.ts +2 -1
  64. package/dist/Feedback/Feedback.Error.js +4 -3
  65. package/dist/Feedback/Feedback.Loading.d.ts +6 -2
  66. package/dist/Feedback/Feedback.Loading.js +2 -2
  67. package/dist/Feedback/Feedback.Progress.d.ts +6 -3
  68. package/dist/Feedback/Feedback.Progress.js +29 -19
  69. package/dist/Feedback/Feedback.ProgressCircle.d.ts +3 -2
  70. package/dist/Feedback/Feedback.ProgressCircle.js +10 -7
  71. package/dist/Feedback/Feedback.Skeleton.d.ts +4 -4
  72. package/dist/Feedback/Feedback.Skeleton.js +15 -3
  73. package/dist/Feedback/Feedback.Spinner.d.ts +3 -3
  74. package/dist/Feedback/Feedback.Spinner.js +40 -9
  75. package/dist/Feedback/Feedback.Splash.d.ts +2 -2
  76. package/dist/Feedback/Feedback.Splash.js +5 -3
  77. package/dist/Feedback/Toast.context.d.ts +64 -3
  78. package/dist/Feedback/Toast.context.js +112 -31
  79. package/dist/Feedback/index.d.ts +15 -1
  80. package/dist/Feedback/index.js +4 -1
  81. package/dist/Form/Form.Checkbox.d.ts +3 -1
  82. package/dist/Form/Form.Checkbox.js +2 -2
  83. package/dist/Form/Form.DatePicker.js +3 -2
  84. package/dist/Form/Form.Dropdown.d.ts +15 -3
  85. package/dist/Form/Form.Dropdown.js +21 -6
  86. package/dist/Form/Form.ErrorSummary.d.ts +23 -0
  87. package/dist/Form/Form.ErrorSummary.js +53 -0
  88. package/dist/Form/Form.FilterButton.d.ts +1 -1
  89. package/dist/Form/Form.Input.d.ts +4 -3
  90. package/dist/Form/Form.Input.js +2 -2
  91. package/dist/Form/Form.KeyboardForm.d.ts +11 -0
  92. package/dist/Form/Form.KeyboardForm.js +9 -0
  93. package/dist/Form/Form.KeyboardToolbar.d.ts +21 -0
  94. package/dist/Form/Form.KeyboardToolbar.js +70 -0
  95. package/dist/Form/Form.Select.d.ts +2 -1
  96. package/dist/Form/Form.Select.js +26 -26
  97. package/dist/Form/index.d.ts +9 -0
  98. package/dist/Form/index.js +6 -0
  99. package/dist/Navigation/Navigation.AppBar.js +8 -6
  100. package/dist/Navigation/Navigation.BottomNav.js +10 -5
  101. package/dist/Navigation/Navigation.Header.d.ts +2 -2
  102. package/dist/Navigation/Navigation.Menu.js +10 -3
  103. package/dist/Navigation/Navigation.RowItem.d.ts +1 -1
  104. package/dist/Navigation/Navigation.RowItem.js +2 -2
  105. package/dist/Navigation/Navigation.Search.d.ts +41 -0
  106. package/dist/Navigation/Navigation.Search.js +47 -0
  107. package/dist/Navigation/Navigation.SearchBar.d.ts +5 -1
  108. package/dist/Navigation/Navigation.SearchBar.js +25 -7
  109. package/dist/Navigation/Navigation.SearchSuggestions.d.ts +14 -0
  110. package/dist/Navigation/Navigation.SearchSuggestions.js +7 -0
  111. package/dist/Navigation/Navigation.SegmentedControl.d.ts +11 -1
  112. package/dist/Navigation/Navigation.SegmentedControl.js +29 -15
  113. package/dist/Navigation/index.d.ts +13 -0
  114. package/dist/Navigation/index.js +4 -0
  115. package/dist/Typography/Typography.Heading.js +1 -1
  116. package/dist/Typography/Typography.SelectableText.d.ts +10 -0
  117. package/dist/Typography/Typography.SelectableText.js +16 -0
  118. package/dist/Typography/Typography.Text.js +4 -20
  119. package/dist/Typography/index.d.ts +3 -0
  120. package/dist/Typography/index.js +3 -0
  121. package/dist/branding.d.ts +3 -2
  122. package/dist/layouts/AuthContainer.d.ts +4 -1
  123. package/dist/layouts/AuthContainer.js +3 -3
  124. package/dist/primitives/BaseButton.d.ts +15 -12
  125. package/dist/primitives/BaseButton.js +21 -9
  126. package/dist/theme/typography.d.ts +16 -1
  127. package/dist/theme/typography.js +19 -0
  128. package/dist/utils/criteria.d.ts +56 -0
  129. package/dist/utils/criteria.js +99 -0
  130. package/dist/utils/image.d.ts +3 -0
  131. package/dist/utils/image.js +13 -0
  132. package/dist/utils/keys.d.ts +1 -0
  133. package/dist/utils/keys.js +7 -0
  134. package/dist/utils/progress.d.ts +1 -0
  135. package/dist/utils/progress.js +5 -0
  136. package/dist/utils/reorder.d.ts +4 -0
  137. package/dist/utils/reorder.js +29 -0
  138. package/dist/utils/useReducedMotion.d.ts +1 -0
  139. package/dist/utils/useReducedMotion.js +43 -0
  140. package/dist/utils/useSheetTranslation.d.ts +5 -0
  141. package/dist/utils/useSheetTranslation.js +23 -0
  142. package/dist/views/AppSplashView.d.ts +3 -2
  143. package/dist/views/AppSplashView.js +3 -2
  144. package/dist/views/AuthFormView.d.ts +6 -3
  145. package/dist/views/AuthFormView.js +2 -2
  146. package/dist/views/FormViewV2.d.ts +9 -4
  147. package/dist/views/FormViewV2.js +35 -16
  148. package/dist/views/ListViewV2.context.d.ts +3 -1
  149. package/dist/views/ListViewV2.context.js +41 -21
  150. package/dist/views/ListViewV2.d.ts +18 -7
  151. package/dist/views/ListViewV2.js +69 -35
  152. package/dist/views/types/IListView.js +6 -5
  153. package/dist/widgets/CollectionOptions.d.ts +15 -0
  154. package/dist/widgets/CollectionOptions.js +129 -0
  155. package/dist/widgets/FilterBar.d.ts +21 -0
  156. package/dist/widgets/FilterBar.js +14 -0
  157. package/dist/widgets/FilterBuilder.d.ts +10 -0
  158. package/dist/widgets/FilterBuilder.js +115 -0
  159. package/dist/widgets/HomeHeader.d.ts +2 -2
  160. package/dist/widgets/PromoModal.js +3 -1
  161. package/dist/widgets/QueryChoice.d.ts +10 -0
  162. package/dist/widgets/QueryChoice.js +13 -0
  163. package/dist/widgets/ReorderableList.d.ts +51 -0
  164. package/dist/widgets/ReorderableList.js +138 -0
  165. package/dist/widgets/ScreenHeader.d.ts +2 -2
  166. package/dist/widgets/index.d.ts +4 -0
  167. package/dist/widgets/index.js +3 -0
  168. package/package.json +18 -1
@@ -1,5 +1,6 @@
1
1
  import { type VariantProps } from "../theme/tw.js";
2
2
  import type React from "react";
3
+ import type { AccessibilityProps } from "react-native";
3
4
  declare const button: import("tailwind-variants").TVReturnType<{
4
5
  variant: {
5
6
  primary: "bg-accent";
@@ -10,18 +11,18 @@ declare const button: import("tailwind-variants").TVReturnType<{
10
11
  outlineDanger: "bg-transparent border border-danger";
11
12
  outlineBlack: "bg-transparent border border-border-strong";
12
13
  flat: "bg-text-primary/10";
13
- link: "bg-transparent min-h-0";
14
+ link: "bg-transparent";
14
15
  transparent: "bg-transparent border border-border-light";
15
16
  };
16
17
  size: {
17
- small: "py-1.5 px-3 min-h-[36px]";
18
- medium: "py-2.5 px-4 min-h-[44px]";
18
+ small: "py-1.5 px-3 min-h-[48px]";
19
+ medium: "py-2.5 px-4 min-h-[48px]";
19
20
  large: "py-3 px-5 min-h-[48px]";
20
21
  };
21
22
  disabled: {
22
23
  true: "opacity-70";
23
24
  };
24
- }, undefined, "rounded-md items-center justify-center flex-row min-h-[44px]", {
25
+ }, undefined, "rounded-md items-center justify-center flex-row min-h-[48px]", {
25
26
  variant: {
26
27
  primary: "bg-accent";
27
28
  accent: "bg-transparent";
@@ -31,12 +32,12 @@ declare const button: import("tailwind-variants").TVReturnType<{
31
32
  outlineDanger: "bg-transparent border border-danger";
32
33
  outlineBlack: "bg-transparent border border-border-strong";
33
34
  flat: "bg-text-primary/10";
34
- link: "bg-transparent min-h-0";
35
+ link: "bg-transparent";
35
36
  transparent: "bg-transparent border border-border-light";
36
37
  };
37
38
  size: {
38
- small: "py-1.5 px-3 min-h-[36px]";
39
- medium: "py-2.5 px-4 min-h-[44px]";
39
+ small: "py-1.5 px-3 min-h-[48px]";
40
+ medium: "py-2.5 px-4 min-h-[48px]";
40
41
  large: "py-3 px-5 min-h-[48px]";
41
42
  };
42
43
  disabled: {
@@ -52,12 +53,12 @@ declare const button: import("tailwind-variants").TVReturnType<{
52
53
  outlineDanger: "bg-transparent border border-danger";
53
54
  outlineBlack: "bg-transparent border border-border-strong";
54
55
  flat: "bg-text-primary/10";
55
- link: "bg-transparent min-h-0";
56
+ link: "bg-transparent";
56
57
  transparent: "bg-transparent border border-border-light";
57
58
  };
58
59
  size: {
59
- small: "py-1.5 px-3 min-h-[36px]";
60
- medium: "py-2.5 px-4 min-h-[44px]";
60
+ small: "py-1.5 px-3 min-h-[48px]";
61
+ medium: "py-2.5 px-4 min-h-[48px]";
61
62
  large: "py-3 px-5 min-h-[48px]";
62
63
  };
63
64
  disabled: {
@@ -128,7 +129,7 @@ declare const buttonIcon: import("tailwind-variants").TVReturnType<{
128
129
  true: "opacity-70";
129
130
  };
130
131
  }, undefined>>;
131
- export interface ButtonProps extends VariantProps<typeof button> {
132
+ export interface ButtonProps extends VariantProps<typeof button>, AccessibilityProps {
132
133
  title: string;
133
134
  onPress?: () => void;
134
135
  confirm?: string;
@@ -136,14 +137,16 @@ export interface ButtonProps extends VariantProps<typeof button> {
136
137
  disabled?: boolean;
137
138
  className?: string;
138
139
  icon?: React.ReactNode;
140
+ testID?: string;
139
141
  }
140
- export interface ButtonIconProps extends VariantProps<typeof buttonIcon> {
142
+ export interface ButtonIconProps extends VariantProps<typeof buttonIcon>, AccessibilityProps {
141
143
  icon: string;
142
144
  onPress?: () => void;
143
145
  confirm?: string;
144
146
  loading?: boolean;
145
147
  disabled?: boolean;
146
148
  className?: string;
149
+ testID?: string;
147
150
  }
148
151
  declare const ButtonWithIcon: React.FC<ButtonProps> & {
149
152
  Icon: React.FC<ButtonIconProps>;
@@ -6,10 +6,9 @@ import { tv } from "../theme/tw.js";
6
6
  import { Typography } from "../Typography/index.js";
7
7
  import { useCallback } from "react";
8
8
  import { ActivityIndicator, TouchableOpacity, View } from "react-native";
9
- import { runOnJS } from "react-native-reanimated";
10
9
  // ─── Style variants ───────────────────────────────────────────────────────────
11
10
  const button = tv({
12
- base: "rounded-md items-center justify-center flex-row min-h-[44px]",
11
+ base: "rounded-md items-center justify-center flex-row min-h-[48px]",
13
12
  variants: {
14
13
  variant: {
15
14
  primary: "bg-accent",
@@ -20,12 +19,12 @@ const button = tv({
20
19
  outlineDanger: "bg-transparent border border-danger",
21
20
  outlineBlack: "bg-transparent border border-border-strong",
22
21
  flat: "bg-text-primary/10",
23
- link: "bg-transparent min-h-0",
22
+ link: "bg-transparent",
24
23
  transparent: "bg-transparent border border-border-light",
25
24
  },
26
25
  size: {
27
- small: "py-1.5 px-3 min-h-[36px]",
28
- medium: "py-2.5 px-4 min-h-[44px]",
26
+ small: "py-1.5 px-3 min-h-[48px]",
27
+ medium: "py-2.5 px-4 min-h-[48px]",
29
28
  large: "py-3 px-5 min-h-[48px]",
30
29
  },
31
30
  disabled: {
@@ -152,7 +151,7 @@ const textVariantMap = {
152
151
  medium: "button",
153
152
  large: "buttonLarge",
154
153
  };
155
- const Button = ({ title, onPress, confirm, variant = "primary", size = "medium", loading = false, disabled = false, className, icon, }) => {
154
+ const Button = ({ title, onPress, confirm, variant = "primary", size = "medium", loading = false, disabled = false, className, icon, testID, accessibilityLabel, accessibilityState, ...accessibilityProps }) => {
156
155
  const { show, hide } = useConfirmationContext();
157
156
  const textColorClass = textColor({ variant: variant, disabled });
158
157
  const loadingColorValue = getLoadingColor(variant);
@@ -166,22 +165,30 @@ const Button = ({ title, onPress, confirm, variant = "primary", size = "medium",
166
165
  cancelText: "Cancelar",
167
166
  onConfirm: () => {
168
167
  hide();
169
- runOnJS(onPress)();
168
+ onPress();
170
169
  },
171
170
  onCancel: () => hide(),
172
171
  });
173
172
  }
174
173
  else if (onPress) {
175
- runOnJS(onPress)();
174
+ onPress();
176
175
  }
177
176
  }, [onPress, confirm, show, hide]);
178
177
  if (variant === "link") {
179
- return (_jsx(TouchableOpacity, { activeOpacity: 0.7, className: className, disabled: disabled || loading, onPress: handlePress, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Typography.Text, { className: textColorClass, variant: textVariantValue, children: title })) }));
178
+ return (_jsx(TouchableOpacity, { activeOpacity: 0.7, className: className, disabled: disabled || loading, onPress: handlePress, ...accessibilityProps, accessibilityLabel: accessibilityLabel ?? title, accessibilityRole: "button", accessibilityState: {
179
+ ...accessibilityState,
180
+ disabled: disabled || loading,
181
+ busy: loading,
182
+ }, style: { minHeight: 48, minWidth: 48, justifyContent: "center" }, testID: testID, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Typography.Text, { allowFontScaling: true, className: textColorClass, style: { flexShrink: 1 }, variant: textVariantValue, children: title })) }));
180
183
  }
181
184
  const emphasize = variant === "primary" || variant === "cta";
182
- return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: button({ variant, size, disabled, className }), disabled: disabled || loading, onPress: handlePress, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsxs(_Fragment, { children: [icon ? _jsx(View, { className: "mr-2", children: icon }) : null, _jsx(Typography.Text, { allowFontScaling: false, className: textColorClass, ellipsizeMode: "tail", numberOfLines: 1, semibold: emphasize, variant: textVariantValue, children: title })] })) }));
185
+ return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: button({ variant, size, disabled, className }), disabled: disabled || loading, onPress: handlePress, ...accessibilityProps, accessibilityLabel: accessibilityLabel ?? title, accessibilityRole: "button", accessibilityState: {
186
+ ...accessibilityState,
187
+ disabled: disabled || loading,
188
+ busy: loading,
189
+ }, style: { minHeight: 48, minWidth: 48 }, testID: testID, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsxs(_Fragment, { children: [icon ? _jsx(View, { className: "mr-2", children: icon }) : null, _jsx(Typography.Text, { allowFontScaling: true, className: textColorClass, semibold: emphasize, style: { flexShrink: 1 }, variant: textVariantValue, children: title })] })) }));
183
190
  };
184
- const ButtonIcon = ({ icon, onPress, confirm, variant = "primary", size = "medium", loading = false, disabled = false, className, }) => {
191
+ const ButtonIcon = ({ icon, onPress, confirm, variant = "primary", size = "medium", loading = false, disabled = false, className, testID, accessibilityState, ...accessibilityProps }) => {
185
192
  const { show, hide } = useConfirmationContext();
186
193
  const iconColorValue = getIconColor(variant, disabled);
187
194
  const iconSizeValue = iconSizeMap[size] ?? 20;
@@ -195,16 +202,20 @@ const ButtonIcon = ({ icon, onPress, confirm, variant = "primary", size = "mediu
195
202
  cancelText: "Cancelar",
196
203
  onConfirm: () => {
197
204
  hide();
198
- runOnJS(onPress)();
205
+ onPress();
199
206
  },
200
207
  onCancel: () => hide(),
201
208
  });
202
209
  }
203
210
  else if (onPress) {
204
- runOnJS(onPress)();
211
+ onPress();
205
212
  }
206
213
  }, [onPress, confirm, show, hide]);
207
- return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: buttonIcon({ variant, size, disabled, className }), disabled: disabled || loading, onPress: handlePress, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Icon, { color: iconColorValue, name: icon, size: iconSizeValue })) }));
214
+ return (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: buttonIcon({ variant, size, disabled, className }), disabled: disabled || loading, onPress: handlePress, ...accessibilityProps, accessibilityRole: "button", accessibilityState: {
215
+ ...accessibilityState,
216
+ disabled: disabled || loading,
217
+ busy: loading,
218
+ }, style: { minHeight: 48, minWidth: 48 }, testID: testID, children: loading ? (_jsx(ActivityIndicator, { color: loadingColorValue, size: "small" })) : (_jsx(Icon, { color: iconColorValue, name: icon, size: iconSizeValue })) }));
208
219
  };
209
220
  const ButtonWithIcon = Object.assign(Button, { Icon: ButtonIcon });
210
221
  export default ButtonWithIcon;
@@ -0,0 +1,20 @@
1
+ import { type ReactNode } from "react";
2
+ export interface DockProps {
3
+ primaryAction: ReactNode;
4
+ children: ReactNode;
5
+ summary?: ReactNode;
6
+ title?: string;
7
+ moreLabel?: string;
8
+ collapseLabel?: string;
9
+ backdropLabel?: string;
10
+ expanded?: boolean;
11
+ defaultExpanded?: boolean;
12
+ onExpandedChange?: (expanded: boolean) => void;
13
+ dismissOnBackdrop?: boolean;
14
+ maxExpandedHeightRatio?: number;
15
+ placement?: "fixed" | "footer";
16
+ className?: string;
17
+ testID?: string;
18
+ }
19
+ declare function Dock({ primaryAction, children, summary, title, moreLabel, collapseLabel, backdropLabel, expanded: controlledExpanded, defaultExpanded, onExpandedChange, dismissOnBackdrop, maxExpandedHeightRatio, placement, className, testID, }: DockProps): import("react").JSX.Element;
20
+ export default Dock;
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "nativewind/jsx-runtime";
2
+ /* eslint-disable react-hooks/refs */
3
+ import Icon from "../Display/Display.Icon.js";
4
+ import Pressable from "../primitives/Pressable.js";
5
+ import { themeToVars, useTheme } from "../theme/index.js";
6
+ import { cn } from "../theme/tw.js";
7
+ import { Typography } from "../Typography/index.js";
8
+ import { useReducedMotion } from "../utils/useReducedMotion.js";
9
+ import { vars } from "nativewind";
10
+ import { useEffect, useRef, useState } from "react";
11
+ import { Animated, KeyboardAvoidingView, Modal, PanResponder, Platform, ScrollView, useWindowDimensions, View, } from "react-native";
12
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
13
+ function Dock({ primaryAction, children, summary, title = "Más opciones", moreLabel = "Más opciones", collapseLabel = "Ocultar opciones", backdropLabel = "Cerrar panel", expanded: controlledExpanded, defaultExpanded = false, onExpandedChange, dismissOnBackdrop = true, maxExpandedHeightRatio = 0.6, placement = "fixed", className, testID, }) {
14
+ const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);
15
+ const expanded = controlledExpanded ?? internalExpanded;
16
+ const theme = useTheme();
17
+ const reducedMotion = useReducedMotion();
18
+ const insets = useSafeAreaInsets();
19
+ const { height } = useWindowDimensions();
20
+ const [barHeight, setBarHeight] = useState(0);
21
+ const translateY = useRef(new Animated.Value(0)).current;
22
+ const requestExpanded = (next) => {
23
+ if (next === expanded)
24
+ return;
25
+ if (controlledExpanded === undefined)
26
+ setInternalExpanded(next);
27
+ onExpandedChange?.(next);
28
+ };
29
+ const gestureRef = useRef({ expanded, requestExpanded, reducedMotion });
30
+ gestureRef.current = { expanded, requestExpanded, reducedMotion };
31
+ const resolvedRatio = Number.isFinite(maxExpandedHeightRatio)
32
+ ? Math.min(0.9, Math.max(0.1, maxExpandedHeightRatio))
33
+ : 0.6;
34
+ const maxPanelHeight = Math.max(0, Math.min(height * resolvedRatio, height - insets.top - insets.bottom - barHeight));
35
+ const resetDrag = () => {
36
+ translateY.stopAnimation();
37
+ if (gestureRef.current.reducedMotion) {
38
+ translateY.setValue(0);
39
+ return;
40
+ }
41
+ Animated.spring(translateY, {
42
+ toValue: 0,
43
+ useNativeDriver: true,
44
+ damping: 24,
45
+ stiffness: 260,
46
+ }).start();
47
+ };
48
+ useEffect(() => {
49
+ translateY.stopAnimation();
50
+ translateY.setValue(0);
51
+ return () => translateY.stopAnimation();
52
+ }, [expanded, reducedMotion, translateY]);
53
+ const [pan] = useState(() => PanResponder.create({
54
+ onStartShouldSetPanResponder: () => true,
55
+ onPanResponderGrant: () => translateY.stopAnimation(),
56
+ onPanResponderTerminationRequest: () => false,
57
+ onPanResponderMove: (_, gesture) => {
58
+ if (gestureRef.current.expanded)
59
+ translateY.setValue(Math.max(0, gesture.dy));
60
+ },
61
+ onPanResponderRelease: (_, gesture) => {
62
+ const isVertical = Math.abs(gesture.dy) > Math.abs(gesture.dx);
63
+ const shouldChange = gestureRef.current.expanded
64
+ ? gesture.dy > 40 || gesture.vy > 0.5
65
+ : gesture.dy < -40 || gesture.vy < -0.5;
66
+ if (isVertical && shouldChange) {
67
+ gestureRef.current.requestExpanded(!gestureRef.current.expanded);
68
+ }
69
+ resetDrag();
70
+ },
71
+ onPanResponderTerminate: resetDrag,
72
+ }));
73
+ const handle = (_jsx(View, { className: "min-h-12 items-center justify-center", ...pan.panHandlers, testID: testID ? `${testID}-handle` : undefined, children: _jsx(View, { className: "h-1 w-10 rounded-full bg-border-strong" }) }));
74
+ const bar = (_jsxs(View, { className: cn("gap-3 border-t border-border-light bg-bg-card px-4 pb-2", className), onLayout: (event) => setBarHeight(event.nativeEvent.layout.height), testID: testID ? `${testID}-bar` : undefined, children: [!expanded ? handle : null, summary, _jsxs(View, { className: "flex-row items-center gap-3", children: [_jsxs(Pressable, { accessibilityLabel: expanded ? collapseLabel : moreLabel, accessibilityRole: "button", accessibilityState: { expanded }, className: "min-h-12 flex-1 flex-row items-center justify-center gap-1 rounded-lg bg-bg-muted px-3", onPress: () => requestExpanded(!expanded), testID: testID ? `${testID}-more` : undefined, children: [_jsx(Typography.Text, { className: "text-text-primary", variant: "buttonSmall", children: expanded ? collapseLabel : moreLabel }), _jsx(Icon, { color: theme.icon.secondary, name: expanded ? "chevron-down" : "chevron-up", size: 16 })] }), _jsx(View, { className: "flex-1", children: primaryAction })] })] }));
75
+ return (_jsxs(_Fragment, { children: [_jsx(View, { className: cn(placement === "fixed" && "absolute bottom-0 left-0 right-0 z-20"), style: expanded ? { height: barHeight } : undefined, testID: testID, children: !expanded ? bar : null }), _jsx(Modal, { animationType: "none", onRequestClose: () => requestExpanded(false), presentationStyle: "overFullScreen", testID: testID ? `${testID}-modal` : undefined, transparent: true, visible: expanded, children: _jsx(KeyboardAvoidingView, { behavior: Platform.OS === "ios" ? "padding" : "height", style: { flex: 1 }, testID: testID ? `${testID}-keyboard` : undefined, children: _jsxs(View, { accessibilityViewIsModal: true, style: { flex: 1, justifyContent: "flex-end" }, children: [_jsx(Pressable, { accessibilityLabel: backdropLabel, accessibilityRole: "button", className: "absolute inset-0 bg-black/50", disabled: !dismissOnBackdrop, onPress: dismissOnBackdrop ? () => requestExpanded(false) : undefined, testID: testID ? `${testID}-backdrop` : undefined }), _jsxs(View, { onAccessibilityEscape: () => requestExpanded(false), style: [
76
+ vars(themeToVars(theme)),
77
+ {
78
+ paddingBottom: insets.bottom,
79
+ backgroundColor: theme.bg.card,
80
+ maxHeight: height - insets.top,
81
+ flexShrink: 1,
82
+ },
83
+ ], children: [_jsx(View, { style: { overflow: "hidden", flexShrink: 1 }, children: _jsxs(Animated.View, { style: {
84
+ maxHeight: maxPanelHeight,
85
+ flexShrink: 1,
86
+ transform: [{ translateY }],
87
+ }, testID: testID ? `${testID}-expanded-content` : undefined, children: [handle, _jsxs(ScrollView, { contentContainerStyle: { paddingHorizontal: 16, paddingBottom: 16 }, keyboardShouldPersistTaps: "handled", nestedScrollEnabled: true, style: { flexShrink: 1 }, testID: testID ? `${testID}-scroll` : undefined, children: [title ? (_jsx(Typography.Text, { accessibilityRole: "header", className: "pb-2 text-text-primary", semibold: true, variant: "subtitle", children: title })) : null, children] })] }) }), bar] })] }) }) })] }));
88
+ }
89
+ export default Dock;
@@ -5,6 +5,7 @@ export interface FABProps {
5
5
  position?: "bottom-right" | "bottom-left";
6
6
  className?: string;
7
7
  testID?: string;
8
+ accessibilityLabel?: string;
8
9
  }
9
- declare function FAB({ icon, onPress, label, position, className, testID, }: FABProps): import("react").JSX.Element;
10
+ declare function FAB({ icon, onPress, label, position, className, testID, accessibilityLabel, }: FABProps): import("react").JSX.Element;
10
11
  export default FAB;
@@ -5,13 +5,15 @@ import { theme } from "../theme/index.js";
5
5
  import { cn } from "../theme/tw.js";
6
6
  import { Typography } from "../Typography/index.js";
7
7
  import { useSafeAreaInsets } from "react-native-safe-area-context";
8
- function FAB({ icon, onPress, label, position = "bottom-right", className, testID, }) {
8
+ function FAB({ icon, onPress, label, position = "bottom-right", className, testID, accessibilityLabel, }) {
9
9
  const insets = useSafeAreaInsets();
10
- return (_jsxs(Pressable, { accessibilityLabel: label ?? "Acción", accessibilityRole: "button", className: cn("absolute flex-row items-center justify-center rounded-full bg-primary", label ? "h-14 px-5 gap-2" : "w-14 h-14", className), onPress: onPress, style: {
10
+ return (_jsxs(Pressable, { accessibilityLabel: accessibilityLabel ?? label ?? "Acción", accessibilityRole: "button", className: cn("absolute flex-row items-center justify-center rounded-full bg-primary", label ? "min-h-14 px-5 py-3 gap-2" : "w-14 h-14", className), onPress: onPress, style: {
11
+ minHeight: 56,
12
+ minWidth: 56,
11
13
  bottom: insets.bottom + 16,
12
14
  right: position === "bottom-right" ? 16 : undefined,
13
15
  left: position === "bottom-left" ? 16 : undefined,
14
16
  ...theme.shadow.lg,
15
- }, testID: testID, children: [_jsx(Icon, { color: theme.icon.inverse, name: icon, size: 24 }), label ? (_jsx(Typography.Text, { className: "text-text-on-primary font-semibold", children: label })) : null] }));
17
+ }, testID: testID, children: [_jsx(Icon, { color: theme.icon.inverse, name: icon, size: 24 }), label ? (_jsx(Typography.Text, { className: "text-text-on-primary font-semibold", style: { flexShrink: 1 }, children: label })) : null] }));
16
18
  }
17
19
  export default FAB;
@@ -3,8 +3,16 @@ export interface FilterButtonProps {
3
3
  title: string;
4
4
  active: boolean;
5
5
  onPress: () => void;
6
+ variant?: "default" | "mobile";
7
+ disabled?: boolean;
8
+ className?: string;
9
+ testID?: string;
6
10
  }
7
11
  export declare const FilterButton: FC<FilterButtonProps>;
8
- export declare function FilterButtonGroup({ children }: {
12
+ export interface FilterButtonGroupProps {
9
13
  children: ReactNode;
10
- }): import("react").JSX.Element;
14
+ layout?: "row" | "scroll" | "wrap";
15
+ className?: string;
16
+ testID?: string;
17
+ }
18
+ export declare function FilterButtonGroup({ children, layout, className, testID, }: FilterButtonGroupProps): import("react").JSX.Element;
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx } from "nativewind/jsx-runtime";
2
- import { tv } from "../theme/tw.js";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import Icon from "../Display/Display.Icon.js";
3
+ import Pressable from "../primitives/Pressable.js";
4
+ import { useTheme } from "../theme/index.js";
5
+ import { cn, tv } from "../theme/tw.js";
3
6
  import { Typography } from "../Typography/index.js";
4
- import { TouchableOpacity, View } from "react-native";
7
+ import { ScrollView, TouchableOpacity, View } from "react-native";
5
8
  const filterButton = tv({
6
9
  base: "rounded-lg items-center justify-center py-2 px-3 min-h-[36px]",
7
10
  variants: {
@@ -22,7 +25,19 @@ const filterText = tv({
22
25
  },
23
26
  defaultVariants: { active: false },
24
27
  });
25
- export const FilterButton = ({ title, active, onPress }) => (_jsx(TouchableOpacity, { activeOpacity: 0.8, className: filterButton({ active }), onPress: onPress, children: _jsx(Typography.Text, { className: filterText({ active }), variant: "buttonSmall", children: title }) }));
26
- export function FilterButtonGroup({ children }) {
27
- return _jsx(View, { className: "flex-row gap-2 p-3", children: children });
28
+ export const FilterButton = ({ title, active, onPress, variant = "default", disabled = false, className, testID, }) => {
29
+ const theme = useTheme();
30
+ if (variant === "mobile") {
31
+ return (_jsxs(Pressable, { accessibilityLabel: title, accessibilityRole: "button", accessibilityState: { selected: active, disabled }, activeOpacity: 1 - theme.state.press, className: cn("flex-row items-center self-start rounded-full px-3 py-2 gap-2 max-w-full", active ? "bg-container-primary" : "bg-bg-muted", className), disabled: disabled, onPress: onPress, style: {
32
+ minHeight: 48,
33
+ minWidth: 48,
34
+ }, testID: testID, children: [active ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: _jsx(Icon, { color: theme.container.onPrimary, name: "checkmark", size: 18 }) })) : null, _jsx(Typography.Text, { className: cn("flex-shrink", active ? "text-container-on-primary" : "text-text-primary"), variant: "bodyLarge", children: title })] }));
35
+ }
36
+ return (_jsx(TouchableOpacity, { accessibilityLabel: title, accessibilityRole: "button", accessibilityState: { selected: active, disabled }, activeOpacity: 0.8, className: filterButton({ active, className }), disabled: disabled, onPress: onPress, testID: testID, children: _jsx(Typography.Text, { className: filterText({ active }), variant: "buttonSmall", children: title }) }));
37
+ };
38
+ export function FilterButtonGroup({ children, layout = "row", className, testID, }) {
39
+ if (layout === "scroll") {
40
+ return (_jsx(ScrollView, { className: cn("py-1", className), contentContainerStyle: { gap: 8 }, horizontal: true, keyboardShouldPersistTaps: "handled", showsHorizontalScrollIndicator: false, testID: testID, children: children }));
41
+ }
42
+ return (_jsx(View, { className: cn("flex-row gap-2 p-3", layout === "wrap" && "flex-wrap", className), testID: testID, children: children }));
28
43
  }
@@ -1,5 +1,6 @@
1
1
  import { type VariantProps } from "../theme/tw.js";
2
2
  import { IconType } from "../utils/icon.js";
3
+ import type { AccessibilityProps } from "react-native";
3
4
  declare const iconButton: import("tailwind-variants").TVReturnType<{
4
5
  variant: {
5
6
  primary: "bg-primary";
@@ -55,13 +56,14 @@ declare const iconButton: import("tailwind-variants").TVReturnType<{
55
56
  true: "opacity-50";
56
57
  };
57
58
  }, undefined>>;
58
- export interface IconButtonProps extends VariantProps<typeof iconButton> {
59
+ export interface IconButtonProps extends VariantProps<typeof iconButton>, AccessibilityProps {
59
60
  icon?: string;
60
61
  type?: IconType;
61
62
  onPress: () => void;
62
63
  loading?: boolean;
63
64
  iconColor?: string;
64
65
  className?: string;
66
+ testID?: string;
65
67
  }
66
- declare function IconButton({ icon, type, onPress, variant, size, loading, disabled, rounded, iconColor, className, }: IconButtonProps): import("react").JSX.Element;
68
+ declare function IconButton({ icon, type, onPress, variant, size, loading, disabled, rounded, iconColor, className, testID, accessibilityState, ...accessibilityProps }: IconButtonProps): import("react").JSX.Element;
67
69
  export default IconButton;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "nativewind/jsx-runtime";
2
- import { Display } from "../Display/index.js";
2
+ import Icon from "../Display/Display.Icon.js";
3
3
  import { theme } from "../theme/index.js";
4
4
  import { tv } from "../theme/tw.js";
5
5
  import { ActivityIndicator, TouchableOpacity } from "react-native";
@@ -31,8 +31,12 @@ const iconButton = tv({
31
31
  disabled: false,
32
32
  },
33
33
  });
34
- function IconButton({ icon, type = "feather", onPress, variant = "ghost", size = "medium", loading = false, disabled = false, rounded = false, iconColor, className, }) {
34
+ function IconButton({ icon, type = "feather", onPress, variant = "ghost", size = "medium", loading = false, disabled = false, rounded = false, iconColor, className, testID, accessibilityState, ...accessibilityProps }) {
35
35
  const resolvedColor = iconColor ?? theme.text.accent;
36
- return (_jsx(TouchableOpacity, { activeOpacity: 0.7, className: iconButton({ variant, size, rounded, disabled, className }), disabled: disabled || loading, onPress: onPress, children: loading ? (_jsx(ActivityIndicator, { color: resolvedColor, size: "small" })) : (_jsx(Display.Icon, { color: resolvedColor, name: icon, size: 24, type: type })) }));
36
+ return (_jsx(TouchableOpacity, { activeOpacity: 0.7, className: iconButton({ variant, size, rounded, disabled, className }), disabled: disabled || loading, onPress: onPress, ...accessibilityProps, accessibilityRole: "button", accessibilityState: {
37
+ ...accessibilityState,
38
+ disabled: disabled || loading,
39
+ busy: loading,
40
+ }, style: { minHeight: 48, minWidth: 48 }, testID: testID, children: loading ? (_jsx(ActivityIndicator, { color: resolvedColor, size: "small" })) : (_jsx(Icon, { color: resolvedColor, name: icon, size: 24, type: type })) }));
37
41
  }
38
42
  export default IconButton;
@@ -1,3 +1,4 @@
1
+ import Dock from "./Actions.Dock.js";
1
2
  import FAB from "./Actions.FAB.js";
2
3
  import { FilterButtonGroup } from "./Actions.FilterButton.js";
3
4
  import IconButton from "./Actions.IconButton.js";
@@ -6,17 +7,20 @@ export declare const Actions: {
6
7
  Button: import("react").FC<import("./Actions.Button.js").ButtonProps> & {
7
8
  Icon: import("react").FC<import("./Actions.Button.js").ButtonIconProps>;
8
9
  };
10
+ /** Compact primary-action dock with additional options in a dismissible sheet. */
11
+ Dock: typeof Dock;
9
12
  /** Small icon-only tap target — ghost, primary, secondary, tertiary variants. */
10
13
  IconButton: typeof IconButton;
11
14
  /** Floating Action Button — fixed bottom-right/left, label-optional. */
12
15
  FAB: typeof FAB;
13
16
  /** Chip-style active/inactive toggle — use inside `Actions.FilterButtonGroup`. */
14
17
  FilterButton: import("react").FC<import("./Actions.FilterButton.js").FilterButtonProps>;
15
- /** Horizontal scroll container for `Actions.FilterButton` chips. */
18
+ /** Filter chip layout; opt into horizontal scrolling or wrapping with `layout`. */
16
19
  FilterButtonGroup: typeof FilterButtonGroup;
17
20
  };
18
21
  export type { ButtonIconProps, ButtonProps } from "./Actions.Button.js";
22
+ export type { DockProps } from "./Actions.Dock.js";
19
23
  export type { FABProps } from "./Actions.FAB.js";
20
- export type { FilterButtonProps } from "./Actions.FilterButton.js";
24
+ export type { FilterButtonGroupProps, FilterButtonProps, } from "./Actions.FilterButton.js";
21
25
  export type { IconButtonProps } from "./Actions.IconButton.js";
22
26
  export default Actions;
@@ -1,17 +1,20 @@
1
1
  import ButtonWithIcon from "./Actions.Button.js";
2
+ import Dock from "./Actions.Dock.js";
2
3
  import FAB from "./Actions.FAB.js";
3
4
  import { FilterButton, FilterButtonGroup, } from "./Actions.FilterButton.js";
4
5
  import IconButton from "./Actions.IconButton.js";
5
6
  export const Actions = {
6
7
  /** Primary action button. The filled one is gold; navy is text. Supports confirm dialog. */
7
8
  Button: ButtonWithIcon,
9
+ /** Compact primary-action dock with additional options in a dismissible sheet. */
10
+ Dock,
8
11
  /** Small icon-only tap target — ghost, primary, secondary, tertiary variants. */
9
12
  IconButton,
10
13
  /** Floating Action Button — fixed bottom-right/left, label-optional. */
11
14
  FAB,
12
15
  /** Chip-style active/inactive toggle — use inside `Actions.FilterButtonGroup`. */
13
16
  FilterButton,
14
- /** Horizontal scroll container for `Actions.FilterButton` chips. */
17
+ /** Filter chip layout; opt into horizontal scrolling or wrapping with `layout`. */
15
18
  FilterButtonGroup,
16
19
  };
17
20
  export default Actions;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
2
  /* eslint-disable react-hooks/refs */
3
3
  import { theme } from "../../theme/index.js";
4
- import { createContext, useContext, useEffect, useRef } from "react";
4
+ import { useSheetTranslation } from "../../utils/useSheetTranslation.js";
5
+ import { createContext, useContext, useRef } from "react";
5
6
  import { Animated, Dimensions, Modal, PanResponder, Pressable, ScrollView, Text, View, } from "react-native";
6
7
  import { useSafeAreaInsets } from "react-native-safe-area-context";
7
8
  const BottomSheetContext = createContext(null);
@@ -98,27 +99,17 @@ const SIZE_MAP = {
98
99
  function Root({ visible, onClose, size = "auto", dismissible = true, children }) {
99
100
  const insets = useSafeAreaInsets();
100
101
  const screenHeight = Dimensions.get("window").height;
101
- const translateY = useRef(new Animated.Value(screenHeight)).current;
102
+ const { translateY, reducedMotion } = useSheetTranslation(visible, screenHeight);
103
+ const gesture = useRef({ dismissible, onClose, reducedMotion });
104
+ gesture.current = { dismissible, onClose, reducedMotion };
102
105
  const maxHeight = size === "auto" ? screenHeight * 0.9 : screenHeight * SIZE_MAP[size];
103
106
  const minHeight = size === "auto" ? 0 : screenHeight * SIZE_MAP[size];
104
- useEffect(() => {
105
- if (visible) {
106
- Animated.spring(translateY, {
107
- toValue: 0,
108
- useNativeDriver: true,
109
- damping: 20,
110
- stiffness: 300,
111
- }).start();
112
- }
113
- else {
114
- translateY.setValue(screenHeight);
115
- }
116
- }, [visible, screenHeight, translateY]);
117
107
  const panResponder = useRef(PanResponder.create({
118
- onStartShouldSetPanResponder: () => dismissible,
108
+ onStartShouldSetPanResponder: () => gesture.current.dismissible,
119
109
  onMoveShouldSetPanResponder: (_, gestureState) => {
120
- return dismissible && Math.abs(gestureState.dy) > 10;
110
+ return gesture.current.dismissible && Math.abs(gestureState.dy) > 10;
121
111
  },
112
+ onPanResponderGrant: () => translateY.stopAnimation(),
122
113
  onPanResponderMove: (_, gestureState) => {
123
114
  if (gestureState.dy > 0) {
124
115
  translateY.setValue(gestureState.dy);
@@ -126,36 +117,33 @@ function Root({ visible, onClose, size = "auto", dismissible = true, children })
126
117
  },
127
118
  onPanResponderRelease: (_, gestureState) => {
128
119
  if (gestureState.dy > 100 || gestureState.vy > 0.5) {
129
- Animated.timing(translateY, {
130
- toValue: screenHeight,
131
- duration: 200,
132
- useNativeDriver: true,
133
- }).start(() => onClose());
120
+ translateY.stopAnimation();
121
+ gesture.current.onClose();
134
122
  }
135
123
  else {
136
- Animated.spring(translateY, {
137
- toValue: 0,
138
- useNativeDriver: true,
139
- damping: 20,
140
- stiffness: 300,
141
- }).start();
124
+ if (gesture.current.reducedMotion)
125
+ translateY.setValue(0);
126
+ else
127
+ Animated.spring(translateY, {
128
+ toValue: 0,
129
+ useNativeDriver: true,
130
+ damping: 20,
131
+ stiffness: 300,
132
+ }).start();
142
133
  }
143
134
  },
144
135
  })).current;
145
136
  function handleBackdropPress() {
146
137
  if (dismissible) {
147
- Animated.timing(translateY, {
148
- toValue: screenHeight,
149
- duration: 200,
150
- useNativeDriver: true,
151
- }).start(() => onClose());
138
+ translateY.stopAnimation();
139
+ onClose();
152
140
  }
153
141
  }
154
142
  const contextValue = {
155
143
  close: onClose,
156
144
  panHandlers: panResponder.panHandlers,
157
145
  };
158
- return (_jsx(Modal, { animationType: "fade", onRequestClose: onClose, presentationStyle: "overFullScreen", transparent: true, visible: visible, children: _jsxs(View, { className: "flex-1 bg-black/50", children: [_jsx(Pressable, { className: "flex-1", onPress: handleBackdropPress }), _jsx(Animated.View, { className: "rounded-t-3xl overflow-hidden", style: {
146
+ return (_jsx(Modal, { animationType: reducedMotion ? "none" : "fade", onRequestClose: onClose, presentationStyle: "overFullScreen", transparent: true, visible: visible, children: _jsxs(View, { className: "flex-1 bg-black/50", children: [_jsx(Pressable, { className: "flex-1", onPress: handleBackdropPress }), _jsx(Animated.View, { className: "rounded-t-3xl overflow-hidden", style: {
159
147
  backgroundColor: theme.bg.popover,
160
148
  maxHeight,
161
149
  minHeight: minHeight || undefined,
@@ -12,6 +12,7 @@ export interface ActionSheetProps {
12
12
  title?: string;
13
13
  message?: string;
14
14
  cancelLabel?: string;
15
+ testID?: string;
15
16
  }
16
- declare function ActionSheet({ visible, onClose, actions, title, message, cancelLabel, }: ActionSheetProps): import("react").JSX.Element;
17
+ declare function ActionSheet({ visible, onClose, actions, title, message, cancelLabel, testID, }: ActionSheetProps): import("react").JSX.Element;
17
18
  export default ActionSheet;