@iyulab/chat-components 0.1.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 (79) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE +21 -0
  3. package/README.md +20 -0
  4. package/dist/components/blocks/UCodeBlock.component.d.ts +24 -0
  5. package/dist/components/blocks/UCodeBlock.component.js +65 -0
  6. package/dist/components/blocks/UCodeBlock.d.ts +7 -0
  7. package/dist/components/blocks/UCodeBlock.js +5 -0
  8. package/dist/components/blocks/UCodeBlock.styles.d.ts +1 -0
  9. package/dist/components/blocks/UCodeBlock.styles.js +175 -0
  10. package/dist/components/blocks/UMarkedBlock.component.d.ts +24 -0
  11. package/dist/components/blocks/UMarkedBlock.component.js +80 -0
  12. package/dist/components/blocks/UMarkedBlock.d.ts +7 -0
  13. package/dist/components/blocks/UMarkedBlock.js +5 -0
  14. package/dist/components/blocks/UMarkedBlock.styles.d.ts +1 -0
  15. package/dist/components/blocks/UMarkedBlock.styles.js +1240 -0
  16. package/dist/components/blocks/UTextBlock.component.d.ts +37 -0
  17. package/dist/components/blocks/UTextBlock.component.js +123 -0
  18. package/dist/components/blocks/UTextBlock.d.ts +7 -0
  19. package/dist/components/blocks/UTextBlock.js +5 -0
  20. package/dist/components/blocks/UTextBlock.styles.d.ts +1 -0
  21. package/dist/components/blocks/UTextBlock.styles.js +71 -0
  22. package/dist/components/blocks/UThinkBlock.component.d.ts +28 -0
  23. package/dist/components/blocks/UThinkBlock.component.js +84 -0
  24. package/dist/components/blocks/UThinkBlock.d.ts +7 -0
  25. package/dist/components/blocks/UThinkBlock.js +5 -0
  26. package/dist/components/blocks/UThinkBlock.styles.d.ts +1 -0
  27. package/dist/components/blocks/UThinkBlock.styles.js +93 -0
  28. package/dist/components/blocks/UToolBlock.component.d.ts +16 -0
  29. package/dist/components/blocks/UToolBlock.component.js +126 -0
  30. package/dist/components/blocks/UToolBlock.d.ts +7 -0
  31. package/dist/components/blocks/UToolBlock.js +5 -0
  32. package/dist/components/blocks/UToolBlock.styles.d.ts +1 -0
  33. package/dist/components/blocks/UToolBlock.styles.js +107 -0
  34. package/dist/components/buttons/UAttachButton.component.d.ts +24 -0
  35. package/dist/components/buttons/UAttachButton.component.js +78 -0
  36. package/dist/components/buttons/UAttachButton.d.ts +7 -0
  37. package/dist/components/buttons/UAttachButton.js +5 -0
  38. package/dist/components/buttons/UAttachButton.styles.d.ts +1 -0
  39. package/dist/components/buttons/UAttachButton.styles.js +21 -0
  40. package/dist/components/buttons/UCopyButton.component.d.ts +25 -0
  41. package/dist/components/buttons/UCopyButton.component.js +105 -0
  42. package/dist/components/buttons/UCopyButton.d.ts +7 -0
  43. package/dist/components/buttons/UCopyButton.js +5 -0
  44. package/dist/components/buttons/UCopyButton.styles.d.ts +1 -0
  45. package/dist/components/buttons/UCopyButton.styles.js +47 -0
  46. package/dist/components/buttons/USendButton.component.d.ts +13 -0
  47. package/dist/components/buttons/USendButton.component.js +46 -0
  48. package/dist/components/buttons/USendButton.d.ts +7 -0
  49. package/dist/components/buttons/USendButton.js +5 -0
  50. package/dist/components/buttons/USendButton.styles.d.ts +1 -0
  51. package/dist/components/buttons/USendButton.styles.js +23 -0
  52. package/dist/components/buttons/UThinkButton.component.d.ts +19 -0
  53. package/dist/components/buttons/UThinkButton.component.js +73 -0
  54. package/dist/components/buttons/UThinkButton.d.ts +7 -0
  55. package/dist/components/buttons/UThinkButton.js +5 -0
  56. package/dist/components/buttons/UThinkButton.styles.d.ts +1 -0
  57. package/dist/components/buttons/UThinkButton.styles.js +72 -0
  58. package/dist/components/json-viewer/UJsonViewer.component.d.ts +44 -0
  59. package/dist/components/json-viewer/UJsonViewer.component.js +137 -0
  60. package/dist/components/json-viewer/UJsonViewer.d.ts +7 -0
  61. package/dist/components/json-viewer/UJsonViewer.js +5 -0
  62. package/dist/components/json-viewer/UJsonViewer.lib.d.ts +16 -0
  63. package/dist/components/json-viewer/UJsonViewer.lib.js +28 -0
  64. package/dist/components/json-viewer/UJsonViewer.styles.d.ts +1 -0
  65. package/dist/components/json-viewer/UJsonViewer.styles.js +115 -0
  66. package/dist/components/message/UMessage.component.d.ts +13 -0
  67. package/dist/components/message/UMessage.component.js +104 -0
  68. package/dist/components/message/UMessage.d.ts +8 -0
  69. package/dist/components/message/UMessage.js +5 -0
  70. package/dist/components/message/UMessage.styles.d.ts +1 -0
  71. package/dist/components/message/UMessage.styles.js +72 -0
  72. package/dist/components/message/UMessage.types.d.ts +21 -0
  73. package/dist/events/UStopEvent.d.ts +6 -0
  74. package/dist/events/USubmitEvent.d.ts +6 -0
  75. package/dist/index.d.ts +13 -0
  76. package/dist/index.js +22 -0
  77. package/dist/internals/date-helpers.d.ts +8 -0
  78. package/dist/internals/date-helpers.js +27 -0
  79. package/package.json +65 -0
