@grafana/ui
Version:
Grafana Components Library
1 lines • 10.6 kB
Source Map (JSON)
{"version":3,"file":"Field.cjs","sources":["../../../../src/components/Forms/Field.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useId, type HTMLAttributes } from 'react';\nimport * as React from 'react';\n\nimport { type GrafanaTheme2 } from '@grafana/data';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { getChildId } from '../../utils/reactUtils';\n\nimport { FieldContext } from './FieldContext';\nimport { FieldValidationMessage } from './FieldValidationMessage';\nimport { Label, getLabelStyles } from './Label';\nimport { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup';\n\ntype ChildProps = Record<string, unknown>;\n\nexport interface FieldProps extends HTMLAttributes<HTMLElement> {\n /** Form input element, i.e Input or Switch */\n children: React.ReactElement<ChildProps>;\n /** Label for the field */\n label?: React.ReactNode;\n /** Description of the field */\n description?: React.ReactNode;\n /** Indicates if field is in invalid state */\n invalid?: boolean;\n /** Indicates if field is in loading state */\n loading?: boolean;\n /** Indicates if field is disabled */\n disabled?: boolean;\n /** Indicates if field is required */\n required?: boolean;\n /** Error message to display */\n error?: React.ReactNode;\n /** Indicates horizontal layout of the field */\n horizontal?: boolean;\n /** make validation message overflow horizontally. Prevents pushing out adjacent inline components */\n validationMessageHorizontalOverflow?: boolean;\n /** Whether to use a <fieldset> + <legend> for rendering the label. Only use for RadioButtonGroup */\n useFieldset?: boolean;\n\n className?: string;\n /**\n * A unique id that associates the label of the Field component with the control with the unique id.\n * If the `htmlFor` property is missing the `htmlFor` will be inferred from the `id` or `inputId` property of the first child.\n * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for\n */\n htmlFor?: string;\n /** Remove the bottom margin */\n noMargin?: boolean;\n}\n\n/**\n * Field is the basic component for rendering form elements together with labels and description.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/forms-field--docs\n */\nexport const Field = React.forwardRef<HTMLDivElement, FieldProps>(\n (\n {\n label: labelProp,\n description,\n horizontal,\n invalid,\n loading,\n disabled,\n required,\n error,\n children,\n className,\n validationMessageHorizontalOverflow,\n htmlFor,\n noMargin,\n useFieldset: useFieldsetProp,\n ...otherProps\n }: FieldProps,\n ref\n ) => {\n const styles = useStyles2(getFieldStyles, noMargin);\n const labelStyles = useStyles2(getLabelStyles);\n const useFieldset = useFieldsetProp ?? children.type === RadioButtonGroup;\n const label = typeof labelProp === 'string' ? `${labelProp}${required ? ' *' : ''}` : labelProp;\n const fieldId = useId();\n const errorId = useId();\n const inputId = htmlFor ?? getChildId(children) ?? fieldId;\n\n let labelElement = label;\n\n if (useFieldset) {\n if (typeof label === 'string') {\n labelElement = (\n <legend className={labelStyles.label}>\n <div className={labelStyles.labelContent}>{label}</div>\n {description && <span className={labelStyles.description}>{description}</span>}\n </legend>\n );\n } else {\n labelElement = <legend className={labelStyles.label}>{label}</legend>;\n }\n } else if (typeof label === 'string') {\n labelElement = (\n <Label htmlFor={inputId} description={description}>\n {label}\n </Label>\n );\n }\n\n // @deprecated — passing props via children is discouraged and will be removed at some point, use FieldContext instead\n const childProps: ChildProps = deleteUndefinedProps({ invalid, disabled, loading });\n if (invalid && error) {\n // this should probably use aria-errormessage, but seems like voiceover still doesn't support that...\n childProps['aria-describedby'] = errorId;\n }\n const Wrapper = useFieldset ? 'fieldset' : 'div';\n return (\n <FieldContext.Provider\n value={{\n id: inputId,\n invalid,\n disabled,\n loading,\n 'aria-describedby': invalid && error ? errorId : undefined,\n }}\n >\n <Wrapper className={cx(styles.field, horizontal && styles.fieldHorizontal, className)} {...otherProps}>\n {labelElement}\n <div>\n <div ref={ref}>\n {React.cloneElement(children, children.type !== React.Fragment ? childProps : undefined)}\n </div>\n {invalid && error && !horizontal && (\n <div\n className={cx(styles.fieldValidationWrapper, {\n [styles.validationMessageHorizontalOverflow]: !!validationMessageHorizontalOverflow,\n })}\n >\n <FieldValidationMessage id={errorId}>{error}</FieldValidationMessage>\n </div>\n )}\n </div>\n\n {invalid && error && horizontal && (\n <div\n className={cx(styles.fieldValidationWrapper, styles.fieldValidationWrapperHorizontal, {\n [styles.validationMessageHorizontalOverflow]: !!validationMessageHorizontalOverflow,\n })}\n >\n <FieldValidationMessage id={errorId}>{error}</FieldValidationMessage>\n </div>\n )}\n </Wrapper>\n </FieldContext.Provider>\n );\n }\n);\n\nField.displayName = 'Field';\n\nfunction deleteUndefinedProps<T extends Object>(obj: T): Partial<T> {\n for (const key in obj) {\n if (obj[key] === undefined) {\n delete obj[key];\n }\n }\n\n return obj;\n}\n\nconst getFieldStyles = (theme: GrafanaTheme2, noMargin?: boolean) => ({\n field: css({\n display: 'flex',\n flexDirection: 'column',\n marginBottom: theme.spacing(noMargin ? 0 : 2),\n }),\n fieldHorizontal: css({\n flexDirection: 'row',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n }),\n fieldValidationWrapper: css({\n marginTop: theme.spacing(0.5),\n }),\n fieldValidationWrapperHorizontal: css({\n flex: '1 1 100%',\n }),\n validationMessageHorizontalOverflow: css({\n width: 0,\n overflowX: 'visible',\n\n '& > *': {\n whiteSpace: 'nowrap',\n },\n }),\n});\n"],"names":["React","useStyles2","getLabelStyles","RadioButtonGroup","useId","getChildId","jsxs","jsx","Label","FieldContext","cx","FieldValidationMessage","css"],"mappings":"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"}