@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.
Files changed (272) hide show
  1. package/README.md +8 -6
  2. package/assets/jwms-portal-frontend-BtHTA-UF.css +1 -0
  3. package/assets/styles/global-utilities.css +34 -0
  4. package/assets/styles/j-components.css +1 -1
  5. package/assets/styles/themes.css +128 -21
  6. package/components/atoms/JAvatar.vue.cjs +1 -1
  7. package/components/atoms/JAvatar.vue.cjs.map +1 -1
  8. package/components/atoms/JAvatar.vue.js +10 -7
  9. package/components/atoms/JAvatar.vue.js.map +1 -1
  10. package/components/atoms/JBadge.vue.cjs +1 -1
  11. package/components/atoms/JBadge.vue.cjs.map +1 -1
  12. package/components/atoms/JBadge.vue.js +7 -6
  13. package/components/atoms/JBadge.vue.js.map +1 -1
  14. package/components/atoms/JButton.vue.cjs +6 -1
  15. package/components/atoms/JButton.vue.cjs.map +1 -1
  16. package/components/atoms/JButton.vue.js +10 -85
  17. package/components/atoms/JButton.vue.js.map +1 -1
  18. package/components/atoms/JButton.vue2.cjs +1 -1
  19. package/components/atoms/JButton.vue2.cjs.map +1 -1
  20. package/components/atoms/JButton.vue2.js +85 -2
  21. package/components/atoms/JButton.vue2.js.map +1 -1
  22. package/components/atoms/JDatepicker.vue.cjs +1 -1
  23. package/components/atoms/JDatepicker.vue.cjs.map +1 -1
  24. package/components/atoms/JDatepicker.vue.js +10 -10
  25. package/components/atoms/JDatepicker.vue.js.map +1 -1
  26. package/components/atoms/JEditor.vue.cjs +1 -1
  27. package/components/atoms/JEditor.vue.js +1 -1
  28. package/components/atoms/JEditor.vue2.cjs +1 -1
  29. package/components/atoms/JEditor.vue2.cjs.map +1 -1
  30. package/components/atoms/JEditor.vue2.js +31 -17
  31. package/components/atoms/JEditor.vue2.js.map +1 -1
  32. package/components/atoms/JGrid.vue.cjs +1 -1
  33. package/components/atoms/JGrid.vue.js +2 -2
  34. package/components/atoms/JGrid.vue2.cjs +1 -1
  35. package/components/atoms/JGrid.vue2.cjs.map +1 -1
  36. package/components/atoms/JGrid.vue2.js +59 -43
  37. package/components/atoms/JGrid.vue2.js.map +1 -1
  38. package/components/atoms/JIcon.vue.cjs +1 -1
  39. package/components/atoms/JIcon.vue.cjs.map +1 -1
  40. package/components/atoms/JIcon.vue.js +14 -13
  41. package/components/atoms/JIcon.vue.js.map +1 -1
  42. package/components/atoms/JKbd.vue.cjs +1 -1
  43. package/components/atoms/JKbd.vue.cjs.map +1 -1
  44. package/components/atoms/JKbd.vue.js +13 -10
  45. package/components/atoms/JKbd.vue.js.map +1 -1
  46. package/components/atoms/JLabel.vue.cjs +1 -1
  47. package/components/atoms/JLabel.vue.cjs.map +1 -1
  48. package/components/atoms/JLabel.vue.js +26 -22
  49. package/components/atoms/JLabel.vue.js.map +1 -1
  50. package/components/atoms/JLink.vue.cjs +1 -1
  51. package/components/atoms/JLink.vue.cjs.map +1 -1
  52. package/components/atoms/JLink.vue.js +5 -5
  53. package/components/atoms/JLink.vue.js.map +1 -1
  54. package/components/atoms/JPreview.vue.cjs +1 -1
  55. package/components/atoms/JPreview.vue.js +2 -2
  56. package/components/atoms/JPreview.vue2.cjs +1 -1
  57. package/components/atoms/JPreview.vue2.cjs.map +1 -1
  58. package/components/atoms/JPreview.vue2.js +33 -20
  59. package/components/atoms/JPreview.vue2.js.map +1 -1
  60. package/components/atoms/JProgress.vue.cjs +1 -1
  61. package/components/atoms/JProgress.vue.cjs.map +1 -1
  62. package/components/atoms/JProgress.vue.js +15 -9
  63. package/components/atoms/JProgress.vue.js.map +1 -1
  64. package/components/atoms/JRadio.vue.cjs +1 -1
  65. package/components/atoms/JRadio.vue.cjs.map +1 -1
  66. package/components/atoms/JRadio.vue.js +1 -1
  67. package/components/atoms/JRadio.vue.js.map +1 -1
  68. package/components/atoms/JSearchCombo.vue.cjs +1 -1
  69. package/components/atoms/JSearchCombo.vue.cjs.map +1 -1
  70. package/components/atoms/JSearchCombo.vue.js +38 -37
  71. package/components/atoms/JSearchCombo.vue.js.map +1 -1
  72. package/components/atoms/JSectionTitle.vue.cjs +7 -0
  73. package/components/atoms/JSectionTitle.vue.cjs.map +1 -0
  74. package/components/atoms/JSectionTitle.vue.js +13 -0
  75. package/components/atoms/JSectionTitle.vue.js.map +1 -0
  76. package/components/atoms/JSectionTitle.vue2.cjs +2 -0
  77. package/components/atoms/JSectionTitle.vue2.cjs.map +1 -0
  78. package/components/atoms/JSectionTitle.vue2.js +67 -0
  79. package/components/atoms/JSectionTitle.vue2.js.map +1 -0
  80. package/components/atoms/JSpinner.vue.cjs +1 -1
  81. package/components/atoms/JSpinner.vue.cjs.map +1 -1
  82. package/components/atoms/JSpinner.vue.js +8 -7
  83. package/components/atoms/JSpinner.vue.js.map +1 -1
  84. package/components/atoms/JSplitter.vue.cjs +6 -1
  85. package/components/atoms/JSplitter.vue.cjs.map +1 -1
  86. package/components/atoms/JSplitter.vue.js +10 -54
  87. package/components/atoms/JSplitter.vue.js.map +1 -1
  88. package/components/atoms/JSplitter.vue2.cjs +1 -1
  89. package/components/atoms/JSplitter.vue2.cjs.map +1 -1
  90. package/components/atoms/JSplitter.vue2.js +59 -2
  91. package/components/atoms/JSplitter.vue2.js.map +1 -1
  92. package/components/atoms/JTooltip.vue.cjs +1 -1
  93. package/components/atoms/JTooltip.vue.cjs.map +1 -1
  94. package/components/atoms/JTooltip.vue.js +18 -15
  95. package/components/atoms/JTooltip.vue.js.map +1 -1
  96. package/components/examples/ExampleCrudPage.vue.cjs +1 -1
  97. package/components/examples/ExampleCrudPage.vue.cjs.map +1 -1
  98. package/components/examples/ExampleCrudPage.vue.js +265 -191
  99. package/components/examples/ExampleCrudPage.vue.js.map +1 -1
  100. package/components/examples/ExampleTabMappingPage.vue.cjs +1 -1
  101. package/components/examples/ExampleTabMappingPage.vue.cjs.map +1 -1
  102. package/components/examples/ExampleTabMappingPage.vue.js +349 -333
  103. package/components/examples/ExampleTabMappingPage.vue.js.map +1 -1
  104. package/components/molecules/JAlert.vue.cjs +1 -1
  105. package/components/molecules/JAlert.vue.cjs.map +1 -1
  106. package/components/molecules/JAlert.vue.js +18 -16
  107. package/components/molecules/JAlert.vue.js.map +1 -1
  108. package/components/molecules/JBreadcrumb.vue.cjs +1 -1
  109. package/components/molecules/JBreadcrumb.vue.cjs.map +1 -1
  110. package/components/molecules/JBreadcrumb.vue.js +3 -3
  111. package/components/molecules/JBreadcrumb.vue.js.map +1 -1
  112. package/components/molecules/JCard.vue.cjs +1 -1
  113. package/components/molecules/JCard.vue.cjs.map +1 -1
  114. package/components/molecules/JCard.vue.js +55 -39
  115. package/components/molecules/JCard.vue.js.map +1 -1
  116. package/components/molecules/JEmptyState.vue.cjs +7 -0
  117. package/components/molecules/JEmptyState.vue.cjs.map +1 -0
  118. package/components/molecules/JEmptyState.vue.js +13 -0
  119. package/components/molecules/JEmptyState.vue.js.map +1 -0
  120. package/components/molecules/JEmptyState.vue2.cjs +2 -0
  121. package/components/molecules/JEmptyState.vue2.cjs.map +1 -0
  122. package/components/molecules/JEmptyState.vue2.js +127 -0
  123. package/components/molecules/JEmptyState.vue2.js.map +1 -0
  124. package/components/molecules/JFormField.vue.cjs +6 -1
  125. package/components/molecules/JFormField.vue.cjs.map +1 -1
  126. package/components/molecules/JFormField.vue.js +10 -262
  127. package/components/molecules/JFormField.vue.js.map +1 -1
  128. package/components/molecules/JFormField.vue2.cjs +2 -0
  129. package/components/molecules/JFormField.vue2.cjs.map +1 -0
  130. package/components/molecules/JFormField.vue2.js +271 -0
  131. package/components/molecules/JFormField.vue2.js.map +1 -0
  132. package/components/molecules/JTabs.vue.cjs +1 -1
  133. package/components/molecules/JTabs.vue.js +1 -1
  134. package/components/molecules/JTabs.vue2.cjs +1 -1
  135. package/components/molecules/JTabs.vue2.cjs.map +1 -1
  136. package/components/molecules/JTabs.vue2.js +50 -56
  137. package/components/molecules/JTabs.vue2.js.map +1 -1
  138. package/components/molecules/JTitlebar.vue.cjs +1 -1
  139. package/components/molecules/JTitlebar.vue.cjs.map +1 -1
  140. package/components/molecules/JTitlebar.vue.js +49 -47
  141. package/components/molecules/JTitlebar.vue.js.map +1 -1
  142. package/components/organisms/JDynamicForm.vue2.cjs +1 -1
  143. package/components/organisms/JDynamicForm.vue2.cjs.map +1 -1
  144. package/components/organisms/JDynamicForm.vue2.js +35 -32
  145. package/components/organisms/JDynamicForm.vue2.js.map +1 -1
  146. package/components/organisms/JDynamicTabs.vue.cjs +1 -1
  147. package/components/organisms/JDynamicTabs.vue.cjs.map +1 -1
  148. package/components/organisms/JDynamicTabs.vue.js +47 -52
  149. package/components/organisms/JDynamicTabs.vue.js.map +1 -1
  150. package/components/organisms/JFilterBar.vue.cjs +6 -1
  151. package/components/organisms/JFilterBar.vue.cjs.map +1 -1
  152. package/components/organisms/JFilterBar.vue.js +10 -137
  153. package/components/organisms/JFilterBar.vue.js.map +1 -1
  154. package/components/organisms/JFilterBar.vue2.cjs +1 -1
  155. package/components/organisms/JFilterBar.vue2.cjs.map +1 -1
  156. package/components/organisms/JFilterBar.vue2.js +141 -2
  157. package/components/organisms/JFilterBar.vue2.js.map +1 -1
  158. package/components/organisms/JFormModal.vue.cjs +1 -1
  159. package/components/organisms/JFormModal.vue.cjs.map +1 -1
  160. package/components/organisms/JFormModal.vue.js +54 -49
  161. package/components/organisms/JFormModal.vue.js.map +1 -1
  162. package/components/organisms/JHeader.vue.cjs +1 -1
  163. package/components/organisms/JHeader.vue.cjs.map +1 -1
  164. package/components/organisms/JHeader.vue.js +211 -208
  165. package/components/organisms/JHeader.vue.js.map +1 -1
  166. package/components/organisms/JModal.vue.cjs +1 -1
  167. package/components/organisms/JModal.vue.cjs.map +1 -1
  168. package/components/organisms/JModal.vue.js +31 -26
  169. package/components/organisms/JModal.vue.js.map +1 -1
  170. package/components/organisms/JPageContainer.vue.cjs +1 -1
  171. package/components/organisms/JPageContainer.vue.cjs.map +1 -1
  172. package/components/organisms/JPageContainer.vue.js +22 -22
  173. package/components/organisms/JPageContainer.vue.js.map +1 -1
  174. package/components/organisms/JSearchPanel.vue2.cjs +1 -1
  175. package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
  176. package/components/organisms/JSearchPanel.vue2.js +34 -32
  177. package/components/organisms/JSearchPanel.vue2.js.map +1 -1
  178. package/components/organisms/JShuttle.vue.cjs +7 -0
  179. package/components/organisms/JShuttle.vue.cjs.map +1 -0
  180. package/components/organisms/JShuttle.vue.js +13 -0
  181. package/components/organisms/JShuttle.vue.js.map +1 -0
  182. package/components/organisms/JShuttle.vue2.cjs +2 -0
  183. package/components/organisms/JShuttle.vue2.cjs.map +1 -0
  184. package/components/organisms/JShuttle.vue2.js +216 -0
  185. package/components/organisms/JShuttle.vue2.js.map +1 -0
  186. package/components/organisms/JSidebarAdvanced.vue.cjs +1 -1
  187. package/components/organisms/JSidebarAdvanced.vue.js +7 -7
  188. package/components/organisms/JSidebarAdvanced.vue2.cjs +1 -1
  189. package/components/organisms/JSidebarAdvanced.vue2.cjs.map +1 -1
  190. package/components/organisms/JSidebarAdvanced.vue2.js +40 -40
  191. package/components/organisms/JSidebarAdvanced.vue2.js.map +1 -1
  192. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs +1 -1
  193. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs.map +1 -1
  194. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js +83 -63
  195. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js.map +1 -1
  196. package/components/organisms/JSidebarSimple.vue.cjs +1 -1
  197. package/components/organisms/JSidebarSimple.vue.js +2 -2
  198. package/components/organisms/JSidebarSimple.vue2.cjs +1 -1
  199. package/components/organisms/JSidebarSimple.vue2.cjs.map +1 -1
  200. package/components/organisms/JSidebarSimple.vue2.js +2 -2
  201. package/components/organisms/JSidebarSimple.vue2.js.map +1 -1
  202. package/components/shadcn/AccordionTrigger.vue.cjs +1 -1
  203. package/components/shadcn/AccordionTrigger.vue.cjs.map +1 -1
  204. package/components/shadcn/AccordionTrigger.vue.js +3 -3
  205. package/components/shadcn/AccordionTrigger.vue.js.map +1 -1
  206. package/components/shadcn/Card.vue.cjs +1 -1
  207. package/components/shadcn/Card.vue.cjs.map +1 -1
  208. package/components/shadcn/Card.vue.js +1 -1
  209. package/components/shadcn/Card.vue.js.map +1 -1
  210. package/components/shadcn/CardContent.vue.cjs +1 -1
  211. package/components/shadcn/CardContent.vue.cjs.map +1 -1
  212. package/components/shadcn/CardContent.vue.js +4 -4
  213. package/components/shadcn/CardContent.vue.js.map +1 -1
  214. package/components/shadcn/CardDescription.vue.cjs +1 -1
  215. package/components/shadcn/CardDescription.vue.cjs.map +1 -1
  216. package/components/shadcn/CardDescription.vue.js +1 -1
  217. package/components/shadcn/CardDescription.vue.js.map +1 -1
  218. package/components/shadcn/CardFooter.vue.cjs +1 -1
  219. package/components/shadcn/CardFooter.vue.cjs.map +1 -1
  220. package/components/shadcn/CardFooter.vue.js +7 -7
  221. package/components/shadcn/CardFooter.vue.js.map +1 -1
  222. package/components/shadcn/CardHeader.vue.cjs +1 -1
  223. package/components/shadcn/CardHeader.vue.cjs.map +1 -1
  224. package/components/shadcn/CardHeader.vue.js +8 -8
  225. package/components/shadcn/CardHeader.vue.js.map +1 -1
  226. package/components/shadcn/CardTitle.vue.cjs +1 -1
  227. package/components/shadcn/CardTitle.vue.cjs.map +1 -1
  228. package/components/shadcn/CardTitle.vue.js +5 -5
  229. package/components/shadcn/CardTitle.vue.js.map +1 -1
  230. package/components/shadcn/Input.vue.cjs +1 -1
  231. package/components/shadcn/Input.vue.cjs.map +1 -1
  232. package/components/shadcn/Input.vue.js +3 -3
  233. package/components/shadcn/Input.vue.js.map +1 -1
  234. package/components/shadcn/SelectTrigger.vue.cjs +1 -1
  235. package/components/shadcn/SelectTrigger.vue.cjs.map +1 -1
  236. package/components/shadcn/SelectTrigger.vue.js +2 -2
  237. package/components/shadcn/SelectTrigger.vue.js.map +1 -1
  238. package/components/shadcn/Switch.vue.cjs +1 -1
  239. package/components/shadcn/Switch.vue.cjs.map +1 -1
  240. package/components/shadcn/Switch.vue.js +2 -2
  241. package/components/shadcn/Switch.vue.js.map +1 -1
  242. package/components/shadcn/TabsContent.vue.cjs +1 -1
  243. package/components/shadcn/TabsContent.vue.cjs.map +1 -1
  244. package/components/shadcn/TabsContent.vue.js +1 -1
  245. package/components/shadcn/TabsContent.vue.js.map +1 -1
  246. package/components/shadcn/TabsList.vue.cjs +1 -1
  247. package/components/shadcn/TabsList.vue.cjs.map +1 -1
  248. package/components/shadcn/TabsList.vue.js +10 -10
  249. package/components/shadcn/TabsList.vue.js.map +1 -1
  250. package/components/shadcn/TabsTrigger.vue.cjs +1 -1
  251. package/components/shadcn/TabsTrigger.vue.cjs.map +1 -1
  252. package/components/shadcn/TabsTrigger.vue.js +4 -4
  253. package/components/shadcn/TabsTrigger.vue.js.map +1 -1
  254. package/components/shadcn/Textarea.vue.cjs +1 -1
  255. package/components/shadcn/Textarea.vue.cjs.map +1 -1
  256. package/components/shadcn/Textarea.vue.js +2 -2
  257. package/components/shadcn/Textarea.vue.js.map +1 -1
  258. package/components/shadcn/index.cjs +1 -1
  259. package/components/shadcn/index.cjs.map +1 -1
  260. package/components/shadcn/index.js +9 -8
  261. package/components/shadcn/index.js.map +1 -1
  262. package/components/templates/JLayout.vue.cjs.map +1 -1
  263. package/components/templates/JLayout.vue.js.map +1 -1
  264. package/index.cjs +1 -1
  265. package/index.js +73 -67
  266. package/package.json +1 -1
  267. package/types/index.d.ts +1025 -766
  268. package/assets/jwms-portal-frontend-DntSIcYt.css +0 -1
  269. package/components/molecules/JFormField.vue3.cjs +0 -2
  270. package/components/molecules/JFormField.vue3.cjs.map +0 -1
  271. package/components/molecules/JFormField.vue3.js +0 -6
  272. package/components/molecules/JFormField.vue3.js.map +0 -1
