@iyulab/chat-components 0.1.0 → 0.2.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 (111) hide show
  1. package/CHANGELOG.md +30 -4
  2. package/LICENSE +20 -20
  3. package/README.md +36 -20
  4. package/dist/components/blocks/UCodeBlock.component.d.ts +7 -8
  5. package/dist/components/blocks/UCodeBlock.component.js +32 -21
  6. package/dist/components/blocks/UCodeBlock.styles.js +7 -6
  7. package/dist/components/{json-viewer/UJsonViewer.component.d.ts → blocks/UJsonBlock.component.d.ts} +5 -4
  8. package/dist/components/{json-viewer/UJsonViewer.component.js → blocks/UJsonBlock.component.js} +20 -17
  9. package/dist/components/blocks/UJsonBlock.d.ts +7 -0
  10. package/dist/components/blocks/UJsonBlock.js +5 -0
  11. package/dist/components/blocks/UMarkedBlock.component.d.ts +30 -9
  12. package/dist/components/blocks/UMarkedBlock.component.js +75 -26
  13. package/dist/components/blocks/UMarkedBlock.styles.js +288 -949
  14. package/dist/components/blocks/UThinkBlock.component.d.ts +3 -8
  15. package/dist/components/blocks/UThinkBlock.component.js +28 -22
  16. package/dist/components/blocks/UThinkBlock.styles.js +35 -54
  17. package/dist/components/blocks/UToolBlock.component.d.ts +13 -9
  18. package/dist/components/blocks/UToolBlock.component.js +30 -76
  19. package/dist/components/blocks/UToolBlock.styles.js +21 -62
  20. package/dist/components/buttons/UAttachButton.component.d.ts +3 -5
  21. package/dist/components/buttons/UAttachButton.component.js +30 -19
  22. package/dist/components/buttons/UAttachButton.styles.js +5 -12
  23. package/dist/components/buttons/UCopyButton.component.d.ts +3 -8
  24. package/dist/components/buttons/UCopyButton.component.js +29 -53
  25. package/dist/components/buttons/UCopyButton.styles.js +8 -37
  26. package/dist/components/buttons/UReportButton.component.d.ts +9 -0
  27. package/dist/components/buttons/UReportButton.component.js +36 -0
  28. package/dist/components/buttons/UReportButton.d.ts +7 -0
  29. package/dist/components/buttons/UReportButton.js +5 -0
  30. package/dist/components/buttons/UReportButton.styles.js +14 -0
  31. package/dist/components/buttons/URetryButton.component.d.ts +11 -0
  32. package/dist/components/buttons/URetryButton.component.js +53 -0
  33. package/dist/components/buttons/URetryButton.d.ts +7 -0
  34. package/dist/components/buttons/URetryButton.js +5 -0
  35. package/dist/components/buttons/URetryButton.styles.js +26 -0
  36. package/dist/components/buttons/UShareButton.component.d.ts +9 -0
  37. package/dist/components/buttons/UShareButton.component.js +36 -0
  38. package/dist/components/buttons/UShareButton.d.ts +7 -0
  39. package/dist/components/buttons/UShareButton.js +5 -0
  40. package/dist/components/buttons/UShareButton.styles.d.ts +1 -0
  41. package/dist/components/buttons/UShareButton.styles.js +14 -0
  42. package/dist/components/buttons/UVoteButton.component.d.ts +15 -0
  43. package/dist/components/buttons/UVoteButton.component.js +70 -0
  44. package/dist/components/buttons/UVoteButton.d.ts +8 -0
  45. package/dist/components/buttons/UVoteButton.js +5 -0
  46. package/dist/components/buttons/UVoteButton.styles.d.ts +1 -0
  47. package/dist/components/buttons/UVoteButton.styles.js +19 -0
  48. package/dist/components/loaders/UDotLoader.component.d.ts +9 -0
  49. package/dist/components/loaders/UDotLoader.component.js +23 -0
  50. package/dist/components/loaders/UDotLoader.d.ts +7 -0
  51. package/dist/components/loaders/UDotLoader.js +5 -0
  52. package/dist/components/loaders/UDotLoader.styles.d.ts +1 -0
  53. package/dist/components/loaders/UDotLoader.styles.js +50 -0
  54. package/dist/components/message/UMessage.component.d.ts +12 -6
  55. package/dist/components/message/UMessage.component.js +39 -59
  56. package/dist/components/message/UMessage.d.ts +0 -1
  57. package/dist/components/message/UMessage.styles.js +30 -49
  58. package/dist/components/prompt/UPrompt.component.d.ts +25 -0
  59. package/dist/components/prompt/UPrompt.component.js +113 -0
  60. package/dist/components/prompt/UPrompt.d.ts +7 -0
  61. package/dist/components/prompt/UPrompt.js +5 -0
  62. package/dist/components/prompt/UPrompt.styles.d.ts +1 -0
  63. package/dist/components/prompt/UPrompt.styles.js +42 -0
  64. package/dist/components/references/URefCard.component.d.ts +22 -0
  65. package/dist/components/references/URefCard.component.js +96 -0
  66. package/dist/components/references/URefCard.d.ts +7 -0
  67. package/dist/components/references/URefCard.js +5 -0
  68. package/dist/components/references/URefCard.styles.d.ts +1 -0
  69. package/dist/components/references/URefCard.styles.js +103 -0
  70. package/dist/components/references/URefCardGroup.component.d.ts +25 -0
  71. package/dist/components/references/URefCardGroup.component.js +88 -0
  72. package/dist/components/references/URefCardGroup.d.ts +7 -0
  73. package/dist/components/references/URefCardGroup.js +5 -0
  74. package/dist/components/references/URefCardGroup.styles.d.ts +1 -0
  75. package/dist/components/references/URefCardGroup.styles.js +69 -0
  76. package/dist/components/references/URefTag.component.d.ts +11 -0
  77. package/dist/components/{buttons/USendButton.component.js → references/URefTag.component.js} +17 -14
  78. package/dist/components/references/URefTag.d.ts +7 -0
  79. package/dist/components/references/URefTag.js +5 -0
  80. package/dist/components/references/URefTag.styles.d.ts +1 -0
  81. package/dist/components/references/URefTag.styles.js +51 -0
  82. package/dist/events/UCancelEvent.d.ts +6 -0
  83. package/dist/index.d.ts +15 -5
  84. package/dist/index.js +20 -6
  85. package/dist/types/BlockItem.d.ts +36 -0
  86. package/dist/types/BlockReference.d.ts +32 -0
  87. package/dist/types/JsonNode.d.ts +20 -0
  88. package/dist/utilities/converters.d.ts +9 -0
  89. package/dist/utilities/converters.js +19 -0
  90. package/package.json +14 -15
  91. package/dist/components/buttons/USendButton.component.d.ts +0 -13
  92. package/dist/components/buttons/USendButton.d.ts +0 -7
  93. package/dist/components/buttons/USendButton.js +0 -5
  94. package/dist/components/buttons/USendButton.styles.js +0 -23
  95. package/dist/components/buttons/UThinkButton.component.d.ts +0 -19
  96. package/dist/components/buttons/UThinkButton.component.js +0 -73
  97. package/dist/components/buttons/UThinkButton.d.ts +0 -7
  98. package/dist/components/buttons/UThinkButton.js +0 -5
  99. package/dist/components/buttons/UThinkButton.styles.js +0 -72
  100. package/dist/components/json-viewer/UJsonViewer.d.ts +0 -7
  101. package/dist/components/json-viewer/UJsonViewer.js +0 -5
  102. package/dist/components/json-viewer/UJsonViewer.lib.d.ts +0 -16
  103. package/dist/components/json-viewer/UJsonViewer.lib.js +0 -28
  104. package/dist/components/message/UMessage.types.d.ts +0 -21
  105. package/dist/events/UStopEvent.d.ts +0 -6
  106. package/dist/internals/date-helpers.d.ts +0 -8
  107. package/dist/internals/date-helpers.js +0 -27
  108. /package/dist/components/{buttons/USendButton.styles.d.ts → blocks/UJsonBlock.styles.d.ts} +0 -0
  109. /package/dist/components/{json-viewer/UJsonViewer.styles.js → blocks/UJsonBlock.styles.js} +0 -0
  110. /package/dist/components/buttons/{UThinkButton.styles.d.ts → UReportButton.styles.d.ts} +0 -0
  111. /package/dist/components/{json-viewer/UJsonViewer.styles.d.ts → buttons/URetryButton.styles.d.ts} +0 -0
