elseware-ui 3.0.6 → 3.0.7

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.
@@ -1,4 +1,4 @@
1
- import { Pressable, View, ActivityIndicator, Text, Animated, Easing, TextInput } from 'react-native';
1
+ import { Pressable, View, ActivityIndicator, Text, Animated, Easing, TextInput, Modal, ScrollView } from 'react-native';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import { createContext, useState, useContext, useRef, useEffect } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
@@ -598,139 +598,6 @@ function Checkbox(checkboxProps) {
598
598
  errorText ? /* @__PURE__ */ jsx$1(Text, { className: "px-2 py-1 text-sm font-medium text-eui-danger-500", children: errorText }) : null
599
599
  ] });
600
600
  }
601
- function renderFormChildren(children, formik) {
602
- return typeof children === "function" ? children(formik) : children;
603
- }
604
- function FormObservers({
605
- formik,
606
- onChange,
607
- onDirtyChange
608
- }) {
609
- const prevValuesRef = useRef(formik.values);
610
- useEffect(() => {
611
- onDirtyChange?.(formik.dirty);
612
- }, [formik.dirty, onDirtyChange]);
613
- useEffect(() => {
614
- if (!onChange) return;
615
- const currentValues = formik.values;
616
- const prevValues = prevValuesRef.current;
617
- const changed = {};
618
- Object.keys(currentValues).forEach((key) => {
619
- if (currentValues[key] !== prevValues[key]) {
620
- changed[key] = currentValues[key];
621
- }
622
- });
623
- if (Object.keys(changed).length > 0) {
624
- onChange(currentValues, { changed });
625
- }
626
- prevValuesRef.current = currentValues;
627
- }, [formik.values, onChange]);
628
- return null;
629
- }
630
- function Form({
631
- initialValues = {},
632
- validationSchema,
633
- enableReinitialize,
634
- children,
635
- className,
636
- contentClassName,
637
- onSubmit,
638
- onChange,
639
- onDirtyChange
640
- }) {
641
- return /* @__PURE__ */ jsx$1(
642
- Formik,
643
- {
644
- initialValues,
645
- validationSchema,
646
- enableReinitialize,
647
- onSubmit: async (values, helpers) => {
648
- await onSubmit(values, helpers);
649
- },
650
- children: (formik) => /* @__PURE__ */ jsxs(View, { className: cn(className), children: [
651
- /* @__PURE__ */ jsx$1(
652
- FormObservers,
653
- {
654
- formik,
655
- onChange,
656
- onDirtyChange
657
- }
658
- ),
659
- /* @__PURE__ */ jsx$1(View, { className: cn(contentClassName), children: renderFormChildren(children, formik) })
660
- ] })
661
- }
662
- );
663
- }
664
-
665
- // src/components/data-entry/form/form-response/base/FormResponse.styles.ts
666
- var formResponseSizeStyles = {
667
- xs: {
668
- root: "px-2 py-1",
669
- text: "text-xs"
670
- },
671
- sm: {
672
- root: "px-3 py-2",
673
- text: "text-sm"
674
- },
675
- md: {
676
- root: "px-4 py-2",
677
- text: "text-base"
678
- },
679
- lg: {
680
- root: "px-5 py-3",
681
- text: "text-lg"
682
- },
683
- xl: {
684
- root: "px-6 py-4",
685
- text: "text-xl"
686
- }
687
- };
688
- function isTextClassName(token) {
689
- const styleToken = token.split(":").pop() ?? token;
690
- return styleToken.startsWith("text-");
691
- }
692
- function splitClassName(className) {
693
- const tokens = className.split(/\s+/).filter(Boolean);
694
- return {
695
- root: tokens.filter((token) => !isTextClassName(token)).join(" "),
696
- text: tokens.filter(isTextClassName).join(" ")
697
- };
698
- }
699
- function resolveFormResponseStyles({
700
- shape,
701
- size,
702
- variant
703
- }) {
704
- const variantClassNames = splitClassName(variantsLite[variant]);
705
- const sizeClassNames = formResponseSizeStyles[size];
706
- return {
707
- rootClassName: [
708
- "border",
709
- variantClassNames.root,
710
- shapes[shape],
711
- sizeClassNames.root
712
- ].filter(Boolean).join(" "),
713
- textClassName: [
714
- "font-poppins font-light",
715
- variantClassNames.text,
716
- sizeClassNames.text
717
- ].filter(Boolean).join(" ")
718
- };
719
- }
720
- function FormResponse({
721
- text,
722
- variant = "default",
723
- shape = "roundedSquare",
724
- size = "md",
725
- className,
726
- textClassName
727
- }) {
728
- if (!text) {
729
- return null;
730
- }
731
- const styles = resolveFormResponseStyles({ shape, size, variant });
732
- return /* @__PURE__ */ jsx$1(View, { className: cn(styles.rootClassName, className), children: /* @__PURE__ */ jsx$1(Text, { className: cn(styles.textClassName, textClassName), children: text }) });
733
- }
734
601
 
735
602
  // src/components/data-entry/input/input-label/base/InputLabel.styles.ts
736
603
  var inputLabelStaticClassName = "pointer-events-none select-none px-0 text-[13.5px] leading-none text-[#6B7280]";
@@ -874,35 +741,8 @@ function InputResponse({
874
741
  }
875
742
  ) });
876
743
  }
877
- function resolveInputType({
878
- passwordVisible,
879
- type
880
- }) {
881
- return type === "password" && passwordVisible ? "text" : type;
882
- }
883
- function useResolvedInputConfig({
884
- label,
885
- placeholder,
886
- shape,
887
- type = "text"
888
- }) {
889
- const eui = useEUIConfig();
890
- return {
891
- shape: shape ?? eui?.config?.global?.shape ?? "square",
892
- type,
893
- label: label ?? placeholder
894
- };
895
- }
896
- function useInputFieldState(props) {
897
- const [field, meta, helpers] = useField(props);
898
- return {
899
- field,
900
- meta,
901
- helpers
902
- };
903
- }
904
744
 
