@gfazioli/mantine-clock
Version:
React Clock components and hooks for Mantine with timezone support, countdown timers, customization options, and real-time updates.
239 lines (235 loc) • 6.84 kB
JavaScript
'use client';
;
var dayjs = require('dayjs');
var duration = require('dayjs/plugin/duration');
var isLeapYear = require('dayjs/plugin/isLeapYear');
var timezonePlugin = require('dayjs/plugin/timezone');
var utc = require('dayjs/plugin/utc');
var weekOfYear = require('dayjs/plugin/weekOfYear');
var React = require('react');
var hooks = require('@mantine/hooks');
dayjs.extend(utc);
dayjs.extend(timezonePlugin);
dayjs.extend(weekOfYear);
dayjs.extend(isLeapYear);
dayjs.extend(duration);
dayjs.extend(utc);
dayjs.extend(timezonePlugin);
dayjs.extend(weekOfYear);
dayjs.extend(isLeapYear);
dayjs.extend(duration);
function useClockCountDown({
enabled = true,
timezone = "UTC",
updateFrequency = 1e3,
use24Hours = true,
padSeconds = false,
padMinutes = false,
padHours = false,
targetDate,
hours = 0,
minutes = 0,
seconds = 0,
onCountDownCompleted
}) {
const mounted = hooks.useMounted();
const [remainingTime, setRemainingTime] = React.useState(0);
const [isRunning, setIsRunning] = React.useState(false);
const [isCompleted, setIsCompleted] = React.useState(false);
const intervalRef = React.useRef(null);
const initialDurationRef = React.useRef(0);
const targetDateRef = React.useRef(null);
const completedCallbackRef = React.useRef(onCountDownCompleted);
const initialEnabledRef = React.useRef(enabled);
React.useEffect(() => {
completedCallbackRef.current = onCountDownCompleted;
}, [onCountDownCompleted]);
const calculateInitialDuration = React.useCallback(() => {
if (!mounted) {
return 0;
}
let target;
if (targetDate) {
target = dayjs(targetDate).tz(timezone);
} else {
const now2 = dayjs().tz(timezone);
const h = Math.max(0, hours);
const m = Math.max(0, minutes);
const s = Math.max(0, seconds);
if (h === 0 && m === 0 && s === 0) {
target = now2.add(1, "hour");
} else {
target = now2.add(h, "hour").add(m, "minute").add(s, "second");
}
}
targetDateRef.current = target;
const now = dayjs().tz(timezone);
return Math.max(0, target.diff(now));
}, [targetDate, hours, minutes, seconds, timezone, mounted]);
React.useEffect(() => {
if (!mounted) {
return;
}
const duration2 = calculateInitialDuration();
initialDurationRef.current = duration2;
setRemainingTime(duration2);
setIsCompleted(duration2 <= 0);
if (enabled && duration2 > 0) {
setIsRunning(true);
} else {
setIsRunning(false);
}
}, [mounted, calculateInitialDuration, enabled]);
React.useEffect(() => {
if (!mounted || !isRunning || isCompleted) {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
return;
}
intervalRef.current = setInterval(() => {
setRemainingTime((prev) => {
const newTime = Math.max(0, prev - updateFrequency);
if (newTime <= 0) {
setIsCompleted(true);
setIsRunning(false);
if (completedCallbackRef.current) {
completedCallbackRef.current();
}
}
return newTime;
});
}, updateFrequency);
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
}, [mounted, isRunning, isCompleted, updateFrequency]);
const start = React.useCallback(() => {
if (!mounted || isCompleted) {
return;
}
setIsRunning(true);
}, [mounted, isCompleted]);
const pause = React.useCallback(() => {
setIsRunning(false);
}, []);
const resume = React.useCallback(() => {
if (!mounted || isCompleted || remainingTime <= 0) {
return;
}
setIsRunning(true);
}, [mounted, isCompleted, remainingTime]);
const reset = React.useCallback(() => {
setIsRunning(false);
setIsCompleted(false);
const duration2 = calculateInitialDuration();
initialDurationRef.current = duration2;
setRemainingTime(duration2);
if (initialEnabledRef.current && duration2 > 0) {
setIsRunning(true);
}
}, [calculateInitialDuration]);
if (!mounted) {
const staticHours = padHours ? "00" : 0;
const staticMinutes = padMinutes ? "00" : 0;
const staticSeconds = padSeconds ? "00" : 0;
return {
year: 0,
month: 1,
day: 0,
week: 0,
isLeap: false,
hours: staticHours,
minutes: staticMinutes,
seconds: staticSeconds,
milliseconds: 0,
amPm: use24Hours ? void 0 : "AM",
isCompleted: false,
isRunning: false,
totalMilliseconds: 0,
start: () => {
},
pause: () => {
},
reset: () => {
},
resume: () => {
}
};
}
if (isCompleted || remainingTime <= 0) {
const staticHours = padHours ? "00" : 0;
const staticMinutes = padMinutes ? "00" : 0;
const staticSeconds = padSeconds ? "00" : 0;
return {
year: 0,
month: 0,
day: 0,
week: 0,
isLeap: false,
hours: staticHours,
minutes: staticMinutes,
seconds: staticSeconds,
milliseconds: 0,
amPm: use24Hours ? void 0 : "AM",
isCompleted: true,
isRunning: false,
totalMilliseconds: 0,
start: () => {
},
pause,
reset,
resume: () => {
}
};
}
const dur = dayjs.duration(remainingTime);
const remainingYears = Math.floor(dur.asYears());
const remainingMonths = Math.floor(dur.asMonths()) % 12;
const remainingDays = Math.floor(dur.asDays()) % 365;
const remainingWeeks = Math.floor(dur.asWeeks());
let remainingHours = Math.floor(dur.asHours()) % 24;
let remainingMinutes = dur.minutes();
let remainingSecondsCount = dur.seconds();
const remainingMilliseconds = dur.milliseconds();
let amPm;
if (!use24Hours) {
amPm = remainingHours >= 12 ? "PM" : "AM";
remainingHours = remainingHours % 12 || 12;
}
if (padHours) {
remainingHours = remainingHours.toString().padStart(2, "0");
}
if (padMinutes) {
remainingMinutes = remainingMinutes.toString().padStart(2, "0");
}
if (padSeconds) {
remainingSecondsCount = remainingSecondsCount.toString().padStart(2, "0");
}
const isLeap = targetDateRef.current ? targetDateRef.current.isLeapYear() : false;
return {
year: remainingYears,
month: remainingMonths + 1,
day: remainingDays,
week: remainingWeeks,
isLeap,
hours: remainingHours,
minutes: remainingMinutes,
seconds: remainingSecondsCount,
milliseconds: remainingMilliseconds,
amPm,
isCompleted: false,
isRunning,
totalMilliseconds: remainingTime,
start,
pause,
reset,
resume
};
}
exports.useClockCountDown = useClockCountDown;
//# sourceMappingURL=use-clock-count-down.cjs.map