@react-ui-org/react-ui 0.58.0 → 0.59.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -11
- package/dist/react-ui.css +17 -17
- package/dist/react-ui.development.css +1230 -1053
- package/dist/react-ui.development.js +126 -66
- package/dist/react-ui.js +1 -1
- package/package.json +5 -5
- package/src/components/Alert/Alert.jsx +4 -4
- package/src/components/Alert/README.md +1 -27
- package/src/components/Alert/_settings.scss +1 -2
- package/src/components/Badge/Badge.jsx +2 -2
- package/src/components/Button/Button.jsx +2 -2
- package/src/components/ButtonGroup/ButtonGroup.jsx +2 -2
- package/src/components/Card/Card.jsx +6 -6
- package/src/components/Card/Card.module.scss +2 -2
- package/src/components/Card/CardBody.jsx +1 -1
- package/src/components/Card/CardFooter.jsx +1 -1
- package/src/components/Card/README.md +12 -30
- package/src/components/Card/_settings.scss +1 -2
- package/src/components/Card/_theme.scss +2 -0
- package/src/components/CheckboxField/CheckboxField.jsx +2 -2
- package/src/components/FileInputField/FileInputField.jsx +147 -21
- package/src/components/FileInputField/FileInputField.module.scss +87 -1
- package/src/components/FileInputField/README.md +83 -2
- package/src/components/FileInputField/_settings.scss +15 -0
- package/src/components/FormLayout/FormLayout.jsx +2 -2
- package/src/components/FormLayout/FormLayoutCustomField.jsx +2 -2
- package/src/components/FormLayout/README.md +8 -6
- package/src/components/Grid/Grid.jsx +1 -1
- package/src/components/Grid/Grid.module.scss +2 -2
- package/src/components/Grid/GridSpan.jsx +1 -1
- package/src/components/InputGroup/InputGroup.jsx +2 -2
- package/src/components/InputGroup/InputGroup.module.scss +3 -3
- package/src/components/InputGroup/README.md +1 -1
- package/src/components/Modal/Modal.jsx +117 -45
- package/src/components/Modal/Modal.module.scss +34 -18
- package/src/components/Modal/ModalBody.jsx +2 -2
- package/src/components/Modal/ModalBody.module.scss +18 -0
- package/src/components/Modal/ModalCloseButton.jsx +1 -1
- package/src/components/Modal/ModalContent.jsx +1 -1
- package/src/components/Modal/ModalFooter.jsx +2 -2
- package/src/components/Modal/ModalFooter.module.scss +6 -2
- package/src/components/Modal/ModalHeader.jsx +2 -2
- package/src/components/Modal/ModalHeader.module.scss +8 -1
- package/src/components/Modal/ModalTitle.jsx +1 -1
- package/src/components/Modal/README.md +391 -171
- package/src/components/Modal/_animations.scss +9 -0
- package/src/components/Modal/_helpers/dialogOnCancelHandler.js +28 -0
- package/src/components/Modal/_helpers/dialogOnClickHandler.js +46 -0
- package/src/components/Modal/_helpers/dialogOnCloseHandler.js +28 -0
- package/src/components/Modal/_helpers/dialogOnKeyDownHandler.js +62 -0
- package/src/components/Modal/_helpers/getPositionClassName.js +1 -1
- package/src/components/Modal/_hooks/useModalFocus.js +24 -91
- package/src/components/Modal/_settings.scss +4 -3
- package/src/components/Modal/_theme.scss +1 -0
- package/src/components/Paper/Paper.jsx +2 -2
- package/src/components/Popover/Popover.jsx +2 -2
- package/src/components/Popover/PopoverWrapper.jsx +1 -1
- package/src/components/Radio/Radio.jsx +2 -2
- package/src/components/ScrollView/ScrollView.jsx +2 -2
- package/src/components/SelectField/SelectField.jsx +2 -2
- package/src/components/Table/Table.jsx +1 -1
- package/src/components/Tabs/Tabs.jsx +1 -1
- package/src/components/Tabs/TabsItem.jsx +2 -2
- package/src/components/Text/Text.jsx +2 -2
- package/src/components/TextArea/TextArea.jsx +2 -2
- package/src/components/TextField/TextField.jsx +2 -2
- package/src/components/TextLink/TextLink.jsx +1 -1
- package/src/components/Toggle/Toggle.jsx +2 -2
- package/src/components/Toolbar/Toolbar.jsx +2 -2
- package/src/components/Toolbar/ToolbarGroup.jsx +2 -2
- package/src/components/Toolbar/ToolbarItem.jsx +2 -2
- package/src/helpers/classNames/README.md +65 -0
- package/src/helpers/classNames/classNames.js +11 -0
- package/src/helpers/classNames/index.js +1 -0
- package/src/helpers/transferProps/README.md +46 -0
- package/src/helpers/transferProps/index.js +1 -0
- package/src/index.js +3 -3
- package/src/styles/elements/_links.scss +2 -14
- package/src/styles/generic/_focus.scss +1 -1
- package/src/styles/theme/_form-fields.scss +5 -5
- package/src/styles/tools/_accessibility.scss +3 -5
- package/src/styles/tools/_collections.scss +3 -20
- package/src/styles/tools/_links.scss +17 -0
- package/src/styles/tools/form-fields/_box-field-elements.scss +21 -9
- package/src/styles/tools/form-fields/_box-field-layout.scss +2 -2
- package/src/styles/tools/form-fields/_box-field-sizes.scss +6 -10
- package/src/styles/tools/form-fields/_variants.scss +10 -10
- package/src/theme.scss +53 -3
- package/src/translations/en.js +5 -0
- package/src/styles/settings/_z-indexes.scss +0 -2
- package/src/utils/classNames.js +0 -8
- /package/src/{utils → helpers/transferProps}/transferProps.js +0 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
// Disable coverage for the following function
|
2
|
+
/* istanbul ignore next */
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Handles the click event of the dialog which is fired when the user clicks on the dialog or on its descendants.
|
6
|
+
*
|
7
|
+
* This handler is used to close the dialog when the user clicks on the backdrop, if it is allowed to close
|
8
|
+
* on backdrop click and the close button is not disabled.
|
9
|
+
*
|
10
|
+
* @param e
|
11
|
+
* @param closeButtonRef
|
12
|
+
* @param dialogRef
|
13
|
+
* @param allowCloseOnBackdropClick
|
14
|
+
*/
|
15
|
+
export const dialogOnClickHandler = (
|
16
|
+
e,
|
17
|
+
closeButtonRef,
|
18
|
+
dialogRef,
|
19
|
+
allowCloseOnBackdropClick,
|
20
|
+
) => {
|
21
|
+
// If it is not allowed to close modal on backdrop click, do nothing.
|
22
|
+
if (!allowCloseOnBackdropClick) {
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
|
26
|
+
// Detection of the click on the backdrop is based on the following conditions:
|
27
|
+
// 1. The click target is the dialog itself. This prevents detection of clicks on the dialog's children.
|
28
|
+
// 2. The click is outside the dialog's boundaries.
|
29
|
+
const dialogRect = dialogRef.current.getBoundingClientRect();
|
30
|
+
const isClickedOnBackdrop = dialogRef.current === e.target && (
|
31
|
+
e.clientX < dialogRect.left
|
32
|
+
|| e.clientX > dialogRect.right
|
33
|
+
|| e.clientY < dialogRect.top
|
34
|
+
|| e.clientY > dialogRect.bottom
|
35
|
+
);
|
36
|
+
|
37
|
+
// If user does not click on the backdrop, do nothing.
|
38
|
+
if (!isClickedOnBackdrop) {
|
39
|
+
return;
|
40
|
+
}
|
41
|
+
|
42
|
+
// If the close button is not disabled, close the modal.
|
43
|
+
if (closeButtonRef?.current != null && closeButtonRef?.current?.disabled === false) {
|
44
|
+
closeButtonRef.current.click();
|
45
|
+
}
|
46
|
+
};
|
@@ -0,0 +1,28 @@
|
|
1
|
+
// Disable coverage for the following function
|
2
|
+
/* istanbul ignore next */
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Handles the close event of the dialog which is fired when the user presses the Escape key or triggers close event
|
6
|
+
* by native dialog mechanism.
|
7
|
+
*
|
8
|
+
* It prevents the default behaviour of the native dialog and closes the dialog manually by clicking the close button,
|
9
|
+
* if the close button is not disabled.
|
10
|
+
*
|
11
|
+
* @param e
|
12
|
+
* @param closeButtonRef
|
13
|
+
* @param onCloseHandler
|
14
|
+
*/
|
15
|
+
export const dialogOnCloseHandler = (e, closeButtonRef, onCloseHandler = undefined) => {
|
16
|
+
// Prevent the default behaviour of the event as we want to close dialog manually.
|
17
|
+
e.preventDefault();
|
18
|
+
|
19
|
+
// If the close button is not disabled, close the modal.
|
20
|
+
if (closeButtonRef?.current != null && closeButtonRef?.current?.disabled === false) {
|
21
|
+
closeButtonRef.current.click();
|
22
|
+
}
|
23
|
+
|
24
|
+
// This is a custom handler that is passed as a prop to the Modal component
|
25
|
+
if (onCloseHandler) {
|
26
|
+
onCloseHandler(e);
|
27
|
+
}
|
28
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// Disable coverage for the following function
|
2
|
+
/* istanbul ignore next */
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Handles the keydown event of the dialog which is fired when the user presses a key within the dialog.
|
6
|
+
*
|
7
|
+
* This handler is used to stop propagation of the Escape key press, if it is not allowed to close
|
8
|
+
* on Escape key and the close button is disabled.
|
9
|
+
*
|
10
|
+
* It is also used to trigger the primary action when the user presses the Enter key, if it is allowed to trigger
|
11
|
+
* the primary action on Enter key and the primary button is not disabled. This applies only when the focused
|
12
|
+
* element is an input or select as other elements should not trigger the primary action. Textarea is omitted
|
13
|
+
* as Enter key is used for new line.
|
14
|
+
*
|
15
|
+
* @param e
|
16
|
+
* @param closeButtonRef
|
17
|
+
* @param primaryButtonRef
|
18
|
+
* @param allowCloseOnEscapeKey
|
19
|
+
* @param allowPrimaryActionOnEnterKey
|
20
|
+
*/
|
21
|
+
export const dialogOnKeyDownHandler = (
|
22
|
+
e,
|
23
|
+
closeButtonRef,
|
24
|
+
primaryButtonRef,
|
25
|
+
allowCloseOnEscapeKey,
|
26
|
+
allowPrimaryActionOnEnterKey,
|
27
|
+
) => {
|
28
|
+
if (e.key === 'Escape') {
|
29
|
+
// Prevent closing the modal using the Escape key when one of the following conditions is met:
|
30
|
+
// 1. The close button is not present
|
31
|
+
// 2. The close button is disabled
|
32
|
+
// 3. `allowCloseOnEscapeKey` is set to `false`
|
33
|
+
//
|
34
|
+
// ⚠️ Else-if statement calling `closeButtonRef.current.click()` is necessary due to missing support
|
35
|
+
// of close event in happy-dom library. When this is fixed, the `else` statement can be removed
|
36
|
+
// as the `closeButtonRef.current.click()` will be handled by `dialogOnCancelHandler.js`.
|
37
|
+
if (
|
38
|
+
closeButtonRef?.current == null
|
39
|
+
|| closeButtonRef?.current?.disabled === true
|
40
|
+
|| !allowCloseOnEscapeKey
|
41
|
+
) {
|
42
|
+
e.preventDefault();
|
43
|
+
} else if (process?.env?.NODE_ENV === 'test') {
|
44
|
+
closeButtonRef.current.click();
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
// Trigger the primary action when the Enter key is pressed and the following conditions are met:
|
49
|
+
// 1. The primary button is present
|
50
|
+
// 2. The primary button is not disabled
|
51
|
+
// 3. `allowPrimaryActionOnEnterKey` is set to `true`
|
52
|
+
// 4. The focused element is an input or select (text area is omitted as Enter key is used for new line)
|
53
|
+
if (
|
54
|
+
e.key === 'Enter'
|
55
|
+
&& primaryButtonRef?.current != null
|
56
|
+
&& primaryButtonRef?.current?.disabled === false
|
57
|
+
&& allowPrimaryActionOnEnterKey
|
58
|
+
&& ['INPUT', 'SELECT'].includes(e.target.nodeName)
|
59
|
+
) {
|
60
|
+
primaryButtonRef.current.click();
|
61
|
+
}
|
62
|
+
};
|
@@ -2,9 +2,8 @@ import { useEffect } from 'react';
|
|
2
2
|
|
3
3
|
export const useModalFocus = (
|
4
4
|
autoFocus,
|
5
|
-
|
5
|
+
dialogRef,
|
6
6
|
primaryButtonRef,
|
7
|
-
closeButtonRef,
|
8
7
|
) => {
|
9
8
|
useEffect(
|
10
9
|
() => {
|
@@ -12,115 +11,49 @@ export const useModalFocus = (
|
|
12
11
|
// field element (input, textarea or select) or primary button and focuses it. This is
|
13
12
|
// necessary to have focus on one of those elements to be able to submit the form
|
14
13
|
// by pressing Enter key. If there are neither, it tries to focus any other focusable
|
15
|
-
// elements. In case there are none or `autoFocus` is disabled,
|
14
|
+
// elements. In case there are none or `autoFocus` is disabled, dialogElement
|
16
15
|
// (Modal itself) is focused.
|
17
16
|
|
18
|
-
const
|
17
|
+
const dialogElement = dialogRef.current;
|
19
18
|
|
20
|
-
if (
|
19
|
+
if (dialogElement == null) {
|
21
20
|
return () => {};
|
22
21
|
}
|
23
22
|
|
24
23
|
const childrenFocusableElements = Array.from(
|
25
|
-
|
24
|
+
dialogElement.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
|
26
25
|
);
|
27
26
|
|
28
27
|
const firstFocusableElement = childrenFocusableElements[0];
|
29
|
-
const lastFocusableElement = childrenFocusableElements[childrenFocusableElements.length - 1];
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
37
|
-
|
38
|
-
const firstFormFieldEl = childrenFocusableElements.find(
|
39
|
-
(element) => ['INPUT', 'TEXTAREA', 'SELECT'].includes(element.nodeName) && !element.disabled,
|
40
|
-
);
|
41
|
-
|
42
|
-
if (firstFormFieldEl) {
|
43
|
-
firstFormFieldEl.focus();
|
44
|
-
return;
|
45
|
-
}
|
46
|
-
|
47
|
-
if (primaryButtonRef?.current != null) {
|
48
|
-
primaryButtonRef.current.focus();
|
49
|
-
return;
|
50
|
-
}
|
51
|
-
|
52
|
-
firstFocusableElement.focus();
|
53
|
-
};
|
54
|
-
|
55
|
-
const keyPressHandler = (e) => {
|
56
|
-
if (e.key === 'Escape' && closeButtonRef?.current != null) {
|
57
|
-
closeButtonRef.current.click();
|
58
|
-
return;
|
59
|
-
}
|
60
|
-
|
61
|
-
if (
|
62
|
-
e.key === 'Enter'
|
63
|
-
&& e.target.nodeName !== 'BUTTON'
|
64
|
-
&& e.target.nodeName !== 'TEXTAREA'
|
65
|
-
&& e.target.nodeName !== 'A'
|
66
|
-
&& primaryButtonRef?.current != null
|
67
|
-
) {
|
68
|
-
primaryButtonRef.current.click();
|
69
|
-
return;
|
70
|
-
}
|
71
|
-
|
72
|
-
// Following code traps focus inside Modal
|
73
|
-
|
74
|
-
if (e.key !== 'Tab') {
|
75
|
-
return;
|
76
|
-
}
|
77
|
-
|
78
|
-
if (childrenFocusableElements.length === 0) {
|
79
|
-
childrenWrapperElement.focus();
|
80
|
-
e.preventDefault();
|
81
|
-
return;
|
82
|
-
}
|
83
|
-
|
84
|
-
if (
|
85
|
-
![
|
86
|
-
...childrenFocusableElements,
|
87
|
-
childrenWrapperElement,
|
88
|
-
]
|
89
|
-
.includes(window.document.activeElement)
|
90
|
-
) {
|
91
|
-
firstFocusableElement.focus();
|
92
|
-
e.preventDefault();
|
93
|
-
return;
|
94
|
-
}
|
29
|
+
if (!autoFocus || childrenFocusableElements.length === 0) {
|
30
|
+
dialogElement.tabIndex = -1;
|
31
|
+
dialogElement.focus();
|
32
|
+
return () => {};
|
33
|
+
}
|
95
34
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
return;
|
100
|
-
}
|
35
|
+
const firstFormFieldEl = childrenFocusableElements.find(
|
36
|
+
(element) => ['INPUT', 'TEXTAREA', 'SELECT'].includes(element.nodeName) && !element.disabled,
|
37
|
+
);
|
101
38
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
)
|
107
|
-
) {
|
108
|
-
lastFocusableElement.focus();
|
109
|
-
e.preventDefault();
|
110
|
-
}
|
111
|
-
};
|
39
|
+
if (firstFormFieldEl) {
|
40
|
+
firstFormFieldEl.focus();
|
41
|
+
return () => {};
|
42
|
+
}
|
112
43
|
|
113
|
-
|
44
|
+
if (primaryButtonRef?.current != null && primaryButtonRef?.current?.disabled === false) {
|
45
|
+
primaryButtonRef.current.focus();
|
46
|
+
return () => {};
|
47
|
+
}
|
114
48
|
|
115
|
-
|
49
|
+
firstFocusableElement.focus();
|
116
50
|
|
117
|
-
return () =>
|
51
|
+
return () => {};
|
118
52
|
},
|
119
53
|
[
|
120
54
|
autoFocus,
|
121
|
-
|
55
|
+
dialogRef,
|
122
56
|
primaryButtonRef,
|
123
|
-
closeButtonRef,
|
124
57
|
],
|
125
58
|
);
|
126
59
|
};
|
@@ -1,9 +1,10 @@
|
|
1
1
|
@use "sass:map";
|
2
|
-
@use "../../styles/settings/
|
2
|
+
@use "../../styles/settings/collections";
|
3
3
|
@use "../../styles/theme/borders";
|
4
4
|
@use "../../styles/theme/typography";
|
5
5
|
|
6
|
+
$border-width: borders.$width;
|
6
7
|
$border-radius: borders.$radius-2;
|
7
|
-
$z-index: z-indexes.$modal;
|
8
|
-
$backdrop-z-index: z-indexes.$modal-backdrop;
|
9
8
|
$title-font-size: map.get(typography.$font-size-values, 2);
|
9
|
+
$colors: collections.$feedback-colors;
|
10
|
+
$themeable-properties: border-color, background-color;
|
@@ -10,6 +10,7 @@ $footer-gap: var(--rui-Modal__footer__gap);
|
|
10
10
|
$backdrop-background: var(--rui-Modal__backdrop__background);
|
11
11
|
$outer-spacing-xs: var(--rui-Modal__outer-spacing--xs);
|
12
12
|
$outer-spacing-sm: var(--rui-Modal__outer-spacing--sm);
|
13
|
+
$animation-duration: var(--rui-Modal__animation__duration);
|
13
14
|
|
14
15
|
$sizes: (
|
15
16
|
auto: (
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import styles from './Paper.module.scss';
|
7
7
|
|
8
8
|
export const Paper = ({
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { createPortal } from 'react-dom';
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
|
+
import { classNames } from '../../helpers/classNames';
|
4
6
|
import { withGlobalProps } from '../../providers/globalProps';
|
5
|
-
import { classNames } from '../../utils/classNames';
|
6
|
-
import { transferProps } from '../../utils/transferProps';
|
7
7
|
import cleanPlacementStyle from './_helpers/cleanPlacementStyle';
|
8
8
|
import getRootSideClassName from './_helpers/getRootSideClassName';
|
9
9
|
import getRootAlignmentClassName from './_helpers/getRootAlignmentClassName';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { transferProps } from '../../
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
5
|
import styles from './PopoverWrapper.module.scss';
|
6
6
|
|
7
7
|
export const PopoverWrapper = ({
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
7
7
|
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
|
8
8
|
import { FormLayoutContext } from '../FormLayout';
|
@@ -8,8 +8,8 @@ import React, {
|
|
8
8
|
} from 'react';
|
9
9
|
import { TranslationsContext } from '../../providers/translations';
|
10
10
|
import { withGlobalProps } from '../../providers/globalProps';
|
11
|
-
import { classNames } from '../../
|
12
|
-
import { transferProps } from '../../
|
11
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
12
|
+
import { transferProps } from '../../helpers/transferProps';
|
13
13
|
import { getElementsPositionDifference } from './_helpers/getElementsPositionDifference';
|
14
14
|
import { useLoadResize } from './_hooks/useLoadResizeHook';
|
15
15
|
import { useScrollPosition } from './_hooks/useScrollPositionHook';
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
7
7
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
8
8
|
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { transferProps } from '../../
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
5
|
import { TableHeaderCell } from './_components/TableHeaderCell';
|
6
6
|
import { TableBodyCell } from './_components/TableBodyCell';
|
7
7
|
import styles from './Table.module.scss';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { transferProps } from '../../
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
5
|
import styles from './Tabs.module.scss';
|
6
6
|
|
7
7
|
export const Tabs = ({
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import styles from './TabsItem.module.scss';
|
7
7
|
|
8
8
|
export const TabsItem = ({
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
7
7
|
import { getRootClampClassName } from './_helpers/getRootClampClassName';
|
8
8
|
import { getRootHyphensClassName } from './_helpers/getRootHyphensClassName';
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
7
7
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
8
8
|
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
7
7
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
8
8
|
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { transferProps } from '../../
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
5
|
import styles from './TextLink.module.scss';
|
6
6
|
|
7
7
|
export const TextLink = ({
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
7
7
|
import { FormLayoutContext } from '../FormLayout';
|
8
8
|
import styles from './Toggle.module.scss';
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
7
7
|
import { getAlignClassName } from './_helpers/getAlignClassName';
|
8
8
|
import { getJustifyClassName } from './_helpers/getJustifyClassName';
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
3
|
import { withGlobalProps } from '../../providers/globalProps';
|
4
|
-
import { classNames } from '../../
|
5
|
-
import { transferProps } from '../../
|
4
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
5
|
+
import { transferProps } from '../../helpers/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
7
7
|
import { getAlignClassName } from './_helpers/getAlignClassName';
|
8
8
|
import styles from './Toolbar.module.scss';
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { classNames } from '../../
|
4
|
-
import { transferProps } from '../../
|
3
|
+
import { classNames } from '../../helpers/classNames/classNames';
|
4
|
+
import { transferProps } from '../../helpers/transferProps';
|
5
5
|
import { withGlobalProps } from '../../providers/globalProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
7
7
|
import styles from './Toolbar.module.scss';
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# classNames
|
2
|
+
|
3
|
+
The `classNames` helper function simplifies creating a string passable to
|
4
|
+
the `class` / `className` attribute.
|
5
|
+
|
6
|
+
It accepts multiple arguments, filters out invalid values, and returns a single
|
7
|
+
string where the remaining parameters are joined by a space.
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
To use `classNames` helper, you need to import it first:
|
12
|
+
|
13
|
+
```js
|
14
|
+
import { classNames } from '@react-ui-org/react-ui';
|
15
|
+
```
|
16
|
+
|
17
|
+
And use it:
|
18
|
+
|
19
|
+
```docoff-react-preview
|
20
|
+
<>
|
21
|
+
<div
|
22
|
+
className={classNames(
|
23
|
+
'd-block',
|
24
|
+
new Date('2025-01-01T00:00:00') < new Date() && 'text-danger',
|
25
|
+
)}
|
26
|
+
>
|
27
|
+
{(new Date()).toLocaleDateString()}
|
28
|
+
</div>
|
29
|
+
<div
|
30
|
+
className={classNames(
|
31
|
+
'd-block',
|
32
|
+
new Date('3000-01-01T00:00:00') < new Date() && 'text-danger',
|
33
|
+
)}
|
34
|
+
>
|
35
|
+
{(new Date()).toLocaleDateString()}
|
36
|
+
</div>
|
37
|
+
</>
|
38
|
+
```
|
39
|
+
|
40
|
+
## Parameter Filtering
|
41
|
+
|
42
|
+
The `classNames` function:
|
43
|
+
|
44
|
+
* filters out all values that are not strings
|
45
|
+
* filters out empty strings
|
46
|
+
* filters out whitespace only strings
|
47
|
+
|
48
|
+
<!-- markdownlint-disable MD010 -->
|
49
|
+
```docoff-react-preview
|
50
|
+
{classNames(
|
51
|
+
'class-1',
|
52
|
+
'class-2 class-3',
|
53
|
+
' ',
|
54
|
+
' ', // non-breakable space
|
55
|
+
' ', // tab
|
56
|
+
'',
|
57
|
+
0,
|
58
|
+
1,
|
59
|
+
null,
|
60
|
+
undefined,
|
61
|
+
true,
|
62
|
+
false,
|
63
|
+
)}
|
64
|
+
```
|
65
|
+
<!-- markdownlint-enable MD010 -->
|
@@ -0,0 +1,11 @@
|
|
1
|
+
export const classNames = (...classes) => {
|
2
|
+
const filteredClassNames = classes.filter(
|
3
|
+
(className) => typeof className === 'string'
|
4
|
+
&& className.trim().length > 0,
|
5
|
+
);
|
6
|
+
|
7
|
+
return filteredClassNames.length > 0
|
8
|
+
? filteredClassNames.join(' ')
|
9
|
+
// React does not render attributes whose value is `undefined` and we do not want an empty `class` attribute in HTML
|
10
|
+
: undefined;
|
11
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export { classNames } from './classNames';
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# transferProps
|
2
|
+
|
3
|
+
The `transferProps` helper controls passing of props from the React component
|
4
|
+
to the HTML element.
|
5
|
+
|
6
|
+
It enables making the component interactive and helps to improve its
|
7
|
+
accessibility. However some props should never be passed to the HTML element
|
8
|
+
as it would break things. This function is used to filter them out. Among these
|
9
|
+
props are:
|
10
|
+
|
11
|
+
- `children`
|
12
|
+
- `className`
|
13
|
+
- `contentEditable`
|
14
|
+
- `dangerouslySetInnerHtml`
|
15
|
+
- `ref`
|
16
|
+
- `staticContext`
|
17
|
+
- `style`
|
18
|
+
- `suppressContentEditableWarning`
|
19
|
+
|
20
|
+
👉 When run in development mode, the function will log the error to the console
|
21
|
+
if any invalid props are passed.
|
22
|
+
|
23
|
+
## Basic Usage
|
24
|
+
|
25
|
+
To use `transferProps` helper, you need to import it first:
|
26
|
+
|
27
|
+
```js
|
28
|
+
import { transferProps } from "@react-ui-org/react-ui";
|
29
|
+
```
|
30
|
+
|
31
|
+
And use it:
|
32
|
+
|
33
|
+
```jsx
|
34
|
+
const CustomComponent = ({
|
35
|
+
children,
|
36
|
+
id,
|
37
|
+
...restProps
|
38
|
+
}) => (
|
39
|
+
<div
|
40
|
+
{...transferProps(restProps)}
|
41
|
+
id={id && `${id}__customComponent`}
|
42
|
+
>
|
43
|
+
{children}
|
44
|
+
</div>
|
45
|
+
);
|
46
|
+
```
|
@@ -0,0 +1 @@
|
|
1
|
+
export { transferProps } from './transferProps';
|