diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0be4c35b7..358c85bcc9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,11 @@ should change the heading of the (upcoming) version to include a major version b
## @rjsf/utils
- switch `lodash.isEqualWith` to `fast-equals.createCustomEqual` providing `areFunctionsEqual` assuming any functions are equal.
+- Fixed issue with file accept attribute, fixing [#4404](https://github.com/rjsf-team/react-jsonschema-form/issues/4404).
+
+## @rjsf/mui
+
+- Fixed issue with file accept attribute, fixing [#4404](https://github.com/rjsf-team/react-jsonschema-form/issues/4404).
# 5.24.1
diff --git a/packages/docs/docs/usage/validation.md b/packages/docs/docs/usage/validation.md
index 9e15796838..00674a7e43 100644
--- a/packages/docs/docs/usage/validation.md
+++ b/packages/docs/docs/usage/validation.md
@@ -88,7 +88,7 @@ import * as precompiledValidator from 'path_to/yourCompiledSchema';
const validator = createPrecompiledValidator(precompiledValidator as ValidatorFunctions);
-render(
, document.getElementById('app'));
+render(, document.getElementById('app'));
```
### Dynamically pre-compiling validators
diff --git a/packages/mui/src/BaseInputTemplate/BaseInputTemplate.tsx b/packages/mui/src/BaseInputTemplate/BaseInputTemplate.tsx
index 9c3f0a706a..4eb8fea899 100644
--- a/packages/mui/src/BaseInputTemplate/BaseInputTemplate.tsx
+++ b/packages/mui/src/BaseInputTemplate/BaseInputTemplate.tsx
@@ -53,16 +53,8 @@ export default function BaseInputTemplate<
} = props;
const inputProps = getInputProps(schema, type, options);
// Now we need to pull out the step, min, max into an inner `inputProps` for material-ui
- const { step, min, max, ...rest } = inputProps;
- const otherProps = {
- inputProps: {
- step,
- min,
- max,
- ...(schema.examples ? { list: examplesId(id) } : undefined),
- },
- ...rest,
- };
+ const { step, min, max, accept, ...rest } = inputProps;
+ const htmlInputProps = { step, min, max, accept, ...(schema.examples ? { list: examplesId(id) } : undefined) };
const _onChange = ({ target: { value } }: ChangeEvent) =>
onChange(value === '' ? options.emptyValue : value);
const _onBlur = ({ target }: FocusEvent) => onBlur(id, target && target.value);
@@ -84,7 +76,10 @@ export default function BaseInputTemplate<
autoFocus={autofocus}
required={required}
disabled={disabled || readonly}
- {...otherProps}
+ slotProps={{
+ htmlInput: htmlInputProps,
+ }}
+ {...rest}
value={value || value === 0 ? value : ''}
error={rawErrors.length > 0}
onChange={onChangeOverride || _onChange}
diff --git a/packages/utils/src/getInputProps.ts b/packages/utils/src/getInputProps.ts
index 39d31e0e87..6ebb673322 100644
--- a/packages/utils/src/getInputProps.ts
+++ b/packages/utils/src/getInputProps.ts
@@ -51,5 +51,9 @@ export default function getInputProps<
inputProps.autoComplete = options.autocomplete;
}
+ if (options.accept) {
+ inputProps.accept = options.accept as string;
+ }
+
return inputProps;
}
diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts
index 359d6bb45c..2d6c8335c3 100644
--- a/packages/utils/src/types.ts
+++ b/packages/utils/src/types.ts
@@ -150,6 +150,8 @@ export type InputPropsType = Omit & {
step?: number | 'any';
/** Specifies the `autoComplete` value for an element */
autoComplete?: HTMLInputElement['autocomplete'];
+ /** Specifies a filter for what file types the user can upload. */
+ accept?: HTMLInputElement['accept'];
};
/** Type describing an id used for a field in the `IdSchema` */
diff --git a/packages/utils/test/getInputProps.test.ts b/packages/utils/test/getInputProps.test.ts
index 8708083730..0ad15f22f9 100644
--- a/packages/utils/test/getInputProps.test.ts
+++ b/packages/utils/test/getInputProps.test.ts
@@ -1,16 +1,23 @@
-import { getInputProps, RJSFSchema } from '../src';
+import { getInputProps, RJSFSchema, UIOptionsType } from '../src';
describe('getInputProps', () => {
it('returns type=text when no other data is passed', () => {
expect(getInputProps({})).toEqual({ type: 'text' });
});
it('returns type and autoComplete from options when provided', () => {
- const options = { inputType: 'password', autocomplete: 'on' };
+ const options: UIOptionsType = { inputType: 'password', autocomplete: 'on' };
expect(getInputProps({}, 'text', options)).toEqual({
type: options.inputType,
autoComplete: options.autocomplete,
});
});
+ it('returns type and accept from options when provided', () => {
+ const options: UIOptionsType = { accept: '.pdf' };
+ expect(getInputProps({}, 'file', options)).toEqual({
+ type: 'file',
+ accept: options.accept,
+ });
+ });
it('returns type=defaultType even when schema has type', () => {
const schema: RJSFSchema = {
type: 'number',