import type { Currency } from '$libs/currency'; import type { Locale } from '$libs/locale'; import type { Timezone } from '$libs/timezone'; import { currencyDimension } from './dimensions/currency.ts'; import { densityDimension } from './dimensions/density.ts'; import { directionDimension } from './dimensions/direction.ts'; import { languageDimension } from './dimensions/language.ts'; import { localeDimension } from './dimensions/locale.ts'; import { motionDimension } from './dimensions/motion.ts'; import { themeDimension } from './dimensions/theme.ts'; import { timezoneDimension } from './dimensions/timezone.ts'; import { unitSystemDimension } from './dimensions/unit-system.ts'; /** * Catalog input for `standardPrefsDimensions`. Apps declare which * languages, locales and currencies they support; the preset wires the * canonical built-ins around them. */ export interface StandardPrefsCatalog { readonly languages: readonly Locale[]; readonly locales: readonly Locale[]; readonly currencies: readonly Currency[]; /** Optional IANA zone allowlist; omit for "any zone Intl can canonicalize". */ readonly timezones?: readonly Timezone[]; /** * Optional per-dimension defaults. When omitted each dimension picks * its own — usually the first entry in its catalog. */ readonly defaults?: { readonly language?: Locale; readonly locale?: Locale; readonly currency?: Currency; readonly timezone?: Timezone; }; } /** * Compose the canonical built-in dimensions around the application's * catalogs. Returns the schema fragment so apps can spread it into * their full schema: * * ```ts * const schema = { * ...standardPrefsDimensions({ languages, locales, currencies }), * // App-specific dimensions * sidebarCollapsed: booleanDimension({ default: false }), * notificationLevel: enumDimension(['all','mentions','none'] as const, { default: 'mentions' }) * }; * * createActiveApp({ prefs: { schema } }); * ``` * * Apps that don't want a particular built-in (say, a single-currency * app skipping `currency`) drop the entry after spreading or compose a * subset by hand instead of using this preset. */ export function standardPrefsDimensions(catalog: StandardPrefsCatalog) { const defaults = catalog.defaults ?? {}; return { language: languageDimension({ catalog: catalog.languages, default: defaults.language }), locale: localeDimension({ catalog: catalog.locales, default: defaults.locale }), currency: currencyDimension({ catalog: catalog.currencies, default: defaults.currency }), timezone: timezoneDimension({ catalog: catalog.timezones, default: defaults.timezone }), unitSystem: unitSystemDimension(), theme: themeDimension(), density: densityDimension(), motion: motionDimension(), direction: directionDimension() } as const; } /** * Neutral baseline used by `createActiveApp` when the caller omits * `options.prefs`. Keeps the core surface populated even for apps that * don't think about preferences. Apps that DO care override * `options.prefs.schema`. */ export const NEUTRAL_PREFS_SCHEMA = standardPrefsDimensions({ languages: ['en'], locales: ['en-US'], currencies: ['USD'] }); export type StandardPrefsSchema = ReturnType;