Skip to content

Commit

Permalink
feat #218 - Fix FormSubmitBtn useShortcutProps type, add comments
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-dassana committed Feb 19, 2021
1 parent e8fba5d commit 36e2fa8
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/components/Form/Form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ const Template: Story<FormProps<UserModel>> = (args: FormProps<UserModel>) => (
name='cloudAccounts'
treeData={treeData}
/>
<Form.SubmitButton>Submit</Form.SubmitButton>
<Form.SubmitButton useShortcutProps={{ keys: ['Shift', 'Enter'] }}>
Submit
</Form.SubmitButton>
</Form>
)

Expand Down
9 changes: 8 additions & 1 deletion src/components/Form/FormSubmitButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import {
} from 'components/ShortcutMicrocopy'
import { useShortcut, UseShortcutConfig } from '@dassana-io/web-utils'

/**
* TODO: Move to web-utils
* More info on Distributive Conditional Types: https://stackoverflow.com/a/57103940/11279811
*/
type DistributiveOmit<T, K extends keyof T> = T extends T ? Omit<T, K> : never

export interface FormButtonProps
extends Omit<ButtonProps, 'loading' | 'onClick'> {
isDisabled?: (
Expand All @@ -18,7 +24,8 @@ export interface FormButtonProps
) => boolean
renderShortcutMicrocopy?: boolean
shortcutMicrocopyProps?: ShortcutMicrocopyProps
useShortcutProps?: Omit<

useShortcutProps?: DistributiveOmit<
UseShortcutConfig,
'additionalConditionalFn' | 'callback'
>
Expand Down
17 changes: 15 additions & 2 deletions src/components/Form/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,42 @@ interface Params {
required?: boolean
}

/**
* For Form items that have input type of array, react-hook-form's required check no longer works - an array of length 0 is a valid response.
* This util function will add an extra "required" rule that checks if the array is empty or not
* It will also take the rules passed to the component and format it to satisfy react-hook-form's ValidationRules type - which consists of some default rules and a customizable "validate" rule.
*/
export const getRulesForArrVals = ({
rules = {},
required = false
}: Params): ValidationRules => {
// first make a clone of the passed rules
const newRules = cloneDeep(rules)

if (required) {
// we still want to make sure required is set to true in case value is undefined instead of an array
newRules.required = true

// Then create requiredRules which consists of an object with the required rule that checks if input array is empty
const requiredRules = {
required: (values: string[]) => values.length > 0 || ''
required: (values?: string[]) => (values && values.length > 0) || ''
}

let extraRules = {}

// Because react-hook-form's rules.validate can either be an object of validation rules or a function, we need to check the type of the passed "validate" rule and copy it to "newRules" accordingly
// If a "validate" is passed,
if (newRules.validate) {
// and if it's an object, just set extraRules to be the "validate" rules object
if (typeof newRules.validate === 'object') {
extraRules = { ...newRules.validate }
extraRules = newRules.validate
} else {
// otherwise it's a function so we copy that to a new key called "validate"
extraRules = { validate: newRules.validate }
}
}

// In the end, we copy over the extra validation rules and required rules to "validate" - all custom validation rules need to go inside this "validate" rules object
newRules.validate = {
...extraRules,
...requiredRules
Expand Down

0 comments on commit 36e2fa8

Please sign in to comment.