@iyulab/data-components 0.3.1 → 0.4.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,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.1] - 2026-05-07
4
+
5
+ ### Fixed
6
+ - eslint.config.js에서 제거된 React 플러그인 참조 삭제 (eslint-plugin-react-hooks, eslint-plugin-react-refresh)
7
+
8
+ ## [0.4.0] - 2026-05-07
9
+
10
+ ### BREAKING CHANGES
11
+ - `UDataGrid` 컴포넌트 제거 — DevExtreme 상용 라이선스 의존성 해소
12
+ - `src/components/data-grid/UDataGrid.tsx`, `UDataGrid.types.ts` 삭제
13
+ - `src/utilities/devExtremeCssInjection.ts`, `src/styles/devextreme-overrides.css` 삭제
14
+ - `exports['./data-grid']` 제거
15
+ - `dependencies`에서 `devextreme`, `devextreme-react`, `react`, `react-dom` 제거
16
+
17
+ ### Migration
18
+ UDataGrid 대체: `@iyulab/flex-table` + `@iyulab/flex-table/odata` 조합 사용
19
+ → [마이그레이션 가이드](./docs/migrating-from-datagrid.md)
20
+
21
+ ## [0.3.2] - 2026-05-07
22
+
23
+ ### Added
24
+ - `docs/migrating-from-datagrid.md`: UDataGrid(DevExtreme)에서 `@iyulab/flex-table`로 전환하는 마이그레이션 가이드 추가 (yesung-oms 9개 페이지 실증 기반)
25
+ - README에 UDataGrid 대안 섹션 및 마이그레이션 가이드 링크 추가
26
+ - `docs/UDataGrid.md` 상단에 마이그레이션 가이드 링크 추가
27
+
3
28
  ## [0.3.1] - 2026-04-01
4
29
  ### Changed
5
30
  - 컴포넌트 파일 구조 리팩토링: `.component.ts` 파일을 기존 `.ts`로 병합 (UDataView, USimpleSheet, URichTable)
package/README.md CHANGED
@@ -6,7 +6,11 @@
6
6
 
7
7
  - **USimpleSheet** — 엑셀 호환 스프레드시트 입력 컴포넌트 (Lit, compute 자동 계산 지원)
8
8
  - **UDataView** — Grid / List / Table 뷰 전환 컴포넌트 (Lit)
9
- - **UDataGrid** — OData 기반 서버 사이드 데이터 그리드 (React + DevExtreme)
9
+ - **URichTable** — 정렬/필터/편집/페이지네이션 지원 테이블 (Lit)
10
+
11
+ > **UDataGrid (DevExtreme)는 v0.4.0에서 제거되었습니다.**
12
+ > OData 서버 사이드 그리드가 필요하면 `@iyulab/flex-table`을 사용하세요.
13
+ > → [마이그레이션 가이드](./docs/migrating-from-datagrid.md)
10
14
 
11
15
  ## Installation
12
16
 
@@ -73,26 +77,12 @@ npm install @iyulab/data-components
73
77
  ></u-data-view>