@@ -0,0 +1,13 @@
1
+ import t from "./JEmptyState.vue2.js";
2
+ /* empty css */
3
+ const o = (o_comp, o_opts) => {
4
+ const o_merged = o_comp.__vccOpts || o_comp;
5
+ for (const [o_key, o_val] of o_opts)
6
+ o_merged[o_key] = o_val;
7
+ return o_merged;
8
+ };
9
+ const a = /* @__PURE__ */ o(t, [["__scopeId", "data-v-b6b7e0cc"]]);
10
+ export {
11
+ a as default
12
+ };
13
+ //# sourceMappingURL=JEmptyState.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JEmptyState.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),u=require("../atoms/JButton.vue.cjs");require("../shadcn/index.cjs");require("lucide-vue-next");const i=require("../../lib/utils.cjs");require("@internationalized/date");require("md-editor-v3");;/* empty css */;/* empty css */require("../shadcn/badge-variants.cjs");require("@vueuse/core");require("reka-ui");;/* empty css */require("../shadcn/avatar-variants.cjs");const l=require("../atoms/JIcon.vue.cjs");require("dompurify");;/* empty css */require("ag-grid-vue3");require("ag-grid-community");require("ag-grid-enterprise");;/* empty css */;/* empty css */;/* empty css */;/* empty css */;/* empty css */;/* empty css */require("vue-sonner");const a={key:1,class:"text-sm text-muted-foreground"},d={key:0,class:"j-empty-icon-wrapper"},m={key:1,class:"text-xl font-semibold text-foreground mb-2 tracking-tight"},f={key:2,class:"text-sm text-muted-foreground mb-6 max-w-sm leading-relaxed"},k=e.defineComponent({__name:"JEmptyState",props:{icon:{default:"inbox"},title:{},description:{},actionText:{},variant:{default:"default"},class:{}},emits:["action"],setup(t,{emit:s}){const o=t,c=s;return(r,n)=>t.variant==="simple"?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(e.unref(i.cn)("j-empty-state-simple","flex flex-col items-center justify-center p-8 text-center","rounded-sm border-4 border-dashed",o.class))},[t.icon||r.$slots.icon?(e.openBlock(),e.createBlock(e.unref(l.default),{key:0,name:t.icon||"inbox",class:"w-12 h-12 text-muted-foreground mb-3"},{default:e.withCtx(()=>[e.renderSlot(r.$slots,"icon",{},void 0,!0)]),_:3},8,["name"])):e.createCommentVNode("",!0),t.title||r.$slots.title?(e.openBlock(),e.createElementBlock("p",a,[e.renderSlot(r.$slots,"title",{},()=>[e.createTextVNode(e.toDisplayString(t.title),1)],!0)])):e.createCommentVNode("",!0)],2)):(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(e.unref(i.cn)("j-empty-state","flex flex-col items-center justify-center","p-12 text-center","max-w-lg mx-auto","rounded-sm border border-border","bg-card shadow-sm",o.class))},[t.icon||r.$slots.icon?(e.openBlock(),e.createElementBlock("div",d,[e.renderSlot(r.$slots,"icon",{},()=>[t.icon?(e.openBlock(),e.createBlock(e.unref(l.default),{key:0,name:t.icon,class:"w-12 h-12 text-muted-foreground"},null,8,["name"])):e.createCommentVNode("",!0)],!0)])):e.createCommentVNode("",!0),t.title||r.$slots.title?(e.openBlock(),e.createElementBlock("h3",m,[e.renderSlot(r.$slots,"title",{},()=>[e.createTextVNode(e.toDisplayString(t.title),1)],!0)])):e.createCommentVNode("",!0),t.description||r.$slots.description?(e.openBlock(),e.createElementBlock("p",f,[e.renderSlot(r.$slots,"description",{},()=>[e.createTextVNode(e.toDisplayString(t.description),1)],!0)])):e.createCommentVNode("",!0),e.renderSlot(r.$slots,"action",{},()=>[t.actionText?(e.openBlock(),e.createBlock(e.unref(u.default),{key:0,styletype:"primary",size:"sm",onClick:n[0]||(n[0]=q=>c("action"))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.actionText),1)]),_:1})):e.createCommentVNode("",!0)],!0)],2))}});exports.default=k;
2
+ //# sourceMappingURL=JEmptyState.vue2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JEmptyState.vue2.cjs","sources":["../../../../src/components/molecules/JEmptyState.vue"],"sourcesContent":["<template>\n <!-- Simple variant: 아이콘 + 텍스트만 -->\n <div \n v-if=\"variant === 'simple'\"\n :class=\"cn(\n 'j-empty-state-simple',\n 'flex flex-col items-center justify-center p-8 text-center',\n 'rounded-sm border-4 border-dashed',\n props.class\n )\"\n >\n <JIcon \n v-if=\"icon || $slots.icon\" \n :name=\"icon || 'inbox'\" \n class=\"w-12 h-12 text-muted-foreground mb-3\"\n >\n <slot name=\"icon\" />\n </JIcon>\n \n <p v-if=\"title || $slots.title\" class=\"text-sm text-muted-foreground\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n </div>\n\n <!-- Default variant: 풀 스타일 -->\n <div \n v-else\n :class=\"cn(\n 'j-empty-state',\n 'flex flex-col items-center justify-center',\n 'p-12 text-center',\n 'max-w-lg mx-auto',\n 'rounded-sm border border-border',\n 'bg-card shadow-sm',\n props.class\n )\"\n >\n <!-- 아이콘 (원형 배경) -->\n <div v-if=\"icon || $slots.icon\" class=\"j-empty-icon-wrapper\">\n <slot name=\"icon\">\n <JIcon \n v-if=\"icon\" \n :name=\"icon\" \n class=\"w-12 h-12 text-muted-foreground\"\n />\n </slot>\n </div>\n\n <!-- 제목 -->\n <h3 v-if=\"title || $slots.title\" \n class=\"text-xl font-semibold text-foreground mb-2 tracking-tight\">\n <slot name=\"title\">{{ title }}</slot>\n </h3>\n\n <!-- 설명 -->\n <p v-if=\"description || $slots.description\" \n class=\"text-sm text-muted-foreground mb-6 max-w-sm leading-relaxed\">\n <slot name=\"description\">{{ description }}</slot>\n </p>\n\n <!-- 액션 버튼 -->\n <slot name=\"action\">\n <JButton \n v-if=\"actionText\" \n styletype=\"primary\"\n size=\"sm\"\n @click=\"emit('action')\"\n >\n {{ actionText }}\n </JButton>\n </slot>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { JIcon, JButton } from '@/components/atoms'\nimport { cn } from '@/lib/utils'\nimport type { JEmptyStateProps, JEmptyStateEmits } from '@/types/empty-state.types'\n\nconst props = withDefaults(defineProps<JEmptyStateProps>(), {\n icon: 'inbox',\n variant: 'default',\n})\n\nconst emit = defineEmits<JEmptyStateEmits>()\n</script>\n\n<style scoped>\n.j-empty-state {\n transition: all 0.2s ease;\n}\n\n.j-empty-state-simple {\n border-color: hsl(var(--border) / 0.5);\n background: hsl(var(--muted) / 0.1);\n transition: all 0.2s ease;\n}\n\n.j-empty-state-simple:hover {\n border-color: hsl(var(--border) / 0.8);\n background: hsl(var(--muted) / 0.15);\n}\n\n.j-empty-icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 5rem;\n height: 5rem;\n margin-bottom: 1.5rem;\n border-radius: 9999px;\n background: linear-gradient(135deg, \n hsl(var(--primary) / 0.08) 0%, \n hsl(var(--primary) / 0.02) 100%);\n border: 1px solid hsl(var(--border));\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .j-empty-icon-wrapper {\n animation: pulse 3s ease-in-out infinite;\n }\n}\n\n@keyframes pulse {\n 0%, 100% { \n opacity: 1; \n transform: scale(1);\n }\n 50% { \n opacity: 0.85; \n transform: scale(1.02);\n }\n}\n</style>\n"],"names":["props","__props","emit","__emit","_createElementBlock","_unref","cn","$slots","_createBlock","JIcon","_renderSlot","_ctx","_openBlock","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","JButton"],"mappings":"+uDA+EA,MAAMA,EAAQC,EAKRC,EAAOC,eAjFHF,EAAA,UAAO,wBADfG,EAAAA,mBAoBM,MAAA,OAlBH,uBAAOC,EAAAA,MAAAC,IAAA,yHAAsJN,EAAM,KAAA,KAQ5JC,EAAA,MAAQM,EAAAA,OAAO,oBADvBC,EAAAA,YAMQH,QAAAI,EAAAA,OAAA,EAAA,OAJL,KAAMR,EAAA,MAAI,QACX,MAAM,sCAAA,qBAEN,IAAoB,CAApBS,EAAAA,WAAoBC,EAAA,OAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,iDAGbV,EAAA,OAASM,EAAAA,OAAO,OAAzBK,EAAAA,YAAAR,EAAAA,mBAEI,IAFJS,EAEI,CADFH,EAAAA,WAAqCC,oBAArC,IAAqC,qCAAfV,EAAA,KAAK,EAAA,CAAA,CAAA,yDAK/BG,EAAAA,mBA8CM,MAAA,OA5CH,uBAAOC,EAAAA,MAAAC,IAAA,0JAA4MN,EAAM,KAAA,KAW/MC,EAAA,MAAQM,EAAAA,OAAO,MAA1BK,EAAAA,YAAAR,EAAAA,mBAQM,MARNU,EAQM,CAPJJ,EAAAA,WAMOC,mBANP,IAMO,CAJGV,EAAA,oBADRO,EAAAA,YAIEH,EAAAA,MAAAI,EAAAA,OAAA,EAAA,OAFC,KAAMR,EAAA,KACP,MAAM,iCAAA,oFAMFA,EAAA,OAASM,EAAAA,OAAO,OAA1BK,EAAAA,YAAAR,EAAAA,mBAGK,KAHLW,EAGK,CADHL,EAAAA,WAAqCC,oBAArC,IAAqC,qCAAfV,EAAA,KAAK,EAAA,CAAA,CAAA,qCAIpBA,EAAA,aAAeM,EAAAA,OAAO,aAA/BK,EAAAA,YAAAR,EAAAA,mBAGI,IAHJY,EAGI,CADFN,EAAAA,WAAiDC,0BAAjD,IAAiD,qCAArBV,EAAA,WAAW,EAAA,CAAA,CAAA,qCAIzCS,EAAAA,WASOC,qBATP,IASO,CAPGV,EAAA,0BADRO,EAAAA,YAOUH,EAAAA,MAAAY,EAAAA,OAAA,EAAA,OALR,UAAU,UACV,KAAK,KACJ,uBAAOf,EAAI,QAAA,EAAA,qBAEZ,IAAgB,qCAAbD,EAAA,UAAU,EAAA,CAAA,CAAA"}
@@ -0,0 +1,127 @@
1
+ import { defineComponent as $, createElementBlock as r, openBlock as o, normalizeClass as u, unref as m, createBlock as a, createCommentVNode as i, withCtx as p, renderSlot as s, createTextVNode as n, toDisplayString as l } from "vue";
2
+ import b from "../atoms/JButton.vue.js";
3
+ import "../shadcn/index.js";
4
+ import "lucide-vue-next";
5
+ import { cn as f } from "../../lib/utils.js";
6
+ import "@internationalized/date";
7
+ import "md-editor-v3";
8
+ /* empty css */
9
+ /* empty css */
10
+ import "../shadcn/badge-variants.js";
11
+ import "@vueuse/core";
12
+ import "reka-ui";
13
+ /* empty css */
14
+ import "../shadcn/avatar-variants.js";
15
+ import y from "../atoms/JIcon.vue.js";
16
+ import "dompurify";
17
+ /* empty css */
18
+ import "ag-grid-vue3";
19
+ import "ag-grid-community";
20
+ import "ag-grid-enterprise";
21
+ /* empty css */
22
+ /* empty css */
23
+ /* empty css */
24
+ /* empty css */
25
+ /* empty css */
26
+ /* empty css */
27
+ import "vue-sonner";
28
+ const g = {
29
+ key: 1,
30
+ class: "text-sm text-muted-foreground"
31
+ }, h = {
32
+ key: 0,
33
+ class: "j-empty-icon-wrapper"
34
+ }, v = {
35
+ key: 1,
36
+ class: "text-xl font-semibold text-foreground mb-2 tracking-tight"
37
+ }, w = {
38
+ key: 2,
39
+ class: "text-sm text-muted-foreground mb-6 max-w-sm leading-relaxed"
40
+ }, Z = /* @__PURE__ */ $({
41
+ __name: "JEmptyState",
42
+ props: {
43
+ icon: { default: "inbox" },
44
+ title: {},
45
+ description: {},
46
+ actionText: {},
47
+ variant: { default: "default" },
48
+ class: {}
49
+ },
50
+ emits: ["action"],
51
+ setup(t, { emit: x }) {
52
+ const c = t, k = x;
53
+ return (e, d) => t.variant === "simple" ? (o(), r("div", {
54
+ key: 0,
55
+ class: u(m(f)(
56
+ "j-empty-state-simple",
57
+ "flex flex-col items-center justify-center p-8 text-center",
58
+ "rounded-sm border-4 border-dashed",
59
+ c.class
60
+ ))
61
+ }, [
62
+ t.icon || e.$slots.icon ? (o(), a(m(y), {
63
+ key: 0,
64
+ name: t.icon || "inbox",
65
+ class: "w-12 h-12 text-muted-foreground mb-3"
66
+ }, {
67
+ default: p(() => [
68
+ s(e.$slots, "icon", {}, void 0, !0)
69
+ ]),
70
+ _: 3
71
+ }, 8, ["name"])) : i("", !0),
72
+ t.title || e.$slots.title ? (o(), r("p", g, [
73
+ s(e.$slots, "title", {}, () => [
74
+ n(l(t.title), 1)
75
+ ], !0)
76
+ ])) : i("", !0)
77
+ ], 2)) : (o(), r("div", {
78
+ key: 1,
79
+ class: u(m(f)(
80
+ "j-empty-state",
81
+ "flex flex-col items-center justify-center",
82
+ "p-12 text-center",
83
+ "max-w-lg mx-auto",
84
+ "rounded-sm border border-border",
85
+ "bg-card shadow-sm",
86
+ c.class
87
+ ))
88
+ }, [
89
+ t.icon || e.$slots.icon ? (o(), r("div", h, [
90
+ s(e.$slots, "icon", {}, () => [
91
+ t.icon ? (o(), a(m(y), {
92
+ key: 0,
93
+ name: t.icon,
94
+ class: "w-12 h-12 text-muted-foreground"
95
+ }, null, 8, ["name"])) : i("", !0)
96
+ ], !0)
97
+ ])) : i("", !0),
98
+ t.title || e.$slots.title ? (o(), r("h3", v, [
99
+ s(e.$slots, "title", {}, () => [
100
+ n(l(t.title), 1)
101
+ ], !0)
102
+ ])) : i("", !0),
103
+ t.description || e.$slots.description ? (o(), r("p", w, [
104
+ s(e.$slots, "description", {}, () => [
105
+ n(l(t.description), 1)
106
+ ], !0)
107
+ ])) : i("", !0),
108
+ s(e.$slots, "action", {}, () => [
109
+ t.actionText ? (o(), a(m(b), {
110
+ key: 0,
111
+ styletype: "primary",
112
+ size: "sm",
113
+ onClick: d[0] || (d[0] = (j) => k("action"))
114
+ }, {
115
+ default: p(() => [
116
+ n(l(t.actionText), 1)
117
+ ]),
118
+ _: 1
119
+ })) : i("", !0)
120
+ ], !0)
121
+ ], 2));
122
+ }
123
+ });
124
+ export {
125
+ Z as default
126
+ };
127
+ //# sourceMappingURL=JEmptyState.vue2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JEmptyState.vue2.js","sources":["../../../../src/components/molecules/JEmptyState.vue"],"sourcesContent":["<template>\n <!-- Simple variant: 아이콘 + 텍스트만 -->\n <div \n v-if=\"variant === 'simple'\"\n :class=\"cn(\n 'j-empty-state-simple',\n 'flex flex-col items-center justify-center p-8 text-center',\n 'rounded-sm border-4 border-dashed',\n props.class\n )\"\n >\n <JIcon \n v-if=\"icon || $slots.icon\" \n :name=\"icon || 'inbox'\" \n class=\"w-12 h-12 text-muted-foreground mb-3\"\n >\n <slot name=\"icon\" />\n </JIcon>\n \n <p v-if=\"title || $slots.title\" class=\"text-sm text-muted-foreground\">\n <slot name=\"title\">{{ title }}</slot>\n </p>\n </div>\n\n <!-- Default variant: 풀 스타일 -->\n <div \n v-else\n :class=\"cn(\n 'j-empty-state',\n 'flex flex-col items-center justify-center',\n 'p-12 text-center',\n 'max-w-lg mx-auto',\n 'rounded-sm border border-border',\n 'bg-card shadow-sm',\n props.class\n )\"\n >\n <!-- 아이콘 (원형 배경) -->\n <div v-if=\"icon || $slots.icon\" class=\"j-empty-icon-wrapper\">\n <slot name=\"icon\">\n <JIcon \n v-if=\"icon\" \n :name=\"icon\" \n class=\"w-12 h-12 text-muted-foreground\"\n />\n </slot>\n </div>\n\n <!-- 제목 -->\n <h3 v-if=\"title || $slots.title\" \n class=\"text-xl font-semibold text-foreground mb-2 tracking-tight\">\n <slot name=\"title\">{{ title }}</slot>\n </h3>\n\n <!-- 설명 -->\n <p v-if=\"description || $slots.description\" \n class=\"text-sm text-muted-foreground mb-6 max-w-sm leading-relaxed\">\n <slot name=\"description\">{{ description }}</slot>\n </p>\n\n <!-- 액션 버튼 -->\n <slot name=\"action\">\n <JButton \n v-if=\"actionText\" \n styletype=\"primary\"\n size=\"sm\"\n @click=\"emit('action')\"\n >\n {{ actionText }}\n </JButton>\n </slot>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { JIcon, JButton } from '@/components/atoms'\nimport { cn } from '@/lib/utils'\nimport type { JEmptyStateProps, JEmptyStateEmits } from '@/types/empty-state.types'\n\nconst props = withDefaults(defineProps<JEmptyStateProps>(), {\n icon: 'inbox',\n variant: 'default',\n})\n\nconst emit = defineEmits<JEmptyStateEmits>()\n</script>\n\n<style scoped>\n.j-empty-state {\n transition: all 0.2s ease;\n}\n\n.j-empty-state-simple {\n border-color: hsl(var(--border) / 0.5);\n background: hsl(var(--muted) / 0.1);\n transition: all 0.2s ease;\n}\n\n.j-empty-state-simple:hover {\n border-color: hsl(var(--border) / 0.8);\n background: hsl(var(--muted) / 0.15);\n}\n\n.j-empty-icon-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 5rem;\n height: 5rem;\n margin-bottom: 1.5rem;\n border-radius: 9999px;\n background: linear-gradient(135deg, \n hsl(var(--primary) / 0.08) 0%, \n hsl(var(--primary) / 0.02) 100%);\n border: 1px solid hsl(var(--border));\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .j-empty-icon-wrapper {\n animation: pulse 3s ease-in-out infinite;\n }\n}\n\n@keyframes pulse {\n 0%, 100% { \n opacity: 1; \n transform: scale(1);\n }\n 50% { \n opacity: 0.85; \n transform: scale(1.02);\n }\n}\n</style>\n"],"names":["props","__props","emit","__emit","_createElementBlock","_unref","cn","$slots","_createBlock","JIcon","_renderSlot","_ctx","_openBlock","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","JButton"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EA,UAAMA,IAAQC,GAKRC,IAAOC;qBAjFHF,EAAA,YAAO,iBADfG,EAoBM,OAAA;AAAA;MAlBH,SAAOC,EAAAC,CAAA;AAAA;;;QAAsJN,EAAM;AAAA,MAAA;;MAQ5JC,EAAA,QAAQM,EAAAA,OAAO,aADvBC,EAMQH,EAAAI,CAAA,GAAA;AAAA;QAJL,MAAMR,EAAA,QAAI;AAAA,QACX,OAAM;AAAA,MAAA;mBAEN,MAAoB;AAAA,UAApBS,EAAoBC,EAAA,QAAA,QAAA,CAAA,GAAA,QAAA,EAAA;AAAA,QAAA;;;MAGbV,EAAA,SAASM,EAAAA,OAAO,SAAzBK,KAAAR,EAEI,KAFJS,GAEI;AAAA,QADFH,EAAqCC,uBAArC,MAAqC;AAAA,cAAfV,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;;mBAK/BG,EA8CM,OAAA;AAAA;MA5CH,SAAOC,EAAAC,CAAA;AAAA;;;;;;QAA4MN,EAAM;AAAA,MAAA;;MAW/MC,EAAA,QAAQM,EAAAA,OAAO,QAA1BK,KAAAR,EAQM,OARNU,GAQM;AAAA,QAPJJ,EAMOC,sBANP,MAMO;AAAA,UAJGV,EAAA,aADRO,EAIEH,EAAAI,CAAA,GAAA;AAAA;YAFC,MAAMR,EAAA;AAAA,YACP,OAAM;AAAA,UAAA;;;MAMFA,EAAA,SAASM,EAAAA,OAAO,SAA1BK,KAAAR,EAGK,MAHLW,GAGK;AAAA,QADHL,EAAqCC,uBAArC,MAAqC;AAAA,cAAfV,EAAA,KAAK,GAAA,CAAA;AAAA,QAAA;;MAIpBA,EAAA,eAAeM,EAAAA,OAAO,eAA/BK,KAAAR,EAGI,KAHJY,GAGI;AAAA,QADFN,EAAiDC,6BAAjD,MAAiD;AAAA,cAArBV,EAAA,WAAW,GAAA,CAAA;AAAA,QAAA;;MAIzCS,EASOC,wBATP,MASO;AAAA,QAPGV,EAAA,mBADRO,EAOUH,EAAAY,CAAA,GAAA;AAAA;UALR,WAAU;AAAA,UACV,MAAK;AAAA,UACJ,gCAAOf,EAAI,QAAA;AAAA,QAAA;qBAEZ,MAAgB;AAAA,gBAAbD,EAAA,UAAU,GAAA,CAAA;AAAA,UAAA;;;;;;;"}
@@ -1,2 +1,7 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue");require("../shadcn/index.cjs");require("lucide-vue-next");const h=require("../atoms/JInput.vue.cjs"),F=require("../atoms/JTextarea.vue.cjs"),N=require("../atoms/JCheckbox.vue.cjs"),z=require("../atoms/JCombo.vue.cjs"),T=require("../atoms/JSearchCombo.vue.cjs"),S=require("../atoms/JRadio.vue.cjs"),J=require("../atoms/JSwitch.vue.cjs"),M=require("../atoms/JDatepicker.vue.cjs");require("md-editor-v3");;/* empty css */;/* empty css */require("clsx");require("tailwind-merge");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 */require("vue-sonner");const i=require("../shadcn/FieldGroup.vue.cjs"),g=require("../shadcn/Field.vue.cjs"),k=require("../shadcn/FieldLabel.vue.cjs"),q=require("../shadcn/FieldContent.vue.cjs"),P=require("../shadcn/FieldDescription.vue.cjs"),E=require("../shadcn/FieldError.vue.cjs"),L={key:0,class:"text-destructive ml-1"},j=e.defineComponent({__name:"JFormField",props:{label:{},description:{},errorMsg:{},type:{default:"input"},inlineLabel:{},orientation:{default:"vertical"},labelAlign:{default:"left"},labelWidth:{default:"8rem"},id:{},modelValue:{},placeholder:{},disabled:{type:Boolean},readonly:{type:Boolean},required:{type:Boolean},name:{},styleType:{},inputType:{},options:{},multiple:{type:Boolean},radioDirection:{default:"horizontal"}},emits:["update:modelValue","change","focus","blur"],setup(l,{expose:C,emit:x}){const b=["label","description","errorMsg","type","inlineLabel","orientation","labelAlign","labelWidth","radioDirection"],r=l,n=x,o=e.ref(""),c=e.computed(()=>r.errorMsg||o.value),s=e.computed(()=>{const t={},a=r;for(const u in a)b.includes(u)||(t[u]=a[u]);if(r.inputType&&r.type==="input"&&(t.type=r.inputType,delete t.inputType,!r.placeholder)){const u={text:"텍스트를 입력하세요",email:"이메일을 입력하세요",password:"비밀번호를 입력하세요",tel:"전화번호를 입력하세요",url:"URL을 입력하세요",number:"숫자를 입력하세요",search:"검색어를 입력하세요",date:"날짜를 선택하세요",time:"시간을 선택하세요","datetime-local":"날짜와 시간을 선택하세요",month:"월을 선택하세요",week:"주를 선택하세요"};t.placeholder=u[r.inputType]||"입력하세요"}return r.radioDirection&&r.type==="radio"&&(t.styletype=r.radioDirection,delete t.radioDirection),t}),d=t=>{if(!r.required)return;o.value="";const a=t!==void 0?t:r.modelValue;r.type==="checkbox"||r.type==="switch"?a!=="Y"&&(o.value="필수 항목입니다."):(a==null||a==="")&&(o.value="필수 입력 항목입니다.")},B=e.computed(()=>!(r.modelValue!==null&&r.modelValue!==void 0&&r.modelValue!=="")),p=t=>{n("update:modelValue",t),d(t)},f=t=>{n("change",t),d(t)},_=t=>{n("focus",t)},m=t=>{B.value&&d(),n("blur",t)},V=e.computed(()=>{const t={left:"justify-start",middle:"justify-center",right:"justify-end"},a={left:"text-left",middle:"text-center",right:"text-right"};return r.orientation==="horizontal"?t[r.labelAlign]:a[r.labelAlign]}),w=e.computed(()=>{switch(r.styleType){case"sm":return"form-density-sm";case"lg":return"form-density-lg";default:return"form-density-md"}}),v=e.computed(()=>{const t="h-[var(--ctl-h)] leading-[var(--ctl-h)]";return r.type==="datepicker"?`${t} max-w-xs`:r.type==="radio"&&r.radioDirection==="vertical"?"":t}),D={input:h.default,textarea:F.default,checkbox:N.default,switch:J.default,combo:z.default,radio:S.default,searchCombo:T.default,datepicker:M.default},y=e.computed(()=>D[r.type]||h.default);return C({clearError:()=>{o.value=""}}),(t,a)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["space-y-2 flex-1 min-w-0",w.value])},[e.createVNode(e.unref(i.default),null,{default:e.withCtx(()=>[e.createVNode(e.unref(g.default),{class:e.normalizeClass([l.orientation==="horizontal"?"grid grid-cols-[var(--label-w,8rem)_1fr] items-start space-y-0 gap-2":"space-y-1 gap-1"]),style:e.normalizeStyle(l.orientation==="horizontal"?`--label-w:${l.labelWidth};`:"")},{default:e.withCtx(()=>[e.createVNode(e.unref(k.default),{for:l.id,class:e.normalizeClass([l.orientation==="horizontal"?"flex items-center h-[var(--ctl-h)] w-full":"flex items-center",V.value])},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.label)+" ",1),l.required?(e.openBlock(),e.createElementBlock("span",L,"*")):e.createCommentVNode("",!0)]),_:1},8,["for","class"]),e.createVNode(e.unref(q.default),{class:e.normalizeClass([l.orientation==="horizontal"?"min-h-[var(--ctl-h)] flex flex-col justify-start gap-0.5 mt-0":"space-y-2 gap-0"])},{default:e.withCtx(()=>[l.type==="checkbox"||l.type==="switch"?(e.openBlock(),e.createBlock(e.unref(i.default),{key:0,"data-slot":"checkbox-group"},{default:e.withCtx(()=>[e.createVNode(e.unref(g.default),{orientation:"horizontal",class:"flex gap-2 space-y-0 h-[var(--ctl-h)] leading-[var(--ctl-h)] items-center"},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m}),null,16)),l.inlineLabel?(e.openBlock(),e.createBlock(e.unref(k.default),{key:0,for:l.id,class:"font-normal m-0 h-[var(--ctl-h)] leading-[var(--ctl-h)]"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.inlineLabel),1)]),_:1},8,["for"])):e.createCommentVNode("",!0)]),_:1})]),_:1})):l.type==="radio"?(e.openBlock(),e.createBlock(e.unref(i.default),{key:1},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m,class:v.value}),null,16,["class"]))]),_:1})):(e.openBlock(),e.createBlock(e.unref(i.default),{key:2},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m,class:v.value}),null,16,["class"]))]),_:1})),l.description||c.value?(e.openBlock(),e.createBlock(e.unref(q.default),{key:3},{default:e.withCtx(()=>[l.description?(e.openBlock(),e.createBlock(e.unref(P.default),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.description),1)]),_:1})):e.createCommentVNode("",!0),c.value?(e.openBlock(),e.createBlock(e.unref(E.default),{key:1},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(c.value),1)]),_:1})):e.createCommentVNode("",!0)]),_:1})):e.createCommentVNode("",!0)]),_:1},8,["class"])]),_:1},8,["class","style"])]),_:1})],2))}});exports.default=j;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./JFormField.vue2.cjs");;/* empty css */const t = (t_comp, t_opts) => {
2
+ const t_merged = t_comp.__vccOpts || t_comp;
3
+ for (const [t_key, t_val] of t_opts)
4
+ t_merged[t_key] = t_val;
5
+ return t_merged;
6
+ };,u=t(e.default,[["__scopeId","data-v-9053fa66"]]);exports.default=u;
2
7
  //# sourceMappingURL=JFormField.vue.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"JFormField.vue.cjs","sources":["../../../../src/components/molecules/JFormField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { Field, FieldContent, FieldLabel, FieldDescription, FieldError, FieldGroup } from '@/components/shadcn'\nimport { JInput, JTextarea, JCheckbox, JSwitch, JCombo, JRadio, JSearchCombo, JDatepicker } from '@/components/atoms'\n\n// 컴포넌트 타입 정의\ntype ComponentType = 'input' | 'textarea' | 'checkbox' | 'switch' | 'combo' | 'radio' | 'searchCombo' | 'datepicker'\n\n// FormField 자체의 props (레이아웃 관련)\nconst FORM_FIELD_PROPS = [\n 'label',\n 'description',\n 'errorMsg',\n 'type',\n 'inlineLabel',\n 'orientation',\n 'labelAlign',\n 'labelWidth',\n 'radioDirection',\n] as const\n\nconst props = withDefaults(\n defineProps<{\n // ============ FormField 자체 props (레이아웃만) ============\n /** 필드 레이블 */\n label?: string\n /** 필드 설명 (레이블 아래 표시) */\n description?: string\n /** 에러 메시지 */\n errorMsg?: string\n /** 컴포넌트 타입 (렌더링할 컴포넌트 지정) */\n type?: ComponentType\n /** 체크박스/스위치 타입일 때만 사용하는 옆 라벨 */\n inlineLabel?: string\n /** 레이블과 컨트롤의 배치 방향 */\n orientation?: 'vertical' | 'horizontal' | 'responsive'\n /** 레이블 텍스트 정렬 */\n labelAlign?: 'left' | 'middle' | 'right'\n /** 레이블 영역 너비 (horizontal orientation일 때만 적용) */\n labelWidth?: string\n\n // ============ 내부 컴포넌트로 전달할 공통 props ============\n /** Input 요소의 id (label for와 연결) */\n id?: string\n /** v-model로 양방향 데이터 바인딩 */\n modelValue?: any\n /** 입력 전 표시되는 안내문 (Input/Textarea/Select/Combobox) */\n placeholder?: string\n /** 비활성화 상태 (전체) */\n disabled?: boolean\n /** 읽기 전용 상태 (Input/Textarea) */\n readonly?: boolean\n /** 필수 입력/선택 여부 (전체) */\n required?: boolean\n /** form 데이터 전송 시 키 이름 (전체) */\n name?: string\n /** 스타일 테마 지정 (J-prefixed 컴포넌트의 styleType) */\n styleType?: string\n\n // ============ Input 전용 props ============\n /** Input 타입 (text, email, password 등) */\n inputType?: string\n\n\n // ============ Select/Combobox/Radio 전용 props ============\n /** 선택 가능한 항목 배열 */\n options?: Array<{ label: string; value: string | number; disabled?: boolean }>\n \n // ============ Select/Combobox 전용 props ============\n /** 다중 선택 허용 여부 */\n multiple?: boolean\n\n\n // ============ Radio 전용 props ============\n /** Radio 옵션 나열 방향 */\n radioDirection?: 'horizontal' | 'vertical'\n }>(),\n {\n type: 'input',\n orientation: 'vertical',\n labelAlign: 'left',\n labelWidth: '8rem',\n radioDirection: 'horizontal',\n }\n)\n\n// 이벤트 정의\nconst emit = defineEmits<{\n 'update:modelValue': [value: any]\n 'change': [value: any]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n// 내부 에러 상태 (props.error가 없을 때만 사용)\nconst internalError = ref<string>('')\n\n// 최종 에러 메시지 (외부 errorMsg가 우선)\nconst finalError = computed(() => props.errorMsg || internalError.value)\n\n// FormField 자체 props와 내부 컴포넌트 props 분리\nconst controlProps = computed(() => {\n const result: Record<string, any> = {}\n const propsObj = props as Record<string, any>\n \n for (const key in propsObj) {\n // FormField 자체 props는 제외\n if (!FORM_FIELD_PROPS.includes(key as any)) {\n result[key] = propsObj[key]\n }\n }\n \n // inputType을 type으로 변환 (JInput 컴포넌트에서 사용)\n if (props.inputType && props.type === 'input') {\n result.type = props.inputType\n delete result.inputType // inputType은 제거\n \n // placeholder가 없으면 inputType에 따라 기본값 설정\n if (!props.placeholder) {\n const defaultPlaceholders: Record<string, string> = {\n 'text': '텍스트를 입력하세요',\n 'email': '이메일을 입력하세요',\n 'password': '비밀번호를 입력하세요',\n 'tel': '전화번호를 입력하세요',\n 'url': 'URL을 입력하세요',\n 'number': '숫자를 입력하세요',\n 'search': '검색어를 입력하세요',\n 'date': '날짜를 선택하세요',\n 'time': '시간을 선택하세요',\n 'datetime-local': '날짜와 시간을 선택하세요',\n 'month': '월을 선택하세요',\n 'week': '주를 선택하세요',\n }\n \n result.placeholder = defaultPlaceholders[props.inputType] || '입력하세요'\n }\n }\n \n // radioDirection을 styletype으로 변환 (JRadio 컴포넌트에서 사용)\n if (props.radioDirection && props.type === 'radio') {\n result.styletype = props.radioDirection\n delete result.radioDirection // radioDirection은 제거\n }\n \n return result\n})\n\n // Built-in validation\n const validateField = (currentValue?: any) => {\n if (!props.required) return\n\n internalError.value = ''\n\n // 현재 값 또는 props.modelValue 사용\n const value = currentValue !== undefined ? currentValue : props.modelValue\n\n // Required 체크\n if (props.type === 'checkbox' || props.type === 'switch') {\n if (value !== 'Y') {\n internalError.value = '필수 항목입니다.'\n }\n } else {\n if (value === null || value === undefined || value === '') {\n internalError.value = '필수 입력 항목입니다.'\n }\n }\n }\n\n // 초기 로드 시 validation 실행 (blur 이벤트에서만)\n const shouldValidateOnMount = computed(() => {\n // Storybook에서 초기값이 있는 경우 validation 스킵\n if (props.modelValue !== null && props.modelValue !== undefined && props.modelValue !== '') {\n return false\n }\n return true\n })\n\n// 이벤트 핸들러\nconst handleUpdateModelValue = (value: any) => {\n emit('update:modelValue', value)\n \n // 값이 변경되면 즉시 validation 실행 (현재 값 전달)\n validateField(value)\n}\n\nconst handleChange = (value: any) => {\n emit('change', value)\n \n // change 이벤트에서도 validation 실행 (현재 값 전달)\n validateField(value)\n}\n\nconst handleFocus = (event: FocusEvent) => {\n emit('focus', event)\n}\n\n const handleBlur = (event: FocusEvent) => {\n // blur 시에만 validation 실행 (초기 로드 시에는 실행하지 않음)\n if (shouldValidateOnMount.value) {\n validateField()\n }\n emit('blur', event)\n }\n\n// 레이블 정렬 클래스 (레이블 영역 내에서 레이블의 위치 제어)\nconst labelAlignClass = computed(() => {\n // horizontal일 때는 레이블 영역 내에서 레이블의 위치를 제어\n const mapHorizontal = { \n left: 'justify-start', // 레이블 영역의 왼쪽에 레이블 위치\n middle: 'justify-center', // 레이블 영역의 가운데에 레이블 위치\n right: 'justify-end' // 레이블 영역의 오른쪽에 레이블 위치 (input과 가까이)\n }\n // vertical일 때는 텍스트 정렬만 제어\n const mapVertical = { left: 'text-left', middle: 'text-center', right: 'text-right' }\n return props.orientation === 'horizontal' ? mapHorizontal[props.labelAlign] : mapVertical[props.labelAlign]\n})\n\n/** 행높이 토큰 클래스 매핑 */\nconst densityClass = computed(() => {\n switch (props.styleType) {\n case 'sm': return 'form-density-sm'\n case 'lg': return 'form-density-lg'\n default: return 'form-density-md'\n }\n})\n\n/** 컨트롤 클래스 (datepicker는 최대 너비 제한, radio vertical은 높이 제한 없음) */\nconst controlClass = computed(() => {\n const baseClass = 'h-[var(--ctl-h)] leading-[var(--ctl-h)]'\n \n if (props.type === 'datepicker') {\n return `${baseClass} max-w-xs`\n }\n \n // Radio vertical일 때는 높이 제한 없음\n if (props.type === 'radio' && props.radioDirection === 'vertical') {\n return ''\n }\n \n return baseClass\n})\n\n// 컴포넌트 매핑\nconst componentMap: Record<ComponentType, any> = {\n input: JInput,\n textarea: JTextarea,\n checkbox: JCheckbox,\n switch: JSwitch,\n combo: JCombo,\n radio: JRadio,\n searchCombo: JSearchCombo,\n datepicker: JDatepicker,\n}\n\n// type에 따라 렌더링할 컴포넌트 결정\nconst resolvedComponent = computed(() => {\n return componentMap[props.type!] || JInput\n})\n\n// 외부에서 수동으로 에러 클리어 가능하도록 expose\ndefineExpose({\n clearError: () => { internalError.value = '' }\n})\n</script>\n\n<template>\n <div :class=\"['space-y-2 flex-1 min-w-0', densityClass]\">\n <FieldGroup >\n <Field :class=\"[\n orientation === 'horizontal'\n ? 'grid grid-cols-[var(--label-w,8rem)_1fr] items-start space-y-0 gap-2'\n : 'space-y-1 gap-1'\n ]\"\n :style=\"orientation === 'horizontal' ? `--label-w:${labelWidth};` : ''\"\n >\n <!-- 메인 라벨 (필수표기 포함) -->\n <FieldLabel \n :for=\"id\" \n :class=\"[\n orientation === 'horizontal'\n ? 'flex items-center h-[var(--ctl-h)] w-full'\n : 'flex items-center',\n labelAlignClass\n ]\"\n >\n {{ label }}\n <span v-if=\"required\" class=\"text-destructive ml-1\">*</span>\n </FieldLabel>\n\n <FieldContent \n :class=\"[\n orientation === 'horizontal'\n ? 'min-h-[var(--ctl-h)] flex flex-col justify-start gap-0.5 mt-0'\n : 'space-y-2 gap-0'\n ]\"\n >\n <!-- 체크박스/스위치: 항상 가로 정렬로 컨트롤 + 인라인 라벨 묶기 -->\n <FieldGroup v-if=\"type === 'checkbox' || type === 'switch'\" data-slot=\"checkbox-group\">\n <!-- 부모 orientation과 무관하게 수평 정렬 고정 -->\n <Field orientation=\"horizontal\" class=\"flex gap-2 space-y-0 h-[var(--ctl-h)] leading-[var(--ctl-h)] items-center\">\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n />\n <FieldLabel\n v-if=\"inlineLabel\"\n :for=\"id\"\n class=\"font-normal m-0 h-[var(--ctl-h)] leading-[var(--ctl-h)]\"\n >\n {{ inlineLabel }}\n </FieldLabel>\n </Field>\n </FieldGroup>\n\n <!-- Radio 버튼: radioDirection에 따라 분기 처리 -->\n <FieldGroup v-else-if=\"type === 'radio'\">\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n :class=\"controlClass\"\n />\n </FieldGroup>\n\n <!-- 그 외 컨트롤: orientation 규칙 그대로 따름 -->\n <FieldGroup v-else>\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n :class=\"controlClass\"\n />\n </FieldGroup>\n \n <!-- 설명/에러: 항상 컨트롤 '바로 아래'에 표시 -->\n <FieldContent v-if=\"description || finalError\">\n <FieldDescription v-if=\"description\">\n {{ description }}\n </FieldDescription>\n <FieldError v-if=\"finalError\">\n {{ finalError }}\n </FieldError>\n </FieldContent>\n </FieldContent>\n </Field>\n </FieldGroup>\n </div>\n</template>\n\n\n\n<style>\n/* ⬇⬇ 높이 토큰(밀도) — 프로젝트 전역/레이아웃에 한 번 정의해두고 재사용하세요 */\n.form-density-sm { --ctl-h: 2rem; /* 32px */ }\n.form-density-md { --ctl-h: 2.25rem; /* 36px (shadcn 기본에 근접) */ }\n.form-density-lg { --ctl-h: 2.5rem; /* 40px */ }\n</style>"],"names":["FORM_FIELD_PROPS","props","__props","emit","__emit","internalError","ref","finalError","computed","controlProps","result","propsObj","key","defaultPlaceholders","validateField","currentValue","value","shouldValidateOnMount","handleUpdateModelValue","handleChange","handleFocus","event","handleBlur","labelAlignClass","mapHorizontal","mapVertical","densityClass","controlClass","baseClass","componentMap","JInput","JTextarea","JCheckbox","JSwitch","JCombo","JRadio","JSearchCombo","JDatepicker","resolvedComponent","__expose","_createElementBlock","_createVNode","_unref","FieldGroup","Field","_normalizeClass","_normalizeStyle","FieldLabel","_createTextVNode","_toDisplayString","_hoisted_1","FieldContent","_createBlock","_openBlock","_resolveDynamicComponent","_mergeProps","FieldDescription","FieldError"],"mappings":"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"}
