@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,96 @@
|
|
|
1
|
+
import React, { FC, Key } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './TableBody.module.scss';
|
|
4
|
+
import { Column, Row } from '../../../types';
|
|
5
|
+
import { TableRow } from '../common/TableRow/TableRow';
|
|
6
|
+
|
|
7
|
+
export interface TableBodyProps {
|
|
8
|
+
/**
|
|
9
|
+
* The table columns to be rendered
|
|
10
|
+
*/
|
|
11
|
+
columns: Column[];
|
|
12
|
+
/**
|
|
13
|
+
* The unique key to identify a React node for each row.
|
|
14
|
+
*/
|
|
15
|
+
rowKey: Key;
|
|
16
|
+
/**
|
|
17
|
+
* The table rows to be rendered
|
|
18
|
+
*/
|
|
19
|
+
rows: Row[];
|
|
20
|
+
/**
|
|
21
|
+
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
22
|
+
* for a specific column.
|
|
23
|
+
*/
|
|
24
|
+
align?: 'left' | 'right' | 'center';
|
|
25
|
+
/**
|
|
26
|
+
* A custom class to apply to the table body.
|
|
27
|
+
*/
|
|
28
|
+
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* A global placeholder for empty cells. Note: can be overwriten by
|
|
31
|
+
* the same attribute passed for an individual column config object.
|
|
32
|
+
*/
|
|
33
|
+
emptyCellPlaceholder?: string | number | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Enable a hover state on table rows.
|
|
36
|
+
*/
|
|
37
|
+
hoverableRows?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the table has borders or not.
|
|
40
|
+
*/
|
|
41
|
+
isBorderless?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the table rows have smaller padding
|
|
44
|
+
*/
|
|
45
|
+
isCompact?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the table rows have a striped pattern
|
|
48
|
+
*/
|
|
49
|
+
isStriped?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Truncate overflow inside column based on column width. Can be overwritten on specific columns,
|
|
52
|
+
* by passing `truncateOverflow` value on a specific Column
|
|
53
|
+
*/
|
|
54
|
+
truncateOverflow?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const TableBody: FC<TableBodyProps> = ({
|
|
58
|
+
columns,
|
|
59
|
+
rowKey,
|
|
60
|
+
rows,
|
|
61
|
+
align = 'left',
|
|
62
|
+
className = '',
|
|
63
|
+
emptyCellPlaceholder = '',
|
|
64
|
+
hoverableRows = false,
|
|
65
|
+
isBorderless = false,
|
|
66
|
+
isCompact = false,
|
|
67
|
+
isStriped = false,
|
|
68
|
+
truncateOverflow = false,
|
|
69
|
+
}) => {
|
|
70
|
+
const tableBodyClasses = classNames(
|
|
71
|
+
styles['table-body'],
|
|
72
|
+
{
|
|
73
|
+
[styles.striped]: isStriped,
|
|
74
|
+
[styles.hover]: hoverableRows,
|
|
75
|
+
},
|
|
76
|
+
className
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<tbody className={tableBodyClasses}>
|
|
81
|
+
{rows.map((row, rowIndex) => (
|
|
82
|
+
<TableRow
|
|
83
|
+
columns={columns}
|
|
84
|
+
row={row}
|
|
85
|
+
rowIndex={rowIndex}
|
|
86
|
+
align={align}
|
|
87
|
+
key={row[rowKey as any]}
|
|
88
|
+
emptyCellPlaceholder={emptyCellPlaceholder}
|
|
89
|
+
truncateOverflow={truncateOverflow}
|
|
90
|
+
isBorderless={isBorderless}
|
|
91
|
+
isCompact={isCompact}
|
|
92
|
+
/>
|
|
93
|
+
))}
|
|
94
|
+
</tbody>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.table-cell {
|
|
2
|
+
border-color: var(--color-border-default);
|
|
3
|
+
border-bottom-style: solid;
|
|
4
|
+
border-width: 0 0 var(--size-border-width-sm) 0;
|
|
5
|
+
color: var(--color-font-base);
|
|
6
|
+
padding: var(--size-spacing-md) var(--size-spacing-lg);
|
|
7
|
+
|
|
8
|
+
&.borderless {
|
|
9
|
+
border-width: 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
&.compact {
|
|
13
|
+
padding: var(--size-spacing-sm) var(--size-spacing-md);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.truncated {
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
text-overflow: ellipsis;
|
|
19
|
+
white-space: nowrap;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.sticky-column-left {
|
|
23
|
+
background-color: var(--color-background-primary);
|
|
24
|
+
left: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&.sticky-column-right {
|
|
28
|
+
background-color: var(--color-background-primary);
|
|
29
|
+
right: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&.sticky-column {
|
|
33
|
+
position: sticky;
|
|
34
|
+
z-index: calc(var(--size-z-index-sticky) - 1);
|
|
35
|
+
background-color: var(--color-background-primary);
|
|
36
|
+
box-shadow: 5px 0 5px -2px rgb(0 0 0 / 10%),
|
|
37
|
+
-5px 0 5px -2px rgb(0 0 0 / 10%);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&.align-right {
|
|
41
|
+
text-align: right;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&.align-center {
|
|
45
|
+
text-align: center;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import TableCell from './TableBodyCell';
|
|
4
|
+
|
|
5
|
+
describe('TableCell', () => {
|
|
6
|
+
describe('States', () => {
|
|
7
|
+
test('It renders an empty td when no children passed', () => {
|
|
8
|
+
render(<TableCell />);
|
|
9
|
+
|
|
10
|
+
const tableCell = screen.getByRole('cell');
|
|
11
|
+
expect(tableCell).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('td element is rendered with specific width style attribute based on width prop', () => {
|
|
15
|
+
render(<TableCell width={200}>ID</TableCell>);
|
|
16
|
+
|
|
17
|
+
const tableCell = screen.getByText('ID');
|
|
18
|
+
|
|
19
|
+
expect(tableCell).toHaveStyle({ minWidth: '200px', maxWidth: '200px' });
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("td content is truncated if 'isTruncated' prop is passed", () => {
|
|
23
|
+
render(
|
|
24
|
+
<TableCell width={50} truncateOverflow>
|
|
25
|
+
Lots of long long long content
|
|
26
|
+
</TableCell>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const tableCellWithEllipsis = screen.getByRole('cell');
|
|
30
|
+
|
|
31
|
+
expect(tableCellWithEllipsis).toHaveClass('truncated');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("td is borderless if 'isBorderless' prop is passed", () => {
|
|
35
|
+
render(<TableCell isBorderless>ID</TableCell>);
|
|
36
|
+
|
|
37
|
+
const tableCellWithEllipsis = screen.getByRole('cell');
|
|
38
|
+
|
|
39
|
+
expect(tableCellWithEllipsis).toHaveClass('borderless');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test("td is compact if 'isCompact' prop is passed", () => {
|
|
43
|
+
render(<TableCell isCompact>ID</TableCell>);
|
|
44
|
+
|
|
45
|
+
const tableCellWithEllipsis = screen.getByRole('cell');
|
|
46
|
+
|
|
47
|
+
expect(tableCellWithEllipsis).toHaveClass('compact');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('It renders with a custom class is passed as prop', () => {
|
|
51
|
+
render(<TableCell className="my-custom-class" />);
|
|
52
|
+
|
|
53
|
+
const tableCell = screen.getByRole('cell');
|
|
54
|
+
expect(tableCell).toHaveClass('my-custom-class');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('Sticky', () => {
|
|
58
|
+
test('it renders as a <th> element if sticky is passed as a prop with "left" as its value', () => {
|
|
59
|
+
render(<TableCell sticky="left" />);
|
|
60
|
+
|
|
61
|
+
const tableRowHeader = screen.getByRole('rowheader');
|
|
62
|
+
|
|
63
|
+
expect(tableRowHeader).toBeInTheDocument();
|
|
64
|
+
expect(tableRowHeader).toHaveAttribute('scope', 'row');
|
|
65
|
+
expect(tableRowHeader).toHaveClass('sticky-column');
|
|
66
|
+
expect(tableRowHeader).toHaveClass('sticky-column-left');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('it renders as a <th> element if sticky is passed as a prop with "right" as its value', () => {
|
|
70
|
+
render(<TableCell sticky="right" />);
|
|
71
|
+
|
|
72
|
+
const tableRowHeader = screen.getByRole('rowheader');
|
|
73
|
+
|
|
74
|
+
expect(tableRowHeader).toBeInTheDocument();
|
|
75
|
+
expect(tableRowHeader).toHaveAttribute('scope', 'row');
|
|
76
|
+
expect(tableRowHeader).toHaveClass('sticky-column');
|
|
77
|
+
expect(tableRowHeader).toHaveClass('sticky-column-right');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { FC, ReactNode } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { Box } from '../../../Box/Box';
|
|
4
|
+
import styles from './TableBodyCell.module.scss';
|
|
5
|
+
|
|
6
|
+
export interface TableBodyCellProps {
|
|
7
|
+
/**
|
|
8
|
+
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
9
|
+
* for a specific column.
|
|
10
|
+
*/
|
|
11
|
+
align?: 'left' | 'right' | 'center';
|
|
12
|
+
/**
|
|
13
|
+
* Children node to be rendered.
|
|
14
|
+
*/
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Custom class to be applied to `<tr>` element.
|
|
18
|
+
*/
|
|
19
|
+
className?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Remove borders around td elements.
|
|
22
|
+
*/
|
|
23
|
+
isBorderless?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Reduces padding inside table cells.
|
|
26
|
+
*/
|
|
27
|
+
isCompact?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Will stick to either the left or right side of a table during horizontal scroll.
|
|
30
|
+
*/
|
|
31
|
+
sticky?: 'left' | 'right';
|
|
32
|
+
/**
|
|
33
|
+
* Truncates the cell contents based on width established by `Column`
|
|
34
|
+
* NOTE: Truncate only on cells with primitive data types.
|
|
35
|
+
*/
|
|
36
|
+
truncateOverflow?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Placeholder for an empty cell, will be rendered when content is `null` `undefined`
|
|
39
|
+
* or `''`. Placeholders will not be rendered on values of `0`.
|
|
40
|
+
*/
|
|
41
|
+
emptyCellPlaceholder?: ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Fixed width for a particular cell.
|
|
44
|
+
* Value should be taken from column config so it matches its parent.
|
|
45
|
+
*/
|
|
46
|
+
width?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const TableBodyCell: FC<TableBodyCellProps> = ({
|
|
50
|
+
align = 'left',
|
|
51
|
+
children = null,
|
|
52
|
+
className = '',
|
|
53
|
+
emptyCellPlaceholder = null,
|
|
54
|
+
isBorderless = false,
|
|
55
|
+
isCompact = false,
|
|
56
|
+
sticky = undefined,
|
|
57
|
+
truncateOverflow = false,
|
|
58
|
+
width = undefined,
|
|
59
|
+
}) => {
|
|
60
|
+
const columnIsSticky = sticky === 'left' || sticky === 'right';
|
|
61
|
+
const tableCellClasses = classNames(
|
|
62
|
+
styles['table-cell'],
|
|
63
|
+
{
|
|
64
|
+
[styles.truncated]: truncateOverflow,
|
|
65
|
+
[styles.compact]: isCompact,
|
|
66
|
+
[styles.borderless]: isBorderless,
|
|
67
|
+
[styles['sticky-column']]: columnIsSticky,
|
|
68
|
+
[styles['sticky-column-left']]: sticky === 'left',
|
|
69
|
+
[styles['sticky-column-right']]: sticky === 'right',
|
|
70
|
+
[styles['align-right']]: align === 'right',
|
|
71
|
+
[styles['align-center']]: align === 'center',
|
|
72
|
+
},
|
|
73
|
+
className
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Box
|
|
78
|
+
as={columnIsSticky ? 'th' : 'td'}
|
|
79
|
+
className={tableCellClasses}
|
|
80
|
+
display="table-cell"
|
|
81
|
+
width={`${width}px`}
|
|
82
|
+
style={{
|
|
83
|
+
...(width && { minWidth: `${width}px`, maxWidth: `${width}px` }),
|
|
84
|
+
}}
|
|
85
|
+
scope="row"
|
|
86
|
+
>
|
|
87
|
+
{children === null || typeof children === 'undefined' || children === ''
|
|
88
|
+
? emptyCellPlaceholder
|
|
89
|
+
: children}
|
|
90
|
+
</Box>
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export default TableBodyCell;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { TableHead } from './TableHead';
|
|
4
|
+
|
|
5
|
+
const columns = [
|
|
6
|
+
{ heading: 'ID', dataKey: 'id' },
|
|
7
|
+
{ heading: 'Color', dataKey: 'color' },
|
|
8
|
+
{ heading: 'Flavor', dataKey: 'flavor' },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
describe('TableHead', () => {
|
|
12
|
+
describe('States', () => {
|
|
13
|
+
test('it renders an empty thead element if no children are passed', () => {
|
|
14
|
+
render(<TableHead columns={columns} />);
|
|
15
|
+
|
|
16
|
+
const tableHead = screen.getByRole('rowgroup');
|
|
17
|
+
expect(tableHead).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { Column, EventWithColumnKey } from '../../../types';
|
|
4
|
+
import { TableRow } from '../common/TableRow/TableRow';
|
|
5
|
+
|
|
6
|
+
export interface TableHeadProps {
|
|
7
|
+
/**
|
|
8
|
+
* The table columns to be rendered
|
|
9
|
+
*/
|
|
10
|
+
columns: Column[];
|
|
11
|
+
/**
|
|
12
|
+
* Text alignment for all table cells. Can be superseded by passing the same prop into the `Column` object
|
|
13
|
+
* for a specific column.
|
|
14
|
+
*/
|
|
15
|
+
align?: 'left' | 'right' | 'center';
|
|
16
|
+
/**
|
|
17
|
+
* Custom class to be applied to the `<thead>` element.
|
|
18
|
+
*/
|
|
19
|
+
className?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Whether the table has borders or not.
|
|
22
|
+
*/
|
|
23
|
+
isBorderless?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the table rows have smaller padding
|
|
26
|
+
*/
|
|
27
|
+
isCompact?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* If table scrolls vertically, header will remain stuck to the top of the table, and not scroll away.
|
|
30
|
+
*/
|
|
31
|
+
hasStickyHeader?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Callback function to fire on sorting one of the table headers.
|
|
34
|
+
*/
|
|
35
|
+
onSort?: (event: EventWithColumnKey) => void;
|
|
36
|
+
/**
|
|
37
|
+
* The key of the sorted column and its sort direction.
|
|
38
|
+
*/
|
|
39
|
+
sortedColumn?: {
|
|
40
|
+
dataKey: string | undefined;
|
|
41
|
+
sortDirection: 'none' | 'ascending' | 'descending' | undefined;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Truncate overflow inside column based on column width. Can be overwritten on specific columns,
|
|
45
|
+
* by passing `truncateOverflow` value on a specific Column
|
|
46
|
+
*/
|
|
47
|
+
truncateOverflow?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const TableHead: FC<TableHeadProps> = ({
|
|
51
|
+
columns,
|
|
52
|
+
align = 'left',
|
|
53
|
+
className = '',
|
|
54
|
+
isBorderless = false,
|
|
55
|
+
isCompact = false,
|
|
56
|
+
hasStickyHeader = false,
|
|
57
|
+
onSort = undefined,
|
|
58
|
+
sortedColumn = undefined,
|
|
59
|
+
truncateOverflow = false,
|
|
60
|
+
}) => {
|
|
61
|
+
const tableHeadClasses = classNames(className);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<thead className={tableHeadClasses}>
|
|
65
|
+
<TableRow
|
|
66
|
+
columns={columns}
|
|
67
|
+
align={align}
|
|
68
|
+
isTableHead
|
|
69
|
+
isBorderless={isBorderless}
|
|
70
|
+
isCompact={isCompact}
|
|
71
|
+
onSort={onSort}
|
|
72
|
+
sortedColumn={sortedColumn}
|
|
73
|
+
truncateOverflow={truncateOverflow}
|
|
74
|
+
hasStickyHeader={hasStickyHeader}
|
|
75
|
+
/>
|
|
76
|
+
</thead>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
.table-header-cell {
|
|
2
|
+
text-align: left;
|
|
3
|
+
text-transform: uppercase;
|
|
4
|
+
letter-spacing: 0.05em;
|
|
5
|
+
white-space: nowrap;
|
|
6
|
+
border-color: var(--color-border-default);
|
|
7
|
+
border-bottom-style: solid;
|
|
8
|
+
border-width: 0 0 var(--size-border-width-sm) 0;
|
|
9
|
+
background-color: var(--color-background-primary);
|
|
10
|
+
color: var(--color-font-primary);
|
|
11
|
+
font-size: var(--size-font-size-sm);
|
|
12
|
+
font-weight: var(--size-font-weight-bold);
|
|
13
|
+
padding: var(--size-spacing-md)
|
|
14
|
+
var(--size-spacing-lg);
|
|
15
|
+
|
|
16
|
+
&.sortable {
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
&.borderless {
|
|
21
|
+
border-width: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
&.truncated {
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
text-overflow: ellipsis;
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.compact {
|
|
31
|
+
padding: var(--size-spacing-sm) var(--size-spacing-md);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&.sticky-header {
|
|
35
|
+
position: sticky;
|
|
36
|
+
top: 0;
|
|
37
|
+
z-index: var(--size-z-index-sticky);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
&.sticky-column-left {
|
|
42
|
+
left: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&.sticky-column-right {
|
|
46
|
+
right: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.sticky-column {
|
|
50
|
+
position: sticky;
|
|
51
|
+
z-index: calc(var(--size-z-index-sticky) + 1);
|
|
52
|
+
box-shadow: 5px 0 5px -2px rgb(0 0 0 / 10%), -5px 0 5px -2px rgb(0 0 0 / 10%);
|
|
53
|
+
background-color: var(--color-background-primary);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
&.align-right {
|
|
58
|
+
text-align: right;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&.align-center {
|
|
62
|
+
text-align: center;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.heading {
|
|
66
|
+
white-space: nowrap;
|
|
67
|
+
|
|
68
|
+
.sort-icon {
|
|
69
|
+
margin-left: var(--size-spacing-xs);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import { TableHeaderCell } from './TableHeaderCell';
|
|
4
|
+
|
|
5
|
+
const column = {
|
|
6
|
+
heading: 'ID',
|
|
7
|
+
dataKey: 'id',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const sortedColumn = (
|
|
11
|
+
direction: 'none' | 'ascending' | 'descending' | undefined
|
|
12
|
+
) => ({
|
|
13
|
+
dataKey: 'id',
|
|
14
|
+
sortDirection: direction,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('TableHeaderCell', () => {
|
|
18
|
+
describe('Callback Handling', () => {
|
|
19
|
+
describe('onSort', () => {
|
|
20
|
+
test('onSort event fires callback function on click', () => {
|
|
21
|
+
const mockHandleSort = jest.fn();
|
|
22
|
+
render(
|
|
23
|
+
<TableHeaderCell column={column} onSort={mockHandleSort} isSortable />
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
27
|
+
|
|
28
|
+
fireEvent.click(tableHeaderCell);
|
|
29
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('onSort event fires callback function on Enter keydown', () => {
|
|
33
|
+
const mockHandleSort = jest.fn();
|
|
34
|
+
render(
|
|
35
|
+
<TableHeaderCell column={column} isSortable onSort={mockHandleSort} />
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
39
|
+
|
|
40
|
+
fireEvent.keyDown(tableHeaderCell, { keyCode: 13 });
|
|
41
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('onSort event fires callback function on Space keydown', () => {
|
|
45
|
+
const mockHandleSort = jest.fn();
|
|
46
|
+
render(
|
|
47
|
+
<TableHeaderCell column={column} isSortable onSort={mockHandleSort} />
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
51
|
+
|
|
52
|
+
fireEvent.keyDown(tableHeaderCell, { keyCode: 32 });
|
|
53
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(1);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('onSort does NOT fire callback function on keydown that is not ENTER or SPACE', () => {
|
|
57
|
+
const mockHandleSort = jest.fn();
|
|
58
|
+
render(
|
|
59
|
+
<TableHeaderCell column={column} isSortable onSort={mockHandleSort} />
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
63
|
+
|
|
64
|
+
fireEvent.keyDown(tableHeaderCell, { keyCode: 77 });
|
|
65
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('onSort does NOT fire callback when keyed unless both onSort and isSortable props are provided', () => {
|
|
69
|
+
const mockHandleSort = jest.fn();
|
|
70
|
+
render(<TableHeaderCell column={column} onSort={mockHandleSort} />);
|
|
71
|
+
|
|
72
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
73
|
+
|
|
74
|
+
fireEvent.keyDown(tableHeaderCell, { keyCode: 32 });
|
|
75
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(0);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('onSort does NOT fire callback when clicked unless both onSort and isSortable props are provided', () => {
|
|
80
|
+
const mockHandleSort = jest.fn();
|
|
81
|
+
render(<TableHeaderCell column={column} onSort={mockHandleSort} />);
|
|
82
|
+
|
|
83
|
+
const tableHeaderCell = screen.getByText('ID');
|
|
84
|
+
|
|
85
|
+
fireEvent.click(tableHeaderCell);
|
|
86
|
+
expect(mockHandleSort).toHaveBeenCalledTimes(0);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('States', () => {
|
|
91
|
+
test("It renders the header with sort icon and default sortDirection if 'isSortable' is passed", () => {
|
|
92
|
+
render(<TableHeaderCell column={column} isSortable />);
|
|
93
|
+
|
|
94
|
+
const tableHeaderCell = screen.getByRole('columnheader');
|
|
95
|
+
|
|
96
|
+
expect(tableHeaderCell).toHaveAttribute('aria-sort', 'none');
|
|
97
|
+
expect(
|
|
98
|
+
screen.getByTestId('tableHeaderCellSortNone-testid')
|
|
99
|
+
).toBeInTheDocument();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('It renders the header with sort icon and proper sortDirection', () => {
|
|
103
|
+
const { rerender } = render(
|
|
104
|
+
<TableHeaderCell
|
|
105
|
+
column={column}
|
|
106
|
+
isSortable
|
|
107
|
+
sortedColumn={sortedColumn('none')}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const tableHeaderCell = screen.getByRole('columnheader');
|
|
112
|
+
|
|
113
|
+
expect(tableHeaderCell).toHaveAttribute('aria-sort', 'none');
|
|
114
|
+
expect(
|
|
115
|
+
screen.getByTestId('tableHeaderCellSortNone-testid')
|
|
116
|
+
).toBeInTheDocument();
|
|
117
|
+
|
|
118
|
+
rerender(
|
|
119
|
+
<TableHeaderCell
|
|
120
|
+
column={column}
|
|
121
|
+
isSortable
|
|
122
|
+
sortedColumn={sortedColumn('ascending')}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
expect(tableHeaderCell).toHaveAttribute('aria-sort', 'ascending');
|
|
127
|
+
expect(
|
|
128
|
+
screen.getByTestId('tableHeaderCellSortAsc-testid')
|
|
129
|
+
).toBeInTheDocument();
|
|
130
|
+
|
|
131
|
+
rerender(
|
|
132
|
+
<TableHeaderCell
|
|
133
|
+
column={column}
|
|
134
|
+
isSortable
|
|
135
|
+
sortedColumn={sortedColumn('descending')}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(tableHeaderCell).toHaveAttribute('aria-sort', 'descending');
|
|
140
|
+
expect(
|
|
141
|
+
screen.getByTestId('tableHeaderCellSortDesc-testid')
|
|
142
|
+
).toBeInTheDocument();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('th element is rendered with specific width style attribute based on width prop', () => {
|
|
146
|
+
render(<TableHeaderCell column={column} width={200} />);
|
|
147
|
+
|
|
148
|
+
const tableHeaderCell = screen.getByText('ID').closest('th');
|
|
149
|
+
|
|
150
|
+
expect(tableHeaderCell).toHaveStyle({ width: '200px' });
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('th element is rendered with custom class when passed as a prop', () => {
|
|
154
|
+
render(<TableHeaderCell column={column} className="my-custom-class" />);
|
|
155
|
+
|
|
156
|
+
const tableHeaderCell = screen.getByRole('columnheader');
|
|
157
|
+
|
|
158
|
+
expect(tableHeaderCell).toHaveClass('my-custom-class');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe('Sticky', () => {
|
|
162
|
+
test('it renders as a <th> element with correct classes and attributes if sticky is passed as a prop with "left" as its value', () => {
|
|
163
|
+
// eslint-disable-line max-len
|
|
164
|
+
render(<TableHeaderCell column={column} sticky="left" />);
|
|
165
|
+
|
|
166
|
+
const tableColumnHeader = screen.getByRole('columnheader');
|
|
167
|
+
|
|
168
|
+
expect(tableColumnHeader).toBeInTheDocument();
|
|
169
|
+
expect(tableColumnHeader).toHaveAttribute('scope', 'col');
|
|
170
|
+
expect(tableColumnHeader).toHaveClass('sticky-column');
|
|
171
|
+
expect(tableColumnHeader).toHaveClass('sticky-column-left');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test('it renders as a <th> element with correct classes and attributes if sticky is passed as a prop with "right" as its value', () => {
|
|
175
|
+
// eslint-disable-line max-len
|
|
176
|
+
render(<TableHeaderCell column={column} sticky="right" />);
|
|
177
|
+
|
|
178
|
+
const tableColumnHeader = screen.getByRole('columnheader');
|
|
179
|
+
|
|
180
|
+
expect(tableColumnHeader).toBeInTheDocument();
|
|
181
|
+
expect(tableColumnHeader).toHaveAttribute('scope', 'col');
|
|
182
|
+
expect(tableColumnHeader).toHaveClass('sticky-column');
|
|
183
|
+
expect(tableColumnHeader).toHaveClass('sticky-column-right');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|