@iyulab/flex-table 0.24.0 → 0.26.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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.26.0] - 2026-08-20
4
+
5
+ ### Added
6
+
7
+ - **`ColumnDefinition.headerAlign`** (`'start' | 'center' | 'end'`, default `'start'`). Header
8
+ label alignment was previously fixed to the left regardless of how the column's own content is
9
+ rendered. A column whose `renderer` centers its content (an icon-only action column, for
10
+ example) had no way to make the header label match, so the two visually drifted apart. Setting
11
+ `headerAlign: 'center'` (or `'end'`) aligns the header text independently of cell content
12
+ alignment, which the consumer already fully controls via `renderer`.
13
+
14
+ ## [0.25.0] - 2026-08-07
15
+
16
+ ### Added
17
+
18
+ - **`--ft-font-size` now reads `var(--u-density, 14px)`.** When a consumer sets the design
19
+ system's `--u-density` switch on an ancestor, the table's base font size (and everything
20
+ derived from it) follows automatically. Unset, behavior is unchanged.
21
+
22
+ ### Fixed
23
+
24
+ - **Hovering an odd (striped) row produced no visible feedback in dark mode.** Odd rows sit on
25
+ the raised-surface background, and the hover style used the same global hover token that raised
26
+ happened to equal in dark — so the row simply didn't respond. Odd-row hover now reads a
27
+ dedicated raised-surface hover token when the design system sheet provides one, falling back to
28
+ the previous behavior otherwise. Even rows are unaffected.
29
+
3
30
  ## [0.24.0] - 2026-08-05
4
31
 
5
32
  ### Changed
package/README.md CHANGED
@@ -4,6 +4,12 @@ A lightweight, schema-agnostic data grid web component built with [Lit](https://
4
4
 
5
5
  Designed for effortless data input and crystal-clear visibility. Bridges the gap between spreadsheet freedom and database structural integrity.
6
6
 
7
+ **`flex-table` vs. `URichTable`** (`@iyulab/data-components`): both can consume external data
8
+ sources such as OData — the choice is about scale and interaction, not the data source.
9
+
10
+ - **`flex-table`** — large datasets, cell-level editing, spreadsheet-grade interaction
11
+ - **`URichTable`** — small-to-medium datasets, row-level CRUD, selection/filter-focused UX
12
+
7
13
  ## Install
8
14
 
9
15
  ```bash
@@ -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
- --ft-font-size: 14px;
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);
@@ -143,6 +153,9 @@ var s = t`
143
153
  .ft-header-cell.ft-sortable { cursor: pointer; }
144
154
  .ft-header-cell.ft-sortable:hover { background: var(--ft-header-hover-bg); }
145
155
 
156
+ .ft-header-cell.ft-header-align-center { justify-content: center; }
157
+ .ft-header-cell.ft-header-align-end { justify-content: flex-end; }
158
+
146
159
  .ft-resize-handle {
147
160
  position: absolute;
148
161
  right: 0; top: 0; bottom: 0;
@@ -241,7 +254,8 @@ var s = t`
241
254
 
242
255
  .ft-row-even .ft-cell { background: var(--ft-row-even-bg); }
243
256
  .ft-row-odd .ft-cell { background: var(--ft-row-odd-bg); }
244
- .ft-row:hover .ft-cell { background: var(--ft-row-hover-bg); }
257
+ .ft-row-even:hover .ft-cell { background: var(--ft-row-hover-bg); }
258
+ .ft-row-odd:hover .ft-cell { background: var(--ft-row-odd-hover-bg); }
245
259
 
246
260
  .ft-cell.ft-active {
247
261
  outline: 2px solid var(--ft-active-color);
@@ -407,7 +421,8 @@ var s = t`
407
421
  }
408
422
 
409
423
  .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); }
424
+ .ft-row-even:hover .ft-row-num { background: var(--ft-row-hover-bg); }
425
+ .ft-row-odd:hover .ft-row-num { background: var(--ft-row-odd-hover-bg); }
411
426
 
412
427
  .ft-row-num:hover {
413
428
  background: var(--ft-header-hover-bg);
@@ -425,7 +440,8 @@ var s = t`
425
440
 
426
441
  .ft-row-even .ft-cell.ft-pinned { background: var(--ft-row-even-bg); }
427
442
  .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); }
443
+ .ft-row-even:hover .ft-cell.ft-pinned { background: var(--ft-row-hover-bg); }
444
+ .ft-row-odd:hover .ft-cell.ft-pinned { background: var(--ft-row-odd-hover-bg); }
429
445
  .ft-cell.ft-pinned.ft-selected { background: var(--ft-selection-bg) !important; }
430
446
 
431
447
  /* --- Filter UI --- */
@@ -576,7 +592,8 @@ var s = t`
576
592
  }
577
593
 
578
594
  .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); }
