@sincpro/mobile-ui 2.0.1 → 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/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 +35 -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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
|
-
import DateTimePicker from "@
|
|
2
|
+
import DateTimePicker from "@expo/ui/community/datetime-picker";
|
|
3
|
+
import { Actions } from "../Actions/index.js";
|
|
4
|
+
import Sheet from "../Dialog/Dialog.Sheet.js";
|
|
3
5
|
import Icon from "../Display/Display.Icon.js";
|
|
4
6
|
import Pressable from "../primitives/Pressable.js";
|
|
5
|
-
import { useTheme } from "../theme/index.js";
|
|
7
|
+
import { relativeLuminance, useTheme } from "../theme/index.js";
|
|
6
8
|
import { cn } from "../theme/tw.js";
|
|
7
9
|
import { Typography } from "../Typography/index.js";
|
|
8
|
-
import { useState } from "react";
|
|
10
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
9
11
|
import { Platform, View } from "react-native";
|
|
10
12
|
function defaultFormat(value, mode) {
|
|
11
13
|
if (mode === "time")
|
|
@@ -14,26 +16,119 @@ function defaultFormat(value, mode) {
|
|
|
14
16
|
return value.toLocaleString("es-BO");
|
|
15
17
|
return value.toLocaleDateString("es-BO");
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
function
|
|
28
|
-
const
|
|
19
|
+
function comparableDate(value, mode) {
|
|
20
|
+
return mode === "date"
|
|
21
|
+
? new Date(value.getFullYear(), value.getMonth(), value.getDate()).getTime()
|
|
22
|
+
: value.getTime();
|
|
23
|
+
}
|
|
24
|
+
function withCalendarDay(base, day) {
|
|
25
|
+
const next = new Date(base);
|
|
26
|
+
next.setFullYear(day.getFullYear(), day.getMonth(), day.getDate());
|
|
27
|
+
return next;
|
|
28
|
+
}
|
|
29
|
+
function withClockTime(base, time) {
|
|
30
|
+
const next = new Date(base);
|
|
31
|
+
next.setHours(time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds());
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
function DatePicker({ value, onChange, mode = "date", label, placeholder = "Seleccionar…", format, minimumDate, maximumDate, disabled = false, readOnly = false, className, testID, }) {
|
|
29
35
|
const theme = useTheme();
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
36
|
+
const appearance = relativeLuminance(theme.bg.card) < 0.179 ? "dark" : "light";
|
|
37
|
+
const saving = useRef(false);
|
|
38
|
+
const dialogSession = useRef(0);
|
|
39
|
+
const visibleOwner = useRef(0);
|
|
40
|
+
const [open, setOpen] = useState(false);
|
|
41
|
+
const [phase, setPhase] = useState("date");
|
|
42
|
+
const [draft, setDraft] = useState(() => value ?? new Date());
|
|
43
|
+
const [pending, setPending] = useState(false);
|
|
44
|
+
const [error, setError] = useState();
|
|
45
|
+
const blocked = disabled || readOnly || pending;
|
|
46
|
+
const android = Platform.OS === "android";
|
|
47
|
+
useLayoutEffect(() => {
|
|
48
|
+
if (!android || !open)
|
|
49
|
+
return;
|
|
50
|
+
visibleOwner.current = dialogSession.current;
|
|
51
|
+
}, [android, open, phase]);
|
|
52
|
+
const fmt = format ?? ((date) => defaultFormat(date, mode));
|
|
53
|
+
const close = () => {
|
|
54
|
+
if (!saving.current)
|
|
55
|
+
setOpen(false);
|
|
56
|
+
};
|
|
57
|
+
const outOfRange = (next) => (minimumDate !== undefined &&
|
|
58
|
+
comparableDate(next, mode) < comparableDate(minimumDate, mode)) ||
|
|
59
|
+
(maximumDate !== undefined &&
|
|
60
|
+
comparableDate(next, mode) > comparableDate(maximumDate, mode));
|
|
61
|
+
const apply = async (next) => {
|
|
62
|
+
if (android)
|
|
63
|
+
setOpen(false);
|
|
64
|
+
if (blocked || saving.current)
|
|
65
|
+
return;
|
|
66
|
+
if (outOfRange(next)) {
|
|
67
|
+
setError("Selecciona una fecha y hora dentro del rango permitido.");
|
|
68
|
+
setDraft(next);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
saving.current = true;
|
|
72
|
+
setPending(true);
|
|
73
|
+
setError(undefined);
|
|
74
|
+
try {
|
|
75
|
+
await onChange(next);
|
|
33
76
|
setOpen(false);
|
|
34
|
-
|
|
35
|
-
|
|
77
|
+
}
|
|
78
|
+
catch (cause) {
|
|
79
|
+
setDraft(next);
|
|
80
|
+
setError(cause instanceof Error && cause.message.trim()
|
|
81
|
+
? cause.message
|
|
82
|
+
: "No se pudo aplicar la fecha. Vuelve a intentarlo.");
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
saving.current = false;
|
|
86
|
+
setPending(false);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const update = (date) => {
|
|
90
|
+
if (!date || blocked || saving.current)
|
|
91
|
+
return;
|
|
92
|
+
setDraft(date);
|
|
93
|
+
setError(undefined);
|
|
94
|
+
};
|
|
95
|
+
const confirmAndroid = (date) => {
|
|
96
|
+
if (!date || blocked || saving.current)
|
|
97
|
+
return;
|
|
98
|
+
if (mode === "datetime" && phase === "date") {
|
|
99
|
+
dialogSession.current += 1;
|
|
100
|
+
setDraft((current) => withCalendarDay(current, date));
|
|
101
|
+
setPhase("time");
|
|
102
|
+
setError(undefined);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const next = mode === "datetime" ? withClockTime(draft, date) : date;
|
|
106
|
+
void apply(next);
|
|
107
|
+
};
|
|
108
|
+
const dismissAndroid = () => {
|
|
109
|
+
if (dialogSession.current !== visibleOwner.current)
|
|
110
|
+
return;
|
|
111
|
+
setOpen(false);
|
|
112
|
+
};
|
|
113
|
+
const openPicker = () => {
|
|
114
|
+
const initial = error ? draft : (value ?? new Date());
|
|
115
|
+
const clamped = minimumDate && comparableDate(initial, mode) < comparableDate(minimumDate, mode)
|
|
116
|
+
? minimumDate
|
|
117
|
+
: maximumDate && comparableDate(initial, mode) > comparableDate(maximumDate, mode)
|
|
118
|
+
? maximumDate
|
|
119
|
+
: initial;
|
|
120
|
+
dialogSession.current += 1;
|
|
121
|
+
visibleOwner.current = dialogSession.current;
|
|
122
|
+
setDraft(clamped);
|
|
123
|
+
setPhase("date");
|
|
124
|
+
setError(undefined);
|
|
125
|
+
setOpen(true);
|
|
36
126
|
};
|
|
37
|
-
|
|
127
|
+
const androidMode = mode === "datetime" ? phase : mode;
|
|
128
|
+
return (_jsxs(View, { className: cn("gap-1", className), testID: testID, children: [label ? (_jsx(Typography.Text, { className: "text-text-primary", semibold: true, variant: "bodySmall", children: label })) : null, _jsxs(Pressable, { accessibilityHint: "Abre el selector de fecha y hora", accessibilityLabel: label ?? placeholder, accessibilityRole: "button", accessibilityState: { disabled: blocked, expanded: open }, accessibilityValue: { text: value ? fmt(value) : placeholder }, className: "flex-row items-center gap-3 rounded-lg border border-input bg-bg-card px-3", disabled: blocked, onPress: openPicker, style: { minHeight: 48, minWidth: 48 }, children: [_jsx(Typography.Text, { className: cn("flex-1", value ? "text-text-primary" : "text-text-tertiary"), style: { paddingVertical: 12 }, children: value ? fmt(value) : placeholder }), _jsx(Icon, { color: theme.icon.secondary, name: mode === "time" ? "time" : "calendar", size: 18 })] }), android && error ? (_jsx(Typography.Text, { accessibilityLiveRegion: "polite", accessibilityRole: "alert", className: "text-danger", selectable: true, children: error })) : null, android && open ? (_jsx(DateTimePicker, { accentColor: theme.primary, display: "default", maximumDate: maximumDate, minimumDate: minimumDate, mode: androidMode, negativeButton: { label: "Cancelar" }, onDismiss: dismissAndroid, onValueChange: (_event, date) => confirmAndroid(date), positiveButton: {
|
|
129
|
+
label: mode === "datetime" && phase === "date" ? "Continuar" : "Aplicar",
|
|
130
|
+
}, presentation: "dialog", testID: testID
|
|
131
|
+
? `${testID}-${androidMode === "time" ? "time" : "date"}-picker`
|
|
132
|
+
: undefined, themeVariant: appearance, value: draft }, androidMode)) : null, android ? null : (_jsxs(Sheet, { dismissible: !pending, footer: _jsx(Actions.Button, { disabled: blocked, loading: pending, onPress: () => void apply(draft), title: "Aplicar" }), onClose: close, title: label ?? (mode === "time" ? "Seleccionar hora" : "Seleccionar fecha"), visible: open, children: [open ? (_jsx(View, { accessibilityElementsHidden: blocked, importantForAccessibility: blocked ? "no-hide-descendants" : "auto", pointerEvents: blocked ? "none" : "auto", children: _jsx(DateTimePicker, { accentColor: theme.primary, disabled: blocked, display: mode === "time" || mode === "datetime" ? "spinner" : "inline", maximumDate: maximumDate, minimumDate: minimumDate, mode: mode, onValueChange: (_event, date) => update(date), presentation: "inline", testID: testID ? `${testID}-date-picker` : undefined, themeVariant: appearance, value: draft }) })) : null, error ? (_jsx(Typography.Text, { accessibilityLiveRegion: "polite", accessibilityRole: "alert", className: "pt-3 text-danger", selectable: true, children: error })) : null] }))] }));
|
|
38
133
|
}
|
|
39
134
|
export default DatePicker;
|
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
export interface DropdownOption {
|
|
1
|
+
import { type PressableProps } from "../primitives/Pressable.js";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export type DropdownOption = {
|
|
5
4
|
id: string;
|
|
6
5
|
title: string;
|
|
7
|
-
onPress: () => void
|
|
6
|
+
onPress: () => void | Promise<void>;
|
|
8
7
|
disabled?: boolean;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
8
|
+
};
|
|
9
|
+
export type DropdownButtonProps = {
|
|
11
10
|
title: string;
|
|
12
11
|
options: readonly DropdownOption[];
|
|
13
12
|
variant?: "primary" | "secondary" | "outline";
|
|
14
13
|
size?: "xs" | "small" | "medium" | "large";
|
|
15
14
|
disabled?: boolean;
|
|
16
|
-
|
|
17
|
-
buttonProps?: Omit<
|
|
18
|
-
contentProps?: Omit<ViewProps, "children">;
|
|
19
|
-
optionProps?: Omit<TouchableOpacityProps, "children" | "onPress" | "disabled">;
|
|
20
|
-
titleTextProps?: ComponentProps<typeof Typography.Text>;
|
|
21
|
-
optionTextProps?: ComponentProps<typeof Typography.Text>;
|
|
15
|
+
readOnly?: boolean;
|
|
16
|
+
buttonProps?: Omit<PressableProps, "children" | "onPress" | "disabled">;
|
|
22
17
|
renderOption?: (option: DropdownOption) => ReactNode;
|
|
23
18
|
testID?: string;
|
|
24
|
-
}
|
|
25
|
-
declare function
|
|
26
|
-
export default
|
|
19
|
+
};
|
|
20
|
+
declare function Dropdown({ title, options, variant, size, disabled, readOnly, buttonProps, renderOption, testID, }: DropdownButtonProps): import("react").JSX.Element;
|
|
21
|
+
export default Dropdown;
|
|
@@ -1,100 +1,64 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "nativewind/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import Sheet from "../Dialog/Dialog.Sheet.js";
|
|
3
3
|
import Icon from "../Display/Display.Icon.js";
|
|
4
|
+
import Pressable from "../primitives/Pressable.js";
|
|
4
5
|
import { useTheme } from "../theme/index.js";
|
|
5
6
|
import { cn } from "../theme/tw.js";
|
|
6
7
|
import { Typography } from "../Typography/index.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import { tv } from "tailwind-variants";
|
|
11
|
-
const dropdown = tv({
|
|
12
|
-
slots: {
|
|
13
|
-
button: "flex-row justify-between items-center rounded-lg px-3",
|
|
14
|
-
overlay: "flex-1 bg-black/40 justify-center items-center",
|
|
15
|
-
dropdownContainer: "rounded-xl mx-5 max-w-[320px] w-[90%] max-h-[70%]",
|
|
16
|
-
header: "flex-row justify-between items-center px-4 py-3 border-b border-border-default",
|
|
17
|
-
optionsList: "p-1",
|
|
18
|
-
option: "py-3 px-3 rounded-lg my-0.5",
|
|
19
|
-
separator: "h-[1px] bg-border-light mx-3",
|
|
20
|
-
},
|
|
21
|
-
variants: {
|
|
22
|
-
variant: {
|
|
23
|
-
primary: {
|
|
24
|
-
button: "bg-primary",
|
|
25
|
-
},
|
|
26
|
-
secondary: {
|
|
27
|
-
button: "bg-bg-card border border-primary",
|
|
28
|
-
},
|
|
29
|
-
outline: {
|
|
30
|
-
button: "bg-transparent border border-primary",
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
size: {
|
|
34
|
-
xs: {
|
|
35
|
-
button: "py-1.5 min-h-[32px]",
|
|
36
|
-
},
|
|
37
|
-
small: {
|
|
38
|
-
button: "py-2 min-h-[36px]",
|
|
39
|
-
},
|
|
40
|
-
medium: {
|
|
41
|
-
button: "py-2.5 min-h-[40px]",
|
|
42
|
-
},
|
|
43
|
-
large: {
|
|
44
|
-
button: "py-3 min-h-[44px]",
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
disabled: {
|
|
48
|
-
true: {
|
|
49
|
-
option: "opacity-50",
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
defaultVariants: {
|
|
54
|
-
variant: "secondary",
|
|
55
|
-
size: "small",
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
function DropdownButton({ title, options, variant = "secondary", size = "small", disabled = false, closeAccessibilityLabel = "Cerrar opciones", buttonProps, contentProps, optionProps, titleTextProps, optionTextProps, renderOption, testID, }) {
|
|
8
|
+
import { useRef, useState } from "react";
|
|
9
|
+
import { ActivityIndicator, View } from "react-native";
|
|
10
|
+
function Dropdown({ title, options, variant = "secondary", size = "small", disabled = false, readOnly = false, buttonProps, renderOption, testID, }) {
|
|
59
11
|
const theme = useTheme();
|
|
60
|
-
const
|
|
61
|
-
const [
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
12
|
+
const saving = useRef(false);
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
const [pending, setPending] = useState();
|
|
15
|
+
const [error, setError] = useState();
|
|
16
|
+
const blocked = disabled || readOnly || pending !== undefined;
|
|
17
|
+
const close = () => {
|
|
18
|
+
if (!saving.current)
|
|
19
|
+
setOpen(false);
|
|
20
|
+
};
|
|
21
|
+
const choose = async (option) => {
|
|
22
|
+
if (blocked || option.disabled || saving.current)
|
|
23
|
+
return;
|
|
24
|
+
saving.current = true;
|
|
25
|
+
setPending(option.id);
|
|
26
|
+
setError(undefined);
|
|
27
|
+
try {
|
|
28
|
+
await option.onPress();
|
|
29
|
+
setOpen(false);
|
|
30
|
+
}
|
|
31
|
+
catch (cause) {
|
|
32
|
+
setError(cause instanceof Error && cause.message.trim()
|
|
33
|
+
? cause.message
|
|
34
|
+
: "No se pudo completar la acción. Vuelve a intentarlo.");
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
saving.current = false;
|
|
38
|
+
setPending(undefined);
|
|
66
39
|
}
|
|
67
40
|
};
|
|
68
|
-
|
|
69
|
-
const textColorClass = {
|
|
70
|
-
primary: "text-text-on-primary",
|
|
71
|
-
outline: "text-text-accent",
|
|
72
|
-
secondary: "text-text-accent",
|
|
73
|
-
}[variant];
|
|
74
|
-
const iconColor = {
|
|
75
|
-
primary: theme.text.onPrimary,
|
|
76
|
-
outline: theme.text.accent,
|
|
77
|
-
secondary: theme.text.accent,
|
|
78
|
-
}[variant];
|
|
79
|
-
const textVariant = {
|
|
80
|
-
large: "body",
|
|
81
|
-
medium: "body",
|
|
82
|
-
xs: "bodySmall",
|
|
83
|
-
small: "bodySmall",
|
|
84
|
-
}[size];
|
|
85
|
-
return (_jsxs(_Fragment, { children: [_jsxs(TouchableOpacity, { ...buttonProps, accessibilityLabel: buttonProps?.accessibilityLabel ?? title, accessibilityRole: "button", accessibilityState: {
|
|
41
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Pressable, { ...buttonProps, accessibilityLabel: buttonProps?.accessibilityLabel ?? title, accessibilityRole: "button", accessibilityState: {
|
|
86
42
|
...buttonProps?.accessibilityState,
|
|
87
|
-
disabled,
|
|
88
|
-
expanded:
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
43
|
+
disabled: blocked,
|
|
44
|
+
expanded: open,
|
|
45
|
+
}, className: cn("flex-row items-center justify-between gap-3 rounded-lg px-3", variant === "primary"
|
|
46
|
+
? "bg-primary"
|
|
47
|
+
: variant === "secondary"
|
|
48
|
+
? "bg-bg-card border border-primary"
|
|
49
|
+
: "bg-transparent border border-primary", buttonProps?.className), disabled: blocked, onPress: () => {
|
|
50
|
+
setError(undefined);
|
|
51
|
+
setOpen(true);
|
|
52
|
+
}, style: [
|
|
53
|
+
{
|
|
54
|
+
minHeight: 48,
|
|
55
|
+
minWidth: 48,
|
|
56
|
+
paddingVertical: { xs: 6, small: 8, medium: 10, large: 12 }[size],
|
|
57
|
+
},
|
|
58
|
+
buttonProps?.style,
|
|
59
|
+
], testID: testID, children: [_jsx(Typography.Text, { className: variant === "primary" ? "text-text-on-primary" : "text-text-accent", variant: size === "large" || size === "medium" ? "body" : "bodySmall", children: title }), _jsx(Icon, { color: variant === "primary" ? theme.text.onPrimary : theme.text.accent, name: "expand", size: 16 })] }), _jsxs(Sheet, { dismissible: pending === undefined, onClose: close, title: title, visible: open, children: [options.map((option) => (_jsxs(Pressable, { accessibilityLabel: option.title, accessibilityRole: "button", accessibilityState: {
|
|
60
|
+
disabled: blocked || !!option.disabled,
|
|
61
|
+
busy: pending === option.id,
|
|
62
|
+
}, className: "flex-row items-center gap-3 border-b border-border-light py-3", disabled: blocked || option.disabled, onPress: () => void choose(option), style: { minHeight: 48, minWidth: 48 }, children: [_jsx(View, { className: "flex-1", children: renderOption ? (renderOption(option)) : (_jsx(Typography.Text, { className: option.disabled ? "text-text-disabled" : "text-text-primary", children: option.title })) }), pending === option.id ? _jsx(ActivityIndicator, { color: theme.primary }) : null] }, option.id))), !options.length ? (_jsx(Typography.Text, { children: "No hay opciones disponibles." })) : null, error ? (_jsx(Typography.Text, { accessibilityLiveRegion: "polite", accessibilityRole: "alert", className: "pt-3 text-danger", selectable: true, children: error })) : null] })] }));
|
|
99
63
|
}
|
|
100
|
-
export default
|
|
64
|
+
export default Dropdown;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
|
+
import { Actions } from "../Actions/index.js";
|
|
2
3
|
import { Dialog } from "../Dialog/index.js";
|
|
3
4
|
import { Display } from "../Display/index.js";
|
|
4
5
|
import { Typography } from "../Typography/index.js";
|
|
@@ -91,8 +92,8 @@ function FractionalQuantityInput({ value, onChange, precision = 2, minIncrement,
|
|
|
91
92
|
setDraft(String(value));
|
|
92
93
|
setModalVisible(true);
|
|
93
94
|
}
|
|
94
|
-
function confirmDraft() {
|
|
95
|
-
let parsed = parseLocalizedNumber(
|
|
95
|
+
function confirmDraft(nextDraft) {
|
|
96
|
+
let parsed = parseLocalizedNumber(nextDraft);
|
|
96
97
|
parsed = roundTo(parsed, precision);
|
|
97
98
|
if (parsed < 0)
|
|
98
99
|
parsed = 0;
|
|
@@ -102,17 +103,9 @@ function FractionalQuantityInput({ value, onChange, precision = 2, minIncrement,
|
|
|
102
103
|
setModalVisible(false);
|
|
103
104
|
}
|
|
104
105
|
const formatted = useMemo(() => value.toFixed(precision), [value, precision]);
|
|
105
|
-
const modalChips = chips.map((item) => ({
|
|
106
|
-
label: `+${item}`,
|
|
107
|
-
onPress: () => {
|
|
108
|
-
const base = parseLocalizedNumber(draft) || 0;
|
|
109
|
-
const next = roundTo(base + item, precision);
|
|
110
|
-
setDraft(String(next));
|
|
111
|
-
},
|
|
112
|
-
}));
|
|
113
106
|
const decrementStyles = fractionalQuantityInput({ disabled: disabled || value <= 0 });
|
|
114
107
|
const incrementStyles = fractionalQuantityInput({ disabled });
|
|
115
108
|
const containerStyles = fractionalQuantityInput();
|
|
116
|
-
return (_jsxs(View, { accessibilityLabel: `Cantidad ${formatted}`, className: containerStyles.container(), style: style, children: [_jsx(TouchableOpacity, { className: decrementStyles.button(), disabled: disabled || value <= 0, onPress: handleDecrement, children: _jsx(Display.Icon, { name: "
|
|
109
|
+
return (_jsxs(View, { accessibilityLabel: `Cantidad ${formatted}`, className: containerStyles.container(), style: style, children: [_jsx(TouchableOpacity, { className: decrementStyles.button(), disabled: disabled || value <= 0, onPress: handleDecrement, children: _jsx(Display.Icon, { name: "remove", size: 16 }) }), _jsx(TouchableOpacity, { className: containerStyles.valueContainer(), disabled: disabled, onPress: openModal, children: _jsx(Typography.Text, { semibold: true, variant: "body", children: formatted }) }), _jsx(TouchableOpacity, { className: incrementStyles.button(), disabled: disabled, onPress: handleIncrement, children: _jsx(Display.Icon, { name: "add", size: 16 }) }), _jsx(Dialog.EditValue, { footerAdornment: _jsx(View, { className: "flex-row flex-wrap gap-2", children: chips.map((item, index) => (_jsx(Actions.Button, { onPress: () => setDraft((current) => String(roundTo(parseLocalizedNumber(current) + item, precision))), size: "small", title: `+${item}`, variant: "secondary" }, `${item}-${index}`))) }), keyboardType: "decimal-pad", onChange: setDraft, onClose: () => setModalVisible(false), onConfirm: confirmDraft, placeholder: `0${precision > 0 ? ",".padEnd(precision + 1, "0") : ""}`, rightAdornment: _jsxs(Typography.Text, { className: "ml-1", variant: "body", children: ["(m\u00EDn ", effectiveIncrement, ")"] }), title: "Editar cantidad", value: draft, visible: modalVisible })] }));
|
|
117
110
|
}
|
|
118
111
|
export default FractionalQuantityInput;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Ref } from "react";
|
|
2
|
+
import { type TextInputInstance, type TextInputProps } from "react-native";
|
|
3
3
|
interface FormInputProps extends TextInputProps {
|
|
4
|
-
ref?: Ref<
|
|
4
|
+
ref?: Ref<TextInputInstance>;
|
|
5
5
|
label: string;
|
|
6
6
|
error?: string;
|
|
7
7
|
tooltip?: string;
|
|
@@ -5,7 +5,7 @@ export interface KeyboardFormProps extends KeyboardAwareScrollViewProps {
|
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
ref?: Ref<KeyboardAwareScrollViewRef>;
|
|
7
7
|
toolbar?: boolean;
|
|
8
|
+
stickyFooterHeight?: number;
|
|
8
9
|
toolbarProps?: Omit<KeyboardToolbarProps, "onHeightChange">;
|
|
9
|
-
toolbarLabels?: Pick<KeyboardToolbarProps, "previousLabel" | "nextLabel" | "doneLabel" | "showDoneLabel">;
|
|
10
10
|
}
|
|
11
|
-
export default function KeyboardForm({ children, toolbar,
|
|
11
|
+
export default function KeyboardForm({ children, toolbar, stickyFooterHeight, toolbarProps, bottomOffset, style, ...props }: KeyboardFormProps): import("react").JSX.Element;
|
|
@@ -3,7 +3,7 @@ import KeyboardToolbar from "./Form.KeyboardToolbar.js";
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { View } from "react-native";
|
|
5
5
|
import { KeyboardAwareScrollView, KeyboardToolbar as NativeToolbar, } from "react-native-keyboard-controller";
|
|
6
|
-
export default function KeyboardForm({ children, toolbar = true,
|
|
6
|
+
export default function KeyboardForm({ children, toolbar = true, stickyFooterHeight = 0, toolbarProps, bottomOffset, style, ...props }) {
|
|
7
7
|
const [toolbarHeight, setToolbarHeight] = useState(48);
|
|
8
|
-
return (_jsxs(View, { style: { flex: 1 }, children: [_jsx(NativeToolbar.Group, { style: { flex: 1 }, children: _jsx(KeyboardAwareScrollView, { bottomOffset: bottomOffset ?? (toolbar ? toolbarHeight + 24 :
|
|
8
|
+
return (_jsxs(View, { style: { flex: 1 }, children: [_jsx(NativeToolbar.Group, { style: { flex: 1 }, children: _jsx(KeyboardAwareScrollView, { bottomOffset: bottomOffset ?? stickyFooterHeight + (toolbar ? toolbarHeight + 24 : 24), keyboardShouldPersistTaps: "handled", style: [{ flex: 1 }, style], ...props, children: children }) }), toolbar ? (_jsx(KeyboardToolbar, { ...toolbarProps, bottomGapOffset: -stickyFooterHeight, onHeightChange: setToolbarHeight })) : null] }));
|
|
9
9
|
}
|
|
@@ -12,10 +12,11 @@ export interface KeyboardToolbarProps {
|
|
|
12
12
|
actionStyle?: StyleProp<ViewStyle>;
|
|
13
13
|
labelStyle?: StyleProp<TextStyle>;
|
|
14
14
|
iconSize?: number;
|
|
15
|
+
bottomGapOffset?: number;
|
|
15
16
|
testID?: string;
|
|
16
17
|
renderActionContent?: (action: KeyboardToolbarAction, state: {
|
|
17
18
|
label: string;
|
|
18
19
|
disabled: boolean;
|
|
19
20
|
}) => ReactNode;
|
|
20
21
|
}
|
|
21
|
-
export default function KeyboardToolbar({ previousLabel, nextLabel, doneLabel, showDoneLabel, onHeightChange, className, style, actionStyle, labelStyle, iconSize, testID, renderActionContent, }: KeyboardToolbarProps): import("react").JSX.Element;
|
|
22
|
+
export default function KeyboardToolbar({ previousLabel, nextLabel, doneLabel, showDoneLabel, onHeightChange, className, style, actionStyle, labelStyle, iconSize, bottomGapOffset, testID, renderActionContent, }: KeyboardToolbarProps): import("react").JSX.Element;
|
|
@@ -6,7 +6,7 @@ import { Typography } from "../Typography/index.js";
|
|
|
6
6
|
import { useEffect, useRef, useState } from "react";
|
|
7
7
|
import { StyleSheet, useWindowDimensions, View, } from "react-native";
|
|
8
8
|
import { FocusedInputEvents, KeyboardController, KeyboardStickyView, useKeyboardState, } from "react-native-keyboard-controller";
|
|
9
|
-
export default function KeyboardToolbar({ previousLabel = "Campo anterior", nextLabel = "Campo siguiente", doneLabel = "Ocultar teclado", showDoneLabel = false, onHeightChange, className, style, actionStyle, labelStyle, iconSize = 20, testID = "keyboard-toolbar", renderActionContent, }) {
|
|
9
|
+
export default function KeyboardToolbar({ previousLabel = "Campo anterior", nextLabel = "Campo siguiente", doneLabel = "Ocultar teclado", showDoneLabel = false, onHeightChange, className, style, actionStyle, labelStyle, iconSize = 20, bottomGapOffset = 0, testID = "keyboard-toolbar", renderActionContent, }) {
|
|
10
10
|
const theme = useTheme();
|
|
11
11
|
const frame = useRef(null);
|
|
12
12
|
const { height: windowHeight } = useWindowDimensions();
|
|
@@ -25,15 +25,11 @@ export default function KeyboardToolbar({ previousLabel = "Campo anterior", next
|
|
|
25
25
|
return renderActionContent(action, { label, disabled });
|
|
26
26
|
if (action === "done" && showDoneLabel)
|
|
27
27
|
return (_jsx(Typography.Text, { className: "text-text-accent", style: labelStyle, variant: "bodySmall", children: label }));
|
|
28
|
-
return (_jsx(Icon, { color: disabled ? theme.text.tertiary : theme.text.accent, name: action === "previous"
|
|
29
|
-
? "chevron-up"
|
|
30
|
-
: action === "next"
|
|
31
|
-
? "chevron-down"
|
|
32
|
-
: "checkmark", size: iconSize }));
|
|
28
|
+
return (_jsx(Icon, { color: disabled ? theme.text.tertiary : theme.text.accent, name: action === "previous" ? "collapse" : action === "next" ? "expand" : "check", size: iconSize }));
|
|
33
29
|
};
|
|
34
30
|
return (_jsx(View, { accessibilityElementsHidden: !isVisible, importantForAccessibility: isVisible ? "auto" : "no-hide-descendants", onLayout: () => {
|
|
35
31
|
frame.current?.measureInWindow((_x, y, _width, frameHeight) => setBottomGap(Math.max(0, windowHeight - y - frameHeight)));
|
|
36
|
-
}, pointerEvents: "box-none", ref: frame, style: StyleSheet.absoluteFill, children: _jsx(KeyboardStickyView, { offset: { closed: height, opened: bottomGap - 8 }, style: { position: "absolute", bottom: 0, left: 0, right: 0 }, children: _jsxs(View, { className: className, onLayout: (event) => {
|
|
32
|
+
}, pointerEvents: "box-none", ref: frame, style: StyleSheet.absoluteFill, children: _jsx(KeyboardStickyView, { offset: { closed: height, opened: bottomGap + bottomGapOffset - 8 }, style: { position: "absolute", bottom: 0, left: 0, right: 0 }, children: _jsxs(View, { className: className, onLayout: (event) => {
|
|
37
33
|
const nextHeight = event.nativeEvent.layout.height;
|
|
38
34
|
setHeight(nextHeight);
|
|
39
35
|
onHeightChange?.(nextHeight);
|
|
@@ -12,6 +12,6 @@ const PasswordField = ({ label, error, inputProps }) => {
|
|
|
12
12
|
secureTextEntry: !showPassword,
|
|
13
13
|
autoComplete: "off",
|
|
14
14
|
importantForAutofill: "no",
|
|
15
|
-
}, label: label }), _jsx(TouchableOpacity, { className: "absolute right-3 bottom-[25px]", hitSlop: 8, onPress: () => setShowPassword(!showPassword), children: _jsx(Display.Icon, { color: theme.text.primary, name: showPassword ? "
|
|
15
|
+
}, label: label }), _jsx(TouchableOpacity, { className: "absolute right-3 bottom-[25px]", hitSlop: 8, onPress: () => setShowPassword(!showPassword), children: _jsx(Display.Icon, { color: theme.text.primary, name: showPassword ? "hidden" : "visibility", size: 22 }) })] }));
|
|
16
16
|
};
|
|
17
17
|
export default PasswordField;
|
|
@@ -31,6 +31,6 @@ function QuantitySelector({ value, onChange, min = 1, max = 999, style, }) {
|
|
|
31
31
|
const decrementStyles = quantitySelector({ disabled: value <= min });
|
|
32
32
|
const incrementStyles = quantitySelector({ disabled: value >= max });
|
|
33
33
|
const containerStyles = quantitySelector();
|
|
34
|
-
return (_jsxs(View, { className: containerStyles.container(), style: style, children: [_jsx(TouchableOpacity, { className: decrementStyles.button(), disabled: value <= min, onPress: handleDecrement, children: _jsx(Display.Icon, { name: "
|
|
34
|
+
return (_jsxs(View, { className: containerStyles.container(), style: style, children: [_jsx(TouchableOpacity, { className: decrementStyles.button(), disabled: value <= min, onPress: handleDecrement, children: _jsx(Display.Icon, { name: "remove", size: 16 }) }), _jsx(View, { className: containerStyles.valueContainer(), children: _jsx(Typography.Text, { semibold: true, variant: "body", children: value }) }), _jsx(TouchableOpacity, { className: incrementStyles.button(), disabled: value >= max, onPress: handleIncrement, children: _jsx(Display.Icon, { name: "add", size: 16 }) })] }));
|
|
35
35
|
}
|
|
36
36
|
export default QuantitySelector;
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type SelectOption<T extends string | number> = {
|
|
2
2
|
label: string;
|
|
3
3
|
value: T;
|
|
4
|
-
}
|
|
5
|
-
export
|
|
6
|
-
options: SelectOption<T>[];
|
|
4
|
+
};
|
|
5
|
+
export type SelectProps<T extends string | number> = {
|
|
6
|
+
options: readonly SelectOption<T>[];
|
|
7
7
|
value: T | null;
|
|
8
|
-
onChange: (value: T) => void
|
|
8
|
+
onChange: (value: T) => void | Promise<void>;
|
|
9
|
+
onBlur?: () => void;
|
|
9
10
|
label?: string;
|
|
10
11
|
placeholder?: string;
|
|
11
12
|
title?: string;
|
|
13
|
+
confirmLabel?: string;
|
|
12
14
|
disabled?: boolean;
|
|
15
|
+
readOnly?: boolean;
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
error?: string;
|
|
13
18
|
className?: string;
|
|
14
19
|
testID?: string;
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
declare function Select<T extends string | number>({ options, value, onChange, label, placeholder, title, disabled, className, testID, showCloseButton, }: SelectProps<T>): import("react").JSX.Element;
|
|
20
|
+
};
|
|
21
|
+
declare function Select<T extends string | number>({ options, value, onChange, onBlur, label, placeholder, title, confirmLabel, disabled, readOnly, loading, error, className, testID, }: SelectProps<T>): import("react").JSX.Element;
|
|
18
22
|
export default Select;
|