diff --git a/src/lib/types/configurator.ts b/src/lib/types/cfg/configurator.ts similarity index 50% rename from src/lib/types/configurator.ts rename to src/lib/types/cfg/configurator.ts index 7748428..d3da380 100644 --- a/src/lib/types/configurator.ts +++ b/src/lib/types/cfg/configurator.ts @@ -1,35 +1,40 @@ +import { + type ValueProvider, + type BooleanProvider, + type StringProvider, + type NumberProvider, + type OptionValueProvider +} from './provider'; +import { type Quantity } from './quantity'; export type OptionValue = string | number | boolean; -export type OptionValuer= OptionValue | (() => OptionValue); +export type IdToIndexMap= Record; -export type IdsPos = Record; -export type Enabler = boolean | (() => boolean); -// ============ Cantidad ============ -export interface Quantity { - value : OptionValuer; - min? : OptionValuer; - max? : OptionValuer; - step? : number; // Para incrementos (ej: de 5 en 5) -} - export type RestrictionType = 'choices' | 'range'; -export type OptionRestriction = - | { mode: 'choices'; values: OptionValue[] } - | { - mode: 'range'; +interface RestrictionBase { + mode: T; +} + +export interface ChoicesRestriction extends RestrictionBase<'choices'> { + values: OptionValue[]; +} + +export interface RangeRestriction extends RestrictionBase<'range'> { range: { - min: number | (() => number); - max: number | (() => number); + min: NumberProvider; + max: NumberProvider; step?: number; }; -}; +} + +export type OptionRestriction = ChoicesRestriction | RangeRestriction; export type OptionRestrictions = OptionRestriction[]; @@ -39,7 +44,7 @@ export type OptionRestrictions = OptionRestriction[]; export type ValidatorType = "min" | "max" | "regex" | "allowed" | "custom"; -export type Validator = (v: OptionRestriction) => boolean; +export type Validator = (v: OptionValue) => boolean; export interface OptionValidator { mode : ValidatorType; @@ -57,7 +62,7 @@ export type DependencyOperator = '=' | '!=' | '<=' | '<' | '>=' | '>'; export interface Dependency { entity : string; group : string; // Nombre del grupo del que depende - value : OptionValuer; + value : OptionValueProvider; operator? : DependencyOperator; // Por defecto '=' si no se indica } @@ -67,40 +72,40 @@ export type Dependencies = Dependency[]; export interface ImageContent { id : string; - name : string; + name : StringProvider; src : string; thumb? : string; large? : string; - title? : string; - text? : string; - alt? : string; + title? : StringProvider; + text? : StringProvider; + alt? : StringProvider; width? : number; height? : number; } export interface PdfContent { - title : string; - text : string; - image? : string; + title : StringProvider; + text : StringProvider; + image? : StringProvider; } export interface TextContent { - label? : string; // Etiqueta corta, ideal para botones o encabezados - title? : string; // Título principal o destacado - description? : string; // Texto descriptivo o explicativo - help? : string; // Texto de ayuda o aclaración contextual - message_ok? : string; // Mensaje positivo (éxito, selección válida) - message_err? : string; // Mensaje de error o validación - placeholder? : string; // Texto de entrada (para inputs) - tooltip? : string; // Texto breve al pasar el cursor + label? : StringProvider; // Etiqueta corta, ideal para botones o encabezados + title? : StringProvider; // Título principal o destacado + description? : StringProvider; // Texto descriptivo o explicativo + help? : StringProvider; // Texto de ayuda o aclaración contextual + messageOk? : StringProvider; // Mensaje positivo (éxito, selección válida) + messageErr? : StringProvider; // Mensaje de error o validación + placeholder? : StringProvider; // Texto de entrada (para inputs) + tooltip? : StringProvider; // Texto breve al pasar el cursor // 🔹 Campos relacionados con precio - priceLabel? : string; // Ej: "Precio" - priceUnit? : string; // Ej: "€/m²", "€/ud" - priceMsg? : string; // Mensaje contextual sobre precio (ej. "Incluye IVA") - priceRangeMsg?: string; // Mensaje contextual si es un precio calculado por rango + priceLabel? : StringProvider; // Ej: "Precio" + priceUnit? : StringProvider; // Ej: "€/m²", "€/ud" + priceMsg? : StringProvider; // Mensaje contextual sobre precio (ej. "Incluye IVA") + priceRangeMsg?: StringProvider; // Mensaje contextual si es un precio calculado por rango } @@ -122,14 +127,14 @@ export interface Content { export interface Group { id : string; - name : string; + name : StringProvider; default : number; // idx default option, normally 0 - enabled : Enabler; - required : boolean; + enabled : BooleanProvider; + required : BooleanProvider; multiple : boolean; options : Options; - optionIds : IdsPos; + optionIds : IdToIndexMap; content? : Content; @@ -141,9 +146,9 @@ export type Groups = Group[]; export interface Option { id : string; - name : string; + name : StringProvider; - enabled : Enabler; + enabled : BooleanProvider; value : OptionValue; price? : Price; choices? : OptionValue[]; @@ -161,17 +166,18 @@ export type Options = Option[]; export interface Entity { - name : string; + id : string; + name : StringProvider; content? : Content; groups : Groups; - groupsIds : IdsPos; + groupsIds : IdToIndexMap; dependsOn? : Dependencies; entities? : Entities; - entitiesIds : Record; + entitiesIds : IdToIndexMap ; } @@ -181,5 +187,29 @@ export type Entities = Entity[]; // ============ Utilidades de tipo ============ export type DeepPartial = { - [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; -}; \ No newline at end of file + [P in keyof T]?: T[P] extends object + ? T[P] extends Function + ? T[P] + : DeepPartial + : T[P]; +}; + + + + + + + + + + + + + + + + + + + + diff --git a/src/lib/types/cfg/content.ts b/src/lib/types/cfg/content.ts new file mode 100644 index 0000000..0444b88 --- /dev/null +++ b/src/lib/types/cfg/content.ts @@ -0,0 +1,47 @@ +// content.ts + + +import { type StringProvider } from "./provider"; + + +export interface ImageContent { + id : string; + name : StringProvider; + src : string; + thumb? : string; + large? : string; + title? : StringProvider; + text? : StringProvider; + alt? : StringProvider; + width? : number; + height? : number; +} + +export interface PdfContent { + title : StringProvider; + text : StringProvider; + image? : StringProvider; +} + +export interface TextContent { + label? : StringProvider; + title? : StringProvider; + description?: StringProvider; + help? : StringProvider; + messageOk? : StringProvider; + messageErr? : StringProvider; + placeholder?: StringProvider; + tooltip? : StringProvider; + + priceLabel? : StringProvider; + priceUnit? : StringProvider; + priceMsg? : StringProvider; + priceRangeMsg?: StringProvider; +} + +export interface Content { + text? : TextContent; + pdf? : PdfContent; + image? : ImageContent; + gallery? : ImageContent[]; +} diff --git a/src/lib/types/cfg/dependency.ts b/src/lib/types/cfg/dependency.ts new file mode 100644 index 0000000..f3c47e5 --- /dev/null +++ b/src/lib/types/cfg/dependency.ts @@ -0,0 +1,13 @@ +// dependenies.ts +import { OptionValueProvider } from "./provider"; + +export type DependencyOperator = '=' | '!=' | '<=' | '<' | '>=' | '>'; + +export interface Dependency { + entity : string; + group : string; + value : OptionValueProvider; + operator? : DependencyOperator; +} + +export type Dependencies = Dependency[]; \ No newline at end of file diff --git a/src/lib/types/cfg/entity.ts b/src/lib/types/cfg/entity.ts new file mode 100644 index 0000000..254a0d4 --- /dev/null +++ b/src/lib/types/cfg/entity.ts @@ -0,0 +1,17 @@ +import { StringProvider } from "./provider"; +import { Content } from "./content"; +import { Groups } from "./group"; +import { Dependencies } from "./dependency"; + +export interface Entity { + id: string; + name: StringProvider; + content?: Content; + groups: Groups; + groupsIds: Record; + dependsOn?: Dependencies; + entities?: Entities; + entitiesIds: Record; +} + +export type Entities = Entity[]; diff --git a/src/lib/types/cfg/group.ts b/src/lib/types/cfg/group.ts new file mode 100644 index 0000000..5862b65 --- /dev/null +++ b/src/lib/types/cfg/group.ts @@ -0,0 +1,21 @@ +import { BooleanProvider, StringProvider } from "./provider"; +import { Dependencies } from "./dependency"; +import { Content } from "./content"; +import { Options } from "./option"; + +export type IdToIndexMap = Record; + +export interface Group { + id: string; + name: StringProvider; + default: number; + enabled: BooleanProvider; + required: BooleanProvider; + multiple: boolean; + options: Options; + optionIds: IdToIndexMap; + content?: Content; + dependsOn?: Dependencies; +} + +export type Groups = Group[]; diff --git a/src/lib/types/cfg/index.ts b/src/lib/types/cfg/index.ts new file mode 100644 index 0000000..735f44a --- /dev/null +++ b/src/lib/types/cfg/index.ts @@ -0,0 +1,11 @@ +export * from "./provider"; +export * from "./quantity"; +export * from "./restriction"; +export * from "./validator"; +export * from "./dependency"; +export * from "./content"; +export * from "./pricing"; +export * from "./option"; +export * from "./group"; +export * from "./entity"; +export * from "./utils"; diff --git a/src/lib/types/cfg/option.ts b/src/lib/types/cfg/option.ts new file mode 100644 index 0000000..ce2dc68 --- /dev/null +++ b/src/lib/types/cfg/option.ts @@ -0,0 +1,29 @@ +// option.ts +import { BooleanProvider, StringProvider } from "./provider"; +import { OptionValidators } from "./validator"; +import { OptionRestrictions } from "./restriction"; +import { Dependencies } from "./dependency"; +import { Content } from "./content"; +import { Price } from "./pricing"; +import { Quantity } from "./quantity"; + + + +export type OptionValue = string | number | boolean; + +export interface Option { + id: string; + name: StringProvider; + enabled: BooleanProvider; + value: OptionValue; + price?: Price; + choices?: OptionValue[]; + unit?: string; + quantity?: Quantity; + content?: Content; + dependsOn?: Dependencies; + validates?: OptionValidators; + restrictions?: OptionRestrictions; +} + +export type Options = Option[]; diff --git a/src/lib/types/cfg/price.ts b/src/lib/types/cfg/price.ts new file mode 100644 index 0000000..c769058 --- /dev/null +++ b/src/lib/types/cfg/price.ts @@ -0,0 +1 @@ +// price.ts diff --git a/src/lib/types/cfg/provider.ts b/src/lib/types/cfg/provider.ts new file mode 100644 index 0000000..914044f --- /dev/null +++ b/src/lib/types/cfg/provider.ts @@ -0,0 +1,37 @@ +// provider.ts + + +export type ValueProvider = T | (() => T); + +export type AsyncValueProvider = ValueProvider | Promise; + + +export type BooleanProvider = ValueProvider; +export type StringProvider = ValueProvider; +export type NumberProvider = ValueProvider; + +export type OptionValue = string | number | boolean; +export type OptionValueProvider = ValueProvider; + + + + + + + +export const provide = { + value(p: ValueProvider): T { + return typeof p === 'function' ? (p as () => T)() : p; + }, + string : (p: StringProvider) => provide.value(p), + boolean: (p: BooleanProvider) => provide.value(p), + number : (p: NumberProvider) => provide.value(p), + option : (p: OptionValueProvider) => provide.value(p), +}; + + +export const provideAsync = { + async value(p: AsyncValueProvider): Promise { + return typeof p === 'function' ? await (p as () => T | Promise)() : p; + }, +}; \ No newline at end of file diff --git a/src/lib/types/cfg/quantity.ts b/src/lib/types/cfg/quantity.ts new file mode 100644 index 0000000..35cfdb0 --- /dev/null +++ b/src/lib/types/cfg/quantity.ts @@ -0,0 +1,11 @@ +// quantity.ts +import type { NumberProvider } from '$lib/types/cfg/provider'; + + +// ============ Cantidad ============ +export interface Quantity { + value : NumberProvider; + min? : NumberProvider; + max? : NumberProvider; + step? : number; // Para incrementos (ej: de 5 en 5) +} diff --git a/src/lib/types/cfg/restriction.ts b/src/lib/types/cfg/restriction.ts new file mode 100644 index 0000000..603fbf1 --- /dev/null +++ b/src/lib/types/cfg/restriction.ts @@ -0,0 +1,24 @@ +// restriction.ts + + +export type RestrictionType = 'choices' | 'range'; + + +interface RestrictionBase { + mode: T; +} + +export interface ChoicesRestriction extends RestrictionBase<'choices'> { + values: OptionValue[]; +} + +export interface RangeRestriction extends RestrictionBase<'range'> { + range: { + min: number | (() => number); + max: number | (() => number); + step?: number; + }; +} + +export type OptionRestriction = ChoicesRestriction | RangeRestriction; +export type OptionRestrictions = OptionRestriction[]; \ No newline at end of file diff --git a/src/lib/types/cfg/utils.ts b/src/lib/types/cfg/utils.ts new file mode 100644 index 0000000..f1ba24a --- /dev/null +++ b/src/lib/types/cfg/utils.ts @@ -0,0 +1,8 @@ + +export type DeepPartial = { + [P in keyof T]?: T[P] extends object + ? T[P] extends Function + ? T[P] + : DeepPartial + : T[P]; +} \ No newline at end of file diff --git a/src/lib/types/cfg/validator.ts b/src/lib/types/cfg/validator.ts new file mode 100644 index 0000000..946d9cd --- /dev/null +++ b/src/lib/types/cfg/validator.ts @@ -0,0 +1,18 @@ +// validator.ts + + +import { type OptionValue } from "./provider"; + + + +export type ValidatorType = "min" | "max" | "regex" | "allowed" | "custom"; +export type Validator = (v: OptionValue) => boolean; + +export interface OptionValidator { + mode: ValidatorType; + value?: OptionValue | OptionValue[]; + func?: Validator; + message?: (v: OptionValue) => string; +} + +export type OptionValidators = OptionValidator[]; \ No newline at end of file