MultiNumPassInput.jsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import {useEffect, useRef, useState} from "react";
  2. import styled from 'styled-components/macro';
  3. import {toast} from 'react-toastify';
  4. const StyledInput= styled.input`
  5. position: absolute;
  6. font-size:1.2rem !important;
  7. font-weight:700 !important;
  8. text-align: center;
  9. padding: .5rem !important;
  10. `;
  11. const StyledInputControl=styled.button`
  12. padding: 0rem !important;
  13. justify-content: center !important;
  14. height:3.5rem !important;
  15. `
  16. const StyledPass=styled.div`
  17. width: 0.65rem;
  18. height: 0.65rem;
  19. background: var(--header);
  20. border-radius: 50%;
  21. `
  22. const MultiNumPassInput=({innerRef, ...props})=>{
  23. const [values,setValues]=useState([]);
  24. const [focusIndex,setFocusIndex]=useState(-1);
  25. const {length,value,focus,onChange,onFinish,className}=props;
  26. const col=length<1?1:length;
  27. const inputRef = useRef(null);
  28. const btnRefs = useRef([]);
  29. useEffect(()=>{
  30. initValues();
  31. return ()=>{
  32. }
  33. },[]);
  34. useEffect(()=>{
  35. if (inputRef.current)inputRef.current.focus();
  36. },[focusIndex]);
  37. useEffect(()=>{
  38. if (focus){
  39. if (values.length>0){
  40. checkFocus(values);
  41. }
  42. }
  43. },[focus])
  44. const initValues=()=>{
  45. let values=[];
  46. let initValues=[];
  47. if (value!=null){
  48. initValues=value.split('');
  49. }
  50. for (let i = 0; i <length ; i++) {
  51. values[i]=initValues[i]?initValues[i]:"";
  52. }
  53. setValues(values);
  54. if (focus)checkFocus(values);
  55. }
  56. // const checkFocus=(index)=>{
  57. // // console.log(inputRefs);
  58. // for (let i = 0; i <values.length; i++) {
  59. // let value=values[i];
  60. // if (i===index)continue;
  61. // if (value===""){
  62. // let input=inputRefs[i];
  63. // if (input)input.focus();
  64. // break;
  65. // }
  66. // }
  67. // }
  68. const checkFocus=(valueArr)=>{
  69. let fIndex=-1;
  70. for (let i = 0; i <valueArr.length; i++) {
  71. let value=valueArr[i];
  72. if (value===""){
  73. fIndex=i;
  74. break;
  75. }
  76. }
  77. setFocusIndex(fIndex);
  78. // toast.success(fIndex);
  79. if (fIndex===-1){
  80. if (onFinish)onFinish(valueArr);
  81. }
  82. }
  83. const handleChange=(index,value)=>{
  84. let valueArr=values.slice(0);
  85. valueArr[index]=value;
  86. if (value!==""){
  87. checkFocus(valueArr);
  88. }
  89. else
  90. {
  91. if (index==0){
  92. valueArr=Array.from({ length: length }, (_, index) => "");
  93. }
  94. }
  95. setValues(valueArr);
  96. if (onChange)onChange(index,value);
  97. }
  98. const renderContent=()=>{
  99. return (
  100. <>
  101. {
  102. values.map((value,index)=>{
  103. return (
  104. <StyledInputControl
  105. ref={(ref) => (btnRefs.current[index] = ref)}
  106. onClick={()=>{
  107. setFocusIndex(index);
  108. }}
  109. type={"button"} key={index} className={`input-control ${value===""?className:''}`}>
  110. {
  111. !(focusIndex===index)?(<></>):(
  112. <StyledInput
  113. ref={inputRef}
  114. // autoFocus={true}
  115. onChange={(e)=>{
  116. let text=e.target.value;
  117. handleChange(index,text)
  118. }}
  119. onFocus={()=>{
  120. handleChange(index,"");
  121. }}
  122. onKeyDown={(e)=>{
  123. if (e.keyCode === 8 || e.key === "Backspace") {
  124. if (focusIndex>0){
  125. setFocusIndex(focusIndex-1);
  126. }
  127. }
  128. }}
  129. value={""}
  130. type={"number"}
  131. pattern="[0-9]*"
  132. />
  133. )
  134. }
  135. {
  136. value==null||value===""?(<></>):(<StyledPass/>)
  137. }
  138. </StyledInputControl>
  139. )
  140. })
  141. }
  142. </>
  143. )
  144. }
  145. return (
  146. <div className={`w-100 d-grid g-16 row-1 ${'col-'+col}`} ref={innerRef}>
  147. {renderContent()}
  148. </div>
  149. )
  150. }
  151. export default MultiNumPassInput;