@j-solution/components 1.6.1 → 1.8.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 +8 -6
- package/assets/jwms-portal-frontend-BtHTA-UF.css +1 -0
- package/assets/styles/global-utilities.css +34 -0
- package/assets/styles/j-components.css +1 -1
- package/assets/styles/themes.css +128 -21
- package/components/atoms/JAvatar.vue.cjs +1 -1
- package/components/atoms/JAvatar.vue.cjs.map +1 -1
- package/components/atoms/JAvatar.vue.js +10 -7
- package/components/atoms/JAvatar.vue.js.map +1 -1
- package/components/atoms/JBadge.vue.cjs +1 -1
- package/components/atoms/JBadge.vue.cjs.map +1 -1
- package/components/atoms/JBadge.vue.js +7 -6
- package/components/atoms/JBadge.vue.js.map +1 -1
- 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/JDatepicker.vue.cjs +1 -1
- package/components/atoms/JDatepicker.vue.cjs.map +1 -1
- package/components/atoms/JDatepicker.vue.js +10 -10
- package/components/atoms/JDatepicker.vue.js.map +1 -1
- package/components/atoms/JEditor.vue.cjs +1 -1
- package/components/atoms/JEditor.vue.js +1 -1
- package/components/atoms/JEditor.vue2.cjs +1 -1
- package/components/atoms/JEditor.vue2.cjs.map +1 -1
- package/components/atoms/JEditor.vue2.js +31 -17
- package/components/atoms/JEditor.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 +59 -43
- package/components/atoms/JGrid.vue2.js.map +1 -1
- package/components/atoms/JIcon.vue.cjs +1 -1
- package/components/atoms/JIcon.vue.cjs.map +1 -1
- package/components/atoms/JIcon.vue.js +14 -13
- package/components/atoms/JIcon.vue.js.map +1 -1
- package/components/atoms/JKbd.vue.cjs +1 -1
- package/components/atoms/JKbd.vue.cjs.map +1 -1
- package/components/atoms/JKbd.vue.js +13 -10
- package/components/atoms/JKbd.vue.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/JLink.vue.cjs +1 -1
- package/components/atoms/JLink.vue.cjs.map +1 -1
- package/components/atoms/JLink.vue.js +5 -5
- package/components/atoms/JLink.vue.js.map +1 -1
- package/components/atoms/JPreview.vue.cjs +1 -1
- package/components/atoms/JPreview.vue.js +2 -2
- package/components/atoms/JPreview.vue2.cjs +1 -1
- package/components/atoms/JPreview.vue2.cjs.map +1 -1
- package/components/atoms/JPreview.vue2.js +33 -20
- package/components/atoms/JPreview.vue2.js.map +1 -1
- package/components/atoms/JProgress.vue.cjs +1 -1
- package/components/atoms/JProgress.vue.cjs.map +1 -1
- package/components/atoms/JProgress.vue.js +15 -9
- package/components/atoms/JProgress.vue.js.map +1 -1
- package/components/atoms/JRadio.vue.cjs +1 -1
- package/components/atoms/JRadio.vue.cjs.map +1 -1
- package/components/atoms/JRadio.vue.js +1 -1
- package/components/atoms/JRadio.vue.js.map +1 -1
- package/components/atoms/JSearchCombo.vue.cjs +1 -1
- package/components/atoms/JSearchCombo.vue.cjs.map +1 -1
- package/components/atoms/JSearchCombo.vue.js +38 -37
- package/components/atoms/JSearchCombo.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/JSpinner.vue.cjs +1 -1
- package/components/atoms/JSpinner.vue.cjs.map +1 -1
- package/components/atoms/JSpinner.vue.js +8 -7
- package/components/atoms/JSpinner.vue.js.map +1 -1
- package/components/atoms/JSplitter.vue.cjs +6 -1
- package/components/atoms/JSplitter.vue.cjs.map +1 -1
- package/components/atoms/JSplitter.vue.js +10 -54
- 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/atoms/JTooltip.vue.cjs +1 -1
- package/components/atoms/JTooltip.vue.cjs.map +1 -1
- package/components/atoms/JTooltip.vue.js +18 -15
- package/components/atoms/JTooltip.vue.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 +265 -191
- 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 +349 -333
- 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/JBreadcrumb.vue.cjs +1 -1
- package/components/molecules/JBreadcrumb.vue.cjs.map +1 -1
- package/components/molecules/JBreadcrumb.vue.js +3 -3
- package/components/molecules/JBreadcrumb.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 -262
- 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 +50 -56
- 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 +49 -47
- 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 +141 -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 +211 -208
- 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 +31 -26
- 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/JSidebarAdvanced.vue.cjs +1 -1
- package/components/organisms/JSidebarAdvanced.vue.js +7 -7
- package/components/organisms/JSidebarAdvanced.vue2.cjs +1 -1
- package/components/organisms/JSidebarAdvanced.vue2.cjs.map +1 -1
- package/components/organisms/JSidebarAdvanced.vue2.js +40 -40
- package/components/organisms/JSidebarAdvanced.vue2.js.map +1 -1
- 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 +83 -63
- package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js.map +1 -1
- package/components/organisms/JSidebarSimple.vue.cjs +1 -1
- package/components/organisms/JSidebarSimple.vue.js +2 -2
- package/components/organisms/JSidebarSimple.vue2.cjs +1 -1
- package/components/organisms/JSidebarSimple.vue2.cjs.map +1 -1
- package/components/organisms/JSidebarSimple.vue2.js +2 -2
- package/components/organisms/JSidebarSimple.vue2.js.map +1 -1
- package/components/shadcn/AccordionTrigger.vue.cjs +1 -1
- package/components/shadcn/AccordionTrigger.vue.cjs.map +1 -1
- package/components/shadcn/AccordionTrigger.vue.js +3 -3
- package/components/shadcn/AccordionTrigger.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/CardDescription.vue.cjs +1 -1
- package/components/shadcn/CardDescription.vue.cjs.map +1 -1
- package/components/shadcn/CardDescription.vue.js +1 -1
- package/components/shadcn/CardDescription.vue.js.map +1 -1
- package/components/shadcn/CardFooter.vue.cjs +1 -1
- package/components/shadcn/CardFooter.vue.cjs.map +1 -1
- package/components/shadcn/CardFooter.vue.js +7 -7
- package/components/shadcn/CardFooter.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 +8 -8
- package/components/shadcn/CardHeader.vue.js.map +1 -1
- package/components/shadcn/CardTitle.vue.cjs +1 -1
- package/components/shadcn/CardTitle.vue.cjs.map +1 -1
- package/components/shadcn/CardTitle.vue.js +5 -5
- package/components/shadcn/CardTitle.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 +2 -2
- package/components/shadcn/SelectTrigger.vue.js.map +1 -1
- package/components/shadcn/Switch.vue.cjs +1 -1
- package/components/shadcn/Switch.vue.cjs.map +1 -1
- package/components/shadcn/Switch.vue.js +2 -2
- package/components/shadcn/Switch.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/TabsTrigger.vue.cjs +1 -1
- package/components/shadcn/TabsTrigger.vue.cjs.map +1 -1
- package/components/shadcn/TabsTrigger.vue.js +4 -4
- package/components/shadcn/TabsTrigger.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 +2 -2
- 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 +9 -8
- 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/index.cjs +1 -1
- package/index.js +73 -67
- package/package.json +1 -1
- package/types/index.d.ts +1025 -766
- package/assets/jwms-portal-frontend-DntSIcYt.css +0 -1
- package/components/molecules/JFormField.vue3.cjs +0 -2
- 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,5 +1,144 @@
|
|
|
1
|
-
import f from "
|
|
1
|
+
import { defineComponent as D, computed as x, createElementBlock as u, openBlock as o, normalizeClass as v, unref as p, createElementVNode as n, withDirectives as T, createCommentVNode as i, createBlock as f, createVNode as b, Fragment as $, renderList as z, withCtx as m, toDisplayString as d, withModifiers as E, renderSlot as V, createTextVNode as B, vShow as F } from "vue";
|
|
2
|
+
import { ChevronDown as N, X as R } from "lucide-vue-next";
|
|
3
|
+
import J from "../atoms/JBadge.vue.js";
|
|
4
|
+
import k from "../atoms/JButton.vue.js";
|
|
5
|
+
import O from "../atoms/JLabel.vue.js";
|
|
6
|
+
import { cn as L } from "../../lib/utils.js";
|
|
7
|
+
const M = { class: "flex items-center justify-between px-3 py-1.5" }, X = { class: "flex items-center gap-2" }, q = {
|
|
8
|
+
key: 2,
|
|
9
|
+
class: "flex items-center gap-1 flex-wrap"
|
|
10
|
+
}, G = { class: "text-muted-foreground" }, H = ["onClick"], I = { class: "flex items-center gap-2" }, K = { class: "px-3 pb-3" }, ee = /* @__PURE__ */ D({
|
|
11
|
+
__name: "JFilterBar",
|
|
12
|
+
props: {
|
|
13
|
+
class: {},
|
|
14
|
+
title: {},
|
|
15
|
+
collapsed: { type: Boolean, default: !0 },
|
|
16
|
+
collapsible: { type: Boolean, default: !0 },
|
|
17
|
+
filterValues: { default: () => ({}) },
|
|
18
|
+
filterDisplay: { default: () => ({}) },
|
|
19
|
+
showResetButton: { type: Boolean, default: !1 },
|
|
20
|
+
showSearchButton: { type: Boolean, default: !1 },
|
|
21
|
+
resetButtonText: { default: "초기화" },
|
|
22
|
+
searchButtonText: { default: "조회" }
|
|
23
|
+
},
|
|
24
|
+
emits: ["update:collapsed", "update:filterValues", "search", "reset"],
|
|
25
|
+
setup(r, { emit: w }) {
|
|
26
|
+
const l = r, a = w, y = x(() => l.collapsible ? !l.collapsed : !0);
|
|
27
|
+
function C(e) {
|
|
28
|
+
return !!(e == null || typeof e == "string" && e.trim() === "" || Array.isArray(e) && e.length === 0);
|
|
29
|
+
}
|
|
30
|
+
const h = x(() => {
|
|
31
|
+
const e = [];
|
|
32
|
+
for (const [t, s] of Object.entries(l.filterDisplay)) {
|
|
33
|
+
const c = l.filterValues[t];
|
|
34
|
+
if (C(c)) continue;
|
|
35
|
+
const g = s.displayValue ? s.displayValue(c) : String(c);
|
|
36
|
+
g.trim() !== "" && e.push({
|
|
37
|
+
key: t,
|
|
38
|
+
label: s.label,
|
|
39
|
+
value: g
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return e;
|
|
43
|
+
});
|
|
44
|
+
function _() {
|
|
45
|
+
a("update:collapsed", !l.collapsed);
|
|
46
|
+
}
|
|
47
|
+
function S() {
|
|
48
|
+
const e = {};
|
|
49
|
+
for (const t of Object.keys(l.filterValues)) {
|
|
50
|
+
const s = l.filterValues[t];
|
|
51
|
+
typeof s == "string" ? e[t] = "" : Array.isArray(s) ? e[t] = [] : e[t] = null;
|
|
52
|
+
}
|
|
53
|
+
a("update:filterValues", e), a("reset");
|
|
54
|
+
}
|
|
55
|
+
function A() {
|
|
56
|
+
a("search");
|
|
57
|
+
}
|
|
58
|
+
function j(e) {
|
|
59
|
+
const t = { ...l.filterValues }, s = t[e];
|
|
60
|
+
typeof s == "string" ? t[e] = "" : Array.isArray(s) ? t[e] = [] : t[e] = null, a("update:filterValues", t);
|
|
61
|
+
}
|
|
62
|
+
return (e, t) => (o(), u("div", {
|
|
63
|
+
class: v(p(L)("j-filter-bar w-full rounded-sm border bg-card text-card-foreground", l.class))
|
|
64
|
+
}, [
|
|
65
|
+
n("div", M, [
|
|
66
|
+
n("div", X, [
|
|
67
|
+
r.collapsible ? (o(), u("button", {
|
|
68
|
+
key: 0,
|
|
69
|
+
type: "button",
|
|
70
|
+
class: "flex items-center justify-center h-6 w-6 rounded hover:bg-accent hover:text-accent-foreground transition-colors",
|
|
71
|
+
onClick: _
|
|
72
|
+
}, [
|
|
73
|
+
b(p(N), {
|
|
74
|
+
class: v([
|
|
75
|
+
"h-3.5 w-3.5 transition-transform",
|
|
76
|
+
y.value ? "rotate-0" : "-rotate-90"
|
|
77
|
+
])
|
|
78
|
+
}, null, 8, ["class"])
|
|
79
|
+
])) : i("", !0),
|
|
80
|
+
r.title ? (o(), f(O, {
|
|
81
|
+
key: 1,
|
|
82
|
+
text: r.title,
|
|
83
|
+
class: "text-sm font-semibold text-foreground"
|
|
84
|
+
}, null, 8, ["text"])) : i("", !0),
|
|
85
|
+
h.value.length > 0 ? (o(), u("div", q, [
|
|
86
|
+
(o(!0), u($, null, z(h.value, (s) => (o(), f(J, {
|
|
87
|
+
key: s.key,
|
|
88
|
+
variant: "secondary",
|
|
89
|
+
size: "sm",
|
|
90
|
+
class: "flex items-center gap-1 cursor-default"
|
|
91
|
+
}, {
|
|
92
|
+
default: m(() => [
|
|
93
|
+
n("span", G, d(s.label) + ":", 1),
|
|
94
|
+
n("span", null, d(s.value), 1),
|
|
95
|
+
n("button", {
|
|
96
|
+
type: "button",
|
|
97
|
+
class: "ml-0.5 rounded-full hover:bg-gray-300 p-0.5 transition-colors",
|
|
98
|
+
onClick: E((c) => j(s.key), ["stop"])
|
|
99
|
+
}, [
|
|
100
|
+
b(p(R), { class: "h-3 w-3" })
|
|
101
|
+
], 8, H)
|
|
102
|
+
]),
|
|
103
|
+
_: 2
|
|
104
|
+
}, 1024))), 128))
|
|
105
|
+
])) : i("", !0)
|
|
106
|
+
]),
|
|
107
|
+
n("div", I, [
|
|
108
|
+
V(e.$slots, "actions", {}, void 0, !0),
|
|
109
|
+
r.showResetButton ? (o(), f(k, {
|
|
110
|
+
key: 0,
|
|
111
|
+
variant: "secondary",
|
|
112
|
+
size: "sm",
|
|
113
|
+
onClick: S
|
|
114
|
+
}, {
|
|
115
|
+
default: m(() => [
|
|
116
|
+
B(d(r.resetButtonText), 1)
|
|
117
|
+
]),
|
|
118
|
+
_: 1
|
|
119
|
+
})) : i("", !0),
|
|
120
|
+
r.showSearchButton ? (o(), f(k, {
|
|
121
|
+
key: 1,
|
|
122
|
+
styletype: "primary",
|
|
123
|
+
size: "sm",
|
|
124
|
+
onClick: A
|
|
125
|
+
}, {
|
|
126
|
+
default: m(() => [
|
|
127
|
+
B(d(r.searchButtonText), 1)
|
|
128
|
+
]),
|
|
129
|
+
_: 1
|
|
130
|
+
})) : i("", !0)
|
|
131
|
+
])
|
|
132
|
+
]),
|
|
133
|
+
T(n("div", K, [
|
|
134
|
+
V(e.$slots, "filters", {}, void 0, !0)
|
|
135
|
+
], 512), [
|
|
136
|
+
[F, y.value]
|
|
137
|
+
])
|
|
138
|
+
], 2));
|
|
139
|
+
}
|
|
140
|
+
});
|
|
2
141
|
export {
|
|
3
|
-
|
|
142
|
+
ee as default
|
|
4
143
|
};
|
|
5
144
|
//# sourceMappingURL=JFilterBar.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JFilterBar.vue2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
1
|
+
{"version":3,"file":"JFilterBar.vue2.js","sources":["../../../../src/components/organisms/JFilterBar.vue"],"sourcesContent":["<template>\r\n <div :class=\"cn('j-filter-bar w-full rounded-sm border bg-card text-card-foreground', props.class)\">\r\n <!-- Row 1: toolbar -->\r\n <div class=\"flex items-center justify-between px-3 py-1.5\">\r\n <div class=\"flex items-center gap-2\">\r\n <button\r\n v-if=\"collapsible\"\r\n type=\"button\"\r\n class=\"flex items-center justify-center h-6 w-6 rounded hover:bg-accent hover:text-accent-foreground transition-colors\"\r\n @click=\"toggleCollapsed\"\r\n >\r\n <ChevronDown\r\n :class=\"[\r\n 'h-3.5 w-3.5 transition-transform',\r\n isExpanded ? 'rotate-0' : '-rotate-90',\r\n ]\"\r\n />\r\n </button>\r\n <!-- 타이틀 -->\r\n <JLabel\r\n v-if=\"title\"\r\n :text=\"title\"\r\n class=\"text-sm font-semibold text-foreground\"\r\n />\r\n <!-- 선택된 필터 뱃지 표시 -->\r\n <div v-if=\"activeFilters.length > 0\" class=\"flex items-center gap-1 flex-wrap\">\r\n <JBadge\r\n v-for=\"filter in activeFilters\"\r\n :key=\"filter.key\"\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n class=\"flex items-center gap-1 cursor-default\"\r\n >\r\n <span class=\"text-muted-foreground\">{{ filter.label }}:</span>\r\n <span>{{ filter.value }}</span>\r\n <button\r\n type=\"button\"\r\n class=\"ml-0.5 rounded-full hover:bg-gray-300 p-0.5 transition-colors\"\r\n @click.stop=\"removeFilter(filter.key)\"\r\n >\r\n <X class=\"h-3 w-3\" />\r\n </button>\r\n </JBadge>\r\n </div>\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n <slot name=\"actions\" />\r\n <JButton\r\n v-if=\"showResetButton\"\r\n variant=\"secondary\"\r\n size=\"sm\"\r\n @click=\"handleReset\"\r\n >\r\n {{ resetButtonText }}\r\n </JButton>\r\n <JButton\r\n v-if=\"showSearchButton\"\r\n styletype=\"primary\"\r\n size=\"sm\"\r\n @click=\"handleSearch\"\r\n >\r\n {{ searchButtonText }}\r\n </JButton>\r\n </div>\r\n </div>\r\n\r\n <!-- Row 2: filters -->\r\n <div v-show=\"isExpanded\" class=\"px-3 pb-3\">\r\n <slot name=\"filters\" />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { ChevronDown, X } from 'lucide-vue-next'\r\nimport JBadge from '@/components/atoms/JBadge.vue'\r\nimport JButton from '@/components/atoms/JButton.vue'\r\nimport JLabel from '@/components/atoms/JLabel.vue'\r\nimport { cn } from '@/lib/utils'\r\n\r\n/** 활성 필터 아이템 타입 */\r\nexport interface ActiveFilterItem {\r\n /** 필터 식별 키 */\r\n key: string\r\n /** 표시할 라벨 (필터명) */\r\n label: string\r\n /** 표시할 값 */\r\n value: string\r\n}\r\n\r\n/** 필터 설정 타입 */\r\nexport interface FilterDisplayItem {\r\n /** 표시할 라벨 */\r\n label: string\r\n /** 값을 표시용 문자열로 변환 (예: combo value -> label) */\r\n displayValue?: (value: unknown) => string\r\n}\r\n\r\nexport interface JFilterBarProps {\r\n /** 추가 클래스 (외부 커스터마이징용) */\r\n class?: string\r\n /** 필터바 타이틀 */\r\n title?: string\r\n /** 필터 접힘 상태 (v-model 지원) */\r\n collapsed?: boolean\r\n /** 접기/펼치기 가능 여부. false면 토글 버튼 숨김 & 필터 항상 표시 */\r\n collapsible?: boolean\r\n /** 필터 값 객체 (v-model:filterValues 지원) */\r\n filterValues?: Record<string, unknown>\r\n /** 필터 표시 설정 (label, displayValue 등) */\r\n filterDisplay?: Record<string, FilterDisplayItem>\r\n /** 초기화 버튼 표시 여부 */\r\n showResetButton?: boolean\r\n /** 조회 버튼 표시 여부 */\r\n showSearchButton?: boolean\r\n /** 초기화 버튼 텍스트 */\r\n resetButtonText?: string\r\n /** 조회 버튼 텍스트 */\r\n searchButtonText?: string\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFilterBarProps>(), {\r\n collapsed: true,\r\n collapsible: true,\r\n filterValues: () => ({}),\r\n filterDisplay: () => ({}),\r\n showResetButton: false,\r\n showSearchButton: false,\r\n resetButtonText: '초기화',\r\n searchButtonText: '조회',\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:collapsed': [value: boolean]\r\n 'update:filterValues': [value: Record<string, unknown>]\r\n /** 조회 버튼 클릭 */\r\n search: []\r\n /** 초기화 버튼 클릭 */\r\n reset: []\r\n}>()\r\n\r\nconst isExpanded = computed(() => {\r\n if (!props.collapsible) return true\r\n return !props.collapsed\r\n})\r\n\r\n/** 값이 비어있는지 확인 */\r\nfunction isEmpty(value: unknown): boolean {\r\n if (value === null || value === undefined) return true\r\n if (typeof value === 'string' && value.trim() === '') return true\r\n if (Array.isArray(value) && value.length === 0) return true\r\n return false\r\n}\r\n\r\n/** filterValues + filterDisplay 기반으로 활성 필터 목록 자동 생성 */\r\nconst activeFilters = computed<ActiveFilterItem[]>(() => {\r\n const filters: ActiveFilterItem[] = []\r\n\r\n for (const [key, config] of Object.entries(props.filterDisplay)) {\r\n const value = props.filterValues[key]\r\n if (isEmpty(value)) continue\r\n\r\n const displayValue = config.displayValue ? config.displayValue(value) : String(value)\r\n if (displayValue.trim() === '') continue\r\n\r\n filters.push({\r\n key,\r\n label: config.label,\r\n value: displayValue,\r\n })\r\n }\r\n\r\n return filters\r\n})\r\n\r\nfunction toggleCollapsed() {\r\n emit('update:collapsed', !props.collapsed)\r\n}\r\n\r\nfunction handleReset() {\r\n // filterValues의 모든 값을 초기화\r\n const resetValues: Record<string, unknown> = {}\r\n for (const key of Object.keys(props.filterValues)) {\r\n const currentValue = props.filterValues[key]\r\n if (typeof currentValue === 'string') {\r\n resetValues[key] = ''\r\n } else if (Array.isArray(currentValue)) {\r\n resetValues[key] = []\r\n } else {\r\n resetValues[key] = null\r\n }\r\n }\r\n emit('update:filterValues', resetValues)\r\n emit('reset')\r\n}\r\n\r\nfunction handleSearch() {\r\n emit('search')\r\n}\r\n\r\nfunction removeFilter(key: string) {\r\n // filterValues 업데이트 (해당 키 값을 초기화)\r\n const newValues = { ...props.filterValues }\r\n const currentValue = newValues[key]\r\n\r\n // 타입에 따라 적절한 초기값으로 설정\r\n if (typeof currentValue === 'string') {\r\n newValues[key] = ''\r\n } else if (Array.isArray(currentValue)) {\r\n newValues[key] = []\r\n } else {\r\n newValues[key] = null\r\n }\r\n\r\n emit('update:filterValues', newValues)\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n/* ========================================\r\n 패턴 3: Tabs 아래 배치 시 연결 스타일\r\n ======================================== */\r\n\r\n:deep([data-state=\"active\"]) > .j-filter-bar {\r\n border-top: none;\r\n border-top-left-radius: 0;\r\n border-top-right-radius: 0;\r\n}\r\n\r\n:deep([role=\"tabpanel\"]) .j-filter-bar {\r\n border-top: none;\r\n}\r\n</style>\r\n"],"names":["props","__props","emit","__emit","isExpanded","computed","isEmpty","value","activeFilters","filters","key","config","displayValue","toggleCollapsed","handleReset","resetValues","currentValue","handleSearch","removeFilter","newValues","_createElementBlock","_normalizeClass","_unref","cn","_createElementVNode","_hoisted_1","_hoisted_2","_createVNode","ChevronDown","_createBlock","JLabel","_openBlock","_hoisted_3","_Fragment","_renderList","filter","JBadge","_hoisted_4","_toDisplayString","_withModifiers","$event","X","_hoisted_6","_renderSlot","_ctx","JButton","_withDirectives","_hoisted_7"],"mappings":"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"}
|
|
@@ -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
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue");require("../shadcn/index.cjs");const o=require("../atoms/JButton.vue.cjs");require("lucide-vue-next");require("clsx");require("tailwind-merge");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");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");;/* empty css */;/* empty css */;/* empty css */;/* empty css */;/* empty css */const g=require("./JDynamicForm.vue.cjs");;/* empty css */;/* empty css */require("vue-router");;/* empty css */;/* empty css */;/* empty css */const h=require("../shadcn/Dialog.vue.cjs"),y=require("../shadcn/DialogContent.vue.cjs"),C=require("../shadcn/DialogHeader.vue.cjs"),V=require("../shadcn/DialogTitle.vue.cjs"),b=require("../shadcn/DialogBody.vue.cjs"),k=require("../shadcn/DialogFooter.vue.cjs"),w={class:"space-y-4"},D={key:0,class:"text-sm text-muted-foreground"},N=e.defineComponent({__name:"JFormModal",props:{open:{type:Boolean,default:!1},title:{},description:{},schema:{},modelValue:{},size:{default:"lg"},buttonType:{default:"OkCancel"},confirmText:{default:"확인"},cancelText:{default:"취소"},confirmVariant:{default:"default"},confirmDisabled:{type:Boolean,default:!1}},emits:["update:open","update:modelValue","confirm","cancel","submit","change","error"],setup(r,{expose:d,emit:s}){const n=r,u=s,a=e.ref(null),l=e.ref(n.modelValue||{}),i=e.ref(!1),m=e.computed(()=>({sm:"!max-w-sm",md:"!max-w-md",lg:"!max-w-2xl",xl:"!max-w-4xl","2xl":"!max-w-6xl",full:"!max-w-[95vw]"})[n.size]);e.watch(()=>n.modelValue,t=>{t!=null?l.value={...t}:l.value={}},{deep:!0});const f=t=>{l.value=t,u("update:modelValue",t)},q=t=>{u("change",t)},v=t=>{u("submit",t),i.value&&(u("confirm",t),i.value=!1)},p=t=>{u("error",t),i.value=!1},x=t=>{u("update:open",t)},c=()=>{i.value=!0,a.value&&a.value.submit()},_=()=>{u("cancel"),a.value&&a.value.reset()};return d({reset:()=>a.value?.reset(),submit:()=>a.value?.submit(),formState:e.computed(()=>a.value?.formState)}),(t,B)=>(e.openBlock(),e.createBlock(e.unref(h.default),{open:r.open,"onUpdate:open":x,class:e.normalizeClass(m.value)},{default:e.withCtx(()=>[e.createVNode(e.unref(y.default),null,{default:e.withCtx(()=>[r.title?(e.openBlock(),e.createBlock(e.unref(C.default),{key:0,class:"bg-muted/50 border-b"},{default:e.withCtx(()=>[e.createVNode(e.unref(V.default),null,{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(r.title),1)]),_:1})]),_:1})):e.createCommentVNode("",!0),e.createVNode(e.unref(b.default),{class:"max-h-[70vh] overflow-y-auto"},{default:e.withCtx(()=>[e.createElementVNode("div",w,[r.description?(e.openBlock(),e.createElementBlock("p",D,e.toDisplayString(r.description),1)):e.createCommentVNode("",!0),e.createVNode(e.unref(g.default),{ref_key:"dynamicFormRef",ref:a,schema:r.schema,"model-value":l.value,"onUpdate:modelValue":f,onSubmit:v,onChange:q,onError:p},null,8,["schema","model-value"]),e.renderSlot(t.$slots,"body")])]),_:3}),e.createVNode(e.unref(k.default),null,{default:e.withCtx(()=>[r.buttonType==="OkCancel"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createVNode(e.unref(o.default),{variant:"outline",onClick:_},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(r.cancelText),1)]),_:1}),e.createVNode(e.unref(o.default),{variant:r.confirmVariant,disabled:r.confirmDisabled,onClick:c},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(r.confirmText),1)]),_:1},8,["variant","disabled"])],64)):r.buttonType==="Ok"?(e.openBlock(),e.createBlock(e.unref(o.default),{key:1,variant:r.confirmVariant,disabled:r.confirmDisabled,onClick:c,class:"w-full"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(r.confirmText),1)]),_:1},8,["variant","disabled"])):e.createCommentVNode("",!0),e.renderSlot(t.$slots,"footer")]),_:3})]),_:3})]),_:3},8,["open","class"]))}});exports.default=N;
|
|
2
2
|
//# sourceMappingURL=JFormModal.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JFormModal.vue.cjs","sources":["../../../../src/components/organisms/JFormModal.vue"],"sourcesContent":["<template>\r\n <Dialog\r\n :open=\"open\"\r\n @update:open=\"onOpenChange\"\r\n :class=\"sizeClass\"\r\n >\r\n <DialogContent>\r\n <!-- Header -->\r\n <DialogHeader v-if=\"title\" class=\"bg-muted/50 border-b\">\r\n <DialogTitle>\r\n {{ title }}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <!-- Body -->\r\n <DialogBody class=\"max-h-[70vh] overflow-y-auto\">\r\n <div class=\"space-y-4\">\r\n <!-- Description -->\r\n <p v-if=\"description\" class=\"text-sm text-muted-foreground\">\r\n {{ description }}\r\n </p>\r\n\r\n <!-- JDynamicForm -->\r\n <JDynamicForm\r\n ref=\"dynamicFormRef\"\r\n :schema=\"schema\"\r\n :model-value=\"internalFormValue\"\r\n @update:model-value=\"handleFormChange\"\r\n @submit=\"handleFormSubmit\"\r\n @change=\"handleFieldChange\"\r\n @error=\"handleFormError\"\r\n />\r\n\r\n <!-- 커스텀 컨텐츠 슬롯 -->\r\n <slot name=\"body\" />\r\n </div>\r\n </DialogBody>\r\n\r\n <!-- Footer -->\r\n <DialogFooter>\r\n <!-- 확인/취소 버튼 -->\r\n <template v-if=\"buttonType === 'OkCancel'\">\r\n <JButton\r\n variant=\"outline\"\r\n @click=\"handleCancel\"\r\n >\r\n {{ cancelText }}\r\n </JButton>\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n \r\n <!-- 확인 버튼만 -->\r\n <template v-else-if=\"buttonType === 'Ok'\">\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n class=\"w-full\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n\r\n <!-- 커스텀 푸터 슬롯 -->\r\n <slot name=\"footer\" />\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport {\r\n Dialog,\r\n DialogBody,\r\n DialogContent,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/shadcn'\r\nimport { JButton } from '@/components/atoms'\r\nimport { JDynamicForm } from '@/components/organisms'\r\nimport type { FormSchema } from '@/types/dynamic-form'\r\n\r\nexport interface JFormModalProps {\r\n // 모달 표시 여부\r\n open: boolean\r\n // 헤더\r\n title?: string\r\n description?: string\r\n // 다이나믹 폼 스키마 (필수)\r\n schema: FormSchema\r\n // 폼 값\r\n modelValue?: Record<string, any>\r\n // 모달 사이즈 (유동적)\r\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n // 버튼 설정\r\n buttonType?: 'Ok' | 'OkCancel'\r\n confirmText?: string\r\n cancelText?: string\r\n confirmVariant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\r\n confirmDisabled?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFormModalProps>(), {\r\n open: false,\r\n size: 'lg',\r\n buttonType: 'OkCancel',\r\n confirmText: '확인',\r\n cancelText: '취소',\r\n confirmVariant: 'default',\r\n confirmDisabled: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:open': [value: boolean]\r\n 'update:modelValue': [value: Record<string, any>]\r\n 'confirm': [value: Record<string, any>]\r\n 'cancel': []\r\n 'submit': [value: Record<string, any>]\r\n 'change': [data: { field: string; value: any }]\r\n 'error': [errors: any]\r\n}>()\r\n\r\n// 다이나믹 폼 ref\r\nconst dynamicFormRef = ref<InstanceType<typeof JDynamicForm> | null>(null)\r\n\r\n// 내부 폼 값 관리\r\nconst internalFormValue = ref<Record<string, any>>(props.modelValue || {})\r\n// 확인 버튼 클릭 이후 검증 성공 시점에만 confirm 이벤트를 방출하기 위한 플래그\r\nconst isConfirming = ref<boolean>(false)\r\n\r\n// 사이즈 클래스 계산\r\nconst sizeClass = computed(() => {\r\n // Dialog.vue에 기본 max-w-lg가 하드코딩되어 있어 !max-w-*로 오버라이드\r\n const sizeMap: Record<NonNullable<JFormModalProps['size']>, string> = {\r\n 'sm': '!max-w-sm',\r\n 'md': '!max-w-md',\r\n 'lg': '!max-w-2xl',\r\n 'xl': '!max-w-4xl',\r\n '2xl': '!max-w-6xl',\r\n 'full': '!max-w-[95vw]'\r\n }\r\n return sizeMap[props.size]\r\n})\r\n\r\n// props.modelValue 변경 감지\r\nwatch(() => props.modelValue, (newValue) => {\r\n if (newValue != null) {\r\n internalFormValue.value = { ...newValue }\r\n } else {\r\n internalFormValue.value = {}\r\n }\r\n}, { deep: true })\r\n\r\n// 폼 변경 핸들러\r\nconst handleFormChange = (value: Record<string, any>) => {\r\n internalFormValue.value = value\r\n emit('update:modelValue', value)\r\n}\r\n\r\n// 필드 변경 핸들러\r\nconst handleFieldChange = (data: { field: string; value: any }) => {\r\n emit('change', data)\r\n}\r\n\r\n// 폼 제출 핸들러\r\nconst handleFormSubmit = (value: Record<string, any>) => {\r\n emit('submit', value)\r\n if (isConfirming.value) {\r\n emit('confirm', value)\r\n isConfirming.value = false\r\n }\r\n}\r\n\r\n// 폼 에러 핸들러\r\nconst handleFormError = (errors: any) => {\r\n emit('error', errors)\r\n // 검증 실패 시 confirm 방출을 차단\r\n isConfirming.value = false\r\n}\r\n\r\n// 모달 열기/닫기 핸들러\r\nconst onOpenChange = (value: boolean) => {\r\n emit('update:open', value)\r\n}\r\n\r\n// 확인 버튼 핸들러\r\nconst handleConfirm = () => {\r\n // 폼 제출 트리거 (검증 성공 시점에 handleFormSubmit에서 confirm 방출)\r\n isConfirming.value = true\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.submit()\r\n }\r\n}\r\n\r\n// 취소 버튼 핸들러\r\nconst handleCancel = () => {\r\n emit('cancel')\r\n // 폼 리셋\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.reset()\r\n }\r\n}\r\n\r\n// 외부에서 접근 가능한 메서드\r\ndefineExpose({\r\n reset: () => dynamicFormRef.value?.reset(),\r\n submit: () => dynamicFormRef.value?.submit(),\r\n formState: computed(() => dynamicFormRef.value?.formState),\r\n})\r\n</script>\r\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","internalFormValue","isConfirming","sizeClass","computed","watch","newValue","handleFormChange","value","handleFieldChange","data","handleFormSubmit","handleFormError","errors","onOpenChange","handleConfirm","handleCancel","__expose","_createBlock","_unref","Dialog","_createVNode","DialogContent","DialogHeader","DialogTitle","DialogBody","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_toDisplayString","JDynamicForm","_renderSlot","_ctx","DialogFooter","_Fragment","JButton"],"mappings":"
|
|
1
|
+
{"version":3,"file":"JFormModal.vue.cjs","sources":["../../../../src/components/organisms/JFormModal.vue"],"sourcesContent":["<template>\r\n <Dialog\r\n :open=\"open\"\r\n @update:open=\"onOpenChange\"\r\n :class=\"sizeClass\"\r\n >\r\n <DialogContent>\r\n <!-- Header -->\r\n <DialogHeader v-if=\"title\" class=\"bg-muted/50 border-b\">\r\n <DialogTitle>\r\n {{ title }}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <!-- Body -->\r\n <DialogBody class=\"max-h-[70vh] overflow-y-auto\">\r\n <div class=\"space-y-4\">\r\n <!-- Description -->\r\n <p v-if=\"description\" class=\"text-sm text-muted-foreground\">\r\n {{ description }}\r\n </p>\r\n\r\n <!-- JDynamicForm -->\r\n <JDynamicForm\r\n ref=\"dynamicFormRef\"\r\n :schema=\"schema\"\r\n :model-value=\"internalFormValue\"\r\n @update:model-value=\"handleFormChange\"\r\n @submit=\"handleFormSubmit\"\r\n @change=\"handleFieldChange\"\r\n @error=\"handleFormError\"\r\n />\r\n\r\n <!-- 커스텀 컨텐츠 슬롯 -->\r\n <slot name=\"body\" />\r\n </div>\r\n </DialogBody>\r\n\r\n <!-- Footer -->\r\n <DialogFooter>\r\n <!-- 확인/취소 버튼 -->\r\n <template v-if=\"buttonType === 'OkCancel'\">\r\n <JButton\r\n variant=\"outline\"\r\n @click=\"handleCancel\"\r\n >\r\n {{ cancelText }}\r\n </JButton>\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n \r\n <!-- 확인 버튼만 -->\r\n <template v-else-if=\"buttonType === 'Ok'\">\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n class=\"w-full\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n\r\n <!-- 커스텀 푸터 슬롯 -->\r\n <slot name=\"footer\" />\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport {\r\n Dialog,\r\n DialogBody,\r\n DialogContent,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/shadcn'\r\nimport { JButton } from '@/components/atoms'\r\nimport { JDynamicForm } from '@/components/organisms'\r\nimport type { FormSchema } from '@/types/dynamic-form'\r\n\r\nexport interface JFormModalProps {\r\n // 모달 표시 여부\r\n open: boolean\r\n // 헤더\r\n title?: string\r\n description?: string\r\n // 다이나믹 폼 스키마 (필수)\r\n schema: FormSchema\r\n // 폼 값\r\n modelValue?: Record<string, any>\r\n // 모달 사이즈 (유동적)\r\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n // 버튼 설정\r\n buttonType?: 'Ok' | 'OkCancel'\r\n confirmText?: string\r\n cancelText?: string\r\n confirmVariant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\r\n confirmDisabled?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFormModalProps>(), {\r\n open: false,\r\n size: 'lg',\r\n buttonType: 'OkCancel',\r\n confirmText: '확인',\r\n cancelText: '취소',\r\n confirmVariant: 'default',\r\n confirmDisabled: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:open': [value: boolean]\r\n 'update:modelValue': [value: Record<string, any>]\r\n 'confirm': [value: Record<string, any>]\r\n 'cancel': []\r\n 'submit': [value: Record<string, any>]\r\n 'change': [data: { field: string; value: any }]\r\n 'error': [errors: any]\r\n}>()\r\n\r\n// 다이나믹 폼 ref\r\nconst dynamicFormRef = ref<InstanceType<typeof JDynamicForm> | null>(null)\r\n\r\n// 내부 폼 값 관리\r\nconst internalFormValue = ref<Record<string, any>>(props.modelValue || {})\r\n// 확인 버튼 클릭 이후 검증 성공 시점에만 confirm 이벤트를 방출하기 위한 플래그\r\nconst isConfirming = ref<boolean>(false)\r\n\r\n// 사이즈 클래스 계산\r\nconst sizeClass = computed(() => {\r\n // Dialog.vue에 기본 max-w-lg가 하드코딩되어 있어 !max-w-*로 오버라이드\r\n const sizeMap: Record<NonNullable<JFormModalProps['size']>, string> = {\r\n 'sm': '!max-w-sm',\r\n 'md': '!max-w-md',\r\n 'lg': '!max-w-2xl',\r\n 'xl': '!max-w-4xl',\r\n '2xl': '!max-w-6xl',\r\n 'full': '!max-w-[95vw]'\r\n }\r\n return sizeMap[props.size]\r\n})\r\n\r\n// props.modelValue 변경 감지\r\nwatch(() => props.modelValue, (newValue) => {\r\n if (newValue != null) {\r\n internalFormValue.value = { ...newValue }\r\n } else {\r\n internalFormValue.value = {}\r\n }\r\n}, { deep: true })\r\n\r\n// 폼 변경 핸들러\r\nconst handleFormChange = (value: Record<string, any>) => {\r\n internalFormValue.value = value\r\n emit('update:modelValue', value)\r\n}\r\n\r\n// 필드 변경 핸들러\r\nconst handleFieldChange = (data: { field: string; value: any }) => {\r\n emit('change', data)\r\n}\r\n\r\n// 폼 제출 핸들러\r\nconst handleFormSubmit = (value: Record<string, any>) => {\r\n emit('submit', value)\r\n if (isConfirming.value) {\r\n emit('confirm', value)\r\n isConfirming.value = false\r\n }\r\n}\r\n\r\n// 폼 에러 핸들러\r\nconst handleFormError = (errors: any) => {\r\n emit('error', errors)\r\n // 검증 실패 시 confirm 방출을 차단\r\n isConfirming.value = false\r\n}\r\n\r\n// 모달 열기/닫기 핸들러\r\nconst onOpenChange = (value: boolean) => {\r\n emit('update:open', value)\r\n}\r\n\r\n// 확인 버튼 핸들러\r\nconst handleConfirm = () => {\r\n // 폼 제출 트리거 (검증 성공 시점에 handleFormSubmit에서 confirm 방출)\r\n isConfirming.value = true\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.submit()\r\n }\r\n}\r\n\r\n// 취소 버튼 핸들러\r\nconst handleCancel = () => {\r\n emit('cancel')\r\n // 폼 리셋\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.reset()\r\n }\r\n}\r\n\r\n// 외부에서 접근 가능한 메서드\r\ndefineExpose({\r\n reset: () => dynamicFormRef.value?.reset(),\r\n submit: () => dynamicFormRef.value?.submit(),\r\n formState: computed(() => dynamicFormRef.value?.formState),\r\n})\r\n</script>\r\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","internalFormValue","isConfirming","sizeClass","computed","watch","newValue","handleFormChange","value","handleFieldChange","data","handleFormSubmit","handleFormError","errors","onOpenChange","handleConfirm","handleCancel","__expose","_createBlock","_unref","Dialog","_createVNode","DialogContent","DialogHeader","DialogTitle","DialogBody","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_toDisplayString","JDynamicForm","_renderSlot","_ctx","DialogFooter","_Fragment","JButton"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineComponent as
|
|
1
|
+
import { defineComponent as S, ref as f, computed as b, watch as D, createBlock as p, openBlock as r, unref as o, normalizeClass as E, withCtx as a, createVNode as i, createCommentVNode as v, createTextVNode as s, toDisplayString as n, createElementVNode as N, createElementBlock as y, renderSlot as C, Fragment as O } from "vue";
|
|
2
2
|
import "../shadcn/index.js";
|
|
3
3
|
import h from "../atoms/JButton.vue.js";
|
|
4
4
|
import "lucide-vue-next";
|
|
@@ -22,26 +22,31 @@ 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
|
/* empty css */
|
|
27
29
|
/* empty css */
|
|
28
30
|
/* empty css */
|
|
29
31
|
/* empty css */
|
|
30
|
-
|
|
32
|
+
/* empty css */
|
|
33
|
+
import J from "./JDynamicForm.vue.js";
|
|
31
34
|
/* empty css */
|
|
35
|
+
/* empty css */
|
|
32
36
|
import "vue-router";
|
|
33
37
|
/* empty css */
|
|
34
38
|
/* empty css */
|
|
35
|
-
|
|
39
|
+
/* empty css */
|
|
40
|
+
import M from "../shadcn/Dialog.vue.js";
|
|
36
41
|
import R from "../shadcn/DialogContent.vue.js";
|
|
37
42
|
import U from "../shadcn/DialogHeader.vue.js";
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
import
|
|
41
|
-
const
|
|
43
|
+
import j from "../shadcn/DialogTitle.vue.js";
|
|
44
|
+
import q from "../shadcn/DialogBody.vue.js";
|
|
45
|
+
import A from "../shadcn/DialogFooter.vue.js";
|
|
46
|
+
const G = { class: "space-y-4" }, H = {
|
|
42
47
|
key: 0,
|
|
43
48
|
class: "text-sm text-muted-foreground"
|
|
44
|
-
},
|
|
49
|
+
}, Me = /* @__PURE__ */ S({
|
|
45
50
|
__name: "JFormModal",
|
|
46
51
|
props: {
|
|
47
52
|
open: { type: Boolean, default: !1 },
|
|
@@ -58,7 +63,7 @@ const A = { class: "space-y-4" }, G = {
|
|
|
58
63
|
},
|
|
59
64
|
emits: ["update:open", "update:modelValue", "confirm", "cancel", "submit", "change", "error"],
|
|
60
65
|
setup(t, { expose: k, emit: g }) {
|
|
61
|
-
const d = t,
|
|
66
|
+
const d = t, l = g, m = f(null), c = f(d.modelValue || {}), u = f(!1), V = b(() => ({
|
|
62
67
|
sm: "!max-w-sm",
|
|
63
68
|
md: "!max-w-md",
|
|
64
69
|
lg: "!max-w-2xl",
|
|
@@ -70,53 +75,53 @@ const A = { class: "space-y-4" }, G = {
|
|
|
70
75
|
e != null ? c.value = { ...e } : c.value = {};
|
|
71
76
|
}, { deep: !0 });
|
|
72
77
|
const w = (e) => {
|
|
73
|
-
c.value = e,
|
|
78
|
+
c.value = e, l("update:modelValue", e);
|
|
74
79
|
}, F = (e) => {
|
|
75
|
-
|
|
80
|
+
l("change", e);
|
|
76
81
|
}, T = (e) => {
|
|
77
|
-
|
|
82
|
+
l("submit", e), u.value && (l("confirm", e), u.value = !1);
|
|
78
83
|
}, $ = (e) => {
|
|
79
|
-
|
|
84
|
+
l("error", e), u.value = !1;
|
|
80
85
|
}, z = (e) => {
|
|
81
|
-
|
|
86
|
+
l("update:open", e);
|
|
82
87
|
}, x = () => {
|
|
83
|
-
|
|
84
|
-
},
|
|
85
|
-
|
|
88
|
+
u.value = !0, m.value && m.value.submit();
|
|
89
|
+
}, B = () => {
|
|
90
|
+
l("cancel"), m.value && m.value.reset();
|
|
86
91
|
};
|
|
87
92
|
return k({
|
|
88
|
-
reset: () =>
|
|
89
|
-
submit: () =>
|
|
90
|
-
formState: b(() =>
|
|
91
|
-
}), (e,
|
|
93
|
+
reset: () => m.value?.reset(),
|
|
94
|
+
submit: () => m.value?.submit(),
|
|
95
|
+
formState: b(() => m.value?.formState)
|
|
96
|
+
}), (e, I) => (r(), p(o(M), {
|
|
92
97
|
open: t.open,
|
|
93
98
|
"onUpdate:open": z,
|
|
94
99
|
class: E(V.value)
|
|
95
100
|
}, {
|
|
96
|
-
default:
|
|
97
|
-
i(
|
|
98
|
-
default:
|
|
99
|
-
t.title ? (
|
|
101
|
+
default: a(() => [
|
|
102
|
+
i(o(R), null, {
|
|
103
|
+
default: a(() => [
|
|
104
|
+
t.title ? (r(), p(o(U), {
|
|
100
105
|
key: 0,
|
|
101
106
|
class: "bg-muted/50 border-b"
|
|
102
107
|
}, {
|
|
103
|
-
default:
|
|
104
|
-
i(
|
|
105
|
-
default:
|
|
106
|
-
|
|
108
|
+
default: a(() => [
|
|
109
|
+
i(o(j), null, {
|
|
110
|
+
default: a(() => [
|
|
111
|
+
s(n(t.title), 1)
|
|
107
112
|
]),
|
|
108
113
|
_: 1
|
|
109
114
|
})
|
|
110
115
|
]),
|
|
111
116
|
_: 1
|
|
112
117
|
})) : v("", !0),
|
|
113
|
-
i(
|
|
114
|
-
default:
|
|
115
|
-
N("div",
|
|
116
|
-
t.description ? (
|
|
117
|
-
i(
|
|
118
|
+
i(o(q), { class: "max-h-[70vh] overflow-y-auto" }, {
|
|
119
|
+
default: a(() => [
|
|
120
|
+
N("div", G, [
|
|
121
|
+
t.description ? (r(), y("p", H, n(t.description), 1)) : v("", !0),
|
|
122
|
+
i(o(J), {
|
|
118
123
|
ref_key: "dynamicFormRef",
|
|
119
|
-
ref:
|
|
124
|
+
ref: m,
|
|
120
125
|
schema: t.schema,
|
|
121
126
|
"model-value": c.value,
|
|
122
127
|
"onUpdate:modelValue": w,
|
|
@@ -129,37 +134,37 @@ const A = { class: "space-y-4" }, G = {
|
|
|
129
134
|
]),
|
|
130
135
|
_: 3
|
|
131
136
|
}),
|
|
132
|
-
i(
|
|
133
|
-
default:
|
|
134
|
-
t.buttonType === "OkCancel" ? (
|
|
135
|
-
i(
|
|
137
|
+
i(o(A), null, {
|
|
138
|
+
default: a(() => [
|
|
139
|
+
t.buttonType === "OkCancel" ? (r(), y(O, { key: 0 }, [
|
|
140
|
+
i(o(h), {
|
|
136
141
|
variant: "outline",
|
|
137
|
-
onClick:
|
|
142
|
+
onClick: B
|
|
138
143
|
}, {
|
|
139
|
-
default:
|
|
140
|
-
|
|
144
|
+
default: a(() => [
|
|
145
|
+
s(n(t.cancelText), 1)
|
|
141
146
|
]),
|
|
142
147
|
_: 1
|
|
143
148
|
}),
|
|
144
|
-
i(
|
|
149
|
+
i(o(h), {
|
|
145
150
|
variant: t.confirmVariant,
|
|
146
151
|
disabled: t.confirmDisabled,
|
|
147
152
|
onClick: x
|
|
148
153
|
}, {
|
|
149
|
-
default:
|
|
150
|
-
|
|
154
|
+
default: a(() => [
|
|
155
|
+
s(n(t.confirmText), 1)
|
|
151
156
|
]),
|
|
152
157
|
_: 1
|
|
153
158
|
}, 8, ["variant", "disabled"])
|
|
154
|
-
], 64)) : t.buttonType === "Ok" ? (
|
|
159
|
+
], 64)) : t.buttonType === "Ok" ? (r(), p(o(h), {
|
|
155
160
|
key: 1,
|
|
156
161
|
variant: t.confirmVariant,
|
|
157
162
|
disabled: t.confirmDisabled,
|
|
158
163
|
onClick: x,
|
|
159
164
|
class: "w-full"
|
|
160
165
|
}, {
|
|
161
|
-
default:
|
|
162
|
-
|
|
166
|
+
default: a(() => [
|
|
167
|
+
s(n(t.confirmText), 1)
|
|
163
168
|
]),
|
|
164
169
|
_: 1
|
|
165
170
|
}, 8, ["variant", "disabled"])) : v("", !0),
|
|
@@ -176,6 +181,6 @@ const A = { class: "space-y-4" }, G = {
|
|
|
176
181
|
}
|
|
177
182
|
});
|
|
178
183
|
export {
|
|
179
|
-
|
|
184
|
+
Me as default
|
|
180
185
|
};
|
|
181
186
|
//# sourceMappingURL=JFormModal.vue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JFormModal.vue.js","sources":["../../../../src/components/organisms/JFormModal.vue"],"sourcesContent":["<template>\r\n <Dialog\r\n :open=\"open\"\r\n @update:open=\"onOpenChange\"\r\n :class=\"sizeClass\"\r\n >\r\n <DialogContent>\r\n <!-- Header -->\r\n <DialogHeader v-if=\"title\" class=\"bg-muted/50 border-b\">\r\n <DialogTitle>\r\n {{ title }}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <!-- Body -->\r\n <DialogBody class=\"max-h-[70vh] overflow-y-auto\">\r\n <div class=\"space-y-4\">\r\n <!-- Description -->\r\n <p v-if=\"description\" class=\"text-sm text-muted-foreground\">\r\n {{ description }}\r\n </p>\r\n\r\n <!-- JDynamicForm -->\r\n <JDynamicForm\r\n ref=\"dynamicFormRef\"\r\n :schema=\"schema\"\r\n :model-value=\"internalFormValue\"\r\n @update:model-value=\"handleFormChange\"\r\n @submit=\"handleFormSubmit\"\r\n @change=\"handleFieldChange\"\r\n @error=\"handleFormError\"\r\n />\r\n\r\n <!-- 커스텀 컨텐츠 슬롯 -->\r\n <slot name=\"body\" />\r\n </div>\r\n </DialogBody>\r\n\r\n <!-- Footer -->\r\n <DialogFooter>\r\n <!-- 확인/취소 버튼 -->\r\n <template v-if=\"buttonType === 'OkCancel'\">\r\n <JButton\r\n variant=\"outline\"\r\n @click=\"handleCancel\"\r\n >\r\n {{ cancelText }}\r\n </JButton>\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n \r\n <!-- 확인 버튼만 -->\r\n <template v-else-if=\"buttonType === 'Ok'\">\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n class=\"w-full\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n\r\n <!-- 커스텀 푸터 슬롯 -->\r\n <slot name=\"footer\" />\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport {\r\n Dialog,\r\n DialogBody,\r\n DialogContent,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/shadcn'\r\nimport { JButton } from '@/components/atoms'\r\nimport { JDynamicForm } from '@/components/organisms'\r\nimport type { FormSchema } from '@/types/dynamic-form'\r\n\r\nexport interface JFormModalProps {\r\n // 모달 표시 여부\r\n open: boolean\r\n // 헤더\r\n title?: string\r\n description?: string\r\n // 다이나믹 폼 스키마 (필수)\r\n schema: FormSchema\r\n // 폼 값\r\n modelValue?: Record<string, any>\r\n // 모달 사이즈 (유동적)\r\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n // 버튼 설정\r\n buttonType?: 'Ok' | 'OkCancel'\r\n confirmText?: string\r\n cancelText?: string\r\n confirmVariant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\r\n confirmDisabled?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFormModalProps>(), {\r\n open: false,\r\n size: 'lg',\r\n buttonType: 'OkCancel',\r\n confirmText: '확인',\r\n cancelText: '취소',\r\n confirmVariant: 'default',\r\n confirmDisabled: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:open': [value: boolean]\r\n 'update:modelValue': [value: Record<string, any>]\r\n 'confirm': [value: Record<string, any>]\r\n 'cancel': []\r\n 'submit': [value: Record<string, any>]\r\n 'change': [data: { field: string; value: any }]\r\n 'error': [errors: any]\r\n}>()\r\n\r\n// 다이나믹 폼 ref\r\nconst dynamicFormRef = ref<InstanceType<typeof JDynamicForm> | null>(null)\r\n\r\n// 내부 폼 값 관리\r\nconst internalFormValue = ref<Record<string, any>>(props.modelValue || {})\r\n// 확인 버튼 클릭 이후 검증 성공 시점에만 confirm 이벤트를 방출하기 위한 플래그\r\nconst isConfirming = ref<boolean>(false)\r\n\r\n// 사이즈 클래스 계산\r\nconst sizeClass = computed(() => {\r\n // Dialog.vue에 기본 max-w-lg가 하드코딩되어 있어 !max-w-*로 오버라이드\r\n const sizeMap: Record<NonNullable<JFormModalProps['size']>, string> = {\r\n 'sm': '!max-w-sm',\r\n 'md': '!max-w-md',\r\n 'lg': '!max-w-2xl',\r\n 'xl': '!max-w-4xl',\r\n '2xl': '!max-w-6xl',\r\n 'full': '!max-w-[95vw]'\r\n }\r\n return sizeMap[props.size]\r\n})\r\n\r\n// props.modelValue 변경 감지\r\nwatch(() => props.modelValue, (newValue) => {\r\n if (newValue != null) {\r\n internalFormValue.value = { ...newValue }\r\n } else {\r\n internalFormValue.value = {}\r\n }\r\n}, { deep: true })\r\n\r\n// 폼 변경 핸들러\r\nconst handleFormChange = (value: Record<string, any>) => {\r\n internalFormValue.value = value\r\n emit('update:modelValue', value)\r\n}\r\n\r\n// 필드 변경 핸들러\r\nconst handleFieldChange = (data: { field: string; value: any }) => {\r\n emit('change', data)\r\n}\r\n\r\n// 폼 제출 핸들러\r\nconst handleFormSubmit = (value: Record<string, any>) => {\r\n emit('submit', value)\r\n if (isConfirming.value) {\r\n emit('confirm', value)\r\n isConfirming.value = false\r\n }\r\n}\r\n\r\n// 폼 에러 핸들러\r\nconst handleFormError = (errors: any) => {\r\n emit('error', errors)\r\n // 검증 실패 시 confirm 방출을 차단\r\n isConfirming.value = false\r\n}\r\n\r\n// 모달 열기/닫기 핸들러\r\nconst onOpenChange = (value: boolean) => {\r\n emit('update:open', value)\r\n}\r\n\r\n// 확인 버튼 핸들러\r\nconst handleConfirm = () => {\r\n // 폼 제출 트리거 (검증 성공 시점에 handleFormSubmit에서 confirm 방출)\r\n isConfirming.value = true\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.submit()\r\n }\r\n}\r\n\r\n// 취소 버튼 핸들러\r\nconst handleCancel = () => {\r\n emit('cancel')\r\n // 폼 리셋\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.reset()\r\n }\r\n}\r\n\r\n// 외부에서 접근 가능한 메서드\r\ndefineExpose({\r\n reset: () => dynamicFormRef.value?.reset(),\r\n submit: () => dynamicFormRef.value?.submit(),\r\n formState: computed(() => dynamicFormRef.value?.formState),\r\n})\r\n</script>\r\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","internalFormValue","isConfirming","sizeClass","computed","watch","newValue","handleFormChange","value","handleFieldChange","data","handleFormSubmit","handleFormError","errors","onOpenChange","handleConfirm","handleCancel","__expose","_createBlock","_unref","Dialog","_createVNode","DialogContent","DialogHeader","DialogTitle","DialogBody","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_toDisplayString","JDynamicForm","_renderSlot","_ctx","DialogFooter","_Fragment","JButton"],"mappings":"
|
|
1
|
+
{"version":3,"file":"JFormModal.vue.js","sources":["../../../../src/components/organisms/JFormModal.vue"],"sourcesContent":["<template>\r\n <Dialog\r\n :open=\"open\"\r\n @update:open=\"onOpenChange\"\r\n :class=\"sizeClass\"\r\n >\r\n <DialogContent>\r\n <!-- Header -->\r\n <DialogHeader v-if=\"title\" class=\"bg-muted/50 border-b\">\r\n <DialogTitle>\r\n {{ title }}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <!-- Body -->\r\n <DialogBody class=\"max-h-[70vh] overflow-y-auto\">\r\n <div class=\"space-y-4\">\r\n <!-- Description -->\r\n <p v-if=\"description\" class=\"text-sm text-muted-foreground\">\r\n {{ description }}\r\n </p>\r\n\r\n <!-- JDynamicForm -->\r\n <JDynamicForm\r\n ref=\"dynamicFormRef\"\r\n :schema=\"schema\"\r\n :model-value=\"internalFormValue\"\r\n @update:model-value=\"handleFormChange\"\r\n @submit=\"handleFormSubmit\"\r\n @change=\"handleFieldChange\"\r\n @error=\"handleFormError\"\r\n />\r\n\r\n <!-- 커스텀 컨텐츠 슬롯 -->\r\n <slot name=\"body\" />\r\n </div>\r\n </DialogBody>\r\n\r\n <!-- Footer -->\r\n <DialogFooter>\r\n <!-- 확인/취소 버튼 -->\r\n <template v-if=\"buttonType === 'OkCancel'\">\r\n <JButton\r\n variant=\"outline\"\r\n @click=\"handleCancel\"\r\n >\r\n {{ cancelText }}\r\n </JButton>\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n \r\n <!-- 확인 버튼만 -->\r\n <template v-else-if=\"buttonType === 'Ok'\">\r\n <JButton\r\n :variant=\"confirmVariant\"\r\n :disabled=\"confirmDisabled\"\r\n @click=\"handleConfirm\"\r\n class=\"w-full\"\r\n >\r\n {{ confirmText }}\r\n </JButton>\r\n </template>\r\n\r\n <!-- 커스텀 푸터 슬롯 -->\r\n <slot name=\"footer\" />\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport {\r\n Dialog,\r\n DialogBody,\r\n DialogContent,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogTitle,\r\n} from '@/components/shadcn'\r\nimport { JButton } from '@/components/atoms'\r\nimport { JDynamicForm } from '@/components/organisms'\r\nimport type { FormSchema } from '@/types/dynamic-form'\r\n\r\nexport interface JFormModalProps {\r\n // 모달 표시 여부\r\n open: boolean\r\n // 헤더\r\n title?: string\r\n description?: string\r\n // 다이나믹 폼 스키마 (필수)\r\n schema: FormSchema\r\n // 폼 값\r\n modelValue?: Record<string, any>\r\n // 모달 사이즈 (유동적)\r\n size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n // 버튼 설정\r\n buttonType?: 'Ok' | 'OkCancel'\r\n confirmText?: string\r\n cancelText?: string\r\n confirmVariant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\r\n confirmDisabled?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFormModalProps>(), {\r\n open: false,\r\n size: 'lg',\r\n buttonType: 'OkCancel',\r\n confirmText: '확인',\r\n cancelText: '취소',\r\n confirmVariant: 'default',\r\n confirmDisabled: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n 'update:open': [value: boolean]\r\n 'update:modelValue': [value: Record<string, any>]\r\n 'confirm': [value: Record<string, any>]\r\n 'cancel': []\r\n 'submit': [value: Record<string, any>]\r\n 'change': [data: { field: string; value: any }]\r\n 'error': [errors: any]\r\n}>()\r\n\r\n// 다이나믹 폼 ref\r\nconst dynamicFormRef = ref<InstanceType<typeof JDynamicForm> | null>(null)\r\n\r\n// 내부 폼 값 관리\r\nconst internalFormValue = ref<Record<string, any>>(props.modelValue || {})\r\n// 확인 버튼 클릭 이후 검증 성공 시점에만 confirm 이벤트를 방출하기 위한 플래그\r\nconst isConfirming = ref<boolean>(false)\r\n\r\n// 사이즈 클래스 계산\r\nconst sizeClass = computed(() => {\r\n // Dialog.vue에 기본 max-w-lg가 하드코딩되어 있어 !max-w-*로 오버라이드\r\n const sizeMap: Record<NonNullable<JFormModalProps['size']>, string> = {\r\n 'sm': '!max-w-sm',\r\n 'md': '!max-w-md',\r\n 'lg': '!max-w-2xl',\r\n 'xl': '!max-w-4xl',\r\n '2xl': '!max-w-6xl',\r\n 'full': '!max-w-[95vw]'\r\n }\r\n return sizeMap[props.size]\r\n})\r\n\r\n// props.modelValue 변경 감지\r\nwatch(() => props.modelValue, (newValue) => {\r\n if (newValue != null) {\r\n internalFormValue.value = { ...newValue }\r\n } else {\r\n internalFormValue.value = {}\r\n }\r\n}, { deep: true })\r\n\r\n// 폼 변경 핸들러\r\nconst handleFormChange = (value: Record<string, any>) => {\r\n internalFormValue.value = value\r\n emit('update:modelValue', value)\r\n}\r\n\r\n// 필드 변경 핸들러\r\nconst handleFieldChange = (data: { field: string; value: any }) => {\r\n emit('change', data)\r\n}\r\n\r\n// 폼 제출 핸들러\r\nconst handleFormSubmit = (value: Record<string, any>) => {\r\n emit('submit', value)\r\n if (isConfirming.value) {\r\n emit('confirm', value)\r\n isConfirming.value = false\r\n }\r\n}\r\n\r\n// 폼 에러 핸들러\r\nconst handleFormError = (errors: any) => {\r\n emit('error', errors)\r\n // 검증 실패 시 confirm 방출을 차단\r\n isConfirming.value = false\r\n}\r\n\r\n// 모달 열기/닫기 핸들러\r\nconst onOpenChange = (value: boolean) => {\r\n emit('update:open', value)\r\n}\r\n\r\n// 확인 버튼 핸들러\r\nconst handleConfirm = () => {\r\n // 폼 제출 트리거 (검증 성공 시점에 handleFormSubmit에서 confirm 방출)\r\n isConfirming.value = true\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.submit()\r\n }\r\n}\r\n\r\n// 취소 버튼 핸들러\r\nconst handleCancel = () => {\r\n emit('cancel')\r\n // 폼 리셋\r\n if (dynamicFormRef.value) {\r\n dynamicFormRef.value.reset()\r\n }\r\n}\r\n\r\n// 외부에서 접근 가능한 메서드\r\ndefineExpose({\r\n reset: () => dynamicFormRef.value?.reset(),\r\n submit: () => dynamicFormRef.value?.submit(),\r\n formState: computed(() => dynamicFormRef.value?.formState),\r\n})\r\n</script>\r\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","internalFormValue","isConfirming","sizeClass","computed","watch","newValue","handleFormChange","value","handleFieldChange","data","handleFormSubmit","handleFormError","errors","onOpenChange","handleConfirm","handleCancel","__expose","_createBlock","_unref","Dialog","_createVNode","DialogContent","DialogHeader","DialogTitle","DialogBody","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_toDisplayString","JDynamicForm","_renderSlot","_ctx","DialogFooter","_Fragment","JButton"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),u=require("../atoms/JIcon.vue.cjs"),K=require("../atoms/JAvatar.vue.cjs"),g=require("../atoms/JButton.vue.cjs"),N=require("../atoms/JPopover.vue.cjs"),v=require("../../lib/utils.cjs"),r=require("../../lib/theme-utils.cjs"),z=require("../../assets/images/logo-fallback.png.cjs"),W={class:"flex items-center gap-6 flex-1"},H=["src"],Q={key:1,class:"text-lg font-bold text-foreground"},X={key:2,class:"flex items-center gap-1"},Z={class:"flex items-center gap-3"},ee={class:"p-2 min-w-[200px]"},te={class:"space-y-1"},oe=["onClick"],le={key:1,class:"w-4"},ne={class:"flex-1 capitalize"},ae={key:0,class:"absolute top-0 right-0 h-4 w-4 rounded-full bg-destructive text-destructive-foreground text-xs flex items-center justify-center"},se={class:"p-2"},re={key:0,class:"max-h-96 overflow-y-auto space-y-1"},ce=["onClick"],ie={class:"flex items-start gap-2"},de={class:"flex-1 min-w-0"},ue={class:"text-sm font-medium text-foreground"},me={key:0,class:"text-xs text-muted-foreground mt-1"},fe={key:1,class:"text-xs text-muted-foreground/60 mt-1"},he={key:1,class:"p-4 text-center text-sm text-muted-foreground"},ke={class:"flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity"},ge={class:"text-sm text-foreground hidden sm:inline"},ve={class:"w-full rounded-md overflow-hidden"},pe={class:"px-3 py-2 border-b border-border"},xe={class:"text-sm font-medium text-foreground"},ye={key:0,class:"text-xs text-muted-foreground mt-0.5"},be=["disabled","onClick"],Be={class:"flex-1 text-left truncate"},_e={key:1,class:"h-px bg-muted my-1"},Ce={key:0,class:"h-px bg-muted my-1"},Te=e.defineComponent({__name:"JHeader",props:{logo:{},logoText:{default:"JWMS Portal"},navItems:{},showNotifications:{type:Boolean,default:!1},notifications:{default:()=>[]},userAvatar:{},userName:{},isLoggedIn:{type:Boolean},userEmail:{},userId:{},styletype:{default:"default"},showSidebarToggle:{type:Boolean,default:!0},isSidebarOpen:{type:Boolean,default:!0},showThemeSelector:{type:Boolean,default:!0},defaultTheme:{default:void 0},availableThemes:{default:void 0}},emits:["logoClick","navClick","notificationClick","userMenuSelect","sidebarToggle","login"],setup(l,{emit:L}){const d=l,f=L,S={default:{containerClass:"h-14 px-4 border-b border-border bg-background",navItemClass:"text-sm text-muted-foreground hover:text-foreground transition-colors px-3 py-2 rounded-md hover:bg-accent",navItemActiveClass:"text-foreground font-medium bg-accent"},minimal:{containerClass:"h-12 px-3 border-b border-border bg-background",navItemClass:"text-xs text-muted-foreground hover:text-foreground transition-colors px-2 py-1 rounded-md hover:bg-accent",navItemActiveClass:"text-foreground font-medium bg-accent"}},B=e.computed(()=>S[d.styletype]??S.default),h=e.ref(0),D=e.computed(()=>{if(d.logo)return d.logo}),_=e.computed(()=>{if(d.logo)return h.value>=1&&z.default?z.default:D.value}),O=()=>{h.value===0?h.value=1:h.value===1&&(h.value=2)},C=e.computed(()=>d.notifications?.filter(o=>!o.read).length||0),M=[{id:"profile",label:"프로필",icon:"user"},{id:"settings",label:"설정",icon:"settings"},{id:"separator",label:"",separator:!0},{id:"logout",label:"로그아웃",icon:"logOut"}],V=e.computed(()=>[{items:M}]),A=()=>{f("logoClick")},F=(o,a)=>{o.onClick?.(),f("navClick",o,a)},q=o=>{o.onClick?.(),f("notificationClick",o)},G=o=>{f("userMenuSelect",o)},J=()=>{f("login")},U=()=>{f("sidebarToggle")},m=e.ref(!1),k=e.ref(r.getDefaultTheme()),p=e.ref([]);let x=!1,y=null,b=null;const I=()=>typeof window>"u"?!1:!!(window.location?.href?.includes("storybook")||window.__STORYBOOK_GLOBALS__),T=()=>{const o=r.detectThemeClasses(),a=r.ensureDefaultTheme(o);if(d.availableThemes&&d.availableThemes.length>0){const t=a.filter(n=>d.availableThemes.includes(n));p.value=r.ensureDefaultTheme(t)}else p.value=a},$=()=>{if(typeof window>"u")return"light";const o=localStorage.getItem("theme");return o==="dark"||o==="light"?o:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"},E=o=>{x=!0;const a=document.documentElement;o==="dark"?(a.classList.add("dark"),m.value=!0):(a.classList.remove("dark"),m.value=!1),localStorage.setItem("theme",o),x=!1},P=()=>{const o=m.value?"light":"dark";E(o)},R=()=>{if(d.defaultTheme)return r.validateThemeExists(d.defaultTheme);const o=r.getStoredTheme("tweakcn-theme");return o?r.validateThemeExists(o):r.getDefaultTheme()},w=o=>{x=!0;const a=r.validateThemeExists(o),t=r.applyTheme(a);if(t){if(k.value=a,r.setStoredTheme(a,"tweakcn-theme"),I())try{const n=window.__STORYBOOK_GLOBALS__;n&&(n.theme=a)}catch{}}else{const n=r.getDefaultTheme();r.applyTheme(n),k.value=n,r.setStoredTheme(n,"tweakcn-theme")}return x=!1,t},Y=o=>{w(String(o))},j=e.computed(()=>m.value?"sun":"moon");return e.onMounted(()=>{T();const o=$();E(o);const a=R();w(a);const t=document.documentElement;m.value=t.classList.contains("dark"),y=new MutationObserver(()=>{if(x)return;const s=t.classList.contains("dark");s!==m.value&&(m.value=s,localStorage.setItem("theme",s?"dark":"light")),T();const c=Array.from(t.classList).find(i=>i.startsWith("theme-"));if(c){const i=c.replace("theme-","");p.value.includes(i)&&(k.value=i)}}),y.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),b=new MutationObserver(()=>{T()}),b.observe(document.head,{childList:!0,subtree:!0});let n=null;if(I()){const s=()=>{try{const c=window.__STORYBOOK_GLOBALS__;if(c){if(typeof c.darkMode<"u"){const i=c.darkMode;i!==m.value&&E(i?"dark":"light")}if(c.theme&&c.theme!==k.value){const i=String(c.theme);p.value.includes(i)&&w(i)}}}catch{}};s(),n=setInterval(s,500)}e.onUnmounted(()=>{y&&(y.disconnect(),y=null),b&&(b.disconnect(),b=null),n&&clearInterval(n)})}),(o,a)=>(e.openBlock(),e.createElementBlock("header",{class:e.normalizeClass(e.unref(v.cn)("flex items-center justify-between w-full",B.value.containerClass))},[e.createElementVNode("div",W,[l.showSidebarToggle?(e.openBlock(),e.createBlock(g.default,{key:0,variant:"ghost",size:"icon",class:"flex-shrink-0","aria-label":"사이드바 토글",onClick:U},{default:e.withCtx(()=>[e.createVNode(u.default,{name:"menu",size:"md"})]),_:1})):e.createCommentVNode("",!0),_.value||l.logoText?(e.openBlock(),e.createElementBlock("div",{key:1,class:"flex items-center cursor-pointer",onClick:A},[_.value&&h.value<2?(e.openBlock(),e.createElementBlock("img",{key:0,src:_.value,alt:"로고",class:"h-8 w-auto",onError:O},null,40,H)):l.logoText?(e.openBlock(),e.createElementBlock("span",Q,e.toDisplayString(l.logoText),1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),l.navItems&&l.navItems.length>0?(e.openBlock(),e.createElementBlock("nav",X,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(l.navItems,(t,n)=>(e.openBlock(),e.createBlock(g.default,{key:n,variant:"ghost",class:e.normalizeClass(e.unref(v.cn)(B.value.navItemClass,t.active&&B.value.navItemActiveClass)),onClick:s=>F(t,n)},{default:e.withCtx(()=>[t.icon?(e.openBlock(),e.createBlock(u.default,{key:0,name:t.icon,size:"sm",class:"mr-1.5"},null,8,["name"])):e.createCommentVNode("",!0),e.createTextVNode(" "+e.toDisplayString(t.label),1)]),_:2},1032,["class","onClick"]))),128))])):e.createCommentVNode("",!0)]),e.createElementVNode("div",Z,[l.showThemeSelector?(e.openBlock(),e.createBlock(N.default,{key:0,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createVNode(g.default,{variant:"ghost",size:"icon","aria-label":"테마 선택"},{default:e.withCtx(()=>[e.createVNode(u.default,{name:"palette",size:"md"})]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",ee,[a[0]||(a[0]=e.createElementVNode("div",{class:"text-xs font-medium text-muted-foreground px-2 py-1.5 mb-1"}," 테마 선택 ",-1)),e.createElementVNode("div",te,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(p.value,t=>(e.openBlock(),e.createElementBlock("button",{key:t,class:e.normalizeClass(e.unref(v.cn)("w-full flex items-center gap-2 px-2 py-1.5 text-sm rounded-md transition-colors","hover:bg-accent hover:text-accent-foreground","border-0 outline-none text-left",k.value===t&&"bg-accent text-accent-foreground font-medium")),onClick:n=>Y(t)},[k.value===t?(e.openBlock(),e.createBlock(u.default,{key:0,name:"check",size:"sm",class:"flex-shrink-0"})):(e.openBlock(),e.createElementBlock("span",le)),e.createElementVNode("span",ne,e.toDisplayString(t),1)],10,oe))),128))])])]),_:1})):e.createCommentVNode("",!0),l.showNotifications?(e.openBlock(),e.createBlock(N.default,{key:1,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createVNode(g.default,{variant:"ghost",size:"icon",class:"relative","aria-label":"알림"},{default:e.withCtx(()=>[e.createVNode(u.default,{name:"circleAlert",size:"md"}),C.value>0?(e.openBlock(),e.createElementBlock("span",ae,e.toDisplayString(C.value>9?"9+":C.value),1)):e.createCommentVNode("",!0)]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",se,[l.notifications&&l.notifications.length>0?(e.openBlock(),e.createElementBlock("div",re,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(l.notifications,t=>(e.openBlock(),e.createElementBlock("div",{key:t.id,class:e.normalizeClass(e.unref(v.cn)("p-3 rounded-md cursor-pointer transition-colors",t.read?"hover:bg-accent/50":"bg-accent")),onClick:n=>q(t)},[e.createElementVNode("div",ie,[t.icon?(e.openBlock(),e.createBlock(u.default,{key:0,name:t.icon,size:"sm",class:"mt-0.5 flex-shrink-0"},null,8,["name"])):e.createCommentVNode("",!0),e.createElementVNode("div",de,[e.createElementVNode("p",ue,e.toDisplayString(t.title),1),t.message?(e.openBlock(),e.createElementBlock("p",me,e.toDisplayString(t.message),1)):e.createCommentVNode("",!0),t.time?(e.openBlock(),e.createElementBlock("p",fe,e.toDisplayString(t.time),1)):e.createCommentVNode("",!0)])])],10,ce))),128))])):(e.openBlock(),e.createElementBlock("div",he," 알림이 없습니다. "))])]),_:1})):e.createCommentVNode("",!0),e.createVNode(g.default,{variant:"ghost",size:"icon","aria-label":m.value?"라이트 모드로 전환":"다크 모드로 전환",onClick:P},{default:e.withCtx(()=>[e.createVNode(u.default,{name:j.value,size:"md"},null,8,["name"])]),_:1},8,["aria-label"]),l.userName?(e.openBlock(),e.createBlock(N.default,{key:2,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createElementVNode("div",ke,[e.createVNode(K.default,{src:l.userAvatar,fallback:l.userName?l.userName[0]:"U",size:"sm"},null,8,["src","fallback"]),e.createElementVNode("span",ge,e.toDisplayString(l.userName),1),e.createVNode(u.default,{name:"chevronDown",size:"sm",class:"text-muted-foreground hidden sm:inline"})])]),default:e.withCtx(()=>[e.createElementVNode("div",ve,[e.createElementVNode("div",pe,[e.createElementVNode("p",xe,e.toDisplayString(l.userName),1),l.userEmail?(e.openBlock(),e.createElementBlock("p",ye,e.toDisplayString(l.userEmail),1)):e.createCommentVNode("",!0)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(V.value,(t,n)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:n},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.items,(s,c)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:s.id},[s.separator?s.separator&&c>0?(e.openBlock(),e.createElementBlock("div",_e)):e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:0,disabled:s.disabled,class:e.normalizeClass(e.unref(v.cn)("w-full flex items-center gap-2 px-3 py-1.5 text-sm transition-colors",s.id==="logout"?"text-destructive hover:bg-destructive/10 hover:text-destructive":"hover:bg-accent hover:text-accent-foreground","disabled:opacity-50 disabled:pointer-events-none","border-0 outline-none",t.items[c+1]?.separator&&"border-b-0")),onClick:i=>G(s.id)},[s.icon?(e.openBlock(),e.createBlock(u.default,{key:0,name:s.icon,size:"sm",class:e.normalizeClass(e.unref(v.cn)("flex-shrink-0",s.id==="logout"&&"text-destructive"))},null,8,["name","class"])):e.createCommentVNode("",!0),e.createElementVNode("span",Be,e.toDisplayString(s.label),1)],10,be))],64))),128)),n<V.value.length-1?(e.openBlock(),e.createElementBlock("div",Ce)):e.createCommentVNode("",!0)],64))),128))])]),_:1})):(e.openBlock(),e.createBlock(g.default,{key:3,variant:"ghost",size:"sm","aria-label":"로그인",onClick:J},{default:e.withCtx(()=>[e.createVNode(u.default,{name:"logIn",size:"sm",class:"sm:mr-1.5"}),a[1]||(a[1]=e.createElementVNode("span",{class:"hidden sm:inline"},"로그인",-1))]),_:1})),e.renderSlot(o.$slots,"actions")])],2))}});exports.default=Te;
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),m=require("../atoms/JIcon.vue.cjs"),W=require("../atoms/JAvatar.vue.cjs"),v=require("../atoms/JButton.vue.cjs"),w=require("../atoms/JPopover.vue.cjs"),g=require("../../lib/utils.cjs"),r=require("../../lib/theme-utils.cjs"),L=require("../../assets/images/logo-fallback.png.cjs"),H={class:"flex items-center gap-6 flex-1"},Q=["src"],X={key:1,class:"text-sm font-bold text-foreground"},Z={key:2,class:"flex items-center gap-1"},ee={class:"flex items-center gap-3"},te={class:"p-2 min-w-[200px]"},oe={class:"space-y-1"},le=["onClick"],ae={key:1,class:"w-4"},ne={class:"flex-1 capitalize"},se={key:0,class:"absolute top-0 right-0 h-4 w-4 rounded-full bg-destructive text-destructive-foreground text-xs flex items-center justify-center"},re={class:"p-2"},ce={key:0,class:"max-h-96 overflow-y-auto space-y-1"},ie=["onClick"],de={class:"flex items-start gap-2"},ue={class:"flex-1 min-w-0"},me={class:"text-xs font-medium text-foreground"},fe={key:0,class:"text-xs text-muted-foreground mt-1"},he={key:1,class:"text-xs text-muted-foreground/60 mt-1"},ke={key:1,class:"p-4 text-center text-xs text-muted-foreground"},ve={class:"flex items-center gap-2 cursor-pointer hover:opacity-80 transition-opacity"},ge={class:"text-xs text-foreground hidden sm:inline"},pe={class:"w-full rounded-md overflow-hidden"},xe={class:"px-3 py-1.5 border-b border-border"},be={class:"text-xs font-medium text-foreground"},ye={key:0,class:"text-xs text-muted-foreground mt-0.5"},Be=["disabled","onClick"],Ce={class:"flex-1 text-left truncate"},_e={key:1,class:"h-px bg-muted my-1"},Te={key:0,class:"h-px bg-muted my-1"},Ee=e.defineComponent({__name:"JHeader",props:{logo:{},logoText:{default:"JWMS Portal"},navItems:{},showNotifications:{type:Boolean,default:!1},notifications:{default:()=>[]},userAvatar:{},userName:{},isLoggedIn:{type:Boolean},userEmail:{},userId:{},styletype:{default:"default"},showSidebarToggle:{type:Boolean,default:!0},isSidebarOpen:{type:Boolean,default:!0},showThemeSelector:{type:Boolean,default:!0},defaultTheme:{default:void 0},availableThemes:{default:void 0}},emits:["logoClick","navClick","notificationClick","userMenuSelect","sidebarToggle","login"],setup(l,{emit:D}){const u=l,h=D,N={default:{containerClass:"h-10 px-4 border-b border-border bg-muted dark:bg-card",navItemClass:"text-xs text-muted-foreground hover:text-foreground transition-colors px-3 py-1.5 rounded-md hover:bg-accent",navItemActiveClass:"text-foreground font-medium bg-accent"},minimal:{containerClass:"h-8 px-3 border-b border-border bg-muted dark:bg-card",navItemClass:"text-xs text-muted-foreground hover:text-foreground transition-colors px-2 py-1 rounded-md hover:bg-accent",navItemActiveClass:"text-foreground font-medium bg-accent"}},C=e.computed(()=>N[u.styletype]??N.default),k=e.ref(0),M=e.computed(()=>{if(u.logo)return u.logo}),_=e.computed(()=>{if(u.logo)return k.value>=1&&L.default?L.default:M.value}),O=()=>{k.value===0?k.value=1:k.value===1&&(k.value=2)},T=e.computed(()=>u.notifications?.filter(o=>!o.read).length||0),A=[{id:"profile",label:"프로필",icon:"user"},{id:"settings",label:"설정",icon:"settings"},{id:"separator",label:"",separator:!0},{id:"logout",label:"로그아웃",icon:"logOut"}],S=e.computed(()=>[{items:A}]),F=()=>{h("logoClick")},q=(o,a)=>{o.onClick?.(),h("navClick",o,a)},J=o=>{o.onClick?.(),h("notificationClick",o)},U=o=>{h("userMenuSelect",o)},G=()=>{h("login")},$=()=>{h("sidebarToggle")},i=e.ref(!1),f=e.ref(r.getDefaultTheme()),p=e.ref([]);let x=!1,b=null,y=null;const V=()=>typeof window>"u"?!1:!!(window.location?.href?.includes("storybook")||window.__STORYBOOK_GLOBALS__),E=()=>{const o=r.detectThemeClasses(),a=r.ensureDefaultTheme(o);if(u.availableThemes&&u.availableThemes.length>0){const t=a.filter(s=>u.availableThemes.includes(s));p.value=r.ensureDefaultTheme(t)}else p.value=a},P=()=>{if(typeof window>"u")return"light";const o=localStorage.getItem("theme");return o==="dark"||o==="light"?o:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"},I=o=>{x=!0;const a=document.documentElement;o==="dark"?(a.classList.add("dark"),i.value=!0):(a.classList.remove("dark"),i.value=!1),localStorage.setItem("theme",o),x=!1},j=()=>{const o=i.value?"light":"dark";I(o)},R=()=>{if(u.defaultTheme)return r.validateThemeExists(u.defaultTheme);const o=r.getStoredTheme("tweakcn-theme");return o?r.validateThemeExists(o):r.getDefaultTheme()},z=o=>{x=!0;const a=r.validateThemeExists(o),t=r.applyTheme(a);if(t)f.value=a,V()||r.setStoredTheme(a,"tweakcn-theme");else{const s=r.getDefaultTheme();r.applyTheme(s),f.value=s,r.setStoredTheme(s,"tweakcn-theme")}return x=!1,t},Y=o=>{z(String(o))},K=e.computed(()=>i.value?"sun":"moon");return e.onMounted(()=>{E();const o=P();I(o);const a=R();z(a);const t=document.documentElement;i.value=t.classList.contains("dark"),b=new MutationObserver(()=>{if(x)return;const n=t.classList.contains("dark");n!==i.value&&(i.value=n,localStorage.setItem("theme",n?"dark":"light")),E();const c=Array.from(t.classList).find(d=>d.startsWith("theme-"));if(c){const d=c.replace("theme-","");p.value.includes(d)&&(f.value=d)}}),b.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),y=new MutationObserver(()=>{E()}),y.observe(document.head,{childList:!0,subtree:!0});let s=null;if(V()){const n=()=>{try{const c=window.__STORYBOOK_GLOBALS__;if(c){if(typeof c.darkMode<"u"){const d=c.darkMode;if(d!==i.value){const B=document.documentElement;d?(B.classList.add("dark"),i.value=!0):(B.classList.remove("dark"),i.value=!1)}}if(c.theme&&c.theme!==f.value){const d=String(c.theme);if(p.value.includes(d)){const B=r.validateThemeExists(d);r.applyTheme(B),f.value=B}}}}catch{}};n(),s=setInterval(n,200)}e.onUnmounted(()=>{b&&(b.disconnect(),b=null),y&&(y.disconnect(),y=null),s&&clearInterval(s)})}),(o,a)=>(e.openBlock(),e.createElementBlock("header",{class:e.normalizeClass(e.unref(g.cn)("flex items-center justify-between w-full",C.value.containerClass))},[e.createElementVNode("div",H,[l.showSidebarToggle?(e.openBlock(),e.createBlock(v.default,{key:0,variant:"ghost",size:"sm",class:"flex-shrink-0 w-8 h-8 p-0","aria-label":"사이드바 토글",onClick:$},{default:e.withCtx(()=>[e.createVNode(m.default,{name:"menu",size:"sm"})]),_:1})):e.createCommentVNode("",!0),_.value||l.logoText?(e.openBlock(),e.createElementBlock("div",{key:1,class:"flex items-center cursor-pointer",onClick:F},[_.value&&k.value<2?(e.openBlock(),e.createElementBlock("img",{key:0,src:_.value,alt:"로고",class:"h-6 w-auto",onError:O},null,40,Q)):l.logoText?(e.openBlock(),e.createElementBlock("span",X,e.toDisplayString(l.logoText),1)):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),l.navItems&&l.navItems.length>0?(e.openBlock(),e.createElementBlock("nav",Z,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(l.navItems,(t,s)=>(e.openBlock(),e.createBlock(v.default,{key:s,variant:"ghost",class:e.normalizeClass(e.unref(g.cn)(C.value.navItemClass,t.active&&C.value.navItemActiveClass)),onClick:n=>q(t,s)},{default:e.withCtx(()=>[t.icon?(e.openBlock(),e.createBlock(m.default,{key:0,name:t.icon,size:"sm",class:"mr-1.5"},null,8,["name"])):e.createCommentVNode("",!0),e.createTextVNode(" "+e.toDisplayString(t.label),1)]),_:2},1032,["class","onClick"]))),128))])):e.createCommentVNode("",!0)]),e.createElementVNode("div",ee,[l.showThemeSelector?(e.openBlock(),e.createBlock(w.default,{key:0,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createVNode(v.default,{variant:"ghost",size:"sm",class:"w-8 h-8 p-0","aria-label":"테마 선택"},{default:e.withCtx(()=>[e.createVNode(m.default,{name:"palette",size:"sm"})]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",te,[a[0]||(a[0]=e.createElementVNode("div",{class:"text-xs font-medium text-muted-foreground px-2 py-1.5 mb-1"}," 테마 선택 ",-1)),e.createElementVNode("div",oe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(p.value,t=>(e.openBlock(),e.createElementBlock("button",{key:t,class:e.normalizeClass(e.unref(g.cn)("w-full flex items-center gap-2 px-2 py-1.5 text-xs rounded-md transition-colors","hover:bg-accent hover:text-accent-foreground","border-0 outline-none text-left",f.value===t&&"bg-accent text-accent-foreground font-medium")),onClick:s=>Y(t)},[f.value===t?(e.openBlock(),e.createBlock(m.default,{key:0,name:"check",size:"sm",class:"flex-shrink-0"})):(e.openBlock(),e.createElementBlock("span",ae)),e.createElementVNode("span",ne,e.toDisplayString(t),1)],10,le))),128))])])]),_:1})):e.createCommentVNode("",!0),l.showNotifications?(e.openBlock(),e.createBlock(w.default,{key:1,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createVNode(v.default,{variant:"ghost",size:"sm",class:"relative w-8 h-8 p-0","aria-label":"알림"},{default:e.withCtx(()=>[e.createVNode(m.default,{name:"circleAlert",size:"sm"}),T.value>0?(e.openBlock(),e.createElementBlock("span",se,e.toDisplayString(T.value>9?"9+":T.value),1)):e.createCommentVNode("",!0)]),_:1})]),default:e.withCtx(()=>[e.createElementVNode("div",re,[l.notifications&&l.notifications.length>0?(e.openBlock(),e.createElementBlock("div",ce,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(l.notifications,t=>(e.openBlock(),e.createElementBlock("div",{key:t.id,class:e.normalizeClass(e.unref(g.cn)("p-3 rounded-md cursor-pointer transition-colors",t.read?"hover:bg-accent/50":"bg-accent")),onClick:s=>J(t)},[e.createElementVNode("div",de,[t.icon?(e.openBlock(),e.createBlock(m.default,{key:0,name:t.icon,size:"sm",class:"mt-0.5 flex-shrink-0"},null,8,["name"])):e.createCommentVNode("",!0),e.createElementVNode("div",ue,[e.createElementVNode("p",me,e.toDisplayString(t.title),1),t.message?(e.openBlock(),e.createElementBlock("p",fe,e.toDisplayString(t.message),1)):e.createCommentVNode("",!0),t.time?(e.openBlock(),e.createElementBlock("p",he,e.toDisplayString(t.time),1)):e.createCommentVNode("",!0)])])],10,ie))),128))])):(e.openBlock(),e.createElementBlock("div",ke," 알림이 없습니다. "))])]),_:1})):e.createCommentVNode("",!0),e.createVNode(v.default,{variant:"ghost",size:"sm",class:"w-8 h-8 p-0","aria-label":i.value?"라이트 모드로 전환":"다크 모드로 전환",onClick:j},{default:e.withCtx(()=>[e.createVNode(m.default,{name:K.value,size:"sm"},null,8,["name"])]),_:1},8,["aria-label"]),e.renderSlot(o.$slots,"toolbar"),l.userName?(e.openBlock(),e.createBlock(w.default,{key:2,position:"bottom",align:"end",styletype:"default-sm"},{trigger:e.withCtx(()=>[e.createElementVNode("div",ve,[e.createVNode(W.default,{src:l.userAvatar,fallback:l.userName?l.userName[0]:"U",size:"xs"},null,8,["src","fallback"]),e.createElementVNode("span",ge,e.toDisplayString(l.userName),1),e.createVNode(m.default,{name:"chevronDown",size:"sm",class:"text-muted-foreground hidden sm:inline"})])]),default:e.withCtx(()=>[e.createElementVNode("div",pe,[e.createElementVNode("div",xe,[e.createElementVNode("p",be,e.toDisplayString(l.userName),1),l.userEmail?(e.openBlock(),e.createElementBlock("p",ye,e.toDisplayString(l.userEmail),1)):e.createCommentVNode("",!0)]),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(S.value,(t,s)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:s},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.items,(n,c)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:n.id},[n.separator?n.separator&&c>0?(e.openBlock(),e.createElementBlock("div",_e)):e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("button",{key:0,disabled:n.disabled,class:e.normalizeClass(e.unref(g.cn)("w-full flex items-center gap-2 px-3 py-1.5 text-xs transition-colors",n.id==="logout"?"text-destructive hover:bg-destructive/10 hover:text-destructive":"hover:bg-accent hover:text-accent-foreground","disabled:opacity-50 disabled:pointer-events-none","border-0 outline-none",t.items[c+1]?.separator&&"border-b-0")),onClick:d=>U(n.id)},[n.icon?(e.openBlock(),e.createBlock(m.default,{key:0,name:n.icon,size:"sm",class:e.normalizeClass(e.unref(g.cn)("flex-shrink-0",n.id==="logout"&&"text-destructive"))},null,8,["name","class"])):e.createCommentVNode("",!0),e.createElementVNode("span",Ce,e.toDisplayString(n.label),1)],10,Be))],64))),128)),s<S.value.length-1?(e.openBlock(),e.createElementBlock("div",Te)):e.createCommentVNode("",!0)],64))),128))])]),_:1})):(e.openBlock(),e.createBlock(v.default,{key:3,variant:"ghost",size:"sm","aria-label":"로그인",onClick:G},{default:e.withCtx(()=>[e.createVNode(m.default,{name:"logIn",size:"sm",class:"sm:mr-1.5"}),a[1]||(a[1]=e.createElementVNode("span",{class:"hidden sm:inline"},"로그인",-1))]),_:1}))])],2))}});exports.default=Ee;
|
|
2
2
|
//# sourceMappingURL=JHeader.vue.cjs.map
|