# Changelog
All notable changes to OPEN_GRID will be documented in this file.
## [1.0.7] - 2026-06-27
### Fixed
- **워크시트(다중 시트) 데이터 미표시 버그 수정** — `addWorksheet()`로 시트를 추가하거나 탭을
전환할 때 헤더·탭은 그려지지만 **데이터 행이 렌더되지 않던** 문제를 고쳤다. 원인은 시트 전환
콜백이 내부 데이터만 갱신하고 가상 스크롤(virtual scroll)의 총 행수를 갱신하지 않아 보이는
행 범위가 비어 있었던 것. 시트 전환 시 `setData`와 동일한 경로(총 행수·aria·컬럼 폭 재계산)를
거치도록 통합해 시트마다 컬럼 구성이 달라도 올바르게 표시된다.
## [1.0.6] - 2026-06-26
### Changed
- 메타데이터·문서 정리(기능·동작 변경 없음). 발행 패키지를 경량화(소스맵 제외)했다.
## [1.0.5] - 2026-06-24
### Changed
- **런타임 의존성 0 (zero runtime dependencies)** — Excel 내보내기에 쓰이는 `xlsx`·`xlsx-js-style`을
`dependencies` → `devDependencies`로 옮겼다. 이들은 **빌드 시 `dist/`에 번들로 포함**되므로
(`src`의 `import('xlsx-js-style')`가 빌드 과정에서 `dist/xlsx.min-*.js` 청크로 변환됨),
설치하는 쪽에서 별도로 받을 필요가 없다 — `npm install open-grid`는 외부 런타임 의존성을
하나도 끌어오지 않는다. **Excel 내보내기는 번들된 SheetJS로 그대로 동작**한다(설치 불필요).
코드·동작 변경 없음(의존성 분류만 정정). 번들된 SheetJS는 Apache-2.0이며 `NOTICE`/`THIRD_PARTY_LICENSES.txt`로 귀속 표기됨.
## [1.0.4] - 2026-06-24
### Changed
- **소개 문구(intro) 추가** — README 상단과 npm `description`에 제품 소개 문구를 추가하고
npm 배지 버전 표기를 현행화했다. 코드·기능 변경 없음(문서/메타데이터만).
("zero-dependency **core**" — Excel 내보내기는 SheetJS를 번들하므로 "코어 무의존"으로 정확히 표기.)
## [1.0.3] - 2026-06-24
### Changed
- **라이선스 준수 내역을 배포 패키지에 명시** — 발행 tarball에 `CHANGELOG.md`를 포함하고,
README·변경 이력에 1.0.2의 라이선스 컴플라이언스 조치(아래)를 명확히 기재했다.
코드·기능 변경 없음(문서/배포 메타데이터만).
## [1.0.2] - 2026-06-24
### Fixed — 라이선스 컴플라이언스 (잠재적 라이선스 위반 소지 해소)
- **문제** — Excel 내보내기 기능에 쓰이는 `xlsx`(SheetJS Community Edition)와
`xlsx-js-style`는 **Apache License 2.0** 라이선스이며 빌드 결과물(`dist/`)에 번들되어
함께 배포된다. 그런데 1.0.1까지의 배포 패키지에는 OPEN_GRID 자체의 **MIT LICENSE만**
들어 있고, Apache-2.0가 재배포 시 요구하는 **라이선스 사본과 저작권 귀속 고지가 누락**
되어 있었다(Apache-2.0 §4(a)·§4(c) 미충족 → **잠재적 라이선스 위반 소지**).
- **해결** — 배포 패키지에 다음을 추가하고 `files`에 포함해 함께 배포한다:
- `THIRD_PARTY_LICENSES.txt` — Apache License 2.0 **전문** + 번들 구성요소 식별·저작권 고지
- `NOTICE` — SheetJS LLC(`xlsx`) 및 SheetJS LLC·Brent Ely(`xlsx-js-style`) 저작권 귀속
- README에 "Third-party licenses" 안내 추가
- **영향 범위** — OPEN_GRID 본체 라이선스(MIT)와 코드는 **변경 없음**. MIT와 Apache-2.0는
서로 호환되어 **라이선스 충돌은 없으며**, 누락돼 있던 Apache-2.0 **귀속 의무만 충족**시킨
조치다.
## [1.0.1] - 2026-06-24
### Fixed
- **그리드 초기화 크래시 수정** — `summary` 푸터를 사용하는 그리드를 생성할 때
`Cannot read properties of undefined (reading 'getStrategy')` 로 초기화가 실패하던 문제.
생성자에서 OverrideKernel 부착(및 strategy resolver 배선)을 최초 마운트 **이전**으로
옮겨, 초기 푸터/그룹 렌더가 strategy 슬롯을 조회할 때 커널이 항상 준비되도록 했다.
(피벗·집계 푸터·그룹 합계 등 `summary`/`footer` 옵션을 쓰는 모든 구성에 영향.)
## [1.0.0] - 2026-06-23
첫 정식 메이저 릴리스. 본문(코어) 코드 무수정으로 동작을 확장하는 `grid.override()` API와 헤더 줄바꿈을 추가.
### Added
- **`grid.override()` — 본문 무수정 동작 확장 API** (신규 `src/core/OverrideKernel.ts`)
- `grid.override(name, (orig, ...args) => result)` — 메서드 래핑. `orig()`는 `super`처럼 항상 호출 가능.
합성 순서는 FIFO 좌측폴드(나중에 건 것이 가장 바깥), 재진입 깊이 32 + 사이클 가드.
- `grid.override.strategy(slot, fn)` — 6개 알고리즘 슬롯 교체: 정렬 비교(sortComparator),
필터 술어(filterPredicate), 표시 포맷터(displayFormatter), 엑셀 직렬화(cellSerializer),
그룹 키(groupKeyFn), 집계 연산(summaryOp).
- `grid.restore(name)` / `grid.restoreAll()` — 원복. `destroy()` 시 자동 전체 복원.
- `OpenGrid.defaultOverride(name, fn)` / `OpenGrid.defaults.strategy(slot, fn)` — 전역(앞으로 생성될 모든 그리드) 기본 오버라이드.
- 오류는 기본(strict) 그대로 전파. 기존 메서드 본문은 한 줄도 수정하지 않음(C1 원칙 준수).
- **헤더 줄바꿈** — `ColumnDef.headerWrap?: boolean` + 헤더 문자열 `\n` 줄바꿈 + 헤더 높이 자동 확장.
- **override 데모 32종 × 5 프레임워크**(Vanilla/React/Vue/jQuery/Angular) — `examples/override/`, 허브 포함.
- **그리드 튜닝 참고자료 페이지** — 아키텍처/시퀀스 UML 다이어그램 기반 내부 동작 설명.
- **AI 에이전트용 override 가이드**(KO/EN) + 개발 가이드 override 챕터.
### Tests
- override 코어 + 헤더 줄바꿈 단위 테스트 추가. 전체 테스트 통과(회귀 0).
## [0.3.2] - 2026-06-18
### Fixed
- **셀 줄바꿈(col.wrap)이 실제로 꺾이지 않던 문제** — `.og-cell--wrap` 는 셀에 적용됐지만, 내부 텍스트
span(`.og-cell-text`)을 렌더러가 인라인 `white-space:nowrap` 으로 렌더해 클래스만으로는 못 이겼다.
`.og-cell--wrap .og-cell-text/.og-cell-date { white-space: normal !important; text-overflow: clip !important }`
로 인라인을 무력화. e2e 도 셀이 아닌 **내부 span + 실제 줄 수**를 검증하도록 강화.
(npm `open-grid@0.3.1` 은 이 수정 직전에 발행되어 wrap 미동작 → **0.3.2 로 재발행**, npm latest = 0.3.2.)
## [0.3.1] - 2026-06-17
### Fixed
- **Host CSS isolation — 임베드 시 호스트 테마 CSS inbound 상속으로 레이아웃/색상 깨짐** (foxnail.kr/WordPress 통합에서 발견)
- 원인: 헤더가 실제 `
`/`` 라서, 임베드 호스트(WordPress 등)의 element/높은 특이도 셀렉터
(`th,td`, `.entry-content th`, `.fn-post-content th` 등)가 그리드 헤더로 침범 — `line-height`, `border`,
`background`, `color`, `table{margin}` 등이 새어들어와 헤더가 깨지거나 호스트 색(navy/white)으로 칠해짐.
바디는 `` 라 안전. (헤더 ` ` 는 element 셀렉터라 그리드의 클래스/상속값을 이김)
- `src/core/GridRenderer.ts` — 헤더 ` | ` 의 모든 시각 속성을 **인라인으로 고정**(인라인이 호스트 셀렉터를 이김):
`background`/`color`/`line-height`/`font-size`/`vertical-align`/`border-top·left` (data + extra/rownumber/check 컬럼 전부).
헤더 `` 에 `og-header-table` 클래스 부여 + 인라인 `margin:0;border-spacing:0`.
- `src/styles/base.css` — `.og-container { line-height: normal }` (바디 셀 메트릭 격리) 및 헤더 클래스 기본 방어.
- **WordPress 전역 스타일 `:where([style*="border-color"]){border-style:solid}` 대응** — 그리드 인라인 보더가
`var(--og-border-color)` 를 참조해 "border-color" 문자열에 매칭되면, 폭 미지정 변에 `medium`(3px) 보더가
강제돼 헤더(`.og-header`)·그룹행·병합셀의 좌/우/상에 굵은 선이 생기고 바디 컬럼선과 어긋나던 문제 수정.
`GridRenderer.ts` 의 단일변 인라인 보더에 `border:0` 선행(미지정 변 폭 0 명시). 테마 무관(전 테마 동일 적용).
- **컨텍스트메뉴 위치 — 임베드 호스트의 transform 조상 아래에서 마우스 좌표를 벗어남** (그리드 너비 확대 시 두드러짐)
- `src/core/ContextMenu.ts` — 메뉴를 그리드 컨테이너 대신 `document.body` 에 부착 → `position:fixed` 가
항상 뷰포트 기준으로 동작. 테마 변수 보존을 위해 `data-og-theme` 복사 + `.og-context-menu` 에 `--og-cm-*` 정의 확장.
### Added
- **셀 툴팁** — `column.tooltip`(문자열|함수) 또는 그리드 옵션 `tooltips: true`(모든 셀에 값 자동 노출).
헤더 셀도 `title` 노출(잘린 헤더 가독성).
- **셀 줄바꿈(wrap)** — `column.wrap: true` 시 nowrap+ellipsis 대신 여러 줄 표시(`white-space:normal`).
가상 스크롤 고정 행 높이와 함께 `rowHeight` 확대 권장.
- 회귀 테스트: `test/e2e/host-isolation.spec.ts` + 적대적 호스트 픽스처 `examples/host-isolation/`
(line-height/border/margin/색상 격리 + 컨텍스트메뉴 transform 조상 + 툴팁/wrap, before/after 변별 — 10 케이스).
## [0.3.0] - 2026-06-05
### Added
- **개발 가이드 DB화 완성** — 39개 섹션 전체 SQLite DB화 (G1~G6)
- G1: 시작하기 (npm 설치, 퀵스타트, 기본 설정)
- G2: 데이터/옵션 (컬럼 정의, 데이터 옵션, 선택/체크박스/DnD/상태 관리)
- G3: 편집/이벤트 (셀 편집, 셀 타입, 마스킹, 병합, 이벤트, 트리거)
- G4: 그룹/페이징 (그룹, 트리, 푸터, 페이지네이션, 파인드바, 키보드)
- G5: 고급/내보내기 (피벗, 워크시트, SAP, XML, 수식, 조직도, Excel/CSV/인쇄)
- G6: 스타일/API (테마, 커스텀, 폰트, 사이징, 접근성, 그리드/컬럼/이벤트 API)
- **전 프레임워크 데모 완성** — React / Vue / jQuery / Angular / Vanilla 각 49개 섹션
- Angular A~H: AngularJS 1.x CDN 기반, `$scope.$apply` 없이 ng-show/ng-hide 패턴
- **Guide 렌더러** — `lang='html'` 감지 시 innerHTML 직접 주입 방식으로 전환 (pre/code 래핑 없음)
## [0.2.0] - 2026-06-04
### Fixed
- **Formula 셀 클릭 버그** — `CellEventHandler.ts`: formula 컬럼 cellClick 시 `e.value`가 `undefined`이던 문제 수정
- `row[col.field]` 대신 `evaluateFormula()`로 직접 계산 후 주입
### Added
- **React 데모** — `demo-react/index.php` 신규 (React 18 CDN, `useRef+useEffect+createRoot` 패턴)
- React 프레임워크 전 섹션(A~H, 49개) DB 삽입 완료
- 선택/필터셀렉트 API 버그 수정 (`getSelections()`, `valueMap` 기반 표시)
## [0.1.2] - 2026-05-30
### Added (Sprint 29 추가분)
- **변경 추적 API 보강**
- `getChanges()` — `{ added, edited, removed }` 한 번에 반환. edited 행에 `_changedFields` 포함
- `getEditedRows()` — 수정된 행만 반환 (기존 `getChangedRows()` 개선판)
- `getChangedColumns()` — `{ row, fields, diff[] }` 형태로 컬럼 단위 diff 반환 (oldValue/newValue 포함)
- `getOriginalRow(rowIndex)` — 수정 전 원본 행 데이터 반환
- **합계 / 소계 (Footer)**
- `setFooter(FooterDef[])` — 런타임 푸터 설정 (SUM/AVG/MIN/MAX/COUNT)
- `getFooterValue(field)` — 특정 필드 집계 결과 조회
- `getFooterData()` — 전체 집계 데이터 배열 조회
- OGDecimal 기반 정밀 계산 — 소수점 누적 오류 없음 (0.1 × 10 = 정확히 1.00)
- 데이터 수정/추가/삭제 시 푸터 자동 재계산
- **Guide** — Ch26(변경 추적), Ch27(합계/소계) 추가 → 총 27챕터
- **Vanilla 데모** — '변경 추적' 섹션, '합계/소계' 섹션 추가
## [0.1.1] - 2026-05-30
### Added (Sprint 29)
- **columnReorder** — `columnReorder: true` 옵션으로 헤더 드래그 컬럼 순서 변경 지원
- `onColumnReorder` 이벤트 콜백 (`{ fromIndex, toIndex, field }`)
- 드래그 중 시각 피드백 (`og-col-dragging` / `og-col-drop-over` CSS 클래스)
- **Guide** — 개발 가이드 4개 챕터 신규 추가 (Ch22~Ch25)
- Ch22: 데이터 마스킹 (10종 타입, 셀/컬럼 단위 해제, maskOnExport)
- Ch23: 조직도 (OrgChart API, setData, expandAll/collapseAll, 테마 연동)
- Ch24: 페이지네이션 (API, 서버사이드, React/Vue 예제)
- Ch25: 키보드 단축키 (WCAG 2.2 준수 표, aria-label 설정)
- **E2E Tests** — sprint29.spec.ts 25개 시나리오 추가
- checkColumn 선택/해제, 컨텍스트 메뉴 렌더링/닫힘, 테마 전환(data-og-theme), 키보드 네비게이션, 셀 편집, 정렬(aria-sort)
### Changed
- `GridRenderer` 내부 콜백에 `onColDragStart` / `onColDrop` / `getColDragIdx` 추가
## [0.1.0] - 2026-05-24
### Added
- **Core Engine**
- `OpenGrid` class — main grid instance with `new OpenGrid(container, options)` API
- `DataLayer` — CRUD, state tracking (added/edited/removed), sort, filter
- `VirtualScroll` — rAF-based rendering with row pooling (100k+ rows)
- `ColumnLayout` — group headers, frozen columns, flex widths
- `EventEmitter` — on/once/off/emit event system
- **Cell Renderers** (8 types)
- text, number (format), date, checkbox, button, badge, link, template
- **Cell Editors** (5 types)
- text, number, select, date, checkbox
- Inline editing: click / dblclick / F2 entry, Enter/Tab/Esc exit
- **Grouping + Summary**
- `groupBy(fields[])` — multi-level hierarchical grouping
- `summary` option — SUM / AVG / MIN / MAX / COUNT per column
- `expandAll()` / `collapseAll()` / `clearGroup()`
- **Tree Grid**
- `enableTree()` / `disableTree()` — flat-to-tree via `treeId` / `treeParentId`
- `expandNodes(ids)` / `expandAllNodes()` / `collapseAllNodes()`
- Indent + toggle arrow rendering per depth level
- **Cell Merge**
- `mergeCells([{row, col, rowSpan?, colSpan?}])` — manual merge
- `autoMerge(fields[])` — auto rowSpan for consecutive identical values
- `clearMerge()` — remove all merges
- **Row Drag & Drop**
- `draggable: true` option
- Ghost row + drop indicator
- `reorderRow(from, to)` public API
- `onRowDrop` callback
- **Filter UI**
- Column header filter icon
- 9 operators: `=`, `!=`, `contains`, `startsWith`, `endsWith`, `>`, `<`, `>=`, `<=`
- **Export**
- `exportExcel(options?)` — SheetJS xlsx (dynamic import, code-split)
- `exportCsv(options?)` — BOM-aware CSV
- `exportJson(options?)` — JSON download
- **Pagination**
- `pagination: true` + `pageSize` option
- Page size selector (10/20/50/100/200)
- First/Prev/Next/Last navigation
- **Keyboard Navigation**
- Arrow keys — cell navigation
- Tab / Shift+Tab — next/prev cell
- F2 / Enter — start edit
- Escape — cancel edit / clear focus
- Ctrl+C / Ctrl+V — clipboard
- **UI**
- Column resize (drag)
- Multi-sort (Shift+click)
- Dark theme (`theme: 'dark'`)
- CSS Variables — full theme customization
- `setTheme(theme)` / `setThemeVar(key, value)`
- **Vue 3 Component** (`open-grid/vue`)
- Composition API, `defineProps` / `defineEmits`
- Reactive `data` / `columns` watchers
- `grid` instance exposed via `defineExpose`
- **React 18 Component** (`open-grid/react`)
- Hooks-based (`useRef`, `useEffect`)
- `OpenGridReact` + `OpenGridWithRef` (forwardRef)
- `stateColumn`, `draggable`, `onRowDrop` props
- **API Naming** — distinctive, self-consistent method names
- `readCell`, `writeCell` for cell access
- `orderBy` for sorting
- `jumpToRow` for scrolling
- `getSelections` for selection
- (40+ purpose-built method names)
### Performance
- Multi-sort 100k rows: 1789ms → **40ms** (44× improvement via Schwartzian transform)
- Single sort 100k rows: ~38ms
- Filter 100k rows: ~17ms
- Group build 100k rows: ~3ms (5 groups)
- Tree build 100k rows: ~25ms
### Tests
- 124 unit tests across 7 test files
- EventEmitter (7), DataLayer (14), GroupEngine (18), TreeEngine (20),
MergeEngine (16), CellEditor (23), CellRenderer (26)
| |