UNPKG

lumir-design-system-02

Version:
1,913 lines 94.7 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { Surface, Frame, Icon, Text, Sizing, Asterisk, Divider } from 'lumir-design-system-shared';
import React, { forwardRef, useState, useRef, useEffect, createContext, useContext } from 'react';

const Badge = ({ color, size = 'md', layout = 'only text', style = 'filled', type = 'round-square', text, iconName, iconType = 'line', className, disabled, }) => {
    // 크기별 텍스트 variant 매핑
    const getTextVariant = (size) => {
        switch (size) {
            case 'lg':
                return 'label-1'; // label-1 medium
            case 'md':
                return 'label-2'; // label-2 medium
            case 'sm':
                return 'caption-2'; // caption-2 medium
        }
    };
    // 크기별 아이콘-텍스트 간격 매핑 (Frame gap) - System-02: Modern & Friendly
    const getContentGap = (size) => {
        switch (size) {
            case 'lg': return 'xs'; // xxs → xs (더 넓은 간격)
            case 'md': return 'xs'; // xxs → xs (더 넓은 간격)  
            case 'sm': return 'xxs'; // 작은 크기는 유지
        }
    };
    // 스타일별 배경색 결정
    const getBackgroundColor = () => {
        if (style === 'filled') {
            switch (color) {
                case 'primary': return 'primary-system02-1-rest';
                case 'secondary': return 'secondary-system02-1-rest';
                case 'cta': return 'cta-system02-1-rest';
                case 'error': return 'error';
                case 'warning': return 'warning';
                default: return 'primary-system02-1-rest';
            }
        }
        return undefined; // outlined, transparent 스타일은 배경 투명
    };
    // 스타일별 테두리 색상 결정
    const getBorderColor = () => {
        if (style === 'outlined') {
            switch (color) {
                case 'primary': return 'primary-system02-1-rest';
                case 'secondary': return 'secondary-system02-1-rest';
                case 'cta': return 'cta-system02-1-rest';
                case 'error': return 'error';
                case 'warning': return 'warning';
                default: return 'primary-system02-1-rest';
            }
        }
        return undefined; // filled, transparent 스타일은 테두리 없음
    };
    // 스타일별 전경색 결정 (텍스트와 아이콘 모두 적용)
    const getForegroundColor = () => {
        // disabled 상태 처리
        if (disabled)
            return 'secondary-system02-2-disabled';
        if (style === 'filled') {
            switch (color) {
                case 'primary':
                case 'cta':
                    // primary, cta filled일 때는 oncolor 사용
                    return 'primary-system02-oncolor';
                case 'error':
                case 'warning':
                    return 'secondary-system02-oncolor';
                case 'secondary': return 'secondary-system02-2-rest';
                default: return 'primary-system02-oncolor';
            }
        }
        else {
            // outlined, transparent 스타일
            switch (color) {
                case 'primary': return 'primary-system02-1-rest';
                case 'secondary': return 'secondary-system02-1-rest';
                case 'cta': return 'cta-system02-1-rest';
                case 'error': return 'error';
                case 'warning': return 'warning';
                default: return 'secondary-system02-1-rest';
            }
        }
    };
    // 형태별 border radius 매핑 (System-02: 더 둥근 모서리)
    const getBorderRadius = (type) => {
        return type === 'circle' ? 'circular' : 'xl'; // System-02 가이드라인: xl 사용 (더 친근한 느낌)
    };
    // 크기별 아이콘 크기 매핑
    const getIconSize = (size) => {
        switch (size) {
            case 'lg': return 'sm'; // 16px
            case 'md': return 'sm'; // 16px
            case 'sm': return 'xs'; // 12px
        }
    };
    const backgroundColor = getBackgroundColor();
    const borderColor = getBorderColor();
    const foregroundColor = getForegroundColor();
    const textVariant = getTextVariant(size);
    const iconSize = getIconSize(size);
    const contentGap = getContentGap(size);
    const borderRadius = getBorderRadius(type);
    return (jsx(Surface, { background: backgroundColor, foreground: foregroundColor, borderColor: borderColor, borderWidth: borderColor ? 'thin' : undefined, borderStyle: borderColor ? 'solid' : 'none', borderRadius: borderRadius, className: className, style: { width: 'fit-content', height: 'fit-content' }, children: jsxs(Frame, { display: "flex", direction: "row", align: "center", justify: "center", gap: contentGap, padding: "xxs" // System-02: Badge는 컴팩트하게 유지 (xxs)
            , children: [(layout === 'text+icon' || layout === 'only icon') && iconName && (jsx(Icon, { name: iconName, size: iconSize })), (layout === 'text+icon' || layout === 'only text') && text && (jsx(Text, { variant: textVariant, weight: "regular" // System-02: medium → regular (더 부드러운 느낌)
                    , children: text }))] }) }));
};

/**
 * Button 컴포넌트는 사용자 상호작용을 위한 기본적인 요소입니다.
 * Lumir Design System의 스타일링을 따르며, 시맨틱 토큰을 사용하여 일관된 디자인을 제공합니다.
 */
const Button = forwardRef(({ variant = 'filled', buttonType = 'text-only', colorScheme = 'primary', size = 'md', isFullWidth = false, textAlign = 'center', isLoading = false, isSelected = false, disabled = false, leftIcon, rightIcon, className, children, ...rest }, ref) => {
    // 마우스 상태 관리 추가
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    // 마우스 이벤트 핸들러들
    const handleMouseEnter = () => {
        if (!disabled && !isLoading) {
            setIsHovered(true);
        }
    };
    const handleMouseLeave = () => {
        setIsHovered(false);
        setIsPressed(false);
    };
    const handleMouseDown = () => {
        if (!disabled && !isLoading) {
            setIsPressed(true);
        }
    };
    const handleMouseUp = () => {
        setIsPressed(false);
    };
    const resolveButtonType = () => {
        if (buttonType === 'icon-only' && (leftIcon || rightIcon)) {
            return 'icon-only';
        }
        if (buttonType === 'text-icon' && (leftIcon || rightIcon)) {
            return 'text-icon';
        }
        return 'text-only';
    };
    const actualButtonType = resolveButtonType();
    // 크기별 높이 토큰 결정 (Sizing 컴포넌트용)
    const getSizingHeight = () => {
        switch (size) {
            case 'xs': return 'sm'; // 24px
            case 'sm': return 'md'; // 28px  
            case 'md': return 'lg'; // 32px
            case 'lg': return 'xl'; // 36px
            case 'xl': return 'xxl'; // 40px
            default: return 'lg';
        }
    };
    // 크기별 텍스트 variant 결정 (텍스트: xl(16), lg(16), md(14), sm(14), xs(12))
    const getTextVariant = () => {
        switch (size) {
            case 'xs': return 'label-2'; // 12px
            case 'sm': return 'body-2'; // 14px
            case 'md': return 'body-2'; // 14px
            case 'lg': return 'body-1'; // 16px
            case 'xl': return 'body-1'; // 16px
            default: return 'body-2';
        }
    };
    // 크기별 아이콘 크기 결정 (System-02: 더 큰 아이콘 사용)
    const getIconSize = () => {
        switch (size) {
            case 'xs': return 'xs'; // 12px
            case 'sm': return 'sm'; // 16px (xs → sm)
            case 'md': return 'md'; // 20px (xs → md)  
            case 'lg': return 'lg'; // 24px (sm → lg)
            case 'xl': return 'xl'; // 28px (md → xl)
            default: return 'md';
        }
    };
    // 크기별 패딩 결정 (System-02: Modern & Friendly - 더 여유로운 패딩)
    const getPadding = () => {
        switch (size) {
            case 'xs': return 'sm'; // xs → sm (더 여유로운)
            case 'sm': return 'sm'; // xs → sm
            case 'md': return 'md'; // sm → md
            case 'lg': return 'lg'; // md → lg
            case 'xl': return 'xl'; // lg → xl
            default: return 'md';
        }
    };
    // 배경색 결정 (hover/active 상태 포함)
    const getBackgroundColor = () => {
        const currentState = getCurrentState();
        if (variant === 'filled') {
            if (colorScheme === 'primary') {
                if (currentState === 'disabled')
                    return 'primary-system02-1-disabled';
                if (currentState === 'pressed')
                    return 'primary-system02-1-pressed';
                if (currentState === 'hovered')
                    return 'primary-system02-1-hovered';
                return 'primary-system02-1-rest';
            }
            if (colorScheme === 'secondary') {
                if (currentState === 'disabled')
                    return 'secondary-system02-2-disabled';
                if (currentState === 'pressed')
                    return 'secondary-system02-2-pressed';
                if (currentState === 'hovered')
                    return 'secondary-system02-2-hovered';
                return 'secondary-system02-2-rest';
            }
            if (colorScheme === 'cta') {
                if (currentState === 'disabled')
                    return 'cta-system02-1-disabled';
                if (currentState === 'pressed')
                    return 'cta-system02-1-pressed';
                if (currentState === 'hovered')
                    return 'cta-system02-1-hovered';
                return 'cta-system02-1-rest';
            }
        }
        if (variant === 'outlined') {
            // outlined는 연한 배경색 위계 사용 (background-3 = 더 subtle)
            if (currentState === 'rest' || currentState === 'disabled')
                return undefined;
            if (currentState === 'hovered') {
                if (colorScheme === 'primary')
                    return 'secondary-system02-3-hovered'; // 연한 배경
                if (colorScheme === 'secondary')
                    return 'secondary-system02-3-hovered';
                if (colorScheme === 'cta')
                    return 'secondary-system02-3-hovered';
            }
            if (currentState === 'pressed') {
                if (colorScheme === 'primary')
                    return 'secondary-system02-3-pressed'; // 연한 배경
                if (colorScheme === 'secondary')
                    return 'secondary-system02-3-pressed';
                if (colorScheme === 'cta')
                    return 'secondary-system02-3-pressed';
            }
            return undefined;
        }
        if (variant === 'transparent') {
            // transparent는 항상 배경색 없음 (텍스트 색상만 변경)
            return undefined;
        }
        return 'primary-system02-1-rest';
    };
    // 전경색 결정 (hover/active 상태 포함)
    const getForegroundColor = () => {
        const currentState = getCurrentState();
        if (variant === 'filled') {
            // filled는 onColor 사용 (배경색 위에 올라가는 텍스트)
            if (colorScheme === 'primary') {
                if (currentState === 'disabled')
                    return 'secondary-system02-3-disabled'; // 대비되는 disabled 색상 사용
                return 'primary-system02-oncolor'; // onColor 사용
            }
            if (colorScheme === 'secondary') {
                if (currentState === 'disabled')
                    return 'secondary-system02-3-disabled'; // 대비되는 disabled 색상 사용
                return 'secondary-system02-oncolor'; // onColor 사용
            }
            if (colorScheme === 'cta') {
                if (currentState === 'disabled')
                    return 'secondary-system02-3-disabled'; // 대비되는 disabled 색상 사용
                return 'cta-system02-oncolor'; // onColor 사용
            }
        }
        if (variant === 'outlined' || variant === 'transparent') {
            // outlined/transparent는 일반 foreground 색상 사용
            if (currentState === 'disabled') {
                return 'secondary-system02-2-disabled';
            }
            // hover/pressed 상태에서는 더 진한 색상 사용
            if (currentState === 'hovered') {
                if (colorScheme === 'primary')
                    return 'primary-system02-1-hovered'; // 연한 색상 위계
                if (colorScheme === 'secondary')
                    return 'secondary-system02-1-hovered';
                if (colorScheme === 'cta')
                    return 'cta-system02-1-hovered';
            }
            if (currentState === 'pressed') {
                if (colorScheme === 'primary')
                    return 'primary-system02-1-pressed';
                if (colorScheme === 'secondary')
                    return 'secondary-system02-1-pressed';
                if (colorScheme === 'cta')
                    return 'cta-system02-1-pressed';
            }
            // rest 상태
            if (colorScheme === 'primary')
                return 'primary-system02-1-rest';
            if (colorScheme === 'secondary')
                return 'secondary-system02-1-rest';
            if (colorScheme === 'cta')
                return 'cta-system02-1-rest';
            return 'secondary-system02-2-disabled';
        }
        return 'primary-system02-1-rest';
    };
    // 테두리 속성 결정 (outlined 버튼용)
    const getBorderProps = () => {
        if (variant !== 'outlined')
            return {};
        const currentState = getCurrentState();
        if (colorScheme === 'primary') {
            let borderColor = 'secondary-system02-2-rest';
            if (currentState === 'disabled')
                borderColor = 'secondary-system02-3-disabled';
            else if (currentState === 'pressed')
                borderColor = 'primary-system02-1-pressed';
            else if (currentState === 'hovered')
                borderColor = 'primary-system02-1-hovered';
            else
                borderColor = 'primary-system02-1-rest';
            return { borderWidth: 'thin', borderColor };
        }
        if (colorScheme === 'secondary') {
            let borderColor = 'secondary-system02-2-rest';
            if (currentState === 'disabled')
                borderColor = 'secondary-system02-2-disabled';
            else if (currentState === 'pressed')
                borderColor = 'secondary-system02-1-pressed';
            else if (currentState === 'hovered')
                borderColor = 'secondary-system02-1-hovered';
            else
                borderColor = 'secondary-system02-1-rest';
            return { borderWidth: 'thin', borderColor };
        }
        if (colorScheme === 'cta') {
            let borderColor = 'secondary-system02-2-rest';
            if (currentState === 'disabled')
                borderColor = 'secondary-system02-3-disabled';
            else if (currentState === 'pressed')
                borderColor = 'cta-system02-1-pressed';
            else if (currentState === 'hovered')
                borderColor = 'cta-system02-1-hovered';
            else
                borderColor = 'cta-system02-1-rest';
            return { borderWidth: 'thin', borderColor };
        }
        return { borderWidth: 'thin', borderColor: 'secondary-system02-2-rest' };
    };
    // 현재 상태 결정
    const getCurrentState = () => {
        if (disabled || isLoading)
            return 'disabled';
        if (isPressed)
            return 'pressed';
        if (isHovered)
            return 'hovered';
        return 'rest';
    };
    // full width일 때 정렬 방식 결정
    const getJustifyContent = () => {
        if (!isFullWidth)
            return 'center';
        switch (textAlign) {
            case 'left': return 'flex-start';
            case 'right': return 'flex-end';
            case 'center':
            default: return 'center';
        }
    };
    // onClick과 style을 제외한 나머지 props
    const { onClick, style: customStyle, color, ...otherProps } = rest;
    const borderProps = getBorderProps();
    return (jsx(Surface, { ref: ref, background: getBackgroundColor(), foreground: getForegroundColor(), borderRadius: "xl" // System-02: md → lg (더 둥근 모서리)
        , borderWidth: borderProps.borderWidth, borderColor: borderProps.borderColor, borderStyle: borderProps.borderWidth ? 'solid' : 'none', boxShadow: "20" // System-02: 부드러운 그림자 추가
        , className: className, onClick: disabled || isLoading ? undefined : onClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, style: {
            cursor: disabled || isLoading ? 'not-allowed' : 'pointer',
            ...customStyle
        }, ...otherProps, children: jsx(Sizing, { height: getSizingHeight(), width: isFullWidth ? '100%' : 'fit-content', children: jsxs(Frame, { display: "flex", direction: "row", align: "center", justify: getJustifyContent(), gap: "md" // System-02: sm → md (더 넓은 간격)
                , fill: true, padding: getPadding(), children: [isLoading && (jsx(Icon, { name: "LineIconsMenuMenuIcon", size: getIconSize(), "aria-hidden": true })), leftIcon && !isLoading && (jsx(Icon, { name: leftIcon, size: getIconSize(), "aria-hidden": true })), (actualButtonType !== 'icon-only' && children) && (jsx(Text, { as: "span", variant: getTextVariant(), weight: "regular" // System-02: medium → regular (더 부드러운 느낌)
                        , children: children })), rightIcon && !isLoading && (jsx(Icon, { name: rightIcon, size: getIconSize(), "aria-hidden": true }))] }) }) }));
});
Button.displayName = 'Button';

