import { isEmpty, isFunction } from '@legendapp/state'; import { BindKeys, ShapeWith$, reactive } from '@legendapp/state/react'; import { ComponentClass, FC, LegacyRef, createElement, forwardRef } from 'react'; import { ActivityIndicator, ActivityIndicatorProps, Button, ButtonProps, FlatList, FlatListProps, Image, ImageProps, Pressable, PressableProps, ScrollView, ScrollViewProps, SectionList, SectionListProps, Switch, SwitchProps, Text, TextInput, TextInputProps, TextProps, TouchableWithoutFeedback, TouchableWithoutFeedbackProps, View, ViewProps, } from 'react-native'; type FCReactive = P & FC< ShapeWith$ & { ref?: LegacyRef

| undefined; } >; const bindables: BindKeys = { TextInput: { handler: 'onChange', getValue: (e) => e.nativeEvent.text, defaultValue: '', }, Switch: { handler: 'onValueChange', getValue: (e) => e, defaultValue: false }, }; const Components: Record> = { ActivityIndicator: ActivityIndicator, Button: Button, FlatList: FlatList, Image: Image, Pressable: Pressable, ScrollView: ScrollView, SectionList: SectionList, Switch: Switch, Text: Text, TextInput: TextInput, TouchableWithoutFeedback: TouchableWithoutFeedback, View: View, }; export const Legend = new Proxy( {}, { get(target: Record, p: keyof typeof Components) { if (!target[p]) { // Create a wrapper around createElement with the string so we can proxy it // eslint-disable-next-line react/display-name const render = forwardRef((props, ref) => { const propsOut = { ...props } as any; if (ref && (isFunction(ref) || !isEmpty(ref))) { propsOut.ref = ref; } return createElement(Components[p], propsOut); }); target[p] = reactive( render, bindables[p] && ({ value: bindables[p], } as BindKeys), ); } return target[p]; }, }, ) as { ActivityIndicator: FCReactive; Button: FCReactive; FlatList: FCReactive>; Image: FCReactive; Pressable: FCReactive; ScrollView: FCReactive; SectionList: FCReactive>; Switch: FCReactive; Text: FCReactive; TextInput: FCReactive; TouchableWithoutFeedback: FCReactive; View: FCReactive; };