diff --git a/docs.md b/docs.md index 83b450f7..a1c7eaf2 100644 --- a/docs.md +++ b/docs.md @@ -136,24 +136,27 @@ * [triggerOnKeys][132] * [Parameters][133] * [Examples][134] -* [Modal][135] +* [filterInvalidHtmlProps][135] * [Parameters][136] * [Examples][137] -* [cloudinaryUploader][138] +* [Modal][138] * [Parameters][139] * [Examples][140] +* [cloudinaryUploader][141] + * [Parameters][142] + * [Examples][143] ## ColorPicker -A control component for picking a hex color value. Built using the [react-color][141] `ChromePicker`. +A control component for picking a hex color value. Built using the [react-color][144] `ChromePicker`. ### Parameters -* `value` **[String][142]?** The hex value of the selected color -* `onChange` **[Function][143]?** A function called with the new hex value when a color is selected -* `onOpen` **[Function][143]?** A function called when the picker is expanded -* `onClose` **[Function][143]?** A function called when the picker is closed -* `active` **[Boolean][144]?** A boolean that controls whether the picker is expanded or not. +* `value` **[String][145]?** The hex value of the selected color +* `onChange` **[Function][146]?** A function called with the new hex value when a color is selected +* `onOpen` **[Function][146]?** A function called when the picker is expanded +* `onClose` **[Function][146]?** A function called when the picker is closed +* `active` **[Boolean][147]?** A boolean that controls whether the picker is expanded or not. ### Examples @@ -177,15 +180,15 @@ A control component for navigating between multiple numbered pages. ### Parameters -* `value` **[Number][145]** The number of the current page (optional, default `1`) -* `onChange` **[Function][143]?** A function called with the new value when a page is clicked. -* `min` **[Number][145]** The number of the first page (optional, default `1`) -* `max` **[Number][145]** The number of the last page. (optional, default `1`) -* `alwaysShow` **[Boolean][144]** Always show the component, even when there's only one page visible. (optional, default `false`) -* `pagesShown` **[Number][145]** The number of pages to display around (and including) the current page (optional, default `3`) -* `previousLabel` **[String][142]** The text of the "previous page" button (optional, default `'Prev'`) -* `nextLabel` **[String][142]** The text of the "next page" button (optional, default `'Next'`) -* `delimiter` **[String][142]** The delimiter that will be shown when there are hidden pages (optional, default `'...'`) +* `value` **[Number][148]** The number of the current page (optional, default `1`) +* `onChange` **[Function][146]?** A function called with the new value when a page is clicked. +* `min` **[Number][148]** The number of the first page (optional, default `1`) +* `max` **[Number][148]** The number of the last page. (optional, default `1`) +* `alwaysShow` **[Boolean][147]** Always show the component, even when there's only one page visible. (optional, default `false`) +* `pagesShown` **[Number][148]** The number of pages to display around (and including) the current page (optional, default `3`) +* `previousLabel` **[String][145]** The text of the "previous page" button (optional, default `'Prev'`) +* `nextLabel` **[String][145]** The text of the "next page" button (optional, default `'Next'`) +* `delimiter` **[String][145]** The delimiter that will be shown when there are hidden pages (optional, default `'...'`) ### Examples @@ -212,11 +215,11 @@ A control component for navigating among multiple tabs ### Parameters -* `vertical` **[Boolean][144]?** A boolean setting the `className` of the `ul` to 'horizontal' (default), or 'vertical', which determines the alignment of the tabs (optional, default `false`) -* `options` **[Array][146]** An array of tab values (strings or key-value pairs) -* `value` **([String][142] | [Number][145])** The value of the current tab -* `onChange` **[Function][143]?** A function called with the new value when a tab is clicked -* `activeClassName` **[String][142]?** The class of the active tab, (optional, default `active`) +* `vertical` **[Boolean][147]?** A boolean setting the `className` of the `ul` to 'horizontal' (default), or 'vertical', which determines the alignment of the tabs (optional, default `false`) +* `options` **[Array][149]** An array of tab values (strings or key-value pairs) +* `value` **([String][145] | [Number][148])** The value of the current tab +* `onChange` **[Function][146]?** A function called with the new value when a tab is clicked +* `activeClassName` **[String][145]?** The class of the active tab, (optional, default `active`) ### Examples @@ -248,12 +251,12 @@ If a className is provided to the component, it will be appended to the conditio ### Parameters -* `invalid` **[Boolean][144]?** Whether or not a related form is invalid (will set aria-disabled when `true`) -* `pristine` **[Boolean][144]?** Whether or not a related form is pristine (will set aria-disabled when `true`) -* `variant` **[String][142]** A descriptive string that will be appended to the button's class with format `button-` (optional, default `"primary"`) -* `submitting` **[Boolean][144]?** Whether or not a related form is submitting (will give button class `'in-progress` when `true`) -* `type` **[Boolean][144]** The [type][147] attribute of the button element (optional, default `"button"`) -* `children` **[Function][143]?** Any React component(s) being wrapped by the button +* `invalid` **[Boolean][147]?** Whether or not a related form is invalid (will set aria-disabled when `true`) +* `pristine` **[Boolean][147]?** Whether or not a related form is pristine (will set aria-disabled when `true`) +* `variant` **[String][145]** A descriptive string that will be appended to the button's class with format `button-` (optional, default `"primary"`) +* `submitting` **[Boolean][147]?** Whether or not a related form is submitting (will give button class `'in-progress` when `true`) +* `type` **[Boolean][147]** The [type][150] attribute of the button element (optional, default `"button"`) +* `children` **[Function][146]?** Any React component(s) being wrapped by the button ### Examples @@ -280,8 +283,8 @@ If a `className` is provided to the component, it will be appended to the defaul ### Parameters -* `className` **[String][142]?** A class to add to the wrapper -* `children` **[Function][143]?** The React component(s) being wrapped +* `className` **[String][145]?** A class to add to the wrapper +* `children` **[Function][146]?** The React component(s) being wrapped ### Examples @@ -332,8 +335,8 @@ This input only accepts and stores boolean values. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object ### Examples @@ -367,10 +370,10 @@ Clicking an unselected checkbox adds its value to this array, and clicking a sel ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `options` **[Array][146]** An array of checkbox values (strings, numbers, or key-value pairs) -* `checkboxInputProps` **[Object][148]** An object of key-value pairs representing props to pass down to all checkbox inputs (optional, default `{}`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `options` **[Array][149]** An array of checkbox values (strings, numbers, or key-value pairs) +* `checkboxInputProps` **[Object][151]** An object of key-value pairs representing props to pass down to all checkbox inputs (optional, default `{}`) ### Examples @@ -425,7 +428,7 @@ export default TodoForm ## CloudinaryFileInput -A wrapper around a file input component (defaults to [FileInput][36]) that automatically uploads files to cloudinary via the [cloudinaryUploader][151] HOC. +A wrapper around a file input component (defaults to [FileInput][36]) that automatically uploads files to cloudinary via the [cloudinaryUploader][154] HOC. The value of this input will only get set upon successful upload. The shape of the value will be of a file object or an array of file objects with the `url` set to the public URL of the uploaded file. The full response from Cloudinary is accessible via the value's `meta.cloudinary` key. @@ -436,12 +439,12 @@ or via the `CLOUDINARY_CLOUD_NAME` and `CLOUDINARY_BUCKET` env vars (recommended ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `fileInput` **[Function][143]** A component that gets wrapped with Cloudinary upload logic (optional, default `FileInput`) -* `multiple` **[Boolean][144]** A flag indicating whether or not to accept multiple files (optional, default `false`) -* `onUploadSuccess` **[Function][143]** A handler that gets invoked with the response from a successful upload to Cloudinary (optional, default `noop`) -* `onUploadFailure` **[Function][143]** A handler that gets invoked with the error from a failed upload to Cloudinary (optional, default `noop`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `fileInput` **[Function][146]** A component that gets wrapped with Cloudinary upload logic (optional, default `FileInput`) +* `multiple` **[Boolean][147]** A flag indicating whether or not to accept multiple files (optional, default `false`) +* `onUploadSuccess` **[Function][146]** A handler that gets invoked with the response from a successful upload to Cloudinary (optional, default `noop`) +* `onUploadFailure` **[Function][146]** A handler that gets invoked with the error from a failed upload to Cloudinary (optional, default `noop`) ### Examples @@ -470,8 +473,8 @@ The value of this input is a hex color string. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object ### Examples @@ -493,21 +496,21 @@ function UserForm ({ handleSubmit, pristine, invalid, submitting }) { ## DateInput -An input component that wraps a `DatePicker` component from the [react-datepicker][152] library. +An input component that wraps a `DatePicker` component from the [react-datepicker][155] library. This wrapper adds the following functionality to `DatePicker`: * Adapts it to receive `redux-form`-style input props. * Adds name and error labels. With the exception of the `input` and `meta` props, all props are passed down to the `DatePicker` component. -A full list of props supported by this component can be found [here][153]. Note that unfortunately `aria-*` props are **not** supported. +A full list of props supported by this component can be found [here][156]. Note that unfortunately `aria-*` props are **not** supported. -*Note: this component requires special styles in order to render correctly. To include these styles in your project, follow the directions in the main [README][154] file.* +*Note: this component requires special styles in order to render correctly. To include these styles in your project, follow the directions in the main [README][157] file.* ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object ### Examples @@ -530,7 +533,7 @@ function BirthdayForm ({ handleSubmit }) { ## DropdownCheckboxGroup A group of checkboxes that can be used in a `redux-form`-controlled form. -Wraps the [CheckboxGroup][21] component in a [DropdownSelect][155] component, which displays the selected values as a list. +Wraps the [CheckboxGroup][21] component in a [DropdownSelect][158] component, which displays the selected values as a list. Options are displayed in a scrollable `Select`-style dropdown container. The value of each checkbox is specified via the `options` prop. This prop can either be: @@ -543,9 +546,9 @@ Clicking an unselected checkbox adds its value to this array, and clicking a sel ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `options` **[Array][146]** An array of checkbox values (strings or key-value pairs) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `options` **[Array][149]** An array of checkbox values (strings or key-value pairs) ### Examples @@ -588,18 +591,18 @@ A component passed using `previewComponent` will receive the following props: ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `readFiles` **[Function][143]** A callback that is fired with new files and is expected to return an array of file objects with the `url` key set to the "read" value. This can be either a data URL or the public URL from a 3rd party API (optional, default `readFilesAsDataUrls`) -* `multiple` **[Boolean][144]** A flag indicating whether or not to accept multiple files (optional, default `false`) -* `accept` **[String][142]?** Value that defines the file types the file input should accept (e.g., ".doc,.docx"). More info: [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept][156] -* `capture` **(`"user"` | `"environment"`)?** Value that specifies which camera to use, if the accept attribute indicates the input type of image or video. This is not available for all devices (e.g., desktops). More info: [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture][157] -* `onRemove` **[Function][143]** A callback fired when a file is removed (optional, default `noop`) -* `previewComponent` **[Function][143]** A custom component that is used to display a preview of each attached file (optional, default `RenderPreview`) -* `removeComponent` **[Function][143]** A custom component that receives `value` and `onRemove` props (optional, default `RemoveButton`) -* `thumbnail` **[String][142]?** A placeholder image to display before the file is loaded -* `hidePreview` **[Boolean][144]** A flag indicating whether or not to hide the file preview (optional, default `false`) -* `selectText` **[String][142]?** An override for customizing the text that is displayed on the input's label. Defaults to 'Select File' or 'Select File(s)' depending on the `multiple` prop value +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `readFiles` **[Function][146]** A callback that is fired with new files and is expected to return an array of file objects with the `url` key set to the "read" value. This can be either a data URL or the public URL from a 3rd party API (optional, default `readFilesAsDataUrls`) +* `multiple` **[Boolean][147]** A flag indicating whether or not to accept multiple files (optional, default `false`) +* `accept` **[String][145]?** Value that defines the file types the file input should accept (e.g., ".doc,.docx"). More info: [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept][159] +* `capture` **(`"user"` | `"environment"`)?** Value that specifies which camera to use, if the accept attribute indicates the input type of image or video. This is not available for all devices (e.g., desktops). More info: [https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture][160] +* `onRemove` **[Function][146]** A callback fired when a file is removed (optional, default `noop`) +* `previewComponent` **[Function][146]** A custom component that is used to display a preview of each attached file (optional, default `RenderPreview`) +* `removeComponent` **[Function][146]** A custom component that receives `value` and `onRemove` props (optional, default `RemoveButton`) +* `thumbnail` **[String][145]?** A placeholder image to display before the file is loaded +* `hidePreview` **[Boolean][147]** A flag indicating whether or not to hide the file preview (optional, default `false`) +* `selectText` **[String][145]?** An override for customizing the text that is displayed on the input's label. Defaults to 'Select File' or 'Select File(s)' depending on the `multiple` prop value ### Examples @@ -653,9 +656,9 @@ Any children passed to this component will be rendered within this wrapper. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `type` **[String][142]?** A string to specify the type of input element (defaults to `text`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `type` **[String][145]?** A string to specify the type of input element (defaults to `text`) ### Examples @@ -687,7 +690,7 @@ Additionally, the fieldset of this [Input][41] will be given the class `"icon-la ### Parameters -* `icon` **[String][142]** The name of the icon associated with the input +* `icon` **[String][145]** The name of the icon associated with the input ### Examples @@ -711,15 +714,15 @@ function TwitterForm ({ handleSubmit, pristine, invalid, submitting }) { ## MaskedInput -A masked input that can be used in a `redux-form`-controlled form. Built on top of [cleave.js][158]. +A masked input that can be used in a `redux-form`-controlled form. Built on top of [cleave.js][161]. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `maskOptions` **[Object][148]** An object of options to pass to the underlying `Cleave` instance. [(supported options)][159] (optional, default `{}`) -* `onInit` **[Function][143]** A function that will be invoked with the object representing the class when the input is initialized (optional, default `null`) -* `htmlRef` **([Function][143] | [Object][148])** A stable reference that can be used to access the DOM node of the underlying input (optional, default `null`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `maskOptions` **[Object][151]** An object of options to pass to the underlying `Cleave` instance. [(supported options)][162] (optional, default `{}`) +* `onInit` **[Function][146]** A function that will be invoked with the object representing the class when the input is initialized (optional, default `null`) +* `htmlRef` **([Function][146] | [Object][151])** A stable reference that can be used to access the DOM node of the underlying input (optional, default `null`) ### Examples @@ -746,12 +749,12 @@ A range input that can be used in a `redux-form`-controlled form. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `min` **[Number][145]** The minumum attribute of the slider control (optional, default `0`) -* `max` **[Number][145]** The maximum attribute of the slider control (optional, default `100`) -* `step` **[Number][145]** The step attribute of the slider control (optional, default `1`) -* `hideRangeValue` **[Boolean][144]** A boolean representing whether or not to display the range value (optional, default `false`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `min` **[Number][148]** The minumum attribute of the slider control (optional, default `0`) +* `max` **[Number][148]** The maximum attribute of the slider control (optional, default `100`) +* `step` **[Number][148]** The step attribute of the slider control (optional, default `1`) +* `hideRangeValue` **[Boolean][147]** A boolean representing whether or not to display the range value (optional, default `false`) ### Examples @@ -789,10 +792,10 @@ The value of the entire `RadioGroup` component is the value of the currently sel ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `options` **[Array][146]** An array of radio button values (strings, numbers, booleans, or key-value pairs) -* `radioInputProps` **[Object][148]** An object of key-value pairs representing props to pass down to all radio inputs (optional, default `{}`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `options` **[Array][149]** An array of radio button values (strings, numbers, booleans, or key-value pairs) +* `radioInputProps` **[Object][151]** An object of key-value pairs representing props to pass down to all radio inputs (optional, default `{}`) ### Examples @@ -867,12 +870,12 @@ The value of the `Select` component will be the same as the value of the selecte ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `options` **[Array][146]** An array of option values (strings, numbers, or key-value pairs). This prop will be ignored if `optionGroups` is present. -* `optionGroups` **[Array][146]** An array of option group objects -* `placeholder` **[String][142]** A string to display as a placeholder option. Pass in `false` to hide the placeholder option. (optional, default `'Select'`) -* `enablePlaceholderOption` **[Boolean][144]** A flag indicating that the placeholder option should not be `disabled` (optional, default `false`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `options` **[Array][149]** An array of option values (strings, numbers, or key-value pairs). This prop will be ignored if `optionGroups` is present. +* `optionGroups` **[Array][149]** An array of option group objects +* `placeholder` **[String][145]** A string to display as a placeholder option. Pass in `false` to hide the placeholder option. (optional, default `'Select'`) +* `enablePlaceholderOption` **[Boolean][147]** A flag indicating that the placeholder option should not be `disabled` (optional, default `false`) ### Examples @@ -925,14 +928,14 @@ A switch input that can be used in a `redux-form`-controlled form. This input only accepts and stores boolean values. -See the [react-switch][160] documentation for additional styling properties. +See the [react-switch][163] documentation for additional styling properties. ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `checkedIcon` **([Element][161] | [Boolean][144])** An icon displayed when the switch is checked. Set to `false` if no check icon is desired. -* `uncheckedIcon` **([Element][161] | [Boolean][144])** An icon displayed when the switch is unchecked. Set to `false` if no uncheck icon is desired. +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `checkedIcon` **([Element][164] | [Boolean][147])** An icon displayed when the switch is checked. Set to `false` if no check icon is desired. +* `uncheckedIcon` **([Element][164] | [Boolean][147])** An icon displayed when the switch is unchecked. Set to `false` if no uncheck icon is desired. ### Examples @@ -958,10 +961,10 @@ Can forward ref down to textarea input and optionally displays a character count ### Parameters -* `input` **[Object][148]** A `redux-form` [input][149] object -* `meta` **[Object][148]** A `redux-form` [meta][150] object -* `maxLength` **[Number][145]?** The maximum allowed length of the input -* `hideCharacterCount` **[Boolean][144]** Whether to hide the character count if given a maxLength (optional, default `false`) +* `input` **[Object][151]** A `redux-form` [input][152] object +* `meta` **[Object][151]** A `redux-form` [meta][153] object +* `maxLength` **[Number][148]?** The maximum allowed length of the input +* `hideCharacterCount` **[Boolean][147]** Whether to hide the character count if given a maxLength (optional, default `false`) * `forwardedRef` **Ref?** A ref to be forwarded to `textarea` input (standard `ref` cannot currently be forwarded) ### Examples @@ -989,7 +992,7 @@ A label for displaying error message. ### Parameters -* `children` **[String][142]** A message to display +* `children` **[String][145]** A message to display ### Examples @@ -1029,10 +1032,10 @@ In addition to the props below, any extra props will be passed directly to the i ### Parameters -* `error` **([String][142] | [Array][146])** An error message or array of error messages to display -* `invalid` **[Boolean][144]** Whether the associated input has an invalid value -* `touched` **[String][142]** Whether the associated input has been touched -* `name` **[String][142]** The name of the input (used to generate a unique ID) +* `error` **([String][145] | [Array][149])** An error message or array of error messages to display +* `invalid` **[Boolean][147]** Whether the associated input has an invalid value +* `touched` **[String][145]** Whether the associated input has been touched +* `name` **[String][145]** The name of the input (used to generate a unique ID) ### Examples @@ -1070,21 +1073,21 @@ The text of the label is set using the following rules: * Else If the `label` prop is set to a string, the label will display that text * Otherwise, the label will be set using the `name` prop. -If `name` is used to set the text, it will be stripped of its prefixes and converted to [start case][162]. +If `name` is used to set the text, it will be stripped of its prefixes and converted to [start case][165]. For instance: `'person.firstName'` becomes `'First Name'` -Note: When using third party form libraries (e.g., [Redux Form][163]), it's likely that setting the `required` prop will turn on the browser's automatic validation, which could cause the library to behave unexpectedly. If the browser validation behavior is causing issues, then add a `noValidate` prop to the form to [turn off][164] automatic validation. (e.g., `
`) +Note: When using third party form libraries (e.g., [Redux Form][166]), it's likely that setting the `required` prop will turn on the browser's automatic validation, which could cause the library to behave unexpectedly. If the browser validation behavior is causing issues, then add a `noValidate` prop to the form to [turn off][167] automatic validation. (e.g., `
`) ### Parameters -* `name` **[String][142]** The name of the associated input -* `id` **[String][142]** The id of the associated input (defaults to name) (optional, default `name`) -* `hint` **[String][142]?** A usage hint for the associated input -* `label` **([String][142] | [Boolean][144])?** Custom text for the label -* `tooltip` **[String][142]?** A message to display in a tooltip -* `required` **[Boolean][144]?** A boolean value to indicate whether the field is required -* `requiredIndicator` **[String][142]?** Custom character to denote a field is required (optional, default `''`) +* `name` **[String][145]** The name of the associated input +* `id` **[String][145]** The id of the associated input (defaults to name) (optional, default `name`) +* `hint` **[String][145]?** A usage hint for the associated input +* `label` **([String][145] | [Boolean][147])?** Custom text for the label +* `tooltip` **[String][145]?** A message to display in a tooltip +* `required` **[Boolean][147]?** A boolean value to indicate whether the field is required +* `requiredIndicator` **[String][145]?** Custom character to denote a field is required (optional, default `''`) ### Examples @@ -1122,9 +1125,9 @@ use the [omitLabelProps][91] helper. ### Parameters -* `hideErrorLabel` **[Boolean][144]?** A boolean determining whether to hide the error label on input error (optional, default `false`) -* `labelComponent` **[Function][143]** A custom label component for the input (optional, default `InputLabel`) -* `errorComponent` **[Function][143]** A custom error component for the input (optional, default `InputError`) +* `hideErrorLabel` **[Boolean][147]?** A boolean determining whether to hide the error label on input error (optional, default `false`) +* `labelComponent` **[Function][146]** A custom label component for the input (optional, default `InputLabel`) +* `errorComponent` **[Function][146]** A custom error component for the input (optional, default `InputError`) ### Examples @@ -1208,7 +1211,7 @@ by stripping its namespace and converting it to start case. ### Parameters -* `name` **[String][142]** A redux-form field name +* `name` **[String][145]** A redux-form field name ### Examples @@ -1217,7 +1220,7 @@ convertNameToLabel('example') // -> 'Example' convertNameToLabel('person.firstName') // -> 'First Name' ``` -Returns **[String][142]** A user-friendly field label +Returns **[String][145]** A user-friendly field label ## fieldOptionsType @@ -1233,8 +1236,8 @@ Type: PropTypes ## fieldPropTypesWithValue -A function that takes `PropTypes` for a `redux-form` [input][149] object. -Returns an object containing all `PropTypes` for `redux-form` [Field][165] components. +A function that takes `PropTypes` for a `redux-form` [input][152] object. +Returns an object containing all `PropTypes` for `redux-form` [Field][168] components. ### Parameters @@ -1264,20 +1267,20 @@ fieldPropTypesWithValue(valuePropType) // } ``` -Returns **[Object][148]** `PropTypes` for `redux-form` [input][149] and [meta][150] objects +Returns **[Object][151]** `PropTypes` for `redux-form` [input][152] and [meta][153] objects ## defaultValueTypes -A constant representing default `PropTypes` for `redux-form` [Field][165] values. +A constant representing default `PropTypes` for `redux-form` [Field][168] values. Default types are either `number` or `string`. Type: PropTypes ## fieldPropTypes -An object containing the default `PropTypes` for `redux-form` [Field][165] components. +An object containing the default `PropTypes` for `redux-form` [Field][168] components. -Type: [Object][148] +Type: [Object][151] ## radioGroupPropTypes @@ -1305,7 +1308,7 @@ Omits the following props: ### Parameters -* `props` **[Object][148]** A props object +* `props` **[Object][151]** A props object ### Examples @@ -1338,7 +1341,7 @@ function Input (props) { } ``` -Returns **[Object][148]** `props` object with [InputLabel][71] props omitted +Returns **[Object][151]** `props` object with [InputLabel][71] props omitted ## replaceEmptyStringValue @@ -1379,7 +1382,7 @@ This component's behavior is largely determined by the [TableColumn][103] compon ### Parameters -* `data` **[Array][146]** An array of objects to display in the table- one object per row (optional, default `[]`) +* `data` **[Array][149]** An array of objects to display in the table- one object per row (optional, default `[]`) ### Examples @@ -1402,15 +1405,15 @@ This component's behavior is largely determined by the [TableColumn][103] compon ### Parameters -* `data` **[Array][146]** An array of objects to display in the table- one object per row (optional, default `[]`) -* `initialColumn` **[Number][145]** The name of the column that's initially selected (optional, default `''`) -* `initialAscending` **[Boolean][144]** The sort direction of the initial column (optional, default `true`) -* `disableReverse` **[Boolean][144]** Disables automatic reversing of descending sorts (optional, default `false`) -* `disableSort` **[Boolean][144]** A flag to disable sorting on all columns and hide sorting arrows. (optional, default `false`) -* `controlled` **[Boolean][144]** A flag to disable sorting on all columns, while keeping the sorting arrows. Used when sorting is controlled by an external source. (optional, default `false`) -* `onChange` **[Function][143]?** A callback that will be fired when the sorting state changes -* `rowComponent` **[Function][143]?** A custom row component for the table. Will be passed the `data` for the row, several internal table states (the current column being sorted (sortPath), whether ascending sort is active or not (ascending), the sorting function (sortFunc), and the value getter (valueGetter)) as well as `children` to render. -* `headerComponent` **[Function][143]?** A custom header component for the table. Will be passed the configuration of the corresponding column, as well as the current `sortPath` / `ascending` and an `onClick` handler. May be overridden by a custom `headerComponent` for a column. +* `data` **[Array][149]** An array of objects to display in the table- one object per row (optional, default `[]`) +* `initialColumn` **[Number][148]** The name of the column that's initially selected (optional, default `''`) +* `initialAscending` **[Boolean][147]** The sort direction of the initial column (optional, default `true`) +* `disableReverse` **[Boolean][147]** Disables automatic reversing of descending sorts (optional, default `false`) +* `disableSort` **[Boolean][147]** A flag to disable sorting on all columns and hide sorting arrows. (optional, default `false`) +* `controlled` **[Boolean][147]** A flag to disable sorting on all columns, while keeping the sorting arrows. Used when sorting is controlled by an external source. (optional, default `false`) +* `onChange` **[Function][146]?** A callback that will be fired when the sorting state changes +* `rowComponent` **[Function][146]?** A custom row component for the table. Will be passed the `data` for the row, several internal table states (the current column being sorted (sortPath), whether ascending sort is active or not (ascending), the sorting function (sortFunc), and the value getter (valueGetter)) as well as `children` to render. +* `headerComponent` **[Function][146]?** A custom header component for the table. Will be passed the configuration of the corresponding column, as well as the current `sortPath` / `ascending` and an `onClick` handler. May be overridden by a custom `headerComponent` for a column. ### Examples @@ -1432,16 +1435,16 @@ A component used to pass column information to a [Table][97] or [SortableTable][ ### Parameters -* `name` **[String][142]** The key of the value to display in the column from each data object -* `label` **[String][142]?** The text that will be displayed in the column header. Defaults to `name`. -* `sortFunc` **[Function][143]?** The function that will be used to sort the table data when the column is selected -* `component` **[Function][143]?** A custom cell component for the column. Will be passed the `key`, `name`, `value` and `data` for the row. -* `headerComponent` **[Function][143]?** A custom header component for the column. Will be passed the configuration of the column, as well as the current `sortPath` / `ascending` and an `onClick` handler. `onClick` must be appended to allow for sorting functionality. -* `onClick` **[Function][143]?** A function that will be called `onClick` on every cell in the column. -* `format` **[Function][143]?** A function that formats the value displayed in each cell in the column -* `disabled` **[Boolean][144]?** A flag that disables sorting for the column -* `placeholder` **[String][142]?** A string that will be displayed if the value of the cell is `undefined` or `null` -* `valueGetter` **[Function][143]?** A function that will return a cell's value derived from each data object. Will be passed the `data` for the row. +* `name` **[String][145]** The key of the value to display in the column from each data object +* `label` **[String][145]?** The text that will be displayed in the column header. Defaults to `name`. +* `sortFunc` **[Function][146]?** The function that will be used to sort the table data when the column is selected +* `component` **[Function][146]?** A custom cell component for the column. Will be passed the `key`, `name`, `value` and `data` for the row. +* `headerComponent` **[Function][146]?** A custom header component for the column. Will be passed the configuration of the column, as well as the current `sortPath` / `ascending` and an `onClick` handler. `onClick` must be appended to allow for sorting functionality. +* `onClick` **[Function][146]?** A function that will be called `onClick` on every cell in the column. +* `format` **[Function][146]?** A function that formats the value displayed in each cell in the column +* `disabled` **[Boolean][147]?** A flag that disables sorting for the column +* `placeholder` **[String][145]?** A string that will be displayed if the value of the cell is `undefined` or `null` +* `valueGetter` **[Function][146]?** A function that will return a cell's value derived from each data object. Will be passed the `data` for the row. ### Examples @@ -1471,9 +1474,9 @@ A component that displays a flash message. ### Parameters -* `children` **[String][142]** The flash message that will be displayed. -* `isError` **[Boolean][144]** A flag to indicate whether the message is an error message. (optional, default `false`) -* `onDismiss` **[Function][143]?** A callback for dismissing the flash message. The dismiss button will only be shown if this callback is provided. +* `children` **[String][145]** The flash message that will be displayed. +* `isError` **[Boolean][147]** A flag to indicate whether the message is an error message. (optional, default `false`) +* `onDismiss` **[Function][146]?** A callback for dismissing the flash message. The dismiss button will only be shown if this callback is provided. ### Examples @@ -1494,14 +1497,14 @@ function MyView () { ## FlashMessageContainer -A component that displays multiple flash messages generated by [redux-flash][166]. +A component that displays multiple flash messages generated by [redux-flash][169]. Most apps will need only one of these containers at the top level. Will pass down any additional props to the inner `FlashMessage` components. ### Parameters -* `messages` **[Object][148]** The flash messages that will be displayed. -* `limit` **[Number][145]?** Maximum number of concurrent messages to display +* `messages` **[Object][151]** The flash messages that will be displayed. +* `limit` **[Number][148]?** Maximum number of concurrent messages to display ### Examples @@ -1547,7 +1550,7 @@ depending on whether `isLoading` is true or false ### Parameters -* `isLoading` **[Boolean][144]** Whether the inner component should be indicated as loading (optional, default `false`) +* `isLoading` **[Boolean][147]** Whether the inner component should be indicated as loading (optional, default `false`) ### Examples @@ -1570,8 +1573,8 @@ certain path, and runs given comparison function on those values. ### Parameters -* `path` **[String][142]** Name of the path to values -* `func` **[Function][143]** Comparison function to run on values at specified path +* `path` **[String][145]** Name of the path to values +* `func` **[Function][146]** Comparison function to run on values at specified path ### Examples @@ -1593,7 +1596,7 @@ people.sort(ageComparator) // ] ``` -Returns **[Function][143]** Comparison function +Returns **[Function][146]** Comparison function ## generateInputErrorId @@ -1602,7 +1605,7 @@ is centralized to facilitate reference by multiple input components. ### Parameters -* `name` **[String][142]** The name of the input +* `name` **[String][145]** The name of the input ### Examples @@ -1614,7 +1617,7 @@ generateInputErrorId(name) // 'cardNumberError' ``` -Returns **[String][142]** String representing error id +Returns **[String][145]** String representing error id ## serializeOptions @@ -1623,7 +1626,7 @@ Function that transforms string options into object options with keys of ### Parameters -* `optionArray` **[Array][146]** Array of option values +* `optionArray` **[Array][149]** Array of option values ### Examples @@ -1635,7 +1638,7 @@ serializeOptions(options) // [{ key: 'apple', value: 'apple' }, { key: 'banana', value: 'banana' }] ``` -Returns **[Array][146]** Array of object options +Returns **[Array][149]** Array of object options ## serializeOptionGroups @@ -1644,7 +1647,7 @@ object options with keys of `key` and `value` ### Parameters -* `optionGroupArray` **[Array][146]** Array of option values +* `optionGroupArray` **[Array][149]** Array of option values ### Examples @@ -1668,7 +1671,7 @@ serializeOptionGroups(optionGroups) // ] ``` -Returns **[Array][146]** Array of object group options +Returns **[Array][149]** Array of object group options ## stripNamespace @@ -1678,7 +1681,7 @@ Returns the argument if it is undefined or not a string. ### Parameters -* `str` **[String][142]** Namespaced string +* `str` **[String][145]** Namespaced string ### Examples @@ -1690,14 +1693,14 @@ stripNamespace(namespace) // 'name' ``` -Returns **[String][142]** String with namespace removed +Returns **[String][145]** String with namespace removed ## triggerOnKeys ### Parameters -* `fn` **[Function][143]** The function to trigger -* `keyCodes` **([Number][145] | [String][142] | [Array][146]<([Number][145] | [String][142])>)** Number, String, or Array of key codes +* `fn` **[Function][146]** The function to trigger +* `keyCodes` **([Number][148] | [String][145] | [Array][149]<([Number][148] | [String][145])>)** Number, String, or Array of key codes ### Examples @@ -1706,23 +1709,48 @@ const triggerOnEnter = triggerOnKeys(() => console.log('Hi'), [13]) function MyExample () { return } ``` -Returns **[Function][143]** Returns a function that takes an event and watches for keys +Returns **[Function][146]** Returns a function that takes an event and watches for keys + +## filterInvalidHtmlProps + +A function that filters out props 1) that are not recognized as a valid HTML attribute +and 2) that are valid HTML attributes but not allowed for the provided element. + +### Parameters + +* `element` **[String][145]** HTML element +* `props` **[Object][151]** React props that are set on the HTML element + +### Examples + +```javascript +const rest = { form: "planDetailsForm", type: "text", placeholder: "Enter plan name", showField: true } + + This field is required! + + +// +// This field is required! +// +``` + +Returns **[Object][151]** React props that are valid for the HTML element ## Modal -A modal component with a built-in close button. Uses [`react-modal`][167] under the hood, and can accept any props `react-modal` does. +A modal component with a built-in close button. Uses [`react-modal`][170] under the hood, and can accept any props `react-modal` does. -Unlike `react-modal`, this component does not require an `isOpen` prop to render. However, that prop can still be used in the case where animations are necessary- see [this issue][168]. +Unlike `react-modal`, this component does not require an `isOpen` prop to render. However, that prop can still be used in the case where animations are necessary- see [this issue][171]. Note: this component requires custom styles. These styles can be imported from the `lib/styles` folder as shown inn the example below. ### Parameters -* `onClose` **[Function][143]** A handler for closing the modal. May be triggered via the close button, and outside click, or a key press. -* `className` **([String][142] | [Object][148])** Additional class to append to the base class of the modal (modal-inner). See [React Modal's style documentation][169] for more details. (optional, default `""`) -* `overlayClassName` **([String][142] | [Object][148])** Additional class to append to the base class of the modal overlay (modal-fade-screen). See [React Modal's style documentation][169] for more details. (optional, default `""`) -* `isOpen` **[Boolean][144]** A flag for showing the modal. (optional, default `true`) -* `preventClose` **[Boolean][144]** A flag for preventing the modal from being closed (close button, escape, or overlay click). (optional, default `false`) +* `onClose` **[Function][146]** A handler for closing the modal. May be triggered via the close button, and outside click, or a key press. +* `className` **([String][145] | [Object][151])** Additional class to append to the base class of the modal (modal-inner). See [React Modal's style documentation][172] for more details. (optional, default `""`) +* `overlayClassName` **([String][145] | [Object][151])** Additional class to append to the base class of the modal overlay (modal-fade-screen). See [React Modal's style documentation][172] for more details. (optional, default `""`) +* `isOpen` **[Boolean][147]** A flag for showing the modal. (optional, default `true`) +* `preventClose` **[Boolean][147]** A flag for preventing the modal from being closed (close button, escape, or overlay click). (optional, default `false`) ### Examples @@ -1750,7 +1778,7 @@ function MyView () { ## cloudinaryUploader -A function that returns a React HOC for uploading files to (Cloudinary)\[[https://cloudinary.com][170]]. +A function that returns a React HOC for uploading files to (Cloudinary)\[[https://cloudinary.com][173]]. `cloudinaryUploader` exposes the following props to the wrapped component: @@ -1759,15 +1787,15 @@ A function that returns a React HOC for uploading files to (Cloudinary)\[[https: ### Parameters -* `cloudName` **[string][142]** The name of the Cloudinary cloud to upload to. Can also be set via `CLOUDINARY_CLOUD_NAME` in `process.env`. -* `bucket` **[string][142]** The name of the Cloudinary bucket to upload to. Can also be set via `CLOUDINARY_BUCKET` in `process.env`. -* `apiAdapter` **[Object][148]** Adapter that responds to `post` with a Promise -* `uploadPreset` **[string][142]** The name of the Cloudinary upload preset. Can also be set via `CLOUDINARY_UPLOAD_PRESET` in `process.env`. (optional, default `default`) -* `endpoint` **[string][142]** The endpoint for the upload request. Can also be set via `CLOUDINARY_ENDPOINT` in `process.env`. (optional, default `https://api.cloudinary.com/v1_1/`) -* `fileType` **[string][142]** The type of file. (optional, default `auto`) -* `cloudinaryPublicId` **[string][142]?** The name of the file stored in Cloudinary. -* `createPublicId` **[string][142]?** A function to generate a custom public id for the uploaded file. This function is passed the file object and is expected to return a string. Overridden by the `cloudinaryPublicId` prop. -* `requestOptions` **[object][148]** Options for the request, as specified by (`lp-requests`)\[[https://github.com/LaunchPadLab/lp-requests/blob/master/src/http/http.js][171]]. (optional, default `DEFAULT_REQUEST_OPTIONS`) +* `cloudName` **[string][145]** The name of the Cloudinary cloud to upload to. Can also be set via `CLOUDINARY_CLOUD_NAME` in `process.env`. +* `bucket` **[string][145]** The name of the Cloudinary bucket to upload to. Can also be set via `CLOUDINARY_BUCKET` in `process.env`. +* `apiAdapter` **[Object][151]** Adapter that responds to `post` with a Promise +* `uploadPreset` **[string][145]** The name of the Cloudinary upload preset. Can also be set via `CLOUDINARY_UPLOAD_PRESET` in `process.env`. (optional, default `default`) +* `endpoint` **[string][145]** The endpoint for the upload request. Can also be set via `CLOUDINARY_ENDPOINT` in `process.env`. (optional, default `https://api.cloudinary.com/v1_1/`) +* `fileType` **[string][145]** The type of file. (optional, default `auto`) +* `cloudinaryPublicId` **[string][145]?** The name of the file stored in Cloudinary. +* `createPublicId` **[string][145]?** A function to generate a custom public id for the uploaded file. This function is passed the file object and is expected to return a string. Overridden by the `cloudinaryPublicId` prop. +* `requestOptions` **[object][151]** Options for the request, as specified by (`lp-requests`)\[[https://github.com/LaunchPadLab/lp-requests/blob/master/src/http/http.js][174]]. (optional, default `DEFAULT_REQUEST_OPTIONS`) ### Examples @@ -1799,7 +1827,7 @@ export default compose( )(CloudinaryFileInput) ``` -Returns **[Function][143]** A HOC that can be used to wrap a component. +Returns **[Function][146]** A HOC that can be used to wrap a component. [1]: #colorpicker @@ -2069,76 +2097,82 @@ Returns **[Function][143]** A HOC that can be used to wrap a component. [134]: #examples-43 -[135]: #modal +[135]: #filterinvalidhtmlprops [136]: #parameters-40 [137]: #examples-44 -[138]: #cloudinaryuploader +[138]: #modal [139]: #parameters-41 [140]: #examples-45 -[141]: https://casesandberg.github.io/react-color/ +[141]: #cloudinaryuploader + +[142]: #parameters-42 + +[143]: #examples-46 + +[144]: https://casesandberg.github.io/react-color/ -[142]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[145]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[143]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[146]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[144]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[147]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[145]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number +[148]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[146]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[149]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array -[147]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type +[150]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type -[148]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[151]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[149]: http://redux-form.com/6.5.0/docs/api/Field.md/#input-props +[152]: http://redux-form.com/6.5.0/docs/api/Field.md/#input-props -[150]: http://redux-form.com/6.5.0/docs/api/Field.md/#meta-props +[153]: http://redux-form.com/6.5.0/docs/api/Field.md/#meta-props -[151]: https://github.com/LaunchPadLab/lp-hoc/blob/master/docs.md#cloudinaryuploader +[154]: https://github.com/LaunchPadLab/lp-hoc/blob/master/docs.md#cloudinaryuploader -[152]: https://github.com/Hacker0x01/react-datepicker +[155]: https://github.com/Hacker0x01/react-datepicker -[153]: https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md +[156]: https://github.com/Hacker0x01/react-datepicker/blob/master/docs/datepicker.md -[154]: README.md#dateinput-styles +[157]: README.md#dateinput-styles -[155]: DropdownSelect +[158]: DropdownSelect -[156]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept +[159]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept -[157]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture +[160]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture -[158]: https://github.com/nosir/cleave.js +[161]: https://github.com/nosir/cleave.js -[159]: https://github.com/nosir/cleave.js/blob/master/doc/options.md +[162]: https://github.com/nosir/cleave.js/blob/master/doc/options.md -[160]: https://github.com/markusenglund/react-switch +[163]: https://github.com/markusenglund/react-switch -[161]: https://developer.mozilla.org/docs/Web/API/Element +[164]: https://developer.mozilla.org/docs/Web/API/Element -[162]: https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage +[165]: https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage -[163]: https://redux-form.com +[166]: https://redux-form.com -[164]: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation#Validating_forms_using_JavaScript +[167]: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation#Validating_forms_using_JavaScript -[165]: http://redux-form.com/6.5.0/docs/api/Field.md/ +[168]: http://redux-form.com/6.5.0/docs/api/Field.md/ -[166]: https://github.com/LaunchPadLab/redux-flash +[169]: https://github.com/LaunchPadLab/redux-flash -[167]: https://github.com/reactjs/react-modal +[170]: https://github.com/reactjs/react-modal -[168]: https://github.com/reactjs/react-modal/issues/25 +[171]: https://github.com/reactjs/react-modal/issues/25 -[169]: http://reactcommunity.org/react-modal/styles/classes/#for-the-content-and-overlay +[172]: http://reactcommunity.org/react-modal/styles/classes/#for-the-content-and-overlay -[170]: https://cloudinary.com +[173]: https://cloudinary.com -[171]: https://github.com/LaunchPadLab/lp-requests/blob/master/src/http/http.js +[174]: https://github.com/LaunchPadLab/lp-requests/blob/master/src/http/http.js diff --git a/package.json b/package.json index 6941b414..7eb87918 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,8 @@ "cleave.js": "^1.6.0", "date-fns": "^2.28.0", "filter-invalid-dom-props": "^2.1.0", + "html-attributes": "^1.1.0", + "html-element-attributes": "^3.1.0", "lodash": "^4.17.21", "prop-types": "^15.8.1", "react-color": "^2.19.3", diff --git a/src/forms/labels/input-error.js b/src/forms/labels/input-error.js index 446a36fd..b64666c2 100644 --- a/src/forms/labels/input-error.js +++ b/src/forms/labels/input-error.js @@ -1,7 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -import { generateInputErrorId, filterInvalidDOMProps } from '../../utils' +import { generateInputErrorId, filterInvalidHtmlProps } from '../../utils' import { hasInputError } from '../helpers' /** @@ -75,7 +75,7 @@ function InputError({ error, invalid, touched, name, className, ...rest }) { {formatError(error)} diff --git a/src/utils/local/filter-invalid-html-props.js b/src/utils/local/filter-invalid-html-props.js new file mode 100644 index 00000000..bed09aec --- /dev/null +++ b/src/utils/local/filter-invalid-html-props.js @@ -0,0 +1,54 @@ +import { htmlElementAttributes } from 'html-element-attributes' +import htmlAttributes from 'html-attributes' // An object of all HTML attributes with the JSX prop (e.g., "className", "tabIndex") as keys and the JavaScript prop (e.g., "class", "tabindex") as values +import { difference, omitBy, compact, concat } from 'lodash' +import filterInvalidDOMProps from 'filter-invalid-dom-props' + +// An array of basic HTML _global_ attributes (note: this does not include event handlers, "aria-", "role", and "data-") +const basicGlobalAttributes = htmlElementAttributes['*'] +// An array of all existing HTML attributes (note: this does not include event handlers, "aria-" and "data-") +const allHtmlAttributes = Object.values(htmlAttributes) + +/** + * + * A function that filters out props 1) that are not recognized as a valid HTML attribute + * and 2) that are valid HTML attributes but not allowed for the provided element. + * + * @param {String} element - HTML element + * @param {Object} props - React props that are set on the HTML element + * @returns {Object} - React props that are valid for the HTML element + * + * @example + * + * const rest = { form: "planDetailsForm", type: "text", placeholder: "Enter plan name", showField: true } + * + * This field is required! + * + * + * // + * // This field is required! + * // + * + */ + +function filterInvalidHtmlProps(element, props) { + // This util (filterInvalidDOMProps) covers event handlers such as "onClick" and props that begin with "data-" and "aria-" + // but it does not filter out HTML attributes that are not allowed for the element in question + const validDOMProps = filterInvalidDOMProps(props) + + const notAllowedAttributes = generateNotAllowedAttributes(element) + return omitBy(validDOMProps, (_, key) => + notAllowedAttributes.includes(htmlAttributes[key]) + ) +} + +// ----- PRIVATE ------ +// Returns an array of all existing HTML attributes (in plain JavaScript) that are not allowed for the given element +function generateNotAllowedAttributes(element) { + const additionalAllowedAttributes = htmlElementAttributes[element] // e.g., ul => ['compact', 'type'] + const allAllowedAttributes = compact( + concat(basicGlobalAttributes, 'role', additionalAllowedAttributes) + ) + return difference(allHtmlAttributes, allAllowedAttributes) +} + +export default filterInvalidHtmlProps diff --git a/src/utils/local/index.js b/src/utils/local/index.js index e39f9170..2267a853 100644 --- a/src/utils/local/index.js +++ b/src/utils/local/index.js @@ -8,3 +8,4 @@ export stripNamespace from './strip-namespace' export triggerOnKeys from './trigger-on-keys' export KeyCodes from './key-codes' export useToggle from './use-toggle' +export filterInvalidHtmlProps from './filter-invalid-html-props' diff --git a/yarn.lock b/yarn.lock index 57b07047..750f15bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8109,11 +8109,16 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -html-attributes@1.1.0: +html-attributes@1.1.0, html-attributes@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/html-attributes/-/html-attributes-1.1.0.tgz#82027a4fac7a6070ea6c18cc3886aea18d6dea09" integrity sha1-ggJ6T6x6YHDqbBjMOIauoY1t6gk= +html-element-attributes@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-element-attributes/-/html-element-attributes-3.1.0.tgz#07869037b9020bec3bb1897263e97dd65829d15b" + integrity sha512-cHM9qM06tyWHwvGqDqVEBwoYtGgyq7X/GQt3dor38M1hYMZw1yVadaDQrwwQer6NefiYAoHaqFARI8ETMCAOYA== + html-element-map@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.3.1.tgz#44b2cbcfa7be7aa4ff59779e47e51012e1c73c08"