grafana/ui: Export types and utils required by grafana/experimental (#42133)

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
Dominik Prokop 2021-11-23 15:41:51 +01:00 committed by GitHub
parent 694600ed04
commit d2d38c978f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 43 additions and 37 deletions

View File

@ -4,7 +4,7 @@ import { stylesFactory, useTheme2 } from '../../themes';
import { css, cx } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { FieldValidationMessage } from './FieldValidationMessage';
import { getChildId } from '../../utils/children';
import { getChildId } from '../../utils/reactUtils';
export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
/** Form input element, i.e Input or Switch */

View File

@ -5,7 +5,7 @@ import { useTheme } from '../../themes';
import { InlineLabel } from './InlineLabel';
import { PopoverContent } from '../Tooltip/Tooltip';
import { FieldProps } from './Field';
import { getChildId } from '../../utils/children';
import { getChildId } from '../../utils/reactUtils';
export interface Props extends Omit<FieldProps, 'css' | 'horizontal' | 'description' | 'error'> {
/** Content for the label's tooltip */

View File

@ -2,6 +2,7 @@ import React from 'react';
import { SelectableValue } from '@grafana/data';
import { SelectCommonProps, MultiSelectCommonProps, SelectAsyncProps } from './types';
import { SelectBase } from './SelectBase';
import { SelectContainer, SelectContainerProps } from './SelectContainer';
export function Select<T>(props: SelectCommonProps<T>) {
return <SelectBase {...props} />;
@ -31,3 +32,5 @@ export function AsyncMultiSelect<T>(props: AsyncMultiSelectProps<T>) {
// @ts-ignore
return <SelectBase {...props} isMulti />;
}
export { SelectContainer, SelectContainerProps };

View File

@ -9,13 +9,13 @@ import { focusCss } from '../../themes/mixins';
import { components, ContainerProps as BaseContainerProps, GroupBase } from 'react-select';
// isFocus prop is actually available, but its not in the types for the version we have.
export interface ContainerProps<Option, isMulti extends boolean, Group extends GroupBase<Option>>
export interface SelectContainerProps<Option, isMulti extends boolean, Group extends GroupBase<Option>>
extends BaseContainerProps<Option, isMulti, Group> {
isFocused: boolean;
}
export const SelectContainer = <Option, isMulti extends boolean, Group extends GroupBase<Option>>(
props: ContainerProps<Option, isMulti, Group>
props: SelectContainerProps<Option, isMulti, Group>
) => {
const { isDisabled, isFocused, children } = props;

View File

@ -201,6 +201,7 @@ export { selectOptionInTest } from './Select/test-utils';
export * from './Select/Select';
export { DropdownIndicator } from './Select/DropdownIndicator';
export { getSelectStyles } from './Select/getSelectStyles';
export * from './Select/types';
export { HorizontalGroup, VerticalGroup, Container } from './Layout/Layout';
export { Badge, BadgeColor, BadgeProps } from './Badge/Badge';

View File

@ -12,8 +12,12 @@ export { ansicolor } from 'ansicolor';
import * as DOMUtil from './dom'; // includes Element.closest polyfill
export { DOMUtil };
export { renderOrCallToRender } from './renderOrCallToRender';
export { createLogger } from './logger';
export { attachDebugger } from './debug';
export * from './nodeGraph';
export { fuzzyMatch } from './fuzzy';
// React utils
import * as ReactUtils from './reactUtils';
export { ReactUtils };

View File

@ -17,3 +17,24 @@ export function getChildId(children: ReactElement): string | undefined {
return typeof inputId === 'string' ? inputId : undefined;
}
/**
* Given react node or function returns element accordingly
*
* @param itemToRender
* @param props props to be passed to the function if item provided as such
*/
export function renderOrCallToRender<TProps = any>(
itemToRender: ((props?: TProps) => React.ReactNode) | React.ReactNode,
props?: TProps
): React.ReactNode {
if (React.isValidElement(itemToRender) || typeof itemToRender === 'string' || typeof itemToRender === 'number') {
return itemToRender;
}
if (typeof itemToRender === 'function') {
return itemToRender(props);
}
throw new Error(`${itemToRender} is not a React element nor a function that returns React element`);
}

View File

@ -1,22 +0,0 @@
import React from 'react';
/**
* Given react node or function returns element accordingly
*
* @param itemToRender
* @param props props to be passed to the function if item provided as such
*/
export function renderOrCallToRender<TProps = any>(
itemToRender: ((props?: TProps) => React.ReactNode) | React.ReactNode,
props?: TProps
): React.ReactNode {
if (React.isValidElement(itemToRender) || typeof itemToRender === 'string' || typeof itemToRender === 'number') {
return itemToRender;
}
if (typeof itemToRender === 'function') {
return itemToRender(props);
}
throw new Error(`${itemToRender} is not a React element nor a function that returns React element`);
}

View File

@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react';
import { Icon, renderOrCallToRender, stylesFactory, useTheme } from '@grafana/ui';
import { Icon, ReactUtils, stylesFactory, useTheme } from '@grafana/ui';
import { GrafanaTheme } from '@grafana/data';
import { css, cx } from '@emotion/css';
import { useUpdateEffect } from 'react-use';
@ -69,9 +69,9 @@ export const QueryOperationRow: React.FC<QueryOperationRowProps> = ({
},
};
const titleElement = title && renderOrCallToRender(title, renderPropArgs);
const actionsElement = actions && renderOrCallToRender(actions, renderPropArgs);
const headerElementRendered = headerElement && renderOrCallToRender(headerElement, renderPropArgs);
const titleElement = title && ReactUtils.renderOrCallToRender(title, renderPropArgs);
const actionsElement = actions && ReactUtils.renderOrCallToRender(actions, renderPropArgs);
const headerElementRendered = headerElement && ReactUtils.renderOrCallToRender(headerElement, renderPropArgs);
const rowHeader = (
<div className={styles.header}>

View File

@ -1,7 +1,6 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Field, Icon, PopoverContent, stylesFactory, Tooltip, useTheme2 } from '@grafana/ui';
import { getChildId } from '@grafana/ui/src/utils/children';
import { Field, Icon, PopoverContent, stylesFactory, Tooltip, useTheme2, ReactUtils } from '@grafana/ui';
import { Space } from 'app/plugins/datasource/grafana-azure-monitor-datasource/components/Space';
import React from 'react';
@ -18,7 +17,7 @@ const EditorField: React.FC<EditorFieldProps> = (props) => {
const theme = useTheme2();
const styles = getStyles(theme, props);
const childInputId = getChildId(children);
const childInputId = ReactUtils.getChildId(children);
const labelEl = (
<>

View File

@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { Select, stylesFactory, useTheme2 } from '@grafana/ui';
import {
ContainerProps,
SelectContainerProps,
SelectContainer as BaseSelectContainer,
} from '@grafana/ui/src/components/Select/SelectContainer';
import { SelectCommonProps } from '@grafana/ui/src/components/Select/types';
@ -39,7 +39,7 @@ function InlineSelect<T>({ label: labelProp, ...props }: InlineSelectProps<T>) {
export default InlineSelect;
const SelectContainer = <Option, isMulti extends boolean, Group extends GroupBase<Option>>(
props: ContainerProps<Option, isMulti, Group>
props: SelectContainerProps<Option, isMulti, Group>
) => {
const { children } = props;
@ -54,7 +54,7 @@ const SelectContainer = <Option, isMulti extends boolean, Group extends GroupBas
};
const ValueContainer = <Option, isMulti extends boolean, Group extends GroupBase<Option>>(
props: ContainerProps<Option, isMulti, Group>
props: SelectContainerProps<Option, isMulti, Group>
) => {
const { className, children } = props;
const theme = useTheme2();