-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6213b0a
commit 781da8c
Showing
14 changed files
with
592 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import PropTypes from 'prop-types'; | ||
import React, { useContext } from 'react'; | ||
import { Text } from '../Text'; | ||
import { withGlobalProps } from '../../provider'; | ||
import { classNames } from '../../utils/classNames'; | ||
import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; | ||
import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; | ||
import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; | ||
import { transferProps } from '../_helpers/transferProps'; | ||
import { FormLayoutContext } from '../FormLayout'; | ||
import { InputGroupContext } from './InputGroupContext'; | ||
import styles from './InputGroup.scss'; | ||
|
||
export const InputGroup = ({ | ||
children, | ||
isLabelVisible, | ||
label, | ||
layout, | ||
size, | ||
validationTexts, | ||
...restProps | ||
}) => { | ||
const formLayoutContext = useContext(FormLayoutContext); | ||
|
||
if (isChildrenEmpty(children)) { | ||
return null; | ||
} | ||
|
||
const validationState = children.reduce( | ||
(state, child) => { | ||
if (state === 'invalid' || (state === 'warning' && child.props.validationState === 'valid')) { | ||
return state; | ||
} | ||
return child.props.validationState ?? state; | ||
}, | ||
null, | ||
); | ||
|
||
return ( | ||
<label | ||
className={classNames( | ||
styles.root, | ||
resolveContextOrProp(formLayoutContext && formLayoutContext.layout, layout) === 'horizontal' | ||
? styles.isRootLayoutHorizontal | ||
: styles.isRootLayoutVertical, | ||
getRootValidationStateClassName(validationState, styles), | ||
)} | ||
> | ||
<div | ||
className={classNames( | ||
styles.label, | ||
!isLabelVisible && styles.isLabelHidden, | ||
)} | ||
> | ||
{label} | ||
</div> | ||
<div className={styles.field}> | ||
<div | ||
{...transferProps(restProps)} | ||
className={styles.inputGroup} | ||
> | ||
<InputGroupContext.Provider | ||
value={{ | ||
layout, | ||
size, | ||
}} | ||
> | ||
{children} | ||
</InputGroupContext.Provider> | ||
</div> | ||
{validationTexts && ( | ||
<div | ||
className={styles.validationTexts} | ||
> | ||
{validationTexts.map((validationText) => ( | ||
<Text blockLevel key={validationText}> | ||
{validationText} | ||
</Text> | ||
))} | ||
</div> | ||
)} | ||
</div> | ||
</label> | ||
); | ||
}; | ||
|
||
InputGroup.defaultProps = { | ||
children: null, | ||
isLabelVisible: true, | ||
layout: 'horizontal', | ||
size: 'medium', | ||
validationTexts: null, | ||
}; | ||
|
||
InputGroup.propTypes = { | ||
/** | ||
* Supported elements to be grouped: | ||
* * `Button` | ||
* * `SelectField` | ||
* * `TextField` | ||
* | ||
* If none are provided nothing is rendered. | ||
*/ | ||
children: PropTypes.node, | ||
/** | ||
* If `false`, the label will be visually hidden (but remains accessible by assistive | ||
* technologies). | ||
*/ | ||
isLabelVisible: PropTypes.bool, | ||
/** | ||
* Input group label. | ||
*/ | ||
label: PropTypes.string.isRequired, | ||
/** | ||
* Layout of the group. | ||
* | ||
* Ignored if the component is rendered within `FormLayout` component | ||
* as the value is inherited in such case. | ||
*/ | ||
layout: PropTypes.oneOf(['horizontal', 'vertical']), | ||
/** | ||
* Size of the `children` elements. | ||
*/ | ||
size: PropTypes.oneOf(['small', 'medium', 'large']), | ||
/** | ||
* An array of validation messages to be displayed. | ||
*/ | ||
validationTexts: PropTypes.node, | ||
}; | ||
|
||
export const InputGroupWithGlobalProps = withGlobalProps(InputGroup, 'InputGroup'); | ||
|
||
export default InputGroupWithGlobalProps; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
@use "../../styles/tools/form-fields/box-field-elements"; | ||
@use "../../styles/tools/form-fields/box-field-layout"; | ||
@use "../../styles/tools/form-fields/box-field-sizes"; | ||
@use "../../styles/tools/form-fields/foundation"; | ||
@use "../../styles/tools/form-fields/variants"; | ||
@use "../../styles/tools/accessibility"; | ||
@use "theme"; | ||
|
||
.root { | ||
@include box-field-elements.input-container(); | ||
} | ||
|
||
.label { | ||
@include foundation.label(); | ||
} | ||
|
||
.inputGroup { | ||
@include box-field-elements.input-container(); | ||
|
||
gap: theme.$gap; | ||
max-width: none; | ||
} | ||
|
||
.validationTexts { | ||
@include foundation.help-text(); | ||
} | ||
|
||
// States | ||
.isRootStateInvalid { | ||
@include variants.validation(invalid); | ||
} | ||
|
||
.isRootStateValid { | ||
@include variants.validation(valid); | ||
} | ||
|
||
.isRootStateWarning { | ||
@include variants.validation(warning); | ||
} | ||
|
||
// Invisible label | ||
.isLabelHidden { | ||
@include accessibility.hide-text(); | ||
} | ||
|
||
// Layouts | ||
.isRootLayoutVertical, | ||
.isRootLayoutHorizontal { | ||
@include box-field-layout.vertical(); | ||
} | ||
|
||
.isRootLayoutHorizontal { | ||
@include box-field-layout.horizontal($has-min-tap-target: true); | ||
} | ||
|
||
.isRootLayoutHorizontal .label { | ||
width: max-content; | ||
} | ||
|
||
// Sizes | ||
.isRootSizeSmall { | ||
@include box-field-sizes.size(small); | ||
} | ||
|
||
.isRootSizeMedium { | ||
@include box-field-sizes.size(medium); | ||
} | ||
|
||
.isRootSizeLarge { | ||
@include box-field-sizes.size(large); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import React from 'react'; | ||
|
||
export const InputGroupContext = React.createContext(null); |
Oops, something went wrong.