igniteui-webcomponents 6.3.0-beta.1 → 6.3.1

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 (129) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/components/chat/chat-input.d.ts +5 -17
  3. package/components/chat/chat-input.js +49 -27
  4. package/components/chat/chat-input.js.map +1 -1
  5. package/components/chat/chat-message.d.ts +3 -3
  6. package/components/chat/chat-message.js +96 -52
  7. package/components/chat/chat-message.js.map +1 -1
  8. package/components/chat/chat-state.d.ts +43 -45
  9. package/components/chat/chat-state.js +67 -74
  10. package/components/chat/chat-state.js.map +1 -1
  11. package/components/chat/chat.d.ts +66 -20
  12. package/components/chat/chat.js +82 -91
  13. package/components/chat/chat.js.map +1 -1
  14. package/components/chat/extras/markdown-renderer.d.ts +2 -2
  15. package/components/chat/extras/markdown-renderer.js +6 -1
  16. package/components/chat/extras/markdown-renderer.js.map +1 -1
  17. package/components/chat/message-attachments.d.ts +2 -2
  18. package/components/chat/message-attachments.js +17 -14
  19. package/components/chat/message-attachments.js.map +1 -1
  20. package/components/chat/themes/chat.base.css.js +1 -1
  21. package/components/chat/themes/chat.base.css.js.map +1 -1
  22. package/components/chat/themes/dark/chat.bootstrap.css.js +1 -1
  23. package/components/chat/themes/dark/chat.bootstrap.css.js.map +1 -1
  24. package/components/chat/themes/dark/chat.fluent.css.js +1 -1
  25. package/components/chat/themes/dark/chat.fluent.css.js.map +1 -1
  26. package/components/chat/themes/dark/chat.indigo.css.js +1 -1
  27. package/components/chat/themes/dark/chat.indigo.css.js.map +1 -1
  28. package/components/chat/themes/dark/chat.material.css.js +1 -1
  29. package/components/chat/themes/dark/chat.material.css.js.map +1 -1
  30. package/components/chat/themes/input.base.css.js +1 -1
  31. package/components/chat/themes/input.base.css.js.map +1 -1
  32. package/components/chat/themes/light/chat.bootstrap.css.js +1 -1
  33. package/components/chat/themes/light/chat.bootstrap.css.js.map +1 -1
  34. package/components/chat/themes/light/chat.indigo.css.js +1 -1
  35. package/components/chat/themes/light/chat.indigo.css.js.map +1 -1
  36. package/components/chat/themes/light/chat.shared.css.js +1 -1
  37. package/components/chat/themes/light/chat.shared.css.js.map +1 -1
  38. package/components/chat/themes/message-attachments.base.css.js +1 -1
  39. package/components/chat/themes/message-attachments.base.css.js.map +1 -1
  40. package/components/chat/themes/message.base.css.js +1 -1
  41. package/components/chat/themes/message.base.css.js.map +1 -1
  42. package/components/chat/themes/shared/chat.bootstrap.css.js +1 -1
  43. package/components/chat/themes/shared/chat.bootstrap.css.js.map +1 -1
  44. package/components/chat/themes/shared/chat.fluent.css.js +1 -1
  45. package/components/chat/themes/shared/chat.fluent.css.js.map +1 -1
  46. package/components/chat/themes/shared/chat.indigo.css.js +1 -1
  47. package/components/chat/themes/shared/chat.indigo.css.js.map +1 -1
  48. package/components/chat/themes/shared/message-attachments/message-attachments.common.css.js +1 -1
  49. package/components/chat/themes/shared/message-attachments/message-attachments.common.css.js.map +1 -1
  50. package/components/chat/types.d.ts +164 -30
  51. package/components/chat/types.js.map +1 -1
  52. package/components/chat/utils.d.ts +3 -4
  53. package/components/chat/utils.js +0 -12
  54. package/components/chat/utils.js.map +1 -1
  55. package/components/checkbox/themes/checkbox.base.css.js +1 -1
  56. package/components/checkbox/themes/checkbox.base.css.js.map +1 -1
  57. package/components/checkbox/themes/switch.base.css.js +1 -1
  58. package/components/checkbox/themes/switch.base.css.js.map +1 -1
  59. package/components/common/i18n/chat.resources.d.ts +3 -0
  60. package/components/common/i18n/chat.resources.js +3 -0
  61. package/components/common/i18n/chat.resources.js.map +1 -1
  62. package/components/common/util.d.ts +3 -0
  63. package/components/common/util.js +9 -1
  64. package/components/common/util.js.map +1 -1
  65. package/components/input/themes/shared/input.bootstrap.css.js +1 -1
  66. package/components/input/themes/shared/input.bootstrap.css.js.map +1 -1
  67. package/components/input/themes/shared/input.indigo.css.js +1 -1
  68. package/components/input/themes/shared/input.indigo.css.js.map +1 -1
  69. package/components/list/themes/header.js +2 -28
  70. package/components/list/themes/header.js.map +1 -1
  71. package/components/list/themes/item.js +6 -20
  72. package/components/list/themes/item.js.map +1 -1
  73. package/components/textarea/themes/shared/textarea.bootstrap.css.js +1 -1
  74. package/components/textarea/themes/shared/textarea.bootstrap.css.js.map +1 -1
  75. package/components/tile-manager/themes/tile-manager.base.css.js +1 -1
  76. package/components/tile-manager/themes/tile-manager.base.css.js.map +1 -1
  77. package/custom-elements.json +2110 -2045
  78. package/igniteui-webcomponents.css-data.json +1 -1
  79. package/igniteui-webcomponents.html-data.json +1 -1
  80. package/package.json +24 -2
  81. package/web-types.json +2 -2
  82. package/components/list/themes/dark/header/list-header.bootstrap.css.d.ts +0 -1
  83. package/components/list/themes/dark/header/list-header.bootstrap.css.js +0 -3
  84. package/components/list/themes/dark/header/list-header.bootstrap.css.js.map +0 -1
  85. package/components/list/themes/dark/header/list-header.fluent.css.d.ts +0 -1
  86. package/components/list/themes/dark/header/list-header.fluent.css.js +0 -3
  87. package/components/list/themes/dark/header/list-header.fluent.css.js.map +0 -1
  88. package/components/list/themes/dark/header/list-header.indigo.css.d.ts +0 -1
  89. package/components/list/themes/dark/header/list-header.indigo.css.js +0 -3
  90. package/components/list/themes/dark/header/list-header.indigo.css.js.map +0 -1
  91. package/components/list/themes/dark/header/list-header.material.css.d.ts +0 -1
  92. package/components/list/themes/dark/header/list-header.material.css.js +0 -3
  93. package/components/list/themes/dark/header/list-header.material.css.js.map +0 -1
  94. package/components/list/themes/dark/item/list-item.bootstrap.css.d.ts +0 -1
  95. package/components/list/themes/dark/item/list-item.bootstrap.css.js +0 -3
  96. package/components/list/themes/dark/item/list-item.bootstrap.css.js.map +0 -1
  97. package/components/list/themes/dark/item/list-item.fluent.css.d.ts +0 -1
  98. package/components/list/themes/dark/item/list-item.fluent.css.js +0 -3
  99. package/components/list/themes/dark/item/list-item.fluent.css.js.map +0 -1
  100. package/components/list/themes/dark/item/list-item.indigo.css.d.ts +0 -1
  101. package/components/list/themes/dark/item/list-item.indigo.css.js +0 -3
  102. package/components/list/themes/dark/item/list-item.indigo.css.js.map +0 -1
  103. package/components/list/themes/dark/item/list-item.material.css.d.ts +0 -1
  104. package/components/list/themes/dark/item/list-item.material.css.js +0 -3
  105. package/components/list/themes/dark/item/list-item.material.css.js.map +0 -1
  106. package/components/list/themes/light/header/list-header.bootstrap.css.d.ts +0 -1
  107. package/components/list/themes/light/header/list-header.bootstrap.css.js +0 -3
  108. package/components/list/themes/light/header/list-header.bootstrap.css.js.map +0 -1
  109. package/components/list/themes/light/header/list-header.fluent.css.d.ts +0 -1
  110. package/components/list/themes/light/header/list-header.fluent.css.js +0 -3
  111. package/components/list/themes/light/header/list-header.fluent.css.js.map +0 -1
  112. package/components/list/themes/light/header/list-header.indigo.css.d.ts +0 -1
  113. package/components/list/themes/light/header/list-header.indigo.css.js +0 -3
  114. package/components/list/themes/light/header/list-header.indigo.css.js.map +0 -1
  115. package/components/list/themes/light/header/list-header.material.css.d.ts +0 -1
  116. package/components/list/themes/light/header/list-header.material.css.js +0 -3
  117. package/components/list/themes/light/header/list-header.material.css.js.map +0 -1
  118. package/components/list/themes/light/item/list-item.bootstrap.css.d.ts +0 -1
  119. package/components/list/themes/light/item/list-item.bootstrap.css.js +0 -3
  120. package/components/list/themes/light/item/list-item.bootstrap.css.js.map +0 -1
  121. package/components/list/themes/light/item/list-item.fluent.css.d.ts +0 -1
  122. package/components/list/themes/light/item/list-item.fluent.css.js +0 -3
  123. package/components/list/themes/light/item/list-item.fluent.css.js.map +0 -1
  124. package/components/list/themes/light/item/list-item.indigo.css.d.ts +0 -1
  125. package/components/list/themes/light/item/list-item.indigo.css.js +0 -3
  126. package/components/list/themes/light/item/list-item.indigo.css.js.map +0 -1
  127. package/components/list/themes/light/item/list-item.material.css.d.ts +0 -1
  128. package/components/list/themes/light/item/list-item.material.css.js +0 -3
  129. package/components/list/themes/light/item/list-item.material.css.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [6.3.1] - 2025-09-18
