@smitch/fluid
Version:
A lightweight, Tailwind-powered React/Next.js UI component library.
99 lines • 5.56 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from "react";
import { twMerge } from "tailwind-merge";
var layouts = {
column: "flex-col items-center",
"column-reverse": "flex-col-reverse items-center",
row: "flex-row items-center gap-2",
"row-reverse": "flex-row-reverse items-center gap-2",
};
var labelsizes = {
sm: "text-sm",
md: "text-base",
lg: "text-lg",
xl: "text-xl",
};
var Clock = function (_a) {
var _b;
var _c = _a.timezone, timezone = _c === void 0 ? "UTC" : _c, _d = _a.size, size = _d === void 0 ? 120 : _d, _e = _a.showSeconds, showSeconds = _e === void 0 ? false : _e, _f = _a.ticks, ticks = _f === void 0 ? false : _f, theme = _a.theme, _g = _a.layout, layout = _g === void 0 ? "column" : _g, _h = _a.showLabel, showLabel = _h === void 0 ? true : _h, _j = _a.clockFaceStroke, clockFaceStroke = _j === void 0 ? 4 : _j, _k = _a.labelSize, labelSize = _k === void 0 ? "md" : _k, _l = _a.className, className = _l === void 0 ? "" : _l;
var _m = useState(new Date()), time = _m[0], setTime = _m[1];
var _o = useState(""), city = _o[0], setCity = _o[1];
useEffect(function () {
if (!timezone)
setCity("");
else {
var parts = timezone.split("/");
if (parts.length > 1) {
setCity(parts[1].replace(/_/g, " "));
}
else {
setCity(timezone);
}
}
}, [timezone]);
useEffect(function () {
var timer = setInterval(function () {
setTime(new Date());
}, 1000);
return function () { return clearInterval(timer); };
}, []);
var layoutClass = layouts[layout] || "flex-col";
var labelClass = labelsizes[labelSize] || "text-base";
var hours = time.getHours();
var minutes = time.getMinutes();
var seconds = time.getSeconds();
var label = "";
if (timezone) {
var parts = new Intl.DateTimeFormat("en-US", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
timeZone: timezone,
timeZoneName: "short",
})
.formatToParts(time)
.reduce(function (acc, part) {
if (part.type === "hour")
acc.hour = parseInt(part.value, 10);
if (part.type === "minute")
acc.minute = parseInt(part.value, 10);
if (part.type === "second")
acc.second = parseInt(part.value, 10);
if (part.type === "timeZoneName")
acc.label = part.value;
return acc;
}, {});
hours = parts.hour;
minutes = parts.minute;
seconds = parts.second;
label = parts.label;
}
else {
label =
((_b = Intl.DateTimeFormat(undefined, { timeZoneName: "short" })
.formatToParts(time)
.find(function (part) { return part.type === "timeZoneName"; })) === null || _b === void 0 ? void 0 : _b.value) || "";
}
var hourAngle = ((hours % 12) + minutes / 60) * 30;
var minuteAngle = (minutes + seconds / 60) * 6;
var secondAngle = seconds * 6;
var ariaTime = time.toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
second: showSeconds ? "2-digit" : undefined,
hour12: false,
timeZone: timezone,
});
return (_jsxs("div", { "data-testid": "clock", "aria-label": "Analog clock showing ".concat(ariaTime, " in ").concat(city || label), className: twMerge("clock flex group ".concat(layoutClass, " space-y-4"), className), children: [_jsxs("svg", { width: size, height: size, viewBox: "0 0 120 120", "aria-hidden": "true", className: "clock_face", children: [_jsx("circle", { cx: 60, cy: 60, r: 55, fill: theme === "dark" ? "#222" : "#fff", stroke: theme === "dark" ? "#fff" : "#222", strokeWidth: clockFaceStroke }), ticks &&
Array.from({ length: 12 }).map(function (_, i) {
var angle = i * 30 * (Math.PI / 180);
var x1 = 60 + 48 * Math.sin(angle);
var y1 = 60 - 48 * Math.cos(angle);
var x2 = 60 + 54 * Math.sin(angle);
var y2 = 60 - 54 * Math.cos(angle);
return (_jsx("line", { x1: x1, y1: y1, x2: x2, y2: y2, stroke: theme === "dark" ? "#fff" : "#222", strokeWidth: 3, strokeLinecap: "round" }, i));
}), showSeconds && (_jsx("line", { x1: 60, y1: 60, x2: 60 + 45 * Math.sin((Math.PI / 180) * secondAngle), y2: 60 - 45 * Math.cos((Math.PI / 180) * secondAngle), stroke: theme === "dark" ? "#fff" : "#222", strokeWidth: 2, strokeLinecap: "round", opacity: 0.5 })), _jsx("line", { x1: 60, y1: 60, x2: 60 + 40 * Math.sin((Math.PI / 180) * minuteAngle), y2: 60 - 40 * Math.cos((Math.PI / 180) * minuteAngle), stroke: theme === "dark" ? "#fff" : "#222", strokeWidth: 3, strokeLinecap: "round" }), _jsx("line", { x1: 60, y1: 60, x2: 60 + 25 * Math.sin((Math.PI / 180) * hourAngle), y2: 60 - 25 * Math.cos((Math.PI / 180) * hourAngle), stroke: theme === "dark" ? "#fff" : "#222", strokeWidth: 5, strokeLinecap: "round" }), _jsx("circle", { cx: 60, cy: 60, r: 4, fill: theme === "dark" ? "#fff" : "#222" })] }), showLabel && _jsx("div", { className: "clock_label ".concat(labelClass), children: city || label || timezone })] }));
};
export default Clock;
//# sourceMappingURL=Clock.js.map