leaflet_svelte/src/lib/features/settings/schema.ts
2026-06-17 00:20:55 +09:00

172 lines
3.7 KiB
TypeScript

/**
* Declarative settings schema. Each `SettingsField` describes a single setting
* that renders as a labeled form control in the Settings panel. Keep this
* independent of Svelte so the same schema can drive future serializers
* (export/import settings, URL state, etc.).
*/
export type FieldKind = 'boolean' | 'select' | 'number' | 'string';
export interface BaseField<K extends FieldKind> {
kind: K;
/** Dot-separated path into AppSettings (e.g. `'map.baseLayer'`). */
path: string;
labelKey: string;
descriptionKey?: string;
}
export interface BooleanField extends BaseField<'boolean'> {}
export interface NumberField extends BaseField<'number'> {
min?: number;
max?: number;
step?: number;
}
export interface StringField extends BaseField<'string'> {
placeholder?: string;
}
export interface SelectField extends BaseField<'select'> {
options: { value: string; labelKey: string }[];
}
export type SettingsField = BooleanField | NumberField | StringField | SelectField;
export interface SettingsSection {
titleKey: string;
fields: SettingsField[];
}
export const SETTINGS_SCHEMA: SettingsSection[] = [
{
titleKey: 'settings.language',
fields: [
{
kind: 'select',
path: 'locale',
labelKey: 'settings.language',
options: [
{ value: 'ru', labelKey: 'common.yes' },
{ value: 'en', labelKey: 'common.yes' },
],
},
],
},
{
titleKey: 'settings.map',
fields: [
{
kind: 'select',
path: 'map.baseLayer',
labelKey: 'settings.baseLayer',
options: [
{ value: 'osm', labelKey: 'settings.baseLayer' },
{ value: 'satellite', labelKey: 'settings.baseLayer' },
],
},
{ kind: 'boolean', path: 'map.showScale', labelKey: 'settings.showScale' },
{ kind: 'boolean', path: 'map.showNavigation', labelKey: 'settings.showNavigation' },
],
},
{
titleKey: 'settings.units',
fields: [
{
kind: 'select',
path: 'units.system',
labelKey: 'settings.units',
options: [
{ value: 'metric', labelKey: 'settings.metric' },
{ value: 'imperial', labelKey: 'settings.imperial' },
],
},
],
},
{
titleKey: 'settings.wind',
fields: [
{ kind: 'boolean', path: 'wind.enabled', labelKey: 'settings.windEnabled' },
{
kind: 'number',
path: 'wind.step',
labelKey: 'settings.windStep',
min: 0.25,
max: 10,
step: 0.25,
},
{
kind: 'number',
path: 'wind.trajectoryStep',
labelKey: 'settings.windTrajectoryStep',
min: 0.25,
max: 5,
step: 0.25,
},
{
kind: 'number',
path: 'wind.prefetchIntervalMinutes',
labelKey: 'settings.windPrefetchInterval',
min: 5,
max: 60,
step: 5,
},
{
kind: 'number',
path: 'wind.maxFlightDurationHours',
labelKey: 'settings.windMaxDuration',
min: 1,
max: 8,
step: 0.5,
},
{
kind: 'number',
path: 'wind.maxRegionDegrees',
labelKey: 'settings.windMaxRegion',
min: 5,
max: 60,
step: 5,
},
{
kind: 'number',
path: 'wind.trajectoryMarginDegrees',
labelKey: 'settings.windMargin',
min: 0.5,
max: 5,
step: 0.5,
},
{
kind: 'number',
path: 'wind.particleDensity',
labelKey: 'settings.windParticleDensity',
min: 0.25,
max: 3,
step: 0.25,
},
{
kind: 'number',
path: 'wind.particleSpeed',
labelKey: 'settings.windParticleSpeed',
min: 0.25,
max: 4,
step: 0.25,
},
{
kind: 'number',
path: 'wind.trailPersistence',
labelKey: 'settings.windTrailPersistence',
min: 0.7,
max: 0.98,
step: 0.02,
},
{
kind: 'number',
path: 'wind.maxVelocity',
labelKey: 'settings.windMaxVelocity',
min: 10,
max: 80,
step: 5,
},
],
},
];