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.

125 lines (120 loc) 3.67 kB
"use client"; 'use strict'; var jsxRuntime = require('react/jsx-runtime'); var reactSlot = require('@radix-ui/react-slot'); var react = require('react'); var capitalize = require('../utils/capitalize.cjs'); var intl = require('../utils/intl.cjs'); var useInterval = require('../utils/use-interval.cjs'); var useRerender = require('../utils/use-rerender.cjs'); const DYNAMIC_DATE_THRESHOLD = 3 * 24 * 60 * 60 * 1e3; const RENDER_INTERVAL = 30 * 1e3; const TIMESTAMP_NAME = "Timestamp"; const relativeUnits = { seconds: 60, minutes: 60, hours: 24, days: 7, weeks: 4.34524, months: 12 }; function formatVerboseDate(date, locale) { const formatter = intl.dateTimeFormat(locale, { year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric" }); return capitalize.capitalize(formatter.format(date)); } function formatShortDate(date, locale) { const formatter = intl.dateTimeFormat(locale, { month: "short", day: "numeric" }); return capitalize.capitalize(formatter.format(date)); } const localesWithBrokenNarrowRelativeFormatting = [ "br", "fr", "nb", "nn", "no", "ro", "sv" ]; function formatRelativeDate(date, locale) { let resolvedLocale; if (locale) { resolvedLocale = locale; } else { const formatter2 = intl.relativeTimeFormat(); resolvedLocale = formatter2.resolvedOptions().locale; } const isBrokenWhenNarrow = localesWithBrokenNarrowRelativeFormatting.some( (locale2) => resolvedLocale === locale2 || resolvedLocale.startsWith(`${locale2}-`) ); const formatter = intl.relativeTimeFormat(resolvedLocale, { style: isBrokenWhenNarrow ? "short" : "narrow", numeric: "auto" }); let difference = (date.getTime() - Date.now()) / 1e3; if (difference > -relativeUnits.seconds && difference < relativeUnits.seconds) { return formatter.format(0, "seconds"); } for (const [unit, length] of Object.entries(relativeUnits)) { if (Math.abs(difference) < length) { return formatter.format( Math.round(difference), unit ); } difference /= length; } return capitalize.capitalize(formatter.format(Math.round(difference), "years")); } function formatDynamicDate(date, locale) { return date.getTime() > Date.now() - DYNAMIC_DATE_THRESHOLD ? formatRelativeDate(date, locale) : formatShortDate(date, locale); } const Timestamp = react.forwardRef( ({ date, locale, children: renderChildren = formatDynamicDate, title: renderTitle = formatVerboseDate, dateTime, interval = RENDER_INTERVAL, asChild, ...props }, forwardedRef) => { const Component = asChild ? reactSlot.Slot : "time"; const [rerender, key] = useRerender.useRerender(); const parsedDate = react.useMemo(() => new Date(date), [date]); const normalizedDate = react.useMemo( () => parsedDate.toISOString(), [parsedDate] ); const title = react.useMemo( () => typeof renderTitle === "function" ? renderTitle(parsedDate, locale) : renderTitle, [renderTitle, parsedDate, key] ); const children = react.useMemo( () => typeof renderChildren === "function" ? renderChildren(parsedDate, locale) : renderChildren, [renderChildren, parsedDate, key] ); useInterval.useInterval(rerender, interval); return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props, ref: forwardedRef, dateTime: dateTime ?? normalizedDate, title, children }); } ); if (process.env.NODE_ENV !== "production") { Timestamp.displayName = TIMESTAMP_NAME; } exports.Timestamp = Timestamp; //# sourceMappingURL=Timestamp.cjs.map