{"version":3,"file":"JHeader.vue.cjs","sources":["../../../../src/components/organisms/JHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, onMounted, onUnmounted } from 'vue'\nimport JIcon from '@/components/atoms/JIcon.vue'\nimport JAvatar from '@/components/atoms/JAvatar.vue'\nimport JButton from '@/components/atoms/JButton.vue'\nimport JPopover from '@/components/atoms/JPopover.vue'\nimport { cn } from '@/lib/utils'\nimport type { ContextMenuItem, ContextMenuGroup } from '@/types/context-menu.types'\nimport {\n  detectThemeClasses,\n  ensureDefaultTheme,\n  validateThemeExists,\n  getDefaultTheme,\n  getStoredTheme,\n  setStoredTheme,\n  applyTheme,\n} from '@/lib/theme-utils'\n\n// Fallback 로고 이미지 import (logo prop이 없거나 로드 실패 시 사용)\nimport logoFallback from '@/assets/images/logo-fallback.png'\n\n/**\n * JHeader - 상단 헤더 컴포넌트 (organisms)\n * Header Component\n * \n * @description\n * 애플리케이션의 상단 헤더 영역을 담당하는 컴포넌트입니다.\n * 로고, 네비게이션, 검색, 알림, 사용자 메뉴 등을 포함할 수 있습니다.\n * \n * @example\n * ```vue\n * <JHeader\n *   logo=\"/logo.png\"\n *   :user-menu-items=\"userMenuItems\"\n *   @logo-click=\"handleLogoClick\"\n * />\n * ```\n */\n\nexport type HeaderNavItem = {\n  /** 라벨 */\n  label: string\n  /** 링크 URL */\n  href?: string\n  /** 아이콘 */\n  icon?: string\n  /** 활성 상태 */\n  active?: boolean\n  /** 클릭 핸들러 */\n  onClick?: () => void\n}\n\nexport type NotificationItem = {\n  /** 알림 ID */\n  id: string\n  /** 알림 제목 */\n  title: string\n  /** 알림 내용 */\n  message?: string\n  /** 알림 시간 */\n  time?: string\n  /** 읽음 상태 */\n  read?: boolean\n  /** 아이콘 */\n  icon?: string\n  /** 클릭 핸들러 */\n  onClick?: () => void\n}\n\ntype StyleType =\n  | 'default'   // 기본 스타일\n  | 'minimal'   // 최소 스타일\n\nconst props = withDefaults(\n  defineProps<{\n    /** 로고 이미지 URL */\n    logo?: string\n    /** 로고 텍스트 (기본값, 이미지가 없을 때) */\n    logoText?: string\n    /** 네비게이션 아이템 목록 */\n    navItems?: HeaderNavItem[]\n    /** 알림 표시 여부 */\n    showNotifications?: boolean\n    /** 알림 목록 */\n    notifications?: NotificationItem[]\n    /** 사용자 아바타 이미지 */\n    userAvatar?: string\n    /** 사용자 이름 */\n    userName?: string\n    /** 로그인 상태 */\n    isLoggedIn?: boolean\n    /** 사용자 이메일 */\n    userEmail?: string\n    /** 사용자 ID */\n    userId?: string\n    /** 스타일 타입 */\n    styletype?: StyleType\n    /** 사이드바 토글 버튼 표시 여부 */\n    showSidebarToggle?: boolean\n    /** 사이드바 열림 상태 */\n    isSidebarOpen?: boolean\n    /** 테마 선택기 표시 여부 */\n    showThemeSelector?: boolean\n    /** 초기 테마 (기본값: 'default' 또는 저장된 테마) */\n    defaultTheme?: string\n    /** 선택 가능한 테마 목록 (지정하지 않으면 모든 감지된 테마 사용) */\n    availableThemes?: string[]\n  }>(),\n  {\n    logoText: 'JWMS Portal', // 기본값: 텍스트 로고\n    showNotifications: false,\n    notifications: () => [],\n    styletype: 'default',\n    showSidebarToggle: true,\n    isSidebarOpen: true,\n    showThemeSelector: true,\n    defaultTheme: undefined,\n    availableThemes: undefined,\n  }\n)\n\nconst emit = defineEmits<{\n  /** 로고 클릭 이벤트 */\n  logoClick: []\n  /** 네비게이션 아이템 클릭 이벤트 */\n  navClick: [item: HeaderNavItem, index: number]\n  /** 알림 클릭 이벤트 */\n  notificationClick: [item: NotificationItem]\n  /** 사용자 메뉴 아이템 선택 이벤트 */\n  userMenuSelect: [itemId: string]\n  /** 사이드바 토글 이벤트 */\n  sidebarToggle: []\n  /** 로그인 버튼 클릭 이벤트 */\n  login: []\n}>()\n\n/**\n * 스타일 프리셋\n */\nconst STYLE_PRESETS: Record<StyleType, {\n  containerClass: string\n  navItemClass: string\n  navItemActiveClass: string\n}> = {\n  default: {\n    containerClass: 'h-10 px-4 border-b border-border bg-muted dark:bg-card',\n    navItemClass: 'text-xs text-muted-foreground hover:text-foreground transition-colors px-3 py-1.5 rounded-md hover:bg-accent',\n    navItemActiveClass: 'text-foreground font-medium bg-accent',\n  },\n  minimal: {\n    containerClass: 'h-8 px-3 border-b border-border bg-muted dark:bg-card',\n    navItemClass: 'text-xs text-muted-foreground hover:text-foreground transition-colors px-2 py-1 rounded-md hover:bg-accent',\n    navItemActiveClass: 'text-foreground font-medium bg-accent',\n  },\n}\n\nconst preset = computed(() => {\n  return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\n/**\n * 로고 이미지 로드 에러 상태\n * 0: 에러 없음, 1: 첫 번째 이미지(logo) 에러, 2: fallback 이미지도 에러\n */\nconst logoImageError = ref(0)\n\n/**\n * 로고 이미지 경로 계산\n */\nconst logoImageSrc = computed(() => {\n  // props.logo가 있으면 사용\n  if (props.logo) {\n    return props.logo\n  }\n  return undefined\n})\n\n/**\n * 실제 표시할 로고 이미지 경로\n * 1. props.logo가 있으면 사용\n * 2. logo 에러 시 fallback 이미지\n * 3. fallback도 에러면 undefined (텍스트로 대체)\n */\nconst displayLogoImage = computed(() => {\n  // logo prop이 없으면 이미지 표시 안함 (텍스트 사용)\n  if (!props.logo) {\n    return undefined\n  }\n  \n  // logo 에러가 발생했으면 fallback 사용\n  if (logoImageError.value >= 1 && logoFallback) {\n    return logoFallback\n  }\n  \n  // 정상적으로 logo 사용\n  return logoImageSrc.value\n})\n\n/**\n * 로고 이미지 로드 에러 핸들러\n */\nconst handleLogoError = () => {\n  // 첫 번째 이미지(logo) 에러\n  if (logoImageError.value === 0) {\n    logoImageError.value = 1\n  }\n  // fallback 이미지도 에러면 2로 설정 (텍스트로 대체)\n  else if (logoImageError.value === 1) {\n    logoImageError.value = 2\n  }\n}\n\n/**\n * 읽지 않은 알림 개수\n */\nconst unreadCount = computed(() => {\n  return props.notifications?.filter(n => !n.read).length || 0\n})\n\n/**\n * 고정 사용자 메뉴 아이템\n */\nconst fixedUserMenuItems: ContextMenuItem[] = [\n  { id: 'profile', label: '프로필', icon: 'user' },\n  { id: 'settings', label: '설정', icon: 'settings' },\n  { id: 'separator', label: '', separator: true },\n  { id: 'logout', label: '로그아웃', icon: 'logOut' },\n]\n\n/**\n * 사용자 메뉴 아이템을 ContextMenuGroup 형식으로 변환\n */\nconst userMenuGroups = computed<ContextMenuGroup[]>(() => {\n  return [{\n    items: fixedUserMenuItems\n  }]\n})\n\n/**\n * 로고 클릭 핸들러\n */\nconst handleLogoClick = () => {\n  emit('logoClick')\n}\n\n/**\n * 네비게이션 아이템 클릭 핸들러\n */\nconst handleNavClick = (item: HeaderNavItem, index: number) => {\n  item.onClick?.()\n  emit('navClick', item, index)\n}\n\n/**\n * 알림 클릭 핸들러\n */\nconst handleNotificationClick = (item: NotificationItem) => {\n  item.onClick?.()\n  emit('notificationClick', item)\n}\n\n/**\n * 사용자 메뉴 선택 핸들러\n */\nconst handleUserMenuSelect = (itemId: string) => {\n  emit('userMenuSelect', itemId)\n}\n\n/**\n * 로그인 버튼 클릭 핸들러\n */\nconst handleLogin = () => {\n  emit('login')\n}\n\n/**\n * 사이드바 토글 핸들러\n */\nconst handleSidebarToggle = () => {\n  emit('sidebarToggle')\n}\n\n/**\n * tweakcn 테마 타입 정의 (동적 감지 지원)\n */\ntype ThemeName = string\n\n/**\n * 다크모드 상태를 추적하는 반응형 변수\n * - false: 라이트 모드\n * - true: 다크 모드\n * 초기값은 false(라이트 모드)이며, 컴포넌트 마운트 시 실제 테마로 업데이트됩니다.\n */\nconst isDarkMode = ref(false)\n\n/**\n * 현재 선택된 tweakcn 테마 (디폴트 테마로 초기화)\n */\nconst currentTheme = ref<ThemeName>(getDefaultTheme())\n\n/**\n * 테마 옵션 목록 (동적으로 감지)\n */\nconst themeOptions = ref<ThemeName[]>([])\n\n/**\n * 내부 업데이트 플래그\n * - true: 컴포넌트 내부에서 테마를 변경 중 (MutationObserver가 무시해야 함)\n * - false: 외부에서 테마가 변경됨 (MutationObserver가 동기화해야 함)\n */\nlet isInternalUpdate = false\n\n/**\n * MutationObserver 인스턴스\n */\nlet themeObserver: MutationObserver | null = null\nlet styleObserver: MutationObserver | null = null\n\n/**\n * Storybook 환경인지 확인하는 함수\n * \n * @returns Storybook 환경이면 true, 아니면 false\n */\nconst isStorybook = (): boolean => {\n  if (typeof window === 'undefined') return false\n  return !!(\n    window.location?.href?.includes('storybook') ||\n    (window as any).__STORYBOOK_GLOBALS__\n  )\n}\n\n/**\n * 테마 목록을 동적으로 감지하고 업데이트합니다.\n */\nconst updateThemeOptions = () => {\n  const detectedThemes = detectThemeClasses()\n  const ensuredThemes = ensureDefaultTheme(detectedThemes)\n  \n  // availableThemes prop이 지정되면 필터링\n  if (props.availableThemes && props.availableThemes.length > 0) {\n    const filtered = ensuredThemes.filter(theme => props.availableThemes!.includes(theme))\n    // default는 항상 포함\n    themeOptions.value = ensureDefaultTheme(filtered)\n  } else {\n    themeOptions.value = ensuredThemes\n  }\n}\n\n/**\n * localStorage에서 저장된 다크모드 테마를 읽어오는 함수\n * \n * 우선순위:\n * 1. localStorage에 저장된 'theme' 값 (사용자가 이전에 선택한 테마)\n * 2. 시스템 설정 (OS의 다크모드 설정)\n * 3. 기본값 'light' (라이트 모드)\n * \n * @returns 'light' | 'dark' - 적용할 테마\n */\nconst getStoredDarkModeTheme = (): 'light' | 'dark' => {\n  if (typeof window === 'undefined') return 'light'\n  \n  const stored = localStorage.getItem('theme')\n  if (stored === 'dark' || stored === 'light') {\n    return stored\n  }\n  \n  if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {\n    return 'dark'\n  }\n  \n  return 'light'\n}\n\n/**\n * 다크모드 테마를 HTML 문서에 적용하는 함수\n * \n * @param theme - 적용할 테마 ('light' 또는 'dark')\n */\nconst applyDarkModeTheme = (theme: 'light' | 'dark') => {\n  isInternalUpdate = true\n  \n  const root = document.documentElement\n  \n  if (theme === 'dark') {\n    root.classList.add('dark')\n    isDarkMode.value = true\n  } else {\n    root.classList.remove('dark')\n    isDarkMode.value = false\n  }\n  \n  localStorage.setItem('theme', theme)\n  \n  isInternalUpdate = false\n}\n\n/**\n * 테마 토글 버튼 클릭 시 호출되는 핸들러 함수\n */\nconst handleThemeToggle = () => {\n  const newTheme = isDarkMode.value ? 'light' : 'dark'\n  applyDarkModeTheme(newTheme)\n}\n\n/**\n * 저장된 tweakcn 테마를 가져와서 적용합니다.\n */\nconst getStoredTweakcnTheme = (): ThemeName => {\n  // defaultTheme prop이 지정되면 우선 사용\n  if (props.defaultTheme) {\n    const validated = validateThemeExists(props.defaultTheme)\n    return validated\n  }\n  \n  const stored = getStoredTheme('tweakcn-theme')\n  if (!stored) {\n    return getDefaultTheme()\n  }\n  \n  // 저장된 테마가 유효한지 검증\n  const validated = validateThemeExists(stored)\n  return validated\n}\n\n/**\n * tweakcn 테마를 HTML 문서에 적용하는 함수\n */\nconst applyTweakcnTheme = (theme: ThemeName): boolean => {\n  isInternalUpdate = true\n  \n  const validatedTheme = validateThemeExists(theme)\n  const success = applyTheme(validatedTheme)\n  \n  if (success) {\n    currentTheme.value = validatedTheme\n    \n    // Storybook 환경이 아닐 때만 localStorage에 저장\n    // Storybook에서는 툴바가 source of truth이므로 JHeader 변경을 무시\n    if (!isStorybook()) {\n      setStoredTheme(validatedTheme, 'tweakcn-theme')\n    }\n  } else {\n    // 실패 시 디폴트 테마로 폴백\n    const defaultTheme = getDefaultTheme()\n    applyTheme(defaultTheme)\n    currentTheme.value = defaultTheme\n    setStoredTheme(defaultTheme, 'tweakcn-theme')\n  }\n  \n  isInternalUpdate = false\n  return success\n}\n\n/**\n * 테마 변경 핸들러\n */\nconst handleThemeChange = (theme: ThemeName | string | number) => {\n  applyTweakcnTheme(String(theme))\n}\n\n/**\n * 현재 테마에 따라 표시할 아이콘을 계산하는 computed 속성\n */\nconst themeIcon = computed(() => {\n  return isDarkMode.value ? 'sun' : 'moon'\n})\n\n/**\n * 초기화: 저장된 테마 적용 및 테마 목록 감지\n */\nonMounted(() => {\n  // 테마 목록 초기 감지\n  updateThemeOptions()\n  \n  // 저장된 다크모드 테마 적용\n  const darkModeTheme = getStoredDarkModeTheme()\n  applyDarkModeTheme(darkModeTheme)\n  \n  // 저장된 tweakcn 테마 적용\n  const storedTheme = getStoredTweakcnTheme()\n  applyTweakcnTheme(storedTheme)\n  \n  // HTML의 dark 클래스 변경을 감지하여 헤더 컴포넌트 상태를 동기화\n  const root = document.documentElement\n  \n  // 현재 dark 클래스 상태로 초기화\n  isDarkMode.value = root.classList.contains('dark')\n  \n  // MutationObserver로 동적 테마 클래스 감지\n  themeObserver = new MutationObserver(() => {\n    if (isInternalUpdate) return\n    \n    // 다크모드 클래스 변경 감지\n    const hasDarkClass = root.classList.contains('dark')\n    if (hasDarkClass !== isDarkMode.value) {\n      isDarkMode.value = hasDarkClass\n      localStorage.setItem('theme', hasDarkClass ? 'dark' : 'light')\n    }\n    \n    // 테마 목록 업데이트\n    updateThemeOptions()\n    \n    // 현재 적용된 tweakcn 테마 확인\n    const currentThemeClass = Array.from(root.classList).find(cls => cls.startsWith('theme-'))\n    if (currentThemeClass) {\n      const themeName = currentThemeClass.replace('theme-', '')\n      if (themeOptions.value.includes(themeName)) {\n        currentTheme.value = themeName\n      }\n    }\n  })\n  \n  // document.documentElement의 클래스 변경 감지\n  themeObserver.observe(document.documentElement, {\n    attributes: true,\n    attributeFilter: ['class'],\n  })\n  \n  // 스타일시트 변경 감지 (동적으로 추가된 테마 감지)\n  styleObserver = new MutationObserver(() => {\n    updateThemeOptions()\n  })\n  \n  styleObserver.observe(document.head, {\n    childList: true,\n    subtree: true,\n  })\n  \n  // 스토리북 환경에서만 다크모드 및 테마 변경 감지\n  // Storybook 툴바가 source of truth이며, JHeader는 이를 따라감\n  let intervalId: ReturnType<typeof setInterval> | null = null\n  \n  if (isStorybook()) {\n    const checkStorybookGlobals = () => {\n      try {\n        const storybookGlobals = (window as any).__STORYBOOK_GLOBALS__\n        if (storybookGlobals) {\n          // 다크모드 동기화 (Storybook → JHeader)\n          if (typeof storybookGlobals.darkMode !== 'undefined') {\n            const storybookDarkMode = storybookGlobals.darkMode\n            if (storybookDarkMode !== isDarkMode.value) {\n              // isInternalUpdate를 사용하지 않음 - Storybook이 source of truth\n              const root = document.documentElement\n              if (storybookDarkMode) {\n                root.classList.add('dark')\n                isDarkMode.value = true\n              } else {\n                root.classList.remove('dark')\n                isDarkMode.value = false\n              }\n              // Storybook 환경에서는 localStorage 업데이트 안 함\n            }\n          }\n          \n          // tweakcn 테마 동기화 (Storybook → JHeader)\n          if (storybookGlobals.theme && storybookGlobals.theme !== currentTheme.value) {\n            const storybookTheme = String(storybookGlobals.theme)\n            if (themeOptions.value.includes(storybookTheme)) {\n              // isInternalUpdate를 사용하지 않음 - Storybook이 source of truth\n              const validatedTheme = validateThemeExists(storybookTheme)\n              applyTheme(validatedTheme)\n              currentTheme.value = validatedTheme\n              // Storybook 환경에서는 localStorage 업데이트 안 함\n            }\n          }\n        }\n      } catch {\n        // 무시\n      }\n    }\n\n    // 초기 확인\n    checkStorybookGlobals()\n    \n    // 주기적으로 확인 (200ms마다 - 더 빠른 동기화)\n    intervalId = setInterval(checkStorybookGlobals, 200)\n  }\n  \n  // 컴포넌트 언마운트 시 정리\n  onUnmounted(() => {\n    if (themeObserver) {\n      themeObserver.disconnect()\n      themeObserver = null\n    }\n    if (styleObserver) {\n      styleObserver.disconnect()\n      styleObserver = null\n    }\n    if (intervalId) {\n      clearInterval(intervalId)\n    }\n  })\n})\n</script>\n\n<template>\n  <header :class=\"cn('flex items-center justify-between w-full', preset.containerClass)\">\n    <!-- 왼쪽: 햄버거 메뉴 + 로고 + 네비게이션 -->\n    <div class=\"flex items-center gap-6 flex-1\">\n      <!-- 햄버거 메뉴 버튼 (사이드바 토글) -->\n      <JButton\n        v-if=\"showSidebarToggle\"\n        variant=\"ghost\"\n        size=\"sm\"\n        class=\"flex-shrink-0 w-8 h-8 p-0\"\n        aria-label=\"사이드바 토글\"\n        @click=\"handleSidebarToggle\"\n      >\n        <JIcon name=\"menu\" size=\"sm\" />\n      </JButton>\n\n      <!-- 로고 -->\n      <div\n        v-if=\"displayLogoImage || logoText\"\n        class=\"flex items-center cursor-pointer\"\n        @click=\"handleLogoClick\"\n      >\n        <!-- 로고 이미지 (logo prop이 있고 에러가 2 미만일 때) -->\n        <img\n          v-if=\"displayLogoImage && logoImageError < 2\"\n          :src=\"displayLogoImage\"\n          alt=\"로고\"\n          class=\"h-6 w-auto\"\n          @error=\"handleLogoError\"\n        />\n        <!-- 로고 텍스트 (기본 또는 모든 이미지 실패 시) -->\n        <span\n          v-else-if=\"logoText\"\n          class=\"text-sm font-bold text-foreground\"\n        >\n          {{ logoText }}\n        </span>\n      </div>\n\n      <!-- 네비게이션 -->\n      <nav\n        v-if=\"navItems && navItems.length > 0\"\n        class=\"flex items-center gap-1\"\n      >\n        <JButton\n          v-for=\"(item, index) in navItems\"\n          :key=\"index\"\n          variant=\"ghost\"\n          :class=\"cn(\n            preset.navItemClass,\n            item.active && preset.navItemActiveClass\n          )\"\n          @click=\"handleNavClick(item, index)\"\n        >\n          <JIcon\n            v-if=\"item.icon\"\n            :name=\"item.icon\"\n            size=\"sm\"\n            class=\"mr-1.5\"\n          />\n          {{ item.label }}\n        </JButton>\n      </nav>\n    </div>\n\n    <!-- 오른쪽: 테마 선택기 + 알림 + 다크모드 토글 + 사용자 메뉴 -->\n    <div class=\"flex items-center gap-3\">\n      <!-- tweakcn 테마 선택기 -->\n      <JPopover\n        v-if=\"showThemeSelector\"\n        position=\"bottom\"\n        align=\"end\"\n        styletype=\"default-sm\"\n      >\n        <template #trigger>\n          <JButton\n            variant=\"ghost\"\n            size=\"sm\"\n            class=\"w-8 h-8 p-0\"\n            aria-label=\"테마 선택\"\n          >\n            <JIcon name=\"palette\" size=\"sm\" />\n          </JButton>\n        </template>\n        <div class=\"p-2 min-w-[200px]\">\n          <div class=\"text-xs font-medium text-muted-foreground px-2 py-1.5 mb-1\">\n            테마 선택\n          </div>\n          <div class=\"space-y-1\">\n            <button\n              v-for=\"theme in themeOptions\"\n              :key=\"theme\"\n              :class=\"cn(\n                'w-full flex items-center gap-2 px-2 py-1.5 text-xs rounded-md transition-colors',\n                'hover:bg-accent hover:text-accent-foreground',\n                'border-0 outline-none text-left',\n                currentTheme === theme && 'bg-accent text-accent-foreground font-medium'\n              )\"\n              @click=\"handleThemeChange(theme)\"\n            >\n              <JIcon\n                v-if=\"currentTheme === theme\"\n                name=\"check\"\n                size=\"sm\"\n                class=\"flex-shrink-0\"\n              />\n              <span v-else class=\"w-4\" />\n              <span class=\"flex-1 capitalize\">{{ theme }}</span>\n            </button>\n          </div>\n        </div>\n      </JPopover>\n\n      <!-- 알림 -->\n      <JPopover\n        v-if=\"showNotifications\"\n        position=\"bottom\"\n        align=\"end\"\n        styletype=\"default-sm\"\n      >\n        <template #trigger>\n          <JButton\n            variant=\"ghost\"\n            size=\"sm\"\n            class=\"relative w-8 h-8 p-0\"\n            aria-label=\"알림\"\n          >\n            <JIcon name=\"circleAlert\" size=\"sm\" />\n            <span\n              v-if=\"unreadCount > 0\"\n              class=\"absolute top-0 right-0 h-4 w-4 rounded-full bg-destructive text-destructive-foreground text-xs flex items-center justify-center\"\n            >\n              {{ unreadCount > 9 ? '9+' : unreadCount }}\n            </span>\n          </JButton>\n        </template>\n        <div class=\"p-2\">\n          <div\n            v-if=\"notifications && notifications.length > 0\"\n            class=\"max-h-96 overflow-y-auto space-y-1\"\n          >\n            <div\n              v-for=\"notification in notifications\"\n              :key=\"notification.id\"\n              :class=\"cn(\n                'p-3 rounded-md cursor-pointer transition-colors',\n                !notification.read ? 'bg-accent' : 'hover:bg-accent/50'\n              )\"\n              @click=\"handleNotificationClick(notification)\"\n            >\n              <div class=\"flex items-start gap-2\">\n                <JIcon\n                  v-if=\"notification.icon\"\n                  :name=\"notification.icon\"\n                  size=\"sm\"\n                  class=\"mt-0.5 flex-shrink-0\"\n                />\n                <div class=\"flex-1 min-w-0\">\n                  <p class=\"text-xs font-medium text-foreground\">\n                    {{ notification.title }}\n                  </p>\n                  <p\n                    v-if=\"notification.message\"\n                    class=\"text-xs text-muted-foreground mt-1\"\n                  >\n                    {{ notification.message }}\n                  </p>\n                  <p\n                    v-if=\"notification.time\"\n                    class=\"text-xs text-muted-foreground/60 mt-1\"\n                  >\n                    {{ notification.time }}\n                  </p>\n                </div>\n              </div>\n            </div>\n          </div>\n          <div\n            v-else\n            class=\"p-4 text-center text-xs text-muted-foreground\"\n          >\n            알림이 없습니다.\n          </div>\n        </div>\n      </JPopover>\n\n      <!-- 다크모드 토글 버튼 -->\n      <JButton\n        variant=\"ghost\"\n        size=\"sm\"\n        class=\"w-8 h-8 p-0\"\n        :aria-label=\"isDarkMode ? '라이트 모드로 전환' : '다크 모드로 전환'\"\n        @click=\"handleThemeToggle\"\n      >\n        <JIcon :name=\"themeIcon\" size=\"sm\" />\n      </JButton>\n\n      <!-- 커스텀 툴바 슬롯 (다크모드 토글 버튼 우측) -->\n      <slot name=\"toolbar\" />\n\n      <!-- 사용자 메뉴 (userName이 있으면 표시) -->\n      <JPopover\n        v-if=\"userName\"\n        position=\"bottom\"\n        align=\"end\"\n        styletype=\"default-sm\"\n      >\n        <template #trigger>\n          <div class=\"flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity\">\n            <JAvatar\n              :src=\"userAvatar\"\n              :fallback=\"userName ? userName[0] : 'U'\"\n              size=\"xs\"\n            />\n            <span\n              class=\"text-xs text-foreground hidden sm:inline\"\n            >\n              {{ userName }}\n            </span>\n            <JIcon name=\"chevronDown\" size=\"sm\" class=\"text-muted-foreground hidden sm:inline\" />\n          </div>\n        </template>\n        <div class=\"w-full rounded-md overflow-hidden\">\n          <!-- 프로필 정보 영역 -->\n          <div class=\"px-3 py-1.5 border-b border-border\">\n            <p class=\"text-xs font-medium text-foreground\">{{ userName }}</p>\n            <p\n              v-if=\"userEmail\"\n              class=\"text-xs text-muted-foreground mt-0.5\"\n            >\n              {{ userEmail }}\n            </p>\n          </div>\n          \n          <!-- 메뉴 아이템 -->\n          <template v-for=\"(group, groupIndex) in userMenuGroups\" :key=\"groupIndex\">\n            <template v-for=\"(item, itemIndex) in group.items\" :key=\"item.id\">\n              <button\n                v-if=\"!item.separator\"\n                :disabled=\"item.disabled\"\n                :class=\"cn(\n                  'w-full flex items-center gap-2 px-3 py-1.5 text-xs transition-colors',\n                  item.id === 'logout' \n                    ? 'text-destructive hover:bg-destructive/10 hover:text-destructive' \n                    : 'hover:bg-accent hover:text-accent-foreground',\n                  'disabled:opacity-50 disabled:pointer-events-none',\n                  'border-0 outline-none',\n                  group.items[itemIndex + 1]?.separator && 'border-b-0'\n                )\"\n                @click=\"handleUserMenuSelect(item.id)\"\n              >\n                <JIcon\n                  v-if=\"item.icon\"\n                  :name=\"item.icon\"\n                  size=\"sm\"\n                  :class=\"cn(\n                    'flex-shrink-0',\n                    item.id === 'logout' && 'text-destructive'\n                  )\"\n                />\n                <span class=\"flex-1 text-left truncate\">{{ item.label }}</span>\n              </button>\n              <div\n                v-else-if=\"item.separator && itemIndex > 0\"\n                class=\"h-px bg-muted my-1\"\n              />\n            </template>\n            <div\n              v-if=\"groupIndex < userMenuGroups.length - 1\"\n              class=\"h-px bg-muted my-1\"\n            />\n          </template>\n        </div>\n      </JPopover>\n\n      <!-- 로그인 버튼 (userName이 없으면 표시) -->\n      <JButton\n        v-else\n        variant=\"ghost\"\n        size=\"sm\"\n        aria-label=\"로그인\"\n        @click=\"handleLogin\"\n      >\n        <JIcon name=\"logIn\" size=\"sm\" class=\"sm:mr-1.5\" />\n        <span class=\"hidden sm:inline\">로그인</span>\n      </JButton>\n    </div>\n  </header>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","logoImageError","ref","logoImageSrc","displayLogoImage","logoFallback","handleLogoError","unreadCount","n","fixedUserMenuItems","userMenuGroups","handleLogoClick","handleNavClick","item","index","handleNotificationClick","handleUserMenuSelect","itemId","handleLogin","handleSidebarToggle","isDarkMode","currentTheme","getDefaultTheme","themeOptions","isInternalUpdate","themeObserver","styleObserver","isStorybook","updateThemeOptions","detectedThemes","detectThemeClasses","ensuredThemes","ensureDefaultTheme","filtered","theme","getStoredDarkModeTheme","stored","applyDarkModeTheme","root","handleThemeToggle","newTheme","getStoredTweakcnTheme","validateThemeExists","getStoredTheme","applyTweakcnTheme","validatedTheme","success","applyTheme","setStoredTheme","defaultTheme","handleThemeChange","themeIcon","onMounted","darkModeTheme","storedTheme","hasDarkClass","currentThemeClass","cls","themeName","intervalId","checkStorybookGlobals","storybookGlobals","storybookDarkMode","storybookTheme","onUnmounted","_createElementBlock","_normalizeClass","_unref","cn","_createElementVNode","_hoisted_1","_createBlock","JButton","_createVNode","JIcon","_hoisted_3","_toDisplayString","_openBlock","_hoisted_4","_Fragment","_renderList","$event","_hoisted_5","JPopover","_hoisted_6","_cache","_hoisted_7","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","notification","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_renderSlot","_ctx","_hoisted_21","JAvatar","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_26","group","groupIndex","itemIndex","_hoisted_29","_hoisted_28","_hoisted_30"],"mappings":"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"}