@j-solution/components 2.0.5 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +4 -6
  2. package/assets/jwms-portal-frontend-Cu-V5XAR.css +1 -0
  3. package/assets/styles/j-components.css +1 -1
  4. package/assets/styles/main.css +22 -0
  5. package/components/atoms/JSplitter.vue.cjs +1 -1
  6. package/components/atoms/JSplitter.vue.js +2 -2
  7. package/components/atoms/JSplitter.vue2.cjs +1 -1
  8. package/components/atoms/JSplitter.vue2.cjs.map +1 -1
  9. package/components/atoms/JSplitter.vue2.js +30 -28
  10. package/components/atoms/JSplitter.vue2.js.map +1 -1
  11. package/components/molecules/JFormField.vue.cjs +1 -1
  12. package/components/molecules/JFormField.vue.js +2 -2
  13. package/components/molecules/JFormField.vue2.cjs +1 -1
  14. package/components/molecules/JFormField.vue2.cjs.map +1 -1
  15. package/components/molecules/JFormField.vue2.js +80 -79
  16. package/components/molecules/JFormField.vue2.js.map +1 -1
  17. package/components/templates/JLayout.vue.cjs +6 -1
  18. package/components/templates/JLayout.vue.cjs.map +1 -1
  19. package/components/templates/JLayout.vue.js +10 -43
  20. package/components/templates/JLayout.vue.js.map +1 -1
  21. package/components/templates/JLayout.vue2.cjs +1 -1
  22. package/components/templates/JLayout.vue2.cjs.map +1 -1
  23. package/components/templates/JLayout.vue2.js +71 -2
  24. package/components/templates/JLayout.vue2.js.map +1 -1
  25. package/components/templates/JLayoutAdvanced.vue.cjs +1 -1
  26. package/components/templates/JLayoutAdvanced.vue.js +12 -12
  27. package/components/templates/JLayoutSimple.vue.cjs +1 -1
  28. package/components/templates/JLayoutSimple.vue.cjs.map +1 -1
  29. package/components/templates/JLayoutSimple.vue.js +32 -22
  30. package/components/templates/JLayoutSimple.vue.js.map +1 -1
  31. package/composables/useBreakpoint.cjs +2 -0
  32. package/composables/useBreakpoint.cjs.map +1 -0
  33. package/composables/useBreakpoint.js +27 -0
  34. package/composables/useBreakpoint.js.map +1 -0
  35. package/index.cjs +1 -1
  36. package/index.js +30 -28
  37. package/package.json +2 -1
  38. package/types/index.d.ts +22 -8
  39. package/assets/jwms-portal-frontend-CrtMPGot.css +0 -1
@@ -1,5 +1,74 @@
1
- import f from "./JLayout.vue.js";
1
+ import { defineComponent as C, computed as n, createElementBlock as o, openBlock as s, normalizeClass as r, unref as B, renderSlot as t, createElementVNode as c, Fragment as S, createVNode as f, Transition as u, withCtx as m, createCommentVNode as v } from "vue";
2
+ import { cn as p } from "../../lib/utils.js";
3
+ import { useBreakpoint as O } from "../../composables/useBreakpoint.js";
4
+ const E = {
5
+ key: 0,
6
+ class: "fixed inset-y-0 left-0 z-50 w-[280px] max-w-[80vw] shadow-xl"
7
+ }, V = /* @__PURE__ */ C({
8
+ __name: "JLayout",
9
+ props: {
10
+ styletype: { default: "default" },
11
+ contentScroll: { type: Boolean, default: !0 },
12
+ class: {},
13
+ sidebarOverlay: { type: Boolean, default: !1 },
14
+ sidebarOpen: { type: Boolean, default: !1 }
15
+ },
16
+ emits: ["backdrop-click"],
17
+ setup(a, { emit: k }) {
18
+ const e = a, y = k, { isMobile: b } = O(), h = n(() => e.sidebarOverlay || b.value), d = {
19
+ default: {
20
+ containerClass: "flex flex-col h-screen w-full overflow-hidden",
21
+ contentClass: "flex flex-1 overflow-hidden"
22
+ },
23
+ minimal: {
24
+ containerClass: "flex flex-col h-screen w-full overflow-hidden",
25
+ contentClass: "flex flex-1 overflow-hidden"
26
+ }
27
+ }, i = n(() => d[e.styletype] ?? d.default), w = n(() => p(
28
+ i.value.contentClass,
29
+ !e.contentScroll && "overflow-hidden"
30
+ )), x = () => {
31
+ y("backdrop-click");
32
+ };
33
+ return (l, $) => (s(), o("div", {
34
+ class: r(B(p)(i.value.containerClass, e.class))
35
+ }, [
36
+ t(l.$slots, "header", {}, void 0, !0),
37
+ c("div", {
38
+ class: r(w.value)
39
+ }, [
40
+ h.value ? (s(), o(S, { key: 0 }, [
41
+ f(u, { name: "j-sidebar-backdrop" }, {
42
+ default: m(() => [
43
+ a.sidebarOpen ? (s(), o("div", {
44
+ key: 0,
45
+ class: "fixed inset-0 z-40 bg-black/40",
46
+ onClick: x
47
+ })) : v("", !0)
48
+ ]),
49
+ _: 1
50
+ }),
51
+ f(u, { name: "j-sidebar-drawer" }, {
52
+ default: m(() => [
53
+ a.sidebarOpen ? (s(), o("div", E, [
54
+ t(l.$slots, "sidebar", {}, void 0, !0)
55
+ ])) : v("", !0)
56
+ ]),
57
+ _: 3
58
+ })
59
+ ], 64)) : t(l.$slots, "sidebar", { key: 1 }, void 0, !0),
60
+ c("div", {
61
+ class: r(["flex-1 flex flex-col min-h-0", e.contentScroll ? "overflow-auto" : "overflow-hidden"])
62
+ }, [
63
+ t(l.$slots, "content", {}, () => [
64
+ t(l.$slots, "default", {}, void 0, !0)
65
+ ], !0)
66
+ ], 2)
67
+ ], 2)
68
+ ], 2));
69
+ }
70
+ });
2
71
  export {
3
- f as default
72
+ V as default
4
73
  };
