react-use-precision-timer
Version:
A versatile precision timer hook for React. Doubles as a stopwatch.
266 lines (265 loc) • 23.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UseTimerExample = void 0;
require("bootstrap/dist/css/bootstrap.css");
const React = __importStar(require("react"));
const react_bootstrap_1 = require("react-bootstrap");
const useTimer_1 = require("../hooks/useTimer");
const TimerRenderer_1 = require("./TimerRenderer");
function UseTimerExample({ initialDelay = 1000 }) {
const [delay, setDelay] = React.useState(initialDelay);
const [speedMultiplier, setSpeedMultiplier] = React.useState(1);
const [startTimeEnabled, setStartTimeEnabled] = React.useState(false);
const [startTime, setStartTime] = React.useState(Date.now());
const [callbackTime, setCallbackTime] = React.useState(-1);
const [overdueCallCount, setOverdueCallCount] = React.useState(0);
const [runOnce, setRunOnce] = React.useState(false);
const [fireOnStart, setFireOnStart] = React.useState(false);
const [startImmediately, setStartImmediately] = React.useState(true);
const [delayChanged, setDelayChanged] = React.useState(false);
const [renderRate, setRenderRate] = React.useState(10);
const callback = React.useCallback((overdueCount) => {
setCallbackTime(new Date().getTime());
setOverdueCallCount(overdueCount);
}, []);
const timer = (0, useTimer_1.useTimer)({
delay: isNaN(delay) ? 0 : delay,
runOnce,
fireOnStart,
startImmediately,
speedMultiplier,
}, callback);
const effectiveDelay = React.useMemo(() => timer.getEffectiveDelay(), [timer]);
// Automatically start or stop when the delay changes.
React.useEffect(() => {
if (delayChanged) {
setDelayChanged(false);
if (startImmediately) {
timer.start(startTimeEnabled ? startTime : undefined);
}
else {
timer.stop();
}
}
}, [delay, delayChanged, startImmediately, startTime, startTimeEnabled, timer]);
return (React.createElement("div", { className: "d-flex" },
React.createElement(react_bootstrap_1.Card, null,
React.createElement(react_bootstrap_1.Card.Body, { className: "d-flex flex-column align-items-center gap-2" },
React.createElement("div", { className: "d-flex flex-wrap justify-content-center gap-2" },
React.createElement(react_bootstrap_1.Card, { style: { minWidth: 300, maxWidth: 600 } },
React.createElement(react_bootstrap_1.Card.Header, null, "Timer Options"),
React.createElement(react_bootstrap_1.Card.Body, null,
React.createElement("div", { className: "d-flex align-items-center gap-2 mb-3" },
"Delay:",
' ',
React.createElement(react_bootstrap_1.Form.Range, { min: "0", max: "5000", value: isNaN(delay) ? 0 : delay, onChange: (e) => {
const newDelay = parseInt(e.target.value);
setDelay(newDelay);
setDelayChanged(true);
if (newDelay === 0) {
setCallbackTime(-1);
setOverdueCallCount(0);
}
} }),
' ',
React.createElement(react_bootstrap_1.Form.Control, { type: "number", min: 0, value: delay, onChange: (e) => {
const newDelay = parseInt(e.target.value);
setDelay(newDelay);
setDelayChanged(true);
if (newDelay === 0) {
setCallbackTime(-1);
setOverdueCallCount(0);
}
}, style: { width: 80 } }),
"ms"),
React.createElement("div", { className: "d-flex flex-wrap align-items-start gap-1 mb-3" },
React.createElement(react_bootstrap_1.Form.Check, { inline: true, label: "Use start time:", id: "start-time-checkbox", name: "startTimeEnabled", checked: startTimeEnabled, onChange: (e) => {
setStartTimeEnabled(e.target.checked);
} }),
React.createElement("div", null,
React.createElement(react_bootstrap_1.Form.Control, { type: "number", min: "0", value: startTime, onChange: (e) => {
const newVal = parseInt(e.target.value);
setStartTime(newVal);
}, style: { width: 180 } }),
React.createElement("div", null,
React.createElement(react_bootstrap_1.Form.Text, { className: "text-muted" }, "(Unix timestamp in millis)")))),
React.createElement("div", { className: "d-flex flex-wrap justify-content-center gap-1 mb-3" },
React.createElement(react_bootstrap_1.Form.Check, { inline: true, label: "runOnce", id: "runOnce", name: "runOnce", checked: runOnce, onChange: (e) => setRunOnce(e.target.checked) }),
React.createElement(react_bootstrap_1.Form.Check, { inline: true, label: "fireOnStart", id: "fireOnStart", name: "fireOnStart", checked: fireOnStart, onChange: (e) => setFireOnStart(e.target.checked) }),
React.createElement(react_bootstrap_1.Form.Check, { inline: true, label: "startImmediately", id: "startImmediately", name: "startImmediately", checked: startImmediately, onChange: (e) => setStartImmediately(e.target.checked) })),
React.createElement("div", { className: "d-flex flex-column" },
React.createElement("div", null, "Speed multiplier:"),
React.createElement("div", { className: "d-flex align-items-center gap-2" },
React.createElement(react_bootstrap_1.Form.Range, { min: 0, max: 5, step: 0.25, value: isNaN(speedMultiplier) ? 1 : speedMultiplier, onChange: (e) => {
const newSpeed = parseFloat(e.target.value);
setSpeedMultiplier(newSpeed);
setDelayChanged(true);
} }),
' ',
React.createElement("div", { className: "d-flex align-items-center gap-1" },
"\u00D7",
React.createElement(react_bootstrap_1.Form.Control, { type: "number", min: 0, step: 0.25, value: isNaN(speedMultiplier) ? 1 : speedMultiplier, onChange: (e) => {
const newSpeed = parseFloat(e.target.value);
setSpeedMultiplier(newSpeed);
setDelayChanged(true);
}, style: { width: 80 } }))),
speedMultiplier !== 1 && (React.createElement("div", null,
React.createElement(react_bootstrap_1.Form.Text, { className: "text-muted" },
"Effective delay: ",
effectiveDelay,
" ms")))))),
React.createElement(react_bootstrap_1.Card, null,
React.createElement(react_bootstrap_1.Card.Body, { className: "d-flex flex-column justify-content-center align-items-center" },
React.createElement("div", { className: "text-center" },
"Render every:",
React.createElement("br", null),
renderRate,
" ms"),
React.createElement("div", null,
React.createElement(react_bootstrap_1.Form.Range, { min: "1", max: "5000", value: renderRate, onChange: (e) => {
setRenderRate(parseInt(e.target.value));
} }))))),
React.createElement(react_bootstrap_1.Card, { style: { minWidth: 300, maxWidth: 600 } },
React.createElement(react_bootstrap_1.Card.Body, null,
React.createElement("div", { className: "d-flex gap-1 justify-content-center" },
React.createElement(react_bootstrap_1.Button, { variant: timer.isStopped() ? 'primary' : 'outline-dark', onClick: () => {
timer.start(startTimeEnabled ? startTime : undefined);
} }, "Start"),
React.createElement(react_bootstrap_1.Button, { variant: timer.isStarted() ? 'primary' : 'outline-dark', onClick: () => {
timer.stop();
} }, "Stop"),
React.createElement(react_bootstrap_1.Button, { variant: timer.isRunning() ? 'primary' : 'outline-dark', onClick: () => {
timer.pause();
} }, "Pause"),
React.createElement(react_bootstrap_1.Button, { variant: timer.isPaused() ? 'primary' : 'outline-dark', onClick: () => {
timer.resume();
} }, "Resume")))),
React.createElement("div", { className: "d-flex justify-content-center", style: { minWidth: 300, maxWidth: 600 } },
React.createElement(react_bootstrap_1.Table, { striped: true, bordered: true, responsive: true, className: "w-100" },
React.createElement("tbody", null,
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "Callback time:"),
React.createElement("td", { style: { minWidth: 200 } },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement("div", { className: "mb-2" },
React.createElement("style", null, `.progress-bar {
-webkit-transition: none !important;
-moz-transition: none !important;
-ms-transition: none !important;
-o-transition: none !important;
transition: none !important;
}`),
effectiveDelay > 0 && (React.createElement(react_bootstrap_1.ProgressBar, { variant: "primary", now: t.isStopped() ? 0 : effectiveDelay - t.getRemainingTime(), max: effectiveDelay, label: `${effectiveDelay - t.getRemainingTime()} ms`, style: { transition: 'none' } })),
(isNaN(effectiveDelay) || effectiveDelay === 0) && (React.createElement(react_bootstrap_1.Badge, { className: "fw-bold m-0" }, "Stopwatch")))) }),
React.createElement("div", null,
React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, callbackTime)))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "isStarted():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: t.isStarted() ? 'success' : 'danger', className: "font-monospace" }, t.isStarted() + '')) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "isStopped():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: t.isStopped() ? 'success' : 'danger', className: "font-monospace" }, t.isStopped() + '')) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "isPaused():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: t.isPaused() ? 'success' : 'danger', className: "font-monospace" }, t.isPaused() + '')) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "isRunning():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: t.isRunning() ? 'success' : 'danger', className: "font-monospace" }, t.isRunning() + '')) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getEffectiveDelay():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getEffectiveDelay(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getStartTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, t.getStartTime())) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getLastFireTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, t.getLastFireTime())) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getNextFireTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, t.getNextFireTime())) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getPauseTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, t.getPauseTime())) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getResumeTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, t.getResumeTime())) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getRemainingTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getRemainingTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getElapsedStartedTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getElapsedStartedTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getElapsedRunningTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getElapsedRunningTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getTotalElapsedPausedTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getTotalElapsedPausedTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getPeriodElapsedPausedTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getPeriodElapsedPausedTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "getElapsedResumedTime():"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "primary" },
t.getElapsedResumedTime(),
" ms")) }))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "Overdue call count (for delays under 10ms):"),
React.createElement("td", { className: "text-break" },
React.createElement(react_bootstrap_1.Badge, { pill: true, bg: "dark" }, overdueCallCount))),
React.createElement("tr", null,
React.createElement("td", { className: "text-break" }, "Render time:"),
React.createElement("td", { className: "text-break" },
React.createElement(TimerRenderer_1.TimerRenderer, { timer: timer, renderRate: renderRate, render: (t) => (React.createElement(react_bootstrap_1.Badge, { bg: "warning", className: "text-black" }, Date.now())) }))))))))));
}
exports.UseTimerExample = UseTimerExample;