@iyulab/data-components 0.3.0 → 0.3.1

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,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.1] - 2026-04-01
4
+ ### Changed
5
+ - 컴포넌트 파일 구조 리팩토링: `.component.ts` 파일을 기존 `.ts`로 병합 (UDataView, USimpleSheet, URichTable)
6
+ - UDataView: 다크모드 하드코딩 스타일 제거 — CSS 변수 기반으로 전환
7
+ - 의존성 업데이트: devextreme 25.2.5, vite 8.0.3, typescript-eslint 8.57.2 등
8
+
9
+ ## [0.3.0] - 2026-03-26
10
+ ### Added
11
+ - URichTable: 코어 컴포넌트 추가 — 렌더링, 정렬, 필터, 편집, 페이지네이션
12
+ - URichTable: 엑셀 스타일 클립보드(복사/붙여넣기) + 키보드 네비게이션
13
+ - URichTable: 다크모드 지원 (`:host-context([theme="dark"])`)
14
+ - USimpleSheet: `setSelection()`, `selectAll()` 공개 API 추가
15
+
3
16
  ## [0.1.8] - 2026-03-08
4
17
  ### Added
5
18
  - USimpleSheet: `format` 속성 — Intl.NumberFormatOptions(통화, 퍼센트 등) 또는 콜백 함수로 표시 포맷 지정
@@ -13,5 +26,30 @@
13
26
  - 에러 발생 시 빈 문자열 표시
14
27
  - 붙여넣기/Fill 시 compute 열 건너뛰기
15
28
 
