import React from 'react'; import { Pressable, StyleSheet, Switch, Text, View } from 'react-native'; import type { SduiBlock } from '@proulr/sdui-contract'; import { Card } from '../ui/Card'; import { AppIcon } from '../ui/app-icon'; import { colors, fonts, m3Colors, m3Type, spacing } from '../theme/proulr-theme'; import { resolveDataRef, resolveDataRefBoolean, resolveDataRefString, } from '../lib/resolve-data-ref'; import { SelectRow as UiSelectRow } from '../ui/SelectRow'; import { resolveViewStyleProps } from '../theme/resolve-style-props'; import type { SduiBlockRenderProps } from './SduiPrimitiveBlocks'; function readStringProp(block: SduiBlock, key: string): string | undefined { const value = block.props[key]; return typeof value === 'string' ? value : undefined; } function readBooleanProp(block: SduiBlock, key: string): boolean { return block.props[key] === true; } export function SduiCardBlock({ block, children }: SduiBlockRenderProps) { return ( )])}> {children} ); } export function SduiSectionHeaderBlock({ block, onAction }: SduiBlockRenderProps) { const title = readStringProp(block, 'title') ?? ''; const actionLabel = readStringProp(block, 'action_label'); const actionId = readStringProp(block, 'action_id'); return ( {title} {actionLabel && actionId ? ( onAction(actionId)} hitSlop={8}> {actionLabel} ) : null} ); } export function SduiListItemBlock({ block, data, onAction }: SduiBlockRenderProps) { const title = readStringProp(block, 'title') ?? ''; const subtitleRef = readStringProp(block, 'subtitle_ref'); const subtitle = subtitleRef ? resolveDataRefString(data, subtitleRef) : readStringProp(block, 'subtitle'); const trailingRef = readStringProp(block, 'trailing_ref'); const trailingText = trailingRef ? resolveDataRefString(data, trailingRef) : readStringProp(block, 'trailing_text'); const actionId = readStringProp(block, 'action_id'); const showDivider = readBooleanProp(block, 'show_divider'); const showChevron = block.props.show_chevron !== false; const navChevron = Boolean(actionId) && showChevron && !trailingText; const inner = ( <> {title} {subtitle ? ( {subtitle} ) : null} {navChevron ? : null} {trailingText ? {trailingText} : null} ); if (actionId) { return ( onAction(actionId)} > {inner} ); } return {inner}; } export function SduiToggleRowBlock({ block, data, onAction }: SduiBlockRenderProps) { const label = readStringProp(block, 'label') ?? ''; const hint = readStringProp(block, 'hint'); const dataRef = readStringProp(block, 'data_ref'); const toggleActionId = readStringProp(block, 'toggle_action_id'); const disabled = readBooleanProp(block, 'disabled'); const value = resolveDataRefBoolean(data, dataRef); return ( {label} {hint ? {hint} : null} { if (!toggleActionId) return; onAction(toggleActionId, { value: String(next) }); }} trackColor={{ false: m3Colors.surfaceContainerHighest, true: m3Colors.primary }} thumbColor={m3Colors.onPrimary} /> ); } export function SduiSelectRowBlock({ block, data, onAction }: SduiBlockRenderProps) { const label = readStringProp(block, 'label') ?? ''; const dataRef = readStringProp(block, 'data_ref'); const optionsRef = readStringProp(block, 'options_ref'); const changeActionId = readStringProp(block, 'change_action_id'); const disabled = readBooleanProp(block, 'disabled'); const value = dataRef ? resolveDataRefString(data, dataRef) : ''; const optionsRaw = optionsRef ? resolveDataRef(data, optionsRef) : []; const options = Array.isArray(optionsRaw) ? optionsRaw.map(String) : []; return ( { if (disabled || !changeActionId) return; onAction(changeActionId, { value: next }); }} /> ); } const styles = StyleSheet.create({ card: { paddingVertical: spacing.xs, paddingHorizontal: spacing.sm, }, sectionHeaderRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: spacing.sm, marginTop: spacing.xl, }, sectionHeader: { color: colors.textSecondary, fontSize: 14, fontFamily: fonts.semibold, }, sectionAction: { color: colors.accentText, fontSize: 13, fontFamily: fonts.semibold, }, listItem: { flexDirection: 'row', alignItems: 'center', gap: spacing.md, paddingVertical: spacing.md, }, listItemDivider: { borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: colors.border, }, listContent: { flex: 1 }, listTitle: { color: colors.textPrimary, fontSize: 15, fontFamily: fonts.semibold }, listSubtitle: { color: colors.textSecondary, fontSize: 13, marginTop: 2 }, trailingText: { ...m3Type.bodySmall, color: colors.textSecondary }, toggleRow: { flexDirection: 'row', alignItems: 'center', gap: spacing.md, paddingVertical: spacing.xs, }, toggleCopy: { flex: 1, gap: spacing.xs, }, toggleLabel: { color: m3Colors.onSurface, fontSize: 15, fontFamily: fonts.semibold, }, toggleHint: { color: m3Colors.onSurfaceVariant, fontSize: 12, lineHeight: 17, fontFamily: fonts.regular, }, });