Chore: modal refactor
This commit is contained in:
34
src/components/ConfigProvider/ConfigProvider.tsx
Normal file
34
src/components/ConfigProvider/ConfigProvider.tsx
Normal 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>);
|
||||
};
|
||||
70
src/components/Modal/ModalController.tsx
Normal file
70
src/components/Modal/ModalController.tsx
Normal 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()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export { GFHeartIcon } from './GFHeartIcon/GFHeartIcon';
|
||||
export { FAIcon } from './FAIcon/FAIcon';
|
||||
export { Tooltip } from './Tooltip/Tooltip';
|
||||
export { ModalController } from './Modal/ModalController';
|
||||
|
||||
Reference in New Issue
Block a user