UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

200 lines (199 loc) 6.34 kB
"use client"; import _extends from "@babel/runtime/helpers/esm/extends"; import "core-js/modules/es.string.replace.js"; import "core-js/modules/web.dom-collections.iterator.js"; import React, { useCallback, useContext, useEffect, useMemo, useState, useRef } from 'react'; import SharedContext from '../../shared/Context'; import { convertStringToDate } from '../date-picker/DatePickerCalc'; import { formatDate, getRelativeTime, getRelativeTimeNextUpdateMs, parseDuration, formatDuration, isValidDuration } from './DateFormatUtils'; import { format } from 'date-fns'; import classnames from 'classnames'; import { createSpacingClasses } from '../space/SpacingUtils'; import Tooltip from '../Tooltip'; import { createSkeletonClass, skeletonDOMAttributes } from '../skeleton/SkeletonHelper'; import { useTranslation } from '../../shared'; import { convertJsxToString } from '../../shared/component-helper'; function DateFormat(props) { const context = useContext(SharedContext); const { invalidDate } = useTranslation().DateFormat; const { value, children, locale: localeProp, dateStyle = 'long', skeleton, relativeTime = false } = props; const locale = localeProp || context.locale; const ref = useRef(); const date = useMemo(() => { return getDate({ value, children }); }, [value, children]); const durationValue = useMemo(() => { const durationString = String(value || children); if (!durationString || !isValidDuration(durationString)) { return; } return parseDuration(durationString); }, [value, children]); const getDuration = useCallback(dateStyle => { if (durationValue === undefined) { return; } return formatDuration(durationValue, locale, dateStyle, String(value || children)); }, [children, durationValue, locale, value]); const durationFormatted = useMemo(() => { return getDuration(dateStyle); }, [dateStyle, getDuration]); const durationFormattedFull = useMemo(() => { return getDuration('full'); }, [getDuration]); const attributes = useMemo(() => { const attrs = { className: classnames('dnb-date-format', createSpacingClasses(props), createSkeletonClass('font', skeleton, context)), lang: locale }; skeletonDOMAttributes(attrs, skeleton, context); return attrs; }, [props, skeleton, context, locale]); const getAbsoluteDateTime = useCallback(function () { let style = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'yyyy-MM-dd'; if (!date || isNaN(date.getTime())) { return; } return format(date, style); }, [date]); const getAbsoluteDateFormatted = useCallback(function () { let { options = { dateStyle } } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (!date || isNaN(date.getTime())) { return; } return formatDate(date, { locale, options }); }, [date, locale, dateStyle]); const [label, setLabel] = useState(() => { return relativeTime && date ? getRelativeTime(date, locale, undefined, dateStyle) : undefined; }); useEffect(() => { if (!relativeTime || !date) { return; } let timeoutId; const scheduleNextUpdate = () => { const delay = getRelativeTimeNextUpdateMs(date); timeoutId = setTimeout(() => { const next = getRelativeTime(date, locale, undefined, dateStyle); setLabel(prev => prev !== next ? next : prev); scheduleNextUpdate(); }, delay); }; setLabel(getRelativeTime(date, locale, undefined, dateStyle)); scheduleNextUpdate(); return () => { clearTimeout(timeoutId); }; }, [date, locale, relativeTime, dateStyle]); const hasValidDate = date && !isNaN(date.getTime()); if (durationValue !== undefined) { const originalDurationString = String(value || children); const hasAriaLabel = durationFormattedFull !== durationFormatted; return React.createElement("time", _extends({}, attributes, { dateTime: originalDurationString, "aria-label": hasAriaLabel ? durationFormattedFull : undefined }), React.createElement("span", { "aria-hidden": hasAriaLabel }, durationFormatted)); } if (relativeTime) { if (hasValidDate) { return React.createElement(React.Fragment, null, React.createElement("time", _extends({ dateTime: getAbsoluteDateTime('yyyy-MM-dd HH:mm:ss') }, attributes, { ref: ref }), label), React.createElement(Tooltip, { targetElement: ref, tooltip: getAbsoluteDateFormatted({ options: { dateStyle, timeStyle: 'short' } }) })); } return React.createElement("span", { className: "dnb-date-format" }, invalidDate.replace('{value}', getInvalidValue({ value, children }))); } if (!hasValidDate && !durationValue) { return React.createElement("span", { className: "dnb-date-format" }, invalidDate.replace('{value}', getInvalidValue({ value, children }))); } if (hasValidDate) { return React.createElement("time", _extends({ dateTime: getAbsoluteDateTime() }, attributes), getAbsoluteDateFormatted()); } return React.createElement("span", { className: "dnb-date-format" }, invalidDate.replace('{value}', getInvalidValue({ value, children }))); } function getDate(_ref) { let { value, children } = _ref; if (value) { if (typeof value === 'string' && isValidDuration(value)) { return; } if (typeof value === 'string') { return convertStringToDate(value); } if (value instanceof Date) { return value; } return convertStringToDate(String(value)); } const childrenValue = convertJsxToString(children); if (childrenValue && isValidDuration(childrenValue)) { return; } return convertStringToDate(childrenValue); } function getInvalidValue(_ref2) { let { value, children } = _ref2; if (value instanceof Date) { return value.toString(); } if (children !== undefined && value === undefined) { return String(children); } return String(value); } export default DateFormat; DateFormat._supportsSpacingProps = true; //# sourceMappingURL=DateFormat.js.map