refactor(api): tidy the api and shared packages (#2733)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-13 17:37:48 +02:00
1 parent 580401d2dc
commit 5afbf67a70
333 files changed
+10180 -7910

No files matched your search

+13 -13
View File
@@ -28,28 +28,28 @@ export function formatDuration(seconds: number): string {
export function formatShortRelativeTime(timestamp: DateInput, minUnit: '1m' | 'now' = 'now'): string {
const date = parseDate(timestamp);
const now = new Date();
const diffMs = date.getTime() - now.getTime();
const diffMs = Math.abs(date.getTime() - now.getTime());
const diffSeconds = Math.floor(diffMs / 1000);
const diffMinutes = Math.floor(diffSeconds / SECONDS_PER_MINUTE);
const diffHours = Math.floor(diffMinutes / MINUTES_PER_HOUR);
const diffDays = Math.floor(diffHours / HOURS_PER_DAY);
if (Math.abs(diffSeconds) < SECONDS_PER_MINUTE) {
if (diffSeconds < SECONDS_PER_MINUTE) {
return minUnit === '1m' ? '1m' : 'now';
}
if (Math.abs(diffMinutes) < MINUTES_PER_HOUR) {
return `${Math.abs(diffMinutes)}m`;
if (diffMinutes < MINUTES_PER_HOUR) {
return `${diffMinutes}m`;
}
if (Math.abs(diffHours) < HOURS_PER_DAY) {
return `${Math.abs(diffHours)}h`;
if (diffHours < HOURS_PER_DAY) {
return `${diffHours}h`;
}
if (Math.abs(diffDays) < DAYS_PER_WEEK) {
return `${Math.abs(diffDays)}d`;
if (diffDays < DAYS_PER_WEEK) {
return `${diffDays}d`;
}
if (Math.abs(diffDays) < DAYS_PER_MONTH) {
return `${Math.floor(Math.abs(diffDays) / DAYS_PER_WEEK)}w`;
if (diffDays < DAYS_PER_MONTH) {
return `${Math.floor(diffDays / DAYS_PER_WEEK)}w`;
}
if (Math.abs(diffDays) < DAYS_PER_YEAR) {
return `${Math.floor(Math.abs(diffDays) / DAYS_PER_MONTH)}mo`;
if (diffDays < DAYS_PER_YEAR) {
return `${Math.floor(diffDays / DAYS_PER_MONTH)}mo`;
}
return `${Math.floor(Math.abs(diffDays) / DAYS_PER_YEAR)}y`;
return `${Math.floor(diffDays / DAYS_PER_YEAR)}y`;
}
+2 -21
View File
@@ -1,26 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
const TWELVE_HOUR_LOCALES = [
'en-us',
'en-ca',
'en-au',
'en-nz',
'en-ph',
'en-in',
'en-pk',
'en-bd',
'en-za',
'es-mx',
'es-co',
'ar',
'hi',
'bn',
'ur',
'fil',
'tl',
];
import {getDateFormatter} from '@fluxer/date_utils/src/DateFormatterCache';
export function localeUses12Hour(locale: string): boolean {
const lang = locale.toLowerCase();
return TWELVE_HOUR_LOCALES.some((l) => lang.startsWith(l));
return getDateFormatter(locale, {hour: 'numeric'}).resolvedOptions().hour12 === true;
}
+4 -7
View File
@@ -12,20 +12,17 @@ export function getDateFieldOrder(locale: string): Array<DateFieldType> {
const parts = formatter.formatToParts(new Date(2000, 0, 1));
const order: Array<DateFieldType> = [];
for (const part of parts) {
if (part.type === 'month' && !order.includes('month')) {
order.push('month');
} else if (part.type === 'day' && !order.includes('day')) {
order.push('day');
} else if (part.type === 'year' && !order.includes('year')) {
order.push('year');
if ((part.type === 'month' || part.type === 'day' || part.type === 'year') && !order.includes(part.type)) {
order.push(part.type);
}
}
return order;
}
export function getMonthNames(locale: string, format: 'long' | 'short' = 'long'): Array<string> {
const formatter = getDateFormatter(locale, {month: format});
return Array.from({length: 12}, (_, index) => {
const monthDate = new Date(2000, index, 1);
return getDateFormatter(locale, {month: format}).format(monthDate);
return formatter.format(monthDate);
});
}
+15 -21
View File
@@ -1,19 +1,9 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {getTimeZones, timeZonesNames} from '@vvo/tzdb';
import {getTimeZones, type TimeZone, timeZonesNames} from '@vvo/tzdb';
const UTC_TIME_ZONE_ID = 'UTC';
interface TimeZoneRecord {
readonly name: string;
readonly group: ReadonlyArray<string>;
readonly alternativeName?: string;
readonly countryName?: string;
readonly countryCode?: string;
readonly mainCities: ReadonlyArray<string>;
readonly currentTimeOffsetInMinutes: number;
}
interface TimeZoneDisplayOption {
readonly value: string;
readonly label: string;
@@ -28,17 +18,15 @@ function cleanTimeZoneId(timeZone: string | null | undefined): string | null {
return value ? value : null;
}
function getDisplayTimeZones(): Array<TimeZoneRecord> {
return getTimeZones({includeUtc: true});
function getDisplayTimeZones(): Array<TimeZone> {
return getTimeZones({includeUtc: true}).map((record) =>
record.group.includes(UTC_TIME_ZONE_ID) ? {...record, name: UTC_TIME_ZONE_ID} : record,
);
}
function findTimeZone(timeZone: string | null | undefined): TimeZoneRecord | null {
const value = cleanTimeZoneId(timeZone);
if (!value) {
return null;
}
function findTimeZone(timeZone: string): TimeZone | null {
for (const record of getDisplayTimeZones()) {
if (record.name === value || record.group.includes(value)) {
if (record.name === timeZone || record.group.includes(timeZone)) {
return record;
}
}
@@ -81,7 +69,13 @@ export function isSupportedTimeZoneId(timeZone: string | null | undefined): bool
}
export function getCurrentTimeZoneOffsetMinutes(timeZone: string | null | undefined): number | null {
const record = findTimeZone(timeZone);
const value = cleanTimeZoneId(timeZone);
if (!value) return null;
if (supportedTimeZoneIds.has(value)) {
const offset = getRuntimeOffsetMinutes(value);
if (offset !== null) return offset;
}
const record = findTimeZone(value);
if (!record) {
return null;
}
@@ -98,7 +92,7 @@ function formatUtcOffset(offsetMinutes: number): string {
return `UTC${sign}${hours}:${minutes}`;
}
function formatTimeZonePlace(record: TimeZoneRecord): string {
function formatTimeZonePlace(record: TimeZone): string {
if (record.name === UTC_TIME_ZONE_ID) {
return UTC_TIME_ZONE_ID;
}