74
78
  ```
75
79
 
76
- ### UDataGrid (React)
77
-
78
- ```tsx
79
- import { UDataGrid } from '@iyulab/data-components';
80
-
81
- <UDataGrid
82
- dataSourceUrl="https://api.example.com/odata/products"
83
- keyField="id"
84
- columns={[
85
- { dataField: 'name', caption: '상품명' },
86
- { dataField: 'price', caption: '가격', dataType: 'number' },
87
- ]}
88
- />
89
- ```
90
-
91
80
  ## Documentation
92
81
 
93
82
  - [USimpleSheet](./docs/USimpleSheet.md)
94
83
  - [UDataView](./docs/UDataView.md)
95
- - [UDataGrid](./docs/UDataGrid.md)
84
+ - [URichTable](./docs/URichTable.md)
85
+ - [UDataGrid 마이그레이션 가이드](./docs/migrating-from-datagrid.md)
96
86
 
97
87
  ## Theming
98
88
 
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.122.0/helpers/decorate.js
1
+ //#region \0@oxc-project+runtime@0.127.0/helpers/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.122.0/helpers/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.127.0/helpers/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.122.0/helpers/decorateMetadata.js";
3
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
2
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.js";
3
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/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";
@@ -1,5 +1,5 @@
1
- import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js";
2
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
1
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.js";
2
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/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";
@@ -1,5 +1,5 @@
1
- import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js";
2
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js";
1
+ import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorateMetadata.js";
2
+ import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js";
3
3
  import { richTableStyles } from "./styles.js";
4
4
  import { parseTSV, toTSV } from "./utils/clipboard.js";
5
5
  import { LitElement, html } from "lit";
@@ -578,8 +578,9 @@ var URichTable = class URichTable extends LitElement {
578
578
  _moveFocus(dx, dy) {
579
579
  if (!this.focusedCell) return;
580
580
  const newCol = Math.max(0, Math.min(this.columns.length - 1, this.focusedCell.colIndex + dx));
581
+ const newRow = Math.max(0, Math.min(this.data.length - 1, this.focusedCell.rowIndex + dy));
581
582
  this.focusedCell = {
582
- rowIndex: Math.max(0, Math.min(this.data.length - 1, this.focusedCell.rowIndex + dy)),
583
+ rowIndex: newRow,
583
584
  colIndex: newCol
584
585
  };
585
586
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- export { UDataGrid } from './components/data-grid/UDataGrid';
2
- export type { UDataGridColumn, UDataGridProps } from './components/data-grid/UDataGrid.types';
3
1
  export * from './components/data-view/UDataView';
4
2
  export * from './components/simple-sheet/USimpleSheet';
5
3
  export * from './components/u-rich-table/URichTable';
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- import { UDataGrid } from "./components/data-grid/UDataGrid.js";
2
1
  import { UDataView } from "./components/data-view/UDataView.js";
3
2
  import { USimpleSheet } from "./components/simple-sheet/USimpleSheet.js";
4
3
  import { URichTable } from "./components/u-rich-table/URichTable.js";
5
- export { UDataGrid, UDataView, URichTable, USimpleSheet };
4
+ export { UDataView, URichTable, USimpleSheet };
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.3.1",
4
+ "version": "0.4.1",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -31,13 +31,10 @@
31
31
  "./init": "./dist/init.js",
32
32
  "./simple-sheet": "./dist/components/simple-sheet/USimpleSheet.js",
33
33
  "./data-view": "./dist/components/data-view/UDataView.js",
34
- "./data-grid": "./dist/components/data-grid/UDataGrid.js",
35
34
  "./u-rich-table": "./dist/components/u-rich-table/URichTable.js"
36
35
  },
37
36
  "sideEffects": [
38
37
  "./dist/utilities/shadowDomProtection.js",
39
- "./dist/utilities/devExtremeCssInjection.js",
40
- "./dist/components/data-grid/UDataGrid.js",
41
38
  "./dist/components/data-view/UDataView.js",
42
39
  "./dist/components/simple-sheet/USimpleSheet.js",
43
40
  "./dist/components/u-rich-table/URichTable.js",
@@ -48,27 +45,18 @@
48
45
  "build": "eslint && vite build"
49
46
  },
50
47
  "dependencies": {
51
- "@iyulab/components": "^1.0.0",
52
- "devextreme": "^25.2.5",
53
- "devextreme-react": "^25.2.5",
54
- "lit": "^3.3.2",
55
- "react": "^19.2.4",
56
- "react-dom": "^19.2.4"
48
+ "@iyulab/components": "^1.0.4",
49
+ "lit": "^3.3.2"
57
50
  },
58
51
  "devDependencies": {
59
52
  "@eslint/js": "^9.39.4",
60
- "@types/node": "^25.5.0",
61
- "@types/react": "^19.2.14",
62
- "@types/react-dom": "^19.2.3",
63
- "@vitejs/plugin-react": "^6.0.1",
53
+ "@types/node": "^25.6.0",
64
54
  "eslint": "^9.39.4",
65
- "eslint-plugin-react-hooks": "^7.0.1",
66
- "eslint-plugin-react-refresh": "^0.5.2",
67
55
  "glob": "^13.0.6",
68
- "globals": "^17.4.0",
56
+ "globals": "^17.5.0",
69
57
  "typescript": "^5.9.3",
70
- "typescript-eslint": "^8.57.2",
71
- "vite": "^8.0.3",
58
+ "typescript-eslint": "^8.58.2",
59
+ "vite": "^8.0.8",
72
60
  "vite-plugin-dts": "^4.5.4"
73
61
  }
74
62
  }
@@ -1,2 +0,0 @@
1
- import { UDataGridProps } from './UDataGrid.types.js';
2
- export declare function UDataGrid({ dataSourceUrl, keyField, selectFields, columns, pageSize, showBorders, allowColumnReordering, allowColumnResizing, showGroupPanel, showSearchPanel, showFilterRow, showHeaderFilter, allowExport, exportFileName, isDevelopment, onDataLoaded, onDataLoadError, onExporting, onRowClick, beforeSend }: UDataGridProps): import("react/jsx-runtime").JSX.Element;
@@ -1,146 +0,0 @@
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
- });
144
- }
145
- //#endregion
146
- export { UDataGrid };
@@ -1,42 +0,0 @@
1
- export interface UDataGridColumn {
2
- dataField?: string;
3
- caption: string;
4
- width?: number;
5
- minWidth?: number;
6
- dataType?: 'string' | 'number' | 'date' | 'datetime' | 'boolean';
7
- format?: string;
8
- alignment?: 'left' | 'center' | 'right';
9
- fixed?: boolean;
10
- fixedPosition?: 'left' | 'right';
11
- allowHiding?: boolean;
12
- allowSorting?: boolean;
13
- allowFiltering?: boolean;
14
- allowGrouping?: boolean;
15
- sortOrder?: 'asc' | 'desc';
16
- cellRender?: (cellData: any) => React.ReactNode;
17
- visible?: boolean;
18
- }
19
- export interface UDataGridProps {
20
- dataSourceUrl: string;
21
- keyField: string;
22
- selectFields?: string[];
23
- columns: UDataGridColumn[];
24
- pageSize?: number;
25
- showBorders?: boolean;
26
- allowColumnReordering?: boolean;
27
- allowColumnResizing?: boolean;
28
- showGroupPanel?: boolean;
29
- showSearchPanel?: boolean;
30
- showFilterRow?: boolean;
31
- showHeaderFilter?: boolean;
32
- allowExport?: boolean;
33
- exportFileName?: string;
34
- isDevelopment?: boolean;
35
- onDataLoaded?: (data: any) => void;
36
- onDataLoadError?: (error: any) => void;
37
- onExporting?: (e: any) => void;
38
- onRowClick?: (e: {
39
- data: Record<string, unknown>;
40
- }) => void;
41
- beforeSend?: (operation: string, ajaxOptions: any) => void;
42
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * DevExtreme CSS Shadow DOM Injection
3
- *
4
- * DevExtreme components render inside Shadow DOM but their CSS is loaded
5
- * in the Light DOM. Due to Shadow DOM encapsulation, Light DOM CSS doesn't
6
- * apply to Shadow DOM content.
7
- *
8
- * This module:
9
- * 1. Imports DevExtreme CSS as text (using Vite ?inline query)
10
- * 2. Creates a CSSStyleSheet from the CSS text
11
- * 3. Injects the stylesheet into all Shadow DOMs
12
- * 4. Uses MutationObserver to detect and inject into new Shadow DOMs
13
- */
14
- /**
15
- * Initialize DevExtreme CSS injection
16
- * Sets up MutationObserver to detect new Shadow DOMs
17
- */
18
- export declare function initDevExtremeCssInjection(): void;
19
- /**
20
- * Register and inject custom CSS into all Shadow DOMs (existing and future)
21
- * Sets up automatic injection for new Shadow DOMs via MutationObserver
22
- */
23
- export declare function injectCssToShadowDoms(cssText: string): CSSStyleSheet | null;