Config Provider
Installation
npx shadcn@latest add http://fumastudio/com/r/config-provider.json"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { createContext, type ReactNode, useContext } from "react";
const queryClient = new QueryClient();
export type Socials = {
href: string;
label: string;
iconUrl: string;
};
export interface CopyPageDropdown {
id: string;
label: string;
description: string;
url?: string;
icon?: React.ReactNode;
}
type CopyPageOptions = {
enabled: boolean;
enableDropdown?: boolean;
dropdown?: CopyPageDropdown[];
};
export type Settings = {
enableTryItButton?: boolean;
poweredBy?: ReactNode | null;
socials?: Socials[];
copyPage?: CopyPageOptions;
};
const ConfigContext = createContext<Settings | null>(null);
const defaultConfig: Settings = {
enableTryItButton: false,
poweredBy: null,
socials: [],
copyPage: {
enabled: true,
enableDropdown: true,
dropdown: [],
},
};
export function ConfigProvider(props: {
children: ReactNode;
config: Settings | null;
}) {
return (
<ConfigContext.Provider
value={props.config ? props.config : defaultConfig}>
{props.children}
</ConfigContext.Provider>
);
}
export const useConfig = () => {
const ctx = useContext(ConfigContext);
if (!ctx)
throw new Error(
"useSettings must be used inside <SettingsProvider />",
);
return ctx;
};
export function TanstackProvider(props: { children: React.ReactNode }) {
return (
<QueryClientProvider client={queryClient}>
{props.children}
</QueryClientProvider>
);
}
Usage
import { TanstackProvider } from "@/components/fumastudio/config-provider";
export default function Layout({ children }: { children: ReactNode }) {
return (
<html
lang="en"
className="antialiased"
suppressHydrationWarning>
<body className="min-h-screen ">
<TanstackProvider>
{children}
<Toaster />
</TanstackProvider>
</body>
</html>
);
}Usage
import { source } from "@/lib/source";
import { useMDXComponents } from "@/mdx-components";
import { ConfigProvider } from "@/components/fumastudio/config-provider";
type PageParams = { slug: string[] };
type PageProps = {
params: Promise<PageParams>;
};
export default async function Page(props: PageProps) {
const params = await props.params;
const src = await source.getPage(params.slug);
if (!src) {
return notFound();
}
const MDX = src.data.body;
const pageTree = source.getPageTree();
const schemes = await source.getSchemes(params.slug);
return (
<SidebarProvider>
<PageTree tree={pageTree} />
<SidebarInset>
<div className="flex items-center h-14 gap-2 px-4 border-b shrink-0">
<div className="flex items-center">
<SidebarTrigger className="ml-1.5" />
<Separator
orientation="vertical"
className="mr-2 data-[orientation=vertical]:h-4"
/>
</div>
<div className="flex items-center ml-auto">
<SearchDialog />
<ThemeSelector />
</div>
</div>
<ConfigProvider config={config}>
<div className="flex flex-col flex-1 gap-4 pt-24 mx-auto w-full max-w-[70rem] px-16 md:max-w-[60rem] md:px-24 group is-api-page">
<MDX
schemes={schemes}
components={useMDXComponents()}
/>
</div>
</ConfigProvider>
</SidebarInset>
</SidebarProvider>
);
}