16
- ## [0.1.6]
17
- - Initial library version release
29
+ ## [0.1.6] - 2026-03-08
30
+ ### Added
31
+ - USimpleSheet: 드롭다운 셀렉터 기능 (`options`/`strict` 속성)
32
+ - 드롭다운 상태 관리, 필터링, 키보드 네비게이션
33
+ - 다크모드 지원
34
+ ### Fixed
35
+ - USimpleSheet: 문자 입력 시 이중 입력 방지 (`preventDefault` 추가)
36
+ - USimpleSheet: strict 모드에서 `_isDropdownClick` 리셋 및 안전한 스크롤 처리
37
+
38
+ ## [0.1.4] - 2026-03-07
39
+ ### Changed
40
+ - UDataView, USimpleSheet: 다크모드 스타일 업데이트
41
+
42
+ ## [0.1.3] - 2026-03-07
43
+ ### Fixed
44
+ - Vite 빌드에 컴포넌트 엔트리 포인트 추가 (sub-path exports 수정)
45
+
46
+ ## [0.1.2] - 2026-03-07
47
+ ### Added
48
+ - 컴포넌트별 독립 임포트를 위한 sub-path exports 추가
49
+
50
+ ## [0.1.1] - 2026-03-06
51
+ ### Changed
52
+ - 재배포를 위한 버전 범프
53
+
54
+ ## [0.1.0] - 2026-03-06
55
+ - 초기 라이브러리 릴리스
@@ -0,0 +1,9 @@
1
+ //#region \0@oxc-project+runtime@0.122.0/helpers/decorate.js
2
+ function __decorate(decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ }
8
+ //#endregion
9
+ export { __decorate };
@@ -0,0 +1,6 @@
1
+ //#region \0@oxc-project+runtime@0.122.0/helpers/decorateMetadata.js
2
+ function __decorateMetadata(k, v) {
3
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
+ }
5
+ //#endregion
6
+ export { __decorateMetadata };
@@ -1,174 +1,146 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { useMemo } from 'react';
3
- import 'devextreme/data/odata/store';
4
- import DataGrid, { LoadPanel, Selection, FilterRow, HeaderFilter, SearchPanel, Grouping, GroupPanel, ColumnChooser, Paging, Export, Toolbar, Item, Column } from 'devextreme-react/data-grid';
5
-
6
- function UDataGrid({
7
- dataSourceUrl,
8
- keyField,
9
- selectFields,
10
- columns,
11
- pageSize = 25,
12
- showBorders = true,
13
- allowColumnReordering = true,
14
- allowColumnResizing = true,
15
- showGroupPanel = true,
16
- showSearchPanel = true,
17
- showFilterRow = true,
18
- showHeaderFilter = true,
19
- allowExport = true,
20
- exportFileName,
21
- isDevelopment = false,
22
- onDataLoaded,
23
- onDataLoadError,
24
- onExporting,
25
- onRowClick,
26
- beforeSend
27
- }) {
28
- const defaultBeforeSend = (operation, ajaxOptions) => {
29
- try {
30
- if (!ajaxOptions) {
31
- console.warn("ajaxOptions가 undefined입니다");
32
- return;
33
- }
34
- if (!ajaxOptions.headers || typeof ajaxOptions.headers !== "object") {
35
- ajaxOptions.headers = {};
36
- }
37
- ajaxOptions.headers["Accept"] = "application/json";
38
- ajaxOptions.headers["Content-Type"] = "application/json";
39
- if (isDevelopment) {
40
- ajaxOptions.crossDomain = true;
41
- ajaxOptions.headers["Access-Control-Allow-Origin"] = "*";
42
- }
43
- console.log(`U-DataGrid ${operation} 요청:`, {
44
- url: ajaxOptions.url,
45
- headers: ajaxOptions.headers,
46
- method: ajaxOptions.type || "GET"
47
- });
48
- } catch (error) {
49
- console.error("beforeSend 처리 중 오류:", error);
50
- }
51
- };
52
- const defaultOnLoadError = (error) => {
53
- console.error("U-DataGrid 데이터 로딩 오류:", error);
54
- let errorMessage = "데이터를 불러오는 오류가 발생했습니다.";
55
- try {
56
- if (error && typeof error === "object") {
57
- if (error.status === 404) {
58
- errorMessage = "API 엔드포인트를 찾을 수 없습니다. 서버가 실행중인지 확인해주세요.";
59
- } else if (error.status === 0) {
60
- errorMessage = "CORS 오류 또는 네트워크 연결 문제입니다. 서버 설정을 확인해주세요.";
61
- } else if (error.status >= 500) {
62
- errorMessage = "서버 내부 오류입니다. 서버 로그를 확인해주세요.";
63
- } else if (error.message) {
64
- errorMessage = error.message;
65
- } else if (typeof error === "string") {
66
- errorMessage = error;
67
- }
68
- }
69
- } catch (parseError) {
70
- console.error("오류 메시지 파싱 중 문제:", parseError);
71
- }
72
- alert(`${errorMessage}
73
-
74
- 요청 URL: ${dataSourceUrl}`);
75
- };
76
- const dataSource = useMemo(() => {
77
- return {
78
- store: {
79
- type: "odata",
80
- version: 4,
81
- url: dataSourceUrl,
82
- key: keyField,
83
- beforeSend: beforeSend || defaultBeforeSend,
84
- onLoading: () => {
85
- console.log("U-DataGrid 데이터 로딩 시작...");
86
- },
87
- onLoaded: (data) => {
88
- console.log("U-DataGrid 데이터 로딩 완료:", data);
89
- onDataLoaded?.(data);
90
- },
91
- onLoadError: onDataLoadError || defaultOnLoadError
92
- },
93
- select: selectFields
94
- };
95
- }, [dataSourceUrl, keyField, selectFields, beforeSend, onDataLoaded, onDataLoadError]);
96
- const handleExporting = (e) => {
97
- if (exportFileName) {
98
- e.fileName = exportFileName;
99
- } else {
100
- e.fileName = `DataGrid_Export_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
101
- }
102
- onExporting?.(e);
103
- };
104
- return /* @__PURE__ */ jsx("div", { style: {
105
- width: "100%",
106
- height: "100%",
107
- position: "relative",
108
- contain: "layout style",
109
- isolation: "isolate",
110
- overflow: "hidden"
111
- }, children: /* @__PURE__ */ jsxs(
112
- DataGrid,
113
- {
114
- dataSource,
115
- showBorders,
116
- allowColumnReordering,
117
- allowColumnResizing,
118
- columnAutoWidth: false,
119
- showColumnLines: true,
120
- showRowLines: true,
121
- rowAlternationEnabled: true,
122
- hoverStateEnabled: true,
123
- height: "100%",
124
- width: "100%",
125
- wordWrapEnabled: true,
126
- columnResizingMode: "widget",
127
- remoteOperations: true,
128
- onExporting: handleExporting,
129
- onRowClick,
130
- children: [
131
- /* @__PURE__ */ jsx(LoadPanel, { enabled: true }),
132
- /* @__PURE__ */ jsx(Selection, { mode: "multiple" }),
133
- showFilterRow && /* @__PURE__ */ jsx(FilterRow, { visible: true }),
134
- showHeaderFilter && /* @__PURE__ */ jsx(HeaderFilter, { visible: true }),
135
- showSearchPanel && /* @__PURE__ */ jsx(SearchPanel, { visible: true, placeholder: "검색..." }),
136
- /* @__PURE__ */ jsx(Grouping, { autoExpandAll: false }),
137
- showGroupPanel && /* @__PURE__ */ jsx(GroupPanel, { visible: true }),
138
- /* @__PURE__ */ jsx(ColumnChooser, { enabled: true }),
139
- /* @__PURE__ */ jsx(Paging, { defaultPageSize: pageSize }),
140
- allowExport && /* @__PURE__ */ jsx(Export, { enabled: true }),
141
- /* @__PURE__ */ jsxs(Toolbar, { children: [
142
- showGroupPanel && /* @__PURE__ */ jsx(Item, { name: "groupPanel" }),
143
- allowExport && /* @__PURE__ */ jsx(Item, { name: "exportButton" }),
144
- /* @__PURE__ */ jsx(Item, { name: "columnChooserButton" }),
145
- showSearchPanel && /* @__PURE__ */ jsx(Item, { name: "searchPanel" })
146
- ] }),
147
- columns.map((col, index) => /* @__PURE__ */ jsx(
148
- Column,
149
- {
150
- dataField: col.dataField,
151
- caption: col.caption,
152
- width: col.width,
153
- minWidth: col.minWidth,
154
- dataType: col.dataType,
155
- format: col.format,
156
- alignment: col.alignment,
157
- fixed: col.fixed,
158
- fixedPosition: col.fixedPosition,
159
- allowHiding: col.allowHiding,
160
- allowSorting: col.allowSorting,
161
- allowFiltering: col.allowFiltering,
162
- allowGrouping: col.allowGrouping,
163
- sortOrder: col.sortOrder,
164
- cellRender: col.cellRender,
165
- visible: col.visible
166
- },
167
- col.dataField || `column-${index}`
168
- ))
169
- ]
170
- }
171
- ) });
1
+ import { useMemo } from "react";
2
+ import "devextreme/data/odata/store";
3
+ import DataGrid, { Column, ColumnChooser, Export, FilterRow, GroupPanel, Grouping, HeaderFilter, Item, LoadPanel, Paging, SearchPanel, Selection, Toolbar } from "devextreme-react/data-grid";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/data-grid/UDataGrid.tsx
6
+ function UDataGrid({ dataSourceUrl, keyField, selectFields, columns, pageSize = 25, showBorders = true, allowColumnReordering = true, allowColumnResizing = true, showGroupPanel = true, showSearchPanel = true, showFilterRow = true, showHeaderFilter = true, allowExport = true, exportFileName, isDevelopment = false, onDataLoaded, onDataLoadError, onExporting, onRowClick, beforeSend }) {
7
+ const defaultBeforeSend = (operation, ajaxOptions) => {
8
+ try {
9
+ if (!ajaxOptions) {
10
+ console.warn("ajaxOptions가 undefined입니다");
11
+ return;
12
+ }
13
+ if (!ajaxOptions.headers || typeof ajaxOptions.headers !== "object") ajaxOptions.headers = {};
14
+ ajaxOptions.headers["Accept"] = "application/json";
15
+ ajaxOptions.headers["Content-Type"] = "application/json";
16
+ if (isDevelopment) {
17
+ ajaxOptions.crossDomain = true;
18
+ ajaxOptions.headers["Access-Control-Allow-Origin"] = "*";
19
+ }
20
+ console.log(`U-DataGrid ${operation} 요청:`, {
21
+ url: ajaxOptions.url,
22
+ headers: ajaxOptions.headers,
23
+ method: ajaxOptions.type || "GET"
24
+ });
25
+ } catch (error) {
26
+ console.error("beforeSend 처리 중 오류:", error);
27
+ }
28
+ };
29
+ const defaultOnLoadError = (error) => {
30
+ console.error("U-DataGrid 데이터 로딩 오류:", error);
31
+ let errorMessage = "데이터를 불러오는 중 오류가 발생했습니다.";
32
+ try {
33
+ if (error && typeof error === "object") {
34
+ if (error.status === 404) errorMessage = "API 엔드포인트를 찾을 수 없습니다. 서버가 실행중인지 확인해주세요.";
35
+ else if (error.status === 0) errorMessage = "CORS 오류 또는 네트워크 연결 문제입니다. 서버 설정을 확인해주세요.";
36
+ else if (error.status >= 500) errorMessage = "서버 내부 오류입니다. 서버 로그를 확인해주세요.";
37
+ else if (error.message) errorMessage = error.message;
38
+ else if (typeof error === "string") errorMessage = error;
39
+ }
40
+ } catch (parseError) {
41
+ console.error("오류 메시지 파싱 중 문제:", parseError);
42
+ }
43
+ alert(`${errorMessage}\n\n요청 URL: ${dataSourceUrl}`);
44
+ };
45
+ const dataSource = useMemo(() => {
46
+ return {
47
+ store: {
48
+ type: "odata",
49
+ version: 4,
50
+ url: dataSourceUrl,
51
+ key: keyField,
52
+ beforeSend: beforeSend || defaultBeforeSend,
53
+ onLoading: () => {
54
+ console.log("U-DataGrid 데이터 로딩 시작...");
55
+ },
56
+ onLoaded: (data) => {
57
+ console.log("U-DataGrid 데이터 로딩 완료:", data);
58
+ onDataLoaded?.(data);
59
+ },
60
+ onLoadError: onDataLoadError || defaultOnLoadError
61
+ },
62
+ select: selectFields
63
+ };
64
+ }, [
65
+ dataSourceUrl,
66
+ keyField,
67
+ selectFields,
68
+ beforeSend,
69
+ onDataLoaded,
70
+ onDataLoadError
71
+ ]);
72
+ const handleExporting = (e) => {
73
+ if (exportFileName) e.fileName = exportFileName;
74
+ else e.fileName = `DataGrid_Export_${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
75
+ onExporting?.(e);
76
+ };
77
+ return /* @__PURE__ */ jsx("div", {
78
+ style: {
79
+ width: "100%",
80
+ height: "100%",
81
+ position: "relative",
82
+ contain: "layout style",
83
+ isolation: "isolate",
84
+ overflow: "hidden"
85
+ },
86
+ children: /* @__PURE__ */ jsxs(DataGrid, {
87
+ dataSource,
88
+ showBorders,
89
+ allowColumnReordering,
90
+ allowColumnResizing,
91
+ columnAutoWidth: false,
92
+ showColumnLines: true,
93
+ showRowLines: true,
94
+ rowAlternationEnabled: true,
95
+ hoverStateEnabled: true,
96
+ height: "100%",
97
+ width: "100%",
98
+ wordWrapEnabled: true,
99
+ columnResizingMode: "widget",
100
+ remoteOperations: true,
101
+ onExporting: handleExporting,
102
+ onRowClick,
103
+ children: [
104
+ /* @__PURE__ */ jsx(LoadPanel, { enabled: true }),
105
+ /* @__PURE__ */ jsx(Selection, { mode: "multiple" }),
106
+ showFilterRow && /* @__PURE__ */ jsx(FilterRow, { visible: true }),
107
+ showHeaderFilter && /* @__PURE__ */ jsx(HeaderFilter, { visible: true }),
108
+ showSearchPanel && /* @__PURE__ */ jsx(SearchPanel, {
109
+ visible: true,
110
+ placeholder: "검색..."
111
+ }),
112
+ /* @__PURE__ */ jsx(Grouping, { autoExpandAll: false }),
113
+ showGroupPanel && /* @__PURE__ */ jsx(GroupPanel, { visible: true }),
114
+ /* @__PURE__ */ jsx(ColumnChooser, { enabled: true }),
115
+ /* @__PURE__ */ jsx(Paging, { defaultPageSize: pageSize }),
116
+ allowExport && /* @__PURE__ */ jsx(Export, { enabled: true }),
117
+ /* @__PURE__ */ jsxs(Toolbar, { children: [
118
+ showGroupPanel && /* @__PURE__ */ jsx(Item, { name: "groupPanel" }),
119
+ allowExport && /* @__PURE__ */ jsx(Item, { name: "exportButton" }),
120
+ /* @__PURE__ */ jsx(Item, { name: "columnChooserButton" }),
121
+ showSearchPanel && /* @__PURE__ */ jsx(Item, { name: "searchPanel" })
122
+ ] }),
123
+ columns.map((col, index) => /* @__PURE__ */ jsx(Column, {
124
+ dataField: col.dataField,
125
+ caption: col.caption,
126
+ width: col.width,
127
+ minWidth: col.minWidth,
128
+ dataType: col.dataType,
129
+ format: col.format,
130
+ alignment: col.alignment,
131
+ fixed: col.fixed,
132
+ fixedPosition: col.fixedPosition,
133
+ allowHiding: col.allowHiding,
134
+ allowSorting: col.allowSorting,
135
+ allowFiltering: col.allowFiltering,
136
+ allowGrouping: col.allowGrouping,
137
+ sortOrder: col.sortOrder,
138
+ cellRender: col.cellRender,
139
+ visible: col.visible
140
+ }, col.dataField || `column-${index}`))
141
+ ]
142
+ })
143
+ });
172
144
  }
173
-
145
+ //#endregion
174
146
  export { UDataGrid };
@@ -1,8 +1,49 @@
1
- import { UDataView } from './UDataView.component.js';
1
+ import { TemplateResult } from 'lit';
2
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
3
+ export type ViewMode = 'grid' | 'list' | 'table';
4
+ export interface DataColumn {
5
+ key: string;
6
+ label?: string;
7
+ width?: string;
8
+ }
9
+ /**
10
+ * Data View Component
11
+ * 데이터를 3가지 레이아웃(grid, list, table)으로 표시하는 컴포넌트
12
+ */
13
+ export declare class UDataView extends UElement {
14
+ static styles: import('lit').CSSResultGroup[];
15
+ /** 표시할 데이터 배열 */
16
+ items: any[];
17
+ /** 현재 뷰 모드 */
18
+ mode: ViewMode;
19
+ /** 표시할 컬럼 설정 (미지정시 자동 감지) */
20
+ columns?: DataColumn[];
21
+ /** 그리드 모드 최소 폭 */
22
+ gridMinWidth: string;
23
+ /** 아이템 간격 */
24
+ gap: string;
25
+ /** 커스텀 렌더 함수 (grid/list 카드용) */
26
+ renderCard?: (item: any, index: number) => TemplateResult;
27
+ /** 커스텀 셀 렌더 함수 (table용) */
28
+ renderCell?: (item: any, column: DataColumn, index: number) => TemplateResult | string;
29
+ private selectedIndex;
30
+ render(): TemplateResult<1>;
31
+ private renderToolbar;
32
+ private renderViewButton;
33
+ private renderContent;
34
+ private renderGrid;
35
+ private renderList;
36
+ private renderTable;
37
+ private renderGridItem;
38
+ private renderListItem;
39
+ private renderDefaultCard;
40
+ private getCellContent;
41
+ private getColumns;
42
+ private formatLabel;
43
+ private formatValue;
44
+ }
2
45
  declare global {
3
46
  interface HTMLElementTagNameMap {
4
47
  "u-data-view": UDataView;
5
48
  }
6
49
  }
7
- export { UDataView };
8
- export type { Column, ViewMode } from './UDataView.component.js';
@@ -1,5 +1,173 @@
1
- import { UDataView } from './UDataView.component.js';
2
-
3
- UDataView.define("u-data-view");
4
-
1
+ import { styles } from "./UDataView.styles.js";
2
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js";
3
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
4
+ import { html } from "lit";
5
+ import { customElement, property, state } from "lit/decorators.js";
6
+ import "@iyulab/components/dist/components/icon/UIcon.js";
7
+ import "@iyulab/components/dist/components/button/UButton.js";
8
+ import { UElement } from "@iyulab/components/dist/components/UElement.js";
9
+ //#region src/components/data-view/UDataView.ts
10
+ var UDataView = class UDataView extends UElement {
11
+ constructor(..._args) {
12
+ super(..._args);
13
+ this.items = [];
14
+ this.mode = "grid";
15
+ this.gridMinWidth = "200px";
16
+ this.gap = "1rem";
17
+ this.selectedIndex = null;
18
+ }
19
+ static {
20
+ this.styles = [super.styles, styles];
21
+ }
22
+ render() {
23
+ return html`
24
+ <div class="data-view">
25
+ ${this.renderToolbar()}
26
+ ${this.renderContent()}
27
+ </div>
28
+ `;
29
+ }
30
+ renderToolbar() {
31
+ return html`
32
+ <div class="toolbar">
33
+ <div class="view-toggles">
34
+ ${this.renderViewButton("grid", "grid-3x3-gap", "Grid")}
35
+ ${this.renderViewButton("list", "list-ul", "List")}
36
+ ${this.renderViewButton("table", "table", "Table")}
37
+ </div>
38
+ <div class="info">
39
+ ${this.items.length} items
40
+ </div>
41
+ </div>
42
+ `;
43
+ }
44
+ renderViewButton(mode, icon, label) {
45
+ return html`
46
+ <u-button
47
+ ?active=${this.mode === mode}
48
+ title=${label}
49
+ >
50
+ <u-icon lib="bootstrap" name=${icon}></u-icon>
51
+ </u-button>
52
+ `;
53
+ }
54
+ renderContent() {
55
+ if (!this.items?.length) return html`<div class="empty">No data available</div>`;
56
+ switch (this.mode) {
57
+ case "grid": return this.renderGrid();
58
+ case "list": return this.renderList();
59
+ case "table": return this.renderTable();
60
+ }
61
+ }
62
+ renderGrid() {
63
+ return html`
64
+ <div class="grid" style="--min-width: ${this.gridMinWidth}; --gap: ${this.gap};">
65
+ ${this.items.map((item, index) => this.renderGridItem(item, index))}
66
+ </div>
67
+ `;
68
+ }
69
+ renderList() {
70
+ return html`
71
+ <div class="list" style="--gap: ${this.gap};">
72
+ ${this.items.map((item, index) => this.renderListItem(item, index))}
73
+ </div>
74
+ `;
75
+ }
76
+ renderTable() {
77
+ const cols = this.getColumns();
78
+ return html`
79
+ <div class="table-wrapper">
80
+ <table>
81
+ <thead>
82
+ <tr>
83
+ ${cols.map((col) => html`
84
+ <th style=${col.width ? `width: ${col.width}` : ""}>
85
+ ${col.label || this.formatLabel(col.key)}
86
+ </th>
87
+ `)}
88
+ </tr>
89
+ </thead>
90
+ <tbody>
91
+ ${this.items.map((item, index) => html`
92
+ <tr
93
+ class=${this.selectedIndex === index ? "selected" : ""}
94
+ >
95
+ ${cols.map((col) => html`
96
+ <td>${this.getCellContent(item, col, index)}</td>
97
+ `)}
98
+ </tr>
99
+ `)}
100
+ </tbody>
101
+ </table>
102
+ </div>
103
+ `;
104
+ }
105
+ renderGridItem(item, index) {
106
+ const content = this.renderCard ? this.renderCard(item, index) : this.renderDefaultCard(item);
107
+ return html`
108
+ <div
109
+ class="card ${this.selectedIndex === index ? "selected" : ""}"
110
+ >
111
+ ${content}
112
+ </div>
113
+ `;
114
+ }
115
+ renderListItem(item, index) {
116
+ const content = this.renderCard ? this.renderCard(item, index) : this.renderDefaultCard(item);
117
+ return html`
118
+ <div
119
+ class="card list-card ${this.selectedIndex === index ? "selected" : ""}"
120
+ >
121
+ ${content}
122
+ </div>
123
+ `;
124
+ }
125
+ renderDefaultCard(item) {
126
+ return html`
127
+ <div class="card-content">
128
+ ${this.getColumns().slice(0, 5).map((col) => {
129
+ const value = item[col.key];
130
+ return html`
131
+ <div class="card-field">
132
+ <span class="label">${col.label || this.formatLabel(col.key)}:</span>
133
+ <span class="value">${this.formatValue(value)}</span>
134
+ </div>
135
+ `;
136
+ })}
137
+ </div>
138
+ `;
139
+ }
140
+ getCellContent(item, column, index) {
141
+ if (this.renderCell) return this.renderCell(item, column, index);
142
+ return this.formatValue(item[column.key]);
143
+ }
144
+ getColumns() {
145
+ if (this.columns?.length) return this.columns;
146
+ if (this.items.length > 0) {
147
+ const firstItem = this.items[0];
148
+ return Object.keys(firstItem).map((key) => ({ key }));
149
+ }
150
+ return [];
151
+ }
152
+ formatLabel(key) {
153
+ return key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).trim();
154
+ }
155
+ formatValue(value) {
156
+ if (value == null) return "—";
157
+ if (typeof value === "boolean") return value ? "✓" : "✗";
158
+ if (value instanceof Date) return value.toLocaleString();
159
+ if (typeof value === "object") return JSON.stringify(value);
160
+ return String(value);
161
+ }
162
+ };
163
+ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UDataView.prototype, "items", void 0);
164
+ __decorate([property({ type: String }), __decorateMetadata("design:type", Object)], UDataView.prototype, "mode", void 0);
165
+ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UDataView.prototype, "columns", void 0);
166
+ __decorate([property({ type: String }), __decorateMetadata("design:type", Object)], UDataView.prototype, "gridMinWidth", void 0);
167
+ __decorate([property({ type: String }), __decorateMetadata("design:type", Object)], UDataView.prototype, "gap", void 0);
168
+ __decorate([property({ attribute: false }), __decorateMetadata("design:type", Function)], UDataView.prototype, "renderCard", void 0);
169
+ __decorate([property({ attribute: false }), __decorateMetadata("design:type", Function)], UDataView.prototype, "renderCell", void 0);
170
+ __decorate([state(), __decorateMetadata("design:type", Object)], UDataView.prototype, "selectedIndex", void 0);
171
+ UDataView = __decorate([customElement("u-data-view")], UDataView);
172
+ //#endregion
5
173
  export { UDataView };