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