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.
- package/CHANGELOG.md +19 -0
- package/components/chat/chat-input.d.ts +5 -17
- package/components/chat/chat-input.js +49 -27
- package/components/chat/chat-input.js.map +1 -1
- package/components/chat/chat-message.d.ts +3 -3
- package/components/chat/chat-message.js +96 -52
- package/components/chat/chat-message.js.map +1 -1
- package/components/chat/chat-state.d.ts +43 -45
- package/components/chat/chat-state.js +67 -74
- package/components/chat/chat-state.js.map +1 -1
- package/components/chat/chat.d.ts +66 -20
- package/components/chat/chat.js +82 -91
- package/components/chat/chat.js.map +1 -1
- package/components/chat/extras/markdown-renderer.d.ts +2 -2
- package/components/chat/extras/markdown-renderer.js +6 -1
- package/components/chat/extras/markdown-renderer.js.map +1 -1
- package/components/chat/message-attachments.d.ts +2 -2
- package/components/chat/message-attachments.js +17 -14
- package/components/chat/message-attachments.js.map +1 -1
- package/components/chat/themes/chat.base.css.js +1 -1
- package/components/chat/themes/chat.base.css.js.map +1 -1
- package/components/chat/themes/dark/chat.bootstrap.css.js +1 -1
- package/components/chat/themes/dark/chat.bootstrap.css.js.map +1 -1
- package/components/chat/themes/dark/chat.fluent.css.js +1 -1
- package/components/chat/themes/dark/chat.fluent.css.js.map +1 -1
- package/components/chat/themes/dark/chat.indigo.css.js +1 -1
- package/components/chat/themes/dark/chat.indigo.css.js.map +1 -1
- package/components/chat/themes/dark/chat.material.css.js +1 -1
- package/components/chat/themes/dark/chat.material.css.js.map +1 -1
- package/components/chat/themes/input.base.css.js +1 -1
- package/components/chat/themes/input.base.css.js.map +1 -1
- package/components/chat/themes/light/chat.bootstrap.css.js +1 -1
- package/components/chat/themes/light/chat.bootstrap.css.js.map +1 -1
- package/components/chat/themes/light/chat.indigo.css.js +1 -1
- package/components/chat/themes/light/chat.indigo.css.js.map +1 -1
- package/components/chat/themes/light/chat.shared.css.js +1 -1
- package/components/chat/themes/light/chat.shared.css.js.map +1 -1
- package/components/chat/themes/message-attachments.base.css.js +1 -1
- package/components/chat/themes/message-attachments.base.css.js.map +1 -1
- package/components/chat/themes/message.base.css.js +1 -1
- package/components/chat/themes/message.base.css.js.map +1 -1
- package/components/chat/themes/shared/chat.bootstrap.css.js +1 -1
- package/components/chat/themes/shared/chat.bootstrap.css.js.map +1 -1
- package/components/chat/themes/shared/chat.fluent.css.js +1 -1
- package/components/chat/themes/shared/chat.fluent.css.js.map +1 -1
- package/components/chat/themes/shared/chat.indigo.css.js +1 -1
- package/components/chat/themes/shared/chat.indigo.css.js.map +1 -1
- package/components/chat/themes/shared/message-attachments/message-attachments.common.css.js +1 -1
- package/components/chat/themes/shared/message-attachments/message-attachments.common.css.js.map +1 -1
- package/components/chat/types.d.ts +164 -30
- package/components/chat/types.js.map +1 -1
- package/components/chat/utils.d.ts +3 -4
- package/components/chat/utils.js +0 -12
- package/components/chat/utils.js.map +1 -1
- package/components/checkbox/themes/checkbox.base.css.js +1 -1
- package/components/checkbox/themes/checkbox.base.css.js.map +1 -1
- package/components/checkbox/themes/switch.base.css.js +1 -1
- package/components/checkbox/themes/switch.base.css.js.map +1 -1
- package/components/common/i18n/chat.resources.d.ts +3 -0
- package/components/common/i18n/chat.resources.js +3 -0
- package/components/common/i18n/chat.resources.js.map +1 -1
- package/components/common/util.d.ts +3 -0
- package/components/common/util.js +9 -1
- package/components/common/util.js.map +1 -1
- package/components/input/themes/shared/input.bootstrap.css.js +1 -1
- package/components/input/themes/shared/input.bootstrap.css.js.map +1 -1
- package/components/input/themes/shared/input.indigo.css.js +1 -1
- package/components/input/themes/shared/input.indigo.css.js.map +1 -1
- package/components/list/themes/header.js +2 -28
- package/components/list/themes/header.js.map +1 -1
- package/components/list/themes/item.js +6 -20
- package/components/list/themes/item.js.map +1 -1
- package/components/textarea/themes/shared/textarea.bootstrap.css.js +1 -1
- package/components/textarea/themes/shared/textarea.bootstrap.css.js.map +1 -1
- package/components/tile-manager/themes/tile-manager.base.css.js +1 -1
- package/components/tile-manager/themes/tile-manager.base.css.js.map +1 -1
- package/custom-elements.json +2110 -2045
- package/igniteui-webcomponents.css-data.json +1 -1
- package/igniteui-webcomponents.html-data.json +1 -1
- package/package.json +24 -2
- package/web-types.json +2 -2
- package/components/list/themes/dark/header/list-header.bootstrap.css.d.ts +0 -1
- package/components/list/themes/dark/header/list-header.bootstrap.css.js +0 -3
- package/components/list/themes/dark/header/list-header.bootstrap.css.js.map +0 -1
- package/components/list/themes/dark/header/list-header.fluent.css.d.ts +0 -1
- package/components/list/themes/dark/header/list-header.fluent.css.js +0 -3
- package/components/list/themes/dark/header/list-header.fluent.css.js.map +0 -1
- package/components/list/themes/dark/header/list-header.indigo.css.d.ts +0 -1
- package/components/list/themes/dark/header/list-header.indigo.css.js +0 -3
- package/components/list/themes/dark/header/list-header.indigo.css.js.map +0 -1
- package/components/list/themes/dark/header/list-header.material.css.d.ts +0 -1
- package/components/list/themes/dark/header/list-header.material.css.js +0 -3
- package/components/list/themes/dark/header/list-header.material.css.js.map +0 -1
- package/components/list/themes/dark/item/list-item.bootstrap.css.d.ts +0 -1
- package/components/list/themes/dark/item/list-item.bootstrap.css.js +0 -3
- package/components/list/themes/dark/item/list-item.bootstrap.css.js.map +0 -1
- package/components/list/themes/dark/item/list-item.fluent.css.d.ts +0 -1
- package/components/list/themes/dark/item/list-item.fluent.css.js +0 -3
- package/components/list/themes/dark/item/list-item.fluent.css.js.map +0 -1
- package/components/list/themes/dark/item/list-item.indigo.css.d.ts +0 -1
- package/components/list/themes/dark/item/list-item.indigo.css.js +0 -3
- package/components/list/themes/dark/item/list-item.indigo.css.js.map +0 -1
- package/components/list/themes/dark/item/list-item.material.css.d.ts +0 -1
- package/components/list/themes/dark/item/list-item.material.css.js +0 -3
- package/components/list/themes/dark/item/list-item.material.css.js.map +0 -1
- package/components/list/themes/light/header/list-header.bootstrap.css.d.ts +0 -1
- package/components/list/themes/light/header/list-header.bootstrap.css.js +0 -3
- package/components/list/themes/light/header/list-header.bootstrap.css.js.map +0 -1
- package/components/list/themes/light/header/list-header.fluent.css.d.ts +0 -1
- package/components/list/themes/light/header/list-header.fluent.css.js +0 -3
- package/components/list/themes/light/header/list-header.fluent.css.js.map +0 -1
- package/components/list/themes/light/header/list-header.indigo.css.d.ts +0 -1
- package/components/list/themes/light/header/list-header.indigo.css.js +0 -3
- package/components/list/themes/light/header/list-header.indigo.css.js.map +0 -1
- package/components/list/themes/light/header/list-header.material.css.d.ts +0 -1
- package/components/list/themes/light/header/list-header.material.css.js +0 -3
- package/components/list/themes/light/header/list-header.material.css.js.map +0 -1
- package/components/list/themes/light/item/list-item.bootstrap.css.d.ts +0 -1
- package/components/list/themes/light/item/list-item.bootstrap.css.js +0 -3
- package/components/list/themes/light/item/list-item.bootstrap.css.js.map +0 -1
- package/components/list/themes/light/item/list-item.fluent.css.d.ts +0 -1
- package/components/list/themes/light/item/list-item.fluent.css.js +0 -3
- package/components/list/themes/light/item/list-item.fluent.css.js.map +0 -1
- package/components/list/themes/light/item/list-item.indigo.css.d.ts +0 -1
- package/components/list/themes/light/item/list-item.indigo.css.js +0 -3
- package/components/list/themes/light/item/list-item.indigo.css.js.map +0 -1
- package/components/list/themes/light/item/list-item.material.css.d.ts +0 -1
- package/components/list/themes/light/item/list-item.material.css.js +0 -3
- 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
|
|
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
|
-
|
|
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
|
-
|
|
49
|
-
this.
|
|
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
|
|
60
|
-
if (
|
|
79
|
+
const isSendRequest = event.key.toLowerCase() === enterKey.toLowerCase() && !event.shiftKey;
|
|
80
|
+
if (isSendRequest) {
|
|
61
81
|
event.preventDefault();
|
|
62
|
-
this.
|
|
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.
|
|
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.
|
|
134
|
+
this._state.attachFilesWithEvent(Array.from(input.files));
|
|
117
135
|
}
|
|
118
136
|
}
|
|
119
137
|
_renderAttachmentsArea(attachments) {
|
|
120
|
-
return html `${attachments?.map((attachment
|
|
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.
|
|
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
|
|
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.
|
|
205
|
+
@click=${this._sendMessage}
|
|
186
206
|
></igc-icon-button>
|
|
187
207
|
`;
|
|
188
208
|
}
|
|
189
209
|
_renderActionsArea() {
|
|
190
|
-
const ctx = {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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="
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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
|
|
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
|
|
88
|
-
const hasText = this.message
|
|
89
|
-
const hasAttachments =
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
|
|
131
|
+
${this._renderActionButton(this.message.reactions?.includes(DISLIKE_ACTIVE)
|
|
103
132
|
? DISLIKE_ACTIVE
|
|
104
133
|
: DISLIKE_INACTIVE, resourceStrings.reactionDislike)}
|
|
105
|
-
|
|
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 }) =>
|
|
116
|
-
@focus=${({ target }) =>
|
|
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
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
:
|
|
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(
|
|
149
|
-
?
|
|
150
|
-
:
|
|
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)}
|