Add prop type validation

This commit is contained in:
Tom Southall
2022-02-12 20:52:34 +00:00
parent 69f1a5c46d
commit a2e9ee56d0
4 changed files with 2739 additions and 36 deletions

2688
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,10 @@
"description": "In development. React multi-search autocomplete component.", "description": "In development. React multi-search autocomplete component.",
"author": "Tom Southall", "author": "Tom Southall",
"keywords": [], "keywords": [],
"files": ["dist", "README.md"], "files": [
"dist",
"README.md"
],
"main": "./dist/turnstone.umd.js", "main": "./dist/turnstone.umd.js",
"module": "./dist/turnstone.es.js", "module": "./dist/turnstone.es.js",
"exports": { "exports": {
@@ -20,23 +23,31 @@
}, },
"dependencies": { "dependencies": {
"first-of-type": "^1.0.0", "first-of-type": "^1.0.0",
"prop-types": "^15.8.1",
"react-use": "^17.3.2", "react-use": "^17.3.2",
"setify": "^1.0.4", "setify": "^1.0.4",
"swr": "^1.1.2", "swr": "^1.1.2",
"use-debounce": "^7.0.1" "use-debounce": "^7.0.1"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-react": "^1.0.7",
"eslint": "^8.9.0",
"eslint-plugin-react": "^7.28.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"@vitejs/plugin-react": "^1.0.7",
"vite": "^2.8.0" "vite": "^2.8.0"
}, },
"eslintConfig": { "eslintConfig": {
"env": {
"es6": true
},
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"react-app", "plugin:react/recommended"
"react-app/jest" ],
] "parserOptions": {
"sourceType": "module"
}
}, },
"browserslist": { "browserslist": {
"production": [ "production": [
@@ -50,4 +61,4 @@
"last 1 safari version" "last 1 safari version"
] ]
} }
} }

View File

@@ -17,5 +17,3 @@ const App = () => {
} }
export default App export default App

View File

@@ -1,5 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { TurnstoneContextProvider } from './context/turnstone' import { TurnstoneContextProvider } from './context/turnstone'
import isUndefined from './utils/isUndefined'
import AutocompleteInput from './components/input' import AutocompleteInput from './components/input'
export default function Turnstone(props) { export default function Turnstone(props) {
@@ -13,3 +15,63 @@ export default function Turnstone(props) {
</TurnstoneContextProvider> </TurnstoneContextProvider>
) )
} }
//////////////////////////////////////////////////////
// Prop validation //
//////////////////////////////////////////////////////
const msgBothRequired = `Either a "data" prop or an "itemGroups" prop must be provided. Both are missing.`
const msgOneOnly = `Both a "data" prop and an "itemGroups" prop were provided. Provide one only.`
const requiredPropsAreMissing = (props) => isUndefined(props.data) && isUndefined(props.itemGroups)
Turnstone.propTypes = {
autoFocus: PropTypes.bool,
data: (props) => {
if(requiredPropsAreMissing(props)) return new Error(msgBothRequired)
if(!isUndefined(props.data) && !isUndefined(props.itemGroups)) return new Error(msgOneOnly)
PropTypes.checkPropTypes(
{data: PropTypes.oneOfType([PropTypes.array, PropTypes.func])},
{data: props.data},
'prop', 'Turnstone'
)
},
dataSearchType: PropTypes.oneOf(['startswith', 'contains']),
debounceWait: PropTypes.number,
defaultItemGroups: PropTypes.array,
defaultItemGroupsAreImmutable: PropTypes.bool,
displayField: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
itemGroups: (props) => {
if(requiredPropsAreMissing(props)) return new Error(msgBothRequired)
if(!isUndefined(props.data) && !isUndefined(props.itemGroups)) return new Error(msgOneOnly)
PropTypes.checkPropTypes(
{
itemGroups: PropTypes.arrayOf(PropTypes.exact({
name: PropTypes.string.isRequired,
data: PropTypes.oneOfType([
PropTypes.func,
PropTypes.array
]).isRequired,
dataSearchType: PropTypes.oneOf(['startswith', 'contains']),
displayField: PropTypes.string,
ratio: PropTypes.number
}))
},
{itemGroups: props.itemGroups},
'prop', 'Turnstone'
)
},
itemGroupsAreImmutable: PropTypes.bool,
loadingMessage: PropTypes.string,
minQueryLength: PropTypes.number,
noItemsMessage: PropTypes.string,
onChange: PropTypes.func,
onSelect: PropTypes.func,
onEnter: PropTypes.func,
onTab: PropTypes.func,
placeholder: PropTypes.string,
maxItems: PropTypes.number,
splitChar: PropTypes.string,
styles: PropTypes.object,
text: PropTypes.string
}
//////////////////////////////////////////////////////