@iyulab/chat-components 0.3.0 → 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.
Files changed (208) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +133 -16
  3. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorate.js +9 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.122.0/helpers/decorateMetadata.js +6 -0
  5. package/dist/_virtual/_glob-assets_raw/intent-prompt.md.1907474e.js +4 -0
  6. package/dist/_virtual/_glob-assets_raw/view-prompt.md.e0dbcffe.js +4 -0
  7. package/dist/components/blocks/UCodeBlock.d.ts +24 -2
  8. package/dist/components/blocks/UCodeBlock.js +65 -2
  9. package/dist/components/blocks/UCodeBlock.styles.js +10 -4
  10. package/dist/components/blocks/UFileBlock.d.ts +33 -0
  11. package/dist/components/blocks/UFileBlock.js +154 -0
  12. package/dist/components/blocks/UFileBlock.styles.js +128 -0
  13. package/dist/components/blocks/UJsonBlock.d.ts +44 -2
  14. package/dist/components/blocks/UJsonBlock.js +128 -3
  15. package/dist/components/blocks/UJsonBlock.styles.js +4 -4
  16. package/dist/components/blocks/UMarkedBlock.d.ts +44 -2
  17. package/dist/components/blocks/UMarkedBlock.js +154 -4
  18. package/dist/components/blocks/UMarkedBlock.styles.js +4 -4
  19. package/dist/components/blocks/URefBlock.d.ts +16 -2
  20. package/dist/components/blocks/URefBlock.js +58 -3
  21. package/dist/components/blocks/URefBlock.styles.js +4 -4
  22. package/dist/components/blocks/UTableBlock.d.ts +52 -0
  23. package/dist/components/blocks/UTableBlock.js +198 -0
  24. package/dist/components/blocks/UTableBlock.styles.js +133 -0
  25. package/dist/components/blocks/UTextBlock.d.ts +36 -2
  26. package/dist/components/blocks/UTextBlock.js +94 -4
  27. package/dist/components/blocks/UTextBlock.styles.js +4 -4
  28. package/dist/components/blocks/UThinkBlock.d.ts +30 -2
  29. package/dist/components/blocks/UThinkBlock.js +86 -4
  30. package/dist/components/blocks/UThinkBlock.styles.js +4 -4
  31. package/dist/components/blocks/UToolBlock.d.ts +19 -2
  32. package/dist/components/blocks/UToolBlock.js +68 -3
  33. package/dist/components/blocks/UToolBlock.styles.js +4 -4
  34. package/dist/components/buttons/UAttachButton.d.ts +21 -2
  35. package/dist/components/buttons/UAttachButton.js +61 -3
  36. package/dist/components/buttons/UAttachButton.styles.js +4 -4
  37. package/dist/components/buttons/UCopyButton.d.ts +19 -2
  38. package/dist/components/buttons/UCopyButton.js +57 -3
  39. package/dist/components/buttons/UCopyButton.styles.js +4 -4
  40. package/dist/components/buttons/UVoteButton.d.ts +14 -3
  41. package/dist/components/buttons/UVoteButton.js +62 -3
  42. package/dist/components/buttons/UVoteButton.styles.js +4 -4
  43. package/dist/components/intents/UQuestionIntent.d.ts +22 -0
  44. package/dist/components/intents/UQuestionIntent.js +41 -0
  45. package/dist/components/intents/UQuestionIntent.styles.js +43 -0
  46. package/dist/components/message/UMessage.d.ts +18 -2
  47. package/dist/components/message/UMessage.js +47 -2
  48. package/dist/components/message/UMessage.styles.js +42 -15
  49. package/dist/components/prompt/UPrompt.d.ts +32 -2
  50. package/dist/components/prompt/UPrompt.js +118 -2
  51. package/dist/components/prompt/UPrompt.styles.js +43 -5
  52. package/dist/components/references/URefCard.d.ts +30 -2
  53. package/dist/components/references/URefCard.js +97 -2
  54. package/dist/components/references/URefCard.styles.js +4 -4
  55. package/dist/components/references/URefCardGroup.d.ts +25 -2
  56. package/dist/components/references/URefCardGroup.js +69 -4
  57. package/dist/components/references/URefCardGroup.styles.js +4 -4
  58. package/dist/components/references/URefTag.d.ts +12 -2
  59. package/dist/components/references/URefTag.js +37 -2
  60. package/dist/components/references/URefTag.styles.js +4 -4
  61. package/dist/components/views/UChartView.d.ts +39 -0
  62. package/dist/components/views/UChartView.js +167 -0
  63. package/dist/components/views/UChartView.styles.js +86 -0
  64. package/dist/components/views/UImagesView.d.ts +33 -0
  65. package/dist/components/views/UImagesView.js +144 -0
  66. package/dist/components/views/UImagesView.styles.d.ts +1 -0
  67. package/dist/components/views/UImagesView.styles.js +219 -0
  68. package/dist/components/views/UMapView.d.ts +24 -0
  69. package/dist/components/views/UMapView.js +45 -0
  70. package/dist/components/views/UMapView.styles.d.ts +1 -0
  71. package/dist/components/views/UMapView.styles.js +47 -0
  72. package/dist/components/views/UVideoView.d.ts +25 -0
  73. package/dist/components/views/UVideoView.js +81 -0
  74. package/dist/components/views/UVideoView.styles.d.ts +1 -0
  75. package/dist/components/views/UVideoView.styles.js +36 -0
  76. package/dist/components/views/UView.d.ts +46 -0
  77. package/dist/components/views/UView.js +113 -0
  78. package/dist/components/views/UView.styles.d.ts +1 -0
  79. package/dist/components/views/UView.styles.js +33 -0
  80. package/dist/events/AttachEvent.d.ts +9 -0
  81. package/dist/events/ChoiceEvent.d.ts +9 -0
  82. package/dist/events/SendEvent.d.ts +7 -0
  83. package/dist/events/StopEvent.d.ts +7 -0
  84. package/dist/index.d.ts +15 -6
  85. package/dist/index.js +28 -38
  86. package/dist/react/UAttachButton.d.ts +11 -0
  87. package/dist/react/UAttachButton.js +12 -0
  88. package/dist/react/UChartView.d.ts +9 -0
  89. package/dist/react/UChartView.js +10 -0
  90. package/dist/react/UCodeBlock.d.ts +9 -0
  91. package/dist/react/UCodeBlock.js +10 -0
  92. package/dist/react/UCopyButton.d.ts +9 -0
  93. package/dist/react/UCopyButton.js +10 -0
  94. package/dist/react/UFileBlock.d.ts +11 -0
  95. package/dist/react/UFileBlock.js +12 -0
  96. package/dist/react/UImagesView.d.ts +9 -0
  97. package/dist/react/UImagesView.js +10 -0
  98. package/dist/react/UJsonBlock.d.ts +9 -0
  99. package/dist/react/UJsonBlock.js +10 -0
  100. package/dist/react/UMapView.d.ts +9 -0
  101. package/dist/react/UMapView.js +10 -0
  102. package/dist/react/UMarkedBlock.d.ts +9 -0
  103. package/dist/react/UMarkedBlock.js +10 -0
  104. package/dist/react/UMessage.d.ts +9 -0
  105. package/dist/react/UMessage.js +10 -0
  106. package/dist/react/UPrompt.d.ts +13 -0
  107. package/dist/react/UPrompt.js +13 -0
  108. package/dist/react/UQuestionIntent.d.ts +11 -0
  109. package/dist/react/UQuestionIntent.js +12 -0
  110. package/dist/react/URefBlock.d.ts +9 -0
  111. package/dist/react/URefBlock.js +10 -0
  112. package/dist/react/URefCard.d.ts +9 -0
  113. package/dist/react/URefCard.js +10 -0
  114. package/dist/react/URefCardGroup.d.ts +9 -0
  115. package/dist/react/URefCardGroup.js +10 -0
  116. package/dist/react/URefTag.d.ts +9 -0
  117. package/dist/react/URefTag.js +10 -0
  118. package/dist/react/UTableBlock.d.ts +9 -0
  119. package/dist/react/UTableBlock.js +10 -0
  120. package/dist/react/UTextBlock.d.ts +9 -0
  121. package/dist/react/UTextBlock.js +10 -0
  122. package/dist/react/UThinkBlock.d.ts +9 -0
  123. package/dist/react/UThinkBlock.js +10 -0
  124. package/dist/react/UToolBlock.d.ts +9 -0
  125. package/dist/react/UToolBlock.js +10 -0
  126. package/dist/react/UVideoView.d.ts +9 -0
  127. package/dist/react/UVideoView.js +10 -0
  128. package/dist/react/UView.d.ts +9 -0
  129. package/dist/react/UView.js +10 -0
  130. package/dist/react/UVoteButton.d.ts +9 -0
  131. package/dist/react/UVoteButton.js +10 -0
  132. package/dist/react/index.d.ts +23 -0
  133. package/dist/react/index.js +23 -0
  134. package/dist/types/BlockItem.d.ts +21 -1
  135. package/dist/types/Intents.d.ts +26 -0
  136. package/dist/types/Intents.js +30 -0
  137. package/dist/types/JsonSchema.d.ts +59 -0
  138. package/dist/types/Views.d.ts +34 -0
  139. package/dist/types/Views.js +150 -0
  140. package/dist/utilities/IntentPromptBuilder.d.ts +40 -0
  141. package/dist/utilities/IntentPromptBuilder.js +95 -0
  142. package/dist/utilities/ViewPromptBuilder.d.ts +28 -0
  143. package/dist/utilities/ViewPromptBuilder.js +76 -0
  144. package/dist/utilities/dom-agent/DOMAgent.d.ts +74 -0
  145. package/dist/utilities/dom-agent/DOMController.d.ts +78 -0
  146. package/dist/utilities/dom-agent/DOMPromptBuilder.d.ts +54 -0
  147. package/dist/utilities/dom-agent/DOMScanner.d.ts +83 -0
  148. package/dist/utilities/dom-agent/index.d.ts +9 -0
  149. package/dist/utilities/dom-agent/types.d.ts +209 -0
  150. package/package.json +34 -18
  151. package/dist/components/blocks/UCodeBlock.component.d.ts +0 -23
  152. package/dist/components/blocks/UCodeBlock.component.js +0 -76
  153. package/dist/components/blocks/UJsonBlock.component.d.ts +0 -45
  154. package/dist/components/blocks/UJsonBlock.component.js +0 -140
  155. package/dist/components/blocks/UMarkedBlock.component.d.ts +0 -45
  156. package/dist/components/blocks/UMarkedBlock.component.js +0 -129
  157. package/dist/components/blocks/URefBlock.component.d.ts +0 -17
  158. package/dist/components/blocks/URefBlock.component.js +0 -74
  159. package/dist/components/blocks/UTextBlock.component.d.ts +0 -37
  160. package/dist/components/blocks/UTextBlock.component.js +0 -123
  161. package/dist/components/blocks/UThinkBlock.component.d.ts +0 -23
  162. package/dist/components/blocks/UThinkBlock.component.js +0 -90
  163. package/dist/components/blocks/UToolBlock.component.d.ts +0 -20
  164. package/dist/components/blocks/UToolBlock.component.js +0 -80
  165. package/dist/components/buttons/UAttachButton.component.d.ts +0 -22
  166. package/dist/components/buttons/UAttachButton.component.js +0 -89
  167. package/dist/components/buttons/UCopyButton.component.d.ts +0 -20
  168. package/dist/components/buttons/UCopyButton.component.js +0 -81
  169. package/dist/components/buttons/UReportButton.component.d.ts +0 -9
  170. package/dist/components/buttons/UReportButton.component.js +0 -36
  171. package/dist/components/buttons/UReportButton.d.ts +0 -7
  172. package/dist/components/buttons/UReportButton.js +0 -5
  173. package/dist/components/buttons/UReportButton.styles.js +0 -14
  174. package/dist/components/buttons/URetryButton.component.d.ts +0 -11
  175. package/dist/components/buttons/URetryButton.component.js +0 -53
  176. package/dist/components/buttons/URetryButton.d.ts +0 -7
  177. package/dist/components/buttons/URetryButton.js +0 -5
  178. package/dist/components/buttons/URetryButton.styles.js +0 -26
  179. package/dist/components/buttons/UShareButton.component.d.ts +0 -9
  180. package/dist/components/buttons/UShareButton.component.js +0 -36
  181. package/dist/components/buttons/UShareButton.d.ts +0 -7
  182. package/dist/components/buttons/UShareButton.js +0 -5
  183. package/dist/components/buttons/UShareButton.styles.js +0 -14
  184. package/dist/components/buttons/UVoteButton.component.d.ts +0 -15
  185. package/dist/components/buttons/UVoteButton.component.js +0 -70
  186. package/dist/components/loaders/UDotLoader.component.d.ts +0 -9
  187. package/dist/components/loaders/UDotLoader.component.js +0 -23
  188. package/dist/components/loaders/UDotLoader.d.ts +0 -7
  189. package/dist/components/loaders/UDotLoader.js +0 -5
  190. package/dist/components/loaders/UDotLoader.styles.js +0 -50
  191. package/dist/components/message/UMessage.component.d.ts +0 -19
  192. package/dist/components/message/UMessage.component.js +0 -90
  193. package/dist/components/prompt/UPrompt.component.d.ts +0 -25
  194. package/dist/components/prompt/UPrompt.component.js +0 -113
  195. package/dist/components/references/URefCard.component.d.ts +0 -24
  196. package/dist/components/references/URefCard.component.js +0 -105
  197. package/dist/components/references/URefCardGroup.component.d.ts +0 -25
  198. package/dist/components/references/URefCardGroup.component.js +0 -88
  199. package/dist/components/references/URefTag.component.d.ts +0 -13
  200. package/dist/components/references/URefTag.component.js +0 -54
  201. package/dist/events/UCancelEvent.d.ts +0 -6
  202. package/dist/events/USubmitEvent.d.ts +0 -6
  203. package/dist/utilities/converters.d.ts +0 -9
  204. package/dist/utilities/converters.js +0 -19
  205. /package/dist/components/{buttons/UReportButton.styles.d.ts → blocks/UFileBlock.styles.d.ts} +0 -0
  206. /package/dist/components/{buttons/URetryButton.styles.d.ts → blocks/UTableBlock.styles.d.ts} +0 -0
  207. /package/dist/components/{buttons/UShareButton.styles.d.ts → intents/UQuestionIntent.styles.d.ts} +0 -0
  208. /package/dist/components/{loaders/UDotLoader.styles.d.ts → views/UChartView.styles.d.ts} +0 -0
