1import { css, cx } from '@emotion/css';
2import { GrafanaTheme2 } from '@grafana/data';
3import { Select, stylesFactory, useTheme2 } from '@grafana/ui';
4import {
5  SelectContainerProps,
6  SelectContainer as BaseSelectContainer,
7} from '@grafana/ui/src/components/Select/SelectContainer';
8import { SelectCommonProps } from '@grafana/ui/src/components/Select/types';
9import React, { useState } from 'react';
10import { GroupTypeBase } from 'react-select';
11
12interface InlineSelectProps<T> extends SelectCommonProps<T> {
13  label?: string;
14}
15
16function InlineSelect<T>({ label: labelProp, ...props }: InlineSelectProps<T>) {
17  const theme = useTheme2();
18  const [id] = useState(() => Math.random().toString(16).slice(2));
19  const styles = getSelectStyles(theme);
20  const components = {
21    SelectContainer,
22    ValueContainer,
23    SingleValue: ValueContainer,
24  };
25
26  return (
27    <div className={styles.root}>
28      {labelProp && (
29        <label className={styles.label} htmlFor={id}>
30          {labelProp}
31          {':'}&nbsp;
32        </label>
33      )}
34      <Select openMenuOnFocus inputId={id} {...props} width="auto" components={components} />
35    </div>
36  );
37}
38
39export default InlineSelect;
40
41const SelectContainer = <Option, isMulti extends boolean, Group extends GroupTypeBase<Option>>(
42  props: SelectContainerProps<Option, isMulti, Group>
43) => {
44  const { children } = props;
45
46  const theme = useTheme2();
47  const styles = getSelectStyles(theme);
48
49  return (
50    <BaseSelectContainer {...props} className={cx(props.className, styles.container)}>
51      {children}
52    </BaseSelectContainer>
53  );
54};
55
56const ValueContainer = <Option, isMulti extends boolean, Group extends GroupTypeBase<Option>>(
57  props: SelectContainerProps<Option, isMulti, Group>
58) => {
59  const { className, children } = props;
60  const theme = useTheme2();
61  const styles = getSelectStyles(theme);
62
63  return <div className={cx(className, styles.valueContainer)}>{children}</div>;
64};
65
66const getSelectStyles = stylesFactory((theme: GrafanaTheme2) => ({
67  root: css({
68    display: 'flex',
69    fontSize: 12,
70    alignItems: 'center',
71  }),
72
73  label: css({
74    color: theme.colors.text.secondary,
75  }),
76
77  container: css({
78    background: 'none',
79    borderColor: 'transparent',
80  }),
81
82  valueContainer: css({
83    display: 'flex',
84    alignItems: 'center',
85    flex: 'initial',
86    color: theme.colors.text.secondary,
87    fontSize: 12,
88  }),
89}));
90