import { BackgroundConfiguration as ItemBackgroundConfiguration, ImageConfiguration as ItemImageConfiguration, LabelConfiguration as ItemLabelConfiguration, NowPlayingAssetConfiguration as ItemNowPlayingAssetConfiguration, CheckboxAssetsConfiguration as ItemCheckboxAssetsConfiguration, ActionButtonAssetsConfiguration as ItemActionButtonAssetsConfiguration, ItemConfiguration, } from "../Components/Item"; import { TitleConfiguration as HeaderTitleConfiguration, HeaderConfiguration, } from "../Components/Header"; import { BackgroundConfiguration as ButtonBackgroundConfiguration, TitleConfiguration as ButtonTitleConfiguration, ButtonConfiguration, } from "../Components/Button"; // --------------------------------------------------------------------------- // Item Merging Helpers // --------------------------------------------------------------------------- function mergeItemBackground( base: ItemBackgroundConfiguration, defaultOverride?: Record, focusedOverride?: Record ): ItemBackgroundConfiguration { if (!defaultOverride && !focusedOverride) return base; // Only take focused color from the focused/pressed bucket (or legacy // mis-parsed focus* aliases). Never fall back to default background — // that would overwrite base.focusedColor whenever Studio only sets default. const focusedColor = focusedOverride?.backgroundColor ?? defaultOverride?.focusColor ?? defaultOverride?.focusBackgroundColor; return { ...base, ...(defaultOverride?.backgroundColor ? { defaultColor: defaultOverride.backgroundColor } : {}), ...(focusedColor != null && focusedColor !== "" ? { focusedColor } : {}), ...(defaultOverride?.borderRadius !== undefined ? { cornerRadius: defaultOverride.borderRadius } : {}), ...(defaultOverride?.paddingTop !== undefined ? { paddingTop: defaultOverride.paddingTop } : {}), ...(defaultOverride?.paddingRight !== undefined ? { paddingRight: defaultOverride.paddingRight } : {}), ...(defaultOverride?.paddingBottom !== undefined ? { paddingBottom: defaultOverride.paddingBottom } : {}), ...(defaultOverride?.paddingLeft !== undefined ? { paddingLeft: defaultOverride.paddingLeft } : {}), }; } function mergeItemImage( base: ItemImageConfiguration, override?: Record ): ItemImageConfiguration { if (!override) return base; return { ...base, ...(override.width !== undefined ? { width: override.width } : {}), ...(override.height !== undefined ? { height: override.height } : {}), ...(override.borderRadius !== undefined ? { cornerRadius: override.borderRadius } : {}), ...(override.borderWidth !== undefined ? { borderWidth: override.borderWidth } : {}), ...(override.borderColor ? { borderColor: override.borderColor } : {}), }; } function mergeItemLabel( base: ItemLabelConfiguration, override?: Record ): ItemLabelConfiguration { if (!override) return base; return { ...base, ...(override.fontColor ? { fontColor: override.fontColor } : {}), ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}), ...(override.lineHeight !== undefined ? { lineHeight: override.lineHeight } : {}), ...(override.fontFamily ? { iosFontFamily: override.fontFamily, androidFontFamily: override.fontFamily, } : {}), ...(override.iosFontFamily ? { iosFontFamily: override.iosFontFamily } : {}), ...(override.androidFontFamily ? { androidFontFamily: override.androidFontFamily } : {}), ...(override.letterSpacing !== undefined ? { iosLetterSpacing: override.letterSpacing, androidLetterSpacing: override.letterSpacing, } : {}), ...(override.iosLetterSpacing !== undefined ? { iosLetterSpacing: override.iosLetterSpacing } : {}), ...(override.androidLetterSpacing !== undefined ? { androidLetterSpacing: override.androidLetterSpacing } : {}), ...(override.textTransform ? { textTransform: override.textTransform } : {}), }; } function mergeItemNowPlayingAsset( base: ItemNowPlayingAssetConfiguration, override?: Record ): ItemNowPlayingAssetConfiguration { if (!override) return base; return { ...base, ...(override.asset ? { asset: override.asset } : {}), }; } function mergeItemCheckboxAssets( base: ItemCheckboxAssetsConfiguration, override?: Record ): ItemCheckboxAssetsConfiguration { if (!override) return base; return { ...base, ...(override.asset ? { asset: override.asset } : {}), ...(override.checkedAsset ? { checkedAsset: override.checkedAsset } : {}), }; } function mergeItemActionButtonAssets( base: ItemActionButtonAssetsConfiguration, override?: Record ): ItemActionButtonAssetsConfiguration { if (!override) return base; return { ...base, ...(override.removeAsset ? { removeAsset: override.removeAsset } : {}), ...(override.dragAsset ? { dragAsset: override.dragAsset } : {}), }; } export function mergeItemConfiguration( base: ItemConfiguration, itemBlock?: Record ): ItemConfiguration { if (!itemBlock) return base; const bgDefault = itemBlock.background?.default || itemBlock.background; const bgFocused = itemBlock.background?.focused || itemBlock.background?.focus || itemBlock.background?.pressed; const img = itemBlock.image?.default || itemBlock.image; const label1 = itemBlock.textLabel1?.default || itemBlock.textLabel1; const label2 = itemBlock.textLabel2?.default || itemBlock.textLabel2; const npLabel = itemBlock.nowPlayingLabel?.default || itemBlock.nowPlayingLabel; const npAsset = itemBlock.nowPlayingAsset?.default || itemBlock.nowPlayingAsset; const checkbox = itemBlock.checkbox?.default || itemBlock.checkbox; const actionButtons = itemBlock.actionButtons?.default || itemBlock.actionButtons; return { ...base, background: mergeItemBackground(base.background, bgDefault, bgFocused), image: mergeItemImage(base.image, img), textLabel1: mergeItemLabel(base.textLabel1, label1), textLabel2: mergeItemLabel(base.textLabel2, label2), nowPlayingLabel: mergeItemLabel(base.nowPlayingLabel, npLabel), nowPlayingAsset: mergeItemNowPlayingAsset(base.nowPlayingAsset, npAsset), checkboxAssets: mergeItemCheckboxAssets( base.checkboxAssets || {}, checkbox ), actionButtonAssets: mergeItemActionButtonAssets( base.actionButtonAssets || {}, actionButtons ), }; } // --------------------------------------------------------------------------- // Header Merging Helpers // --------------------------------------------------------------------------- function mergeHeaderTitle( base: HeaderTitleConfiguration, override?: Record ): HeaderTitleConfiguration { if (!override) return base; return { ...base, ...(override.fontColor ? { fontColor: override.fontColor } : {}), ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}), }; } export function mergeHeaderConfiguration( base: HeaderConfiguration, headerBlock?: Record ): HeaderConfiguration & { backgroundColor?: string } { if (!headerBlock) return base; const bgOverride = headerBlock.container?.default?.backgroundColor; return { ...base, title: mergeHeaderTitle(base.title, headerBlock.title?.default), ...(bgOverride ? { backgroundColor: bgOverride } : {}), }; } // --------------------------------------------------------------------------- // Button Merging Helpers // --------------------------------------------------------------------------- function mergeButtonBackground( base: ButtonBackgroundConfiguration, defaultOverride?: Record, focusedOverride?: Record ): ButtonBackgroundConfiguration { if (!defaultOverride && !focusedOverride) return base; // Same as mergeItemBackground: do not use default background as focusedColor. const focusedColor = focusedOverride?.backgroundColor ?? defaultOverride?.focusColor ?? defaultOverride?.focusBackgroundColor; return { ...base, ...(defaultOverride?.backgroundColor ? { defaultColor: defaultOverride.backgroundColor } : {}), ...(focusedColor != null && focusedColor !== "" ? { focusedColor } : {}), ...(defaultOverride?.borderRadius !== undefined ? { cornerRadius: defaultOverride.borderRadius } : {}), ...(defaultOverride?.paddingTop !== undefined ? { paddingTop: defaultOverride.paddingTop } : {}), ...(defaultOverride?.paddingRight !== undefined ? { paddingRight: defaultOverride.paddingRight } : {}), ...(defaultOverride?.paddingBottom !== undefined ? { paddingBottom: defaultOverride.paddingBottom } : {}), ...(defaultOverride?.paddingLeft !== undefined ? { paddingLeft: defaultOverride.paddingLeft } : {}), }; } function mergeButtonTitle( base: ButtonTitleConfiguration, override?: Record ): ButtonTitleConfiguration { if (!override) return base; return { ...base, ...(override.fontColor ? { fontColor: override.fontColor } : {}), ...(override.fontSize !== undefined ? { fontSize: override.fontSize } : {}), ...(override.lineHeight !== undefined ? { lineHeight: override.lineHeight } : {}), ...(override.fontFamily ? { iosFontFamily: override.fontFamily, androidFontFamily: override.fontFamily, } : {}), ...(override.iosFontFamily ? { iosFontFamily: override.iosFontFamily } : {}), ...(override.androidFontFamily ? { androidFontFamily: override.androidFontFamily } : {}), ...(override.letterSpacing !== undefined ? { iosLetterSpacing: override.letterSpacing, androidLetterSpacing: override.letterSpacing, } : {}), ...(override.iosLetterSpacing !== undefined ? { iosLetterSpacing: override.iosLetterSpacing } : {}), ...(override.androidLetterSpacing !== undefined ? { androidLetterSpacing: override.androidLetterSpacing } : {}), ...(override.textTransform ? { textTransform: override.textTransform } : {}), }; } function mergeButtonIcons( base: ButtonConfiguration["icons"], iconsOverride?: Record, leadingOverride?: Record ): ButtonConfiguration["icons"] { if (!iconsOverride && !leadingOverride) return base; const iconsDefault = iconsOverride?.default || iconsOverride; const leadingDefault = leadingOverride?.default || leadingOverride; return { ...base, ...(iconsDefault?.width !== undefined ? { width: iconsDefault.width } : {}), ...(iconsDefault?.height !== undefined ? { height: iconsDefault.height } : {}), leadingIcon: { ...base.leadingIcon, ...(leadingDefault?.enabled !== undefined ? { enabled: leadingDefault.enabled } : {}), ...(leadingDefault?.actionType ? { actionType: leadingDefault.actionType } : {}), ...(leadingDefault?.asset ? { asset: leadingDefault.asset } : {}), }, }; } export function mergeButtonConfiguration( base: ButtonConfiguration, buttonBlock?: Record, actionBlock?: Record ): ButtonConfiguration { if (!buttonBlock && !actionBlock) return base; const bgDefault = buttonBlock?.background?.default || actionBlock?.background?.default; const bgFocused = buttonBlock?.background?.focused || buttonBlock?.background?.focus || actionBlock?.background?.focused || actionBlock?.background?.focus || buttonBlock?.background?.pressed || actionBlock?.background?.pressed; const titleOverride = buttonBlock?.title?.default || actionBlock?.title?.default; const iconsOverride = buttonBlock?.icons || actionBlock?.icons; const leadingOverride = buttonBlock?.leadingIcon || actionBlock?.leadingIcon; return { ...base, background: mergeButtonBackground(base.background, bgDefault, bgFocused), title: mergeButtonTitle(base.title, titleOverride), icons: mergeButtonIcons(base.icons, iconsOverride, leadingOverride), }; }