@react-ui-org/react-ui 0.57.0 → 0.58.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/.nvmrc +1 -1
- package/dist/react-ui.css +14 -14
- package/dist/react-ui.development.css +225 -14
- package/dist/react-ui.development.js +102 -62
- package/dist/react-ui.js +1 -1
- package/package.json +12 -1
- package/src/components/Alert/Alert.jsx +3 -5
- package/src/components/Alert/Alert.module.scss +3 -3
- package/src/components/Alert/README.md +22 -10
- package/src/components/Badge/Badge.jsx +1 -1
- package/src/components/Button/Button.jsx +1 -1
- package/src/components/ButtonGroup/ButtonGroup.jsx +1 -1
- package/src/components/Card/Card.jsx +1 -1
- package/src/components/Card/Card.module.scss +6 -5
- package/src/components/Card/CardBody.jsx +1 -1
- package/src/components/Card/CardFooter.jsx +1 -1
- package/src/components/Card/README.md +22 -0
- package/src/components/CheckboxField/CheckboxField.jsx +9 -3
- package/src/components/CheckboxField/README.md +110 -5
- package/src/components/FileInputField/FileInputField.jsx +1 -1
- package/src/components/FormLayout/FormLayout.jsx +1 -1
- package/src/components/FormLayout/FormLayoutCustomField.jsx +1 -1
- package/src/components/Grid/Grid.jsx +1 -1
- package/src/components/Grid/GridSpan.jsx +1 -1
- package/src/components/InputGroup/InputGroup.jsx +2 -2
- package/src/components/InputGroup/InputGroup.module.scss +9 -5
- package/src/components/Modal/Modal.jsx +1 -1
- package/src/components/Modal/ModalBody.jsx +1 -1
- package/src/components/Modal/ModalCloseButton.jsx +3 -5
- package/src/components/Modal/ModalContent.jsx +1 -1
- package/src/components/Modal/ModalFooter.jsx +1 -1
- package/src/components/Modal/ModalHeader.jsx +1 -1
- package/src/components/Modal/ModalTitle.jsx +1 -1
- package/src/components/Modal/README.md +18 -18
- package/src/components/Paper/Paper.jsx +1 -1
- package/src/components/Popover/Popover.jsx +58 -13
- package/src/components/Popover/Popover.module.scss +37 -9
- package/src/components/Popover/PopoverWrapper.jsx +1 -1
- package/src/components/Popover/README.md +60 -3
- package/src/components/Popover/_helpers/cleanPlacementStyle.js +20 -0
- package/src/components/Radio/README.md +103 -0
- package/src/components/Radio/Radio.jsx +9 -3
- package/src/components/Radio/Radio.module.scss +4 -0
- package/src/components/ScrollView/ScrollView.jsx +3 -5
- package/src/components/SelectField/README.md +103 -0
- package/src/components/SelectField/SelectField.jsx +9 -3
- package/src/components/Table/Table.jsx +1 -1
- package/src/components/Tabs/Tabs.jsx +1 -1
- package/src/components/Tabs/TabsItem.jsx +1 -1
- package/src/components/Text/Text.jsx +1 -1
- package/src/components/TextArea/TextArea.jsx +1 -1
- package/src/components/TextField/README.md +14 -2
- package/src/components/TextField/TextField.jsx +1 -1
- package/src/components/TextLink/README.md +10 -3
- package/src/components/TextLink/TextLink.jsx +1 -1
- package/src/components/TextLink/_theme.scss +3 -3
- package/src/components/Toggle/README.md +83 -1
- package/src/components/Toggle/Toggle.jsx +9 -3
- package/src/components/Toolbar/Toolbar.jsx +1 -1
- package/src/components/Toolbar/ToolbarGroup.jsx +1 -1
- package/src/components/Toolbar/ToolbarItem.jsx +1 -1
- package/src/components/_helpers/resolveContextOrProp.js +6 -3
- package/src/index.js +3 -2
- package/src/providers/globalProps/GlobalPropsContext.jsx +5 -0
- package/src/providers/globalProps/GlobalPropsProvider.jsx +33 -0
- package/src/providers/globalProps/index.js +3 -0
- package/src/{provider → providers/globalProps}/withGlobalProps.jsx +16 -16
- package/src/providers/translations/TranslationsContext.jsx +6 -0
- package/src/providers/translations/TranslationsProvider.jsx +33 -0
- package/src/providers/translations/index.js +2 -0
- package/src/styles/elements/_links.scss +7 -2
- package/src/styles/theme/_form-fields.scss +19 -0
- package/src/styles/theme/_links.scss +4 -3
- package/src/styles/tools/_collections.scss +79 -5
- package/src/styles/tools/form-fields/_foundation.scss +6 -4
- package/src/styles/tools/form-fields/_variants.scss +5 -1
- package/src/theme.scss +2 -1
- package/src/provider/RUIContext.jsx +0 -9
- package/src/provider/RUIProvider.jsx +0 -42
- package/src/provider/index.js +0 -3
@@ -6,10 +6,8 @@ import React, {
|
|
6
6
|
useRef,
|
7
7
|
useState,
|
8
8
|
} from 'react';
|
9
|
-
import {
|
10
|
-
|
11
|
-
withGlobalProps,
|
12
|
-
} from '../../provider';
|
9
|
+
import { TranslationsContext } from '../../providers/translations';
|
10
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
13
11
|
import { classNames } from '../../utils/classNames';
|
14
12
|
import { transferProps } from '../../utils/transferProps';
|
15
13
|
import { getElementsPositionDifference } from './_helpers/getElementsPositionDifference';
|
@@ -48,7 +46,7 @@ export const ScrollView = React.forwardRef((props, ref) => {
|
|
48
46
|
...restProps
|
49
47
|
} = props;
|
50
48
|
|
51
|
-
const
|
49
|
+
const translations = useContext(TranslationsContext);
|
52
50
|
|
53
51
|
const [isAutoScrollInProgress, setIsAutoScrollInProgress] = useState(false);
|
54
52
|
const [isScrolledAtStart, setIsScrolledAtStart] = useState(false);
|
@@ -592,6 +592,109 @@ React.createElement(() => {
|
|
592
592
|
})
|
593
593
|
```
|
594
594
|
|
595
|
+
### Required State
|
596
|
+
|
597
|
+
The required state indicates that the input is mandatory.
|
598
|
+
|
599
|
+
```docoff-react-preview
|
600
|
+
React.createElement(() => {
|
601
|
+
const [fruit, setFruit] = React.useState('apple');
|
602
|
+
return (
|
603
|
+
<SelectField
|
604
|
+
label="Your favourite fruit"
|
605
|
+
onChange={(e) => setFruit(e.target.value)}
|
606
|
+
options={[
|
607
|
+
{
|
608
|
+
label: 'Apple',
|
609
|
+
value: 'apple',
|
610
|
+
},
|
611
|
+
{
|
612
|
+
label: 'Banana',
|
613
|
+
value: 'banana',
|
614
|
+
},
|
615
|
+
{
|
616
|
+
label: 'Grapefruit',
|
617
|
+
value: 'grapefruit',
|
618
|
+
},
|
619
|
+
]}
|
620
|
+
value={fruit}
|
621
|
+
required
|
622
|
+
/>
|
623
|
+
);
|
624
|
+
});
|
625
|
+
```
|
626
|
+
|
627
|
+
#### Styling the Required State
|
628
|
+
|
629
|
+
All form fields in React UI can be
|
630
|
+
[styled](/docs/customize/theming/forms/#required-state)
|
631
|
+
to indicate the required state.
|
632
|
+
|
633
|
+
However, you may find yourself in a situation where a form field is valid in
|
634
|
+
both selected and unselected states, for example to turn on or off a feature.
|
635
|
+
If your project uses the label color as the primary means to indicate the
|
636
|
+
required state of input fields and the usual asterisk `*` is omitted, you may
|
637
|
+
want to keep the label color consistent for both states to avoid confusion.
|
638
|
+
|
639
|
+
For this edge case, there is the `renderAsRequired` prop:
|
640
|
+
|
641
|
+
```docoff-react-preview
|
642
|
+
React.createElement(() => {
|
643
|
+
const [fruit, setFruit] = React.useState('apple');
|
644
|
+
const options = [
|
645
|
+
{
|
646
|
+
label: 'Apple',
|
647
|
+
value: 'apple',
|
648
|
+
},
|
649
|
+
{
|
650
|
+
label: 'Banana',
|
651
|
+
value: 'banana',
|
652
|
+
},
|
653
|
+
{
|
654
|
+
label: 'Grapefruit',
|
655
|
+
value: 'grapefruit',
|
656
|
+
},
|
657
|
+
];
|
658
|
+
return (
|
659
|
+
<React.Fragment>
|
660
|
+
<style>
|
661
|
+
{`
|
662
|
+
.example {
|
663
|
+
display: flex;
|
664
|
+
flex-wrap: wrap;
|
665
|
+
gap: 1rem 0.5rem;
|
666
|
+
}
|
667
|
+
|
668
|
+
.example--themed-form-fields {
|
669
|
+
--rui-FormField__label__color: var(--rui-color-text-secondary);
|
670
|
+
--rui-FormField--required__label__color: var(--rui-color-text-primary);
|
671
|
+
--rui-FormField--required__sign: '';
|
672
|
+
}
|
673
|
+
`}
|
674
|
+
</style>
|
675
|
+
<div class="example example--themed-form-fields">
|
676
|
+
<SelectField
|
677
|
+
label="This field is optional"
|
678
|
+
onChange={(e) => setFruit(e.target.value)}
|
679
|
+
options={options}
|
680
|
+
value={fruit}
|
681
|
+
/>
|
682
|
+
<SelectField
|
683
|
+
label="This field is optional but looks like required"
|
684
|
+
onChange={(e) => setFruit(e.target.value)}
|
685
|
+
options={options}
|
686
|
+
value={fruit}
|
687
|
+
renderAsRequired
|
688
|
+
/>
|
689
|
+
</div>
|
690
|
+
</React.Fragment>
|
691
|
+
);
|
692
|
+
});
|
693
|
+
```
|
694
|
+
|
695
|
+
It renders the field as if it was required, but doesn't add the `required`
|
696
|
+
attribute to the actual input.
|
697
|
+
|
595
698
|
### Disabled State
|
596
699
|
|
597
700
|
It's possible to disable just some options or the whole input.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
@@ -21,6 +21,7 @@ export const SelectField = React.forwardRef((props, ref) => {
|
|
21
21
|
label,
|
22
22
|
layout,
|
23
23
|
options,
|
24
|
+
renderAsRequired,
|
24
25
|
required,
|
25
26
|
size,
|
26
27
|
validationState,
|
@@ -43,7 +44,7 @@ export const SelectField = React.forwardRef((props, ref) => {
|
|
43
44
|
? styles.isRootLayoutHorizontal
|
44
45
|
: styles.isRootLayoutVertical,
|
45
46
|
inputGroupContext && styles.isRootGrouped,
|
46
|
-
required && styles.isRootRequired,
|
47
|
+
(renderAsRequired || required) && styles.isRootRequired,
|
47
48
|
getRootSizeClassName(
|
48
49
|
resolveContextOrProp(inputGroupContext && inputGroupContext.size, size),
|
49
50
|
styles,
|
@@ -136,6 +137,7 @@ SelectField.defaultProps = {
|
|
136
137
|
id: undefined,
|
137
138
|
isLabelVisible: true,
|
138
139
|
layout: 'vertical',
|
140
|
+
renderAsRequired: false,
|
139
141
|
required: false,
|
140
142
|
size: 'medium',
|
141
143
|
validationState: null,
|
@@ -227,7 +229,11 @@ SelectField.propTypes = {
|
|
227
229
|
})),
|
228
230
|
]).isRequired,
|
229
231
|
/**
|
230
|
-
* If `true`, the input will be required.
|
232
|
+
* If `true`, the input will be rendered as if it was required.
|
233
|
+
*/
|
234
|
+
renderAsRequired: PropTypes.bool,
|
235
|
+
/**
|
236
|
+
* If `true`, the input will be made and rendered as required, regardless of the `renderAsRequired` prop.
|
231
237
|
*/
|
232
238
|
required: PropTypes.bool,
|
233
239
|
/**
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { transferProps } from '../../utils/transferProps';
|
5
5
|
import { TableHeaderCell } from './_components/TableHeaderCell';
|
6
6
|
import { TableBodyCell } from './_components/TableBodyCell';
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { transferProps } from '../../utils/transferProps';
|
5
5
|
import styles from './Tabs.module.scss';
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import styles from './TabsItem.module.scss';
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
@@ -388,7 +388,13 @@ have.
|
|
388
388
|
label="User name"
|
389
389
|
onChange={() => {}}
|
390
390
|
validationState="warning"
|
391
|
-
validationText=
|
391
|
+
validationText={(
|
392
|
+
<>
|
393
|
+
Account with this name already exists, pick a different one.
|
394
|
+
{' '}
|
395
|
+
<TextLink href="#" label="Forgot your password?" />
|
396
|
+
</>
|
397
|
+
)}
|
392
398
|
value="joe"
|
393
399
|
required
|
394
400
|
/>
|
@@ -411,7 +417,13 @@ have.
|
|
411
417
|
label="User name"
|
412
418
|
onChange={() => {}}
|
413
419
|
validationState="warning"
|
414
|
-
validationText=
|
420
|
+
validationText={(
|
421
|
+
<>
|
422
|
+
Account with this name already exists, pick a different one.
|
423
|
+
{' '}
|
424
|
+
<TextLink href="#" label="Forgot your password?" />
|
425
|
+
</>
|
426
|
+
)}
|
415
427
|
variant="filled"
|
416
428
|
value="joe"
|
417
429
|
required
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { getRootSizeClassName } from '../_helpers/getRootSizeClassName';
|
@@ -64,13 +64,20 @@ helps to improve its accessibility.
|
|
64
64
|
|
65
65
|
## Theming
|
66
66
|
|
67
|
+
ℹ️ The TextLink component is context-aware and can inherit text color from its
|
68
|
+
parent component. This applies for components using
|
69
|
+
[Feedback color collection](/docs/foundation/collections#colors) and for
|
70
|
+
components in any of the supported
|
71
|
+
[validation states](/docs/foundation/colors#validation-states).
|
72
|
+
In such cases, the custom properties marked with an asterisk (\*) are ignored.
|
73
|
+
|
67
74
|
| Custom Property | Description |
|
68
75
|
|-------------------------------------------|-------------------------------------|
|
69
|
-
| `--rui-TextLink__color`
|
76
|
+
| `--rui-TextLink__color` \* | Text color |
|
70
77
|
| `--rui-TextLink__text-decoration` | Text decoration, e.g. underline |
|
71
|
-
| `--rui-TextLink--hover__color`
|
78
|
+
| `--rui-TextLink--hover__color` \* | Text color on hover |
|
72
79
|
| `--rui-TextLink--hover__text-decoration` | Text decoration on hover |
|
73
|
-
| `--rui-TextLink--active__color`
|
80
|
+
| `--rui-TextLink--active__color` \* | Text color in the active state |
|
74
81
|
| `--rui-TextLink--active__text-decoration` | Text decoration in the active state |
|
75
82
|
|
76
83
|
[a-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attributes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { transferProps } from '../../utils/transferProps';
|
5
5
|
import styles from './TextLink.module.scss';
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
$color: var(--rui-TextLink__color);
|
1
|
+
$color: var(--rui-local-link-color, var(--rui-TextLink__color));
|
2
2
|
$text-decoration: var(--rui-TextLink__text-decoration);
|
3
|
-
$hover-color: var(--rui-TextLink--hover__color);
|
3
|
+
$hover-color: var(--rui-local-link-color-hover, var(--rui-TextLink--hover__color));
|
4
4
|
$hover-text-decoration: var(--rui-TextLink--hover__text-decoration);
|
5
|
-
$active-color: var(--rui-TextLink--active__color);
|
5
|
+
$active-color: var(--rui-local-link-color-active, var(--rui-TextLink--active__color));
|
6
6
|
$active-text-decoration: var(--rui-TextLink--active__text-decoration);
|
@@ -148,13 +148,95 @@ React.createElement(() => {
|
|
148
148
|
label="Listen in studio quality"
|
149
149
|
onChange={() => setStudioQuality(!studioQuality)}
|
150
150
|
validationState="invalid"
|
151
|
-
validationText=
|
151
|
+
validationText={(
|
152
|
+
<>
|
153
|
+
Please
|
154
|
+
{' '}
|
155
|
+
<TextLink href="#" label="upgrade your plan" />
|
156
|
+
{' '}
|
157
|
+
to make this option available.
|
158
|
+
</>
|
159
|
+
)}
|
152
160
|
/>
|
153
161
|
</>
|
154
162
|
);
|
155
163
|
});
|
156
164
|
```
|
157
165
|
|
166
|
+
### Required State
|
167
|
+
|
168
|
+
The required state indicates that the input is mandatory.
|
169
|
+
|
170
|
+
```docoff-react-preview
|
171
|
+
React.createElement(() => {
|
172
|
+
const [studioQuality, setStudioQuality] = React.useState(true);
|
173
|
+
return (
|
174
|
+
<Toggle
|
175
|
+
checked={studioQuality}
|
176
|
+
label="Listen in studio quality"
|
177
|
+
onChange={() => setStudioQuality(!studioQuality)}
|
178
|
+
required
|
179
|
+
/>
|
180
|
+
);
|
181
|
+
});
|
182
|
+
```
|
183
|
+
|
184
|
+
#### Styling the Required State
|
185
|
+
|
186
|
+
All form fields in React UI can be
|
187
|
+
[styled](/docs/customize/theming/forms/#required-state)
|
188
|
+
to indicate the required state.
|
189
|
+
|
190
|
+
However, you may find yourself in a situation where a form field is valid in
|
191
|
+
both checked and unchecked states, for example to turn on or off a feature.
|
192
|
+
If your project uses the label color as the primary means to indicate the
|
193
|
+
required state of input fields and the usual asterisk `*` is omitted, you may
|
194
|
+
want to keep the label color consistent for both states to avoid confusion.
|
195
|
+
|
196
|
+
For this edge case, there is the `renderAsRequired` prop:
|
197
|
+
|
198
|
+
```docoff-react-preview
|
199
|
+
React.createElement(() => {
|
200
|
+
const [optional, setOptional] = React.useState(false);
|
201
|
+
const [renderAsRequired, setRenderAsRequired] = React.useState(false);
|
202
|
+
return (
|
203
|
+
<React.Fragment>
|
204
|
+
<style>
|
205
|
+
{`
|
206
|
+
.example {
|
207
|
+
display: flex;
|
208
|
+
flex-wrap: wrap;
|
209
|
+
gap: 1rem 0.5rem;
|
210
|
+
}
|
211
|
+
|
212
|
+
.example--themed-form-fields {
|
213
|
+
--rui-FormField__label__color: var(--rui-color-text-secondary);
|
214
|
+
--rui-FormField--required__label__color: var(--rui-color-text-primary);
|
215
|
+
--rui-FormField--required__sign: '';
|
216
|
+
}
|
217
|
+
`}
|
218
|
+
</style>
|
219
|
+
<div class="example example--themed-form-fields">
|
220
|
+
<Toggle
|
221
|
+
checked={optional}
|
222
|
+
label="This field is optional"
|
223
|
+
onChange={() => setOptional(!optional)}
|
224
|
+
/>
|
225
|
+
<Toggle
|
226
|
+
checked={renderAsRequired}
|
227
|
+
label="This field is optional but looks like required"
|
228
|
+
onChange={() => setRenderAsRequired(!renderAsRequired)}
|
229
|
+
renderAsRequired
|
230
|
+
/>
|
231
|
+
</div>
|
232
|
+
</React.Fragment>
|
233
|
+
);
|
234
|
+
});
|
235
|
+
```
|
236
|
+
|
237
|
+
It renders the field as if it was required, but doesn't add the `required`
|
238
|
+
attribute to the actual input.
|
239
|
+
|
158
240
|
### Disabled State
|
159
241
|
|
160
242
|
Disabled state makes the input unavailable.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React, { useContext } from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName';
|
@@ -15,6 +15,7 @@ export const Toggle = React.forwardRef((props, ref) => {
|
|
15
15
|
isLabelVisible,
|
16
16
|
label,
|
17
17
|
labelPosition,
|
18
|
+
renderAsRequired,
|
18
19
|
required,
|
19
20
|
validationState,
|
20
21
|
validationText,
|
@@ -31,7 +32,7 @@ export const Toggle = React.forwardRef((props, ref) => {
|
|
31
32
|
context && context.layout === 'horizontal' ? styles.isRootLayoutHorizontal : styles.isRootLayoutVertical,
|
32
33
|
labelPosition === 'before' && styles.hasRootLabelBefore,
|
33
34
|
disabled && styles.isRootDisabled,
|
34
|
-
required && styles.isRootRequired,
|
35
|
+
(required || renderAsRequired) && styles.isRootRequired,
|
35
36
|
getRootValidationStateClassName(validationState, styles),
|
36
37
|
)}
|
37
38
|
htmlFor={id}
|
@@ -84,6 +85,7 @@ Toggle.defaultProps = {
|
|
84
85
|
id: undefined,
|
85
86
|
isLabelVisible: true,
|
86
87
|
labelPosition: 'after',
|
88
|
+
renderAsRequired: false,
|
87
89
|
required: false,
|
88
90
|
validationState: null,
|
89
91
|
validationText: null,
|
@@ -120,7 +122,11 @@ Toggle.propTypes = {
|
|
120
122
|
*/
|
121
123
|
labelPosition: PropTypes.oneOf(['before', 'after']),
|
122
124
|
/**
|
123
|
-
* If `true`, the input will be required.
|
125
|
+
* If `true`, the input will be rendered as if it was required.
|
126
|
+
*/
|
127
|
+
renderAsRequired: PropTypes.bool,
|
128
|
+
/**
|
129
|
+
* If `true`, the input will be made and rendered as required, regardless of the `renderAsRequired` prop.
|
124
130
|
*/
|
125
131
|
required: PropTypes.bool,
|
126
132
|
/**
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
2
|
import React from 'react';
|
3
|
-
import { withGlobalProps } from '../../
|
3
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
4
4
|
import { classNames } from '../../utils/classNames';
|
5
5
|
import { transferProps } from '../../utils/transferProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
|
2
2
|
import React from 'react';
|
3
3
|
import { classNames } from '../../utils/classNames';
|
4
4
|
import { transferProps } from '../../utils/transferProps';
|
5
|
-
import { withGlobalProps } from '../../
|
5
|
+
import { withGlobalProps } from '../../providers/globalProps';
|
6
6
|
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty';
|
7
7
|
import styles from './Toolbar.module.scss';
|
8
8
|
|
@@ -1,7 +1,10 @@
|
|
1
1
|
export const resolveContextOrProp = (contextValue, propValue) => {
|
2
|
-
|
3
|
-
|
2
|
+
// We need to test:
|
3
|
+
// * `false` - for when the `contextValue` is boolean
|
4
|
+
// * `null` - for when the `contextValue` is non-boolean
|
5
|
+
if (contextValue === false || contextValue === null) {
|
6
|
+
return propValue;
|
4
7
|
}
|
5
8
|
|
6
|
-
return
|
9
|
+
return contextValue;
|
7
10
|
};
|
package/src/index.js
CHANGED
@@ -57,8 +57,9 @@ export {
|
|
57
57
|
ToolbarItem,
|
58
58
|
} from './components/Toolbar';
|
59
59
|
|
60
|
-
//
|
61
|
-
export {
|
60
|
+
// Providers
|
61
|
+
export { GlobalPropsProvider } from './providers/globalProps';
|
62
|
+
export { TranslationsProvider } from './providers/translations';
|
62
63
|
|
63
64
|
// Utils
|
64
65
|
export { classNames } from './utils/classNames';
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
import React, {
|
3
|
+
useContext,
|
4
|
+
} from 'react';
|
5
|
+
import { mergeDeep } from '../../utils/mergeDeep';
|
6
|
+
import GlobalPropsContext from './GlobalPropsContext';
|
7
|
+
|
8
|
+
const GlobalPropsProvider = ({
|
9
|
+
children,
|
10
|
+
globalProps,
|
11
|
+
}) => {
|
12
|
+
const contextGlobalProps = useContext(GlobalPropsContext);
|
13
|
+
|
14
|
+
return (
|
15
|
+
<GlobalPropsContext.Provider
|
16
|
+
value={mergeDeep(contextGlobalProps, globalProps)}
|
17
|
+
>
|
18
|
+
{children}
|
19
|
+
</GlobalPropsContext.Provider>
|
20
|
+
);
|
21
|
+
};
|
22
|
+
|
23
|
+
GlobalPropsProvider.defaultProps = {
|
24
|
+
children: null,
|
25
|
+
globalProps: {},
|
26
|
+
};
|
27
|
+
|
28
|
+
GlobalPropsProvider.propTypes = {
|
29
|
+
children: PropTypes.node,
|
30
|
+
globalProps: PropTypes.shape({}),
|
31
|
+
};
|
32
|
+
|
33
|
+
export default GlobalPropsProvider;
|
@@ -1,26 +1,24 @@
|
|
1
1
|
import PropTypes from 'prop-types';
|
2
|
-
import React
|
3
|
-
|
2
|
+
import React, {
|
3
|
+
useContext,
|
4
|
+
} from 'react';
|
5
|
+
import GlobalPropsContext from './GlobalPropsContext';
|
4
6
|
|
5
7
|
export default (Component, componentName) => {
|
6
8
|
const WithGlobalPropsComponent = ({
|
7
9
|
forwardedRef,
|
8
10
|
...rest
|
9
|
-
}) =>
|
10
|
-
|
11
|
-
{({ globalProps }) => {
|
12
|
-
const contextGlobalProps = globalProps ? globalProps[componentName] : null;
|
11
|
+
}) => {
|
12
|
+
const contextGlobalProps = useContext(GlobalPropsContext);
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
</RUIContext.Consumer>
|
23
|
-
);
|
14
|
+
return (
|
15
|
+
<Component
|
16
|
+
{...contextGlobalProps[componentName] || {}}
|
17
|
+
{...rest}
|
18
|
+
ref={forwardedRef}
|
19
|
+
/>
|
20
|
+
);
|
21
|
+
};
|
24
22
|
|
25
23
|
WithGlobalPropsComponent.defaultProps = {
|
26
24
|
forwardedRef: undefined,
|
@@ -29,6 +27,8 @@ export default (Component, componentName) => {
|
|
29
27
|
WithGlobalPropsComponent.propTypes = {
|
30
28
|
forwardedRef: PropTypes.oneOfType([
|
31
29
|
PropTypes.func,
|
30
|
+
|
31
|
+
// The props can be of any type and here we need to support them all
|
32
32
|
// eslint-disable-next-line react/forbid-prop-types
|
33
33
|
PropTypes.shape({ current: PropTypes.any }),
|
34
34
|
]),
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
import React, {
|
3
|
+
useContext,
|
4
|
+
} from 'react';
|
5
|
+
import { mergeDeep } from '../../utils/mergeDeep';
|
6
|
+
import TranslationsContext from './TranslationsContext';
|
7
|
+
|
8
|
+
const TranslationsProvider = ({
|
9
|
+
children,
|
10
|
+
translations,
|
11
|
+
}) => {
|
12
|
+
const contextTranslations = useContext(TranslationsContext);
|
13
|
+
|
14
|
+
return (
|
15
|
+
<TranslationsContext.Provider
|
16
|
+
value={mergeDeep(contextTranslations, translations)}
|
17
|
+
>
|
18
|
+
{children}
|
19
|
+
</TranslationsContext.Provider>
|
20
|
+
);
|
21
|
+
};
|
22
|
+
|
23
|
+
TranslationsProvider.defaultProps = {
|
24
|
+
children: null,
|
25
|
+
translations: {},
|
26
|
+
};
|
27
|
+
|
28
|
+
TranslationsProvider.propTypes = {
|
29
|
+
children: PropTypes.node,
|
30
|
+
translations: PropTypes.shape({}),
|
31
|
+
};
|
32
|
+
|
33
|
+
export default TranslationsProvider;
|