@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,14 +1,82 @@
1
- import { jsx as _jsx } from "nativewind/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import Icon from "./Display.Icon.js";
3
+ import Pressable from "../primitives/Pressable.js";
4
+ import { useTheme } from "../theme/index.js";
2
5
  import { Typography } from "../Typography/index.js";
3
6
  import * as Clipboard from "expo-clipboard";
4
- import { TouchableOpacity } from "react-native";
5
- function CopyableText({ value, getValue, label, className }) {
7
+ import { useEffect, useRef, useState } from "react";
8
+ import { AccessibilityInfo, ActivityIndicator, View } from "react-native";
9
+ function CopyableText({ value, getValue, label, className, accessibilityLabel, testID, disabled = false, onCopied, onCopyError, selectable = false, }) {
10
+ const theme = useTheme();
11
+ const pending = useRef(false);
12
+ const [status, setStatus] = useState("idle");
13
+ const [copiedValue, setCopiedValue] = useState();
6
14
  const hasStaticValue = value !== undefined;
7
- const displayText = label || value;
15
+ const isCopied = status === "copied" && (!hasStaticValue || copiedValue === value);
16
+ const displayText = label || value || "Copiar";
17
+ const copyLabel = accessibilityLabel ?? `Copiar ${displayText}`;
18
+ useEffect(() => {
19
+ if (status !== "copied")
20
+ return;
21
+ const timer = setTimeout(() => setStatus("idle"), 3000);
22
+ return () => clearTimeout(timer);
23
+ }, [status]);
8
24
  const handleCopy = async () => {
9
- const textToCopy = hasStaticValue ? value : getValue();
10
- await Clipboard.setStringAsync(textToCopy);
25
+ if (pending.current || disabled)
26
+ return;
27
+ pending.current = true;
28
+ setStatus("copying");
29
+ let textToCopy;
30
+ try {
31
+ textToCopy = hasStaticValue ? value : getValue();
32
+ const copied = await Clipboard.setStringAsync(textToCopy);
33
+ if (!copied)
34
+ throw new Error("El portapapeles no pudo copiar el texto");
35
+ }
36
+ catch (cause) {
37
+ const error = cause instanceof Error ? cause : new Error(String(cause));
38
+ setStatus("error");
39
+ AccessibilityInfo.announceForAccessibility("No se pudo copiar. Toca para reintentar.");
40
+ pending.current = false;
41
+ console.error("CopyableText: no se pudo copiar", error);
42
+ onCopyError?.(error);
43
+ return;
44
+ }
45
+ pending.current = false;
46
+ setCopiedValue(textToCopy);
47
+ setStatus("copied");
48
+ AccessibilityInfo.announceForAccessibility("Copiado");
49
+ onCopied?.(textToCopy);
11
50
  };
12
- return (_jsx(TouchableOpacity, { onPress: handleCopy, children: _jsx(Typography.Text, { className: className || "text-text-accent", semibold: true, variant: "bodySmall", children: displayText }) }));
51
+ return (_jsxs(View, { children: [_jsxs(View, { style: {
52
+ flexDirection: "row",
53
+ alignItems: selectable ? "flex-start" : "center",
54
+ gap: 8,
55
+ }, children: [selectable ? (_jsx(Typography.SelectableText, { className: className, style: { flex: 1 }, value: displayText, variant: "body" })) : null, _jsxs(Pressable, { accessibilityHint: selectable ? "Copia el texto completo" : "Toca para copiar", accessibilityLabel: isCopied ? `${copyLabel}. Copiado` : copyLabel, accessibilityState: {
56
+ disabled: disabled || status === "copying",
57
+ busy: status === "copying",
58
+ }, accessibilityValue: {
59
+ text: isCopied
60
+ ? "Copiado"
61
+ : status === "copying"
62
+ ? "Copiando"
63
+ : status === "error"
64
+ ? "Error al copiar"
65
+ : "",
66
+ }, disabled: disabled || status === "copying", onPress: () => {
67
+ void handleCopy();
68
+ }, style: {
69
+ minHeight: 48,
70
+ minWidth: 48,
71
+ flexDirection: "row",
72
+ alignItems: "center",
73
+ justifyContent: selectable ? "center" : "flex-start",
74
+ gap: 8,
75
+ flexShrink: selectable ? 0 : 1,
76
+ }, testID: testID, children: [!selectable ? (_jsx(Typography.Text, { className: className, style: { flexShrink: 1 }, variant: "body", children: displayText })) : null, _jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", style: { width: 24, alignItems: "center" }, children: status === "copying" ? (_jsx(ActivityIndicator, { color: theme.text.accent, size: "small" })) : (_jsx(Icon, { color: isCopied ? theme.success : theme.text.accent, name: isCopied
77
+ ? "checkmark"
78
+ : status === "error"
79
+ ? "alert-circle-outline"
80
+ : "copy-outline", size: 20 })) })] })] }), status === "error" ? (_jsx(Typography.Text, { accessibilityLiveRegion: "polite", className: "text-danger", variant: "bodySmall", children: "No se pudo copiar. Toca para reintentar." })) : null] }));
13
81
  }
