You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.9 KiB
50 lines
1.9 KiB
import { Context } from 'runed';
|
|
|
|
import { readableActive, type Active, type ActiveProps } from '$terra/utils';
|
|
|
|
import type { TerraConfigPropsWithoutChildren } from './types';
|
|
|
|
|
|
|
|
type TerraConfigStateProps = ActiveProps<TerraConfigPropsWithoutChildren>;
|
|
|
|
|
|
|
|
export const TerraConfigContext = new Context<TerraConfigState>('TerraConfig');
|
|
|
|
|
|
|
|
export function getTerraConfig() {
|
|
|
|
const fallback = new TerraConfigState(null, {});
|
|
|
|
return TerraConfigContext.getOr(fallback).opts;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useTerraConfig(opts: TerraConfigStateProps) {
|
|
|
|
return TerraConfigContext.set(new TerraConfigState(TerraConfigContext.getOr(null), opts));
|
|
|
|
}
|
|
|
|
|
|
|
|
export class TerraConfigState {
|
|
|
|
readonly opts: Required<TerraConfigStateProps>;
|
|
|
|
|
|
|
|
constructor(parent: TerraConfigState | null, opts: TerraConfigStateProps) {
|
|
|
|
const resolveConfigOption = createConfigResolver(parent, opts);
|
|
|
|
this.opts = {
|
|
|
|
defaultPortalTo: resolveConfigOption((config) => config.defaultPortalTo),
|
|
|
|
defaultLocale: resolveConfigOption((config) => config.defaultLocale),
|
|
|
|
defaultDir: resolveConfigOption((config) => config.defaultDir),
|
|
|
|
defaultDateOrder: resolveConfigOption((config) => config.defaultDateOrder),
|
|
|
|
defaultTimeFormat: resolveConfigOption((config) => config.defaultTimeFormat),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type ConfigOptionGetter<T> = (config: TerraConfigStateProps) => Active<T> | undefined;
|
|
|
|
type ConfigOptionResolver = <T>(getter: ConfigOptionGetter<T>) => Active<T | undefined>;
|
|
|
|
|
|
|
|
function createConfigResolver(
|
|
|
|
parent: TerraConfigState | null,
|
|
|
|
currentOpts: TerraConfigStateProps
|
|
|
|
): ConfigOptionResolver {
|
|
|
|
return <T>(getter: ConfigOptionGetter<T>) => {
|
|
|
|
const configOption = readableActive(() => {
|
|
|
|
const value = getter(currentOpts)?.current;
|
|
|
|
if (value !== undefined) return value;
|
|
|
|
if (parent === null) return undefined;
|
|
|
|
return getter(parent.opts)?.current;
|
|
|
|
});
|
|
|
|
return configOption;
|
|
|
|
};
|
|
|
|
}
|
|
|