import React, { FC, PropsWithChildren } from "react"; import { useThemeProps } from "native-base"; import { pick, omit } from "lodash"; interface IWithThemeOpts { name?: string; skipProps?: string | string[]; } /** * HOC to apply themed props to a component (convert theme defintions to css style-properties) * @param options - options for the HOC * @param options.name - the name of the component - should match the key in the theme * @param options.skipProps - props to skip when applying the theme. Should be used for arrayed values, or props * @param Component - the component to apply the theme to * @returns a themed component * @example */ export const withTheme = (options?: IWithThemeOpts) => // @ts-ignore (Component: React.ComponentType>) => { const { name: defaultName } = Component; const { name, skipProps = [] } = options ?? {}; const id = name ?? defaultName; if (!id) { throw new Error( "Theming can not be applied on anonymous function without " + "setting component name explicitly in the HoC options: " + 'useTheme({ name: "MyComponent" })(props => )' ); } const Wrapped: FC = ({ children, ...props }: any) => { // useThemeProps expects themed props, // and array props are considered ie. breakpoint values or colormode values, // so it only returns a single value from any arrayed prop // to prevent component specific props from losing its context, // we split the arrayed props based on a list of given keys const componentProps = pick(props, skipProps); const themeProps = useThemeProps(id, omit(props, skipProps)); // @ts-ignore // prettier-ignore return {children}; }; Wrapped.displayName = `withTheme(${id})`; return Wrapped; };