otp-timer 2.1.1 → 3.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/README.md +79 -62
- package/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +115 -0
- package/dist/index.mjs +78 -0
- package/package.json +57 -35
- package/.babelrc +0 -13
- package/.vscode/settings.json +0 -3
- package/example/index.css +0 -3
- package/example/index.html +0 -9
- package/example/index.js +0 -28
- package/example/webpack.config.js +0 -23
- package/lib/timer.js +0 -136
- package/src/timer.js +0 -114
package/README.md
CHANGED
|
@@ -1,62 +1,79 @@
|
|
|
1
|
-
# otp-timer
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
1
|
+
# otp-timer
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/otp-timer)
|
|
4
|
+
[](https://github.com/927tanmay/otp-timer/actions/workflows/ci.yml)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
A tiny React countdown timer for OTP screens. It counts down, then swaps itself for a **Resend** button that restarts the timer.
|
|
8
|
+
|
|
9
|
+
- Works with React 16.8 through 19
|
|
10
|
+
- Zero dependencies, ~2 KB
|
|
11
|
+
- TypeScript types included
|
|
12
|
+
- ESM and CommonJS builds
|
|
13
|
+
|
|
14
|
+
## Demo
|
|
15
|
+
|
|
16
|
+
[927tanmay.github.io/otp-timer](https://927tanmay.github.io/otp-timer/)
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install otp-timer
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```jsx
|
|
27
|
+
import OtpTimer from "otp-timer";
|
|
28
|
+
|
|
29
|
+
export default function VerifyOtp() {
|
|
30
|
+
const handleResend = () => {
|
|
31
|
+
// request a new OTP here
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return <OtpTimer minutes={1} seconds={0} resend={handleResend} />;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A named export is also available: `import { OtpTimer } from "otp-timer"`.
|
|
39
|
+
|
|
40
|
+
## Props
|
|
41
|
+
|
|
42
|
+
### Behaviour
|
|
43
|
+
|
|
44
|
+
| Prop | Description | Default | Example |
|
|
45
|
+
| :----------- | :------------------------------------------------------------- | :------------- | :-------------------------- |
|
|
46
|
+
| `minutes` | Minutes to count down from | `0` | `minutes={1}` |
|
|
47
|
+
| `seconds` | Seconds to count down from (values over 59 roll into minutes) | `30` | `seconds={20}` |
|
|
48
|
+
| `resend` | Called when the resend button is clicked; the timer restarts | – | `resend={handleResend}` |
|
|
49
|
+
| `text` | Label shown before the countdown | `"Time left:"` | `text="Code expires in"` |
|
|
50
|
+
| `ButtonText` | Resend button content | `"Resend"` | `ButtonText="Send again"` |
|
|
51
|
+
|
|
52
|
+
### Styling
|
|
53
|
+
|
|
54
|
+
| Prop | Description | Default | Example |
|
|
55
|
+
| :---------------- | :------------------------------ | :---------- | :--------------------------------- |
|
|
56
|
+
| `textColor` | Timer text color | `"#000000"` | `textColor="#333"` |
|
|
57
|
+
| `buttonColor` | Resend button text color | `"#fff"` | `buttonColor="#fff"` |
|
|
58
|
+
| `background` | Resend button background color | `"#0033cc"` | `background="#0033cc"` |
|
|
59
|
+
| `buttonClassName` | Class name for the button | – | `buttonClassName="btn"` |
|
|
60
|
+
| `buttonStyle` | Inline styles for the button | – | `buttonStyle={{ padding: 8 }}` |
|
|
61
|
+
| `timerSpanClass` | Class name for the timer text | – | `timerSpanClass="timer"` |
|
|
62
|
+
| `timerSpanStyle` | Inline styles for the timer text| – | `timerSpanStyle={{ fontWeight: 600 }}` |
|
|
63
|
+
|
|
64
|
+
## Upgrading from v2
|
|
65
|
+
|
|
66
|
+
See [CHANGELOG.md](./CHANGELOG.md#300). For most apps, no code changes are needed.
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
npm install
|
|
72
|
+
npm run dev # example app at http://localhost:5173
|
|
73
|
+
npm test
|
|
74
|
+
npm run build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT © [Simran Gupta](https://github.com/1209simran) & [Tanmay Sharma](https://github.com/927tanmay)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { ReactNode, CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
interface OtpTimerProps {
|
|
4
|
+
/** Minutes to count down from. Default: 0 */
|
|
5
|
+
minutes?: number;
|
|
6
|
+
/** Seconds to count down from. Values above 59 roll over into minutes. Default: 30 */
|
|
7
|
+
seconds?: number;
|
|
8
|
+
/** Called when the resend button is clicked, before the timer restarts. */
|
|
9
|
+
resend?: () => void;
|
|
10
|
+
/** Label shown before the countdown. Default: "Time left:" */
|
|
11
|
+
text?: ReactNode;
|
|
12
|
+
/** Resend button content. Default: "Resend" */
|
|
13
|
+
ButtonText?: ReactNode;
|
|
14
|
+
/** Timer text color. Default: "#000000" */
|
|
15
|
+
textColor?: string;
|
|
16
|
+
/** Resend button text color. Default: "#fff" */
|
|
17
|
+
buttonColor?: string;
|
|
18
|
+
/** Resend button background color. Default: "#0033cc" */
|
|
19
|
+
background?: string;
|
|
20
|
+
buttonClassName?: string;
|
|
21
|
+
buttonStyle?: CSSProperties;
|
|
22
|
+
timerSpanClass?: string;
|
|
23
|
+
timerSpanStyle?: CSSProperties;
|
|
24
|
+
}
|
|
25
|
+
declare function OtpTimer({ minutes, seconds, resend, text, ButtonText, textColor, buttonColor, background, buttonClassName, buttonStyle, timerSpanClass, timerSpanStyle, }: OtpTimerProps): React.JSX.Element;
|
|
26
|
+
|
|
27
|
+
export { OtpTimer, type OtpTimerProps, OtpTimer as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React, { ReactNode, CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
interface OtpTimerProps {
|
|
4
|
+
/** Minutes to count down from. Default: 0 */
|
|
5
|
+
minutes?: number;
|
|
6
|
+
/** Seconds to count down from. Values above 59 roll over into minutes. Default: 30 */
|
|
7
|
+
seconds?: number;
|
|
8
|
+
/** Called when the resend button is clicked, before the timer restarts. */
|
|
9
|
+
resend?: () => void;
|
|
10
|
+
/** Label shown before the countdown. Default: "Time left:" */
|
|
11
|
+
text?: ReactNode;
|
|
12
|
+
/** Resend button content. Default: "Resend" */
|
|
13
|
+
ButtonText?: ReactNode;
|
|
14
|
+
/** Timer text color. Default: "#000000" */
|
|
15
|
+
textColor?: string;
|
|
16
|
+
/** Resend button text color. Default: "#fff" */
|
|
17
|
+
buttonColor?: string;
|
|
18
|
+
/** Resend button background color. Default: "#0033cc" */
|
|
19
|
+
background?: string;
|
|
20
|
+
buttonClassName?: string;
|
|
21
|
+
buttonStyle?: CSSProperties;
|
|
22
|
+
timerSpanClass?: string;
|
|
23
|
+
timerSpanStyle?: CSSProperties;
|
|
24
|
+
}
|
|
25
|
+
declare function OtpTimer({ minutes, seconds, resend, text, ButtonText, textColor, buttonColor, background, buttonClassName, buttonStyle, timerSpanClass, timerSpanStyle, }: OtpTimerProps): React.JSX.Element;
|
|
26
|
+
|
|
27
|
+
export { OtpTimer, type OtpTimerProps, OtpTimer as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
OtpTimer: () => OtpTimer,
|
|
34
|
+
default: () => OtpTimer
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/OtpTimer.tsx
|
|
39
|
+
var import_react = __toESM(require("react"));
|
|
40
|
+
var { useEffect, useRef, useState } = import_react.default;
|
|
41
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
42
|
+
var toNumber = (value, fallback) => {
|
|
43
|
+
if (value === null || value === void 0 || value === "") return fallback;
|
|
44
|
+
const n = Number(value);
|
|
45
|
+
return Number.isFinite(n) ? n : fallback;
|
|
46
|
+
};
|
|
47
|
+
function OtpTimer({
|
|
48
|
+
minutes,
|
|
49
|
+
seconds,
|
|
50
|
+
resend,
|
|
51
|
+
text,
|
|
52
|
+
ButtonText,
|
|
53
|
+
textColor,
|
|
54
|
+
buttonColor,
|
|
55
|
+
background,
|
|
56
|
+
buttonClassName,
|
|
57
|
+
buttonStyle,
|
|
58
|
+
timerSpanClass,
|
|
59
|
+
timerSpanStyle
|
|
60
|
+
}) {
|
|
61
|
+
const total = Math.max(
|
|
62
|
+
0,
|
|
63
|
+
Math.floor(toNumber(minutes, 0) * 60 + toNumber(seconds, 30))
|
|
64
|
+
);
|
|
65
|
+
const [remaining, setRemaining] = useState(total);
|
|
66
|
+
const [cycle, setCycle] = useState(0);
|
|
67
|
+
const durationRef = useRef(total);
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
const duration = durationRef.current;
|
|
70
|
+
if (duration <= 0) return;
|
|
71
|
+
const deadline = Date.now() + duration * 1e3;
|
|
72
|
+
const id = setInterval(() => {
|
|
73
|
+
const left = Math.max(0, Math.round((deadline - Date.now()) / 1e3));
|
|
74
|
+
setRemaining(left);
|
|
75
|
+
if (left === 0) clearInterval(id);
|
|
76
|
+
}, 1e3);
|
|
77
|
+
return () => clearInterval(id);
|
|
78
|
+
}, [cycle]);
|
|
79
|
+
const handleClick = (event) => {
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
resend == null ? void 0 : resend();
|
|
82
|
+
durationRef.current = total;
|
|
83
|
+
setRemaining(total);
|
|
84
|
+
setCycle((c) => c + 1);
|
|
85
|
+
};
|
|
86
|
+
const textStyle = {
|
|
87
|
+
fontSize: "16px",
|
|
88
|
+
fontFamily: "Roboto",
|
|
89
|
+
lineHeight: "22px",
|
|
90
|
+
color: textColor || "#000000"
|
|
91
|
+
};
|
|
92
|
+
const buttonStyling = {
|
|
93
|
+
border: "none",
|
|
94
|
+
cursor: "pointer",
|
|
95
|
+
background: background || "#0033cc",
|
|
96
|
+
color: buttonColor || "#fff",
|
|
97
|
+
fontSize: "16px",
|
|
98
|
+
lineHeight: "22px",
|
|
99
|
+
...buttonStyle
|
|
100
|
+
};
|
|
101
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { style: textStyle }, remaining === 0 ? /* @__PURE__ */ import_react.default.createElement(
|
|
102
|
+
"button",
|
|
103
|
+
{
|
|
104
|
+
type: "button",
|
|
105
|
+
style: buttonStyling,
|
|
106
|
+
onClick: handleClick,
|
|
107
|
+
className: buttonClassName
|
|
108
|
+
},
|
|
109
|
+
ButtonText ? /* @__PURE__ */ import_react.default.createElement("span", null, ButtonText, " ") : /* @__PURE__ */ import_react.default.createElement("span", null, "Resend")
|
|
110
|
+
) : /* @__PURE__ */ import_react.default.createElement("span", { role: "timer", className: timerSpanClass, style: timerSpanStyle }, /* @__PURE__ */ import_react.default.createElement("span", null, text || "Time left:", " "), pad(Math.floor(remaining / 60)), ":", pad(remaining % 60)));
|
|
111
|
+
}
|
|
112
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
113
|
+
0 && (module.exports = {
|
|
114
|
+
OtpTimer
|
|
115
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/OtpTimer.tsx
|
|
2
|
+
import React from "react";
|
|
3
|
+
var { useEffect, useRef, useState } = React;
|
|
4
|
+
var pad = (n) => String(n).padStart(2, "0");
|
|
5
|
+
var toNumber = (value, fallback) => {
|
|
6
|
+
if (value === null || value === void 0 || value === "") return fallback;
|
|
7
|
+
const n = Number(value);
|
|
8
|
+
return Number.isFinite(n) ? n : fallback;
|
|
9
|
+
};
|
|
10
|
+
function OtpTimer({
|
|
11
|
+
minutes,
|
|
12
|
+
seconds,
|
|
13
|
+
resend,
|
|
14
|
+
text,
|
|
15
|
+
ButtonText,
|
|
16
|
+
textColor,
|
|
17
|
+
buttonColor,
|
|
18
|
+
background,
|
|
19
|
+
buttonClassName,
|
|
20
|
+
buttonStyle,
|
|
21
|
+
timerSpanClass,
|
|
22
|
+
timerSpanStyle
|
|
23
|
+
}) {
|
|
24
|
+
const total = Math.max(
|
|
25
|
+
0,
|
|
26
|
+
Math.floor(toNumber(minutes, 0) * 60 + toNumber(seconds, 30))
|
|
27
|
+
);
|
|
28
|
+
const [remaining, setRemaining] = useState(total);
|
|
29
|
+
const [cycle, setCycle] = useState(0);
|
|
30
|
+
const durationRef = useRef(total);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const duration = durationRef.current;
|
|
33
|
+
if (duration <= 0) return;
|
|
34
|
+
const deadline = Date.now() + duration * 1e3;
|
|
35
|
+
const id = setInterval(() => {
|
|
36
|
+
const left = Math.max(0, Math.round((deadline - Date.now()) / 1e3));
|
|
37
|
+
setRemaining(left);
|
|
38
|
+
if (left === 0) clearInterval(id);
|
|
39
|
+
}, 1e3);
|
|
40
|
+
return () => clearInterval(id);
|
|
41
|
+
}, [cycle]);
|
|
42
|
+
const handleClick = (event) => {
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
resend == null ? void 0 : resend();
|
|
45
|
+
durationRef.current = total;
|
|
46
|
+
setRemaining(total);
|
|
47
|
+
setCycle((c) => c + 1);
|
|
48
|
+
};
|
|
49
|
+
const textStyle = {
|
|
50
|
+
fontSize: "16px",
|
|
51
|
+
fontFamily: "Roboto",
|
|
52
|
+
lineHeight: "22px",
|
|
53
|
+
color: textColor || "#000000"
|
|
54
|
+
};
|
|
55
|
+
const buttonStyling = {
|
|
56
|
+
border: "none",
|
|
57
|
+
cursor: "pointer",
|
|
58
|
+
background: background || "#0033cc",
|
|
59
|
+
color: buttonColor || "#fff",
|
|
60
|
+
fontSize: "16px",
|
|
61
|
+
lineHeight: "22px",
|
|
62
|
+
...buttonStyle
|
|
63
|
+
};
|
|
64
|
+
return /* @__PURE__ */ React.createElement("div", { style: textStyle }, remaining === 0 ? /* @__PURE__ */ React.createElement(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
type: "button",
|
|
68
|
+
style: buttonStyling,
|
|
69
|
+
onClick: handleClick,
|
|
70
|
+
className: buttonClassName
|
|
71
|
+
},
|
|
72
|
+
ButtonText ? /* @__PURE__ */ React.createElement("span", null, ButtonText, " ") : /* @__PURE__ */ React.createElement("span", null, "Resend")
|
|
73
|
+
) : /* @__PURE__ */ React.createElement("span", { role: "timer", className: timerSpanClass, style: timerSpanStyle }, /* @__PURE__ */ React.createElement("span", null, text || "Time left:", " "), pad(Math.floor(remaining / 60)), ":", pad(remaining % 60)));
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
OtpTimer,
|
|
77
|
+
OtpTimer as default
|
|
78
|
+
};
|
package/package.json
CHANGED
|
@@ -1,52 +1,74 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "otp-timer",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "lib/timer.js",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Lightweight React OTP countdown timer with a resend button",
|
|
6
5
|
"author": "Simran Gupta & Tanmay Sharma",
|
|
7
6
|
"license": "MIT",
|
|
8
7
|
"repository": {
|
|
9
8
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/927tanmay/otp-timer.git"
|
|
9
|
+
"url": "git+https://github.com/927tanmay/otp-timer.git"
|
|
11
10
|
},
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"prop-types": "^15.6.0",
|
|
17
|
-
"react": "^16.13.1",
|
|
18
|
-
"react-dom": "^16.13.1"
|
|
11
|
+
"homepage": "https://github.com/927tanmay/otp-timer#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/927tanmay/otp-timer/issues"
|
|
19
14
|
},
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"webpack-cli": "^5.1.4",
|
|
36
|
-
"webpack-dev-server": "^4.15.0"
|
|
15
|
+
"type": "commonjs",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"module": "./dist/index.mjs",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/index.d.mts",
|
|
23
|
+
"default": "./dist/index.mjs"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
37
30
|
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"sideEffects": false,
|
|
38
35
|
"scripts": {
|
|
39
|
-
"build": "
|
|
40
|
-
"dev": "
|
|
41
|
-
"
|
|
36
|
+
"build": "tsup",
|
|
37
|
+
"dev": "vite example",
|
|
38
|
+
"build:example": "vite build example",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"prepublishOnly": "npm run typecheck && npm test",
|
|
42
|
+
"prepack": "npm run build"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": ">=16.8.0"
|
|
42
46
|
},
|
|
43
47
|
"keywords": [
|
|
44
48
|
"react",
|
|
45
49
|
"react-component",
|
|
46
|
-
"otptimer",
|
|
47
50
|
"otp",
|
|
48
51
|
"otp-timer",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
+
"otptimer",
|
|
53
|
+
"resend-otp",
|
|
54
|
+
"countdown",
|
|
55
|
+
"timer"
|
|
56
|
+
],
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@testing-library/dom": "^10.4.2",
|
|
59
|
+
"@testing-library/react": "^16.3.3",
|
|
60
|
+
"@types/react": "^19.3.0",
|
|
61
|
+
"@types/react-dom": "^19.3.0",
|
|
62
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
63
|
+
"jsdom": "^29.1.1",
|
|
64
|
+
"react": "^19.3.0",
|
|
65
|
+
"react-dom": "^19.3.0",
|
|
66
|
+
"tsup": "^8.5.1",
|
|
67
|
+
"typescript": "^5.9.3",
|
|
68
|
+
"vite": "^8.3.2",
|
|
69
|
+
"vitest": "^5.0.3"
|
|
70
|
+
},
|
|
71
|
+
"overrides": {
|
|
72
|
+
"esbuild": "^0.28.2"
|
|
73
|
+
}
|
|
52
74
|
}
|
package/.babelrc
DELETED
package/.vscode/settings.json
DELETED
package/example/index.css
DELETED
package/example/index.html
DELETED
package/example/index.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import OtpTimer from "../lib/timer";
|
|
2
|
-
import ReactDOM from "react-dom";
|
|
3
|
-
import React, { Component, PropTypes } from "react";
|
|
4
|
-
import './index.css'
|
|
5
|
-
|
|
6
|
-
class Example extends Component {
|
|
7
|
-
submit() {
|
|
8
|
-
console.log("button clicked");
|
|
9
|
-
}
|
|
10
|
-
render() {
|
|
11
|
-
return (
|
|
12
|
-
<div>
|
|
13
|
-
<OtpTimer
|
|
14
|
-
seconds={2}
|
|
15
|
-
minutes={0}
|
|
16
|
-
resend={this.submit.bind(this)}
|
|
17
|
-
text="Time:"
|
|
18
|
-
ButtonText="Resend"
|
|
19
|
-
timerSpanClass= "btn"
|
|
20
|
-
timerSpanStyle={{ fontSize: "16px" }}
|
|
21
|
-
buttonStyle={{ backgroundColor: "lightBlue" }}
|
|
22
|
-
/>
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
ReactDOM.render(<Example />, document.getElementById("root"));
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
entry: ['./example/index.js'],
|
|
5
|
-
devtool: 'inline-source-map',
|
|
6
|
-
output: { filename: 'bundle.js', publicPath: '' },
|
|
7
|
-
module: {
|
|
8
|
-
rules: [
|
|
9
|
-
{
|
|
10
|
-
test: /\.js$/,
|
|
11
|
-
use: [ { loader: 'babel-loader', options: { presets: ['@babel/preset-env', '@babel/react'] } } ],
|
|
12
|
-
exclude: /node_modules/,
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
test: /\.css$/,
|
|
16
|
-
use: ["style-loader", "css-loader"],
|
|
17
|
-
},
|
|
18
|
-
]
|
|
19
|
-
},
|
|
20
|
-
plugins: [
|
|
21
|
-
new HtmlWebpackPlugin({ title: 'react infinite loader example', template: './example/index.html' })
|
|
22
|
-
],
|
|
23
|
-
}
|
package/lib/timer.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
|
-
Object.defineProperty(exports, "__esModule", {
|
|
5
|
-
value: true
|
|
6
|
-
});
|
|
7
|
-
exports["default"] = void 0;
|
|
8
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
11
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
12
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
|
13
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
15
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
16
|
-
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
17
|
-
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
18
|
-
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
19
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
20
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
21
|
-
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
22
|
-
function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
|
|
23
|
-
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
|
|
24
|
-
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
25
|
-
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
|
|
26
|
-
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
|
|
27
|
-
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
|
|
28
|
-
var Otp = exports["default"] = /*#__PURE__*/function (_Component) {
|
|
29
|
-
function Otp(props) {
|
|
30
|
-
var _this;
|
|
31
|
-
_classCallCheck(this, Otp);
|
|
32
|
-
_this = _callSuper(this, Otp, [props]);
|
|
33
|
-
_this.state = {
|
|
34
|
-
showfield: false,
|
|
35
|
-
minutes: _this.props.minutes ? _this.props.minutes : 0,
|
|
36
|
-
seconds: _this.props.seconds ? _this.props.seconds : 30
|
|
37
|
-
};
|
|
38
|
-
_this.handleClick = _this.handleClick.bind(_this);
|
|
39
|
-
return _this;
|
|
40
|
-
}
|
|
41
|
-
_inherits(Otp, _Component);
|
|
42
|
-
return _createClass(Otp, [{
|
|
43
|
-
key: "componentDidMount",
|
|
44
|
-
value: function componentDidMount() {
|
|
45
|
-
clearInterval(this.myInterval);
|
|
46
|
-
this.otptimer();
|
|
47
|
-
}
|
|
48
|
-
}, {
|
|
49
|
-
key: "otptimer",
|
|
50
|
-
value: function otptimer() {
|
|
51
|
-
var _this2 = this;
|
|
52
|
-
clearInterval(this.myInterval);
|
|
53
|
-
this.myInterval = setInterval(function () {
|
|
54
|
-
var _this2$state = _this2.state,
|
|
55
|
-
seconds = _this2$state.seconds,
|
|
56
|
-
minutes = _this2$state.minutes;
|
|
57
|
-
if (seconds > 0) {
|
|
58
|
-
_this2.setState(function (_ref) {
|
|
59
|
-
var seconds = _ref.seconds;
|
|
60
|
-
return {
|
|
61
|
-
seconds: seconds - 1
|
|
62
|
-
};
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
if (seconds === 0) {
|
|
66
|
-
if (minutes === 0) {
|
|
67
|
-
clearInterval(_this2.myInterval);
|
|
68
|
-
} else {
|
|
69
|
-
_this2.setState(function (_ref2) {
|
|
70
|
-
var minutes = _ref2.minutes;
|
|
71
|
-
return {
|
|
72
|
-
minutes: minutes - 1,
|
|
73
|
-
seconds: 59
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}, 1000);
|
|
79
|
-
}
|
|
80
|
-
}, {
|
|
81
|
-
key: "componentWillUnmount",
|
|
82
|
-
value: function componentWillUnmount() {
|
|
83
|
-
clearInterval(this.myInterval);
|
|
84
|
-
}
|
|
85
|
-
}, {
|
|
86
|
-
key: "handleClick",
|
|
87
|
-
value: function handleClick(event) {
|
|
88
|
-
this.setState({
|
|
89
|
-
minutes: this.props.minutes ? this.props.minutes : 0,
|
|
90
|
-
seconds: this.props.seconds ? this.props.seconds : 30
|
|
91
|
-
});
|
|
92
|
-
this.props.resend();
|
|
93
|
-
this.otptimer();
|
|
94
|
-
event.preventDefault();
|
|
95
|
-
}
|
|
96
|
-
// wrapperFunction(e){
|
|
97
|
-
// this.props.resend;
|
|
98
|
-
// this.handleClick.bind(this);
|
|
99
|
-
// }
|
|
100
|
-
}, {
|
|
101
|
-
key: "render",
|
|
102
|
-
value: function render() {
|
|
103
|
-
var textStyle = {
|
|
104
|
-
fontSize: "16px",
|
|
105
|
-
fontFamily: "Roboto",
|
|
106
|
-
lineHeight: "22px",
|
|
107
|
-
color: this.props.textColor ? this.props.textColor : "#000000"
|
|
108
|
-
};
|
|
109
|
-
var buttonStyling = {
|
|
110
|
-
border: "none",
|
|
111
|
-
cursor: "pointer",
|
|
112
|
-
background: this.props.background ? this.props.background : "#0033cc",
|
|
113
|
-
color: this.props.buttonColor ? this.props.buttonColor : "#fff",
|
|
114
|
-
fontSize: "16px",
|
|
115
|
-
lineHeight: "22px"
|
|
116
|
-
};
|
|
117
|
-
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
118
|
-
style: textStyle
|
|
119
|
-
}, this.state.minutes === 0 && this.state.seconds === 0 ? /*#__PURE__*/_react["default"].createElement("button", {
|
|
120
|
-
style: _objectSpread(_objectSpread({}, buttonStyling), this.props.buttonStyle),
|
|
121
|
-
onClick: this.handleClick,
|
|
122
|
-
className: this.props.buttonClassName
|
|
123
|
-
}, this.props.ButtonText ? /*#__PURE__*/_react["default"].createElement("span", null, this.props.ButtonText, " ") : /*#__PURE__*/_react["default"].createElement("span", null, "Resend")) : /*#__PURE__*/_react["default"].createElement("span", {
|
|
124
|
-
className: this.props.timerSpanClass,
|
|
125
|
-
style: this.props.timerSpanStyle
|
|
126
|
-
}, this.props.text ? /*#__PURE__*/_react["default"].createElement("span", null, this.props.text, " ") : /*#__PURE__*/_react["default"].createElement("span", null, "Time left: "), this.state.minutes < 10 ? "0".concat(this.state.minutes) : this.state.minutes, ":", this.state.seconds < 10 ? "0".concat(this.state.seconds) : this.state.seconds));
|
|
127
|
-
}
|
|
128
|
-
}], [{
|
|
129
|
-
key: "propTypes",
|
|
130
|
-
get: function get() {
|
|
131
|
-
return {
|
|
132
|
-
options: _propTypes["default"].object
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
}]);
|
|
136
|
-
}(_react.Component);
|
package/src/timer.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import React, { Component } from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
|
|
4
|
-
export default class Otp extends Component {
|
|
5
|
-
static get propTypes() {
|
|
6
|
-
return {
|
|
7
|
-
options: PropTypes.object,
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
constructor(props) {
|
|
12
|
-
super(props);
|
|
13
|
-
this.state = {
|
|
14
|
-
showfield: false,
|
|
15
|
-
minutes: this.props.minutes ? this.props.minutes : 0,
|
|
16
|
-
seconds: this.props.seconds ? this.props.seconds : 30,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
this.handleClick = this.handleClick.bind(this);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
componentDidMount() {
|
|
23
|
-
clearInterval(this.myInterval);
|
|
24
|
-
this.otptimer();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
otptimer() {
|
|
28
|
-
clearInterval(this.myInterval);
|
|
29
|
-
this.myInterval = setInterval(() => {
|
|
30
|
-
const { seconds, minutes } = this.state;
|
|
31
|
-
|
|
32
|
-
if (seconds > 0) {
|
|
33
|
-
this.setState(({ seconds }) => ({
|
|
34
|
-
seconds: seconds - 1,
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
37
|
-
if (seconds === 0) {
|
|
38
|
-
if (minutes === 0) {
|
|
39
|
-
clearInterval(this.myInterval);
|
|
40
|
-
} else {
|
|
41
|
-
this.setState(({ minutes }) => ({
|
|
42
|
-
minutes: minutes - 1,
|
|
43
|
-
seconds: 59,
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}, 1000);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
componentWillUnmount() {
|
|
51
|
-
clearInterval(this.myInterval);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
handleClick(event) {
|
|
55
|
-
this.setState({
|
|
56
|
-
minutes: this.props.minutes ? this.props.minutes : 0,
|
|
57
|
-
seconds: this.props.seconds ? this.props.seconds : 30,
|
|
58
|
-
});
|
|
59
|
-
this.props.resend();
|
|
60
|
-
this.otptimer();
|
|
61
|
-
event.preventDefault();
|
|
62
|
-
}
|
|
63
|
-
// wrapperFunction(e){
|
|
64
|
-
// this.props.resend;
|
|
65
|
-
// this.handleClick.bind(this);
|
|
66
|
-
// }
|
|
67
|
-
|
|
68
|
-
render() {
|
|
69
|
-
const textStyle = {
|
|
70
|
-
fontSize: "16px",
|
|
71
|
-
fontFamily: "Roboto",
|
|
72
|
-
lineHeight: "22px",
|
|
73
|
-
color: this.props.textColor ? this.props.textColor : "#000000",
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const buttonStyling = {
|
|
77
|
-
border: "none",
|
|
78
|
-
cursor: "pointer",
|
|
79
|
-
background: this.props.background ? this.props.background : "#0033cc",
|
|
80
|
-
color: this.props.buttonColor ? this.props.buttonColor : "#fff",
|
|
81
|
-
fontSize: "16px",
|
|
82
|
-
lineHeight: "22px",
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<div style={textStyle}>
|
|
87
|
-
{this.state.minutes === 0 && this.state.seconds === 0 ? (
|
|
88
|
-
<button style={{...buttonStyling, ...this.props.buttonStyle}} onClick={this.handleClick} className={this.props.buttonClassName}>
|
|
89
|
-
{this.props.ButtonText ? (
|
|
90
|
-
<span>{this.props.ButtonText} </span>
|
|
91
|
-
) : (
|
|
92
|
-
<span>Resend</span>
|
|
93
|
-
)}
|
|
94
|
-
</button>
|
|
95
|
-
) : (
|
|
96
|
-
<span className={this.props.timerSpanClass} style={this.props.timerSpanStyle}>
|
|
97
|
-
{this.props.text ? (
|
|
98
|
-
<span>{this.props.text} </span>
|
|
99
|
-
) : (
|
|
100
|
-
<span>Time left: </span>
|
|
101
|
-
)}
|
|
102
|
-
{this.state.minutes < 10
|
|
103
|
-
? `0${this.state.minutes}`
|
|
104
|
-
: this.state.minutes}
|
|
105
|
-
:
|
|
106
|
-
{this.state.seconds < 10
|
|
107
|
-
? `0${this.state.seconds}`
|
|
108
|
-
: this.state.seconds}
|
|
109
|
-
</span>
|
|
110
|
-
)}
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|