UNPKG

vira

Version:

A simple and highly versatile design system using element-vir.

97 lines (95 loc) 3.05 kB
import { convertDuration, getNowInUtcTimezone, toRelativeString, } from 'date-vir'; import { css, html, nothing } from 'element-vir'; import { viraTheme } from '../styles/vira-color-theme.js'; import { defineViraElement } from '../util/define-vira-element.js'; import { formatAbsoluteTime, ViraAbsoluteTime } from './vira-absolute-time.element.js'; /** * Displays a date/time as a live, relative timestamp (for example `5 minutes ago`). The relative * string automatically updates over time. Optionally renders the absolute timestamp beneath the * relative string. * * @category Time * @category Elements * @see https://electrovir.github.io/vira/book/elements/vira-relative-time */ export const ViraRelativeTime = defineViraElement()({ tagName: 'vira-relative-time', styles: css ` :host { display: inline-flex; flex-direction: column; white-space: nowrap; } ${ViraAbsoluteTime} { font-size: 12px; color: ${viraTheme.colors['vira-grey-foreground-non-body'].foreground.value}; } `, state() { return { now: getNowInUtcTimezone(), timeoutId: undefined, }; }, init({ inputs, updateState }) { /** * Reschedule with a fresh timeout after each update so the delay always reflects the * current `updateInterval` input. */ function scheduleNextUpdate() { const updateInterval = inputs.updateInterval || { seconds: 5, }; updateState({ timeoutId: globalThis.setTimeout(() => { updateState({ now: getNowInUtcTimezone(), }); scheduleNextUpdate(); }, convertDuration(updateInterval, { milliseconds: true, }).milliseconds), }); } scheduleNextUpdate(); }, cleanup({ state, updateState }) { globalThis.clearTimeout(state.timeoutId); updateState({ timeoutId: undefined, }); }, render({ state, inputs }) { const relativeTime = toRelativeString({ start: state.now, end: inputs.time, }, { years: true, months: true, days: true, hours: true, minutes: true, seconds: true, }, { useOnlyLargestUnit: true, decimalCount: 0, }); return html ` <span title=${formatAbsoluteTime(inputs.time, { timezone: inputs.timezone, })} > ${relativeTime} </span> ${inputs.showAbsoluteTime ? html ` <${ViraAbsoluteTime.assign({ time: inputs.time, timezone: inputs.timezone, })}></${ViraAbsoluteTime}> ` : nothing} `; }, });