@hyphen/hyphen-components 7.10.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/css/fonts.css +1 -1
  2. package/dist/css/index.css +292 -150
  3. package/dist/css/reset.css +1 -1
  4. package/dist/css/utilities.css +480 -38
  5. package/dist/css/variables.css +170 -25
  6. package/dist/hyphen-components.cjs.development.js +244 -311
  7. package/dist/hyphen-components.cjs.development.js.map +1 -1
  8. package/dist/hyphen-components.cjs.production.min.js +2 -2
  9. package/dist/hyphen-components.cjs.production.min.js.map +1 -1
  10. package/dist/hyphen-components.esm.js +198 -265
  11. package/dist/hyphen-components.esm.js.map +1 -1
  12. package/dist/index.d.ts +25 -60
  13. package/package.json +3 -3
  14. package/src/components/Alert/Alert.mdx +1 -1
  15. package/src/components/Alert/Alert.module.scss +29 -34
  16. package/src/components/Alert/Alert.stories.tsx +11 -3
  17. package/src/components/Alert/Alert.test.tsx +17 -11
  18. package/src/components/Alert/Alert.tsx +9 -16
  19. package/src/components/Badge/Badge.mdx +46 -4
  20. package/src/components/Badge/Badge.module.scss +235 -185
  21. package/src/components/Badge/Badge.stories.tsx +126 -36
  22. package/src/components/Badge/Badge.test.tsx +180 -21
  23. package/src/components/Badge/Badge.tsx +56 -21
  24. package/src/components/Drawer/Drawer.mdx +14 -16
  25. package/src/components/Formik/Formik.stories.tsx +3 -5
  26. package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +34 -67
  27. package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +0 -2
  28. package/src/components/Table/Table.stories.tsx +4 -4
  29. package/src/components/TimePicker/TimePicker.mdx +3 -11
  30. package/src/components/TimePicker/TimePicker.stories.tsx +61 -60
  31. package/src/components/TimePicker/TimePicker.test.tsx +76 -7
  32. package/src/components/TimePicker/TimePicker.tsx +37 -7
  33. package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
  34. package/src/docs/Colors.mdx +13 -0
  35. package/src/index.ts +0 -2
  36. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +0 -175
  37. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +0 -38
  38. package/src/components/TimePickerNative/TimePickerNative.mdx +0 -67
  39. package/src/components/TimePickerNative/TimePickerNative.stories.tsx +0 -150
  40. package/src/components/TimePickerNative/TimePickerNative.test.tsx +0 -117
  41. package/src/components/TimePickerNative/TimePickerNative.tsx +0 -93
@@ -6,13 +6,12 @@ import * as Stories from './TimePicker.stories';
6
6
 
7
7
  # TimePicker
8
8
 
9
- Use a TimePicker when you want users to select from a list of a available times agnostic of date.
9
+ Use a TimePicker when you want users to select from a list of available times, agnostic of date.
10
10
 
11
- _NOTE:_ This component is abstracted from the [SelectInput](?path=/docs/components-selectinput-overview--default-story)
11
+ _NOTE:_ This component is abstracted from the [SelectInputNative](?path=/docs/components-selectinputnative-overview--default-story)
12
12
  and as such includes the same underlying props interface with an added method for generating the time options automatically.
13
13
 
14
- _ABOUT TIME FORMAT:_ While the `value` prop technically returns `{ label: string; value: string; }` the value returned will always
15
- be a JS ISO date string, like this: `2016-07-13T18:46:01.933Z`.
14
+ _ABOUT TIME FORMAT:_ The value returned will always be a JS ISO date string, like this: `2016-07-13T18:46:01.933Z`.
16
15
 
17
16
  ## Props
18
17
 
@@ -53,13 +52,6 @@ The example below is shown in military (24-hour) time.
53
52
 
54
53
  <Canvas of={Stories.WithCustomDateDisplay} />
55
54
 