@@ -0,0 +1,52 @@
1
+ import { UDataElement } from '@iyulab/components/dist/components/UDataElement.js';
2
+ /** 테이블 셀 데이터 타입 */
3
+ export interface TableCell {
4
+ /** 셀에 표시할 텍스트 내용 */
5
+ text: string;
6
+ /** 셀 내용의 정렬 방식. 기본값은 "left" */
7
+ align: "left" | "center" | "right" | null;
8
+ }
9
+ /** 테이블 정렬 상태 */
10
+ export interface SortState {
11
+ /** 현재 정렬 기준이 되는 컬럼 인덱스. -1이면 정렬 안 된 상태 */
12
+ index: number;
13
+ /** 정렬 방향. "asc"는 오름차순, "desc"는 내림차순 */
14
+ dir: "asc" | "desc";
15
+ }
16
+ /**
17
+ * 마크다운 테이블 데이터를 렌더링하는 컴포넌트입니다.
18
+ * 컬럼 정렬, CSV 다운로드 기능을 지원합니다.
19
+ * light DOM 내 `<script type="application/json">` 에서 데이터를 자동으로 읽어냅니다.
20
+ */
21
+ export declare class UTableBlock extends UDataElement {
22
+ static styles: (import('lit').CSSResult | import('lit').CSSResultGroup[])[];
23
+ /** 테이블 헤더 목록. 각 헤더는 { text, align } 형식입니다. */
24
+ headers: TableCell[];
25
+ /** 테이블 행 목록. 각 행은 셀 배열입니다. */
26
+ rows: TableCell[][];
27
+ private loading;
28
+ private sort;
29
+ private search;
30
+ private searchCache?;
31
+ private searchTimer;
32
+ render(): import('lit-html').TemplateResult<1>;
33
+ /**
34
+ * 하이라이트 렌더링: search 기준으로 매칭되는 부분을 <mark>로 감쌉니다.
35
+ * 내부적으로 안전하게 escape한 뒤 매칭을 위해 RegExp를 사용합니다.
36
+ */
37
+ private renderHighlightedText;
38
+ /**
39
+ * 현재 검색어와 정렬 상태에 따라 필터링 및 정렬된 행 목록을 반환합니다.
40
+ */
41
+ private getFilteredSortedRows;
42
+ private handleSearchInput;
43
+ private handleSortColumn;
44
+ private handleDownloadCSV;
45
+ private handleDownloadXLS;
46
+ private triggerDownload;
47
+ }
48
+ declare global {
49
+ interface HTMLElementTagNameMap {
50
+ "u-table-block": UTableBlock;
51
+ }
52
+ }
@@ -0,0 +1,198 @@
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";
3
+ import { styles } from "./UTableBlock.styles.js";
4
+ import { html } from "lit";
5
+ import { customElement, property, state } from "lit/decorators.js";
6
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
7
+ import "@iyulab/components/dist/components/icon/UIcon.js";
8
+ import "@iyulab/components/dist/components/button/UButton.js";
9
+ import { UDataElement } from "@iyulab/components/dist/components/UDataElement.js";
10
+ import { repeat } from "lit/directives/repeat.js";
11
+ import "@iyulab/components/dist/components/skeleton/USkeleton.js";
12
+ //#region src/components/blocks/UTableBlock.ts
13
+ var UTableBlock = class UTableBlock extends UDataElement {
14
+ constructor(..._args) {
15
+ super(..._args);
16
+ this.headers = [];
17
+ this.rows = [];
18
+ this.loading = false;
19
+ this.sort = {
20
+ index: -1,
21
+ dir: "asc"
22
+ };
23
+ this.search = "";
24
+ this.searchTimer = null;
25
+ }
26
+ static {
27
+ this.styles = [super.styles, styles];
28
+ }
29
+ render() {
30
+ const rows = this.getFilteredSortedRows();
31
+ return html`
32
+ <div class="toolbar">
33
+ <div class="toolbar-left">
34
+ <u-input
35
+ class="toolbar-search"
36
+ type="search"
37
+ placeholder="Search..."
38
+ .value=${this.search}
39
+ @input=${this.handleSearchInput}
40
+ >
41
+ <u-icon slot="prefix" lib="internal" name="search"></u-icon>
42
+ </u-input>
43
+ <span class="toolbar-count">
44
+ ${rows.length} / ${this.rows.length} Rows
45
+ </span>
46
+ </div>
47
+ <div class="toolbar-right">
48
+ <u-button @click=${this.handleDownloadXLS} title="Excel Download">
49
+ XLS
50
+ <u-icon slot="suffix" lib="bootstrap" name="download"></u-icon>
51
+ </u-button>
52
+ <u-button @click=${this.handleDownloadCSV} title="CSV Download">
53
+ CSV
54
+ <u-icon slot="suffix" lib="bootstrap" name="download"></u-icon>
55
+ </u-button>
56
+ </div>
57
+ </div>
58
+ <div class="table-wrapper" scrollable>
59
+ <table>
60
+ <thead ?hidden=${!this.headers.length}>
61
+ <tr>
62
+ ${repeat(this.headers, (_, i) => i, (h, i) => {
63
+ const isActive = this.sort.index === i;
64
+ return html`
65
+ <th
66
+ ?active=${isActive}
67
+ align=${h.align ?? "left"}
68
+ @click=${() => this.handleSortColumn(i)}
69
+ >
70
+ ${unsafeHTML(h.text)}
71
+ <u-icon
72
+ class="sort-icon"
73
+ lib="bootstrap"
74
+ name=${isActive ? this.sort.dir === "asc" ? "sort-alpha-up" : "sort-alpha-down" : "arrow-down-up"}
75
+ ></u-icon>
76
+ </th>
77
+ `;
78
+ })}
79
+ </tr>
80
+ </thead>
81
+ <tbody>
82
+ ${this.loading ? html`
83
+ <tr>
84
+ <td colspan=${this.headers.length || 1}>
85
+ <u-skeleton width="80%" height="1.2em"></u-skeleton>
86
+ <u-skeleton width="60%" height="1.2em"></u-skeleton>
87
+ <u-skeleton width="70%" height="1.2em"></u-skeleton>
88
+ <u-skeleton width="50%" height="1.2em"></u-skeleton>
89
+ </td>
90
+ </tr>
91
+ ` : repeat(rows, (_, i) => i, (row) => html`
92
+ <tr>
93
+ ${repeat(row, (_, j) => j, (cell) => html`
94
+ <td align=${cell.align ?? "left"}>
95
+ ${unsafeHTML(this.renderHighlightedText(cell.text))}
96
+ </td>
97
+ `)}
98
+ </tr>
99
+ `)}
100
+ </tbody>
101
+ </table>
102
+ </div>
103
+ `;
104
+ }
105
+ /**
106
+ * 하이라이트 렌더링: search 기준으로 매칭되는 부분을 <mark>로 감쌉니다.
107
+ * 내부적으로 안전하게 escape한 뒤 매칭을 위해 RegExp를 사용합니다.
108
+ */
109
+ renderHighlightedText(text) {
110
+ const q = this.search.trim();
111
+ if (!q) return text;
112
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
113
+ const re = new RegExp(`(${escaped})`, "gi");
114
+ const parts = String(text).split(re);
115
+ if (parts.length === 1) return text;
116
+ return parts.map((p, idx) => idx % 2 === 1 ? `<mark>${p}</mark>` : p).join("");
117
+ }
118
+ /**
119
+ * 현재 검색어와 정렬 상태에 따라 필터링 및 정렬된 행 목록을 반환합니다.
120
+ */
121
+ getFilteredSortedRows() {
122
+ let rows = this.rows;
123
+ const q = this.search.trim();
124
+ if (q) {
125
+ const qLower = q.toLowerCase();
126
+ rows = rows.filter((row) => row.some((cell) => cell.text.toLowerCase().includes(qLower)));
127
+ }
128
+ const { index, dir } = this.sort;
129
+ if (index < 0) return rows;
130
+ return [...rows].sort((a, b) => {
131
+ const av = a[index]?.text ?? "";
132
+ const bv = b[index]?.text ?? "";
133
+ const an = Number(av);
134
+ const bn = Number(bv);
135
+ const cmp = !isNaN(an) && !isNaN(bn) ? an - bn : av.localeCompare(bv, void 0, { sensitivity: "base" });
136
+ return dir === "asc" ? cmp : -cmp;
137
+ });
138
+ }
139
+ handleSearchInput(e) {
140
+ this.searchCache = e.target.value || "";
141
+ if (this.searchTimer !== null) window.clearTimeout(this.searchTimer);
142
+ this.loading = true;
143
+ this.searchTimer = window.setTimeout(() => {
144
+ this.search = this.searchCache || "";
145
+ this.loading = false;
146
+ this.searchTimer = null;
147
+ }, 250);
148
+ }
149
+ handleSortColumn(index) {
150
+ if (this.sort.index === index) this.sort = {
151
+ ...this.sort,
152
+ dir: this.sort.dir === "asc" ? "desc" : "asc"
153
+ };
154
+ else this.sort = {
155
+ index,
156
+ dir: "asc"
157
+ };
158
+ }
159
+ handleDownloadCSV() {
160
+ const escCsv = (v) => v.includes(",") || v.includes("\"") || v.includes("\n") ? `"${v.replace(/"/g, "\"\"")}"` : v;
161
+ const lines = [this.headers.map((h) => escCsv(h.text)).join(","), ...this.rows.map((row) => row.map((cell) => escCsv(cell.text)).join(","))];
162
+ const blob = new Blob([lines.join("\n")], { type: "text/csv;charset=utf-8;" });
163
+ this.triggerDownload(`table-${Date.now()}.csv`, blob);
164
+ }
165
+ handleDownloadXLS() {
166
+ const escXml = (v) => v.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
167
+ const cell = (v) => `<Cell><Data ss:Type="String">${escXml(v)}</Data></Cell>`;
168
+ const row = (cells) => `<Row>${cells.map(cell).join("")}</Row>`;
169
+ const xml = [
170
+ `<?xml version="1.0" encoding="UTF-8"?>`,
171
+ `<?mso-application progid="Excel.Sheet"?>`,
172
+ `<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"`,
173
+ ` xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">`,
174
+ `<Worksheet ss:Name="Sheet1"><Table>`,
175
+ row(this.headers.map((h) => h.text)),
176
+ ...this.rows.map((r) => row(r.map((c) => c.text))),
177
+ `</Table></Worksheet></Workbook>`
178
+ ].join("\n");
179
+ const blob = new Blob([xml], { type: "application/vnd.ms-excel;charset=utf-8;" });
180
+ this.triggerDownload(`table-${Date.now()}.xls`, blob);
181
+ }
182
+ triggerDownload(filename, blob) {
183
+ const url = URL.createObjectURL(blob);
184
+ const a = document.createElement("a");
185
+ a.href = url;
186
+ a.download = filename;
187
+ a.click();
188
+ URL.revokeObjectURL(url);
189
+ }
190
+ };
191
+ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UTableBlock.prototype, "headers", void 0);
192
+ __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UTableBlock.prototype, "rows", void 0);
193
+ __decorate([state(), __decorateMetadata("design:type", Boolean)], UTableBlock.prototype, "loading", void 0);
194
+ __decorate([state(), __decorateMetadata("design:type", Object)], UTableBlock.prototype, "sort", void 0);
195
+ __decorate([state(), __decorateMetadata("design:type", String)], UTableBlock.prototype, "search", void 0);
196
+ UTableBlock = __decorate([customElement("u-table-block")], UTableBlock);
197
+ //#endregion
198
+ export { UTableBlock };
@@ -0,0 +1,133 @@
1
+ import { css } from "lit";
2
+ //#region src/components/blocks/UTableBlock.styles.ts
3
+ var styles = css`
4
+ :host {
5
+ display: block;
6
+ width: 100%;
7
+ margin: 8px 0;
8
+ border: 1px solid var(--u-border-color);
9
+ border-radius: 8px;
10
+ overflow: hidden;
11
+ }
12
+
13
+ .toolbar {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ padding: 6px 12px;
18
+ background-color: var(--u-neutral-100);
19
+ border-bottom: 1px solid var(--u-border-color);
20
+ gap: 8px;
21
+ }
22
+
23
+ .toolbar-left {
24
+ display: flex;
25
+ align-items: center;
26
+ gap: 8px;
27
+ flex: 1;
28
+ min-width: 0;
29
+ }
30
+
31
+ .toolbar-search {
32
+ flex: 1;
33
+ max-width: 200px;
34
+ font-size: 12px;
35
+ }
36
+
37
+ .toolbar-count {
38
+ font-size: 12px;
39
+ color: var(--u-txt-color-weak);
40
+ }
41
+
42
+ .toolbar-right {
43
+ display: flex;
44
+ align-items: center;
45
+ gap: 8px;
46
+ flex-shrink: 0;
47
+ }
48
+
49
+ .toolbar-right u-button {
50
+ font-size: 12px;
51
+ padding: 0.25em 0.5em;
52
+ }
53
+
54
+ .table-wrapper {
55
+ overflow-x: auto;
56
+ overflow-y: auto;
57
+ max-height: 480px;
58
+ width: 100%;
59
+ }
60
+
61
+ table {
62
+ width: 100%;
63
+ border-collapse: collapse;
64
+ font-size: 14px;
65
+ }
66
+
67
+ thead {
68
+ position: sticky;
69
+ top: 0;
70
+ }
71
+
72
+ thead tr {
73
+ background-color: var(--u-neutral-100);
74
+ }
75
+
76
+ th {
77
+ padding: 8px 12px;
78
+ font-weight: 600;
79
+ text-align: left;
80
+ border-bottom: 2px solid var(--u-border-color);
81
+ white-space: nowrap;
82
+ cursor: pointer;
83
+ user-select: none;
84
+ }
85
+ th:hover {
86
+ background-color: var(--u-neutral-200);
87
+ }
88
+ th:hover .sort-icon {
89
+ opacity: 0.7;
90
+ }
91
+ th[active] {
92
+ color: var(--u-primary, #4a90e2);
93
+ }
94
+ th[active] .sort-icon {
95
+ opacity: 1;
96
+ }
97
+
98
+ th .sort-icon {
99
+ display: inline-flex;
100
+ margin-left: 4px;
101
+ font-size: 12px;
102
+ opacity: 0.3;
103
+ transition: opacity 0.15s;
104
+ }
105
+
106
+ tbody tr {
107
+ background-color: var(--u-neutral-0);
108
+ }
109
+ tbody tr:hover td {
110
+ background-color: var(--u-neutral-50, rgba(0,0,0,0.02));
111
+ }
112
+ tbody tr:last-child td {
113
+ border-bottom: none;
114
+ }
115
+
116
+ td {
117
+ padding: 8px 12px;
118
+ border-bottom: 1px solid var(--u-border-color);
119
+ vertical-align: top;
120
+ }
121
+
122
+ th[align="left"], td[align="left"] {
123
+ text-align: left;
124
+ }
125
+ th[align="center"], td[align="center"] {
126
+ text-align: center;
127
+ }
128
+ th[align="right"], td[align="right"] {
129
+ text-align: right;
130
+ }
131
+ `;
132
+ //#endregion
133
+ export { styles };
@@ -1,7 +1,41 @@
1
- import { UTextBlock } from './UTextBlock.component.js';
1
+ import { PropertyValues } from 'lit';
2
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
3
+ /**
4
+ * 텍스트를 표시하거나 편집할 수 있는 블록 컴포넌트입니다.
5
+ */
6
+ export declare class UTextBlock extends UElement {
7
+ static styles: import('lit').CSSResultGroup[];
8
+ /** 편집 가능 여부 */
9
+ editable: boolean;
10
+ /** 스펠체크 여부 */
11
+ spellcheck: boolean;
12
+ /** 플레이스홀더 텍스트 */
13
+ placeholder?: string;
14
+ /** 최소 행 수, 기본값은 1 */
15
+ minRows: number;
16
+ /** 최대 행 수 */
17
+ maxRows?: number;
18
+ /** 텍스트 블록의 내용 */
19
+ value?: string;
20
+ textareaEl: HTMLTextAreaElement;
21
+ preEl: HTMLPreElement;
22
+ protected updated(changedProperties: PropertyValues): void;
23
+ render(): import('lit-html').TemplateResult<1>;
24
+ /**
25
+ * textarea에 포커스를 줍니다.
26
+ */
27
+ focus(options?: FocusOptions): void;
28
+ /**
29
+ * 텍스트 입력시 value를 업데이트하고 이벤트를 재전파합니다.
30
+ */
31
+ private updateValueFrom;
32
+ /**
33
+ * pre 엘리먼트에 주입될 값을 정규화합니다.
34
+ */
35
+ private normalizeValue;
36
+ }
2
37
  declare global {
3
38
  interface HTMLElementTagNameMap {
4
39
  "u-text-block": UTextBlock;
5
40
  }
6
41
  }