/**
 * TextDisplay 컴포넌트는 다양한 텍스트 요소들을 조합하여 표시하는 컴파운드 컴포넌트입니다.
 * 라벨, 메인 텍스트, 설명, 캡션을 선택적으로 표시할 수 있으며, 아이콘도 함께 표시할 수 있습니다.
 *
 * @example
 * ```tsx
 * // 기본 사용법
 * <TextDisplay
 *   primaryText="Hello World"
 * />
 *
 * // 모든 요소 포함
 * <TextDisplay
 *   size="lg"
 *   style="center"
 *   iconPosition="above"
 *   iconName="star-filled"
 *   iconType="flat"
 *   showLabel={true}
 *   labelText="Status"
 *   primaryText="Success"
 *   showDescription={true}
 *   descriptionText="Your operation completed successfully"
 *   showCaption={true}
 *   captionText="Last updated: 2024-01-01"
 * />
 *
 * // 좌측 정렬 + 앞쪽 아이콘
 * <TextDisplay
 *   style="left"
 *   iconPosition="before"
 *   iconName="info"
 *   primaryText="Information"
 *   showDescription={true}
 *   descriptionText="Additional details here"
 * />
 * ```
 */
const TextDisplay = forwardRef(({ size = 'md', style = 'left', iconPosition = 'none', iconName = 'LineIconsStarFilledIcon', iconType = 'line', showLabel = false, labelText = 'label', primaryText, showDescription = false, descriptionText = 'description text', showCaption = false, captionText = 'caption', className, ...rest }, ref) => {
    // 크기별 텍스트 variant 매핑 (피그마 실제 크기 기준 - 수정됨)
    const getTextVariants = (size) => {
        switch (size) {
            case 'xlg':
                return {
                    label: 'body-2', // 14px (피그마는 15px이지만 가장 근접한 토큰)
                    primary: 'title-2', // 24px (lg의 20px에서 자연스러운 다음 단계)
                    description: 'heading-3', // 16px (피그마는 18px이지만 가장 근접한 토큰)
                    caption: 'body-2', // 14px (피그마는 15px이지만 가장 근접한 토큰)
                };
            case 'lg':
                return {
                    label: 'label-1', // 14px (정확히 일치)
                    primary: 'heading-1', // 20px (md와 lg 사이의 자연스러운 중간 단계)
                    description: 'body-1', // 16px (정확히 일치)
                    caption: 'label-1', // 14px (정확히 일치)
                };
            case 'md':
                return {
                    label: 'label-2', // 12px (피그마는 13px이지만 가장 근접한 토큰)
                    primary: 'heading-3', // 16px (피그마는 18px이지만 가장 근접한 토큰)
                    description: 'label-1', // 14px (정확히 일치)
                    caption: 'label-2', // 12px (피그마는 13px이지만 가장 근접한 토큰)
                };
            case 'sm':
                return {
                    label: 'caption-1', // 12px (정확히 일치)
                    primary: 'body-1', // 16px (정확히 일치)
                    description: 'label-1', // 14px (정확히 일치)
                    caption: 'caption-1', // 12px (정확히 일치)
                };
            case 'xsm':
                return {
                    label: 'caption-1', // 12px (정확히 일치)
                    primary: 'label-1', // 14px (정확히 일치)
                    description: 'caption-1', // 12px (정확히 일치)
                    caption: 'caption-3', // 11px (정확히 일치)
                };
        }
    };
    // 크기별 font weight 매핑 (피그마 기준)
    const getTextWeights = (size) => {
        switch (size) {
            case 'xlg':
                return {
                    label: 'regular', // 400
                    primary: 'bold', // 700
                    description: 'regular', // 400
                    caption: 'regular', // 400
                };
            case 'lg':
                return {
                    label: 'regular', // 400
                    primary: 'bold', // 700
                    description: 'regular', // 400
                    caption: 'regular', // 400
                };
            case 'md':
                return {
                    label: 'regular', // 400
                    primary: 'bold', // 700
                    description: 'regular', // 400
                    caption: 'regular', // 400
                };
            case 'sm':
                return {
                    label: 'regular', // 400
                    primary: 'bold', // 700
                    description: 'regular', // 400
                    caption: 'regular', // 400
                };
            case 'xsm':
                return {
                    label: 'regular', // 400
                    primary: 'bold', // 700
                    description: 'regular', // 400
                    caption: 'regular', // 400
                };
        }
    };
    // 크기별 아이콘 크기 매핑
    const getIconSize = (size) => {
        switch (size) {
            case 'xlg': return 'lg';
            case 'lg': return 'md';
            case 'md': return 'sm';
            case 'sm': return 'xs';
            case 'xsm': return 'xs';
        }
    };
    // Surface foreground 색상 결정
    const getForegroundColors = () => {
        return {
            label: 'secondary-system02-2-rest',
            primary: 'secondary-system02-1-rest',
            description: 'secondary-system02-2-rest',
            caption: 'secondary-system02-3-rest',
        };
    };
    const textVariants = getTextVariants(size);
    const textWeights = getTextWeights(size);
    const iconSize = getIconSize(size);
    const foregroundColors = getForegroundColors();
    // 아이콘 렌더링
    const renderIcon = () => {
        if (iconPosition === 'none' || !iconName)
            return null;
        return (jsx(Icon, { name: iconName, size: iconSize }));
    };
    // 텍스트 콘텐츠 렌더링
    const renderTextContent = () => {
        const alignItems = style === 'center' ? 'center' : 'flex-start';
        const textAlign = style === 'center' ? 'center' : 'left';
        return (jsxs(Frame, { display: "flex", direction: "column", gap: "xxxs", align: alignItems, children: [showLabel && labelText && (jsx(Surface, { foreground: foregroundColors.label, children: jsx(Text, { variant: textVariants.label, weight: textWeights.label, textAlign: textAlign, children: labelText }) })), primaryText && (jsx(Surface, { foreground: foregroundColors.primary, children: jsx(Text, { variant: textVariants.primary, weight: textWeights.primary, textAlign: textAlign, children: primaryText }) })), showDescription && descriptionText && (jsx(Surface, { foreground: foregroundColors.description, children: jsx(Text, { variant: textVariants.description, weight: textWeights.description, textAlign: textAlign, children: descriptionText }) })), showCaption && captionText && (jsx(Surface, { foreground: foregroundColors.caption, children: jsx(Text, { variant: textVariants.caption, weight: textWeights.caption, textAlign: textAlign, children: captionText }) }))] }));
    };
    // 레이아웃 구성
    if (iconPosition === 'above') {
        // 아이콘이 위에 있는 경우 (세로 레이아웃)
        return (jsx("div", { ref: ref, className: className, ...rest, children: jsxs(Frame, { display: "flex", direction: "column", gap: "sm", align: "center", children: [renderIcon(), renderTextContent()] }) }));
    }
    else if (iconPosition === 'before' || iconPosition === 'after') {
        // 아이콘이 앞뒤에 있는 경우 (가로 레이아웃)
        return (jsx("div", { ref: ref, className: className, ...rest, children: jsxs(Frame, { display: "flex", direction: "row", gap: "sm", align: "center", children: [iconPosition === 'before' && renderIcon(), renderTextContent(), iconPosition === 'after' && renderIcon()] }) }));
    }
    else {
        // 아이콘이 없는 경우
        return (jsx("div", { ref: ref, className: className, ...rest, children: renderTextContent() }));
    }
});
TextDisplay.displayName = 'TextDisplay';