595
+ .ft-row-even:hover .ft-checkbox-cell { background: var(--ft-row-hover-bg); }
596
+ .ft-row-odd:hover .ft-checkbox-cell { background: var(--ft-row-odd-hover-bg); }
580
597
  .ft-row-selected .ft-checkbox-cell { background: var(--ft-selection-bg); }
581
598
  .ft-row-selected .ft-cell { background: var(--ft-selection-bg) !important; }
582
599
  .ft-row-selected .ft-row-num { background: var(--ft-selection-bg); }
@@ -1228,12 +1245,13 @@ function O(e) {
1228
1245
  }
1229
1246
  if (t[i] === "\"") {
1230
1247
  let e = "";
1231
- for (i++; i < a;) if (t[i] === "\"") if (i + 1 < a && t[i + 1] === "\"") e += "\"", i += 2;
1232
- else {
1233
- i++;
1234
- break;
1235
- }
1236
- else e += t[i], i++;
1248
+ for (i++; i < a;) if (t[i] === "\"") {
1249
+ if (i + 1 < a && t[i + 1] === "\"") e += "\"", i += 2;
1250
+ else {
1251
+ i++;
1252
+ break;
1253
+ }
1254
+ } else e += t[i], i++;
1237
1255
  r.push(e), i < a && t[i] === " " ? i++ : i < a && t[i] === "\n" && (n.push(r), r = [], i++);
1238
1256
  } else {
1239
1257
  let e = "";
@@ -1520,7 +1538,7 @@ async function xe(e) {
1520
1538
  };
1521
1539
  }
1522
1540
  //#endregion
1523
- //#region \0@oxc-project+runtime@0.142.0/helpers/esm/decorate.js
1541
+ //#region \0@oxc-project+runtime@0.146.0/helpers/esm/decorate.js
1524
1542
  function q(e, t, n, r) {
1525
1543
  var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
1526
1544
  if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
@@ -2778,7 +2796,9 @@ var J = {
2778
2796
  let i = e.sortable !== !1, a = this._sortCriteria.find((t) => t.key === e.key), o = this._sortCriteria.length > 1 ? this._sortCriteria.findIndex((t) => t.key === e.key) : -1, s = this._filters.some((t) => t.key === e.key), c = e.pinned === "left", l = e.pinned === "right", u = [
2779
2797
  "ft-header-cell",
2780
2798
  i ? "ft-sortable" : "",
2781
- c || l ? "ft-pinned" : ""
2799
+ c || l ? "ft-pinned" : "",
2800
+ e.headerAlign === "center" ? "ft-header-align-center" : "",
2801
+ e.headerAlign === "end" ? "ft-header-align-end" : ""
2782
2802
  ].filter(Boolean).join(" "), d = i ? a ? a.direction === "asc" ? "ascending" : "descending" : "none" : void 0, f = this._getColWidth(e), p = this.headerHeight, m = this._colLeftOffsets[t] ?? 0, h;
2783
2803
  h = c ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(t)}px; width: ${f}px; height: ${p}px; z-index: 4;` : l ? `position: absolute; top: 0; right: ${-this._scrollLeft + this._getPinnedRight(t)}px; width: ${f}px; height: ${p}px; z-index: 4;` : `left: ${m}px; width: ${f}px; height: ${p}px;`;
2784
2804
  let g = this._colDrag?.active && this._colDrag.colIndex === t, _ = [...u.split(" "), g ? "ft-col-dragging" : ""].filter(Boolean).join(" "), v = this.columns, y = v.findIndex((t) => t.key === e.key), b = [];
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, r, t as i } from "./flex-table-D-OLUYir.js";
1
+ import { a as e, i as t, n, r, t as i } from "./flex-table-BSxnKOL3.js";
2
2
  export { i as FlexTable, t as RowSelectionState, r as UndoStack, n as exportData, e as renderCell };
@@ -59,6 +59,13 @@ export interface ColumnDefinition<T = DataRow> {
59
59
  hidden?: boolean;
60
60
  /** Whether the column is sortable (default: true) */
61
61
  sortable?: boolean;
62
+ /**
63
+ * Horizontal alignment of the header label (default: 'start').
64
+ * Independent of cell content alignment — a consumer centering cell content
65
+ * via a custom `renderer` (e.g. an icon-only action column) sets this to
66
+ * 'center' so the header visually matches.
67
+ */
68
+ headerAlign?: 'start' | 'center' | 'end';
62
69
  /** Custom cell renderer — overrides built-in type rendering */
63
70
  renderer?: CellRenderer<T>;
64
71
  /** Whether the column is editable (default: true — follows global editable setting) */
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./flex-table-D-OLUYir.js";
1
+ import { t as e } from "./flex-table-BSxnKOL3.js";
2
2
  import t from "react";
3
3
  import { createComponent as n } from "@lit/react";
4
4
  var r = n({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/flex-table",
3
- "version": "0.24.0",
3
+ "version": "0.26.0",
4
4
  "description": "A minimalist, input-centric data grid web component",
5
5
  "type": "module",
6
6
  "main": "./dist/flex-table.js",