1
+ {"version":3,"file":"JFormField.vue.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,265 +1,13 @@
1
- import { defineComponent as N, ref as R, computed as c, createElementBlock as D, openBlock as o, normalizeClass as p, createVNode as u, unref as a, withCtx as i, normalizeStyle as S, createTextVNode as y, createCommentVNode as d, toDisplayString as h, createBlock as n, resolveDynamicComponent as w, mergeProps as B } from "vue";
2
- import "../shadcn/index.js";
3
- import "lucide-vue-next";
4
- import F from "../atoms/JInput.vue.js";
5
- import W from "../atoms/JTextarea.vue.js";
6
- import H from "../atoms/JCheckbox.vue.js";
7
- import I from "../atoms/JCombo.vue.js";
8
- import J from "../atoms/JSearchCombo.vue.js";
9
- import Y from "../atoms/JRadio.vue.js";
10
- import G from "../atoms/JSwitch.vue.js";
11
- import K from "../atoms/JDatepicker.vue.js";
12
- import "md-editor-v3";
13
- /* empty css */
14
- /* empty css */
15
- import "clsx";
16
- import "tailwind-merge";
17
- import "../shadcn/badge-variants.js";
18
- import "@vueuse/core";
19
- import "reka-ui";
20
- /* empty css */
21
- import "../shadcn/avatar-variants.js";
22
- import "dompurify";
23
- /* empty css */
24
- import "ag-grid-vue3";
25
- import "ag-grid-community";
26
- import "ag-grid-enterprise";
27
- /* empty css */
28
- /* empty css */
29
- /* empty css */
30
- /* empty css */
31
- import "vue-sonner";
32
- import v from "../shadcn/FieldGroup.vue.js";
33
- import T from "../shadcn/Field.vue.js";
34
- import M from "../shadcn/FieldLabel.vue.js";
35
- import L from "../shadcn/FieldContent.vue.js";
36
- import Q from "../shadcn/FieldDescription.vue.js";
37
- import X from "../shadcn/FieldError.vue.js";
38
- const Z = {
39
- key: 0,
40
- class: "text-destructive ml-1"
41
- }, Pe = /* @__PURE__ */ N({
42
- __name: "JFormField",
43
- props: {
44
- label: {},
45
- description: {},
46
- errorMsg: {},
47
- type: { default: "input" },
48
- inlineLabel: {},
49
- orientation: { default: "vertical" },
50
- labelAlign: { default: "left" },
51
- labelWidth: { default: "8rem" },
52
- id: {},
53
- modelValue: {},
54
- placeholder: {},
55
- disabled: { type: Boolean },
56
- readonly: { type: Boolean },
57
- required: { type: Boolean },
58
- name: {},
59
- styleType: {},
60
- inputType: {},
61
- options: {},
62
- multiple: { type: Boolean },
63
- radioDirection: { default: "horizontal" }
64
- },
65
- emits: ["update:modelValue", "change", "focus", "blur"],
66
- setup(l, { expose: j, emit: A }) {
67
- const E = [
68
- "label",
69
- "description",
70
- "errorMsg",
71
- "type",
72
- "inlineLabel",
73
- "orientation",
74
- "labelAlign",
75
- "labelWidth",
76
- "radioDirection"
77
- ], t = l, f = A, s = R(""), g = c(() => t.errorMsg || s.value), b = c(() => {
78
- const e = {}, r = t;
79
- for (const m in r)
80
- E.includes(m) || (e[m] = r[m]);
81
- if (t.inputType && t.type === "input" && (e.type = t.inputType, delete e.inputType, !t.placeholder)) {
82
- const m = {
83
- text: "텍스트를 입력하세요",
84
- email: "이메일을 입력하세요",
85
- password: "비밀번호를 입력하세요",
86
- tel: "전화번호를 입력하세요",
87
- url: "URL을 입력하세요",
88
- number: "숫자를 입력하세요",
89
- search: "검색어를 입력하세요",
90
- date: "날짜를 선택하세요",
91
- time: "시간을 선택하세요",
92
- "datetime-local": "날짜와 시간을 선택하세요",
93
- month: "월을 선택하세요",
94
- week: "주를 선택하세요"
95
- };
96
- e.placeholder = m[t.inputType] || "입력하세요";
97
- }
98
- return t.radioDirection && t.type === "radio" && (e.styletype = t.radioDirection, delete e.radioDirection), e;
99
- }), x = (e) => {
100
- if (!t.required) return;
101
- s.value = "";
102
- const r = e !== void 0 ? e : t.modelValue;
103
- t.type === "checkbox" || t.type === "switch" ? r !== "Y" && (s.value = "필수 항목입니다.") : (r == null || r === "") && (s.value = "필수 입력 항목입니다.");
104
- }, P = c(() => !(t.modelValue !== null && t.modelValue !== void 0 && t.modelValue !== "")), k = (e) => {
105
- f("update:modelValue", e), x(e);
106
- }, _ = (e) => {
107
- f("change", e), x(e);
108
- }, $ = (e) => {
109
- f("focus", e);
110
- }, C = (e) => {
111
- P.value && x(), f("blur", e);
112
- }, U = c(() => {
113
- const e = {
114
- left: "justify-start",
115
- // 레이블 영역의 왼쪽에 레이블 위치
116
- middle: "justify-center",
117
- // 레이블 영역의 가운데에 레이블 위치
118
- right: "justify-end"
119
- // 레이블 영역의 오른쪽에 레이블 위치 (input과 가까이)
120
- }, r = { left: "text-left", middle: "text-center", right: "text-right" };
121
- return t.orientation === "horizontal" ? e[t.labelAlign] : r[t.labelAlign];
122
- }), O = c(() => {
123
- switch (t.styleType) {
124
- case "sm":
125
- return "form-density-sm";
126
- case "lg":
127
- return "form-density-lg";
128
- default:
129
- return "form-density-md";
130
- }
131
- }), z = c(() => {
132
- const e = "h-[var(--ctl-h)] leading-[var(--ctl-h)]";
133
- return t.type === "datepicker" ? `${e} max-w-xs` : t.type === "radio" && t.radioDirection === "vertical" ? "" : e;
134
- }), q = {
135
- input: F,
136
- textarea: W,
137
- checkbox: H,
138
- switch: G,
139
- combo: I,
140
- radio: Y,
141
- searchCombo: J,
142
- datepicker: K
143
- }, V = c(() => q[t.type] || F);
144
- return j({
145
- clearError: () => {
146
- s.value = "";
147
- }
148
- }), (e, r) => (o(), D("div", {
149
- class: p(["space-y-2 flex-1 min-w-0", O.value])
150
- }, [
151
- u(a(v), null, {
152
- default: i(() => [
153
- u(a(T), {
154
- class: p([
155
- l.orientation === "horizontal" ? "grid grid-cols-[var(--label-w,8rem)_1fr] items-start space-y-0 gap-2" : "space-y-1 gap-1"
156
- ]),
157
- style: S(l.orientation === "horizontal" ? `--label-w:${l.labelWidth};` : "")
158
- }, {
159
- default: i(() => [
160
- u(a(M), {
161
- for: l.id,
162
- class: p([
163
- l.orientation === "horizontal" ? "flex items-center h-[var(--ctl-h)] w-full" : "flex items-center",
164
- U.value
165
- ])
166
- }, {
167
- default: i(() => [
168
- y(h(l.label) + " ", 1),
169
- l.required ? (o(), D("span", Z, "*")) : d("", !0)
170
- ]),
171
- _: 1
172
- }, 8, ["for", "class"]),
173
- u(a(L), {
174
- class: p([
175
- l.orientation === "horizontal" ? "min-h-[var(--ctl-h)] flex flex-col justify-start gap-0.5 mt-0" : "space-y-2 gap-0"
176
- ])
177
- }, {
178
- default: i(() => [
179
- l.type === "checkbox" || l.type === "switch" ? (o(), n(a(v), {
180
- key: 0,
181
- "data-slot": "checkbox-group"
182
- }, {
183
- default: i(() => [
184
- u(a(T), {
185
- orientation: "horizontal",
186
- class: "flex gap-2 space-y-0 h-[var(--ctl-h)] leading-[var(--ctl-h)] items-center"
187
- }, {
188
- default: i(() => [
189
- (o(), n(w(V.value), B(b.value, {
190
- "onUpdate:modelValue": k,
191
- onChange: _,
192
- onFocus: $,
193
- onBlur: C
194
- }), null, 16)),
195
- l.inlineLabel ? (o(), n(a(M), {
196
- key: 0,
197
- for: l.id,
198
- class: "font-normal m-0 h-[var(--ctl-h)] leading-[var(--ctl-h)]"
199
- }, {
200
- default: i(() => [
201
- y(h(l.inlineLabel), 1)
202
- ]),
203
- _: 1
204
- }, 8, ["for"])) : d("", !0)
205
- ]),
206
- _: 1
207
- })
208
- ]),
209
- _: 1
210
- })) : l.type === "radio" ? (o(), n(a(v), { key: 1 }, {
211
- default: i(() => [
212
- (o(), n(w(V.value), B(b.value, {
213
- "onUpdate:modelValue": k,
214
- onChange: _,
215
- onFocus: $,
216
- onBlur: C,
217
- class: z.value
218
- }), null, 16, ["class"]))
219
- ]),
220
- _: 1
221
- })) : (o(), n(a(v), { key: 2 }, {
222
- default: i(() => [
223
- (o(), n(w(V.value), B(b.value, {
224
- "onUpdate:modelValue": k,
225
- onChange: _,
226
- onFocus: $,
227
- onBlur: C,
228
- class: z.value
229
- }), null, 16, ["class"]))
230
- ]),
231
- _: 1
232
- })),
233
- l.description || g.value ? (o(), n(a(L), { key: 3 }, {
234
- default: i(() => [
235
- l.description ? (o(), n(a(Q), { key: 0 }, {
236
- default: i(() => [
237
- y(h(l.description), 1)
238
- ]),
239
- _: 1
240
- })) : d("", !0),
241
- g.value ? (o(), n(a(X), { key: 1 }, {
242
- default: i(() => [
243
- y(h(g.value), 1)
244
- ]),
245
- _: 1
246
- })) : d("", !0)
247
- ]),
248
- _: 1
249
- })) : d("", !0)
250
- ]),
251
- _: 1
252
- }, 8, ["class"])
253
- ]),
254
- _: 1
255
- }, 8, ["class", "style"])
256
- ]),
257
- _: 1
258
- })
259
- ], 2));
260
- }
261
- });
1
+ import o from "./JFormField.vue2.js";
2
+ /* empty css */
3
+ const r = (r_comp, r_opts) => {
4
+ const r_merged = r_comp.__vccOpts || r_comp;
5
+ for (const [r_key, r_val] of r_opts)
6
+ r_merged[r_key] = r_val;
7
+ return r_merged;
8
+ };
9
+ const f = /* @__PURE__ */ r(o, [["__scopeId", "data-v-9053fa66"]]);
262
10
  export {
263
- Pe as default
11
+ f as default
264
12
  };
265
13
  //# sourceMappingURL=JFormField.vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"JFormField.vue.js","sources":["../../../../src/components/molecules/JFormField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { Field, FieldContent, FieldLabel, FieldDescription, FieldError, FieldGroup } from '@/components/shadcn'\nimport { JInput, JTextarea, JCheckbox, JSwitch, JCombo, JRadio, JSearchCombo, JDatepicker } from '@/components/atoms'\n\n// 컴포넌트 타입 정의\ntype ComponentType = 'input' | 'textarea' | 'checkbox' | 'switch' | 'combo' | 'radio' | 'searchCombo' | 'datepicker'\n\n// FormField 자체의 props (레이아웃 관련)\nconst FORM_FIELD_PROPS = [\n 'label',\n 'description',\n 'errorMsg',\n 'type',\n 'inlineLabel',\n 'orientation',\n 'labelAlign',\n 'labelWidth',\n 'radioDirection',\n] as const\n\nconst props = withDefaults(\n defineProps<{\n // ============ FormField 자체 props (레이아웃만) ============\n /** 필드 레이블 */\n label?: string\n /** 필드 설명 (레이블 아래 표시) */\n description?: string\n /** 에러 메시지 */\n errorMsg?: string\n /** 컴포넌트 타입 (렌더링할 컴포넌트 지정) */\n type?: ComponentType\n /** 체크박스/스위치 타입일 때만 사용하는 옆 라벨 */\n inlineLabel?: string\n /** 레이블과 컨트롤의 배치 방향 */\n orientation?: 'vertical' | 'horizontal' | 'responsive'\n /** 레이블 텍스트 정렬 */\n labelAlign?: 'left' | 'middle' | 'right'\n /** 레이블 영역 너비 (horizontal orientation일 때만 적용) */\n labelWidth?: string\n\n // ============ 내부 컴포넌트로 전달할 공통 props ============\n /** Input 요소의 id (label for와 연결) */\n id?: string\n /** v-model로 양방향 데이터 바인딩 */\n modelValue?: any\n /** 입력 전 표시되는 안내문 (Input/Textarea/Select/Combobox) */\n placeholder?: string\n /** 비활성화 상태 (전체) */\n disabled?: boolean\n /** 읽기 전용 상태 (Input/Textarea) */\n readonly?: boolean\n /** 필수 입력/선택 여부 (전체) */\n required?: boolean\n /** form 데이터 전송 시 키 이름 (전체) */\n name?: string\n /** 스타일 테마 지정 (J-prefixed 컴포넌트의 styleType) */\n styleType?: string\n\n // ============ Input 전용 props ============\n /** Input 타입 (text, email, password 등) */\n inputType?: string\n\n\n // ============ Select/Combobox/Radio 전용 props ============\n /** 선택 가능한 항목 배열 */\n options?: Array<{ label: string; value: string | number; disabled?: boolean }>\n \n // ============ Select/Combobox 전용 props ============\n /** 다중 선택 허용 여부 */\n multiple?: boolean\n\n\n // ============ Radio 전용 props ============\n /** Radio 옵션 나열 방향 */\n radioDirection?: 'horizontal' | 'vertical'\n }>(),\n {\n type: 'input',\n orientation: 'vertical',\n labelAlign: 'left',\n labelWidth: '8rem',\n radioDirection: 'horizontal',\n }\n)\n\n// 이벤트 정의\nconst emit = defineEmits<{\n 'update:modelValue': [value: any]\n 'change': [value: any]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n// 내부 에러 상태 (props.error가 없을 때만 사용)\nconst internalError = ref<string>('')\n\n// 최종 에러 메시지 (외부 errorMsg가 우선)\nconst finalError = computed(() => props.errorMsg || internalError.value)\n\n// FormField 자체 props와 내부 컴포넌트 props 분리\nconst controlProps = computed(() => {\n const result: Record<string, any> = {}\n const propsObj = props as Record<string, any>\n \n for (const key in propsObj) {\n // FormField 자체 props는 제외\n if (!FORM_FIELD_PROPS.includes(key as any)) {\n result[key] = propsObj[key]\n }\n }\n \n // inputType을 type으로 변환 (JInput 컴포넌트에서 사용)\n if (props.inputType && props.type === 'input') {\n result.type = props.inputType\n delete result.inputType // inputType은 제거\n \n // placeholder가 없으면 inputType에 따라 기본값 설정\n if (!props.placeholder) {\n const defaultPlaceholders: Record<string, string> = {\n 'text': '텍스트를 입력하세요',\n 'email': '이메일을 입력하세요',\n 'password': '비밀번호를 입력하세요',\n 'tel': '전화번호를 입력하세요',\n 'url': 'URL을 입력하세요',\n 'number': '숫자를 입력하세요',\n 'search': '검색어를 입력하세요',\n 'date': '날짜를 선택하세요',\n 'time': '시간을 선택하세요',\n 'datetime-local': '날짜와 시간을 선택하세요',\n 'month': '월을 선택하세요',\n 'week': '주를 선택하세요',\n }\n \n result.placeholder = defaultPlaceholders[props.inputType] || '입력하세요'\n }\n }\n \n // radioDirection을 styletype으로 변환 (JRadio 컴포넌트에서 사용)\n if (props.radioDirection && props.type === 'radio') {\n result.styletype = props.radioDirection\n delete result.radioDirection // radioDirection은 제거\n }\n \n return result\n})\n\n // Built-in validation\n const validateField = (currentValue?: any) => {\n if (!props.required) return\n\n internalError.value = ''\n\n // 현재 값 또는 props.modelValue 사용\n const value = currentValue !== undefined ? currentValue : props.modelValue\n\n // Required 체크\n if (props.type === 'checkbox' || props.type === 'switch') {\n if (value !== 'Y') {\n internalError.value = '필수 항목입니다.'\n }\n } else {\n if (value === null || value === undefined || value === '') {\n internalError.value = '필수 입력 항목입니다.'\n }\n }\n }\n\n // 초기 로드 시 validation 실행 (blur 이벤트에서만)\n const shouldValidateOnMount = computed(() => {\n // Storybook에서 초기값이 있는 경우 validation 스킵\n if (props.modelValue !== null && props.modelValue !== undefined && props.modelValue !== '') {\n return false\n }\n return true\n })\n\n// 이벤트 핸들러\nconst handleUpdateModelValue = (value: any) => {\n emit('update:modelValue', value)\n \n // 값이 변경되면 즉시 validation 실행 (현재 값 전달)\n validateField(value)\n}\n\nconst handleChange = (value: any) => {\n emit('change', value)\n \n // change 이벤트에서도 validation 실행 (현재 값 전달)\n validateField(value)\n}\n\nconst handleFocus = (event: FocusEvent) => {\n emit('focus', event)\n}\n\n const handleBlur = (event: FocusEvent) => {\n // blur 시에만 validation 실행 (초기 로드 시에는 실행하지 않음)\n if (shouldValidateOnMount.value) {\n validateField()\n }\n emit('blur', event)\n }\n\n// 레이블 정렬 클래스 (레이블 영역 내에서 레이블의 위치 제어)\nconst labelAlignClass = computed(() => {\n // horizontal일 때는 레이블 영역 내에서 레이블의 위치를 제어\n const mapHorizontal = { \n left: 'justify-start', // 레이블 영역의 왼쪽에 레이블 위치\n middle: 'justify-center', // 레이블 영역의 가운데에 레이블 위치\n right: 'justify-end' // 레이블 영역의 오른쪽에 레이블 위치 (input과 가까이)\n }\n // vertical일 때는 텍스트 정렬만 제어\n const mapVertical = { left: 'text-left', middle: 'text-center', right: 'text-right' }\n return props.orientation === 'horizontal' ? mapHorizontal[props.labelAlign] : mapVertical[props.labelAlign]\n})\n\n/** 행높이 토큰 클래스 매핑 */\nconst densityClass = computed(() => {\n switch (props.styleType) {\n case 'sm': return 'form-density-sm'\n case 'lg': return 'form-density-lg'\n default: return 'form-density-md'\n }\n})\n\n/** 컨트롤 클래스 (datepicker는 최대 너비 제한, radio vertical은 높이 제한 없음) */\nconst controlClass = computed(() => {\n const baseClass = 'h-[var(--ctl-h)] leading-[var(--ctl-h)]'\n \n if (props.type === 'datepicker') {\n return `${baseClass} max-w-xs`\n }\n \n // Radio vertical일 때는 높이 제한 없음\n if (props.type === 'radio' && props.radioDirection === 'vertical') {\n return ''\n }\n \n return baseClass\n})\n\n// 컴포넌트 매핑\nconst componentMap: Record<ComponentType, any> = {\n input: JInput,\n textarea: JTextarea,\n checkbox: JCheckbox,\n switch: JSwitch,\n combo: JCombo,\n radio: JRadio,\n searchCombo: JSearchCombo,\n datepicker: JDatepicker,\n}\n\n// type에 따라 렌더링할 컴포넌트 결정\nconst resolvedComponent = computed(() => {\n return componentMap[props.type!] || JInput\n})\n\n// 외부에서 수동으로 에러 클리어 가능하도록 expose\ndefineExpose({\n clearError: () => { internalError.value = '' }\n})\n</script>\n\n<template>\n <div :class=\"['space-y-2 flex-1 min-w-0', densityClass]\">\n <FieldGroup >\n <Field :class=\"[\n orientation === 'horizontal'\n ? 'grid grid-cols-[var(--label-w,8rem)_1fr] items-start space-y-0 gap-2'\n : 'space-y-1 gap-1'\n ]\"\n :style=\"orientation === 'horizontal' ? `--label-w:${labelWidth};` : ''\"\n >\n <!-- 메인 라벨 (필수표기 포함) -->\n <FieldLabel \n :for=\"id\" \n :class=\"[\n orientation === 'horizontal'\n ? 'flex items-center h-[var(--ctl-h)] w-full'\n : 'flex items-center',\n labelAlignClass\n ]\"\n >\n {{ label }}\n <span v-if=\"required\" class=\"text-destructive ml-1\">*</span>\n </FieldLabel>\n\n <FieldContent \n :class=\"[\n orientation === 'horizontal'\n ? 'min-h-[var(--ctl-h)] flex flex-col justify-start gap-0.5 mt-0'\n : 'space-y-2 gap-0'\n ]\"\n >\n <!-- 체크박스/스위치: 항상 가로 정렬로 컨트롤 + 인라인 라벨 묶기 -->\n <FieldGroup v-if=\"type === 'checkbox' || type === 'switch'\" data-slot=\"checkbox-group\">\n <!-- 부모 orientation과 무관하게 수평 정렬 고정 -->\n <Field orientation=\"horizontal\" class=\"flex gap-2 space-y-0 h-[var(--ctl-h)] leading-[var(--ctl-h)] items-center\">\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n />\n <FieldLabel\n v-if=\"inlineLabel\"\n :for=\"id\"\n class=\"font-normal m-0 h-[var(--ctl-h)] leading-[var(--ctl-h)]\"\n >\n {{ inlineLabel }}\n </FieldLabel>\n </Field>\n </FieldGroup>\n\n <!-- Radio 버튼: radioDirection에 따라 분기 처리 -->\n <FieldGroup v-else-if=\"type === 'radio'\">\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n :class=\"controlClass\"\n />\n </FieldGroup>\n\n <!-- 그 외 컨트롤: orientation 규칙 그대로 따름 -->\n <FieldGroup v-else>\n <component\n :is=\"resolvedComponent\"\n v-bind=\"controlProps\"\n @update:modelValue=\"handleUpdateModelValue\"\n @change=\"handleChange\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n :class=\"controlClass\"\n />\n </FieldGroup>\n \n <!-- 설명/에러: 항상 컨트롤 '바로 아래'에 표시 -->\n <FieldContent v-if=\"description || finalError\">\n <FieldDescription v-if=\"description\">\n {{ description }}\n </FieldDescription>\n <FieldError v-if=\"finalError\">\n {{ finalError }}\n </FieldError>\n </FieldContent>\n </FieldContent>\n </Field>\n </FieldGroup>\n </div>\n</template>\n\n\n\n<style>\n/* ⬇⬇ 높이 토큰(밀도) — 프로젝트 전역/레이아웃에 한 번 정의해두고 재사용하세요 */\n.form-density-sm { --ctl-h: 2rem; /* 32px */ }\n.form-density-md { --ctl-h: 2.25rem; /* 36px (shadcn 기본에 근접) */ }\n.form-density-lg { --ctl-h: 2.5rem; /* 40px */ }\n</style>"],"names":["FORM_FIELD_PROPS","props","__props","emit","__emit","internalError","ref","finalError","computed","controlProps","result","propsObj","key","defaultPlaceholders","validateField","currentValue","value","shouldValidateOnMount","handleUpdateModelValue","handleChange","handleFocus","event","handleBlur","labelAlignClass","mapHorizontal","mapVertical","densityClass","controlClass","baseClass","componentMap","JInput","JTextarea","JCheckbox","JSwitch","JCombo","JRadio","JSearchCombo","JDatepicker","resolvedComponent","__expose","_createElementBlock","_createVNode","_unref","FieldGroup","Field","_normalizeClass","_normalizeStyle","FieldLabel","_createTextVNode","_toDisplayString","_hoisted_1","FieldContent","_createBlock","_openBlock","_resolveDynamicComponent","_mergeProps","FieldDescription","FieldError"],"mappings":"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"}
1
+ {"version":3,"file":"JFormField.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue");require("../shadcn/index.cjs");require("lucide-vue-next");;/* empty css */const h=require("../atoms/JInput.vue.cjs"),F=require("../atoms/JTextarea.vue.cjs"),N=require("../atoms/JCheckbox.vue.cjs"),z=require("../atoms/JCombo.vue.cjs"),T=require("../atoms/JSearchCombo.vue.cjs"),S=require("../atoms/JRadio.vue.cjs"),J=require("../atoms/JSwitch.vue.cjs"),M=require("../atoms/JDatepicker.vue.cjs");require("md-editor-v3");;/* empty css */;/* empty css */const P=require("../../lib/utils.cjs");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");const i=require("../shadcn/FieldGroup.vue.cjs"),g=require("../shadcn/Field.vue.cjs"),k=require("../shadcn/FieldLabel.vue.cjs"),q=require("../shadcn/FieldContent.vue.cjs"),E=require("../shadcn/FieldDescription.vue.cjs"),L=require("../shadcn/FieldError.vue.cjs"),j={key:0,class:"text-destructive ml-1"},A=e.defineComponent({__name:"JFormField",props:{class:{},label:{},description:{},errorMsg:{},type:{default:"input"},inlineLabel:{},orientation:{default:"vertical"},labelAlign:{default:"left"},labelWidth:{default:"8rem"},id:{},modelValue:{},placeholder:{},disabled:{type:Boolean},readonly:{type:Boolean},required:{type:Boolean},name:{},styleType:{},inputType:{},options:{},multiple:{type:Boolean},radioDirection:{default:"horizontal"}},emits:["update:modelValue","change","focus","blur"],setup(l,{expose:x,emit:C}){const b=["class","label","description","errorMsg","type","inlineLabel","orientation","labelAlign","labelWidth","radioDirection"],t=l,n=C,o=e.ref(""),c=e.computed(()=>t.errorMsg||o.value),s=e.computed(()=>{const r={},a=t;for(const u in a)b.includes(u)||(r[u]=a[u]);if(t.inputType&&t.type==="input"&&(r.type=t.inputType,delete r.inputType,!t.placeholder)){const u={text:"텍스트를 입력하세요",email:"이메일을 입력하세요",password:"비밀번호를 입력하세요",tel:"전화번호를 입력하세요",url:"URL을 입력하세요",number:"숫자를 입력하세요",search:"검색어를 입력하세요",date:"날짜를 선택하세요",time:"시간을 선택하세요","datetime-local":"날짜와 시간을 선택하세요",month:"월을 선택하세요",week:"주를 선택하세요"};r.placeholder=u[t.inputType]||"입력하세요"}return t.radioDirection&&t.type==="radio"&&(r.styletype=t.radioDirection,delete r.radioDirection),r}),d=r=>{if(!t.required)return;o.value="";const a=r!==void 0?r:t.modelValue;t.type==="checkbox"||t.type==="switch"?a!=="Y"&&(o.value="필수 항목입니다."):(a==null||a==="")&&(o.value="필수 입력 항목입니다.")},B=e.computed(()=>!(t.modelValue!==null&&t.modelValue!==void 0&&t.modelValue!=="")),p=r=>{n("update:modelValue",r),d(r)},f=r=>{n("change",r),d(r)},_=r=>{n("focus",r)},m=r=>{B.value&&d(),n("blur",r)},V=e.computed(()=>{const r={left:"justify-start",middle:"justify-center",right:"justify-end"},a={left:"text-left",middle:"text-center",right:"text-right"};return t.orientation==="horizontal"?r[t.labelAlign]:a[t.labelAlign]}),w=e.computed(()=>{switch(t.styleType){case"md":return"form-density-md";case"lg":return"form-density-lg";default:return"form-density-sm"}}),v=e.computed(()=>{const r="h-[var(--ctl-h)] leading-[var(--ctl-h)]";return t.type==="datepicker"?`${r} max-w-xs`:t.type==="radio"&&t.radioDirection==="vertical"?"":r}),D={input:h.default,textarea:F.default,checkbox:N.default,switch:J.default,combo:z.default,radio:S.default,searchCombo:T.default,datepicker:M.default},y=e.computed(()=>D[t.type]||h.default);return x({clearError:()=>{o.value=""}}),(r,a)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(e.unref(P.cn)("space-y-2 flex-1 min-w-0",w.value,t.class))},[e.createVNode(e.unref(i.default),null,{default:e.withCtx(()=>[e.createVNode(e.unref(g.default),{class:e.normalizeClass([l.orientation==="horizontal"?"grid grid-cols-[var(--label-w,8rem)_1fr] items-start space-y-0 gap-2":"space-y-1 gap-1"]),style:e.normalizeStyle(l.orientation==="horizontal"?`--label-w:${l.labelWidth};`:"")},{default:e.withCtx(()=>[e.createVNode(e.unref(k.default),{for:l.id,class:e.normalizeClass(["text-xs",l.orientation==="horizontal"?"flex items-center h-[var(--ctl-h)] w-full":"flex items-center",V.value])},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.label)+" ",1),l.required?(e.openBlock(),e.createElementBlock("span",j,"*")):e.createCommentVNode("",!0)]),_:1},8,["for","class"]),e.createVNode(e.unref(q.default),{class:e.normalizeClass([l.orientation==="horizontal"?"min-h-[var(--ctl-h)] flex flex-col justify-start gap-0.5 mt-0":"space-y-2 gap-0"])},{default:e.withCtx(()=>[l.type==="checkbox"||l.type==="switch"?(e.openBlock(),e.createBlock(e.unref(i.default),{key:0,"data-slot":"checkbox-group"},{default:e.withCtx(()=>[e.createVNode(e.unref(g.default),{orientation:"horizontal",class:"flex gap-2 space-y-0 h-[var(--ctl-h)] leading-[var(--ctl-h)] items-center"},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m}),null,16)),l.inlineLabel?(e.openBlock(),e.createBlock(e.unref(k.default),{key:0,for:l.id,class:"text-xs font-normal m-0 h-[var(--ctl-h)] leading-[var(--ctl-h)]"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.inlineLabel),1)]),_:1},8,["for"])):e.createCommentVNode("",!0)]),_:1})]),_:1})):l.type==="radio"?(e.openBlock(),e.createBlock(e.unref(i.default),{key:1},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m,class:v.value}),null,16,["class"]))]),_:1})):(e.openBlock(),e.createBlock(e.unref(i.default),{key:2},{default:e.withCtx(()=>[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(y.value),e.mergeProps(s.value,{"onUpdate:modelValue":p,onChange:f,onFocus:_,onBlur:m,class:v.value}),null,16,["class"]))]),_:1})),l.description||c.value?(e.openBlock(),e.createBlock(e.unref(q.default),{key:3},{default:e.withCtx(()=>[l.description?(e.openBlock(),e.createBlock(e.unref(E.default),{key:0},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(l.description),1)]),_:1})):e.createCommentVNode("",!0),c.value?(e.openBlock(),e.createBlock(e.unref(L.default),{key:1},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(c.value),1)]),_:1})):e.createCommentVNode("",!0)]),_:1})):e.createCommentVNode("",!0)]),_:1},8,["class"])]),_:1},8,["class","style"])]),_:1})],2))}});exports.default=A;
2
+ //# sourceMappingURL=JFormField.vue2.cjs.map