{"version":3,"file":"JLayout.vue2.cjs","sources":["../../../../src/components/templates/JLayout.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '@/lib/utils'\nimport { useBreakpoint } from '@/composables/useBreakpoint'\n\n/**\n * JLayout - 기본 레이아웃 컴포넌트 (templates)\n * Base Layout Component\n *\n * @description\n * 공통 레이아웃 구조를 제공하는 기본 컴포넌트입니다.\n * Header, Sidebar, Content 영역을 슬롯으로 제공하여 유연한 레이아웃 구성이 가능합니다.\n * 모바일에서는 사이드바가 오버레이 드로어로 전환됩니다.\n *\n * 레이아웃 구조:\n * - header: 상단 헤더 영역 (슬롯)\n * - sidebar: 사이드바 영역 (슬롯)\n * - content: 메인 콘텐츠 영역 (슬롯, 기본 슬롯도 지원)\n *\n * @example\n * ```vue\n * <JLayout styletype=\"default\" :content-scroll=\"true\">\n *   <template #header>\n *     <JHeader logo-text=\"JWMS Portal\" />\n *   </template>\n *   <template #sidebar>\n *     <JSidebarSimple :menu-items=\"menuItems\" />\n *   </template>\n *   <template #content>\n *     <div>메인 콘텐츠</div>\n *   </template>\n * </JLayout>\n * ```\n */\n\ntype StyleType = 'default' | 'minimal'\n\nconst props = withDefaults(\n  defineProps<{\n    /** 레이아웃 스타일 타입 */\n    styletype?: StyleType\n    /** 콘텐츠 영역 스크롤 가능 여부 */\n    contentScroll?: boolean\n    /** 추가 CSS 클래스 */\n    class?: string\n    /** 모바일에서 사이드바를 오버레이 드로어로 표시 */\n    sidebarOverlay?: boolean\n    /** 사이드바 오버레이 열림 상태 (sidebarOverlay=true일 때만 사용) */\n    sidebarOpen?: boolean\n  }>(),\n  {\n    styletype: 'default',\n    contentScroll: true,\n    sidebarOverlay: false,\n    sidebarOpen: false,\n  }\n)\n\nconst emit = defineEmits<{\n  'backdrop-click': []\n}>()\n\nconst { isMobile } = useBreakpoint()\n\n// 실제 오버레이 모드: prop으로 명시하거나 모바일 자동 감지\nconst isOverlayMode = computed(() => props.sidebarOverlay || isMobile.value)\n\n/**\n * 스타일 프리셋\n */\nconst STYLE_PRESETS: Record<StyleType, {\n  containerClass: string\n  contentClass: string\n}> = {\n  default: {\n    containerClass: 'flex flex-col h-screen w-full overflow-hidden',\n    contentClass: 'flex flex-1 overflow-hidden',\n  },\n  minimal: {\n    containerClass: 'flex flex-col h-screen w-full overflow-hidden',\n    contentClass: 'flex flex-1 overflow-hidden',\n  },\n}\n\nconst preset = computed(() => {\n  return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\nconst contentClasses = computed(() => {\n  return cn(\n    preset.value.contentClass,\n    !props.contentScroll && 'overflow-hidden'\n  )\n})\n\nconst handleBackdropClick = () => {\n  emit('backdrop-click')\n}\n</script>\n\n<template>\n  <div :class=\"cn(preset.containerClass, props.class)\">\n    <!-- 헤더 슬롯 -->\n    <slot name=\"header\" />\n\n    <!-- 메인 컨텐츠 영역 -->\n    <div :class=\"contentClasses\">\n      <!-- 사이드바: 데스크톱은 인라인, 모바일은 오버레이 -->\n      <template v-if=\"isOverlayMode\">\n        <!-- 모바일 오버레이 드로어 -->\n        <Transition name=\"j-sidebar-backdrop\">\n          <div\n            v-if=\"sidebarOpen\"\n            class=\"fixed inset-0 z-40 bg-black/40\"\n            @click=\"handleBackdropClick\"\n          />\n        </Transition>\n        <Transition name=\"j-sidebar-drawer\">\n          <div\n            v-if=\"sidebarOpen\"\n            class=\"fixed inset-y-0 left-0 z-50 w-[280px] max-w-[80vw] shadow-xl\"\n          >\n            <slot name=\"sidebar\" />\n          </div>\n        </Transition>\n      </template>\n      <template v-else>\n        <!-- 데스크톱 인라인 사이드바 -->\n        <slot name=\"sidebar\" />\n      </template>\n\n      <!-- 콘텐츠 슬롯 -->\n      <div class=\"flex-1 flex flex-col min-h-0\" :class=\"props.contentScroll ? 'overflow-auto' : 'overflow-hidden'\">\n        <slot name=\"content\">\n          <!-- 기본 슬롯도 지원 -->\n          <slot />\n        </slot>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n/* 사이드바 드로어 슬라이드 애니메이션 */\n.j-sidebar-drawer-enter-active,\n.j-sidebar-drawer-leave-active {\n  transition: transform 0.25s ease;\n}\n.j-sidebar-drawer-enter-from,\n.j-sidebar-drawer-leave-to {\n  transform: translateX(-100%);\n}\n\n/* 백드롭 페이드 애니메이션 */\n.j-sidebar-backdrop-enter-active,\n.j-sidebar-backdrop-leave-active {\n  transition: opacity 0.25s ease;\n}\n.j-sidebar-backdrop-enter-from,\n.j-sidebar-backdrop-leave-to {\n  opacity: 0;\n}\n</style>\n"],"names":["props","__props","emit","__emit","isMobile","useBreakpoint","isOverlayMode","computed","STYLE_PRESETS","preset","contentClasses","cn","handleBackdropClick","_createElementBlock","_normalizeClass","_unref","_renderSlot","_ctx","_createElementVNode","_Fragment","_createVNode","_Transition","_openBlock","_hoisted_1"],"mappings":"2hBAqCA,MAAMA,EAAQC,EAqBRC,EAAOC,EAIP,CAAE,SAAAC,CAAA,EAAaC,gBAAA,EAGfC,EAAgBC,EAAAA,SAAS,IAAMP,EAAM,gBAAkBI,EAAS,KAAK,EAKrEI,EAGD,CACH,QAAS,CACP,eAAgB,gDAChB,aAAc,6BAAA,EAEhB,QAAS,CACP,eAAgB,gDAChB,aAAc,6BAAA,CAChB,EAGIC,EAASF,EAAAA,SAAS,IACfC,EAAcR,EAAM,SAAS,GAAKQ,EAAc,OACxD,EAEKE,EAAiBH,EAAAA,SAAS,IACvBI,EAAAA,GACLF,EAAO,MAAM,aACb,CAACT,EAAM,eAAiB,iBAAA,CAE3B,EAEKY,EAAsB,IAAM,CAChCV,EAAK,gBAAgB,CACvB,8BAIEW,EAAAA,mBAsCM,MAAA,CAtCA,MAAKC,EAAAA,eAAEC,EAAAA,YAAGN,EAAA,MAAO,eAAgBT,EAAM,KAAK,CAAA,CAAA,GAEhDgB,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,EAGtBC,EAAAA,mBAgCM,MAAA,CAhCA,uBAAOR,EAAA,KAAc,CAAA,GAETJ,EAAA,qBAAhBO,EAAAA,mBAiBWM,EAAAA,SAAA,CAAA,IAAA,GAAA,CAfTC,EAAAA,YAMaC,EAAAA,WAAA,CAND,KAAK,sBAAoB,mBACnC,IAIE,CAHMpB,EAAA,2BADRY,EAAAA,mBAIE,MAAA,OAFA,MAAM,iCACL,QAAOD,CAAA,wCAGZQ,EAAAA,YAOaC,EAAAA,WAAA,CAPD,KAAK,oBAAkB,mBACjC,IAKM,CAJEpB,EAAA,aADRqB,EAAAA,UAAA,EAAAT,EAAAA,mBAKM,MALNU,EAKM,CADJP,EAAAA,WAAuBC,EAAA,OAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,8CAM3BD,aAAuBC,EAAA,OAAA,UAAA,CAAA,IAAA,GAAA,OAAA,EAAA,EAIzBC,EAAAA,mBAKM,MAAA,CALD,MAAKJ,EAAAA,eAAA,CAAC,+BAAuCd,EAAM,cAAa,gBAAA,iBAAA,CAAA,CAAA,GACnEgB,EAAAA,WAGOC,sBAHP,IAGO,CADLD,EAAAA,WAAQC,EAAA,OAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA"}