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,
},
});