@iyulab/data-components 0.1.4 → 0.1.7
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,4 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [0.1.7] - 2026-03-08
|
|
4
|
+
### Added
|
|
5
|
+
- USimpleSheet: `compute` 콜백을 통한 열 단위 자동 계산 기능
|
|
6
|
+
- 가로(같은 행) 및 세로(행 간) 계산 모두 지원
|
|
7
|
+
- compute 열 자동 readonly 및 시각적 구분 (이탤릭 + 파란 배경)
|
|
8
|
+
- 에러 발생 시 빈 문자열 표시
|
|
9
|
+
- 붙여넣기/Fill 시 compute 열 건너뛰기
|
|
10
|
+
|
|
11
|
+
## [0.1.6]
|
|
4
12
|
- Initial library version release
|
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
데이터 표시 및 입력을 위한 웹 컴포넌트 라이브러리.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**[Live Demo](https://iyulab.github.io/node-data-components/)**
|
|
6
|
+
|
|
7
|
+
- **USimpleSheet** — 엑셀 호환 스프레드시트 입력 컴포넌트 (Lit, compute 자동 계산 지원)
|
|
6
8
|
- **UDataView** — Grid / List / Table 뷰 전환 컴포넌트 (Lit)
|
|
7
9
|
- **UDataGrid** — OData 기반 서버 사이드 데이터 그리드 (React + DevExtreme)
|
|
8
10
|
|
|
@@ -42,6 +44,25 @@ npm install @iyulab/data-components
|
|
|
42
44
|
></u-simple-sheet>
|
|
43
45
|
```
|
|
44
46
|
|
|
47
|
+
자동 계산 열 (compute):
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<u-simple-sheet
|
|
51
|
+
.columns=${[
|
|
52
|
+
{ key: 'item', label: '품목', width: 150 },
|
|
53
|
+
{ key: 'qty', label: '수량', width: 80 },
|
|
54
|
+
{ key: 'price', label: '단가', width: 100 },
|
|
55
|
+
{ key: 'total', label: '합계', width: 100,
|
|
56
|
+
compute: (r, data) => {
|
|
57
|
+
const qty = Number(data[r][1]) || 0;
|
|
58
|
+
const price = Number(data[r][2]) || 0;
|
|
59
|
+
return String(qty * price);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
]}
|
|
63
|
+
></u-simple-sheet>
|
|
64
|
+
```
|
|
65
|
+
|
|
45
66
|
### UDataView
|
|
46
67
|
|
|
47
68
|
```html
|
|
@@ -9,6 +9,12 @@ export interface SheetColumn {
|
|
|
9
9
|
width?: number;
|
|
10
10
|
/** 읽기 전용 열 */
|
|
11
11
|
readonly?: boolean;
|
|
12
|
+
/** 선택 가능한 옵션 목록 (정적 배열 또는 동적 콜백) */
|
|
13
|
+
options?: string[] | ((row: number, col: number) => string[]);
|
|
14
|
+
/** true이면 목록에 있는 값만 입력 가능 (기본: false = 자유 입력 허용) */
|
|
15
|
+
strict?: boolean;
|
|
16
|
+
/** 자동 계산 함수. 설정 시 해당 열은 자동 readonly. 열 순서(좌→우), 행 순서(위→아래)로 계산. */
|
|
17
|
+
compute?: (rowIndex: number, data: string[][]) => string;
|
|
12
18
|
}
|
|
13
19
|
/**
|
|
14
20
|
* USimpleSheet - 심플 스프레드시트 컴포넌트
|
|
@@ -44,6 +50,9 @@ export declare class USimpleSheet extends UElement {
|
|
|
44
50
|
private _editing;
|
|
45
51
|
private _editVal;
|
|
46
52
|
private _replaceOnEdit;
|
|
53
|
+
private _dropdownItems;
|
|
54
|
+
private _dropdownIndex;
|
|
55
|
+
private _isDropdownClick;
|
|
47
56
|
private _data;
|
|
48
57
|
private _colWidths;
|
|
49
58
|
private _isMouseSelecting;
|
|
@@ -79,6 +88,7 @@ export declare class USimpleSheet extends UElement {
|
|
|
79
88
|
private _onInputChange;
|
|
80
89
|
private _onInputKeyDown;
|
|
81
90
|
private _onInputBlur;
|
|
91
|
+
private _onDropdownItemMouseDown;
|
|
82
92
|
private _onTableMouseDown;
|
|
83
93
|
private _onTableMouseOver;
|
|
84
94
|
private _onTableDblClick;
|
|
@@ -112,6 +122,11 @@ export declare class USimpleSheet extends UElement {
|
|
|
112
122
|
private _scrollCellIntoView;
|
|
113
123
|
private _getCellFromEvent;
|
|
114
124
|
private _isColReadonly;
|
|
125
|
+
private _isColComputed;
|
|
126
|
+
/** compute 열을 재계산 (열 순서 좌→우, 행 순서 위→아래) */
|
|
127
|
+
private _recompute;
|
|
128
|
+
private _getColOptions;
|
|
129
|
+
private _filterOptions;
|
|
115
130
|
private _emitChange;
|
|
116
131
|
/** 현재 데이터를 2D 배열로 반환 */
|
|
117
132
|
getData(): string[][];
|
|
@@ -32,6 +32,9 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
32
32
|
this._editing = null;
|
|
33
33
|
this._editVal = "";
|
|
34
34
|
this._replaceOnEdit = false;
|
|
35
|
+
this._dropdownItems = [];
|
|
36
|
+
this._dropdownIndex = -1;
|
|
37
|
+
this._isDropdownClick = false;
|
|
35
38
|
// @state() 없음 — 직접 requestUpdate() 호출
|
|
36
39
|
this._data = [];
|
|
37
40
|
this._colWidths = [];
|
|
@@ -180,6 +183,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
180
183
|
return;
|
|
181
184
|
}
|
|
182
185
|
if (!this.readonly && !this._isColReadonly(anchor.col) && e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
|
|
186
|
+
e.preventDefault();
|
|
183
187
|
this._startEdit(anchor.row, anchor.col, e.key);
|
|
184
188
|
}
|
|
185
189
|
};
|
|
@@ -188,14 +192,46 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
188
192
|
// ──────────────────────────────────────────
|
|
189
193
|
this._onInputChange = (e) => {
|
|
190
194
|
this._editVal = e.target.value;
|
|
195
|
+
if (this._editing) {
|
|
196
|
+
const options = this._getColOptions(this._editing.row, this._editing.col);
|
|
197
|
+
if (options) {
|
|
198
|
+
const filtered = this._filterOptions(options, this._editVal);
|
|
199
|
+
this._dropdownItems = filtered;
|
|
200
|
+
this._dropdownIndex = filtered.length > 0 ? 0 : -1;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
191
203
|
};
|
|
192
204
|
this._onInputKeyDown = (e) => {
|
|
193
205
|
e.stopPropagation();
|
|
206
|
+
const hasDropdown = this._dropdownItems.length > 0;
|
|
194
207
|
if (e.key === "Escape") {
|
|
195
208
|
e.preventDefault();
|
|
196
209
|
this._cancelEdit();
|
|
197
210
|
return;
|
|
198
211
|
}
|
|
212
|
+
if (hasDropdown && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
213
|
+
e.preventDefault();
|
|
214
|
+
const len = this._dropdownItems.length;
|
|
215
|
+
if (e.key === "ArrowDown") {
|
|
216
|
+
this._dropdownIndex = (this._dropdownIndex + 1) % len;
|
|
217
|
+
} else {
|
|
218
|
+
this._dropdownIndex = (this._dropdownIndex - 1 + len) % len;
|
|
219
|
+
}
|
|
220
|
+
this.updateComplete.then(() => {
|
|
221
|
+
const dropdown = this.renderRoot.querySelector(".cell-dropdown");
|
|
222
|
+
const highlighted = this.renderRoot.querySelector(".dropdown-item.highlighted");
|
|
223
|
+
if (dropdown && highlighted) {
|
|
224
|
+
const dRect = dropdown.getBoundingClientRect();
|
|
225
|
+
const hRect = highlighted.getBoundingClientRect();
|
|
226
|
+
if (hRect.bottom > dRect.bottom) dropdown.scrollTop += hRect.bottom - dRect.bottom;
|
|
227
|
+
else if (hRect.top < dRect.top) dropdown.scrollTop -= dRect.top - hRect.top;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (hasDropdown && this._dropdownIndex >= 0 && (e.key === "Enter" || e.key === "Tab")) {
|
|
233
|
+
this._editVal = this._dropdownItems[this._dropdownIndex];
|
|
234
|
+
}
|
|
199
235
|
if (e.key === "Enter") {
|
|
200
236
|
e.preventDefault();
|
|
201
237
|
const pos = this._editing;
|
|
@@ -248,10 +284,20 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
248
284
|
}
|
|
249
285
|
};
|
|
250
286
|
this._onInputBlur = () => {
|
|
287
|
+
if (this._isDropdownClick) {
|
|
288
|
+
this._isDropdownClick = false;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
251
291
|
if (this._editing) {
|
|
252
292
|
this._commitEdit();
|
|
253
293
|
}
|
|
254
294
|
};
|
|
295
|
+
this._onDropdownItemMouseDown = (e, value) => {
|
|
296
|
+
e.preventDefault();
|
|
297
|
+
this._isDropdownClick = true;
|
|
298
|
+
this._editVal = value;
|
|
299
|
+
this._commitEdit();
|
|
300
|
+
};
|
|
255
301
|
// ──────────────────────────────────────────
|
|
256
302
|
// 마우스 이벤트
|
|
257
303
|
// ──────────────────────────────────────────
|
|
@@ -431,6 +477,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
431
477
|
newData.push(row);
|
|
432
478
|
}
|
|
433
479
|
this._data = newData;
|
|
480
|
+
this._recompute();
|
|
434
481
|
this._history = [this._data.map((r) => [...r])];
|
|
435
482
|
this._historyIndex = 0;
|
|
436
483
|
const prevWidths = this._colWidths;
|
|
@@ -464,6 +511,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
464
511
|
if (this._historyIndex <= 0) return;
|
|
465
512
|
this._historyIndex--;
|
|
466
513
|
this._data = this._history[this._historyIndex].map((r) => [...r]);
|
|
514
|
+
this._recompute();
|
|
467
515
|
this._emitChange();
|
|
468
516
|
this.requestUpdate();
|
|
469
517
|
}
|
|
@@ -471,6 +519,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
471
519
|
if (this._historyIndex >= this._history.length - 1) return;
|
|
472
520
|
this._historyIndex++;
|
|
473
521
|
this._data = this._history[this._historyIndex].map((r) => [...r]);
|
|
522
|
+
this._recompute();
|
|
474
523
|
this._emitChange();
|
|
475
524
|
this.requestUpdate();
|
|
476
525
|
}
|
|
@@ -573,12 +622,20 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
573
622
|
const isSelected = this._inSel(r, c);
|
|
574
623
|
const isAnchor = this._isAnchor(r, c);
|
|
575
624
|
const value = this._data[r]?.[c] ?? "";
|
|
625
|
+
const isColReadonly = this._isColReadonly(c);
|
|
626
|
+
const isComputed = this._isColComputed(c);
|
|
576
627
|
const classes = [
|
|
577
628
|
"cell",
|
|
578
629
|
isSelected ? "selected" : "",
|
|
579
630
|
isAnchor ? "anchor" : "",
|
|
580
|
-
isEditing ? "editing" : ""
|
|
631
|
+
isEditing ? "editing" : "",
|
|
632
|
+
isColReadonly ? "cell-readonly" : "",
|
|
633
|
+
isComputed ? "cell-computed" : ""
|
|
581
634
|
].filter(Boolean).join(" ");
|
|
635
|
+
const hasOptions = isEditing && this._getColOptions(r, c) !== null;
|
|
636
|
+
const showDropdown = isEditing && this._dropdownItems.length > 0;
|
|
637
|
+
const isStrict = this.columns?.[c]?.strict ?? false;
|
|
638
|
+
const noMatch = isEditing && hasOptions && this._dropdownItems.length === 0 && this._editVal !== "";
|
|
582
639
|
return html`
|
|
583
640
|
<td
|
|
584
641
|
class=${classes}
|
|
@@ -593,6 +650,20 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
593
650
|
@keydown=${this._onInputKeyDown}
|
|
594
651
|
@blur=${this._onInputBlur}
|
|
595
652
|
/>
|
|
653
|
+
${showDropdown ? html`
|
|
654
|
+
<div class="cell-dropdown">
|
|
655
|
+
${this._dropdownItems.map((item, i) => html`
|
|
656
|
+
<div
|
|
657
|
+
class="dropdown-item ${i === this._dropdownIndex ? "highlighted" : ""}"
|
|
658
|
+
@mousedown=${(e) => this._onDropdownItemMouseDown(e, item)}
|
|
659
|
+
>${item}</div>
|
|
660
|
+
`)}
|
|
661
|
+
</div>
|
|
662
|
+
` : noMatch && isStrict ? html`
|
|
663
|
+
<div class="cell-dropdown">
|
|
664
|
+
<div class="dropdown-empty">일치하는 항목 없음</div>
|
|
665
|
+
</div>
|
|
666
|
+
` : ""}
|
|
596
667
|
` : value}
|
|
597
668
|
</td>
|
|
598
669
|
`;
|
|
@@ -630,12 +701,13 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
630
701
|
for (let ci = 0; ci < pasteRows[ri].length; ci++) {
|
|
631
702
|
const r = anchor.row + ri;
|
|
632
703
|
const c = anchor.col + ci;
|
|
633
|
-
if (r < newData.length && c < (newData[r]?.length ?? 0)) {
|
|
704
|
+
if (r < newData.length && c < (newData[r]?.length ?? 0) && !this._isColComputed(c)) {
|
|
634
705
|
newData[r][c] = pasteRows[ri][ci];
|
|
635
706
|
}
|
|
636
707
|
}
|
|
637
708
|
}
|
|
638
709
|
this._data = newData;
|
|
710
|
+
this._recompute();
|
|
639
711
|
this._pushHistory();
|
|
640
712
|
this._emitChange();
|
|
641
713
|
this.requestUpdate();
|
|
@@ -658,6 +730,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
658
730
|
}
|
|
659
731
|
}
|
|
660
732
|
this._data = newData;
|
|
733
|
+
this._recompute();
|
|
661
734
|
this._pushHistory();
|
|
662
735
|
this._emitChange();
|
|
663
736
|
this.requestUpdate();
|
|
@@ -677,6 +750,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
677
750
|
}
|
|
678
751
|
}
|
|
679
752
|
this._data = newData;
|
|
753
|
+
this._recompute();
|
|
680
754
|
this._pushHistory();
|
|
681
755
|
this._emitChange();
|
|
682
756
|
this.requestUpdate();
|
|
@@ -692,6 +766,15 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
692
766
|
this._editVal = typedChar !== void 0 ? typedChar : this._data[row]?.[col] ?? "";
|
|
693
767
|
this._editing = { row, col };
|
|
694
768
|
this._select(row, col);
|
|
769
|
+
const options = this._getColOptions(row, col);
|
|
770
|
+
if (options) {
|
|
771
|
+
const filtered = this._filterOptions(options, this._editVal);
|
|
772
|
+
this._dropdownItems = filtered;
|
|
773
|
+
this._dropdownIndex = filtered.length > 0 ? 0 : -1;
|
|
774
|
+
} else {
|
|
775
|
+
this._dropdownItems = [];
|
|
776
|
+
this._dropdownIndex = -1;
|
|
777
|
+
}
|
|
695
778
|
this.updateComplete.then(() => {
|
|
696
779
|
const input = this.renderRoot.querySelector(".cell-input");
|
|
697
780
|
if (input) {
|
|
@@ -708,12 +791,28 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
708
791
|
_commitEdit() {
|
|
709
792
|
if (!this._editing) return;
|
|
710
793
|
const { row, col } = this._editing;
|
|
794
|
+
const colDef = this.columns?.[col];
|
|
795
|
+
if (colDef?.strict && colDef?.options && this._editVal !== "") {
|
|
796
|
+
const allOptions = this._getColOptions(row, col) ?? [];
|
|
797
|
+
if (!allOptions.includes(this._editVal)) {
|
|
798
|
+
this._editing = null;
|
|
799
|
+
this._dropdownItems = [];
|
|
800
|
+
this._dropdownIndex = -1;
|
|
801
|
+
this._isDropdownClick = false;
|
|
802
|
+
this.requestUpdate();
|
|
803
|
+
this._containerEl?.focus();
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
711
807
|
const prevVal = this._data[row]?.[col] ?? "";
|
|
712
808
|
const newData = this._data.map((r) => [...r]);
|
|
713
809
|
newData[row][col] = this._editVal;
|
|
714
810
|
this._data = newData;
|
|
715
811
|
this._editing = null;
|
|
812
|
+
this._dropdownItems = [];
|
|
813
|
+
this._dropdownIndex = -1;
|
|
716
814
|
if (this._editVal !== prevVal) {
|
|
815
|
+
this._recompute();
|
|
717
816
|
this._pushHistory();
|
|
718
817
|
this._emitChange();
|
|
719
818
|
}
|
|
@@ -722,6 +821,8 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
722
821
|
}
|
|
723
822
|
_cancelEdit() {
|
|
724
823
|
this._editing = null;
|
|
824
|
+
this._dropdownItems = [];
|
|
825
|
+
this._dropdownIndex = -1;
|
|
725
826
|
this.requestUpdate();
|
|
726
827
|
this._containerEl?.focus();
|
|
727
828
|
}
|
|
@@ -735,6 +836,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
735
836
|
}
|
|
736
837
|
}
|
|
737
838
|
this._data = newData;
|
|
839
|
+
this._recompute();
|
|
738
840
|
this._pushHistory();
|
|
739
841
|
this._emitChange();
|
|
740
842
|
this.requestUpdate();
|
|
@@ -764,7 +866,35 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
764
866
|
return { row, col };
|
|
765
867
|
}
|
|
766
868
|
_isColReadonly(col) {
|
|
767
|
-
return this.columns?.[col]?.readonly ?? false;
|
|
869
|
+
return (this.columns?.[col]?.readonly ?? false) || this._isColComputed(col);
|
|
870
|
+
}
|
|
871
|
+
_isColComputed(col) {
|
|
872
|
+
return typeof this.columns?.[col]?.compute === "function";
|
|
873
|
+
}
|
|
874
|
+
/** compute 열을 재계산 (열 순서 좌→우, 행 순서 위→아래) */
|
|
875
|
+
_recompute() {
|
|
876
|
+
if (!this.columns?.some((c) => c.compute)) return;
|
|
877
|
+
for (let c = 0; c < this._colCount; c++) {
|
|
878
|
+
const fn = this.columns?.[c]?.compute;
|
|
879
|
+
if (!fn) continue;
|
|
880
|
+
for (let r = 0; r < this._rowCount; r++) {
|
|
881
|
+
try {
|
|
882
|
+
this._data[r][c] = fn(r, this._data);
|
|
883
|
+
} catch {
|
|
884
|
+
this._data[r][c] = "";
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
_getColOptions(row, col) {
|
|
890
|
+
const colDef = this.columns?.[col];
|
|
891
|
+
if (!colDef?.options) return null;
|
|
892
|
+
return typeof colDef.options === "function" ? colDef.options(row, col) : colDef.options;
|
|
893
|
+
}
|
|
894
|
+
_filterOptions(options, query) {
|
|
895
|
+
if (!query) return options;
|
|
896
|
+
const lower = query.toLowerCase();
|
|
897
|
+
return options.filter((o) => o.toLowerCase().includes(lower));
|
|
768
898
|
}
|
|
769
899
|
_emitChange() {
|
|
770
900
|
this.emit("change", { data: this._data });
|
|
@@ -804,6 +934,7 @@ const _USimpleSheet = class _USimpleSheet extends UElement {
|
|
|
804
934
|
const newData = this._data.map((r) => [...r]);
|
|
805
935
|
newData[row][col] = value;
|
|
806
936
|
this._data = newData;
|
|
937
|
+
this._recompute();
|
|
807
938
|
this._pushHistory();
|
|
808
939
|
this._emitChange();
|
|
809
940
|
this.requestUpdate();
|
|
@@ -850,6 +981,12 @@ __decorateClass([
|
|
|
850
981
|
__decorateClass([
|
|
851
982
|
state()
|
|
852
983
|
], _USimpleSheet.prototype, "_replaceOnEdit");
|
|
984
|
+
__decorateClass([
|
|
985
|
+
state()
|
|
986
|
+
], _USimpleSheet.prototype, "_dropdownItems");
|
|
987
|
+
__decorateClass([
|
|
988
|
+
state()
|
|
989
|
+
], _USimpleSheet.prototype, "_dropdownIndex");
|
|
853
990
|
let USimpleSheet = _USimpleSheet;
|
|
854
991
|
|
|
855
992
|
export { USimpleSheet };
|
|
@@ -197,7 +197,81 @@ const styles = css`
|
|
|
197
197
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
/*
|
|
200
|
+
/* Dropdown overlay */
|
|
201
|
+
.cell-dropdown {
|
|
202
|
+
position: absolute;
|
|
203
|
+
top: 100%;
|
|
204
|
+
left: -1px;
|
|
205
|
+
width: calc(100% + 2px);
|
|
206
|
+
min-width: 120px;
|
|
207
|
+
max-height: 200px;
|
|
208
|
+
overflow-y: auto;
|
|
209
|
+
background: var(--u-bg-color, #fff);
|
|
210
|
+
border: 1px solid var(--u-border-color, #e2e8f0);
|
|
211
|
+
border-top: none;
|
|
212
|
+
border-radius: 0 0 4px 4px;
|
|
213
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
|
214
|
+
z-index: 20;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.dropdown-item {
|
|
218
|
+
padding: 4px 8px;
|
|
219
|
+
font-size: 13px;
|
|
220
|
+
color: var(--u-txt-color, #0f172a);
|
|
221
|
+
cursor: pointer;
|
|
222
|
+
white-space: nowrap;
|
|
223
|
+
overflow: hidden;
|
|
224
|
+
text-overflow: ellipsis;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.dropdown-item:hover {
|
|
228
|
+
background: var(--u-neutral-100, #f1f5f9);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.dropdown-item.highlighted {
|
|
232
|
+
background: var(--u-blue-50, #eff6ff);
|
|
233
|
+
color: var(--u-blue-800, #1e40af);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.dropdown-empty {
|
|
237
|
+
padding: 6px 8px;
|
|
238
|
+
font-size: 12px;
|
|
239
|
+
color: var(--u-txt-color-weak, #64748b);
|
|
240
|
+
font-style: italic;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Readonly column/cell */
|
|
244
|
+
.cell.cell-readonly {
|
|
245
|
+
background: var(--u-neutral-50, #f8fafc);
|
|
246
|
+
color: var(--u-txt-color-weak, #64748b);
|
|
247
|
+
cursor: default;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.cell.cell-readonly.selected {
|
|
251
|
+
background: var(--u-neutral-100, #f1f5f9);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.cell.cell-readonly.anchor {
|
|
255
|
+
background: var(--u-neutral-50, #f8fafc);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Computed column/cell */
|
|
259
|
+
.cell.cell-computed {
|
|
260
|
+
background: var(--u-blue-50, #eff6ff);
|
|
261
|
+
color: var(--u-txt-color, #0f172a);
|
|
262
|
+
font-style: italic;
|
|
263
|
+
cursor: default;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.cell.cell-computed.selected {
|
|
267
|
+
background: var(--u-blue-100, #dbeafe);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.cell.cell-computed.anchor {
|
|
271
|
+
background: var(--u-blue-50, #eff6ff);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Readonly mode (whole sheet) */
|
|
201
275
|
:host([readonly]) .cell {
|
|
202
276
|
cursor: default;
|
|
203
277
|
}
|
|
@@ -254,6 +328,32 @@ const styles = css`
|
|
|
254
328
|
border-bottom-color: var(--u-border-color-weak, #2A2A2A);
|
|
255
329
|
}
|
|
256
330
|
|
|
331
|
+
:host-context([theme="dark"]) .cell.cell-readonly {
|
|
332
|
+
background: var(--u-neutral-100, #1E1E1E);
|
|
333
|
+
color: var(--u-txt-color-weak, #8A8A8A);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
:host-context([theme="dark"]) .cell.cell-readonly.selected {
|
|
337
|
+
background: var(--u-neutral-200, #2A2A2A);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
:host-context([theme="dark"]) .cell.cell-readonly.anchor {
|
|
341
|
+
background: var(--u-neutral-100, #1E1E1E);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
:host-context([theme="dark"]) .cell.cell-computed {
|
|
345
|
+
background: var(--u-blue-100, #1e3a5f);
|
|
346
|
+
color: var(--u-txt-color, #D4D4D4);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
:host-context([theme="dark"]) .cell.cell-computed.selected {
|
|
350
|
+
background: var(--u-blue-200, #2a4a6f);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
:host-context([theme="dark"]) .cell.cell-computed.anchor {
|
|
354
|
+
background: var(--u-blue-100, #1e3a5f);
|
|
355
|
+
}
|
|
356
|
+
|
|
257
357
|
:host-context([theme="dark"]) .cell.selected {
|
|
258
358
|
background: var(--u-blue-0, #0a1e3d);
|
|
259
359
|
}
|
|
@@ -273,6 +373,29 @@ const styles = css`
|
|
|
273
373
|
outline-color: var(--u-blue-500, #6ba3e3);
|
|
274
374
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
|
275
375
|
}
|
|
376
|
+
|
|
377
|
+
:host-context([theme="dark"]) .cell-dropdown {
|
|
378
|
+
background: var(--u-bg-color, #121212);
|
|
379
|
+
border-color: var(--u-border-color, #3D3D3D);
|
|
380
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
:host-context([theme="dark"]) .dropdown-item {
|
|
384
|
+
color: var(--u-txt-color, #D4D4D4);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
:host-context([theme="dark"]) .dropdown-item:hover {
|
|
388
|
+
background: var(--u-neutral-100, #1E1E1E);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
:host-context([theme="dark"]) .dropdown-item.highlighted {
|
|
392
|
+
background: var(--u-blue-100, #1e3a5f);
|
|
393
|
+
color: var(--u-blue-800, #c2deff);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
:host-context([theme="dark"]) .dropdown-empty {
|
|
397
|
+
color: var(--u-txt-color-weak, #8A8A8A);
|
|
398
|
+
}
|
|
276
399
|
`;
|
|
277
400
|
|
|
278
401
|
export { styles };
|