import { matchesNavigationConditions, type UnleashChecker } from "./navigation"; import type { FunnelAnswers, ScreenDefinition, ScreenVariantDefinition, } from "./types"; function cloneScreen(screen: T): T { if (typeof globalThis.structuredClone === "function") { return globalThis.structuredClone(screen); } return JSON.parse(JSON.stringify(screen)) as T; } function isPlainObject(value: unknown): value is Record { return typeof value === "object" && value !== null && !Array.isArray(value); } function deepMerge(target: T, source: Partial | undefined): T { if (!source) { return target; } const result: T = Array.isArray(target) ? ([...target] as unknown as T) : ({ ...(target as Record) } as T); for (const key of Object.keys(source) as (keyof T)[]) { const sourceValue = source[key]; if (sourceValue === undefined) { continue; } const targetValue = (result as Record)[key as unknown as string]; if (isPlainObject(sourceValue)) { const baseValue = isPlainObject(targetValue) ? targetValue : {}; (result as Record)[key as unknown as string] = deepMerge( baseValue, sourceValue as Record ) as unknown as T[keyof T]; continue; } (result as Record)[key as unknown as string] = sourceValue as unknown as T[keyof T]; } return result; } function applyScreenOverrides( screen: T, overrides: ScreenVariantDefinition["overrides"] ): T { const cloned = cloneScreen(screen); // DeepPartial совместим с deepMerge, так как deepMerge обрабатывает вложенные объекты return deepMerge(cloned, overrides as unknown as Partial); } export function resolveScreenVariant( screen: T, answers: FunnelAnswers, allScreens?: ScreenDefinition[], unleashChecker?: UnleashChecker ): T { const variants = (screen as T & { variants?: ScreenVariantDefinition[] }).variants; if (!variants || variants.length === 0) { return screen; } for (const variant of variants) { // Передаем allScreens и unleashChecker для правильной проверки условий if (matchesNavigationConditions(variant.conditions, answers, allScreens, unleashChecker)) { return applyScreenOverrides(screen, variant.overrides); } } return screen; }