56
- ## With Open Menu
57
-
58
- The menu can be rendered open with the `menuIsOpen` prop. We do this here to confirm option generation
59
- via our UI visual snapshot testing (Chromatic).
60
-
61
- <Canvas of={Stories.WithOpenMenu} />
62
-
63
55
  ## Help Text
64
56
 
65
57
  <Canvas of={Stories.HelpText} />
@@ -16,11 +16,11 @@ export default meta;
16
16
  export const Default = () => {
17
17
  const [value, setValue] = useState<string | null>(null);
18
18
  return (
19
- <Box height="360px">
19
+ <Box>
20
20
  <TimePicker
21
21
  id="defaultTimePicker"
22
22
  name="defaultTimePicker"
23
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
23
+ onChange={(event: ChangeEvent<HTMLSelectElement>) => {
24
24
  setValue(event.target.value);
25
25
  }}
26
26
  label="Pick a Time"
@@ -30,74 +30,75 @@ export const Default = () => {
30
30
  );
31
31
  };
32
32
 
33
- export const WithASpecificInterval = () => (
34
- <Box height="360px">
35
- <TimePicker
36
- id="intervalTimePicker"
37
- name="intervalTimePicker"
38
- onChange={() => {}}
39
- label="Pick a Time"
40
- interval={3600}
41
- />
42
- </Box>
43
- );
44
-
45
- export const WithMinAndMaxTimes = () => (
46
- <Box height="360px">
47
- <TimePicker
48
- id="startEnd"
49
- name="startEnd"
50
- onChange={() => {}}
51
- label="Pick a Time"
52
- startTime={{ hour: 9, minute: 0 }}
53
- endTime={{ hour: 15, minute: 31 }}
54
- />
55
- </Box>
56
- );
57
-
58
- export const WithCustomDateDisplay = () => (
59
- <Box height="360px">
60
- <TimePicker
61
- id="customDate"
62
- name="customDate"
63
- onChange={() => {}}
64
- label="Pick a Time"
65
- startTime={{ hour: 9, minute: 0 }}
66
- endTime={{ hour: 15, minute: 31 }}
67
- dateDisplayOptions={{ hour12: false, hour: '2-digit', minute: '2-digit' }}
68
- />
69
- </Box>
70
- );
33
+ export const WithASpecificInterval = () => {
34
+ const [value, setValue] = useState<string | null>(null);
35
+ return (
36
+ <Box>
37
+ <TimePicker
38
+ id="intervalTimePicker"
39
+ name="intervalTimePicker"
40
+ onChange={(event: ChangeEvent<HTMLSelectElement>) =>
41
+ setValue(event.target.value)
42
+ }
43
+ value={value}
44
+ label="Pick a Time"
45
+ interval={3600}
46
+ />
47
+ </Box>
48
+ );
49
+ };
71
50
 
72
- export const WithOpenMenu = () => {
51
+ export const WithMinAndMaxTimes = () => {
73
52
  const [value, setValue] = useState<string | null>(null);
74
53
  return (
75
- <Box height="260px">
54
+ <Box>
76
55
  <TimePicker
77
- id="openMenu"
78
- name="openMenu"
79
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
80
- setValue(event.target.value);
81
- }}
56
+ id="startEnd"
57
+ name="startEnd"
58
+ onChange={(event: ChangeEvent<HTMLSelectElement>) =>
59
+ setValue(event.target.value)
60
+ }
61
+ value={value}
82
62
  label="Pick a Time"
63
+ startTime={{ hour: 9, minute: 0 }}
64
+ endTime={{ hour: 15, minute: 31 }}
65
+ />
66
+ </Box>
67
+ );
68
+ };
69
+
70
+ export const WithCustomDateDisplay = () => {
71
+ const [value, setValue] = useState<string | null>(null);
72
+ return (
73
+ <Box>
74
+ <TimePicker
75
+ id="customDate"
76
+ name="customDate"
77
+ onChange={(event: ChangeEvent<HTMLSelectElement>) =>
78
+ setValue(event.target.value)
79
+ }
83
80
  value={value}
84
- menuIsOpen
85
- interval={3600}
81
+ label="Pick a Time"
86
82
  startTime={{ hour: 9, minute: 0 }}
87
- endTime={{ hour: 13, minute: 1 }}
83
+ endTime={{ hour: 15, minute: 31 }}
84
+ dateDisplayOptions={{
85
+ hour12: false,
86
+ hour: '2-digit',
87
+ minute: '2-digit',
88
+ }}
88
89
  />
89
90
  </Box>
90
91
  );
91
92
  };
