@gen-epix/ui-core-form 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/_chunks/Autocomplete.js.map +1 -1
  2. package/dist/_chunks/DatePicker.js +74 -74
  3. package/dist/_chunks/DatePicker.js.map +1 -1
  4. package/dist/_chunks/FormUtil.js +136 -141
  5. package/dist/_chunks/FormUtil.js.map +1 -1
  6. package/dist/_chunks/RichTextEditor.js +17451 -18531
  7. package/dist/_chunks/RichTextEditor.js.map +1 -1
  8. package/dist/_chunks/TransferList.js +1 -1
  9. package/dist/_chunks/TransferList.js.map +1 -1
  10. package/dist/_chunks/UploadButton.js.map +1 -1
  11. package/dist/_chunks/index.esm.js +236 -186
  12. package/dist/_chunks/index.esm.js.map +1 -1
  13. package/dist/_chunks/isEqual.js.map +1 -1
  14. package/dist/_chunks/isValid.js +1 -1
  15. package/dist/_chunks/isValid.js.map +1 -1
  16. package/dist/_chunks/rolldown-runtime.js +2 -2
  17. package/dist/_chunks/sv.js +15 -15
  18. package/dist/components/fields/CheckboxGroup/index.js +89 -89
  19. package/dist/components/fields/CheckboxGroup/index.js.map +1 -1
  20. package/dist/components/fields/DateRangePicker/index.js +193 -193
  21. package/dist/components/fields/DateRangePicker/index.js.map +1 -1
  22. package/dist/components/fields/NumberField/index.js.map +1 -1
  23. package/dist/components/fields/NumberRangeInput/index.js +140 -140
  24. package/dist/components/fields/NumberRangeInput/index.js.map +1 -1
  25. package/dist/components/fields/RadioGroup/index.js.map +1 -1
  26. package/dist/components/fields/Select/index.js.map +1 -1
  27. package/dist/components/fields/Switch/index.js +44 -44
  28. package/dist/components/fields/Switch/index.js.map +1 -1
  29. package/dist/components/fields/TextField/index.js.map +1 -1
  30. package/dist/components/fields/ToggleButtonGroup/index.js.map +1 -1
  31. package/dist/components/helpers/FormFieldHelperText/index.js.map +1 -1
  32. package/dist/components/helpers/GenericForm/index.js.map +1 -1
  33. package/package.json +3 -3
  34. /package/dist/@types/{ui-form.d.ts → ui-core-form.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../src/components/fields/Autocomplete/AutocompleteSelectAllContext.tsx","../../src/components/fields/Autocomplete/AutocompleteSelectAllPaper.tsx","../../src/components/fields/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import { createContext } from 'react';\n\nimport type { AutocompleteSelectAllContextData } from '../../../models/form';\n\nexport const AutocompleteSelectAllContext = createContext<AutocompleteSelectAllContextData | null>(null);\n","import type { MouseEvent } from 'react';\nimport {\n use,\n useCallback,\n} from 'react';\nimport {\n Box,\n Checkbox,\n Divider,\n Paper,\n} from '@mui/material';\nimport type { PaperProps } from '@mui/material';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport IndeterminateCheckBoxIcon from '@mui/icons-material/IndeterminateCheckBox';\n\nimport { AutocompleteSelectAllContext } from './AutocompleteSelectAllContext';\n\nexport const AutocompleteSelectAllPaper = ({ children, ...props }: PaperProps) => {\n const ctx = use(AutocompleteSelectAllContext);\n\n const onClickSelectAll = useCallback(() => {\n if (!ctx) {\n return;\n }\n const { currentValues, enabledOptionValues, handleSelectAll } = ctx;\n const selCount = currentValues.filter(v => enabledOptionValues.includes(v)).length;\n const curIsAll = enabledOptionValues.length > 0 && selCount === enabledOptionValues.length;\n handleSelectAll(curIsAll, currentValues);\n }, [ctx]);\n\n const onMouseDownSelectAll = useCallback((e: MouseEvent<HTMLElement>) => {\n e.preventDefault();\n }, []);\n\n const currentValues = ctx?.currentValues ?? [];\n const enabledOptionValues = ctx?.enabledOptionValues ?? [];\n const selectedEnabledCount = currentValues.filter(v => enabledOptionValues.includes(v)).length;\n const isAll = enabledOptionValues.length > 0 && selectedEnabledCount === enabledOptionValues.length;\n const isSome = selectedEnabledCount > 0 && !isAll;\n\n return (\n <Paper {...props}>\n {!!ctx && (\n <>\n <Box\n onClick={onClickSelectAll}\n onMouseDown={onMouseDownSelectAll}\n sx={{ '&:hover': { bgcolor: 'action.hover' }, alignItems: 'center', cursor: 'pointer', display: 'flex' }}\n >\n <Checkbox\n checked={isAll}\n checkedIcon={<CheckBoxIcon />}\n icon={<CheckBoxOutlineBlankIcon />}\n indeterminate={isSome}\n indeterminateIcon={<IndeterminateCheckBoxIcon />}\n style={{ marginRight: 8 }}\n />\n {ctx.selectAllLabel}\n </Box>\n <Divider />\n </>\n )}\n {children}\n </Paper>\n );\n};\n","import type {\n HTMLAttributes,\n ReactElement,\n ReactNode,\n SyntheticEvent,\n} from 'react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Checkbox,\n Chip,\n FormControl,\n Autocomplete as MuiAutocomplete,\n Stack,\n TextField,\n} from '@mui/material';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport type {\n AutocompleteRenderInputParams,\n AutocompleteRenderOptionState,\n AutocompleteRenderValueGetItemProps,\n AutocompleteValue,\n FilterOptionsState,\n} from '@mui/material';\nimport type {\n ControllerRenderProps,\n FieldValues,\n Path,\n UseControllerReturn,\n} from 'react-hook-form';\nimport {\n Controller,\n useFormContext,\n} from 'react-hook-form';\nimport classnames from 'classnames';\nimport { useTranslation } from 'react-i18next';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\n\nimport type {\n AutoCompleteOption,\n AutocompleteSelectAllContextData,\n} from '../../../models/form';\nimport { FormUtil } from '../../../utils/FormUtil';\nimport { FormFieldHelperText } from '../../helpers/FormFieldHelperText';\nimport { FormFieldLoadingIndicator } from '../../helpers/FormFieldLoadingIndicator';\n\nimport { AutocompleteSelectAllPaper } from './AutocompleteSelectAllPaper';\nimport { AutocompleteSelectAllContext } from './AutocompleteSelectAllContext';\n\n\nexport type AutocompleteProps<TFieldValues extends FieldValues, TName extends Path<TFieldValues>, TMultiple extends boolean> = {\n readonly disabled?: boolean;\n readonly groupValues?: boolean;\n readonly infoMessage?: string;\n readonly label: string;\n readonly loading?: boolean;\n readonly multiple?: TMultiple;\n readonly name: TName;\n readonly onChange?: (value: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>) => void;\n readonly options: AutoCompleteOption[];\n readonly required?: boolean;\n readonly shouldSortOptions?: boolean;\n readonly warningMessage?: string;\n};\ntype MultipleRenderValueItemProps = ReturnType<AutocompleteRenderValueGetItemProps<true>>;\n\ntype Value = number | string;\n\nexport const Autocomplete = <TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>, TMultiple extends boolean = false>({\n disabled = false,\n groupValues = false,\n infoMessage,\n label,\n loading = false,\n multiple,\n name,\n onChange: onChangeProp,\n options,\n required = false,\n shouldSortOptions,\n warningMessage,\n}: AutocompleteProps<TFieldValues, TName, TMultiple>): ReactElement => {\n const { t } = useTranslation();\n const { control, formState: { errors }, setValue, watch } = useFormContext<TFieldValues>();\n const errorMessage = FormUtil.getFieldErrorMessage(errors, name);\n const inputRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState('');\n\n const onChangePropRef = useRef(onChangeProp);\n useEffect(() => {\n onChangePropRef.current = onChangeProp;\n }, [onChangeProp]);\n\n const hasError = !!errorMessage;\n const hasWarning = !!warningMessage && !hasError;\n\n const sortedOptions = useMemo(() => {\n if (!shouldSortOptions) {\n return options;\n }\n return structuredClone(options).sort((a, b) => a.label.localeCompare(b.label));\n }, [options, shouldSortOptions]);\n\n const { mappedOptions, optionValues }: { mappedOptions: Map<Value, AutoCompleteOption>; optionValues: Array<Value> } = useMemo(() => {\n const values: Array<Value> = [];\n const mapped = new Map<Value, AutoCompleteOption>();\n sortedOptions.forEach(option => {\n values.push(option.value);\n mapped.set(option.value, option);\n });\n return {\n mappedOptions: mapped,\n optionValues: values,\n };\n }, [sortedOptions]);\n\n const getOptionLabel = useCallback((value: AutoCompleteOption['value']) => loading ? t`Loading...` : mappedOptions.get(value)?.label, [loading, mappedOptions, t]);\n const getIsOptionEqualToValue = useCallback((optionValue: AutoCompleteOption['value'], value: AutoCompleteOption['value']) => optionValue === value, []);\n const getIsOptionDisabled = useCallback((value: AutoCompleteOption['value']): boolean => mappedOptions.get(value)?.disabled, [mappedOptions]);\n const groupBy = useCallback((value: AutoCompleteOption['value']): string => mappedOptions.get(value)?.groupByValue, [mappedOptions]);\n const getOptionKey = useCallback((value: AutoCompleteOption['value']): string => String(mappedOptions.get(value)?.value), [mappedOptions]);\n\n const renderOption = useCallback((props: HTMLAttributes<HTMLLIElement>, option: TFieldValues[TName], state: AutocompleteRenderOptionState): ReactNode => {\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <li\n aria-disabled={props['aria-disabled']}\n aria-selected={props['aria-selected']}\n className={props.className}\n data-option-index={(props as { 'data-option-index': string })['data-option-index']}\n id={props.id}\n key={getOptionKey(option)}\n onClick={props.onClick}\n onMouseMove={props.onMouseMove}\n onTouchStart={props.onTouchStart}\n role={props.role}\n style={{\n margin: 0,\n padding: 0,\n }}\n tabIndex={props.tabIndex}\n >\n <Checkbox\n checked={state.selected}\n checkedIcon={<CheckBoxIcon />}\n icon={<CheckBoxOutlineBlankIcon />}\n style={{ marginRight: 8 }}\n />\n {getOptionLabel(option)}\n </li>\n );\n }, [getOptionKey, getOptionLabel]);\n\n const onMuiAutocompleteInputChange = useCallback((_event: SyntheticEvent, value: string) => {\n setInputValue(value);\n }, []);\n\n const renderInput = useCallback((params: AutocompleteRenderInputParams) => {\n const helperText = (\n <FormFieldHelperText\n errorMessage={errorMessage}\n infoMessage={infoMessage}\n warningMessage={warningMessage}\n />\n );\n\n return (\n <TextField\n disabled={disabled || loading}\n error={hasError}\n fullWidth={params.fullWidth}\n helperText={helperText}\n id={params.id}\n inputRef={inputRef}\n label={label}\n size={params.size}\n slotProps={{\n formHelperText: { className: classnames({ 'Mui-warning': hasWarning }) },\n htmlInput: {\n ...params.slotProps.htmlInput,\n },\n input: {\n ...params.slotProps.input,\n className: classnames(params.slotProps.input.className, {\n 'Mui-warning': hasWarning,\n }),\n },\n inputLabel: {\n ...params.slotProps.inputLabel,\n className: classnames({ 'Mui-warning': hasWarning }),\n required: required && !disabled,\n },\n }}\n variant={'outlined'}\n />\n );\n }, [disabled, errorMessage, hasError, hasWarning, infoMessage, label, loading, required, warningMessage]);\n\n const renderValue = useCallback((values: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>, getItemProps: AutocompleteRenderValueGetItemProps<TMultiple>) => {\n const selectedValues = (Array.isArray(values) ? values : [values]) as Value[];\n\n return (\n <Stack\n direction={'row'}\n sx={{\n flexWrap: 'wrap',\n }}\n >\n {selectedValues.map((value: Value, index: number) => {\n const props = getItemProps({ index }) as MultipleRenderValueItemProps;\n const option = mappedOptions.get(value);\n\n return (\n <Chip\n {...props}\n // eslint-disable-next-line @eslint-react/jsx-no-key-after-spread\n key={String(value)}\n label={getOptionLabel(value)}\n onDelete={option?.disabled ? undefined : props.onDelete}\n size={'small'}\n />\n );\n })}\n </Stack>\n );\n }, [getOptionLabel, mappedOptions]);\n\n const onMuiAutocompleteChange = useCallback((onChange: ControllerRenderProps<TFieldValues, TName>['onChange']) =>\n (_event: SyntheticEvent, value: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>) => {\n if (onChangeProp) {\n onChangeProp(value);\n }\n onChange(value);\n }\n , [onChangeProp]);\n\n const filterOptions = useCallback((_filterableOptions: TFieldValues[TName][], filterState: FilterOptionsState<TFieldValues[TName]>): TFieldValues[TName][] => {\n if (filterState.inputValue) {\n return sortedOptions.filter(option => option.label.toLowerCase().includes(filterState.inputValue.toLowerCase())).map((option) => option.value) as TFieldValues[TName][];\n }\n return sortedOptions.map((option) => option.value) as TFieldValues[TName][];\n }, [sortedOptions]);\n\n const enabledOptionValues = useMemo(() =>\n optionValues.filter(v => !mappedOptions.get(v)?.disabled)\n , [optionValues, mappedOptions]);\n\n const watchedValue = watch(name);\n const currentValues = useMemo(() =>\n multiple && Array.isArray(watchedValue) ? watchedValue as Value[] : []\n , [multiple, watchedValue]);\n\n const handleSelectAll = useCallback((isCurrentlyAll: boolean, curValues: Value[]) => {\n const newValue = isCurrentlyAll\n ? curValues.filter(v => mappedOptions.get(v)?.disabled)\n : [...new Set([...curValues, ...enabledOptionValues])];\n onChangePropRef.current?.(newValue as unknown as AutocompleteValue<TFieldValues[TName], TMultiple, false, false>);\n setValue(name, newValue as TFieldValues[TName], { shouldDirty: true, shouldTouch: true, shouldValidate: true });\n }, [enabledOptionValues, mappedOptions, name, setValue]);\n\n const selectAllContextValue = useMemo<AutocompleteSelectAllContextData>(() => ({\n currentValues,\n enabledOptionValues,\n handleSelectAll,\n selectAllLabel: t`Select all`,\n }), [currentValues, enabledOptionValues, handleSelectAll, t]);\n\n const renderController = useCallback(({ field: { onBlur, onChange, ref, value } }: UseControllerReturn<TFieldValues, TName>) => {\n ref({\n focus: () => {\n inputRef?.current?.focus();\n },\n });\n return (\n <MuiAutocomplete<TFieldValues[TName], TMultiple>\n autoComplete\n autoHighlight\n disableClearable={required as undefined}\n disableCloseOnSelect={multiple}\n disabled={disabled || loading}\n filterOptions={filterOptions}\n getOptionDisabled={getIsOptionDisabled}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n groupBy={groupValues ? groupBy : undefined}\n inputValue={multiple ? inputValue : undefined}\n isOptionEqualToValue={getIsOptionEqualToValue}\n multiple={multiple}\n noOptionsText={t`No results`}\n onBlur={onBlur}\n onChange={onMuiAutocompleteChange(onChange)}\n onInputChange={multiple ? onMuiAutocompleteInputChange : undefined}\n options={optionValues as TFieldValues[TName]}\n renderInput={renderInput}\n renderOption={multiple ? renderOption : undefined}\n renderValue={multiple ? renderValue : undefined}\n slots={multiple ? { paper: AutocompleteSelectAllPaper } : undefined}\n value={value}\n />\n );\n }, [required, multiple, disabled, loading, filterOptions, getIsOptionDisabled, getOptionKey, getOptionLabel, groupValues, groupBy, inputValue, getIsOptionEqualToValue, t, onMuiAutocompleteChange, onMuiAutocompleteInputChange, optionValues, renderInput, renderOption, renderValue]);\n\n return (\n <AutocompleteSelectAllContext value={multiple ? selectAllContextValue : null}>\n <FormControl\n {...TestIdUtil.createAttributes('Autocomplete', { label, name })}\n fullWidth\n >\n <Controller\n control={control}\n defaultValue={null}\n name={name}\n render={renderController}\n />\n {!!loading && <FormFieldLoadingIndicator />}\n </FormControl>\n </AutocompleteSelectAllContext>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Autocomplete.js","names":[],"sources":["../../src/components/fields/Autocomplete/AutocompleteSelectAllContext.tsx","../../src/components/fields/Autocomplete/AutocompleteSelectAllPaper.tsx","../../src/components/fields/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import { createContext } from 'react';\n\nimport type { AutocompleteSelectAllContextData } from '../../../models/form';\n\nexport const AutocompleteSelectAllContext = createContext<AutocompleteSelectAllContextData | null>(null);\n","import type { MouseEvent } from 'react';\nimport {\n use,\n useCallback,\n} from 'react';\nimport {\n Box,\n Checkbox,\n Divider,\n Paper,\n} from '@mui/material';\nimport type { PaperProps } from '@mui/material';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport IndeterminateCheckBoxIcon from '@mui/icons-material/IndeterminateCheckBox';\n\nimport { AutocompleteSelectAllContext } from './AutocompleteSelectAllContext';\n\nexport const AutocompleteSelectAllPaper = ({ children, ...props }: PaperProps) => {\n const ctx = use(AutocompleteSelectAllContext);\n\n const onClickSelectAll = useCallback(() => {\n if (!ctx) {\n return;\n }\n const { currentValues, enabledOptionValues, handleSelectAll } = ctx;\n const selCount = currentValues.filter(v => enabledOptionValues.includes(v)).length;\n const curIsAll = enabledOptionValues.length > 0 && selCount === enabledOptionValues.length;\n handleSelectAll(curIsAll, currentValues);\n }, [ctx]);\n\n const onMouseDownSelectAll = useCallback((e: MouseEvent<HTMLElement>) => {\n e.preventDefault();\n }, []);\n\n const currentValues = ctx?.currentValues ?? [];\n const enabledOptionValues = ctx?.enabledOptionValues ?? [];\n const selectedEnabledCount = currentValues.filter(v => enabledOptionValues.includes(v)).length;\n const isAll = enabledOptionValues.length > 0 && selectedEnabledCount === enabledOptionValues.length;\n const isSome = selectedEnabledCount > 0 && !isAll;\n\n return (\n <Paper {...props}>\n {!!ctx && (\n <>\n <Box\n onClick={onClickSelectAll}\n onMouseDown={onMouseDownSelectAll}\n sx={{ '&:hover': { bgcolor: 'action.hover' }, alignItems: 'center', cursor: 'pointer', display: 'flex' }}\n >\n <Checkbox\n checked={isAll}\n checkedIcon={<CheckBoxIcon />}\n icon={<CheckBoxOutlineBlankIcon />}\n indeterminate={isSome}\n indeterminateIcon={<IndeterminateCheckBoxIcon />}\n style={{ marginRight: 8 }}\n />\n {ctx.selectAllLabel}\n </Box>\n <Divider />\n </>\n )}\n {children}\n </Paper>\n );\n};\n","import type {\n HTMLAttributes,\n ReactElement,\n ReactNode,\n SyntheticEvent,\n} from 'react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Checkbox,\n Chip,\n FormControl,\n Autocomplete as MuiAutocomplete,\n Stack,\n TextField,\n} from '@mui/material';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport type {\n AutocompleteRenderInputParams,\n AutocompleteRenderOptionState,\n AutocompleteRenderValueGetItemProps,\n AutocompleteValue,\n FilterOptionsState,\n} from '@mui/material';\nimport type {\n ControllerRenderProps,\n FieldValues,\n Path,\n UseControllerReturn,\n} from 'react-hook-form';\nimport {\n Controller,\n useFormContext,\n} from 'react-hook-form';\nimport classnames from 'classnames';\nimport { useTranslation } from 'react-i18next';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\n\nimport type {\n AutoCompleteOption,\n AutocompleteSelectAllContextData,\n} from '../../../models/form';\nimport { FormUtil } from '../../../utils/FormUtil';\nimport { FormFieldHelperText } from '../../helpers/FormFieldHelperText';\nimport { FormFieldLoadingIndicator } from '../../helpers/FormFieldLoadingIndicator';\n\nimport { AutocompleteSelectAllPaper } from './AutocompleteSelectAllPaper';\nimport { AutocompleteSelectAllContext } from './AutocompleteSelectAllContext';\n\n\nexport type AutocompleteProps<TFieldValues extends FieldValues, TName extends Path<TFieldValues>, TMultiple extends boolean> = {\n readonly disabled?: boolean;\n readonly groupValues?: boolean;\n readonly infoMessage?: string;\n readonly label: string;\n readonly loading?: boolean;\n readonly multiple?: TMultiple;\n readonly name: TName;\n readonly onChange?: (value: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>) => void;\n readonly options: AutoCompleteOption[];\n readonly required?: boolean;\n readonly shouldSortOptions?: boolean;\n readonly warningMessage?: string;\n};\ntype MultipleRenderValueItemProps = ReturnType<AutocompleteRenderValueGetItemProps<true>>;\n\ntype Value = number | string;\n\nexport const Autocomplete = <TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>, TMultiple extends boolean = false>({\n disabled = false,\n groupValues = false,\n infoMessage,\n label,\n loading = false,\n multiple,\n name,\n onChange: onChangeProp,\n options,\n required = false,\n shouldSortOptions,\n warningMessage,\n}: AutocompleteProps<TFieldValues, TName, TMultiple>): ReactElement => {\n const { t } = useTranslation();\n const { control, formState: { errors }, setValue, watch } = useFormContext<TFieldValues>();\n const errorMessage = FormUtil.getFieldErrorMessage(errors, name);\n const inputRef = useRef<HTMLInputElement>(null);\n const [inputValue, setInputValue] = useState('');\n\n const onChangePropRef = useRef(onChangeProp);\n useEffect(() => {\n onChangePropRef.current = onChangeProp;\n }, [onChangeProp]);\n\n const hasError = !!errorMessage;\n const hasWarning = !!warningMessage && !hasError;\n\n const sortedOptions = useMemo(() => {\n if (!shouldSortOptions) {\n return options;\n }\n return structuredClone(options).sort((a, b) => a.label.localeCompare(b.label));\n }, [options, shouldSortOptions]);\n\n const { mappedOptions, optionValues }: { mappedOptions: Map<Value, AutoCompleteOption>; optionValues: Array<Value> } = useMemo(() => {\n const values: Array<Value> = [];\n const mapped = new Map<Value, AutoCompleteOption>();\n sortedOptions.forEach(option => {\n values.push(option.value);\n mapped.set(option.value, option);\n });\n return {\n mappedOptions: mapped,\n optionValues: values,\n };\n }, [sortedOptions]);\n\n const getOptionLabel = useCallback((value: AutoCompleteOption['value']) => loading ? t`Loading...` : mappedOptions.get(value)?.label, [loading, mappedOptions, t]);\n const getIsOptionEqualToValue = useCallback((optionValue: AutoCompleteOption['value'], value: AutoCompleteOption['value']) => optionValue === value, []);\n const getIsOptionDisabled = useCallback((value: AutoCompleteOption['value']): boolean => mappedOptions.get(value)?.disabled, [mappedOptions]);\n const groupBy = useCallback((value: AutoCompleteOption['value']): string => mappedOptions.get(value)?.groupByValue, [mappedOptions]);\n const getOptionKey = useCallback((value: AutoCompleteOption['value']): string => String(mappedOptions.get(value)?.value), [mappedOptions]);\n\n const renderOption = useCallback((props: HTMLAttributes<HTMLLIElement>, option: TFieldValues[TName], state: AutocompleteRenderOptionState): ReactNode => {\n return (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <li\n aria-disabled={props['aria-disabled']}\n aria-selected={props['aria-selected']}\n className={props.className}\n data-option-index={(props as { 'data-option-index': string })['data-option-index']}\n id={props.id}\n key={getOptionKey(option)}\n onClick={props.onClick}\n onMouseMove={props.onMouseMove}\n onTouchStart={props.onTouchStart}\n role={props.role}\n style={{\n margin: 0,\n padding: 0,\n }}\n tabIndex={props.tabIndex}\n >\n <Checkbox\n checked={state.selected}\n checkedIcon={<CheckBoxIcon />}\n icon={<CheckBoxOutlineBlankIcon />}\n style={{ marginRight: 8 }}\n />\n {getOptionLabel(option)}\n </li>\n );\n }, [getOptionKey, getOptionLabel]);\n\n const onMuiAutocompleteInputChange = useCallback((_event: SyntheticEvent, value: string) => {\n setInputValue(value);\n }, []);\n\n const renderInput = useCallback((params: AutocompleteRenderInputParams) => {\n const helperText = (\n <FormFieldHelperText\n errorMessage={errorMessage}\n infoMessage={infoMessage}\n warningMessage={warningMessage}\n />\n );\n\n return (\n <TextField\n disabled={disabled || loading}\n error={hasError}\n fullWidth={params.fullWidth}\n helperText={helperText}\n id={params.id}\n inputRef={inputRef}\n label={label}\n size={params.size}\n slotProps={{\n formHelperText: { className: classnames({ 'Mui-warning': hasWarning }) },\n htmlInput: {\n ...params.slotProps.htmlInput,\n },\n input: {\n ...params.slotProps.input,\n className: classnames(params.slotProps.input.className, {\n 'Mui-warning': hasWarning,\n }),\n },\n inputLabel: {\n ...params.slotProps.inputLabel,\n className: classnames({ 'Mui-warning': hasWarning }),\n required: required && !disabled,\n },\n }}\n variant={'outlined'}\n />\n );\n }, [disabled, errorMessage, hasError, hasWarning, infoMessage, label, loading, required, warningMessage]);\n\n const renderValue = useCallback((values: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>, getItemProps: AutocompleteRenderValueGetItemProps<TMultiple>) => {\n const selectedValues = (Array.isArray(values) ? values : [values]) as Value[];\n\n return (\n <Stack\n direction={'row'}\n sx={{\n flexWrap: 'wrap',\n }}\n >\n {selectedValues.map((value: Value, index: number) => {\n const props = getItemProps({ index }) as MultipleRenderValueItemProps;\n const option = mappedOptions.get(value);\n\n return (\n <Chip\n {...props}\n // eslint-disable-next-line @eslint-react/jsx-no-key-after-spread\n key={String(value)}\n label={getOptionLabel(value)}\n onDelete={option?.disabled ? undefined : props.onDelete}\n size={'small'}\n />\n );\n })}\n </Stack>\n );\n }, [getOptionLabel, mappedOptions]);\n\n const onMuiAutocompleteChange = useCallback((onChange: ControllerRenderProps<TFieldValues, TName>['onChange']) =>\n (_event: SyntheticEvent, value: AutocompleteValue<TFieldValues[TName], TMultiple, false, false>) => {\n if (onChangeProp) {\n onChangeProp(value);\n }\n onChange(value);\n }\n , [onChangeProp]);\n\n const filterOptions = useCallback((_filterableOptions: TFieldValues[TName][], filterState: FilterOptionsState<TFieldValues[TName]>): TFieldValues[TName][] => {\n if (filterState.inputValue) {\n return sortedOptions.filter(option => option.label.toLowerCase().includes(filterState.inputValue.toLowerCase())).map((option) => option.value) as TFieldValues[TName][];\n }\n return sortedOptions.map((option) => option.value) as TFieldValues[TName][];\n }, [sortedOptions]);\n\n const enabledOptionValues = useMemo(() =>\n optionValues.filter(v => !mappedOptions.get(v)?.disabled)\n , [optionValues, mappedOptions]);\n\n const watchedValue = watch(name);\n const currentValues = useMemo(() =>\n multiple && Array.isArray(watchedValue) ? watchedValue as Value[] : []\n , [multiple, watchedValue]);\n\n const handleSelectAll = useCallback((isCurrentlyAll: boolean, curValues: Value[]) => {\n const newValue = isCurrentlyAll\n ? curValues.filter(v => mappedOptions.get(v)?.disabled)\n : [...new Set([...curValues, ...enabledOptionValues])];\n onChangePropRef.current?.(newValue as unknown as AutocompleteValue<TFieldValues[TName], TMultiple, false, false>);\n setValue(name, newValue as TFieldValues[TName], { shouldDirty: true, shouldTouch: true, shouldValidate: true });\n }, [enabledOptionValues, mappedOptions, name, setValue]);\n\n const selectAllContextValue = useMemo<AutocompleteSelectAllContextData>(() => ({\n currentValues,\n enabledOptionValues,\n handleSelectAll,\n selectAllLabel: t`Select all`,\n }), [currentValues, enabledOptionValues, handleSelectAll, t]);\n\n const renderController = useCallback(({ field: { onBlur, onChange, ref, value } }: UseControllerReturn<TFieldValues, TName>) => {\n ref({\n focus: () => {\n inputRef?.current?.focus();\n },\n });\n return (\n <MuiAutocomplete<TFieldValues[TName], TMultiple>\n autoComplete\n autoHighlight\n disableClearable={required as undefined}\n disableCloseOnSelect={multiple}\n disabled={disabled || loading}\n filterOptions={filterOptions}\n getOptionDisabled={getIsOptionDisabled}\n getOptionKey={getOptionKey}\n getOptionLabel={getOptionLabel}\n groupBy={groupValues ? groupBy : undefined}\n inputValue={multiple ? inputValue : undefined}\n isOptionEqualToValue={getIsOptionEqualToValue}\n multiple={multiple}\n noOptionsText={t`No results`}\n onBlur={onBlur}\n onChange={onMuiAutocompleteChange(onChange)}\n onInputChange={multiple ? onMuiAutocompleteInputChange : undefined}\n options={optionValues as TFieldValues[TName]}\n renderInput={renderInput}\n renderOption={multiple ? renderOption : undefined}\n renderValue={multiple ? renderValue : undefined}\n slots={multiple ? { paper: AutocompleteSelectAllPaper } : undefined}\n value={value}\n />\n );\n }, [required, multiple, disabled, loading, filterOptions, getIsOptionDisabled, getOptionKey, getOptionLabel, groupValues, groupBy, inputValue, getIsOptionEqualToValue, t, onMuiAutocompleteChange, onMuiAutocompleteInputChange, optionValues, renderInput, renderOption, renderValue]);\n\n return (\n <AutocompleteSelectAllContext value={multiple ? selectAllContextValue : null}>\n <FormControl\n {...TestIdUtil.createAttributes('Autocomplete', { label, name })}\n fullWidth\n >\n <Controller\n control={control}\n defaultValue={null}\n name={name}\n render={renderController}\n />\n {!!loading && <FormFieldLoadingIndicator />}\n </FormControl>\n </AutocompleteSelectAllContext>\n );\n};\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { n as e } from "./rolldown-runtime.js";
2
- import { p as t, t as n } from "./FormUtil.js";
2
+ import { t, u as n } from "./FormUtil.js";
3
3
  import { i as r, t as i } from "./index.esm.js";
4
4
  import { FormFieldHelperText as a } from "../components/helpers/FormFieldHelperText/index.js";
5
5
  import { FormFieldLoadingIndicator as o } from "../components/helpers/FormFieldLoadingIndicator/index.js";
@@ -30,10 +30,10 @@ var E = /* @__PURE__ */ e(s(), 1), D = ({ children: e, disabled: t, loading: n,
30
30
  }), e]
31
31
  });
32
32
  }, O = ({ dateFormat: e = l.DATE, disabled: s = !1, infoMessage: p, label: g, loading: _ = !1, name: v, onChange: O, required: k = !1, warningMessage: A }) => {
33
- let { control: j, formState: { errors: M } } = r(), N = n.getFieldErrorMessage(M, v), P = !!N, F = !!A && !P, I = f(null), L = f(() => void 0), R = u((e) => (t) => {
33
+ let { control: j, formState: { errors: M } } = r(), N = t.getFieldErrorMessage(M, v), P = !!N, F = !!A && !P, I = f(null), L = f(() => void 0), R = u((e) => (t) => {
34
34
  O && O(t), e(t);
35
35
  }, [O]), z = d(() => ({
36
- ...t,
36
+ ...n,
37
37
  formatLong: c.formatLong
38
38
  }), []), B = d(() => {
39
39
  switch (e) {
@@ -43,81 +43,81 @@ var E = /* @__PURE__ */ e(s(), 1), D = ({ children: e, disabled: t, loading: n,
43
43
  case l.YEAR_MONTH: return ["year", "month"];
44
44
  default: throw Error(`Unsupported date format: ${e}`);
45
45
  }
46
- }, [e]), V = e === l.DATE_TIME ? C : S;
46
+ }, [e]), V = e === l.DATE_TIME ? C : S, H = u(({ field: { onBlur: t, onChange: n, ref: r, value: i } }) => (r({ focus: () => {
47
+ I?.current?.focus();
48
+ } }), L.current = () => {
49
+ n(null);
50
+ }, /* @__PURE__ */ b(m, {
51
+ ...x.createAttributes("DatePicker", {
52
+ label: g,
53
+ name: v
54
+ }),
55
+ fullWidth: !0,
56
+ sx: {
57
+ "&:hover .DatePicker-resetButton, &:focus-within .DatePicker-resetButton": { display: "initial" },
58
+ "& .DatePicker-resetButton": { display: "none" }
59
+ },
60
+ children: [
61
+ /* @__PURE__ */ y(w, {
62
+ adapterLocale: z,
63
+ dateAdapter: T,
64
+ children: /* @__PURE__ */ y(V, {
65
+ disabled: s || _,
66
+ inputRef: I,
67
+ label: g,
68
+ loading: _,
69
+ onChange: R(n),
70
+ openTo: e === l.DATE_TIME ? void 0 : "year",
71
+ slotProps: { textField: {
72
+ className: (0, E.default)({ "Mui-warning": F }),
73
+ error: P,
74
+ onBlur: t,
75
+ slotProps: { inputLabel: { required: k } },
76
+ variant: "outlined"
77
+ } },
78
+ slots: { inputAdornment: (e) => /* @__PURE__ */ y(D, {
79
+ ...e,
80
+ disabled: s,
81
+ loading: _,
82
+ onResetButtonClickRef: L
83
+ }) },
84
+ value: i,
85
+ views: B
86
+ })
87
+ }),
88
+ !!_ && /* @__PURE__ */ y(o, {}),
89
+ /* @__PURE__ */ y(h, {
90
+ sx: { ml: 0 },
91
+ children: /* @__PURE__ */ y(a, {
92
+ errorMessage: N,
93
+ infoMessage: p,
94
+ noIndent: !0,
95
+ warningMessage: A
96
+ })
97
+ })
98
+ ]
99
+ })), [
100
+ V,
101
+ z,
102
+ e,
103
+ s,
104
+ N,
105
+ P,
106
+ F,
107
+ p,
108
+ g,
109
+ _,
110
+ v,
111
+ R,
112
+ k,
113
+ B,
114
+ A
115
+ ]);
47
116
  return /* @__PURE__ */ y(i, {
48
117
  control: j,
49
118
  defaultValue: "",
50
119
  name: v,
51
- render: u(({ field: { onBlur: t, onChange: n, ref: r, value: i } }) => (r({ focus: () => {
52
- I?.current?.focus();
53
- } }), L.current = () => {
54
- n(null);
55
- }, /* @__PURE__ */ b(m, {
56
- ...x.createAttributes("DatePicker", {
57
- label: g,
58
- name: v
59
- }),
60
- fullWidth: !0,
61
- sx: {
62
- "&:hover .DatePicker-resetButton, &:focus-within .DatePicker-resetButton": { display: "initial" },
63
- "& .DatePicker-resetButton": { display: "none" }
64
- },
65
- children: [
66
- /* @__PURE__ */ y(w, {
67
- adapterLocale: z,
68
- dateAdapter: T,
69
- children: /* @__PURE__ */ y(V, {
70
- disabled: s || _,
71
- inputRef: I,
72
- label: g,
73
- loading: _,
74
- onChange: R(n),
75
- openTo: e === l.DATE_TIME ? void 0 : "year",
76
- slotProps: { textField: {
77
- className: (0, E.default)({ "Mui-warning": F }),
78
- error: P,
79
- onBlur: t,
80
- slotProps: { inputLabel: { required: k } },
81
- variant: "outlined"
82
- } },
83
- slots: { inputAdornment: (e) => /* @__PURE__ */ y(D, {
84
- ...e,
85
- disabled: s,
86
- loading: _,
87
- onResetButtonClickRef: L
88
- }) },
89
- value: i,
90
- views: B
91
- })
92
- }),
93
- !!_ && /* @__PURE__ */ y(o, {}),
94
- /* @__PURE__ */ y(h, {
95
- sx: { ml: 0 },
96
- children: /* @__PURE__ */ y(a, {
97
- errorMessage: N,
98
- infoMessage: p,
99
- noIndent: !0,
100
- warningMessage: A
101
- })
102
- })
103
- ]
104
- })), [
105
- V,
106
- z,
107
- e,
108
- s,
109
- N,
110
- P,
111
- F,
112
- p,
113
- g,
114
- _,
115
- v,
116
- R,
117
- k,
118
- B,
119
- A
120
- ])
120
+ render: H
121
121
  });
122
122
  };
123
123
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.js","names":[],"sources":["../../src/components/fields/DatePicker/DatePickerInputAdornment.tsx","../../src/components/fields/DatePicker/DatePicker.tsx"],"sourcesContent":["import type { RefObject } from 'react';\nimport type { InputAdornmentProps } from '@mui/material';\nimport {\n IconButton,\n InputAdornment,\n} from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\nimport { useTranslation } from 'react-i18next';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\n\nexport type DatePickerInputAdornmentProps = {\n readonly disabled: boolean;\n readonly loading: boolean;\n readonly onResetButtonClickRef: RefObject<() => void>;\n} & InputAdornmentProps;\n\nexport const DatePickerInputAdornment = ({\n children,\n disabled,\n loading,\n onResetButtonClickRef,\n ...props\n}: DatePickerInputAdornmentProps) => {\n const { t } = useTranslation();\n return (\n <InputAdornment {...props}>\n {!disabled && !loading && (\n <IconButton\n {...TestIdUtil.createAttributes('DatePicker-reset')}\n aria-label={t`Clear date field`}\n className={'DatePicker-resetButton'}\n // eslint-disable-next-line @eslint-react/kit/jsx-no-bind\n onClick={() => onResetButtonClickRef.current()}\n sx={{\n '& svg': {\n fontSize: '16px',\n },\n }}\n tabIndex={-1}\n >\n <ClearIcon />\n </IconButton>\n )}\n {children}\n </InputAdornment>\n );\n};\n","import type { ReactElement } from 'react';\nimport {\n useCallback,\n useMemo,\n useRef,\n} from 'react';\nimport {\n FormControl,\n FormHelperText,\n} from '@mui/material';\nimport type {\n ControllerRenderProps,\n FieldValues,\n Path,\n PathValue,\n UseControllerReturn,\n} from 'react-hook-form';\nimport {\n Controller,\n useFormContext,\n} from 'react-hook-form';\nimport type {\n DatePickerProps as MuiDatePickerProps,\n DateTimePickerProps as MuiDateTimePickerProps,\n} from '@mui/x-date-pickers';\nimport {\n LocalizationProvider,\n DatePicker as MuiDatePicker,\n DateTimePicker as MuiDateTimePicker,\n} from '@mui/x-date-pickers';\nimport classNames from 'classnames';\nimport type { Locale } from 'date-fns';\nimport {\n enUS,\n sv,\n} from 'date-fns/locale';\nimport { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport { FormUtil } from '../../../utils/FormUtil';\nimport { FormFieldHelperText } from '../../helpers/FormFieldHelperText';\nimport { FormFieldLoadingIndicator } from '../../helpers/FormFieldLoadingIndicator';\n\nimport { DatePickerInputAdornment } from './DatePickerInputAdornment';\n\n\nexport type DatePickerProps<TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>> = {\n readonly dateFormat?: typeof DATE_FORMAT[keyof typeof DATE_FORMAT];\n readonly disabled?: boolean;\n readonly infoMessage?: string;\n readonly label: string;\n readonly loading?: boolean;\n readonly name: TName;\n readonly onChange?: (value: Date) => void;\n readonly required?: boolean;\n readonly warningMessage?: string;\n};\n\nexport const DatePicker = <TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>>({\n dateFormat = DATE_FORMAT.DATE,\n disabled = false,\n infoMessage,\n label,\n loading = false,\n name,\n onChange: onChangeProp,\n required = false,\n warningMessage,\n}: DatePickerProps<TFieldValues, TName>): ReactElement => {\n const { control, formState: { errors } } = useFormContext<TFieldValues>();\n const errorMessage = FormUtil.getFieldErrorMessage(errors, name);\n const hasError = !!errorMessage;\n const hasWarning = !!warningMessage && !hasError;\n const inputRef = useRef<HTMLInputElement>(null);\n const onResetButtonClickRef = useRef<() => void>(() => undefined);\n\n const onMuiDatePickerChange = useCallback((onChange: ControllerRenderProps<TFieldValues, TName>['onChange']) =>\n (newValue: Date) => {\n if (onChangeProp) {\n onChangeProp(newValue);\n }\n onChange(newValue);\n }\n , [onChangeProp]);\n\n const customLocale = useMemo<Locale>(() => {\n /**\n * Use everything from enUS, but format dates the Swedish way (ISO 8601)\n */\n return {\n ...enUS,\n formatLong: sv.formatLong,\n };\n }, []);\n\n const views = useMemo<MuiDateTimePickerProps['views']>(() => {\n switch (dateFormat) {\n case DATE_FORMAT.DATE:\n case DATE_FORMAT.DATE_TIME:\n return undefined;\n case DATE_FORMAT.YEAR:\n return ['year'];\n case DATE_FORMAT.YEAR_MONTH:\n return ['year', 'month'];\n default:\n throw new Error(`Unsupported date format: ${dateFormat}`);\n }\n }, [dateFormat]);\n\n const MuiComponent = dateFormat === DATE_FORMAT.DATE_TIME ? MuiDateTimePicker : MuiDatePicker;\n\n const renderController = useCallback(({ field: { onBlur, onChange, ref, value } }: UseControllerReturn<TFieldValues, TName>) => {\n ref({\n focus: () => {\n inputRef?.current?.focus();\n },\n });\n\n onResetButtonClickRef.current = () => {\n onChange(null);\n };\n\n return (\n <FormControl\n {...TestIdUtil.createAttributes('DatePicker', { label, name })}\n fullWidth\n sx={{\n '&:hover .DatePicker-resetButton, &:focus-within .DatePicker-resetButton': {\n display: 'initial',\n },\n '& .DatePicker-resetButton': {\n display: 'none',\n },\n }}\n >\n <LocalizationProvider\n adapterLocale={customLocale}\n dateAdapter={AdapterDateFns}\n >\n <MuiComponent\n disabled={disabled || loading}\n inputRef={inputRef}\n label={label}\n loading={loading}\n onChange={onMuiDatePickerChange(onChange)}\n openTo={dateFormat === DATE_FORMAT.DATE_TIME ? undefined : 'year'}\n slotProps={{\n textField: {\n className: classNames({ 'Mui-warning': hasWarning }),\n error: hasError,\n onBlur,\n slotProps: {\n inputLabel: {\n required,\n },\n },\n variant: 'outlined',\n },\n }}\n slots={{\n inputAdornment: (props) => (\n <DatePickerInputAdornment\n {...props}\n disabled={disabled}\n loading={loading}\n onResetButtonClickRef={onResetButtonClickRef}\n />\n ),\n }}\n value={value}\n views={views as MuiDatePickerProps['views']}\n />\n </LocalizationProvider>\n {!!loading && <FormFieldLoadingIndicator />}\n <FormHelperText sx={{ ml: 0 }}>\n <FormFieldHelperText\n errorMessage={errorMessage}\n infoMessage={infoMessage}\n noIndent\n warningMessage={warningMessage}\n />\n </FormHelperText>\n </FormControl>\n );\n }, [MuiComponent, customLocale, dateFormat, disabled, errorMessage, hasError, hasWarning, infoMessage, label, loading, name, onMuiDatePickerChange, required, views, warningMessage]);\n\n return (\n <Controller\n control={control}\n defaultValue={'' as PathValue<TFieldValues, TName>}\n name={name}\n render={renderController}\n />\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;mCAgBA,KAAA,EAAA,aAAA,aAAA,YAAA,0BAAA,GAAA,QAAA;;;;;;;;;;;;;;AA8BA,GCaa,KAAuG,EAClH,gBAAa,EAAY,MACzB,cAAW,IACX,gBACA,UACA,aAAU,IACV,SACA,UAAU,GACV,cAAW,IACX,wBACwD;CACxD,IAAM,EAAE,YAAS,WAAW,EAAE,gBAAa,EAA6B,GAClE,IAAe,EAAS,qBAAqB,GAAQ,CAAI,GACzD,IAAW,CAAC,CAAC,GACb,IAAa,CAAC,CAAC,KAAkB,CAAC,GAClC,IAAW,EAAyB,IAAI,GACxC,IAAwB,QAAyB,KAAA,CAAS,GAE1D,IAAwB,GAAa,OACxC,MAAmB;EAIlB,AAHI,KACF,EAAa,CAAQ,GAEvB,EAAS,CAAQ;CACnB,GACA,CAAC,CAAY,CAAC,GAEV,IAAe,SAIZ;EACL,GAAG;EACH,YAAY,EAAG;CACjB,IACC,CAAC,CAAC,GAEC,IAAQ,QAA+C;EAC3D,QAAQ,GAAR;GACE,KAAK,EAAY;GACjB,KAAK,EAAY,WACf;GACF,KAAK,EAAY,MACf,OAAO,CAAC,MAAM;GAChB,KAAK,EAAY,YACf,OAAO,CAAC,QAAQ,OAAO;GACzB,SACE,MAAU,MAAM,4BAA4B,GAAY;EAC5D;CACF,GAAG,CAAC,CAAU,CAAC,GAET,IAAe,MAAe,EAAY,YAAY,IAAoB;CA6EhF,OACE,kBAAC,GAAD;EACW;EACT,cAAc;EACR;EACN,QAhFqB,GAAa,EAAE,OAAO,EAAE,WAAQ,aAAU,QAAK,kBACtE,EAAI,EACF,aAAa;GACX,GAAU,SAAS,MAAM;EAC3B,EACF,CAAC,GAED,EAAsB,gBAAgB;GACpC,EAAS,IAAI;EACf,GAGE,kBAAC,GAAD;GACE,GAAI,EAAW,iBAAiB,cAAc;IAAE;IAAO;GAAK,CAAC;GAC7D,WAAA;GACA,IAAI;IACF,2EAA2E,EACzE,SAAS,UACX;IACA,6BAA6B,EAC3B,SAAS,OACX;GACF;aAVF;IAYE,kBAAC,GAAD;KACE,eAAe;KACf,aAAa;eAEb,kBAAC,GAAD;MACE,UAAU,KAAY;MACZ;MACH;MACE;MACT,UAAU,EAAsB,CAAQ;MACxC,QAAQ,MAAe,EAAY,YAAY,KAAA,IAAY;MAC3D,WAAW,EACT,WAAW;OACT,YAAA,GAAA,EAAA,QAAA,CAAsB,EAAE,eAAe,EAAW,CAAC;OACnD,OAAO;OACP;OACA,WAAW,EACT,YAAY,EACV,YACF,EACF;OACA,SAAS;MACX,EACF;MACA,OAAO,EACL,iBAAiB,MACf,kBAAC,GAAD;OACE,GAAI;OACM;OACD;OACc;MACxB,CAAA,EAEL;MACO;MACA;KACR,CAAA;IACmB,CAAA;IACrB,CAAC,CAAC,KAAW,kBAAC,GAAD,CAA4B,CAAA;IAC1C,kBAAC,GAAD;KAAgB,IAAI,EAAE,IAAI,EAAE;eAC1B,kBAAC,GAAD;MACgB;MACD;MACb,UAAA;MACgB;KACjB,CAAA;IACa,CAAA;GACL;OAEd;GAAC;GAAc;GAAc;GAAY;GAAU;GAAc;GAAU;GAAY;GAAa;GAAO;GAAS;GAAM;GAAuB;GAAU;GAAO;EAAc,CAOvK;CACT,CAAA;AAEL"}
1
+ {"version":3,"file":"DatePicker.js","names":[],"sources":["../../src/components/fields/DatePicker/DatePickerInputAdornment.tsx","../../src/components/fields/DatePicker/DatePicker.tsx"],"sourcesContent":["import type { RefObject } from 'react';\nimport type { InputAdornmentProps } from '@mui/material';\nimport {\n IconButton,\n InputAdornment,\n} from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\nimport { useTranslation } from 'react-i18next';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\n\nexport type DatePickerInputAdornmentProps = {\n readonly disabled: boolean;\n readonly loading: boolean;\n readonly onResetButtonClickRef: RefObject<() => void>;\n} & InputAdornmentProps;\n\nexport const DatePickerInputAdornment = ({\n children,\n disabled,\n loading,\n onResetButtonClickRef,\n ...props\n}: DatePickerInputAdornmentProps) => {\n const { t } = useTranslation();\n return (\n <InputAdornment {...props}>\n {!disabled && !loading && (\n <IconButton\n {...TestIdUtil.createAttributes('DatePicker-reset')}\n aria-label={t`Clear date field`}\n className={'DatePicker-resetButton'}\n // eslint-disable-next-line @eslint-react/kit/jsx-no-bind\n onClick={() => onResetButtonClickRef.current()}\n sx={{\n '& svg': {\n fontSize: '16px',\n },\n }}\n tabIndex={-1}\n >\n <ClearIcon />\n </IconButton>\n )}\n {children}\n </InputAdornment>\n );\n};\n","import type { ReactElement } from 'react';\nimport {\n useCallback,\n useMemo,\n useRef,\n} from 'react';\nimport {\n FormControl,\n FormHelperText,\n} from '@mui/material';\nimport type {\n ControllerRenderProps,\n FieldValues,\n Path,\n PathValue,\n UseControllerReturn,\n} from 'react-hook-form';\nimport {\n Controller,\n useFormContext,\n} from 'react-hook-form';\nimport type {\n DatePickerProps as MuiDatePickerProps,\n DateTimePickerProps as MuiDateTimePickerProps,\n} from '@mui/x-date-pickers';\nimport {\n LocalizationProvider,\n DatePicker as MuiDatePicker,\n DateTimePicker as MuiDateTimePicker,\n} from '@mui/x-date-pickers';\nimport classNames from 'classnames';\nimport type { Locale } from 'date-fns';\nimport {\n enUS,\n sv,\n} from 'date-fns/locale';\nimport { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';\nimport { TestIdUtil } from '@gen-epix/ui-core/utils/TestIdUtil';\nimport { DATE_FORMAT } from '@gen-epix/ui-core/constants/date';\n\nimport { FormUtil } from '../../../utils/FormUtil';\nimport { FormFieldHelperText } from '../../helpers/FormFieldHelperText';\nimport { FormFieldLoadingIndicator } from '../../helpers/FormFieldLoadingIndicator';\n\nimport { DatePickerInputAdornment } from './DatePickerInputAdornment';\n\n\nexport type DatePickerProps<TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>> = {\n readonly dateFormat?: typeof DATE_FORMAT[keyof typeof DATE_FORMAT];\n readonly disabled?: boolean;\n readonly infoMessage?: string;\n readonly label: string;\n readonly loading?: boolean;\n readonly name: TName;\n readonly onChange?: (value: Date) => void;\n readonly required?: boolean;\n readonly warningMessage?: string;\n};\n\nexport const DatePicker = <TFieldValues extends FieldValues, TName extends Path<TFieldValues> = Path<TFieldValues>>({\n dateFormat = DATE_FORMAT.DATE,\n disabled = false,\n infoMessage,\n label,\n loading = false,\n name,\n onChange: onChangeProp,\n required = false,\n warningMessage,\n}: DatePickerProps<TFieldValues, TName>): ReactElement => {\n const { control, formState: { errors } } = useFormContext<TFieldValues>();\n const errorMessage = FormUtil.getFieldErrorMessage(errors, name);\n const hasError = !!errorMessage;\n const hasWarning = !!warningMessage && !hasError;\n const inputRef = useRef<HTMLInputElement>(null);\n const onResetButtonClickRef = useRef<() => void>(() => undefined);\n\n const onMuiDatePickerChange = useCallback((onChange: ControllerRenderProps<TFieldValues, TName>['onChange']) =>\n (newValue: Date) => {\n if (onChangeProp) {\n onChangeProp(newValue);\n }\n onChange(newValue);\n }\n , [onChangeProp]);\n\n const customLocale = useMemo<Locale>(() => {\n /**\n * Use everything from enUS, but format dates the Swedish way (ISO 8601)\n */\n return {\n ...enUS,\n formatLong: sv.formatLong,\n };\n }, []);\n\n const views = useMemo<MuiDateTimePickerProps['views']>(() => {\n switch (dateFormat) {\n case DATE_FORMAT.DATE:\n case DATE_FORMAT.DATE_TIME:\n return undefined;\n case DATE_FORMAT.YEAR:\n return ['year'];\n case DATE_FORMAT.YEAR_MONTH:\n return ['year', 'month'];\n default:\n throw new Error(`Unsupported date format: ${dateFormat}`);\n }\n }, [dateFormat]);\n\n const MuiComponent = dateFormat === DATE_FORMAT.DATE_TIME ? MuiDateTimePicker : MuiDatePicker;\n\n const renderController = useCallback(({ field: { onBlur, onChange, ref, value } }: UseControllerReturn<TFieldValues, TName>) => {\n ref({\n focus: () => {\n inputRef?.current?.focus();\n },\n });\n\n onResetButtonClickRef.current = () => {\n onChange(null);\n };\n\n return (\n <FormControl\n {...TestIdUtil.createAttributes('DatePicker', { label, name })}\n fullWidth\n sx={{\n '&:hover .DatePicker-resetButton, &:focus-within .DatePicker-resetButton': {\n display: 'initial',\n },\n '& .DatePicker-resetButton': {\n display: 'none',\n },\n }}\n >\n <LocalizationProvider\n adapterLocale={customLocale}\n dateAdapter={AdapterDateFns}\n >\n <MuiComponent\n disabled={disabled || loading}\n inputRef={inputRef}\n label={label}\n loading={loading}\n onChange={onMuiDatePickerChange(onChange)}\n openTo={dateFormat === DATE_FORMAT.DATE_TIME ? undefined : 'year'}\n slotProps={{\n textField: {\n className: classNames({ 'Mui-warning': hasWarning }),\n error: hasError,\n onBlur,\n slotProps: {\n inputLabel: {\n required,\n },\n },\n variant: 'outlined',\n },\n }}\n slots={{\n inputAdornment: (props) => (\n <DatePickerInputAdornment\n {...props}\n disabled={disabled}\n loading={loading}\n onResetButtonClickRef={onResetButtonClickRef}\n />\n ),\n }}\n value={value}\n views={views as MuiDatePickerProps['views']}\n />\n </LocalizationProvider>\n {!!loading && <FormFieldLoadingIndicator />}\n <FormHelperText sx={{ ml: 0 }}>\n <FormFieldHelperText\n errorMessage={errorMessage}\n infoMessage={infoMessage}\n noIndent\n warningMessage={warningMessage}\n />\n </FormHelperText>\n </FormControl>\n );\n }, [MuiComponent, customLocale, dateFormat, disabled, errorMessage, hasError, hasWarning, infoMessage, label, loading, name, onMuiDatePickerChange, required, views, warningMessage]);\n\n return (\n <Controller\n control={control}\n defaultValue={'' as PathValue<TFieldValues, TName>}\n name={name}\n render={renderController}\n />\n );\n};\n"],"mappings":"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"}