const Card = ({ variant = "filled", title, badge, showBadge = true, description, actionButton, showActionButton = true, imageUrl, showImage = true, imageHeight = "242", imageObjectFit = "cover", imageObjectPosition = "center", imageAspectRatio, size, textStyle, showLabel, labelText, showDescription, showCaption, captionText, onClick, className, width = '100%', minWidth, maxWidth, // maxWidth 제한 제거 - Grid에서 자유롭게 확장 가능
badgeText, badgeColor, badgeIconName, badgeSize, badgeStyle, badgeLayout, badgeType, 
// Button props
buttonVariant = "filled", buttonType = "icon-only", buttonColorScheme = "primary", buttonSize = "md", buttonPosition = "top-right", buttonText, buttonIcon, buttonRightIcon, buttonIsFullWidth = false, buttonIsSelected = false, }) => {
    const handleClick = () => {
        if (onClick) {
            onClick();
        }
    };
    const handleActionClick = (e) => {
        e.stopPropagation();
        if (actionButton === null || actionButton === void 0 ? void 0 : actionButton.onClick) {
            actionButton.onClick(e);
        }
    };
    // Variant에 따른 스타일 설정
    const getCardStyles = () => {
        switch (variant) {
            case 'filled':
                return {
                    background: "secondary-system02-1-rest",
                    borderColor: "secondary-system02-2-rest",
                    borderWidth: "thin",
                    borderStyle: "solid",
                    boxShadow: "20", // Foundation shadow 토큰 사용
                };
            case 'outlined':
                return {
                    background: undefined,
                    borderColor: "secondary-system02-2-rest",
                    borderWidth: "thin",
                    borderStyle: "solid",
                    boxShadow: undefined,
                };
            case 'transparent':
                return {
                    background: undefined,
                    borderColor: undefined,
                    borderWidth: undefined,
                    borderStyle: undefined,
                    boxShadow: undefined,
                };
            default:
                return {
                    background: "secondary-system02-1-rest",
                    borderColor: "secondary-system02-2-rest",
                    borderWidth: "thin",
                    borderStyle: "solid",
                    boxShadow: "20", // 더 자연스러운 그림자를 위해 20 사용
                };
        }
    };
    const cardStyles = getCardStyles();
    return (jsx(Sizing, { width: width, minWidth: minWidth, maxWidth: maxWidth, className: className, children: jsx(Surface, { borderRadius: variant === 'transparent' ? undefined : "xl", background: cardStyles.background, borderColor: cardStyles.borderColor, borderWidth: cardStyles.borderWidth, borderStyle: cardStyles.borderStyle, boxShadow: cardStyles.boxShadow, onClick: handleClick, children: jsxs(Frame, { display: "flex", direction: "column", gap: "xxl", padding: variant === 'transparent' ? undefined : "lg", children: [showImage && (jsx(Sizing, { height: imageHeight, aspectRatio: imageAspectRatio, children: jsx(Surface, { borderRadius: "lg" // 10px (피그마와 동일)
                            , children: imageUrl ? (jsx(Sizing, { width: "100%", height: "100%", objectFit: imageObjectFit, objectPosition: imageObjectPosition, children: jsx("img", { src: imageUrl, alt: title, style: {
                                        width: '100%',
                                        height: '100%',
                                        display: 'block'
                                    } }) })) : (jsx(Frame, { display: "flex", align: "center", justify: "center", fill: true, children: jsx(TextDisplay, { size: "lg", style: "center", primaryText: "Product" }) })) }) })), buttonPosition === 'bottom-full' ? (
                    /* bottom-full: 텍스트 아래에 full-width 버튼 */
                    jsxs(Frame, { display: "flex", direction: "column", gap: "lg", children: [jsxs(Frame, { display: "flex", direction: "column", gap: "xs", children: [showBadge && (badge || badgeText) && (jsx(Badge, { text: badgeText || (badge === null || badge === void 0 ? void 0 : badge.text) || 'Badge', color: badgeColor || (badge === null || badge === void 0 ? void 0 : badge.color) || 'primary', iconName: badgeIconName || (badge === null || badge === void 0 ? void 0 : badge.iconName), size: badgeSize || (badge === null || badge === void 0 ? void 0 : badge.size) || 'sm', style: badgeStyle || (badge === null || badge === void 0 ? void 0 : badge.style) || 'filled', layout: badgeLayout || (badge === null || badge === void 0 ? void 0 : badge.layout) || 'only text', type: badgeType || (badge === null || badge === void 0 ? void 0 : badge.type) || 'round-square' })), jsx(TextDisplay, { size: size || 'md', style: textStyle || 'left', primaryText: title, showLabel: showLabel, labelText: labelText, showDescription: showDescription && !!description, descriptionText: description, showCaption: showCaption, captionText: captionText })] }), showActionButton && (jsx(Button, { variant: buttonVariant, buttonType: buttonType, colorScheme: buttonColorScheme, size: buttonSize, leftIcon: buttonIcon || (actionButton === null || actionButton === void 0 ? void 0 : actionButton.iconName) || 'LineIconsPlusPlusIcon', rightIcon: buttonRightIcon, isFullWidth: true, isSelected: buttonIsSelected, disabled: actionButton === null || actionButton === void 0 ? void 0 : actionButton.disabled, isLoading: actionButton === null || actionButton === void 0 ? void 0 : actionButton.isLoading, onClick: handleActionClick, ...actionButton === null || actionButton === void 0 ? void 0 : actionButton.buttonProps, children: buttonText }))] })) : buttonPosition === 'bottom-right' ? (
                    /* bottom-right: 전체를 세로로 배치하고 마지막에 우측 정렬 버튼 */
                    jsxs(Frame, { display: "flex", direction: "column", gap: "lg", children: [jsxs(Frame, { display: "flex", direction: "column", gap: "xs", children: [showBadge && (badge || badgeText) && (jsx(Badge, { text: badgeText || (badge === null || badge === void 0 ? void 0 : badge.text) || 'Badge', color: badgeColor || (badge === null || badge === void 0 ? void 0 : badge.color) || 'primary', iconName: badgeIconName || (badge === null || badge === void 0 ? void 0 : badge.iconName), size: badgeSize || (badge === null || badge === void 0 ? void 0 : badge.size) || 'sm', style: badgeStyle || (badge === null || badge === void 0 ? void 0 : badge.style) || 'filled', layout: badgeLayout || (badge === null || badge === void 0 ? void 0 : badge.layout) || 'only text', type: badgeType || (badge === null || badge === void 0 ? void 0 : badge.type) || 'round-square' })), jsx(TextDisplay, { size: size || 'md', style: textStyle || 'left', primaryText: title, showLabel: showLabel, labelText: labelText, showDescription: showDescription && !!description, descriptionText: description, showCaption: showCaption, captionText: captionText })] }), showActionButton && (jsx(Frame, { display: "flex", justify: "flex-end", children: jsx(Button, { variant: buttonVariant, buttonType: buttonType, colorScheme: buttonColorScheme, size: buttonSize, leftIcon: buttonIcon || (actionButton === null || actionButton === void 0 ? void 0 : actionButton.iconName) || 'LineIconsPlusPlusIcon', rightIcon: buttonRightIcon, isFullWidth: buttonIsFullWidth, isSelected: buttonIsSelected, disabled: actionButton === null || actionButton === void 0 ? void 0 : actionButton.disabled, isLoading: actionButton === null || actionButton === void 0 ? void 0 : actionButton.isLoading, onClick: handleActionClick, ...actionButton === null || actionButton === void 0 ? void 0 : actionButton.buttonProps, children: buttonText }) }))] })) : (
                    /* top-right (기본): 기존 가로 배치 */
                    jsxs(Frame, { display: "flex", direction: "row", justify: "space-between", align: "flex-start", gap: "xxl", children: [jsxs(Frame, { display: "flex", direction: "column", gap: "xs", children: [showBadge && (badge || badgeText) && (jsx(Badge, { text: badgeText || (badge === null || badge === void 0 ? void 0 : badge.text) || 'Badge', color: badgeColor || (badge === null || badge === void 0 ? void 0 : badge.color) || 'primary', iconName: badgeIconName || (badge === null || badge === void 0 ? void 0 : badge.iconName), size: badgeSize || (badge === null || badge === void 0 ? void 0 : badge.size) || 'sm', style: badgeStyle || (badge === null || badge === void 0 ? void 0 : badge.style) || 'filled', layout: badgeLayout || (badge === null || badge === void 0 ? void 0 : badge.layout) || 'only text', type: badgeType || (badge === null || badge === void 0 ? void 0 : badge.type) || 'round-square' })), jsx(TextDisplay, { size: size || 'md', style: textStyle || 'left', primaryText: title, showLabel: showLabel, labelText: labelText, showDescription: showDescription && !!description, descriptionText: description, showCaption: showCaption, captionText: captionText })] }), showActionButton && (jsx(Button, { variant: buttonVariant, buttonType: buttonType, colorScheme: buttonColorScheme, size: buttonSize, leftIcon: buttonIcon || (actionButton === null || actionButton === void 0 ? void 0 : actionButton.iconName) || 'LineIconsPlusPlusIcon', rightIcon: buttonRightIcon, isFullWidth: buttonIsFullWidth, isSelected: buttonIsSelected, disabled: actionButton === null || actionButton === void 0 ? void 0 : actionButton.disabled, isLoading: actionButton === null || actionButton === void 0 ? void 0 : actionButton.isLoading, onClick: handleActionClick, ...actionButton === null || actionButton === void 0 ? void 0 : actionButton.buttonProps, children: buttonText }))] }))] }) }) }));
};