905
- // src/components/data-entry/input/input/base/Input.styles.ts
745
+ // src/data/styles/shared.styles.tsx
906
746
  var inputShapes = shapes;
907
747
  var inputRootClassName = "relative w-full";
908
748
  var inputFrameClassName = "relative h-14 w-full overflow-hidden border bg-white/95 px-3 dark:bg-eui-primary-300/10";
@@ -927,55 +767,49 @@ var nativeInputControlStyle = {
927
767
  outlineStyle: "none",
928
768
  textAlignVertical: "center"
929
769
  };
930
- function Input(inputProps) {
770
+ function useResolvedDateSelectorConfig({
771
+ label,
772
+ placeholder,
773
+ shape
774
+ }) {
775
+ const eui = useEUIConfig();
776
+ return {
777
+ label: label ?? placeholder,
778
+ shape: shape ?? eui?.config?.global?.shape ?? "square"
779
+ };
780
+ }
781
+ function useDateSelectorFieldState(props) {
782
+ const [field, meta, helpers] = useField(props);
783
+ return {
784
+ field,
785
+ helpers,
786
+ meta
787
+ };
788
+ }
789
+ function DateSelector(dateSelectorProps) {
931
790
  const {
932
- type = "text",
933
- label,
934
- placeholder,
791
+ disabled = false,
935
792
  inputClassName,
793
+ label,
936
794
  labelClassName,
795
+ placeholder,
937
796
  responseClassName,
938
- step: _step,
939
797
  shape,
940
- disabled = false,
798
+ styles,
941
799
  className,
942
800
  onBlur,
943
- onFocus,
944
- onChange: _onChange,
945
- ..._props
946
- } = inputProps;
947
- const { field, helpers, meta } = useInputFieldState(inputProps);
801
+ onFocus
802
+ } = dateSelectorProps;
803
+ const { field, helpers, meta } = useDateSelectorFieldState(dateSelectorProps);
948
804
  const [focused, setFocused] = useState(false);
949
- const [passwordVisible, setPasswordVisible] = useState(false);
950
- const labelProgress = useRef(
951
- new Animated.Value(String(field.value ?? "").length > 0 ? 1 : 0)
952
- ).current;
953
- const {
954
- shape: resolvedShape,
955
- type: resolvedType,
956
- label: resolvedLabel
957
- } = useResolvedInputConfig({
805
+ const labelProgress = useRef(new Animated.Value(1)).current;
806
+ const { label: resolvedLabel, shape: resolvedShape } = useResolvedDateSelectorConfig({
958
807
  label,
959
808
  placeholder,
960
- shape,
961
- type
962
- });
963
- const inputType = resolveInputType({
964
- passwordVisible,
965
- type: resolvedType
809
+ shape
966
810
  });
967
811
  const hasError = Boolean(meta.touched && meta.error);
968
812
  const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
969
- const hasValue = String(field.value ?? "").length > 0;
970
- const floating = focused || hasValue;
971
- useEffect(() => {
972
- Animated.timing(labelProgress, {
973
- duration: 190,
974
- easing: Easing.out(Easing.cubic),
975
- toValue: floating ? 1 : 0,
976
- useNativeDriver: false
977
- }).start();
978
- }, [floating, labelProgress]);
979
813
  const handleBlur = (event) => {
980
814
  setFocused(false);
981
815
  helpers.setTouched(true);
@@ -983,7 +817,9 @@ function Input(inputProps) {
983
817
  };
984
818
  const handleFocus = (event) => {
985
819
  setFocused(true);
986
- onFocus?.(event);
820
+ onFocus?.(
821
+ event
822
+ );
987
823
  };
988
824
  return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
989
825
  /* @__PURE__ */ jsx$1(
@@ -994,7 +830,8 @@ function Input(inputProps) {
994
830
  hasError ? inputFrameErrorClassName : focused ? inputFrameActiveClassName : inputFrameIdleClassName,
995
831
  inputShapes[resolvedShape],
996
832
  disabled && inputFrameDisabledClassName,
997
- className
833
+ className,
834
+ styles
998
835
  ),
999
836
  children: /* @__PURE__ */ jsx$1(
1000
837
  TextInput,
@@ -1003,16 +840,14 @@ function Input(inputProps) {
1003
840
  className: cn(
1004
841
  inputControlClassName,
1005
842
  nativeInputControlClassName,
1006
- type === "password" && nativePasswordInputClassName,
1007
843
  inputClassName
1008
844
  ),
1009
845
  editable: !disabled,
1010
- keyboardType: inputType === "number" ? "numeric" : "default",
846
+ keyboardType: "numbers-and-punctuation",
1011
847
  onBlur: handleBlur,
1012
848
  onChangeText: (value) => helpers.setValue(value),
1013
849
  onFocus: handleFocus,
1014
850
  placeholder: "",
1015
- secureTextEntry: type === "password" && !passwordVisible,
1016
851
  style: nativeInputControlStyle,
1017
852
  underlineColorAndroid: "transparent",
1018
853
  value: field.value ?? ""
@@ -1026,22 +861,979 @@ function Input(inputProps) {
1026
861
  animatedValue: labelProgress,
1027
862
  disabled,
1028
863
  errored: hasError,
1029
- floating,
864
+ floating: true,
1030
865
  text: resolvedLabel,
1031
866
  className: labelClassName
1032
867
  }
1033
868
  ),
1034
- type === "password" ? /* @__PURE__ */ jsx$1(
1035
- Pressable,
869
+ /* @__PURE__ */ jsx$1(
870
+ InputResponse,
1036
871
  {
1037
- accessibilityRole: "button",
1038
- accessibilityLabel: passwordVisible ? "Hide password" : "Show password",
1039
- className: nativePasswordToggleClassName,
1040
- disabled,
1041
- onPress: () => setPasswordVisible((current) => !current),
1042
- children: /* @__PURE__ */ jsx$1(Text, { className: nativePasswordToggleTextClassName, children: passwordVisible ? "Hide" : "Show" })
872
+ message: errorText,
873
+ name: field.name,
874
+ visibility: Boolean(errorText),
875
+ variant: "danger",
876
+ className: responseClassName
1043
877
  }
1044
- ) : null,
878
+ )
879
+ ] });
880
+ }
881
+ function renderFormChildren(children, formik) {
882
+ return typeof children === "function" ? children(formik) : children;
883
+ }
884
+ function FormObservers({
885
+ formik,
886
+ onChange,
887
+ onDirtyChange
888
+ }) {
889
+ const prevValuesRef = useRef(formik.values);
890
+ useEffect(() => {
891
+ onDirtyChange?.(formik.dirty);
892
+ }, [formik.dirty, onDirtyChange]);
893
+ useEffect(() => {
894
+ if (!onChange) return;
895
+ const currentValues = formik.values;
896
+ const prevValues = prevValuesRef.current;
897
+ const changed = {};
898
+ Object.keys(currentValues).forEach((key) => {
899
+ if (currentValues[key] !== prevValues[key]) {
900
+ changed[key] = currentValues[key];
901
+ }
902
+ });
903
+ if (Object.keys(changed).length > 0) {
904
+ onChange(currentValues, { changed });
905
+ }
906
+ prevValuesRef.current = currentValues;
907
+ }, [formik.values, onChange]);
908
+ return null;
909
+ }
910
+ function Form({
911
+ initialValues = {},
912
+ validationSchema,
913
+ enableReinitialize,
914
+ children,
915
+ className,
916
+ contentClassName,
917
+ onSubmit,
918
+ onChange,
919
+ onDirtyChange
920
+ }) {
921
+ return /* @__PURE__ */ jsx$1(
922
+ Formik,
923
+ {
924
+ initialValues,
925
+ validationSchema,
926
+ enableReinitialize,
927
+ onSubmit: async (values, helpers) => {
928
+ await onSubmit(values, helpers);
929
+ },
930
+ children: (formik) => /* @__PURE__ */ jsxs(View, { className: cn(className), children: [
931
+ /* @__PURE__ */ jsx$1(
932
+ FormObservers,
933
+ {
934
+ formik,
935
+ onChange,
936
+ onDirtyChange
937
+ }
938
+ ),
939
+ /* @__PURE__ */ jsx$1(View, { className: cn(contentClassName), children: renderFormChildren(children, formik) })
940
+ ] })
941
+ }
942
+ );
943
+ }
944
+
945
+ // src/components/data-entry/form/form-response/base/FormResponse.styles.ts
946
+ var formResponseSizeStyles = {
947
+ xs: {
948
+ root: "px-2 py-1",
949
+ text: "text-xs"
950
+ },
951
+ sm: {
952
+ root: "px-3 py-2",
953
+ text: "text-sm"
954
+ },
955
+ md: {
956
+ root: "px-4 py-2",
957
+ text: "text-base"
958
+ },
959
+ lg: {
960
+ root: "px-5 py-3",
961
+ text: "text-lg"
962
+ },
963
+ xl: {
964
+ root: "px-6 py-4",
965
+ text: "text-xl"
966
+ }
967
+ };
968
+ function isTextClassName(token) {
969
+ const styleToken = token.split(":").pop() ?? token;
970
+ return styleToken.startsWith("text-");
971
+ }
972
+ function splitClassName(className) {
973
+ const tokens = className.split(/\s+/).filter(Boolean);
974
+ return {
975
+ root: tokens.filter((token) => !isTextClassName(token)).join(" "),
976
+ text: tokens.filter(isTextClassName).join(" ")
977
+ };
978
+ }
979
+ function resolveFormResponseStyles({
980
+ shape,
981
+ size,
982
+ variant
983
+ }) {
984
+ const variantClassNames = splitClassName(variantsLite[variant]);
985
+ const sizeClassNames = formResponseSizeStyles[size];
986
+ return {
987
+ rootClassName: [
988
+ "border",
989
+ variantClassNames.root,
990
+ shapes[shape],
991
+ sizeClassNames.root
992
+ ].filter(Boolean).join(" "),
993
+ textClassName: [
994
+ "font-poppins font-light",
995
+ variantClassNames.text,
996
+ sizeClassNames.text
997
+ ].filter(Boolean).join(" ")
998
+ };
999
+ }
1000
+ function FormResponse({
1001
+ text,
1002
+ variant = "default",
1003
+ shape = "roundedSquare",
1004
+ size = "md",
1005
+ className,
1006
+ textClassName
1007
+ }) {
1008
+ if (!text) {
1009
+ return null;
1010
+ }
1011
+ const styles = resolveFormResponseStyles({ shape, size, variant });
1012
+ return /* @__PURE__ */ jsx$1(View, { className: cn(styles.rootClassName, className), children: /* @__PURE__ */ jsx$1(Text, { className: cn(styles.textClassName, textClassName), children: text }) });
1013
+ }
1014
+ function resolveInputType({
1015
+ passwordVisible,
1016
+ type
1017
+ }) {
1018
+ return type === "password" && passwordVisible ? "text" : type;
1019
+ }
1020
+ function useResolvedInputConfig({
1021
+ label,
1022
+ placeholder,
1023
+ shape,
1024
+ type = "text"
1025
+ }) {
1026
+ const eui = useEUIConfig();
1027
+ return {
1028
+ shape: shape ?? eui?.config?.global?.shape ?? "square",
1029
+ type,
1030
+ label: label ?? placeholder
1031
+ };
1032
+ }
1033
+ function useInputFieldState(props) {
1034
+ const [field, meta, helpers] = useField(props);
1035
+ return {
1036
+ field,
1037
+ meta,
1038
+ helpers
1039
+ };
1040
+ }
1041
+ function Input(inputProps) {
1042
+ const {
1043
+ type = "text",
1044
+ label,
1045
+ placeholder,
1046
+ inputClassName,
1047
+ labelClassName,
1048
+ responseClassName,
1049
+ step: _step,
1050
+ shape,
1051
+ disabled = false,
1052
+ className,
1053
+ onBlur,
1054
+ onFocus,
1055
+ onChange: _onChange,
1056
+ ..._props
1057
+ } = inputProps;
1058
+ const { field, helpers, meta } = useInputFieldState(inputProps);
1059
+ const [focused, setFocused] = useState(false);
1060
+ const [passwordVisible, setPasswordVisible] = useState(false);
1061
+ const labelProgress = useRef(
1062
+ new Animated.Value(String(field.value ?? "").length > 0 ? 1 : 0)
1063
+ ).current;
1064
+ const {
1065
+ shape: resolvedShape,
1066
+ type: resolvedType,
1067
+ label: resolvedLabel
1068
+ } = useResolvedInputConfig({
1069
+ label,
1070
+ placeholder,
1071
+ shape,
1072
+ type
1073
+ });
1074
+ const inputType = resolveInputType({
1075
+ passwordVisible,
1076
+ type: resolvedType
1077
+ });
1078
+ const hasError = Boolean(meta.touched && meta.error);
1079
+ const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
1080
+ const hasValue = String(field.value ?? "").length > 0;
1081
+ const floating = focused || hasValue;
1082
+ useEffect(() => {
1083
+ Animated.timing(labelProgress, {
1084
+ duration: 190,
1085
+ easing: Easing.out(Easing.cubic),
1086
+ toValue: floating ? 1 : 0,
1087
+ useNativeDriver: false
1088
+ }).start();
1089
+ }, [floating, labelProgress]);
1090
+ const handleBlur = (event) => {
1091
+ setFocused(false);
1092
+ helpers.setTouched(true);
1093
+ onBlur?.(event);
1094
+ };
1095
+ const handleFocus = (event) => {
1096
+ setFocused(true);
1097
+ onFocus?.(event);
1098
+ };
1099
+ return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
1100
+ /* @__PURE__ */ jsx$1(
1101
+ View,
1102
+ {
1103
+ className: cn(
1104
+ inputFrameClassName,
1105
+ hasError ? inputFrameErrorClassName : focused ? inputFrameActiveClassName : inputFrameIdleClassName,
1106
+ inputShapes[resolvedShape],
1107
+ disabled && inputFrameDisabledClassName,
1108
+ className
1109
+ ),
1110
+ children: /* @__PURE__ */ jsx$1(
1111
+ TextInput,
1112
+ {
1113
+ accessibilityLabel: resolvedLabel,
1114
+ className: cn(
1115
+ inputControlClassName,
1116
+ nativeInputControlClassName,
1117
+ type === "password" && nativePasswordInputClassName,
1118
+ inputClassName
1119
+ ),
1120
+ editable: !disabled,
1121
+ keyboardType: inputType === "number" ? "numeric" : "default",
1122
+ onBlur: handleBlur,
1123
+ onChangeText: (value) => helpers.setValue(value),
1124
+ onFocus: handleFocus,
1125
+ placeholder: "",
1126
+ secureTextEntry: type === "password" && !passwordVisible,
1127
+ style: nativeInputControlStyle,
1128
+ underlineColorAndroid: "transparent",
1129
+ value: field.value ?? ""
1130
+ }
1131
+ )
1132
+ }
1133
+ ),
1134
+ /* @__PURE__ */ jsx$1(
1135
+ InputLabel,
1136
+ {
1137
+ animatedValue: labelProgress,
1138
+ disabled,
1139
+ errored: hasError,
1140
+ floating,
1141
+ text: resolvedLabel,
1142
+ className: labelClassName
1143
+ }
1144
+ ),
1145
+ type === "password" ? /* @__PURE__ */ jsx$1(
1146
+ Pressable,
1147
+ {
1148
+ accessibilityRole: "button",
1149
+ accessibilityLabel: passwordVisible ? "Hide password" : "Show password",
1150
+ className: nativePasswordToggleClassName,
1151
+ disabled,
1152
+ onPress: () => setPasswordVisible((current) => !current),
1153
+ children: /* @__PURE__ */ jsx$1(Text, { className: nativePasswordToggleTextClassName, children: passwordVisible ? "Hide" : "Show" })
1154
+ }
1155
+ ) : null,
1156
+ /* @__PURE__ */ jsx$1(
1157
+ InputResponse,
1158
+ {
1159
+ message: errorText,
1160
+ name: field.name,
1161
+ visibility: Boolean(errorText),
1162
+ variant: "danger",
1163
+ className: responseClassName
1164
+ }
1165
+ )
1166
+ ] });
1167
+ }
1168
+ function useResolvedInputFileConfig({
1169
+ label,
1170
+ placeholder,
1171
+ shape
1172
+ }) {
1173
+ const eui = useEUIConfig();
1174
+ return {
1175
+ label: label ?? placeholder,
1176
+ shape: shape ?? eui?.config?.global?.shape ?? "square"
1177
+ };
1178
+ }
1179
+ function useInputFileFieldState(props) {
1180
+ const [field, meta, helpers] = useField(props);
1181
+ return {
1182
+ field,
1183
+ helpers,
1184
+ meta
1185
+ };
1186
+ }
1187
+ function isNativeInputFileValue(file) {
1188
+ return Boolean(file && typeof file === "object");
1189
+ }
1190
+ function getInputFileName(file) {
1191
+ if (!isNativeInputFileValue(file)) {
1192
+ return "";
1193
+ }
1194
+ if ("name" in file && file.name) {
1195
+ return file.name;
1196
+ }
1197
+ if ("fileName" in file && file.fileName) {
1198
+ return file.fileName;
1199
+ }
1200
+ if ("uri" in file && file.uri) {
1201
+ return file.uri.split("/").filter(Boolean).pop() ?? "";
1202
+ }
1203
+ return "";
1204
+ }
1205
+ function InputFile(inputFileProps) {
1206
+ const {
1207
+ disabled = false,
1208
+ inputClassName,
1209
+ label,
1210
+ labelClassName,
1211
+ onFileSelect,
1212
+ placeholder,
1213
+ responseClassName,
1214
+ shape,
1215
+ className
1216
+ } = inputFileProps;
1217
+ const { field, meta, helpers } = useInputFileFieldState(inputFileProps);
1218
+ const [focused, setFocused] = useState(false);
1219
+ const { label: resolvedLabel, shape: resolvedShape } = useResolvedInputFileConfig({
1220
+ label,
1221
+ placeholder,
1222
+ shape
1223
+ });
1224
+ const hasError = Boolean(meta.touched && meta.error);
1225
+ const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
1226
+ const fileName = getInputFileName(field.value);
1227
+ const floating = focused || Boolean(fileName);
1228
+ const handlePress = async () => {
1229
+ if (disabled || !onFileSelect) {
1230
+ return;
1231
+ }
1232
+ setFocused(true);
1233
+ const selectedFile = await onFileSelect();
1234
+ if (selectedFile !== void 0) {
1235
+ await helpers.setValue(selectedFile);
1236
+ await helpers.setTouched(true);
1237
+ }
1238
+ };
1239
+ return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
1240
+ /* @__PURE__ */ jsx$1(
1241
+ Pressable,
1242
+ {
1243
+ accessibilityLabel: resolvedLabel,
1244
+ accessibilityRole: "button",
1245
+ disabled,
1246
+ onBlur: () => setFocused(false),
1247
+ onFocus: () => setFocused(true),
1248
+ onPress: () => void handlePress(),
1249
+ className: cn(
1250
+ inputFrameClassName,
1251
+ "justify-center",
1252
+ hasError ? inputFrameErrorClassName : focused ? inputFrameActiveClassName : inputFrameIdleClassName,
1253
+ inputShapes[resolvedShape],
1254
+ disabled && inputFrameDisabledClassName,
1255
+ className
1256
+ ),
1257
+ children: /* @__PURE__ */ jsx$1(
1258
+ Text,
1259
+ {
1260
+ numberOfLines: 1,
1261
+ className: cn(
1262
+ inputControlClassName,
1263
+ "pt-5 pb-2",
1264
+ !fileName && "text-gray-500 dark:text-gray-300",
1265
+ inputClassName
1266
+ ),
1267
+ style: { includeFontPadding: false },
1268
+ children: fileName
1269
+ }
1270
+ )
1271
+ }
1272
+ ),
1273
+ /* @__PURE__ */ jsx$1(
1274
+ InputLabel,
1275
+ {
1276
+ disabled,
1277
+ errored: hasError,
1278
+ floating,
1279
+ text: resolvedLabel,
1280
+ className: labelClassName
1281
+ }
1282
+ ),
1283
+ /* @__PURE__ */ jsx$1(
1284
+ InputResponse,
1285
+ {
1286
+ message: errorText,
1287
+ name: field.name,
1288
+ visibility: Boolean(errorText),
1289
+ variant: "danger",
1290
+ className: responseClassName
1291
+ }
1292
+ )
1293
+ ] });
1294
+ }
1295
+ function useResolvedSelectConfig({
1296
+ label,
1297
+ placeholder,
1298
+ shape
1299
+ }) {
1300
+ const eui = useEUIConfig();
1301
+ return {
1302
+ label: label ?? placeholder,
1303
+ shape: shape ?? eui?.config?.global?.shape ?? "square"
1304
+ };
1305
+ }
1306
+ function useSelectFieldState(props) {
1307
+ const [field, meta, helpers] = useField(props);
1308
+ return {
1309
+ field,
1310
+ helpers,
1311
+ meta
1312
+ };
1313
+ }
1314
+ function getSelectOptionLabel(options, value) {
1315
+ const option = options.find((item) => item.value === value);
1316
+ if (!option) {
1317
+ return "";
1318
+ }
1319
+ return String(option.label ?? "");
1320
+ }
1321
+ function Select(selectProps) {
1322
+ const {
1323
+ disabled = false,
1324
+ inputClassName,
1325
+ label,
1326
+ labelClassName,
1327
+ options,
1328
+ placeholder,
1329
+ responseClassName,
1330
+ shape,
1331
+ styles,
1332
+ className,
1333
+ onBlur,
1334
+ onFocus,
1335
+ ..._props
1336
+ } = selectProps;
1337
+ const { field, helpers, meta } = useSelectFieldState(selectProps);
1338
+ const [focused, setFocused] = useState(false);
1339
+ const [open, setOpen] = useState(false);
1340
+ const { label: resolvedLabel, shape: resolvedShape } = useResolvedSelectConfig({
1341
+ label,
1342
+ placeholder,
1343
+ shape
1344
+ });
1345
+ const hasError = Boolean(meta.touched && meta.error);
1346
+ const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
1347
+ const selectedLabel = getSelectOptionLabel(options, field.value ?? "");
1348
+ const closeOptions = () => {
1349
+ setOpen(false);
1350
+ setFocused(false);
1351
+ void helpers.setTouched(true);
1352
+ };
1353
+ const handleOpen = () => {
1354
+ if (disabled) {
1355
+ return;
1356
+ }
1357
+ setFocused(true);
1358
+ setOpen(true);
1359
+ };
1360
+ const handleSelect = (option) => {
1361
+ if (option.disabled) {
1362
+ return;
1363
+ }
1364
+ void helpers.setValue(option.value);
1365
+ void helpers.setTouched(true);
1366
+ setOpen(false);
1367
+ setFocused(false);
1368
+ };
1369
+ const handleBlur = (event) => {
1370
+ setFocused(false);
1371
+ void helpers.setTouched(true);
1372
+ onBlur?.(event);
1373
+ };
1374
+ const handleFocus = (event) => {
1375
+ setFocused(true);
1376
+ onFocus?.(event);
1377
+ };
1378
+ return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
1379
+ /* @__PURE__ */ jsx$1(
1380
+ Pressable,
1381
+ {
1382
+ accessibilityLabel: resolvedLabel,
1383
+ accessibilityRole: "button",
1384
+ accessibilityState: { disabled, expanded: open },
1385
+ disabled,
1386
+ onBlur: handleBlur,
1387
+ onFocus: handleFocus,
1388
+ onPress: handleOpen,
1389
+ className: cn(
1390
+ inputFrameClassName,
1391
+ "justify-center",
1392
+ hasError ? inputFrameErrorClassName : focused || open ? inputFrameActiveClassName : inputFrameIdleClassName,
1393
+ inputShapes[resolvedShape],
1394
+ disabled && inputFrameDisabledClassName,
1395
+ className,
1396
+ styles
1397
+ ),
1398
+ children: /* @__PURE__ */ jsx$1(
1399
+ Text,
1400
+ {
1401
+ numberOfLines: 1,
1402
+ className: cn(
1403
+ inputControlClassName,
1404
+ "pt-5 pb-2",
1405
+ !selectedLabel && "text-gray-500 dark:text-gray-300",
1406
+ inputClassName
1407
+ ),
1408
+ style: { includeFontPadding: false },
1409
+ children: selectedLabel
1410
+ }
1411
+ )
1412
+ }
1413
+ ),
1414
+ /* @__PURE__ */ jsx$1(
1415
+ InputLabel,
1416
+ {
1417
+ disabled,
1418
+ errored: hasError,
1419
+ floating: true,
1420
+ text: resolvedLabel,
1421
+ className: labelClassName
1422
+ }
1423
+ ),
1424
+ /* @__PURE__ */ jsx$1(
1425
+ InputResponse,
1426
+ {
1427
+ message: errorText,
1428
+ name: field.name,
1429
+ visibility: Boolean(errorText),
1430
+ variant: "danger",
1431
+ className: responseClassName
1432
+ }
1433
+ ),
1434
+ /* @__PURE__ */ jsx$1(
1435
+ Modal,
1436
+ {
1437
+ animationType: "fade",
1438
+ onRequestClose: closeOptions,
1439
+ transparent: true,
1440
+ visible: open,
1441
+ children: /* @__PURE__ */ jsxs(View, { className: "flex-1 justify-end bg-black/40 px-4 py-6", children: [
1442
+ /* @__PURE__ */ jsx$1(
1443
+ Pressable,
1444
+ {
1445
+ accessibilityLabel: "Close select options",
1446
+ accessibilityRole: "button",
1447
+ className: "absolute inset-0",
1448
+ onPress: closeOptions
1449
+ }
1450
+ ),
1451
+ /* @__PURE__ */ jsx$1(View, { className: "max-h-[70%] overflow-hidden rounded-lg bg-white shadow-xl dark:bg-eui-dark-500", children: /* @__PURE__ */ jsx$1(ScrollView, { children: options.map((option) => {
1452
+ const selected = option.value === field.value;
1453
+ return /* @__PURE__ */ jsx$1(
1454
+ Pressable,
1455
+ {
1456
+ accessibilityRole: "button",
1457
+ accessibilityState: {
1458
+ disabled: option.disabled,
1459
+ selected
1460
+ },
1461
+ disabled: option.disabled,
1462
+ onPress: () => handleSelect(option),
1463
+ className: cn(
1464
+ "min-h-12 justify-center border-b border-gray-200 px-4 py-3 dark:border-eui-dark-300",
1465
+ selected && "bg-eui-secondary-500/10",
1466
+ option.disabled && "opacity-50"
1467
+ ),
1468
+ children: /* @__PURE__ */ jsx$1(Text, { className: "text-base font-medium text-gray-950 dark:text-gray-50", children: String(option.label) })
1469
+ },
1470
+ option.value
1471
+ );
1472
+ }) }) })
1473
+ ] })
1474
+ }
1475
+ )
1476
+ ] });
1477
+ }
1478
+ function useResolvedTagsConfig({
1479
+ label,
1480
+ limit = 10,
1481
+ placeholder,
1482
+ shape
1483
+ }) {
1484
+ const eui = useEUIConfig();
1485
+ return {
1486
+ label: label ?? placeholder,
1487
+ limit,
1488
+ shape: shape ?? eui?.config?.global?.shape ?? "square"
1489
+ };
1490
+ }
1491
+ function useTagsFieldState(props) {
1492
+ const [field, meta, helpers] = useField(props);
1493
+ return {
1494
+ field,
1495
+ helpers,
1496
+ meta
1497
+ };
1498
+ }
1499
+ function getTagsValue(value) {
1500
+ if (!Array.isArray(value)) {
1501
+ return [];
1502
+ }
1503
+ return value.filter((tag) => typeof tag === "string");
1504
+ }
1505
+ function addTagToList(tags, value, limit) {
1506
+ const trimmed = value.trim();
1507
+ if (!trimmed || tags.includes(trimmed) || tags.length >= limit) {
1508
+ return tags;
1509
+ }
1510
+ return [...tags, trimmed];
1511
+ }
1512
+ function removeTagFromList(tags, index) {
1513
+ return tags.filter((_, tagIndex) => tagIndex !== index);
1514
+ }
1515
+ var nativeTagsInputControlStyle = {
1516
+ ...nativeInputControlStyle,
1517
+ minHeight: 28,
1518
+ paddingBottom: 0,
1519
+ paddingTop: 0
1520
+ };
1521
+ function Tags(tagsProps) {
1522
+ const {
1523
+ disabled = false,
1524
+ inputClassName,
1525
+ label,
1526
+ labelClassName,
1527
+ limit,
1528
+ placeholder,
1529
+ responseClassName,
1530
+ shape,
1531
+ styles,
1532
+ tagClassName,
1533
+ removeButtonClassName,
1534
+ counterClassName,
1535
+ className,
1536
+ onBlur,
1537
+ onFocus,
1538
+ ..._props
1539
+ } = tagsProps;
1540
+ const { field, helpers, meta } = useTagsFieldState(tagsProps);
1541
+ const [input, setInput] = useState("");
1542
+ const [focused, setFocused] = useState(false);
1543
+ const {
1544
+ label: resolvedLabel,
1545
+ limit: resolvedLimit,
1546
+ shape: resolvedShape
1547
+ } = useResolvedTagsConfig({
1548
+ label,
1549
+ limit,
1550
+ placeholder,
1551
+ shape
1552
+ });
1553
+ const tags = getTagsValue(field.value);
1554
+ const hasError = Boolean(meta.touched && meta.error);
1555
+ const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
1556
+ const floating = focused || input.length > 0 || tags.length > 0;
1557
+ const handleAddTag = (value = input) => {
1558
+ if (disabled) {
1559
+ return;
1560
+ }
1561
+ const nextTags = addTagToList(tags, value, resolvedLimit);
1562
+ if (nextTags !== tags) {
1563
+ void helpers.setValue(nextTags);
1564
+ }
1565
+ if (value.trim()) {
1566
+ void helpers.setTouched(true);
1567
+ }
1568
+ setInput("");
1569
+ };
1570
+ const handleChangeText = (value) => {
1571
+ if (value.endsWith(",")) {
1572
+ handleAddTag(value.slice(0, -1));
1573
+ return;
1574
+ }
1575
+ setInput(value);
1576
+ };
1577
+ const handleKeyPress = (event) => {
1578
+ if (event.nativeEvent?.key === "Backspace" && input === "" && tags.length) {
1579
+ void helpers.setValue(tags.slice(0, -1));
1580
+ void helpers.setTouched(true);
1581
+ }
1582
+ };
1583
+ const handleRemoveTag = (index) => {
1584
+ if (disabled) {
1585
+ return;
1586
+ }
1587
+ void helpers.setValue(removeTagFromList(tags, index));
1588
+ void helpers.setTouched(true);
1589
+ };
1590
+ const handleBlur = (event) => {
1591
+ setFocused(false);
1592
+ void helpers.setTouched(true);
1593
+ onBlur?.(event);
1594
+ };
1595
+ const handleFocus = (event) => {
1596
+ setFocused(true);
1597
+ onFocus?.(event);
1598
+ };
1599
+ return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
1600
+ /* @__PURE__ */ jsxs(
1601
+ View,
1602
+ {
1603
+ className: cn(
1604
+ inputFrameClassName,
1605
+ "h-auto min-h-14 flex-row flex-wrap items-center gap-2 overflow-visible px-3 pt-6 pb-7",
1606
+ hasError ? inputFrameErrorClassName : focused ? inputFrameActiveClassName : inputFrameIdleClassName,
1607
+ inputShapes[resolvedShape],
1608
+ disabled && inputFrameDisabledClassName,
1609
+ className,
1610
+ styles
1611
+ ),
1612
+ children: [
1613
+ tags.map((tag, index) => /* @__PURE__ */ jsxs(
1614
+ View,
1615
+ {
1616
+ className: cn(
1617
+ "max-w-full flex-row items-center gap-1 rounded bg-eui-light-300 px-2 py-1 dark:bg-eui-dark-400",
1618
+ tagClassName
1619
+ ),
1620
+ children: [
1621
+ /* @__PURE__ */ jsx$1(
1622
+ Text,
1623
+ {
1624
+ className: "shrink text-sm font-medium text-eui-dark-700 dark:text-eui-light-300",
1625
+ numberOfLines: 1,
1626
+ style: { includeFontPadding: false },
1627
+ children: tag
1628
+ }
1629
+ ),
1630
+ /* @__PURE__ */ jsx$1(
1631
+ Pressable,
1632
+ {
1633
+ accessibilityLabel: `Remove ${tag}`,
1634
+ accessibilityRole: "button",
1635
+ className: cn(
1636
+ "h-5 w-5 items-center justify-center",
1637
+ disabled && "opacity-50",
1638
+ removeButtonClassName
1639
+ ),
1640
+ disabled,
1641
+ onPress: () => handleRemoveTag(index),
1642
+ children: /* @__PURE__ */ jsx$1(
1643
+ Text,
1644
+ {
1645
+ className: "text-xs font-bold text-eui-danger-500",
1646
+ style: { includeFontPadding: false },
1647
+ children: "x"
1648
+ }
1649
+ )
1650
+ }
1651
+ )
1652
+ ]
1653
+ },
1654
+ `${tag}-${index}`
1655
+ )),
1656
+ tags.length < resolvedLimit ? /* @__PURE__ */ jsx$1(
1657
+ TextInput,
1658
+ {
1659
+ accessibilityLabel: resolvedLabel,
1660
+ className: cn(
1661
+ inputControlClassName,
1662
+ "h-7 w-auto min-w-[120px] flex-1 p-0",
1663
+ inputClassName
1664
+ ),
1665
+ editable: !disabled,
1666
+ onBlur: handleBlur,
1667
+ onChangeText: handleChangeText,
1668
+ onFocus: handleFocus,
1669
+ onKeyPress: handleKeyPress,
1670
+ onSubmitEditing: () => handleAddTag(),
1671
+ placeholder: "",
1672
+ returnKeyType: "done",
1673
+ style: nativeTagsInputControlStyle,
1674
+ underlineColorAndroid: "transparent",
1675
+ value: input
1676
+ }
1677
+ ) : null,
1678
+ /* @__PURE__ */ jsxs(
1679
+ Text,
1680
+ {
1681
+ className: cn(
1682
+ "absolute bottom-3 right-3 text-xs font-semibold text-eui-dark-50",
1683
+ counterClassName
1684
+ ),
1685
+ style: { includeFontPadding: false },
1686
+ children: [
1687
+ tags.length,
1688
+ "/",
1689
+ resolvedLimit
1690
+ ]
1691
+ }
1692
+ )
1693
+ ]
1694
+ }
1695
+ ),
1696
+ /* @__PURE__ */ jsx$1(
1697
+ InputLabel,
1698
+ {
1699
+ disabled,
1700
+ errored: hasError,
1701
+ floating,
1702
+ text: resolvedLabel,
1703
+ className: labelClassName
1704
+ }
1705
+ ),
1706
+ /* @__PURE__ */ jsx$1(
1707
+ InputResponse,
1708
+ {
1709
+ message: errorText,
1710
+ name: field.name,
1711
+ visibility: Boolean(errorText),
1712
+ variant: "danger",
1713
+ className: responseClassName
1714
+ }
1715
+ )
1716
+ ] });
1717
+ }
1718
+ function useResolvedTextAreaConfig({
1719
+ label,
1720
+ limit = 1e3,
1721
+ placeholder,
1722
+ shape
1723
+ }) {
1724
+ const eui = useEUIConfig();
1725
+ return {
1726
+ label: label ?? placeholder,
1727
+ limit,
1728
+ shape: shape ?? eui?.config?.global?.shape ?? "square"
1729
+ };
1730
+ }
1731
+ function useTextAreaFieldState(props) {
1732
+ const [field, meta, helpers] = useField(props);
1733
+ return {
1734
+ field,
1735
+ helpers,
1736
+ meta
1737
+ };
1738
+ }
1739
+ function getTextAreaCharacterCount(value) {
1740
+ return String(value ?? "").length;
1741
+ }
1742
+ var nativeTextAreaControlStyle = {
1743
+ ...nativeInputControlStyle,
1744
+ minHeight: 128,
1745
+ textAlignVertical: "top"
1746
+ };
1747
+ function TextArea(textAreaProps) {
1748
+ const {
1749
+ disabled = false,
1750
+ inputClassName,
1751
+ label,
1752
+ labelClassName,
1753
+ limit,
1754
+ placeholder,
1755
+ responseClassName,
1756
+ shape,
1757
+ styles,
1758
+ className,
1759
+ onBlur,
1760
+ onFocus,
1761
+ ..._props
1762
+ } = textAreaProps;
1763
+ const { field, helpers, meta } = useTextAreaFieldState(textAreaProps);
1764
+ const [focused, setFocused] = useState(false);
1765
+ const {
1766
+ label: resolvedLabel,
1767
+ limit: resolvedLimit,
1768
+ shape: resolvedShape
1769
+ } = useResolvedTextAreaConfig({
1770
+ label,
1771
+ limit,
1772
+ placeholder,
1773
+ shape
1774
+ });
1775
+ const hasError = Boolean(meta.touched && meta.error);
1776
+ const errorText = hasError && typeof meta.error === "string" ? meta.error : null;
1777
+ const characterCount = getTextAreaCharacterCount(field.value);
1778
+ const floating = focused || characterCount > 0;
1779
+ const handleBlur = (event) => {
1780
+ setFocused(false);
1781
+ void helpers.setTouched(true);
1782
+ onBlur?.(event);
1783
+ };
1784
+ const handleFocus = (event) => {
1785
+ setFocused(true);
1786
+ onFocus?.(event);
1787
+ };
1788
+ return /* @__PURE__ */ jsxs(View, { className: inputRootClassName, children: [
1789
+ /* @__PURE__ */ jsxs(
1790
+ View,
1791
+ {
1792
+ className: cn(
1793
+ inputFrameClassName,
1794
+ "h-auto min-h-32 px-3",
1795
+ hasError ? inputFrameErrorClassName : focused ? inputFrameActiveClassName : inputFrameIdleClassName,
1796
+ inputShapes[resolvedShape],
1797
+ disabled && inputFrameDisabledClassName,
1798
+ className,
1799
+ styles
1800
+ ),
1801
+ children: [
1802
+ /* @__PURE__ */ jsx$1(
1803
+ TextInput,
1804
+ {
1805
+ accessibilityLabel: resolvedLabel,
1806
+ className: cn(inputControlClassName, "min-h-32 pb-8", inputClassName),
1807
+ editable: !disabled,
1808
+ maxLength: resolvedLimit,
1809
+ multiline: true,
1810
+ onBlur: handleBlur,
1811
+ onChangeText: (value) => helpers.setValue(value),
1812
+ onFocus: handleFocus,
1813
+ placeholder: "",
1814
+ style: nativeTextAreaControlStyle,
1815
+ underlineColorAndroid: "transparent",
1816
+ value: field.value ?? ""
1817
+ }
1818
+ ),
1819
+ /* @__PURE__ */ jsxs(Text, { className: "absolute bottom-3 right-3 text-xs font-semibold text-eui-dark-50", children: [
1820
+ characterCount,
1821
+ "/",
1822
+ resolvedLimit
1823
+ ] })
1824
+ ]
1825
+ }
1826
+ ),
1827
+ /* @__PURE__ */ jsx$1(
1828
+ InputLabel,
1829
+ {
1830
+ disabled,
1831
+ errored: hasError,
1832
+ floating,
1833
+ text: resolvedLabel,
1834
+ className: labelClassName
1835
+ }
1836
+ ),
1045
1837
  /* @__PURE__ */ jsx$1(
1046
1838
  InputResponse,
1047
1839
  {
@@ -1055,6 +1847,6 @@ function Input(inputProps) {
1055
1847
  ] });
1056
1848
  }
1057
1849
 
1058
- export { Button_native_default as Button, Checkbox, EUIProvider, Form, FormResponse, Input, InputLabel, InputResponse, resolveWithGlobal, useEUIConfig };
1850
+ export { Button_native_default as Button, Checkbox, DateSelector, EUIProvider, Form, FormResponse, Input, InputFile, InputLabel, InputResponse, Select, Tags, TextArea, resolveWithGlobal, useEUIConfig };
1059
1851
  //# sourceMappingURL=index.native.mjs.map
1060
1852
  //# sourceMappingURL=index.native.mjs.map