@iyulab/data-components 0.4.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 CHANGED
@@ -1,5 +1,20 @@
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
+
3
18
  ## [0.4.1] - 2026-05-07
4
19
 
5
20
  ### Fixed
package/README.md CHANGED
@@ -77,6 +77,49 @@ npm install @iyulab/data-components
77
77
  ></u-data-view>
78
78
  ```
79
79
 
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
+ ```
89
+
90
+ ```tsx
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 로 추론
121
+ ```
122
+
80
123
  ## Documentation
81
124
 
82
125
  - [USimpleSheet](./docs/USimpleSheet.md)
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.127.0/helpers/decorate.js
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.127.0/helpers/decorateMetadata.js
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.127.0/helpers/decorateMetadata.js";
3
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js";
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.127.0/helpers/decorateMetadata.js";
2
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js";
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.127.0/helpers/decorateMetadata.js";
2
- import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js";
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";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./utilities/shadowDomProtection.js";
1
2
  import { UDataView } from "./components/data-view/UDataView.js";
2
3
  import { USimpleSheet } from "./components/simple-sheet/USimpleSheet.js";
3
4
  import { URichTable } from "./components/u-rich-table/URichTable.js";
@@ -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.1",
4
+ "version": "0.5.0",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "web-components",
@@ -29,11 +29,20 @@
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
38
  "./u-rich-table": "./dist/components/u-rich-table/URichTable.js"
35
39
  },
36
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",
37
46
  "./dist/utilities/shadowDomProtection.js",
38
47
  "./dist/components/data-view/UDataView.js",
39
48
  "./dist/components/simple-sheet/USimpleSheet.js",
@@ -45,18 +54,33 @@
45
54
  "build": "eslint && vite build"
46
55
  },
47
56
  "dependencies": {
48
- "@iyulab/components": "^1.0.4",
49
- "lit": "^3.3.2"
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
+ }
50
71
  },
51
72
  "devDependencies": {
52
73
  "@eslint/js": "^9.39.4",
53
- "@types/node": "^25.6.0",
74
+ "@lit/react": "^1.0.8",
75
+ "@types/react": "^19.2.14",
76
+ "@types/node": "^25.8.0",
54
77
  "eslint": "^9.39.4",
55
78
  "glob": "^13.0.6",
56
- "globals": "^17.5.0",
79
+ "globals": "^17.6.0",
80
+ "react": "^19.2.6",
57
81
  "typescript": "^5.9.3",
58
- "typescript-eslint": "^8.58.2",
59
- "vite": "^8.0.8",
60
- "vite-plugin-dts": "^4.5.4"
82
+ "typescript-eslint": "^8.59.3",
83
+ "vite": "^8.0.13",
84
+ "vite-plugin-dts": "^5.0.0"
61
85
  }
62
86
  }