@@ -1,5 +1,4 @@
1
1
  import { PropertyValues } from 'lit';
2
- import { nothing } from 'lit/html.js';
3
2
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
4
3
  /**
5
4
  * 추론 내용을 표시하는 블록입니다.
@@ -8,7 +7,7 @@ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
8
7
  export declare class UThinkBlock extends BaseElement {
9
8
  static styles: import('lit').CSSResultGroup[];
10
9
  static dependencies: Record<string, typeof BaseElement>;
11
- bodyEl: HTMLElement;
10
+ bodyEl: HTMLDivElement;
12
11
  /** 컨텐츠가 로딩 중인지 여부 */
13
12
  loading: boolean;
14
13
  /** 컨텐츠가 접혀있는지 여부 */
@@ -16,13 +15,9 @@ export declare class UThinkBlock extends BaseElement {
16
15
  /** 추론 컨텐츠의 내용 */
17
16
  value?: string;
18
17
  protected updated(changedProperties: PropertyValues): void;
19
- render(): typeof nothing | import('lit-html').TemplateResult<1>;
20
- /**
21
- * 컨텐츠 접기/펼치기 토글
22
- */
23
- private toggleCollapsed;
18
+ render(): import('lit-html').TemplateResult<1>;
24
19
  /**
25
20
  * 컨텐츠가 로딩 중일 때, 스크롤을 맨 아래로 이동
26
21
  */
27
- private scrollBodyContent;
22
+ private scrollToBottom;
28
23
  }
