velox-grid 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +483 -0
  2. package/README.md +755 -0
  3. package/dist/react/index.esm.js +3757 -0
  4. package/dist/react/index.esm.js.map +1 -0
  5. package/dist/react/index.js +7 -0
  6. package/dist/react/index.js.map +1 -0
  7. package/dist/react/react/VeloxGridReact.d.ts +33 -0
  8. package/dist/react/react/VeloxGridReact.d.ts.map +1 -0
  9. package/dist/react/react/index.d.ts +9 -0
  10. package/dist/react/react/index.d.ts.map +1 -0
  11. package/dist/react/react/types.d.ts +52 -0
  12. package/dist/react/react/types.d.ts.map +1 -0
  13. package/dist/react/react/useVeloxGrid.d.ts +23 -0
  14. package/dist/react/react/useVeloxGrid.d.ts.map +1 -0
  15. package/dist/react/types/index.d.ts +878 -0
  16. package/dist/react/types/index.d.ts.map +1 -0
  17. package/dist/types/core/GridColumnMenu.d.ts +35 -0
  18. package/dist/types/core/GridColumnMenu.d.ts.map +1 -0
  19. package/dist/types/core/GridDragManager.d.ts +83 -0
  20. package/dist/types/core/GridDragManager.d.ts.map +1 -0
  21. package/dist/types/core/GridEditorFactory.d.ts +33 -0
  22. package/dist/types/core/GridEditorFactory.d.ts.map +1 -0
  23. package/dist/types/core/GridFilterPopup.d.ts +43 -0
  24. package/dist/types/core/GridFilterPopup.d.ts.map +1 -0
  25. package/dist/types/core/GridHistory.d.ts +84 -0
  26. package/dist/types/core/GridHistory.d.ts.map +1 -0
  27. package/dist/types/core/GridRenderer.d.ts +73 -0
  28. package/dist/types/core/GridRenderer.d.ts.map +1 -0
  29. package/dist/types/core/GridSummary.d.ts +98 -0
  30. package/dist/types/core/GridSummary.d.ts.map +1 -0
  31. package/dist/types/core/GridTooltip.d.ts +43 -0
  32. package/dist/types/core/GridTooltip.d.ts.map +1 -0
  33. package/dist/types/core/GridValidator.d.ts +63 -0
  34. package/dist/types/core/GridValidator.d.ts.map +1 -0
  35. package/dist/types/core/VeloxGrid.d.ts +437 -0
  36. package/dist/types/core/VeloxGrid.d.ts.map +1 -0
  37. package/dist/types/core/index.d.ts +15 -0
  38. package/dist/types/core/index.d.ts.map +1 -0
  39. package/dist/types/index.d.ts +16 -0
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/react/VeloxGridReact.d.ts +40 -0
  42. package/dist/types/react/VeloxGridReact.d.ts.map +1 -0
  43. package/dist/types/react/index.d.ts +9 -0
  44. package/dist/types/react/index.d.ts.map +1 -0
  45. package/dist/types/react/types.d.ts +55 -0
  46. package/dist/types/react/types.d.ts.map +1 -0
  47. package/dist/types/react/useVeloxGrid.d.ts +54 -0
  48. package/dist/types/react/useVeloxGrid.d.ts.map +1 -0
  49. package/dist/types/types/index.d.ts +878 -0
  50. package/dist/types/types/index.d.ts.map +1 -0
  51. package/dist/types/utils/data.d.ts +41 -0
  52. package/dist/types/utils/data.d.ts.map +1 -0
  53. package/dist/types/utils/dom.d.ts +13 -0
  54. package/dist/types/utils/dom.d.ts.map +1 -0
  55. package/dist/types/utils/export.d.ts +60 -0
  56. package/dist/types/utils/export.d.ts.map +1 -0
  57. package/dist/types/utils/index.d.ts +4 -0
  58. package/dist/types/utils/index.d.ts.map +1 -0
  59. package/dist/types/vue/index.d.ts +9 -0
  60. package/dist/types/vue/index.d.ts.map +1 -0
  61. package/dist/types/vue/types.d.ts +68 -0
  62. package/dist/types/vue/types.d.ts.map +1 -0
  63. package/dist/types/vue/useVeloxGrid.d.ts +49 -0
  64. package/dist/types/vue/useVeloxGrid.d.ts.map +1 -0
  65. package/dist/velox-grid.css +1 -0
  66. package/dist/velox-grid.esm.js +3387 -0
  67. package/dist/velox-grid.esm.js.map +1 -0
  68. package/dist/velox-grid.iife.js +14 -0
  69. package/dist/velox-grid.iife.js.map +1 -0
  70. package/dist/velox-grid.js +14 -0
  71. package/dist/velox-grid.js.map +1 -0
  72. package/dist/vue/index.esm.js +3754 -0
  73. package/dist/vue/index.esm.js.map +1 -0
  74. package/dist/vue/index.js +7 -0
  75. package/dist/vue/index.js.map +1 -0
  76. package/dist/vue/types/index.d.ts +878 -0
  77. package/dist/vue/types/index.d.ts.map +1 -0
  78. package/dist/vue/vue/index.d.ts +9 -0
  79. package/dist/vue/vue/index.d.ts.map +1 -0
  80. package/dist/vue/vue/types.d.ts +65 -0
  81. package/dist/vue/vue/types.d.ts.map +1 -0
  82. package/dist/vue/vue/useVeloxGrid.d.ts +21 -0
  83. package/dist/vue/vue/useVeloxGrid.d.ts.map +1 -0
  84. package/package.json +120 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"velox-grid.esm.js","sources":["../src/utils/dom.ts","../src/utils/data.ts","../src/utils/export.ts","../src/core/GridHistory.ts","../src/core/GridValidator.ts","../src/core/GridEditorFactory.ts","../src/core/GridTooltip.ts","../src/core/GridRenderer.ts","../src/core/GridFilterPopup.ts","../src/core/GridColumnMenu.ts","../src/core/GridDragManager.ts","../src/core/GridSummary.ts","../src/core/VeloxGrid.ts","../src/index.ts"],"sourcesContent":["/**\r\n * DOM Utility Functions\r\n */\r\n\r\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\r\n tag: K,\r\n className?: string,\r\n attributes?: Record<string, string>\r\n): HTMLElementTagNameMap[K] {\r\n const element = document.createElement(tag);\r\n if (className) {\r\n element.className = className;\r\n }\r\n if (attributes) {\r\n Object.entries(attributes).forEach(([key, value]) => {\r\n element.setAttribute(key, value);\r\n });\r\n }\r\n return element;\r\n}\r\n\r\nexport function addClass(element: HTMLElement, ...classNames: string[]): void {\r\n element.classList.add(...classNames);\r\n}\r\n\r\nexport function removeClass(element: HTMLElement, ...classNames: string[]): void {\r\n element.classList.remove(...classNames);\r\n}\r\n\r\nexport function toggleClass(element: HTMLElement, className: string, force?: boolean): void {\r\n element.classList.toggle(className, force);\r\n}\r\n\r\nexport function hasClass(element: HTMLElement, className: string): boolean {\r\n return element.classList.contains(className);\r\n}\r\n\r\nexport function setStyles(element: HTMLElement, styles: Partial<CSSStyleDeclaration>): void {\r\n Object.assign(element.style, styles);\r\n}\r\n\r\nexport function getScrollbarWidth(): number {\r\n const outer = createElement('div');\r\n outer.style.visibility = 'hidden';\r\n outer.style.overflow = 'scroll';\r\n document.body.appendChild(outer);\r\n\r\n const inner = createElement('div');\r\n outer.appendChild(inner);\r\n\r\n const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\r\n outer.parentNode?.removeChild(outer);\r\n\r\n return scrollbarWidth;\r\n}\r\n\r\nexport function throttle<T extends (...args: unknown[]) => unknown>(\r\n func: T,\r\n limit: number\r\n): (...args: Parameters<T>) => void {\r\n let inThrottle = false;\r\n return function (this: unknown, ...args: Parameters<T>) {\r\n if (!inThrottle) {\r\n func.apply(this, args);\r\n inThrottle = true;\r\n setTimeout(() => (inThrottle = false), limit);\r\n }\r\n };\r\n}\r\n\r\nexport function debounce<T extends (...args: unknown[]) => unknown>(\r\n func: T,\r\n wait: number\r\n): (...args: Parameters<T>) => void {\r\n let timeout: ReturnType<typeof setTimeout> | null = null;\r\n return function (this: unknown, ...args: Parameters<T>) {\r\n if (timeout) clearTimeout(timeout);\r\n timeout = setTimeout(() => func.apply(this, args), wait);\r\n };\r\n}\r\n","/**\r\n * Data Utility Functions\r\n */\r\n\r\nimport type { CellValue, RowData, SortState, FilterCondition, FilterState, ValueType } from '../types';\r\n\r\n/**\r\n * Deep clone an object\r\n */\r\nexport function deepClone<T>(obj: T): T {\r\n if (obj === null || typeof obj !== 'object') {\r\n return obj;\r\n }\r\n if (obj instanceof Date) {\r\n return new Date(obj.getTime()) as T;\r\n }\r\n if (Array.isArray(obj)) {\r\n return obj.map((item) => deepClone(item)) as T;\r\n }\r\n const cloned = {} as T;\r\n for (const key in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\r\n cloned[key] = deepClone(obj[key]);\r\n }\r\n }\r\n return cloned;\r\n}\r\n\r\n/**\r\n * Generate unique ID\r\n */\r\nexport function generateId(prefix = 'velox'): string {\r\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Format cell value based on type\r\n */\r\nexport function formatValue(value: CellValue, type: ValueType = 'text'): string {\r\n if (value === null || value === undefined) {\r\n return '';\r\n }\r\n\r\n switch (type) {\r\n case 'number':\r\n return typeof value === 'number' ? value.toLocaleString() : String(value);\r\n case 'boolean':\r\n return value ? 'Yes' : 'No';\r\n case 'date':\r\n if (value instanceof Date) {\r\n return value.toLocaleDateString();\r\n }\r\n return String(value);\r\n case 'datetime':\r\n if (value instanceof Date) {\r\n return value.toLocaleString();\r\n }\r\n return String(value);\r\n case 'text':\r\n default:\r\n return String(value);\r\n }\r\n}\r\n\r\n/**\r\n * Parse value to specific type\r\n */\r\nexport function parseValue(value: string, type: ValueType): CellValue {\r\n if (value === '' || value === null || value === undefined) {\r\n return null;\r\n }\r\n\r\n switch (type) {\r\n case 'number':\r\n const num = parseFloat(value.replace(/,/g, ''));\r\n return isNaN(num) ? null : num;\r\n case 'boolean':\r\n return value.toLowerCase() === 'true' || value === '1' || value.toLowerCase() === 'yes';\r\n case 'date':\r\n case 'datetime':\r\n const date = new Date(value);\r\n return isNaN(date.getTime()) ? null : date;\r\n case 'text':\r\n default:\r\n return value;\r\n }\r\n}\r\n\r\n/**\r\n * Compare two values\r\n */\r\nexport function compareValues(a: CellValue, b: CellValue, type: ValueType = 'text'): number {\r\n // Handle null/undefined\r\n if (a === null || a === undefined) return b === null || b === undefined ? 0 : -1;\r\n if (b === null || b === undefined) return 1;\r\n\r\n switch (type) {\r\n case 'number':\r\n return (a as number) - (b as number);\r\n case 'boolean':\r\n return (a as boolean) === (b as boolean) ? 0 : (a as boolean) ? 1 : -1;\r\n case 'date':\r\n case 'datetime':\r\n const dateA = a instanceof Date ? a : new Date(a as string);\r\n const dateB = b instanceof Date ? b : new Date(b as string);\r\n return dateA.getTime() - dateB.getTime();\r\n case 'text':\r\n default:\r\n return String(a).localeCompare(String(b));\r\n }\r\n}\r\n\r\n/**\r\n * Sort data by multiple columns\r\n */\r\nexport function sortData(\r\n data: RowData[],\r\n sortStates: SortState[],\r\n columnTypes: Record<string, ValueType>\r\n): RowData[] {\r\n if (!sortStates.length) return data;\r\n\r\n return [...data].sort((a, b) => {\r\n for (const { field, direction } of sortStates) {\r\n if (!direction) continue;\r\n \r\n const type = columnTypes[field] || 'text';\r\n const comparison = compareValues(a[field], b[field], type);\r\n \r\n if (comparison !== 0) {\r\n return direction === 'asc' ? comparison : -comparison;\r\n }\r\n }\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * Check if value matches filter condition\r\n */\r\nexport function matchesFilter(value: CellValue, condition: FilterCondition): boolean {\r\n const { operator, value: filterValue, value2 } = condition;\r\n\r\n // Handle empty checks first\r\n if (operator === 'isEmpty') {\r\n return value === null || value === undefined || value === '';\r\n }\r\n if (operator === 'isNotEmpty') {\r\n return value !== null && value !== undefined && value !== '';\r\n }\r\n\r\n // For other operators, convert to strings for comparison\r\n const strValue = String(value ?? '').toLowerCase();\r\n const strFilterValue = String(filterValue ?? '').toLowerCase();\r\n\r\n switch (operator) {\r\n case 'equals':\r\n return strValue === strFilterValue;\r\n case 'notEquals':\r\n return strValue !== strFilterValue;\r\n case 'contains':\r\n return strValue.includes(strFilterValue);\r\n case 'notContains':\r\n return !strValue.includes(strFilterValue);\r\n case 'startsWith':\r\n return strValue.startsWith(strFilterValue);\r\n case 'endsWith':\r\n return strValue.endsWith(strFilterValue);\r\n case 'greaterThan':\r\n return Number(value) > Number(filterValue);\r\n case 'lessThan':\r\n return Number(value) < Number(filterValue);\r\n case 'greaterThanOrEqual':\r\n return Number(value) >= Number(filterValue);\r\n case 'lessThanOrEqual':\r\n return Number(value) <= Number(filterValue);\r\n case 'between':\r\n const numValue = Number(value);\r\n return numValue >= Number(filterValue) && numValue <= Number(value2);\r\n default:\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Filter data by conditions\r\n */\r\nexport function filterData(data: RowData[], filterState: FilterState | null): RowData[] {\r\n if (!filterState || !filterState.conditions.length) {\r\n return data;\r\n }\r\n\r\n const { conditions, logic } = filterState;\r\n\r\n return data.filter((row) => {\r\n const results = conditions.map((condition) => \r\n matchesFilter(row[condition.field], condition)\r\n );\r\n\r\n return logic === 'and' \r\n ? results.every(Boolean) \r\n : results.some(Boolean);\r\n });\r\n}\r\n\r\n/**\r\n * Escape HTML special characters\r\n */\r\nexport function escapeHtml(text: string): string {\r\n const div = document.createElement('div');\r\n div.textContent = text;\r\n return div.innerHTML;\r\n}\r\n","/**\r\n * VeloxGrid Export Utilities\r\n * Phase 8: Excel Export/Import\r\n * \r\n * @description Provides export functionality for Excel, CSV, and JSON formats\r\n */\r\n\r\nimport type { RowData, ColumnDefinition, ExportOptions, CellValue, ValueType } from '../types';\r\n// formatValue can be used for custom formatting in future\r\n\r\n// ============================================\r\n// Types\r\n// ============================================\r\n\r\nexport interface ExportContext {\r\n data: RowData[];\r\n displayData: RowData[];\r\n columns: ColumnDefinition[];\r\n selectedRows: number[];\r\n options: ExportOptions;\r\n}\r\n\r\nexport interface ImportResult {\r\n data: RowData[];\r\n headers: string[];\r\n errors: string[];\r\n}\r\n\r\n// ============================================\r\n// CSV Export\r\n// ============================================\r\n\r\n/**\r\n * Export data to CSV format\r\n */\r\nexport function exportToCSV(context: ExportContext): string {\r\n const { data, displayData, columns, selectedRows, options } = context;\r\n \r\n // Determine which columns to export\r\n const exportColumns = options.columns\r\n ? columns.filter(c => options.columns!.includes(c.field) && c.visible !== false)\r\n : columns.filter(c => c.visible !== false);\r\n \r\n // Determine which rows to export\r\n let rowsToExport: RowData[];\r\n if (options.selectedOnly && selectedRows.length > 0) {\r\n const sourceData = options.filteredOnly ? displayData : data;\r\n rowsToExport = selectedRows.map(i => sourceData[i]).filter(Boolean);\r\n } else if (options.filteredOnly) {\r\n rowsToExport = displayData;\r\n } else {\r\n rowsToExport = data;\r\n }\r\n \r\n const lines: string[] = [];\r\n \r\n // Add header row\r\n if (options.includeHeader !== false) {\r\n const headerRow = exportColumns.map(col => escapeCSVValue(col.header));\r\n lines.push(headerRow.join(','));\r\n }\r\n \r\n // Add data rows\r\n rowsToExport.forEach(row => {\r\n const values = exportColumns.map(col => {\r\n const value = row[col.field];\r\n return escapeCSVValue(formatExportValue(value, col.type));\r\n });\r\n lines.push(values.join(','));\r\n });\r\n \r\n return lines.join('\\r\\n');\r\n}\r\n\r\n/**\r\n * Escape a value for CSV format\r\n */\r\nfunction escapeCSVValue(value: string | null | undefined): string {\r\n if (value === null || value === undefined) return '';\r\n \r\n const stringValue = String(value);\r\n \r\n // Check if value needs quoting\r\n if (stringValue.includes(',') || stringValue.includes('\"') || stringValue.includes('\\n') || stringValue.includes('\\r')) {\r\n return `\"${stringValue.replace(/\"/g, '\"\"')}\"`;\r\n }\r\n \r\n return stringValue;\r\n}\r\n\r\n// ============================================\r\n// JSON Export\r\n// ============================================\r\n\r\n/**\r\n * Export data to JSON format\r\n */\r\nexport function exportToJSON(context: ExportContext): string {\r\n const { data, displayData, columns, selectedRows, options } = context;\r\n \r\n // Determine which columns to export\r\n const exportColumns = options.columns\r\n ? columns.filter(c => options.columns!.includes(c.field) && c.visible !== false)\r\n : columns.filter(c => c.visible !== false);\r\n \r\n // Determine which rows to export\r\n let rowsToExport: RowData[];\r\n if (options.selectedOnly && selectedRows.length > 0) {\r\n const sourceData = options.filteredOnly ? displayData : data;\r\n rowsToExport = selectedRows.map(i => sourceData[i]).filter(Boolean);\r\n } else if (options.filteredOnly) {\r\n rowsToExport = displayData;\r\n } else {\r\n rowsToExport = data;\r\n }\r\n \r\n // Filter columns for each row\r\n const result = rowsToExport.map(row => {\r\n const obj: RowData = {};\r\n exportColumns.forEach(col => {\r\n obj[col.field] = row[col.field];\r\n });\r\n return obj;\r\n });\r\n \r\n return JSON.stringify(result, null, 2);\r\n}\r\n\r\n// ============================================\r\n// Excel Export (using SheetJS)\r\n// ============================================\r\n\r\n/**\r\n * Check if SheetJS is available\r\n */\r\nexport function isSheetJSAvailable(): boolean {\r\n return typeof (window as any).XLSX !== 'undefined';\r\n}\r\n\r\n/**\r\n * Get SheetJS library\r\n */\r\nfunction getXLSX(): any {\r\n const XLSX = (window as any).XLSX;\r\n if (!XLSX) {\r\n throw new Error(\r\n 'SheetJS (xlsx) library is not loaded. ' +\r\n 'Please include it via CDN: <script src=\"https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js\"></script>'\r\n );\r\n }\r\n return XLSX;\r\n}\r\n\r\n/**\r\n * Export data to Excel format\r\n */\r\nexport function exportToExcel(context: ExportContext): void {\r\n const XLSX = getXLSX();\r\n const { data, displayData, columns, selectedRows, options } = context;\r\n \r\n // Determine which columns to export\r\n const exportColumns = options.columns\r\n ? columns.filter(c => options.columns!.includes(c.field) && c.visible !== false)\r\n : columns.filter(c => c.visible !== false);\r\n \r\n // Determine which rows to export\r\n let rowsToExport: RowData[];\r\n if (options.selectedOnly && selectedRows.length > 0) {\r\n const sourceData = options.filteredOnly ? displayData : data;\r\n rowsToExport = selectedRows.map(i => sourceData[i]).filter(Boolean);\r\n } else if (options.filteredOnly) {\r\n rowsToExport = displayData;\r\n } else {\r\n rowsToExport = data;\r\n }\r\n \r\n // Build worksheet data\r\n const wsData: any[][] = [];\r\n \r\n // Add header row\r\n if (options.includeHeader !== false) {\r\n wsData.push(exportColumns.map(col => col.header));\r\n }\r\n \r\n // Add data rows\r\n rowsToExport.forEach(row => {\r\n const rowData = exportColumns.map(col => {\r\n const value = row[col.field];\r\n return formatExcelValue(value, col.type);\r\n });\r\n wsData.push(rowData);\r\n });\r\n \r\n // Create worksheet\r\n const ws = XLSX.utils.aoa_to_sheet(wsData);\r\n \r\n // Set column widths\r\n const colWidths = exportColumns.map(col => ({\r\n wch: Math.max(\r\n col.header.length,\r\n ...rowsToExport.slice(0, 100).map(row => {\r\n const value = row[col.field];\r\n return String(value ?? '').length;\r\n })\r\n ) + 2\r\n }));\r\n ws['!cols'] = colWidths;\r\n \r\n // Create workbook\r\n const wb = XLSX.utils.book_new();\r\n const sheetName = options.sheetName || 'Sheet1';\r\n XLSX.utils.book_append_sheet(wb, ws, sheetName);\r\n \r\n // Generate filename\r\n const filename = (options.filename || 'export') + '.xlsx';\r\n \r\n // Write file\r\n XLSX.writeFile(wb, filename);\r\n}\r\n\r\n/**\r\n * Format value for Excel export\r\n */\r\nfunction formatExcelValue(value: CellValue, type?: ValueType): any {\r\n if (value === null || value === undefined) return '';\r\n \r\n switch (type) {\r\n case 'number':\r\n return typeof value === 'number' ? value : parseFloat(String(value)) || 0;\r\n case 'boolean':\r\n return Boolean(value);\r\n case 'date':\r\n case 'datetime':\r\n if (value instanceof Date) return value;\r\n if (typeof value === 'string' || typeof value === 'number') {\r\n const date = new Date(value);\r\n return isNaN(date.getTime()) ? String(value) : date;\r\n }\r\n return String(value);\r\n default:\r\n return String(value);\r\n }\r\n}\r\n\r\n/**\r\n * Format value for general export\r\n */\r\nfunction formatExportValue(value: CellValue, type?: ValueType): string {\r\n if (value === null || value === undefined) return '';\r\n \r\n switch (type) {\r\n case 'date':\r\n if (value instanceof Date) {\r\n return value.toISOString().split('T')[0];\r\n }\r\n return String(value);\r\n case 'datetime':\r\n if (value instanceof Date) {\r\n return value.toISOString();\r\n }\r\n return String(value);\r\n default:\r\n return String(value);\r\n }\r\n}\r\n\r\n// ============================================\r\n// CSV Import\r\n// ============================================\r\n\r\n/**\r\n * Parse CSV string to data array\r\n */\r\nexport function parseCSV(csvString: string, hasHeader = true): ImportResult {\r\n const result: ImportResult = {\r\n data: [],\r\n headers: [],\r\n errors: []\r\n };\r\n \r\n try {\r\n const lines = parseCSVLines(csvString);\r\n \r\n if (lines.length === 0) {\r\n result.errors.push('CSV file is empty');\r\n return result;\r\n }\r\n \r\n let dataStartIndex = 0;\r\n \r\n if (hasHeader) {\r\n result.headers = lines[0];\r\n dataStartIndex = 1;\r\n } else {\r\n // Generate default headers\r\n const columnCount = lines[0]?.length || 0;\r\n result.headers = Array.from({ length: columnCount }, (_, i) => `Column${i + 1}`);\r\n }\r\n \r\n // Parse data rows\r\n for (let i = dataStartIndex; i < lines.length; i++) {\r\n const line = lines[i];\r\n const row: RowData = {};\r\n \r\n result.headers.forEach((header, colIndex) => {\r\n row[header] = line[colIndex] ?? '';\r\n });\r\n \r\n result.data.push(row);\r\n }\r\n } catch (error) {\r\n result.errors.push(`CSV parsing error: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * Parse CSV string into lines and cells\r\n */\r\nfunction parseCSVLines(csvString: string): string[][] {\r\n const lines: string[][] = [];\r\n let currentLine: string[] = [];\r\n let currentCell = '';\r\n let inQuotes = false;\r\n \r\n for (let i = 0; i < csvString.length; i++) {\r\n const char = csvString[i];\r\n const nextChar = csvString[i + 1];\r\n \r\n if (inQuotes) {\r\n if (char === '\"') {\r\n if (nextChar === '\"') {\r\n // Escaped quote\r\n currentCell += '\"';\r\n i++;\r\n } else {\r\n // End of quoted field\r\n inQuotes = false;\r\n }\r\n } else {\r\n currentCell += char;\r\n }\r\n } else {\r\n if (char === '\"') {\r\n inQuotes = true;\r\n } else if (char === ',') {\r\n currentLine.push(currentCell);\r\n currentCell = '';\r\n } else if (char === '\\r') {\r\n // Skip carriage return\r\n continue;\r\n } else if (char === '\\n') {\r\n currentLine.push(currentCell);\r\n if (currentLine.some(cell => cell.trim() !== '')) {\r\n lines.push(currentLine);\r\n }\r\n currentLine = [];\r\n currentCell = '';\r\n } else {\r\n currentCell += char;\r\n }\r\n }\r\n }\r\n \r\n // Handle last cell/line\r\n if (currentCell !== '' || currentLine.length > 0) {\r\n currentLine.push(currentCell);\r\n if (currentLine.some(cell => cell.trim() !== '')) {\r\n lines.push(currentLine);\r\n }\r\n }\r\n \r\n return lines;\r\n}\r\n\r\n// ============================================\r\n// Excel Import (using SheetJS)\r\n// ============================================\r\n\r\n/**\r\n * Import data from Excel file\r\n */\r\nexport function importFromExcel(file: File, sheetIndex = 0): Promise<ImportResult> {\r\n return new Promise((resolve) => {\r\n const result: ImportResult = {\r\n data: [],\r\n headers: [],\r\n errors: []\r\n };\r\n \r\n if (!isSheetJSAvailable()) {\r\n result.errors.push(\r\n 'SheetJS (xlsx) library is not loaded. ' +\r\n 'Please include it via CDN: <script src=\"https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js\"></script>'\r\n );\r\n resolve(result);\r\n return;\r\n }\r\n \r\n const XLSX = getXLSX();\r\n const reader = new FileReader();\r\n \r\n reader.onload = (e) => {\r\n try {\r\n const data = e.target?.result;\r\n const workbook = XLSX.read(data, { type: 'array' });\r\n \r\n // Get sheet\r\n const sheetNames = workbook.SheetNames;\r\n if (sheetIndex >= sheetNames.length) {\r\n result.errors.push(`Sheet index ${sheetIndex} not found. Available sheets: ${sheetNames.join(', ')}`);\r\n resolve(result);\r\n return;\r\n }\r\n \r\n const sheetName = sheetNames[sheetIndex];\r\n const worksheet = workbook.Sheets[sheetName];\r\n \r\n // Convert to JSON\r\n const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) as any[][];\r\n \r\n if (jsonData.length === 0) {\r\n result.errors.push('Excel sheet is empty');\r\n resolve(result);\r\n return;\r\n }\r\n \r\n // First row as headers\r\n result.headers = jsonData[0].map((h: any) => String(h ?? ''));\r\n \r\n // Data rows\r\n for (let i = 1; i < jsonData.length; i++) {\r\n const row: RowData = {};\r\n const rowData = jsonData[i];\r\n \r\n result.headers.forEach((header, colIndex) => {\r\n const value = rowData[colIndex];\r\n row[header] = value ?? '';\r\n });\r\n \r\n // Skip empty rows\r\n if (Object.values(row).some(v => v !== '')) {\r\n result.data.push(row);\r\n }\r\n }\r\n \r\n resolve(result);\r\n } catch (error) {\r\n result.errors.push(`Excel parsing error: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n resolve(result);\r\n }\r\n };\r\n \r\n reader.onerror = () => {\r\n result.errors.push('Failed to read file');\r\n resolve(result);\r\n };\r\n \r\n reader.readAsArrayBuffer(file);\r\n });\r\n}\r\n\r\n/**\r\n * Import data from Excel file by sheet name\r\n */\r\nexport function importFromExcelBySheetName(file: File, sheetName: string): Promise<ImportResult> {\r\n return new Promise((resolve) => {\r\n const result: ImportResult = {\r\n data: [],\r\n headers: [],\r\n errors: []\r\n };\r\n \r\n if (!isSheetJSAvailable()) {\r\n result.errors.push('SheetJS (xlsx) library is not loaded.');\r\n resolve(result);\r\n return;\r\n }\r\n \r\n const XLSX = getXLSX();\r\n const reader = new FileReader();\r\n \r\n reader.onload = (e) => {\r\n try {\r\n const data = e.target?.result;\r\n const workbook = XLSX.read(data, { type: 'array' });\r\n \r\n if (!workbook.SheetNames.includes(sheetName)) {\r\n result.errors.push(`Sheet \"${sheetName}\" not found. Available sheets: ${workbook.SheetNames.join(', ')}`);\r\n resolve(result);\r\n return;\r\n }\r\n \r\n const worksheet = workbook.Sheets[sheetName];\r\n const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) as any[][];\r\n \r\n if (jsonData.length === 0) {\r\n result.errors.push('Excel sheet is empty');\r\n resolve(result);\r\n return;\r\n }\r\n \r\n result.headers = jsonData[0].map((h: any) => String(h ?? ''));\r\n \r\n for (let i = 1; i < jsonData.length; i++) {\r\n const row: RowData = {};\r\n const rowData = jsonData[i];\r\n \r\n result.headers.forEach((header, colIndex) => {\r\n row[header] = rowData[colIndex] ?? '';\r\n });\r\n \r\n if (Object.values(row).some(v => v !== '')) {\r\n result.data.push(row);\r\n }\r\n }\r\n \r\n resolve(result);\r\n } catch (error) {\r\n result.errors.push(`Excel parsing error: ${error instanceof Error ? error.message : 'Unknown error'}`);\r\n resolve(result);\r\n }\r\n };\r\n \r\n reader.onerror = () => {\r\n result.errors.push('Failed to read file');\r\n resolve(result);\r\n };\r\n \r\n reader.readAsArrayBuffer(file);\r\n });\r\n}\r\n\r\n// ============================================\r\n// Download Utility\r\n// ============================================\r\n\r\n/**\r\n * Download content as a file\r\n */\r\nexport function downloadFile(content: string | Blob, filename: string, mimeType = 'text/plain'): void {\r\n const blob = content instanceof Blob ? content : new Blob([content], { type: mimeType });\r\n const url = URL.createObjectURL(blob);\r\n \r\n const link = document.createElement('a');\r\n link.href = url;\r\n link.download = filename;\r\n link.style.display = 'none';\r\n \r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n \r\n URL.revokeObjectURL(url);\r\n}\r\n\r\n/**\r\n * Download CSV file\r\n */\r\nexport function downloadCSV(context: ExportContext): void {\r\n const csv = exportToCSV(context);\r\n const filename = (context.options.filename || 'export') + '.csv';\r\n downloadFile(csv, filename, 'text/csv;charset=utf-8');\r\n}\r\n\r\n/**\r\n * Download JSON file\r\n */\r\nexport function downloadJSON(context: ExportContext): void {\r\n const json = exportToJSON(context);\r\n const filename = (context.options.filename || 'export') + '.json';\r\n downloadFile(json, filename, 'application/json');\r\n}\r\n","/**\r\n * GridHistory - Undo/Redo History Manager\r\n * @description Manages undo/redo stacks for grid operations\r\n */\r\n\r\nimport type {\r\n UndoAction,\r\n CellEditUndoData,\r\n BulkEditUndoData,\r\n RowAddUndoData,\r\n RowRemoveUndoData,\r\n CellValue,\r\n RowData,\r\n} from '../types';\r\n\r\nexport interface HistoryOptions {\r\n /** Enable history tracking */\r\n enabled: boolean;\r\n /** Maximum stack size */\r\n maxSize: number;\r\n}\r\n\r\nconst DEFAULT_OPTIONS: HistoryOptions = {\r\n enabled: true,\r\n maxSize: 50,\r\n};\r\n\r\nexport class GridHistory {\r\n private undoStack: UndoAction[] = [];\r\n private redoStack: UndoAction[] = [];\r\n private options: HistoryOptions;\r\n\r\n constructor(options: Partial<HistoryOptions> = {}) {\r\n this.options = { ...DEFAULT_OPTIONS, ...options };\r\n }\r\n\r\n /**\r\n * Check if history tracking is enabled\r\n */\r\n isEnabled(): boolean {\r\n return this.options.enabled;\r\n }\r\n\r\n /**\r\n * Set enabled state\r\n */\r\n setEnabled(enabled: boolean): void {\r\n this.options.enabled = enabled;\r\n }\r\n\r\n /**\r\n * Set maximum stack size\r\n */\r\n setMaxSize(size: number): void {\r\n this.options.maxSize = size;\r\n this.trimStack();\r\n }\r\n\r\n /**\r\n * Push an action to the undo stack\r\n */\r\n push(action: UndoAction): void {\r\n if (!this.options.enabled) return;\r\n\r\n this.undoStack.push(action);\r\n this.trimStack();\r\n \r\n // Clear redo stack when new action is performed\r\n this.redoStack = [];\r\n }\r\n\r\n /**\r\n * Create and push a cell edit action\r\n */\r\n pushCellEdit(rowIndex: number, field: string, oldValue: CellValue, newValue: CellValue): void {\r\n this.push({\r\n type: 'cell_edit',\r\n timestamp: Date.now(),\r\n data: { rowIndex, field, oldValue, newValue } as CellEditUndoData,\r\n });\r\n }\r\n\r\n /**\r\n * Create and push a bulk edit action (paste, cut, delete)\r\n */\r\n pushBulkEdit(\r\n type: 'paste' | 'cut' | 'delete' | 'bulk_edit',\r\n changes: BulkEditUndoData['changes']\r\n ): void {\r\n if (changes.length === 0) return;\r\n \r\n this.push({\r\n type,\r\n timestamp: Date.now(),\r\n data: { changes } as BulkEditUndoData,\r\n });\r\n }\r\n\r\n /**\r\n * Create and push a row add action\r\n */\r\n pushRowAdd(row: RowData, index: number): void {\r\n this.push({\r\n type: 'row_add',\r\n timestamp: Date.now(),\r\n data: { row: { ...row }, index } as RowAddUndoData,\r\n });\r\n }\r\n\r\n /**\r\n * Create and push a row remove action\r\n */\r\n pushRowRemove(row: RowData, index: number): void {\r\n this.push({\r\n type: 'row_remove',\r\n timestamp: Date.now(),\r\n data: { row: { ...row }, index } as RowRemoveUndoData,\r\n });\r\n }\r\n\r\n /**\r\n * Pop from undo stack and push to redo stack\r\n * Returns the action to be undone\r\n */\r\n popUndo(): UndoAction | null {\r\n if (!this.options.enabled || this.undoStack.length === 0) {\r\n return null;\r\n }\r\n\r\n const action = this.undoStack.pop()!;\r\n this.redoStack.push(action);\r\n return action;\r\n }\r\n\r\n /**\r\n * Pop from redo stack and push to undo stack\r\n * Returns the action to be redone\r\n */\r\n popRedo(): UndoAction | null {\r\n if (!this.options.enabled || this.redoStack.length === 0) {\r\n return null;\r\n }\r\n\r\n const action = this.redoStack.pop()!;\r\n this.undoStack.push(action);\r\n return action;\r\n }\r\n\r\n /**\r\n * Check if undo is available\r\n */\r\n canUndo(): boolean {\r\n return this.options.enabled && this.undoStack.length > 0;\r\n }\r\n\r\n /**\r\n * Check if redo is available\r\n */\r\n canRedo(): boolean {\r\n return this.options.enabled && this.redoStack.length > 0;\r\n }\r\n\r\n /**\r\n * Get undo stack size\r\n */\r\n getUndoCount(): number {\r\n return this.undoStack.length;\r\n }\r\n\r\n /**\r\n * Get redo stack size\r\n */\r\n getRedoCount(): number {\r\n return this.redoStack.length;\r\n }\r\n\r\n /**\r\n * Clear all history\r\n */\r\n clear(): void {\r\n this.undoStack = [];\r\n this.redoStack = [];\r\n }\r\n\r\n /**\r\n * Trim undo stack to max size\r\n */\r\n private trimStack(): void {\r\n while (this.undoStack.length > this.options.maxSize) {\r\n this.undoStack.shift();\r\n }\r\n }\r\n}\r\n","/**\r\n * VeloxGrid - GridValidator\r\n * @description Cell validation logic\r\n * Phase 12.1: Cell Validation\r\n */\r\n\r\nimport type { CellValue, RowData, ValidationRule, ValidationResult, ColumnDefinition } from '../types';\r\n\r\nexport class GridValidator {\r\n /**\r\n * 단일 값에 대한 유효성 검사\r\n * @param value - 검사할 값\r\n * @param rules - 유효성 규칙 배열\r\n * @param row - 전체 행 데이터 (custom validator용)\r\n * @returns 검사 결과\r\n */\r\n static validate(value: CellValue, rules: ValidationRule[], row?: RowData): ValidationResult {\r\n const errors: Array<{ field: string; message: string }> = [];\r\n\r\n for (const rule of rules) {\r\n const error = this.validateRule(value, rule, row);\r\n if (error) {\r\n errors.push({ field: '', message: error });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors\r\n };\r\n }\r\n\r\n /**\r\n * 단일 규칙 검사\r\n * @param value - 검사할 값\r\n * @param rule - 유효성 규칙\r\n * @param row - 전체 행 데이터\r\n * @returns 에러 메시지 또는 null\r\n */\r\n private static validateRule(value: CellValue, rule: ValidationRule, row?: RowData): string | null {\r\n switch (rule.type) {\r\n case 'required':\r\n return this.validateRequired(value) ? null : rule.message;\r\n\r\n case 'min':\r\n return this.validateMin(value, rule.value as number) ? null : rule.message;\r\n\r\n case 'max':\r\n return this.validateMax(value, rule.value as number) ? null : rule.message;\r\n\r\n case 'minLength':\r\n return this.validateMinLength(value, rule.value as number) ? null : rule.message;\r\n\r\n case 'maxLength':\r\n return this.validateMaxLength(value, rule.value as number) ? null : rule.message;\r\n\r\n case 'pattern':\r\n return this.validatePattern(value, rule.value as RegExp | string) ? null : rule.message;\r\n\r\n case 'custom':\r\n if (rule.validator) {\r\n const result = rule.validator(value, row || {});\r\n if (typeof result === 'boolean') {\r\n return result ? null : rule.message;\r\n } else {\r\n return result || null;\r\n }\r\n }\r\n return null;\r\n\r\n default:\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Required 검사 - null, undefined, 빈 문자열 체크\r\n */\r\n private static validateRequired(value: CellValue): boolean {\r\n if (value === null || value === undefined) {\r\n return false;\r\n }\r\n if (typeof value === 'string' && value.trim() === '') {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Min 검사 - 숫자 최소값\r\n */\r\n private static validateMin(value: CellValue, min: number): boolean {\r\n if (value === null || value === undefined) {\r\n return true; // required가 아니면 빈 값은 통과\r\n }\r\n const num = typeof value === 'number' ? value : parseFloat(String(value));\r\n return !isNaN(num) && num >= min;\r\n }\r\n\r\n /**\r\n * Max 검사 - 숫자 최대값\r\n */\r\n private static validateMax(value: CellValue, max: number): boolean {\r\n if (value === null || value === undefined) {\r\n return true;\r\n }\r\n const num = typeof value === 'number' ? value : parseFloat(String(value));\r\n return !isNaN(num) && num <= max;\r\n }\r\n\r\n /**\r\n * MinLength 검사 - 문자열 최소 길이\r\n */\r\n private static validateMinLength(value: CellValue, minLength: number): boolean {\r\n if (value === null || value === undefined) {\r\n return true;\r\n }\r\n return String(value).length >= minLength;\r\n }\r\n\r\n /**\r\n * MaxLength 검사 - 문자열 최대 길이\r\n */\r\n private static validateMaxLength(value: CellValue, maxLength: number): boolean {\r\n if (value === null || value === undefined) {\r\n return true;\r\n }\r\n return String(value).length <= maxLength;\r\n }\r\n\r\n /**\r\n * Pattern 검사 - 정규식 매칭\r\n */\r\n private static validatePattern(value: CellValue, pattern: RegExp | string): boolean {\r\n if (value === null || value === undefined) {\r\n return true;\r\n }\r\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\r\n return regex.test(String(value));\r\n }\r\n\r\n /**\r\n * 전체 행 유효성 검사\r\n * @param row - 검사할 행 데이터\r\n * @param columns - 컬럼 정의 (validation 규칙 포함)\r\n * @returns 검사 결과\r\n */\r\n static validateRow(row: RowData, columns: ColumnDefinition[]): ValidationResult {\r\n const errors: Array<{ field: string; message: string }> = [];\r\n\r\n for (const column of columns) {\r\n if (column.validation && column.validation.length > 0) {\r\n const value = row[column.field];\r\n const result = this.validate(value, column.validation, row);\r\n \r\n if (!result.valid) {\r\n for (const error of result.errors) {\r\n errors.push({\r\n field: column.field,\r\n message: error.message\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors\r\n };\r\n }\r\n\r\n /**\r\n * 전체 데이터 유효성 검사\r\n * @param data - 검사할 데이터 배열\r\n * @param columns - 컬럼 정의\r\n * @returns 행별 검사 결과 배열\r\n */\r\n static validateAll(data: RowData[], columns: ColumnDefinition[]): ValidationResult[] {\r\n return data.map(row => this.validateRow(row, columns));\r\n }\r\n}\r\n","/**\r\n * VeloxGrid - GridEditorFactory\r\n * @description Custom cell editor factory for different input types\r\n * Phase 12.2: Custom Cell Editor\r\n */\r\n\r\nimport type { CellValue, EditorOptions } from '../types';\r\n\r\nexport class GridEditorFactory {\r\n /**\r\n * Create an editor element based on type\r\n */\r\n static createEditor(\r\n value: CellValue,\r\n options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLElement {\r\n const { type } = options;\r\n\r\n switch (type) {\r\n case 'text':\r\n case 'number':\r\n return this.createTextEditor(value, options, onSave, onCancel, onMove);\r\n case 'select':\r\n return this.createSelectEditor(value, options, onSave, onCancel, onMove);\r\n case 'date':\r\n return this.createDateEditor(value, options, onSave, onCancel, onMove);\r\n case 'checkbox':\r\n return this.createCheckboxEditor(value, options, onSave, onCancel, onMove);\r\n case 'custom':\r\n return this.createCustomEditor(value, options, onSave, onCancel, onMove);\r\n default:\r\n return this.createTextEditor(value, options, onSave, onCancel, onMove);\r\n }\r\n }\r\n\r\n /**\r\n * Create text/number input editor\r\n */\r\n private static createTextEditor(\r\n value: CellValue,\r\n options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLInputElement {\r\n const input = document.createElement('input');\r\n input.className = 'velox-edit-input';\r\n input.type = options.type === 'number' ? 'number' : 'text';\r\n input.value = value != null ? String(value) : '';\r\n\r\n if (options.placeholder) {\r\n input.placeholder = options.placeholder;\r\n }\r\n\r\n if (options.type === 'number') {\r\n if (options.min !== undefined) input.min = String(options.min);\r\n if (options.max !== undefined) input.max = String(options.max);\r\n if (options.step !== undefined) input.step = String(options.step);\r\n }\r\n\r\n // Event handlers\r\n input.addEventListener('blur', () => {\r\n const newValue = options.type === 'number' ? parseFloat(input.value) : input.value;\r\n onSave(newValue);\r\n });\r\n\r\n input.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const newValue = options.type === 'number' ? parseFloat(input.value) : input.value;\r\n onSave(newValue);\r\n if (onMove) onMove(e.shiftKey ? 'up' : 'down');\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n const newValue = options.type === 'number' ? parseFloat(input.value) : input.value;\r\n onSave(newValue);\r\n if (onMove) onMove(e.shiftKey ? 'left' : 'right');\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onCancel();\r\n }\r\n });\r\n\r\n return input;\r\n }\r\n\r\n /**\r\n * Create select dropdown editor\r\n */\r\n private static createSelectEditor(\r\n value: CellValue,\r\n options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLSelectElement {\r\n const select = document.createElement('select');\r\n select.className = 'velox-edit-select';\r\n\r\n // Add options\r\n if (options.options && options.options.length > 0) {\r\n options.options.forEach(option => {\r\n const optionElement = document.createElement('option');\r\n optionElement.value = String(option.value ?? '');\r\n optionElement.textContent = option.label;\r\n if (option.value === value) {\r\n optionElement.selected = true;\r\n }\r\n select.appendChild(optionElement);\r\n });\r\n }\r\n\r\n // Event handlers\r\n select.addEventListener('change', () => {\r\n console.log('📦 Select change event', select.value);\r\n onSave(select.value);\r\n });\r\n\r\n // blur 이벤트 제거 - change만으로 충분 (중복 방지)\r\n\r\n select.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSave(select.value);\r\n if (onMove) onMove(e.shiftKey ? 'up' : 'down');\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSave(select.value);\r\n if (onMove) onMove(e.shiftKey ? 'left' : 'right');\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onCancel();\r\n }\r\n });\r\n\r\n return select;\r\n }\r\n\r\n /**\r\n * Create date input editor\r\n */\r\n private static createDateEditor(\r\n value: CellValue,\r\n _options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLInputElement {\r\n const input = document.createElement('input');\r\n input.className = 'velox-edit-input velox-edit-date';\r\n input.type = 'date';\r\n\r\n // Format date value\r\n if (value instanceof Date) {\r\n input.value = value.toISOString().split('T')[0];\r\n } else if (typeof value === 'string' && value) {\r\n const date = new Date(value);\r\n if (!isNaN(date.getTime())) {\r\n input.value = date.toISOString().split('T')[0];\r\n }\r\n }\r\n\r\n // Event handlers\r\n input.addEventListener('blur', () => {\r\n onSave(input.value ? new Date(input.value) : null);\r\n });\r\n\r\n input.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSave(input.value ? new Date(input.value) : null);\r\n if (onMove) onMove(e.shiftKey ? 'up' : 'down');\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSave(input.value ? new Date(input.value) : null);\r\n if (onMove) onMove(e.shiftKey ? 'left' : 'right');\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onCancel();\r\n }\r\n });\r\n\r\n return input;\r\n }\r\n\r\n /**\r\n * Create checkbox editor\r\n */\r\n private static createCheckboxEditor(\r\n value: CellValue,\r\n _options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLElement {\r\n const container = document.createElement('div');\r\n container.className = 'velox-edit-checkbox-container';\r\n\r\n const checkbox = document.createElement('input');\r\n checkbox.className = 'velox-edit-checkbox';\r\n checkbox.type = 'checkbox';\r\n checkbox.checked = Boolean(value);\r\n\r\n container.appendChild(checkbox);\r\n\r\n // Event handlers\r\n checkbox.addEventListener('change', () => {\r\n console.log('📦 Checkbox change event', checkbox.checked);\r\n onSave(checkbox.checked);\r\n });\r\n\r\n // blur 이벤트 제거 - change 이벤트로 충분함 (중복 호출 방지)\r\n\r\n checkbox.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n checkbox.checked = !checkbox.checked;\r\n onSave(checkbox.checked);\r\n if (e.key === 'Enter' && onMove) onMove(e.shiftKey ? 'up' : 'down');\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSave(checkbox.checked);\r\n if (onMove) onMove(e.shiftKey ? 'left' : 'right');\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onCancel();\r\n }\r\n });\r\n\r\n return container;\r\n }\r\n\r\n /**\r\n * Create custom editor using renderer function\r\n */\r\n private static createCustomEditor(\r\n value: CellValue,\r\n options: EditorOptions,\r\n onSave: (value: CellValue) => void,\r\n onCancel: () => void,\r\n onMove?: (direction: 'up' | 'down' | 'left' | 'right') => void\r\n ): HTMLElement {\r\n const container = document.createElement('div');\r\n container.className = 'velox-edit-custom';\r\n\r\n if (options.renderer) {\r\n options.renderer(container, value, onSave, onCancel);\r\n } else {\r\n // Fallback to text editor\r\n return this.createTextEditor(value, { type: 'text' }, onSave, onCancel, onMove);\r\n }\r\n\r\n return container;\r\n }\r\n}\r\n","/**\r\n * VeloxGrid - GridTooltip\r\n * @description Cell tooltip management for hover information display\r\n * Phase 12.3: Cell Tooltip\r\n */\r\n\r\nimport type { CellValue, RowData, ColumnDefinition } from '../types';\r\n\r\nexport class GridTooltip {\r\n private tooltip: HTMLElement | null = null;\r\n private currentCell: HTMLElement | null = null;\r\n private hideTimeout: number | null = null;\r\n private readonly HIDE_DELAY = 100; // ms\r\n\r\n constructor(private container: HTMLElement) {\r\n this.createTooltipElement();\r\n }\r\n\r\n /**\r\n * Create tooltip element\r\n */\r\n private createTooltipElement(): void {\r\n this.tooltip = document.createElement('div');\r\n this.tooltip.className = 'velox-tooltip';\r\n this.tooltip.style.display = 'none';\r\n this.tooltip.style.position = 'absolute';\r\n this.tooltip.style.pointerEvents = 'none';\r\n this.container.appendChild(this.tooltip);\r\n }\r\n\r\n /**\r\n * Show tooltip for a cell\r\n */\r\n show(\r\n cell: HTMLElement,\r\n value: CellValue,\r\n row: RowData,\r\n column: ColumnDefinition\r\n ): void {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n\r\n this.currentCell = cell;\r\n\r\n // Get tooltip content\r\n let content: string | null = null;\r\n\r\n if (column.tooltip === true) {\r\n // Auto tooltip for long text\r\n content = this.getAutoTooltipContent(cell, value);\r\n } else if (typeof column.tooltip === 'function') {\r\n // Custom tooltip callback\r\n content = column.tooltip(value, row);\r\n }\r\n\r\n if (!content || !this.tooltip) {\r\n this.hide();\r\n return;\r\n }\r\n\r\n // Set content and show\r\n this.tooltip.textContent = content;\r\n this.tooltip.style.display = 'block';\r\n this.positionTooltip(cell);\r\n }\r\n\r\n /**\r\n * Get auto tooltip content for truncated text\r\n */\r\n private getAutoTooltipContent(cell: HTMLElement, value: CellValue): string | null {\r\n const content = cell.querySelector('.velox-cell-content');\r\n if (!content) return null;\r\n\r\n // Check if text is truncated\r\n const isOverflowing = content.scrollWidth > content.clientWidth ||\r\n content.scrollHeight > content.clientHeight;\r\n\r\n if (isOverflowing) {\r\n return String(value ?? '');\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Position tooltip relative to cell\r\n */\r\n private positionTooltip(cell: HTMLElement): void {\r\n if (!this.tooltip) return;\r\n\r\n const cellRect = cell.getBoundingClientRect();\r\n const containerRect = this.container.getBoundingClientRect();\r\n const tooltipRect = this.tooltip.getBoundingClientRect();\r\n\r\n // Default position: below the cell\r\n let top = cellRect.bottom - containerRect.top + 5;\r\n let left = cellRect.left - containerRect.left;\r\n\r\n // Check if tooltip would go outside viewport\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n\r\n // Adjust horizontal position\r\n if (cellRect.left + tooltipRect.width > viewportWidth) {\r\n left = cellRect.right - containerRect.left - tooltipRect.width;\r\n }\r\n\r\n // Adjust vertical position (show above if no space below)\r\n if (cellRect.bottom + tooltipRect.height + 5 > viewportHeight) {\r\n top = cellRect.top - containerRect.top - tooltipRect.height - 5;\r\n }\r\n\r\n this.tooltip.style.top = `${top}px`;\r\n this.tooltip.style.left = `${left}px`;\r\n }\r\n\r\n /**\r\n * Hide tooltip\r\n */\r\n hide(): void {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n }\r\n\r\n this.hideTimeout = window.setTimeout(() => {\r\n if (this.tooltip) {\r\n this.tooltip.style.display = 'none';\r\n this.tooltip.textContent = '';\r\n }\r\n this.currentCell = null;\r\n this.hideTimeout = null;\r\n }, this.HIDE_DELAY);\r\n }\r\n\r\n /**\r\n * Update tooltip position (for scroll events)\r\n */\r\n update(): void {\r\n if (this.currentCell && this.tooltip && this.tooltip.style.display !== 'none') {\r\n this.positionTooltip(this.currentCell);\r\n }\r\n }\r\n\r\n /**\r\n * Destroy tooltip\r\n */\r\n destroy(): void {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n }\r\n\r\n if (this.tooltip) {\r\n this.tooltip.remove();\r\n this.tooltip = null;\r\n }\r\n\r\n this.currentCell = null;\r\n }\r\n}\r\n","/**\r\n * GridRenderer - Rendering Module\r\n * Phase 8: Code Structure Optimization\r\n * \r\n * VeloxGrid의 렌더링 로직을 담당하는 모듈\r\n * - Header, Body, Cell 렌더링\r\n * - Row 생성 및 업데이트\r\n */\r\n\r\nimport type { ColumnDefinition, RowData, GridContext } from '../types';\r\nimport { createElement, addClass } from '../utils/dom';\r\nimport { formatValue } from '../utils/data';\r\n\r\nexport class GridRenderer {\r\n constructor(private ctx: GridContext) {}\r\n\r\n /**\r\n * 전체 그리드 렌더링\r\n */\r\n render(): void {\r\n const state = this.ctx.getState();\r\n console.log('🎨 GridRenderer.render() called', { editing: state.edit.editing });\r\n this.renderHeader();\r\n this.renderBody();\r\n this.renderFooter();\r\n this.updateLoadingState();\r\n console.log('🎨 GridRenderer.render() completed', { editing: state.edit.editing });\r\n }\r\n\r\n /**\r\n * 헤더 렌더링 (Phase 14: Fixed Right 지원)\r\n */\r\n renderHeader(): void {\r\n const ctx = this.ctx;\r\n\r\n // 1. Fixed left header (only when colCount > 0)\r\n if (ctx.fixedLeftHeader) {\r\n ctx.fixedLeftHeader.innerHTML = '';\r\n const headerRow = createElement('div', 'velox-header-row');\r\n \r\n // Fixed left columns (Special + Data columns when colCount > 0)\r\n ctx.getFixedLeftColumns().forEach((col: ColumnDefinition) => {\r\n if (col.field === '__drag') {\r\n // Drag handle placeholder\r\n const dragPlaceholder = createElement('div', 'velox-row-drag-handle');\r\n dragPlaceholder.style.visibility = 'hidden';\r\n headerRow.appendChild(dragPlaceholder);\r\n } else if (col.field === '__checkbox') {\r\n // CheckBar header\r\n headerRow.appendChild(this.createHeaderCheckbarCell());\r\n } else if (col.field === '__rownum') {\r\n // Row numbers header\r\n const rowNumCell = createElement('div', 'velox-header-cell velox-rownumber-cell');\r\n rowNumCell.textContent = '#';\r\n headerRow.appendChild(rowNumCell);\r\n } else {\r\n // Data column\r\n headerRow.appendChild(this.createHeaderCell(col));\r\n }\r\n });\r\n \r\n ctx.fixedLeftHeader.appendChild(headerRow);\r\n }\r\n\r\n // 2. Scrollable header (includes special columns when colCount = 0)\r\n const headerRow = createElement('div', 'velox-header-row');\r\n \r\n ctx.getScrollableColumns().forEach((col: ColumnDefinition) => {\r\n if (col.field === '__drag') {\r\n // Drag handle placeholder\r\n const dragPlaceholder = createElement('div', 'velox-row-drag-handle');\r\n dragPlaceholder.style.visibility = 'hidden';\r\n headerRow.appendChild(dragPlaceholder);\r\n } else if (col.field === '__checkbox') {\r\n // CheckBar header\r\n headerRow.appendChild(this.createHeaderCheckbarCell());\r\n } else if (col.field === '__rownum') {\r\n // Row numbers header\r\n const rowNumCell = createElement('div', 'velox-header-cell velox-rownumber-cell');\r\n rowNumCell.textContent = '#';\r\n headerRow.appendChild(rowNumCell);\r\n } else {\r\n // Data column\r\n headerRow.appendChild(this.createHeaderCell(col));\r\n }\r\n });\r\n \r\n ctx.headerElement.innerHTML = '';\r\n ctx.headerElement.appendChild(headerRow);\r\n\r\n // 3. Fixed right header (Phase 14)\r\n if (ctx.fixedRightHeader) {\r\n ctx.fixedRightHeader.innerHTML = '';\r\n const fixedRightRow = createElement('div', 'velox-header-row');\r\n \r\n ctx.getFixedRightColumns().forEach((col: ColumnDefinition) => \r\n fixedRightRow.appendChild(this.createHeaderCell(col))\r\n );\r\n \r\n ctx.fixedRightHeader.appendChild(fixedRightRow);\r\n \r\n // Calculate and set explicit width for Fixed Right container\r\n this.updateFixedRightWidth();\r\n }\r\n }\r\n\r\n /**\r\n * CheckBar 헤더 셀 생성\r\n */\r\n private createHeaderCheckbarCell(): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const state = ctx.getState();\r\n \r\n const cell = createElement('div', 'velox-header-cell velox-checkbox-cell');\r\n const checkBar = options.checkBar!;\r\n \r\n if (checkBar.showAll && !checkBar.exclusive) {\r\n const checkbox = createElement('input', 'velox-checkbox') as HTMLInputElement;\r\n checkbox.type = 'checkbox';\r\n \r\n const checkableCount = state.checkBar.checkableRows.size;\r\n const checkedCount = state.checkBar.checkedRows.size;\r\n const allChecked = checkableCount > 0 && checkedCount === checkableCount;\r\n const someChecked = checkedCount > 0 && !allChecked;\r\n \r\n checkbox.checked = allChecked;\r\n checkbox.indeterminate = someChecked;\r\n checkbox.addEventListener('change', () => ctx.checkAll(checkbox.checked));\r\n cell.appendChild(checkbox);\r\n } else if (checkBar.exclusive) {\r\n const label = createElement('span', 'velox-checkbox-label');\r\n label.textContent = '선택';\r\n cell.appendChild(label);\r\n }\r\n \r\n return cell;\r\n }\r\n\r\n /**\r\n * 헤더 셀 생성\r\n */\r\n createHeaderCell(column: ColumnDefinition): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const state = ctx.getState();\r\n \r\n const cell = createElement('div', 'velox-header-cell');\r\n cell.dataset.field = column.field;\r\n \r\n const align = column.headerAlign || column.align || 'left';\r\n addClass(cell, `velox-header-cell--align-${align}`);\r\n\r\n if (column.width) {\r\n cell.style.width = `${column.width}px`;\r\n cell.style.minWidth = `${column.minWidth || column.width}px`;\r\n cell.style.maxWidth = `${column.width}px`;\r\n cell.style.flexShrink = '0';\r\n } else {\r\n cell.style.flex = '1';\r\n cell.style.minWidth = `${column.minWidth || 100}px`;\r\n }\r\n\r\n if (column.headerClass) addClass(cell, column.headerClass);\r\n if (options.sortable && column.sortable !== false) {\r\n addClass(cell, 'velox-header-cell--sortable');\r\n const sortState = state.sort.find((s: any) => s.field === column.field);\r\n if (sortState?.direction) addClass(cell, 'velox-header-cell--sorted');\r\n }\r\n\r\n const contentWrapper = createElement('div', 'velox-header-content');\r\n \r\n // Column drag handle\r\n const dragHandle = createElement('span', 'velox-column-drag-handle');\r\n dragHandle.innerHTML = '⋮⋮';\r\n dragHandle.title = '드래그하여 컬럼 순서 변경';\r\n dragHandle.addEventListener('mousedown', (e) => ctx.startColumnDrag(e, column));\r\n contentWrapper.appendChild(dragHandle);\r\n \r\n const text = createElement('span', 'velox-header-text');\r\n text.textContent = column.header;\r\n contentWrapper.appendChild(text);\r\n\r\n cell.appendChild(contentWrapper);\r\n\r\n // Sort button (우측 정렬)\r\n if (options.sortable && column.sortable !== false) {\r\n const sortBtn = createElement('button', 'velox-sort-btn');\r\n const sortState = state.sort.find((s: any) => s.field === column.field);\r\n \r\n if (sortState?.direction === 'asc') {\r\n addClass(sortBtn, 'velox-sort-btn--asc');\r\n sortBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 4.5h14.25M3 9h9.75M3 13.5h5.25m5.25-.75L17.25 9m0 0L21 12.75M17.25 9v12\" /></svg>`;\r\n } else if (sortState?.direction === 'desc') {\r\n addClass(sortBtn, 'velox-sort-btn--desc');\r\n sortBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0-3.75-3.75M17.25 21 21 17.25\" /></svg>`;\r\n } else {\r\n sortBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0-3.75-3.75M17.25 21 21 17.25\" /></svg>`;\r\n }\r\n \r\n if (sortState?.direction) addClass(sortBtn, 'velox-sort-btn--active');\r\n sortBtn.title = '정렬';\r\n sortBtn.addEventListener('click', (e) => { \r\n e.stopPropagation(); \r\n ctx.handleSort(column.field); \r\n });\r\n cell.appendChild(sortBtn);\r\n }\r\n\r\n // Filter button\r\n if (options.filterable && column.filterable !== false) {\r\n const filterBtn = createElement('button', 'velox-filter-btn');\r\n filterBtn.innerHTML = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z\" /></svg>`;\r\n const hasFilter = state.filter?.conditions.some((c: any) => c.field === column.field);\r\n if (hasFilter) addClass(filterBtn, 'velox-filter-btn--active');\r\n filterBtn.addEventListener('click', (e) => { \r\n e.stopPropagation(); \r\n ctx.showFilterPopup(column, filterBtn);\r\n });\r\n cell.appendChild(filterBtn);\r\n }\r\n \r\n // Column menu button\r\n const menuBtn = createElement('button', 'velox-column-menu-btn');\r\n menuBtn.innerHTML = '⋯';\r\n menuBtn.title = '컬럼 메뉴';\r\n menuBtn.addEventListener('click', (e) => { \r\n e.stopPropagation(); \r\n ctx.showColumnMenu(column, menuBtn);\r\n });\r\n cell.appendChild(menuBtn);\r\n\r\n // Resize handle\r\n if (options.resizable && column.resizable !== false) {\r\n const handle = createElement('div', 'velox-resize-handle');\r\n handle.addEventListener('mousedown', (e) => ctx.startResize(e, column));\r\n cell.appendChild(handle);\r\n }\r\n\r\n return cell;\r\n }\r\n\r\n /**\r\n * 바디 렌더링 (Phase 14: Fixed Right 지원)\r\n */\r\n renderBody(): void {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const visibleRows = ctx.getVisibleRows();\r\n const virtualState = ctx.getVirtualState();\r\n const rowHeight = options.rowHeight || 40;\r\n\r\n // 1. Fixed left body (Special + Fixed Left Data)\r\n if (ctx.fixedLeftBodyInner) {\r\n ctx.fixedLeftBodyInner.innerHTML = '';\r\n if (options.virtualScroll) {\r\n ctx.fixedLeftBodyInner.style.height = `${virtualState.totalHeight}px`;\r\n ctx.fixedLeftBodyInner.style.position = 'relative';\r\n } else {\r\n ctx.fixedLeftBodyInner.style.height = '';\r\n ctx.fixedLeftBodyInner.style.position = '';\r\n }\r\n\r\n visibleRows.forEach(({ data, index }) => {\r\n const row = this.createRowBase(data, index, 'fixedLeft');\r\n if (options.virtualScroll) {\r\n row.style.position = 'absolute';\r\n row.style.top = `${index * rowHeight}px`;\r\n row.style.left = '0';\r\n row.style.right = '0';\r\n }\r\n ctx.fixedLeftBodyInner!.appendChild(row);\r\n });\r\n }\r\n\r\n // 2. Scrollable body\r\n ctx.bodyInner.innerHTML = '';\r\n if (options.virtualScroll) {\r\n ctx.bodyInner.style.height = `${virtualState.totalHeight}px`;\r\n ctx.bodyInner.style.position = 'relative';\r\n } else {\r\n ctx.bodyInner.style.height = '';\r\n ctx.bodyInner.style.position = '';\r\n }\r\n\r\n if (visibleRows.length === 0) {\r\n const emptyDiv = createElement('div', 'velox-empty');\r\n emptyDiv.textContent = options.emptyMessage || '데이터가 없습니다.';\r\n ctx.bodyInner.appendChild(emptyDiv);\r\n return;\r\n }\r\n\r\n visibleRows.forEach(({ data, index }) => {\r\n const row = this.createRowBase(data, index, 'scrollable');\r\n if (options.virtualScroll) {\r\n row.style.position = 'absolute';\r\n row.style.top = `${index * rowHeight}px`;\r\n row.style.left = '0';\r\n row.style.right = '0';\r\n }\r\n ctx.bodyInner.appendChild(row);\r\n });\r\n\r\n // 3. Fixed right body (Phase 14)\r\n if (ctx.fixedRightBodyInner) {\r\n ctx.fixedRightBodyInner.innerHTML = '';\r\n if (options.virtualScroll) {\r\n ctx.fixedRightBodyInner.style.height = `${virtualState.totalHeight}px`;\r\n ctx.fixedRightBodyInner.style.position = 'relative';\r\n } else {\r\n ctx.fixedRightBodyInner.style.height = '';\r\n ctx.fixedRightBodyInner.style.position = '';\r\n }\r\n\r\n visibleRows.forEach(({ data, index }) => {\r\n const row = this.createRowBase(data, index, 'fixedRight');\r\n if (options.virtualScroll) {\r\n row.style.position = 'absolute';\r\n row.style.top = `${index * rowHeight}px`;\r\n row.style.left = '0';\r\n row.style.right = '0';\r\n }\r\n ctx.fixedRightBodyInner!.appendChild(row);\r\n });\r\n \r\n // Ensure Fixed Right width is consistent with header\r\n this.updateFixedRightWidth();\r\n }\r\n }\r\n\r\n /**\r\n * Update Fixed Right container width based on columns\r\n * Phase 14: Ensure header and body alignment\r\n */\r\n private updateFixedRightWidth(): void {\r\n const ctx = this.ctx;\r\n if (!ctx.fixedRightContainer) return;\r\n \r\n const fixedRightColumns = ctx.getFixedRightColumns();\r\n if (fixedRightColumns.length === 0) return;\r\n \r\n // Calculate total width of fixed right columns\r\n let totalWidth = 0;\r\n fixedRightColumns.forEach((col: ColumnDefinition) => {\r\n totalWidth += col.width || col.minWidth || 100;\r\n });\r\n \r\n // Get scrollbar width from Fixed Right body\r\n const scrollbarWidth = this.getScrollbarWidth(ctx.fixedRightBody);\r\n \r\n // Set explicit width to Fixed Right container (including scrollbar)\r\n ctx.fixedRightContainer.style.width = `${totalWidth + scrollbarWidth}px`;\r\n ctx.fixedRightContainer.style.minWidth = `${totalWidth + scrollbarWidth}px`;\r\n ctx.fixedRightContainer.style.maxWidth = `${totalWidth + scrollbarWidth}px`;\r\n \r\n // Add padding to header to account for scrollbar\r\n if (ctx.fixedRightHeader && scrollbarWidth > 0) {\r\n ctx.fixedRightHeader.style.paddingRight = `${scrollbarWidth}px`;\r\n }\r\n \r\n // Add padding to footer to account for scrollbar\r\n if (ctx.fixedRightFooter && scrollbarWidth > 0) {\r\n ctx.fixedRightFooter.style.paddingRight = `${scrollbarWidth}px`;\r\n }\r\n }\r\n \r\n /**\r\n * Get scrollbar width of an element\r\n * Phase 14: For Fixed Right alignment\r\n */\r\n private getScrollbarWidth(element: HTMLElement | null): number {\r\n if (!element) return 0;\r\n \r\n // Calculate scrollbar width: offsetWidth - clientWidth\r\n const scrollbarWidth = element.offsetWidth - element.clientWidth;\r\n return scrollbarWidth;\r\n }\r\n\r\n /**\r\n * Row 생성 (통합 메서드)\r\n * @param area - 'fixedLeft' | 'scrollable' | 'fixedRight' (Phase 14)\r\n */\r\n createRowBase(rowData: RowData, rowIndex: number, area: 'fixedLeft' | 'scrollable' | 'fixedRight'): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const state = ctx.getState();\r\n \r\n const row = createElement('div', 'velox-row');\r\n row.dataset.rowIndex = String(rowIndex);\r\n\r\n // Alternating row style\r\n if (rowIndex % 2 === 1) addClass(row, 'velox-row--alt');\r\n \r\n // Selection state\r\n if (options.selectionStyle === 'row' && state.selection.selectedRows.has(rowIndex)) {\r\n addClass(row, 'velox-row--selected');\r\n }\r\n \r\n // CheckBar state\r\n if (area === 'fixedLeft' && state.checkBar.checkedRows.has(rowIndex)) {\r\n addClass(row, 'velox-row--checked');\r\n }\r\n\r\n // Row click handler\r\n row.addEventListener('click', (e) => {\r\n const target = e.target as HTMLElement;\r\n if (target.classList.contains('velox-checkbox')) return;\r\n if (target.classList.contains('velox-row-drag-handle')) return;\r\n ctx.handleRowClick(rowIndex, e);\r\n });\r\n\r\n // Double click (only for scrollable and fixedRight areas)\r\n if (area !== 'fixedLeft') {\r\n row.addEventListener('dblclick', (e) => ctx.handleRowDoubleClick(rowIndex, e));\r\n }\r\n\r\n // Content based on area (Phase 14)\r\n if (area === 'fixedLeft') {\r\n // Fixed left columns (includes special columns when colCount > 0)\r\n ctx.getFixedLeftColumns().forEach((col: ColumnDefinition) => {\r\n if (col.field === '__drag') {\r\n // Row drag handle\r\n const dragHandle = createElement('div', 'velox-row-drag-handle');\r\n dragHandle.innerHTML = '☰';\r\n dragHandle.title = '드래그하여 행 순서 변경';\r\n dragHandle.addEventListener('mousedown', (e) => ctx.startRowDrag(e, rowIndex, row));\r\n row.appendChild(dragHandle);\r\n } else if (col.field === '__checkbox') {\r\n // CheckBar\r\n row.appendChild(this.createCheckbarCell(rowIndex));\r\n } else if (col.field === '__rownum') {\r\n // Row numbers\r\n const rowNumCell = createElement('div', 'velox-cell velox-rownumber-cell');\r\n rowNumCell.textContent = String(rowIndex + 1);\r\n row.appendChild(rowNumCell);\r\n } else {\r\n // Data cell\r\n row.appendChild(this.createCell(rowData, rowIndex, col));\r\n }\r\n });\r\n } else if (area === 'scrollable') {\r\n // Scrollable columns (includes special columns when colCount = 0)\r\n ctx.getScrollableColumns().forEach((col: ColumnDefinition) => {\r\n if (col.field === '__drag') {\r\n // Row drag handle\r\n const dragHandle = createElement('div', 'velox-row-drag-handle');\r\n dragHandle.innerHTML = '☰';\r\n dragHandle.title = '드래그하여 행 순서 변경';\r\n dragHandle.addEventListener('mousedown', (e) => ctx.startRowDrag(e, rowIndex, row));\r\n row.appendChild(dragHandle);\r\n } else if (col.field === '__checkbox') {\r\n // CheckBar\r\n row.appendChild(this.createCheckbarCell(rowIndex));\r\n } else if (col.field === '__rownum') {\r\n // Row numbers\r\n const rowNumCell = createElement('div', 'velox-cell velox-rownumber-cell');\r\n rowNumCell.textContent = String(rowIndex + 1);\r\n row.appendChild(rowNumCell);\r\n } else {\r\n // Data cell\r\n row.appendChild(this.createCell(rowData, rowIndex, col));\r\n }\r\n });\r\n } else if (area === 'fixedRight') {\r\n // Fixed right columns (Phase 14)\r\n ctx.getFixedRightColumns().forEach((col: ColumnDefinition) => \r\n row.appendChild(this.createCell(rowData, rowIndex, col))\r\n );\r\n }\r\n\r\n return row;\r\n }\r\n\r\n /**\r\n * CheckBar 셀 생성\r\n */\r\n private createCheckbarCell(rowIndex: number): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const state = ctx.getState();\r\n \r\n const cell = createElement('div', 'velox-cell velox-checkbox-cell');\r\n const checkBar = options.checkBar!;\r\n const isCheckable = state.checkBar.checkableRows.has(rowIndex);\r\n const isChecked = state.checkBar.checkedRows.has(rowIndex);\r\n \r\n const input = createElement('input', 'velox-checkbox') as HTMLInputElement;\r\n input.type = checkBar.exclusive ? 'radio' : 'checkbox';\r\n input.name = checkBar.exclusive ? `${ctx.getGridId()}-check` : '';\r\n input.checked = isChecked;\r\n input.disabled = !isCheckable;\r\n \r\n if (!isCheckable) {\r\n addClass(cell, 'velox-checkbox-cell--disabled');\r\n }\r\n \r\n input.addEventListener('click', (e) => {\r\n console.log('✅ Checkbox clicked', { rowIndex, checked: input.checked });\r\n e.stopPropagation();\r\n });\r\n input.addEventListener('change', () => {\r\n console.log('🔄 Checkbox changed', { rowIndex, checked: input.checked });\r\n if (checkBar.exclusive) {\r\n // Edit 상태 보존\r\n const editState = { ...ctx.getState().edit };\r\n \r\n state.checkBar.checkedRows.clear();\r\n if (input.checked) {\r\n state.checkBar.checkedRows.add(rowIndex);\r\n }\r\n this.render();\r\n \r\n // Edit 중이었다면 상태 복원\r\n if (editState.editing && editState.rowIndex !== null && editState.field !== null) {\r\n ctx.getState().edit = editState;\r\n ctx.renderEditCell(editState.rowIndex, editState.field, editState.originalValue);\r\n }\r\n \r\n ctx.emitEvent('onCheckChange', rowIndex, input.checked);\r\n } else {\r\n ctx.checkItem(rowIndex, input.checked);\r\n }\r\n });\r\n \r\n cell.appendChild(input);\r\n return cell;\r\n }\r\n\r\n /**\r\n * Cell 생성\r\n */\r\n createCell(rowData: RowData, rowIndex: number, column: ColumnDefinition): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const state = ctx.getState();\r\n \r\n const cell = createElement('div', 'velox-cell');\r\n cell.dataset.field = column.field;\r\n cell.dataset.rowIndex = String(rowIndex);\r\n\r\n const align = column.align || 'left';\r\n addClass(cell, `velox-cell--align-${align}`);\r\n\r\n if (column.width) {\r\n cell.style.width = `${column.width}px`;\r\n cell.style.minWidth = `${column.minWidth || column.width}px`;\r\n cell.style.maxWidth = `${column.width}px`;\r\n cell.style.flexShrink = '0';\r\n } else {\r\n cell.style.flex = '1';\r\n cell.style.minWidth = `${column.minWidth || 100}px`;\r\n }\r\n\r\n if (column.cellClass) {\r\n const className = typeof column.cellClass === 'function'\r\n ? column.cellClass(rowData[column.field], rowData) : column.cellClass;\r\n if (className) addClass(cell, className);\r\n }\r\n\r\n const cellKey = `${rowIndex}:${column.field}`;\r\n if (state.selection.selectedCells.has(cellKey)) {\r\n addClass(cell, 'velox-cell--selected');\r\n }\r\n \r\n const focusedCell = state.selection.focusedCell;\r\n if (focusedCell && focusedCell.rowIndex === rowIndex && focusedCell.field === column.field) {\r\n addClass(cell, 'velox-cell--focused');\r\n }\r\n\r\n if (options.editable && column.editable !== false) {\r\n addClass(cell, 'velox-cell--editable');\r\n cell.addEventListener('dblclick', (e) => { \r\n // 이미 편집 중인 셀이면 더블클릭 무시\r\n if (cell.classList.contains('velox-cell--editing')) {\r\n console.log('🚫 Double click ignored - already editing');\r\n e.stopPropagation();\r\n e.preventDefault();\r\n return;\r\n }\r\n console.log('🖱️🖱️ Double click detected', { rowIndex, field: column.field });\r\n e.stopPropagation(); \r\n ctx.startEdit(rowIndex, column.field); \r\n });\r\n }\r\n\r\n const value = rowData[column.field];\r\n const content = createElement('span', 'velox-cell-content');\r\n\r\n if (column.renderer) content.innerHTML = column.renderer(value, rowData, column);\r\n else if (column.formatter) content.textContent = column.formatter(value, rowData, column);\r\n else content.textContent = formatValue(value, column.type);\r\n\r\n cell.appendChild(content);\r\n \r\n cell.addEventListener('click', (e) => {\r\n // 편집 중인 셀이면 클릭 무시 (단, interactive 요소는 예외)\r\n if (cell.classList.contains('velox-cell--editing')) {\r\n const target = e.target as HTMLElement;\r\n // input, select, button 등 interactive 요소는 이벤트 허용하되 전파는 중단\r\n if (target.tagName === 'INPUT' || \r\n target.tagName === 'SELECT' || \r\n target.tagName === 'BUTTON' ||\r\n target.tagName === 'TEXTAREA') {\r\n console.log('✅ Interactive element click allowed during edit');\r\n e.stopPropagation(); // 상위로 전파 막기 (document까지 가지 않도록)\r\n return;\r\n }\r\n console.log('🚫 Cell click ignored - editing mode (cell background)');\r\n e.stopPropagation();\r\n e.preventDefault();\r\n return;\r\n }\r\n ctx.handleCellClick(rowIndex, column.field, value, e);\r\n });\r\n \r\n cell.addEventListener('mousedown', (e) => {\r\n // 편집 중인 셀은 VeloxGrid에서 처리하므로 여기서는 무시\r\n if (cell.classList.contains('velox-cell--editing')) {\r\n console.log('🔒 Cell mousedown - editing mode (ignored in renderer)');\r\n return;\r\n }\r\n if (options.selectionStyle === 'block' && e.button === 0) {\r\n ctx.startBlockSelection(rowIndex, column.field);\r\n }\r\n });\r\n \r\n cell.addEventListener('mouseenter', () => {\r\n if (ctx.isBlockSelecting()) {\r\n ctx.updateBlockSelection(rowIndex, column.field);\r\n }\r\n });\r\n\r\n // Tooltip\r\n if (column.tooltip) {\r\n addClass(cell, 'velox-cell--has-tooltip');\r\n \r\n cell.addEventListener('mouseenter', () => ctx.showTooltip(cell, value, rowData, column));\r\n cell.addEventListener('mouseleave', () => ctx.hideTooltip());\r\n }\r\n\r\n return cell;\r\n }\r\n\r\n /**\r\n * Footer Summary 렌더링 (Phase 13, Phase 14: Fixed Right 지원)\r\n */\r\n renderFooter(): void {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n\r\n // Footer summary가 비활성화되어 있으면 건너뀨기\r\n if (!options.footerSummary?.visible) return;\r\n\r\n // 1. Fixed left footer (Special + Fixed Left Data)\r\n if (ctx.fixedLeftFooter) {\r\n ctx.fixedLeftFooter.innerHTML = '';\r\n const footerRow = createElement('div', 'velox-footer-row');\r\n \r\n // Row drag handle placeholder (only if rowDraggable is enabled)\r\n if (options.rowDraggable) {\r\n const dragPlaceholder = createElement('div', 'velox-row-drag-handle');\r\n dragPlaceholder.style.visibility = 'hidden';\r\n footerRow.appendChild(dragPlaceholder);\r\n }\r\n \r\n if (options.checkBar?.visible) {\r\n const checkboxCell = createElement('div', 'velox-footer-cell velox-checkbox-cell');\r\n footerRow.appendChild(checkboxCell);\r\n }\r\n \r\n // Fixed left columns (Special + Data columns from fixedOptions.colCount)\r\n ctx.getFixedLeftColumns().forEach((col: ColumnDefinition) => \r\n footerRow.appendChild(this.createFooterCell(col))\r\n );\r\n \r\n ctx.fixedLeftFooter.appendChild(footerRow);\r\n }\r\n\r\n // 2. Scrollable footer\r\n if (ctx.footerElement) {\r\n ctx.footerElement.innerHTML = '';\r\n const footerRow = createElement('div', 'velox-footer-row');\r\n \r\n // Row number placeholder in footer\r\n if (options.showRowNumbers) {\r\n const rowNumCell = createElement('div', 'velox-footer-cell velox-rownumber-cell');\r\n footerRow.appendChild(rowNumCell);\r\n }\r\n \r\n ctx.getScrollableColumns().forEach((col: ColumnDefinition) => \r\n footerRow.appendChild(this.createFooterCell(col))\r\n );\r\n ctx.footerElement.appendChild(footerRow);\r\n }\r\n\r\n // 3. Fixed right footer (Phase 14)\r\n if (ctx.fixedRightFooter) {\r\n ctx.fixedRightFooter.innerHTML = '';\r\n const fixedRightRow = createElement('div', 'velox-footer-row');\r\n \r\n ctx.getFixedRightColumns().forEach((col: ColumnDefinition) => \r\n fixedRightRow.appendChild(this.createFooterCell(col))\r\n );\r\n \r\n ctx.fixedRightFooter.appendChild(fixedRightRow);\r\n }\r\n }\r\n\r\n /**\r\n * Footer 셀 생성 (Phase 13)\r\n */\r\n private createFooterCell(column: ColumnDefinition): HTMLElement {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n \r\n const cell = createElement('div', 'velox-footer-cell');\r\n cell.dataset.field = column.field;\r\n\r\n // Alignment\r\n const align = column.align || 'left';\r\n addClass(cell, `velox-footer-cell--align-${align}`);\r\n\r\n // Width\r\n if (column.width) {\r\n cell.style.width = `${column.width}px`;\r\n cell.style.minWidth = `${column.minWidth || column.width}px`;\r\n } else {\r\n cell.style.flex = '1';\r\n cell.style.minWidth = `${column.minWidth || 100}px`;\r\n }\r\n\r\n // Summary 값 계산 및 표시\r\n const summaryConfig = options.footerSummary?.columns?.[column.field] || column.summary;\r\n \r\n if (summaryConfig) {\r\n const summaryValue = ctx.getSummaryValue(column.field);\r\n const content = createElement('span', 'velox-footer-content');\r\n \r\n // Label 표시\r\n if (summaryConfig.label) {\r\n const label = createElement('span', 'velox-footer-label');\r\n label.textContent = summaryConfig.label;\r\n content.appendChild(label);\r\n }\r\n \r\n // Value 표시\r\n const valueSpan = createElement('span', 'velox-footer-value');\r\n \r\n // Custom formatter 사용\r\n if (summaryConfig.formatter) {\r\n valueSpan.textContent = summaryConfig.formatter(summaryValue);\r\n } else {\r\n valueSpan.textContent = formatValue(summaryValue, column.type);\r\n }\r\n \r\n content.appendChild(valueSpan);\r\n cell.appendChild(content);\r\n \r\n // Custom className\r\n if (summaryConfig.className) {\r\n addClass(cell, summaryConfig.className);\r\n }\r\n }\r\n\r\n return cell;\r\n }\r\n\r\n /**\r\n * Loading 상태 업데이트\r\n */\r\n updateLoadingState(): void {\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n \r\n if (ctx.loadingOverlay) {\r\n ctx.loadingOverlay.style.display = options.loading ? 'flex' : 'none';\r\n }\r\n }\r\n\r\n /**\r\n * Row validation 상태 업데이트\r\n */\r\n updateRowValidationState(rowIndex: number): void {\r\n const ctx = this.ctx;\r\n const state = ctx.getState();\r\n \r\n const row = ctx.rootElement.querySelector(`[data-row-index=\"${rowIndex}\"]`) as HTMLElement;\r\n if (!row) return;\r\n\r\n const cells = row.querySelectorAll('.velox-cell');\r\n cells.forEach((cellEl: Element) => {\r\n const cell = cellEl as HTMLElement;\r\n const field = cell.dataset.field;\r\n if (!field) return;\r\n\r\n const column = state.columns.find((c: ColumnDefinition) => c.field === field);\r\n if (!column?.validation) return;\r\n\r\n // Validation은 VeloxGrid 내부에서 처리됨\r\n });\r\n }\r\n}\r\n","/**\r\n * GridFilterPopup - Filter Popup Module\r\n * Phase 8: Code Structure Optimization (Step 4)\r\n * \r\n * VeloxGrid의 필터 팝업 UI를 담당하는 모듈\r\n * - Filter 팝업 표시/숨김\r\n * - Filter 조건 적용/제거\r\n */\r\n\r\nimport type { ColumnDefinition, FilterOperator, CellValue, FilterCondition, GridContext } from '../types';\r\nimport { createElement } from '../utils/dom';\r\nimport { formatValue } from '../utils/data';\r\nimport type { VeloxGrid } from './VeloxGrid';\r\n\r\n// VeloxGrid는 GridContext를 구현하므로, 타입 안전성을 위해 GridContext 사용\r\ntype GridInstance = VeloxGrid & GridContext;\r\n\r\nexport class GridFilterPopup {\r\n private filterPopup: HTMLElement | null = null;\r\n private boundHandleOutsideClick: (e: MouseEvent) => void;\r\n\r\n constructor(private ctx: GridInstance) {\r\n this.boundHandleOutsideClick = this.handleOutsideClick.bind(this);\r\n }\r\n\r\n /**\r\n * Filter 팝업 표시\r\n */\r\n showFilterPopup(column: ColumnDefinition, anchor: HTMLElement): void {\r\n this.closeFilterPopup();\r\n\r\n const ctx = this.ctx;\r\n const state = ctx.getState();\r\n const popup = createElement('div', 'velox-filter-popup');\r\n const rect = anchor.getBoundingClientRect();\r\n const gridRect = ctx.rootElement.getBoundingClientRect();\r\n\r\n popup.style.top = `${rect.bottom - gridRect.top + 5}px`;\r\n popup.style.left = `${Math.max(0, rect.left - gridRect.left - 100)}px`;\r\n\r\n const uniqueValues = [...new Set(state.data.map((row: any) => row[column.field]))]\r\n .filter((v: any) => v !== null && v !== undefined)\r\n .sort();\r\n\r\n const currentFilter = state.filter?.conditions.find((c: FilterCondition) => c.field === column.field);\r\n\r\n // Operator select\r\n const operatorSelect = createElement('select', 'velox-filter-operator') as HTMLSelectElement;\r\n const operators: { value: FilterOperator; label: string }[] = [\r\n { value: 'contains', label: '포함' },\r\n { value: 'equals', label: '같음' },\r\n { value: 'notEquals', label: '같지 않음' },\r\n { value: 'startsWith', label: '시작' },\r\n { value: 'endsWith', label: '끝' },\r\n { value: 'greaterThan', label: '>' },\r\n { value: 'lessThan', label: '<' },\r\n { value: 'greaterThanOrEqual', label: '>=' },\r\n { value: 'lessThanOrEqual', label: '<=' },\r\n { value: 'isEmpty', label: '비어있음' },\r\n { value: 'isNotEmpty', label: '비어있지 않음' },\r\n ];\r\n\r\n operators.forEach(op => {\r\n const option = createElement('option') as HTMLOptionElement;\r\n option.value = op.value;\r\n option.textContent = op.label;\r\n if (currentFilter?.operator === op.value) option.selected = true;\r\n operatorSelect.appendChild(option);\r\n });\r\n popup.appendChild(operatorSelect);\r\n\r\n // Value input\r\n const valueInput = createElement('input', 'velox-filter-input') as HTMLInputElement;\r\n valueInput.type = column.type === 'number' ? 'number' : 'text';\r\n valueInput.placeholder = '값 입력...';\r\n if (currentFilter?.value !== undefined) valueInput.value = String(currentFilter.value);\r\n popup.appendChild(valueInput);\r\n\r\n // Quick select list\r\n if (uniqueValues.length > 0 && uniqueValues.length <= 15) {\r\n const listContainer = createElement('div', 'velox-filter-list');\r\n const listLabel = createElement('div', 'velox-filter-list-label');\r\n listLabel.textContent = '빠른 선택:';\r\n listContainer.appendChild(listLabel);\r\n\r\n uniqueValues.slice(0, 10).forEach((value: any) => {\r\n const item = createElement('div', 'velox-filter-list-item');\r\n item.textContent = formatValue(value, column.type);\r\n item.addEventListener('click', () => {\r\n this.applyColumnFilter(column.field, 'equals', value);\r\n this.closeFilterPopup();\r\n });\r\n listContainer.appendChild(item);\r\n });\r\n popup.appendChild(listContainer);\r\n }\r\n\r\n // Buttons\r\n const btnContainer = createElement('div', 'velox-filter-buttons');\r\n \r\n const applyBtn = createElement('button', 'velox-filter-apply');\r\n applyBtn.textContent = '적용';\r\n applyBtn.addEventListener('click', () => {\r\n const operator = operatorSelect.value as FilterOperator;\r\n const value = column.type === 'number' ? parseFloat(valueInput.value) : valueInput.value;\r\n this.applyColumnFilter(column.field, operator, value);\r\n this.closeFilterPopup();\r\n });\r\n btnContainer.appendChild(applyBtn);\r\n\r\n const clearBtn = createElement('button', 'velox-filter-clear');\r\n clearBtn.textContent = '해제';\r\n clearBtn.addEventListener('click', () => {\r\n this.removeColumnFilter(column.field);\r\n this.closeFilterPopup();\r\n });\r\n btnContainer.appendChild(clearBtn);\r\n\r\n popup.appendChild(btnContainer);\r\n this.filterPopup = popup;\r\n ctx.rootElement.appendChild(popup);\r\n\r\n setTimeout(() => document.addEventListener('click', this.boundHandleOutsideClick), 0);\r\n valueInput.focus();\r\n }\r\n\r\n /**\r\n * Filter 팝업 닫기\r\n */\r\n closeFilterPopup(): void {\r\n if (this.filterPopup) {\r\n this.filterPopup.remove();\r\n this.filterPopup = null;\r\n document.removeEventListener('click', this.boundHandleOutsideClick);\r\n }\r\n }\r\n\r\n /**\r\n * 외부 클릭 핸들러\r\n */\r\n private handleOutsideClick(e: MouseEvent): void {\r\n if (this.filterPopup && !this.filterPopup.contains(e.target as Node)) {\r\n this.closeFilterPopup();\r\n }\r\n }\r\n\r\n /**\r\n * Column filter 적용\r\n */\r\n applyColumnFilter(field: string, operator: FilterOperator, value: CellValue): void {\r\n const ctx = this.ctx;\r\n const state = ctx.getState();\r\n const newCondition: FilterCondition = { field, operator, value };\r\n \r\n if (state.filter) {\r\n const conditions = state.filter.conditions.filter((c: FilterCondition) => c.field !== field);\r\n conditions.push(newCondition);\r\n state.filter = { conditions, logic: 'and' };\r\n } else {\r\n state.filter = { conditions: [newCondition], logic: 'and' };\r\n }\r\n \r\n ctx.clearSelectionState();\r\n ctx.applyDataTransformations();\r\n ctx.render();\r\n ctx.emitEvent('onFilter', state.filter);\r\n }\r\n\r\n /**\r\n * Column filter 제거\r\n */\r\n removeColumnFilter(field: string): void {\r\n const ctx = this.ctx;\r\n const state = ctx.getState();\r\n \r\n if (state.filter) {\r\n const conditions = state.filter.conditions.filter((c: FilterCondition) => c.field !== field);\r\n state.filter = conditions.length === 0 ? null : { conditions, logic: 'and' };\r\n \r\n ctx.clearSelectionState();\r\n ctx.applyDataTransformations();\r\n ctx.render();\r\n \r\n if (state.filter) {\r\n ctx.emitEvent('onFilter', state.filter);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Filter 팝업이 열려있는지 확인\r\n */\r\n isOpen(): boolean {\r\n return this.filterPopup !== null;\r\n }\r\n}\r\n","/**\r\n * GridColumnMenu - Column Menu Module\r\n * Phase 8: Code Structure Optimization (Step 5)\r\n * \r\n * VeloxGrid의 컬럼 메뉴 UI를 담당하는 모듈\r\n * - Column 메뉴 표시/숨김\r\n * - 정렬, 숨기기, 고정 등의 기능 제공\r\n */\r\n\r\nimport type { ColumnDefinition, ContextMenuItem, ContextMenuContext, GridContext } from '../types';\r\nimport { createElement, addClass } from '../utils/dom';\r\nimport type { VeloxGrid } from './VeloxGrid';\r\n\r\n// VeloxGrid는 GridContext를 구현하므로, 타입 안전성을 위해 GridContext 사용\r\ntype GridInstance = VeloxGrid & GridContext;\r\n\r\nexport class GridColumnMenu {\r\n private columnMenuPopup: HTMLElement | null = null;\r\n private boundHandleOutsideClick: (e: MouseEvent) => void;\r\n\r\n constructor(private ctx: GridInstance) {\r\n this.boundHandleOutsideClick = this.handleOutsideClick.bind(this);\r\n }\r\n\r\n /**\r\n * Column 메뉴 표시\r\n */\r\n showColumnMenu(column: ColumnDefinition, anchor: HTMLElement): void {\r\n this.closeColumnMenu();\r\n\r\n const ctx = this.ctx;\r\n const options = ctx.getOptions();\r\n const menu = createElement('div', 'velox-column-menu');\r\n const rect = anchor.getBoundingClientRect();\r\n const gridRect = ctx.rootElement.getBoundingClientRect();\r\n\r\n menu.style.top = `${rect.bottom - gridRect.top + 5}px`;\r\n menu.style.left = `${rect.left - gridRect.left}px`;\r\n\r\n // Create context for custom menu items\r\n const context: ContextMenuContext = {\r\n field: column.field,\r\n column,\r\n selectedRows: ctx.getSelectedRows(),\r\n selectedCells: ctx.getSelectedCells(),\r\n grid: ctx,\r\n };\r\n\r\n // Get menu items (custom or default)\r\n const menuConfig = options.contextMenu;\r\n const showDefault = menuConfig?.showDefaultItems !== false;\r\n const customItems = menuConfig?.headerItems || [];\r\n\r\n // Default menu items\r\n const defaultItems: ContextMenuItem[] = [\r\n { \r\n id: 'sort-asc', \r\n label: '오름차순 정렬', \r\n icon: '↑', \r\n action: () => ctx.sort(column.field, 'asc') \r\n },\r\n { \r\n id: 'sort-desc', \r\n label: '내림차순 정렬', \r\n icon: '↓', \r\n action: () => ctx.sort(column.field, 'desc') \r\n },\r\n { \r\n id: 'sort-clear', \r\n label: '정렬 해제', \r\n icon: '✕', \r\n action: () => ctx.clearSort() \r\n },\r\n { type: 'separator' },\r\n { \r\n id: 'hide', \r\n label: '컬럼 숨기기', \r\n icon: '👁', \r\n action: () => ctx.hideColumn(column.field) \r\n },\r\n { \r\n id: 'autofit', \r\n label: '컬럼 너비 자동', \r\n icon: '↔', \r\n action: () => ctx.autoFitColumn(column.field) \r\n },\r\n { \r\n id: 'autofit-all', \r\n label: '모든 컬럼 자동', \r\n icon: '⇔', \r\n action: () => ctx.autoFitAllColumns() \r\n },\r\n { type: 'separator' },\r\n { \r\n id: 'fix-left', \r\n label: '왼쪽에 고정', \r\n icon: '◀', \r\n action: () => ctx.fixColumn(column.field, 'left') \r\n },\r\n { \r\n id: 'unfix', \r\n label: '고정 해제', \r\n icon: '◇', \r\n action: () => ctx.fixColumn(column.field, false) \r\n },\r\n ];\r\n\r\n // Combine items\r\n let items: ContextMenuItem[] = [];\r\n if (showDefault) {\r\n items = [...defaultItems];\r\n if (customItems.length > 0) {\r\n items.push({ type: 'separator' });\r\n items.push(...customItems);\r\n }\r\n } else {\r\n items = customItems;\r\n }\r\n\r\n // Render menu items\r\n items.forEach(item => {\r\n // Check visibility\r\n const isVisible = typeof item.visible === 'function' \r\n ? item.visible(context) \r\n : item.visible !== false;\r\n if (!isVisible) return;\r\n\r\n if (item.type === 'separator') {\r\n const sep = createElement('div', 'velox-column-menu-separator');\r\n menu.appendChild(sep);\r\n } else {\r\n const menuItem = createElement('div', 'velox-column-menu-item');\r\n if (item.className) addClass(menuItem, item.className);\r\n \r\n // Check disabled state\r\n const isDisabled = typeof item.disabled === 'function'\r\n ? item.disabled(context)\r\n : item.disabled === true;\r\n if (isDisabled) addClass(menuItem, 'velox-column-menu-item--disabled');\r\n\r\n // Build item content\r\n let html = '';\r\n if (item.icon) html += `<span class=\"velox-column-menu-icon\">${item.icon}</span>`;\r\n html += `<span class=\"velox-column-menu-label\">${item.label || ''}</span>`;\r\n if (item.shortcut) html += `<span class=\"velox-column-menu-shortcut\">${item.shortcut}</span>`;\r\n menuItem.innerHTML = html;\r\n\r\n if (!isDisabled) {\r\n menuItem.addEventListener('click', () => {\r\n item.action?.(context);\r\n this.closeColumnMenu();\r\n });\r\n }\r\n menu.appendChild(menuItem);\r\n }\r\n });\r\n\r\n this.columnMenuPopup = menu;\r\n ctx.rootElement.appendChild(menu);\r\n\r\n // Add outside click listener with delay to avoid immediate close\r\n setTimeout(() => document.addEventListener('click', this.boundHandleOutsideClick), 0);\r\n }\r\n\r\n /**\r\n * Column 메뉴 닫기\r\n */\r\n closeColumnMenu(): void {\r\n if (this.columnMenuPopup) {\r\n this.columnMenuPopup.remove();\r\n this.columnMenuPopup = null;\r\n document.removeEventListener('click', this.boundHandleOutsideClick);\r\n }\r\n }\r\n\r\n /**\r\n * 외부 클릭 핸들러\r\n */\r\n private handleOutsideClick(e: MouseEvent): void {\r\n if (this.columnMenuPopup && !this.columnMenuPopup.contains(e.target as Node)) {\r\n this.closeColumnMenu();\r\n }\r\n }\r\n\r\n /**\r\n * Column 메뉴가 열려있는지 확인\r\n */\r\n isOpen(): boolean {\r\n return this.columnMenuPopup !== null;\r\n }\r\n}\r\n","/**\r\n * GridDragManager - Drag & Drop Module\r\n * Phase 8: Code Structure Optimization (Step 6)\r\n * \r\n * VeloxGrid의 드래그 앤 드롭 기능을 담당하는 모듈\r\n * - Column 드래그 앤 드롭 (순서 변경)\r\n * - Row 드래그 앤 드롭 (순서 변경)\r\n * - Resize 핸들링\r\n */\r\n\r\nimport type { ColumnDefinition, GridContext } from '../types';\r\nimport { createElement, addClass, removeClass } from '../utils/dom';\r\nimport type { VeloxGrid } from './VeloxGrid';\r\n\r\n// VeloxGrid는 GridContext를 구현하므로, 타입 안전성을 위해 GridContext 사용\r\ntype GridInstance = VeloxGrid & GridContext;\r\n\r\ninterface ColumnDragState {\r\n field: string;\r\n startX: number;\r\n element: HTMLElement | null;\r\n}\r\n\r\ninterface RowDragState {\r\n index: number;\r\n startY: number;\r\n element: HTMLElement | null;\r\n}\r\n\r\ninterface ResizeState {\r\n column: ColumnDefinition;\r\n startX: number;\r\n startWidth: number;\r\n}\r\n\r\nexport class GridDragManager {\r\n private columnDragging: ColumnDragState | null = null;\r\n private rowDragging: RowDragState | null = null;\r\n private resizing: ResizeState | null = null;\r\n\r\n private boundHandleColumnDragMove: (e: MouseEvent) => void;\r\n private boundHandleColumnDragEnd: (e: MouseEvent) => void;\r\n private boundHandleRowDragMove: (e: MouseEvent) => void;\r\n private boundHandleRowDragEnd: (e: MouseEvent) => void;\r\n private boundHandleResizeMove: (e: MouseEvent) => void;\r\n private boundHandleResizeEnd: (e: MouseEvent) => void;\r\n\r\n constructor(private ctx: GridInstance) {\r\n this.boundHandleColumnDragMove = this.handleColumnDragMove.bind(this);\r\n this.boundHandleColumnDragEnd = this.handleColumnDragEnd.bind(this);\r\n this.boundHandleRowDragMove = this.handleRowDragMove.bind(this);\r\n this.boundHandleRowDragEnd = this.handleRowDragEnd.bind(this);\r\n this.boundHandleResizeMove = this.handleResizeMove.bind(this);\r\n this.boundHandleResizeEnd = this.handleResizeEnd.bind(this);\r\n }\r\n\r\n // ============================================\r\n // Column Drag & Drop\r\n // ============================================\r\n\r\n /**\r\n * Column 드래그 시작\r\n */\r\n startColumnDrag(e: MouseEvent, column: ColumnDefinition): void {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n this.columnDragging = {\r\n field: column.field,\r\n startX: e.clientX,\r\n element: null,\r\n };\r\n \r\n const indicator = createElement('div', 'velox-column-drag-indicator');\r\n indicator.textContent = column.header;\r\n indicator.style.position = 'fixed';\r\n indicator.style.left = `${e.clientX}px`;\r\n indicator.style.top = `${e.clientY}px`;\r\n document.body.appendChild(indicator);\r\n this.columnDragging.element = indicator;\r\n\r\n document.addEventListener('mousemove', this.boundHandleColumnDragMove);\r\n document.addEventListener('mouseup', this.boundHandleColumnDragEnd);\r\n addClass(document.body, 'velox-no-select');\r\n }\r\n\r\n /**\r\n * Column 드래그 이동\r\n */\r\n private handleColumnDragMove(e: MouseEvent): void {\r\n const ctx = this.ctx;\r\n\r\n if (!this.columnDragging?.element) return;\r\n \r\n this.columnDragging.element.style.left = `${e.clientX + 10}px`;\r\n this.columnDragging.element.style.top = `${e.clientY + 10}px`;\r\n \r\n const target = document.elementFromPoint(e.clientX, e.clientY);\r\n const headerCell = target?.closest('.velox-header-cell') as HTMLElement;\r\n \r\n ctx.headerElement.querySelectorAll('.velox-header-cell--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-header-cell--drop-target');\r\n });\r\n \r\n if (headerCell && headerCell.dataset.field !== this.columnDragging.field) {\r\n addClass(headerCell, 'velox-header-cell--drop-target');\r\n }\r\n }\r\n\r\n /**\r\n * Column 드래그 종료\r\n */\r\n private handleColumnDragEnd(e: MouseEvent): void {\r\n const ctx = this.ctx;\r\n\r\n if (!this.columnDragging) return;\r\n \r\n const sourceField = this.columnDragging.field;\r\n \r\n const target = document.elementFromPoint(e.clientX, e.clientY);\r\n const headerCell = target?.closest('.velox-header-cell') as HTMLElement;\r\n const targetField = headerCell?.dataset.field;\r\n \r\n if (this.columnDragging.element) {\r\n this.columnDragging.element.remove();\r\n }\r\n ctx.headerElement.querySelectorAll('.velox-header-cell--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-header-cell--drop-target');\r\n });\r\n \r\n document.removeEventListener('mousemove', this.boundHandleColumnDragMove);\r\n document.removeEventListener('mouseup', this.boundHandleColumnDragEnd);\r\n removeClass(document.body, 'velox-no-select');\r\n \r\n if (targetField && targetField !== sourceField) {\r\n ctx.reorderColumn(sourceField, targetField);\r\n }\r\n \r\n this.columnDragging = null;\r\n }\r\n\r\n /**\r\n * Column 드래그 중인지 확인\r\n */\r\n isColumnDragging(): boolean {\r\n return this.columnDragging !== null;\r\n }\r\n\r\n // ============================================\r\n // Row Drag & Drop\r\n // ============================================\r\n\r\n /**\r\n * Row 드래그 시작\r\n */\r\n startRowDrag(e: MouseEvent, rowIndex: number, rowElement: HTMLElement): void {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n this.rowDragging = {\r\n index: rowIndex,\r\n startY: e.clientY,\r\n element: null,\r\n };\r\n \r\n const indicator = createElement('div', 'velox-row-drag-indicator');\r\n indicator.textContent = `행 ${rowIndex + 1}`;\r\n indicator.style.position = 'fixed';\r\n indicator.style.left = `${e.clientX}px`;\r\n indicator.style.top = `${e.clientY}px`;\r\n document.body.appendChild(indicator);\r\n this.rowDragging.element = indicator;\r\n \r\n addClass(rowElement, 'velox-row--dragging');\r\n\r\n document.addEventListener('mousemove', this.boundHandleRowDragMove);\r\n document.addEventListener('mouseup', this.boundHandleRowDragEnd);\r\n addClass(document.body, 'velox-no-select');\r\n }\r\n\r\n /**\r\n * Row 드래그 이동\r\n */\r\n private handleRowDragMove(e: MouseEvent): void {\r\n const ctx = this.ctx;\r\n\r\n if (!this.rowDragging?.element) return;\r\n \r\n this.rowDragging.element.style.left = `${e.clientX + 10}px`;\r\n this.rowDragging.element.style.top = `${e.clientY + 10}px`;\r\n \r\n const target = document.elementFromPoint(e.clientX, e.clientY);\r\n const rowElement = target?.closest('.velox-row') as HTMLElement;\r\n \r\n ctx.bodyInner.querySelectorAll('.velox-row--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-row--drop-target');\r\n });\r\n ctx.fixedLeftBodyInner?.querySelectorAll('.velox-row--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-row--drop-target');\r\n });\r\n \r\n if (rowElement) {\r\n const targetIndex = parseInt(rowElement.dataset.rowIndex || '-1', 10);\r\n if (targetIndex !== -1 && targetIndex !== this.rowDragging.index) {\r\n addClass(rowElement, 'velox-row--drop-target');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Row 드래그 종료\r\n */\r\n private handleRowDragEnd(e: MouseEvent): void {\r\n const ctx = this.ctx;\r\n\r\n if (!this.rowDragging) return;\r\n \r\n const sourceIndex = this.rowDragging.index;\r\n \r\n const target = document.elementFromPoint(e.clientX, e.clientY);\r\n const rowElement = target?.closest('.velox-row') as HTMLElement;\r\n const targetIndex = rowElement ? parseInt(rowElement.dataset.rowIndex || '-1', 10) : -1;\r\n \r\n if (this.rowDragging.element) {\r\n this.rowDragging.element.remove();\r\n }\r\n ctx.bodyInner.querySelectorAll('.velox-row--dragging, .velox-row--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-row--dragging');\r\n removeClass(el as HTMLElement, 'velox-row--drop-target');\r\n });\r\n ctx.fixedLeftBodyInner?.querySelectorAll('.velox-row--dragging, .velox-row--drop-target').forEach((el: Element) => {\r\n removeClass(el as HTMLElement, 'velox-row--dragging');\r\n removeClass(el as HTMLElement, 'velox-row--drop-target');\r\n });\r\n \r\n document.removeEventListener('mousemove', this.boundHandleRowDragMove);\r\n document.removeEventListener('mouseup', this.boundHandleRowDragEnd);\r\n removeClass(document.body, 'velox-no-select');\r\n \r\n if (targetIndex !== -1 && targetIndex !== sourceIndex) {\r\n ctx.moveRow(sourceIndex, targetIndex);\r\n }\r\n \r\n this.rowDragging = null;\r\n }\r\n\r\n /**\r\n * Row 드래그 중인지 확인\r\n */\r\n isRowDragging(): boolean {\r\n return this.rowDragging !== null;\r\n }\r\n\r\n // ============================================\r\n // Column Resize\r\n // ============================================\r\n\r\n /**\r\n * Column 리사이즈 시작\r\n */\r\n startResize(e: MouseEvent, column: ColumnDefinition): void {\r\n const ctx = this.ctx;\r\n\r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const headerCell = ctx.headerElement.querySelector(`[data-field=\"${column.field}\"]`) as HTMLElement;\r\n \r\n if (headerCell) {\r\n this.resizing = {\r\n column,\r\n startX: e.clientX,\r\n startWidth: headerCell.offsetWidth,\r\n };\r\n \r\n document.addEventListener('mousemove', this.boundHandleResizeMove);\r\n document.addEventListener('mouseup', this.boundHandleResizeEnd);\r\n addClass(document.body, 'velox-no-select');\r\n }\r\n }\r\n\r\n /**\r\n * Column 리사이즈 이동\r\n */\r\n private handleResizeMove(e: MouseEvent): void {\r\n const ctx = this.ctx;\r\n\r\n if (!this.resizing) return;\r\n \r\n const deltaX = e.clientX - this.resizing.startX;\r\n const newWidth = Math.max(50, this.resizing.startWidth + deltaX);\r\n \r\n this.resizing.column.width = newWidth;\r\n \r\n ctx.invalidateColumnCache();\r\n ctx.render();\r\n }\r\n\r\n /**\r\n * Column 리사이즈 종료\r\n */\r\n private handleResizeEnd(): void {\r\n const ctx = this.ctx;\r\n \r\n if (!this.resizing) return;\r\n \r\n document.removeEventListener('mousemove', this.boundHandleResizeMove);\r\n document.removeEventListener('mouseup', this.boundHandleResizeEnd);\r\n removeClass(document.body, 'velox-no-select');\r\n \r\n ctx.emitEvent('onColumnResize', this.resizing.column.field, this.resizing.column.width || 0);\r\n \r\n this.resizing = null;\r\n }\r\n\r\n /**\r\n * 리사이즈 중인지 확인\r\n */\r\n isResizing(): boolean {\r\n return this.resizing !== null;\r\n }\r\n\r\n /**\r\n * 모든 드래그 상태 초기화\r\n */\r\n cleanup(): void {\r\n // Column drag cleanup\r\n if (this.columnDragging) {\r\n if (this.columnDragging.element) {\r\n this.columnDragging.element.remove();\r\n }\r\n document.removeEventListener('mousemove', this.boundHandleColumnDragMove);\r\n document.removeEventListener('mouseup', this.boundHandleColumnDragEnd);\r\n this.columnDragging = null;\r\n }\r\n\r\n // Row drag cleanup\r\n if (this.rowDragging) {\r\n if (this.rowDragging.element) {\r\n this.rowDragging.element.remove();\r\n }\r\n document.removeEventListener('mousemove', this.boundHandleRowDragMove);\r\n document.removeEventListener('mouseup', this.boundHandleRowDragEnd);\r\n this.rowDragging = null;\r\n }\r\n\r\n // Resize cleanup\r\n if (this.resizing) {\r\n document.removeEventListener('mousemove', this.boundHandleResizeMove);\r\n document.removeEventListener('mouseup', this.boundHandleResizeEnd);\r\n this.resizing = null;\r\n }\r\n\r\n removeClass(document.body, 'velox-no-select');\r\n }\r\n\r\n /**\r\n * 리소스 정리 (destroy 별칭)\r\n */\r\n destroy(): void {\r\n this.cleanup();\r\n }\r\n}\r\n","/**\r\n * VeloxGrid - GridSummary\r\n * @description Summary/Aggregation calculation module\r\n * Phase 13: Summary/Aggregation\r\n */\r\n\r\nimport type {\r\n GridContext,\r\n RowData,\r\n CellValue,\r\n SummaryConfig,\r\n SummaryResult,\r\n ColumnDefinition,\r\n} from '../types';\r\n\r\n/**\r\n * GridSummary 클래스\r\n * \r\n * Footer Summary와 Group Summary 계산 담당\r\n */\r\nexport class GridSummary {\r\n private context: GridContext;\r\n private summaryCache: Map<string, SummaryResult>;\r\n\r\n constructor(context: GridContext) {\r\n this.context = context;\r\n this.summaryCache = new Map();\r\n }\r\n\r\n /**\r\n * Footer Summary 값 계산\r\n * @param field 컬럼 필드명\r\n * @returns 계산된 집계 값\r\n */\r\n public calculateFooterSummary(field: string): SummaryResult | null {\r\n const options = this.context.getOptions();\r\n const column = this.context.getState().columns.find(col => col.field === field);\r\n \r\n if (!column) return null;\r\n\r\n // 컬럼별 summary 설정 우선, 없으면 footerSummary.columns에서 찾기\r\n const summaryConfig = column.summary || options.footerSummary?.columns?.[field];\r\n \r\n if (!summaryConfig) return null;\r\n\r\n // 캐시 키\r\n const cacheKey = `footer:${field}`;\r\n \r\n // 캐시된 값이 있으면 반환\r\n if (this.summaryCache.has(cacheKey)) {\r\n return this.summaryCache.get(cacheKey)!;\r\n }\r\n\r\n // 표시 데이터에서 해당 컬럼 값 추출\r\n const displayData = this.context.getDisplayData();\r\n const values = displayData.map(row => row[field]);\r\n\r\n // 집계 함수 실행\r\n const value = this.executeAggregation(summaryConfig, values, displayData);\r\n\r\n // 포맷팅\r\n const formattedValue = this.formatSummaryValue(value, summaryConfig, column);\r\n\r\n const result: SummaryResult = {\r\n field,\r\n function: summaryConfig.function,\r\n value,\r\n formattedValue,\r\n };\r\n\r\n // 캐시 저장\r\n this.summaryCache.set(cacheKey, result);\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 모든 Footer Summary 값 계산\r\n * @returns field -> SummaryResult 맵\r\n */\r\n public calculateAllFooterSummaries(): Map<string, SummaryResult> {\r\n const options = this.context.getOptions();\r\n const results = new Map<string, SummaryResult>();\r\n\r\n if (!options.footerSummary?.visible) {\r\n return results;\r\n }\r\n\r\n const columns = this.context.getVisibleColumns();\r\n\r\n columns.forEach(column => {\r\n const result = this.calculateFooterSummary(column.field);\r\n if (result) {\r\n results.set(column.field, result);\r\n }\r\n });\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Group Summary 값 계산\r\n * @param field 컬럼 필드명\r\n * @param _groupValue 그룹 값 (reserved for future use)\r\n * @param groupData 그룹 데이터\r\n * @returns 계산된 집계 값\r\n */\r\n public calculateGroupSummary(\r\n field: string,\r\n _groupValue: CellValue,\r\n groupData: RowData[]\r\n ): SummaryResult | null {\r\n const options = this.context.getOptions();\r\n const column = this.context.getState().columns.find(col => col.field === field);\r\n\r\n if (!column || !options.groupSummary?.enabled) return null;\r\n\r\n const summaryConfig = options.groupSummary.columns?.[field];\r\n \r\n if (!summaryConfig) return null;\r\n\r\n // 그룹 데이터에서 해당 컬럼 값 추출\r\n const values = groupData.map(row => row[field]);\r\n\r\n // 집계 함수 실행\r\n const value = this.executeAggregation(summaryConfig, values, groupData);\r\n\r\n // 포맷팅\r\n const formattedValue = this.formatSummaryValue(value, summaryConfig, column);\r\n\r\n return {\r\n field,\r\n function: summaryConfig.function,\r\n value,\r\n formattedValue,\r\n };\r\n }\r\n\r\n /**\r\n * 집계 함수 실행\r\n * @param config Summary 설정\r\n * @param values 값 배열\r\n * @param data 원본 데이터 배열\r\n * @returns 집계된 값\r\n */\r\n private executeAggregation(\r\n config: SummaryConfig,\r\n values: CellValue[],\r\n data: RowData[]\r\n ): CellValue {\r\n // null/undefined 필터링\r\n const validValues = values.filter(v => v !== null && v !== undefined);\r\n\r\n switch (config.function) {\r\n case 'sum':\r\n return this.calculateSum(validValues);\r\n \r\n case 'avg':\r\n return this.calculateAverage(validValues);\r\n \r\n case 'count':\r\n return this.calculateCount(validValues);\r\n \r\n case 'min':\r\n return this.calculateMin(validValues);\r\n \r\n case 'max':\r\n return this.calculateMax(validValues);\r\n \r\n case 'custom':\r\n if (config.customFunction) {\r\n return config.customFunction(values, data);\r\n }\r\n return null;\r\n \r\n default:\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * 합계 계산\r\n */\r\n private calculateSum(values: CellValue[]): number {\r\n return values.reduce((sum: number, val) => {\r\n const num = this.toNumber(val);\r\n return sum + (num !== null ? num : 0);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * 평균 계산\r\n */\r\n private calculateAverage(values: CellValue[]): number | null {\r\n if (values.length === 0) return null;\r\n \r\n const sum = this.calculateSum(values);\r\n const count = values.filter(v => this.toNumber(v) !== null).length;\r\n \r\n return count > 0 ? sum / count : null;\r\n }\r\n\r\n /**\r\n * 개수 계산\r\n */\r\n private calculateCount(values: CellValue[]): number {\r\n return values.length;\r\n }\r\n\r\n /**\r\n * 최소값 계산\r\n */\r\n private calculateMin(values: CellValue[]): number | null {\r\n const numbers = values\r\n .map(v => this.toNumber(v))\r\n .filter(n => n !== null) as number[];\r\n \r\n return numbers.length > 0 ? Math.min(...numbers) : null;\r\n }\r\n\r\n /**\r\n * 최대값 계산\r\n */\r\n private calculateMax(values: CellValue[]): number | null {\r\n const numbers = values\r\n .map(v => this.toNumber(v))\r\n .filter(n => n !== null) as number[];\r\n \r\n return numbers.length > 0 ? Math.max(...numbers) : null;\r\n }\r\n\r\n /**\r\n * CellValue를 숫자로 변환\r\n */\r\n private toNumber(value: CellValue): number | null {\r\n if (typeof value === 'number') return value;\r\n if (typeof value === 'string') {\r\n // 콤마 제거 후 변환\r\n const cleaned = value.replace(/,/g, '');\r\n const num = parseFloat(cleaned);\r\n return isNaN(num) ? null : num;\r\n }\r\n if (typeof value === 'boolean') return value ? 1 : 0;\r\n return null;\r\n }\r\n\r\n /**\r\n * Summary 값 포맷팅\r\n */\r\n private formatSummaryValue(\r\n value: CellValue,\r\n config: SummaryConfig,\r\n column: ColumnDefinition\r\n ): string {\r\n // 커스텀 포맷터가 있으면 사용\r\n if (config.formatter) {\r\n return config.formatter(value);\r\n }\r\n\r\n // 컬럼 포맷터가 있으면 사용\r\n if (column.formatter) {\r\n return column.formatter(value, {} as RowData, column);\r\n }\r\n\r\n // 기본 포맷팅\r\n if (value === null || value === undefined) {\r\n return '';\r\n }\r\n\r\n if (typeof value === 'number') {\r\n // config.format 적용 (예: '0,0.00')\r\n if (config.format) {\r\n return this.applyNumberFormat(value, config.format);\r\n }\r\n // 기본 숫자 포맷\r\n return this.formatNumber(value);\r\n }\r\n\r\n return String(value);\r\n }\r\n\r\n /**\r\n * 숫자 포맷 적용\r\n * @param value 숫자 값\r\n * @param format 포맷 문자열 (예: '0,0.00')\r\n */\r\n private applyNumberFormat(value: number, format: string): string {\r\n // 간단한 포맷 파싱\r\n const hasComma = format.includes(',');\r\n const decimalMatch = format.match(/\\.(\\d+)/);\r\n const decimalPlaces = decimalMatch ? decimalMatch[1].length : 0;\r\n\r\n let result = value.toFixed(decimalPlaces);\r\n\r\n if (hasComma) {\r\n // 천 단위 콤마 추가\r\n const parts = result.split('.');\r\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\r\n result = parts.join('.');\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * 기본 숫자 포맷팅\r\n */\r\n private formatNumber(value: number): string {\r\n // 정수면 그대로, 소수면 소수점 2자리까지\r\n if (Number.isInteger(value)) {\r\n return value.toLocaleString('en-US');\r\n }\r\n return value.toLocaleString('en-US', {\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 2,\r\n });\r\n }\r\n\r\n /**\r\n * 캐시 무효화\r\n */\r\n public invalidateCache(): void {\r\n this.summaryCache.clear();\r\n }\r\n\r\n /**\r\n * 특정 필드의 캐시만 무효화\r\n */\r\n public invalidateFieldCache(field: string): void {\r\n this.summaryCache.delete(`footer:${field}`);\r\n }\r\n\r\n /**\r\n * Summary 값 가져오기 (캐시 우선)\r\n */\r\n public getSummaryValue(field: string): CellValue {\r\n const result = this.calculateFooterSummary(field);\r\n return result?.value ?? null;\r\n }\r\n\r\n /**\r\n * 모든 Summary 값 가져오기\r\n */\r\n public getAllSummaryValues(): Record<string, CellValue> {\r\n const results = this.calculateAllFooterSummaries();\r\n const values: Record<string, CellValue> = {};\r\n \r\n results.forEach((result, field) => {\r\n values[field] = result.value;\r\n });\r\n\r\n return values;\r\n }\r\n}\r\n","/**\r\n * VeloxGrid - Core Grid Class v6.0\r\n * \r\n * A lightweight, high-performance data grid library\r\n * \r\n * Architecture:\r\n * - Modular design with delegated components\r\n * - GridRenderer: Rendering (header, body, cells)\r\n * - GridFilterPopup: Filter UI\r\n * - GridColumnMenu: Column context menu\r\n * - GridDragManager: Column/Row drag & resize\r\n * - GridHistory: Undo/Redo management\r\n * - Column caching for performance\r\n */\r\n\r\nimport type {\r\n GridOptions,\r\n GridState,\r\n RowData,\r\n ColumnDefinition,\r\n SortState,\r\n SortDirection,\r\n FilterState,\r\n FilterCondition,\r\n CellValue,\r\n VeloxGridInstance,\r\n GridEvents,\r\n ValueType,\r\n FilterOperator,\r\n CellIndex,\r\n Selection,\r\n CheckBarOptions,\r\n ExportOptions,\r\n UndoAction,\r\n CellEditUndoData,\r\n BulkEditUndoData,\r\n RowAddUndoData,\r\n RowRemoveUndoData,\r\n GridContext,\r\n RowStateType,\r\n ChangesResult,\r\n PaginationState,\r\n DataRequestParams,\r\n} from '../types';\r\nimport { createElement, addClass, throttle } from '../utils/dom';\r\nimport { formatValue, sortData, filterData, generateId } from '../utils/data';\r\nimport {\r\n exportToExcel as exportToExcelUtil,\r\n exportToCSV as exportToCSVUtil,\r\n exportToJSON as exportToJSONUtil,\r\n downloadCSV,\r\n downloadJSON,\r\n parseCSV,\r\n importFromExcel,\r\n isSheetJSAvailable,\r\n type ExportContext,\r\n type ImportResult,\r\n} from '../utils/export';\r\nimport { GridHistory } from './GridHistory';\r\nimport { GridValidator } from './GridValidator';\r\nimport { GridEditorFactory } from './GridEditorFactory';\r\nimport { GridTooltip } from './GridTooltip';\r\nimport { GridRenderer } from './GridRenderer';\r\nimport { GridFilterPopup } from './GridFilterPopup';\r\nimport { GridColumnMenu } from './GridColumnMenu';\r\nimport { GridDragManager } from './GridDragManager';\r\nimport { GridSummary } from './GridSummary';\r\n\r\nconst DEFAULT_OPTIONS: Partial<GridOptions> = {\r\n rowHeight: 40,\r\n headerHeight: 44,\r\n showRowNumbers: false,\r\n rowDraggable: false,\r\n selectable: true,\r\n selectionMode: 'multiple',\r\n selectionStyle: 'row',\r\n showCheckbox: false,\r\n sortable: true,\r\n filterable: false,\r\n editable: false,\r\n resizable: true,\r\n virtualScroll: false,\r\n bufferSize: 5,\r\n theme: 'default',\r\n locale: 'ko-KR',\r\n emptyMessage: '데이터가 없습니다.',\r\n loading: false,\r\n loadingMessage: '로딩 중...',\r\n undoable: true,\r\n undoStackSize: 50,\r\n};\r\n\r\nconst DEFAULT_CHECKBAR: CheckBarOptions = {\r\n visible: false,\r\n exclusive: false,\r\n showAll: true,\r\n};\r\n\r\n// Column cache interface for performance optimization\r\ninterface ColumnCache {\r\n visible: ColumnDefinition[] | null;\r\n fixedLeft: ColumnDefinition[] | null;\r\n scrollable: ColumnDefinition[] | null;\r\n fixedRight: ColumnDefinition[] | null; // Phase 14: Columns fixed to right\r\n dirty: boolean;\r\n}\r\n\r\nexport class VeloxGrid implements VeloxGridInstance, GridContext {\r\n private container: HTMLElement;\r\n private options: GridOptions;\r\n private state: GridState;\r\n private events: GridEvents;\r\n private gridId: string;\r\n\r\n // DOM Elements - public for GridContext access\r\n public rootElement!: HTMLElement;\r\n public headerElement!: HTMLElement;\r\n public bodyElement!: HTMLElement;\r\n public bodyInner!: HTMLElement;\r\n public footerElement: HTMLElement | null = null;\r\n public fixedLeftFooter: HTMLElement | null = null;\r\n public loadingOverlay: HTMLElement | null = null;\r\n public fixedLeftContainer: HTMLElement | null = null;\r\n public fixedLeftHeader: HTMLElement | null = null;\r\n public fixedLeftBody: HTMLElement | null = null;\r\n public fixedLeftBodyInner: HTMLElement | null = null;\r\n // Phase 14: Fixed Right DOM elements\r\n public fixedRightContainer: HTMLElement | null = null;\r\n public fixedRightHeader: HTMLElement | null = null;\r\n public fixedRightBody: HTMLElement | null = null;\r\n public fixedRightBodyInner: HTMLElement | null = null;\r\n public fixedRightFooter: HTMLElement | null = null;\r\n // Phase 18: Pagination DOM\r\n public paginationContainer: HTMLElement | null = null;\r\n // Phase 18: Infinite scroll state\r\n private infiniteScrollLoading = false;\r\n private infiniteScrollAllLoaded = false;\r\n\r\n // Internal state\r\n private blockSelecting: { startRow: number; startField: string } | null = null;\r\n\r\n // Cached canvas for text measurement (performance optimization)\r\n private measureCanvas: HTMLCanvasElement | null = null;\r\n private measureContext: CanvasRenderingContext2D | null = null;\r\n\r\n // Bound event handlers (avoid creating new functions on each call)\r\n private boundHandleBlockSelectionEnd: () => void;\r\n private boundHandleKeyDown: (e: KeyboardEvent) => void;\r\n\r\n private virtualState = {\r\n startIndex: 0,\r\n endIndex: 0,\r\n visibleCount: 0,\r\n totalHeight: 0,\r\n };\r\n\r\n private dataIndexMap: Map<RowData, number> = new Map();\r\n\r\n // Column cache for performance optimization\r\n private columnCache: ColumnCache = {\r\n visible: null,\r\n fixedLeft: null,\r\n scrollable: null,\r\n fixedRight: null, // Phase 14: Columns fixed to right\r\n dirty: true,\r\n };\r\n\r\n // Undo/Redo - using GridHistory (refactored)\r\n private history: GridHistory;\r\n private tooltip: GridTooltip | null = null;\r\n \r\n // Edit mode document click handler cleanup\r\n private editModeCleanup: (() => void) | null = null;\r\n\r\n // Modularized components\r\n private renderer: GridRenderer;\r\n private filterPopupManager: GridFilterPopup;\r\n private columnMenuManager: GridColumnMenu;\r\n private dragManager: GridDragManager;\r\n private summary: GridSummary;\r\n\r\n constructor(\r\n container: HTMLElement | string,\r\n options: GridOptions,\r\n events: GridEvents = {}\r\n ) {\r\n if (typeof container === 'string') {\r\n const el = document.querySelector(container);\r\n if (!el) throw new Error(`Container not found: ${container}`);\r\n this.container = el as HTMLElement;\r\n } else {\r\n this.container = container;\r\n }\r\n\r\n this.options = { ...DEFAULT_OPTIONS, ...options } as GridOptions;\r\n \r\n if (this.options.checkBar) {\r\n this.options.checkBar = { ...DEFAULT_CHECKBAR, ...this.options.checkBar };\r\n } else if (this.options.showCheckbox) {\r\n this.options.checkBar = { ...DEFAULT_CHECKBAR, visible: true };\r\n }\r\n\r\n this.events = events;\r\n this.gridId = generateId('velox-grid');\r\n\r\n // Bind event handlers once in constructor (performance optimization)\r\n this.boundHandleBlockSelectionEnd = this.handleBlockSelectionEnd.bind(this);\r\n this.boundHandleKeyDown = this.handleKeyDown.bind(this);\r\n\r\n // Initialize history manager (refactored from inline stacks)\r\n this.history = new GridHistory({\r\n enabled: this.options.undoable ?? true,\r\n maxSize: this.options.undoStackSize ?? 50,\r\n });\r\n\r\n // Initialize modularized components\r\n this.renderer = new GridRenderer(this);\r\n this.filterPopupManager = new GridFilterPopup(this);\r\n this.columnMenuManager = new GridColumnMenu(this);\r\n this.dragManager = new GridDragManager(this);\r\n this.summary = new GridSummary(this);\r\n\r\n this.state = {\r\n data: [],\r\n displayData: [],\r\n columns: this.options.columns.map(col => ({ ...col })),\r\n selection: {\r\n selectedRows: new Set<number>(),\r\n selectedCells: new Set<string>(),\r\n focusedCell: null,\r\n selections: [],\r\n lastSelectedRow: null,\r\n },\r\n checkBar: {\r\n checkedRows: new Set<number>(),\r\n checkableRows: new Set<number>(),\r\n },\r\n rowStates: new Map<RowData, RowStateType>(), // Phase 15: Row state tracking\r\n sort: [],\r\n filter: null,\r\n edit: {\r\n editing: false,\r\n rowIndex: null,\r\n field: null,\r\n originalValue: null,\r\n },\r\n pagination: {\r\n currentPage: 1,\r\n pageSize: this.options.pagination?.pageSize || 20,\r\n totalCount: this.options.dataSource?.totalCount || 0,\r\n totalPages: 0,\r\n loading: false,\r\n },\r\n scroll: { top: 0, left: 0 },\r\n };\r\n\r\n if (this.options.data) {\r\n this.state.data = this.options.data.map(row => ({ ...row }));\r\n this.rebuildDataIndexMap();\r\n this.state.displayData = [...this.state.data];\r\n this.initCheckableRows();\r\n // Phase 15: Initialize all existing rows as 'none' state\r\n this.state.data.forEach(row => {\r\n this.state.rowStates.set(row, 'none');\r\n });\r\n }\r\n\r\n this.build();\r\n this.tooltip = new GridTooltip(this.rootElement);\r\n \r\n // Phase 18: 초기 데이터 로드\r\n if (this.options.pagination?.enabled) {\r\n if (this.isRemoteDataSource()) {\r\n // Remote: 서버에서 첫 페이지 데이터 가져오기\r\n this.render(); // 빈 상태로 먼저 렌더 (pagination UI 포함)\r\n this.fetchData();\r\n } else {\r\n // Local: pagination 적용 후 렌더\r\n this.state.pagination.totalCount = this.state.data.length;\r\n this.updateTotalPages();\r\n if (this.options.pagination.mode === 'infinite') {\r\n this.applyLocalInfiniteScroll();\r\n } else {\r\n this.applyLocalPagination();\r\n }\r\n this.render();\r\n }\r\n } else {\r\n this.render();\r\n }\r\n \r\n this.attachEvents();\r\n this.events.onReady?.(this);\r\n }\r\n\r\n // GridContext: Data index methods (public for module access)\r\n rebuildDataIndexMap(): void {\r\n this.dataIndexMap.clear();\r\n this.state.data.forEach((row, index) => {\r\n this.dataIndexMap.set(row, index);\r\n });\r\n }\r\n\r\n initCheckableRows(): void {\r\n this.state.checkBar.checkableRows.clear();\r\n const checkBar = this.options.checkBar;\r\n \r\n this.state.displayData.forEach((row, index) => {\r\n if (checkBar?.checkableCallback) {\r\n if (checkBar.checkableCallback(row, index)) {\r\n this.state.checkBar.checkableRows.add(index);\r\n }\r\n } else {\r\n this.state.checkBar.checkableRows.add(index);\r\n }\r\n });\r\n }\r\n\r\n // GridContext: Column cache methods (public for module access)\r\n invalidateColumnCache(): void {\r\n this.columnCache.dirty = true;\r\n this.columnCache.visible = null;\r\n this.columnCache.fixedLeft = null;\r\n this.columnCache.scrollable = null;\r\n this.columnCache.fixedRight = null;\r\n }\r\n\r\n /**\r\n * Get special columns with displayOrder\r\n * Phase 14.1: Helper method to generate special columns sorted by displayOrder\r\n */\r\n private getSpecialColumnsWithOrder(): ColumnDefinition[] {\r\n interface SpecialColumnDef {\r\n col: ColumnDefinition;\r\n order: number;\r\n }\r\n \r\n const specialColumnsWithOrder: SpecialColumnDef[] = [];\r\n \r\n // DragHandle\r\n if (typeof this.options.rowDraggable === 'object' && this.options.rowDraggable.enabled) {\r\n const order = this.options.rowDraggable.displayOrder ?? 0;\r\n specialColumnsWithOrder.push({\r\n col: { field: '__drag', header: '', width: 44, visible: true },\r\n order\r\n });\r\n } else if (this.options.rowDraggable === true) {\r\n specialColumnsWithOrder.push({\r\n col: { field: '__drag', header: '', width: 44, visible: true },\r\n order: 0 // default order\r\n });\r\n }\r\n \r\n // CheckBar\r\n if (this.options.checkBar?.visible) {\r\n const order = this.options.checkBar.displayOrder ?? 10;\r\n specialColumnsWithOrder.push({\r\n col: { field: '__checkbox', header: '', width: 44, visible: true },\r\n order\r\n });\r\n }\r\n \r\n // RowNumbers\r\n if (typeof this.options.showRowNumbers === 'object' && this.options.showRowNumbers.visible) {\r\n const order = this.options.showRowNumbers.displayOrder ?? 20;\r\n specialColumnsWithOrder.push({\r\n col: { field: '__rownum', header: '#', width: 50, visible: true },\r\n order\r\n });\r\n } else if (this.options.showRowNumbers === true) {\r\n specialColumnsWithOrder.push({\r\n col: { field: '__rownum', header: '#', width: 50, visible: true },\r\n order: 20 // default order\r\n });\r\n }\r\n \r\n // Sort by displayOrder (ascending = left to right)\r\n specialColumnsWithOrder.sort((a, b) => a.order - b.order);\r\n \r\n return specialColumnsWithOrder.map(item => item.col);\r\n }\r\n\r\n /**\r\n * Get fixed left columns\r\n * Phase 14: Only include special columns when fixedOptions.colCount > 0\r\n * Phase 14.1: Sort special columns by displayOrder\r\n * \r\n * Logic:\r\n * - If colCount = 0: Fixed left is empty (special columns go to scrollable)\r\n * - If colCount > 0: Fixed left = special columns (sorted by displayOrder) + first N data columns\r\n */\r\n getFixedLeftColumns(): ColumnDefinition[] {\r\n if (this.columnCache.dirty || !this.columnCache.fixedLeft) {\r\n const { colCount = 0 } = this.options.fixedOptions || {};\r\n \r\n // Only include special columns when colCount > 0\r\n if (colCount > 0) {\r\n // Generate special columns with displayOrder\r\n const specialColumns = this.getSpecialColumnsWithOrder();\r\n \r\n // Data columns fixed by fixedOptions.colCount\r\n const dataColumns = this.getDataColumns();\r\n const fixedDataColumns = dataColumns.slice(0, colCount);\r\n \r\n this.columnCache.fixedLeft = [...specialColumns, ...fixedDataColumns];\r\n } else {\r\n // colCount = 0: no fixed left columns\r\n this.columnCache.fixedLeft = [];\r\n }\r\n }\r\n return this.columnCache.fixedLeft;\r\n }\r\n\r\n /**\r\n * Get columns fixed to right (based on fixedOptions.rightCount)\r\n * Phase 14: New method for right fixed columns\r\n */\r\n getFixedRightColumns(): ColumnDefinition[] {\r\n if (this.columnCache.dirty || !this.columnCache.fixedRight) {\r\n const { rightCount = 0 } = this.options.fixedOptions || {};\r\n const dataColumns = this.getDataColumns();\r\n const totalCount = dataColumns.length;\r\n this.columnCache.fixedRight = rightCount > 0 ? dataColumns.slice(totalCount - rightCount) : [];\r\n }\r\n return this.columnCache.fixedRight;\r\n }\r\n\r\n /**\r\n * Get scrollable columns (middle area between fixed left and fixed right)\r\n * Phase 14: Include special columns when colCount = 0\r\n * Phase 14.1: Sort special columns by displayOrder\r\n * \r\n * Logic:\r\n * - If colCount = 0: Scrollable = special columns (sorted by displayOrder) + all data columns (except fixed right)\r\n * - If colCount > 0: Scrollable = middle data columns only (between fixed left and fixed right)\r\n */\r\n getScrollableColumns(): ColumnDefinition[] {\r\n if (this.columnCache.dirty || !this.columnCache.scrollable) {\r\n const { colCount = 0, rightCount = 0 } = this.options.fixedOptions || {};\r\n const dataColumns = this.getDataColumns();\r\n const totalCount = dataColumns.length;\r\n \r\n if (colCount === 0) {\r\n // Generate special columns with displayOrder\r\n const specialColumns = this.getSpecialColumnsWithOrder();\r\n \r\n // Scrollable = special columns + data columns (except fixed right)\r\n const endIndex = totalCount - rightCount;\r\n const scrollableDataColumns = endIndex > 0 ? dataColumns.slice(0, endIndex) : [];\r\n \r\n this.columnCache.scrollable = [...specialColumns, ...scrollableDataColumns];\r\n } else {\r\n // Calculate scrollable range: colCount ~ (totalCount - rightCount)\r\n const startIndex = colCount;\r\n const endIndex = totalCount - rightCount;\r\n \r\n this.columnCache.scrollable = startIndex < endIndex \r\n ? dataColumns.slice(startIndex, endIndex)\r\n : [];\r\n }\r\n \r\n this.columnCache.dirty = false; // Mark as clean after all queries\r\n }\r\n return this.columnCache.scrollable;\r\n }\r\n\r\n /**\r\n * Get data columns (exclude special columns)\r\n * Phase 14: Helper method to filter out special columns\r\n */\r\n private getDataColumns(): ColumnDefinition[] {\r\n return this.state.columns.filter(\r\n col => col.visible !== false && !this.isSpecialColumn(col)\r\n );\r\n }\r\n\r\n /**\r\n * Check if column is special (CheckBar, RowNumbers, DragHandle)\r\n * Phase 14: Helper method to identify special columns\r\n */\r\n private isSpecialColumn(col: ColumnDefinition): boolean {\r\n return col.field === '__checkbox' || \r\n col.field === '__rownum' || \r\n col.field === '__drag';\r\n }\r\n\r\n getVisibleColumns(): ColumnDefinition[] {\r\n if (this.columnCache.dirty || !this.columnCache.visible) {\r\n this.columnCache.visible = this.state.columns.filter(col => col.visible !== false);\r\n }\r\n return this.columnCache.visible;\r\n }\r\n\r\n /**\r\n * Check if grid has fixed left columns\r\n * Phase 14: Only true when fixedOptions.colCount > 0\r\n */\r\n hasFixedLeft(): boolean {\r\n const { colCount = 0 } = this.options.fixedOptions || {};\r\n return colCount > 0;\r\n }\r\n\r\n /**\r\n * Check if grid has fixed right columns\r\n * Phase 14: New method for hasFixedRight\r\n */\r\n hasFixedRight(): boolean {\r\n const { rightCount = 0 } = this.options.fixedOptions || {};\r\n return rightCount > 0;\r\n }\r\n\r\n private build(): void {\r\n this.rootElement = createElement('div', 'velox-grid');\r\n this.rootElement.id = this.gridId;\r\n this.rootElement.tabIndex = 0;\r\n \r\n if (this.options.className) addClass(this.rootElement, this.options.className);\r\n \r\n // Phase 14: Add has-fixed-right class for CSS styling\r\n if (this.hasFixedRight()) {\r\n addClass(this.rootElement, 'has-fixed-right');\r\n }\r\n\r\n if (this.options.width) {\r\n this.rootElement.style.width = typeof this.options.width === 'number' \r\n ? `${this.options.width}px` : this.options.width;\r\n }\r\n if (this.options.height) {\r\n this.rootElement.style.height = typeof this.options.height === 'number'\r\n ? `${this.options.height}px` : this.options.height;\r\n }\r\n\r\n const wrapper = createElement('div', 'velox-wrapper');\r\n\r\n if (this.hasFixedLeft()) {\r\n this.fixedLeftContainer = createElement('div', 'velox-fixed-left');\r\n this.fixedLeftHeader = createElement('div', 'velox-header velox-header--fixed');\r\n this.fixedLeftBody = createElement('div', 'velox-body--fixed');\r\n this.fixedLeftBodyInner = createElement('div', 'velox-body-inner');\r\n this.fixedLeftBody.appendChild(this.fixedLeftBodyInner);\r\n this.fixedLeftContainer.appendChild(this.fixedLeftHeader);\r\n this.fixedLeftContainer.appendChild(this.fixedLeftBody);\r\n \r\n // Phase 13: Footer Summary for fixed left\r\n if (this.options.footerSummary?.visible) {\r\n this.fixedLeftFooter = createElement('div', 'velox-footer velox-footer--fixed');\r\n this.fixedLeftContainer.appendChild(this.fixedLeftFooter);\r\n }\r\n \r\n wrapper.appendChild(this.fixedLeftContainer);\r\n }\r\n\r\n const mainSection = createElement('div', 'velox-main');\r\n this.headerElement = createElement('div', 'velox-header');\r\n this.bodyElement = createElement('div', 'velox-body');\r\n this.bodyInner = createElement('div', 'velox-body-inner');\r\n this.bodyElement.appendChild(this.bodyInner);\r\n mainSection.appendChild(this.headerElement);\r\n mainSection.appendChild(this.bodyElement);\r\n \r\n // Phase 13: Footer Summary\r\n if (this.options.footerSummary?.visible) {\r\n this.footerElement = createElement('div', 'velox-footer');\r\n mainSection.appendChild(this.footerElement);\r\n }\r\n \r\n wrapper.appendChild(mainSection);\r\n\r\n // Phase 14: Fixed Right Container\r\n if (this.hasFixedRight()) {\r\n this.fixedRightContainer = createElement('div', 'velox-fixed-right');\r\n this.fixedRightHeader = createElement('div', 'velox-header velox-header--fixed-right');\r\n this.fixedRightBody = createElement('div', 'velox-body--fixed');\r\n this.fixedRightBodyInner = createElement('div', 'velox-body-inner');\r\n this.fixedRightBody.appendChild(this.fixedRightBodyInner);\r\n this.fixedRightContainer.appendChild(this.fixedRightHeader);\r\n this.fixedRightContainer.appendChild(this.fixedRightBody);\r\n \r\n // Phase 14: Footer Summary for fixed right\r\n if (this.options.footerSummary?.visible) {\r\n this.fixedRightFooter = createElement('div', 'velox-footer velox-footer--fixed-right');\r\n this.fixedRightContainer.appendChild(this.fixedRightFooter);\r\n }\r\n \r\n wrapper.appendChild(this.fixedRightContainer);\r\n }\r\n\r\n this.rootElement.appendChild(wrapper);\r\n\r\n // Phase 18: Pagination Bar\r\n if (this.options.pagination?.enabled) {\r\n this.paginationContainer = createElement('div', 'velox-pagination');\r\n this.rootElement.appendChild(this.paginationContainer);\r\n }\r\n\r\n this.container.innerHTML = '';\r\n this.container.appendChild(this.rootElement);\r\n\r\n this.buildLoadingOverlay();\r\n }\r\n\r\n private buildLoadingOverlay(): void {\r\n this.loadingOverlay = createElement('div', 'velox-loading-overlay');\r\n this.loadingOverlay.style.display = 'none';\r\n \r\n const spinner = createElement('div', 'velox-loading-spinner');\r\n const message = createElement('div', 'velox-loading-message');\r\n message.textContent = this.options.loadingMessage || '로딩 중...';\r\n \r\n this.loadingOverlay.appendChild(spinner);\r\n this.loadingOverlay.appendChild(message);\r\n this.rootElement.appendChild(this.loadingOverlay);\r\n }\r\n\r\n // GridContext: Virtual scroll methods (public for module access)\r\n calculateVirtualState(): void {\r\n if (!this.options.virtualScroll) return;\r\n\r\n const rowHeight = this.options.rowHeight || 40;\r\n const containerHeight = this.bodyElement.clientHeight;\r\n const scrollTop = this.bodyElement.scrollTop;\r\n const bufferSize = this.options.bufferSize || 5;\r\n\r\n this.virtualState.visibleCount = Math.ceil(containerHeight / rowHeight);\r\n this.virtualState.startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - bufferSize);\r\n this.virtualState.endIndex = Math.min(\r\n this.state.displayData.length,\r\n this.virtualState.startIndex + this.virtualState.visibleCount + bufferSize * 2\r\n );\r\n this.virtualState.totalHeight = this.state.displayData.length * rowHeight;\r\n }\r\n\r\n getVisibleRows(): { data: RowData; index: number }[] {\r\n if (!this.options.virtualScroll) {\r\n return this.state.displayData.map((data, index) => ({ data, index }));\r\n }\r\n this.calculateVirtualState();\r\n const rows: { data: RowData; index: number }[] = [];\r\n for (let i = this.virtualState.startIndex; i < this.virtualState.endIndex; i++) {\r\n if (this.state.displayData[i]) rows.push({ data: this.state.displayData[i], index: i });\r\n }\r\n return rows;\r\n }\r\n\r\n // GridContext: Rendering methods - delegated to GridRenderer\r\n render(): void {\r\n console.log('🔄 render() called', { editing: this.state.edit.editing, rowIndex: this.state.edit.rowIndex, field: this.state.edit.field });\r\n this.renderer.render();\r\n // Phase 18: Pagination UI\r\n if (this.paginationContainer) {\r\n this.renderPagination();\r\n }\r\n }\r\n\r\n renderHeader(): void {\r\n this.renderer.renderHeader();\r\n }\r\n renderBody(): void {\r\n this.renderer.renderBody();\r\n }\r\n\r\n updateLoadingState(): void {\r\n this.renderer.updateLoadingState();\r\n }\r\n\r\n // GridContext: Filter popup methods - delegated to GridFilterPopup\r\n showFilterPopup(column: ColumnDefinition, anchor: HTMLElement): void {\r\n this.filterPopupManager.showFilterPopup(column, anchor);\r\n }\r\n\r\n closeFilterPopup(): void {\r\n this.filterPopupManager.closeFilterPopup();\r\n }\r\n\r\n applyColumnFilter(field: string, operator: FilterOperator, value: CellValue): void {\r\n this.filterPopupManager.applyColumnFilter(field, operator, value);\r\n }\r\n\r\n removeColumnFilter(field: string): void {\r\n this.filterPopupManager.removeColumnFilter(field);\r\n }\r\n\r\n // Store event handlers for cleanup\r\n private scrollHandlers: (() => void)[] = [];\r\n private wheelHandler: ((e: WheelEvent) => void) | null = null;\r\n\r\n private detachEvents(): void {\r\n // Remove all scroll handlers\r\n this.scrollHandlers.forEach(handler => {\r\n this.bodyElement.removeEventListener('scroll', handler);\r\n if (this.fixedRightBody) {\r\n this.fixedRightBody.removeEventListener('scroll', handler);\r\n }\r\n });\r\n this.scrollHandlers = [];\r\n \r\n // Remove wheel handler\r\n if (this.wheelHandler) {\r\n this.bodyElement.removeEventListener('wheel', this.wheelHandler);\r\n this.wheelHandler = null;\r\n }\r\n }\r\n\r\n private attachEvents(): void {\r\n // Clean up existing event handlers first\r\n this.detachEvents();\r\n \r\n // Track if we're currently syncing to prevent infinite loops\r\n let isSyncing = false;\r\n let throttleTimer: number | null = null;\r\n \r\n const handleScroll = (source: 'body' | 'fixedRight') => {\r\n if (isSyncing) return;\r\n \r\n if (throttleTimer !== null) return;\r\n \r\n throttleTimer = window.setTimeout(() => {\r\n throttleTimer = null;\r\n }, 16);\r\n \r\n isSyncing = true;\r\n \r\n // Get scroll values from the source element\r\n const scrollTop = source === 'fixedRight' && this.fixedRightBody \r\n ? this.fixedRightBody.scrollTop \r\n : this.bodyElement.scrollTop;\r\n const scrollLeft = this.bodyElement.scrollLeft;\r\n \r\n this.state.scroll.top = scrollTop;\r\n this.state.scroll.left = scrollLeft;\r\n \r\n // Sync vertical scroll to other areas (not the source)\r\n if (this.fixedLeftBody && this.fixedLeftBody.scrollTop !== scrollTop) {\r\n this.fixedLeftBody.scrollTop = scrollTop;\r\n }\r\n if (source !== 'fixedRight' && this.fixedRightBody && this.fixedRightBody.scrollTop !== scrollTop) {\r\n this.fixedRightBody.scrollTop = scrollTop;\r\n }\r\n if (source !== 'body' && this.bodyElement.scrollTop !== scrollTop) {\r\n this.bodyElement.scrollTop = scrollTop;\r\n }\r\n \r\n // Sync horizontal scroll (Header and Footer)\r\n if (this.headerElement.scrollLeft !== scrollLeft) {\r\n this.headerElement.scrollLeft = scrollLeft;\r\n }\r\n if (this.footerElement && this.footerElement.scrollLeft !== scrollLeft) {\r\n this.footerElement.scrollLeft = scrollLeft;\r\n }\r\n \r\n if (this.options.virtualScroll) this.renderBody();\r\n this.events.onScroll?.(this.state.scroll.top, this.state.scroll.left);\r\n \r\n // Phase 18: Infinite Scroll - 스크롤 바닥 감지\r\n if (source === 'body' || source === 'fixedRight') {\r\n this.checkInfiniteScroll();\r\n }\r\n \r\n isSyncing = false;\r\n };\r\n \r\n // Header horizontal scroll handler\r\n const handleHeaderScroll = throttle(() => {\r\n const scrollLeft = this.headerElement.scrollLeft;\r\n this.bodyElement.scrollLeft = scrollLeft;\r\n if (this.footerElement) {\r\n this.footerElement.scrollLeft = scrollLeft;\r\n }\r\n }, 16);\r\n\r\n // Phase 14: Wheel event handler for body to control Fixed Right scroll\r\n if (this.hasFixedRight()) {\r\n this.wheelHandler = (e: WheelEvent) => {\r\n // Prevent default scroll behavior on body\r\n e.preventDefault();\r\n \r\n // Apply wheel delta to Fixed Right body\r\n if (this.fixedRightBody) {\r\n this.fixedRightBody.scrollTop += e.deltaY;\r\n }\r\n };\r\n \r\n this.bodyElement.addEventListener('wheel', this.wheelHandler, { passive: false });\r\n \r\n // Listen to Fixed Right scroll for synchronization\r\n const fixedRightScrollHandler = () => handleScroll('fixedRight');\r\n this.fixedRightBody!.addEventListener('scroll', fixedRightScrollHandler);\r\n this.scrollHandlers.push(fixedRightScrollHandler);\r\n \r\n // Also listen to body for horizontal scroll\r\n const bodyScrollHandler = () => handleScroll('body');\r\n this.bodyElement.addEventListener('scroll', bodyScrollHandler);\r\n this.scrollHandlers.push(bodyScrollHandler);\r\n } else {\r\n // No Fixed Right: normal body scroll\r\n const bodyScrollHandler = () => handleScroll('body');\r\n this.bodyElement.addEventListener('scroll', bodyScrollHandler);\r\n this.scrollHandlers.push(bodyScrollHandler);\r\n }\r\n \r\n // Header horizontal scroll synchronization\r\n this.headerElement.addEventListener('scroll', handleHeaderScroll);\r\n this.scrollHandlers.push(handleHeaderScroll);\r\n \r\n document.addEventListener('mouseup', this.boundHandleBlockSelectionEnd);\r\n this.rootElement.addEventListener('keydown', this.boundHandleKeyDown);\r\n }\r\n\r\n handleSort(field: string): void {\r\n const existingIndex = this.state.sort.findIndex(s => s.field === field);\r\n let newDirection: SortDirection = 'asc';\r\n if (existingIndex >= 0) {\r\n const current = this.state.sort[existingIndex].direction;\r\n if (current === 'asc') newDirection = 'desc';\r\n else if (current === 'desc') newDirection = null;\r\n }\r\n this.state.sort = newDirection ? [{ field, direction: newDirection }] : [];\r\n this.clearSelectionState();\r\n this.applyDataTransformations();\r\n \r\n // Remote 모드가 아닌 경우에만 즉시 render (remote는 fetchData 내에서 render)\r\n if (!this.isRemoteDataSource() || !this.options.pagination?.enabled) {\r\n this.render();\r\n }\r\n \r\n this.events.onSort?.(this.state.sort);\r\n }\r\n\r\n // GridContext: Event handlers (public for module access)\r\n handleRowClick(rowIndex: number, e: MouseEvent): void {\r\n if (!this.options.selectable) return;\r\n \r\n const selectionStyle = this.options.selectionStyle || 'row';\r\n \r\n if (selectionStyle === 'row') {\r\n this.handleRowSelection(rowIndex, e);\r\n }\r\n \r\n this.events.onRowClick?.(rowIndex, this.state.displayData[rowIndex]);\r\n }\r\n\r\n handleRowSelection(rowIndex: number, e: MouseEvent): void {\r\n const selectionMode = this.options.selectionMode || 'multiple';\r\n \r\n if (selectionMode === 'none') return;\r\n \r\n if (selectionMode === 'multiple' && (e.ctrlKey || e.metaKey)) {\r\n const isSelected = this.state.selection.selectedRows.has(rowIndex);\r\n this.selectRow(rowIndex, !isSelected);\r\n } else if (selectionMode === 'multiple' && e.shiftKey) {\r\n const selectedArray = Array.from(this.state.selection.selectedRows);\r\n if (selectedArray.length > 0) {\r\n const lastSelected = selectedArray[selectedArray.length - 1];\r\n const start = Math.min(lastSelected, rowIndex);\r\n const end = Math.max(lastSelected, rowIndex);\r\n for (let i = start; i <= end; i++) this.state.selection.selectedRows.add(i);\r\n this.render();\r\n this.events.onSelectionChange?.(this.getSelectedRows());\r\n } else {\r\n this.selectRow(rowIndex, true);\r\n }\r\n } else if (selectionMode === 'extended' && (e.ctrlKey || e.metaKey)) {\r\n const isSelected = this.state.selection.selectedRows.has(rowIndex);\r\n this.selectRow(rowIndex, !isSelected);\r\n } else {\r\n this.state.selection.selectedRows.clear();\r\n this.selectRow(rowIndex, true);\r\n }\r\n }\r\n\r\n handleCellClick(rowIndex: number, field: string, value: CellValue, e: MouseEvent): void {\r\n console.log('🔍 handleCellClick', { rowIndex, field, editing: this.state.edit.editing, editRow: this.state.edit.rowIndex, editField: this.state.edit.field });\r\n \r\n // 편집 중인 셀을 클릭하면 편집 모드 유지\r\n if (this.state.edit.editing && \r\n this.state.edit.rowIndex === rowIndex && \r\n this.state.edit.field === field) {\r\n console.log('✅ Same cell clicked - maintaining edit mode');\r\n return;\r\n }\r\n \r\n const selectionStyle = this.options.selectionStyle || 'row';\r\n \r\n if (selectionStyle === 'cell' || selectionStyle === 'block') {\r\n this.handleCellSelection(rowIndex, field, e);\r\n } else if (selectionStyle === 'row') {\r\n // Row 모드에서도 focusedCell 설정 (Quick Edit 지원)\r\n this.state.selection.focusedCell = { rowIndex, field };\r\n }\r\n \r\n this.events.onCellClick?.(rowIndex, field, value);\r\n }\r\n\r\n handleCellSelection(rowIndex: number, field: string, e: MouseEvent): void {\r\n const selectionMode = this.options.selectionMode || 'multiple';\r\n const cellKey = `${rowIndex}:${field}`;\r\n \r\n if (selectionMode === 'none') return;\r\n \r\n this.state.selection.focusedCell = { rowIndex, field };\r\n \r\n if (selectionMode === 'multiple' && (e.ctrlKey || e.metaKey)) {\r\n const isSelected = this.state.selection.selectedCells.has(cellKey);\r\n if (isSelected) {\r\n this.state.selection.selectedCells.delete(cellKey);\r\n } else {\r\n this.state.selection.selectedCells.add(cellKey);\r\n }\r\n } else if (selectionMode === 'multiple' && e.shiftKey) {\r\n const focusedCell = this.state.selection.focusedCell;\r\n if (focusedCell) {\r\n this.selectCellRange(focusedCell.rowIndex, focusedCell.field, rowIndex, field);\r\n }\r\n } else {\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.selectedCells.add(cellKey);\r\n }\r\n \r\n this.render();\r\n this.events.onCellSelectionChange?.(this.getSelectedCells());\r\n }\r\n\r\n selectCellRange(startRow: number, startField: string, endRow: number, endField: string): void {\r\n const columns = this.getVisibleColumns();\r\n const startColIndex = columns.findIndex(c => c.field === startField);\r\n const endColIndex = columns.findIndex(c => c.field === endField);\r\n \r\n const minRow = Math.min(startRow, endRow);\r\n const maxRow = Math.max(startRow, endRow);\r\n const minCol = Math.min(startColIndex, endColIndex);\r\n const maxCol = Math.max(startColIndex, endColIndex);\r\n \r\n this.state.selection.selectedCells.clear();\r\n \r\n for (let r = minRow; r <= maxRow; r++) {\r\n for (let c = minCol; c <= maxCol; c++) {\r\n const field = columns[c].field;\r\n this.state.selection.selectedCells.add(`${r}:${field}`);\r\n }\r\n }\r\n }\r\n\r\n // GridContext: Block selection methods (public for module access)\r\n startBlockSelection(rowIndex: number, field: string): void {\r\n if (this.options.selectionStyle !== 'block') return;\r\n \r\n this.blockSelecting = { startRow: rowIndex, startField: field };\r\n this.state.selection.focusedCell = { rowIndex, field };\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.selectedCells.add(`${rowIndex}:${field}`);\r\n this.render();\r\n }\r\n\r\n updateBlockSelection(rowIndex: number, field: string): void {\r\n if (!this.blockSelecting) return;\r\n \r\n this.selectCellRange(\r\n this.blockSelecting.startRow,\r\n this.blockSelecting.startField,\r\n rowIndex,\r\n field\r\n );\r\n this.render();\r\n }\r\n\r\n handleBlockSelectionEnd(): void {\r\n if (this.blockSelecting) {\r\n this.blockSelecting = null;\r\n this.events.onCellSelectionChange?.(this.getSelectedCells());\r\n }\r\n }\r\n\r\n handleRowDoubleClick(rowIndex: number, _e: MouseEvent): void {\r\n this.events.onRowDoubleClick?.(rowIndex, this.state.displayData[rowIndex]);\r\n }\r\n\r\n handleKeyDown(e: KeyboardEvent): void {\r\n // Handle editing state\r\n if (this.state.edit.editing) {\r\n if (e.key === 'Escape') {\r\n this.cancelEdit();\r\n } else if (e.key === 'Enter') {\r\n e.preventDefault();\r\n this.endEditAndMove(e.shiftKey ? 'up' : 'down'); // ✅ Shift+Enter = up\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n this.endEditAndMove(e.shiftKey ? 'left' : 'right');\r\n }\r\n return;\r\n }\r\n \r\n // Handle Undo/Redo (Ctrl+Z, Ctrl+Y)\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'z') {\r\n e.preventDefault();\r\n this.undo();\r\n return;\r\n }\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'y') {\r\n e.preventDefault();\r\n this.redo();\r\n return;\r\n }\r\n \r\n // Handle Copy/Paste/Cut shortcuts\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'c') {\r\n e.preventDefault();\r\n this.copy();\r\n return;\r\n }\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'v') {\r\n e.preventDefault();\r\n this.paste();\r\n return;\r\n }\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'x') {\r\n e.preventDefault();\r\n this.cut();\r\n return;\r\n }\r\n \r\n // Handle Delete key\r\n if (e.key === 'Delete' || e.key === 'Backspace') {\r\n if (this.options.editable) {\r\n e.preventDefault();\r\n this.deleteSelectedCells();\r\n return;\r\n }\r\n }\r\n \r\n const focusedCell = this.state.selection.focusedCell;\r\n // Phase 15.1: Quick Edit - typing starts editing immediately\r\n if (!this.state.edit.editing && this.options.editable && focusedCell) {\r\n const column = this.state.columns.find(c => c.field === focusedCell.field);\r\n \r\n // Printable character (alphanumeric, punctuation, space) triggers quick edit\r\n if (column?.editable !== false && \r\n e.key.length === 1 && \r\n !e.ctrlKey && !e.metaKey && !e.altKey) {\r\n \r\n e.preventDefault();\r\n \r\n // Start edit mode\r\n this.startEdit(focusedCell.rowIndex, focusedCell.field);\r\n \r\n // Set the typed character in the editor\r\n setTimeout(() => {\r\n const input = document.querySelector('.velox-edit-input') as HTMLInputElement;\r\n if (input) {\r\n input.value = e.key; // Replace existing value with new character\r\n input.setSelectionRange(1, 1); // Move cursor to end\r\n }\r\n }, 0);\r\n \r\n return;\r\n }\r\n }\r\n this.events.onKeyDown?.(e, focusedCell);\r\n \r\n if (!focusedCell) return;\r\n \r\n const columns = this.getVisibleColumns();\r\n const currentColIndex = columns.findIndex(c => c.field === focusedCell.field);\r\n let newRowIndex = focusedCell.rowIndex;\r\n let newColIndex = currentColIndex;\r\n let handled = false;\r\n \r\n switch (e.key) {\r\n case 'ArrowUp':\r\n if (newRowIndex > 0) { newRowIndex--; handled = true; }\r\n break;\r\n case 'ArrowDown':\r\n if (newRowIndex < this.state.displayData.length - 1) { newRowIndex++; handled = true; }\r\n break;\r\n case 'ArrowLeft':\r\n if (newColIndex > 0) { newColIndex--; handled = true; }\r\n break;\r\n case 'ArrowRight':\r\n if (newColIndex < columns.length - 1) { newColIndex++; handled = true; }\r\n break;\r\n case 'Tab':\r\n // Tab: Move right, Shift+Tab: Move left\r\n if (e.shiftKey) {\r\n if (newColIndex > 0) { \r\n newColIndex--; \r\n } else if (newRowIndex > 0) {\r\n // Wrap to end of previous row\r\n newRowIndex--;\r\n newColIndex = columns.length - 1;\r\n }\r\n } else {\r\n if (newColIndex < columns.length - 1) { \r\n newColIndex++; \r\n } else if (newRowIndex < this.state.displayData.length - 1) {\r\n // Wrap to start of next row\r\n newRowIndex++;\r\n newColIndex = 0;\r\n }\r\n }\r\n handled = true;\r\n break;\r\n case 'Home':\r\n if (e.ctrlKey) { newRowIndex = 0; newColIndex = 0; }\r\n else { newColIndex = 0; }\r\n handled = true;\r\n break;\r\n case 'End':\r\n if (e.ctrlKey) { newRowIndex = this.state.displayData.length - 1; newColIndex = columns.length - 1; }\r\n else { newColIndex = columns.length - 1; }\r\n handled = true;\r\n break;\r\n case 'PageUp':\r\n newRowIndex = Math.max(0, newRowIndex - this.virtualState.visibleCount);\r\n handled = true;\r\n break;\r\n case 'PageDown':\r\n newRowIndex = Math.min(this.state.displayData.length - 1, newRowIndex + this.virtualState.visibleCount);\r\n handled = true;\r\n break;\r\n case 'Enter':\r\n case 'F2':\r\n if (this.options.editable) { this.startEdit(focusedCell.rowIndex, focusedCell.field); handled = true; }\r\n break;\r\n case ' ':\r\n if (this.options.checkBar?.visible) { this.checkItem(focusedCell.rowIndex, !this.isItemChecked(focusedCell.rowIndex)); handled = true; }\r\n break;\r\n case 'a':\r\n case 'A':\r\n if (e.ctrlKey || e.metaKey) { this.selectAllCells(); handled = true; }\r\n break;\r\n }\r\n \r\n if (handled) {\r\n e.preventDefault();\r\n \r\n const newField = columns[newColIndex]?.field;\r\n if (newField && (newRowIndex !== focusedCell.rowIndex || newField !== focusedCell.field)) {\r\n this.setFocusedCell(newRowIndex, newField);\r\n \r\n if (e.shiftKey && (this.options.selectionStyle === 'cell' || this.options.selectionStyle === 'block')) {\r\n this.selectCellRange(focusedCell.rowIndex, focusedCell.field, newRowIndex, newField);\r\n } else if (!e.shiftKey && !e.ctrlKey) {\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.selectedCells.add(`${newRowIndex}:${newField}`);\r\n \r\n if (this.options.selectionStyle === 'row') {\r\n this.state.selection.selectedRows.clear();\r\n this.state.selection.selectedRows.add(newRowIndex);\r\n }\r\n }\r\n \r\n this.render();\r\n this.scrollToCell(newRowIndex, newField);\r\n }\r\n }\r\n }\r\n\r\n private selectAllCells(): void {\r\n const columns = this.getVisibleColumns();\r\n this.state.selection.selectedCells.clear();\r\n \r\n for (let r = 0; r < this.state.displayData.length; r++) {\r\n for (const col of columns) {\r\n this.state.selection.selectedCells.add(`${r}:${col.field}`);\r\n }\r\n }\r\n \r\n this.render();\r\n this.events.onCellSelectionChange?.(this.getSelectedCells());\r\n }\r\n\r\n // GridContext: Resize methods - delegated to GridDragManager\r\n startResize(e: MouseEvent, column: ColumnDefinition): void {\r\n this.dragManager.startResize(e, column);\r\n }\r\n\r\n // GridContext: Data transformation (public for module access)\r\n applyDataTransformations(): void {\r\n // Phase 18: Pagination이 활성화된 경우 별도 로직\r\n if (this.options.pagination?.enabled) {\r\n // Infinite scroll 상태 리셋\r\n this.infiniteScrollLoading = false;\r\n this.infiniteScrollAllLoaded = false;\r\n this.state.pagination.currentPage = 1;\r\n \r\n if (this.isRemoteDataSource()) {\r\n if (this.options.pagination.mode === 'infinite') {\r\n // Remote infinite: 데이터 초기화 후 첫 페이지 로드\r\n this.state.data = [];\r\n this.state.displayData = [];\r\n }\r\n this.fetchData();\r\n return;\r\n } else {\r\n // Local pagination/infinite: sort/filter + 페이지 슬라이싱\r\n if (this.options.pagination.mode === 'infinite') {\r\n this.applyLocalInfiniteScroll();\r\n } else {\r\n this.applyLocalPagination();\r\n }\r\n return;\r\n }\r\n }\r\n \r\n // 기존 로직 (pagination 없음)\r\n let data = [...this.state.data];\r\n if (this.state.filter) data = filterData(data, this.state.filter);\r\n if (this.state.sort.length > 0) {\r\n const columnTypes: Record<string, ValueType> = {};\r\n this.state.columns.forEach(col => { columnTypes[col.field] = col.type || 'text'; });\r\n data = sortData(data, this.state.sort, columnTypes);\r\n }\r\n this.state.displayData = data;\r\n this.initCheckableRows();\r\n }\r\n\r\n /**\r\n * Clear all selection state (rows, cells, focused cell)\r\n * Extracted to reduce code duplication\r\n */\r\n // GridContext: Selection state clearing (public for module access)\r\n clearSelectionState(): void {\r\n this.state.selection.selectedRows.clear();\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.focusedCell = null;\r\n }\r\n\r\n // --- Public API: Data Methods ---\r\n\r\n getData(): RowData[] {\r\n return this.state.data.map(row => ({ ...row }));\r\n }\r\n \r\n setData(data: RowData[]): void {\r\n this.state.data = data.map(row => ({ ...row }));\r\n this.rebuildDataIndexMap();\r\n this.clearSelectionState();\r\n this.state.checkBar.checkedRows.clear();\r\n \r\n // Phase 15: Initialize all new data rows as 'none' state\r\n this.state.rowStates.clear();\r\n this.state.data.forEach(row => {\r\n this.state.rowStates.set(row, 'none');\r\n });\r\n \r\n // Phase 18: Local pagination인 경우 totalCount 업데이트\r\n if (this.options.pagination?.enabled && !this.isRemoteDataSource()) {\r\n this.state.pagination.totalCount = this.state.data.length;\r\n this.state.pagination.currentPage = 1;\r\n this.updateTotalPages();\r\n }\r\n \r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n\r\n getRow(index: number): RowData | null {\r\n return this.state.displayData[index] ? { ...this.state.displayData[index] } : null;\r\n }\r\n\r\n getRowCount(): number {\r\n return this.state.data.length;\r\n }\r\n\r\n getVisibleRowCount(): number {\r\n return this.state.displayData.length;\r\n }\r\n\r\n addRow(row: RowData, index?: number): void {\r\n const newRow = { ...row };\r\n const insertIndex = index !== undefined ? index : this.state.data.length;\r\n this.state.data.splice(insertIndex, 0, newRow);\r\n this.rebuildDataIndexMap();\r\n \r\n // Phase 15: Set new row state as 'created'\r\n this.state.rowStates.set(newRow, 'created');\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onRowAdd?.(newRow, insertIndex);\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n\r\n updateRow(index: number, data: Partial<RowData>): void {\r\n const displayRow = this.state.displayData[index];\r\n if (!displayRow) return;\r\n \r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n Object.assign(this.state.data[dataIndex], data);\r\n \r\n // Phase 15: Update row state\r\n const currentState = this.state.rowStates.get(this.state.data[dataIndex]) || 'none';\r\n if (currentState === 'none') {\r\n this.state.rowStates.set(this.state.data[dataIndex], 'updated');\r\n }\r\n // If 'created', stay 'created'\r\n // If 'updated', stay 'updated'\r\n // If 'deleted', stay 'deleted' (shouldn't happen)\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onRowUpdate?.(this.state.data[dataIndex], index, data);\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n }\r\n\r\n removeRow(index: number): void {\r\n const displayRow = this.state.displayData[index];\r\n if (!displayRow) return;\r\n \r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n const removed = this.state.data[dataIndex];\r\n \r\n // Phase 15: Handle row state on deletion\r\n const currentState = this.state.rowStates.get(removed) || 'none';\r\n if (currentState === 'created') {\r\n // Created then deleted → 'createAndDeleted' (no server action needed)\r\n this.state.rowStates.set(removed, 'createAndDeleted');\r\n } else {\r\n // Mark as deleted (for server sync)\r\n this.state.rowStates.set(removed, 'deleted');\r\n }\r\n \r\n // Remove from data array\r\n this.state.data.splice(dataIndex, 1);\r\n this.rebuildDataIndexMap();\r\n \r\n this.state.selection.selectedRows.delete(index);\r\n const newSelectedRows = new Set<number>();\r\n this.state.selection.selectedRows.forEach(i => {\r\n if (i > index) newSelectedRows.add(i - 1);\r\n else if (i < index) newSelectedRows.add(i);\r\n });\r\n this.state.selection.selectedRows = newSelectedRows;\r\n \r\n this.state.checkBar.checkedRows.delete(index);\r\n const newCheckedRows = new Set<number>();\r\n this.state.checkBar.checkedRows.forEach(i => {\r\n if (i > index) newCheckedRows.add(i - 1);\r\n else if (i < index) newCheckedRows.add(i);\r\n });\r\n this.state.checkBar.checkedRows = newCheckedRows;\r\n\r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onRowRemove?.(removed, index);\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n }\r\n\r\n clearData(): void {\r\n this.state.data = [];\r\n this.state.displayData = [];\r\n this.dataIndexMap.clear();\r\n this.state.selection.selectedRows.clear();\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.focusedCell = null;\r\n this.state.checkBar.checkedRows.clear();\r\n this.state.checkBar.checkableRows.clear();\r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.render();\r\n this.events.onDataChange?.([]);\r\n }\r\n\r\n // --- Public API: Row Selection ---\r\n\r\n getSelectedRows(): number[] {\r\n return Array.from(this.state.selection.selectedRows).sort((a, b) => a - b);\r\n }\r\n\r\n getSelectedData(): RowData[] {\r\n return this.getSelectedRows()\r\n .map(i => this.state.displayData[i])\r\n .filter(Boolean)\r\n .map(row => ({ ...row }));\r\n }\r\n\r\n selectRow(index: number, selected = true): void {\r\n if (selected) {\r\n if (this.options.selectionMode === 'single') this.state.selection.selectedRows.clear();\r\n this.state.selection.selectedRows.add(index);\r\n } else {\r\n this.state.selection.selectedRows.delete(index);\r\n }\r\n this.render();\r\n this.events.onRowSelect?.(index, selected);\r\n this.events.onSelectionChange?.(this.getSelectedRows());\r\n }\r\n\r\n selectAll(selected = true): void {\r\n if (selected) {\r\n for (let i = 0; i < this.state.displayData.length; i++) {\r\n this.state.selection.selectedRows.add(i);\r\n }\r\n } else {\r\n this.state.selection.selectedRows.clear();\r\n }\r\n this.render();\r\n this.events.onAllSelect?.(selected);\r\n this.events.onSelectionChange?.(this.getSelectedRows());\r\n }\r\n\r\n clearSelection(): void {\r\n this.clearSelectionState();\r\n this.render();\r\n this.events.onSelectionChange?.([]);\r\n this.events.onCellSelectionChange?.([]);\r\n }\r\n\r\n isRowSelected(index: number): boolean {\r\n return this.state.selection.selectedRows.has(index);\r\n }\r\n\r\n // --- Public API: Cell Selection ---\r\n\r\n selectCell(rowIndex: number, field: string, selected = true): void {\r\n const cellKey = `${rowIndex}:${field}`;\r\n if (selected) {\r\n this.state.selection.selectedCells.add(cellKey);\r\n } else {\r\n this.state.selection.selectedCells.delete(cellKey);\r\n }\r\n this.render();\r\n this.events.onCellSelect?.({ rowIndex, field }, selected);\r\n this.events.onCellSelectionChange?.(this.getSelectedCells());\r\n }\r\n\r\n getSelectedCells(): CellIndex[] {\r\n return Array.from(this.state.selection.selectedCells).map(key => {\r\n const [rowIndex, field] = key.split(':');\r\n return { rowIndex: parseInt(rowIndex, 10), field };\r\n });\r\n }\r\n\r\n setFocusedCell(rowIndex: number, field: string): void {\r\n this.state.selection.focusedCell = { rowIndex, field };\r\n this.render();\r\n }\r\n\r\n getFocusedCell(): CellIndex | null {\r\n return this.state.selection.focusedCell;\r\n }\r\n\r\n setSelection(selection: Selection): void {\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.selectedRows.clear();\r\n \r\n if (selection.style === 'row') {\r\n for (let r = selection.startRow; r <= selection.endRow; r++) {\r\n this.state.selection.selectedRows.add(r);\r\n }\r\n } else if (selection.style === 'cell' || selection.style === 'block') {\r\n if (selection.startColumn && selection.endColumn) {\r\n this.selectCellRange(selection.startRow, selection.startColumn, selection.endRow, selection.endColumn);\r\n }\r\n }\r\n \r\n this.state.selection.selections = [selection];\r\n this.render();\r\n }\r\n\r\n getSelection(): Selection | null {\r\n const selections = this.state.selection.selections;\r\n return selections.length > 0 ? selections[0] : null;\r\n }\r\n\r\n getSelectionData(): CellValue[][] {\r\n const cells = this.getSelectedCells();\r\n if (cells.length === 0) return [];\r\n \r\n const rowIndices = [...new Set(cells.map(c => c.rowIndex))].sort((a, b) => a - b);\r\n const fields = [...new Set(cells.map(c => c.field))];\r\n \r\n const columns = this.getVisibleColumns();\r\n const orderedFields = columns.filter(c => fields.includes(c.field)).map(c => c.field);\r\n \r\n const result: CellValue[][] = [];\r\n for (const rowIndex of rowIndices) {\r\n const rowData = this.state.displayData[rowIndex];\r\n if (rowData) {\r\n const row: CellValue[] = orderedFields.map(field => rowData[field]);\r\n result.push(row);\r\n }\r\n }\r\n \r\n return result;\r\n }\r\n\r\n // --- Public API: CheckBar ---\r\n\r\n checkItem(index: number, checked = true): void {\r\n console.log('🔵 checkItem START', { index, checked, currentEditState: this.state.edit });\r\n if (!this.state.checkBar.checkableRows.has(index)) return;\r\n \r\n const checkBar = this.options.checkBar;\r\n \r\n if (checkBar?.exclusive && checked) {\r\n this.state.checkBar.checkedRows.clear();\r\n }\r\n \r\n if (checked) {\r\n this.state.checkBar.checkedRows.add(index);\r\n } else {\r\n this.state.checkBar.checkedRows.delete(index);\r\n }\r\n \r\n // Edit 상태 보존하면서 render\r\n const editState = { ...this.state.edit };\r\n console.log('💾 Saved edit state before render', editState);\r\n this.render();\r\n console.log('🔄 Render complete, edit state after render', this.state.edit);\r\n \r\n // Edit 중이었다면 상태 복원 및 재렌더링\r\n if (editState.editing && editState.rowIndex !== null && editState.field !== null) {\r\n console.log('♻️ Restoring edit state', editState);\r\n this.state.edit = editState;\r\n this.renderEditCell(editState.rowIndex, editState.field, editState.originalValue);\r\n }\r\n \r\n this.events.onCheckChange?.(index, checked);\r\n console.log('🔵 checkItem END');\r\n }\r\n\r\n checkItems(indices: number[], checked = true): void {\r\n indices.forEach(index => {\r\n if (this.state.checkBar.checkableRows.has(index)) {\r\n if (checked) {\r\n this.state.checkBar.checkedRows.add(index);\r\n } else {\r\n this.state.checkBar.checkedRows.delete(index);\r\n }\r\n }\r\n });\r\n this.render();\r\n }\r\n\r\n checkAll(checked = true): void {\r\n if (this.options.checkBar?.exclusive) return;\r\n \r\n if (checked) {\r\n this.state.checkBar.checkableRows.forEach(index => {\r\n this.state.checkBar.checkedRows.add(index);\r\n });\r\n } else {\r\n this.state.checkBar.checkedRows.clear();\r\n }\r\n \r\n this.render();\r\n this.events.onCheckAllChange?.(checked);\r\n }\r\n\r\n uncheckAll(): void {\r\n this.checkAll(false);\r\n }\r\n\r\n getCheckedItems(): number[] {\r\n return Array.from(this.state.checkBar.checkedRows).sort((a, b) => a - b);\r\n }\r\n\r\n getCheckedData(): RowData[] {\r\n return this.getCheckedItems()\r\n .map(i => this.state.displayData[i])\r\n .filter(Boolean)\r\n .map(row => ({ ...row }));\r\n }\r\n\r\n isItemChecked(index: number): boolean {\r\n return this.state.checkBar.checkedRows.has(index);\r\n }\r\n\r\n isItemCheckable(index: number): boolean {\r\n return this.state.checkBar.checkableRows.has(index);\r\n }\r\n\r\n checkRow(index: number, checked = true): void { this.checkItem(index, checked); }\r\n getCheckedRows(): number[] { return this.getCheckedItems(); }\r\n\r\n // --- Public API: Sort ---\r\n\r\n sort(field: string, direction: SortDirection = 'asc'): void {\r\n this.state.sort = direction ? [{ field, direction }] : [];\r\n this.clearSelectionState();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onSort?.(this.state.sort);\r\n }\r\n\r\n clearSort(): void {\r\n this.state.sort = [];\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onSort?.([]);\r\n }\r\n\r\n getSortState(): SortState[] {\r\n return [...this.state.sort];\r\n }\r\n\r\n // --- Public API: Filter ---\r\n\r\n filter(conditions: FilterCondition | FilterCondition[]): void {\r\n const conditionArray = Array.isArray(conditions) ? conditions : [conditions];\r\n this.state.filter = { conditions: conditionArray, logic: 'and' };\r\n this.clearSelectionState();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onFilter?.(this.state.filter);\r\n }\r\n\r\n clearFilter(): void {\r\n this.state.filter = null;\r\n this.clearSelectionState();\r\n this.applyDataTransformations();\r\n this.render();\r\n }\r\n\r\n getFilterState(): FilterState | null {\r\n return this.state.filter ? { ...this.state.filter } : null;\r\n }\r\n\r\n // --- Public API: Edit ---\r\n\r\n startEdit(rowIndex: number, field: string): void {\r\n console.log('🎬 startEdit called', { rowIndex, field, editable: this.options.editable });\r\n if (!this.options.editable) return;\r\n \r\n // 이미 같은 셀을 편집 중이면 무시\r\n if (this.state.edit.editing && \r\n this.state.edit.rowIndex === rowIndex && \r\n this.state.edit.field === field) {\r\n console.log('⚠️ Already editing this cell - ignoring startEdit');\r\n return;\r\n }\r\n \r\n const column = this.state.columns.find(c => c.field === field);\r\n console.log('📋 Column found', { column: column?.field, editable: column?.editable });\r\n if (!column || column.editable === false) return;\r\n if (this.state.edit.editing) this.endEdit(true);\r\n const value = this.state.displayData[rowIndex]?.[field];\r\n this.state.edit = { editing: true, rowIndex, field, originalValue: value };\r\n console.log('✅ Edit state updated', this.state.edit);\r\n this.events.onCellEditStart?.(rowIndex, field, value);\r\n this.renderEditCell(rowIndex, field, value);\r\n }\r\n\r\n renderEditCell(rowIndex: number, field: string, value: CellValue): void {\r\n console.log('🎨 renderEditCell START', { rowIndex, field, value, currentEditState: this.state.edit });\r\n \r\n // 이전 edit mode의 document 리스너 정리\r\n if (this.editModeCleanup) {\r\n console.log('🧹 Cleaning up previous edit mode listener');\r\n this.editModeCleanup();\r\n this.editModeCleanup = null;\r\n }\r\n \r\n const row = this.bodyInner.querySelector(`[data-row-index=\"${rowIndex}\"]`);\r\n const cell = row?.querySelector(`[data-field=\"${field}\"]`) as HTMLElement;\r\n console.log('🔍 Cell element found', { cell: !!cell, hasClass: cell?.classList.contains('velox-cell--editing') });\r\n if (!cell) return;\r\n\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (!column) return;\r\n\r\n addClass(cell, 'velox-cell--editing');\r\n console.log('✅ Added velox-cell--editing class', { classList: Array.from(cell.classList) });\r\n \r\n // Document click으로 외부 클릭 감지 (cell/input 클릭은 제외)\r\n const handleOutsideClick = (e: MouseEvent) => {\r\n const target = e.target as Node;\r\n if (!cell.contains(target)) {\r\n console.log('🌍 Outside click detected - ending edit');\r\n this.editModeCleanup = null; // cleanup 실행됨\r\n document.removeEventListener('mousedown', handleOutsideClick);\r\n this.endEdit(true);\r\n } else {\r\n console.log('📦 Inside cell click - maintaining edit mode');\r\n }\r\n };\r\n \r\n // cleanup 함수 저장\r\n this.editModeCleanup = () => {\r\n document.removeEventListener('mousedown', handleOutsideClick);\r\n };\r\n \r\n setTimeout(() => {\r\n document.addEventListener('mousedown', handleOutsideClick);\r\n }, 0);\r\n\r\n // Phase 12.2: Use GridEditorFactory if editor is specified\r\n if (column.editor) {\r\n const editor = GridEditorFactory.createEditor(\r\n value,\r\n column.editor,\r\n (newValue) => {\r\n // Save callback\r\n console.log('💾 Editor save callback', { newValue, editing: this.state.edit.editing });\r\n \r\n // Phase 15: Use setCellValue to update row state\r\n this.setCellValue(rowIndex, field, newValue);\r\n \r\n // Checkbox editor는 edit 모드를 유지 (즉시 종료하지 않음)\r\n if (column.editor?.type === 'checkbox') {\r\n console.log('✅ Checkbox editor - maintaining edit mode, new value:', newValue);\r\n \r\n // originalValue를 새 값으로 업데이트 (다음 렌더링에서 사용)\r\n this.state.edit.originalValue = newValue;\r\n \r\n // Edit 상태 보존\r\n const editState = { ...this.state.edit };\r\n \r\n // Edit 모드 복원 (새 값으로 렌더링)\r\n if (editState.editing) {\r\n this.state.edit = editState;\r\n this.renderEditCell(editState.rowIndex!, editState.field!, newValue);\r\n }\r\n } else {\r\n // 다른 editor는 기존대로 edit 종료\r\n console.log('🛑 Other editor - ending edit mode');\r\n this.state.edit.editing = false;\r\n this.applyDataTransformations();\r\n this.render();\r\n }\r\n \r\n const event = this.events as any;\r\n if (event.onCellEditEnd) {\r\n event.onCellEditEnd({\r\n rowIndex,\r\n field,\r\n oldValue: value,\r\n newValue,\r\n row: this.state.displayData[rowIndex]\r\n });\r\n }\r\n },\r\n () => {\r\n // Cancel callback\r\n this.cancelEdit();\r\n },\r\n (direction: 'up' | 'down' | 'left' | 'right') => {\r\n // Move callback for Enter/Tab keys (Phase 15.1)\r\n this.endEditAndMove(direction);\r\n }\r\n );\r\n\r\n cell.innerHTML = '';\r\n cell.appendChild(editor);\r\n \r\n // 편집 중인 editor 클릭 로그용\r\n editor.addEventListener('mousedown', () => {\r\n console.log('🖱️ Editor mousedown');\r\n });\r\n \r\n // Focus the editor\r\n setTimeout(() => {\r\n if (editor instanceof HTMLInputElement || editor instanceof HTMLSelectElement) {\r\n editor.focus();\r\n if (editor instanceof HTMLInputElement && editor.type === 'text') {\r\n editor.select();\r\n }\r\n }\r\n }, 0);\r\n } else {\r\n // 기존 text input 방식\r\n const input = createElement('input', 'velox-edit-input') as HTMLInputElement;\r\n input.type = column.type === 'number' ? 'number' : 'text';\r\n input.value = value != null ? String(value) : '';\r\n\r\n cell.innerHTML = '';\r\n cell.appendChild(input);\r\n input.focus();\r\n input.select();\r\n \r\n // Input mousedown 로그용\r\n input.addEventListener('mousedown', () => {\r\n console.log('🖱️ Input mousedown');\r\n });\r\n\r\n input.addEventListener('keydown', (e) => {\r\n console.log('⌨️ Input keydown:', e.key, { shiftKey: e.shiftKey });\r\n \r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n console.log('✅ Enter detected - calling endEditAndMove');\r\n // endEditAndMove가 내부적으로 endEdit(true)를 호출함\r\n this.endEditAndMove(e.shiftKey ? 'up' : 'down');\r\n } else if (e.key === 'Tab') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n console.log('✅ Tab detected - calling endEditAndMove');\r\n // endEditAndMove가 내부적으로 endEdit(true)를 호출함\r\n this.endEditAndMove(e.shiftKey ? 'left' : 'right');\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n console.log('✅ Escape detected - calling cancelEdit');\r\n this.cancelEdit();\r\n }\r\n });\r\n }\r\n }\r\n\r\n endEdit(save = true): void {\r\n console.log('🛑 endEdit called', { save, editing: this.state.edit.editing });\r\n \r\n // Document 리스너 정리\r\n if (this.editModeCleanup) {\r\n console.log('🧹 Cleaning up edit mode listener on endEdit');\r\n this.editModeCleanup();\r\n this.editModeCleanup = null;\r\n }\r\n \r\n if (!this.state.edit.editing) return;\r\n const { rowIndex, field, originalValue } = this.state.edit;\r\n if (rowIndex === null || field === null) return;\r\n \r\n const row = this.bodyInner.querySelector(`[data-row-index=\"${rowIndex}\"]`);\r\n const cell = row?.querySelector(`[data-field=\"${field}\"]`);\r\n \r\n if (save && cell) {\r\n const column = this.state.columns.find(c => c.field === field);\r\n const displayRow = this.state.displayData[rowIndex];\r\n \r\n // Phase 12.2: Get value from different editor types\r\n let newValue: CellValue = originalValue;\r\n \r\n const input = cell.querySelector('.velox-edit-input') as HTMLInputElement;\r\n const select = cell.querySelector('.velox-editor--select') as HTMLSelectElement;\r\n const checkbox = cell.querySelector('.velox-editor--checkbox input[type=\"checkbox\"]') as HTMLInputElement;\r\n const dateInput = cell.querySelector('.velox-editor--date') as HTMLInputElement;\r\n const numberInput = cell.querySelector('.velox-editor--number') as HTMLInputElement;\r\n \r\n if (checkbox) {\r\n // Checkbox editor\r\n newValue = checkbox.checked;\r\n } else if (select) {\r\n // Select editor\r\n if (select.multiple) {\r\n newValue = Array.from(select.selectedOptions).map(opt => opt.value);\r\n } else {\r\n newValue = select.value;\r\n }\r\n } else if (dateInput) {\r\n // Date editor\r\n newValue = dateInput.value;\r\n } else if (numberInput) {\r\n // Number editor\r\n newValue = numberInput.value === '' ? null : Number(numberInput.value);\r\n } else if (input) {\r\n // Default text/number input\r\n newValue = input.value;\r\n }\r\n \r\n // Check if value changed\r\n const valueChanged = JSON.stringify(newValue) !== JSON.stringify(originalValue);\r\n \r\n if (valueChanged) {\r\n // Phase 12.1: Validation\r\n if (column?.validation && column.validation.length > 0) {\r\n const parsedValue = column.type === 'number' && typeof newValue === 'string' \r\n ? parseFloat(newValue) \r\n : newValue;\r\n const validationResult = GridValidator.validate(parsedValue, column.validation, displayRow);\r\n \r\n if (!validationResult.valid) {\r\n // Validation failed - show error\r\n if (cell) {\r\n addClass(cell as HTMLElement, 'velox-cell--invalid');\r\n \r\n // Show error tooltip\r\n const errors = validationResult.errors.map(e => e.message).join(', ');\r\n (cell as HTMLElement).title = errors;\r\n }\r\n \r\n // Fire validation error event\r\n this.events.onValidationError?.({\r\n rowIndex,\r\n field,\r\n value: parsedValue,\r\n errors: validationResult.errors.map(e => e.message)\r\n });\r\n \r\n // Keep editing mode - focus input\r\n if (input) input.focus();\r\n else if (select) select.focus();\r\n else if (dateInput) dateInput.focus();\r\n else if (numberInput) numberInput.focus();\r\n return;\r\n }\r\n }\r\n \r\n // Validation passed - save the value\r\n const parsedValue = column?.type === 'number' && typeof newValue === 'string'\r\n ? parseFloat(newValue)\r\n : newValue;\r\n \r\n // Phase 15: Use setCellValue to update row state\r\n this.setCellValue(rowIndex, field, parsedValue);\r\n \r\n this.events.onCellEditEnd?.({\r\n rowIndex,\r\n field,\r\n oldValue: originalValue,\r\n newValue: parsedValue,\r\n row: this.state.displayData[rowIndex]\r\n });\r\n }\r\n } else {\r\n this.events.onCellEditCancel?.(rowIndex, field);\r\n }\r\n \r\n this.state.edit = { editing: false, rowIndex: null, field: null, originalValue: null };\r\n this.applyDataTransformations();\r\n this.render();\r\n }\r\n\r\n cancelEdit(): void { this.endEdit(false); }\r\n isEditing(): boolean { return this.state.edit.editing; }\r\n\r\n /**\r\n * End edit and move to adjacent cell (Phase 9)\r\n */\r\n private endEditAndMove(direction: 'up' | 'down' | 'left' | 'right'): void {\r\n const { rowIndex, field } = this.state.edit;\r\n if (rowIndex === null || field === null) return;\r\n \r\n this.endEdit(true);\r\n \r\n const columns = this.getVisibleColumns();\r\n const currentColIndex = columns.findIndex(c => c.field === field);\r\n let newRowIndex = rowIndex;\r\n let newColIndex = currentColIndex;\r\n \r\n switch (direction) {\r\n case 'up':\r\n if (newRowIndex > 0) newRowIndex--;\r\n break;\r\n case 'down':\r\n if (newRowIndex < this.state.displayData.length - 1) newRowIndex++;\r\n break;\r\n case 'left':\r\n if (newColIndex > 0) newColIndex--;\r\n else if (newRowIndex > 0) {\r\n newRowIndex--;\r\n newColIndex = columns.length - 1;\r\n }\r\n break;\r\n case 'right':\r\n if (newColIndex < columns.length - 1) newColIndex++;\r\n else if (newRowIndex < this.state.displayData.length - 1) {\r\n newRowIndex++;\r\n newColIndex = 0;\r\n }\r\n break;\r\n }\r\n \r\n const newField = columns[newColIndex]?.field;\r\n if (newField) {\r\n this.setFocusedCell(newRowIndex, newField);\r\n this.state.selection.selectedCells.clear();\r\n this.state.selection.selectedCells.add(`${newRowIndex}:${newField}`);\r\n this.scrollToCell(newRowIndex, newField);\r\n this.render();\r\n \r\n // 편집 종료 후 grid에 focus 복원 (Phase 15.1: keyboard navigation)\r\n this.rootElement.focus();\r\n }\r\n }\r\n\r\n // --- Public API: Column ---\r\n\r\n getColumn(field: string): ColumnDefinition | null {\r\n return this.state.columns.find(c => c.field === field) || null;\r\n }\r\n\r\n setColumnWidth(field: string, width: number): void {\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (column) {\r\n column.width = width;\r\n this.invalidateColumnCache();\r\n this.render();\r\n this.events.onColumnResize?.(field, width);\r\n }\r\n }\r\n\r\n showColumn(field: string): void {\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (column) {\r\n column.visible = true;\r\n this.invalidateColumnCache();\r\n this.render();\r\n }\r\n }\r\n\r\n hideColumn(field: string): void {\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (column) {\r\n column.visible = false;\r\n this.invalidateColumnCache();\r\n this.render();\r\n }\r\n }\r\n\r\n setColumns(columns: ColumnDefinition[]): void {\r\n this.state.columns = columns.map(col => ({ ...col }));\r\n this.invalidateColumnCache();\r\n this.render();\r\n }\r\n\r\n autoFitColumn(field: string): void {\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (!column) return;\r\n \r\n let maxWidth = 100;\r\n \r\n const headerText = column.header || '';\r\n maxWidth = Math.max(maxWidth, this.measureTextWidth(headerText) + 40);\r\n \r\n this.state.displayData.forEach(row => {\r\n const value = row[column.field];\r\n const text = formatValue(value, column.type);\r\n const width = this.measureTextWidth(text) + 20;\r\n maxWidth = Math.max(maxWidth, width);\r\n });\r\n \r\n column.width = Math.min(maxWidth, 500);\r\n this.invalidateColumnCache();\r\n this.render();\r\n this.events.onColumnResize?.(field, column.width);\r\n }\r\n\r\n autoFitAllColumns(): void {\r\n this.getVisibleColumns().forEach(col => this.autoFitColumn(col.field));\r\n }\r\n\r\n // GridContext: Text measurement (public for module access)\r\n measureTextWidth(text: string, font?: string): number {\r\n // Reuse canvas instance for better performance\r\n if (!this.measureCanvas) {\r\n this.measureCanvas = document.createElement('canvas');\r\n this.measureContext = this.measureCanvas.getContext('2d');\r\n }\r\n if (!this.measureContext) return 100;\r\n \r\n // Apply font if provided, otherwise use default\r\n this.measureContext.font = font || '14px sans-serif';\r\n return this.measureContext.measureText(text).width;\r\n }\r\n\r\n // --- Public API: Scroll ---\r\n\r\n scrollToRow(index: number): void {\r\n const rowHeight = this.options.rowHeight || 40;\r\n this.bodyElement.scrollTop = index * rowHeight;\r\n if (this.fixedLeftBody) this.fixedLeftBody.scrollTop = index * rowHeight;\r\n }\r\n\r\n scrollToTop(): void {\r\n this.bodyElement.scrollTop = 0;\r\n if (this.fixedLeftBody) this.fixedLeftBody.scrollTop = 0;\r\n }\r\n\r\n scrollToBottom(): void {\r\n this.bodyElement.scrollTop = this.bodyElement.scrollHeight;\r\n if (this.fixedLeftBody) this.fixedLeftBody.scrollTop = this.fixedLeftBody.scrollHeight;\r\n }\r\n\r\n scrollToCell(rowIndex: number, field: string): void {\r\n const rowHeight = this.options.rowHeight || 40;\r\n const containerHeight = this.bodyElement.clientHeight;\r\n const currentScrollTop = this.bodyElement.scrollTop;\r\n \r\n const rowTop = rowIndex * rowHeight;\r\n const rowBottom = rowTop + rowHeight;\r\n \r\n if (rowTop < currentScrollTop) {\r\n this.bodyElement.scrollTop = rowTop;\r\n } else if (rowBottom > currentScrollTop + containerHeight) {\r\n this.bodyElement.scrollTop = rowBottom - containerHeight;\r\n }\r\n \r\n if (this.fixedLeftBody) {\r\n this.fixedLeftBody.scrollTop = this.bodyElement.scrollTop;\r\n }\r\n \r\n const cell = this.bodyInner.querySelector(`[data-field=\"${field}\"]`) as HTMLElement;\r\n if (cell) {\r\n const cellLeft = cell.offsetLeft;\r\n const cellRight = cellLeft + cell.offsetWidth;\r\n const containerWidth = this.bodyElement.clientWidth;\r\n const currentScrollLeft = this.bodyElement.scrollLeft;\r\n \r\n if (cellLeft < currentScrollLeft) {\r\n this.bodyElement.scrollLeft = cellLeft;\r\n } else if (cellRight > currentScrollLeft + containerWidth) {\r\n this.bodyElement.scrollLeft = cellRight - containerWidth;\r\n }\r\n }\r\n }\r\n\r\n // --- Public API: Clipboard ---\r\n\r\n copy(): void {\r\n const data = this.getSelectionData();\r\n if (data.length === 0) return;\r\n \r\n const text = data.map(row => row.join('\\t')).join('\\n');\r\n navigator.clipboard.writeText(text).then(() => {\r\n this.events.onCopy?.(data.map(row => row.map(v => String(v ?? ''))));\r\n });\r\n }\r\n\r\n paste(): void {\r\n const focusedCell = this.state.selection.focusedCell;\r\n if (!focusedCell) return;\r\n \r\n navigator.clipboard.readText().then(text => {\r\n const rows = text.split('\\n').map(row => row.split('\\t'));\r\n this.events.onPaste?.(rows, focusedCell);\r\n \r\n const columns = this.getVisibleColumns();\r\n const startColIndex = columns.findIndex(c => c.field === focusedCell.field);\r\n \r\n rows.forEach((row, rOffset) => {\r\n const rowIndex = focusedCell.rowIndex + rOffset;\r\n if (rowIndex >= this.state.displayData.length) return;\r\n \r\n row.forEach((value, cOffset) => {\r\n const colIndex = startColIndex + cOffset;\r\n if (colIndex >= columns.length) return;\r\n \r\n const field = columns[colIndex].field;\r\n const column = columns[colIndex];\r\n \r\n if (column.editable !== false) {\r\n const displayRow = this.state.displayData[rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][field] = column.type === 'number' ? parseFloat(value) : value;\r\n }\r\n }\r\n });\r\n });\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onDataChange?.(this.state.data);\r\n });\r\n }\r\n\r\n cut(): void {\r\n const data = this.getSelectionData();\r\n if (data.length === 0) return;\r\n \r\n this.copy();\r\n \r\n // Collect changes for undo\r\n const changes: BulkEditUndoData['changes'] = [];\r\n \r\n const cells = this.getSelectedCells();\r\n cells.forEach(cell => {\r\n const column = this.state.columns.find(c => c.field === cell.field);\r\n if (column?.editable !== false) {\r\n const displayRow = this.state.displayData[cell.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n const oldValue = this.state.data[dataIndex][cell.field];\r\n changes.push({\r\n rowIndex: cell.rowIndex,\r\n field: cell.field,\r\n oldValue,\r\n newValue: ''\r\n });\r\n this.state.data[dataIndex][cell.field] = '';\r\n }\r\n }\r\n });\r\n \r\n // Push to undo stack\r\n if (changes.length > 0) {\r\n this.pushUndo({ type: 'cut', timestamp: Date.now(), data: { changes } as BulkEditUndoData });\r\n }\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onCut?.(data.map(row => row.map(v => String(v ?? ''))));\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n\r\n // --- Public API: Undo/Redo ---\r\n\r\n pushUndo(action: UndoAction): void {\r\n this.history.push(action);\r\n }\r\n\r\n undo(): boolean {\r\n const action = this.history.popUndo();\r\n if (!action) return false;\r\n \r\n switch (action.type) {\r\n case 'cell_edit': {\r\n const data = action.data as CellEditUndoData;\r\n const displayRow = this.state.displayData[data.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][data.field] = data.oldValue;\r\n }\r\n break;\r\n }\r\n case 'bulk_edit':\r\n case 'paste':\r\n case 'cut':\r\n case 'delete': {\r\n const data = action.data as BulkEditUndoData;\r\n data.changes.forEach(change => {\r\n const displayRow = this.state.displayData[change.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][change.field] = change.oldValue;\r\n }\r\n });\r\n break;\r\n }\r\n case 'row_add': {\r\n const data = action.data as RowAddUndoData;\r\n this.state.data.splice(data.index, 1);\r\n this.rebuildDataIndexMap();\r\n break;\r\n }\r\n case 'row_remove': {\r\n const data = action.data as RowRemoveUndoData;\r\n this.state.data.splice(data.index, 0, { ...data.row });\r\n this.rebuildDataIndexMap();\r\n break;\r\n }\r\n }\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onUndo?.(action);\r\n this.events.onDataChange?.(this.state.data);\r\n \r\n return true;\r\n }\r\n\r\n redo(): boolean {\r\n const action = this.history.popRedo();\r\n if (!action) return false;\r\n \r\n switch (action.type) {\r\n case 'cell_edit': {\r\n const data = action.data as CellEditUndoData;\r\n const displayRow = this.state.displayData[data.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][data.field] = data.newValue;\r\n }\r\n break;\r\n }\r\n case 'bulk_edit':\r\n case 'paste':\r\n case 'cut':\r\n case 'delete': {\r\n const data = action.data as BulkEditUndoData;\r\n data.changes.forEach(change => {\r\n const displayRow = this.state.displayData[change.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][change.field] = change.newValue;\r\n }\r\n });\r\n break;\r\n }\r\n case 'row_add': {\r\n const data = action.data as RowAddUndoData;\r\n this.state.data.splice(data.index, 0, { ...data.row });\r\n this.rebuildDataIndexMap();\r\n break;\r\n }\r\n case 'row_remove': {\r\n const data = action.data as RowRemoveUndoData;\r\n this.state.data.splice(data.index, 1);\r\n this.rebuildDataIndexMap();\r\n break;\r\n }\r\n }\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onRedo?.(action);\r\n this.events.onDataChange?.(this.state.data);\r\n \r\n return true;\r\n }\r\n\r\n canUndo(): boolean {\r\n return this.history.canUndo();\r\n }\r\n\r\n canRedo(): boolean {\r\n return this.history.canRedo();\r\n }\r\n\r\n clearHistory(): void {\r\n this.history.clear();\r\n }\r\n\r\n // --- Public API: Delete ---\r\n\r\n deleteSelectedCells(): void {\r\n if (!this.options.editable) return;\r\n \r\n const cells = this.getSelectedCells();\r\n if (cells.length === 0) return;\r\n \r\n const changes: BulkEditUndoData['changes'] = [];\r\n \r\n cells.forEach(cell => {\r\n const column = this.state.columns.find(c => c.field === cell.field);\r\n if (column?.editable !== false) {\r\n const displayRow = this.state.displayData[cell.rowIndex];\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n const oldValue = this.state.data[dataIndex][cell.field];\r\n if (oldValue !== '' && oldValue !== null && oldValue !== undefined) {\r\n changes.push({\r\n rowIndex: cell.rowIndex,\r\n field: cell.field,\r\n oldValue,\r\n newValue: ''\r\n });\r\n this.state.data[dataIndex][cell.field] = '';\r\n }\r\n }\r\n }\r\n });\r\n \r\n if (changes.length > 0) {\r\n this.pushUndo({ type: 'delete', timestamp: Date.now(), data: { changes } as BulkEditUndoData });\r\n this.applyDataTransformations();\r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.render();\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n }\r\n\r\n deleteSelectedRows(): void {\r\n const selectedRows = this.getSelectedRows();\r\n if (selectedRows.length === 0) return;\r\n \r\n // Sort in reverse order to delete from end first\r\n const sortedRows = [...selectedRows].sort((a, b) => b - a);\r\n \r\n sortedRows.forEach(index => {\r\n this.removeRow(index);\r\n });\r\n }\r\n\r\n // --- Public API: Export/Import ---\r\n\r\n private createExportContext(options: ExportOptions = {}): ExportContext {\r\n return {\r\n data: this.state.data,\r\n displayData: this.state.displayData,\r\n columns: this.state.columns,\r\n selectedRows: this.getSelectedRows(),\r\n options,\r\n };\r\n }\r\n\r\n /**\r\n * Export grid data to Excel (.xlsx) file\r\n * Requires SheetJS library to be loaded via CDN:\r\n * <script src=\"https://cdn.sheetjs.com/xlsx-0.20.1/package/dist/xlsx.full.min.js\"></script>\r\n */\r\n exportToExcel(options: ExportOptions = {}): void {\r\n const context = this.createExportContext(options);\r\n exportToExcelUtil(context);\r\n }\r\n\r\n /**\r\n * Export grid data to CSV format\r\n * @returns CSV string\r\n */\r\n exportToCSV(options: ExportOptions = {}): string {\r\n const context = this.createExportContext(options);\r\n return exportToCSVUtil(context);\r\n }\r\n\r\n /**\r\n * Export grid data to JSON format\r\n * @returns JSON string\r\n */\r\n exportToJSON(options: ExportOptions = {}): string {\r\n const context = this.createExportContext(options);\r\n return exportToJSONUtil(context);\r\n }\r\n\r\n /**\r\n * Download grid data as CSV file\r\n */\r\n downloadCSV(options: ExportOptions = {}): void {\r\n const context = this.createExportContext(options);\r\n downloadCSV(context);\r\n }\r\n\r\n /**\r\n * Download grid data as JSON file\r\n */\r\n downloadJSON(options: ExportOptions = {}): void {\r\n const context = this.createExportContext(options);\r\n downloadJSON(context);\r\n }\r\n\r\n /**\r\n * Import data from CSV string\r\n * @param csvString CSV content\r\n * @param hasHeader Whether first row is header (default: true)\r\n */\r\n importFromCSV(csvString: string, hasHeader = true): ImportResult {\r\n const result = parseCSV(csvString, hasHeader);\r\n if (result.errors.length === 0 && result.data.length > 0) {\r\n this.setData(result.data);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Import data from Excel file\r\n * Requires SheetJS library to be loaded via CDN\r\n * @param file Excel file (File object)\r\n * @param sheetIndex Sheet index to import (default: 0)\r\n */\r\n async importFromExcel(file: File, sheetIndex = 0): Promise<ImportResult> {\r\n const result = await importFromExcel(file, sheetIndex);\r\n if (result.errors.length === 0 && result.data.length > 0) {\r\n this.setData(result.data);\r\n }\r\n return result;\r\n }\r\n\r\n /**\r\n * Check if SheetJS library is available for Excel operations\r\n */\r\n static isExcelSupported(): boolean {\r\n return isSheetJSAvailable();\r\n }\r\n\r\n // ============================================\r\n // Public API - Utility Methods\r\n // ============================================\r\n\r\n getCellValue(rowIndex: number, field: string): CellValue {\r\n return this.state.displayData[rowIndex]?.[field];\r\n }\r\n\r\n setCellValue(rowIndex: number, field: string, value: CellValue): void {\r\n const displayRow = this.state.displayData[rowIndex];\r\n if (!displayRow) return;\r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex >= 0) {\r\n this.state.data[dataIndex][field] = value;\r\n \r\n // Phase 15: Update row state\r\n const currentState = this.state.rowStates.get(this.state.data[dataIndex]) || 'none';\r\n if (currentState === 'none') {\r\n this.state.rowStates.set(this.state.data[dataIndex], 'updated');\r\n }\r\n // If 'created', stay 'created'\r\n // If 'updated', stay 'updated'\r\n \r\n // Invalidate summary cache\r\n this.summary.invalidateCache();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n }\r\n\r\n // ============================================\r\n // Phase 13: Summary Methods\r\n // ============================================\r\n\r\n /**\r\n * Get summary value for a specific field\r\n * @param field Column field name\r\n * @returns Calculated summary value\r\n */\r\n getSummaryValue(field: string): CellValue {\r\n return this.summary.getSummaryValue(field);\r\n }\r\n\r\n /**\r\n * Get all summary values\r\n * @returns Object with field names as keys and summary values\r\n */\r\n getSummaryValues(): Record<string, CellValue> {\r\n return this.summary.getAllSummaryValues();\r\n }\r\n\r\n /**\r\n * Refresh summary calculations (clear cache)\r\n */\r\n refreshSummary(): void {\r\n this.summary.invalidateCache();\r\n this.render();\r\n }\r\n\r\n setOptions(options: Partial<GridOptions>): void {\r\n this.options = { ...this.options, ...options };\r\n \r\n if (options.checkBar) {\r\n this.options.checkBar = { ...DEFAULT_CHECKBAR, ...options.checkBar };\r\n }\r\n \r\n if (options.columns) {\r\n this.state.columns = options.columns.map(col => ({ ...col }));\r\n }\r\n \r\n if (options.loading !== undefined) {\r\n this.updateLoadingState();\r\n }\r\n \r\n this.render();\r\n }\r\n\r\n getOptions(): GridOptions { \r\n return { ...this.options }; \r\n }\r\n\r\n setLoading(loading: boolean): void {\r\n this.options.loading = loading;\r\n this.updateLoadingState();\r\n }\r\n\r\n refresh(): void {\r\n this.applyDataTransformations();\r\n this.render();\r\n }\r\n\r\n // ============================================\r\n // Phase 10: Column Reorder & Menu\r\n // ============================================\r\n\r\n /**\r\n * Fix/unfix column to a position\r\n */\r\n fixColumn(field: string, position: 'left' | 'right' | false): void {\r\n const column = this.state.columns.find(c => c.field === field);\r\n if (column) {\r\n column.fixed = position;\r\n this.invalidateColumnCache();\r\n this.render();\r\n }\r\n }\r\n\r\n /**\r\n * Reorder column to new position\r\n */\r\n reorderColumn(sourceField: string, targetField: string): void {\r\n const sourceIndex = this.state.columns.findIndex(c => c.field === sourceField);\r\n const targetIndex = this.state.columns.findIndex(c => c.field === targetField);\r\n \r\n if (sourceIndex === -1 || targetIndex === -1) return;\r\n \r\n const [removed] = this.state.columns.splice(sourceIndex, 1);\r\n this.state.columns.splice(targetIndex, 0, removed);\r\n \r\n this.invalidateColumnCache();\r\n this.render();\r\n this.events.onColumnReorder?.(sourceField, sourceIndex, targetIndex);\r\n }\r\n\r\n // GridContext: Column menu methods - delegated to GridColumnMenu\r\n showColumnMenu(column: ColumnDefinition, anchor: HTMLElement): void {\r\n this.closeFilterPopup();\r\n this.columnMenuManager.showColumnMenu(column, anchor);\r\n }\r\n\r\n closeColumnMenu(): void {\r\n this.columnMenuManager.closeColumnMenu();\r\n }\r\n\r\n // GridContext: Column drag methods - delegated to GridDragManager\r\n startColumnDrag(e: MouseEvent, column: ColumnDefinition): void {\r\n this.dragManager.startColumnDrag(e, column);\r\n }\r\n\r\n // ============================================\r\n // Phase 11: Row Drag & Drop\r\n // ============================================\r\n\r\n /**\r\n * Move row to new position\r\n */\r\n moveRow(fromIndex: number, toIndex: number): void {\r\n const displayRow = this.state.displayData[fromIndex];\r\n if (!displayRow) return;\r\n \r\n const dataIndex = this.state.data.indexOf(displayRow);\r\n if (dataIndex === -1) return;\r\n \r\n const targetDisplayRow = this.state.displayData[toIndex];\r\n const targetDataIndex = targetDisplayRow ? this.state.data.indexOf(targetDisplayRow) : this.state.data.length;\r\n \r\n const [removed] = this.state.data.splice(dataIndex, 1);\r\n const adjustedTargetIndex = targetDataIndex > dataIndex ? targetDataIndex - 1 : targetDataIndex;\r\n this.state.data.splice(adjustedTargetIndex, 0, removed);\r\n \r\n this.rebuildDataIndexMap();\r\n this.applyDataTransformations();\r\n this.render();\r\n this.events.onDataChange?.(this.state.data);\r\n }\r\n\r\n // GridContext: Row drag methods - delegated to GridDragManager\r\n startRowDrag(e: MouseEvent, rowIndex: number, rowElement: HTMLElement): void {\r\n this.dragManager.startRowDrag(e, rowIndex, rowElement);\r\n }\r\n\r\n // ============================================\r\n // GridContext Implementation\r\n // ============================================\r\n\r\n /** GridContext: 그리드 상태 반환 */\r\n getState(): GridState {\r\n return this.state;\r\n }\r\n\r\n /** GridContext: 이벤트 핸들러 반환 */\r\n getEvents(): GridEvents {\r\n return this.events;\r\n }\r\n\r\n /** GridContext: 그리드 고유 ID 반환 */\r\n getGridId(): string {\r\n return this.gridId;\r\n }\r\n\r\n /** GridContext: 표시 데이터 반환 */\r\n getDisplayData(): RowData[] {\r\n return this.state.displayData;\r\n }\r\n\r\n /** GridContext: 가상 스크롤 상태 반환 */\r\n getVirtualState(): typeof this.virtualState {\r\n return this.virtualState;\r\n }\r\n\r\n /** GridContext: 이벤트 발행 헬퍼 */\r\n emitEvent<K extends keyof GridEvents>(\r\n event: K, \r\n ...args: Parameters<NonNullable<GridEvents[K]>>\r\n ): void {\r\n const handler = this.events[event];\r\n if (handler) {\r\n (handler as (...args: any[]) => void)(...args);\r\n }\r\n }\r\n\r\n // ============================================\r\n // GridContext: Internal Handlers\r\n // ============================================\r\n\r\n /** GridContext: Block selection 상태 확인 */\r\n isBlockSelecting(): boolean {\r\n return this.blockSelecting !== null;\r\n }\r\n\r\n /** GridContext: Tooltip 표시 */\r\n showTooltip(cell: HTMLElement, value: CellValue, rowData: RowData, column: ColumnDefinition): void {\r\n if (this.tooltip) {\r\n this.tooltip.show(cell, value, rowData, column);\r\n }\r\n }\r\n\r\n /** GridContext: Tooltip 숨기기 */\r\n hideTooltip(): void {\r\n if (this.tooltip) {\r\n this.tooltip.hide();\r\n }\r\n }\r\n\r\n // ============================================\r\n // Phase 14: Fixed Columns\r\n // ============================================\r\n\r\n /**\r\n * Set fixed columns options\r\n * @param options - Fixed options (colCount, rightCount)\r\n */\r\n setFixedOptions(options: import('../types').FixedOptions): void {\r\n const oldOptions = this.options.fixedOptions || { colCount: 0, rightCount: 0 };\r\n const newOptions = {\r\n colCount: options.colCount ?? this.options.fixedOptions?.colCount ?? 0,\r\n rightCount: options.rightCount ?? this.options.fixedOptions?.rightCount ?? 0,\r\n };\r\n \r\n // Check if DOM structure needs to be rebuilt\r\n const needsRebuild = \r\n // Left fixed changes\r\n ((oldOptions.colCount || 0) === 0 && newOptions.colCount > 0) || // Left 추가\r\n ((oldOptions.colCount || 0) > 0 && newOptions.colCount === 0) || // Left 제거\r\n // Right fixed changes\r\n ((oldOptions.rightCount || 0) === 0 && newOptions.rightCount > 0) || // Right 추가\r\n ((oldOptions.rightCount || 0) > 0 && newOptions.rightCount === 0); // Right 제거\r\n \r\n this.options.fixedOptions = newOptions;\r\n \r\n // Invalidate column cache to recalculate partitions\r\n this.invalidateColumnCache();\r\n \r\n if (needsRebuild) {\r\n // Rebuild DOM structure (with re-attaching events)\r\n this.rebuildDOM();\r\n }\r\n \r\n // Re-render grid with new fixed columns\r\n this.render();\r\n }\r\n \r\n /**\r\n * Rebuild DOM structure and re-attach events\r\n * Phase 14: For dynamic fixed columns\r\n */\r\n private rebuildDOM(): void {\r\n // Save current scroll position\r\n const scrollTop = this.bodyElement?.scrollTop || 0;\r\n const scrollLeft = this.bodyElement?.scrollLeft || 0;\r\n \r\n // Detach old event handlers before rebuilding DOM\r\n this.detachEvents();\r\n \r\n // Rebuild DOM\r\n this.build();\r\n \r\n // Re-attach event handlers to new DOM elements\r\n this.attachEvents();\r\n \r\n // Restore scroll position\r\n if (this.bodyElement) {\r\n this.bodyElement.scrollTop = scrollTop;\r\n this.bodyElement.scrollLeft = scrollLeft;\r\n }\r\n \r\n // Sync Fixed Right scroll if it exists\r\n if (this.fixedRightBody) {\r\n this.fixedRightBody.scrollTop = scrollTop;\r\n }\r\n }\r\n\r\n /**\r\n * Get current fixed columns options\r\n * @returns Fixed options\r\n */\r\n getFixedOptions(): import('../types').FixedOptions {\r\n return this.options.fixedOptions || { colCount: 0, rightCount: 0 };\r\n }\r\n\r\n // ============================================\r\n // Phase 15: Row State Management\r\n // ============================================\r\n\r\n /**\r\n * Get row state by display index\r\n * @param index - Display index (in displayData array)\r\n * @returns Row state type\r\n */\r\n getRowState(index: number): RowStateType {\r\n const row = this.state.displayData[index];\r\n if (!row) return 'none';\r\n return this.state.rowStates.get(row) || 'none';\r\n }\r\n\r\n /**\r\n * Get row state by row data object\r\n * @param row - Row data object\r\n * @returns Row state type\r\n */\r\n getRowStateByData(row: RowData): RowStateType {\r\n return this.state.rowStates.get(row) || 'none';\r\n }\r\n\r\n /**\r\n * Set row state manually\r\n * @param index - Display index\r\n * @param state - New state\r\n */\r\n setRowState(index: number, state: RowStateType): void {\r\n const row = this.state.displayData[index];\r\n if (!row) return;\r\n \r\n this.state.rowStates.set(row, state);\r\n this.render();\r\n }\r\n\r\n /**\r\n * Get all changes (created, updated, deleted rows)\r\n * @returns Changes result with separated arrays\r\n */\r\n getChanges(): ChangesResult {\r\n const created: RowData[] = [];\r\n const updated: RowData[] = [];\r\n const deleted: RowData[] = [];\r\n \r\n this.state.rowStates.forEach((state, row) => {\r\n if (state === 'created') {\r\n created.push(row);\r\n } else if (state === 'updated') {\r\n updated.push(row);\r\n } else if (state === 'deleted') {\r\n deleted.push(row);\r\n }\r\n // 'createAndDeleted' and 'none' are intentionally excluded\r\n });\r\n \r\n return { created, updated, deleted };\r\n }\r\n\r\n /**\r\n * Get newly created rows\r\n * @returns Array of created rows\r\n */\r\n getCreatedRows(): RowData[] {\r\n const created: RowData[] = [];\r\n this.state.rowStates.forEach((state, row) => {\r\n if (state === 'created') {\r\n created.push(row);\r\n }\r\n });\r\n return created;\r\n }\r\n\r\n /**\r\n * Get updated rows\r\n * @returns Array of updated rows\r\n */\r\n getUpdatedRows(): RowData[] {\r\n const updated: RowData[] = [];\r\n this.state.rowStates.forEach((state, row) => {\r\n if (state === 'updated') {\r\n updated.push(row);\r\n }\r\n });\r\n return updated;\r\n }\r\n\r\n /**\r\n * Get deleted rows (marked for deletion)\r\n * @returns Array of deleted rows\r\n */\r\n getDeletedRows(): RowData[] {\r\n const deleted: RowData[] = [];\r\n this.state.rowStates.forEach((state, row) => {\r\n if (state === 'deleted') {\r\n deleted.push(row);\r\n }\r\n });\r\n return deleted;\r\n }\r\n\r\n /**\r\n * Clear all row states (reset to 'none')\r\n */\r\n clearRowStates(): void {\r\n this.state.rowStates.clear();\r\n // Re-initialize existing rows as 'none'\r\n this.state.data.forEach(row => {\r\n this.state.rowStates.set(row, 'none');\r\n });\r\n this.render();\r\n }\r\n\r\n /**\r\n * Commit changes (mark all rows as 'none')\r\n * This is typically called after successfully saving changes to server\r\n */\r\n commit(): void {\r\n // Remove 'createAndDeleted' rows completely\r\n const rowsToRemove: RowData[] = [];\r\n this.state.rowStates.forEach((state, row) => {\r\n if (state === 'createAndDeleted') {\r\n rowsToRemove.push(row);\r\n }\r\n });\r\n \r\n // Remove createAndDeleted rows from data\r\n rowsToRemove.forEach(row => {\r\n const index = this.state.data.indexOf(row);\r\n if (index >= 0) {\r\n this.state.data.splice(index, 1);\r\n }\r\n });\r\n \r\n // Set all remaining rows to 'none'\r\n this.state.rowStates.clear();\r\n this.state.data.forEach(row => {\r\n this.state.rowStates.set(row, 'none');\r\n });\r\n \r\n // Rebuild indexes and re-render\r\n this.rebuildDataIndexMap();\r\n this.applyDataTransformations();\r\n this.render();\r\n }\r\n\r\n // ============================================\r\n // Phase 18: Data Source & Pagination\r\n // ============================================\r\n\r\n /**\r\n * Remote 데이터 소스 여부 확인\r\n */\r\n isRemoteDataSource(): boolean {\r\n return this.options.dataSource?.type === 'remote';\r\n }\r\n\r\n /**\r\n * 페이지네이션 상태 조회\r\n */\r\n getPaginationState(): PaginationState {\r\n return { ...this.state.pagination };\r\n }\r\n\r\n /**\r\n * 특정 페이지로 이동\r\n * @param page - 이동할 페이지 번호 (1-based)\r\n */\r\n goToPage(page: number): void {\r\n const { totalPages } = this.state.pagination;\r\n const targetPage = Math.max(1, Math.min(page, totalPages || 1));\r\n \r\n if (targetPage === this.state.pagination.currentPage && this.state.displayData.length > 0) return;\r\n \r\n this.state.pagination.currentPage = targetPage;\r\n \r\n if (this.isRemoteDataSource()) {\r\n this.fetchData();\r\n } else {\r\n this.applyLocalPagination();\r\n this.render();\r\n }\r\n \r\n this.events.onPageChange?.(targetPage, this.state.pagination.pageSize);\r\n }\r\n\r\n /**\r\n * 페이지 크기 변경\r\n * @param pageSize - 새 페이지 크기\r\n */\r\n setPageSize(pageSize: number): void {\r\n if (pageSize < 1 || pageSize === this.state.pagination.pageSize) return;\r\n \r\n this.state.pagination.pageSize = pageSize;\r\n this.state.pagination.currentPage = 1;\r\n this.updateTotalPages();\r\n \r\n if (this.isRemoteDataSource()) {\r\n this.fetchData();\r\n } else {\r\n this.applyLocalPagination();\r\n this.render();\r\n }\r\n \r\n this.events.onPageSizeChange?.(pageSize);\r\n }\r\n\r\n /**\r\n * 서버에서 데이터 가져오기 (remote 모드)\r\n */\r\n async fetchData(): Promise<void> {\r\n const dataSource = this.options.dataSource;\r\n if (!dataSource?.fetch) return;\r\n \r\n const params: DataRequestParams = {\r\n page: this.state.pagination.currentPage,\r\n pageSize: this.state.pagination.pageSize,\r\n sort: this.state.sort.length > 0 ? this.state.sort : undefined,\r\n filter: this.state.filter,\r\n };\r\n \r\n this.state.pagination.loading = true;\r\n this.setLoading(true);\r\n \r\n try {\r\n const result = await dataSource.fetch(params);\r\n \r\n this.state.data = result.data.map(row => ({ ...row }));\r\n this.state.displayData = this.state.data;\r\n this.state.pagination.totalCount = result.totalCount;\r\n this.updateTotalPages();\r\n \r\n // Row state 초기화\r\n this.state.rowStates.clear();\r\n this.state.data.forEach(row => {\r\n this.state.rowStates.set(row, 'none');\r\n });\r\n \r\n this.rebuildDataIndexMap();\r\n this.summary.invalidateCache();\r\n this.clearSelectionState();\r\n } catch (error) {\r\n console.error('VeloxGrid: fetchData error', error);\r\n } finally {\r\n this.state.pagination.loading = false;\r\n this.setLoading(false);\r\n this.render();\r\n }\r\n }\r\n\r\n /**\r\n * 전체 페이지 수 재계산\r\n */\r\n private updateTotalPages(): void {\r\n const { pageSize, totalCount } = this.state.pagination;\r\n this.state.pagination.totalPages = Math.max(1, Math.ceil(totalCount / pageSize));\r\n }\r\n\r\n /**\r\n * 로컬 데이터에 페이지네이션 적용\r\n * sort/filter 적용 후 현재 페이지 데이터만 displayData에 설정\r\n */\r\n private applyLocalPagination(): void {\r\n // 먼저 sort/filter 적용\r\n let data = [...this.state.data];\r\n if (this.state.filter) data = filterData(data, this.state.filter);\r\n if (this.state.sort.length > 0) {\r\n const columnTypes: Record<string, ValueType> = {};\r\n this.state.columns.forEach(col => { columnTypes[col.field] = col.type || 'text'; });\r\n data = sortData(data, this.state.sort, columnTypes);\r\n }\r\n \r\n // totalCount 및 totalPages 업데이트\r\n this.state.pagination.totalCount = data.length;\r\n this.updateTotalPages();\r\n \r\n // 현재 페이지에 해당하는 데이터만 추출\r\n const { currentPage, pageSize } = this.state.pagination;\r\n const startIndex = (currentPage - 1) * pageSize;\r\n this.state.displayData = data.slice(startIndex, startIndex + pageSize);\r\n \r\n this.initCheckableRows();\r\n }\r\n\r\n /**\r\n * Infinite Scroll: 스크롤 바닥 감지 (Phase 18)\r\n */\r\n private checkInfiniteScroll(): void {\r\n const opts = this.options.pagination;\r\n if (!opts?.enabled || opts.mode !== 'infinite') return;\r\n if (this.infiniteScrollLoading || this.infiniteScrollAllLoaded) return;\r\n \r\n const threshold = opts.infiniteScrollThreshold || 100;\r\n const { scrollTop, scrollHeight, clientHeight } = this.bodyElement;\r\n \r\n if (scrollHeight - scrollTop - clientHeight <= threshold) {\r\n this.loadNextPage();\r\n }\r\n }\r\n\r\n /**\r\n * Infinite Scroll: 다음 페이지 로드 (Phase 18)\r\n */\r\n private async loadNextPage(): Promise<void> {\r\n const { currentPage, totalPages } = this.state.pagination;\r\n if (currentPage >= totalPages) {\r\n this.infiniteScrollAllLoaded = true;\r\n this.renderInfiniteScrollStatus();\r\n return;\r\n }\r\n \r\n this.infiniteScrollLoading = true;\r\n this.state.pagination.currentPage++;\r\n this.renderInfiniteScrollStatus();\r\n \r\n if (this.isRemoteDataSource()) {\r\n const dataSource = this.options.dataSource;\r\n if (!dataSource?.fetch) return;\r\n \r\n const params: DataRequestParams = {\r\n page: this.state.pagination.currentPage,\r\n pageSize: this.state.pagination.pageSize,\r\n sort: this.state.sort.length > 0 ? this.state.sort : undefined,\r\n filter: this.state.filter,\r\n };\r\n \r\n try {\r\n const result = await dataSource.fetch(params);\r\n \r\n // 기존 데이터에 추가 (append)\r\n const newRows = result.data.map(row => ({ ...row }));\r\n this.state.data.push(...newRows);\r\n this.state.displayData = [...this.state.data];\r\n this.state.pagination.totalCount = result.totalCount;\r\n this.updateTotalPages();\r\n \r\n newRows.forEach(row => this.state.rowStates.set(row, 'none'));\r\n this.rebuildDataIndexMap();\r\n this.summary.invalidateCache();\r\n \r\n if (this.state.pagination.currentPage >= this.state.pagination.totalPages) {\r\n this.infiniteScrollAllLoaded = true;\r\n }\r\n } catch (error) {\r\n console.error('VeloxGrid: infinite scroll fetch error', error);\r\n this.state.pagination.currentPage--;\r\n }\r\n } else {\r\n // Local infinite scroll\r\n this.applyLocalInfiniteScroll();\r\n }\r\n \r\n this.infiniteScrollLoading = false;\r\n this.render();\r\n }\r\n\r\n /**\r\n * Local Infinite Scroll: 다음 페이지 데이터 추가 (Phase 18)\r\n */\r\n private applyLocalInfiniteScroll(): void {\r\n let data = [...this.state.data];\r\n if (this.state.filter) data = filterData(data, this.state.filter);\r\n if (this.state.sort.length > 0) {\r\n const columnTypes: Record<string, ValueType> = {};\r\n this.state.columns.forEach(col => { columnTypes[col.field] = col.type || 'text'; });\r\n data = sortData(data, this.state.sort, columnTypes);\r\n }\r\n \r\n const { currentPage, pageSize } = this.state.pagination;\r\n const endIndex = currentPage * pageSize;\r\n this.state.displayData = data.slice(0, endIndex);\r\n \r\n if (endIndex >= data.length) {\r\n this.infiniteScrollAllLoaded = true;\r\n }\r\n \r\n this.initCheckableRows();\r\n }\r\n\r\n /**\r\n * Infinite Scroll 상태 표시 렌더링 (Phase 18)\r\n */\r\n private renderInfiniteScrollStatus(): void {\r\n if (!this.paginationContainer) return;\r\n \r\n this.paginationContainer.innerHTML = '';\r\n \r\n if (this.infiniteScrollLoading) {\r\n const loading = createElement('div', 'velox-infinite-status');\r\n loading.textContent = 'Loading...';\r\n this.paginationContainer.appendChild(loading);\r\n } else if (this.infiniteScrollAllLoaded) {\r\n const done = createElement('div', 'velox-infinite-status velox-infinite-status--done');\r\n const { totalCount } = this.state.pagination;\r\n done.textContent = `All ${totalCount.toLocaleString()} items loaded`;\r\n this.paginationContainer.appendChild(done);\r\n }\r\n }\r\n\r\n /**\r\n * Pagination UI 렌더링 (Phase 18)\r\n */\r\n private renderPagination(): void {\r\n if (!this.paginationContainer) return;\r\n \r\n // Infinite scroll 모드일 때는 상태 표시만\r\n if (this.options.pagination?.mode === 'infinite') {\r\n this.renderInfiniteScrollStatus();\r\n return;\r\n }\r\n \r\n const { currentPage, totalPages, totalCount, pageSize } = this.state.pagination;\r\n const opts = this.options.pagination;\r\n const maxButtons = opts?.maxPageButtons || 5;\r\n \r\n this.paginationContainer.innerHTML = '';\r\n \r\n // 좌측: 페이지 정보\r\n if (opts?.showInfo !== false) {\r\n const info = createElement('div', 'velox-pagination-info');\r\n const start = (currentPage - 1) * pageSize + 1;\r\n const end = Math.min(currentPage * pageSize, totalCount);\r\n info.textContent = totalCount > 0 \r\n ? `${start}-${end} / ${totalCount.toLocaleString()}`\r\n : '0 items';\r\n this.paginationContainer.appendChild(info);\r\n }\r\n \r\n // 중앙: 페이지 버튼\r\n const nav = createElement('div', 'velox-pagination-nav');\r\n \r\n // 처음 / 이전\r\n nav.appendChild(this.createPageButton('«', 1, currentPage === 1));\r\n nav.appendChild(this.createPageButton('‹', currentPage - 1, currentPage === 1));\r\n \r\n // 페이지 번호 버튼\r\n const half = Math.floor(maxButtons / 2);\r\n let startPage = Math.max(1, currentPage - half);\r\n const endPage = Math.min(totalPages, startPage + maxButtons - 1);\r\n if (endPage - startPage + 1 < maxButtons) {\r\n startPage = Math.max(1, endPage - maxButtons + 1);\r\n }\r\n \r\n if (startPage > 1) {\r\n nav.appendChild(this.createPageButton('1', 1, false));\r\n if (startPage > 2) {\r\n const ellipsis = createElement('span', 'velox-pagination-ellipsis');\r\n ellipsis.textContent = '…';\r\n nav.appendChild(ellipsis);\r\n }\r\n }\r\n \r\n for (let i = startPage; i <= endPage; i++) {\r\n const btn = this.createPageButton(String(i), i, false);\r\n if (i === currentPage) addClass(btn, 'velox-pagination-btn--active');\r\n nav.appendChild(btn);\r\n }\r\n \r\n if (endPage < totalPages) {\r\n if (endPage < totalPages - 1) {\r\n const ellipsis = createElement('span', 'velox-pagination-ellipsis');\r\n ellipsis.textContent = '…';\r\n nav.appendChild(ellipsis);\r\n }\r\n nav.appendChild(this.createPageButton(String(totalPages), totalPages, false));\r\n }\r\n \r\n // 다음 / 마지막\r\n nav.appendChild(this.createPageButton('›', currentPage + 1, currentPage === totalPages));\r\n nav.appendChild(this.createPageButton('»', totalPages, currentPage === totalPages));\r\n \r\n this.paginationContainer.appendChild(nav);\r\n \r\n // 우측: 페이지 크기 변경\r\n if (opts?.showSizeChanger) {\r\n const sizer = createElement('div', 'velox-pagination-sizer');\r\n const select = document.createElement('select');\r\n select.className = 'velox-pagination-select';\r\n const sizes = opts.pageSizeOptions || [10, 20, 50, 100];\r\n sizes.forEach(size => {\r\n const option = document.createElement('option');\r\n option.value = String(size);\r\n option.textContent = `${size} / page`;\r\n if (size === pageSize) option.selected = true;\r\n select.appendChild(option);\r\n });\r\n select.addEventListener('change', () => {\r\n this.setPageSize(Number(select.value));\r\n });\r\n sizer.appendChild(select);\r\n this.paginationContainer.appendChild(sizer);\r\n }\r\n }\r\n \r\n /**\r\n * 페이지 버튼 생성 헬퍼 (Phase 18)\r\n */\r\n private createPageButton(text: string, page: number, disabled: boolean): HTMLElement {\r\n const btn = createElement('button', 'velox-pagination-btn');\r\n btn.textContent = text;\r\n if (disabled) {\r\n btn.setAttribute('disabled', 'true');\r\n addClass(btn, 'velox-pagination-btn--disabled');\r\n } else {\r\n btn.addEventListener('click', () => this.goToPage(page));\r\n }\r\n return btn;\r\n }\r\n\r\n destroy(): void {\r\n // Clean up drag manager resources\r\n this.dragManager.destroy();\r\n // Detach all event handlers\r\n this.detachEvents();\r\n document.removeEventListener('mouseup', this.boundHandleBlockSelectionEnd);\r\n // Close any open popups\r\n this.closeFilterPopup();\r\n this.closeColumnMenu();\r\n this.rootElement.removeEventListener('keydown', this.boundHandleKeyDown);\r\n // Clean up cached canvas\r\n this.measureCanvas = null;\r\n this.measureContext = null;\r\n // Phase 12.3: Cleanup tooltip\r\n if (this.tooltip) {\r\n this.tooltip.destroy();\r\n this.tooltip = null;\r\n }\r\n this.container.innerHTML = '';\r\n this.events.onDestroy?.();\r\n }\r\n}","/**\r\n * VeloxGrid\r\n * A fast, lightweight, and framework-agnostic data grid library\r\n * \r\n * @author bumki\r\n * @license MIT\r\n * @version 0.9.1\r\n */\r\n\r\n// Core\r\nexport { VeloxGrid } from './core';\r\n\r\n// Types\r\nexport type {\r\n // Value types\r\n ValueType,\r\n CellValue,\r\n RowData,\r\n \r\n // Column\r\n ColumnDefinition,\r\n \r\n // Options\r\n GridOptions,\r\n \r\n // Sort & Filter\r\n SortDirection,\r\n SortState,\r\n FilterOperator,\r\n FilterCondition,\r\n FilterState,\r\n \r\n // Selection\r\n SelectionState,\r\n SelectionMode,\r\n SelectionStyle,\r\n CellIndex,\r\n Selection,\r\n CheckBarOptions,\r\n CheckBarState,\r\n RowNumbersOptions,\r\n RowDragOptions,\r\n \r\n // Row State (Phase 15)\r\n RowStateType,\r\n RowStateManager,\r\n ChangesResult,\r\n \r\n // Edit\r\n EditState,\r\n CellEditEvent,\r\n \r\n // Export/Import (Phase 8)\r\n ExportOptions,\r\n ImportResult,\r\n \r\n // Events\r\n GridEvents,\r\n \r\n // Instance\r\n VeloxGridInstance,\r\n \r\n // Internal (for extension)\r\n GridState,\r\n RenderContext,\r\n} from './types';\r\n\r\n// Utilities (for extension)\r\nexport {\r\n createElement,\r\n addClass,\r\n removeClass,\r\n toggleClass,\r\n hasClass,\r\n setStyles,\r\n throttle,\r\n debounce,\r\n} from './utils/dom';\r\n\r\nexport {\r\n deepClone,\r\n generateId,\r\n formatValue,\r\n parseValue,\r\n compareValues,\r\n sortData,\r\n filterData,\r\n escapeHtml,\r\n} from './utils/data';\r\n\r\n// Export utilities (Phase 8)\r\nexport {\r\n exportToExcel,\r\n exportToCSV,\r\n exportToJSON,\r\n downloadFile,\r\n downloadCSV,\r\n downloadJSON,\r\n parseCSV,\r\n importFromExcel,\r\n importFromExcelBySheetName,\r\n isSheetJSAvailable,\r\n type ExportContext,\r\n} from './utils/export';\r\n\r\n// Styles\r\nimport './styles/velox-grid.css';\r\n\r\n// Version\r\nexport const VERSION = '0.11.0';\r\n"],"names":["createElement","tag","className","attributes","element","key","value","addClass","classNames","removeClass","toggleClass","force","hasClass","setStyles","styles","throttle","func","limit","inThrottle","args","debounce","wait","timeout","deepClone","obj","item","cloned","generateId","prefix","formatValue","type","parseValue","num","date","compareValues","a","b","dateA","dateB","sortData","data","sortStates","columnTypes","field","direction","comparison","matchesFilter","condition","operator","filterValue","value2","strValue","strFilterValue","numValue","filterData","filterState","conditions","logic","row","results","escapeHtml","text","div","exportToCSV","context","displayData","columns","selectedRows","options","exportColumns","c","rowsToExport","sourceData","i","lines","headerRow","escapeCSVValue","col","values","formatExportValue","stringValue","exportToJSON","result","isSheetJSAvailable","getXLSX","XLSX","exportToExcel","wsData","rowData","formatExcelValue","ws","colWidths","wb","sheetName","filename","parseCSV","csvString","hasHeader","_a","parseCSVLines","dataStartIndex","columnCount","_","line","header","colIndex","error","currentLine","currentCell","inQuotes","char","nextChar","cell","importFromExcel","file","sheetIndex","resolve","reader","e","workbook","sheetNames","worksheet","jsonData","h","v","importFromExcelBySheetName","downloadFile","content","mimeType","blob","url","link","downloadCSV","csv","downloadJSON","json","DEFAULT_OPTIONS","GridHistory","enabled","size","action","rowIndex","oldValue","newValue","changes","index","GridValidator","rules","errors","rule","min","max","minLength","maxLength","pattern","column","GridEditorFactory","onSave","onCancel","onMove","input","select","option","optionElement","_options","container","checkbox","GridTooltip","cellRect","containerRect","tooltipRect","top","left","viewportWidth","viewportHeight","GridRenderer","ctx","state","dragPlaceholder","rowNumCell","fixedRightRow","checkBar","checkableCount","checkedCount","allChecked","someChecked","label","align","sortState","s","contentWrapper","dragHandle","sortBtn","filterBtn","menuBtn","handle","visibleRows","virtualState","rowHeight","emptyDiv","fixedRightColumns","totalWidth","scrollbarWidth","area","target","isCheckable","isChecked","editState","cellKey","focusedCell","_b","footerRow","checkboxCell","summaryConfig","summaryValue","valueSpan","cellEl","GridFilterPopup","anchor","popup","rect","gridRect","uniqueValues","currentFilter","operatorSelect","op","valueInput","listContainer","listLabel","btnContainer","applyBtn","clearBtn","newCondition","GridColumnMenu","menu","menuConfig","showDefault","customItems","defaultItems","items","sep","menuItem","isDisabled","html","GridDragManager","indicator","headerCell","el","sourceField","targetField","rowElement","targetIndex","sourceIndex","deltaX","newWidth","GridSummary","cacheKey","formattedValue","_groupValue","groupData","config","validValues","sum","val","count","numbers","n","cleaned","format","hasComma","decimalMatch","decimalPlaces","parts","DEFAULT_CHECKBAR","VeloxGrid","events","_c","_d","_e","specialColumnsWithOrder","order","colCount","specialColumns","fixedDataColumns","rightCount","dataColumns","totalCount","endIndex","scrollableDataColumns","startIndex","wrapper","mainSection","spinner","message","containerHeight","scrollTop","bufferSize","rows","handler","isSyncing","throttleTimer","handleScroll","source","scrollLeft","handleHeaderScroll","fixedRightScrollHandler","bodyScrollHandler","existingIndex","newDirection","current","selectionMode","isSelected","selectedArray","lastSelected","start","end","selectionStyle","startRow","startField","endRow","endField","startColIndex","endColIndex","minRow","maxRow","minCol","maxCol","r","currentColIndex","newRowIndex","newColIndex","handled","newField","newRow","insertIndex","displayRow","dataIndex","removed","newSelectedRows","newCheckedRows","selected","selection","selections","cells","rowIndices","fields","orderedFields","checked","indices","conditionArray","handleOutsideClick","editor","event","save","_f","originalValue","dateInput","numberInput","opt","parsedValue","validationResult","width","maxWidth","headerText","font","currentScrollTop","rowTop","rowBottom","cellLeft","cellRight","containerWidth","currentScrollLeft","rOffset","cOffset","change","exportToExcelUtil","exportToCSVUtil","exportToJSONUtil","loading","position","fromIndex","toIndex","targetDisplayRow","targetDataIndex","adjustedTargetIndex","oldOptions","newOptions","needsRebuild","created","updated","deleted","rowsToRemove","page","totalPages","targetPage","pageSize","dataSource","params","currentPage","opts","threshold","scrollHeight","clientHeight","newRows","done","maxButtons","info","nav","half","startPage","endPage","ellipsis","btn","sizer","disabled","VERSION"],"mappings":"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"}