92
93
 
93
94
  export const HelpText = () => {
94
- const [value, setValue] = useState<string>('');
95
+ const [value, setValue] = useState<string | null>(null);
95
96
  return (
96
- <Box height="360px">
97
+ <Box>
97
98
  <TimePicker
98
99
  id="helpText"
99
100
  name="helpText"
100
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
101
+ onChange={(event: ChangeEvent<HTMLSelectElement>) => {
101
102
  setValue(event.target.value);
102
103
  }}
103
104
  label="Pick a Time"
@@ -109,15 +110,15 @@ export const HelpText = () => {
109
110
  };
110
111
 
111
112
  export const Sizes = () => {
112
- const [value, setValue] = useState<string>();
113
- const [value1, setValue1] = useState<string>();
114
- const [value2, setValue2] = useState<string>();
113
+ const [value, setValue] = useState<string | null>(null);
114
+ const [value1, setValue1] = useState<string | null>(null);
115
+ const [value2, setValue2] = useState<string | null>(null);
115
116
  return (
116
- <Box gap="md" height="360px">
117
+ <Box gap="md">
117
118
  <TimePicker
118
119
  id="smTimePicker"
119
120
  name="smTimePicker"
120
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
121
+ onChange={(event: ChangeEvent<HTMLSelectElement>) => {
121
122
  setValue(event.target.value);
122
123
  }}
123
124
  label="Small"
@@ -127,7 +128,7 @@ export const Sizes = () => {
127
128
  <TimePicker
128
129
  id="mdTimePicker"
129
130
  name="mdTimePicker"
130
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
131
+ onChange={(event: ChangeEvent<HTMLSelectElement>) => {
131
132
  setValue1(event.target.value);
132
133
  }}
133
134
  label="Medium"
@@ -137,7 +138,7 @@ export const Sizes = () => {
137
138
  <TimePicker
138
139
  id="lgTimePicker"
139
140
  name="lgTimePicker"
140
- onChange={(event: ChangeEvent<HTMLInputElement>) => {
141
+ onChange={(event: ChangeEvent<HTMLSelectElement>) => {
141
142
  setValue2(event.target.value);
142
143
  }}
143
144
  label="Large"
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { screen, render } from '@testing-library/react';
2
+ import { screen, render, fireEvent } from '@testing-library/react';
3
3
  import { TimePicker } from './TimePicker';
4
4
 
5
5
  describe('TimePicker', () => {
@@ -12,8 +12,6 @@ describe('TimePicker', () => {
12
12
  onChange={() => null}
13
13
  value={null}
14
14
  label="Select Time"
15
- menuIsOpen
16
- maxMenuHeight={2000}
17
15
  />
18
16
  );
19
17
 
@@ -43,8 +41,6 @@ describe('TimePicker', () => {
43
41
  onChange={() => null}
44
42
  value={null}
45
43
  label="Select Time"
46
- menuIsOpen
47
- maxMenuHeight={2000}
48
44
  interval={3600}
49
45
  startTime={{ hour: 9, minute: 0 }}
50
46
  endTime={{ hour: 12, minute: 0 }}
@@ -65,6 +61,55 @@ describe('TimePicker', () => {
65
61
  expect(screen.queryByText(time)).toBe(null);
66
62
  });
67
63
  });
64
+
65
+ it('supports intervals shorter than one minute', () => {
66
+ render(
67
+ <TimePicker
68
+ name="timePicker"
69
+ id="timePicker"
70
+ onChange={() => null}
71
+ value={null}
72
+ label="Select Time"
73
+ interval={45}
74
+ startTime={{ hour: 1, minute: 0 }}
75
+ endTime={{ hour: 1, minute: 2 }}
76
+ dateDisplayOptions={{
77
+ hour: '2-digit',
78
+ minute: '2-digit',
79
+ second: '2-digit',
80
+ hour12: false,
81
+ }}
82
+ />
83
+ );
84
+
85
+ expect(screen.getByText('01:00:00')).toBeInTheDocument();
86
+ expect(screen.getByText('01:00:45')).toBeInTheDocument();
87
+ expect(screen.getByText('01:01:30')).toBeInTheDocument();
88
+ });
89
+ });
90
+
91
+ describe('Selected value', () => {
92
+ it('selects a matching time from a previous date', () => {
93
+ const savedValue = new Date(2020, 0, 1, 13, 0, 0, 123).toISOString();
94
+ const expectedValue = new Date();
95
+ expectedValue.setHours(13, 0, 0, 0);
96
+
97
+ render(
98
+ <TimePicker
99
+ name="timePicker"
100
+ id="timePicker"
101
+ onChange={() => null}
102
+ value={savedValue}
103
+ label="Select Time"
104
+ startTime={{ hour: 13, minute: 0 }}
105
+ endTime={{ hour: 14, minute: 0 }}
106
+ />
107
+ );
108
+
109
+ expect(screen.getByLabelText('Select Time')).toHaveValue(
110
+ expectedValue.toISOString()
111
+ );
112
+ });
68
113
  });
69
114
 
70
115
  describe('Custom Date Display', () => {
@@ -76,8 +121,6 @@ describe('TimePicker', () => {
76
121
  onChange={() => null}
77
122
  value={null}
78
123
  label="Select Time"
79
- menuIsOpen
80
- maxMenuHeight={2000}
81
124
  dateDisplayOptions={{ hour12: false }}
82
125
  startTime={{ hour: 13, minute: 0 }}
83
126
  endTime={{ hour: 15, minute: 1 }}
@@ -94,4 +137,30 @@ describe('TimePicker', () => {
94
137
  });
95
138
  });
96
139
  });
140
+
141
+ describe('Callback Handling', () => {
142
+ it('it fires an onchange callback with the correct value', async () => {
143
+ const mockedHandleChange = jest.fn(() => {}); // eslint-disable-line
144
+
145
+ render(
146
+ <TimePicker
147
+ name="timePicker"
148
+ id="timePicker"
149
+ onChange={mockedHandleChange}
150
+ value={null}
151
+ label="Select Time"
152
+ dateDisplayOptions={{ hour12: false }}
153
+ startTime={{ hour: 13, minute: 0 }}
154
+ endTime={{ hour: 15, minute: 1 }}
155
+ interval={3600}
156
+ />
157
+ );
158
+
159
+ const timePicker = screen.getByLabelText('Select Time');
160
+
161
+ fireEvent.change(timePicker, { target: { value: 'hello' } });
162
+
163
+ expect(mockedHandleChange).toBeCalledTimes(1);
164
+ });
165
+ });
97
166
  });
@@ -1,7 +1,11 @@
1
1
  import React, { FC } from 'react';
2
- import { SelectInput, SelectInputProps } from '../SelectInput/SelectInput';
2
+ import {
3
+ SelectInputNative,
4
+ SelectInputNativeProps,
5
+ } from '../SelectInputNative/SelectInputNative';
3
6
 
4
- export type TimePickerProps = Omit<SelectInputProps, 'options'> & {
7
+ export interface TimePickerProps
8
+ extends Omit<SelectInputNativeProps, 'options'> {
5
9
  /**
6
10
  * Options to govern the display of the option labels in the select.
7
11
  * This is a direct passthrough to the second argument of JS `toLocaleTimeString`.
@@ -26,7 +30,11 @@ export type TimePickerProps = Omit<SelectInputProps, 'options'> & {
26
30
  * Start hour and minute
27
31
  */
28
32
  startTime?: { hour: number; minute: number };
29
- };
33
+ /**
34
+ * Should be ISO timestamp as returned by `onChange`, and matching value of option object.
35
+ */
36
+ value: SelectInputNativeProps['value'];
37
+ }
30
38
 
31
39
  export const TimePicker: FC<TimePickerProps> = ({
32
40
  id,
@@ -62,22 +70,44 @@ export const TimePicker: FC<TimePickerProps> = ({
62
70
  value: currentTime.toISOString(),
63
71
  label: currentTime.toLocaleTimeString(locales, dateDisplayOptions),
64
72
  });
65
- currentTime.setSeconds(first.getSeconds() + interval);
73
+ currentTime.setSeconds(currentTime.getSeconds() + interval);
66
74
  }
67
75
 
68
76
  return timeOptions;
69
77
  };
70
78
 
79
+ const options = generateTimes();
80
+ let valueDate: Date | undefined;
81
+
82
+ if (typeof value === 'string') {
83
+ valueDate = new Date(value);
84
+ } else if (typeof value === 'number') {
85
+ valueDate = new Date(value);
86
+ }
87
+
88
+ const matchingOption =
89
+ valueDate && !Number.isNaN(valueDate.getTime())
90
+ ? options.find(({ value: optionValue }) => {
91
+ const optionDate = new Date(optionValue);
92
+
93
+ return (
94
+ optionDate.getHours() === valueDate.getHours() &&
95
+ optionDate.getMinutes() === valueDate.getMinutes() &&
96
+ optionDate.getSeconds() === valueDate.getSeconds()
97
+ );
98
+ })
99
+ : undefined;
100
+
71
101
  return (
72
- <SelectInput
102
+ <SelectInputNative
73
103
  {...restProps}
74
104
  id={id}
75
105
  name={name}
76
106
  label={label}
77
107
  onChange={onChange}
78
- options={generateTimes()}
108
+ options={options}
79
109
  placeholder={placeholder}
80
- value={value}
110
+ value={matchingOption?.value ?? value}
81
111
  />
82
112
  );
83
113
  };
@@ -45,7 +45,7 @@ export const BadgeTooltip = () => (
45
45
  <TooltipProvider delayDuration={100}>
46
46
  <Tooltip>
47
47
  <TooltipTrigger asChild>
48
- <Badge as="button" variant="blue">
48
+ <Badge as="button" color="blue">
49
49
  hover
50
50
  </Badge>
51
51
  </TooltipTrigger>
@@ -54,6 +54,19 @@ import designTokens from '@hyphen/hyphen-design-tokens/build/json/variables.json
54
54
  {}
55
55
  )}
56
56
  />
57
+ <ColorItem
58
+ title="color-base-orange"
59
+ subtitle="Orange"
60
+ colors={Object.keys(designTokens.color.base.orange).reduce(
61
+ (acc, item, i) => {
62
+ acc[item] = Object.keys(designTokens.color.base.orange).map(
63
+ (g) => designTokens.color.base.orange[g].value
64
+ )[i];
65
+ return acc;
66
+ },
67
+ {}
68
+ )}
69
+ />
57
70
  <ColorItem
58
71
  title="color-base-green"
59
72
  subtitle="Green"
package/src/index.ts CHANGED
@@ -23,7 +23,6 @@ export * from './components/Formik/FormikSelectInputNative/FormikSelectInputNati
23
23
  export * from './components/Formik/FormikTextInput/FormikTextInput';
24
24
  export * from './components/Formik/FormikTextareaInput/FormikTextareaInput';
25
25
  export * from './components/Formik/FormikTimePicker/FormikTimePicker';
26
- export * from './components/Formik/FormikTimePickerNative/FormikTimePickerNative';
27
26
  export * from './components/Formik/FormikSwitch/FormikSwitch';
28
27
  export * from './components/Formik/FormikToggleGroup/FormikToggleGroup';
29
28
  export * from './components/Formik/FormikToggleGroupMulti/FormikToggleGroupMulti';
@@ -49,7 +48,6 @@ export * from './components/TextInput/TextInput';
49
48
  export * from './components/TextInputInset/TextInputInset';
50
49
  export * from './components/ThemeProvider/ThemeProvider';
51
50
  export * from './components/TimePicker/TimePicker';
52
- export * from './components/TimePickerNative/TimePickerNative';
53
51
  export * from './components/Toast';
54
52
  export * from './components/Toggle/Toggle';
55
53
  export * from './components/ToggleGroup/ToggleGroup';
@@ -1,175 +0,0 @@
1
- import React from 'react';
2
- import { render, fireEvent, screen, waitFor } from '@testing-library/react';
3
- import { Formik, Form, Field, FormikValues, getIn, setIn } from 'formik';
4
- import { FormikTimePickerNative } from './FormikTimePickerNative';
5
-
6
- const testLabelName = 'test select';
7
-
8
- const handleValidation = (testValueKey: string) => (values: FormikValues) =>
9
- getIn(values, testValueKey)?.length > 1
10
- ? {}
11
- : setIn({}, testValueKey, 'input is required');
12
-
13
- const renderForm = (
14
- initialValue: any, // eslint-disable-line
15
- props: {
16
- placeholder?: string;
17
- hideLabel?: boolean;
18
- isRequired?: unknown;
19
- isDisabled?: boolean;
20
- onChange?: jest.Mock<void, [React.ChangeEvent<HTMLSelectElement>]>; // eslint-disable-line
21
- interval?: number;
22
- },
23
- testValueKey = testLabelName
24
- ) => (
25
- <Formik
26
- initialValues={{
27
- [testLabelName]: initialValue,
28
- }}
29
- validate={props.isRequired ? handleValidation(testValueKey) : undefined} // eslint-disable-line
30
- onSubmit={() => {}} // eslint-disable-line
31
- >
32
- {() => (
33
- <Form noValidate>
34
- <Field
35
- label={testValueKey}
36
- name={testValueKey}
37
- id={testValueKey}
38
- component={FormikTimePickerNative}
39
- {...props}
40
- />
41
- <button type="submit">submit</button>
42
- </Form>
43
- )}
44
- </Formik>
45
- );
46
-
47
- describe('FormikTimePickerNative', () => {
48
- describe('States', () => {
49
- describe('Hidden label, with a placeholder', () => {
50
- test('it renders input without a visual label, and with a placeholder', () => {
51
- render(
52
- renderForm(undefined, {
53
- placeholder: 'Test Placeholder',
54
- hideLabel: true,
55
- })
56
- );
57
- expect(screen.queryByText(testLabelName)).toBeNull();
58
- expect(screen.getByText('Test Placeholder')).toBeInTheDocument();
59
- });
60
- });
61
-
62
- describe('No Aria-labelledby', () => {
63
- test('does not assign "aria-labelledby" attribute when a label is hidden', () => {
64
- render(renderForm(undefined, { hideLabel: true }));
65
- const inputElement = screen.getByLabelText(testLabelName);
66
- expect(inputElement).not.toHaveAttribute('aria-labelledby');
67
- });
68
- });
69
-
70
- describe('With a label, and no custom placeholder', () => {
71
- test('it renders input with a label, and with a default placeholder', () => {
72
- render(renderForm(undefined, {}));
73
-
74
- expect(screen.getByLabelText(testLabelName)).toBeInTheDocument();
75
- expect(screen.getByText('HH:MM')).toBeInTheDocument();
76
- });
77
-
78
- test('assigns the "aria-labelledby" attribute and renders label with correct id, when label is provided', () => {
79
- render(renderForm(undefined, {}));
80
- const inputElement = screen.getByLabelText(testLabelName);
81
- expect(inputElement).toHaveAttribute(
82
- 'aria-labelledby',
83
- `${testLabelName}Label`
84
- );
85
- expect(
86
- document.getElementById(`${testLabelName}Label`)
87
- ).toBeInTheDocument();
88
- });
89
- });
90
-
91
- describe('Single select, pre-selected', () => {
92
- test('it renders with value pre-selected', () => {
93
- render(renderForm('2020-10-23T04:30:00.120Z', {}));
94
-
95
- expect(screen.getByText('12:00 AM')).toBeInTheDocument();
96
- });
97
- });
98
-
99
- describe('Is Required', () => {
100
- test('it sets aria-required on the input', () => {
101
- render(renderForm(undefined, { isRequired: true }));
102
- const inputElement = screen.getByLabelText(testLabelName);
103
- expect(inputElement).toHaveAttribute('aria-required', 'true');
104
- });
105
- });
106
-
107
- describe('Is Disabled', () => {
108
- test('it disables the input', () => {
109
- render(renderForm(undefined, { isDisabled: true }));
110
-
111
- expect(screen.getByLabelText(testLabelName)).toBeDisabled();
112
- });
113
- });
114
-
115
- describe('Is Invalid, with a helpful message', () => {
116
- test('it renders the helpful message', async () => {
117
- const { getByText } = render(
118
- renderForm(undefined, { isRequired: true })
119
- );
120
- const submitButton = getByText('submit');
121
-
122
- fireEvent.click(submitButton);
123
- await waitFor(() =>
124
- expect(screen.getByText('input is required')).toBeInTheDocument()
125
- );
126
- });
127
-
128
- test('it renders the error message from nested object', async () => {
129
- const { getByText } = render(
130
- renderForm(
131
- { outer: { nested: [] } },
132
- { isRequired: true },
133
- `${testLabelName}.outer.nested`
134
- )
135
- );
136
- const submitButton = getByText('submit');
137
-
138
- fireEvent.click(submitButton);
139
- await waitFor(() =>
140
- expect(screen.getByText('input is required')).toBeInTheDocument()
141
- );
142
- });
143
- });
144
- });
145
-
146
- describe('Callback Handling', () => {
147
- describe('onChange', () => {
148
- test("Custom onChange event fires callback function, overwriting Formik's onChange", async () => {
149
- let value: string | undefined;
150
- const mockedHandleChange = jest.fn((event) => {
151
- event.persist();
152
- });
153
-
154
- const { getByLabelText } = render(
155
- renderForm(value, { onChange: mockedHandleChange })
156
- );
157
- const selectInput = getByLabelText(testLabelName);
158
- fireEvent.change(selectInput, { target: { value: 'hello' } });
159
- expect(mockedHandleChange).toHaveBeenCalledTimes(1);
160
- });
161
-
162
- test('it fires onChange callback on change', async () => {
163
- const mockedHandleChange = jest.fn();
164
-
165
- const { getByLabelText } = render(
166
- renderForm(undefined, { onChange: mockedHandleChange })
167
- );
168
-
169
- await fireEvent.change(getByLabelText(testLabelName));
170
-
171
- expect(mockedHandleChange).toBeCalledTimes(1);
172
- });
173
- });
174
- });
175
- });
@@ -1,38 +0,0 @@
1
- import React, { FC } from 'react';
2
- import {
3
- FormikTouched,
4
- FormikErrors,
5
- FormikValues,
6
- FieldAttributes,
7
- getIn,
8
- } from 'formik';
9
- import {
10
- TimePickerNative,
11
- TimePickerNativeProps,
12
- } from '../../TimePickerNative/TimePickerNative';
13
-
14
- export interface FormikTimePickerNativeProps
15
- extends Omit<TimePickerNativeProps, 'onChange'> {
16
- field: FieldAttributes<HTMLTextAreaElement>;
17
- form: {
18
- touched: FormikTouched<FormikValues>;
19
- errors: FormikErrors<FormikValues>;
20
- };
21
- onChange: TimePickerNativeProps['onChange'];
22
- }
23
-
24
- export const FormikTimePickerNative: FC<FormikTimePickerNativeProps> = ({
25
- field: { name, onBlur, onChange: formikOnChange, value },
26
- form: { touched, errors },
27
- onChange,
28
- ...props
29
- }) => (
30
- <TimePickerNative
31
- {...props}
32
- name={name}
33
- onBlur={onBlur}
34
- onChange={onChange ?? formikOnChange}
35
- value={value}
36
- error={getIn(touched, name) && getIn(errors, name)}
37
- />
38
- );