14
82
  export default CopyableText;
@@ -0,0 +1,8 @@
1
+ import { Image } from "expo-image";
2
+ import type { ComponentPropsWithRef } from "react";
3
+ export type ExpoImageProps = Omit<ComponentPropsWithRef<typeof Image>, "resizeMode" | "defaultSource" | "loadingIndicatorSource"> & {
4
+ className?: string;
5
+ };
6
+ declare function ExpoImage({ cachePolicy, transition, autoplay, sfEffect, onError, source, recyclingKey, ...props }: ExpoImageProps): import("react").JSX.Element;
7
+ export default ExpoImage;
8
+ export { ExpoImage };
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "nativewind/jsx-runtime";
2
+ import { imageSourceKey } from "../utils/image.js";
3
+ import { useReducedMotion } from "../utils/useReducedMotion.js";
4
+ import { Image } from "expo-image";
5
+ import { cssInterop } from "nativewind";
6
+ const StyledImage = cssInterop(Image, { className: "style" });
7
+ function ExpoImage({ cachePolicy = "disk", transition = 0, autoplay = true, sfEffect, onError, source, recyclingKey, ...props }) {
8
+ const reducedMotion = useReducedMotion();
9
+ return (_jsx(StyledImage, { ...props, autoplay: autoplay && !reducedMotion, cachePolicy: cachePolicy, onError: (event) => {
10
+ console.error("[ExpoImage] Image load failed", event.error);
11
+ onError?.(event);
12
+ }, recyclingKey: recyclingKey === undefined ? imageSourceKey(source) : recyclingKey, sfEffect: reducedMotion ? null : sfEffect, source: source, transition: reducedMotion ? 0 : transition }));
13
+ }
14
+ export default ExpoImage;
15
+ export { ExpoImage };
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx } from "nativewind/jsx-runtime";
2
2
  import { AntDesign, Feather, FontAwesome, FontAwesome5, Ionicons, MaterialCommunityIcons, MaterialIcons, SimpleLineIcons, } from "@expo/vector-icons";
3
- import { theme } from "../theme/index.js";
3
+ import { useTheme } from "../theme/index.js";
4
4
  import { View } from "react-native";