const Label = React.forwardRef(({ size = 'md', type = 'regular', disabled = false, asterisk = false, align = 'top', interactionState, className, children, ...props }, ref) => {
    // 현재 토큰 시스템에 맞춰 Text variant 매핑
    // 피그마 원본: lg=15px, md=14px, sm=13px
    // 토큰 시스템: lg=16px, md=14px, sm=12px (가장 가까운 값)
    const getTextVariant = () => {
        if (size === 'lg') {
            // 16px - heading-3 계열 사용 (bold=600, medium=500, regular=400)
            return 'heading-3';
        }
        else if (size === 'md') {
            // 14px - body-2 계열 사용 (bold=700, medium=500, regular=400)  
            return 'body-2';
        }
        else {
            // 12px - label-2 계열 사용 (bold=700, medium=500, regular=400)
            return 'label-2';
        }
    };
    // 피그마 기준 fontWeight 매핑
    const getFontWeight = () => {
        switch (type) {
            case 'bold': return 'bold';
            case 'medium': return 'medium';
            case 'regular': return 'regular';
            default: return 'regular';
        }
    };
    // 색상 결정 (피그마 기준)
    const getTextColor = () => {
        return disabled ? 'secondary-system02-1-disabled' : 'secondary-system02-1-rest';
    };
    return (jsx("label", { ref: ref, className: className, ...props, children: jsx(Surface, { foreground: getTextColor(), children: jsxs(Frame, { display: "flex", align: align === 'center' ? 'center' : 'flex-start', direction: "row", gap: "xxxs", children: [jsx(Text, { as: "span", variant: getTextVariant(), weight: getFontWeight(), children: children }), asterisk && (jsx(Asterisk, { disabled: disabled }))] }) }) }));
});
Label.displayName = 'Label';

const Checkbox = forwardRef(({ checked = false, indeterminate = false, disabled = false, label, showLabel = true, name, value, onChange, onClick, onFocus, onBlur, className, style, ...props }, ref) => {
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    const [isFocused, setIsFocused] = useState(false);
    const handleChange = (event) => {
        if (!disabled && onChange) {
            onChange(event.target.checked);
        }
    };
    const handleClick = (event) => {
        if (!disabled && onChange) {
            onChange(!checked);
        }
        if (onClick) {
            onClick(event);
        }
    };
    const handleFocus = (event) => {
        setIsFocused(true);
        if (onFocus) {
            onFocus(event);
        }
    };
    const handleBlur = (event) => {
        setIsFocused(false);
        if (onBlur) {
            onBlur(event);
        }
    };
    const handleMouseEnter = () => {
        if (!disabled) {
            setIsHovered(true);
        }
    };
    const handleMouseLeave = () => {
        setIsHovered(false);
        setIsPressed(false);
    };
    const handleMouseDown = () => {
        if (!disabled) {
            setIsPressed(true);
        }
    };
    const handleMouseUp = () => {
        setIsPressed(false);
    };
    // 배경색 결정
    const getBackgroundColor = () => {
        if (!checked && !indeterminate) {
            // 체크되지 않은 상태는 투명 배경
            if (disabled)
                return 'secondary-system02-1-disabled';
            if (isPressed)
                return 'secondary-system02-1-pressed';
            if (isHovered)
                return 'secondary-system02-1-hovered';
            return 'secondary-system02-1-rest'; // 체크되지 않은 상태는 secondary 색상 사용
        }
        // 체크된 상태는 primary 색상 
        if (disabled)
            return 'primary-system02-1-disabled';
        if (isPressed)
            return 'primary-system02-1-pressed';
        if (isHovered)
            return 'primary-system02-1-hovered';
        return 'primary-system02-1-rest';
    };
    // 테두리 색상 결정
    const getBorderColor = () => {
        if (disabled)
            return 'secondary-system02-2-disabled'; // disabled일 때만 연한 색
        return 'secondary-system02-1-rest'; // 기본 상태는 더 진한 색
    };
    const renderCheckIcon = () => {
        if (indeterminate) {
            return (jsx(Surface, { background: "primary-system02-1-rest", borderRadius: "xl", children: jsx(Sizing, { style: { width: '8px', height: '2px' } }) }));
        }
        if (checked) {
            return (jsx(Icon, { name: "LineIconsCheckmarkCheckmarkIcon", size: "xs" }));
        }
        return null;
    };
    return (jsxs(Frame, { display: "flex", direction: "row", align: "center", gap: "sm", className: className, style: {
            cursor: disabled ? 'not-allowed' : 'pointer',
            ...style
        }, children: [jsx("input", { ref: ref, type: "checkbox", checked: checked, disabled: disabled, name: name, value: value, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, style: {
                    position: 'absolute',
                    opacity: 0,
                    width: 0,
                    height: 0,
                    margin: 0,
                    padding: 0,
                    border: 'none'
                }, ...props }), jsx(Surface, { background: getBackgroundColor(), foreground: checked || indeterminate ? "primary-system02-oncolor" : "secondary-system02-1-rest", borderRadius: "xl", borderWidth: "thin", borderStyle: "solid", borderColor: getBorderColor(), onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, style: {
                    cursor: disabled ? 'not-allowed' : 'pointer',
                }, children: jsx(Sizing, { width: "sm", height: "xxs", children: jsx(Frame, { display: "flex", align: "center", justify: "center", fill: true, children: renderCheckIcon() }) }) }), showLabel && label && (jsx(Label, { htmlFor: name, disabled: disabled, onClick: !disabled ? (() => handleClick({})) : undefined, children: label }))] }));
});
Checkbox.displayName = 'Checkbox';

/**
 * Chip 컴포넌트는 선택된 항목이나 태그를 표시하는 컴포넌트입니다.
 * ComboBox에서 선택된 항목을 표시하거나 태그 입력에서 사용할 수 있습니다.
 */
const Chip = forwardRef(({ children, variant = 'filled', size = 'md', state, disabled = false, removable = false, selectable = false, selected = false, onClick, onRemove, ...rest }, ref) => {
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    // 실제 상태 결정
    const getActualState = () => {
        if (disabled)
            return 'disabled';
        if (state && state !== 'default')
            return state;
        if (isPressed)
            return 'pressed';
        if (isHovered)
            return 'hovered';
        return 'default';
    };
    // 크기별 설정 - 시멘틱 토큰 활용
    const sizeConfig = {
        sm: {
            padding: 'xxs', // 4px
            variant: 'caption-1', // 12px/16px
            iconSize: 'xs',
        },
        md: {
            padding: 'xs', // 6px
            variant: 'body-2', // 14px/20px
            iconSize: 'sm',
        }
    };
    const config = sizeConfig[size];
    const actualState = getActualState();
    // 배경색 결정
    const getBackgroundColor = () => {
        if (variant === 'filled') {
            // Filled variant 색상 로직
            if (disabled)
                return 'secondary-system02-2-disabled';
            if (selected) {
                if (actualState === 'pressed')
                    return 'primary-system02-1-pressed';
                if (actualState === 'hovered')
                    return 'primary-system02-1-hovered';
                return 'primary-system02-1-rest';
            }
            if (actualState === 'pressed')
                return 'secondary-system02-1-pressed';
            if (actualState === 'hovered')
                return 'secondary-system02-1-hovered';
            return 'secondary-system02-1-rest';
        }
        else {
            // Ghost variant 색상 로직  
            if (disabled)
                return 'secondary-system02-1-disabled';
            if (selected)
                return 'primary-system02-1-rest';
            return 'secondary-system02-2-rest';
        }
    };
    // 테두리 색상 결정
    const getBorderColor = () => {
        if (variant === 'filled')
            return undefined; // filled는 테두리 없음
        // outlined variant
        if (disabled)
            return 'secondary-system02-2-disabled';
        if (selected)
            return 'primary-system02-1-rest';
        return 'secondary-system02-1-rest';
    };
    // 전경색 결정
    const getForegroundColor = () => {
        if (disabled)
            return 'secondary-system02-1-disabled';
        if (variant === 'outlined') {
            if (selected)
                return 'primary-system02-1-rest';
            return 'secondary-system02-2-rest';
        }
        // filled variant
        if (selected)
            return 'primary-system02-oncolor'; // primary 배경에서 잘 보이도록 onColor 사용
        return 'secondary-system02-2-rest';
    };
    // 이벤트 핸들러
    const handleMouseEnter = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsHovered(true);
        }
    };
    const handleMouseLeave = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsHovered(false);
            setIsPressed(false);
        }
    };
    const handleMouseDown = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsPressed(true);
        }
    };
    const handleMouseUp = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsPressed(false);
        }
    };
    const handleClick = () => {
        if (disabled)
            return;
        if (selectable && onClick) {
            onClick();
        }
    };
    const handleRemoveClick = (event) => {
        event.stopPropagation();
        if (disabled)
            return;
        if (onRemove) {
            onRemove();
        }
    };
    return (jsx(Surface, { ref: ref, background: getBackgroundColor(), foreground: getForegroundColor(), borderRadius: "pill", borderWidth: variant === 'outlined' ? 'thin' : undefined, borderStyle: variant === 'outlined' ? 'solid' : undefined, borderColor: getBorderColor(), style: {
            cursor: disabled ? 'not-allowed' : selectable ? 'pointer' : 'default',
            userSelect: 'none',
            display: 'inline-flex',
            width: 'fit-content',
        }, onClick: selectable ? handleClick : undefined, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, ...rest, children: jsxs(Frame, { display: "flex", direction: "row", gap: "xxs", align: "center", padding: config.padding, fill: true, children: [jsx(Text, { variant: config.variant, color: undefined, style: {
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        whiteSpace: 'nowrap',
                        flex: 1,
                    }, children: children }), removable && (jsx(Surface, { borderRadius: "xl", onClick: handleRemoveClick, style: {
                        cursor: disabled ? 'not-allowed' : 'pointer',
                    }, children: jsx(Frame, { display: "flex", align: "center", justify: "center", padding: "xxxs", style: {
                            flexShrink: 0,
                        }, children: jsx(Icon, { name: "LineIconsCloseCloseIcon", size: config.iconSize }) }) }))] }) }));
});
Chip.displayName = 'Chip';

