From 52d2c09a6e4869a3729ec203e50849fc3f12cd31 Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 20:49:47 +0000 Subject: [PATCH] code: tsx,storybook,src (1 files) --- storybook/src/components/registry.tsx | 345 ++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 storybook/src/components/registry.tsx diff --git a/storybook/src/components/registry.tsx b/storybook/src/components/registry.tsx new file mode 100644 index 000000000..f2e25c808 --- /dev/null +++ b/storybook/src/components/registry.tsx @@ -0,0 +1,345 @@ +/** + * Component Registry + * Maps Lua component type names to React components + */ + +import React, { type ComponentType, type ReactNode } from 'react' + +export interface LuaComponentProps { + className?: string + children?: ReactNode + [key: string]: unknown +} + +type AnyComponent = ComponentType + +/** + * Basic UI Components + * These mirror the components available in the main app's fakemui library + */ + +export const Box: React.FC = ({ className, children, ...props }) => ( +
{children}
+) + +export const Stack: React.FC = ({ className = 'flex flex-col gap-4', children }) => ( +
{children}
+) + +export const Flex: React.FC = ({ className = 'flex gap-4', children }) => ( +
{children}
+) + +export const Grid: React.FC = ({ className = 'grid grid-cols-2 gap-4', children }) => ( +
{children}
+) + +export const Container: React.FC = ({ className = 'max-w-7xl mx-auto px-4', children }) => ( +
{children}
+) + +export const Card: React.FC = ({ className = 'rounded-lg border shadow-sm bg-canvas', children }) => ( +
{children}
+) + +export const CardHeader: React.FC = ({ className = 'p-6 pb-2', children }) => ( +
{children}
+) + +export const CardContent: React.FC = ({ className = 'p-6 pt-0', children }) => ( +
{children}
+) + +export const CardActions: React.FC = ({ className = 'p-6 pt-0 flex gap-2', children }) => ( +
{children}
+) + +export const Paper: React.FC = ({ className = 'rounded border p-4 bg-canvas', children }) => ( +
{children}
+) + +interface TypographyProps extends LuaComponentProps { + variant?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body1' | 'body2' | 'caption' | 'overline' + text?: string +} + +export const Typography: React.FC = ({ + variant = 'body1', + text, + className = '', + children +}) => { + const content = text ?? children + const variantClasses: Record = { + h1: 'text-4xl font-bold', + h2: 'text-3xl font-bold', + h3: 'text-2xl font-semibold', + h4: 'text-xl font-semibold', + h5: 'text-lg font-medium', + h6: 'text-base font-medium', + body1: 'text-base', + body2: 'text-sm', + caption: 'text-xs text-muted-foreground', + overline: 'text-xs uppercase tracking-wide text-muted-foreground', + } + + const Element = variant.startsWith('h') ? variant as keyof JSX.IntrinsicElements : 'p' + return {content} +} + +interface ButtonProps extends LuaComponentProps { + variant?: 'contained' | 'outlined' | 'text' + color?: 'primary' | 'secondary' | 'error' + size?: 'small' | 'medium' | 'large' + onClick?: () => void +} + +export const Button: React.FC = ({ + variant = 'contained', + color = 'primary', + size = 'medium', + className = '', + children, + onClick, +}) => { + const baseClass = 'rounded font-medium transition-colors cursor-pointer' + const sizeClasses = { + small: 'px-2 py-1 text-sm', + medium: 'px-4 py-2', + large: 'px-6 py-3 text-lg', + } + const variantClasses = { + contained: 'bg-accent text-accent-foreground hover:opacity-90', + outlined: 'border border-accent text-accent hover:bg-accent/10', + text: 'text-accent hover:bg-accent/10', + } + + return ( + + ) +} + +interface IconProps extends LuaComponentProps { + name: string + size?: 'small' | 'medium' | 'large' +} + +export const Icon: React.FC = ({ name, size = 'medium', className = '' }) => { + const sizeClasses = { small: 'text-sm', medium: 'text-xl', large: 'text-3xl' } + // Simple emoji/text fallback for icons + const iconMap: Record = { + users: '👥', + settings: '⚙️', + dashboard: '📊', + home: '🏠', + edit: '✏️', + delete: '🗑️', + add: '➕', + check: '✓', + close: '✕', + arrow_up: '↑', + arrow_down: '↓', + trending_up: '📈', + trending_down: '📉', + } + return {iconMap[name] || `[${name}]`} +} + +export const Divider: React.FC = ({ className = 'border-t my-4' }) => ( +
+) + +export const Avatar: React.FC = ({ + src, + alt = 'Avatar', + className = 'w-10 h-10 rounded-full bg-muted flex items-center justify-center' +}) => ( + src ? {alt} :
{alt[0]}
+) + +interface TabsProps extends LuaComponentProps { + value?: string + items?: Array<{ value: string; label: string; content?: ReactNode }> +} + +export const Tabs: React.FC = ({ items = [], className = '' }) => { + const [active, setActive] = React.useState(items[0]?.value || '') + + return ( +
+
+ {items.map(item => ( + + ))} +
+
+ {items.find(i => i.value === active)?.content} +
+
+ ) +} + +export const Tab: React.FC = ({ + label, + children, + className = 'py-2 px-4' +}) => ( +
{label || children}
+) + +export const Alert: React.FC = ({ + severity = 'info', + className = '', + children, +}) => { + const colors = { + info: 'bg-blue-50 border-blue-200 text-blue-800', + success: 'bg-green-50 border-green-200 text-green-800', + warning: 'bg-yellow-50 border-yellow-200 text-yellow-800', + error: 'bg-red-50 border-red-200 text-red-800', + } + return
{children}
+} + +export const Badge: React.FC = ({ + color = 'default', + className = '', + children, +}) => ( + + {children} + +) + +export const Chip: React.FC = ({ + label, + className = 'inline-flex items-center px-3 py-1 rounded-full text-sm bg-muted', + children, +}) => ( + {label || children} +) + +// Placeholder components for complex Lua package components +export const Level4Header: React.FC = ({ + username = 'User', + nerdMode = false, +}) => ( +
+
+ Level 4 - Admin Panel + {nerdMode && Nerd Mode} +
+
+ + {username} +
+
+) + +export const IntroSection: React.FC = ({ eyebrow, title, description }) => ( +
+ {eyebrow && {eyebrow}} + {title && {title}} + {description && {description}} +
+) + +export const AppHeader: React.FC = ({ children }) => ( +
{children}
+) + +export const AppFooter: React.FC = ({ children }) => ( +
{children}
+) + +export const Sidebar: React.FC = ({ children, className = 'w-64 border-r p-4 bg-canvas' }) => ( + +) + +/** + * Component Registry - maps Lua type names to React components + */ +export const componentRegistry: Record = { + // Layout + Box, + Stack, + Flex, + Grid, + Container, + + // Surfaces + Card, + CardHeader, + CardContent, + CardActions, + CardTitle: CardHeader, + CardFooter: CardActions, + Paper, + + // Typography + Typography, + Text: Typography, + + // Inputs + Button, + + // Display + Icon, + Avatar, + Badge, + Chip, + Divider, + Alert, + + // Navigation + Tabs, + Tab, + + // App-specific (from Lua packages) + Level4Header, + IntroSection, + AppHeader, + AppFooter, + Sidebar, +} + +/** + * Get a component by its Lua type name + */ +export function getComponent(typeName: string): AnyComponent | undefined { + return componentRegistry[typeName] +} + +/** + * Register a custom component + */ +export function registerComponent(typeName: string, component: AnyComponent): void { + componentRegistry[typeName] = component +} + +/** + * Check if a component type is registered + */ +export function hasComponent(typeName: string): boolean { + return typeName in componentRegistry +}