@vellira-ui/react-native 2.29.0 → 2.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +300 -131
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -47,7 +47,7 @@ export function Example() {
47
47
 
48
48
  return (
49
49
  <View style={{ gap: 16 }}>
50
- <Input label='Email' value={email} onChange={setEmail} />
50
+ <Input label='Email' value={email} onValueChange={setEmail} />
51
51
  <Checkbox
52
52
  label='Accept terms'
53
53
  description='Required to create an account.'
package/dist/index.js CHANGED
@@ -944,6 +944,7 @@ import { useControllableState as useControllableState2 } from "@vellira-ui/core"
944
944
  import { View as View11 } from "react-native";
945
945
 
946
946
  // src/patterns/FormField/FormField.tsx
947
+ import { useId } from "react";
947
948
  import { Text as Text6, View as View10 } from "react-native";
948
949
 
949
950
  // src/patterns/FormField/FormField.styles.ts
@@ -954,14 +955,14 @@ var createStyles12 = (theme) => StyleSheet12.create({
954
955
  width: "100%",
955
956
  minWidth: 0,
956
957
  alignSelf: "stretch",
957
- gap: theme.tokens.spacing[2]
958
+ gap: theme.components.formField.size.md.gap
958
959
  },
959
960
  label: {
960
961
  color: theme.components.formField.label.fg,
961
962
  fontFamily: theme.tokens.typography.family.medium,
962
- fontSize: theme.tokens.typography.size.md,
963
+ fontSize: theme.components.formField.size.md.labelFontSize,
963
964
  fontWeight: fontWeight(theme.tokens.typography.weight.medium),
964
- lineHeight: theme.tokens.typography.lineHeight.md
965
+ lineHeight: theme.components.formField.size.md.labelLineHeight
965
966
  },
966
967
  labelDisabled: {
967
968
  color: theme.components.formField.disabled.labelFg
@@ -970,11 +971,25 @@ var createStyles12 = (theme) => StyleSheet12.create({
970
971
  marginLeft: theme.tokens.spacing[1],
971
972
  color: theme.components.formField.requiredMark.fg
972
973
  },
974
+ optional: {
975
+ marginLeft: theme.components.formField.size.md.gap,
976
+ color: theme.components.formField.optional.fg,
977
+ fontFamily: theme.tokens.typography.family.regular,
978
+ fontSize: theme.components.formField.size.md.optionalFontSize,
979
+ lineHeight: theme.components.formField.size.md.optionalLineHeight
980
+ },
981
+ labelInfo: {
982
+ marginLeft: theme.components.formField.size.md.gap,
983
+ color: theme.components.formField.labelInfo.fg,
984
+ fontFamily: theme.tokens.typography.family.medium,
985
+ fontSize: theme.components.formField.size.md.labelInfoFontSize,
986
+ lineHeight: theme.components.formField.size.md.labelInfoSize
987
+ },
973
988
  description: {
974
989
  color: theme.components.formField.description.fg,
975
990
  fontFamily: theme.tokens.typography.family.regular,
976
- fontSize: theme.tokens.typography.size.sm,
977
- lineHeight: theme.tokens.typography.lineHeight.sm
991
+ fontSize: theme.components.formField.size.md.descriptionFontSize,
992
+ lineHeight: theme.components.formField.size.md.descriptionLineHeight
978
993
  },
979
994
  descriptionDisabled: {
980
995
  color: theme.components.formField.disabled.descriptionFg
@@ -992,22 +1007,32 @@ var createStyles12 = (theme) => StyleSheet12.create({
992
1007
  error: {
993
1008
  color: theme.components.formField.helperText.error.fg,
994
1009
  fontFamily: theme.tokens.typography.family.regular,
995
- fontSize: theme.tokens.typography.size.sm,
996
- lineHeight: theme.tokens.typography.lineHeight.sm
1010
+ fontSize: theme.components.formField.size.md.helperTextFontSize,
1011
+ lineHeight: theme.components.formField.size.md.helperTextLineHeight
997
1012
  },
998
1013
  helperTextDisabled: {
999
1014
  color: theme.components.formField.disabled.helperTextFg
1000
1015
  }
1001
1016
  });
1002
1017
 
1018
+ // src/patterns/FormField/FormFieldContext.ts
1019
+ import { createContext as createContext3, useContext as useContext3 } from "react";
1020
+ var FormFieldContext = createContext3(null);
1021
+ var useFormFieldContext = () => useContext3(FormFieldContext);
1022
+
1003
1023
  // src/patterns/FormField/FormField.tsx
1004
1024
  import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1005
1025
  function FormField({
1026
+ id,
1006
1027
  label,
1007
1028
  description,
1008
1029
  error,
1009
1030
  required = false,
1010
1031
  disabled = false,
1032
+ invalid = false,
1033
+ size = "md",
1034
+ labelInfo,
1035
+ optionalText,
1011
1036
  children,
1012
1037
  style,
1013
1038
  controlStyle,
@@ -1016,18 +1041,46 @@ function FormField({
1016
1041
  errorStyle,
1017
1042
  ...rest
1018
1043
  }) {
1044
+ const { theme } = useTheme();
1019
1045
  const styles = useThemeStyles(createStyles12);
1046
+ const sizeTokens = theme.components.formField.size[size];
1047
+ const generatedId = useId();
1048
+ const controlId = id ?? generatedId;
1049
+ const labelId = label ? `${controlId}-label` : void 0;
1050
+ const descriptionId = description ? `${controlId}-description` : void 0;
1051
+ const errorId = error ? `${controlId}-error` : void 0;
1052
+ const isInvalid = invalid || Boolean(error);
1053
+ const contextValue = {
1054
+ controlId,
1055
+ labelId,
1056
+ descriptionId,
1057
+ errorId,
1058
+ required,
1059
+ disabled,
1060
+ invalid: isInvalid,
1061
+ size,
1062
+ ariaLabelledBy: labelId,
1063
+ ariaDescribedBy: [descriptionId, errorId].filter(Boolean).join(" ") || void 0
1064
+ };
1020
1065
  return /* @__PURE__ */ jsxs7(
1021
1066
  View10,
1022
1067
  {
1023
1068
  ...rest,
1024
1069
  accessibilityState: disabled ? { disabled: true } : void 0,
1025
- style: [styles.root, style],
1070
+ style: [styles.root, { gap: sizeTokens.gap }, style],
1026
1071
  children: [
1027
1072
  label && (typeof label === "string" || typeof label === "number" ? /* @__PURE__ */ jsxs7(
1028
1073
  Text6,
1029
1074
  {
1030
- style: [styles.label, disabled && styles.labelDisabled, labelStyle],
1075
+ style: [
1076
+ styles.label,
1077
+ {
1078
+ fontSize: sizeTokens.labelFontSize,
1079
+ lineHeight: sizeTokens.labelLineHeight
1080
+ },
1081
+ disabled && styles.labelDisabled,
1082
+ labelStyle
1083
+ ],
1031
1084
  children: [
1032
1085
  label,
1033
1086
  required && /* @__PURE__ */ jsx14(
@@ -1038,6 +1091,32 @@ function FormField({
1038
1091
  importantForAccessibility: "no",
1039
1092
  children: " *"
1040
1093
  }
1094
+ ),
1095
+ !required && optionalText && /* @__PURE__ */ jsx14(
1096
+ Text6,
1097
+ {
1098
+ style: [
1099
+ styles.optional,
1100
+ {
1101
+ fontSize: sizeTokens.optionalFontSize,
1102
+ lineHeight: sizeTokens.optionalLineHeight
1103
+ }
1104
+ ],
1105
+ children: optionalText
1106
+ }
1107
+ ),
1108
+ labelInfo && /* @__PURE__ */ jsx14(
1109
+ Text6,
1110
+ {
1111
+ style: [
1112
+ styles.labelInfo,
1113
+ {
1114
+ fontSize: sizeTokens.labelInfoFontSize,
1115
+ lineHeight: sizeTokens.labelInfoSize
1116
+ }
1117
+ ],
1118
+ children: labelInfo
1119
+ }
1041
1120
  )
1042
1121
  ]
1043
1122
  }
@@ -1051,26 +1130,36 @@ function FormField({
1051
1130
  importantForAccessibility: "no",
1052
1131
  children: "*"
1053
1132
  }
1054
- )
1133
+ ),
1134
+ !required && optionalText,
1135
+ labelInfo
1055
1136
  ] })),
1056
1137
  description && (typeof description === "string" || typeof description === "number" ? /* @__PURE__ */ jsx14(
1057
1138
  Text6,
1058
1139
  {
1059
1140
  style: [
1060
1141
  styles.description,
1142
+ {
1143
+ fontSize: sizeTokens.descriptionFontSize,
1144
+ lineHeight: sizeTokens.descriptionLineHeight
1145
+ },
1061
1146
  disabled && styles.descriptionDisabled,
1062
1147
  descriptionStyle
1063
1148
  ],
1064
1149
  children: description
1065
1150
  }
1066
1151
  ) : description),
1067
- /* @__PURE__ */ jsx14(View10, { style: [styles.control, controlStyle], children }),
1152
+ /* @__PURE__ */ jsx14(FormFieldContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx14(View10, { style: [styles.control, { gap: sizeTokens.gap }, controlStyle], children }) }),
1068
1153
  error && (typeof error === "string" || typeof error === "number" ? /* @__PURE__ */ jsx14(
1069
1154
  Text6,
1070
1155
  {
1071
1156
  accessibilityLiveRegion: "polite",
1072
1157
  style: [
1073
1158
  styles.error,
1159
+ {
1160
+ fontSize: sizeTokens.helperTextFontSize,
1161
+ lineHeight: sizeTokens.helperTextLineHeight
1162
+ },
1074
1163
  disabled && styles.helperTextDisabled,
1075
1164
  errorStyle
1076
1165
  ],
@@ -1101,11 +1190,11 @@ var createStyles13 = (theme) => StyleSheet13.create({
1101
1190
  });
1102
1191
 
1103
1192
  // src/components/RadioGroup/RadioGroupContext.tsx
1104
- import { createContext as createContext3, useContext as useContext3 } from "react";
1105
- var RadioGroupContext = createContext3(null);
1193
+ import { createContext as createContext4, useContext as useContext4 } from "react";
1194
+ var RadioGroupContext = createContext4(null);
1106
1195
  var RadioGroupProvider = RadioGroupContext.Provider;
1107
1196
  function useRadioGroupContext() {
1108
- return useContext3(RadioGroupContext);
1197
+ return useContext4(RadioGroupContext);
1109
1198
  }
1110
1199
 
1111
1200
  // src/components/RadioGroup/RadioGroup.tsx
@@ -1642,11 +1731,11 @@ Select.displayName = "Select";
1642
1731
  import { View as View14 } from "react-native";
1643
1732
 
1644
1733
  // src/components/Tabs/TabsContext.tsx
1645
- import { createContext as createContext4, useContext as useContext4 } from "react";
1646
- var TabsContext = createContext4(null);
1734
+ import { createContext as createContext5, useContext as useContext5 } from "react";
1735
+ var TabsContext = createContext5(null);
1647
1736
  var TabsProvider = TabsContext.Provider;
1648
1737
  var useTabs = () => {
1649
- const context = useContext4(TabsContext);
1738
+ const context = useContext5(TabsContext);
1650
1739
  if (!context) {
1651
1740
  throw new Error("Tabs components must be used inside <Tabs>.");
1652
1741
  }
@@ -2805,7 +2894,6 @@ import { Pressable as Pressable12, Text as Text13, TextInput, View as View21 } f
2805
2894
 
2806
2895
  // src/primitives/Input/Input.styles.ts
2807
2896
  import { StyleSheet as StyleSheet23 } from "react-native";
2808
- var getPlaceholderTextColor = (theme) => theme.components.input.default.placeholder;
2809
2897
  var getDisabledPlaceholderTextColor = (theme) => theme.components.input.disabled.placeholder;
2810
2898
  var resolveRingColor = (ring) => typeof ring === "string" ? ring : ring.color;
2811
2899
  var createStyles23 = (theme) => StyleSheet23.create({
@@ -2867,6 +2955,24 @@ var createStyles23 = (theme) => StyleSheet23.create({
2867
2955
  alignItems: "center",
2868
2956
  justifyContent: "center"
2869
2957
  },
2958
+ revealButton: {
2959
+ position: "absolute",
2960
+ right: theme.tokens.spacing[3],
2961
+ top: "50%",
2962
+ zIndex: 1,
2963
+ minWidth: 40,
2964
+ height: 28,
2965
+ marginTop: -14,
2966
+ borderRadius: theme.tokens.radius.sm,
2967
+ alignItems: "center",
2968
+ justifyContent: "center"
2969
+ },
2970
+ revealButtonText: {
2971
+ color: theme.components.input.icon.muted,
2972
+ fontFamily: theme.tokens.typography.family.medium,
2973
+ fontSize: theme.tokens.typography.size.xs,
2974
+ lineHeight: theme.tokens.typography.lineHeight.xs
2975
+ },
2870
2976
  clearButtonText: {
2871
2977
  color: theme.components.input.clearButton.fg,
2872
2978
  fontSize: 16,
@@ -2920,20 +3026,6 @@ var createStyles23 = (theme) => StyleSheet23.create({
2920
3026
  shadowRadius: 6,
2921
3027
  elevation: 1
2922
3028
  },
2923
- success: {
2924
- borderColor: theme.components.input.success.border
2925
- },
2926
- successFocused: {
2927
- borderColor: theme.components.input.success.border,
2928
- shadowColor: resolveRingColor(theme.components.input.success.ring),
2929
- shadowOffset: {
2930
- width: 0,
2931
- height: 0
2932
- },
2933
- shadowOpacity: 0.18,
2934
- shadowRadius: 6,
2935
- elevation: 1
2936
- },
2937
3029
  readOnly: {
2938
3030
  color: theme.components.input.readOnly.fg,
2939
3031
  borderColor: theme.components.input.readOnly.border,
@@ -2976,24 +3068,48 @@ var autoCorrectByInputType = {
2976
3068
  url: false,
2977
3069
  search: false
2978
3070
  };
3071
+ var applyPatternMask = (value, pattern) => {
3072
+ const digits = value.replace(/\D/g, "");
3073
+ let digitIndex = 0;
3074
+ let maskedValue = "";
3075
+ for (const character of pattern) {
3076
+ if (character === "#") {
3077
+ const nextDigit = digits[digitIndex];
3078
+ if (!nextDigit) break;
3079
+ maskedValue += nextDigit;
3080
+ digitIndex += 1;
3081
+ continue;
3082
+ }
3083
+ if (digitIndex < digits.length) {
3084
+ maskedValue += character;
3085
+ }
3086
+ }
3087
+ return maskedValue;
3088
+ };
3089
+ var applyMask = (value, mask) => {
3090
+ if (!mask) return value;
3091
+ return typeof mask === "function" ? mask(value) : applyPatternMask(value, mask);
3092
+ };
2979
3093
  var Input = forwardRef3(
2980
3094
  ({
2981
3095
  label,
2982
3096
  description,
2983
3097
  value,
2984
3098
  defaultValue,
2985
- onChange,
3099
+ onValueChange,
2986
3100
  placeholder,
2987
- size = "md",
3101
+ size,
2988
3102
  error,
3103
+ invalid = false,
2989
3104
  disabled = false,
2990
3105
  required = false,
3106
+ loading = false,
2991
3107
  readOnly = false,
2992
3108
  type = "text",
2993
- leftIcon,
2994
- rightIcon,
2995
- leftIconTone = "default",
2996
- rightIconTone = "default",
3109
+ startIcon,
3110
+ endIcon,
3111
+ startIconTone = "default",
3112
+ endIconTone = "default",
2997
3113
  clearIcon,
2998
3114
  clearIconTone = "danger",
2999
3115
  iconSize,
@@ -3012,19 +3128,38 @@ var Input = forwardRef3(
3012
3128
  maxLength,
3013
3129
  clearable,
3014
3130
  onClear,
3131
+ color = "primary",
3132
+ variant = "outline",
3133
+ revealPassword = false,
3134
+ showCounter: _showCounter,
3135
+ mask,
3136
+ format,
3137
+ parse,
3015
3138
  ...props
3016
3139
  }, ref) => {
3017
3140
  const { theme } = useTheme();
3018
3141
  const styles = useThemeStyles(createStyles23);
3142
+ const field = useFormFieldContext();
3143
+ const hasOwnField = Boolean(label || description || error);
3019
3144
  const [isFocused, setIsFocused] = useState6(false);
3020
3145
  const [uncontrolledValue, setUncontrolledValue] = useState6(
3021
3146
  defaultValue ?? ""
3022
3147
  );
3023
3148
  const isControlled = value !== void 0;
3024
3149
  const currentValue = isControlled ? value : uncontrolledValue;
3150
+ const displayValue = format ? format(currentValue) : currentValue;
3025
3151
  const hasValue = currentValue !== "";
3026
- const placeholderTextColor = disabled ? getDisabledPlaceholderTextColor(theme) : readOnly ? theme.components.input.readOnly.placeholder : getPlaceholderTextColor(theme);
3152
+ const resolvedSize = size ?? field?.size ?? "md";
3153
+ const inputColorPalette = theme.components.input[color];
3154
+ const inputPalette = inputColorPalette[variant];
3155
+ const inputState = isFocused ? inputPalette.focus : inputPalette.default;
3156
+ const isInvalid = invalid || Boolean(error) || !hasOwnField && Boolean(field?.invalid);
3157
+ const isDisabled = disabled || !hasOwnField && Boolean(field?.disabled);
3158
+ const isRequired = required || !hasOwnField && Boolean(field?.required);
3159
+ const isReadOnly = readOnly || loading;
3160
+ const placeholderTextColor = isDisabled ? getDisabledPlaceholderTextColor(theme) : readOnly ? theme.components.input.readOnly.placeholder : inputState.placeholder;
3027
3161
  const isPassword = type === "password";
3162
+ const [isPasswordRevealed, setIsPasswordRevealed] = useState6(false);
3028
3163
  const resolvedIconSize = iconSize ?? 16;
3029
3164
  const handleFocus = (event) => {
3030
3165
  setIsFocused(true);
@@ -3035,114 +3170,148 @@ var Input = forwardRef3(
3035
3170
  onBlur?.(event);
3036
3171
  };
3037
3172
  const handleChangeText = (nextValue) => {
3173
+ const parsedValue = parse ? parse(nextValue) : nextValue;
3174
+ const maskedValue = applyMask(parsedValue, mask);
3038
3175
  if (!isControlled) {
3039
- setUncontrolledValue(nextValue);
3176
+ setUncontrolledValue(maskedValue);
3040
3177
  }
3041
- onChange?.(nextValue);
3178
+ onValueChange?.(maskedValue);
3042
3179
  };
3043
3180
  const handleClear = () => {
3044
3181
  if (!isControlled) {
3045
3182
  setUncontrolledValue("");
3046
3183
  }
3184
+ onValueChange?.("");
3047
3185
  onClear?.();
3048
3186
  };
3049
- const showClearButton = clearable && hasValue && !disabled && !readOnly;
3050
- const showRightIcon = !showClearButton && Boolean(rightIcon);
3051
- const leftIconColor = disabled ? theme.components.input.disabled.icon : theme.components.input.icon[leftIconTone];
3052
- const rightIconColor = disabled ? theme.components.input.disabled.icon : theme.components.input.icon[rightIconTone];
3053
- const clearIconColor = disabled ? theme.components.input.disabled.icon : theme.components.input.icon[clearIconTone];
3187
+ const showClearButton = clearable && hasValue && !isDisabled && !isReadOnly;
3188
+ const showRevealButton = revealPassword && isPassword && !isDisabled;
3189
+ const showRightIcon = !showClearButton && !showRevealButton && Boolean(endIcon);
3190
+ const startIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[startIconTone];
3191
+ const endIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[endIconTone];
3192
+ const clearIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[clearIconTone];
3193
+ const control = /* @__PURE__ */ jsxs14(View21, { style: styles.inputWrapper, children: [
3194
+ startIcon && /* @__PURE__ */ jsx25(
3195
+ View21,
3196
+ {
3197
+ pointerEvents: "none",
3198
+ style: styles.leftIcon,
3199
+ accessibilityElementsHidden: true,
3200
+ importantForAccessibility: "no",
3201
+ children: cloneElement6(startIcon, {
3202
+ color: startIconColor,
3203
+ size: resolvedIconSize
3204
+ })
3205
+ }
3206
+ ),
3207
+ /* @__PURE__ */ jsx25(
3208
+ TextInput,
3209
+ {
3210
+ ...props,
3211
+ ref,
3212
+ nativeID: props.nativeID ?? (!hasOwnField ? field?.controlId : void 0),
3213
+ value: displayValue,
3214
+ onChangeText: handleChangeText,
3215
+ editable: !isDisabled && !isReadOnly,
3216
+ placeholder,
3217
+ keyboardType: keyboardType ?? keyboardTypeByInputType[type],
3218
+ secureTextEntry: secureTextEntry ?? (isPassword && !isPasswordRevealed),
3219
+ autoCapitalize: autoCapitalize ?? autoCapitalizeByInputType[type],
3220
+ autoCorrect: autoCorrect ?? autoCorrectByInputType[type],
3221
+ onBlur: handleBlur,
3222
+ onFocus: handleFocus,
3223
+ autoFocus,
3224
+ maxLength,
3225
+ testID,
3226
+ placeholderTextColor,
3227
+ accessibilityLabel: accessibilityLabel ?? label,
3228
+ accessibilityHint,
3229
+ accessibilityState: { disabled: isDisabled },
3230
+ accessibilityLabelledBy: !hasOwnField ? field?.labelId : void 0,
3231
+ "aria-describedby": !hasOwnField ? field?.ariaDescribedBy : void 0,
3232
+ style: [
3233
+ styles.input,
3234
+ {
3235
+ color: inputState.fg,
3236
+ backgroundColor: inputState.bg,
3237
+ borderColor: inputState.border
3238
+ },
3239
+ styles[resolvedSize],
3240
+ inputStyle,
3241
+ startIcon && styles.inputWithLeftAdornment,
3242
+ (showRightIcon || showClearButton || showRevealButton) && styles.inputWithRightAdornment,
3243
+ isFocused && !isDisabled && !isReadOnly && {
3244
+ color: inputPalette.focus.fg,
3245
+ backgroundColor: inputPalette.focus.bg,
3246
+ borderColor: inputPalette.focus.border,
3247
+ shadowColor: inputColorPalette.ring,
3248
+ shadowOffset: {
3249
+ width: 0,
3250
+ height: 0
3251
+ },
3252
+ shadowOpacity: 0.18,
3253
+ shadowRadius: 6,
3254
+ elevation: 1
3255
+ },
3256
+ isInvalid && styles.error,
3257
+ isFocused && isInvalid && !isDisabled && !isReadOnly && styles.errorFocused,
3258
+ isReadOnly && !isDisabled && styles.readOnly,
3259
+ isDisabled && styles.disabled
3260
+ ]
3261
+ }
3262
+ ),
3263
+ showClearButton ? /* @__PURE__ */ jsx25(
3264
+ Pressable12,
3265
+ {
3266
+ accessibilityRole: "button",
3267
+ accessibilityLabel: "Clear input",
3268
+ hitSlop: 8,
3269
+ onPress: handleClear,
3270
+ style: styles.clearButton,
3271
+ children: clearIcon ? cloneElement6(clearIcon, {
3272
+ color: clearIconColor,
3273
+ size: resolvedIconSize
3274
+ }) : /* @__PURE__ */ jsx25(Text13, { style: [styles.clearButtonText, { color: clearIconColor }], children: "\xD7" })
3275
+ }
3276
+ ) : showRevealButton ? /* @__PURE__ */ jsx25(
3277
+ Pressable12,
3278
+ {
3279
+ accessibilityRole: "button",
3280
+ accessibilityLabel: isPasswordRevealed ? "Hide password" : "Show password",
3281
+ hitSlop: 8,
3282
+ onPress: () => setIsPasswordRevealed((revealed) => !revealed),
3283
+ style: styles.revealButton,
3284
+ children: /* @__PURE__ */ jsx25(Text13, { style: styles.revealButtonText, children: isPasswordRevealed ? "Hide" : "Show" })
3285
+ }
3286
+ ) : showRightIcon && endIcon && /* @__PURE__ */ jsx25(
3287
+ View21,
3288
+ {
3289
+ pointerEvents: "none",
3290
+ style: styles.rightIcon,
3291
+ accessibilityElementsHidden: true,
3292
+ importantForAccessibility: "no",
3293
+ children: cloneElement6(endIcon, {
3294
+ color: endIconColor,
3295
+ size: resolvedIconSize
3296
+ })
3297
+ }
3298
+ )
3299
+ ] });
3300
+ if (!hasOwnField && field) {
3301
+ return control;
3302
+ }
3054
3303
  return /* @__PURE__ */ jsx25(
3055
3304
  FormField,
3056
3305
  {
3057
3306
  label,
3058
3307
  description,
3059
3308
  error,
3060
- required,
3061
- disabled,
3309
+ required: isRequired,
3310
+ disabled: isDisabled,
3311
+ invalid: isInvalid,
3312
+ size: resolvedSize,
3062
3313
  style: containerStyle,
3063
- children: /* @__PURE__ */ jsxs14(View21, { style: styles.inputWrapper, children: [
3064
- leftIcon && /* @__PURE__ */ jsx25(
3065
- View21,
3066
- {
3067
- pointerEvents: "none",
3068
- style: styles.leftIcon,
3069
- accessibilityElementsHidden: true,
3070
- importantForAccessibility: "no",
3071
- children: cloneElement6(leftIcon, {
3072
- color: leftIconColor,
3073
- size: resolvedIconSize
3074
- })
3075
- }
3076
- ),
3077
- /* @__PURE__ */ jsx25(
3078
- TextInput,
3079
- {
3080
- ...props,
3081
- ref,
3082
- value: currentValue,
3083
- onChangeText: handleChangeText,
3084
- editable: !disabled && !readOnly,
3085
- placeholder,
3086
- keyboardType: keyboardType ?? keyboardTypeByInputType[type],
3087
- secureTextEntry: secureTextEntry ?? isPassword,
3088
- autoCapitalize: autoCapitalize ?? autoCapitalizeByInputType[type],
3089
- autoCorrect: autoCorrect ?? autoCorrectByInputType[type],
3090
- onBlur: handleBlur,
3091
- onFocus: handleFocus,
3092
- autoFocus,
3093
- maxLength,
3094
- testID,
3095
- placeholderTextColor,
3096
- accessibilityLabel: accessibilityLabel ?? label,
3097
- accessibilityHint,
3098
- accessibilityState: { disabled },
3099
- style: [
3100
- styles.input,
3101
- styles[size],
3102
- inputStyle,
3103
- leftIcon && styles.inputWithLeftAdornment,
3104
- (showRightIcon || showClearButton) && styles.inputWithRightAdornment,
3105
- isFocused && !disabled && !readOnly && styles.focused,
3106
- error && styles.error,
3107
- isFocused && error && !disabled && !readOnly && styles.errorFocused,
3108
- readOnly && !disabled && styles.readOnly,
3109
- disabled && styles.disabled
3110
- ]
3111
- }
3112
- ),
3113
- showClearButton ? /* @__PURE__ */ jsx25(
3114
- Pressable12,
3115
- {
3116
- accessibilityRole: "button",
3117
- accessibilityLabel: "Clear input",
3118
- hitSlop: 8,
3119
- onPress: handleClear,
3120
- style: styles.clearButton,
3121
- children: clearIcon ? cloneElement6(clearIcon, {
3122
- color: clearIconColor,
3123
- size: resolvedIconSize
3124
- }) : /* @__PURE__ */ jsx25(
3125
- Text13,
3126
- {
3127
- style: [styles.clearButtonText, { color: clearIconColor }],
3128
- children: "\xD7"
3129
- }
3130
- )
3131
- }
3132
- ) : showRightIcon && rightIcon && /* @__PURE__ */ jsx25(
3133
- View21,
3134
- {
3135
- pointerEvents: "none",
3136
- style: styles.rightIcon,
3137
- accessibilityElementsHidden: true,
3138
- importantForAccessibility: "no",
3139
- children: cloneElement6(rightIcon, {
3140
- color: rightIconColor,
3141
- size: resolvedIconSize
3142
- })
3143
- }
3144
- )
3145
- ] })
3314
+ children: control
3146
3315
  }
3147
3316
  );
3148
3317
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellira-ui/react-native",
3
- "version": "2.29.0",
3
+ "version": "2.30.0",
4
4
  "description": "React Native components for Vellira Design System",
5
5
  "author": "Roman Bakurov",
6
6
  "license": "MIT",