Files
Ashley Harrison 47f8717149 React: Use new JSX transform (#88802)
* update eslint, tsconfig + esbuild to handle new jsx transform

* remove thing that breaks the new jsx transform

* remove react imports

* adjust grafana-icons build

* is this the correct syntax?

* try this

* well this was much easier than expected...

* change grafana-plugin-configs webpack config

* fixes

* fix lockfile

* fix 2 more violations

* use path.resolve instead of require.resolve

* remove react import

* fix react imports

* more fixes

* remove React import

* remove import React from docs

* remove another react import
2024-06-25 12:43:47 +01:00

111 lines
2.9 KiB
TypeScript

import { css } from '@emotion/css';
import * as React from 'react';
import { StandardEditorProps, StringFieldConfigSettings, GrafanaTheme2 } from '@grafana/data';
import { config } from '@grafana/runtime';
import { stylesFactory, Button, Icon, Input } from '@grafana/ui';
type Props = StandardEditorProps<string[], StringFieldConfigSettings>;
interface State {
showAdd: boolean;
}
export class StringArrayEditor extends React.PureComponent<Props, State> {
state = {
showAdd: false,
};
onRemoveString = (index: number) => {
const { value, onChange } = this.props;
const copy = [...value];
copy.splice(index, 1);
onChange(copy);
};
onValueChange = (e: React.KeyboardEvent<HTMLInputElement> | React.FocusEvent<HTMLInputElement>, idx: number) => {
if ('key' in e) {
if (e.key !== 'Enter') {
return;
}
}
const { value, onChange } = this.props;
// Form event, or Enter
const v = e.currentTarget.value.trim();
if (idx < 0) {
if (v) {
e.currentTarget.value = ''; // reset last value
onChange([...value, v]);
}
this.setState({ showAdd: false });
return;
}
if (!v) {
return this.onRemoveString(idx);
}
const copy = [...value];
copy[idx] = v;
onChange(copy);
};
render() {
const { value, item } = this.props;
const { showAdd } = this.state;
const styles = getStyles(config.theme2);
const placeholder = item.settings?.placeholder || 'Add text';
return (
<div>
{value.map((v, index) => {
return (
<Input
className={styles.textInput}
key={`${index}/${v}`}
defaultValue={v || ''}
onBlur={(e) => this.onValueChange(e, index)}
onKeyDown={(e) => this.onValueChange(e, index)}
suffix={<Icon className={styles.trashIcon} name="trash-alt" onClick={() => this.onRemoveString(index)} />}
/>
);
})}
{showAdd ? (
<Input
autoFocus
className={styles.textInput}
placeholder={placeholder}
defaultValue={''}
onBlur={(e) => this.onValueChange(e, -1)}
onKeyDown={(e) => this.onValueChange(e, -1)}
suffix={<Icon name="plus-circle" />}
/>
) : (
<Button icon="plus" size="sm" variant="secondary" onClick={() => this.setState({ showAdd: true })}>
{placeholder}
</Button>
)}
</div>
);
}
}
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
textInput: css({
marginBottom: '5px',
'&:hover': {
border: `1px solid ${theme.components.input.borderHover}`,
},
}),
trashIcon: css({
color: theme.colors.text.secondary,
cursor: 'pointer',
'&:hover': {
color: theme.colors.text.primary,
},
}),
};
});