'use client' import React from 'react' import { cn } from '../../utils/cn' import type { ActionsMenuGroup } from '../ui/actions-menu' import { PageActions, type PageActionButton } from '../ui/page-actions' import { BackButton } from './back-button' // Legacy interface for backward compatibility (layout version) interface LegacyPageContainerProps { children: React.ReactNode; className?: string; /** Whether to apply full-width background to the entire section */ fullWidthBackground?: boolean; /** Custom background style/className for the section wrapper */ backgroundClassName?: string; /** Custom background style object */ backgroundStyle?: React.CSSProperties; /** Custom padding for the content container (overrides default responsive padding) */ contentPadding?: string; /** Custom max-width for the content container (default: max-w-[1920px]) */ maxWidth?: string; /** HTML element type for the container */ as?: 'section' | 'div' | 'main' | 'article'; /** HTML id for the container */ id?: string; } // New advanced interface (UI version) interface AdvancedPageContainerProps { /** * Page content */ children: React.ReactNode /** * Page variant determines layout structure */ variant?: 'list' | 'detail' | 'form' | 'content' /** * Page title (displayed as h1) */ title?: string /** * Subtitle or description (supports both string and ReactNode) */ subtitle?: string | React.ReactNode /** * Back button configuration */ backButton?: { label?: string onClick: () => void } /** * Header actions (buttons, controls, etc.) * Can be used together with or instead of `actions` prop */ headerActions?: React.ReactNode /** * Page action buttons configuration * Automatically renders PageActions component with appropriate variant: * - 'list' variant → 'icon-buttons' (collapses to menu on mobile) * - 'detail'/'form' variants → 'primary-buttons' (fixed bottom on mobile) */ actions?: PageActionButton[] /** * Override the automatically determined PageActions variant */ actionsVariant?: 'icon-buttons' | 'primary-buttons' | 'menu-primary' /** * Page action menu items configuration */ menuActions?: ActionsMenuGroup[] /** * Custom header content (overrides title/subtitle) */ headerContent?: React.ReactNode /** * Container padding */ padding?: 'none' | 'sm' | 'md' | 'lg' /** * Container background */ background?: 'default' | 'card' | 'transparent' /** * Additional CSS classes for container */ className?: string /** * Additional CSS classes for content area */ contentClassName?: string /** * Whether to show the standard header section */ showHeader?: boolean } // Union type that supports both interfaces export type PageContainerProps = LegacyPageContainerProps | AdvancedPageContainerProps // Type guard to determine which interface is being used function isAdvancedProps(props: PageContainerProps): props is AdvancedPageContainerProps { return 'variant' in props || 'title' in props || 'subtitle' in props || 'backButton' in props || 'headerActions' in props || 'headerContent' in props || 'showHeader' in props || 'contentClassName' in props || 'actions' in props || 'actionsVariant' in props } /** * @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. * * Unified Page Container Component * * Supports both legacy layout patterns and advanced UI patterns: * * LEGACY USAGE (backward compatible): * *

Your Content

*
* * ADVANCED USAGE (new features): * {}}}> *
Your Content
*
*/ export function PageContainer(props: PageContainerProps) { if (isAdvancedProps(props)) { return renderAdvancedPageContainer(props) } else { return renderLegacyPageContainer(props) } } // Legacy implementation (preserves original behavior exactly) function renderLegacyPageContainer({ children, className = '', fullWidthBackground = true, backgroundClassName = 'bg-ods-bg', backgroundStyle, contentPadding, maxWidth = 'max-w-[1920px]', as: Component = 'section', id }: LegacyPageContainerProps) { const content = (
{children}
); if (fullWidthBackground) { return ( {content} ); } // If fullWidthBackground is false, apply background to content container only return (
{children}
); } // Advanced implementation (from UI component) function renderAdvancedPageContainer({ children, variant = 'content', title, subtitle, backButton, headerActions, headerContent, actions, actionsVariant, menuActions, padding = 'none', background = 'transparent', className, contentClassName, showHeader = true }: AdvancedPageContainerProps) { // Determine PageActions variant based on page variant const getActionsVariant = () => { if (actionsVariant) return actionsVariant // List pages use icon-buttons (collapses to menu on mobile) if (variant === 'list') return 'icon-buttons' // Detail/form pages use primary-buttons (fixed bottom on mobile) return 'primary-buttons' } // Render actions component const renderActions = () => { if (!actions || actions.length === 0) return null return } // Check if we need bottom padding for mobile fixed actions const needsBottomPadding = actions && actions.length > 0 && getActionsVariant() === 'primary-buttons' const paddingClasses = { none: '', sm: 'p-4', md: 'p-6', lg: 'p-8' } const backgroundClasses = { default: 'bg-ods-bg', card: 'bg-ods-card', transparent: '' } const renderHeader = () => { if (!showHeader) return null if (headerContent) { return (
{headerContent}
) } if (variant === 'detail') { return (
{/* Back Button */} {backButton && ( )} {/* Title */} {title && (

{title}

)} {/* Subtitle */} {subtitle && (
{subtitle}
)}
{/* Header Actions */} {(headerActions || actions) && (
{headerActions} {renderActions()}
)}
) } if (variant === 'list') { return (
{/* Back Button */} {backButton && ( )} {title && (

{title}

)} {subtitle && (
{subtitle}
)}
{/* Header Actions */} {(headerActions || actions) && (
{headerActions} {renderActions()}
)}
) } if (variant === 'form') { return (
{/* Back Button */} {backButton && ( )} {title && (

{title}

)}
{/* Header Actions */} {(headerActions || actions) && (
{headerActions} {renderActions()}
)}
) } // Default content header return (
{(title || subtitle) && (
{title && (

{title}

)} {subtitle && (
{subtitle}
)}
)} {(headerActions || actions) && (
{headerActions} {renderActions()}
)}
) } const getContainerClasses = () => { const baseClasses = [ 'flex flex-col w-full', backgroundClasses[background], paddingClasses[padding] ] switch (variant) { case 'list': return cn(baseClasses, 'gap-4 md:gap-6', className) case 'detail': return cn(baseClasses, 'gap-4 md:gap-6', className) case 'form': return cn(baseClasses, 'gap-6 md:gap-10', className) case 'content': default: return cn(baseClasses, 'gap-4 md:gap-6', className) } } const getContentClasses = () => { // Add bottom padding on mobile when using primary-buttons variant (fixed bottom bar) const mobilePadding = needsBottomPadding ? 'pb-28 md:pb-0' : '' switch (variant) { case 'detail': return cn('flex-1 overflow-auto', mobilePadding, contentClassName) case 'list': return cn('flex flex-col gap-4 md:gap-6', mobilePadding, contentClassName) case 'form': return cn('flex flex-col gap-4 md:gap-10', mobilePadding, contentClassName) case 'content': default: return cn('flex-1', mobilePadding, contentClassName) } } return (
{renderHeader()}
{children}
) } /** @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. */ export const ListPageContainer = (props: Omit) => /** @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. */ export const DetailPageContainer = (props: Omit) => /** @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. */ export const FormPageContainer = (props: Omit) => /** @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. */ export const ContentPageContainer = (props: Omit) => // Re-export PageActionButton type for convenience export type { PageActionButton } from '../ui/page-actions' /** @deprecated Use `PageLayout` from `'../layout/page-layout'` instead. */ export default PageContainer;