{"version":3,"file":"JFormModal.vue.cjs","sources":["../../../../src/components/organisms/JFormModal.vue"],"sourcesContent":["<template>\r\n  <Dialog\r\n    :open=\"open\"\r\n    :class=\"sizeClass\"\r\n    @update:open=\"onOpenChange\"\r\n  >\r\n    <DialogContent>\r\n      <!-- Header -->\r\n      <DialogHeader v-if=\"title\" class=\"bg-muted/50 border-b\">\r\n        <DialogTitle>\r\n          {{ title }}\r\n        </DialogTitle>\r\n      </DialogHeader>\r\n\r\n      <!-- Body -->\r\n      <DialogBody class=\"max-h-[70vh] overflow-y-auto\">\r\n        <div class=\"space-y-4\">\r\n          <!-- Description -->\r\n          <p v-if=\"description\" class=\"text-sm text-muted-foreground\">\r\n            {{ description }}\r\n          </p>\r\n\r\n          <!-- JDynamicForm (schema 없으면 렌더하지 않음 — body 슬롯 전용 모드) -->\r\n          <JDynamicForm\r\n            v-if=\"schema\"\r\n            ref=\"dynamicFormRef\"\r\n            :schema=\"schema\"\r\n            :model-value=\"internalFormValue\"\r\n            @update:model-value=\"handleFormChange\"\r\n            @submit=\"handleFormSubmit\"\r\n            @change=\"handleFieldChange\"\r\n            @error=\"handleFormError\"\r\n          />\r\n\r\n          <!-- 커스텀 컨텐츠 슬롯 -->\r\n          <slot name=\"body\" />\r\n        </div>\r\n      </DialogBody>\r\n\r\n      <!-- Footer -->\r\n      <DialogFooter>\r\n        <!-- 확인/취소 버튼 -->\r\n        <template v-if=\"buttonType === 'OkCancel'\">\r\n          <JButton\r\n            variant=\"outline\"\r\n            @click=\"handleCancel\"\r\n          >\r\n            {{ cancelText }}\r\n          </JButton>\r\n          <JButton\r\n            :variant=\"confirmVariant\"\r\n            :disabled=\"confirmDisabled\"\r\n            @click=\"handleConfirm\"\r\n          >\r\n            {{ confirmText }}\r\n          </JButton>\r\n        </template>\r\n        \r\n        <!-- 확인 버튼만 -->\r\n        <template v-else-if=\"buttonType === 'Ok'\">\r\n          <JButton\r\n            :variant=\"confirmVariant\"\r\n            :disabled=\"confirmDisabled\"\r\n            class=\"w-full\"\r\n            @click=\"handleConfirm\"\r\n          >\r\n            {{ confirmText }}\r\n          </JButton>\r\n        </template>\r\n\r\n        <!-- 커스텀 푸터 슬롯 -->\r\n        <slot name=\"footer\" />\r\n      </DialogFooter>\r\n    </DialogContent>\r\n  </Dialog>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch } from 'vue'\r\nimport {\r\n  Dialog,\r\n  DialogBody,\r\n  DialogContent,\r\n  DialogFooter,\r\n  DialogHeader,\r\n  DialogTitle,\r\n} from '@/components/shadcn'\r\nimport { JButton } from '@/components/atoms'\r\nimport { JDynamicForm } from '@/components/organisms'\r\nimport type { FormSchema } from '@/types/dynamic-form'\r\n\r\nexport interface JFormModalProps {\r\n  // 모달 표시 여부\r\n  open: boolean\r\n  // 헤더\r\n  title?: string\r\n  description?: string\r\n  // 다이나믹 폼 스키마 (선택 — 없으면 body 슬롯 전용 모달로 동작)\r\n  schema?: FormSchema\r\n  // 폼 값\r\n  modelValue?: Record<string, any>\r\n  // 모달 사이즈 (유동적)\r\n  size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full'\r\n  // 버튼 설정\r\n  buttonType?: 'Ok' | 'OkCancel'\r\n  confirmText?: string\r\n  cancelText?: string\r\n  confirmVariant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\r\n  confirmDisabled?: boolean\r\n}\r\n\r\nconst props = withDefaults(defineProps<JFormModalProps>(), {\r\n  open: false,\r\n  size: 'lg',\r\n  buttonType: 'OkCancel',\r\n  confirmText: '확인',\r\n  cancelText: '취소',\r\n  confirmVariant: 'default',\r\n  confirmDisabled: false,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n  'update:open': [value: boolean]\r\n  'update:modelValue': [value: Record<string, any>]\r\n  'confirm': [value: Record<string, any>]\r\n  'cancel': []\r\n  'submit': [value: Record<string, any>]\r\n  'change': [data: { field: string; value: any }]\r\n  'error': [errors: any]\r\n}>()\r\n\r\n// 다이나믹 폼 ref\r\nconst dynamicFormRef = ref<InstanceType<typeof JDynamicForm> | null>(null)\r\n\r\n// 내부 폼 값 관리\r\nconst internalFormValue = ref<Record<string, any>>(props.modelValue || {})\r\n// 확인 버튼 클릭 이후 검증 성공 시점에만 confirm 이벤트를 방출하기 위한 플래그\r\nconst isConfirming = ref<boolean>(false)\r\n\r\n// 사이즈 클래스 계산\r\nconst sizeClass = computed(() => {\r\n  // Dialog.vue에 기본 max-w-lg가 하드코딩되어 있어 !max-w-*로 오버라이드\r\n  const sizeMap: Record<NonNullable<JFormModalProps['size']>, string> = {\r\n    'sm': '!max-w-sm',\r\n    'md': '!max-w-md',\r\n    'lg': '!max-w-2xl',\r\n    'xl': '!max-w-4xl',\r\n    '2xl': '!max-w-6xl',\r\n    'full': '!max-w-[95vw]'\r\n  }\r\n  return sizeMap[props.size]\r\n})\r\n\r\n// props.modelValue 변경 감지\r\nwatch(() => props.modelValue, (newValue) => {\r\n  if (newValue != null) {\r\n    internalFormValue.value = { ...newValue }\r\n  } else {\r\n    internalFormValue.value = {}\r\n  }\r\n}, { deep: true })\r\n\r\n// 폼 변경 핸들러\r\nconst handleFormChange = (value: Record<string, any>) => {\r\n  internalFormValue.value = value\r\n  emit('update:modelValue', value)\r\n}\r\n\r\n// 필드 변경 핸들러\r\nconst handleFieldChange = (data: { field: string; value: any }) => {\r\n  emit('change', data)\r\n}\r\n\r\n// 폼 제출 핸들러\r\nconst handleFormSubmit = (value: Record<string, any>) => {\r\n  emit('submit', value)\r\n  if (isConfirming.value) {\r\n    emit('confirm', value)\r\n    isConfirming.value = false\r\n  }\r\n}\r\n\r\n// 폼 에러 핸들러\r\nconst handleFormError = (errors: any) => {\r\n  emit('error', errors)\r\n  // 검증 실패 시 confirm 방출을 차단\r\n  isConfirming.value = false\r\n}\r\n\r\n// 모달 열기/닫기 핸들러\r\nconst onOpenChange = (value: boolean) => {\r\n  emit('update:open', value)\r\n}\r\n\r\n// 확인 버튼 핸들러\r\nconst handleConfirm = () => {\r\n  // schema 없는 body 슬롯 전용 모드: 폼 검증을 건너뛰고 바로 confirm 방출\r\n  if (!props.schema) {\r\n    emit('confirm', internalFormValue.value)\r\n    return\r\n  }\r\n  // 폼 제출 트리거 (검증 성공 시점에 handleFormSubmit에서 confirm 방출)\r\n  isConfirming.value = true\r\n  if (dynamicFormRef.value) {\r\n    dynamicFormRef.value.submit()\r\n  }\r\n}\r\n\r\n// 취소 버튼 핸들러\r\nconst handleCancel = () => {\r\n  emit('cancel')\r\n  // 폼 리셋\r\n  if (dynamicFormRef.value) {\r\n    dynamicFormRef.value.reset()\r\n  }\r\n}\r\n\r\n// 외부에서 접근 가능한 메서드\r\ndefineExpose({\r\n  reset: () => dynamicFormRef.value?.reset(),\r\n  submit: () => dynamicFormRef.value?.submit(),\r\n  formState: computed(() => dynamicFormRef.value?.formState),\r\n})\r\n</script>\r\n"],"names":["props","__props","emit","__emit","dynamicFormRef","ref","internalFormValue","isConfirming","sizeClass","computed","watch","newValue","handleFormChange","value","handleFieldChange","data","handleFormSubmit","handleFormError","errors","onOpenChange","handleConfirm","handleCancel","__expose","_createBlock","_unref","Dialog","_createVNode","DialogContent","DialogHeader","DialogTitle","DialogBody","_createElementVNode","_hoisted_1","_createElementBlock","_hoisted_2","_toDisplayString","JDynamicForm","_renderSlot","_ctx","DialogFooter","_Fragment","JButton"],"mappings":"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"}