diff --git a/packages/grafana-ui/src/components/Segment/Segment.story.tsx b/packages/grafana-ui/src/components/Segment/Segment.story.tsx index 949e3cdadac..9de2b52933d 100644 --- a/packages/grafana-ui/src/components/Segment/Segment.story.tsx +++ b/packages/grafana-ui/src/components/Segment/Segment.story.tsx @@ -80,6 +80,38 @@ SegmentStories.add('Grouped Array Options', () => { ); }); +SegmentStories.add('With custom options allowed', () => { + const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption); + return ( + + {(value, updateValue) => ( + <> +
+
+ Segment Name +
+ ) => { + updateValue(value); + action('Segment value changed')(value); + }} + /> + ) => action('New value added')(value)} + options={options} + /> +
+ + )} +
+ ); +}); + const CustomLabelComponent = ({ value }: any) =>
custom({value})
; SegmentStories.add('Custom Label Field', () => { diff --git a/packages/grafana-ui/src/components/Segment/Segment.tsx b/packages/grafana-ui/src/components/Segment/Segment.tsx index 9f064549634..6d4b062fd48 100644 --- a/packages/grafana-ui/src/components/Segment/Segment.tsx +++ b/packages/grafana-ui/src/components/Segment/Segment.tsx @@ -13,6 +13,7 @@ export function Segment({ onChange, Component, className, + allowCustomValue, }: React.PropsWithChildren>) { const [Label, width, expanded, setExpanded] = useExpandableLabel(false); @@ -25,6 +26,7 @@ export function Segment({ width={width} options={options} onClickOutside={() => setExpanded(false)} + allowCustomValue={allowCustomValue} onChange={value => { setExpanded(false); onChange(value); diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx index cee3b401528..75aa2ec4c3e 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx @@ -81,8 +81,39 @@ SegmentStories.add('Grouped Array Options', () => { ); }); -const CustomLabelComponent = ({ value }: any) =>
custom({value})
; +SegmentStories.add('With custom options allowed', () => { + const options = ['Option1', 'Option2', 'OptionWithLooongLabel', 'Option4'].map(toOption); + return ( + + {(value, updateValue) => ( + <> +
+
+ Segment Name +
+ loadOptions(options)} + onChange={value => { + updateValue(value); + action('Segment value changed')(value); + }} + /> + action('New value added')(value)} + loadOptions={() => loadOptions(options)} + /> +
+ + )} +
+ ); +}); +const CustomLabelComponent = ({ value }: any) =>
custom({value})
; SegmentStories.add('Custom Label Field', () => { return ( diff --git a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx index cf529cf55c8..599441b0442 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentAsync.tsx @@ -14,6 +14,7 @@ export function SegmentAsync({ loadOptions, Component, className, + allowCustomValue, }: React.PropsWithChildren>) { const [selectPlaceholder, setSelectPlaceholder] = useState(''); const [loadedOptions, setLoadedOptions] = useState>>([]); @@ -38,6 +39,7 @@ export function SegmentAsync({ width={width} options={loadedOptions} noOptionsMessage={selectPlaceholder} + allowCustomValue={allowCustomValue} onClickOutside={() => { setSelectPlaceholder(''); setLoadedOptions([]); diff --git a/packages/grafana-ui/src/components/Segment/SegmentSelect.tsx b/packages/grafana-ui/src/components/Segment/SegmentSelect.tsx index f0c5a643b3d..de3aaa64f46 100644 --- a/packages/grafana-ui/src/components/Segment/SegmentSelect.tsx +++ b/packages/grafana-ui/src/components/Segment/SegmentSelect.tsx @@ -10,6 +10,7 @@ export interface Props { onClickOutside: () => void; width: number; noOptionsMessage?: string; + allowCustomValue?: boolean; } export function SegmentSelect({ @@ -18,6 +19,7 @@ export function SegmentSelect({ onClickOutside, width, noOptionsMessage = '', + allowCustomValue = false, }: React.PropsWithChildren>) { const ref = useRef(null); @@ -39,6 +41,7 @@ export function SegmentSelect({ isOpen={true} onChange={({ value }) => onChange(value!)} options={options} + allowCustomValue={allowCustomValue} /> ); diff --git a/packages/grafana-ui/src/components/Segment/types.ts b/packages/grafana-ui/src/components/Segment/types.ts index 792c6dfb23d..89d809c7777 100644 --- a/packages/grafana-ui/src/components/Segment/types.ts +++ b/packages/grafana-ui/src/components/Segment/types.ts @@ -5,4 +5,5 @@ export interface SegmentProps { value?: T; Component?: ReactElement; className?: string; + allowCustomValue?: boolean; } diff --git a/packages/grafana-ui/src/components/Select/Select.story.tsx b/packages/grafana-ui/src/components/Select/Select.story.tsx index 27601611c5d..6532b250230 100644 --- a/packages/grafana-ui/src/components/Select/Select.story.tsx +++ b/packages/grafana-ui/src/components/Select/Select.story.tsx @@ -36,3 +36,30 @@ SelectStories.add('default', () => { ); }); + +SelectStories.add('With allowCustomValue', () => { + const intialState: SelectableValue = { label: 'A label', value: 'A value' }; + const value = object>('Selected Value:', intialState); + const options = object>>('Options:', [ + intialState, + { label: 'Another label', value: 'Another value' }, + ]); + + return ( + + {(value, updateValue) => { + return ( +