@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,13 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import ExpoImage from "./Display.ExpoImage.js";
2
3
  import Icon from "./Display.Icon.js";
3
4
  import Pressable from "../primitives/Pressable.js";
4
5
  import { theme } from "../theme/index.js";
5
6
  import { Typography } from "../Typography/index.js";
7
+ import { useReducedMotion } from "../utils/useReducedMotion.js";
6
8
  import { LinearGradient } from "expo-linear-gradient";
7
- import { Image, Modal, Pressable as RNPressable, View, } from "react-native";
9
+ import { Modal, Pressable as RNPressable, View } from "react-native";
8
10
  import { useSafeAreaInsets } from "react-native-safe-area-context";
9
11
  function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, subtitle, time, avatar, progress = 1, muted, paused, onToggleMute, onTogglePause, onMore, footer, testID, }) {
10
12
  const insets = useSafeAreaInsets();
13
+ const reducedMotion = useReducedMotion();
11
14
  const current = slides[index];
12
15
  const goPrev = () => {
13
16
  if (index > 0)
@@ -21,7 +24,7 @@ function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, su
21
24
  };
22
25
  if (!current)
23
26
  return null;
24
- return (_jsx(Modal, { animationType: "fade", onRequestClose: onClose, statusBarTranslucent: true, transparent: false, visible: visible, children: _jsxs(View, { style: { flex: 1, backgroundColor: "#000" }, testID: testID, children: [_jsx(Image, { resizeMode: "contain", source: current.image, style: {
27
+ return (_jsx(Modal, { animationType: reducedMotion ? "none" : "fade", onRequestClose: onClose, statusBarTranslucent: true, transparent: false, visible: visible, children: _jsxs(View, { style: { flex: 1, backgroundColor: "#000" }, testID: testID, children: [_jsx(ExpoImage, { contentFit: "contain", source: current.image, style: {
25
28
  position: "absolute",
26
29
  top: 0,
27
30
  left: 0,
@@ -57,7 +60,7 @@ function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, su
57
60
  ? `${Math.round(progress * 100)}%`
58
61
  : "0%",
59
62
  backgroundColor: "#fff",
60
- } }) }, i))) }), _jsxs(View, { style: { flexDirection: "row", alignItems: "center", marginTop: 12 }, children: [avatar ? (_jsx(Image, { source: avatar, style: { width: 36, height: 36, borderRadius: 18, marginRight: 8 } })) : null, _jsxs(View, { style: { flex: 1 }, children: [_jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 6 }, children: [_jsx(Typography.Text, { className: "text-white", semibold: true, variant: "body", children: title }), time ? (_jsx(Typography.Text, { style: { color: "rgba(255,255,255,0.7)" }, variant: "caption", children: time })) : null] }), subtitle ? (_jsx(Typography.Text, { numberOfLines: 1, style: { color: "rgba(255,255,255,0.8)" }, variant: "caption", children: subtitle })) : null] }), onToggleMute ? (_jsx(Pressable, { accessibilityLabel: muted ? "Activar sonido" : "Silenciar", hitSlop: 8, onPress: onToggleMute, children: _jsx(Icon, { color: "#fff", name: muted ? "volume-mute" : "volume-high", size: 22 }) })) : null, onTogglePause ? (_jsx(Pressable, { accessibilityLabel: paused ? "Reanudar" : "Pausar", hitSlop: 8, onPress: onTogglePause, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: paused ? "play" : "pause", size: 22 }) })) : null, onMore ? (_jsx(Pressable, { accessibilityLabel: "M\u00E1s opciones", hitSlop: 8, onPress: onMore, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: "ellipsis-horizontal", size: 22 }) })) : null, _jsx(Pressable, { accessibilityLabel: "Cerrar", hitSlop: 8, onPress: onClose, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: "close", size: 24 }) })] })] }), index < slides.length - 1 ? (_jsx(Pressable, { accessibilityLabel: "Siguiente", onPress: goNext, style: {
63
+ } }) }, i))) }), _jsxs(View, { style: { flexDirection: "row", alignItems: "center", marginTop: 12 }, children: [avatar ? (_jsx(ExpoImage, { source: avatar, style: { width: 36, height: 36, borderRadius: 18, marginRight: 8 } })) : null, _jsxs(View, { style: { flex: 1 }, children: [_jsxs(View, { style: { flexDirection: "row", alignItems: "center", gap: 6 }, children: [_jsx(Typography.Text, { className: "text-white", semibold: true, variant: "body", children: title }), time ? (_jsx(Typography.Text, { style: { color: "rgba(255,255,255,0.7)" }, variant: "caption", children: time })) : null] }), subtitle ? (_jsx(Typography.Text, { numberOfLines: 1, style: { color: "rgba(255,255,255,0.8)" }, variant: "caption", children: subtitle })) : null] }), onToggleMute ? (_jsx(Pressable, { accessibilityLabel: muted ? "Activar sonido" : "Silenciar", hitSlop: 8, onPress: onToggleMute, children: _jsx(Icon, { color: "#fff", name: muted ? "volume-mute" : "volume-high", size: 22 }) })) : null, onTogglePause ? (_jsx(Pressable, { accessibilityLabel: paused ? "Reanudar" : "Pausar", hitSlop: 8, onPress: onTogglePause, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: paused ? "play" : "pause", size: 22 }) })) : null, onMore ? (_jsx(Pressable, { accessibilityLabel: "M\u00E1s opciones", hitSlop: 8, onPress: onMore, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: "ellipsis-horizontal", size: 22 }) })) : null, _jsx(Pressable, { accessibilityLabel: "Cerrar", hitSlop: 8, onPress: onClose, style: { marginLeft: 14 }, children: _jsx(Icon, { color: "#fff", name: "close", size: 24 }) })] })] }), index < slides.length - 1 ? (_jsx(Pressable, { accessibilityLabel: "Siguiente", onPress: goNext, style: {
61
64
  position: "absolute",
62
65
  right: 8,
63
66
  top: "50%",
@@ -7,9 +7,11 @@ export interface SwipeRowAction {
7
7
  }
8
8
  export interface SwipeableRowProps {
9
9
  children: ReactNode;
10
+ /** Visible alternative for essential swipe actions. */
11
+ visibleActions?: ReactNode;
10
12
  rightActions?: SwipeRowAction[];
11
13
  leftActions?: SwipeRowAction[];
12
14
  testID?: string;
13
15
  }
14
- declare function SwipeableRow({ children, rightActions, leftActions, testID }: SwipeableRowProps): import("react").JSX.Element;
16
+ declare function SwipeableRow({ children, visibleActions, rightActions, leftActions, testID, }: SwipeableRowProps): import("react").JSX.Element;
15
17
  export default SwipeableRow;
@@ -17,13 +17,13 @@ function ActionButtons({ actions, onDone, }) {
17
17
  paddingHorizontal: 20,
18
18
  }, children: [action.icon ? (_jsx(Icon, { color: theme.text.inverse, name: action.icon, size: 20 })) : null, action.label ? (_jsx(Typography.Text, { className: "text-text-inverse text-xs mt-1", children: action.label })) : null] }, index))) }));
