@retray-dev/ui-kit 9.1.0 → 9.2.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/COMPONENTS.md +165 -4
- package/CONSUMER.md +247 -0
- package/DESIGN.md +668 -0
- package/FONTS.md +107 -0
- package/README.md +3 -3
- package/dist/AlertBanner.d.mts +3 -1
- package/dist/AlertBanner.d.ts +3 -1
- package/dist/AlertBanner.js +18 -2
- package/dist/AlertBanner.mjs +1 -1
- package/dist/ConfirmDialog.d.mts +3 -1
- package/dist/ConfirmDialog.d.ts +3 -1
- package/dist/ConfirmDialog.js +3 -0
- package/dist/ConfirmDialog.mjs +1 -1
- package/dist/CurrencyInput.d.mts +3 -1
- package/dist/CurrencyInput.d.ts +3 -1
- package/dist/CurrencyInput.js +31 -4
- package/dist/CurrencyInput.mjs +2 -2
- package/dist/ImageUpload.d.mts +27 -0
- package/dist/ImageUpload.d.ts +27 -0
- package/dist/ImageUpload.js +399 -0
- package/dist/ImageUpload.mjs +9 -0
- package/dist/Input.d.mts +3 -1
- package/dist/Input.d.ts +3 -1
- package/dist/Input.js +27 -2
- package/dist/Input.mjs +1 -1
- package/dist/ListItem.d.mts +3 -1
- package/dist/ListItem.d.ts +3 -1
- package/dist/ListItem.js +2 -1
- package/dist/ListItem.mjs +1 -1
- package/dist/SheetSelect.d.mts +25 -0
- package/dist/SheetSelect.d.ts +25 -0
- package/dist/SheetSelect.js +440 -0
- package/dist/SheetSelect.mjs +9 -0
- package/dist/{chunk-M6ZXVBTK.mjs → chunk-6MKGPAR2.mjs} +21 -5
- package/dist/{chunk-7QHVVCB3.mjs → chunk-FZZLPJ6B.mjs} +3 -0
- package/dist/{chunk-MAC465BB.mjs → chunk-KNSENOV4.mjs} +5 -3
- package/dist/{chunk-756RAKE4.mjs → chunk-LVYEU5ZK.mjs} +27 -2
- package/dist/{chunk-BNP626TY.mjs → chunk-T4I5WVHA.mjs} +2 -1
- package/dist/chunk-URI2WBIV.mjs +147 -0
- package/dist/chunk-Y4GL2MHX.mjs +112 -0
- package/dist/index.d.mts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +327 -8
- package/dist/index.mjs +51 -12
- package/package.json +18 -5
- package/src/components/AlertBanner/AlertBanner.tsx +21 -3
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +5 -0
- package/src/components/CurrencyInput/CurrencyInput.tsx +4 -0
- package/src/components/ImageUpload/ImageUpload.tsx +158 -0
- package/src/components/ImageUpload/index.ts +1 -0
- package/src/components/Input/Input.tsx +51 -23
- package/src/components/ListItem/ListItem.tsx +4 -1
- package/src/components/SheetSelect/SheetSelect.tsx +192 -0
- package/src/components/SheetSelect/index.ts +1 -0
- package/src/hooks/useConfirmDialog.ts +67 -0
- package/src/index.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -12,11 +12,11 @@ var Ionicons = require('@expo/vector-icons/Ionicons');
|
|
|
12
12
|
var pressto = require('pressto');
|
|
13
13
|
var Animated13 = require('react-native-reanimated');
|
|
14
14
|
var expoFont = require('expo-font');
|
|
15
|
+
var bottomSheet = require('@gorhom/bottom-sheet');
|
|
15
16
|
var vectorIcons = require('@expo/vector-icons');
|
|
16
17
|
var expoLinearGradient = require('expo-linear-gradient');
|
|
17
18
|
var reactNativeEase = require('react-native-ease');
|
|
18
19
|
var RNSlider = require('@react-native-community/slider');
|
|
19
|
-
var bottomSheet = require('@gorhom/bottom-sheet');
|
|
20
20
|
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
|
|
21
21
|
var picker = require('@react-native-picker/picker');
|
|
22
22
|
var sonnerNative = require('sonner-native');
|
|
@@ -1011,7 +1011,7 @@ function useColorTransition(active, options = {}) {
|
|
|
1011
1011
|
|
|
1012
1012
|
// src/components/Input/Input.tsx
|
|
1013
1013
|
var webInputResetStyle = reactNative.Platform.OS === "web" ? { outlineStyle: "none", outlineWidth: 0, outlineColor: "transparent", boxShadow: "none" } : {};
|
|
1014
|
-
function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
|
|
1014
|
+
function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suffixStyle, prefixIcon, suffixIcon, prefixIconColor, suffixIconColor, type = "text", containerStyle, inputWrapperStyle, sheetMode = false, style, onFocus, onBlur, secureTextEntry, editable, accessibilityLabel, ...props }) {
|
|
1015
1015
|
const { colors } = useTheme();
|
|
1016
1016
|
const [focused, setFocused] = React25.useState(false);
|
|
1017
1017
|
const [showPassword, setShowPassword] = React25.useState(false);
|
|
@@ -1048,7 +1048,31 @@ function Input({ label, error, hint, disabled, prefix, suffix, prefixStyle, suff
|
|
|
1048
1048
|
},
|
|
1049
1049
|
/* @__PURE__ */ React25__default.default.createElement(Animated13__default.default.View, { style: [styles4.borderOverlay, borderAnimStyle], pointerEvents: "none" }),
|
|
1050
1050
|
effectivePrefix ? typeof effectivePrefix === "string" ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles4.prefixText, { color: colors.foregroundMuted }, prefixStyle], allowFontScaling: true }, effectivePrefix) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles4.prefixContainer }, effectivePrefix) : null,
|
|
1051
|
-
/* @__PURE__ */ React25__default.default.createElement(
|
|
1051
|
+
sheetMode ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1052
|
+
bottomSheet.BottomSheetTextInput,
|
|
1053
|
+
{
|
|
1054
|
+
style: [
|
|
1055
|
+
styles4.input,
|
|
1056
|
+
{ color: colors.foreground },
|
|
1057
|
+
webInputResetStyle,
|
|
1058
|
+
style
|
|
1059
|
+
],
|
|
1060
|
+
onFocus: (e) => {
|
|
1061
|
+
setFocused(true);
|
|
1062
|
+
onFocus?.(e);
|
|
1063
|
+
},
|
|
1064
|
+
onBlur: (e) => {
|
|
1065
|
+
setFocused(false);
|
|
1066
|
+
onBlur?.(e);
|
|
1067
|
+
},
|
|
1068
|
+
placeholderTextColor: colors.foregroundMuted,
|
|
1069
|
+
allowFontScaling: true,
|
|
1070
|
+
secureTextEntry: effectiveSecure,
|
|
1071
|
+
editable: isDisabled ? false : editable,
|
|
1072
|
+
accessibilityLabel: accessibilityLabel ?? label,
|
|
1073
|
+
...props
|
|
1074
|
+
}
|
|
1075
|
+
) : /* @__PURE__ */ React25__default.default.createElement(
|
|
1052
1076
|
reactNative.TextInput,
|
|
1053
1077
|
{
|
|
1054
1078
|
style: [
|
|
@@ -1604,7 +1628,7 @@ var styles10 = reactNative.StyleSheet.create({
|
|
|
1604
1628
|
right: 0
|
|
1605
1629
|
}
|
|
1606
1630
|
});
|
|
1607
|
-
function AlertBanner({ title, description, variant = "default", icon, iconName, iconColor, style }) {
|
|
1631
|
+
function AlertBanner({ title, description, variant = "default", icon, iconName, iconColor, onDismiss, style }) {
|
|
1608
1632
|
const { colors, colorScheme } = useTheme();
|
|
1609
1633
|
const isDark = colorScheme === "dark";
|
|
1610
1634
|
const accentColor = variant === "destructive" ? colors.destructive : variant === "success" ? colors.success : variant === "warning" ? colors.warning : colors.foreground;
|
|
@@ -1630,7 +1654,18 @@ function AlertBanner({ title, description, variant = "default", icon, iconName,
|
|
|
1630
1654
|
accessibilityLabel: a11yLabel
|
|
1631
1655
|
},
|
|
1632
1656
|
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.iconSlot }, effectiveIcon),
|
|
1633
|
-
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.description, { color: colors.foreground, opacity: 0.85 }], allowFontScaling: true }, description) : null)
|
|
1657
|
+
/* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles11.content }, /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles11.description, { color: colors.foreground, opacity: 0.85 }], allowFontScaling: true }, description) : null),
|
|
1658
|
+
onDismiss ? /* @__PURE__ */ React25__default.default.createElement(
|
|
1659
|
+
reactNative.TouchableOpacity,
|
|
1660
|
+
{
|
|
1661
|
+
onPress: onDismiss,
|
|
1662
|
+
style: styles11.dismissButton,
|
|
1663
|
+
activeOpacity: 0.6,
|
|
1664
|
+
accessibilityRole: "button",
|
|
1665
|
+
accessibilityLabel: "Dismiss"
|
|
1666
|
+
},
|
|
1667
|
+
/* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "x", size: ms(16), color: colors.foregroundMuted })
|
|
1668
|
+
) : null
|
|
1634
1669
|
);
|
|
1635
1670
|
}
|
|
1636
1671
|
var styles11 = reactNative.StyleSheet.create({
|
|
@@ -1656,6 +1691,11 @@ var styles11 = reactNative.StyleSheet.create({
|
|
|
1656
1691
|
description: {
|
|
1657
1692
|
fontFamily: "Sohne-Regular",
|
|
1658
1693
|
fontSize: ms(12)
|
|
1694
|
+
},
|
|
1695
|
+
dismissButton: {
|
|
1696
|
+
padding: s(4),
|
|
1697
|
+
marginTop: vs(-2),
|
|
1698
|
+
marginRight: -s(4)
|
|
1659
1699
|
}
|
|
1660
1700
|
});
|
|
1661
1701
|
function Progress({ value = 0, max = 100, variant = "default", style, accessibilityLabel }) {
|
|
@@ -3249,7 +3289,8 @@ function CurrencyInput({
|
|
|
3249
3289
|
placeholder,
|
|
3250
3290
|
editable,
|
|
3251
3291
|
containerStyle,
|
|
3252
|
-
style
|
|
3292
|
+
style,
|
|
3293
|
+
sheetMode
|
|
3253
3294
|
}) {
|
|
3254
3295
|
const handleChange = (text) => {
|
|
3255
3296
|
const withoutPrefix = prefix && text.startsWith(prefix) ? text.slice(prefix.length) : text;
|
|
@@ -3282,7 +3323,8 @@ function CurrencyInput({
|
|
|
3282
3323
|
prefixStyle,
|
|
3283
3324
|
containerStyle,
|
|
3284
3325
|
inputWrapperStyle: isLarge ? { paddingVertical: vs(16), minHeight: 72 } : void 0,
|
|
3285
|
-
style: [inputStyle, style]
|
|
3326
|
+
style: [inputStyle, style],
|
|
3327
|
+
sheetMode
|
|
3286
3328
|
}
|
|
3287
3329
|
);
|
|
3288
3330
|
}
|
|
@@ -3359,6 +3401,7 @@ function ListItemBase({
|
|
|
3359
3401
|
style,
|
|
3360
3402
|
titleStyle,
|
|
3361
3403
|
subtitleStyle,
|
|
3404
|
+
subtitleNumberOfLines = 2,
|
|
3362
3405
|
captionStyle,
|
|
3363
3406
|
accessibilityLabel
|
|
3364
3407
|
}) {
|
|
@@ -3393,7 +3436,7 @@ function ListItemBase({
|
|
|
3393
3436
|
reactNative.Text,
|
|
3394
3437
|
{
|
|
3395
3438
|
style: [styles25.subtitle, { color: colors.foregroundMuted }, subtitleStyle],
|
|
3396
|
-
numberOfLines:
|
|
3439
|
+
numberOfLines: subtitleNumberOfLines,
|
|
3397
3440
|
allowFontScaling: true
|
|
3398
3441
|
},
|
|
3399
3442
|
subtitle
|
|
@@ -3861,6 +3904,7 @@ function ConfirmDialog({
|
|
|
3861
3904
|
confirmLabel = "Confirm",
|
|
3862
3905
|
cancelLabel = "Cancel",
|
|
3863
3906
|
confirmVariant = "primary",
|
|
3907
|
+
loading = false,
|
|
3864
3908
|
onConfirm,
|
|
3865
3909
|
onCancel
|
|
3866
3910
|
}) {
|
|
@@ -3900,6 +3944,8 @@ function ConfirmDialog({
|
|
|
3900
3944
|
label: confirmLabel,
|
|
3901
3945
|
variant: confirmVariant,
|
|
3902
3946
|
fullWidth: true,
|
|
3947
|
+
loading,
|
|
3948
|
+
disabled: loading,
|
|
3903
3949
|
onPress: () => {
|
|
3904
3950
|
notificationSuccess();
|
|
3905
3951
|
onConfirm();
|
|
@@ -5465,6 +5511,240 @@ var styles44 = reactNative.StyleSheet.create({
|
|
|
5465
5511
|
alignItems: "center"
|
|
5466
5512
|
}
|
|
5467
5513
|
});
|
|
5514
|
+
function SheetSelectChip({
|
|
5515
|
+
option,
|
|
5516
|
+
selected,
|
|
5517
|
+
onPress
|
|
5518
|
+
}) {
|
|
5519
|
+
const { colors } = useTheme();
|
|
5520
|
+
const handlePress = () => {
|
|
5521
|
+
selectionAsync();
|
|
5522
|
+
onPress();
|
|
5523
|
+
};
|
|
5524
|
+
const iconColor = selected ? colors.primaryForeground : colors.foreground;
|
|
5525
|
+
const resolvedIcon = option.iconName ? renderIcon(option.iconName, ms(13), iconColor) : null;
|
|
5526
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
5527
|
+
PressableChip,
|
|
5528
|
+
{
|
|
5529
|
+
onPress: option.disabled ? void 0 : handlePress,
|
|
5530
|
+
rippleColor: "transparent",
|
|
5531
|
+
touchSoundDisabled: true,
|
|
5532
|
+
accessibilityRole: "button",
|
|
5533
|
+
accessibilityLabel: option.disabled ? `${option.label}, unavailable` : option.label,
|
|
5534
|
+
accessibilityState: { selected, disabled: option.disabled }
|
|
5535
|
+
},
|
|
5536
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
5537
|
+
reactNativeEase.EaseView,
|
|
5538
|
+
{
|
|
5539
|
+
style: [styles45.chip, option.disabled && styles45.chipDisabled],
|
|
5540
|
+
animate: {
|
|
5541
|
+
backgroundColor: selected ? colors.primary : colors.surface,
|
|
5542
|
+
borderColor: selected ? colors.primary : colors.border
|
|
5543
|
+
},
|
|
5544
|
+
transition: COLOR_TRANSITION
|
|
5545
|
+
},
|
|
5546
|
+
resolvedIcon ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles45.chipIcon }, resolvedIcon) : null,
|
|
5547
|
+
/* @__PURE__ */ React25__default.default.createElement(
|
|
5548
|
+
reactNative.Text,
|
|
5549
|
+
{
|
|
5550
|
+
style: [styles45.chipLabel, { color: selected ? colors.primaryForeground : colors.foreground }],
|
|
5551
|
+
allowFontScaling: true
|
|
5552
|
+
},
|
|
5553
|
+
option.label
|
|
5554
|
+
)
|
|
5555
|
+
)
|
|
5556
|
+
);
|
|
5557
|
+
}
|
|
5558
|
+
function SheetSelect({
|
|
5559
|
+
options,
|
|
5560
|
+
value,
|
|
5561
|
+
onValueChange,
|
|
5562
|
+
multiSelect = false,
|
|
5563
|
+
label,
|
|
5564
|
+
error,
|
|
5565
|
+
wrap = false,
|
|
5566
|
+
style,
|
|
5567
|
+
accessibilityLabel
|
|
5568
|
+
}) {
|
|
5569
|
+
const { colors } = useTheme();
|
|
5570
|
+
const isSelected2 = (optionValue) => {
|
|
5571
|
+
if (Array.isArray(value)) return value.includes(optionValue);
|
|
5572
|
+
return optionValue === value;
|
|
5573
|
+
};
|
|
5574
|
+
const handlePress = (optionValue) => {
|
|
5575
|
+
if (!multiSelect) {
|
|
5576
|
+
onValueChange?.(optionValue);
|
|
5577
|
+
return;
|
|
5578
|
+
}
|
|
5579
|
+
const currentArray = Array.isArray(value) ? value : value != null ? [value] : [];
|
|
5580
|
+
const alreadySelected = currentArray.includes(optionValue);
|
|
5581
|
+
const newArray = alreadySelected ? currentArray.filter((v) => v !== optionValue) : [...currentArray, optionValue];
|
|
5582
|
+
onValueChange?.(newArray);
|
|
5583
|
+
};
|
|
5584
|
+
const chips = options.map((opt) => /* @__PURE__ */ React25__default.default.createElement(
|
|
5585
|
+
SheetSelectChip,
|
|
5586
|
+
{
|
|
5587
|
+
key: opt.value,
|
|
5588
|
+
option: opt,
|
|
5589
|
+
selected: isSelected2(opt.value),
|
|
5590
|
+
onPress: () => handlePress(opt.value)
|
|
5591
|
+
}
|
|
5592
|
+
));
|
|
5593
|
+
return /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles45.container, style], accessibilityLabel }, label ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles45.label, { color: colors.foreground }], allowFontScaling: true }, label) : null, wrap ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles45.wrapContainer }, chips) : /* @__PURE__ */ React25__default.default.createElement(
|
|
5594
|
+
reactNative.ScrollView,
|
|
5595
|
+
{
|
|
5596
|
+
horizontal: true,
|
|
5597
|
+
showsHorizontalScrollIndicator: false,
|
|
5598
|
+
contentContainerStyle: styles45.scrollContent
|
|
5599
|
+
},
|
|
5600
|
+
chips
|
|
5601
|
+
), error ? /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles45.error, { color: colors.destructive }], allowFontScaling: true, accessibilityLiveRegion: "polite" }, error) : null);
|
|
5602
|
+
}
|
|
5603
|
+
var styles45 = reactNative.StyleSheet.create({
|
|
5604
|
+
container: {
|
|
5605
|
+
gap: vs(8)
|
|
5606
|
+
},
|
|
5607
|
+
label: {
|
|
5608
|
+
fontFamily: "Sohne-Medium",
|
|
5609
|
+
fontSize: ms(14)
|
|
5610
|
+
},
|
|
5611
|
+
scrollContent: {
|
|
5612
|
+
flexDirection: "row",
|
|
5613
|
+
gap: s(8)
|
|
5614
|
+
},
|
|
5615
|
+
wrapContainer: {
|
|
5616
|
+
flexDirection: "row",
|
|
5617
|
+
flexWrap: "wrap",
|
|
5618
|
+
gap: s(8)
|
|
5619
|
+
},
|
|
5620
|
+
chip: {
|
|
5621
|
+
borderRadius: RADIUS.full,
|
|
5622
|
+
paddingHorizontal: s(14),
|
|
5623
|
+
paddingVertical: vs(10),
|
|
5624
|
+
minHeight: 44,
|
|
5625
|
+
borderWidth: 1,
|
|
5626
|
+
alignItems: "center",
|
|
5627
|
+
justifyContent: "center",
|
|
5628
|
+
flexDirection: "row",
|
|
5629
|
+
gap: s(5)
|
|
5630
|
+
},
|
|
5631
|
+
chipDisabled: {
|
|
5632
|
+
opacity: 0.4
|
|
5633
|
+
},
|
|
5634
|
+
chipIcon: {
|
|
5635
|
+
alignItems: "center",
|
|
5636
|
+
justifyContent: "center"
|
|
5637
|
+
},
|
|
5638
|
+
chipLabel: {
|
|
5639
|
+
fontFamily: "Sohne-Medium",
|
|
5640
|
+
fontSize: ms(13),
|
|
5641
|
+
lineHeight: mvs(18)
|
|
5642
|
+
},
|
|
5643
|
+
error: {
|
|
5644
|
+
fontFamily: "Sohne-Regular",
|
|
5645
|
+
fontSize: ms(13)
|
|
5646
|
+
}
|
|
5647
|
+
});
|
|
5648
|
+
function ImageUpload({
|
|
5649
|
+
value,
|
|
5650
|
+
onChange,
|
|
5651
|
+
loading = false,
|
|
5652
|
+
placeholder = "Tap to add image",
|
|
5653
|
+
width,
|
|
5654
|
+
height = 200,
|
|
5655
|
+
borderRadius = RADIUS.lg,
|
|
5656
|
+
resizeMode = "cover",
|
|
5657
|
+
disabled = false,
|
|
5658
|
+
style,
|
|
5659
|
+
accessibilityLabel
|
|
5660
|
+
}) {
|
|
5661
|
+
const { colors } = useTheme();
|
|
5662
|
+
const handlePress = async () => {
|
|
5663
|
+
if (disabled || loading) return;
|
|
5664
|
+
impactLight();
|
|
5665
|
+
let ImagePicker;
|
|
5666
|
+
try {
|
|
5667
|
+
ImagePicker = await import('expo-image-picker');
|
|
5668
|
+
} catch {
|
|
5669
|
+
if (__DEV__) console.warn("[ImageUpload] expo-image-picker not installed. Add it as a dependency.");
|
|
5670
|
+
return;
|
|
5671
|
+
}
|
|
5672
|
+
if (reactNative.Platform.OS !== "web") {
|
|
5673
|
+
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
|
5674
|
+
if (status !== "granted") return;
|
|
5675
|
+
}
|
|
5676
|
+
const result = await ImagePicker.launchImageLibraryAsync({
|
|
5677
|
+
mediaTypes: ["images"],
|
|
5678
|
+
allowsEditing: true,
|
|
5679
|
+
quality: 0.8
|
|
5680
|
+
});
|
|
5681
|
+
if (!result.canceled && result.assets[0]) {
|
|
5682
|
+
onChange?.(result.assets[0].uri);
|
|
5683
|
+
}
|
|
5684
|
+
};
|
|
5685
|
+
const containerStyle = {
|
|
5686
|
+
width,
|
|
5687
|
+
height,
|
|
5688
|
+
borderRadius,
|
|
5689
|
+
borderWidth: value ? 0 : 1,
|
|
5690
|
+
borderStyle: "dashed",
|
|
5691
|
+
borderColor: colors.border,
|
|
5692
|
+
backgroundColor: value ? "transparent" : colors.surface,
|
|
5693
|
+
overflow: "hidden"
|
|
5694
|
+
};
|
|
5695
|
+
return /* @__PURE__ */ React25__default.default.createElement(
|
|
5696
|
+
PressableCard,
|
|
5697
|
+
{
|
|
5698
|
+
onPress: handlePress,
|
|
5699
|
+
enabled: !disabled && !loading,
|
|
5700
|
+
rippleColor: "transparent",
|
|
5701
|
+
touchSoundDisabled: true,
|
|
5702
|
+
accessibilityRole: "button",
|
|
5703
|
+
accessibilityLabel: accessibilityLabel ?? (value ? "Change image" : placeholder),
|
|
5704
|
+
accessibilityState: { disabled: disabled || loading },
|
|
5705
|
+
style: [containerStyle, style]
|
|
5706
|
+
},
|
|
5707
|
+
value ? /* @__PURE__ */ React25__default.default.createElement(
|
|
5708
|
+
reactNative.Image,
|
|
5709
|
+
{
|
|
5710
|
+
source: { uri: value },
|
|
5711
|
+
style: [reactNative.StyleSheet.absoluteFillObject, { borderRadius }],
|
|
5712
|
+
resizeMode
|
|
5713
|
+
}
|
|
5714
|
+
) : /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles46.placeholder }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "image", size: ms(28), color: colors.foregroundMuted }), /* @__PURE__ */ React25__default.default.createElement(reactNative.Text, { style: [styles46.placeholderText, { color: colors.foregroundMuted }], allowFontScaling: true }, placeholder)),
|
|
5715
|
+
loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles46.loadingOverlay, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React25__default.default.createElement(Spinner, { size: "md" })) : null,
|
|
5716
|
+
value && !loading ? /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: styles46.editBadge, pointerEvents: "none" }, /* @__PURE__ */ React25__default.default.createElement(reactNative.View, { style: [styles46.editBadgeInner, { backgroundColor: colors.overlay }] }, /* @__PURE__ */ React25__default.default.createElement(vectorIcons.Feather, { name: "edit-2", size: ms(12), color: "#fff" }))) : null
|
|
5717
|
+
);
|
|
5718
|
+
}
|
|
5719
|
+
var styles46 = reactNative.StyleSheet.create({
|
|
5720
|
+
placeholder: {
|
|
5721
|
+
flex: 1,
|
|
5722
|
+
alignItems: "center",
|
|
5723
|
+
justifyContent: "center",
|
|
5724
|
+
gap: vs(8)
|
|
5725
|
+
},
|
|
5726
|
+
placeholderText: {
|
|
5727
|
+
fontFamily: "Sohne-Regular",
|
|
5728
|
+
fontSize: ms(13)
|
|
5729
|
+
},
|
|
5730
|
+
loadingOverlay: {
|
|
5731
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
5732
|
+
alignItems: "center",
|
|
5733
|
+
justifyContent: "center"
|
|
5734
|
+
},
|
|
5735
|
+
editBadge: {
|
|
5736
|
+
position: "absolute",
|
|
5737
|
+
bottom: vs(8),
|
|
5738
|
+
right: s(8)
|
|
5739
|
+
},
|
|
5740
|
+
editBadgeInner: {
|
|
5741
|
+
width: s(28),
|
|
5742
|
+
height: s(28),
|
|
5743
|
+
borderRadius: 999,
|
|
5744
|
+
alignItems: "center",
|
|
5745
|
+
justifyContent: "center"
|
|
5746
|
+
}
|
|
5747
|
+
});
|
|
5468
5748
|
|
|
5469
5749
|
// src/utils/typography.ts
|
|
5470
5750
|
function getResponsiveFontSize(text, maxSize, steps = [
|
|
@@ -5479,6 +5759,42 @@ function getResponsiveFontSize(text, maxSize, steps = [
|
|
|
5479
5759
|
}
|
|
5480
5760
|
return maxSize - 8;
|
|
5481
5761
|
}
|
|
5762
|
+
function useConfirmDialog(options) {
|
|
5763
|
+
const [visible, setVisible] = React25.useState(false);
|
|
5764
|
+
const [target, setTarget] = React25.useState(null);
|
|
5765
|
+
const [loading, setLoading] = React25.useState(false);
|
|
5766
|
+
const open = React25.useCallback((t) => {
|
|
5767
|
+
setTarget(t ?? null);
|
|
5768
|
+
setVisible(true);
|
|
5769
|
+
}, []);
|
|
5770
|
+
const handleConfirm = React25.useCallback(async () => {
|
|
5771
|
+
setLoading(true);
|
|
5772
|
+
try {
|
|
5773
|
+
await options.onConfirm();
|
|
5774
|
+
} finally {
|
|
5775
|
+
setLoading(false);
|
|
5776
|
+
setVisible(false);
|
|
5777
|
+
setTarget(null);
|
|
5778
|
+
}
|
|
5779
|
+
}, [options]);
|
|
5780
|
+
const handleCancel = React25.useCallback(() => {
|
|
5781
|
+
setVisible(false);
|
|
5782
|
+
setTarget(null);
|
|
5783
|
+
options.onCancel?.();
|
|
5784
|
+
}, [options]);
|
|
5785
|
+
return {
|
|
5786
|
+
visible,
|
|
5787
|
+
target,
|
|
5788
|
+
loading,
|
|
5789
|
+
open,
|
|
5790
|
+
dialogProps: {
|
|
5791
|
+
visible,
|
|
5792
|
+
loading,
|
|
5793
|
+
onConfirm: handleConfirm,
|
|
5794
|
+
onCancel: handleCancel
|
|
5795
|
+
}
|
|
5796
|
+
};
|
|
5797
|
+
}
|
|
5482
5798
|
|
|
5483
5799
|
Object.defineProperty(exports, "BottomSheetModalProvider", {
|
|
5484
5800
|
enumerable: true,
|
|
@@ -5523,6 +5839,7 @@ exports.FormSection = FormSection;
|
|
|
5523
5839
|
exports.ICON_SIZES = ICON_SIZES;
|
|
5524
5840
|
exports.Icon = Icon;
|
|
5525
5841
|
exports.IconButton = IconButton;
|
|
5842
|
+
exports.ImageUpload = ImageUpload;
|
|
5526
5843
|
exports.ImageViewer = ImageViewer;
|
|
5527
5844
|
exports.Input = Input;
|
|
5528
5845
|
exports.LabelValue = LabelValue;
|
|
@@ -5549,6 +5866,7 @@ exports.Select = Select;
|
|
|
5549
5866
|
exports.SelectableGrid = SelectableGrid;
|
|
5550
5867
|
exports.Separator = Separator;
|
|
5551
5868
|
exports.Sheet = Sheet;
|
|
5869
|
+
exports.SheetSelect = SheetSelect;
|
|
5552
5870
|
exports.Skeleton = Skeleton;
|
|
5553
5871
|
exports.Slider = Slider;
|
|
5554
5872
|
exports.Spinner = Spinner;
|
|
@@ -5579,5 +5897,6 @@ exports.notificationWarning = notificationWarning;
|
|
|
5579
5897
|
exports.renderIcon = renderIcon;
|
|
5580
5898
|
exports.richHaptics = richHaptics;
|
|
5581
5899
|
exports.selectionAsync = selectionAsync;
|
|
5900
|
+
exports.useConfirmDialog = useConfirmDialog;
|
|
5582
5901
|
exports.useTheme = useTheme;
|
|
5583
5902
|
exports.useToast = useToast;
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
export { Text } from './chunk-WJLKJMKR.mjs';
|
|
2
|
+
export { Textarea } from './chunk-EH745HE5.mjs';
|
|
1
3
|
export { Toggle } from './chunk-KIHCWCWL.mjs';
|
|
2
4
|
export { VirtualList } from './chunk-NC5ZTR2Y.mjs';
|
|
5
|
+
export { BottomSheetModalProvider, Sheet, BottomSheetTextInput as SheetTextInput } from './chunk-PFZTM6D5.mjs';
|
|
6
|
+
export { SheetSelect } from './chunk-URI2WBIV.mjs';
|
|
3
7
|
export { Skeleton } from './chunk-AJ7ZDNBT.mjs';
|
|
4
8
|
export { Slider } from './chunk-JMOZEC77.mjs';
|
|
5
|
-
export { Spinner } from './chunk-WBOOUHSS.mjs';
|
|
6
9
|
export { Switch } from './chunk-QKH5ZOD5.mjs';
|
|
7
10
|
export { TabBar } from './chunk-MLF3EZFW.mjs';
|
|
8
11
|
export { Tabs, TabsContent } from './chunk-GQYFLP3D.mjs';
|
|
9
|
-
export {
|
|
10
|
-
export { Textarea } from './chunk-EH745HE5.mjs';
|
|
12
|
+
export { Pressable } from './chunk-MBMXYJJV.mjs';
|
|
11
13
|
export { PricingCard } from './chunk-4I7D47FH.mjs';
|
|
12
14
|
export { Progress } from './chunk-OB4JUQ3O.mjs';
|
|
13
15
|
export { RadioGroup } from './chunk-X4G6APW6.mjs';
|
|
@@ -16,33 +18,33 @@ export { ToastProvider, sonnerToast as toast, useToast } from './chunk-2UYENBLV.
|
|
|
16
18
|
export { Select } from './chunk-A3A6KNQN.mjs';
|
|
17
19
|
export { SelectableGrid } from './chunk-NA7PARID.mjs';
|
|
18
20
|
export { Separator } from './chunk-MX6HRKMI.mjs';
|
|
19
|
-
export {
|
|
21
|
+
export { LabelValue } from './chunk-A4MDAP7G.mjs';
|
|
20
22
|
export { ListGroup, ListGroupFooter, ListGroupHeader } from './chunk-SOA2Z4RB.mjs';
|
|
21
|
-
export { ListItem } from './chunk-
|
|
23
|
+
export { ListItem } from './chunk-T4I5WVHA.mjs';
|
|
22
24
|
export { MediaCard } from './chunk-VGTDN7SW.mjs';
|
|
23
25
|
export { MenuGroup, MenuGroupFooter, MenuGroupHeader } from './chunk-IRRY3CRZ.mjs';
|
|
24
26
|
export { MenuItem } from './chunk-ZJKGQMYH.mjs';
|
|
25
27
|
export { MonthPicker, dateToMonthPickerValue, monthPickerValueToDate } from './chunk-GD6KXMG5.mjs';
|
|
26
|
-
export { Pressable } from './chunk-MBMXYJJV.mjs';
|
|
27
28
|
export { EmptyState } from './chunk-6OAZJ577.mjs';
|
|
28
29
|
export { ErrorBoundary } from './chunk-LXJIIOYQ.mjs';
|
|
29
30
|
export { Form, FormField, FormFooter, FormSection } from './chunk-6Q64UFIA.mjs';
|
|
31
|
+
export { ImageUpload } from './chunk-Y4GL2MHX.mjs';
|
|
32
|
+
export { Spinner } from './chunk-WBOOUHSS.mjs';
|
|
30
33
|
export { ImageViewer } from './chunk-Z4BVUWW6.mjs';
|
|
31
34
|
export { PagerDots } from './chunk-4K625MVM.mjs';
|
|
32
|
-
export { LabelValue } from './chunk-A4MDAP7G.mjs';
|
|
33
35
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './chunk-ID72TK46.mjs';
|
|
34
36
|
export { CategoryStrip } from './chunk-VQ57HWPL.mjs';
|
|
35
37
|
import './chunk-YNROWHQJ.mjs';
|
|
36
38
|
export { Checkbox } from './chunk-AV4EMIRH.mjs';
|
|
37
39
|
export { Chip, ChipGroup } from './chunk-UREA2GYY.mjs';
|
|
38
|
-
export { ConfirmDialog } from './chunk-
|
|
40
|
+
export { ConfirmDialog } from './chunk-FZZLPJ6B.mjs';
|
|
39
41
|
export { CurrencyDisplay } from './chunk-BRKYVJVV.mjs';
|
|
40
|
-
export { CurrencyInput } from './chunk-
|
|
41
|
-
export { Input } from './chunk-
|
|
42
|
+
export { CurrencyInput } from './chunk-KNSENOV4.mjs';
|
|
43
|
+
export { Input } from './chunk-LVYEU5ZK.mjs';
|
|
42
44
|
import './chunk-26BCI223.mjs';
|
|
43
45
|
export { DetailRow } from './chunk-JB67UOB5.mjs';
|
|
44
46
|
export { Accordion } from './chunk-O3HA6TYM.mjs';
|
|
45
|
-
export { AlertBanner } from './chunk-
|
|
47
|
+
export { AlertBanner } from './chunk-6MKGPAR2.mjs';
|
|
46
48
|
export { AppHeader } from './chunk-AZJF2BLK.mjs';
|
|
47
49
|
export { IconButton } from './chunk-3U4SSNWP.mjs';
|
|
48
50
|
export { Avatar } from './chunk-JT7HKXRB.mjs';
|
|
@@ -57,6 +59,7 @@ export { ThemeProvider, defaultDark, defaultLight, deriveColors, useTheme } from
|
|
|
57
59
|
export { ButtonGroup } from './chunk-3BBOZ3OQ.mjs';
|
|
58
60
|
import './chunk-2CE3TQVY.mjs';
|
|
59
61
|
import './chunk-Y6FXYEAI.mjs';
|
|
62
|
+
import { useState, useCallback } from 'react';
|
|
60
63
|
|
|
61
64
|
// src/utils/typography.ts
|
|
62
65
|
function getResponsiveFontSize(text, maxSize, steps = [
|
|
@@ -71,5 +74,41 @@ function getResponsiveFontSize(text, maxSize, steps = [
|
|
|
71
74
|
}
|
|
72
75
|
return maxSize - 8;
|
|
73
76
|
}
|
|
77
|
+
function useConfirmDialog(options) {
|
|
78
|
+
const [visible, setVisible] = useState(false);
|
|
79
|
+
const [target, setTarget] = useState(null);
|
|
80
|
+
const [loading, setLoading] = useState(false);
|
|
81
|
+
const open = useCallback((t) => {
|
|
82
|
+
setTarget(t ?? null);
|
|
83
|
+
setVisible(true);
|
|
84
|
+
}, []);
|
|
85
|
+
const handleConfirm = useCallback(async () => {
|
|
86
|
+
setLoading(true);
|
|
87
|
+
try {
|
|
88
|
+
await options.onConfirm();
|
|
89
|
+
} finally {
|
|
90
|
+
setLoading(false);
|
|
91
|
+
setVisible(false);
|
|
92
|
+
setTarget(null);
|
|
93
|
+
}
|
|
94
|
+
}, [options]);
|
|
95
|
+
const handleCancel = useCallback(() => {
|
|
96
|
+
setVisible(false);
|
|
97
|
+
setTarget(null);
|
|
98
|
+
options.onCancel?.();
|
|
99
|
+
}, [options]);
|
|
100
|
+
return {
|
|
101
|
+
visible,
|
|
102
|
+
target,
|
|
103
|
+
loading,
|
|
104
|
+
open,
|
|
105
|
+
dialogProps: {
|
|
106
|
+
visible,
|
|
107
|
+
loading,
|
|
108
|
+
onConfirm: handleConfirm,
|
|
109
|
+
onCancel: handleCancel
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
74
113
|
|
|
75
|
-
export { getResponsiveFontSize };
|
|
114
|
+
export { getResponsiveFontSize, useConfirmDialog };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retray-dev/ui-kit",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.2.0",
|
|
4
4
|
"description": "Personal UI Kit for React Native / Expo",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
"dist",
|
|
23
23
|
"src",
|
|
24
24
|
"COMPONENTS.md",
|
|
25
|
-
"
|
|
25
|
+
"CONSUMER.md",
|
|
26
|
+
"EXAMPLES.md",
|
|
27
|
+
"FONTS.md",
|
|
28
|
+
"DESIGN.md"
|
|
26
29
|
],
|
|
27
30
|
"scripts": {
|
|
28
31
|
"build": "tsup",
|
|
@@ -55,6 +58,7 @@
|
|
|
55
58
|
"@shopify/react-native-skia": ">=1.0.0",
|
|
56
59
|
"expo-font": ">=14.0.0",
|
|
57
60
|
"expo-haptics": ">=14.0.0",
|
|
61
|
+
"expo-image-picker": ">=15.0.0",
|
|
58
62
|
"expo-linear-gradient": ">=13.0.0",
|
|
59
63
|
"expo-sensors": ">=13.0.0",
|
|
60
64
|
"pressto": ">=0.6.0",
|
|
@@ -63,13 +67,13 @@
|
|
|
63
67
|
"react-native-ease": ">=0.7.0",
|
|
64
68
|
"react-native-gesture-handler": ">=2.0.0",
|
|
65
69
|
"react-native-pulsar": ">=1.6.0",
|
|
66
|
-
"react-native-reanimated": ">=4.0.0",
|
|
70
|
+
"react-native-reanimated": ">=4.0.0 <5.0.0",
|
|
67
71
|
"react-native-safe-area-context": ">=4.0.0",
|
|
68
72
|
"react-native-screens": ">=3.0.0",
|
|
69
73
|
"react-native-size-matters": ">=0.4.0",
|
|
70
74
|
"react-native-svg": ">=15.0.0",
|
|
71
|
-
"react-native-worklets": "
|
|
72
|
-
"sonner-native": ">=0.
|
|
75
|
+
"react-native-worklets": "~0.5.1",
|
|
76
|
+
"sonner-native": ">=0.22.0"
|
|
73
77
|
},
|
|
74
78
|
"peerDependenciesMeta": {
|
|
75
79
|
"@shopify/react-native-skia": {
|
|
@@ -80,6 +84,15 @@
|
|
|
80
84
|
},
|
|
81
85
|
"react-native-pulsar": {
|
|
82
86
|
"optional": true
|
|
87
|
+
},
|
|
88
|
+
"expo-image-picker": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"react-native-ease": {
|
|
92
|
+
"optional": false
|
|
93
|
+
},
|
|
94
|
+
"pressto": {
|
|
95
|
+
"optional": false
|
|
83
96
|
}
|
|
84
97
|
},
|
|
85
98
|
"pnpm": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
3
|
-
import { FontAwesome5, MaterialIcons, Entypo } from '@expo/vector-icons'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle, TouchableOpacity } from 'react-native'
|
|
3
|
+
import { FontAwesome5, MaterialIcons, Entypo, Feather } from '@expo/vector-icons'
|
|
4
4
|
import { useTheme } from '../../theme'
|
|
5
5
|
import { s, vs, ms } from '../../utils/scaling'
|
|
6
6
|
import { renderIcon } from '../../utils/icons'
|
|
@@ -15,10 +15,12 @@ export interface AlertBannerProps {
|
|
|
15
15
|
icon?: React.ReactNode
|
|
16
16
|
iconName?: string
|
|
17
17
|
iconColor?: string
|
|
18
|
+
/** Called when the user taps the dismiss (×) button. If omitted, no button is shown. */
|
|
19
|
+
onDismiss?: () => void
|
|
18
20
|
style?: ViewStyle
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
export function AlertBanner({ title, description, variant = 'default', icon, iconName, iconColor, style }: AlertBannerProps) {
|
|
23
|
+
export function AlertBanner({ title, description, variant = 'default', icon, iconName, iconColor, onDismiss, style }: AlertBannerProps) {
|
|
22
24
|
const { colors, colorScheme } = useTheme()
|
|
23
25
|
|
|
24
26
|
// Match Toast richColors appearance — saturated semantic colors
|
|
@@ -81,6 +83,17 @@ export function AlertBanner({ title, description, variant = 'default', icon, ico
|
|
|
81
83
|
<Text style={[styles.description, { color: colors.foreground, opacity: 0.85 }]} allowFontScaling={true}>{description}</Text>
|
|
82
84
|
) : null}
|
|
83
85
|
</View>
|
|
86
|
+
{onDismiss ? (
|
|
87
|
+
<TouchableOpacity
|
|
88
|
+
onPress={onDismiss}
|
|
89
|
+
style={styles.dismissButton}
|
|
90
|
+
activeOpacity={0.6}
|
|
91
|
+
accessibilityRole="button"
|
|
92
|
+
accessibilityLabel="Dismiss"
|
|
93
|
+
>
|
|
94
|
+
<Feather name="x" size={ms(16)} color={colors.foregroundMuted} />
|
|
95
|
+
</TouchableOpacity>
|
|
96
|
+
) : null}
|
|
84
97
|
</View>
|
|
85
98
|
)
|
|
86
99
|
}
|
|
@@ -109,4 +122,9 @@ const styles = StyleSheet.create({
|
|
|
109
122
|
fontFamily: 'Sohne-Regular',
|
|
110
123
|
fontSize: ms(12),
|
|
111
124
|
},
|
|
125
|
+
dismissButton: {
|
|
126
|
+
padding: s(4),
|
|
127
|
+
marginTop: vs(-2),
|
|
128
|
+
marginRight: -s(4),
|
|
129
|
+
},
|
|
112
130
|
})
|