/**
 * Field 컴포넌트는 사용자 입력을 받기 위한 텍스트 필드입니다.
 * outlined, transparent, filled 스타일을 지원하며, 라벨 위치를 다양하게 설정할 수 있습니다.
 */
const Field = forwardRef(({ variant = 'outlined', labelPosition = 'above', size = 'md', fieldWidth, minWidth, truncateOnFit, label, required = false, disabled = false, error = false, errorMessage, helperText, placeholder, value, type = 'text', leftIcon, rightIcon, onChange, onFocus, onBlur, onClick, className, style, ...rest }, ref) => {
    // 상태 관리 추가
    const [isHovered, setIsHovered] = useState(false);
    const [isFocused, setIsFocused] = useState(false);
    // 이벤트 핸들러들
    const handleMouseEnter = () => {
        if (!disabled) {
            setIsHovered(true);
        }
    };
    const handleMouseLeave = () => {
        setIsHovered(false);
    };
    const handleFocus = (event) => {
        setIsFocused(true);
        if (onFocus) {
            onFocus(event);
        }
    };
    const handleBlur = (event) => {
        setIsFocused(false);
        if (onBlur) {
            onBlur(event);
        }
    };
    // 현재 상태 결정
    const getCurrentState = () => {
        if (disabled)
            return 'disabled';
        if (isFocused)
            return 'pressed'; // 포커스된 상태를 pressed로 처리
        if (isHovered)
            return 'hovered';
        return 'rest';
    };
    // 필드 너비 설정
    const getFieldWidth = () => {
        if (fieldWidth === 'fit-content') {
            return 'fit-content';
        }
        if (fieldWidth === 'fill-width') {
            return '100%';
        }
        if (fieldWidth) {
            return fieldWidth;
        }
        return '100%'; // 기본값
    };
    // 최소 너비 설정
    const getMinWidth = () => {
        return minWidth || '80px';
    };
    // 텍스트 색상 결정 (Surface foreground용)
    const getTextColor = () => {
        if (error)
            return 'error';
        if (variant === 'transparent') {
            const state = getCurrentState();
            switch (state) {
                case 'disabled':
                    return 'secondary-system01-1-disabled';
                case 'hovered':
                    return 'secondary-system01-1-hovered';
                case 'pressed':
                    return 'secondary-system01-1-pressed';
                default:
                    return 'secondary-system01-1-rest';
            }
        }
        return 'secondary-system01-1-rest';
    };
    // input 스타일 결정
    const getInputStyle = () => {
        const baseStyle = {
            border: 'none',
            background: 'transparent',
            outline: 'none',
            color: 'inherit', // Surface foreground 상속
            fontSize: '14px', // body-2와 동일
            fontFamily: 'inherit',
            lineHeight: '1.4',
            fontWeight: '400', // regular
            width: '100%',
            height: '100%'
        };
        if (fieldWidth === 'fit-content') {
            // 현재 값이나 placeholder의 길이에 따라 너비 계산
            const displayText = value || placeholder || '';
            const textLength = displayText.length;
            const dynamicWidth = Math.max(textLength * 0.6 + 2, 4); // 최소 4ch
            const fitContentStyle = {
                ...baseStyle,
                width: `${dynamicWidth}ch`,
                minWidth: '4ch', // 최소 4글자 너비
                maxWidth: truncateOnFit ? '25ch' : 'none',
            };
            // truncate 옵션이 활성화된 경우 input에 직접 적용
            if (truncateOnFit) {
                return {
                    ...fitContentStyle,
                    whiteSpace: 'nowrap',
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    maxWidth: '25ch',
                };
            }
            return fitContentStyle;
        }
        return baseStyle;
    };
    // 필드 배경색 결정 (상태별)
    const getFieldBackgroundColor = () => {
        if (variant !== 'filled')
            return undefined;
        const state = getCurrentState();
        switch (state) {
            case 'disabled':
                return 'secondary-system01-1-disabled';
            case 'hovered':
                return 'secondary-system01-1-hovered';
            case 'pressed':
                return 'secondary-system01-1-pressed';
            default:
                return 'secondary-system01-1-rest';
        }
    };
    // 필드 테두리 설정 (상태별)
    const getFieldBorderProps = () => {
        if (variant === 'transparent') {
            return {
                borderWidth: undefined,
                borderColor: undefined
            };
        }
        if (error) {
            return {
                borderWidth: 'thin',
                borderColor: 'error'
            };
        }
        // outlined의 경우 상태별 테두리 색상
        const state = getCurrentState();
        let borderColor = 'secondary-system01-1-rest';
        switch (state) {
            case 'disabled':
                borderColor = 'secondary-system01-1-disabled';
                break;
            case 'hovered':
                borderColor = 'secondary-system01-1-hovered';
                break;
            case 'pressed':
                borderColor = 'secondary-system01-1-pressed';
                break;
            default:
                borderColor = 'secondary-system01-1-rest';
        }
        return {
            borderWidth: 'thin',
            borderColor
        };
    };
    // 사이즈별 높이 토큰 매핑
    const getSizingHeight = () => {
        switch (size) {
            case 'md':
                return 'lg'; // 32px
            case 'lg':
                return 'xl'; // 36px  
            case 'xlg':
                return 'xxl'; // 40px
            default:
                return 'lg';
        }
    };
    // 라벨 컴포넌트 렌더링
    const renderLabel = () => {
        if (!label || labelPosition === 'none')
            return null;
        return (jsx(Label, { size: "md", type: "regular", align: "top", asterisk: required, disabled: disabled, children: label }));
    };
    // 입력 필드 렌더링
    const renderInputField = () => {
        const borderProps = getFieldBorderProps();
        return (jsx(Surface, { background: getFieldBackgroundColor(), foreground: getTextColor(), borderWidth: borderProps.borderWidth, borderColor: borderProps.borderColor, borderStyle: borderProps.borderWidth ? 'solid' : 'none', borderRadius: "xl", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: onClick, className: className, style: {
                width: getFieldWidth(),
                minWidth: getMinWidth(),
                ...style
            }, children: jsx(Sizing, { height: getSizingHeight(), children: jsxs(Frame, { display: "flex", direction: "row", align: "center", justify: "flex-start", gap: "sm", fill: true, padding: "md", style: {
                        cursor: onClick ? 'pointer' : 'text'
                    }, children: [leftIcon && (jsx(Icon, { name: leftIcon, size: "sm" })), jsx(Frame, { style: {
                                flex: 1,
                                display: 'flex',
                                alignItems: 'center'
                            }, children: jsx("input", { ref: ref, type: type, value: value, placeholder: placeholder, disabled: disabled, onChange: onChange, onFocus: handleFocus, onBlur: handleBlur, style: getInputStyle(), ...rest }) }), rightIcon && (jsx(Icon, { name: rightIcon, size: "sm" }))] }) }) }));
    };
    // 도움말/에러 메시지 렌더링
    const renderMessage = () => {
        const message = error ? errorMessage : helperText;
        if (!message)
            return null;
        // 헬퍼 텍스트 색상 결정 (연한 secondary 색상 사용)
        const getHelperTextColor = () => {
            if (disabled)
                return 'secondary-system01-3-disabled';
            if (error)
                return 'error';
            return 'secondary-system01-3-rest'; // 기본 텍스트보다 연한 색상
        };
        return (jsx(Surface, { foreground: getHelperTextColor(), children: jsx(Text, { variant: "caption-1", children: message }) }));
    };
    // 라벨 위치에 따른 레이아웃 결정
    if (labelPosition === 'before') {
        return (jsxs(Frame, { display: "flex", direction: "row", gap: "md", align: "flex-start", children: [renderLabel(), jsxs(Frame, { display: "flex", direction: "column", gap: "xxs", flex: 1, children: [renderInputField(), renderMessage()] })] }));
    }
    // labelPosition이 'above' 또는 'none'인 경우
    return (jsxs(Frame, { display: "flex", direction: "column", gap: "xxs", children: [renderLabel(), renderInputField(), renderMessage()] }));
});
Field.displayName = 'Field';

