@j-solution/components 1.9.4 → 1.9.6
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.
- package/README.md +5 -4
- package/assets/jwms-portal-frontend-DLwBRhhZ.css +1 -0
- package/assets/styles/j-components.css +1 -1
- package/assets/styles/main.css +33 -38
- package/components/atoms/JCombo.vue.cjs +1 -1
- package/components/atoms/JCombo.vue.cjs.map +1 -1
- package/components/atoms/JCombo.vue.js +1 -1
- package/components/atoms/JCombo.vue.js.map +1 -1
- package/components/atoms/JDatepicker.vue.cjs +1 -1
- package/components/atoms/JDatepicker.vue.cjs.map +1 -1
- package/components/atoms/JDatepicker.vue.js +1 -1
- package/components/atoms/JDatepicker.vue.js.map +1 -1
- package/components/atoms/JGrid.vue.cjs +1 -1
- package/components/atoms/JGrid.vue.js +2 -2
- package/components/atoms/JGrid.vue2.cjs.map +1 -1
- package/components/atoms/JGrid.vue2.js.map +1 -1
- package/components/atoms/JInput.vue.cjs +1 -1
- package/components/atoms/JInput.vue.cjs.map +1 -1
- package/components/atoms/JInput.vue.js +1 -1
- package/components/atoms/JInput.vue.js.map +1 -1
- package/components/atoms/JSearchCombo.vue.cjs +1 -1
- package/components/atoms/JSearchCombo.vue.cjs.map +1 -1
- package/components/atoms/JSearchCombo.vue.js +5 -5
- package/components/atoms/JSearchCombo.vue.js.map +1 -1
- package/components/atoms/JSplitter.vue.cjs +1 -1
- package/components/atoms/JSplitter.vue.js +2 -2
- package/components/atoms/JSplitter.vue2.cjs +1 -1
- package/components/atoms/JSplitter.vue2.cjs.map +1 -1
- package/components/atoms/JSplitter.vue2.js +14 -10
- package/components/atoms/JSplitter.vue2.js.map +1 -1
- package/components/molecules/JTabs.vue.cjs +1 -1
- package/components/molecules/JTabs.vue.js +2 -2
- package/components/molecules/JTabs.vue2.cjs +1 -1
- package/components/molecules/JTabs.vue2.cjs.map +1 -1
- package/components/molecules/JTabs.vue2.js +4 -4
- package/components/molecules/JTabs.vue2.js.map +1 -1
- package/components/organisms/JDynamicForm.vue.cjs +1 -1
- package/components/organisms/JDynamicForm.vue.js +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs.map +1 -1
- package/components/organisms/JDynamicForm.vue2.js +35 -35
- package/components/organisms/JDynamicForm.vue2.js.map +1 -1
- package/components/organisms/JFilterBar.vue.cjs +1 -1
- package/components/organisms/JFilterBar.vue.js +2 -2
- package/components/organisms/JFilterBar.vue2.cjs +1 -1
- package/components/organisms/JFilterBar.vue2.cjs.map +1 -1
- package/components/organisms/JFilterBar.vue2.js +2 -2
- package/components/organisms/JFilterBar.vue2.js.map +1 -1
- package/components/organisms/JPageContainer.vue.cjs +1 -1
- package/components/organisms/JPageContainer.vue.cjs.map +1 -1
- package/components/organisms/JPageContainer.vue.js +4 -4
- package/components/organisms/JPageContainer.vue.js.map +1 -1
- package/components/organisms/JSearchPanel.vue.cjs +1 -1
- package/components/organisms/JSearchPanel.vue.js +2 -2
- package/components/organisms/JSearchPanel.vue2.cjs +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
- package/components/organisms/JSearchPanel.vue2.js +3 -3
- package/components/organisms/JSearchPanel.vue2.js.map +1 -1
- package/components/shadcn/Input.vue.cjs +1 -1
- package/components/shadcn/Input.vue.cjs.map +1 -1
- package/components/shadcn/Input.vue.js +1 -1
- package/components/shadcn/Input.vue.js.map +1 -1
- package/components/shadcn/SelectTrigger.vue.cjs +1 -1
- package/components/shadcn/SelectTrigger.vue.cjs.map +1 -1
- package/components/shadcn/SelectTrigger.vue.js +1 -1
- package/components/shadcn/SelectTrigger.vue.js.map +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.cjs +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.cjs.map +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.js +3 -3
- package/components/shadcn/resizable/ResizableHandle.vue.js.map +1 -1
- package/package.json +1 -1
- package/assets/jwms-portal-frontend-Bd12BmyZ.css +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("vue");require("../shadcn/index.cjs");const i=require("../shadcn/Input.vue.cjs"),p=l.defineComponent({__name:"JInput",props:{modelValue:{},type:{default:"text"},placeholder:{default:""},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(o,{emit:d}){const e=o,r=d,u={default:{class:""},error:{class:"border-destructive focus-visible:ring-destructive"},success:{class:"border-green-500 focus-visible:ring-green-500"},warning:{class:"border-amber-500 focus-visible:ring-amber-500"},sm:{class:"h-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("vue");require("../shadcn/index.cjs");const i=require("../shadcn/Input.vue.cjs"),p=l.defineComponent({__name:"JInput",props:{modelValue:{},type:{default:"text"},placeholder:{default:""},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(o,{emit:d}){const e=o,r=d,u={default:{class:""},error:{class:"border-destructive focus-visible:ring-destructive"},success:{class:"border-green-500 focus-visible:ring-green-500"},warning:{class:"border-amber-500 focus-visible:ring-amber-500"},sm:{class:"h-7 text-xs px-2"},lg:{class:"h-12 text-base px-4"}},n=l.computed(()=>{const t=e.styletype||"default",a=[(u[t]??u.default)?.class,e.class].filter(Boolean).join(" ");return{type:e.type,placeholder:e.placeholder,disabled:e.disabled,readonly:e.readonly,required:e.required,name:e.name,id:e.id,class:a}}),c=t=>{r("update:modelValue",t),r("change",t)};return(t,s)=>(l.openBlock(),l.createBlock(l.unref(i.default),l.mergeProps(n.value,{"model-value":o.modelValue,"onUpdate:modelValue":c,onFocus:s[0]||(s[0]=a=>r("focus",a)),onBlur:s[1]||(s[1]=a=>r("blur",a))}),{default:l.withCtx(()=>[l.renderSlot(t.$slots,"default")]),_:3},16,["model-value"]))}});exports.default=p;
|
|
2
2
|
//# sourceMappingURL=JInput.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JInput.vue.cjs","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\r\n}>()\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \
|
|
1
|
+
{"version":3,"file":"JInput.vue.cjs","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\r\n}>()\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \n class: 'h-7 text-xs px-2',\n },\n lg: { \r\n class: 'h-12 text-base px-4',\r\n },\r\n}\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const styleKey = props.styletype || 'default'\r\n const preset = STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\r\n const finalClass = [preset?.class, props.class].filter(Boolean).join(' ')\r\n \r\n return {\r\n type: props.type,\r\n placeholder: props.placeholder,\r\n disabled: props.disabled,\r\n readonly: props.readonly,\r\n required: props.required,\r\n name: props.name,\r\n id: props.id,\r\n class: finalClass,\r\n }\r\n})\r\n\r\nconst handleInput = (value: string | number) => {\r\n emit('update:modelValue', value)\r\n emit('change', value)\r\n}\r\n</script>\r\n\r\n<template>\r\n <Input \r\n v-bind=\"mapped\" \r\n :model-value=\"modelValue\" \r\n @update:model-value=\"handleInput\"\r\n @focus=\"emit('focus', $event)\"\r\n @blur=\"emit('blur', $event)\"\r\n >\r\n <slot />\r\n </Input>\r\n</template>\r\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","mapped","computed","styleKey","finalClass","handleInput","value","_createBlock","_unref","Input","_mergeProps","_cache","$event","_renderSlot","_ctx"],"mappings":"2hBAYA,MAAMA,EAAQC,EAwBRC,EAAOC,EAUPC,EAAsD,CAC1D,QAAS,CAAE,MAAO,EAAA,EAClB,MAAO,CACL,MAAO,mDAAA,EAET,QAAS,CACP,MAAO,+CAAA,EAET,QAAS,CACP,MAAO,+CAAA,EAET,GAAI,CACF,MAAO,kBAAA,EAET,GAAI,CACF,MAAO,qBAAA,CACT,EAIIC,EAASC,EAAAA,SAAS,IAAM,CAC5B,MAAMC,EAAWP,EAAM,WAAa,UAE9BQ,EAAa,EADJJ,EAAcG,CAAQ,GAAKH,EAAc,UAC5B,MAAOJ,EAAM,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAExE,MAAO,CACL,KAAMA,EAAM,KACZ,YAAaA,EAAM,YACnB,SAAUA,EAAM,SAChB,SAAUA,EAAM,SAChB,SAAUA,EAAM,SAChB,KAAMA,EAAM,KACZ,GAAIA,EAAM,GACV,MAAOQ,CAAA,CAEX,CAAC,EAEKC,EAAeC,GAA2B,CAC9CR,EAAK,oBAAqBQ,CAAK,EAC/BR,EAAK,SAAUQ,CAAK,CACtB,8BAIEC,EAAAA,YAQQC,EAAAA,MAAAC,EAAAA,OAAA,EARRC,EAAAA,WAQQT,EAAA,MAPQ,CACb,cAAaJ,EAAA,WACb,sBAAoBQ,EACpB,QAAKM,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAEd,EAAI,QAAUc,CAAM,GAC3B,OAAID,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAEd,EAAI,OAASc,CAAM,EAAA,sBAE1B,IAAQ,CAARC,aAAQC,EAAA,OAAA,SAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JInput.vue.js","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\r\n}>()\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \
|
|
1
|
+
{"version":3,"file":"JInput.vue.js","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\r\n}>()\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \n class: 'h-7 text-xs px-2',\n },\n lg: { \r\n class: 'h-12 text-base px-4',\r\n },\r\n}\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const styleKey = props.styletype || 'default'\r\n const preset = STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\r\n const finalClass = [preset?.class, props.class].filter(Boolean).join(' ')\r\n \r\n return {\r\n type: props.type,\r\n placeholder: props.placeholder,\r\n disabled: props.disabled,\r\n readonly: props.readonly,\r\n required: props.required,\r\n name: props.name,\r\n id: props.id,\r\n class: finalClass,\r\n }\r\n})\r\n\r\nconst handleInput = (value: string | number) => {\r\n emit('update:modelValue', value)\r\n emit('change', value)\r\n}\r\n</script>\r\n\r\n<template>\r\n <Input \r\n v-bind=\"mapped\" \r\n :model-value=\"modelValue\" \r\n @update:model-value=\"handleInput\"\r\n @focus=\"emit('focus', $event)\"\r\n @blur=\"emit('blur', $event)\"\r\n >\r\n <slot />\r\n </Input>\r\n</template>\r\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","mapped","computed","styleKey","finalClass","handleInput","value","_createBlock","_unref","Input","_mergeProps","_cache","$event","_renderSlot","_ctx"],"mappings":";;;;;;;;;;;;;;;;;;;AAYA,UAAMA,IAAQC,GAwBRC,IAAOC,GAUPC,IAAsD;AAAA,MAC1D,SAAS,EAAE,OAAO,GAAA;AAAA,MAClB,OAAO;AAAA,QACL,OAAO;AAAA,MAAA;AAAA,MAET,SAAS;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,MAET,SAAS;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,MAET,IAAI;AAAA,QACF,OAAO;AAAA,MAAA;AAAA,MAET,IAAI;AAAA,QACF,OAAO;AAAA,MAAA;AAAA,IACT,GAIIC,IAASC,EAAS,MAAM;AAC5B,YAAMC,IAAWP,EAAM,aAAa,WAE9BQ,IAAa,EADJJ,EAAcG,CAAQ,KAAKH,EAAc,UAC5B,OAAOJ,EAAM,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAExE,aAAO;AAAA,QACL,MAAMA,EAAM;AAAA,QACZ,aAAaA,EAAM;AAAA,QACnB,UAAUA,EAAM;AAAA,QAChB,UAAUA,EAAM;AAAA,QAChB,UAAUA,EAAM;AAAA,QAChB,MAAMA,EAAM;AAAA,QACZ,IAAIA,EAAM;AAAA,QACV,OAAOQ;AAAA,MAAA;AAAA,IAEX,CAAC,GAEKC,IAAc,CAACC,MAA2B;AAC9C,MAAAR,EAAK,qBAAqBQ,CAAK,GAC/BR,EAAK,UAAUQ,CAAK;AAAA,IACtB;2BAIEC,EAQQC,EAAAC,CAAA,GARRC,EAQQT,EAAA,OAPQ;AAAA,MACb,eAAaJ,EAAA;AAAA,MACb,uBAAoBQ;AAAA,MACpB,SAAKM,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEd,EAAI,SAAUc,CAAM;AAAA,MAC3B,QAAID,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEd,EAAI,QAASc,CAAM;AAAA,IAAA;iBAE1B,MAAQ;AAAA,QAARC,EAAQC,EAAA,QAAA,SAAA;AAAA,MAAA;;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),n=require("lucide-vue-next"),o=require("../../lib/utils.cjs");require("../shadcn/index.cjs");const b=require("../shadcn/Combobox.vue.cjs"),x=require("../shadcn/ComboboxAnchor.vue.cjs"),_=require("../shadcn/ComboboxTrigger.vue.cjs"),v=require("../shadcn/Button.vue.cjs"),C=require("../shadcn/ComboboxList.vue.cjs"),h=require("../shadcn/ComboboxInput.vue.cjs"),y=require("../shadcn/ComboboxEmpty.vue.cjs"),g=require("../shadcn/ComboboxGroup.vue.cjs"),V=require("../shadcn/ComboboxItem.vue.cjs"),q={class:"relative w-full max-w-sm items-center"},N={class:"absolute start-0 inset-y-0 flex items-center justify-center px-2.5"},w=e.defineComponent({__name:"JSearchCombo",props:{modelValue:{},options:{default:()=>[]},placeholder:{default:"선택해주세요."},searchPlaceholder:{default:""},emptyText:{default:"검색 결과가 없습니다."},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},multiple:{type:Boolean,default:!1},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(t,{emit:c}){const d=t,r=c,i={default:{variant:"outline",buttonClass:"h-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),n=require("lucide-vue-next"),o=require("../../lib/utils.cjs");require("../shadcn/index.cjs");const b=require("../shadcn/Combobox.vue.cjs"),x=require("../shadcn/ComboboxAnchor.vue.cjs"),_=require("../shadcn/ComboboxTrigger.vue.cjs"),v=require("../shadcn/Button.vue.cjs"),C=require("../shadcn/ComboboxList.vue.cjs"),h=require("../shadcn/ComboboxInput.vue.cjs"),y=require("../shadcn/ComboboxEmpty.vue.cjs"),g=require("../shadcn/ComboboxGroup.vue.cjs"),V=require("../shadcn/ComboboxItem.vue.cjs"),q={class:"relative w-full max-w-sm items-center"},N={class:"absolute start-0 inset-y-0 flex items-center justify-center px-2.5"},w=e.defineComponent({__name:"JSearchCombo",props:{modelValue:{},options:{default:()=>[]},placeholder:{default:"선택해주세요."},searchPlaceholder:{default:""},emptyText:{default:"검색 결과가 없습니다."},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},multiple:{type:Boolean,default:!1},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(t,{emit:c}){const d=t,r=c,i={default:{variant:"outline",buttonClass:"h-7 text-xs px-2.5"},error:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-destructive text-destructive",inputClass:"border-destructive focus:ring-destructive"},success:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-green-500 text-green-700",inputClass:"border-green-500 focus:ring-green-500"},warning:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-amber-500 text-amber-700",inputClass:"border-amber-500 focus:ring-amber-500"},sm:{variant:"outline",buttonClass:"h-7 text-[11px] px-2",inputClass:"h-7 text-[11px] px-2 py-1"},lg:{variant:"outline",buttonClass:"h-10 text-sm px-3",inputClass:"h-10 text-sm px-3 py-2"}},s=e.computed(()=>{const a=d.styletype||"default";return i[a]??i.default}),p=e.computed(()=>o.cn("justify-between",s.value?.buttonClass,d.class)),f=e.computed(()=>o.cn("pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs",s.value?.inputClass)),m=a=>{r("update:modelValue",a),r("change",a)};return(a,l)=>(e.openBlock(),e.createBlock(e.unref(b.default),{"model-value":t.modelValue,by:"label",disabled:t.disabled,required:t.required,name:t.name,"onUpdate:modelValue":l[2]||(l[2]=u=>m(u))},{default:e.withCtx(()=>[e.createVNode(e.unref(x.default),{"as-child":""},{default:e.withCtx(()=>[e.createVNode(e.unref(_.default),{"as-child":""},{default:e.withCtx(()=>[e.createVNode(e.unref(v.default),{id:t.id,variant:s.value.variant,class:e.normalizeClass(p.value),disabled:t.disabled,onFocus:l[0]||(l[0]=u=>r("focus",u)),onBlur:l[1]||(l[1]=u=>r("blur",u))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.modelValue?.label??t.placeholder)+" ",1),e.createVNode(e.unref(n.ChevronsUpDown),{class:"ml-2 h-3.5 w-3.5 shrink-0 opacity-50"})]),_:1},8,["id","variant","class","disabled"])]),_:1})]),_:1}),e.createVNode(e.unref(C.default),null,{default:e.withCtx(()=>[e.createElementVNode("div",q,[e.createVNode(e.unref(h.default),{class:e.normalizeClass(f.value),placeholder:t.searchPlaceholder},null,8,["class","placeholder"]),e.createElementVNode("span",N,[e.createVNode(e.unref(n.Search),{class:"size-3.5 text-muted-foreground"})])]),e.createVNode(e.unref(y.default),null,{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.emptyText),1)]),_:1}),e.createVNode(e.unref(g.default),null,{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,u=>(e.openBlock(),e.createBlock(e.unref(V.default),{key:u.value,value:u},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(u.label)+" ",1),t.modelValue?.value===u.value?(e.openBlock(),e.createBlock(e.unref(n.Check),{key:0,class:e.normalizeClass(e.unref(o.cn)("ml-auto h-3.5 w-3.5"))},null,8,["class"])):e.createCommentVNode("",!0)]),_:2},1032,["value"]))),128))]),_:1})]),_:1})]),_:1},8,["model-value","disabled","required","name"]))}});exports.default=w;
|
|
2
2
|
//# sourceMappingURL=JSearchCombo.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchCombo.vue.cjs","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-
|
|
1
|
+
{"version":3,"file":"JSearchCombo.vue.cjs","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5',\n },\n error: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-destructive text-destructive',\n inputClass: 'border-destructive focus:ring-destructive',\n },\n success: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-green-500 text-green-700',\n inputClass: 'border-green-500 focus:ring-green-500',\n },\n warning: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-amber-500 text-amber-700',\n inputClass: 'border-amber-500 focus:ring-amber-500',\n },\n sm: { \n variant: 'outline',\n buttonClass: 'h-7 text-[11px] px-2',\n inputClass: 'h-7 text-[11px] px-2 py-1',\n },\n lg: { \n variant: 'outline',\n buttonClass: 'h-10 text-sm px-3',\n inputClass: 'h-10 text-sm px-3 py-2',\n },\n}\n\nconst preset = computed(() => {\n const styleKey = props.styletype || 'default'\n return STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\n})\n\nconst buttonClass = computed(() => {\n return cn('justify-between', preset.value?.buttonClass, props.class)\n})\n\nconst inputClass = computed(() => {\n return cn('pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs', preset.value?.inputClass)\n})\n\nconst handleChange = (value: ComboboxOption | undefined) => {\n emit('update:modelValue', value)\n emit('change', value)\n}\n</script>\n\n<template>\n <Combobox \n :model-value=\"modelValue\" \n by=\"label\" \n :disabled=\"disabled\"\n :required=\"required\"\n :name=\"name\"\n @update:model-value=\"(value) => handleChange(value as ComboboxOption | undefined)\"\n >\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button \n :id=\"id\"\n :variant=\"preset.variant\" \n :class=\"buttonClass\"\n :disabled=\"disabled\"\n @focus=\"emit('focus', $event as FocusEvent)\"\n @blur=\"emit('blur', $event as FocusEvent)\"\n >\n {{ modelValue?.label ?? placeholder }}\n <ChevronsUpDown class=\"ml-2 h-3.5 w-3.5 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :class=\"inputClass\" :placeholder=\"searchPlaceholder\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-2.5\">\n <Search class=\"size-3.5 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n {{ emptyText }}\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"option in options\"\n :key=\"option.value\"\n :value=\"option\"\n >\n {{ option.label }}\n\n <Check v-if=\"modelValue?.value === option.value\" :class=\"cn('ml-auto h-3.5 w-3.5')\" />\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","styleKey","buttonClass","cn","inputClass","handleChange","value","_createBlock","_unref","Combobox","_cache","_createVNode","ComboboxAnchor","ComboboxTrigger","Button","$event","_createTextVNode","_toDisplayString","ChevronsUpDown","ComboboxList","_createElementVNode","_hoisted_1","ComboboxInput","_hoisted_2","Search","ComboboxEmpty","ComboboxGroup","_createElementBlock","_Fragment","_renderList","option","ComboboxItem","Check"],"mappings":"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"}
|
|
@@ -32,21 +32,21 @@ const J = { class: "relative w-full max-w-sm items-center" }, K = { class: "abso
|
|
|
32
32
|
const x = e, u = C, h = {
|
|
33
33
|
default: {
|
|
34
34
|
variant: "outline",
|
|
35
|
-
buttonClass: "h-
|
|
35
|
+
buttonClass: "h-7 text-xs px-2.5"
|
|
36
36
|
},
|
|
37
37
|
error: {
|
|
38
38
|
variant: "outline",
|
|
39
|
-
buttonClass: "h-
|
|
39
|
+
buttonClass: "h-7 text-xs px-2.5 border-destructive text-destructive",
|
|
40
40
|
inputClass: "border-destructive focus:ring-destructive"
|
|
41
41
|
},
|
|
42
42
|
success: {
|
|
43
43
|
variant: "outline",
|
|
44
|
-
buttonClass: "h-
|
|
44
|
+
buttonClass: "h-7 text-xs px-2.5 border-green-500 text-green-700",
|
|
45
45
|
inputClass: "border-green-500 focus:ring-green-500"
|
|
46
46
|
},
|
|
47
47
|
warning: {
|
|
48
48
|
variant: "outline",
|
|
49
|
-
buttonClass: "h-
|
|
49
|
+
buttonClass: "h-7 text-xs px-2.5 border-amber-500 text-amber-700",
|
|
50
50
|
inputClass: "border-amber-500 focus:ring-amber-500"
|
|
51
51
|
},
|
|
52
52
|
sm: {
|
|
@@ -62,7 +62,7 @@ const J = { class: "relative w-full max-w-sm items-center" }, K = { class: "abso
|
|
|
62
62
|
}, i = d(() => {
|
|
63
63
|
const n = x.styletype || "default";
|
|
64
64
|
return h[n] ?? h.default;
|
|
65
|
-
}), y = d(() => b("justify-between", i.value?.buttonClass, x.class)), g = d(() => b("pl-8 pr-2 py-1
|
|
65
|
+
}), y = d(() => b("justify-between", i.value?.buttonClass, x.class)), g = d(() => b("pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs", i.value?.inputClass)), V = (n) => {
|
|
66
66
|
u("update:modelValue", n), u("change", n);
|
|
67
67
|
};
|
|
68
68
|
return (n, r) => (o(), m(t(q), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchCombo.vue.js","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-
|
|
1
|
+
{"version":3,"file":"JSearchCombo.vue.js","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5',\n },\n error: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-destructive text-destructive',\n inputClass: 'border-destructive focus:ring-destructive',\n },\n success: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-green-500 text-green-700',\n inputClass: 'border-green-500 focus:ring-green-500',\n },\n warning: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-amber-500 text-amber-700',\n inputClass: 'border-amber-500 focus:ring-amber-500',\n },\n sm: { \n variant: 'outline',\n buttonClass: 'h-7 text-[11px] px-2',\n inputClass: 'h-7 text-[11px] px-2 py-1',\n },\n lg: { \n variant: 'outline',\n buttonClass: 'h-10 text-sm px-3',\n inputClass: 'h-10 text-sm px-3 py-2',\n },\n}\n\nconst preset = computed(() => {\n const styleKey = props.styletype || 'default'\n return STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\n})\n\nconst buttonClass = computed(() => {\n return cn('justify-between', preset.value?.buttonClass, props.class)\n})\n\nconst inputClass = computed(() => {\n return cn('pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs', preset.value?.inputClass)\n})\n\nconst handleChange = (value: ComboboxOption | undefined) => {\n emit('update:modelValue', value)\n emit('change', value)\n}\n</script>\n\n<template>\n <Combobox \n :model-value=\"modelValue\" \n by=\"label\" \n :disabled=\"disabled\"\n :required=\"required\"\n :name=\"name\"\n @update:model-value=\"(value) => handleChange(value as ComboboxOption | undefined)\"\n >\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button \n :id=\"id\"\n :variant=\"preset.variant\" \n :class=\"buttonClass\"\n :disabled=\"disabled\"\n @focus=\"emit('focus', $event as FocusEvent)\"\n @blur=\"emit('blur', $event as FocusEvent)\"\n >\n {{ modelValue?.label ?? placeholder }}\n <ChevronsUpDown class=\"ml-2 h-3.5 w-3.5 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :class=\"inputClass\" :placeholder=\"searchPlaceholder\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-2.5\">\n <Search class=\"size-3.5 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n {{ emptyText }}\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"option in options\"\n :key=\"option.value\"\n :value=\"option\"\n >\n {{ option.label }}\n\n <Check v-if=\"modelValue?.value === option.value\" :class=\"cn('ml-auto h-3.5 w-3.5')\" />\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","styleKey","buttonClass","cn","inputClass","handleChange","value","_createBlock","_unref","Combobox","_cache","_createVNode","ComboboxAnchor","ComboboxTrigger","Button","$event","_createTextVNode","_toDisplayString","ChevronsUpDown","ComboboxList","_createElementVNode","_hoisted_1","ComboboxInput","_hoisted_2","Search","ComboboxEmpty","ComboboxGroup","_createElementBlock","_Fragment","_renderList","option","ComboboxItem","Check"],"mappings":"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"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
for (const [t_key, t_val] of t_opts)
|
|
4
4
|
t_merged[t_key] = t_val;
|
|
5
5
|
return t_merged;
|
|
6
|
-
};,u=t(e.default,[["__scopeId","data-v-
|
|
6
|
+
};,u=t(e.default,[["__scopeId","data-v-9c1f0de8"]]);exports.default=u;
|
|
7
7
|
//# sourceMappingURL=JSplitter.vue.cjs.map
|
|
@@ -6,8 +6,8 @@ const o = (o_comp, o_opts) => {
|
|
|
6
6
|
o_merged[o_key] = o_val;
|
|
7
7
|
return o_merged;
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const f = /* @__PURE__ */ o(t, [["__scopeId", "data-v-9c1f0de8"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
f as default
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=JSplitter.vue.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),s=require("../shadcn/resizable/ResizableHandle.vue.cjs"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),s=require("../../lib/utils.cjs"),r=require("../shadcn/resizable/ResizableHandle.vue.cjs"),u=require("../shadcn/resizable/ResizablePanelGroup.vue.cjs"),l=require("reka-ui"),o=e.defineComponent({__name:"JSplitter",props:{direction:{default:"horizontal"},defaultSize:{default:40},minSize:{default:20},maxSize:{},secondMinSize:{},secondMaxSize:{},withHandle:{type:Boolean,default:!1},gap:{default:2},class:{}},setup(t){const i=t,n=e.computed(()=>100-i.defaultSize);return(a,d)=>(e.openBlock(),e.createBlock(e.unref(u.default),{direction:t.direction,class:e.normalizeClass(e.unref(s.cn)("jsplitter-group min-h-0 min-w-0",a.$props.class))},{default:e.withCtx(()=>[e.createVNode(e.unref(l.SplitterPanel),{"default-size":t.defaultSize,"min-size":t.minSize,"max-size":t.maxSize,class:e.normalizeClass(t.gap>0?t.direction==="horizontal"?"pr-[calc(var(--gap)/2)]":"pb-[calc(var(--gap)/2)]":""),style:e.normalizeStyle(t.gap>0?{"--gap":`${t.gap}px`}:{})},{default:e.withCtx(()=>[e.renderSlot(a.$slots,"first",{},void 0,!0),e.renderSlot(a.$slots,"left",{},void 0,!0),e.renderSlot(a.$slots,"top",{},void 0,!0)]),_:3},8,["default-size","min-size","max-size","class","style"]),e.createVNode(e.unref(r.default),{"with-handle":t.withHandle,class:"jsplitter-handle"},null,8,["with-handle"]),e.createVNode(e.unref(l.SplitterPanel),{"default-size":n.value,"min-size":t.secondMinSize,"max-size":t.secondMaxSize,class:e.normalizeClass(t.gap>0?t.direction==="horizontal"?"pl-[calc(var(--gap)/2)]":"pt-[calc(var(--gap)/2)]":""),style:e.normalizeStyle(t.gap>0?{"--gap":`${t.gap}px`}:{})},{default:e.withCtx(()=>[e.renderSlot(a.$slots,"second",{},void 0,!0),e.renderSlot(a.$slots,"right",{},void 0,!0),e.renderSlot(a.$slots,"bottom",{},void 0,!0)]),_:3},8,["default-size","min-size","max-size","class","style"])]),_:3},8,["direction","class"]))}});exports.default=o;
|
|
2
2
|
//# sourceMappingURL=JSplitter.vue2.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSplitter.vue2.cjs","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap:
|
|
1
|
+
{"version":3,"file":"JSplitter.vue2.cjs","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '@/lib/utils'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap: 2,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"cn('jsplitter-group min-h-0 min-w-0', $props.class)\">\n <!-- 첫 번째 패널 (좌측/상단) -->\n <ResizablePanel \n :default-size=\"defaultSize\" \n :min-size=\"minSize\" \n :max-size=\"maxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pr-[calc(var(--gap)/2)]' : 'pb-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"first\" />\n <!-- direction=\"horizontal\"일 때 left, vertical일 때 top으로도 사용 가능 -->\n <slot name=\"left\" />\n <slot name=\"top\" />\n </ResizablePanel>\n\n <!-- 크기 조정 핸들 -->\n <ResizableHandle :with-handle=\"withHandle\" class=\"jsplitter-handle\" />\n\n <!-- 두 번째 패널 (우측/하단) -->\n <ResizablePanel\n :default-size=\"secondDefaultSize\"\n :min-size=\"secondMinSize\"\n :max-size=\"secondMaxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pl-[calc(var(--gap)/2)]' : 'pt-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"second\" />\n <!-- direction=\"horizontal\"일 때 right, vertical일 때 bottom으로도 사용 가능 -->\n <slot name=\"right\" />\n <slot name=\"bottom\" />\n </ResizablePanel>\n </ResizablePanelGroup>\n</template>\n\n<style scoped>\n/* 패널 콘텐츠가 최소 크기 이하로 줄 때 overflow 깨짐 방지 */\n:deep(.jsplitter-group [data-panel]) {\n min-width: 0;\n min-height: 0;\n}\n\n/* splitter: 시각선 1px + 드래그 히트영역 8px */\n:deep(.jsplitter-handle[data-orientation=\"horizontal\"]) {\n width: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle[data-orientation=\"vertical\"]) {\n height: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle::after) {\n background: hsl(var(--border) / 0.75) !important;\n}\n\n:deep(.jsplitter-handle:hover) {\n background: hsl(var(--primary) / 0.05) !important;\n}\n\n:deep(.jsplitter-handle:hover::after),\n:deep(.jsplitter-handle:active::after),\n:deep(.jsplitter-handle[data-state=\"drag\"]::after) {\n background: hsl(var(--primary) / 0.85) !important;\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_normalizeClass","cn","$props","_createVNode","ResizablePanel","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":"kiBAWA,MAAMA,EAAQC,EA+BRC,EAAoBC,EAAAA,SAAS,IAAM,IAAMH,EAAM,WAAW,8BAI9DI,EAAAA,YA+BsBC,EAAAA,MAAAC,EAAAA,OAAA,EAAA,CA/BA,UAAWL,EAAA,UAAY,MAAKM,EAAAA,eAAEF,EAAAA,MAAAG,EAAAA,EAAA,EAAE,kCAAoCC,EAAAA,OAAO,KAAK,CAAA,CAAA,qBAEpG,IAWiB,CAXjBC,cAWiBL,EAAAA,MAAAM,EAAAA,aAAA,EAAA,CAVd,eAAcV,EAAA,YACd,WAAUA,EAAA,QACV,WAAUA,EAAA,QACV,MAAKM,EAAAA,eAAEN,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKW,EAAAA,eAAEX,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAqB,CAArBY,EAAAA,WAAqBC,EAAA,OAAA,QAAA,CAAA,EAAA,OAAA,EAAA,EAErBD,EAAAA,WAAoBC,EAAA,OAAA,OAAA,CAAA,EAAA,OAAA,EAAA,EACpBD,EAAAA,WAAmBC,EAAA,OAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,kEAIrBJ,cAAsEL,EAAAA,MAAAU,EAAAA,OAAA,EAAA,CAApD,cAAad,EAAA,WAAY,MAAM,kBAAA,0BAGjDS,cAWiBL,EAAAA,MAAAM,EAAAA,aAAA,EAAA,CAVd,eAAcT,EAAA,MACd,WAAUD,EAAA,cACV,WAAUA,EAAA,cACV,MAAKM,EAAAA,eAAEN,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKW,EAAAA,eAAEX,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAsB,CAAtBY,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,EAEtBD,EAAAA,WAAqBC,EAAA,OAAA,QAAA,CAAA,EAAA,OAAA,EAAA,EACrBD,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import S from "
|
|
3
|
-
import g from "../shadcn/resizable/
|
|
1
|
+
import { defineComponent as m, computed as u, createBlock as f, openBlock as z, unref as t, normalizeClass as l, withCtx as s, createVNode as n, normalizeStyle as o, renderSlot as i } from "vue";
|
|
2
|
+
import { cn as S } from "../../lib/utils.js";
|
|
3
|
+
import g from "../shadcn/resizable/ResizableHandle.vue.js";
|
|
4
|
+
import h from "../shadcn/resizable/ResizablePanelGroup.vue.js";
|
|
4
5
|
import { SplitterPanel as d } from "reka-ui";
|
|
5
|
-
const
|
|
6
|
+
const M = /* @__PURE__ */ m({
|
|
6
7
|
__name: "JSplitter",
|
|
7
8
|
props: {
|
|
8
9
|
direction: { default: "horizontal" },
|
|
@@ -12,14 +13,14 @@ const w = /* @__PURE__ */ u({
|
|
|
12
13
|
secondMinSize: {},
|
|
13
14
|
secondMaxSize: {},
|
|
14
15
|
withHandle: { type: Boolean, default: !1 },
|
|
15
|
-
gap: { default:
|
|
16
|
+
gap: { default: 2 },
|
|
16
17
|
class: {}
|
|
17
18
|
},
|
|
18
19
|
setup(e) {
|
|
19
|
-
const c = e, r =
|
|
20
|
-
return (a,
|
|
20
|
+
const c = e, r = u(() => 100 - c.defaultSize);
|
|
21
|
+
return (a, p) => (z(), f(t(h), {
|
|
21
22
|
direction: e.direction,
|
|
22
|
-
class: l(
|
|
23
|
+
class: l(t(S)("jsplitter-group min-h-0 min-w-0", a.$props.class))
|
|
23
24
|
}, {
|
|
24
25
|
default: s(() => [
|
|
25
26
|
n(t(d), {
|
|
@@ -36,7 +37,10 @@ const w = /* @__PURE__ */ u({
|
|
|
36
37
|
]),
|
|
37
38
|
_: 3
|
|
38
39
|
}, 8, ["default-size", "min-size", "max-size", "class", "style"]),
|
|
39
|
-
n(t(
|
|
40
|
+
n(t(g), {
|
|
41
|
+
"with-handle": e.withHandle,
|
|
42
|
+
class: "jsplitter-handle"
|
|
43
|
+
}, null, 8, ["with-handle"]),
|
|
40
44
|
n(t(d), {
|
|
41
45
|
"default-size": r.value,
|
|
42
46
|
"min-size": e.secondMinSize,
|
|
@@ -57,6 +61,6 @@ const w = /* @__PURE__ */ u({
|
|
|
57
61
|
}
|
|
58
62
|
});
|
|
59
63
|
export {
|
|
60
|
-
|
|
64
|
+
M as default
|
|
61
65
|
};
|
|
62
66
|
//# sourceMappingURL=JSplitter.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSplitter.vue2.js","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap:
|
|
1
|
+
{"version":3,"file":"JSplitter.vue2.js","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '@/lib/utils'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap: 2,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"cn('jsplitter-group min-h-0 min-w-0', $props.class)\">\n <!-- 첫 번째 패널 (좌측/상단) -->\n <ResizablePanel \n :default-size=\"defaultSize\" \n :min-size=\"minSize\" \n :max-size=\"maxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pr-[calc(var(--gap)/2)]' : 'pb-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"first\" />\n <!-- direction=\"horizontal\"일 때 left, vertical일 때 top으로도 사용 가능 -->\n <slot name=\"left\" />\n <slot name=\"top\" />\n </ResizablePanel>\n\n <!-- 크기 조정 핸들 -->\n <ResizableHandle :with-handle=\"withHandle\" class=\"jsplitter-handle\" />\n\n <!-- 두 번째 패널 (우측/하단) -->\n <ResizablePanel\n :default-size=\"secondDefaultSize\"\n :min-size=\"secondMinSize\"\n :max-size=\"secondMaxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pl-[calc(var(--gap)/2)]' : 'pt-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"second\" />\n <!-- direction=\"horizontal\"일 때 right, vertical일 때 bottom으로도 사용 가능 -->\n <slot name=\"right\" />\n <slot name=\"bottom\" />\n </ResizablePanel>\n </ResizablePanelGroup>\n</template>\n\n<style scoped>\n/* 패널 콘텐츠가 최소 크기 이하로 줄 때 overflow 깨짐 방지 */\n:deep(.jsplitter-group [data-panel]) {\n min-width: 0;\n min-height: 0;\n}\n\n/* splitter: 시각선 1px + 드래그 히트영역 8px */\n:deep(.jsplitter-handle[data-orientation=\"horizontal\"]) {\n width: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle[data-orientation=\"vertical\"]) {\n height: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle::after) {\n background: hsl(var(--border) / 0.75) !important;\n}\n\n:deep(.jsplitter-handle:hover) {\n background: hsl(var(--primary) / 0.05) !important;\n}\n\n:deep(.jsplitter-handle:hover::after),\n:deep(.jsplitter-handle:active::after),\n:deep(.jsplitter-handle[data-state=\"drag\"]::after) {\n background: hsl(var(--primary) / 0.85) !important;\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_normalizeClass","cn","$props","_createVNode","ResizablePanel","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":";;;;;;;;;;;;;;;;;;;AAWA,UAAMA,IAAQC,GA+BRC,IAAoBC,EAAS,MAAM,MAAMH,EAAM,WAAW;2BAI9DI,EA+BsBC,EAAAC,CAAA,GAAA;AAAA,MA/BA,WAAWL,EAAA;AAAA,MAAY,OAAKM,EAAEF,EAAAG,CAAA,EAAE,mCAAoCC,EAAAA,OAAO,KAAK,CAAA;AAAA,IAAA;iBAEpG,MAWiB;AAAA,QAXjBC,EAWiBL,EAAAM,CAAA,GAAA;AAAA,UAVd,gBAAcV,EAAA;AAAA,UACd,YAAUA,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKM,EAAEN,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKW,EAAEX,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAqB;AAAA,YAArBY,EAAqBC,EAAA,QAAA,SAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YAErBD,EAAoBC,EAAA,QAAA,QAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YACpBD,EAAmBC,EAAA,QAAA,OAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;QAIrBJ,EAAsEL,EAAAU,CAAA,GAAA;AAAA,UAApD,eAAad,EAAA;AAAA,UAAY,OAAM;AAAA,QAAA;QAGjDS,EAWiBL,EAAAM,CAAA,GAAA;AAAA,UAVd,gBAAcT,EAAA;AAAA,UACd,YAAUD,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKM,EAAEN,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKW,EAAEX,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAsB;AAAA,YAAtBY,EAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YAEtBD,EAAqBC,EAAA,QAAA,SAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YACrBD,EAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;;;;;;"}
|
|
@@ -6,8 +6,8 @@ const t = (t_comp, t_opts) => {
|
|
|
6
6
|
t_merged[t_key] = t_val;
|
|
7
7
|
return t_merged;
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const p = /* @__PURE__ */ t(o, [["__scopeId", "data-v-0e5b57c9"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
p as default
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=JTabs.vue.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue");require("../shadcn/index.cjs");const h=require("lucide-vue-next"),i=require("../../lib/utils.cjs"),x=require("../atoms/JIcon.vue.cjs"),y=require("../shadcn/Tabs.vue.cjs"),T=require("../shadcn/TabsList.vue.cjs"),b=require("../shadcn/TabsTrigger.vue.cjs"),B=require("../shadcn/TabsContent.vue.cjs"),S={class:"flex-1 truncate"},E=["aria-label","onClick"],P={class:"flex-1 w-full overflow-auto"},q={key:1,class:"p-4"},V={class:"text-muted-foreground"},z=e.defineComponent({__name:"JTabs",props:{tabs:{},activeTabId:{},class:{},listClass:{},styletype:{default:"default"}},emits:["tabChange","tabClose","update:activeTabId"],setup(f,{emit:v}){const n=f,r=v,u=e.computed(()=>Array.isArray(n.tabs)?n.tabs:[]),a=e.ref(n.activeTabId||(u.value.length>0?u.value[0]?.id:"")||"");let o=!1;e.watch(()=>n.activeTabId,t=>{t!==void 0&&t!==a.value&&(a.value=t)},{immediate:!0}),e.watch(u,t=>{!n.activeTabId&&t.length>0&&!t.find(s=>s.id===a.value)&&t[0]&&(a.value=t[0].id)});const _=t=>{if(o)return;const s=String(t);s!==a.value&&(o=!0,a.value=s,r("update:activeTabId",s),r("tabChange",s),e.nextTick(()=>{o=!1}))},m=t=>{o||t===a.value||(o=!0,a.value=t,r("update:activeTabId",t),r("tabChange",t),e.nextTick(()=>{o=!1}))},C=(t,s)=>{t.stopPropagation(),r("tabClose",s)},g=e.computed(()=>i.cn("flex flex-col w-full h-full",n.class)),d={default:{tabPaddingClass:"px-2 py-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue");require("../shadcn/index.cjs");const h=require("lucide-vue-next"),i=require("../../lib/utils.cjs"),x=require("../atoms/JIcon.vue.cjs"),y=require("../shadcn/Tabs.vue.cjs"),T=require("../shadcn/TabsList.vue.cjs"),b=require("../shadcn/TabsTrigger.vue.cjs"),B=require("../shadcn/TabsContent.vue.cjs"),S={class:"flex-1 truncate"},E=["aria-label","onClick"],P={class:"flex-1 w-full overflow-auto"},q={key:1,class:"p-4"},V={class:"text-muted-foreground"},z=e.defineComponent({__name:"JTabs",props:{tabs:{},activeTabId:{},class:{},listClass:{},styletype:{default:"default"}},emits:["tabChange","tabClose","update:activeTabId"],setup(f,{emit:v}){const n=f,r=v,u=e.computed(()=>Array.isArray(n.tabs)?n.tabs:[]),a=e.ref(n.activeTabId||(u.value.length>0?u.value[0]?.id:"")||"");let o=!1;e.watch(()=>n.activeTabId,t=>{t!==void 0&&t!==a.value&&(a.value=t)},{immediate:!0}),e.watch(u,t=>{!n.activeTabId&&t.length>0&&!t.find(s=>s.id===a.value)&&t[0]&&(a.value=t[0].id)});const _=t=>{if(o)return;const s=String(t);s!==a.value&&(o=!0,a.value=s,r("update:activeTabId",s),r("tabChange",s),e.nextTick(()=>{o=!1}))},m=t=>{o||t===a.value||(o=!0,a.value=t,r("update:activeTabId",t),r("tabChange",t),e.nextTick(()=>{o=!1}))},C=(t,s)=>{t.stopPropagation(),r("tabClose",s)},g=e.computed(()=>i.cn("flex flex-col w-full h-full",n.class)),d={default:{tabPaddingClass:"px-2 py-1",tabTextSizeClass:"text-xs",listPaddingClass:"px-1 py-1"},minimal:{tabPaddingClass:"px-1.5 py-1",tabTextSizeClass:"text-xs",listPaddingClass:"px-1 py-1"}},c=e.computed(()=>d[n.styletype]??d.default),k=e.computed(()=>i.cn("w-full justify-start",c.value.listPaddingClass,n.listClass));return(t,s)=>(e.openBlock(),e.createBlock(e.unref(y.default),{"model-value":a.value,"onUpdate:modelValue":_,orientation:"horizontal",class:e.normalizeClass(g.value)},{default:e.withCtx(()=>[e.createVNode(e.unref(T.default),{class:e.normalizeClass(k.value)},{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(u.value,l=>(e.openBlock(),e.createBlock(e.unref(b.default),{key:l.id,value:l.id,onClick:p=>m(l.id),class:e.normalizeClass(e.unref(i.cn)("!flex !items-center !gap-2",c.value.tabPaddingClass,c.value.tabTextSizeClass))},{default:e.withCtx(()=>[l.icon?(e.openBlock(),e.createBlock(x.default,{key:0,name:l.icon,size:"sm",class:"flex-shrink-0"},null,8,["name"])):e.createCommentVNode("",!0),e.createElementVNode("span",S,e.toDisplayString(l.label),1),l.closable?(e.openBlock(),e.createElementBlock("button",{key:1,type:"button",class:"flex-shrink-0 h-3.5 w-3.5 rounded-sm hover:bg-destructive/10 hover:text-destructive transition-colors focus:outline-none focus:ring-2 focus:ring-ring flex items-center justify-center","aria-label":`${l.label} 탭 닫기`,onClick:p=>C(p,l.id)},[e.createVNode(e.unref(h.X),{class:"h-2.5 w-2.5"})],8,E)):e.createCommentVNode("",!0)]),_:2},1032,["value","onClick","class"]))),128))]),_:1},8,["class"]),e.createElementVNode("div",P,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(u.value,l=>(e.openBlock(),e.createBlock(e.unref(B.default),{key:`content-${l.id}`,value:l.id,class:"h-full mt-0 data-[state=active]:flex data-[state=active]:flex-col"},{default:e.withCtx(()=>[e.renderSlot(t.$slots,`content-${l.id}`,{tab:l},()=>[l.component?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(l.component),e.mergeProps({key:0,ref_for:!0},l.props||{}),null,16)):(e.openBlock(),e.createElementBlock("div",q,[e.createElementVNode("p",V,e.toDisplayString(l.label)+" 콘텐츠",1)]))],!0)]),_:2},1032,["value"]))),128))])]),_:3},8,["model-value","class"]))}});exports.default=z;
|
|
2
2
|
//# sourceMappingURL=JTabs.vue2.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JTabs.vue2.cjs","sources":["../../../../src/components/molecules/JTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick } from 'vue'\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/shadcn'\nimport type { JTabsProps, JTabsEmits } from '@/types/dynamic-tabs.types'\nimport { X } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport JIcon from '@/components/atoms/JIcon.vue'\n\n/**\n * JTabs - 기본 탭 UI 컴포넌트 (molecules)\n * Basic Tabs UI Component\n * \n * @description\n * 정적인 탭 목록을 렌더링하는 기본 탭 컴포넌트입니다.\n * 닫기 버튼, 아이콘 등을 지원합니다.\n * \n * @example\n * ```vue\n * <JTabs \n * :tabs=\"tabs\"\n * :active-tab-id=\"activeId\"\n * @tab-change=\"handleChange\"\n * @tab-close=\"handleClose\"\n * />\n * ```\n */\n\ntype StyleType = 'default' | 'minimal'\n\nconst props = withDefaults(defineProps<JTabsProps>(), {\n styletype: 'default',\n})\n\nconst emit = defineEmits<JTabsEmits>()\n\n/**\n * 안전한 tabs 배열 (undefined/null 체크)\n * Safe tabs array (undefined/null check)\n */\nconst safeTabs = computed(() => {\n return Array.isArray(props.tabs) ? props.tabs : []\n})\n\n/**\n * 현재 활성화된 탭 ID (내부 상태)\n * Current active tab ID (internal state)\n */\nconst internalActiveId = ref<string>(\n props.activeTabId || (safeTabs.value.length > 0 ? safeTabs.value[0]?.id : '') || ''\n)\n\n/**\n * 이벤트 처리 중 플래그 (중복 이벤트 방지)\n * Flag to prevent duplicate events\n */\nlet isHandlingEvent = false\n\n/**\n * props.activeTabId가 변경되면 내부 상태 동기화\n * Sync internal state when props.activeTabId changes\n */\nwatch(() => props.activeTabId, (newValue) => {\n if (newValue !== undefined && newValue !== internalActiveId.value) {\n internalActiveId.value = newValue\n }\n}, { immediate: true })\n\n/**\n * props.tabs가 변경되고 activeTabId가 없으면 첫 번째 탭 활성화\n * Activate first tab when tabs change and no activeTabId\n */\nwatch(safeTabs, (newTabs) => {\n if (!props.activeTabId && newTabs.length > 0 && !newTabs.find(t => t.id === internalActiveId.value) && newTabs[0]) {\n internalActiveId.value = newTabs[0].id\n }\n})\n\n/**\n * 탭 값 변경 핸들러 (reka-ui TabsRoot에서 직접 호출됨)\n * Tab value change handler (called directly from reka-ui TabsRoot)\n */\nconst handleTabValueChange = (value: string | number) => {\n if (isHandlingEvent) return\n \n const stringValue = String(value)\n if (stringValue !== internalActiveId.value) {\n isHandlingEvent = true\n internalActiveId.value = stringValue\n emit('update:activeTabId', stringValue)\n emit('tabChange', stringValue)\n // 다음 tick에서 플래그 리셋\n nextTick(() => {\n isHandlingEvent = false\n })\n }\n}\n\n/**\n * 탭 클릭 핸들러 (백업 방안 - reka-ui 이벤트가 작동하지 않을 경우)\n * Tab click handler (backup - in case reka-ui events don't work)\n */\nconst handleTabClick = (tabId: string) => {\n // reka-ui 이벤트가 작동하지 않을 경우 직접 처리\n // handleTabValueChange가 이미 처리했으면 중복 방지\n if (isHandlingEvent || tabId === internalActiveId.value) return\n \n isHandlingEvent = true\n internalActiveId.value = tabId\n emit('update:activeTabId', tabId)\n emit('tabChange', tabId)\n // 다음 tick에서 플래그 리셋\n nextTick(() => {\n isHandlingEvent = false\n })\n}\n\n/**\n * 탭 닫기 핸들러\n * Tab close handler\n */\nconst handleCloseTab = (e: Event, tabId: string) => {\n e.stopPropagation() // 탭 클릭 이벤트 전파 방지\n emit('tabClose', tabId)\n}\n\n/**\n * 루트 클래스\n * Root classes\n */\nconst rootClasses = computed(() => {\n return cn('flex flex-col w-full h-full', props.class)\n})\n\n/**\n * 스타일 프리셋\n */\nconst STYLE_PRESETS: Record<StyleType, {\n tabPaddingClass: string\n tabTextSizeClass: string\n listPaddingClass: string\n}> = {\n default: {\n tabPaddingClass: 'px-2 py-0.5',\n tabTextSizeClass: 'text-xs',\n listPaddingClass: 'px-1.5 py-0.5',\n },\n minimal: {\n tabPaddingClass: 'px-1.5 py-0.5',\n tabTextSizeClass: 'text-xs',\n listPaddingClass: 'px-1.5 py-0.5',\n },\n}\n\nconst preset = computed(() => {\n return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\n/**\n * 탭 리스트 클래스\n * Tabs list classes\n */\nconst listClasses = computed(() => {\n return cn('w-full justify-start', preset.value.listPaddingClass, props.listClass)\n})\n</script>\n\n<template>\n <Tabs\n :model-value=\"internalActiveId\"\n @update:model-value=\"handleTabValueChange\"\n orientation=\"horizontal\"\n :class=\"rootClasses\"\n >\n <!-- 탭 헤더 영역 / Tab Headers -->\n <TabsList :class=\"listClasses\">\n <TabsTrigger\n v-for=\"tab in safeTabs\"\n :key=\"tab.id\"\n :value=\"tab.id\"\n @click=\"handleTabClick(tab.id)\"\n :class=\"cn('!flex !items-center !gap-2', preset.tabPaddingClass, preset.tabTextSizeClass)\"\n >\n <!-- 탭 아이콘 (있을 경우) / Tab Icon -->\n <JIcon \n v-if=\"tab.icon\" \n :name=\"tab.icon\" \n size=\"sm\"\n class=\"flex-shrink-0\"\n />\n \n <!-- 탭 레이블 / Tab Label -->\n <span class=\"flex-1 truncate\">{{ tab.label }}</span>\n \n <!-- 닫기 버튼 / Close Button (항상 표시) -->\n <button\n v-if=\"tab.closable\"\n type=\"button\"\n class=\"flex-shrink-0 h-3.5 w-3.5 rounded-sm hover:bg-destructive/10 hover:text-destructive transition-colors focus:outline-none focus:ring-2 focus:ring-ring flex items-center justify-center\"\n :aria-label=\"`${tab.label} 탭 닫기`\"\n @click=\"(e) => handleCloseTab(e, tab.id)\"\n >\n <X class=\"h-2.5 w-2.5\" />\n </button>\n </TabsTrigger>\n </TabsList>\n\n <!-- 탭 콘텐츠 영역 / Tab Contents -->\n <div class=\"flex-1 w-full overflow-auto\">\n <TabsContent\n v-for=\"tab in safeTabs\"\n :key=\"`content-${tab.id}`\"\n :value=\"tab.id\"\n class=\"h-full mt-0 data-[state=active]:flex data-[state=active]:flex-col\"\n >\n <!-- 슬롯 우선 / Slot First -->\n <slot :name=\"`content-${tab.id}`\" :tab=\"tab\">\n <!-- 동적 컴포넌트 렌더링 / Dynamic Component Rendering -->\n <component\n v-if=\"tab.component\"\n :is=\"tab.component\"\n v-bind=\"tab.props || {}\"\n />\n \n <!-- 기본 콘텐츠 / Default Content -->\n <div v-else class=\"p-4\">\n <p class=\"text-muted-foreground\">{{ tab.label }} 콘텐츠</p>\n </div>\n </slot>\n </TabsContent>\n </div>\n </Tabs>\n</template>\n\n<style scoped>\n/**\n * 탭 리스트 스타일 - 하단 보더 제거\n * Tab list styles without bottom border\n */\n:deep([role=\"tablist\"]:not(.ag-side-buttons)) {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\n background: hsl(var(--background));\n padding: 0.125rem 0.375rem 0;\n gap: 0.125rem;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar) {\n height: 6px;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-track) {\n background: transparent;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb:hover) {\n background-color: rgba(0, 0, 0, 0.3);\n}\n\n/**\n * 다크모드에서 스크롤바 스타일\n * Scrollbar styles in dark mode\n */\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb) {\n background-color: rgba(255, 255, 255, 0.2);\n}\n\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb:hover) {\n background-color: rgba(255, 255, 255, 0.3);\n}\n\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)) {\n scrollbar-color: rgba(255, 255, 255, 0.2) transparent;\n}\n\n/**\n * 탭 버튼 스타일 - 명확한 구분\n * Tab button styles - clear distinction\n */\n:deep([role=\"tab\"]) {\n position: relative;\n padding: 0.25rem 0.625rem;\n min-height: 1.75rem;\n border-radius: 0.375rem 0.375rem 0 0;\n transition: all 0.2s ease;\n border: 1px solid transparent;\n border-bottom: none;\n}\n\n/**\n * Minimal 스타일 탭 버튼 - JSidebarAdvanced와 높이 맞춤\n */\n:deep([role=\"tablist\"][class*=\"p-0.5\"] [role=\"tab\"]) {\n padding: 0.25rem 0.5rem;\n}\n\n/**\n * 비활성 탭 - 명확하게 구분\n * Inactive tabs - clear distinction\n */\n:deep([role=\"tab\"][data-state=\"inactive\"]) {\n background: hsl(var(--muted) / 0.2);\n color: hsl(var(--muted-foreground));\n border-top: 1px solid hsl(var(--border) / 0.4);\n border-left: 1px solid hsl(var(--border) / 0.4);\n border-right: 1px solid hsl(var(--border) / 0.4);\n}\n\n:deep([role=\"tab\"][data-state=\"inactive\"]:hover) {\n background: hsl(var(--muted) / 0.4);\n color: hsl(var(--foreground));\n}\n\n/**\n * 다크모드에서 비활성 탭 - 다크 배경색 사용\n * Inactive tabs in dark mode - use dark background\n */\n.dark :deep([role=\"tab\"][data-state=\"inactive\"]) {\n background: hsl(var(--secondary));\n color: hsl(var(--secondary-foreground));\n border-top: 1px solid hsl(var(--border) / 0.5);\n border-left: 1px solid hsl(var(--border) / 0.5);\n border-right: 1px solid hsl(var(--border) / 0.5);\n}\n\n.dark :deep([role=\"tab\"][data-state=\"inactive\"]:hover) {\n background: hsl(var(--muted));\n color: hsl(var(--muted-foreground));\n}\n\n/**\n * 활성 탭 - 강조된 스타일\n * Active tab - emphasized style\n */\n:deep([role=\"tab\"][data-state=\"active\"]) {\n background: hsl(var(--background));\n color: hsl(var(--foreground));\n font-weight: 500;\n border-top: 2px solid hsl(var(--primary));\n border-left: 1px solid hsl(var(--border));\n border-right: 1px solid hsl(var(--border));\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n z-index: 1;\n}\n\n/**\n * 다크모드에서 활성 탭 - 배경색 명확히 구분\n * Active tab in dark mode - clear background distinction\n */\n.dark :deep([role=\"tab\"][data-state=\"active\"]) {\n background: hsl(var(--card));\n color: hsl(var(--card-foreground));\n border-top: 2px solid hsl(var(--primary));\n border-left: 1px solid hsl(var(--border));\n border-right: 1px solid hsl(var(--border));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n</style>\n"],"names":["props","__props","emit","__emit","safeTabs","computed","internalActiveId","ref","isHandlingEvent","watch","newValue","newTabs","t","handleTabValueChange","value","stringValue","nextTick","handleTabClick","tabId","handleCloseTab","e","rootClasses","cn","STYLE_PRESETS","preset","listClasses","_createBlock","_unref","Tabs","_createVNode","TabsList","_createElementBlock","_Fragment","_renderList","tab","TabsTrigger","$event","_normalizeClass","JIcon","_createElementVNode","_hoisted_1","_toDisplayString","X","_hoisted_3","TabsContent","_renderSlot","_ctx","_openBlock","_resolveDynamicComponent","_mergeProps","_hoisted_4","_hoisted_5"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JTabs.vue2.cjs","sources":["../../../../src/components/molecules/JTabs.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick } from 'vue'\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/shadcn'\nimport type { JTabsProps, JTabsEmits } from '@/types/dynamic-tabs.types'\nimport { X } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport JIcon from '@/components/atoms/JIcon.vue'\n\n/**\n * JTabs - 기본 탭 UI 컴포넌트 (molecules)\n * Basic Tabs UI Component\n * \n * @description\n * 정적인 탭 목록을 렌더링하는 기본 탭 컴포넌트입니다.\n * 닫기 버튼, 아이콘 등을 지원합니다.\n * \n * @example\n * ```vue\n * <JTabs \n * :tabs=\"tabs\"\n * :active-tab-id=\"activeId\"\n * @tab-change=\"handleChange\"\n * @tab-close=\"handleClose\"\n * />\n * ```\n */\n\ntype StyleType = 'default' | 'minimal'\n\nconst props = withDefaults(defineProps<JTabsProps>(), {\n styletype: 'default',\n})\n\nconst emit = defineEmits<JTabsEmits>()\n\n/**\n * 안전한 tabs 배열 (undefined/null 체크)\n * Safe tabs array (undefined/null check)\n */\nconst safeTabs = computed(() => {\n return Array.isArray(props.tabs) ? props.tabs : []\n})\n\n/**\n * 현재 활성화된 탭 ID (내부 상태)\n * Current active tab ID (internal state)\n */\nconst internalActiveId = ref<string>(\n props.activeTabId || (safeTabs.value.length > 0 ? safeTabs.value[0]?.id : '') || ''\n)\n\n/**\n * 이벤트 처리 중 플래그 (중복 이벤트 방지)\n * Flag to prevent duplicate events\n */\nlet isHandlingEvent = false\n\n/**\n * props.activeTabId가 변경되면 내부 상태 동기화\n * Sync internal state when props.activeTabId changes\n */\nwatch(() => props.activeTabId, (newValue) => {\n if (newValue !== undefined && newValue !== internalActiveId.value) {\n internalActiveId.value = newValue\n }\n}, { immediate: true })\n\n/**\n * props.tabs가 변경되고 activeTabId가 없으면 첫 번째 탭 활성화\n * Activate first tab when tabs change and no activeTabId\n */\nwatch(safeTabs, (newTabs) => {\n if (!props.activeTabId && newTabs.length > 0 && !newTabs.find(t => t.id === internalActiveId.value) && newTabs[0]) {\n internalActiveId.value = newTabs[0].id\n }\n})\n\n/**\n * 탭 값 변경 핸들러 (reka-ui TabsRoot에서 직접 호출됨)\n * Tab value change handler (called directly from reka-ui TabsRoot)\n */\nconst handleTabValueChange = (value: string | number) => {\n if (isHandlingEvent) return\n \n const stringValue = String(value)\n if (stringValue !== internalActiveId.value) {\n isHandlingEvent = true\n internalActiveId.value = stringValue\n emit('update:activeTabId', stringValue)\n emit('tabChange', stringValue)\n // 다음 tick에서 플래그 리셋\n nextTick(() => {\n isHandlingEvent = false\n })\n }\n}\n\n/**\n * 탭 클릭 핸들러 (백업 방안 - reka-ui 이벤트가 작동하지 않을 경우)\n * Tab click handler (backup - in case reka-ui events don't work)\n */\nconst handleTabClick = (tabId: string) => {\n // reka-ui 이벤트가 작동하지 않을 경우 직접 처리\n // handleTabValueChange가 이미 처리했으면 중복 방지\n if (isHandlingEvent || tabId === internalActiveId.value) return\n \n isHandlingEvent = true\n internalActiveId.value = tabId\n emit('update:activeTabId', tabId)\n emit('tabChange', tabId)\n // 다음 tick에서 플래그 리셋\n nextTick(() => {\n isHandlingEvent = false\n })\n}\n\n/**\n * 탭 닫기 핸들러\n * Tab close handler\n */\nconst handleCloseTab = (e: Event, tabId: string) => {\n e.stopPropagation() // 탭 클릭 이벤트 전파 방지\n emit('tabClose', tabId)\n}\n\n/**\n * 루트 클래스\n * Root classes\n */\nconst rootClasses = computed(() => {\n return cn('flex flex-col w-full h-full', props.class)\n})\n\n/**\n * 스타일 프리셋\n */\nconst STYLE_PRESETS: Record<StyleType, {\n tabPaddingClass: string\n tabTextSizeClass: string\n listPaddingClass: string\n}> = {\n default: {\n tabPaddingClass: 'px-2 py-1',\n tabTextSizeClass: 'text-xs',\n listPaddingClass: 'px-1 py-1',\n },\n minimal: {\n tabPaddingClass: 'px-1.5 py-1',\n tabTextSizeClass: 'text-xs',\n listPaddingClass: 'px-1 py-1',\n },\n}\n\nconst preset = computed(() => {\n return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\n/**\n * 탭 리스트 클래스\n * Tabs list classes\n */\nconst listClasses = computed(() => {\n return cn('w-full justify-start', preset.value.listPaddingClass, props.listClass)\n})\n</script>\n\n<template>\n <Tabs\n :model-value=\"internalActiveId\"\n @update:model-value=\"handleTabValueChange\"\n orientation=\"horizontal\"\n :class=\"rootClasses\"\n >\n <!-- 탭 헤더 영역 / Tab Headers -->\n <TabsList :class=\"listClasses\">\n <TabsTrigger\n v-for=\"tab in safeTabs\"\n :key=\"tab.id\"\n :value=\"tab.id\"\n @click=\"handleTabClick(tab.id)\"\n :class=\"cn('!flex !items-center !gap-2', preset.tabPaddingClass, preset.tabTextSizeClass)\"\n >\n <!-- 탭 아이콘 (있을 경우) / Tab Icon -->\n <JIcon \n v-if=\"tab.icon\" \n :name=\"tab.icon\" \n size=\"sm\"\n class=\"flex-shrink-0\"\n />\n \n <!-- 탭 레이블 / Tab Label -->\n <span class=\"flex-1 truncate\">{{ tab.label }}</span>\n \n <!-- 닫기 버튼 / Close Button (항상 표시) -->\n <button\n v-if=\"tab.closable\"\n type=\"button\"\n class=\"flex-shrink-0 h-3.5 w-3.5 rounded-sm hover:bg-destructive/10 hover:text-destructive transition-colors focus:outline-none focus:ring-2 focus:ring-ring flex items-center justify-center\"\n :aria-label=\"`${tab.label} 탭 닫기`\"\n @click=\"(e) => handleCloseTab(e, tab.id)\"\n >\n <X class=\"h-2.5 w-2.5\" />\n </button>\n </TabsTrigger>\n </TabsList>\n\n <!-- 탭 콘텐츠 영역 / Tab Contents -->\n <div class=\"flex-1 w-full overflow-auto\">\n <TabsContent\n v-for=\"tab in safeTabs\"\n :key=\"`content-${tab.id}`\"\n :value=\"tab.id\"\n class=\"h-full mt-0 data-[state=active]:flex data-[state=active]:flex-col\"\n >\n <!-- 슬롯 우선 / Slot First -->\n <slot :name=\"`content-${tab.id}`\" :tab=\"tab\">\n <!-- 동적 컴포넌트 렌더링 / Dynamic Component Rendering -->\n <component\n v-if=\"tab.component\"\n :is=\"tab.component\"\n v-bind=\"tab.props || {}\"\n />\n \n <!-- 기본 콘텐츠 / Default Content -->\n <div v-else class=\"p-4\">\n <p class=\"text-muted-foreground\">{{ tab.label }} 콘텐츠</p>\n </div>\n </slot>\n </TabsContent>\n </div>\n </Tabs>\n</template>\n\n<style scoped>\n/**\n * 탭 리스트 스타일 - 하단 보더 제거\n * Tab list styles without bottom border\n */\n:deep([role=\"tablist\"]:not(.ag-side-buttons)) {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: thin;\n scrollbar-color: rgba(0, 0, 0, 0.2) transparent;\n background: hsl(var(--background));\n padding: 0 0.25rem;\n gap: 0.25rem;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar) {\n height: 6px;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-track) {\n background: transparent;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.2);\n border-radius: 3px;\n}\n\n:deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb:hover) {\n background-color: rgba(0, 0, 0, 0.3);\n}\n\n/**\n * 다크모드에서 스크롤바 스타일\n * Scrollbar styles in dark mode\n */\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb) {\n background-color: rgba(255, 255, 255, 0.2);\n}\n\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)::-webkit-scrollbar-thumb:hover) {\n background-color: rgba(255, 255, 255, 0.3);\n}\n\n.dark :deep([role=\"tablist\"]:not(.ag-side-buttons)) {\n scrollbar-color: rgba(255, 255, 255, 0.2) transparent;\n}\n\n/**\n * 탭 버튼 스타일 - 명확한 구분\n * Tab button styles - clear distinction\n */\n:deep([role=\"tab\"]) {\n position: relative;\n padding: 0.25rem 0.5rem;\n min-height: 1.75rem;\n border-radius: 0.375rem 0.375rem 0 0;\n transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n border: 1px solid transparent;\n border-bottom: none;\n}\n\n/**\n * Minimal 스타일 탭 버튼 - JSidebarAdvanced와 높이 맞춤\n */\n:deep([role=\"tablist\"][class*=\"p-0.5\"] [role=\"tab\"]) {\n padding: 0.25rem 0.5rem;\n}\n\n/**\n * 비활성 탭 - 명확하게 구분\n * Inactive tabs - clear distinction\n */\n:deep([role=\"tab\"][data-state=\"inactive\"]) {\n background: hsl(var(--muted) / 0.2);\n color: hsl(var(--muted-foreground));\n border-top: 1px solid hsl(var(--border) / 0.4);\n border-left: 1px solid hsl(var(--border) / 0.4);\n border-right: 1px solid hsl(var(--border) / 0.4);\n}\n\n:deep([role=\"tab\"][data-state=\"inactive\"]:hover) {\n background: hsl(var(--muted) / 0.4);\n color: hsl(var(--foreground));\n}\n\n/**\n * 다크모드에서 비활성 탭 - 다크 배경색 사용\n * Inactive tabs in dark mode - use dark background\n */\n.dark :deep([role=\"tab\"][data-state=\"inactive\"]) {\n background: hsl(var(--secondary));\n color: hsl(var(--secondary-foreground));\n border-top: 1px solid hsl(var(--border) / 0.5);\n border-left: 1px solid hsl(var(--border) / 0.5);\n border-right: 1px solid hsl(var(--border) / 0.5);\n}\n\n.dark :deep([role=\"tab\"][data-state=\"inactive\"]:hover) {\n background: hsl(var(--muted));\n color: hsl(var(--muted-foreground));\n}\n\n/**\n * 활성 탭 - 강조된 스타일\n * Active tab - emphasized style\n */\n:deep([role=\"tab\"][data-state=\"active\"]) {\n background: hsl(var(--background));\n color: hsl(var(--foreground));\n font-weight: 500;\n border-top: 2px solid hsl(var(--primary));\n border-left: 1px solid hsl(var(--border));\n border-right: 1px solid hsl(var(--border));\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);\n z-index: 1;\n}\n\n/**\n * 다크모드에서 활성 탭 - 배경색 명확히 구분\n * Active tab in dark mode - clear background distinction\n */\n.dark :deep([role=\"tab\"][data-state=\"active\"]) {\n background: hsl(var(--card));\n color: hsl(var(--card-foreground));\n border-top: 2px solid hsl(var(--primary));\n border-left: 1px solid hsl(var(--border));\n border-right: 1px solid hsl(var(--border));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n}\n\n</style>\n"],"names":["props","__props","emit","__emit","safeTabs","computed","internalActiveId","ref","isHandlingEvent","watch","newValue","newTabs","t","handleTabValueChange","value","stringValue","nextTick","handleTabClick","tabId","handleCloseTab","e","rootClasses","cn","STYLE_PRESETS","preset","listClasses","_createBlock","_unref","Tabs","_createVNode","TabsList","_createElementBlock","_Fragment","_renderList","tab","TabsTrigger","$event","_normalizeClass","JIcon","_createElementVNode","_hoisted_1","_toDisplayString","X","_hoisted_3","TabsContent","_renderSlot","_ctx","_openBlock","_resolveDynamicComponent","_mergeProps","_hoisted_4","_hoisted_5"],"mappings":"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"}
|
|
@@ -44,14 +44,14 @@ const Y = { class: "flex-1 truncate" }, q = ["aria-label", "onClick"], G = { cla
|
|
|
44
44
|
e.stopPropagation(), r("tabClose", l);
|
|
45
45
|
}, w = d(() => C("flex flex-col w-full h-full", n.class)), h = {
|
|
46
46
|
default: {
|
|
47
|
-
tabPaddingClass: "px-2 py-
|
|
47
|
+
tabPaddingClass: "px-2 py-1",
|
|
48
48
|
tabTextSizeClass: "text-xs",
|
|
49
|
-
listPaddingClass: "px-1
|
|
49
|
+
listPaddingClass: "px-1 py-1"
|
|
50
50
|
},
|
|
51
51
|
minimal: {
|
|
52
|
-
tabPaddingClass: "px-1.5 py-
|
|
52
|
+
tabPaddingClass: "px-1.5 py-1",
|
|
53
53
|
tabTextSizeClass: "text-xs",
|
|
54
|
-
listPaddingClass: "px-1
|
|
54
|
+
listPaddingClass: "px-1 py-1"
|
|
55
55
|
}
|
|
56
56
|
}, p = d(() => h[n.styletype] ?? h.default), A = d(() => C("w-full justify-start", p.value.listPaddingClass, n.listClass));
|
|
57
57
|
return (e, l) => (s(), u(i(J), {
|