UNPKG

@restnfeel/agentc-starter-kit

Version:

한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템

279 lines (262 loc) 7.92 kB
export interface ChatbotTheme { primary: string; secondary: string; background: string; surface: string; text: { primary: string; secondary: string; inverse: string; }; border: string; shadow: string; success: string; warning: string; error: string; radius: { sm: string; md: string; lg: string; full: string; }; spacing: { xs: string; sm: string; md: string; lg: string; xl: string; }; typography: { fontFamily: string; fontSize: { xs: string; sm: string; md: string; lg: string; xl: string; }; fontWeight: { normal: string; medium: string; semibold: string; bold: string; }; }; } export const defaultTheme: ChatbotTheme = { primary: "#3B82F6", secondary: "#64748B", background: "#FFFFFF", surface: "#F8FAFC", text: { primary: "#1F2937", secondary: "#6B7280", inverse: "#FFFFFF", }, border: "#E5E7EB", shadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1)", success: "#10B981", warning: "#F59E0B", error: "#EF4444", radius: { sm: "0.375rem", md: "0.5rem", lg: "0.75rem", full: "9999px", }, spacing: { xs: "0.25rem", sm: "0.5rem", md: "1rem", lg: "1.5rem", xl: "2rem", }, typography: { fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', fontSize: { xs: "0.75rem", sm: "0.875rem", md: "1rem", lg: "1.125rem", xl: "1.25rem", }, fontWeight: { normal: "400", medium: "500", semibold: "600", bold: "700", }, }, }; export const darkTheme: ChatbotTheme = { primary: "#60A5FA", secondary: "#94A3B8", background: "#1F2937", surface: "#374151", text: { primary: "#F9FAFB", secondary: "#D1D5DB", inverse: "#1F2937", }, border: "#4B5563", shadow: "0 10px 15px -3px rgba(0, 0, 0, 0.3)", success: "#34D399", warning: "#FBBF24", error: "#F87171", radius: { sm: "0.375rem", md: "0.5rem", lg: "0.75rem", full: "9999px", }, spacing: { xs: "0.25rem", sm: "0.5rem", md: "1rem", lg: "1.5rem", xl: "2rem", }, typography: { fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', fontSize: { xs: "0.75rem", sm: "0.875rem", md: "1rem", lg: "1.125rem", xl: "1.25rem", }, fontWeight: { normal: "400", medium: "500", semibold: "600", bold: "700", }, }, }; export const compactTheme: ChatbotTheme = { ...defaultTheme, spacing: { xs: "0.125rem", sm: "0.25rem", md: "0.5rem", lg: "0.75rem", xl: "1rem", }, typography: { ...defaultTheme.typography, fontSize: { xs: "0.625rem", sm: "0.75rem", md: "0.875rem", lg: "1rem", xl: "1.125rem", }, }, }; export const themes = { default: defaultTheme, dark: darkTheme, compact: compactTheme, } as const; export type ThemeName = keyof typeof themes; // Theme utility functions export function getThemeVariables(theme: ChatbotTheme): Record<string, string> { return { "--chatbot-primary": theme.primary, "--chatbot-secondary": theme.secondary, "--chatbot-background": theme.background, "--chatbot-surface": theme.surface, "--chatbot-text-primary": theme.text.primary, "--chatbot-text-secondary": theme.text.secondary, "--chatbot-text-inverse": theme.text.inverse, "--chatbot-border": theme.border, "--chatbot-shadow": theme.shadow, "--chatbot-success": theme.success, "--chatbot-warning": theme.warning, "--chatbot-error": theme.error, "--chatbot-radius-sm": theme.radius.sm, "--chatbot-radius-md": theme.radius.md, "--chatbot-radius-lg": theme.radius.lg, "--chatbot-radius-full": theme.radius.full, "--chatbot-spacing-xs": theme.spacing.xs, "--chatbot-spacing-sm": theme.spacing.sm, "--chatbot-spacing-md": theme.spacing.md, "--chatbot-spacing-lg": theme.spacing.lg, "--chatbot-spacing-xl": theme.spacing.xl, "--chatbot-font-family": theme.typography.fontFamily, "--chatbot-font-size-xs": theme.typography.fontSize.xs, "--chatbot-font-size-sm": theme.typography.fontSize.sm, "--chatbot-font-size-md": theme.typography.fontSize.md, "--chatbot-font-size-lg": theme.typography.fontSize.lg, "--chatbot-font-size-xl": theme.typography.fontSize.xl, "--chatbot-font-weight-normal": theme.typography.fontWeight.normal, "--chatbot-font-weight-medium": theme.typography.fontWeight.medium, "--chatbot-font-weight-semibold": theme.typography.fontWeight.semibold, "--chatbot-font-weight-bold": theme.typography.fontWeight.bold, }; } export function applyTheme(theme: ChatbotTheme, element?: HTMLElement): void { const target = element || document.documentElement; const variables = getThemeVariables(theme); Object.entries(variables).forEach(([property, value]) => { target.style.setProperty(property, value); }); } export function createThemeStylesheet(theme: ChatbotTheme): string { const variables = getThemeVariables(theme); const variableDeclarations = Object.entries(variables) .map(([property, value]) => ` ${property}: ${value};`) .join("\n"); return `:root {\n${variableDeclarations}\n}`; } // CSS class generator for theme-aware components export function generateThemeClasses(theme: ChatbotTheme) { return { button: { primary: `bg-[var(--chatbot-primary)] text-[var(--chatbot-text-inverse)] hover:opacity-90 border border-transparent rounded-[var(--chatbot-radius-md)] px-[var(--chatbot-spacing-md)] py-[var(--chatbot-spacing-sm)] font-[var(--chatbot-font-weight-medium)] text-[var(--chatbot-font-size-sm)] transition-all duration-200 focus:ring-2 focus:ring-[var(--chatbot-primary)] focus:ring-opacity-50`, secondary: `bg-[var(--chatbot-surface)] text-[var(--chatbot-text-primary)] hover:bg-[var(--chatbot-border)] border border-[var(--chatbot-border)] rounded-[var(--chatbot-radius-md)] px-[var(--chatbot-spacing-md)] py-[var(--chatbot-spacing-sm)] font-[var(--chatbot-font-weight-medium)] text-[var(--chatbot-font-size-sm)] transition-all duration-200 focus:ring-2 focus:ring-[var(--chatbot-primary)] focus:ring-opacity-50`, }, input: `bg-[var(--chatbot-background)] text-[var(--chatbot-text-primary)] border border-[var(--chatbot-border)] rounded-[var(--chatbot-radius-md)] px-[var(--chatbot-spacing-md)] py-[var(--chatbot-spacing-sm)] text-[var(--chatbot-font-size-sm)] font-[var(--chatbot-font-weight-normal)] focus:border-[var(--chatbot-primary)] focus:ring-2 focus:ring-[var(--chatbot-primary)] focus:ring-opacity-50 placeholder:text-[var(--chatbot-text-secondary)]`, surface: `bg-[var(--chatbot-surface)] border border-[var(--chatbot-border)] rounded-[var(--chatbot-radius-lg)] shadow-[var(--chatbot-shadow)]`, text: { primary: "text-[var(--chatbot-text-primary)]", secondary: "text-[var(--chatbot-text-secondary)]", inverse: "text-[var(--chatbot-text-inverse)]", }, }; } // React hook for theme management export function useTheme(initialTheme: ThemeName = "default") { const [currentTheme, setCurrentTheme] = React.useState<ThemeName>(initialTheme); React.useEffect(() => { applyTheme(themes[currentTheme]); }, [currentTheme]); const changeTheme = React.useCallback((themeName: ThemeName) => { setCurrentTheme(themeName); }, []); return { currentTheme, theme: themes[currentTheme], changeTheme, availableThemes: Object.keys(themes) as ThemeName[], }; } // Add React import for the hook import React from "react";