7
- export { UTextBlock };
@@ -1,5 +1,95 @@
1
- import { UTextBlock } from './UTextBlock.component.js';
2
-
3
- UTextBlock.define("u-text-block");
4
-
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";
3
+ import { styles } from "./UTextBlock.styles.js";
4
+ import { html } from "lit";
5
+ import { customElement, property, query } from "lit/decorators.js";
6
+ import { UElement } from "@iyulab/components/dist/components/UElement.js";
7
+ //#region src/components/blocks/UTextBlock.ts
8
+ var _ref, _ref2;
9
+ var UTextBlock = class UTextBlock extends UElement {
10
+ constructor(..._args) {
11
+ super(..._args);
12
+ this.editable = false;
13
+ this.spellcheck = false;
14
+ this.minRows = 1;
15
+ this.updateValueFrom = (event) => {
16
+ event.stopPropagation();
17
+ this.value = this.textareaEl.value;
18
+ this.dispatchEvent(new InputEvent("input", {
19
+ bubbles: true,
20
+ composed: true,
21
+ cancelable: true,
22
+ data: this.value,
23
+ inputType: event.inputType,
24
+ isComposing: event.isComposing,
25
+ dataTransfer: event.dataTransfer,
26
+ detail: event.detail,
27
+ targetRanges: event.getTargetRanges(),
28
+ view: event.view
29
+ }));
30
+ };
31
+ }
32
+ static {
33
+ this.styles = [super.styles, styles];
34
+ }
35
+ updated(changedProperties) {
36
+ super.updated(changedProperties);
37
+ if (changedProperties.has("minRows") && this.minRows > 0) {
38
+ const lineHeight = parseFloat(getComputedStyle(this.preEl).lineHeight);
39
+ this.preEl.style.minHeight = `${this.minRows * lineHeight}px`;
40
+ }
41
+ if (changedProperties.has("maxRows") && this.maxRows && this.maxRows > 0 && this.maxRows > this.minRows) {
42
+ const lineHeight = parseFloat(getComputedStyle(this.preEl).lineHeight);
43
+ this.preEl.style.maxHeight = `${this.maxRows * lineHeight}px`;
44
+ }
45
+ if (changedProperties.has("editable") && this.editable) requestAnimationFrame(() => {
46
+ this.textareaEl.focus();
47
+ this.textareaEl.setSelectionRange(this.value?.length || 0, this.value?.length || 0);
48
+ });
49
+ }
50
+ render() {
51
+ return html`
52
+ <div class="container">
53
+ <textarea
54
+ name="message"
55
+ placeholder=${this.placeholder || ""}
56
+ spellcheck=${this.spellcheck}
57
+ .readOnly=${!this.editable}
58
+ .value=${this.value || ""}
59
+ @input=${this.updateValueFrom}
60
+ ></textarea>
61
+ <pre
62
+ .textContent=${this.normalizeValue(this.value)}
63
+ ></pre>
64
+ </div>
65
+ `;
66
+ }
67
+ /**
68
+ * textarea에 포커스를 줍니다.
69
+ */
70
+ focus(options) {
71
+ this.textareaEl.focus(options);
72
+ }
73
+ /**
74
+ * pre 엘리먼트에 주입될 값을 정규화합니다.
75
+ */
76
+ normalizeValue(value) {
77
+ if (!value) return "​";
78
+ if (value.endsWith("\n")) return value + "​";
79
+ return value;
80
+ }
81
+ };
82
+ __decorate([property({
83
+ type: Boolean,
84
+ reflect: true
85
+ }), __decorateMetadata("design:type", Boolean)], UTextBlock.prototype, "editable", void 0);
86
+ __decorate([property({ type: Boolean }), __decorateMetadata("design:type", Boolean)], UTextBlock.prototype, "spellcheck", void 0);
87
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextBlock.prototype, "placeholder", void 0);
88
+ __decorate([property({ type: Number }), __decorateMetadata("design:type", Number)], UTextBlock.prototype, "minRows", void 0);
89
+ __decorate([property({ type: Number }), __decorateMetadata("design:type", Number)], UTextBlock.prototype, "maxRows", void 0);
90
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UTextBlock.prototype, "value", void 0);
91
+ __decorate([query("textarea"), __decorateMetadata("design:type", typeof (_ref = typeof HTMLTextAreaElement !== "undefined" && HTMLTextAreaElement) === "function" ? _ref : Object)], UTextBlock.prototype, "textareaEl", void 0);
92
+ __decorate([query("pre"), __decorateMetadata("design:type", typeof (_ref2 = typeof HTMLPreElement !== "undefined" && HTMLPreElement) === "function" ? _ref2 : Object)], UTextBlock.prototype, "preEl", void 0);
93
+ UTextBlock = __decorate([customElement("u-text-block")], UTextBlock);
94
+ //#endregion
5
95
  export { UTextBlock };
