@hyphen/hyphen-components 2.9.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.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/package.json +138 -0
- package/src/components/Alert/Alert.constants.ts +19 -0
- package/src/components/Alert/Alert.mdx +29 -0
- package/src/components/Alert/Alert.module.scss +74 -0
- package/src/components/Alert/Alert.stories.tsx +102 -0
- package/src/components/Alert/Alert.test.tsx +187 -0
- package/src/components/Alert/Alert.tsx +157 -0
- package/src/components/Alert/Alert.types.ts +14 -0
- package/src/components/Badge/Badge.mdx +28 -0
- package/src/components/Badge/Badge.module.scss +155 -0
- package/src/components/Badge/Badge.stories.tsx +52 -0
- package/src/components/Badge/Badge.test.tsx +74 -0
- package/src/components/Badge/Badge.tsx +70 -0
- package/src/components/Box/Box.mdx +259 -0
- package/src/components/Box/Box.module.scss +16 -0
- package/src/components/Box/Box.stories.tsx +1679 -0
- package/src/components/Box/Box.test.tsx +478 -0
- package/src/components/Box/Box.tsx +636 -0
- package/src/components/Button/Button.constants.ts +10 -0
- package/src/components/Button/Button.mdx +71 -0
- package/src/components/Button/Button.module.scss +312 -0
- package/src/components/Button/Button.stories.tsx +117 -0
- package/src/components/Button/Button.test.tsx +460 -0
- package/src/components/Button/Button.tsx +241 -0
- package/src/components/Card/Card.mdx +46 -0
- package/src/components/Card/Card.module.scss +6 -0
- package/src/components/Card/Card.stories.tsx +101 -0
- package/src/components/Card/Card.test.tsx +11 -0
- package/src/components/Card/Card.tsx +61 -0
- package/src/components/Card/components/CardFooter/CardFooter.test.tsx +11 -0
- package/src/components/Card/components/CardFooter/CardFooter.tsx +35 -0
- package/src/components/Card/components/CardHeader/CardHeader.test.tsx +23 -0
- package/src/components/Card/components/CardHeader/CardHeader.tsx +54 -0
- package/src/components/Card/components/CardSection/CardSection.test.tsx +28 -0
- package/src/components/Card/components/CardSection/CardSection.tsx +102 -0
- package/src/components/Card/components/index.ts +3 -0
- package/src/components/CheckboxInput/CheckboxInput.mdx +98 -0
- package/src/components/CheckboxInput/CheckboxInput.stories.tsx +254 -0
- package/src/components/CheckboxInput/CheckboxInput.test.tsx +436 -0
- package/src/components/CheckboxInput/CheckboxInput.tsx +171 -0
- package/src/components/CheckboxInput/components/Checkbox.module.scss +174 -0
- package/src/components/CheckboxInput/components/Checkbox.test.tsx +201 -0
- package/src/components/CheckboxInput/components/Checkbox.tsx +176 -0
- package/src/components/CheckboxInput/components/CheckboxIcon.tsx +71 -0
- package/src/components/DateInput/DateInput.mdx +61 -0
- package/src/components/DateInput/DateInput.stories.tsx +168 -0
- package/src/components/DateInput/DateInput.test.tsx +258 -0
- package/src/components/DateInput/DateInput.tsx +189 -0
- package/src/components/DatePicker/DatePicker.mdx +52 -0
- package/src/components/DatePicker/DatePicker.module.scss +603 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +199 -0
- package/src/components/DatePicker/DatePicker.test.tsx +26 -0
- package/src/components/DatePicker/DatePicker.tsx +138 -0
- package/src/components/Details/Details.mdx +30 -0
- package/src/components/Details/Details.module.scss +32 -0
- package/src/components/Details/Details.stories.tsx +38 -0
- package/src/components/Details/Details.test.tsx +189 -0
- package/src/components/Details/Details.tsx +51 -0
- package/src/components/Details/DetailsSummary.tsx +65 -0
- package/src/components/Drawer/Drawer.mdx +117 -0
- package/src/components/Drawer/Drawer.module.scss +96 -0
- package/src/components/Drawer/Drawer.stories.tsx +380 -0
- package/src/components/Drawer/Drawer.test.tsx +90 -0
- package/src/components/Drawer/Drawer.tsx +249 -0
- package/src/components/FormControl/FormControl.tsx +78 -0
- package/src/components/FormLabel/FormLabel.mdx +24 -0
- package/src/components/FormLabel/FormLabel.module.scss +19 -0
- package/src/components/FormLabel/FormLabel.stories.tsx +20 -0
- package/src/components/FormLabel/FormLabel.test.tsx +35 -0
- package/src/components/FormLabel/FormLabel.tsx +96 -0
- package/src/components/Formik/Formik.mdx +10 -0
- package/src/components/Formik/Formik.stories.tsx +307 -0
- package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.test.tsx +172 -0
- package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.tsx +41 -0
- package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.test.tsx +205 -0
- package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.tsx +37 -0
- package/src/components/Formik/FormikSelectInput/FormikSelectInput.test.tsx +210 -0
- package/src/components/Formik/FormikSelectInput/FormikSelectInput.tsx +41 -0
- package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.test.tsx +153 -0
- package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.tsx +44 -0
- package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.test.tsx +161 -0
- package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.tsx +46 -0
- package/src/components/Formik/FormikTextInput/FormikTextInput.test.tsx +176 -0
- package/src/components/Formik/FormikTextInput/FormikTextInput.tsx +38 -0
- package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.test.tsx +170 -0
- package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.tsx +42 -0
- package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.test.tsx +186 -0
- package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.tsx +42 -0
- package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.test.tsx +179 -0
- package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.tsx +42 -0
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +224 -0
- package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +37 -0
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +175 -0
- package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +38 -0
- package/src/components/Formik/FormikToggle/FormikToggle.test.tsx +172 -0
- package/src/components/Formik/FormikToggle/FormikToggle.tsx +38 -0
- package/src/components/Heading/Heading.constants.ts +19 -0
- package/src/components/Heading/Heading.mdx +35 -0
- package/src/components/Heading/Heading.module.scss +5 -0
- package/src/components/Heading/Heading.stories.tsx +90 -0
- package/src/components/Heading/Heading.test.tsx +67 -0
- package/src/components/Heading/Heading.tsx +67 -0
- package/src/components/HelpText/HelpText.module.scss +14 -0
- package/src/components/HelpText/HelpText.tsx +33 -0
- package/src/components/Icon/Icon.mdx +40 -0
- package/src/components/Icon/Icon.stories.tsx +72 -0
- package/src/components/Icon/Icon.test.tsx +30 -0
- package/src/components/Icon/Icon.tsx +61 -0
- package/src/components/InputValidationMessage/InputValidationMessage.module.scss +3 -0
- package/src/components/InputValidationMessage/InputValidationMessage.tsx +27 -0
- package/src/components/Modal/Modal.mdx +60 -0
- package/src/components/Modal/Modal.module.scss +135 -0
- package/src/components/Modal/Modal.stories.tsx +194 -0
- package/src/components/Modal/Modal.test.tsx +81 -0
- package/src/components/Modal/Modal.tsx +174 -0
- package/src/components/Modal/components/ModalBody/ModalBody.test.tsx +20 -0
- package/src/components/Modal/components/ModalBody/ModalBody.tsx +24 -0
- package/src/components/Modal/components/ModalFooter/ModalFooter.test.tsx +32 -0
- package/src/components/Modal/components/ModalFooter/ModalFooter.tsx +37 -0
- package/src/components/Modal/components/ModalHeader/ModalHeader.test.tsx +29 -0
- package/src/components/Modal/components/ModalHeader/ModalHeader.tsx +58 -0
- package/src/components/Modal/components/index.ts +5 -0
- package/src/components/Pagination/Pagination.mdx +26 -0
- package/src/components/Pagination/Pagination.stories.tsx +55 -0
- package/src/components/Pagination/Pagination.test.tsx +225 -0
- package/src/components/Pagination/Pagination.tsx +162 -0
- package/src/components/Pagination/Pagination.utilities.test.ts +133 -0
- package/src/components/Pagination/Pagination.utilities.ts +101 -0
- package/src/components/Popover/Popover.mdx +104 -0
- package/src/components/Popover/Popover.module.scss +74 -0
- package/src/components/Popover/Popover.stories.tsx +471 -0
- package/src/components/Popover/Popover.test.tsx +128 -0
- package/src/components/Popover/Popover.tsx +277 -0
- package/src/components/RadioGroup/RadioGroup.mdx +81 -0
- package/src/components/RadioGroup/RadioGroup.module.scss +23 -0
- package/src/components/RadioGroup/RadioGroup.stories.tsx +375 -0
- package/src/components/RadioGroup/RadioGroup.test.tsx +282 -0
- package/src/components/RadioGroup/RadioGroup.tsx +145 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.module.scss +114 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.test.tsx +156 -0
- package/src/components/RadioGroup/RadioInput/RadioInput.tsx +148 -0
- package/src/components/RadioGroup/RadioInput/RadioInputIcon.tsx +59 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.mdx +36 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.stories.tsx +54 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.test.tsx +70 -0
- package/src/components/ResponsiveProvider/ResponsiveProvider.tsx +73 -0
- package/src/components/SelectInput/SelectInput.mdx +115 -0
- package/src/components/SelectInput/SelectInput.module.scss +357 -0
- package/src/components/SelectInput/SelectInput.stories.tsx +373 -0
- package/src/components/SelectInput/SelectInput.test.tsx +403 -0
- package/src/components/SelectInput/SelectInput.tsx +245 -0
- package/src/components/SelectInputInset/SelectInputInset.mdx +56 -0
- package/src/components/SelectInputInset/SelectInputInset.module.scss +397 -0
- package/src/components/SelectInputInset/SelectInputInset.stories.tsx +189 -0
- package/src/components/SelectInputInset/SelectInputInset.test.tsx +305 -0
- package/src/components/SelectInputInset/SelectInputInset.tsx +235 -0
- package/src/components/SelectInputNative/SelectInputNative.mdx +87 -0
- package/src/components/SelectInputNative/SelectInputNative.module.scss +356 -0
- package/src/components/SelectInputNative/SelectInputNative.stories.tsx +282 -0
- package/src/components/SelectInputNative/SelectInputNative.test.tsx +341 -0
- package/src/components/SelectInputNative/SelectInputNative.tsx +121 -0
- package/src/components/Spinner/Spinner.mdx +29 -0
- package/src/components/Spinner/Spinner.module.scss +16 -0
- package/src/components/Spinner/Spinner.stories.tsx +48 -0
- package/src/components/Spinner/Spinner.test.tsx +47 -0
- package/src/components/Spinner/Spinner.tsx +116 -0
- package/src/components/Table/Table.mdx +216 -0
- package/src/components/Table/Table.module.scss +61 -0
- package/src/components/Table/Table.stories.tsx +884 -0
- package/src/components/Table/Table.test.tsx +437 -0
- package/src/components/Table/Table.tsx +171 -0
- package/src/components/Table/TableBody/TableBody.module.scss +19 -0
- package/src/components/Table/TableBody/TableBody.test.tsx +38 -0
- package/src/components/Table/TableBody/TableBody.tsx +96 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.module.scss +47 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.test.tsx +81 -0
- package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.tsx +94 -0
- package/src/components/Table/TableHead/TableHead.test.tsx +20 -0
- package/src/components/Table/TableHead/TableHead.tsx +78 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.module.scss +72 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.test.tsx +187 -0
- package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.tsx +192 -0
- package/src/components/Table/common/TableRow/TableRow.module.scss +5 -0
- package/src/components/Table/common/TableRow/TableRow.test.tsx +52 -0
- package/src/components/Table/common/TableRow/TableRow.tsx +155 -0
- package/src/components/TextInput/TextInput.mdx +96 -0
- package/src/components/TextInput/TextInput.module.scss +405 -0
- package/src/components/TextInput/TextInput.stories.tsx +268 -0
- package/src/components/TextInput/TextInput.test.tsx +231 -0
- package/src/components/TextInput/TextInput.tsx +263 -0
- package/src/components/TextInputInset/TextInputInset.mdx +62 -0
- package/src/components/TextInputInset/TextInputInset.module.scss +418 -0
- package/src/components/TextInputInset/TextInputInset.stories.tsx +213 -0
- package/src/components/TextInputInset/TextInputInset.test.tsx +222 -0
- package/src/components/TextInputInset/TextInputInset.tsx +261 -0
- package/src/components/TextareaInput/TextareaInput.mdx +117 -0
- package/src/components/TextareaInput/TextareaInput.module.scss +275 -0
- package/src/components/TextareaInput/TextareaInput.stories.tsx +293 -0
- package/src/components/TextareaInput/TextareaInput.test.tsx +195 -0
- package/src/components/TextareaInput/TextareaInput.tsx +182 -0
- package/src/components/TextareaInputInset/TextareaInputInset.mdx +55 -0
- package/src/components/TextareaInputInset/TextareaInputInset.module.scss +337 -0
- package/src/components/TextareaInputInset/TextareaInputInset.stories.tsx +160 -0
- package/src/components/TextareaInputInset/TextareaInputInset.test.tsx +199 -0
- package/src/components/TextareaInputInset/TextareaInputInset.tsx +213 -0
- package/src/components/ThemeProvider/ThemeProvider.mdx +11 -0
- package/src/components/ThemeProvider/ThemeProvider.stories.tsx +56 -0
- package/src/components/ThemeProvider/ThemeProvider.tsx +75 -0
- package/src/components/TimePicker/TimePicker.mdx +75 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +149 -0
- package/src/components/TimePicker/TimePicker.test.tsx +97 -0
- package/src/components/TimePicker/TimePicker.tsx +83 -0
- package/src/components/TimePickerNative/TimePickerNative.mdx +67 -0
- package/src/components/TimePickerNative/TimePickerNative.stories.tsx +151 -0
- package/src/components/TimePickerNative/TimePickerNative.test.tsx +117 -0
- package/src/components/TimePickerNative/TimePickerNative.tsx +93 -0
- package/src/components/Toast/Toast.mdx +134 -0
- package/src/components/Toast/Toast.store.ts +280 -0
- package/src/components/Toast/Toast.stories.tsx +283 -0
- package/src/components/Toast/Toast.test.tsx +784 -0
- package/src/components/Toast/Toast.types.ts +98 -0
- package/src/components/Toast/ToastContainer.tsx +170 -0
- package/src/components/Toast/ToastNotification.module.scss +63 -0
- package/src/components/Toast/ToastNotification.tsx +176 -0
- package/src/components/Toast/index.ts +4 -0
- package/src/components/Toast/toast.ts +102 -0
- package/src/components/Toast/useToasts.ts +102 -0
- package/src/components/Toggle/Toggle.mdx +51 -0
- package/src/components/Toggle/Toggle.module.scss +294 -0
- package/src/components/Toggle/Toggle.stories.tsx +128 -0
- package/src/components/Toggle/Toggle.test.tsx +308 -0
- package/src/components/Toggle/Toggle.tsx +184 -0
- package/src/constants/keyCodes.ts +2 -0
- package/src/docs/Brands.mdx +153 -0
- package/src/docs/Colors.mdx +158 -0
- package/src/docs/DesignTokens.mdx +415 -0
- package/src/docs/GetStarted.mdx +47 -0
- package/src/docs/intro.mdx +12 -0
- package/src/fonts/AvenirBold.otf +0 -0
- package/src/fonts/AvenirBold.woff +0 -0
- package/src/fonts/AvenirBold.woff2 +0 -0
- package/src/fonts/AvenirLight.otf +0 -0
- package/src/fonts/AvenirLight.woff +0 -0
- package/src/fonts/AvenirLight.woff2 +0 -0
- package/src/fonts/AvenirRegular.otf +0 -0
- package/src/fonts/AvenirRegular.woff +0 -0
- package/src/fonts/AvenirRegular.woff2 +0 -0
- package/src/fonts/Geist-Bold.otf +0 -0
- package/src/fonts/Geist-Bold.woff +0 -0
- package/src/fonts/Geist-Bold.woff2 +0 -0
- package/src/fonts/Geist-Medium.otf +0 -0
- package/src/fonts/Geist-Medium.woff +0 -0
- package/src/fonts/Geist-Medium.woff2 +0 -0
- package/src/fonts/Geist-Regular.otf +0 -0
- package/src/fonts/Geist-Regular.woff +0 -0
- package/src/fonts/Geist-Regular.woff2 +0 -0
- package/src/fonts/Geist-SemiBold.otf +0 -0
- package/src/fonts/Geist-SemiBold.woff +0 -0
- package/src/fonts/Geist-SemiBold.woff2 +0 -0
- package/src/fonts/GeistMono-Regular.otf +0 -0
- package/src/fonts/GeistMono-Regular.woff +0 -0
- package/src/fonts/GeistMono-Regular.woff2 +0 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useBreakpoint/useBreakpoint.mdx +26 -0
- package/src/hooks/useBreakpoint/useBreakpoint.stories.tsx +30 -0
- package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +19 -0
- package/src/hooks/useBreakpoint/useBreakpoint.ts +50 -0
- package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayouEffect.ts +5 -0
- package/src/hooks/useOpenClose/useOpenClose.mdx +15 -0
- package/src/hooks/useOpenClose/useOpenClose.stories.tsx +41 -0
- package/src/hooks/useOpenClose/useOpenClose.test.tsx +119 -0
- package/src/hooks/useOpenClose/useOpenClose.tsx +95 -0
- package/src/hooks/useWindowSize/useWindowSize.mdx +25 -0
- package/src/hooks/useWindowSize/useWindowSize.stories.tsx +35 -0
- package/src/hooks/useWindowSize/useWindowSize.ts +24 -0
- package/src/index.ts +48 -0
- package/src/lib/cssShorthandToClasses.test.ts +149 -0
- package/src/lib/cssShorthandToClasses.ts +133 -0
- package/src/lib/doesStringIncludeCssUnit.ts +6 -0
- package/src/lib/generateResponsiveClasses.test.ts +24 -0
- package/src/lib/generateResponsiveClasses.ts +30 -0
- package/src/lib/getAutoCompleteValue.test.ts +27 -0
- package/src/lib/getAutoCompleteValue.ts +12 -0
- package/src/lib/getColumnKeys.ts +27 -0
- package/src/lib/getDimensionCss.test.ts +148 -0
- package/src/lib/getDimensionCss.ts +73 -0
- package/src/lib/getElementType.test.tsx +42 -0
- package/src/lib/getElementType.ts +42 -0
- package/src/lib/getFlexCss.test.ts +122 -0
- package/src/lib/getFlexCss.ts +67 -0
- package/src/lib/index.ts +15 -0
- package/src/lib/isFunction.ts +6 -0
- package/src/lib/mergeRefs.ts +15 -0
- package/src/lib/prefersReducedMotion.ts +12 -0
- package/src/lib/react-children-utilities/filter.ts +12 -0
- package/src/lib/react-children-utilities/index.ts +1 -0
- package/src/lib/reactRouterClickHandler.ts +37 -0
- package/src/lib/resolveValue.ts +7 -0
- package/src/lib/tokens.ts +139 -0
- package/src/modes.ts +8 -0
- package/src/styles/animation.scss +152 -0
- package/src/styles/cursor.scss +43 -0
- package/src/styles/display.scss +119 -0
- package/src/styles/flex.scss +453 -0
- package/src/styles/fonts.scss +44 -0
- package/src/styles/globals/utilities.scss +4 -0
- package/src/styles/mixins.scss +14 -0
- package/src/styles/overflow.scss +41 -0
- package/src/styles/position.scss +45 -0
- package/src/styles/reset.scss +108 -0
- package/src/styles/text-align.scss +21 -0
- package/src/styles/utilities.scss +9 -0
- package/src/styles/variables/forms.scss +71 -0
- package/src/styles/variables/index.scss +3 -0
- package/src/styles/white-space.scss +21 -0
- package/src/types/index.ts +201 -0
- package/src/types/lib.types.ts +3 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
ChangeEvent,
|
|
3
|
+
forwardRef,
|
|
4
|
+
FocusEvent,
|
|
5
|
+
ForwardRefExoticComponent,
|
|
6
|
+
ReactNode,
|
|
7
|
+
HTMLProps,
|
|
8
|
+
InputHTMLAttributes,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import classNames from 'classnames';
|
|
11
|
+
import { ResponsiveProp } from '../../types';
|
|
12
|
+
import { generateResponsiveClasses } from '../../lib/generateResponsiveClasses';
|
|
13
|
+
|
|
14
|
+
import { Box, BoxProps } from '../Box/Box';
|
|
15
|
+
import { HelpText } from '../HelpText/HelpText';
|
|
16
|
+
import { getAutoCompleteValue } from '../../lib/getAutoCompleteValue';
|
|
17
|
+
import styles from './TextareaInputInset.module.scss';
|
|
18
|
+
import { InputValidationMessage } from '../InputValidationMessage/InputValidationMessage';
|
|
19
|
+
|
|
20
|
+
export type TextareaInputInsetSize = 'md' | 'lg';
|
|
21
|
+
export interface TextareaInputInsetProps {
|
|
22
|
+
/**
|
|
23
|
+
* The input's id attribute. Used to programmatically tie the input with its label.
|
|
24
|
+
*/
|
|
25
|
+
id: string;
|
|
26
|
+
/**
|
|
27
|
+
* Custom content to be displayed above the input. If the label is hidden, will be used to set aria-label attribute.
|
|
28
|
+
*/
|
|
29
|
+
label: string;
|
|
30
|
+
/**
|
|
31
|
+
* Callback function to call on change event.
|
|
32
|
+
*/
|
|
33
|
+
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
34
|
+
/**
|
|
35
|
+
* The text value of the input. Required since our Input is a controlled component.
|
|
36
|
+
*/
|
|
37
|
+
value: InputHTMLAttributes<HTMLInputElement>['value'];
|
|
38
|
+
/**
|
|
39
|
+
* Automatically focus the input when the page is loaded.
|
|
40
|
+
*/
|
|
41
|
+
autoFocus?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Custom class to be added to standard input classes.
|
|
44
|
+
*/
|
|
45
|
+
className?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Mark the input field as invalid and display a validation message.
|
|
48
|
+
* Pass a string or node to render a validation message below the input.
|
|
49
|
+
*/
|
|
50
|
+
error?: ReactNode;
|
|
51
|
+
/**
|
|
52
|
+
* Additional clarifying text to help describe the input
|
|
53
|
+
*/
|
|
54
|
+
helpText?: ReactNode;
|
|
55
|
+
/**
|
|
56
|
+
* Props passed directly to the input element of the component
|
|
57
|
+
*/
|
|
58
|
+
inputProps?: BoxProps & HTMLProps<HTMLInputElement>;
|
|
59
|
+
/**
|
|
60
|
+
* The input's disabled attribute
|
|
61
|
+
*/
|
|
62
|
+
isDisabled?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* The required and aria-required attributes on the input
|
|
65
|
+
*/
|
|
66
|
+
isRequired?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* The input's 'maxlength' attribute.
|
|
69
|
+
* NOTE: initializing the input with a value longer than the desired maxlength will not trim this value.
|
|
70
|
+
*/
|
|
71
|
+
maxLength?: number;
|
|
72
|
+
/**
|
|
73
|
+
* The input's 'name' attribute.
|
|
74
|
+
*/
|
|
75
|
+
name?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Callback function to call on blur event.
|
|
78
|
+
*/
|
|
79
|
+
onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
|
|
80
|
+
/**
|
|
81
|
+
* Callback function to call on focus event.
|
|
82
|
+
*/
|
|
83
|
+
onFocus?: (event: FocusEvent<HTMLInputElement>) => void;
|
|
84
|
+
/**
|
|
85
|
+
* The input placeholder attribute.
|
|
86
|
+
*/
|
|
87
|
+
placeholder?: string;
|
|
88
|
+
/**
|
|
89
|
+
* An input helper rendered before the input field value
|
|
90
|
+
*/
|
|
91
|
+
prefix?: ReactNode;
|
|
92
|
+
/**
|
|
93
|
+
* Visual indicator that the field is required, that gets appended to the label
|
|
94
|
+
*/
|
|
95
|
+
requiredIndicator?: ReactNode;
|
|
96
|
+
/**
|
|
97
|
+
* Textarea resize behavior
|
|
98
|
+
*/
|
|
99
|
+
resize?: 'vertical' | 'horizontal' | 'none' | 'both';
|
|
100
|
+
/**
|
|
101
|
+
* number of visible text lines for the control.
|
|
102
|
+
*/
|
|
103
|
+
rows?: number;
|
|
104
|
+
/**
|
|
105
|
+
* The size of the text input.
|
|
106
|
+
*/
|
|
107
|
+
size?: TextareaInputInsetSize | ResponsiveProp<TextareaInputInsetSize>;
|
|
108
|
+
/**
|
|
109
|
+
* An input helper rendered after the input field value
|
|
110
|
+
*/
|
|
111
|
+
suffix?: ReactNode;
|
|
112
|
+
/**
|
|
113
|
+
* The input 'type' value. Defaults to type 'text'.
|
|
114
|
+
*/
|
|
115
|
+
type?: InputHTMLAttributes<HTMLInputElement>['type'];
|
|
116
|
+
/**
|
|
117
|
+
* Additional props to be spread to rendered element
|
|
118
|
+
*/
|
|
119
|
+
[x: string]: any; // eslint-disable-line
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const TextareaInputInset: ForwardRefExoticComponent<TextareaInputInsetProps> =
|
|
123
|
+
forwardRef<HTMLDivElement, TextareaInputInsetProps>(
|
|
124
|
+
(
|
|
125
|
+
{
|
|
126
|
+
id,
|
|
127
|
+
label,
|
|
128
|
+
onChange,
|
|
129
|
+
value,
|
|
130
|
+
autoComplete = false,
|
|
131
|
+
autoFocus = false,
|
|
132
|
+
className,
|
|
133
|
+
error = false,
|
|
134
|
+
helpText,
|
|
135
|
+
inputProps = {},
|
|
136
|
+
isDisabled = false,
|
|
137
|
+
isRequired = false,
|
|
138
|
+
maxLength = undefined,
|
|
139
|
+
name = '',
|
|
140
|
+
onBlur = undefined,
|
|
141
|
+
onFocus = undefined,
|
|
142
|
+
placeholder = ' ',
|
|
143
|
+
requiredIndicator = ' *',
|
|
144
|
+
resize = 'vertical',
|
|
145
|
+
rows = 5,
|
|
146
|
+
size = 'md',
|
|
147
|
+
type = 'text',
|
|
148
|
+
},
|
|
149
|
+
ref
|
|
150
|
+
) => {
|
|
151
|
+
const responsiveClasses = generateResponsiveClasses('size', size);
|
|
152
|
+
|
|
153
|
+
const inputWrapperClasses = classNames(
|
|
154
|
+
'hyphen-components__variables__form-control',
|
|
155
|
+
styles['text-input-wrapper'],
|
|
156
|
+
...responsiveClasses.map((c) => styles[c]),
|
|
157
|
+
{
|
|
158
|
+
[styles.disabled]: isDisabled,
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const computedInputProps: TextareaInputInsetProps['inputProps'] = {
|
|
163
|
+
...inputProps, // These are spread first so that we don't have top level props overwritten by the user.
|
|
164
|
+
'aria-required': isRequired,
|
|
165
|
+
'aria-invalid': !!error,
|
|
166
|
+
'aria-label': label,
|
|
167
|
+
'aria-labelledby': label ? `${id}Label` : undefined,
|
|
168
|
+
autoComplete: getAutoCompleteValue(autoComplete),
|
|
169
|
+
autoFocus,
|
|
170
|
+
className: classNames(styles[`textarea-resize-${resize}`], {
|
|
171
|
+
[styles.error]: error,
|
|
172
|
+
}),
|
|
173
|
+
disabled: isDisabled,
|
|
174
|
+
id,
|
|
175
|
+
maxLength,
|
|
176
|
+
name,
|
|
177
|
+
onBlur,
|
|
178
|
+
onChange,
|
|
179
|
+
onFocus,
|
|
180
|
+
placeholder,
|
|
181
|
+
required: isRequired,
|
|
182
|
+
rows,
|
|
183
|
+
type,
|
|
184
|
+
value,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<Box width="100" ref={ref} className={className}>
|
|
189
|
+
<Box
|
|
190
|
+
display="block"
|
|
191
|
+
position="relative"
|
|
192
|
+
className={inputWrapperClasses}
|
|
193
|
+
>
|
|
194
|
+
<Box as="textarea" {...computedInputProps} />
|
|
195
|
+
<label
|
|
196
|
+
htmlFor={id}
|
|
197
|
+
className={styles['text-input-label']}
|
|
198
|
+
id={`${id}Label`}
|
|
199
|
+
>
|
|
200
|
+
{label}
|
|
201
|
+
{isRequired && requiredIndicator && (
|
|
202
|
+
<span>{requiredIndicator}</span>
|
|
203
|
+
)}
|
|
204
|
+
</label>
|
|
205
|
+
</Box>
|
|
206
|
+
{helpText && <HelpText>{helpText}</HelpText>}
|
|
207
|
+
{error && error !== true && (
|
|
208
|
+
<InputValidationMessage>{error}</InputValidationMessage>
|
|
209
|
+
)}
|
|
210
|
+
</Box>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import { ThemeProvider } from './ThemeProvider';
|
|
3
|
+
import * as Stories from './ThemeProvider.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
# ThemeProvider
|
|
8
|
+
|
|
9
|
+
Allow users to set the theme for the entire application by adding the `ThemeProvider` to the root of the application.
|
|
10
|
+
|
|
11
|
+
<Canvas of={Stories.BasicUsage} />
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ThemeProvider } from './ThemeProvider';
|
|
3
|
+
import type { Meta } from '@storybook/react';
|
|
4
|
+
import { Box } from '../Box/Box';
|
|
5
|
+
import { RadioGroup } from '../RadioGroup/RadioGroup';
|
|
6
|
+
import { useTheme, Theme } from './ThemeProvider';
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof ThemeProvider> = {
|
|
9
|
+
title: 'Providers/ThemeProvider',
|
|
10
|
+
component: ThemeProvider,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
|
|
15
|
+
export const BasicUsage = () =>
|
|
16
|
+
(() => {
|
|
17
|
+
const App = () => {
|
|
18
|
+
const { theme, setTheme } = useTheme();
|
|
19
|
+
|
|
20
|
+
const options = [
|
|
21
|
+
{
|
|
22
|
+
id: 'light',
|
|
23
|
+
value: 'light',
|
|
24
|
+
label: 'Light',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'dark',
|
|
28
|
+
value: 'dark',
|
|
29
|
+
label: 'Dark',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'system',
|
|
33
|
+
value: 'system',
|
|
34
|
+
label: 'System',
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Box gap="md" background="secondary" padding="xl" color="base">
|
|
40
|
+
<p>Theme: {theme}</p>
|
|
41
|
+
|
|
42
|
+
<RadioGroup
|
|
43
|
+
name="SelectTheme"
|
|
44
|
+
value={theme}
|
|
45
|
+
onChange={(event) => setTheme(event.target.value as Theme)}
|
|
46
|
+
options={options}
|
|
47
|
+
/>
|
|
48
|
+
</Box>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
return (
|
|
52
|
+
<ThemeProvider defaultTheme="light" storageKey="hyphen-ui-theme">
|
|
53
|
+
<App />
|
|
54
|
+
</ThemeProvider>
|
|
55
|
+
);
|
|
56
|
+
})();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React, { createContext, useState, useEffect, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export type Theme = 'dark' | 'light' | 'system';
|
|
4
|
+
|
|
5
|
+
type ThemeProviderProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
defaultTheme?: Theme;
|
|
8
|
+
storageKey?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type ThemeProviderState = {
|
|
12
|
+
theme: Theme;
|
|
13
|
+
setTheme: (theme: Theme) => void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const initialState: ThemeProviderState = {
|
|
17
|
+
theme: 'system',
|
|
18
|
+
setTheme: () => null,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const ThemeProviderContext = createContext<ThemeProviderState>(initialState);
|
|
22
|
+
|
|
23
|
+
export function ThemeProvider({
|
|
24
|
+
children,
|
|
25
|
+
defaultTheme = 'system',
|
|
26
|
+
storageKey = 'hyphen-ui-theme',
|
|
27
|
+
...props
|
|
28
|
+
}: ThemeProviderProps) {
|
|
29
|
+
const [theme, setTheme] = useState<Theme>(
|
|
30
|
+
() => (localStorage.getItem(storageKey) as Theme) || defaultTheme
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const root = window.document.documentElement;
|
|
35
|
+
|
|
36
|
+
root.classList.remove('light', 'dark');
|
|
37
|
+
|
|
38
|
+
if (theme === 'system') {
|
|
39
|
+
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)')
|
|
40
|
+
.matches
|
|
41
|
+
? 'dark'
|
|
42
|
+
: 'light';
|
|
43
|
+
|
|
44
|
+
root.classList.add(systemTheme);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
root.classList.add(theme);
|
|
49
|
+
}, [theme]);
|
|
50
|
+
|
|
51
|
+
const value = {
|
|
52
|
+
theme,
|
|
53
|
+
setTheme: (theme: Theme) => {
|
|
54
|
+
localStorage.setItem(storageKey, theme);
|
|
55
|
+
setTheme(theme);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<ThemeProviderContext.Provider {...props} value={value}>
|
|
61
|
+
{children}
|
|
62
|
+
</ThemeProviderContext.Provider>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const useTheme = () => {
|
|
67
|
+
const context = useContext(ThemeProviderContext);
|
|
68
|
+
|
|
69
|
+
if (context === undefined)
|
|
70
|
+
throw new Error(
|
|
71
|
+
'useTheme must be used within a ThemeProvider. Be sure your App is wrapped in ThemeProvider.'
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return context;
|
|
75
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import { TimePicker } from './TimePicker';
|
|
3
|
+
import * as Stories from './TimePicker.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
# TimePicker
|
|
8
|
+
|
|
9
|
+
Use a TimePicker 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 [SelectInput](?path=/docs/components-selectinput-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:_ 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`.
|
|
16
|
+
|
|
17
|
+
## Props
|
|
18
|
+
|
|
19
|
+
<ArgTypes of={TimePicker} />
|
|
20
|
+
|
|
21
|
+
## Default
|
|
22
|
+
|
|
23
|
+
<Canvas of={Stories.Default} />
|
|
24
|
+
|
|
25
|
+
## With A Specific Interval
|
|
26
|
+
|
|
27
|
+
Pass an `interval` (seconds) value to determine how many times get generated as options.
|
|
28
|
+
The example below uses `3600` --> 1 Hour Intervals
|
|
29
|
+
|
|
30
|
+
<Canvas of={Stories.WithASpecificInterval} />
|
|
31
|
+
|
|
32
|
+
## With Min and Max Times
|
|
33
|
+
|
|
34
|
+
You can determine the range of times to be shown by capping the start and end times.
|
|
35
|
+
Use `startTime` and `endTime` for this. The expected values for `hour` and `minute` properties
|
|
36
|
+
are `0-24` and `0-60` respectively.
|
|
37
|
+
|
|
38
|
+
IMPORTANT: `startTime` is inclusive, and `endTime` is exclusive. This is to avoid
|
|
39
|
+
the options showing the startTime twice when using a 24-hour cycle.
|
|
40
|
+
|
|
41
|
+
See example below where we want to show 15 minute increments starting at 9:00AM and ending at 3:30PM.
|
|
42
|
+
|
|
43
|
+
<Canvas of={Stories.WithMinAndMaxTimes} />
|
|
44
|
+
|
|
45
|
+
## With Custom Date Display
|
|
46
|
+
|
|
47
|
+
The labels for the dropdwon options are governed by JS `toLocaleTimeString`, and as such
|
|
48
|
+
options are available to customize these.
|
|
49
|
+
|
|
50
|
+
NOTE: that the option values are always returned as ISO strings regardless of the label display option.
|
|
51
|
+
|
|
52
|
+
The example below is shown in military (24-hour) time.
|
|
53
|
+
|
|
54
|
+
<Canvas of={Stories.WithCustomDateDisplay} />
|
|
55
|
+
|
|
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
|
+
## Help Text
|
|
64
|
+
|
|
65
|
+
<Canvas of={Stories.HelpText} />
|
|
66
|
+
|
|
67
|
+
## Sizes
|
|
68
|
+
|
|
69
|
+
Set the size of the input to `sm`, `md` or `lg`. `md` is the default size.
|
|
70
|
+
|
|
71
|
+
<Canvas of={Stories.Sizes} />
|
|
72
|
+
|
|
73
|
+
## Component Design Tokens
|
|
74
|
+
|
|
75
|
+
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).
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react';
|
|
2
|
+
import React, { ChangeEvent, useState } from 'react';
|
|
3
|
+
import { TimePicker } from './TimePicker';
|
|
4
|
+
import { Box } from '../Box/Box';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof TimePicker> = {
|
|
7
|
+
title: 'Components/TimePicker',
|
|
8
|
+
component: TimePicker,
|
|
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 height="360px">
|
|
20
|
+
<TimePicker
|
|
21
|
+
id="defaultTimePicker"
|
|
22
|
+
name="defaultTimePicker"
|
|
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
|
+
<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
|
+
);
|
|
71
|
+
|
|
72
|
+
export const WithOpenMenu = () => {
|
|
73
|
+
const [value, setValue] = useState<string | null>(null);
|
|
74
|
+
return (
|
|
75
|
+
<Box height="260px">
|
|
76
|
+
<TimePicker
|
|
77
|
+
id="openMenu"
|
|
78
|
+
name="openMenu"
|
|
79
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
80
|
+
setValue(event.target.value);
|
|
81
|
+
}}
|
|
82
|
+
label="Pick a Time"
|
|
83
|
+
value={value}
|
|
84
|
+
menuIsOpen
|
|
85
|
+
interval={3600}
|
|
86
|
+
startTime={{ hour: 9, minute: 0 }}
|
|
87
|
+
endTime={{ hour: 13, minute: 1 }}
|
|
88
|
+
/>
|
|
89
|
+
</Box>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const HelpText = () => {
|
|
94
|
+
const [value, setValue] = useState<string>('');
|
|
95
|
+
return (
|
|
96
|
+
<Box height="360px">
|
|
97
|
+
<TimePicker
|
|
98
|
+
id="helpText"
|
|
99
|
+
name="helpText"
|
|
100
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
101
|
+
setValue(event.target.value);
|
|
102
|
+
}}
|
|
103
|
+
label="Pick a Time"
|
|
104
|
+
value={value}
|
|
105
|
+
helpText="pick a time, any time..."
|
|
106
|
+
/>
|
|
107
|
+
</Box>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const Sizes = () => {
|
|
112
|
+
const [value, setValue] = useState<string>();
|
|
113
|
+
const [value1, setValue1] = useState<string>();
|
|
114
|
+
const [value2, setValue2] = useState<string>();
|
|
115
|
+
return (
|
|
116
|
+
<Box gap="md" height="360px">
|
|
117
|
+
<TimePicker
|
|
118
|
+
id="smTimePicker"
|
|
119
|
+
name="smTimePicker"
|
|
120
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
121
|
+
setValue(event.target.value);
|
|
122
|
+
}}
|
|
123
|
+
label="Small"
|
|
124
|
+
value={value}
|
|
125
|
+
size="sm"
|
|
126
|
+
/>
|
|
127
|
+
<TimePicker
|
|
128
|
+
id="mdTimePicker"
|
|
129
|
+
name="mdTimePicker"
|
|
130
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
131
|
+
setValue1(event.target.value);
|
|
132
|
+
}}
|
|
133
|
+
label="Medium"
|
|
134
|
+
value={value1}
|
|
135
|
+
size="md"
|
|
136
|
+
/>
|
|
137
|
+
<TimePicker
|
|
138
|
+
id="lgTimePicker"
|
|
139
|
+
name="lgTimePicker"
|
|
140
|
+
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
|
141
|
+
setValue2(event.target.value);
|
|
142
|
+
}}
|
|
143
|
+
label="Large"
|
|
144
|
+
value={value2}
|
|
145
|
+
size="lg"
|
|
146
|
+
/>
|
|
147
|
+
</Box>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { screen, render } from '@testing-library/react';
|
|
3
|
+
import { TimePicker } from './TimePicker';
|
|
4
|
+
|
|
5
|
+
describe('TimePicker', () => {
|
|
6
|
+
describe('Default', () => {
|
|
7
|
+
it('Renders a TimePicker (select) with default props', () => {
|
|
8
|
+
render(
|
|
9
|
+
<TimePicker
|
|
10
|
+
name="timePicker"
|
|
11
|
+
id="timePicker"
|
|
12
|
+
onChange={() => null}
|
|
13
|
+
value={null}
|
|
14
|
+
label="Select Time"
|
|
15
|
+
menuIsOpen
|
|
16
|
+
maxMenuHeight={2000}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
21
|
+
|
|
22
|
+
const expectedTimes = [
|
|
23
|
+
'12:00 AM',
|
|
24
|
+
'12:15 AM',
|
|
25
|
+
'12:30 AM',
|
|
26
|
+
'12:45 AM',
|
|
27
|
+
'01:00 AM',
|
|
28
|
+
'01:15 AM',
|
|
29
|
+
];
|
|
30
|
+
expect(timePicker).toBeInTheDocument();
|
|
31
|
+
expectedTimes.forEach((time) => {
|
|
32
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('Min/Max & Interval', () => {
|
|
38
|
+
it('Renders correct options based on interval and start end times.', () => {
|
|
39
|
+
render(
|
|
40
|
+
<TimePicker
|
|
41
|
+
name="timePicker"
|
|
42
|
+
id="timePicker"
|
|
43
|
+
onChange={() => null}
|
|
44
|
+
value={null}
|
|
45
|
+
label="Select Time"
|
|
46
|
+
menuIsOpen
|
|
47
|
+
maxMenuHeight={2000}
|
|
48
|
+
interval={3600}
|
|
49
|
+
startTime={{ hour: 9, minute: 0 }}
|
|
50
|
+
endTime={{ hour: 12, minute: 0 }}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
55
|
+
|
|
56
|
+
const expectedTimes = ['09:00 AM', '10:00 AM', '11:00 AM'];
|
|
57
|
+
|
|
58
|
+
const notExpected = ['12:00 PM', '12:45 AM', '01:00 AM', '01:15 AM'];
|
|
59
|
+
expect(timePicker).toBeInTheDocument();
|
|
60
|
+
expectedTimes.forEach((time) => {
|
|
61
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
notExpected.forEach((time) => {
|
|
65
|
+
expect(screen.queryByText(time)).toBe(null);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('Custom Date Display', () => {
|
|
71
|
+
it('renders the times based on the options provided', () => {
|
|
72
|
+
render(
|
|
73
|
+
<TimePicker
|
|
74
|
+
name="timePicker"
|
|
75
|
+
id="timePicker"
|
|
76
|
+
onChange={() => null}
|
|
77
|
+
value={null}
|
|
78
|
+
label="Select Time"
|
|
79
|
+
menuIsOpen
|
|
80
|
+
maxMenuHeight={2000}
|
|
81
|
+
dateDisplayOptions={{ hour12: false }}
|
|
82
|
+
startTime={{ hour: 13, minute: 0 }}
|
|
83
|
+
endTime={{ hour: 15, minute: 1 }}
|
|
84
|
+
interval={3600}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const timePicker = screen.getByLabelText('Select Time');
|
|
89
|
+
|
|
90
|
+
const expectedTimes = ['13:00:00', '14:00:00', '15:00:00'];
|
|
91
|
+
expect(timePicker).toBeInTheDocument();
|
|
92
|
+
expectedTimes.forEach((time) => {
|
|
93
|
+
expect(screen.queryByText(time)).toBeInTheDocument();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|