const Radio = forwardRef(({ checked = false, disabled = false, label, showLabel = true, name, value, variant = 'radio', onChange, onClick, onFocus, onBlur, className, style, ...props }, ref) => {
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    const [isFocused, setIsFocused] = useState(false);
    const handleChange = (event) => {
        if (!disabled && onChange && value) {
            onChange(value);
        }
    };
    const handleClick = (event) => {
        if (!disabled && onChange && value) {
            onChange(value);
        }
        if (onClick) {
            onClick(event);
        }
    };
    const handleFocus = (event) => {
        setIsFocused(true);
        if (onFocus) {
            onFocus(event);
        }
    };
    const handleBlur = (event) => {
        setIsFocused(false);
        if (onBlur) {
            onBlur(event);
        }
    };
    const handleMouseEnter = () => {
        if (!disabled) {
            setIsHovered(true);
        }
    };
    const handleMouseLeave = () => {
        setIsHovered(false);
        setIsPressed(false);
    };
    const handleMouseDown = () => {
        if (!disabled) {
            setIsPressed(true);
        }
    };
    const handleMouseUp = () => {
        setIsPressed(false);
    };
    // 현재 상태 결정
    const getCurrentState = () => {
        if (disabled)
            return 'disabled';
        if (isPressed)
            return 'pressed';
        if (isHovered)
            return 'hovered';
        return 'rest';
    };
    // 라디오 버튼 배경색 결정 (기존 secondary-1 로직 유지)
    const getBackgroundColor = () => {
        const state = getCurrentState();
        switch (state) {
            case 'disabled':
                return 'secondary-system02-1-disabled';
            case 'pressed':
                return 'secondary-system02-1-pressed';
            case 'hovered':
                return 'secondary-system02-1-hovered';
            default:
                return 'secondary-system02-1-rest';
        }
    };
    // 라디오 버튼 테두리 색상 결정 (기존 secondary-stroke-1 로직 유지)
    const getBorderColor = () => {
        const state = getCurrentState();
        switch (state) {
            case 'disabled':
                return 'secondary-system02-1-disabled';
            case 'pressed':
                return 'secondary-system02-1-pressed';
            case 'hovered':
                return 'secondary-system02-1-hovered';
            default:
                return 'secondary-system02-1-rest';
        }
    };
    // 내부 원/체크마크 배경색 결정 (기존 primary-1 로직 유지)
    const getInnerBackgroundColor = () => {
        const state = getCurrentState();
        switch (state) {
            case 'disabled':
                return 'primary-system02-1-disabled';
            case 'pressed':
                return 'primary-system02-1-pressed';
            case 'hovered':
                return 'primary-system02-1-hovered';
            default:
                return 'primary-system02-1-rest';
        }
    };
    // 내부 표시 렌더링
    const renderInnerContent = () => {
        if (!checked)
            return null;
        if (variant === 'checkmark') {
            return (jsx(Icon, { name: "LineIconsRadioButtonOnIcon", size: "xs" }));
        }
        // radio 스타일: 내부 원 (기존 6px x 6px 크기 유지)
        return (jsx(Sizing, { width: "6px", height: "6px", children: jsx(Surface, { background: getInnerBackgroundColor(), borderRadius: "circular", fill: true }) }));
    };
    return (jsxs(Frame, { display: "flex", direction: "row", align: "center", gap: "sm", className: className, style: style, children: [jsx("input", { ref: ref, type: "radio", checked: checked, disabled: disabled, name: name, value: value, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, style: {
                    position: 'absolute',
                    opacity: 0,
                    width: 0,
                    height: 0,
                    margin: 0,
                    padding: 0,
                    border: 'none'
                }, ...props }), jsx(Sizing, { width: "16px", height: "16px", children: jsx(Surface, { background: getBackgroundColor(), borderRadius: variant === 'checkmark' ? 'xl' : 'circular', borderWidth: "thin", borderColor: getBorderColor(), borderStyle: "solid", onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, style: { cursor: disabled ? 'not-allowed' : 'pointer' }, fill: true, children: jsx(Frame, { display: "flex", direction: "column", align: "center", justify: "center", fill: true, children: renderInnerContent() }) }) }), showLabel && label && (jsx(Label, { htmlFor: name, disabled: disabled, interactionState: getCurrentState(), style: { cursor: disabled ? 'not-allowed' : 'pointer' }, onClick: !disabled ? (() => handleClick({})) : undefined, children: label }))] }));
});
Radio.displayName = 'Radio';

/**
 * OptionList 컴포넌트는 선택 가능한 옵션 아이템을 나타냅니다.
 * ComboBox, 드롭다운 메뉴, 선택 목록 등에서 사용할 수 있는 범용적인 컴포넌트입니다.
 */
const OptionList = forwardRef(({ type = 'single-select', state = 'default', selected = false, disabled = false, children, onClick, onMouseEnter, onMouseLeave, 
// Radio props
radioName, radioValue, radioChecked, onRadioChange, 
// Checkbox props
checkboxName, checkboxValue, checkboxChecked, checkboxIndeterminate, onCheckboxChange, ...rest }, ref) => {
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    // 실제 상태 결정 (외부 state prop이 있으면 우선, 없으면 실시간 상태 사용)
    const getActualState = () => {
        if (disabled)
            return 'disabled';
        if (state && state !== 'default')
            return state;
        if (isPressed)
            return 'pressed';
        if (isHovered)
            return 'hovered';
        if (selected)
            return 'selected';
        return 'default';
    };
    // 상태에 따른 배경색 결정
    const getBackgroundColor = () => {
        const actualState = getActualState();
        if (actualState === 'disabled')
            return 'secondary-system02-1-disabled';
        if (actualState === 'pressed')
            return 'secondary-system02-1-pressed';
        if (actualState === 'hovered')
            return 'secondary-system02-1-hovered';
        if (actualState === 'selected')
            return 'secondary-system02-1-selected';
        return 'secondary-system02-1-rest';
    };
    // 상태에 따른 텍스트 색상 결정
    const getForegroundColor = () => {
        const actualState = getActualState();
        if (actualState === 'disabled')
            return 'secondary-system02-1-disabled';
        return 'secondary-system02-1-rest';
    };
    // 이벤트 핸들러들
    const handleMouseEnter = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsHovered(true);
        }
        if (onMouseEnter)
            onMouseEnter();
    };
    const handleMouseLeave = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsHovered(false);
            setIsPressed(false);
        }
        if (onMouseLeave)
            onMouseLeave();
    };
    const handleMouseDown = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsPressed(true);
        }
    };
    const handleMouseUp = () => {
        if (!disabled && (!state || state === 'default')) {
            setIsPressed(false);
        }
    };
    const handleClick = () => {
        if (disabled)
            return;
        // Radio 컴포넌트 타입일 때
        if (type === 'radio-component' && onRadioChange && radioValue) {
            onRadioChange(radioValue);
        }
        // Checkbox 컴포넌트 타입일 때
        if (type === 'checkbox-component' && onCheckboxChange) {
            onCheckboxChange(!checkboxChecked);
        }
        // 기본 클릭 핸들러
        if (onClick) {
            onClick();
        }
    };
    // 텍스트 스타일 결정
    const getTextVariant = () => {
        if (type === 'menu-header')
            return 'caption-1';
        return 'body-2';
    };
    // 텍스트 굵기 결정
    const getFontWeight = () => {
        if (type === 'menu-header')
            return 'bold';
        return 'regular';
    };
    // 패딩 결정
    const getPadding = () => {
        if (type === 'menu-header')
            return 'xs';
        if (type === 'radio-component' || type === 'checkbox-component')
            return 'sm';
        return 'sm';
    };
    // 테두리 스타일
    const getBorderProps = () => {
        if (state === 'focused') {
            return {
                borderWidth: 'thin',
                borderColor: 'primary-system02-1-rest',
                borderStyle: 'solid'
            };
        }
        return {};
    };
    const borderProps = getBorderProps();
    // 컨텐츠 렌더링
    const renderContent = () => {
        // Radio 컴포넌트 렌더링
        if (type === 'radio-component') {
            return (jsx(Radio, { name: radioName, value: radioValue, label: children, checked: radioChecked || false, disabled: disabled, onChange: onRadioChange, showLabel: true }));
        }
        // Checkbox 컴포넌트 렌더링
        if (type === 'checkbox-component') {
            return (jsx(Checkbox, { name: checkboxName, value: checkboxValue, label: children, checked: checkboxChecked || false, indeterminate: checkboxIndeterminate || false, disabled: disabled, onChange: onCheckboxChange, showLabel: true }));
        }
        // 기본 텍스트 렌더링
        return (jsx(Text, { variant: getTextVariant(), weight: getFontWeight(), color: undefined, children: children }));
    };
    return (jsx(Surface, { ref: ref, background: getBackgroundColor(), foreground: getForegroundColor(), borderRadius: "xl", ...borderProps, style: {
            cursor: disabled ? 'not-allowed' : 'pointer',
            userSelect: 'none'
        }, onClick: disabled ? undefined : handleClick, onMouseEnter: disabled ? undefined : handleMouseEnter, onMouseLeave: disabled ? undefined : handleMouseLeave, onMouseDown: disabled ? undefined : handleMouseDown, onMouseUp: disabled ? undefined : handleMouseUp, ...rest, children: jsxs(Sizing, { height: "lg", width: "100%", children: [" ", jsx(Frame, { display: "flex", align: "center", padding: getPadding(), fill: true, children: renderContent() })] }) }));
});
OptionList.displayName = 'OptionList';

/**
 * ComboBox 컴포넌트는 Field를 기반으로 하는 선택 가능한 드롭다운 메뉴입니다.
 * 검색 기능, 단일/다중 선택을 지원하며 선택된 항목을 Chip으로 표시합니다.
 */
