-
Nicolò Pretto authored
* fix(sdk): modal pushing content below when opened * render the portal below the content so we don't need the zIndex Co-authored-by:
Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev> --------- Co-authored-by:
Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
Nicolò Pretto authored* fix(sdk): modal pushing content below when opened * render the portal below the content so we don't need the zIndex Co-authored-by:
Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev> --------- Co-authored-by:
Mahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MetabaseProvider.tsx 3.48 KiB
import { Global } from "@emotion/react";
import type { Action, Store } from "@reduxjs/toolkit";
import { type JSX, type ReactNode, memo, useEffect } from "react";
import { Provider } from "react-redux";
import { SdkThemeProvider } from "embedding-sdk/components/private/SdkThemeProvider";
import { EMBEDDING_SDK_ROOT_ELEMENT_ID } from "embedding-sdk/config";
import { useInitData } from "embedding-sdk/hooks";
import type { SdkEventHandlersConfig } from "embedding-sdk/lib/events";
import type { SdkPluginsConfig } from "embedding-sdk/lib/plugins";
import { getSdkStore } from "embedding-sdk/store";
import {
setErrorComponent,
setEventHandlers,
setLoaderComponent,
setMetabaseClientUrl,
setPlugins,
} from "embedding-sdk/store/reducer";
import type { SdkStoreState } from "embedding-sdk/store/types";
import type { SDKConfig } from "embedding-sdk/types";
import type { MetabaseTheme } from "embedding-sdk/types/theme";
import { setOptions } from "metabase/redux/embed";
import { EmotionCacheProvider } from "metabase/styled-components/components/EmotionCacheProvider";
import { SCOPED_CSS_RESET } from "../private/PublicComponentStylesWrapper";
import { SdkFontsGlobalStyles } from "../private/SdkGlobalFontsStyles";
import { PortalContainer } from "../private/SdkPortalContainer";
import { SdkUsageProblemDisplay } from "../private/SdkUsageProblem";
import "metabase/css/index.module.css";
import "metabase/css/vendor.css";
export interface MetabaseProviderProps {
children: ReactNode;
config: SDKConfig;
pluginsConfig?: SdkPluginsConfig;
eventHandlers?: SdkEventHandlersConfig;
theme?: MetabaseTheme;
className?: string;
}
interface InternalMetabaseProviderProps extends MetabaseProviderProps {
store: Store<SdkStoreState, Action>;
}
export const MetabaseProviderInternal = ({
children,
config,
pluginsConfig,
eventHandlers,
theme,
store,
className,
}: InternalMetabaseProviderProps): JSX.Element => {
const { fontFamily } = theme ?? {};
useInitData({ config });
useEffect(() => {
if (fontFamily) {
store.dispatch(setOptions({ font: fontFamily }));
}
}, [store, fontFamily]);
useEffect(() => {
store.dispatch(setPlugins(pluginsConfig || null));
}, [store, pluginsConfig]);
useEffect(() => {
store.dispatch(setEventHandlers(eventHandlers || null));
}, [store, eventHandlers]);
useEffect(() => {
store.dispatch(setLoaderComponent(config.loaderComponent ?? null));
}, [store, config.loaderComponent]);
useEffect(() => {
store.dispatch(setErrorComponent(config.errorComponent ?? null));
}, [store, config.errorComponent]);
useEffect(() => {
store.dispatch(setMetabaseClientUrl(config.metabaseInstanceUrl));
}, [store, config.metabaseInstanceUrl]);
return (
<EmotionCacheProvider>
<Global styles={SCOPED_CSS_RESET} />
<SdkThemeProvider theme={theme}>
<SdkFontsGlobalStyles baseUrl={config.metabaseInstanceUrl} />
<div className={className} id={EMBEDDING_SDK_ROOT_ELEMENT_ID}>
{children}
<SdkUsageProblemDisplay config={config} />
<PortalContainer />
</div>
</SdkThemeProvider>
</EmotionCacheProvider>
);
};
export const MetabaseProvider = memo(function MetabaseProvider({
// @ts-expect-error -- we don't want to expose the store prop
// eslint-disable-next-line react/prop-types
store = getSdkStore(),
...props
}: MetabaseProviderProps) {
return (
<Provider store={store}>
<MetabaseProviderInternal store={store} {...props} />
</Provider>
);
});