import React, { useMemo } from 'react'; import { View, ImageBackground, StyleSheet, type ViewStyle } from 'react-native'; import type { TContainer, TComponent } from '@namiml/sdk-core'; import { applyStyles, parseColor, resolveFillImageUrl } from '../../utils/styles'; import { TemplateRenderer } from '../TemplateRenderer'; interface Props { component: TContainer; scaleFactor: number; onClose?: () => void; } export const NamiBackgroundContainer: React.FC = ({ component, scaleFactor, onClose }) => { if (!component || component.hidden) return null; const containerStyle = useMemo( () => applyStyles(component as any, scaleFactor) as ViewStyle, [component, scaleFactor] ); const fillImageUrl = resolveFillImageUrl(component.fillImage); const bgColor = parseColor(component.fillColor) ?? parseColor(component.fillColorFallback); // Only clip when the container is a filled "tile" with specific (non-all-corners) // rounding (NAM-1798); all-corners / unrounded filled containers stay unclipped so // NC-3948 / NAM-1201 over-rounding is not reintroduced. Matches the Apple/Web gate. const roundBorders = component.roundBorders; const hasSpecificCorners = Array.isArray(roundBorders) && roundBorders.length > 0 && roundBorders.length < 4; const clipStyle: ViewStyle = (component.fillColor || component.fillImage) && hasSpecificCorners ? { overflow: 'hidden' } : {}; const direction = component.direction ?? 'vertical'; const content = ( <> {component.components?.map((comp: TComponent, i: number) => { const marginKey = direction === 'vertical' ? 'topMargin' : 'leftMargin'; const spacedComponent = i === 0 || !component.spacing ? comp : ({ ...comp, [marginKey]: mergeRawMarginValue((comp as any)[marginKey], component.spacing), } as TComponent); return ( ); })} ); if (fillImageUrl) { return ( {content} ); } return ( {content} ); }; function mergeRawMarginValue(existing: unknown, spacing: unknown): unknown { if (existing == null) return spacing; const existingNumeric = toNumericMargin(existing); const spacingNumeric = toNumericMargin(spacing); if (existingNumeric == null || spacingNumeric == null) { return existing; } return existingNumeric + spacingNumeric; } function toNumericMargin(value: unknown): number | null { if (typeof value === 'number' && Number.isFinite(value)) { return value; } if (typeof value !== 'string') { return null; } const trimmed = value.trim(); if (!trimmed || !/^-?\d+(\.\d+)?$/.test(trimmed)) { return null; } const parsed = Number(trimmed); return Number.isFinite(parsed) ? parsed : null; } const styles = StyleSheet.create({ background: { ...StyleSheet.absoluteFillObject, }, });