8
+ ### Fixed
9
+ - peerDependencies versions
10
+
11
+ ## [6.3.0] - 2025-09-18
12
+ ### Added
13
+ - Chat component
14
+
15
+ ### Fixed
16
+ - #### List
17
+ - removed duplicated CSS variables across list components and themes [#1853](https://github.com/IgniteUI/igniteui-webcomponents/pull/1853)
18
+
19
+ ## [6.2.2] - 2025-09-16
20
+ ### Fixed
21
+ - Minor bug fixes around styles
22
+
7
23
  ## [6.2.1] - 2025-09-01
8
24
  ### Added
9
25
  - #### Date picker
@@ -1010,6 +1026,9 @@ Initial release of Ignite UI Web Components
1010
1026
  - Ripple component
1011
1027
  - Switch component
1012
1028
 
1029
+ [6.3.1]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.3.0...6.3.1
1030
+ [6.3.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.2.2...6.3.0
1031
+ [6.2.2]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.2.1...6.2.2
1013
1032
  [6.2.1]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.2.0...6.2.1
1014
1033
  [6.2.0]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.1.2...6.2.0
1015
1034
  [6.1.2]: https://github.com/IgniteUI/igniteui-webcomponents/compare/6.1.1...6.1.2
@@ -22,7 +22,7 @@ import { LitElement } from 'lit';
22
22
  * @csspart input-container - Container for the input section
23
23
  * @csspart input-wrapper - Wrapper around the text input
24
24
  * @csspart text-input - The `<igc-textarea>` component
25
- * @csspart buttons-container - Container for file upload/send buttons
25
+ * @csspart actions-container - Container for file upload/send buttons
26
26
  * @csspart send-button - The send icon button
27
27
  * @csspart attachments - Container for rendering attachments
28
28
  * @csspart attachment-wrapper - Wrapper for individual attachment
@@ -40,8 +40,11 @@ export default class IgcChatInputComponent extends LitElement {
40
40
  private _parts;
41
41
  private get _acceptedTypes();
42
42
  constructor();
43
- protected firstUpdated(): void;
43
+ /** @internal */
44
+ focusInput(): void;
44
45
  private _getRenderer;
46
+ private _sendMessage;
47
+ private _handleAttachmentRemoved;
45
48
  private _handleKeydown;
46
49
  private _handleFileInputClick;
47
50
  private _handleFocusState;
@@ -49,11 +52,6 @@ export default class IgcChatInputComponent extends LitElement {
49
52
  private _handleDragOver;
50
53
  private _handleDragLeave;
51
54
  private _handleDrop;
52
- /**
53
- * Handles input text changes.
54
- * Updates internal inputValue and emits 'igcInputChange' event.
55
- * @param e Input event from the text area
56
- */
57
55
  private _handleInput;
58
56
  private _handleFileUpload;
59
57
  /**
@@ -68,17 +66,7 @@ export default class IgcChatInputComponent extends LitElement {
68
66
  * @returns TemplateResult containing the text area
69
67
  */
70
68
  private _renderTextArea;
71
- /**
72
- * Default file upload button template used when no custom template is provided.
73
- * Renders a file input for attaching files.
74
- * @returns TemplateResult containing the file upload button
75
- */
76
69
  private _renderFileUploadButton;
77
- /**
78
- * Default send button template used when no custom template is provided.
79
- * Renders a send button that submits the current input value and attachments.
80
- * @returns TemplateResult containing the send button
81
- */
82
70
  private _renderSendButton;
83
71
  private _renderActionsArea;
84
72
  protected render(): import("lit-html").TemplateResult<1>;
@@ -17,7 +17,7 @@ import { chatContext, chatUserInputContext } from '../common/context.js';
17
17
  import { enterKey } from '../common/controllers/key-bindings.js';
18
18
  import { registerComponent } from '../common/definitions/register.js';
19
19
  import { partMap } from '../common/part-map.js';
20
- import { bindIf, hasFiles, isEmpty } from '../common/util.js';
20
+ import { bindIf, hasFiles, isEmpty, trimmedHtml } from '../common/util.js';
21
21
  import IgcIconComponent from '../icon/icon.js';
22
22
  import IgcTextareaComponent from '../textarea/textarea.js';
23
23
  import { styles } from './themes/input.base.css.js';
@@ -39,15 +39,16 @@ export default class IgcChatInputComponent extends LitElement {
39
39
  fileUploadButton: () => this._renderFileUploadButton(),
40
40
  input: () => this._renderTextArea(),
41
41
  inputActions: () => this._renderActionsArea(),
42
+ inputActionsEnd: () => nothing,
43
+ inputActionsStart: () => nothing,
42
44
  inputAttachments: (ctx) => this._renderAttachmentsArea(ctx.attachments),
43
45
  sendButton: () => this._renderSendButton(),
44
46
  });
45
47
  this._parts = { 'input-container': true, dragging: false };
46
48
  addThemingController(this, all);
47
49
  }
48
- firstUpdated() {
49
- this._state.updateAcceptedTypesCache();
50
- this._state.textArea = this._textInputElement;
50
+ focusInput() {
51
+ this._textInputElement.focus();
51
52
  }
52
53
  _getRenderer(name) {
53
54
  return this._state.options?.renderers
@@ -55,11 +56,30 @@ export default class IgcChatInputComponent extends LitElement {
55
56
  this._defaults[name])
56
57
  : this._defaults[name];
57
58
  }
59
+ async _sendMessage() {
60
+ if (!this._userInputState.hasInputValue &&
61
+ !this._userInputState.hasInputAttachments) {
62
+ return;
63
+ }
64
+ this._userInputState.addMessageWithEvent({
65
+ text: this._userInputState.inputValue,
66
+ attachments: this._userInputState.inputAttachments,
67
+ });
68
+ this.style.height = 'auto';
69
+ await this._userInputState.host.updateComplete;
70
+ this.focusInput();
71
+ }
72
+ _handleAttachmentRemoved(attachment) {
73
+ const current = this._userInputState.inputAttachments;
74
+ if (this._state.emitAttachmentRemoved(attachment)) {
75
+ this._state.inputAttachments = current.toSpliced(current.indexOf(attachment), 1);
76
+ }
77
+ }
58
78
  _handleKeydown(event) {
59
- const isSend = event.key === enterKey && !event.shiftKey;
60
- if (isSend) {
79
+ const isSendRequest = event.key.toLowerCase() === enterKey.toLowerCase() && !event.shiftKey;
80
+ if (isSendRequest) {
61
81
  event.preventDefault();
62
- this._state.sendMessage();
82
+ this._sendMessage();
63
83
  }
64
84
  else {
65
85
  this._state.handleKeyDown(event);
@@ -101,29 +121,28 @@ export default class IgcChatInputComponent extends LitElement {
101
121
  this._parts = { 'input-container': true, dragging: false };
102
122
  const validFiles = getChatAcceptedFiles(event, this._acceptedTypes);
103
123
  this._state.emitEvent('igcAttachmentDrop');
104
- this._state.attachFiles(validFiles);
124
+ this._state.attachFilesWithEvent(validFiles);
105
125
  this.requestUpdate();
106
126
  }
107
127
  _handleInput({ detail }) {
108
- if (detail === this._state.inputValue)
109
- return;
110
128
  this._state.inputValue = detail;
111
129
  this._state.emitEvent('igcInputChange', { detail: { value: detail } });
112
130
  }
113
131
  _handleFileUpload(event) {
114
132
  const input = event.target;
115
133
  if (hasFiles(input)) {
116
- this._state.attachFiles(Array.from(input.files));
134
+ this._state.attachFilesWithEvent(Array.from(input.files));
117
135
  }
118
136
  }
119
137
  _renderAttachmentsArea(attachments) {
120
- return html `${attachments?.map((attachment, index) => html `
138
+ return html `${attachments?.map((attachment) => html `
121
139
  <div part="attachment-wrapper" role="listitem">
122
140
  <igc-chip
123
141
  removable
124
- @igcRemove=${() => this._state.removeAttachment(index)}
142
+ @igcRemove=${() => this._handleAttachmentRemoved(attachment)}
125
143
  >
126
144
  <igc-icon
145
+ part="attachment-icon"
127
146
  slot="prefix"
128
147
  name=${getIconName(attachment.file?.type ?? attachment.type)}
129
148
  ></igc-icon>
@@ -154,7 +173,7 @@ export default class IgcChatInputComponent extends LitElement {
154
173
  return html `${cache(attachmentsDisabled
155
174
  ? nothing
156
175
  : html `
157
- <label for="input_attachments" part="upload-button">
176
+ <label for="input_attachments" part="file-upload">
158
177
  <igc-icon-button
159
178
  aria-label="Attach files"
160
179
  variant="flat"
@@ -164,6 +183,7 @@ export default class IgcChatInputComponent extends LitElement {
164
183
  <input
165
184
  type="file"
166
185
  id="input_attachments"
186
+ tabindex="-1"
167
187
  name="input_attachments"
168
188
  aria-label="Upload button"
169
189
  multiple
@@ -182,25 +202,27 @@ export default class IgcChatInputComponent extends LitElement {
182
202
  variant="contained"
183
203
  part="send-button"
184
204
  ?disabled=${!enabled}
185
- @click=${this._state.sendMessage}
205
+ @click=${this._sendMessage}
186
206
  ></igc-icon-button>
187
207
  `;
188
208
  }
189
209
  _renderActionsArea() {
190
- const ctx = {
191
- defaults: this._defaults,
192
- instance: this._state.host,
193
- };
194
- return html `
195
- ${this._getRenderer('fileUploadButton')(ctx)}
196
- ${this._getRenderer('sendButton')(ctx)}
210
+ const ctx = { instance: this._state.host };
211
+ return trimmedHtml `
212
+ <div part="file-upload-container">
213
+ ${this._getRenderer('fileUploadButton')(ctx)}
214
+ </div>
215
+ <div part="input-actions-start">
216
+ ${this._getRenderer('inputActionsStart')(ctx)}
217
+ </div>
218
+ <div part="send-button-container">${this._getRenderer('sendButton')(ctx)}</div>
219
+ <div part="input-actions-end">
220
+ ${this._getRenderer('inputActionsEnd')(ctx)}
221
+ </div>
197
222
  `;
198
223
  }
199
224
  render() {
200
- const ctx = {
201
- defaults: this._defaults,
202
- instance: this._state.host,
203
- };
225
+ const ctx = { instance: this._state.host };
204
226
  const inputCtx = {
205
227
  ...ctx,
206
228
  attachments: this._state.inputAttachments,
@@ -226,7 +248,7 @@ export default class IgcChatInputComponent extends LitElement {
226
248
  ${until(this._getRenderer('input')(inputCtx))}
227
249
  </div>
228
250
 
229
- <div part="buttons-container">
251
+ <div part="actions-container">
230
252
  ${until(this._getRenderer('inputActions')(ctx))}
231
253
  </div>
232
254
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"chat-input.js","sourceRoot":"","sources":["../../../src/components/chat/chat-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { query, state } from 'lit/decorators.js';\nimport { cache } from 'lit/directives/cache.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { until } from 'lit/directives/until.js';\nimport { addThemingController } from '../../theming/theming-controller.js';\nimport IgcIconButtonComponent from '../button/icon-button.js';\nimport IgcChipComponent from '../chip/chip.js';\nimport { chatContext, chatUserInputContext } from '../common/context.js';\nimport { enterKey } from '../common/controllers/key-bindings.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport { partMap } from '../common/part-map.js';\nimport { bindIf, hasFiles, isEmpty } from '../common/util.js';\nimport IgcIconComponent from '../icon/icon.js';\nimport IgcTextareaComponent from '../textarea/textarea.js';\nimport type { ChatState } from './chat-state.js';\nimport { styles } from './themes/input.base.css.js';\nimport { all } from './themes/input.js';\nimport { styles as shared } from './themes/shared/input/input.common.css.js';\nimport type {\n ChatRendererContext,\n ChatTemplateRenderer,\n IgcMessageAttachment,\n InputRendererContext,\n} from './types.js';\nimport { getChatAcceptedFiles, getIconName } from './utils.js';\n\ntype DefaultInputRenderers = {\n input: ChatTemplateRenderer<InputRendererContext>;\n inputActions: ChatTemplateRenderer<ChatRendererContext>;\n inputAttachments: ChatTemplateRenderer<InputRendererContext>;\n fileUploadButton: ChatTemplateRenderer<ChatRendererContext>;\n sendButton: ChatTemplateRenderer<ChatRendererContext>;\n};\n/**\n * A web component that provides the input area for the `igc-chat` interface.\n *\n * It supports:\n * - Text input with automatic resizing\n * - Sending messages on Enter key (with Shift+Enter for newlines)\n * - File attachments via file picker or drag-and-drop\n * - Customizable templates for send button, attachments, and text input\n * - Emits various chat-related events (typing, input focus/blur, attachment drop, etc.)\n *\n * @element igc-chat-input\n *\n * @slot - Default unnamed slot for rendering inside the component\n * @fires igcTypingChange - Fired when the user starts/stops typing\n * @fires igcInputFocus - Fired when the input area receives focus\n * @fires igcInputBlur - Fired when the input area loses focus\n * @fires igcAttachmentDrag - Fired when dragging a file over the input\n * @fires igcAttachmentDrop - Fired when a file is dropped into the input\n * @fires igcChange - Fired when file input changes (delegated from `<igc-file-input>`)\n *\n * @csspart input-container - Container for the input section\n * @csspart input-wrapper - Wrapper around the text input\n * @csspart text-input - The `<igc-textarea>` component\n * @csspart buttons-container - Container for file upload/send buttons\n * @csspart send-button - The send icon button\n * @csspart attachments - Container for rendering attachments\n * @csspart attachment-wrapper - Wrapper for individual attachment\n * @csspart attachment-name - Display name of an attachment\n */\nexport default class IgcChatInputComponent extends LitElement {\n public static readonly tagName = 'igc-chat-input';\n public static override styles = [styles, shared];\n\n /* blazorSuppress */\n public static register(): void {\n registerComponent(\n IgcChatInputComponent,\n IgcTextareaComponent,\n IgcIconButtonComponent,\n IgcChipComponent,\n IgcIconComponent\n );\n }\n\n private readonly _defaults: Readonly<DefaultInputRenderers> = Object.freeze({\n fileUploadButton: () => this._renderFileUploadButton(),\n input: () => this._renderTextArea(),\n inputActions: () => this._renderActionsArea(),\n inputAttachments: (ctx) => this._renderAttachmentsArea(ctx.attachments),\n sendButton: () => this._renderSendButton(),\n });\n\n @consume({ context: chatContext, subscribe: true })\n private readonly _state!: ChatState;\n\n @consume({ context: chatUserInputContext, subscribe: true })\n private readonly _userInputState!: ChatState;\n\n @query(IgcTextareaComponent.tagName)\n private readonly _textInputElement!: IgcTextareaComponent;\n\n @query('#input_attachments')\n protected readonly _fileInput!: HTMLInputElement;\n\n @state()\n private _parts = { 'input-container': true, dragging: false };\n\n private get _acceptedTypes() {\n return this._state.acceptedFileTypes;\n }\n\n constructor() {\n super();\n addThemingController(this, all);\n }\n\n protected override firstUpdated() {\n this._state.updateAcceptedTypesCache();\n this._state.textArea = this._textInputElement;\n }\n\n private _getRenderer<U extends keyof DefaultInputRenderers>(\n name: U\n ): DefaultInputRenderers[U] {\n return this._state.options?.renderers\n ? ((this._state.options.renderers[name] ??\n this._defaults[name]) as DefaultInputRenderers[U])\n : this._defaults[name];\n }\n\n private _handleKeydown(event: KeyboardEvent): void {\n const isSend = event.key === enterKey && !event.shiftKey;\n\n if (isSend) {\n event.preventDefault();\n this._state.sendMessage();\n } else {\n // TODO:\n this._state.handleKeyDown(event);\n }\n }\n\n private _handleFileInputClick(): void {\n this._fileInput.showPicker();\n }\n\n private _handleFocusState(event: FocusEvent): void {\n this._state.emitEvent(\n event.type === 'focus' ? 'igcInputFocus' : 'igcInputBlur'\n );\n }\n\n private _handleDragEnter(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n\n const validFiles = getChatAcceptedFiles(event, this._acceptedTypes);\n this._parts = { 'input-container': true, dragging: !isEmpty(validFiles) };\n this._state.emitEvent('igcAttachmentDrag');\n }\n\n private _handleDragOver(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n private _handleDragLeave(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n\n // Check if we're actually leaving the container\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n\n if (\n x <= rect.left ||\n x >= rect.right ||\n y <= rect.top ||\n y >= rect.bottom\n ) {\n this._parts = { 'input-container': true, dragging: false };\n }\n }\n\n private _handleDrop(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n this._parts = { 'input-container': true, dragging: false };\n\n const validFiles = getChatAcceptedFiles(event, this._acceptedTypes);\n this._state.emitEvent('igcAttachmentDrop');\n this._state.attachFiles(validFiles);\n this.requestUpdate();\n }\n\n /**\n * Handles input text changes.\n * Updates internal inputValue and emits 'igcInputChange' event.\n * @param e Input event from the text area\n */\n private _handleInput({ detail }: CustomEvent<string>): void {\n if (detail === this._state.inputValue) return;\n\n this._state.inputValue = detail;\n this._state.emitEvent('igcInputChange', { detail: { value: detail } });\n }\n\n private _handleFileUpload(event: Event): void {\n const input = event.target as HTMLInputElement;\n\n if (hasFiles(input)) {\n this._state.attachFiles(Array.from(input.files!));\n }\n }\n /**\n * Default attachments area template used when no custom template is provided.\n * Renders the list of input attachments as chips.\n * @returns TemplateResult containing the attachments area\n */\n private _renderAttachmentsArea(attachments: IgcMessageAttachment[]) {\n return html`${attachments?.map(\n (attachment, index) => html`\n <div part=\"attachment-wrapper\" role=\"listitem\">\n <igc-chip\n removable\n @igcRemove=${() => this._state.removeAttachment(index)}\n >\n <igc-icon\n slot=\"prefix\"\n name=${getIconName(attachment.file?.type ?? attachment.type)}\n ></igc-icon>\n <span part=\"attachment-name\">${attachment.name}</span>\n </igc-chip>\n </div>\n `\n )} `;\n }\n\n /**\n * Default text area template used when no custom template is provided.\n * Renders a text area for user input.\n * @returns TemplateResult containing the text area\n */\n private _renderTextArea() {\n return html`\n <igc-textarea\n part=\"text-input\"\n aria-label=\"Chat text input\"\n placeholder=${ifDefined(this._state.options?.inputPlaceholder)}\n resize=\"auto\"\n rows=\"1\"\n .value=${this._userInputState?.inputValue}\n @igcInput=${this._handleInput}\n @keydown=${this._handleKeydown}\n @focus=${this._handleFocusState}\n @blur=${this._handleFocusState}\n ></igc-textarea>\n `;\n }\n\n /**\n * Default file upload button template used when no custom template is provided.\n * Renders a file input for attaching files.\n * @returns TemplateResult containing the file upload button\n */\n private _renderFileUploadButton() {\n const accepted = this._state.options?.acceptedFiles;\n const attachmentsDisabled = this._state.options?.disableInputAttachments;\n\n return html`${cache(\n attachmentsDisabled\n ? nothing\n : html`\n <label for=\"input_attachments\" part=\"upload-button\">\n <igc-icon-button\n aria-label=\"Attach files\"\n variant=\"flat\"\n name=\"attach_file\"\n @click=${this._handleFileInputClick}\n ></igc-icon-button>\n <input\n type=\"file\"\n id=\"input_attachments\"\n name=\"input_attachments\"\n aria-label=\"Upload button\"\n multiple\n accept=${bindIf(accepted, accepted)}\n @change=${this._handleFileUpload}\n />\n </label>\n `\n )}`;\n }\n\n /**\n * Default send button template used when no custom template is provided.\n * Renders a send button that submits the current input value and attachments.\n * @returns TemplateResult containing the send button\n */\n private _renderSendButton() {\n const enabled =\n this._state.hasInputValue || this._state.hasInputAttachments;\n\n return html`\n <igc-icon-button\n aria-label=\"Send message\"\n name=\"send_message\"\n variant=\"contained\"\n part=\"send-button\"\n ?disabled=${!enabled}\n @click=${this._state.sendMessage}\n ></igc-icon-button>\n `;\n }\n\n private _renderActionsArea() {\n const ctx: ChatRendererContext = {\n defaults: this._defaults,\n instance: this._state.host,\n };\n\n return html`\n ${this._getRenderer('fileUploadButton')(ctx)}\n ${this._getRenderer('sendButton')(ctx)}\n `;\n }\n\n protected override render() {\n const ctx: ChatRendererContext = {\n defaults: this._defaults,\n instance: this._state.host,\n };\n\n const inputCtx: InputRendererContext = {\n ...ctx,\n attachments: this._state.inputAttachments,\n value: this._state.inputValue,\n };\n\n return html`\n <div\n part=${partMap(this._parts)}\n @dragenter=${this._handleDragEnter}\n @dragover=${this._handleDragOver}\n @dragleave=${this._handleDragLeave}\n @drop=${this._handleDrop}\n >\n ${this._state.hasInputAttachments\n ? html`\n <div part=\"attachments\" role=\"list\" aria-label=\"Attachments\">\n ${until(this._getRenderer('inputAttachments')(inputCtx))}\n </div>\n `\n : nothing}\n\n <div part=\"input-wrapper\">\n ${until(this._getRenderer('input')(inputCtx))}\n </div>\n\n <div part=\"buttons-container\">\n ${until(this._getRenderer('inputActions')(ctx))}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-input': IgcChatInputComponent;\n }\n}\n"]}
1
+ {"version":3,"file":"chat-input.js","sourceRoot":"","sources":["../../../src/components/chat/chat-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { consume } from '@lit/context';\nimport { html, LitElement, nothing } from 'lit';\nimport { query, state } from 'lit/decorators.js';\nimport { cache } from 'lit/directives/cache.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { until } from 'lit/directives/until.js';\nimport { addThemingController } from '../../theming/theming-controller.js';\nimport IgcIconButtonComponent from '../button/icon-button.js';\nimport IgcChipComponent from '../chip/chip.js';\nimport { chatContext, chatUserInputContext } from '../common/context.js';\nimport { enterKey } from '../common/controllers/key-bindings.js';\nimport { registerComponent } from '../common/definitions/register.js';\nimport { partMap } from '../common/part-map.js';\nimport { bindIf, hasFiles, isEmpty, trimmedHtml } from '../common/util.js';\nimport IgcIconComponent from '../icon/icon.js';\nimport IgcTextareaComponent from '../textarea/textarea.js';\nimport type { ChatState } from './chat-state.js';\nimport { styles } from './themes/input.base.css.js';\nimport { all } from './themes/input.js';\nimport { styles as shared } from './themes/shared/input/input.common.css.js';\nimport type {\n ChatInputRenderContext,\n ChatRenderContext,\n ChatTemplateRenderer,\n IgcChatMessageAttachment,\n} from './types.js';\nimport { getChatAcceptedFiles, getIconName } from './utils.js';\n\ntype DefaultInputRenderers = {\n input: ChatTemplateRenderer<ChatInputRenderContext>;\n inputActions: ChatTemplateRenderer<ChatRenderContext>;\n inputActionsEnd: ChatTemplateRenderer<ChatRenderContext>;\n inputActionsStart: ChatTemplateRenderer<ChatRenderContext>;\n inputAttachments: ChatTemplateRenderer<ChatInputRenderContext>;\n fileUploadButton: ChatTemplateRenderer<ChatRenderContext>;\n sendButton: ChatTemplateRenderer<ChatRenderContext>;\n};\n\n/* blazorSuppress */\n/**\n * A web component that provides the input area for the `igc-chat` interface.\n *\n * It supports:\n * - Text input with automatic resizing\n * - Sending messages on Enter key (with Shift+Enter for newlines)\n * - File attachments via file picker or drag-and-drop\n * - Customizable templates for send button, attachments, and text input\n * - Emits various chat-related events (typing, input focus/blur, attachment drop, etc.)\n *\n * @element igc-chat-input\n *\n * @slot - Default unnamed slot for rendering inside the component\n * @fires igcTypingChange - Fired when the user starts/stops typing\n * @fires igcInputFocus - Fired when the input area receives focus\n * @fires igcInputBlur - Fired when the input area loses focus\n * @fires igcAttachmentDrag - Fired when dragging a file over the input\n * @fires igcAttachmentDrop - Fired when a file is dropped into the input\n * @fires igcChange - Fired when file input changes (delegated from `<igc-file-input>`)\n *\n * @csspart input-container - Container for the input section\n * @csspart input-wrapper - Wrapper around the text input\n * @csspart text-input - The `<igc-textarea>` component\n * @csspart actions-container - Container for file upload/send buttons\n * @csspart send-button - The send icon button\n * @csspart attachments - Container for rendering attachments\n * @csspart attachment-wrapper - Wrapper for individual attachment\n * @csspart attachment-name - Display name of an attachment\n */\nexport default class IgcChatInputComponent extends LitElement {\n public static readonly tagName = 'igc-chat-input';\n public static override styles = [styles, shared];\n\n /* blazorSuppress */\n public static register(): void {\n registerComponent(\n IgcChatInputComponent,\n IgcTextareaComponent,\n IgcIconButtonComponent,\n IgcChipComponent,\n IgcIconComponent\n );\n }\n\n private readonly _defaults: Readonly<DefaultInputRenderers> = Object.freeze({\n fileUploadButton: () => this._renderFileUploadButton(),\n input: () => this._renderTextArea(),\n inputActions: () => this._renderActionsArea(),\n inputActionsEnd: () => nothing,\n inputActionsStart: () => nothing,\n inputAttachments: (ctx) => this._renderAttachmentsArea(ctx.attachments),\n sendButton: () => this._renderSendButton(),\n });\n\n @consume({ context: chatContext, subscribe: true })\n private readonly _state!: ChatState;\n\n @consume({ context: chatUserInputContext, subscribe: true })\n private readonly _userInputState!: ChatState;\n\n @query(IgcTextareaComponent.tagName)\n private readonly _textInputElement!: IgcTextareaComponent;\n\n @query('#input_attachments')\n protected readonly _fileInput!: HTMLInputElement;\n\n @state()\n private _parts = { 'input-container': true, dragging: false };\n\n private get _acceptedTypes() {\n return this._state.acceptedFileTypes;\n }\n\n constructor() {\n super();\n addThemingController(this, all);\n }\n\n /** @internal */\n public focusInput(): void {\n this._textInputElement.focus();\n }\n\n private _getRenderer<U extends keyof DefaultInputRenderers>(\n name: U\n ): DefaultInputRenderers[U] {\n return this._state.options?.renderers\n ? ((this._state.options.renderers[name] ??\n this._defaults[name]) as DefaultInputRenderers[U])\n : this._defaults[name];\n }\n\n private async _sendMessage(): Promise<void> {\n if (\n !this._userInputState.hasInputValue &&\n !this._userInputState.hasInputAttachments\n ) {\n return;\n }\n\n this._userInputState.addMessageWithEvent({\n text: this._userInputState.inputValue,\n attachments: this._userInputState.inputAttachments,\n });\n\n this.style.height = 'auto';\n\n await this._userInputState.host.updateComplete;\n this.focusInput();\n }\n\n private _handleAttachmentRemoved(attachment: IgcChatMessageAttachment): void {\n const current = this._userInputState.inputAttachments;\n\n if (this._state.emitAttachmentRemoved(attachment)) {\n this._state.inputAttachments = current.toSpliced(\n current.indexOf(attachment),\n 1\n );\n }\n }\n\n private _handleKeydown(event: KeyboardEvent): void {\n const isSendRequest =\n event.key.toLowerCase() === enterKey.toLowerCase() && !event.shiftKey;\n\n if (isSendRequest) {\n event.preventDefault();\n this._sendMessage();\n } else {\n // TODO:\n this._state.handleKeyDown(event);\n }\n }\n\n private _handleFileInputClick(): void {\n this._fileInput.showPicker();\n }\n\n private _handleFocusState(event: FocusEvent): void {\n this._state.emitEvent(\n event.type === 'focus' ? 'igcInputFocus' : 'igcInputBlur'\n );\n }\n\n private _handleDragEnter(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n\n const validFiles = getChatAcceptedFiles(event, this._acceptedTypes);\n this._parts = { 'input-container': true, dragging: !isEmpty(validFiles) };\n this._state.emitEvent('igcAttachmentDrag');\n }\n\n private _handleDragOver(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n }\n\n private _handleDragLeave(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n\n // Check if we're actually leaving the container\n const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n\n if (\n x <= rect.left ||\n x >= rect.right ||\n y <= rect.top ||\n y >= rect.bottom\n ) {\n this._parts = { 'input-container': true, dragging: false };\n }\n }\n\n private _handleDrop(event: DragEvent): void {\n event.preventDefault();\n event.stopPropagation();\n this._parts = { 'input-container': true, dragging: false };\n\n const validFiles = getChatAcceptedFiles(event, this._acceptedTypes);\n this._state.emitEvent('igcAttachmentDrop');\n this._state.attachFilesWithEvent(validFiles);\n this.requestUpdate();\n }\n\n private _handleInput({ detail }: CustomEvent<string>): void {\n this._state.inputValue = detail;\n this._state.emitEvent('igcInputChange', { detail: { value: detail } });\n }\n\n private _handleFileUpload(event: Event): void {\n const input = event.target as HTMLInputElement;\n\n if (hasFiles(input)) {\n this._state.attachFilesWithEvent(Array.from(input.files!));\n }\n }\n /**\n * Default attachments area template used when no custom template is provided.\n * Renders the list of input attachments as chips.\n * @returns TemplateResult containing the attachments area\n */\n private _renderAttachmentsArea(attachments: IgcChatMessageAttachment[]) {\n return html`${attachments?.map(\n (attachment) => html`\n <div part=\"attachment-wrapper\" role=\"listitem\">\n <igc-chip\n removable\n @igcRemove=${() => this._handleAttachmentRemoved(attachment)}\n >\n <igc-icon\n part=\"attachment-icon\"\n slot=\"prefix\"\n name=${getIconName(attachment.file?.type ?? attachment.type)}\n ></igc-icon>\n <span part=\"attachment-name\">${attachment.name}</span>\n </igc-chip>\n </div>\n `\n )} `;\n }\n\n /**\n * Default text area template used when no custom template is provided.\n * Renders a text area for user input.\n * @returns TemplateResult containing the text area\n */\n private _renderTextArea() {\n return html`\n <igc-textarea\n part=\"text-input\"\n aria-label=\"Chat text input\"\n placeholder=${ifDefined(this._state.options?.inputPlaceholder)}\n resize=\"auto\"\n rows=\"1\"\n .value=${this._userInputState?.inputValue}\n @igcInput=${this._handleInput}\n @keydown=${this._handleKeydown}\n @focus=${this._handleFocusState}\n @blur=${this._handleFocusState}\n ></igc-textarea>\n `;\n }\n\n private _renderFileUploadButton() {\n const accepted = this._state.options?.acceptedFiles;\n const attachmentsDisabled = this._state.options?.disableInputAttachments;\n\n return html`${cache(\n attachmentsDisabled\n ? nothing\n : html`\n <label for=\"input_attachments\" part=\"file-upload\">\n <igc-icon-button\n aria-label=\"Attach files\"\n variant=\"flat\"\n name=\"attach_file\"\n @click=${this._handleFileInputClick}\n ></igc-icon-button>\n <input\n type=\"file\"\n id=\"input_attachments\"\n tabindex=\"-1\"\n name=\"input_attachments\"\n aria-label=\"Upload button\"\n multiple\n accept=${bindIf(accepted, accepted)}\n @change=${this._handleFileUpload}\n />\n </label>\n `\n )}`;\n }\n\n private _renderSendButton() {\n const enabled =\n this._state.hasInputValue || this._state.hasInputAttachments;\n\n return html`\n <igc-icon-button\n aria-label=\"Send message\"\n name=\"send_message\"\n variant=\"contained\"\n part=\"send-button\"\n ?disabled=${!enabled}\n @click=${this._sendMessage}\n ></igc-icon-button>\n `;\n }\n\n private _renderActionsArea() {\n const ctx: ChatRenderContext = { instance: this._state.host };\n\n return trimmedHtml`\n <div part=\"file-upload-container\">\n ${this._getRenderer('fileUploadButton')(ctx)}\n </div>\n <div part=\"input-actions-start\">\n ${this._getRenderer('inputActionsStart')(ctx)}\n </div>\n <div part=\"send-button-container\">${this._getRenderer('sendButton')(ctx)}</div>\n <div part=\"input-actions-end\">\n ${this._getRenderer('inputActionsEnd')(ctx)}\n </div>\n `;\n }\n\n protected override render() {\n const ctx: ChatRenderContext = { instance: this._state.host };\n\n const inputCtx: ChatInputRenderContext = {\n ...ctx,\n attachments: this._state.inputAttachments,\n value: this._state.inputValue,\n };\n\n return html`\n <div\n part=${partMap(this._parts)}\n @dragenter=${this._handleDragEnter}\n @dragover=${this._handleDragOver}\n @dragleave=${this._handleDragLeave}\n @drop=${this._handleDrop}\n >\n ${this._state.hasInputAttachments\n ? html`\n <div part=\"attachments\" role=\"list\" aria-label=\"Attachments\">\n ${until(this._getRenderer('inputAttachments')(inputCtx))}\n </div>\n `\n : nothing}\n\n <div part=\"input-wrapper\">\n ${until(this._getRenderer('input')(inputCtx))}\n </div>\n\n <div part=\"actions-container\">\n ${until(this._getRenderer('inputActions')(ctx))}\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'igc-chat-input': IgcChatInputComponent;\n }\n}\n"]}
@@ -1,11 +1,10 @@
1
1
  import { LitElement } from 'lit';
2
- import type { IgcMessage } from './types.js';
2
+ import type { IgcChatMessage } from './types.js';
3
3
  /**
4
4
  * A chat message component for displaying individual messages in `<igc-chat>`.
5
5
  *
6
6
  * @element igc-chat-message
7
7
  *
8
- * @fires igcMessageReact - Fired when a message is reacted to.
9
8
  *
10
9
  * This component renders a single chat message including:
11
10
  * - Message text (sanitized)
@@ -27,10 +26,11 @@ export default class IgcChatMessageComponent extends LitElement {
27
26
  /**
28
27
  * The chat message to render.
29
28
  */
30
- message?: IgcMessage;
29
+ message: IgcChatMessage;
31
30
  constructor();
32
31
  protected firstUpdated(): void;
33
32
  private _getRenderer;
33
+ private _handleCopy;
34
34
  private _handleMessageActionClick;
35
35
  private _renderHeader;
36
36
  private _renderContent;
@@ -14,27 +14,27 @@ import IgcIconButtonComponent from '../button/icon-button.js';
14
14
  import { chatContext } from '../common/context.js';
15
15
  import { registerComponent } from '../common/definitions/register.js';
16
16
  import { partMap } from '../common/part-map.js';
17
- import { isEmpty } from '../common/util.js';
18
- import IgcTooltipComponent from '../tooltip/tooltip.js';
17
+ import { isEmpty, trimmedHtml } from '../common/util.js';
19
18
  import IgcMessageAttachmentsComponent from './message-attachments.js';
20
19
  import { styles } from './themes/message.base.css.js';
21
20
  import { all } from './themes/message.js';
22
21
  import { styles as shared } from './themes/shared/chat-message/chat-message.common.css.js';
23
- import { chatMessageAdoptPageStyles, showChatActionsTooltip } from './utils.js';
22
+ import { chatMessageAdoptPageStyles } from './utils.js';
24
23
  const LIKE_INACTIVE = 'thumb_up_inactive';
25
24
  const LIKE_ACTIVE = 'thumb_up_active';
26
25
  const DISLIKE_INACTIVE = 'thumb_down_inactive';
27
26
  const DISLIKE_ACTIVE = 'thumb_down_active';
27
+ const COPY_CONTENT = 'copy_content';
28
+ const REGENERATE = 'regenerate';
28
29
  export default class IgcChatMessageComponent extends LitElement {
29
30
  static { this.tagName = 'igc-chat-message'; }
30
31
  static { this.styles = [styles, shared]; }
31
32
  static register() {
32
- registerComponent(IgcChatMessageComponent, IgcMessageAttachmentsComponent, IgcIconButtonComponent, IgcTooltipComponent);
33
+ registerComponent(IgcChatMessageComponent, IgcMessageAttachmentsComponent, IgcIconButtonComponent);
33
34
  }
34
35
  constructor() {
35
36
  super();
36
37
  this._defaults = Object.freeze({
37
- message: () => this._renderMessage(),
38
38
  messageHeader: () => this._renderHeader(),
39
39
  messageContent: () => this._renderContent(),
40
40
  messageAttachments: () => this._renderAttachments(),
@@ -43,50 +43,80 @@ export default class IgcChatMessageComponent extends LitElement {
43
43
  addThemingController(this, all);
44
44
  }
45
45
  firstUpdated() {
46
- chatMessageAdoptPageStyles(this);
46
+ if (this._state.options?.adoptRootStyles) {
47
+ chatMessageAdoptPageStyles(this);
48
+ }
47
49
  }
48
50
  _getRenderer(name) {
49
51
  return this._state.options?.renderers
50
52
  ? (this._state.options.renderers[name] ?? this._defaults[name])
51
53
  : this._defaults[name];
52
54
  }
55
+ async _handleCopy() {
56
+ const text = this.message.text;
57
+ const separator = text ? '\n\n' : '';
58
+ const attachments = this.message.attachments ?? [];
59
+ const { attachmentLabel, attachmentsListLabel, messageCopied } = this._state.resourceStrings;
60
+ const attachmentsText = isEmpty(attachments)
61
+ ? ''
62
+ : attachments
63
+ .map(({ name, url }) => `${name ?? attachmentLabel}: ${url ?? ''}`)
64
+ .join('\n');
65
+ const payload = attachmentsText
66
+ ? `${text}${separator}${attachmentsListLabel}:\n${attachmentsText}`
67
+ : text;
68
+ try {
69
+ await navigator.clipboard.writeText(payload);
70
+ this._state.showActionToast(messageCopied);
71
+ }
72
+ catch (err) {
73
+ throw new Error(`Failed to copy message: ${err}`);
74
+ }
75
+ }
53
76
  _handleMessageActionClick(event) {
54
77
  const targetButton = event.target;
55
78
  const button = targetButton.closest(IgcIconButtonComponent.tagName);
56
- if (!button)
79
+ if (!button) {
57
80
  return;
58
- let reaction = button.getAttribute('name');
59
- if (this.message) {
60
- if (reaction === LIKE_INACTIVE) {
61
- reaction = LIKE_ACTIVE;
62
- this.message.reactions = [reaction];
63
- }
64
- else if (reaction === DISLIKE_INACTIVE) {
65
- reaction = DISLIKE_ACTIVE;
66
- this.message.reactions = [reaction];
67
- }
68
- else if (reaction === this.message.reactions?.[0]) {
69
- reaction = null;
70
- this.message.reactions = [];
71
- }
72
- this.requestUpdate();
73
81
  }
74
- this._state.emitEvent('igcMessageReact', {
75
- detail: { message: this.message, reaction },
76
- });
82
+ let reaction = button.name;
83
+ switch (reaction) {
84
+ case LIKE_INACTIVE:
85
+ case LIKE_ACTIVE:
86
+ reaction = this.message.reactions?.includes(LIKE_ACTIVE)
87
+ ? LIKE_INACTIVE
88
+ : LIKE_ACTIVE;
89
+ break;
90
+ case DISLIKE_INACTIVE:
91
+ case DISLIKE_ACTIVE:
92
+ reaction = this.message.reactions?.includes(DISLIKE_ACTIVE)
93
+ ? DISLIKE_INACTIVE
94
+ : DISLIKE_ACTIVE;
95
+ break;
96
+ case COPY_CONTENT:
97
+ reaction = COPY_CONTENT;
98
+ this._handleCopy();
99
+ break;
100
+ case REGENERATE:
101
+ reaction = REGENERATE;
102
+ break;
103
+ default:
104
+ reaction = '';
105
+ }
106
+ this.message.reactions = reaction ? [reaction] : [];
107
+ this._state.emitMessageReaction({ message: this.message, reaction });
108
+ this.requestUpdate();
77
109
  }
78
110
  _renderHeader() {
79
111
  return nothing;
80
112
  }
81
113
  _renderContent() {
82
- return this.message?.text
83
- ? html `<pre part="plain-text">${this.message.text}</pre>`
84
- : nothing;
114
+ return html `${this.message.text}`;
85
115
  }
86
116
  _renderActions() {
87
- const isSent = this.message?.sender === this._state.currentUserId;
88
- const hasText = this.message?.text.trim();
89
- const hasAttachments = this.message?.attachments && !isEmpty(this.message?.attachments);
117
+ const isSent = this.message.sender === this._state.currentUserId;
118
+ const hasText = this.message.text.trim();
119
+ const hasAttachments = !isEmpty(this.message.attachments ?? []);
90
120
  const isTyping = this._state._isTyping;
91
121
  const isLastMessage = this.message === this._state.messages.at(-1);
92
122
  const resourceStrings = this._state.resourceStrings;
@@ -94,16 +124,14 @@ export default class IgcChatMessageComponent extends LitElement {
94
124
  return nothing;
95
125
  }
96
126
  return html `
97
- <div @click=${this._handleMessageActionClick}>
98
- ${this._renderActionButton('copy_content', resourceStrings.reactionCopy)}
99
- ${this._renderActionButton(this.message?.reactions?.includes(LIKE_ACTIVE)
127
+ ${this._renderActionButton(COPY_CONTENT, resourceStrings.reactionCopy)}
128
+ ${this._renderActionButton(this.message.reactions?.includes(LIKE_ACTIVE)
100
129
  ? LIKE_ACTIVE
101
130
  : LIKE_INACTIVE, resourceStrings.reactionLike)}
102
- ${this._renderActionButton(this.message?.reactions?.includes(DISLIKE_ACTIVE)
131
+ ${this._renderActionButton(this.message.reactions?.includes(DISLIKE_ACTIVE)
103
132
  ? DISLIKE_ACTIVE
104
133
  : DISLIKE_INACTIVE, resourceStrings.reactionDislike)}
105
- ${this._renderActionButton('regenerate', resourceStrings.reactionRegenerate)}
106
- </div>
134
+ ${this._renderActionButton(REGENERATE, resourceStrings.reactionRegenerate)}
107
135
  `;
108
136
  }
109
137
  _renderActionButton(name, tooltipMessage) {
@@ -112,29 +140,50 @@ export default class IgcChatMessageComponent extends LitElement {
112
140
  id=${`${name}-button`}
113
141
  name=${name}
114
142
  variant="flat"
115
- @pointerenter=${({ target }) => showChatActionsTooltip(target, tooltipMessage)}
116
- @focus=${({ target }) => showChatActionsTooltip(target, tooltipMessage)}
143
+ @pointerenter=${({ target }) => this._state.showActionsTooltip(target, tooltipMessage)}
144
+ @focus=${({ target }) => this._state.showActionsTooltip(target, tooltipMessage)}
117
145
  ></igc-icon-button>
118
146
  `;
119
147
  }
120
148
  _renderAttachments() {
121
- return isEmpty(this.message?.attachments ?? [])
149
+ return isEmpty(this.message.attachments ?? [])
122
150
  ? nothing
123
151
  : html `
124
152
  <igc-message-attachments
125
153
  .message=${this.message}
154
+ exportparts="
155
+ attachment,
156
+ attachment-header,
157
+ attachment-icon,
158
+ file-name,
159
+ attachment-content"
126
160
  ></igc-message-attachments>
127
161
  `;
128
162
  }
129
163
  _renderMessage() {
130
- return this.message
131
- ? html `${this._renderHeader()}${this._renderContent()}${this._renderAttachments()}${this._renderActions()}`
132
- : nothing;
164
+ const ctx = {
165
+ message: this.message,
166
+ instance: this._state.host,
167
+ };
168
+ return trimmedHtml `
169
+ <div part="message-header">
170
+ ${until(this._getRenderer('messageHeader')(ctx))}
171
+ </div>
172
+ <div part="plain-text">
173
+ ${until(this._getRenderer('messageContent')(ctx))}
174
+ </div>
175
+ <div part="message-attachments">
176
+ ${until(this._getRenderer('messageAttachments')(ctx))}
177
+ </div>
178
+ <div part="message-actions" @click=${this._handleMessageActionClick}>
179
+ ${until(this._getRenderer('messageActions')(ctx))}
180
+ </div>
181
+ `;
133
182
  }
134
183
  render() {
184
+ const messageRenderer = this._state.options?.renderers?.message;
135
185
  const ctx = {
136
186
  message: this.message,
137
- defaults: this._defaults,
138
187
  instance: this._state.host,
139
188
  };
140
189
  const parts = {
@@ -145,14 +194,9 @@ export default class IgcChatMessageComponent extends LitElement {
145
194
  ${cache(this.message
146
195
  ? html `
147
196
  <div part=${partMap(parts)}>
148
- ${cache(this._state.options?.renderers?.message
149
- ? html `${until(this._getRenderer('message')(ctx))}`
150
- : html `
151
- ${until(this._getRenderer('messageHeader')(ctx))}
152
- ${until(this._getRenderer('messageContent')(ctx))}
153
- ${until(this._getRenderer('messageAttachments')(ctx))}
154
- ${until(this._getRenderer('messageActions')(ctx))}
155
- `)}
197
+ ${cache(messageRenderer
198
+ ? until(messageRenderer(ctx))
199
+ : this._renderMessage())}
156
200
  </div>
157
201
  `
158
202
  : nothing)}