UNPKG

libmodulor

Version:

A TypeScript library to create platform-agnostic applications

95 lines (94 loc) 4.16 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; import { FlatList, Pressable, StyleSheet, Switch, Text, TextInput, } from 'react-native'; import { TBoolean } from '../../dt/index.js'; import { UCInputFieldChangeOperator, ucifRepeatability, } from '../../uc/index.js'; import { isBlank } from '../../utils/index.js'; import { styleDef, useStyleContext, } from '../lib/react/StyleContextProvider.js'; import { rnInputDef } from '../lib/rn/input.js'; const MULTIPLE_VALUES_SEPARATOR = ','; // TODO : Split this into smaller components export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onChange: onChangeBase, }) { const { colors, formFieldControl, renderFormFieldControl } = useStyleContext(); const [internalValue, setInternalValue] = useState(f.getValue()); // biome-ignore lint/correctness/useExhaustiveDependencies: false positive : It is actually necessary (only `f` does not trigger the effect) useEffect(() => { setInternalValue(f.getValue()); }, [f.getValue()]); const component = renderFormFieldControl?.({ disabled, errMsg, execState, f, onChange: onChangeBase, }); if (component) { return component; } const onChangeText = (value) => { const [isRepeatable] = ucifRepeatability(f.def); if (isRepeatable && typeof value === 'string') { const valueArr = value .split(MULTIPLE_VALUES_SEPARATOR) .map((v) => v.trim()); onChangeBase(f, UCInputFieldChangeOperator.SET, valueArr); } else { onChangeBase(f, UCInputFieldChangeOperator.SET, value); } setInternalValue(value); }; const onSelect = (value) => { if (internalValue === value) { onChangeBase(f, UCInputFieldChangeOperator.RESET, null); setInternalValue(null); return; } onChangeBase(f, UCInputFieldChangeOperator.SET, value); setInternalValue(value); }; const onValueChange = (value) => { onChangeBase(f, UCInputFieldChangeOperator.SET, value); setInternalValue(value); }; const attrs = rnInputDef(f, disabled, errMsg); const { type } = f.def; const options = type.getOptions(); if (options) { // TODO : Handle type.hasStrictOptions() => display an input text alongside the options // TODO : Consider using a picker when the options count > X return (_jsx(FlatList, { data: options, horizontal: true, keyExtractor: (item) => item.value.toString(), renderItem: ({ item }) => (_jsx(Pressable, { disabled: !attrs.spec?.editable, onPress: () => onSelect(item.value), style: [ styles.selectOption, { borderColor: item.value === internalValue ? colors?.primary : 'transparent', }, ], children: _jsx(Text, { children: item.label }) })), showsHorizontalScrollIndicator: false, style: styles.select })); } // TODO : Implement picker for TFile (requires a dependency...) if (type instanceof TBoolean) { const { style } = styleDef(formFieldControl, 'Switch'); return (_jsx(Switch, { disabled: !attrs.spec?.editable, onValueChange: onValueChange, style: style, trackColor: { true: colors?.primary }, value: internalValue })); } let valueAsString = ''; if (!isBlank(internalValue)) { if (Array.isArray(internalValue)) { valueAsString = internalValue.join(MULTIPLE_VALUES_SEPARATOR); } else { valueAsString = internalValue.toString(); } } const { style } = styleDef(formFieldControl, 'TextInput', 'default'); return (_jsx(TextInput, { ...attrs.spec, onChangeText: onChangeText, style: style, value: valueAsString })); } const styles = StyleSheet.create({ select: { flexGrow: 0, // Prevent the list from extending full height }, selectOption: { borderWidth: 1, padding: 2, }, });