@sincpro/mobile-ui 2.0.0 → 3.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.
- package/README.md +7 -2
- package/assets/brand-mesh.png +0 -0
- package/assets/fonts/FFL.txt +57 -0
- package/assets/fonts/Satoshi-Black.otf +0 -0
- package/assets/fonts/Satoshi-Bold.otf +0 -0
- package/assets/fonts/Satoshi-Medium.otf +0 -0
- package/assets/fonts/Satoshi-Regular.otf +0 -0
- package/dist/Actions/Actions.Button.d.ts +2 -1
- package/dist/Actions/Actions.Button.js +31 -37
- package/dist/Actions/Actions.Dock.d.ts +6 -6
- package/dist/Actions/Actions.Dock.js +14 -72
- package/dist/Actions/Actions.FAB.d.ts +2 -1
- package/dist/Actions/Actions.FilterButton.js +1 -1
- package/dist/Actions/Actions.IconButton.d.ts +3 -4
- package/dist/Actions/Actions.IconButton.js +2 -2
- package/dist/Dialog/Confirmation.context.d.ts +5 -14
- package/dist/Dialog/Confirmation.context.js +11 -51
- package/dist/Dialog/Dialog.ActionSheet.d.ts +8 -7
- package/dist/Dialog/Dialog.ActionSheet.js +45 -19
- package/dist/Dialog/Dialog.Confirmation.d.ts +14 -11
- package/dist/Dialog/Dialog.Confirmation.js +38 -14
- package/dist/Dialog/Dialog.EditValue.d.ts +21 -16
- package/dist/Dialog/Dialog.EditValue.js +73 -14
- package/dist/Dialog/Dialog.Sheet.d.ts +8 -24
- package/dist/Dialog/Dialog.Sheet.js +15 -60
- package/dist/Dialog/index.d.ts +14 -14
- package/dist/Dialog/index.js +5 -3
- package/dist/Dialog/requestConfirmation.d.ts +3 -0
- package/dist/Dialog/requestConfirmation.js +13 -0
- package/dist/Display/Display.Accordion.js +1 -1
- package/dist/Display/Display.Avatar.d.ts +6 -6
- package/dist/Display/Display.Avatar.js +2 -2
- package/dist/Display/Display.Badge.js +4 -4
- package/dist/Display/Display.Card.js +5 -2
- package/dist/Display/Display.Carousel.js +1 -1
- package/dist/Display/Display.CircleButton.d.ts +3 -8
- package/dist/Display/Display.CircleButton.js +2 -2
- package/dist/Display/Display.CopyableText.js +1 -5
- package/dist/Display/Display.Date.d.ts +3 -2
- package/dist/Display/Display.Date.js +3 -3
- package/dist/Display/Display.GradientSurface.d.ts +52 -9
- package/dist/Display/Display.GradientSurface.js +9 -14
- package/dist/Display/Display.Icon.d.ts +7 -11
- package/dist/Display/Display.Icon.js +15 -30
- package/dist/Display/Display.Image.d.ts +2 -1
- package/dist/Display/Display.Image.js +1 -1
- package/dist/Display/Display.KeyValue.js +1 -1
- package/dist/Display/Display.ListItem.js +1 -1
- package/dist/Display/Display.MenuButton.js +4 -4
- package/dist/Display/Display.MenuCard.d.ts +3 -8
- package/dist/Display/Display.MenuCard.js +2 -2
- package/dist/Display/Display.MenuGrid.d.ts +2 -7
- package/dist/Display/Display.MenuGrid.js +1 -1
- package/dist/Display/Display.Monetary.d.ts +2 -6
- package/dist/Display/Display.Monetary.js +2 -2
- package/dist/Display/Display.PriceTag.js +1 -1
- package/dist/Display/Display.Rating.js +1 -1
- package/dist/Display/Display.SearchHistory.d.ts +2 -1
- package/dist/Display/Display.SearchHistory.js +1 -1
- package/dist/Display/Display.StatCard.d.ts +2 -1
- package/dist/Display/Display.StatCard.js +1 -1
- package/dist/Display/Display.StoryViewer.js +10 -6
- package/dist/Display/Display.SwipeableRow.d.ts +2 -1
- package/dist/Display/Display.Timeline.js +1 -1
- package/dist/Display/icon-map.d.ts +344 -0
- package/dist/Display/icon-map.js +86 -0
- package/dist/Display/index.d.ts +2 -0
- package/dist/Display/index.js +1 -0
- package/dist/Feedback/Feedback.Banner.js +13 -12
- package/dist/Feedback/Feedback.Empty.js +1 -1
- package/dist/Feedback/Feedback.EmptyState.d.ts +2 -1
- package/dist/Feedback/Feedback.EmptyState.js +1 -1
- package/dist/Feedback/Feedback.Error.js +1 -1
- package/dist/Feedback/Feedback.PermissionCard.d.ts +2 -1
- package/dist/Feedback/Feedback.PermissionCard.js +2 -2
- package/dist/Feedback/Toast.context.js +3 -3
- package/dist/Form/Form.ControlledDropdown.d.ts +5 -11
- package/dist/Form/Form.ControlledDropdown.js +5 -2
- package/dist/Form/Form.DatePicker.d.ts +5 -9
- package/dist/Form/Form.DatePicker.js +116 -21
- package/dist/Form/Form.Dropdown.d.ts +11 -16
- package/dist/Form/Form.Dropdown.js +54 -90
- package/dist/Form/Form.FractionalQuantityInput.js +4 -11
- package/dist/Form/Form.Input.d.ts +3 -3
- package/dist/Form/Form.KeyboardForm.d.ts +2 -2
- package/dist/Form/Form.KeyboardForm.js +2 -2
- package/dist/Form/Form.KeyboardToolbar.d.ts +2 -1
- package/dist/Form/Form.KeyboardToolbar.js +3 -7
- package/dist/Form/Form.PasswordInput.js +1 -1
- package/dist/Form/Form.QuantitySelector.js +1 -1
- package/dist/Form/Form.Select.d.ts +12 -8
- package/dist/Form/Form.Select.js +64 -31
- package/dist/Form/Form.Slider.d.ts +4 -7
- package/dist/Form/Form.Slider.js +11 -10
- package/dist/Form/Form.Switch.js +2 -1
- package/dist/Form/index.d.ts +6 -14
- package/dist/Form/index.js +0 -11
- package/dist/Navigation/Navigation.AppBar.d.ts +2 -1
- package/dist/Navigation/Navigation.AppBar.js +2 -2
- package/dist/Navigation/Navigation.BottomNav.d.ts +4 -8
- package/dist/Navigation/Navigation.BottomNav.js +2 -2
- package/dist/Navigation/Navigation.CollapsingHeader.js +3 -2
- package/dist/Navigation/Navigation.Menu.d.ts +16 -11
- package/dist/Navigation/Navigation.Menu.js +97 -42
- package/dist/Navigation/Navigation.Search.js +2 -2
- package/dist/Navigation/Navigation.SearchBar.js +3 -4
- package/dist/Navigation/Navigation.SegmentedControl.d.ts +7 -25
- package/dist/Navigation/Navigation.SegmentedControl.js +18 -39
- package/dist/Navigation/Navigation.Steps.js +1 -1
- package/dist/Navigation/Navigation.Tabs.d.ts +2 -1
- package/dist/Navigation/index.d.ts +0 -6
- package/dist/Navigation/index.js +0 -8
- package/dist/Typography/Typography.SelectableText.js +3 -7
- package/dist/Typography/Typography.Text.d.ts +1 -6
- package/dist/Typography/Typography.Text.js +3 -6
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -4
- package/dist/layouts/AuthContainer.d.ts +4 -2
- package/dist/layouts/AuthContainer.js +3 -4
- package/dist/layouts/Container.d.ts +0 -4
- package/dist/layouts/Container.js +3 -4
- package/dist/layouts/ScrollContainer.d.ts +7 -3
- package/dist/layouts/ScrollContainer.js +5 -4
- package/dist/primitives/BaseButton.d.ts +2 -1
- package/dist/theme/build.js +0 -4
- package/dist/theme/css-vars.js +0 -4
- package/dist/theme/dark.js +2 -6
- package/dist/theme/default.js +1 -5
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +1 -1
- package/dist/theme/types.d.ts +0 -11
- package/dist/theme/typography.d.ts +8 -7
- package/dist/theme/typography.js +25 -4
- package/dist/utils/timezone.d.ts +0 -5
- package/dist/views/AuthFormView.d.ts +3 -1
- package/dist/views/AuthFormView.js +2 -2
- package/dist/views/FormViewV2.d.ts +6 -13
- package/dist/views/FormViewV2.js +29 -25
- package/dist/views/ListViewV2.context.d.ts +5 -5
- package/dist/views/ListViewV2.d.ts +23 -18
- package/dist/views/ListViewV2.js +45 -48
- package/dist/views/types/IListView.d.ts +5 -4
- package/dist/views/types/IListView.js +18 -15
- package/dist/widgets/CollectionOptions.d.ts +2 -2
- package/dist/widgets/CollectionOptions.js +92 -65
- package/dist/widgets/FilterBar.js +1 -1
- package/dist/widgets/PromoModal.js +10 -4
- package/dist/widgets/QuickActions.d.ts +2 -7
- package/dist/widgets/QuickActions.js +1 -1
- package/dist/widgets/ReorderableList.js +3 -3
- package/dist/widgets/TimeZoneSelectorModal.d.ts +1 -6
- package/dist/widgets/TimeZoneSelectorModal.js +17 -12
- package/dist/widgets/index.d.ts +0 -11
- package/dist/widgets/index.js +0 -7
- package/package.json +36 -38
- package/tailwind.preset.js +0 -4
- package/dist/Dialog/BottomSheet/BottomSheet.Root.d.ts +0 -324
- package/dist/Dialog/BottomSheet/BottomSheet.Root.js +0 -373
- package/dist/Dialog/BottomSheet/index.d.ts +0 -1
- package/dist/Dialog/BottomSheet/index.js +0 -1
- package/dist/Dialog/Dialog.NativeSheet.d.ts +0 -10
- package/dist/Dialog/Dialog.NativeSheet.js +0 -21
- package/dist/Form/Form.Button.d.ts +0 -3
- package/dist/Form/Form.Button.js +0 -1
- package/dist/Form/Form.FAB.d.ts +0 -3
- package/dist/Form/Form.FAB.js +0 -1
- package/dist/Form/Form.FilterButton.d.ts +0 -3
- package/dist/Form/Form.FilterButton.js +0 -1
- package/dist/Form/Form.IconButton.d.ts +0 -3
- package/dist/Form/Form.IconButton.js +0 -1
- package/dist/Form/Form.SearchBar.d.ts +0 -13
- package/dist/Form/Form.SearchBar.js +0 -26
- package/dist/Navigation/Navigation.Header.d.ts +0 -16
- package/dist/Navigation/Navigation.Header.js +0 -17
- package/dist/Navigation/Navigation.HeaderToolbar.d.ts +0 -15
- package/dist/Navigation/Navigation.HeaderToolbar.js +0 -18
- package/dist/Navigation/Navigation.TabIcon.d.ts +0 -18
- package/dist/Navigation/Navigation.TabIcon.js +0 -12
- package/dist/Navigation/Navigation.TabItem.d.ts +0 -19
- package/dist/Navigation/Navigation.TabItem.js +0 -13
- package/dist/icons/OdooIcon.d.ts +0 -11
- package/dist/icons/OdooIcon.js +0 -11
- package/dist/icons/PrinterIcon.d.ts +0 -9
- package/dist/icons/PrinterIcon.js +0 -9
- package/dist/layouts/TabNavigatorLayout.d.ts +0 -26
- package/dist/layouts/TabNavigatorLayout.js +0 -60
- package/dist/utils/icon.d.ts +0 -1
- package/dist/utils/icon.js +0 -1
- package/dist/widgets/CircleButton.d.ts +0 -3
- package/dist/widgets/CircleButton.js +0 -1
- package/dist/widgets/GeoPermissionCard.d.ts +0 -13
- package/dist/widgets/GeoPermissionCard.js +0 -24
- package/dist/widgets/HomeHeader.d.ts +0 -15
- package/dist/widgets/HomeHeader.js +0 -13
- package/dist/widgets/MenuCard.d.ts +0 -3
- package/dist/widgets/MenuCard.js +0 -1
- package/dist/widgets/MenuGrid.d.ts +0 -5
- package/dist/widgets/MenuGrid.js +0 -1
- package/dist/widgets/MenuSection.d.ts +0 -3
- package/dist/widgets/MenuSection.js +0 -1
- package/dist/widgets/ScreenHeader.d.ts +0 -25
- package/dist/widgets/ScreenHeader.js +0 -32
- package/dist/widgets/TimeZoneSelector.d.ts +0 -12
- package/dist/widgets/TimeZoneSelector.js +0 -24
|
@@ -114,6 +114,6 @@ function Carousel({ data, renderItem, keyExtractor, itemWidth, gap = 12, showDot
|
|
|
114
114
|
},
|
|
115
115
|
dotStyle,
|
|
116
116
|
index === current ? activeDotStyle : undefined,
|
|
117
|
-
] }, keys[index]))) })) : null, data.length > 1 ? (renderControls ? (renderControls(controls)) : (_jsxs(View, { className: controlsClassName ?? "flex-row items-center justify-center gap-3 mt-2", children: [_jsx(IconButton, { accessibilityLabel: previousAccessibilityLabel, disabled: !controls.canPrevious, icon: "
|
|
117
|
+
] }, keys[index]))) })) : null, data.length > 1 ? (renderControls ? (renderControls(controls)) : (_jsxs(View, { className: controlsClassName ?? "flex-row items-center justify-center gap-3 mt-2", children: [_jsx(IconButton, { accessibilityLabel: previousAccessibilityLabel, disabled: !controls.canPrevious, icon: "back", onPress: controls.previous }), _jsx(Typography.Text, { ...paginationTextProps, accessibilityLiveRegion: "polite", children: formatPageLabel(current, data.length) }), _jsx(IconButton, { accessibilityLabel: nextAccessibilityLabel, disabled: !controls.canNext, icon: "next", onPress: controls.next })] }))) : null] }));
|
|
118
118
|
}
|
|
119
119
|
export default Carousel;
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ComponentType } from "react";
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
3
2
|
export interface CircleButtonProps {
|
|
4
|
-
iconType?: IconType;
|
|
5
3
|
size?: "sm" | "md" | "lg";
|
|
6
4
|
color?: string;
|
|
7
5
|
variant?: "primary" | "secondary" | "accent" | "success" | "danger" | "warning";
|
|
8
6
|
className?: string;
|
|
9
|
-
|
|
10
|
-
size?: number;
|
|
11
|
-
color?: string;
|
|
12
|
-
}>;
|
|
7
|
+
icon: IconName;
|
|
13
8
|
}
|
|
14
|
-
export declare function CircleButton({
|
|
9
|
+
export declare function CircleButton({ size, color, variant, className, icon, }: CircleButtonProps): import("react").JSX.Element;
|
|
15
10
|
export default CircleButton;
|
|
@@ -31,9 +31,9 @@ const SIZE_MAP = {
|
|
|
31
31
|
md: { icon: 30 },
|
|
32
32
|
lg: { icon: 40 },
|
|
33
33
|
};
|
|
34
|
-
export function CircleButton({
|
|
34
|
+
export function CircleButton({ size = "md", color, variant = "accent", className, icon, }) {
|
|
35
35
|
const theme = useTheme();
|
|
36
36
|
const iconColor = color ?? theme.text.inverse;
|
|
37
|
-
return (_jsx(View, { className: cn(circleButtonVariants({ size, variant }), className), children: _jsx(Icon, { color: iconColor,
|
|
37
|
+
return (_jsx(View, { className: cn(circleButtonVariants({ size, variant }), className), children: _jsx(Icon, { color: iconColor, name: icon, size: SIZE_MAP[size].icon }) }));
|
|
38
38
|
}
|
|
39
39
|
export default CircleButton;
|
|
@@ -73,10 +73,6 @@ function CopyableText({ value, getValue, label, className, accessibilityLabel, t
|
|
|
73
73
|
justifyContent: selectable ? "center" : "flex-start",
|
|
74
74
|
gap: 8,
|
|
75
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] }));
|
|
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 ? "check" : status === "error" ? "error" : "copy", size: 20 })) })] })] }), status === "error" ? (_jsx(Typography.Text, { accessibilityLiveRegion: "polite", className: "text-danger", variant: "bodySmall", children: "No se pudo copiar. Toca para reintentar." })) : null] }));
|
|
81
77
|
}
|
|
82
78
|
export default CopyableText;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
1
2
|
import { typographyVariants } from "../theme/typography.js";
|
|
2
3
|
import { type StyleProp, type TextStyle } from "react-native";
|
|
3
4
|
type DateFormat = "short" | "long" | "numeric";
|
|
@@ -22,8 +23,8 @@ interface DateFieldProps {
|
|
|
22
23
|
timezone?: string;
|
|
23
24
|
/** App-like layout. Default `inline` (no visual change vs. previous version). */
|
|
24
25
|
variant?: DateVariant;
|
|
25
|
-
/** Override the
|
|
26
|
-
icon?:
|
|
26
|
+
/** Override the semantic icon. Defaults: calendar, or time if `showTime`. */
|
|
27
|
+
icon?: IconName;
|
|
27
28
|
/** Show relative time ("hace 2 h") instead of the absolute date. */
|
|
28
29
|
relative?: boolean;
|
|
29
30
|
}
|
|
@@ -30,10 +30,10 @@ function DateField({ value, format = "short", prefix = "", textVariant = "body",
|
|
|
30
30
|
: formatDateWithDefaultTimezone(value, { showTime, locale });
|
|
31
31
|
const formatted = value && relative ? relativeTime(value) : absolute;
|
|
32
32
|
const text = prefix ? `${prefix}${formatted}` : formatted;
|
|
33
|
-
const iconName = icon ?? (showTime && !relative ? "time
|
|
34
|
-
const label = (_jsx(Typography.Text, { bold: bold,
|
|
33
|
+
const iconName = icon ?? (showTime && !relative ? "time" : "calendar");
|
|
34
|
+
const label = (_jsx(Typography.Text, { bold: bold, semibold: semibold && !bold, style: [{ color }, style], variant: textVariant, children: text }));
|
|
35
35
|
if (variant === "inline") {
|
|
36
|
-
return (_jsx(Typography.Text, { bold: bold, className: className,
|
|
36
|
+
return (_jsx(Typography.Text, { bold: bold, className: className, semibold: semibold && !bold, style: [{ color }, style], variant: textVariant, children: text }));
|
|
37
37
|
}
|
|
38
38
|
if (variant === "pill") {
|
|
39
39
|
return (_jsxs(View, { className: cn("flex-row items-center self-start gap-1.5 rounded-full bg-bg-muted px-2.5 py-1", className), children: [_jsx(Icon, { color: color ?? theme.icon.secondary, name: iconName, size: 14 }), label] }));
|
|
@@ -64,15 +64,7 @@ declare const GRADIENT_PRESETS: {
|
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
66
|
};
|
|
67
|
-
|
|
68
|
-
* Aliases kept for backwards compatibility. These were the original names; the
|
|
69
|
-
* canonical ones are above. Use the canonical names in new code.
|
|
70
|
-
* @deprecated use `warm` instead of `gold-mesh`.
|
|
71
|
-
*/
|
|
72
|
-
declare const DEPRECATED_PRESETS: {
|
|
73
|
-
readonly "gold-mesh": "warm";
|
|
74
|
-
};
|
|
75
|
-
export type GradientPreset = keyof typeof GRADIENT_PRESETS | keyof typeof DEPRECATED_PRESETS | "brand";
|
|
67
|
+
export type GradientPreset = keyof typeof GRADIENT_PRESETS | "brand";
|
|
76
68
|
declare const surface: import("tailwind-variants").TVReturnType<{
|
|
77
69
|
radius: {
|
|
78
70
|
none: "rounded-none";
|
|
@@ -125,6 +117,57 @@ export interface GradientSurfaceProps extends VariantProps<typeof surface> {
|
|
|
125
117
|
style?: ViewStyle;
|
|
126
118
|
testID?: string;
|
|
127
119
|
}
|
|
120
|
+
export declare function resolveGradientPreset(preset?: GradientPreset): {
|
|
121
|
+
colors: readonly [string, string] | readonly ["#1A1714", "#C89B3C", "#B88A2E"] | readonly ["#1C3765", "#2A4A85", "#8FA9E8"];
|
|
122
|
+
start: {
|
|
123
|
+
readonly x: 0;
|
|
124
|
+
readonly y: 0;
|
|
125
|
+
};
|
|
126
|
+
end: {
|
|
127
|
+
readonly x: 1;
|
|
128
|
+
readonly y: 1;
|
|
129
|
+
};
|
|
130
|
+
} | {
|
|
131
|
+
colors: readonly [string, string] | readonly ["#1A1714", "#C89B3C", "#B88A2E"] | readonly ["#1C3765", "#2A4A85", "#8FA9E8"];
|
|
132
|
+
start: {
|
|
133
|
+
readonly x: 0;
|
|
134
|
+
readonly y: 0;
|
|
135
|
+
};
|
|
136
|
+
end: {
|
|
137
|
+
readonly x: 1;
|
|
138
|
+
readonly y: 1;
|
|
139
|
+
};
|
|
140
|
+
} | {
|
|
141
|
+
colors: readonly [string, string] | readonly ["#1A1714", "#C89B3C", "#B88A2E"] | readonly ["#1C3765", "#2A4A85", "#8FA9E8"];
|
|
142
|
+
start: {
|
|
143
|
+
readonly x: 0;
|
|
144
|
+
readonly y: 0;
|
|
145
|
+
};
|
|
146
|
+
end: {
|
|
147
|
+
readonly x: 1;
|
|
148
|
+
readonly y: 1;
|
|
149
|
+
};
|
|
150
|
+
} | {
|
|
151
|
+
colors: readonly [string, string] | readonly ["#1A1714", "#C89B3C", "#B88A2E"] | readonly ["#1C3765", "#2A4A85", "#8FA9E8"];
|
|
152
|
+
start: {
|
|
153
|
+
readonly x: 0;
|
|
154
|
+
readonly y: 0;
|
|
155
|
+
};
|
|
156
|
+
end: {
|
|
157
|
+
readonly x: 1;
|
|
158
|
+
readonly y: 1;
|
|
159
|
+
};
|
|
160
|
+
} | {
|
|
161
|
+
colors: readonly [string, string] | readonly ["#1A1714", "#C89B3C", "#B88A2E"] | readonly ["#1C3765", "#2A4A85", "#8FA9E8"];
|
|
162
|
+
start: {
|
|
163
|
+
readonly x: 0;
|
|
164
|
+
readonly y: 0;
|
|
165
|
+
};
|
|
166
|
+
end: {
|
|
167
|
+
readonly x: 1;
|
|
168
|
+
readonly y: 1;
|
|
169
|
+
};
|
|
170
|
+
};
|
|
128
171
|
/**
|
|
129
172
|
* Modern gradient surface. Wraps `expo-linear-gradient` with named presets +
|
|
130
173
|
* tokenized radius/padding. iOS + Android (no native dep beyond the already-peer
|
|
@@ -35,14 +35,6 @@ const GRADIENT_PRESETS = {
|
|
|
35
35
|
end: { x: 1, y: 1 },
|
|
36
36
|
},
|
|
37
37
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Aliases kept for backwards compatibility. These were the original names; the
|
|
40
|
-
* canonical ones are above. Use the canonical names in new code.
|
|
41
|
-
* @deprecated use `warm` instead of `gold-mesh`.
|
|
42
|
-
*/
|
|
43
|
-
const DEPRECATED_PRESETS = {
|
|
44
|
-
"gold-mesh": "warm",
|
|
45
|
-
};
|
|
46
38
|
const surface = tv({
|
|
47
39
|
variants: {
|
|
48
40
|
radius: {
|
|
@@ -60,18 +52,21 @@ const surface = tv({
|
|
|
60
52
|
},
|
|
61
53
|
defaultVariants: { radius: "lg", padding: "none" },
|
|
62
54
|
});
|
|
55
|
+
export function resolveGradientPreset(preset = "warm") {
|
|
56
|
+
const surface = preset === "brand" ? GRADIENT_PRESETS.warm : GRADIENT_PRESETS[preset];
|
|
57
|
+
return {
|
|
58
|
+
...surface,
|
|
59
|
+
colors: preset === "brand" ? theme.gradient.primary : surface.colors,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
63
62
|
/**
|
|
64
63
|
* Modern gradient surface. Wraps `expo-linear-gradient` with named presets +
|
|
65
64
|
* tokenized radius/padding. iOS + Android (no native dep beyond the already-peer
|
|
66
65
|
* `expo-linear-gradient`). Replaces the legacy `GradientContainer`.
|
|
67
66
|
*/
|
|
68
67
|
function GradientSurface({ preset = "warm", colors, start, end, radius, padding, children, className, style, testID, }) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
: preset);
|
|
72
|
-
const p = resolvedPreset === "brand" ? GRADIENT_PRESETS.warm : GRADIENT_PRESETS[resolvedPreset];
|
|
73
|
-
const presetColors = resolvedPreset === "brand" ? theme.gradient.primary : p.colors;
|
|
74
|
-
const resolvedColors = (colors ?? presetColors);
|
|
68
|
+
const p = resolveGradientPreset(preset);
|
|
69
|
+
const resolvedColors = colors ?? p.colors;
|
|
75
70
|
return (_jsxs(View, { className: cn("overflow-hidden", surface({ radius })), style: style, testID: testID, children: [_jsx(LinearGradient, { colors: [...resolvedColors], end: end ?? p.end, start: start ?? p.start, style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0 } }), _jsx(View, { className: cn(surface({ padding }), className), children: children })] }));
|
|
76
71
|
}
|
|
77
72
|
export default GradientSurface;
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type IconName } from "./icon-map.js";
|
|
2
|
+
import type { FC } from "react";
|
|
3
|
+
import { type ColorValue, type ViewProps } from "react-native";
|
|
4
|
+
export type IconProps = Omit<ViewProps, "children"> & {
|
|
5
|
+
name: IconName;
|
|
5
6
|
size?: number;
|
|
6
|
-
color?:
|
|
7
|
-
type?: IconType;
|
|
8
|
-
customIcon?: ComponentType<{
|
|
9
|
-
size?: number;
|
|
10
|
-
color?: string;
|
|
11
|
-
}>;
|
|
7
|
+
color?: ColorValue;
|
|
12
8
|
className?: string;
|
|
13
|
-
}
|
|
9
|
+
};
|
|
14
10
|
declare const Icon: FC<IconProps>;
|
|
15
11
|
export default Icon;
|
|
@@ -1,36 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx } from "nativewind/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { ICON_MAP } from "./icon-map.js";
|
|
3
3
|
import { useTheme } from "../theme/index.js";
|
|
4
|
+
import { cn } from "../theme/tw.js";
|
|
5
|
+
import { SymbolView } from "expo-symbols";
|
|
4
6
|
import { View } from "react-native";
|
|
5
|
-
const Icon = ({ name, size = 24, color,
|
|
7
|
+
const Icon = ({ name, size = 24, color, className, style, accessible, accessibilityLabel, accessibilityRole, ...viewProps }) => {
|
|
6
8
|
const theme = useTheme();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
case "material":
|
|
19
|
-
return _jsx(MaterialIcons, { color: iconColor, name: name, size: size });
|
|
20
|
-
case "fontawesome5":
|
|
21
|
-
return _jsx(FontAwesome5, { color: iconColor, name: name, size: size });
|
|
22
|
-
case "simplelineicons":
|
|
23
|
-
return _jsx(SimpleLineIcons, { color: iconColor, name: name, size: size });
|
|
24
|
-
case "antdesign":
|
|
25
|
-
return _jsx(AntDesign, { color: iconColor, name: name, size: size });
|
|
26
|
-
case "feather":
|
|
27
|
-
return _jsx(Feather, { color: iconColor, name: name, size: size });
|
|
28
|
-
case "MaterialCommunityIcons":
|
|
29
|
-
return _jsx(MaterialCommunityIcons, { color: iconColor, name: name, size: size });
|
|
30
|
-
default:
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
return (_jsx(View, { className: `justify-center items-center ${className || ""}`, children: renderIcon() }));
|
|
9
|
+
if (typeof name !== "string" || !Object.hasOwn(ICON_MAP, name)) {
|
|
10
|
+
throw new Error(`Unknown icon name: ${String(name)}`);
|
|
11
|
+
}
|
|
12
|
+
if (!Number.isFinite(size) || size <= 0) {
|
|
13
|
+
throw new RangeError(`Invalid icon size: ${String(size)}`);
|
|
14
|
+
}
|
|
15
|
+
if (["type", "customIcon", "fallback", "children"].some((key) => Object.hasOwn(viewProps, key))) {
|
|
16
|
+
throw new Error("Display.Icon accepts semantic names, not icon families or custom renderers");
|
|
17
|
+
}
|
|
18
|
+
const icon = ICON_MAP[name];
|
|
19
|
+
return (_jsx(View, { ...viewProps, accessibilityLabel: accessibilityLabel, accessibilityRole: accessibilityRole ?? (accessibilityLabel ? "image" : undefined), accessible: accessible ?? Boolean(accessibilityLabel), className: cn("justify-center items-center", className), style: style, children: _jsx(SymbolView, { accessibilityElementsHidden: true, accessible: false, importantForAccessibility: "no-hide-descendants", name: { ios: icon.sf, android: icon.md, web: icon.md }, size: size, tintColor: color ?? theme.text.primary }) }));
|
|
35
20
|
};
|
|
36
21
|
export default Icon;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
1
2
|
import { type ExpoImageProps } from "./Display.ExpoImage.js";
|
|
2
3
|
import { type ImageSource } from "../utils/image.js";
|
|
3
4
|
import { type ReactNode } from "react";
|
|
@@ -8,7 +9,7 @@ export interface DisplayImageProps extends Omit<ExpoImageProps, "source" | "styl
|
|
|
8
9
|
height?: number;
|
|
9
10
|
aspectRatio?: number;
|
|
10
11
|
radius?: number;
|
|
11
|
-
fallbackIcon?:
|
|
12
|
+
fallbackIcon?: IconName;
|
|
12
13
|
className?: string;
|
|
13
14
|
style?: ExpoImageProps["style"];
|
|
14
15
|
containerStyle?: StyleProp<ViewStyle>;
|
|
@@ -8,7 +8,7 @@ import { cn } from "../theme/tw.js";
|
|
|
8
8
|
import { imageSourceKey } from "../utils/image.js";
|
|
9
9
|
import { useLayoutEffect, useRef, useState } from "react";
|
|
10
10
|
import { View } from "react-native";
|
|
11
|
-
function ImageContent({ source, width = "100%", height, aspectRatio, radius = 12, contentFit = "cover", placeholder, fallbackIcon = "image
|
|
11
|
+
function ImageContent({ source, width = "100%", height, aspectRatio, radius = 12, contentFit = "cover", placeholder, fallbackIcon = "image", className, style, containerStyle, renderError, testID, onError, onLoadStart, onLoadEnd, onLoad, accessibilityLabel, accessible, retry, ...imageProps }) {
|
|
12
12
|
const theme = useTheme();
|
|
13
13
|
const [loading, setLoading] = useState(true);
|
|
14
14
|
const [failed, setFailed] = useState(false);
|
|
@@ -6,6 +6,6 @@ import CopyableText from "./Display.CopyableText";
|
|
|
6
6
|
function KeyValue({ label, value, align = "row", className, testID, copyable = false, selectable = false, }) {
|
|
7
7
|
const { width, fontScale } = useWindowDimensions();
|
|
8
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: "
|
|
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: "min-w-0 shrink text-text-secondary", variant: "labelSmall", 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)] }));
|
|
10
10
|
}
|
|
11
11
|
export default KeyValue;
|
|
@@ -14,7 +14,7 @@ function ListItem({ title, subtitle, leading, trailing, chevron = false, onPress
|
|
|
14
14
|
(value !== undefined || trailing != null) &&
|
|
15
15
|
(layout === "stacked" || (layout === "auto" && (fontScale > 1.3 || width < 360)));
|
|
16
16
|
const right = trailing ??
|
|
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: "
|
|
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: "next", size: 18 }) })) : null] })) : null);
|
|
18
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
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);
|
|
20
20
|
if (onPress) {
|
|
@@ -12,7 +12,7 @@ function BadgeChip({ badge }) {
|
|
|
12
12
|
flexDirection: "row",
|
|
13
13
|
alignItems: "center",
|
|
14
14
|
gap: 4,
|
|
15
|
-
backgroundColor: theme.
|
|
15
|
+
backgroundColor: theme.container.success,
|
|
16
16
|
paddingHorizontal: 8,
|
|
17
17
|
paddingVertical: 3,
|
|
18
18
|
borderRadius: 999,
|
|
@@ -23,7 +23,7 @@ function BadgeChip({ badge }) {
|
|
|
23
23
|
flexDirection: "row",
|
|
24
24
|
alignItems: "center",
|
|
25
25
|
gap: 4,
|
|
26
|
-
backgroundColor: theme.
|
|
26
|
+
backgroundColor: theme.container.warning,
|
|
27
27
|
paddingHorizontal: 8,
|
|
28
28
|
paddingVertical: 3,
|
|
29
29
|
borderRadius: 999,
|
|
@@ -63,11 +63,11 @@ const menuButton = tv({
|
|
|
63
63
|
label: "text-text-primary",
|
|
64
64
|
},
|
|
65
65
|
danger: {
|
|
66
|
-
iconContainer: "bg-danger
|
|
66
|
+
iconContainer: "bg-container-danger",
|
|
67
67
|
label: "text-danger",
|
|
68
68
|
},
|
|
69
69
|
success: {
|
|
70
|
-
iconContainer: "bg-success
|
|
70
|
+
iconContainer: "bg-container-success",
|
|
71
71
|
label: "text-success",
|
|
72
72
|
},
|
|
73
73
|
},
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ComponentType } from "react";
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
3
2
|
export interface MenuCardProps {
|
|
4
3
|
title: string;
|
|
5
|
-
iconType?: IconType;
|
|
6
4
|
onPress?: () => void;
|
|
7
|
-
|
|
8
|
-
size?: number;
|
|
9
|
-
color?: string;
|
|
10
|
-
}>;
|
|
5
|
+
icon: IconName;
|
|
11
6
|
/** `"md"` = 2-column grid (default). `"sm"` = 3-column grid, smaller icon. */
|
|
12
7
|
size?: "sm" | "md";
|
|
13
8
|
}
|
|
14
|
-
export declare function MenuCard({ title,
|
|
9
|
+
export declare function MenuCard({ title, onPress, icon, size }: MenuCardProps): import("react").JSX.Element;
|
|
15
10
|
export default MenuCard;
|
|
@@ -3,7 +3,7 @@ import CircleButton from "./Display.CircleButton.js";
|
|
|
3
3
|
import { useTheme } from "../theme/index.js";
|
|
4
4
|
import { Typography } from "../Typography/index.js";
|
|
5
5
|
import { TouchableOpacity, View } from "react-native";
|
|
6
|
-
export function MenuCard({ title,
|
|
6
|
+
export function MenuCard({ title, onPress, icon, size = "md" }) {
|
|
7
7
|
const theme = useTheme();
|
|
8
8
|
const isSmall = size === "sm";
|
|
9
9
|
return (_jsx(TouchableOpacity, { activeOpacity: 0.7, onPress: onPress, style: {
|
|
@@ -15,7 +15,7 @@ export function MenuCard({ title, iconType = "ionicons", onPress, customIcon, si
|
|
|
15
15
|
borderWidth: 1,
|
|
16
16
|
borderColor: theme.border.default,
|
|
17
17
|
...theme.shadow.sm,
|
|
18
|
-
}, children: _jsxs(View, { style: { alignItems: "center", justifyContent: "center" }, children: [_jsx(CircleButton, {
|
|
18
|
+
}, children: _jsxs(View, { style: { alignItems: "center", justifyContent: "center" }, children: [_jsx(CircleButton, { icon: icon, size: isSmall ? "sm" : "md" }), _jsx(Typography.Text, { numberOfLines: 2, style: {
|
|
19
19
|
color: theme.text.primary,
|
|
20
20
|
marginTop: isSmall ? 8 : 12,
|
|
21
21
|
textAlign: "center",
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ComponentType } from "react";
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
3
2
|
export interface MenuGridItem {
|
|
4
3
|
id: string;
|
|
5
4
|
title: string;
|
|
6
|
-
iconType?: IconType;
|
|
7
5
|
onPress?: () => void;
|
|
8
|
-
|
|
9
|
-
size?: number;
|
|
10
|
-
color?: string;
|
|
11
|
-
}>;
|
|
6
|
+
icon: IconName;
|
|
12
7
|
}
|
|
13
8
|
export interface MenuGridProps {
|
|
14
9
|
items: MenuGridItem[];
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx } from "nativewind/jsx-runtime";
|
|
|
2
2
|
import MenuCard from "./Display.MenuCard.js";
|
|
3
3
|
import { View } from "react-native";
|
|
4
4
|
export function MenuGrid({ items, size = "md" }) {
|
|
5
|
-
return (_jsx(View, { className: "flex-row flex-wrap justify-start p-2 bg-bg-page", children: items.map((item) => (_jsx(MenuCard, {
|
|
5
|
+
return (_jsx(View, { className: "flex-row flex-wrap justify-start p-2 bg-bg-page", children: items.map((item) => (_jsx(MenuCard, { icon: item.icon, onPress: item.onPress, size: size, title: item.title }, item.id))) }));
|
|
6
6
|
}
|
|
7
7
|
export default MenuGrid;
|
|
@@ -4,16 +4,12 @@ interface MonetaryFieldProps {
|
|
|
4
4
|
value: number | string | null | undefined;
|
|
5
5
|
currencySymbol?: string;
|
|
6
6
|
prefix?: string;
|
|
7
|
-
/** @deprecated Use className="text-{color}" instead */
|
|
8
|
-
color?: string;
|
|
9
7
|
textVariant?: keyof typeof typographyVariants;
|
|
10
|
-
/** @deprecated Use className for styling */
|
|
11
8
|
style?: StyleProp<TextStyle>;
|
|
12
|
-
|
|
13
|
-
symbolColor?: string;
|
|
9
|
+
symbolStyle?: StyleProp<TextStyle>;
|
|
14
10
|
semibold?: boolean;
|
|
15
11
|
bold?: boolean;
|
|
16
12
|
className?: string;
|
|
17
13
|
}
|
|
18
|
-
declare function MonetaryField({ value, currencySymbol, prefix,
|
|
14
|
+
declare function MonetaryField({ value, currencySymbol, prefix, textVariant, style, symbolStyle, semibold, bold, className, }: MonetaryFieldProps): import("react").JSX.Element;
|
|
19
15
|
export default MonetaryField;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
2
|
import { Typography } from "../Typography/index.js";
|
|
3
3
|
import { formatTwoDecimals } from "../utils/monetary.js";
|
|
4
|
-
function MonetaryField({ value, currencySymbol = "₡", prefix = "",
|
|
4
|
+
function MonetaryField({ value, currencySymbol = "₡", prefix = "", textVariant = "data", style = {}, symbolStyle, semibold = true, bold = false, className, }) {
|
|
5
5
|
const isEmptyValue = value === null || value === undefined || value === "";
|
|
6
6
|
const formatted = isEmptyValue ? "0.00" : formatTwoDecimals(value);
|
|
7
|
-
return (_jsxs(Typography.Text, { bold: bold, className: className,
|
|
7
|
+
return (_jsxs(Typography.Text, { bold: bold, className: className, semibold: semibold && !bold, style: style, variant: textVariant, children: [_jsx(Typography.Text, { className: className, style: [style, symbolStyle], variant: textVariant, children: currencySymbol }), " ", prefix && `${prefix} `, formatted] }));
|
|
8
8
|
}
|
|
9
9
|
export default MonetaryField;
|
|
@@ -18,6 +18,6 @@ function PriceTag({ amount, originalAmount, currency = "Bs", size = "md", classN
|
|
|
18
18
|
const variants = sizeMap[size];
|
|
19
19
|
const hasDiscount = typeof originalAmount === "number" && originalAmount > amount;
|
|
20
20
|
const off = hasDiscount ? Math.round((1 - amount / originalAmount) * 100) : 0;
|
|
21
|
-
return (_jsxs(View, { className: cn("flex-row items-baseline gap-2", className), testID: testID, children: [_jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: variants.price, children: format(amount, currency) }), hasDiscount ? (_jsxs(_Fragment, { children: [_jsx(Typography.Text, { className: "text-text-tertiary", style: { textDecorationLine: "line-through" }, variant: variants.original, children: format(originalAmount, currency) }), _jsx(View, { className: "bg-danger
|
|
21
|
+
return (_jsxs(View, { className: cn("flex-row items-baseline gap-2", className), testID: testID, children: [_jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: variants.price, children: format(amount, currency) }), hasDiscount ? (_jsxs(_Fragment, { children: [_jsx(Typography.Text, { className: "text-text-tertiary", style: { textDecorationLine: "line-through" }, variant: variants.original, children: format(originalAmount, currency) }), _jsx(View, { className: "bg-container-danger rounded px-1.5 py-0.5", children: _jsxs(Typography.Text, { className: "text-danger font-semibold", variant: "caption", children: ["-", off, "%"] }) })] })) : null] }));
|
|
22
22
|
}
|
|
23
23
|
export default PriceTag;
|
|
@@ -7,7 +7,7 @@ function Rating({ value, max = 5, size = 24, onChange, readOnly = false, classNa
|
|
|
7
7
|
const interactive = !readOnly && !!onChange;
|
|
8
8
|
return (_jsx(View, { accessibilityLabel: `Calificación ${value} de ${max}`, accessibilityRole: interactive ? "adjustable" : "image", className: className, style: { flexDirection: "row", gap: 4 }, testID: testID, children: Array.from({ length: max }).map((_, index) => {
|
|
9
9
|
const filled = index < Math.round(value);
|
|
10
|
-
const star = (_jsx(Icon, { color: filled ? theme.warning : theme.icon.disabled, name: filled ? "
|
|
10
|
+
const star = (_jsx(Icon, { color: filled ? theme.warning : theme.icon.disabled, name: filled ? "rating" : "rating-empty", size: size }));
|
|
11
11
|
if (!interactive)
|
|
12
12
|
return _jsx(View, { children: star }, index);
|
|
13
13
|
return (_jsx(Pressable, { accessibilityLabel: `${index + 1} estrellas`, hitSlop: 6, onPress: () => onChange?.(index + 1), children: star }, index));
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import type { IconName } from "./index.js";
|
|
1
2
|
export interface SearchHistoryProps {
|
|
2
3
|
items: string[];
|
|
3
4
|
onSelect: (value: string) => void;
|
|
4
5
|
onRemove: (value: string) => void;
|
|
5
6
|
onClearAll?: () => void;
|
|
6
7
|
title?: string;
|
|
7
|
-
icon?:
|
|
8
|
+
icon?: IconName;
|
|
8
9
|
className?: string;
|
|
9
10
|
testID?: string;
|
|
10
11
|
}
|
|
@@ -5,7 +5,7 @@ import { theme } from "../theme/index.js";
|
|
|
5
5
|
import { cn } from "../theme/tw.js";
|
|
6
6
|
import { Typography } from "../Typography/index.js";
|
|
7
7
|
import { View } from "react-native";
|
|
8
|
-
function SearchHistory({ items, onSelect, onRemove, onClearAll, title = "Búsquedas recientes", icon = "time
|
|
8
|
+
function SearchHistory({ items, onSelect, onRemove, onClearAll, title = "Búsquedas recientes", icon = "time", className, testID, }) {
|
|
9
9
|
if (items.length === 0)
|
|
10
10
|
return null;
|
|
11
11
|
return (_jsxs(View, { className: cn("gap-1", className), testID: testID, children: [_jsxs(View, { className: "flex-row items-center justify-between px-4 py-1", children: [_jsx(Typography.Text, { className: "text-text-secondary", semibold: true, variant: "bodySmall", children: title }), onClearAll ? (_jsx(Pressable, { accessibilityLabel: "Borrar todo", hitSlop: 8, onPress: onClearAll, children: _jsx(Typography.Text, { className: "text-text-accent", variant: "bodySmall", children: "Borrar todo" }) })) : null] }), items.map((value) => (_jsxs(Pressable, { accessibilityLabel: value, className: "flex-row items-center gap-3 px-4 py-2.5", onPress: () => onSelect(value), children: [_jsx(Icon, { color: theme.icon.tertiary, name: icon, size: 18 }), _jsx(Typography.Text, { className: "flex-1 text-text-primary", numberOfLines: 1, children: value }), _jsx(Pressable, { accessibilityLabel: `Quitar ${value}`, hitSlop: 10, onPress: () => onRemove(value), children: _jsx(Icon, { color: theme.icon.tertiary, name: "close", size: 16 }) })] }, value)))] }));
|
|
@@ -8,6 +8,6 @@ function StatCard({ label, value, icon, delta, deltaSuffix = "%", hint, trailing
|
|
|
8
8
|
const hasDelta = typeof delta === "number";
|
|
9
9
|
const up = hasDelta && delta >= 0;
|
|
10
10
|
const deltaColor = up ? theme.success : theme.danger;
|
|
11
|
-
return (_jsxs(View, { className: cn("bg-bg-card rounded-lg border border-border-light p-4 gap-1", className), style: theme.shadow.sm, testID: testID, children: [_jsxs(View, { className: "flex-row items-center justify-between", children: [_jsx(Typography.Text, { className: "text-text-secondary", variant: "caption", children: label }), icon ? _jsx(Icon, { color: theme.icon.secondary, name: icon, size: 18 }) : null, trailing] }), _jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: "h3", children: value }), hasDelta || hint ? (_jsxs(View, { className: "flex-row items-center gap-1", children: [hasDelta ? (_jsxs(_Fragment, { children: [_jsx(Icon, { color: deltaColor, name: up ? "
|
|
11
|
+
return (_jsxs(View, { className: cn("bg-bg-card rounded-lg border border-border-light p-4 gap-1", className), style: theme.shadow.sm, testID: testID, children: [_jsxs(View, { className: "flex-row items-center justify-between", children: [_jsx(Typography.Text, { className: "text-text-secondary", variant: "caption", children: label }), icon ? _jsx(Icon, { color: theme.icon.secondary, name: icon, size: 18 }) : null, trailing] }), _jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: "h3", children: value }), hasDelta || hint ? (_jsxs(View, { className: "flex-row items-center gap-1", children: [hasDelta ? (_jsxs(_Fragment, { children: [_jsx(Icon, { color: deltaColor, name: up ? "up" : "down", size: 14 }), _jsxs(Typography.Text, { style: { color: deltaColor }, variant: "caption", children: [Math.abs(delta), deltaSuffix] })] })) : null, hint ? (_jsx(Typography.Text, { className: "text-text-tertiary", variant: "caption", children: hint })) : null] })) : null] }));
|
|
12
12
|
}
|
|
13
13
|
export default StatCard;
|
|
@@ -2,14 +2,16 @@ import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
|
2
2
|
import ExpoImage from "./Display.ExpoImage.js";
|
|
3
3
|
import Icon from "./Display.Icon.js";
|
|
4
4
|
import Pressable from "../primitives/Pressable.js";
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from "../theme/index.js";
|
|
6
6
|
import { Typography } from "../Typography/index.js";
|
|
7
7
|
import { useReducedMotion } from "../utils/useReducedMotion.js";
|
|
8
8
|
import { LinearGradient } from "expo-linear-gradient";
|
|
9
9
|
import { Modal, Pressable as RNPressable, View } from "react-native";
|
|
10
|
+
import { KeyboardStickyView } from "react-native-keyboard-controller";
|
|
10
11
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
11
12
|
function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, subtitle, time, avatar, progress = 1, muted, paused, onToggleMute, onTogglePause, onMore, footer, testID, }) {
|
|
12
13
|
const insets = useSafeAreaInsets();
|
|
14
|
+
const theme = useTheme();
|
|
13
15
|
const reducedMotion = useReducedMotion();
|
|
14
16
|
const current = slides[index];
|
|
15
17
|
const goPrev = () => {
|
|
@@ -45,7 +47,8 @@ function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, su
|
|
|
45
47
|
left: 0,
|
|
46
48
|
right: 0,
|
|
47
49
|
paddingTop: insets.top + 8,
|
|
48
|
-
|
|
50
|
+
paddingLeft: insets.left + 10,
|
|
51
|
+
paddingRight: insets.right + 10,
|
|
49
52
|
}, children: [_jsx(View, { style: { flexDirection: "row", gap: 4 }, children: slides.map((_, i) => (_jsx(View, { style: {
|
|
50
53
|
flex: 1,
|
|
51
54
|
height: 2.5,
|
|
@@ -60,9 +63,9 @@ function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, su
|
|
|
60
63
|
? `${Math.round(progress * 100)}%`
|
|
61
64
|
: "0%",
|
|
62
65
|
backgroundColor: "#fff",
|
|
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 ? "
|
|
66
|
+
} }) }, 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 ? "mute" : "volume", 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: "more", 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: {
|
|
64
67
|
position: "absolute",
|
|
65
|
-
right: 8,
|
|
68
|
+
right: insets.right + 8,
|
|
66
69
|
top: "50%",
|
|
67
70
|
width: 36,
|
|
68
71
|
height: 36,
|
|
@@ -70,13 +73,14 @@ function StoryViewer({ visible, slides, index, onIndexChange, onClose, title, su
|
|
|
70
73
|
backgroundColor: "rgba(255,255,255,0.9)",
|
|
71
74
|
alignItems: "center",
|
|
72
75
|
justifyContent: "center",
|
|
73
|
-
}, children: _jsx(Icon, { color: theme.text.primary, name: "
|
|
76
|
+
}, children: _jsx(Icon, { color: theme.text.primary, name: "next", size: 22 }) })) : null, footer ? (_jsx(KeyboardStickyView, { style: {
|
|
74
77
|
position: "absolute",
|
|
75
78
|
left: 0,
|
|
76
79
|
right: 0,
|
|
77
80
|
bottom: 0,
|
|
78
81
|
paddingBottom: insets.bottom + 8,
|
|
79
|
-
|
|
82
|
+
paddingLeft: insets.left + 16,
|
|
83
|
+
paddingRight: insets.right + 16,
|
|
80
84
|
}, children: footer })) : null] }) }));
|
|
81
85
|
}
|
|
82
86
|
export default StoryViewer;
|