const ComboBox = forwardRef(({ options, value, multiple = false, searchable = false, placeholder = '선택해주세요', label, disabled = false, errorMessage, helperText, required = false, direction = 'down', fieldVariant, fieldSize, fieldWidth, labelPosition, leftIcon, onChange, onSearch, onToggle, ...rest }, ref) => {
    // 기본값 처리
    const selectedValues = multiple
        ? (Array.isArray(value) ? value : [])
        : (typeof value === 'string' ? [value] : []);
    const [isOpen, setIsOpen] = useState(false);
    const [searchTerm, setSearchTerm] = useState('');
    const [filteredOptions, setFilteredOptions] = useState(options);
    const containerRef = useRef(null);
    const fieldRef = useRef(null);
    // 검색어에 따른 옵션 필터링
    useEffect(() => {
        if (!searchable || !searchTerm) {
            setFilteredOptions(options);
            return;
        }
        const filtered = options.filter(option => option.label.toLowerCase().includes(searchTerm.toLowerCase()));
        setFilteredOptions(filtered);
        if (onSearch) {
            onSearch(searchTerm);
        }
    }, [searchTerm, options, searchable, onSearch]);
    // 외부 클릭 감지로 드롭다운 닫기
    useEffect(() => {
        const handleClickOutside = (event) => {
            if (containerRef.current && !containerRef.current.contains(event.target)) {
                setIsOpen(false);
                setSearchTerm(''); // 드롭다운이 닫힐 때 검색어 초기화
            }
        };
        if (isOpen) {
            document.addEventListener('mousedown', handleClickOutside);
        }
        return () => {
            document.removeEventListener('mousedown', handleClickOutside);
        };
    }, [isOpen]);
    // 드롭다운 토글
    const handleToggle = () => {
        if (disabled)
            return;
        const newIsOpen = !isOpen;
        setIsOpen(newIsOpen);
        if (newIsOpen && searchable && fieldRef.current) {
            fieldRef.current.focus();
        }
        if (!newIsOpen) {
            setSearchTerm(''); // 드롭다운이 닫힐 때 검색어 초기화
        }
        if (onToggle) {
            onToggle(newIsOpen);
        }
    };
    // 옵션 선택 처리
    const handleOptionSelect = (optionValue) => {
        if (disabled)
            return;
        if (multiple) {
            const newValues = selectedValues.includes(optionValue)
                ? selectedValues.filter(v => v !== optionValue)
                : [...selectedValues, optionValue];
            if (onChange) {
                onChange(newValues);
            }
        }
        else {
            if (onChange) {
                onChange(optionValue);
            }
            setIsOpen(false);
            setSearchTerm('');
        }
    };
    // 칩 제거 처리
    const handleChipRemove = (valueToRemove) => {
        if (disabled)
            return;
        const newValues = selectedValues.filter(v => v !== valueToRemove);
        if (onChange) {
            onChange(multiple ? newValues : '');
        }
    };
    // 선택된 값들의 라벨 표시
    const getDisplayValue = () => {
        if (selectedValues.length === 0)
            return '';
        if (selectedValues.length === 1) {
            const option = options.find(opt => opt.value === selectedValues[0]);
            return (option === null || option === void 0 ? void 0 : option.label) || '';
        }
        return `${selectedValues.length}개 선택됨`;
    };
    // 검색 입력 처리
    const handleSearchChange = (event) => {
        setSearchTerm(event.target.value);
    };
    // Field 클릭 처리
    const handleFieldClick = (event) => {
        // 검색 가능한 상태에서 input을 직접 클릭한 경우에는 토글하지 않음
        if (searchable && event.target instanceof HTMLInputElement) {
            return;
        }
        handleToggle();
    };
    // 키보드 이벤트 처리
    const handleKeyDown = (event) => {
        if (event.key === 'Enter' || (event.key === ' ' && !searchable)) {
            event.preventDefault();
            handleToggle();
        }
        else if (event.key === 'Escape' && isOpen) {
            setIsOpen(false);
            setSearchTerm('');
        }
    };
    // 옵션들을 그룹별로 정리
    const groupedOptions = filteredOptions.reduce((groups, option) => {
        const groupName = option.group || 'default';
        if (!groups[groupName]) {
            groups[groupName] = [];
        }
        groups[groupName].push(option);
        return groups;
    }, {});
    // 선택된 칩들 렌더링
    const renderSelectedChips = () => {
        if (!multiple || selectedValues.length === 0)
            return null;
        return (jsx(Frame, { display: "flex", direction: "row", wrap: "wrap", gap: "xs", children: selectedValues.map((selectedValue) => {
                const option = options.find(opt => opt.value === selectedValue);
                if (!option)
                    return null;
                return (jsx(Chip, { size: "sm", removable: true, disabled: disabled, onRemove: () => handleChipRemove(selectedValue), children: option.label }, selectedValue));
            }) }));
    };
    return (jsx(Surface, { style: { position: 'relative', width: '100%' }, ...rest, children: jsxs("div", { ref: containerRef, children: [jsxs(Frame, { display: "flex", direction: "column", gap: "sm", children: [jsx(Field, { ref: fieldRef, variant: fieldVariant, size: fieldSize, fieldWidth: fieldWidth, minWidth: "80px", truncateOnFit: fieldWidth === 'fit-content', labelPosition: labelPosition, leftIcon: leftIcon, label: label, placeholder: placeholder, value: searchable && isOpen ? searchTerm : getDisplayValue(), disabled: disabled, error: !!errorMessage, errorMessage: errorMessage, helperText: helperText, required: required, readOnly: !searchable, rightIcon: "LineIconsArrowChevronDownIcon", onClick: handleFieldClick, onChange: searchable ? handleSearchChange : undefined, onKeyDown: handleKeyDown, style: {
                                cursor: disabled ? 'not-allowed' : 'pointer',
                            } }), renderSelectedChips()] }), isOpen && (jsx(Surface, { background: "secondary-system01-1-rest", borderRadius: "xl", borderColor: "secondary-system01-1-rest", borderWidth: "thin", borderStyle: "solid", style: {
                        position: 'absolute',
                        top: direction === 'down' ? '100%' : 'auto',
                        bottom: direction === 'up' ? '100%' : 'auto',
                        left: 0,
                        right: 0,
                        zIndex: 1000,
                        marginTop: direction === 'down' ? 'var(--semantic-gap-global-xxs)' : '0',
                        marginBottom: direction === 'up' ? 'var(--semantic-gap-global-xxs)' : '0',
                        maxHeight: '200px',
                        overflowY: 'auto'
                    }, children: jsxs(Frame, { display: "flex", direction: "column", padding: "xs", children: [Object.entries(groupedOptions).map(([groupName, groupOptions], groupIndex) => (jsxs(React.Fragment, { children: [groupName !== 'default' && (jsxs(Fragment, { children: [groupIndex > 0 && (jsx(Frame, { display: "flex", gap: "xxs", children: jsx(Divider, { orientation: "horizontal", thickness: "thin" }) })), jsx(OptionList, { type: "menu-header", children: groupName })] })), groupOptions.map((option) => {
                                        const isSelected = selectedValues.includes(option.value);
                                        return (jsx(OptionList, { type: multiple ? 'checkbox-component' : 'single-select', selected: !multiple ? isSelected : undefined, disabled: option.disabled, onClick: () => handleOptionSelect(option.value), checkboxChecked: multiple ? isSelected : undefined, onCheckboxChange: multiple ? () => handleOptionSelect(option.value) : undefined, children: option.label }, option.value));
                                    })] }, groupName))), filteredOptions.length === 0 && (jsx(OptionList, { type: "menu-header", disabled: true, children: "\uAC80\uC0C9 \uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }))] }) }))] }) }));
});
ComboBox.displayName = 'ComboBox';

/**
 * Link 컴포넌트는 다른 페이지나 외부 사이트로 이동하는 컴파운드 컴포넌트입니다.
 * Text와 Icon 프리미티브를 조합하여 만들어지며, 다양한 크기, 색상, 상태를 지원하고 접근성을 고려한 설계가 적용되어 있습니다.
 */
const Link = forwardRef(({ variant = 'default', size = 'body-1', color = 'primary-foreground-1', interactionState = 'rest', underline = 'hover', external = false, disabled = false, children, className, target, rel, onClick, style, ...rest }, ref) => {
    // 현재 상태에 따른 색상 결정
    const getCurrentColor = () => {
        if (disabled)
            return `${color}--disabled`;
        return `${color}--${interactionState}`;
    };
    // 텍스트 스타일 결정
    const getTextStyle = () => {
        const baseStyle = {
            textDecoration: underline === 'always' ? 'underline' :
                underline === 'hover' ? undefined : 'none',
            opacity: variant === 'subtle' ? 0.7 : 1,
            fontWeight: variant === 'prominent' ? 600 : undefined,
            cursor: disabled ? 'not-allowed' : 'pointer',
            ...style
        };
        return baseStyle;
    };
    // 외부 링크 props 처리
    const externalProps = external ? {
        target: target || '_blank',
        rel: rel || 'noopener noreferrer'
    } : { target, rel };
    // 클릭 핸들러
    const handleClick = (event) => {
        if (disabled) {
            event.preventDefault();
            return;
        }
        if (onClick) {
            onClick(event);
        }
    };
    return (jsxs("a", { ref: ref, className: className, onClick: handleClick, "aria-disabled": disabled, tabIndex: disabled ? -1 : undefined, style: {
            display: 'inline-flex',
            alignItems: 'center',
            gap: 'var(--semantic-spacingHor-global-xxxs)',
            textDecoration: 'none',
            outline: 'none',
            transition: 'all var(--semantic-animation-duration-transition-button) var(--semantic-animation-easing-interaction-button)',
            ...style
        }, ...externalProps, ...rest, children: [jsx(Text, { variant: size, color: getCurrentColor(), style: getTextStyle(), children: children }), external && (jsx(Icon, { name: "ExternalLinkIcon", size: "xs", style: { opacity: 0.7 } }))] }));
});
Link.displayName = 'Link';

/**
 * MenuHeader 컴포넌트는 아코디언이나 GNB 메뉴에서 사용할 수 있는 헤더 역할을 합니다.
 * 클릭 가능한 버튼 형태로 구현되어 메뉴 확장/축소 등의 동작을 처리할 수 있습니다.
 *

 */
const MenuHeader = forwardRef(({ size = 'lg', state, children, leftIcon, rightIcon, expanded = false, showChevron = true, disabled = false, className, onClick, color, ...rest }, ref) => {
    // 실시간 인터랙션 상태 관리
    const [isHovered, setIsHovered] = useState(false);
    const [isPressed, setIsPressed] = useState(false);
    const [isFocused, setIsFocused] = useState(false);
    // 실제 상태 결정 (외부 state prop이 있으면 우선, 없으면 실시간 상태 사용)
    const getActualState = () => {
        if (disabled)
            return 'disabled';
        if (state)
            return state; // 외부에서 명시적으로 상태를 지정한 경우
        if (isPressed)
            return 'pressed';
        if (isHovered)
            return 'hovered';
        if (isFocused)
            return 'focused';
        return 'default';
    };
    const actualState = getActualState();
    // 크기별 높이 토큰 매핑
    const heightMap = {
        'md': 'lg', // 32px
        'lg': 'xl', // 36px 
        'xlg': 'xxl' // 40px
    };
    // 크기별 아이콘 사이즈 매핑 - Button 컴포넌트와 일치
    const iconSizeMap = {
        'md': 'xs', // 16px (Button md와 동일)
        'lg': 'sm', // 20px (Button lg와 동일)  
        'xlg': 'md' // 24px (Button xl과 동일)
    };
    // 상태별 배경색 - 선택된 상태와 비활성화 상태는 배경색 없음
    const getBackgroundColor = () => {
        if (actualState === 'disabled')
            return undefined; // 비활성화시 배경색 없음
        if (actualState === 'selected')
            return undefined; // 선택된 상태에서 배경색 없음
        if (actualState === 'pressed')
            return 'secondary-system02-1-pressed';
        if (actualState === 'hovered')
            return 'secondary-system02-1-hovered';
        if (actualState === 'focused')
            return undefined; // 포커스시 배경색 없음
        return undefined; // 기본 상태도 배경색 없음
    };
    // 상태별 전경색
    const getForegroundColor = () => {
        if (actualState === 'disabled')
            return 'secondary-system02-1-disabled';
        if (actualState === 'selected')
            return 'primary-system02-1-rest';
        return 'secondary-system02-1-rest';
    };
    // 포커스 상태 보더 색상
    const getBorderProps = () => {
        if (actualState === 'focused') {
            return {
                borderWidth: 'thin',
                borderStyle: 'solid',
                borderColor: 'focused'
            };
        }
        return {};
    };
    // 이벤트 핸들러
    const handleMouseEnter = (event) => {
        if (!disabled && !state)
            setIsHovered(true);
    };
    const handleMouseLeave = (event) => {
        if (!disabled && !state) {
            setIsHovered(false);
            setIsPressed(false);
        }
    };
    const handleMouseDown = (event) => {
        if (!disabled && !state)
            setIsPressed(true);
    };
    const handleMouseUp = (event) => {
        if (!disabled && !state)
            setIsPressed(false);
    };
    const handleFocus = (event) => {
        if (!disabled && !state)
            setIsFocused(true);
    };
    const handleBlur = (event) => {
        if (!disabled && !state)
            setIsFocused(false);
    };
    const handleClick = (event) => {
        if (disabled)
            return;
        if (onClick) {
            onClick(event);
        }
    };
    return (jsx(Surface, { ref: ref, background: getBackgroundColor(), foreground: getForegroundColor(), borderRadius: "xl", ...getBorderProps(), style: {
            cursor: disabled ? 'not-allowed' : 'pointer',
            width: '100%',
            ...rest.style
        }, onClick: disabled ? undefined : handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onFocus: handleFocus, onBlur: handleBlur, tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, "aria-expanded": expanded, className: className, ...rest, children: jsx(Sizing, { height: heightMap[size], children: jsxs(Frame, { display: "flex", align: "center", justify: "space-between", paddingX: "sm", paddingY: "xs", fill: true, children: [jsxs(Frame, { display: "flex", align: "center", gap: "xs", children: [leftIcon && (jsx(Icon, { name: leftIcon, size: iconSizeMap[size] })), jsx(Text, { variant: "heading-3", weight: "bold", children: children }), rightIcon && (jsx(Icon, { name: rightIcon, size: iconSizeMap[size] }))] }), showChevron && (jsx(Button, { variant: "transparent", buttonType: "icon-only", colorScheme: actualState === 'selected' ? 'primary' : 'secondary', size: size === 'xlg' ? 'md' : size === 'lg' ? 'sm' : 'xs', rightIcon: expanded ? "LineIconsArrowChevronUpIcon" : "LineIconsArrowChevronDownIcon", disabled: disabled, onClick: (e) => {
                            e.stopPropagation();
                            if (onClick) {
                                onClick(e);
                            }
                        } }))] }) }) }));
});
MenuHeader.displayName = 'MenuHeader';

const SegmentButtonContext = createContext(null);
const SegmentButton = ({ mode, selectedValues, defaultSelectedValues = [], size = 'md', variant = 'primary', onChange, children, ...rest }) => {
    // Internal state for uncontrolled component
    const [internalSelectedValues, setInternalSelectedValues] = useState(defaultSelectedValues);
    // Use controlled values if provided, otherwise use internal state
    const currentSelectedValues = selectedValues !== null && selectedValues !== void 0 ? selectedValues : internalSelectedValues;
    const handleItemClick = (value) => {
        let newSelectedValues;
        if (mode === 'single') {
            // Single select: replace current selection
            newSelectedValues = [value];
        }
        else {
            // Multi select: toggle selection
            if (currentSelectedValues.includes(value)) {
                newSelectedValues = currentSelectedValues.filter(v => v !== value);
            }
            else {
                newSelectedValues = [...currentSelectedValues, value];
            }
        }
        // Update internal state if uncontrolled
        if (selectedValues === undefined) {
            setInternalSelectedValues(newSelectedValues);
        }
        // Call onChange callback
        onChange === null || onChange === void 0 ? void 0 : onChange(newSelectedValues);
    };
    // Surface props 분리
    const { style, ...surfaceProps } = rest;
    const contextValue = {
        selectedValues: currentSelectedValues,
        mode,
        size,
        variant,
        onItemClick: handleItemClick,
        children,
    };
    return (jsx(SegmentButtonContext.Provider, { value: contextValue, children: jsx(Surface, { background: "secondary-system02-1-rest", borderColor: "secondary-system02-1-rest", borderWidth: "thin", borderStyle: "solid", borderRadius: "xl", style: { width: 'fit-content', ...style }, ...surfaceProps, children: jsx(Frame, { display: "flex", direction: "row", align: "stretch", justify: "flex-start", gap: "none", fill: true, children: children }) }) }));
};
const SegmentButtonItem = ({ value, disabled = false, children }) => {
    const context = useContext(SegmentButtonContext);
    if (!context) {
        throw new Error('SegmentButton.Item must be used within SegmentButton');
    }
    const { selectedValues, onItemClick, size, variant } = context;
    const selected = selectedValues.includes(value);
    // 현재 아이템의 위치 정보 계산
    const items = React.Children.toArray(context.children);
    const currentIndex = items.findIndex((child) => React.isValidElement(child) &&
        child.props &&
        child.props.value === value);
    const isFirst = currentIndex === 0;
    const isLast = currentIndex === items.length - 1;
    const isSingle = items.length === 1;
    // 위치에 따른 스타일 결정 (구분선과 radius)
    const getButtonStyle = () => {
        const baseStyle = {};
        if (isSingle) {
            // 단일 버튼은 기본 radius
            return baseStyle;
        }
        if (isFirst) {
            // 첫 번째 버튼: 왼쪽만 radius
            baseStyle.borderTopRightRadius = '0';
            baseStyle.borderBottomRightRadius = '0';
        }
        else if (isLast) {
            // 마지막 버튼: 오른쪽만 radius
            baseStyle.borderTopLeftRadius = '0';
            baseStyle.borderBottomLeftRadius = '0';
        }
        else {
            // 가운데 버튼: radius 없음
            baseStyle.borderRadius = '0';
        }
        // 구분선 추가 (마지막 버튼 제외) - System-02 색상 사용
        if (!isLast) {
            baseStyle.borderRight = '1px solid var(--foundation-foundation-color-grey-light-80)';
        }
        return baseStyle;
    };
    // 선택 상태별 variant 결정
    const getButtonVariant = () => {
        if (selected) {
            return 'filled'; // 선택된 상태는 filled
        }
        return 'transparent'; // 비선택 상태는 transparent
    };
    // 선택 상태별 colorScheme 결정 (Tab처럼)
    const getButtonColorScheme = () => {
        if (selected) {
            return 'primary'; // 선택된 상태는 primary (System-02: purple)
        }
        return 'secondary'; // 비선택 상태는 secondary
    };
    return (jsx(Button, { variant: getButtonVariant(), colorScheme: getButtonColorScheme(), size: size, disabled: disabled, onClick: () => !disabled && onItemClick(value), style: getButtonStyle(), "aria-pressed": selected, children: children }));
};
// Attach the Item component to the main component
SegmentButton.Item = SegmentButtonItem;

const Tab = ({ items, selectedId: controlledSelectedId, defaultSelectedId, size = 'lg', showBorder = true, onChange, ...surfaceProps }) => {
    var _a;
    const [internalSelectedId, setInternalSelectedId] = useState(defaultSelectedId || ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.id) || '');
    // 마우스 상태 관리
    const [hoveredId, setHoveredId] = useState(null);
    const [pressedId, setPressedId] = useState(null);
    // controlled vs uncontrolled 지원
    const selectedId = controlledSelectedId !== undefined ? controlledSelectedId : internalSelectedId;
    const handleTabClick = (id) => {
        if (selectedId !== id) {
            if (controlledSelectedId === undefined) {
                setInternalSelectedId(id);
            }
            onChange === null || onChange === void 0 ? void 0 : onChange(id);
        }
    };
    // 현재 상태 결정
    const getCurrentState = (itemId) => {
        const item = items.find(item => item.id === itemId);
        if (item === null || item === void 0 ? void 0 : item.disabled)
            return 'disabled';
        if (pressedId === itemId)
            return 'pressed';
        if (hoveredId === itemId)
            return 'hovered';
        return 'rest';
    };
    // 크기별 설정 - System-02는 패딩을 줄여서 간격을 좁힘
    const getSizeConfig = () => {
        if (size === 'md') {
            return {
                padding: 'sm', // md -> sm으로 변경
                textVariant: 'body-2',
                iconSize: 'xs',
                minHeight: '40px'
            };
        }
        return {
            padding: 'md', // lg -> md로 변경
            textVariant: 'body-1',
            iconSize: 'sm',
            minHeight: '48px'
        };
    };
    const config = getSizeConfig();
    return (jsx(Surface, { ...surfaceProps, children: jsx(Frame, { display: "flex", direction: "row", gap: "none", align: "flex-start", children: items.map((item) => {
                const isSelected = selectedId === item.id;
                const isDisabled = item.disabled;
                const currentState = getCurrentState(item.id);
                // Surface 색상 결정 - 더 연한 호버 색상 사용 (System-02: Purple 계열)
                const getSurfaceColors = () => {
                    if (isDisabled) {
                        return {
                            foreground: 'secondary-system02-1-disabled',
                            borderColor: 'secondary-system02-1-disabled'
                        };
                    }
                    if (isSelected) {
                        // 선택된 탭은 primary 색상 사용
                        if (currentState === 'pressed') {
                            return {
                                foreground: 'primary-system02-1-pressed',
                                borderColor: 'primary-system02-1-pressed'
                            };
                        }
                        if (currentState === 'hovered') {
                            return {
                                foreground: 'primary-system02-1-hovered',
                                borderColor: 'primary-system02-1-hovered'
                            };
                        }
                        return {
                            foreground: 'primary-system02-1-rest',
                            borderColor: 'primary-system02-1-rest'
                        };
                    }
                    // 비선택 탭은 secondary 색상 사용
                    if (currentState === 'pressed') {
                        return {
                            foreground: 'secondary-system02-1-pressed',
                            borderColor: 'secondary-system02-1-pressed'
                        };
                    }
                    if (currentState === 'hovered') {
                        return {
                            foreground: 'secondary-system02-1-hovered',
                            borderColor: 'secondary-system02-1-hovered'
                        };
                    }
                    return {
                        foreground: 'secondary-system02-1-rest',
                        borderColor: 'secondary-system02-1-rest'
                    };
                };
                const surfaceColors = getSurfaceColors();
                return (jsx(Surface, { background: undefined, foreground: surfaceColors.foreground, borderRadius: "none", borderWidth: isSelected && showBorder ? "medium" : undefined, borderColor: isSelected && showBorder ? surfaceColors.borderColor : undefined, borderStyle: isSelected && showBorder ? "solid" : undefined, style: {
                        ...(isSelected && showBorder ? {
                            borderTop: 'none',
                            borderLeft: 'none',
                            borderRight: 'none'
                        } : {}),
                        cursor: isDisabled ? "not-allowed" : "pointer",
                        minHeight: config.minHeight
                    }, onClick: () => !isDisabled && handleTabClick(item.id), onMouseEnter: () => !isDisabled && setHoveredId(item.id), onMouseLeave: () => {
                        setHoveredId(null);
                        setPressedId(null);
                    }, onMouseDown: () => !isDisabled && setPressedId(item.id), onMouseUp: () => setPressedId(null), children: jsxs(Frame, { display: "flex", direction: "row", align: "center", justify: "center", gap: "sm", padding: config.padding, children: [item.icon && (jsx(Icon, { name: item.icon, size: config.iconSize })), jsx(Text, { variant: config.textVariant, weight: isSelected ? 'bold' : 'regular', children: item.label })] }) }, item.id));
            }) }) }));
};

export { Badge, Button, Card, Checkbox, Chip, ComboBox, Field, Label, Link, MenuHeader, OptionList, Radio, SegmentButton, Tab, TextDisplay };