@iyulab/data-components 0.3.1 → 0.5.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 +40 -0
- package/README.md +46 -13
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorate.js +1 -1
- package/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.133.0/helpers/esm}/decorateMetadata.js +1 -1
- package/dist/components/data-view/UDataView.js +2 -2
- package/dist/components/simple-sheet/USimpleSheet.js +2 -2
- package/dist/components/u-rich-table/URichTable.js +4 -3
- package/dist/index.d.ts +0 -2
- package/dist/index.js +2 -2
- package/dist/react.d.ts +29 -0
- package/dist/react.js +48 -0
- package/dist/utilities/shadowDomProtection.js +99 -0
- package/package.json +31 -19
- package/dist/components/data-grid/UDataGrid.d.ts +0 -2
- package/dist/components/data-grid/UDataGrid.js +0 -146
- package/dist/components/data-grid/UDataGrid.types.d.ts +0 -42
- package/dist/utilities/devExtremeCssInjection.d.ts +0 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0] - 2026-06-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- React 일급 래퍼 서브패스 `@iyulab/data-components/react` (`@lit/react` createComponent 기반)
|
|
7
|
+
- `USimpleSheetReact` / `UDataViewReact` / `URichTableReact`
|
|
8
|
+
- rich property를 JSX props로 직접 전달, 커스텀 이벤트는 타입드 `onXxx` props로 노출
|
|
9
|
+
(USimpleSheet `onChange`, URichTable은 `RichTableEventMap` 9종 전부)
|
|
10
|
+
- `@lit/react`, `react`는 optional peerDependency — React 미사용 소비자에 영향 없음
|
|
11
|
+
- README에 React 사용법 및 TypeScript 직접 사용(HTMLElementTagNameMap) 안내 추가
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- `sideEffects`가 dist 경로만 나열해 빌드 시 `shadowDomProtection` 자동 초기화 import가
|
|
15
|
+
번들에서 제거되던 문제 수정 (src 경로 추가) — 0.4.x 배포본에서 Shadow DOM 스타일 보호가
|
|
16
|
+
실제로 동작하지 않던 잠재 결함
|
|
17
|
+
|
|
18
|
+
## [0.4.1] - 2026-05-07
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- eslint.config.js에서 제거된 React 플러그인 참조 삭제 (eslint-plugin-react-hooks, eslint-plugin-react-refresh)
|
|
22
|
+
|
|
23
|
+
## [0.4.0] - 2026-05-07
|
|
24
|
+
|
|
25
|
+
### BREAKING CHANGES
|
|
26
|
+
- `UDataGrid` 컴포넌트 제거 — DevExtreme 상용 라이선스 의존성 해소
|
|
27
|
+
- `src/components/data-grid/UDataGrid.tsx`, `UDataGrid.types.ts` 삭제
|
|
28
|
+
- `src/utilities/devExtremeCssInjection.ts`, `src/styles/devextreme-overrides.css` 삭제
|
|
29
|
+
- `exports['./data-grid']` 제거
|
|
30
|
+
- `dependencies`에서 `devextreme`, `devextreme-react`, `react`, `react-dom` 제거
|
|
31
|
+
|
|
32
|
+
### Migration
|
|
33
|
+
UDataGrid 대체: `@iyulab/flex-table` + `@iyulab/flex-table/odata` 조합 사용
|
|
34
|
+
→ [마이그레이션 가이드](./docs/migrating-from-datagrid.md)
|
|
35
|
+
|
|
36
|
+
## [0.3.2] - 2026-05-07
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- `docs/migrating-from-datagrid.md`: UDataGrid(DevExtreme)에서 `@iyulab/flex-table`로 전환하는 마이그레이션 가이드 추가 (yesung-oms 9개 페이지 실증 기반)
|
|
40
|
+
- README에 UDataGrid 대안 섹션 및 마이그레이션 가이드 링크 추가
|
|
41
|
+
- `docs/UDataGrid.md` 상단에 마이그레이션 가이드 링크 추가
|
|
42
|
+
|
|
3
43
|
## [0.3.1] - 2026-04-01
|
|
4
44
|
### Changed
|
|
5
45
|
- 컴포넌트 파일 구조 리팩토링: `.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
|
-
- **
|
|
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,55 @@ npm install @iyulab/data-components
|
|
|
73
77
|
></u-data-view>
|
|
74
78
|
```
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
## React
|
|
81
|
+
|
|
82
|
+
`@lit/react` 기반 일급 래퍼를 `/react` 서브패스로 제공합니다. rich property(`data`, `columns` 등)를
|
|
83
|
+
JSX props로 직접 전달할 수 있고, 커스텀 이벤트는 `onXxx` props로 받습니다 — ref + `useEffect`
|
|
84
|
+
브리지가 필요 없습니다.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm install @iyulab/data-components @lit/react react
|
|
88
|
+
```
|
|
77
89
|
|
|
78
90
|
```tsx
|
|
79
|
-
import {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
import { USimpleSheetReact, type SheetColumn } from '@iyulab/data-components/react';
|
|
92
|
+
|
|
93
|
+
const columns: SheetColumn[] = [
|
|
94
|
+
{ key: 'name', label: '이름', width: 150 },
|
|
95
|
+
{ key: 'email', label: '이메일', width: 220 },
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
export function MySheet() {
|
|
99
|
+
return (
|
|
100
|
+
<USimpleSheetReact
|
|
101
|
+
style={{ height: 400 }}
|
|
102
|
+
columns={columns}
|
|
103
|
+
data={[['홍길동', 'hong@example.com']]}
|
|
104
|
+
rows={25}
|
|
105
|
+
onChange={(e) => console.log(e.detail.data)}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`URichTableReact`는 `RichTableEventMap`의 모든 이벤트(`onRowUpdate`, `onSortChange`,
|
|
112
|
+
`onSelectionChange` 등)를 타입드 props로 노출합니다. `UDataViewReact`도 동일하게 제공됩니다.
|
|
113
|
+
|
|
114
|
+
타입스크립트만 필요하다면 래퍼 없이도 엘리먼트 클래스와 `HTMLElementTagNameMap` 증강이
|
|
115
|
+
메인 엔트리에서 제공됩니다:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import type { USimpleSheet } from '@iyulab/data-components';
|
|
119
|
+
|
|
120
|
+
const sheet = document.querySelector('u-simple-sheet'); // USimpleSheet | null 로 추론
|
|
89
121
|
```
|
|
90
122
|
|
|
91
123
|
## Documentation
|
|
92
124
|
|
|
93
125
|
- [USimpleSheet](./docs/USimpleSheet.md)
|
|
94
126
|
- [UDataView](./docs/UDataView.md)
|
|
95
|
-
- [
|
|
127
|
+
- [URichTable](./docs/URichTable.md)
|
|
128
|
+
- [UDataGrid 마이그레이션 가이드](./docs/migrating-from-datagrid.md)
|
|
96
129
|
|
|
97
130
|
## Theming
|
|
98
131
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region \0@oxc-project+runtime@0.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.133.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.
|
|
1
|
+
//#region \0@oxc-project+runtime@0.133.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.
|
|
3
|
-
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.
|
|
2
|
+
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
3
|
+
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.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";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.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";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.
|
|
2
|
-
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import { __decorateMetadata } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/decorateMetadata.js";
|
|
2
|
+
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.133.0/helpers/esm/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:
|
|
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,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./utilities/shadowDomProtection.js";
|
|
2
2
|
import { UDataView } from "./components/data-view/UDataView.js";
|
|
3
3
|
import { USimpleSheet } from "./components/simple-sheet/USimpleSheet.js";
|
|
4
4
|
import { URichTable } from "./components/u-rich-table/URichTable.js";
|
|
5
|
-
export {
|
|
5
|
+
export { UDataView, URichTable, USimpleSheet };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventName } from '@lit/react';
|
|
2
|
+
import { USimpleSheet } from './components/simple-sheet/USimpleSheet';
|
|
3
|
+
import { UDataView } from './components/data-view/UDataView';
|
|
4
|
+
import { URichTable } from './components/u-rich-table/URichTable';
|
|
5
|
+
import { RichTableEventMap } from './components/u-rich-table/types';
|
|
6
|
+
/** USimpleSheet React 래퍼 — `change` 이벤트는 `onChange`로 노출 */
|
|
7
|
+
export declare const USimpleSheetReact: import('@lit/react').ReactWebComponent<USimpleSheet, {
|
|
8
|
+
onChange: EventName<CustomEvent<{
|
|
9
|
+
data: string[][];
|
|
10
|
+
}>>;
|
|
11
|
+
}>;
|
|
12
|
+
/** UDataView React 래퍼 */
|
|
13
|
+
export declare const UDataViewReact: import('@lit/react').ReactWebComponent<UDataView, {}>;
|
|
14
|
+
/** URichTable React 래퍼 — RichTableEventMap의 모든 이벤트를 onXxx로 노출 */
|
|
15
|
+
export declare const URichTableReact: import('@lit/react').ReactWebComponent<URichTable, {
|
|
16
|
+
onSelectionChange: EventName<RichTableEventMap["selection-change"]>;
|
|
17
|
+
onRowCreate: EventName<RichTableEventMap["row-create"]>;
|
|
18
|
+
onRowUpdate: EventName<RichTableEventMap["row-update"]>;
|
|
19
|
+
onRowDelete: EventName<RichTableEventMap["row-delete"]>;
|
|
20
|
+
onRowExpand: EventName<RichTableEventMap["row-expand"]>;
|
|
21
|
+
onSortChange: EventName<RichTableEventMap["sort-change"]>;
|
|
22
|
+
onFilterChange: EventName<RichTableEventMap["filter-change"]>;
|
|
23
|
+
onPageChange: EventName<RichTableEventMap["page-change"]>;
|
|
24
|
+
onPaste: EventName<RichTableEventMap["paste"]>;
|
|
25
|
+
}>;
|
|
26
|
+
export { USimpleSheet, UDataView, URichTable };
|
|
27
|
+
export type { SheetColumn } from './components/simple-sheet/USimpleSheet';
|
|
28
|
+
export type { DataColumn, ViewMode } from './components/data-view/UDataView';
|
|
29
|
+
export type { ColumnDef, CellPosition, SortState, FilterState, RichTableEventMap, } from './components/u-rich-table/types';
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "./utilities/shadowDomProtection.js";
|
|
2
|
+
import { UDataView } from "./components/data-view/UDataView.js";
|
|
3
|
+
import { USimpleSheet } from "./components/simple-sheet/USimpleSheet.js";
|
|
4
|
+
import { URichTable } from "./components/u-rich-table/URichTable.js";
|
|
5
|
+
import React from "react";
|
|
6
|
+
import { createComponent } from "@lit/react";
|
|
7
|
+
//#region src/react.ts
|
|
8
|
+
/**
|
|
9
|
+
* React 래퍼 엔트리 (`@iyulab/data-components/react`)
|
|
10
|
+
*
|
|
11
|
+
* `@lit/react` createComponent 기반 — rich property(`data`, `columns` 등)를
|
|
12
|
+
* JSX props로 직접 전달할 수 있고, 커스텀 이벤트는 `onXxx` props로 노출됩니다.
|
|
13
|
+
*
|
|
14
|
+
* react / @lit/react 는 optional peerDependency — 이 서브패스를 import하는
|
|
15
|
+
* React 소비자에게만 필요합니다.
|
|
16
|
+
*/
|
|
17
|
+
/** USimpleSheet React 래퍼 — `change` 이벤트는 `onChange`로 노출 */
|
|
18
|
+
var USimpleSheetReact = createComponent({
|
|
19
|
+
tagName: "u-simple-sheet",
|
|
20
|
+
elementClass: USimpleSheet,
|
|
21
|
+
react: React,
|
|
22
|
+
events: { onChange: "change" }
|
|
23
|
+
});
|
|
24
|
+
/** UDataView React 래퍼 */
|
|
25
|
+
var UDataViewReact = createComponent({
|
|
26
|
+
tagName: "u-data-view",
|
|
27
|
+
elementClass: UDataView,
|
|
28
|
+
react: React
|
|
29
|
+
});
|
|
30
|
+
/** URichTable React 래퍼 — RichTableEventMap의 모든 이벤트를 onXxx로 노출 */
|
|
31
|
+
var URichTableReact = createComponent({
|
|
32
|
+
tagName: "u-rich-table",
|
|
33
|
+
elementClass: URichTable,
|
|
34
|
+
react: React,
|
|
35
|
+
events: {
|
|
36
|
+
onSelectionChange: "selection-change",
|
|
37
|
+
onRowCreate: "row-create",
|
|
38
|
+
onRowUpdate: "row-update",
|
|
39
|
+
onRowDelete: "row-delete",
|
|
40
|
+
onRowExpand: "row-expand",
|
|
41
|
+
onSortChange: "sort-change",
|
|
42
|
+
onFilterChange: "filter-change",
|
|
43
|
+
onPageChange: "page-change",
|
|
44
|
+
onPaste: "paste"
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
//#endregion
|
|
48
|
+
export { UDataView, UDataViewReact, URichTable, URichTableReact, USimpleSheet, USimpleSheetReact };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
//#region src/utilities/shadowDomProtection.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shadow DOM Style Protection
|
|
4
|
+
*
|
|
5
|
+
* Protects Lit component styles from being overwritten by Vite HMR.
|
|
6
|
+
* When DevExtreme or other libraries load CSS, Vite HMR may clear/replace
|
|
7
|
+
* Shadow DOM's adoptedStyleSheets, causing Lit component styles to be lost.
|
|
8
|
+
*
|
|
9
|
+
* This module intercepts adoptedStyleSheets setter to:
|
|
10
|
+
* 1. Detect and save Lit styles (identified by :host selector)
|
|
11
|
+
* 2. Block HMR reset attempts that would clear Lit styles
|
|
12
|
+
* 3. Merge Lit styles with other styles (like DevExtreme)
|
|
13
|
+
* 4. Protect registered custom stylesheets from being lost during re-renders
|
|
14
|
+
*/
|
|
15
|
+
var isInitialized = false;
|
|
16
|
+
var protectedCustomStylesheets = /* @__PURE__ */ new Set();
|
|
17
|
+
/**
|
|
18
|
+
* Check if a stylesheet is a protected custom stylesheet
|
|
19
|
+
*/
|
|
20
|
+
function isProtectedCustomStylesheet(sheet) {
|
|
21
|
+
return protectedCustomStylesheets.has(sheet);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if a stylesheet is a Lit component stylesheet
|
|
25
|
+
* Lit styles typically start with :host selector
|
|
26
|
+
*/
|
|
27
|
+
function isLitStyleSheet(sheet) {
|
|
28
|
+
try {
|
|
29
|
+
if (!sheet.cssRules || sheet.cssRules.length === 0) return false;
|
|
30
|
+
return sheet.cssRules[0].cssText.startsWith(":host");
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Check if the sheets array is empty or an HMR reset attempt
|
|
37
|
+
* Vite HMR may set adoptedStyleSheets to empty array or sheets without rules
|
|
38
|
+
*/
|
|
39
|
+
function isEmptyOrHMRReset(sheets) {
|
|
40
|
+
if (!sheets || sheets.length === 0) return true;
|
|
41
|
+
return sheets.every((sheet) => {
|
|
42
|
+
try {
|
|
43
|
+
return !sheet.cssRules || sheet.cssRules.length === 0;
|
|
44
|
+
} catch {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Initialize Shadow DOM style protection
|
|
51
|
+
* Should be called before any Lit components are loaded
|
|
52
|
+
*/
|
|
53
|
+
function initShadowDomProtection() {
|
|
54
|
+
if (isInitialized) return;
|
|
55
|
+
if (typeof window === "undefined") return;
|
|
56
|
+
const originalDescriptor = Object.getOwnPropertyDescriptor(ShadowRoot.prototype, "adoptedStyleSheets");
|
|
57
|
+
if (!originalDescriptor) {
|
|
58
|
+
console.warn("[data-components] adoptedStyleSheets descriptor not found");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const protectedLitStylesMap = /* @__PURE__ */ new WeakMap();
|
|
62
|
+
Object.defineProperty(ShadowRoot.prototype, "adoptedStyleSheets", {
|
|
63
|
+
get() {
|
|
64
|
+
return originalDescriptor.get?.call(this) ?? [];
|
|
65
|
+
},
|
|
66
|
+
set(sheets) {
|
|
67
|
+
const savedLitStyles = protectedLitStylesMap.get(this) || [];
|
|
68
|
+
const newLitStyles = sheets?.filter(isLitStyleSheet) || [];
|
|
69
|
+
const newNonLitStyles = sheets?.filter((s) => !isLitStyleSheet(s)) || [];
|
|
70
|
+
if (newLitStyles.length > 0) protectedLitStylesMap.set(this, [...newLitStyles]);
|
|
71
|
+
const protectedSheets = Array.from(protectedCustomStylesheets);
|
|
72
|
+
if (isEmptyOrHMRReset(sheets) && (savedLitStyles.length > 0 || protectedSheets.length > 0)) {
|
|
73
|
+
const preserved = [...savedLitStyles, ...protectedSheets.filter((s) => !savedLitStyles.includes(s))];
|
|
74
|
+
originalDescriptor.set?.call(this, preserved);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (savedLitStyles.length > 0 && newLitStyles.length === 0 && newNonLitStyles.length > 0) {
|
|
78
|
+
const nonProtectedNewStyles = newNonLitStyles.filter((s) => !isProtectedCustomStylesheet(s));
|
|
79
|
+
const mergedSheets = [
|
|
80
|
+
...savedLitStyles,
|
|
81
|
+
...protectedSheets.filter((s) => !savedLitStyles.includes(s)),
|
|
82
|
+
...nonProtectedNewStyles.filter((s) => !protectedSheets.includes(s))
|
|
83
|
+
];
|
|
84
|
+
originalDescriptor.set?.call(this, mergedSheets);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const finalSheets = sheets ? [...sheets] : [];
|
|
88
|
+
protectedSheets.forEach((ps) => {
|
|
89
|
+
if (!finalSheets.includes(ps)) finalSheets.push(ps);
|
|
90
|
+
});
|
|
91
|
+
originalDescriptor.set?.call(this, finalSheets);
|
|
92
|
+
},
|
|
93
|
+
configurable: true,
|
|
94
|
+
enumerable: true
|
|
95
|
+
});
|
|
96
|
+
isInitialized = true;
|
|
97
|
+
}
|
|
98
|
+
initShadowDomProtection();
|
|
99
|
+
//#endregion
|
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.5.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"iyulab",
|
|
7
7
|
"web-components",
|
|
@@ -29,15 +29,21 @@
|
|
|
29
29
|
},
|
|
30
30
|
"./dist/*": "./dist/*",
|
|
31
31
|
"./init": "./dist/init.js",
|
|
32
|
+
"./react": {
|
|
33
|
+
"types": "./dist/react.d.ts",
|
|
34
|
+
"import": "./dist/react.js"
|
|
35
|
+
},
|
|
32
36
|
"./simple-sheet": "./dist/components/simple-sheet/USimpleSheet.js",
|
|
33
37
|
"./data-view": "./dist/components/data-view/UDataView.js",
|
|
34
|
-
"./data-grid": "./dist/components/data-grid/UDataGrid.js",
|
|
35
38
|
"./u-rich-table": "./dist/components/u-rich-table/URichTable.js"
|
|
36
39
|
},
|
|
37
40
|
"sideEffects": [
|
|
41
|
+
"./src/utilities/shadowDomProtection.ts",
|
|
42
|
+
"./src/components/data-view/UDataView.ts",
|
|
43
|
+
"./src/components/simple-sheet/USimpleSheet.ts",
|
|
44
|
+
"./src/components/u-rich-table/URichTable.ts",
|
|
45
|
+
"./src/init.ts",
|
|
38
46
|
"./dist/utilities/shadowDomProtection.js",
|
|
39
|
-
"./dist/utilities/devExtremeCssInjection.js",
|
|
40
|
-
"./dist/components/data-grid/UDataGrid.js",
|
|
41
47
|
"./dist/components/data-view/UDataView.js",
|
|
42
48
|
"./dist/components/simple-sheet/USimpleSheet.js",
|
|
43
49
|
"./dist/components/u-rich-table/URichTable.js",
|
|
@@ -48,27 +54,33 @@
|
|
|
48
54
|
"build": "eslint && vite build"
|
|
49
55
|
},
|
|
50
56
|
"dependencies": {
|
|
51
|
-
"@iyulab/components": "^1.0.
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"react": "^
|
|
56
|
-
"react
|
|
57
|
+
"@iyulab/components": "^1.0.6",
|
|
58
|
+
"lit": "^3.3.3"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@lit/react": "^1.0.0",
|
|
62
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependenciesMeta": {
|
|
65
|
+
"@lit/react": {
|
|
66
|
+
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"react": {
|
|
69
|
+
"optional": true
|
|
70
|
+
}
|
|
57
71
|
},
|
|
58
72
|
"devDependencies": {
|
|
59
73
|
"@eslint/js": "^9.39.4",
|
|
60
|
-
"@
|
|
74
|
+
"@lit/react": "^1.0.8",
|
|
61
75
|
"@types/react": "^19.2.14",
|
|
62
|
-
"@types/
|
|
63
|
-
"@vitejs/plugin-react": "^6.0.1",
|
|
76
|
+
"@types/node": "^25.8.0",
|
|
64
77
|
"eslint": "^9.39.4",
|
|
65
|
-
"eslint-plugin-react-hooks": "^7.0.1",
|
|
66
|
-
"eslint-plugin-react-refresh": "^0.5.2",
|
|
67
78
|
"glob": "^13.0.6",
|
|
68
|
-
"globals": "^17.
|
|
79
|
+
"globals": "^17.6.0",
|
|
80
|
+
"react": "^19.2.6",
|
|
69
81
|
"typescript": "^5.9.3",
|
|
70
|
-
"typescript-eslint": "^8.
|
|
71
|
-
"vite": "^8.0.
|
|
72
|
-
"vite-plugin-dts": "^
|
|
82
|
+
"typescript-eslint": "^8.59.3",
|
|
83
|
+
"vite": "^8.0.13",
|
|
84
|
+
"vite-plugin-dts": "^5.0.0"
|
|
73
85
|
}
|
|
74
86
|
}
|
|
@@ -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;
|