@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,192 @@
|
|
|
1
|
+
import React, { FC, Key, KeyboardEvent, MouseEvent, ReactNode } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { Box } from '../../../Box/Box';
|
|
4
|
+
import { Icon } from '../../../Icon/Icon';
|
|
5
|
+
import { Column, EventWithColumnKey } from '../../../../types';
|
|
6
|
+
import styles from './TableHeaderCell.module.scss';
|
|
7
|
+
|
|
8
|
+
export interface TableHeaderCellProps {
|
|
9
|
+
/**
|
|
10
|
+
* Title to display for the column.
|
|
11
|
+
*/
|
|
12
|
+
column: Column;
|
|
13
|
+
/**
|
|
14
|
+
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
15
|
+
* for a specific column.
|
|
16
|
+
*/
|
|
17
|
+
align?: 'left' | 'right' | 'center';
|
|
18
|
+
/**
|
|
19
|
+
* Custom class to apply to the `<th>` element.
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Key of corresponding data value in the table.
|
|
24
|
+
*/
|
|
25
|
+
dataKey?: Key;
|
|
26
|
+
/**
|
|
27
|
+
* Remove borders around th elements.
|
|
28
|
+
*/
|
|
29
|
+
isBorderless?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Determines if table header cells should render as compact (less padding);
|
|
32
|
+
*/
|
|
33
|
+
isCompact?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* If table scrolls vertically, header will remain stuck to the top of the table, and not scroll away.
|
|
36
|
+
*/
|
|
37
|
+
hasStickyHeader?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Boolean to mark if a column is sortable. This will show the sorting icons. Use
|
|
40
|
+
* in conjunction with the `sortDirection` prop to determine which icon is shown.
|
|
41
|
+
*/
|
|
42
|
+
isSortable?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Callback function to execute when a sortable column's header is clicked.
|
|
45
|
+
* Column can be sorted without providing an onSort method, it means that the arrows
|
|
46
|
+
* will not be clickable, but they will still represent the sort state
|
|
47
|
+
* of a column as determined by the `sortDirection` prop.
|
|
48
|
+
*/
|
|
49
|
+
onSort?: (event: EventWithColumnKey) => void;
|
|
50
|
+
/**
|
|
51
|
+
* The key of the sorted column and its sort direction.
|
|
52
|
+
*/
|
|
53
|
+
sortedColumn?: {
|
|
54
|
+
dataKey: string | undefined;
|
|
55
|
+
sortDirection: 'none' | 'ascending' | 'descending' | undefined;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Will stick to either the left or right side of a table during horizontal scroll.
|
|
59
|
+
*/
|
|
60
|
+
sticky?: 'left' | 'right';
|
|
61
|
+
/**
|
|
62
|
+
* Whether the text should be cut off with ellipsis if it exceeds the width of the column.
|
|
63
|
+
*/
|
|
64
|
+
truncateOverflow?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Width of the column, if using the `useFixedWidthColumns` prop is set to true.
|
|
67
|
+
*/
|
|
68
|
+
width?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// eslint-disable-line import/prefer-default-export
|
|
72
|
+
export const TableHeaderCell: FC<TableHeaderCellProps> = ({
|
|
73
|
+
column,
|
|
74
|
+
align = 'left',
|
|
75
|
+
className = undefined,
|
|
76
|
+
dataKey = undefined,
|
|
77
|
+
isBorderless = false,
|
|
78
|
+
isCompact = false,
|
|
79
|
+
hasStickyHeader = false,
|
|
80
|
+
isSortable = false,
|
|
81
|
+
onSort = undefined,
|
|
82
|
+
sortedColumn = undefined,
|
|
83
|
+
sticky = undefined,
|
|
84
|
+
truncateOverflow = false,
|
|
85
|
+
width = undefined,
|
|
86
|
+
}) => {
|
|
87
|
+
const isColumnSorted = (columnDataKey: Key | undefined): boolean =>
|
|
88
|
+
!!sortedColumn && sortedColumn.dataKey === columnDataKey;
|
|
89
|
+
|
|
90
|
+
const getSortDirection = ():
|
|
91
|
+
| 'ascending'
|
|
92
|
+
| 'descending'
|
|
93
|
+
| 'none'
|
|
94
|
+
| undefined =>
|
|
95
|
+
sortedColumn && isColumnSorted(column.dataKey)
|
|
96
|
+
? sortedColumn.sortDirection
|
|
97
|
+
: 'none';
|
|
98
|
+
|
|
99
|
+
const renderIcon = (): ReactNode => {
|
|
100
|
+
const renderArrows = (): ReactNode => {
|
|
101
|
+
if (getSortDirection() === 'ascending') {
|
|
102
|
+
return (
|
|
103
|
+
<Icon
|
|
104
|
+
name="caret-sm-up"
|
|
105
|
+
data-testid="tableHeaderCellSortAsc-testid"
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
if (getSortDirection() === 'descending') {
|
|
110
|
+
return (
|
|
111
|
+
<Icon
|
|
112
|
+
name="caret-sm-down"
|
|
113
|
+
data-testid="tableHeaderCellSortDesc-testid"
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<Box
|
|
120
|
+
display="inline-block"
|
|
121
|
+
width="12px"
|
|
122
|
+
height="12px"
|
|
123
|
+
aria-hidden="true"
|
|
124
|
+
data-testid="tableHeaderCellSortNone-testid"
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return <span className={styles['sort-icon']}>{renderArrows()}</span>;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleKeyPress = (
|
|
133
|
+
event: KeyboardEvent<HTMLTableHeaderCellElement>
|
|
134
|
+
): void => {
|
|
135
|
+
if (!onSort || !isSortable) return;
|
|
136
|
+
|
|
137
|
+
const enterKey = 13;
|
|
138
|
+
const spaceKey = 32;
|
|
139
|
+
|
|
140
|
+
if (event.keyCode === enterKey || event.keyCode === spaceKey) {
|
|
141
|
+
const eventWithKey: EventWithColumnKey = { ...event, sortedKey: dataKey };
|
|
142
|
+
onSort(eventWithKey);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const handleSort = (event: MouseEvent<HTMLTableHeaderCellElement>): void => {
|
|
147
|
+
if (!onSort || !isSortable) return;
|
|
148
|
+
|
|
149
|
+
const eventWithKey: EventWithColumnKey = { ...event, sortedKey: dataKey };
|
|
150
|
+
onSort(eventWithKey);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const tableHeaderClasses = classNames(
|
|
154
|
+
styles['table-header-cell'],
|
|
155
|
+
{
|
|
156
|
+
[styles.sortable]: isSortable,
|
|
157
|
+
[styles.compact]: isCompact,
|
|
158
|
+
[styles.truncated]: truncateOverflow,
|
|
159
|
+
[styles.borderless]: isBorderless,
|
|
160
|
+
[styles['sticky-header']]: hasStickyHeader,
|
|
161
|
+
[styles['sticky-column']]: sticky === 'left' || sticky === 'right',
|
|
162
|
+
[styles['sticky-column-left']]: sticky === 'left',
|
|
163
|
+
[styles['sticky-column-right']]: sticky === 'right',
|
|
164
|
+
[styles['align-right']]: align === 'right',
|
|
165
|
+
[styles['align-center']]: align === 'center',
|
|
166
|
+
},
|
|
167
|
+
className
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<Box
|
|
172
|
+
as="th"
|
|
173
|
+
display="table-cell"
|
|
174
|
+
className={tableHeaderClasses}
|
|
175
|
+
width={`${width}px`}
|
|
176
|
+
aria-sort={
|
|
177
|
+
sortedColumn && isColumnSorted(column.dataKey)
|
|
178
|
+
? sortedColumn.sortDirection
|
|
179
|
+
: 'none'
|
|
180
|
+
}
|
|
181
|
+
tabIndex={isSortable ? 0 : undefined}
|
|
182
|
+
onClick={handleSort}
|
|
183
|
+
onKeyDown={handleKeyPress}
|
|
184
|
+
scope="col"
|
|
185
|
+
>
|
|
186
|
+
<div className={styles.heading}>
|
|
187
|
+
{column.heading}
|
|
188
|
+
{isSortable && renderIcon()}
|
|
189
|
+
</div>
|
|
190
|
+
</Box>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { TableRow } from './TableRow';
|
|
4
|
+
|
|
5
|
+
const row = { id: 1, flavor: 'vanilla' };
|
|
6
|
+
const rowIndex = 1;
|
|
7
|
+
const columns = [
|
|
8
|
+
{ heading: 'ID', dataKey: 'id' },
|
|
9
|
+
{ heading: 'Flavor', dataKey: 'flavor' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
describe('TableRow', () => {
|
|
13
|
+
describe('States', () => {
|
|
14
|
+
test('It renders with a custom class is passed as prop', () => {
|
|
15
|
+
render(
|
|
16
|
+
<TableRow
|
|
17
|
+
row={row}
|
|
18
|
+
rowIndex={rowIndex}
|
|
19
|
+
columns={columns}
|
|
20
|
+
className="my-custom-class"
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const tableRow = screen.getByRole('row');
|
|
25
|
+
expect(tableRow).toHaveClass('my-custom-class');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('It renders with a custom cell class (function) is passed as prop', () => {
|
|
29
|
+
const func = jest.fn().mockReturnValue('my-custom-class');
|
|
30
|
+
const customClassCell = [
|
|
31
|
+
{ heading: 'ID', dataKey: 'id', cellClassName: func },
|
|
32
|
+
];
|
|
33
|
+
render(
|
|
34
|
+
<TableRow row={row} rowIndex={rowIndex} columns={customClassCell} />
|
|
35
|
+
);
|
|
36
|
+
expect(func).toHaveBeenCalledWith(customClassCell[0], row, rowIndex);
|
|
37
|
+
const element = document.getElementsByClassName('my-custom-class')[0];
|
|
38
|
+
expect(element).toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('It renders with a custom cell class (string) is passed as prop', () => {
|
|
42
|
+
const customClassCell = [
|
|
43
|
+
{ heading: 'ID', dataKey: 'id', cellClassName: 'string-class' },
|
|
44
|
+
];
|
|
45
|
+
render(
|
|
46
|
+
<TableRow row={row} rowIndex={rowIndex} columns={customClassCell} />
|
|
47
|
+
);
|
|
48
|
+
const element = document.getElementsByClassName('string-class')[0];
|
|
49
|
+
expect(element).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import React, { FC, ReactNode } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './TableRow.module.scss';
|
|
4
|
+
import { Column, EventWithColumnKey, Row } from '../../../../types';
|
|
5
|
+
import { getColumnKeys } from '../../../../lib/getColumnKeys';
|
|
6
|
+
import TableBodyCell from '../../TableBody/TableBodyCell/TableBodyCell';
|
|
7
|
+
import { TableHeaderCell } from '../../TableHead/TableHeaderCell/TableHeaderCell';
|
|
8
|
+
|
|
9
|
+
export interface TableRowProps {
|
|
10
|
+
/**
|
|
11
|
+
* The table columns to be rendered
|
|
12
|
+
*/
|
|
13
|
+
columns: Column[];
|
|
14
|
+
/**
|
|
15
|
+
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
16
|
+
* for a specific column.
|
|
17
|
+
*/
|
|
18
|
+
align?: 'left' | 'right' | 'center';
|
|
19
|
+
/**
|
|
20
|
+
* Custom class to be applied to `<tr>` element.
|
|
21
|
+
*/
|
|
22
|
+
className?: string;
|
|
23
|
+
/**
|
|
24
|
+
* A global placeholder for empty cells. Note: can be overwriten by
|
|
25
|
+
* the same attribute passed for an individual column config object.
|
|
26
|
+
*/
|
|
27
|
+
emptyCellPlaceholder?: string | number | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* Whether the table has borders or not.
|
|
30
|
+
*/
|
|
31
|
+
isBorderless?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the table rows have smaller padding
|
|
34
|
+
*/
|
|
35
|
+
isCompact?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* If table scrolls vertically, header will remain stuck to the top of the table, and not scroll away.
|
|
38
|
+
*/
|
|
39
|
+
hasStickyHeader?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Determine whether row is hoverable
|
|
42
|
+
*/
|
|
43
|
+
isHoverable?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether the row is inside the table head (thead).
|
|
46
|
+
*/
|
|
47
|
+
isTableHead?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Callback function to fire on sorting one of the table headers.
|
|
50
|
+
*/
|
|
51
|
+
onSort?: (event: EventWithColumnKey) => void;
|
|
52
|
+
/**
|
|
53
|
+
* The specific row to be rendered.
|
|
54
|
+
*/
|
|
55
|
+
row?: Row;
|
|
56
|
+
/**
|
|
57
|
+
* The unique key to identify a React node for each row.
|
|
58
|
+
*/
|
|
59
|
+
rowIndex?: number;
|
|
60
|
+
/**
|
|
61
|
+
* The key of the sorted column and its sort direction.
|
|
62
|
+
*/
|
|
63
|
+
sortedColumn?: {
|
|
64
|
+
dataKey: string | undefined;
|
|
65
|
+
sortDirection: 'none' | 'ascending' | 'descending' | undefined;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Truncate overflow inside column based on column width. Can be overwritten on specific columns,
|
|
69
|
+
* by passing `truncateOverflow` value on a specific Column
|
|
70
|
+
*/
|
|
71
|
+
truncateOverflow?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const TableRow: FC<TableRowProps> = ({
|
|
75
|
+
columns,
|
|
76
|
+
align = 'left',
|
|
77
|
+
className = '',
|
|
78
|
+
emptyCellPlaceholder = '',
|
|
79
|
+
isBorderless = false,
|
|
80
|
+
isCompact = false,
|
|
81
|
+
hasStickyHeader = false,
|
|
82
|
+
isHoverable = false,
|
|
83
|
+
isTableHead = false,
|
|
84
|
+
onSort = undefined,
|
|
85
|
+
sortedColumn = undefined,
|
|
86
|
+
row = undefined,
|
|
87
|
+
rowIndex = undefined,
|
|
88
|
+
truncateOverflow = false,
|
|
89
|
+
}) => {
|
|
90
|
+
const tableRowClasses = classNames(
|
|
91
|
+
styles['table-row'],
|
|
92
|
+
{ [styles.hoverable]: isHoverable },
|
|
93
|
+
className
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const renderCellContent = (column: Column): ReactNode => {
|
|
97
|
+
if (column.render) {
|
|
98
|
+
const cellValue = column.dataKey && row ? row[column.dataKey] : undefined;
|
|
99
|
+
return column.render(cellValue, row, rowIndex);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return column.dataKey && row ? row[column.dataKey] : null;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const getCellClassName = (column: Column): string | undefined => {
|
|
106
|
+
if (column.cellClassName) {
|
|
107
|
+
if (typeof column.cellClassName === 'function') {
|
|
108
|
+
return column.cellClassName(column, row, rowIndex);
|
|
109
|
+
}
|
|
110
|
+
return column.cellClassName;
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<tr className={tableRowClasses}>
|
|
117
|
+
{Object.values(columns).map((column, columnIndex) =>
|
|
118
|
+
isTableHead ? (
|
|
119
|
+
<TableHeaderCell
|
|
120
|
+
column={column}
|
|
121
|
+
align={column.align || align}
|
|
122
|
+
key={getColumnKeys(columns)[columnIndex]}
|
|
123
|
+
dataKey={column.dataKey}
|
|
124
|
+
className={column.headerClassName}
|
|
125
|
+
isSortable={column.isSortable}
|
|
126
|
+
onSort={onSort}
|
|
127
|
+
isBorderless={isBorderless}
|
|
128
|
+
isCompact={isCompact}
|
|
129
|
+
sortedColumn={sortedColumn}
|
|
130
|
+
truncateOverflow={column.truncateOverflow || truncateOverflow}
|
|
131
|
+
width={column.width}
|
|
132
|
+
hasStickyHeader={hasStickyHeader}
|
|
133
|
+
sticky={column.sticky}
|
|
134
|
+
/>
|
|
135
|
+
) : (
|
|
136
|
+
<TableBodyCell
|
|
137
|
+
align={column.align || align}
|
|
138
|
+
className={getCellClassName(column)}
|
|
139
|
+
emptyCellPlaceholder={
|
|
140
|
+
column.emptyCellPlaceholder || emptyCellPlaceholder
|
|
141
|
+
}
|
|
142
|
+
truncateOverflow={column.truncateOverflow || truncateOverflow}
|
|
143
|
+
key={getColumnKeys(columns)[columnIndex]}
|
|
144
|
+
isBorderless={isBorderless}
|
|
145
|
+
isCompact={isCompact}
|
|
146
|
+
width={column.width}
|
|
147
|
+
sticky={column.sticky}
|
|
148
|
+
>
|
|
149
|
+
{renderCellContent(column)}
|
|
150
|
+
</TableBodyCell>
|
|
151
|
+
)
|
|
152
|
+
)}
|
|
153
|
+
</tr>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Canvas, Meta, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import { TextInput } from './TextInput';
|
|
3
|
+
import * as Stories from './TextInput.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={Stories} />
|
|
6
|
+
|
|
7
|
+
# TextInput
|
|
8
|
+
|
|
9
|
+
Use TextInput to render a single-line text input. Masks can also be applied to custom format the input; currently supported masks include Credit Card and Phone.
|
|
10
|
+
|
|
11
|
+
<Canvas isExpanded of={Stories.Basic} />
|
|
12
|
+
|
|
13
|
+
## Props
|
|
14
|
+
|
|
15
|
+
<ArgTypes of={TextInput} />
|
|
16
|
+
|
|
17
|
+
## Examples
|
|
18
|
+
|
|
19
|
+
All that is required to render a basic version of the TextInput is a unique `id`, `label`, `value`, and an onchange event handler passed to the `onChange` prop.
|
|
20
|
+
|
|
21
|
+
<Canvas of={Stories.Examples} />
|
|
22
|
+
|
|
23
|
+
## Required
|
|
24
|
+
|
|
25
|
+
Use the `isRequired` prop to set the `required` and `aria-required` on the underlying input element.
|
|
26
|
+
|
|
27
|
+
<Canvas of={Stories.Required} />
|
|
28
|
+
|
|
29
|
+
You can remove or customize the required indicator using the `requiredIndicator` prop.
|
|
30
|
+
|
|
31
|
+
<Canvas of={Stories.CustomRequiredIndicator} />
|
|
32
|
+
|
|
33
|
+
## With Help Text
|
|
34
|
+
|
|
35
|
+
Use the `helpText` prop to add clarifying text beneath the input label.
|
|
36
|
+
|
|
37
|
+
<Canvas of={Stories.WithHelpText} />
|
|
38
|
+
|
|
39
|
+
## Placeholder
|
|
40
|
+
|
|
41
|
+
Use the `placeholder` prop to add a custom placeholder.
|
|
42
|
+
|
|
43
|
+
<Canvas of={Stories.Placeholder} />
|
|
44
|
+
|
|
45
|
+
## Autofocus
|
|
46
|
+
|
|
47
|
+
Use the `autoFocus` prop to autofocus the input.
|
|
48
|
+
|
|
49
|
+
<Canvas of={Stories.Autofocus} />
|
|
50
|
+
|
|
51
|
+
## Hidden Label
|
|
52
|
+
|
|
53
|
+
Use the `hideLabel` prop to not render the label.
|
|
54
|
+
|
|
55
|
+
<Canvas of={Stories.HiddenLabel} />
|
|
56
|
+
|
|
57
|
+
## Prefix and Suffix
|
|
58
|
+
|
|
59
|
+
All that is required to render a basic version of the TextInput is a unique `id`, `label`, `value`, and an onchange event handler passed to the `onChange` prop.
|
|
60
|
+
|
|
61
|
+
<Canvas of={Stories.PrefixAndSuffix} />
|
|
62
|
+
|
|
63
|
+
## Disabled
|
|
64
|
+
|
|
65
|
+
Use the `isDisabled` prop to mark the input as disabled.
|
|
66
|
+
|
|
67
|
+
<Canvas of={Stories.Disabled} />
|
|
68
|
+
|
|
69
|
+
## Clearable
|
|
70
|
+
|
|
71
|
+
Use the `onClear` prop to display a clear icon (x) when the input has a value. `onClear` will fire
|
|
72
|
+
a callback function when the clear icon is clicked, which can then be handled to clear the value.
|
|
73
|
+
|
|
74
|
+
<Canvas of={Stories.Clearable} />
|
|
75
|
+
|
|
76
|
+
## Sizes
|
|
77
|
+
|
|
78
|
+
Set the `size` of the input to `sm`, `md` or `lg`. The `size` prop is also a `ResponsiveProp`, so it can be sized differently at each [breakpoint](?path=/docs/design-tokens-design-tokens--page#breakpoints) by passing an object.
|
|
79
|
+
|
|
80
|
+
<Canvas of={Stories.Sizes} />
|
|
81
|
+
|
|
82
|
+
## Max Length
|
|
83
|
+
|
|
84
|
+
Use the `maxLength` prop to limit the number of characters that can be entered into an input.
|
|
85
|
+
|
|
86
|
+
<Canvas of={Stories.MaxLength} />
|
|
87
|
+
|
|
88
|
+
## Validation Error
|
|
89
|
+
|
|
90
|
+
Use the `error` prop to mark the input as invalid. `error` accepts a `boolean`, `string`, or `node`.
|
|
91
|
+
|
|
92
|
+
<Canvas of={Stories.ValidationError} />
|
|
93
|
+
|
|
94
|
+
## Component Design Tokens
|
|
95
|
+
|
|
96
|
+
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).
|