import { ReactNode, createContext, useCallback, useContext, useState, } from "react"; interface WidgetStyle { selectClassName?: string; inputClassName?: string; rangeClassName?: string; switchClassName?: string; inputNextLine?: boolean; rangeNextLine?: boolean; } interface ChildrenMeta { type?: "unknown" | "input" | "range"; error?: string; } export interface ListProps { className?: string; children?: ReactNode; id?: string; isMobileScreen?: boolean; widgetStyle?: WidgetStyle; } type Error = | { error: true; message: string; } | { error: false; }; export interface ListItemProps { title: string; subTitle?: string; children?: JSX.Element | JSX.Element[]; className?: string; onClick?: () => void; nextline?: boolean; validator?: (v: any) => Error | Promise; } export const ListContext = createContext< { isMobileScreen?: boolean; update?: (m: ChildrenMeta) => void; handleValidate?: (v: any) => void; } & WidgetStyle >({ isMobileScreen: false }); export function ListItem(props: ListItemProps) { const { className = "", onClick, title, subTitle, children, nextline, validator, } = props; const context = useContext(ListContext); const [childrenMeta, setMeta] = useState({}); const { inputNextLine, rangeNextLine } = context; const { type, error } = childrenMeta; let internalNextLine; switch (type) { case "input": internalNextLine = !!(nextline || inputNextLine); break; case "range": internalNextLine = !!(nextline || rangeNextLine); break; default: internalNextLine = false; } const update = useCallback((m: ChildrenMeta) => { setMeta((pre) => ({ ...pre, ...m })); }, []); const handleValidate = useCallback((v: any) => { const insideValidator = validator || (() => {}); Promise.resolve(insideValidator(v)).then((result) => { if (result && result.error) { return update({ error: result.message, }); } update({ error: undefined, }); }); }, []); return (
{title}
{subTitle && (
{subTitle}
)}
{children}
{!!error && (
{error}
)}
); } function List(props: ListProps) { const { className, children, id, widgetStyle } = props; const { isMobileScreen } = useContext(ListContext); return (
{children}
); } List.ListItem = ListItem; List.ListContext = ListContext; export default List;