@iyulab/data-components 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -0
- package/README.md +67 -0
- package/dist/components/data-view/UDataView.styles.js +20 -4
- package/dist/components/simple-sheet/USimpleSheet.js +3 -2
- package/dist/components/simple-sheet/USimpleSheet.styles.js +52 -13
- package/dist/components/u-rich-table/URichTable.js +19 -13
- package/dist/components/u-rich-table/styles.js +22 -8
- package/dist/utilities/messages.d.ts +25 -0
- package/dist/utilities/messages.js +23 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,97 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.0] - 2026-08-04
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **`u-rich-table` 의 `_id` 부재 경고가 영어로 이주했다** — 개발자 대면 진단이므로 로케일
|
|
8
|
+
레지스트리에 넣지 않는다(사용자가 읽는 문자열이 아니다).
|
|
9
|
+
|
|
10
|
+
- ⚠**표 문구가 «영어 기본 + 로케일 레지스트리»로 이주했다** — 기본값 7건이 한국어 리터럴이었다
|
|
11
|
+
(`u-rich-table` 6 · `u-simple-sheet` 1).
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Locale } from '@iyulab/components';
|
|
15
|
+
import { messages } from '@iyulab/data-components';
|
|
16
|
+
|
|
17
|
+
Locale.set('ko'); // 검증 메시지와 함께 전환된다
|
|
18
|
+
messages.register('ja', { empty: 'データなし' }); // 언어를 더하거나 문구를 덮는다
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
⚠**한국어 환경은 종전과 같은 문구를 본다**(내장 `ko` · `ko-KR` → `ko`).
|
|
22
|
+
⚠**소비자가 준 값은 여전히 이긴다** — `emptyMessage` 등 프로퍼티 계약은 그대로다.
|
|
23
|
+
|
|
24
|
+
★**기본값을 «비우고» 렌더에서 해석한다.** 프로퍼티 초기값에 문자열을 박으면 **생성 시점의
|
|
25
|
+
로케일에 고정**돼 나중에 `Locale.set()` 을 불러도 이미 만들어진 표는 따라오지 않는다.
|
|
26
|
+
⚠**따라서 프로퍼티를 읽으면 기본 상태에서 `''` 가 나온다**(종전에는 한국어 리터럴).
|
|
27
|
+
화면 문구는 렌더 결과가 계약이다.
|
|
28
|
+
|
|
29
|
+
★검증 메시지(`필수 항목입니다`)는 **`@iyulab/components` 의 키셋**을 쓴다
|
|
30
|
+
(`Locale.getValue('valueMissing')` · 14로케일). 같은 문장을 두 곳에 두지 않는다.
|
|
31
|
+
|
|
32
|
+
### Requires
|
|
33
|
+
|
|
34
|
+
- `@iyulab/components >= 1.23.0` (`Locale.namespace`).
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **`u-simple-sheet` 의 행 높이·여백·글자 크기를 소비자가 정할 수 있다** — 조절점 6종.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
--dc-row-height 24px 셀 height · line-height (둘 다)
|
|
42
|
+
--dc-cell-padding-block 0px 셀 · 편집 입력의 세로 여백 (행 높이에 가산)
|
|
43
|
+
--dc-cell-padding-inline 6px 〃 가로 여백
|
|
44
|
+
--dc-font-size 13px 본문 셀 · 편집 입력 · 드롭다운 항목
|
|
45
|
+
--dc-header-font-size 12px 열 머리
|
|
46
|
+
--dc-header-font-weight 600 〃
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
종전에는 치수가 전부 리터럴이라, 한 화면에 표가 여럿일 때 **시트만 다른 높이로 남아도
|
|
50
|
+
맞출 방법이 없었다**(공개 API 에 치수 노브 0건 · `part` 0건). 0.10.0 이 연 색 축과 같은
|
|
51
|
+
자리이고, 색을 맞추고 나서야 높이 차이가 드러난 형태다.
|
|
52
|
+
|
|
53
|
+
⚠**행 높이와 `line-height` 는 한 토큰이 정한다.** 따로 열면 소비자가 한쪽만 바꿔 글자가
|
|
54
|
+
세로로 어긋난다 — 그 묶임이 이 축의 유일한 제약이다.
|
|
55
|
+
|
|
56
|
+
⚠**색 축과 달리 역할 토큰에서 파생하지 않는다** — 역할 층에 치수 축이 없다. 그래서
|
|
57
|
+
`:host` 리터럴 기본값이고, 소비자는 **요소 선택자**로 덮는다(`:root` 는 닿지 않는다).
|
|
58
|
+
|
|
59
|
+
⚠**기본 렌더는 변하지 않는다.** 선언하지 않으면 종전 값으로 그려진다.
|
|
60
|
+
|
|
61
|
+
⚠**선언값과 읽히는 행 높이는 1.5px 다르다** — `border-collapse` 로 접힌 테두리가 사용값에
|
|
62
|
+
더해진다(`24px` 선언 → `25.5px` 로 읽힘). 32px 로 맞추려면 `30.5px` 를 선언한다.
|
|
63
|
+
|
|
64
|
+
`tests/browser/simple-sheet-density.browser.test.ts` 가 **실제 크로미움 계산값으로** 효력을
|
|
65
|
+
잰다 — 소스 대조는 «적혀 있음»만 증명하고, 문서 스코프 선언이 섀도의 `:host` 를 이기는지는
|
|
66
|
+
캐스케이드 문제라 계산값으로만 갈린다.
|
|
67
|
+
|
|
68
|
+
## [0.10.0] - 2026-08-03
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- **표의 보조 전경을 «표 안에서만» 조절할 수 있다** — 파생 토큰 5단.
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
--dc-empty-color 빈 상태 안내문 data-view · simple-sheet · rich-table
|
|
76
|
+
--dc-header-color 열 머리 · 행 머리 data-view · simple-sheet
|
|
77
|
+
--dc-muted-color 보조 텍스트 · 라벨 data-view · rich-table
|
|
78
|
+
--dc-icon-color 정렬 표시 · 확장 · 행 메뉴 rich-table
|
|
79
|
+
--dc-readonly-color 읽기 전용 셀 simple-sheet
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
종전에는 세 컴포넌트가 보조 전경을 전부 `--u-txt-color-weak` 로 **섀도 안에서 직독**해,
|
|
83
|
+
문서 전체의 보조 텍스트를 바꾸지 않고는 표만 맞출 방법이 없었다(소비자 토큰 0 · `part` 0).
|
|
84
|
+
|
|
85
|
+
⚠**기본 렌더는 변하지 않는다.** 다섯 단이 전부 `--u-txt-color-weak` 에서 파생되고
|
|
86
|
+
다크 대응도 그 역할 토큰이 이미 갖고 있다 — 다크 전용 선언을 더하지 않았다.
|
|
87
|
+
|
|
88
|
+
★**한 토큰으로 접지 않았다.** 전 컬럼이 읽기 전용인 시트에서는 데이터가 통째로 흐려
|
|
89
|
+
보이는데, 단이 하나면 *"읽기 전용 셀만 진하게"* 가 원리적으로 불가능해진다.
|
|
90
|
+
|
|
91
|
+
⚠**컴포넌트가 «읽는» 단만 선언한다** — 다섯을 어디서나 선언하면 소비자가 바꿔도 아무 일이
|
|
92
|
+
없는 자리가 생긴다. 어느 단이 어디에 있는지는 README 의 표가 정본이고,
|
|
93
|
+
`tests/consumer-tokens.test.ts` 가 **선언과 사용을 양방향으로** 대조한다.
|
|
94
|
+
|
|
3
95
|
## [0.9.1] - 2026-08-03
|
|
4
96
|
|
|
5
97
|
### Fixed
|
package/README.md
CHANGED
|
@@ -157,6 +157,73 @@ import '@iyulab/components/styles/tokens.css';
|
|
|
157
157
|
:root { --u-primary-color: #7B1FA2; }
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
+
### 보조 전경 조절 (0.10.0~)
|
|
161
|
+
|
|
162
|
+
표의 **보조 전경**(빈 상태 안내문·열 머리·읽기 전용 셀 등)은 역할 토큰
|
|
163
|
+
`--u-txt-color-weak` 에서 파생된 단으로 그려집니다. 그 단을 **표 안에서만** 조절할 수
|
|
164
|
+
있습니다 — 문서 전체의 보조 텍스트를 건드리지 않고 표만 맞출 때 씁니다.
|
|
165
|
+
|
|
166
|
+
| 토큰 | 무엇을 칠하나 | `u-data-view` | `u-simple-sheet` | `u-rich-table` |
|
|
167
|
+
|---|---|:---:|:---:|:---:|
|
|
168
|
+
| `--dc-empty-color` | 빈 상태 안내문 | ● | ● | ● |
|
|
169
|
+
| `--dc-header-color` | 열 머리 · 행 머리 | ● | ● | |
|
|
170
|
+
| `--dc-muted-color` | 보조 텍스트 · 라벨 | ● | | ● |
|
|
171
|
+
| `--dc-icon-color` | 정렬 표시 · 확장 · 행 메뉴 | | | ● |
|
|
172
|
+
| `--dc-readonly-color` | 읽기 전용 셀 | | ● | |
|
|
173
|
+
|
|
174
|
+
⚠**빈 칸은 그 컴포넌트가 그 단을 «읽지 않는다»는 뜻**입니다. 값을 줘도 아무 일이
|
|
175
|
+
일어나지 않습니다 — 읽지 않는 토큰을 선언해 두지 않는 것이 이 패키지의 방침입니다.
|
|
176
|
+
|
|
177
|
+
커스텀 프로퍼티는 상속되므로 **범위는 선택자로 정합니다**:
|
|
178
|
+
|
|
179
|
+
```css
|
|
180
|
+
/* 세 표를 한꺼번에 */
|
|
181
|
+
:root { --dc-empty-color: #9AA0A6; }
|
|
182
|
+
|
|
183
|
+
/* 한 컴포넌트만 */
|
|
184
|
+
u-rich-table { --dc-icon-color: #B0B0B0; }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
★**한 토큰으로 접지 않은 이유**: 전 컬럼이 읽기 전용인 시트에서는 데이터가 통째로
|
|
188
|
+
흐려 보이는데, 단이 하나면 *"읽기 전용 셀만 진하게"* 가 원리적으로 불가능합니다.
|
|
189
|
+
|
|
190
|
+
⚠**`0.10.0` 은 조절점만 엽니다 — 기본 렌더는 변하지 않습니다.** 다섯 단이 전부
|
|
191
|
+
`--u-txt-color-weak` 에서 파생되며, 다크 대응도 그 역할 토큰이 이미 갖고 있습니다.
|
|
192
|
+
|
|
193
|
+
### 시트 밀도·타이포 조절 (`u-simple-sheet` · 0.11.0~)
|
|
194
|
+
|
|
195
|
+
한 화면에 표가 여럿일 때 **행 높이를 서로 맞추기 위한** 조절점입니다. 색 축(위)과 같은
|
|
196
|
+
이유로 열렸습니다 — 어느 높이가 옳은지는 소비자가 정할 일인데, 종전에는 치수가 전부
|
|
197
|
+
리터럴이라 정할 방법이 없었습니다.
|
|
198
|
+
|
|
199
|
+
| 토큰 | 기본값 | 무엇을 정하나 |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `--dc-row-height` | `24px` | 셀 `height` 와 `line-height` **둘 다** |
|
|
202
|
+
| `--dc-cell-padding-block` | `0px` | 셀·편집 입력의 세로 여백 (행 높이에 **가산**) |
|
|
203
|
+
| `--dc-cell-padding-inline` | `6px` | 〃 가로 여백 |
|
|
204
|
+
| `--dc-font-size` | `13px` | 본문 셀 · 편집 입력 · 드롭다운 항목 |
|
|
205
|
+
| `--dc-header-font-size` | `12px` | 열 머리 |
|
|
206
|
+
| `--dc-header-font-weight` | `600` | 〃 |
|
|
207
|
+
|
|
208
|
+
```css
|
|
209
|
+
/* ⚠요소 선택자로 겨눕니다 — :root 는 닿지 않습니다(아래 참조) */
|
|
210
|
+
u-simple-sheet {
|
|
211
|
+
--dc-row-height: 30.5px; /* 읽히는 행 높이 32px */
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
⚠**`:root` 로는 닿지 않습니다.** 커스텀 프로퍼티 상속값은 섀도 루트의 `:host` 선언에
|
|
216
|
+
집니다. 색 축과 달리 이 여섯은 `:host` 에 리터럴 기본값을 갖고 있으므로(역할 층에 치수
|
|
217
|
+
축이 없어 파생할 곳이 없습니다) **요소 선택자**(`u-simple-sheet { … }`)로 선언하십시오.
|
|
218
|
+
|
|
219
|
+
⚠**선언값과 «읽히는» 행 높이는 1.5px 다릅니다.** `border-collapse` 로 접힌 테두리가
|
|
220
|
+
사용값에 더해집니다 — 기본 `24px` 선언이 `25.5px` 로 읽힙니다. 32px 로 맞추려면
|
|
221
|
+
`30.5px` 를 선언하십시오. (같은 이유로 **빈 행은 데이터 행보다 1.5px 낮습니다** —
|
|
222
|
+
`0.11.0` 이전부터 그랬고, 교정하면 기본 렌더가 바뀌므로 이 릴리스에서는 두었습니다.)
|
|
223
|
+
|
|
224
|
+
⚠**`0.11.0` 도 조절점만 엽니다** — 선언하지 않으면 종전과 같은 값으로 그려집니다.
|
|
225
|
+
이 여섯은 `u-simple-sheet` 전용입니다(`u-data-view`·`u-rich-table` 은 읽지 않습니다).
|
|
226
|
+
|
|
160
227
|
### 알려진 제약
|
|
161
228
|
|
|
162
229
|
- **표면 높이를 뜻하는 토큰이 없습니다** — 배경 역할 토큰은 상호작용 상태 이름
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { css } from "lit";
|
|
2
2
|
var styles = [css`
|
|
3
3
|
:host {
|
|
4
|
+
|
|
5
|
+
/* ── 소비자 조절점 — 보조 전경 5단 ──
|
|
6
|
+
★이 셋의 보조 전경이 전부 --u-txt-color-weak 직독이라 «표 안에서만» 조절할 방법이
|
|
7
|
+
없었다(소비자 토큰 0 · part 0). 소비앱은 한 제품 안에 표를 넷 두는데, 그중 업스트림
|
|
8
|
+
표만 조절되지 않으면 나머지에 맞출 수가 없다.
|
|
9
|
+
⚠**한 토큰으로 접지 않는다** — 실측상 16곳의 역할이 갈리고, 접으면 "읽기 전용 셀만
|
|
10
|
+
진하게" 같은 요청이 원리적으로 불가능해진다. 그것이 이 요청의 발단이었다.
|
|
11
|
+
⚠**다크 블록에 다시 선언하지 않는다.** --u-txt-color-weak 자체가 테마 변형이므로
|
|
12
|
+
시트가 있으면 따라온다. 이 패키지의 다크 블록이 «비어 있는 것»이 목표 상태다.
|
|
13
|
+
⚠**폴백 리터럴은 라이트 시트 값의 복제다**(루트 tokens:sync 가 대조한다).
|
|
14
|
+
⚠**이 컴포넌트가 «읽는» 단만 선언한다.** 다섯을 어디서나 선언하면 소비자가
|
|
15
|
+
바꿔도 아무 일이 없는 자리가 생긴다 — 이 리포가 반복해서 본 «토큰 존재 ≠ 배선»
|
|
16
|
+
이다. 어느 단이 어디에 있는지는 README 의 표가 정본이다. */
|
|
17
|
+
--dc-muted-color: var(--u-txt-color-weak, #757575); /* 보조 텍스트 · 라벨 */
|
|
18
|
+
--dc-header-color: var(--u-txt-color-weak, #757575); /* 열 머리 · 행 머리 */
|
|
19
|
+
--dc-empty-color: var(--u-txt-color-weak, #757575); /* 빈 상태 안내문 */
|
|
4
20
|
display: block;
|
|
5
21
|
width: 100%;
|
|
6
22
|
}
|
|
@@ -40,7 +56,7 @@ var styles = [css`
|
|
|
40
56
|
|
|
41
57
|
.info {
|
|
42
58
|
font-size: 0.875rem;
|
|
43
|
-
color: var(--
|
|
59
|
+
color: var(--dc-muted-color);
|
|
44
60
|
font-weight: 500;
|
|
45
61
|
}
|
|
46
62
|
|
|
@@ -95,7 +111,7 @@ var styles = [css`
|
|
|
95
111
|
.card-field .label {
|
|
96
112
|
font-size: 0.875rem;
|
|
97
113
|
font-weight: 600;
|
|
98
|
-
color: var(--
|
|
114
|
+
color: var(--dc-muted-color);
|
|
99
115
|
min-width: 80px;
|
|
100
116
|
flex-shrink: 0;
|
|
101
117
|
}
|
|
@@ -147,7 +163,7 @@ var styles = [css`
|
|
|
147
163
|
text-align: left;
|
|
148
164
|
font-size: 0.875rem;
|
|
149
165
|
font-weight: 600;
|
|
150
|
-
color: var(--
|
|
166
|
+
color: var(--dc-header-color);
|
|
151
167
|
border-bottom: 2px solid var(--u-border-color, #E0E0E0);
|
|
152
168
|
white-space: nowrap;
|
|
153
169
|
}
|
|
@@ -181,7 +197,7 @@ var styles = [css`
|
|
|
181
197
|
align-items: center;
|
|
182
198
|
justify-content: center;
|
|
183
199
|
min-height: 300px;
|
|
184
|
-
color: var(--
|
|
200
|
+
color: var(--dc-empty-color);
|
|
185
201
|
font-size: 1rem;
|
|
186
202
|
}
|
|
187
203
|
`];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
|
|
2
2
|
import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
|
|
3
|
+
import { messages } from "../../utilities/messages.js";
|
|
3
4
|
import { styles } from "./USimpleSheet.styles.js";
|
|
4
5
|
import { html } from "lit";
|
|
5
6
|
import { customElement, property, state } from "lit/decorators.js";
|
|
@@ -25,7 +26,7 @@ var USimpleSheet = class USimpleSheet extends UElement {
|
|
|
25
26
|
this.rows = 20;
|
|
26
27
|
this.cols = 10;
|
|
27
28
|
this.readonly = false;
|
|
28
|
-
this.noMatchMessage = "
|
|
29
|
+
this.noMatchMessage = "";
|
|
29
30
|
this._sel = null;
|
|
30
31
|
this._editing = null;
|
|
31
32
|
this._editVal = "";
|
|
@@ -612,7 +613,7 @@ var USimpleSheet = class USimpleSheet extends UElement {
|
|
|
612
613
|
</div>
|
|
613
614
|
` : noMatch && isStrict ? html`
|
|
614
615
|
<div class="cell-dropdown">
|
|
615
|
-
<div class="dropdown-empty">${this.noMatchMessage}</div>
|
|
616
|
+
<div class="dropdown-empty">${this.noMatchMessage || messages.text("noMatch")}</div>
|
|
616
617
|
</div>
|
|
617
618
|
` : ""}
|
|
618
619
|
` : this._formatValue(value, c, r)}
|
|
@@ -2,6 +2,41 @@ import { css, unsafeCSS } from "lit";
|
|
|
2
2
|
//#region src/components/simple-sheet/USimpleSheet.styles.ts
|
|
3
3
|
var baseStyles = css`
|
|
4
4
|
:host {
|
|
5
|
+
|
|
6
|
+
/* ── 소비자 조절점 — 보조 전경 5단 ──
|
|
7
|
+
★이 셋의 보조 전경이 전부 --u-txt-color-weak 직독이라 «표 안에서만» 조절할 방법이
|
|
8
|
+
없었다(소비자 토큰 0 · part 0). 소비앱은 한 제품 안에 표를 넷 두는데, 그중 업스트림
|
|
9
|
+
표만 조절되지 않으면 나머지에 맞출 수가 없다.
|
|
10
|
+
⚠**한 토큰으로 접지 않는다** — 실측상 16곳의 역할이 갈리고, 접으면 "읽기 전용 셀만
|
|
11
|
+
진하게" 같은 요청이 원리적으로 불가능해진다. 그것이 이 요청의 발단이었다.
|
|
12
|
+
⚠**다크 블록에 다시 선언하지 않는다.** --u-txt-color-weak 자체가 테마 변형이므로
|
|
13
|
+
시트가 있으면 따라온다. 이 패키지의 다크 블록이 «비어 있는 것»이 목표 상태다.
|
|
14
|
+
⚠**폴백 리터럴은 라이트 시트 값의 복제다**(루트 tokens:sync 가 대조한다).
|
|
15
|
+
⚠**이 컴포넌트가 «읽는» 단만 선언한다.** 다섯을 어디서나 선언하면 소비자가
|
|
16
|
+
바꿔도 아무 일이 없는 자리가 생긴다 — 이 리포가 반복해서 본 «토큰 존재 ≠ 배선»
|
|
17
|
+
이다. 어느 단이 어디에 있는지는 README 의 표가 정본이다. */
|
|
18
|
+
--dc-header-color: var(--u-txt-color-weak, #757575); /* 열 머리 · 행 머리 */
|
|
19
|
+
--dc-empty-color: var(--u-txt-color-weak, #757575); /* 빈 상태 안내문 */
|
|
20
|
+
--dc-readonly-color: var(--u-txt-color-weak, #757575); /* 읽기 전용 셀 */
|
|
21
|
+
|
|
22
|
+
/* ── 소비자 조절점 — 밀도·타이포 ──
|
|
23
|
+
★색 축(위)과 같은 이유로 열었다. 한 제품 안에 표가 여럿일 때 «어느 높이가 옳은가»는
|
|
24
|
+
소비자가 정할 일인데, 이 컴포넌트는 치수가 전부 리터럴이라 정할 방법이 없었다.
|
|
25
|
+
⚠**행 높이와 line-height 는 한 토큰이 정한다.** 따로 열면 소비자가 한쪽만 바꿔
|
|
26
|
+
글자가 세로로 어긋난다 — 그 묶임이 이 축의 유일한 제약이다.
|
|
27
|
+
⚠**여백 축은 «가산»이다**: 실제 행 높이 = --dc-row-height + 2×--dc-cell-padding-block.
|
|
28
|
+
기본값이 0 이라 선언하지 않으면 종전과 같다.
|
|
29
|
+
⚠**색 축과 달리 역할 토큰에서 파생하지 않는다** — 역할 층에 치수 축이 없다.
|
|
30
|
+
그래서 폴백이 아니라 :host 리터럴 기본값이고, 소비자는 **요소 선택자**로 덮는다
|
|
31
|
+
(:host 선언은 상속값을 이기므로 :root 로는 닿지 않는다).
|
|
32
|
+
⚠**이 컴포넌트가 «읽는» 단만 선언한다** — 색 축과 같은 규칙이다. */
|
|
33
|
+
--dc-row-height: 24px; /* 셀 height · line-height (묶임) */
|
|
34
|
+
--dc-cell-padding-block: 0px; /* 셀 · 편집 입력의 세로 여백 (가산) */
|
|
35
|
+
--dc-cell-padding-inline: 6px; /* 〃 가로 여백 */
|
|
36
|
+
--dc-font-size: 13px; /* 본문 셀 · 편집 입력 · 드롭다운 항목 */
|
|
37
|
+
--dc-header-font-size: 12px; /* 열 머리 */
|
|
38
|
+
--dc-header-font-weight: 600; /* 〃 */
|
|
39
|
+
|
|
5
40
|
display: block;
|
|
6
41
|
width: 100%;
|
|
7
42
|
height: 400px;
|
|
@@ -62,9 +97,9 @@ var baseStyles = css`
|
|
|
62
97
|
background: var(--u-neutral-100, #F5F5F5);
|
|
63
98
|
padding: 4px 8px;
|
|
64
99
|
text-align: center;
|
|
65
|
-
font-size:
|
|
66
|
-
font-weight:
|
|
67
|
-
color: var(--
|
|
100
|
+
font-size: var(--dc-header-font-size);
|
|
101
|
+
font-weight: var(--dc-header-font-weight);
|
|
102
|
+
color: var(--dc-header-color);
|
|
68
103
|
border-right: 1px solid var(--u-border-color, #E0E0E0);
|
|
69
104
|
border-bottom: 2px solid var(--u-border-color, #E0E0E0);
|
|
70
105
|
white-space: nowrap;
|
|
@@ -124,7 +159,7 @@ var baseStyles = css`
|
|
|
124
159
|
text-align: right;
|
|
125
160
|
padding: 0 6px;
|
|
126
161
|
font-size: 11px;
|
|
127
|
-
color: var(--
|
|
162
|
+
color: var(--dc-header-color);
|
|
128
163
|
/* 예외 — 표면 높이 축이 없다. 행번호 여백은 "비활성"이 아니라 시트 바탕보다
|
|
129
164
|
한 단 내려간 면이다. --u-bg-color-disabled 를 쓰면 다크에서 바탕(neutral-100)과
|
|
130
165
|
같은 값이 되어 여백 구분이 사라진다 — 스냅샷이 그것을 잡았다. */
|
|
@@ -144,18 +179,20 @@ var baseStyles = css`
|
|
|
144
179
|
|
|
145
180
|
/* Data cells */
|
|
146
181
|
.cell {
|
|
147
|
-
padding:
|
|
182
|
+
padding: var(--dc-cell-padding-block) var(--dc-cell-padding-inline);
|
|
148
183
|
border-right: 1px solid var(--u-border-color-weak, #EEEEEE);
|
|
149
184
|
border-bottom: 1px solid var(--u-border-color-weak, #EEEEEE);
|
|
150
|
-
font-size:
|
|
185
|
+
font-size: var(--dc-font-size);
|
|
151
186
|
color: var(--u-txt-color, #212121);
|
|
152
187
|
min-width: 80px;
|
|
153
188
|
overflow: hidden;
|
|
154
189
|
text-overflow: ellipsis;
|
|
155
190
|
white-space: nowrap;
|
|
156
191
|
cursor: cell;
|
|
157
|
-
height
|
|
158
|
-
|
|
192
|
+
/* ⚠height 는 «빈 셀»을 정한다 — 내용이 있는 셀의 높이는 line-height 가 만든다.
|
|
193
|
+
둘 중 하나만 배선하면 데이터 행과 빈 행의 높이가 갈린다(네거티브 컨트롤이 잡은 자리). */
|
|
194
|
+
height: var(--dc-row-height);
|
|
195
|
+
line-height: var(--dc-row-height);
|
|
159
196
|
vertical-align: middle;
|
|
160
197
|
position: relative;
|
|
161
198
|
box-sizing: border-box;
|
|
@@ -190,8 +227,9 @@ var baseStyles = css`
|
|
|
190
227
|
border: none;
|
|
191
228
|
outline: 2px solid var(--u-blue-500, #2196F3);
|
|
192
229
|
outline-offset: -1px;
|
|
193
|
-
|
|
194
|
-
|
|
230
|
+
/* ⚠셀과 «같은 값»이어야 한다 — 어긋나면 편집 진입 순간 글자가 튄다. */
|
|
231
|
+
padding: var(--dc-cell-padding-block) var(--dc-cell-padding-inline);
|
|
232
|
+
font-size: var(--dc-font-size);
|
|
195
233
|
font-family: inherit;
|
|
196
234
|
color: var(--u-txt-color, #212121);
|
|
197
235
|
background: var(--u-bg-color, #FFFFFF);
|
|
@@ -219,7 +257,8 @@ var baseStyles = css`
|
|
|
219
257
|
|
|
220
258
|
.dropdown-item {
|
|
221
259
|
padding: 4px 8px;
|
|
222
|
-
|
|
260
|
+
/* 셀 값의 후보를 보이는 자리다 — 본문 글자 축을 따른다. */
|
|
261
|
+
font-size: var(--dc-font-size);
|
|
223
262
|
color: var(--u-txt-color, #212121);
|
|
224
263
|
cursor: pointer;
|
|
225
264
|
white-space: nowrap;
|
|
@@ -239,7 +278,7 @@ var baseStyles = css`
|
|
|
239
278
|
.dropdown-empty {
|
|
240
279
|
padding: 6px 8px;
|
|
241
280
|
font-size: 12px;
|
|
242
|
-
color: var(--
|
|
281
|
+
color: var(--dc-empty-color);
|
|
243
282
|
font-style: italic;
|
|
244
283
|
}
|
|
245
284
|
|
|
@@ -251,7 +290,7 @@ var baseStyles = css`
|
|
|
251
290
|
/* Readonly column/cell */
|
|
252
291
|
.cell.cell-readonly {
|
|
253
292
|
background: var(--u-bg-color-disabled, #FAFAFA);
|
|
254
|
-
color: var(--
|
|
293
|
+
color: var(--dc-readonly-color);
|
|
255
294
|
cursor: default;
|
|
256
295
|
}
|
|
257
296
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
|
|
2
2
|
import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
|
|
3
|
+
import { messages } from "../../utilities/messages.js";
|
|
3
4
|
import { richTableStyles } from "./styles.js";
|
|
4
5
|
import { parseTSV, toTSV } from "./utils/clipboard.js";
|
|
5
6
|
import { LitElement, html } from "lit";
|
|
6
7
|
import { customElement, property, state } from "lit/decorators.js";
|
|
8
|
+
import { Locale } from "@iyulab/components/dist/utilities/Locale.js";
|
|
7
9
|
//#region src/components/u-rich-table/URichTable.ts
|
|
8
10
|
var URichTable = class URichTable extends LitElement {
|
|
9
11
|
constructor(..._args) {
|
|
@@ -14,12 +16,16 @@ var URichTable = class URichTable extends LitElement {
|
|
|
14
16
|
this.pageSize = 25;
|
|
15
17
|
this.currentPage = 1;
|
|
16
18
|
this.loading = false;
|
|
17
|
-
this.emptyMessage = "
|
|
18
|
-
this.loadingMessage = "
|
|
19
|
-
this.filterPlaceholder = "
|
|
20
|
-
this.filterAllLabel = "
|
|
21
|
-
this.addRowLabel = "
|
|
22
|
-
this.pageInfoFormatter = (total, start, end) =>
|
|
19
|
+
this.emptyMessage = "";
|
|
20
|
+
this.loadingMessage = "";
|
|
21
|
+
this.filterPlaceholder = "";
|
|
22
|
+
this.filterAllLabel = "";
|
|
23
|
+
this.addRowLabel = "";
|
|
24
|
+
this.pageInfoFormatter = (total, start, end) => messages.text("pageInfo", {
|
|
25
|
+
total: total.toLocaleString(),
|
|
26
|
+
start,
|
|
27
|
+
end
|
|
28
|
+
});
|
|
23
29
|
this.selectable = false;
|
|
24
30
|
this.editable = false;
|
|
25
31
|
this.addable = false;
|
|
@@ -113,7 +119,7 @@ var URichTable = class URichTable extends LitElement {
|
|
|
113
119
|
_warnMissingRowId() {
|
|
114
120
|
if (this._warnedMissingRowId) return;
|
|
115
121
|
this._warnedMissingRowId = true;
|
|
116
|
-
console.warn("[@iyulab/data-components] u-rich-table:
|
|
122
|
+
console.warn("[@iyulab/data-components] u-rich-table: rows have no `_id`, so selection is tracked by **position**. Re-sorting or re-paging the data moves the selection to a different row. Give every row a unique `_id`.");
|
|
117
123
|
}
|
|
118
124
|
getSelectedRows() {
|
|
119
125
|
return this.data.filter((row, i) => this.selectedIds.has(this._rowId(row, i)));
|
|
@@ -149,7 +155,7 @@ var URichTable = class URichTable extends LitElement {
|
|
|
149
155
|
<div style="flex:1"></div>
|
|
150
156
|
<slot name="toolbar-end"></slot>
|
|
151
157
|
${this.addable ? html`
|
|
152
|
-
<button class="btn btn-success" @click=${this._onAddRowClick}>${this.addRowLabel}</button>
|
|
158
|
+
<button class="btn btn-success" @click=${this._onAddRowClick}>${this.addRowLabel || messages.text("addRow")}</button>
|
|
153
159
|
` : ""}
|
|
154
160
|
</div>
|
|
155
161
|
`;
|
|
@@ -184,10 +190,10 @@ var URichTable = class URichTable extends LitElement {
|
|
|
184
190
|
${this.columns.map((col) => html`
|
|
185
191
|
<td>
|
|
186
192
|
${col.filterable !== false ? col.filterType === "select" && col.options ? html`<select @change=${(e) => this._onFilterChange(col.key, e.target.value)}>
|
|
187
|
-
<option value="">${this.filterAllLabel}</option>
|
|
193
|
+
<option value="">${this.filterAllLabel || messages.text("filterAll")}</option>
|
|
188
194
|
${col.options.map((o) => html`<option value=${o.value}>${o.label}</option>`)}
|
|
189
195
|
</select>` : html`<input
|
|
190
|
-
placeholder=${this.filterPlaceholder}
|
|
196
|
+
placeholder=${this.filterPlaceholder || messages.text("filterPlaceholder")}
|
|
191
197
|
@input=${(e) => this._onFilterChange(col.key, e.target.value)} />` : ""}
|
|
192
198
|
</td>
|
|
193
199
|
`)}
|
|
@@ -196,8 +202,8 @@ var URichTable = class URichTable extends LitElement {
|
|
|
196
202
|
`;
|
|
197
203
|
}
|
|
198
204
|
_renderBody() {
|
|
199
|
-
if (this.loading) return html`<tr><td colspan=${this._colSpan()}><div class="loading-overlay">${this.loadingMessage}</div></td></tr>`;
|
|
200
|
-
if (this.data.length === 0) return html`<tr><td colspan=${this._colSpan()}><div class="empty-message">${this.emptyMessage}</div></td></tr>`;
|
|
205
|
+
if (this.loading) return html`<tr><td colspan=${this._colSpan()}><div class="loading-overlay">${this.loadingMessage || messages.text("loading")}</div></td></tr>`;
|
|
206
|
+
if (this.data.length === 0) return html`<tr><td colspan=${this._colSpan()}><div class="empty-message">${this.emptyMessage || messages.text("empty")}</div></td></tr>`;
|
|
201
207
|
return this.data.map((row, rowIdx) => {
|
|
202
208
|
const rowId = this._rowId(row, rowIdx);
|
|
203
209
|
const isSelected = this.selectedIds.has(rowId);
|
|
@@ -438,7 +444,7 @@ var URichTable = class URichTable extends LitElement {
|
|
|
438
444
|
let newValue = this.editValue;
|
|
439
445
|
if (col.type === "number") newValue = Number(newValue);
|
|
440
446
|
if (col.required && !newValue && newValue !== 0) {
|
|
441
|
-
this.validationErrors = new Map(this.validationErrors).set(`${rowIndex}-${colIndex}`, "
|
|
447
|
+
this.validationErrors = new Map(this.validationErrors).set(`${rowIndex}-${colIndex}`, Locale.getValue("valueMissing"));
|
|
442
448
|
return;
|
|
443
449
|
}
|
|
444
450
|
if (col.validator) {
|
|
@@ -2,6 +2,20 @@ import { css } from "lit";
|
|
|
2
2
|
//#region src/components/u-rich-table/styles.ts
|
|
3
3
|
var richTableStyles = css`
|
|
4
4
|
:host {
|
|
5
|
+
/* ── 소비자 조절점 — 보조 전경 ──
|
|
6
|
+
★이 패키지 표 셋의 보조 전경이 전부 --u-txt-color-weak 직독이라 «표 안에서만»
|
|
7
|
+
조절할 방법이 없었다(소비자 토큰 0 · part 0). 소비앱은 한 제품 안에 표를 넷 두는데,
|
|
8
|
+
그중 업스트림 표만 조절되지 않으면 나머지에 맞출 수가 없다.
|
|
9
|
+
⚠**한 토큰으로 접지 않는다** — 실측상 역할이 갈리고, 접으면 "읽기 전용 셀만 진하게"
|
|
10
|
+
같은 요청이 원리적으로 불가능해진다. 그것이 이 요청의 발단이었다.
|
|
11
|
+
⚠**이 컴포넌트가 «읽는» 단만 선언한다.** 다섯을 어디서나 선언하면 소비자가 바꿔도
|
|
12
|
+
아무 일이 없는 자리가 생긴다 — 이 리포가 반복해서 본 «토큰 존재 ≠ 배선»이다.
|
|
13
|
+
⚠**다크 블록에 다시 선언하지 않는다.** --u-txt-color-weak 자체가 테마 변형이므로
|
|
14
|
+
시트가 있으면 따라온다. 이 패키지의 다크 블록이 «비어 있는 것»이 목표 상태다.
|
|
15
|
+
⚠**폴백 리터럴은 라이트 시트 값의 복제다**(루트 tokens:sync 가 대조한다). */
|
|
16
|
+
--dc-muted-color: var(--u-txt-color-weak, #757575); /* 보조 텍스트 · 라벨 */
|
|
17
|
+
--dc-icon-color: var(--u-txt-color-weak, #757575); /* 정렬 표시 · 확장 · 행 메뉴 */
|
|
18
|
+
--dc-empty-color: var(--u-txt-color-weak, #757575); /* 빈 상태 안내문 */
|
|
5
19
|
display: block;
|
|
6
20
|
font-family: system-ui, -apple-system, sans-serif;
|
|
7
21
|
font-size: 13px;
|
|
@@ -22,7 +36,7 @@ var richTableStyles = css`
|
|
|
22
36
|
|
|
23
37
|
.toolbar .selection-info {
|
|
24
38
|
font-size: 12px;
|
|
25
|
-
color: var(--
|
|
39
|
+
color: var(--dc-muted-color);
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
.toolbar .search-input {
|
|
@@ -80,7 +94,7 @@ var richTableStyles = css`
|
|
|
80
94
|
|
|
81
95
|
.sort-indicator {
|
|
82
96
|
font-size: 10px;
|
|
83
|
-
color: var(--
|
|
97
|
+
color: var(--dc-icon-color);
|
|
84
98
|
margin-left: 4px;
|
|
85
99
|
}
|
|
86
100
|
|
|
@@ -158,7 +172,7 @@ var richTableStyles = css`
|
|
|
158
172
|
width: 30px;
|
|
159
173
|
text-align: center;
|
|
160
174
|
cursor: pointer;
|
|
161
|
-
color: var(--
|
|
175
|
+
color: var(--dc-icon-color);
|
|
162
176
|
}
|
|
163
177
|
|
|
164
178
|
.expand-cell:hover {
|
|
@@ -183,7 +197,7 @@ var richTableStyles = css`
|
|
|
183
197
|
border-radius: 3px;
|
|
184
198
|
background: transparent;
|
|
185
199
|
font-size: 12px;
|
|
186
|
-
color: var(--
|
|
200
|
+
color: var(--dc-muted-color);
|
|
187
201
|
outline: none;
|
|
188
202
|
}
|
|
189
203
|
|
|
@@ -215,7 +229,7 @@ var richTableStyles = css`
|
|
|
215
229
|
background: var(--u-bg-color-raised, #FAFAFA);
|
|
216
230
|
border-top: 1px solid var(--u-border-color, #E0E0E0);
|
|
217
231
|
font-size: 12px;
|
|
218
|
-
color: var(--
|
|
232
|
+
color: var(--dc-muted-color);
|
|
219
233
|
}
|
|
220
234
|
|
|
221
235
|
.pagination .page-buttons {
|
|
@@ -254,7 +268,7 @@ var richTableStyles = css`
|
|
|
254
268
|
align-items: center;
|
|
255
269
|
justify-content: center;
|
|
256
270
|
padding: 40px;
|
|
257
|
-
color: var(--
|
|
271
|
+
color: var(--dc-muted-color);
|
|
258
272
|
}
|
|
259
273
|
|
|
260
274
|
.empty-message {
|
|
@@ -262,7 +276,7 @@ var richTableStyles = css`
|
|
|
262
276
|
align-items: center;
|
|
263
277
|
justify-content: center;
|
|
264
278
|
padding: 40px;
|
|
265
|
-
color: var(--
|
|
279
|
+
color: var(--dc-empty-color);
|
|
266
280
|
}
|
|
267
281
|
|
|
268
282
|
|
|
@@ -270,7 +284,7 @@ var richTableStyles = css`
|
|
|
270
284
|
.styles.ts 만 훑는 정리로는 보이지 않는 자리다. */
|
|
271
285
|
.row-menu {
|
|
272
286
|
cursor: pointer;
|
|
273
|
-
color: var(--
|
|
287
|
+
color: var(--dc-icon-color);
|
|
274
288
|
}
|
|
275
289
|
|
|
276
290
|
.row-error-cell {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@iyulab/data-components` 의 화면 문자열 — **영어 기본 + 로케일 레지스트리**.
|
|
3
|
+
*
|
|
4
|
+
* ## 왜 생겼나
|
|
5
|
+
*
|
|
6
|
+
* 표 컴포넌트의 기본 문구가 **한국어 리터럴**이었다(실측 7건). 소비자가 `emptyMessage` 등을
|
|
7
|
+
* 넘겨 덮을 수는 있었지만, **덮지 않으면 한국어가 나온다** — 로케일 표준(영어 기본 +
|
|
8
|
+
* 레지스트리)을 채택한 리포에서 그것은 미이주다.
|
|
9
|
+
*
|
|
10
|
+
* ## 기본값을 «비워» 두고 렌더에서 해석한다
|
|
11
|
+
*
|
|
12
|
+
* 프로퍼티 초기값으로 문자열을 박으면 **생성 시점의 로케일에 고정**된다 — `Locale.set()` 을
|
|
13
|
+
* 나중에 부르면 이미 만들어진 표는 따라오지 않는다. 그래서 기본값은 빈 문자열이고,
|
|
14
|
+
* 렌더가 `this.x || messages.text(...)` 로 해석한다.
|
|
15
|
+
*
|
|
16
|
+
* ⚠**소비자가 덮는 경로는 그대로다** — 값을 주면 그 값이 이긴다.
|
|
17
|
+
*
|
|
18
|
+
* ## 검증 메시지는 여기 두지 않는다
|
|
19
|
+
*
|
|
20
|
+
* `필수 항목입니다` 는 `@iyulab/components` 의 **검증 메시지 키셋에 이미 있고 14로케일이
|
|
21
|
+
* 딸려 온다**(`Locale.getValue('valueMissing')`). 같은 문장을 이 표에 복제하면 두 곳이
|
|
22
|
+
* 갈라진다.
|
|
23
|
+
*/
|
|
24
|
+
export type DataMessageKey = 'empty' | 'loading' | 'filterPlaceholder' | 'filterAll' | 'addRow' | 'pageInfo' | 'noMatch';
|
|
25
|
+
export declare const messages: import('@iyulab/components/dist/utilities/Locale.js').LocaleNamespace<DataMessageKey>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Locale } from "@iyulab/components/dist/utilities/Locale.js";
|
|
2
|
+
//#region src/utilities/messages.ts
|
|
3
|
+
var messages = Locale.namespace("@iyulab/data-components");
|
|
4
|
+
messages.register("en", {
|
|
5
|
+
empty: "No data",
|
|
6
|
+
loading: "Loading…",
|
|
7
|
+
filterPlaceholder: "Filter…",
|
|
8
|
+
filterAll: "All",
|
|
9
|
+
addRow: "+ New row",
|
|
10
|
+
pageInfo: "Showing {start}-{end} of {total}",
|
|
11
|
+
noMatch: "No matching item"
|
|
12
|
+
});
|
|
13
|
+
messages.register("ko", {
|
|
14
|
+
empty: "데이터가 없습니다",
|
|
15
|
+
loading: "로딩 중...",
|
|
16
|
+
filterPlaceholder: "필터...",
|
|
17
|
+
filterAll: "전체",
|
|
18
|
+
addRow: "+ 새 행",
|
|
19
|
+
pageInfo: "전체 {total}건 중 {start}-{end} 표시",
|
|
20
|
+
noMatch: "일치하는 항목 없음"
|
|
21
|
+
});
|
|
22
|
+
//#endregion
|
|
23
|
+
export { messages };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/data-components",
|
|
3
3
|
"description": "iyulab data visualization components",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"web-components",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"lint:fix": "eslint src/ --fix"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@iyulab/components": "^1.
|
|
61
|
+
"@iyulab/components": "^1.23.0",
|
|
62
62
|
"lit": "^3.3.3"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"@lit/react": "^1.0.8",
|
|
79
79
|
"@types/node": "^26.1.1",
|
|
80
80
|
"@types/react": "^19.2.17",
|
|
81
|
+
"@vitest/browser-playwright": "^4.1.10",
|
|
81
82
|
"eslint": "^9.39.4",
|
|
82
83
|
"glob": "^13.0.6",
|
|
83
84
|
"globals": "^17.7.0",
|