UNPKG

@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.

197 lines (193 loc) 5.58 kB
"use client"; import { jsx } from 'react/jsx-runtime'; import { Slot } from '@radix-ui/react-slot'; import { forwardRef, useMemo } from 'react'; import { numberFormat } from '../utils/intl.js'; import { useInterval } from '../utils/use-interval.js'; import { useRerender } from '../utils/use-rerender.js'; 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 = 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 = numberFormat(resolvedLocale, { style: "unit", unit: durationPartsToNumberFormatOptions[unit], unitDisplay: "narrow" }); formattedParts.push(formatter.format(value)); } if (!formattedParts.length) { formattedParts.push( 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 = 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 = numberFormat(resolvedLocale, { style: "unit", unit: durationPartsToNumberFormatOptions[unit], unitDisplay: "long" }); formattedParts.push(formatter.format(value)); } if (!formattedParts.length) { formattedParts.push( 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 = forwardRef( ({ duration, from, to, locale, dateTime, title: renderTitle = formatVerboseDuration, children: renderChildren = formatShortDuration, interval = RENDER_INTERVAL, asChild, ...props }, forwardedRef) => { const Component = asChild ? Slot : "time"; const [rerender, key] = useRerender(); const resolvedDuration = 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 = useMemo( () => formatIso8601Duration(resolvedDuration), [resolvedDuration] ); const title = useMemo( () => typeof renderTitle === "function" ? renderTitle(resolvedDuration, locale) : renderTitle, // eslint-disable-next-line react-hooks/exhaustive-deps [renderTitle, resolvedDuration, locale] ); const children = useMemo( () => typeof renderChildren === "function" ? renderChildren(resolvedDuration, locale) : renderChildren, [renderChildren, resolvedDuration, locale] ); useInterval( rerender, from !== void 0 && to === void 0 ? interval : false ); return /* @__PURE__ */ jsx( Component, { ...props, ref: forwardedRef, dateTime: dateTime ?? normalizedDuration, title, children } ); } ); if (process.env.NODE_ENV !== "production") { Duration.displayName = DURATION_NAME; } export { Duration, formatIso8601Duration, getDuration }; //# sourceMappingURL=Duration.js.map