5
74
  //# sourceMappingURL=JLayout.vue2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JLayout.vue2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"JLayout.vue2.js","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":";;;;;;;;;;;;;;;;;AAqCA,UAAMA,IAAQC,GAqBRC,IAAOC,GAIP,EAAE,UAAAC,EAAA,IAAaC,EAAA,GAGfC,IAAgBC,EAAS,MAAMP,EAAM,kBAAkBI,EAAS,KAAK,GAKrEI,IAGD;AAAA,MACH,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,cAAc;AAAA,MAAA;AAAA,MAEhB,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,cAAc;AAAA,MAAA;AAAA,IAChB,GAGIC,IAASF,EAAS,MACfC,EAAcR,EAAM,SAAS,KAAKQ,EAAc,OACxD,GAEKE,IAAiBH,EAAS,MACvBI;AAAA,MACLF,EAAO,MAAM;AAAA,MACb,CAACT,EAAM,iBAAiB;AAAA,IAAA,CAE3B,GAEKY,IAAsB,MAAM;AAChC,MAAAV,EAAK,gBAAgB;AAAA,IACvB;2BAIEW,EAsCM,OAAA;AAAA,MAtCA,OAAKC,EAAEC,KAAGN,EAAA,MAAO,gBAAgBT,EAAM,KAAK,CAAA;AAAA,IAAA;MAEhDgB,EAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,MAGtBC,EAgCM,OAAA;AAAA,QAhCA,SAAOR,EAAA,KAAc;AAAA,MAAA;QAETJ,EAAA,cAAhBO,EAiBWM,GAAA,EAAA,KAAA,KAAA;AAAA,UAfTC,EAMaC,GAAA,EAND,MAAK,wBAAoB;AAAA,uBACnC,MAIE;AAAA,cAHMpB,EAAA,oBADRY,EAIE,OAAA;AAAA;gBAFA,OAAM;AAAA,gBACL,SAAOD;AAAA,cAAA;;;;UAGZQ,EAOaC,GAAA,EAPD,MAAK,sBAAkB;AAAA,uBACjC,MAKM;AAAA,cAJEpB,EAAA,eADRqB,EAAA,GAAAT,EAKM,OALNU,GAKM;AAAA,gBADJP,EAAuBC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;;;;kBAM3BD,EAAuBC,EAAA,QAAA,WAAA,EAAA,KAAA,KAAA,QAAA,EAAA;AAAA,QAIzBC,EAKM,OAAA;AAAA,UALD,OAAKJ,EAAA,CAAC,gCAAuCd,EAAM,gBAAa,kBAAA,iBAAA,CAAA;AAAA,QAAA;UACnEgB,EAGOC,yBAHP,MAGO;AAAA,YADLD,EAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;;;;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),A=require("./JLayout.vue.cjs"),k=require("../organisms/JHeader.vue.cjs"),S=require("../organisms/JSidebarAdvanced.vue.cjs"),x=require("../organisms/JDynamicTabs.vue.cjs"),f=require("vue-router"),P={key:1,class:"flex-1 p-6"},w={class:"text-muted-foreground"},B={key:0,class:"text-xs text-gray-400 mt-2"},R=e.defineComponent({__name:"JLayoutAdvanced",props:{styletype:{default:"minimal"},contentScroll:{type:Boolean,default:!0},class:{},menuItems:{default:()=>[]},favorites:{default:()=>[]},permissions:{default:()=>[]}},emits:["menuClick","tabAdd","tabChange","tabClose","favoriteChange"],setup(m,{emit:b}){const o=m,s=b,u=e.ref(!0),y=()=>{u.value=!u.value},d=e.ref(null),l=e.ref([]),n=e.ref(void 0),h=t=>t?`tab-${t.replace(/^\/+|\/+$/g,"").replace(/\//g,"-")}`:"";let i=null;try{i=f.useRouter()}catch{i=null}const g=async t=>{const a=t.menuItem;if(!a||a.menuType!=="L"){s("menuClick",t);return}if(!a.path){s("menuClick",t);return}const r=h(a.path);if(await e.nextTick(),await e.nextTick(),d.value&&typeof d.value.addTab=="function")try{d.value.addTab({id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0,meta:{path:a.path,menuKey:a.menuKey}}),s("tabAdd",{id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0}),i&&i.push({path:a.path});return}catch(p){console.error("탭 추가 실패:",p)}const c={id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0,meta:{path:a.path,menuKey:a.menuKey}};Array.isArray(l.value)||(l.value=[]),l.value.find(p=>p.id===r)?n.value=r:(l.value=[...l.value,c],n.value=r,s("tabAdd",c)),i&&i.push({path:a.path})},_=t=>{Array.isArray(l.value)||(l.value=[]),l.value.find(r=>r.id===t.id)||l.value.push(t),n.value=t.id,s("tabAdd",t)},C=t=>{!l.value||!Array.isArray(l.value)||l.value.length===0||(l.value=l.value.filter(a=>a.id!==t),n.value===t&&Array.isArray(l.value)&&l.value.length>0&&l.value[0]?n.value=l.value[0].id:Array.isArray(l.value)&&l.value.length===0&&(n.value=void 0),s("tabClose",t))},T=t=>{n.value=t,s("tabChange",t)},v=e.computed(()=>Array.isArray(l.value)?l.value:[]);return(t,a)=>(e.openBlock(),e.createBlock(A.default,e.normalizeProps(e.guardReactiveProps(o)),{header:e.withCtx(()=>[e.renderSlot(t.$slots,"header",{isSidebarOpen:u.value,onSidebarToggle:y},()=>[e.createVNode(k.default,{"logo-text":"JWMS Portal",styletype:o.styletype,"show-sidebar-toggle":!0,"is-sidebar-open":u.value,onSidebarToggle:y},null,8,["styletype","is-sidebar-open"])])]),sidebar:e.withCtx(()=>[e.renderSlot(t.$slots,"sidebar",{isSidebarOpen:u.value},()=>[e.createVNode(S.default,{"menu-items":o.menuItems,favorites:o.favorites,permissions:o.permissions,styletype:o.styletype,"is-visible":u.value,onMenuClick:g,onFavoriteChange:a[0]||(a[0]=(r,c)=>s("favoriteChange",r,c))},null,8,["menu-items","favorites","permissions","styletype","is-visible"])])]),content:e.withCtx(()=>[e.renderSlot(t.$slots,"content",{tabs:v.value,activeTabId:n.value,tabsRef:d.value},()=>[e.createVNode(x.default,{ref_key:"tabsRef",ref:d,"initial-tabs":v.value,"default-active-id":n.value,styletype:o.styletype||"minimal",onTabAdd:_,onTabClose:C,onTabChange:T},e.createSlots({_:2},[e.renderList(v.value,r=>({name:`content-${r.id}`,fn:e.withCtx(c=>[e.renderSlot(t.$slots,`content-${r.id}`,e.normalizeProps(e.guardReactiveProps(c)),()=>[r.meta?.path&&e.unref(i)?(e.openBlock(),e.createBlock(e.unref(f.RouterView),{key:r.id})):(e.openBlock(),e.createElementBlock("div",P,[e.createElementVNode("p",w,"콘텐츠를 배치해주세요. (Path: "+e.toDisplayString(r.meta?.path||"N/A")+")",1),e.unref(i)?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("p",B," Router가 없어서 슬롯으로 콘텐츠를 제공해야 합니다. "))]))])])}))]),1032,["initial-tabs","default-active-id","styletype"])])]),_:3},16))}});exports.default=R;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),A=require("./JLayout.vue.cjs"),k=require("../organisms/JHeader.vue.cjs"),S=require("../organisms/JSidebarAdvanced.vue.cjs"),x=require("../organisms/JDynamicTabs.vue.cjs"),y=require("vue-router"),P={key:1,class:"flex-1 p-6"},w={class:"text-muted-foreground"},B={key:0,class:"text-xs text-gray-400 mt-2"},R=e.defineComponent({__name:"JLayoutAdvanced",props:{styletype:{default:"minimal"},contentScroll:{type:Boolean,default:!0},class:{},menuItems:{default:()=>[]},favorites:{default:()=>[]},permissions:{default:()=>[]}},emits:["menuClick","tabAdd","tabChange","tabClose","favoriteChange"],setup(m,{emit:b}){const o=m,s=b,u=e.ref(!0),f=()=>{u.value=!u.value},c=e.ref(null),l=e.ref([]),n=e.ref(void 0),h=t=>t?`tab-${t.replace(/^\/+|\/+$/g,"").replace(/\//g,"-")}`:"";let i=null;try{i=y.useRouter()}catch{i=null}const g=async t=>{const a=t.menuItem;if(!a||a.menuType!=="L"){s("menuClick",t);return}if(!a.path){s("menuClick",t);return}const r=h(a.path);if(await e.nextTick(),await e.nextTick(),c.value&&typeof c.value.addTab=="function")try{c.value.addTab({id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0,meta:{path:a.path,menuKey:a.menuKey}}),s("tabAdd",{id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0}),i&&i.push({path:a.path});return}catch(p){console.error("탭 추가 실패:",p)}const d={id:r,label:a.label||"제목 없음",icon:a.icon,closable:!0,meta:{path:a.path,menuKey:a.menuKey}};Array.isArray(l.value)||(l.value=[]),l.value.find(p=>p.id===r)?n.value=r:(l.value=[...l.value,d],n.value=r,s("tabAdd",d)),i&&i.push({path:a.path})},_=t=>{Array.isArray(l.value)||(l.value=[]),l.value.find(r=>r.id===t.id)||l.value.push(t),n.value=t.id,s("tabAdd",t)},C=t=>{!l.value||!Array.isArray(l.value)||l.value.length===0||(l.value=l.value.filter(a=>a.id!==t),n.value===t&&Array.isArray(l.value)&&l.value.length>0&&l.value[0]?n.value=l.value[0].id:Array.isArray(l.value)&&l.value.length===0&&(n.value=void 0),s("tabClose",t))},T=t=>{n.value=t,s("tabChange",t)},v=e.computed(()=>Array.isArray(l.value)?l.value:[]);return(t,a)=>(e.openBlock(),e.createBlock(A.default,e.normalizeProps(e.guardReactiveProps(o)),{header:e.withCtx(()=>[e.renderSlot(t.$slots,"header",{isSidebarOpen:u.value,onSidebarToggle:f},()=>[e.createVNode(k.default,{"logo-text":"JWMS Portal",styletype:o.styletype,"show-sidebar-toggle":!0,"is-sidebar-open":u.value,onSidebarToggle:f},null,8,["styletype","is-sidebar-open"])])]),sidebar:e.withCtx(()=>[e.renderSlot(t.$slots,"sidebar",{isSidebarOpen:u.value},()=>[e.createVNode(S.default,{"menu-items":o.menuItems,favorites:o.favorites,permissions:o.permissions,styletype:o.styletype,"is-visible":u.value,onMenuClick:g,onFavoriteChange:a[0]||(a[0]=(r,d)=>s("favoriteChange",r,d))},null,8,["menu-items","favorites","permissions","styletype","is-visible"])])]),content:e.withCtx(()=>[e.renderSlot(t.$slots,"content",{tabs:v.value,activeTabId:n.value,tabsRef:c.value},()=>[e.createVNode(x.default,{ref_key:"tabsRef",ref:c,"initial-tabs":v.value,"default-active-id":n.value,styletype:o.styletype||"minimal",onTabAdd:_,onTabClose:C,onTabChange:T},e.createSlots({_:2},[e.renderList(v.value,r=>({name:`content-${r.id}`,fn:e.withCtx(d=>[e.renderSlot(t.$slots,`content-${r.id}`,e.normalizeProps(e.guardReactiveProps(d)),()=>[r.meta?.path&&e.unref(i)?(e.openBlock(),e.createBlock(e.unref(y.RouterView),{key:r.id})):(e.openBlock(),e.createElementBlock("div",P,[e.createElementVNode("p",w,"콘텐츠를 배치해주세요. (Path: "+e.toDisplayString(r.meta?.path||"N/A")+")",1),e.unref(i)?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("p",B," Router가 없어서 슬롯으로 콘텐츠를 제공해야 합니다. "))]))])])}))]),1032,["initial-tabs","default-active-id","styletype"])])]),_:3},16))}});exports.default=R;
2
2
  //# sourceMappingURL=JLayoutAdvanced.vue.cjs.map
@@ -1,4 +1,4 @@
1
- import { defineComponent as B, ref as c, computed as K, createBlock as A, openBlock as m, normalizeProps as C, guardReactiveProps as T, withCtx as v, renderSlot as p, createVNode as b, createSlots as N, renderList as V, createElementBlock as _, unref as h, createElementVNode as J, createCommentVNode as L, toDisplayString as M, nextTick as k } from "vue";
1
+ import { defineComponent as B, ref as c, computed as J, createBlock as A, openBlock as m, normalizeProps as C, guardReactiveProps as T, withCtx as v, renderSlot as p, createVNode as b, createSlots as K, renderList as L, createElementBlock as k, unref as h, createElementVNode as N, createCommentVNode as V, toDisplayString as M, nextTick as _ } from "vue";
2
2
  import O from "./JLayout.vue.js";
3
3
  import E from "../organisms/JHeader.vue.js";
4
4
  import F from "../organisms/JSidebarAdvanced.vue.js";
@@ -21,10 +21,10 @@ const j = {
21
21
  permissions: { default: () => [] }
22
22
  },
23
23
  emits: ["menuClick", "tabAdd", "tabChange", "tabClose", "favoriteChange"],
