Chore: modal refactor

This commit is contained in:
Alexander Zobnin
2020-05-19 17:31:03 +03:00
parent 0c2197e4ad
commit f6e127e55c
7 changed files with 280 additions and 154 deletions

View File

@@ -0,0 +1,34 @@
import React from 'react';
import { config, GrafanaBootConfig } from '@grafana/runtime';
import { ThemeContext, getTheme } from '@grafana/ui';
import { GrafanaThemeType } from '@grafana/data';
export const ConfigContext = React.createContext<GrafanaBootConfig>(config);
export const ConfigConsumer = ConfigContext.Consumer;
export const provideConfig = (component: React.ComponentType<any>) => {
const ConfigProvider = (props: any) => (
<ConfigContext.Provider value={config}>{React.createElement(component, { ...props })}</ConfigContext.Provider>
);
return ConfigProvider;
};
export const getCurrentThemeName = () =>
config.bootData.user.lightTheme ? GrafanaThemeType.Light : GrafanaThemeType.Dark;
export const getCurrentTheme = () => getTheme(getCurrentThemeName());
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
return (
<ConfigConsumer>
{config => {
return <ThemeContext.Provider value={getCurrentTheme()}>{children}</ThemeContext.Provider>;
}}
</ConfigConsumer>
);
};
export const provideTheme = (component: React.ComponentType<any>) => {
return provideConfig((props: any) => <ThemeProvider>{React.createElement(component, { ...props })}</ThemeProvider>);
};

View File

@@ -0,0 +1,70 @@
import React, { FC } from 'react';
import ReactDOM from 'react-dom';
import { provideTheme } from '../ConfigProvider/ConfigProvider';
interface ModalWrapperProps {
showModal: <T>(component: React.ComponentType<T>, props: T) => void;
hideModal: () => void;
}
type ModalWrapper<T> = FC<ModalWrapperProps>;
interface Props {
children: ModalWrapper<any>;
}
interface State {
component: React.ComponentType<any> | null;
props: any;
}
export class ModalController extends React.Component<Props, State> {
modalRoot = document.body;
modalNode = document.createElement('div');
constructor(props: Props) {
super(props);
this.state = {
component: null,
props: {},
};
}
showModal = (component: React.ComponentType<any>, props: any) => {
this.setState({
component,
props
});
};
hideModal = () => {
this.modalRoot.removeChild(this.modalNode);
this.setState({
component: null,
props: {},
});
};
renderModal() {
const { component, props } = this.state;
if (!component) {
return null;
}
this.modalRoot.appendChild(this.modalNode);
const modal = React.createElement(provideTheme(component), props);
return ReactDOM.createPortal(modal, this.modalNode);
}
render() {
const { children } = this.props;
const ChildrenComponent = children;
return (
<>
<ChildrenComponent showModal={this.showModal} hideModal={this.hideModal} />
{this.renderModal()}
</>
);
}
}

View File

@@ -1,3 +1,4 @@
export { GFHeartIcon } from './GFHeartIcon/GFHeartIcon';
export { FAIcon } from './FAIcon/FAIcon';
export { Tooltip } from './Tooltip/Tooltip';
export { ModalController } from './Modal/ModalController';