UNPKG

@base-ui/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

356 lines (352 loc) 11.3 kB
'use client'; import { addDays } from 'date-fns/addDays'; import { addHours } from 'date-fns/addHours'; import { addMinutes } from 'date-fns/addMinutes'; import { addMonths } from 'date-fns/addMonths'; import { addSeconds } from 'date-fns/addSeconds'; import { addMilliseconds } from 'date-fns/addMilliseconds'; import { addWeeks } from 'date-fns/addWeeks'; import { addYears } from 'date-fns/addYears'; import { differenceInDays } from 'date-fns/differenceInDays'; import { differenceInHours } from 'date-fns/differenceInHours'; import { differenceInMinutes } from 'date-fns/differenceInMinutes'; import { differenceInMonths } from 'date-fns/differenceInMonths'; import { differenceInWeeks } from 'date-fns/differenceInWeeks'; import { differenceInYears } from 'date-fns/differenceInYears'; import { endOfDay } from 'date-fns/endOfDay'; import { endOfHour } from 'date-fns/endOfHour'; import { endOfMinute } from 'date-fns/endOfMinute'; import { endOfMonth } from 'date-fns/endOfMonth'; import { endOfSecond } from 'date-fns/endOfSecond'; import { endOfWeek } from 'date-fns/endOfWeek'; import { endOfYear } from 'date-fns/endOfYear'; import { format as dateFnsFormat } from 'date-fns/format'; import { getDate } from 'date-fns/getDate'; import { getDay } from 'date-fns/getDay'; import { getDaysInMonth } from 'date-fns/getDaysInMonth'; import { getHours } from 'date-fns/getHours'; import { getMilliseconds } from 'date-fns/getMilliseconds'; import { getMinutes } from 'date-fns/getMinutes'; import { getMonth } from 'date-fns/getMonth'; import { getSeconds } from 'date-fns/getSeconds'; import { getWeek } from 'date-fns/getWeek'; import { getYear } from 'date-fns/getYear'; import { isAfter } from 'date-fns/isAfter'; import { isBefore } from 'date-fns/isBefore'; import { isEqual } from 'date-fns/isEqual'; import { isSameDay } from 'date-fns/isSameDay'; import { isSameHour } from 'date-fns/isSameHour'; import { isSameYear } from 'date-fns/isSameYear'; import { isSameMonth } from 'date-fns/isSameMonth'; import { isValid } from 'date-fns/isValid'; import { isWithinInterval } from 'date-fns/isWithinInterval'; import { enUS } from 'date-fns/locale/en-US'; import { parse } from 'date-fns/parse'; import { setDate } from 'date-fns/setDate'; import { setHours } from 'date-fns/setHours'; import { setMilliseconds } from 'date-fns/setMilliseconds'; import { setMinutes } from 'date-fns/setMinutes'; import { setMonth } from 'date-fns/setMonth'; import { setSeconds } from 'date-fns/setSeconds'; import { setYear } from 'date-fns/setYear'; import { startOfDay } from 'date-fns/startOfDay'; import { startOfHour } from 'date-fns/startOfHour'; import { startOfMinute } from 'date-fns/startOfMinute'; import { startOfMonth } from 'date-fns/startOfMonth'; import { startOfSecond } from 'date-fns/startOfSecond'; import { startOfYear } from 'date-fns/startOfYear'; import { startOfWeek } from 'date-fns/startOfWeek'; import { TZDate } from '@date-fns/tz'; const FORMATS = { // Digit formats with leading zeroes yearPadded: 'yyyy', monthPadded: 'MM', dayOfMonthPadded: 'dd', hours24hPadded: 'HH', hours12hPadded: 'hh', minutesPadded: 'mm', secondsPadded: 'ss', // Digit formats without leading zeroes dayOfMonth: 'd', hours24h: 'H', hours12h: 'h', // Letter formats month3Letters: 'MMM', monthFullLetter: 'MMMM', weekday: 'EEEE', weekday3Letters: 'EEE', weekday1Letter: 'EEEEE', meridiem: 'a', // Full formats localizedDateWithFullMonthAndWeekDay: 'PPPP', localizedNumericDate: 'P' // Note: Day and month are padded on enUS unlike Luxon }; export class TemporalAdapterDateFns { isTimezoneCompatible = true; lib = 'date-fns'; formats = FORMATS; escapedCharacters = { start: "'", end: "'" }; constructor({ locale } = {}) { this.locale = locale ?? enUS; } now = timezone => { if (timezone === 'system' || timezone === 'default') { return new Date(); } return TZDate.tz(timezone); }; date = (value, timezone) => { if (value === null) { return null; } const date = new Date(value); // Date-only strings (e.g. "2026-04-06") are parsed as UTC midnight by the JS spec, // so we must use UTC getters to extract the intended face-value components. // Datetime strings (e.g. "2026-04-06T14:30") are parsed as local time, // so local getters correctly return the face-value components. const isDateOnly = typeof value === 'string' && !value.includes('T'); if (timezone === 'system' || timezone === 'default') { if (isDateOnly) { return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()); } return date; } // `new TZDate(value, timezone)` returns a date with the same timestamp `new Date(value)` would return, // whereas we want to create a date that represents the string in the given timezone. return new TZDate(isDateOnly ? date.getUTCFullYear() : date.getFullYear(), isDateOnly ? date.getUTCMonth() : date.getMonth(), isDateOnly ? date.getUTCDate() : date.getDate(), isDateOnly ? date.getUTCHours() : date.getHours(), isDateOnly ? date.getUTCMinutes() : date.getMinutes(), isDateOnly ? date.getUTCSeconds() : date.getSeconds(), isDateOnly ? date.getUTCMilliseconds() : date.getMilliseconds(), timezone); }; parse = (value, format, timezone) => { const date = parse(value, format, new Date(), { locale: this.locale }); if (timezone === 'system' || timezone === 'default') { return date; } // `new TZDate(value, timezone)` returns a date with the same timestamp `new Date(value)` would return, // whereas we want to create that represents the string in the given timezone. return new TZDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds(), timezone); }; getTimezone = value => { if (value instanceof TZDate) { return value.timeZone ?? 'system'; } return 'system'; }; setTimezone = (value, timezone) => { const isSystemTimezone = timezone === 'system' || timezone === 'default'; const canChangeTz = typeof value?.withTimeZone === 'function'; if (isSystemTimezone) { return this.toJsDate(value); } if (canChangeTz) { return value.withTimeZone(timezone); } return new TZDate(value, timezone); }; toJsDate = value => { if (value instanceof TZDate) { return new Date(value.getTime()); } return value; }; getCurrentLocaleCode = () => { return this.locale.code; }; isValid = value => { if (value == null) { return false; } return isValid(value); }; format = (value, formatKey) => { return this.formatByString(value, this.formats[formatKey]); }; formatByString = (value, format) => { return dateFnsFormat(value, format, { locale: this.locale }); }; isEqual = (value, comparing) => { if (value === null && comparing === null) { return true; } if (value === null || comparing === null) { return false; } return isEqual(value, comparing); }; isSameYear = (value, comparing) => { return isSameYear(value, comparing); }; isSameMonth = (value, comparing) => { return isSameMonth(value, comparing); }; isSameDay = (value, comparing) => { return isSameDay(value, comparing); }; isSameHour = (value, comparing) => { return isSameHour(value, comparing); }; isAfter = (value, comparing) => { return isAfter(value, comparing); }; isBefore = (value, comparing) => { return isBefore(value, comparing); }; isWithinRange = (value, [start, end]) => { return isWithinInterval(value, { start, end }); }; startOfYear = value => { return startOfYear(value); }; startOfMonth = value => { return startOfMonth(value); }; startOfWeek = value => { return startOfWeek(value, { locale: this.locale }); }; startOfDay = value => { return startOfDay(value); }; startOfHour = value => { return startOfHour(value); }; startOfMinute = value => { return startOfMinute(value); }; startOfSecond = value => { return startOfSecond(value); }; endOfYear = value => { return endOfYear(value); }; endOfMonth = value => { return endOfMonth(value); }; endOfWeek = value => { return endOfWeek(value, { locale: this.locale }); }; endOfDay = value => { return endOfDay(value); }; endOfHour = value => { return endOfHour(value); }; endOfMinute = value => { return endOfMinute(value); }; endOfSecond = value => { return endOfSecond(value); }; addYears = (value, amount) => { return addYears(value, amount); }; addMonths = (value, amount) => { return addMonths(value, amount); }; addWeeks = (value, amount) => { return addWeeks(value, amount); }; addDays = (value, amount) => { return addDays(value, amount); }; addHours = (value, amount) => { return addHours(value, amount); }; addMinutes = (value, amount) => { return addMinutes(value, amount); }; addSeconds = (value, amount) => { return addSeconds(value, amount); }; addMilliseconds = (value, amount) => { return addMilliseconds(value, amount); }; getYear = value => { return getYear(value); }; getMonth = value => { return getMonth(value); }; getDate = value => { return getDate(value); }; getHours = value => { return getHours(value); }; getMinutes = value => { return getMinutes(value); }; getSeconds = value => { return getSeconds(value); }; getMilliseconds = value => { return getMilliseconds(value); }; getTime = value => { return value.getTime(); }; setYear = (value, year) => { return setYear(value, year); }; setMonth = (value, month) => { return setMonth(value, month); }; setDate = (value, date) => { return setDate(value, date); }; setHours = (value, hours) => { return setHours(value, hours); }; setMinutes = (value, minutes) => { return setMinutes(value, minutes); }; setSeconds = (value, seconds) => { return setSeconds(value, seconds); }; setMilliseconds = (value, milliseconds) => { return setMilliseconds(value, milliseconds); }; differenceInYears = (value, comparing) => { return differenceInYears(value, comparing); }; differenceInMonths = (value, comparing) => { return differenceInMonths(value, comparing); }; differenceInWeeks = (value, comparing) => { return differenceInWeeks(value, comparing); }; differenceInDays = (value, comparing) => { return differenceInDays(value, comparing); }; differenceInHours = (value, comparing) => { return differenceInHours(value, comparing); }; differenceInMinutes = (value, comparing) => { return differenceInMinutes(value, comparing); }; getDaysInMonth = value => { return getDaysInMonth(value); }; getWeekNumber = value => { return getWeek(value, { locale: this.locale }); }; getDayOfWeek = value => { const weekStartsOn = this.locale.options?.weekStartsOn ?? 0; return (getDay(value) + 7 - weekStartsOn) % 7 + 1; }; }