@iyulab/flex-table 0.23.2 → 0.25.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.
- package/CHANGELOG.md +558 -0
- package/dist/{flex-table-D-OLUYir.js → flex-table-DZFtW02v.js} +27 -12
- package/dist/flex-table.js +1 -1
- package/dist/react.js +1 -1
- package/package.json +15 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.25.0] - 2026-08-07
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`--ft-font-size` now reads `var(--u-density, 14px)`.** When a consumer sets the design
|
|
8
|
+
system's `--u-density` switch on an ancestor, the table's base font size (and everything
|
|
9
|
+
derived from it) follows automatically. Unset, behavior is unchanged.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Hovering an odd (striped) row produced no visible feedback in dark mode.** Odd rows sit on
|
|
14
|
+
the raised-surface background, and the hover style used the same global hover token that raised
|
|
15
|
+
happened to equal in dark — so the row simply didn't respond. Odd-row hover now reads a
|
|
16
|
+
dedicated raised-surface hover token when the design system sheet provides one, falling back to
|
|
17
|
+
the previous behavior otherwise. Even rows are unaffected.
|
|
18
|
+
|
|
19
|
+
## [0.24.0] - 2026-08-05
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- ⚠**`@iyulab/components` is now a required peer dependency (`>=1.24.0`).** The
|
|
24
|
+
stylesheet is not decoration here — 313 token references depend on it, and without
|
|
25
|
+
it the fallback literals silently stand in for the real theme. Declaring the peer as
|
|
26
|
+
optional would keep allowing exactly the situation the fallbacks were meant to reveal.
|
|
27
|
+
|
|
28
|
+
Consumers pinned to `@iyulab/components@1.23.x` will see an `ERESOLVE` on install.
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`sideEffects` no longer misses the shared chunk.** With more than one entry point,
|
|
33
|
+
the bundler splits common code — including the custom-element registrations — into a
|
|
34
|
+
hash-named chunk. The declaration listed only the named entries, so a consumer's
|
|
35
|
+
bundler could drop that chunk and the elements would never register, with no error at
|
|
36
|
+
build time. It now covers the emitted output as a whole (`./dist/*.js`), which is
|
|
37
|
+
hash-stable across builds.
|
|
38
|
+
|
|
39
|
+
- **The `./react` and `./odata` subpaths point back at the built output.** They had been
|
|
40
|
+
rewritten to source paths, which do not exist in the published package.
|
|
41
|
+
|
|
42
|
+
## [0.23.2] - 2026-08-04
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **OData 요청 실패 기본 문구가 영어가 된다** — `요청 실패 (500)` → `Request failed (500)`.
|
|
47
|
+
서버가 오류 메시지를 주면 **그쪽이 이긴다**(종전과 같다) — 이 문구는 서버가 아무것도 주지
|
|
48
|
+
않을 때의 폴백이다.
|
|
49
|
+
|
|
50
|
+
⚠**로케일 레지스트리를 도입하지 않았다.** 문자열 하나를 위해 런타임 의존을 들이는 것은
|
|
51
|
+
비용이 이득을 넘는다(이 패키지의 의존은 `lit` · `odata-query` 둘뿐이다). 수요가 모이면 그때
|
|
52
|
+
같은 형태로 연다.
|
|
53
|
+
|
|
54
|
+
All notable changes to this project will be documented in this file.
|
|
55
|
+
|
|
56
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
57
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
58
|
+
|
|
59
|
+
## [Unreleased]
|
|
60
|
+
|
|
61
|
+
## [0.23.1] - 2026-08-03
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- 🔴**토큰 폴백 리터럴 48곳이 디자인 시스템 값이 아니었다.** `var(--u-토큰, #리터럴)` 의
|
|
66
|
+
리터럴은 **정의상 시트 값의 복제**이고, 시트를 로드하지 않은 소비자가 실제로 보는
|
|
67
|
+
값이다. 그런데 이 표의 48곳은 낡은 것이 아니라 **처음부터 다른 팔레트**였다.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
--u-primary-color #1a73e8 → #1976D2 (7곳)
|
|
71
|
+
--u-txt-color #202124 → #212121 (6곳)
|
|
72
|
+
--u-bg-color-raised #f8f9fa → #FAFAFA (6곳)
|
|
73
|
+
--u-txt-color-weak #5f6368 → #757575 (6곳)
|
|
74
|
+
--u-bg-color-active #e8eaed → #EEEEEE (3곳) … 외 7종
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
⚠**시트를 로드하는 소비자에게는 변화가 없다** — 폴백은 그 경우 아예 평가되지 않는다.
|
|
78
|
+
**시트 없이 쓰던 소비자**는 표의 색이 디자인 시스템 기본값으로 바뀐 것을 본다. 그것이
|
|
79
|
+
이 폴백이 원래 뜻하던 값이다.
|
|
80
|
+
|
|
81
|
+
⚠**개발 환경에서는 드러날 수 없는 부류의 결함이다.** 시트가 있으면 폴백은 평가되지
|
|
82
|
+
않으므로, 어긋난 값은 *우리가 보지 못하는 화면*에서만 나타난다.
|
|
83
|
+
|
|
84
|
+
## [0.23.0] - 2026-08-03
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
|
|
88
|
+
- ★**표의 밀도와 머리행 위계를 조절할 수 있다.** 색은 0.22.0 에서 열렸지만 **치수는 닫혀
|
|
89
|
+
있었다** — 한 화면에 이 표와 다른 표가 함께 놓이는 경우, 소비자는 색만 맞추고 밀도·위계는
|
|
90
|
+
맞추지 못했다. 그리고 *"고칠 수 있는 쪽만 고치면 더 갈라지므로"* 실제로는 **양쪽 다
|
|
91
|
+
포기하는** 선택으로 밀린다.
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
--ft-row-height 32px 행 높이
|
|
95
|
+
--ft-cell-padding-block 6px 그 높이 안에서 글자의 자리
|
|
96
|
+
--ft-cell-padding-inline 12px
|
|
97
|
+
--ft-header-font-size 기본값 = --ft-font-size
|
|
98
|
+
--ft-header-font-weight 600
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**기본값이 종전 렌더값과 같다** — 아무것도 선언하지 않은 소비자의 화면은 바뀌지 않는다.
|
|
102
|
+
|
|
103
|
+
⚠**`--ft-row-height` 만 성질이 다르다.** 이 표는 가상 스크롤이라 행이 `index × rowHeight`
|
|
104
|
+
로 절대 배치되고 셀 높이가 인라인으로 박힌다 — ***행 높이는 캐스케이드로 닿지 않는다.***
|
|
105
|
+
그래서 이 토큰은 **첫 렌더에 한 번 판독**되어 가상화 계산에 들어간다. 이후에 바꾸려면
|
|
106
|
+
`rowHeight` 프로퍼티(또는 `row-height` 속성)를 쓴다. 명시 지정은 **항상 토큰을 이기고**,
|
|
107
|
+
`px` 이외 단위는 무시된다.
|
|
108
|
+
|
|
109
|
+
⚠**행 높이는 고정이고 여백은 그 안에서 글자를 배치한다.** 셀은 설계상 한 줄이다
|
|
110
|
+
(`nowrap` + 말줄임). 행 높이를 줄이면 여백도 함께 줄일 것 —
|
|
111
|
+
`padding-block × 2 + 한 줄 높이 ≤ row-height` 를 넘으면 아래가 잘린다.
|
|
112
|
+
|
|
113
|
+
## [0.22.0] - 2026-08-03
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- ★**표 색이 `@iyulab/components` 디자인 토큰에서 파생한다.**
|
|
118
|
+
|
|
119
|
+
종전에는 자체 팔레트를 리터럴로 갖고 있어, 소비자가 셸·버튼의 브랜드를 맞춰도
|
|
120
|
+
**표만 다른 색 체계**로 남았다. 업무앱에서 표는 화면 면적의 대부분이라 나머지를
|
|
121
|
+
아무리 맞춰도 체감이 바뀌지 않는다. 이제 `--u-primary-color` 한 줄로 표의 강조색·
|
|
122
|
+
선택 표시·불리언 표시가 함께 따라온다.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
--ft-active-color → --u-primary-color (강조 · 정렬 활성 · 포커스)
|
|
126
|
+
--ft-selection-bg → --u-primary-bg-color (선택된 셀/행)
|
|
127
|
+
--ft-bg / -row-even-bg → --u-bg-color
|
|
128
|
+
--ft-header-bg → --u-bg-color-raised (크롬 면)
|
|
129
|
+
--ft-row-hover-bg → --u-bg-color-hover
|
|
130
|
+
--ft-text-color → --u-txt-color
|
|
131
|
+
--ft-border-color → --u-border-color
|
|
132
|
+
--ft-sort-…/-empty-… → --u-txt-color-weak
|
|
133
|
+
--ft-editor-bg → --u-input-bg-color
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
⚠**의존성이 늘지 않는다.** CSS 커스텀 프로퍼티 참조는 `import` 를 만들지 않는다 —
|
|
137
|
+
`package.json` 은 그대로다.
|
|
138
|
+
|
|
139
|
+
⚠**시트 없는 독립 사용은 종전과 같다.** 모든 참조가 리터럴 폴백을 갖고 다크 블록도
|
|
140
|
+
남아 있어, 토큰 시트를 로드하지 않으면 예전 색·예전 자동 다크로 렌더된다.
|
|
141
|
+
회귀 테스트가 이 둘을 함께 지킨다.
|
|
142
|
+
|
|
143
|
+
**소비자 영향**: 토큰 시트를 쓰는 앱에서는 **표 색이 바뀐다** — Google 계열
|
|
144
|
+
(`#1a73e8` 등)에서 디자인 시스템 팔레트로 이동한다. 종전 색을 유지하려면 `--ft-*` 를
|
|
145
|
+
직접 지정하면 된다(그 경로는 그대로다).
|
|
146
|
+
|
|
147
|
+
### Fixed
|
|
148
|
+
|
|
149
|
+
- **상태 색이 규칙 안에 박혀 있어 덮을 수 없고 테마를 몰랐다** — 무효 셀, 드롭 표시,
|
|
150
|
+
찾기 강조가 리터럴이라 다크에서도 라이트 값 그대로였다. `--ft-invalid-*`·`--ft-drop-*`·
|
|
151
|
+
`--ft-find-*` 로 열고 상태 색에서 알파를 뽑는다.
|
|
152
|
+
|
|
153
|
+
★**면 토큰이 아니라 알파 파생인 이유**: 이 배경들은 불투명 면이 아니라 **겹침**이다 —
|
|
154
|
+
줄무늬(홀/짝 행)와 선택 표시가 아래에서 비쳐야 "어느 행의 어떤 셀"인지 읽힌다.
|
|
155
|
+
부수 효과로 두 테마 모두에서 성립한다.
|
|
156
|
+
|
|
157
|
+
- **댓글 입력 포커스 링이 팔레트에 없는 색이었다**(`rgba(59,130,246,.2)` — Tailwind
|
|
158
|
+
blue-500). 바로 옆 줄의 테두리는 `--ft-active-color` 를 쓰고 있어 **두 색이 서로 달랐다.**
|
|
159
|
+
|
|
160
|
+
## [0.21.1] - 2026-08-02
|
|
161
|
+
|
|
162
|
+
### Fixed
|
|
163
|
+
|
|
164
|
+
- **빈 셀 문구가 라이트 테마에서 WCAG AA 에 미달하던 문제.** `--ft-empty-color` 가 `#999`
|
|
165
|
+
로 흰 바탕 대비 **2.85** 였다(AA 기준 4.5). 정렬 표시와 같은 회색인 `#5f6368`(**6.05**)로
|
|
166
|
+
맞췄다 — 팔레트를 한 계열로 유지한다.
|
|
167
|
+
|
|
168
|
+
다크 값(`#9aa0a6` on `#1e1e2e` = 6.31)은 원래 정상이었으므로 손대지 않았다.
|
|
169
|
+
**라이트 한쪽만의 결함**이었다.
|
|
170
|
+
|
|
171
|
+
### Known issues
|
|
172
|
+
|
|
173
|
+
- `--ft-border-color` 가 바탕 대비 **1.32**(라이트) · **1.59**(다크)로 WCAG 1.4.11(3.0)에
|
|
174
|
+
미달한다. 표 격자선을 "UI 컴포넌트 경계"로 볼지가 판단을 요구하고, 값을 올리면 표의
|
|
175
|
+
시각 무게가 크게 바뀌므로 이번에 손대지 않았다. 나머지 조합(본문·헤더·선택행·호버행·
|
|
176
|
+
활성색·불리언 표시)은 두 테마 모두 통과한다.
|
|
177
|
+
|
|
178
|
+
## [0.21.0] - 2026-07-17
|
|
179
|
+
|
|
180
|
+
### Fixed
|
|
181
|
+
- `useODataSource`: 검색어를 인용 없이 `$search`로 전송해 **숫자·하이픈이 포함된 검색어가 전부 400**으로 거부되던 결함 수정. 이제 공백으로 나눈 토큰을 각각 인용된 phrase로 감싸 `AND`로 결합해 전송한다 (`red shirt` → `$search="red" AND "shirt"`). 실사용에서 관측(상품코드·주문번호·연도처럼 숫자·하이픈을 포함한 검색이 전부 무응답).
|
|
182
|
+
- **원인은 문법 제약이 아니라 버전 스큐**: OData 4.0의 `searchWord`는 문자(Unicode L/Nl)만 허용하나, 4.01은 `searchChar`(`unreserved` 포함 — 숫자·`-`·`.`·`_`·`~`)로 완화했다. Microsoft.OData 렉서가 아직 4.0 규칙이라 `2026`·`ZT-E2E-A`를 거부한다([odata.net#2445](https://github.com/OData/odata.net/issues/2445), OPEN). `searchPhrase`는 4.0·4.01 양쪽에서 적법해 서버 버전과 무관하게 안전하다.
|
|
183
|
+
- **통째가 아니라 토큰별로 감싸는 이유**: 인용 없는 다중 단어는 암묵 AND로 파싱된다(`searchAndExpr = RWS [ 'AND' RWS ] searchExpr`). 전체를 한 phrase로 감싸면 연속 문자열 매칭으로 의미가 바뀌므로, 토큰별 인용이 기존 의미론을 보존한다.
|
|
184
|
+
- `"`는 phrase에 담을 수 없고 OData가 이스케이프를 정의하지 않아 검색어에서 제거한다. 공백뿐인 검색어는 `$search`를 붙이지 않는다.
|
|
185
|
+
- **거동 변경 주의**: 단일 토큰도 word에서 phrase로 바뀐다. `$search`의 매칭 정의는 스펙상 implementation-specific이라 서버에 따라 결과가 달라질 수 있어 patch가 아닌 minor로 올린다.
|
|
186
|
+
- `eslint.config.js`에 `eslint-plugin-react-hooks`가 등록된 적이 없는데 `use-odata-source.ts`가 `react-hooks/exhaustive-deps` disable 지시자를 사용해 **`npm run lint`가 계속 exit 1**이던 결함 수정. 존재하지 않는 규칙을 가리키는 고아 지시자를 제거하고 deps가 부분집합인 이유는 산문 주석으로 보존했다.
|
|
187
|
+
|
|
188
|
+
### Added
|
|
189
|
+
- `src/odata/` 단위 테스트 신설(11건) — 이 디렉터리는 테스트가 전무했고, 그것이 위 `$search` 결함이 배포된 원인이다. `$search` 쿼리 문자열을 `odata-query` 통합까지 포함해 검증한다.
|
|
190
|
+
|
|
191
|
+
### Documentation
|
|
192
|
+
- README `OData Source Hook`: **반환값 표 신설**. 기존엔 옵션만 문서화되어 `setSearch`·`error` 등 반환 필드의 계약을 알 수 없었다. `error`는 렌더하지 않으면 실패한 요청이 그리드를 조용히 비운다는 점을 명시.
|
|
193
|
+
- README `Search semantics` 신설: `setSearch`가 OData 검색 표현식이 아닌 **리터럴 텍스트**를 받는다는 계약과 인용 근거를 문서화.
|
|
194
|
+
|
|
195
|
+
## [0.20.1] - 2026-07-03
|
|
196
|
+
|
|
197
|
+
### Fixed
|
|
198
|
+
- `FlexTable`: `clearSelectionOnDataChange` 활성화 시 React 래퍼(`FlexTableReact`, `@lit/react`) 경유하면 체크박스 행 선택 자체가 불가능하던 결함 수정. `@lit/react`가 dirty-check 없이 매 렌더마다 `.data`를 재대입하는데, `set data()`가 참조 동일성 비교 없이 무조건 `deselectAll()`을 호출해 "선택 → setState → 리렌더 → data 재대입 → 선택 해제" 루프가 발생했다. 이제 `set data()`는 참조가 실제로 바뀐(외부 교체) 경우에만 선택 해제/undo 클리어 side-effect를 실행한다(`clearUndoOnDataChange`도 동일 가드 적용). 동일 참조 재대입에도 `hasChanged: () => true`에 의한 in-place 리렌더는 유지된다. 실사용에서 관측(기존 우회: `gridKey` remount).
|
|
199
|
+
|
|
200
|
+
## [0.20.0] - 2026-07-02
|
|
201
|
+
|
|
202
|
+
### Added
|
|
203
|
+
- `FlexTable`/`FlexTableReact`: `loading?: boolean` prop 추가. `true`일 때 그리드 위에 내장 오버레이를 표시하고 host에 `aria-busy="true"`를 반영한다. `useODataSource()`가 반환하는 `loading`과 자연 연동(`<FlexTableReact loading={source.loading} .../>`). 이전에는 각 소비 페이지가 `style={{opacity: loading ? 0.6 : 1}}` 같은 인라인 opacity 해킹으로 우회하고 있었다.
|
|
204
|
+
|
|
205
|
+
## [0.19.1] - 2026-07-02
|
|
206
|
+
|
|
207
|
+
### Documentation
|
|
208
|
+
- README: `format` vs `renderer` 가이드 추가 — `ColumnDefinition.format`이 인터페이스 표에서 누락되어 있었고, 두 옵션의 차이(원본 값 유지 vs 렌더 전체 대체)와 우선순위(`renderer` > `format`)가 문서화되어 있지 않았음
|
|
209
|
+
- README: React `ref` 명령형 API 사용 예시 추가 — `FlexTableReact`가 `ref`를 내부 `FlexTable` 엘리먼트로 포워딩해 `addRow`/`deleteRows`/`selectAll` 등 [Methods](#methods)를 리렌더 없이 호출 가능함을 명시
|
|
210
|
+
|
|
211
|
+
## [0.19.0] - 2026-07-02
|
|
212
|
+
|
|
213
|
+
### Added
|
|
214
|
+
- `useODataSource`: `fetcher`(커스텀 transport), `baseUrl`(origin override), `onUnauthorized`(401/403 콜백) 옵션 추가
|
|
215
|
+
- 기본값은 기존 동작(전역 `fetch` + `window.location.origin`)과 동일 — 하위 호환
|
|
216
|
+
- 소비 앱이 인증 헤더 주입·세션 만료 처리를 `HttpClient` 등 자체 transport로 일원화 가능 (전역 `window.fetch` 몽키패치 우회 불필요)
|
|
217
|
+
- `ColumnDefinition<T>`/`CellRenderer<T>`/`CellEditor<T>`/`CellValidator<T>`/`ConditionalRule<T>` 제네릭화, `FlexTableReact<T>` React 래퍼 제네릭 지원
|
|
218
|
+
- 기본값 `T = DataRow`로 기존(비제네릭) 사용 100% 하위 호환. `<FlexTableReact<Order> data={orders} columns={columns} />`처럼 실제 행 타입을 지정하면 `renderer`/`editor`/`validator`/`format` 콜백까지 타입 추론됨 — 소비 측 `as unknown as` 캐스트 불필요
|
|
219
|
+
- 내부 커스텀 엘리먼트(`FlexTable`)는 DOM 특성상 인스턴스별 제네릭이 불가능하므로 계속 `DataRow` 기반으로 동작 — 캐스트는 `FlexTableReact` 경계에서 라이브러리가 1회 수행(소비자에게는 보이지 않음)
|
|
220
|
+
- `clearSelectionOnDataChange` 속성(`clear-selection-on-data-change`) 추가 — 활성화 시 `data`가 외부에서 교체될 때 행 선택(체크박스)을 자동 해제하고 빈 선택으로 `selection-change`를 재발화
|
|
221
|
+
- 기본값 `false`(기존 `clearUndoOnDataChange`와 동일 컨벤션) — 하위 호환
|
|
222
|
+
- **안전 목적**: 행 선택은 인덱스 기반이라, `data`가 동일 길이의 다른 행으로 교체돼도 선택 상태가 그대로 남아 잘못된 행에 일괄 작업(상태전이/입금 등)이 적용될 위험이 있음. 선택이 벌크 액션을 구동하는 `selectable` 그리드(특히 서버 모드 + `useODataSource` 조합)에는 이 옵션 활성화를 권장
|
|
223
|
+
|
|
224
|
+
## [0.18.0] - 2026-05-19
|
|
225
|
+
|
|
226
|
+
### Added
|
|
227
|
+
- **셀 코멘트 편집 팝업**: 우클릭 컨텍스트 메뉴에서 코멘트를 직접 편집
|
|
228
|
+
- 코멘트 없는 셀: "Add Comment" 메뉴 항목 표시
|
|
229
|
+
- 코멘트 있는 셀: "Edit Comment" + "Delete Comment" 메뉴 항목 표시
|
|
230
|
+
- 편집 팝업: textarea + Cancel/Save 버튼
|
|
231
|
+
- 단축키: Ctrl+Enter 저장, Escape 취소
|
|
232
|
+
- 팝업 외부 클릭 시 자동 저장
|
|
233
|
+
- 편집 결과는 `setComment()` API와 동일하게 undo/redo 연동
|
|
234
|
+
|
|
235
|
+
## [0.17.0] - 2026-05-19
|
|
236
|
+
|
|
237
|
+
### Added
|
|
238
|
+
- **Undo/Redo 갭 보완**: 주요 API에 undo/redo 지원 추가
|
|
239
|
+
- `importFromFile()` undo/redo 지원 — import 전 데이터 상태로 복원 가능
|
|
240
|
+
- `setComment()` undo/redo 지원 — 이전 코멘트 상태로 복원 가능
|
|
241
|
+
- `clearComments()` undo 지원 — 전체 코멘트 복원 가능
|
|
242
|
+
- `hideColumn()` / `showColumn()` undo/redo 지원 — 컬럼 가시성 복원 가능
|
|
243
|
+
- **Ctrl+Y** Redo 단축키 (Excel/브라우저 표준)
|
|
244
|
+
- **공개 API**: `undo()`, `redo()`, `clearUndoHistory()` 메서드 추가
|
|
245
|
+
- 외부 툴바/버튼에서 직접 호출 가능
|
|
246
|
+
- **`clear-undo-on-data-change`** 속성 (`clearUndoOnDataChange: boolean`, 기본값: `false`)
|
|
247
|
+
- `true`로 설정 시 외부에서 `table.data = ...`를 통해 데이터를 교체하면 undo/redo 히스토리 자동 clear
|
|
248
|
+
- 내부 undo/redo 동작은 영향받지 않음
|
|
249
|
+
|
|
250
|
+
### Internal
|
|
251
|
+
- `_applyComment()` 내부 메서드 분리 (undo/redo 재귀 호출 방지)
|
|
252
|
+
- `_inUndoRedo: boolean` 플래그로 내부 undo/redo 경로 식별 (`clearUndoOnDataChange` 연동)
|
|
253
|
+
- `data` 속성을 getter/setter 패턴으로 전환 (backing field `_data`, Lit reactive property 유지)
|
|
254
|
+
- 키보드 핸들러(Ctrl+Z/Y)가 공개 `undo()`/`redo()` 메서드를 재사용 (DRY)
|
|
255
|
+
|
|
256
|
+
## [0.16.1] - 2026-05-19
|
|
257
|
+
|
|
258
|
+
### Fixed
|
|
259
|
+
- Fill handle position offset: `_colLeftOffsets` already includes `_prefixWidth`, but `_renderFillHandle` and `_renderFillPreview` were adding it again, causing the handle to appear displaced to the right (especially noticeable with row numbers or checkbox columns enabled)
|
|
260
|
+
|
|
261
|
+
## [0.16.0] - 2026-05-19
|
|
262
|
+
|
|
263
|
+
### Added
|
|
264
|
+
- **XLSX Import**: `.xlsx` 및 `.csv` 파일을 테이블에 가져오기
|
|
265
|
+
- `importFromFile(file: File): Promise<void>` API
|
|
266
|
+
- `import-enabled` 속성으로 드래그&드롭 활성화 (파일 드롭 오버레이 포함)
|
|
267
|
+
- 첫 행 헤더 → 기존 컬럼 key 자동 매칭 (exact 우선, 대소문자 무관 fallback)
|
|
268
|
+
- 컬럼 타입에 따라 자동 형 변환 (number, boolean, text)
|
|
269
|
+
- `data-import` CustomEvent (`detail.count`: 가져온 행 수)
|
|
270
|
+
- 외부 의존성 없는 순수 TypeScript 구현 (ZIP 중앙 디렉터리 파싱, OOXML DOMParser, DEFLATE/STORE 지원)
|
|
271
|
+
- **셀 코멘트**: 셀 단위 메모/코멘트 부착
|
|
272
|
+
- `setComment(dataIndex, colKey, text|null)` API — 빈 문자열/null 전달 시 제거
|
|
273
|
+
- `getComment(dataIndex, colKey)` API
|
|
274
|
+
- `getAllComments()` — 전체 코멘트 배열 반환
|
|
275
|
+
- `clearComments()` — 전체 코멘트 삭제
|
|
276
|
+
- `comment-change` CustomEvent (`detail: { dataIndex, colKey, text }`)
|
|
277
|
+
- 코멘트 있는 셀 우상단에 오렌지색 삼각형 인디케이터 표시, hover 시 title tooltip
|
|
278
|
+
|
|
279
|
+
### Internal
|
|
280
|
+
- `src/export/xlsx-reader.ts`: ZIP 리더 + OOXML 파서 (shared strings, 셀 타입 처리, 날짜 시리얼 변환)
|
|
281
|
+
- `_comments: Map<number, Map<string, string>>` 내부 저장소 (dataIndex → colKey → text)
|
|
282
|
+
- `_applyImportedSheet`, `_applyImportedRows`, `_buildHeaderColumnMap` 내부 메서드
|
|
283
|
+
- `_onDragover`, `_onDragleave`, `_onDrop` 드래그&드롭 핸들러
|
|
284
|
+
- `.ft-import-overlay`, `.ft-has-comment`, `.ft-comment-indicator` 스타일 추가
|
|
285
|
+
|
|
286
|
+
## [0.15.0] - 2026-05-19
|
|
287
|
+
|
|
288
|
+
### Added
|
|
289
|
+
- **고급 필터 — 텍스트 모드**: 필터 드롭다운에 모드 셀렉터 추가 (`contains` / `starts with` / `ends with` / `wildcard`). 와일드카드는 `*`(임의 문자열), `?`(단일 문자) 지원
|
|
290
|
+
- **고급 필터 — 빈 셀 필터**: 모든 컬럼 타입 (text/number/date/boolean)에 "Empty only" / "Non-empty only" 옵션 추가. 텍스트 입력 시 자동 해제
|
|
291
|
+
- **고급 필터 — 숫자 2조건 AND/OR**: 숫자 필터가 `=`, `≠`, `>`, `<`, `≥`, `≤` 연산자 선택 + 2개 조건 AND/OR 결합으로 대체. 단일 조건만 설정해도 동작
|
|
292
|
+
- **행 고정 (`frozen-rows`)**: `frozenRows: number` 속성으로 상단 N행 고정. 세로 스크롤 중 항상 표시. 편집 가능, 핀 컬럼과 올바르게 교차 렌더링, `position: sticky` 기반
|
|
293
|
+
|
|
294
|
+
### Changed
|
|
295
|
+
- 숫자 필터 UI: 기존 Min/Max 범위 입력 → 연산자 선택 + 2조건 AND/OR UI로 교체
|
|
296
|
+
- 필터 드롭다운 최소 너비 160px → 200px
|
|
297
|
+
|
|
298
|
+
### Internal
|
|
299
|
+
- `TextFilterMode` 타입 추가 (`contains` | `starts` | `ends` | `wildcard`)
|
|
300
|
+
- `NumericOp`, `NumCondition`, `NumberAdvState` 타입 추가
|
|
301
|
+
- `_buildTextPredicate`, `_buildNumberPredicate`, `_buildDatePredicate`, `_buildEmptyPredicate` predicate 빌더 메서드 추가
|
|
302
|
+
- `_applyFilterForKey`: 필터 재적용 단일 진입점으로 리팩터링
|
|
303
|
+
- `_frozenRowCount`, `frozenRowsHeight` getter 추가
|
|
304
|
+
- `_renderFrozenRows`: sticky 컨테이너에 frozen rows 렌더링
|
|
305
|
+
|
|
306
|
+
## [0.14.0] - 2026-05-19
|
|
307
|
+
|
|
308
|
+
### Added
|
|
309
|
+
- **내장 컨텍스트 메뉴 (`show-context-menu`)**: 셀 우클릭 시 기본 메뉴 표시 (복사, 행 삽입·삭제, 컬럼 숨기기, 정렬, 필터)
|
|
310
|
+
- `context-menu` 이벤트에서 `preventDefault()` 호출 시 내장 메뉴 억제
|
|
311
|
+
- 화면 경계 자동 위치 보정
|
|
312
|
+
- **XLSX Export**: `exportToFile('xlsx', ...)` / `exportToString('xlsx')` 지원
|
|
313
|
+
- 외부 의존성 없는 순수 TypeScript 구현 (ZIP STORE + OOXML)
|
|
314
|
+
- 헤더 행 포함, 숫자/날짜/불리언 셀 타입 지원, 헤더 bold 스타일
|
|
315
|
+
|
|
316
|
+
### Changed
|
|
317
|
+
- `ExportFormat`에 `'xlsx'` 추가
|
|
318
|
+
- `exportToString` 반환 타입: `string | Uint8Array` (xlsx는 Uint8Array)
|
|
319
|
+
- `context-menu` CustomEvent가 이제 `cancelable: true`
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## [0.13.0] - 2026-05-19
|
|
324
|
+
|
|
325
|
+
### Added
|
|
326
|
+
- **셀 표시 형식 (`format`)**: `ColumnDefinition.format`에 형식 문자열(`'#,##0.00'`, `'0.00%'`, `'$#,##0'`, `'yyyy-MM-dd'` 등) 또는 커스텀 함수 지정. 편집/클립보드에는 raw value 유지
|
|
327
|
+
- **조건부 서식 (`conditionalRules`)**: `ColumnDefinition.conditionalRules`에 `{ when, style }` 규칙 배열 지정. 조건 true 시 background/color/fontWeight/fontStyle 인라인 스타일 적용. 다중 규칙 병합
|
|
328
|
+
- **자동완성 편집기 (`autocomplete`)**: `ColumnDefinition.autocomplete: true | 'strict'`. 텍스트 편집 시 기존 컬럼 값 기반 드롭다운 제안. Arrow Down/Up으로 탐색, Enter로 선택. `'strict'` 모드는 목록 외 값 거부
|
|
329
|
+
- **컬럼 숨기기/표시 UI**: 헤더 우클릭 → 내장 컨텍스트 메뉴 (Hide column / Show 숨긴 열). 숨겨진 열 인접 인디케이터 버튼. `hideColumn(key)` / `showColumn(key)` / `getHiddenColumns()` API
|
|
330
|
+
|
|
331
|
+
### Changed
|
|
332
|
+
- `ColumnDefinition`에 `format`, `conditionalRules`, `autocomplete` 필드 추가
|
|
333
|
+
- 새 공개 타입: `CellStyle`, `ConditionalRule`
|
|
334
|
+
- 새 이벤트: `header-context-menu`, `column-visibility-change`
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## [0.12.0] - 2026-05-19
|
|
339
|
+
|
|
340
|
+
### Added
|
|
341
|
+
- **비연속 다중 선택 (Ctrl+Click)**: Ctrl+Click으로 떨어진 셀들 추가/제거 토글. 선택된 비연속 셀 Delete 시 일괄 클리어 (단일 undo)
|
|
342
|
+
- **컬럼 드래그 이동 UI**: 헤더 셀 드래그로 열 순서 변경. ghost + 드롭 인디케이터 표시. 리사이즈 핸들과 드래그 영역 분리
|
|
343
|
+
- **드롭다운 편집기 (`type: 'select'`)**: `options: string[] | { label, value }[]` 로 셀 편집 시 `<select>` 편집기 표시. 미편집 시 label 표시
|
|
344
|
+
- **찾기/바꾸기 (Ctrl+F / Ctrl+H)**: 찾기 패널 + 바꾸기 패널 오버레이. 다음/이전 이동, 단건/모두 바꾸기 (모두 바꾸기는 단일 undo). `find-replace` 이벤트
|
|
345
|
+
- **행 드래그 정렬**: 행 번호 셀 드래그로 행 순서 변경. ghost + 수평 인디케이터. undo/redo + `row-reorder` 이벤트
|
|
346
|
+
- **Fill Handle**: 선택 범위 우하단 8px 핸들 드래그로 값 복제/시리즈 채우기. 숫자 등차수열 자동 감지. undo/redo + `fill-handle-apply` 이벤트
|
|
347
|
+
- Ctrl+Z/Y 키가 active cell 없이도 동작하도록 개선 (전역 처리)
|
|
348
|
+
|
|
349
|
+
### Changed
|
|
350
|
+
- `ColumnDefinition`에 `options?: string[] | SelectOption[]` 필드 추가
|
|
351
|
+
- `ColumnType`에 `'select'` 추가
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## [0.11.0] - 2026-05-18
|
|
356
|
+
|
|
357
|
+
### Added
|
|
358
|
+
- Mouse drag range selection: mousedown + mouseenter로 셀 범위 드래그 확장
|
|
359
|
+
- Fill Down (Ctrl+D): 선택 범위 첫 행 값을 아래 행에 채우기. 단일 셀 시 위 셀 값 복사
|
|
360
|
+
- Fill Right (Ctrl+R): 선택 범위 첫 열 값을 오른쪽 열에 채우기. 단일 셀 시 왼쪽 셀 값 복사
|
|
361
|
+
- 모든 Fill 동작은 undo/redo 지원
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## [0.10.0] - 2026-03-31
|
|
366
|
+
|
|
367
|
+
### Added
|
|
368
|
+
- React wrapper via `@iyulab/flex-table/react` subpath export
|
|
369
|
+
- `FlexTableReact` component wraps `<flex-table>` for idiomatic React usage
|
|
370
|
+
- All 23 custom events mapped to React callback props (onCellSelect, onSortChange, etc.)
|
|
371
|
+
- `react` and `@lit/react` as optional peer dependencies
|
|
372
|
+
|
|
373
|
+
### Changed
|
|
374
|
+
- Vite build now produces multi-entry output (flex-table + react)
|
|
375
|
+
|
|
376
|
+
## [0.9.0] - 2026-03-31
|
|
377
|
+
|
|
378
|
+
### Added
|
|
379
|
+
- `pinned: 'right'` support for right-side fixed columns during horizontal scroll
|
|
380
|
+
- Scroll-only update optimization: `_recomputeView()` skipped during pure scroll events (100K+ row performance)
|
|
381
|
+
- `_getPinnedRight()` method for calculating right-pinned column offsets
|
|
382
|
+
|
|
383
|
+
### Changed
|
|
384
|
+
- `willUpdate()` uses `changedProperties` analysis to skip unnecessary filter/sort recomputation
|
|
385
|
+
- `ColumnDefinition.pinned` type extended: `'left' | 'right'`
|
|
386
|
+
- Pinned column rendering unified for header, body, and footer cells
|
|
387
|
+
|
|
388
|
+
## [0.8.0] - 2026-03-31
|
|
389
|
+
|
|
390
|
+
### Added
|
|
391
|
+
- ESLint configuration (`@typescript-eslint` + `eslint-plugin-lit`, flat config)
|
|
392
|
+
- `lint` and `lint:fix` npm scripts
|
|
393
|
+
- 5 API coverage tests (getColumnWidth, activeCell, editingCell, sortCriteria, filterKeys)
|
|
394
|
+
- `minWidth` enforcement in cell rendering (not just resize)
|
|
395
|
+
|
|
396
|
+
### Changed
|
|
397
|
+
- `_onKeyDown` refactored: split into `_handleCtrlKey`, `_handleAltKey`, `_handleNavigation`
|
|
398
|
+
- `_handlePaste` refactored: split into `_readClipboardText`, `_expandRowsForPaste`, `_applyPasteData`
|
|
399
|
+
- `_getColWidth` now enforces `minWidth` floor on all rendered cells
|
|
400
|
+
|
|
401
|
+
## [0.7.0] - 2026-03-31
|
|
402
|
+
|
|
403
|
+
### Added
|
|
404
|
+
- Date/datetime filter UI with native date range picker (from/to inputs)
|
|
405
|
+
- Column selection via `selectColumn(colIndex)` API and Ctrl+Click on header
|
|
406
|
+
- `column-select` event with column index, key, and row count detail
|
|
407
|
+
- Keyboard column resize with Alt+ArrowLeft/Right (±20px per keystroke)
|
|
408
|
+
- Validation visual feedback: red border + `aria-invalid` on cells that fail validator (auto-clears after 3s)
|
|
409
|
+
- Filter UI state persistence: text, number, and date filter inputs retain values when dropdown reopens
|
|
410
|
+
|
|
411
|
+
### Fixed
|
|
412
|
+
- Filter dropdown clipped at viewport bottom now flips upward (boundary detection)
|
|
413
|
+
- Number filter inputs now reflect `_numberFilterState` via `.value` binding (API↔UI sync)
|
|
414
|
+
- Text filter inputs now track state across open/close cycles
|
|
415
|
+
|
|
416
|
+
## [0.6.3] - 2026-03-31
|
|
417
|
+
|
|
418
|
+
### Fixed
|
|
419
|
+
- Pinned column rendered one row below due to block-level stacking of `position: sticky` elements
|
|
420
|
+
- Header pinned/prefix cells not visible on vertical scroll (nested `position: sticky` paint issue in Chrome)
|
|
421
|
+
- Whitespace gap between row-number and pinned columns caused by inline-flex layout hack
|
|
422
|
+
- Unified all prefix/pinned cell positioning to `position: absolute` with `scrollLeft` compensation across header, body, and footer
|
|
423
|
+
|
|
424
|
+
### Added
|
|
425
|
+
- GitHub Actions CI/CD: npm publish on release, GitHub Pages demo deployment
|
|
426
|
+
- `build:demo` script and `vite.config.demo.ts` for standalone demo build
|
|
427
|
+
- npm version existence check in publish workflow (idempotent deploys)
|
|
428
|
+
|
|
429
|
+
### Changed
|
|
430
|
+
- `.ft-header` z-index raised from 2 to 3 to ensure header paints above body sticky cells
|
|
431
|
+
|
|
432
|
+
## [0.6.0] - 2026-02-20
|
|
433
|
+
|
|
434
|
+
### Added
|
|
435
|
+
- Horizontal virtual scrolling: only columns visible in the viewport (+ 5 overscan) are rendered to DOM
|
|
436
|
+
- Constant DOM footprint regardless of column count (50, 100, or more columns)
|
|
437
|
+
- `data-col-index` attribute on cells for reliable column identification
|
|
438
|
+
- Demo: 100-column horizontal virtual scroll test section
|
|
439
|
+
|
|
440
|
+
### Changed
|
|
441
|
+
- Row/cell layout changed from CSS Grid to absolute positioning for selective column rendering
|
|
442
|
+
- Auto-fit resize and context menu now use `data-col-index` instead of DOM position
|
|
443
|
+
- `_scrollToActiveCell` uses cached column offsets instead of manual recomputation
|
|
444
|
+
|
|
445
|
+
### Fixed
|
|
446
|
+
- Filter predicate error handling wraps predicates in try-catch (fail-open)
|
|
447
|
+
- Data mutation reactivity: `hasChanged: () => true` on data property, public `refreshData()` method
|
|
448
|
+
|
|
449
|
+
## [0.5.0] - 2026-02-19
|
|
450
|
+
|
|
451
|
+
### Added
|
|
452
|
+
- Row selection via checkbox (`selectable` property, `selection-mode` attribute)
|
|
453
|
+
- `selectAll()`, `deselectAll()`, `getSelectedRows()` public API
|
|
454
|
+
- `selection-change` event with `{ selectedIndices, selectedRows }` detail
|
|
455
|
+
- Footer/summary row support (`footer-data` property)
|
|
456
|
+
- Data mode: `dataMode` property (`'client'` / `'server'`)
|
|
457
|
+
- Context menu event: `context-menu` with position, row data, and column info
|
|
458
|
+
|
|
459
|
+
## [0.4.0] - 2026-02-19
|
|
460
|
+
|
|
461
|
+
### Added
|
|
462
|
+
- `aria-selected` on all cells (`"true"` / `"false"`) per WAI-ARIA grid pattern
|
|
463
|
+
- `aria-readonly="true"` on non-editable cells (global `editable` or per-column `editable`)
|
|
464
|
+
- `aria-label` and `aria-expanded` on filter buttons for screen reader support
|
|
465
|
+
- Editor focus outline (`outline: 2px solid`) for keyboard navigation visibility
|
|
466
|
+
- README: full API documentation rewrite (Properties, Methods, Events, Usage Guide)
|
|
467
|
+
|
|
468
|
+
### Changed
|
|
469
|
+
- Filter button opacity `0.5` → `0.7` for improved visibility (WCAG)
|
|
470
|
+
|
|
471
|
+
## [0.3.0] - 2026-02-19
|
|
472
|
+
|
|
473
|
+
### Added
|
|
474
|
+
- `addColumn(def, index?)` method — dynamically add columns
|
|
475
|
+
- `deleteColumn(key)` method — remove columns with automatic filter/sort cleanup
|
|
476
|
+
- `moveColumn(key, newIndex)` method — reorder columns programmatically
|
|
477
|
+
- `updateRows(changes)` method — batch update multiple cells as single undo action
|
|
478
|
+
- `exportToString(format, { selectionOnly: true })` — export only selected range
|
|
479
|
+
- `maxUndoSize` property (`max-undo-size` attribute) — configurable undo stack size
|
|
480
|
+
- `showFilters` property (`show-filters` attribute) — built-in header filter dropdown UI
|
|
481
|
+
- `ColumnDefinition.pinned` field — freeze columns during horizontal scroll (`'left'`)
|
|
482
|
+
- Built-in filter UI: text search, number range (min/max), boolean toggle
|
|
483
|
+
- Filter active indicator — highlighted filter icon when filter is applied
|
|
484
|
+
- Events: `column-add`, `column-delete`, `column-reorder`, `batch-update`
|
|
485
|
+
- Row number column sticky positioning on horizontal scroll
|
|
486
|
+
- Demo: add/delete column buttons, pinned columns, built-in filter UI
|
|
487
|
+
|
|
488
|
+
## [0.2.0] - 2026-02-19
|
|
489
|
+
|
|
490
|
+
### Added
|
|
491
|
+
- `theme` property with `reflect: true` — programmatic theme switching (`table.theme = 'dark'`)
|
|
492
|
+
- `editable` property — global read-only mode (`table.editable = false`)
|
|
493
|
+
- `ColumnDefinition.editable` field — per-column editing control
|
|
494
|
+
- `maxRows` property — cap row additions and paste auto-expansion
|
|
495
|
+
- `canUndo` / `canRedo` public getters
|
|
496
|
+
- `undo-state-change` event with `{ canUndo, canRedo }` detail
|
|
497
|
+
- `cell-edit-start` event with `{ row, col, key, value }` detail
|
|
498
|
+
- `clipboard-error` event on clipboard API failure
|
|
499
|
+
- `getColumnWidth(key)` method — query internal resize widths
|
|
500
|
+
- RFC 4180 compliant clipboard parser (quoted fields, embedded tabs/newlines)
|
|
501
|
+
- Horizontal scroll tracking in keyboard navigation
|
|
502
|
+
- Column auto-fit on resize handle double-click
|
|
503
|
+
- Demo: filter UI, add row, export CSV, undo/redo status display
|
|
504
|
+
- `typecheck` and `test:coverage` npm scripts
|
|
505
|
+
|
|
506
|
+
### Fixed
|
|
507
|
+
- `aria-sort` no longer rendered on non-sortable columns (ARIA spec compliance)
|
|
508
|
+
- Column resize no longer mutates original `ColumnDefinition` objects
|
|
509
|
+
- Date/datetime export uses ISO 8601 for `Date` objects
|
|
510
|
+
- Clipboard errors now dispatch events instead of being silently swallowed
|
|
511
|
+
|
|
512
|
+
### Changed
|
|
513
|
+
- `addRow()` returns `DataRow | null` (returns `null` when `maxRows` reached)
|
|
514
|
+
|
|
515
|
+
## [0.1.0] - 2026-02-19
|
|
516
|
+
|
|
517
|
+
### Added
|
|
518
|
+
- Initial release
|
|
519
|
+
- `<flex-table>` Lit 3 web component with CSS Grid layout
|
|
520
|
+
- Column types: text, number, boolean, date, datetime
|
|
521
|
+
- Custom cell renderer via `ColumnDefinition.renderer` callback
|
|
522
|
+
- Virtual scroll (10K+ rows, overscan=5)
|
|
523
|
+
- Cell selection and keyboard navigation (Arrow, Tab, Home, End, Ctrl+Home/End)
|
|
524
|
+
- Range selection (Shift+Arrow, Shift+Click)
|
|
525
|
+
- Row selection via row number click
|
|
526
|
+
- Inline editing (Enter/F2, Escape, Tab/Enter commit)
|
|
527
|
+
- Type-specific editors (text, number, date, datetime-local, boolean toggle)
|
|
528
|
+
- Type-to-start editing (printable character starts edit with that character)
|
|
529
|
+
- Clipboard: copy (Ctrl+C), cut (Ctrl+X), paste (Ctrl+V) in TSV format
|
|
530
|
+
- Paste auto-expand rows beyond data bounds
|
|
531
|
+
- Delete/Backspace clears selected range
|
|
532
|
+
- Column sorting (header click asc/desc/none)
|
|
533
|
+
- Multi-column sorting (Shift+click)
|
|
534
|
+
- Sort indicators (arrow + order number)
|
|
535
|
+
- Filter API: `setFilter()`, `removeFilter()`, `clearFilters()`
|
|
536
|
+
- Row operations: `addRow()`, `deleteRows()`
|
|
537
|
+
- Undo/Redo (Ctrl+Z/Y, max 100 actions)
|
|
538
|
+
- Column resize (drag header border)
|
|
539
|
+
- Optional row numbers (`show-row-numbers` attribute)
|
|
540
|
+
- Dark/Light theme (CSS custom properties, `prefers-color-scheme` auto)
|
|
541
|
+
- Export: `exportToString('csv'|'tsv'|'json')`, `exportToFile()`
|
|
542
|
+
- ARIA: `role="grid"`, `aria-sort`, `aria-rowcount`, `aria-colcount`
|
|
543
|
+
- Events: cell-select, cell-edit-commit, cell-edit-cancel, sort-change, filter-change, row-add, row-delete, column-resize, clipboard-copy, clipboard-cut, clipboard-paste
|
|
544
|
+
- 16 CSS custom properties for theming
|
|
545
|
+
- README with full API documentation
|
|
546
|
+
|
|
547
|
+
[unreleased]: https://github.com/iyulab/flex-table/compare/v0.10.0...HEAD
|
|
548
|
+
[0.10.0]: https://github.com/iyulab/flex-table/compare/v0.9.0...v0.10.0
|
|
549
|
+
[0.9.0]: https://github.com/iyulab/flex-table/compare/v0.8.0...v0.9.0
|
|
550
|
+
[0.8.0]: https://github.com/iyulab/flex-table/compare/v0.7.0...v0.8.0
|
|
551
|
+
[0.7.0]: https://github.com/iyulab/flex-table/compare/v0.6.3...v0.7.0
|
|
552
|
+
[0.6.3]: https://github.com/iyulab/flex-table/compare/v0.6.0...v0.6.3
|
|
553
|
+
[0.6.0]: https://github.com/iyulab/flex-table/compare/v0.5.0...v0.6.0
|
|
554
|
+
[0.5.0]: https://github.com/iyulab/flex-table/compare/v0.4.0...v0.5.0
|
|
555
|
+
[0.4.0]: https://github.com/iyulab/flex-table/compare/v0.3.0...v0.4.0
|
|
556
|
+
[0.3.0]: https://github.com/iyulab/flex-table/compare/v0.2.0...v0.3.0
|
|
557
|
+
[0.2.0]: https://github.com/iyulab/flex-table/compare/v0.1.0...v0.2.0
|
|
558
|
+
[0.1.0]: https://github.com/iyulab/flex-table/releases/tag/v0.1.0
|
|
@@ -5,7 +5,8 @@ var s = t`
|
|
|
5
5
|
/* --- Theme Variables (Light defaults) --- */
|
|
6
6
|
:host {
|
|
7
7
|
--ft-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
8
|
-
--
|
|
8
|
+
/* 밀도 스위치 진입점 — components 의 --u-density 를 그대로 읽는다(묶음 결정 DL-253-1). */
|
|
9
|
+
--ft-font-size: var(--u-density, 14px);
|
|
9
10
|
|
|
10
11
|
/* --- 치수·위계 축 (기본값 = 종전 렌더값) ---
|
|
11
12
|
이 표는 가상 스크롤이라 행 높이가 **JS 로 계산된다**(index * rowHeight).
|
|
@@ -29,6 +30,13 @@ var s = t`
|
|
|
29
30
|
--ft-row-even-bg: var(--u-bg-color, #FFFFFF);
|
|
30
31
|
--ft-row-odd-bg: var(--u-bg-color-raised, #FAFAFA);
|
|
31
32
|
--ft-row-hover-bg: var(--u-bg-color-hover, #F5F5F5);
|
|
33
|
+
/* ★홀수 행은 --ft-row-odd-bg(=raised) 위에 앉는다 — 짝수 행과 같은
|
|
34
|
+
--ft-row-hover-bg(=전역 hover) 를 쓰면 다크에서 raised==hover 라 «올려도 아무
|
|
35
|
+
일도 안 일어난다»(§D-14, L2-11-1). --u-bg-color-raised-hover 는 다크에서
|
|
36
|
+
color-mix 로 새로 계산되고, 라이트에서는 기존 hover 에 별칭된다(components
|
|
37
|
+
light.css) — 두 테마 다 늘 선언돼 있으므로 폴백 리터럴은 시트 미로드 시에만
|
|
38
|
+
쓰인다(다른 토큰들과 같은 관례). */
|
|
39
|
+
--ft-row-odd-hover-bg: var(--u-bg-color-raised-hover, #F5F5F5);
|
|
32
40
|
--ft-active-color: var(--u-primary-color, #1976D2);
|
|
33
41
|
--ft-selection-bg: var(--u-primary-bg-color, #E3F2FD);
|
|
34
42
|
--ft-bool-color: var(--u-primary-color, #1976D2);
|
|
@@ -72,6 +80,7 @@ var s = t`
|
|
|
72
80
|
--ft-row-even-bg: var(--u-bg-color, #FFFFFF);
|
|
73
81
|
--ft-row-odd-bg: var(--u-bg-color-raised, #FAFAFA);
|
|
74
82
|
--ft-row-hover-bg: var(--u-bg-color-hover, #F5F5F5);
|
|
83
|
+
--ft-row-odd-hover-bg: var(--u-bg-color-raised-hover, #F5F5F5);
|
|
75
84
|
--ft-active-color: var(--u-primary-color, #1976D2);
|
|
76
85
|
--ft-selection-bg: var(--u-primary-bg-color, #E3F2FD);
|
|
77
86
|
--ft-bool-color: var(--u-primary-color, #1976D2);
|
|
@@ -92,6 +101,7 @@ var s = t`
|
|
|
92
101
|
--ft-row-even-bg: var(--u-bg-color, #FFFFFF);
|
|
93
102
|
--ft-row-odd-bg: var(--u-bg-color-raised, #FAFAFA);
|
|
94
103
|
--ft-row-hover-bg: var(--u-bg-color-hover, #F5F5F5);
|
|
104
|
+
--ft-row-odd-hover-bg: var(--u-bg-color-raised-hover, #F5F5F5);
|
|
95
105
|
--ft-active-color: var(--u-primary-color, #1976D2);
|
|
96
106
|
--ft-selection-bg: var(--u-primary-bg-color, #E3F2FD);
|
|
97
107
|
--ft-bool-color: var(--u-primary-color, #1976D2);
|
|
@@ -241,7 +251,8 @@ var s = t`
|
|
|
241
251
|
|
|
242
252
|
.ft-row-even .ft-cell { background: var(--ft-row-even-bg); }
|
|
243
253
|
.ft-row-odd .ft-cell { background: var(--ft-row-odd-bg); }
|
|
244
|
-
.ft-row:hover .ft-cell { background: var(--ft-row-hover-bg); }
|
|
254
|
+
.ft-row-even:hover .ft-cell { background: var(--ft-row-hover-bg); }
|
|
255
|
+
.ft-row-odd:hover .ft-cell { background: var(--ft-row-odd-hover-bg); }
|
|
245
256
|
|
|
246
257
|
.ft-cell.ft-active {
|
|
247
258
|
outline: 2px solid var(--ft-active-color);
|
|
@@ -407,7 +418,8 @@ var s = t`
|
|
|
407
418
|
}
|
|
408
419
|
|
|
409
420
|
.ft-row-odd .ft-row-num { background: var(--ft-row-odd-bg); }
|
|
410
|
-
.ft-row:hover .ft-row-num { background: var(--ft-row-hover-bg); }
|
|
421
|
+
.ft-row-even:hover .ft-row-num { background: var(--ft-row-hover-bg); }
|
|
422
|
+
.ft-row-odd:hover .ft-row-num { background: var(--ft-row-odd-hover-bg); }
|
|
411
423
|
|
|
412
424
|
.ft-row-num:hover {
|
|
413
425
|
background: var(--ft-header-hover-bg);
|
|
@@ -425,7 +437,8 @@ var s = t`
|
|
|
425
437
|
|
|
426
438
|
.ft-row-even .ft-cell.ft-pinned { background: var(--ft-row-even-bg); }
|
|
427
439
|
.ft-row-odd .ft-cell.ft-pinned { background: var(--ft-row-odd-bg); }
|
|
428
|
-
.ft-row:hover .ft-cell.ft-pinned { background: var(--ft-row-hover-bg); }
|
|
440
|
+
.ft-row-even:hover .ft-cell.ft-pinned { background: var(--ft-row-hover-bg); }
|
|
441
|
+
.ft-row-odd:hover .ft-cell.ft-pinned { background: var(--ft-row-odd-hover-bg); }
|
|
429
442
|
.ft-cell.ft-pinned.ft-selected { background: var(--ft-selection-bg) !important; }
|
|
430
443
|
|
|
431
444
|
/* --- Filter UI --- */
|
|
@@ -576,7 +589,8 @@ var s = t`
|
|
|
576
589
|
}
|
|
577
590
|
|
|
578
591
|
.ft-row-odd .ft-checkbox-cell { background: var(--ft-row-odd-bg); }
|
|
579
|
-
.ft-row:hover .ft-checkbox-cell { background: var(--ft-row-hover-bg); }
|
|
592
|
+
.ft-row-even:hover .ft-checkbox-cell { background: var(--ft-row-hover-bg); }
|
|
593
|
+
.ft-row-odd:hover .ft-checkbox-cell { background: var(--ft-row-odd-hover-bg); }
|
|
580
594
|
.ft-row-selected .ft-checkbox-cell { background: var(--ft-selection-bg); }
|
|
581
595
|
.ft-row-selected .ft-cell { background: var(--ft-selection-bg) !important; }
|
|
582
596
|
.ft-row-selected .ft-row-num { background: var(--ft-selection-bg); }
|
|
@@ -1228,12 +1242,13 @@ function O(e) {
|
|
|
1228
1242
|
}
|
|
1229
1243
|
if (t[i] === "\"") {
|
|
1230
1244
|
let e = "";
|
|
1231
|
-
for (i++; i < a;) if (t[i] === "\"")
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1245
|
+
for (i++; i < a;) if (t[i] === "\"") {
|
|
1246
|
+
if (i + 1 < a && t[i + 1] === "\"") e += "\"", i += 2;
|
|
1247
|
+
else {
|
|
1248
|
+
i++;
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
} else e += t[i], i++;
|
|
1237
1252
|
r.push(e), i < a && t[i] === " " ? i++ : i < a && t[i] === "\n" && (n.push(r), r = [], i++);
|
|
1238
1253
|
} else {
|
|
1239
1254
|
let e = "";
|
|
@@ -1520,7 +1535,7 @@ async function xe(e) {
|
|
|
1520
1535
|
};
|
|
1521
1536
|
}
|
|
1522
1537
|
//#endregion
|
|
1523
|
-
//#region \0@oxc-project+runtime@0.
|
|
1538
|
+
//#region \0@oxc-project+runtime@0.143.0/helpers/esm/decorate.js
|
|
1524
1539
|
function q(e, t, n, r) {
|
|
1525
1540
|
var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
|
|
1526
1541
|
if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
|
package/dist/flex-table.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, r, t as i } from "./flex-table-
|
|
1
|
+
import { a as e, i as t, n, r, t as i } from "./flex-table-DZFtW02v.js";
|
|
2
2
|
export { i as FlexTable, t as RowSelectionState, r as UndoStack, n as exportData, e as renderCell };
|
package/dist/react.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/flex-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "A minimalist, input-centric data grid web component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/flex-table.js",
|
|
@@ -20,12 +20,23 @@
|
|
|
20
20
|
"import": "./dist/odata/index.js"
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
+
"sideEffects": [
|
|
24
|
+
"./src/flex-table.ts",
|
|
25
|
+
"./dist/*.js"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=20"
|
|
29
|
+
},
|
|
23
30
|
"files": [
|
|
24
|
-
"dist"
|
|
31
|
+
"dist",
|
|
32
|
+
"package.json",
|
|
33
|
+
"README.md",
|
|
34
|
+
"CHANGELOG.md",
|
|
35
|
+
"LICENSE"
|
|
25
36
|
],
|
|
26
37
|
"scripts": {
|
|
27
38
|
"dev": "vite serve demo",
|
|
28
|
-
"build": "vite build && tsc --emitDeclarationOnly",
|
|
39
|
+
"build": "npm run typecheck && vite build && tsc --emitDeclarationOnly",
|
|
29
40
|
"build:demo": "vite build --config vite.config.demo.ts",
|
|
30
41
|
"typecheck": "tsc --noEmit",
|
|
31
42
|
"test": "vitest run",
|
|
@@ -56,6 +67,7 @@
|
|
|
56
67
|
"odata-query": "^8.1.0"
|
|
57
68
|
},
|
|
58
69
|
"peerDependencies": {
|
|
70
|
+
"@iyulab/components": ">=1.24.0",
|
|
59
71
|
"@lit/react": "^1.0.0",
|
|
60
72
|
"react": "^18.0.0 || ^19.0.0"
|
|
61
73
|
},
|