@zendeskgarden/container-field
Version:
Containers relating to field in the Garden Design System
104 lines (99 loc) • 2.69 kB
JavaScript
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/
import React, { useCallback, useMemo } from 'react';
import { useId } from '@zendeskgarden/container-utilities';
import PropTypes from 'prop-types';
const useField = ({
idPrefix,
hasHint,
hasMessage
}) => {
const prefix = useId(idPrefix);
const inputId = `${prefix}--input`;
const labelId = `${prefix}--label`;
const hintId = `${prefix}--hint`;
const messageId = `${prefix}--message`;
const getLabelProps = useCallback(({
id = labelId,
htmlFor = inputId,
...other
} = {}) => ({
'data-garden-container-id': 'containers.field.label',
'data-garden-container-version': '3.0.22',
id,
htmlFor,
...other
}), [labelId, inputId]);
const getHintProps = useCallback(({
id = hintId,
...other
} = {}) => ({
'data-garden-container-id': 'containers.field.hint',
'data-garden-container-version': '3.0.22',
id,
...other
}), [hintId]);
const getInputProps = useCallback(({
id = inputId,
'aria-describedby': ariaDescribedBy,
...other
} = {}) => {
const getDescribedBy = () => {
if (ariaDescribedBy) {
return ariaDescribedBy;
}
const describedBy = [];
if (hasHint) {
describedBy.push(hintId);
}
if (hasMessage) {
describedBy.push(messageId);
}
return describedBy.length > 0 ? describedBy.join(' ') : undefined;
};
return {
'data-garden-container-id': 'containers.field.input',
'data-garden-container-version': '3.0.22',
id,
'aria-labelledby': labelId,
'aria-describedby': getDescribedBy(),
...other
};
}, [inputId, labelId, hintId, messageId, hasHint, hasMessage]);
const getMessageProps = useCallback(({
id = messageId,
role = 'alert',
...other
} = {}) => ({
'data-garden-container-id': 'containers.field.message',
'data-garden-container-version': '3.0.22',
role: role === null ? undefined : role,
id,
...other
}), [messageId]);
return useMemo(() => ({
getLabelProps,
getHintProps,
getInputProps,
getMessageProps
}), [getLabelProps, getHintProps, getInputProps, getMessageProps]);
};
const FieldContainer = ({
children,
render = children,
...options
}) => {
return React.createElement(React.Fragment, null, render(useField(options)));
};
FieldContainer.propTypes = {
children: PropTypes.func,
render: PropTypes.func,
idPrefix: PropTypes.string,
hasHint: PropTypes.bool,
hasMessage: PropTypes.bool
};
export { FieldContainer, useField };