@j-solution/components 1.9.3 → 1.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/assets/jwms-portal-frontend-CJtAlYis.css +1 -0
- package/assets/styles/j-components.css +1 -1
- package/assets/styles/main.css +12 -3
- package/components/atoms/JCombo.vue.cjs +1 -1
- package/components/atoms/JCombo.vue.cjs.map +1 -1
- package/components/atoms/JCombo.vue.js +1 -1
- package/components/atoms/JCombo.vue.js.map +1 -1
- package/components/atoms/JDatepicker.vue.cjs +1 -1
- package/components/atoms/JDatepicker.vue.cjs.map +1 -1
- package/components/atoms/JDatepicker.vue.js +1 -1
- package/components/atoms/JDatepicker.vue.js.map +1 -1
- package/components/atoms/JGrid.vue.cjs +1 -1
- package/components/atoms/JGrid.vue.js +1 -1
- package/components/atoms/JGrid.vue2.cjs +1 -1
- package/components/atoms/JGrid.vue2.cjs.map +1 -1
- package/components/atoms/JGrid.vue2.js +3 -3
- package/components/atoms/JGrid.vue2.js.map +1 -1
- package/components/atoms/JInput.vue.cjs +1 -1
- package/components/atoms/JInput.vue.cjs.map +1 -1
- package/components/atoms/JInput.vue.js +1 -1
- package/components/atoms/JInput.vue.js.map +1 -1
- package/components/atoms/JSearchCombo.vue.cjs +1 -1
- package/components/atoms/JSearchCombo.vue.cjs.map +1 -1
- package/components/atoms/JSearchCombo.vue.js +5 -5
- package/components/atoms/JSearchCombo.vue.js.map +1 -1
- package/components/atoms/JSplitter.vue.cjs +1 -1
- package/components/atoms/JSplitter.vue.js +2 -2
- package/components/atoms/JSplitter.vue2.cjs +1 -1
- package/components/atoms/JSplitter.vue2.cjs.map +1 -1
- package/components/atoms/JSplitter.vue2.js +26 -22
- package/components/atoms/JSplitter.vue2.js.map +1 -1
- package/components/molecules/JFormField.vue.cjs +1 -1
- package/components/molecules/JFormField.vue.js +2 -2
- package/components/molecules/JFormField.vue2.cjs +1 -1
- package/components/molecules/JFormField.vue2.cjs.map +1 -1
- package/components/molecules/JFormField.vue2.js +28 -28
- package/components/molecules/JFormField.vue2.js.map +1 -1
- package/components/molecules/JTabs.vue.cjs +1 -1
- package/components/molecules/JTabs.vue.js +2 -2
- package/components/molecules/JTabs.vue2.cjs +1 -1
- package/components/molecules/JTabs.vue2.cjs.map +1 -1
- package/components/molecules/JTabs.vue2.js +4 -4
- package/components/molecules/JTabs.vue2.js.map +1 -1
- package/components/organisms/JDynamicForm.vue.cjs +1 -1
- package/components/organisms/JDynamicForm.vue.js +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs.map +1 -1
- package/components/organisms/JDynamicForm.vue2.js +35 -35
- package/components/organisms/JDynamicForm.vue2.js.map +1 -1
- package/components/organisms/JFilterBar.vue.cjs +1 -1
- package/components/organisms/JFilterBar.vue.js +1 -1
- package/components/organisms/JFilterBar.vue2.cjs +1 -1
- package/components/organisms/JFilterBar.vue2.cjs.map +1 -1
- package/components/organisms/JFilterBar.vue2.js +2 -2
- package/components/organisms/JFilterBar.vue2.js.map +1 -1
- package/components/organisms/JPageContainer.vue.cjs +1 -1
- package/components/organisms/JPageContainer.vue.cjs.map +1 -1
- package/components/organisms/JPageContainer.vue.js +4 -4
- package/components/organisms/JPageContainer.vue.js.map +1 -1
- package/components/organisms/JSearchPanel.vue.cjs +1 -1
- package/components/organisms/JSearchPanel.vue.js +2 -2
- package/components/organisms/JSearchPanel.vue2.cjs +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
- package/components/organisms/JSearchPanel.vue2.js +3 -3
- package/components/organisms/JSearchPanel.vue2.js.map +1 -1
- package/components/shadcn/Input.vue.cjs +1 -1
- package/components/shadcn/Input.vue.cjs.map +1 -1
- package/components/shadcn/Input.vue.js +1 -1
- package/components/shadcn/Input.vue.js.map +1 -1
- package/components/shadcn/SelectTrigger.vue.cjs +1 -1
- package/components/shadcn/SelectTrigger.vue.cjs.map +1 -1
- package/components/shadcn/SelectTrigger.vue.js +1 -1
- package/components/shadcn/SelectTrigger.vue.js.map +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.cjs +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.cjs.map +1 -1
- package/components/shadcn/resizable/ResizableHandle.vue.js +3 -3
- package/components/shadcn/resizable/ResizableHandle.vue.js.map +1 -1
- package/package.json +1 -1
- package/assets/jwms-portal-frontend-BrNxcNUC.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JGrid.vue2.js","sources":["../../../../src/components/atoms/JGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport { AgGridVue } from 'ag-grid-vue3'\nimport { cn } from '@/lib/utils'\nimport type {\n ColDef,\n GridOptions,\n RowClickedEvent,\n CellClickedEvent,\n SelectionChangedEvent,\n CellValueChangedEvent,\n RowDoubleClickedEvent,\n GridReadyEvent,\n ICellRendererParams,\n} from 'ag-grid-community'\nimport { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community'\n// Enterprise 모듈 import (Grouping, Pivot, Excel Export 등)\nimport { AllEnterpriseModule } from 'ag-grid-enterprise'\n\n// AG Grid 모듈 등록 (Community + Enterprise)\nModuleRegistry.registerModules([AllCommunityModule, AllEnterpriseModule])\n\n// ── 공식 권장: data-ag-theme-mode attribute 기반 다크모드 전환 ─────────────────\n// AG Grid v33 공식 패턴:\n// 1. themeQuartz.withParams({...}, 'light').withParams({...}, 'dark') 로 두 모드 정의\n// 2. data-ag-theme-mode attribute 전환으로 모드 스위칭 (theme 객체 재생성 불필요)\n// 3. CSS --ag-* 변수 오버라이드로 앱 CSS 변수 참조 (getCSSVar 우회 불필요)\nconst jTheme = themeQuartz\n .withParams({\n browserColorScheme: 'light', // 네이티브 폼/스크롤바를 라이트 스타일로\n cellHorizontalPaddingScale: 1,\n columnBorder: true,\n fontSize: 13,\n headerFontWeight: 500,\n headerVerticalPaddingScale: 0.45,\n iconSize: 14,\n rowVerticalPaddingScale: 0.4,\n }, 'light')\n .withParams({\n browserColorScheme: 'dark', // 네이티브 폼/스크롤바를 다크 스타일로\n }, 'dark')\n\n// JLIS는 .dark class 기반 다크모드이므로 MutationObserver로 감지 후 attribute 동기화\nconst isDark = ref(typeof document !== 'undefined' && document.documentElement.classList.contains('dark'))\nconst gridContainerRef = ref<HTMLElement | null>(null)\nlet darkObserver: MutationObserver | null = null\n\n// isDark 변경 → data-ag-theme-mode 동기화 (AG Grid가 내부적으로 반응)\nwatch(isDark, (dark) => {\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', dark ? 'dark' : 'light')\n})\n\nonMounted(() => {\n // 초기 attribute 설정\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', isDark.value ? 'dark' : 'light')\n\n // 이후 변경 감지\n darkObserver = new MutationObserver(() => {\n isDark.value = document.documentElement.classList.contains('dark')\n })\n darkObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n})\n\nonUnmounted(() => {\n darkObserver?.disconnect()\n})\n\n/**\n * Action Button 정의 타입\n */\nexport type ActionButton = {\n /** 버튼 아이콘 이름 (lucide) - label이 없을 때 기본 텍스트 생성에 사용 */\n icon?: string\n /** 버튼 라벨 */\n label?: string\n /** 툴팁 텍스트 */\n tooltip?: string\n /** 버튼 클릭 핸들러 (rowData 전달) */\n onClick: (rowData: any) => void\n /** 버튼 스타일 타입 */\n styletype?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'\n /** 조건부 표시 함수 (rowData를 받아 boolean 반환) */\n show?: (rowData: any) => boolean\n}\n\nconst props = withDefaults(\n defineProps<{\n /** 추가 클래스 (외부 커스터마이징용) */\n class?: string\n /** 그리드에 표시할 데이터 배열 */\n rowData: any[]\n /** 컬럼 정의 배열 */\n columnDefs: ColDef[]\n /** 페이지네이션 활성화 여부 */\n pagination?: boolean\n /** 체크박스 선택 활성화 여부 */\n checkbox?: boolean\n /** 행 번호 표시 여부 (Enterprise) */\n rowNumbers?: boolean\n /** 플로팅 필터 표시 여부 */\n floatingFilters?: boolean\n /** 플로팅 필터 표시 여부 (하위호환 alias) */\n floatingFilter?: boolean\n /** 행 번호 컬럼 너비(px) */\n rowNumberWidth?: number\n /** 행별 액션 버튼 목록 */\n actionButtons?: ActionButton[]\n /** 요약 컬럼 표시 여부 */\n summaryColumn?: boolean\n /** 숨김 컬럼 관리 활성화 여부 */\n hiddenColumn?: boolean\n /** 그룹핑 기능 활성화 여부 (Enterprise) */\n enableGrouping?: boolean\n /** 피벗 기능 활성화 여부 (Enterprise) */\n enablePivot?: boolean\n /** Excel 내보내기 기능 활성화 여부 (Enterprise) */\n enableExcelExport?: boolean\n /** Tree Data 기능 활성화 여부 (Enterprise) */\n enableTreeData?: boolean\n /** Tree Data 계층 경로를 반환하는 함수 */\n getDataPath?: (data: any) => (string | number)[]\n /** Tree Data 그룹 컬럼 정의 */\n autoGroupColumnDef?: ColDef\n /** 선택된 행 데이터 배열 (v-model:selected-rows) */\n selectedRows?: any[]\n /** 컬럼 호버 하이라이트 활성화 여부 */\n columnHover?: boolean\n /** Columns Tool Panel 활성화 여부 (Enterprise) */\n enableColumnsToolPanel?: boolean\n /** Status Bar 활성화 여부 (Enterprise) */\n statusBar?: boolean\n /** 간소화된 Footer 모드 (Status Bar 제거, Pagination만 표시) */\n compactFooter?: boolean\n /** Row Group Panel 표시 여부 ('always' | 'onlyWhenGrouping' | 'never') */\n rowGroupPanelShow?: 'always' | 'onlyWhenGrouping' | 'never'\n /** 그룹 기본 확장 레벨 (-1: 모두 닫힘, 0: 첫 레벨만, 1: 2레벨까지...) */\n groupDefaultExpanded?: number\n /** Pivot Mode Panel 표시 여부 */\n pivotPanelShow?: 'always' | 'onlyWhenPivoting' | 'never'\n /** Pivot Mode 활성화 여부 */\n pivotMode?: boolean\n }>(),\n {\n pagination: true,\n checkbox: false,\n rowNumbers: true,\n floatingFilters: true,\n floatingFilter: undefined,\n rowNumberWidth: 38,\n actionButtons: undefined,\n summaryColumn: false,\n hiddenColumn: false,\n enableGrouping: true,\n enablePivot: false,\n enableExcelExport: false,\n enableTreeData: false,\n getDataPath: undefined,\n autoGroupColumnDef: undefined,\n selectedRows: () => [],\n columnHover: true,\n enableColumnsToolPanel: true,\n statusBar: true,\n compactFooter: false,\n rowGroupPanelShow: 'never',\n groupDefaultExpanded: -1,\n pivotPanelShow: 'never',\n pivotMode: false,\n },\n)\n\nconst emit = defineEmits<{\n /** 행 클릭 이벤트 */\n rowClicked: [event: RowClickedEvent]\n /** 행 더블클릭 이벤트 */\n rowDoubleClicked: [event: RowDoubleClickedEvent]\n /** 셀 클릭 이벤트 */\n cellClicked: [event: CellClickedEvent]\n /** 선택 변경 이벤트 (체크박스 등) */\n selectionChanged: [event: SelectionChangedEvent]\n /** 셀 값 변경 이벤트 */\n cellValueChanged: [event: CellValueChangedEvent]\n /** 그리드 준비 완료 이벤트 */\n gridReady: [event: GridReadyEvent]\n /** 선택된 행 변경 이벤트 (v-model:selected-rows) */\n 'update:selectedRows': [rows: any[]]\n}>()\n\n// ag-Grid 인스턴스 참조\nconst gridApi = ref<any>(null)\nconst gridColumnApi = ref<any>(null)\n\n// Action Buttons Cell Renderer - 함수형으로 DOM 직접 생성\nconst ActionButtonsCellRenderer = (params: ICellRendererParams) => {\n const buttons = props.actionButtons || []\n const rowData = params.data\n \n // 표시할 버튼 필터링\n const visibleButtons = buttons.filter(btn => {\n if (btn.show) {\n return btn.show(rowData)\n }\n return true\n })\n \n if (visibleButtons.length === 0) {\n return ''\n }\n \n // 컨테이너 div 생성\n const container = document.createElement('div')\n container.className = 'flex items-center gap-1'\n \n // 각 버튼 생성\n visibleButtons.forEach((btn) => {\n const button = document.createElement('button')\n button.className = 'px-2 py-1 text-xs border rounded transition-colors'\n \n // styletype에 따른 클래스 추가\n if (btn.styletype === 'danger') {\n button.className += ' bg-red-50 border-red-400 text-red-700 hover:bg-red-100 dark:bg-red-950 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900'\n } else {\n button.className += ' bg-gray-50 border-gray-400 text-gray-700 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700'\n }\n \n // tooltip\n if (btn.tooltip) {\n button.title = btn.tooltip\n }\n \n // 라벨 추가 (텍스트 버튼)\n if (btn.label) {\n button.textContent = btn.label\n } else if (btn.icon) {\n // 라벨이 없으면 기본 텍스트 생성\n if (btn.icon === 'pencil') {\n button.textContent = '수정'\n } else if (btn.icon === 'trash2' || btn.icon === 'trash') {\n button.textContent = '삭제'\n } else if (btn.icon === 'eye') {\n button.textContent = '보기'\n } else if (btn.icon === 'copy') {\n button.textContent = '복사'\n } else if (btn.icon === 'download') {\n button.textContent = '다운로드'\n } else if (btn.icon === 'circleX') {\n button.textContent = '비활성화'\n } else if (btn.icon === 'circleCheckBig') {\n button.textContent = '활성화'\n } else {\n button.textContent = btn.icon\n }\n }\n \n // 클릭 이벤트\n button.addEventListener('click', (e) => {\n e.stopPropagation()\n btn.onClick(rowData)\n })\n \n container.appendChild(button)\n })\n \n return container\n}\n\n// Action Buttons 컬럼 정의\nconst actionButtonsColumn = computed<ColDef | null>(() => {\n if (!props.actionButtons || props.actionButtons.length === 0) {\n return null\n }\n \n return {\n colId: 'actionButtons',\n headerName: '작업',\n field: '_actions',\n width: 120,\n minWidth: 80,\n maxWidth: 200,\n lockPosition: 'left' as const,\n sortable: false,\n filter: false,\n resizable: true,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellRenderer: ActionButtonsCellRenderer,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n }\n})\n\n// checkbox 활성화 및 추가 컬럼 처리\nconst processedColumnDefs = computed(() => {\n const columns: ColDef[] = []\n \n // 1. Checkbox 컬럼 (최우선)\n if (props.checkbox) {\n columns.push({\n colId: 'rowSelection',\n headerName: '',\n // field와 valueGetter 제거 - AG Grid 공식 방식\n width: 50,\n minWidth: 50,\n maxWidth: 50,\n lockPosition: 'left' as const,\n checkboxSelection: true,\n headerCheckboxSelection: true,\n sortable: false,\n filter: false,\n resizable: false,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n })\n }\n \n // 2. Action Buttons 컬럼\n if (actionButtonsColumn.value) {\n columns.push(actionButtonsColumn.value)\n }\n \n // 3. 사용자 정의 컬럼들 (Row Numbers는 AG Grid가 자동으로 추가)\n columns.push(...props.columnDefs)\n \n return columns\n})\n\n// Grid 옵션 설정\nconst gridOptions = computed<GridOptions>(() => {\n const useFloatingFilters = props.floatingFilter ?? props.floatingFilters\n const options: GridOptions = {\n theme: jTheme,\n pagination: props.pagination,\n defaultColDef: {\n filter: true,\n floatingFilter: useFloatingFilters,\n },\n rowSelection: props.checkbox ? 'multiple' : undefined,\n // 체크박스 모드일 때 row 클릭으로 선택이 변경되지 않도록 설정\n // 체크박스만으로 선택을 제어하도록 함\n suppressRowClickSelection: props.checkbox,\n\n // Row Numbers (Enterprise) - AG Grid 표준 방식\n rowNumbers: props.rowNumbers\n ? ({\n minWidth: props.rowNumberWidth,\n width: props.rowNumberWidth,\n } as any)\n : false,\n\n // Column Hover Highlight\n columnHoverHighlight: props.columnHover,\n\n // Enterprise 기능 옵션\n sideBar: props.enableColumnsToolPanel || props.enableGrouping || props.enablePivot ? {\n toolPanels: [\n {\n id: 'columns',\n labelDefault: 'Columns',\n labelKey: 'columns',\n iconKey: 'columns',\n toolPanel: 'agColumnsToolPanel',\n toolPanelParams: {\n suppressRowGroups: !props.enableGrouping,\n suppressValues: !props.enablePivot,\n suppressPivots: !props.enablePivot,\n suppressPivotMode: !props.enablePivot,\n },\n },\n ],\n defaultToolPanel: '', // 초기에는 접힌 상태\n } : undefined,\n\n // Status Bar (Enterprise)\n // compactFooter 모드에서는 Status Bar 비활성화\n statusBar: (props.statusBar && !props.compactFooter) ? {\n statusPanels: [\n { statusPanel: 'agTotalAndFilteredRowCountComponent', align: 'left' as const },\n { statusPanel: 'agSelectedRowCountComponent', align: 'left' as const },\n { statusPanel: 'agAggregationComponent', align: 'right' as const },\n ],\n } : undefined,\n\n // Row Group Panel 설정 (Enterprise) - 그리드 상단에 드래그 영역 표시\n rowGroupPanelShow: props.rowGroupPanelShow !== 'never' ? props.rowGroupPanelShow : undefined,\n\n // Pivot Panel 설정 (Enterprise) - 피벗 모드용 드래그 영역\n pivotPanelShow: props.pivotPanelShow !== 'never' ? props.pivotPanelShow : undefined,\n \n // Pivot Mode 활성화\n pivotMode: props.pivotMode,\n\n // 그룹핑 기본 설정\n groupDefaultExpanded: props.groupDefaultExpanded,\n suppressAggFuncInHeader: false,\n\n // Tree Data 설정 (Enterprise)\n treeData: props.enableTreeData || undefined,\n getDataPath: props.enableTreeData\n ? (props.getDataPath || ((data: any) => data.path || []))\n : undefined,\n autoGroupColumnDef: props.enableTreeData && props.autoGroupColumnDef\n ? props.autoGroupColumnDef\n : undefined,\n }\n\n return options\n})\n\n// Excel 내보내기 함수 (외부에서 사용 가능하도록 expose)\nconst exportToExcel = () => {\n if (gridApi.value && props.enableExcelExport) {\n gridApi.value.exportDataAsExcel({\n fileName: 'grid-export.xlsx',\n })\n }\n}\n\n// 그리드 API를 외부에 노출\ndefineExpose({\n gridApi,\n gridColumnApi,\n exportToExcel,\n})\n\n// Grid ready 이벤트 핸들러\nconst onGridReady = (params: GridReadyEvent) => {\n gridApi.value = params.api\n gridColumnApi.value = params.api // v34에서 columnApi는 deprecated\n emit('gridReady', params)\n}\n\n// 행 클릭 이벤트 핸들러\nconst onRowClicked = (event: RowClickedEvent) => {\n emit('rowClicked', event)\n}\n\n// 행 더블클릭 이벤트 핸들러\nconst onRowDoubleClicked = (event: RowDoubleClickedEvent) => {\n emit('rowDoubleClicked', event)\n}\n\n// 셀 클릭 이벤트 핸들러\nconst onCellClicked = (event: CellClickedEvent) => {\n emit('cellClicked', event)\n}\n\n// 선택 변경 이벤트 핸들러\nconst onSelectionChanged = (event: SelectionChangedEvent) => {\n emit('selectionChanged', event)\n emit('update:selectedRows', event.api.getSelectedRows())\n}\n\n// 셀 값 변경 이벤트 핸들러\nconst onCellValueChanged = (event: CellValueChangedEvent) => {\n emit('cellValueChanged', event)\n}\n\n// columnDefs 변경 감지\nwatch(\n () => props.columnDefs,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('columnDefs', processedColumnDefs.value)\n }\n },\n { deep: true },\n)\n\n// rowData 변경 감지\nwatch(\n () => props.rowData,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('rowData', props.rowData)\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div ref=\"gridContainerRef\" :class=\"cn('ag-grid-container', props.class)\">\n <AgGridVue\n :column-defs=\"processedColumnDefs\"\n :row-data=\"rowData\"\n :grid-options=\"gridOptions\"\n style=\"height: 100%; width: 100%\"\n @grid-ready=\"onGridReady\"\n @row-clicked=\"onRowClicked\"\n @row-double-clicked=\"onRowDoubleClicked\"\n @cell-clicked=\"onCellClicked\"\n @selection-changed=\"onSelectionChanged\"\n @cell-value-changed=\"onCellValueChanged\"\n />\n </div>\n</template>\n\n<style scoped>\n.ag-grid-container {\n width: 100%;\n height: 100%;\n\n /*\n * App CSS 변수 → AG Grid CSS 변수 브릿지\n * CSS 변수는 런타임 해소 → .dark 클래스 전환 시 라이트/다크 자동 대응\n * AG Grid v33 공식 CSS variable 명칭 사용\n */\n --ag-background-color: hsl(var(--background));\n --ag-foreground-color: hsl(var(--foreground));\n --ag-border-color: hsl(var(--border));\n --ag-header-background-color: hsl(var(--muted));\n --ag-header-foreground-color: hsl(var(--foreground));\n --ag-odd-row-background-color: hsl(var(--card));\n --ag-row-hover-color: hsl(var(--accent));\n --ag-selected-row-background-color: hsl(var(--primary) / 0.12);\n --ag-accent-color: hsl(var(--primary));\n}\n\n/* ============================================\n COMPACT FOOTER: Status Bar + Pagination 통합\n ============================================ */\n\n/* Status Bar 높이 줄이기 */\n:deep(.ag-status-bar) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 0.8125rem;\n}\n\n/* Status Bar 컴포넌트들 높이 조정 */\n:deep(.ag-status-bar-left),\n:deep(.ag-status-bar-center),\n:deep(.ag-status-bar-right) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Status Bar 패널들 간격 조정 */\n:deep(.ag-status-panel) {\n padding: 0;\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Pagination Panel 높이 줄이기 */\n:deep(.ag-paging-panel) {\n min-height: 28px !important;\n height: 28px !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n font-size: 0.8125rem;\n}\n\n/* Pagination 컴포넌트들 높이 조정 */\n:deep(.ag-paging-page-size),\n:deep(.ag-paging-row-summary-panel) {\n height: 28px;\n display: flex;\n align-items: center;\n}\n\n/* Page Size Selector 높이 조정 */\n:deep(.ag-paging-page-size .ag-picker-field) {\n height: 24px;\n min-height: 24px;\n}\n\n:deep(.ag-paging-page-size .ag-picker-field-wrapper) {\n height: 24px;\n padding: 0 4px;\n}\n\n/* Pagination 버튼들 높이 조정 */\n:deep(.ag-paging-button) {\n height: 24px;\n width: 24px;\n padding: 2px;\n}\n\n/* Pagination 버튼 래퍼 */\n:deep(.ag-paging-button-wrapper) {\n height: 28px;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Row summary 텍스트 */\n:deep(.ag-paging-row-summary-panel-number) {\n line-height: 28px;\n}\n\n/* ========================================\n 패턴 9: AG-Grid 스타일 향상\n ======================================== */\n\n:deep(.ag-root-wrapper) {\n border: 1px solid hsl(var(--border));\n border-radius: 0.375rem;\n}\n\n/* ── Header ──────────────────────────────────────────────────────────── */\n:deep(.ag-header) {\n border-bottom: 1px solid hsl(var(--border));\n font-weight: 500;\n}\n\n:deep(.ag-header-cell) {\n color: hsl(var(--foreground));\n font-size: 0.75rem;\n padding: 0.25rem 0.5rem;\n}\n\n/* Floating Filter 행 높이 컴팩트화 */\n:deep(.ag-header-row.ag-floating-filter) {\n min-height: 26px !important;\n height: 26px !important;\n}\n\n:deep(.ag-floating-filter-body) {\n min-height: 24px;\n}\n\n:deep(.ag-floating-filter-body input),\n:deep(.ag-floating-filter-body .ag-input-field-input),\n:deep(.ag-floating-filter-body .ag-picker-field-wrapper) {\n height: 22px !important;\n min-height: 22px !important;\n font-size: 0.75rem;\n}\n\n/* ── Rows ────────────────────────────────────────────────────────────── */\n:deep(.ag-row) {\n transition: background-color 0.15s ease, box-shadow 0.15s ease;\n cursor: pointer;\n}\n\n/* 선택된 행: 왼쪽 accent 기둥으로 명확한 시각적 선택 표시 (라이트/다크 모두) */\n:deep(.ag-row-selected) {\n box-shadow: inset 3px 0 0 hsl(var(--primary));\n}\n\n/* ── Cells ───────────────────────────────────────────────────────────── */\n:deep(.ag-cell) {\n line-height: 1.25;\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.5);\n}\n\n:deep(.ag-cell-wrapper) {\n align-items: center;\n}\n\n:deep(.ag-cell-value) {\n display: flex;\n align-items: center;\n min-height: 100%;\n}\n\n/* 행 클릭 시 row number 셀에 보이는 강한 포커스 음영 제거 */\n:deep(.ag-cell.ag-row-number-cell.ag-cell-focus),\n:deep(.ag-cell.ag-row-number-cell:focus-within) {\n box-shadow: none !important;\n outline: none !important;\n}\n\n/* 셀 포커스 */\n:deep(.ag-cell.ag-cell-focus) {\n box-shadow: inset 0 0 0 1px hsl(var(--ring) / 0.5) !important;\n}\n\n/* ── Pagination ──────────────────────────────────────────────────────── */\n:deep(.ag-paging-panel) {\n border-top: 1px solid hsl(var(--border));\n}\n</style>\n"],"names":["ModuleRegistry","AllCommunityModule","AllEnterpriseModule","jTheme","themeQuartz","isDark","ref","gridContainerRef","darkObserver","watch","dark","onMounted","onUnmounted","props","__props","emit","__emit","gridApi","gridColumnApi","ActionButtonsCellRenderer","params","buttons","rowData","visibleButtons","btn","container","button","e","actionButtonsColumn","computed","processedColumnDefs","columns","gridOptions","useFloatingFilters","data","__expose","onGridReady","onRowClicked","event","onRowDoubleClicked","onCellClicked","onSelectionChanged","onCellValueChanged","_createElementBlock","_normalizeClass","_unref","cn","_createVNode","AgGridVue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JGrid.vue2.js","sources":["../../../../src/components/atoms/JGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport { AgGridVue } from 'ag-grid-vue3'\nimport { cn } from '@/lib/utils'\nimport type {\n ColDef,\n GridOptions,\n RowClickedEvent,\n CellClickedEvent,\n SelectionChangedEvent,\n CellValueChangedEvent,\n RowDoubleClickedEvent,\n GridReadyEvent,\n ICellRendererParams,\n} from 'ag-grid-community'\nimport { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community'\n// Enterprise 모듈 import (Grouping, Pivot, Excel Export 등)\nimport { AllEnterpriseModule } from 'ag-grid-enterprise'\n\n// AG Grid 모듈 등록 (Community + Enterprise)\nModuleRegistry.registerModules([AllCommunityModule, AllEnterpriseModule])\n\n// ── 공식 권장: data-ag-theme-mode attribute 기반 다크모드 전환 ─────────────────\n// AG Grid v33 공식 패턴:\n// 1. themeQuartz.withParams({...}, 'light').withParams({...}, 'dark') 로 두 모드 정의\n// 2. data-ag-theme-mode attribute 전환으로 모드 스위칭 (theme 객체 재생성 불필요)\n// 3. CSS --ag-* 변수 오버라이드로 앱 CSS 변수 참조 (getCSSVar 우회 불필요)\nconst jTheme = themeQuartz\n .withParams({\n // 공통 사이즈 (라이트/다크 모두 적용)\n cellHorizontalPaddingScale: 1,\n columnBorder: true,\n fontSize: 13,\n headerFontWeight: 500,\n headerVerticalPaddingScale: 0.45,\n iconSize: 14,\n rowVerticalPaddingScale: 0.4,\n })\n .withParams({\n browserColorScheme: 'light',\n }, 'light')\n .withParams({\n browserColorScheme: 'dark',\n }, 'dark')\n\n// JLIS는 .dark class 기반 다크모드이므로 MutationObserver로 감지 후 attribute 동기화\nconst isDark = ref(typeof document !== 'undefined' && document.documentElement.classList.contains('dark'))\nconst gridContainerRef = ref<HTMLElement | null>(null)\nlet darkObserver: MutationObserver | null = null\n\n// isDark 변경 → data-ag-theme-mode 동기화 (AG Grid가 내부적으로 반응)\nwatch(isDark, (dark) => {\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', dark ? 'dark' : 'light')\n})\n\nonMounted(() => {\n // 초기 attribute 설정\n gridContainerRef.value?.setAttribute('data-ag-theme-mode', isDark.value ? 'dark' : 'light')\n\n // 이후 변경 감지\n darkObserver = new MutationObserver(() => {\n isDark.value = document.documentElement.classList.contains('dark')\n })\n darkObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n})\n\nonUnmounted(() => {\n darkObserver?.disconnect()\n})\n\n/**\n * Action Button 정의 타입\n */\nexport type ActionButton = {\n /** 버튼 아이콘 이름 (lucide) - label이 없을 때 기본 텍스트 생성에 사용 */\n icon?: string\n /** 버튼 라벨 */\n label?: string\n /** 툴팁 텍스트 */\n tooltip?: string\n /** 버튼 클릭 핸들러 (rowData 전달) */\n onClick: (rowData: any) => void\n /** 버튼 스타일 타입 */\n styletype?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger'\n /** 조건부 표시 함수 (rowData를 받아 boolean 반환) */\n show?: (rowData: any) => boolean\n}\n\nconst props = withDefaults(\n defineProps<{\n /** 추가 클래스 (외부 커스터마이징용) */\n class?: string\n /** 그리드에 표시할 데이터 배열 */\n rowData: any[]\n /** 컬럼 정의 배열 */\n columnDefs: ColDef[]\n /** 페이지네이션 활성화 여부 */\n pagination?: boolean\n /** 체크박스 선택 활성화 여부 */\n checkbox?: boolean\n /** 행 번호 표시 여부 (Enterprise) */\n rowNumbers?: boolean\n /** 플로팅 필터 표시 여부 */\n floatingFilters?: boolean\n /** 플로팅 필터 표시 여부 (하위호환 alias) */\n floatingFilter?: boolean\n /** 행 번호 컬럼 너비(px) */\n rowNumberWidth?: number\n /** 행별 액션 버튼 목록 */\n actionButtons?: ActionButton[]\n /** 요약 컬럼 표시 여부 */\n summaryColumn?: boolean\n /** 숨김 컬럼 관리 활성화 여부 */\n hiddenColumn?: boolean\n /** 그룹핑 기능 활성화 여부 (Enterprise) */\n enableGrouping?: boolean\n /** 피벗 기능 활성화 여부 (Enterprise) */\n enablePivot?: boolean\n /** Excel 내보내기 기능 활성화 여부 (Enterprise) */\n enableExcelExport?: boolean\n /** Tree Data 기능 활성화 여부 (Enterprise) */\n enableTreeData?: boolean\n /** Tree Data 계층 경로를 반환하는 함수 */\n getDataPath?: (data: any) => (string | number)[]\n /** Tree Data 그룹 컬럼 정의 */\n autoGroupColumnDef?: ColDef\n /** 선택된 행 데이터 배열 (v-model:selected-rows) */\n selectedRows?: any[]\n /** 컬럼 호버 하이라이트 활성화 여부 */\n columnHover?: boolean\n /** Columns Tool Panel 활성화 여부 (Enterprise) */\n enableColumnsToolPanel?: boolean\n /** Status Bar 활성화 여부 (Enterprise) */\n statusBar?: boolean\n /** 간소화된 Footer 모드 (Status Bar 제거, Pagination만 표시) */\n compactFooter?: boolean\n /** Row Group Panel 표시 여부 ('always' | 'onlyWhenGrouping' | 'never') */\n rowGroupPanelShow?: 'always' | 'onlyWhenGrouping' | 'never'\n /** 그룹 기본 확장 레벨 (-1: 모두 닫힘, 0: 첫 레벨만, 1: 2레벨까지...) */\n groupDefaultExpanded?: number\n /** Pivot Mode Panel 표시 여부 */\n pivotPanelShow?: 'always' | 'onlyWhenPivoting' | 'never'\n /** Pivot Mode 활성화 여부 */\n pivotMode?: boolean\n }>(),\n {\n pagination: true,\n checkbox: false,\n rowNumbers: true,\n floatingFilters: true,\n floatingFilter: undefined,\n rowNumberWidth: 38,\n actionButtons: undefined,\n summaryColumn: false,\n hiddenColumn: false,\n enableGrouping: true,\n enablePivot: false,\n enableExcelExport: false,\n enableTreeData: false,\n getDataPath: undefined,\n autoGroupColumnDef: undefined,\n selectedRows: () => [],\n columnHover: true,\n enableColumnsToolPanel: true,\n statusBar: true,\n compactFooter: false,\n rowGroupPanelShow: 'never',\n groupDefaultExpanded: -1,\n pivotPanelShow: 'never',\n pivotMode: false,\n },\n)\n\nconst emit = defineEmits<{\n /** 행 클릭 이벤트 */\n rowClicked: [event: RowClickedEvent]\n /** 행 더블클릭 이벤트 */\n rowDoubleClicked: [event: RowDoubleClickedEvent]\n /** 셀 클릭 이벤트 */\n cellClicked: [event: CellClickedEvent]\n /** 선택 변경 이벤트 (체크박스 등) */\n selectionChanged: [event: SelectionChangedEvent]\n /** 셀 값 변경 이벤트 */\n cellValueChanged: [event: CellValueChangedEvent]\n /** 그리드 준비 완료 이벤트 */\n gridReady: [event: GridReadyEvent]\n /** 선택된 행 변경 이벤트 (v-model:selected-rows) */\n 'update:selectedRows': [rows: any[]]\n}>()\n\n// ag-Grid 인스턴스 참조\nconst gridApi = ref<any>(null)\nconst gridColumnApi = ref<any>(null)\n\n// Action Buttons Cell Renderer - 함수형으로 DOM 직접 생성\nconst ActionButtonsCellRenderer = (params: ICellRendererParams) => {\n const buttons = props.actionButtons || []\n const rowData = params.data\n \n // 표시할 버튼 필터링\n const visibleButtons = buttons.filter(btn => {\n if (btn.show) {\n return btn.show(rowData)\n }\n return true\n })\n \n if (visibleButtons.length === 0) {\n return ''\n }\n \n // 컨테이너 div 생성\n const container = document.createElement('div')\n container.className = 'flex items-center gap-1'\n \n // 각 버튼 생성\n visibleButtons.forEach((btn) => {\n const button = document.createElement('button')\n button.className = 'px-2 py-1 text-xs border rounded transition-colors'\n \n // styletype에 따른 클래스 추가\n if (btn.styletype === 'danger') {\n button.className += ' bg-red-50 border-red-400 text-red-700 hover:bg-red-100 dark:bg-red-950 dark:border-red-700 dark:text-red-400 dark:hover:bg-red-900'\n } else {\n button.className += ' bg-gray-50 border-gray-400 text-gray-700 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700'\n }\n \n // tooltip\n if (btn.tooltip) {\n button.title = btn.tooltip\n }\n \n // 라벨 추가 (텍스트 버튼)\n if (btn.label) {\n button.textContent = btn.label\n } else if (btn.icon) {\n // 라벨이 없으면 기본 텍스트 생성\n if (btn.icon === 'pencil') {\n button.textContent = '수정'\n } else if (btn.icon === 'trash2' || btn.icon === 'trash') {\n button.textContent = '삭제'\n } else if (btn.icon === 'eye') {\n button.textContent = '보기'\n } else if (btn.icon === 'copy') {\n button.textContent = '복사'\n } else if (btn.icon === 'download') {\n button.textContent = '다운로드'\n } else if (btn.icon === 'circleX') {\n button.textContent = '비활성화'\n } else if (btn.icon === 'circleCheckBig') {\n button.textContent = '활성화'\n } else {\n button.textContent = btn.icon\n }\n }\n \n // 클릭 이벤트\n button.addEventListener('click', (e) => {\n e.stopPropagation()\n btn.onClick(rowData)\n })\n \n container.appendChild(button)\n })\n \n return container\n}\n\n// Action Buttons 컬럼 정의\nconst actionButtonsColumn = computed<ColDef | null>(() => {\n if (!props.actionButtons || props.actionButtons.length === 0) {\n return null\n }\n \n return {\n colId: 'actionButtons',\n headerName: '작업',\n field: '_actions',\n width: 120,\n minWidth: 80,\n maxWidth: 200,\n lockPosition: 'left' as const,\n sortable: false,\n filter: false,\n resizable: true,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellRenderer: ActionButtonsCellRenderer,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n }\n})\n\n// checkbox 활성화 및 추가 컬럼 처리\nconst processedColumnDefs = computed(() => {\n const columns: ColDef[] = []\n \n // 1. Checkbox 컬럼 (최우선)\n if (props.checkbox) {\n columns.push({\n colId: 'rowSelection',\n headerName: '',\n // field와 valueGetter 제거 - AG Grid 공식 방식\n width: 50,\n minWidth: 50,\n maxWidth: 50,\n lockPosition: 'left' as const,\n checkboxSelection: true,\n headerCheckboxSelection: true,\n sortable: false,\n filter: false,\n resizable: false,\n suppressNavigable: true,\n suppressHeaderMenuButton: true,\n cellStyle: { display: 'flex', justifyContent: 'center', alignItems: 'center' },\n })\n }\n \n // 2. Action Buttons 컬럼\n if (actionButtonsColumn.value) {\n columns.push(actionButtonsColumn.value)\n }\n \n // 3. 사용자 정의 컬럼들 (Row Numbers는 AG Grid가 자동으로 추가)\n columns.push(...props.columnDefs)\n \n return columns\n})\n\n// Grid 옵션 설정\nconst gridOptions = computed<GridOptions>(() => {\n const useFloatingFilters = props.floatingFilter ?? props.floatingFilters\n const options: GridOptions = {\n theme: jTheme,\n pagination: props.pagination,\n defaultColDef: {\n filter: true,\n floatingFilter: useFloatingFilters,\n },\n rowSelection: props.checkbox ? 'multiple' : undefined,\n // 체크박스 모드일 때 row 클릭으로 선택이 변경되지 않도록 설정\n // 체크박스만으로 선택을 제어하도록 함\n suppressRowClickSelection: props.checkbox,\n\n // Row Numbers (Enterprise) - AG Grid 표준 방식\n rowNumbers: props.rowNumbers\n ? ({\n minWidth: props.rowNumberWidth,\n width: props.rowNumberWidth,\n } as any)\n : false,\n\n // Column Hover Highlight\n columnHoverHighlight: props.columnHover,\n\n // Enterprise 기능 옵션\n sideBar: props.enableColumnsToolPanel || props.enableGrouping || props.enablePivot ? {\n toolPanels: [\n {\n id: 'columns',\n labelDefault: 'Columns',\n labelKey: 'columns',\n iconKey: 'columns',\n toolPanel: 'agColumnsToolPanel',\n toolPanelParams: {\n suppressRowGroups: !props.enableGrouping,\n suppressValues: !props.enablePivot,\n suppressPivots: !props.enablePivot,\n suppressPivotMode: !props.enablePivot,\n },\n },\n ],\n defaultToolPanel: '', // 초기에는 접힌 상태\n } : undefined,\n\n // Status Bar (Enterprise)\n // compactFooter 모드에서는 Status Bar 비활성화\n statusBar: (props.statusBar && !props.compactFooter) ? {\n statusPanels: [\n { statusPanel: 'agTotalAndFilteredRowCountComponent', align: 'left' as const },\n { statusPanel: 'agSelectedRowCountComponent', align: 'left' as const },\n { statusPanel: 'agAggregationComponent', align: 'right' as const },\n ],\n } : undefined,\n\n // Row Group Panel 설정 (Enterprise) - 그리드 상단에 드래그 영역 표시\n rowGroupPanelShow: props.rowGroupPanelShow !== 'never' ? props.rowGroupPanelShow : undefined,\n\n // Pivot Panel 설정 (Enterprise) - 피벗 모드용 드래그 영역\n pivotPanelShow: props.pivotPanelShow !== 'never' ? props.pivotPanelShow : undefined,\n \n // Pivot Mode 활성화\n pivotMode: props.pivotMode,\n\n // 그룹핑 기본 설정\n groupDefaultExpanded: props.groupDefaultExpanded,\n suppressAggFuncInHeader: false,\n\n // Tree Data 설정 (Enterprise)\n treeData: props.enableTreeData || undefined,\n getDataPath: props.enableTreeData\n ? (props.getDataPath || ((data: any) => data.path || []))\n : undefined,\n autoGroupColumnDef: props.enableTreeData && props.autoGroupColumnDef\n ? props.autoGroupColumnDef\n : undefined,\n }\n\n return options\n})\n\n// Excel 내보내기 함수 (외부에서 사용 가능하도록 expose)\nconst exportToExcel = () => {\n if (gridApi.value && props.enableExcelExport) {\n gridApi.value.exportDataAsExcel({\n fileName: 'grid-export.xlsx',\n })\n }\n}\n\n// 그리드 API를 외부에 노출\ndefineExpose({\n gridApi,\n gridColumnApi,\n exportToExcel,\n})\n\n// Grid ready 이벤트 핸들러\nconst onGridReady = (params: GridReadyEvent) => {\n gridApi.value = params.api\n gridColumnApi.value = params.api // v34에서 columnApi는 deprecated\n emit('gridReady', params)\n}\n\n// 행 클릭 이벤트 핸들러\nconst onRowClicked = (event: RowClickedEvent) => {\n emit('rowClicked', event)\n}\n\n// 행 더블클릭 이벤트 핸들러\nconst onRowDoubleClicked = (event: RowDoubleClickedEvent) => {\n emit('rowDoubleClicked', event)\n}\n\n// 셀 클릭 이벤트 핸들러\nconst onCellClicked = (event: CellClickedEvent) => {\n emit('cellClicked', event)\n}\n\n// 선택 변경 이벤트 핸들러\nconst onSelectionChanged = (event: SelectionChangedEvent) => {\n emit('selectionChanged', event)\n emit('update:selectedRows', event.api.getSelectedRows())\n}\n\n// 셀 값 변경 이벤트 핸들러\nconst onCellValueChanged = (event: CellValueChangedEvent) => {\n emit('cellValueChanged', event)\n}\n\n// columnDefs 변경 감지\nwatch(\n () => props.columnDefs,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('columnDefs', processedColumnDefs.value)\n }\n },\n { deep: true },\n)\n\n// rowData 변경 감지\nwatch(\n () => props.rowData,\n () => {\n if (gridApi.value) {\n gridApi.value.setGridOption('rowData', props.rowData)\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div ref=\"gridContainerRef\" :class=\"cn('ag-grid-container', props.class)\">\n <AgGridVue\n :column-defs=\"processedColumnDefs\"\n :row-data=\"rowData\"\n :grid-options=\"gridOptions\"\n style=\"height: 100%; width: 100%\"\n @grid-ready=\"onGridReady\"\n @row-clicked=\"onRowClicked\"\n @row-double-clicked=\"onRowDoubleClicked\"\n @cell-clicked=\"onCellClicked\"\n @selection-changed=\"onSelectionChanged\"\n @cell-value-changed=\"onCellValueChanged\"\n />\n </div>\n</template>\n\n<style scoped>\n.ag-grid-container {\n width: 100%;\n height: 100%;\n\n /*\n * App CSS 변수 → AG Grid CSS 변수 브릿지\n * CSS 변수는 런타임 해소 → .dark 클래스 전환 시 라이트/다크 자동 대응\n * AG Grid v33 공식 CSS variable 명칭 사용\n */\n --ag-background-color: hsl(var(--background));\n --ag-foreground-color: hsl(var(--foreground));\n --ag-border-color: hsl(var(--border));\n --ag-header-background-color: hsl(var(--muted));\n --ag-header-foreground-color: hsl(var(--foreground));\n --ag-odd-row-background-color: hsl(var(--card));\n --ag-row-hover-color: hsl(var(--accent));\n --ag-selected-row-background-color: hsl(var(--primary) / 0.12);\n --ag-accent-color: hsl(var(--primary));\n --ag-header-height: var(--j-grid-header-h);\n --ag-row-height: var(--j-grid-row-h);\n}\n\n/* ============================================\n COMPACT FOOTER: Status Bar + Pagination 통합\n ============================================ */\n\n/* Status Bar 높이 줄이기 */\n:deep(.ag-status-bar) {\n min-height: var(--j-grid-footer-h) !important;\n height: var(--j-grid-footer-h) !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n display: flex;\n align-items: center;\n justify-content: space-between;\n font-size: 0.8125rem;\n}\n\n/* Status Bar 컴포넌트들 높이 조정 */\n:deep(.ag-status-bar-left),\n:deep(.ag-status-bar-center),\n:deep(.ag-status-bar-right) {\n height: var(--j-grid-footer-h);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* Status Bar 패널들 간격 조정 */\n:deep(.ag-status-panel) {\n padding: 0;\n height: var(--j-grid-footer-h);\n display: flex;\n align-items: center;\n}\n\n/* Pagination Panel 높이 줄이기 */\n:deep(.ag-paging-panel) {\n min-height: var(--j-grid-footer-h) !important;\n height: var(--j-grid-footer-h) !important;\n padding: 0 12px !important;\n border-top: 1px solid var(--ag-border-color);\n font-size: 0.8125rem;\n}\n\n/* Pagination 컴포넌트들 높이 조정 */\n:deep(.ag-paging-page-size),\n:deep(.ag-paging-row-summary-panel) {\n height: var(--j-grid-footer-h);\n display: flex;\n align-items: center;\n}\n\n/* Page Size Selector 높이 조정 */\n:deep(.ag-paging-page-size .ag-picker-field) {\n height: 24px;\n min-height: 24px;\n}\n\n:deep(.ag-paging-page-size .ag-picker-field-wrapper) {\n height: 24px;\n padding: 0 4px;\n}\n\n/* Pagination 버튼들 높이 조정 */\n:deep(.ag-paging-button) {\n height: 24px;\n width: 24px;\n padding: 2px;\n}\n\n/* Pagination 버튼 래퍼 */\n:deep(.ag-paging-button-wrapper) {\n height: var(--j-grid-footer-h);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Row summary 텍스트 */\n:deep(.ag-paging-row-summary-panel-number) {\n line-height: var(--j-grid-footer-h);\n}\n\n/* ========================================\n 패턴 9: AG-Grid 스타일 향상\n ======================================== */\n\n:deep(.ag-root-wrapper) {\n border: 1px solid hsl(var(--border));\n border-radius: 0.375rem;\n}\n\n/* ── Header ──────────────────────────────────────────────────────────── */\n:deep(.ag-header) {\n border-bottom: 1px solid hsl(var(--border));\n font-weight: 500;\n}\n\n:deep(.ag-header-row:not(.ag-floating-filter)) {\n min-height: var(--j-grid-header-h) !important;\n height: var(--j-grid-header-h) !important;\n}\n\n:deep(.ag-header-cell) {\n color: hsl(var(--foreground));\n font-size: 0.75rem;\n padding: 0 0.5rem;\n display: flex;\n align-items: center;\n}\n\n/* Floating Filter: 헤더보다 밝게 → 입력 영역임을 시각적으로 구분 */\n:deep(.ag-header-row.ag-floating-filter) {\n min-height: var(--j-grid-filter-h) !important;\n height: var(--j-grid-filter-h) !important;\n background-color: hsl(var(--background));\n}\n\n:deep(.ag-floating-filter-body) {\n min-height: var(--j-grid-filter-h);\n}\n\n:deep(.ag-floating-filter-body input),\n:deep(.ag-floating-filter-body .ag-input-field-input),\n:deep(.ag-floating-filter-body .ag-picker-field-wrapper) {\n height: 20px !important;\n min-height: 20px !important;\n font-size: 0.75rem;\n}\n\n/* ── Rows ────────────────────────────────────────────────────────────── */\n:deep(.ag-row) {\n min-height: var(--j-grid-row-h) !important;\n height: var(--j-grid-row-h) !important;\n transition: background-color 0.15s ease, box-shadow 0.15s ease;\n cursor: pointer;\n}\n\n/* 선택된 행: 왼쪽 accent 기둥으로 명확한 시각적 선택 표시 (라이트/다크 모두) */\n:deep(.ag-row-selected) {\n box-shadow: inset 3px 0 0 hsl(var(--primary));\n}\n\n/* ── Cells ───────────────────────────────────────────────────────────── */\n:deep(.ag-cell) {\n line-height: 1.2;\n padding: 0 0.5rem;\n border-bottom: 1px solid hsl(var(--border) / 0.5);\n}\n\n:deep(.ag-cell-wrapper) {\n align-items: center;\n}\n\n:deep(.ag-cell-value) {\n display: flex;\n align-items: center;\n min-height: 100%;\n}\n\n/* 행 클릭 시 row number 셀에 보이는 강한 포커스 음영 제거 */\n:deep(.ag-cell.ag-row-number-cell.ag-cell-focus),\n:deep(.ag-cell.ag-row-number-cell:focus-within) {\n box-shadow: none !important;\n outline: none !important;\n}\n\n/* 셀 포커스 */\n:deep(.ag-cell.ag-cell-focus) {\n box-shadow: inset 0 0 0 1px hsl(var(--ring) / 0.5) !important;\n}\n\n/* 인라인 편집 셀: 내부 여백 확보 → 텍스트가 테두리에 가리지 않도록 */\n:deep(.ag-cell-inline-editing) {\n padding: 0 !important;\n}\n\n:deep(.ag-cell-inline-editing .ag-cell-editor),\n:deep(.ag-cell-inline-editing .ag-input-field),\n:deep(.ag-cell-inline-editing input) {\n height: 100%;\n padding: 0 0.5rem;\n border: 2px solid hsl(var(--primary));\n border-radius: 2px;\n background-color: hsl(var(--background));\n}\n\n/* ── Pagination ──────────────────────────────────────────────────────── */\n:deep(.ag-paging-panel) {\n border-top: 1px solid hsl(var(--border));\n}\n</style>\n"],"names":["ModuleRegistry","AllCommunityModule","AllEnterpriseModule","jTheme","themeQuartz","isDark","ref","gridContainerRef","darkObserver","watch","dark","onMounted","onUnmounted","props","__props","emit","__emit","gridApi","gridColumnApi","ActionButtonsCellRenderer","params","buttons","rowData","visibleButtons","btn","container","button","e","actionButtonsColumn","computed","processedColumnDefs","columns","gridOptions","useFloatingFilters","data","__expose","onGridReady","onRowClicked","event","onRowDoubleClicked","onCellClicked","onSelectionChanged","onCellValueChanged","_createElementBlock","_normalizeClass","_unref","cn","_createVNode","AgGridVue"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,IAAAA,EAAe,gBAAgB,CAACC,GAAoBC,CAAmB,CAAC;AAOxE,UAAMC,IAASC,EACZ,WAAW;AAAA;AAAA,MAEV,4BAA4B;AAAA,MAC5B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,kBAAkB;AAAA,MAClB,4BAA4B;AAAA,MAC5B,UAAU;AAAA,MACV,yBAAyB;AAAA,IAAA,CAC1B,EACA,WAAW;AAAA,MACV,oBAAoB;AAAA,IAAA,GACnB,OAAO,EACT,WAAW;AAAA,MACV,oBAAoB;AAAA,IAAA,GACnB,MAAM,GAGLC,IAASC,EAAI,OAAO,WAAa,OAAe,SAAS,gBAAgB,UAAU,SAAS,MAAM,CAAC,GACnGC,IAAmBD,EAAwB,IAAI;AACrD,QAAIE,IAAwC;AAG5C,IAAAC,EAAMJ,GAAQ,CAACK,MAAS;AACtB,MAAAH,EAAiB,OAAO,aAAa,sBAAsBG,IAAO,SAAS,OAAO;AAAA,IACpF,CAAC,GAEDC,EAAU,MAAM;AAEd,MAAAJ,EAAiB,OAAO,aAAa,sBAAsBF,EAAO,QAAQ,SAAS,OAAO,GAG1FG,IAAe,IAAI,iBAAiB,MAAM;AACxC,QAAAH,EAAO,QAAQ,SAAS,gBAAgB,UAAU,SAAS,MAAM;AAAA,MACnE,CAAC,GACDG,EAAa,QAAQ,SAAS,iBAAiB,EAAE,YAAY,IAAM,iBAAiB,CAAC,OAAO,GAAG;AAAA,IACjG,CAAC,GAEDI,EAAY,MAAM;AAChB,MAAAJ,GAAc,WAAA;AAAA,IAChB,CAAC;AAoBD,UAAMK,IAAQC,GAqFRC,IAAOC,GAkBPC,IAAUX,EAAS,IAAI,GACvBY,IAAgBZ,EAAS,IAAI,GAG7Ba,IAA4B,CAACC,MAAgC;AACjE,YAAMC,IAAUR,EAAM,iBAAiB,CAAA,GACjCS,IAAUF,EAAO,MAGjBG,IAAiBF,EAAQ,OAAO,CAAAG,MAChCA,EAAI,OACCA,EAAI,KAAKF,CAAO,IAElB,EACR;AAED,UAAIC,EAAe,WAAW;AAC5B,eAAO;AAIT,YAAME,IAAY,SAAS,cAAc,KAAK;AAC9C,aAAAA,EAAU,YAAY,2BAGtBF,EAAe,QAAQ,CAACC,MAAQ;AAC9B,cAAME,IAAS,SAAS,cAAc,QAAQ;AAC9C,QAAAA,EAAO,YAAY,sDAGfF,EAAI,cAAc,WACpBE,EAAO,aAAa,wIAEpBA,EAAO,aAAa,+IAIlBF,EAAI,YACNE,EAAO,QAAQF,EAAI,UAIjBA,EAAI,QACNE,EAAO,cAAcF,EAAI,QAChBA,EAAI,SAETA,EAAI,SAAS,WACfE,EAAO,cAAc,OACZF,EAAI,SAAS,YAAYA,EAAI,SAAS,UAC/CE,EAAO,cAAc,OACZF,EAAI,SAAS,QACtBE,EAAO,cAAc,OACZF,EAAI,SAAS,SACtBE,EAAO,cAAc,OACZF,EAAI,SAAS,aACtBE,EAAO,cAAc,SACZF,EAAI,SAAS,YACtBE,EAAO,cAAc,SACZF,EAAI,SAAS,mBACtBE,EAAO,cAAc,QAErBA,EAAO,cAAcF,EAAI,OAK7BE,EAAO,iBAAiB,SAAS,CAACC,MAAM;AACtC,UAAAA,EAAE,gBAAA,GACFH,EAAI,QAAQF,CAAO;AAAA,QACrB,CAAC,GAEDG,EAAU,YAAYC,CAAM;AAAA,MAC9B,CAAC,GAEMD;AAAA,IACT,GAGMG,IAAsBC,EAAwB,MAC9C,CAAChB,EAAM,iBAAiBA,EAAM,cAAc,WAAW,IAClD,OAGF;AAAA,MACL,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV,cAAc;AAAA,MACd,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,mBAAmB;AAAA,MACnB,0BAA0B;AAAA,MAC1B,cAAcM;AAAA,MACd,WAAW,EAAE,SAAS,QAAQ,gBAAgB,UAAU,YAAY,SAAA;AAAA,IAAS,CAEhF,GAGKW,IAAsBD,EAAS,MAAM;AACzC,YAAME,IAAoB,CAAA;AAG1B,aAAIlB,EAAM,YACRkB,EAAQ,KAAK;AAAA,QACX,OAAO;AAAA,QACP,YAAY;AAAA;AAAA,QAEZ,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,yBAAyB;AAAA,QACzB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,mBAAmB;AAAA,QACnB,0BAA0B;AAAA,QAC1B,WAAW,EAAE,SAAS,QAAQ,gBAAgB,UAAU,YAAY,SAAA;AAAA,MAAS,CAC9E,GAICH,EAAoB,SACtBG,EAAQ,KAAKH,EAAoB,KAAK,GAIxCG,EAAQ,KAAK,GAAGlB,EAAM,UAAU,GAEzBkB;AAAA,IACT,CAAC,GAGKC,IAAcH,EAAsB,MAAM;AAC9C,YAAMI,IAAqBpB,EAAM,kBAAkBA,EAAM;AA6EzD,aA5E6B;AAAA,QAC3B,OAAOV;AAAA,QACP,YAAYU,EAAM;AAAA,QAClB,eAAe;AAAA,UACb,QAAQ;AAAA,UACR,gBAAgBoB;AAAA,QAAA;AAAA,QAElB,cAAcpB,EAAM,WAAW,aAAa;AAAA;AAAA;AAAA,QAG5C,2BAA2BA,EAAM;AAAA;AAAA,QAGjC,YAAYA,EAAM,aACb;AAAA,UACC,UAAUA,EAAM;AAAA,UAChB,OAAOA,EAAM;AAAA,QAAA,IAEf;AAAA;AAAA,QAGJ,sBAAsBA,EAAM;AAAA;AAAA,QAG5B,SAASA,EAAM,0BAA0BA,EAAM,kBAAkBA,EAAM,cAAc;AAAA,UACnF,YAAY;AAAA,YACV;AAAA,cACE,IAAI;AAAA,cACJ,cAAc;AAAA,cACd,UAAU;AAAA,cACV,SAAS;AAAA,cACT,WAAW;AAAA,cACX,iBAAiB;AAAA,gBACf,mBAAmB,CAACA,EAAM;AAAA,gBAC1B,gBAAgB,CAACA,EAAM;AAAA,gBACvB,gBAAgB,CAACA,EAAM;AAAA,gBACvB,mBAAmB,CAACA,EAAM;AAAA,cAAA;AAAA,YAC5B;AAAA,UACF;AAAA,UAEF,kBAAkB;AAAA;AAAA,QAAA,IAChB;AAAA;AAAA;AAAA,QAIJ,WAAYA,EAAM,aAAa,CAACA,EAAM,gBAAiB;AAAA,UACrD,cAAc;AAAA,YACZ,EAAE,aAAa,uCAAuC,OAAO,OAAA;AAAA,YAC7D,EAAE,aAAa,+BAA+B,OAAO,OAAA;AAAA,YACrD,EAAE,aAAa,0BAA0B,OAAO,QAAA;AAAA,UAAiB;AAAA,QACnE,IACE;AAAA;AAAA,QAGJ,mBAAmBA,EAAM,sBAAsB,UAAUA,EAAM,oBAAoB;AAAA;AAAA,QAGnF,gBAAgBA,EAAM,mBAAmB,UAAUA,EAAM,iBAAiB;AAAA;AAAA,QAG1E,WAAWA,EAAM;AAAA;AAAA,QAGjB,sBAAsBA,EAAM;AAAA,QAC5B,yBAAyB;AAAA;AAAA,QAGzB,UAAUA,EAAM,kBAAkB;AAAA,QAClC,aAAaA,EAAM,iBACdA,EAAM,gBAAgB,CAACqB,MAAcA,EAAK,QAAQ,CAAA,KACnD;AAAA,QACJ,oBAAoBrB,EAAM,kBAAkBA,EAAM,qBAC9CA,EAAM,qBACN;AAAA,MAAA;AAAA,IAIR,CAAC;AAYD,IAAAsB,EAAa;AAAA,MACX,SAAAlB;AAAA,MACA,eAAAC;AAAA,MACA,eAZoB,MAAM;AAC1B,QAAID,EAAQ,SAASJ,EAAM,qBACzBI,EAAQ,MAAM,kBAAkB;AAAA,UAC9B,UAAU;AAAA,QAAA,CACX;AAAA,MAEL;AAAA,IAME,CACD;AAGD,UAAMmB,IAAc,CAAChB,MAA2B;AAC9C,MAAAH,EAAQ,QAAQG,EAAO,KACvBF,EAAc,QAAQE,EAAO,KAC7BL,EAAK,aAAaK,CAAM;AAAA,IAC1B,GAGMiB,IAAe,CAACC,MAA2B;AAC/C,MAAAvB,EAAK,cAAcuB,CAAK;AAAA,IAC1B,GAGMC,IAAqB,CAACD,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK;AAAA,IAChC,GAGME,IAAgB,CAACF,MAA4B;AACjD,MAAAvB,EAAK,eAAeuB,CAAK;AAAA,IAC3B,GAGMG,IAAqB,CAACH,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK,GAC9BvB,EAAK,uBAAuBuB,EAAM,IAAI,gBAAA,CAAiB;AAAA,IACzD,GAGMI,IAAqB,CAACJ,MAAiC;AAC3D,MAAAvB,EAAK,oBAAoBuB,CAAK;AAAA,IAChC;AAGA,WAAA7B;AAAA,MACE,MAAMI,EAAM;AAAA,MACZ,MAAM;AACJ,QAAII,EAAQ,SACVA,EAAQ,MAAM,cAAc,cAAca,EAAoB,KAAK;AAAA,MAEvE;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK,GAIfrB;AAAA,MACE,MAAMI,EAAM;AAAA,MACZ,MAAM;AACJ,QAAII,EAAQ,SACVA,EAAQ,MAAM,cAAc,WAAWJ,EAAM,OAAO;AAAA,MAExD;AAAA,MACA,EAAE,MAAM,GAAA;AAAA,IAAK,mBAKb8B,EAaM,OAAA;AAAA,eAbG;AAAA,MAAJ,KAAIpC;AAAA,MAAoB,OAAKqC,EAAEC,EAAAC,CAAA,EAAE,qBAAsBjC,EAAM,KAAK,CAAA;AAAA,IAAA;MACrEkC,EAWEF,EAAAG,CAAA,GAAA;AAAA,QAVC,eAAalB,EAAA;AAAA,QACb,YAAUhB,EAAA;AAAA,QACV,gBAAckB,EAAA;AAAA,QACf,OAAA,EAAA,QAAA,QAAA,OAAA,OAAA;AAAA,QACC,aAAAI;AAAA,QACA,cAAAC;AAAA,QACA,oBAAAE;AAAA,QACA,eAAAC;AAAA,QACA,oBAAAC;AAAA,QACA,oBAAAC;AAAA,MAAA;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("vue");require("../shadcn/index.cjs");const i=require("../shadcn/Input.vue.cjs"),p=l.defineComponent({__name:"JInput",props:{modelValue:{},type:{default:"text"},placeholder:{default:""},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(o,{emit:d}){const e=o,r=d,u={default:{class:""},error:{class:"border-destructive focus-visible:ring-destructive"},success:{class:"border-green-500 focus-visible:ring-green-500"},warning:{class:"border-amber-500 focus-visible:ring-amber-500"},sm:{class:"h-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("vue");require("../shadcn/index.cjs");const i=require("../shadcn/Input.vue.cjs"),p=l.defineComponent({__name:"JInput",props:{modelValue:{},type:{default:"text"},placeholder:{default:""},disabled:{type:Boolean,default:!1},readonly:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(o,{emit:d}){const e=o,r=d,u={default:{class:""},error:{class:"border-destructive focus-visible:ring-destructive"},success:{class:"border-green-500 focus-visible:ring-green-500"},warning:{class:"border-amber-500 focus-visible:ring-amber-500"},sm:{class:"h-7 text-xs px-2"},lg:{class:"h-12 text-base px-4"}},n=l.computed(()=>{const t=e.styletype||"default",a=[(u[t]??u.default)?.class,e.class].filter(Boolean).join(" ");return{type:e.type,placeholder:e.placeholder,disabled:e.disabled,readonly:e.readonly,required:e.required,name:e.name,id:e.id,class:a}}),c=t=>{r("update:modelValue",t),r("change",t)};return(t,s)=>(l.openBlock(),l.createBlock(l.unref(i.default),l.mergeProps(n.value,{"model-value":o.modelValue,"onUpdate:modelValue":c,onFocus:s[0]||(s[0]=a=>r("focus",a)),onBlur:s[1]||(s[1]=a=>r("blur",a))}),{default:l.withCtx(()=>[l.renderSlot(t.$slots,"default")]),_:3},16,["model-value"]))}});exports.default=p;
|
|
2
2
|
//# sourceMappingURL=JInput.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JInput.vue.cjs","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\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 error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \
|
|
1
|
+
{"version":3,"file":"JInput.vue.cjs","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\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 error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \n class: 'h-7 text-xs px-2',\n },\n lg: { \r\n class: 'h-12 text-base px-4',\r\n },\r\n}\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const styleKey = props.styletype || 'default'\r\n const preset = STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\r\n const finalClass = [preset?.class, props.class].filter(Boolean).join(' ')\r\n \r\n return {\r\n type: props.type,\r\n placeholder: props.placeholder,\r\n disabled: props.disabled,\r\n readonly: props.readonly,\r\n required: props.required,\r\n name: props.name,\r\n id: props.id,\r\n class: finalClass,\r\n }\r\n})\r\n\r\nconst handleInput = (value: string | number) => {\r\n emit('update:modelValue', value)\r\n emit('change', value)\r\n}\r\n</script>\r\n\r\n<template>\r\n <Input \r\n v-bind=\"mapped\" \r\n :model-value=\"modelValue\" \r\n @update:model-value=\"handleInput\"\r\n @focus=\"emit('focus', $event)\"\r\n @blur=\"emit('blur', $event)\"\r\n >\r\n <slot />\r\n </Input>\r\n</template>\r\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","mapped","computed","styleKey","finalClass","handleInput","value","_createBlock","_unref","Input","_mergeProps","_cache","$event","_renderSlot","_ctx"],"mappings":"2hBAYA,MAAMA,EAAQC,EAwBRC,EAAOC,EAUPC,EAAsD,CAC1D,QAAS,CAAE,MAAO,EAAA,EAClB,MAAO,CACL,MAAO,mDAAA,EAET,QAAS,CACP,MAAO,+CAAA,EAET,QAAS,CACP,MAAO,+CAAA,EAET,GAAI,CACF,MAAO,kBAAA,EAET,GAAI,CACF,MAAO,qBAAA,CACT,EAIIC,EAASC,EAAAA,SAAS,IAAM,CAC5B,MAAMC,EAAWP,EAAM,WAAa,UAE9BQ,EAAa,EADJJ,EAAcG,CAAQ,GAAKH,EAAc,UAC5B,MAAOJ,EAAM,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAExE,MAAO,CACL,KAAMA,EAAM,KACZ,YAAaA,EAAM,YACnB,SAAUA,EAAM,SAChB,SAAUA,EAAM,SAChB,SAAUA,EAAM,SAChB,KAAMA,EAAM,KACZ,GAAIA,EAAM,GACV,MAAOQ,CAAA,CAEX,CAAC,EAEKC,EAAeC,GAA2B,CAC9CR,EAAK,oBAAqBQ,CAAK,EAC/BR,EAAK,SAAUQ,CAAK,CACtB,8BAIEC,EAAAA,YAQQC,EAAAA,MAAAC,EAAAA,OAAA,EARRC,EAAAA,WAQQT,EAAA,MAPQ,CACb,cAAaJ,EAAA,WACb,sBAAoBQ,EACpB,QAAKM,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAEd,EAAI,QAAUc,CAAM,GAC3B,OAAID,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAAC,GAAEd,EAAI,OAASc,CAAM,EAAA,sBAE1B,IAAQ,CAARC,aAAQC,EAAA,OAAA,SAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JInput.vue.js","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\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 error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \
|
|
1
|
+
{"version":3,"file":"JInput.vue.js","sources":["../../../../src/components/atoms/JInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\nimport { Input } from '@/components/shadcn'\r\n\r\ntype StyleType =\r\n | 'default' // 기본 스타일\r\n | 'error' // 에러 상태 (빨강 테두리)\r\n | 'success' // 성공 상태 (초록 테두리)\r\n | 'warning' // 경고 상태 (주황 테두리)\r\n | 'sm' // 작은 크기\r\n | 'lg' // 큰 크기\r\n\r\nconst props = withDefaults(\r\n defineProps<{\r\n modelValue?: string | number\r\n type?: string\r\n placeholder?: string\r\n disabled?: boolean\r\n readonly?: boolean\r\n required?: boolean\r\n name?: string\r\n id?: string\r\n class?: string\r\n /** 스타일 프리셋 */\r\n styletype?: StyleType\r\n }>(),\r\n {\r\n type: 'text',\r\n placeholder: '',\r\n disabled: false,\r\n readonly: false,\r\n required: false,\r\n styletype: 'default',\r\n },\r\n)\r\n\r\nconst emit = defineEmits<{\r\n 'update:modelValue': [value: string | number]\r\n 'change': [value: string | number]\r\n 'focus': [event: FocusEvent]\r\n 'blur': [event: FocusEvent]\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 error: { \r\n class: 'border-destructive focus-visible:ring-destructive',\r\n },\r\n success: { \r\n class: 'border-green-500 focus-visible:ring-green-500',\r\n },\r\n warning: { \r\n class: 'border-amber-500 focus-visible:ring-amber-500',\r\n },\r\n sm: { \n class: 'h-7 text-xs px-2',\n },\n lg: { \r\n class: 'h-12 text-base px-4',\r\n },\r\n}\r\n\r\n/** 최종 바인딩: 직접 넘긴 class가 있으면 styletype 기본값과 병합 */\r\nconst mapped = computed(() => {\r\n const styleKey = props.styletype || 'default'\r\n const preset = STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\r\n const finalClass = [preset?.class, props.class].filter(Boolean).join(' ')\r\n \r\n return {\r\n type: props.type,\r\n placeholder: props.placeholder,\r\n disabled: props.disabled,\r\n readonly: props.readonly,\r\n required: props.required,\r\n name: props.name,\r\n id: props.id,\r\n class: finalClass,\r\n }\r\n})\r\n\r\nconst handleInput = (value: string | number) => {\r\n emit('update:modelValue', value)\r\n emit('change', value)\r\n}\r\n</script>\r\n\r\n<template>\r\n <Input \r\n v-bind=\"mapped\" \r\n :model-value=\"modelValue\" \r\n @update:model-value=\"handleInput\"\r\n @focus=\"emit('focus', $event)\"\r\n @blur=\"emit('blur', $event)\"\r\n >\r\n <slot />\r\n </Input>\r\n</template>\r\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","mapped","computed","styleKey","finalClass","handleInput","value","_createBlock","_unref","Input","_mergeProps","_cache","$event","_renderSlot","_ctx"],"mappings":";;;;;;;;;;;;;;;;;;;AAYA,UAAMA,IAAQC,GAwBRC,IAAOC,GAUPC,IAAsD;AAAA,MAC1D,SAAS,EAAE,OAAO,GAAA;AAAA,MAClB,OAAO;AAAA,QACL,OAAO;AAAA,MAAA;AAAA,MAET,SAAS;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,MAET,SAAS;AAAA,QACP,OAAO;AAAA,MAAA;AAAA,MAET,IAAI;AAAA,QACF,OAAO;AAAA,MAAA;AAAA,MAET,IAAI;AAAA,QACF,OAAO;AAAA,MAAA;AAAA,IACT,GAIIC,IAASC,EAAS,MAAM;AAC5B,YAAMC,IAAWP,EAAM,aAAa,WAE9BQ,IAAa,EADJJ,EAAcG,CAAQ,KAAKH,EAAc,UAC5B,OAAOJ,EAAM,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAExE,aAAO;AAAA,QACL,MAAMA,EAAM;AAAA,QACZ,aAAaA,EAAM;AAAA,QACnB,UAAUA,EAAM;AAAA,QAChB,UAAUA,EAAM;AAAA,QAChB,UAAUA,EAAM;AAAA,QAChB,MAAMA,EAAM;AAAA,QACZ,IAAIA,EAAM;AAAA,QACV,OAAOQ;AAAA,MAAA;AAAA,IAEX,CAAC,GAEKC,IAAc,CAACC,MAA2B;AAC9C,MAAAR,EAAK,qBAAqBQ,CAAK,GAC/BR,EAAK,UAAUQ,CAAK;AAAA,IACtB;2BAIEC,EAQQC,EAAAC,CAAA,GARRC,EAQQT,EAAA,OAPQ;AAAA,MACb,eAAaJ,EAAA;AAAA,MACb,uBAAoBQ;AAAA,MACpB,SAAKM,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEd,EAAI,SAAUc,CAAM;AAAA,MAC3B,QAAID,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA,CAAAC,MAAEd,EAAI,QAASc,CAAM;AAAA,IAAA;iBAE1B,MAAQ;AAAA,QAARC,EAAQC,EAAA,QAAA,SAAA;AAAA,MAAA;;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),n=require("lucide-vue-next"),o=require("../../lib/utils.cjs");require("../shadcn/index.cjs");const b=require("../shadcn/Combobox.vue.cjs"),x=require("../shadcn/ComboboxAnchor.vue.cjs"),_=require("../shadcn/ComboboxTrigger.vue.cjs"),v=require("../shadcn/Button.vue.cjs"),C=require("../shadcn/ComboboxList.vue.cjs"),h=require("../shadcn/ComboboxInput.vue.cjs"),y=require("../shadcn/ComboboxEmpty.vue.cjs"),g=require("../shadcn/ComboboxGroup.vue.cjs"),V=require("../shadcn/ComboboxItem.vue.cjs"),q={class:"relative w-full max-w-sm items-center"},N={class:"absolute start-0 inset-y-0 flex items-center justify-center px-2.5"},w=e.defineComponent({__name:"JSearchCombo",props:{modelValue:{},options:{default:()=>[]},placeholder:{default:"선택해주세요."},searchPlaceholder:{default:""},emptyText:{default:"검색 결과가 없습니다."},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},multiple:{type:Boolean,default:!1},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(t,{emit:c}){const d=t,r=c,i={default:{variant:"outline",buttonClass:"h-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),n=require("lucide-vue-next"),o=require("../../lib/utils.cjs");require("../shadcn/index.cjs");const b=require("../shadcn/Combobox.vue.cjs"),x=require("../shadcn/ComboboxAnchor.vue.cjs"),_=require("../shadcn/ComboboxTrigger.vue.cjs"),v=require("../shadcn/Button.vue.cjs"),C=require("../shadcn/ComboboxList.vue.cjs"),h=require("../shadcn/ComboboxInput.vue.cjs"),y=require("../shadcn/ComboboxEmpty.vue.cjs"),g=require("../shadcn/ComboboxGroup.vue.cjs"),V=require("../shadcn/ComboboxItem.vue.cjs"),q={class:"relative w-full max-w-sm items-center"},N={class:"absolute start-0 inset-y-0 flex items-center justify-center px-2.5"},w=e.defineComponent({__name:"JSearchCombo",props:{modelValue:{},options:{default:()=>[]},placeholder:{default:"선택해주세요."},searchPlaceholder:{default:""},emptyText:{default:"검색 결과가 없습니다."},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{},id:{},multiple:{type:Boolean,default:!1},class:{},styletype:{default:"default"}},emits:["update:modelValue","change","focus","blur"],setup(t,{emit:c}){const d=t,r=c,i={default:{variant:"outline",buttonClass:"h-7 text-xs px-2.5"},error:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-destructive text-destructive",inputClass:"border-destructive focus:ring-destructive"},success:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-green-500 text-green-700",inputClass:"border-green-500 focus:ring-green-500"},warning:{variant:"outline",buttonClass:"h-7 text-xs px-2.5 border-amber-500 text-amber-700",inputClass:"border-amber-500 focus:ring-amber-500"},sm:{variant:"outline",buttonClass:"h-7 text-[11px] px-2",inputClass:"h-7 text-[11px] px-2 py-1"},lg:{variant:"outline",buttonClass:"h-10 text-sm px-3",inputClass:"h-10 text-sm px-3 py-2"}},s=e.computed(()=>{const a=d.styletype||"default";return i[a]??i.default}),p=e.computed(()=>o.cn("justify-between",s.value?.buttonClass,d.class)),f=e.computed(()=>o.cn("pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs",s.value?.inputClass)),m=a=>{r("update:modelValue",a),r("change",a)};return(a,l)=>(e.openBlock(),e.createBlock(e.unref(b.default),{"model-value":t.modelValue,by:"label",disabled:t.disabled,required:t.required,name:t.name,"onUpdate:modelValue":l[2]||(l[2]=u=>m(u))},{default:e.withCtx(()=>[e.createVNode(e.unref(x.default),{"as-child":""},{default:e.withCtx(()=>[e.createVNode(e.unref(_.default),{"as-child":""},{default:e.withCtx(()=>[e.createVNode(e.unref(v.default),{id:t.id,variant:s.value.variant,class:e.normalizeClass(p.value),disabled:t.disabled,onFocus:l[0]||(l[0]=u=>r("focus",u)),onBlur:l[1]||(l[1]=u=>r("blur",u))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.modelValue?.label??t.placeholder)+" ",1),e.createVNode(e.unref(n.ChevronsUpDown),{class:"ml-2 h-3.5 w-3.5 shrink-0 opacity-50"})]),_:1},8,["id","variant","class","disabled"])]),_:1})]),_:1}),e.createVNode(e.unref(C.default),null,{default:e.withCtx(()=>[e.createElementVNode("div",q,[e.createVNode(e.unref(h.default),{class:e.normalizeClass(f.value),placeholder:t.searchPlaceholder},null,8,["class","placeholder"]),e.createElementVNode("span",N,[e.createVNode(e.unref(n.Search),{class:"size-3.5 text-muted-foreground"})])]),e.createVNode(e.unref(y.default),null,{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(t.emptyText),1)]),_:1}),e.createVNode(e.unref(g.default),null,{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,u=>(e.openBlock(),e.createBlock(e.unref(V.default),{key:u.value,value:u},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(u.label)+" ",1),t.modelValue?.value===u.value?(e.openBlock(),e.createBlock(e.unref(n.Check),{key:0,class:e.normalizeClass(e.unref(o.cn)("ml-auto h-3.5 w-3.5"))},null,8,["class"])):e.createCommentVNode("",!0)]),_:2},1032,["value"]))),128))]),_:1})]),_:1})]),_:1},8,["model-value","disabled","required","name"]))}});exports.default=w;
|
|
2
2
|
//# sourceMappingURL=JSearchCombo.vue.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchCombo.vue.cjs","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-
|
|
1
|
+
{"version":3,"file":"JSearchCombo.vue.cjs","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5',\n },\n error: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-destructive text-destructive',\n inputClass: 'border-destructive focus:ring-destructive',\n },\n success: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-green-500 text-green-700',\n inputClass: 'border-green-500 focus:ring-green-500',\n },\n warning: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-amber-500 text-amber-700',\n inputClass: 'border-amber-500 focus:ring-amber-500',\n },\n sm: { \n variant: 'outline',\n buttonClass: 'h-7 text-[11px] px-2',\n inputClass: 'h-7 text-[11px] px-2 py-1',\n },\n lg: { \n variant: 'outline',\n buttonClass: 'h-10 text-sm px-3',\n inputClass: 'h-10 text-sm px-3 py-2',\n },\n}\n\nconst preset = computed(() => {\n const styleKey = props.styletype || 'default'\n return STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\n})\n\nconst buttonClass = computed(() => {\n return cn('justify-between', preset.value?.buttonClass, props.class)\n})\n\nconst inputClass = computed(() => {\n return cn('pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs', preset.value?.inputClass)\n})\n\nconst handleChange = (value: ComboboxOption | undefined) => {\n emit('update:modelValue', value)\n emit('change', value)\n}\n</script>\n\n<template>\n <Combobox \n :model-value=\"modelValue\" \n by=\"label\" \n :disabled=\"disabled\"\n :required=\"required\"\n :name=\"name\"\n @update:model-value=\"(value) => handleChange(value as ComboboxOption | undefined)\"\n >\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button \n :id=\"id\"\n :variant=\"preset.variant\" \n :class=\"buttonClass\"\n :disabled=\"disabled\"\n @focus=\"emit('focus', $event as FocusEvent)\"\n @blur=\"emit('blur', $event as FocusEvent)\"\n >\n {{ modelValue?.label ?? placeholder }}\n <ChevronsUpDown class=\"ml-2 h-3.5 w-3.5 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :class=\"inputClass\" :placeholder=\"searchPlaceholder\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-2.5\">\n <Search class=\"size-3.5 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n {{ emptyText }}\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"option in options\"\n :key=\"option.value\"\n :value=\"option\"\n >\n {{ option.label }}\n\n <Check v-if=\"modelValue?.value === option.value\" :class=\"cn('ml-auto h-3.5 w-3.5')\" />\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","styleKey","buttonClass","cn","inputClass","handleChange","value","_createBlock","_unref","Combobox","_cache","_createVNode","ComboboxAnchor","ComboboxTrigger","Button","$event","_createTextVNode","_toDisplayString","ChevronsUpDown","ComboboxList","_createElementVNode","_hoisted_1","ComboboxInput","_hoisted_2","Search","ComboboxEmpty","ComboboxGroup","_createElementBlock","_Fragment","_renderList","option","ComboboxItem","Check"],"mappings":"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"}
|
|
@@ -32,21 +32,21 @@ const J = { class: "relative w-full max-w-sm items-center" }, K = { class: "abso
|
|
|
32
32
|
const x = e, u = C, h = {
|
|
33
33
|
default: {
|
|
34
34
|
variant: "outline",
|
|
35
|
-
buttonClass: "h-
|
|
35
|
+
buttonClass: "h-7 text-xs px-2.5"
|
|
36
36
|
},
|
|
37
37
|
error: {
|
|
38
38
|
variant: "outline",
|
|
39
|
-
buttonClass: "h-
|
|
39
|
+
buttonClass: "h-7 text-xs px-2.5 border-destructive text-destructive",
|
|
40
40
|
inputClass: "border-destructive focus:ring-destructive"
|
|
41
41
|
},
|
|
42
42
|
success: {
|
|
43
43
|
variant: "outline",
|
|
44
|
-
buttonClass: "h-
|
|
44
|
+
buttonClass: "h-7 text-xs px-2.5 border-green-500 text-green-700",
|
|
45
45
|
inputClass: "border-green-500 focus:ring-green-500"
|
|
46
46
|
},
|
|
47
47
|
warning: {
|
|
48
48
|
variant: "outline",
|
|
49
|
-
buttonClass: "h-
|
|
49
|
+
buttonClass: "h-7 text-xs px-2.5 border-amber-500 text-amber-700",
|
|
50
50
|
inputClass: "border-amber-500 focus:ring-amber-500"
|
|
51
51
|
},
|
|
52
52
|
sm: {
|
|
@@ -62,7 +62,7 @@ const J = { class: "relative w-full max-w-sm items-center" }, K = { class: "abso
|
|
|
62
62
|
}, i = d(() => {
|
|
63
63
|
const n = x.styletype || "default";
|
|
64
64
|
return h[n] ?? h.default;
|
|
65
|
-
}), y = d(() => b("justify-between", i.value?.buttonClass, x.class)), g = d(() => b("pl-8 pr-2 py-1
|
|
65
|
+
}), y = d(() => b("justify-between", i.value?.buttonClass, x.class)), g = d(() => b("pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs", i.value?.inputClass)), V = (n) => {
|
|
66
66
|
u("update:modelValue", n), u("change", n);
|
|
67
67
|
};
|
|
68
68
|
return (n, r) => (o(), m(t(q), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSearchCombo.vue.js","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-
|
|
1
|
+
{"version":3,"file":"JSearchCombo.vue.js","sources":["../../../../src/components/atoms/JSearchCombo.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { Check, ChevronsUpDown, Search } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport {\n Button,\n Combobox,\n ComboboxAnchor,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxInput,\n ComboboxItem,\n ComboboxList,\n ComboboxTrigger,\n} from '@/components/shadcn'\n\nexport interface ComboboxOption {\n value: string | number\n label: string\n}\n\ntype StyleType =\n | 'default' // 기본 스타일\n | 'error' // 에러 상태\n | 'success' // 성공 상태\n | 'warning' // 경고 상태\n | 'sm' // 작은 크기\n | 'lg' // 큰 크기\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: ComboboxOption\n options?: ComboboxOption[]\n placeholder?: string\n searchPlaceholder?: string\n emptyText?: string\n disabled?: boolean\n required?: boolean\n name?: string\n id?: string\n multiple?: boolean\n class?: string\n /** 스타일 프리셋 */\n styletype?: StyleType\n }>(),\n {\n options: () => [],\n placeholder: '선택해주세요.',\n searchPlaceholder: '',\n emptyText: '검색 결과가 없습니다.',\n disabled: false,\n required: false,\n multiple: false,\n styletype: 'default',\n },\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: ComboboxOption | undefined]\n 'change': [value: ComboboxOption | undefined]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\n/**\n * styletype -> variant/class 매핑\n */\nconst STYLE_PRESETS: Record<StyleType, { variant: 'default' | 'outline' | 'destructive' | 'secondary' | 'ghost' | 'link', buttonClass?: string, inputClass?: string }> = {\n default: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5',\n },\n error: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-destructive text-destructive',\n inputClass: 'border-destructive focus:ring-destructive',\n },\n success: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-green-500 text-green-700',\n inputClass: 'border-green-500 focus:ring-green-500',\n },\n warning: { \n variant: 'outline',\n buttonClass: 'h-7 text-xs px-2.5 border-amber-500 text-amber-700',\n inputClass: 'border-amber-500 focus:ring-amber-500',\n },\n sm: { \n variant: 'outline',\n buttonClass: 'h-7 text-[11px] px-2',\n inputClass: 'h-7 text-[11px] px-2 py-1',\n },\n lg: { \n variant: 'outline',\n buttonClass: 'h-10 text-sm px-3',\n inputClass: 'h-10 text-sm px-3 py-2',\n },\n}\n\nconst preset = computed(() => {\n const styleKey = props.styletype || 'default'\n return STYLE_PRESETS[styleKey] ?? STYLE_PRESETS.default\n})\n\nconst buttonClass = computed(() => {\n return cn('justify-between', preset.value?.buttonClass, props.class)\n})\n\nconst inputClass = computed(() => {\n return cn('pl-8 pr-2 py-1 focus-visible:ring-0 border-0 border-b rounded-none h-7 text-xs', preset.value?.inputClass)\n})\n\nconst handleChange = (value: ComboboxOption | undefined) => {\n emit('update:modelValue', value)\n emit('change', value)\n}\n</script>\n\n<template>\n <Combobox \n :model-value=\"modelValue\" \n by=\"label\" \n :disabled=\"disabled\"\n :required=\"required\"\n :name=\"name\"\n @update:model-value=\"(value) => handleChange(value as ComboboxOption | undefined)\"\n >\n <ComboboxAnchor as-child>\n <ComboboxTrigger as-child>\n <Button \n :id=\"id\"\n :variant=\"preset.variant\" \n :class=\"buttonClass\"\n :disabled=\"disabled\"\n @focus=\"emit('focus', $event as FocusEvent)\"\n @blur=\"emit('blur', $event as FocusEvent)\"\n >\n {{ modelValue?.label ?? placeholder }}\n <ChevronsUpDown class=\"ml-2 h-3.5 w-3.5 shrink-0 opacity-50\" />\n </Button>\n </ComboboxTrigger>\n </ComboboxAnchor>\n\n <ComboboxList>\n <div class=\"relative w-full max-w-sm items-center\">\n <ComboboxInput :class=\"inputClass\" :placeholder=\"searchPlaceholder\" />\n <span class=\"absolute start-0 inset-y-0 flex items-center justify-center px-2.5\">\n <Search class=\"size-3.5 text-muted-foreground\" />\n </span>\n </div>\n\n <ComboboxEmpty>\n {{ emptyText }}\n </ComboboxEmpty>\n\n <ComboboxGroup>\n <ComboboxItem\n v-for=\"option in options\"\n :key=\"option.value\"\n :value=\"option\"\n >\n {{ option.label }}\n\n <Check v-if=\"modelValue?.value === option.value\" :class=\"cn('ml-auto h-3.5 w-3.5')\" />\n </ComboboxItem>\n </ComboboxGroup>\n </ComboboxList>\n </Combobox>\n</template>\n"],"names":["props","__props","emit","__emit","STYLE_PRESETS","preset","computed","styleKey","buttonClass","cn","inputClass","handleChange","value","_createBlock","_unref","Combobox","_cache","_createVNode","ComboboxAnchor","ComboboxTrigger","Button","$event","_createTextVNode","_toDisplayString","ChevronsUpDown","ComboboxList","_createElementVNode","_hoisted_1","ComboboxInput","_hoisted_2","Search","ComboboxEmpty","ComboboxGroup","_createElementBlock","_Fragment","_renderList","option","ComboboxItem","Check"],"mappings":"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"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
for (const [t_key, t_val] of t_opts)
|
|
4
4
|
t_merged[t_key] = t_val;
|
|
5
5
|
return t_merged;
|
|
6
|
-
};,u=t(e.default,[["__scopeId","data-v-
|
|
6
|
+
};,u=t(e.default,[["__scopeId","data-v-9c1f0de8"]]);exports.default=u;
|
|
7
7
|
//# sourceMappingURL=JSplitter.vue.cjs.map
|
|
@@ -6,8 +6,8 @@ const o = (o_comp, o_opts) => {
|
|
|
6
6
|
o_merged[o_key] = o_val;
|
|
7
7
|
return o_merged;
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const f = /* @__PURE__ */ o(t, [["__scopeId", "data-v-9c1f0de8"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
f as default
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=JSplitter.vue.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),s=require("../shadcn/resizable/ResizableHandle.vue.cjs"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("vue"),s=require("../../lib/utils.cjs"),r=require("../shadcn/resizable/ResizableHandle.vue.cjs"),u=require("../shadcn/resizable/ResizablePanelGroup.vue.cjs"),l=require("reka-ui"),o=e.defineComponent({__name:"JSplitter",props:{direction:{default:"horizontal"},defaultSize:{default:40},minSize:{default:20},maxSize:{},secondMinSize:{},secondMaxSize:{},withHandle:{type:Boolean,default:!1},gap:{default:2},class:{}},setup(t){const i=t,n=e.computed(()=>100-i.defaultSize);return(a,d)=>(e.openBlock(),e.createBlock(e.unref(u.default),{direction:t.direction,class:e.normalizeClass(e.unref(s.cn)("jsplitter-group min-h-0 min-w-0",a.$props.class))},{default:e.withCtx(()=>[e.createVNode(e.unref(l.SplitterPanel),{"default-size":t.defaultSize,"min-size":t.minSize,"max-size":t.maxSize,class:e.normalizeClass(t.gap>0?t.direction==="horizontal"?"pr-[calc(var(--gap)/2)]":"pb-[calc(var(--gap)/2)]":""),style:e.normalizeStyle(t.gap>0?{"--gap":`${t.gap}px`}:{})},{default:e.withCtx(()=>[e.renderSlot(a.$slots,"first",{},void 0,!0),e.renderSlot(a.$slots,"left",{},void 0,!0),e.renderSlot(a.$slots,"top",{},void 0,!0)]),_:3},8,["default-size","min-size","max-size","class","style"]),e.createVNode(e.unref(r.default),{"with-handle":t.withHandle,class:"jsplitter-handle"},null,8,["with-handle"]),e.createVNode(e.unref(l.SplitterPanel),{"default-size":n.value,"min-size":t.secondMinSize,"max-size":t.secondMaxSize,class:e.normalizeClass(t.gap>0?t.direction==="horizontal"?"pl-[calc(var(--gap)/2)]":"pt-[calc(var(--gap)/2)]":""),style:e.normalizeStyle(t.gap>0?{"--gap":`${t.gap}px`}:{})},{default:e.withCtx(()=>[e.renderSlot(a.$slots,"second",{},void 0,!0),e.renderSlot(a.$slots,"right",{},void 0,!0),e.renderSlot(a.$slots,"bottom",{},void 0,!0)]),_:3},8,["default-size","min-size","max-size","class","style"])]),_:3},8,["direction","class"]))}});exports.default=o;
|
|
2
2
|
//# sourceMappingURL=JSplitter.vue2.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSplitter.vue2.cjs","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle:
|
|
1
|
+
{"version":3,"file":"JSplitter.vue2.cjs","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '@/lib/utils'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap: 2,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"cn('jsplitter-group min-h-0 min-w-0', $props.class)\">\n <!-- 첫 번째 패널 (좌측/상단) -->\n <ResizablePanel \n :default-size=\"defaultSize\" \n :min-size=\"minSize\" \n :max-size=\"maxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pr-[calc(var(--gap)/2)]' : 'pb-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"first\" />\n <!-- direction=\"horizontal\"일 때 left, vertical일 때 top으로도 사용 가능 -->\n <slot name=\"left\" />\n <slot name=\"top\" />\n </ResizablePanel>\n\n <!-- 크기 조정 핸들 -->\n <ResizableHandle :with-handle=\"withHandle\" class=\"jsplitter-handle\" />\n\n <!-- 두 번째 패널 (우측/하단) -->\n <ResizablePanel\n :default-size=\"secondDefaultSize\"\n :min-size=\"secondMinSize\"\n :max-size=\"secondMaxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pl-[calc(var(--gap)/2)]' : 'pt-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"second\" />\n <!-- direction=\"horizontal\"일 때 right, vertical일 때 bottom으로도 사용 가능 -->\n <slot name=\"right\" />\n <slot name=\"bottom\" />\n </ResizablePanel>\n </ResizablePanelGroup>\n</template>\n\n<style scoped>\n/* 패널 콘텐츠가 최소 크기 이하로 줄 때 overflow 깨짐 방지 */\n:deep(.jsplitter-group [data-panel]) {\n min-width: 0;\n min-height: 0;\n}\n\n/* splitter: 시각선 1px + 드래그 히트영역 8px */\n:deep(.jsplitter-handle[data-orientation=\"horizontal\"]) {\n width: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle[data-orientation=\"vertical\"]) {\n height: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle::after) {\n background: hsl(var(--border) / 0.75) !important;\n}\n\n:deep(.jsplitter-handle:hover) {\n background: hsl(var(--primary) / 0.05) !important;\n}\n\n:deep(.jsplitter-handle:hover::after),\n:deep(.jsplitter-handle:active::after),\n:deep(.jsplitter-handle[data-state=\"drag\"]::after) {\n background: hsl(var(--primary) / 0.85) !important;\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_normalizeClass","cn","$props","_createVNode","ResizablePanel","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":"kiBAWA,MAAMA,EAAQC,EA+BRC,EAAoBC,EAAAA,SAAS,IAAM,IAAMH,EAAM,WAAW,8BAI9DI,EAAAA,YA+BsBC,EAAAA,MAAAC,EAAAA,OAAA,EAAA,CA/BA,UAAWL,EAAA,UAAY,MAAKM,EAAAA,eAAEF,EAAAA,MAAAG,EAAAA,EAAA,EAAE,kCAAoCC,EAAAA,OAAO,KAAK,CAAA,CAAA,qBAEpG,IAWiB,CAXjBC,cAWiBL,EAAAA,MAAAM,EAAAA,aAAA,EAAA,CAVd,eAAcV,EAAA,YACd,WAAUA,EAAA,QACV,WAAUA,EAAA,QACV,MAAKM,EAAAA,eAAEN,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKW,EAAAA,eAAEX,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAqB,CAArBY,EAAAA,WAAqBC,EAAA,OAAA,QAAA,CAAA,EAAA,OAAA,EAAA,EAErBD,EAAAA,WAAoBC,EAAA,OAAA,OAAA,CAAA,EAAA,OAAA,EAAA,EACpBD,EAAAA,WAAmBC,EAAA,OAAA,MAAA,CAAA,EAAA,OAAA,EAAA,CAAA,kEAIrBJ,cAAsEL,EAAAA,MAAAU,EAAAA,OAAA,EAAA,CAApD,cAAad,EAAA,WAAY,MAAM,kBAAA,0BAGjDS,cAWiBL,EAAAA,MAAAM,EAAAA,aAAA,EAAA,CAVd,eAAcT,EAAA,MACd,WAAUD,EAAA,cACV,WAAUA,EAAA,cACV,MAAKM,EAAAA,eAAEN,EAAA,IAAG,EAAQA,EAAA,YAAS,aAAA,0BAAA,0BAAA,EAAA,EAC3B,MAAKW,EAAAA,eAAEX,EAAA,IAAG,EAAA,CAAA,QAAA,GAAqBA,EAAA,GAAG,IAAA,EAAA,CAAA,CAAA,CAAA,qBAEnC,IAAsB,CAAtBY,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,EAEtBD,EAAAA,WAAqBC,EAAA,OAAA,QAAA,CAAA,EAAA,OAAA,EAAA,EACrBD,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import S from "
|
|
3
|
-
import g from "../shadcn/resizable/
|
|
1
|
+
import { defineComponent as m, computed as u, createBlock as f, openBlock as z, unref as t, normalizeClass as l, withCtx as s, createVNode as n, normalizeStyle as o, renderSlot as i } from "vue";
|
|
2
|
+
import { cn as S } from "../../lib/utils.js";
|
|
3
|
+
import g from "../shadcn/resizable/ResizableHandle.vue.js";
|
|
4
|
+
import h from "../shadcn/resizable/ResizablePanelGroup.vue.js";
|
|
4
5
|
import { SplitterPanel as d } from "reka-ui";
|
|
5
|
-
const
|
|
6
|
+
const M = /* @__PURE__ */ m({
|
|
6
7
|
__name: "JSplitter",
|
|
7
8
|
props: {
|
|
8
9
|
direction: { default: "horizontal" },
|
|
@@ -11,43 +12,46 @@ const w = /* @__PURE__ */ u({
|
|
|
11
12
|
maxSize: {},
|
|
12
13
|
secondMinSize: {},
|
|
13
14
|
secondMaxSize: {},
|
|
14
|
-
withHandle: { type: Boolean, default: !
|
|
15
|
-
gap: { default:
|
|
15
|
+
withHandle: { type: Boolean, default: !1 },
|
|
16
|
+
gap: { default: 2 },
|
|
16
17
|
class: {}
|
|
17
18
|
},
|
|
18
19
|
setup(e) {
|
|
19
|
-
const c = e, r =
|
|
20
|
-
return (a,
|
|
20
|
+
const c = e, r = u(() => 100 - c.defaultSize);
|
|
21
|
+
return (a, p) => (z(), f(t(h), {
|
|
21
22
|
direction: e.direction,
|
|
22
|
-
class: l(
|
|
23
|
+
class: l(t(S)("jsplitter-group min-h-0 min-w-0", a.$props.class))
|
|
23
24
|
}, {
|
|
24
|
-
default:
|
|
25
|
-
|
|
25
|
+
default: s(() => [
|
|
26
|
+
n(t(d), {
|
|
26
27
|
"default-size": e.defaultSize,
|
|
27
28
|
"min-size": e.minSize,
|
|
28
29
|
"max-size": e.maxSize,
|
|
29
30
|
class: l(e.gap > 0 ? e.direction === "horizontal" ? "pr-[calc(var(--gap)/2)]" : "pb-[calc(var(--gap)/2)]" : ""),
|
|
30
31
|
style: o(e.gap > 0 ? { "--gap": `${e.gap}px` } : {})
|
|
31
32
|
}, {
|
|
32
|
-
default:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
default: s(() => [
|
|
34
|
+
i(a.$slots, "first", {}, void 0, !0),
|
|
35
|
+
i(a.$slots, "left", {}, void 0, !0),
|
|
36
|
+
i(a.$slots, "top", {}, void 0, !0)
|
|
36
37
|
]),
|
|
37
38
|
_: 3
|
|
38
39
|
}, 8, ["default-size", "min-size", "max-size", "class", "style"]),
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
n(t(g), {
|
|
41
|
+
"with-handle": e.withHandle,
|
|
42
|
+
class: "jsplitter-handle"
|
|
43
|
+
}, null, 8, ["with-handle"]),
|
|
44
|
+
n(t(d), {
|
|
41
45
|
"default-size": r.value,
|
|
42
46
|
"min-size": e.secondMinSize,
|
|
43
47
|
"max-size": e.secondMaxSize,
|
|
44
48
|
class: l(e.gap > 0 ? e.direction === "horizontal" ? "pl-[calc(var(--gap)/2)]" : "pt-[calc(var(--gap)/2)]" : ""),
|
|
45
49
|
style: o(e.gap > 0 ? { "--gap": `${e.gap}px` } : {})
|
|
46
50
|
}, {
|
|
47
|
-
default:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
default: s(() => [
|
|
52
|
+
i(a.$slots, "second", {}, void 0, !0),
|
|
53
|
+
i(a.$slots, "right", {}, void 0, !0),
|
|
54
|
+
i(a.$slots, "bottom", {}, void 0, !0)
|
|
51
55
|
]),
|
|
52
56
|
_: 3
|
|
53
57
|
}, 8, ["default-size", "min-size", "max-size", "class", "style"])
|
|
@@ -57,6 +61,6 @@ const w = /* @__PURE__ */ u({
|
|
|
57
61
|
}
|
|
58
62
|
});
|
|
59
63
|
export {
|
|
60
|
-
|
|
64
|
+
M as default
|
|
61
65
|
};
|
|
62
66
|
//# sourceMappingURL=JSplitter.vue2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JSplitter.vue2.js","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle:
|
|
1
|
+
{"version":3,"file":"JSplitter.vue2.js","sources":["../../../../src/components/atoms/JSplitter.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { cn } from '@/lib/utils'\nimport {\n ResizablePanelGroup,\n ResizablePanel,\n ResizableHandle,\n} from '@/components/shadcn/resizable'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nconst props = withDefaults(\n defineProps<{\n /** 분할 방향 (horizontal: 좌우, vertical: 상하) */\n direction?: Orientation\n /** 첫 번째 패널의 기본 크기 (%) */\n defaultSize?: number\n /** 첫 번째 패널의 최소 크기 (%) */\n minSize?: number\n /** 첫 번째 패널의 최대 크기 (%) */\n maxSize?: number\n /** 두 번째 패널의 최소 크기 (%) */\n secondMinSize?: number\n /** 두 번째 패널의 최대 크기 (%) */\n secondMaxSize?: number\n /** ResizableHandle에 grip 아이콘 표시 여부 */\n withHandle?: boolean\n /** 패널 간 여백 (px) */\n gap?: number\n /** 추가 CSS 클래스 */\n class?: string\n }>(),\n {\n direction: 'horizontal',\n defaultSize: 40,\n minSize: 20,\n withHandle: false,\n gap: 2,\n },\n)\n\n// 두 번째 패널의 기본 크기 계산\nconst secondDefaultSize = computed(() => 100 - props.defaultSize)\n</script>\n\n<template>\n <ResizablePanelGroup :direction=\"direction\" :class=\"cn('jsplitter-group min-h-0 min-w-0', $props.class)\">\n <!-- 첫 번째 패널 (좌측/상단) -->\n <ResizablePanel \n :default-size=\"defaultSize\" \n :min-size=\"minSize\" \n :max-size=\"maxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pr-[calc(var(--gap)/2)]' : 'pb-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"first\" />\n <!-- direction=\"horizontal\"일 때 left, vertical일 때 top으로도 사용 가능 -->\n <slot name=\"left\" />\n <slot name=\"top\" />\n </ResizablePanel>\n\n <!-- 크기 조정 핸들 -->\n <ResizableHandle :with-handle=\"withHandle\" class=\"jsplitter-handle\" />\n\n <!-- 두 번째 패널 (우측/하단) -->\n <ResizablePanel\n :default-size=\"secondDefaultSize\"\n :min-size=\"secondMinSize\"\n :max-size=\"secondMaxSize\"\n :class=\"gap > 0 ? (direction === 'horizontal' ? 'pl-[calc(var(--gap)/2)]' : 'pt-[calc(var(--gap)/2)]') : ''\"\n :style=\"gap > 0 ? { '--gap': `${gap}px` } : {}\"\n >\n <slot name=\"second\" />\n <!-- direction=\"horizontal\"일 때 right, vertical일 때 bottom으로도 사용 가능 -->\n <slot name=\"right\" />\n <slot name=\"bottom\" />\n </ResizablePanel>\n </ResizablePanelGroup>\n</template>\n\n<style scoped>\n/* 패널 콘텐츠가 최소 크기 이하로 줄 때 overflow 깨짐 방지 */\n:deep(.jsplitter-group [data-panel]) {\n min-width: 0;\n min-height: 0;\n}\n\n/* splitter: 시각선 1px + 드래그 히트영역 8px */\n:deep(.jsplitter-handle[data-orientation=\"horizontal\"]) {\n width: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle[data-orientation=\"vertical\"]) {\n height: 8px !important;\n background: transparent !important;\n z-index: 3;\n}\n\n:deep(.jsplitter-handle::after) {\n background: hsl(var(--border) / 0.75) !important;\n}\n\n:deep(.jsplitter-handle:hover) {\n background: hsl(var(--primary) / 0.05) !important;\n}\n\n:deep(.jsplitter-handle:hover::after),\n:deep(.jsplitter-handle:active::after),\n:deep(.jsplitter-handle[data-state=\"drag\"]::after) {\n background: hsl(var(--primary) / 0.85) !important;\n}\n</style>\n"],"names":["props","__props","secondDefaultSize","computed","_createBlock","_unref","ResizablePanelGroup","_normalizeClass","cn","$props","_createVNode","ResizablePanel","_normalizeStyle","_renderSlot","_ctx","ResizableHandle"],"mappings":";;;;;;;;;;;;;;;;;;;AAWA,UAAMA,IAAQC,GA+BRC,IAAoBC,EAAS,MAAM,MAAMH,EAAM,WAAW;2BAI9DI,EA+BsBC,EAAAC,CAAA,GAAA;AAAA,MA/BA,WAAWL,EAAA;AAAA,MAAY,OAAKM,EAAEF,EAAAG,CAAA,EAAE,mCAAoCC,EAAAA,OAAO,KAAK,CAAA;AAAA,IAAA;iBAEpG,MAWiB;AAAA,QAXjBC,EAWiBL,EAAAM,CAAA,GAAA;AAAA,UAVd,gBAAcV,EAAA;AAAA,UACd,YAAUA,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKM,EAAEN,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKW,EAAEX,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAqB;AAAA,YAArBY,EAAqBC,EAAA,QAAA,SAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YAErBD,EAAoBC,EAAA,QAAA,QAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YACpBD,EAAmBC,EAAA,QAAA,OAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;QAIrBJ,EAAsEL,EAAAU,CAAA,GAAA;AAAA,UAApD,eAAad,EAAA;AAAA,UAAY,OAAM;AAAA,QAAA;QAGjDS,EAWiBL,EAAAM,CAAA,GAAA;AAAA,UAVd,gBAAcT,EAAA;AAAA,UACd,YAAUD,EAAA;AAAA,UACV,YAAUA,EAAA;AAAA,UACV,OAAKM,EAAEN,EAAA,MAAG,IAAQA,EAAA,cAAS,eAAA,4BAAA,4BAAA,EAAA;AAAA,UAC3B,OAAKW,EAAEX,EAAA,MAAG,IAAA,EAAA,SAAA,GAAqBA,EAAA,GAAG,KAAA,IAAA,CAAA,CAAA;AAAA,QAAA;qBAEnC,MAAsB;AAAA,YAAtBY,EAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YAEtBD,EAAqBC,EAAA,QAAA,SAAA,CAAA,GAAA,QAAA,EAAA;AAAA,YACrBD,EAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,UAAA;;;;;;;;"}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
for (const [t_key, t_val] of t_opts)
|
|
4
4
|
t_merged[t_key] = t_val;
|
|
5
5
|
return t_merged;
|
|
6
|
-
};,u=t(e.default,[["__scopeId","data-v-
|
|
6
|
+
};,u=t(e.default,[["__scopeId","data-v-f600f461"]]);exports.default=u;
|
|
7
7
|
//# sourceMappingURL=JFormField.vue.cjs.map
|
|
@@ -6,8 +6,8 @@ const r = (r_comp, r_opts) => {
|
|
|
6
6
|
r_merged[r_key] = r_val;
|
|
7
7
|
return r_merged;
|
|
8
8
|
};
|
|
9
|
-
const
|
|
9
|
+
const p = /* @__PURE__ */ r(o, [["__scopeId", "data-v-f600f461"]]);
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
p as default
|
|
12
12
|
};
|
|
13
13
|
//# sourceMappingURL=JFormField.vue.js.map
|