@@ -1,6 +1,6 @@
1
- import { css } from 'lit';
2
-
3
- const styles = css`
1
+ import { css } from "lit";
2
+ //#region src/components/blocks/UTextBlock.styles.ts
3
+ var styles = css`
4
4
  :host {
5
5
  display: block;
6
6
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@@ -67,5 +67,5 @@ const styles = css`
67
67
  min-height: 1.5em;
68
68
  }
69
69
  `;
70
-
70
+ //#endregion
71
71
  export { styles };
@@ -1,7 +1,35 @@
1
- import { UThinkBlock } from './UThinkBlock.component.js';
1
+ import { PropertyValues } from 'lit';
2
+ import { UElement } from '@iyulab/components/dist/components/UElement.js';
3
+ /**
4
+ * 추론 내용을 표시하는 블록입니다.
5
+ * 로딩 중일 때는 "Thinking..." 메시지를 표시하고, 내용 펼치기/접기 기능을 제공합니다.
6
+ */
7
+ export declare class UThinkBlock extends UElement {
8
+ static styles: import('lit').CSSResultGroup[];
9
+ /** 컨텐츠가 로딩 중인지 여부 */
10
+ loading: boolean;
11
+ /** 컨텐츠가 접혀있는지 여부 */
12
+ collapsed: boolean;
13
+ /** 컨텐츠 업데이트 시 자동으로 스크롤할지 여부 */
14
+ autoScroll: boolean;
15
+ /** 추론 컨텐츠의 내용 */
16
+ value?: string;
17
+ bodyEl: HTMLDivElement;
18
+ protected updated(changedProperties: PropertyValues): void;
19
+ render(): import('lit-html').TemplateResult<1>;
20
+ /**
21
+ * 컨텐츠 스크롤을 맨 아래로 이동
22
+ * @returns 스크롤 작업이 시작되었는지 여부 (bodyEl이 존재할 때만 true)
23
+ */
24
+ scrollToBottom(): boolean;
25
+ /**
26
+ * 사용자의 스크롤 인터럽트 처리
27
+ * 휠이나 터치 입력 시 자동 스크롤 중지
28
+ */
29
+ private handleUserInterrupt;
30
+ }
2
31
  declare global {
3
32
  interface HTMLElementTagNameMap {
4
33
  "u-think-block": UThinkBlock;
5
34
  }
6
35
  }
7
- export { UThinkBlock };
@@ -1,5 +1,87 @@
1
- import { UThinkBlock } from './UThinkBlock.component.js';
2
-
3
- UThinkBlock.define("u-think-block");
4
-
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";
3
+ import "./UMarkedBlock.js";
4
+ import { styles } from "./UThinkBlock.styles.js";
5
+ import { html } from "lit";
6
+ import { customElement, property, query } from "lit/decorators.js";
7
+ import "@iyulab/components/dist/components/icon/UIcon.js";
8
+ import { UElement } from "@iyulab/components/dist/components/UElement.js";
9
+ //#region src/components/blocks/UThinkBlock.ts
10
+ var _ref;
11
+ var UThinkBlock = class UThinkBlock extends UElement {
12
+ constructor(..._args) {
13
+ super(..._args);
14
+ this.loading = false;
15
+ this.collapsed = true;
16
+ this.autoScroll = false;
17
+ this.handleUserInterrupt = () => {
18
+ if (this.autoScroll) this.autoScroll = false;
19
+ };
20
+ }
21
+ static {
22
+ this.styles = [super.styles, styles];
23
+ }
24
+ updated(changedProperties) {
25
+ super.updated(changedProperties);
26
+ if (changedProperties.has("value") && this.autoScroll) this.scrollToBottom();
27
+ }
28
+ render() {
29
+ return html`
30
+ <div class="header" part="header"
31
+ @click=${() => this.collapsed = !this.collapsed}>
32
+ <u-icon class="prefix-icon"
33
+ ?loading=${this.loading}
34
+ lib="bootstrap"
35
+ name="lightbulb-fill"
36
+ ></u-icon>
37
+ <span class="title">
38
+ ${this.loading ? "Thinking..." : "Thought"}
39
+ </span>
40
+ <u-icon class="suffix-icon"
41
+ lib="internal"
42
+ name=${this.collapsed ? "plus-lg" : "dash-lg"}
43
+ ></u-icon>
44
+ </div>
45
+
46
+ <div class="body" part="body" scrollable
47
+ ?hidden=${this.collapsed}
48
+ @wheel=${this.handleUserInterrupt}
49
+ @touchstart=${this.handleUserInterrupt}>
50
+ <u-marked-block
51
+ .value=${this.value}
52
+ ></u-marked-block>
53
+ </div>
54
+ `;
55
+ }
56
+ /**
57
+ * 컨텐츠 스크롤을 맨 아래로 이동
58
+ * @returns 스크롤 작업이 시작되었는지 여부 (bodyEl이 존재할 때만 true)
59
+ */
60
+ scrollToBottom() {
61
+ if (!this.bodyEl) return false;
62
+ requestAnimationFrame(() => {
63
+ this.bodyEl.scrollTo({
64
+ top: this.bodyEl.scrollHeight,
65
+ behavior: "smooth"
66
+ });
67
+ });
68
+ return true;
69
+ }
70
+ };
71
+ __decorate([property({
72
+ type: Boolean,
73
+ reflect: true
74
+ }), __decorateMetadata("design:type", Boolean)], UThinkBlock.prototype, "loading", void 0);
75
+ __decorate([property({
76
+ type: Boolean,
77
+ reflect: true
78
+ }), __decorateMetadata("design:type", Boolean)], UThinkBlock.prototype, "collapsed", void 0);
79
+ __decorate([property({
80
+ type: Boolean,
81
+ attribute: "auto-scroll"
82
+ }), __decorateMetadata("design:type", Boolean)], UThinkBlock.prototype, "autoScroll", void 0);
83
+ __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UThinkBlock.prototype, "value", void 0);
84
+ __decorate([query(".body"), __decorateMetadata("design:type", typeof (_ref = typeof HTMLDivElement !== "undefined" && HTMLDivElement) === "function" ? _ref : Object)], UThinkBlock.prototype, "bodyEl", void 0);
85
+ UThinkBlock = __decorate([customElement("u-think-block")], UThinkBlock);
86
+ //#endregion
5
87
  export { UThinkBlock };
@@ -1,6 +1,6 @@
1
- import { css } from 'lit';
2
-
3
- const styles = css`
1
+ import { css } from "lit";
2
+ //#region src/components/blocks/UThinkBlock.styles.ts
3
+ var styles = css`
4
4
  :host {
5
5
  display: flex;
6
6
  flex-direction: column;
@@ -70,5 +70,5 @@ const styles = css`
70
70
  }
71
71
  }
72
72
  `;
73
-
73
+ //#endregion
74
74
  export { styles };