FormInput.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* eslint-disable react/jsx-props-no-spreading */
  2. /* eslint-disable no-shadow */
  3. /* eslint-disable no-underscore-dangle */
  4. /* eslint-disable no-restricted-syntax */
  5. import * as WebBrowser from "expo-web-browser";
  6. import * as React from "react";
  7. import { View, StyleSheet, TouchableWithoutFeedback } from "react-native";
  8. import {
  9. Layout,
  10. Input,
  11. Button,
  12. Icon,
  13. Text,
  14. SelectItem,
  15. } from "@ui-kitten/components";
  16. import { Cascader, BottomModal } from "beeshell";
  17. import { useCreation } from "@umijs/hooks";
  18. import { useModel } from "flooks";
  19. import moment from "moment";
  20. import OpenTime from "./OpenTime";
  21. import Datepicker from "./Datepicker";
  22. import UpLoadImage from "./UpLoadImage";
  23. import Actionsheet from "./Actionsheet";
  24. const styles = StyleSheet.create({
  25. inputContainer: {
  26. flexDirection: "row",
  27. alignItems: "center",
  28. paddingVertical: 10,
  29. paddingHorizontal: 4,
  30. },
  31. input: {
  32. flex: 1,
  33. },
  34. label: {
  35. width: 80,
  36. marginRight: 19,
  37. flexShrink: 0,
  38. },
  39. labelleft: {
  40. width: 73,
  41. flexShrink: 0,
  42. },
  43. right: {
  44. flexDirection: "row",
  45. },
  46. code: {
  47. paddingHorizontal: 5,
  48. marginLeft: 5,
  49. },
  50. selectContent: {
  51. backgroundColor: "#F0F0F0",
  52. },
  53. titleStyle: {
  54. fontSize: 15,
  55. },
  56. leftLabelTextStyle: {
  57. fontSize: 13,
  58. },
  59. rightLabelTextStyle: {
  60. fontSize: 13,
  61. },
  62. sub: {
  63. color: "#787878",
  64. position: "absolute",
  65. left: 90,
  66. zIndex: 2,
  67. },
  68. upload: {
  69. marginTop: 20,
  70. width: 67,
  71. height: 67,
  72. },
  73. });
  74. function* flattenSelect(array, key) {
  75. for (const item of array) {
  76. const _array = key ? item[key] : item;
  77. if (Array.isArray(_array) && _array.length > 0) {
  78. yield* flattenSelect(_array, key);
  79. } else {
  80. yield item;
  81. }
  82. }
  83. }
  84. function getInputProps(
  85. type,
  86. value,
  87. placeholder,
  88. onChange,
  89. secureTextEntry,
  90. renderIcon
  91. ) {
  92. let _props = {
  93. defaultValue: value || "",
  94. placeholder,
  95. };
  96. if (type === "phone") {
  97. _props = {
  98. ..._props,
  99. dataDetectorTypes: "phoneNumber",
  100. maxLength: 11,
  101. keyboardType: "phone-pad",
  102. };
  103. } else if (type === "password") {
  104. _props = {
  105. ..._props,
  106. accessoryRight: ImageProps => renderIcon(ImageProps),
  107. secureTextEntry,
  108. };
  109. } else if (type === "code") {
  110. _props = {
  111. ..._props,
  112. maxLength: 6,
  113. keyboardType: "numeric",
  114. };
  115. } else if (type === "amount" || type === "money") {
  116. _props = {
  117. ..._props,
  118. keyboardType: "numeric",
  119. };
  120. }
  121. if (onChange) {
  122. _props = {
  123. ..._props,
  124. onChangeText: nextValue => onChange(nextValue),
  125. };
  126. }
  127. return _props;
  128. }
  129. const ForwardIcon = props => <Icon {...props} name="arrow-ios-forward" />;
  130. const Label = ({ type, labelStyle, label, appearance }) => {
  131. return (
  132. <View
  133. style={[
  134. appearance === "inner" ? styles.labelleft : styles.label,
  135. type === "img" ? { alignSelf: "flex-start" } : {},
  136. labelStyle || {},
  137. ]}
  138. >
  139. <Text
  140. category="c1"
  141. style={{
  142. textAlign: appearance !== "inner" ? "right" : "left",
  143. }}
  144. >
  145. {label}
  146. </Text>
  147. </View>
  148. );
  149. };
  150. const Btn = ({ btnText }) => (
  151. <Button
  152. appearance="ghost"
  153. size="tiny"
  154. style={{ paddingVertical: 8, marginLeft: 5 }}
  155. >
  156. {btnText}
  157. </Button>
  158. );
  159. const FormInput = React.memo(props => {
  160. const {
  161. placeholder,
  162. appearance,
  163. type,
  164. selectList,
  165. value,
  166. style,
  167. sub,
  168. onChange,
  169. labelStyle,
  170. label,
  171. } = props;
  172. const [secureTextEntry, setSecureTextEntry] = React.useState(true);
  173. const { cancel, confirm } = useModel("wordsModel");
  174. const toggleSecureEntry = () => {
  175. setSecureTextEntry(!secureTextEntry);
  176. };
  177. // eslint-disable-next-line no-shadow
  178. const renderIcon = props => (
  179. <TouchableWithoutFeedback onPress={toggleSecureEntry}>
  180. <Icon {...props} name={secureTextEntry ? "eye-off" : "eye"} />
  181. </TouchableWithoutFeedback>
  182. );
  183. const inputProps = useCreation(() => {
  184. return getInputProps(
  185. type,
  186. value,
  187. placeholder,
  188. onChange,
  189. secureTextEntry,
  190. renderIcon
  191. );
  192. }, [type, value, placeholder, onChange, secureTextEntry, renderIcon]);
  193. const [bottomModalX, changeBottomModalx] = React.useState("");
  194. const [selectVal, setSelectVal] = React.useState("");
  195. const selectInfo = useCreation(() => {
  196. if (type === "select" && props.value && selectList) {
  197. const childrens = [...flattenSelect(selectList, "children")];
  198. return (
  199. childrens.find(item => {
  200. return item.id === props.value;
  201. }) || { name: " " }
  202. );
  203. }
  204. return { name: " " };
  205. }, [value, type, selectList]);
  206. const [open, ChangeOpen] = React.useState(false);
  207. function getMain(type, props, inputProps) {
  208. if (type === "select") {
  209. return (
  210. <>
  211. <SelectItem
  212. appearance="form"
  213. style={{ flex: 1 }}
  214. accessoryRight={ForwardIcon}
  215. title={selectInfo.name}
  216. onPress={() => {
  217. bottomModalX.open();
  218. }}
  219. />
  220. <BottomModal
  221. ref={c => {
  222. changeBottomModalx(c);
  223. }}
  224. title={props.selectTitle}
  225. titleStyle={styles.titleStyle}
  226. cancelable
  227. leftLabelText={cancel}
  228. leftLabelTextStyle={styles.leftLabelTextStyle}
  229. rightLabelText={confirm}
  230. rightLabelTextStyle={styles.rightLabelTextStyle}
  231. rightCallback={() => {
  232. props.onChange(selectVal);
  233. }}
  234. >
  235. <Cascader
  236. style={{
  237. width: "100%",
  238. height: 200,
  239. marginBottom: 50,
  240. minHeight: 200,
  241. }}
  242. data={selectList}
  243. fieldKeys={{
  244. labelKey: "name",
  245. idKey: "id",
  246. activeKey: "choose",
  247. }}
  248. onChange={value => {
  249. setSelectVal(value[0]);
  250. }}
  251. />
  252. </BottomModal>
  253. </>
  254. );
  255. }
  256. if (type === "openTime") {
  257. return (
  258. <OpenTime
  259. submit={(week, startTime, endTime) => {
  260. props.onChange(week, startTime, endTime);
  261. }}
  262. week={props.week}
  263. startTime={props.startTime}
  264. endTime={props.endTime}
  265. />
  266. );
  267. }
  268. if (type === "date") {
  269. return <Datepicker chooseDate={props.onChange} value={props.value} />;
  270. }
  271. if (type === "url") {
  272. return (
  273. <SelectItem
  274. appearance="form"
  275. style={{ flex: 1 }}
  276. accessoryRight={ForwardIcon}
  277. title={props.value || " "}
  278. onPress={props.changePath}
  279. />
  280. );
  281. }
  282. if (type === "actionSheet") {
  283. return (
  284. <>
  285. <Actionsheet
  286. list={props.list}
  287. value={props.value}
  288. onChange={props.onChange}
  289. />
  290. </>
  291. );
  292. }
  293. if (type === "img") {
  294. return (
  295. <UpLoadImage
  296. style={styles.upload}
  297. value={props.value}
  298. changeIcon={props.onChange}
  299. aspect={[1, 1]}
  300. />
  301. );
  302. }
  303. if (appearance === "inner" && type === "code") {
  304. return (
  305. <Input
  306. {...inputProps}
  307. accessoryLeft={() => (
  308. <Label
  309. type={type}
  310. labelStyle={labelStyle}
  311. label={label}
  312. appearance={appearance}
  313. />
  314. )}
  315. accessoryRight={() => <Btn btnText={props.btnText} />}
  316. size="small"
  317. style={styles.input}
  318. appearance="innerCode"
  319. />
  320. );
  321. }
  322. if (appearance === "inner") {
  323. return (
  324. <Input
  325. {...inputProps}
  326. accessoryLeft={() => (
  327. <Label
  328. type={type}
  329. labelStyle={labelStyle}
  330. label={label}
  331. appearance={appearance}
  332. />
  333. )}
  334. size="small"
  335. style={styles.input}
  336. appearance="inner"
  337. />
  338. );
  339. }
  340. if (type === "label") {
  341. return null;
  342. }
  343. return <Input {...inputProps} size="small" style={styles.input} />;
  344. }
  345. return (
  346. <Layout
  347. level="1"
  348. style={[
  349. styles.inputContainer,
  350. { ...style },
  351. type === "img" ? { flexDirection: "column" } : {},
  352. { paddingVertical: appearance === "inner" ? 0 : 10 },
  353. ]}
  354. >
  355. {appearance !== "inner" && (
  356. <Label
  357. type={type}
  358. labelStyle={labelStyle}
  359. label={label}
  360. appearance={appearance}
  361. />
  362. )}
  363. {(!value || value === " ") && (
  364. <Text category="c1" style={styles.sub}>
  365. {sub}
  366. </Text>
  367. )}
  368. {getMain(type, props, inputProps)}
  369. {appearance !== "inner" && type === "code" && Btn(props)}
  370. </Layout>
  371. );
  372. });
  373. export default FormInput;