1import React, { FC } from 'react'; 2import { cx, css } from '@emotion/css'; 3import { GrafanaTheme } from '@grafana/data'; 4import { useTheme } from '../../themes'; 5import { InlineLabel } from './InlineLabel'; 6import { PopoverContent } from '../Tooltip/Tooltip'; 7import { FieldProps } from './Field'; 8import { getChildId } from '../../utils/reactUtils'; 9 10export interface Props extends Omit<FieldProps, 'css' | 'horizontal' | 'description' | 'error'> { 11 /** Content for the label's tooltip */ 12 tooltip?: PopoverContent; 13 /** Custom width for the label as a multiple of 8px */ 14 labelWidth?: number | 'auto'; 15 /** Make the field's child to fill the width of the row. Equivalent to setting `flex-grow:1` on the field */ 16 grow?: boolean; 17 /** Make field's background transparent */ 18 transparent?: boolean; 19 htmlFor?: string; 20} 21 22export const InlineField: FC<Props> = ({ 23 children, 24 label, 25 tooltip, 26 labelWidth = 'auto', 27 invalid, 28 loading, 29 disabled, 30 className, 31 htmlFor, 32 grow, 33 transparent, 34 ...htmlProps 35}) => { 36 const theme = useTheme(); 37 const styles = getStyles(theme, grow); 38 const inputId = htmlFor ?? getChildId(children); 39 40 const labelElement = 41 typeof label === 'string' ? ( 42 <InlineLabel width={labelWidth} tooltip={tooltip} htmlFor={inputId} transparent={transparent}> 43 {label} 44 </InlineLabel> 45 ) : ( 46 label 47 ); 48 49 return ( 50 <div className={cx(styles.container, className)} {...htmlProps}> 51 {labelElement} 52 {React.cloneElement(children, { invalid, disabled, loading })} 53 </div> 54 ); 55}; 56 57InlineField.displayName = 'InlineField'; 58 59const getStyles = (theme: GrafanaTheme, grow?: boolean) => { 60 return { 61 container: css` 62 display: flex; 63 flex-direction: row; 64 align-items: flex-start; 65 text-align: left; 66 position: relative; 67 flex: ${grow ? 1 : 0} 0 auto; 68 margin: 0 ${theme.spacing.xs} ${theme.spacing.xs} 0; 69 `, 70 }; 71}; 72