@@ -0,0 +1,72 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ position: relative;
6
+ padding: 8px;
7
+ font-size: 16px;
8
+ border-radius: 8px;
9
+ cursor: pointer;
10
+ user-select: none;
11
+ }
12
+ :host(:hover) {
13
+ background-color: var(--u-neutral-100);
14
+ }
15
+ :host([disabled]) {
16
+ opacity: 0.5;
17
+ pointer-events: none;
18
+ background-color: transparent;
19
+ cursor: not-allowed;
20
+ }
21
+ /* u-icon 스타일 */
22
+ :host([value="low"]) u-icon {
23
+ filter: brightness(0.8);
24
+ color: var(--u-yellow-700);
25
+ }
26
+ :host([value="medium"]) u-icon {
27
+ color: var(--u-yellow-700);
28
+ }
29
+ :host([value="high"]) u-icon {
30
+ color: var(--u-yellow-700);
31
+ }
32
+ /* indicators 스타일 */
33
+ :host([value="low"]) .indicators > span:last-child {
34
+ background-color: var(--u-yellow-700);
35
+ }
36
+ :host([value="medium"]) .indicators > span:nth-last-child(-n+2) {
37
+ background-color: var(--u-yellow-700);
38
+ }
39
+ :host([value="high"]) .indicators > span {
40
+ background-color: var(--u-yellow-700);
41
+ }
42
+
43
+ .container {
44
+ display: flex;
45
+ flex-direction: row;
46
+ align-items: center;
47
+ gap: 4px;
48
+ }
49
+
50
+ u-icon {
51
+ font-size: inherit;
52
+ color: #e0e0e0;
53
+ transition: color 0.3s ease, filter 0.3s ease;
54
+ }
55
+
56
+ .indicators {
57
+ height: 1em;
58
+ display: flex;
59
+ flex-direction: column;
60
+ align-items: center;
61
+ justify-content: space-between;
62
+ }
63
+ .indicators > span {
64
+ width: 0.5em;
65
+ height: 0.2em;
66
+ border-radius: 2px;
67
+ background-color: #e0e0e0;
68
+ transition: background-color 0.3s ease;
69
+ }
70
+ `;
71
+
72
+ export { styles };
@@ -0,0 +1,44 @@
1
+ import { PropertyValues, TemplateResult } from 'lit';
2
+ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
3
+ import { JsonNode } from './UJsonViewer.lib.js';
4
+ /**
5
+ * json 데이터를 트리 형태로 시각화하는 컴포넌트입니다.
6
+ */
7
+ export declare class UJsonViewer extends BaseElement {
8
+ static styles: import('lit').CSSResultGroup[];
9
+ static dependencies: Record<string, typeof BaseElement>;
10
+ state: Record<string, boolean>;
11
+ /** 초기 확장 상태를 관리하는 속성입니다. */
12
+ expanded: boolean;
13
+ /** JSON 데이터 (속성으로 전달 가능) */
14
+ value: JsonNode;
15
+ connectedCallback(): void;
16
+ protected willUpdate(changedProperties: PropertyValues): void;
17
+ render(): TemplateResult<1>;
18
+ /**
19
+ * JsonNode를 렌더링합니다.
20
+ * @param value - JsonNode (JsonObject, JsonArray, 또는 JsonValue)
21
+ * @param parent - 부모 노드의 경로
22
+ */
23
+ private renderNode;
24
+ /**
25
+ * JsonValue를 렌더링합니다.
26
+ * @param node - JsonValue (string, number, boolean, null 등)
27
+ */
28
+ private renderValue;
29
+ /**
30
+ * JsonObject 또는 JsonArray를 렌더링합니다.
31
+ * @param node - JsonObject 또는 JsonArray
32
+ * @param depth - 현재 깊이
33
+ */
34
+ private renderObject;
35
+ /**
36
+ * 노드의 미리보기를 렌더링합니다.
37
+ * @param node - JsonObject 또는 JsonArray
38
+ */
39
+ private renderPreview;
40
+ /** 노드 확장/축소 클릭 핸들러 */
41
+ private toggle;
42
+ /** JSON 데이터를 순회하며 각 경로의 확장 상태를 설정합니다. */
43
+ private setState;
44
+ }
@@ -0,0 +1,137 @@
1
+ import { html } from 'lit';
2
+ import { state, property } from 'lit/decorators.js';
3
+ import { map } from 'lit/directives/map.js';
4
+ import { when } from 'lit/directives/when.js';
5
+ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
6
+ import { isValueType, getNodeName, jsonConverter } from './UJsonViewer.lib.js';
7
+ import { styles } from './UJsonViewer.styles.js';
8
+
9
+ var __defProp = Object.defineProperty;
10
+ var __decorateClass = (decorators, target, key, kind) => {
11
+ var result = void 0 ;
12
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
13
+ if (decorator = decorators[i])
14
+ result = (decorator(target, key, result) ) || result;
15
+ if (result) __defProp(target, key, result);
16
+ return result;
17
+ };
18
+ class UJsonViewer extends BaseElement {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.state = {};
22
+ this.expanded = true;
23
+ this.value = {};
24
+ }
25
+ static {
26
+ this.styles = [super.styles, styles];
27
+ }
28
+ static {
29
+ this.dependencies = {};
30
+ }
31
+ connectedCallback() {
32
+ super.connectedCallback();
33
+ this.setAttribute("tabindex", "0");
34
+ }
35
+ willUpdate(changedProperties) {
36
+ super.willUpdate(changedProperties);
37
+ if (changedProperties.has("value") || changedProperties.has("expanded")) {
38
+ this.state = this.setState(this.value);
39
+ }
40
+ }
41
+ render() {
42
+ return html`
43
+ <div part="base">
44
+ ${this.renderNode(this.value)}
45
+ </div>
46
+ `;
47
+ }
48
+ /**
49
+ * JsonNode를 렌더링합니다.
50
+ * @param value - JsonNode (JsonObject, JsonArray, 또는 JsonValue)
51
+ * @param parent - 부모 노드의 경로
52
+ */
53
+ renderNode(value, parent = "") {
54
+ return isValueType(value) ? this.renderValue(value) : this.renderObject(value, parent);
55
+ }
56
+ /**
57
+ * JsonValue를 렌더링합니다.
58
+ * @param node - JsonValue (string, number, boolean, null 등)
59
+ */
60
+ renderValue(node) {
61
+ const type = getNodeName(node);
62
+ return html`
63
+ <span part="${type}" class="${type}" role="treeitem">
64
+ ${JSON.stringify(node)}
65
+ </span>
66
+ `;
67
+ }
68
+ /**
69
+ * JsonObject 또는 JsonArray를 렌더링합니다.
70
+ * @param node - JsonObject 또는 JsonArray
71
+ * @param depth - 현재 깊이
72
+ */
73
+ renderObject(node, parent) {
74
+ return html`
75
+ <ul part="object" role="group">
76
+ ${map(Object.entries(node), ([key, value]) => {
77
+ const path = parent ? `${parent}.${key}` : key;
78
+ const isValue = isValueType(value);
79
+ const isExpanded = this.state[path] ?? this.expanded;
80
+ return html`
81
+ <li part="property" role="treeitem"
82
+ data-path="${path}"
83
+ aria-expanded="${isExpanded ? "true" : "false"}">
84
+ <span part="key"
85
+ class="key"
86
+ ?collapsable="${!isValue}"
87
+ ?collapsed="${!isValue && !isExpanded}"
88
+ @click=${!isValue ? () => this.toggle(path) : null}>
89
+ ${key}:
90
+ ${when(!isValue && !isExpanded, () => this.renderPreview(value))}
91
+ </span>
92
+
93
+ ${when(isValue || isExpanded, () => this.renderNode(value, path))}
94
+ </li>`;
95
+ })}
96
+ </ul>
97
+ `;
98
+ }
99
+ /**
100
+ * 노드의 미리보기를 렌더링합니다.
101
+ * @param node - JsonObject 또는 JsonArray
102
+ */
103
+ renderPreview(node) {
104
+ return html`
105
+ <span part="preview" class="preview">
106
+ ${Array.isArray(node) ? node.length === 0 ? "[ ]" : `[ ${node.length} items ]` : Object.keys(node).length === 0 ? "{ }" : `{ ${Object.keys(node).length} properties }`}
107
+ </span>
108
+ `;
109
+ }
110
+ /** 노드 확장/축소 클릭 핸들러 */
111
+ toggle(path) {
112
+ const isExpanded = this.state[path] ?? false;
113
+ this.state = { ...this.state, [path]: !isExpanded };
114
+ }
115
+ /** JSON 데이터를 순회하며 각 경로의 확장 상태를 설정합니다. */
116
+ setState(value, parent = "") {
117
+ if (typeof value !== "object" || value === null) return {};
118
+ const state2 = {};
119
+ Object.entries(value).forEach(([key, item]) => {
120
+ const path = parent ? `${parent}.${key}` : key;
121
+ state2[path] = this.expanded;
122
+ Object.assign(state2, this.setState(item, path));
123
+ });
124
+ return state2;
125
+ }
126
+ }
127
+ __decorateClass([
128
+ state()
129
+ ], UJsonViewer.prototype, "state");
130
+ __decorateClass([
131
+ property({ type: Boolean })
132
+ ], UJsonViewer.prototype, "expanded");
133
+ __decorateClass([
134
+ property({ type: Object, converter: jsonConverter })
135
+ ], UJsonViewer.prototype, "value");
136
+
137
+ export { UJsonViewer };
@@ -0,0 +1,7 @@
1
+ import { UJsonViewer } from './UJsonViewer.component.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'u-json-viewer': UJsonViewer;
5
+ }
6
+ }
7
+ export { UJsonViewer };
@@ -0,0 +1,5 @@
1
+ import { UJsonViewer } from './UJsonViewer.component.js';
2
+
3
+ UJsonViewer.define("u-json-viewer");
4
+
5
+ export { UJsonViewer };
@@ -0,0 +1,16 @@
1
+ export type JsonValue = string | number | boolean | null;
2
+ export type JsonObject = {
3
+ [x: string]: JsonNode;
4
+ };
5
+ export type JsonArray = Array<JsonNode>;
6
+ export type JsonNode = JsonValue | JsonObject | JsonArray;
7
+ /**
8
+ * 이 컨버터는 JsonNode 타입을 사용하여 JSON 데이터를 처리합니다.
9
+ * 문자열 어트리뷰트로 전달된 JSON 문자열을 객체로 변환/직렬화합니다.
10
+ */
11
+ export declare const jsonConverter: {
12
+ fromAttribute: (value: string | null) => JsonNode;
13
+ toAttribute: (value: JsonNode) => string;
14
+ };
15
+ export declare const isValueType: (value: JsonNode) => boolean;
16
+ export declare const getNodeName: (value: JsonNode) => string;
@@ -0,0 +1,28 @@
1
+ const jsonConverter = {
2
+ fromAttribute: (value) => {
3
+ if (!value || !value.trim()) return {};
4
+ try {
5
+ return JSON.parse(value);
6
+ } catch {
7
+ return {};
8
+ }
9
+ },
10
+ toAttribute: (value) => {
11
+ try {
12
+ return JSON.stringify(value);
13
+ } catch {
14
+ return "{}";
15
+ }
16
+ }
17
+ };
18
+ const isValueType = (value) => {
19
+ return value !== Object(value);
20
+ };
21
+ const getNodeName = (value) => {
22
+ if (value === null) return "null";
23
+ if (Array.isArray(value)) return "array";
24
+ if (typeof value === "object") return "object";
25
+ return typeof value;
26
+ };
27
+
28
+ export { getNodeName, isValueType, jsonConverter };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,115 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ --indent-size: 2em;
6
+
7
+ --json-property-color: #0451a5;
8
+ --json-string-color: #a31515;
9
+ --json-number-color: #098658;
10
+ --json-boolean-color: #0000ff;
11
+ --json-null-color: #0000ff;
12
+ --json-preview-color: #999999;
13
+ --json-arrow-color: #666968;
14
+ --json-guide-color: #c0c0c0;
15
+ }
16
+ :host-context([theme="dark"]) {
17
+ --json-property-color: #9cdcfe;
18
+ --json-string-color: #ce9178;
19
+ --json-number-color: #b5cea8;
20
+ --json-boolean-color: #569cd6;
21
+ --json-null-color: #569CD6;
22
+ --json-preview-color: #999999;
23
+ --json-arrow-color: #d4d4d4;
24
+ --json-guide-color: #3c3c3c;
25
+ }
26
+
27
+ :host {
28
+ display: block;
29
+ font-family: inherit;
30
+ font-size: inherit;
31
+ line-height: 1.5;
32
+ }
33
+
34
+ .key {
35
+ color: var(--json-property-color);
36
+ display: inline-flex;
37
+ align-items: center;
38
+ }
39
+ .key[collapsable] {
40
+ cursor: pointer;
41
+ user-select: none;
42
+ }
43
+ .key[collapsable]::before {
44
+ display: inline-flex;
45
+ font-size: 0.5em;
46
+ content: '▶';
47
+ align-items: center;
48
+ justify-content: center;
49
+
50
+ transform: rotate(90deg);
51
+ transition: transform 0.2s ease-out;
52
+ margin-right: 0.5em;
53
+
54
+ color: var(--json-arrow-color);
55
+ }
56
+ .key[collapsable][collapsed]::before {
57
+ transform: rotate(0);
58
+ }
59
+
60
+ .preview {
61
+ color: var(--json-preview-color);
62
+ margin-left: 0.5em;
63
+ }
64
+
65
+ .string {
66
+ color: var(--json-string-color);
67
+ }
68
+
69
+ .number {
70
+ color: var(--json-number-color);
71
+ }
72
+
73
+ .boolean {
74
+ color: var(--json-boolean-color);
75
+ }
76
+
77
+ .null {
78
+ color: var(--json-null-color);
79
+ }
80
+
81
+ /* object styles */
82
+ ul {
83
+ position: relative;
84
+ list-style: none;
85
+ margin: 0;
86
+ padding: 0;
87
+ clear: both;
88
+ }
89
+
90
+ /* property styles */
91
+ li {
92
+ position: relative;
93
+ list-style: none;
94
+ outline: none;
95
+ }
96
+
97
+ /* nested property styles */
98
+ li ul > li {
99
+ position: relative;
100
+ margin-left: var(--indent-size);
101
+ padding-left: 0px;
102
+ }
103
+
104
+ /* guide line styles */
105
+ ul ul::before {
106
+ content: '';
107
+ border-left: 1px solid var(--json-guide-color);
108
+ position: absolute;
109
+ left: calc(1.5em / 2 - 1px);
110
+ top: 0.2em;
111
+ bottom: 0.2em;
112
+ }
113
+ `;
114
+
115
+ export { styles };
@@ -0,0 +1,13 @@
1
+ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
2
+ import { BlockItem } from './UMessage.types.js';
3
+ export declare class UMessage extends BaseElement {
4
+ static styles: import('lit').CSSResultGroup[];
5
+ static dependencies: Record<string, typeof BaseElement>;
6
+ items?: BlockItem[];
7
+ timestamp?: string;
8
+ render(): import('lit-html').TemplateResult<1>;
9
+ /**
10
+ * 텍스트 및 마크다운 블록의 내용을 모아서 하나의 문자열로 반환합니다.
11
+ */
12
+ private getTextValue;
13
+ }
@@ -0,0 +1,104 @@
1
+ import { nothing, html } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import { repeat } from 'lit/directives/repeat.js';
4
+ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
5
+ import { UCopyButton } from '../buttons/UCopyButton.component.js';
6
+ import { UTextBlock } from '../blocks/UTextBlock.component.js';
7
+ import { UMarkedBlock } from '../blocks/UMarkedBlock.component.js';
8
+ import { UThinkBlock } from '../blocks/UThinkBlock.component.js';
9
+ import { UToolBlock } from '../blocks/UToolBlock.component.js';
10
+ import { format } from '../../internals/date-helpers.js';
11
+ import { styles } from './UMessage.styles.js';
12
+
13
+ var __defProp = Object.defineProperty;
14
+ var __decorateClass = (decorators, target, key, kind) => {
15
+ var result = void 0 ;
16
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
17
+ if (decorator = decorators[i])
18
+ result = (decorator(target, key, result) ) || result;
19
+ if (result) __defProp(target, key, result);
20
+ return result;
21
+ };
22
+ class UMessage extends BaseElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ /**
26
+ * 텍스트 및 마크다운 블록의 내용을 모아서 하나의 문자열로 반환합니다.
27
+ */
28
+ this.getTextValue = (items) => {
29
+ if (!items) return "";
30
+ return items.reduce((acc, item) => {
31
+ if (item.type === "text" || item.type === "markdown") {
32
+ return acc ? acc + "\n" + (item.value || "") : item.value || "";
33
+ }
34
+ return acc;
35
+ }, "");
36
+ };
37
+ }
38
+ static {
39
+ this.styles = [super.styles, styles];
40
+ }
41
+ static {
42
+ this.dependencies = {
43
+ "u-text-block": UTextBlock,
44
+ "u-marked-block": UMarkedBlock,
45
+ "u-think-block": UThinkBlock,
46
+ "u-tool-block": UToolBlock,
47
+ "u-copy-button": UCopyButton
48
+ };
49
+ }
50
+ render() {
51
+ return html`
52
+ <div class="container">
53
+ <div class="header" part="header">
54
+ <slot name="header"></slot>
55
+ </div>
56
+ <div class="body" part="body">
57
+ ${this.items && this.items.length > 0 ? repeat(this.items, (_, idx) => idx, (item, idx) => {
58
+ return item.type === "text" ? html`
59
+ <u-text-block
60
+ .value=${item.value}
61
+ ></u-text-block>` : item.type === "markdown" ? html`
62
+ <u-marked-block
63
+ .value=${item.value}
64
+ ></u-marked-block>` : item.type === "thinking" ? html`
65
+ <u-think-block
66
+ ?loading=${this.items?.length === (idx || 0) + 1}
67
+ .value=${item.value}
68
+ ></u-think-block>` : item.type === "tool" ? html`
69
+ <u-tool-block
70
+ .index=${idx}
71
+ .status=${item.status}
72
+ .name=${item.name}
73
+ .input=${item.input}
74
+ .output=${item.output}
75
+ ></u-tool-block>` : nothing;
76
+ }) : html`
77
+ <svg class="loader" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
78
+ <circle class="dot" cx="4" cy="12" r="3"/>
79
+ <circle class="dot d1" cx="12" cy="12" r="3"/>
80
+ <circle class="dot d2" cx="20" cy="12" r="3"/>
81
+ </svg>`}
82
+ </div>
83
+ <div class="footer" part="footer">
84
+ <u-copy-button
85
+ .value=${this.getTextValue(this.items)}
86
+ ></u-copy-button>
87
+ <slot name="footer"></slot>
88
+ <div style="flex:1;"></div>
89
+ <div class="timestamp">
90
+ ${format(this.timestamp)}
91
+ </div>
92
+ </div>
93
+ </div>
94
+ `;
95
+ }
96
+ }
97
+ __decorateClass([
98
+ property({ type: Array })
99
+ ], UMessage.prototype, "items");
100
+ __decorateClass([
101
+ property({ type: String })
102
+ ], UMessage.prototype, "timestamp");
103
+
104
+ export { UMessage };
@@ -0,0 +1,8 @@
1
+ import { UMessage } from './UMessage.component.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ "u-message": UMessage;
5
+ }
6
+ }
7
+ export { UMessage };
8
+ export type * from './UMessage.types';
@@ -0,0 +1,5 @@
1
+ import { UMessage } from './UMessage.component.js';
2
+
3
+ UMessage.define("u-message");
4
+
5
+ export { UMessage };
@@ -0,0 +1 @@
1
+ export declare const styles: import('lit').CSSResult;
@@ -0,0 +1,72 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ display: block;
6
+ font-family: 'Roboto', sans-serif;
7
+ font-size: 14px;
8
+ line-height: 1.5;
9
+ }
10
+
11
+ .container {
12
+ display: flex;
13
+ flex-direction: column;
14
+ }
15
+
16
+ .header {
17
+ display: flex;
18
+ flex-direction: row;
19
+ align-items: center;
20
+ }
21
+
22
+ .body {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 12px;
26
+ padding: 8px;
27
+ border: none;
28
+ border-radius: 8px;
29
+ }
30
+
31
+ .footer {
32
+ display: flex;
33
+ flex-direction: row;
34
+ align-items: center;
35
+ justify-content: space-between;
36
+ padding: 8px 0px;
37
+ gap: 12px;
38
+ font-size: 12px;
39
+ }
40
+
41
+ .loader {
42
+ width: 1em;
43
+ height: 1em;
44
+ fill: currentColor;
45
+ }
46
+
47
+ .dot {
48
+ animation: bounce_action 1.05s infinite
49
+ }
50
+ .d1 {
51
+ animation-delay:.1s
52
+ }
53
+ .d2 {
54
+ animation-delay:.2s
55
+ }
56
+
57
+ @keyframes bounce_action {
58
+ 0%,57.14% {
59
+ animation-timing-function: cubic-bezier(0.33,.66,.66,1);
60
+ transform: translate(0);
61
+ }
62
+ 28.57% {
63
+ animation-timing-function: cubic-bezier(0.33,0,.66,.33);
64
+ transform: translateY(-6px);
65
+ }
66
+ 100% {
67
+ transform: translate(0);
68
+ }
69
+ }
70
+ `;
71
+
72
+ export { styles };
@@ -0,0 +1,21 @@
1
+ export interface TextBlockItem {
2
+ type: "text";
3
+ value?: string;
4
+ }
5
+ export interface MarkdownBlockItem {
6
+ type: "markdown";
7
+ value?: string;
8
+ }
9
+ export interface ThinkingBlockItem {
10
+ type: "thinking";
11
+ value?: string;
12
+ }
13
+ export type ToolBlockStatus = ("pending" | "paused" | "inProgress" | "success" | "failure");
14
+ export interface ToolBlockItem {
15
+ type: "tool";
16
+ status: ToolBlockStatus;
17
+ name?: string;
18
+ input?: string;
19
+ output?: string;
20
+ }
21
+ export type BlockItem = (TextBlockItem | MarkdownBlockItem | ThinkingBlockItem | ToolBlockItem);
@@ -0,0 +1,6 @@
1
+ export type UStopEvent = CustomEvent<undefined>;
2
+ declare global {
3
+ interface HTMLElementEventMap {
4
+ 'u-stop': UStopEvent;
5
+ }
6
+ }
@@ -0,0 +1,6 @@
1
+ export type USubmitEvent = CustomEvent<string>;
2
+ declare global {
3
+ interface HTMLElementEventMap {
4
+ 'u-submit': USubmitEvent;
5
+ }
6
+ }