@j-solution/components 1.6.0 → 1.7.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 (197) hide show
  1. package/README.md +8 -7
  2. package/assets/jwms-portal-frontend-CwxPfHfa.css +1 -0
  3. package/assets/styles/j-components.css +1 -1
  4. package/assets/styles/themes.css +107 -0
  5. package/components/atoms/JAvatar.vue.cjs +1 -1
  6. package/components/atoms/JAvatar.vue.cjs.map +1 -1
  7. package/components/atoms/JAvatar.vue.js +10 -7
  8. package/components/atoms/JAvatar.vue.js.map +1 -1
  9. package/components/atoms/JBadge.vue.cjs +1 -1
  10. package/components/atoms/JBadge.vue.cjs.map +1 -1
  11. package/components/atoms/JBadge.vue.js +7 -6
  12. package/components/atoms/JBadge.vue.js.map +1 -1
  13. package/components/atoms/JButton.vue.cjs +1 -1
  14. package/components/atoms/JButton.vue.cjs.map +1 -1
  15. package/components/atoms/JButton.vue.js +5 -5
  16. package/components/atoms/JButton.vue.js.map +1 -1
  17. package/components/atoms/JDatepicker.vue.cjs +1 -1
  18. package/components/atoms/JDatepicker.vue.cjs.map +1 -1
  19. package/components/atoms/JDatepicker.vue.js +10 -10
  20. package/components/atoms/JDatepicker.vue.js.map +1 -1
  21. package/components/atoms/JEditor.vue.cjs +1 -1
  22. package/components/atoms/JEditor.vue.js +1 -1
  23. package/components/atoms/JEditor.vue2.cjs +1 -1
  24. package/components/atoms/JEditor.vue2.cjs.map +1 -1
  25. package/components/atoms/JEditor.vue2.js +31 -17
  26. package/components/atoms/JEditor.vue2.js.map +1 -1
  27. package/components/atoms/JGrid.vue.cjs +1 -1
  28. package/components/atoms/JGrid.vue.js +2 -2
  29. package/components/atoms/JGrid.vue2.cjs +1 -1
  30. package/components/atoms/JGrid.vue2.cjs.map +1 -1
  31. package/components/atoms/JGrid.vue2.js +45 -33
  32. package/components/atoms/JGrid.vue2.js.map +1 -1
  33. package/components/atoms/JIcon.vue.cjs +1 -1
  34. package/components/atoms/JIcon.vue.cjs.map +1 -1
  35. package/components/atoms/JIcon.vue.js +14 -13
  36. package/components/atoms/JIcon.vue.js.map +1 -1
  37. package/components/atoms/JKbd.vue.cjs +1 -1
  38. package/components/atoms/JKbd.vue.cjs.map +1 -1
  39. package/components/atoms/JKbd.vue.js +13 -10
  40. package/components/atoms/JKbd.vue.js.map +1 -1
  41. package/components/atoms/JLabel.vue.cjs +1 -1
  42. package/components/atoms/JLabel.vue.cjs.map +1 -1
  43. package/components/atoms/JLabel.vue.js +4 -4
  44. package/components/atoms/JLabel.vue.js.map +1 -1
  45. package/components/atoms/JLink.vue.cjs +1 -1
  46. package/components/atoms/JLink.vue.cjs.map +1 -1
  47. package/components/atoms/JLink.vue.js +5 -5
  48. package/components/atoms/JLink.vue.js.map +1 -1
  49. package/components/atoms/JPreview.vue.cjs +1 -1
  50. package/components/atoms/JPreview.vue.js +2 -2
  51. package/components/atoms/JPreview.vue2.cjs +1 -1
  52. package/components/atoms/JPreview.vue2.cjs.map +1 -1
  53. package/components/atoms/JPreview.vue2.js +33 -20
  54. package/components/atoms/JPreview.vue2.js.map +1 -1
  55. package/components/atoms/JProgress.vue.cjs +1 -1
  56. package/components/atoms/JProgress.vue.cjs.map +1 -1
  57. package/components/atoms/JProgress.vue.js +15 -9
  58. package/components/atoms/JProgress.vue.js.map +1 -1
  59. package/components/atoms/JRadio.vue.cjs +1 -1
  60. package/components/atoms/JRadio.vue.cjs.map +1 -1
  61. package/components/atoms/JRadio.vue.js +1 -1
  62. package/components/atoms/JRadio.vue.js.map +1 -1
  63. package/components/atoms/JSearchCombo.vue.cjs +1 -1
  64. package/components/atoms/JSearchCombo.vue.cjs.map +1 -1
  65. package/components/atoms/JSearchCombo.vue.js +38 -37
  66. package/components/atoms/JSearchCombo.vue.js.map +1 -1
  67. package/components/atoms/JSpinner.vue.cjs +1 -1
  68. package/components/atoms/JSpinner.vue.cjs.map +1 -1
  69. package/components/atoms/JSpinner.vue.js +8 -7
  70. package/components/atoms/JSpinner.vue.js.map +1 -1
  71. package/components/atoms/JSplitter.vue.cjs +1 -1
  72. package/components/atoms/JSplitter.vue.cjs.map +1 -1
  73. package/components/atoms/JSplitter.vue.js +32 -27
  74. package/components/atoms/JSplitter.vue.js.map +1 -1
  75. package/components/atoms/JTooltip.vue.cjs +1 -1
  76. package/components/atoms/JTooltip.vue.cjs.map +1 -1
  77. package/components/atoms/JTooltip.vue.js +18 -15
  78. package/components/atoms/JTooltip.vue.js.map +1 -1
  79. package/components/examples/ExampleCrudPage.vue.cjs +2 -0
  80. package/components/examples/ExampleCrudPage.vue.cjs.map +1 -0
  81. package/components/examples/ExampleCrudPage.vue.js +358 -0
  82. package/components/examples/ExampleCrudPage.vue.js.map +1 -0
  83. package/components/examples/ExampleCrudPage.vue2.cjs +2 -0
  84. package/components/examples/ExampleCrudPage.vue2.cjs.map +1 -0
  85. package/components/examples/ExampleCrudPage.vue2.js +5 -0
  86. package/components/examples/ExampleCrudPage.vue2.js.map +1 -0
  87. package/components/examples/ExampleTabMappingPage.vue.cjs +2 -0
  88. package/components/examples/ExampleTabMappingPage.vue.cjs.map +1 -0
  89. package/components/examples/ExampleTabMappingPage.vue.js +522 -0
  90. package/components/examples/ExampleTabMappingPage.vue.js.map +1 -0
  91. package/components/examples/ExampleTabMappingPage.vue2.cjs +2 -0
  92. package/components/examples/ExampleTabMappingPage.vue2.cjs.map +1 -0
  93. package/components/examples/ExampleTabMappingPage.vue2.js +5 -0
  94. package/components/examples/ExampleTabMappingPage.vue2.js.map +1 -0
  95. package/components/molecules/JBreadcrumb.vue.cjs +1 -1
  96. package/components/molecules/JBreadcrumb.vue.cjs.map +1 -1
  97. package/components/molecules/JBreadcrumb.vue.js +3 -3
  98. package/components/molecules/JBreadcrumb.vue.js.map +1 -1
  99. package/components/molecules/JFormField.vue.cjs +1 -1
  100. package/components/molecules/JFormField.vue.cjs.map +1 -1
  101. package/components/molecules/JFormField.vue.js +26 -24
  102. package/components/molecules/JFormField.vue.js.map +1 -1
  103. package/components/molecules/JTabs.vue.cjs +1 -1
  104. package/components/molecules/JTabs.vue.js +1 -1
  105. package/components/molecules/JTabs.vue2.cjs +1 -1
  106. package/components/molecules/JTabs.vue2.cjs.map +1 -1
  107. package/components/molecules/JTabs.vue2.js +7 -7
  108. package/components/molecules/JTabs.vue2.js.map +1 -1
  109. package/components/molecules/JTitlebar.vue.cjs +1 -1
  110. package/components/molecules/JTitlebar.vue.cjs.map +1 -1
  111. package/components/molecules/JTitlebar.vue.js +35 -36
  112. package/components/molecules/JTitlebar.vue.js.map +1 -1
  113. package/components/organisms/JFilterBar.vue.cjs +1 -1
  114. package/components/organisms/JFilterBar.vue.cjs.map +1 -1
  115. package/components/organisms/JFilterBar.vue.js +5 -5
  116. package/components/organisms/JFilterBar.vue.js.map +1 -1
  117. package/components/organisms/JHeader.vue.cjs +1 -1
  118. package/components/organisms/JHeader.vue.cjs.map +1 -1
  119. package/components/organisms/JHeader.vue.js +25 -23
  120. package/components/organisms/JHeader.vue.js.map +1 -1
  121. package/components/organisms/JModal.vue.cjs +1 -1
  122. package/components/organisms/JModal.vue.cjs.map +1 -1
  123. package/components/organisms/JModal.vue.js +30 -27
  124. package/components/organisms/JModal.vue.js.map +1 -1
  125. package/components/organisms/JSidebarAdvanced.vue.cjs +1 -1
  126. package/components/organisms/JSidebarAdvanced.vue.js +7 -7
  127. package/components/organisms/JSidebarAdvanced.vue2.cjs +1 -1
  128. package/components/organisms/JSidebarAdvanced.vue2.cjs.map +1 -1
  129. package/components/organisms/JSidebarAdvanced.vue2.js +40 -40
  130. package/components/organisms/JSidebarAdvanced.vue2.js.map +1 -1
  131. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs +1 -1
  132. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.cjs.map +1 -1
  133. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js +83 -63
  134. package/components/organisms/JSidebarSimple/JDynamicMenuItem.vue.js.map +1 -1
  135. package/components/organisms/JSidebarSimple.vue.cjs +1 -1
  136. package/components/organisms/JSidebarSimple.vue.js +2 -2
  137. package/components/organisms/JSidebarSimple.vue2.cjs +1 -1
  138. package/components/organisms/JSidebarSimple.vue2.cjs.map +1 -1
  139. package/components/organisms/JSidebarSimple.vue2.js +2 -2
  140. package/components/organisms/JSidebarSimple.vue2.js.map +1 -1
  141. package/components/shadcn/AccordionTrigger.vue.cjs +1 -1
  142. package/components/shadcn/AccordionTrigger.vue.cjs.map +1 -1
  143. package/components/shadcn/AccordionTrigger.vue.js +3 -3
  144. package/components/shadcn/AccordionTrigger.vue.js.map +1 -1
  145. package/components/shadcn/CardContent.vue.cjs +1 -1
  146. package/components/shadcn/CardContent.vue.cjs.map +1 -1
  147. package/components/shadcn/CardContent.vue.js +1 -1
  148. package/components/shadcn/CardContent.vue.js.map +1 -1
  149. package/components/shadcn/CardDescription.vue.cjs +1 -1
  150. package/components/shadcn/CardDescription.vue.cjs.map +1 -1
  151. package/components/shadcn/CardDescription.vue.js +1 -1
  152. package/components/shadcn/CardDescription.vue.js.map +1 -1
  153. package/components/shadcn/CardFooter.vue.cjs +1 -1
  154. package/components/shadcn/CardFooter.vue.cjs.map +1 -1
  155. package/components/shadcn/CardFooter.vue.js +7 -7
  156. package/components/shadcn/CardFooter.vue.js.map +1 -1
  157. package/components/shadcn/CardHeader.vue.cjs +1 -1
  158. package/components/shadcn/CardHeader.vue.cjs.map +1 -1
  159. package/components/shadcn/CardHeader.vue.js +8 -8
  160. package/components/shadcn/CardHeader.vue.js.map +1 -1
  161. package/components/shadcn/CardTitle.vue.cjs +1 -1
  162. package/components/shadcn/CardTitle.vue.cjs.map +1 -1
  163. package/components/shadcn/CardTitle.vue.js +5 -5
  164. package/components/shadcn/CardTitle.vue.js.map +1 -1
  165. package/components/shadcn/Input.vue.cjs +1 -1
  166. package/components/shadcn/Input.vue.cjs.map +1 -1
  167. package/components/shadcn/Input.vue.js +1 -1
  168. package/components/shadcn/Input.vue.js.map +1 -1
  169. package/components/shadcn/SelectTrigger.vue.cjs +1 -1
  170. package/components/shadcn/SelectTrigger.vue.cjs.map +1 -1
  171. package/components/shadcn/SelectTrigger.vue.js +2 -2
  172. package/components/shadcn/SelectTrigger.vue.js.map +1 -1
  173. package/components/shadcn/Switch.vue.cjs +1 -1
  174. package/components/shadcn/Switch.vue.cjs.map +1 -1
  175. package/components/shadcn/Switch.vue.js +2 -2
  176. package/components/shadcn/Switch.vue.js.map +1 -1
  177. package/components/shadcn/TabsList.vue.cjs +1 -1
  178. package/components/shadcn/TabsList.vue.cjs.map +1 -1
  179. package/components/shadcn/TabsList.vue.js +1 -1
  180. package/components/shadcn/TabsList.vue.js.map +1 -1
  181. package/components/shadcn/TabsTrigger.vue.cjs +1 -1
  182. package/components/shadcn/TabsTrigger.vue.cjs.map +1 -1
  183. package/components/shadcn/TabsTrigger.vue.js +4 -4
  184. package/components/shadcn/TabsTrigger.vue.js.map +1 -1
  185. package/components/shadcn/Textarea.vue.cjs +1 -1
  186. package/components/shadcn/Textarea.vue.cjs.map +1 -1
  187. package/components/shadcn/Textarea.vue.js +2 -2
  188. package/components/shadcn/Textarea.vue.js.map +1 -1
  189. package/components/shadcn/index.cjs +1 -1
  190. package/components/shadcn/index.cjs.map +1 -1
  191. package/components/shadcn/index.js +8 -7
  192. package/components/shadcn/index.js.map +1 -1
  193. package/index.cjs +1 -1
  194. package/index.js +76 -72
  195. package/package.json +1 -1
  196. package/types/index.d.ts +742 -15
  197. package/assets/jwms-portal-frontend-DntSIcYt.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"JTooltip.vue.cjs","sources":["../../../../src/components/atoms/JTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, ref, onMounted, onUnmounted } from 'vue'\r\nimport Tooltip from '@/components/shadcn/Tooltip.vue'\r\nimport TooltipContent from '@/components/shadcn/TooltipContent.vue'\r\nimport TooltipProvider from '@/components/shadcn/TooltipProvider.vue'\r\nimport TooltipTrigger from '@/components/shadcn/TooltipTrigger.vue'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'primary' // 강조 스타일 (파랑)\r\n | 'success' // 성공 스타일 (초록)\r\n | 'warning' // 경고 스타일 (주황)\r\n | 'danger' // 위험 스타일 (빨강)\r\n\r\ntype Size = 'sm' | 'md' | 'lg'\r\n\r\ntype Trigger = 'hover' | 'focus' | 'click' | 'manual'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n content?: string\r\n side?: 'top' | 'right' | 'bottom' | 'left'\r\n align?: 'start' | 'center' | 'end'\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n /** 툴팁 크기 */\r\n size?: Size\r\n /** 툴팁 비활성화 */\r\n disabled?: boolean\r\n /** 표시 지연 시간 (ms) */\r\n delay?: number\r\n /** 툴팁 최대 너비 */\r\n maxWidth?: string | number\r\n /** 툴팁 트리거 타입 */\r\n trigger?: Trigger\r\n }>(),\r\n {\r\n side: 'top',\r\n align: 'center',\r\n styletype: 'default',\r\n size: 'md',\r\n disabled: false,\r\n delay: 200,\r\n maxWidth: '200px',\r\n trigger: 'hover',\r\n },\r\n)\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n primary: { \r\n class: 'bg-blue-500 text-white border-blue-600',\r\n },\r\n success: { \r\n class: 'bg-green-500 text-white border-green-600',\r\n },\r\n warning: { \r\n class: 'bg-amber-500 text-white border-amber-600',\r\n },\r\n danger: { \r\n class: 'bg-red-500 text-white border-red-600',\r\n },\r\n}\r\n\r\n/**\r\n * size -> class 매핑\r\n */\r\nconst SIZE_PRESETS: Record<Size, { class: string }> = {\r\n sm: { \r\n class: 'text-xs px-2 py-1',\r\n },\r\n md: { \r\n class: 'text-sm px-3 py-1.5',\r\n },\r\n lg: { \r\n class: 'text-base px-4 py-2',\r\n },\r\n}\r\n\r\n// click과 manual 트리거를 위한 상태 관리\r\nconst isOpen = ref(false)\r\n\r\n// 각 트리거 타입별 핸들러\r\nconst handleClick = (event: MouseEvent) => {\r\n console.log('Click handler called, trigger:', props.trigger)\r\n if (props.trigger === 'click') {\r\n console.log('Toggling tooltip, current state:', isOpen.value)\r\n isOpen.value = !isOpen.value\r\n console.log('New state:', isOpen.value)\r\n } else if (props.trigger === 'focus') {\r\n // focus 트리거에서는 클릭 이벤트 무시\r\n event.preventDefault()\r\n event.stopPropagation()\r\n }\r\n}\r\n\r\n// delay를 위한 타이머 관리\r\nlet hoverTimer: number | null = null\r\n\r\nconst handleMouseEnter = () => {\r\n if (props.trigger === 'hover') {\r\n // 기존 타이머가 있으면 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n // delay 적용\r\n hoverTimer = setTimeout(() => {\r\n isOpen.value = true\r\n }, props.delay)\r\n }\r\n}\r\n\r\nconst handleMouseLeave = () => {\r\n if (props.trigger === 'hover') {\r\n // 타이머 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n hoverTimer = null\r\n }\r\n isOpen.value = false\r\n }\r\n}\r\n\r\nconst handleFocus = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 트리거 타입에 따른 Tooltip 설정 계산\r\nconst tooltipConfig = computed(() => {\r\n const config: any = {\r\n disabled: props.disabled,\r\n }\r\n \r\n // 모든 트리거 타입에 대해 수동 제어\r\n config.open = isOpen.value\r\n \r\n return config\r\n})\r\n\r\n// 외부 클릭 감지를 위한 핸들러\r\nconst handleOutsideClick = (event: Event) => {\r\n if (props.trigger === 'hover' && isOpen.value) {\r\n const target = event.target as HTMLElement\r\n const tooltipElement = document.querySelector('[data-tooltip-trigger]')\r\n if (tooltipElement && !tooltipElement.contains(target)) {\r\n isOpen.value = false\r\n }\r\n }\r\n}\r\n\r\n// manual 트리거를 위한 메서드들\r\nconst showTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst hideTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 외부에서 사용할 수 있도록 expose\r\ndefineExpose({\r\n showTooltip,\r\n hideTooltip,\r\n})\r\n\r\n// 외부 클릭 감지를 위한 이벤트 리스너 등록/해제\r\nonMounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.addEventListener('click', handleOutsideClick)\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.removeEventListener('click', handleOutsideClick)\r\n }\r\n \r\n // 타이머 정리\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n})\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype과 size 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const stylePreset = STYLE_PRESETS[props.styletype!]\r\n const sizePreset = SIZE_PRESETS[props.size!]\r\n const finalClass = [stylePreset.class, sizePreset.class, props.class].filter(Boolean).join(' ')\r\n \r\n // maxWidth 스타일 처리\r\n const maxWidthStyle = typeof props.maxWidth === 'number' \r\n ? `${props.maxWidth}px` \r\n : props.maxWidth\r\n \r\n return {\r\n side: props.side,\r\n align: props.align,\r\n class: finalClass,\r\n style: {\r\n maxWidth: maxWidthStyle,\r\n },\r\n }\r\n})\r\n</script>\r\n\r\n<template>\r\n <TooltipProvider :delayDuration=\"props.delay\">\r\n <Tooltip v-bind=\"tooltipConfig\">\r\n <TooltipTrigger \r\n as-child\r\n :data-tooltip-trigger=\"true\"\r\n @click=\"handleClick\"\r\n @mouseenter=\"handleMouseEnter\"\r\n @mouseleave=\"handleMouseLeave\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n >\r\n <slot name=\"trigger\" />\r\n </TooltipTrigger>\r\n <TooltipContent v-bind=\"mapped\">\r\n {{ props.content }}\r\n </TooltipContent>\r\n </Tooltip>\r\n </TooltipProvider>\r\n</template>\r\n"],"names":["props","__props","STYLE_PRESETS","SIZE_PRESETS","isOpen","ref","handleClick","event","hoverTimer","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","tooltipConfig","computed","config","handleOutsideClick","target","tooltipElement","__expose","onMounted","onUnmounted","mapped","stylePreset","sizePreset","finalClass","maxWidthStyle","_createBlock","TooltipProvider","_createVNode","Tooltip","TooltipTrigger","_renderSlot","_ctx","TooltipContent","_createTextVNode","_toDisplayString"],"mappings":"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"}