5
5
  const Icon = ({ name, size = 24, color, type = "ionicons", customIcon, className, }) => {
6
+ const theme = useTheme();
6
7
  const iconColor = color || theme.text.primary;
7
8
  const renderIcon = () => {
8
9
  if (type === "custom" && customIcon) {
@@ -1,15 +1,19 @@
1
- import { type ImageResizeMode, type ImageSourcePropType, type ImageStyle } from "react-native";
2
- export interface DisplayImageProps {
3
- source: ImageSourcePropType;
1
+ import { type ExpoImageProps } from "./Display.ExpoImage.js";
2
+ import { type ImageSource } from "../utils/image.js";
3
+ import { type ReactNode } from "react";
4
+ import { type StyleProp, type ViewStyle } from "react-native";
5
+ export interface DisplayImageProps extends Omit<ExpoImageProps, "source" | "style"> {
6
+ source: ImageSource;
4
7
  width?: number | `${number}%`;
5
8
  height?: number;
6
9
  aspectRatio?: number;
7
10
  radius?: number;
8
- resizeMode?: ImageResizeMode;
9
11
  fallbackIcon?: string;
10
12
  className?: string;
11
- style?: ImageStyle;
13
+ style?: ExpoImageProps["style"];
14
+ containerStyle?: StyleProp<ViewStyle>;
15
+ renderError?: (retry: () => void) => ReactNode;
12
16
  testID?: string;
13
17
  }
14
- declare function DisplayImage({ source, width, height, aspectRatio, radius, resizeMode, fallbackIcon, className, style, testID, }: DisplayImageProps): import("react").JSX.Element;
18
+ declare function DisplayImage(props: DisplayImageProps): import("react").JSX.Element;
15
19
  export default DisplayImage;
@@ -1,17 +1,50 @@
1
+ import { createElement as _createElement } from "nativewind";
1
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "nativewind/jsx-runtime";
3
+ import ExpoImage from "./Display.ExpoImage.js";
2
4
  import Icon from "./Display.Icon.js";
3
5
  import Skeleton from "../Feedback/Feedback.Skeleton.js";
4
- import { theme } from "../theme/index.js";
6
+ import { useTheme } from "../theme/index.js";
5
7
  import { cn } from "../theme/tw.js";
6
- import { useState } from "react";
7
- import { Image, View, } from "react-native";
8
- function DisplayImage({ source, width = "100%", height, aspectRatio, radius = 12, resizeMode = "cover", fallbackIcon = "image-outline", className, style, testID, }) {
8
+ import { imageSourceKey } from "../utils/image.js";
9
+ import { useLayoutEffect, useRef, useState } from "react";
10
+ import { View } from "react-native";
11
+ function ImageContent({ source, width = "100%", height, aspectRatio, radius = 12, contentFit = "cover", placeholder, fallbackIcon = "image-outline", className, style, containerStyle, renderError, testID, onError, onLoadStart, onLoadEnd, onLoad, accessibilityLabel, accessible, retry, ...imageProps }) {
12
+ const theme = useTheme();
9
13
  const [loading, setLoading] = useState(true);
10
14
  const [failed, setFailed] = useState(false);
15
+ const active = useRef(true);
16
+ useLayoutEffect(() => {
17
+ active.current = true;
18
+ return () => {
19
+ active.current = false;
20
+ };
21
+ }, []);
11
22
  const dimensions = { width, height, aspectRatio, borderRadius: radius };
12
- return (_jsx(View, { className: cn("overflow-hidden bg-bg-muted", className), style: dimensions, testID: testID, children: failed ? (_jsx(View, { className: "flex-1 items-center justify-center", children: _jsx(Icon, { color: theme.icon.disabled, name: fallbackIcon, size: 32 }) })) : (_jsxs(_Fragment, { children: [_jsx(Image, { onError: () => {
23
+ return (_jsx(View, { className: cn("overflow-hidden bg-bg-muted", className), style: [dimensions, containerStyle], testID: testID, children: failed ? (renderError ? (renderError(retry)) : (_jsx(View, { accessibilityLabel: accessibilityLabel ? `${accessibilityLabel}. Imagen no disponible` : undefined, accessibilityRole: "image", accessible: accessible ?? !!accessibilityLabel, className: "flex-1 items-center justify-center", children: _jsx(Icon, { color: theme.icon.disabled, name: fallbackIcon, size: 32 }) }))) : (_jsxs(_Fragment, { children: [_jsx(ExpoImage, { ...imageProps, accessibilityLabel: accessibilityLabel, accessible: accessible, contentFit: contentFit, onError: (event) => {
24
+ if (!active.current)
25
+ return;
13
26
  setFailed(true);
14
27
  setLoading(false);
15
- }, onLoadEnd: () => setLoading(false), resizeMode: resizeMode, source: source, style: [{ width: "100%", height: "100%" }, style] }), loading ? (_jsx(View, { style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, children: _jsx(Skeleton, { height: "100%", radius: radius, width: "100%" }) })) : null] })) }));
28
+ onError?.(event);
29
+ }, onLoad: (event) => {
30
+ if (!active.current)
31
+ return;
32
+ setLoading(false);
33
+ onLoad?.(event);
34
+ }, onLoadEnd: () => {
35
+ if (!active.current)
36
+ return;
37
+ setLoading(false);
38
+ onLoadEnd?.();
39
+ }, onLoadStart: () => {
40
+ if (!active.current)
41
+ return;
42
+ setLoading(true);
43
+ onLoadStart?.();
44
+ }, placeholder: placeholder, placeholderContentFit: imageProps.placeholderContentFit ?? contentFit, source: source, style: [{ width: "100%", height: "100%" }, style] }), loading && !placeholder ? (_jsx(View, { style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 }, children: _jsx(Skeleton, { height: "100%", radius: radius, width: "100%" }) })) : null] })) }));
45
+ }
46
+ function DisplayImage(props) {
47
+ const [attempt, setAttempt] = useState(0);
48
+ return (_createElement(ImageContent, { ...props, key: `${imageSourceKey(props.source)}:${attempt}`, retry: () => setAttempt((current) => current + 1) }));
16
49
  }
17
50
  export default DisplayImage;
@@ -1,10 +1,17 @@
1
1
  import type { ReactNode } from "react";
2
- export interface KeyValueProps {
2
+ interface KeyValueLayoutProps {
3
3
  label: string;
4
- value?: ReactNode;
5
- align?: "row" | "stacked";
4
+ align?: "row" | "stacked" | "auto";
6
5
  className?: string;
7
6
  testID?: string;
7
+ selectable?: boolean;
8
8
  }
9
- declare function KeyValue({ label, value, align, className, testID }: KeyValueProps): import("react").JSX.Element;
9
+ export type KeyValueProps = KeyValueLayoutProps & ({
10
+ copyable: true;
11
+ value: string | number;
12
+ } | {
13
+ copyable?: false;
14
+ value?: ReactNode;
15
+ });
16
+ declare function KeyValue({ label, value, align, className, testID, copyable, selectable, }: KeyValueProps): import("react").JSX.Element;
10
17
  export default KeyValue;
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
2
  import { cn } from "../theme/tw.js";
3
3
  import { Typography } from "../Typography/index.js";
4
- import { View } from "react-native";
5
- function KeyValue({ label, value, align = "row", className, testID }) {
6
- const isRow = align === "row";
7
- return (_jsxs(View, { className: cn(isRow ? "flex-row items-center justify-between gap-3" : "gap-0.5", "py-2", className), testID: testID, children: [_jsx(Typography.Text, { className: "text-text-secondary", variant: "caption", children: label }), typeof value === "string" || typeof value === "number" ? (_jsx(Typography.Text, { className: cn("text-text-primary", isRow && "text-right"), semibold: isRow, children: value })) : (value)] }));
4
+ import { useWindowDimensions, View } from "react-native";
5
+ import CopyableText from "./Display.CopyableText";
6
+ function KeyValue({ label, value, align = "row", className, testID, copyable = false, selectable = false, }) {
7
+ const { width, fontScale } = useWindowDimensions();
8
+ const isRow = align === "row" || (align === "auto" && width >= 360 && fontScale <= 1.3);
9
+ return (_jsxs(View, { className: cn(isRow ? "flex-row items-center justify-between gap-3" : "gap-0.5", "py-2", className), testID: testID, children: [_jsx(Typography.Text, { className: "text-text-secondary", variant: "caption", children: label }), typeof value === "string" || typeof value === "number" ? (_jsx(View, { className: cn("flex-shrink min-w-0", isRow && "flex-1 items-end"), children: copyable ? (_jsx(CopyableText, { accessibilityLabel: `Copiar ${label}`, selectable: selectable, value: String(value) })) : selectable ? (_jsx(Typography.SelectableText, { className: cn("text-text-primary", isRow && "text-right"), semibold: isRow, style: { alignSelf: "stretch" }, value: String(value) })) : (_jsx(Typography.Text, { className: cn("text-text-primary", isRow && "text-right"), selectable: selectable, semibold: isRow, children: value })) })) : (value)] }));
8
10
  }
9
11
  export default KeyValue;
@@ -0,0 +1,23 @@
1
+ import { type SectionHeaderAction, type SectionHeaderProps } from "./Display.SectionHeader.js";
2
+ import { Typography } from "../Typography/index.js";
3
+ import { type ComponentProps, type ReactNode } from "react";
4
+ import { type StyleProp, type ViewStyle } from "react-native";
5
+ export interface ListGroupProps {
6
+ title: string;
7
+ description?: string;
8
+ footer?: ReactNode;
9
+ action?: SectionHeaderAction;
10
+ children: ReactNode;
11
+ surface?: "inset" | "plain";
12
+ separators?: boolean;
13
+ className?: string;
14
+ contentClassName?: string;
15
+ testID?: string;
16
+ headerProps?: Omit<SectionHeaderProps, "title" | "subtitle" | "action">;
17
+ footerTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
18
+ style?: StyleProp<ViewStyle>;
19
+ contentStyle?: StyleProp<ViewStyle>;
20
+ separatorStyle?: StyleProp<ViewStyle>;
21
+ }
22
+ declare function ListGroup({ title, description, footer, action, children, surface, separators, className, contentClassName, testID, headerProps, footerTextProps, style, contentStyle, separatorStyle, }: ListGroupProps): import("react").JSX.Element;
23
+ export default ListGroup;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import SectionHeader from "./Display.SectionHeader.js";
3
+ import { cn } from "../theme/tw.js";
4
+ import { Typography } from "../Typography/index.js";
5
+ import { Children } from "react";
6
+ import { StyleSheet, View } from "react-native";
7
+ function ListGroup({ title, description, footer, action, children, surface = "inset", separators = true, className, contentClassName, testID, headerProps, footerTextProps, style, contentStyle, separatorStyle, }) {
8
+ const rows = Children.toArray(children);
9
+ return (_jsxs(View, { className: cn("gap-2", className), style: style, testID: testID, children: [_jsx(SectionHeader, { ...headerProps, action: action, subtitle: description, title: title }), _jsx(View, { className: cn(surface === "inset" && "rounded-2xl bg-bg-card overflow-hidden", contentClassName), style: contentStyle, testID: testID ? `${testID}-content` : undefined, children: rows.map((row, index) => (_jsxs(View, { children: [row, separators && index < rows.length - 1 ? (_jsx(View, { accessibilityElementsHidden: true, className: "bg-border-default", importantForAccessibility: "no-hide-descendants", style: [
10
+ {
11
+ height: StyleSheet.hairlineWidth,
12
+ marginHorizontal: 16,
13
+ },
14
+ separatorStyle,
15
+ ], testID: testID ? `${testID}-separator-${index}` : undefined })) : null] }, typeof row === "object" && "key" in row ? row.key : index))) }), typeof footer === "string" ? (_jsx(Typography.Text, { className: "text-text-secondary px-4", variant: "bodySmall", ...footerTextProps, children: footer })) : (footer)] }));
16
+ }
17
+ export default ListGroup;
@@ -1,4 +1,6 @@
1
- import type { ReactNode } from "react";
1
+ import { Typography } from "../Typography/index.js";
2
+ import type { ComponentProps, ReactNode } from "react";
3
+ import { type StyleProp, type ViewStyle } from "react-native";
2
4
  export interface ListItemProps {
3
5
  title: string;
4
6
  subtitle?: string;
@@ -12,6 +14,17 @@ export interface ListItemProps {
12
14
  showDivider?: boolean;
13
15
  className?: string;
14
16
  testID?: string;
17
+ accessibilityLabel?: string;
18
+ accessibilityHint?: string;
19
+ disabled?: boolean;
20
+ variant?: "default" | "mobile";
21
+ value?: string;
22
+ layout?: "auto" | "row" | "stacked";
23
+ density?: "compact" | "comfortable";
24
+ style?: StyleProp<ViewStyle>;
25
+ titleTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
26
+ subtitleTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
27
+ valueTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
15
28
  }
16
- declare function ListItem({ title, subtitle, leading, trailing, chevron, onPress, showDivider, className, testID, }: ListItemProps): import("react").JSX.Element;
29
+ declare function ListItem({ title, subtitle, leading, trailing, chevron, onPress, showDivider, className, testID, accessibilityLabel, accessibilityHint, disabled, variant, value, layout, density, style, titleTextProps, subtitleTextProps, valueTextProps, }: ListItemProps): import("react").JSX.Element;
17
30
  export default ListItem;
@@ -1,18 +1,35 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "nativewind/jsx-runtime";
2
2
  import Icon from "./Display.Icon.js";
3
3
  import Pressable from "../primitives/Pressable.js";
4
- import { theme } from "../theme/index.js";
4
+ import { useTheme } from "../theme/index.js";
5
5
  import { cn } from "../theme/tw.js";
6
6
  import { Typography } from "../Typography/index.js";
7
- import { View } from "react-native";
8
- function ListItem({ title, subtitle, leading, trailing, chevron = false, onPress, showDivider = true, className, testID, }) {
7
+ import { Pressable as NativePressable, useWindowDimensions, View, } from "react-native";
8
+ function ListItem({ title, subtitle, leading, trailing, chevron = false, onPress, showDivider, className, testID, accessibilityLabel, accessibilityHint, disabled = false, variant = "default", value, layout = "auto", density = "compact", style, titleTextProps, subtitleTextProps, valueTextProps, }) {
9
+ const theme = useTheme();
10
+ const { width, fontScale } = useWindowDimensions();
11
+ const mobile = variant === "mobile";
12
+ const comfortable = mobile && density === "comfortable";
13
+ const stacked = mobile &&
14
+ (value !== undefined || trailing != null) &&
15
+ (layout === "stacked" || (layout === "auto" && (fontScale > 1.3 || width < 360)));
9
16
  const right = trailing ??
10
- (chevron ? _jsx(Icon, { color: theme.icon.tertiary, name: "chevron-forward", size: 18 }) : null);
11
- const content = (_jsxs(_Fragment, { children: [leading ? _jsx(View, { className: "mr-3 justify-center", children: leading }) : null, _jsxs(View, { className: "flex-1 gap-0.5", children: [_jsx(Typography.Text, { className: "text-text-primary", numberOfLines: 1, semibold: true, variant: "body", children: title }), subtitle ? (_jsx(Typography.Text, { className: "text-text-secondary", numberOfLines: 1, variant: "bodySmall", children: subtitle })) : null] }), right ? _jsx(View, { className: "ml-3 justify-center", children: right }) : null] }));
12
- const base = cn("flex-row items-center py-3 px-4 bg-bg-card", showDivider && "border-b border-border-default", className);
17
+ (value || chevron ? (_jsxs(View, { className: "flex-row items-center gap-2", children: [value ? (_jsx(Typography.Text, { className: "text-text-secondary flex-shrink", variant: comfortable ? "bodyReadable" : "body", ...valueTextProps, children: value })) : null, chevron ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: _jsx(Icon, { color: theme.icon.tertiary, name: "chevron-forward", size: 18 }) })) : null] })) : null);
18
+ const content = (_jsxs(_Fragment, { children: [leading ? _jsx(View, { className: "mr-3 justify-center", children: leading }) : null, _jsxs(View, { className: cn("flex-1", mobile ? "min-w-0 gap-1" : "gap-0.5"), children: [_jsx(Typography.Text, { className: mobile && disabled ? "text-text-disabled" : "text-text-primary", semibold: !mobile || comfortable, variant: comfortable ? "bodyReadable" : "body", ...titleTextProps, children: title }), subtitle ? (_jsx(Typography.Text, { className: "text-text-secondary", variant: comfortable ? "bodyLarge" : "bodySmall", ...subtitleTextProps, children: subtitle })) : null, stacked && right ? _jsx(View, { className: "self-start mt-1", children: right }) : null] }), !stacked && right ? (_jsx(View, { className: cn("ml-3 justify-center", mobile && "flex-shrink"), style: mobile ? { maxWidth: "45%" } : undefined, children: right })) : null] }));
19
+ const base = cn("flex-row items-center px-4", mobile && !comfortable ? "py-2" : "py-3", !mobile && "bg-bg-card", (showDivider ?? !mobile) && "border-b border-border-default", disabled && !mobile && "opacity-50", className);
13
20
  if (onPress) {
14
- return (_jsx(Pressable, { className: base, onPress: onPress, testID: testID, children: content }));
21
+ if (mobile) {
22
+ return (_jsx(NativePressable, { accessibilityHint: accessibilityHint ?? subtitle, accessibilityLabel: accessibilityLabel ?? title, accessibilityRole: "button", accessibilityState: { disabled }, accessibilityValue: value !== undefined ? { text: value } : undefined, className: base, disabled: disabled, onPress: onPress, style: ({ pressed }) => [
23
+ {
24
+ minHeight: 48,
25
+ minWidth: 48,
26
+ backgroundColor: pressed ? theme.bg.hover : undefined,
27
+ },
28
+ style,
29
+ ], testID: testID, children: content }));
30
+ }
31
+ return (_jsx(Pressable, { accessibilityHint: accessibilityHint, accessibilityLabel: accessibilityLabel, className: base, disabled: disabled, onPress: onPress, style: [{ minHeight: 48, minWidth: 48 }, style], testID: testID, children: content }));
15
32
  }
16
- return (_jsx(View, { className: base, testID: testID, children: content }));
33
+ return (_jsx(View, { className: base, style: style, testID: testID, children: content }));
17
34
  }
18
35
  export default ListItem;
@@ -1,6 +1,6 @@
1
1
  import { type VariantProps } from "../theme/tw.js";
2
+ import type { ImageSource } from "../utils/image.js";
2
3
  import { FC } from "react";
3
- import { type ImageSourcePropType } from "react-native";
4
4
  declare const logo: import("tailwind-variants").TVReturnType<{
5
5
  size: {
6
6
  small: {
@@ -48,7 +48,7 @@ declare const logo: import("tailwind-variants").TVReturnType<{
48
48
  image: string;
49
49
  }>>;
50
50
  export interface LogoProps extends VariantProps<typeof logo> {
51
- source?: ImageSourcePropType;
51
+ source?: ImageSource;
52
52
  className?: string;
53
53
  }
54
54
  declare const Logo: FC<LogoProps>;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "nativewind/jsx-runtime";
2
2
  import { getBrandingLogo } from "../branding.js";
3
+ import ExpoImage from "./Display.ExpoImage.js";
3
4
  import { tv } from "../theme/tw.js";
4
- import { Image, View } from "react-native";
5
+ import { View } from "react-native";
5
6
  const logo = tv({
6
7
  slots: {
7
8
  container: "items-center justify-center",
@@ -28,7 +29,7 @@ function renderImage(imageClassName, source) {
28
29
  if (!source) {
29
30
  return null;
30
31
  }
31
- return _jsx(Image, { className: imageClassName, resizeMode: "contain", source: source });
32
+ return _jsx(ExpoImage, { className: imageClassName, contentFit: "contain", source: source });
32
33
  }
33
34
  const Logo = ({ source, size = "medium", className }) => {
34
35
  const styles = logo({ size });
@@ -1,7 +1,7 @@
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 MediaCardProps {
4
- image: ImageSourcePropType;
4
+ image: ImageSource;
5
5
  title?: string;
6
6
  subtitle?: string;
7
7
  badge?: ReactNode;
@@ -1,7 +1,7 @@
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 MediaEmbedProps {
4
- thumbnail: ImageSourcePropType;
4
+ thumbnail: ImageSource;
5
5
  onPress: () => void;
6
6
  duration?: string;
7
7
  title?: string;
@@ -1,8 +1,8 @@
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 ProductCardProps {
4
4
  title: string;
5
- image: ImageSourcePropType;
5
+ image: ImageSource;
6
6
  price: number;
7
7
  originalPrice?: number;
8
8
  currency?: string;
@@ -1,3 +1,6 @@
1
+ import { Typography } from "../Typography/index.js";
2
+ import type { ComponentProps } from "react";
3
+ import { type StyleProp, type ViewStyle } from "react-native";
1
4
  export interface SectionHeaderAction {
2
5
  label: string;
3
6
  onPress: () => void;
@@ -8,6 +11,13 @@ export interface SectionHeaderProps {
8
11
  action?: SectionHeaderAction;
9
12
  className?: string;
10
13
  testID?: string;
14
+ variant?: "default" | "mobile";
15
+ titleTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children" | "accessibilityRole">;
16
+ subtitleTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
17
+ style?: StyleProp<ViewStyle>;
18
+ contentStyle?: StyleProp<ViewStyle>;
19
+ actionStyle?: StyleProp<ViewStyle>;
20
+ actionTextProps?: Omit<ComponentProps<typeof Typography.Text>, "children">;
11
21
  }
12
- declare function SectionHeader({ title, subtitle, action, className, testID }: SectionHeaderProps): import("react").JSX.Element;
22
+ declare function SectionHeader({ title, subtitle, action, className, testID, variant, titleTextProps, subtitleTextProps, style, contentStyle, actionStyle, actionTextProps, }: SectionHeaderProps): import("react").JSX.Element;
13
23
  export default SectionHeader;
@@ -3,7 +3,16 @@ import Pressable from "../primitives/Pressable.js";
3
3
  import { cn } from "../theme/tw.js";
4
4
  import { Typography } from "../Typography/index.js";
5
5
  import { View } from "react-native";
6
- function SectionHeader({ title, subtitle, action, className, testID }) {
7
- return (_jsxs(View, { className: cn("flex-row items-center justify-between px-4 py-2", className), testID: testID, children: [_jsxs(View, { className: "flex-1", children: [_jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: "subtitle", children: title }), subtitle ? (_jsx(Typography.Text, { className: "text-text-secondary", variant: "bodySmall", children: subtitle })) : null] }), action ? (_jsx(Pressable, { accessibilityRole: "button", hitSlop: 8, onPress: action.onPress, children: _jsx(Typography.Text, { className: "text-text-accent text-sm font-semibold", children: action.label }) })) : null] }));
6
+ function SectionHeader({ title, subtitle, action, className, testID, variant = "default", titleTextProps, subtitleTextProps, style, contentStyle, actionStyle, actionTextProps, }) {
7
+ return (_jsxs(View, { className: cn("flex-row items-center justify-between px-4 py-2", className), style: style, testID: testID, children: [_jsxs(View, { className: "flex-1", style: contentStyle, children: [_jsx(Typography.Text, { accessibilityRole: "header", className: "text-text-primary", semibold: true, variant: variant === "mobile" ? "bodyReadable" : "subtitle", ...titleTextProps, children: title }), subtitle ? (_jsx(Typography.Text, { className: "text-text-secondary", variant: variant === "mobile" ? "bodyLarge" : "bodySmall", ...subtitleTextProps, children: subtitle })) : null] }), action ? (_jsx(Pressable, { accessibilityLabel: action.label, accessibilityRole: "button", hitSlop: 8, onPress: action.onPress, style: [
8
+ {
9
+ minHeight: 48,
10
+ minWidth: 48,
11
+ justifyContent: "center",
12
+ marginLeft: 12,
13
+ flexShrink: 1,
14
+ },
15
+ actionStyle,
16
+ ], children: _jsx(Typography.Text, { className: "text-text-accent text-sm font-semibold", ...actionTextProps, children: action.label }) })) : null] }));
8
17
  }
9
18
  export default SectionHeader;
@@ -1,11 +1,11 @@
1
- import { type ImageSourcePropType } from "react-native";
1
+ import type { ImageSource } from "../utils/image.js";
2
2
  export interface StoryProps {
3
- image: ImageSourcePropType;
3
+ image: ImageSource;
4
4
  label?: string;
5
5
  seen?: boolean;
6
6
  variant?: "circle" | "card";
7
7
  size?: number;
8
- avatar?: ImageSourcePropType;
8
+ avatar?: ImageSource;
9
9
  /** Mostrar el círculo del autor en la card. `false` = card de historia sin avatar. */
10
10
  showAvatar?: boolean;
11
11
  onPress?: () => void;
@@ -1,20 +1,21 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
+ import ExpoImage from "./Display.ExpoImage.js";
2
3
  import Pressable from "../primitives/Pressable.js";
3
4
  import { theme } from "../theme/index.js";
4
5
  import { Typography } from "../Typography/index.js";
5
6
  import { LinearGradient } from "expo-linear-gradient";
6
- import { Image, View } from "react-native";
7
+ import { View } from "react-native";
7
8
  const RING = ["#F58529", "#DD2A7B"];
8
9
  function Story({ image, label, seen = false, variant = "circle", size = 68, avatar, showAvatar = true, onPress, testID, }) {
9
10
  if (variant === "card") {
10
- return (_jsxs(Pressable, { accessibilityLabel: label, accessibilityRole: "button", onPress: onPress, style: { width: size * 1.6, borderRadius: 14, overflow: "hidden" }, testID: testID, children: [_jsx(Image, { source: image, style: { width: "100%", height: size * 2.6 } }), showAvatar ? (_jsx(View, { style: {
11
+ return (_jsxs(Pressable, { accessibilityLabel: label, accessibilityRole: "button", onPress: onPress, style: { width: size * 1.6, borderRadius: 14, overflow: "hidden" }, testID: testID, children: [_jsx(ExpoImage, { source: image, style: { width: "100%", height: size * 2.6 } }), showAvatar ? (_jsx(View, { style: {
11
12
  position: "absolute",
12
13
  top: 8,
13
14
  left: 8,
14
15
  borderRadius: 999,
15
16
  borderWidth: 3,
16
17
  borderColor: seen ? theme.border.strong : theme.primary,
17
- }, children: _jsx(Image, { source: avatar ?? image, style: { width: 34, height: 34, borderRadius: 17 } }) })) : null, label ? (_jsx(LinearGradient, { colors: ["transparent", "rgba(0,0,0,0.7)"], style: {
18
+ }, children: _jsx(ExpoImage, { source: avatar ?? image, style: { width: 34, height: 34, borderRadius: 17 } }) })) : null, label ? (_jsx(LinearGradient, { colors: ["transparent", "rgba(0,0,0,0.7)"], style: {
18
19
  position: "absolute",
19
20
  left: 0,
20
21
  right: 0,
@@ -38,6 +39,6 @@ function Story({ image, label, seen = false, variant = "circle", size = 68, avat
38
39
  backgroundColor: theme.bg.card,
39
40
  alignItems: "center",
40
41
  justifyContent: "center",
41
- }, children: _jsx(Image, { source: image, style: { width: innerSize, height: innerSize, borderRadius: innerSize / 2 } }) }) }), label ? (_jsx(Typography.Text, { className: "text-text-secondary", numberOfLines: 1, style: { maxWidth: size + 6 }, variant: "caption", children: label })) : null] }));
42
+ }, children: _jsx(ExpoImage, { source: image, style: { width: innerSize, height: innerSize, borderRadius: innerSize / 2 } }) }) }), label ? (_jsx(Typography.Text, { className: "text-text-secondary", numberOfLines: 1, style: { maxWidth: size + 6 }, variant: "caption", children: label })) : null] }));
42
43
  }
43
44
  export default Story;
@@ -1,14 +1,14 @@
1
- import { type ImageSourcePropType } from "react-native";
1
+ import type { ImageSource } from "../utils/image.js";
2
2
  export interface StoryTrayItem {
3
3
  id: string;
4
- image: ImageSourcePropType;
4
+ image: ImageSource;
5
5
  label?: string;
6
- avatar?: ImageSourcePropType;
6
+ avatar?: ImageSource;
7
7
  seen?: boolean;
8
8
  }
9
9
  export interface StoryTrayCreate {
10
10
  label?: string;
11
- image?: ImageSourcePropType;
11
+ image?: ImageSource;
12
12
  onPress: () => void;
13
13
  }
14
14
  export interface StoryTrayProps {
@@ -1,10 +1,11 @@
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 Story from "./Display.Story.js";
4
5
  import Pressable from "../primitives/Pressable.js";
5
6
  import { theme } from "../theme/index.js";
6
7
  import { Typography } from "../Typography/index.js";
7
- import { Image, ScrollView, View } from "react-native";
8
+ import { ScrollView, View } from "react-native";
8
9
  function CreateCard({ create, size }) {
9
10
  const w = size * 1.6;
10
11
  return (_jsxs(Pressable, { accessibilityLabel: create.label ?? "Crear historia", accessibilityRole: "button", onPress: create.onPress, style: {
@@ -14,7 +15,7 @@ function CreateCard({ create, size }) {
14
15
  backgroundColor: theme.bg.card,
15
16
  borderWidth: 1,
16
17
  borderColor: theme.border.light,
17
- }, children: [create.image ? (_jsx(Image, { source: create.image, style: { width: "100%", height: size * 1.7 } })) : (_jsx(View, { style: { width: "100%", height: size * 1.7, backgroundColor: theme.bg.muted } })), _jsxs(View, { style: { alignItems: "center", paddingVertical: 14 }, children: [_jsx(View, { style: {
18
+ }, children: [create.image ? (_jsx(ExpoImage, { source: create.image, style: { width: "100%", height: size * 1.7 } })) : (_jsx(View, { style: { width: "100%", height: size * 1.7, backgroundColor: theme.bg.muted } })), _jsxs(View, { style: { alignItems: "center", paddingVertical: 14 }, children: [_jsx(View, { style: {
18
19
  position: "absolute",
19
20
  top: -16,
20
21
  width: 32,
@@ -1,7 +1,7 @@
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 StoryViewerSlide {
4
- image: ImageSourcePropType;
4
+ image: ImageSource;
5
5
  }
6
6
  export interface StoryViewerProps {
7
7
  visible: boolean;
@@ -12,7 +12,7 @@ export interface StoryViewerProps {
12
12
  title: string;
13
13
  subtitle?: string;
14
14
  time?: string;
15
- avatar?: ImageSourcePropType;
15
+ avatar?: ImageSource;
16
16
  progress?: number;
17
17
  muted?: boolean;
18
18
  paused?: boolean;