import { memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; import { Autocomplete, Box, Checkbox, Popper, styled, TextField, Tooltip, Typography } from "@mui/material"; import { DataContext } from "../../context/Context"; import ComponentWrapper from "../../common/ComponentWrapper"; import { getFieldName } from "../../permissions/getFieldName"; import { inputProps } from "../../interface/inputfieldProps"; import { getComponentProps, getSchemaProps } from "../../common/getComponentProps"; import _ from "lodash"; import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank"; import CheckBoxIcon from "@mui/icons-material/CheckBox"; import MultiSelectSearchPanel from "./MultiSelectSearchPanel"; import { useJsonForms } from "@jsonforms/react"; const StyledAutocompletePopper = styled("div")(({ theme, style }: { theme: any, style: any }) => ({ ...theme.AutoCompleteStyle, ...style })); const CustomPopper = (props: any) => { const { theme, style, anchorEl, ...other } = props; return ( ); }; export const ImpaktAppsAutoComplete = memo(function CustomAutoComplete( props: inputProps | any ) { const { errors, uischema, rootSchema, data, required, handleChange, path, schema, options, } = props.props; const uischemaData = uischema?.config?.main; const { pageName, permissions, theme, setSchema, serviceProvider } = useContext(DataContext); const ctx = useJsonForms(); const dynamicStyle = useMemo(() => { return serviceProvider( ctx, { onClick: uischema.config?.main?.styleFunction || 'getStyle', }, { event: { _reactName: 'onClick' }, path, }, ); }, [data, path]); const componentStyle = useMemo( () => ({ ...uischema.config?.style, ...dynamicStyle }), [uischema.config?.style, dynamicStyle] ); const fieldName = getFieldName(path); const [changeState, setChangeState] = useState(""); const [selectOptions, setSelectOptions] = useState( options || uischemaData.options || [] ); const [value, setValue] = useState(uischemaData.multiple ? [] : ""); const [open, setOpen] = useState(false); const [dropdownSearch, setDropdownSearch] = useState(""); const isDisabled = getSchemaProps(schema, rootSchema).disabled; const inputRef = useRef(null); const handleRemoveChip = useCallback( (val: any) => { setValue((prev: any[]) => { const next = prev.filter((option) => option.value !== val); handleChange(path, next.length === 0 ? undefined : next.map((e) => e?.value)); return next; }); setTimeout(() => inputRef.current?.focus(), 0); }, [handleChange, path] ); const PopperSlot = useMemo( () => (props: any) => ( ), [componentStyle?.AutoCompleteStyle] ); const triggerDisplayValue = useMemo(() => { if (!uischemaData.multiple) return undefined; if (!Array.isArray(value) || value.length === 0) return ""; if (value.length === 1) return value[0]?.label ?? ""; return `${value.length} selected`; }, [uischemaData.multiple, value]); const MultiSelectDropdownPanelProps = useMemo( () => ({ selectedOptions: Array.isArray(value) ? value : [], searchValue: dropdownSearch, onSearchChange: setDropdownSearch, searchPlaceholder: uischemaData?.searchPlaceholder, onRemoveChip: handleRemoveChip, styleConfig: componentStyle, isDisabled, appTheme: theme }), [value, dropdownSearch, uischemaData?.searchPlaceholder, handleRemoveChip, componentStyle, isDisabled, theme] ); const filteredSelectOptions = useMemo(() => { if (uischemaData.lazyLoading) return selectOptions; if (!uischemaData.multiple || !dropdownSearch) return selectOptions; return selectOptions.filter((opt: any) => opt.label?.toLowerCase().includes(dropdownSearch.toLowerCase()) ); }, [selectOptions, dropdownSearch, uischemaData.multiple]); useEffect(() => { setSelectOptions(options || []); }, [options]); useEffect(() => { updateFreeSoloOptions(); }, []); function updateFreeSoloOptions() { if (uischemaData.freeSolo && !uischemaData.lazyLoading && data) { // let Updatedresponse = [{const:data||"",title:data||""}]; if (options) { const OptionsClone = _.cloneDeep(options); const updatedOptions = OptionsClone?.map((e: any) => { return { const: e.value, title: e.label }; }); const filterResult = updatedOptions.filter((e) => { return e.const === data; }); if (filterResult.length > 0) { return; } updatedOptions.push({ const: data || "", title: data || "" }); updateSchema({ options, response: updatedOptions, setSchema, path, uischemaData, }); } else { updateSchema({ options, response: [{ const: data || "", title: data || "" }], setSchema, path, uischemaData, }); } } } const debouncedFunction = useMemo( () => _.debounce((value: string, currentData: any) => { serviceProvider( props.ctx, { ...uischemaData, onInputChange: uischemaData.lazyLoadFunction || "getSelectOptions", }, { event: { _reactName: "onInputChange" }, path, ...uischemaData.additionalData, paramValue: { path, serachValue: value, currentValue: currentData, }, } ).then((response: any) => { if (response) { if (uischemaData.freeSolo) { response[response.length] = { const: changeState, title: changeState }; } updateSchema({ options, response, setSchema, path, uischemaData }); const filteredOptions = []; response.forEach((e) => { if (!data?.includes(e?.const)) { filteredOptions.push({ label: e.title, value: e.const }); } }); setSelectOptions(filteredOptions); } }); }, 1000), [changeState, uischemaData, serviceProvider, path, options, setSchema, props.ctx, data] ); useEffect(() => { if (!uischemaData.lazyLoading) return; debouncedFunction(dropdownSearch, data); }, [dropdownSearch]); const findOptions = () => { const value = data ? uischemaData.multiple ? options?.filter((o) => data.includes(o.value)) ?? [] : options?.find((o) => o.value === data) ?? data : uischemaData.multiple ? [] : ""; setValue(value); }; useEffect(() => { if (options) { findOptions(); } }, [options, data]); const computedProps = getComponentProps( `${pageName}:${fieldName}`, permissions, schema, rootSchema ); return ( { if (!uischemaData.multiple) return; if (!e.currentTarget.contains(e.relatedTarget as Node)) { setOpen(false); setDropdownSearch(""); } }} > setOpen(true) : undefined} onClose={uischemaData.multiple ? () => {} : undefined} openOnFocus={uischemaData.multiple ? false : undefined} clearOnBlur={uischemaData.multiple ? false : undefined} disabled={isDisabled && !uischemaData.multiple} onChange={(event, newValue: any) => { if (uischemaData.multiple) { if(isDisabled) return; if (newValue.length === 0) { handleChange(path, undefined); } else { handleChange( path, newValue.map((e) => e?.value || e) ); } } else { handleChange(path, newValue === null ? undefined : newValue.value); } }} filterOptions={uischemaData.lazyLoading ? (option) => option : undefined} onInputChange={(event, newInputValue) => { if (uischemaData.multiple) return; if (uischemaData.lazyLoading) setDropdownSearch(newInputValue); }} onMouseLeave={() => updateFreeSoloOptions()} // placeholder={uischemaData.placeholder} sx={{ ...theme.InputFieldStyle, ...(computedProps.disabled && { '& .MuiOutlinedInput-root.Mui-disabled': { borderRadius: '12px' }, '& .MuiOutlinedInput-input.Mui-disabled': { WebkitTextFillColor:theme.myTheme.palette?.disabled?.text }, }), ...(isDisabled && uischemaData.multiple && { "& .MuiOutlinedInput-root": { "& .MuiOutlinedInput-notchedOutline": { borderColor: theme.myTheme.palette.primary?.main, }, "& input": { WebkitTextFillColor: theme.myTheme.palette?.disabled?.text, }, }, "& .MuiInputLabel-root": { color: theme.myTheme.palette?.disabled?.text, }, "& .MuiInputLabel-root.Mui-focused": { color: theme.myTheme.palette?.disabled?.text, }, "& .MuiSvgIcon-root": { color: theme.myTheme.palette?.disabled?.text, }, }), ...componentStyle }} freeSolo={uischemaData.freeSolo ? true : false} multiple={uischemaData.multiple ? true : false} id={path} options={filteredSelectOptions ?? []} value={value} slots={{ popper: PopperSlot, ...(uischemaData.multiple ? { paper: MultiSelectSearchPanel } : {}), }} slotProps={{ listbox: { sx: { overflowY: "auto", "&::-webkit-scrollbar": { width: "4px" }, "&::-webkit-scrollbar-thumb": { backgroundColor: theme.myTheme.palette?.secondary?.light, borderRadius: "4px", }, }, }, ...(uischemaData.multiple ? { paper: MultiSelectDropdownPanelProps } : {}), ...(uischemaData.multiple ? { popupIndicator: { onClick: (e: any) => { e.preventDefault(); e.stopPropagation(); setOpen((prev) => !prev); }, }, } : {}), }} renderTags={uischemaData.multiple ? () => null : undefined} renderOption={ uischemaData.multiple ? (optionProps: any, option: any, { selected: isSelected }: any) => (
  • } checkedIcon={} sx={{ padding: 0 }} disableRipple onMouseDown={(e) => e.preventDefault()} /> {option.label}
  • ) : undefined } renderInput={(params) => ( { setChangeState(newValue.target.value); handleChange(path, newValue.target.value); } : () => {} } /> )} />
    ); }); export default ImpaktAppsAutoComplete; function updateSchema(param) { if (param.uischemaData.multiple) { param.setSchema((pre: any) => { return { ...pre, properties: { ...pre.properties, [param.path]: { ...pre.properties?.[param.path], type: "array", items: { oneOf: param.response, }, }, }, }; }); } else { param.setSchema((pre: any) => { return { ...pre, properties: { ...pre.properties, [param.path]: { ...pre.properties?.[param.path], uniqueItems: true, oneOf: param.response || [], }, }, }; }); } }