mirror of https://github.com/grafana/grafana
UI: Segment Input (#20904)
* Add input segment * Rename story * Cleanup * Fix lint error * More cleanup * Export ui component * Use measure text utilpull/20924/head
parent
a533e00622
commit
047abc87c2
@ -0,0 +1,29 @@ |
||||
import React from 'react'; |
||||
import { storiesOf } from '@storybook/react'; |
||||
import { action } from '@storybook/addon-actions'; |
||||
const SegmentStories = storiesOf('UI/Segment/SegmentInput', module); |
||||
import { SegmentInput } from '.'; |
||||
import { UseState } from '../../utils/storybook/UseState'; |
||||
|
||||
SegmentStories.add('Segment Input', () => { |
||||
return ( |
||||
<UseState initialState={'some text'}> |
||||
{(value, updateValue) => ( |
||||
<> |
||||
<div className="gf-form-inline"> |
||||
<div className="gf-form"> |
||||
<span className="gf-form-label width-8 query-keyword">Segment Name</span> |
||||
</div> |
||||
<SegmentInput |
||||
value={value} |
||||
onChange={text => { |
||||
updateValue(text as string); |
||||
action('Segment value changed')(text); |
||||
}} |
||||
/> |
||||
</div> |
||||
</> |
||||
)} |
||||
</UseState> |
||||
); |
||||
}); |
||||
@ -0,0 +1,48 @@ |
||||
import React, { useRef, useState } from 'react'; |
||||
import { cx, css } from 'emotion'; |
||||
import useClickAway from 'react-use/lib/useClickAway'; |
||||
import { measureText } from '../../utils/measureText'; |
||||
import { useExpandableLabel, SegmentProps } from '.'; |
||||
|
||||
export interface SegmentInputProps<T> extends SegmentProps<T> { |
||||
value: string | number; |
||||
onChange: (text: string | number) => void; |
||||
} |
||||
|
||||
const FONT_SIZE = 14; |
||||
|
||||
export function SegmentInput<T>({ |
||||
value, |
||||
onChange, |
||||
Component, |
||||
className, |
||||
}: React.PropsWithChildren<SegmentInputProps<T>>) { |
||||
const ref = useRef(null); |
||||
const [inputWidth, setInputWidth] = useState<number>(measureText(value.toString(), FONT_SIZE).width); |
||||
const [Label, , expanded, setExpanded] = useExpandableLabel(false); |
||||
useClickAway(ref, () => setExpanded(false)); |
||||
|
||||
if (!expanded) { |
||||
return <Label Component={Component || <a className={cx('gf-form-label', 'query-part', className)}>{value}</a>} />; |
||||
} |
||||
|
||||
const inputWidthStyle = css` |
||||
width: ${Math.max(inputWidth + 20, 32)}px; |
||||
`;
|
||||
|
||||
return ( |
||||
<input |
||||
ref={ref} |
||||
autoFocus |
||||
className={cx(`gf-form gf-form-input`, inputWidthStyle)} |
||||
value={value} |
||||
onChange={item => { |
||||
const { width } = measureText(item.target.value, FONT_SIZE); |
||||
setInputWidth(width); |
||||
onChange(item.target.value); |
||||
}} |
||||
onBlur={() => setExpanded(false)} |
||||
onKeyDown={e => [13, 27].includes(e.keyCode) && setExpanded(false)} |
||||
/> |
||||
); |
||||
} |
||||
@ -1,5 +1,6 @@ |
||||
export { Segment } from './Segment'; |
||||
export { SegmentAsync } from './SegmentAsync'; |
||||
export { SegmentSelect } from './SegmentSelect'; |
||||
export { SegmentInput } from './SegmentInput'; |
||||
export { SegmentProps } from './types'; |
||||
export { useExpandableLabel } from './useExpandableLabel'; |
||||
|
||||
Loading…
Reference in new issue