react-multi-timezone-viewer
Version:
271 lines (269 loc) • 10.9 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.tsx
var index_exports = {};
__export(index_exports, {
MultiTimezoneViewer: () => multi_timezone_viewer_default
});
module.exports = __toCommonJS(index_exports);
// src/multi-timezone-viewer.tsx
var import_react = require("react");
var import_luxon = require("luxon");
var import_tzdb = require("@vvo/tzdb");
var import_jsx_runtime = require("react/jsx-runtime");
var STORAGE_KEY = "multi_tz_zones";
var allTimezones = import_tzdb.timeZonesNames.map((tz) => {
const now = import_luxon.DateTime.now().setZone(tz);
const offset = now.offset / 60;
const sign = offset >= 0 ? "+" : "-";
const offsetHours = Math.floor(Math.abs(offset));
const offsetMinutes = Math.abs(now.offset % 60);
return {
label: `${tz} (UTC${sign}${offsetHours.toString().padStart(2, "0")}:${offsetMinutes.toString().padStart(2, "0")})`,
value: tz,
offset
};
}).sort((a, b) => a.offset - b.offset).map(({ label, value }) => ({ label, value }));
var getUserTimezones = () => {
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : [Intl.DateTimeFormat().resolvedOptions().timeZone];
};
var setUserTimezones = (zones) => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(zones));
};
var MultiTimezoneViewer = ({
datetime,
dateTimeZone,
useCrossSiteStorage = false,
customStyles = {}
}) => {
const baseTime = import_luxon.DateTime.fromFormat(datetime, "yyyy-MM-dd HH:mm:ss", {
zone: dateTimeZone
});
const [timezones, setTimezones] = (0, import_react.useState)([]);
const [showTooltip, setShowTooltip] = (0, import_react.useState)(false);
const [tooltipPos, setTooltipPos] = (0, import_react.useState)({ top: 0, left: 0 });
const [showDialog, setShowDialog] = (0, import_react.useState)(false);
const iframeRef = (0, import_react.useRef)(null);
const [hoveringText, setHoveringText] = (0, import_react.useState)(false);
const [hoveringTooltip, setHoveringTooltip] = (0, import_react.useState)(false);
(0, import_react.useEffect)(() => {
if (!hoveringText && !hoveringTooltip) {
const timeout = setTimeout(() => {
setShowTooltip(false);
}, 100);
return () => clearTimeout(timeout);
}
}, [hoveringText, hoveringTooltip]);
(0, import_react.useEffect)(() => {
if (useCrossSiteStorage) {
window.addEventListener("message", (e) => {
if (e.data?.type === "RETURN_TIMEZONES") {
setTimezones(e.data.zones);
}
});
const iframe = document.createElement("iframe");
iframe.src = "https://www.explisoft.com/npm/react-multi-timezone-viewer/script.html";
iframe.style.display = "none";
document.body.appendChild(iframe);
iframeRef.current = iframe;
iframe.onload = () => {
iframe.contentWindow?.postMessage("GET_TIMEZONES", "*");
};
} else {
setTimezones(getUserTimezones());
}
}, [useCrossSiteStorage]);
const handleSave = (zones) => {
setTimezones(zones);
if (useCrossSiteStorage && iframeRef.current) {
iframeRef.current.contentWindow?.postMessage({ type: "SET_TIMEZONES", zones }, "*");
} else {
setUserTimezones(zones);
}
};
const handleMouseEnter = (e) => {
const spacing = 10;
const tooltipWidth = 260;
const tooltipHeight = 200;
let left = e.clientX;
let top = e.clientY;
if (left + tooltipWidth > window.innerWidth) {
left = window.innerWidth - tooltipWidth - spacing;
}
if (top + tooltipHeight > window.innerHeight) {
top = window.innerHeight - tooltipHeight - spacing;
}
setTooltipPos({ top: top + window.scrollY + spacing, left: left + window.scrollX + spacing });
setShowTooltip(true);
};
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"span",
{
onMouseEnter: (e) => {
setHoveringText(true);
handleMouseEnter(e);
},
onMouseLeave: () => setHoveringText(false),
style: { display: "inline", cursor: "pointer", textDecoration: "none", ...customStyles.container },
children: baseTime.toFormat("ff")
}
),
showTooltip && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"div",
{
onMouseEnter: () => setHoveringTooltip(true),
onMouseLeave: () => setHoveringTooltip(false),
style: {
position: "absolute",
top: tooltipPos.top,
left: tooltipPos.left,
background: "#fff",
border: "1px solid #ccc",
padding: "10px",
borderRadius: "4px",
zIndex: 1e3,
boxShadow: "0 4px 8px rgba(0,0,0,0.1)",
maxWidth: "400px",
maxHeight: "300px",
overflowY: "auto",
textAlign: "left",
...customStyles.tooltip
},
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"div",
{
style: {
display: "flex",
justifyContent: "space-between",
marginBottom: "8px",
fontWeight: "bold",
...customStyles.tooltipHeader
},
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "\u{1F552} Timezones" }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"span",
{
style: { cursor: "pointer" },
onClick: () => {
setShowDialog(true);
setShowTooltip(false);
},
children: "\u2699\uFE0F"
}
)
]
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { style: { width: "100%", borderCollapse: "collapse" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: timezones.map((tz) => {
const time = baseTime.setZone(tz).toFormat("ff");
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { padding: "4px 8px", verticalAlign: "top", textAlign: "left" }, children: tz }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { padding: "4px 8px", verticalAlign: "top", textAlign: "left" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: time }) })
] }, tz);
}) }) }),
useCrossSiteStorage && iframeRef.current && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px", fontSize: "11px", color: "#888", textAlign: "right" }, children: [
"Powered by ",
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://www.explisoft.com", target: "_blank", rel: "noopener noreferrer", children: "explisoft.com" })
] })
]
}
),
showDialog && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
style: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
background: "rgba(0,0,0,0.3)",
zIndex: 100,
...customStyles.dialogOverlay
},
onClick: () => setShowDialog(false),
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"div",
{
onClick: (e) => e.stopPropagation(),
style: {
background: "#fff",
padding: "20px",
borderRadius: "8px",
width: "400px",
maxHeight: "80vh",
overflowY: "auto",
margin: "5% auto",
textAlign: "left",
position: "relative",
...customStyles.dialogBox
},
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"span",
{
onClick: () => setShowDialog(false),
style: { position: "absolute", top: 10, right: 15, cursor: "pointer" },
children: "\u274C"
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "Select Timezones" }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { margin: "10px 0" }, children: allTimezones.map((tz) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
"label",
{
style: { display: "block", marginBottom: "5px", fontSize: "14px", cursor: "pointer", ...customStyles.checkboxLabel },
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"input",
{
type: "checkbox",
checked: timezones.includes(tz.value),
onChange: (e) => {
const newZones = e.target.checked ? [...timezones, tz.value] : timezones.filter((z) => z !== tz.value);
handleSave(newZones);
}
}
),
" ",
tz.label
]
},
tz.value
)) }),
useCrossSiteStorage && iframeRef.current && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px", fontSize: "11px", color: "#888", textAlign: "right" }, children: [
"Powered by ",
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://www.explisoft.com", target: "_blank", rel: "noopener noreferrer", children: "explisoft.com" })
] })
]
}
)
}
)
] });
};
var multi_timezone_viewer_default = MultiTimezoneViewer;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
MultiTimezoneViewer
});
//# sourceMappingURL=index.js.map