'use strict'; import type { AnyRecord, ValueProcessorContext } from '../types'; import { ValueProcessorTarget } from '../types'; import { isConfigPropertyAlias, isDefined, isRecord } from '../utils'; import type { StyleBuilder, StyleBuilderConfig, StyleBuildMiddleware, } from './types'; type StyleBuilderOptions

= { buildMiddleware?: StyleBuildMiddleware

; separatelyInterpolatedNestedProperties?: (keyof P)[]; target?: ValueProcessorTarget; }; class StyleBuilderImpl

implements StyleBuilder

{ private readonly buildMiddleware: StyleBuildMiddleware

; private readonly config: StyleBuilderConfig

; private readonly separatelyInterpolatedNestedProperties_: (keyof P)[]; private readonly context: ValueProcessorContext; private processedProps = {} as P; constructor(config: StyleBuilderConfig

, options?: StyleBuilderOptions

) { this.config = config; this.buildMiddleware = options?.buildMiddleware ?? ((props) => props); this.separatelyInterpolatedNestedProperties_ = options?.separatelyInterpolatedNestedProperties ?? []; this.context = { target: options?.target ?? ValueProcessorTarget.Default, }; } isSeparatelyInterpolatedNestedProperty(property: keyof P): boolean { return this.separatelyInterpolatedNestedProperties_.includes(property); } add(property: keyof P, value: P[keyof P]): void { const configValue = this.config[property]; if (!configValue || !isDefined(value)) { return; } if (configValue === true) { this.maybeAssignProp(property, value); } else if (isConfigPropertyAlias

(configValue)) { this.add(configValue.as, value); } else { const { process } = configValue; const processedValue = process ? process(value, this.context) : value; if (!isDefined(processedValue)) { return; } if (isRecord

(processedValue)) { this.maybeAssignProps(processedValue); } else { this.maybeAssignProp(property, processedValue); } } } build(): P | null { const result = this.buildMiddleware(this.processedProps); this.cleanup(); if (Object.keys(result).length === 0) { return null; } return result; } buildFrom(props: P): P | null { Object.entries(props).forEach(([key, value]) => this.add(key, value)); return this.build(); } private maybeAssignProp(property: keyof P, value: P[keyof P]) { this.processedProps[property] ??= value; } private maybeAssignProps(props: P) { Object.entries(props).forEach(([key, value]) => this.maybeAssignProp(key, value) ); } private cleanup() { this.processedProps = {} as P; } } export default function createStyleBuilder

( config: StyleBuilderConfig

, options?: StyleBuilderOptions

): StyleBuilder> { return new StyleBuilderImpl(config, options); }