24
- setup(S, { emit: $ }) {
25
- const r = S, s = $, o = c(!0), g = () => {
24
+ setup(S, { emit: x }) {
25
+ const r = S, s = x, o = c(!0), g = () => {
26
26
  o.value = !o.value;
27
- }, d = c(null), t = c([]), n = c(void 0), x = (e) => e ? `tab-${e.replace(/^\/+|\/+$/g, "").replace(/\//g, "-")}` : "";
27
+ }, d = c(null), t = c([]), n = c(void 0), $ = (e) => e ? `tab-${e.replace(/^\/+|\/+$/g, "").replace(/\//g, "-")}` : "";
28
28
  let i = null;
29
29
  try {
30
30
  i = D();
@@ -41,8 +41,8 @@ const j = {
41
41
  s("menuClick", e);
42
42
  return;
43
43
  }
44
- const l = x(a.path);
45
- if (await k(), await k(), d.value && typeof d.value.addTab == "function")
44
+ const l = $(a.path);
45
+ if (await _(), await _(), d.value && typeof d.value.addTab == "function")
46
46
  try {
47
47
  d.value.addTab({
48
48
  id: l,
@@ -75,7 +75,7 @@ const j = {
75
75
  !t.value || !Array.isArray(t.value) || t.value.length === 0 || (t.value = t.value.filter((a) => a.id !== e), n.value === e && Array.isArray(t.value) && t.value.length > 0 && t.value[0] ? n.value = t.value[0].id : Array.isArray(t.value) && t.value.length === 0 && (n.value = void 0), s("tabClose", e));
76
76
  }, w = (e) => {
77
77
  n.value = e, s("tabChange", e);
78
- }, f = K(() => Array.isArray(t.value) ? t.value : []);
78
+ }, f = J(() => Array.isArray(t.value) ? t.value : []);
79
79
  return (e, a) => (m(), A(O, C(T(r)), {
80
80
  header: v(() => [
81
81
  p(e.$slots, "header", {
@@ -119,16 +119,16 @@ const j = {
119
119
  onTabAdd: P,
120
120
  onTabClose: R,
121
121
  onTabChange: w
122
- }, N({ _: 2 }, [
123
- V(f.value, (l) => ({
122
+ }, K({ _: 2 }, [
123
+ L(f.value, (l) => ({
124
124
  name: `content-${l.id}`,
125
125
  fn: v((u) => [
126
126
  p(e.$slots, `content-${l.id}`, C(T(u)), () => [
127
127
  l.meta?.path && h(i) ? (m(), A(h(W), {
128
128
  key: l.id
129
- })) : (m(), _("div", j, [
130
- J("p", q, "콘텐츠를 배치해주세요. (Path: " + M(l.meta?.path || "N/A") + ")", 1),
131
- h(i) ? L("", !0) : (m(), _("p", G, " Router가 없어서 슬롯으로 콘텐츠를 제공해야 합니다. "))
129
+ })) : (m(), k("div", j, [
130
+ N("p", q, "콘텐츠를 배치해주세요. (Path: " + M(l.meta?.path || "N/A") + ")", 1),
131
+ h(i) ? V("", !0) : (m(), k("p", G, " Router가 없어서 슬롯으로 콘텐츠를 제공해야 합니다. "))
132
132
  ]))
133
133
  ])
134
134
  ])
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),p=require("./JLayout.vue.cjs"),c=require("../organisms/JHeader.vue.cjs"),_=require("../organisms/JSidebar/JSidebar.vue.cjs"),v=require("../organisms/JPageContainer.vue.cjs"),g=e.defineComponent({__name:"JLayoutSimple",props:{styletype:{default:"default"},contentScroll:{type:Boolean,default:!0},class:{},menuItems:{default:()=>[]},activePath:{},storageKey:{}},emits:["menu-click"],setup(s,{emit:u}){const o=s,n=u,t=e.ref(!1),r=()=>{t.value=!t.value},i=(l,a)=>{n("menu-click",l,a)};return(l,a)=>(e.openBlock(),e.createBlock(p.default,e.normalizeProps(e.guardReactiveProps(o)),{header:e.withCtx(()=>[e.renderSlot(l.$slots,"header",{isSidebarCollapsed:t.value,onSidebarToggle:r},()=>[e.createVNode(c.default,{"logo-text":"JWMS Portal",styletype:o.styletype,"show-sidebar-toggle":!0,"is-sidebar-open":!t.value,onSidebarToggle:r},null,8,["styletype","is-sidebar-open"])])]),sidebar:e.withCtx(()=>[e.renderSlot(l.$slots,"sidebar",{isSidebarCollapsed:t.value},()=>[e.createVNode(_.default,{collapsed:t.value,"onUpdate:collapsed":a[0]||(a[0]=d=>t.value=d),items:o.menuItems,"active-path":o.activePath,"storage-key":o.storageKey,onMenuClick:i},null,8,["collapsed","items","active-path","storage-key"])])]),content:e.withCtx(()=>[e.renderSlot(l.$slots,"content",{},()=>[e.renderSlot(l.$slots,"default",{},()=>[e.createVNode(v.default,{title:"페이지 제목"},{default:e.withCtx(()=>[...a[1]||(a[1]=[e.createElementVNode("div",{class:"p-6"},[e.createElementVNode("p",{class:"text-muted-foreground"},"콘텐츠를 배치해주세요.")],-1)])]),_:1})])])]),_:3},16))}});exports.default=g;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),v=require("./JLayout.vue.cjs"),_=require("../organisms/JHeader.vue.cjs"),g=require("../organisms/JSidebar/JSidebar.vue.cjs"),m=require("../organisms/JPageContainer.vue.cjs"),f=require("../../composables/useBreakpoint.cjs"),y=e.defineComponent({__name:"JLayoutSimple",props:{styletype:{default:"default"},contentScroll:{type:Boolean,default:!0},class:{},menuItems:{default:()=>[]},activePath:{},storageKey:{}},emits:["menu-click"],setup(u,{emit:n}){const o=u,i=n,{isMobile:r}=f.useBreakpoint(),t=e.ref(!1);e.watch(r,a=>{a&&(t.value=!0)});const s=()=>{t.value=!t.value},d=(a,l)=>{i("menu-click",a,l),r.value&&(t.value=!0)},c=()=>{t.value=!0};return(a,l)=>(e.openBlock(),e.createBlock(v.default,e.mergeProps(o,{"sidebar-open":!t.value,onBackdropClick:c}),{header:e.withCtx(()=>[e.renderSlot(a.$slots,"header",{isSidebarCollapsed:t.value,onSidebarToggle:s},()=>[e.createVNode(_.default,{"logo-text":"JWMS Portal",styletype:o.styletype,"show-sidebar-toggle":!0,"is-sidebar-open":!t.value,onSidebarToggle:s},null,8,["styletype","is-sidebar-open"])])]),sidebar:e.withCtx(()=>[e.renderSlot(a.$slots,"sidebar",{isSidebarCollapsed:t.value},()=>[e.createVNode(g.default,{collapsed:t.value,"onUpdate:collapsed":l[0]||(l[0]=p=>t.value=p),items:o.menuItems,"active-path":o.activePath,"storage-key":o.storageKey,onMenuClick:d},null,8,["collapsed","items","active-path","storage-key"])])]),content:e.withCtx(()=>[e.renderSlot(a.$slots,"content",{},()=>[e.renderSlot(a.$slots,"default",{},()=>[e.createVNode(m.default,{title:"페이지 제목"},{default:e.withCtx(()=>[...l[1]||(l[1]=[e.createElementVNode("div",{class:"p-6"},[e.createElementVNode("p",{class:"text-muted-foreground"},"콘텐츠를 배치해주세요.")],-1)])]),_:1})])])]),_:3},16,["sidebar-open"]))}});exports.default=y;
2
2
  //# sourceMappingURL=JLayoutSimple.vue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"JLayoutSimple.vue.cjs","sources":["../../../../src/components/templates/JLayoutSimple.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport JLayout from './JLayout.vue'\nimport JHeader from '@/components/organisms/JHeader.vue'\nimport JSidebar from '@/components/organisms/JSidebar/JSidebar.vue'\nimport JPageContainer from '@/components/organisms/JPageContainer.vue'\nimport type { SidebarMenuItem } from '@/types/sidebar.types'\n\n/**\n * JLayoutSimple - JSidebar + 일반 PageContainer 조합 템플릿\n *\n * @example\n * ```vue\n * <JLayoutSimple :menu-items=\"menuItems\" storage-key=\"my-app-favorites\">\n * <template #content>\n * <RouterView />\n * </template>\n * </JLayoutSimple>\n * ```\n */\n\nconst props = withDefaults(\n defineProps<{\n /** 레이아웃 스타일 타입 */\n styletype?: 'default' | 'minimal'\n /** 콘텐츠 영역 스크롤 가능 여부 */\n contentScroll?: boolean\n /** 추가 CSS 클래스 */\n class?: string\n /** 메뉴 아이템 목록 */\n menuItems?: SidebarMenuItem[]\n /** 현재 활성 경로 */\n activePath?: string\n /** 즐겨찾기 localStorage 키 */\n storageKey?: string\n }>(),\n {\n styletype: 'default',\n contentScroll: true,\n menuItems: () => [],\n }\n)\n\nconst emit = defineEmits<{\n 'menu-click': [item: SidebarMenuItem, event: MouseEvent]\n}>()\n\nconst isSidebarCollapsed = ref(false)\n\nconst handleSidebarToggle = () => {\n isSidebarCollapsed.value = !isSidebarCollapsed.value\n}\n\nconst handleMenuClick = (item: SidebarMenuItem, event: MouseEvent) => {\n emit('menu-click', item, event)\n}\n</script>\n\n<template>\n <JLayout v-bind=\"props\">\n <template #header>\n <slot name=\"header\" :is-sidebar-collapsed=\"isSidebarCollapsed\" :on-sidebar-toggle=\"handleSidebarToggle\">\n <JHeader\n logo-text=\"JWMS Portal\"\n :styletype=\"props.styletype\"\n :show-sidebar-toggle=\"true\"\n :is-sidebar-open=\"!isSidebarCollapsed\"\n @sidebar-toggle=\"handleSidebarToggle\"\n />\n </slot>\n </template>\n <template #sidebar>\n <slot name=\"sidebar\" :is-sidebar-collapsed=\"isSidebarCollapsed\">\n <JSidebar\n v-model:collapsed=\"isSidebarCollapsed\"\n :items=\"props.menuItems\"\n :active-path=\"props.activePath\"\n :storage-key=\"props.storageKey\"\n @menu-click=\"handleMenuClick\"\n />\n </slot>\n </template>\n <template #content>\n <slot name=\"content\">\n <slot>\n <!-- 기본 콘텐츠 예시 -->\n <JPageContainer title=\"페이지 제목\">\n <div class=\"p-6\">\n <p class=\"text-muted-foreground\">콘텐츠를 배치해주세요.</p>\n </div>\n </JPageContainer>\n </slot>\n </slot>\n </template>\n </JLayout>\n</template>\n"],"names":["props","__props","emit","__emit","isSidebarCollapsed","ref","handleSidebarToggle","handleMenuClick","item","event","_openBlock","_createBlock","JLayout","_renderSlot","_ctx","_createVNode","JHeader","JSidebar","$event","JPageContainer","_cache","_createElementVNode"],"mappings":"khBAqBA,MAAMA,EAAQC,EAsBRC,EAAOC,EAIPC,EAAqBC,EAAAA,IAAI,EAAK,EAE9BC,EAAsB,IAAM,CAChCF,EAAmB,MAAQ,CAACA,EAAmB,KACjD,EAEMG,EAAkB,CAACC,EAAuBC,IAAsB,CACpEP,EAAK,aAAcM,EAAMC,CAAK,CAChC,gBAIEC,EAAAA,UAAA,EAAAC,cAmCUC,EAAAA,8CAnCOZ,CAAK,CAAA,EAAA,CACT,iBACT,IAQO,CARPa,aAQOC,EAAA,OAAA,SAAA,CARc,mBAAsBV,EAAA,MAAqB,gBAAmBE,CAAA,EAAnF,IAQO,CAPLS,EAAAA,YAMEC,EAAAA,QAAA,CALA,YAAU,cACT,UAAWhB,EAAM,UACjB,sBAAqB,GACrB,mBAAkBI,EAAA,MAClB,gBAAgBE,CAAA,8CAIZ,kBACT,IAQO,CARPO,aAQOC,EAAA,OAAA,UAAA,CARe,mBAAsBV,EAAA,KAAA,EAA5C,IAQO,CAPLW,EAAAA,YAMEE,EAAAA,QAAA,CALQ,UAAWb,EAAA,0CAAAA,EAAkB,MAAAc,GACpC,MAAOlB,EAAM,UACb,cAAaA,EAAM,WACnB,cAAaA,EAAM,WACnB,YAAYO,CAAA,gEAIR,kBACT,IASO,CATPM,EAAAA,WASOC,sBATP,IASO,CARLD,EAAAA,WAOOC,sBAPP,IAOO,CALLC,EAAAA,YAIiBI,EAAAA,QAAA,CAJD,MAAM,UAAQ,mBAC5B,IAEM,CAAA,GAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,CAFNC,EAAAA,mBAEM,MAAA,CAFD,MAAM,OAAK,CACdA,EAAAA,mBAAiD,IAAA,CAA9C,MAAM,uBAAA,EAAwB,cAAY,CAAA"}
1
+ {"version":3,"file":"JLayoutSimple.vue.cjs","sources":["../../../../src/components/templates/JLayoutSimple.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport JLayout from './JLayout.vue'\nimport JHeader from '@/components/organisms/JHeader.vue'\nimport JSidebar from '@/components/organisms/JSidebar/JSidebar.vue'\nimport JPageContainer from '@/components/organisms/JPageContainer.vue'\nimport { useBreakpoint } from '@/composables/useBreakpoint'\nimport type { SidebarMenuItem } from '@/types/sidebar.types'\n\n/**\n * JLayoutSimple - JSidebar + 일반 PageContainer 조합 템플릿\n *\n * 모바일에서는 사이드바가 오버레이 드로어로 전환되며,\n * 메뉴 클릭 시 자동으로 닫힙니다.\n *\n * @example\n * ```vue\n * <JLayoutSimple :menu-items=\"menuItems\" storage-key=\"my-app-favorites\">\n * <template #content>\n * <RouterView />\n * </template>\n * </JLayoutSimple>\n * ```\n */\n\nconst props = withDefaults(\n defineProps<{\n /** 레이아웃 스타일 타입 */\n styletype?: 'default' | 'minimal'\n /** 콘텐츠 영역 스크롤 가능 여부 */\n contentScroll?: boolean\n /** 추가 CSS 클래스 */\n class?: string\n /** 메뉴 아이템 목록 */\n menuItems?: SidebarMenuItem[]\n /** 현재 활성 경로 */\n activePath?: string\n /** 즐겨찾기 localStorage 키 */\n storageKey?: string\n }>(),\n {\n styletype: 'default',\n contentScroll: true,\n menuItems: () => [],\n }\n)\n\nconst emit = defineEmits<{\n 'menu-click': [item: SidebarMenuItem, event: MouseEvent]\n}>()\n\nconst { isMobile } = useBreakpoint()\nconst isSidebarCollapsed = ref(false)\n\n// 모바일 전환 시 사이드바 자동 닫기\nwatch(isMobile, (mobile) => {\n if (mobile) isSidebarCollapsed.value = true\n})\n\nconst handleSidebarToggle = () => {\n isSidebarCollapsed.value = !isSidebarCollapsed.value\n}\n\nconst handleMenuClick = (item: SidebarMenuItem, event: MouseEvent) => {\n emit('menu-click', item, event)\n // 모바일에서 메뉴 클릭 시 사이드바 자동 닫기\n if (isMobile.value) isSidebarCollapsed.value = true\n}\n\nconst handleBackdropClick = () => {\n isSidebarCollapsed.value = true\n}\n</script>\n\n<template>\n <JLayout\n v-bind=\"props\"\n :sidebar-open=\"!isSidebarCollapsed\"\n @backdrop-click=\"handleBackdropClick\"\n >\n <template #header>\n <slot name=\"header\" :is-sidebar-collapsed=\"isSidebarCollapsed\" :on-sidebar-toggle=\"handleSidebarToggle\">\n <JHeader\n logo-text=\"JWMS Portal\"\n :styletype=\"props.styletype\"\n :show-sidebar-toggle=\"true\"\n :is-sidebar-open=\"!isSidebarCollapsed\"\n @sidebar-toggle=\"handleSidebarToggle\"\n />\n </slot>\n </template>\n <template #sidebar>\n <slot name=\"sidebar\" :is-sidebar-collapsed=\"isSidebarCollapsed\">\n <JSidebar\n v-model:collapsed=\"isSidebarCollapsed\"\n :items=\"props.menuItems\"\n :active-path=\"props.activePath\"\n :storage-key=\"props.storageKey\"\n @menu-click=\"handleMenuClick\"\n />\n </slot>\n </template>\n <template #content>\n <slot name=\"content\">\n <slot>\n <!-- 기본 콘텐츠 예시 -->\n <JPageContainer title=\"페이지 제목\">\n <div class=\"p-6\">\n <p class=\"text-muted-foreground\">콘텐츠를 배치해주세요.</p>\n </div>\n </JPageContainer>\n </slot>\n </slot>\n </template>\n </JLayout>\n</template>\n"],"names":["props","__props","emit","__emit","isMobile","useBreakpoint","isSidebarCollapsed","ref","watch","mobile","handleSidebarToggle","handleMenuClick","item","event","handleBackdropClick","_createBlock","JLayout","_mergeProps","_renderSlot","_ctx","_createVNode","JHeader","JSidebar","$event","JPageContainer","_cache","_createElementVNode"],"mappings":"mkBAyBA,MAAMA,EAAQC,EAsBRC,EAAOC,EAIP,CAAE,SAAAC,CAAA,EAAaC,gBAAA,EACfC,EAAqBC,EAAAA,IAAI,EAAK,EAGpCC,QAAMJ,EAAWK,GAAW,CACtBA,MAA2B,MAAQ,GACzC,CAAC,EAED,MAAMC,EAAsB,IAAM,CAChCJ,EAAmB,MAAQ,CAACA,EAAmB,KACjD,EAEMK,EAAkB,CAACC,EAAuBC,IAAsB,CACpEX,EAAK,aAAcU,EAAMC,CAAK,EAE1BT,EAAS,QAAOE,EAAmB,MAAQ,GACjD,EAEMQ,EAAsB,IAAM,CAChCR,EAAmB,MAAQ,EAC7B,8BAIES,EAAAA,YAuCUC,EAAAA,QAvCVC,EAAAA,WAuCUjB,EAtCK,CACZ,gBAAeM,EAAA,MACf,gBAAgBQ,CAAA,IAEN,iBACT,IAQO,CARPI,aAQOC,EAAA,OAAA,SAAA,CARc,mBAAsBb,EAAA,MAAqB,gBAAmBI,CAAA,EAAnF,IAQO,CAPLU,EAAAA,YAMEC,EAAAA,QAAA,CALA,YAAU,cACT,UAAWrB,EAAM,UACjB,sBAAqB,GACrB,mBAAkBM,EAAA,MAClB,gBAAgBI,CAAA,8CAIZ,kBACT,IAQO,CARPQ,aAQOC,EAAA,OAAA,UAAA,CARe,mBAAsBb,EAAA,KAAA,EAA5C,IAQO,CAPLc,EAAAA,YAMEE,EAAAA,QAAA,CALQ,UAAWhB,EAAA,0CAAAA,EAAkB,MAAAiB,GACpC,MAAOvB,EAAM,UACb,cAAaA,EAAM,WACnB,cAAaA,EAAM,WACnB,YAAYW,CAAA,gEAIR,kBACT,IASO,CATPO,EAAAA,WASOC,sBATP,IASO,CARLD,EAAAA,WAOOC,sBAPP,IAOO,CALLC,EAAAA,YAIiBI,EAAAA,QAAA,CAJD,MAAM,UAAQ,mBAC5B,IAEM,CAAA,GAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,CAFNC,EAAAA,mBAEM,MAAA,CAFD,MAAM,OAAK,CACdA,EAAAA,mBAAiD,IAAA,CAA9C,MAAM,uBAAA,EAAwB,cAAY,CAAA"}
@@ -1,9 +1,10 @@
1
- import { defineComponent as f, ref as g, createBlock as y, openBlock as v, normalizeProps as b, guardReactiveProps as S, withCtx as l, renderSlot as s, createVNode as r, createElementVNode as n } from "vue";
2
- import k from "./JLayout.vue.js";
3
- import _ from "../organisms/JHeader.vue.js";
4
- import $ from "../organisms/JSidebar/JSidebar.vue.js";
5
- import h from "../organisms/JPageContainer.vue.js";
6
- const w = /* @__PURE__ */ f({
1
+ import { defineComponent as g, ref as y, watch as b, createBlock as k, openBlock as S, mergeProps as h, withCtx as l, renderSlot as s, createVNode as r, createElementVNode as d } from "vue";
2
+ import C from "./JLayout.vue.js";
3
+ import $ from "../organisms/JHeader.vue.js";
4
+ import B from "../organisms/JSidebar/JSidebar.vue.js";
5
+ import _ from "../organisms/JPageContainer.vue.js";
6
+ import { useBreakpoint as M } from "../../composables/useBreakpoint.js";
7
+ const L = /* @__PURE__ */ g({
7
8
  __name: "JLayoutSimple",
8
9
  props: {
9
10
  styletype: { default: "default" },
@@ -14,46 +15,55 @@ const w = /* @__PURE__ */ f({
14
15
  storageKey: {}
15
16
  },
16
17
  emits: ["menu-click"],
17
- setup(d, { emit: p }) {
18
- const a = d, m = p, e = g(!1), i = () => {
18
+ setup(u, { emit: p }) {
19
+ const a = u, c = p, { isMobile: i } = M(), e = y(!1);
20
+ b(i, (t) => {
21
+ t && (e.value = !0);
22
+ });
23
+ const n = () => {
19
24
  e.value = !e.value;
20
- }, u = (t, o) => {
21
- m("menu-click", t, o);
25
+ }, m = (t, o) => {
26
+ c("menu-click", t, o), i.value && (e.value = !0);
27
+ }, f = () => {
28
+ e.value = !0;
22
29
  };
23
- return (t, o) => (v(), y(k, b(S(a)), {
30
+ return (t, o) => (S(), k(C, h(a, {
31
+ "sidebar-open": !e.value,
32
+ onBackdropClick: f
33
+ }), {
24
34
  header: l(() => [
25
35
  s(t.$slots, "header", {
26
36
  isSidebarCollapsed: e.value,
27
- onSidebarToggle: i
37
+ onSidebarToggle: n
28
38
  }, () => [
29
- r(_, {
39
+ r($, {
30
40
  "logo-text": "JWMS Portal",
31
41
  styletype: a.styletype,
32
42
  "show-sidebar-toggle": !0,
33
43
  "is-sidebar-open": !e.value,
34
- onSidebarToggle: i
44
+ onSidebarToggle: n
35
45
  }, null, 8, ["styletype", "is-sidebar-open"])
36
46
  ])
37
47
  ]),
38
48
  sidebar: l(() => [
39
49
  s(t.$slots, "sidebar", { isSidebarCollapsed: e.value }, () => [
40
- r($, {
50
+ r(B, {
41
51
  collapsed: e.value,
42
- "onUpdate:collapsed": o[0] || (o[0] = (c) => e.value = c),
52
+ "onUpdate:collapsed": o[0] || (o[0] = (v) => e.value = v),
43
53
  items: a.menuItems,
44
54
  "active-path": a.activePath,
45
55
  "storage-key": a.storageKey,
46
- onMenuClick: u
56
+ onMenuClick: m
47
57
  }, null, 8, ["collapsed", "items", "active-path", "storage-key"])
48
58
  ])
49
59
  ]),
50
60
  content: l(() => [
51
61
  s(t.$slots, "content", {}, () => [
52
62
  s(t.$slots, "default", {}, () => [
53
- r(h, { title: "페이지 제목" }, {
63
+ r(_, { title: "페이지 제목" }, {
54
64
  default: l(() => [...o[1] || (o[1] = [
55
- n("div", { class: "p-6" }, [
56
- n("p", { class: "text-muted-foreground" }, "콘텐츠를 배치해주세요.")
65
+ d("div", { class: "p-6" }, [
66
+ d("p", { class: "text-muted-foreground" }, "콘텐츠를 배치해주세요.")
57
67
  ], -1)
58
68
  ])]),
59
69
  _: 1
@@ -62,10 +72,10 @@ const w = /* @__PURE__ */ f({
62
72
  ])
63
73
  ]),
64
74
  _: 3
65
- }, 16));
75
+ }, 16, ["sidebar-open"]));
66
76
  }
67
77
  });
68
78
  export {
69
- w as default
79
+ L as default
70
80
  };
71
81
  //# sourceMappingURL=JLayoutSimple.vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JLayoutSimple.vue.js","sources":["../../../../src/components/templates/JLayoutSimple.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport JLayout from './JLayout.vue'\nimport JHeader from '@/components/organisms/JHeader.vue'\nimport JSidebar from '@/components/organisms/JSidebar/JSidebar.vue'\nimport JPageContainer from '@/components/organisms/JPageContainer.vue'\nimport type { SidebarMenuItem } from '@/types/sidebar.types'\n\n/**\n * JLayoutSimple - JSidebar + 일반 PageContainer 조합 템플릿\n *\n * @example\n * ```vue\n * <JLayoutSimple :menu-items=\"menuItems\" storage-key=\"my-app-favorites\">\n * <template #content>\n * <RouterView />\n * </template>\n * </JLayoutSimple>\n * ```\n */\n\nconst props = withDefaults(\n defineProps<{\n /** 레이아웃 스타일 타입 */\n styletype?: 'default' | 'minimal'\n /** 콘텐츠 영역 스크롤 가능 여부 */\n contentScroll?: boolean\n /** 추가 CSS 클래스 */\n class?: string\n /** 메뉴 아이템 목록 */\n menuItems?: SidebarMenuItem[]\n /** 현재 활성 경로 */\n activePath?: string\n /** 즐겨찾기 localStorage 키 */\n storageKey?: string\n }>(),\n {\n styletype: 'default',\n contentScroll: true,\n menuItems: () => [],\n }\n)\n\nconst emit = defineEmits<{\n 'menu-click': [item: SidebarMenuItem, event: MouseEvent]\n}>()\n\nconst isSidebarCollapsed = ref(false)\n\nconst handleSidebarToggle = () => {\n isSidebarCollapsed.value = !isSidebarCollapsed.value\n}\n\nconst handleMenuClick = (item: SidebarMenuItem, event: MouseEvent) => {\n emit('menu-click', item, event)\n}\n</script>\n\n<template>\n <JLayout v-bind=\"props\">\n <template #header>\n <slot name=\"header\" :is-sidebar-collapsed=\"isSidebarCollapsed\" :on-sidebar-toggle=\"handleSidebarToggle\">\n <JHeader\n logo-text=\"JWMS Portal\"\n :styletype=\"props.styletype\"\n :show-sidebar-toggle=\"true\"\n :is-sidebar-open=\"!isSidebarCollapsed\"\n @sidebar-toggle=\"handleSidebarToggle\"\n />\n </slot>\n </template>\n <template #sidebar>\n <slot name=\"sidebar\" :is-sidebar-collapsed=\"isSidebarCollapsed\">\n <JSidebar\n v-model:collapsed=\"isSidebarCollapsed\"\n :items=\"props.menuItems\"\n :active-path=\"props.activePath\"\n :storage-key=\"props.storageKey\"\n @menu-click=\"handleMenuClick\"\n />\n </slot>\n </template>\n <template #content>\n <slot name=\"content\">\n <slot>\n <!-- 기본 콘텐츠 예시 -->\n <JPageContainer title=\"페이지 제목\">\n <div class=\"p-6\">\n <p class=\"text-muted-foreground\">콘텐츠를 배치해주세요.</p>\n </div>\n </JPageContainer>\n </slot>\n </slot>\n </template>\n </JLayout>\n</template>\n"],"names":["props","__props","emit","__emit","isSidebarCollapsed","ref","handleSidebarToggle","handleMenuClick","item","event","_openBlock","_createBlock","JLayout","_renderSlot","_ctx","_createVNode","JHeader","JSidebar","$event","JPageContainer","_cache","_createElementVNode"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,UAAMA,IAAQC,GAsBRC,IAAOC,GAIPC,IAAqBC,EAAI,EAAK,GAE9BC,IAAsB,MAAM;AAChC,MAAAF,EAAmB,QAAQ,CAACA,EAAmB;AAAA,IACjD,GAEMG,IAAkB,CAACC,GAAuBC,MAAsB;AACpE,MAAAP,EAAK,cAAcM,GAAMC,CAAK;AAAA,IAChC;sBAIEC,EAAA,GAAAC,EAmCUC,OAnCOZ,CAAK,CAAA,GAAA;AAAA,MACT,UACT,MAQO;AAAA,QARPa,EAQOC,EAAA,QAAA,UAAA;AAAA,UARc,oBAAsBV,EAAA;AAAA,UAAqB,iBAAmBE;AAAA,QAAA,GAAnF,MAQO;AAAA,UAPLS,EAMEC,GAAA;AAAA,YALA,aAAU;AAAA,YACT,WAAWhB,EAAM;AAAA,YACjB,uBAAqB;AAAA,YACrB,oBAAkBI,EAAA;AAAA,YAClB,iBAAgBE;AAAA,UAAA;;;MAIZ,WACT,MAQO;AAAA,QARPO,EAQOC,EAAA,QAAA,WAAA,EARe,oBAAsBV,EAAA,MAAA,GAA5C,MAQO;AAAA,UAPLW,EAMEE,GAAA;AAAA,YALQ,WAAWb,EAAA;AAAA,yDAAAA,EAAkB,QAAAc;AAAA,YACpC,OAAOlB,EAAM;AAAA,YACb,eAAaA,EAAM;AAAA,YACnB,eAAaA,EAAM;AAAA,YACnB,aAAYO;AAAA,UAAA;;;MAIR,WACT,MASO;AAAA,QATPM,EASOC,yBATP,MASO;AAAA,UARLD,EAOOC,yBAPP,MAOO;AAAA,YALLC,EAIiBI,GAAA,EAJD,OAAM,YAAQ;AAAA,yBAC5B,MAEM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFNC,EAEM,OAAA,EAFD,OAAM,SAAK;AAAA,kBACdA,EAAiD,KAAA,EAA9C,OAAM,wBAAA,GAAwB,cAAY;AAAA,gBAAA;;;;;;;;;;;"}
1
+ {"version":3,"file":"JLayoutSimple.vue.js","sources":["../../../../src/components/templates/JLayoutSimple.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport JLayout from './JLayout.vue'\nimport JHeader from '@/components/organisms/JHeader.vue'\nimport JSidebar from '@/components/organisms/JSidebar/JSidebar.vue'\nimport JPageContainer from '@/components/organisms/JPageContainer.vue'\nimport { useBreakpoint } from '@/composables/useBreakpoint'\nimport type { SidebarMenuItem } from '@/types/sidebar.types'\n\n/**\n * JLayoutSimple - JSidebar + 일반 PageContainer 조합 템플릿\n *\n * 모바일에서는 사이드바가 오버레이 드로어로 전환되며,\n * 메뉴 클릭 시 자동으로 닫힙니다.\n *\n * @example\n * ```vue\n * <JLayoutSimple :menu-items=\"menuItems\" storage-key=\"my-app-favorites\">\n * <template #content>\n * <RouterView />\n * </template>\n * </JLayoutSimple>\n * ```\n */\n\nconst props = withDefaults(\n defineProps<{\n /** 레이아웃 스타일 타입 */\n styletype?: 'default' | 'minimal'\n /** 콘텐츠 영역 스크롤 가능 여부 */\n contentScroll?: boolean\n /** 추가 CSS 클래스 */\n class?: string\n /** 메뉴 아이템 목록 */\n menuItems?: SidebarMenuItem[]\n /** 현재 활성 경로 */\n activePath?: string\n /** 즐겨찾기 localStorage 키 */\n storageKey?: string\n }>(),\n {\n styletype: 'default',\n contentScroll: true,\n menuItems: () => [],\n }\n)\n\nconst emit = defineEmits<{\n 'menu-click': [item: SidebarMenuItem, event: MouseEvent]\n}>()\n\nconst { isMobile } = useBreakpoint()\nconst isSidebarCollapsed = ref(false)\n\n// 모바일 전환 시 사이드바 자동 닫기\nwatch(isMobile, (mobile) => {\n if (mobile) isSidebarCollapsed.value = true\n})\n\nconst handleSidebarToggle = () => {\n isSidebarCollapsed.value = !isSidebarCollapsed.value\n}\n\nconst handleMenuClick = (item: SidebarMenuItem, event: MouseEvent) => {\n emit('menu-click', item, event)\n // 모바일에서 메뉴 클릭 시 사이드바 자동 닫기\n if (isMobile.value) isSidebarCollapsed.value = true\n}\n\nconst handleBackdropClick = () => {\n isSidebarCollapsed.value = true\n}\n</script>\n\n<template>\n <JLayout\n v-bind=\"props\"\n :sidebar-open=\"!isSidebarCollapsed\"\n @backdrop-click=\"handleBackdropClick\"\n >\n <template #header>\n <slot name=\"header\" :is-sidebar-collapsed=\"isSidebarCollapsed\" :on-sidebar-toggle=\"handleSidebarToggle\">\n <JHeader\n logo-text=\"JWMS Portal\"\n :styletype=\"props.styletype\"\n :show-sidebar-toggle=\"true\"\n :is-sidebar-open=\"!isSidebarCollapsed\"\n @sidebar-toggle=\"handleSidebarToggle\"\n />\n </slot>\n </template>\n <template #sidebar>\n <slot name=\"sidebar\" :is-sidebar-collapsed=\"isSidebarCollapsed\">\n <JSidebar\n v-model:collapsed=\"isSidebarCollapsed\"\n :items=\"props.menuItems\"\n :active-path=\"props.activePath\"\n :storage-key=\"props.storageKey\"\n @menu-click=\"handleMenuClick\"\n />\n </slot>\n </template>\n <template #content>\n <slot name=\"content\">\n <slot>\n <!-- 기본 콘텐츠 예시 -->\n <JPageContainer title=\"페이지 제목\">\n <div class=\"p-6\">\n <p class=\"text-muted-foreground\">콘텐츠를 배치해주세요.</p>\n </div>\n </JPageContainer>\n </slot>\n </slot>\n </template>\n </JLayout>\n</template>\n"],"names":["props","__props","emit","__emit","isMobile","useBreakpoint","isSidebarCollapsed","ref","watch","mobile","handleSidebarToggle","handleMenuClick","item","event","handleBackdropClick","_createBlock","JLayout","_mergeProps","_renderSlot","_ctx","_createVNode","JHeader","JSidebar","$event","JPageContainer","_cache","_createElementVNode"],"mappings":";;;;;;;;;;;;;;;;;;AAyBA,UAAMA,IAAQC,GAsBRC,IAAOC,GAIP,EAAE,UAAAC,EAAA,IAAaC,EAAA,GACfC,IAAqBC,EAAI,EAAK;AAGpC,IAAAC,EAAMJ,GAAU,CAACK,MAAW;AAC1B,MAAIA,QAA2B,QAAQ;AAAA,IACzC,CAAC;AAED,UAAMC,IAAsB,MAAM;AAChC,MAAAJ,EAAmB,QAAQ,CAACA,EAAmB;AAAA,IACjD,GAEMK,IAAkB,CAACC,GAAuBC,MAAsB;AACpE,MAAAX,EAAK,cAAcU,GAAMC,CAAK,GAE1BT,EAAS,UAAOE,EAAmB,QAAQ;AAAA,IACjD,GAEMQ,IAAsB,MAAM;AAChC,MAAAR,EAAmB,QAAQ;AAAA,IAC7B;2BAIES,EAuCUC,GAvCVC,EAuCUjB,GAtCK;AAAA,MACZ,iBAAeM,EAAA;AAAA,MACf,iBAAgBQ;AAAA,IAAA;MAEN,UACT,MAQO;AAAA,QARPI,EAQOC,EAAA,QAAA,UAAA;AAAA,UARc,oBAAsBb,EAAA;AAAA,UAAqB,iBAAmBI;AAAA,QAAA,GAAnF,MAQO;AAAA,UAPLU,EAMEC,GAAA;AAAA,YALA,aAAU;AAAA,YACT,WAAWrB,EAAM;AAAA,YACjB,uBAAqB;AAAA,YACrB,oBAAkBM,EAAA;AAAA,YAClB,iBAAgBI;AAAA,UAAA;;;MAIZ,WACT,MAQO;AAAA,QARPQ,EAQOC,EAAA,QAAA,WAAA,EARe,oBAAsBb,EAAA,MAAA,GAA5C,MAQO;AAAA,UAPLc,EAMEE,GAAA;AAAA,YALQ,WAAWhB,EAAA;AAAA,yDAAAA,EAAkB,QAAAiB;AAAA,YACpC,OAAOvB,EAAM;AAAA,YACb,eAAaA,EAAM;AAAA,YACnB,eAAaA,EAAM;AAAA,YACnB,aAAYW;AAAA,UAAA;;;MAIR,WACT,MASO;AAAA,QATPO,EASOC,yBATP,MASO;AAAA,UARLD,EAOOC,yBAPP,MAOO;AAAA,YALLC,EAIiBI,GAAA,EAJD,OAAM,YAAQ;AAAA,yBAC5B,MAEM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAFNC,EAEM,OAAA,EAFD,OAAM,SAAK;AAAA,kBACdA,EAAiD,KAAA,EAA9C,OAAM,wBAAA,GAAwB,cAAY;AAAA,gBAAA;;;;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),i={md:768,lg:1024};function c(){const n=e.ref("desktop"),a=e.ref(!1),l=e.ref(!1),o=e.ref(!0);let s=null,u=null;function t(){const r=s?.matches??!0,d=u?.matches??!0;r?d?(n.value="desktop",a.value=!1,l.value=!1,o.value=!0):(n.value="tablet",a.value=!1,l.value=!0,o.value=!1):(n.value="mobile",a.value=!0,l.value=!1,o.value=!1)}return e.onMounted(()=>{typeof window>"u"||(s=window.matchMedia(`(min-width: ${i.md}px)`),u=window.matchMedia(`(min-width: ${i.lg}px)`),s.addEventListener("change",t),u.addEventListener("change",t),t())}),e.onUnmounted(()=>{s?.removeEventListener("change",t),u?.removeEventListener("change",t)}),{breakpoint:e.readonly(n),isMobile:e.readonly(a),isTablet:e.readonly(l),isDesktop:e.readonly(o)}}exports.useBreakpoint=c;
2
+ //# sourceMappingURL=useBreakpoint.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBreakpoint.cjs","sources":["../../../src/composables/useBreakpoint.ts"],"sourcesContent":["import { ref, readonly, onMounted, onUnmounted } from 'vue'\r\n\r\ntype Breakpoint = 'mobile' | 'tablet' | 'desktop'\r\n\r\nconst BREAKPOINTS = {\r\n md: 768,\r\n lg: 1024,\r\n} as const\r\n\r\n/**\r\n * useBreakpoint - 반응형 브레이크포인트 감지 composable\r\n *\r\n * @returns isMobile (<768px), isTablet (768~1023px), isDesktop (>=1024px), breakpoint\r\n *\r\n * @example\r\n * ```vue\r\n * const { isMobile, isDesktop } = useBreakpoint()\r\n * // template: v-if=\"isMobile\"\r\n * ```\r\n */\r\nexport function useBreakpoint() {\r\n const breakpoint = ref<Breakpoint>('desktop')\r\n const isMobile = ref(false)\r\n const isTablet = ref(false)\r\n const isDesktop = ref(true)\r\n\r\n let mdQuery: MediaQueryList | null = null\r\n let lgQuery: MediaQueryList | null = null\r\n\r\n function update() {\r\n const mdMatch = mdQuery?.matches ?? true\r\n const lgMatch = lgQuery?.matches ?? true\r\n\r\n if (!mdMatch) {\r\n breakpoint.value = 'mobile'\r\n isMobile.value = true\r\n isTablet.value = false\r\n isDesktop.value = false\r\n } else if (!lgMatch) {\r\n breakpoint.value = 'tablet'\r\n isMobile.value = false\r\n isTablet.value = true\r\n isDesktop.value = false\r\n } else {\r\n breakpoint.value = 'desktop'\r\n isMobile.value = false\r\n isTablet.value = false\r\n isDesktop.value = true\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n if (typeof window === 'undefined') return\r\n\r\n mdQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.md}px)`)\r\n lgQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.lg}px)`)\r\n\r\n mdQuery.addEventListener('change', update)\r\n lgQuery.addEventListener('change', update)\r\n\r\n update()\r\n })\r\n\r\n onUnmounted(() => {\r\n mdQuery?.removeEventListener('change', update)\r\n lgQuery?.removeEventListener('change', update)\r\n })\r\n\r\n return {\r\n breakpoint: readonly(breakpoint),\r\n isMobile: readonly(isMobile),\r\n isTablet: readonly(isTablet),\r\n isDesktop: readonly(isDesktop),\r\n }\r\n}\r\n"],"names":["BREAKPOINTS","useBreakpoint","breakpoint","ref","isMobile","isTablet","isDesktop","mdQuery","lgQuery","update","mdMatch","lgMatch","onMounted","onUnmounted","readonly"],"mappings":"uGAIMA,EAAc,CAClB,GAAI,IACJ,GAAI,IACN,EAaO,SAASC,GAAgB,CAC9B,MAAMC,EAAaC,EAAAA,IAAgB,SAAS,EACtCC,EAAWD,EAAAA,IAAI,EAAK,EACpBE,EAAWF,EAAAA,IAAI,EAAK,EACpBG,EAAYH,EAAAA,IAAI,EAAI,EAE1B,IAAII,EAAiC,KACjCC,EAAiC,KAErC,SAASC,GAAS,CAChB,MAAMC,EAAUH,GAAS,SAAW,GAC9BI,EAAUH,GAAS,SAAW,GAE/BE,EAKOC,GAMVT,EAAW,MAAQ,UACnBE,EAAS,MAAQ,GACjBC,EAAS,MAAQ,GACjBC,EAAU,MAAQ,KARlBJ,EAAW,MAAQ,SACnBE,EAAS,MAAQ,GACjBC,EAAS,MAAQ,GACjBC,EAAU,MAAQ,KARlBJ,EAAW,MAAQ,SACnBE,EAAS,MAAQ,GACjBC,EAAS,MAAQ,GACjBC,EAAU,MAAQ,GAYtB,CAEAM,OAAAA,EAAAA,UAAU,IAAM,CACV,OAAO,OAAW,MAEtBL,EAAU,OAAO,WAAW,eAAeP,EAAY,EAAE,KAAK,EAC9DQ,EAAU,OAAO,WAAW,eAAeR,EAAY,EAAE,KAAK,EAE9DO,EAAQ,iBAAiB,SAAUE,CAAM,EACzCD,EAAQ,iBAAiB,SAAUC,CAAM,EAEzCA,EAAA,EACF,CAAC,EAEDI,EAAAA,YAAY,IAAM,CAChBN,GAAS,oBAAoB,SAAUE,CAAM,EAC7CD,GAAS,oBAAoB,SAAUC,CAAM,CAC/C,CAAC,EAEM,CACL,WAAYK,EAAAA,SAASZ,CAAU,EAC/B,SAAUY,EAAAA,SAASV,CAAQ,EAC3B,SAAUU,EAAAA,SAAST,CAAQ,EAC3B,UAAWS,EAAAA,SAASR,CAAS,CAAA,CAEjC"}
@@ -0,0 +1,27 @@
1
+ import { ref as i, onMounted as v, onUnmounted as f, readonly as u } from "vue";
2
+ const r = {
3
+ md: 768,
4
+ lg: 1024
5
+ };
6
+ function p() {
7
+ const t = i("desktop"), n = i(!1), a = i(!1), l = i(!0);
8
+ let s = null, o = null;
9
+ function e() {
10
+ const d = s?.matches ?? !0, c = o?.matches ?? !0;
11
+ d ? c ? (t.value = "desktop", n.value = !1, a.value = !1, l.value = !0) : (t.value = "tablet", n.value = !1, a.value = !0, l.value = !1) : (t.value = "mobile", n.value = !0, a.value = !1, l.value = !1);
12
+ }
13
+ return v(() => {
14
+ typeof window > "u" || (s = window.matchMedia(`(min-width: ${r.md}px)`), o = window.matchMedia(`(min-width: ${r.lg}px)`), s.addEventListener("change", e), o.addEventListener("change", e), e());
15
+ }), f(() => {
16
+ s?.removeEventListener("change", e), o?.removeEventListener("change", e);
17
+ }), {
18
+ breakpoint: u(t),
19
+ isMobile: u(n),
20
+ isTablet: u(a),
21
+ isDesktop: u(l)
22
+ };
23
+ }
24
+ export {
25
+ p as useBreakpoint
26
+ };
27
+ //# sourceMappingURL=useBreakpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBreakpoint.js","sources":["../../../src/composables/useBreakpoint.ts"],"sourcesContent":["import { ref, readonly, onMounted, onUnmounted } from 'vue'\r\n\r\ntype Breakpoint = 'mobile' | 'tablet' | 'desktop'\r\n\r\nconst BREAKPOINTS = {\r\n md: 768,\r\n lg: 1024,\r\n} as const\r\n\r\n/**\r\n * useBreakpoint - 반응형 브레이크포인트 감지 composable\r\n *\r\n * @returns isMobile (<768px), isTablet (768~1023px), isDesktop (>=1024px), breakpoint\r\n *\r\n * @example\r\n * ```vue\r\n * const { isMobile, isDesktop } = useBreakpoint()\r\n * // template: v-if=\"isMobile\"\r\n * ```\r\n */\r\nexport function useBreakpoint() {\r\n const breakpoint = ref<Breakpoint>('desktop')\r\n const isMobile = ref(false)\r\n const isTablet = ref(false)\r\n const isDesktop = ref(true)\r\n\r\n let mdQuery: MediaQueryList | null = null\r\n let lgQuery: MediaQueryList | null = null\r\n\r\n function update() {\r\n const mdMatch = mdQuery?.matches ?? true\r\n const lgMatch = lgQuery?.matches ?? true\r\n\r\n if (!mdMatch) {\r\n breakpoint.value = 'mobile'\r\n isMobile.value = true\r\n isTablet.value = false\r\n isDesktop.value = false\r\n } else if (!lgMatch) {\r\n breakpoint.value = 'tablet'\r\n isMobile.value = false\r\n isTablet.value = true\r\n isDesktop.value = false\r\n } else {\r\n breakpoint.value = 'desktop'\r\n isMobile.value = false\r\n isTablet.value = false\r\n isDesktop.value = true\r\n }\r\n }\r\n\r\n onMounted(() => {\r\n if (typeof window === 'undefined') return\r\n\r\n mdQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.md}px)`)\r\n lgQuery = window.matchMedia(`(min-width: ${BREAKPOINTS.lg}px)`)\r\n\r\n mdQuery.addEventListener('change', update)\r\n lgQuery.addEventListener('change', update)\r\n\r\n update()\r\n })\r\n\r\n onUnmounted(() => {\r\n mdQuery?.removeEventListener('change', update)\r\n lgQuery?.removeEventListener('change', update)\r\n })\r\n\r\n return {\r\n breakpoint: readonly(breakpoint),\r\n isMobile: readonly(isMobile),\r\n isTablet: readonly(isTablet),\r\n isDesktop: readonly(isDesktop),\r\n }\r\n}\r\n"],"names":["BREAKPOINTS","useBreakpoint","breakpoint","ref","isMobile","isTablet","isDesktop","mdQuery","lgQuery","update","mdMatch","lgMatch","onMounted","onUnmounted","readonly"],"mappings":";AAIA,MAAMA,IAAc;AAAA,EAClB,IAAI;AAAA,EACJ,IAAI;AACN;AAaO,SAASC,IAAgB;AAC9B,QAAMC,IAAaC,EAAgB,SAAS,GACtCC,IAAWD,EAAI,EAAK,GACpBE,IAAWF,EAAI,EAAK,GACpBG,IAAYH,EAAI,EAAI;AAE1B,MAAII,IAAiC,MACjCC,IAAiC;AAErC,WAASC,IAAS;AAChB,UAAMC,IAAUH,GAAS,WAAW,IAC9BI,IAAUH,GAAS,WAAW;AAEpC,IAAKE,IAKOC,KAMVT,EAAW,QAAQ,WACnBE,EAAS,QAAQ,IACjBC,EAAS,QAAQ,IACjBC,EAAU,QAAQ,OARlBJ,EAAW,QAAQ,UACnBE,EAAS,QAAQ,IACjBC,EAAS,QAAQ,IACjBC,EAAU,QAAQ,OARlBJ,EAAW,QAAQ,UACnBE,EAAS,QAAQ,IACjBC,EAAS,QAAQ,IACjBC,EAAU,QAAQ;AAAA,EAYtB;AAEA,SAAAM,EAAU,MAAM;AACd,IAAI,OAAO,SAAW,QAEtBL,IAAU,OAAO,WAAW,eAAeP,EAAY,EAAE,KAAK,GAC9DQ,IAAU,OAAO,WAAW,eAAeR,EAAY,EAAE,KAAK,GAE9DO,EAAQ,iBAAiB,UAAUE,CAAM,GACzCD,EAAQ,iBAAiB,UAAUC,CAAM,GAEzCA,EAAA;AAAA,EACF,CAAC,GAEDI,EAAY,MAAM;AAChB,IAAAN,GAAS,oBAAoB,UAAUE,CAAM,GAC7CD,GAAS,oBAAoB,UAAUC,CAAM;AAAA,EAC/C,CAAC,GAEM;AAAA,IACL,YAAYK,EAASZ,CAAU;AAAA,IAC/B,UAAUY,EAASV,CAAQ;AAAA,IAC3B,UAAUU,EAAST,CAAQ;AAAA,IAC3B,WAAWS,EAASR,CAAS;AAAA,EAAA;AAEjC;"}
package/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  require('./assets/styles/j-components.css');
2
2
  require('./assets/styles/themes.css');
3
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});;/* empty css */;/* empty css */;/* empty css */;/* empty css */const e=require("./components/atoms/JButton.vue.cjs"),t=require("./components/atoms/JInput.vue.cjs"),u=require("./components/atoms/JTextarea.vue.cjs"),r=require("./components/atoms/JCheckbox.vue.cjs"),_=require("./components/atoms/JCombo.vue.cjs"),a=require("./components/atoms/JSearchCombo.vue.cjs"),i=require("./components/atoms/JRadio.vue.cjs"),p=require("./components/atoms/JSwitch.vue.cjs"),s=require("./components/atoms/JDatepicker.vue.cjs"),n=require("./components/atoms/JDivider.vue.cjs"),l=require("./components/atoms/JEditor.vue.cjs"),o=require("./components/atoms/JLink.vue.cjs"),c=require("./components/atoms/JImage.vue.cjs"),J=require("./components/atoms/JBadge.vue.cjs"),d=require("./components/atoms/JProgress.vue.cjs");;/* empty css */const v=require("./components/atoms/JSpinner.vue.cjs"),q=require("./components/atoms/JAvatar.vue.cjs"),f=require("./components/atoms/JKbd.vue.cjs"),g=require("./components/atoms/JTooltip.vue.cjs"),y=require("./components/atoms/JIcon.vue.cjs"),b=require("./components/atoms/JLabel.vue.cjs"),m=require("./components/atoms/JPopover.vue.cjs"),S=require("./components/atoms/JPreview.vue.cjs"),T=require("./components/atoms/JGrid.vue.cjs"),C=require("./components/atoms/JSplitter.vue.cjs"),P=require("./components/atoms/JSectionTitle.vue.cjs"),h=require("vue-sonner"),A=require("./components/atoms/JToast.vue.cjs"),x=require("./components/molecules/JFormField.vue.cjs"),B=require("./components/molecules/JGroupCombo.vue.cjs"),F=require("./components/molecules/JTabs.vue.cjs"),L=require("./components/molecules/JSearchAddr.vue.cjs"),M=require("./components/molecules/JContextMenu.vue.cjs"),D=require("./components/molecules/JCard.vue.cjs"),E=require("./components/molecules/JAlert.vue.cjs"),k=require("./components/molecules/JAccordion.vue.cjs"),G=require("./components/molecules/JTitlebar.vue.cjs"),I=require("./components/molecules/JButtonGroup.vue.cjs"),w=require("./components/molecules/JBreadcrumb.vue.cjs"),j=require("./components/molecules/JEmptyState.vue.cjs"),H=require("./components/organisms/JDynamicTabs.vue.cjs"),K=require("./components/organisms/JModal.vue.cjs"),O=require("./components/organisms/JFormModal.vue.cjs"),R=require("./components/organisms/JDynamicForm.vue.cjs"),z=require("./components/organisms/JSearchPanel.vue.cjs"),N=require("./components/organisms/JFilterBar.vue.cjs"),Q=require("./components/organisms/JHeader.vue.cjs"),U=require("./components/organisms/JSidebar/JSidebar.vue.cjs"),V=require("./components/organisms/JSidebarSimple.vue.cjs"),W=require("./components/organisms/JSidebarAdvanced.vue.cjs"),X=require("./components/organisms/JPageContainer.vue.cjs"),Y=require("./components/organisms/JTree.vue.cjs"),Z=require("./components/organisms/JShuttle.vue.cjs"),$=require("./components/templates/JLayout.vue.cjs"),ee=require("./components/templates/JLayoutSimple.vue.cjs"),te=require("./components/templates/JLayoutAdvanced.vue.cjs"),ue=require("./components/examples/ExampleCrudPage.vue.cjs"),re=require("./components/examples/ExampleTabMappingPage.vue.cjs");exports.JButton=e.default;exports.JInput=t.default;exports.JTextarea=u.default;exports.JCheckbox=r.default;exports.JCombo=_.default;exports.JSearchCombo=a.default;exports.JRadio=i.default;exports.JSwitch=p.default;exports.JDatepicker=s.default;exports.JDivider=n.default;exports.JEditor=l.default;exports.JLink=o.default;exports.JImage=c.default;exports.JBadge=J.default;exports.JProgress=d.default;exports.JSpinner=v.default;exports.JAvatar=q.default;exports.JKbd=f.default;exports.JTooltip=g.default;exports.JIcon=y.default;exports.JLabel=b.default;exports.JPopover=m.default;exports.JPreview=S.default;exports.JGrid=T.default;exports.JSplitter=C.default;exports.JSectionTitle=P.default;Object.defineProperty(exports,"JToast",{enumerable:!0,get:()=>h.toast});exports.JToaster=A.default;exports.JFormField=x.default;exports.JGroupCombo=B.default;exports.JTabs=F.default;exports.JSearchAddr=L.default;exports.JContextMenu=M.default;exports.JCard=D.default;exports.JAlert=E.default;exports.JAccordion=k.default;exports.JTitlebar=G.default;exports.JButtonGroup=I.default;exports.JBreadcrumb=w.default;exports.JEmptyState=j.default;exports.JDynamicTabs=H.default;exports.JModal=K.default;exports.JFormModal=O.default;exports.JDynamicForm=R.default;exports.JSearchPanel=z.default;exports.JFilterBar=N.default;exports.JHeader=Q.default;exports.JSidebar=U.default;exports.JSidebarSimple=V.default;exports.JSidebarAdvanced=W.default;exports.JPageContainer=X.default;exports.JTree=Y.default;exports.JShuttle=Z.default;exports.JLayout=$.default;exports.JLayoutSimple=ee.default;exports.JLayoutAdvanced=te.default;exports.ExampleCrudPage=ue.default;exports.ExampleTabMappingPage=re.default;
3
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});;/* empty css */;/* empty css */;/* empty css */;/* empty css */const e=require("./components/atoms/JButton.vue.cjs"),t=require("./components/atoms/JInput.vue.cjs"),u=require("./components/atoms/JTextarea.vue.cjs"),r=require("./components/atoms/JCheckbox.vue.cjs"),_=require("./components/atoms/JCombo.vue.cjs"),a=require("./components/atoms/JSearchCombo.vue.cjs"),i=require("./components/atoms/JRadio.vue.cjs"),s=require("./components/atoms/JSwitch.vue.cjs"),p=require("./components/atoms/JDatepicker.vue.cjs"),n=require("./components/atoms/JDivider.vue.cjs"),o=require("./components/atoms/JEditor.vue.cjs"),l=require("./components/atoms/JLink.vue.cjs"),c=require("./components/atoms/JImage.vue.cjs"),J=require("./components/atoms/JBadge.vue.cjs"),d=require("./components/atoms/JProgress.vue.cjs");;/* empty css */const v=require("./components/atoms/JSpinner.vue.cjs"),q=require("./components/atoms/JAvatar.vue.cjs"),f=require("./components/atoms/JKbd.vue.cjs"),g=require("./components/atoms/JTooltip.vue.cjs"),y=require("./components/atoms/JIcon.vue.cjs"),b=require("./components/atoms/JLabel.vue.cjs"),m=require("./components/atoms/JPopover.vue.cjs"),S=require("./components/atoms/JPreview.vue.cjs"),T=require("./components/atoms/JGrid.vue.cjs"),C=require("./components/atoms/JSplitter.vue.cjs"),P=require("./components/atoms/JSectionTitle.vue.cjs"),B=require("vue-sonner"),h=require("./components/atoms/JToast.vue.cjs"),A=require("./components/molecules/JFormField.vue.cjs"),x=require("./components/molecules/JGroupCombo.vue.cjs"),F=require("./components/molecules/JTabs.vue.cjs"),L=require("./components/molecules/JSearchAddr.vue.cjs"),k=require("./components/molecules/JContextMenu.vue.cjs"),M=require("./components/molecules/JCard.vue.cjs"),D=require("./components/molecules/JAlert.vue.cjs"),E=require("./components/molecules/JAccordion.vue.cjs"),G=require("./components/molecules/JTitlebar.vue.cjs"),I=require("./components/molecules/JButtonGroup.vue.cjs"),w=require("./components/molecules/JBreadcrumb.vue.cjs"),j=require("./components/molecules/JEmptyState.vue.cjs"),H=require("./components/organisms/JDynamicTabs.vue.cjs"),K=require("./components/organisms/JModal.vue.cjs"),O=require("./components/organisms/JFormModal.vue.cjs"),R=require("./components/organisms/JDynamicForm.vue.cjs"),z=require("./components/organisms/JSearchPanel.vue.cjs"),N=require("./components/organisms/JFilterBar.vue.cjs"),Q=require("./components/organisms/JHeader.vue.cjs"),U=require("./components/organisms/JSidebar/JSidebar.vue.cjs"),V=require("./components/organisms/JSidebarSimple.vue.cjs"),W=require("./components/organisms/JSidebarAdvanced.vue.cjs"),X=require("./components/organisms/JPageContainer.vue.cjs"),Y=require("./components/organisms/JTree.vue.cjs"),Z=require("./components/organisms/JShuttle.vue.cjs"),$=require("./components/templates/JLayout.vue.cjs"),ee=require("./components/templates/JLayoutSimple.vue.cjs"),te=require("./components/templates/JLayoutAdvanced.vue.cjs"),ue=require("./components/examples/ExampleCrudPage.vue.cjs"),re=require("./components/examples/ExampleTabMappingPage.vue.cjs"),_e=require("./composables/useBreakpoint.cjs");exports.JButton=e.default;exports.JInput=t.default;exports.JTextarea=u.default;exports.JCheckbox=r.default;exports.JCombo=_.default;exports.JSearchCombo=a.default;exports.JRadio=i.default;exports.JSwitch=s.default;exports.JDatepicker=p.default;exports.JDivider=n.default;exports.JEditor=o.default;exports.JLink=l.default;exports.JImage=c.default;exports.JBadge=J.default;exports.JProgress=d.default;exports.JSpinner=v.default;exports.JAvatar=q.default;exports.JKbd=f.default;exports.JTooltip=g.default;exports.JIcon=y.default;exports.JLabel=b.default;exports.JPopover=m.default;exports.JPreview=S.default;exports.JGrid=T.default;exports.JSplitter=C.default;exports.JSectionTitle=P.default;Object.defineProperty(exports,"JToast",{enumerable:!0,get:()=>B.toast});exports.JToaster=h.default;exports.JFormField=A.default;exports.JGroupCombo=x.default;exports.JTabs=F.default;exports.JSearchAddr=L.default;exports.JContextMenu=k.default;exports.JCard=M.default;exports.JAlert=D.default;exports.JAccordion=E.default;exports.JTitlebar=G.default;exports.JButtonGroup=I.default;exports.JBreadcrumb=w.default;exports.JEmptyState=j.default;exports.JDynamicTabs=H.default;exports.JModal=K.default;exports.JFormModal=O.default;exports.JDynamicForm=R.default;exports.JSearchPanel=z.default;exports.JFilterBar=N.default;exports.JHeader=Q.default;exports.JSidebar=U.default;exports.JSidebarSimple=V.default;exports.JSidebarAdvanced=W.default;exports.JPageContainer=X.default;exports.JTree=Y.default;exports.JShuttle=Z.default;exports.JLayout=$.default;exports.JLayoutSimple=ee.default;exports.JLayoutAdvanced=te.default;exports.ExampleCrudPage=ue.default;exports.ExampleTabMappingPage=re.default;exports.useBreakpoint=_e.useBreakpoint;
4
4
  //# sourceMappingURL=index.cjs.map
package/index.js CHANGED
@@ -4,7 +4,7 @@ import './assets/styles/themes.css';
4
4
  /* empty css */
5
5
  /* empty css */
6
6
  /* empty css */
7
- import { default as m } from "./components/atoms/JButton.vue.js";
7
+ import { default as p } from "./components/atoms/JButton.vue.js";
8
8
  import { default as l } from "./components/atoms/JInput.vue.js";
9
9
  import { default as s } from "./components/atoms/JTextarea.vue.js";
10
10
  import { default as J } from "./components/atoms/JCheckbox.vue.js";
@@ -16,8 +16,8 @@ import { default as h } from "./components/atoms/JDatepicker.vue.js";
16
16
  import { default as y } from "./components/atoms/JDivider.vue.js";
17
17
  import { default as B } from "./components/atoms/JEditor.vue.js";
18
18
  import { default as L } from "./components/atoms/JLink.vue.js";
19
- import { default as E } from "./components/atoms/JImage.vue.js";
20
- import { default as k } from "./components/atoms/JBadge.vue.js";
19
+ import { default as D } from "./components/atoms/JImage.vue.js";
20
+ import { default as M } from "./components/atoms/JBadge.vue.js";
21
21
  import { default as I } from "./components/atoms/JProgress.vue.js";
22
22
  /* empty css */
23
23
  import { default as H } from "./components/atoms/JSpinner.vue.js";
@@ -29,10 +29,10 @@ import { default as V } from "./components/atoms/JLabel.vue.js";
29
29
  import { default as X } from "./components/atoms/JPopover.vue.js";
30
30
  import { default as Z } from "./components/atoms/JPreview.vue.js";
31
31
  import { default as $ } from "./components/atoms/JGrid.vue.js";
32
- import { default as ae } from "./components/atoms/JSplitter.vue.js";
32
+ import { default as re } from "./components/atoms/JSplitter.vue.js";
33
33
  import { default as oe } from "./components/atoms/JSectionTitle.vue.js";
34
34
  import { toast as fe } from "vue-sonner";
35
- import { default as me } from "./components/atoms/JToast.vue.js";
35
+ import { default as pe } from "./components/atoms/JToast.vue.js";
36
36
  import { default as le } from "./components/molecules/JFormField.vue.js";
37
37
  import { default as se } from "./components/molecules/JGroupCombo.vue.js";
38
38
  import { default as Je } from "./components/molecules/JTabs.vue.js";
@@ -44,8 +44,8 @@ import { default as he } from "./components/molecules/JAccordion.vue.js";
44
44
  import { default as ye } from "./components/molecules/JTitlebar.vue.js";
45
45
  import { default as Be } from "./components/molecules/JButtonGroup.vue.js";
46
46
  import { default as Le } from "./components/molecules/JBreadcrumb.vue.js";
47
- import { default as Ee } from "./components/molecules/JEmptyState.vue.js";
48
- import { default as ke } from "./components/organisms/JDynamicTabs.vue.js";
47
+ import { default as De } from "./components/molecules/JEmptyState.vue.js";
48
+ import { default as Me } from "./components/organisms/JDynamicTabs.vue.js";
49
49
  import { default as Ie } from "./components/organisms/JModal.vue.js";
50
50
  import { default as He } from "./components/organisms/JFormModal.vue.js";
51
51
  import { default as Re } from "./components/organisms/JDynamicForm.vue.js";
@@ -56,22 +56,23 @@ import { default as Ve } from "./components/organisms/JSidebar/JSidebar.vue.js";
56
56
  import { default as Xe } from "./components/organisms/JSidebarSimple.vue.js";
57
57
  import { default as Ze } from "./components/organisms/JSidebarAdvanced.vue.js";
58
58
  import { default as $e } from "./components/organisms/JPageContainer.vue.js";
59
- import { default as aa } from "./components/organisms/JTree.vue.js";
60
- import { default as oa } from "./components/organisms/JShuttle.vue.js";
61
- import { default as fa } from "./components/templates/JLayout.vue.js";
62
- import { default as ma } from "./components/templates/JLayoutSimple.vue.js";
63
- import { default as la } from "./components/templates/JLayoutAdvanced.vue.js";
64
- import { default as sa } from "./components/examples/ExampleCrudPage.vue.js";
65
- import { default as Ja } from "./components/examples/ExampleTabMappingPage.vue.js";
59
+ import { default as rr } from "./components/organisms/JTree.vue.js";
60
+ import { default as or } from "./components/organisms/JShuttle.vue.js";
61
+ import { default as fr } from "./components/templates/JLayout.vue.js";
62
+ import { default as pr } from "./components/templates/JLayoutSimple.vue.js";
63
+ import { default as lr } from "./components/templates/JLayoutAdvanced.vue.js";
64
+ import { default as sr } from "./components/examples/ExampleCrudPage.vue.js";
65
+ import { default as Jr } from "./components/examples/ExampleTabMappingPage.vue.js";
66
+ import { useBreakpoint as nr } from "./composables/useBreakpoint.js";
66
67
  export {
67
- sa as ExampleCrudPage,
68
- Ja as ExampleTabMappingPage,
68
+ sr as ExampleCrudPage,
69
+ Jr as ExampleTabMappingPage,
69
70
  he as JAccordion,
70
71
  ge as JAlert,
71
72
  R as JAvatar,
72
- k as JBadge,
73
+ M as JBadge,
73
74
  Le as JBreadcrumb,
74
- m as JButton,
75
+ p as JButton,
75
76
  Be as JButtonGroup,
76
77
  Te as JCard,
77
78
  J as JCheckbox,
@@ -80,9 +81,9 @@ export {
80
81
  h as JDatepicker,
81
82
  y as JDivider,
82
83
  Re as JDynamicForm,
83
- ke as JDynamicTabs,
84
+ Me as JDynamicTabs,
84
85
  B as JEditor,
85
- Ee as JEmptyState,
86
+ De as JEmptyState,
86
87
  Ne as JFilterBar,
87
88
  le as JFormField,
88
89
  He as JFormModal,
@@ -90,13 +91,13 @@ export {
90
91
  se as JGroupCombo,
91
92
  Qe as JHeader,
92
93
  Q as JIcon,
93
- E as JImage,
94
+ D as JImage,
94
95
  l as JInput,
95
96
  q as JKbd,
96
97
  V as JLabel,
97
- fa as JLayout,
98
- la as JLayoutAdvanced,
99
- ma as JLayoutSimple,
98
+ fr as JLayout,
99
+ lr as JLayoutAdvanced,
100
+ pr as JLayoutSimple,
100
101
  L as JLink,
101
102
  Ie as JModal,
102
103
  $e as JPageContainer,
@@ -108,19 +109,20 @@ export {
108
109
  b as JSearchCombo,
109
110
  qe as JSearchPanel,
110
111
  oe as JSectionTitle,
111
- oa as JShuttle,
112
+ or as JShuttle,
112
113
  Ve as JSidebar,
113
114
  Ze as JSidebarAdvanced,
114
115
  Xe as JSidebarSimple,
115
116
  H as JSpinner,
116
- ae as JSplitter,
117
+ re as JSplitter,
117
118
  g as JSwitch,
118
119
  Je as JTabs,
119
120
  s as JTextarea,
120
121
  ye as JTitlebar,
121
122
  fe as JToast,
122
- me as JToaster,
123
+ pe as JToaster,
123
124
  N as JTooltip,
124
- aa as JTree
125
+ rr as JTree,
126
+ nr as useBreakpoint
125
127
  };
126
128
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@j-solution/components",
3
3
  "description": "Vue 3 Atomic Design component kit for enterprise dashboards",
4
- "version": "2.0.5",
4
+ "version": "2.0.7",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",
7
7
  "module": "./index.js",
@@ -31,6 +31,7 @@
31
31
  "files": [
32
32
  "assets",
33
33
  "components",
34
+ "composables",
34
35
  "lib",
35
36
  "types",
36
37
  "chunks",