@liveblocks/react-ui
Version:
A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.
201 lines (196 loc) • 5.75 kB
JavaScript
"use client";
;
var jsxRuntime = require('react/jsx-runtime');
var reactSlot = require('@radix-ui/react-slot');
var react = require('react');
var intl = require('../utils/intl.cjs');
var useInterval = require('../utils/use-interval.cjs');
var useRerender = require('../utils/use-rerender.cjs');
const RENDER_INTERVAL = 0.5 * 1e3;
const DURATION_NAME = "Duration";
function getDurationParts(duration) {
let remaining = Math.max(duration, 0);
const milliseconds = remaining % 1e3;
remaining = Math.floor(remaining / 1e3);
const seconds = remaining % 60;
remaining = Math.floor(remaining / 60);
const minutes = remaining % 60;
remaining = Math.floor(remaining / 60);
const hours = remaining % 24;
remaining = Math.floor(remaining / 24);
const days = remaining % 7;
const weeks = Math.floor(remaining / 7);
return { weeks, days, hours, minutes, seconds, milliseconds };
}
const durationPartsToNumberFormatOptions = {
weeks: "week",
days: "day",
hours: "hour",
minutes: "minute",
seconds: "second",
milliseconds: "millisecond"
};
function formatShortDuration(duration, locale) {
let resolvedLocale;
if (locale) {
resolvedLocale = locale;
} else {
const formatter = intl.numberFormat();
resolvedLocale = formatter.resolvedOptions().locale;
}
const parts = getDurationParts(duration);
const formattedParts = [];
for (const [unit, value] of Object.entries(parts)) {
if (value === 0 || unit === "milliseconds") {
continue;
}
const formatter = intl.numberFormat(resolvedLocale, {
style: "unit",
unit: durationPartsToNumberFormatOptions[unit],
unitDisplay: "narrow"
});
formattedParts.push(formatter.format(value));
}
if (!formattedParts.length) {
formattedParts.push(
intl.numberFormat(resolvedLocale, {
style: "unit",
unit: "second",
unitDisplay: "narrow"
}).format(0)
);
}
return formattedParts.join(" ");
}
function formatVerboseDuration(duration, locale) {
let resolvedLocale;
if (locale) {
resolvedLocale = locale;
} else {
const formatter = intl.numberFormat();
resolvedLocale = formatter.resolvedOptions().locale;
}
const parts = getDurationParts(duration);
const formattedParts = [];
for (const [unit, value] of Object.entries(parts)) {
if (value === 0 || unit === "milliseconds") {
continue;
}
const formatter = intl.numberFormat(resolvedLocale, {
style: "unit",
unit: durationPartsToNumberFormatOptions[unit],
unitDisplay: "long"
});
formattedParts.push(formatter.format(value));
}
if (!formattedParts.length) {
formattedParts.push(
intl.numberFormat(resolvedLocale, {
style: "unit",
unit: "second",
unitDisplay: "long"
}).format(0)
);
}
return formattedParts.join(" ");
}
function formatIso8601Duration(duration) {
const normalizedDuration = Math.max(duration, 0);
if (normalizedDuration === 0) {
return "PT0S";
}
const { weeks, days, hours, minutes, seconds, milliseconds } = getDurationParts(normalizedDuration);
let isoDuration = "P";
if (weeks > 0) {
isoDuration += `${weeks}W`;
}
if (days > 0) {
isoDuration += `${days}D`;
}
if (hours > 0 || minutes > 0 || seconds > 0 || milliseconds > 0) {
isoDuration += "T";
if (hours > 0) {
isoDuration += `${hours}H`;
}
if (minutes > 0) {
isoDuration += `${minutes}M`;
}
if (seconds > 0 || milliseconds > 0) {
if (milliseconds > 0) {
isoDuration += `${seconds}.${milliseconds.toString().padStart(3, "0").replace(/0+$/, "")}S`;
} else {
isoDuration += `${seconds}S`;
}
}
}
return isoDuration;
}
function getDateTime(date) {
if (date instanceof Date) {
return date.getTime();
}
return new Date(date).getTime();
}
function getDuration(from, to) {
return getDateTime(to) - getDateTime(from);
}
const Duration = react.forwardRef(
({
duration,
from,
to,
locale,
dateTime,
title: renderTitle = formatVerboseDuration,
children: renderChildren = formatShortDuration,
interval = RENDER_INTERVAL,
asChild,
...props
}, forwardedRef) => {
const Component = asChild ? reactSlot.Slot : "time";
const [rerender, key] = useRerender.useRerender();
const resolvedDuration = react.useMemo(() => {
if (duration !== void 0) {
return duration;
}
if (from !== void 0) {
return getDuration(from, to ?? Date.now());
}
return 0;
}, [duration, from, to, key]);
const normalizedDuration = react.useMemo(
() => formatIso8601Duration(resolvedDuration),
[resolvedDuration]
);
const title = react.useMemo(
() => typeof renderTitle === "function" ? renderTitle(resolvedDuration, locale) : renderTitle,
// eslint-disable-next-line react-hooks/exhaustive-deps
[renderTitle, resolvedDuration, locale]
);
const children = react.useMemo(
() => typeof renderChildren === "function" ? renderChildren(resolvedDuration, locale) : renderChildren,
[renderChildren, resolvedDuration, locale]
);
useInterval.useInterval(
rerender,
from !== void 0 && to === void 0 ? interval : false
);
return /* @__PURE__ */ jsxRuntime.jsx(
Component,
{
...props,
ref: forwardedRef,
dateTime: dateTime ?? normalizedDuration,
title,
children
}
);
}
);
if (process.env.NODE_ENV !== "production") {
Duration.displayName = DURATION_NAME;
}
exports.Duration = Duration;
exports.formatIso8601Duration = formatIso8601Duration;
exports.getDuration = getDuration;
//# sourceMappingURL=Duration.cjs.map