@opensite/ui 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/utils.ts","../lib/useNavigation.ts","../components/ui/button.tsx","../lib/Pressable.tsx"],"names":["React2","jsx"],"mappings":"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","file":"pressable.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nexport type LinkType = \"internal\" | \"external\" | \"mailto\" | \"tel\" | \"unknown\" | \"none\";\n\nexport interface UseNavigationArgs {\n href?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n}\n\nexport interface UseNavigationReturn {\n linkType: LinkType;\n normalizedHref: string | undefined;\n target: \"_blank\" | \"_self\" | undefined;\n rel: string | undefined;\n isExternal: boolean;\n isInternal: boolean;\n shouldUseRouter: boolean;\n handleClick: React.MouseEventHandler<HTMLElement>;\n}\n\n/**\n * Normalizes phone numbers to tel: format\n * Handles formats like:\n * - \"+14322386131\"\n * - \"(432) 238-6131\"\n * - \"512-232-2212x123\"\n * - \"tel:+14322386131\"\n */\nfunction normalizePhoneNumber(input: string): string {\n const trimmed = input.trim();\n\n // Already has tel: prefix\n if (trimmed.toLowerCase().startsWith(\"tel:\")) {\n return trimmed;\n }\n\n // Extract digits and extension\n const match = trimmed.match(/^[\\s\\+\\-\\(\\)]*(\\d[\\d\\s\\-\\(\\)\\.]*\\d)[\\s\\-]*(x|ext\\.?|extension)?[\\s\\-]*(\\d+)?$/i);\n\n if (match) {\n // Clean the main number (remove spaces, dashes, dots, parentheses)\n const mainNumber = match[1].replace(/[\\s\\-\\(\\)\\.]/g, \"\");\n const extension = match[3];\n\n // Add + prefix if not already there and number looks international (10+ digits)\n const normalized = mainNumber.length >= 10 && !trimmed.startsWith(\"+\")\n ? `+${mainNumber}`\n : mainNumber;\n\n // Add extension if present\n const withExtension = extension ? `${normalized};ext=${extension}` : normalized;\n\n return `tel:${withExtension}`;\n }\n\n // Fallback: just clean and prefix\n const cleaned = trimmed.replace(/[\\s\\-\\(\\)\\.]/g, \"\");\n return `tel:${cleaned}`;\n}\n\n/**\n * Normalizes email addresses to mailto: format\n */\nfunction normalizeEmail(input: string): string {\n const trimmed = input.trim();\n\n // Already has mailto: prefix\n if (trimmed.toLowerCase().startsWith(\"mailto:\")) {\n return trimmed;\n }\n\n return `mailto:${trimmed}`;\n}\n\n/**\n * Detects if a string is an email address\n */\nfunction isEmail(input: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(input.trim());\n}\n\n/**\n * Detects if a string is a phone number\n */\nfunction isPhoneNumber(input: string): boolean {\n const trimmed = input.trim();\n\n // Already has tel: prefix\n if (trimmed.toLowerCase().startsWith(\"tel:\")) {\n return true;\n }\n\n // Match various phone formats\n const phoneRegex = /^[\\s\\+\\-\\(\\)]*\\d[\\d\\s\\-\\(\\)\\.]*\\d[\\s\\-]*(x|ext\\.?|extension)?[\\s\\-]*\\d*$/i;\n return phoneRegex.test(trimmed);\n}\n\n/**\n * Detects if a URL is internal to the current site\n * Handles cases like:\n * - \"/blog-123\"\n * - \"https://jordansite.com/blog-123\"\n * - \"https://www.jordansite.com/blog-123\"\n */\nfunction isInternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n // SSR fallback: assume relative paths are internal\n return href.startsWith(\"/\") && !href.startsWith(\"//\");\n }\n\n const trimmed = href.trim();\n\n // Relative paths are internal\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) {\n return true;\n }\n\n // Check if full URL matches current origin\n try {\n const url = new URL(trimmed, window.location.href);\n const currentOrigin = window.location.origin;\n\n // Normalize both origins (remove www. for comparison)\n const normalizeOrigin = (origin: string) =>\n origin.replace(/^(https?:\\/\\/)(www\\.)?/, \"$1\");\n\n return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);\n } catch {\n return false;\n }\n}\n\n/**\n * Converts a full URL to a relative path if it's internal\n */\nfunction toRelativePath(href: string): string {\n if (typeof window === \"undefined\") {\n return href;\n }\n\n const trimmed = href.trim();\n\n // Already relative\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) {\n return trimmed;\n }\n\n try {\n const url = new URL(trimmed, window.location.href);\n const currentOrigin = window.location.origin;\n\n // Normalize both origins for comparison\n const normalizeOrigin = (origin: string) =>\n origin.replace(/^(https?:\\/\\/)(www\\.)?/, \"$1\");\n\n if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {\n // Return pathname + search + hash\n return url.pathname + url.search + url.hash;\n }\n } catch {\n // Invalid URL, return as-is\n }\n\n return trimmed;\n}\n\n/**\n * Hook for handling navigation with automatic link type detection,\n * URL normalization, and proper attributes for SEO and accessibility.\n *\n * Features:\n * - Detects link types: internal, external, mailto, tel\n * - Normalizes phone numbers (various formats to tel:)\n * - Normalizes email addresses to mailto:\n * - Converts full URLs matching current origin to relative paths\n * - Determines proper target and rel attributes\n * - Handles React Router-style internal navigation\n *\n * @example\n * ```tsx\n * const nav = useNavigation({ href: \"/about\" });\n * // nav.linkType === \"internal\"\n * // nav.normalizedHref === \"/about\"\n * // nav.target === \"_self\"\n *\n * const nav2 = useNavigation({ href: \"(432) 238-6131\" });\n * // nav2.linkType === \"tel\"\n * // nav2.normalizedHref === \"tel:+14322386131\"\n *\n * const nav3 = useNavigation({ href: \"https://google.com\" });\n * // nav3.linkType === \"external\"\n * // nav3.target === \"_blank\"\n * // nav3.rel === \"noopener noreferrer\"\n * ```\n */\nexport function useNavigation({\n href,\n onClick\n}: UseNavigationArgs = {}): UseNavigationReturn {\n const linkType = React.useMemo((): LinkType => {\n if (!href || href.trim() === \"\") {\n return onClick ? \"none\" : \"none\";\n }\n\n const trimmed = href.trim();\n\n // Check for mailto\n if (trimmed.toLowerCase().startsWith(\"mailto:\") || isEmail(trimmed)) {\n return \"mailto\";\n }\n\n // Check for tel\n if (trimmed.toLowerCase().startsWith(\"tel:\") || isPhoneNumber(trimmed)) {\n return \"tel\";\n }\n\n // Check for internal vs external\n if (isInternalUrl(trimmed)) {\n return \"internal\";\n }\n\n // Check if it's a valid URL\n try {\n new URL(trimmed, typeof window !== \"undefined\" ? window.location.href : \"http://localhost\");\n return \"external\";\n } catch {\n // Not a valid URL, treat as internal path\n return \"internal\";\n }\n }, [href, onClick]);\n\n const normalizedHref = React.useMemo((): string | undefined => {\n if (!href || href.trim() === \"\") {\n return undefined;\n }\n\n const trimmed = href.trim();\n\n switch (linkType) {\n case \"tel\":\n return normalizePhoneNumber(trimmed);\n case \"mailto\":\n return normalizeEmail(trimmed);\n case \"internal\":\n return toRelativePath(trimmed);\n case \"external\":\n return trimmed;\n default:\n return trimmed;\n }\n }, [href, linkType]);\n\n const target = React.useMemo((): \"_blank\" | \"_self\" | undefined => {\n switch (linkType) {\n case \"external\":\n return \"_blank\";\n case \"internal\":\n return \"_self\";\n case \"mailto\":\n case \"tel\":\n // Let browser handle default behavior\n return undefined;\n default:\n return undefined;\n }\n }, [linkType]);\n\n const rel = React.useMemo((): string | undefined => {\n if (linkType === \"external\") {\n return \"noopener noreferrer\";\n }\n return undefined;\n }, [linkType]);\n\n const isExternal = linkType === \"external\";\n const isInternal = linkType === \"internal\";\n const shouldUseRouter = isInternal && typeof normalizedHref === \"string\" && normalizedHref.startsWith(\"/\");\n\n const handleClick = React.useCallback<React.MouseEventHandler<HTMLElement>>(\n (event) => {\n // Call user's onClick first\n if (onClick) {\n try {\n onClick(event);\n } catch (error) {\n console.error(\"Error in user onClick handler:\", error);\n }\n }\n\n // If event was prevented, don't do anything else\n if (event.defaultPrevented) {\n return;\n }\n\n // Only handle internal navigation for left-clicks without modifiers\n if (\n shouldUseRouter &&\n normalizedHref &&\n event.button === 0 && // left-click only\n !event.metaKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.shiftKey\n ) {\n // Check if there's a navigation handler (from opensite-blocks or similar)\n if (typeof window !== \"undefined\") {\n const handler = (window as any).__opensiteNavigationHandler;\n if (typeof handler === \"function\") {\n try {\n const handled = handler(normalizedHref, event.nativeEvent || event);\n if (handled !== false) {\n event.preventDefault();\n }\n } catch (error) {\n console.error(\"Error in navigation handler:\", error);\n }\n }\n }\n }\n },\n [onClick, shouldUseRouter, normalizedHref]\n );\n\n return {\n linkType,\n normalizedHref,\n target,\n rel,\n isExternal,\n isInternal,\n shouldUseRouter,\n handleClick,\n };\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]\",\n destructive:\n \"bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]\",\n ghost:\n \"bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50\",\n link: \"text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n sm: \"h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]\",\n md: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n lg: \"h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]\",\n icon: \"size-[var(--button-height-md,2.25rem)]\",\n \"icon-sm\": \"size-[var(--button-height-sm,2rem)]\",\n \"icon-lg\": \"size-[var(--button-height-lg,2.5rem)]\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport * as React from \"react\";\nimport { type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"./utils\";\nimport { useNavigation } from \"./useNavigation\";\nimport { buttonVariants } from \"../components/ui/button\";\n\ntype FallbackComponentType = \"span\" | \"div\" | \"button\";\n\ninterface PressableBaseProps {\n /**\n * Content inside the Pressable component\n */\n children: React.ReactNode;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n\n /**\n * URL to navigate to (can be internal path, external URL, mailto:, tel:, or email/phone string)\n * Examples:\n * - \"/about\" - internal link\n * - \"https://google.com\" - external link\n * - \"mailto:hello@example.com\" or \"hello@example.com\" - email link\n * - \"tel:+14322386131\" or \"(432) 238-6131\" - phone link\n * - \"https://mysite.com/blog\" - will be converted to \"/blog\" if on mysite.com\n */\n href?: string;\n\n /**\n * Click handler\n */\n onClick?: React.MouseEventHandler<HTMLElement>;\n\n /**\n * The component type to render when there's no href or onClick\n * @default \"span\"\n */\n fallbackComponentType?: FallbackComponentType;\n\n /**\n * Explicit component type to render (overrides automatic selection)\n * Note: Internal links will ALWAYS render as <a> tags for SEO, even if componentType=\"button\"\n */\n componentType?: \"a\" | \"button\" | FallbackComponentType;\n\n /**\n * Whether to render as a button styled link (uses ShadCN button styles)\n * When true, will apply button variant classes even when rendering an <a> tag\n * @default false\n */\n asButton?: boolean;\n\n /**\n * ARIA label for accessibility\n */\n \"aria-label\"?: string;\n\n /**\n * ARIA describedby for accessibility\n */\n \"aria-describedby\"?: string;\n\n /**\n * ID attribute\n */\n id?: string;\n\n /**\n * Data attributes\n */\n [key: `data-${string}`]: any;\n}\n\n// Combine Pressable props with button variants\nexport interface PressableProps\n extends PressableBaseProps,\n VariantProps<typeof buttonVariants> {}\n\n// Type for link-specific props\ninterface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {}\n\n// Type for button-specific props\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\n/**\n * Universal link/button component with automatic URL detection and normalization.\n *\n * Features:\n * - Automatic link type detection (internal, external, mailto, tel)\n * - Phone number normalization (various formats to tel:)\n * - Email normalization to mailto:\n * - Internal URL normalization (full URLs to relative paths)\n * - Proper SEO attributes (always uses <a> for links, even when styled as buttons)\n * - ShadCN button variants and sizes\n * - Flexible layout support (icon+label or custom children)\n * - React Router-style internal navigation\n *\n * @example\n * Simple link\n * ```tsx\n * <Pressable href=\"/about\">About Us</Pressable>\n * ```\n *\n * @example\n * Button-styled link with icon\n * ```tsx\n * <Pressable href=\"/quotes\" variant=\"default\" size=\"lg\" asButton>\n * <DynamicIcon name=\"lucide/calculator\" size={20} />\n * Get a Free Quote\n * </Pressable>\n * ```\n *\n * @example\n * External link (automatically gets target=\"_blank\" and rel=\"noopener noreferrer\")\n * ```tsx\n * <Pressable href=\"https://google.com\">Visit Google</Pressable>\n * ```\n *\n * @example\n * Phone link (automatically normalized to tel: format)\n * ```tsx\n * <Pressable href=\"(432) 238-6131\">Call Us</Pressable>\n * // Renders: <a href=\"tel:+14322386131\">\n * ```\n *\n * @example\n * Custom layout with full children control\n * ```tsx\n * <Pressable href=\"/services\" className=\"custom-card\">\n * <div className=\"card-header\">\n * <DynamicIcon name=\"service-icon\" />\n * <h3>Our Services</h3>\n * </div>\n * <p>Learn more about what we offer</p>\n * </Pressable>\n * ```\n *\n * @example\n * Button with onClick (no href)\n * ```tsx\n * <Pressable onClick={() => alert(\"Clicked\")} variant=\"default\" size=\"md\" asButton>\n * Click Me\n * </Pressable>\n * ```\n */\nexport const Pressable = React.forwardRef<\n HTMLAnchorElement | HTMLButtonElement | HTMLSpanElement,\n PressableProps & Partial<LinkProps> & Partial<ButtonProps>\n>(\n (\n {\n children,\n className,\n href,\n onClick,\n variant,\n size,\n asButton = false,\n fallbackComponentType = \"span\",\n componentType,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedby,\n id,\n ...props\n },\n ref\n ) => {\n const navigation = useNavigation({ href, onClick });\n const {\n normalizedHref,\n target,\n rel,\n linkType,\n isInternal,\n isExternal,\n handleClick,\n } = navigation;\n\n // Determine what component to render\n const shouldRenderLink = normalizedHref && linkType !== \"none\";\n const shouldRenderButton = !shouldRenderLink && onClick;\n const shouldRenderFallback = !shouldRenderLink && !shouldRenderButton;\n\n // Force <a> tag for internal links for SEO (even if componentType=\"button\")\n const effectiveComponentType = componentType || (\n shouldRenderLink\n ? \"a\"\n : shouldRenderButton\n ? \"button\"\n : fallbackComponentType\n );\n\n // Override for SEO: internal links must be <a> tags\n const finalComponentType = isInternal && shouldRenderLink\n ? \"a\"\n : effectiveComponentType;\n\n // Determine if we should apply button styles\n const shouldApplyButtonStyles = asButton || variant || size;\n\n // Build className\n const combinedClassName = cn(\n shouldApplyButtonStyles && buttonVariants({ variant, size }),\n className\n );\n\n // Build common props\n const commonProps = {\n className: combinedClassName,\n onClick: handleClick,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedby,\n id,\n ...Object.fromEntries(\n Object.entries(props).filter(([key]) => key.startsWith(\"data-\"))\n ),\n };\n\n // Render link\n if (finalComponentType === \"a\" && shouldRenderLink) {\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={normalizedHref}\n target={target}\n rel={rel}\n {...commonProps}\n {...(props as LinkProps)}\n >\n {children}\n </a>\n );\n }\n\n // Render button\n if (finalComponentType === \"button\") {\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n type={(props as ButtonProps).type || \"button\"}\n {...commonProps}\n {...(props as ButtonProps)}\n >\n {children}\n </button>\n );\n }\n\n // Render fallback (span or div)\n if (finalComponentType === \"div\") {\n return (\n <div\n ref={ref as React.Ref<HTMLDivElement>}\n {...commonProps}\n >\n {children}\n </div>\n );\n }\n\n // Default to span\n return (\n <span\n ref={ref as React.Ref<HTMLSpanElement>}\n {...commonProps}\n >\n {children}\n </span>\n );\n }\n);\n\nPressable.displayName = \"Pressable\";\n"]}
1
+ {"version":3,"sources":["../lib/utils.ts","../lib/useNavigation.ts","../lib/button-variants.ts","../lib/Pressable.tsx"],"names":["React2"],"mappings":"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","file":"pressable.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nexport type LinkType = \"internal\" | \"external\" | \"mailto\" | \"tel\" | \"unknown\" | \"none\";\n\nexport interface UseNavigationArgs {\n href?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n}\n\nexport interface UseNavigationReturn {\n linkType: LinkType;\n normalizedHref: string | undefined;\n target: \"_blank\" | \"_self\" | undefined;\n rel: string | undefined;\n isExternal: boolean;\n isInternal: boolean;\n shouldUseRouter: boolean;\n handleClick: React.MouseEventHandler<HTMLElement>;\n}\n\n/**\n * Normalizes phone numbers to tel: format\n * Handles formats like:\n * - \"+14322386131\"\n * - \"(432) 238-6131\"\n * - \"512-232-2212x123\"\n * - \"tel:+14322386131\"\n */\nfunction normalizePhoneNumber(input: string): string {\n const trimmed = input.trim();\n\n // Already has tel: prefix\n if (trimmed.toLowerCase().startsWith(\"tel:\")) {\n return trimmed;\n }\n\n // Extract digits and extension\n const match = trimmed.match(/^[\\s\\+\\-\\(\\)]*(\\d[\\d\\s\\-\\(\\)\\.]*\\d)[\\s\\-]*(x|ext\\.?|extension)?[\\s\\-]*(\\d+)?$/i);\n\n if (match) {\n // Clean the main number (remove spaces, dashes, dots, parentheses)\n const mainNumber = match[1].replace(/[\\s\\-\\(\\)\\.]/g, \"\");\n const extension = match[3];\n\n // Add + prefix if not already there and number looks international (10+ digits)\n const normalized = mainNumber.length >= 10 && !trimmed.startsWith(\"+\")\n ? `+${mainNumber}`\n : mainNumber;\n\n // Add extension if present\n const withExtension = extension ? `${normalized};ext=${extension}` : normalized;\n\n return `tel:${withExtension}`;\n }\n\n // Fallback: just clean and prefix\n const cleaned = trimmed.replace(/[\\s\\-\\(\\)\\.]/g, \"\");\n return `tel:${cleaned}`;\n}\n\n/**\n * Normalizes email addresses to mailto: format\n */\nfunction normalizeEmail(input: string): string {\n const trimmed = input.trim();\n\n // Already has mailto: prefix\n if (trimmed.toLowerCase().startsWith(\"mailto:\")) {\n return trimmed;\n }\n\n return `mailto:${trimmed}`;\n}\n\n/**\n * Detects if a string is an email address\n */\nfunction isEmail(input: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(input.trim());\n}\n\n/**\n * Detects if a string is a phone number\n */\nfunction isPhoneNumber(input: string): boolean {\n const trimmed = input.trim();\n\n // Already has tel: prefix\n if (trimmed.toLowerCase().startsWith(\"tel:\")) {\n return true;\n }\n\n // Match various phone formats\n const phoneRegex = /^[\\s\\+\\-\\(\\)]*\\d[\\d\\s\\-\\(\\)\\.]*\\d[\\s\\-]*(x|ext\\.?|extension)?[\\s\\-]*\\d*$/i;\n return phoneRegex.test(trimmed);\n}\n\n/**\n * Detects if a URL is internal to the current site\n * Handles cases like:\n * - \"/blog-123\"\n * - \"https://jordansite.com/blog-123\"\n * - \"https://www.jordansite.com/blog-123\"\n */\nfunction isInternalUrl(href: string): boolean {\n if (typeof window === \"undefined\") {\n // SSR fallback: assume relative paths are internal\n return href.startsWith(\"/\") && !href.startsWith(\"//\");\n }\n\n const trimmed = href.trim();\n\n // Relative paths are internal\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) {\n return true;\n }\n\n // Check if full URL matches current origin\n try {\n const url = new URL(trimmed, window.location.href);\n const currentOrigin = window.location.origin;\n\n // Normalize both origins (remove www. for comparison)\n const normalizeOrigin = (origin: string) =>\n origin.replace(/^(https?:\\/\\/)(www\\.)?/, \"$1\");\n\n return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);\n } catch {\n return false;\n }\n}\n\n/**\n * Converts a full URL to a relative path if it's internal\n */\nfunction toRelativePath(href: string): string {\n if (typeof window === \"undefined\") {\n return href;\n }\n\n const trimmed = href.trim();\n\n // Already relative\n if (trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")) {\n return trimmed;\n }\n\n try {\n const url = new URL(trimmed, window.location.href);\n const currentOrigin = window.location.origin;\n\n // Normalize both origins for comparison\n const normalizeOrigin = (origin: string) =>\n origin.replace(/^(https?:\\/\\/)(www\\.)?/, \"$1\");\n\n if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {\n // Return pathname + search + hash\n return url.pathname + url.search + url.hash;\n }\n } catch {\n // Invalid URL, return as-is\n }\n\n return trimmed;\n}\n\n/**\n * Hook for handling navigation with automatic link type detection,\n * URL normalization, and proper attributes for SEO and accessibility.\n *\n * Features:\n * - Detects link types: internal, external, mailto, tel\n * - Normalizes phone numbers (various formats to tel:)\n * - Normalizes email addresses to mailto:\n * - Converts full URLs matching current origin to relative paths\n * - Determines proper target and rel attributes\n * - Handles React Router-style internal navigation\n *\n * @example\n * ```tsx\n * const nav = useNavigation({ href: \"/about\" });\n * // nav.linkType === \"internal\"\n * // nav.normalizedHref === \"/about\"\n * // nav.target === \"_self\"\n *\n * const nav2 = useNavigation({ href: \"(432) 238-6131\" });\n * // nav2.linkType === \"tel\"\n * // nav2.normalizedHref === \"tel:+14322386131\"\n *\n * const nav3 = useNavigation({ href: \"https://google.com\" });\n * // nav3.linkType === \"external\"\n * // nav3.target === \"_blank\"\n * // nav3.rel === \"noopener noreferrer\"\n * ```\n */\nexport function useNavigation({\n href,\n onClick\n}: UseNavigationArgs = {}): UseNavigationReturn {\n const linkType = React.useMemo((): LinkType => {\n if (!href || href.trim() === \"\") {\n return onClick ? \"none\" : \"none\";\n }\n\n const trimmed = href.trim();\n\n // Check for mailto\n if (trimmed.toLowerCase().startsWith(\"mailto:\") || isEmail(trimmed)) {\n return \"mailto\";\n }\n\n // Check for tel\n if (trimmed.toLowerCase().startsWith(\"tel:\") || isPhoneNumber(trimmed)) {\n return \"tel\";\n }\n\n // Check for internal vs external\n if (isInternalUrl(trimmed)) {\n return \"internal\";\n }\n\n // Check if it's a valid URL\n try {\n new URL(trimmed, typeof window !== \"undefined\" ? window.location.href : \"http://localhost\");\n return \"external\";\n } catch {\n // Not a valid URL, treat as internal path\n return \"internal\";\n }\n }, [href, onClick]);\n\n const normalizedHref = React.useMemo((): string | undefined => {\n if (!href || href.trim() === \"\") {\n return undefined;\n }\n\n const trimmed = href.trim();\n\n switch (linkType) {\n case \"tel\":\n return normalizePhoneNumber(trimmed);\n case \"mailto\":\n return normalizeEmail(trimmed);\n case \"internal\":\n return toRelativePath(trimmed);\n case \"external\":\n return trimmed;\n default:\n return trimmed;\n }\n }, [href, linkType]);\n\n const target = React.useMemo((): \"_blank\" | \"_self\" | undefined => {\n switch (linkType) {\n case \"external\":\n return \"_blank\";\n case \"internal\":\n return \"_self\";\n case \"mailto\":\n case \"tel\":\n // Let browser handle default behavior\n return undefined;\n default:\n return undefined;\n }\n }, [linkType]);\n\n const rel = React.useMemo((): string | undefined => {\n if (linkType === \"external\") {\n return \"noopener noreferrer\";\n }\n return undefined;\n }, [linkType]);\n\n const isExternal = linkType === \"external\";\n const isInternal = linkType === \"internal\";\n const shouldUseRouter = isInternal && typeof normalizedHref === \"string\" && normalizedHref.startsWith(\"/\");\n\n const handleClick = React.useCallback<React.MouseEventHandler<HTMLElement>>(\n (event) => {\n // Call user's onClick first\n if (onClick) {\n try {\n onClick(event);\n } catch (error) {\n console.error(\"Error in user onClick handler:\", error);\n }\n }\n\n // If event was prevented, don't do anything else\n if (event.defaultPrevented) {\n return;\n }\n\n // Only handle internal navigation for left-clicks without modifiers\n if (\n shouldUseRouter &&\n normalizedHref &&\n event.button === 0 && // left-click only\n !event.metaKey &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.shiftKey\n ) {\n // Check if there's a navigation handler (from opensite-blocks or similar)\n if (typeof window !== \"undefined\") {\n const handler = (window as any).__opensiteNavigationHandler;\n if (typeof handler === \"function\") {\n try {\n const handled = handler(normalizedHref, event.nativeEvent || event);\n if (handled !== false) {\n event.preventDefault();\n }\n } catch (error) {\n console.error(\"Error in navigation handler:\", error);\n }\n }\n }\n }\n },\n [onClick, shouldUseRouter, normalizedHref]\n );\n\n return {\n linkType,\n normalizedHref,\n target,\n rel,\n isExternal,\n isInternal,\n shouldUseRouter,\n handleClick,\n };\n}\n","import { cva } from \"class-variance-authority\";\n\n/**\n * Button variants using class-variance-authority (cva).\n * \n * This is extracted to a separate file to avoid importing @radix-ui/react-slot\n * when only the variants are needed (e.g., in Pressable component).\n */\nexport const buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]\",\n destructive:\n \"bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]\",\n ghost:\n \"bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50\",\n link: \"text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n sm: \"h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]\",\n md: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n lg: \"h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]\",\n icon: \"size-[var(--button-height-md,2.25rem)]\",\n \"icon-sm\": \"size-[var(--button-height-sm,2rem)]\",\n \"icon-lg\": \"size-[var(--button-height-lg,2.5rem)]\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n","\"use client\";\n\nimport * as React from \"react\";\nimport { type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"./utils\";\nimport { useNavigation } from \"./useNavigation\";\nimport { buttonVariants } from \"./button-variants\";\n\ntype FallbackComponentType = \"span\" | \"div\" | \"button\";\n\ninterface PressableBaseProps {\n /**\n * Content inside the Pressable component\n */\n children: React.ReactNode;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n\n /**\n * URL to navigate to (can be internal path, external URL, mailto:, tel:, or email/phone string)\n * Examples:\n * - \"/about\" - internal link\n * - \"https://google.com\" - external link\n * - \"mailto:hello@example.com\" or \"hello@example.com\" - email link\n * - \"tel:+14322386131\" or \"(432) 238-6131\" - phone link\n * - \"https://mysite.com/blog\" - will be converted to \"/blog\" if on mysite.com\n */\n href?: string;\n\n /**\n * Click handler\n */\n onClick?: React.MouseEventHandler<HTMLElement>;\n\n /**\n * The component type to render when there's no href or onClick\n * @default \"span\"\n */\n fallbackComponentType?: FallbackComponentType;\n\n /**\n * Explicit component type to render (overrides automatic selection)\n * Note: Internal links will ALWAYS render as <a> tags for SEO, even if componentType=\"button\"\n */\n componentType?: \"a\" | \"button\" | FallbackComponentType;\n\n /**\n * Whether to render as a button styled link (uses ShadCN button styles)\n * When true, will apply button variant classes even when rendering an <a> tag\n * @default false\n */\n asButton?: boolean;\n\n /**\n * ARIA label for accessibility\n */\n \"aria-label\"?: string;\n\n /**\n * ARIA describedby for accessibility\n */\n \"aria-describedby\"?: string;\n\n /**\n * ID attribute\n */\n id?: string;\n\n /**\n * Data attributes\n */\n [key: `data-${string}`]: any;\n}\n\n// Combine Pressable props with button variants\nexport interface PressableProps\n extends PressableBaseProps,\n VariantProps<typeof buttonVariants> {}\n\n// Type for link-specific props\ninterface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {}\n\n// Type for button-specific props\ninterface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}\n\n/**\n * Universal link/button component with automatic URL detection and normalization.\n *\n * Features:\n * - Automatic link type detection (internal, external, mailto, tel)\n * - Phone number normalization (various formats to tel:)\n * - Email normalization to mailto:\n * - Internal URL normalization (full URLs to relative paths)\n * - Proper SEO attributes (always uses <a> for links, even when styled as buttons)\n * - ShadCN button variants and sizes\n * - Flexible layout support (icon+label or custom children)\n * - React Router-style internal navigation\n *\n * @example\n * Simple link\n * ```tsx\n * <Pressable href=\"/about\">About Us</Pressable>\n * ```\n *\n * @example\n * Button-styled link with icon\n * ```tsx\n * <Pressable href=\"/quotes\" variant=\"default\" size=\"lg\" asButton>\n * <DynamicIcon name=\"lucide/calculator\" size={20} />\n * Get a Free Quote\n * </Pressable>\n * ```\n *\n * @example\n * External link (automatically gets target=\"_blank\" and rel=\"noopener noreferrer\")\n * ```tsx\n * <Pressable href=\"https://google.com\">Visit Google</Pressable>\n * ```\n *\n * @example\n * Phone link (automatically normalized to tel: format)\n * ```tsx\n * <Pressable href=\"(432) 238-6131\">Call Us</Pressable>\n * // Renders: <a href=\"tel:+14322386131\">\n * ```\n *\n * @example\n * Custom layout with full children control\n * ```tsx\n * <Pressable href=\"/services\" className=\"custom-card\">\n * <div className=\"card-header\">\n * <DynamicIcon name=\"service-icon\" />\n * <h3>Our Services</h3>\n * </div>\n * <p>Learn more about what we offer</p>\n * </Pressable>\n * ```\n *\n * @example\n * Button with onClick (no href)\n * ```tsx\n * <Pressable onClick={() => alert(\"Clicked\")} variant=\"default\" size=\"md\" asButton>\n * Click Me\n * </Pressable>\n * ```\n */\nexport const Pressable = React.forwardRef<\n HTMLAnchorElement | HTMLButtonElement | HTMLSpanElement,\n PressableProps & Partial<LinkProps> & Partial<ButtonProps>\n>(\n (\n {\n children,\n className,\n href,\n onClick,\n variant,\n size,\n asButton = false,\n fallbackComponentType = \"span\",\n componentType,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedby,\n id,\n ...props\n },\n ref\n ) => {\n const navigation = useNavigation({ href, onClick });\n const {\n normalizedHref,\n target,\n rel,\n linkType,\n isInternal,\n isExternal,\n handleClick,\n } = navigation;\n\n // Determine what component to render\n const shouldRenderLink = normalizedHref && linkType !== \"none\";\n const shouldRenderButton = !shouldRenderLink && onClick;\n const shouldRenderFallback = !shouldRenderLink && !shouldRenderButton;\n\n // Force <a> tag for internal links for SEO (even if componentType=\"button\")\n const effectiveComponentType = componentType || (\n shouldRenderLink\n ? \"a\"\n : shouldRenderButton\n ? \"button\"\n : fallbackComponentType\n );\n\n // Override for SEO: internal links must be <a> tags\n const finalComponentType = isInternal && shouldRenderLink\n ? \"a\"\n : effectiveComponentType;\n\n // Determine if we should apply button styles\n const shouldApplyButtonStyles = asButton || variant || size;\n\n // Build className\n const combinedClassName = cn(\n shouldApplyButtonStyles && buttonVariants({ variant, size }),\n className\n );\n\n // Build common props\n const commonProps = {\n className: combinedClassName,\n onClick: handleClick,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedby,\n id,\n ...Object.fromEntries(\n Object.entries(props).filter(([key]) => key.startsWith(\"data-\"))\n ),\n };\n\n // Render link\n if (finalComponentType === \"a\" && shouldRenderLink) {\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={normalizedHref}\n target={target}\n rel={rel}\n {...commonProps}\n {...(props as LinkProps)}\n >\n {children}\n </a>\n );\n }\n\n // Render button\n if (finalComponentType === \"button\") {\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n type={(props as ButtonProps).type || \"button\"}\n {...commonProps}\n {...(props as ButtonProps)}\n >\n {children}\n </button>\n );\n }\n\n // Render fallback (span or div)\n if (finalComponentType === \"div\") {\n return (\n <div\n ref={ref as React.Ref<HTMLDivElement>}\n {...commonProps}\n >\n {children}\n </div>\n );\n }\n\n // Default to span\n return (\n <span\n ref={ref as React.Ref<HTMLSpanElement>}\n {...commonProps}\n >\n {children}\n </span>\n );\n }\n);\n\nPressable.displayName = \"Pressable\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/utils.ts","../components/ui/container.tsx","../components/ui/section.tsx","../components/blocks/about/alternating-blocks.tsx","../components/blocks/cta/media-hover-ctas.tsx","../components/ui/button.tsx","../components/ui/dynamic-icon.tsx","../components/ui/carousel.tsx","../components/blocks/features/feature-showcase.tsx","../src/registry/blocks.ts"],"names":["twMerge","clsx","React","jsx","jsxs","Img","cva","Slot","React3","iconName","React4","useEmblaCarousel","api","useState","useRef","useEffect"],"mappings":"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","file":"registry.cjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport type { ContainerProps } from \"../../src/types\";\n\nconst maxWidthStyles = {\n sm: \"max-w-screen-sm\",\n md: \"max-w-screen-md\",\n lg: \"max-w-screen-lg\",\n xl: \"max-w-screen-xl\",\n \"2xl\": \"max-w-screen-2xl\",\n \"4xl\": \"max-w-[1536px]\",\n full: \"max-w-full\",\n};\n\n/**\n * Container component for consistent content width and centering\n *\n * @example\n * ```tsx\n * <Container maxWidth=\"xl\">\n * <h1>Page Content</h1>\n * </Container>\n * ```\n */\nexport const Container = React.forwardRef<HTMLDivElement, ContainerProps>(\n ({ children, maxWidth = \"xl\", className, as = \"div\", ...props }, ref) => {\n const Component = as as any;\n return (\n <Component\n ref={ref}\n className={cn(\n \"mx-auto w-full px-4 sm:px-6 lg:px-8\",\n maxWidthStyles[maxWidth],\n className\n )}\n {...props}\n >\n {children}\n </Component>\n );\n }\n);\n\nContainer.displayName = \"Container\";\n","import React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Container } from \"./container\";\nimport type { SectionProps } from \"../../src/types\";\n\n/**\n * Background style variants\n * Uses standard Tailwind/shadcn CSS variables for theming\n */\nconst backgroundStyles = {\n white: \"bg-background text-foreground\",\n gray: \"bg-muted/30 text-foreground\",\n dark: \"bg-foreground text-background\",\n gradient: \"bg-gradient-to-br from-primary via-primary/90 to-foreground text-primary-foreground\",\n primary: \"bg-primary text-primary-foreground\",\n secondary: \"bg-secondary text-secondary-foreground\",\n muted: \"bg-muted text-muted-foreground\",\n};\n\n/**\n * Vertical spacing variants\n */\nconst spacingStyles = {\n sm: \"py-12 md:py-16\",\n md: \"py-16 md:py-24\",\n lg: \"py-20 md:py-32\",\n xl: \"py-24 md:py-40\",\n};\n\n/**\n * Section component for consistent page sections with optional title, subtitle, and background\n *\n * @example\n * ```tsx\n * <Section\n * title=\"Our Services\"\n * subtitle=\"What we offer\"\n * background=\"gray\"\n * spacing=\"lg\"\n * >\n * <div>Section content goes here</div>\n * </Section>\n * ```\n */\nexport const Section = React.forwardRef<HTMLElement, SectionProps>(\n (\n {\n id,\n title,\n subtitle,\n children,\n className,\n style,\n background = \"white\",\n spacing = \"lg\",\n ...props\n },\n ref\n ) => {\n return (\n <section\n ref={ref}\n id={id}\n className={cn(\n backgroundStyles[background],\n spacingStyles[spacing],\n className\n )}\n style={style}\n {...props}\n >\n <Container>\n {(title || subtitle) && (\n <div className=\"text-center mb-12 md:mb-16\">\n {subtitle && (\n <p className=\"text-sm font-semibold uppercase tracking-wider mb-2 text-primary\">\n {subtitle}\n </p>\n )}\n {title && (\n <h2 className=\"text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight\">\n {title}\n </h2>\n )}\n </div>\n )}\n {children}\n </Container>\n </section>\n );\n }\n);\n\nSection.displayName = \"Section\";\n","import * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Section } from \"../../ui/section\";\nimport type { SectionBackground, SectionSpacing } from \"../../../src/types\";\n\nexport interface AlternatingBlockSection {\n content: React.ReactNode;\n media: React.ReactNode;\n mediaLeft?: boolean;\n}\n\nexport interface AlternatingBlocksProps {\n /**\n * Array of sections to display with alternating layout\n */\n sections: AlternatingBlockSection[];\n /**\n * Section title (optional)\n */\n title?: string;\n /**\n * Section subtitle/eyebrow (optional)\n */\n subtitle?: string;\n /**\n * Background style variant\n * @default \"white\"\n */\n background?: SectionBackground;\n /**\n * Vertical spacing variant\n * @default \"lg\"\n */\n spacing?: SectionSpacing;\n /**\n * Additional CSS classes for the Section wrapper\n */\n className?: string;\n /**\n * Additional CSS classes for the content container\n */\n contentClassName?: string;\n}\n\n/**\n * AlternatingBlocks component displays content sections with alternating media placement.\n * Uses the Section component for consistent spacing, backgrounds, and optional titles.\n *\n * @example\n * ```tsx\n * <AlternatingBlocks\n * title=\"Our Story\"\n * subtitle=\"About Us\"\n * background=\"gray\"\n * spacing=\"xl\"\n * sections={[\n * {\n * content: <div><h3>Title</h3><p>Description</p></div>,\n * media: <img src=\"...\" alt=\"...\" />,\n * mediaLeft: false\n * }\n * ]}\n * />\n * ```\n */\nexport function AlternatingBlocks({\n sections,\n title,\n subtitle,\n background = \"white\",\n spacing = \"lg\",\n className,\n contentClassName,\n}: AlternatingBlocksProps) {\n return (\n <Section\n title={title}\n subtitle={subtitle}\n background={background}\n spacing={spacing}\n className={className}\n >\n <div className={cn(\"mx-auto w-full max-w-[900px]\", contentClassName)}>\n <div className=\"space-y-12\">\n {sections?.map((section, index) => (\n <div\n key={index}\n className=\"grid items-center gap-8 md:grid-cols-2 md:gap-12\"\n >\n <div className={section.mediaLeft ? \"md:order-2\" : \"\"}>\n {section.content}\n </div>\n\n <div\n className={cn(\n \"aspect-4/3 overflow-hidden rounded-lg border\",\n section.mediaLeft ? \"md:order-1\" : \"\",\n )}\n >\n <div className=\"flex h-full w-full items-center justify-center\">\n {section.media}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n </Section>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Img } from \"@page-speed/img\";\n\nexport interface MediaHoverCtaItem {\n /**\n * Content to render inside the CTA card.\n */\n content?: React.ReactNode;\n /**\n * Image URL to reveal on hover (optional).\n */\n onHoverImgSrc?: string;\n /**\n * Additional classes for the hover image.\n */\n imgHoverClassName?: string;\n /**\n * Alt text for the hover image (leave empty for decorative images).\n */\n altText?: string;\n /**\n * Optional href to make the card a link.\n */\n cardHref?: string;\n /**\n * Initial background color (CSS color value or CSS variable).\n * Example: \"#111\" or \"var(--brand-900)\".\n */\n initialBackgroundColor?: string;\n /**\n * Hover background color (CSS color value or CSS variable).\n * Applied only when onHoverImgSrc is not provided.\n */\n onHoverBackgroundColor?: string;\n}\n\nexport type MediaHoverCtaType = MediaHoverCtaItem;\n\nexport interface MediaHoverCtasProps {\n /**\n * Additional classes for the section wrapper.\n */\n sectionClassName?: string;\n /**\n * Additional classes for the grid container.\n */\n gridClassName?: string;\n /**\n * CTA items to render.\n */\n items?: MediaHoverCtaItem[];\n /**\n * Optional Optix Flow configuration for @page-speed/img.\n */\n optixFlowConfig?: {\n apiKey: string;\n compression?: number;\n };\n}\n\n/**\n * MediaHoverCtas displays a two-column CTA grid with hover media reveals.\n *\n * Each card can show a hover image or a hover background color while keeping\n * content customizable via React nodes.\n *\n * @example\n * ```tsx\n * <MediaHoverCtas\n * items={[\n * {\n * content: <div><h3>Our Mission</h3><p>...</p></div>,\n * onHoverImgSrc: \"/mission.jpg\",\n * altText: \"Our Mission\"\n * },\n * {\n * content: <div><h3>Our Vision</h3><p>...</p></div>,\n * initialBackgroundColor: \"var(--brand-100)\",\n * onHoverBackgroundColor: \"var(--brand-900)\"\n * }\n * ]}\n * />\n * ```\n */\nexport function MediaHoverCtas(\n props: MediaHoverCtasProps\n): React.JSX.Element {\n const { sectionClassName, gridClassName, items, optixFlowConfig } = props;\n const resolvedItems = items ?? [];\n\n return (\n <section className={cn(\"py-32\", sectionClassName)}>\n <div\n className={cn(\n \"grid min-h-100 grid-cols-1 gap-1 lg:grid-cols-2\",\n gridClassName\n )}\n >\n {resolvedItems.map((item, index) => {\n const CardComponent: React.ElementType = item.cardHref ? \"a\" : \"div\";\n const hasHoverImage = Boolean(item.onHoverImgSrc);\n const applyHoverBackground = Boolean(\n item.onHoverBackgroundColor && !hasHoverImage\n );\n const cardStyle =\n item.initialBackgroundColor || applyHoverBackground\n ? ({\n ...(item.initialBackgroundColor\n ? { \"--media-hover-cta-bg\": item.initialBackgroundColor }\n : {}),\n ...(applyHoverBackground\n ? {\n \"--media-hover-cta-hover-bg\":\n item.onHoverBackgroundColor,\n }\n : {}),\n } as React.CSSProperties)\n : undefined;\n const baseBackgroundClassName = item.initialBackgroundColor\n ? \"bg-[var(--media-hover-cta-bg)]\"\n : \"bg-muted-foreground/10\";\n const hoverBackgroundClassName = applyHoverBackground\n ? \"group-hover:bg-[var(--media-hover-cta-hover-bg)]\"\n : \"\";\n const hoverImageAltText = item.altText ?? \"\";\n\n return (\n <CardComponent\n key={index}\n {...(item.cardHref ? { href: item.cardHref } : {})}\n className={cn(\n \"group relative flex min-h-100 cursor-pointer items-center overflow-hidden justify-start p-10 transition-colors duration-500\",\n index % 2 === 0\n ? \"md:justify-center\"\n : \"md:justify-start md:pl-24\",\n baseBackgroundClassName,\n hoverBackgroundClassName\n )}\n style={cardStyle}\n >\n {item.onHoverImgSrc ? (\n <Img\n src={item.onHoverImgSrc}\n alt={hoverImageAltText}\n aria-hidden={item.altText ? undefined : true}\n className={cn(\n \"absolute top-0 left-0 z-[-1] h-full w-full object-cover opacity-0 transition-opacity duration-500 group-hover:opacity-100\",\n item.imgHoverClassName\n )}\n loading=\"lazy\"\n optixFlowConfig={optixFlowConfig}\n />\n ) : null}\n\n {item.content}\n </CardComponent>\n );\n })}\n </div>\n </section>\n );\n}\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]\",\n destructive:\n \"bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]\",\n ghost:\n \"bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50\",\n link: \"text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n sm: \"h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]\",\n md: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n lg: \"h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]\",\n icon: \"size-[var(--button-height-md,2.25rem)]\",\n \"icon-sm\": \"size-[var(--button-height-sm,2rem)]\",\n \"icon-lg\": \"size-[var(--button-height-lg,2.5rem)]\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\ninterface DynamicIconProps {\n /**\n * Icon name in format: prefix/name or prefix:name\n * Examples: \"lucide/home\", \"mdi:account\", \"heroicons/check\"\n */\n name: string;\n /**\n * Icon size in pixels\n * @default 28\n */\n size?: number;\n /**\n * Icon color - accepts any valid CSS color\n * Note: When not specified, the icon inherits color from parent via CSS currentColor\n */\n color?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Alt text for accessibility\n */\n alt?: string;\n}\n\n// Simple in-memory cache for fetched SVGs\nconst svgCache = new Map<string, string>();\n\n/**\n * Lightweight icon component that dynamically loads SVG icons from icons.opensite.ai API.\n *\n * Features:\n * - Pulls SVGs from https://icons.opensite.ai API and inlines them for CSS color inheritance\n * - Supports currentColor - icons inherit color from parent element\n * - Accepts prefix/name or prefix:name format\n * - Customizable size and explicit color via props\n * - In-memory caching to prevent duplicate fetches\n *\n * @example\n * ```tsx\n * // Icon inherits color from parent (recommended for hover states, etc.)\n * <span className=\"text-white hover:text-red-500\">\n * <DynamicIcon name=\"lucide/home\" size={24} />\n * </span>\n *\n * // Icon with explicit color\n * <DynamicIcon name=\"mdi:account\" size={32} color=\"#ff0000\" />\n * ```\n */\nexport function DynamicIcon({\n name,\n size = 28,\n color,\n className,\n alt,\n}: DynamicIconProps) {\n const [svgContent, setSvgContent] = React.useState<string | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n\n const { url, iconName } = React.useMemo(() => {\n const separator = name.includes(\"/\") ? \"/\" : \":\";\n const [prefix, iconName] = name.split(separator);\n // Don't pass color to API - we'll handle it via CSS\n const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName}?format=svg&width=${size}&height=${size}`;\n\n return {\n url: baseUrl,\n iconName,\n };\n }, [name, size]);\n\n React.useEffect(() => {\n let isMounted = true;\n\n const fetchSvg = async () => {\n // Check cache first\n const cached = svgCache.get(url);\n if (cached) {\n if (isMounted) {\n setSvgContent(cached);\n setIsLoading(false);\n }\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch icon: ${response.status}`);\n }\n\n let svg = await response.text();\n\n // Process SVG to ensure currentColor works:\n // 1. Replace any hardcoded colors with currentColor\n // 2. Ensure stroke/fill use currentColor where appropriate\n svg = processSvgForCurrentColor(svg);\n\n // Cache the processed SVG\n svgCache.set(url, svg);\n\n if (isMounted) {\n setSvgContent(svg);\n setIsLoading(false);\n }\n } catch (err) {\n if (isMounted) {\n setError(err instanceof Error ? err.message : \"Failed to load icon\");\n setIsLoading(false);\n }\n }\n };\n\n fetchSvg();\n\n return () => {\n isMounted = false;\n };\n }, [url]);\n\n // Loading state - show placeholder with same dimensions\n if (isLoading) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n aria-hidden=\"true\"\n />\n );\n }\n\n // Error state - show nothing or fallback\n if (error || !svgContent) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n role=\"img\"\n aria-label={alt || iconName}\n />\n );\n }\n\n // Render inline SVG\n // The color prop applies an explicit color, otherwise inherits from parent via currentColor\n return (\n <span\n className={cn(\"inline-flex items-center justify-center\", className)}\n style={{\n width: size,\n height: size,\n color: color || \"inherit\",\n }}\n role=\"img\"\n aria-label={alt || iconName}\n dangerouslySetInnerHTML={{ __html: svgContent }}\n />\n );\n}\n\n/**\n * Process SVG to ensure it uses currentColor for proper CSS inheritance.\n * This handles various icon libraries that may use different color approaches.\n */\nfunction processSvgForCurrentColor(svg: string): string {\n // Replace stroke=\"currentColor\" is already correct, but ensure fill also works\n // Some icons use fill=\"none\" with stroke, others use fill with no stroke\n\n // Ensure the SVG doesn't have hardcoded colors that should be currentColor\n // Common patterns to replace:\n // - stroke=\"#000\" or stroke=\"#000000\" or stroke=\"black\" -> stroke=\"currentColor\"\n // - fill=\"#000\" or fill=\"#000000\" or fill=\"black\" -> fill=\"currentColor\"\n\n let processed = svg;\n\n // Replace common black color values with currentColor for stroke\n processed = processed.replace(\n /stroke=[\"'](#000000|#000|black)[\"']/gi,\n 'stroke=\"currentColor\"'\n );\n\n // Replace common black color values with currentColor for fill\n // But be careful not to replace fill=\"none\"\n processed = processed.replace(\n /fill=[\"'](#000000|#000|black)[\"']/gi,\n 'fill=\"currentColor\"'\n );\n\n return processed;\n}\n","import * as React from \"react\";\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\nimport { DynamicIcon } from \"./dynamic-icon\";\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ntype CarouselProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: \"horizontal\" | \"vertical\";\n setApi?: (api: CarouselApi) => void;\n};\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselProps;\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n\n return context;\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n );\n const [canScrollPrev, setCanScrollPrev] = React.useState(false);\n const [canScrollNext, setCanScrollNext] = React.useState(false);\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return;\n setCanScrollPrev(api.canScrollPrev());\n setCanScrollNext(api.canScrollNext());\n }, []);\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext]\n );\n\n React.useEffect(() => {\n if (!api || !setApi) return;\n setApi(api);\n }, [api, setApi]);\n\n React.useEffect(() => {\n if (!api) return;\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n );\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel();\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <DynamicIcon name=\"lucide/arrow-left\" />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <DynamicIcon name=\"lucide/arrow-right\" />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n};\n","\"use client\";\n\nimport { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"../../ui/carousel\";\n\nexport interface FeatureShowcaseItem {\n content: ReactNode;\n mediaComponent: ReactNode;\n}\n\nexport interface FeatureShowcaseProps {\n items: FeatureShowcaseItem[];\n children?: ReactNode;\n className?: string;\n carouselClassName?: string;\n slideClassName?: string;\n contentClassName?: string;\n mediaClassName?: string;\n arrowClassName?: string;\n equalizeOnMobile?: boolean;\n stretchMediaOnMobile?: boolean;\n}\n\n/**\n * Feature Showcase component with carousel navigation\n *\n * Displays feature content with media in a carousel format. Each slide shows\n * content (text, headings) alongside media (images, videos). Features mobile\n * height equalization for consistent slide heights and customizable styling.\n *\n * @example\n * ```tsx\n * <FeatureShowcase\n * items={[\n * {\n * content: <div><h3>Feature 1</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature1.jpg\" alt=\"Feature 1\" />\n * },\n * {\n * content: <div><h3>Feature 2</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature2.jpg\" alt=\"Feature 2\" />\n * }\n * ]}\n * />\n * ```\n */\nexport function FeatureShowcase({\n items,\n children,\n className,\n carouselClassName,\n slideClassName,\n contentClassName,\n mediaClassName,\n arrowClassName,\n equalizeOnMobile = true,\n stretchMediaOnMobile = true,\n}: FeatureShowcaseProps) {\n const baseArrowClassName =\n \"bottom-4 top-auto size-12 translate-y-0 rounded-full border border-current bg-transparent text-current shadow-sm focus:ring-current focus:ring-offset-2 focus:ring-offset-transparent hover:bg-current/10 md:bottom-6\";\n const [mobileSlideHeight, setMobileSlideHeight] = useState<number | null>(\n null\n );\n const slideRefs = useRef<Array<HTMLDivElement | null>>([]);\n const mediaWrapperClassName =\n equalizeOnMobile && stretchMediaOnMobile\n ? \"flex-1 min-h-0 md:flex-none\"\n : \"\";\n\n useEffect(() => {\n if (!equalizeOnMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const updateHeights = () => {\n if (typeof window === \"undefined\") return;\n const isMobile = window.innerWidth < 768;\n\n if (!isMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const heights = slideRefs.current\n .slice(0, items.length)\n .map((node) => node?.offsetHeight ?? 0);\n const maxHeight = Math.max(...heights, 0);\n\n if (maxHeight > 0) {\n setMobileSlideHeight((prev) =>\n prev === maxHeight ? prev : maxHeight\n );\n }\n };\n\n updateHeights();\n window.addEventListener(\"resize\", updateHeights);\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(updateHeights);\n slideRefs.current.slice(0, items.length).forEach((node) => {\n if (node) resizeObserver?.observe(node);\n });\n }\n\n return () => {\n window.removeEventListener(\"resize\", updateHeights);\n resizeObserver?.disconnect();\n };\n }, [equalizeOnMobile, items.length]);\n\n return (\n <div className={className}>\n {children}\n <Carousel className={carouselClassName}>\n <div className=\"pb-18 md:pb-24\">\n <CarouselContent className=\"ease-in\">\n {items.map((item, itemIndex) => (\n <CarouselItem key={`slide-${itemIndex}`}>\n <div\n ref={(node) => {\n slideRefs.current[itemIndex] = node;\n }}\n style={\n equalizeOnMobile && mobileSlideHeight\n ? { minHeight: mobileSlideHeight }\n : undefined\n }\n className={cn(\n \"flex flex-col gap-8 md:gap-14 md:flex-row md:items-center md:justify-between\",\n slideClassName\n )}\n >\n <div className={cn(\"w-full\", contentClassName)}>\n {item.content}\n </div>\n <div\n className={cn(\n \"w-full\",\n mediaWrapperClassName,\n mediaClassName\n )}\n >\n {item.mediaComponent}\n </div>\n </div>\n </CarouselItem>\n ))}\n </CarouselContent>\n </div>\n <CarouselPrevious\n className={cn(baseArrowClassName, \"left-4 md:left-6\", arrowClassName)}\n />\n <CarouselNext\n className={cn(baseArrowClassName, \"right-4 md:right-6\", arrowClassName)}\n />\n </Carousel>\n </div>\n );\n}\n","/**\n * Semantic Block Registry\n *\n * This registry maps semantic concepts to available UI blocks for AI-driven\n * site generation. Each block entry contains:\n * - id: Unique identifier for the block\n * - name: Human-readable name\n * - description: What the block does and when to use it\n * - semanticTags: Array of semantic concepts this block represents\n * - category: Block category (about, features, cta, testimonials, etc.)\n * - component: Reference to the actual component\n * - props: TypeScript type for the component's props\n * - exampleUsage: Code example showing how to use the block\n */\n\nimport { AlternatingBlocks } from \"../../components/blocks/about/alternating-blocks\";\nimport type { AlternatingBlocksProps } from \"../../components/blocks/about/alternating-blocks\";\nimport { MediaHoverCtas } from \"../../components/blocks/cta/media-hover-ctas\";\nimport type { MediaHoverCtasProps } from \"../../components/blocks/cta/media-hover-ctas\";\nimport { FeatureShowcase } from \"../../components/blocks/features/feature-showcase\";\nimport type { FeatureShowcaseProps } from \"../../components/blocks/features/feature-showcase\";\n\nexport interface BlockRegistryEntry<T = any> {\n id: string;\n name: string;\n description: string;\n semanticTags: string[];\n category: BlockCategory;\n component: React.ComponentType<T>;\n props: string;\n exampleUsage: string;\n}\n\nexport type BlockCategory =\n | \"about\"\n | \"features\"\n | \"cta\"\n | \"testimonials\"\n | \"services\"\n | \"hero\"\n | \"footer\"\n | \"header\"\n | \"pricing\"\n | \"team\"\n | \"stats\"\n | \"faq\"\n | \"contact\"\n | \"gallery\"\n | \"timeline\"\n | \"process\"\n | \"benefits\"\n | \"comparison\";\n\n/**\n * Block Registry - Central registry of all available UI blocks\n */\nexport const BLOCK_REGISTRY: Record<string, BlockRegistryEntry> = {\n \"alternating-blocks\": {\n id: \"alternating-blocks\",\n name: \"Alternating Content Blocks\",\n description:\n \"Display content sections with alternating left/right media placement. Ideal for storytelling, feature showcases, or company history sections.\",\n semanticTags: [\n \"about\",\n \"story\",\n \"history\",\n \"timeline\",\n \"features\",\n \"benefits\",\n \"alternating\",\n \"two-column\",\n \"content-media\",\n ],\n category: \"about\",\n component: AlternatingBlocks,\n props: \"AlternatingBlocksProps\",\n exampleUsage: `\n<AlternatingBlocks\n sections={[\n {\n content: (\n <div>\n <div className=\"flex items-center gap-2 mb-3\">\n <Lightbulb className=\"h-4 w-4 text-primary\" />\n <span className=\"text-sm font-medium text-muted-foreground\">\n The Origin\n </span>\n </div>\n <h3 className=\"mb-3 text-2xl font-semibold tracking-tight\">\n It started with frustration\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n We spent years watching teams drown in tools that promised to help\n but only added complexity. In 2018, we decided to build something better.\n </p>\n </div>\n ),\n media: <img src=\"...\" alt=\"...\" />,\n mediaLeft: false\n },\n {\n content: <div>...</div>,\n media: <img src=\"...\" alt=\"...\" />,\n mediaLeft: true\n }\n ]}\n/>\n `.trim(),\n },\n \"media-hover-ctas\": {\n id: \"media-hover-ctas\",\n name: \"Media Hover CTAs\",\n description:\n \"Display CTA cards that reveal background imagery or color on hover. Ideal for mission/vision tiles, service highlights, or campaign prompts.\",\n semanticTags: [\n \"cta\",\n \"call-to-action\",\n \"hover\",\n \"media\",\n \"cards\",\n \"grid\",\n \"image-hover\",\n \"tiles\",\n \"mission\",\n \"vision\",\n ],\n category: \"cta\",\n component: MediaHoverCtas,\n props: \"MediaHoverCtasProps\",\n exampleUsage: `\n<MediaHoverCtas\n items={[\n {\n content: (\n <div className=\"flex max-w-sm flex-col gap-4\">\n <span className=\"text-sm font-semibold uppercase tracking-wide text-primary\">\n Our Mission\n </span>\n <p className=\"text-muted-foreground\">\n Deliver remarkable experiences with thoughtful design.\n </p>\n </div>\n ),\n onHoverImgSrc: \"/images/mission.jpg\",\n altText: \"Our Mission\"\n },\n {\n content: (\n <div className=\"flex max-w-sm flex-col gap-4\">\n <span className=\"text-sm font-semibold uppercase tracking-wide text-primary\">\n Our Vision\n </span>\n <p className=\"text-muted-foreground\">\n Build the future of adaptive customer experiences.\n </p>\n </div>\n ),\n initialBackgroundColor: \"var(--brand-100)\",\n onHoverBackgroundColor: \"var(--brand-900)\"\n }\n ]}\n/>\n `.trim(),\n },\n \"feature-showcase\": {\n id: \"feature-showcase\",\n name: \"Feature Showcase Carousel\",\n description:\n \"Display feature content with media in an interactive carousel format. Each slide shows feature content alongside images or videos with smooth navigation. Features mobile height equalization for consistent appearance.\",\n semanticTags: [\n \"features\",\n \"carousel\",\n \"showcase\",\n \"slider\",\n \"highlights\",\n \"product-features\",\n \"capabilities\",\n \"interactive\",\n \"media-gallery\",\n ],\n category: \"features\",\n component: FeatureShowcase,\n props: \"FeatureShowcaseProps\",\n exampleUsage: `\n<FeatureShowcase\n items={[\n {\n content: (\n <div>\n <span className=\"text-sm font-medium text-primary mb-2 block\">\n DESIGNED TO HELP YOU GROW\n </span>\n <h3 className=\"mb-4 text-3xl font-bold tracking-tight\">\n Powerful Analytics\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n Track every metric that matters with real-time dashboards\n and comprehensive reporting tools.\n </p>\n </div>\n ),\n mediaComponent: <img src=\"...\" alt=\"Analytics Dashboard\" className=\"rounded-lg\" />\n },\n {\n content: (\n <div>\n <span className=\"text-sm font-medium text-primary mb-2 block\">\n SEAMLESS INTEGRATION\n </span>\n <h3 className=\"mb-4 text-3xl font-bold tracking-tight\">\n Connect Anywhere\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n Integrate with your favorite tools and platforms in seconds.\n </p>\n </div>\n ),\n mediaComponent: <img src=\"...\" alt=\"Integrations\" className=\"rounded-lg\" />\n }\n ]}\n/>\n `.trim(),\n },\n // Add more blocks here following this pattern\n};\n\n/**\n * Get blocks by semantic tag\n */\nexport function getBlocksBySemanticTag(tag: string): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY).filter((block) =>\n block.semanticTags.includes(tag)\n );\n}\n\n/**\n * Get blocks by category\n */\nexport function getBlocksByCategory(\n category: BlockCategory\n): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY).filter(\n (block) => block.category === category\n );\n}\n\n/**\n * Get block by ID\n */\nexport function getBlockById(id: string): BlockRegistryEntry | undefined {\n return BLOCK_REGISTRY[id];\n}\n\n/**\n * Get all available blocks\n */\nexport function getAllBlocks(): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY);\n}\n\n/**\n * Get all categories\n */\nexport function getAllCategories(): BlockCategory[] {\n return Array.from(\n new Set(Object.values(BLOCK_REGISTRY).map((block) => block.category))\n );\n}\n\n/**\n * Search blocks by query (searches name, description, and semantic tags)\n */\nexport function searchBlocks(query: string): BlockRegistryEntry[] {\n const lowercaseQuery = query.toLowerCase();\n return Object.values(BLOCK_REGISTRY).filter(\n (block) =>\n block.name.toLowerCase().includes(lowercaseQuery) ||\n block.description.toLowerCase().includes(lowercaseQuery) ||\n block.semanticTags.some((tag) =>\n tag.toLowerCase().includes(lowercaseQuery)\n )\n );\n}\n"]}
1
+ {"version":3,"sources":["../lib/utils.ts","../components/ui/container.tsx","../components/ui/section.tsx","../components/blocks/about/alternating-blocks.tsx","../components/blocks/cta/media-hover-ctas.tsx","../lib/button-variants.ts","../components/ui/button.tsx","../components/ui/dynamic-icon.tsx","../components/ui/carousel.tsx","../components/blocks/features/feature-showcase.tsx","../src/registry/blocks.ts"],"names":["twMerge","clsx","React","jsx","jsxs","Img","cva","Slot","React3","iconName","React4","useEmblaCarousel","api","useState","useRef","useEffect"],"mappings":"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","file":"registry.cjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport type { ContainerProps } from \"../../src/types\";\n\nconst maxWidthStyles = {\n sm: \"max-w-screen-sm\",\n md: \"max-w-screen-md\",\n lg: \"max-w-screen-lg\",\n xl: \"max-w-screen-xl\",\n \"2xl\": \"max-w-screen-2xl\",\n \"4xl\": \"max-w-[1536px]\",\n full: \"max-w-full\",\n};\n\n/**\n * Container component for consistent content width and centering\n *\n * @example\n * ```tsx\n * <Container maxWidth=\"xl\">\n * <h1>Page Content</h1>\n * </Container>\n * ```\n */\nexport const Container = React.forwardRef<HTMLDivElement, ContainerProps>(\n ({ children, maxWidth = \"xl\", className, as = \"div\", ...props }, ref) => {\n const Component = as as any;\n return (\n <Component\n ref={ref}\n className={cn(\n \"mx-auto w-full px-4 sm:px-6 lg:px-8\",\n maxWidthStyles[maxWidth],\n className\n )}\n {...props}\n >\n {children}\n </Component>\n );\n }\n);\n\nContainer.displayName = \"Container\";\n","import React from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Container } from \"./container\";\nimport type { SectionProps } from \"../../src/types\";\n\n/**\n * Background style variants\n * Uses standard Tailwind/shadcn CSS variables for theming\n */\nconst backgroundStyles = {\n white: \"bg-background text-foreground\",\n gray: \"bg-muted/30 text-foreground\",\n dark: \"bg-foreground text-background\",\n gradient: \"bg-gradient-to-br from-primary via-primary/90 to-foreground text-primary-foreground\",\n primary: \"bg-primary text-primary-foreground\",\n secondary: \"bg-secondary text-secondary-foreground\",\n muted: \"bg-muted text-muted-foreground\",\n};\n\n/**\n * Vertical spacing variants\n */\nconst spacingStyles = {\n sm: \"py-12 md:py-16\",\n md: \"py-16 md:py-24\",\n lg: \"py-20 md:py-32\",\n xl: \"py-24 md:py-40\",\n};\n\n/**\n * Section component for consistent page sections with optional title, subtitle, and background\n *\n * @example\n * ```tsx\n * <Section\n * title=\"Our Services\"\n * subtitle=\"What we offer\"\n * background=\"gray\"\n * spacing=\"lg\"\n * >\n * <div>Section content goes here</div>\n * </Section>\n * ```\n */\nexport const Section = React.forwardRef<HTMLElement, SectionProps>(\n (\n {\n id,\n title,\n subtitle,\n children,\n className,\n style,\n background = \"white\",\n spacing = \"lg\",\n ...props\n },\n ref\n ) => {\n return (\n <section\n ref={ref}\n id={id}\n className={cn(\n backgroundStyles[background],\n spacingStyles[spacing],\n className\n )}\n style={style}\n {...props}\n >\n <Container>\n {(title || subtitle) && (\n <div className=\"text-center mb-12 md:mb-16\">\n {subtitle && (\n <p className=\"text-sm font-semibold uppercase tracking-wider mb-2 text-primary\">\n {subtitle}\n </p>\n )}\n {title && (\n <h2 className=\"text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight\">\n {title}\n </h2>\n )}\n </div>\n )}\n {children}\n </Container>\n </section>\n );\n }\n);\n\nSection.displayName = \"Section\";\n","import * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Section } from \"../../ui/section\";\nimport type { SectionBackground, SectionSpacing } from \"../../../src/types\";\n\nexport interface AlternatingBlockSection {\n content: React.ReactNode;\n media: React.ReactNode;\n mediaLeft?: boolean;\n}\n\nexport interface AlternatingBlocksProps {\n /**\n * Array of sections to display with alternating layout\n */\n sections: AlternatingBlockSection[];\n /**\n * Section title (optional)\n */\n title?: string;\n /**\n * Section subtitle/eyebrow (optional)\n */\n subtitle?: string;\n /**\n * Background style variant\n * @default \"white\"\n */\n background?: SectionBackground;\n /**\n * Vertical spacing variant\n * @default \"lg\"\n */\n spacing?: SectionSpacing;\n /**\n * Additional CSS classes for the Section wrapper\n */\n className?: string;\n /**\n * Additional CSS classes for the content container\n */\n contentClassName?: string;\n}\n\n/**\n * AlternatingBlocks component displays content sections with alternating media placement.\n * Uses the Section component for consistent spacing, backgrounds, and optional titles.\n *\n * @example\n * ```tsx\n * <AlternatingBlocks\n * title=\"Our Story\"\n * subtitle=\"About Us\"\n * background=\"gray\"\n * spacing=\"xl\"\n * sections={[\n * {\n * content: <div><h3>Title</h3><p>Description</p></div>,\n * media: <img src=\"...\" alt=\"...\" />,\n * mediaLeft: false\n * }\n * ]}\n * />\n * ```\n */\nexport function AlternatingBlocks({\n sections,\n title,\n subtitle,\n background = \"white\",\n spacing = \"lg\",\n className,\n contentClassName,\n}: AlternatingBlocksProps) {\n return (\n <Section\n title={title}\n subtitle={subtitle}\n background={background}\n spacing={spacing}\n className={className}\n >\n <div className={cn(\"mx-auto w-full max-w-[900px]\", contentClassName)}>\n <div className=\"space-y-12\">\n {sections?.map((section, index) => (\n <div\n key={index}\n className=\"grid items-center gap-8 md:grid-cols-2 md:gap-12\"\n >\n <div className={section.mediaLeft ? \"md:order-2\" : \"\"}>\n {section.content}\n </div>\n\n <div\n className={cn(\n \"aspect-4/3 overflow-hidden rounded-lg border\",\n section.mediaLeft ? \"md:order-1\" : \"\",\n )}\n >\n <div className=\"flex h-full w-full items-center justify-center\">\n {section.media}\n </div>\n </div>\n </div>\n ))}\n </div>\n </div>\n </Section>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport { Img } from \"@page-speed/img\";\n\nexport interface MediaHoverCtaItem {\n /**\n * Content to render inside the CTA card.\n */\n content?: React.ReactNode;\n /**\n * Image URL to reveal on hover (optional).\n */\n onHoverImgSrc?: string;\n /**\n * Additional classes for the hover image.\n */\n imgHoverClassName?: string;\n /**\n * Alt text for the hover image (leave empty for decorative images).\n */\n altText?: string;\n /**\n * Optional href to make the card a link.\n */\n cardHref?: string;\n /**\n * Initial background color (CSS color value or CSS variable).\n * Example: \"#111\" or \"var(--brand-900)\".\n */\n initialBackgroundColor?: string;\n /**\n * Hover background color (CSS color value or CSS variable).\n * Applied only when onHoverImgSrc is not provided.\n */\n onHoverBackgroundColor?: string;\n}\n\nexport type MediaHoverCtaType = MediaHoverCtaItem;\n\nexport interface MediaHoverCtasProps {\n /**\n * Additional classes for the section wrapper.\n */\n sectionClassName?: string;\n /**\n * Additional classes for the grid container.\n */\n gridClassName?: string;\n /**\n * CTA items to render.\n */\n items?: MediaHoverCtaItem[];\n /**\n * Optional Optix Flow configuration for @page-speed/img.\n */\n optixFlowConfig?: {\n apiKey: string;\n compression?: number;\n };\n}\n\n/**\n * MediaHoverCtas displays a two-column CTA grid with hover media reveals.\n *\n * Each card can show a hover image or a hover background color while keeping\n * content customizable via React nodes.\n *\n * @example\n * ```tsx\n * <MediaHoverCtas\n * items={[\n * {\n * content: <div><h3>Our Mission</h3><p>...</p></div>,\n * onHoverImgSrc: \"/mission.jpg\",\n * altText: \"Our Mission\"\n * },\n * {\n * content: <div><h3>Our Vision</h3><p>...</p></div>,\n * initialBackgroundColor: \"var(--brand-100)\",\n * onHoverBackgroundColor: \"var(--brand-900)\"\n * }\n * ]}\n * />\n * ```\n */\nexport function MediaHoverCtas(\n props: MediaHoverCtasProps\n): React.JSX.Element {\n const { sectionClassName, gridClassName, items, optixFlowConfig } = props;\n const resolvedItems = items ?? [];\n\n return (\n <section className={cn(\"py-32\", sectionClassName)}>\n <div\n className={cn(\n \"grid min-h-100 grid-cols-1 gap-1 lg:grid-cols-2\",\n gridClassName\n )}\n >\n {resolvedItems.map((item, index) => {\n const CardComponent: React.ElementType = item.cardHref ? \"a\" : \"div\";\n const hasHoverImage = Boolean(item.onHoverImgSrc);\n const applyHoverBackground = Boolean(\n item.onHoverBackgroundColor && !hasHoverImage\n );\n const cardStyle =\n item.initialBackgroundColor || applyHoverBackground\n ? ({\n ...(item.initialBackgroundColor\n ? { \"--media-hover-cta-bg\": item.initialBackgroundColor }\n : {}),\n ...(applyHoverBackground\n ? {\n \"--media-hover-cta-hover-bg\":\n item.onHoverBackgroundColor,\n }\n : {}),\n } as React.CSSProperties)\n : undefined;\n const baseBackgroundClassName = item.initialBackgroundColor\n ? \"bg-[var(--media-hover-cta-bg)]\"\n : \"bg-muted-foreground/10\";\n const hoverBackgroundClassName = applyHoverBackground\n ? \"group-hover:bg-[var(--media-hover-cta-hover-bg)]\"\n : \"\";\n const hoverImageAltText = item.altText ?? \"\";\n\n return (\n <CardComponent\n key={index}\n {...(item.cardHref ? { href: item.cardHref } : {})}\n className={cn(\n \"group relative flex min-h-100 cursor-pointer items-center overflow-hidden justify-start p-10 transition-colors duration-500\",\n index % 2 === 0\n ? \"md:justify-center\"\n : \"md:justify-start md:pl-24\",\n baseBackgroundClassName,\n hoverBackgroundClassName\n )}\n style={cardStyle}\n >\n {item.onHoverImgSrc ? (\n <Img\n src={item.onHoverImgSrc}\n alt={hoverImageAltText}\n aria-hidden={item.altText ? undefined : true}\n className={cn(\n \"absolute top-0 left-0 z-[-1] h-full w-full object-cover opacity-0 transition-opacity duration-500 group-hover:opacity-100\",\n item.imgHoverClassName\n )}\n loading=\"lazy\"\n optixFlowConfig={optixFlowConfig}\n />\n ) : null}\n\n {item.content}\n </CardComponent>\n );\n })}\n </div>\n </section>\n );\n}\n","import { cva } from \"class-variance-authority\";\n\n/**\n * Button variants using class-variance-authority (cva).\n * \n * This is extracted to a separate file to avoid importing @radix-ui/react-slot\n * when only the variants are needed (e.g., in Pressable component).\n */\nexport const buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-button text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n {\n variants: {\n variant: {\n default: \"bg-[var(--button-default-bg,hsl(var(--primary)))] text-[var(--button-default-fg,hsl(var(--primary-foreground)))] hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]\",\n destructive:\n \"bg-[var(--button-destructive-bg,hsl(var(--destructive)))] text-[var(--button-destructive-fg,white)] hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))] focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"border-[var(--button-outline-border-width,1px)] border-[var(--button-outline-border,hsl(var(--border)))] bg-[var(--button-outline-bg,hsl(var(--background)))] text-[var(--button-outline-fg,inherit)] shadow-xs hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))] dark:bg-input/30 dark:border-input dark:hover:bg-input/50\",\n secondary:\n \"bg-[var(--button-secondary-bg,hsl(var(--secondary)))] text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))] hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]\",\n ghost:\n \"bg-[var(--button-ghost-bg,transparent)] text-[var(--button-ghost-fg,inherit)] hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))] hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))] dark:hover:bg-accent/50\",\n link: \"text-[var(--button-link-fg,hsl(var(--primary)))] underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n sm: \"h-[var(--button-height-sm,2rem)] rounded-button gap-1.5 px-[var(--button-padding-x-sm,0.75rem)] has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]\",\n md: \"h-[var(--button-height-md,2.25rem)] px-[var(--button-padding-x-md,1rem)] py-2 has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]\",\n lg: \"h-[var(--button-height-lg,2.5rem)] rounded-button px-[var(--button-padding-x-lg,1.5rem)] has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]\",\n icon: \"size-[var(--button-height-md,2.25rem)]\",\n \"icon-sm\": \"size-[var(--button-height-sm,2rem)]\",\n \"icon-lg\": \"size-[var(--button-height-lg,2.5rem)]\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n","import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\nimport { buttonVariants } from \"../../lib/button-variants\"\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../../lib/utils\";\n\ninterface DynamicIconProps {\n /**\n * Icon name in format: prefix/name or prefix:name\n * Examples: \"lucide/home\", \"mdi:account\", \"heroicons/check\"\n */\n name: string;\n /**\n * Icon size in pixels\n * @default 28\n */\n size?: number;\n /**\n * Icon color - accepts any valid CSS color\n * Note: When not specified, the icon inherits color from parent via CSS currentColor\n */\n color?: string;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Alt text for accessibility\n */\n alt?: string;\n}\n\n// Simple in-memory cache for fetched SVGs\nconst svgCache = new Map<string, string>();\n\n/**\n * Lightweight icon component that dynamically loads SVG icons from icons.opensite.ai API.\n *\n * Features:\n * - Pulls SVGs from https://icons.opensite.ai API and inlines them for CSS color inheritance\n * - Supports currentColor - icons inherit color from parent element\n * - Accepts prefix/name or prefix:name format\n * - Customizable size and explicit color via props\n * - In-memory caching to prevent duplicate fetches\n *\n * @example\n * ```tsx\n * // Icon inherits color from parent (recommended for hover states, etc.)\n * <span className=\"text-white hover:text-red-500\">\n * <DynamicIcon name=\"lucide/home\" size={24} />\n * </span>\n *\n * // Icon with explicit color\n * <DynamicIcon name=\"mdi:account\" size={32} color=\"#ff0000\" />\n * ```\n */\nexport function DynamicIcon({\n name,\n size = 28,\n color,\n className,\n alt,\n}: DynamicIconProps) {\n const [svgContent, setSvgContent] = React.useState<string | null>(null);\n const [isLoading, setIsLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n\n const { url, iconName } = React.useMemo(() => {\n const separator = name.includes(\"/\") ? \"/\" : \":\";\n const [prefix, iconName] = name.split(separator);\n // Don't pass color to API - we'll handle it via CSS\n const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName}?format=svg&width=${size}&height=${size}`;\n\n return {\n url: baseUrl,\n iconName,\n };\n }, [name, size]);\n\n React.useEffect(() => {\n let isMounted = true;\n\n const fetchSvg = async () => {\n // Check cache first\n const cached = svgCache.get(url);\n if (cached) {\n if (isMounted) {\n setSvgContent(cached);\n setIsLoading(false);\n }\n return;\n }\n\n try {\n setIsLoading(true);\n setError(null);\n\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch icon: ${response.status}`);\n }\n\n let svg = await response.text();\n\n // Process SVG to ensure currentColor works:\n // 1. Replace any hardcoded colors with currentColor\n // 2. Ensure stroke/fill use currentColor where appropriate\n svg = processSvgForCurrentColor(svg);\n\n // Cache the processed SVG\n svgCache.set(url, svg);\n\n if (isMounted) {\n setSvgContent(svg);\n setIsLoading(false);\n }\n } catch (err) {\n if (isMounted) {\n setError(err instanceof Error ? err.message : \"Failed to load icon\");\n setIsLoading(false);\n }\n }\n };\n\n fetchSvg();\n\n return () => {\n isMounted = false;\n };\n }, [url]);\n\n // Loading state - show placeholder with same dimensions\n if (isLoading) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n aria-hidden=\"true\"\n />\n );\n }\n\n // Error state - show nothing or fallback\n if (error || !svgContent) {\n return (\n <span\n className={cn(\"inline-block\", className)}\n style={{ width: size, height: size }}\n role=\"img\"\n aria-label={alt || iconName}\n />\n );\n }\n\n // Render inline SVG\n // The color prop applies an explicit color, otherwise inherits from parent via currentColor\n return (\n <span\n className={cn(\"inline-flex items-center justify-center\", className)}\n style={{\n width: size,\n height: size,\n color: color || \"inherit\",\n }}\n role=\"img\"\n aria-label={alt || iconName}\n dangerouslySetInnerHTML={{ __html: svgContent }}\n />\n );\n}\n\n/**\n * Process SVG to ensure it uses currentColor for proper CSS inheritance.\n * This handles various icon libraries that may use different color approaches.\n */\nfunction processSvgForCurrentColor(svg: string): string {\n // Replace stroke=\"currentColor\" is already correct, but ensure fill also works\n // Some icons use fill=\"none\" with stroke, others use fill with no stroke\n\n // Ensure the SVG doesn't have hardcoded colors that should be currentColor\n // Common patterns to replace:\n // - stroke=\"#000\" or stroke=\"#000000\" or stroke=\"black\" -> stroke=\"currentColor\"\n // - fill=\"#000\" or fill=\"#000000\" or fill=\"black\" -> fill=\"currentColor\"\n\n let processed = svg;\n\n // Replace common black color values with currentColor for stroke\n processed = processed.replace(\n /stroke=[\"'](#000000|#000|black)[\"']/gi,\n 'stroke=\"currentColor\"'\n );\n\n // Replace common black color values with currentColor for fill\n // But be careful not to replace fill=\"none\"\n processed = processed.replace(\n /fill=[\"'](#000000|#000|black)[\"']/gi,\n 'fill=\"currentColor\"'\n );\n\n return processed;\n}\n","import * as React from \"react\";\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"./button\";\nimport { DynamicIcon } from \"./dynamic-icon\";\n\ntype CarouselApi = UseEmblaCarouselType[1];\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>;\ntype CarouselOptions = UseCarouselParameters[0];\ntype CarouselPlugin = UseCarouselParameters[1];\n\ntype CarouselProps = {\n opts?: CarouselOptions;\n plugins?: CarouselPlugin;\n orientation?: \"horizontal\" | \"vertical\";\n setApi?: (api: CarouselApi) => void;\n};\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0];\n api: ReturnType<typeof useEmblaCarousel>[1];\n scrollPrev: () => void;\n scrollNext: () => void;\n canScrollPrev: boolean;\n canScrollNext: boolean;\n} & CarouselProps;\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null);\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext);\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\");\n }\n\n return context;\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n );\n const [canScrollPrev, setCanScrollPrev] = React.useState(false);\n const [canScrollNext, setCanScrollNext] = React.useState(false);\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return;\n setCanScrollPrev(api.canScrollPrev());\n setCanScrollNext(api.canScrollNext());\n }, []);\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev();\n }, [api]);\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext();\n }, [api]);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n scrollPrev();\n } else if (event.key === \"ArrowRight\") {\n event.preventDefault();\n scrollNext();\n }\n },\n [scrollPrev, scrollNext]\n );\n\n React.useEffect(() => {\n if (!api || !setApi) return;\n setApi(api);\n }, [api, setApi]);\n\n React.useEffect(() => {\n if (!api) return;\n onSelect(api);\n api.on(\"reInit\", onSelect);\n api.on(\"select\", onSelect);\n\n return () => {\n api?.off(\"select\", onSelect);\n };\n }, [api, onSelect]);\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n );\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel();\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n );\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel();\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <DynamicIcon name=\"lucide/arrow-left\" />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n );\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel();\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <DynamicIcon name=\"lucide/arrow-right\" />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n );\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n};\n","\"use client\";\n\nimport { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../../lib/utils\";\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"../../ui/carousel\";\n\nexport interface FeatureShowcaseItem {\n content: ReactNode;\n mediaComponent: ReactNode;\n}\n\nexport interface FeatureShowcaseProps {\n items: FeatureShowcaseItem[];\n children?: ReactNode;\n className?: string;\n carouselClassName?: string;\n slideClassName?: string;\n contentClassName?: string;\n mediaClassName?: string;\n arrowClassName?: string;\n equalizeOnMobile?: boolean;\n stretchMediaOnMobile?: boolean;\n}\n\n/**\n * Feature Showcase component with carousel navigation\n *\n * Displays feature content with media in a carousel format. Each slide shows\n * content (text, headings) alongside media (images, videos). Features mobile\n * height equalization for consistent slide heights and customizable styling.\n *\n * @example\n * ```tsx\n * <FeatureShowcase\n * items={[\n * {\n * content: <div><h3>Feature 1</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature1.jpg\" alt=\"Feature 1\" />\n * },\n * {\n * content: <div><h3>Feature 2</h3><p>Description</p></div>,\n * mediaComponent: <img src=\"/feature2.jpg\" alt=\"Feature 2\" />\n * }\n * ]}\n * />\n * ```\n */\nexport function FeatureShowcase({\n items,\n children,\n className,\n carouselClassName,\n slideClassName,\n contentClassName,\n mediaClassName,\n arrowClassName,\n equalizeOnMobile = true,\n stretchMediaOnMobile = true,\n}: FeatureShowcaseProps) {\n const baseArrowClassName =\n \"bottom-4 top-auto size-12 translate-y-0 rounded-full border border-current bg-transparent text-current shadow-sm focus:ring-current focus:ring-offset-2 focus:ring-offset-transparent hover:bg-current/10 md:bottom-6\";\n const [mobileSlideHeight, setMobileSlideHeight] = useState<number | null>(\n null\n );\n const slideRefs = useRef<Array<HTMLDivElement | null>>([]);\n const mediaWrapperClassName =\n equalizeOnMobile && stretchMediaOnMobile\n ? \"flex-1 min-h-0 md:flex-none\"\n : \"\";\n\n useEffect(() => {\n if (!equalizeOnMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const updateHeights = () => {\n if (typeof window === \"undefined\") return;\n const isMobile = window.innerWidth < 768;\n\n if (!isMobile) {\n setMobileSlideHeight(null);\n return;\n }\n\n const heights = slideRefs.current\n .slice(0, items.length)\n .map((node) => node?.offsetHeight ?? 0);\n const maxHeight = Math.max(...heights, 0);\n\n if (maxHeight > 0) {\n setMobileSlideHeight((prev) =>\n prev === maxHeight ? prev : maxHeight\n );\n }\n };\n\n updateHeights();\n window.addEventListener(\"resize\", updateHeights);\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(updateHeights);\n slideRefs.current.slice(0, items.length).forEach((node) => {\n if (node) resizeObserver?.observe(node);\n });\n }\n\n return () => {\n window.removeEventListener(\"resize\", updateHeights);\n resizeObserver?.disconnect();\n };\n }, [equalizeOnMobile, items.length]);\n\n return (\n <div className={className}>\n {children}\n <Carousel className={carouselClassName}>\n <div className=\"pb-18 md:pb-24\">\n <CarouselContent className=\"ease-in\">\n {items.map((item, itemIndex) => (\n <CarouselItem key={`slide-${itemIndex}`}>\n <div\n ref={(node) => {\n slideRefs.current[itemIndex] = node;\n }}\n style={\n equalizeOnMobile && mobileSlideHeight\n ? { minHeight: mobileSlideHeight }\n : undefined\n }\n className={cn(\n \"flex flex-col gap-8 md:gap-14 md:flex-row md:items-center md:justify-between\",\n slideClassName\n )}\n >\n <div className={cn(\"w-full\", contentClassName)}>\n {item.content}\n </div>\n <div\n className={cn(\n \"w-full\",\n mediaWrapperClassName,\n mediaClassName\n )}\n >\n {item.mediaComponent}\n </div>\n </div>\n </CarouselItem>\n ))}\n </CarouselContent>\n </div>\n <CarouselPrevious\n className={cn(baseArrowClassName, \"left-4 md:left-6\", arrowClassName)}\n />\n <CarouselNext\n className={cn(baseArrowClassName, \"right-4 md:right-6\", arrowClassName)}\n />\n </Carousel>\n </div>\n );\n}\n","/**\n * Semantic Block Registry\n *\n * This registry maps semantic concepts to available UI blocks for AI-driven\n * site generation. Each block entry contains:\n * - id: Unique identifier for the block\n * - name: Human-readable name\n * - description: What the block does and when to use it\n * - semanticTags: Array of semantic concepts this block represents\n * - category: Block category (about, features, cta, testimonials, etc.)\n * - component: Reference to the actual component\n * - props: TypeScript type for the component's props\n * - exampleUsage: Code example showing how to use the block\n */\n\nimport { AlternatingBlocks } from \"../../components/blocks/about/alternating-blocks\";\nimport type { AlternatingBlocksProps } from \"../../components/blocks/about/alternating-blocks\";\nimport { MediaHoverCtas } from \"../../components/blocks/cta/media-hover-ctas\";\nimport type { MediaHoverCtasProps } from \"../../components/blocks/cta/media-hover-ctas\";\nimport { FeatureShowcase } from \"../../components/blocks/features/feature-showcase\";\nimport type { FeatureShowcaseProps } from \"../../components/blocks/features/feature-showcase\";\n\nexport interface BlockRegistryEntry<T = any> {\n id: string;\n name: string;\n description: string;\n semanticTags: string[];\n category: BlockCategory;\n component: React.ComponentType<T>;\n props: string;\n exampleUsage: string;\n}\n\nexport type BlockCategory =\n | \"about\"\n | \"features\"\n | \"cta\"\n | \"testimonials\"\n | \"services\"\n | \"hero\"\n | \"footer\"\n | \"header\"\n | \"pricing\"\n | \"team\"\n | \"stats\"\n | \"faq\"\n | \"contact\"\n | \"gallery\"\n | \"timeline\"\n | \"process\"\n | \"benefits\"\n | \"comparison\";\n\n/**\n * Block Registry - Central registry of all available UI blocks\n */\nexport const BLOCK_REGISTRY: Record<string, BlockRegistryEntry> = {\n \"alternating-blocks\": {\n id: \"alternating-blocks\",\n name: \"Alternating Content Blocks\",\n description:\n \"Display content sections with alternating left/right media placement. Ideal for storytelling, feature showcases, or company history sections.\",\n semanticTags: [\n \"about\",\n \"story\",\n \"history\",\n \"timeline\",\n \"features\",\n \"benefits\",\n \"alternating\",\n \"two-column\",\n \"content-media\",\n ],\n category: \"about\",\n component: AlternatingBlocks,\n props: \"AlternatingBlocksProps\",\n exampleUsage: `\n<AlternatingBlocks\n sections={[\n {\n content: (\n <div>\n <div className=\"flex items-center gap-2 mb-3\">\n <Lightbulb className=\"h-4 w-4 text-primary\" />\n <span className=\"text-sm font-medium text-muted-foreground\">\n The Origin\n </span>\n </div>\n <h3 className=\"mb-3 text-2xl font-semibold tracking-tight\">\n It started with frustration\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n We spent years watching teams drown in tools that promised to help\n but only added complexity. In 2018, we decided to build something better.\n </p>\n </div>\n ),\n media: <img src=\"...\" alt=\"...\" />,\n mediaLeft: false\n },\n {\n content: <div>...</div>,\n media: <img src=\"...\" alt=\"...\" />,\n mediaLeft: true\n }\n ]}\n/>\n `.trim(),\n },\n \"media-hover-ctas\": {\n id: \"media-hover-ctas\",\n name: \"Media Hover CTAs\",\n description:\n \"Display CTA cards that reveal background imagery or color on hover. Ideal for mission/vision tiles, service highlights, or campaign prompts.\",\n semanticTags: [\n \"cta\",\n \"call-to-action\",\n \"hover\",\n \"media\",\n \"cards\",\n \"grid\",\n \"image-hover\",\n \"tiles\",\n \"mission\",\n \"vision\",\n ],\n category: \"cta\",\n component: MediaHoverCtas,\n props: \"MediaHoverCtasProps\",\n exampleUsage: `\n<MediaHoverCtas\n items={[\n {\n content: (\n <div className=\"flex max-w-sm flex-col gap-4\">\n <span className=\"text-sm font-semibold uppercase tracking-wide text-primary\">\n Our Mission\n </span>\n <p className=\"text-muted-foreground\">\n Deliver remarkable experiences with thoughtful design.\n </p>\n </div>\n ),\n onHoverImgSrc: \"/images/mission.jpg\",\n altText: \"Our Mission\"\n },\n {\n content: (\n <div className=\"flex max-w-sm flex-col gap-4\">\n <span className=\"text-sm font-semibold uppercase tracking-wide text-primary\">\n Our Vision\n </span>\n <p className=\"text-muted-foreground\">\n Build the future of adaptive customer experiences.\n </p>\n </div>\n ),\n initialBackgroundColor: \"var(--brand-100)\",\n onHoverBackgroundColor: \"var(--brand-900)\"\n }\n ]}\n/>\n `.trim(),\n },\n \"feature-showcase\": {\n id: \"feature-showcase\",\n name: \"Feature Showcase Carousel\",\n description:\n \"Display feature content with media in an interactive carousel format. Each slide shows feature content alongside images or videos with smooth navigation. Features mobile height equalization for consistent appearance.\",\n semanticTags: [\n \"features\",\n \"carousel\",\n \"showcase\",\n \"slider\",\n \"highlights\",\n \"product-features\",\n \"capabilities\",\n \"interactive\",\n \"media-gallery\",\n ],\n category: \"features\",\n component: FeatureShowcase,\n props: \"FeatureShowcaseProps\",\n exampleUsage: `\n<FeatureShowcase\n items={[\n {\n content: (\n <div>\n <span className=\"text-sm font-medium text-primary mb-2 block\">\n DESIGNED TO HELP YOU GROW\n </span>\n <h3 className=\"mb-4 text-3xl font-bold tracking-tight\">\n Powerful Analytics\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n Track every metric that matters with real-time dashboards\n and comprehensive reporting tools.\n </p>\n </div>\n ),\n mediaComponent: <img src=\"...\" alt=\"Analytics Dashboard\" className=\"rounded-lg\" />\n },\n {\n content: (\n <div>\n <span className=\"text-sm font-medium text-primary mb-2 block\">\n SEAMLESS INTEGRATION\n </span>\n <h3 className=\"mb-4 text-3xl font-bold tracking-tight\">\n Connect Anywhere\n </h3>\n <p className=\"text-muted-foreground leading-relaxed\">\n Integrate with your favorite tools and platforms in seconds.\n </p>\n </div>\n ),\n mediaComponent: <img src=\"...\" alt=\"Integrations\" className=\"rounded-lg\" />\n }\n ]}\n/>\n `.trim(),\n },\n // Add more blocks here following this pattern\n};\n\n/**\n * Get blocks by semantic tag\n */\nexport function getBlocksBySemanticTag(tag: string): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY).filter((block) =>\n block.semanticTags.includes(tag)\n );\n}\n\n/**\n * Get blocks by category\n */\nexport function getBlocksByCategory(\n category: BlockCategory\n): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY).filter(\n (block) => block.category === category\n );\n}\n\n/**\n * Get block by ID\n */\nexport function getBlockById(id: string): BlockRegistryEntry | undefined {\n return BLOCK_REGISTRY[id];\n}\n\n/**\n * Get all available blocks\n */\nexport function getAllBlocks(): BlockRegistryEntry[] {\n return Object.values(BLOCK_REGISTRY);\n}\n\n/**\n * Get all categories\n */\nexport function getAllCategories(): BlockCategory[] {\n return Array.from(\n new Set(Object.values(BLOCK_REGISTRY).map((block) => block.category))\n );\n}\n\n/**\n * Search blocks by query (searches name, description, and semantic tags)\n */\nexport function searchBlocks(query: string): BlockRegistryEntry[] {\n const lowercaseQuery = query.toLowerCase();\n return Object.values(BLOCK_REGISTRY).filter(\n (block) =>\n block.name.toLowerCase().includes(lowercaseQuery) ||\n block.description.toLowerCase().includes(lowercaseQuery) ||\n block.semanticTags.some((tag) =>\n tag.toLowerCase().includes(lowercaseQuery)\n )\n );\n}\n"]}