@j-solution/components 1.9.1 → 1.9.3
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 +6 -6
- package/assets/jwms-portal-frontend-BrNxcNUC.css +1 -0
- package/assets/styles/j-components.css +1 -1
- package/assets/styles/main.css +15 -5
- package/assets/styles/themes.css +46 -21
- package/components/atoms/JButton.vue.cjs +1 -1
- package/components/atoms/JButton.vue.js +1 -1
- package/components/atoms/JButton.vue2.cjs.map +1 -1
- package/components/atoms/JButton.vue2.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 +1 -1
- package/components/atoms/JGrid.vue2.cjs.map +1 -1
- package/components/atoms/JGrid.vue2.js +140 -112
- package/components/atoms/JGrid.vue2.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 +1 -1
- 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 +9 -9
- package/components/molecules/JTabs.vue2.js.map +1 -1
- package/components/organisms/JDynamicForm.vue.cjs +1 -1
- package/components/organisms/JDynamicForm.vue.js +2 -2
- package/components/organisms/JDynamicForm.vue2.cjs +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs.map +1 -1
- package/components/organisms/JDynamicForm.vue2.js +5 -5
- 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 +1 -1
- package/components/organisms/JPageContainer.vue.js.map +1 -1
- package/components/organisms/JSearchPanel.vue.cjs +1 -1
- package/components/organisms/JSearchPanel.vue.js +7 -7
- package/components/organisms/JSearchPanel.vue2.cjs +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
- package/components/organisms/JSearchPanel.vue2.js +4 -4
- package/components/organisms/JSearchPanel.vue2.js.map +1 -1
- package/components/shadcn/index.cjs +1 -1
- package/components/shadcn/index.cjs.map +1 -1
- package/components/shadcn/index.js +6 -6
- package/components/shadcn/index.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/types/index.d.ts +87 -6
- package/assets/jwms-portal-frontend-Di6lStzZ.css +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { AgGridVue as
|
|
3
|
-
import { cn as
|
|
4
|
-
import { ModuleRegistry as
|
|
5
|
-
import { AllEnterpriseModule as
|
|
6
|
-
const
|
|
1
|
+
import { defineComponent as A, ref as i, watch as f, onMounted as M, onUnmounted as T, computed as m, createElementBlock as W, openBlock as H, normalizeClass as V, unref as b, createVNode as z } from "vue";
|
|
2
|
+
import { AgGridVue as _ } from "ag-grid-vue3";
|
|
3
|
+
import { cn as I } from "../../lib/utils.js";
|
|
4
|
+
import { ModuleRegistry as O, AllCommunityModule as j, themeQuartz as L } from "ag-grid-community";
|
|
5
|
+
import { AllEnterpriseModule as K } from "ag-grid-enterprise";
|
|
6
|
+
const Z = /* @__PURE__ */ A({
|
|
7
7
|
__name: "JGrid",
|
|
8
8
|
props: {
|
|
9
9
|
class: {},
|
|
@@ -12,6 +12,9 @@ const Q = /* @__PURE__ */ R({
|
|
|
12
12
|
pagination: { type: Boolean, default: !0 },
|
|
13
13
|
checkbox: { type: Boolean, default: !1 },
|
|
14
14
|
rowNumbers: { type: Boolean, default: !0 },
|
|
15
|
+
floatingFilters: { type: Boolean, default: !0 },
|
|
16
|
+
floatingFilter: { type: Boolean, default: void 0 },
|
|
17
|
+
rowNumberWidth: { default: 38 },
|
|
15
18
|
actionButtons: { default: void 0 },
|
|
16
19
|
summaryColumn: { type: Boolean, default: !1 },
|
|
17
20
|
hiddenColumn: { type: Boolean, default: !1 },
|
|
@@ -32,31 +35,44 @@ const Q = /* @__PURE__ */ R({
|
|
|
32
35
|
pivotMode: { type: Boolean, default: !1 }
|
|
33
36
|
},
|
|
34
37
|
emits: ["rowClicked", "rowDoubleClicked", "cellClicked", "selectionChanged", "cellValueChanged", "gridReady", "update:selectedRows"],
|
|
35
|
-
setup(
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
browserColorScheme: "
|
|
38
|
+
setup(g, { expose: y, emit: x }) {
|
|
39
|
+
O.registerModules([j, K]);
|
|
40
|
+
const k = L.withParams({
|
|
41
|
+
browserColorScheme: "light",
|
|
42
|
+
// 네이티브 폼/스크롤바를 라이트 스타일로
|
|
39
43
|
cellHorizontalPaddingScale: 1,
|
|
40
44
|
columnBorder: !0,
|
|
41
45
|
fontSize: 13,
|
|
42
|
-
headerBackgroundColor: "#FFFFFF",
|
|
43
46
|
headerFontWeight: 500,
|
|
44
|
-
headerVerticalPaddingScale: 0.
|
|
47
|
+
headerVerticalPaddingScale: 0.45,
|
|
45
48
|
iconSize: 14,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
rowVerticalPaddingScale: 0.4
|
|
50
|
+
}, "light").withParams({
|
|
51
|
+
browserColorScheme: "dark"
|
|
52
|
+
// 네이티브 폼/스크롤바를 다크 스타일로
|
|
53
|
+
}, "dark"), s = i(typeof document < "u" && document.documentElement.classList.contains("dark")), u = i(null);
|
|
54
|
+
let d = null;
|
|
55
|
+
f(s, (t) => {
|
|
56
|
+
u.value?.setAttribute("data-ag-theme-mode", t ? "dark" : "light");
|
|
57
|
+
}), M(() => {
|
|
58
|
+
u.value?.setAttribute("data-ag-theme-mode", s.value ? "dark" : "light"), d = new MutationObserver(() => {
|
|
59
|
+
s.value = document.documentElement.classList.contains("dark");
|
|
60
|
+
}), d.observe(document.documentElement, { attributes: !0, attributeFilter: ["class"] });
|
|
61
|
+
}), T(() => {
|
|
62
|
+
d?.disconnect();
|
|
63
|
+
});
|
|
64
|
+
const e = g, n = x, a = i(null), h = i(null), P = (t) => {
|
|
65
|
+
const c = e.actionButtons || [], r = t.data, w = c.filter((o) => o.show ? o.show(r) : !0);
|
|
66
|
+
if (w.length === 0)
|
|
51
67
|
return "";
|
|
52
|
-
const
|
|
53
|
-
return
|
|
68
|
+
const p = document.createElement("div");
|
|
69
|
+
return p.className = "flex items-center gap-1", w.forEach((o) => {
|
|
54
70
|
const l = document.createElement("button");
|
|
55
|
-
l.className = "px-2 py-1 text-xs border rounded transition-colors",
|
|
56
|
-
|
|
57
|
-
}),
|
|
58
|
-
}),
|
|
59
|
-
},
|
|
71
|
+
l.className = "px-2 py-1 text-xs border rounded transition-colors", o.styletype === "danger" ? l.className += " bg-red-50 border-red-400 text-red-700 hover:bg-red-100 dark:bg-red-950 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900" : l.className += " bg-gray-50 border-gray-400 text-gray-700 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700", o.tooltip && (l.title = o.tooltip), o.label ? l.textContent = o.label : o.icon && (o.icon === "pencil" ? l.textContent = "수정" : o.icon === "trash2" || o.icon === "trash" ? l.textContent = "삭제" : o.icon === "eye" ? l.textContent = "보기" : o.icon === "copy" ? l.textContent = "복사" : o.icon === "download" ? l.textContent = "다운로드" : o.icon === "circleX" ? l.textContent = "비활성화" : o.icon === "circleCheckBig" ? l.textContent = "활성화" : l.textContent = o.icon), l.addEventListener("click", (F) => {
|
|
72
|
+
F.stopPropagation(), o.onClick(r);
|
|
73
|
+
}), p.appendChild(l);
|
|
74
|
+
}), p;
|
|
75
|
+
}, v = m(() => !e.actionButtons || e.actionButtons.length === 0 ? null : {
|
|
60
76
|
colId: "actionButtons",
|
|
61
77
|
headerName: "작업",
|
|
62
78
|
field: "_actions",
|
|
@@ -69,11 +85,11 @@ const Q = /* @__PURE__ */ R({
|
|
|
69
85
|
resizable: !0,
|
|
70
86
|
suppressNavigable: !0,
|
|
71
87
|
suppressHeaderMenuButton: !0,
|
|
72
|
-
cellRenderer:
|
|
88
|
+
cellRenderer: P,
|
|
73
89
|
cellStyle: { display: "flex", justifyContent: "center", alignItems: "center" }
|
|
74
|
-
}),
|
|
75
|
-
const
|
|
76
|
-
return e.checkbox &&
|
|
90
|
+
}), C = m(() => {
|
|
91
|
+
const t = [];
|
|
92
|
+
return e.checkbox && t.push({
|
|
77
93
|
colId: "rowSelection",
|
|
78
94
|
headerName: "",
|
|
79
95
|
// field와 valueGetter 제거 - AG Grid 공식 방식
|
|
@@ -89,114 +105,126 @@ const Q = /* @__PURE__ */ R({
|
|
|
89
105
|
suppressNavigable: !0,
|
|
90
106
|
suppressHeaderMenuButton: !0,
|
|
91
107
|
cellStyle: { display: "flex", justifyContent: "center", alignItems: "center" }
|
|
92
|
-
}),
|
|
93
|
-
}),
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
108
|
+
}), v.value && t.push(v.value), t.push(...e.columnDefs), t;
|
|
109
|
+
}), B = m(() => {
|
|
110
|
+
const t = e.floatingFilter ?? e.floatingFilters;
|
|
111
|
+
return {
|
|
112
|
+
theme: k,
|
|
113
|
+
pagination: e.pagination,
|
|
114
|
+
defaultColDef: {
|
|
115
|
+
filter: !0,
|
|
116
|
+
floatingFilter: t
|
|
117
|
+
},
|
|
118
|
+
rowSelection: e.checkbox ? "multiple" : void 0,
|
|
119
|
+
// 체크박스 모드일 때 row 클릭으로 선택이 변경되지 않도록 설정
|
|
120
|
+
// 체크박스만으로 선택을 제어하도록 함
|
|
121
|
+
suppressRowClickSelection: e.checkbox,
|
|
122
|
+
// Row Numbers (Enterprise) - AG Grid 표준 방식
|
|
123
|
+
rowNumbers: e.rowNumbers ? {
|
|
124
|
+
minWidth: e.rowNumberWidth,
|
|
125
|
+
width: e.rowNumberWidth
|
|
126
|
+
} : !1,
|
|
127
|
+
// Column Hover Highlight
|
|
128
|
+
columnHoverHighlight: e.columnHover,
|
|
129
|
+
// Enterprise 기능 옵션
|
|
130
|
+
sideBar: e.enableColumnsToolPanel || e.enableGrouping || e.enablePivot ? {
|
|
131
|
+
toolPanels: [
|
|
132
|
+
{
|
|
133
|
+
id: "columns",
|
|
134
|
+
labelDefault: "Columns",
|
|
135
|
+
labelKey: "columns",
|
|
136
|
+
iconKey: "columns",
|
|
137
|
+
toolPanel: "agColumnsToolPanel",
|
|
138
|
+
toolPanelParams: {
|
|
139
|
+
suppressRowGroups: !e.enableGrouping,
|
|
140
|
+
suppressValues: !e.enablePivot,
|
|
141
|
+
suppressPivots: !e.enablePivot,
|
|
142
|
+
suppressPivotMode: !e.enablePivot
|
|
143
|
+
}
|
|
118
144
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
})
|
|
147
|
-
|
|
145
|
+
],
|
|
146
|
+
defaultToolPanel: ""
|
|
147
|
+
// 초기에는 접힌 상태
|
|
148
|
+
} : void 0,
|
|
149
|
+
// Status Bar (Enterprise)
|
|
150
|
+
// compactFooter 모드에서는 Status Bar 비활성화
|
|
151
|
+
statusBar: e.statusBar && !e.compactFooter ? {
|
|
152
|
+
statusPanels: [
|
|
153
|
+
{ statusPanel: "agTotalAndFilteredRowCountComponent", align: "left" },
|
|
154
|
+
{ statusPanel: "agSelectedRowCountComponent", align: "left" },
|
|
155
|
+
{ statusPanel: "agAggregationComponent", align: "right" }
|
|
156
|
+
]
|
|
157
|
+
} : void 0,
|
|
158
|
+
// Row Group Panel 설정 (Enterprise) - 그리드 상단에 드래그 영역 표시
|
|
159
|
+
rowGroupPanelShow: e.rowGroupPanelShow !== "never" ? e.rowGroupPanelShow : void 0,
|
|
160
|
+
// Pivot Panel 설정 (Enterprise) - 피벗 모드용 드래그 영역
|
|
161
|
+
pivotPanelShow: e.pivotPanelShow !== "never" ? e.pivotPanelShow : void 0,
|
|
162
|
+
// Pivot Mode 활성화
|
|
163
|
+
pivotMode: e.pivotMode,
|
|
164
|
+
// 그룹핑 기본 설정
|
|
165
|
+
groupDefaultExpanded: e.groupDefaultExpanded,
|
|
166
|
+
suppressAggFuncInHeader: !1,
|
|
167
|
+
// Tree Data 설정 (Enterprise)
|
|
168
|
+
treeData: e.enableTreeData || void 0,
|
|
169
|
+
getDataPath: e.enableTreeData ? e.getDataPath || ((r) => r.path || []) : void 0,
|
|
170
|
+
autoGroupColumnDef: e.enableTreeData && e.autoGroupColumnDef ? e.autoGroupColumnDef : void 0
|
|
171
|
+
};
|
|
172
|
+
});
|
|
173
|
+
y({
|
|
148
174
|
gridApi: a,
|
|
149
|
-
gridColumnApi:
|
|
175
|
+
gridColumnApi: h,
|
|
150
176
|
exportToExcel: () => {
|
|
151
177
|
a.value && e.enableExcelExport && a.value.exportDataAsExcel({
|
|
152
178
|
fileName: "grid-export.xlsx"
|
|
153
179
|
});
|
|
154
180
|
}
|
|
155
181
|
});
|
|
156
|
-
const
|
|
157
|
-
a.value =
|
|
158
|
-
},
|
|
159
|
-
n("rowClicked",
|
|
160
|
-
},
|
|
161
|
-
n("rowDoubleClicked",
|
|
162
|
-
},
|
|
163
|
-
n("cellClicked",
|
|
164
|
-
},
|
|
165
|
-
n("selectionChanged",
|
|
166
|
-
},
|
|
167
|
-
n("cellValueChanged",
|
|
182
|
+
const D = (t) => {
|
|
183
|
+
a.value = t.api, h.value = t.api, n("gridReady", t);
|
|
184
|
+
}, S = (t) => {
|
|
185
|
+
n("rowClicked", t);
|
|
186
|
+
}, E = (t) => {
|
|
187
|
+
n("rowDoubleClicked", t);
|
|
188
|
+
}, R = (t) => {
|
|
189
|
+
n("cellClicked", t);
|
|
190
|
+
}, G = (t) => {
|
|
191
|
+
n("selectionChanged", t), n("update:selectedRows", t.api.getSelectedRows());
|
|
192
|
+
}, N = (t) => {
|
|
193
|
+
n("cellValueChanged", t);
|
|
168
194
|
};
|
|
169
|
-
return
|
|
195
|
+
return f(
|
|
170
196
|
() => e.columnDefs,
|
|
171
197
|
() => {
|
|
172
|
-
a.value && a.value.setGridOption("columnDefs",
|
|
198
|
+
a.value && a.value.setGridOption("columnDefs", C.value);
|
|
173
199
|
},
|
|
174
200
|
{ deep: !0 }
|
|
175
|
-
),
|
|
201
|
+
), f(
|
|
176
202
|
() => e.rowData,
|
|
177
203
|
() => {
|
|
178
204
|
a.value && a.value.setGridOption("rowData", e.rowData);
|
|
179
205
|
},
|
|
180
206
|
{ deep: !0 }
|
|
181
|
-
), (
|
|
182
|
-
|
|
207
|
+
), (t, c) => (H(), W("div", {
|
|
208
|
+
ref_key: "gridContainerRef",
|
|
209
|
+
ref: u,
|
|
210
|
+
class: V(b(I)("ag-grid-container", e.class))
|
|
183
211
|
}, [
|
|
184
|
-
|
|
185
|
-
"column-defs":
|
|
186
|
-
"row-data":
|
|
187
|
-
"grid-options":
|
|
212
|
+
z(b(_), {
|
|
213
|
+
"column-defs": C.value,
|
|
214
|
+
"row-data": g.rowData,
|
|
215
|
+
"grid-options": B.value,
|
|
188
216
|
style: { height: "100%", width: "100%" },
|
|
189
|
-
onGridReady:
|
|
190
|
-
onRowClicked:
|
|
191
|
-
onRowDoubleClicked:
|
|
192
|
-
onCellClicked:
|
|
193
|
-
onSelectionChanged:
|
|
194
|
-
onCellValueChanged:
|
|
217
|
+
onGridReady: D,
|
|
218
|
+
onRowClicked: S,
|
|
219
|
+
onRowDoubleClicked: E,
|
|
220
|
+
onCellClicked: R,
|
|
221
|
+
onSelectionChanged: G,
|
|
222
|
+
onCellValueChanged: N
|
|
195
223
|
}, null, 8, ["column-defs", "row-data", "grid-options"])
|
|
196
224
|
], 2));
|
|
197
225
|
}
|
|
198
226
|
});
|
|
199
227
|
export {
|
|
200
|
-
|
|
228
|
+
Z as default
|
|
201
229
|
};
|
|
202
230
|
//# sourceMappingURL=JGrid.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JGrid.vue2.js","sources":["../../../../src/components/atoms/JGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { AgGridVue } from 'ag-grid-vue3'\nimport { cn } from '@/lib/utils'\nimport type {\n ColDef,\n GridOptions,\n RowClickedEvent,\n CellClickedEvent,\n SelectionChangedEvent,\n CellValueChangedEvent,\n RowDoubleClickedEvent,\n GridReadyEvent,\n ICellRendererParams,\n} from 'ag-grid-community'\nimport { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community'\n// Enterprise 모듈 import (Grouping, Pivot, Excel Export 등)\nimport { AllEnterpriseModule } from 'ag-grid-enterprise'\n\n// AG Grid 모듈 등록 (Community + Enterprise)\nModuleRegistry.registerModules([AllCommunityModule, AllEnterpriseModule])\n\n// Theme Builder API: JLIS 커스텀 테마 (browserColorScheme: 'inherit' → 다크모드 자동 감지)\nconst jTheme = themeQuartz.withParams({\n browserColorScheme: 'inherit',\n cellHorizontalPaddingScale: 1,\n columnBorder: true,\n fontSize: 13,\n headerBackgroundColor: '#FFFFFF',\n headerFontWeight: 500,\n headerVerticalPaddingScale: 0.7,\n iconSize: 14,\n oddRowBackgroundColor: '#CBE6F175',\n rowVerticalPaddingScale: 0.5,\n})\n\n/**\n * Action Button 정의 타입\n */\nexport type ActionButton = {\n /** 버튼 아이콘 이름 (lucide) - label이 없을 때 기본 텍스트 생성에 사용 */\n icon?: string\n /** 버튼 라벨 */\n label?: string\n /** 툴팁 텍스트 */\n tooltip?: string\n /** 버튼 클릭 핸들러 (rowData 전달) */\n onClick: (rowData: any) => void\n /** 버튼 스타일 타입 */\n styletype?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'\n /** 조건부 표시 함수 (rowData를 받아 boolean 반환) */\n show?: (rowData: any) => boolean\n}\n\nconst props = withDefaults(\n defineProps<{\n /** 추가 클래스 (외부 커스터마이징용) */\n class?: string\n /** 그리드에 표시할 데이터 배열 */\n rowData: any[]\n /** 컬럼 정의 배열 */\n columnDefs: ColDef[]\n /** 페이지네이션 활성화 여부 */\n pagination?: boolean\n /** 체크박스 선택 활성화 여부 */\n checkbox?: boolean\n /** 행 번호 표시 여부 (Enterprise) */\n rowNumbers?: boolean\n /** 행별 액션 버튼 목록 */\n actionButtons?: ActionButton[]\n /** 요약 컬럼 표시 여부 */\n summaryColumn?: boolean\n /** 숨김 컬럼 관리 활성화 여부 */\n hiddenColumn?: boolean\n /** 그룹핑 기능 활성화 여부 (Enterprise) */\n enableGrouping?: boolean\n /** 피벗 기능 활성화 여부 (Enterprise) */\n enablePivot?: boolean\n /** Excel 내보내기 기능 활성화 여부 (Enterprise) */\n enableExcelExport?: boolean\n /** Tree Data 기능 활성화 여부 (Enterprise) */\n enableTreeData?: boolean\n /** Tree Data 계층 경로를 반환하는 함수 */\n getDataPath?: (data: any) => (string | number)[]\n /** Tree Data 그룹 컬럼 정의 */\n autoGroupColumnDef?: ColDef\n /** 선택된 행 데이터 배열 (v-model:selected-rows) */\n selectedRows?: any[]\n /** 컬럼 호버 하이라이트 활성화 여부 */\n columnHover?: boolean\n /** Columns Tool Panel 활성화 여부 (Enterprise) */\n enableColumnsToolPanel?: boolean\n /** Status Bar 활성화 여부 (Enterprise) */\n statusBar?: boolean\n /** 간소화된 Footer 모드 (Status Bar 제거, Pagination만 표시) */\n compactFooter?: boolean\n /** Row Group Panel 표시 여부 ('always' | 'onlyWhenGrouping' | 'never') */\n rowGroupPanelShow?: 'always' | 'onlyWhenGrouping' | 'never'\n /** 그룹 기본 확장 레벨 (-1: 모두 닫힘, 0: 첫 레벨만, 1: 2레벨까지...) */\n groupDefaultExpanded?: number\n /** Pivot Mode Panel 표시 여부 */\n pivotPanelShow?: 'always' | 'onlyWhenPivoting' | 'never'\n /** Pivot Mode 활성화 여부 */\n pivotMode?: boolean\n }>(),\n {\n pagination: true,\n checkbox: false,\n rowNumbers: true,\n actionButtons: undefined,\n summaryColumn: false,\n hiddenColumn: false,\n enableGrouping: true,\n enablePivot: false,\n enableExcelExport: false,\n enableTreeData: false,\n getDataPath: undefined,\n autoGroupColumnDef: undefined,\n selectedRows: () => [],\n columnHover: true,\n enableColumnsToolPanel: true,\n statusBar: true,\n compactFooter: false,\n rowGroupPanelShow: 'never',\n groupDefaultExpanded: -1,\n pivotPanelShow: 'never',\n pivotMode: false,\n },\n)\n\nconst emit = defineEmits<{\n /** 행 클릭 이벤트 */\n rowClicked: [event: RowClickedEvent]\n /** 행 더블클릭 이벤트 */\n rowDoubleClicked: [event: RowDoubleClickedEvent]\n /** 셀 클릭 이벤트 */\n cellClicked: [event: CellClickedEvent]\n /** 선택 변경 이벤트 (체크박스 등) */\n selectionChanged: [event: SelectionChangedEvent]\n /** 셀 값 변경 이벤트 */\n cellValueChanged: [event: CellValueChangedEvent]\n /** 그리드 준비 완료 이벤트 */\n gridReady: [event: GridReadyEvent]\n /** 선택된 행 변경 이벤트 (v-model:selected-rows) */\n 'update:selectedRows': [rows: any[]]\n}>()\n\n// ag-Grid 인스턴스 참조\nconst gridApi = ref<any>(null)\nconst gridColumnApi = ref<any>(null)\n\n// Action Buttons Cell Renderer - 함수형으로 DOM 직접 생성\nconst ActionButtonsCellRenderer = (params: ICellRendererParams) => {\n const buttons = props.actionButtons || []\n const rowData = params.data\n \n // 표시할 버튼 필터링\n const visibleButtons = buttons.filter(btn => {\n if (btn.show) {\n return btn.show(rowData)\n }\n return true\n })\n \n if (visibleButtons.length === 0) {\n return ''\n }\n \n // 컨테이너 div 생성\n const container = document.createElement('div')\n container.className = 'flex items-center gap-1'\n \n // 각 버튼 생성\n visibleButtons.forEach((btn) => {\n const button = document.createElement('button')\n button.className = 'px-2 py-1 text-xs border rounded transition-colors'\n \n // styletype에 따른 클래스 추가\n if (btn.styletype === 'danger') {\n button.className += ' bg-red-50 border-red-400 text-red-700 hover:bg-red-100 dark:bg-red-950 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900'\n } else {\n button.className += ' bg-gray-50 border-gray-400 text-gray-700 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700'\n }\n \n // tooltip\n if (btn.tooltip) {\n button.title = btn.tooltip\n }\n \n // 라벨 추가 (텍스트 버튼)\n if (btn.label) {\n button.textContent = btn.label\n } else if (btn.icon) {\n // 라벨이 없으면 기본 텍스트 생성\n if (btn.icon === 'pencil') {\n button.textContent = '수정'\n } else if (btn.icon === 'trash2' || btn.icon === 'trash') {\n button.textContent = '삭제'\n } else if (btn.icon === 'eye') {\n button.textContent = '보기'\n } else if (btn.icon === 'copy') {\n button.textContent = '복사'\n } else if (btn.icon === 'download') {\n button.textContent = '다운로드'\n } else if (btn.icon === 'circleX') {\n button.textContent = '비활성화'\n } else if (btn.icon === 'circleCheckBig') {\n button.textContent = '활성화'\n } else {\n button.textContent = btn.icon\n }\n }\n \n // 클릭 이벤트\n button.addEventListener('click', (e) => {\n e.stopPropagation()\n btn.onClick(rowData)\n })\n \n container.appendChild(button)\n })\n \n return container\n}\n\n// Action Buttons 컬럼 정의\nconst actionButtonsColumn = computed<ColDef | null>(() => {\n if (!props.actionButtons || props.actionButtons.length === 0) {\n return null\n }\n \n return {\n colId: 'actionButtons',\n headerName: '작업',\n field: '_actions',\n width: 120,\n minWidth: 80,\n maxWidth: 200,\n lockPosition: 'left' as const,\n sortable: false,\n filter: false,\n resizable: true,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellRenderer: ActionButtonsCellRenderer,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n }\n})\n\n// checkbox 활성화 및 추가 컬럼 처리\nconst processedColumnDefs = computed(() => {\n const columns: ColDef[] = []\n \n // 1. Checkbox 컬럼 (최우선)\n if (props.checkbox) {\n columns.push({\n colId: 'rowSelection',\n headerName: '',\n // field와 valueGetter 제거 - AG Grid 공식 방식\n width: 50,\n minWidth: 50,\n maxWidth: 50,\n lockPosition: 'left' as const,\n checkboxSelection: true,\n headerCheckboxSelection: true,\n sortable: false,\n filter: false,\n resizable: false,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n })\n }\n \n // 2. Action Buttons 컬럼\n if (actionButtonsColumn.value) {\n columns.push(actionButtonsColumn.value)\n }\n \n // 3. 사용자 정의 컬럼들 (Row Numbers는 AG Grid가 자동으로 추가)\n columns.push(...props.columnDefs)\n \n return columns\n})\n\n// Grid 옵션 설정\nconst gridOptions = computed<GridOptions>(() => {\n const options: GridOptions = {\n theme: jTheme,\n pagination: props.pagination,\n rowSelection: props.checkbox ? 'multiple' : undefined,\n // 체크박스 모드일 때 row 클릭으로 선택이 변경되지 않도록 설정\n // 체크박스만으로 선택을 제어하도록 함\n suppressRowClickSelection: props.checkbox,\n\n // Row Numbers (Enterprise) - AG Grid 표준 방식\n rowNumbers: props.rowNumbers,\n\n // Column Hover Highlight\n columnHoverHighlight: props.columnHover,\n\n // Enterprise 기능 옵션\n sideBar: props.enableColumnsToolPanel || props.enableGrouping || props.enablePivot ? {\n toolPanels: [\n {\n id: 'columns',\n labelDefault: 'Columns',\n labelKey: 'columns',\n iconKey: 'columns',\n toolPanel: 'agColumnsToolPanel',\n toolPanelParams: {\n suppressRowGroups: !props.enableGrouping,\n suppressValues: !props.enablePivot,\n suppressPivots: !props.enablePivot,\n suppressPivotMode: !props.enablePivot,\n },\n },\n ],\n defaultToolPanel: '', // 초기에는 접힌 상태\n } : undefined,\n\n // Status Bar (Enterprise)\n // compactFooter 모드에서는 Status Bar 비활성화\n statusBar: (props.statusBar && !props.compactFooter) ? {\n statusPanels: [\n { statusPanel: 'agTotalAndFilteredRowCountComponent', align: 'left' as const },\n { statusPanel: 'agSelectedRowCountComponent', align: 'left' as const },\n { statusPanel: 'agAggregationComponent', align: 'right' as const },\n ],\n } : undefined,\n\n // Row Group Panel 설정 (Enterprise) - 그리드 상단에 드래그 영역 표시\n rowGroupPanelShow: props.rowGroupPanelShow !== 'never' ? props.rowGroupPanelShow : undefined,\n\n // Pivot Panel 설정 (Enterprise) - 피벗 모드용 드래그 영역\n pivotPanelShow: props.pivotPanelShow !== 'never' ? props.pivotPanelShow : undefined,\n \n // Pivot Mode 활성화\n pivotMode: props.pivotMode,\n\n // 그룹핑 기본 설정\n groupDefaultExpanded: props.groupDefaultExpanded,\n suppressAggFuncInHeader: false,\n\n // Tree Data 설정 (Enterprise)\n treeData: props.enableTreeData || undefined,\n getDataPath: props.enableTreeData\n ? (props.getDataPath || ((data: any) => data.path || []))\n : undefined,\n autoGroupColumnDef: props.enableTreeData && props.autoGroupColumnDef\n ? props.autoGroupColumnDef\n : undefined,\n }\n\n return options\n})\n\n// Excel 내보내기 함수 (외부에서 사용 가능하도록 expose)\nconst exportToExcel = () => {\n if (gridApi.value && props.enableExcelExport) {\n gridApi.value.exportDataAsExcel({\n fileName: 'grid-export.xlsx',\n })\n }\n}\n\n// 그리드 API를 외부에 노출\ndefineExpose({\n gridApi,\n gridColumnApi,\n exportToExcel,\n})\n\n// Grid ready 이벤트 핸들러\nconst onGridReady = (params: GridReadyEvent) => {\n gridApi.value = params.api\n gridColumnApi.value = params.api // v34에서 columnApi는 deprecated\n emit('gridReady', params)\n}\n\n// 행 클릭 이벤트 핸들러\nconst onRowClicked = (event: RowClickedEvent) => {\n emit('rowClicked', event)\n}\n\n// 행 더블클릭 이벤트 핸들러\nconst onRowDoubleClicked = (event: RowDoubleClickedEvent) => {\n emit('rowDoubleClicked', event)\n}\n\n// 셀 클릭 이벤트 핸들러\nconst onCellClicked = (event: CellClickedEvent) => {\n emit('cellClicked', event)\n}\n\n// 선택 변경 이벤트 핸들러\nconst onSelectionChanged = (event: SelectionChangedEvent) => {\n emit('selectionChanged', event)\n emit('update:selectedRows', event.api.getSelectedRows())\n}\n\n// 셀 값 변경 이벤트 핸들러\nconst onCellValueChanged = (event: CellValueChangedEvent) => {\n emit('cellValueChanged', event)\n}\n\n// columnDefs 변경 감지\nwatch(\n () => props.columnDefs,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('columnDefs', processedColumnDefs.value)\n }\n },\n { deep: true },\n)\n\n// rowData 변경 감지\nwatch(\n () => props.rowData,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('rowData', props.rowData)\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div :class=\"cn('ag-grid-container', props.class)\">\n <AgGridVue\n :column-defs=\"processedColumnDefs\"\n :row-data=\"rowData\"\n :grid-options=\"gridOptions\"\n style=\"height: 100%; width: 100%\"\n @grid-ready=\"onGridReady\"\n @row-clicked=\"onRowClicked\"\n @row-double-clicked=\"onRowDoubleClicked\"\n @cell-clicked=\"onCellClicked\"\n @selection-changed=\"onSelectionChanged\"\n @cell-value-changed=\"onCellValueChanged\"\n />\n </div>\n</template>\n\n<style scoped>\n.ag-grid-container {\n width: 100%;\n height: 100%;\n}\n\n/* ============================================\n COMPACT FOOTER: Status Bar + Pagination 통합\n ============================================ */\n\n/* Status Bar 높이 줄이기 */\n:deep(.ag-status-bar) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 0.8125rem;\n}\n\n/* Status Bar 컴포넌트들 높이 조정 */\n:deep(.ag-status-bar-left),\n:deep(.ag-status-bar-center),\n:deep(.ag-status-bar-right) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Status Bar 패널들 간격 조정 */\n:deep(.ag-status-panel) {\n padding: 0;\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Pagination Panel 높이 줄이기 */\n:deep(.ag-paging-panel) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n font-size: 0.8125rem;\n}\n\n/* Pagination 컴포넌트들 높이 조정 */\n:deep(.ag-paging-page-size),\n:deep(.ag-paging-row-summary-panel) {\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Page Size Selector 높이 조정 */\n:deep(.ag-paging-page-size .ag-picker-field) {\n height: 24px;\n min-height: 24px;\n}\n\n:deep(.ag-paging-page-size .ag-picker-field-wrapper) {\n height: 24px;\n padding: 0 4px;\n}\n\n/* Pagination 버튼들 높이 조정 */\n:deep(.ag-paging-button) {\n height: 24px;\n width: 24px;\n padding: 2px;\n}\n\n/* Pagination 버튼 래퍼 */\n:deep(.ag-paging-button-wrapper) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Row summary 텍스트 */\n:deep(.ag-paging-row-summary-panel-number) {\n line-height: 28px;\n}\n\n/* ========================================\n 패턴 9: AG-Grid 스타일 향상\n ======================================== */\n\n:deep(.ag-root-wrapper) {\n border: 1px solid hsl(var(--border));\n border-radius: 0.375rem;\n}\n\n:deep(.ag-header) {\n background-color: hsl(var(--muted));\n border-bottom: 1px solid hsl(var(--border));\n font-weight: 500;\n}\n\n:deep(.ag-header-cell) {\n color: hsl(var(--foreground));\n font-size: 0.75rem;\n padding: 0.5rem;\n}\n\n:deep(.ag-row) {\n transition: background-color 0.2s ease, border-left 0.2s ease;\n cursor: pointer;\n}\n\n:deep(.ag-row:hover) {\n background-color: hsl(var(--primary) / 0.05) !important;\n}\n\n:deep(.ag-row-selected) {\n background-color: hsl(var(--primary) / 0.1) !important;\n border-left: 2px solid hsl(var(--primary)) !important;\n}\n\n:deep(.ag-row-selected:hover) {\n background-color: hsl(var(--primary) / 0.15) !important;\n}\n\n:deep(.ag-cell) {\n line-height: 1.5;\n padding: 0.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.5);\n}\n\n:deep(.ag-paging-panel) {\n background-color: hsl(var(--muted) / 0.5);\n border-top: 1px solid hsl(var(--border));\n}\n</style>\n"],"names":["ModuleRegistry","AllCommunityModule","AllEnterpriseModule","jTheme","themeQuartz","props","__props","emit","__emit","gridApi","ref","gridColumnApi","ActionButtonsCellRenderer","params","buttons","rowData","visibleButtons","btn","container","button","e","actionButtonsColumn","computed","processedColumnDefs","columns","gridOptions","data","__expose","onGridReady","onRowClicked","event","onRowDoubleClicked","onCellClicked","onSelectionChanged","onCellValueChanged","watch","_createElementBlock","_normalizeClass","_unref","cn","_createVNode","AgGridVue"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,IAAAA,EAAe,gBAAgB,CAACC,GAAoBC,CAAmB,CAAC;AAGxE,UAAMC,IAASC,EAAY,WAAW;AAAA,MACpC,oBAAoB;AAAA,MACpB,4BAA4B;AAAA,MAC5B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,uBAAuB;AAAA,MACvB,kBAAkB;AAAA,MAClB,4BAA4B;AAAA,MAC5B,UAAU;AAAA,MACV,uBAAuB;AAAA,MACvB,yBAAyB;AAAA,IAAA,CAC1B,GAoBKC,IAAQC,GA4ERC,IAAOC,GAkBPC,IAAUC,EAAS,IAAI,GACvBC,IAAgBD,EAAS,IAAI,GAG7BE,IAA4B,CAACC,MAAgC;AACjE,YAAMC,IAAUT,EAAM,iBAAiB,CAAA,GACjCU,IAAUF,EAAO,MAGjBG,IAAiBF,EAAQ,OAAO,CAAAG,MAChCA,EAAI,OACCA,EAAI,KAAKF,CAAO,IAElB,EACR;AAED,UAAIC,EAAe,WAAW;AAC5B,eAAO;AAIT,YAAME,IAAY,SAAS,cAAc,KAAK;AAC9C,aAAAA,EAAU,YAAY,2BAGtBF,EAAe,QAAQ,CAACC,MAAQ;AAC9B,cAAME,IAAS,SAAS,cAAc,QAAQ;AAC9C,QAAAA,EAAO,YAAY,sDAGfF,EAAI,cAAc,WACpBE,EAAO,aAAa,wIAEpBA,EAAO,aAAa,+IAIlBF,EAAI,YACNE,EAAO,QAAQF,EAAI,UAIjBA,EAAI,QACNE,EAAO,cAAcF,EAAI,QAChBA,EAAI,SAETA,EAAI,SAAS,WACfE,EAAO,cAAc,OACZF,EAAI,SAAS,YAAYA,EAAI,SAAS,UAC/CE,EAAO,cAAc,OACZF,EAAI,SAAS,QACtBE,EAAO,cAAc,OACZF,EAAI,SAAS,SACtBE,EAAO,cAAc,OACZF,EAAI,SAAS,aACtBE,EAAO,cAAc,SACZF,EAAI,SAAS,YACtBE,EAAO,cAAc,SACZF,EAAI,SAAS,mBACtBE,EAAO,cAAc,QAErBA,EAAO,cAAcF,EAAI,OAK7BE,EAAO,iBAAiB,SAAS,CAACC,MAAM;AACtC,UAAAA,EAAE,gBAAA,GACFH,EAAI,QAAQF,CAAO;AAAA,QACrB,CAAC,GAEDG,EAAU,YAAYC,CAAM;AAAA,MAC9B,CAAC,GAEMD;AAAA,IACT,GAGMG,IAAsBC,EAAwB,MAC9C,CAACjB,EAAM,iBAAiBA,EAAM,cAAc,WAAW,IAClD,OAGF;AAAA,MACL,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,MACd,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,MAC1B,cAAcO;AAAA,MACd,WAAW,EAAE,SAAS,QAAQ,gBAAgB,UAAU,YAAY,SAAA;AAAA,IAAS,CAEhF,GAGKW,IAAsBD,EAAS,MAAM;AACzC,YAAME,IAAoB,CAAA;AAG1B,aAAInB,EAAM,YACRmB,EAAQ,KAAK;AAAA,QACX,OAAO;AAAA,QACP,YAAY;AAAA;AAAA,QAEZ,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,yBAAyB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,mBAAmB;AAAA,QACnB,0BAA0B;AAAA,QAC1B,WAAW,EAAE,SAAS,QAAQ,gBAAgB,UAAU,YAAY,SAAA;AAAA,MAAS,CAC9E,GAICH,EAAoB,SACtBG,EAAQ,KAAKH,EAAoB,KAAK,GAIxCG,EAAQ,KAAK,GAAGnB,EAAM,UAAU,GAEzBmB;AAAA,IACT,CAAC,GAGKC,IAAcH,EAAsB,OACX;AAAA,MAC3B,OAAOnB;AAAA,MACP,YAAYE,EAAM;AAAA,MAClB,cAAcA,EAAM,WAAW,aAAa;AAAA;AAAA;AAAA,MAG5C,2BAA2BA,EAAM;AAAA;AAAA,MAGjC,YAAYA,EAAM;AAAA;AAAA,MAGlB,sBAAsBA,EAAM;AAAA;AAAA,MAG5B,SAASA,EAAM,0BAA0BA,EAAM,kBAAkBA,EAAM,cAAc;AAAA,QACnF,YAAY;AAAA,UACV;AAAA,YACE,IAAI;AAAA,YACJ,cAAc;AAAA,YACd,UAAU;AAAA,YACV,SAAS;AAAA,YACT,WAAW;AAAA,YACX,iBAAiB;AAAA,cACf,mBAAmB,CAACA,EAAM;AAAA,cAC1B,gBAAgB,CAACA,EAAM;AAAA,cACvB,gBAAgB,CAACA,EAAM;AAAA,cACvB,mBAAmB,CAACA,EAAM;AAAA,YAAA;AAAA,UAC5B;AAAA,QACF;AAAA,QAEF,kBAAkB;AAAA;AAAA,MAAA,IAChB;AAAA;AAAA;AAAA,MAIJ,WAAYA,EAAM,aAAa,CAACA,EAAM,gBAAiB;AAAA,QACrD,cAAc;AAAA,UACZ,EAAE,aAAa,uCAAuC,OAAO,OAAA;AAAA,UAC7D,EAAE,aAAa,+BAA+B,OAAO,OAAA;AAAA,UACrD,EAAE,aAAa,0BAA0B,OAAO,QAAA;AAAA,QAAiB;AAAA,MACnE,IACE;AAAA;AAAA,MAGJ,mBAAmBA,EAAM,sBAAsB,UAAUA,EAAM,oBAAoB;AAAA;AAAA,MAGnF,gBAAgBA,EAAM,mBAAmB,UAAUA,EAAM,iBAAiB;AAAA;AAAA,MAG1E,WAAWA,EAAM;AAAA;AAAA,MAGjB,sBAAsBA,EAAM;AAAA,MAC5B,yBAAyB;AAAA;AAAA,MAGzB,UAAUA,EAAM,kBAAkB;AAAA,MAClC,aAAaA,EAAM,iBACdA,EAAM,gBAAgB,CAACqB,MAAcA,EAAK,QAAQ,CAAA,KACnD;AAAA,MACJ,oBAAoBrB,EAAM,kBAAkBA,EAAM,qBAC9CA,EAAM,qBACN;AAAA,IAAA,EAIP;AAYD,IAAAsB,EAAa;AAAA,MACX,SAAAlB;AAAA,MACA,eAAAE;AAAA,MACA,eAZoB,MAAM;AAC1B,QAAIF,EAAQ,SAASJ,EAAM,qBACzBI,EAAQ,MAAM,kBAAkB;AAAA,UAC9B,UAAU;AAAA,QAAA,CACX;AAAA,MAEL;AAAA,IAME,CACD;AAGD,UAAMmB,IAAc,CAACf,MAA2B;AAC9C,MAAAJ,EAAQ,QAAQI,EAAO,KACvBF,EAAc,QAAQE,EAAO,KAC7BN,EAAK,aAAaM,CAAM;AAAA,IAC1B,GAGMgB,IAAe,CAACC,MAA2B;AAC/C,MAAAvB,EAAK,cAAcuB,CAAK;AAAA,IAC1B,GAGMC,IAAqB,CAACD,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK;AAAA,IAChC,GAGME,IAAgB,CAACF,MAA4B;AACjD,MAAAvB,EAAK,eAAeuB,CAAK;AAAA,IAC3B,GAGMG,IAAqB,CAACH,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK,GAC9BvB,EAAK,uBAAuBuB,EAAM,IAAI,gBAAA,CAAiB;AAAA,IACzD,GAGMI,IAAqB,CAACJ,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK;AAAA,IAChC;AAGA,WAAAK;AAAA,MACE,MAAM9B,EAAM;AAAA,MACZ,MAAM;AACJ,QAAII,EAAQ,SACVA,EAAQ,MAAM,cAAc,cAAcc,EAAoB,KAAK;AAAA,MAEvE;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK,GAIfY;AAAA,MACE,MAAM9B,EAAM;AAAA,MACZ,MAAM;AACJ,QAAII,EAAQ,SACVA,EAAQ,MAAM,cAAc,WAAWJ,EAAM,OAAO;AAAA,MAExD;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK,mBAKb+B,EAaM,OAAA;AAAA,MAbA,OAAKC,EAAEC,EAAAC,CAAA,EAAE,qBAAsBlC,EAAM,KAAK,CAAA;AAAA,IAAA;MAC9CmC,EAWEF,EAAAG,CAAA,GAAA;AAAA,QAVC,eAAalB,EAAA;AAAA,QACb,YAAUjB,EAAA;AAAA,QACV,gBAAcmB,EAAA;AAAA,QACf,OAAA,EAAA,QAAA,QAAA,OAAA,OAAA;AAAA,QACC,aAAAG;AAAA,QACA,cAAAC;AAAA,QACA,oBAAAE;AAAA,QACA,eAAAC;AAAA,QACA,oBAAAC;AAAA,QACA,oBAAAC;AAAA,MAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"JGrid.vue2.js","sources":["../../../../src/components/atoms/JGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport { AgGridVue } from 'ag-grid-vue3'\nimport { cn } from '@/lib/utils'\nimport type {\n ColDef,\n GridOptions,\n RowClickedEvent,\n CellClickedEvent,\n SelectionChangedEvent,\n CellValueChangedEvent,\n RowDoubleClickedEvent,\n GridReadyEvent,\n ICellRendererParams,\n} from 'ag-grid-community'\nimport { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community'\n// Enterprise 모듈 import (Grouping, Pivot, Excel Export 등)\nimport { AllEnterpriseModule } from 'ag-grid-enterprise'\n\n// AG Grid 모듈 등록 (Community + Enterprise)\nModuleRegistry.registerModules([AllCommunityModule, AllEnterpriseModule])\n\n// ── 공식 권장: data-ag-theme-mode attribute 기반 다크모드 전환 ─────────────────\n// AG Grid v33 공식 패턴:\n// 1. themeQuartz.withParams({...}, 'light').withParams({...}, 'dark') 로 두 모드 정의\n// 2. data-ag-theme-mode attribute 전환으로 모드 스위칭 (theme 객체 재생성 불필요)\n// 3. CSS --ag-* 변수 오버라이드로 앱 CSS 변수 참조 (getCSSVar 우회 불필요)\nconst jTheme = themeQuartz\n .withParams({\n browserColorScheme: 'light', // 네이티브 폼/스크롤바를 라이트 스타일로\n cellHorizontalPaddingScale: 1,\n columnBorder: true,\n fontSize: 13,\n headerFontWeight: 500,\n headerVerticalPaddingScale: 0.45,\n iconSize: 14,\n rowVerticalPaddingScale: 0.4,\n }, 'light')\n .withParams({\n browserColorScheme: 'dark', // 네이티브 폼/스크롤바를 다크 스타일로\n }, 'dark')\n\n// JLIS는 .dark class 기반 다크모드이므로 MutationObserver로 감지 후 attribute 동기화\nconst isDark = ref(typeof document !== 'undefined' && document.documentElement.classList.contains('dark'))\nconst gridContainerRef = ref<HTMLElement | null>(null)\nlet darkObserver: MutationObserver | null = null\n\n// isDark 변경 → data-ag-theme-mode 동기화 (AG Grid가 내부적으로 반응)\nwatch(isDark, (dark) => {\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', dark ? 'dark' : 'light')\n})\n\nonMounted(() => {\n // 초기 attribute 설정\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', isDark.value ? 'dark' : 'light')\n\n // 이후 변경 감지\n darkObserver = new MutationObserver(() => {\n isDark.value = document.documentElement.classList.contains('dark')\n })\n darkObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n})\n\nonUnmounted(() => {\n darkObserver?.disconnect()\n})\n\n/**\n * Action Button 정의 타입\n */\nexport type ActionButton = {\n /** 버튼 아이콘 이름 (lucide) - label이 없을 때 기본 텍스트 생성에 사용 */\n icon?: string\n /** 버튼 라벨 */\n label?: string\n /** 툴팁 텍스트 */\n tooltip?: string\n /** 버튼 클릭 핸들러 (rowData 전달) */\n onClick: (rowData: any) => void\n /** 버튼 스타일 타입 */\n styletype?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'\n /** 조건부 표시 함수 (rowData를 받아 boolean 반환) */\n show?: (rowData: any) => boolean\n}\n\nconst props = withDefaults(\n defineProps<{\n /** 추가 클래스 (외부 커스터마이징용) */\n class?: string\n /** 그리드에 표시할 데이터 배열 */\n rowData: any[]\n /** 컬럼 정의 배열 */\n columnDefs: ColDef[]\n /** 페이지네이션 활성화 여부 */\n pagination?: boolean\n /** 체크박스 선택 활성화 여부 */\n checkbox?: boolean\n /** 행 번호 표시 여부 (Enterprise) */\n rowNumbers?: boolean\n /** 플로팅 필터 표시 여부 */\n floatingFilters?: boolean\n /** 플로팅 필터 표시 여부 (하위호환 alias) */\n floatingFilter?: boolean\n /** 행 번호 컬럼 너비(px) */\n rowNumberWidth?: number\n /** 행별 액션 버튼 목록 */\n actionButtons?: ActionButton[]\n /** 요약 컬럼 표시 여부 */\n summaryColumn?: boolean\n /** 숨김 컬럼 관리 활성화 여부 */\n hiddenColumn?: boolean\n /** 그룹핑 기능 활성화 여부 (Enterprise) */\n enableGrouping?: boolean\n /** 피벗 기능 활성화 여부 (Enterprise) */\n enablePivot?: boolean\n /** Excel 내보내기 기능 활성화 여부 (Enterprise) */\n enableExcelExport?: boolean\n /** Tree Data 기능 활성화 여부 (Enterprise) */\n enableTreeData?: boolean\n /** Tree Data 계층 경로를 반환하는 함수 */\n getDataPath?: (data: any) => (string | number)[]\n /** Tree Data 그룹 컬럼 정의 */\n autoGroupColumnDef?: ColDef\n /** 선택된 행 데이터 배열 (v-model:selected-rows) */\n selectedRows?: any[]\n /** 컬럼 호버 하이라이트 활성화 여부 */\n columnHover?: boolean\n /** Columns Tool Panel 활성화 여부 (Enterprise) */\n enableColumnsToolPanel?: boolean\n /** Status Bar 활성화 여부 (Enterprise) */\n statusBar?: boolean\n /** 간소화된 Footer 모드 (Status Bar 제거, Pagination만 표시) */\n compactFooter?: boolean\n /** Row Group Panel 표시 여부 ('always' | 'onlyWhenGrouping' | 'never') */\n rowGroupPanelShow?: 'always' | 'onlyWhenGrouping' | 'never'\n /** 그룹 기본 확장 레벨 (-1: 모두 닫힘, 0: 첫 레벨만, 1: 2레벨까지...) */\n groupDefaultExpanded?: number\n /** Pivot Mode Panel 표시 여부 */\n pivotPanelShow?: 'always' | 'onlyWhenPivoting' | 'never'\n /** Pivot Mode 활성화 여부 */\n pivotMode?: boolean\n }>(),\n {\n pagination: true,\n checkbox: false,\n rowNumbers: true,\n floatingFilters: true,\n floatingFilter: undefined,\n rowNumberWidth: 38,\n actionButtons: undefined,\n summaryColumn: false,\n hiddenColumn: false,\n enableGrouping: true,\n enablePivot: false,\n enableExcelExport: false,\n enableTreeData: false,\n getDataPath: undefined,\n autoGroupColumnDef: undefined,\n selectedRows: () => [],\n columnHover: true,\n enableColumnsToolPanel: true,\n statusBar: true,\n compactFooter: false,\n rowGroupPanelShow: 'never',\n groupDefaultExpanded: -1,\n pivotPanelShow: 'never',\n pivotMode: false,\n },\n)\n\nconst emit = defineEmits<{\n /** 행 클릭 이벤트 */\n rowClicked: [event: RowClickedEvent]\n /** 행 더블클릭 이벤트 */\n rowDoubleClicked: [event: RowDoubleClickedEvent]\n /** 셀 클릭 이벤트 */\n cellClicked: [event: CellClickedEvent]\n /** 선택 변경 이벤트 (체크박스 등) */\n selectionChanged: [event: SelectionChangedEvent]\n /** 셀 값 변경 이벤트 */\n cellValueChanged: [event: CellValueChangedEvent]\n /** 그리드 준비 완료 이벤트 */\n gridReady: [event: GridReadyEvent]\n /** 선택된 행 변경 이벤트 (v-model:selected-rows) */\n 'update:selectedRows': [rows: any[]]\n}>()\n\n// ag-Grid 인스턴스 참조\nconst gridApi = ref<any>(null)\nconst gridColumnApi = ref<any>(null)\n\n// Action Buttons Cell Renderer - 함수형으로 DOM 직접 생성\nconst ActionButtonsCellRenderer = (params: ICellRendererParams) => {\n const buttons = props.actionButtons || []\n const rowData = params.data\n \n // 표시할 버튼 필터링\n const visibleButtons = buttons.filter(btn => {\n if (btn.show) {\n return btn.show(rowData)\n }\n return true\n })\n \n if (visibleButtons.length === 0) {\n return ''\n }\n \n // 컨테이너 div 생성\n const container = document.createElement('div')\n container.className = 'flex items-center gap-1'\n \n // 각 버튼 생성\n visibleButtons.forEach((btn) => {\n const button = document.createElement('button')\n button.className = 'px-2 py-1 text-xs border rounded transition-colors'\n \n // styletype에 따른 클래스 추가\n if (btn.styletype === 'danger') {\n button.className += ' bg-red-50 border-red-400 text-red-700 hover:bg-red-100 dark:bg-red-950 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900'\n } else {\n button.className += ' bg-gray-50 border-gray-400 text-gray-700 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700'\n }\n \n // tooltip\n if (btn.tooltip) {\n button.title = btn.tooltip\n }\n \n // 라벨 추가 (텍스트 버튼)\n if (btn.label) {\n button.textContent = btn.label\n } else if (btn.icon) {\n // 라벨이 없으면 기본 텍스트 생성\n if (btn.icon === 'pencil') {\n button.textContent = '수정'\n } else if (btn.icon === 'trash2' || btn.icon === 'trash') {\n button.textContent = '삭제'\n } else if (btn.icon === 'eye') {\n button.textContent = '보기'\n } else if (btn.icon === 'copy') {\n button.textContent = '복사'\n } else if (btn.icon === 'download') {\n button.textContent = '다운로드'\n } else if (btn.icon === 'circleX') {\n button.textContent = '비활성화'\n } else if (btn.icon === 'circleCheckBig') {\n button.textContent = '활성화'\n } else {\n button.textContent = btn.icon\n }\n }\n \n // 클릭 이벤트\n button.addEventListener('click', (e) => {\n e.stopPropagation()\n btn.onClick(rowData)\n })\n \n container.appendChild(button)\n })\n \n return container\n}\n\n// Action Buttons 컬럼 정의\nconst actionButtonsColumn = computed<ColDef | null>(() => {\n if (!props.actionButtons || props.actionButtons.length === 0) {\n return null\n }\n \n return {\n colId: 'actionButtons',\n headerName: '작업',\n field: '_actions',\n width: 120,\n minWidth: 80,\n maxWidth: 200,\n lockPosition: 'left' as const,\n sortable: false,\n filter: false,\n resizable: true,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellRenderer: ActionButtonsCellRenderer,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n }\n})\n\n// checkbox 활성화 및 추가 컬럼 처리\nconst processedColumnDefs = computed(() => {\n const columns: ColDef[] = []\n \n // 1. Checkbox 컬럼 (최우선)\n if (props.checkbox) {\n columns.push({\n colId: 'rowSelection',\n headerName: '',\n // field와 valueGetter 제거 - AG Grid 공식 방식\n width: 50,\n minWidth: 50,\n maxWidth: 50,\n lockPosition: 'left' as const,\n checkboxSelection: true,\n headerCheckboxSelection: true,\n sortable: false,\n filter: false,\n resizable: false,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n })\n }\n \n // 2. Action Buttons 컬럼\n if (actionButtonsColumn.value) {\n columns.push(actionButtonsColumn.value)\n }\n \n // 3. 사용자 정의 컬럼들 (Row Numbers는 AG Grid가 자동으로 추가)\n columns.push(...props.columnDefs)\n \n return columns\n})\n\n// Grid 옵션 설정\nconst gridOptions = computed<GridOptions>(() => {\n const useFloatingFilters = props.floatingFilter ?? props.floatingFilters\n const options: GridOptions = {\n theme: jTheme,\n pagination: props.pagination,\n defaultColDef: {\n filter: true,\n floatingFilter: useFloatingFilters,\n },\n rowSelection: props.checkbox ? 'multiple' : undefined,\n // 체크박스 모드일 때 row 클릭으로 선택이 변경되지 않도록 설정\n // 체크박스만으로 선택을 제어하도록 함\n suppressRowClickSelection: props.checkbox,\n\n // Row Numbers (Enterprise) - AG Grid 표준 방식\n rowNumbers: props.rowNumbers\n ? ({\n minWidth: props.rowNumberWidth,\n width: props.rowNumberWidth,\n } as any)\n : false,\n\n // Column Hover Highlight\n columnHoverHighlight: props.columnHover,\n\n // Enterprise 기능 옵션\n sideBar: props.enableColumnsToolPanel || props.enableGrouping || props.enablePivot ? {\n toolPanels: [\n {\n id: 'columns',\n labelDefault: 'Columns',\n labelKey: 'columns',\n iconKey: 'columns',\n toolPanel: 'agColumnsToolPanel',\n toolPanelParams: {\n suppressRowGroups: !props.enableGrouping,\n suppressValues: !props.enablePivot,\n suppressPivots: !props.enablePivot,\n suppressPivotMode: !props.enablePivot,\n },\n },\n ],\n defaultToolPanel: '', // 초기에는 접힌 상태\n } : undefined,\n\n // Status Bar (Enterprise)\n // compactFooter 모드에서는 Status Bar 비활성화\n statusBar: (props.statusBar && !props.compactFooter) ? {\n statusPanels: [\n { statusPanel: 'agTotalAndFilteredRowCountComponent', align: 'left' as const },\n { statusPanel: 'agSelectedRowCountComponent', align: 'left' as const },\n { statusPanel: 'agAggregationComponent', align: 'right' as const },\n ],\n } : undefined,\n\n // Row Group Panel 설정 (Enterprise) - 그리드 상단에 드래그 영역 표시\n rowGroupPanelShow: props.rowGroupPanelShow !== 'never' ? props.rowGroupPanelShow : undefined,\n\n // Pivot Panel 설정 (Enterprise) - 피벗 모드용 드래그 영역\n pivotPanelShow: props.pivotPanelShow !== 'never' ? props.pivotPanelShow : undefined,\n \n // Pivot Mode 활성화\n pivotMode: props.pivotMode,\n\n // 그룹핑 기본 설정\n groupDefaultExpanded: props.groupDefaultExpanded,\n suppressAggFuncInHeader: false,\n\n // Tree Data 설정 (Enterprise)\n treeData: props.enableTreeData || undefined,\n getDataPath: props.enableTreeData\n ? (props.getDataPath || ((data: any) => data.path || []))\n : undefined,\n autoGroupColumnDef: props.enableTreeData && props.autoGroupColumnDef\n ? props.autoGroupColumnDef\n : undefined,\n }\n\n return options\n})\n\n// Excel 내보내기 함수 (외부에서 사용 가능하도록 expose)\nconst exportToExcel = () => {\n if (gridApi.value && props.enableExcelExport) {\n gridApi.value.exportDataAsExcel({\n fileName: 'grid-export.xlsx',\n })\n }\n}\n\n// 그리드 API를 외부에 노출\ndefineExpose({\n gridApi,\n gridColumnApi,\n exportToExcel,\n})\n\n// Grid ready 이벤트 핸들러\nconst onGridReady = (params: GridReadyEvent) => {\n gridApi.value = params.api\n gridColumnApi.value = params.api // v34에서 columnApi는 deprecated\n emit('gridReady', params)\n}\n\n// 행 클릭 이벤트 핸들러\nconst onRowClicked = (event: RowClickedEvent) => {\n emit('rowClicked', event)\n}\n\n// 행 더블클릭 이벤트 핸들러\nconst onRowDoubleClicked = (event: RowDoubleClickedEvent) => {\n emit('rowDoubleClicked', event)\n}\n\n// 셀 클릭 이벤트 핸들러\nconst onCellClicked = (event: CellClickedEvent) => {\n emit('cellClicked', event)\n}\n\n// 선택 변경 이벤트 핸들러\nconst onSelectionChanged = (event: SelectionChangedEvent) => {\n emit('selectionChanged', event)\n emit('update:selectedRows', event.api.getSelectedRows())\n}\n\n// 셀 값 변경 이벤트 핸들러\nconst onCellValueChanged = (event: CellValueChangedEvent) => {\n emit('cellValueChanged', event)\n}\n\n// columnDefs 변경 감지\nwatch(\n () => props.columnDefs,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('columnDefs', processedColumnDefs.value)\n }\n },\n { deep: true },\n)\n\n// rowData 변경 감지\nwatch(\n () => props.rowData,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('rowData', props.rowData)\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div ref=\"gridContainerRef\" :class=\"cn('ag-grid-container', props.class)\">\n <AgGridVue\n :column-defs=\"processedColumnDefs\"\n :row-data=\"rowData\"\n :grid-options=\"gridOptions\"\n style=\"height: 100%; width: 100%\"\n @grid-ready=\"onGridReady\"\n @row-clicked=\"onRowClicked\"\n @row-double-clicked=\"onRowDoubleClicked\"\n @cell-clicked=\"onCellClicked\"\n @selection-changed=\"onSelectionChanged\"\n @cell-value-changed=\"onCellValueChanged\"\n />\n </div>\n</template>\n\n<style scoped>\n.ag-grid-container {\n width: 100%;\n height: 100%;\n\n /*\n * App CSS 변수 → AG Grid CSS 변수 브릿지\n * CSS 변수는 런타임 해소 → .dark 클래스 전환 시 라이트/다크 자동 대응\n * AG Grid v33 공식 CSS variable 명칭 사용\n */\n --ag-background-color: hsl(var(--background));\n --ag-foreground-color: hsl(var(--foreground));\n --ag-border-color: hsl(var(--border));\n --ag-header-background-color: hsl(var(--muted));\n --ag-header-foreground-color: hsl(var(--foreground));\n --ag-odd-row-background-color: hsl(var(--card));\n --ag-row-hover-color: hsl(var(--accent));\n --ag-selected-row-background-color: hsl(var(--primary) / 0.12);\n --ag-accent-color: hsl(var(--primary));\n}\n\n/* ============================================\n COMPACT FOOTER: Status Bar + Pagination 통합\n ============================================ */\n\n/* Status Bar 높이 줄이기 */\n:deep(.ag-status-bar) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 0.8125rem;\n}\n\n/* Status Bar 컴포넌트들 높이 조정 */\n:deep(.ag-status-bar-left),\n:deep(.ag-status-bar-center),\n:deep(.ag-status-bar-right) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Status Bar 패널들 간격 조정 */\n:deep(.ag-status-panel) {\n padding: 0;\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Pagination Panel 높이 줄이기 */\n:deep(.ag-paging-panel) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n font-size: 0.8125rem;\n}\n\n/* Pagination 컴포넌트들 높이 조정 */\n:deep(.ag-paging-page-size),\n:deep(.ag-paging-row-summary-panel) {\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Page Size Selector 높이 조정 */\n:deep(.ag-paging-page-size .ag-picker-field) {\n height: 24px;\n min-height: 24px;\n}\n\n:deep(.ag-paging-page-size .ag-picker-field-wrapper) {\n height: 24px;\n padding: 0 4px;\n}\n\n/* Pagination 버튼들 높이 조정 */\n:deep(.ag-paging-button) {\n height: 24px;\n width: 24px;\n padding: 2px;\n}\n\n/* Pagination 버튼 래퍼 */\n:deep(.ag-paging-button-wrapper) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Row summary 텍스트 */\n:deep(.ag-paging-row-summary-panel-number) {\n line-height: 28px;\n}\n\n/* ========================================\n 패턴 9: AG-Grid 스타일 향상\n ======================================== */\n\n:deep(.ag-root-wrapper) {\n border: 1px solid hsl(var(--border));\n border-radius: 0.375rem;\n}\n\n/* ── Header ──────────────────────────────────────────────────────────── */\n:deep(.ag-header) {\n border-bottom: 1px solid hsl(var(--border));\n font-weight: 500;\n}\n\n:deep(.ag-header-cell) {\n color: hsl(var(--foreground));\n font-size: 0.75rem;\n padding: 0.25rem 0.5rem;\n}\n\n/* Floating Filter 행 높이 컴팩트화 */\n:deep(.ag-header-row.ag-floating-filter) {\n min-height: 26px !important;\n height: 26px !important;\n}\n\n:deep(.ag-floating-filter-body) {\n min-height: 24px;\n}\n\n:deep(.ag-floating-filter-body input),\n:deep(.ag-floating-filter-body .ag-input-field-input),\n:deep(.ag-floating-filter-body .ag-picker-field-wrapper) {\n height: 22px !important;\n min-height: 22px !important;\n font-size: 0.75rem;\n}\n\n/* ── Rows ────────────────────────────────────────────────────────────── */\n:deep(.ag-row) {\n transition: background-color 0.15s ease, box-shadow 0.15s ease;\n cursor: pointer;\n}\n\n/* 선택된 행: 왼쪽 accent 기둥으로 명확한 시각적 선택 표시 (라이트/다크 모두) */\n:deep(.ag-row-selected) {\n box-shadow: inset 3px 0 0 hsl(var(--primary));\n}\n\n/* ── Cells ───────────────────────────────────────────────────────────── */\n:deep(.ag-cell) {\n line-height: 1.25;\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.5);\n}\n\n:deep(.ag-cell-wrapper) {\n align-items: center;\n}\n\n:deep(.ag-cell-value) {\n display: flex;\n align-items: center;\n min-height: 100%;\n}\n\n/* 행 클릭 시 row number 셀에 보이는 강한 포커스 음영 제거 */\n:deep(.ag-cell.ag-row-number-cell.ag-cell-focus),\n:deep(.ag-cell.ag-row-number-cell:focus-within) {\n box-shadow: none !important;\n outline: none !important;\n}\n\n/* 셀 포커스 */\n:deep(.ag-cell.ag-cell-focus) {\n box-shadow: inset 0 0 0 1px hsl(var(--ring) / 0.5) !important;\n}\n\n/* ── Pagination ──────────────────────────────────────────────────────── */\n:deep(.ag-paging-panel) {\n border-top: 1px solid hsl(var(--border));\n}\n</style>\n"],"names":["ModuleRegistry","AllCommunityModule","AllEnterpriseModule","jTheme","themeQuartz","isDark","ref","gridContainerRef","darkObserver","watch","dark","onMounted","onUnmounted","props","__props","emit","__emit","gridApi","gridColumnApi","ActionButtonsCellRenderer","params","buttons","rowData","visibleButtons","btn","container","button","e","actionButtonsColumn","computed","processedColumnDefs","columns","gridOptions","useFloatingFilters","data","__expose","onGridReady","onRowClicked","event","onRowDoubleClicked","onCellClicked","onSelectionChanged","onCellValueChanged","_createElementBlock","_normalizeClass","_unref","cn","_createVNode","AgGridVue"],"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-111bd13c"]]);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 _ = /* @__PURE__ */ o(t, [["__scopeId", "data-v-111bd13c"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
_ 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"),r=require("../shadcn/resizable/ResizablePanelGroup.vue.cjs"),l=require("reka-ui"),u=e.defineComponent({__name:"JSplitter",props:{direction:{default:"horizontal"},defaultSize:{default:40},minSize:{default:20},maxSize:{},secondMinSize:{},secondMaxSize:{},withHandle:{type:Boolean,default:!0},gap:{default:
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),s=require("../shadcn/resizable/ResizableHandle.vue.cjs"),r=require("../shadcn/resizable/ResizablePanelGroup.vue.cjs"),l=require("reka-ui"),u=e.defineComponent({__name:"JSplitter",props:{direction:{default:"horizontal"},defaultSize:{default:40},minSize:{default:20},maxSize:{},secondMinSize:{},secondMaxSize:{},withHandle:{type:Boolean,default:!0},gap:{default:8},class:{}},setup(t){const i=t,n=e.computed(()=>100-i.defaultSize);return(a,d)=>(e.openBlock(),e.createBlock(e.unref(r.default),{direction:t.direction,class:e.normalizeClass(t.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(s.default),{"with-handle":t.withHandle},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=u;
|
|
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: true,\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 {\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: true,\n gap: 8,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"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\" />\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/* ========================================\n 패턴 5: Splitter Handle 스타일\n ======================================== */\n\n:deep([data-panel-resize-handle-id]) {\n background: transparent;\n transition: background-color 0.15s ease;\n position: relative;\n user-select: none;\n touch-action: none;\n}\n\n:deep([data-panel-resize-handle-id]::before) {\n content: '';\n position: absolute;\n background: hsl(var(--border));\n border-radius: 9999px;\n}\n\n:deep([data-panel-resize-handle-id]:hover) {\n background: hsl(var(--primary) / 0.06);\n}\n\n:deep([data-panel-resize-handle-id]:hover::before) {\n background: hsl(var(--primary) / 0.55);\n}\n\n:deep([data-panel-resize-handle-id]:active) {\n background: hsl(var(--primary) / 0.1);\n}\n\n:deep([data-panel-resize-handle-id]:active::before) {\n background: hsl(var(--primary));\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"horizontal\"]) {\n cursor: col-resize;\n width: 10px;\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"horizontal\"]::before) {\n top: 6px;\n bottom: 6px;\n left: 50%;\n width: 1px;\n transform: translateX(-50%);\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"vertical\"]) {\n cursor: row-resize;\n height: 10px;\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"vertical\"]::before) {\n left: 6px;\n right: 6px;\n top: 50%;\n height: 1px;\n transform: translateY(-50%);\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_createVNode","ResizablePanel","_normalizeClass","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":"igBAUA,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,uBAAOA,EAAA,KAAK,CAAA,qBAEvD,IAWiB,CAXjBM,cAWiBF,EAAAA,MAAAG,EAAAA,aAAA,EAAA,CAVd,eAAcP,EAAA,YACd,WAAUA,EAAA,QACV,WAAUA,EAAA,QACV,MAAKQ,EAAAA,eAAER,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKS,EAAAA,eAAET,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAqB,CAArBU,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,kEAIrBL,EAAAA,YAA6CF,EAAAA,MAAAQ,SAAA,EAAA,CAA3B,cAAaZ,EAAA,UAAA,EAAU,KAAA,EAAA,CAAA,aAAA,CAAA,EAGzCM,cAWiBF,EAAAA,MAAAG,EAAAA,aAAA,EAAA,CAVd,eAAcN,EAAA,MACd,WAAUD,EAAA,cACV,WAAUA,EAAA,cACV,MAAKQ,EAAAA,eAAER,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKS,EAAAA,eAAET,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAsB,CAAtBU,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 +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: true,\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 {\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: true,\n gap: 8,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"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\" />\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/* ========================================\n 패턴 5: Splitter Handle 스타일\n ======================================== */\n\n:deep([data-panel-resize-handle-id]) {\n background: transparent;\n transition: background-color 0.15s ease;\n position: relative;\n user-select: none;\n touch-action: none;\n}\n\n:deep([data-panel-resize-handle-id]::before) {\n content: '';\n position: absolute;\n background: hsl(var(--border));\n border-radius: 9999px;\n}\n\n:deep([data-panel-resize-handle-id]:hover) {\n background: hsl(var(--primary) / 0.06);\n}\n\n:deep([data-panel-resize-handle-id]:hover::before) {\n background: hsl(var(--primary) / 0.55);\n}\n\n:deep([data-panel-resize-handle-id]:active) {\n background: hsl(var(--primary) / 0.1);\n}\n\n:deep([data-panel-resize-handle-id]:active::before) {\n background: hsl(var(--primary));\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"horizontal\"]) {\n cursor: col-resize;\n width: 10px;\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"horizontal\"]::before) {\n top: 6px;\n bottom: 6px;\n left: 50%;\n width: 1px;\n transform: translateX(-50%);\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"vertical\"]) {\n cursor: row-resize;\n height: 10px;\n}\n\n:deep([data-panel-resize-handle-id][data-resize-handle-orientation=\"vertical\"]::before) {\n left: 6px;\n right: 6px;\n top: 50%;\n height: 1px;\n transform: translateY(-50%);\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_createVNode","ResizablePanel","_normalizeClass","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":";;;;;;;;;;;;;;;;;;AAUA,UAAMA,IAAQC,GA+BRC,IAAoBC,EAAS,MAAM,MAAMH,EAAM,WAAW;2BAI9DI,EA+BsBC,EAAAC,CAAA,GAAA;AAAA,MA/BA,WAAWL,EAAA;AAAA,MAAY,SAAOA,EAAA,KAAK;AAAA,IAAA;iBAEvD,MAWiB;AAAA,QAXjBM,EAWiBF,EAAAG,CAAA,GAAA;AAAA,UAVd,gBAAcP,EAAA;AAAA,UACd,YAAUA,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKQ,EAAER,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKS,EAAET,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAqB;AAAA,YAArBU,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;;;QAIrBL,EAA6CF,EAAAQ,CAAA,GAAA,EAA3B,eAAaZ,EAAA,WAAA,GAAU,MAAA,GAAA,CAAA,aAAA,CAAA;AAAA,QAGzCM,EAWiBF,EAAAG,CAAA,GAAA;AAAA,UAVd,gBAAcN,EAAA;AAAA,UACd,YAAUD,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKQ,EAAER,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKS,EAAET,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAsB;AAAA,YAAtBU,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 m = /* @__PURE__ */ t(o, [["__scopeId", "data-v-1e163e81"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
m 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
|
|
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-0.5",tabTextSizeClass:"text-xs",listPaddingClass:"px-1.5 py-0.5"},minimal:{tabPaddingClass:"px-1.5 py-0.5",tabTextSizeClass:"text-xs",listPaddingClass:"px-1.5 py-0.5"}},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
|