diff --git a/apps/demo/src/app/constants/validationColors.constants.ts b/apps/demo/src/app/constants/validationColors.constants.ts deleted file mode 100644 index 8c45d12..0000000 --- a/apps/demo/src/app/constants/validationColors.constants.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { - getColorByRulesClassnames, - getWeightByRulesClassnames -} from '@bedrockstreaming/form-validation-rule-list'; - -export const VALIDATION_CLASSNAMES = { - complete: 'complete-li', - incomplete: 'incomplete-li', - idle: 'idle-li' -}; - -export const weightByRulesClassnames = getWeightByRulesClassnames( - VALIDATION_CLASSNAMES -); - -export const colorByRulesClassnames = getColorByRulesClassnames( - VALIDATION_CLASSNAMES -); diff --git a/apps/demo/src/app/examples/with-material-ui/atoms/rule-list.component.tsx b/apps/demo/src/app/examples/with-material-ui/atoms/rule-list.component.tsx new file mode 100644 index 0000000..bd13064 --- /dev/null +++ b/apps/demo/src/app/examples/with-material-ui/atoms/rule-list.component.tsx @@ -0,0 +1,52 @@ +import { + COMPLETE_STATUS, + DEFAULT_STATUS, + INCOMPLETE_STATUS +} from '@bedrockstreaming/form-validation-rule-list'; +import _ from 'lodash'; +import { makeStyles } from '@mui/styles'; + +const useStyles = makeStyles<{ [key: string]: unknown }>({ + list: { + display: 'flex', + margin: 0, + padding: 0, + textAlign: 'left', + listStyle: 'none' + }, + listItem: { + margin: '4px', + fontSize: 'smaller' + }, + [DEFAULT_STATUS]: { + color: '#2e2e2d' + }, + [COMPLETE_STATUS]: { + color: '#4ed569' + }, + [INCOMPLETE_STATUS]: { + color: '#da3b2b' + } +}); + +export const RuleList = ({ + items +}: { + items: { key: string; status: string }[]; +}) => { + const classes = useStyles(); + + return ( + + ); +}; diff --git a/apps/demo/src/app/examples/with-material-ui/dictionary/date.component.tsx b/apps/demo/src/app/examples/with-material-ui/dictionary/date.component.tsx index 59a892f..a311fba 100644 --- a/apps/demo/src/app/examples/with-material-ui/dictionary/date.component.tsx +++ b/apps/demo/src/app/examples/with-material-ui/dictionary/date.component.tsx @@ -11,10 +11,7 @@ import _ from 'lodash'; import { BirthdateInput } from '@forms/examples/birthdate'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../../../constants/validationColors.constants'; +import { RuleList } from '../atoms/rule-list.component'; const ValidatedTextField = withValidationRuleList(TextField); @@ -70,8 +67,7 @@ export const DateInput = ({ rules={rules} value={value} data-testid={dataTestId} - colorByRulesClassnames={colorByRulesClassnames} - weightByRulesClassnames={weightByRulesClassnames} + ruleComponent={RuleList} /> ); diff --git a/apps/demo/src/app/examples/with-material-ui/dictionary/password.component.tsx b/apps/demo/src/app/examples/with-material-ui/dictionary/password.component.tsx index 94b4b05..9ea380c 100644 --- a/apps/demo/src/app/examples/with-material-ui/dictionary/password.component.tsx +++ b/apps/demo/src/app/examples/with-material-ui/dictionary/password.component.tsx @@ -10,10 +10,7 @@ import { import { TextField } from '@mui/material'; import _ from 'lodash'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../../../constants/validationColors.constants'; +import { RuleList } from '../atoms/rule-list.component'; const ValidatedTextField = withValidationRuleList(TextField); @@ -67,8 +64,7 @@ export const Password = ({ rules={rules} value={value} data-testid={dataTestId} - colorByRulesClassnames={colorByRulesClassnames} - weightByRulesClassnames={weightByRulesClassnames} + ruleComponent={RuleList} /> ); }; diff --git a/apps/demo/src/app/examples/with-material-ui/login/form.component.tsx b/apps/demo/src/app/examples/with-material-ui/login/form.component.tsx index 3b9cb54..4019f19 100644 --- a/apps/demo/src/app/examples/with-material-ui/login/form.component.tsx +++ b/apps/demo/src/app/examples/with-material-ui/login/form.component.tsx @@ -41,30 +41,7 @@ const { const useStyles = makeStyles({ root: { - margin: '16px auto', - - '& .validation-rule-ul': { - display: 'flex', - padding: 0, - listStyle: 'none' - }, - - '& .validation-rule-ul li': { - margin: '4px', - fontSize: 'smaller' - }, - - '& .complete-li': { - color: '#4ed569' - }, - '& .incomplete-li,.idle-li': { - color: '#da3b2b' - }, - '& .step-fields-actions': { - width: '100%', - display: 'flex', - justifyContent: 'center' - } + margin: '16px auto' } }); diff --git a/apps/demo/src/app/examples/with-material-ui/register/form.component.tsx b/apps/demo/src/app/examples/with-material-ui/register/form.component.tsx index 325857a..abdb6f8 100644 --- a/apps/demo/src/app/examples/with-material-ui/register/form.component.tsx +++ b/apps/demo/src/app/examples/with-material-ui/register/form.component.tsx @@ -46,30 +46,7 @@ const { const useStyles = makeStyles({ root: { - margin: '16px auto', - - '& .validation-rule-ul': { - display: 'flex', - padding: 0, - listStyle: 'none' - }, - - '& .validation-rule-ul li': { - margin: '4px', - fontSize: 'smaller' - }, - - '& .complete-li': { - color: '#4ed569' - }, - '& .incomplete-li,.idle-li': { - color: '#da3b2b' - }, - '& .step-fields-actions': { - width: '100%', - display: 'flex', - justifyContent: 'center' - } + margin: '16px auto' } }); diff --git a/apps/demo/src/app/examples/with-styled-components/atoms/rule-list.component.tsx b/apps/demo/src/app/examples/with-styled-components/atoms/rule-list.component.tsx new file mode 100644 index 0000000..5e4bac1 --- /dev/null +++ b/apps/demo/src/app/examples/with-styled-components/atoms/rule-list.component.tsx @@ -0,0 +1,45 @@ +import { + COMPLETE_STATUS, + INCOMPLETE_STATUS, + DEFAULT_STATUS +} from '@bedrockstreaming/form-validation-rule-list'; +import styled from 'styled-components'; + +export const List = styled.ul` + display: flex; + margin: 0; + padding: 0; + text-align: left; + list-style: none; +`; + +export const ListItem = styled.li` + margin: 4px; + font-size: smaller; + + &.${COMPLETE_STATUS} { + color: #4ed569; + } + &.${INCOMPLETE_STATUS} { + color: #da3b2b; + } + &.${DEFAULT_STATUS} { + color: #2e2e2d; + } +`; + +export const RuleList = ({ + items +}: { + items: { key: string; status: string }[]; +}) => { + return ( + + {items.map((item) => ( + + {item.key} + + ))} + + ); +}; diff --git a/apps/demo/src/app/examples/with-styled-components/dictionary/date.component.tsx b/apps/demo/src/app/examples/with-styled-components/dictionary/date.component.tsx index fb41c4f..b9d0a2c 100644 --- a/apps/demo/src/app/examples/with-styled-components/dictionary/date.component.tsx +++ b/apps/demo/src/app/examples/with-styled-components/dictionary/date.component.tsx @@ -9,10 +9,8 @@ import { ValidatedTextField } from '@forms/examples/styled-inputs'; import { BirthdateInput } from '@forms/examples/birthdate'; import { TextFieldMarginWrapper } from './styled'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../../../constants/validationColors.constants'; + +import { RuleList } from '../atoms/rule-list.component'; export const DateInput = ({ errors, @@ -45,8 +43,7 @@ export const DateInput = ({ hasError={hasError} valid={isValid} rules={rules} - weightByRulesClassnames={weightByRulesClassnames} - colorByRulesClassnames={colorByRulesClassnames} + ruleComponent={RuleList} {...props} /> diff --git a/apps/demo/src/app/examples/with-styled-components/dictionary/password.component.tsx b/apps/demo/src/app/examples/with-styled-components/dictionary/password.component.tsx index 058b400..e6d445e 100644 --- a/apps/demo/src/app/examples/with-styled-components/dictionary/password.component.tsx +++ b/apps/demo/src/app/examples/with-styled-components/dictionary/password.component.tsx @@ -8,10 +8,8 @@ import { import { ValidatedPasswordTextField } from '@forms/examples/styled-inputs'; import { TextFieldTopMarginWrapper } from './styled'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../../../constants/validationColors.constants'; + +import { RuleList } from '../atoms/rule-list.component'; export const Password = ({ errors, @@ -39,9 +37,7 @@ export const Password = ({ valid={isValid} {...props} rules={rules} - weightByRulesClassnames={weightByRulesClassnames} - colorByRulesClassnames={colorByRulesClassnames} - label={props.label} + ruleComponent={RuleList} /> ); diff --git a/apps/demo/src/app/examples/with-styled-components/dictionary/text.component.tsx b/apps/demo/src/app/examples/with-styled-components/dictionary/text.component.tsx index 946d5e1..d907cc6 100644 --- a/apps/demo/src/app/examples/with-styled-components/dictionary/text.component.tsx +++ b/apps/demo/src/app/examples/with-styled-components/dictionary/text.component.tsx @@ -4,10 +4,6 @@ import { Validations } from '@bedrockstreaming/form-builder'; import { ValidatedTextField } from '@forms/examples/styled-inputs'; import { TextFieldMarginWrapper } from './styled'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../../../constants/validationColors.constants'; export const Text = ({ errors, @@ -30,10 +26,7 @@ export const Text = ({ hasError={!!error} errorText={error} valid={!!props.value && !error} - weightByRulesClassnames={weightByRulesClassnames} - colorByRulesClassnames={colorByRulesClassnames} {...props} - label={props.label} /> ); diff --git a/apps/docsite/src/form/constants/validationColors.constants.js b/apps/docsite/src/form/constants/validationColors.constants.js deleted file mode 100644 index 8c45d12..0000000 --- a/apps/docsite/src/form/constants/validationColors.constants.js +++ /dev/null @@ -1,18 +0,0 @@ -import { - getColorByRulesClassnames, - getWeightByRulesClassnames -} from '@bedrockstreaming/form-validation-rule-list'; - -export const VALIDATION_CLASSNAMES = { - complete: 'complete-li', - incomplete: 'incomplete-li', - idle: 'idle-li' -}; - -export const weightByRulesClassnames = getWeightByRulesClassnames( - VALIDATION_CLASSNAMES -); - -export const colorByRulesClassnames = getColorByRulesClassnames( - VALIDATION_CLASSNAMES -); diff --git a/apps/docsite/src/form/dictionary/date.component.jsx b/apps/docsite/src/form/dictionary/date.component.jsx index 527f11e..05de418 100644 --- a/apps/docsite/src/form/dictionary/date.component.jsx +++ b/apps/docsite/src/form/dictionary/date.component.jsx @@ -5,14 +5,11 @@ import { withValidationRuleList } from '@bedrockstreaming/form-validation-rule-list'; import { TextField, Box } from '@mui/material'; -import _ from 'lodash'; import { BirthdateInput } from '@forms/examples/birthdate'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../constants/validationColors.constants'; +import { RuleList } from '../rule-list.component'; + const ValidatedTextField = withValidationRuleList(TextField); @@ -54,8 +51,7 @@ export const DateInput = ({ rules={rules} value={value} data-testid={dataTestId} - colorByRulesClassnames={colorByRulesClassnames} - weightByRulesClassnames={weightByRulesClassnames} + ruleComponent={RuleList} /> ); diff --git a/apps/docsite/src/form/dictionary/password.component.jsx b/apps/docsite/src/form/dictionary/password.component.jsx index 46bc00f..5067624 100644 --- a/apps/docsite/src/form/dictionary/password.component.jsx +++ b/apps/docsite/src/form/dictionary/password.component.jsx @@ -6,12 +6,8 @@ import { } from '@bedrockstreaming/form-validation-rule-list'; import { TextField, Box } from '@mui/material'; -import _ from 'lodash'; -import { - colorByRulesClassnames, - weightByRulesClassnames -} from '../constants/validationColors.constants'; +import { RuleList } from '../rule-list.component'; const ValidatedTextField = withValidationRuleList(TextField); @@ -53,8 +49,7 @@ export const Password = ({ rules={rules} value={value} data-testid={dataTestId} - colorByRulesClassnames={colorByRulesClassnames} - weightByRulesClassnames={weightByRulesClassnames} + ruleComponent={RuleList} /> ); diff --git a/apps/docsite/src/form/dictionary/text.component.jsx b/apps/docsite/src/form/dictionary/text.component.jsx index 7beb4e0..9fb64e4 100644 --- a/apps/docsite/src/form/dictionary/text.component.jsx +++ b/apps/docsite/src/form/dictionary/text.component.jsx @@ -1,6 +1,5 @@ import React, { useMemo } from 'react'; import { TextField, Box } from '@mui/material'; -import _ from 'lodash'; export const Text = ({ 'data-testid': dataTestId, diff --git a/apps/docsite/src/form/form.component.jsx b/apps/docsite/src/form/form.component.jsx index e4a6ca4..849c8c8 100644 --- a/apps/docsite/src/form/form.component.jsx +++ b/apps/docsite/src/form/form.component.jsx @@ -45,24 +45,6 @@ const { const useStyles = makeStyles({ root: { margin: '0 auto', - - '& .validation-rule-ul': { - display: 'flex', - padding: 0, - listStyle: 'none' - }, - - '& .validation-rule-ul li': { - margin: '4px', - fontSize: 'smaller' - }, - - '& .complete-li': { - color: '#4ed569' - }, - '& .incomplete-li,.idle-li': { - color: '#da3b2b' - } } }); diff --git a/apps/docsite/src/form/rule-list.component.jsx b/apps/docsite/src/form/rule-list.component.jsx new file mode 100644 index 0000000..2c5220a --- /dev/null +++ b/apps/docsite/src/form/rule-list.component.jsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { + COMPLETE_STATUS, + DEFAULT_STATUS, + INCOMPLETE_STATUS +} from '@bedrockstreaming/form-validation-rule-list'; +import { makeStyles } from '@mui/styles'; + +const useStyles = makeStyles({ + list: { + display: 'flex', + margin: 0, + padding: 0, + textAlign: 'left', + listStyle: 'none' + }, + listItem: { + margin: '4px', + fontSize: 'smaller' + }, + [DEFAULT_STATUS]: { + color: '#2e2e2d' + }, + [COMPLETE_STATUS]: { + color: '#4ed569' + }, + [INCOMPLETE_STATUS]: { + color: '#da3b2b' + } +}); + +export const RuleList = ({ + items +}) => { + const classes = useStyles(); + + return ( + + ); +}; diff --git a/apps/docsite/src/form/utils.ts b/apps/docsite/src/form/utils.ts deleted file mode 100644 index ec3d1e1..0000000 --- a/apps/docsite/src/form/utils.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const weightByRulesClassnames = { - 0: 'with-idle-weight', - 1: 'with-complete-weight', - 2: 'with-incomplete-weight' -}; -export const colorByRulesClassnames = { - 0: 'with-idle-color', - 1: 'with-complete-color', - 2: 'with-incomplete-color' -}; diff --git a/libs/form-validation-rule-list/README.md b/libs/form-validation-rule-list/README.md index d73510a..a15f376 100644 --- a/libs/form-validation-rule-list/README.md +++ b/libs/form-validation-rule-list/README.md @@ -1,6 +1,6 @@ # :judge: form-validation-rule-list -This utility package allows to add a visual validation feedback to your users. It exposes a Higher Order Component adding some behavior to your existing inputs. +This utility package allows to add a visual validation feedback to your users. It exposes a Higher Order Component that helps displaying a list of rules with 3 possible states for each one: default, incomplete, complete ## :question: Why ? @@ -60,6 +60,7 @@ import { } from '@bedrockstreaming/form-validation-rule-list'; import { PasswordTextField } from '@mylib/textfield'; +import { RuleList } from '@mylib/rule-list'; const ValidatedPasswordTextField = withValidationRuleList(PasswordTextField); @@ -84,7 +85,7 @@ const dictionary = { {...props} // specific props required by ValidationRuleList rules={rules} - colors={validationColors} + ruleComponent={RuleList} /> ); diff --git a/libs/form-validation-rule-list/src/index.ts b/libs/form-validation-rule-list/src/index.ts index 95443d1..2e375cc 100644 --- a/libs/form-validation-rule-list/src/index.ts +++ b/libs/form-validation-rule-list/src/index.ts @@ -1,8 +1,5 @@ export * from './lib/rule'; -export * from './lib/utils'; export * from './lib/constants'; export * from './lib/getValidationRulesHints'; -export * from './lib/components/dotText.component'; -export * from './lib/components/dotTextList.component'; export * from './lib/components/validationRuleList.component'; export * from './lib/components/withValidationRuleList.hoc'; diff --git a/libs/form-validation-rule-list/src/lib/__tests__/utils.spec.ts b/libs/form-validation-rule-list/src/lib/__tests__/utils.spec.ts deleted file mode 100644 index e807f46..0000000 --- a/libs/form-validation-rule-list/src/lib/__tests__/utils.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - getColorByRulesClassnames, - getWeightByRulesClassnames -} from '../utils'; -import { - COMPLETE_STATE, - INCOMPLETE_STATE, - DEFAULT_STATE, - COMPLETE_STATUS, - DEFAULT_STATUS, - INCOMPLETE_STATUS -} from '../constants'; - -describe('utils', () => { - const classnamesByStatus = { - [DEFAULT_STATUS]: 'with-foo-idle', - [COMPLETE_STATUS]: 'with-foo-complete', - [INCOMPLETE_STATUS]: 'with-foo-complete' - }; - - describe('getWeightByRulesClassnames()', () => { - it('should return an object mapping classes to state values', () => { - expect(getWeightByRulesClassnames(classnamesByStatus)).toEqual({ - [DEFAULT_STATE]: 'with-foo-idle', - [COMPLETE_STATE]: 'with-foo-complete', - [INCOMPLETE_STATE]: 'with-foo-complete' - }); - }); - }); - - describe('getColorByRulesClassnames()', () => { - it('should return an object mapping classes to state values', () => { - expect(getColorByRulesClassnames(classnamesByStatus)).toEqual({ - [DEFAULT_STATE]: 'with-foo-idle', - [COMPLETE_STATE]: 'with-foo-complete', - [INCOMPLETE_STATE]: 'with-foo-complete' - }); - }); - }); -}); diff --git a/libs/form-validation-rule-list/src/lib/components/__tests__/validationRuleList.component.spec.tsx b/libs/form-validation-rule-list/src/lib/components/__tests__/validationRuleList.component.spec.tsx deleted file mode 100644 index 4af0a97..0000000 --- a/libs/form-validation-rule-list/src/lib/components/__tests__/validationRuleList.component.spec.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { screen, render } from '@testing-library/react'; -import _ from 'lodash'; - -import { - ValidationRuleList, - ValidationRuleListProps -} from '../validationRuleList.component'; -import { RuleObject, rule } from '../../rule'; -import { DotText } from '../dotText.component'; - -describe('', () => { - let props: ValidationRuleListProps; - let lengthHelper: RuleObject; - let fooHelper: RuleObject; - - const getWrapper = async () => render(); - - beforeEach(() => { - lengthHelper = rule( - 'Length helper', - (value: string | number | undefined) => _.get(value, 'length', 11) < 10 - ); - fooHelper = rule('Foo helper', (x) => !!x); - props = { - rules: [] as RuleObject[], - weightByRulesClassnames: { - 0: 'with-idle-weight', - 1: 'with-complete-weight', - 2: 'with-incomplete-weight' - }, - colorByRulesClassnames: { - 0: 'with-idle-color', - 1: 'with-complete-color', - 2: 'with-incomplete-color' - } - }; - }); - - it('should render validation-rule-list component with no list', async () => { - await getWrapper(); - - expect(screen.queryByRole('list')).toBeNull(); - }); - - it('should have created a list of the same length of the helpers array', async () => { - props.rules = [lengthHelper, fooHelper]; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength( - props.rules.length - ); - }); - - it('should have passed componentProp to list as attribute in place of items', async () => { - props.rules = [lengthHelper]; - props.componentProp = 'something'; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength(0); - expect(screen.queryByRole('list')?.getAttribute('something')).toBeDefined(); - }); - - it('should use provided component to display list', async () => { - props.component = ({ something }) => ; - props.rules = [fooHelper, lengthHelper]; - props.componentProp = 'something'; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength( - props.rules.length - ); - expect(screen.queryByRole('list')?.getAttribute('something')).toBeNull(); - }); - - it('should pass corresponding class for colors and font-weight to item', async () => { - props.rules = [lengthHelper]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toBe( - 'validation-rule-li with-idle-weight with-idle-color' - ); - }); - - it('should always set the default state color when no check function are passed', async () => { - const ruleWithoutCheckFunction = rule('awesome key'); - props.rules = [ruleWithoutCheckFunction]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); - - it('should return the complete status when rule evaluates to true and value prop has length superior than 0', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - props.value = 'yolo'; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-complete-color' - ); - }); - - it('should return the idle status when rule evaluates to true but value prop length is 0', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - props.value = ''; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); - - it('should return the idle status when rule evaluates to true but value prop length is undefined', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); -}); diff --git a/libs/form-validation-rule-list/src/lib/components/__tests__/withValidationRuleList.component.spec.tsx b/libs/form-validation-rule-list/src/lib/components/__tests__/withValidationRuleList.component.spec.tsx deleted file mode 100644 index ece7e9b..0000000 --- a/libs/form-validation-rule-list/src/lib/components/__tests__/withValidationRuleList.component.spec.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { screen, render } from '@testing-library/react'; -import _ from 'lodash'; - -import { ValidationRuleListProps } from '../validationRuleList.component'; - -import { withValidationRuleList } from '../withValidationRuleList.hoc'; -import { RuleObject, rule } from '../../rule'; -import { DotText } from '../dotText.component'; - -interface InputProps { - value: string; - onChange: (event: any) => void; - [key: string]: any; -} - -const Input = ({ value, onChange }: InputProps) => { - return ; -}; -const ValidatedInput = withValidationRuleList(Input); - -describe('', () => { - let props: ValidationRuleListProps; - let lengthHelper: RuleObject; - let fooHelper: RuleObject; - - const getWrapper = async () => render(); - - beforeEach(() => { - lengthHelper = rule( - 'Length helper', - (value: string | number | undefined) => _.get(value, 'length', 11) < 10 - ); - fooHelper = rule('Foo helper', (x) => !!x); - props = { - onChange: jest.fn(), - rules: [] as RuleObject[], - weightByRulesClassnames: { - 0: 'with-idle-weight', - 1: 'with-complete-weight', - 2: 'with-incomplete-weight' - }, - colorByRulesClassnames: { - 0: 'with-idle-color', - 1: 'with-complete-color', - 2: 'with-incomplete-color' - } - }; - }); - - it('should render validation-rule-list component with no list', async () => { - await getWrapper(); - - expect(screen.queryByRole('list')).toBeNull(); - }); - - it('should have created a list of the same length of the helpers array', async () => { - props.rules = [lengthHelper, fooHelper]; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength( - props.rules.length - ); - }); - - it('should have passed componentProp to list as attribute in place of items', async () => { - props.rules = [lengthHelper]; - props.componentProp = 'something'; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength(0); - expect(screen.queryByRole('list')?.getAttribute('something')).toBeDefined(); - }); - - it('should use provided component to display list', async () => { - props.component = ({ something }) =>
    {_.map(something, DotText)}
; - props.rules = [fooHelper, lengthHelper]; - props.componentProp = 'something'; - - await getWrapper(); - - expect(screen.queryByRole('list')?.children).toHaveLength( - props.rules.length - ); - expect(screen.queryByRole('list')?.getAttribute('something')).toBeNull(); - }); - - it('should pass corresponding class for colors and font-weight to item', async () => { - props.rules = [lengthHelper]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toBe( - 'validation-rule-li with-idle-weight with-idle-color' - ); - }); - - it('should always set the default state color when no check function are passed', async () => { - const ruleWithoutCheckFunction = rule('awesome key'); - props.rules = [ruleWithoutCheckFunction]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); - - it('should return the complete status when rule evaluates to true and value prop has length superior than 0', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - props.value = 'yolo'; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-complete-color' - ); - }); - - it('should return the idle status when rule evaluates to true but value prop length is 0', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - props.value = ''; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); - - it('should return the idle status when rule evaluates to true but value prop length is undefined', async () => { - const ruleAlwaysTrue = rule('awesome key', () => true); - props.rules = [ruleAlwaysTrue]; - - await getWrapper(); - - expect(screen.getByRole('listitem').getAttribute('class')).toContain( - 'with-idle-color' - ); - }); -}); diff --git a/libs/form-validation-rule-list/src/lib/components/dotText.component.tsx b/libs/form-validation-rule-list/src/lib/components/dotText.component.tsx deleted file mode 100644 index 9bbf5fd..0000000 --- a/libs/form-validation-rule-list/src/lib/components/dotText.component.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; -import classnames from 'classnames'; -import _ from 'lodash'; -export interface DotTextProps { - key: string; - itemColorClass: string; - fontWeightClass: string; - status: string; -} - -export const DotText = ({ - key, - itemColorClass, - fontWeightClass, - status -}: DotTextProps) => { - return ( -
  • - {key} -
  • - ); -}; diff --git a/libs/form-validation-rule-list/src/lib/components/dotTextList.component.tsx b/libs/form-validation-rule-list/src/lib/components/dotTextList.component.tsx deleted file mode 100644 index 01154a7..0000000 --- a/libs/form-validation-rule-list/src/lib/components/dotTextList.component.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import * as React from 'react'; -import classnames from 'classnames'; -import _ from 'lodash'; -import { DotText, DotTextProps } from './dotText.component'; - -export interface DotTextListProps { - items: DotTextProps[]; - className?: string; - [key: string]: any; -} - -export const DotTextList = ({ - items, - className, - ...otherProps -}: DotTextListProps) => ( -
      - {_.map(items, DotText)} -
    -); diff --git a/libs/form-validation-rule-list/src/lib/components/validationRuleList.component.tsx b/libs/form-validation-rule-list/src/lib/components/validationRuleList.component.tsx index 890819b..ac74c5a 100644 --- a/libs/form-validation-rule-list/src/lib/components/validationRuleList.component.tsx +++ b/libs/form-validation-rule-list/src/lib/components/validationRuleList.component.tsx @@ -1,21 +1,12 @@ import * as React from 'react'; import _ from 'lodash'; -import { - INCOMPLETE_STATE, - STATUS_BY_STATE, - StatusValue, - ClassnamesByStatusNumbers -} from '../constants'; +import { INCOMPLETE_STATE, STATUS_BY_STATE } from '../constants'; import { RuleObject } from '../rule'; -import { DotTextList } from './dotTextList.component'; - export interface RulesItem { key: string; - fontWeightClass: string; - itemColorClass: string; - status: StatusValue; + status: string; } export interface BaseRules { @@ -25,6 +16,23 @@ export interface BaseRules { export interface EnhancedRules extends RuleObject, BaseRules {} +const getItemsAndErrors = (rules: RuleObject[], value?: string | number) => + rules.reduce( + (acc, { check, key }) => { + const result = check(value); + + const nextErrors = + result === INCOMPLETE_STATE ? _.concat(acc.errors, key) : acc.errors; + const nextItems = _.concat(acc.items, { + key, + status: STATUS_BY_STATE[result] + }); + + return { items: nextItems, errors: nextErrors }; + }, + { errors: [], items: [] } as BaseRules + ); + export interface ValidationRuleListProps { id?: string; rules?: RuleObject[]; @@ -36,46 +44,26 @@ export interface ValidationRuleListProps { className?: string; name?: string; valueProp?: any; - weightByRulesClassnames: ClassnamesByStatusNumbers; - colorByRulesClassnames: ClassnamesByStatusNumbers; [key: string]: any; } export const ValidationRuleList = ({ rules = [], value = '', - component: Component = DotTextList, + component: Component, componentProp = 'items', - weightByRulesClassnames, - colorByRulesClassnames, onError = _.noop, ...otherProps }: ValidationRuleListProps) => { - if (rules.length) { - const { items, errors } = rules.reduce( - (acc, { check, key }) => { - const result = check(value); - - const nextErrors = - result === INCOMPLETE_STATE ? _.concat(acc.errors, key) : acc.errors; - const nextItems = _.concat(acc.items, { - key, - fontWeightClass: weightByRulesClassnames[result], - itemColorClass: colorByRulesClassnames[result], - status: STATUS_BY_STATE[result] - }); - - return { items: nextItems, errors: nextErrors }; - }, - { errors: [], items: [] } as BaseRules - ); + if (!Component || !rules.length) { + return null; + } - onError(errors); + const { items, errors } = getItemsAndErrors(rules, value); - const componentProps = { ...otherProps, [componentProp]: items }; + onError(errors); - return ; - } + const componentProps = { ...otherProps, [componentProp]: items }; - return null; + return ; }; diff --git a/libs/form-validation-rule-list/src/lib/components/withValidationRuleList.hoc.tsx b/libs/form-validation-rule-list/src/lib/components/withValidationRuleList.hoc.tsx index ce82362..9e5ada3 100644 --- a/libs/form-validation-rule-list/src/lib/components/withValidationRuleList.hoc.tsx +++ b/libs/form-validation-rule-list/src/lib/components/withValidationRuleList.hoc.tsx @@ -10,12 +10,10 @@ export const withValidationRuleList = ( const Enhanced = ({ rules, value, - component, - componentProp, + ruleComponent, + ruleComponentProp, valueProp = 'value', onError, - weightByRulesClassnames, - colorByRulesClassnames, ...otherProps }: ValidationRuleListProps) => { const componentProps = { ...otherProps, [valueProp]: value }; @@ -27,12 +25,10 @@ export const withValidationRuleList = ( ); diff --git a/libs/form-validation-rule-list/src/lib/constants.ts b/libs/form-validation-rule-list/src/lib/constants.ts index a165011..628d891 100644 --- a/libs/form-validation-rule-list/src/lib/constants.ts +++ b/libs/form-validation-rule-list/src/lib/constants.ts @@ -17,18 +17,3 @@ export const DEFAULT_RULES_NAMES = { max: 'max', required: 'required' }; - -export interface ClassnamesByStatusNumbers { - [DEFAULT_STATE]: string; - [COMPLETE_STATE]: string; - [INCOMPLETE_STATE]: string; -} - -export interface ClassnamesByStatusStrings { - [DEFAULT_STATUS]: string; - [COMPLETE_STATUS]: string; - [INCOMPLETE_STATUS]: string; -} - -export type StatusValue = - ClassnamesByStatusNumbers[keyof ClassnamesByStatusNumbers]; diff --git a/libs/form-validation-rule-list/src/lib/rule.ts b/libs/form-validation-rule-list/src/lib/rule.ts index 59c3197..37c59f9 100644 --- a/libs/form-validation-rule-list/src/lib/rule.ts +++ b/libs/form-validation-rule-list/src/lib/rule.ts @@ -3,9 +3,11 @@ import { INCOMPLETE_STATE, DEFAULT_STATE, COMPLETE_STATE } from './constants'; export type RuleCheck = (value?: string | number) => boolean; +export type RuleObjectCheck = (value?: string | number) => 0 | 1 | 2; + export interface RuleObject { key: string; - check: (value?: string | number) => 0 | 1 | 2; + check: RuleObjectCheck; } export type Rule = (key: string, check: RuleCheck) => RuleObject; diff --git a/libs/form-validation-rule-list/src/lib/utils.ts b/libs/form-validation-rule-list/src/lib/utils.ts deleted file mode 100644 index 9561278..0000000 --- a/libs/form-validation-rule-list/src/lib/utils.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - COMPLETE_STATE, - DEFAULT_STATE, - INCOMPLETE_STATE, - ClassnamesByStatusNumbers, - ClassnamesByStatusStrings -} from './constants'; -import _ from 'lodash'; - -export type GetWeightByRulesClassnames = ClassnamesByStatusStrings; - -export const getWeightByRulesClassnames = ({ - complete, - idle, - incomplete -}: GetWeightByRulesClassnames) => ({ - [COMPLETE_STATE]: complete, - [INCOMPLETE_STATE]: incomplete, - [DEFAULT_STATE]: idle -}); - -export interface GetColorByRulesClassnames extends ClassnamesByStatusStrings { - colors?: ClassnamesByStatusNumbers; -} - -export const getColorByRulesClassnames = ({ - complete, - incomplete, - idle, - colors -}: GetColorByRulesClassnames) => - _.merge( - { - [DEFAULT_STATE]: idle, - [COMPLETE_STATE]: complete, - [INCOMPLETE_STATE]: incomplete - }, - colors || {} - );