/**
* I riquadri della pagina Impostazioni (e della schermata di scelta Tema/
* Lingua): una superficie arrotondata che raccoglie righe imparentate, come
* Impostazioni di iPhone e le WhatsApp.
*
* `Riquadro` è solo lo sfondo e gli angoli, con `overflow: 'hidden'` perché il
* colore di sfondo del tocco sulle righe non deve uscire dagli angoli tondi.
* `RigaRiquadro` è la riga: un segno a sinistra (assente nelle righe di
* scelta, dove non serve), il testo, il valore tenue se c'è, e in fondo la
* freccia — normale, obliqua per chi apre il browser, o la spunta di una
* scelta attiva. Ogni riga disegna da sé il separatore sotto di sé (tranne
* l'ultima del riquadro): un `View` a parte, rientrato dopo il segno, non un
* bordo sulla riga — un bordo sulla `Pressable` intera non si può rientrare
* senza tagliare anche l'area toccabile.
*
* Quali segni, quale freccia e quale ruolo di accessibilità per ogni riga
* sono decisioni prese in logica-impostazioni.ts (segnoRiga, segnoFineRiga,
* ruoloRigaImpostazioni): qui si mostra quello che arriva, senza deciderlo.
*/
import type { ReactNode } from 'react';
import { useMemo } from 'react';
import { ActivityIndicator, Pressable, StyleSheet, Text, View } from 'react-native';
import type { ChiaveSegno } from '../segni.ts';
import type { Colori } from '../tema.ts';
import { RAGGIO, SPAZIO, TESTO, useColori } from '../tema.ts';
import Segno from './Segno.tsx';
/** La larghezza riservata al segno a sinistra: allinea il testo di tutte le righe, con o senza segno. */
const LARGO_SEGNO = 24;
export function Riquadro({ children }: { children: ReactNode }) {
const colori = useColori();
const stili = useMemo(() => creaStiliRiquadro(colori), [colori]);
return {children};
}
export type VarianteRiga = 'normale' | 'pericolo' | 'spento';
export type FineRiga = 'freccia' | 'esterno' | 'spunta' | 'nessuno';
export interface PropsRigaRiquadro {
/** Il segno a sinistra. Assente nelle righe di scelta (Scelta.tsx), dove il testo comincia al bordo. */
segno?: ChiaveSegno;
titolo: string;
/** Il valore tenue a destra, prima del segno di fondo: «Come il telefono», «Italiano». */
valore?: string;
/** 'freccia' di default: le altre varianti le sceglie chi chiama con segnoFineRiga/ 'spunta' per le righe di scelta. */
fine?: FineRiga;
variante?: VarianteRiga;
onPress?: () => void;
/** Sostituisce il segno di fondo con lo spinner: l'operazione DI QUESTA riga è in corso. */
inCorso?: boolean;
/** Spenta perché un'altra riga sta scrivendo: niente spinner qui, solo il tocco che non fa niente. */
disabled?: boolean;
/** L'ultima riga del riquadro non ha il separatore sotto. */
ultima?: boolean;
accessibilityRole?: 'button' | 'link';
accessibilityLabel?: string;
accessibilityState?: { selected?: boolean; disabled?: boolean };
}
export function RigaRiquadro({
segno,
titolo,
valore,
fine = 'freccia',
variante = 'normale',
onPress,
inCorso = false,
disabled = false,
ultima = false,
accessibilityRole = 'button',
accessibilityLabel,
accessibilityState,
}: PropsRigaRiquadro) {
const colori = useColori();
const stili = useMemo(() => creaStiliRiga(colori), [colori]);
const spento = variante === 'spento';
const disabilitata = spento || onPress === undefined || inCorso || disabled;
const coloreEnfasi = variante === 'pericolo' ? colori.errore : spento ? colori.testoTenue : colori.testo;
const coloreSegno = variante === 'pericolo' ? colori.errore : spento ? colori.testoTenue : colori.accento;
return (
<>
[stili.riga, pressed && !disabilitata ? stili.premuta : null]}
>
{segno !== undefined ? (
) : null}
{titolo}
{valore !== undefined ? (
{valore}
) : null}
{inCorso ? (
) : fine === 'nessuno' ? null : fine === 'spunta' ? (
accessibilityState?.selected ? : (
// Riserva lo spazio della spunta anche quando manca: senza,
// il testo delle scelte non attive traballerebbe a sinistra
// di un pixel rispetto a quella scelta.
)
) : (
)}
{!ultima ? (
) : null}
>
);
}
const creaStiliRiquadro = (colori: Colori) =>
StyleSheet.create({
riquadro: {
backgroundColor: colori.superficie,
borderRadius: RAGGIO.riga,
overflow: 'hidden',
},
});
const creaStiliRiga = (colori: Colori) =>
StyleSheet.create({
riga: {
flexDirection: 'row',
alignItems: 'center',
minHeight: 44,
paddingVertical: SPAZIO.s,
paddingHorizontal: SPAZIO.l,
gap: SPAZIO.m,
},
premuta: { backgroundColor: colori.bordo },
segno: { width: LARGO_SEGNO, alignItems: 'center' },
titolo: { ...TESTO.corpo, flex: 1 },
valore: { ...TESTO.corpo, color: colori.testoTenue },
separatore: { height: StyleSheet.hairlineWidth, backgroundColor: colori.bordo },
});