Skip to main content
Glama

Fonoster MCP Server

Official
by fonoster
MIT License
118
7,325
  • Apple
  • Linux
preview.tsx6.13 kB
/* * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com) * http://github.com/fonoster/fonoster * * This file is part of Fonoster * * Licensed under the MIT License (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://opensource.org/licenses/MIT * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import type { Preview } from "@storybook/react"; import React, { useEffect } from "react"; import { ThemeProvider, useThemeMode } from "../src/core/providers/styling/mui.provider"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { FormProvider, useForm } from "react-hook-form"; import { FormProvider as FonosterFormProvider } from "../src/core/contexts/form-context"; import { FormFieldContext, FormItemContext } from "../src/core/components/design-system/forms/form.context"; import fonosterTheme from "./fonoster-theme"; import { create } from "@storybook/theming/create"; import "../src/app.css"; // Create dynamic Storybook themes const createStorybookTheme = (mode: "light" | "dark") => { return create({ base: mode, brandTitle: "Fonoster Design System", brandUrl: "https://fonoster.com", brandTarget: "_self", colorPrimary: "#39E19E", colorSecondary: mode === "dark" ? "#CCEFE1" : "#053204", // UI appBg: mode === "dark" ? "#181818" : "#ffffff", appContentBg: mode === "dark" ? "#181818" : "#ffffff", appBorderColor: mode === "dark" ? "#555555" : "#E5E5E5", appBorderRadius: 8, // Typography fontBase: '"Inter", sans-serif', fontCode: "monospace", // Text colors textColor: mode === "dark" ? "#FFFFFF" : "#1A1A1A", textInverseColor: mode === "dark" ? "#1A1A1A" : "#ffffff", // Toolbar colors barTextColor: mode === "dark" ? "#FFFFFF" : "#1A1A1A", barSelectedColor: "#39E19E", barBg: mode === "dark" ? "#252525" : "#ffffff", // Form colors inputBg: mode === "dark" ? "#252525" : "#ffffff", inputBorder: mode === "dark" ? "#555555" : "#E5E5E5", inputTextColor: mode === "dark" ? "#FFFFFF" : "#1A1A1A", inputBorderRadius: 8 }); }; // Component to provide form context for Storybook const FormProviderWrapper = ({ children }: { children: React.ReactNode }) => { const methods = useForm({ defaultValues: { // Default values for common form fields name: "", email: "", description: "", value: "", username: "", password: "", confirmPassword: "", phone: "", address: "" // Add more default values as needed } }); return ( <FormProvider {...methods}> <FonosterFormProvider>{children}</FonosterFormProvider> </FormProvider> ); }; // Component to auto-wrap form components with necessary contexts const FormFieldWrapper = ({ children }: { children: React.ReactNode }) => { const methods = useForm({ defaultValues: { storybook_field: "" } }); return ( <FormProvider {...methods}> <FonosterFormProvider> <FormFieldContext.Provider value={{ name: "storybook_field" }}> <FormItemContext.Provider value={{ id: "storybook-field-id" }}> {children} </FormItemContext.Provider> </FormFieldContext.Provider> </FonosterFormProvider> </FormProvider> ); }; // Component to sync Storybook theme with MUI theme const ThemeSync = ({ theme, children }: { theme: string; children: React.ReactNode; }) => { const { changeTheme } = useThemeMode(); useEffect(() => { changeTheme(theme as "light" | "dark"); }, [theme, changeTheme]); return <>{children}</>; }; const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); const preview: Preview = { parameters: { docs: { theme: fonosterTheme // Default theme, will be overridden dynamically }, actions: { argTypesRegex: "^on[A-Z].*" }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/i } }, backgrounds: { disable: true }, layout: "centered" }, decorators: [ (Story, context) => { const theme = context.globals.theme || "light"; // Update docs theme dynamically context.parameters.docs = { ...context.parameters.docs, theme: createStorybookTheme(theme as "light" | "dark") }; // Check if this is a form component that needs FormField wrapper const storyTitle = context.title.toLowerCase(); const storyName = context.name.toLowerCase(); const isFormComponent = storyTitle.includes("forms/input") || storyTitle.includes("forms/select") || storyTitle.includes("forms/textarea") || storyName.includes("input") || storyName.includes("select") || storyName.includes("textarea") || context.parameters.formField === true; return ( <QueryClientProvider client={queryClient}> <ThemeProvider> <ThemeSync theme={theme}> {isFormComponent ? ( <FormFieldWrapper> <Story /> </FormFieldWrapper> ) : ( <FormProviderWrapper> <Story /> </FormProviderWrapper> )} </ThemeSync> </ThemeProvider> </QueryClientProvider> ); } ], globalTypes: { theme: { description: "Global theme for components", defaultValue: "light", toolbar: { title: "Theme", icon: "paintbrush", items: [ { value: "light", title: "Light" }, { value: "dark", title: "Dark" } ], dynamicTitle: true } } } }; export default preview;

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fonoster/fonoster'

If you have feedback or need assistance with the MCP directory API, please join our Discord server