open-grid 0.4.0 → 1.0.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 (48) hide show
  1. package/dist/OpenGrid-C6SK6VeK.cjs +90 -0
  2. package/dist/OpenGrid-C6SK6VeK.cjs.map +1 -0
  3. package/dist/OpenGrid-D7EJOVi1.js +4864 -0
  4. package/dist/OpenGrid-D7EJOVi1.js.map +1 -0
  5. package/dist/open-grid-react.cjs +1 -1
  6. package/dist/open-grid-react.js +1 -1
  7. package/dist/open-grid-vue.cjs +1 -1
  8. package/dist/open-grid-vue.js +1 -1
  9. package/dist/open-grid.cjs +1 -1
  10. package/dist/open-grid.js +2 -2
  11. package/dist/types/core/CellEditManager.d.ts +2 -3
  12. package/dist/types/core/CellEventHandler.d.ts +4 -5
  13. package/dist/types/core/CellTypeRegistry.d.ts +1 -2
  14. package/dist/types/core/ColumnLayout.d.ts +1 -2
  15. package/dist/types/core/ContextMenu.d.ts +1 -2
  16. package/dist/types/core/CrossGridRegistry.d.ts +1 -2
  17. package/dist/types/core/DataLayer.d.ts +4 -2
  18. package/dist/types/core/ExportManager.d.ts +4 -3
  19. package/dist/types/core/FilterPanel.d.ts +1 -2
  20. package/dist/types/core/FilterSelect.d.ts +1 -2
  21. package/dist/types/core/FindBarManager.d.ts +4 -5
  22. package/dist/types/core/FooterManager.d.ts +2 -1
  23. package/dist/types/core/FormulaEngine.d.ts +1 -2
  24. package/dist/types/core/GridRenderer.d.ts +3 -2
  25. package/dist/types/core/GridShuttle.d.ts +1 -2
  26. package/dist/types/core/GroupEngine.d.ts +7 -4
  27. package/dist/types/core/GroupTreeManager.d.ts +6 -3
  28. package/dist/types/core/KeyboardManager.d.ts +4 -5
  29. package/dist/types/core/OpenGrid.d.ts +27 -4
  30. package/dist/types/core/OverrideKernel.d.ts +70 -0
  31. package/dist/types/core/PivotEngine.d.ts +1 -2
  32. package/dist/types/core/RowManager.d.ts +0 -1
  33. package/dist/types/core/SortFilterManager.d.ts +5 -6
  34. package/dist/types/core/TriggerManager.d.ts +1 -2
  35. package/dist/types/core/WorksheetManager.d.ts +1 -2
  36. package/dist/types/core/editors/CellEditor.d.ts +2 -3
  37. package/dist/types/core/editors/DateEditor.d.ts +2 -3
  38. package/dist/types/core/editors/SelectEditor.d.ts +2 -3
  39. package/dist/types/core/renderers/CellRenderer.d.ts +4 -4
  40. package/dist/types/core/types.d.ts +58 -0
  41. package/dist/types/index.d.ts +1 -1
  42. package/dist/types/react/OpenGrid.d.ts +3 -3
  43. package/dist/types/vue/types.d.ts +1 -2
  44. package/package.json +99 -99
  45. package/dist/OpenGrid-ClmeIJYR.cjs +0 -88
  46. package/dist/OpenGrid-ClmeIJYR.cjs.map +0 -1
  47. package/dist/OpenGrid-doS5aFVl.js +0 -4669
  48. package/dist/OpenGrid-doS5aFVl.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenGrid-C6SK6VeK.cjs","sources":["../src/core/EventEmitter.ts","../src/core/DataLayer.ts","../src/core/VirtualScroll.ts","../src/core/ColumnLayout.ts","../src/core/FilterPanel.ts","../src/core/MathUtils.ts","../src/core/OGDecimal.ts","../src/core/FormulaEngine.ts","../src/core/MaskingEngine.ts","../src/core/renderers/CellRenderer.ts","../src/core/GridRenderer.ts","../src/core/RowManager.ts","../src/core/editors/DateEditor.ts","../src/core/editors/SelectEditor.ts","../src/core/editors/CellEditor.ts","../src/core/CellTypeRegistry.ts","../src/core/CellEditManager.ts","../src/core/FilterSelect.ts","../src/core/Pagination.ts","../src/core/DragVisuals.ts","../src/core/RowDragDrop.ts","../src/core/MergeEngine.ts","../src/core/ContextMenu.ts","../src/core/WorksheetManager.ts","../src/core/ExportManager.ts","../src/core/FooterManager.ts","../src/core/KeyboardManager.ts","../src/core/FindBarManager.ts","../src/core/GroupEngine.ts","../src/core/TreeEngine.ts","../src/core/GroupTreeManager.ts","../src/core/SortFilterManager.ts","../src/core/CellEventHandler.ts","../src/core/TriggerManager.ts","../src/core/CrossGridMapper.ts","../src/core/CrossGridRegistry.ts","../src/core/OverrideKernel.ts","../src/core/OpenGrid.ts"],"sourcesContent":["type Handler = (...args: any[]) => any;\n\ninterface ListenerEntry {\n handler: Handler;\n once: boolean;\n}\n\nexport class EventEmitter {\n private listeners: Map<string, ListenerEntry[]> = new Map();\n\n on(event: string, handler: Handler): this {\n const list = this.listeners.get(event) ?? [];\n list.push({ handler, once: false });\n this.listeners.set(event, list);\n return this;\n }\n\n once(event: string, handler: Handler): this {\n const list = this.listeners.get(event) ?? [];\n list.push({ handler, once: true });\n this.listeners.set(event, list);\n return this;\n }\n\n off(event: string, handler?: Handler): this {\n if (!handler) {\n this.listeners.delete(event);\n return this;\n }\n const list = this.listeners.get(event);\n if (list) {\n const filtered = list.filter(e => e.handler !== handler);\n if (filtered.length === 0) this.listeners.delete(event);\n else this.listeners.set(event, filtered);\n }\n return this;\n }\n\n emit(event: string, ...args: any[]): boolean {\n const list = this.listeners.get(event);\n if (!list || list.length === 0) return false;\n\n const remaining: ListenerEntry[] = [];\n for (const entry of list) {\n entry.handler(...args);\n if (!entry.once) remaining.push(entry);\n }\n\n if (remaining.length !== list.length) {\n if (remaining.length === 0) this.listeners.delete(event);\n else this.listeners.set(event, remaining);\n }\n return true;\n }\n\n removeAllListeners(event?: string): this {\n if (event) this.listeners.delete(event);\n else this.listeners.clear();\n return this;\n }\n\n listenerCount(event: string): number {\n return this.listeners.get(event)?.length ?? 0;\n }\n}\n","import type { SortItem, FilterItem } from './types.js';\n\ntype RowState = 'added' | 'edited' | 'removed' | 'none';\n\ninterface RowMeta {\n state: RowState;\n original?: any;\n rowId: string;\n}\n\nlet _rowIdSeq = 0;\nfunction nextRowId(): string {\n return `og-r-${++_rowIdSeq}`;\n}\n\nexport class DataLayer<T extends Record<string, any> = any> {\n private _data: T[] = [];\n private _original: T[] = [];\n private _meta: Map<string, RowMeta> = new Map();\n private _idField: string;\n\n // 정렬/필터 적용 후 표시되는 인덱스 목록\n private _displayIndexes: number[] = [];\n\n // rowId → _data 인덱스 역매핑\n private _idMap: Map<string, number> = new Map();\n\n // F3: 찾기 바 전용 크로스-필드 OR 필터\n private _findQuery: string = '';\n private _findFields: string[] = [];\n\n // Phase 2: strategy 슬롯 resolver(미설정 시 default 폴백 = 현행 로직).\n private _getStrategy: <F extends Function>(slot: string, fallback: F) => F =\n (_slot, fallback) => fallback;\n\n constructor(idField: string = '_ogRowId') {\n this._idField = idField;\n }\n\n /** Phase 2: OpenGrid 가 OverrideKernel.getStrategy 를 주입(슬롯 sortComparator/filterPredicate 도달용). */\n setStrategyResolver(resolver: <F extends Function>(slot: string, fallback: F) => F): void {\n this._getStrategy = resolver;\n }\n\n // ─── 데이터 설정 ──────────────────────────────────────\n setData(data: T[]): void {\n this._data = data.map(row => {\n const id = nextRowId();\n const item = { ...row, [this._idField]: id };\n this._meta.set(id, { state: 'none', rowId: id });\n return item as T;\n });\n this._original = this._data.map(r => ({ ...r }));\n this._rebuildIdMap();\n this._displayIndexes = this._data.map((_, i) => i);\n }\n\n getData(): T[] {\n return this._displayIndexes.map(i => this._data[i]!);\n }\n\n getOriginalData(): T[] {\n return [...this._original];\n }\n\n getAllData(): T[] {\n return [...this._data];\n }\n\n clearData(): void {\n this._data = [];\n this._original = [];\n this._meta.clear();\n this._idMap.clear();\n this._displayIndexes = [];\n }\n\n get rowCount(): number {\n return this._displayIndexes.length;\n }\n\n get totalRowCount(): number {\n return this._data.length;\n }\n\n // ─── 행 CRUD ──────────────────────────────────────────\n addRow(item: Partial<T>, position: 'first' | 'last' | number = 'last'): void {\n const id = nextRowId();\n const row = { ...item, [this._idField]: id } as T;\n this._meta.set(id, { state: 'added', rowId: id });\n\n if (position === 'last') {\n const idx = this._data.push(row) - 1;\n this._idMap.set(id, idx);\n this._displayIndexes.push(idx);\n } else if (position === 'first') {\n this._data.unshift(row);\n this._rebuildIdMap();\n this._displayIndexes.unshift(0);\n } else {\n const dispPos = Math.min(position, this._displayIndexes.length);\n const dataIdx = dispPos < this._displayIndexes.length\n ? this._displayIndexes[dispPos]!\n : this._data.length;\n this._data.splice(dataIdx, 0, row);\n this._rebuildIdMap();\n this._displayIndexes = this._data.map((_, i) => i);\n }\n }\n\n removeRow(rowIndex: number): T | undefined {\n const dataIdx = this._displayIndexes[rowIndex];\n if (dataIdx === undefined) return undefined;\n\n const row = this._data[dataIdx]!;\n const id = row[this._idField] as string;\n const meta = this._meta.get(id);\n\n if (meta?.state === 'added') {\n // 새로 추가된 행은 완전 삭제\n this._data.splice(dataIdx, 1);\n this._meta.delete(id);\n } else {\n // 기존 행은 soft delete\n this._meta.set(id, { ...meta!, state: 'removed' });\n }\n\n this._rebuildIdMap();\n this._displayIndexes = this._data\n .map((r, i) => ({ r, i }))\n .filter(({ r }) => this._meta.get(r[this._idField] as string)?.state !== 'removed')\n .map(({ i }) => i);\n\n return row;\n }\n\n moveRow(fromDisplayIdx: number, toDisplayIdx: number): void {\n const fromDataIdx = this._displayIndexes[fromDisplayIdx];\n const toDataIdx = this._displayIndexes[toDisplayIdx];\n if (fromDataIdx === undefined || toDataIdx === undefined) return;\n\n // _data 배열에서 실제 이동\n const [row] = this._data.splice(fromDataIdx, 1);\n const insertAt = fromDataIdx < toDataIdx ? toDataIdx - 1 : toDataIdx;\n this._data.splice(insertAt, 0, row!);\n\n this._rebuildIdMap();\n this._displayIndexes = this._data\n .map((r, i) => ({ r, i }))\n .filter(({ r }) => this._meta.get(r[this._idField] as string)?.state !== 'removed')\n .map(({ i }) => i);\n }\n\n updateCell(rowIndex: number, field: string, value: any): boolean {\n const dataIdx = this._displayIndexes[rowIndex];\n if (dataIdx === undefined) return false;\n\n const row = this._data[dataIdx]!;\n const id = row[this._idField] as string;\n const meta = this._meta.get(id);\n\n // original 백업\n if (meta?.state === 'none') {\n this._meta.set(id, {\n ...meta,\n state: 'edited',\n original: { ...this._original[dataIdx] }\n });\n }\n\n (this._data[dataIdx] as any)[field] = value;\n return true;\n }\n\n getRowByIndex(rowIndex: number): T | undefined {\n const dataIdx = this._displayIndexes[rowIndex];\n return dataIdx !== undefined ? this._data[dataIdx] : undefined;\n }\n\n getCellValue(rowIndex: number, field: string): any {\n return this.getRowByIndex(rowIndex)?.[field];\n }\n\n // ─── 변경 추적 ────────────────────────────────────────\n /** 수정된 행만 반환 (추가/삭제 제외) */\n getEditedRows(): T[] {\n return this._data.filter(r =>\n this._meta.get(r[this._idField] as string)?.state === 'edited'\n );\n }\n\n /** 수정된 행만 반환 (하위 호환용 — 신규 코드는 getEditedRows() 사용) */\n getChangedRows(): T[] { return this.getEditedRows(); }\n\n getAddedRows(): T[] {\n return this._data.filter(r =>\n this._meta.get(r[this._idField] as string)?.state === 'added'\n );\n }\n\n getRemovedRows(): T[] {\n return this._data.filter(r =>\n this._meta.get(r[this._idField] as string)?.state === 'removed'\n );\n }\n\n /**\n * 추가/수정/삭제 모든 변경사항을 한 번에 반환.\n * edited 행에는 _changedFields 배열도 포함.\n */\n getChanges(): { added: T[]; edited: T[]; removed: T[] } {\n const added: T[] = [];\n const edited: T[] = [];\n const removed: T[] = [];\n\n for (const row of this._data) {\n const id = row[this._idField] as string;\n const meta = this._meta.get(id);\n const state = meta?.state ?? 'none';\n if (state === 'added') { added.push({ ...row }); }\n else if (state === 'removed') { removed.push({ ...row }); }\n else if (state === 'edited') {\n const orig = meta!.original ?? {};\n const changedFields = Object.keys(row).filter(\n k => k !== this._idField && row[k] !== orig[k]\n );\n edited.push({ ...row, _changedFields: changedFields } as any);\n }\n }\n return { added, edited, removed };\n }\n\n /**\n * 수정된 컬럼 정보 반환 — 각 edited 행에 대해 { row, fields, diff } 반환.\n * diff: { field, oldValue, newValue }[]\n */\n getChangedColumns(): Array<{ row: T; fields: string[]; diff: Array<{ field: string; oldValue: any; newValue: any }> }> {\n return this._data\n .filter(r => this._meta.get(r[this._idField] as string)?.state === 'edited')\n .map(row => {\n const orig = this._meta.get(row[this._idField] as string)?.original ?? {};\n const diff: Array<{ field: string; oldValue: any; newValue: any }> = [];\n for (const key of Object.keys(row)) {\n if (key === this._idField) continue;\n if (row[key] !== orig[key]) {\n diff.push({ field: key, oldValue: orig[key], newValue: row[key] });\n }\n }\n return { row: { ...row }, fields: diff.map(d => d.field), diff };\n });\n }\n\n /** rowIndex 행의 원본(수정 전) 데이터 반환. 추가된 행은 undefined. */\n getOriginalRow(rowIndex: number): T | undefined {\n const dataIdx = this._displayIndexes[rowIndex];\n if (dataIdx === undefined) return undefined;\n const row = this._data[dataIdx]!;\n const meta = this._meta.get(row[this._idField] as string);\n if (!meta || meta.state === 'added') return undefined;\n if (meta.state === 'edited' && meta.original) return { ...meta.original } as T;\n return { ...this._original[dataIdx] } as T;\n }\n\n getRowsWithState(stateField: string): T[] {\n return this._data.map(r => {\n const state = this._meta.get(r[this._idField] as string)?.state ?? 'none';\n return { ...r, [stateField]: state };\n });\n }\n\n getRowState(rowIndex: number): RowState {\n const row = this.getRowByIndex(rowIndex);\n if (!row) return 'none';\n return this._meta.get(row[this._idField] as string)?.state ?? 'none';\n }\n\n // ─── 정렬 ─────────────────────────────────────────────\n applySort(sortList: SortItem[]): void {\n const notRemoved = (i: number) =>\n this._meta.get((this._data[i] as any)?.[this._idField])?.state !== 'removed';\n\n if (sortList.length === 0) {\n this._displayIndexes = this._data.map((_, i) => i).filter(notRemoved);\n return;\n }\n\n // Schwartzian transform: 키를 미리 추출하여 sort comparator 비용 절감\n const keyed = this._displayIndexes\n .filter(notRemoved)\n .map(idx => {\n const row = this._data[idx]!;\n return {\n idx,\n keys: sortList.map(s => row[s.field]),\n };\n });\n\n // Phase 2 슬롯 #1: 단일키 비교자. default = 현행 인라인(number는 av-bv, 그 외 String, null 우선).\n // 멀티키 루프가 단일키 비교를 래핑. dir 부호 적용은 호출자(루프) 책임이므로 슬롯은 비교만.\n // ⚠️ 핫패스(행쌍당) — 슬롯 fn 예외는 호출자 책임(try/catch 비감쌈).\n const cmpStrategy = this._getStrategy(\n 'sortComparator',\n (a: any, b: any, _field: string, _dir: 'asc' | 'desc'): number => {\n if (a == null && b == null) return 0;\n if (a == null) return -1;\n if (b == null) return 1;\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n const sa = String(a), sb = String(b);\n return sa < sb ? -1 : sa > sb ? 1 : 0;\n },\n );\n\n keyed.sort((a, b) => {\n for (let si = 0; si < sortList.length; si++) {\n const dir = sortList[si]!.dir;\n const field = sortList[si]!.field;\n const av = a.keys[si];\n const bv = b.keys[si];\n const cmp = cmpStrategy(av, bv, field, dir);\n if (cmp !== 0) return dir === 'asc' ? cmp : -cmp;\n }\n return 0;\n });\n\n this._displayIndexes = keyed.map(k => k.idx);\n }\n\n // ─── 필터 ─────────────────────────────────────────────\n applyFilter(filters: Record<string, FilterItem[]>): void {\n const fields = Object.keys(filters);\n\n // Phase 2 슬롯 #2: 필터 술어. default = 모듈 matchFilter(operator switch).\n // ⚠️ 핫패스(셀당) — 슬롯 fn 예외는 호출자 책임.\n const predicate = this._getStrategy(\n 'filterPredicate',\n (value: any, fi: FilterItem, _field: string): boolean => matchFilter(value, fi),\n );\n\n this._displayIndexes = this._data\n .map((r, i) => ({ r, i }))\n .filter(({ r }) => {\n if (this._meta.get(r[this._idField] as string)?.state === 'removed') return false;\n // 컬럼별 AND 필터\n if (fields.length > 0) {\n if (!fields.every(field => {\n const val = r[field];\n return filters[field]!.every(fi => predicate(val, fi, field));\n })) return false;\n }\n // F3 찾기 바: 전체 컬럼 OR 검색\n if (this._findQuery && this._findFields.length > 0) {\n const q = this._findQuery;\n const matched = this._findFields.some(f => {\n const v = r[f];\n return v != null && String(v).toLowerCase().includes(q);\n });\n if (!matched) return false;\n }\n return true;\n })\n .map(({ i }) => i);\n }\n\n /** F3: 찾기 바 전체 컬럼 OR 검색 설정 */\n setFindFilter(query: string, fields: string[]): void {\n this._findQuery = query.toLowerCase();\n this._findFields = fields;\n }\n\n // ─── 내부 유틸 ────────────────────────────────────────\n private _rebuildIdMap(): void {\n this._idMap.clear();\n this._data.forEach((r, i) => {\n this._idMap.set(r[this._idField] as string, i);\n });\n }\n}\n\nfunction matchFilter(value: any, fi: FilterItem): boolean {\n const v = value;\n const fv = fi.value;\n switch (fi.operator) {\n case '=': return v == fv;\n case '!=': return v != fv;\n case '>': return v > fv;\n case '>=': return v >= fv;\n case '<': return v < fv;\n case '<=': return v <= fv;\n case 'contains': return String(v).includes(String(fv));\n case 'startsWith': return String(v).startsWith(String(fv));\n case 'endsWith': return String(v).endsWith(String(fv));\n default: return true;\n }\n}\n","export interface VirtualScrollOptions {\n rowHeight: number;\n overscan?: number;\n onRender: (startIndex: number, endIndex: number) => void;\n}\n\nexport interface VirtualScrollRange {\n startIndex: number;\n endIndex: number;\n offsetY: number;\n}\n\nexport class VirtualScroll {\n private container: HTMLElement;\n private rowHeight: number;\n private overscan: number;\n private _totalRows: number = 0;\n private _scrollTop: number = 0;\n private _viewportHeight: number = 0;\n private _rafId: number | null = null;\n private onRender: (startIndex: number, endIndex: number) => void;\n\n constructor(container: HTMLElement, options: VirtualScrollOptions) {\n this.container = container;\n this.rowHeight = options.rowHeight;\n this.overscan = options.overscan ?? 5;\n this.onRender = options.onRender;\n\n this.container.addEventListener('scroll', this._onScroll, { passive: true });\n }\n\n private _onScroll = (): void => {\n this._scrollTop = this.container.scrollTop;\n this._scheduleRender();\n };\n\n private _scheduleRender(): void {\n if (this._rafId !== null) return;\n this._rafId = requestAnimationFrame(() => {\n this._rafId = null;\n const range = this.getVisibleRange();\n this.onRender(range.startIndex, range.endIndex);\n });\n }\n\n getVisibleRange(): VirtualScrollRange {\n const visibleCount = Math.ceil(this._viewportHeight / this.rowHeight);\n const startIndex = Math.max(0, Math.floor(this._scrollTop / this.rowHeight) - this.overscan);\n const endIndex = Math.min(\n this._totalRows - 1,\n startIndex + visibleCount + this.overscan * 2\n );\n const offsetY = startIndex * this.rowHeight;\n return { startIndex, endIndex, offsetY };\n }\n\n setTotalRows(count: number): void {\n this._totalRows = count;\n this._updateSpacerHeight();\n this._scheduleRender();\n }\n\n setViewportHeight(height: number): void {\n this._viewportHeight = height;\n this._scheduleRender();\n }\n\n setRowHeight(height: number): void {\n this.rowHeight = height;\n this._updateSpacerHeight();\n this._scheduleRender();\n }\n\n scrollToRow(rowIndex: number): void {\n const targetTop = rowIndex * this.rowHeight;\n const targetBottom = targetTop + this.rowHeight;\n const viewBottom = this._scrollTop + this._viewportHeight;\n\n if (targetTop < this._scrollTop) {\n this._scrollTop = targetTop;\n this.container.scrollTop = targetTop;\n } else if (targetBottom > viewBottom) {\n const newTop = targetBottom - this._viewportHeight;\n this._scrollTop = newTop;\n this.container.scrollTop = newTop;\n }\n }\n\n getTotalHeight(): number {\n return this._totalRows * this.rowHeight;\n }\n\n private _updateSpacerHeight(): void {\n // spacer 엘리먼트가 있다면 높이 업데이트\n const spacer = this.container.querySelector<HTMLElement>('.og-spacer');\n if (spacer) spacer.style.height = `${this.getTotalHeight()}px`;\n }\n\n destroy(): void {\n this.container.removeEventListener('scroll', this._onScroll);\n if (this._rafId !== null) cancelAnimationFrame(this._rafId);\n }\n}\n","import type { ColumnDef } from './types.js';\n\nexport interface FlatColumn<T = any> extends ColumnDef<T> {\n _colIndex: number;\n _depth: number;\n _leaf: boolean;\n _colSpanCount?: number;\n _rowSpanCount?: number;\n}\n\nexport interface HeaderCell {\n column: FlatColumn;\n colIndex: number;\n depth: number;\n colSpan: number;\n rowSpan: number;\n}\n\nexport class ColumnLayout<T = any> {\n private _columns: ColumnDef<T>[];\n private _flatLeaves: FlatColumn<T>[] = [];\n private _maxDepth: number = 1;\n private _frozenCount: number = 0;\n\n constructor(columns: ColumnDef<T>[], frozenCount: number = 0) {\n this._columns = columns;\n this._frozenCount = frozenCount;\n this._process();\n }\n\n private _process(): void {\n const leaves: FlatColumn<T>[] = [];\n let colIndex = 0;\n\n const walk = (cols: ColumnDef<T>[], depth: number): void => {\n for (const col of cols) {\n if (col.children && col.children.length > 0) {\n walk(col.children, depth + 1);\n this._maxDepth = Math.max(this._maxDepth, depth + 1);\n } else {\n leaves.push({ ...col, _colIndex: colIndex++, _depth: depth, _leaf: true });\n }\n }\n };\n\n this._maxDepth = 1;\n walk(this._columns, 1);\n this._flatLeaves = leaves;\n }\n\n get leaves(): FlatColumn<T>[] {\n return this._flatLeaves;\n }\n\n get visibleLeaves(): FlatColumn<T>[] {\n return this._flatLeaves.filter(c => !c.hidden);\n }\n\n get headerDepth(): number {\n return this._maxDepth;\n }\n\n get frozenCount(): number {\n return this._frozenCount;\n }\n\n setFrozen(count: number): void {\n this._frozenCount = count;\n }\n\n setColumns(columns: ColumnDef<T>[]): void {\n this._columns = columns;\n this._process();\n }\n\n hideColumn(field: string | string[]): void {\n const fields = Array.isArray(field) ? field : [field];\n this._flatLeaves.forEach(c => {\n if (fields.includes(c.field)) c.hidden = true;\n });\n }\n\n showColumn(field: string | string[]): void {\n const fields = Array.isArray(field) ? field : [field];\n this._flatLeaves.forEach(c => {\n if (fields.includes(c.field)) c.hidden = false;\n });\n }\n\n addColumn(colDef: ColumnDef<T>, position: 'first' | 'last' | number = 'last'): void {\n if (position === 'last') {\n this._columns.push(colDef);\n } else if (position === 'first') {\n this._columns.unshift(colDef);\n } else {\n this._columns.splice(position, 0, colDef);\n }\n this._process();\n }\n\n removeColumn(field: string): void {\n const removeFromList = (cols: ColumnDef<T>[]): ColumnDef<T>[] => {\n return cols.filter(c => {\n if (c.field === field) return false;\n if (c.children) c.children = removeFromList(c.children);\n return true;\n });\n };\n this._columns = removeFromList(this._columns);\n this._process();\n }\n\n getColumnByField(field: string): FlatColumn<T> | undefined {\n return this._flatLeaves.find(c => c.field === field);\n }\n\n getColumnByIndex(index: number): FlatColumn<T> | undefined {\n return this._flatLeaves[index];\n }\n\n getColumnIndex(field: string): number {\n return this._flatLeaves.findIndex(c => c.field === field);\n }\n\n /** 헤더 렌더링용 셀 계산 */\n buildHeaderCells(): HeaderCell[][] {\n const rows: HeaderCell[][] = Array.from({ length: this._maxDepth }, () => []);\n let colIndex = 0;\n\n const walk = (cols: ColumnDef<T>[], depth: number): number => {\n let span = 0;\n for (const col of cols) {\n if (col.hidden) continue;\n if (col.children && col.children.length > 0) {\n const childSpan = walk(col.children, depth + 1);\n if (childSpan > 0) {\n rows[depth - 1]!.push({\n column: col as FlatColumn<T>,\n colIndex: colIndex,\n depth,\n colSpan: childSpan,\n rowSpan: 1\n });\n span += childSpan;\n }\n } else {\n rows[depth - 1]!.push({\n column: col as FlatColumn<T>,\n colIndex: colIndex++,\n depth,\n colSpan: 1,\n rowSpan: this._maxDepth - depth + 1\n });\n span++;\n }\n }\n return span;\n };\n\n walk(this._columns, 1);\n return rows;\n }\n\n /** 각 리프 컬럼의 계산된 너비 배열 반환 */\n computeWidths(totalWidth: number, defaultWidth: number = 100): number[] {\n const visible = this.visibleLeaves;\n const flexCols = visible.filter(c => c.flex);\n const fixedTotal = visible\n .filter(c => !c.flex && c.width)\n .reduce((sum, c) => sum + c.width!, 0);\n\n const flexTotal = flexCols.reduce((sum, c) => sum + (c.flex ?? 1), 0);\n const remaining = Math.max(0, totalWidth - fixedTotal);\n\n return visible.map(c => {\n if (c.flex) return Math.round((c.flex / flexTotal) * remaining);\n return c.width ?? defaultWidth;\n });\n }\n}\n","import type { FilterItem } from './types.js';\n\nexport type FilterApplyFn = (field: string, items: FilterItem[]) => void;\nexport type FilterClearFn = (field: string) => void;\n\n/**\n * 컬럼 헤더 필터 드롭다운 패널.\n * 단일 인스턴스를 재사용(열릴 때 위치 재계산).\n */\nexport class FilterPanel {\n private _el: HTMLElement;\n private _field = '';\n private _onApply: FilterApplyFn;\n private _onClear: FilterClearFn;\n private _outsideHandler: ((e: MouseEvent) => void) | null = null;\n\n constructor(container: HTMLElement, onApply: FilterApplyFn, onClear: FilterClearFn) {\n this._onApply = onApply;\n this._onClear = onClear;\n\n this._el = document.createElement('div');\n this._el.className = 'og-filter-panel';\n this._el.style.cssText = `\n position:absolute;z-index:1000;min-width:200px;max-width:280px;\n background:var(--og-row-bg,#fff);border:1px solid var(--og-border-color,#e0e0e0);\n border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,0.15);\n padding:10px;box-sizing:border-box;display:none;font-size:13px;\n `;\n container.appendChild(this._el);\n }\n\n open(field: string, anchorEl: HTMLElement, currentFilters: FilterItem[]): void {\n this._field = field;\n this._el.innerHTML = '';\n\n // 제목\n const title = document.createElement('div');\n title.textContent = '필터';\n title.style.cssText = `font-weight:600;margin-bottom:8px;color:var(--og-text-color,#333);`;\n this._el.appendChild(title);\n\n // 조건 선택\n const condRow = document.createElement('div');\n condRow.style.cssText = 'display:flex;gap:4px;margin-bottom:6px;';\n\n const condSel = document.createElement('select');\n condSel.style.cssText = `flex:1;padding:3px 4px;border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;font-size:12px;`;\n const conditions: Array<{ label: string; value: FilterItem['operator'] }> = [\n { label: '포함', value: 'contains' },\n { label: '같음', value: '=' },\n { label: '같지 않음', value: '!=' },\n { label: '시작', value: 'startsWith' },\n { label: '끝남', value: 'endsWith' },\n { label: '보다 큼', value: '>' },\n { label: '보다 작음', value: '<' },\n { label: '이상', value: '>=' },\n { label: '이하', value: '<=' },\n ];\n for (const c of conditions) {\n const opt = document.createElement('option');\n opt.value = c.value;\n opt.textContent = c.label;\n condSel.appendChild(opt);\n }\n if (currentFilters[0]) condSel.value = currentFilters[0].operator;\n condRow.appendChild(condSel);\n this._el.appendChild(condRow);\n\n // 값 입력\n const valueInput = document.createElement('input');\n valueInput.type = 'text';\n valueInput.placeholder = '필터 값 입력...';\n valueInput.value = currentFilters[0]?.value ?? '';\n valueInput.style.cssText = `\n width:100%;padding:4px 6px;border:1px solid var(--og-border-color,#e0e0e0);\n border-radius:3px;font-size:12px;box-sizing:border-box;margin-bottom:8px;\n outline:none;\n `;\n valueInput.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') applyBtn.click();\n else if (e.key === 'Escape') this.close();\n });\n this._el.appendChild(valueInput);\n\n // 버튼 행\n const btnRow = document.createElement('div');\n btnRow.style.cssText = 'display:flex;gap:6px;justify-content:flex-end;';\n\n const clearBtn = document.createElement('button');\n clearBtn.textContent = '초기화';\n clearBtn.style.cssText = `\n padding:3px 10px;border:1px solid var(--og-border-color,#e0e0e0);\n border-radius:3px;background:#fff;cursor:pointer;font-size:12px;color:#666;\n `;\n clearBtn.addEventListener('click', () => {\n this._onClear(this._field);\n this.close();\n });\n\n const applyBtn = document.createElement('button');\n applyBtn.textContent = '적용';\n applyBtn.style.cssText = `\n padding:3px 10px;border:1px solid var(--og-primary,#1976d2);\n border-radius:3px;background:var(--og-primary,#1976d2);\n color:#fff;cursor:pointer;font-size:12px;\n `;\n applyBtn.addEventListener('click', () => {\n const val = valueInput.value.trim();\n if (!val) {\n this._onClear(this._field);\n } else {\n this._onApply(this._field, [{ operator: condSel.value as FilterItem['operator'], value: val }]);\n }\n this.close();\n });\n\n btnRow.appendChild(clearBtn);\n btnRow.appendChild(applyBtn);\n this._el.appendChild(btnRow);\n\n // 위치 계산 (앵커 기준)\n const rect = anchorEl.getBoundingClientRect();\n const containerRect = this._el.parentElement!.getBoundingClientRect();\n this._el.style.top = `${rect.bottom - containerRect.top + 2}px`;\n this._el.style.left = `${Math.min(rect.left - containerRect.left, containerRect.width - 220)}px`;\n this._el.style.display = 'block';\n\n requestAnimationFrame(() => valueInput.focus());\n\n // 외부 클릭 시 닫기\n if (this._outsideHandler) document.removeEventListener('mousedown', this._outsideHandler);\n this._outsideHandler = (e: MouseEvent) => {\n if (!this._el.contains(e.target as Node) && e.target !== anchorEl) {\n this.close();\n }\n };\n setTimeout(() => document.addEventListener('mousedown', this._outsideHandler!), 0);\n }\n\n close(): void {\n this._el.style.display = 'none';\n if (this._outsideHandler) {\n document.removeEventListener('mousedown', this._outsideHandler);\n this._outsideHandler = null;\n }\n }\n\n get isOpen(): boolean {\n return this._el.style.display !== 'none';\n }\n\n destroy(): void {\n this.close();\n this._el.remove();\n }\n}\n","// ============================================================\n// MathUtils — 부동소수점 안전 연산 유틸리티\n// 레이어: Algorithm\n// 설계 근거(Why): JS IEEE 754 오차(0.1+0.2=0.30000000000000004) 방지.\n// epsilon_round(곱셈 스케일링)와 Kahan compensated summation 두 전략을 조합.\n// ============================================================\n\nconst DEFAULT_PREC = 10;\n\n/**\n * 소수점 precision 자리로 반올림 (epsilon round).\n * 0.1+0.2+... 누적 오차를 최종 표시 단계에서 제거한다.\n */\nexport function round(val: number, precision: number = DEFAULT_PREC): number {\n const factor = Math.pow(10, precision);\n return Math.round(val * factor) / factor;\n}\n\n/**\n * Kahan compensated summation — 대량 합산 시 부동소수점 오차 최소화.\n * 시간복잡도 O(n), 공간 O(1). 빈 배열 → 0 반환.\n */\nexport function kahanSum(arr: number[]): number {\n let sum = 0, c = 0;\n for (const y of arr) {\n const corrected = y - c;\n const t = sum + corrected;\n c = (t - sum) - corrected;\n sum = t;\n }\n return sum;\n}\n\n/**\n * 안전 사칙연산 — 두 수의 곱셈 스케일링으로 소수점 오차 방지.\n */\nexport function safeAdd(a: number, b: number, precision: number = DEFAULT_PREC): number {\n return round(a + b, precision);\n}\n\nexport function safeSub(a: number, b: number, precision: number = DEFAULT_PREC): number {\n return round(a - b, precision);\n}\n\nexport function safeMul(a: number, b: number, precision: number = DEFAULT_PREC): number {\n return round(a * b, precision);\n}\n\nexport function safeDiv(a: number, b: number, precision: number = DEFAULT_PREC): number {\n if (b === 0) throw new Error('safeDiv: division by zero');\n return round(a / b, precision);\n}\n\n/**\n * Kahan 합산 후 precision 반올림.\n * SUM/AVG footer 계산에 사용.\n */\nexport function kahanSumRounded(arr: number[], precision: number = DEFAULT_PREC): number {\n return round(kahanSum(arr), precision);\n}\n\n/**\n * Kahan AVG — 합산 후 count로 나누기.\n */\nexport function kahanAvg(arr: number[], precision: number = DEFAULT_PREC): number {\n if (arr.length === 0) return 0;\n return round(kahanSum(arr) / arr.length, precision);\n}\n","// ============================================================\n// OGDecimal — BigInt 기반 임의정밀도 소수 클래스\n// 레이어: Algorithm\n// 설계 근거(Why): JS IEEE 754는 소수점 17자리가 한계.\n// 음원 수익 배분 등 수백 자리 정밀도가 필요한 경우 BigInt를\n// coefficient + scale 구조로 표현해 오차 없는 연산을 보장한다.\n// 외부 라이브러리 없음 (ES2020+ BigInt 내장 사용).\n// 표현: value = coefficient / 10^scale\n// 예) 3.14 → {c: 314n, s: 2} / 0.001 → {c: 1n, s: 3}\n// ============================================================\n\nexport type OGDecimalLike = string | number | bigint | OGDecimal;\n\nexport class OGDecimal {\n private readonly _c: bigint; // coefficient (부호 포함 정수)\n private readonly _s: number; // scale = 소수점 아래 자릿수\n\n constructor(coefficient: bigint, scale: number) {\n this._c = coefficient;\n this._s = scale < 0 ? 0 : scale;\n }\n\n // ── 생성 ─────────────────────────────────────────────────\n\n static from(value: OGDecimalLike): OGDecimal {\n if (value instanceof OGDecimal) return value;\n if (typeof value === 'bigint') return new OGDecimal(value, 0);\n\n const str = String(value).trim();\n if (!str || str === 'null' || str === 'undefined' || str === 'NaN') {\n return new OGDecimal(0n, 0);\n }\n\n const isNeg = str.startsWith('-');\n const abs = isNeg ? str.slice(1) : str;\n const dot = abs.indexOf('.');\n\n let coeff: bigint;\n let scale: number;\n\n if (dot === -1) {\n coeff = BigInt(abs);\n scale = 0;\n } else {\n const frac = abs.slice(dot + 1);\n coeff = BigInt(abs.slice(0, dot) + frac);\n scale = frac.length;\n }\n\n return new OGDecimal(isNeg ? -coeff : coeff, scale);\n }\n\n static zero(): OGDecimal { return new OGDecimal(0n, 0); }\n static one(): OGDecimal { return new OGDecimal(1n, 0); }\n\n // ── 내부: 두 값의 스케일 정렬 ────────────────────────────\n\n private static _align(a: OGDecimal, b: OGDecimal): [bigint, bigint, number] {\n if (a._s === b._s) return [a._c, b._c, a._s];\n if (a._s > b._s) {\n return [a._c, b._c * (10n ** BigInt(a._s - b._s)), a._s];\n }\n return [a._c * (10n ** BigInt(b._s - a._s)), b._c, b._s];\n }\n\n // ── 사칙연산 ─────────────────────────────────────────────\n\n add(other: OGDecimalLike): OGDecimal {\n const [ac, bc, s] = OGDecimal._align(this, OGDecimal.from(other));\n return new OGDecimal(ac + bc, s);\n }\n\n sub(other: OGDecimalLike): OGDecimal {\n const [ac, bc, s] = OGDecimal._align(this, OGDecimal.from(other));\n return new OGDecimal(ac - bc, s);\n }\n\n mul(other: OGDecimalLike): OGDecimal {\n const o = OGDecimal.from(other);\n return new OGDecimal(this._c * o._c, this._s + o._s);\n }\n\n /**\n * 나눗셈. precision = 결과 소수점 자리수 (기본 20).\n * 수익 배분처럼 소수 수백 자리가 필요하면 precision을 높인다.\n */\n div(other: OGDecimalLike, precision = 20): OGDecimal {\n const o = OGDecimal.from(other);\n if (o._c === 0n) throw new Error('OGDecimal: division by zero');\n // 분자를 키워서 정수 나눗셈으로 정밀도 확보\n const scaledNumerator = this._c * (10n ** BigInt(precision + o._s));\n const result = scaledNumerator / o._c;\n return new OGDecimal(result, precision + this._s);\n }\n\n /** 나머지 (정수 나머지와 동일한 개념을 소수에 적용) */\n mod(other: OGDecimalLike): OGDecimal {\n const o = OGDecimal.from(other);\n const [ac, bc, s] = OGDecimal._align(this, o);\n return new OGDecimal(ac % bc, s);\n }\n\n /** 부호 반전 */\n neg(): OGDecimal { return new OGDecimal(-this._c, this._s); }\n\n /** 절댓값 */\n abs(): OGDecimal {\n return new OGDecimal(this._c < 0n ? -this._c : this._c, this._s);\n }\n\n // ── 비교 ─────────────────────────────────────────────────\n\n eq(other: OGDecimalLike): boolean {\n const [ac, bc] = OGDecimal._align(this, OGDecimal.from(other));\n return ac === bc;\n }\n gt(other: OGDecimalLike): boolean {\n const [ac, bc] = OGDecimal._align(this, OGDecimal.from(other));\n return ac > bc;\n }\n lt(other: OGDecimalLike): boolean {\n const [ac, bc] = OGDecimal._align(this, OGDecimal.from(other));\n return ac < bc;\n }\n gte(other: OGDecimalLike): boolean { return !this.lt(other); }\n lte(other: OGDecimalLike): boolean { return !this.gt(other); }\n isZero(): boolean { return this._c === 0n; }\n isNeg(): boolean { return this._c < 0n; }\n isPos(): boolean { return this._c > 0n; }\n\n // ── 출력 ─────────────────────────────────────────────────\n\n /**\n * 지정 소수점 자리수로 반올림(Half-up) 후 문자열 반환.\n * 음원 배분 등 정확한 자리수 표시에 사용.\n */\n toFixed(dp: number): string {\n let c = this._c;\n let s = this._s;\n\n if (s < dp) {\n c = c * (10n ** BigInt(dp - s));\n } else if (s > dp) {\n const diff = BigInt(s - dp);\n const divisor = 10n ** diff;\n const half = divisor / 2n;\n const isNeg = c < 0n;\n const abs_c = isNeg ? -c : c;\n const rem = abs_c % divisor;\n let rounded = abs_c / divisor;\n if (rem >= half) rounded += 1n;\n c = isNeg ? -rounded : rounded;\n }\n s = dp;\n\n const isNeg = c < 0n;\n const abs_c = isNeg ? -c : c;\n const digits = abs_c.toString().padStart(dp + 1, '0');\n const intPart = digits.slice(0, digits.length - dp) || '0';\n const fracPart = dp > 0 ? '.' + digits.slice(digits.length - dp) : '';\n return (isNeg ? '-' : '') + intPart + fracPart;\n }\n\n /** 정규화(후행 0 제거) 후 최소 표현 문자열 반환 */\n toString(): string {\n if (this._s === 0) return this._c.toString();\n // 후행 0 제거\n let c = this._c, s = this._s;\n while (s > 0 && c !== 0n && c % 10n === 0n) { c /= 10n; s--; }\n return new OGDecimal(c, s).toFixed(s);\n }\n\n /** number로 변환 (정밀도 손실 주의 — 표시 전용) */\n toNumber(): number { return parseFloat(this.toFixed(20)); }\n\n // ── 집계 정적 메서드 ─────────────────────────────────────\n\n /** 정확한 합산 (내부적으로 BigInt 정수 연산) */\n static sum(arr: OGDecimalLike[]): OGDecimal {\n return arr.reduce<OGDecimal>((acc, v) => acc.add(v), OGDecimal.zero());\n }\n\n /** 정확한 평균. precision = 나눗셈 소수점 자리수 */\n static avg(arr: OGDecimalLike[], precision = 20): OGDecimal {\n if (!arr.length) return OGDecimal.zero();\n return OGDecimal.sum(arr).div(arr.length, precision);\n }\n\n /** 배열 최솟값 */\n static min(arr: OGDecimalLike[]): OGDecimal {\n if (!arr.length) throw new Error('OGDecimal.min: empty array');\n return arr.map(OGDecimal.from).reduce((a, b) => a.lt(b) ? a : b);\n }\n\n /** 배열 최댓값 */\n static max(arr: OGDecimalLike[]): OGDecimal {\n if (!arr.length) throw new Error('OGDecimal.max: empty array');\n return arr.map(OGDecimal.from).reduce((a, b) => a.gt(b) ? a : b);\n }\n}\n","// ============================================================\n// FormulaEngine — 그리드 컬럼 수식 파서/실행기\n// 레이어: Algorithm (순수 파싱·연산 로직)\n// 설계 근거(Why): Excel처럼 컬럼에 문자열 수식을 지정하면\n// 행 데이터를 컨텍스트로 OGDecimal 정밀 연산을 수행한다.\n// 재귀 하강 파서(Recursive Descent) 사용 — 연산자 우선순위 자동 처리.\n// 문법:\n// expression = additive\n// additive = multiplicative (('+' | '-') multiplicative)*\n// multiplicative = unary (('*' | '/' | '%') unary)*\n// unary = '-' unary | primary\n// primary = '(' expression ')' | '[' field ']' | number\n// 예시:\n// \"[revenue] * 0.035\"\n// \"([price] - [cost]) / [price] * 100\"\n// \"[qty] * [unit_price] * (1 - [discount_rate] / 100)\"\n// ============================================================\n\nimport { OGDecimal, type OGDecimalLike } from './OGDecimal.js';\n\nexport type FormulaContext = Record<string, OGDecimalLike>;\n\n/**\n * 문자열 수식을 평가해 OGDecimal 결과를 반환한다.\n * @param expr - 수식 문자열 (예: \"[price] * [qty] * 0.035\")\n * @param ctx - 필드값 컨텍스트 (행 데이터)\n * @param divisionPrecision - 나눗셈 소수점 자리수 (기본 30)\n */\nexport function evaluateFormula(\n expr: string,\n ctx: FormulaContext,\n divisionPrecision = 30,\n): OGDecimal {\n return new _FormulaParser(expr, ctx, divisionPrecision).parse();\n}\n\n// ─── 내부: 재귀 하강 파서 ────────────────────────────────\n\nclass _FormulaParser {\n private _pos = 0;\n private readonly _src: string;\n\n constructor(\n src: string,\n private readonly _ctx: FormulaContext,\n private readonly _prec: number,\n ) {\n this._src = src.trim();\n }\n\n parse(): OGDecimal {\n const result = this._additive();\n this._skip();\n if (this._pos < this._src.length) {\n throw new SyntaxError(\n `FormulaEngine: 예상치 못한 토큰 '${this._src[this._pos]}' (위치 ${this._pos})`\n );\n }\n return result;\n }\n\n // ── expression layers ──────────────────────────────────\n\n private _additive(): OGDecimal {\n let left = this._multiplicative();\n this._skip();\n while (this._pos < this._src.length) {\n const ch = this._src[this._pos];\n if (ch !== '+' && ch !== '-') break;\n this._pos++;\n this._skip();\n const right = this._multiplicative();\n left = ch === '+' ? left.add(right) : left.sub(right);\n this._skip();\n }\n return left;\n }\n\n private _multiplicative(): OGDecimal {\n let left = this._unary();\n this._skip();\n while (this._pos < this._src.length) {\n const ch = this._src[this._pos];\n if (ch !== '*' && ch !== '/' && ch !== '%') break;\n this._pos++;\n this._skip();\n const right = this._unary();\n if (ch === '*') left = left.mul(right);\n else if (ch === '/') left = left.div(right, this._prec);\n else left = left.mod(right);\n this._skip();\n }\n return left;\n }\n\n private _unary(): OGDecimal {\n this._skip();\n if (this._src[this._pos] === '-') {\n this._pos++;\n return this._unary().neg();\n }\n return this._primary();\n }\n\n private _primary(): OGDecimal {\n this._skip();\n const ch = this._src[this._pos];\n\n if (ch === '(') {\n this._pos++;\n const val = this._additive();\n this._skip();\n if (this._src[this._pos] !== ')') {\n throw new SyntaxError('FormulaEngine: 닫는 괄호 ) 누락');\n }\n this._pos++;\n return val;\n }\n\n if (ch === '[') return this._fieldRef();\n\n return this._literal();\n }\n\n // ── 토큰 파싱 ─────────────────────────────────────────\n\n /** [fieldName] → 행 데이터에서 값 추출 */\n private _fieldRef(): OGDecimal {\n this._pos++; // skip '['\n const start = this._pos;\n while (this._pos < this._src.length && this._src[this._pos] !== ']') {\n this._pos++;\n }\n if (this._pos >= this._src.length) {\n throw new SyntaxError('FormulaEngine: 닫는 ] 누락');\n }\n const field = this._src.slice(start, this._pos);\n this._pos++; // skip ']'\n\n const val = this._ctx[field];\n if (val == null) {\n throw new ReferenceError(`FormulaEngine: 필드 '[${field}]'가 행 데이터에 없습니다`);\n }\n return OGDecimal.from(val);\n }\n\n /** 숫자 리터럴 파싱 (정수 / 소수 모두) */\n private _literal(): OGDecimal {\n const start = this._pos;\n while (this._pos < this._src.length && /[0-9.]/.test(this._src[this._pos])) {\n this._pos++;\n }\n const numStr = this._src.slice(start, this._pos);\n if (!numStr) {\n throw new SyntaxError(\n `FormulaEngine: 숫자 또는 [필드]를 기대했지만 '${this._src[this._pos] ?? 'EOF'}' 발견 (위치 ${start})`\n );\n }\n return OGDecimal.from(numStr);\n }\n\n /** 공백 스킵 */\n private _skip(): void {\n while (this._pos < this._src.length && /\\s/.test(this._src[this._pos])) {\n this._pos++;\n }\n }\n}\n","// ============================================================\n// F5: MaskingEngine — 컬럼 데이터 마스킹 처리\n// ============================================================\n//\n// 지원 타입 (MaskType):\n// ssn — 주민등록번호 930101-1******\n// phone — 전화번호 010-****-5678 / 02-****-5678\n// mobile — 휴대폰 (phone과 동일)\n// email — 이메일 ho***@example.com\n// credit — 신용카드 1234-****-****-5678\n// account — 계좌번호 123-*****-1234 (앞3 뒤4 노출)\n// password — 비밀번호 ******* (전체 마스킹)\n// name — 이름 홍*동 / 홍**\n// ip — IP 주소 192.168.***.***\n// partial — 부분 마스킹 visiblePrefix/visibleSuffix 자유 지정\n//\n// 사용법:\n// applyMask('01012345678', 'phone')\n// → '010-****-5678'\n//\n// applyMask('hong@example.com', { type: 'email', char: '#' })\n// → 'ho###@example.com'\n//\n// applyMask('1234567890', { type: 'partial', visiblePrefix: 2, visibleSuffix: 2 })\n// → '12******90'\n// ============================================================\n\n/** 지원 마스킹 타입 */\nexport type MaskType =\n | 'ssn' // 주민등록번호: 930101-1******\n | 'phone' // 전화번호: 010-****-5678\n | 'mobile' // 휴대폰 (phone과 동일)\n | 'email' // 이메일: ho***@example.com\n | 'credit' // 신용카드: 1234-****-****-5678\n | 'account' // 계좌번호: 123-*****-1234\n | 'password' // 비밀번호: ******* (전체)\n | 'name' // 이름: 홍*동\n | 'ip' // IP 주소: 192.168.***.***\n | 'partial'; // 부분 마스킹 (visiblePrefix/visibleSuffix 지정)\n\n/** 마스킹 상세 옵션 */\nexport interface MaskDef {\n type: MaskType;\n /** 마스킹 치환 문자 (기본: '*') */\n char?: string;\n /** partial/account: 앞 N자리 표시 */\n visiblePrefix?: number;\n /** partial/account: 뒤 N자리 표시 */\n visibleSuffix?: number;\n}\n\n/**\n * 원본 값에 마스킹을 적용해 표시용 문자열을 반환.\n *\n * @param value 원본 값 (null/undefined → 빈 문자열 그대로 반환)\n * @param maskDef 마스킹 타입 또는 상세 옵션\n * @returns 마스킹된 문자열\n *\n * @example\n * applyMask('930101-1234567', 'ssn') // '930101-1******'\n * applyMask('01012345678', 'phone') // '010-****-5678'\n * applyMask('hong@test.com', 'email') // 'ho***@test.com'\n */\nexport function applyMask(value: string, maskDef: MaskType | MaskDef): string {\n if (value == null || value === '') return value ?? '';\n const def: MaskDef = typeof maskDef === 'string' ? { type: maskDef } : maskDef;\n const char = def.char ?? '*';\n\n switch (def.type) {\n case 'ssn': return _maskSSN(value, char);\n case 'phone':\n case 'mobile': return _maskPhone(value, char);\n case 'email': return _maskEmail(value, char);\n case 'credit': return _maskCredit(value, char);\n case 'account': return _maskAccount(value, char, def.visiblePrefix ?? 3, def.visibleSuffix ?? 4);\n case 'password': return char.repeat(Math.max(value.length, 6));\n case 'name': return _maskName(value, char);\n case 'ip': return _maskIP(value, char);\n case 'partial': return _maskPartial(value, char, def.visiblePrefix ?? 0, def.visibleSuffix ?? 4);\n default: return value;\n }\n}\n\n// ─────────────────────────────────────────────────────────────\n// 개별 마스킹 함수\n// ─────────────────────────────────────────────────────────────\n\n/**\n * 주민등록번호 마스킹\n * 입력: '9301011234567' 또는 '930101-1234567'\n * 출력: '930101-1******' (앞 6자리 + 뒷 1자리 노출, 나머지 마스킹)\n */\nfunction _maskSSN(v: string, c: string): string {\n const clean = v.replace(/[^0-9]/g, '');\n if (clean.length < 7) {\n // 7자리 미만이면 구분자 유지하며 뒷자리 마스킹\n const sep = v.includes('-') ? '-' : '';\n const frontEnd = v.indexOf('-') >= 0 ? v.indexOf('-') : 6;\n return v.slice(0, frontEnd) + sep + c.repeat(Math.max(1, v.length - frontEnd - sep.length));\n }\n const front = clean.slice(0, 6);\n const backFirst = clean[6]!;\n const maskLen = clean.length - 7;\n return `${front}-${backFirst}${c.repeat(maskLen)}`;\n}\n\n/**\n * 전화번호/휴대폰 마스킹\n * 입력: '01012345678' → '010-****-5678'\n * 입력: '0215551234' → '02-****-1234'\n * 입력: '0319991234' → '031-***-1234'\n */\nfunction _maskPhone(v: string, c: string): string {\n const clean = v.replace(/[^0-9]/g, '');\n if (clean.length === 11) {\n // 010-xxxx-xxxx (11자리 휴대폰)\n return `${clean.slice(0, 3)}-${c.repeat(4)}-${clean.slice(7)}`;\n } else if (clean.length === 10) {\n if (clean.startsWith('02')) {\n // 서울 02-xxxx-xxxx\n return `${clean.slice(0, 2)}-${c.repeat(4)}-${clean.slice(6)}`;\n }\n // 지역번호 3자리 031-xxx-xxxx\n return `${clean.slice(0, 3)}-${c.repeat(3)}-${clean.slice(6)}`;\n } else if (clean.length === 9) {\n // 02-xxx-xxxx (구형 서울)\n return `${clean.slice(0, 2)}-${c.repeat(3)}-${clean.slice(5)}`;\n }\n // fallback: 앞 3자리 + 뒤 4자리 노출\n return _maskPartial(v, c, 3, 4);\n}\n\n/**\n * 이메일 마스킹\n * 입력: 'hong@example.com' → 'ho***@example.com'\n * 입력: 'a@b.com' → 'a***@b.com' (1자리도 앞 1자리 노출)\n */\nfunction _maskEmail(v: string, c: string): string {\n const atIdx = v.indexOf('@');\n if (atIdx < 0) return _maskPartial(v, c, 2, 0);\n const local = v.slice(0, atIdx);\n const domain = v.slice(atIdx); // '@' 포함\n const visLen = Math.min(2, local.length);\n const visible = local.slice(0, visLen);\n // 마스킹 최소 3자리 이상으로 표시 (원본 길이 무관)\n const maskLen = Math.max(local.length - visLen, 3);\n return `${visible}${c.repeat(maskLen)}${domain}`;\n}\n\n/**\n * 신용카드 마스킹\n * 입력: '4123456789012345' → '4123-****-****-2345'\n * 앞 4자리 + 뒤 4자리 노출, 중간 마스킹 (4자리씩 구분)\n */\nfunction _maskCredit(v: string, c: string): string {\n const clean = v.replace(/[^0-9]/g, '');\n if (clean.length < 8) return v;\n const first4 = clean.slice(0, 4);\n const last4 = clean.slice(-4);\n const midLen = clean.length - 8;\n // 중간부가 없으면 8자리(****-****)로 패딩\n const mid = c.repeat(Math.max(midLen, 8));\n const parts: string[] = [first4];\n for (let i = 0; i < mid.length; i += 4) {\n const chunk = mid.slice(i, i + 4);\n if (chunk) parts.push(chunk);\n }\n parts.push(last4);\n return parts.join('-');\n}\n\n/**\n * 계좌번호 마스킹\n * 입력: '1234567890123' → '123-*******-0123' (기본 앞3 뒤4)\n * visiblePrefix/visibleSuffix로 조절 가능\n */\nfunction _maskAccount(v: string, c: string, prefixLen: number, suffixLen: number): string {\n const clean = v.replace(/[^0-9]/g, '');\n if (clean.length <= prefixLen + suffixLen) {\n return _maskPartial(clean, c, prefixLen, suffixLen);\n }\n const prefix = clean.slice(0, prefixLen);\n const suffix = clean.slice(-suffixLen);\n const midLen = clean.length - prefixLen - suffixLen;\n return `${prefix}-${c.repeat(midLen)}-${suffix}`;\n}\n\n/**\n * 이름 마스킹\n * 2자: 홍* (첫 글자만 노출)\n * 3자: 홍*동 (첫글자+끝글자, 중간 마스킹)\n * 4자+: 홍**동\n */\nfunction _maskName(v: string, c: string): string {\n const t = v.trim();\n if (t.length === 0) return v;\n if (t.length === 1) return c;\n if (t.length === 2) return `${t[0]}${c}`;\n // 3자 이상: 첫글자 + 중간 마스킹 + 끝글자\n return `${t[0]}${c.repeat(t.length - 2)}${t[t.length - 1]}`;\n}\n\n/**\n * IP 주소 마스킹\n * 입력: '192.168.1.100' → '192.168.***.***'\n * 앞 2옥텟 노출, 3·4 옥텟 마스킹\n */\nfunction _maskIP(v: string, c: string): string {\n const parts = v.split('.');\n if (parts.length !== 4) return _maskPartial(v, c, 3, 0);\n const maskOctet = (octet: string) => c.repeat(Math.max(octet.length, 3));\n return `${parts[0]}.${parts[1]}.${maskOctet(parts[2]!)}.${maskOctet(parts[3]!)}`;\n}\n\n/**\n * 부분 마스킹\n * 앞 visiblePrefix자리 + 중간 마스킹 + 뒤 visibleSuffix자리 노출\n * 예) applyMask('1234567890', { type:'partial', visiblePrefix:2, visibleSuffix:2 })\n * → '12******90'\n */\nfunction _maskPartial(v: string, c: string, prefixLen: number, suffixLen: number): string {\n if (v.length <= prefixLen + suffixLen) return v;\n const prefix = v.slice(0, prefixLen);\n const suffix = suffixLen > 0 ? v.slice(-suffixLen) : '';\n const midLen = v.length - prefixLen - suffixLen;\n return `${prefix}${c.repeat(midLen)}${suffix}`;\n}\n","import type { ColumnDef } from '../types.js';\nimport { round } from '../MathUtils.js';\nimport { OGDecimal } from '../OGDecimal.js';\nimport { evaluateFormula } from '../FormulaEngine.js';\nimport { applyMask } from '../MaskingEngine.js';\n\nexport interface RenderContext<T = any> {\n value: any;\n row: T;\n rowIndex: number;\n column: ColumnDef<T>;\n colIndex: number;\n isSelected: boolean;\n rowState: 'none' | 'added' | 'edited' | 'removed';\n}\n\nexport interface CellRenderer {\n render(ctx: RenderContext): HTMLElement;\n}\n\n// ─── Phase 2 슬롯 #3(렌더러측): displayFormatter ──────────\n/**\n * 모듈 함수 formatNumber/formatDate 는 host 참조가 없으므로(렌더러는 createRenderer 로\n * grid 컨텍스트 없이 생성됨) 모듈 레벨 resolver 로 displayFormatter 슬롯에 도달한다.\n * default = null → 기존 포맷 로직으로 폴백(출력 바이트 동일, 회귀 0).\n * OpenGrid 생성자에서 setDisplayFormatterResolver(_ovk.getStrategy) 주입.\n * 주의(멀티 인스턴스): 렌더러측 커스텀 displayFormatter 는 모듈 전역 — 동시 다중 그리드 시\n * 마지막 설치 그리드의 resolver 가 우선. 인스턴스 안전 경로는 OpenGrid.getDisplayValue 슬롯.\n */\nlet _displayFormatterResolver:\n | ((value: any, field: string, row: any) => string | null)\n | null = null;\n\nexport function setDisplayFormatterResolver(\n resolver: ((value: any, field: string, row: any) => string | null) | null,\n): void {\n _displayFormatterResolver = resolver;\n}\n\n// ─── 수식 평가 헬퍼 ───────────────────────────────────────\n/**\n * 컬럼에 formula가 있으면 OGDecimal로 평가해 표시값(string)을 반환.\n * formula가 없으면 null 반환 → 기존 ctx.value 사용.\n */\nexport function resolveFormula(ctx: RenderContext): string | null {\n const col = ctx.column;\n if (!col.formula) return null;\n const prec = col.formulaPrecision ?? 30;\n try {\n let result: any;\n if (typeof col.formula === 'function') {\n result = col.formula(ctx.row, OGDecimal);\n } else {\n result = evaluateFormula(col.formula, ctx.row as Record<string, any>, prec);\n }\n // OGDecimal → toFixed(precision) or toString\n if (result instanceof OGDecimal) {\n return col.precision != null ? result.toFixed(col.precision) : result.toString();\n }\n // string 반환된 경우 그대로 사용\n if (typeof result === 'string') return result;\n // number 등 → precision 적용\n return col.precision != null\n ? OGDecimal.from(result).toFixed(col.precision)\n : String(result);\n } catch (e) {\n console.warn('[OpenGrid] Formula error:', e);\n return '#ERR';\n }\n}\n\n// ─── 숫자 포맷 유틸 ───────────────────────────────────────\n/**\n * 숫자 포맷.\n * format 문자열:\n * '#,##0' 천단위 콤마, 정수\n * '#,##0.00' 천단위 콤마, 소수 2자리\n * '₩#,##0' 통화 접두 (₩1,234)\n * '$#,##0.00' 통화 접두 ($1,234.56)\n * '#,##0원' 통화 접미 (1,234원)\n * '$#,##0;($#,##0)' 양수;음수 패턴 — 음수를 괄호로 (회계식)\n * currency: ISO 통화코드('KRW'|'USD'|'EUR'…) 지정 시 Intl.NumberFormat 로케일 통화 포맷 우선.\n */\nexport function formatNumber(value: any, format?: string, precision?: number, currency?: string, field?: string, row?: any): string {\n // Phase 2 슬롯 #3(렌더러측): displayFormatter 가 등록되어 non-null 반환 시 그 값을 사용.\n // default(resolver null 또는 null 반환) → 아래 기존 로직(출력 동일). ⚠️ 핫패스 — 예외 비격리.\n if (_displayFormatterResolver) {\n const custom = _displayFormatterResolver(value, field ?? '', row);\n if (custom != null) return custom;\n }\n if (value == null || value === '') return '';\n let num = Number(value);\n if (isNaN(num)) return String(value);\n\n // F4: precision 지정 시 epsilon round 적용\n if (precision != null) num = round(num, precision);\n\n // ISO 통화코드 지정 시 → Intl 로케일 통화 포맷 (format 무시)\n if (currency) {\n try {\n return new Intl.NumberFormat(undefined, {\n style: 'currency', currency,\n ...(precision != null ? { minimumFractionDigits: precision, maximumFractionDigits: precision } : {}),\n }).format(num);\n } catch { /* 잘못된 코드 → 아래 format 폴백 */ }\n }\n\n if (!format) {\n // precision 지정 시 소수점 자리 고정 표시\n return precision != null ? num.toFixed(precision) : String(num);\n }\n\n // 음수 전용 패턴: \"양수포맷;음수포맷\" (음수면 부호는 포맷이 표현 → 절댓값 사용)\n const semi = format.indexOf(';');\n const negFmt = semi >= 0 ? format.slice(semi + 1) : null;\n const useFmt = (num < 0 && negFmt != null) ? negFmt : (semi >= 0 ? format.slice(0, semi) : format);\n const abs = (num < 0 && negFmt != null) ? Math.abs(num) : num;\n\n // 숫자 토큰(#,0,.)과 접두/접미(통화기호 등) 분리\n const m = useFmt.match(/[#0][#0,]*(?:\\.[#0]+)?/);\n if (!m) return String(num); // 숫자 토큰 없음 → 기존 동작 유지\n const token = m[0];\n const prefix = useFmt.slice(0, m.index);\n const suffix = useFmt.slice(m.index! + token.length);\n\n const useGrouping = token.includes(',');\n const decimals = token.includes('.') ? token.split('.')[1]!.length : (precision ?? 0);\n const body = abs.toLocaleString('ko-KR', {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n useGrouping,\n });\n\n return prefix + body + suffix;\n}\n\n// ─── 날짜 포맷 유틸 ───────────────────────────────────────\nexport function formatDate(value: any, format = 'yyyy-MM-dd', field?: string, row?: any): string {\n // Phase 2 슬롯 #3(렌더러측): displayFormatter 우선. default → 기존 로직(출력 동일).\n if (_displayFormatterResolver) {\n const custom = _displayFormatterResolver(value, field ?? '', row);\n if (custom != null) return custom;\n }\n if (!value) return '';\n const d = value instanceof Date ? value : new Date(value);\n if (isNaN(d.getTime())) return String(value);\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return format\n .replace('yyyy', String(y))\n .replace('MM', m)\n .replace('dd', day);\n}\n\n// ─── F5: 마스킹 셀 렌더링 헬퍼 ──────────────────────────\n/**\n * 마스킹된 셀을 렌더링한다.\n * - 좌측: 마스킹 문자열 (monospace)\n * - 우측: 눈 아이콘 버튼 — 클릭 시 해당 셀만 원문 표시 (DOM 직접 교체)\n *\n * 재렌더 시 col._maskRevealedRows에 rowIndex가 있으면 원문이 유지된다.\n */\nfunction _renderMasked(original: string, col: ColumnDef, rowIndex: number): HTMLElement {\n const masked = applyMask(original, col.mask!);\n\n const wrap = document.createElement('span');\n wrap.style.cssText =\n 'display:flex;align-items:center;gap:3px;overflow:hidden;width:100%;box-sizing:border-box;';\n\n const text = document.createElement('span');\n text.style.cssText =\n 'flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;' +\n 'font-family:monospace;letter-spacing:0.4px;color:var(--og-mask-text,#888);';\n text.textContent = masked;\n\n // 눈 아이콘 — SVG (Bootstrap Icons eye)\n const eye = document.createElement('button');\n eye.title = '클릭하면 원문 표시';\n eye.setAttribute('aria-label', '마스킹 해제');\n eye.innerHTML =\n '<svg width=\"13\" height=\"13\" viewBox=\"0 0 16 16\" fill=\"currentColor\">' +\n '<path d=\"M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8z\"/>' +\n '<path d=\"M8 5.5A2.5 2.5 0 1 0 8 10.5 2.5 2.5 0 0 0 8 5.5zm0 4A1.5 1.5 0 1 1 8 6.5a1.5 1.5 0 0 1 0 3z\" fill=\"#fff\"/>' +\n '</svg>';\n eye.style.cssText =\n 'flex-shrink:0;background:none;border:none;cursor:pointer;' +\n 'color:#c0c0c0;padding:1px 2px;line-height:0;border-radius:3px;' +\n 'display:flex;align-items:center;';\n\n eye.addEventListener('mouseover', () => {\n eye.style.color = 'var(--og-primary,#1976d2)';\n eye.style.background = 'rgba(25,118,210,0.08)';\n });\n eye.addEventListener('mouseout', () => {\n eye.style.color = '#c0c0c0';\n eye.style.background = 'none';\n });\n\n eye.addEventListener('click', (e: MouseEvent) => {\n e.stopPropagation();\n // DOM 즉시 교체 — 재렌더 없이 원문 표시\n text.textContent = original;\n text.style.fontFamily = '';\n text.style.letterSpacing = '';\n text.style.color = '';\n eye.remove();\n // 재렌더 시에도 해제 유지: 컬럼 내부 상태에 기록\n ((col as any)._maskRevealedRows as Set<number> | undefined ??\n (((col as any)._maskRevealedRows = new Set<number>()) as Set<number>)).add(rowIndex);\n });\n\n wrap.appendChild(text);\n wrap.appendChild(eye);\n return wrap;\n}\n\n// ─── TextRenderer ────────────────────────────────────────\nexport class TextRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const span = document.createElement('span');\n span.className = 'og-cell-text';\n // formula 우선 평가\n const formulaResult = resolveFormula(ctx);\n if (formulaResult !== null) {\n span.textContent = formulaResult;\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;';\n return span;\n }\n const { value, column, rowIndex } = ctx;\n\n let displayText: string;\n if (column.valueMap && value != null && column.valueMap[value]) {\n displayText = column.valueMap[value]!;\n } else {\n displayText = value == null ? '' : String(value);\n }\n\n // F5: 마스킹 처리\n // 컬럼 전체 해제(_maskRevealed) 또는 해당 행 해제(_maskRevealedRows) 시 원문 표시\n if (column.mask) {\n const colRevealed = (column as any)._maskRevealed === true;\n const rowRevealed = ((column as any)._maskRevealedRows as Set<number> | undefined)?.has(rowIndex) === true;\n if (!colRevealed && !rowRevealed) {\n return _renderMasked(displayText, column, rowIndex);\n }\n }\n\n span.textContent = displayText;\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;';\n return span;\n }\n}\n\n// ─── SelectRenderer ───────────────────────────────────────\nexport class SelectRenderer implements CellRenderer {\n private _opts: Array<{ label: string; value: any }>;\n private _fn: ((row: any, ri: number) => Array<{ label?: string; text?: string; value: any }>) | null;\n\n constructor(\n opts: Array<{ label?: string; text?: string; value: any }> = [],\n fn?: (row: any, ri: number) => Array<{ label?: string; text?: string; value: any }>\n ) {\n this._opts = opts.map(o =>\n typeof o === 'string' ? { label: o, value: o }\n : { label: (o as any).label ?? (o as any).text ?? String((o as any).value ?? ''), value: (o as any).value }\n );\n this._fn = fn ?? null;\n }\n\n render(ctx: RenderContext): HTMLElement {\n const span = document.createElement('span');\n span.className = 'og-cell-text';\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;';\n const rawVal = ctx.value;\n if (rawVal == null || rawVal === '') return span;\n const vs = String(rawVal);\n const list = this._fn\n ? this._fn(ctx.row, ctx.rowIndex).map((o: any) =>\n typeof o === 'string' ? { label: o, value: o }\n : { label: o.label ?? o.text ?? String(o.value ?? ''), value: o.value })\n : this._opts;\n const found = list.find(o => String(o.value) === vs);\n span.textContent = found ? found.label : vs;\n return span;\n }\n}\n\n// ─── NumberRenderer ───────────────────────────────────────\nexport class NumberRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const span = document.createElement('span');\n span.className = 'og-cell-number';\n // formula 우선 평가 (OGDecimal 고정밀도)\n const formulaResult = resolveFormula(ctx);\n if (formulaResult !== null) {\n span.textContent = formulaResult;\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;text-align:right;';\n return span;\n }\n // format 미지정 시 기본 천단위 콤마 (#,##0). precision 있으면 F4 epsilon round 적용.\n // currency(ISO 통화코드) 지정 시 Intl 로케일 통화 포맷 우선.\n span.textContent = formatNumber(ctx.value, ctx.column.format ?? '#,##0', ctx.column.precision, ctx.column.currency, ctx.column.field, ctx.row);\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;width:100%;text-align:right;';\n return span;\n }\n}\n\n// ─── DateRenderer ─────────────────────────────────────────\nexport class DateRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const span = document.createElement('span');\n span.className = 'og-cell-date';\n span.textContent = formatDate(ctx.value, ctx.column.format, ctx.column.field, ctx.row);\n span.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;';\n return span;\n }\n}\n\n// ─── CheckboxRenderer ─────────────────────────────────────\nexport class CheckboxRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.className = 'og-cell-checkbox';\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;';\n const chk = document.createElement('input');\n chk.type = 'checkbox';\n chk.checked = !!ctx.value;\n chk.disabled = true; // 클릭은 셀 이벤트로 처리 (_handleCellClick → writeCell)\n chk.style.cssText += 'cursor:pointer;pointer-events:none;';\n wrap.appendChild(chk);\n return wrap;\n }\n}\n\n// ─── ButtonRenderer ───────────────────────────────────────\nexport interface ButtonRendererDef {\n type: 'button';\n label?: string | ((value: any, row: any) => string);\n buttonClass?: string;\n style?: string;\n}\n\nexport class ButtonRenderer implements CellRenderer {\n constructor(private def?: ButtonRendererDef) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;';\n const btn = document.createElement('button');\n btn.className = `og-cell-btn${this.def?.buttonClass ? ' ' + this.def.buttonClass : ''}`;\n const label = this.def?.label;\n if (typeof label === 'function') btn.textContent = label(ctx.value, ctx.row);\n else btn.textContent = label ?? String(ctx.value ?? 'btn');\n btn.style.cssText = `\n padding:2px 10px;border:1px solid var(--og-primary,#1976d2);\n border-radius:4px;background:var(--og-row-bg,#fff);color:var(--og-primary,#1976d2);\n cursor:pointer;font-size:12px;white-space:nowrap;transition:background 0.12s;\n ${this.def?.style ?? ''}\n `;\n btn.addEventListener('mouseover', () => btn.style.background = 'var(--og-primary-light,#e3f2fd)');\n btn.addEventListener('mouseout', () => btn.style.background = 'var(--og-row-bg,#fff)');\n wrap.appendChild(btn);\n return wrap;\n }\n}\n\n// ─── BadgeRenderer (상태/태그 표시용) ─────────────────────\nexport class BadgeRenderer implements CellRenderer {\n constructor(\n private colorMap?: Record<string, string>,\n private labelMap?: Record<string, string>,\n ) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;height:100%;';\n const badge = document.createElement('span');\n const val = ctx.value == null ? '' : String(ctx.value);\n // labelMap이 있으면 표시 텍스트 변환, 없으면 column.valueMap → 원값 순으로 사용\n const label = this.labelMap?.[val] ?? ctx.column.valueMap?.[val] ?? val;\n badge.textContent = label;\n const color = this.colorMap?.[val] ?? '#666';\n badge.style.cssText = `\n display:inline-block;padding:2px 8px;border-radius:12px;font-size:11px;\n background:${color}22;color:${color};border:1px solid ${color}66;\n white-space:nowrap;\n `;\n wrap.appendChild(badge);\n return wrap;\n }\n}\n\n// ─── LinkRenderer ─────────────────────────────────────────\nexport class LinkRenderer implements CellRenderer {\n constructor(\n private hrefFn?: (value: any, row: any) => string,\n private target?: string,\n ) {}\n\n render(ctx: RenderContext): HTMLElement {\n const a = document.createElement('a');\n a.className = 'og-cell-link';\n a.textContent = ctx.value == null ? '' : String(ctx.value);\n a.href = this.hrefFn ? this.hrefFn(ctx.value, ctx.row) : '#';\n if (this.target) a.target = this.target;\n a.style.cssText = 'color:var(--og-primary,#1976d2);text-decoration:underline;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;';\n if (!this.hrefFn) a.addEventListener('click', e => e.preventDefault());\n return a;\n }\n}\n\n// ─── TemplateRenderer (사용자 정의 HTML) ──────────────────\nexport class TemplateRenderer implements CellRenderer {\n constructor(private templateFn: (value: any, row: any, rowIndex: number) => string) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('div');\n wrap.className = 'og-cell-template';\n wrap.style.cssText = 'display:flex;align-items:center;height:100%;overflow:hidden;';\n wrap.innerHTML = this.templateFn(ctx.value, ctx.row, ctx.rowIndex);\n return wrap;\n }\n}\n\n// ─── ImageRenderer ────────────────────────────────────────\nexport interface ImageRendererDef {\n type: 'image';\n width?: number;\n height?: number;\n radius?: number;\n srcFn?: (value: any, row: any) => string;\n alt?: string | ((value: any, row: any) => string);\n}\n\nexport class ImageRenderer implements CellRenderer {\n constructor(private def?: ImageRendererDef) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;';\n const img = document.createElement('img');\n const src = this.def?.srcFn ? this.def.srcFn(ctx.value, ctx.row) : String(ctx.value ?? '');\n img.src = src;\n const w = this.def?.width ?? 28;\n const h = this.def?.height ?? 28;\n const r = this.def?.radius ?? 4;\n img.style.cssText = `width:${w}px;height:${h}px;object-fit:cover;border-radius:${r}px;display:block;`;\n const alt = this.def?.alt;\n img.alt = typeof alt === 'function' ? alt(ctx.value, ctx.row) : (alt ?? '');\n img.onerror = () => { img.style.display = 'none'; };\n wrap.appendChild(img);\n return wrap;\n }\n}\n\n// ─── ProgressRenderer ─────────────────────────────────────\nexport interface ProgressRendererDef {\n type: 'progress';\n max?: number;\n color?: string;\n showLabel?: boolean;\n colorFn?: (value: number) => string;\n}\n\nexport class ProgressRenderer implements CellRenderer {\n constructor(private def?: ProgressRendererDef) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;gap:5px;width:100%;padding:0 4px;box-sizing:border-box;';\n const max = this.def?.max ?? 100;\n const raw = Number(ctx.value) || 0;\n const pct = Math.min(100, Math.max(0, (raw / max) * 100));\n const color = this.def?.colorFn\n ? this.def.colorFn(raw)\n : (this.def?.color ?? 'var(--og-primary,#1976d2)');\n\n const track = document.createElement('div');\n track.className = 'og-progress-track';\n track.style.cssText = 'flex:1;height:10px;background:#e0e0e0;border-radius:5px;overflow:hidden;';\n const fill = document.createElement('div');\n fill.className = 'og-progress-fill';\n fill.style.cssText = `width:${pct}%;height:100%;background:${color};border-radius:5px;`;\n track.appendChild(fill);\n wrap.appendChild(track);\n\n if (this.def?.showLabel !== false) {\n const lbl = document.createElement('span');\n lbl.style.cssText = 'font-size:11px;color:#666;white-space:nowrap;min-width:28px;text-align:right;';\n lbl.textContent = `${Math.round(pct)}%`;\n wrap.appendChild(lbl);\n }\n return wrap;\n }\n}\n\n// ─── SparklineRenderer (인라인 미니 차트) ─────────────────\nexport interface SparklineRendererDef {\n type: 'sparkline';\n width?: number;\n height?: number;\n color?: string;\n chartType?: 'bar' | 'line' | 'area';\n}\n\nexport class SparklineRenderer implements CellRenderer {\n constructor(private def?: SparklineRendererDef) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;';\n\n const values: number[] = Array.isArray(ctx.value) ? ctx.value.map(Number) : [];\n if (!values.length) {\n wrap.textContent = '-';\n return wrap;\n }\n\n const W = this.def?.width ?? 80;\n const H = this.def?.height ?? 22;\n const color = this.def?.color ?? '#1976d2';\n const chartType = this.def?.chartType ?? 'bar';\n\n const canvas = document.createElement('canvas');\n canvas.width = W;\n canvas.height = H;\n canvas.style.cssText = 'display:block;';\n\n const c = canvas.getContext('2d');\n if (c) {\n const max = Math.max(...values, 1);\n const min = Math.min(...values, 0);\n const range = max - min || 1;\n const n = values.length;\n\n if (chartType === 'bar') {\n const bw = W / n;\n values.forEach((v, i) => {\n const bh = ((v - min) / range) * (H - 2);\n c.fillStyle = color;\n c.fillRect(i * bw + 1, H - bh - 1, bw - 2, bh);\n });\n } else {\n const pts = values.map((v, i) => ({\n x: (i / (n - 1 || 1)) * W,\n y: H - ((v - min) / range) * (H - 4) - 2,\n }));\n if (chartType === 'area') {\n c.fillStyle = color + '33';\n c.beginPath();\n c.moveTo(pts[0]!.x, H);\n pts.forEach(p => c.lineTo(p.x, p.y));\n c.lineTo(pts[pts.length - 1]!.x, H);\n c.closePath();\n c.fill();\n }\n c.strokeStyle = color;\n c.lineWidth = 1.5;\n c.beginPath();\n pts.forEach((p, i) => (i === 0 ? c.moveTo(p.x, p.y) : c.lineTo(p.x, p.y)));\n c.stroke();\n }\n }\n\n wrap.appendChild(canvas);\n return wrap;\n }\n}\n\n// ─── SwitchRenderer (토글 스위치 표시) ───────────────────\nexport class SwitchRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;';\n const on = !!ctx.value;\n const sw = document.createElement('span');\n sw.className = 'og-switch' + (on ? ' og-switch--on' : '');\n sw.style.cssText = `display:inline-block;width:34px;height:18px;border-radius:9px;\n background:${on ? 'var(--og-primary,#1976d2)' : '#bdbdbd'};\n position:relative;transition:background 0.2s;cursor:pointer;flex-shrink:0;pointer-events:none;`;\n const knob = document.createElement('span');\n knob.style.cssText = `position:absolute;top:2px;left:${on ? '16px' : '2px'};\n width:14px;height:14px;border-radius:50%;background:#fff;\n transition:left 0.2s;box-shadow:0 1px 3px rgba(0,0,0,0.3);`;\n sw.appendChild(knob);\n wrap.appendChild(sw);\n return wrap;\n }\n}\n\n// ─── RatingRenderer (별점 표시) ───────────────────────────\nexport interface RatingRendererDef {\n type: 'rating';\n max?: number;\n color?: string;\n}\n\nexport class RatingRenderer implements CellRenderer {\n constructor(private def?: RatingRendererDef) {}\n\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;gap:1px;height:100%;';\n const max = this.def?.max ?? 5;\n const val = Math.round(Number(ctx.value) || 0);\n const color = this.def?.color ?? '#ffa000';\n for (let i = 1; i <= max; i++) {\n const star = document.createElement('span');\n star.textContent = '★';\n star.style.cssText = `font-size:14px;color:${i <= val ? color : '#e0e0e0'};line-height:1;`;\n wrap.appendChild(star);\n }\n return wrap;\n }\n}\n\n// ─── RadioRenderer ────────────────────────────────────────\nexport class RadioRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;pointer-events:none;';\n const radio = document.createElement('input');\n radio.type = 'radio';\n radio.checked = !!ctx.value;\n radio.setAttribute('aria-checked', ctx.value ? 'true' : 'false');\n radio.setAttribute('aria-label', ctx.column.header ?? '선택');\n if (ctx.column.group) radio.name = `og-radio-${ctx.rowIndex}-${ctx.column.group}`;\n radio.style.cssText = 'width:14px;height:14px;cursor:pointer;accent-color:var(--og-primary,#1976d2);';\n wrap.appendChild(radio);\n return wrap;\n }\n}\n\n// ─── ImgRenderer ──────────────────────────────────────────\nexport class ImgRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;overflow:hidden;';\n if (!ctx.value) return wrap;\n const img = document.createElement('img');\n img.src = String(ctx.value);\n img.alt = (ctx.column as any).alt ?? ctx.column.field;\n img.style.cssText = 'max-width:100%;max-height:100%;object-fit:contain;display:block;';\n img.setAttribute('role', 'img');\n wrap.appendChild(img);\n return wrap;\n }\n}\n\n// ─── HtmlRenderer ─────────────────────────────────────────\nfunction _sanitizeHtml(html: string): string {\n const div = document.createElement('div');\n div.innerHTML = html;\n div.querySelectorAll('script,iframe,object,embed').forEach(el => el.remove());\n div.querySelectorAll('*').forEach(el => {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith('on')) el.removeAttribute(attr.name);\n }\n if (el.tagName === 'A') {\n const href = el.getAttribute('href') ?? '';\n if (/^javascript:/i.test(href)) el.removeAttribute('href');\n }\n });\n return div.innerHTML;\n}\n\nexport class HtmlRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const wrap = document.createElement('span');\n wrap.style.cssText = 'display:block;overflow:hidden;width:100%;';\n const doSanitize = (ctx.column as any).sanitize !== false;\n const html = String(ctx.value ?? '');\n wrap.innerHTML = doSanitize ? _sanitizeHtml(html) : html;\n return wrap;\n }\n}\n\n// ─── BarcodeRenderer (Code128B) ───────────────────────────\nconst _C128W: string[] = [\n '212222','222122','222221','121223','121322','131222','122213','122312', // 0-7\n '132212','221213','221312','231212','112232','122132','122231','113222', // 8-15\n '123122','123221','223211','221132','221231','213212','223112','312131', // 16-23\n '311222','321122','321221','312212','322112','322211','212123','212321', // 24-31\n '232121','111323','131123','131321','112313','132113','132311','211313', // 32-39\n '231113','231311','112133','112331','132131','113123','113321','133121', // 40-47\n '313121','211331','231131','213113','213311','213131','311123','311321', // 48-55\n '331121','312113','312311','332111','314111','221411','431111','111224', // 56-63\n '111422','121124','121421','141122','141221','112214','112412','122114', // 64-71\n '122411','142112','142211','241211','221114','413111','241112','134111', // 72-79\n '111242','121142','121241','114212','124112','124211','411212','421112', // 80-87\n '421211','212141','214121','412121','111143','111341','131141','114113', // 88-95\n '114311','411113','411311','113141','114131','311141','411131','211412', // 96-103\n '211214','211232', // 104 (Start B), 105 (Start C)\n];\nconst _C128_STOP = '2331112';\n\nfunction _c128Bits(w: string): string {\n let out = '', bar = true;\n for (const ch of w) { out += (bar ? '1' : '0').repeat(+ch); bar = !bar; }\n return out;\n}\n\nfunction _encodeC128B(text: string): string {\n const codes: number[] = [104]; // Start B\n for (const ch of text) {\n const c = ch.charCodeAt(0) - 32;\n if (c >= 0 && c <= 94) codes.push(c);\n }\n let sum = 104;\n for (let i = 1; i < codes.length; i++) sum += codes[i]! * i;\n codes.push(sum % 103);\n return codes.map(c => _c128Bits(_C128W[c]!)).join('') + _c128Bits(_C128_STOP) + '11';\n}\n\nexport class BarcodeRenderer implements CellRenderer {\n render(ctx: RenderContext): HTMLElement {\n const val = String(ctx.value ?? '');\n const h = (ctx.column as any).barcodeHeight ?? 28;\n const wrap = document.createElement('div');\n wrap.style.cssText = 'display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;overflow:hidden;gap:1px;';\n wrap.setAttribute('role', 'img');\n wrap.setAttribute('aria-label', `바코드: ${val}`);\n wrap.innerHTML = _barcodeSvg(val, h);\n const label = document.createElement('span');\n label.textContent = val;\n label.style.cssText = 'font-size:9px;font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;';\n wrap.appendChild(label);\n return wrap;\n }\n}\n\nfunction _barcodeSvg(text: string, H: number): string {\n if (!text) return '';\n const bits = _encodeC128B(text);\n const MW = 1.4, QZ = 6;\n const TW = bits.length * MW + QZ * 2;\n const rects: string[] = [];\n let i = 0, x = QZ;\n while (i < bits.length) {\n if (bits[i] === '1') {\n let n = 0;\n while (i + n < bits.length && bits[i + n] === '1') n++;\n rects.push(`<rect x=\"${x.toFixed(2)}\" y=\"0\" width=\"${(n * MW).toFixed(2)}\" height=\"${H}\"/>`);\n x += n * MW; i += n;\n } else { x += MW; i++; }\n }\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${TW.toFixed(2)} ${H}\" width=\"${TW.toFixed(2)}\" height=\"${H}\" style=\"display:block\" aria-hidden=\"true\"><g fill=\"currentColor\">${rects.join('')}</g></svg>`;\n}\n\n// ─── Renderer 팩토리 ──────────────────────────────────────\nexport function createRenderer(col: ColumnDef): CellRenderer {\n const renderer = col.renderer;\n if (!renderer) {\n switch (col.type as string) {\n case 'number': return new NumberRenderer();\n case 'date': return new DateRenderer();\n case 'boolean': return new CheckboxRenderer();\n case 'radio': return new RadioRenderer();\n case 'img': return new ImgRenderer();\n case 'html': return new HtmlRenderer();\n case 'barcode': return new BarcodeRenderer();\n case 'select': return new SelectRenderer(col.options as any ?? [], col.optionsFn as any);\n default: return new TextRenderer();\n }\n }\n if (typeof renderer === 'string') {\n switch (renderer) {\n case 'number': return new NumberRenderer();\n case 'date': return new DateRenderer();\n case 'checkbox': return new CheckboxRenderer();\n case 'button': return new ButtonRenderer();\n case 'link': return new LinkRenderer();\n case 'badge': return new BadgeRenderer();\n case 'switch': return new SwitchRenderer();\n case 'radio': return new RadioRenderer();\n case 'img': return new ImgRenderer();\n case 'html': return new HtmlRenderer();\n case 'barcode': return new BarcodeRenderer();\n default: return new TextRenderer();\n }\n }\n // RendererDef 객체\n switch (renderer.type) {\n case 'button': return new ButtonRenderer(renderer as ButtonRendererDef);\n case 'checkbox': return new CheckboxRenderer();\n case 'link': return new LinkRenderer(renderer.hrefFn, renderer.target);\n case 'template': return new TemplateRenderer(renderer.templateFn);\n case 'badge': return new BadgeRenderer(renderer.colorMap, renderer.labelMap ?? renderer.valueMap);\n case 'image': return new ImageRenderer(renderer as ImageRendererDef);\n case 'progress': return new ProgressRenderer(renderer as ProgressRendererDef);\n case 'sparkline': return new SparklineRenderer(renderer as SparklineRendererDef);\n case 'switch': return new SwitchRenderer();\n case 'rating': return new RatingRenderer(renderer as RatingRendererDef);\n case 'number': return new NumberRenderer();\n case 'date': return new DateRenderer();\n case 'radio': return new RadioRenderer();\n case 'img': return new ImgRenderer();\n case 'html': return new HtmlRenderer();\n case 'barcode': return new BarcodeRenderer();\n default: return new TextRenderer();\n }\n}\n","import { DataLayer } from './DataLayer.js';\nimport { RowDragDrop } from './RowDragDrop.js';\nimport { MergeEngine } from './MergeEngine.js';\nimport { createRenderer } from './renderers/CellRenderer.js';\nimport type { ColumnDef, SortItem, TreeNodeIconDef } from './types.js';\n\n// ─── RendererCallbacks ────────────────────────────────────\nexport interface RendererCallbacks {\n onHeaderClick: (field: string, shiftKey: boolean) => void;\n onCellClick: (ri: number, ci: number, e: MouseEvent) => void;\n onCellDblClick: (ri: number, ci: number, e: MouseEvent) => void;\n onCellMouseOver: (ri: number, ci: number, e: MouseEvent) => void;\n onCellMouseOut: (ri: number, ci: number, e: MouseEvent) => void;\n onCellMouseDown: (ri: number, ci: number, e: MouseEvent) => void;\n onCellMouseUp: (ri: number, ci: number, e: MouseEvent) => void;\n onCellMouseMove: (ri: number, ci: number, e: MouseEvent) => void;\n onRowCheck: (ri: number, checked: boolean) => void;\n onAllCheck: (checked: boolean) => void;\n onColResize: (colIndex: number, newWidth: number) => void;\n onFilterIconClick: (field: string, anchorEl: HTMLElement) => void;\n getDndManager: () => RowDragDrop | null;\n onColDragStart: (colIndex: number) => void;\n onColDrop: (toIndex: number) => void;\n getColDragIdx: () => number | null;\n}\n\n// ─── GridRenderer ─────────────────────────────────────────\nexport class GridRenderer {\n private _root: HTMLElement;\n private _header: HTMLElement;\n private _bodyWrap: HTMLElement;\n private _body: HTMLElement;\n private _opts: any;\n private _cbs: RendererCallbacks;\n // rowIndex → {colIndex → cellEl} 맵\n private _cellMap: Map<number, Map<number, HTMLElement>> = new Map();\n\n get bodyWrapper() { return this._bodyWrap; }\n\n constructor(root: HTMLElement, opts: any, cbs: RendererCallbacks) {\n this._root = root;\n this._opts = opts;\n this._cbs = cbs;\n\n this._header = _el('div', 'og-header');\n // host isolation: border:0 로 4변 폭을 먼저 0 으로 못박는다. WordPress 전역 스타일\n // `:where([style*=\"border-color\"]){border-style:solid}` 이 인라인의 var(--og-border-color)\n // 문자열에 매칭되어, 폭 미지정 변에 medium(3px) 기본 보더를 강제하는 것을 차단(헤더 좌/우/상 굵은선 방지).\n this._header.style.cssText = `flex-shrink:0;overflow-x:auto;overflow-y:hidden;border:0;border-bottom:1px solid var(--og-border-color,#e0e0e0);scrollbar-width:none;`;\n\n this._bodyWrap = _el('div', 'og-body-wrapper');\n this._bodyWrap.style.cssText = `flex:1;overflow:auto;position:relative;`;\n this._bodyWrap.style.setProperty('--scrollbar-size', '8px');\n\n this._body = _el('div', 'og-body');\n this._body.style.cssText = `position:relative;`;\n this._bodyWrap.appendChild(this._body);\n\n root.appendChild(this._header);\n root.appendChild(this._bodyWrap);\n\n // 헤더 가로 스크롤 동기화\n this._bodyWrap.addEventListener('scroll', () => {\n this._header.scrollLeft = this._bodyWrap.scrollLeft;\n }, { passive: true });\n }\n\n updateSize(totalHeight: number, headerHeight: number): void {\n this._bodyWrap.style.height = `${totalHeight - headerHeight}px`;\n }\n\n /** 현재 렌더된 헤더 영역의 실제 높이(px). 헤더 줄바꿈으로 늘어난 높이를 레이아웃에 반영할 때 사용. */\n getHeaderHeight(): number {\n return this._header.offsetHeight;\n }\n\n renderHeader(\n headerRows: any[][],\n leaves: ColumnDef[],\n widths: number[],\n sortList: SortItem[],\n opts: any\n ): void {\n this._header.innerHTML = '';\n const frozenCount: number = opts._frozenCount ?? 0;\n\n // 헤더·바디 정렬을 위해 총 컬럼 너비를 계산 — 헤더 table은 이 너비로 고정\n let _extraW = 0;\n if (opts.stateColumn) _extraW += 24;\n if (opts.draggable) _extraW += 18;\n if (opts.rowNumber) _extraW += 44;\n if (opts.checkColumn) _extraW += 36;\n const totalColWidth = _extraW + leaves.reduce((s: number, _: any, i: number) => s + (widths[i] ?? opts.defaultColumnWidth), 0);\n\n // 헤더 div 배경 — 테이블이 totalColWidth보다 짧아도 헤더 영역 전체에 배경 유지\n this._header.style.background = 'var(--og-header-bg,#f5f5f5)';\n\n const table = _el('table', 'og-header-table') as HTMLTableElement;\n table.setAttribute('role', 'presentation');\n // host isolation: margin/border-spacing 을 인라인으로도 0 고정 → 호스트 table{} 차단.\n // (og-header-table 클래스로 base.css 규칙도 적용되나, 인라인으로 이중 방어)\n table.style.cssText = `table-layout:fixed;border-collapse:collapse;border-spacing:0;margin:0;width:${totalColWidth}px;background:var(--og-header-bg,#f5f5f5);`;\n\n // 엑스트라 컬럼 헤더\n const extraRows = headerRows.length;\n let extraHeaderLeft = 0;\n const addExtraCol = (tr: HTMLElement, w: number, label: string, extraClass = '') => {\n const th = _el('th', `og-header-cell og-extra-col ${extraClass}`);\n th.setAttribute('rowspan', String(extraRows));\n th.textContent = label;\n _style(th, {\n width: `${w}px`, minWidth: `${w}px`, textAlign: 'center',\n borderRight: '1px solid var(--og-border-color,#e0e0e0)',\n borderBottom: '1px solid var(--og-border-color,#e0e0e0)',\n // host isolation: extra 컬럼 th 도 호스트 th{} 침범 차단 (border/line-height)\n borderTop: '0', borderLeft: '0', lineHeight: 'normal', verticalAlign: 'middle',\n padding: '0', fontSize: '11px', color: '#999',\n userSelect: 'none', boxSizing: 'border-box',\n background: 'var(--og-header-bg,#f5f5f5)',\n });\n if (frozenCount > 0) {\n th.style.position = 'sticky';\n th.style.left = `${extraHeaderLeft}px`;\n th.style.zIndex = '4';\n }\n extraHeaderLeft += w;\n tr.appendChild(th);\n };\n\n for (let ri = 0; ri < headerRows.length; ri++) {\n const tr = _el('tr', 'og-header-row') as HTMLTableRowElement;\n // 테이블 행의 height 는 사실상 '최소 높이'로 동작한다(내용이 더 크면 행이 늘어남).\n // 따라서 줄바꿈 헤더는 height 를 넘어 자동 확장되고, 줄바꿈 없는 헤더는 기존과 동일하게 유지된다.\n tr.style.height = `${opts.headerHeight}px`;\n\n if (ri === 0) {\n // 컬럼 순서: stateColumn → draggable → rowNumber → checkColumn\n if (opts.stateColumn) addExtraCol(tr, 24, '');\n if (opts.draggable) addExtraCol(tr, 18, '');\n if (opts.rowNumber) addExtraCol(tr, 44, 'No');\n if (opts.checkColumn) {\n const th = _el('th', 'og-header-cell og-extra-col');\n th.setAttribute('rowspan', String(extraRows));\n th.style.cssText = `width:36px;min-width:36px;text-align:center;border-right:1px solid var(--og-border-color,#e0e0e0);border-bottom:1px solid var(--og-border-color,#e0e0e0);border-top:0;border-left:0;line-height:normal;vertical-align:middle;background:var(--og-header-bg,#f5f5f5);box-sizing:border-box;`;\n if (frozenCount > 0) {\n th.style.position = 'sticky';\n th.style.left = `${extraHeaderLeft}px`;\n th.style.zIndex = '4';\n }\n extraHeaderLeft += 36;\n const allChk = document.createElement('input');\n allChk.type = 'checkbox';\n allChk.setAttribute('aria-label', '전체 행 선택');\n allChk.style.cssText = 'width:16px;height:16px;';\n allChk.addEventListener('change', () => this._cbs.onAllCheck(allChk.checked));\n th.appendChild(allChk);\n tr.appendChild(th);\n }\n }\n\n for (const cell of (headerRows[ri] ?? [])) {\n const th = _el('th', 'og-header-cell') as HTMLTableHeaderCellElement;\n const col: ColumnDef = cell.column;\n if (cell.colSpan > 1) th.colSpan = cell.colSpan;\n if (cell.rowSpan > 1) th.rowSpan = cell.rowSpan;\n\n // 너비: leaf 컬럼만\n const leafIdx = cell.colSpan === 1 ? leaves.findIndex(l => l.field === col.field) : -1;\n if (cell.colSpan === 1) {\n const w = leafIdx >= 0 ? (widths[leafIdx] ?? opts.defaultColumnWidth) : (col.width ?? opts.defaultColumnWidth);\n th.style.width = `${w}px`;\n th.style.minWidth = `${w}px`;\n }\n\n const sortInfo = sortList.find(s => s.field === col.field);\n const sortable = col.sortable !== false && opts.sortable && cell.colSpan === 1;\n\n // ARIA + 키보드 접근성\n th.setAttribute('role', 'columnheader');\n th.setAttribute('scope', 'col');\n if (sortable) {\n th.setAttribute('aria-sort', sortInfo ? (sortInfo.dir === 'asc' ? 'ascending' : 'descending') : 'none');\n // 정렬 가능한 헤더는 키보드로 접근 가능 (roving tabindex: 첫 번째만 0)\n th.tabIndex = leafIdx === 0 ? 0 : -1;\n th.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._cbs.onHeaderClick(col.field, e.shiftKey);\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n const next = th.nextElementSibling as HTMLElement;\n if (next?.tagName === 'TH') next.focus();\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n const prev = th.previousElementSibling as HTMLElement;\n if (prev?.tagName === 'TH') prev.focus();\n }\n });\n }\n\n // 고정 컬럼 sticky\n if (leafIdx >= 0 && leafIdx < frozenCount) {\n let leftOff = 0;\n // extra 컬럼 순서와 동일하게: stateColumn → draggable → rowNumber → checkColumn\n if (opts.stateColumn) leftOff += 24;\n if (opts.draggable) leftOff += 18;\n if (opts.rowNumber) leftOff += 44;\n if (opts.checkColumn) leftOff += 36;\n for (let i = 0; i < leafIdx; i++) leftOff += widths[i] ?? opts.defaultColumnWidth;\n th.classList.add('og-frozen');\n if (leafIdx === frozenCount - 1) th.classList.add('og-frozen-last');\n th.style.left = `${leftOff}px`;\n }\n\n // 헤더 줄바꿈 여부: col.headerWrap 또는 header 문자열에 명시적 '\\n' 이 있으면 줄바꿈한다.\n const headerText = col.header ?? col.field;\n const hasExplicitBreak = typeof headerText === 'string' && headerText.indexOf('\\n') >= 0;\n const headerWrap = col.headerWrap === true || hasExplicitBreak;\n\n _style(th, {\n padding: '4px 8px', boxSizing: 'border-box',\n // host isolation: 헤더 <th> 의 모든 시각 속성을 인라인으로 고정한다.\n // 임베드 호스트(WordPress 등)가 `.entry-content th`/`.fn-post-content th`(특이도 0,2,1)로\n // 배경·글자·라인높이·보더·폰트크기를 덮어써도 인라인(최고 우선순위)이 이긴다.\n // (var 참조라 setTheme 시 자동 반영. text-align/padding 은 그리드 의도값 유지)\n background: 'var(--og-header-bg)', color: 'var(--og-header-color)',\n lineHeight: headerWrap ? '1.3' : 'normal', verticalAlign: 'middle',\n fontSize: 'var(--og-font-size)',\n textAlign: col.headerAlign ?? 'center',\n borderTop: '0', borderLeft: '0',\n borderRight: '1px solid var(--og-border-color,#e0e0e0)',\n borderBottom: '1px solid var(--og-border-color,#e0e0e0)',\n userSelect: 'none', cursor: sortable ? 'pointer' : 'default',\n // 줄바꿈 컬럼: nowrap+ellipsis 대신 여러 줄 허용(word-break). 미설정 컬럼은 기존 동작 유지.\n whiteSpace: headerWrap ? 'normal' : 'nowrap',\n overflow: headerWrap ? 'visible' : 'hidden',\n textOverflow: headerWrap ? 'clip' : 'ellipsis',\n wordBreak: headerWrap ? 'break-word' : 'normal',\n position: 'relative',\n });\n\n // 헤더 툴팁: col.tooltip(문자열) 우선, 없으면 헤더 텍스트 — 잘린 헤더 가독성 보조\n th.title = (typeof col.tooltip === 'string' ? col.tooltip : headerText) ?? '';\n\n const label = _el('span');\n if (headerWrap) {\n // 줄바꿈 허용: '\\n' 을 <br> 로 분할 렌더. label 도 nowrap/ellipsis 해제.\n label.style.cssText = 'overflow:visible;text-overflow:clip;white-space:normal;word-break:break-word;';\n const parts = String(headerText).split('\\n');\n parts.forEach((part, i) => {\n if (i > 0) label.appendChild(document.createElement('br'));\n label.appendChild(document.createTextNode(part));\n });\n } else {\n label.textContent = headerText;\n label.style.cssText = 'overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';\n }\n th.appendChild(label);\n\n // 정렬 아이콘\n if (sortInfo) {\n th.classList.add('og-sorted');\n const icon = _el('span', 'og-sort-icon');\n icon.textContent = sortInfo.dir === 'asc' ? ' ↑' : ' ↓';\n th.appendChild(icon);\n }\n\n // 필터 아이콘 (leaf 컬럼 + filterable)\n const filterable = col.filterable !== false && opts.filterable && cell.colSpan === 1;\n if (filterable) {\n const filterIcon = _el('span', 'og-filter-icon');\n const hasFilter = opts._activeFilters?.[col.field]?.length > 0;\n filterIcon.textContent = hasFilter ? '⊿' : '▿';\n filterIcon.title = '필터';\n filterIcon.style.cssText = 'margin-left:3px;cursor:pointer;font-size:10px;opacity:0.6;';\n if (hasFilter) filterIcon.classList.add('og-filter-icon--active');\n filterIcon.addEventListener('click', (e) => {\n e.stopPropagation();\n this._cbs.onFilterIconClick(col.field, filterIcon);\n });\n th.appendChild(filterIcon);\n }\n\n // 컬럼 리사이즈 핸들\n if (col.resizable !== false) {\n const resizer = _el('div', 'og-resize-handle');\n resizer.style.cssText = `position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;z-index:1;`;\n th.appendChild(resizer);\n const capturedLeafIdx = leafIdx;\n _addResizer(resizer, th, (w) => {\n if (capturedLeafIdx >= 0) this._cbs.onColResize(capturedLeafIdx, w);\n });\n }\n\n // 컬럼 드래그 리오더\n if (opts.columnReorder && leafIdx >= 0 && cell.colSpan === 1) {\n th.draggable = true;\n th.addEventListener('dragstart', (e) => {\n this._cbs.onColDragStart(leafIdx);\n th.classList.add('og-col-dragging');\n e.dataTransfer?.setData('text/plain', String(leafIdx));\n });\n th.addEventListener('dragend', () => {\n th.classList.remove('og-col-dragging');\n this._header.querySelectorAll('.og-col-drop-over').forEach(el => el.classList.remove('og-col-drop-over'));\n });\n th.addEventListener('dragover', (e) => {\n e.preventDefault();\n const fromIdx = this._cbs.getColDragIdx();\n if (fromIdx !== null && fromIdx !== leafIdx) {\n this._header.querySelectorAll('.og-col-drop-over').forEach(el => el.classList.remove('og-col-drop-over'));\n th.classList.add('og-col-drop-over');\n }\n });\n th.addEventListener('dragleave', () => {\n th.classList.remove('og-col-drop-over');\n });\n th.addEventListener('drop', (e) => {\n e.preventDefault();\n th.classList.remove('og-col-drop-over');\n this._cbs.onColDrop(leafIdx);\n });\n }\n\n if (sortable) {\n th.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).classList.contains('og-resize-handle')) return;\n this._cbs.onHeaderClick(col.field, e.shiftKey);\n });\n }\n\n tr.appendChild(th);\n }\n table.appendChild(tr);\n }\n this._header.appendChild(table);\n }\n\n renderBody(\n startIndex: number, endIndex: number,\n data: DataLayer<any>,\n leaves: ColumnDef[],\n widths: number[],\n opts: any,\n offsetY: number,\n totalHeight: number,\n selectedRows: Set<number>,\n checkedRows: Set<number>,\n groupFlatRows: Array<any> | null = null,\n onGroupToggle?: (key: string) => void,\n onTreeToggle?: (nodeId: any) => void,\n extraOpts: Record<string, any> = {},\n mergeEngine?: MergeEngine\n ): void {\n // opts에 extraOpts 병합 (DnD _totalRows 등)\n if (Object.keys(extraOpts).length) opts = { ...opts, ...extraOpts };\n this._body.innerHTML = '';\n this._cellMap.clear();\n // autoHeight(비가상): 행을 플로우로 쌓아 높이 자동. 그 외: 고정 rowHeight 절대배치.\n const auto: boolean = opts.autoHeight === true;\n this._body.classList.toggle('og-autoheight', auto);\n this._body.style.height = auto ? '' : `${totalHeight}px`;\n const frozenCount: number = opts._frozenCount ?? 0;\n\n // 바디 최소 너비를 totalColWidth로 설정 — 헤더 table과 너비 동기화 (수평 스크롤 영역 확보)\n {\n let _ew = 0;\n if (opts.stateColumn) _ew += 24;\n if (opts.draggable) _ew += 18;\n if (opts.rowNumber) _ew += 44;\n if (opts.checkColumn) _ew += 36;\n const _totalCW = _ew + leaves.reduce((s: number, _: any, i: number) => s + (widths[i] ?? opts.defaultColumnWidth), 0);\n this._body.style.minWidth = `${_totalCW}px`;\n }\n\n if (endIndex < startIndex) return;\n\n const frag = document.createDocumentFragment();\n for (let ri = startIndex; ri <= endIndex; ri++) {\n // 그룹/트리 모드: flatRow 배열 사용\n const flatItem = groupFlatRows ? groupFlatRows[ri] : null;\n const isGroupRow = flatItem && (flatItem as any)._isGroup === true;\n const isTreeRow = flatItem && (flatItem as any)._isTree === true;\n\n if (isGroupRow) {\n const g = flatItem as any;\n const groupKey = `__${g._groupField}:${g._groupValue}`;\n const rowEl = _el('div', 'og-group-row');\n const top = offsetY + (ri - startIndex) * opts.rowHeight;\n rowEl.style.cssText = [\n auto ? '' : `top:${top}px;height:${opts.rowHeight}px;`,\n 'display:flex;align-items:stretch;cursor:pointer;',\n `padding-left:${4 + g._depth * 12}px;`,\n 'background:var(--og-header-bg,#f5f5f5);',\n // host isolation: border:0 선행 (WP :where([style*=border-color]) 의 3px 강제 차단)\n 'border:0;border-bottom:1px solid var(--og-border-color,#e0e0e0);',\n ].join('');\n rowEl.setAttribute('role', 'row');\n rowEl.setAttribute('aria-expanded', g._expanded ? 'true' : 'false');\n rowEl.setAttribute('aria-rowindex', String(ri + 1));\n rowEl.setAttribute('aria-level', String(g._depth + 1));\n\n // ── extra 컬럼 영역 (stateColumn/draggable/rowNumber/checkColumn) ──────\n let extraW = 0;\n if (opts.stateColumn) extraW += 24;\n if (opts.draggable) extraW += 18;\n if (opts.rowNumber) extraW += 44;\n if (opts.checkColumn) extraW += 36;\n\n // stateColumn 자리: 편집 상태 배지 표시\n if (extraW > 0) {\n const stCell = _el('div', 'og-group-state-cell');\n stCell.style.cssText = [\n `width:${extraW}px;min-width:${extraW}px;flex-shrink:0;`,\n 'display:flex;align-items:center;justify-content:center;',\n 'font-size:10px;font-weight:700;gap:2px;',\n 'border-right:1px solid var(--og-border-color,#e0e0e0);',\n ].join('');\n const st = g._states ?? { added: 0, edited: 0, removed: 0 };\n if (st.added > 0) { const b = _el('span'); b.textContent=`+${st.added}`; b.style.cssText='color:var(--og-row-added-bg,#2e7d32);background:#e8f5e9;padding:1px 3px;border-radius:3px;'; stCell.appendChild(b); }\n if (st.edited > 0) { const b = _el('span'); b.textContent=`M${st.edited}`; b.style.cssText='color:#e65100;background:#fff8e1;padding:1px 3px;border-radius:3px;'; stCell.appendChild(b); }\n if (st.removed > 0) { const b = _el('span'); b.textContent=`D${st.removed}`; b.style.cssText='color:var(--og-row-removed-bg,#c62828);background:#ffebee;padding:1px 3px;border-radius:3px;'; stCell.appendChild(b); }\n rowEl.appendChild(stCell);\n }\n\n // ── 컬럼별 셀 ─────────────────────────────────────────────────────────\n let labelPlaced = false;\n for (let ci = 0; ci < leaves.length; ci++) {\n const col = leaves[ci]!;\n const w = widths[ci] ?? opts.defaultColumnWidth;\n const hasSummary = g._summaryFmt !== undefined && col.field in (g._summaryFmt ?? {});\n\n const cell = _el('div', 'og-group-cell');\n cell.style.cssText = [\n `width:${w}px;min-width:${w}px;flex-shrink:0;`,\n 'padding:2px 8px;box-sizing:border-box;overflow:hidden;',\n 'border-right:1px solid var(--og-border-color,#e0e0e0);',\n 'display:flex;align-items:center;',\n 'white-space:nowrap;text-overflow:ellipsis;',\n ].join('');\n\n if (hasSummary) {\n // 소계 값 — 숫자 컬럼은 우측 정렬\n const fmt = g._summaryFmt[col.field];\n cell.textContent = fmt !== '' ? fmt : '-';\n cell.style.justifyContent = 'flex-end';\n cell.style.color = 'var(--og-primary,#1976d2)';\n cell.style.fontWeight = '600';\n } else if (!labelPlaced) {\n // 맨 첫 번째 비-소계 컬럼에 그룹 레이블 배치\n labelPlaced = true;\n const arrow = _el('span', 'og-group-arrow');\n arrow.textContent = g._expanded ? '▾ ' : '▸ ';\n arrow.style.cssText = 'color:var(--og-primary,#1976d2);margin-right:4px;flex-shrink:0;';\n cell.appendChild(arrow);\n\n const lbl = _el('span', 'og-group-label');\n lbl.textContent = `${g._groupLabel} (${g._childCount}건)`;\n lbl.style.cssText = 'overflow:hidden;text-overflow:ellipsis;font-weight:600;';\n cell.appendChild(lbl);\n cell.style.gap = '0';\n }\n // 소계도 없고 첫 번째도 아닌 열: 빈 셀 (간격 유지)\n\n rowEl.appendChild(cell);\n }\n\n rowEl.addEventListener('click', () => onGroupToggle?.(groupKey));\n frag.appendChild(rowEl);\n continue;\n }\n\n // 일반 데이터 행 (트리 노드 포함)\n const treeNode: any | null = isTreeRow ? (flatItem as any) : null;\n const rowData = treeNode ? treeNode.data : (groupFlatRows ? flatItem : data.getRowByIndex(ri));\n if (!rowData) continue;\n const rowState = (isTreeRow || isGroupRow) ? 'none' : data.getRowState(ri);\n\n const rowEl = _el('div', 'og-row');\n rowEl.setAttribute('role', 'row');\n rowEl.setAttribute('aria-rowindex', String(ri + 1));\n if (!auto) {\n const top = offsetY + (ri - startIndex) * opts.rowHeight;\n rowEl.style.top = `${top}px`;\n rowEl.style.height = `${opts.rowHeight}px`;\n }\n\n // 교차 행 배경 — 가상스크롤에서 :nth-child는 DOM 위치 기반이라 ri 기준으로 인라인 설정\n let bg = ri % 2 === 0 ? 'var(--og-row-bg,#fff)' : 'var(--og-row-alt-bg,#fafafa)';\n rowEl.style.background = bg;\n\n // 상태/선택 CSS 클래스 부착 — !important 로 인라인 background 오버라이드\n if (rowState === 'added') rowEl.classList.add('og-state-added');\n if (rowState === 'edited') rowEl.classList.add('og-state-edited');\n if (rowState === 'removed') rowEl.classList.add('og-state-removed');\n if (selectedRows.has(ri)) rowEl.classList.add('og-selected');\n rowEl.setAttribute('aria-selected', selectedRows.has(ri) ? 'true' : 'false');\n\n // frozen 셀 배경용 bg — 상태행은 상태 색으로 덮어쓰기\n if (rowState === 'added') bg = 'var(--og-row-added-bg,#e8f5e9)';\n if (rowState === 'edited') bg = 'var(--og-row-edited-bg,#fff8e1)';\n if (rowState === 'removed') bg = 'var(--og-row-removed-bg,#ffebee)';\n if (selectedRows.has(ri)) bg = 'var(--og-row-selected-bg,#bbdefb)';\n\n // 행 레벨 클릭 (rowNumber·stateColumn 등 extra 컬럼 포함) → 선택 처리\n const localRowRi = ri;\n rowEl.addEventListener('click', (e) => { this._cbs.onCellClick(localRowRi, -1, e); });\n\n const colMap = new Map<number, HTMLElement>();\n\n // extra 컬럼 순서: stateColumn → draggable → rowNumber → checkColumn\n let extraBodyLeft = 0;\n\n // 상태 컬럼 (맨 앞)\n if (opts.stateColumn) {\n const stCell = _el('div', 'og-cell og-col-state');\n const icons: Record<string, string> = { added: '✚', edited: '✎', removed: '✖', none: '' };\n const colors: Record<string, string> = { added: '#2e7d32', edited: '#bf360c', removed: '#c62828', none: '' };\n stCell.textContent = icons[rowState] ?? '';\n stCell.style.color = colors[rowState] ?? '';\n stCell.title = rowState;\n if (frozenCount > 0) {\n stCell.style.position = 'sticky';\n stCell.style.left = `${extraBodyLeft}px`;\n stCell.style.zIndex = '2';\n stCell.style.background = bg;\n }\n extraBodyLeft += 24;\n rowEl.appendChild(stCell);\n }\n\n // 드래그 핸들\n const dnd = this._cbs.getDndManager();\n if (opts.draggable && dnd) {\n const handle = dnd.attachHandle(rowEl, ri, opts._totalRows ?? endIndex + 1);\n if (frozenCount > 0) {\n handle.style.position = 'sticky';\n handle.style.left = `${extraBodyLeft}px`;\n handle.style.zIndex = '2';\n handle.style.background = bg;\n }\n extraBodyLeft += 18;\n rowEl.appendChild(handle);\n }\n\n // 행 번호 컬럼\n if (opts.rowNumber) {\n const numCell = _el('div', 'og-cell og-col-rownum');\n numCell.textContent = String(ri + 1);\n if (frozenCount > 0) {\n numCell.style.position = 'sticky';\n numCell.style.left = `${extraBodyLeft}px`;\n numCell.style.zIndex = '2';\n numCell.style.background = bg;\n }\n extraBodyLeft += 44;\n rowEl.appendChild(numCell);\n }\n\n // 체크박스 컬럼\n if (opts.checkColumn) {\n const chkCell = _el('div', 'og-cell og-col-check');\n const chk = document.createElement('input');\n chk.type = 'checkbox';\n chk.checked = checkedRows.has(ri);\n chk.setAttribute('aria-label', `${ri + 1}행 선택`);\n chk.addEventListener('click', (e) => e.stopPropagation());\n chk.addEventListener('change', (e) => {\n e.stopPropagation();\n this._cbs.onRowCheck(ri, chk.checked);\n });\n chkCell.appendChild(chk);\n if (frozenCount > 0) {\n chkCell.style.position = 'sticky';\n chkCell.style.left = `${extraBodyLeft}px`;\n chkCell.style.zIndex = '2';\n chkCell.style.background = bg;\n }\n extraBodyLeft += 36;\n rowEl.appendChild(chkCell);\n }\n\n // 데이터 컬럼\n for (let ci = 0; ci < leaves.length; ci++) {\n const col = leaves[ci]!;\n const w = widths[ci] ?? opts.defaultColumnWidth;\n const isEditable = opts.editable && col.editable !== false;\n const isFirstCol = ci === 0;\n\n // 셀 병합 처리\n const mergeInfo = mergeEngine && !mergeEngine.isEmpty\n ? mergeEngine.getInfo(ri, ci)\n : null;\n if (mergeInfo?.hidden) {\n // 병합 하위 셀: flex 공간만 차지하는 투명 placeholder (컬럼 정렬 보존)\n const ph = _el('div', 'og-cell og-cell--merge-ph');\n ph.style.cssText = `width:${w}px;min-width:${w}px;flex-shrink:0;visibility:hidden;box-sizing:border-box;`;\n rowEl.appendChild(ph);\n continue;\n }\n\n const cellEl = _el('div', 'og-cell');\n cellEl.setAttribute('role', 'gridcell');\n cellEl.setAttribute('aria-colindex', String(ci + 1));\n\n // rowSpan 적용: 여러 행 높이만큼 절대 위치로 늘림\n const rs = mergeInfo?.rowSpan ?? 1;\n const cs = mergeInfo?.colSpan ?? 1;\n const mergedHeight = rs > 1 ? rs * opts.rowHeight : opts.rowHeight;\n // colSpan 시 width 합산\n let mergedWidth = w;\n if (cs > 1) {\n for (let dc = 1; dc < cs; dc++) {\n mergedWidth += widths[ci + dc] ?? opts.defaultColumnWidth;\n }\n }\n\n const hPad = treeNode && isFirstCol ? 0 : 8;\n\n // 고정 컬럼 sticky\n const isFrozenCell = ci < frozenCount;\n let frozenLeftOff = 0;\n if (isFrozenCell) {\n // extra 컬럼 순서: stateColumn → draggable → rowNumber → checkColumn\n if (opts.stateColumn) frozenLeftOff += 24;\n if (opts.draggable) frozenLeftOff += 18;\n if (opts.rowNumber) frozenLeftOff += 44;\n if (opts.checkColumn) frozenLeftOff += 36;\n for (let i = 0; i < ci; i++) frozenLeftOff += widths[i] ?? opts.defaultColumnWidth;\n cellEl.classList.add('og-frozen-cell');\n if (ci === frozenCount - 1) cellEl.classList.add('og-frozen-last');\n }\n\n // frozen 셀: sticky 특성상 배경 필요 → bg 적용. 일반 셀: 행에서 상속\n const cellBg = isFrozenCell ? bg : 'inherit';\n cellEl.style.width = `${mergedWidth}px`;\n cellEl.style.minWidth = `${mergedWidth}px`;\n cellEl.style.maxWidth = `${mergedWidth}px`;\n if (rs > 1) cellEl.style.height = `${mergedHeight}px`;\n if (isFrozenCell) cellEl.style.background = bg;\n if (treeNode && isFirstCol) cellEl.style.padding = '0';\n cellEl.style.overflow = 'hidden';\n if (rs > 1) {\n // rowSpan 마스터셀: body 기준 absolute 위치 (flex flow 밖)\n cellEl.style.height = `${mergedHeight}px`;\n cellEl.style.position = 'absolute';\n cellEl.style.zIndex = '3';\n // 마스터셀에 명시적 배경색 필요(하단 행 덮기)\n cellEl.style.background = (bg && bg !== 'inherit') ? bg : 'var(--og-row-bg, #fff)';\n // host isolation: 미지정 변 폭 0 명시 (WP :where([style*=border-color]) 의 3px 강제 차단)\n cellEl.style.borderTop = '0';\n cellEl.style.borderLeft = '0';\n cellEl.style.borderBottom = `1px solid var(--og-border-color, #e0e0e0)`;\n } else if (isFrozenCell) {\n cellEl.style.position = 'sticky';\n cellEl.style.left = `${frozenLeftOff}px`;\n cellEl.style.zIndex = '1';\n }\n if (col.type === 'number' || col.align === 'right') cellEl.classList.add('og-cell--right');\n else if (col.align === 'center') cellEl.classList.add('og-cell--center');\n if (isEditable) cellEl.classList.add('og-cell--editable');\n // 줄바꿈(wrap): nowrap+ellipsis 대신 여러 줄 표시 (rowHeight를 키워 함께 사용)\n if (col.wrap) cellEl.classList.add('og-cell--wrap');\n\n // ── ARIA + 포커스 셀 ───────────────────────\n if (!isEditable) cellEl.setAttribute('aria-readonly', 'true');\n if (cs > 1) cellEl.setAttribute('aria-colspan', String(cs));\n if (rs > 1) cellEl.setAttribute('aria-rowspan', String(rs));\n // 포커스 셀 표시 (og-cell-focused 클래스 + tabIndex for programmatic focus)\n const isFocused = opts._focusCell?.ri === ri && opts._focusCell?.ci === ci;\n if (isFocused) {\n cellEl.classList.add('og-cell-focused');\n cellEl.tabIndex = -1;\n }\n // 셀 접근성 레이블 (헤더명: 값)\n const _rawVal = rowData ? rowData[col.field] : null;\n cellEl.setAttribute('aria-label', `${col.header}: ${_rawVal == null ? '' : String(_rawVal)}`);\n\n // 툴팁(native title): col.tooltip(문자열|함수) 우선, 없고 opts.tooltips 면 셀 값 자동 노출\n if (col.tooltip != null) {\n cellEl.title = typeof col.tooltip === 'function'\n ? String(col.tooltip(_rawVal, rowData as any) ?? '')\n : String(col.tooltip);\n } else if (opts.tooltips && _rawVal != null && _rawVal !== '') {\n cellEl.title = String(_rawVal);\n }\n\n // ── 트리 첫 컬럼: 탐색기 스타일 렌더링 ──────────────\n let _treeRenderTarget: HTMLElement = cellEl;\n\n if (treeNode && isFirstCol) {\n const treeCell = _el('div', 'og-tree-cell');\n\n // ① 조상 가이드 라인 (│ or 空白) — 깊이만큼 반복\n const hasMoreChain: boolean[] = treeNode._ancestorHasMore ?? [];\n for (let d = 0; d < treeNode._depth; d++) {\n const guide = _el('span', 'og-tree-guide');\n if (hasMoreChain[d]) guide.classList.add('og-tree-guide--line');\n treeCell.appendChild(guide);\n }\n\n // ② 연결선 (depth > 0 만) : ├─ 또는 └─\n if (treeNode._depth > 0) {\n const conn = _el('span', 'og-tree-connector');\n conn.classList.add(\n treeNode._isLastChild ? 'og-tree-connector--last' : 'og-tree-connector--mid'\n );\n treeCell.appendChild(conn);\n }\n\n // ③ 토글 래퍼 — branch: 정렬 스페이서(빈 칸), leaf: 원형 점\n const toggleWrap = _el('span', 'og-tree-toggle-wrap');\n if (!treeNode._hasChildren) {\n const dot = _el('span', 'og-tree-leaf-dot');\n toggleWrap.appendChild(dot);\n }\n treeCell.appendChild(toggleWrap);\n\n // ④ 노드 아이콘 — branch: 폴더(클릭 토글), leaf: 파일\n const nodeIcon = document.createElement('i');\n if (treeNode._hasChildren) {\n const iconCls = _resolveTreeIcon(col.treeNodeIcon, rowData, true, treeNode._expanded);\n nodeIcon.className = treeNode._expanded\n ? `${iconCls} og-tree-node-icon og-tree-node-icon--branch og-tree-node-icon--open og-tree-node-icon--toggle`\n : `${iconCls} og-tree-node-icon og-tree-node-icon--branch og-tree-node-icon--toggle`;\n nodeIcon.setAttribute('role', 'button');\n nodeIcon.setAttribute('tabindex', '0');\n nodeIcon.setAttribute('aria-expanded', treeNode._expanded ? 'true' : 'false');\n nodeIcon.setAttribute('aria-label', treeNode._expanded ? '접기' : '펼치기');\n nodeIcon.addEventListener('click', (e: MouseEvent) => {\n e.stopPropagation();\n onTreeToggle?.(treeNode._treeId);\n });\n nodeIcon.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n onTreeToggle?.(treeNode._treeId);\n }\n });\n } else {\n const iconCls = _resolveTreeIcon(col.treeNodeIcon, rowData, false, false);\n nodeIcon.setAttribute('aria-hidden', 'true');\n nodeIcon.className = `${iconCls} og-tree-node-icon og-tree-node-icon--leaf`;\n }\n treeCell.appendChild(nodeIcon);\n\n cellEl.appendChild(treeCell);\n _treeRenderTarget = treeCell;\n }\n\n // 사용자 정의 cellStyle\n if (col.cellStyle) {\n const val = rowData[col.field];\n const s = typeof col.cellStyle === 'function' ? col.cellStyle(val, rowData as any, ri) : col.cellStyle;\n Object.assign(cellEl.style, s);\n }\n\n // 렌더러 사용 — 트리 첫 컬럼은 treeCell 안에 추가, 그 외는 cellEl에 추가\n const renderer = createRenderer(col);\n const rendered = renderer.render({\n value: rowData[col.field], row: rowData, rowIndex: ri,\n column: col as any, colIndex: ci,\n isSelected: selectedRows.has(ri), rowState\n });\n _treeRenderTarget.appendChild(rendered);\n\n // 이벤트\n const localRi = ri, localCi = ci;\n cellEl.addEventListener('click', (e) => { e.stopPropagation(); this._cbs.onCellClick(localRi, localCi, e); });\n cellEl.addEventListener('dblclick', (e) => { e.stopPropagation(); this._cbs.onCellDblClick(localRi, localCi, e); });\n cellEl.addEventListener('mouseover', (e) => { e.stopPropagation(); this._cbs.onCellMouseOver(localRi, localCi, e); });\n cellEl.addEventListener('mouseout', (e) => { e.stopPropagation(); this._cbs.onCellMouseOut(localRi, localCi, e); });\n cellEl.addEventListener('mousedown', (e) => { e.stopPropagation(); this._cbs.onCellMouseDown(localRi, localCi, e); });\n cellEl.addEventListener('mouseup', (e) => { e.stopPropagation(); this._cbs.onCellMouseUp(localRi, localCi, e); });\n cellEl.addEventListener('mousemove', (e) => { e.stopPropagation(); this._cbs.onCellMouseMove(localRi, localCi, e); });\n\n colMap.set(ci, cellEl);\n\n if (rs > 1) {\n // ① 마스터 행의 flex에 투명 placeholder 삽입 → 컬럼 너비 보존\n const ph = document.createElement('div');\n ph.style.cssText = [\n `width:${w}px;min-width:${w}px;height:${opts.rowHeight}px;`,\n 'flex-shrink:0;box-sizing:border-box;',\n 'border-right:1px solid var(--og-border-color,#e0e0e0);',\n ].join('');\n rowEl.appendChild(ph);\n\n // ② 마스터셀은 body 기준 absolute — top/left 정밀 계산\n let leftOff = 0;\n if (opts.stateColumn) leftOff += 24;\n if (opts.draggable) leftOff += 18;\n if (opts.rowNumber) leftOff += 44;\n if (opts.checkColumn) leftOff += 36;\n for (let pc = 0; pc < ci; pc++) leftOff += widths[pc] ?? opts.defaultColumnWidth;\n const rowTop = offsetY + (ri - startIndex) * opts.rowHeight;\n cellEl.style.left = `${leftOff}px`;\n cellEl.style.top = `${rowTop}px`;\n frag.appendChild(cellEl); // rowEl이 아닌 body 레벨에 직접 부착\n } else {\n rowEl.appendChild(cellEl);\n }\n }\n\n this._cellMap.set(ri, colMap);\n frag.appendChild(rowEl);\n }\n\n // 빈 데이터 메시지\n if (data.rowCount === 0) {\n const empty = _el('div', 'og-empty-message');\n empty.textContent = '데이터가 없습니다.';\n empty.style.cssText = `width:100%;`;\n frag.appendChild(empty);\n }\n\n this._body.appendChild(frag);\n }\n\n getCellEl(rowIndex: number, colIndex: number): HTMLElement | undefined {\n return this._cellMap.get(rowIndex)?.get(colIndex);\n }\n\n destroy(): void {\n this._root.innerHTML = '';\n }\n}\n\n// ─── 트리 노드 아이콘 해석 ────────────────────────────────\nfunction _resolveTreeIcon(\n def: TreeNodeIconDef | ((row: Record<string, any>, hasChildren: boolean, expanded: boolean) => string) | undefined,\n row: Record<string, any>,\n hasChildren: boolean,\n expanded: boolean\n): string {\n let icon: string;\n if (!def) {\n icon = hasChildren ? (expanded ? 'bi-folder2-open' : 'bi-folder2') : 'bi-file-earmark';\n } else if (typeof def === 'function') {\n icon = def(row, hasChildren, expanded);\n } else {\n if (hasChildren) {\n icon = expanded ? (def.branchOpen ?? 'bi-folder2-open') : (def.branch ?? 'bi-folder2');\n } else {\n icon = def.leaf ?? 'bi-file-earmark';\n }\n }\n return icon.startsWith('bi ') ? icon : `bi ${icon}`;\n}\n\n// ─── DOM 유틸 ─────────────────────────────────────────────\nexport function _el(tag: string, className?: string): HTMLElement {\n const e = document.createElement(tag);\n if (className) e.className = className;\n return e;\n}\n\nexport function _style(el: HTMLElement, styles: Partial<CSSStyleDeclaration>): void {\n Object.assign(el.style, styles);\n}\n\nexport function _downloadText(content: string, filename: string, mime = 'text/plain;charset=utf-8'): void {\n const blob = new Blob([content], { type: mime });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url; a.download = filename; a.click();\n URL.revokeObjectURL(url);\n}\n\n// ─── 컬럼 리사이즈 헬퍼 ──────────────────────────────────\nfunction _addResizer(handle: HTMLElement, th: HTMLElement, onChange: (w: number) => void): void {\n let startX = 0, startW = 0;\n\n handle.addEventListener('mousedown', (e: MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n startX = e.clientX;\n startW = th.offsetWidth;\n\n const onMove = (ev: MouseEvent) => {\n const w = Math.max(40, startW + ev.clientX - startX);\n th.style.width = `${w}px`;\n th.style.minWidth = `${w}px`;\n };\n const onUp = (ev: MouseEvent) => {\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseup', onUp);\n onChange(Math.max(40, startW + ev.clientX - startX));\n };\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseup', onUp);\n });\n}\n","import { DataLayer } from './DataLayer.js';\n\nexport class RowManager<T extends Record<string, any> = any> {\n private _selectedRows: Set<number> = new Set();\n private _checkedRows: Set<number> = new Set();\n private _data: DataLayer<T>;\n\n constructor(data: DataLayer<T>) {\n this._data = data;\n }\n\n // ─── Read-only 접근 ───────────────────────────────────────\n get selectedRows(): Set<number> { return this._selectedRows; }\n get checkedRows(): Set<number> { return this._checkedRows; }\n\n // ─── 선택 변경 ───────────────────────────────────────────\n selectSingle(ri: number): void {\n this._selectedRows.clear();\n this._selectedRows.add(ri);\n }\n\n selectToggle(ri: number): void {\n if (this._selectedRows.has(ri)) this._selectedRows.delete(ri);\n else this._selectedRows.add(ri);\n }\n\n clearSelection(): void { this._selectedRows.clear(); }\n\n // ─── 체크 변경 ───────────────────────────────────────────\n check(ri: number, checked: boolean): void {\n if (checked) this._checkedRows.add(ri);\n else this._checkedRows.delete(ri);\n }\n\n checkAll(checked: boolean, totalRows: number): void {\n if (checked) {\n for (let i = 0; i < totalRows; i++) this._checkedRows.add(i);\n } else {\n this._checkedRows.clear();\n }\n }\n\n checkByValue(field: string, values: any[]): void {\n for (let i = 0; i < this._data.rowCount; i++) {\n if (values.includes(this._data.getCellValue(i, field))) this._checkedRows.add(i);\n }\n }\n\n uncheckAll(): void { this._checkedRows.clear(); }\n\n checkById(_ids: string[]): void {}\n addCheckById(_ids: string[]): void {}\n uncheckById(_ids: string[]): void {}\n\n // ─── 선택 쿼리 API ───────────────────────────────────────\n getSelections(): T[] {\n return [...this._selectedRows]\n .map(i => this._data.getRowByIndex(i))\n .filter(Boolean) as T[];\n }\n\n getChecked(): Array<{ row: T; rowIndex: number }> {\n return [...this._checkedRows].map(i => ({\n row: this._data.getRowByIndex(i) as T,\n rowIndex: i,\n }));\n }\n\n getAllChecked(): T[] { return this.getChecked().map(r => r.row); }\n\n getActiveRow(): number {\n return this._selectedRows.size > 0 ? [...this._selectedRows][0]! : -1;\n }\n\n activate(index: number): void {\n this._selectedRows.clear();\n this._selectedRows.add(index);\n }\n\n deselect(): void { this._selectedRows.clear(); }\n\n // ─── 전체 초기화 (setData / clearData 시) ────────────────\n reset(): void {\n this._selectedRows.clear();\n this._checkedRows.clear();\n }\n}\n","import type { CellEditor } from './CellEditor.js';\nimport type { RenderContext } from '../renderers/CellRenderer.js';\nimport { formatDate } from '../renderers/CellRenderer.js';\n\nexport class DateEditor implements CellEditor {\n private input!: HTMLInputElement;\n private _container!: HTMLElement;\n private _onCommit!: (v: any) => void;\n private _onCancel!: () => void;\n\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (v: any) => void, onCancel: () => void): void {\n this._container = container;\n this._onCommit = onCommit;\n this._onCancel = onCancel;\n\n container.setAttribute('aria-haspopup', 'dialog');\n container.setAttribute('aria-expanded', 'true');\n\n this.input = document.createElement('input');\n this.input.type = 'date';\n this.input.className = 'og-cell-input';\n this.input.setAttribute('aria-label', ctx.column.header ?? '날짜 선택');\n\n const raw = ctx.value;\n if (raw) {\n const d = raw instanceof Date ? raw : new Date(raw);\n if (!isNaN(d.getTime())) {\n this.input.value = formatDate(d, 'yyyy-MM-dd');\n }\n }\n\n this.input.addEventListener('keydown', this._onKeyDown);\n this.input.addEventListener('blur', this._onBlur);\n container.appendChild(this.input);\n }\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n e.stopPropagation();\n if (e.key === 'Enter') { e.preventDefault(); this._onCommit(this.input.value); }\n else if (e.key === 'Escape') this._onCancel();\n };\n\n private _onBlur = (): void => { this._onCommit(this.input.value); };\n\n getValue(): any { return this.input?.value; }\n focus(): void { this.input?.focus(); }\n\n destroy(): void {\n this._container?.setAttribute('aria-expanded', 'false');\n this.input?.removeEventListener('keydown', this._onKeyDown);\n this.input?.removeEventListener('blur', this._onBlur);\n }\n}\n","import type { CellEditor } from './CellEditor.js';\nimport type { RenderContext } from '../renderers/CellRenderer.js';\n\nexport type SelectOption = string | { label?: string; text?: string; value: any };\n\nfunction normalizeOptions(raw: SelectOption[]): Array<{ label: string; value: any }> {\n return raw.map(o => {\n if (typeof o === 'string') return { label: o, value: o };\n const label = (o as any).label ?? (o as any).text ?? String((o as any).value ?? '');\n return { label, value: (o as any).value };\n });\n}\n\nexport class SelectEditor implements CellEditor {\n private select!: HTMLSelectElement;\n private _container!: HTMLElement;\n private _onCommit!: (v: any) => void;\n private _onCancel!: () => void;\n private _options: Array<{ label: string; value: any }>;\n private _optionsFn: ((row: any, rowIndex: number) => SelectOption[]) | null;\n\n constructor(\n options: SelectOption[] = [],\n optionsFn?: (row: any, rowIndex: number) => SelectOption[]\n ) {\n this._options = normalizeOptions(options);\n this._optionsFn = optionsFn ?? null;\n }\n\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (v: any) => void, onCancel: () => void): void {\n this._container = container;\n this._onCommit = onCommit;\n this._onCancel = onCancel;\n\n container.setAttribute('aria-haspopup', 'listbox');\n container.setAttribute('aria-expanded', 'true');\n\n this.select = document.createElement('select');\n this.select.className = 'og-cell-select';\n this.select.setAttribute('aria-label', ctx.column.header ?? '선택');\n\n const resolved = this._optionsFn\n ? normalizeOptions(this._optionsFn(ctx.row, ctx.rowIndex))\n : this._options;\n\n for (const opt of resolved) {\n const el = document.createElement('option');\n el.value = String(opt.value);\n el.textContent = opt.label;\n this.select.appendChild(el);\n }\n\n const cur = ctx.value == null ? '' : String(ctx.value);\n if (resolved.some(o => String(o.value) === cur)) this.select.value = cur;\n\n this.select.addEventListener('change', () => onCommit(this.select.value));\n this.select.addEventListener('blur', () => onCommit(this.select.value));\n this.select.addEventListener('keydown', (e) => { if (e.key === 'Escape') onCancel(); });\n container.appendChild(this.select);\n }\n\n getValue(): any { return this.select?.value; }\n focus(): void { this.select?.focus(); }\n\n destroy(): void {\n this._container?.setAttribute('aria-expanded', 'false');\n }\n}\n","import type { ColumnDef } from '../types.js';\nimport type { RenderContext } from '../renderers/CellRenderer.js';\nexport { DateEditor } from './DateEditor.js';\nexport { SelectEditor } from './SelectEditor.js';\nimport { DateEditor } from './DateEditor.js';\nimport { SelectEditor } from './SelectEditor.js';\n\nexport interface EditorResult {\n committed: boolean;\n value: any;\n}\n\nexport interface CellEditor {\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (value: any) => void, onCancel: () => void): void;\n getValue(): any;\n focus(): void;\n destroy(): void;\n}\n\n// ─── TextEditor ───────────────────────────────────────────\nexport class TextEditor implements CellEditor {\n private input!: HTMLInputElement;\n private _onCommit!: (v: any) => void;\n private _onCancel!: () => void;\n\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (v: any) => void, onCancel: () => void): void {\n this._onCommit = onCommit;\n this._onCancel = onCancel;\n\n this.input = document.createElement('input');\n this.input.type = 'text';\n this.input.value = ctx.value == null ? '' : String(ctx.value);\n this.input.style.cssText = `\n width:100%;height:100%;border:none;outline:none;padding:0 8px;\n font-size:var(--og-font-size,13px);font-family:var(--og-font-family,sans-serif);\n background:var(--og-row-bg,#fff);box-sizing:border-box;\n `;\n\n this.input.addEventListener('keydown', this._onKeyDown);\n this.input.addEventListener('blur', this._onBlur);\n container.appendChild(this.input);\n }\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n e.stopPropagation();\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n this._onCommit(this.input.value);\n } else if (e.key === 'Escape') {\n this._onCancel();\n }\n };\n\n private _onBlur = (): void => {\n this._onCommit(this.input.value);\n };\n\n getValue(): any { return this.input?.value; }\n\n focus(): void {\n this.input?.focus();\n this.input?.select();\n }\n\n destroy(): void {\n this.input?.removeEventListener('keydown', this._onKeyDown);\n this.input?.removeEventListener('blur', this._onBlur);\n }\n}\n\n// ─── NumberEditor ─────────────────────────────────────────\nexport class NumberEditor implements CellEditor {\n private input!: HTMLInputElement;\n private _onCommit!: (v: any) => void;\n private _onCancel!: () => void;\n private min: number | undefined;\n private max: number | undefined;\n private step: number | undefined;\n\n constructor(opts?: { min?: number; max?: number; step?: number }) {\n this.min = opts?.min;\n this.max = opts?.max;\n this.step = opts?.step;\n }\n\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (v: any) => void, onCancel: () => void): void {\n this._onCommit = onCommit;\n this._onCancel = onCancel;\n\n this.input = document.createElement('input');\n this.input.type = 'number';\n this.input.value = ctx.value == null ? '' : String(ctx.value);\n if (this.min != null) this.input.min = String(this.min);\n if (this.max != null) this.input.max = String(this.max);\n if (this.step != null) this.input.step = String(this.step);\n this.input.style.cssText = `\n width:100%;height:100%;border:none;outline:none;padding:0 8px;\n font-size:var(--og-font-size,13px);text-align:right;\n background:var(--og-row-bg,#fff);box-sizing:border-box;\n `;\n this.input.addEventListener('keydown', this._onKeyDown);\n this.input.addEventListener('blur', this._onBlur);\n container.appendChild(this.input);\n }\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n e.stopPropagation();\n if (e.key === 'Enter' || e.key === 'Tab') { e.preventDefault(); this._commit(); }\n else if (e.key === 'Escape') this._onCancel();\n };\n\n private _onBlur = (): void => { this._commit(); };\n\n private _commit(): void {\n const v = this.input.value === '' ? null : Number(this.input.value);\n this._onCommit(v);\n }\n\n getValue(): any { return this.input?.value === '' ? null : Number(this.input?.value); }\n focus(): void { this.input?.focus(); this.input?.select(); }\n destroy(): void {\n this.input?.removeEventListener('keydown', this._onKeyDown);\n this.input?.removeEventListener('blur', this._onBlur);\n }\n}\n\n\n// ─── CheckboxEditor ───────────────────────────────────────\nexport class CheckboxEditor implements CellEditor {\n private chk!: HTMLInputElement;\n private _onCommit!: (v: any) => void;\n\n mount(container: HTMLElement, ctx: RenderContext, onCommit: (v: any) => void, _onCancel: () => void): void {\n this._onCommit = onCommit;\n container.style.cssText += 'display:flex;align-items:center;justify-content:center;';\n\n this.chk = document.createElement('input');\n this.chk.type = 'checkbox';\n this.chk.checked = !!ctx.value;\n this.chk.style.cursor = 'pointer';\n this.chk.addEventListener('change', () => onCommit(this.chk.checked));\n container.appendChild(this.chk);\n }\n\n getValue(): any { return this.chk?.checked; }\n focus(): void { this.chk?.focus(); }\n destroy(): void {}\n}\n\n// ─── Editor 팩토리 ────────────────────────────────────────\nexport function createEditor(col: ColumnDef): CellEditor {\n const editor = col.editor;\n if (!editor) {\n switch (col.type as string) {\n case 'number': return new NumberEditor();\n case 'date': return new DateEditor();\n case 'boolean': return new CheckboxEditor();\n case 'select': return new SelectEditor(col.options ?? [], col.optionsFn as any);\n default: return new TextEditor();\n }\n }\n if (typeof editor === 'string') {\n switch (editor) {\n case 'number': return new NumberEditor();\n case 'date': return new DateEditor();\n case 'select': return new SelectEditor(col.options ?? [], col.optionsFn as any);\n case 'checkbox': return new CheckboxEditor();\n default: return new TextEditor();\n }\n }\n // EditorDef 객체\n switch (editor.type) {\n case 'number': {\n const opts: { min?: number; max?: number; step?: number } = {};\n if (editor.min != null) opts.min = editor.min;\n if (editor.max != null) opts.max = editor.max;\n if (editor.step != null) opts.step = editor.step;\n return new NumberEditor(opts);\n }\n case 'date': return new DateEditor();\n case 'select': return new SelectEditor(editor.options ?? [], col.optionsFn as any);\n case 'checkbox': return new CheckboxEditor();\n default: return new TextEditor();\n }\n}\n","import type { ColumnDef } from './types.js';\n\nexport function isToggleCol<T>(col: ColumnDef<T>): boolean {\n const rendType = typeof col.renderer === 'string'\n ? col.renderer\n : (col.renderer && typeof col.renderer === 'object' ? (col.renderer as any).type : '');\n return col.type === 'boolean' || (col.type as string) === 'checkbox'\n || rendType === 'checkbox' || rendType === 'switch';\n}\n\nexport function isSelectCol<T>(col: ColumnDef<T>): boolean {\n return (col.type as string) === 'select';\n}\n\nexport function isRadioCol<T>(col: ColumnDef<T>): boolean {\n return (col.type as string) === 'radio';\n}\n","import { DataLayer } from './DataLayer.js';\nimport { ColumnLayout } from './ColumnLayout.js';\nimport { GridRenderer } from './GridRenderer.js';\nimport { createEditor } from './editors/CellEditor.js';\nimport type { CellEditor } from './editors/CellEditor.js';\nimport type { ColumnDef, EditEvent } from './types.js';\nimport { isToggleCol } from './CellTypeRegistry.js';\n\nexport interface CellEditDeps<T extends Record<string, any>> {\n data: DataLayer<T>;\n colLayout: ColumnLayout<T>;\n getRenderer: () => GridRenderer | null;\n getContainer: () => HTMLElement;\n getOptions: () => any;\n emit: (event: string, ...args: any[]) => void;\n doRender: () => void;\n announce: (msg: string) => void;\n writeCell: (ri: number, field: string, value: any) => void;\n scrollToRow: (ri: number) => void;\n getVisibleLeaves: () => ColumnDef<T>[];\n}\n\nexport class CellEditManager<T extends Record<string, any> = any> {\n private _activeEditor: CellEditor | null = null;\n private _editCell: { ri: number; ci: number } | null = null;\n private _focusCell: { ri: number; ci: number } | null = null;\n private _dragColIdx: number | null = null;\n\n private _d: CellEditDeps<T>;\n\n constructor(deps: CellEditDeps<T>) {\n this._d = deps;\n }\n\n // ─── 상태 접근자 ─────────────────────────────────────────\n get activeEditor(): CellEditor | null { return this._activeEditor; }\n get editCell(): { ri: number; ci: number } | null { return this._editCell; }\n get focusCell(): { ri: number; ci: number } | null { return this._focusCell; }\n get dragColIdx(): number | null { return this._dragColIdx; }\n set dragColIdx(v: number | null) { this._dragColIdx = v; }\n\n // ─── 포커스 셀 ───────────────────────────────────────────\n setFocusCell(ri: number, ci: number): void {\n this._focusCell = { ri, ci };\n this._d.scrollToRow(ri);\n this._d.doRender();\n const col = this._d.getVisibleLeaves()[ci];\n const row = this._d.data.getRowByIndex(ri);\n if (col && row) {\n const val = (row as any)[col.field];\n this._d.announce(\n `${ri + 1}행 ${ci + 1}열, ${col.header}: ${val == null ? '빈 값' : String(val)}`\n );\n }\n }\n\n clearFocusCell(): void { this._focusCell = null; }\n\n // ─── 편집 시작 (키보드) ──────────────────────────────────\n startEditByKey(rowIndex: number, colIndex: number): void {\n const col = this._d.getVisibleLeaves()[colIndex];\n if (!col) return;\n\n if (isToggleCol(col)) {\n const opts = this._d.getOptions();\n const colEditable = col.editable !== false && (col.editable !== undefined || opts.editable);\n if (colEditable) {\n const row = this._d.data.getRowByIndex(rowIndex);\n if (row) this._d.writeCell(rowIndex, col.field as unknown as string, !(row as any)[col.field]);\n }\n return;\n }\n\n const row = this._d.data.getRowByIndex(rowIndex);\n if (col.editable === false) return;\n if (typeof col.editable === 'function' && !col.editable(row as T, rowIndex)) return;\n\n this.commitEdit();\n const cellEl = this._d.getRenderer()?.getCellEl(rowIndex, colIndex);\n if (!cellEl) return;\n cellEl.innerHTML = '';\n\n const editor = createEditor(col);\n this._activeEditor = editor;\n this._editCell = { ri: rowIndex, ci: colIndex };\n\n const startEvt: EditEvent<T> = {\n type: 'editStart', rowIndex, columnIndex: colIndex,\n field: col.field, oldValue: row?.[col.field], newValue: row?.[col.field],\n row: row as T, column: col as any\n };\n this._d.emit('editStart', startEvt);\n this._d.getOptions().onEditStart?.(startEvt);\n\n cellEl.classList.add('og-editing');\n const ctx = {\n value: row?.[col.field], row: row as any, rowIndex,\n column: col as any, colIndex, isSelected: true, rowState: 'none' as any\n };\n editor.mount(cellEl, ctx,\n (value) => this.commitEditWithValue(rowIndex, colIndex, value),\n () => this.cancelEdit()\n );\n requestAnimationFrame(() => editor.focus());\n }\n\n // ─── 편집 시작 (마우스) ──────────────────────────────────\n startEdit(rowIndex: number, colIndex: number, _e: MouseEvent): void {\n const opts = this._d.getOptions();\n if (!opts.editable) return;\n const col = this._d.getVisibleLeaves()[colIndex];\n if (!col) return;\n\n if (isToggleCol(col)) return;\n\n const row = this._d.data.getRowByIndex(rowIndex);\n if (col.editable === false) return;\n if (typeof col.editable === 'function' && !col.editable(row as T, rowIndex)) return;\n if (!col.editable && !opts.editable) return;\n\n this.commitEdit();\n\n const cellEl = this._d.getRenderer()?.getCellEl(rowIndex, colIndex);\n if (!cellEl) return;\n cellEl.innerHTML = '';\n\n const editor = createEditor(col);\n this._activeEditor = editor;\n this._editCell = { ri: rowIndex, ci: colIndex };\n\n const startEvt: EditEvent<T> = {\n type: 'editStart', rowIndex, columnIndex: colIndex,\n field: col.field, oldValue: row?.[col.field], newValue: row?.[col.field],\n row: row as T, column: col as any\n };\n this._d.emit('editStart', startEvt);\n opts.onEditStart?.(startEvt);\n\n cellEl.classList.add('og-editing');\n const ctx = {\n value: row?.[col.field], row: row as any, rowIndex,\n column: col as any, colIndex, isSelected: true, rowState: 'none' as any\n };\n editor.mount(cellEl, ctx,\n (value) => this.commitEditWithValue(rowIndex, colIndex, value),\n () => this.cancelEdit()\n );\n requestAnimationFrame(() => editor.focus());\n }\n\n // ─── 편집 종료 ───────────────────────────────────────────\n commitEdit(): void {\n if (!this._activeEditor || !this._editCell) return;\n const val = this._activeEditor.getValue();\n const { ri, ci } = this._editCell;\n this._finishEdit(ri, ci, val, false);\n }\n\n commitEditWithValue(ri: number, ci: number, value: any): void {\n this._finishEdit(ri, ci, value, false);\n }\n\n cancelEdit(): void {\n if (!this._editCell) return;\n const { ri, ci } = this._editCell;\n this._finishEdit(ri, ci, undefined, true);\n }\n\n private _finishEdit(ri: number, ci: number, value: any, cancel: boolean): void {\n if (!this._activeEditor) return;\n const col = this._d.getVisibleLeaves()[ci];\n const cellEl = this._d.getRenderer()?.getCellEl(ri, ci);\n if (cellEl) {\n this._activeEditor.destroy();\n cellEl.classList.remove('og-editing');\n }\n this._activeEditor = null;\n this._editCell = null;\n\n if (!cancel && col) {\n const old = this._d.data.getCellValue(ri, col.field);\n if (value !== old) {\n this._d.data.updateCell(ri, col.field, value);\n const row = this._d.data.getRowByIndex(ri);\n const opts = this._d.getOptions();\n const evt: EditEvent<T> = {\n type: 'editEnd', rowIndex: ri, columnIndex: ci,\n field: col.field, oldValue: old, newValue: value,\n row: row as T, column: col as any\n };\n this._d.emit('editEnd', evt);\n opts.onEditEnd?.(evt);\n this._d.emit('dataChange', this._d.data.getData());\n opts.onDataChange?.(this._d.data.getData());\n }\n }\n this._d.doRender();\n requestAnimationFrame(() => this._d.getContainer().focus({ preventScroll: true }));\n }\n}\n","import type { FilterItem } from './types.js';\n\n// ─── 공개 타입 ────────────────────────────────────────────\n\nexport interface FilterSelectOption {\n value: string;\n text: string;\n}\n\n/**\n * 캐스케이딩 필터 셀렉트 컬럼 정의.\n *\n * ### 데이터 공급 방식 (택 1)\n *\n * **A. JSON 배열 바인딩** (권장)\n * ```ts\n * {\n * field: 'brand',\n * label: '브랜드',\n * data: brandList, // any[] ← JSON 배열\n * valueKey: 'brandCode', // 필터·선택값으로 사용할 키\n * textKey: 'brandName', // 화면에 표시할 텍스트 키\n * filterKey: 'brand', // 그리드 행 데이터의 필터 기준 키 (기본: field)\n * dependsOn: 'category', // 부모 컬럼 field\n * dependsOnKey: 'catCode', // 자식 data[]에서 부모값과 매칭할 키\n * }\n * ```\n *\n * **B. 정적 옵션 배열**\n * ```ts\n * { field: 'status', options: [{ value: 'Y', text: '활성' }] }\n * ```\n */\nexport interface FilterSelectColumn {\n /** 캐스케이딩 식별자 / 기본 필터 키 */\n field: string;\n /** 화면 표시 라벨 */\n label: string;\n\n // ── A. JSON 배열 바인딩 ──────────────────────────────\n /** 바인딩할 JSON 배열 */\n data?: any[];\n /** data[]에서 option value로 사용할 키 */\n valueKey?: string;\n /** data[]에서 화면 표시 text로 사용할 키 (미지정 시 valueKey 사용) */\n textKey?: string;\n /**\n * 그리드 행 데이터에서 실제 필터링할 키.\n * 미지정 시 `field` 값 그대로 사용.\n *\n * @example\n * // 그리드 row.category === selectedValue 로 필터링\n * filterKey: 'category'\n */\n filterKey?: string;\n\n // ── B. 정적 옵션 (data 대신 사용) ───────────────────\n options?: FilterSelectOption[];\n\n // ── 캐스케이딩 ────────────────────────────────────────\n /** 부모 컬럼의 field 명 */\n dependsOn?: string;\n /**\n * 자식 data[]에서 부모 선택값과 비교할 키.\n *\n * @example\n * // brandList.filter(b => b.catCode === parentSelectedValue)\n * dependsOnKey: 'catCode'\n */\n dependsOnKey?: string;\n}\n\nexport interface FilterSelectConfig {\n columns: FilterSelectColumn[];\n /** fieldset 제목 (기본: '필터') */\n legend?: string;\n}\n\ntype FilterFn = (field: string, items: FilterItem[]) => void;\ntype ResetFn = (field?: string) => void;\n\n// ─── FilterSelectPanel ────────────────────────────────────\nexport class FilterSelectPanel {\n private _el: HTMLFieldSetElement;\n private _selects = new Map<string, HTMLSelectElement>();\n /** 현재 선택 상태 { field → selectedValue } */\n private _selected: Record<string, string> = {};\n private _config: FilterSelectConfig;\n private _onFilter: FilterFn;\n private _onReset: ResetFn;\n\n constructor(\n container: HTMLElement,\n config: FilterSelectConfig,\n onFilter: FilterFn,\n onReset: ResetFn,\n gridId?: string,\n ) {\n this._config = config;\n this._onFilter = onFilter;\n this._onReset = onReset;\n\n /* fieldset */\n this._el = document.createElement('fieldset');\n this._el.className = 'og-filter-select';\n\n const legend = document.createElement('legend');\n legend.className = 'og-filter-select-legend';\n legend.textContent = config.legend ?? '필터';\n this._el.appendChild(legend);\n\n const row = document.createElement('div');\n row.className = 'og-filter-select-row';\n\n for (const col of config.columns) {\n const uid = `og-fsel-${col.field}`;\n\n const wrap = document.createElement('div');\n wrap.className = 'og-filter-select-group';\n\n const label = document.createElement('label');\n label.htmlFor = uid;\n label.textContent = col.label;\n label.className = 'og-filter-select-label';\n\n const select = document.createElement('select');\n select.id = uid;\n select.className = 'og-filter-select-sel';\n select.setAttribute('aria-label', col.label);\n if (gridId) select.setAttribute('aria-controls', gridId);\n\n if (!col.dependsOn) {\n /* 루트 컬럼 — 즉시 전체 옵션 로드 */\n this._fill(select, this._resolve(col, ''), true);\n } else {\n /* 종속 컬럼 — 부모 선택 전까지 비활성 */\n this._fill(select, [], false);\n }\n\n select.addEventListener('change', () => this._onChange(col.field, select.value));\n\n wrap.appendChild(label);\n wrap.appendChild(select);\n row.appendChild(wrap);\n this._selects.set(col.field, select);\n }\n\n /* 초기화 버튼 */\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.textContent = '초기화';\n btn.className = 'og-filter-select-reset';\n btn.setAttribute('aria-label', '필터 초기화');\n btn.addEventListener('click', () => this._reset());\n\n this._el.appendChild(row);\n this._el.appendChild(btn);\n\n /* 그리드 헤더 앞에 삽입 */\n container.insertBefore(this._el, container.firstChild);\n }\n\n // ─── 옵션 해결 ────────────────────────────────────────\n /**\n * 컬럼의 옵션 목록을 계산한다.\n *\n * @param col 대상 컬럼 정의\n * @param parentValue 부모 선택값 (캐스케이딩 필터에 사용)\n */\n private _resolve(col: FilterSelectColumn, parentValue: string): FilterSelectOption[] {\n /* B. 정적 옵션 배열 */\n if (col.options) return col.options;\n\n /* A. JSON 배열 + 키 매핑 */\n let rows = col.data ?? [];\n\n /* 캐스케이딩: dependsOnKey 기준으로 부모 선택값과 매칭 */\n if (col.dependsOn && col.dependsOnKey && parentValue) {\n rows = rows.filter(\n item => String(item[col.dependsOnKey!] ?? '') === parentValue,\n );\n }\n\n const vk = col.valueKey ?? 'value';\n const tk = col.textKey ?? vk;\n\n return rows.map(item => ({\n value: String(item[vk] ?? ''),\n text: String(item[tk] ?? item[vk] ?? ''),\n }));\n }\n\n // ─── select DOM 채우기 ────────────────────────────────\n private _fill(\n select: HTMLSelectElement,\n opts: FilterSelectOption[],\n enabled: boolean,\n ): void {\n select.innerHTML = '';\n const all = document.createElement('option');\n all.value = ''; all.textContent = '전체';\n select.appendChild(all);\n for (const o of opts) {\n const el = document.createElement('option');\n el.value = o.value; el.textContent = o.text;\n select.appendChild(el);\n }\n select.disabled = !enabled;\n }\n\n // ─── 선택 변경 처리 ───────────────────────────────────\n private _onChange(field: string, value: string): void {\n const col = this._config.columns.find(c => c.field === field)!;\n const fk = col.filterKey ?? col.field; // 실제 그리드 필터 키\n\n if (value) {\n this._selected[field] = value;\n this._onFilter(fk, [{ operator: '=', value }]);\n } else {\n delete this._selected[field];\n this._onReset(fk);\n }\n this._cascade(field);\n }\n\n /**\n * 부모 컬럼 변경 후 자식 컬럼 옵션을 재계산한다 (재귀).\n */\n private _cascade(parentField: string): void {\n const parentValue = this._selected[parentField] ?? '';\n\n for (const col of this._config.columns) {\n if (col.dependsOn !== parentField) continue;\n const sel = this._selects.get(col.field);\n if (!sel) continue;\n const fk = col.filterKey ?? col.field;\n\n if (!parentValue) {\n /* 부모 초기화 → 자식 비활성 */\n this._fill(sel, [], false);\n delete this._selected[col.field];\n this._onReset(fk);\n this._cascade(col.field); // 하위로 재귀\n } else {\n /* 부모 값 있음 → 자식 옵션 재로드 */\n this._fill(sel, this._resolve(col, parentValue), true);\n sel.value = '';\n delete this._selected[col.field];\n this._onReset(fk);\n }\n }\n }\n\n // ─── 전체 초기화 ──────────────────────────────────────\n private _reset(): void {\n this._selected = {};\n for (const col of this._config.columns) {\n const sel = this._selects.get(col.field);\n const fk = col.filterKey ?? col.field;\n if (!sel) continue;\n if (!col.dependsOn) {\n sel.value = ''; sel.disabled = false;\n } else {\n this._fill(sel, [], false);\n }\n this._onReset(fk);\n }\n }\n\n // ─── 공개 API ─────────────────────────────────────────\n reset(): void { this._reset(); }\n destroy(): void { this._el.remove(); }\n}\n","export interface PageChangeEvent {\n page: number;\n pageSize: number;\n totalRows: number;\n totalPages: number;\n}\n\nexport type PageChangeFn = (e: PageChangeEvent) => void;\n\n/**\n * 그리드 하단 페이지네이션 UI + 상태 관리.\n * DataLayer의 _displayIndexes 슬라이싱을 담당.\n */\nexport class Pagination {\n private _el: HTMLElement;\n private _page = 1;\n private _pageSize: number;\n private _totalRows = 0;\n private _onChange: PageChangeFn;\n\n constructor(container: HTMLElement, pageSize: number, onChange: PageChangeFn) {\n this._pageSize = pageSize;\n this._onChange = onChange;\n\n this._el = document.createElement('div');\n this._el.className = 'og-pagination';\n this._el.style.cssText = `\n display:flex;align-items:center;justify-content:center;gap:4px;\n padding:6px 8px;border-top:1px solid var(--og-border-color,#e0e0e0);\n background:var(--og-header-bg,#f5f5f5);flex-shrink:0;user-select:none;\n font-size:12px;color:var(--og-text-color,#333);\n `;\n container.appendChild(this._el);\n this._render();\n }\n\n get page() { return this._page; }\n get pageSize() { return this._pageSize; }\n get totalPages() { return Math.max(1, Math.ceil(this._totalRows / this._pageSize)); }\n\n /** 전체 행 수 갱신 → 현재 페이지 유효성 검사 후 재렌더 */\n setTotalRows(n: number): void {\n this._totalRows = n;\n if (this._page > this.totalPages) this._page = this.totalPages;\n this._render();\n }\n\n setPageSize(size: number): void {\n this._pageSize = size;\n this._page = 1;\n this._render();\n this._emit();\n }\n\n goTo(page: number): void {\n const p = Math.max(1, Math.min(page, this.totalPages));\n if (p === this._page) return;\n this._page = p;\n this._render();\n this._emit();\n }\n\n /** 현재 페이지의 [startIndex, endIndex] 반환 (DataLayer 인덱스 기준) */\n getRange(): { start: number; end: number } {\n const start = (this._page - 1) * this._pageSize;\n const end = Math.min(start + this._pageSize - 1, this._totalRows - 1);\n return { start, end };\n }\n\n private _emit(): void {\n this._onChange({\n page: this._page, pageSize: this._pageSize,\n totalRows: this._totalRows, totalPages: this.totalPages,\n });\n }\n\n private _render(): void {\n this._el.innerHTML = '';\n const total = this.totalPages;\n\n // 페이지 크기 선택\n const sizeWrap = document.createElement('span');\n sizeWrap.style.cssText = 'display:flex;align-items:center;gap:3px;margin-right:8px;';\n const sizeLabel = document.createElement('span');\n sizeLabel.textContent = '행/페이지:';\n sizeLabel.style.color = '#888';\n const sizeSel = document.createElement('select');\n sizeSel.style.cssText = `padding:2px 4px;border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;font-size:11px;cursor:pointer;`;\n for (const s of [10, 20, 50, 100, 200]) {\n const opt = document.createElement('option');\n opt.value = String(s);\n opt.textContent = String(s);\n if (s === this._pageSize) opt.selected = true;\n sizeSel.appendChild(opt);\n }\n sizeSel.addEventListener('change', () => this.setPageSize(Number(sizeSel.value)));\n sizeWrap.appendChild(sizeLabel);\n sizeWrap.appendChild(sizeSel);\n this._el.appendChild(sizeWrap);\n\n // 총 행 수\n const info = document.createElement('span');\n const { start, end } = this.getRange();\n info.textContent = this._totalRows > 0\n ? `${start + 1}–${end + 1} / ${this._totalRows}건`\n : '0건';\n info.style.cssText = 'margin-right:8px;color:#888;';\n this._el.appendChild(info);\n\n // 이전/다음 버튼 + 페이지 번호\n const mkBtn = (label: string, page: number, disabled: boolean) => {\n const btn = document.createElement('button');\n btn.textContent = label;\n btn.disabled = disabled;\n btn.style.cssText = `\n min-width:28px;height:24px;padding:0 6px;\n border:1px solid var(--og-border-color,#e0e0e0);border-radius:3px;\n background:${disabled ? '#f5f5f5' : '#fff'};\n color:${disabled ? '#bbb' : 'var(--og-text-color,#333)'};\n cursor:${disabled ? 'default' : 'pointer'};font-size:12px;\n `;\n if (!disabled) btn.addEventListener('click', () => this.goTo(page));\n return btn;\n };\n\n this._el.appendChild(mkBtn('«', 1, this._page === 1));\n this._el.appendChild(mkBtn('‹', this._page - 1, this._page === 1));\n\n // 페이지 번호 (최대 5개 표시)\n const range = _pageRange(this._page, total);\n for (const p of range) {\n if (p === -1) {\n const dot = document.createElement('span');\n dot.textContent = '…';\n dot.style.padding = '0 3px';\n this._el.appendChild(dot);\n } else {\n const btn = mkBtn(String(p), p, p === this._page);\n if (p === this._page) {\n btn.style.background = 'var(--og-primary,#1976d2)';\n btn.style.color = '#fff';\n btn.style.borderColor = 'var(--og-primary,#1976d2)';\n }\n this._el.appendChild(btn);\n }\n }\n\n this._el.appendChild(mkBtn('›', this._page + 1, this._page === total));\n this._el.appendChild(mkBtn('»', total, this._page === total));\n }\n\n destroy(): void {\n this._el.remove();\n }\n}\n\n/** 현재 페이지 기준 표시할 페이지 번호 배열 (-1 = ellipsis) */\nfunction _pageRange(current: number, total: number): number[] {\n if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);\n const pages: number[] = [1];\n if (current > 3) pages.push(-1);\n for (let p = Math.max(2, current - 1); p <= Math.min(total - 1, current + 1); p++) {\n pages.push(p);\n }\n if (current < total - 2) pages.push(-1);\n pages.push(total);\n return pages;\n}\n","// ============================================================\n// 드래그 시각 요소 — 고스트(따라다니는 점선 박스) + 드롭 인디케이터(라인)\n// RowDragDrop 에서 분리해 단일 책임으로 캡슐화한다.\n// ============================================================\n\n/** 커서를 따라다니는 점선 고스트. transform 으로 X·Y 모두 이동(부드럽게). */\nexport class DragGhost {\n private _el: HTMLElement;\n private _dx: number; // grab 지점의 좌측 오프셋\n private _dy: number; // grab 지점의 상단 오프셋\n\n constructor(rect: DOMRect, grabX: number, grabY: number, count: number) {\n this._dx = grabX - rect.left;\n this._dy = grabY - rect.top;\n\n const el = document.createElement('div');\n el.className = 'og-drag-ghost';\n el.style.cssText =\n `position:fixed;left:0;top:0;width:${rect.width}px;height:${Math.min(rect.height, 40)}px;` +\n `transform:translate(${rect.left}px,${rect.top}px);` +\n 'background:rgba(25,118,210,0.12);border:2px dashed #1976d2;box-sizing:border-box;' +\n 'pointer-events:none;z-index:10000;border-radius:3px;opacity:0.92;' +\n 'display:flex;align-items:center;padding-left:10px;font-size:12px;color:#1565c0;font-weight:600;' +\n 'white-space:nowrap;overflow:hidden;';\n if (count > 1) el.textContent = `${count}개 행 이동`;\n document.body.appendChild(el);\n this._el = el;\n }\n\n /** 커서 위치로 이동 (grab 오프셋 유지) */\n move(clientX: number, clientY: number): void {\n this._el.style.transform = `translate(${clientX - this._dx}px,${clientY - this._dy}px)`;\n }\n\n destroy(): void { this._el.remove(); }\n}\n\n/**\n * 드롭(삽입) 위치 마커. 행과 행 사이 경계에 \"▶━━━◀\" 형태로 또렷하게 표시해\n * \"여기에 삽입됩니다 / 지금 버튼을 떼면 됩니다\" 를 직관적으로 알린다(워드 표 삽입 표시 느낌).\n * 자기 그리드/타깃 그리드 모두에 재사용.\n */\nexport class DropIndicator {\n private _el: HTMLElement;\n\n constructor(color = '#1976d2') {\n const el = document.createElement('div');\n el.className = 'og-drop-indicator';\n // 경계(top) 중앙에 마커가 오도록 translateY(-50%)\n el.style.cssText =\n 'position:absolute;left:0;right:0;display:none;align-items:center;' +\n 'pointer-events:none;z-index:9998;transform:translateY(-50%);';\n\n const cap = (dir: 'left' | 'right'): HTMLElement => {\n const c = document.createElement('div');\n const side = dir === 'left' ? `border-left:7px solid ${color}` : `border-right:7px solid ${color}`;\n c.style.cssText =\n `width:0;height:0;flex-shrink:0;border-top:5px solid transparent;border-bottom:5px solid transparent;${side};`;\n return c;\n };\n const bar = document.createElement('div');\n bar.style.cssText =\n `flex:1;height:3px;background:${color};border-radius:2px;box-shadow:0 0 0 1px rgba(255,255,255,0.7);`;\n\n el.append(cap('left'), bar, cap('right')); // ▶━━━◀\n this._el = el;\n }\n\n /** parent(그리드 바디) 안의 top(행 경계) 위치에 표시 */\n showIn(parent: HTMLElement, top: number): void {\n if (this._el.parentElement !== parent) {\n this._el.remove();\n parent.appendChild(this._el);\n }\n this._el.style.display = 'flex';\n this._el.style.top = `${top}px`;\n }\n\n hide(): void { this._el.style.display = 'none'; }\n\n destroy(): void { this._el.remove(); }\n}\n","import { DragGhost, DropIndicator } from './DragVisuals.js';\n\nexport type RowDropCallback = (fromIndex: number, toIndex: number) => void;\n\n/** 커서 좌표로 다른 그리드의 바디를 찾는 해석기 */\nexport interface CrossGridResolveResult {\n bodyEl: HTMLElement;\n rowHeight: number;\n totalRows: number;\n}\nexport interface CrossGridConfig {\n /** 커서 위치(x,y)에 있는 다른(crossGrid 허용) 그리드 바디 정보 반환. 없으면 null */\n resolveTarget: (clientX: number, clientY: number) => CrossGridResolveResult | null;\n /** 다른 그리드로 드롭됐을 때 호출 (소스 fromIndex, 타깃 바디, 타깃 삽입 인덱스) */\n onCrossDrop: (fromIndex: number, targetBodyEl: HTMLElement, targetIndex: number) => void;\n}\n\ninterface DragState {\n fromIndex: number;\n bodyEl: HTMLElement;\n rowHeight: number;\n totalRows: number;\n ghost: DragGhost;\n currentTarget: number;\n /** 현재 커서가 올라가 있는 다른 그리드 (없으면 null = 자기 그리드 내 재정렬) */\n crossTarget: { bodyEl: HTMLElement; index: number } | null;\n}\n\nconst clamp = (v: number, lo: number, hi: number) => Math.max(lo, Math.min(hi, v));\n\n/**\n * 행 드래그앤드롭 관리자 (순수 DnD).\n * 행 DOM에 드래그 핸들을 심고, 고스트/인디케이터로 위치를 표시한 뒤 콜백으로 알림.\n * 그리드 간 이동 판정(타깃 그리드 해석)은 주입된 CrossGridConfig 에 위임한다.\n */\nexport class RowDragDrop {\n private _drag: DragState | null = null;\n private readonly _selfIndicator = new DropIndicator('#1976d2'); // 자기 그리드 재정렬\n private readonly _crossIndicator = new DropIndicator('#2e7d32'); // 다른 그리드 드롭\n\n constructor(\n private _bodyEl: HTMLElement,\n private _rowHeight: number,\n private _onDrop: RowDropCallback,\n private _cross: CrossGridConfig | null = null,\n /** fromIndex 기준 함께 드래그할 행 수(멀티행 배지용). 기본 1 */\n private _getDragCount: (fromIndex: number) => number = () => 1,\n ) {\n this._onMouseMove = this._onMouseMove.bind(this);\n this._onMouseUp = this._onMouseUp.bind(this);\n }\n\n /** 행 엘리먼트에 드래그 핸들 삽입 */\n attachHandle(rowEl: HTMLElement, rowIndex: number, totalRows: number): HTMLElement {\n const handle = document.createElement('div');\n handle.className = 'og-drag-handle';\n handle.innerHTML = '⠿';\n handle.style.cssText = `\n width:18px;min-width:18px;height:100%;\n display:flex;align-items:center;justify-content:center;\n cursor:grab;font-size:14px;color:#bbb;flex-shrink:0;\n user-select:none;border-right:1px solid var(--og-border-color,#e0e0e0);\n `;\n handle.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n this._startDrag(e, rowEl, rowIndex, totalRows);\n });\n return handle;\n }\n\n private _startDrag(e: MouseEvent, rowEl: HTMLElement, fromIndex: number, totalRows: number): void {\n const rect = rowEl.getBoundingClientRect();\n const count = this._getDragCount(fromIndex);\n this._drag = {\n fromIndex,\n bodyEl: this._bodyEl,\n rowHeight: this._rowHeight,\n totalRows,\n ghost: new DragGhost(rect, e.clientX, e.clientY, count),\n currentTarget: fromIndex,\n crossTarget: null,\n };\n // 캡처 단계로 등록 — 바디 셀이 mousemove/mouseup 에서 stopPropagation 해도\n // (버블 단계 차단) 드래그 추적/종료가 항상 동작하게 한다.\n document.addEventListener('mousemove', this._onMouseMove, true);\n document.addEventListener('mouseup', this._onMouseUp, true);\n }\n\n private _onMouseMove(e: MouseEvent): void {\n if (!this._drag) return;\n const d = this._drag;\n\n // 고스트가 커서를 X·Y 모두 따라간다 (다른 그리드로 끌어도 끊기지 않음)\n d.ghost.move(e.clientX, e.clientY);\n\n // ── 크로스그리드: 커서가 다른 그리드 위에 있는지 ──\n if (this._cross) {\n const hit = this._cross.resolveTarget(e.clientX, e.clientY);\n if (hit && hit.bodyEl !== d.bodyEl) {\n const tRect = hit.bodyEl.getBoundingClientRect();\n const tRelY = e.clientY - tRect.top + hit.bodyEl.scrollTop;\n const tIdx = clamp(Math.round(tRelY / hit.rowHeight), 0, hit.totalRows);\n d.crossTarget = { bodyEl: hit.bodyEl, index: tIdx };\n this._selfIndicator.hide();\n this._crossIndicator.showIn(hit.bodyEl, tIdx * hit.rowHeight);\n return;\n }\n }\n\n // ── 자기 그리드 내 재정렬 ──\n d.crossTarget = null;\n this._crossIndicator.hide();\n const bodyRect = d.bodyEl.getBoundingClientRect();\n const relY = e.clientY - bodyRect.top + d.bodyEl.scrollTop;\n d.currentTarget = clamp(Math.round(relY / d.rowHeight), 0, d.totalRows - 1);\n this._selfIndicator.showIn(d.bodyEl, d.currentTarget * d.rowHeight);\n }\n\n private _onMouseUp(_e: MouseEvent): void {\n document.removeEventListener('mousemove', this._onMouseMove, true);\n document.removeEventListener('mouseup', this._onMouseUp, true);\n\n if (!this._drag) return;\n const { fromIndex, currentTarget, ghost, crossTarget } = this._drag;\n this._drag = null;\n\n // 모든 드래그 잔상 제거\n ghost.destroy();\n this._selfIndicator.hide();\n this._crossIndicator.hide();\n\n if (crossTarget && this._cross) {\n this._cross.onCrossDrop(fromIndex, crossTarget.bodyEl, crossTarget.index);\n } else if (fromIndex !== currentTarget) {\n this._onDrop(fromIndex, currentTarget);\n }\n }\n\n destroy(): void {\n document.removeEventListener('mousemove', this._onMouseMove, true);\n document.removeEventListener('mouseup', this._onMouseUp, true);\n this._drag?.ghost.destroy();\n this._selfIndicator.destroy();\n this._crossIndicator.destroy();\n this._drag = null;\n }\n}\n","/**\n * 셀 병합 관리 엔진.\n *\n * 두 가지 병합 방식 지원:\n * 1. 동적 병합: mergeCells([{row, col, rowSpan, colSpan}])\n * 2. 자동 병합: 같은 필드에 같은 값이 연속되면 자동으로 rowSpan\n */\n\nexport interface MergeCell {\n row: number; // display row index (0-based)\n col: number; // leaf column index (0-based)\n rowSpan?: number; // 1 이상 (기본 1)\n colSpan?: number; // 1 이상 (기본 1)\n}\n\nexport interface MergeInfo {\n rowSpan: number;\n colSpan: number;\n hidden: boolean; // 병합으로 숨겨진 셀 (렌더링 생략)\n}\n\nexport class MergeEngine {\n // (row, col) → MergeInfo\n private _map: Map<string, MergeInfo> = new Map();\n\n private static _key(row: number, col: number): string {\n return `${row}:${col}`;\n }\n\n /** 수동 병합 정의 목록으로 맵 구성 */\n applyMergeCells(cells: MergeCell[]): void {\n this._map.clear();\n for (const mc of cells) {\n const rs = Math.max(1, mc.rowSpan ?? 1);\n const cs = Math.max(1, mc.colSpan ?? 1);\n // 기준 셀\n this._map.set(MergeEngine._key(mc.row, mc.col), {\n rowSpan: rs, colSpan: cs, hidden: false,\n });\n // 병합된 하위 셀 — hidden:true\n for (let r = 0; r < rs; r++) {\n for (let c = 0; c < cs; c++) {\n if (r === 0 && c === 0) continue;\n this._map.set(MergeEngine._key(mc.row + r, mc.col + c), {\n rowSpan: 1, colSpan: 1, hidden: true,\n });\n }\n }\n }\n }\n\n /**\n * 자동 병합: 지정 컬럼 인덱스 목록에 대해 연속 같은 값을 rowSpan으로 병합.\n * data: 현재 표시 순서의 행 배열, colIndexes: 자동병합할 leaf 컬럼 인덱스\n * fields: colIndexes[i] 에 대응하는 field 이름\n */\n applyAutoMerge(\n data: Record<string, any>[],\n colIndexes: number[],\n fields: string[]\n ): void {\n this._map.clear();\n for (let ci = 0; ci < colIndexes.length; ci++) {\n const col = colIndexes[ci]!;\n const field = fields[ci]!;\n let spanStart = 0;\n\n for (let ri = 1; ri <= data.length; ri++) {\n const prevVal = data[ri - 1]?.[field];\n const curVal = ri < data.length ? data[ri]?.[field] : undefined;\n\n if (ri === data.length || curVal !== prevVal) {\n const span = ri - spanStart;\n if (span > 1) {\n this._map.set(MergeEngine._key(spanStart, col), {\n rowSpan: span, colSpan: 1, hidden: false,\n });\n for (let r = spanStart + 1; r < ri; r++) {\n this._map.set(MergeEngine._key(r, col), {\n rowSpan: 1, colSpan: 1, hidden: true,\n });\n }\n }\n spanStart = ri;\n }\n }\n }\n }\n\n /** 셀 병합 정보 조회. 없으면 null */\n getInfo(row: number, col: number): MergeInfo | null {\n return this._map.get(MergeEngine._key(row, col)) ?? null;\n }\n\n /** 병합 맵 초기화 */\n clear(): void {\n this._map.clear();\n }\n\n get isEmpty(): boolean {\n return this._map.size === 0;\n }\n}\n","// ============================================================\n// ContextMenu — 우클릭 팝업 컨텍스트 메뉴 관리자\n// 레이어: Orchestration (UI 생성 + 이벤트 조율)\n// 설계 근거(Why): 메뉴를 document.body가 아닌 그리드 컨테이너(_anchor)의\n// 자식으로 추가한다. position:fixed로 뷰포트 기준 배치를 유지하면서\n// CSS 변수(--og-*)를 컨테이너에서 자동 상속 → 테마 즉시 반영.\n// ============================================================\n\nimport type { ContextMenuItem } from './types.js';\n\nexport type { ContextMenuItem };\n\nexport interface ContextMenuActions {\n onSortAsc: () => void;\n onSortDesc: () => void;\n onFind: () => void;\n onExcel: () => void;\n onCsv: () => void;\n onPrint: () => void;\n}\n\nexport const DEFAULT_CONTEXT_ITEMS: ContextMenuItem[] = [\n { id: 'sort-asc', label: '오름차순 정렬', icon: '↑', action: 'sortAsc' },\n { id: 'sort-desc', label: '내림차순 정렬', icon: '↓', action: 'sortDesc' },\n { type: 'divider' },\n { id: 'find', label: '찾기', icon: '🔍', action: 'find' },\n { type: 'divider' },\n { id: 'excel', label: 'Excel로 저장', icon: '📊', action: 'excel' },\n { id: 'csv', label: 'CSV로 저장', icon: '📄', action: 'csv' },\n { id: 'print', label: '인쇄', icon: '🖨', action: 'print' },\n];\n\nexport class ContextMenuManager {\n private _el: HTMLElement | null = null;\n private _docClick: ((e: MouseEvent) => void) | null = null;\n private _docKey: ((e: KeyboardEvent) => void) | null = null;\n private _docScroll: (() => void) | null = null;\n private _docMouseMove: ((e: MouseEvent) => void) | null = null;\n private _focusIdx = -1;\n\n /**\n * @param _anchor 그리드 컨테이너 엘리먼트 — CSS 변수 상속 기준점\n * @param _actions 기본 액션 핸들러 (OpenGrid에서 주입)\n */\n constructor(\n private readonly _anchor: HTMLElement,\n private readonly _actions: ContextMenuActions,\n ) {}\n\n open(e: MouseEvent, customItems?: ContextMenuItem[]): void {\n this.close();\n\n const items = customItems ?? DEFAULT_CONTEXT_ITEMS;\n const menu = document.createElement('div');\n menu.className = 'og-context-menu';\n menu.setAttribute('role', 'menu');\n\n for (const item of items) {\n if (item.type === 'divider') {\n const hr = document.createElement('div');\n hr.className = 'og-cm-divider';\n hr.setAttribute('role', 'separator');\n menu.appendChild(hr);\n continue;\n }\n\n const btn = document.createElement('button');\n btn.className = 'og-cm-item';\n btn.setAttribute('role', 'menuitem');\n btn.setAttribute('tabindex', '-1');\n if (item.disabled) {\n btn.classList.add('og-cm-disabled');\n btn.setAttribute('aria-disabled', 'true');\n }\n\n if (item.icon) {\n const ic = document.createElement('span');\n ic.className = 'og-cm-icon';\n // CSS 클래스명(예: 'bi bi-star', 'fa fa-home')이면 <i> 태그로 렌더링\n // 이모지·특수문자·단일 기호면 textContent로 처리\n if (/^[a-zA-Z][\\w-]*(\\s+[\\w-]+)+$/.test(item.icon.trim())) {\n const i = document.createElement('i');\n i.className = item.icon;\n ic.appendChild(i);\n } else {\n ic.textContent = item.icon;\n }\n ic.setAttribute('aria-hidden', 'true');\n btn.appendChild(ic);\n }\n\n const lbl = document.createElement('span');\n lbl.className = 'og-cm-label';\n lbl.textContent = item.label ?? '';\n btn.appendChild(lbl);\n\n btn.addEventListener('click', (ev) => {\n ev.stopPropagation();\n if (!item.disabled) this._runAction(item);\n this.close();\n });\n menu.appendChild(btn);\n }\n\n // document.body 자식으로 추가 → position:fixed 가 항상 뷰포트 기준으로 동작.\n // Why: 그리드 컨테이너(_anchor)에 붙이면, 임베드 호스트(WordPress 글 등)의\n // 조상에 transform/filter 가 있을 때 fixed 기준점이 그 조상으로 바뀌어\n // 메뉴가 마우스 좌표에서 어긋난다(특히 그리드 너비를 넓힐 때). body 부착으로 회피.\n // 테마 CSS 변수(--og-cm-*, --og-*)는 menu 에 data-og-theme 를 복사해 보존한다.\n const themeEl = this._anchor.closest('[data-og-theme]') as HTMLElement | null;\n const theme = themeEl?.getAttribute('data-og-theme');\n if (theme) menu.setAttribute('data-og-theme', theme);\n document.body.appendChild(menu);\n this._el = menu;\n\n // mousemove capture 단계로 등록 — 셀의 stopPropagation() 우회\n // Why: 그리드 셀이 mousemove에 stopPropagation()을 호출해 bubble 단계 document 리스너가 차단됨\n this._docMouseMove = (ev) => {\n if (!this._el) return;\n const r = this._el.getBoundingClientRect();\n if (ev.clientX < r.left - 4 || ev.clientX > r.right + 4 ||\n ev.clientY < r.top - 4 || ev.clientY > r.bottom + 4) {\n this.close();\n }\n };\n\n // position:fixed 기준 좌표 설정 → 포지셔닝 완료 후 올바른 bounds로 리스너 등록\n this._position(menu, e.clientX, e.clientY, () => {\n if (this._el === menu) {\n document.addEventListener('mousemove', this._docMouseMove!, { capture: true, passive: true });\n }\n });\n\n // 외부 클릭 닫기 (다음 틱 — 현재 contextmenu 이벤트 전파 완료 후)\n this._docClick = (ev) => {\n if (!menu.contains(ev.target as Node)) this.close();\n };\n // 키보드 접근성\n this._docKey = (ev) => {\n if (ev.key === 'Escape') { this.close(); return; }\n if (ev.key === 'ArrowDown') { ev.preventDefault(); this._moveFocus(1); return; }\n if (ev.key === 'ArrowUp') { ev.preventDefault(); this._moveFocus(-1); return; }\n if (ev.key === 'Enter') {\n const focused = menu.querySelector<HTMLButtonElement>('.og-cm-item:focus');\n focused?.click();\n }\n };\n this._docScroll = () => this.close();\n\n setTimeout(() => {\n document.addEventListener('click', this._docClick!);\n document.addEventListener('keydown', this._docKey!);\n window.addEventListener('scroll', this._docScroll!, { passive: true });\n }, 0);\n\n // 첫 활성 항목에 포커스\n this._focusIdx = -1;\n this._moveFocus(1);\n }\n\n close(): void {\n this._el?.remove();\n this._el = null;\n if (this._docClick) document.removeEventListener('click', this._docClick);\n if (this._docKey) document.removeEventListener('keydown', this._docKey);\n if (this._docScroll) window.removeEventListener('scroll', this._docScroll);\n if (this._docMouseMove) document.removeEventListener('mousemove', this._docMouseMove, { capture: true });\n this._docClick = this._docKey = this._docScroll = this._docMouseMove = null;\n this._focusIdx = -1;\n }\n\n destroy(): void { this.close(); }\n\n // ── 위치 결정 ─────────────────────────────────────────────\n\n private _position(menu: HTMLElement, x: number, y: number, onPositioned?: () => void): void {\n menu.style.cssText = 'position:fixed;visibility:hidden;left:0;top:0;';\n\n requestAnimationFrame(() => {\n const { width, height } = menu.getBoundingClientRect();\n const vw = window.innerWidth, vh = window.innerHeight;\n const left = x + width > vw ? Math.max(0, x - width) : x;\n const top = y + height > vh ? Math.max(0, y - height) : y;\n menu.style.cssText = `position:fixed;left:${left}px;top:${top}px;z-index:9999;`;\n // 포지셔닝 완료 후 콜백 — mousemove 체크는 정확한 위치 기준으로만 동작\n onPositioned?.();\n });\n }\n\n // ── 키보드 포커스 이동 ────────────────────────────────────\n\n private _moveFocus(dir: 1 | -1): void {\n if (!this._el) return;\n const btns = Array.from(\n this._el.querySelectorAll<HTMLButtonElement>('.og-cm-item:not(.og-cm-disabled)')\n );\n if (!btns.length) return;\n this._focusIdx = (this._focusIdx + dir + btns.length) % btns.length;\n btns[this._focusIdx]?.focus();\n }\n\n // ── 액션 실행 ─────────────────────────────────────────────\n\n private _runAction(item: ContextMenuItem): void {\n if (typeof item.action === 'function') { item.action(); return; }\n switch (item.action) {\n case 'sortAsc': this._actions.onSortAsc(); break;\n case 'sortDesc': this._actions.onSortDesc(); break;\n case 'find': this._actions.onFind(); break;\n case 'excel': this._actions.onExcel(); break;\n case 'csv': this._actions.onCsv(); break;\n case 'print': this._actions.onPrint(); break;\n }\n }\n}\n","// ============================================================\n// WorksheetManager — 그리드 다중 워크시트(탭) 관리자\n// 레이어: Orchestration (시트 상태 관리 + 탭 UI 조율)\n// 설계 근거(Why): OpenGrid 내부에 _wsManager로 보유.\n// 시트별로 독립적인 columns + data를 Map으로 관리하고,\n// 탭 클릭 시 OpenGrid.setData/applyColumns로 화면 전환.\n// 탭 UI는 그리드 컨테이너 하단에 .og-sheet-tabs 영역으로 삽입.\n// ============================================================\n\nimport type { ColumnDef, WorksheetDef, WorksheetState } from './types.js';\n\nexport type SwitchCallback<T> = (name: string, state: WorksheetState<T>) => void;\n\nexport class WorksheetManager<T extends Record<string, any> = any> {\n private _sheets: Map<string, WorksheetState<T>> = new Map();\n private _active: string = '';\n private _tabBar: HTMLElement;\n private _onSwitch: SwitchCallback<T>;\n\n constructor(container: HTMLElement, onSwitch: SwitchCallback<T>) {\n this._onSwitch = onSwitch;\n this._tabBar = this._buildTabBar(container);\n }\n\n // ── 시트 CRUD ────────────────────────────────────────────\n\n add(name: string, columns: ColumnDef<T>[] = [], data: T[] = []): void {\n if (this._sheets.has(name)) {\n throw new Error(`WorksheetManager: 시트 '${name}'이 이미 존재합니다`);\n }\n this._sheets.set(name, { name, columns, data });\n this._renderTabs();\n\n // 첫 시트는 자동 활성\n if (this._sheets.size === 1) this.switch(name);\n }\n\n remove(name: string): void {\n if (!this._sheets.has(name)) return;\n if (this._sheets.size === 1) {\n throw new Error('WorksheetManager: 마지막 시트는 삭제할 수 없습니다');\n }\n const wasActive = this._active === name;\n this._sheets.delete(name);\n this._renderTabs();\n\n if (wasActive) {\n // 삭제 후 첫 번째 남은 시트로 전환\n this.switch(this._sheets.keys().next().value!);\n }\n }\n\n rename(oldName: string, newName: string): void {\n if (!this._sheets.has(oldName)) return;\n if (this._sheets.has(newName)) {\n throw new Error(`WorksheetManager: 시트 '${newName}'이 이미 존재합니다`);\n }\n const state = this._sheets.get(oldName)!;\n // Map 순서 유지를 위해 재삽입\n const entries = Array.from(this._sheets.entries()).map(([k, v]) =>\n k === oldName ? [newName, { ...v, name: newName }] as [string, WorksheetState<T>] : [k, v] as [string, WorksheetState<T>]\n );\n this._sheets = new Map(entries);\n if (this._active === oldName) this._active = newName;\n this._renderTabs();\n }\n\n switch(name: string): void {\n const state = this._sheets.get(name);\n if (!state) throw new Error(`WorksheetManager: 시트 '${name}'을 찾을 수 없습니다`);\n this._active = name;\n this._renderTabs();\n this._onSwitch(name, state);\n }\n\n get(name: string): WorksheetState<T> | undefined {\n return this._sheets.get(name);\n }\n\n getNames(): string[] {\n return Array.from(this._sheets.keys());\n }\n\n getActive(): string { return this._active; }\n\n /** 현재 활성 시트의 data를 갱신 (그리드 편집 동기화용) */\n syncData(name: string, data: T[]): void {\n const state = this._sheets.get(name);\n if (state) state.data = data;\n }\n\n destroy(): void {\n this._tabBar.remove();\n }\n\n // ── 탭 UI ────────────────────────────────────────────────\n\n private _buildTabBar(container: HTMLElement): HTMLElement {\n const bar = document.createElement('div');\n bar.className = 'og-sheet-tabs';\n container.appendChild(bar);\n return bar;\n }\n\n private _renderTabs(): void {\n this._tabBar.innerHTML = '';\n\n for (const name of this._sheets.keys()) {\n const tab = document.createElement('button');\n tab.className = 'og-sheet-tab';\n tab.textContent = name;\n tab.setAttribute('role', 'tab');\n tab.setAttribute('aria-selected', name === this._active ? 'true' : 'false');\n if (name === this._active) tab.classList.add('og-sheet-tab--active');\n\n // 단순 클릭: 시트 전환\n tab.addEventListener('click', () => {\n if (name !== this._active) this.switch(name);\n });\n\n // 더블클릭: 인라인 이름 변경\n tab.addEventListener('dblclick', () => this._startRename(tab, name));\n\n this._tabBar.appendChild(tab);\n }\n\n // '+' 새 시트 버튼\n const addBtn = document.createElement('button');\n addBtn.className = 'og-sheet-add';\n addBtn.textContent = '+';\n addBtn.setAttribute('aria-label', '새 워크시트 추가');\n addBtn.addEventListener('click', () => {\n const n = `Sheet${this._sheets.size + 1}`;\n this.add(n, [], []);\n this.switch(n);\n });\n this._tabBar.appendChild(addBtn);\n }\n\n /** 탭 더블클릭 → input으로 전환해 이름 변경 */\n private _startRename(tab: HTMLButtonElement, oldName: string): void {\n const input = document.createElement('input');\n input.className = 'og-sheet-tab-rename';\n input.value = oldName;\n tab.replaceWith(input);\n input.focus();\n input.select();\n\n const commit = () => {\n const newName = input.value.trim() || oldName;\n try {\n if (newName !== oldName) this.rename(oldName, newName);\n else this._renderTabs();\n } catch {\n this._renderTabs();\n }\n };\n\n input.addEventListener('blur', commit);\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') { input.blur(); }\n if (e.key === 'Escape') { input.value = oldName; input.blur(); }\n });\n }\n}\n","import { ColumnLayout } from './ColumnLayout.js';\nimport { _downloadText } from './GridRenderer.js';\nimport { applyMask } from './MaskingEngine.js';\nimport type { WorksheetManager } from './WorksheetManager.js';\nimport type { ExportOptions } from './types.js';\n\nexport interface ExportDeps<T extends Record<string, any>> {\n getData: () => T[];\n getColLayout: () => ColumnLayout<T>;\n getColWidths: () => number[];\n getOptions: () => any;\n getContainer: () => HTMLElement;\n getMaskEnabled: (field: string) => boolean;\n getWsManager: () => WorksheetManager<T> | null;\n /** Phase 2: OverrideKernel.getStrategy 주입(슬롯 cellSerializer 도달용). */\n getStrategy?: <F extends Function>(slot: string, fallback: F) => F;\n}\n\nexport class ExportManager<T extends Record<string, any> = any> {\n private _d: ExportDeps<T>;\n\n constructor(deps: ExportDeps<T>) {\n this._d = deps;\n }\n\n private _readCssVar(name: string): string {\n return getComputedStyle(this._d.getContainer()).getPropertyValue(name).trim();\n }\n\n private _hexToXlsxRgb(hex: string): string {\n const s = hex.trim();\n const rgbMatch = s.match(/^rgba?\\(\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)/i);\n if (rgbMatch) {\n return [rgbMatch[1], rgbMatch[2], rgbMatch[3]]\n .map(n => parseInt(n).toString(16).padStart(2, '0'))\n .join('').toUpperCase();\n }\n const h = s.replace('#', '').toUpperCase();\n if (h.length === 3) return h[0]+h[0]+h[1]+h[1]+h[2]+h[2];\n return h.length === 6 ? h : '';\n }\n\n exportExcel(options?: ExportOptions | string): void {\n const opts = typeof options === 'string' ? { filename: options } : (options ?? {});\n let fname = opts.filename ?? 'export';\n if (!fname.toLowerCase().endsWith('.xlsx')) fname += '.xlsx';\n const sheetName = opts.sheetName ?? (this._d.getOptions().ariaLabel || 'Sheet1');\n const data = this._d.getData();\n const cols = this._d.getColLayout().visibleLeaves.filter(c => !opts.exceptFields?.includes(c.field));\n const includeHeader = opts.includeHeader !== false;\n\n // Phase 2 슬롯 #4: cellSerializer. default = 현행 인라인(number→v, boolean→✓, object→'', else String).\n const serialize = (this._d.getStrategy ?? ((_s: string, fb: any) => fb))(\n 'cellSerializer',\n (v: any, col: any, _row: any): any => {\n if (col.type === 'number' && typeof v === 'number') return v;\n if (typeof v === 'boolean') return v ? '✓' : '';\n if (typeof v === 'object') return '';\n return String(v);\n },\n );\n\n import('xlsx-js-style').then(({ utils, writeFile }) => {\n const rows: any[][] = [];\n if (includeHeader) rows.push(cols.map(c => c.header));\n for (const row of data) {\n rows.push(cols.map(c => {\n const raw = (row as any)[c.field];\n if (opts.maskOnExport && c.mask && this._d.getMaskEnabled(c.field)) {\n return applyMask(raw == null ? '' : String(raw), c.mask);\n }\n const v = raw;\n if (v == null || v === '') return '';\n return serialize(v, c, row);\n }));\n }\n\n const ws = utils.aoa_to_sheet(rows);\n\n const colWidths = this._d.getColWidths();\n const colLayout = this._d.getColLayout();\n ws['!cols'] = cols.map(c => ({\n wpx: colWidths[colLayout.getColumnIndex(c.field)] ?? 100,\n }));\n ws['!rows'] = rows.map((_, ri) => ({ hpx: ri === 0 && includeHeader ? 22 : 19 }));\n\n const styleMode = opts.styleMode ?? 'theme';\n let hdrBgRgb = '1565C0', hdrFgRgb = 'FFFFFF';\n let rowBgRgb = 'FFFFFF', rowAltRgb = 'EEF2FF';\n let rowFgRgb = '212121', borderRgb = 'BDBDBD';\n let fontSize = 10;\n\n if (styleMode === 'theme') {\n const toRgb = (v: string) => this._hexToXlsxRgb(v);\n hdrBgRgb = toRgb(this._readCssVar('--og-header-bg')) || hdrBgRgb;\n hdrFgRgb = toRgb(this._readCssVar('--og-header-color')) || hdrFgRgb;\n rowBgRgb = toRgb(this._readCssVar('--og-row-bg')) || rowBgRgb;\n rowAltRgb = toRgb(this._readCssVar('--og-row-alt-bg')) || rowAltRgb;\n rowFgRgb = toRgb(this._readCssVar('--og-row-color')) || rowFgRgb;\n borderRgb = toRgb(this._readCssVar('--og-border-color')) || borderRgb;\n const fsStr = this._readCssVar('--og-font-size');\n if (fsStr) fontSize = Math.max(8, Math.round(parseFloat(fsStr) * 0.75));\n }\n\n const noStyle = styleMode === 'none';\n const S = {\n hdrFont: noStyle ? {} : { bold: true, color: { rgb: hdrFgRgb }, sz: fontSize, name: '맑은 고딕' },\n dataFont: noStyle ? {} : { sz: fontSize, color: { rgb: rowFgRgb }, name: '맑은 고딕' },\n hdrFill: noStyle ? {} : { patternType: 'solid' as const, fgColor: { rgb: hdrBgRgb } },\n evenFill: noStyle ? {} : { patternType: 'solid' as const, fgColor: { rgb: rowBgRgb } },\n oddFill: noStyle ? {} : { patternType: 'solid' as const, fgColor: { rgb: rowAltRgb } },\n hdrBorder: noStyle ? {} : {\n top: { style: 'medium', color: { rgb: hdrBgRgb } },\n bottom: { style: 'medium', color: { rgb: hdrBgRgb } },\n left: { style: 'thin', color: { rgb: hdrBgRgb } },\n right: { style: 'thin', color: { rgb: hdrBgRgb } },\n },\n dataBorder: noStyle ? {} : {\n top: { style: 'thin', color: { rgb: borderRgb } },\n bottom: { style: 'thin', color: { rgb: borderRgb } },\n left: { style: 'thin', color: { rgb: borderRgb } },\n right: { style: 'thin', color: { rgb: borderRgb } },\n },\n };\n\n rows.forEach((row, ri) => {\n const isHdr = includeHeader && ri === 0;\n const dataRi = includeHeader ? ri - 1 : ri;\n const isEven = dataRi % 2 === 0;\n\n row.forEach((_v, ci) => {\n const addr = utils.encode_cell({ r: ri, c: ci });\n if (!ws[addr]) ws[addr] = { t: 's', v: '' };\n\n const col = cols[ci]!;\n const isNum = col.type === 'number' || col.align === 'right';\n const hAlign = isHdr ? 'center' : isNum ? 'right' : (col.align ?? 'left');\n\n ws[addr].s = {\n font: isHdr ? S.hdrFont : S.dataFont,\n fill: isHdr ? S.hdrFill : (isEven ? S.evenFill : S.oddFill),\n border: isHdr ? S.hdrBorder : S.dataBorder,\n alignment: { horizontal: hAlign, vertical: 'center', wrapText: false },\n };\n });\n });\n\n const wb = utils.book_new();\n utils.book_append_sheet(wb, ws, sheetName);\n writeFile(wb, fname, { cellStyles: true } as any);\n opts.onAfter?.(new Blob([]));\n }).catch(() => {\n console.error('Excel 내보내기 실패: xlsx 패키지를 확인하세요.');\n });\n }\n\n exportCsv(options?: ExportOptions | string): void {\n const opts = typeof options === 'string' ? { filename: options } : (options ?? {});\n const data = this._d.getData();\n const cols = this._d.getColLayout().visibleLeaves;\n const hdr = cols.map(c => `\"${c.header}\"`).join(',');\n const rows = data.map(row => cols.map(c => {\n const raw = row[c.field] ?? '';\n if (opts.maskOnExport && c.mask && this._d.getMaskEnabled(c.field)) {\n return applyMask(String(raw), c.mask);\n }\n const v = raw;\n return typeof v === 'string' && v.includes(',') ? `\"${v}\"` : v;\n }).join(','));\n const fname = opts.filename ?? 'export.csv';\n _downloadText('' + [hdr, ...rows].join('\\n'), fname);\n }\n\n exportJson(options?: ExportOptions | string): void {\n const fname = typeof options === 'string' ? options : (options?.filename ?? 'export.json');\n _downloadText(JSON.stringify(this._d.getData(), null, 2), fname, 'application/json');\n }\n\n print(options?: { title?: string; excludeFields?: string[]; footerText?: string }): void {\n const title = options?.title ?? 'OPEN_GRID';\n const footerText = options?.footerText ?? '';\n const data = this._d.getData();\n const cols = this._d.getColLayout().visibleLeaves\n .filter(c => !options?.excludeFields?.includes(c.field));\n\n const headerRow = cols.map(c => `<th>${c.header ?? c.field}</th>`).join('');\n const bodyRows = data.map(row =>\n `<tr>${cols.map(c => `<td>${String(row[c.field] ?? '')}</td>`).join('')}</tr>`\n ).join('');\n const footerHtml = footerText\n ? `<div class=\"og-print-footer\">${footerText}</div>`\n : '';\n\n const html = `<!DOCTYPE html>\n<html lang=\"ko\"><head>\n<meta charset=\"UTF-8\"><title>${title}</title>\n<style>\n @page{margin:0;}\n body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:12px;margin:0;padding:1cm;}\n h2{margin:0 0 10px;font-size:14px;color:#333;}\n p{margin:0 0 8px;font-size:11px;color:#999;}\n table{border-collapse:collapse;width:100%;}\n th,td{border:1px solid #ccc;padding:5px 8px;text-align:left;white-space:nowrap;}\n th{background:#f5f5f5;font-weight:600;color:#333;}\n tr:nth-child(even) td{background:#fafafa;}\n .og-print-footer{position:fixed;bottom:0;left:0;right:0;padding:6px 1cm;font-size:10px;color:#888;border-top:1px solid #e5e7eb;background:#fff;text-align:center;}\n</style>\n</head><body>\n<h2>${title}</h2>\n<p>${data.length}행 × ${cols.length}열 · ${new Date().toLocaleString('ko-KR')}</p>\n<table>\n <thead><tr>${headerRow}</tr></thead>\n <tbody>${bodyRows}</tbody>\n</table>\n${footerHtml}\n<script>window.addEventListener('load',()=>{window.print();window.addEventListener('afterprint',()=>window.close());});<\\/script>\n</body></html>`;\n\n const win = window.open('', '_blank', 'width=960,height=640');\n if (win) { win.document.write(html); win.document.close(); }\n }\n\n exportSheetsExcel(filename?: string): void {\n const wsManager = this._d.getWsManager();\n if (!wsManager) { this.exportExcel(filename ?? 'workbook'); return; }\n const fname = filename ?? 'workbook.xlsx';\n\n // Phase 2 슬롯 #4: cellSerializer(시트 직렬화 지점). default = 현행 인라인.\n const serialize = (this._d.getStrategy ?? ((_s: string, fb: any) => fb))(\n 'cellSerializer',\n (v: any, col: any, _row: any): any => {\n if (typeof v === 'boolean') return v ? '✓' : '';\n return col.type === 'number' && typeof v === 'number' ? v : String(v);\n },\n );\n\n import('xlsx-js-style').then(({ utils, writeFile }) => {\n const wb = utils.book_new();\n const opts = this._d.getOptions();\n for (const name of wsManager.getNames()) {\n const state = wsManager.get(name)!;\n const cols = state.columns.length ? state.columns : opts.columns;\n const rows: any[][] = [cols.map((c: any) => c.header)];\n for (const row of state.data) {\n rows.push(cols.map((c: any) => {\n const v = (row as any)[c.field];\n if (v == null) return '';\n return serialize(v, c, row);\n }));\n }\n const ws = utils.aoa_to_sheet(rows);\n ws['!cols'] = cols.map(() => ({ wpx: 100 }));\n utils.book_append_sheet(wb, ws, name);\n }\n writeFile(wb, fname.endsWith('.xlsx') ? fname : fname + '.xlsx', { cellStyles: true } as any);\n }).catch(() => console.error('exportSheetsExcel: xlsx 패키지를 확인하세요.'));\n }\n}\n","import { ColumnLayout } from './ColumnLayout.js';\nimport { OGDecimal } from './OGDecimal.js';\n\nexport interface FooterDeps<T extends Record<string, any>> {\n getData: () => T[];\n getColLayout: () => ColumnLayout<T>;\n getColWidths: () => number[];\n getOptions: () => any;\n getContainer: () => HTMLElement;\n /** Phase 2: OverrideKernel.getStrategy 주입(슬롯 summaryOp 도달용). */\n getStrategy?: <F extends Function>(slot: string, fallback: F) => F;\n}\n\nexport class FooterManager<T extends Record<string, any> = any> {\n private _d: FooterDeps<T>;\n\n constructor(deps: FooterDeps<T>) {\n this._d = deps;\n }\n\n fmtNum(value: number, fmt?: string): string {\n if (!fmt) {\n return Math.round(value).toLocaleString('ko-KR');\n }\n // 통화 기호 등 접두/접미 분리 (숫자 토큰: #,0,콤마,소수 또는 레거시 정수)\n const tok = fmt.match(/[#0][#0,]*(?:\\.[#0]+)?|\\d+/);\n const prefix = tok ? fmt.slice(0, tok.index) : '';\n const suffix = tok ? fmt.slice(tok.index! + tok[0].length) : '';\n const numFmt = tok ? tok[0] : fmt;\n\n const useComma = numFmt.includes('#') || numFmt.includes(',');\n const dpMatch = numFmt.match(/\\.(\\d+)$/);\n const dp = dpMatch\n ? parseInt(dpMatch[1]!, 10)\n : /^\\d+$/.test(numFmt) ? parseInt(numFmt, 10) : 0;\n\n const fixed = Math.abs(value).toFixed(dp);\n const [intPart = '0', decPart] = fixed.split('.');\n const intStr = useComma\n ? intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n : intPart;\n\n const body = decPart !== undefined ? `${intStr}.${decPart}` : intStr;\n const result = `${prefix}${body}${suffix}`;\n return value < 0 ? `-${result}` : result;\n }\n\n computeValues(): any[] {\n const footerDefs = this._d.getOptions().footer;\n if (!footerDefs || footerDefs.length === 0) return [];\n\n const allData = this._d.getData();\n\n return footerDefs\n .filter((d: any) => d.field && d.op)\n .map((def: any) => {\n const field = def.field!;\n const op = def.op!;\n const nums = allData\n .map((r: any) => r[field])\n .filter((v: any) => v !== null && v !== undefined && v !== '');\n\n let result: OGDecimal | null = null;\n const opUC = (op as string).toUpperCase();\n\n // Phase 2 슬롯 #6: summaryOp. default = null(미가로챔 → 기존 SUM/AVG/COUNT/MAX/MIN switch).\n // 슬롯이 number 반환 시 그 값을 사용(MEDIAN/STDEV 등만 가로챔), null 반환 시 기본 분기 폴백.\n const customOp = (this._d.getStrategy ?? ((_s: string, fb: any) => fb))(\n 'summaryOp',\n null as ((op: string, nums: any[], field: string) => number | null) | null,\n );\n if (customOp) {\n const cv = customOp(opUC, nums, field);\n if (cv != null) {\n return { _field: field, _value: cv, _formatted: this.fmtNum(cv, def.format) };\n }\n }\n\n if (opUC === 'SUM') {\n result = nums.length > 0 ? OGDecimal.sum(nums.map((v: any) => String(v))) : null;\n } else if (opUC === 'AVG') {\n result = nums.length > 0\n ? OGDecimal.sum(nums.map((v: any) => String(v))).div(OGDecimal.from(String(nums.length)))\n : null;\n } else if (opUC === 'COUNT') {\n const cnt = nums.length;\n return { _field: field, _value: cnt, _formatted: cnt.toLocaleString('ko-KR') };\n } else if (opUC === 'MAX') {\n result = nums.length > 0 ? OGDecimal.max(nums.map((v: any) => String(v))) : null;\n } else if (opUC === 'MIN') {\n result = nums.length > 0 ? OGDecimal.min(nums.map((v: any) => String(v))) : null;\n }\n\n if (!result) return { _field: field, _value: null, _formatted: '' };\n\n const numVal = result.toNumber();\n const formatted = this.fmtNum(numVal, def.format);\n return { _field: field, _value: numVal, _formatted: formatted };\n });\n }\n\n render(): void {\n const container = this._d.getContainer();\n const old = container.querySelector('.og-footer-bar');\n old?.remove();\n\n const opts = this._d.getOptions();\n const footerDefs = opts.footer;\n if (!footerDefs || footerDefs.length === 0) return;\n\n const leaves = this._d.getColLayout().visibleLeaves;\n const widths = this._d.getColWidths() ?? leaves.map((l: any) => l.width ?? 100);\n const valMap = new Map(\n this.computeValues().map((v: any) => [v._field, v])\n );\n\n const bar = document.createElement('div');\n bar.className = 'og-footer-bar';\n bar.style.cssText = [\n 'display:flex;align-items:stretch;',\n `min-height:${opts.footerHeight}px;`,\n 'border-top:2px solid var(--og-primary,#1976d2);',\n 'background:var(--og-header-bg,#f5f5f5);',\n 'overflow:hidden;flex-shrink:0;font-size:13px;font-weight:600;',\n ].join('');\n\n let extraW = 0;\n if (opts.stateColumn) extraW += 24;\n if (opts.draggable) extraW += 18;\n if (opts.rowNumber) extraW += 44;\n if (opts.checkColumn) extraW += 36;\n if (extraW > 0) {\n const spacer = document.createElement('div');\n spacer.style.cssText = `width:${extraW}px;flex-shrink:0;border-right:1px solid var(--og-border-color,#e0e0e0);`;\n bar.appendChild(spacer);\n }\n\n let leafCursor = 0;\n\n for (const def of footerDefs) {\n const colspan = Math.max(1, def.colspan ?? 1);\n\n let cellW = 0;\n for (let c = 0; c < colspan; c++) {\n cellW += widths[leafCursor + c] ?? 100;\n }\n const targetLeaf = leaves[leafCursor];\n leafCursor += colspan;\n\n const cell = document.createElement('div');\n cell.style.cssText = [\n `width:${cellW}px;min-width:${cellW}px;flex-shrink:0;`,\n 'padding:4px 8px;box-sizing:border-box;overflow:hidden;',\n 'border-right:1px solid var(--og-border-color,#e0e0e0);',\n 'white-space:nowrap;text-overflow:ellipsis;',\n ].join('');\n\n const field = def.field;\n const val = field ? valMap.get(field) : null;\n\n if (val) {\n const displayVal = val._formatted ?? String(val._value ?? '');\n const prefix = def.label ? `${def.label}: ` : '';\n cell.textContent = prefix + displayVal;\n cell.title = `${(def.op as string)?.toUpperCase() ?? ''} = ${displayVal}`;\n cell.style.color = 'var(--og-primary,#1976d2)';\n cell.style.textAlign = def.align ?? (targetLeaf?.type === 'number' ? 'right' : 'right');\n } else if (def.label) {\n cell.textContent = def.label;\n cell.style.textAlign = def.align ?? 'left';\n cell.style.color = 'var(--og-row-color,#212121)';\n }\n\n bar.appendChild(cell);\n }\n\n if (opts.footerPosition === 'top') {\n container.insertBefore(bar, container.firstChild);\n } else {\n container.appendChild(bar);\n }\n }\n}\n","import type { DataLayer } from './DataLayer.js';\nimport type { ColumnLayout } from './ColumnLayout.js';\nimport type { CellEditManager } from './CellEditManager.js';\nimport type { RowManager } from './RowManager.js';\n\nexport interface KeyboardDeps<T extends Record<string, any>> {\n getEditMgr: () => CellEditManager<T>;\n getRowMgr: () => RowManager<T>;\n getData: () => DataLayer<T>;\n getColLayout: () => ColumnLayout<T>;\n getOptions: () => any;\n setFocusCell: (ri: number, ci: number) => void;\n handleRowDrop: (from: number, to: number) => void;\n doRender: () => void;\n announce: (msg: string) => void;\n emit: (event: string, ...args: any[]) => void;\n visRange: () => [number, number];\n handleCellKeyEvt: (eventName: 'cellKeyDown' | 'cellKeyUp' | 'cellKeyPress', e: KeyboardEvent) => void;\n}\n\nexport class KeyboardManager<T extends Record<string, any> = any> {\n private _d: KeyboardDeps<T>;\n\n constructor(deps: KeyboardDeps<T>) {\n this._d = deps;\n }\n\n handleKeyDown(e: KeyboardEvent): void {\n const editMgr = this._d.getEditMgr();\n if (editMgr.activeEditor) return;\n\n this._d.handleCellKeyEvt('cellKeyDown', e);\n\n const data = this._d.getData();\n const colLayout = this._d.getColLayout();\n const totalRows = data.rowCount;\n const totalCols = colLayout.visibleLeaves.length;\n if (totalRows === 0 || totalCols === 0) return;\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'c') {\n e.preventDefault();\n this._copyToClipboard();\n return;\n }\n if ((e.ctrlKey || e.metaKey) && e.key === 'v') {\n e.preventDefault();\n this._pasteFromClipboard();\n return;\n }\n\n const opts = this._d.getOptions();\n if ((e.ctrlKey || e.metaKey) && opts.draggable && editMgr.focusCell) {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n const ri = editMgr.focusCell.ci !== undefined ? editMgr.focusCell.ri : 0;\n if (ri < totalRows - 1) {\n this._d.handleRowDrop(ri, ri + 1);\n this._d.setFocusCell(ri + 1, editMgr.focusCell.ci);\n this._d.announce(`행 ${ri + 1}을(를) ${ri + 2}번째 위치로 이동`);\n }\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n const ri = editMgr.focusCell.ri;\n if (ri > 0) {\n this._d.handleRowDrop(ri, ri - 1);\n this._d.setFocusCell(ri - 1, editMgr.focusCell.ci);\n this._d.announce(`행 ${ri + 1}을(를) ${ri}번째 위치로 이동`);\n }\n return;\n }\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n const nextRi = cur ? Math.min(cur.ri + 1, totalRows - 1) : 0;\n this._d.setFocusCell(nextRi, cur?.ci ?? 0);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n const nextRi = cur ? Math.max(cur.ri - 1, 0) : 0;\n this._d.setFocusCell(nextRi, cur?.ci ?? 0);\n break;\n }\n case 'ArrowRight': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n if (!cur) { this._d.setFocusCell(0, 0); break; }\n if (cur.ci < totalCols - 1) {\n this._d.setFocusCell(cur.ri, cur.ci + 1);\n } else if (cur.ri < totalRows - 1) {\n this._d.setFocusCell(cur.ri + 1, 0);\n }\n break;\n }\n case 'ArrowLeft': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n if (!cur) { this._d.setFocusCell(0, 0); break; }\n if (cur.ci > 0) {\n this._d.setFocusCell(cur.ri, cur.ci - 1);\n } else if (cur.ri > 0) {\n this._d.setFocusCell(cur.ri - 1, totalCols - 1);\n }\n break;\n }\n case 'Tab': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n if (!cur) { this._d.setFocusCell(0, 0); break; }\n if (!e.shiftKey) {\n if (cur.ci < totalCols - 1) this._d.setFocusCell(cur.ri, cur.ci + 1);\n else if (cur.ri < totalRows - 1) this._d.setFocusCell(cur.ri + 1, 0);\n } else {\n if (cur.ci > 0) this._d.setFocusCell(cur.ri, cur.ci - 1);\n else if (cur.ri > 0) this._d.setFocusCell(cur.ri - 1, totalCols - 1);\n }\n break;\n }\n case 'Home': {\n e.preventDefault();\n if (e.ctrlKey || e.metaKey) {\n this._d.setFocusCell(0, 0);\n } else {\n const cur = editMgr.focusCell;\n this._d.setFocusCell(cur?.ri ?? 0, 0);\n }\n break;\n }\n case 'End': {\n e.preventDefault();\n if (e.ctrlKey || e.metaKey) {\n this._d.setFocusCell(totalRows - 1, totalCols - 1);\n } else {\n const cur = editMgr.focusCell;\n this._d.setFocusCell(cur?.ri ?? 0, totalCols - 1);\n }\n break;\n }\n case 'PageDown': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n const step = this._d.getOptions().pageSize ?? 10;\n const nextRi = cur ? Math.min(cur.ri + step, totalRows - 1) : Math.min(step - 1, totalRows - 1);\n this._d.setFocusCell(nextRi, cur?.ci ?? 0);\n break;\n }\n case 'PageUp': {\n e.preventDefault();\n const cur = editMgr.focusCell;\n const step = this._d.getOptions().pageSize ?? 10;\n const nextRi = cur ? Math.max(cur.ri - step, 0) : 0;\n this._d.setFocusCell(nextRi, cur?.ci ?? 0);\n break;\n }\n case ' ': {\n if (editMgr.focusCell) {\n e.preventDefault();\n const ri = editMgr.focusCell.ri;\n const rowMgr = this._d.getRowMgr();\n if (this._d.getOptions().checkColumn) {\n rowMgr.check(ri, !rowMgr.checkedRows.has(ri));\n this._d.doRender();\n } else {\n rowMgr.selectToggle(ri);\n this._d.doRender();\n }\n }\n break;\n }\n case 'F2':\n case 'Enter': {\n if (editMgr.focusCell && this._d.getOptions().editable) {\n e.preventDefault();\n editMgr.startEditByKey(editMgr.focusCell.ri, editMgr.focusCell.ci);\n }\n break;\n }\n case 'Escape': {\n editMgr.clearFocusCell();\n this._d.doRender();\n break;\n }\n }\n }\n\n private _copyToClipboard(): void {\n const opts = this._d.getOptions();\n if (!opts.clipboard) return;\n\n const editMgr = this._d.getEditMgr();\n const colLayout = this._d.getColLayout();\n const data = this._d.getData();\n\n let text = '';\n if (editMgr.focusCell) {\n const { ri, ci } = editMgr.focusCell;\n const col = colLayout.visibleLeaves[ci];\n if (col) text = String(data.getCellValue(ri, col.field) ?? '');\n } else if (this._d.getRowMgr().selectedRows.size > 0) {\n const cols = colLayout.visibleLeaves;\n const rowTexts = [...this._d.getRowMgr().selectedRows].sort((a, b) => a - b).map(ri => {\n const row = data.getRowByIndex(ri);\n return cols.map(c => String(row?.[c.field] ?? '')).join('\\t');\n });\n text = rowTexts.join('\\n');\n }\n\n if (text) navigator.clipboard?.writeText(text).catch(() => {});\n }\n\n private _pasteFromClipboard(): void {\n const opts = this._d.getOptions();\n if (!opts.clipboard || !opts.editable) return;\n\n const editMgr = this._d.getEditMgr();\n if (!editMgr.focusCell) return;\n\n navigator.clipboard?.readText().then(text => {\n if (!text) return;\n const { ri, ci } = editMgr.focusCell!;\n const lines = text.split('\\n');\n const cols = this._d.getColLayout().visibleLeaves;\n const data = this._d.getData();\n\n for (let dr = 0; dr < lines.length; dr++) {\n const cells = lines[dr]!.split('\\t');\n for (let dc = 0; dc < cells.length; dc++) {\n const targetRi = ri + dr;\n const targetCi = ci + dc;\n const col = cols[targetCi];\n if (col && targetRi < data.rowCount) {\n data.updateCell(targetRi, col.field, cells[dc]);\n }\n }\n }\n this._d.emit('dataChange', data.getData());\n this._d.doRender();\n }).catch(() => {});\n }\n}\n","import type { ColumnLayout } from './ColumnLayout.js';\nimport type { DataLayer } from './DataLayer.js';\nimport type { Pagination } from './Pagination.js';\nimport type { VirtualScroll } from './VirtualScroll.js';\n\nexport interface FindBarDeps<T extends Record<string, any>> {\n getColLayout: () => ColumnLayout<T>;\n getData: () => DataLayer<T>;\n getFilters: () => Record<string, any[]>;\n getVs: () => VirtualScroll | null;\n getPagination: () => Pagination | null;\n doRender: () => void;\n}\n\nexport class FindBarManager<T extends Record<string, any> = any> {\n private _bar: HTMLElement | null = null;\n private _input: HTMLInputElement | null = null;\n private _count: HTMLElement | null = null;\n private _filter: string = '';\n private _d: FindBarDeps<T>;\n\n constructor(deps: FindBarDeps<T>) {\n this._d = deps;\n }\n\n get findFilter(): string { return this._filter; }\n\n init(container: HTMLElement): void {\n const bar = document.createElement('div');\n bar.className = 'og-find-bar';\n bar.hidden = true;\n\n const lbl = document.createElement('span');\n lbl.className = 'og-find-label';\n lbl.textContent = '찾기';\n\n const input = document.createElement('input');\n input.type = 'text';\n input.className = 'og-find-input';\n input.placeholder = '검색어 입력...';\n input.setAttribute('aria-label', '그리드 내 검색');\n\n const count = document.createElement('span');\n count.className = 'og-find-count';\n\n const closeBtn = document.createElement('button');\n closeBtn.className = 'og-find-close';\n closeBtn.textContent = '✕';\n closeBtn.setAttribute('aria-label', '찾기 닫기');\n\n bar.appendChild(lbl);\n bar.appendChild(input);\n bar.appendChild(count);\n bar.appendChild(closeBtn);\n\n container.insertBefore(bar, container.firstChild);\n\n input.addEventListener('input', () => {\n this._filter = input.value.trim();\n this._apply();\n });\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') this.close();\n });\n closeBtn.addEventListener('click', () => this.close());\n\n this._bar = bar;\n this._input = input;\n this._count = count;\n }\n\n open(): void {\n if (!this._bar) return;\n this._bar.hidden = false;\n this._input!.focus();\n this._input!.select();\n }\n\n close(): void {\n if (!this._bar) return;\n this._bar.hidden = true;\n this._filter = '';\n this._input!.value = '';\n if (this._count) this._count.textContent = '';\n this._apply();\n }\n\n private _apply(): void {\n const data = this._d.getData();\n const fields = this._d.getColLayout().visibleLeaves.map(c => c.field);\n data.setFindFilter(this._filter, fields);\n data.applyFilter(this._d.getFilters());\n const n = data.rowCount;\n this._d.getVs()?.setTotalRows(n);\n this._d.getPagination()?.setTotalRows(n);\n if (this._count) this._count.textContent = this._filter ? `${n}건` : '';\n this._d.doRender();\n }\n}\n","import type { SummaryOp } from './types.js';\nimport { OGDecimal } from './OGDecimal.js';\n\nexport interface GroupRow<T = any> {\n _isGroup: true;\n _groupField: string;\n _groupValue: any;\n _groupLabel: string;\n _depth: number;\n _expanded: boolean;\n _childCount: number;\n _summary: Record<string, any>; // { field → 계산값(number) }\n _summaryFmt: Record<string, string>; // { field → 포맷된 문자열 }\n _states: { added: number; edited: number; removed: number };\n children: Array<GroupRow<T> | T>;\n}\n\nexport type GroupItem<T> = GroupRow<T> | T;\n\nexport interface SummaryDef {\n field: string;\n op: SummaryOp;\n label?: string;\n format?: string; // '#,##0' | '#,##0.00' | '0.00' | '2' 등\n}\n\nfunction _isGroup<T>(item: any): item is GroupRow<T> {\n return item && item._isGroup === true;\n}\n\n/**\n * flat 데이터를 fields 기준으로 계층 그룹핑.\n * Phase 2 슬롯 #5: groupKeyFn(getKey) — 미지정 시 default = `row[field]`(현행 단일 필드 키).\n * GroupTreeManager 가 host.getStrategy 로 주입. ⚠️ 핫패스(행당) — 슬롯 예외 비격리.\n */\nexport function buildGroups<T extends Record<string, any>>(\n data: T[],\n fields: string[],\n summaryDefs: SummaryDef[] = [],\n expandedKeys: Set<string> = new Set(),\n getRowState?: (row: T) => string,\n getKey?: (row: T, remainingFields: string[]) => any\n): GroupRow<T>[] {\n if (!fields.length) return [];\n return _groupByFields(data, fields, 0, summaryDefs, expandedKeys, '', getRowState, getKey);\n}\n\nfunction _groupByFields<T extends Record<string, any>>(\n data: T[],\n fields: string[],\n depth: number,\n summaryDefs: SummaryDef[],\n expandedKeys: Set<string>,\n parentKey: string,\n getRowState?: (row: T) => string,\n getKey?: (row: T, remainingFields: string[]) => any\n): GroupRow<T>[] {\n const field = fields[depth]!;\n const map = new Map<any, T[]>();\n\n for (const row of data) {\n const key = getKey ? getKey(row, fields.slice(depth)) : row[field];\n if (!map.has(key)) map.set(key, []);\n map.get(key)!.push(row);\n }\n\n const result: GroupRow<T>[] = [];\n for (const [value, rows] of map) {\n const groupKey = `${parentKey}__${field}:${value}`;\n const expanded = expandedKeys.has(groupKey);\n\n let children: Array<GroupRow<T> | T>;\n if (depth < fields.length - 1) {\n children = _groupByFields(rows, fields, depth + 1, summaryDefs, expandedKeys, groupKey, getRowState, getKey);\n } else {\n children = rows;\n }\n\n const { summary, summaryFmt } = _calcSummary(rows, summaryDefs);\n const states = _calcStates(rows, getRowState);\n\n result.push({\n _isGroup: true,\n _groupField: field,\n _groupValue: value,\n _groupLabel: value == null ? '(없음)' : String(value),\n _depth: depth,\n _expanded: expanded,\n _childCount: rows.length,\n _summary: summary,\n _summaryFmt: summaryFmt,\n _states: states,\n children,\n } as GroupRow<T>);\n }\n return result;\n}\n\n/** OGDecimal 정밀 계산으로 summary 집계 */\nfunction _calcSummary(\n data: Record<string, any>[],\n defs: SummaryDef[]\n): { summary: Record<string, any>; summaryFmt: Record<string, string> } {\n const summary: Record<string, any> = {};\n const summaryFmt: Record<string, string> = {};\n\n for (const def of defs) {\n const vals = data\n .map(r => r[def.field])\n .filter(v => v !== null && v !== undefined && v !== '');\n\n let result: OGDecimal | null = null;\n const opUC = (def.op as string).toUpperCase();\n\n if (opUC === 'SUM') {\n result = vals.length > 0 ? OGDecimal.sum(vals.map(String)) : null;\n } else if (opUC === 'AVG') {\n result = vals.length > 0\n ? OGDecimal.sum(vals.map(String)).div(OGDecimal.from(String(vals.length)))\n : null;\n } else if (opUC === 'COUNT') {\n summary[def.field] = data.length;\n summaryFmt[def.field] = data.length.toLocaleString('ko-KR');\n continue;\n } else if (opUC === 'MAX') {\n result = vals.length > 0 ? OGDecimal.max(vals.map(String)) : null;\n } else if (opUC === 'MIN') {\n result = vals.length > 0 ? OGDecimal.min(vals.map(String)) : null;\n }\n\n if (!result) { summary[def.field] = null; summaryFmt[def.field] = ''; continue; }\n\n const numVal = result.toNumber();\n summary[def.field] = numVal;\n summaryFmt[def.field] = _fmtNum(numVal, def.format);\n }\n\n return { summary, summaryFmt };\n}\n\n/** 그룹 내 행 편집 상태 집계 */\nfunction _calcStates<T extends Record<string, any>>(\n rows: T[],\n getRowState?: (row: T) => string\n): { added: number; edited: number; removed: number } {\n if (!getRowState) return { added: 0, edited: 0, removed: 0 };\n let added = 0, edited = 0, removed = 0;\n for (const r of rows) {\n const s = getRowState(r);\n if (s === 'added') added++;\n else if (s === 'edited') edited++;\n else if (s === 'removed') removed++;\n }\n return { added, edited, removed };\n}\n\n/**\n * 숫자 포맷팅 (GroupEngine 내부 + 외부 공용)\n * '#,##0' → 천단위 콤마, 정수\n * '#,##0.00' → 천단위 콤마, 소수 2자리\n * '0.00' → 소수 2자리 (콤마 없음)\n * '2' → 소수 2자리 (하위 호환)\n */\nexport function _fmtNum(value: number, fmt?: string): string {\n if (fmt === undefined || fmt === null) {\n return value % 1 === 0\n ? value.toLocaleString('ko-KR')\n : parseFloat(value.toFixed(6)).toLocaleString('ko-KR', {\n minimumFractionDigits: 2, maximumFractionDigits: 6,\n });\n }\n const useComma = fmt.includes('#') || fmt.includes(',');\n const dpMatch = fmt.match(/\\.(\\d+)$/);\n const dp = dpMatch ? parseInt(dpMatch[1]!, 10) : /^\\d+$/.test(fmt) ? parseInt(fmt, 10) : 0;\n\n const fixed = Math.abs(value).toFixed(dp);\n const [intPart = '0', decPart] = fixed.split('.');\n const intStr = useComma\n ? intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n : intPart;\n const result = decPart !== undefined ? `${intStr}.${decPart}` : intStr;\n return value < 0 ? `-${result}` : result;\n}\n\n/**\n * 그룹 트리를 화면에 표시할 flat 행 배열로 변환.\n * 접힌 그룹(expanded=false)의 자식은 포함하지 않음.\n */\nexport function flattenGroups<T>(groups: GroupRow<T>[]): Array<GroupRow<T> | T> {\n const result: Array<GroupRow<T> | T> = [];\n for (const g of groups) {\n result.push(g);\n if (g._expanded) {\n for (const child of g.children) {\n if (_isGroup(child)) {\n result.push(...flattenGroups([child as GroupRow<T>]));\n } else {\n result.push(child);\n }\n }\n }\n }\n return result;\n}\n\n/** 특정 그룹 키의 펼침 상태를 토글 */\nexport function toggleGroup<T>(\n groups: GroupRow<T>[],\n groupKey: string,\n expandedKeys: Set<string>\n): void {\n if (expandedKeys.has(groupKey)) {\n expandedKeys.delete(groupKey);\n } else {\n expandedKeys.add(groupKey);\n }\n}\n\n/** 모든 그룹 키 수집 */\nexport function collectAllKeys<T>(groups: GroupRow<T>[], parentKey = ''): string[] {\n const keys: string[] = [];\n for (const g of groups) {\n const key = `${parentKey}__${g._groupField}:${g._groupValue}`;\n keys.push(key);\n const nested = g.children.filter((c): c is GroupRow<T> => _isGroup(c));\n if (nested.length) keys.push(...collectAllKeys(nested, key));\n }\n return keys;\n}\n\nexport { _isGroup };\n","export interface TreeNode<T = any> {\n _isTree: true;\n _treeId: any;\n _treeParentId: any;\n _depth: number;\n _expanded: boolean;\n _hasChildren: boolean;\n _childCount: number;\n // 탐색기 스타일 트리 라인 렌더링용 메타\n _isLastChild: boolean; // true → └─ / false → ├─\n _ancestorHasMore: boolean[]; // [d] = true → 깊이 d 조상에 형제가 더 있어 │ 라인 표시\n data: T;\n children: TreeNode<T>[];\n}\n\nexport type TreeItem<T> = TreeNode<T>;\n\nexport function isTreeNode<T>(item: any): item is TreeNode<T> {\n return item != null && item._isTree === true;\n}\n\nexport interface TreeBuildOptions {\n idField: string;\n parentIdField: string;\n expandOnLoad?: boolean;\n}\n\n/**\n * flat 데이터를 트리 구조로 변환.\n * parentId가 null/undefined/''인 행이 루트 노드.\n */\nexport function buildTree<T extends Record<string, any>>(\n data: T[],\n opts: TreeBuildOptions,\n expandedKeys: Set<any> = new Set()\n): TreeNode<T>[] {\n const { idField, parentIdField, expandOnLoad = false } = opts;\n\n const nodeMap = new Map<any, TreeNode<T>>();\n const roots: TreeNode<T>[] = [];\n\n // 1단계: 모든 노드 생성\n for (const row of data) {\n const id = row[idField];\n const node: TreeNode<T> = {\n _isTree: true,\n _treeId: id,\n _treeParentId: row[parentIdField],\n _depth: 0,\n _expanded: expandOnLoad || expandedKeys.has(id),\n _hasChildren: false,\n _childCount: 0,\n _isLastChild: false,\n _ancestorHasMore: [],\n data: row,\n children: [],\n };\n nodeMap.set(id, node);\n }\n\n // 2단계: 부모-자식 연결\n for (const node of nodeMap.values()) {\n const pid = node._treeParentId;\n const isRoot = pid == null || pid === '' || !nodeMap.has(pid);\n if (isRoot) {\n roots.push(node);\n } else {\n const parent = nodeMap.get(pid)!;\n parent.children.push(node);\n parent._hasChildren = true;\n }\n }\n\n // 3단계: 깊이 설정 + childCount\n function assignDepth(nodes: TreeNode<T>[], depth: number): void {\n for (const n of nodes) {\n n._depth = depth;\n n._childCount = _countDescendants(n);\n assignDepth(n.children, depth + 1);\n }\n }\n assignDepth(roots, 0);\n\n // 4단계: 탐색기 라인 메타 (_isLastChild, _ancestorHasMore)\n // parentHasMoreChain[d] = true → 깊이 d 위치에서 아직 형제가 남아있음 → │ 라인\n function assignLineMeta(nodes: TreeNode<T>[], parentHasMoreChain: boolean[]): void {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!;\n const isLast = i === nodes.length - 1;\n node._isLastChild = isLast;\n node._ancestorHasMore = parentHasMoreChain;\n if (node.children.length > 0) {\n // 자식에게 전달: 이 노드가 마지막이 아니면 자식들 가이드에 │ 표시\n assignLineMeta(node.children, [...parentHasMoreChain, !isLast]);\n }\n }\n }\n assignLineMeta(roots, []);\n\n return roots;\n}\n\nfunction _countDescendants<T>(node: TreeNode<T>): number {\n let count = node.children.length;\n for (const child of node.children) count += _countDescendants(child);\n return count;\n}\n\n/**\n * 트리를 화면에 표시할 flat 배열로 변환.\n * 접힌 노드(_expanded=false)의 자식은 제외.\n */\nexport function flattenTree<T>(nodes: TreeNode<T>[]): TreeNode<T>[] {\n const result: TreeNode<T>[] = [];\n for (const node of nodes) {\n result.push(node);\n if (node._expanded && node.children.length > 0) {\n result.push(...flattenTree(node.children));\n }\n }\n return result;\n}\n\n/** 특정 id 노드의 펼침 상태 토글 */\nexport function toggleTreeNode<T>(\n expandedKeys: Set<any>,\n nodeId: any\n): void {\n if (expandedKeys.has(nodeId)) {\n expandedKeys.delete(nodeId);\n } else {\n expandedKeys.add(nodeId);\n }\n}\n\n/** 모든 노드 id 수집 */\nexport function collectAllTreeIds<T>(nodes: TreeNode<T>[]): any[] {\n const ids: any[] = [];\n for (const n of nodes) {\n ids.push(n._treeId);\n if (n.children.length) ids.push(...collectAllTreeIds(n.children));\n }\n return ids;\n}\n","import { DataLayer } from './DataLayer.js';\nimport { VirtualScroll } from './VirtualScroll.js';\nimport {\n buildGroups, flattenGroups, collectAllKeys,\n type GroupRow, type SummaryDef,\n} from './GroupEngine.js';\nimport {\n buildTree, flattenTree, toggleTreeNode, collectAllTreeIds,\n type TreeNode,\n} from './TreeEngine.js';\n\nexport interface GroupTreeDeps<T extends Record<string, any>> {\n getData: () => T[];\n getDataLayer: () => DataLayer<T>;\n getOptions: () => any;\n getVs: () => VirtualScroll | null;\n doRenderFull: (totalRows: number) => void;\n doRender: () => void;\n /** Phase 2: OverrideKernel.getStrategy 주입(슬롯 groupKeyFn 도달용). */\n getStrategy?: <F extends Function>(slot: string, fallback: F) => F;\n}\n\nexport class GroupTreeManager<T extends Record<string, any> = any> {\n private _groupFields: string[] = [];\n private _groupExpandedKeys: Set<string> = new Set();\n private _groupFlatRows: Array<GroupRow<T> | T> = [];\n private _isGroupMode = false;\n private _treeRoots: TreeNode<T>[] = [];\n private _treeFlatRows: TreeNode<T>[] = [];\n private _treeExpandedKeys: Set<any> = new Set();\n private _isTreeMode = false;\n private _d: GroupTreeDeps<T>;\n\n constructor(deps: GroupTreeDeps<T>) {\n this._d = deps;\n }\n\n // ─── 상태 접근자 ─────────────────────────────────────────\n get isGroupMode(): boolean { return this._isGroupMode; }\n get isTreeMode(): boolean { return this._isTreeMode; }\n get groupFlatRows(): Array<GroupRow<T> | T> { return this._groupFlatRows; }\n get treeFlatRows(): TreeNode<T>[] { return this._treeFlatRows; }\n\n // ─── 그룹 ─────────────────────────────────────────────────\n groupBy(fields: string[]): void {\n this._groupFields = fields;\n this._groupExpandedKeys.clear();\n this._isGroupMode = fields.length > 0;\n this.rebuildGroups();\n }\n\n clearGroup(): void {\n this._groupFields = [];\n this._groupExpandedKeys.clear();\n this._isGroupMode = false;\n this._groupFlatRows = [];\n const n = this._d.getData().length;\n this._d.getVs()?.setTotalRows(n);\n this._d.doRender();\n }\n\n expandAll(): void {\n if (!this._isGroupMode) return;\n const groups = buildGroups(this._d.getData(), this._groupFields, this._getSummaryDefs(), undefined, undefined, this._groupKeyFn());\n collectAllKeys(groups).forEach(k => this._groupExpandedKeys.add(k));\n this.rebuildGroups();\n }\n\n /** Phase 2 슬롯 #5: groupKeyFn resolver. default = undefined(→ GroupEngine 가 row[field] 사용). */\n private _groupKeyFn(): ((row: T, remainingFields: string[]) => any) | undefined {\n return this._d.getStrategy\n ? this._d.getStrategy('groupKeyFn', undefined as any)\n : undefined;\n }\n\n collapseAll(): void {\n this._groupExpandedKeys.clear();\n if (this._isGroupMode) this.rebuildGroups();\n }\n\n handleGroupToggle(groupKey: string): void {\n if (this._groupExpandedKeys.has(groupKey)) {\n this._groupExpandedKeys.delete(groupKey);\n } else {\n this._groupExpandedKeys.add(groupKey);\n }\n this.rebuildGroups();\n }\n\n rebuildGroups(): void {\n const data = this._d.getData();\n const dl = this._d.getDataLayer();\n const getState = (row: any): string => {\n const idx = data.indexOf(row);\n return idx >= 0 ? dl.getRowState(idx) : 'none';\n };\n const groups = buildGroups(data, this._groupFields, this._getSummaryDefs(), this._groupExpandedKeys, getState, this._groupKeyFn());\n this._groupFlatRows = flattenGroups(groups);\n this._d.getVs()?.setTotalRows(this._groupFlatRows.length);\n this._d.doRenderFull(this._groupFlatRows.length);\n }\n\n // ─── 트리 ─────────────────────────────────────────────────\n enableTree(): void {\n this._isTreeMode = true;\n this._isGroupMode = false;\n const opts = this._d.getOptions();\n if (opts.expandOnLoad) {\n const temp = buildTree(this._d.getData(), {\n idField: opts.treeId,\n parentIdField: opts.treeParentId,\n });\n collectAllTreeIds(temp).forEach(id => this._treeExpandedKeys.add(id));\n }\n this.rebuildTree();\n }\n\n disableTree(): void {\n this._isTreeMode = false;\n this._treeRoots = [];\n this._treeFlatRows = [];\n this._treeExpandedKeys.clear();\n const n = this._d.getData().length;\n this._d.getVs()?.setTotalRows(n);\n this._d.doRender();\n }\n\n expandNodes(ids: any | any[], open = true): void {\n const arr = Array.isArray(ids) ? ids : [ids];\n for (const id of arr) {\n if (open) this._treeExpandedKeys.add(id);\n else this._treeExpandedKeys.delete(id);\n }\n if (this._isTreeMode) this.rebuildTree();\n }\n\n expandAllNodes(): void {\n if (!this._isTreeMode) return;\n collectAllTreeIds(this._treeRoots).forEach(id => this._treeExpandedKeys.add(id));\n this.rebuildTree();\n }\n\n collapseAllNodes(): void {\n if (!this._isTreeMode) return;\n this._treeExpandedKeys.clear();\n this.rebuildTree();\n }\n\n handleTreeToggle(nodeId: any): void {\n toggleTreeNode(this._treeExpandedKeys, nodeId);\n this.rebuildTree();\n }\n\n rebuildTree(): void {\n const opts = this._d.getOptions();\n this._treeRoots = buildTree(this._d.getData(), {\n idField: opts.treeId,\n parentIdField: opts.treeParentId,\n expandOnLoad: opts.expandOnLoad,\n }, this._treeExpandedKeys);\n this._treeFlatRows = flattenTree(this._treeRoots);\n this._d.getVs()?.setTotalRows(this._treeFlatRows.length);\n this._d.doRenderFull(this._treeFlatRows.length);\n }\n\n // ─── 내부 헬퍼 ───────────────────────────────────────────\n private _getSummaryDefs(): SummaryDef[] {\n const s = this._d.getOptions().summary;\n if (!s) return [];\n if (s.rows && s.rows.length > 0) {\n return s.fields.flatMap((f: string) =>\n s.rows!.map((r: any) => ({ field: f, op: r.op, format: r.format }))\n );\n }\n const ops = Array.isArray(s.ops) ? s.ops : (s.ops ? [s.ops] : ['SUM']);\n return s.fields.map((f: string) => ({ field: f, op: ops[0] ?? 'SUM', format: (s as any).format }));\n }\n}\n","import type { DataLayer } from './DataLayer.js';\nimport type { ColumnLayout } from './ColumnLayout.js';\nimport type { VirtualScroll } from './VirtualScroll.js';\nimport type { Pagination } from './Pagination.js';\nimport type { SortItem, FilterItem } from './types.js';\n\nexport interface SortFilterDeps<T extends Record<string, any>> {\n getData: () => DataLayer<T>;\n getColLayout: () => ColumnLayout<T>;\n getFindFilter: () => string;\n getVs: () => VirtualScroll | null;\n getPagination: () => Pagination | null;\n getOptions: () => any;\n renderHeader: () => void;\n doRender: () => void;\n announce: (msg: string) => void;\n emit: (event: string, ...args: any[]) => void;\n}\n\nexport class SortFilterManager<T extends Record<string, any> = any> {\n private _sortList: SortItem[] = [];\n private _filters: Record<string, FilterItem[]> = {};\n private _d: SortFilterDeps<T>;\n\n constructor(deps: SortFilterDeps<T>) {\n this._d = deps;\n }\n\n // ─── 상태 접근자 ─────────────────────────────────────────\n get sortList(): SortItem[] { return this._sortList; }\n get filters(): Record<string, FilterItem[]> { return this._filters; }\n\n // ─── 정렬 ─────────────────────────────────────────────────\n handleSortClick(field: string, shiftKey: boolean): void {\n const opts = this._d.getOptions();\n if (!opts.sortable) return;\n const idx = this._sortList.findIndex(s => s.field === field);\n if (idx >= 0) {\n const cur = this._sortList[idx]!;\n if (cur.dir === 'asc') {\n cur.dir = 'desc';\n } else {\n this._sortList.splice(idx, 1);\n }\n } else {\n if (!shiftKey || !opts.multiSort) this._sortList = [];\n this._sortList.push({ field, dir: 'asc' });\n }\n this._d.getData().applySort(this._sortList);\n this._d.renderHeader();\n this._d.doRender();\n const sortedItem = this._sortList.find(s => s.field === field);\n const dirLabel = sortedItem ? (sortedItem.dir === 'asc' ? '오름차순' : '내림차순') : '정렬 해제';\n this._d.announce(`${field} ${dirLabel} 정렬`);\n this._d.emit('sortChange', { sortList: this._sortList });\n opts.onSortChange?.({ field, dir: sortedItem?.dir ?? 'asc', sortList: this._sortList });\n }\n\n sort(fieldOrList: string | SortItem[], dir: 'asc' | 'desc' = 'asc'): void {\n if (Array.isArray(fieldOrList)) {\n this._sortList = fieldOrList;\n } else {\n const i = this._sortList.findIndex(s => s.field === fieldOrList);\n if (i >= 0) this._sortList[i]!.dir = dir;\n else this._sortList = [{ field: fieldOrList, dir }];\n if (!this._d.getOptions().multiSort) this._sortList = this._sortList.slice(-1);\n }\n this._d.getData().applySort(this._sortList);\n this._d.renderHeader();\n this._d.doRender();\n this._d.emit('sortChange', { sortList: this._sortList });\n }\n\n resetSort(): void {\n this._sortList = [];\n this._d.getData().applySort([]);\n this._d.renderHeader();\n this._d.doRender();\n }\n\n initSort(sortList: SortItem[]): void {\n this._sortList = [...sortList];\n this._d.getData().applySort(this._sortList);\n }\n\n getSortState(): SortItem[] { return [...this._sortList]; }\n\n // ─── 필터 ─────────────────────────────────────────────────\n setFilter(field: string, filterItems: FilterItem[]): void {\n this._filters[field] = filterItems;\n this.applyFilters();\n this._d.renderHeader();\n this._d.doRender();\n this._d.emit('filterChange', { field, filterItems, allFilters: this._filters });\n this._d.getOptions().onFilterChange?.({ field, filterItems, allFilters: this._filters });\n }\n\n resetFilter(field?: string): void {\n if (field) delete this._filters[field];\n else this._filters = {};\n this.applyFilters();\n this._d.renderHeader();\n this._d.doRender();\n }\n\n getFilterState(): Record<string, FilterItem[]> { return { ...this._filters }; }\n\n restoreFilter(state: Record<string, FilterItem[]>): void {\n this._filters = { ...state };\n this.applyFilters();\n }\n\n applyFilters(): void {\n const data = this._d.getData();\n data.setFindFilter(this._d.getFindFilter(), this._d.getColLayout().visibleLeaves.map(c => c.field));\n data.applyFilter(this._filters);\n const n = data.rowCount;\n this._d.getVs()?.setTotalRows(n);\n this._d.getPagination()?.setTotalRows(n);\n }\n}\n","import type { DataLayer } from './DataLayer.js';\nimport type { ColumnLayout } from './ColumnLayout.js';\nimport type { CellEditManager } from './CellEditManager.js';\nimport type { RowManager } from './RowManager.js';\nimport { isToggleCol } from './CellTypeRegistry.js';\nimport { evaluateFormula } from './FormulaEngine.js';\nimport { OGDecimal } from './OGDecimal.js';\n\nexport interface CellEventDeps<T extends Record<string, any>> {\n getData: () => DataLayer<T>;\n getColLayout: () => ColumnLayout<T>;\n getOptions: () => any;\n getEditMgr: () => CellEditManager<T>;\n getRowMgr: () => RowManager<T>;\n emit: (event: string, ...args: any[]) => void;\n writeCell: (ri: number, field: string, value: any) => void;\n doRender: () => void;\n getContainer: () => HTMLElement;\n}\n\nexport class CellEventHandler<T extends Record<string, any> = any> {\n private _d: CellEventDeps<T>;\n\n constructor(deps: CellEventDeps<T>) {\n this._d = deps;\n }\n\n handleCellClick(rowIndex: number, colIndex: number, e: MouseEvent): void {\n const opts = this._d.getOptions();\n const rowMgr = this._d.getRowMgr();\n const editMgr = this._d.getEditMgr();\n\n if (opts.selection === 'single' || opts.selection === 'row') {\n rowMgr.selectSingle(rowIndex);\n } else if (opts.selection === 'multiple') {\n if (e.ctrlKey || e.metaKey) {\n rowMgr.selectToggle(rowIndex);\n } else {\n rowMgr.selectSingle(rowIndex);\n }\n }\n\n const row = this._d.getData().getRowByIndex(rowIndex);\n const col = this._d.getColLayout().visibleLeaves[colIndex];\n\n if (row && col) {\n const colEditable = col.editable !== false && (col.editable !== undefined || opts.editable);\n if (isToggleCol(col) && colEditable) {\n const curVal = (row as any)[col.field];\n this._d.writeCell(rowIndex, col.field as unknown as string, !curVal);\n }\n\n if ((col.type as string) === 'radio') {\n const grp = (col as any).group;\n for (const c of this._d.getColLayout().visibleLeaves) {\n if ((c.type as string) === 'radio' && c.field !== col.field &&\n (!grp || (c as any).group === grp)) {\n this._d.getData().updateCell(rowIndex, c.field, false);\n }\n }\n this._d.writeCell(rowIndex, col.field as any, true);\n }\n\n let cellValue = (row as any)[col.field];\n if (cellValue === undefined && (col as any).formula) {\n try {\n const prec = (col as any).formulaPrecision ?? 30;\n const result = evaluateFormula((col as any).formula, row as any, prec);\n cellValue = result instanceof OGDecimal\n ? ((col as any).precision != null ? result.toFixed((col as any).precision) : result.toString())\n : String(result);\n } catch {}\n }\n const evt = {\n type: 'cellClick', rowIndex, columnIndex: colIndex,\n field: col.field, value: cellValue, row, column: col,\n target: e.target as HTMLElement, originalEvent: e,\n };\n this._d.emit('cellClick', evt);\n opts.onCellClick?.(evt);\n\n const rowEvt = { type: 'rowClick', rowIndex, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowClick', rowEvt);\n opts.onRowClick?.(rowEvt);\n\n const isSelectCol = (col.type as string) === 'select';\n const alreadyEditing = editMgr.activeEditor != null &&\n editMgr.editCell?.ri === rowIndex && editMgr.editCell?.ci === colIndex;\n if (!alreadyEditing && (opts.editMode === 'click' || isSelectCol) && !isToggleCol(col)) {\n editMgr.startEdit(rowIndex, colIndex, e);\n }\n }\n\n if (editMgr.activeEditor && editMgr.editCell?.ri === rowIndex && editMgr.editCell?.ci === colIndex) {\n return;\n }\n\n this._d.doRender();\n this._d.emit('selectionChange', {\n rows: rowMgr.getSelections(),\n rowIndexes: [...rowMgr.selectedRows],\n });\n opts.onSelectionChange?.({ rows: rowMgr.getSelections(), rowIndexes: [...rowMgr.selectedRows], cells: [] });\n }\n\n handleCellDblClick(rowIndex: number, colIndex: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(rowIndex);\n const col = this._d.getColLayout().visibleLeaves[colIndex];\n if (!row || !col) return;\n\n const opts = this._d.getOptions();\n const evt = {\n type: 'cellDblClick', rowIndex, columnIndex: colIndex,\n field: col.field, value: row[col.field], row, column: col,\n target: e.target as HTMLElement, originalEvent: e,\n };\n this._d.emit('cellDblClick', evt);\n opts.onCellDblClick?.(evt);\n\n const rowEvt = { type: 'rowDblClick', rowIndex, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowDblClick', rowEvt);\n opts.onRowDblClick?.(rowEvt);\n\n if (opts.editMode === 'dblclick') this._d.getEditMgr().startEdit(rowIndex, colIndex, e);\n }\n\n handleCellMouseOver(ri: number, ci: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const cellEvt = { type: 'cellMouseOver', rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('cellMouseOver', cellEvt);\n opts.onCellMouseOver?.(cellEvt);\n const rowEvt = { type: 'rowMouseOver', rowIndex: ri, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowMouseOver', rowEvt);\n opts.onRowMouseOver?.(rowEvt);\n }\n\n handleCellMouseOut(ri: number, ci: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const cellEvt = { type: 'cellMouseOut', rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('cellMouseOut', cellEvt);\n opts.onCellMouseOut?.(cellEvt);\n const rowEvt = { type: 'rowMouseOut', rowIndex: ri, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowMouseOut', rowEvt);\n opts.onRowMouseOut?.(rowEvt);\n }\n\n handleCellMouseDown(ri: number, ci: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const cellEvt = { type: 'cellMouseDown', rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('cellMouseDown', cellEvt);\n opts.onCellMouseDown?.(cellEvt);\n const rowEvt = { type: 'rowMouseDown', rowIndex: ri, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowMouseDown', rowEvt);\n opts.onRowMouseDown?.(rowEvt);\n }\n\n handleCellMouseUp(ri: number, ci: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const cellEvt = { type: 'cellMouseUp', rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('cellMouseUp', cellEvt);\n opts.onCellMouseUp?.(cellEvt);\n const rowEvt = { type: 'rowMouseUp', rowIndex: ri, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowMouseUp', rowEvt);\n opts.onRowMouseUp?.(rowEvt);\n }\n\n handleCellMouseMove(ri: number, ci: number, e: MouseEvent): void {\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const cellEvt = { type: 'cellMouseMove', rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('cellMouseMove', cellEvt);\n opts.onCellMouseMove?.(cellEvt);\n const rowEvt = { type: 'rowMouseMove', rowIndex: ri, row, target: e.target as HTMLElement, originalEvent: e };\n this._d.emit('rowMouseMove', rowEvt);\n opts.onRowMouseMove?.(rowEvt);\n }\n\n handleCellKeyEvt(eventName: 'cellKeyDown' | 'cellKeyUp' | 'cellKeyPress', e: KeyboardEvent): void {\n const editMgr = this._d.getEditMgr();\n if (!editMgr.focusCell || editMgr.activeEditor) return;\n const { ri, ci } = editMgr.focusCell;\n const row = this._d.getData().getRowByIndex(ri);\n const col = this._d.getColLayout().visibleLeaves[ci];\n if (!row || !col) return;\n const opts = this._d.getOptions();\n const evt = { type: eventName, rowIndex: ri, columnIndex: ci, field: col.field, value: (row as any)[col.field], row, column: col as any, key: e.key, target: this._d.getContainer(), originalEvent: e };\n this._d.emit(eventName, evt);\n if (eventName === 'cellKeyDown') opts.onCellKeyDown?.(evt as any);\n else if (eventName === 'cellKeyUp') opts.onCellKeyUp?.(evt as any);\n else opts.onCellKeyPress?.(evt as any);\n }\n}\n","import type { TriggerContext, TriggerHandler, TriggerEvent } from './types.js';\n\nexport class TriggerManager {\n private _triggers = new Map<string, TriggerHandler[]>();\n\n add(event: TriggerEvent | string, handler: TriggerHandler): void {\n if (!this._triggers.has(event)) this._triggers.set(event, []);\n this._triggers.get(event)!.push(handler);\n }\n\n remove(event: TriggerEvent | string, handler: TriggerHandler): void {\n const arr = this._triggers.get(event);\n if (arr) {\n const idx = arr.indexOf(handler);\n if (idx >= 0) arr.splice(idx, 1);\n }\n }\n\n clear(event?: TriggerEvent | string): void {\n if (event) this._triggers.delete(event);\n else this._triggers.clear();\n }\n\n mkCtx(operation: string, args: any[]): TriggerContext {\n let _cancelled = false;\n return {\n operation, args, result: undefined, extra: {},\n timestamp: Date.now(),\n get cancelled() { return _cancelled; },\n cancel() { _cancelled = true; },\n };\n }\n\n exec(event: string, ctx: TriggerContext): boolean {\n const handlers = this._triggers.get(event) ?? [];\n for (const fn of handlers) {\n fn(ctx);\n if (ctx.cancelled) return false;\n }\n if (event.startsWith('after:')) {\n const completeHandlers = this._triggers.get('complete') ?? [];\n for (const fn of completeHandlers) fn(ctx);\n }\n return true;\n }\n}\n","// ============================================================\n// 그리드↔그리드 필드 매핑 UI + 스크립트 생성기\n// ------------------------------------------------------------\n// crossGrid 드롭 시 소스/타깃 스키마(필드)가 다를 때, 개발자가\n// \"타깃 필드 ← 소스 필드\"를 매칭하는 모달을 띄운다. 확인하면\n// ① 매핑(Record<타깃, 소스>)을 반환하고\n// ② 그대로 crossGridMapping 에 baking 할 수 있는 변환 스크립트를 출력한다.\n// 디자인타임 헬퍼 — 한 번 매핑을 확정하면 스크립트를 코드에 박아 모달 없이 운영한다.\n// ============================================================\n\nexport interface FieldInfo {\n field: string;\n header: string;\n}\n\nexport interface MappingResult {\n /** 타깃필드 → 소스필드 (빈 문자열이면 미매핑) */\n mapping: Record<string, string>;\n /** crossGridMapping 에 그대로 쓸 수 있는 변환 함수 소스 */\n script: string;\n}\n\nconst NONE = '';\n\n/** mapping → 변환 함수 스크립트 문자열 생성 */\nexport function buildMappingScript(mapping: Record<string, string>): string {\n const lines = Object.entries(mapping)\n .filter(([, src]) => src !== NONE)\n .map(([tgt, src]) => ` ${JSON.stringify(tgt)}: src[${JSON.stringify(src)}],`);\n return (\n '// crossGridMapping 옵션에 이 함수를 그대로 지정하세요.\\n' +\n 'function mapRow(src) {\\n' +\n ' return {\\n' +\n lines.join('\\n') + (lines.length ? '\\n' : '') +\n ' };\\n' +\n '}'\n );\n}\n\n/** mapping → 실제 행 변환 함수 */\nexport function buildTransform(mapping: Record<string, string>): (src: any) => any {\n return (src: any) => {\n const out: Record<string, any> = {};\n for (const [tgt, sf] of Object.entries(mapping)) {\n if (sf !== NONE) out[tgt] = src[sf];\n }\n return out;\n };\n}\n\n/** 같은 필드 집합인지 (순서 무관) */\nexport function sameSchema(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n const sb = new Set(b);\n return a.every(f => sb.has(f));\n}\n\n/**\n * 매핑 모달을 띄우고 사용자가 확정한 매핑을 Promise 로 반환한다. (취소 시 null)\n * 모달은 document.body 에 오버레이로 붙는다(디자인타임 헬퍼).\n */\nexport function openCrossGridMapper(\n sourceFields: FieldInfo[],\n targetFields: FieldInfo[],\n): Promise<MappingResult | null> {\n return new Promise((resolve) => {\n // ── 기본 매핑: 같은 필드명 자동 매칭 ──\n const srcSet = new Set(sourceFields.map(f => f.field));\n const mapping: Record<string, string> = {};\n for (const tf of targetFields) mapping[tf.field] = srcSet.has(tf.field) ? tf.field : NONE;\n\n // ── 오버레이 ──\n const overlay = document.createElement('div');\n overlay.className = 'og-mapper-overlay';\n overlay.setAttribute('role', 'dialog');\n overlay.setAttribute('aria-modal', 'true');\n overlay.setAttribute('aria-label', '그리드 필드 매핑');\n overlay.style.cssText =\n 'position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,0.45);' +\n 'display:flex;align-items:center;justify-content:center;' +\n 'font-family:var(--og-font-family,-apple-system,sans-serif);';\n\n const box = document.createElement('div');\n box.style.cssText =\n 'background:#fff;border-radius:10px;box-shadow:0 12px 40px rgba(0,0,0,0.3);' +\n 'width:min(620px,92vw);max-height:88vh;overflow:auto;color:#222;';\n overlay.appendChild(box);\n\n // ── 헤더 ──\n const head = document.createElement('div');\n head.style.cssText = 'padding:18px 20px 8px;';\n head.innerHTML =\n '<div style=\"font-size:16px;font-weight:700;\">필드 매핑</div>' +\n '<div style=\"font-size:12.5px;color:#666;margin-top:4px;line-height:1.5;\">' +\n '두 그리드의 필드 구조가 다릅니다. <b>타깃 필드</b>마다 어떤 <b>소스 필드</b>의 값을 가져올지 지정하세요. ' +\n '아래 스크립트를 복사해 <code>crossGridMapping</code> 에 baking 하면 다음부터는 이 창 없이 자동 변환됩니다.</div>';\n box.appendChild(head);\n\n // ── 매핑 테이블 ──\n const table = document.createElement('div');\n table.style.cssText = 'padding:6px 20px;';\n const optionHtml =\n `<option value=\"\">(비움)</option>` +\n sourceFields.map(f =>\n `<option value=\"${esc(f.field)}\">${esc(f.header)} &lt;${esc(f.field)}&gt;</option>`\n ).join('');\n\n for (const tf of targetFields) {\n const row = document.createElement('div');\n row.style.cssText =\n 'display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid #f0f0f0;';\n const label = document.createElement('div');\n label.style.cssText = 'flex:1;font-size:13px;min-width:0;';\n label.innerHTML =\n `<span style=\"font-weight:600;\">${esc(tf.header)}</span>` +\n `<span style=\"color:#999;font-size:11.5px;\"> &lt;${esc(tf.field)}&gt;</span>`;\n const arrow = document.createElement('span');\n arrow.textContent = '←';\n arrow.style.cssText = 'color:#888;flex-shrink:0;';\n const sel = document.createElement('select');\n sel.style.cssText =\n 'flex:1;min-width:0;padding:6px 8px;border:1px solid #ccc;border-radius:6px;font-size:13px;background:#fff;';\n sel.innerHTML = optionHtml;\n sel.value = mapping[tf.field] ?? NONE;\n sel.addEventListener('change', () => { mapping[tf.field] = sel.value; refreshScript(); });\n row.append(label, arrow, sel);\n table.appendChild(row);\n }\n box.appendChild(table);\n\n // ── 스크립트 미리보기 + 복사 ──\n const scriptWrap = document.createElement('div');\n scriptWrap.style.cssText = 'padding:10px 20px 4px;';\n const scriptHead = document.createElement('div');\n scriptHead.style.cssText = 'display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;';\n scriptHead.innerHTML = '<span style=\"font-size:12.5px;font-weight:600;color:#444;\">생성된 변환 스크립트</span>';\n const copyBtn = document.createElement('button');\n copyBtn.type = 'button';\n copyBtn.textContent = '복사';\n copyBtn.style.cssText =\n 'font-size:12px;padding:4px 10px;border:1px solid #ccc;border-radius:6px;background:#f7f7f7;cursor:pointer;';\n scriptHead.appendChild(copyBtn);\n const pre = document.createElement('pre');\n pre.style.cssText =\n 'margin:0;background:#0d1117;color:#c9d1d9;padding:12px;border-radius:8px;' +\n 'font-family:ui-monospace,Consolas,monospace;font-size:12px;line-height:1.5;overflow:auto;max-height:180px;';\n scriptWrap.append(scriptHead, pre);\n box.appendChild(scriptWrap);\n\n function currentScript(): string { return buildMappingScript(mapping); }\n function refreshScript(): void { pre.textContent = currentScript(); }\n refreshScript();\n\n copyBtn.addEventListener('click', () => {\n const txt = currentScript();\n navigator.clipboard?.writeText(txt).then(\n () => { copyBtn.textContent = '복사됨!'; setTimeout(() => (copyBtn.textContent = '복사'), 1200); },\n () => { copyBtn.textContent = '복사 실패'; setTimeout(() => (copyBtn.textContent = '복사'), 1200); },\n );\n });\n\n // ── 푸터 ──\n const foot = document.createElement('div');\n foot.style.cssText = 'display:flex;justify-content:flex-end;gap:8px;padding:14px 20px 18px;';\n const cancelBtn = document.createElement('button');\n cancelBtn.type = 'button';\n cancelBtn.textContent = '취소';\n cancelBtn.style.cssText =\n 'font-size:13px;padding:8px 16px;border:1px solid #ccc;border-radius:7px;background:#fff;cursor:pointer;';\n const okBtn = document.createElement('button');\n okBtn.type = 'button';\n okBtn.textContent = '적용 후 이동';\n okBtn.style.cssText =\n 'font-size:13px;padding:8px 16px;border:0;border-radius:7px;background:#1976d2;color:#fff;cursor:pointer;font-weight:600;';\n foot.append(cancelBtn, okBtn);\n box.appendChild(foot);\n\n // ── 닫기 처리 ──\n let done = false;\n function close(result: MappingResult | null): void {\n if (done) return;\n done = true;\n document.removeEventListener('keydown', onKey);\n overlay.remove();\n resolve(result);\n }\n function onKey(e: KeyboardEvent): void {\n if (e.key === 'Escape') close(null);\n }\n cancelBtn.addEventListener('click', () => close(null));\n overlay.addEventListener('mousedown', (e) => { if (e.target === overlay) close(null); });\n okBtn.addEventListener('click', () => close({ mapping: { ...mapping }, script: currentScript() }));\n document.addEventListener('keydown', onKey);\n\n document.body.appendChild(overlay);\n okBtn.focus();\n });\n}\n\nfunction esc(s: string): string {\n return String(s).replace(/[&<>\"]/g, c =>\n ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;' }[c] as string));\n}\n","// ============================================================\n// 크로스그리드 레지스트리\n// 그리드 바디(.og-body-wrapper) 엘리먼트 → 그리드 인스턴스 매핑.\n// 드래그(좌표→타깃 그리드)와 화살표 셔틀이 공유한다.\n// ============================================================\nimport type { OpenGrid } from './OpenGrid.js'; // 타입 전용 (런타임 순환 없음)\n\nexport class CrossGridRegistry {\n private _map = new Map<HTMLElement, OpenGrid<any>>();\n\n register(bodyEl: HTMLElement, grid: OpenGrid<any>): void { this._map.set(bodyEl, grid); }\n unregister(bodyEl: HTMLElement): void { this._map.delete(bodyEl); }\n get(bodyEl: HTMLElement): OpenGrid<any> | undefined { return this._map.get(bodyEl); }\n get size(): number { return this._map.size; }\n\n /** 커서 좌표 아래의 다른(crossGrid 허용) 그리드 반환. 없으면 null */\n resolveAt(clientX: number, clientY: number, exclude: OpenGrid<any>): OpenGrid<any> | null {\n const el = document.elementFromPoint(clientX, clientY) as HTMLElement | null;\n const body = el?.closest('.og-body-wrapper') as HTMLElement | null;\n if (!body) return null;\n const g = this._map.get(body);\n if (!g || g === exclude) return null;\n return g;\n }\n}\n\n/** 전역 단일 레지스트리 */\nexport const crossGridRegistry = new CrossGridRegistry();\n","/**\n * OverrideKernel — `grid.override()` 확장 커널 (94 최종 종합본 반영)\n *\n * 핵심 원칙(94 §1 F1~F4):\n * - F2: FIFO 합성 = `reduce` 좌측폴드. 먼저 등록 = 안쪽(원본 근접), 나중 등록 = 바깥.\n * `[fn1,fn2,fn3]` → 실행 시 fn3(최후등록)이 최외곽, orig() 호출이 안쪽으로 전파.\n * - F3: 재진입 가드 = 깊이 제한(maxDepth 기본 32) + 호출경로 사이클 감지(_callPath, 동일 name\n * 재출현 시 차단) + 명시적 { reentrant:true } 옵트인. 정당한 cascade는 깊이 내 허용.\n * - F4: 에러 격리 = 기본 strict=true(예외 전파). { onError:'fallback' } 옵트인 시에만\n * 경고 후 orig fallback(멱등 가정, 롤백 불가).\n *\n * 본 커널은 단독 클래스로, OpenGrid 인스턴스를 host 로 받아 프로토타입 메서드를\n * 인스턴스 프로퍼티로 shadowing(순수 런타임 래핑, C1-clean) 한다. 소스 본문 0줄 수정.\n */\n\nexport interface OverrideKernelHost {\n [name: string]: any;\n}\n\n/** override() 호출 시 레이어가 받는 함수 시그니처: 첫 인자는 안쪽(원본 근접) 함수. */\nexport type OverrideLayer = (orig: (...args: any[]) => any, ...args: any[]) => any;\n\nexport interface OverrideOptions {\n /** 동일 name 재진입을 허용(정당한 재귀). 기본 false. */\n reentrant?: boolean;\n /** 'fallback' → 레이어 예외 시 경고 후 orig 실행(멱등 가정). 미지정 시 strict(전파). */\n onError?: 'fallback';\n}\n\ninterface LayerEntry {\n fn: OverrideLayer;\n opts: OverrideOptions;\n}\n\nexport class OverrideKernel {\n private _host: OverrideKernelHost;\n /** name → this-bound 원본 함수 (최초 1회 보존) */\n private _originals = new Map<string, (...args: any[]) => any>();\n /** name → 최초 override 직전 host 가 own 프로퍼티로 메서드를 가졌는지(복구 방식 결정) */\n private _hadOwn = new Map<string, boolean>();\n /** name → 레이어 목록(등록순, FIFO) */\n private _stack = new Map<string, LayerEntry[]>();\n /** slot → strategy 함수 */\n private _strategies = new Map<string, Function>();\n /** F3: 현재 호출 경로(메서드 name 스택) — 사이클 감지용 */\n private _callPath: string[] = [];\n /** F4: 기본 strict (예외 전파) */\n private _strict: boolean;\n /** F3: 재귀 깊이 제한 */\n private _maxDepth: number;\n\n constructor(host: OverrideKernelHost, opts?: { strict?: boolean; maxDepth?: number }) {\n this._host = host;\n this._strict = opts?.strict ?? true;\n this._maxDepth = opts?.maxDepth ?? 32;\n }\n\n /**\n * 메서드 override 등록.\n * 1. 최초 1회 원본을 this-bound 로 보존.\n * 2. 레이어 push (FIFO 등록순).\n * 3. reduce 좌측폴드로 합성(나중 등록 = 최외곽).\n * 4. 재진입 가드 + 에러 격리로 감싼 dispatcher 를 host[name] 인스턴스 프로퍼티에 할당.\n */\n override(name: string, fn: OverrideLayer, opts: OverrideOptions = {}): OverrideKernelHost {\n if (typeof fn !== 'function') {\n throw new TypeError(`OverrideKernel.override: fn for \"${name}\" must be a function`);\n }\n if (!this._originals.has(name)) {\n const orig = this._host[name];\n if (typeof orig !== 'function') {\n throw new TypeError(`OverrideKernel.override: host[\"${name}\"] is not a function`);\n }\n // 복구 방식 결정: own 프로퍼티였으면 원본 값을 되돌리고, 프로토타입 메서드면\n // 인스턴스 shadow 만 delete 하여 프로토타입을 재노출(순수 래핑 가역성).\n this._hadOwn.set(name, Object.prototype.hasOwnProperty.call(this._host, name));\n this._originals.set(name, orig.bind(this._host));\n }\n\n const layers = this._stack.get(name) ?? [];\n layers.push({ fn, opts });\n this._stack.set(name, layers);\n\n this._host[name] = this._buildDispatcher(name);\n return this._host;\n }\n\n /** 합성된 dispatcher 생성. override/restore 시점마다 재구성. */\n private _buildDispatcher(name: string): (...args: any[]) => any {\n const original = this._originals.get(name)!;\n const layers = this._stack.get(name) ?? [];\n\n // F2: reduce 좌측폴드. layers[0]=가장 안쪽(원본 근접), 마지막=최외곽.\n // acc 시작값 = original, 각 layer 는 acc(=innerOrig)를 첫 인자로 받는다.\n const composed = layers.reduce<(...args: any[]) => any>(\n (innerOrig, layer) => (...a: any[]) => layer.fn(innerOrig, ...a),\n original,\n );\n\n // 최외곽 레이어의 옵션이 재진입/에러 정책을 결정.\n const outer = layers[layers.length - 1]?.opts ?? {};\n const reentrant = outer.reentrant === true;\n const fallback = outer.onError === 'fallback';\n\n const self = this;\n return function (this: unknown, ...args: any[]): any {\n // F3: 사이클 감지 — 동일 name 이 이미 호출 경로에 있고 reentrant 옵트인이 아니면 원본으로.\n if (!reentrant && self._callPath.indexOf(name) !== -1) {\n return original(...args);\n }\n // F3: 깊이 제한.\n if (self._callPath.length >= self._maxDepth) {\n if (self._strict && !fallback) {\n throw new Error(\n `OverrideKernel: max override depth (${self._maxDepth}) exceeded at \"${name}\"`,\n );\n }\n return original(...args);\n }\n\n self._callPath.push(name);\n try {\n return composed(...args);\n } catch (e) {\n // F4: 기본 strict 전파. onError:'fallback' 옵트인 시에만 경고 후 orig.\n if (fallback && !self._strict) {\n console.warn(`[og.override:${name}]`, e);\n return original(...args);\n }\n if (fallback && self._strict) {\n // strict 모드라도 명시적 fallback 옵트인은 존중(멱등 가정, 롤백 불가).\n console.warn(`[og.override:${name}]`, e);\n return original(...args);\n }\n throw e;\n } finally {\n self._callPath.pop();\n }\n };\n }\n\n /** strategy 슬롯 등록 (Phase 2 매니저 배선용 API). */\n strategy(slot: string, fn: Function): OverrideKernelHost {\n if (typeof fn !== 'function') {\n throw new TypeError(`OverrideKernel.strategy: fn for \"${slot}\" must be a function`);\n }\n this._strategies.set(slot, fn);\n return this._host;\n }\n\n /** strategy 슬롯 조회 — 미등록 시 fallback 반환 (매니저 read API). */\n getStrategy<F extends Function>(slot: string, fallback: F): F {\n return (this._strategies.get(slot) as F) ?? fallback;\n }\n\n /** 슬롯 등록 여부. */\n hasStrategy(slot: string): boolean {\n return this._strategies.has(slot);\n }\n\n /** 단일 메서드 원본 복구. 없으면 no-op. */\n restore(name: string): OverrideKernelHost {\n if (!this._originals.has(name)) return this._host;\n if (this._hadOwn.get(name)) {\n // 원래 own 프로퍼티였음 → 보존한 원본(this-bound)을 되돌린다.\n this._host[name] = this._originals.get(name)!;\n } else {\n // 프로토타입 메서드였음 → 인스턴스 shadow 삭제로 프로토타입 재노출.\n delete this._host[name];\n }\n this._originals.delete(name);\n this._hadOwn.delete(name);\n this._stack.delete(name);\n return this._host;\n }\n\n /** 전체 복구 + strategy clear. destroy 시 호출. */\n restoreAll(): OverrideKernelHost {\n for (const n of [...this._originals.keys()]) this.restore(n);\n this._strategies.clear();\n this._callPath = [];\n return this._host;\n }\n\n /** override 등록 여부. */\n hasOverride(name: string): boolean {\n return this._originals.has(name);\n }\n\n /** override 등록된 메서드 이름 목록. */\n getOverrideNames(): string[] {\n return [...this._originals.keys()];\n }\n}\n","import { EventEmitter } from './EventEmitter.js';\r\nimport { DataLayer } from './DataLayer.js';\r\nimport { VirtualScroll } from './VirtualScroll.js';\r\nimport { ColumnLayout } from './ColumnLayout.js';\r\nimport { FilterPanel } from './FilterPanel.js';\r\nimport { GridRenderer } from './GridRenderer.js';\r\nimport type { RendererCallbacks } from './GridRenderer.js';\r\nimport { RowManager } from './RowManager.js';\r\nimport { CellEditManager } from './CellEditManager.js';\r\nimport { isToggleCol } from './CellTypeRegistry.js';\r\nimport { FilterSelectPanel } from './FilterSelect.js';\r\nimport type { FilterSelectConfig } from './FilterSelect.js';\r\nimport { Pagination } from './Pagination.js';\r\nimport { RowDragDrop } from './RowDragDrop.js';\r\nimport { MergeEngine, type MergeCell } from './MergeEngine.js';\r\nimport { createRenderer, setDisplayFormatterResolver } from './renderers/CellRenderer.js';\r\nimport { ContextMenuManager, DEFAULT_CONTEXT_ITEMS } from './ContextMenu.js';\r\nimport { WorksheetManager } from './WorksheetManager.js';\r\nimport { ExportManager } from './ExportManager.js';\r\nimport { FooterManager } from './FooterManager.js';\r\nimport { KeyboardManager } from './KeyboardManager.js';\r\nimport { FindBarManager } from './FindBarManager.js';\r\nimport { GroupTreeManager } from './GroupTreeManager.js';\r\nimport { SortFilterManager } from './SortFilterManager.js';\r\nimport { CellEventHandler } from './CellEventHandler.js';\r\nimport { TriggerManager } from './TriggerManager.js';\r\nimport {\r\n openCrossGridMapper, buildTransform, buildMappingScript, sameSchema,\r\n type FieldInfo,\r\n} from './CrossGridMapper.js';\r\nimport { crossGridRegistry } from './CrossGridRegistry.js';\r\nimport { OverrideKernel } from './OverrideKernel.js';\r\nimport type { OverrideLayer } from './OverrideKernel.js';\r\nimport type {\r\n GridOptions, OpenGridInstance, ColumnDef,\r\n SortItem, FilterItem, ExportOptions,\r\n EditEvent, Position, GridDropEvent, GridMappingEvent,\r\n TriggerContext, TriggerHandler, TriggerEvent,\r\n OverrideApi, OverrideCallOptions,\r\n} from './types.js';\r\n\r\nconst ROW_ID_FIELD = '_ogRowId';\r\n\r\nexport class OpenGrid<T extends Record<string, any> = any>\r\n extends EventEmitter\r\n implements OpenGridInstance<T>\r\n{\r\n private _container: HTMLElement;\r\n private _options: Required<GridOptions<T>>;\r\n private _data: DataLayer<T>;\r\n private _colLayout: ColumnLayout<T>;\r\n private _vs: VirtualScroll | null = null;\r\n private _ro: ResizeObserver | null = null;\r\n private _renderer: GridRenderer | null = null;\r\n private _sfMgr!: SortFilterManager<T>;\r\n private _rowMgr!: RowManager<T>;\r\n private _editMgr!: CellEditManager<T>;\r\n private _trigMgr = new TriggerManager();\r\n private _destroyed = false;\r\n private _autoHeightWarned = false;\r\n private _colWidths: number[] = [];\r\n /** 사용자가 헤더 드래그로 직접 조절한 컬럼 폭 (field 기준). _recalcWidths 가 덮어쓰지 않도록 보존 */\r\n private _userWidths = new Map<string, number>();\r\n private _filterPanel: FilterPanel | null = null;\r\n private _filterSelect: FilterSelectPanel | null = null;\r\n private _pagination: Pagination | null = null;\r\n private _dnd: RowDragDrop | null = null;\r\n private _mergeEngine: MergeEngine = new MergeEngine();\r\n private _liveRegion: HTMLElement | null = null;\r\n private _ctxMenu: ContextMenuManager | null = null;\r\n private _cmHandler: ((e: MouseEvent) => void) | null = null;\r\n private _cmKbdHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private _wsManager: WorksheetManager<T> | null = null;\r\n // 분리된 매니저들\r\n private _exportMgr!: ExportManager<T>;\r\n private _footerMgr!: FooterManager<T>;\r\n private _kbdMgr!: KeyboardManager<T>;\r\n private _findMgr!: FindBarManager<T>;\r\n private _grpMgr!: GroupTreeManager<T>;\r\n private _cellEvt!: CellEventHandler<T>;\r\n\r\n // grid.override() 확장 커널 (생성자 말미에 초기화)\r\n private _ovk!: OverrideKernel;\r\n /** 공개 override API (호출가능 + .strategy). 생성자 말미에 부착. */\r\n override!: OverrideApi<T>;\r\n\r\n // ── grid.override() 정적 전역 레지스트리 ──────────────────\r\n /** 정적 전역 override 레이어 (모든 신규 인스턴스에 생성자 말미 적용). */\r\n private static _defaultOverrides: Array<[string, OverrideLayer, OverrideCallOptions]> = [];\r\n /** 정적 전역 strategy 슬롯. */\r\n private static _defaultStrategies: Array<[string, Function]> = [];\r\n\r\n /** 정적: 모든 신규 그리드에 적용될 override 레이어 등록. */\r\n static defaultOverride(name: string, fn: OverrideLayer, opts: OverrideCallOptions = {}): typeof OpenGrid {\r\n OpenGrid._defaultOverrides.push([name, fn, opts]);\r\n return OpenGrid;\r\n }\r\n\r\n /** 정적 전역 defaults 네임스페이스 (strategy 슬롯). */\r\n static defaults = {\r\n strategy(slot: string, fn: Function): typeof OpenGrid {\r\n OpenGrid._defaultStrategies.push([slot, fn]);\r\n return OpenGrid;\r\n },\r\n };\r\n\r\n constructor(container: string | HTMLElement, options: GridOptions<T>) {\r\n super();\r\n const el = typeof container === 'string'\r\n ? (document.querySelector(container) as HTMLElement)\r\n : container;\r\n if (!el) throw new Error(`OpenGrid: container not found: ${container}`);\r\n this._container = el;\r\n\r\n this._options = {\r\n height: '100%', width: '100%',\r\n rowHeight: 32, headerHeight: 34, footerHeight: 30,\r\n autoHeight: false, fillWidth: false, defaultColumnWidth: 100,\r\n editable: false, editMode: 'dblclick', history: true, historySize: 100,\r\n selection: 'single', clipboard: true,\r\n sortable: true, multiSort: true, filterable: true, defaultSort: [],\r\n frozenColumns: 0, frozenRows: 0,\r\n rowNumber: false, stateColumn: false, checkColumn: false, draggable: false, crossGrid: false, crossGridMapping: 'auto',\r\n mergeCells: false, groupBy: [], summary: undefined as any,\r\n treeMode: 'auto', treeId: 'id', treeParentId: 'parentId', expandOnLoad: false,\r\n pagination: false, pageSize: 50,\r\n footer: undefined as any, footerPosition: 'bottom',\r\n theme: 'default', cssVars: {}, ariaLabel: 'OPEN_GRID 데이터 그리드',\r\n ...options\r\n } as Required<GridOptions<T>>;\r\n\r\n this._data = new DataLayer<T>(ROW_ID_FIELD);\r\n this._rowMgr = new RowManager<T>(this._data);\r\n this._colLayout = new ColumnLayout<T>(this._options.columns, this._options.frozenColumns);\r\n this._editMgr = new CellEditManager<T>({\r\n data: this._data,\r\n colLayout: this._colLayout,\r\n getRenderer: () => this._renderer,\r\n getContainer: () => this._container,\r\n getOptions: () => this._options,\r\n emit: (ev, ...args) => this.emit(ev, ...args),\r\n doRender: () => this._doRender(...this._visRange()),\r\n announce: (msg) => this._announce(msg),\r\n writeCell: (ri, field, value) => this.writeCell(ri, field, value),\r\n scrollToRow: (ri) => this._vs?.scrollToRow(ri),\r\n getVisibleLeaves: () => this._colLayout.visibleLeaves,\r\n });\r\n\r\n this._exportMgr = new ExportManager<T>({\r\n getData: () => this._data.getData(),\r\n getColLayout: () => this._colLayout,\r\n getColWidths: () => this._colWidths,\r\n getOptions: () => this._options,\r\n getContainer: () => this._container,\r\n getMaskEnabled: (field) => this.getMaskEnabled(field),\r\n getWsManager: () => this._wsManager,\r\n getStrategy: (slot, fb) => this._ovk.getStrategy(slot, fb),\r\n });\r\n this._footerMgr = new FooterManager<T>({\r\n getData: () => this._data.getData(),\r\n getColLayout: () => this._colLayout,\r\n getColWidths: () => this._colWidths,\r\n getOptions: () => this._options,\r\n getContainer: () => this._container,\r\n getStrategy: (slot, fb) => this._ovk.getStrategy(slot, fb),\r\n });\r\n this._kbdMgr = new KeyboardManager<T>({\r\n getEditMgr: () => this._editMgr,\r\n getRowMgr: () => this._rowMgr,\r\n getData: () => this._data,\r\n getColLayout: () => this._colLayout,\r\n getOptions: () => this._options,\r\n setFocusCell: (ri, ci) => this._setFocusCell(ri, ci),\r\n handleRowDrop: (from, to) => this._handleRowDrop(from, to),\r\n doRender: () => this._doRender(...this._visRange()),\r\n announce: (msg) => this._announce(msg),\r\n emit: (ev, ...args) => this.emit(ev, ...args),\r\n visRange: () => this._visRange(),\r\n handleCellKeyEvt: (name, e) => this._handleCellKeyEvt(name, e),\r\n });\r\n this._sfMgr = new SortFilterManager<T>({\r\n getData: () => this._data,\r\n getColLayout: () => this._colLayout,\r\n getFindFilter: () => this._findMgr.findFilter,\r\n getVs: () => this._vs,\r\n getPagination: () => this._pagination,\r\n getOptions: () => this._options,\r\n renderHeader: () => this._renderHeader(),\r\n doRender: () => this._doRender(...this._visRange()),\r\n announce: (msg) => this._announce(msg),\r\n emit: (ev, ...args) => this.emit(ev, ...args),\r\n });\r\n this._findMgr = new FindBarManager<T>({\r\n getColLayout: () => this._colLayout,\r\n getData: () => this._data,\r\n getFilters: () => this._sfMgr.filters,\r\n getVs: () => this._vs,\r\n getPagination: () => this._pagination,\r\n doRender: () => this._doRender(...this._visRange()),\r\n });\r\n this._cellEvt = new CellEventHandler<T>({\r\n getData: () => this._data,\r\n getColLayout: () => this._colLayout,\r\n getOptions: () => this._options,\r\n getEditMgr: () => this._editMgr,\r\n getRowMgr: () => this._rowMgr,\r\n emit: (ev, ...args) => this.emit(ev, ...args),\r\n writeCell: (ri, field, val) => this.writeCell(ri, field, val),\r\n doRender: () => this._doRender(...this._visRange()),\r\n getContainer: () => this._container,\r\n });\r\n this._grpMgr = new GroupTreeManager<T>({\r\n getData: () => this._data.getData(),\r\n getDataLayer: () => this._data,\r\n getOptions: () => this._options,\r\n getVs: () => this._vs,\r\n doRenderFull: (n) => this._doRender(0, n - 1),\r\n doRender: () => this._doRender(...this._visRange()),\r\n getStrategy: (slot, fb) => this._ovk.getStrategy(slot, fb),\r\n });\r\n\r\n this._mount();\r\n this._bindOptionEvents();\r\n\r\n if (this._options.defaultSort?.length) {\r\n this._sfMgr.initSort(this._options.defaultSort);\r\n }\r\n\r\n // ── grid.override() 확장 커널 부착 (생성자 말미 — 매니저 조립·mount 이후) ──\r\n this._ovk = new OverrideKernel(this, { strict: this._options.overrideStrict ?? true });\r\n // Phase 2: DataLayer(슬롯 sortComparator/filterPredicate) + 렌더러(displayFormatter) strategy 배선.\r\n this._data.setStrategyResolver((slot, fb) => this._ovk.getStrategy(slot, fb));\r\n setDisplayFormatterResolver((v, f, row) =>\r\n this._ovk.getStrategy('displayFormatter', null as any)?.(v, f, row) ?? null,\r\n );\r\n this.override = Object.assign(\r\n (name: string, fn: OverrideLayer, opts?: OverrideCallOptions) => this._ovk.override(name, fn, opts) as any,\r\n { strategy: (slot: string, fn: Function) => this._ovk.strategy(slot, fn) as any },\r\n ) as OverrideApi<T>;\r\n\r\n // destroy 순수 래핑(94 §2.2 채택안2): 원본 본문 0줄 수정, 최외곽에서 restoreAll 보장.\r\n const _origDestroy = this.destroy.bind(this);\r\n this.destroy = () => { try { _origDestroy(); } finally { this._ovk.restoreAll(); } };\r\n\r\n // 정적 전역 defaults 1회 적용(첫 렌더 후, 깜빡임 방지).\r\n for (const [slot, fn] of OpenGrid._defaultStrategies) this._ovk.strategy(slot, fn);\r\n for (const [name, fn, opts] of OpenGrid._defaultOverrides) this._ovk.override(name, fn, opts);\r\n\r\n requestAnimationFrame(() => {\r\n this.emit('ready', this);\r\n this._options.onReady?.(this);\r\n });\r\n }\r\n\r\n // ── grid.override() 위임 메서드 ──────────────────────────\r\n restore(name: string): this { this._ovk.restore(name); return this; }\r\n restoreAll(): this { this._ovk.restoreAll(); return this; }\r\n hasOverride(name: string): boolean { return this._ovk.hasOverride(name); }\r\n getOverrideNames(): string[] { return this._ovk.getOverrideNames(); }\r\n getStrategy<F extends Function>(slot: string, fallback: F): F { return this._ovk.getStrategy(slot, fallback); }\r\n private _mount(): void {\r\n this._container.classList.add('og-container');\r\n const h = this._options.height;\r\n const w = this._options.width;\r\n this._container.style.height = typeof h === 'number' ? `${h}px` : String(h);\r\n this._container.style.width = typeof w === 'number' ? `${w}px` : String(w);\r\n this._container.style.display = 'flex';\r\n this._container.style.flexDirection = 'column';\r\n this._container.style.overflow = 'hidden';\r\n this._container.style.boxSizing = 'border-box';\r\n this._container.style.border = '1px solid var(--og-border-color, #e0e0e0)';\r\n this._container.style.fontFamily = 'var(--og-font-family, -apple-system, sans-serif)';\r\n this._container.style.fontSize = 'var(--og-font-size, 13px)';\r\n this._container.setAttribute('data-og-theme', this._options.theme);\r\n\r\n for (const [k, v] of Object.entries(this._options.cssVars))\r\n this._container.style.setProperty(k, v);\r\n\r\n this._renderer = new GridRenderer(this._container, this._options, {\r\n onHeaderClick: (field, shiftKey) => this._handleSortClick(field, shiftKey),\r\n onCellClick: (ri, ci, e) => this._handleCellClick(ri, ci, e),\r\n onCellDblClick: (ri, ci, e) => this._handleCellDblClick(ri, ci, e),\r\n onCellMouseOver: (ri, ci, e) => this._handleCellMouseOver(ri, ci, e),\r\n onCellMouseOut: (ri, ci, e) => this._handleCellMouseOut(ri, ci, e),\r\n onCellMouseDown: (ri, ci, e) => this._handleCellMouseDown(ri, ci, e),\r\n onCellMouseUp: (ri, ci, e) => this._handleCellMouseUp(ri, ci, e),\r\n onCellMouseMove: (ri, ci, e) => this._handleCellMouseMove(ri, ci, e),\r\n onRowCheck: (ri, checked) => this._handleRowCheck(ri, checked),\r\n onAllCheck: (checked) => this._handleAllCheck(checked),\r\n onColResize: (ci, w) => this._handleColResize(ci, w),\r\n onFilterIconClick: (field, anchorEl) => this._handleFilterIconClick(field, anchorEl),\r\n getDndManager: () => this._dnd,\r\n onColDragStart: (ci) => { this._editMgr.dragColIdx = ci; },\r\n onColDrop: (toIdx) => {\r\n if (this._editMgr.dragColIdx !== null && this._editMgr.dragColIdx !== toIdx) {\r\n this._reorderColumn(this._editMgr.dragColIdx, toIdx);\r\n }\r\n this._editMgr.dragColIdx = null;\r\n },\r\n getColDragIdx: () => this._editMgr.dragColIdx,\r\n });\r\n\r\n this._filterPanel = new FilterPanel(\r\n this._container,\r\n (field, items) => this.setFilter(field, items),\r\n (field) => this.resetFilter(field)\r\n );\r\n // 웹 접근성 속성 설정 (role, aria 레이블, 행/열 수 알림)\r\n // ?묎렐?? role, aria-label, aria-rowcount, aria-colcount\r\n this._container.setAttribute('role', 'grid');\r\n this._container.setAttribute('aria-label', this._options.ariaLabel ?? this._options.cssVars?.['aria-label'] ?? 'OPEN_GRID 데이터 그리드');\r\n this._container.setAttribute('aria-rowcount', '0');\r\n this._container.setAttribute('aria-colcount', String(this._options.columns.filter(c => !c.hidden).length));\r\n // aria-live 영역: 스크린리더에게 상태 변화를 알린다\r\n this._liveRegion = document.createElement('div');\r\n this._liveRegion.setAttribute('aria-live', 'polite');\r\n this._liveRegion.setAttribute('aria-atomic', 'true');\r\n this._liveRegion.className = 'og-live-region';\r\n this._container.insertAdjacentElement('beforebegin', this._liveRegion);\r\n // 키보드로 그리드를 조작할 수 있도록 tabIndex 설정\r\n this._container.tabIndex = 0;\r\n this._container.addEventListener('keydown', (e) => this._handleKeyDown(e));\r\n this._container.addEventListener('keyup', (e) => this._handleCellKeyEvt('cellKeyUp', e));\r\n this._container.addEventListener('keypress', (e) => this._handleCellKeyEvt('cellKeyPress', e));\r\n\r\n this._vs = new VirtualScroll(this._renderer.bodyWrapper, {\r\n rowHeight: this._options.rowHeight,\r\n onRender: (s, e) => this._doRender(s, e),\r\n });\r\n\r\n // 그리드↔그리드 드래그용 레지스트리 등록 (bodyWrapper 기준)\r\n crossGridRegistry.register(this._renderer.bodyWrapper, this);\r\n\r\n if (this._options.draggable) {\r\n this._dnd = new RowDragDrop(\r\n this._renderer.bodyWrapper,\r\n this._options.rowHeight,\r\n (from, to) => this._handleRowDrop(from, to),\r\n this._options.crossGrid ? {\r\n resolveTarget: (x, y) => {\r\n const g = crossGridRegistry.resolveAt(x, y, this);\r\n if (!g || !g._options.crossGrid) return null;\r\n return { bodyEl: g._crossBodyEl(), rowHeight: g._options.rowHeight, totalRows: g._data.rowCount };\r\n },\r\n onCrossDrop: (fromIndex, targetBodyEl, targetIndex) =>\r\n this._handleCrossGridDrop(fromIndex, targetBodyEl, targetIndex),\r\n } : undefined,\r\n (fromIndex) => this._dragRowSet(fromIndex).length,\r\n );\r\n }\r\n // 스크롤 영역, 페이징 바 등 하단 UI 초기화\r\n // ?섏씠吏?UI (?듭뀡?먯꽌 pagination:true???뚮쭔)\r\n if (this._options.pagination) {\r\n this._pagination = new Pagination(\r\n this._container,\r\n this._options.pageSize,\r\n (e) => {\r\n this.emit('pageChange', e);\r\n this._doRender(...this._visRange());\r\n }\r\n );\r\n }\r\n // 찾기 바 초기화 (헤더 위에 삽입)\r\n this._findMgr.init(this._container);\r\n // 오른쪽 클릭 메뉴 초기화\r\n this._initContextMenu();\r\n // 워크시트(탭) 초기화\r\n if (this._options.worksheets?.length) {\r\n this._initWorksheets();\r\n }\r\n\r\n this._ro = new ResizeObserver(() => this._onResize());\r\n this._ro.observe(this._container);\r\n this._onResize();\r\n }\r\n\r\n private _initContextMenu(): void {\r\n const opt = this._options.contextMenu;\r\n if (opt === false) return;\r\n\r\n // 기존 핸들러 제거 — setOptions 재호출 시 중복 등록 방지\r\n if (this._cmHandler) this._container.removeEventListener('contextmenu', this._cmHandler);\r\n if (this._cmKbdHandler) this._container.removeEventListener('keydown', this._cmKbdHandler);\r\n this._cmHandler = this._cmKbdHandler = null;\r\n\r\n this._ctxMenu = new ContextMenuManager(this._container, {\r\n onSortAsc: () => {\r\n const active = this._colLayout.visibleLeaves[0];\r\n if (active) this.orderBy(active.field, 'asc');\r\n },\r\n onSortDesc: () => {\r\n const active = this._colLayout.visibleLeaves[0];\r\n if (active) this.orderBy(active.field, 'desc');\r\n },\r\n onFind: () => this._findMgr.open(),\r\n onExcel: () => this.exportExcel(),\r\n onCsv: () => this.exportCsv(),\r\n onPrint: () => this.print(),\r\n });\r\n\r\n this._cmHandler = (e: MouseEvent) => {\r\n const cell = (e.target as HTMLElement).closest<HTMLElement>('.og-cell');\r\n if (!cell) return;\r\n e.preventDefault();\r\n\r\n const colIdx = Number(cell.dataset.colIndex ?? -1);\r\n const col = this._colLayout.visibleLeaves[colIdx];\r\n\r\n if (col && this._ctxMenu) {\r\n this._ctxMenu['_actions'].onSortAsc = () => this.orderBy(col.field, 'asc');\r\n this._ctxMenu['_actions'].onSortDesc = () => this.orderBy(col.field, 'desc');\r\n }\r\n\r\n // 사용자 정의 메뉴는 단독 표시 (기본 메뉴와 합치지 않음)\r\n const customItems = Array.isArray(opt) ? opt : undefined;\r\n this._ctxMenu?.open(e, customItems);\r\n };\r\n this._container.addEventListener('contextmenu', this._cmHandler);\r\n\r\n this._cmKbdHandler = (e: KeyboardEvent) => {\r\n if (e.shiftKey && e.key === 'F10') {\r\n e.preventDefault();\r\n const rect = this._container.getBoundingClientRect();\r\n const fakeEvent = { clientX: rect.left + 80, clientY: rect.top + 40 } as MouseEvent;\r\n this._ctxMenu?.open(fakeEvent);\r\n }\r\n };\r\n this._container.addEventListener('keydown', this._cmKbdHandler);\r\n }\r\n // openContextMenu / closeContextMenu 공개 API\r\n openContextMenu(e: MouseEvent, items?: import('./types').ContextMenuItem[]): void {\r\n this._ctxMenu?.open(e, items);\r\n }\r\n closeContextMenu(): void {\r\n this._ctxMenu?.close();\r\n }\r\n setFilterSelect(config: FilterSelectConfig | null): void {\r\n this._filterSelect?.destroy();\r\n this._filterSelect = null;\r\n if (!config) return;\r\n if (!this._container.id) {\r\n this._container.id = `og-${Math.random().toString(36).slice(2, 7)}`;\r\n }\r\n this._filterSelect = new FilterSelectPanel(\r\n this._container, config,\r\n (field, items) => this.setFilter(field, items),\r\n (field?) => this.resetFilter(field),\r\n this._container.id\r\n );\r\n }\r\n // 옵션을 런타임에 바꿀 때 호출 (contextMenu 재초기화, groupBy 재구성 등)\r\n setOptions(opts: Partial<GridOptions<T>>): void {\r\n Object.assign(this._options, opts);\r\n if ('contextMenu' in opts) {\r\n this._ctxMenu?.destroy();\r\n this._ctxMenu = null;\r\n this._initContextMenu();\r\n }\r\n // groupBy / summary 변경 시 그룹 재구성\r\n if ('groupBy' in opts || 'summary' in opts) {\r\n const fields = (opts.groupBy ?? []) as string[];\r\n if (fields.length > 0) {\r\n this._grpMgr.groupBy(fields);\r\n } else {\r\n this.clearGroup();\r\n }\r\n return;\r\n }\r\n this._renderHeader();\r\n this._doRender(...this._visRange());\r\n }\r\n\r\n /**\r\n * 컬럼 마스킹 ON/OFF 전환.\r\n * enabled=true → 마스킹 적용 (기본 상태)\r\n * enabled=false → 컬럼 전체 마스킹 해제 (원문 표시)\r\n */\r\n setMaskEnabled(field: string, enabled: boolean): void {\r\n const col = this._colLayout.getColumnByField(field) as any;\r\n if (!col) return;\r\n if (enabled) {\r\n // 마스킹 재활성화: 해제 상태 초기화\r\n col._maskRevealed = false;\r\n (col._maskRevealedRows as Set<number> | undefined)?.clear();\r\n } else {\r\n // 전체 해제\r\n col._maskRevealed = true;\r\n }\r\n this._doRender(...this._visRange());\r\n }\r\n\r\n /** 현재 컬럼 마스킹 활성 여부 반환. true=마스킹 중, false=해제됨 */\r\n getMaskEnabled(field: string): boolean {\r\n const col = this._colLayout.getColumnByField(field) as any;\r\n if (!col) return false;\r\n return col._maskRevealed !== true;\r\n }\r\n private _initWorksheets(): void {\r\n const sheets = this._options.worksheets!;\r\n this._wsManager = new WorksheetManager<T>(\r\n this._container,\r\n (_name, state) => {\r\n // 탭을 전환할 때 데이터와 컬럼을 업데이트한다\r\n this._data.setData(state.data);\r\n this._colLayout = new ColumnLayout<T>(\r\n state.columns.length ? state.columns : this._options.columns,\r\n this._options.frozenColumns,\r\n );\r\n this._doRender(...this._visRange());\r\n this._renderHeader();\r\n }\r\n );\r\n for (const sheet of sheets) {\r\n this._wsManager.add(sheet.name, sheet.columns ?? this._options.columns, sheet.data ?? []);\r\n }\r\n }\r\n\r\n addWorksheet(name: string, columns?: import('./types').ColumnDef<T>[], data?: T[]): void {\r\n if (!this._wsManager) {\r\n this._wsManager = new WorksheetManager<T>(\r\n this._container,\r\n (_n, state) => {\r\n this._data.setData(state.data);\r\n this._colLayout = new ColumnLayout<T>(\r\n state.columns.length ? state.columns : this._options.columns,\r\n this._options.frozenColumns,\r\n );\r\n this._doRender(...this._visRange());\r\n this._renderHeader();\r\n }\r\n );\r\n }\r\n this._wsManager.add(name, columns ?? this._options.columns, data ?? []);\r\n }\r\n\r\n removeWorksheet(name: string): void {\r\n this._wsManager?.remove(name);\r\n }\r\n\r\n switchWorksheet(name: string): void {\r\n this._wsManager?.switch(name);\r\n }\r\n\r\n renameWorksheet(oldName: string, newName: string): void {\r\n this._wsManager?.rename(oldName, newName);\r\n }\r\n\r\n getWorksheet(name: string): import('./types').WorksheetState<T> | undefined {\r\n return this._wsManager?.get(name);\r\n }\r\n\r\n getWorksheetNames(): string[] {\r\n return this._wsManager?.getNames() ?? [];\r\n }\r\n\r\n exportSheetsExcel(filename?: string): void { this._exportMgr.exportSheetsExcel(filename); }\r\n\r\n private _paginationHeight(): number {\r\n return this._options.pagination ? 38 : 0;\r\n }\r\n\r\n private _onResize(): void {\r\n const { width } = this._container.getBoundingClientRect();\r\n if (!width) return;\r\n this._recalcWidths(width);\r\n // _renderHeader() 가 헤더를 그린 뒤 실제 헤더 높이를 측정해 본문/뷰포트 높이를 동기화한다\r\n // (headerWrap/'\\n' 로 헤더가 늘어나도 본문 영역이 침범당하지 않도록).\r\n this._renderHeader();\r\n this._doRender(...this._visRange());\r\n }\r\n\r\n private _recalcWidths(totalWidth: number): void {\r\n this._colWidths = this._colLayout.computeWidths(\r\n totalWidth\r\n - (this._options.stateColumn ? 24 : 0)\r\n - (this._options.draggable ? 18 : 0)\r\n - (this._options.rowNumber ? 44 : 0)\r\n - (this._options.checkColumn ? 36 : 0),\r\n this._options.defaultColumnWidth\r\n );\r\n // 사용자가 직접 조절한 폭은 보존 (리사이즈 후 재계산으로 원복되는 문제 방지)\r\n if (this._userWidths.size) {\r\n this._colLayout.visibleLeaves.forEach((leaf, i) => {\r\n const w = this._userWidths.get(leaf.field);\r\n if (w != null) this._colWidths[i] = w;\r\n });\r\n }\r\n }\r\n // 헤더(컬럼 제목 행)를 다시 그린다\r\n private _renderHeader(): void {\r\n this._renderer?.renderHeader(\r\n this._colLayout.buildHeaderCells(),\r\n this._colLayout.visibleLeaves,\r\n this._colWidths,\r\n this._sfMgr.sortList,\r\n { ...this._options, _activeFilters: this._sfMgr.filters, _frozenCount: this._colLayout.frozenCount }\r\n );\r\n // 헤더 줄바꿈(headerWrap/'\\n')으로 헤더가 늘어나면 본문 영역 높이를 다시 맞춰 침범을 막는다.\r\n this._syncHeaderLayout();\r\n }\r\n\r\n /**\r\n * 렌더된 헤더의 실제 높이를 측정해 본문(bodyWrap) 높이와 뷰포트 높이에 반영한다.\r\n * 줄바꿈이 없는 헤더는 측정 높이가 headerHeight 이하라 기존 고정 동작과 동일하다.\r\n */\r\n private _syncHeaderLayout(): void {\r\n if (!this._renderer || !this._vs) return;\r\n const { height } = this._container.getBoundingClientRect();\r\n if (!height) return;\r\n const measured = this._renderer.getHeaderHeight();\r\n const headerH = measured > this._options.headerHeight ? measured : this._options.headerHeight;\r\n this._renderer.updateSize(height - this._paginationHeight(), headerH);\r\n this._vs.setViewportHeight(height - headerH - this._paginationHeight());\r\n }\r\n private _doRender(startIndex: number, endIndex: number): void {\r\n if (!this._renderer || !this._vs) return;\r\n const range = this._vs.getVisibleRange();\r\n // autoHeight(비가상): 행을 플로우로 쌓으므로 offsetY/totalHeight 절대배치를 쓰지 않는다.\r\n // 스크롤 등으로 부분 범위가 들어와도 전체를 렌더(가상화 안 함)해 행 누락을 막는다.\r\n const auto = this._options.autoHeight === true;\r\n if (auto) {\r\n [startIndex, endIndex] = this._visRange();\r\n // 대용량 가드: autoHeight 는 전 행을 렌더(비가상)하므로 행이 많으면 느려진다(1회 경고).\r\n if (!this._autoHeightWarned && endIndex - startIndex + 1 > 2000) {\r\n this._autoHeightWarned = true;\r\n console.warn(\r\n `[OpenGrid] autoHeight 는 가상 스크롤이 아니라 전 행(${endIndex - startIndex + 1}행)을 렌더합니다. ` +\r\n '행이 많으면 고정 rowHeight(가상 스크롤) 사용을 권장합니다.');\r\n }\r\n }\r\n this._renderer.renderBody(\r\n startIndex, endIndex,\r\n this._data,\r\n this._colLayout.visibleLeaves,\r\n this._colWidths,\r\n this._options,\r\n auto ? 0 : range.offsetY,\r\n auto ? 0 : this._vs.getTotalHeight(),\r\n this._rowMgr.selectedRows,\r\n this._rowMgr.checkedRows,\r\n this._grpMgr.isGroupMode ? this._grpMgr.groupFlatRows : (this._grpMgr.isTreeMode ? this._grpMgr.treeFlatRows : null),\r\n (groupKey) => this._grpMgr.handleGroupToggle(groupKey),\r\n this._grpMgr.isTreeMode ? (nodeId) => this._grpMgr.handleTreeToggle(nodeId) : undefined,\r\n { _totalRows: this._data.rowCount, _frozenCount: this._colLayout.frozenCount, _focusCell: this._editMgr.focusCell },\r\n this._mergeEngine\r\n );\r\n // 데이터가 바뀌면 푸터 합계도 다시 계산한다\r\n if (this._options.footer?.length) this._renderFooterEl();\r\n }\r\n\r\n private _handleGroupToggle(groupKey: string): void { this._grpMgr.handleGroupToggle(groupKey); }\r\n\r\n // 현재 화면에 보이는 행 범위를 반환한다\r\n private _visRange(): [number, number] {\r\n if (this._options.pagination && this._pagination) {\r\n const { start, end } = this._pagination.getRange();\r\n return [start, end];\r\n }\r\n // autoHeight(비가상): 가상화하지 않고 전체 행을 렌더 (높이가 행마다 다르므로 범위 계산 불가)\r\n if (this._options.autoHeight) {\r\n const total = this._grpMgr.isGroupMode ? this._grpMgr.groupFlatRows.length\r\n : this._grpMgr.isTreeMode ? this._grpMgr.treeFlatRows.length\r\n : this._data.rowCount;\r\n return [0, total - 1];\r\n }\r\n const r = this._vs?.getVisibleRange();\r\n return [r?.startIndex ?? 0, Math.min((r?.endIndex ?? 30) + this._visCount() + 5, this._data.rowCount - 1)];\r\n }\r\n\r\n private _visCount(): number {\r\n const h = this._container.getBoundingClientRect().height;\r\n return Math.ceil((h - this._options.headerHeight - this._paginationHeight()) / this._options.rowHeight) + 5;\r\n }\r\n private _handleSortClick(field: string, shiftKey: boolean): void { this._sfMgr.handleSortClick(field, shiftKey); }\r\n\r\n private _isToggleCol(col: ColumnDef<T>): boolean { return isToggleCol(col); }\r\n private _handleCellClick(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellClick(ri, ci, e); }\r\n private _handleCellDblClick(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellDblClick(ri, ci, e); }\r\n private _handleCellMouseOver(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellMouseOver(ri, ci, e); }\r\n private _handleCellMouseOut(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellMouseOut(ri, ci, e); }\r\n private _handleCellMouseDown(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellMouseDown(ri, ci, e); }\r\n private _handleCellMouseUp(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellMouseUp(ri, ci, e); }\r\n private _handleCellMouseMove(ri: number, ci: number, e: MouseEvent): void { this._cellEvt.handleCellMouseMove(ri, ci, e); }\r\n private _handleCellKeyEvt(name: 'cellKeyDown' | 'cellKeyUp' | 'cellKeyPress', e: KeyboardEvent): void { this._cellEvt.handleCellKeyEvt(name, e); }\r\n\r\n private _handleRowCheck(rowIndex: number, checked: boolean): void {\r\n this._rowMgr.check(rowIndex, checked);\r\n this._doRender(...this._visRange());\r\n this.emit('rowCheck', { rowIndex, checked, row: this._data.getRowByIndex(rowIndex) });\r\n }\r\n\r\n private _handleFilterIconClick(field: string, anchorEl: HTMLElement): void {\r\n if (this._filterPanel?.isOpen) {\r\n this._filterPanel.close();\r\n return;\r\n }\r\n const current = this._sfMgr.filters[field] ?? [];\r\n this._filterPanel?.open(field, anchorEl, current);\r\n }\r\n\r\n private _handleAllCheck(checked: boolean): void {\r\n this._rowMgr.checkAll(checked, this._data.rowCount);\r\n this._doRender(...this._visRange());\r\n this.emit('allCheck', { checked });\r\n }\r\n private _handleRowDrop(fromIndex: number, toIndex: number): void {\r\n this._data.moveRow(fromIndex, toIndex);\r\n this._doRender(...this._visRange());\r\n this.emit('rowDrop', { fromIndex, toIndex });\r\n this._options.onRowDrop?.({ fromIndex, toIndex });\r\n }\r\n\r\n // ── 크로스그리드 내부 헬퍼 ──\r\n /** 드래그/셔틀이 참조하는 바디 엘리먼트 (레지스트리 해석용) */\r\n _crossBodyEl(): HTMLElement { return this._renderer!.bodyWrapper; }\r\n /** fromIndex 를 잡고 드래그할 때 함께 이동할 행 집합 (다중선택에 포함되면 선택 전체) */\r\n private _dragRowSet(fromIndex: number): number[] {\r\n const sel = [...this._rowMgr.selectedRows];\r\n return (sel.length > 1 && sel.includes(fromIndex))\r\n ? sel.sort((a, b) => a - b)\r\n : [fromIndex];\r\n }\r\n\r\n /** 드래그 드롭 어댑터 → 공개 moveRowsTo 로 위임 */\r\n private _handleCrossGridDrop(fromIndex: number, targetBodyEl: HTMLElement, targetIndex: number): void {\r\n const targetGrid = crossGridRegistry.get(targetBodyEl) as OpenGrid<T> | undefined;\r\n if (!targetGrid || targetGrid === this) return;\r\n void this.moveRowsTo(targetGrid, this._dragRowSet(fromIndex), targetIndex);\r\n }\r\n\r\n /**\r\n * 이 그리드의 행들을 다른 그리드로 이동(move)한다. 드래그·화살표 셔틀 공통 경로.\r\n * 3단계 이벤트(before→after→complete)와 crossGridMapping(필드 매핑)을 적용한다.\r\n * @param targetGrid 대상 그리드\r\n * @param sourceIndexes 이동할 (표시)행 인덱스들\r\n * @param targetIndex 대상에서 삽입 위치 (생략 시 맨 끝에 추가)\r\n * @returns 이동 성공 true, 취소/무효 false\r\n */\r\n async moveRowsTo(\r\n target: OpenGridInstance<T>,\r\n sourceIndexes: number[],\r\n targetIndex?: number,\r\n ): Promise<boolean> {\r\n const targetGrid = target as OpenGrid<T>;\r\n if (!targetGrid || targetGrid === this || !sourceIndexes.length) return false;\r\n const idxAsc = [...new Set(sourceIndexes)].sort((a, b) => a - b);\r\n const at = targetIndex ?? targetGrid._data.rowCount;\r\n\r\n // 행 데이터 복사 (내부 id 제거 → 타깃이 새 id 부여)\r\n let rows = idxAsc.map(i => {\r\n const r = { ...(this._data.getRowByIndex(i) as any) };\r\n delete r[ROW_ID_FIELD];\r\n return r as T;\r\n });\r\n\r\n // 필드 매핑 (스키마가 다른 그리드 간 이동)\r\n const transform = await this._resolveCrossTransform(targetGrid);\r\n if (transform === false) return false; // 매핑 모달 취소\r\n if (transform) rows = rows.map(r => transform(r) as T);\r\n\r\n const evt: GridDropEvent<T> = {\r\n sourceGrid: this, targetGrid, rows, sourceIndexes: idxAsc, targetIndex: at,\r\n };\r\n\r\n // ① 변경전 (양쪽). false 반환 또는 cancel=true 면 중단\r\n if (this._fireGridDropBefore(evt) === false || evt.cancel) return false;\r\n if (targetGrid._fireGridDropBefore(evt) === false || evt.cancel) return false;\r\n\r\n // 이동: 타깃에 순서대로 삽입 → 소스에서 내림차순 제거\r\n rows.forEach((row, k) => targetGrid.insertRow(row as Partial<T>, at + k));\r\n [...idxAsc].sort((a, b) => b - a).forEach(i => this.deleteRow(i));\r\n\r\n // ② 변경후\r\n this._fireGridDropAfter(evt);\r\n targetGrid._fireGridDropAfter(evt);\r\n // ③ 완료시 (insert/delete 가 이미 양쪽 재렌더)\r\n this._fireGridDropComplete(evt);\r\n targetGrid._fireGridDropComplete(evt);\r\n return true;\r\n }\r\n\r\n /** 체크된 행을 다른 그리드로 이동 (화살표 셔틀용). 체크 없으면 무시. */\r\n async moveCheckedTo(target: OpenGridInstance<T>): Promise<boolean> {\r\n const indexes = this._rowMgr.getChecked().map(c => c.rowIndex);\r\n if (!indexes.length) return false;\r\n this._rowMgr.uncheckAll();\r\n return this.moveRowsTo(target, indexes);\r\n }\r\n\r\n /**\r\n * 크로스그리드 이동의 행 변환 함수를 결정한다.\r\n * 반환: null=변환 불필요(그대로) / 함수=변환 적용 / false=매핑 모달 취소(이동 중단)\r\n */\r\n private async _resolveCrossTransform(targetGrid: OpenGrid<T>): Promise<((src: any) => any) | null | false> {\r\n const mode = this._options.crossGridMapping;\r\n if (typeof mode === 'function') return mode as (src: any) => any;\r\n if (mode !== 'interactive') return null; // 'auto' → 그대로 복사\r\n\r\n const srcInfos: FieldInfo[] = this._colLayout.visibleLeaves.map(c => ({ field: c.field, header: c.header }));\r\n const tgtInfos: FieldInfo[] = targetGrid._colLayout.visibleLeaves.map(c => ({ field: c.field, header: c.header }));\r\n if (sameSchema(srcInfos.map(f => f.field), tgtInfos.map(f => f.field))) return null; // 스키마 동일 → 모달 불필요\r\n\r\n const result = await openCrossGridMapper(srcInfos, tgtInfos);\r\n if (!result) return false; // 취소\r\n const mapEvt: GridMappingEvent<T> = {\r\n sourceGrid: this, targetGrid,\r\n mapping: result.mapping, script: result.script,\r\n };\r\n this.emit('gridDropMapping', mapEvt);\r\n this._options.onGridDropMapping?.(mapEvt);\r\n // 콘솔에도 출력 — 개발자가 바로 복사해 baking 하도록\r\n console.log('[OpenGrid] cross-grid mapping script:\\n' + buildMappingScript(result.mapping));\r\n return buildTransform(result.mapping);\r\n }\r\n\r\n private _fireGridDropBefore(e: GridDropEvent<T>): boolean | void {\r\n this.emit('gridDropBefore', e);\r\n return this._options.onGridDropBefore?.(e);\r\n }\r\n private _fireGridDropAfter(e: GridDropEvent<T>): void {\r\n this.emit('gridDropAfter', e);\r\n this._options.onGridDropAfter?.(e);\r\n }\r\n private _fireGridDropComplete(e: GridDropEvent<T>): void {\r\n this.emit('gridDropComplete', e);\r\n this._options.onGridDropComplete?.(e);\r\n }\r\n /** 행을 드롭으로 이동할 때 실행된다 */\r\n /** ???꾩튂 ?대룞 */\r\n reorderRow(fromIndex: number, toIndex: number): void {\r\n this._data.moveRow(fromIndex, toIndex);\r\n this._doRender(...this._visRange());\r\n }\r\n private _handleColResize(colIndex: number, newWidth: number): void {\r\n if (this._colWidths[colIndex] !== undefined) {\r\n this._colWidths[colIndex] = newWidth;\r\n }\r\n // 사용자가 조절한 폭을 field 기준으로 기억 → 이후 재계산(_recalcWidths)에서 보존\r\n const leaf = this._colLayout.visibleLeaves[colIndex];\r\n if (leaf) this._userWidths.set(leaf.field, newWidth);\r\n this._renderHeader(); // 헤더 폭도 즉시 동기화\r\n this._doRender(...this._visRange());\r\n }\r\n private _handleKeyDown(e: KeyboardEvent): void { this._kbdMgr.handleKeyDown(e); }\r\n\r\n private _setFocusCell(ri: number, ci: number): void {\r\n this._rowMgr.selectSingle(ri);\r\n this._editMgr.setFocusCell(ri, ci);\r\n }\r\n // 스크린리더에게 텍스트를 읽어준다 (aria-live)\r\n private _announce(msg: string): void {\r\n if (!this._liveRegion) return;\r\n this._liveRegion.textContent = '';\r\n setTimeout(() => { if (this._liveRegion) this._liveRegion.textContent = msg; }, 50);\r\n }\r\n\r\n private _bindOptionEvents(): void {\r\n if (this._options.onCellClick) this.on('cellClick', this._options.onCellClick);\r\n if (this._options.onCellDblClick) this.on('cellDblClick', this._options.onCellDblClick);\r\n if (this._options.onRowClick) this.on('rowClick', this._options.onRowClick);\r\n if (this._options.onEditStart) this.on('editStart', this._options.onEditStart);\r\n if (this._options.onEditEnd) this.on('editEnd', this._options.onEditEnd);\r\n if (this._options.onSortChange) this.on('sortChange', this._options.onSortChange);\r\n if (this._options.onFilterChange) this.on('filterChange', this._options.onFilterChange);\r\n if (this._options.onScroll) this.on('scroll', this._options.onScroll);\r\n if (this._options.onDataChange) this.on('dataChange', this._options.onDataChange);\r\n if (this._options.onSelectionChange) this.on('selectionChange', this._options.onSelectionChange);\r\n // Sprint 35 ?좉퇋\r\n if (this._options.onRowDblClick) this.on('rowDblClick', this._options.onRowDblClick);\r\n if (this._options.onRowMouseOver) this.on('rowMouseOver', this._options.onRowMouseOver);\r\n if (this._options.onRowMouseOut) this.on('rowMouseOut', this._options.onRowMouseOut);\r\n if (this._options.onRowMouseDown) this.on('rowMouseDown', this._options.onRowMouseDown);\r\n if (this._options.onRowMouseUp) this.on('rowMouseUp', this._options.onRowMouseUp);\r\n if (this._options.onRowMouseMove) this.on('rowMouseMove', this._options.onRowMouseMove);\r\n if (this._options.onCellMouseOver) this.on('cellMouseOver', this._options.onCellMouseOver);\r\n if (this._options.onCellMouseOut) this.on('cellMouseOut', this._options.onCellMouseOut);\r\n if (this._options.onCellMouseDown) this.on('cellMouseDown', this._options.onCellMouseDown);\r\n if (this._options.onCellMouseUp) this.on('cellMouseUp', this._options.onCellMouseUp);\r\n if (this._options.onCellMouseMove) this.on('cellMouseMove', this._options.onCellMouseMove);\r\n if (this._options.onCellKeyDown) this.on('cellKeyDown', this._options.onCellKeyDown);\r\n if (this._options.onCellKeyUp) this.on('cellKeyUp', this._options.onCellKeyUp);\r\n if (this._options.onCellKeyPress) this.on('cellKeyPress', this._options.onCellKeyPress);\r\n }\r\n setData(data: T[]): void {\r\n const ctx = this._trigMgr.mkCtx('setData', [data]);\r\n if (!this._trigMgr.exec('before:setData', ctx)) return;\r\n this._rowMgr.reset();\r\n this._data.setData(data);\r\n this._applyFilters();\r\n if (this._grpMgr.isTreeMode) {\r\n this._grpMgr.rebuildTree();\r\n } else if (this._grpMgr.isGroupMode) {\r\n this._grpMgr.rebuildGroups();\r\n } else {\r\n this._vs?.setTotalRows(this._data.rowCount);\r\n }\r\n this._container.setAttribute('aria-rowcount', String(this._data.rowCount));\r\n this._container.setAttribute('aria-colcount', String(this._colLayout.visibleLeaves.length));\r\n this._announce(`${this._data.rowCount}행 데이터 로드됨`);\r\n this.emit('dataChange', this._data.getData());\r\n ctx.result = data.length;\r\n this._trigMgr.exec('after:setData', ctx);\r\n }\r\n\r\n getData(): T[] { return this._data.getData(); }\r\n getSourceRows(): T[] { return this._data.getOriginalData(); }\r\n\r\n pushData(data: T[]): void {\r\n const combined = [...this._data.getAllData(), ...data];\r\n this._data.setData(combined);\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n }\r\n\r\n prefixData(data: T[]): void {\r\n const combined = [...data, ...this._data.getAllData()];\r\n this._data.setData(combined);\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n }\r\n\r\n clearData(): void {\r\n this._rowMgr.reset();\r\n this._data.clearData();\r\n this._vs?.setTotalRows(0);\r\n this._pagination?.setTotalRows(0);\r\n this._doRender(0, -1);\r\n this.emit('dataChange', []);\r\n }\r\n\r\n insertRow(item: Partial<T>, position: Position = 'last'): void {\r\n const ctx = this._trigMgr.mkCtx('insertRow', [item, position]);\r\n if (!this._trigMgr.exec('before:insertRow', ctx)) return;\r\n const pos = position === 'before' ? 0\r\n : position === 'after' ? this._data.rowCount\r\n : position as any;\r\n this._data.addRow(item, pos);\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n this._doRender(...this._visRange());\r\n this.emit('dataChange', this._data.getData());\r\n this._options.onDataChange?.(this._data.getData());\r\n ctx.result = { rowCount: n, item };\r\n this._trigMgr.exec('after:insertRow', ctx);\r\n }\r\n\r\n pushRow(items: Partial<T> | Partial<T>[]): void {\r\n const arr = Array.isArray(items) ? items : [items];\r\n arr.forEach(it => this._data.addRow(it, 'last'));\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n this._doRender(...this._visRange());\r\n this.emit('dataChange', this._data.getData());\r\n this._options.onDataChange?.(this._data.getData());\r\n }\r\n\r\n /** @deprecated 하위호환 alias → pushRow */\r\n appendRows(items: Partial<T> | Partial<T>[]): void { this.pushRow(items); }\r\n\r\n unshiftRow(items: Partial<T> | Partial<T>[]): void {\r\n const arr = Array.isArray(items) ? items : [items];\r\n arr.forEach(it => this._data.addRow(it, 'first'));\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n this._doRender(...this._visRange());\r\n this.emit('dataChange', this._data.getData());\r\n this._options.onDataChange?.(this._data.getData());\r\n }\r\n\r\n /** @deprecated 하위호환 alias → unshiftRow */\r\n prependRows(items: Partial<T> | Partial<T>[]): void { this.unshiftRow(items); }\r\n\r\n deleteRow(rowIndex: number | number[]): void {\r\n const ctx = this._trigMgr.mkCtx('deleteRow', [rowIndex]);\r\n const idxArr = Array.isArray(rowIndex) ? [...rowIndex] : [rowIndex];\r\n ctx.extra = { rows: idxArr.map(i => this._data.getRowByIndex(i)) };\r\n if (!this._trigMgr.exec('before:deleteRow', ctx)) return;\r\n const idxs = idxArr.sort((a, b) => b - a);\r\n idxs.forEach(i => this._data.removeRow(i));\r\n const n = this._data.rowCount;\r\n this._vs?.setTotalRows(n);\r\n this._pagination?.setTotalRows(n);\r\n this._doRender(...this._visRange());\r\n this.emit('dataChange', this._data.getData());\r\n this._options.onDataChange?.(this._data.getData());\r\n ctx.result = { deleted: idxs.length, rowCount: n };\r\n this._trigMgr.exec('after:deleteRow', ctx);\r\n }\r\n\r\n deleteById(_ids: string[]): void { /* 異뷀썑 援ы쁽 */ }\r\n\r\n readCell(rowIndex: number, field: string): any {\r\n return this._data.getCellValue(rowIndex, field);\r\n }\r\n getDisplayValue(rowIndex: number, field: string): string {\r\n const val = this.readCell(rowIndex, field);\r\n // Phase 2 슬롯 #3: displayFormatter(본문 1줄 — C1 최소 침습 예외). default = 현행(null→'', else String).\r\n const fmt = this._ovk.getStrategy(\r\n 'displayFormatter',\r\n (v: any, _f: string, _row: any): string => (v == null ? '' : String(v)),\r\n );\r\n return fmt(val, field, this._data.getRowByIndex(rowIndex));\r\n }\r\n\r\n writeCell(rowIndex: number, field: string, value: any): void {\r\n const old = this.readCell(rowIndex, field);\r\n const ctx = this._trigMgr.mkCtx('writeCell', [rowIndex, field, value]);\r\n ctx.extra = { oldValue: old, rowIndex, field };\r\n if (!this._trigMgr.exec('before:writeCell', ctx)) return;\r\n this._data.updateCell(rowIndex, field, value);\r\n const row = this._data.getRowByIndex(rowIndex);\r\n const col = this._colLayout.getColumnByField(field);\r\n const ci = this._colLayout.getColumnIndex(field);\r\n const evt: EditEvent<T> = { type: 'editEnd', rowIndex, columnIndex: ci, field, oldValue: old, newValue: value, row: row as T, column: col as any };\r\n this.emit('editEnd', evt);\r\n this._options.onEditEnd?.(evt);\r\n this.emit('dataChange', this._data.getData());\r\n this._options.onDataChange?.(this._data.getData());\r\n this._doRender(...this._visRange());\r\n ctx.result = { rowIndex, field, oldValue: old, newValue: value };\r\n this._trigMgr.exec('after:writeCell', ctx);\r\n }\r\n\r\n getRowAt(rowIndex: number): T { return this._data.getRowByIndex(rowIndex) as T; }\r\n\r\n getChanges(): { added: T[]; edited: T[]; removed: T[] } { return this._data.getChanges(); }\r\n getEditedRows(): T[] { return this._data.getEditedRows(); }\r\n getChangedRows(): T[] { return this._data.getChangedRows(); } // ?섏쐞 ?명솚\r\n getChangedColumns(): Array<{ row: T; fields: string[]; diff: Array<{ field: string; oldValue: any; newValue: any }> }> {\r\n return this._data.getChangedColumns();\r\n }\r\n getAddedRows(): T[] { return this._data.getAddedRows(); }\r\n getRemovedRows(): T[] { return this._data.getRemovedRows(); }\r\n getOriginalRow(rowIndex: number): T | undefined { return this._data.getOriginalRow(rowIndex); }\r\n getRowsWithState(stateField: string): T[] { return this._data.getRowsWithState(stateField); }\r\n undo(): void {}\r\n redo(): void {}\r\n clearHistory(): void {}\r\n getColumnDefs(): ColumnDef<T>[] { return this._colLayout.visibleLeaves; }\r\n getAllColumnDefs(): ColumnDef<T>[] { return this._colLayout.leaves; }\r\n getColumnCount(): number { return this._colLayout.visibleLeaves.length; }\r\n applyColumns(columns: ColumnDef<T>[]): void {\r\n const ctx = this._trigMgr.mkCtx('applyColumns', [columns]);\r\n if (!this._trigMgr.exec('before:applyColumns', ctx)) return;\r\n this._colLayout.setColumns(columns);\r\n this._recalcWidths(this._container.getBoundingClientRect().width);\r\n this._renderHeader();\r\n this._doRender(...this._visRange());\r\n ctx.result = { columnCount: columns.length };\r\n this._trigMgr.exec('after:applyColumns', ctx);\r\n }\r\n insertColumn(colDef: ColumnDef<T>, position?: Position): void {\r\n this._colLayout.addColumn(colDef, position as any);\r\n this._recalcWidths(this._container.getBoundingClientRect().width);\r\n this._renderHeader(); this._doRender(...this._visRange());\r\n }\r\n deleteColumn(field: string): void {\r\n this._colLayout.removeColumn(field);\r\n this._recalcWidths(this._container.getBoundingClientRect().width);\r\n this._renderHeader(); this._doRender(...this._visRange());\r\n }\r\n\r\n private _reorderColumn(fromIdx: number, toIdx: number): void {\r\n const leaves = this._colLayout.visibleLeaves.map(l => l as ColumnDef<T>);\r\n if (fromIdx < 0 || toIdx < 0 || fromIdx >= leaves.length || toIdx >= leaves.length) return;\r\n const reordered = [...this._options.columns];\r\n const [moved] = reordered.splice(fromIdx, 1);\r\n reordered.splice(toIdx, 0, moved);\r\n this._options.columns = reordered;\r\n this.applyColumns(reordered);\r\n this._options.onColumnReorder?.({ fromIndex: fromIdx, toIndex: toIdx, field: moved.field ?? '' });\r\n }\r\n hideColumn(field: string | string[]): void {\r\n this._colLayout.hideColumn(field);\r\n this._recalcWidths(this._container.getBoundingClientRect().width);\r\n this._renderHeader(); this._doRender(...this._visRange());\r\n }\r\n showColumn(field: string | string[]): void {\r\n this._colLayout.showColumn(field);\r\n this._recalcWidths(this._container.getBoundingClientRect().width);\r\n this._renderHeader(); this._doRender(...this._visRange());\r\n }\r\n getColumnIndex(field: string): number { return this._colLayout.getColumnIndex(field); }\r\n getFieldAt(idx: number): string { return this._colLayout.getColumnByIndex(idx)?.field ?? ''; }\r\n getColValues(field: string, _all = false): any[] { return this._data.getData().map(r => r[field]); }\r\n getUniqueValues(field: string, all = false): any[] { return [...new Set(this.getColValues(field, all))]; }\r\n setColWidths(_widths: number[]): void {}\r\n calcColWidths(_fitToGrid = false): number[] { return []; }\r\n getSelections(): T[] { return this._rowMgr.getSelections(); }\r\n getActiveRow(): number { return this._rowMgr.getActiveRow(); }\r\n activate(index: number): void { this._rowMgr.activate(index); this._doRender(...this._visRange()); }\r\n deselect(): void { this._rowMgr.deselect(); this._doRender(...this._visRange()); }\r\n getChecked(): Array<{ row: T; rowIndex: number }> { return this._rowMgr.getChecked(); }\r\n getAllChecked(): T[] { return this._rowMgr.getAllChecked(); }\r\n checkById(_ids: string[]): void {}\r\n addCheckById(_ids: string[]): void {}\r\n checkByValue(field: string, values: any[]): void {\r\n this._rowMgr.checkByValue(field, values);\r\n this._doRender(...this._visRange());\r\n }\r\n uncheckById(_ids: string[]): void {}\r\n uncheckAll(): void { this._rowMgr.uncheckAll(); this._doRender(...this._visRange()); }\r\n orderBy(fieldOrList: string | SortItem[], dir: 'asc' | 'desc' = 'asc'): void {\r\n const ctx = this._trigMgr.mkCtx('orderBy', [fieldOrList, dir]);\r\n if (!this._trigMgr.exec('before:orderBy', ctx)) return;\r\n this._sfMgr.sort(fieldOrList, dir);\r\n ctx.result = { sortList: this._sfMgr.sortList };\r\n this._trigMgr.exec('after:orderBy', ctx);\r\n }\r\n resetOrder(): void { this._sfMgr.resetSort(); }\r\n setFilter(field: string, filterItems: FilterItem[]): void {\r\n const ctx = this._trigMgr.mkCtx('setFilter', [field, filterItems]);\r\n if (!this._trigMgr.exec('before:setFilter', ctx)) return;\r\n this._sfMgr.setFilter(field, filterItems);\r\n ctx.result = { field, filteredCount: this._data.rowCount };\r\n this._trigMgr.exec('after:setFilter', ctx);\r\n }\r\n resetFilter(field?: string): void { this._sfMgr.resetFilter(field); }\r\n getFilterState(): Record<string, FilterItem[]> { return this._sfMgr.getFilterState(); }\r\n restoreFilter(state: Record<string, FilterItem[]>): void { this._sfMgr.restoreFilter(state); }\r\n private _applyFilters(): void { this._sfMgr.applyFilters(); }\r\n freeze(n: number): void { this._colLayout.setFrozen(n); this._renderHeader(); this._doRender(...this._visRange()); }\r\n /** ?섎룞 蹂묓빀: [{row, col, rowSpan?, colSpan?}] */\r\n mergeCells(cells: MergeCell[]): void {\r\n this._mergeEngine.applyMergeCells(cells);\r\n this._doRender(...this._visRange());\r\n }\r\n /** 자동 병합: 지정 필드 컬럼에서 연속 같은 값을 rowSpan으로 묶는다 */\r\n /** ?먮룞 蹂묓빀: 吏€??field 而щ읆?먯꽌 ?곗냽 媛숈? 媛믪쓣 rowSpan */\r\n autoMerge(fields: string[]): void {\r\n const leaves = this._colLayout.visibleLeaves;\r\n const colIndexes: number[] = [];\r\n const fieldNames: string[] = [];\r\n for (const f of fields) {\r\n const ci = leaves.findIndex(l => l.field === f);\r\n if (ci >= 0) { colIndexes.push(ci); fieldNames.push(f); }\r\n }\r\n this._mergeEngine.applyAutoMerge(this._data.getData(), colIndexes, fieldNames);\r\n this._doRender(...this._visRange());\r\n }\r\n\r\n /** 蹂묓빀 ?댁젣 */\r\n clearMerge(): void {\r\n this._mergeEngine.clear();\r\n this._doRender(...this._visRange());\r\n }\r\n freezeRows(_n: number): void {}\r\n groupBy(fields: string[]): void {\r\n const ctx = this._trigMgr.mkCtx('groupBy', [fields]);\r\n if (!this._trigMgr.exec('before:groupBy', ctx)) return;\r\n this._grpMgr.groupBy(fields);\r\n ctx.result = { fields };\r\n this._trigMgr.exec('after:groupBy', ctx);\r\n }\r\n clearGroup(): void { this._grpMgr.clearGroup(); }\r\n expandAll(): void { this._grpMgr.expandAll(); }\r\n collapseAll(): void { this._grpMgr.collapseAll(); }\r\n enableTree(): void { this._grpMgr.enableTree(); }\r\n disableTree(): void { this._grpMgr.disableTree(); }\r\n expandNodes(ids: any | any[], open = true): void { this._grpMgr.expandNodes(ids, open); }\r\n expandAllNodes(): void { this._grpMgr.expandAllNodes(); }\r\n collapseAllNodes(): void { this._grpMgr.collapseAllNodes(); }\r\n addTreeRow(_item: Partial<T>, _pid: string, _pos?: Position): void {}\r\n exportExcel(options?: ExportOptions | string): void { this._exportMgr.exportExcel(options); }\r\n exportCsv(options?: ExportOptions | string): void { this._exportMgr.exportCsv(options); }\r\n exportJson(options?: ExportOptions | string): void { this._exportMgr.exportJson(options); }\r\n print(options?: { title?: string; excludeFields?: string[] }): void { this._exportMgr.print(options); }\r\n\r\n toArray(keyValue = true): any[] {\r\n const data = this._data.getData();\r\n if (keyValue) return data;\r\n const cols = this._colLayout.visibleLeaves;\r\n return data.map(row => cols.map(c => row[c.field]));\r\n }\r\n jumpToRow(rowIndex: number): void {\r\n this._rowMgr.selectSingle(rowIndex);\r\n this._vs?.scrollToRow(rowIndex);\r\n this._doRender(...this._visRange());\r\n }\r\n jumpToCol(_field: string): void {}\r\n getScrollPos(): { x: number; y: number } {\r\n return { x: this._renderer?.bodyWrapper.scrollLeft ?? 0, y: this._renderer?.bodyWrapper.scrollTop ?? 0 };\r\n }\r\n setFooter(fd: any[]): void {\r\n this._options.footer = fd as any;\r\n this._renderFooterEl();\r\n }\r\n getFooterData(): any[] { return this._footerMgr.computeValues(); }\r\n getFooterValue(field: string): any {\r\n return this._footerMgr.computeValues().find((r: any) => r._field === field)?._value ?? null;\r\n }\r\n private _renderFooterEl(): void { this._footerMgr.render(); }\r\n\r\n resize(w?: number, h?: number): void {\r\n if (w) this._container.style.width = `${w}px`;\r\n if (h) this._container.style.height = `${h}px`;\r\n this._onResize();\r\n }\r\n setTheme(theme: string): void { this._container.setAttribute('data-og-theme', theme); }\r\n setThemeVar(k: string, v: string): void { this._container.style.setProperty(k, v); }\r\n addTrigger(event: TriggerEvent | string, handler: TriggerHandler): this {\r\n this._trigMgr.add(event, handler); return this;\r\n }\r\n removeTrigger(event: TriggerEvent | string, handler: TriggerHandler): this {\r\n this._trigMgr.remove(event, handler); return this;\r\n }\r\n clearTriggers(event?: TriggerEvent | string): this {\r\n this._trigMgr.clear(event); return this;\r\n }\r\n private _mkCtx(operation: string, args: any[]): TriggerContext { return this._trigMgr.mkCtx(operation, args); }\r\n private _trig(event: string, ctx: TriggerContext): boolean { return this._trigMgr.exec(event, ctx); }\r\n\r\n destroy(): void {\r\n if (this._destroyed) return;\r\n this._destroyed = true;\r\n if (this._renderer) crossGridRegistry.unregister(this._renderer.bodyWrapper);\r\n this._trigMgr.clear();\r\n this._ro?.disconnect();\r\n this._vs?.destroy();\r\n this._filterPanel?.destroy();\r\n this._dnd?.destroy();\r\n if (this._cmHandler) this._container.removeEventListener('contextmenu', this._cmHandler);\r\n if (this._cmKbdHandler) this._container.removeEventListener('keydown', this._cmKbdHandler);\r\n this._cmHandler = this._cmKbdHandler = null;\r\n this._ctxMenu?.destroy();\r\n this._wsManager?.destroy();\r\n this._renderer?.destroy();\r\n this._liveRegion?.remove();\r\n this._liveRegion = null;\r\n this._container.innerHTML = '';\r\n this._container.classList.remove('og-container');\r\n this.removeAllListeners();\r\n }\r\n}\r\n\r\n\r\n"],"names":["EventEmitter","event","handler","list","filtered","e","args","remaining","entry","_a","_rowIdSeq","nextRowId","DataLayer","idField","_slot","fallback","resolver","data","row","id","item","r","_","i","position","idx","dispPos","dataIdx","rowIndex","meta","fromDisplayIdx","toDisplayIdx","fromDataIdx","toDataIdx","insertAt","field","value","added","edited","removed","state","orig","changedFields","k","diff","key","d","stateField","sortList","notRemoved","_b","keyed","s","cmpStrategy","a","b","_field","_dir","sa","sb","si","dir","av","bv","cmp","filters","fields","predicate","fi","matchFilter","val","q","f","v","query","fv","VirtualScroll","container","options","range","visibleCount","startIndex","endIndex","offsetY","count","height","targetTop","targetBottom","viewBottom","newTop","spacer","ColumnLayout","columns","frozenCount","leaves","colIndex","walk","cols","depth","col","c","colDef","removeFromList","index","rows","span","childSpan","totalWidth","defaultWidth","visible","flexCols","fixedTotal","sum","flexTotal","FilterPanel","onApply","onClear","anchorEl","currentFilters","title","condRow","condSel","conditions","opt","valueInput","applyBtn","btnRow","clearBtn","rect","containerRect","DEFAULT_PREC","round","precision","factor","OGDecimal","coefficient","scale","str","isNeg","abs","dot","coeff","frac","other","ac","bc","o","result","dp","divisor","half","abs_c","rem","rounded","digits","intPart","fracPart","arr","acc","evaluateFormula","expr","ctx","divisionPrecision","_FormulaParser","src","_ctx","_prec","left","ch","right","start","numStr","applyMask","maskDef","def","char","_maskSSN","_maskPhone","_maskEmail","_maskCredit","_maskAccount","_maskName","_maskIP","_maskPartial","clean","sep","frontEnd","front","backFirst","maskLen","atIdx","local","domain","visLen","first4","last4","midLen","mid","parts","chunk","prefixLen","suffixLen","prefix","suffix","maskOctet","octet","_displayFormatterResolver","setDisplayFormatterResolver","resolveFormula","prec","formatNumber","format","currency","custom","num","semi","negFmt","useFmt","m","token","useGrouping","decimals","body","formatDate","y","day","_renderMasked","original","masked","wrap","text","eye","TextRenderer","formulaResult","column","displayText","colRevealed","rowRevealed","SelectRenderer","opts","fn","rawVal","vs","found","NumberRenderer","DateRenderer","CheckboxRenderer","chk","ButtonRenderer","btn","label","_c","BadgeRenderer","colorMap","labelMap","badge","color","LinkRenderer","hrefFn","target","TemplateRenderer","templateFn","ImageRenderer","img","w","h","_d","alt","_e","ProgressRenderer","max","raw","pct","track","fill","lbl","SparklineRenderer","values","W","H","chartType","canvas","min","n","bw","bh","pts","p","SwitchRenderer","on","sw","knob","RatingRenderer","star","RadioRenderer","radio","ImgRenderer","_sanitizeHtml","html","div","el","attr","href","HtmlRenderer","doSanitize","_C128W","_C128_STOP","_c128Bits","out","bar","_encodeC128B","codes","BarcodeRenderer","_barcodeSvg","bits","MW","QZ","TW","rects","x","createRenderer","renderer","GridRenderer","root","cbs","_el","totalHeight","headerHeight","headerRows","widths","_extraW","totalColWidth","table","extraRows","extraHeaderLeft","addExtraCol","tr","extraClass","th","_style","ri","allChk","cell","leafIdx","l","sortInfo","sortable","next","prev","leftOff","headerText","hasExplicitBreak","headerWrap","part","icon","filterIcon","hasFilter","resizer","capturedLeafIdx","_addResizer","fromIdx","selectedRows","checkedRows","groupFlatRows","onGroupToggle","onTreeToggle","extraOpts","mergeEngine","auto","_ew","_totalCW","frag","flatItem","isGroupRow","isTreeRow","g","groupKey","rowEl","top","extraW","stCell","st","labelPlaced","ci","hasSummary","fmt","arrow","treeNode","rowData","rowState","bg","localRowRi","colMap","extraBodyLeft","icons","colors","dnd","handle","numCell","chkCell","isEditable","isFirstCol","mergeInfo","ph","cellEl","rs","cs","mergedHeight","mergedWidth","dc","isFrozenCell","frozenLeftOff","_rawVal","_treeRenderTarget","treeCell","hasMoreChain","guide","conn","toggleWrap","nodeIcon","iconCls","_resolveTreeIcon","rendered","localRi","localCi","pc","rowTop","empty","hasChildren","expanded","tag","className","styles","_downloadText","content","filename","mime","blob","url","onChange","startX","startW","onMove","ev","onUp","RowManager","checked","totalRows","_ids","DateEditor","onCommit","onCancel","normalizeOptions","SelectEditor","optionsFn","resolved","cur","TextEditor","NumberEditor","CheckboxEditor","_onCancel","createEditor","editor","isToggleCol","rendType","CellEditManager","deps","startEvt","cancel","old","evt","FilterSelectPanel","config","onFilter","onReset","gridId","legend","uid","select","parentValue","vk","tk","enabled","all","fk","parentField","sel","Pagination","pageSize","size","page","end","total","sizeWrap","sizeLabel","sizeSel","info","mkBtn","disabled","_pageRange","current","pages","DragGhost","grabX","grabY","clientX","clientY","DropIndicator","cap","side","parent","clamp","lo","hi","RowDragDrop","_bodyEl","_rowHeight","_onDrop","_cross","_getDragCount","fromIndex","hit","tRect","tRelY","tIdx","bodyRect","relY","currentTarget","ghost","crossTarget","MergeEngine","cells","mc","colIndexes","spanStart","prevVal","curVal","DEFAULT_CONTEXT_ITEMS","ContextMenuManager","_anchor","_actions","customItems","items","menu","hr","ic","themeEl","theme","focused","onPositioned","width","vw","vh","btns","WorksheetManager","onSwitch","name","wasActive","oldName","newName","entries","tab","addBtn","input","commit","ExportManager","hex","rgbMatch","fname","sheetName","includeHeader","serialize","_s","fb","_row","utils","writeFile","ws","colWidths","colLayout","styleMode","hdrBgRgb","hdrFgRgb","rowBgRgb","rowAltRgb","rowFgRgb","borderRgb","fontSize","toRgb","fsStr","noStyle","S","isHdr","isEven","_v","addr","isNum","hAlign","wb","hdr","footerText","headerRow","bodyRows","footerHtml","win","wsManager","FooterManager","tok","numFmt","useComma","dpMatch","fixed","decPart","intStr","footerDefs","allData","op","nums","opUC","customOp","cv","cnt","numVal","formatted","valMap","leafCursor","colspan","cellW","targetLeaf","displayVal","KeyboardManager","editMgr","totalCols","nextRi","step","rowMgr","lines","dr","targetRi","targetCi","FindBarManager","closeBtn","_isGroup","buildGroups","summaryDefs","expandedKeys","getRowState","getKey","_groupByFields","parentKey","map","children","summary","summaryFmt","_calcSummary","states","_calcStates","defs","vals","_fmtNum","flattenGroups","groups","child","collectAllKeys","keys","nested","buildTree","parentIdField","expandOnLoad","nodeMap","roots","node","pid","assignDepth","nodes","_countDescendants","assignLineMeta","parentHasMoreChain","isLast","flattenTree","toggleTreeNode","nodeId","collectAllTreeIds","ids","GroupTreeManager","dl","getState","temp","open","ops","SortFilterManager","shiftKey","sortedItem","dirLabel","fieldOrList","filterItems","CellEventHandler","colEditable","grp","cellValue","rowEvt","isSelectCol","_f","_g","cellEvt","eventName","TriggerManager","operation","_cancelled","handlers","completeHandlers","NONE","buildMappingScript","mapping","tgt","buildTransform","sf","sameSchema","openCrossGridMapper","sourceFields","targetFields","resolve","srcSet","tf","overlay","box","head","optionHtml","esc","refreshScript","scriptWrap","scriptHead","copyBtn","pre","currentScript","txt","foot","cancelBtn","okBtn","done","close","onKey","CrossGridRegistry","bodyEl","grid","exclude","crossGridRegistry","OverrideKernel","host","layers","composed","innerOrig","layer","outer","reentrant","self","slot","ROW_ID_FIELD","_OpenGrid","msg","from","to","_origDestroy","toIdx","targetBodyEl","targetIndex","active","colIdx","fakeEvent","sheets","_name","sheet","_n","leaf","measured","headerH","toIndex","targetGrid","sourceIndexes","idxAsc","at","transform","indexes","mode","srcInfos","tgtInfos","mapEvt","newWidth","combined","pos","it","idxArr","idxs","reordered","moved","_all","_widths","_fitToGrid","fieldNames","_item","_pid","_pos","keyValue","fd","_h","OpenGrid"],"mappings":"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"}