@iyulab/data-components 0.7.0 → 0.8.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,171 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.0] - 2026-08-02
4
+
5
+ ### Changed
6
+
7
+ - **UDataView 가 역할 토큰만 읽는다.** 다크 전용 규칙 92줄을 제거하고, 팔레트 참조
8
+ 4곳을 역할 토큰으로 옮겼다(`--u-blue-600` → `--u-primary-color`, `--u-blue-200` →
9
+ `--u-primary-color-weakest`). **두 테마의 계산색은 그대로다** — 브라우저에서
10
+ 변경 전후 계산값 스냅샷을 대조해 확인했다.
11
+
12
+ 제거한 다크 블록의 24개 선언은 전부 base 규칙과 **같은 토큰**을 가리키고 있었다.
13
+ 역할 토큰(`--u-bg-color`, `--u-border-color`, `--u-txt-color-weak` …)은 두 테마에서
14
+ 서로 다른 팔레트 단에 매핑돼 있어(예: `--u-bg-color` = neutral-0 라이트 /
15
+ neutral-100 다크) 테마 보정이 이미 토큰 층에 들어 있다. 따라서 그 블록은 토큰 시트가
16
+ 로드된 환경에서 계산값을 하나도 바꾸지 못했다.
17
+
18
+ - **USimpleSheet 의 다크 블록을 24개 선언 → 6개로 줄였다.** 지운 것은 base 와 같은 토큰을
19
+ 가리켜 계산값을 바꾸지 못하던 규칙들이다. **남긴 6개는 죽은 규칙이 아니다** — 유채색
20
+ 표면(계산 셀·선택된 열 헤더·강조된 드롭다운 항목)이며, 역할 층에 유채색 표면 토큰이
21
+ 없어서 손으로 메운 보정이다. 비활성화하면 실제로 색이 달라짐을 확인했다.
22
+ - **USimpleSheet 그림자 2곳이 `--u-shadow-color-*` 를 읽는다.** 종전에는 라이트/다크가
23
+ 각각 하드코딩된 `rgba(0,0,0,0.15)` / `0.5` 였다. 역할 토큰은 테마별로 불투명도가
24
+ 튜닝돼 있다(0.16/0.45, 0.12/0.35) — 다크에서 그림자가 아주 조금 옅어진다.
25
+ - **USimpleSheet 읽기전용 셀이 `--u-bg-color-disabled` 를 읽는다.** 이 토큰의 테마별
26
+ 매핑(neutral-50 라이트 / neutral-100 다크)이 종전 다크 블록이 손으로 쓴 단과 **정확히
27
+ 같다** — 그래서 해당 다크 규칙이 불필요해졌다. 계산색은 두 테마 모두 그대로다.
28
+
29
+ ### Added
30
+
31
+ - **UI 문구를 프로퍼티로 열었다** — URichTable 의 `loadingMessage`·`filterPlaceholder`·
32
+ `filterAllLabel`·`addRowLabel`·`pageInfoFormatter`, USimpleSheet 의 `noMatchMessage`.
33
+ 종전에는 `emptyMessage` 하나만 열려 있고 나머지는 한국어로 하드코딩돼 있었다.
34
+ `pageInfoFormatter` 만 함수인 것은 **언어마다 어순이 달라** 템플릿 문자열로는 열 수
35
+ 없기 때문이다.
36
+
37
+ ⚠로케일 레지스트리를 도입하지는 않았다 — 이 패키지에 없는 레이어를 새로 들이는
38
+ 일이고, 현재 수요가 그것을 요구할 만큼 모이지 않았다. 기존 `emptyMessage` 어법을
39
+ 따르는 순수 가산이다.
40
+
41
+ ### Changed
42
+
43
+ - **업스트림 토큰 채택 (`@iyulab/components` 1.15.0).** 이 릴리스에서 소비 측 우회 둘이
44
+ 사라졌다:
45
+ - **보조 텍스트 AA 우회 해제** — URichTable 4곳이 역할 토큰을 피해 고정값을 쓰고
46
+ 있었다(`--u-txt-color-weak` 가 라이트에서 2.68 로 AA 미달이었기 때문). 업스트림이
47
+ neutral-600(4.61)으로 고쳐져 **역할 토큰으로 되돌렸다.** 그 넷을 위해 남겨 둔
48
+ 다크 규칙도 함께 사라졌다 — 이제 이 색은 테마 오버라이드를 따른다.
49
+ - **유채색 표면 토큰 채택** — `--u-primary-bg-color`·`--u-success-bg-color`·
50
+ `--u-danger-bg-color` 로 옮겼다. 이 토큰들은 두 테마가 **같은 세기**가 되도록
51
+ 짝지어져 있어(라이트 shade-0 ↔ 다크 shade-100), 손으로 쓰던 다크 보정 2개가
52
+ 불필요해졌다. **다크에서 선택된 행·계산 셀 틴트가 제 세기로 보인다** —
53
+ 종전에는 팔레트 유채색이 다크에서 짓눌려 절반 이하로 옅었다.
54
+
55
+ ⇒ 다크 전용 규칙이 **8 → 3**, 팔레트 직접 참조가 **40 → 31** 로 줄었다.
56
+
57
+ ### Fixed
58
+
59
+ - **URichTable 템플릿에 인라인으로 박혀 있던 색 3곳**(행 메뉴 `⋯`, 행 오류 줄, 새 행
60
+ 표시)을 클래스 + 역할 토큰으로 옮겼다. `style="…#94a3b8"` 형태라 **스타일 시트만
61
+ 훑는 정리에는 보이지 않는 자리**였다. 색이 조금 바뀐다 — 행 오류 줄 배경
62
+ `#FEF2F2` → `#FFEBEE`, 행 메뉴 `#94A3B8` → `#9E9E9E`, 새 행 표시 `#86EFAC` →
63
+ `#A5D6A7`. (이 셋은 계산색 스냅샷이 덮지 못한다 — 렌더 조건이 내부 상태다.)
64
+
65
+ - ★**URichTable 에서 `_id` 없는 행을 넘기면 한 행 선택이 전체 선택으로 번지던 문제.**
66
+ 선택·확장·행 오류 상태가 전부 `_id` 로 추적되는데 그 값을 **어디서도 부여하지 않아**,
67
+ 소비자가 넣지 않으면 모든 행이 `undefined` 로 같은 키를 갖게 됐다. 이제 `_id` 가 없으면
68
+ **위치로 식별하고 개발 경고**를 낸다. 위치 기반 식별은 데이터가 재정렬·재페이징되면
69
+ 선택이 다른 행으로 옮겨가므로 안전망일 뿐이다 — 정렬·필터·페이지가 소비자 책임인
70
+ 컴포넌트이니 `_id` 를 주는 것이 옳다.
71
+
72
+ ### Documentation
73
+
74
+ - **`docs/URichTable.md` 신설.** 종전에는 README 가 *"문서 작성 예정"* 이라며 `types.ts`
75
+ 를 가리키고 있었다. 타입만으로는 드러나지 않는 두 계약을 먼저 적었다 — ⑴ `data` 는
76
+ 그대로 렌더되며 **정렬·필터·페이지는 소비자 책임**이다(헤더 클릭은 이벤트만 낸다),
77
+ ⑵ 각 행에 `_id` 가 필요하다. 속성·이벤트 9종·키보드/클립보드 표 포함.
78
+ - **README 의 Theming 절을 실제 동작에 맞게 고쳤다** — 토큰 시트가 필요하다는 것,
79
+ 없을 때의 폴백 규약, 브랜드 색 한 줄 변경, 그리고 알려진 제약 둘(AA 미달, Chromium
80
+ 한정 규칙)을 명시했다.
81
+
82
+ - **`--u-blue-50` 은 토큰 시트에 정의가 없다.** USimpleSheet 4곳(계산 셀·선택 셀·강조된
83
+ 드롭다운 항목)이 이 이름을 참조해 **두 테마 모두에서** 항상 리터럴 폴백으로 떨어지고
84
+ 있었다 — 즉 토큰 층과 무관하게 고정색이었다. 팔레트의 틴트 끝인 `--u-blue-0` 로
85
+ 고쳤다. **라이트에서 색이 바뀐다**: `#EFF6FF` → `#E3F2FD`. 다크는 종전과 동일하다.
86
+
87
+ - ★**URichTable 이 디자인 토큰을 읽기 시작한다 — 라이트 재도색.** 이 컴포넌트는 base
88
+ 레이어가 토큰을 **하나도** 쓰지 않고 고정 hex 를 박아 두었다. 즉 라이트에서 테마·브랜드
89
+ 설정에 전혀 반응하지 않았고, 다크는 그 위에 얹은 별도 재구현(57개 선언)이었다.
90
+ base 를 역할 토큰으로 옮기면서 다크 블록은 **2개 규칙**만 남았다.
91
+
92
+ **라이트에서 색이 바뀐다** — 주요 항목:
93
+
94
+ | 자리 | 전 | 후 |
95
+ |---|---|---|
96
+ | 테두리 | `#E2E8F0` | `#E0E0E0` (`--u-border-color`) |
97
+ | 입력 테두리 | `#D1D5DB` | `#E0E0E0` (`--u-input-border-color`) |
98
+ | 툴바·페이지네이션 배경 | `#F8FAFC` | `#FAFAFA` |
99
+ | 헤더 배경 | `#F1F5F9` | `#F5F5F5` |
100
+ | 주 버튼 | `#3B82F6` | `#1E88E5` (`--u-primary-color`) |
101
+ | 성공 버튼 | `#10B981` | `#43A047` (`--u-success-color`) |
102
+ | 선택된 행 | `#EFF6FF` | `#E3F2FD` |
103
+ | 편집·필터 행 | `#FEFCE8` | `#FFFDE7` |
104
+ | 오류 행 | `#FEF2F2` | `#FFEBEE` |
105
+ | 새 행 | `#F0FDF4` | `#E8F5E9` |
106
+
107
+ ⇒ 이제 `:root { --u-primary-color: … }` 한 줄로 이 표의 버튼·강조색이 따라온다.
108
+
109
+ **다크에서는 성공 버튼만 바뀐다**(green-500 → `--u-success-color`). 나머지가 종전
110
+ 값 그대로임을 계산색 스냅샷으로 확인했다 — 두 테마 × 14개 선택자(상태 틴트 포함:
111
+ 선택된 행·필터 줄·새 행). 스냅샷이 덮지 못한 자리는 `tbody tr.error`(내부 상태 필요)
112
+ 와 `.dropdown-item.highlighted` 두 곳이다.
113
+
114
+ ⚠**`:host` 가 이제 글자색을 정한다.** 종전에는 base 에 `color` 선언이 없어 페이지에서
115
+ **상속**받았고, 다크 블록만 그것을 덮었다. 이제 base 가 `--u-txt-color` 를 읽는다.
116
+ 토큰 시트를 쓰는 환경에서는 개선이지만, 시트 없이 페이지 글자색을 직접 지정하던
117
+ 소비자는 그 상속을 잃는다 — 필요하면 `--u-txt-color` 를 지정하세요.
118
+
119
+ ⚠**Firefox/Safari 에서 다크가 동작하기 시작한다.** 종전에는 다크가 전부
120
+ `:host-context()` 안에 있었고 그 선택자는 Chromium 전용이라, 다른 브라우저에서는
121
+ **다크 모드가 아예 적용되지 않았다.** 이제 색의 대부분이 토큰 층에서 테마를 따르므로
122
+ 전 브라우저에서 동작한다. 남은 2개 규칙(표면 높이·보조 텍스트)만 Chromium 한정으로
123
+ 남는다.
124
+
125
+ ### Removed
126
+
127
+ - **UDataView 의 `theme` 속성이 더 이상 색을 바꾸지 않는다.**
128
+ 토큰 시트를 로드한 환경에서는 원래부터 효과가 없었다(위 참조). 시트를 로드하지 않는
129
+ 환경에서는 요소에 `theme="dark"` 를 걸면 다크 고정값이 적용됐으나, 이제는 적용되지
130
+ 않는다 — 토큰 미공급 시 폴백은 라이트 기준 고정값이라는 규약을 따른다.
131
+ **다크가 필요하면 토큰 시트를 로드할 것**(`@iyulab/components/styles/tokens.css`).
132
+ 문서 단위 다크(`<html theme="dark">`)는 종전과 동일하게 동작한다.
133
+
134
+ ### Added
135
+
136
+ - 브라우저 테스트 프로젝트(playwright chromium). 계산색을 실제로 측정한다 —
137
+ 기존 유닛 테스트는 스타일 **문자열**에서 셀렉터를 세므로, 규칙이 적혀 있음은 보여도
138
+ 그 규칙이 무언가를 바꾸는지는 말하지 못한다. 위 24개 선언이 정확히 그 사각에 있었다.
139
+ - `data-view-colors.browser.test.ts` — 두 테마 계산색 스냅샷 회귀망
140
+ - `theme-resolution.browser.test.ts` — 역할 토큰의 테마별 매핑, 팔레트 틴트 비대칭
141
+
142
+ ### Known issues
143
+
144
+ - **유채색에는 테마 보정 층이 없다.** 역할 토큰의 중립 계열 17종은 두 테마에서 다른
145
+ 팔레트 단에 매핑되지만, `--u-primary/success/danger/warning-*` 는 양 테마가 같은 단을
146
+ 가리킨다. 그런데 팔레트의 틴트 세기는 계열마다 비대칭이다 — 바탕 대비 델타 실측:
147
+ 중립은 다크가 라이트의 1.34~1.62배, 청색은 0.38~0.54배, 적색은 0.25~0.58배,
148
+ 황색은 4.2~6.1배. 그래서 유채색 표면을 쓰는 컴포넌트는 다크 보정을 손으로 써야 한다.
149
+ - **"주색 위의 글자" 역할 토큰이 없다.** 활성 뷰 버튼은 다크에서 대비 3.45 이며
150
+ 흰 글자였다면 6.09 다. 팔레트를 직접 바꾸면 게시된 시각이 움직이므로 보류했다.
151
+ - **UI 문자열이 한국어로 하드코딩돼 있다** — `URichTable` 의 `로딩 중...`·`필터...`·
152
+ `전체`·`전체 N건 중 X-Y 표시`, `USimpleSheet` 의 `일치하는 항목 없음`. `emptyMessage`
153
+ 만 프로퍼티로 열려 있고 나머지는 소비자가 바꿀 수 없다. 이 패키지에는 로케일 레이어가
154
+ 없어 단순 프로퍼티 추가로 갈지 로케일 레지스트리를 도입할지가 설계 결정이다.
155
+ - ★**`--u-txt-color-weak` 의 라이트 매핑이 WCAG AA 에 미달한다** — neutral-500(#9E9E9E)
156
+ = 흰 배경 대비 **2.68**(AA 기준 4.5). 다크는 neutral-700 = **5.43** 으로 정상이므로
157
+ **라이트 한쪽만의 결함**이다. 그래서 URichTable 의 보조 텍스트 4곳은 역할 토큰으로
158
+ 옮기지 못했다(옮기면 4.76 → 2.68 로 후퇴). 업스트림에서 라이트 매핑을
159
+ **neutral-600(4.61)** 으로 한 단 내리면 해소된다.
160
+
161
+ ## [0.7.1] - 2026-08-01
162
+
163
+ ### Documentation
164
+
165
+ - 체인지로그와 마이그레이션 가이드에서 **발견 정황 서술을 제거**했다. 결함이 무엇이고 어떤
166
+ 조건에서 재현되는지는 그대로이며, 라이브러리와 무관한 서술만 걷어냈다.
167
+ 코드 변경은 없다 — 게시본 문서를 정리하기 위한 패치 릴리스다.
168
+
3
169
  ## [0.7.0] - 2026-07-19
4
170
 
5
171
  ### Changed
@@ -15,7 +181,7 @@
15
181
  ## [0.6.0] - 2026-06-11
16
182
 
17
183
  ### Added
18
- - `USimpleSheet`: `theme` 속성 1급 지원 (`'light' | 'dark'`, attribute 리플렉트) — per-element 테마 지정 가능, `:host-context` 미지원 브라우저(Firefox/Safari)에서도 동작 (ISSUE-20260610-usimplesheet-darkmode-inconsistent)
184
+ - `USimpleSheet`: `theme` 속성 1급 지원 (`'light' | 'dark'`, attribute 리플렉트) — per-element 테마 지정 가능, `:host-context` 미지원 브라우저(Firefox/Safari)에서도 동작
19
185
  - `USimpleSheet`: 조상 `data-theme="dark"` 컨텍스트에서도 다크 모드 적용 — Theme 유틸 없이 `data-theme`만 설정하는 앱에서 도구별 다크 적용이 비일관하던 문제 해소
20
186
 
21
187
  ### Changed
@@ -57,7 +223,7 @@ UDataGrid 대체: `@iyulab/flex-table` + `@iyulab/flex-table/odata` 조합 사
57
223
  ## [0.3.2] - 2026-05-07
58
224
 
59
225
  ### Added
60
- - `docs/migrating-from-datagrid.md`: UDataGrid(DevExtreme)에서 `@iyulab/flex-table`로 전환하는 마이그레이션 가이드 추가 (yesung-oms 9개 페이지 실증 기반)
226
+ - `docs/migrating-from-datagrid.md`: UDataGrid(DevExtreme)에서 `@iyulab/flex-table`로 전환하는 마이그레이션 가이드 추가 (리스트 페이지 9개 전환 실증 기반)
61
227
  - README에 UDataGrid 대안 섹션 및 마이그레이션 가이드 링크 추가
62
228
  - `docs/UDataGrid.md` 상단에 마이그레이션 가이드 링크 추가
63
229
 
package/README.md CHANGED
@@ -124,12 +124,12 @@ const sheet = document.querySelector('u-simple-sheet'); // USimpleSheet | null
124
124
 
125
125
  - [USimpleSheet](./docs/USimpleSheet.md)
126
126
  - [UDataView](./docs/UDataView.md)
127
- - URichTable — 문서 작성 예정([types.ts](./src/components/u-rich-table/types.ts) 참고)
127
+ - [URichTable](./docs/URichTable.md)
128
128
  - [UDataGrid 마이그레이션 가이드](./docs/migrating-from-datagrid.md)
129
129
 
130
130
  ## Theming
131
131
 
132
- `@iyulab/components`의 테마 시스템을 사용합니다. 라이트/다크 모드 자동 지원.
132
+ `@iyulab/components`의 디자인 토큰을 읽습니다. **토큰 시트가 문서에 있어야 테마가 동작합니다.**
133
133
 
134
134
  ```typescript
135
135
  import { Theme } from '@iyulab/components';
@@ -138,6 +138,40 @@ Theme.init({ default: 'system' });
138
138
  Theme.set('dark'); // 'light' | 'dark' | 'system'
139
139
  ```
140
140
 
141
+ `Theme.init()`을 쓰지 않는다면 정적 진입점을 대신 임포트하세요:
142
+
143
+ ```typescript
144
+ import '@iyulab/components/styles/tokens.css';
145
+ ```
146
+
147
+ ### 토큰 시트가 없으면
148
+
149
+ 컴포넌트는 렌더되지만 **라이트 기준 고정값**으로 그려지며, 다크 테마와 테마 변수
150
+ 오버라이드가 적용되지 않습니다. 이는 의도된 폴백 규약입니다.
151
+
152
+ ### 브랜드 색 바꾸기
153
+
154
+ 색은 역할 토큰을 통해 읽으므로, 주색 한 줄로 버튼·선택 강조·포커스가 함께 따라옵니다:
155
+
156
+ ```css
157
+ :root { --u-primary-color: #7B1FA2; }
158
+ ```
159
+
160
+ ### 알려진 제약
161
+
162
+ - **표면 높이를 뜻하는 토큰이 없습니다** — 배경 역할 토큰은 상호작용 상태 이름
163
+ (`-hover`/`-active`/`-disabled`)뿐이라 "바탕보다 한 단 올라온 면"을 표현할 수 없습니다.
164
+ 라이트에서는 팔레트 음영이 흰 바탕 위에서 충분히 읽히지만 다크에서는 거의 검정이라,
165
+ 툴바·표 헤더 등 몇 자리는 `:host-context()`로 보정합니다. **이 선택자는
166
+ Firefox/Safari에서 동작하지 않습니다** — 해당 브라우저에서 그 면들이 배경에 묻힙니다.
167
+ 그 밖의 색은 전 브라우저에서 테마를 따릅니다.
168
+ - **경고(노랑) 표면에는 역할 토큰이 없습니다** — 라이트 황색 틴트가 거의 보이지 않아
169
+ 두 테마의 세기를 맞출 단 짝이 없습니다(업스트림 미해결). 필터 줄·편집 중 행은
170
+ 팔레트를 직접 읽습니다.
171
+
172
+ > `--u-txt-color-weak`의 WCAG AA 미달(2.68)은 `@iyulab/components` 1.15.0에서
173
+ > 해소됐습니다(4.61). 이 패키지가 쓰던 우회도 함께 제거됐습니다.
174
+
141
175
  ## License
142
176
 
143
177
  MIT
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
1
+ //#region \0@oxc-project+runtime@0.142.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.142.0/helpers/esm/decorateMetadata.js
2
2
  function __decorateMetadata(k, v) {
3
3
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
4
  }
@@ -1,6 +1,6 @@
1
1
  import { styles } from "./UDataView.styles.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorate.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
4
4
  import { html } from "lit";
5
5
  import { customElement, property, state } from "lit/decorators.js";
6
6
  import "@iyulab/components/dist/components/icon/UIcon.js";
@@ -123,9 +123,10 @@ var UDataView = class UDataView extends UElement {
123
123
  `;
124
124
  }
125
125
  renderDefaultCard(item) {
126
+ const cols = this.getColumns();
126
127
  return html`
127
128
  <div class="card-content">
128
- ${this.getColumns().slice(0, 5).map((col) => {
129
+ ${cols.slice(0, 5).map((col) => {
129
130
  const value = item[col.key];
130
131
  return html`
131
132
  <div class="card-field">
@@ -1,6 +1,5 @@
1
- import { css, unsafeCSS } from "lit";
2
- //#region src/components/data-view/UDataView.styles.ts
3
- var baseStyles = css`
1
+ import { css } from "lit";
2
+ var styles = [css`
4
3
  :host {
5
4
  display: block;
6
5
  width: 100%;
@@ -30,7 +29,12 @@ var baseStyles = css`
30
29
  }
31
30
 
32
31
  .view-toggles u-button[active] {
33
- background: var(--u-blue-600, #1E88E5);
32
+ background: var(--u-primary-color, #1E88E5);
33
+ /* 예외 1 — "주색 위의 글자" 역할 토큰이 없다.
34
+ 역할 층의 유채색은 전경 5단(--u-primary-color-*)뿐이고, 그 위에 얹는 글자색을
35
+ 가리키는 토큰은 없다. 실측: 라이트 #FFFFFF/#1E88E5 = 3.68, 다크 #000000/#2A659D
36
+ = 3.45 — 다크는 흰 글자였다면 6.09 였다. 즉 현재 값이 최선이 아니지만, 팔레트를
37
+ 직접 바꾸면 게시된 시각이 움직이므로 토큰 추가 결정까지 현행을 유지한다. */
34
38
  color: var(--u-neutral-0, #fff);
35
39
  }
36
40
 
@@ -65,15 +69,15 @@ var baseStyles = css`
65
69
  }
66
70
 
67
71
  .card:hover {
68
- border-color: var(--u-blue-600, #1E88E5);
72
+ border-color: var(--u-primary-color, #1E88E5);
69
73
  box-shadow: 0 4px 12px var(--u-shadow-color-weak, rgba(0, 0, 0, 0.08));
70
74
  transform: translateY(-2px);
71
75
  }
72
76
 
73
77
  .card.selected {
74
- border-color: var(--u-blue-600, #1E88E5);
78
+ border-color: var(--u-primary-color, #1E88E5);
75
79
  background: var(--u-bg-color-active, #EEEEEE);
76
- box-shadow: 0 0 0 3px var(--u-blue-200, #90CAF9);
80
+ box-shadow: 0 0 0 3px var(--u-primary-color-weakest, #90CAF9);
77
81
  }
78
82
 
79
83
  .card-content {
@@ -127,6 +131,11 @@ var baseStyles = css`
127
131
  }
128
132
 
129
133
  thead {
134
+ /* 예외 2 — 표면 높이 축이 없다.
135
+ 배경 역할 토큰은 상호작용 상태 이름(-hover/-active/-disabled)뿐이라,
136
+ "바탕보다 한 단 올라온 면"을 뜻하는 토큰이 없다. 헤더에 -hover 를 쓰면
137
+ 마우스 상태를 뜻하게 되므로 팔레트를 직접 읽는다. neutral-50 은 두 테마에서
138
+ 각각 #FAFAFA/#0A0A0A 로 반전되므로 다크 보정은 필요 없다. */
130
139
  background: var(--u-neutral-50, #f8fafc);
131
140
  position: sticky;
132
141
  top: 0;
@@ -175,88 +184,6 @@ var baseStyles = css`
175
184
  color: var(--u-txt-color-weak, #64748b);
176
185
  font-size: 1rem;
177
186
  }
178
- `;
179
- var DARK_PREFIXES = [
180
- ":host([theme=\"dark\"])",
181
- ":host-context([theme=\"dark\"])",
182
- ":host-context([data-theme=\"dark\"])"
183
- ];
184
- var darkRules = (host) => `
185
- ${host} .toolbar {
186
- background: var(--u-bg-color, #121212);
187
- border-color: var(--u-border-color, #3D3D3D);
188
- }
189
-
190
- ${host} .view-toggles u-button[active] {
191
- background: var(--u-blue-600, #87B8F5);
192
- color: var(--u-neutral-0, #000);
193
- }
194
-
195
- ${host} .info {
196
- color: var(--u-txt-color-weak, #8A8A8A);
197
- }
198
-
199
- ${host} .card {
200
- background: var(--u-bg-color, #121212);
201
- border-color: var(--u-border-color, #3D3D3D);
202
- }
203
-
204
- ${host} .card:hover {
205
- border-color: var(--u-blue-600, #87B8F5);
206
- box-shadow: 0 4px 12px var(--u-shadow-color-weak, rgba(0, 0, 0, 0.25));
207
- }
208
-
209
- ${host} .card.selected {
210
- border-color: var(--u-blue-600, #87B8F5);
211
- background: var(--u-bg-color-active, #3D3D3D);
212
- box-shadow: 0 0 0 3px var(--u-blue-200, #2B4F7E);
213
- }
214
-
215
- ${host} .card-field .label {
216
- color: var(--u-txt-color-weak, #8A8A8A);
217
- }
218
-
219
- ${host} .card-field .value {
220
- color: var(--u-txt-color, #D4D4D4);
221
- }
222
-
223
- ${host} .table-wrapper {
224
- border-color: var(--u-border-color, #3D3D3D);
225
- }
226
-
227
- ${host} table {
228
- background: var(--u-bg-color, #121212);
229
- }
230
-
231
- ${host} thead {
232
- background: var(--u-neutral-50, #0A0A0A);
233
- }
234
-
235
- ${host} th {
236
- color: var(--u-txt-color-weak, #8A8A8A);
237
- border-bottom-color: var(--u-border-color, #3D3D3D);
238
- }
239
-
240
- ${host} tbody tr:hover {
241
- background: var(--u-bg-color-hover, #2A2A2A);
242
- }
243
-
244
- ${host} tbody tr.selected {
245
- background: var(--u-bg-color-active, #3D3D3D);
246
- }
247
-
248
- ${host} tbody tr:not(:last-child) {
249
- border-bottom-color: var(--u-border-color-weak, #2A2A2A);
250
- }
251
-
252
- ${host} td {
253
- color: var(--u-txt-color, #D4D4D4);
254
- }
255
-
256
- ${host} .empty {
257
- color: var(--u-txt-color-weak, #8A8A8A);
258
- }
259
- `;
260
- var styles = [baseStyles, unsafeCSS(DARK_PREFIXES.map(darkRules).join("\n"))];
187
+ `];
261
188
  //#endregion
262
189
  export { styles };
@@ -48,6 +48,8 @@ export declare class USimpleSheet extends UElement {
48
48
  cols: number;
49
49
  /** 읽기 전용 모드 */
50
50
  readonly: boolean;
51
+ /** 드롭다운에 일치 항목이 없을 때 문구 */
52
+ noMatchMessage: string;
51
53
  /**
52
54
  * 명시 테마. 'dark'이면 다크 스타일을 적용합니다.
53
55
  * 미설정 시 조상 컨텍스트의 theme/data-theme 속성에 따릅니다 (:host-context, Chromium 한정).
@@ -1,5 +1,5 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.139.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.142.0/helpers/esm/decorate.js";
3
3
  import { styles } from "./USimpleSheet.styles.js";
4
4
  import { html } from "lit";
5
5
  import { customElement, property, state } from "lit/decorators.js";
@@ -25,6 +25,7 @@ var USimpleSheet = class USimpleSheet extends UElement {
25
25
  this.rows = 20;
26
26
  this.cols = 10;
27
27
  this.readonly = false;
28
+ this.noMatchMessage = "일치하는 항목 없음";
28
29
  this._sel = null;
29
30
  this._editing = null;
30
31
  this._editVal = "";
@@ -611,7 +612,7 @@ var USimpleSheet = class USimpleSheet extends UElement {
611
612
  </div>
612
613
  ` : noMatch && isStrict ? html`
613
614
  <div class="cell-dropdown">
614
- <div class="dropdown-empty">일치하는 항목 없음</div>
615
+ <div class="dropdown-empty">${this.noMatchMessage}</div>
615
616
  </div>
616
617
  ` : ""}
617
618
  ` : this._formatValue(value, c, r)}
@@ -924,6 +925,7 @@ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)]
924
925
  __decorate([property({ type: Number }), __decorateMetadata("design:type", Object)], USimpleSheet.prototype, "rows", void 0);
925
926
  __decorate([property({ type: Number }), __decorateMetadata("design:type", Object)], USimpleSheet.prototype, "cols", void 0);
926
927
  __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Object)], USimpleSheet.prototype, "readonly", void 0);
928
+ __decorate([property({ type: String }), __decorateMetadata("design:type", Object)], USimpleSheet.prototype, "noMatchMessage", void 0);
927
929
  __decorate([property({
928
930
  type: String,
929
931
  reflect: true
@@ -125,6 +125,9 @@ var baseStyles = css`
125
125
  padding: 0 6px;
126
126
  font-size: 11px;
127
127
  color: var(--u-txt-color-weak, #64748b);
128
+ /* 예외 — 표면 높이 축이 없다. 행번호 여백은 "비활성"이 아니라 시트 바탕보다
129
+ 한 단 내려간 면이다. --u-bg-color-disabled 를 쓰면 다크에서 바탕(neutral-100)과
130
+ 같은 값이 되어 여백 구분이 사라진다 — 스냅샷이 그것을 잡았다. */
128
131
  background: var(--u-neutral-50, #f8fafc);
129
132
  border-right: 1px solid var(--u-border-color, #e2e8f0);
130
133
  border-bottom: 1px solid var(--u-border-color-weak, #f1f5f9);
@@ -159,7 +162,7 @@ var baseStyles = css`
159
162
  }
160
163
 
161
164
  .cell.selected {
162
- background: var(--u-blue-50, #eff6ff);
165
+ background: var(--u-primary-bg-color, #E3F2FD);
163
166
  }
164
167
 
165
168
  /* The anchor cell (top-left of selection) */
@@ -194,7 +197,7 @@ var baseStyles = css`
194
197
  background: var(--u-bg-color, #fff);
195
198
  box-sizing: border-box;
196
199
  z-index: 10;
197
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
200
+ box-shadow: 0 2px 8px var(--u-shadow-color-strong, rgba(0, 0, 0, 0.16));
198
201
  }
199
202
 
200
203
  /* Dropdown overlay */
@@ -210,7 +213,7 @@ var baseStyles = css`
210
213
  border: 1px solid var(--u-border-color, #e2e8f0);
211
214
  border-top: none;
212
215
  border-radius: 0 0 4px 4px;
213
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
216
+ box-shadow: 0 4px 12px var(--u-shadow-color-normal, rgba(0, 0, 0, 0.12));
214
217
  z-index: 20;
215
218
  }
216
219
 
@@ -229,7 +232,7 @@ var baseStyles = css`
229
232
  }
230
233
 
231
234
  .dropdown-item.highlighted {
232
- background: var(--u-blue-50, #eff6ff);
235
+ background: var(--u-primary-bg-color, #E3F2FD);
233
236
  color: var(--u-blue-800, #1e40af);
234
237
  }
235
238
 
@@ -247,7 +250,7 @@ var baseStyles = css`
247
250
 
248
251
  /* Readonly column/cell */
249
252
  .cell.cell-readonly {
250
- background: var(--u-neutral-50, #f8fafc);
253
+ background: var(--u-bg-color-disabled, #FAFAFA);
251
254
  color: var(--u-txt-color-weak, #64748b);
252
255
  cursor: default;
253
256
  }
@@ -257,12 +260,12 @@ var baseStyles = css`
257
260
  }
258
261
 
259
262
  .cell.cell-readonly.anchor {
260
- background: var(--u-neutral-50, #f8fafc);
263
+ background: var(--u-bg-color-disabled, #FAFAFA);
261
264
  }
262
265
 
263
266
  /* Computed column/cell */
264
267
  .cell.cell-computed {
265
- background: var(--u-blue-50, #eff6ff);
268
+ background: var(--u-primary-bg-color, #E3F2FD);
266
269
  color: var(--u-txt-color, #0f172a);
267
270
  font-style: italic;
268
271
  cursor: default;
@@ -273,7 +276,7 @@ var baseStyles = css`
273
276
  }
274
277
 
275
278
  .cell.cell-computed.anchor {
276
- background: var(--u-blue-50, #eff6ff);
279
+ background: var(--u-primary-bg-color, #E3F2FD);
277
280
  }
278
281
 
279
282
  /* Readonly mode (whole sheet) */
@@ -288,71 +291,14 @@ var DARK_PREFIXES = [
288
291
  ":host-context([data-theme=\"dark\"])"
289
292
  ];
290
293
  var darkRules = (host) => `
291
- ${host} .sheet-container {
292
- background: var(--u-bg-color, #121212);
293
- border-color: var(--u-border-color, #3D3D3D);
294
- }
295
-
296
- ${host} .sheet-container:focus-within {
297
- border-color: var(--u-blue-500, #6ba3e3);
298
- box-shadow: 0 0 0 2px var(--u-blue-100, #1e3a5f);
299
- }
300
-
301
- ${host} .corner {
302
- background: var(--u-neutral-100, #121212);
303
- border-color: var(--u-border-color, #3D3D3D);
304
- }
305
-
306
- ${host} .corner:hover {
307
- background: var(--u-neutral-200, #1E1E1E);
308
- }
309
-
310
- ${host} .col-header {
311
- background: var(--u-neutral-100, #121212);
312
- color: var(--u-txt-color-weak, #8A8A8A);
313
- border-color: var(--u-border-color, #3D3D3D);
314
- }
315
-
316
294
  ${host} .col-header.col-selected {
317
295
  background: var(--u-blue-100, #1e3a5f);
318
- color: var(--u-blue-800, #c2deff);
319
- }
320
-
321
- ${host} .row-num {
322
- background: var(--u-neutral-50, #0A0A0A);
323
- color: var(--u-txt-color-weak, #8A8A8A);
324
- border-right-color: var(--u-border-color, #3D3D3D);
325
- border-bottom-color: var(--u-border-color-weak, #2A2A2A);
326
- }
327
-
328
- ${host} .row-num.row-selected {
329
- background: var(--u-blue-100, #1e3a5f);
330
- color: var(--u-blue-800, #c2deff);
331
- }
332
-
333
- ${host} .cell {
334
- color: var(--u-txt-color, #D4D4D4);
335
- border-right-color: var(--u-border-color-weak, #2A2A2A);
336
- border-bottom-color: var(--u-border-color-weak, #2A2A2A);
337
- }
338
-
339
- ${host} .cell.cell-readonly {
340
- background: var(--u-neutral-100, #1E1E1E);
341
- color: var(--u-txt-color-weak, #8A8A8A);
342
296
  }
343
297
 
344
298
  ${host} .cell.cell-readonly.selected {
345
299
  background: var(--u-neutral-200, #2A2A2A);
346
300
  }
347
301
 
348
- ${host} .cell.cell-readonly.anchor {
349
- background: var(--u-neutral-100, #1E1E1E);
350
- }
351
-
352
- ${host} .cell.cell-computed {
353
- background: var(--u-blue-100, #1e3a5f);
354
- color: var(--u-txt-color, #D4D4D4);
355
- }
356
302
 
357
303
  ${host} .cell.cell-computed.selected {
358
304
  background: var(--u-blue-200, #2a4a6f);
@@ -362,48 +308,6 @@ var darkRules = (host) => `
362
308
  background: var(--u-blue-100, #1e3a5f);
363
309
  }
364
310
 
365
- ${host} .cell.selected {
366
- background: var(--u-blue-0, #0a1e3d);
367
- }
368
-
369
- ${host} .cell.anchor {
370
- background: var(--u-bg-color, #121212);
371
- outline-color: var(--u-blue-500, #6ba3e3);
372
- }
373
-
374
- ${host} .resize-handle:hover::after {
375
- background: var(--u-blue-500, #6ba3e3);
376
- }
377
-
378
- ${host} .cell-input {
379
- background: var(--u-bg-color, #121212);
380
- color: var(--u-txt-color, #D4D4D4);
381
- outline-color: var(--u-blue-500, #6ba3e3);
382
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
383
- }
384
-
385
- ${host} .cell-dropdown {
386
- background: var(--u-bg-color, #121212);
387
- border-color: var(--u-border-color, #3D3D3D);
388
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
389
- }
390
-
391
- ${host} .dropdown-item {
392
- color: var(--u-txt-color, #D4D4D4);
393
- }
394
-
395
- ${host} .dropdown-item:hover {
396
- background: var(--u-neutral-100, #1E1E1E);
397
- }
398
-
399
- ${host} .dropdown-item.highlighted {
400
- background: var(--u-blue-100, #1e3a5f);
401
- color: var(--u-blue-800, #c2deff);
402
- }
403
-
404
- ${host} .dropdown-empty {
405
- color: var(--u-txt-color-weak, #8A8A8A);
406
- }
407
311
  `;
408
312
  var styles = [baseStyles, unsafeCSS(DARK_PREFIXES.map(darkRules).join("\n"))];
409
313
  //#endregion