@akinon/pz-otp 2.0.0-beta.8 → 2.0.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/CHANGELOG.md +128 -15
- package/package.json +10 -10
- package/readme.md +116 -0
- package/src/views/Otp.tsx +51 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,39 +1,152 @@
|
|
|
1
1
|
# @akinon/pz-otp
|
|
2
2
|
|
|
3
|
-
## 2.0.0
|
|
3
|
+
## 2.0.0
|
|
4
4
|
|
|
5
|
-
## 2.0.0-beta.
|
|
5
|
+
## 2.0.0-beta.27
|
|
6
6
|
|
|
7
|
-
## 2.0.0-beta.
|
|
7
|
+
## 2.0.0-beta.26
|
|
8
|
+
|
|
9
|
+
## 2.0.0-beta.25
|
|
10
|
+
|
|
11
|
+
## 2.0.0-beta.24
|
|
12
|
+
|
|
13
|
+
## 2.0.0-beta.23
|
|
14
|
+
|
|
15
|
+
## 2.0.0-beta.22
|
|
16
|
+
|
|
17
|
+
## 2.0.0-beta.21
|
|
18
|
+
|
|
19
|
+
## 2.0.0-beta.20
|
|
20
|
+
|
|
21
|
+
## 1.126.0
|
|
22
|
+
|
|
23
|
+
## 1.125.2
|
|
24
|
+
|
|
25
|
+
## 1.125.1
|
|
26
|
+
|
|
27
|
+
## 1.125.0
|
|
28
|
+
|
|
29
|
+
## 1.124.0
|
|
30
|
+
|
|
31
|
+
## 1.123.0
|
|
32
|
+
|
|
33
|
+
## 1.122.0
|
|
34
|
+
|
|
35
|
+
## 1.121.0
|
|
36
|
+
|
|
37
|
+
## 1.120.0
|
|
38
|
+
|
|
39
|
+
### Minor Changes
|
|
40
|
+
|
|
41
|
+
- 6ad72e8d: ZERO-4032: Add loading state management for payment submissions across multiple components and add safe guarding
|
|
42
|
+
|
|
43
|
+
## 1.119.0
|
|
44
|
+
|
|
45
|
+
## 1.118.0
|
|
46
|
+
|
|
47
|
+
## 1.117.0
|
|
48
|
+
|
|
49
|
+
## 1.116.0
|
|
50
|
+
|
|
51
|
+
## 1.115.0
|
|
52
|
+
|
|
53
|
+
## 1.114.0
|
|
54
|
+
|
|
55
|
+
## 1.113.0
|
|
56
|
+
|
|
57
|
+
## 1.112.0
|
|
58
|
+
|
|
59
|
+
## 1.111.0
|
|
60
|
+
|
|
61
|
+
## 1.110.0
|
|
62
|
+
|
|
63
|
+
## 1.109.0
|
|
64
|
+
|
|
65
|
+
## 1.108.0
|
|
66
|
+
|
|
67
|
+
## 1.107.0
|
|
68
|
+
|
|
69
|
+
## 1.106.0
|
|
70
|
+
|
|
71
|
+
### Minor Changes
|
|
72
|
+
|
|
73
|
+
- ae010f0: ZERO-3410: Update readme
|
|
74
|
+
|
|
75
|
+
## 1.105.0
|
|
76
|
+
|
|
77
|
+
## 1.104.0
|
|
78
|
+
|
|
79
|
+
## 1.103.0
|
|
80
|
+
|
|
81
|
+
## 1.102.0
|
|
82
|
+
|
|
83
|
+
## 1.101.0
|
|
84
|
+
|
|
85
|
+
## 1.100.0
|
|
86
|
+
|
|
87
|
+
## 1.99.0
|
|
88
|
+
|
|
89
|
+
### Minor Changes
|
|
90
|
+
|
|
91
|
+
- d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
|
|
92
|
+
|
|
93
|
+
## 1.98.0
|
|
94
|
+
|
|
95
|
+
## 1.97.0
|
|
96
|
+
|
|
97
|
+
## 1.96.0
|
|
98
|
+
|
|
99
|
+
## 1.95.0
|
|
100
|
+
|
|
101
|
+
## 1.94.0
|
|
102
|
+
|
|
103
|
+
## 1.93.0
|
|
104
|
+
|
|
105
|
+
## 1.92.0
|
|
106
|
+
|
|
107
|
+
## 1.91.0
|
|
108
|
+
|
|
109
|
+
## 1.90.0
|
|
8
110
|
|
|
9
111
|
### Minor Changes
|
|
10
112
|
|
|
11
|
-
-
|
|
113
|
+
- 9c3a22a: ZERO-3382: Enhance OTP component with customizable UI rendering support
|
|
114
|
+
|
|
115
|
+
## 1.89.0
|
|
12
116
|
|
|
13
|
-
##
|
|
117
|
+
## 1.88.0
|
|
14
118
|
|
|
15
|
-
##
|
|
119
|
+
## 1.87.0
|
|
16
120
|
|
|
17
|
-
##
|
|
121
|
+
## 1.86.0
|
|
18
122
|
|
|
19
|
-
##
|
|
123
|
+
## 1.85.0
|
|
20
124
|
|
|
21
125
|
### Minor Changes
|
|
22
126
|
|
|
23
|
-
-
|
|
24
|
-
- 1eeb3d8: ZERO-3116: Add not found page
|
|
127
|
+
- a0a1bac: ZERO-3228 :edit OTP login flow to use Redux for popup visibility and clean up unused props
|
|
25
128
|
|
|
26
|
-
##
|
|
129
|
+
## 1.84.0
|
|
27
130
|
|
|
28
131
|
### Minor Changes
|
|
29
132
|
|
|
30
|
-
- ZERO-
|
|
133
|
+
- 624a4eb: ZERO-3276: Update installation instructions across multiple README files to standardize format and improve clarity
|
|
134
|
+
|
|
135
|
+
## 1.83.0
|
|
136
|
+
|
|
137
|
+
## 1.82.0
|
|
138
|
+
|
|
139
|
+
## 1.81.0
|
|
140
|
+
|
|
141
|
+
## 1.80.0
|
|
142
|
+
|
|
143
|
+
## 1.79.0
|
|
31
144
|
|
|
32
|
-
##
|
|
145
|
+
## 1.78.0
|
|
33
146
|
|
|
34
|
-
|
|
147
|
+
## 1.77.0
|
|
35
148
|
|
|
36
|
-
|
|
149
|
+
## 1.76.0
|
|
37
150
|
|
|
38
151
|
## 1.75.0
|
|
39
152
|
|
package/package.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-otp",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"module": "./src/index.ts",
|
|
7
7
|
"peerDependencies": {
|
|
8
|
-
"react": "^19.0.0",
|
|
9
|
-
"react-dom": "^19.0.0"
|
|
8
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
9
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@types/node": "^
|
|
13
|
-
"@types/react": "^
|
|
14
|
-
"@types/react-dom": "^
|
|
15
|
-
"prettier": "
|
|
12
|
+
"@types/node": "^18.7.8",
|
|
13
|
+
"@types/react": "^18.0.17",
|
|
14
|
+
"@types/react-dom": "^18.0.6",
|
|
15
|
+
"prettier": "3.0.3",
|
|
16
16
|
"prettier-plugin-tailwindcss": "0.5.6",
|
|
17
|
-
"react": "
|
|
18
|
-
"react-dom": "
|
|
17
|
+
"react": "19.2.5",
|
|
18
|
+
"react-dom": "19.2.5",
|
|
19
19
|
"react-hook-form": "7.31.3",
|
|
20
|
-
"typescript": "^
|
|
20
|
+
"typescript": "^4.7.4"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"react-otp-input": "^3.1.0",
|
package/readme.md
CHANGED
|
@@ -9,3 +9,119 @@ You can use the following command to install the extension with the latest plugi
|
|
|
9
9
|
npx @akinon/projectzero@latest --plugins
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
+
|
|
13
|
+
### Props
|
|
14
|
+
|
|
15
|
+
| Property | Type | Required | Description |
|
|
16
|
+
| --- | --- | --- | --- |
|
|
17
|
+
| `customUIRender` | `React.ReactNode` | `Optional` | function to fully customize the otp. Receives closeHandler, resendHandler, otp, setOtp, hasError, error, canResend, time, codeLength, setHasError and onSubmit props. |
|
|
18
|
+
| `submitAction` | `SubmitHandler<{ [key: string]: any }>` | `Required` | A submit handler function triggered when OTP form is submitted. |
|
|
19
|
+
| `data` | `{ [key: string]: any }` | `Required` | Data object containing required fields like phone number. OTP code will be appended here before submission |
|
|
20
|
+
|
|
21
|
+
### Default Usage
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
25
|
+
|
|
26
|
+
<PluginModule
|
|
27
|
+
component={Component.Otp}
|
|
28
|
+
props={{
|
|
29
|
+
data: getValues(),
|
|
30
|
+
submitAction: registerHandler
|
|
31
|
+
}}
|
|
32
|
+
/>;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Customizing OTP
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
39
|
+
|
|
40
|
+
<PluginModule
|
|
41
|
+
component={Component.Otp}
|
|
42
|
+
props={{
|
|
43
|
+
data: getValues(),
|
|
44
|
+
submitAction: registerHandler,
|
|
45
|
+
customUIRender: ({
|
|
46
|
+
closeHandler,
|
|
47
|
+
resendHandler,
|
|
48
|
+
onSubmit,
|
|
49
|
+
otp,
|
|
50
|
+
setOtp,
|
|
51
|
+
hasError,
|
|
52
|
+
error,
|
|
53
|
+
canResend,
|
|
54
|
+
time,
|
|
55
|
+
codeLength,
|
|
56
|
+
setHasError
|
|
57
|
+
}) => {
|
|
58
|
+
return (
|
|
59
|
+
<div className="fixed left-0 top-0 z-50 flex h-screen w-screen items-end md:items-center md:justify-center md:bg-black/10">
|
|
60
|
+
<div className="h-[calc(100vh-48px)] w-screen flex md:h-auto md:max-w-lg flex-col items-center rounded-sm bg-white p-8 shadow-xl">
|
|
61
|
+
<div className="w-full flex items-center justify-end">
|
|
62
|
+
<div className="cursor-pointer" onClick={closeHandler}>
|
|
63
|
+
<svg
|
|
64
|
+
width="14"
|
|
65
|
+
height="14"
|
|
66
|
+
viewBox="0 0 14 14"
|
|
67
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
68
|
+
>
|
|
69
|
+
<g fill="#000" fillRule="nonzero">
|
|
70
|
+
<path d="M.684 14A.684.684 0 0 1 .2 12.833L12.833.2a.684.684 0 1 1 .967.967L1.167 13.8a.682.682 0 0 1-.483.2z" />
|
|
71
|
+
<path d="M13.316 14a.682.682 0 0 1-.483-.2L.2 1.167A.684.684 0 0 1 1.167.2L13.8 12.833A.684.684 0 0 1 13.316 14z" />
|
|
72
|
+
</g>
|
|
73
|
+
</svg>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div className="flex flex-col items-center px-14 mt-5">
|
|
77
|
+
<div className="text-2xl font-medium">OTP Verification</div>
|
|
78
|
+
<div className={twMerge('mt-2.5 text-center text-gray-700')}>
|
|
79
|
+
{`Please enter the ${codeLength}-digit sms code sent to your registered number and email address`}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
<form
|
|
83
|
+
onSubmit={onSubmit}
|
|
84
|
+
className="flex flex-col items-center w-full"
|
|
85
|
+
>
|
|
86
|
+
<OtpInput
|
|
87
|
+
value={otp}
|
|
88
|
+
onChange={(otp) => {
|
|
89
|
+
setOtp(otp);
|
|
90
|
+
setHasError(false);
|
|
91
|
+
}}
|
|
92
|
+
numInputs={codeLength}
|
|
93
|
+
containerStyle="mt-12 gap-2 flex-wrap"
|
|
94
|
+
inputStyle={twMerge(
|
|
95
|
+
'h-12 w-8 md:h-16 md:w-12 rounded-md border border-gray-600 text-center text-lg',
|
|
96
|
+
hasError && 'border-error'
|
|
97
|
+
)}
|
|
98
|
+
renderInput={({ ...props }) => <input {...props} />}
|
|
99
|
+
skipDefaultStyles={true}
|
|
100
|
+
/>
|
|
101
|
+
{error && <p className="text-xs text-error mt-2">{error}</p>}
|
|
102
|
+
<Button
|
|
103
|
+
type="submit"
|
|
104
|
+
className="mt-5 h-auto w-full py-4 text-lg font-medium uppercase"
|
|
105
|
+
>
|
|
106
|
+
Verify
|
|
107
|
+
</Button>
|
|
108
|
+
</form>
|
|
109
|
+
<div className="mt-6 flex flex-col items-center">
|
|
110
|
+
<span className="text-gray-700">I didn`t receive a code</span>
|
|
111
|
+
<div
|
|
112
|
+
className={twMerge(
|
|
113
|
+
' font-medium underline cursor-pointer',
|
|
114
|
+
!canResend && 'cursor-not-allowed text-gray-700'
|
|
115
|
+
)}
|
|
116
|
+
onClick={resendHandler}
|
|
117
|
+
>
|
|
118
|
+
RESEND
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}}
|
|
126
|
+
/>;
|
|
127
|
+
```
|
package/src/views/Otp.tsx
CHANGED
|
@@ -43,6 +43,19 @@ type OtpProps = {
|
|
|
43
43
|
[c in ComponentClasses]?: string;
|
|
44
44
|
};
|
|
45
45
|
error?: string;
|
|
46
|
+
customUIRender?: (props: {
|
|
47
|
+
closeHandler?: () => void;
|
|
48
|
+
resendHandler?: () => void;
|
|
49
|
+
onSubmit?: (event: FormEvent<HTMLFormElement>) => Promise<void>;
|
|
50
|
+
otp?: string;
|
|
51
|
+
setOtp?: (otp: string) => void;
|
|
52
|
+
hasError?: boolean;
|
|
53
|
+
error?: string;
|
|
54
|
+
canResend?: boolean;
|
|
55
|
+
time?: number;
|
|
56
|
+
codeLength?: number;
|
|
57
|
+
setHasError?: (hasError: boolean) => void;
|
|
58
|
+
}) => ReactNode;
|
|
46
59
|
};
|
|
47
60
|
|
|
48
61
|
export const Otp = ({
|
|
@@ -52,13 +65,15 @@ export const Otp = ({
|
|
|
52
65
|
timer = 60,
|
|
53
66
|
texts,
|
|
54
67
|
classes,
|
|
55
|
-
error
|
|
68
|
+
error,
|
|
69
|
+
customUIRender
|
|
56
70
|
}: OtpProps) => {
|
|
57
71
|
const { phone } = data;
|
|
58
72
|
const [otp, setOtp] = useState('');
|
|
59
73
|
const [canResend, setCanResend] = useState(false);
|
|
60
74
|
const [time, setTime] = useState(timer);
|
|
61
75
|
const [hasError, setHasError] = useState(false);
|
|
76
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
62
77
|
const dispatch = useAppDispatch();
|
|
63
78
|
const { isPopupVisible } = useAppSelector((state) => state.otp);
|
|
64
79
|
|
|
@@ -70,18 +85,26 @@ export const Otp = ({
|
|
|
70
85
|
const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
71
86
|
event.preventDefault();
|
|
72
87
|
|
|
73
|
-
if (
|
|
74
|
-
data.code = otp;
|
|
75
|
-
data.phone = phone;
|
|
76
|
-
const res = await submitAction(data);
|
|
88
|
+
if (isSubmitting) return;
|
|
77
89
|
|
|
78
|
-
|
|
79
|
-
setHasError(true);
|
|
80
|
-
}
|
|
90
|
+
setIsSubmitting(true);
|
|
81
91
|
|
|
82
|
-
|
|
83
|
-
|
|
92
|
+
try {
|
|
93
|
+
if (submitAction) {
|
|
94
|
+
data.code = otp;
|
|
95
|
+
data.phone = phone;
|
|
96
|
+
const res = await submitAction(data);
|
|
97
|
+
|
|
98
|
+
if (res?.status !== 200 || error) {
|
|
99
|
+
setHasError(true);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (res?.status === 200) {
|
|
103
|
+
dispatch(hidePopup());
|
|
104
|
+
}
|
|
84
105
|
}
|
|
106
|
+
} finally {
|
|
107
|
+
setIsSubmitting(false);
|
|
85
108
|
}
|
|
86
109
|
};
|
|
87
110
|
|
|
@@ -129,9 +152,25 @@ export const Otp = ({
|
|
|
129
152
|
|
|
130
153
|
if (!isPopupVisible) return null;
|
|
131
154
|
|
|
155
|
+
if (customUIRender) {
|
|
156
|
+
return customUIRender({
|
|
157
|
+
closeHandler,
|
|
158
|
+
resendHandler,
|
|
159
|
+
onSubmit,
|
|
160
|
+
otp,
|
|
161
|
+
setOtp,
|
|
162
|
+
hasError,
|
|
163
|
+
error,
|
|
164
|
+
canResend,
|
|
165
|
+
time,
|
|
166
|
+
codeLength,
|
|
167
|
+
setHasError
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
132
171
|
return (
|
|
133
172
|
<div className="fixed left-0 top-0 z-50 flex h-screen w-screen items-end md:items-center md:justify-center md:bg-black/10">
|
|
134
|
-
<div className="h-[calc(100vh-48px)] w-screen flex md:h-auto md:max-w-lg flex-col items-center rounded-
|
|
173
|
+
<div className="h-[calc(100vh-48px)] w-screen flex md:h-auto md:max-w-lg flex-col items-center rounded-sm bg-white p-8 shadow-xl">
|
|
135
174
|
<div className="w-full flex items-center justify-end">
|
|
136
175
|
<div className="cursor-pointer" onClick={closeHandler}>
|
|
137
176
|
<svg
|
|
@@ -195,6 +234,7 @@ export const Otp = ({
|
|
|
195
234
|
{error && <p className="text-xs text-error mt-2">{error}</p>}
|
|
196
235
|
<Button
|
|
197
236
|
type="submit"
|
|
237
|
+
disabled={isSubmitting}
|
|
198
238
|
className={twMerge(
|
|
199
239
|
'mt-5 h-auto w-full py-4 text-lg font-medium uppercase',
|
|
200
240
|
classes?.submitButton
|