Skip to content

Commit 5c9fe64

Browse files
committed
Merge branch 'next-release'
2 parents d911a0a + 123025a commit 5c9fe64

File tree

9 files changed

+37121
-87
lines changed

9 files changed

+37121
-87
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ Here is a simple example that shows how to customize `Button` and `Input`
5858

5959
Minimum system versions
6060

61-
- `node >= 12.x`
62-
- `npm >= 6.x`
61+
- `node >= 14.x`
62+
- `npm >= 7.x`
6363

6464
You can start to development with `npm run dev` command. The command watches for changes and builds the toolkit. If you want to generate a production ready build you can use `npm run build`.
6565

package-lock.json

Lines changed: 37038 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hipo/react-ui-toolkit",
3-
"version": "1.0.0-alpha.5.2.0",
3+
"version": "1.0.0-alpha.5.2.1",
44
"description": "React based UI toolkit.",
55
"main": "dist/index.js",
66
"scripts": {

src/core/utils/hooks/useDateTimer.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,56 @@ import {useEffect, useRef, useState, useLayoutEffect} from "react";
33
import {SECOND_IN_MS} from "../time/timeConstants";
44
import {RemainingTimeBreakdown} from "../time/timeTypes";
55
import {calculateRemainingTimeBreakdown} from "../time/timeUtils";
6-
import {TimerType} from "../../../date-timer/util/dateTimerTypes";
6+
import {DateTimerProps, TimerType} from "../../../date-timer/util/dateTimerTypes";
77

88
/**
99
* A React Hook that provides a date timer
10-
* @param {Date[]} range - The target date range we're counting down to
11-
* @param {number} cadence - The rate of the timer in milliseconds
12-
* @param {TimerType} timerType - Type of the timer, either "down" or "up"
10+
* @param {Date[]} options.range - The target date range we're counting down to
11+
* @param {number} options.cadence - The rate of the timer in milliseconds
12+
* @param {TimerType} options.timerType - Type of the timer, either "down" or "up"
13+
* @param {onEnd} options.onEnd - If provided, runs this callback when the timer ended
1314
* @returns {object} The RemainingTimeBreakdown object
1415
*/
15-
function useDateTimer(
16-
range: Date[],
16+
function useDateTimer({
17+
range,
1718
cadence = SECOND_IN_MS,
18-
timerType = "down" as TimerType
19-
): RemainingTimeBreakdown {
20-
const cadenceInMs = cadence * SECOND_IN_MS;
21-
const [counter, setCounter] = useState(0);
19+
timerType = "down",
20+
onEnd
21+
}: {
22+
range: DateTimerProps["range"];
23+
cadence?: number;
24+
timerType?: TimerType;
25+
onEnd?: DateTimerProps["onEnd"];
26+
}): RemainingTimeBreakdown {
27+
const counterForIntervalRef = useRef(0);
2228
const interval = useRef<NodeJS.Timeout>();
2329
const [dateTimer, setDateTimer] = useState<RemainingTimeBreakdown>(
24-
calculateRemainingTimeBreakdown(range, counter, timerType)
30+
calculateRemainingTimeBreakdown(range, counterForIntervalRef.current, timerType)
2531
);
32+
const [rangeStart, rangeEnd] = range;
33+
34+
const savedOnEndCallback = useRef<typeof onEnd>();
35+
36+
useLayoutEffect(() => {
37+
savedOnEndCallback.current = onEnd;
38+
}, [onEnd]);
2639

2740
useLayoutEffect(() => {
2841
interval.current = setInterval(() => {
29-
if (range.length > 1) {
30-
setCounter(counter + cadence);
42+
if (rangeEnd) {
43+
counterForIntervalRef.current += cadence;
3144
}
3245

33-
const data = calculateRemainingTimeBreakdown(range, counter, timerType);
46+
const data = calculateRemainingTimeBreakdown(
47+
[rangeStart, rangeEnd],
48+
counterForIntervalRef.current,
49+
timerType
50+
);
3451

35-
if (data.delta >= 0) {
52+
if (data.delta >= SECOND_IN_MS) {
3653
setDateTimer(data);
3754
} else {
55+
clearInterval(interval.current!);
3856
setDateTimer({
3957
delta: 0,
4058
days: 0,
@@ -43,16 +61,20 @@ function useDateTimer(
4361
seconds: 0
4462
});
4563
}
46-
}, cadenceInMs);
64+
}, cadence);
4765

4866
return () => {
4967
clearInterval(interval.current!);
5068
};
51-
}, [cadence, cadenceInMs, range, counter, timerType]);
69+
}, [cadence, rangeStart, rangeEnd, timerType]);
5270

5371
useEffect(() => {
5472
if (dateTimer.delta <= 0) {
5573
clearInterval(interval.current!);
74+
75+
if (savedOnEndCallback.current) {
76+
savedOnEndCallback.current();
77+
}
5678
}
5779
}, [dateTimer.delta]);
5880

src/core/utils/time/timeUtils.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {TimerType} from "../../../date-timer/util/dateTimerTypes";
1+
import {DateTimerProps, TimerType} from "../../../date-timer/util/dateTimerTypes";
22
import {
33
DAY_IN_HRS,
44
DAY_IN_S,
@@ -15,20 +15,23 @@ function sortDateRange(initialRange: Date[]): Date[] {
1515
}
1616

1717
function calculateRemainingTimeBreakdown(
18-
range: Date[],
18+
range: DateTimerProps["range"],
1919
intervalCount = 0,
2020
timerType = "down" as TimerType
2121
): RemainingTimeBreakdown {
22-
let originDate = new Date();
23-
let targetDate = range[0];
22+
let originDate;
23+
let targetDate;
2424

2525
if (range.length > 1 || timerType === "up") {
2626
[originDate, targetDate] = sortDateRange([range[0], range[1] || new Date()]);
27+
} else {
28+
targetDate = range[0];
29+
originDate = new Date();
2730
}
2831

2932
const delta = targetDate.getTime() - originDate.getTime();
3033

31-
const deltaInSeconds = delta / SECOND_IN_MS - intervalCount;
34+
const deltaInSeconds = (delta - intervalCount) / SECOND_IN_MS;
3235

3336
return {
3437
delta,

src/date-timer/DateTimer.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import "./_date-timer.scss";
22

3-
import React, {useEffect, useLayoutEffect, useRef} from "react";
3+
import React, {useEffect} from "react";
44
import classNames from "classnames";
55

66
import useDateTimer from "../core/utils/hooks/useDateTimer";
@@ -9,6 +9,7 @@ import ListItem from "../list/item/ListItem";
99
import {generateDateTimerItems} from "./util/dateTimerUtils";
1010
import {DateTimerProps} from "./util/dateTimerTypes";
1111
import {sortDateRange} from "../core/utils/time/timeUtils";
12+
import {SECOND_IN_MS} from "../core/utils/time/timeConstants";
1213

1314
function DateTimer({
1415
testid,
@@ -20,9 +21,13 @@ function DateTimer({
2021
onEnd,
2122
customClassName
2223
}: DateTimerProps) {
23-
const dateTimerData = useDateTimer(range, timerInterval, timerType);
24+
const dateTimerData = useDateTimer({
25+
range,
26+
cadence: timerInterval * SECOND_IN_MS,
27+
timerType,
28+
onEnd
29+
});
2430
const items = generateDateTimerItems({titleMap, alwaysShowSeconds}, dateTimerData);
25-
const savedOnEndCallback = useRef<DateTimerProps["onEnd"]>();
2631

2732
// Validate the `range` prop according to the `timerType` prop
2833
useEffect(() => {
@@ -37,16 +42,6 @@ function DateTimer({
3742
}
3843
}, [range, timerType]);
3944

40-
useLayoutEffect(() => {
41-
savedOnEndCallback.current = onEnd;
42-
}, [onEnd]);
43-
44-
useLayoutEffect(() => {
45-
if (dateTimerData.delta <= 0 && savedOnEndCallback.current) {
46-
savedOnEndCallback.current();
47-
}
48-
}, [dateTimerData.delta]);
49-
5045
return (
5146
<List
5247
customClassName={classNames("date-timer", customClassName)}

src/date-timer/util/dateTimerTypes.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@ import {RemainingTimeBreakdown} from "../../core/utils/time/timeTypes";
22

33
export type TimerType = "down" | "up";
44

5+
export type DateTimerItemID = keyof Omit<RemainingTimeBreakdown, "delta">;
6+
57
export interface DateTimerProps {
6-
range: Date[];
8+
range: [Date, Date?];
79
testid?: string;
8-
titleMap?: {
9-
day?: string;
10-
hour?: string;
11-
minute?: string;
12-
second?: string;
13-
};
10+
titleMap?: Record<DateTimerItemID, undefined | string>;
1411

1512
timerInterval?: number /* in seconds */;
1613
timerType?: TimerType;
@@ -20,8 +17,6 @@ export interface DateTimerProps {
2017
customClassName?: string;
2118
}
2219

23-
export type DateTimerItemID = keyof Omit<RemainingTimeBreakdown, "delta">;
24-
2520
export interface DateTimerItem {
2621
id: DateTimerItemID;
2722
title: string;

src/date-timer/util/dateTimerUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function generateDateTimerItems(
2626
id: key,
2727
// eslint-disable-next-line no-magic-numbers
2828
count: dateTimerData[key].toString().padStart(2, "0"),
29-
title: (titleMap ? titleMap[key.replace("s", "")] : undefined) || key
29+
title: (titleMap ? titleMap[key] : undefined) || key
3030
}));
3131
}
3232

stories/15-DateTimer.stories.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ storiesOf("DateTimer", module).add("DateTimer", () => (
1414
onEnd={handleDateTimerEnd}
1515
/>
1616

17+
<DateTimer
18+
range={[calculateFutureDate(1, "day"), calculateFutureDate(3, "day")]}
19+
titleMap={{
20+
days: "d",
21+
hours: "h",
22+
minutes: "m",
23+
seconds: "s"
24+
}}
25+
alwaysShowSeconds={true}
26+
onEnd={handleDateTimerEnd}
27+
/>
28+
1729
<hr />
1830

1931
<span>{"Since `Jan 10 2022` - timerType=`up`"}</span>
@@ -57,6 +69,14 @@ storiesOf("DateTimer", module).add("DateTimer", () => (
5769
<span>{"10 Seconds Later"}</span>
5870

5971
<DateTimer range={[calculateFutureDate(10, "second")]} onEnd={handleDateTimerEnd} />
72+
73+
<span>{"10 Seconds Later with 5s timer interval"}</span>
74+
75+
<DateTimer
76+
range={[calculateFutureDate(10, "second")]}
77+
onEnd={handleDateTimerEnd}
78+
timerInterval={5}
79+
/>
6080
</StoryFragment>
6181
));
6282

0 commit comments

Comments
 (0)