19
19
  }
20
- function SwipeableRow({ children, rightActions, leftActions, testID }) {
20
+ function SwipeableRow({ children, visibleActions, rightActions, leftActions, testID, }) {
21
21
  const ref = useRef(null);
22
22
  const close = () => ref.current?.close();
23
- return (_jsx(Swipeable, { ref: ref, renderLeftActions: leftActions?.length
23
+ return (_jsxs(Swipeable, { ref: ref, renderLeftActions: leftActions?.length
24
24
  ? () => _jsx(ActionButtons, { actions: leftActions, onDone: close })
25
25
  : undefined, renderRightActions: rightActions?.length
26
26
  ? () => _jsx(ActionButtons, { actions: rightActions, onDone: close })
27
- : undefined, testID: testID, children: children }));
27
+ : undefined, testID: testID, children: [children, visibleActions ? _jsx(View, { className: "flex-row", children: visibleActions }) : null] }));
28
28
  }
29
29
  export default SwipeableRow;
@@ -8,10 +8,12 @@ import CountRecords from "./Display.CountRecords.js";
8
8
  import DataTable from "./Display.DataTable.js";
9
9
  import Date from "./Display.Date.js";
10
10
  import Divider from "./Display.Divider.js";
11
+ import ExpoImage from "./Display.ExpoImage.js";
11
12
  import GradientSurface from "./Display.GradientSurface.js";
12
13
  import IconBadge from "./Display.IconBadge.js";
13
14
  import DisplayImage from "./Display.Image.js";
14
15
  import KeyValue from "./Display.KeyValue.js";
16
+ import ListGroup from "./Display.ListGroup.js";
15
17
  import ListItem from "./Display.ListItem.js";
16
18
  import MediaCard from "./Display.MediaCard.js";
17
19
  import MediaEmbed from "./Display.MediaEmbed.js";
@@ -36,6 +38,11 @@ import Tag from "./Display.Tag.js";
36
38
  import Timeline from "./Display.Timeline.js";
37
39
  import Tooltip from "./Display.Tooltip.js";
38
40
  export declare const Display: {
41
+ AmountSummary: {
42
+ Root: ({ children, currencySymbol, variant, className, testID, }: import("./Display.AmountSummary.js").AmountSummaryRootProps) => import("react").JSX.Element;
43
+ Row: ({ label, value, currencySymbol, prefix, className, labelClassName, valueClassName, testID, }: import("./Display.AmountSummary.js").AmountSummaryRowProps) => import("react").JSX.Element;
44
+ Total: (props: import("./Display.AmountSummary.js").AmountSummaryTotalProps) => import("react").JSX.Element;
45
+ };
39
46
  Badge: typeof Badge;
40
47
  BadgeVariants: typeof BadgeVariants;
41
48
  Accordion: (({ children, className }: {
@@ -60,12 +67,14 @@ export declare const Display: {
60
67
  Chip: typeof Chip;
61
68
  Tag: typeof Tag;
62
69
  Image: typeof DisplayImage;
70
+ ExpoImage: typeof ExpoImage;
63
71
  MediaCard: typeof MediaCard;
64
72
  MediaEmbed: typeof MediaEmbed;
65
73
  Story: typeof Story;
66
74
  StoryTray: typeof StoryTray;
67
75
  StoryViewer: typeof StoryViewer;
68
76
  ListItem: typeof ListItem;
77
+ ListGroup: typeof ListGroup;
69
78
  KeyValue: typeof KeyValue;
70
79
  DataTable: typeof DataTable;
71
80
  Stat: typeof Stat;
@@ -95,7 +104,11 @@ export declare const Display: {
95
104
  Pattern: typeof Pattern;
96
105
  };
97
106
  export { type BadgeProps, BadgeVariants };
107
+ export type { AmountSummaryRootProps, AmountSummaryRowProps, AmountSummaryTotalProps, } from "./Display.AmountSummary.js";
108
+ export type { CarouselControlsProps, CarouselProps, } from "./Display.Carousel.js";
98
109
  export type { CircleButtonProps } from "./Display.CircleButton.js";
110
+ export type { ListGroupProps } from "./Display.ListGroup.js";
111
+ export type { ListItemProps } from "./Display.ListItem.js";
99
112
  export type { MenuCardProps } from "./Display.MenuCard.js";
100
113
  export type { MenuGridItem } from "./Display.MenuGrid.js";
101
114
  export default Display;
@@ -1,4 +1,5 @@
1
1
  import Accordion from "./Display.Accordion.js";
2
+ import AmountSummary from "./Display.AmountSummary.js";
2
3
  import Avatar from "./Display.Avatar.js";
3
4
  import AvatarGroup from "./Display.AvatarGroup.js";
4
5
  import Badge, { BadgeVariants, } from "./Display.Badge.js";
@@ -11,11 +12,13 @@ import CountRecords from "./Display.CountRecords.js";
11
12
  import DataTable from "./Display.DataTable.js";
12
13
  import Date from "./Display.Date.js";
13
14
  import Divider from "./Display.Divider.js";
15
+ import ExpoImage from "./Display.ExpoImage.js";
14
16
  import GradientSurface from "./Display.GradientSurface.js";
15
17
  import Icon from "./Display.Icon.js";
16
18
  import IconBadge from "./Display.IconBadge.js";
17
19
  import DisplayImage from "./Display.Image.js";
18
20
  import KeyValue from "./Display.KeyValue.js";
21
+ import ListGroup from "./Display.ListGroup.js";
19
22
  import ListItem from "./Display.ListItem.js";
20
23
  import Logo from "./Display.Logo.js";
21
24
  import MediaCard from "./Display.MediaCard.js";
@@ -41,6 +44,7 @@ import Tag from "./Display.Tag.js";
41
44
  import Timeline from "./Display.Timeline.js";
42
45
  import Tooltip from "./Display.Tooltip.js";
43
46
  export const Display = {
47
+ AmountSummary,
44
48
  Badge,
45
49
  BadgeVariants,
46
50
  Accordion,
@@ -51,12 +55,14 @@ export const Display = {
51
55
  Chip,
52
56
  Tag,
53
57
  Image: DisplayImage,
58
+ ExpoImage,
54
59
  MediaCard,
55
60
  MediaEmbed,
56
61
  Story,
57
62
  StoryTray,
58
63
  StoryViewer,
59
64
  ListItem,
65
+ ListGroup,
60
66
  KeyValue,
61
67
  DataTable,
62
68
  Stat,
@@ -30,6 +30,6 @@ const iconByTone = {
30
30
  function Banner({ message, title, tone = "info", onClose, action, className, testID, }) {
31
31
  const styles = banner({ tone });
32
32
  const icon = iconByTone[tone ?? "info"];
33
- return (_jsxs(View, { className: styles.root({ className }), testID: testID, children: [_jsx(Icon, { color: icon.color, name: icon.name, size: 20 }), _jsxs(View, { className: "flex-1 gap-0.5", children: [title ? _jsx(Typography.Text, { className: styles.title(), children: title }) : null, _jsx(Typography.Text, { className: styles.message(), children: message }), action ? _jsx(View, { className: "mt-2", children: action }) : null] }), onClose ? (_jsx(Pressable, { accessibilityLabel: "Cerrar", hitSlop: 8, onPress: onClose, children: _jsx(Icon, { color: theme.icon.secondary, name: "close", size: 18 }) })) : null] }));
33
+ return (_jsxs(View, { accessibilityLiveRegion: tone === "danger" ? "assertive" : "polite", accessibilityRole: tone === "danger" ? "alert" : undefined, className: styles.root({ className }), testID: testID, children: [_jsx(Icon, { color: icon.color, name: icon.name, size: 20 }), _jsxs(View, { className: "flex-1 gap-0.5", children: [title ? _jsx(Typography.Text, { className: styles.title(), children: title }) : null, _jsx(Typography.Text, { className: styles.message(), children: message }), action ? _jsx(View, { className: "mt-2", children: action }) : null] }), onClose ? (_jsx(Pressable, { accessibilityLabel: "Cerrar", accessibilityRole: "button", hitSlop: 8, onPress: onClose, children: _jsx(Icon, { color: theme.icon.secondary, name: "close", size: 18 }) })) : null] }));
34
34
  }
35
35
  export default Banner;
@@ -1,11 +1,20 @@
1
- import type React from "react";
2
- import { ReactNode } from "react";
3
- interface DomainSplashScreenProps {
1
+ import { type ReactNode } from "react";
2
+ import { type StyleProp, type ViewStyle } from "react-native";
3
+ export interface DomainSplashRenderProps {
4
+ domainName: string;
5
+ isLoading: boolean;
6
+ reducedMotion: boolean;
7
+ }
8
+ export interface DomainSplashScreenProps {
4
9
  domainName: string;
5
10
  isLoading: boolean;
6
11
  children: ReactNode;
7
12
  onComplete?: () => void;
8
13
  minDuration?: number;
14
+ containerStyle?: StyleProp<ViewStyle>;
15
+ overlayStyle?: StyleProp<ViewStyle>;
16
+ renderLoading?: (props: DomainSplashRenderProps) => ReactNode;
17
+ testID?: string;
9
18
  }
10
- declare function DomainSplashScreen({ domainName, isLoading, children, onComplete, minDuration, }: DomainSplashScreenProps): React.JSX.Element;
19
+ declare function DomainSplashScreen({ domainName, isLoading, children, onComplete, minDuration, containerStyle, overlayStyle, renderLoading, testID, }: DomainSplashScreenProps): import("react").JSX.Element;
11
20
  export default DomainSplashScreen;
@@ -1,65 +1,80 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
2
  import GradientSurface from "../Display/Display.GradientSurface.js";
3
3
  import Pattern from "../Display/Display.Pattern.js";
4
- import { theme } from "../theme/index.js";
4
+ import Progress from "./Feedback.Progress.js";
5
+ import { useTheme } from "../theme/index.js";
5
6
  import { Typography } from "../Typography/index.js";
6
- import { useCallback, useEffect, useState } from "react";
7
- import { StyleSheet, View } from "react-native";
8
- import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming, } from "react-native-reanimated";
9
- import { scheduleOnRN } from "react-native-worklets";
10
- function DomainSplashScreen({ domainName, isLoading, children, onComplete, minDuration = 300, }) {
11
- const progressValue = useSharedValue(0);
12
- const opacityValue = useSharedValue(1);
13
- const [isComplete, setIsComplete] = useState(false);
14
- const handleComplete = useCallback(() => {
15
- if (onComplete) {
16
- onComplete();
17
- }
7
+ import { useReducedMotion } from "../utils/useReducedMotion.js";
8
+ import { useEffect, useRef, useState } from "react";
9
+ import { Animated, StyleSheet, View } from "react-native";
10
+ function DomainSplashScreen({ domainName, isLoading, children, onComplete, minDuration = 300, containerStyle, overlayStyle, renderLoading, testID, }) {
11
+ if (!Number.isFinite(minDuration) || minDuration < 0)
12
+ throw new RangeError("DomainSplashScreen minDuration must be a finite, non-negative number.");
13
+ const theme = useTheme();
14
+ const reducedMotion = useReducedMotion();
15
+ const [opacity] = useState(() => new Animated.Value(isLoading ? 1 : 0));
16
+ const [visible, setVisible] = useState(isLoading);
17
+ const startedAt = useRef(null);
18
+ const completed = useRef(false);
19
+ const onCompleteRef = useRef(onComplete);
20
+ const busy = isLoading || visible;
21
+ if (isLoading && !visible)
22
+ setVisible(true);
23
+ useEffect(() => {
24
+ onCompleteRef.current = onComplete;
18
25
  }, [onComplete]);
19
26
  useEffect(() => {
20
- if (!isLoading) {
21
- progressValue.value = withTiming(100, {
22
- duration: 300,
23
- easing: Easing.out(Easing.ease),
24
- });
25
- setTimeout(() => {
26
- opacityValue.value = withTiming(0, {
27
- duration: 400,
28
- easing: Easing.out(Easing.ease),
29
- });
30
- }, 100);
27
+ if (isLoading) {
28
+ startedAt.current = Date.now();
29
+ completed.current = false;
30
+ }
31
+ }, [isLoading]);
32
+ useEffect(() => {
33
+ if (isLoading) {
34
+ opacity.stopAnimation();
35
+ opacity.setValue(1);
31
36
  return;
32
37
  }
33
- const startTime = Date.now();
34
- const totalDuration = 2500;
35
- const interval = setInterval(() => {
36
- const elapsed = Date.now() - startTime;
37
- const newProgress = Math.min((elapsed / totalDuration) * 100, 100);
38
- progressValue.value = newProgress;
39
- if (newProgress >= 100) {
40
- clearInterval(interval);
41
- setIsComplete(true);
42
- setTimeout(() => {
43
- opacityValue.value = withTiming(0, {
44
- duration: 800,
45
- easing: Easing.out(Easing.ease),
46
- }, (finished) => {
47
- if (finished) {
48
- scheduleOnRN(handleComplete);
49
- }
50
- });
51
- }, 500);
38
+ if (startedAt.current === null || completed.current)
39
+ return;
40
+ let active = true;
41
+ let animation;
42
+ const finish = () => {
43
+ if (!active || completed.current)
44
+ return;
45
+ completed.current = true;
46
+ setVisible(false);
47
+ onCompleteRef.current?.();
48
+ };
49
+ const timeout = setTimeout(() => {
50
+ if (reducedMotion) {
51
+ opacity.setValue(0);
52
+ finish();
52
53
  }
53
- }, 50);
54
- return () => clearInterval(interval);
55
- }, [isLoading]);
56
- const progressBarStyle = useAnimatedStyle(() => ({
57
- width: `${progressValue.value}%`,
58
- }));
59
- const splashStyle = useAnimatedStyle(() => ({
60
- opacity: opacityValue.value,
61
- }));
62
- return (_jsxs(View, { style: styles.container, children: [children, _jsx(Animated.View, { pointerEvents: isLoading ? "auto" : "none", style: [StyleSheet.absoluteFill, splashStyle], children: _jsxs(GradientSurface, { preset: "warm", radius: "none", style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, children: [_jsx(Pattern, { color: theme.primary, kind: "dots", opacity: 0.14, size: 26 }), _jsx(View, { className: "flex-1 justify-center items-center px-8", children: _jsxs(View, { className: "w-full items-center gap-5", children: [_jsx(Typography.Text, { bold: true, style: { color: "#FFFFFF", fontSize: 24, letterSpacing: 0.5 }, children: isComplete ? "¡Listo!" : `Cargando ${domainName}` }), !isComplete && (_jsx(View, { className: "w-full rounded-full h-1.5 overflow-hidden", style: { backgroundColor: "rgba(255,255,255,0.18)" }, children: _jsx(Animated.View, { className: "rounded-full h-1.5", style: [{ backgroundColor: theme.primary }, progressBarStyle] }) })), isComplete && (_jsxs(Typography.Text, { style: { color: "rgba(255,255,255,0.8)", fontSize: 13 }, children: ["Ya puedes comenzar a usar ", domainName, "."] }))] }) })] }) })] }));
54
+ else {
55
+ animation = Animated.timing(opacity, {
56
+ toValue: 0,
57
+ duration: 400,
58
+ useNativeDriver: true,
59
+ isInteraction: false,
60
+ });
61
+ animation.start(({ finished }) => {
62
+ if (finished)
63
+ finish();
64
+ });
65
+ }
66
+ }, Math.max(0, minDuration - (Date.now() - startedAt.current)));
67
+ return () => {
68
+ active = false;
69
+ clearTimeout(timeout);
70
+ animation?.stop();
71
+ };
72
+ }, [isLoading, minDuration, opacity, reducedMotion]);
73
+ return (_jsxs(View, { style: [styles.container, containerStyle], testID: testID, children: [_jsx(View, { accessibilityElementsHidden: busy, importantForAccessibility: busy ? "no-hide-descendants" : "auto", pointerEvents: busy ? "none" : "auto", style: styles.container, testID: testID ? `${testID}-content` : undefined, children: children }), busy ? (_jsx(Animated.View, { style: [
74
+ StyleSheet.absoluteFill,
75
+ { opacity: isLoading ? 1 : opacity },
76
+ overlayStyle,
77
+ ], testID: testID ? `${testID}-loading` : undefined, children: renderLoading ? (renderLoading({ domainName, isLoading, reducedMotion })) : (_jsxs(GradientSurface, { className: "flex-1", preset: "warm", radius: "none", style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, children: [_jsx(Pattern, { color: theme.primary, kind: "dots", opacity: 0.14, size: 26 }), _jsx(View, { className: "flex-1 justify-center items-center px-8", children: _jsxs(View, { className: "w-full items-center gap-5", children: [_jsx(Typography.Text, { bold: true, style: { color: "#FFFFFF", fontSize: 24, letterSpacing: 0.5 }, children: `Cargando ${domainName}` }), _jsx(Progress, { accessibilityLabel: `Cargando ${domainName}`, indeterminate: true, indicatorStyle: { backgroundColor: theme.primary }, style: { backgroundColor: "rgba(255,255,255,0.18)" } })] }) })] })) })) : null] }));
63
78
  }
64
79
  const styles = StyleSheet.create({
65
80
  container: {
@@ -1,10 +1,10 @@
1
+ import type { ImageSource } from "../utils/image.js";
1
2
  import type { ReactNode } from "react";
2
- import { type ImageSourcePropType } from "react-native";
3
3
  export interface EmptyStateProps {
4
4
  title: string;
5
5
  description?: string;
6
6
  icon?: string;
7
- image?: ImageSourcePropType;
7
+ image?: ImageSource;
8
8
  actionLabel?: string;
9
9
  onAction?: () => void;
10
10
  children?: ReactNode;
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import ExpoImage from "../Display/Display.ExpoImage.js";
2
3
  import Icon from "../Display/Display.Icon.js";
3
4
  import { BaseButton } from "../primitives/BaseButton.js";
4
5
  import { theme } from "../theme/index.js";
5
6
  import { cn } from "../theme/tw.js";
6
7
  import { Typography } from "../Typography/index.js";
7
- import { Image, View } from "react-native";
8
+ import { View } from "react-native";
8
9
  function EmptyState({ title, description, icon = "file-tray-outline", image, actionLabel, onAction, children, className, testID, }) {
9
- return (_jsxs(View, { className: cn("flex-1 items-center justify-center px-8 gap-3", className), testID: testID, children: [image ? (_jsx(Image, { resizeMode: "contain", source: image, style: { width: 140, height: 140 } })) : (_jsx(View, { className: "w-20 h-20 rounded-full bg-bg-muted items-center justify-center", children: _jsx(Icon, { color: theme.icon.tertiary, name: icon, size: 40 }) })), _jsx(Typography.Text, { align: "center", className: "text-text-primary", semibold: true, variant: "subtitle", children: title }), description ? (_jsx(Typography.Text, { align: "center", className: "text-text-secondary", variant: "body", children: description })) : null, actionLabel && onAction ? (_jsx(View, { className: "mt-2", children: _jsx(BaseButton, { onPress: onAction, title: actionLabel, variant: "primary" }) })) : null, children] }));
10
+ return (_jsxs(View, { className: cn("flex-1 items-center justify-center px-8 gap-3", className), testID: testID, children: [image ? (_jsx(ExpoImage, { contentFit: "contain", source: image, style: { width: 140, height: 140 } })) : (_jsx(View, { className: "w-20 h-20 rounded-full bg-bg-muted items-center justify-center", children: _jsx(Icon, { color: theme.icon.tertiary, name: icon, size: 40 }) })), _jsx(Typography.Text, { accessibilityRole: "header", align: "center", className: "text-text-primary", semibold: true, variant: "subtitle", children: title }), description ? (_jsx(Typography.Text, { align: "center", className: "text-text-secondary", variant: "body", children: description })) : null, actionLabel && onAction ? (_jsx(View, { className: "mt-2", children: _jsx(BaseButton, { onPress: onAction, title: actionLabel, variant: "primary" }) })) : null, children] }));
10
11
  }
11
12
  export default EmptyState;
@@ -4,6 +4,7 @@ interface ErrorProps {
4
4
  onBack?: () => void;
5
5
  onHome?: () => void;
6
6
  className?: string;
7
+ testID?: string;
7
8
  }
8
- declare function Error({ message, onRetry, onBack, onHome, className }: ErrorProps): import("react").JSX.Element;
9
+ declare function Error({ message, onRetry, onBack, onHome, className, testID }: ErrorProps): import("react").JSX.Element;
9
10
  export default Error;
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
2
  import Icon from "../Display/Display.Icon.js";
3
- import Button from "../Form/Form.Button.js";
3
+ import Button from "../primitives/BaseButton.js";
4
+ import { theme } from "../theme/index.js";
4
5
  import { cn } from "../theme/tw.js";
5
6
  import { Typography } from "../Typography/index.js";
6
7
  import { View } from "react-native";
7
- function Error({ message, onRetry, onBack, onHome, className }) {
8
- return (_jsxs(View, { className: cn("flex-1 items-center justify-center px-4", className), children: [_jsx(Icon, { color: "#ef4444", name: "exclamation-circle", size: 80, type: "fontawesome5" }), _jsx(Typography.Text, { className: "pt-4 text-text-primary", semibold: true, variant: "h3", children: "\u00A1Error!" }), _jsx(Typography.Text, { className: "pt-2 text-center text-base leading-5.5 text-text-secondary", variant: "h5", children: message || "Ocurrió un error al cargar la información" }), _jsxs(View, { className: "mt-8 w-full gap-3", children: [onRetry && _jsx(Button, { className: "w-full", onPress: onRetry, title: "Reintentar" }), onBack && (_jsx(Button, { className: "w-full", onPress: onBack, title: "Volver", variant: "secondary" })), onHome && (_jsx(Button, { className: "w-full", onPress: onHome, title: "Ir al inicio", variant: "outline" }))] })] }));
8
+ function Error({ message, onRetry, onBack, onHome, className, testID }) {
9
+ return (_jsxs(View, { className: cn("flex-1 items-center justify-center px-4", className), testID: testID, children: [_jsx(Icon, { color: theme.danger, name: "exclamation-circle", size: 80, type: "fontawesome5" }), _jsx(Typography.Text, { accessibilityRole: "header", className: "pt-4 text-text-primary", semibold: true, variant: "h3", children: "\u00A1Error!" }), _jsx(Typography.Text, { accessibilityLiveRegion: "polite", className: "pt-2 text-center text-base leading-5.5 text-text-secondary", variant: "h5", children: message || "Ocurrió un error al cargar la información" }), _jsxs(View, { className: "mt-8 w-full gap-3", children: [onRetry && _jsx(Button, { className: "w-full", onPress: onRetry, title: "Reintentar" }), onBack && (_jsx(Button, { className: "w-full", onPress: onBack, title: "Volver", variant: "secondary" })), onHome && (_jsx(Button, { className: "w-full", onPress: onHome, title: "Ir al inicio", variant: "outline" }))] })] }));
9
10
  }
10
11
  export default Error;
@@ -1,11 +1,15 @@
1
1
  import { type SpinnerVariant } from "./Feedback.Spinner.js";
2
2
  import type React from "react";
3
+ import { type StyleProp, type ViewStyle } from "react-native";
3
4
  interface LoadingStateProps {
4
5
  message?: string;
5
6
  size?: "small" | "large";
6
7
  variant?: SpinnerVariant;
7
- style?: object;
8
+ style?: StyleProp<ViewStyle>;
8
9
  className?: string;
10
+ animated?: boolean;
11
+ accessibilityLabel?: string;
12
+ testID?: string;
9
13
  }
10
- declare function LoadingState({ message, size, variant, style, className, }: LoadingStateProps): React.JSX.Element;
14
+ declare function LoadingState({ message, size, variant, style, className, animated, accessibilityLabel, testID, }: LoadingStateProps): React.JSX.Element;
11
15
  export default LoadingState;
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "nativewind/jsx-runtime";
2
2
  import Spinner from "./Feedback.Spinner.js";
3
3
  import { cn } from "../theme/tw.js";
4
4
  import { View } from "react-native";
5
- function LoadingState({ message = "Cargando…", size = "small", variant = "spinner", style = {}, className, }) {
6
- return (_jsx(View, { className: cn("flex-1 justify-center items-center", className), style: style, children: _jsx(Spinner, { className: "mb-5", size: size, text: message, variant: variant }) }));
5
+ function LoadingState({ message = "Cargando…", size = "small", variant = "spinner", style = {}, className, animated, accessibilityLabel, testID, }) {
6
+ return (_jsx(View, { className: cn("flex-1 justify-center items-center", className), style: style, children: _jsx(Spinner, { accessibilityLabel: accessibilityLabel, animated: animated, className: "mb-5", size: size, testID: testID, text: message, variant: variant }) }));
7
7
  }
8
8
  export default LoadingState;
@@ -1,9 +1,12 @@
1
- export interface ProgressProps {
1
+ import { type StyleProp, type ViewProps, type ViewStyle } from "react-native";
2
+ export interface ProgressProps extends Omit<ViewProps, "children" | "accessibilityValue" | "accessibilityRole" | "accessibilityState"> {
2
3
  value?: number;
3
4
  indeterminate?: boolean;
4
5
  height?: number;
5
6
  className?: string;
6
- testID?: string;
7
+ animated?: boolean;
8
+ indicatorClassName?: string;
9
+ indicatorStyle?: StyleProp<ViewStyle>;
7
10
  }
8
- declare function Progress({ value, indeterminate, height, className, testID, }: ProgressProps): import("react").JSX.Element;
11
+ declare function Progress({ value, indeterminate, height, className, animated, indicatorClassName, indicatorStyle, style, ...props }: ProgressProps): import("react").JSX.Element;
9
12
  export default Progress;
@@ -1,37 +1,47 @@
1
1
  import { jsx as _jsx } from "nativewind/jsx-runtime";
2
2
  import { cn } from "../theme/tw.js";
3
3
  import { motion } from "../tokens/motion.js";
4
+ import { normalizeProgress } from "../utils/progress.js";
5
+ import { useReducedMotion } from "../utils/useReducedMotion.js";
4
6
  import { useEffect, useRef } from "react";
5
- import { Animated, Easing, View } from "react-native";
6
- function clamp(n) {
7
- return Math.max(0, Math.min(1, n));
8
- }
9
- function Progress({ value = 0, indeterminate = false, height = 6, className, testID, }) {
7
+ import { Animated, Easing, View, } from "react-native";
8
+ function Progress({ value = 0, indeterminate = false, height = 6, className, animated = true, indicatorClassName, indicatorStyle, style, ...props }) {
9
+ const reducedMotion = useReducedMotion();
10
+ const shouldAnimate = indeterminate && animated && !reducedMotion;
11
+ const progress = indeterminate ? 0 : normalizeProgress(value);
10
12
  // eslint-disable-next-line react-hooks/refs
11
13
  const translate = useRef(new Animated.Value(0)).current;
12
14
  useEffect(() => {
13
- if (!indeterminate)
15
+ translate.setValue(0);
16
+ if (!shouldAnimate)
14
17
  return;
15
18
  const loop = Animated.loop(Animated.timing(translate, {
16
19
  toValue: 1,
17
20
  duration: motion.duration.slower,
18
21
  easing: Easing.inOut(Easing.ease),
19
22
  useNativeDriver: true,
23
+ isInteraction: false,
20
24
  }));
21
25
  loop.start();
22
26
  return () => loop.stop();
23
- }, [indeterminate, translate]);
24
- return (_jsx(View, { accessibilityRole: "progressbar", accessibilityValue: indeterminate ? undefined : { now: Math.round(clamp(value) * 100), min: 0, max: 100 }, className: cn("w-full overflow-hidden rounded-full bg-bg-muted", className), style: { height }, testID: testID, children: indeterminate ? (_jsx(Animated.View, { className: "h-full rounded-full bg-primary", style: {
25
- width: "40%",
26
- transform: [
27
- {
28
- // eslint-disable-next-line react-hooks/refs
29
- translateX: translate.interpolate({
30
- inputRange: [0, 1],
31
- outputRange: ["-40%", "250%"],
32
- }),
33
- },
34
- ],
35
- } })) : (_jsx(View, { className: "h-full rounded-full bg-primary", style: { width: `${clamp(value) * 100}%` } })) }));
27
+ }, [shouldAnimate, translate]);
28
+ return (_jsx(View, { ...props, accessibilityRole: "progressbar", accessibilityState: { busy: indeterminate }, accessibilityValue: indeterminate ? undefined : { now: Math.round(progress * 100), min: 0, max: 100 }, accessible: true, className: cn("w-full overflow-hidden rounded-full bg-bg-muted", className), style: [{ height }, style], children: indeterminate ? (_jsx(Animated.View, { className: cn("h-full rounded-full bg-primary", indicatorClassName), style: [
29
+ {
30
+ width: "40%",
31
+ marginLeft: shouldAnimate ? 0 : "30%",
32
+ transform: shouldAnimate
33
+ ? [
34
+ {
35
+ // eslint-disable-next-line react-hooks/refs
36
+ translateX: translate.interpolate({
37
+ inputRange: [0, 1],
38
+ outputRange: ["-40%", "250%"],
39
+ }),
40
+ },
41
+ ]
42
+ : [],
43
+ },
44
+ indicatorStyle,
45
+ ] })) : (_jsx(View, { className: cn("h-full rounded-full bg-primary", indicatorClassName), style: [{ width: `${progress * 100}%` }, indicatorStyle] })) }));
36
46
  }
37
47
  export default Progress;
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
- export interface ProgressCircleProps {
2
+ import { type ViewProps } from "react-native";
3
+ export interface ProgressCircleProps extends Omit<ViewProps, "accessibilityValue" | "accessibilityRole"> {
3
4
  value?: number;
4
5
  size?: number;
5
6
  strokeWidth?: number;
@@ -8,5 +9,5 @@ export interface ProgressCircleProps {
8
9
  children?: ReactNode;
9
10
  testID?: string;
10
11
  }
11
- declare function ProgressCircle({ value, size, strokeWidth, color, trackColor, children, testID, }: ProgressCircleProps): import("react").JSX.Element;
12
+ declare function ProgressCircle({ value, size, strokeWidth, color, trackColor, children, style, ...props }: ProgressCircleProps): import("react").JSX.Element;
12
13
  export default ProgressCircle;
@@ -1,15 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
- import { theme } from "../theme/index.js";
2
+ import { useTheme } from "../theme/index.js";
3
+ import { normalizeProgress } from "../utils/progress.js";
3
4
  import { View } from "react-native";
4
5
  import Svg, { Circle } from "react-native-svg";
5
- function clamp(n) {
6
- return Math.max(0, Math.min(1, n));
7
- }
8
- function ProgressCircle({ value = 0, size = 64, strokeWidth = 6, color, trackColor, children, testID, }) {
6
+ function ProgressCircle({ value = 0, size = 64, strokeWidth = 6, color, trackColor, children, style, ...props }) {
7
+ const theme = useTheme();
8
+ const progress = normalizeProgress(value);
9
9
  const radius = (size - strokeWidth) / 2;
10
10
  const circumference = 2 * Math.PI * radius;
11
- const offset = circumference * (1 - clamp(value));
11
+ const offset = circumference * (1 - progress);
12
12
  const center = size / 2;
13
- return (_jsxs(View, { accessibilityRole: "progressbar", accessibilityValue: { now: Math.round(clamp(value) * 100), min: 0, max: 100 }, style: { width: size, height: size, alignItems: "center", justifyContent: "center" }, testID: testID, children: [_jsxs(Svg, { height: size, style: { position: "absolute" }, width: size, children: [_jsx(Circle, { cx: center, cy: center, fill: "none", r: radius, stroke: trackColor ?? theme.bg.muted, strokeWidth: strokeWidth }), _jsx(Circle, { cx: center, cy: center, fill: "none", r: radius, stroke: color ?? theme.primary, strokeDasharray: `${circumference} ${circumference}`, strokeDashoffset: offset, strokeLinecap: "round", strokeWidth: strokeWidth, transform: `rotate(-90 ${center} ${center})` })] }), children] }));
13
+ return (_jsxs(View, { ...props, accessibilityRole: "progressbar", accessibilityValue: { now: Math.round(progress * 100), min: 0, max: 100 }, accessible: true, style: [
14
+ { width: size, height: size, alignItems: "center", justifyContent: "center" },
15
+ style,
16
+ ], children: [_jsxs(Svg, { height: size, style: { position: "absolute" }, width: size, children: [_jsx(Circle, { cx: center, cy: center, fill: "none", r: radius, stroke: trackColor ?? theme.bg.muted, strokeWidth: strokeWidth }), _jsx(Circle, { cx: center, cy: center, fill: "none", r: radius, stroke: color ?? theme.primary, strokeDasharray: `${circumference} ${circumference}`, strokeDashoffset: offset, strokeLinecap: "round", strokeWidth: strokeWidth, transform: `rotate(-90 ${center} ${center})` })] }), children] }));
14
17
  }
15
18
  export default ProgressCircle;
@@ -1,11 +1,11 @@
1
- import { type DimensionValue, type ViewStyle } from "react-native";
2
- export interface SkeletonProps {
1
+ import { type DimensionValue, type ViewProps } from "react-native";
2
+ export interface SkeletonProps extends Omit<ViewProps, "children"> {
3
3
  width?: DimensionValue;
4
4
  height?: DimensionValue;
5
5
  radius?: number;
6
6
  circle?: boolean;
7
7
  className?: string;
8
- style?: ViewStyle;
8
+ animated?: boolean;
9
9
  }
10
- declare function Skeleton({ width, height, radius, circle, className, style, }: SkeletonProps): import("react").JSX.Element;
10
+ declare function Skeleton({ width, height, radius, circle, className, style, animated, ...props }: SkeletonProps): import("react").JSX.Element;
11
11
  export default Skeleton;