1
+ {"version":3,"file":"JTooltip.vue.cjs","sources":["../../../../src/components/atoms/JTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, ref, onMounted, onUnmounted } from 'vue'\r\nimport Tooltip from '@/components/shadcn/Tooltip.vue'\r\nimport TooltipContent from '@/components/shadcn/TooltipContent.vue'\r\nimport TooltipProvider from '@/components/shadcn/TooltipProvider.vue'\r\nimport TooltipTrigger from '@/components/shadcn/TooltipTrigger.vue'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'primary' // 강조 스타일 (파랑)\r\n | 'success' // 성공 스타일 (초록)\r\n | 'warning' // 경고 스타일 (주황)\r\n | 'danger' // 위험 스타일 (빨강)\r\n\r\ntype Size = 'xs' | 'sm' | 'md' | 'lg'\n\r\ntype Trigger = 'hover' | 'focus' | 'click' | 'manual'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n content?: string\r\n side?: 'top' | 'right' | 'bottom' | 'left'\r\n align?: 'start' | 'center' | 'end'\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n /** 툴팁 크기 */\r\n size?: Size\r\n /** 툴팁 비활성화 */\r\n disabled?: boolean\r\n /** 표시 지연 시간 (ms) */\r\n delay?: number\r\n /** 툴팁 최대 너비 */\r\n maxWidth?: string | number\r\n /** 툴팁 트리거 타입 */\r\n trigger?: Trigger\r\n }>(),\r\n {\n side: 'top',\n align: 'center',\n styletype: 'default',\n size: 'sm',\n disabled: false,\n delay: 200,\n maxWidth: '200px',\n trigger: 'hover',\r\n },\r\n)\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n primary: { \r\n class: 'bg-blue-500 text-white border-blue-600',\r\n },\r\n success: { \r\n class: 'bg-green-500 text-white border-green-600',\r\n },\r\n warning: { \r\n class: 'bg-amber-500 text-white border-amber-600',\r\n },\r\n danger: { \r\n class: 'bg-red-500 text-white border-red-600',\r\n },\r\n}\r\n\r\n/**\r\n * size -> class 매핑\r\n */\r\nconst SIZE_PRESETS: Record<Size, { class: string }> = {\n xs: { \n class: 'text-[10px] px-1.5 py-0.5 max-w-40',\n },\n sm: { \n class: 'text-xs px-2 py-1 max-w-48',\n },\n md: { \n class: 'text-xs px-2.5 py-1 max-w-56',\n },\n lg: { \n class: 'text-sm px-3 py-1.5 max-w-64',\n },\n}\n\r\n// click과 manual 트리거를 위한 상태 관리\r\nconst isOpen = ref(false)\r\n\r\n// 각 트리거 타입별 핸들러\r\nconst handleClick = (event: MouseEvent) => {\r\n console.log('Click handler called, trigger:', props.trigger)\r\n if (props.trigger === 'click') {\r\n console.log('Toggling tooltip, current state:', isOpen.value)\r\n isOpen.value = !isOpen.value\r\n console.log('New state:', isOpen.value)\r\n } else if (props.trigger === 'focus') {\r\n // focus 트리거에서는 클릭 이벤트 무시\r\n event.preventDefault()\r\n event.stopPropagation()\r\n }\r\n}\r\n\r\n// delay를 위한 타이머 관리\r\nlet hoverTimer: number | null = null\r\n\r\nconst handleMouseEnter = () => {\r\n if (props.trigger === 'hover') {\r\n // 기존 타이머가 있으면 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n // delay 적용\r\n hoverTimer = setTimeout(() => {\r\n isOpen.value = true\r\n }, props.delay)\r\n }\r\n}\r\n\r\nconst handleMouseLeave = () => {\r\n if (props.trigger === 'hover') {\r\n // 타이머 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n hoverTimer = null\r\n }\r\n isOpen.value = false\r\n }\r\n}\r\n\r\nconst handleFocus = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 트리거 타입에 따른 Tooltip 설정 계산\r\nconst tooltipConfig = computed(() => {\r\n const config: any = {\r\n disabled: props.disabled,\r\n }\r\n \r\n // 모든 트리거 타입에 대해 수동 제어\r\n config.open = isOpen.value\r\n \r\n return config\r\n})\r\n\r\n// 외부 클릭 감지를 위한 핸들러\r\nconst handleOutsideClick = (event: Event) => {\r\n if (props.trigger === 'hover' && isOpen.value) {\r\n const target = event.target as HTMLElement\r\n const tooltipElement = document.querySelector('[data-tooltip-trigger]')\r\n if (tooltipElement && !tooltipElement.contains(target)) {\r\n isOpen.value = false\r\n }\r\n }\r\n}\r\n\r\n// manual 트리거를 위한 메서드들\r\nconst showTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst hideTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 외부에서 사용할 수 있도록 expose\r\ndefineExpose({\r\n showTooltip,\r\n hideTooltip,\r\n})\r\n\r\n// 외부 클릭 감지를 위한 이벤트 리스너 등록/해제\r\nonMounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.addEventListener('click', handleOutsideClick)\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.removeEventListener('click', handleOutsideClick)\r\n }\r\n \r\n // 타이머 정리\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n})\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype과 size 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const stylePreset = STYLE_PRESETS[props.styletype!]\r\n const sizePreset = SIZE_PRESETS[props.size!]\r\n const finalClass = [stylePreset.class, sizePreset.class, props.class].filter(Boolean).join(' ')\r\n \r\n // maxWidth 스타일 처리\r\n const maxWidthStyle = typeof props.maxWidth === 'number' \r\n ? `${props.maxWidth}px` \r\n : props.maxWidth\r\n \r\n return {\r\n side: props.side,\r\n align: props.align,\r\n class: finalClass,\r\n style: {\r\n maxWidth: maxWidthStyle,\r\n },\r\n }\r\n})\r\n</script>\r\n\r\n<template>\r\n <TooltipProvider :delayDuration=\"props.delay\">\r\n <Tooltip v-bind=\"tooltipConfig\">\r\n <TooltipTrigger \r\n as-child\r\n :data-tooltip-trigger=\"true\"\r\n @click=\"handleClick\"\r\n @mouseenter=\"handleMouseEnter\"\r\n @mouseleave=\"handleMouseLeave\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n >\r\n <slot name=\"trigger\" />\r\n </TooltipTrigger>\r\n <TooltipContent v-bind=\"mapped\">\r\n {{ props.content }}\r\n </TooltipContent>\r\n </Tooltip>\r\n </TooltipProvider>\r\n</template>\r\n"],"names":["props","__props","STYLE_PRESETS","SIZE_PRESETS","isOpen","ref","handleClick","event","hoverTimer","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","tooltipConfig","computed","config","handleOutsideClick","target","tooltipElement","__expose","onMounted","onUnmounted","mapped","stylePreset","sizePreset","finalClass","maxWidthStyle","_createBlock","TooltipProvider","_createVNode","Tooltip","TooltipTrigger","_renderSlot","_ctx","TooltipContent","_createTextVNode","_toDisplayString"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { defineComponent as S, ref as k, computed as c, onMounted as w, onUnmounted as C, createBlock as P, openBlock as B, withCtx as s, createVNode as i, normalizeProps as u, guardReactiveProps as d, renderSlot as W, createTextVNode as $, toDisplayString as M } from "vue";
1
+ import { defineComponent as E, ref as S, computed as c, onMounted as k, onUnmounted as C, createBlock as P, openBlock as B, withCtx as s, createVNode as i, normalizeProps as u, guardReactiveProps as d, renderSlot as W, createTextVNode as $, toDisplayString as M } from "vue";
2
2
  import z from "../shadcn/Tooltip.vue.js";
3
3
  import D from "../shadcn/TooltipContent.vue.js";
4
4
  import L from "../shadcn/TooltipProvider.vue.js";
5
5
  import N from "../shadcn/TooltipTrigger.vue.js";
6
- const J = /* @__PURE__ */ S({
6
+ const J = /* @__PURE__ */ E({
7
7
  __name: "JTooltip",
8
8
  props: {
9
9
  content: {},
@@ -11,7 +11,7 @@ const J = /* @__PURE__ */ S({
11
11
  align: { default: "center" },
12
12
  class: {},
13
13
  styletype: { default: "default" },
14
- size: { default: "md" },
14
+ size: { default: "sm" },
15
15
  disabled: { type: Boolean, default: !1 },
16
16
  delay: { default: 200 },
17
17
  maxWidth: { default: "200px" },
@@ -33,24 +33,27 @@ const J = /* @__PURE__ */ S({
33
33
  class: "bg-red-500 text-white border-red-600"
34
34
  }
35
35
  }, m = {
36
+ xs: {
37
+ class: "text-[10px] px-1.5 py-0.5 max-w-40"
38
+ },
36
39
  sm: {
37
- class: "text-xs px-2 py-1"
40
+ class: "text-xs px-2 py-1 max-w-48"
38
41
  },
39
42
  md: {
40
- class: "text-sm px-3 py-1.5"
43
+ class: "text-xs px-2.5 py-1 max-w-56"
41
44
  },
42
45
  lg: {
43
- class: "text-base px-4 py-2"
46
+ class: "text-sm px-3 py-1.5 max-w-64"
44
47
  }
45
- }, t = k(!1), h = (o) => {
48
+ }, t = S(!1), x = (o) => {
46
49
  console.log("Click handler called, trigger:", e.trigger), e.trigger === "click" ? (console.log("Toggling tooltip, current state:", t.value), t.value = !t.value, console.log("New state:", t.value)) : e.trigger === "focus" && (o.preventDefault(), o.stopPropagation());
47
50
  };
48
51
  let l = null;
49
- const v = () => {
52
+ const h = () => {
50
53
  e.trigger === "hover" && (l && clearTimeout(l), l = setTimeout(() => {
51
54
  t.value = !0;
52
55
  }, e.delay));
53
- }, x = () => {
56
+ }, v = () => {
54
57
  e.trigger === "hover" && (l && (clearTimeout(l), l = null), t.value = !1);
55
58
  }, y = () => {
56
59
  e.trigger === "focus" && (t.value = !0);
@@ -74,19 +77,19 @@ const J = /* @__PURE__ */ S({
74
77
  hideTooltip: () => {
75
78
  e.trigger === "manual" && (t.value = !1);
76
79
  }
77
- }), w(() => {
80
+ }), k(() => {
78
81
  e.trigger === "hover" && document.addEventListener("click", n);
79
82
  }), C(() => {
80
83
  e.trigger === "hover" && document.removeEventListener("click", n), l && clearTimeout(l);
81
84
  });
82
85
  const T = c(() => {
83
- const o = p[e.styletype], a = m[e.size], r = [o.class, a.class, e.class].filter(Boolean).join(" "), E = typeof e.maxWidth == "number" ? `${e.maxWidth}px` : e.maxWidth;
86
+ const o = p[e.styletype], a = m[e.size], r = [o.class, a.class, e.class].filter(Boolean).join(" "), w = typeof e.maxWidth == "number" ? `${e.maxWidth}px` : e.maxWidth;
84
87
  return {
85
88
  side: e.side,
86
89
  align: e.align,
87
90
  class: r,
88
91
  style: {
89
- maxWidth: E
92
+ maxWidth: w
90
93
  }
91
94
  };
92
95
  });
@@ -99,9 +102,9 @@ const J = /* @__PURE__ */ S({
99
102
  i(N, {
100
103
  "as-child": "",
101
104
  "data-tooltip-trigger": !0,
102
- onClick: h,
103
- onMouseenter: v,
104
- onMouseleave: x,
105
+ onClick: x,
106
+ onMouseenter: h,
107
+ onMouseleave: v,
105
108
  onFocus: y,
106
109
  onBlur: _
107
110
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"JTooltip.vue.js","sources":["../../../../src/components/atoms/JTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, ref, onMounted, onUnmounted } from 'vue'\r\nimport Tooltip from '@/components/shadcn/Tooltip.vue'\r\nimport TooltipContent from '@/components/shadcn/TooltipContent.vue'\r\nimport TooltipProvider from '@/components/shadcn/TooltipProvider.vue'\r\nimport TooltipTrigger from '@/components/shadcn/TooltipTrigger.vue'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'primary' // 강조 스타일 (파랑)\r\n | 'success' // 성공 스타일 (초록)\r\n | 'warning' // 경고 스타일 (주황)\r\n | 'danger' // 위험 스타일 (빨강)\r\n\r\ntype Size = 'sm' | 'md' | 'lg'\r\n\r\ntype Trigger = 'hover' | 'focus' | 'click' | 'manual'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n content?: string\r\n side?: 'top' | 'right' | 'bottom' | 'left'\r\n align?: 'start' | 'center' | 'end'\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n /** 툴팁 크기 */\r\n size?: Size\r\n /** 툴팁 비활성화 */\r\n disabled?: boolean\r\n /** 표시 지연 시간 (ms) */\r\n delay?: number\r\n /** 툴팁 최대 너비 */\r\n maxWidth?: string | number\r\n /** 툴팁 트리거 타입 */\r\n trigger?: Trigger\r\n }>(),\r\n {\r\n side: 'top',\r\n align: 'center',\r\n styletype: 'default',\r\n size: 'md',\r\n disabled: false,\r\n delay: 200,\r\n maxWidth: '200px',\r\n trigger: 'hover',\r\n },\r\n)\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n primary: { \r\n class: 'bg-blue-500 text-white border-blue-600',\r\n },\r\n success: { \r\n class: 'bg-green-500 text-white border-green-600',\r\n },\r\n warning: { \r\n class: 'bg-amber-500 text-white border-amber-600',\r\n },\r\n danger: { \r\n class: 'bg-red-500 text-white border-red-600',\r\n },\r\n}\r\n\r\n/**\r\n * size -> class 매핑\r\n */\r\nconst SIZE_PRESETS: Record<Size, { class: string }> = {\r\n sm: { \r\n class: 'text-xs px-2 py-1',\r\n },\r\n md: { \r\n class: 'text-sm px-3 py-1.5',\r\n },\r\n lg: { \r\n class: 'text-base px-4 py-2',\r\n },\r\n}\r\n\r\n// click과 manual 트리거를 위한 상태 관리\r\nconst isOpen = ref(false)\r\n\r\n// 각 트리거 타입별 핸들러\r\nconst handleClick = (event: MouseEvent) => {\r\n console.log('Click handler called, trigger:', props.trigger)\r\n if (props.trigger === 'click') {\r\n console.log('Toggling tooltip, current state:', isOpen.value)\r\n isOpen.value = !isOpen.value\r\n console.log('New state:', isOpen.value)\r\n } else if (props.trigger === 'focus') {\r\n // focus 트리거에서는 클릭 이벤트 무시\r\n event.preventDefault()\r\n event.stopPropagation()\r\n }\r\n}\r\n\r\n// delay를 위한 타이머 관리\r\nlet hoverTimer: number | null = null\r\n\r\nconst handleMouseEnter = () => {\r\n if (props.trigger === 'hover') {\r\n // 기존 타이머가 있으면 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n // delay 적용\r\n hoverTimer = setTimeout(() => {\r\n isOpen.value = true\r\n }, props.delay)\r\n }\r\n}\r\n\r\nconst handleMouseLeave = () => {\r\n if (props.trigger === 'hover') {\r\n // 타이머 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n hoverTimer = null\r\n }\r\n isOpen.value = false\r\n }\r\n}\r\n\r\nconst handleFocus = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 트리거 타입에 따른 Tooltip 설정 계산\r\nconst tooltipConfig = computed(() => {\r\n const config: any = {\r\n disabled: props.disabled,\r\n }\r\n \r\n // 모든 트리거 타입에 대해 수동 제어\r\n config.open = isOpen.value\r\n \r\n return config\r\n})\r\n\r\n// 외부 클릭 감지를 위한 핸들러\r\nconst handleOutsideClick = (event: Event) => {\r\n if (props.trigger === 'hover' && isOpen.value) {\r\n const target = event.target as HTMLElement\r\n const tooltipElement = document.querySelector('[data-tooltip-trigger]')\r\n if (tooltipElement && !tooltipElement.contains(target)) {\r\n isOpen.value = false\r\n }\r\n }\r\n}\r\n\r\n// manual 트리거를 위한 메서드들\r\nconst showTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst hideTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 외부에서 사용할 수 있도록 expose\r\ndefineExpose({\r\n showTooltip,\r\n hideTooltip,\r\n})\r\n\r\n// 외부 클릭 감지를 위한 이벤트 리스너 등록/해제\r\nonMounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.addEventListener('click', handleOutsideClick)\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.removeEventListener('click', handleOutsideClick)\r\n }\r\n \r\n // 타이머 정리\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n})\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype과 size 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const stylePreset = STYLE_PRESETS[props.styletype!]\r\n const sizePreset = SIZE_PRESETS[props.size!]\r\n const finalClass = [stylePreset.class, sizePreset.class, props.class].filter(Boolean).join(' ')\r\n \r\n // maxWidth 스타일 처리\r\n const maxWidthStyle = typeof props.maxWidth === 'number' \r\n ? `${props.maxWidth}px` \r\n : props.maxWidth\r\n \r\n return {\r\n side: props.side,\r\n align: props.align,\r\n class: finalClass,\r\n style: {\r\n maxWidth: maxWidthStyle,\r\n },\r\n }\r\n})\r\n</script>\r\n\r\n<template>\r\n <TooltipProvider :delayDuration=\"props.delay\">\r\n <Tooltip v-bind=\"tooltipConfig\">\r\n <TooltipTrigger \r\n as-child\r\n :data-tooltip-trigger=\"true\"\r\n @click=\"handleClick\"\r\n @mouseenter=\"handleMouseEnter\"\r\n @mouseleave=\"handleMouseLeave\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n >\r\n <slot name=\"trigger\" />\r\n </TooltipTrigger>\r\n <TooltipContent v-bind=\"mapped\">\r\n {{ props.content }}\r\n </TooltipContent>\r\n </Tooltip>\r\n </TooltipProvider>\r\n</template>\r\n"],"names":["props","__props","STYLE_PRESETS","SIZE_PRESETS","isOpen","ref","handleClick","event","hoverTimer","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","tooltipConfig","computed","config","handleOutsideClick","target","tooltipElement","__expose","onMounted","onUnmounted","mapped","stylePreset","sizePreset","finalClass","maxWidthStyle","_createBlock","TooltipProvider","_createVNode","Tooltip","TooltipTrigger","_renderSlot","_ctx","TooltipContent","_createTextVNode","_toDisplayString"],"mappings":"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"}
1
+ {"version":3,"file":"JTooltip.vue.js","sources":["../../../../src/components/atoms/JTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed, ref, onMounted, onUnmounted } from 'vue'\r\nimport Tooltip from '@/components/shadcn/Tooltip.vue'\r\nimport TooltipContent from '@/components/shadcn/TooltipContent.vue'\r\nimport TooltipProvider from '@/components/shadcn/TooltipProvider.vue'\r\nimport TooltipTrigger from '@/components/shadcn/TooltipTrigger.vue'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'primary' // 강조 스타일 (파랑)\r\n | 'success' // 성공 스타일 (초록)\r\n | 'warning' // 경고 스타일 (주황)\r\n | 'danger' // 위험 스타일 (빨강)\r\n\r\ntype Size = 'xs' | 'sm' | 'md' | 'lg'\n\r\ntype Trigger = 'hover' | 'focus' | 'click' | 'manual'\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n content?: string\r\n side?: 'top' | 'right' | 'bottom' | 'left'\r\n align?: 'start' | 'center' | 'end'\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n /** 툴팁 크기 */\r\n size?: Size\r\n /** 툴팁 비활성화 */\r\n disabled?: boolean\r\n /** 표시 지연 시간 (ms) */\r\n delay?: number\r\n /** 툴팁 최대 너비 */\r\n maxWidth?: string | number\r\n /** 툴팁 트리거 타입 */\r\n trigger?: Trigger\r\n }>(),\r\n {\n side: 'top',\n align: 'center',\n styletype: 'default',\n size: 'sm',\n disabled: false,\n delay: 200,\n maxWidth: '200px',\n trigger: 'hover',\r\n },\r\n)\r\n\r\n/**\r\n * styletype -> class 매핑\r\n */\r\nconst STYLE_PRESETS: Record<StyleType, { class: string }> = {\r\n default: { class: '' },\r\n primary: { \r\n class: 'bg-blue-500 text-white border-blue-600',\r\n },\r\n success: { \r\n class: 'bg-green-500 text-white border-green-600',\r\n },\r\n warning: { \r\n class: 'bg-amber-500 text-white border-amber-600',\r\n },\r\n danger: { \r\n class: 'bg-red-500 text-white border-red-600',\r\n },\r\n}\r\n\r\n/**\r\n * size -> class 매핑\r\n */\r\nconst SIZE_PRESETS: Record<Size, { class: string }> = {\n xs: { \n class: 'text-[10px] px-1.5 py-0.5 max-w-40',\n },\n sm: { \n class: 'text-xs px-2 py-1 max-w-48',\n },\n md: { \n class: 'text-xs px-2.5 py-1 max-w-56',\n },\n lg: { \n class: 'text-sm px-3 py-1.5 max-w-64',\n },\n}\n\r\n// click과 manual 트리거를 위한 상태 관리\r\nconst isOpen = ref(false)\r\n\r\n// 각 트리거 타입별 핸들러\r\nconst handleClick = (event: MouseEvent) => {\r\n console.log('Click handler called, trigger:', props.trigger)\r\n if (props.trigger === 'click') {\r\n console.log('Toggling tooltip, current state:', isOpen.value)\r\n isOpen.value = !isOpen.value\r\n console.log('New state:', isOpen.value)\r\n } else if (props.trigger === 'focus') {\r\n // focus 트리거에서는 클릭 이벤트 무시\r\n event.preventDefault()\r\n event.stopPropagation()\r\n }\r\n}\r\n\r\n// delay를 위한 타이머 관리\r\nlet hoverTimer: number | null = null\r\n\r\nconst handleMouseEnter = () => {\r\n if (props.trigger === 'hover') {\r\n // 기존 타이머가 있으면 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n // delay 적용\r\n hoverTimer = setTimeout(() => {\r\n isOpen.value = true\r\n }, props.delay)\r\n }\r\n}\r\n\r\nconst handleMouseLeave = () => {\r\n if (props.trigger === 'hover') {\r\n // 타이머 취소\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n hoverTimer = null\r\n }\r\n isOpen.value = false\r\n }\r\n}\r\n\r\nconst handleFocus = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (props.trigger === 'focus') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 트리거 타입에 따른 Tooltip 설정 계산\r\nconst tooltipConfig = computed(() => {\r\n const config: any = {\r\n disabled: props.disabled,\r\n }\r\n \r\n // 모든 트리거 타입에 대해 수동 제어\r\n config.open = isOpen.value\r\n \r\n return config\r\n})\r\n\r\n// 외부 클릭 감지를 위한 핸들러\r\nconst handleOutsideClick = (event: Event) => {\r\n if (props.trigger === 'hover' && isOpen.value) {\r\n const target = event.target as HTMLElement\r\n const tooltipElement = document.querySelector('[data-tooltip-trigger]')\r\n if (tooltipElement && !tooltipElement.contains(target)) {\r\n isOpen.value = false\r\n }\r\n }\r\n}\r\n\r\n// manual 트리거를 위한 메서드들\r\nconst showTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = true\r\n }\r\n}\r\n\r\nconst hideTooltip = () => {\r\n if (props.trigger === 'manual') {\r\n isOpen.value = false\r\n }\r\n}\r\n\r\n// 외부에서 사용할 수 있도록 expose\r\ndefineExpose({\r\n showTooltip,\r\n hideTooltip,\r\n})\r\n\r\n// 외부 클릭 감지를 위한 이벤트 리스너 등록/해제\r\nonMounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.addEventListener('click', handleOutsideClick)\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n if (props.trigger === 'hover') {\r\n document.removeEventListener('click', handleOutsideClick)\r\n }\r\n \r\n // 타이머 정리\r\n if (hoverTimer) {\r\n clearTimeout(hoverTimer)\r\n }\r\n})\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype과 size 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const stylePreset = STYLE_PRESETS[props.styletype!]\r\n const sizePreset = SIZE_PRESETS[props.size!]\r\n const finalClass = [stylePreset.class, sizePreset.class, props.class].filter(Boolean).join(' ')\r\n \r\n // maxWidth 스타일 처리\r\n const maxWidthStyle = typeof props.maxWidth === 'number' \r\n ? `${props.maxWidth}px` \r\n : props.maxWidth\r\n \r\n return {\r\n side: props.side,\r\n align: props.align,\r\n class: finalClass,\r\n style: {\r\n maxWidth: maxWidthStyle,\r\n },\r\n }\r\n})\r\n</script>\r\n\r\n<template>\r\n <TooltipProvider :delayDuration=\"props.delay\">\r\n <Tooltip v-bind=\"tooltipConfig\">\r\n <TooltipTrigger \r\n as-child\r\n :data-tooltip-trigger=\"true\"\r\n @click=\"handleClick\"\r\n @mouseenter=\"handleMouseEnter\"\r\n @mouseleave=\"handleMouseLeave\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n >\r\n <slot name=\"trigger\" />\r\n </TooltipTrigger>\r\n <TooltipContent v-bind=\"mapped\">\r\n {{ props.content }}\r\n </TooltipContent>\r\n </Tooltip>\r\n </TooltipProvider>\r\n</template>\r\n"],"names":["props","__props","STYLE_PRESETS","SIZE_PRESETS","isOpen","ref","handleClick","event","hoverTimer","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","tooltipConfig","computed","config","handleOutsideClick","target","tooltipElement","__expose","onMounted","onUnmounted","mapped","stylePreset","sizePreset","finalClass","maxWidthStyle","_createBlock","TooltipProvider","_createVNode","Tooltip","TooltipTrigger","_renderSlot","_ctx","TooltipContent","_createTextVNode","_toDisplayString"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),u=require("../molecules/JFormField.vue.cjs");;/* empty css */require("../shadcn/index.cjs");require("@vueuse/core");require("reka-ui");require("clsx");require("tailwind-merge");require("lucide-vue-next");;/* empty css */;/* empty css */;/* empty css */const w=require("../molecules/JCard.vue.cjs"),n=require("../atoms/JButton.vue.cjs");require("@internationalized/date");require("md-editor-v3");;/* empty css */;/* empty css */require("../shadcn/badge-variants.cjs");;/* empty css */require("../shadcn/avatar-variants.cjs");require("dompurify");;/* empty css */const x=require("../atoms/JGrid.vue.cjs"),A=require("../atoms/JSplitter.vue.cjs");require("vue-sonner");const h=require("../molecules/JTitlebar.vue.cjs");;/* empty css */;/* empty css */const z=require("../organisms/JFilterBar.vue.cjs");require("vue-router");;/* empty css */;/* empty css */const B={class:"flex flex-col h-full gap-2 bg-background text-foreground"},Y={class:"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2"},E={class:"h-full overflow-auto bg-background"},U={class:"h-full overflow-y-auto border-l bg-muted/30"},P={class:"grid grid-cols-1 md:grid-cols-2 gap-2 mt-2"},T={class:"grid grid-cols-1 md:grid-cols-2 gap-2 mt-2"},J={class:"grid grid-cols-1 gap-2 mt-2"},R={class:"flex justify-end gap-2"},S=e.defineComponent({__name:"ExampleCrudPage",setup(G,{expose:c}){const d=e.ref(!1),o=e.ref({isActive:"",keyword:""}),f={isActive:{label:"활성여부",displayValue:r=>r==="Y"?"Y:활성":r==="N"?"N:비활성":""},keyword:{label:"검색어"}},m=[{value:"Y",label:"Y:활성"},{value:"N",label:"N:비활성"}],v=[{value:"A",label:"A등급"},{value:"B",label:"B등급"},{value:"C",label:"C등급"}],s=e.ref(),p=e.ref([{code:"C001",name:"제이솔루션",category:"A",isActive:"Y",remark:"주력 고객사"},{code:"C002",name:"ABC물류",category:"B",isActive:"Y",remark:""},{code:"C003",name:"XYZ유통",category:"A",isActive:"N",remark:"비활성"},{code:"C004",name:"대한물류",category:"B",isActive:"Y",remark:""},{code:"C005",name:"글로벌이커머스",category:"A",isActive:"Y",remark:"신규 고객사"}]),g=e.ref([{field:"code",headerName:"코드",width:120,enableValue:!0},{field:"name",headerName:"이름",width:200,enableValue:!0},{field:"category",headerName:"분류",width:100,enableRowGroup:!0,enablePivot:!0},{field:"isActive",headerName:"활성",width:100,cellRenderer:r=>r.value==="Y"?"✓":"",enableRowGroup:!0,enablePivot:!0},{field:"remark",headerName:"비고",flex:1,enableValue:!0}]),V=[{icon:"pencil",label:"수정",tooltip:"편집",onClick:r=>{i.value=!1,t.value={code:r.code,name:r.name,category:r.category,isActive:r.isActive,remark:r.remark}}},{icon:"trash2",label:"삭제",tooltip:"삭제",styletype:"danger",onClick:r=>{confirm(`${r.name}을(를) 삭제하시겠습니까?`)&&(console.log("삭제:",r.code),alert(`삭제되었습니다: ${r.name}`))}}],i=e.ref(!1),t=e.ref({code:"",name:"",category:"",isActive:"Y",remark:""});function y(r){i.value=!1;const l=r.data;t.value={code:l.code,name:l.name,category:l.category,isActive:l.isActive,remark:l.remark}}function _(){i.value=!0,t.value={code:"",name:"",category:"",isActive:"Y",remark:""}}function b(){console.log("저장:",t.value),alert(`저장되었습니다: ${t.value.name}`)}function N(){confirm(`${t.value.name}을(를) 삭제하시겠습니까?`)&&(console.log("삭제:",t.value.code),alert(`삭제되었습니다: ${t.value.name}`))}function k(){o.value={isActive:"",keyword:""},console.log("필터 초기화")}function q(){console.log("조회 조건:",o.value)}function C(){alert("고객사 관리 페이지 도움말")}return c({gridRef:s}),(r,l)=>(e.openBlock(),e.createElementBlock("div",B,[e.createVNode(e.unref(h.default),{icon:"building",title:"고객사 관리",description:"고객사 정보를 조회하고 관리합니다",showHelp:!0,onHelp:C}),e.createVNode(e.unref(z.default),{collapsed:d.value,"onUpdate:collapsed":l[2]||(l[2]=a=>d.value=a),filterValues:o.value,"onUpdate:filterValues":l[3]||(l[3]=a=>o.value=a),filterDisplay:f,collapsible:!0,title:"고객사 목록"},{actions:e.withCtx(()=>[e.createVNode(e.unref(n.default),{size:"sm",variant:"outline",onClick:k},{default:e.withCtx(()=>[...l[9]||(l[9]=[e.createTextVNode("초기화",-1)])]),_:1}),e.createVNode(e.unref(n.default),{size:"sm",styletype:"primary",onClick:q},{default:e.withCtx(()=>[...l[10]||(l[10]=[e.createTextVNode("조회",-1)])]),_:1}),e.createVNode(e.unref(n.default),{size:"sm",styletype:"primary",onClick:_},{default:e.withCtx(()=>[...l[11]||(l[11]=[e.createTextVNode("신규",-1)])]),_:1})]),filters:e.withCtx(()=>[e.createElementVNode("div",Y,[e.createVNode(e.unref(u.default),{type:"combo",label:"활성여부",modelValue:o.value.isActive,"onUpdate:modelValue":l[0]||(l[0]=a=>o.value.isActive=a),options:m,orientation:"horizontal",labelWidth:"30%"},null,8,["modelValue"]),e.createVNode(e.unref(u.default),{type:"input",label:"검색어",modelValue:o.value.keyword,"onUpdate:modelValue":l[1]||(l[1]=a=>o.value.keyword=a),orientation:"horizontal",labelWidth:"30%"},null,8,["modelValue"])])]),_:1},8,["collapsed","filterValues"]),e.createVNode(e.unref(A.default),{direction:"horizontal","default-size":60,"min-size":30,"second-min-size":20,"second-max-size":60,gap:2,class:"flex-1"},{left:e.withCtx(()=>[e.createElementVNode("div",E,[e.createVNode(e.unref(x.default),{ref_key:"gridRef",ref:s,columnDefs:g.value,rowData:p.value,"action-buttons":V,enableGrouping:!0,enablePivot:!0,enableColumnsToolPanel:!0,rowGroupPanelShow:"always",pivotPanelShow:"always",groupDefaultExpanded:1,compactFooter:!0,onRowClicked:y},null,8,["columnDefs","rowData"])])]),right:e.withCtx(()=>[e.createElementVNode("div",U,[e.createVNode(e.unref(w.default),{class:"h-full",title:i.value?"신규 등록":"상세 정보"},{footer:e.withCtx(()=>[e.createElementVNode("div",R,[e.createVNode(e.unref(n.default),{styletype:"primary",size:"sm",onClick:b},{default:e.withCtx(()=>[...l[12]||(l[12]=[e.createTextVNode("저장",-1)])]),_:1}),i.value?e.createCommentVNode("",!0):(e.openBlock(),e.createBlock(e.unref(n.default),{key:0,variant:"outline",size:"sm",onClick:N},{default:e.withCtx(()=>[...l[13]||(l[13]=[e.createTextVNode("삭제",-1)])]),_:1}))])]),default:e.withCtx(()=>[e.createElementVNode("div",P,[e.createVNode(e.unref(u.default),{type:"input",label:"코드",modelValue:t.value.code,"onUpdate:modelValue":l[4]||(l[4]=a=>t.value.code=a),readonly:!i.value,placeholder:"고객사 코드"},null,8,["modelValue","readonly"]),e.createVNode(e.unref(u.default),{type:"input",label:"이름",modelValue:t.value.name,"onUpdate:modelValue":l[5]||(l[5]=a=>t.value.name=a),placeholder:"고객사 이름"},null,8,["modelValue"])]),e.createElementVNode("div",T,[e.createVNode(e.unref(u.default),{type:"combo",label:"분류",modelValue:t.value.category,"onUpdate:modelValue":l[6]||(l[6]=a=>t.value.category=a),options:v},null,8,["modelValue"]),e.createVNode(e.unref(u.default),{type:"checkbox",label:"활성여부",modelValue:t.value.isActive,"onUpdate:modelValue":l[7]||(l[7]=a=>t.value.isActive=a),inlineLabel:"활성"},null,8,["modelValue"])]),e.createElementVNode("div",J,[e.createVNode(e.unref(u.default),{type:"textarea",label:"비고",modelValue:t.value.remark,"onUpdate:modelValue":l[8]||(l[8]=a=>t.value.remark=a),placeholder:"비고"},null,8,["modelValue"])])]),_:1},8,["title"])])]),_:1})]))}});exports.default=S;
2
+ //# sourceMappingURL=ExampleCrudPage.vue.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExampleCrudPage.vue.cjs","sources":["../../../../src/components/examples/ExampleCrudPage.vue"],"sourcesContent":["<template>\n <div class=\"flex flex-col h-full gap-2 bg-background text-foreground\">\n <!-- ==================== 타이틀바 ==================== -->\n <JTitlebar \n icon=\"building\" \n title=\"고객사 관리\" \n description=\"고객사 정보를 조회하고 관리합니다\"\n :showHelp=\"true\" \n @help=\"onHelp\" \n />\n\n <!-- ==================== 필터바 ==================== -->\n <JFilterBar\n v-model:collapsed=\"filterCollapsed\"\n v-model:filterValues=\"filterValues\"\n :filterDisplay=\"filterDisplay\"\n :collapsible=\"true\"\n title=\"고객사 목록\"\n >\n <!-- 액션 버튼 -->\n <template #actions>\n <JButton size=\"sm\" variant=\"outline\" @click=\"onReset\">초기화</JButton>\n <JButton size=\"sm\" styletype=\"primary\" @click=\"onSearch\">조회</JButton>\n <JButton size=\"sm\" styletype=\"primary\" @click=\"onNew\">신규</JButton>\n </template>\n\n <!-- 필터 필드 - 다중 열 배치 -->\n <template #filters>\n <div class=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2\">\n <JFormField\n type=\"combo\"\n label=\"활성여부\"\n v-model=\"filterValues.isActive\"\n :options=\"activeOptions\"\n orientation=\"horizontal\"\n labelWidth=\"30%\"\n />\n <JFormField type=\"input\" label=\"검색어\" v-model=\"filterValues.keyword\"\n orientation=\"horizontal\"\n labelWidth=\"30%\" />\n </div>\n </template>\n </JFilterBar>\n\n <!-- ==================== 그리드 + 상세 영역 (Resizable) ==================== -->\n <JSplitter\n direction=\"horizontal\"\n :default-size=\"60\"\n :min-size=\"30\"\n :second-min-size=\"20\"\n :second-max-size=\"60\"\n :gap=\"2\"\n class=\"flex-1\"\n >\n <!-- 좌측: 그리드 -->\n <template #left>\n <div class=\"h-full overflow-auto bg-background\">\n <JGrid\n ref=\"gridRef\"\n :columnDefs=\"columnDefs\"\n :rowData=\"rowData\"\n :action-buttons=\"actionButtons\"\n :enableGrouping=\"true\"\n :enablePivot=\"true\"\n :enableColumnsToolPanel=\"true\"\n rowGroupPanelShow=\"always\"\n pivotPanelShow=\"always\"\n :groupDefaultExpanded=\"1\"\n :compactFooter=\"true\"\n @row-clicked=\"onRowClicked\"\n />\n </div>\n </template>\n\n <!-- 우측: 상세 영역 -->\n <template #right>\n <div class=\"h-full overflow-y-auto border-l bg-muted/30\">\n <JCard class=\"h-full\" :title=\"isNew ? '신규 등록' : '상세 정보'\">\n\n <!-- 2열 그리드: 코드, 이름 -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-2 mt-2\">\n <JFormField\n type=\"input\"\n label=\"코드\"\n v-model=\"detail.code\"\n :readonly=\"!isNew\"\n placeholder=\"고객사 코드\"\n />\n <JFormField\n type=\"input\"\n label=\"이름\"\n v-model=\"detail.name\"\n placeholder=\"고객사 이름\"\n />\n </div>\n\n <!-- 2열 그리드: 분류, 활성여부 -->\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-2 mt-2\">\n <JFormField\n type=\"combo\"\n label=\"분류\"\n v-model=\"detail.category\"\n :options=\"categoryOptions\"\n />\n <JFormField\n type=\"checkbox\"\n label=\"활성여부\"\n v-model=\"detail.isActive\"\n inlineLabel=\"활성\"\n />\n </div>\n <div class=\"grid grid-cols-1 gap-2 mt-2\">\n <!-- 전체 너비: 비고 -->\n <JFormField type=\"textarea\" label=\"비고\" v-model=\"detail.remark\" placeholder=\"비고\" />\n\n </div>\n\n \n <!-- 액션 버튼 -->\n <template #footer>\n <div class=\"flex justify-end gap-2\">\n <JButton styletype=\"primary\" size=\"sm\" @click=\"onSave\">저장</JButton>\n <JButton variant=\"outline\" size=\"sm\" @click=\"onDelete\" v-if=\"!isNew\">삭제</JButton>\n </div>\n </template>\n </JCard>\n </div>\n </template>\n </JSplitter>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport { JTitlebar, JCard } from '@/components/molecules'\nimport { JFilterBar } from '@/components/organisms'\nimport { JGrid, JButton, JSplitter, type ActionButton } from '@/components/atoms'\nimport { JFormField } from '@/components/molecules'\n\n// ==================== 필터 상태 ====================\nconst filterCollapsed = ref(false)\n\n// 필터 값 (v-model:filterValues)\nconst filterValues = ref({\n isActive: '',\n keyword: '',\n})\n\n// 필터 표시 설정 (배지에 표시될 라벨 및 값 변환 함수)\nconst filterDisplay = {\n isActive: {\n label: '활성여부',\n displayValue: (val: unknown) => {\n if (val === 'Y') return 'Y:활성'\n if (val === 'N') return 'N:비활성'\n return ''\n },\n },\n keyword: {\n label: '검색어',\n },\n}\n\n// ==================== 옵션 데이터 ====================\nconst activeOptions = [\n { value: 'Y', label: 'Y:활성' },\n { value: 'N', label: 'N:비활성' },\n]\n\nconst categoryOptions = [\n { value: 'A', label: 'A등급' },\n { value: 'B', label: 'B등급' },\n { value: 'C', label: 'C등급' },\n]\n\n// ==================== 그리드 설정 ====================\nconst gridRef = ref()\n\n// Mock 데이터 - 실제 백엔드 응답 구조\nconst rowData = ref([\n { code: 'C001', name: '제이솔루션', category: 'A', isActive: 'Y', remark: '주력 고객사' },\n { code: 'C002', name: 'ABC물류', category: 'B', isActive: 'Y', remark: '' },\n { code: 'C003', name: 'XYZ유통', category: 'A', isActive: 'N', remark: '비활성' },\n { code: 'C004', name: '대한물류', category: 'B', isActive: 'Y', remark: '' },\n { code: 'C005', name: '글로벌이커머스', category: 'A', isActive: 'Y', remark: '신규 고객사' },\n])\n\nconst columnDefs = ref([\n { \n field: 'code', \n headerName: '코드', \n width: 120,\n enableValue: true, // 집계 가능 (count)\n },\n { \n field: 'name', \n headerName: '이름', \n width: 200,\n enableValue: true, // 집계 가능 (count)\n },\n { \n field: 'category', \n headerName: '분류', \n width: 100,\n enableRowGroup: true, // Row Group으로 사용 가능\n enablePivot: true, // Pivot Column으로 사용 가능\n },\n {\n field: 'isActive',\n headerName: '활성',\n width: 100,\n cellRenderer: (params: any) => (params.value === 'Y' ? '✓' : ''),\n enableRowGroup: true, // Row Group으로 사용 가능\n enablePivot: true, // Pivot Column으로 사용 가능\n },\n { \n field: 'remark', \n headerName: '비고', \n flex: 1,\n enableValue: true, // 집계 가능 (count)\n },\n])\n\n// 행별 액션 버튼\nconst actionButtons: ActionButton[] = [\n {\n icon: 'pencil',\n label: '수정',\n tooltip: '편집',\n onClick: (rowData: any) => {\n isNew.value = false\n detail.value = {\n code: rowData.code,\n name: rowData.name,\n category: rowData.category,\n isActive: rowData.isActive,\n remark: rowData.remark,\n }\n },\n },\n {\n icon: 'trash2',\n label: '삭제',\n tooltip: '삭제',\n styletype: 'danger',\n onClick: (rowData: any) => {\n if (confirm(`${rowData.name}을(를) 삭제하시겠습니까?`)) {\n console.log('삭제:', rowData.code)\n alert(`삭제되었습니다: ${rowData.name}`)\n }\n },\n },\n]\n\n// ==================== 상세 영역 상태 ====================\nconst isNew = ref(false)\nconst detail = ref({\n code: '',\n name: '',\n category: '',\n isActive: 'Y',\n remark: '',\n})\n\n// ==================== 이벤트 핸들러 ====================\n\n/**\n * 그리드 행 클릭 핸들러\n */\nfunction onRowClicked(event: any) {\n isNew.value = false\n const rowData = event.data\n\n // 선택된 행 데이터를 상세 영역에 바인딩\n detail.value = {\n code: rowData.code,\n name: rowData.name,\n category: rowData.category,\n isActive: rowData.isActive,\n remark: rowData.remark,\n }\n}\n\n/**\n * 신규 버튼 클릭\n */\nfunction onNew() {\n isNew.value = true\n // 상세 영역 초기화\n detail.value = {\n code: '',\n name: '',\n category: '',\n isActive: 'Y',\n remark: '',\n }\n}\n\n/**\n * 저장 버튼 클릭\n */\nfunction onSave() {\n console.log('저장:', detail.value)\n // TODO: 실제 구현 시 API 호출로 대체\n // if (isNew.value) {\n // await api.createCustomer(detail.value)\n // } else {\n // await api.updateCustomer(detail.value.code, detail.value)\n // }\n // 성공 시 그리드 데이터 갱신\n alert(`저장되었습니다: ${detail.value.name}`)\n}\n\n/**\n * 삭제 버튼 클릭\n */\nfunction onDelete() {\n if (confirm(`${detail.value.name}을(를) 삭제하시겠습니까?`)) {\n console.log('삭제:', detail.value.code)\n // TODO: 실제 구현 시 API 호출로 대체\n // await api.deleteCustomer(detail.value.code)\n // 성공 시 그리드에서 해당 행 제거\n alert(`삭제되었습니다: ${detail.value.name}`)\n }\n}\n\n/**\n * 초기화 버튼 클릭\n */\nfunction onReset() {\n filterValues.value = {\n isActive: '',\n keyword: '',\n }\n console.log('필터 초기화')\n}\n\n/**\n * 조회 버튼 클릭\n */\nfunction onSearch() {\n console.log('조회 조건:', filterValues.value)\n // TODO: 실제 구현 시 API 호출로 대체\n // const result = await api.searchCustomers(filterValues.value)\n // rowData.value = result.data\n}\n\n/**\n * 도움말 아이콘 클릭\n */\nfunction onHelp() {\n alert('고객사 관리 페이지 도움말')\n}\n\ndefineExpose({ gridRef })\n</script>\n"],"names":["filterCollapsed","ref","filterValues","filterDisplay","val","activeOptions","categoryOptions","gridRef","rowData","columnDefs","params","actionButtons","isNew","detail","onRowClicked","event","onNew","onSave","onDelete","onReset","onSearch","onHelp","__expose","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","JTitlebar","JFilterBar","$event","JButton","_cache","_createElementVNode","_hoisted_2","JFormField","JSplitter","_hoisted_3","JGrid","_hoisted_4","JCard","_hoisted_8","_createBlock","_hoisted_5","_hoisted_6","_hoisted_7"],"mappings":"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"}
@@ -0,0 +1,358 @@
1
+ import { defineComponent as B, ref as s, createElementBlock as U, openBlock as g, createVNode as i, unref as a, withCtx as r, createElementVNode as u, createTextVNode as c, createBlock as P, createCommentVNode as R } from "vue";
2
+ import d from "../molecules/JFormField.vue.js";
3
+ /* empty css */
4
+ import "../shadcn/index.js";
5
+ import "@vueuse/core";
6
+ import "reka-ui";
7
+ import "clsx";
8
+ import "tailwind-merge";
9
+ import "lucide-vue-next";
10
+ /* empty css */
11
+ /* empty css */
12
+ /* empty css */
13
+ import G from "../molecules/JCard.vue.js";
14
+ import p from "../atoms/JButton.vue.js";
15
+ import "@internationalized/date";
16
+ import "md-editor-v3";
17
+ /* empty css */
18
+ /* empty css */
19
+ import "../shadcn/badge-variants.js";
20
+ /* empty css */
21
+ import "../shadcn/avatar-variants.js";
22
+ import "dompurify";
23
+ /* empty css */
24
+ import D from "../atoms/JGrid.vue.js";
25
+ import E from "../atoms/JSplitter.vue.js";
26
+ import "vue-sonner";
27
+ import S from "../molecules/JTitlebar.vue.js";
28
+ /* empty css */
29
+ /* empty css */
30
+ import H from "../organisms/JFilterBar.vue.js";
31
+ import "vue-router";
32
+ /* empty css */
33
+ /* empty css */
34
+ const O = { class: "flex flex-col h-full gap-2 bg-background text-foreground" }, T = { class: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2" }, W = { class: "h-full overflow-auto bg-background" }, j = { class: "h-full overflow-y-auto border-l bg-muted/30" }, F = { class: "grid grid-cols-1 md:grid-cols-2 gap-2 mt-2" }, J = { class: "grid grid-cols-1 md:grid-cols-2 gap-2 mt-2" }, L = { class: "grid grid-cols-1 gap-2 mt-2" }, X = { class: "flex justify-end gap-2" }, Ye = /* @__PURE__ */ B({
35
+ __name: "ExampleCrudPage",
36
+ setup(Z, { expose: y }) {
37
+ const f = s(!1), n = s({
38
+ isActive: "",
39
+ keyword: ""
40
+ }), b = {
41
+ isActive: {
42
+ label: "활성여부",
43
+ displayValue: (o) => o === "Y" ? "Y:활성" : o === "N" ? "N:비활성" : ""
44
+ },
45
+ keyword: {
46
+ label: "검색어"
47
+ }
48
+ }, k = [
49
+ { value: "Y", label: "Y:활성" },
50
+ { value: "N", label: "N:비활성" }
51
+ ], V = [
52
+ { value: "A", label: "A등급" },
53
+ { value: "B", label: "B등급" },
54
+ { value: "C", label: "C등급" }
55
+ ], v = s(), A = s([
56
+ { code: "C001", name: "제이솔루션", category: "A", isActive: "Y", remark: "주력 고객사" },
57
+ { code: "C002", name: "ABC물류", category: "B", isActive: "Y", remark: "" },
58
+ { code: "C003", name: "XYZ유통", category: "A", isActive: "N", remark: "비활성" },
59
+ { code: "C004", name: "대한물류", category: "B", isActive: "Y", remark: "" },
60
+ { code: "C005", name: "글로벌이커머스", category: "A", isActive: "Y", remark: "신규 고객사" }
61
+ ]), C = s([
62
+ {
63
+ field: "code",
64
+ headerName: "코드",
65
+ width: 120,
66
+ enableValue: !0
67
+ // 집계 가능 (count)
68
+ },
69
+ {
70
+ field: "name",
71
+ headerName: "이름",
72
+ width: 200,
73
+ enableValue: !0
74
+ // 집계 가능 (count)
75
+ },
76
+ {
77
+ field: "category",
78
+ headerName: "분류",
79
+ width: 100,
80
+ enableRowGroup: !0,
81
+ // Row Group으로 사용 가능
82
+ enablePivot: !0
83
+ // Pivot Column으로 사용 가능
84
+ },
85
+ {
86
+ field: "isActive",
87
+ headerName: "활성",
88
+ width: 100,
89
+ cellRenderer: (o) => o.value === "Y" ? "✓" : "",
90
+ enableRowGroup: !0,
91
+ // Row Group으로 사용 가능
92
+ enablePivot: !0
93
+ // Pivot Column으로 사용 가능
94
+ },
95
+ {
96
+ field: "remark",
97
+ headerName: "비고",
98
+ flex: 1,
99
+ enableValue: !0
100
+ // 집계 가능 (count)
101
+ }
102
+ ]), w = [
103
+ {
104
+ icon: "pencil",
105
+ label: "수정",
106
+ tooltip: "편집",
107
+ onClick: (o) => {
108
+ m.value = !1, l.value = {
109
+ code: o.code,
110
+ name: o.name,
111
+ category: o.category,
112
+ isActive: o.isActive,
113
+ remark: o.remark
114
+ };
115
+ }
116
+ },
117
+ {
118
+ icon: "trash2",
119
+ label: "삭제",
120
+ tooltip: "삭제",
121
+ styletype: "danger",
122
+ onClick: (o) => {
123
+ confirm(`${o.name}을(를) 삭제하시겠습니까?`) && (console.log("삭제:", o.code), alert(`삭제되었습니다: ${o.name}`));
124
+ }
125
+ }
126
+ ], m = s(!1), l = s({
127
+ code: "",
128
+ name: "",
129
+ category: "",
130
+ isActive: "Y",
131
+ remark: ""
132
+ });
133
+ function _(o) {
134
+ m.value = !1;
135
+ const e = o.data;
136
+ l.value = {
137
+ code: e.code,
138
+ name: e.name,
139
+ category: e.category,
140
+ isActive: e.isActive,
141
+ remark: e.remark
142
+ };
143
+ }
144
+ function x() {
145
+ m.value = !0, l.value = {
146
+ code: "",
147
+ name: "",
148
+ category: "",
149
+ isActive: "Y",
150
+ remark: ""
151
+ };
152
+ }
153
+ function N() {
154
+ console.log("저장:", l.value), alert(`저장되었습니다: ${l.value.name}`);
155
+ }
156
+ function z() {
157
+ confirm(`${l.value.name}을(를) 삭제하시겠습니까?`) && (console.log("삭제:", l.value.code), alert(`삭제되었습니다: ${l.value.name}`));
158
+ }
159
+ function Y() {
160
+ n.value = {
161
+ isActive: "",
162
+ keyword: ""
163
+ }, console.log("필터 초기화");
164
+ }
165
+ function $() {
166
+ console.log("조회 조건:", n.value);
167
+ }
168
+ function h() {
169
+ alert("고객사 관리 페이지 도움말");
170
+ }
171
+ return y({ gridRef: v }), (o, e) => (g(), U("div", O, [
172
+ i(a(S), {
173
+ icon: "building",
174
+ title: "고객사 관리",
175
+ description: "고객사 정보를 조회하고 관리합니다",
176
+ showHelp: !0,
177
+ onHelp: h
178
+ }),
179
+ i(a(H), {
180
+ collapsed: f.value,
181
+ "onUpdate:collapsed": e[2] || (e[2] = (t) => f.value = t),
182
+ filterValues: n.value,
183
+ "onUpdate:filterValues": e[3] || (e[3] = (t) => n.value = t),
184
+ filterDisplay: b,
185
+ collapsible: !0,
186
+ title: "고객사 목록"
187
+ }, {
188
+ actions: r(() => [
189
+ i(a(p), {
190
+ size: "sm",
191
+ variant: "outline",
192
+ onClick: Y
193
+ }, {
194
+ default: r(() => [...e[9] || (e[9] = [
195
+ c("초기화", -1)
196
+ ])]),
197
+ _: 1
198
+ }),
199
+ i(a(p), {
200
+ size: "sm",
201
+ styletype: "primary",
202
+ onClick: $
203
+ }, {
204
+ default: r(() => [...e[10] || (e[10] = [
205
+ c("조회", -1)
206
+ ])]),
207
+ _: 1
208
+ }),
209
+ i(a(p), {
210
+ size: "sm",
211
+ styletype: "primary",
212
+ onClick: x
213
+ }, {
214
+ default: r(() => [...e[11] || (e[11] = [
215
+ c("신규", -1)
216
+ ])]),
217
+ _: 1
218
+ })
219
+ ]),
220
+ filters: r(() => [
221
+ u("div", T, [
222
+ i(a(d), {
223
+ type: "combo",
224
+ label: "활성여부",
225
+ modelValue: n.value.isActive,
226
+ "onUpdate:modelValue": e[0] || (e[0] = (t) => n.value.isActive = t),
227
+ options: k,
228
+ orientation: "horizontal",
229
+ labelWidth: "30%"
230
+ }, null, 8, ["modelValue"]),
231
+ i(a(d), {
232
+ type: "input",
233
+ label: "검색어",
234
+ modelValue: n.value.keyword,
235
+ "onUpdate:modelValue": e[1] || (e[1] = (t) => n.value.keyword = t),
236
+ orientation: "horizontal",
237
+ labelWidth: "30%"
238
+ }, null, 8, ["modelValue"])
239
+ ])
240
+ ]),
241
+ _: 1
242
+ }, 8, ["collapsed", "filterValues"]),
243
+ i(a(E), {
244
+ direction: "horizontal",
245
+ "default-size": 60,
246
+ "min-size": 30,
247
+ "second-min-size": 20,
248
+ "second-max-size": 60,
249
+ gap: 2,
250
+ class: "flex-1"
251
+ }, {
252
+ left: r(() => [
253
+ u("div", W, [
254
+ i(a(D), {
255
+ ref_key: "gridRef",
256
+ ref: v,
257
+ columnDefs: C.value,
258
+ rowData: A.value,
259
+ "action-buttons": w,
260
+ enableGrouping: !0,
261
+ enablePivot: !0,
262
+ enableColumnsToolPanel: !0,
263
+ rowGroupPanelShow: "always",
264
+ pivotPanelShow: "always",
265
+ groupDefaultExpanded: 1,
266
+ compactFooter: !0,
267
+ onRowClicked: _
268
+ }, null, 8, ["columnDefs", "rowData"])
269
+ ])
270
+ ]),
271
+ right: r(() => [
272
+ u("div", j, [
273
+ i(a(G), {
274
+ class: "h-full",
275
+ title: m.value ? "신규 등록" : "상세 정보"
276
+ }, {
277
+ footer: r(() => [
278
+ u("div", X, [
279
+ i(a(p), {
280
+ styletype: "primary",
281
+ size: "sm",
282
+ onClick: N
283
+ }, {
284
+ default: r(() => [...e[12] || (e[12] = [
285
+ c("저장", -1)
286
+ ])]),
287
+ _: 1
288
+ }),
289
+ m.value ? R("", !0) : (g(), P(a(p), {
290
+ key: 0,
291
+ variant: "outline",
292
+ size: "sm",
293
+ onClick: z
294
+ }, {
295
+ default: r(() => [...e[13] || (e[13] = [
296
+ c("삭제", -1)
297
+ ])]),
298
+ _: 1
299
+ }))
300
+ ])
301
+ ]),
302
+ default: r(() => [
303
+ u("div", F, [
304
+ i(a(d), {
305
+ type: "input",
306
+ label: "코드",
307
+ modelValue: l.value.code,
308
+ "onUpdate:modelValue": e[4] || (e[4] = (t) => l.value.code = t),
309
+ readonly: !m.value,
310
+ placeholder: "고객사 코드"
311
+ }, null, 8, ["modelValue", "readonly"]),
312
+ i(a(d), {
313
+ type: "input",
314
+ label: "이름",
315
+ modelValue: l.value.name,
316
+ "onUpdate:modelValue": e[5] || (e[5] = (t) => l.value.name = t),
317
+ placeholder: "고객사 이름"
318
+ }, null, 8, ["modelValue"])
319
+ ]),
320
+ u("div", J, [
321
+ i(a(d), {
322
+ type: "combo",
323
+ label: "분류",
324
+ modelValue: l.value.category,
325
+ "onUpdate:modelValue": e[6] || (e[6] = (t) => l.value.category = t),
326
+ options: V
327
+ }, null, 8, ["modelValue"]),
328
+ i(a(d), {
329
+ type: "checkbox",
330
+ label: "활성여부",
331
+ modelValue: l.value.isActive,
332
+ "onUpdate:modelValue": e[7] || (e[7] = (t) => l.value.isActive = t),
333
+ inlineLabel: "활성"
334
+ }, null, 8, ["modelValue"])
335
+ ]),
336
+ u("div", L, [
337
+ i(a(d), {
338
+ type: "textarea",
339
+ label: "비고",
340
+ modelValue: l.value.remark,
341
+ "onUpdate:modelValue": e[8] || (e[8] = (t) => l.value.remark = t),
342
+ placeholder: "비고"
343
+ }, null, 8, ["modelValue"])
344
+ ])
345
+ ]),
346
+ _: 1
347
+ }, 8, ["title"])
348
+ ])
349
+ ]),
350
+ _: 1
351
+ })
352
+ ]));
353
+ }
354
+ });
355
+ export {
356
+ Ye as default
357
+ };
358
+ //# sourceMappingURL=ExampleCrudPage.vue.js.map