@hyphen/hyphen-components 7.10.0 → 8.0.1
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.
- package/dist/css/fonts.css +5 -3
- package/dist/css/fonts.css.map +1 -0
- package/dist/css/index.css +370 -222
- package/dist/css/index.css.map +1 -0
- package/dist/css/reset.css +5 -3
- package/dist/css/reset.css.map +1 -0
- package/dist/css/utilities.css +487 -43
- package/dist/css/utilities.css.map +1 -0
- package/dist/css/variables.css +180 -33
- package/dist/css/variables.css.map +1 -0
- package/dist/hyphen-components.cjs.development.js +250 -317
- package/dist/hyphen-components.cjs.development.js.map +1 -1
- package/dist/hyphen-components.cjs.production.min.js +2 -2
- package/dist/hyphen-components.cjs.production.min.js.map +1 -1
- package/dist/hyphen-components.esm.js +204 -271
- package/dist/hyphen-components.esm.js.map +1 -1
- package/dist/index.d.ts +25 -60
- package/package.json +4 -4
- package/src/components/Alert/Alert.mdx +1 -1
- package/src/components/Alert/Alert.module.scss +29 -34
- package/src/components/Alert/Alert.stories.tsx +11 -3
- package/src/components/Alert/Alert.test.tsx +17 -11
- package/src/components/Alert/Alert.tsx +9 -16
- package/src/components/Badge/Badge.mdx +46 -4
- package/src/components/Badge/Badge.module.scss +235 -185
- package/src/components/Badge/Badge.stories.tsx +126 -36
- package/src/components/Badge/Badge.test.tsx +180 -21
- package/src/components/Badge/Badge.tsx +56 -21
- package/src/components/Button/Button.module.scss +1 -1
- package/src/components/CheckboxInput/components/Checkbox.module.scss +2 -2
- package/src/components/Drawer/Drawer.mdx +14 -16
- package/src/components/Drawer/Drawer.module.scss +1 -1
- package/src/components/DropdownMenu/DropdownMenu.tsx +6 -8
- package/src/components/Formik/Formik.stories.tsx +3 -5
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +34 -67
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +0 -2
- package/src/components/Modal/Modal.module.scss +1 -1
- package/src/components/RadioGroup/RadioInput/RadioInput.module.scss +2 -2
- package/src/components/SelectInput/SelectInput.module.scss +1 -1
- package/src/components/SelectInputInset/SelectInputInset.module.scss +1 -1
- package/src/components/SelectInputNative/SelectInputNative.module.scss +1 -1
- package/src/components/Switch/Switch.module.scss +1 -1
- package/src/components/Table/Table.stories.tsx +4 -4
- package/src/components/TextInput/TextInput.module.scss +1 -1
- package/src/components/TextInputInset/TextInputInset.module.scss +1 -1
- package/src/components/TextareaInput/TextareaInput.module.scss +1 -1
- package/src/components/TextareaInputInset/TextareaInputInset.module.scss +1 -1
- package/src/components/TimePicker/TimePicker.mdx +3 -11
- package/src/components/TimePicker/TimePicker.stories.tsx +61 -60
- package/src/components/TimePicker/TimePicker.test.tsx +76 -7
- package/src/components/TimePicker/TimePicker.tsx +37 -7
- package/src/components/Toggle/Toggle.module.scss +1 -1
- package/src/components/ToggleGroup/ToggleGroup.module.scss +1 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -1
- package/src/docs/Colors.mdx +13 -0
- package/src/index.ts +0 -2
- package/src/styles/display.scss +1 -1
- package/src/styles/flex.scss +1 -1
- package/src/styles/overflow.scss +2 -0
- package/src/styles/position.scss +2 -0
- package/src/styles/text-align.scss +2 -0
- package/src/styles/utilities.scss +10 -9
- package/src/styles/variables/index.scss +2 -1
- package/src/styles/white-space.scss +2 -0
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +0 -175
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +0 -38
- package/src/components/TimePickerNative/TimePickerNative.mdx +0 -67
- package/src/components/TimePickerNative/TimePickerNative.stories.tsx +0 -150
- package/src/components/TimePickerNative/TimePickerNative.test.tsx +0 -117
- package/src/components/TimePickerNative/TimePickerNative.tsx +0 -93
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import React, { FC } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
SelectInputNative,
|
|
4
|
+
SelectInputNativeProps,
|
|
5
|
+
} from '../SelectInputNative/SelectInputNative';
|
|
3
6
|
|
|
4
|
-
export
|
|
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(
|
|
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
|
-
<
|
|
102
|
+
<SelectInputNative
|
|
73
103
|
{...restProps}
|
|
74
104
|
id={id}
|
|
75
105
|
name={name}
|
|
76
106
|
label={label}
|
|
77
107
|
onChange={onChange}
|
|
78
|
-
options={
|
|
108
|
+
options={options}
|
|
79
109
|
placeholder={placeholder}
|
|
80
|
-
value={value}
|
|
110
|
+
value={matchingOption?.value ?? value}
|
|
81
111
|
/>
|
|
82
112
|
);
|
|
83
113
|
};
|
package/src/docs/Colors.mdx
CHANGED
|
@@ -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';
|
package/src/styles/display.scss
CHANGED
package/src/styles/flex.scss
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
@
|
|
1
|
+
@use '@hyphen/hyphen-design-tokens/build/scss/variables' as *;
|
|
2
2
|
|
|
3
3
|
// min-width and min-height needed because of this
|
|
4
4
|
// https://stackoverflow.com/questions/36247140/why-doesnt-flex-item-shrink-past-content-size
|
package/src/styles/overflow.scss
CHANGED
package/src/styles/position.scss
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
@use './animation';
|
|
2
|
+
@use './cursor';
|
|
3
|
+
@use './display';
|
|
4
|
+
@use './flex';
|
|
5
|
+
@use './overflow';
|
|
6
|
+
@use './text-align';
|
|
7
|
+
@use './white-space';
|
|
8
|
+
@use './position';
|
|
9
|
+
@use './transform';
|
|
10
|
+
|
|
1
11
|
@import '@hyphen/hyphen-design-tokens/build/utilities/utilities.css';
|
|
2
|
-
@import './animation';
|
|
3
|
-
@import './cursor';
|
|
4
|
-
@import './display';
|
|
5
|
-
@import './flex';
|
|
6
|
-
@import './overflow';
|
|
7
|
-
@import './text-align';
|
|
8
|
-
@import './white-space';
|
|
9
|
-
@import './position';
|
|
10
|
-
@import './transform';
|
|
11
12
|
|
|
12
13
|
.sr-only {
|
|
13
14
|
position: absolute;
|
|
@@ -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
|
-
);
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Canvas, Meta, ArgTypes } from '@storybook/addon-docs/blocks';
|
|
2
|
-
import { TimePickerNative } from './TimePickerNative';
|
|
3
|
-
import * as Stories from './TimePickerNative.stories';
|
|
4
|
-
|
|
5
|
-
<Meta of={Stories} />
|
|
6
|
-
|
|
7
|
-
# TimePickerNative
|
|
8
|
-
|
|
9
|
-
Use a TimePickerNative when you want users to select from a list of a available times agnostic of date.
|
|
10
|
-
|
|
11
|
-
_NOTE:_ This component is abstracted from the [SelectInputNative](?path=/docs/components-selectinputnative-overview--default-story)
|
|
12
|
-
and as such includes the same underlying props interface with an added method for generating the time options automatically.
|
|
13
|
-
|
|
14
|
-
_ABOUT TIME FORMAT:_ The value returned will always be a JS ISO date string, like this: `2016-07-13T18:46:01.933Z`.
|
|
15
|
-
|
|
16
|
-
## Props
|
|
17
|
-
|
|
18
|
-
<ArgTypes of={TimePickerNative} />
|
|
19
|
-
|
|
20
|
-
## Default
|
|
21
|
-
|
|
22
|
-
<Canvas of={Stories.Default} />
|
|
23
|
-
|
|
24
|
-
## With A Specific Interval
|
|
25
|
-
|
|
26
|
-
Pass an `interval` (seconds) value to determine how many times get generated as options.
|
|
27
|
-
The example below uses `3600` --> 1 Hour Intervals
|
|
28
|
-
|
|
29
|
-
<Canvas of={Stories.WithASpecificInterval} />
|
|
30
|
-
|
|
31
|
-
## With Min and Max Times
|
|
32
|
-
|
|
33
|
-
You can determine the range of times to be shown by capping the start and end times.
|
|
34
|
-
Use `startTime` and `endTime` for this. The expected values for `hour` and `minute` properties
|
|
35
|
-
are `0-24` and `0-60` respectively.
|
|
36
|
-
|
|
37
|
-
IMPORTANT: `startTime` is inclusive, and `endTime` is exclusive. This is to avoid
|
|
38
|
-
the options showing the startTime twice when using a 24-hour cycle.
|
|
39
|
-
|
|
40
|
-
See example below where we want to show 15 minute increments starting at 9:00AM and ending at 3:30PM.
|
|
41
|
-
|
|
42
|
-
<Canvas of={Stories.WithMinAndMaxTimes} />
|
|
43
|
-
|
|
44
|
-
## With Custom Date Display
|
|
45
|
-
|
|
46
|
-
The labels for the dropdwon options are governed by JS `toLocaleTimeString`, and as such
|
|
47
|
-
options are available to customize these.
|
|
48
|
-
|
|
49
|
-
NOTE: that the option values are always returned as ISO strings regardless of the label display option.
|
|
50
|
-
|
|
51
|
-
The example below is shown in military (24-hour) time.
|
|
52
|
-
|
|
53
|
-
<Canvas of={Stories.WithCustomDateDisplay} />
|
|
54
|
-
|
|
55
|
-
## Help Text
|
|
56
|
-
|
|
57
|
-
<Canvas of={Stories.HelpText} />
|
|
58
|
-
|
|
59
|
-
## Sizes
|
|
60
|
-
|
|
61
|
-
Set the size of the input to `sm`, `md` or `lg`. `md` is the default size.
|
|
62
|
-
|
|
63
|
-
<Canvas of={Stories.Sizes} />
|
|
64
|
-
|
|
65
|
-
## Component Design Tokens
|
|
66
|
-
|
|
67
|
-
This component shares component design tokens with all form controls. For a complete list of tokens, see the [Theming Form Controls documentation](/docs/theming-form-controls--custom-theme-form).
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import type { Meta } from '@storybook/react-vite';
|
|
2
|
-
import React, { ChangeEvent, useState } from 'react';
|
|
3
|
-
import { TimePickerNative } from './TimePickerNative';
|
|
4
|
-
import { Box } from '../Box/Box';
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof TimePickerNative> = {
|
|
7
|
-
title: 'Components/TimePickerNative',
|
|
8
|
-
component: TimePickerNative,
|
|
9
|
-
parameters: {
|
|
10
|
-
controls: { hideNoControlsWarning: true },
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default meta;
|
|
15
|
-
|
|
16
|
-
export const Default = () => {
|
|
17
|
-
const [value, setValue] = useState<string | null>(null);
|
|
18
|
-
return (
|
|
19
|
-
<Box>
|
|
20
|
-
<TimePickerNative
|
|
21
|
-
id="defaultTimePickerNative"
|
|
22
|
-
name="defaultTimePickerNative"
|
|
23
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
24
|
-
setValue(event.target.value);
|
|
25
|
-
}}
|
|
26
|
-
label="Pick a Time"
|
|
27
|
-
value={value}
|
|
28
|
-
/>
|
|
29
|
-
</Box>
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const WithASpecificInterval = () => {
|
|
34
|
-
const [value, setValue] = useState<string | null>(null);
|
|
35
|
-
return (
|
|
36
|
-
<Box>
|
|
37
|
-
<TimePickerNative
|
|
38
|
-
id="intervalTimePickerNative"
|
|
39
|
-
name="intervalTimePickerNative"
|
|
40
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
41
|
-
setValue(event.target.value)
|
|
42
|
-
}
|
|
43
|
-
value={value}
|
|
44
|
-
label="Pick a Time"
|
|
45
|
-
interval={3600}
|
|
46
|
-
/>
|
|
47
|
-
</Box>
|
|
48
|
-
);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const WithMinAndMaxTimes = () => {
|
|
52
|
-
const [value, setValue] = useState<string | null>(null);
|
|
53
|
-
return (
|
|
54
|
-
<Box>
|
|
55
|
-
<TimePickerNative
|
|
56
|
-
id="startEnd"
|
|
57
|
-
name="startEnd"
|
|
58
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
59
|
-
setValue(event.target.value)
|
|
60
|
-
}
|
|
61
|
-
value={value}
|
|
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
|
-
<TimePickerNative
|
|
75
|
-
id="customDate"
|
|
76
|
-
name="customDate"
|
|
77
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
|
78
|
-
setValue(event.target.value)
|
|
79
|
-
}
|
|
80
|
-
value={value}
|
|
81
|
-
label="Pick a Time"
|
|
82
|
-
startTime={{ hour: 9, minute: 0 }}
|
|
83
|
-
endTime={{ hour: 15, minute: 31 }}
|
|
84
|
-
dateDisplayOptions={{
|
|
85
|
-
hour12: false,
|
|
86
|
-
hour: '2-digit',
|
|
87
|
-
minute: '2-digit',
|
|
88
|
-
}}
|
|
89
|
-
/>
|
|
90
|
-
</Box>
|
|
91
|
-
);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const HelpText = () => {
|
|
95
|
-
const [value, setValue] = useState<string | null>(null);
|
|
96
|
-
return (
|
|
97
|
-
<Box>
|
|
98
|
-
<TimePickerNative
|
|
99
|
-
id="helpText"
|
|
100
|
-
name="helpText"
|
|
101
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
102
|
-
setValue(event.target.value);
|
|
103
|
-
}}
|
|
104
|
-
label="Pick a Time"
|
|
105
|
-
value={value}
|
|
106
|
-
helpText="pick a time, any time..."
|
|
107
|
-
/>
|
|
108
|
-
</Box>
|
|
109
|
-
);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
export const Sizes = () => {
|
|
113
|
-
const [value, setValue] = useState<string | null>(null);
|
|
114
|
-
const [value1, setValue1] = useState<string | null>(null);
|
|
115
|
-
const [value2, setValue2] = useState<string | null>(null);
|
|
116
|
-
return (
|
|
117
|
-
<Box gap="md">
|
|
118
|
-
<TimePickerNative
|
|
119
|
-
id="smTimePickerNative"
|
|
120
|
-
name="smTimePickerNative"
|
|
121
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
122
|
-
setValue(event.target.value);
|
|
123
|
-
}}
|
|
124
|
-
label="Small"
|
|
125
|
-
value={value}
|
|
126
|
-
size="sm"
|
|
127
|
-
/>
|
|
128
|
-
<TimePickerNative
|
|
129
|
-
id="mdTimePickerNative"
|
|
130
|
-
name="mdTimePickerNative"
|
|
131
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
132
|
-
setValue1(event.target.value);
|
|
133
|
-
}}
|
|
134
|
-
label="Medium"
|
|
135
|
-
value={value1}
|
|
136
|
-
size="md"
|
|
137
|
-
/>
|
|
138
|
-
<TimePickerNative
|
|
139
|
-
id="lgTimePickerNative"
|
|
140
|
-
name="lgTimePickerNative"
|
|
141
|
-
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
142
|
-
setValue2(event.target.value);
|
|
143
|
-
}}
|
|
144
|
-
label="Large"
|
|
145
|
-
value={value2}
|
|
146
|
-
size="lg"
|
|
147
|
-
/>
|
|
148
|
-
</Box>
|
|
149
|
-
);
|
|
150
|
-
};
|