@totalsoft/rocket-ui
Version:
A set of reusable and composable React components built on top of Material UI core for developing fast and friendly web applications interfaces.
86 lines (73 loc) • 3.33 kB
text/typescript
import { createFilterOptions } from '@mui/material/Autocomplete'
import { prop, map, innerJoin, find, propEq, all, includes, is, isEmpty, isNil, props, omit, equals, any } from 'ramda'
import { AutocompleteValue, FilterOptionsState } from '@mui/material'
export const findFirstNotNil = (propNames: string[], option: any) => find(x => !isNil(x), props(propNames, option))
export const isStringOrNumber = (option: unknown) => is(String, option) || is(Number, option)
const hasStringOptions = <T>(options: T[]) => all(is(String), options) && !isEmpty(options)
const filter = createFilterOptions()
export const filterOptions =
(labelKey: string, valueKey: string, creatable: boolean) => (options: unknown[], params: FilterOptionsState<unknown>) => {
const filtered = filter(options, params)
const { inputValue } = params
// Suggest the creation of a new value if it's not empty and it doesn't already exist
const exists = any(
(option: any) =>
is(Object, option)
? equals(inputValue, is(String, option?.[labelKey]) ? option?.[labelKey] : JSON.stringify(option?.[labelKey]))
: equals(inputValue, is(String, option) ? option : JSON.stringify(option)),
options
)
if (creatable && !(isEmpty(inputValue) || isNil(inputValue)) && !exists) {
filtered.push(
hasStringOptions(options)
? {
_primitiveValue: inputValue,
_createdOption: true
}
: {
// TODO: The valueKey should be different from the inputValue
[valueKey]: inputValue,
[labelKey]: inputValue,
_createdOption: true
}
)
}
return filtered
}
export const getSimpleValue = <T extends Record<string, unknown>>(
readonlyOptions: readonly T[],
value: unknown,
valueKey: string,
isMultiSelection: boolean
) => {
const options = readonlyOptions as T[]
if (isMultiSelection && (!is(Array, value) || isEmpty(options))) return []
if (!all(is(Object), options)) return value
// Add new options if the DeprecatedAutocomplete is multiSelection and creatable
if (is(Array, value)) {
const optionsSimpleValues = map(prop(valueKey), options)
value?.map(v => {
if (!includes(v, optionsSimpleValues)) options.push({ [valueKey]: v } as T)
})
}
const result = isMultiSelection
? innerJoin((o, v) => o[valueKey as keyof T] === v, options, value as any)
: find(propEq(value, valueKey), options)
return result || null
}
export const computeChangedMultiValue = <T, Multiple, DisableClearable, FreeSolo>(
input: any,
simpleValue: boolean,
valueKey: string,
labelKey: string
): AutocompleteValue<T, Multiple, DisableClearable, FreeSolo> =>
simpleValue
? input.map((a: unknown) => (!is(Object, a) ? a : findFirstNotNil([valueKey, labelKey, '_primitiveValue'], a)))
: input.map((a: unknown) => (!is(Object, a) ? a : prop('_primitiveValue', a) || omit(['_createdOption'], a)))
export const computeChangedSingleValue = (input: any, simpleValue: boolean, valueKey: string, labelKey: string) =>
simpleValue
? findFirstNotNil([valueKey, labelKey], input)
: (prop('_primitiveValue', input) ?? omit(['_createdOption'], input))
export const stopPropagation = (event: any) => {
event.stopPropagation()
}