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

View File

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

View File

@@ -1,5 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import { TurnstoneContextProvider } from './context/turnstone'
import isUndefined from './utils/isUndefined'
import AutocompleteInput from './components/input'
export default function Turnstone(props) {
@@ -13,3 +15,63 @@ export default function Turnstone(props) {
</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
}
//////////////////////////////////////////////////////