{"version":3,"file":"JTitlebar.vue.cjs","sources":["../../../../src/components/molecules/JTitlebar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\"\nimport { JIcon, JLabel, JPopover, JButton } from '@/components/atoms'\nimport type { ButtonVariants } from '@/components/shadcn'\nimport { cn } from \"@/lib/utils\"\n\nexport type TitlebarButton = {\n  /** 버튼 아이콘 */\n  icon?: string\n  /** 버튼 텍스트 */\n  text?: string\n  /** 버튼 클릭 핸들러 */\n  onClick?: () => void\n  /** 버튼 variant */\n  variant?: ButtonVariants['variant']\n  /** 버튼 스타일 타입 */\n  styletype?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'outline' | 'ghost' | 'link' | 'sm' | 'lg' | 'icon'\n  /** 버튼 size */\n  size?: 'sm' | 'md' | 'lg'\n  /** 버튼 비활성화 */\n  disabled?: boolean\n  /** 버튼 로딩 상태 */\n  loading?: boolean\n}\n\ntype StyleType =\n  | 'default'    // 기본 스타일: 일반 페이지용 (흰 배경, 얇은 보더)\n  | 'primary'    // 강조 스타일: 주요 기능용 (밝은 파란 배경, 흰 텍스트)\n  | 'accent'     // 액센트 스타일: 부드러운 강조용 (연한 파란 배경, 진한 텍스트)\n  | 'neutral'    // 중립 스타일: 서브 페이지용 (회색 배경, 회색 텍스트)\n  | 'elevated'   // 강조 스타일: 깊이감 있는 구분 (흰 배경, 그림자, 보더)\n\nconst props = withDefaults(\n  defineProps<{\n    /** Titlebar 스타일 타입 */\n    styletype?: StyleType\n    /** 프로그램 아이콘 */\n    icon?: string\n    /** 프로그램명 */\n    title?: string\n    /** 프로그램 설명 (Popover에 표시) */\n    description?: string\n    /** 도움말 아이콘(?) 표시 여부 — 클릭 시 help 이벤트 emit */\n    showHelp?: boolean\n    /** 메인 버튼 목록 */\n    buttons?: TitlebarButton[]\n    /** 추가 클래스 (외부 커스터마이징용) */\n    class?: string\n  }>(),\n  {\n    styletype: 'default',\n    buttons: () => [],\n  }\n)\n\n/**\n * styletype -> class 매핑 (배경, 보더, 그림자 등)\n */\nconst STYLE_PRESETS: Record<StyleType, { \n  class: string\n  iconClass: string      // 아이콘 색상 클래스\n  titleClass: string     // 제목 텍스트 색상 클래스\n  infoIconClass: string  // 정보 아이콘 색상 클래스\n}> = {\n  default: {\n    // 기본: 흰 배경 + 얇은 보더 (가장 일반적)\n    class: 'flex items-center justify-between w-full h-9 px-3 border-b border-border bg-background',\n    iconClass: 'text-primary',\n    titleClass: 'text-foreground text-md',\n    infoIconClass: 'text-muted-foreground hover:text-primary',\n  },\n  primary: {\n    // 강조: 밝은 파란 배경 + 흰 텍스트 (명확한 강조)\n    // text-white를 제거하여 버튼이 색상 상속을 받지 않도록 함\n    class: 'flex items-center justify-between w-full h-9 px-3 border-b border-blue-400/30 bg-blue-500',\n    iconClass: 'text-white',\n    titleClass: 'text-white font-semibold text-md',\n    infoIconClass: 'text-white/80 hover:text-white',\n  },\n  accent: {\n    // 액센트: 연한 파란 배경 + 진한 파란 텍스트 (부드러운 강조)\n    // text-blue-700을 제거하여 버튼이 색상 상속을 받지 않도록 함\n    class: 'flex items-center justify-between w-full h-9 px-3 border-b border-blue-200 bg-blue-50',\n    iconClass: 'text-blue-600',\n    titleClass: 'text-blue-700 font-semibold text-md',\n    infoIconClass: 'text-blue-600/70 hover:text-blue-700',\n  },\n  neutral: {\n    // 중립: 회색 배경 + 회색 텍스트 (확실한 구분)\n    // text-gray-700을 제거하여 버튼이 색상 상속을 받지 않도록 함\n    class: 'flex items-center justify-between w-full h-9 px-3 border-b border-gray-300 bg-gray-100',\n    iconClass: 'text-gray-600',\n    titleClass: 'text-gray-700 text-md',\n    infoIconClass: 'text-gray-500 hover:text-gray-700',\n  },\n  elevated: {\n    // 강조: 흰 배경 + 그림자 + 보더 (깊이감 있는 구분)\n    class: 'flex items-center justify-between w-full h-9 px-3 border-b border-border bg-background shadow-md',\n    iconClass: 'text-primary',\n    titleClass: 'text-foreground font-semibold text-md',\n    infoIconClass: 'text-muted-foreground hover:text-primary',\n  },\n}\n\nconst preset = computed(() => {\n  return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\nconst emit = defineEmits<{\n  /** 버튼 클릭 이벤트 */\n  buttonClick: [button: TitlebarButton]\n  /** 도움말 아이콘 클릭 이벤트 */\n  help: []\n}>()\n\nconst handleButtonClick = (button: TitlebarButton) => {\n  // 버튼 클릭 핸들러 패턴:\n  // 1. button.onClick이 있으면 실행 (인라인 핸들러)\n  // 2. 항상 emit('buttonClick', button) 실행 (부모 컴포넌트로 전달)\n  // 주의: onClick과 emit이 모두 실행되므로 중복 처리 가능성 있음\n  button.onClick?.()\n  emit('buttonClick', button)\n}\n</script>\n\n<template>\n  <div :class=\"cn(preset.class, props.class)\">\n    <!-- 왼쪽: 아이콘 + 프로그램명 -->\n    <div class=\"flex items-center gap-3 flex-1\">\n      <!-- 아이콘 -->\n      <JIcon \n        v-if=\"icon\" \n        :name=\"icon\" \n        :class=\"preset.iconClass\"\n      />\n      \n      <!-- 프로그램명 + 정보 아이콘 + Popover -->\n      <div class=\"flex items-center gap-2\">\n        <!-- 프로그램명 -->\n        <JLabel \n          :text=\"title || ''\" \n          :class=\"cn('font-semibold', preset.titleClass)\"\n        />\n        \n        <!-- 정보 아이콘 (description이 있을 때만 표시) -->\n        <JPopover \n          v-if=\"description\" \n          position=\"bottom\"\n          align=\"center\"\n          :side-offset=\"8\"\n        >\n          <template #trigger>\n            <JIcon \n              name=\"info\" \n              size=\"sm\" \n              :class=\"cn('cursor-help transition-colors inline-flex', preset.infoIconClass)\"\n            />\n          </template>\n          <div class=\"p-2\">\n            <p class=\"text-xs text-muted-foreground whitespace-normal break-words\">{{ description }}</p>\n          </div>\n        </JPopover>\n\n        <!-- 도움말 아이콘 (showHelp일 때 표시, 클릭 시 help 이벤트) -->\n        <JIcon\n          v-if=\"showHelp\"\n          name=\"circleQuestionMark\"\n          size=\"sm\"\n          :class=\"cn('cursor-pointer transition-colors inline-flex', preset.infoIconClass)\"\n          @click=\"emit('help')\"\n        />\n      </div>\n    </div>\n\n    <!-- 오른쪽: 메인 버튼들 -->\n    <!-- buttons prop으로 정의된 버튼들 (v-if로 조건부 렌더링) -->\n    <div v-if=\"buttons && buttons.length > 0\" class=\"flex items-center gap-2\">\n      <JButton\n        v-for=\"(button, index) in buttons\"\n        :key=\"index\"\n        :variant=\"button.variant\"\n        :styletype=\"button.styletype\"\n        :disabled=\"button.disabled\"\n        :loading=\"button.loading\"\n        :size=\"button.size\"\n        @click=\"handleButtonClick(button)\"\n      >\n        <JIcon v-if=\"button.icon\" :name=\"button.icon\" size=\"sm\" class=\"mr-1.5\" />\n        <span v-if=\"button.text\">{{ button.text }}</span>\n      </JButton>\n    </div>\n\n    <!-- 버튼 슬롯 레이아웃 설명:\n         - buttons prop과 buttons slot이 모두 제공되면 함께 표시됨\n         - buttons prop: 구조화된 버튼 정의 (JButton 컴포넌트 사용)\n         - buttons slot: 완전한 커스텀 버튼 제어 가능\n         - 레이아웃: buttons prop이 먼저 렌더링되고, 그 다음 slot이 렌더링됨 -->\n    <slot name=\"buttons\" />\n  </div>\n</template>\n\n"],"names":["props","__props","STYLE_PRESETS","preset","computed","emit","__emit","handleButtonClick","button","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_hoisted_1","_createBlock","JIcon","_hoisted_2","_createVNode","JLabel","cn","JPopover","_hoisted_3","_hoisted_4","_toDisplayString","_openBlock","_hoisted_5","_Fragment","_renderList","index","JButton","$event","_hoisted_6","_renderSlot","_ctx"],"mappings":"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"}