@j-solution/components 1.7.0 → 1.9.0
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 +413 -415
- package/assets/jwms-portal-frontend-Ct2Tc7yj.css +1 -0
- package/assets/styles/global-utilities.css +34 -0
- package/assets/styles/j-components.css +1 -1
- package/assets/styles/themes.css +443 -443
- package/components/atoms/JButton.vue.cjs +6 -1
- package/components/atoms/JButton.vue.cjs.map +1 -1
- package/components/atoms/JButton.vue.js +10 -85
- package/components/atoms/JButton.vue.js.map +1 -1
- package/components/atoms/JButton.vue2.cjs +1 -1
- package/components/atoms/JButton.vue2.cjs.map +1 -1
- package/components/atoms/JButton.vue2.js +85 -2
- package/components/atoms/JButton.vue2.js.map +1 -1
- package/components/atoms/JGrid.vue.cjs +1 -1
- package/components/atoms/JGrid.vue.js +1 -1
- package/components/atoms/JGrid.vue2.cjs +1 -1
- package/components/atoms/JGrid.vue2.cjs.map +1 -1
- package/components/atoms/JGrid.vue2.js +39 -35
- package/components/atoms/JGrid.vue2.js.map +1 -1
- package/components/atoms/JLabel.vue.cjs +1 -1
- package/components/atoms/JLabel.vue.cjs.map +1 -1
- package/components/atoms/JLabel.vue.js +26 -22
- package/components/atoms/JLabel.vue.js.map +1 -1
- package/components/atoms/JSectionTitle.vue.cjs +7 -0
- package/components/atoms/JSectionTitle.vue.cjs.map +1 -0
- package/components/atoms/JSectionTitle.vue.js +13 -0
- package/components/atoms/JSectionTitle.vue.js.map +1 -0
- package/components/atoms/JSectionTitle.vue2.cjs +2 -0
- package/components/atoms/JSectionTitle.vue2.cjs.map +1 -0
- package/components/atoms/JSectionTitle.vue2.js +67 -0
- package/components/atoms/JSectionTitle.vue2.js.map +1 -0
- package/components/atoms/JSplitter.vue.cjs +6 -1
- package/components/atoms/JSplitter.vue.cjs.map +1 -1
- package/components/atoms/JSplitter.vue.js +10 -59
- package/components/atoms/JSplitter.vue.js.map +1 -1
- package/components/atoms/JSplitter.vue2.cjs +1 -1
- package/components/atoms/JSplitter.vue2.cjs.map +1 -1
- package/components/atoms/JSplitter.vue2.js +59 -2
- package/components/atoms/JSplitter.vue2.js.map +1 -1
- package/components/examples/ExampleCrudPage.vue.cjs +1 -1
- package/components/examples/ExampleCrudPage.vue.cjs.map +1 -1
- package/components/examples/ExampleCrudPage.vue.js +228 -208
- package/components/examples/ExampleCrudPage.vue.js.map +1 -1
- package/components/examples/ExampleTabMappingPage.vue.cjs +1 -1
- package/components/examples/ExampleTabMappingPage.vue.cjs.map +1 -1
- package/components/examples/ExampleTabMappingPage.vue.js +341 -368
- package/components/examples/ExampleTabMappingPage.vue.js.map +1 -1
- package/components/molecules/JAlert.vue.cjs +1 -1
- package/components/molecules/JAlert.vue.cjs.map +1 -1
- package/components/molecules/JAlert.vue.js +18 -16
- package/components/molecules/JAlert.vue.js.map +1 -1
- package/components/molecules/JCard.vue.cjs +1 -1
- package/components/molecules/JCard.vue.cjs.map +1 -1
- package/components/molecules/JCard.vue.js +55 -39
- package/components/molecules/JCard.vue.js.map +1 -1
- package/components/molecules/JEmptyState.vue.cjs +7 -0
- package/components/molecules/JEmptyState.vue.cjs.map +1 -0
- package/components/molecules/JEmptyState.vue.js +13 -0
- package/components/molecules/JEmptyState.vue.js.map +1 -0
- package/components/molecules/JEmptyState.vue2.cjs +2 -0
- package/components/molecules/JEmptyState.vue2.cjs.map +1 -0
- package/components/molecules/JEmptyState.vue2.js +127 -0
- package/components/molecules/JEmptyState.vue2.js.map +1 -0
- package/components/molecules/JFormField.vue.cjs +6 -1
- package/components/molecules/JFormField.vue.cjs.map +1 -1
- package/components/molecules/JFormField.vue.js +10 -264
- package/components/molecules/JFormField.vue.js.map +1 -1
- package/components/molecules/JFormField.vue2.cjs +2 -0
- package/components/molecules/JFormField.vue2.cjs.map +1 -0
- package/components/molecules/JFormField.vue2.js +271 -0
- package/components/molecules/JFormField.vue2.js.map +1 -0
- package/components/molecules/JTabs.vue.cjs +1 -1
- package/components/molecules/JTabs.vue.js +1 -1
- package/components/molecules/JTabs.vue2.cjs +1 -1
- package/components/molecules/JTabs.vue2.cjs.map +1 -1
- package/components/molecules/JTabs.vue2.js +44 -50
- package/components/molecules/JTabs.vue2.js.map +1 -1
- package/components/molecules/JTitlebar.vue.cjs +1 -1
- package/components/molecules/JTitlebar.vue.cjs.map +1 -1
- package/components/molecules/JTitlebar.vue.js +23 -20
- package/components/molecules/JTitlebar.vue.js.map +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 -32
- package/components/organisms/JDynamicForm.vue2.js.map +1 -1
- package/components/organisms/JDynamicTabs.vue.cjs +1 -1
- package/components/organisms/JDynamicTabs.vue.cjs.map +1 -1
- package/components/organisms/JDynamicTabs.vue.js +47 -52
- package/components/organisms/JDynamicTabs.vue.js.map +1 -1
- package/components/organisms/JFilterBar.vue.cjs +6 -1
- package/components/organisms/JFilterBar.vue.cjs.map +1 -1
- package/components/organisms/JFilterBar.vue.js +10 -137
- package/components/organisms/JFilterBar.vue.js.map +1 -1
- package/components/organisms/JFilterBar.vue2.cjs +1 -1
- package/components/organisms/JFilterBar.vue2.cjs.map +1 -1
- package/components/organisms/JFilterBar.vue2.js +143 -2
- package/components/organisms/JFilterBar.vue2.js.map +1 -1
- package/components/organisms/JFormModal.vue.cjs +1 -1
- package/components/organisms/JFormModal.vue.cjs.map +1 -1
- package/components/organisms/JFormModal.vue.js +54 -49
- package/components/organisms/JFormModal.vue.js.map +1 -1
- package/components/organisms/JHeader.vue.cjs +1 -1
- package/components/organisms/JHeader.vue.cjs.map +1 -1
- package/components/organisms/JHeader.vue.js +191 -190
- package/components/organisms/JHeader.vue.js.map +1 -1
- package/components/organisms/JModal.vue.cjs +1 -1
- package/components/organisms/JModal.vue.cjs.map +1 -1
- package/components/organisms/JModal.vue.js +47 -45
- package/components/organisms/JModal.vue.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 +22 -22
- package/components/organisms/JPageContainer.vue.js.map +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
- package/components/organisms/JSearchPanel.vue2.js +34 -32
- package/components/organisms/JSearchPanel.vue2.js.map +1 -1
- package/components/organisms/JShuttle.vue.cjs +7 -0
- package/components/organisms/JShuttle.vue.cjs.map +1 -0
- package/components/organisms/JShuttle.vue.js +13 -0
- package/components/organisms/JShuttle.vue.js.map +1 -0
- package/components/organisms/JShuttle.vue2.cjs +2 -0
- package/components/organisms/JShuttle.vue2.cjs.map +1 -0
- package/components/organisms/JShuttle.vue2.js +216 -0
- package/components/organisms/JShuttle.vue2.js.map +1 -0
- package/components/organisms/JSidebar/JSidebar.vue.cjs +2 -0
- package/components/organisms/JSidebar/JSidebar.vue.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebar.vue.js +189 -0
- package/components/organisms/JSidebar/JSidebar.vue.js.map +1 -0
- package/components/{molecules/JFormField.vue3.cjs → organisms/JSidebar/JSidebar.vue2.cjs} +2 -2
- package/components/organisms/JSidebar/JSidebar.vue2.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebar.vue2.js +5 -0
- package/components/organisms/JSidebar/JSidebar.vue2.js.map +1 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue.cjs +2 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue.js +89 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue.js.map +1 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue2.cjs +2 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue2.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue2.js +5 -0
- package/components/organisms/JSidebar/JSidebarGroup.vue2.js.map +1 -0
- package/components/organisms/JSidebar/JSidebarItem.vue.cjs +2 -0
- package/components/organisms/JSidebar/JSidebarItem.vue.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebarItem.vue.js +79 -0
- package/components/organisms/JSidebar/JSidebarItem.vue.js.map +1 -0
- package/components/organisms/JSidebar/JSidebarItem.vue2.cjs +2 -0
- package/components/organisms/JSidebar/JSidebarItem.vue2.cjs.map +1 -0
- package/components/organisms/JSidebar/JSidebarItem.vue2.js +5 -0
- package/components/organisms/JSidebar/JSidebarItem.vue2.js.map +1 -0
- package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs +1 -1
- package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs.map +1 -1
- package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js +52 -52
- package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js.map +1 -1
- package/components/shadcn/Card.vue.cjs +1 -1
- package/components/shadcn/Card.vue.cjs.map +1 -1
- package/components/shadcn/Card.vue.js +1 -1
- package/components/shadcn/Card.vue.js.map +1 -1
- package/components/shadcn/CardContent.vue.cjs +1 -1
- package/components/shadcn/CardContent.vue.cjs.map +1 -1
- package/components/shadcn/CardContent.vue.js +4 -4
- package/components/shadcn/CardContent.vue.js.map +1 -1
- package/components/shadcn/CardHeader.vue.cjs +1 -1
- package/components/shadcn/CardHeader.vue.cjs.map +1 -1
- package/components/shadcn/CardHeader.vue.js +5 -5
- package/components/shadcn/CardHeader.vue.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 +3 -3
- 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/TabsContent.vue.cjs +1 -1
- package/components/shadcn/TabsContent.vue.cjs.map +1 -1
- package/components/shadcn/TabsContent.vue.js +1 -1
- package/components/shadcn/TabsContent.vue.js.map +1 -1
- package/components/shadcn/TabsList.vue.cjs +1 -1
- package/components/shadcn/TabsList.vue.cjs.map +1 -1
- package/components/shadcn/TabsList.vue.js +10 -10
- package/components/shadcn/TabsList.vue.js.map +1 -1
- package/components/shadcn/Textarea.vue.cjs +1 -1
- package/components/shadcn/Textarea.vue.cjs.map +1 -1
- package/components/shadcn/Textarea.vue.js +1 -1
- package/components/shadcn/Textarea.vue.js.map +1 -1
- package/components/shadcn/index.cjs +1 -1
- package/components/shadcn/index.cjs.map +1 -1
- package/components/shadcn/index.js +4 -4
- package/components/shadcn/index.js.map +1 -1
- package/components/templates/JLayout.vue.cjs.map +1 -1
- package/components/templates/JLayout.vue.js.map +1 -1
- package/components/templates/JLayoutSimple.vue.cjs +1 -1
- package/components/templates/JLayoutSimple.vue.cjs.map +1 -1
- package/components/templates/JLayoutSimple.vue.js +36 -30
- package/components/templates/JLayoutSimple.vue.js.map +1 -1
- package/index.cjs +1 -1
- package/index.js +75 -67
- package/package.json +1 -1
- package/types/index.d.ts +662 -461
- package/types/sidebar.types.cjs +2 -0
- package/types/sidebar.types.cjs.map +1 -0
- package/types/sidebar.types.js +5 -0
- package/types/sidebar.types.js.map +1 -0
- package/assets/jwms-portal-frontend-CwxPfHfa.css +0 -1
- package/components/molecules/JFormField.vue3.cjs.map +0 -1
- package/components/molecules/JFormField.vue3.js +0 -6
- package/components/molecules/JFormField.vue3.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineComponent as B, computed as s, createElementBlock as
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import { defineComponent as B, computed as s, createElementBlock as g, openBlock as n, normalizeClass as i, unref as p, createBlock as u, createCommentVNode as d, createElementVNode as h, withCtx as w, renderSlot as m } from "vue";
|
|
2
|
+
import x from "../molecules/JBreadcrumb.vue.js";
|
|
3
|
+
import S from "../molecules/JTitlebar.vue.js";
|
|
4
4
|
import { cn as b } from "../../lib/utils.js";
|
|
5
5
|
const $ = /* @__PURE__ */ B({
|
|
6
6
|
__name: "JPageContainer",
|
|
@@ -22,46 +22,46 @@ const $ = /* @__PURE__ */ B({
|
|
|
22
22
|
const l = t, o = f, a = {
|
|
23
23
|
default: {
|
|
24
24
|
containerClass: "flex flex-col h-full w-full bg-background",
|
|
25
|
-
contentClass: "flex-1 p-
|
|
25
|
+
contentClass: "flex-1 p-3 pt-2 pb-2 gap-2 bg-background text-foreground"
|
|
26
26
|
},
|
|
27
27
|
minimal: {
|
|
28
28
|
containerClass: "flex flex-col h-full w-full bg-background",
|
|
29
|
-
contentClass: "flex-1 p-
|
|
29
|
+
contentClass: "flex-1 p-1 gap-1 bg-background text-foreground"
|
|
30
30
|
}
|
|
31
|
-
},
|
|
32
|
-
|
|
31
|
+
}, r = s(() => a[l.styletype] ?? a.default), C = s(() => b(
|
|
32
|
+
r.value.contentClass,
|
|
33
33
|
l.contentScroll ? "overflow-auto" : "overflow-hidden"
|
|
34
|
-
)),
|
|
35
|
-
o("breadcrumbClick", e,
|
|
36
|
-
},
|
|
34
|
+
)), k = (e, c) => {
|
|
35
|
+
o("breadcrumbClick", e, c);
|
|
36
|
+
}, y = (e) => {
|
|
37
37
|
o("titlebarButtonClick", e);
|
|
38
38
|
};
|
|
39
|
-
return (e,
|
|
40
|
-
class: i(p(b)(
|
|
39
|
+
return (e, c) => (n(), g("div", {
|
|
40
|
+
class: i(p(b)(r.value.containerClass, l.class))
|
|
41
41
|
}, [
|
|
42
|
-
t.showBreadcrumb && t.breadcrumbItems && t.breadcrumbItems.length > 0 ? (n(), u(
|
|
42
|
+
t.showBreadcrumb && t.breadcrumbItems && t.breadcrumbItems.length > 0 ? (n(), u(x, {
|
|
43
43
|
key: 0,
|
|
44
44
|
items: t.breadcrumbItems,
|
|
45
|
-
onItemClick:
|
|
46
|
-
}, null, 8, ["items"])) :
|
|
47
|
-
t.showTitlebar ? (n(), u(
|
|
45
|
+
onItemClick: k
|
|
46
|
+
}, null, 8, ["items"])) : d("", !0),
|
|
47
|
+
t.showTitlebar ? (n(), u(S, {
|
|
48
48
|
key: 1,
|
|
49
49
|
title: t.title,
|
|
50
50
|
icon: t.icon,
|
|
51
51
|
description: t.description,
|
|
52
52
|
buttons: t.titlebarButtons,
|
|
53
53
|
styletype: t.titlebarStyletype,
|
|
54
|
-
onButtonClick:
|
|
54
|
+
onButtonClick: y
|
|
55
55
|
}, {
|
|
56
|
-
buttons:
|
|
57
|
-
|
|
56
|
+
buttons: w(() => [
|
|
57
|
+
m(e.$slots, "titlebar-buttons")
|
|
58
58
|
]),
|
|
59
59
|
_: 3
|
|
60
|
-
}, 8, ["title", "icon", "description", "buttons", "styletype"])) :
|
|
61
|
-
|
|
60
|
+
}, 8, ["title", "icon", "description", "buttons", "styletype"])) : d("", !0),
|
|
61
|
+
h("div", {
|
|
62
62
|
class: i(C.value)
|
|
63
63
|
}, [
|
|
64
|
-
|
|
64
|
+
m(e.$slots, "default")
|
|
65
65
|
], 2)
|
|
66
66
|
], 2));
|
|
67
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JPageContainer.vue.js","sources":["../../../../src/components/organisms/JPageContainer.vue"],"sourcesContent":["<script setup lang=\"ts\">\
|
|
1
|
+
{"version":3,"file":"JPageContainer.vue.js","sources":["../../../../src/components/organisms/JPageContainer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport JBreadcrumb from '@/components/molecules/JBreadcrumb.vue'\nimport JTitlebar from '@/components/molecules/JTitlebar.vue'\nimport { cn } from '@/lib/utils'\nimport type { BreadcrumbItem } from '@/components/molecules/JBreadcrumb.vue'\nimport type { TitlebarButton } from '@/components/molecules/JTitlebar.vue'\n\n/**\n * JPageContainer - 기본 페이지 컨테이너 컴포넌트 (organisms)\n * Page Container Component\n * \n * @description\n * 페이지의 기본 레이아웃을 담당하는 컨테이너 컴포넌트입니다.\n * 브레드크럼, 제목 영역(JTitlebar), 콘텐츠 영역을 포함합니다.\n * \n * @example\n * ```vue\n * <JPageContainer\n * :breadcrumb-items=\"breadcrumbItems\"\n * title=\"페이지 제목\"\n * :titlebar-buttons=\"buttons\"\n * >\n * <div>페이지 콘텐츠</div>\n * </JPageContainer>\n * ```\n */\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'minimal' // 최소 스타일\n\nconst props = withDefaults(\n defineProps<{\n /** 브레드크럼 아이템 목록 */\n breadcrumbItems?: BreadcrumbItem[]\n /** 브레드크럼 표시 여부 */\n showBreadcrumb?: boolean\n /** JTitlebar의 모든 props 전달 */\n title?: string\n icon?: string\n description?: string\n titlebarButtons?: TitlebarButton[]\n titlebarStyletype?: 'default' | 'primary' | 'accent' | 'neutral' | 'elevated'\n /** JTitlebar 표시 여부 */\n showTitlebar?: boolean\n /** 스타일 타입 */\n styletype?: StyleType\n /** 콘텐츠 영역 스크롤 가능 여부 */\n contentScroll?: boolean\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n breadcrumbItems: () => [],\n showBreadcrumb: true,\n showTitlebar: true,\n styletype: 'default',\n contentScroll: true,\n }\n)\n\nconst emit = defineEmits<{\n /** 브레드크럼 아이템 클릭 이벤트 */\n breadcrumbClick: [item: BreadcrumbItem, index: number]\n /** 타이틀바 버튼 클릭 이벤트 */\n titlebarButtonClick: [button: TitlebarButton]\n}>()\n\n/**\n * 스타일 프리셋\n */\nconst STYLE_PRESETS: Record<StyleType, {\n containerClass: string\n contentClass: string\n}> = {\n default: {\n containerClass: 'flex flex-col h-full w-full bg-background',\n contentClass: 'flex-1 p-3 pt-2 pb-2 gap-2 bg-background text-foreground',\n },\n minimal: {\n containerClass: 'flex flex-col h-full w-full bg-background',\n contentClass: 'flex-1 p-1 gap-1 bg-background text-foreground',\n },\n}\n\nconst preset = computed(() => {\n return STYLE_PRESETS[props.styletype] ?? STYLE_PRESETS.default\n})\n\n/**\n * 콘텐츠 클래스 (스크롤 포함)\n */\nconst contentClasses = computed(() => {\n return cn(\n preset.value.contentClass,\n props.contentScroll ? 'overflow-auto' : 'overflow-hidden'\n )\n})\n\n/**\n * 브레드크럼 아이템 클릭 핸들러\n */\nconst handleBreadcrumbClick = (item: BreadcrumbItem, index: number) => {\n emit('breadcrumbClick', item, index)\n}\n\n/**\n * 타이틀바 버튼 클릭 핸들러\n */\nconst handleTitlebarButtonClick = (button: TitlebarButton) => {\n emit('titlebarButtonClick', button)\n}\n</script>\n\n<template>\n <div :class=\"cn(preset.containerClass, props.class)\">\n <!-- 브레드크럼 -->\n <JBreadcrumb\n v-if=\"showBreadcrumb && breadcrumbItems && breadcrumbItems.length > 0\"\n :items=\"breadcrumbItems\"\n @item-click=\"handleBreadcrumbClick\"\n />\n\n <!-- 제목 영역 (JTitlebar) -->\n <JTitlebar\n v-if=\"showTitlebar\"\n :title=\"title\"\n :icon=\"icon\"\n :description=\"description\"\n :buttons=\"titlebarButtons\"\n :styletype=\"titlebarStyletype\"\n @button-click=\"handleTitlebarButtonClick\"\n >\n <template #buttons>\n <slot name=\"titlebar-buttons\" />\n </template>\n </JTitlebar>\n\n <!-- 콘텐츠 영역 -->\n <div :class=\"contentClasses\">\n <slot />\n </div>\n </div>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","contentClasses","cn","handleBreadcrumbClick","item","index","handleTitlebarButtonClick","button","_createElementBlock","_normalizeClass","_unref","_createBlock","JBreadcrumb","JTitlebar","_renderSlot","_ctx","_createElementVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAgCA,UAAMA,IAAQC,GA8BRC,IAAOC,GAUPC,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,IAASC,EAAS,MACfF,EAAcJ,EAAM,SAAS,KAAKI,EAAc,OACxD,GAKKG,IAAiBD,EAAS,MACvBE;AAAA,MACLH,EAAO,MAAM;AAAA,MACbL,EAAM,gBAAgB,kBAAkB;AAAA,IAAA,CAE3C,GAKKS,IAAwB,CAACC,GAAsBC,MAAkB;AACrE,MAAAT,EAAK,mBAAmBQ,GAAMC,CAAK;AAAA,IACrC,GAKMC,IAA4B,CAACC,MAA2B;AAC5D,MAAAX,EAAK,uBAAuBW,CAAM;AAAA,IACpC;2BAIEC,EA2BM,OAAA;AAAA,MA3BA,OAAKC,EAAEC,KAAGX,EAAA,MAAO,gBAAgBL,EAAM,KAAK,CAAA;AAAA,IAAA;MAGxCC,EAAA,kBAAkBA,EAAA,mBAAmBA,EAAA,gBAAgB,SAAM,UADnEgB,EAIEC,GAAA;AAAA;QAFC,OAAOjB,EAAA;AAAA,QACP,aAAYQ;AAAA,MAAA;MAKPR,EAAA,qBADRgB,EAYYE,GAAA;AAAA;QAVT,OAAOlB,EAAA;AAAA,QACP,MAAMA,EAAA;AAAA,QACN,aAAaA,EAAA;AAAA,QACb,SAASA,EAAA;AAAA,QACT,WAAWA,EAAA;AAAA,QACX,eAAcW;AAAA,MAAA;QAEJ,WACT,MAAgC;AAAA,UAAhCQ,EAAgCC,EAAA,QAAA,kBAAA;AAAA,QAAA;;;MAKpCC,EAEM,OAAA;AAAA,QAFA,SAAOf,EAAA,KAAc;AAAA,MAAA;QACzBa,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"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),v=require("lucide-vue-next");require("../shadcn/index.cjs");const N=require("../atoms/JButton.vue.cjs");require("clsx");require("tailwind-merge");require("@internationalized/date");require("md-editor-v3");;/* empty css */;/* empty css */const V=require("../atoms/JBadge.vue.cjs");require("@vueuse/core");require("reka-ui");;/* empty css */require("../shadcn/avatar-variants.cjs");require("dompurify");;/* empty css */require("ag-grid-vue3");require("ag-grid-community");require("ag-grid-enterprise");;/* empty css */;/* empty css */;/* empty css */;/* empty css */;/* empty css */;/* empty css */require("vue-sonner");const C=require("./JDynamicForm.vue.cjs"),g=require("../shadcn/Card.vue.cjs"),w=require("../shadcn/CardHeader.vue.cjs"),B=require("../shadcn/CardTitle.vue.cjs"),E=require("../shadcn/CardContent.vue.cjs"),S={class:"flex items-center justify-between"},D={class:"flex items-center gap-3 flex-1"},F={key:2,class:"flex flex-wrap items-center gap-2 ml-2"},j=["onClick","aria-label"],T=e.defineComponent({__name:"JSearchPanel",props:{title:{default:"조회조건"},schema:{},modelValue:{},defaultCollapsed:{type:Boolean,default:!1},collapsible:{type:Boolean,default:!0}},emits:["update:modelValue","submit","reset"],setup(i,{emit:_}){const a=i,u=_,d=e.ref(null),n=e.ref(!a.defaultCollapsed),s=e.reactive(a.modelValue?{...a.modelValue}:{});let c=!1;e.watch(()=>a.modelValue,l=>{l&&!c&&(Object.keys(s).forEach(r=>{r in l||delete s[r]}),Object.assign(s,l)),c=!1},{deep:!0,immediate:!0});function y(l){c=!0,Object.assign(s,l),u("update:modelValue",{...l})}const m=e.computed(()=>{if(!a.schema)return[];const l=[];return a.schema.type==="simple"&&a.schema.fields?l.push(...a.schema.fields):a.schema.type==="sectioned"&&a.schema.sections?a.schema.sections.forEach(r=>{r.fields&&l.push(...r.fields)}):a.schema.type==="wizard"&&a.schema.steps&&a.schema.steps.forEach(r=>{r.fields&&l.push(...r.fields)}),l}),f=e.computed(()=>{if(!s||!a.schema)return[];const l=[],r=s;return m.value.forEach(t=>{const o=r[t.controlName];if(o==null||o===""||o==="ALL"||o==="SELECT"||t.type==="checkbox"&&o==="N"||t.type==="switch"&&o==="N")return;let p=String(o);if((t.type==="combo"||t.type==="searchcombo")&&t.options){const h=t.options.find(k=>k.value===o);h&&(p=h.label)}t.type==="checkbox"||t.type==="switch"?o==="Y"&&l.push({fieldName:t.controlName,label:t.label,value:t.inlineLabel||t.label}):l.push({fieldName:t.controlName,label:t.label,value:p})}),l});function b(l){u("submit",l)}function q(){d.value&&(d.value.reset(),u("reset"))}function x(l){if(!s||!a.schema)return;const r=m.value.find(t=>t.controlName===l);r&&(r.type==="checkbox"||r.type==="switch"?s[l]="N":s[l]="",c=!0,u("update:modelValue",{...s}))}return(l,r)=>(e.openBlock(),e.createBlock(e.unref(g.default),{class:"w-full"},{default:e.withCtx(()=>[e.createVNode(e.unref(w.default),{class:"pt-4 pb-3 px-6"},{default:e.withCtx(()=>[e.createElementVNode("div",S,[e.createElementVNode("div",D,[i.collapsible?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",onClick:r[0]||(r[0]=t=>n.value=!n.value),class:"flex items-center gap-2 font-semibold hover:text-primary transition-colors"},[e.createVNode(e.unref(v.ChevronDown),{class:e.normalizeClass(["h-4 w-4 transition-transform",n.value?"rotate-0":"-rotate-90"])},null,8,["class"]),e.createTextVNode(" "+e.toDisplayString(i.title),1)])):(e.openBlock(),e.createBlock(e.unref(B.default),{key:1,class:"mb-0"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(i.title),1)]),_:1})),f.value.length>0?(e.openBlock(),e.createElementBlock("div",F,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(f.value,t=>(e.openBlock(),e.createBlock(e.unref(V.default),{key:t.fieldName,variant:"secondary",size:"sm",class:"flex items-center gap-1.5 pr-1"},{default:e.withCtx(()=>[e.createElementVNode("span",null,e.toDisplayString(t.label)+": "+e.toDisplayString(t.value),1),e.createElementVNode("button",{type:"button",onClick:e.withModifiers(o=>x(t.fieldName),["stop"]),class:"h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center","aria-label":`${t.label} 조건 제거`},[e.createVNode(e.unref(v.X),{class:"h-3 w-3"})],8,j)]),_:2},1024))),128))])):e.createCommentVNode("",!0)]),e.createVNode(e.unref(N.default),{variant:"outline",size:"sm",onClick:e.withModifiers(q,["stop"])},{default:e.withCtx(()=>[...r[1]||(r[1]=[e.createTextVNode(" 초기화 ",-1)])]),_:1})])]),_:1}),e.withDirectives(e.createVNode(e.unref(E.default),{class:"px-6 pb-6 pt-0"},{default:e.withCtx(()=>[e.createVNode(C.default,{ref_key:"dynamicFormRef",ref:d,schema:i.schema,"model-value":s,"onUpdate:modelValue":y,onSubmit:b},null,8,["schema","model-value"])]),_:1},512),[[e.vShow,n.value||!i.collapsible]])]),_:1}))}});exports.default=T;
|
|
2
2
|
//# sourceMappingURL=JSearchPanel.vue2.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchPanel.vue2.cjs","sources":["../../../../src/components/organisms/JSearchPanel.vue"],"sourcesContent":["<template>\n <Card class=\"w-full\">\n <!-- 헤더: 제목, Badge 목록, 초기화 버튼 -->\n <CardHeader class=\"pt-4 pb-3 px-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3 flex-1\">\n <button\n v-if=\"collapsible\"\n type=\"button\"\n @click=\"isExpanded = !isExpanded\"\n class=\"flex items-center gap-2 font-semibold hover:text-primary transition-colors\"\n >\n <ChevronDown\n :class=\"['h-4 w-4 transition-transform', isExpanded ? 'rotate-0' : '-rotate-90']\"\n />\n {{ title }}\n </button>\n <CardTitle v-else class=\"mb-0\">{{ title }}</CardTitle>\n \n <!-- 조건 Badge 목록 -->\n <div v-if=\"conditionBadges.length > 0\" class=\"flex flex-wrap items-center gap-2 ml-2\">\n <JBadge\n v-for=\"badge in conditionBadges\"\n :key=\"badge.fieldName\"\n variant=\"secondary\"\n size=\"sm\"\n class=\"flex items-center gap-1.5 pr-1\"\n >\n <span>{{ badge.label }}: {{ badge.value }}</span>\n <button\n type=\"button\"\n @click.stop=\"handleFieldReset(badge.fieldName)\"\n class=\"h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center\"\n :aria-label=\"`${badge.label} 조건 제거`\"\n >\n <X class=\"h-3 w-3\" />\n </button>\n </JBadge>\n </div>\n </div>\n \n <JButton\n variant=\"outline\"\n size=\"sm\"\n @click.stop=\"handleReset\"\n >\n 초기화\n </JButton>\n </div>\n </CardHeader>\n \n <!-- 폼 내용 -->\n <CardContent v-show=\"isExpanded || !collapsible\" class=\"px-6 pb-6 pt-0\">\n <JDynamicForm\n ref=\"dynamicFormRef\"\n :schema=\"schema\"\n :model-value=\"localModelValue\"\n @update:model-value=\"handleFormValueUpdate\"\n @submit=\"handleSubmit\"\n />\n </CardContent>\n </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, reactive, watch } from 'vue'\nimport { ChevronDown, X } from 'lucide-vue-next'\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/shadcn'\nimport { JButton, JBadge } from '@/components/atoms'\nimport JDynamicForm from './JDynamicForm.vue'\nimport type { FormSchema, DynamicFormField } from '@/types/dynamic-form'\nimport type { ComponentPublicInstance } from 'vue'\n\ninterface ConditionBadge {\n fieldName: string\n label: string\n value: string\n}\n\nexport interface JSearchPanelProps {\n /** 패널 제목 */\n title?: string\n /** JDynamicForm에 전달할 FormSchema */\n schema: FormSchema\n /** JDynamicForm의 v-model 값 */\n modelValue?: Record<string, any>\n /** 기본 접힘 상태 */\n defaultCollapsed?: boolean\n /** 접기/펼치기 가능 여부 */\n collapsible?: boolean\n}\n\nconst props = withDefaults(defineProps<JSearchPanelProps>(), {\n title: '조회조건',\n defaultCollapsed: false,\n collapsible: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Record<string, any>]\n 'submit': [values: Record<string, any>]\n 'reset': []\n}>()\n\nconst dynamicFormRef = ref<ComponentPublicInstance & { reset: () => void } | null>(null)\nconst isExpanded = ref(!props.defaultCollapsed)\n\n// 로컬 modelValue - reactive로 관리하여 양방향 바인딩\nconst localModelValue = reactive<Record<string, any>>(props.modelValue ? { ...props.modelValue } : {})\n\n// 내부 변경인지 외부 변경인지 구분하는 플래그\nlet isInternalUpdate = false\n\n// props.modelValue 변경 시 localModelValue 동기화 (외부 변경)\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue && !isInternalUpdate) {\n // 기존 키 중 새 값에 없는 것은 삭제\n Object.keys(localModelValue).forEach(key => {\n if (!(key in newValue)) {\n delete localModelValue[key]\n }\n })\n // 새 값으로 업데이트\n Object.assign(localModelValue, newValue)\n }\n isInternalUpdate = false\n },\n { deep: true, immediate: true }\n)\n\n// JDynamicForm에서 값이 변경되었을 때 처리\nfunction handleFormValueUpdate(value: Record<string, any>) {\n // JDynamicForm에서 emit된 값을 localModelValue에 반영\n isInternalUpdate = true\n Object.assign(localModelValue, value)\n // 상위로 emit\n emit('update:modelValue', { ...value })\n}\n\n// 모든 필드 가져오기\nconst allFields = computed((): DynamicFormField[] => {\n if (!props.schema) return []\n \n const fields: DynamicFormField[] = []\n if (props.schema.type === 'simple' && props.schema.fields) {\n fields.push(...props.schema.fields)\n } else if (props.schema.type === 'sectioned' && props.schema.sections) {\n props.schema.sections.forEach(section => {\n if (section.fields) fields.push(...section.fields)\n })\n } else if (props.schema.type === 'wizard' && props.schema.steps) {\n props.schema.steps.forEach(step => {\n if (step.fields) fields.push(...step.fields)\n })\n }\n return fields\n})\n\n// 조건 Badge 목록 생성\nconst conditionBadges = computed((): ConditionBadge[] => {\n if (!localModelValue || !props.schema) {\n return []\n }\n\n const badges: ConditionBadge[] = []\n const formState = localModelValue\n\n allFields.value.forEach((field) => {\n const value = formState[field.controlName]\n \n // 빈 값 체크 (빈 문자열, null, undefined, 'ALL', 'SELECT' 제외)\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n value === 'ALL' ||\n value === 'SELECT' ||\n (field.type === 'checkbox' && value === 'N') ||\n (field.type === 'switch' && value === 'N')\n ) {\n return\n }\n\n // 필드 타입에 따라 값 표시\n let displayValue = String(value)\n\n // 콤보/검색콤보인 경우 옵션의 label 찾기\n if ((field.type === 'combo' || field.type === 'searchcombo') && field.options) {\n const option = field.options.find(opt => opt.value === value)\n if (option) {\n displayValue = option.label\n }\n }\n\n // 체크박스/스위치는 'Y'일 때만 표시\n if (field.type === 'checkbox' || field.type === 'switch') {\n if (value === 'Y') {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: field.inlineLabel || field.label\n })\n }\n } else {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: displayValue\n })\n }\n })\n\n return badges\n})\n\n// submit 핸들러\nfunction handleSubmit(values: Record<string, any>) {\n emit('submit', values)\n}\n\n// 전체 초기화 핸들러\nfunction handleReset() {\n if (dynamicFormRef.value) {\n dynamicFormRef.value.reset()\n emit('reset')\n }\n}\n\n// 필드별 초기화 핸들러\nfunction handleFieldReset(fieldName: string) {\n if (!localModelValue || !props.schema) return\n \n const field = allFields.value.find(f => f.controlName === fieldName)\n \n if (field) {\n // 필드 타입에 따라 초기값 설정 - reactive 객체 직접 수정\n if (field.type === 'checkbox' || field.type === 'switch') {\n localModelValue[fieldName] = 'N'\n } else {\n localModelValue[fieldName] = ''\n }\n \n // localModelValue 변경 후 상위로 emit하여 JDynamicForm에도 반영\n isInternalUpdate = true\n emit('update:modelValue', { ...localModelValue })\n }\n}\n</script>\n\n<style scoped>\n/* 필요시 스타일 추가 */\n</style>\n\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","isExpanded","localModelValue","reactive","isInternalUpdate","watch","newValue","key","handleFormValueUpdate","value","allFields","computed","fields","section","step","conditionBadges","badges","formState","field","displayValue","option","opt","handleSubmit","values","handleReset","handleFieldReset","fieldName","f","_createBlock","_unref","Card","_createVNode","CardHeader","_createElementVNode","_hoisted_1","_hoisted_2","_createElementBlock","_cache","$event","ChevronDown","_createTextVNode","CardTitle","_openBlock","_hoisted_3","_Fragment","_renderList","badge","JBadge","_toDisplayString","_withModifiers","X","JButton","CardContent","JDynamicForm","_vShow"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JSearchPanel.vue2.cjs","sources":["../../../../src/components/organisms/JSearchPanel.vue"],"sourcesContent":["<template>\n <Card class=\"w-full\">\n <!-- 헤더: 제목, Badge 목록, 초기화 버튼 -->\n <CardHeader class=\"pt-4 pb-3 px-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3 flex-1\">\n <button\n v-if=\"collapsible\"\n type=\"button\"\n @click=\"isExpanded = !isExpanded\"\n class=\"flex items-center gap-2 font-semibold hover:text-primary transition-colors\"\n >\n <ChevronDown\n :class=\"['h-4 w-4 transition-transform', isExpanded ? 'rotate-0' : '-rotate-90']\"\n />\n {{ title }}\n </button>\n <CardTitle v-else class=\"mb-0\">{{ title }}</CardTitle>\n \n <!-- 조건 Badge 목록 -->\n <div v-if=\"conditionBadges.length > 0\" class=\"flex flex-wrap items-center gap-2 ml-2\">\n <JBadge\n v-for=\"badge in conditionBadges\"\n :key=\"badge.fieldName\"\n variant=\"secondary\"\n size=\"sm\"\n class=\"flex items-center gap-1.5 pr-1\"\n >\n <span>{{ badge.label }}: {{ badge.value }}</span>\n <button\n type=\"button\"\n @click.stop=\"handleFieldReset(badge.fieldName)\"\n class=\"h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center\"\n :aria-label=\"`${badge.label} 조건 제거`\"\n >\n <X class=\"h-3 w-3\" />\n </button>\n </JBadge>\n </div>\n </div>\n \n <JButton\n variant=\"outline\"\n size=\"sm\"\n @click.stop=\"handleReset\"\n >\n 초기화\n </JButton>\n </div>\n </CardHeader>\n \n <!-- 폼 내용 -->\n <CardContent v-show=\"isExpanded || !collapsible\" class=\"px-6 pb-6 pt-0\">\n <JDynamicForm\n ref=\"dynamicFormRef\"\n :schema=\"schema\"\n :model-value=\"localModelValue\"\n @update:model-value=\"handleFormValueUpdate\"\n @submit=\"handleSubmit\"\n />\n </CardContent>\n </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, reactive, watch } from 'vue'\nimport { ChevronDown, X } from 'lucide-vue-next'\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/shadcn'\nimport { JButton, JBadge } from '@/components/atoms'\nimport JDynamicForm from './JDynamicForm.vue'\nimport type { FormSchema, DynamicFormField } from '@/types/dynamic-form'\nimport type { ComponentPublicInstance } from 'vue'\n\ninterface ConditionBadge {\n fieldName: string\n label: string\n value: string\n}\n\nexport interface JSearchPanelProps {\n /** 패널 제목 */\n title?: string\n /** JDynamicForm에 전달할 FormSchema */\n schema: FormSchema\n /** JDynamicForm의 v-model 값 */\n modelValue?: Record<string, any>\n /** 기본 접힘 상태 */\n defaultCollapsed?: boolean\n /** 접기/펼치기 가능 여부 */\n collapsible?: boolean\n}\n\nconst props = withDefaults(defineProps<JSearchPanelProps>(), {\n title: '조회조건',\n defaultCollapsed: false,\n collapsible: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Record<string, any>]\n 'submit': [values: Record<string, any>]\n 'reset': []\n}>()\n\nconst dynamicFormRef = ref<ComponentPublicInstance & { reset: () => void } | null>(null)\nconst isExpanded = ref(!props.defaultCollapsed)\n\n// 로컬 modelValue - reactive로 관리하여 양방향 바인딩\nconst localModelValue = reactive<Record<string, any>>(props.modelValue ? { ...props.modelValue } : {})\n\n// 내부 변경인지 외부 변경인지 구분하는 플래그\nlet isInternalUpdate = false\n\n// props.modelValue 변경 시 localModelValue 동기화 (외부 변경)\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue && !isInternalUpdate) {\n // 기존 키 중 새 값에 없는 것은 삭제\n Object.keys(localModelValue).forEach(key => {\n if (!(key in newValue)) {\n delete localModelValue[key]\n }\n })\n // 새 값으로 업데이트\n Object.assign(localModelValue, newValue)\n }\n isInternalUpdate = false\n },\n { deep: true, immediate: true }\n)\n\n// JDynamicForm에서 값이 변경되었을 때 처리\nfunction handleFormValueUpdate(value: Record<string, any>) {\n // JDynamicForm에서 emit된 값을 localModelValue에 반영\n isInternalUpdate = true\n Object.assign(localModelValue, value)\n // 상위로 emit\n emit('update:modelValue', { ...value })\n}\n\n// 모든 필드 가져오기\nconst allFields = computed((): DynamicFormField[] => {\n if (!props.schema) return []\n \n const fields: DynamicFormField[] = []\n if (props.schema.type === 'simple' && props.schema.fields) {\n fields.push(...props.schema.fields)\n } else if (props.schema.type === 'sectioned' && props.schema.sections) {\n props.schema.sections.forEach(section => {\n if (section.fields) fields.push(...section.fields)\n })\n } else if (props.schema.type === 'wizard' && props.schema.steps) {\n props.schema.steps.forEach(step => {\n if (step.fields) fields.push(...step.fields)\n })\n }\n return fields\n})\n\n// 조건 Badge 목록 생성\nconst conditionBadges = computed((): ConditionBadge[] => {\n if (!localModelValue || !props.schema) {\n return []\n }\n\n const badges: ConditionBadge[] = []\n const formState = localModelValue\n\n allFields.value.forEach((field) => {\n const value = formState[field.controlName]\n \n // 빈 값 체크 (빈 문자열, null, undefined, 'ALL', 'SELECT' 제외)\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n value === 'ALL' ||\n value === 'SELECT' ||\n (field.type === 'checkbox' && value === 'N') ||\n (field.type === 'switch' && value === 'N')\n ) {\n return\n }\n\n // 필드 타입에 따라 값 표시\n let displayValue = String(value)\n\n // 콤보/검색콤보인 경우 옵션의 label 찾기\n if ((field.type === 'combo' || field.type === 'searchcombo') && field.options) {\n const option = field.options.find(opt => opt.value === value)\n if (option) {\n displayValue = option.label\n }\n }\n\n // 체크박스/스위치는 'Y'일 때만 표시\n if (field.type === 'checkbox' || field.type === 'switch') {\n if (value === 'Y') {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: field.inlineLabel || field.label\n })\n }\n } else {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: displayValue\n })\n }\n })\n\n return badges\n})\n\n// submit 핸들러\nfunction handleSubmit(values: Record<string, any>) {\n emit('submit', values)\n}\n\n// 전체 초기화 핸들러\nfunction handleReset() {\n if (dynamicFormRef.value) {\n dynamicFormRef.value.reset()\n emit('reset')\n }\n}\n\n// 필드별 초기화 핸들러\nfunction handleFieldReset(fieldName: string) {\n if (!localModelValue || !props.schema) return\n \n const field = allFields.value.find(f => f.controlName === fieldName)\n \n if (field) {\n // 필드 타입에 따라 초기값 설정 - reactive 객체 직접 수정\n if (field.type === 'checkbox' || field.type === 'switch') {\n localModelValue[fieldName] = 'N'\n } else {\n localModelValue[fieldName] = ''\n }\n \n // localModelValue 변경 후 상위로 emit하여 JDynamicForm에도 반영\n isInternalUpdate = true\n emit('update:modelValue', { ...localModelValue })\n }\n}\n</script>\n\n<style scoped>\n/* 필요시 스타일 추가 */\n</style>\n\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","isExpanded","localModelValue","reactive","isInternalUpdate","watch","newValue","key","handleFormValueUpdate","value","allFields","computed","fields","section","step","conditionBadges","badges","formState","field","displayValue","option","opt","handleSubmit","values","handleReset","handleFieldReset","fieldName","f","_createBlock","_unref","Card","_createVNode","CardHeader","_createElementVNode","_hoisted_1","_hoisted_2","_createElementBlock","_cache","$event","ChevronDown","_createTextVNode","CardTitle","_openBlock","_hoisted_3","_Fragment","_renderList","badge","JBadge","_toDisplayString","_withModifiers","X","JButton","CardContent","JDynamicForm","_vShow"],"mappings":"g5DA4FA,MAAMA,EAAQC,EAMRC,EAAOC,EAMPC,EAAiBC,EAAAA,IAA4D,IAAI,EACjFC,EAAaD,EAAAA,IAAI,CAACL,EAAM,gBAAgB,EAGxCO,EAAkBC,EAAAA,SAA8BR,EAAM,WAAa,CAAE,GAAGA,EAAM,UAAA,EAAe,EAAE,EAGrG,IAAIS,EAAmB,GAGvBC,EAAAA,MACE,IAAMV,EAAM,WACXW,GAAa,CACRA,GAAY,CAACF,IAEf,OAAO,KAAKF,CAAe,EAAE,QAAQK,GAAO,CACpCA,KAAOD,GACX,OAAOJ,EAAgBK,CAAG,CAE9B,CAAC,EAED,OAAO,OAAOL,EAAiBI,CAAQ,GAEzCF,EAAmB,EACrB,EACA,CAAE,KAAM,GAAM,UAAW,EAAA,CAAK,EAIhC,SAASI,EAAsBC,EAA4B,CAEzDL,EAAmB,GACnB,OAAO,OAAOF,EAAiBO,CAAK,EAEpCZ,EAAK,oBAAqB,CAAE,GAAGY,EAAO,CACxC,CAGA,MAAMC,EAAYC,EAAAA,SAAS,IAA0B,CACnD,GAAI,CAAChB,EAAM,OAAQ,MAAO,CAAA,EAE1B,MAAMiB,EAA6B,CAAA,EACnC,OAAIjB,EAAM,OAAO,OAAS,UAAYA,EAAM,OAAO,OACjDiB,EAAO,KAAK,GAAGjB,EAAM,OAAO,MAAM,EACzBA,EAAM,OAAO,OAAS,aAAeA,EAAM,OAAO,SAC3DA,EAAM,OAAO,SAAS,QAAQkB,GAAW,CACnCA,EAAQ,QAAQD,EAAO,KAAK,GAAGC,EAAQ,MAAM,CACnD,CAAC,EACQlB,EAAM,OAAO,OAAS,UAAYA,EAAM,OAAO,OACxDA,EAAM,OAAO,MAAM,QAAQmB,GAAQ,CAC7BA,EAAK,QAAQF,EAAO,KAAK,GAAGE,EAAK,MAAM,CAC7C,CAAC,EAEIF,CACT,CAAC,EAGKG,EAAkBJ,EAAAA,SAAS,IAAwB,CACvD,GAAI,CAACT,GAAmB,CAACP,EAAM,OAC7B,MAAO,CAAA,EAGT,MAAMqB,EAA2B,CAAA,EAC3BC,EAAYf,EAElB,OAAAQ,EAAU,MAAM,QAASQ,GAAU,CACjC,MAAMT,EAAQQ,EAAUC,EAAM,WAAW,EAGzC,GAEET,GAAU,MACVA,IAAU,IACVA,IAAU,OACVA,IAAU,UACTS,EAAM,OAAS,YAAcT,IAAU,KACvCS,EAAM,OAAS,UAAYT,IAAU,IAEtC,OAIF,IAAIU,EAAe,OAAOV,CAAK,EAG/B,IAAKS,EAAM,OAAS,SAAWA,EAAM,OAAS,gBAAkBA,EAAM,QAAS,CAC7E,MAAME,EAASF,EAAM,QAAQ,KAAKG,GAAOA,EAAI,QAAUZ,CAAK,EACxDW,IACFD,EAAeC,EAAO,MAE1B,CAGIF,EAAM,OAAS,YAAcA,EAAM,OAAS,SAC1CT,IAAU,KACZO,EAAO,KAAK,CACV,UAAWE,EAAM,YACjB,MAAOA,EAAM,MACb,MAAOA,EAAM,aAAeA,EAAM,KAAA,CACnC,EAGHF,EAAO,KAAK,CACV,UAAWE,EAAM,YACjB,MAAOA,EAAM,MACb,MAAOC,CAAA,CACR,CAEL,CAAC,EAEMH,CACT,CAAC,EAGD,SAASM,EAAaC,EAA6B,CACjD1B,EAAK,SAAU0B,CAAM,CACvB,CAGA,SAASC,GAAc,CACjBzB,EAAe,QACjBA,EAAe,MAAM,MAAA,EACrBF,EAAK,OAAO,EAEhB,CAGA,SAAS4B,EAAiBC,EAAmB,CAC3C,GAAI,CAACxB,GAAmB,CAACP,EAAM,OAAQ,OAEvC,MAAMuB,EAAQR,EAAU,MAAM,KAAKiB,GAAKA,EAAE,cAAgBD,CAAS,EAE/DR,IAEEA,EAAM,OAAS,YAAcA,EAAM,OAAS,SAC9ChB,EAAgBwB,CAAS,EAAI,IAE7BxB,EAAgBwB,CAAS,EAAI,GAI/BtB,EAAmB,GACnBP,EAAK,oBAAqB,CAAE,GAAGK,EAAiB,EAEpD,6BAvPE0B,EAAAA,YA4DOC,EAAAA,MAAAC,EAAAA,OAAA,EAAA,CA5DD,MAAM,UAAQ,mBAElB,IA8Ca,CA9CbC,EAAAA,YA8CaF,EAAAA,MAAAG,EAAAA,OAAA,EAAA,CA9CD,MAAM,kBAAgB,mBAChC,IA4CM,CA5CNC,EAAAA,mBA4CM,MA5CNC,EA4CM,CA3CJD,EAAAA,mBAkCM,MAlCNE,EAkCM,CAhCIvC,EAAA,2BADRwC,EAAAA,mBAUS,SAAA,OARP,KAAK,SACJ,QAAKC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAErC,EAAA,MAAU,CAAIA,EAAA,OACtB,MAAM,4EAAA,GAEN8B,cAEEF,EAAAA,MAAAU,EAAAA,WAAA,EAAA,CADC,uDAAwCtC,EAAA,MAAU,WAAA,YAAA,CAAA,CAAA,oBACnDuC,EAAAA,gBAAA,sBACC5C,EAAA,KAAK,EAAA,CAAA,CAAA,mBAEVgC,EAAAA,YAAsDC,EAAAA,MAAAY,EAAAA,OAAA,EAAA,OAApC,MAAM,MAAA,qBAAO,IAAW,qCAAR7C,EAAA,KAAK,EAAA,CAAA,CAAA,UAG5BmB,EAAA,MAAgB,OAAM,GAAjC2B,EAAAA,YAAAN,EAAAA,mBAkBM,MAlBNO,EAkBM,kBAjBJP,EAAAA,mBAgBSQ,EAAAA,SAAA,KAAAC,EAAAA,WAfS9B,EAAA,MAAT+B,kBADTlB,EAAAA,YAgBSC,EAAAA,MAAAkB,EAAAA,OAAA,EAAA,CAdN,IAAKD,EAAM,UACZ,QAAQ,YACR,KAAK,KACL,MAAM,gCAAA,qBAEN,IAAiD,CAAjDb,EAAAA,mBAAiD,OAAA,KAAAe,EAAAA,gBAAxCF,EAAM,KAAK,EAAG,KAAEE,EAAAA,gBAAGF,EAAM,KAAK,EAAA,CAAA,EACvCb,EAAAA,mBAOS,SAAA,CANP,KAAK,SACJ,QAAKgB,EAAAA,cAAAX,GAAOb,EAAiBqB,EAAM,SAAS,EAAA,CAAA,MAAA,CAAA,EAC7C,MAAM,yHACL,aAAU,GAAKA,EAAM,KAAK,QAAA,GAE3Bf,EAAAA,YAAqBF,EAAAA,MAAAqB,EAAAA,CAAA,EAAA,CAAlB,MAAM,UAAS,CAAA,6DAM1BnB,cAMUF,EAAAA,MAAAsB,EAAAA,OAAA,EAAA,CALR,QAAQ,UACR,KAAK,KACJ,wBAAY3B,EAAW,CAAA,MAAA,CAAA,CAAA,qBACzB,IAED,CAAA,GAAAa,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,mBAFC,QAED,EAAA,CAAA,sCAKJN,EAAAA,YAQcF,QAAAuB,EAAAA,OAAA,EAAA,CARmC,MAAM,kBAAgB,mBACrE,IAME,CANFrB,EAAAA,YAMEsB,EAAAA,QAAA,SALI,iBAAJ,IAAItD,EACH,OAAQH,EAAA,OACR,cAAaM,EACb,sBAAoBM,EACpB,SAAQc,CAAA,gDANQ,CAAAgC,EAAAA,MAAArD,EAAA,QAAeL,EAAA,WAAW,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent as L, ref as V, reactive as z, watch as D, computed as C, createBlock as v, openBlock as n, unref as i, withCtx as m, createVNode as c, withDirectives as R, createElementVNode as d, createElementBlock as y, createCommentVNode as
|
|
1
|
+
import { defineComponent as L, ref as V, reactive as z, watch as D, computed as C, createBlock as v, openBlock as n, unref as i, withCtx as m, createVNode as c, withDirectives as R, createElementVNode as d, createElementBlock as y, createCommentVNode as J, createTextVNode as x, normalizeClass as O, toDisplayString as h, Fragment as U, renderList as M, withModifiers as g, vShow as T } from "vue";
|
|
2
2
|
import { ChevronDown as A, X as I } from "lucide-vue-next";
|
|
3
3
|
import "../shadcn/index.js";
|
|
4
4
|
import P from "../atoms/JButton.vue.js";
|
|
@@ -22,6 +22,8 @@ import "ag-grid-enterprise";
|
|
|
22
22
|
/* empty css */
|
|
23
23
|
/* empty css */
|
|
24
24
|
/* empty css */
|
|
25
|
+
/* empty css */
|
|
26
|
+
/* empty css */
|
|
25
27
|
import "vue-sonner";
|
|
26
28
|
import Y from "./JDynamicForm.vue.js";
|
|
27
29
|
import q from "../shadcn/Card.vue.js";
|
|
@@ -31,7 +33,7 @@ import K from "../shadcn/CardContent.vue.js";
|
|
|
31
33
|
const Q = { class: "flex items-center justify-between" }, W = { class: "flex items-center gap-3 flex-1" }, Z = {
|
|
32
34
|
key: 2,
|
|
33
35
|
class: "flex flex-wrap items-center gap-2 ml-2"
|
|
34
|
-
}, ee = ["onClick", "aria-label"],
|
|
36
|
+
}, ee = ["onClick", "aria-label"], Le = /* @__PURE__ */ L({
|
|
35
37
|
__name: "JSearchPanel",
|
|
36
38
|
props: {
|
|
37
39
|
title: { default: "조회조건" },
|
|
@@ -42,34 +44,34 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
42
44
|
},
|
|
43
45
|
emits: ["update:modelValue", "submit", "reset"],
|
|
44
46
|
setup(r, { emit: E }) {
|
|
45
|
-
const
|
|
47
|
+
const l = r, u = E, b = V(null), p = V(!l.defaultCollapsed), a = z(l.modelValue ? { ...l.modelValue } : {});
|
|
46
48
|
let f = !1;
|
|
47
49
|
D(
|
|
48
|
-
() =>
|
|
50
|
+
() => l.modelValue,
|
|
49
51
|
(t) => {
|
|
50
|
-
t && !f && (Object.keys(a).forEach((
|
|
51
|
-
|
|
52
|
+
t && !f && (Object.keys(a).forEach((o) => {
|
|
53
|
+
o in t || delete a[o];
|
|
52
54
|
}), Object.assign(a, t)), f = !1;
|
|
53
55
|
},
|
|
54
56
|
{ deep: !0, immediate: !0 }
|
|
55
57
|
);
|
|
56
|
-
function
|
|
58
|
+
function S(t) {
|
|
57
59
|
f = !0, Object.assign(a, t), u("update:modelValue", { ...t });
|
|
58
60
|
}
|
|
59
61
|
const _ = C(() => {
|
|
60
|
-
if (!
|
|
62
|
+
if (!l.schema) return [];
|
|
61
63
|
const t = [];
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
}) :
|
|
65
|
-
|
|
64
|
+
return l.schema.type === "simple" && l.schema.fields ? t.push(...l.schema.fields) : l.schema.type === "sectioned" && l.schema.sections ? l.schema.sections.forEach((o) => {
|
|
65
|
+
o.fields && t.push(...o.fields);
|
|
66
|
+
}) : l.schema.type === "wizard" && l.schema.steps && l.schema.steps.forEach((o) => {
|
|
67
|
+
o.fields && t.push(...o.fields);
|
|
66
68
|
}), t;
|
|
67
69
|
}), k = C(() => {
|
|
68
|
-
if (!a || !
|
|
70
|
+
if (!a || !l.schema)
|
|
69
71
|
return [];
|
|
70
|
-
const t = [],
|
|
72
|
+
const t = [], o = a;
|
|
71
73
|
return _.value.forEach((e) => {
|
|
72
|
-
const s =
|
|
74
|
+
const s = o[e.controlName];
|
|
73
75
|
if (s == null || s === "" || s === "ALL" || s === "SELECT" || e.type === "checkbox" && s === "N" || e.type === "switch" && s === "N")
|
|
74
76
|
return;
|
|
75
77
|
let w = String(s);
|
|
@@ -88,18 +90,18 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
88
90
|
});
|
|
89
91
|
}), t;
|
|
90
92
|
});
|
|
91
|
-
function
|
|
93
|
+
function $(t) {
|
|
92
94
|
u("submit", t);
|
|
93
95
|
}
|
|
94
|
-
function
|
|
96
|
+
function B() {
|
|
95
97
|
b.value && (b.value.reset(), u("reset"));
|
|
96
98
|
}
|
|
97
|
-
function
|
|
98
|
-
if (!a || !
|
|
99
|
-
const
|
|
100
|
-
|
|
99
|
+
function F(t) {
|
|
100
|
+
if (!a || !l.schema) return;
|
|
101
|
+
const o = _.value.find((e) => e.controlName === t);
|
|
102
|
+
o && (o.type === "checkbox" || o.type === "switch" ? a[t] = "N" : a[t] = "", f = !0, u("update:modelValue", { ...a }));
|
|
101
103
|
}
|
|
102
|
-
return (t,
|
|
104
|
+
return (t, o) => (n(), v(i(q), { class: "w-full" }, {
|
|
103
105
|
default: m(() => [
|
|
104
106
|
c(i(G), { class: "pt-4 pb-3 px-6" }, {
|
|
105
107
|
default: m(() => [
|
|
@@ -108,11 +110,11 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
108
110
|
r.collapsible ? (n(), y("button", {
|
|
109
111
|
key: 0,
|
|
110
112
|
type: "button",
|
|
111
|
-
onClick:
|
|
113
|
+
onClick: o[0] || (o[0] = (e) => p.value = !p.value),
|
|
112
114
|
class: "flex items-center gap-2 font-semibold hover:text-primary transition-colors"
|
|
113
115
|
}, [
|
|
114
116
|
c(i(A), {
|
|
115
|
-
class:
|
|
117
|
+
class: O(["h-4 w-4 transition-transform", p.value ? "rotate-0" : "-rotate-90"])
|
|
116
118
|
}, null, 8, ["class"]),
|
|
117
119
|
x(" " + h(r.title), 1)
|
|
118
120
|
])) : (n(), v(i(H), {
|
|
@@ -125,7 +127,7 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
125
127
|
_: 1
|
|
126
128
|
})),
|
|
127
129
|
k.value.length > 0 ? (n(), y("div", Z, [
|
|
128
|
-
(n(!0), y(
|
|
130
|
+
(n(!0), y(U, null, M(k.value, (e) => (n(), v(i(X), {
|
|
129
131
|
key: e.fieldName,
|
|
130
132
|
variant: "secondary",
|
|
131
133
|
size: "sm",
|
|
@@ -135,7 +137,7 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
135
137
|
d("span", null, h(e.label) + ": " + h(e.value), 1),
|
|
136
138
|
d("button", {
|
|
137
139
|
type: "button",
|
|
138
|
-
onClick: g((s) =>
|
|
140
|
+
onClick: g((s) => F(e.fieldName), ["stop"]),
|
|
139
141
|
class: "h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center",
|
|
140
142
|
"aria-label": `${e.label} 조건 제거`
|
|
141
143
|
}, [
|
|
@@ -144,14 +146,14 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
144
146
|
]),
|
|
145
147
|
_: 2
|
|
146
148
|
}, 1024))), 128))
|
|
147
|
-
])) :
|
|
149
|
+
])) : J("", !0)
|
|
148
150
|
]),
|
|
149
151
|
c(i(P), {
|
|
150
152
|
variant: "outline",
|
|
151
153
|
size: "sm",
|
|
152
|
-
onClick: g(
|
|
154
|
+
onClick: g(B, ["stop"])
|
|
153
155
|
}, {
|
|
154
|
-
default: m(() => [...
|
|
156
|
+
default: m(() => [...o[1] || (o[1] = [
|
|
155
157
|
x(" 초기화 ", -1)
|
|
156
158
|
])]),
|
|
157
159
|
_: 1
|
|
@@ -167,8 +169,8 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
167
169
|
ref: b,
|
|
168
170
|
schema: r.schema,
|
|
169
171
|
"model-value": a,
|
|
170
|
-
"onUpdate:modelValue":
|
|
171
|
-
onSubmit:
|
|
172
|
+
"onUpdate:modelValue": S,
|
|
173
|
+
onSubmit: $
|
|
172
174
|
}, null, 8, ["schema", "model-value"])
|
|
173
175
|
]),
|
|
174
176
|
_: 1
|
|
@@ -181,6 +183,6 @@ const Q = { class: "flex items-center justify-between" }, W = { class: "flex ite
|
|
|
181
183
|
}
|
|
182
184
|
});
|
|
183
185
|
export {
|
|
184
|
-
|
|
186
|
+
Le as default
|
|
185
187
|
};
|
|
186
188
|
//# sourceMappingURL=JSearchPanel.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchPanel.vue2.js","sources":["../../../../src/components/organisms/JSearchPanel.vue"],"sourcesContent":["<template>\n <Card class=\"w-full\">\n <!-- 헤더: 제목, Badge 목록, 초기화 버튼 -->\n <CardHeader class=\"pt-4 pb-3 px-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3 flex-1\">\n <button\n v-if=\"collapsible\"\n type=\"button\"\n @click=\"isExpanded = !isExpanded\"\n class=\"flex items-center gap-2 font-semibold hover:text-primary transition-colors\"\n >\n <ChevronDown\n :class=\"['h-4 w-4 transition-transform', isExpanded ? 'rotate-0' : '-rotate-90']\"\n />\n {{ title }}\n </button>\n <CardTitle v-else class=\"mb-0\">{{ title }}</CardTitle>\n \n <!-- 조건 Badge 목록 -->\n <div v-if=\"conditionBadges.length > 0\" class=\"flex flex-wrap items-center gap-2 ml-2\">\n <JBadge\n v-for=\"badge in conditionBadges\"\n :key=\"badge.fieldName\"\n variant=\"secondary\"\n size=\"sm\"\n class=\"flex items-center gap-1.5 pr-1\"\n >\n <span>{{ badge.label }}: {{ badge.value }}</span>\n <button\n type=\"button\"\n @click.stop=\"handleFieldReset(badge.fieldName)\"\n class=\"h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center\"\n :aria-label=\"`${badge.label} 조건 제거`\"\n >\n <X class=\"h-3 w-3\" />\n </button>\n </JBadge>\n </div>\n </div>\n \n <JButton\n variant=\"outline\"\n size=\"sm\"\n @click.stop=\"handleReset\"\n >\n 초기화\n </JButton>\n </div>\n </CardHeader>\n \n <!-- 폼 내용 -->\n <CardContent v-show=\"isExpanded || !collapsible\" class=\"px-6 pb-6 pt-0\">\n <JDynamicForm\n ref=\"dynamicFormRef\"\n :schema=\"schema\"\n :model-value=\"localModelValue\"\n @update:model-value=\"handleFormValueUpdate\"\n @submit=\"handleSubmit\"\n />\n </CardContent>\n </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, reactive, watch } from 'vue'\nimport { ChevronDown, X } from 'lucide-vue-next'\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/shadcn'\nimport { JButton, JBadge } from '@/components/atoms'\nimport JDynamicForm from './JDynamicForm.vue'\nimport type { FormSchema, DynamicFormField } from '@/types/dynamic-form'\nimport type { ComponentPublicInstance } from 'vue'\n\ninterface ConditionBadge {\n fieldName: string\n label: string\n value: string\n}\n\nexport interface JSearchPanelProps {\n /** 패널 제목 */\n title?: string\n /** JDynamicForm에 전달할 FormSchema */\n schema: FormSchema\n /** JDynamicForm의 v-model 값 */\n modelValue?: Record<string, any>\n /** 기본 접힘 상태 */\n defaultCollapsed?: boolean\n /** 접기/펼치기 가능 여부 */\n collapsible?: boolean\n}\n\nconst props = withDefaults(defineProps<JSearchPanelProps>(), {\n title: '조회조건',\n defaultCollapsed: false,\n collapsible: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Record<string, any>]\n 'submit': [values: Record<string, any>]\n 'reset': []\n}>()\n\nconst dynamicFormRef = ref<ComponentPublicInstance & { reset: () => void } | null>(null)\nconst isExpanded = ref(!props.defaultCollapsed)\n\n// 로컬 modelValue - reactive로 관리하여 양방향 바인딩\nconst localModelValue = reactive<Record<string, any>>(props.modelValue ? { ...props.modelValue } : {})\n\n// 내부 변경인지 외부 변경인지 구분하는 플래그\nlet isInternalUpdate = false\n\n// props.modelValue 변경 시 localModelValue 동기화 (외부 변경)\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue && !isInternalUpdate) {\n // 기존 키 중 새 값에 없는 것은 삭제\n Object.keys(localModelValue).forEach(key => {\n if (!(key in newValue)) {\n delete localModelValue[key]\n }\n })\n // 새 값으로 업데이트\n Object.assign(localModelValue, newValue)\n }\n isInternalUpdate = false\n },\n { deep: true, immediate: true }\n)\n\n// JDynamicForm에서 값이 변경되었을 때 처리\nfunction handleFormValueUpdate(value: Record<string, any>) {\n // JDynamicForm에서 emit된 값을 localModelValue에 반영\n isInternalUpdate = true\n Object.assign(localModelValue, value)\n // 상위로 emit\n emit('update:modelValue', { ...value })\n}\n\n// 모든 필드 가져오기\nconst allFields = computed((): DynamicFormField[] => {\n if (!props.schema) return []\n \n const fields: DynamicFormField[] = []\n if (props.schema.type === 'simple' && props.schema.fields) {\n fields.push(...props.schema.fields)\n } else if (props.schema.type === 'sectioned' && props.schema.sections) {\n props.schema.sections.forEach(section => {\n if (section.fields) fields.push(...section.fields)\n })\n } else if (props.schema.type === 'wizard' && props.schema.steps) {\n props.schema.steps.forEach(step => {\n if (step.fields) fields.push(...step.fields)\n })\n }\n return fields\n})\n\n// 조건 Badge 목록 생성\nconst conditionBadges = computed((): ConditionBadge[] => {\n if (!localModelValue || !props.schema) {\n return []\n }\n\n const badges: ConditionBadge[] = []\n const formState = localModelValue\n\n allFields.value.forEach((field) => {\n const value = formState[field.controlName]\n \n // 빈 값 체크 (빈 문자열, null, undefined, 'ALL', 'SELECT' 제외)\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n value === 'ALL' ||\n value === 'SELECT' ||\n (field.type === 'checkbox' && value === 'N') ||\n (field.type === 'switch' && value === 'N')\n ) {\n return\n }\n\n // 필드 타입에 따라 값 표시\n let displayValue = String(value)\n\n // 콤보/검색콤보인 경우 옵션의 label 찾기\n if ((field.type === 'combo' || field.type === 'searchcombo') && field.options) {\n const option = field.options.find(opt => opt.value === value)\n if (option) {\n displayValue = option.label\n }\n }\n\n // 체크박스/스위치는 'Y'일 때만 표시\n if (field.type === 'checkbox' || field.type === 'switch') {\n if (value === 'Y') {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: field.inlineLabel || field.label\n })\n }\n } else {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: displayValue\n })\n }\n })\n\n return badges\n})\n\n// submit 핸들러\nfunction handleSubmit(values: Record<string, any>) {\n emit('submit', values)\n}\n\n// 전체 초기화 핸들러\nfunction handleReset() {\n if (dynamicFormRef.value) {\n dynamicFormRef.value.reset()\n emit('reset')\n }\n}\n\n// 필드별 초기화 핸들러\nfunction handleFieldReset(fieldName: string) {\n if (!localModelValue || !props.schema) return\n \n const field = allFields.value.find(f => f.controlName === fieldName)\n \n if (field) {\n // 필드 타입에 따라 초기값 설정 - reactive 객체 직접 수정\n if (field.type === 'checkbox' || field.type === 'switch') {\n localModelValue[fieldName] = 'N'\n } else {\n localModelValue[fieldName] = ''\n }\n \n // localModelValue 변경 후 상위로 emit하여 JDynamicForm에도 반영\n isInternalUpdate = true\n emit('update:modelValue', { ...localModelValue })\n }\n}\n</script>\n\n<style scoped>\n/* 필요시 스타일 추가 */\n</style>\n\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","isExpanded","localModelValue","reactive","isInternalUpdate","watch","newValue","key","handleFormValueUpdate","value","allFields","computed","fields","section","step","conditionBadges","badges","formState","field","displayValue","option","opt","handleSubmit","values","handleReset","handleFieldReset","fieldName","f","_createBlock","_unref","Card","_createVNode","CardHeader","_createElementVNode","_hoisted_1","_hoisted_2","_createElementBlock","_cache","$event","ChevronDown","_createTextVNode","CardTitle","_openBlock","_hoisted_3","_Fragment","_renderList","badge","JBadge","_toDisplayString","_withModifiers","X","JButton","CardContent","JDynamicForm","_vShow"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JSearchPanel.vue2.js","sources":["../../../../src/components/organisms/JSearchPanel.vue"],"sourcesContent":["<template>\n <Card class=\"w-full\">\n <!-- 헤더: 제목, Badge 목록, 초기화 버튼 -->\n <CardHeader class=\"pt-4 pb-3 px-6\">\n <div class=\"flex items-center justify-between\">\n <div class=\"flex items-center gap-3 flex-1\">\n <button\n v-if=\"collapsible\"\n type=\"button\"\n @click=\"isExpanded = !isExpanded\"\n class=\"flex items-center gap-2 font-semibold hover:text-primary transition-colors\"\n >\n <ChevronDown\n :class=\"['h-4 w-4 transition-transform', isExpanded ? 'rotate-0' : '-rotate-90']\"\n />\n {{ title }}\n </button>\n <CardTitle v-else class=\"mb-0\">{{ title }}</CardTitle>\n \n <!-- 조건 Badge 목록 -->\n <div v-if=\"conditionBadges.length > 0\" class=\"flex flex-wrap items-center gap-2 ml-2\">\n <JBadge\n v-for=\"badge in conditionBadges\"\n :key=\"badge.fieldName\"\n variant=\"secondary\"\n size=\"sm\"\n class=\"flex items-center gap-1.5 pr-1\"\n >\n <span>{{ badge.label }}: {{ badge.value }}</span>\n <button\n type=\"button\"\n @click.stop=\"handleFieldReset(badge.fieldName)\"\n class=\"h-4 w-4 rounded-full hover:bg-destructive/20 hover:text-destructive transition-colors flex items-center justify-center\"\n :aria-label=\"`${badge.label} 조건 제거`\"\n >\n <X class=\"h-3 w-3\" />\n </button>\n </JBadge>\n </div>\n </div>\n \n <JButton\n variant=\"outline\"\n size=\"sm\"\n @click.stop=\"handleReset\"\n >\n 초기화\n </JButton>\n </div>\n </CardHeader>\n \n <!-- 폼 내용 -->\n <CardContent v-show=\"isExpanded || !collapsible\" class=\"px-6 pb-6 pt-0\">\n <JDynamicForm\n ref=\"dynamicFormRef\"\n :schema=\"schema\"\n :model-value=\"localModelValue\"\n @update:model-value=\"handleFormValueUpdate\"\n @submit=\"handleSubmit\"\n />\n </CardContent>\n </Card>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, reactive, watch } from 'vue'\nimport { ChevronDown, X } from 'lucide-vue-next'\nimport { Card, CardHeader, CardTitle, CardContent } from '@/components/shadcn'\nimport { JButton, JBadge } from '@/components/atoms'\nimport JDynamicForm from './JDynamicForm.vue'\nimport type { FormSchema, DynamicFormField } from '@/types/dynamic-form'\nimport type { ComponentPublicInstance } from 'vue'\n\ninterface ConditionBadge {\n fieldName: string\n label: string\n value: string\n}\n\nexport interface JSearchPanelProps {\n /** 패널 제목 */\n title?: string\n /** JDynamicForm에 전달할 FormSchema */\n schema: FormSchema\n /** JDynamicForm의 v-model 값 */\n modelValue?: Record<string, any>\n /** 기본 접힘 상태 */\n defaultCollapsed?: boolean\n /** 접기/펼치기 가능 여부 */\n collapsible?: boolean\n}\n\nconst props = withDefaults(defineProps<JSearchPanelProps>(), {\n title: '조회조건',\n defaultCollapsed: false,\n collapsible: true,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Record<string, any>]\n 'submit': [values: Record<string, any>]\n 'reset': []\n}>()\n\nconst dynamicFormRef = ref<ComponentPublicInstance & { reset: () => void } | null>(null)\nconst isExpanded = ref(!props.defaultCollapsed)\n\n// 로컬 modelValue - reactive로 관리하여 양방향 바인딩\nconst localModelValue = reactive<Record<string, any>>(props.modelValue ? { ...props.modelValue } : {})\n\n// 내부 변경인지 외부 변경인지 구분하는 플래그\nlet isInternalUpdate = false\n\n// props.modelValue 변경 시 localModelValue 동기화 (외부 변경)\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue && !isInternalUpdate) {\n // 기존 키 중 새 값에 없는 것은 삭제\n Object.keys(localModelValue).forEach(key => {\n if (!(key in newValue)) {\n delete localModelValue[key]\n }\n })\n // 새 값으로 업데이트\n Object.assign(localModelValue, newValue)\n }\n isInternalUpdate = false\n },\n { deep: true, immediate: true }\n)\n\n// JDynamicForm에서 값이 변경되었을 때 처리\nfunction handleFormValueUpdate(value: Record<string, any>) {\n // JDynamicForm에서 emit된 값을 localModelValue에 반영\n isInternalUpdate = true\n Object.assign(localModelValue, value)\n // 상위로 emit\n emit('update:modelValue', { ...value })\n}\n\n// 모든 필드 가져오기\nconst allFields = computed((): DynamicFormField[] => {\n if (!props.schema) return []\n \n const fields: DynamicFormField[] = []\n if (props.schema.type === 'simple' && props.schema.fields) {\n fields.push(...props.schema.fields)\n } else if (props.schema.type === 'sectioned' && props.schema.sections) {\n props.schema.sections.forEach(section => {\n if (section.fields) fields.push(...section.fields)\n })\n } else if (props.schema.type === 'wizard' && props.schema.steps) {\n props.schema.steps.forEach(step => {\n if (step.fields) fields.push(...step.fields)\n })\n }\n return fields\n})\n\n// 조건 Badge 목록 생성\nconst conditionBadges = computed((): ConditionBadge[] => {\n if (!localModelValue || !props.schema) {\n return []\n }\n\n const badges: ConditionBadge[] = []\n const formState = localModelValue\n\n allFields.value.forEach((field) => {\n const value = formState[field.controlName]\n \n // 빈 값 체크 (빈 문자열, null, undefined, 'ALL', 'SELECT' 제외)\n if (\n value === undefined ||\n value === null ||\n value === '' ||\n value === 'ALL' ||\n value === 'SELECT' ||\n (field.type === 'checkbox' && value === 'N') ||\n (field.type === 'switch' && value === 'N')\n ) {\n return\n }\n\n // 필드 타입에 따라 값 표시\n let displayValue = String(value)\n\n // 콤보/검색콤보인 경우 옵션의 label 찾기\n if ((field.type === 'combo' || field.type === 'searchcombo') && field.options) {\n const option = field.options.find(opt => opt.value === value)\n if (option) {\n displayValue = option.label\n }\n }\n\n // 체크박스/스위치는 'Y'일 때만 표시\n if (field.type === 'checkbox' || field.type === 'switch') {\n if (value === 'Y') {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: field.inlineLabel || field.label\n })\n }\n } else {\n badges.push({\n fieldName: field.controlName,\n label: field.label,\n value: displayValue\n })\n }\n })\n\n return badges\n})\n\n// submit 핸들러\nfunction handleSubmit(values: Record<string, any>) {\n emit('submit', values)\n}\n\n// 전체 초기화 핸들러\nfunction handleReset() {\n if (dynamicFormRef.value) {\n dynamicFormRef.value.reset()\n emit('reset')\n }\n}\n\n// 필드별 초기화 핸들러\nfunction handleFieldReset(fieldName: string) {\n if (!localModelValue || !props.schema) return\n \n const field = allFields.value.find(f => f.controlName === fieldName)\n \n if (field) {\n // 필드 타입에 따라 초기값 설정 - reactive 객체 직접 수정\n if (field.type === 'checkbox' || field.type === 'switch') {\n localModelValue[fieldName] = 'N'\n } else {\n localModelValue[fieldName] = ''\n }\n \n // localModelValue 변경 후 상위로 emit하여 JDynamicForm에도 반영\n isInternalUpdate = true\n emit('update:modelValue', { ...localModelValue })\n }\n}\n</script>\n\n<style scoped>\n/* 필요시 스타일 추가 */\n</style>\n\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","isExpanded","localModelValue","reactive","isInternalUpdate","watch","newValue","key","handleFormValueUpdate","value","allFields","computed","fields","section","step","conditionBadges","badges","formState","field","displayValue","option","opt","handleSubmit","values","handleReset","handleFieldReset","fieldName","f","_createBlock","_unref","Card","_createVNode","CardHeader","_createElementVNode","_hoisted_1","_hoisted_2","_createElementBlock","_cache","$event","ChevronDown","_createTextVNode","CardTitle","_openBlock","_hoisted_3","_Fragment","_renderList","badge","JBadge","_toDisplayString","_withModifiers","X","JButton","CardContent","JDynamicForm","_vShow"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./JShuttle.vue2.cjs");;/* empty css */const t = (t_comp, t_opts) => {
|
|
2
|
+
const t_merged = t_comp.__vccOpts || t_comp;
|
|
3
|
+
for (const [t_key, t_val] of t_opts)
|
|
4
|
+
t_merged[t_key] = t_val;
|
|
5
|
+
return t_merged;
|
|
6
|
+
};,u=t(e.default,[["__scopeId","data-v-6e1488b8"]]);exports.default=u;
|
|
7
|
+
//# sourceMappingURL=JShuttle.vue.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JShuttle.vue.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import t from "./JShuttle.vue2.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
const o = (o_comp, o_opts) => {
|
|
4
|
+
const o_merged = o_comp.__vccOpts || o_comp;
|
|
5
|
+
for (const [o_key, o_val] of o_opts)
|
|
6
|
+
o_merged[o_key] = o_val;
|
|
7
|
+
return o_merged;
|
|
8
|
+
};
|
|
9
|
+
const p = /* @__PURE__ */ o(t, [["__scopeId", "data-v-6e1488b8"]]);
|
|
10
|
+
export {
|
|
11
|
+
p as default
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=JShuttle.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JShuttle.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),V=require("../atoms/JButton.vue.cjs"),_=require("../atoms/JInput.vue.cjs");require("../shadcn/index.cjs");require("lucide-vue-next");const k=require("../../lib/utils.cjs");require("@internationalized/date");require("md-editor-v3");;/* empty css */;/* empty css */require("../shadcn/badge-variants.cjs");require("@vueuse/core");require("reka-ui");;/* empty css */require("../shadcn/avatar-variants.cjs");const d=require("../atoms/JIcon.vue.cjs");require("dompurify");;/* empty css */const N=require("../atoms/JGrid.vue.cjs");;/* empty css */;/* empty css */require("vue-sonner");const x={class:"j-shuttle-container"},y={class:"j-shuttle-panel"},q={class:"j-shuttle-panel-card"},b={class:"j-shuttle-panel-header"},B={class:"j-shuttle-panel-title"},S={class:"j-shuttle-panel-count"},C={key:0,class:"j-shuttle-search"},R={class:"j-shuttle-grid-wrapper"},T={class:"j-shuttle-panel-footer"},L={class:"text-xs text-muted-foreground"},M={class:"j-shuttle-actions"},U={class:"j-shuttle-actions-buttons"},G={class:"j-shuttle-panel"},J={class:"j-shuttle-panel-card"},F={class:"j-shuttle-panel-header j-shuttle-panel-header--primary"},z={class:"j-shuttle-panel-title"},O={class:"j-shuttle-panel-count j-shuttle-panel-count--primary"},I={key:0,class:"j-shuttle-search"},P={class:"j-shuttle-grid-wrapper"},A={class:"j-shuttle-panel-footer"},H={class:"text-xs text-muted-foreground"},K=e.defineComponent({__name:"JShuttle",props:{leftTitle:{default:"Unmapped"},rightTitle:{default:"Mapped"},leftData:{},rightData:{},columnDefs:{},searchable:{type:Boolean,default:!1},class:{}},emits:["update:leftData","update:rightData","move"],setup(n,{expose:w,emit:D}){const s=n,u=D,r=e.ref([]),o=e.ref([]),c=e.ref(""),i=e.ref(""),m=e.ref(),p=e.ref(),v=e.computed(()=>{if(!s.searchable||!c.value)return s.leftData;const a=c.value.toLowerCase();return s.leftData.filter(t=>Object.values(t).some(l=>String(l).toLowerCase().includes(a)))}),g=e.computed(()=>{if(!s.searchable||!i.value)return s.rightData;const a=i.value.toLowerCase();return s.rightData.filter(t=>Object.values(t).some(l=>String(l).toLowerCase().includes(a)))});function E(){if(r.value.length===0)return;const a=[...r.value],t=s.leftData.filter(f=>!a.some(h=>h.id===f.id)),l=[...s.rightData,...a];u("update:leftData",t),u("update:rightData",l),u("move",{items:a,direction:"toRight"}),r.value=[]}function j(){if(o.value.length===0)return;const a=[...o.value],t=s.rightData.filter(f=>!a.some(h=>h.id===f.id)),l=[...s.leftData,...a];u("update:leftData",l),u("update:rightData",t),u("move",{items:a,direction:"toLeft"}),o.value=[]}return w({leftGridRef:m,rightGridRef:p}),(a,t)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(e.unref(k.cn)("j-shuttle",s.class))},[e.createElementVNode("div",x,[e.createElementVNode("div",y,[e.createElementVNode("div",q,[e.createElementVNode("div",b,[e.createElementVNode("h4",B,e.toDisplayString(n.leftTitle||"Unmapped"),1),e.createElementVNode("span",S,e.toDisplayString(v.value.length)+" items ",1)]),n.searchable?(e.openBlock(),e.createElementBlock("div",C,[e.createVNode(e.unref(_.default),{modelValue:c.value,"onUpdate:modelValue":t[0]||(t[0]=l=>c.value=l),placeholder:"검색..."},{prefix:e.withCtx(()=>[e.createVNode(e.unref(d.default),{name:"search",class:"w-4 h-4 text-muted-foreground"})]),_:1},8,["modelValue"])])):e.createCommentVNode("",!0),e.createElementVNode("div",R,[e.createVNode(e.unref(N.default),{ref_key:"leftGridRef",ref:m,"row-data":v.value,"column-defs":n.columnDefs,checkbox:!0,"row-numbers":!1,pagination:!1,"selected-rows":r.value,"onUpdate:selectedRows":t[1]||(t[1]=l=>r.value=l),class:"h-full"},null,8,["row-data","column-defs","selected-rows"])]),e.createElementVNode("div",T,[e.createElementVNode("span",L,[r.value.length>0?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("strong",null,e.toDisplayString(r.value.length),1),t[4]||(t[4]=e.createTextVNode(" selected ",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(" No items selected ")],64))])])])]),e.createElementVNode("div",M,[t[5]||(t[5]=e.createElementVNode("div",{class:"j-shuttle-actions-divider"},null,-1)),e.createElementVNode("div",U,[e.createVNode(e.unref(V.default),{styletype:"primary",size:"xs",disabled:r.value.length===0,onClick:E,class:"j-shuttle-action-btn",title:"선택한 항목을 오른쪽으로 이동"},{default:e.withCtx(()=>[e.createVNode(e.unref(d.default),{name:"chevronRight",class:"w-3.5 h-3.5"})]),_:1},8,["disabled"]),e.createVNode(e.unref(V.default),{variant:"outline",size:"xs",disabled:o.value.length===0,onClick:j,class:"j-shuttle-action-btn",title:"선택한 항목을 왼쪽으로 이동"},{default:e.withCtx(()=>[e.createVNode(e.unref(d.default),{name:"chevronLeft",class:"w-3.5 h-3.5"})]),_:1},8,["disabled"])])]),e.createElementVNode("div",G,[e.createElementVNode("div",J,[e.createElementVNode("div",F,[e.createElementVNode("h4",z,e.toDisplayString(n.rightTitle||"Mapped"),1),e.createElementVNode("span",O,e.toDisplayString(g.value.length)+" items ",1)]),n.searchable?(e.openBlock(),e.createElementBlock("div",I,[e.createVNode(e.unref(_.default),{modelValue:i.value,"onUpdate:modelValue":t[2]||(t[2]=l=>i.value=l),placeholder:"검색..."},{prefix:e.withCtx(()=>[e.createVNode(e.unref(d.default),{name:"search",class:"w-4 h-4 text-muted-foreground"})]),_:1},8,["modelValue"])])):e.createCommentVNode("",!0),e.createElementVNode("div",P,[e.createVNode(e.unref(N.default),{ref_key:"rightGridRef",ref:p,"row-data":g.value,"column-defs":n.columnDefs,checkbox:!0,"row-numbers":!1,pagination:!1,"selected-rows":o.value,"onUpdate:selectedRows":t[3]||(t[3]=l=>o.value=l),class:"h-full"},null,8,["row-data","column-defs","selected-rows"])]),e.createElementVNode("div",A,[e.createElementVNode("span",H,[o.value.length>0?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("strong",null,e.toDisplayString(o.value.length),1),t[6]||(t[6]=e.createTextVNode(" selected ",-1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(" No items selected ")],64))])])])])])],2))}});exports.default=K;
|
|
2
|
+
//# sourceMappingURL=JShuttle.vue2.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JShuttle.vue2.cjs","sources":["../../../../src/components/organisms/JShuttle.vue"],"sourcesContent":["<template>\n <div :class=\"cn('j-shuttle', props.class)\">\n <div class=\"j-shuttle-container\">\n <!-- 왼쪽 패널 -->\n <div class=\"j-shuttle-panel\">\n <div class=\"j-shuttle-panel-card\">\n <!-- 헤더 -->\n <div class=\"j-shuttle-panel-header\">\n <h4 class=\"j-shuttle-panel-title\">\n {{ leftTitle || 'Unmapped' }}\n </h4>\n <span class=\"j-shuttle-panel-count\">\n {{ filteredLeftData.length }} items\n </span>\n </div>\n\n <!-- 검색 -->\n <div v-if=\"searchable\" class=\"j-shuttle-search\">\n <JInput\n v-model=\"leftSearch\"\n placeholder=\"검색...\"\n >\n <template #prefix>\n <JIcon name=\"search\" class=\"w-4 h-4 text-muted-foreground\" />\n </template>\n </JInput>\n </div>\n\n <!-- 그리드 -->\n <div class=\"j-shuttle-grid-wrapper\">\n <JGrid\n ref=\"leftGridRef\"\n :row-data=\"filteredLeftData\"\n :column-defs=\"columnDefs\"\n :checkbox=\"true\"\n :row-numbers=\"false\"\n :pagination=\"false\"\n v-model:selected-rows=\"leftSelectedRows\"\n class=\"h-full\"\n />\n </div>\n\n <!-- 푸터 (선택 개수) -->\n <div class=\"j-shuttle-panel-footer\">\n <span class=\"text-xs text-muted-foreground\">\n <template v-if=\"leftSelectedRows.length > 0\">\n <strong>{{ leftSelectedRows.length }}</strong> selected\n </template>\n <template v-else>\n No items selected\n </template>\n </span>\n </div>\n </div>\n </div>\n\n <!-- 중앙 버튼 영역 -->\n <div class=\"j-shuttle-actions\">\n <div class=\"j-shuttle-actions-divider\" />\n <div class=\"j-shuttle-actions-buttons\">\n <JButton\n styletype=\"primary\"\n size=\"xs\"\n :disabled=\"leftSelectedRows.length === 0\"\n @click=\"moveToRight\"\n class=\"j-shuttle-action-btn\"\n title=\"선택한 항목을 오른쪽으로 이동\"\n >\n <JIcon name=\"chevronRight\" class=\"w-3.5 h-3.5\" />\n </JButton>\n <JButton\n variant=\"outline\"\n size=\"xs\"\n :disabled=\"rightSelectedRows.length === 0\"\n @click=\"moveToLeft\"\n class=\"j-shuttle-action-btn\"\n title=\"선택한 항목을 왼쪽으로 이동\"\n >\n <JIcon name=\"chevronLeft\" class=\"w-3.5 h-3.5\" />\n </JButton>\n </div>\n </div>\n\n <!-- 오른쪽 패널 -->\n <div class=\"j-shuttle-panel\">\n <div class=\"j-shuttle-panel-card\">\n <!-- 헤더 -->\n <div class=\"j-shuttle-panel-header j-shuttle-panel-header--primary\">\n <h4 class=\"j-shuttle-panel-title\">\n {{ rightTitle || 'Mapped' }}\n </h4>\n <span class=\"j-shuttle-panel-count j-shuttle-panel-count--primary\">\n {{ filteredRightData.length }} items\n </span>\n </div>\n\n <!-- 검색 -->\n <div v-if=\"searchable\" class=\"j-shuttle-search\">\n <JInput\n v-model=\"rightSearch\"\n placeholder=\"검색...\"\n >\n <template #prefix>\n <JIcon name=\"search\" class=\"w-4 h-4 text-muted-foreground\" />\n </template>\n </JInput>\n </div>\n\n <!-- 그리드 -->\n <div class=\"j-shuttle-grid-wrapper\">\n <JGrid\n ref=\"rightGridRef\"\n :row-data=\"filteredRightData\"\n :column-defs=\"columnDefs\"\n :checkbox=\"true\"\n :row-numbers=\"false\"\n :pagination=\"false\"\n v-model:selected-rows=\"rightSelectedRows\"\n class=\"h-full\"\n />\n </div>\n\n <!-- 푸터 (선택 개수) -->\n <div class=\"j-shuttle-panel-footer\">\n <span class=\"text-xs text-muted-foreground\">\n <template v-if=\"rightSelectedRows.length > 0\">\n <strong>{{ rightSelectedRows.length }}</strong> selected\n </template>\n <template v-else>\n No items selected\n </template>\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\nimport { JGrid, JButton, JIcon, JInput } from '@/components/atoms'\nimport { cn } from '@/lib/utils'\nimport type { JShuttleProps, JShuttleEmits, ShuttleItem } from '@/types/shuttle.types'\n\nconst props = withDefaults(defineProps<JShuttleProps>(), {\n searchable: false,\n leftTitle: 'Unmapped',\n rightTitle: 'Mapped',\n})\n\nconst emit = defineEmits<JShuttleEmits>()\n\n// 선택된 행\nconst leftSelectedRows = ref<ShuttleItem[]>([])\nconst rightSelectedRows = ref<ShuttleItem[]>([])\n\n// 검색어\nconst leftSearch = ref('')\nconst rightSearch = ref('')\n\n// 그리드 참조\nconst leftGridRef = ref()\nconst rightGridRef = ref()\n\n// 검색 필터링된 데이터\nconst filteredLeftData = computed(() => {\n if (!props.searchable || !leftSearch.value) {\n return props.leftData\n }\n const search = leftSearch.value.toLowerCase()\n return props.leftData.filter((item) => {\n return Object.values(item).some((val) =>\n String(val).toLowerCase().includes(search)\n )\n })\n})\n\nconst filteredRightData = computed(() => {\n if (!props.searchable || !rightSearch.value) {\n return props.rightData\n }\n const search = rightSearch.value.toLowerCase()\n return props.rightData.filter((item) => {\n return Object.values(item).some((val) =>\n String(val).toLowerCase().includes(search)\n )\n })\n})\n\n// 왼쪽 → 오른쪽 이동\nfunction moveToRight() {\n if (leftSelectedRows.value.length === 0) return\n\n const itemsToMove = [...leftSelectedRows.value]\n const newLeftData = props.leftData.filter(\n (item) => !itemsToMove.some((selected) => selected.id === item.id)\n )\n const newRightData = [...props.rightData, ...itemsToMove]\n\n emit('update:leftData', newLeftData)\n emit('update:rightData', newRightData)\n emit('move', { items: itemsToMove, direction: 'toRight' })\n\n leftSelectedRows.value = []\n}\n\n// 오른쪽 → 왼쪽 이동\nfunction moveToLeft() {\n if (rightSelectedRows.value.length === 0) return\n\n const itemsToMove = [...rightSelectedRows.value]\n const newRightData = props.rightData.filter(\n (item) => !itemsToMove.some((selected) => selected.id === item.id)\n )\n const newLeftData = [...props.leftData, ...itemsToMove]\n\n emit('update:leftData', newLeftData)\n emit('update:rightData', newRightData)\n emit('move', { items: itemsToMove, direction: 'toLeft' })\n\n rightSelectedRows.value = []\n}\n\ndefineExpose({\n leftGridRef,\n rightGridRef,\n})\n</script>\n\n<style scoped>\n.j-shuttle {\n width: 100%;\n height: 100%;\n min-height: 500px;\n}\n\n.j-shuttle-container {\n display: flex;\n gap: 0.5rem;\n height: 100%;\n padding: 0;\n border-radius: 0;\n background: transparent;\n}\n\n.j-shuttle-panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.j-shuttle-panel-card {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: hsl(var(--card));\n border: 1px solid hsl(var(--border));\n border-radius: 0.125rem; /* rounded-sm */\n box-shadow: none;\n overflow: hidden;\n}\n\n.j-shuttle-panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.4rem 1rem;\n border-bottom: 1px solid hsl(var(--border));\n background: hsl(var(--muted) / 0.3);\n transition: background-color 0.2s ease;\n}\n\n.j-shuttle-panel-header--primary {\n background: linear-gradient(135deg,\n hsl(var(--primary) / 0.08) 0%,\n hsl(var(--primary) / 0.02) 100%);\n}\n\n.j-shuttle-panel-title {\n font-size: 0.8125rem;\n font-weight: 600;\n color: hsl(var(--foreground));\n letter-spacing: -0.01em;\n}\n\n.j-shuttle-panel-count {\n font-size: 0.75rem;\n font-weight: 500;\n color: hsl(var(--muted-foreground));\n padding: 0.25rem 0.625rem;\n border-radius: 0.125rem; /* rounded-sm */\n background: hsl(var(--muted));\n border: 1px solid hsl(var(--border) / 0.5);\n}\n\n.j-shuttle-panel-count--primary {\n color: hsl(var(--primary));\n background: hsl(var(--primary) / 0.1);\n border-color: hsl(var(--primary) / 0.2);\n}\n\n.j-shuttle-search {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid hsl(var(--border) / 0.5);\n background: hsl(var(--card));\n}\n\n.j-shuttle-grid-wrapper {\n flex: 1;\n overflow: hidden;\n padding: 0;\n background: hsl(var(--background));\n}\n\n.j-shuttle-panel-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 0.625rem 1rem;\n border-top: 1px solid hsl(var(--border) / 0.5);\n background: hsl(var(--muted) / 0.2);\n min-height: 2.5rem;\n}\n\n.j-shuttle-actions {\n position: relative;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 0;\n min-width: 2.5rem;\n}\n\n.j-shuttle-actions-divider {\n position: absolute;\n width: 1px;\n height: 100%;\n background: linear-gradient(to bottom,\n transparent 0%,\n hsl(var(--border)) 10%,\n hsl(var(--border)) 90%,\n transparent 100%);\n}\n\n.j-shuttle-actions-buttons {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n padding: 0.375rem;\n background: transparent;\n border: none;\n box-shadow: none;\n}\n\n.j-shuttle-action-btn {\n min-width: 2rem;\n min-height: 2rem;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.j-shuttle-action-btn:not(:disabled):hover {\n transform: scale(1.08);\n box-shadow: 0 2px 6px 0 rgb(0 0 0 / 0.12);\n}\n\n.j-shuttle-action-btn:not(:disabled):active {\n transform: scale(1.02);\n}\n\n.j-shuttle-action-btn:disabled {\n opacity: 1;\n background: hsl(var(--muted));\n color: hsl(var(--muted-foreground) / 0.4);\n border-color: hsl(var(--border));\n cursor: not-allowed;\n transform: scale(1);\n}\n\n/* 다크모드 조정 */\n.dark .j-shuttle-container {\n background: linear-gradient(135deg, \n hsl(var(--muted) / 0.2) 0%, \n hsl(var(--muted) / 0.05) 100%);\n}\n\n.dark .j-shuttle-panel-card {\n box-shadow: 0 2px 4px 0 rgb(0 0 0 / 0.2);\n}\n\n.dark .j-shuttle-panel-card:hover {\n box-shadow: 0 4px 6px 0 rgb(0 0 0 / 0.3);\n}\n</style>\n"],"names":["props","__props","emit","__emit","leftSelectedRows","ref","rightSelectedRows","leftSearch","rightSearch","leftGridRef","rightGridRef","filteredLeftData","computed","search","item","val","filteredRightData","moveToRight","itemsToMove","newLeftData","selected","newRightData","moveToLeft","__expose","_createElementBlock","_normalizeClass","_unref","cn","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_toDisplayString","_hoisted_6","_openBlock","_hoisted_7","_createVNode","JInput","$event","JIcon","_hoisted_8","JGrid","_hoisted_9","_hoisted_10","_Fragment","_hoisted_11","_hoisted_12","JButton","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21"],"mappings":"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"}
|