Skip to content
This repository was archived by the owner on Dec 1, 2025. It is now read-only.

Commit a68fba3

Browse files
committed
email and phone input fields created
1 parent b25a1f7 commit a68fba3

9 files changed

Lines changed: 422 additions & 21 deletions

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
---
2+
name: Email
3+
menu: Forms
4+
route: /forms/email
5+
---
6+
7+
import { Playground } from '@playground';
8+
import { Form } from 'react-final-form';
9+
import { FFInputEmail, validateEmail } from './email';
10+
import { validate } from '../../validation';
11+
import { renderFields } from '../../renderFields';
12+
13+
# Input
14+
15+
A basic widget for getting the user input as a email field. Keyboard and mouse can be used for providing or changing data.
16+
17+
## When To Use
18+
19+
- A user input in a form field is needed.
20+
- A search input is required.
21+
22+
## Usage
23+
24+
`Inside your React project directory, run the following:`
25+
26+
```js
27+
yarn add @tpr/forms
28+
```
29+
30+
`or with npm`
31+
32+
```js
33+
npm install @tpr/forms
34+
```
35+
36+
`import items you wish to use from the library`
37+
38+
```js
39+
import { Form, FFInputEmail } from '@tpr/forms';
40+
```
41+
42+
## Examples
43+
44+
[CodeSandbox](https://codesandbox.io)
45+
46+
Example using field level validation
47+
48+
<Playground>
49+
<Form onSubmit={console.log}>
50+
{({ handleSubmit }) => (
51+
<form onSubmit={handleSubmit}>
52+
<FFInputEmail
53+
name="event_name"
54+
label="Event name"
55+
placeholder="john.smith@tpr.gov.uk"
56+
hint="Must be between 6 and 8 digits long"
57+
inputWidth={5}
58+
cfg={{ my: 5 }}
59+
/>
60+
<button type="submit" children="Submit" />
61+
</form>
62+
)}
63+
</Form>
64+
</Playground>
65+
66+
<br />
67+
Example using record level validation
68+
69+
```js
70+
import { Form, validate, renderFields } from '@tpr/forms';
71+
```
72+
73+
<Playground>
74+
{() => {
75+
const fields = [
76+
{
77+
type: 'email',
78+
name: 'event_place',
79+
label: 'Event place',
80+
hint: 'The word must be London exactly',
81+
error: (value, _fields) => {
82+
return value === 'London' ? undefined : 'Must be in London';
83+
},
84+
placeholder: 'add some text here...',
85+
inputWidth: 5,
86+
cfg: { my: 5 },
87+
},
88+
{
89+
type: 'email',
90+
name: 'event_name',
91+
label: 'Event name',
92+
hint: 'Cannot be empty',
93+
error: 'Enter an event name',
94+
placeholder: 'add some text here...',
95+
inputWidth: 5,
96+
cfg: { my: 5 },
97+
},
98+
];
99+
return (
100+
<Form onSubmit={console.log} validate={validate(fields)}>
101+
{({ handleSubmit }) => (
102+
<form onSubmit={handleSubmit}>
103+
{renderFields(fields)}
104+
<button
105+
type="submit"
106+
style={{ display: 'none' }}
107+
children="Submit"
108+
/>
109+
</form>
110+
)}
111+
</Form>
112+
);
113+
}}
114+
</Playground>
115+
116+
## API
117+
118+
```
119+
Accepted config props: FlexProps, SpaceProps
120+
```
121+
122+
### Props
123+
124+
| Property | Required | Type | Description |
125+
| -------- | -------- | ------- | -------------------------------------------- |
126+
| cfg | false | object | FlexProps & SpaceProps |
127+
| disabled | false | boolean | Disable checkbox |
128+
| testId | false | string | data attribute for testers |
129+
| label | true | string | Checkbox description |
130+
| hint | false | string | More detailed description about the checkbox |
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import React from 'react';
2+
import { Field, FieldRenderProps } from 'react-final-form';
3+
import { StyledInputLabel, InputElementHeading } from '../elements';
4+
import { FieldProps, FieldExtraProps } from '../../renderFields';
5+
import { Input } from '../input/input';
6+
7+
// NOTE: composition option for validate on FFInputEmail
8+
// const compose = (...functions: Function[]) => (args: any[]) => {
9+
// return functions.reduceRight((arg, fn) => {
10+
// if (typeof fn === 'function') {
11+
// const fnValue = fn(arg);
12+
// console.log(fnValue);
13+
// if (fnValue) {
14+
// return fnValue;
15+
// }
16+
// }
17+
// }, args);
18+
// };
19+
20+
export function validEmail(email: string) {
21+
const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
22+
return regex.test(String(email).toLowerCase());
23+
}
24+
25+
type InputEmailProps = FieldRenderProps<string> & FieldExtraProps;
26+
const InputEmail: React.FC<InputEmailProps> = ({
27+
label,
28+
hint,
29+
input,
30+
testId,
31+
meta,
32+
required,
33+
inputWidth: width,
34+
cfg,
35+
}) => {
36+
return (
37+
<StyledInputLabel
38+
isError={meta && meta.touched && meta.error}
39+
cfg={Object.assign({ flexDirection: 'column', mt: 1 }, cfg)}
40+
>
41+
<InputElementHeading
42+
label={label}
43+
required={required}
44+
hint={hint}
45+
meta={meta}
46+
/>
47+
<Input
48+
type="email"
49+
width={width}
50+
testId={testId}
51+
label={label}
52+
touched={meta && meta.touched && meta.error}
53+
{...input}
54+
/>
55+
</StyledInputLabel>
56+
);
57+
};
58+
59+
export const FFInputEmail: React.FC<FieldProps & FieldExtraProps> = (
60+
fieldProps,
61+
) => {
62+
return (
63+
<Field
64+
{...fieldProps}
65+
required={typeof fieldProps.validate === 'function' || fieldProps.error}
66+
validate={(email, allValues) => {
67+
// NOTE: might be a good option to use currying but then we would
68+
// need to provide default error message
69+
if (fieldProps.validate) {
70+
return fieldProps.validate(email, allValues);
71+
} else {
72+
return validEmail(email) ? undefined : 'Invalid email address';
73+
}
74+
}}
75+
component={InputEmail}
76+
/>
77+
);
78+
};
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
name: Phone
3+
menu: Forms
4+
route: /forms/phone
5+
---
6+
7+
import { Playground } from '@playground';
8+
import { Form } from 'react-final-form';
9+
import { FFInputPhone } from './phone';
10+
import { validate } from '../../validation';
11+
import { renderFields } from '../../renderFields';
12+
13+
# Input
14+
15+
A basic widget for getting the user input as a phone field. Keyboard and mouse can be used for providing or changing data.
16+
17+
## When To Use
18+
19+
- A user input in a form field is needed.
20+
- A search input is required.
21+
22+
## Usage
23+
24+
`Inside your React project directory, run the following:`
25+
26+
```js
27+
yarn add @tpr/forms
28+
```
29+
30+
`or with npm`
31+
32+
```js
33+
npm install @tpr/forms
34+
```
35+
36+
`import items you wish to use from the library`
37+
38+
```js
39+
import { Form, FFInputPhone } from '@tpr/forms';
40+
```
41+
42+
## Examples
43+
44+
[CodeSandbox](https://codesandbox.io)
45+
46+
Example using field level validation
47+
48+
<Playground>
49+
<Form onSubmit={console.log}>
50+
{({ handleSubmit }) => (
51+
<form onSubmit={handleSubmit}>
52+
<FFInputPhone
53+
name="event_name"
54+
label="Event name"
55+
placeholder="07543 221 321"
56+
hint="Must be between 6 and 8 digits long"
57+
validate={(value) => (value ? undefined : 'Enter an event name')}
58+
inputWidth={5}
59+
cfg={{ my: 5 }}
60+
/>
61+
<button type="submit" style={{ display: 'none' }} children="Submit" />
62+
</form>
63+
)}
64+
</Form>
65+
</Playground>
66+
67+
<br />
68+
Example using record level validation
69+
70+
```js
71+
import { Form, validate, renderFields } from '@tpr/forms';
72+
```
73+
74+
<Playground>
75+
{() => {
76+
const fields = [
77+
{
78+
type: 'phone',
79+
name: 'event_place',
80+
label: 'Event place',
81+
hint: 'The word must be London exactly',
82+
error: (value, _fields) => {
83+
return value === 'London' ? undefined : 'Must be in London';
84+
},
85+
placeholder: 'add some text here...',
86+
inputWidth: 5,
87+
cfg: { my: 5 },
88+
},
89+
{
90+
type: 'phone',
91+
name: 'event_name',
92+
label: 'Event name',
93+
hint: 'Cannot be empty',
94+
error: 'Enter an event name',
95+
placeholder: 'add some text here...',
96+
inputWidth: 5,
97+
cfg: { my: 5 },
98+
},
99+
];
100+
return (
101+
<Form onSubmit={console.log} validate={validate(fields)}>
102+
{({ handleSubmit }) => (
103+
<form onSubmit={handleSubmit}>
104+
{renderFields(fields)}
105+
<button
106+
type="submit"
107+
style={{ display: 'none' }}
108+
children="Submit"
109+
/>
110+
</form>
111+
)}
112+
</Form>
113+
);
114+
}}
115+
</Playground>
116+
117+
## API
118+
119+
```
120+
Accepted config props: FlexProps, SpaceProps
121+
```
122+
123+
### Props
124+
125+
| Property | Required | Type | Description |
126+
| -------- | -------- | ------- | -------------------------------------------- |
127+
| cfg | false | object | FlexProps & SpaceProps |
128+
| disabled | false | boolean | Disable checkbox |
129+
| testId | false | string | data attribute for testers |
130+
| label | true | string | Checkbox description |
131+
| hint | false | string | More detailed description about the checkbox |
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import { Field, FieldRenderProps } from 'react-final-form';
3+
import { StyledInputLabel, InputElementHeading } from '../elements';
4+
import { FieldProps, FieldExtraProps } from '../../renderFields';
5+
import { Input } from '../input/input';
6+
7+
// TODO: find a way to add regex to email validation
8+
9+
type InputPhoneProps = FieldRenderProps<string> & FieldExtraProps;
10+
const InputPhone: React.FC<InputPhoneProps> = ({
11+
label,
12+
hint,
13+
input,
14+
testId,
15+
meta,
16+
required,
17+
inputWidth: width,
18+
cfg,
19+
}) => {
20+
return (
21+
<StyledInputLabel
22+
isError={meta && meta.touched && meta.error}
23+
cfg={Object.assign({ flexDirection: 'column', mt: 1 }, cfg)}
24+
>
25+
<InputElementHeading
26+
label={label}
27+
required={required}
28+
hint={hint}
29+
meta={meta}
30+
/>
31+
<Input
32+
type="phone"
33+
width={width}
34+
testId={testId}
35+
label={label}
36+
touched={meta && meta.touched && meta.error}
37+
{...input}
38+
/>
39+
</StyledInputLabel>
40+
);
41+
};
42+
43+
export const FFInputPhone: React.FC<FieldProps & FieldExtraProps> = (
44+
fieldProps,
45+
) => {
46+
return (
47+
<Field
48+
{...fieldProps}
49+
required={typeof fieldProps.validate === 'function' || fieldProps.error}
50+
component={InputPhone}
51+
/>
52+
);
53+
};

0 commit comments

Comments
 (0)