@@ -1,8 +1,8 @@
1
1
  import { html } from 'lit';
2
2
  import { query, property } from 'lit/decorators.js';
3
- import { nothing } from 'lit/html.js';
4
3
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
5
4
  import { UIcon } from '@iyulab/components/dist/components/icon/UIcon.component.js';
5
+ import { UMarkedBlock } from './UMarkedBlock.component.js';
6
6
  import { styles } from './UThinkBlock.styles.js';
7
7
 
8
8
  var __defProp = Object.defineProperty;
@@ -19,17 +19,10 @@ class UThinkBlock extends BaseElement {
19
19
  super(...arguments);
20
20
  this.loading = false;
21
21
  this.collapsed = true;
22
- /**
23
- * 컨텐츠 접기/펼치기 토글
24
- */
25
- this.toggleCollapsed = () => {
26
- if (this.loading) return;
27
- this.collapsed = !this.collapsed;
28
- };
29
22
  /**
30
23
  * 컨텐츠가 로딩 중일 때, 스크롤을 맨 아래로 이동
31
24
  */
32
- this.scrollBodyContent = () => {
25
+ this.scrollToBottom = () => {
33
26
  if (!this.bodyEl) return;
34
27
  requestAnimationFrame(() => {
35
28
  this.bodyEl.scrollTo({
@@ -44,26 +37,39 @@ class UThinkBlock extends BaseElement {
44
37
  }
45
38
  static {
46
39
  this.dependencies = {
47
- "u-icon": UIcon
40
+ "u-icon": UIcon,
41
+ "u-marked-block": UMarkedBlock
48
42
  };
49
43
  }
50
44
  updated(changedProperties) {
51
45
  super.updated(changedProperties);
52
- if (changedProperties.has("value") && this.loading) {
53
- this.scrollBodyContent();
46
+ if (changedProperties.has("value") && this.value) {
47
+ this.scrollToBottom();
54
48
  }
55
49
  }
56
50
  render() {
57
- if (!this.value) return nothing;
58
51
  return html`
59
- <div class="container">
60
- <div class="header" @click=${this.toggleCollapsed}>
61
- ${this.loading ? html`<div class="title dots">🤔 Thinking</div>` : html`<div class="title">💡 Thought</div>
62
- ${this.collapsed ? html`<u-icon lib="internal" name="plus-lg"></u-icon>` : html`<u-icon lib="internal" name="dash-lg"></u-icon>`}`}
63
- </div>
64
- <div class="body scroll" ?collapsed=${!this.loading && this.collapsed}>
65
- ${this.value}
66
- </div>
52
+ <div class="header" part="header"
53
+ @click=${() => this.collapsed = !this.collapsed}>
54
+ <u-icon class="prefix-icon"
55
+ ?loading=${this.loading}
56
+ lib="internal"
57
+ name="lightbulb-fill"
58
+ ></u-icon>
59
+ <span class="title">
60
+ ${this.loading ? "Thinking..." : "Thought"}
61
+ </span>
62
+ <u-icon class="suffix-icon"
63
+ lib="internal"
64
+ name=${this.collapsed ? "plus-lg" : "dash-lg"}
65
+ ></u-icon>
66
+ </div>
67
+
68
+ <div class="body" part="body" scrollable
69
+ ?hidden=${this.collapsed}>
70
+ <u-marked-block
71
+ .value=${this.value}
72
+ ></u-marked-block>
67
73
  </div>
68
74
  `;
69
75
  }
@@ -75,7 +81,7 @@ __decorateClass([
75
81
  property({ type: Boolean, reflect: true })
76
82
  ], UThinkBlock.prototype, "loading");
77
83
  __decorateClass([
78
- property({ type: Boolean })
84
+ property({ type: Boolean, reflect: true })
79
85
  ], UThinkBlock.prototype, "collapsed");
80
86
  __decorateClass([
81
87
  property({ type: String })
@@ -2,45 +2,39 @@ import { css } from 'lit';
2
2
 
3
3
  const styles = css`
4
4
  :host {
5
- --loading-rows: 3;
6
- --max-rows: 10;
7
- }
8
-
9
- :host {
10
- display: block;
11
- width: 100%;
12
- height: auto;
13
- }
14
- :host([loading]) .header {
15
- pointer-events: none;
16
- cursor: wait;
17
- }
18
- :host([loading]) .body {
19
- overflow: hidden !important;
20
- max-height: calc(1.5em * var(--loading-rows) + 8px);
21
- animation: pulse_action 1.5s infinite;
22
- pointer-events: none;
23
- cursor: wait;
24
- }
25
-
26
- .container {
27
5
  display: flex;
28
6
  flex-direction: column;
29
7
  width: 100%;
8
+ font-size: 14px;
30
9
  border: 1px solid var(--u-border-color);
31
10
  border-radius: 8px;
32
- font-size: 14px;
33
11
  }
34
12
 
35
13
  .header {
36
14
  width: 100%;
15
+ padding: 8px;
16
+ border-radius: inherit;
37
17
  display: flex;
38
18
  flex-direction: row;
39
19
  align-items: center;
40
20
  justify-content: space-between;
41
- padding: 8px;
42
- cursor: pointer;
21
+ gap: 8px;
43
22
  user-select: none;
23
+ cursor: pointer;
24
+ }
25
+ .header:hover {
26
+ background: linear-gradient(var(--u-neutral-100), transparent);
27
+ }
28
+ .header:active {
29
+ background: linear-gradient(var(--u-neutral-200), transparent);
30
+ }
31
+
32
+ .header .prefix-icon {
33
+ color: var(--u-yellow-800);
34
+ transition: all 0.3s ease-in-out;
35
+ }
36
+ .header .prefix-icon[loading] {
37
+ animation: pulse-glow 3s ease-in-out infinite;
44
38
  }
45
39
  .header .title {
46
40
  flex: 1;
@@ -48,44 +42,31 @@ const styles = css`
48
42
  font-weight: 600;
49
43
  line-height: 1;
50
44
  }
51
- .header .title.dots::after {
52
- content: '';
53
- animation: dots_action 1.5s infinite;
54
- }
55
45
 
56
46
  .body {
57
- overflow: auto;
58
- padding: 8px;
59
- max-height: calc(1.5em * var(--max-rows) + 8px);
60
47
  font-size: inherit;
61
- line-height: 1.5;
62
48
  font-weight: 300;
63
- border-bottom-left-radius: 8px;
64
- border-bottom-right-radius: 8px;
65
- transition: max-height 0.15s ease, padding 0.15s ease;
66
- }
67
- .body[collapsed] {
68
- overflow: hidden !important;
69
- padding: 0;
70
- max-height: 0;
49
+ line-height: 1.5;
50
+ padding: 8px;
51
+ max-height: 210px;
52
+ overflow: auto;
71
53
  }
72
-
73
- @keyframes dots_action {
74
- 0%, 20% { content: ' '; }
75
- 40% { content: ' .'; }
76
- 60% { content: ' ..'; }
77
- 80%, 100% { content: ' ...'; }
54
+ .body u-marked-block {
55
+ font-size: inherit;
56
+ font-family: inherit;
57
+ line-height: inherit;
78
58
  }
79
59
 
80
- @keyframes pulse_action {
81
- 0% {
82
- box-shadow: inset 0px -20px 20px -15px rgb(0, 0, 0, 0.1);
60
+ @keyframes pulse-glow {
61
+ 0%, 100% {
62
+ opacity: 1;
63
+ filter: brightness(1);
64
+ transform: scale(1);
83
65
  }
84
66
  50% {
85
- box-shadow: inset 0px -20px 20px -15px rgb(0, 0, 0, 0.2);
86
- }
87
- 100% {
88
- box-shadow: inset 0px -20px 20px -15px rgb(0, 0, 0, 0.1);
67
+ opacity: 0.7;
68
+ filter: brightness(1.3);
69
+ transform: scale(1.1);
89
70
  }
90
71
  }
91
72
  `;
@@ -1,16 +1,20 @@
1
1
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
2
- import { ToolBlockStatus } from '../message/UMessage.types.js';
2
+ import { JsonNode } from '../../types/JsonNode.js';
3
+ /**
4
+ * 툴 사용 블록 컴포넌트입니다.
5
+ */
3
6
  export declare class UToolBlock extends BaseElement {
4
7
  static styles: import('lit').CSSResultGroup[];
5
8
  static dependencies: Record<string, typeof BaseElement>;
9
+ /** 로딩 상태 */
10
+ loading: boolean;
11
+ /** 블록 접힘 여부 */
6
12
  collapsed: boolean;
7
- status: ToolBlockStatus;
8
- index?: number;
9
- name?: string;
10
- input?: string;
11
- output?: string;
13
+ /** 헤딩 텍스트 */
14
+ heading?: string;
15
+ /** 입력 데이터 (JSON Object) */
16
+ input?: JsonNode;
17
+ /** 출력 데이터 (JSON Object) */
18
+ output?: JsonNode;
12
19
  render(): import('lit-html').TemplateResult<1>;
13
- private parseJson;
14
- handleClickConfirm(): void;
15
- handleClickDeny(): void;
16
20
  }
@@ -1,11 +1,10 @@
1
- import { nothing, html } from 'lit';
1
+ import { html } from 'lit';
2
2
  import { property } from 'lit/decorators.js';
3
3
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
4
4
  import { UIcon } from '@iyulab/components/dist/components/icon/UIcon.component.js';
5
- import { UTooltip } from '@iyulab/components/dist/components/tooltip/UTooltip.component.js';
6
- import { UButton } from '@iyulab/components/dist/components/button/UButton.component.js';
7
5
  import { USpinner } from '@iyulab/components/dist/components/spinner/USpinner.component.js';
8
- import { UJsonViewer } from '../json-viewer/UJsonViewer.component.js';
6
+ import { UJsonBlock } from './UJsonBlock.component.js';
7
+ import { jsonAttrConverter } from '../../utilities/converters.js';
9
8
  import { styles } from './UToolBlock.styles.js';
10
9
 
11
10
  var __defProp = Object.defineProperty;
@@ -20,8 +19,8 @@ var __decorateClass = (decorators, target, key, kind) => {
20
19
  class UToolBlock extends BaseElement {
21
20
  constructor() {
22
21
  super(...arguments);
22
+ this.loading = false;
23
23
  this.collapsed = true;
24
- this.status = "pending";
25
24
  }
26
25
  static {
27
26
  this.styles = [super.styles, styles];
@@ -29,98 +28,53 @@ class UToolBlock extends BaseElement {
29
28
  static {
30
29
  this.dependencies = {
31
30
  "u-icon": UIcon,
32
- "u-tooltip": UTooltip,
33
- "u-button": UButton,
34
31
  "u-spinner": USpinner,
35
- "u-json-viewer": UJsonViewer
32
+ "u-json-block": UJsonBlock
36
33
  };
37
34
  }
38
35
  render() {
39
36
  return html`
40
- <div class="container">
41
- <div class="header" @click=${() => this.collapsed = !this.collapsed}>
42
- ${this.status === "pending" || this.status === "paused" ? html`<u-icon lib="internal" name="eye"></u-icon>` : this.status === "inProgress" ? html`<u-spinner></u-spinner>` : this.status === "success" ? html`<u-icon lib="internal" name="check-lg"></u-icon>` : this.status === "failure" ? html`<u-icon lib="internal" name="x-lg"></u-icon>` : nothing}
43
- <div class="display">
44
- Tool Call [${this.name}]
45
- </div>
46
- <u-icon
47
- lib="internal"
48
- name=${this.collapsed ? "plus-lg" : "dash-lg"}
49
- ></u-icon>
37
+ <div class="header" @click=${() => this.collapsed = !this.collapsed}>
38
+ ${this.loading ? html`<u-spinner></u-spinner>` : html`<u-icon lib="internal" name="tools"></u-icon>`}
39
+ <div class="title">
40
+ ${this.heading || "Tool Usage"}
50
41
  </div>
42
+ <u-icon
43
+ lib="internal"
44
+ name=${this.collapsed ? "plus-lg" : "dash-lg"}
45
+ ></u-icon>
46
+ </div>
51
47
 
52
- <div class="body" ?hidden=${this.collapsed}>
53
- <div class="viewer" ?hidden=${!this.input}>
54
- <div class="label">
55
- <u-icon lib="internal" name="chevron-right"></u-icon>
56
- <u-tooltip placement="left">Input</u-tooltip>
57
- </div>
58
- <u-json-viewer
59
- .value=${this.parseJson(this.input)}
60
- ></u-json-viewer>
61
- </div>
62
- <div class="viewer" ?hidden=${!this.output}>
63
- <div class="label">
64
- <u-icon lib="internal" name="chevron-right"></u-icon>
65
- <u-tooltip placement="left">Output</u-tooltip>
66
- </div>
67
- <u-json-viewer
68
- .value=${this.parseJson(this.output)}
69
- ></u-json-viewer>
70
- </div>
48
+ <div class="body" part="body" scrollable ?hidden=${this.collapsed}>
49
+ <div class="input-view" ?hidden=${!this.input}>
50
+ <u-json-block
51
+ .value=${this.input || {}}
52
+ ></u-json-block>
71
53
  </div>
72
-
73
- <div class="footer" ?hidden=${this.status !== "paused"}>
74
- <u-button @click=${this.handleClickConfirm}>
75
- <u-icon slot="prefix" lib="internal" name="check-lg"></u-icon>
76
- Confirm
77
- </u-button>
78
- <u-button @click=${this.handleClickDeny}>
79
- <u-icon slot="prefix" lib="internal" name="x-lg"></u-icon>
80
- Deny
81
- </u-button>
54
+ <div class="output-view" ?hidden=${!this.output}>
55
+ <u-icon lib="internal" name="chevron-down"></u-icon>
56
+ <u-json-block
57
+ .value=${this.output || {}}
58
+ ></u-json-block>
82
59
  </div>
83
60
  </div>
84
61
  `;
85
62
  }
86
- parseJson(value) {
87
- if (!value || !value.trim()) return {};
88
- try {
89
- return JSON.parse(value);
90
- } catch {
91
- return value;
92
- }
93
- }
94
- handleClickConfirm() {
95
- this.emit("tool-approval", {
96
- index: this.index,
97
- isApproved: true
98
- });
99
- }
100
- handleClickDeny() {
101
- this.emit("tool-approval", {
102
- index: this.index,
103
- isApproved: false
104
- });
105
- }
106
63
  }
107
64
  __decorateClass([
108
65
  property({ type: Boolean, reflect: true })
109
- ], UToolBlock.prototype, "collapsed");
66
+ ], UToolBlock.prototype, "loading");
110
67
  __decorateClass([
111
- property({ type: String })
112
- ], UToolBlock.prototype, "status");
113
- __decorateClass([
114
- property({ type: Number })
115
- ], UToolBlock.prototype, "index");
68
+ property({ type: Boolean, reflect: true })
69
+ ], UToolBlock.prototype, "collapsed");
116
70
  __decorateClass([
117
71
  property({ type: String })
118
- ], UToolBlock.prototype, "name");
72
+ ], UToolBlock.prototype, "heading");
119
73
  __decorateClass([
120
- property({ type: String })
74
+ property({ type: Object, converter: jsonAttrConverter })
121
75
  ], UToolBlock.prototype, "input");
122
76
  __decorateClass([
123
- property({ type: String })
77
+ property({ type: Object, converter: jsonAttrConverter })
124
78
  ], UToolBlock.prototype, "output");
125
79
 
126
80
  export { UToolBlock };
@@ -2,42 +2,37 @@ import { css } from 'lit';
2
2
 
3
3
  const styles = css`
4
4
  :host {
5
- display: block;
5
+ display: flex;
6
+ flex-direction: column;
6
7
  width: 100%;
7
- height: auto;
8
+ font-size: 14px;
8
9
  border: 1px solid var(--u-border-color);
9
10
  border-radius: 8px;
10
- font-size: 14px;
11
- }
12
-
13
- .container {
14
- width: 100%;
15
- display: flex;
16
- flex-direction: column;
17
11
  }
18
12
 
19
13
  .header {
20
14
  width: 100%;
15
+ padding: 8px;
16
+ border-radius: inherit;
21
17
  display: flex;
22
18
  flex-direction: row;
23
19
  align-items: center;
24
20
  justify-content: space-between;
25
21
  gap: 8px;
26
- padding: 8px;
27
22
  cursor: pointer;
28
23
  user-select: none;
29
24
  }
30
- .header u-icon[name="eye"] {
31
- font-size: 16px;
32
- color: var(--u-blue-500);
25
+ .header:hover {
26
+ background: linear-gradient(var(--u-neutral-100), transparent);
33
27
  }
34
- .header u-icon[name="check-lg"] {
35
- color: var(--u-green-500);
28
+ .header:active {
29
+ background: linear-gradient(var(--u-neutral-200), transparent);
36
30
  }
37
- .header u-icon[name="x-lg"] {
38
- color: var(--u-red-500);
31
+
32
+ .header u-icon[name="tools"] {
33
+ color: var(--u-blue-800);
39
34
  }
40
- .header .display {
35
+ .header .title {
41
36
  flex: 1;
42
37
  font-size: inherit;
43
38
  font-weight: 600;
@@ -49,58 +44,22 @@ const styles = css`
49
44
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
50
45
  width: 100%;
51
46
  max-height: 260px;
47
+ padding: 8px;
52
48
  overflow: auto;
53
- scrollbar-width: thin;
54
- scrollbar-color: var(--u-scrollbar-color) transparent;
55
- }
56
- .body .viewer {
57
- width: 100%;
58
- display: flex;
59
- flex-direction: row;
60
- align-items: flex-start;
61
- gap: 8px;
62
- padding: 4px 8px;
63
- }
64
- .body .viewer:not(:last-child) {
65
- border-bottom: 1px dashed var(--u-border-color);
66
49
  }
67
- .body .viewer .label {
68
- display: flex;
69
- align-items: center;
70
- justify-content: center;
71
- font-size: inherit;
72
- font-weight: 400;
73
- width: 1.5em;
74
- height: 1.5em;
75
- }
76
- .body .viewer u-json-viewer {
77
- width: calc(100% - 1.5em);
50
+ .body u-json-viewer {
78
51
  font-size: inherit;
79
52
  font-family: inherit;
80
53
  line-height: 1.5;
81
54
  }
82
-
83
- .footer {
84
- display: flex;
85
- flex-direction: row;
86
- align-items: center;
87
- justify-content: flex-end;
88
- gap: 8px;
89
- padding: 4px 12px;
55
+ .body u-icon[name="chevron-down"] {
56
+ align-self: center;
57
+ font-size: 16px;
58
+ color: var(--u-neutral-600, #4b5563);
90
59
  }
91
- .footer u-button {
60
+ .body .output-view {
92
61
  display: flex;
93
- flex-direction: row;
94
- align-items: center;
95
- gap: 4px;
96
- padding: 6px 8px;
97
- font-size: 12px;
98
- }
99
- .footer u-icon[name="check-lg"] {
100
- color: var(--u-green-500);
101
- }
102
- .footer u-icon[name="x-lg"] {
103
- color: var(--u-red-500);
62
+ flex-direction: column;
104
63
  }
105
64
  `;
106
65
 
@@ -5,20 +5,18 @@ import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
5
5
  export declare class UAttachButton extends BaseElement {
6
6
  static styles: import('lit').CSSResultGroup[];
7
7
  static dependencies: Record<string, typeof BaseElement>;
8
- input: HTMLInputElement;
8
+ input?: HTMLInputElement;
9
9
  /** 첨부 파일 유형 제한, 컴마로 구분된 MIME 타입 문자열 (예: "image/*,application/pdf") */
10
10
  accept?: string;
11
11
  /** 다중 파일 선택 가능 여부 */
12
12
  multiple: boolean;
13
- connectedCallback(): void;
14
- disconnectedCallback(): void;
15
13
  render(): import('lit-html').TemplateResult<1>;
16
14
  /**
17
15
  * 버튼 클릭 핸들러
18
16
  */
19
- private openFileExplorer;
17
+ private handleButtonClick;
20
18
  /**
21
19
  * 파일 선택 이벤트 핸들러
22
20
  */
23
- private handleFileSelected;
21
+ private handleInputChange;
24
22
  }
@@ -2,6 +2,8 @@ import { html } from 'lit';
2
2
  import { query, property } from 'lit/decorators.js';
3
3
  import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
4
4
  import { UIcon } from '@iyulab/components/dist/components/icon/UIcon.component.js';
5
+ import { UButton } from '@iyulab/components/dist/components/button/UButton.component.js';
6
+ import { UTooltip } from '@iyulab/components/dist/components/tooltip/UTooltip.component.js';
5
7
  import { styles } from './UAttachButton.styles.js';
6
8
 
7
9
  var __defProp = Object.defineProperty;
@@ -20,18 +22,22 @@ class UAttachButton extends BaseElement {
20
22
  /**
21
23
  * 버튼 클릭 핸들러
22
24
  */
23
- this.openFileExplorer = () => {
25
+ this.handleButtonClick = () => {
24
26
  if (!this.input) return;
25
27
  this.input.click();
26
28
  };
27
29
  /**
28
30
  * 파일 선택 이벤트 핸들러
29
31
  */
30
- this.handleFileSelected = (e) => {
32
+ this.handleInputChange = (e) => {
33
+ e.preventDefault();
34
+ e.stopPropagation();
31
35
  const target = e.target;
32
36
  const files = target.files;
33
37
  if (!files || files.length === 0) return;
34
- this.emit("select-files", files);
38
+ this.emit("u-change", {
39
+ files: Array.from(files)
40
+ });
35
41
  target.value = "";
36
42
  };
37
43
  }
@@ -40,27 +46,32 @@ class UAttachButton extends BaseElement {
40
46
  }
41
47
  static {
42
48
  this.dependencies = {
43
- "u-icon": UIcon
49
+ "u-icon": UIcon,
50
+ "u-button": UButton,
51
+ "u-tooltip": UTooltip
44
52
  };
45
53
  }
46
- connectedCallback() {
47
- super.connectedCallback();
48
- this.addEventListener("click", this.openFileExplorer);
49
- }
50
- disconnectedCallback() {
51
- this.removeEventListener("click", this.openFileExplorer);
52
- super.disconnectedCallback();
53
- }
54
54
  render() {
55
55
  return html`
56
- <u-icon
57
- lib="internal"
58
- name="paperclip"
59
- ></u-icon>
60
- <input type="file"
56
+ <u-button part="base"
57
+ variant="borderless"
58
+ @click=${this.handleButtonClick}>
59
+ <u-icon part="icon"
60
+ lib="internal"
61
+ name="paperclip"
62
+ ></u-icon>
63
+ </u-button>
64
+
65
+ <u-tooltip for="u-button" placement="bottom" distance="8">
66
+ <slot></slot>
67
+ </u-tooltip>
68
+
69
+ <input
70
+ hidden
71
+ type="file"
61
72
  ?multiple=${this.multiple}
62
- .accept=${this.accept || ""}
63
- @change=${this.handleFileSelected}
73
+ .accept=${this.accept || "*"}
74
+ @change=${this.handleInputChange}
64
75
  />
65
76
  `;
66
77
  }
@@ -1,20 +1,13 @@
1
1
  import { css } from 'lit';
2
2
 
3
3
  const styles = css`
4
- :host {
5
- position: relative;
6
- display: inline-flex;
7
- padding: 8px;
8
- font-size: 16px;
9
- border-radius: 8px;
10
- cursor: pointer;
11
- }
12
- :host(:hover) {
13
- background-color: var(--u-neutral-100, #f3f4f6);
4
+ :host(:empty) u-tooltip {
5
+ display: none;
14
6
  }
15
7
 
16
- input[type="file"] {
17
- display: none;
8
+ u-button {
9
+ color: var(--u-txt-color-weak);
10
+ font-size: 16px;
18
11
  }
19
12
  `;
20
13