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