@nuraly/lumenui 0.5.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cdn.js +1 -1
- package/dist/nuralyui.bundle.js +106 -97
- package/dist/nuralyui.bundle.js.gz +0 -0
- package/dist/src/components/canvas/bundle.js +149 -140
- package/dist/src/components/canvas/bundle.js.gz +0 -0
- package/dist/src/components/chatbot/bundle.js +120 -111
- package/dist/src/components/chatbot/bundle.js.gz +0 -0
- package/dist/src/components/chatbot/chatbot.component.d.ts +13 -2
- package/dist/src/components/chatbot/chatbot.component.js +81 -10
- package/dist/src/components/chatbot/chatbot.style.js +31 -42
- package/dist/src/components/chatbot/chatbot.types.d.ts +1 -0
- package/dist/src/components/chatbot/templates/artifact-panel.template.js +13 -13
- package/dist/src/components/chatbot/templates/chatbot-main.template.d.ts +4 -0
- package/dist/src/components/chatbot/templates/chatbot-main.template.js +6 -4
- package/dist/src/components/chatbot/templates/file-upload-area.template.js +3 -3
- package/dist/src/components/chatbot/templates/input-box.template.js +21 -14
- package/dist/src/components/chatbot/templates/message.template.d.ts +3 -8
- package/dist/src/components/chatbot/templates/message.template.js +30 -17
- package/dist/src/components/chatbot/templates/thread-sidebar.template.js +12 -11
- package/package.json +1 -1
- package/packages/themes/dist/default.css +12 -0
|
@@ -45,6 +45,7 @@ function renderContextTags(files, onRemove, i18n, onFileClick) {
|
|
|
45
45
|
<div
|
|
46
46
|
slot="trigger"
|
|
47
47
|
class="file-thumb ${f.isUploading ? 'file-thumb--uploading' : ''}"
|
|
48
|
+
part="file-thumb"
|
|
48
49
|
role="button"
|
|
49
50
|
tabindex="0"
|
|
50
51
|
title="${f.name}"
|
|
@@ -53,22 +54,24 @@ function renderContextTags(files, onRemove, i18n, onFileClick) {
|
|
|
53
54
|
${isImage(f.mimeType) && (f.previewUrl || f.url) ? html `
|
|
54
55
|
<img
|
|
55
56
|
class="file-thumb__image"
|
|
57
|
+
part="file-thumb-image"
|
|
56
58
|
src="${f.previewUrl || f.url}"
|
|
57
59
|
alt="${f.name}"
|
|
58
60
|
/>
|
|
59
61
|
` : html `
|
|
60
|
-
<div class="file-thumb__ext" data-ext="${getExtension(f.name, f.mimeType)}">
|
|
61
|
-
<span class="file-thumb__ext-label">${getExtension(f.name, f.mimeType)}</span>
|
|
62
|
+
<div class="file-thumb__ext" part="file-thumb-ext" data-ext="${getExtension(f.name, f.mimeType)}">
|
|
63
|
+
<span class="file-thumb__ext-label" part="file-thumb-ext-label">${getExtension(f.name, f.mimeType)}</span>
|
|
62
64
|
</div>
|
|
63
65
|
`}
|
|
64
66
|
${f.isUploading ? html `
|
|
65
|
-
<div class="file-thumb__spinner" aria-label="${i18n.input.uploadingLabel}">
|
|
67
|
+
<div class="file-thumb__spinner" part="file-thumb-spinner" aria-label="${i18n.input.uploadingLabel}">
|
|
66
68
|
<span class="file-thumb__spinner-ring"></span>
|
|
67
69
|
</div>
|
|
68
70
|
` : ''}
|
|
69
71
|
<button
|
|
70
72
|
type="button"
|
|
71
73
|
class="file-thumb__remove"
|
|
74
|
+
part="file-thumb-remove"
|
|
72
75
|
aria-label="${i18n.input.removeFileLabel}"
|
|
73
76
|
title="${i18n.input.removeFileLabel}"
|
|
74
77
|
@click=${(e) => { e.stopPropagation(); onRemove(f.id); }}
|
|
@@ -199,9 +202,10 @@ function renderRecordingBar(data, handlers) {
|
|
|
199
202
|
<path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/>
|
|
200
203
|
</svg>`;
|
|
201
204
|
return html `
|
|
202
|
-
<div class="audio-recording-bar">
|
|
205
|
+
<div class="audio-recording-bar" part="audio-recording-bar">
|
|
203
206
|
<button
|
|
204
207
|
class="audio-rec-cancel"
|
|
208
|
+
part="audio-cancel-button"
|
|
205
209
|
title="${data.i18n.audio.cancelRecordingLabel}"
|
|
206
210
|
@click=${handlers.onAudioCancel}
|
|
207
211
|
aria-label="${data.i18n.audio.cancelRecordingLabel}"
|
|
@@ -213,22 +217,23 @@ function renderRecordingBar(data, handlers) {
|
|
|
213
217
|
</svg>
|
|
214
218
|
</button>
|
|
215
219
|
|
|
216
|
-
<div class="audio-rec-indicator">
|
|
217
|
-
<span class="audio-rec-dot"></span>
|
|
218
|
-
<div class="audio-rec-wave">
|
|
220
|
+
<div class="audio-rec-indicator" part="audio-indicator">
|
|
221
|
+
<span class="audio-rec-dot" part="audio-dot"></span>
|
|
222
|
+
<div class="audio-rec-wave" part="audio-wave">
|
|
219
223
|
${bars.map(v => html `
|
|
220
|
-
<div class="audio-rec-bar" style=${styleMap({ height: `${Math.round(v * 24)}px` })}></div>
|
|
224
|
+
<div class="audio-rec-bar" part="audio-bar" style=${styleMap({ height: `${Math.round(v * 24)}px` })}></div>
|
|
221
225
|
`)}
|
|
222
226
|
</div>
|
|
223
|
-
<span class="audio-rec-time">${duration}</span>
|
|
227
|
+
<span class="audio-rec-time" part="audio-time">${duration}</span>
|
|
224
228
|
</div>
|
|
225
229
|
|
|
226
|
-
<span class="audio-rec-mode-label">
|
|
230
|
+
<span class="audio-rec-mode-label" part="audio-mode-label">
|
|
227
231
|
${isTranscribe ? data.i18n.audio.speechToTextLabel : data.i18n.audio.voiceMessageLabel}
|
|
228
232
|
</span>
|
|
229
233
|
|
|
230
234
|
<button
|
|
231
235
|
class="audio-rec-send ${isTranscribe ? 'audio-rec-send--transcribe' : ''}"
|
|
236
|
+
part="audio-send-button"
|
|
232
237
|
title="${sendTitle}"
|
|
233
238
|
@click=${handlers.onAudioSend}
|
|
234
239
|
aria-label="${sendTitle}"
|
|
@@ -243,19 +248,20 @@ function renderRecordingBar(data, handlers) {
|
|
|
243
248
|
*/
|
|
244
249
|
function renderActionButtons(data, handlers) {
|
|
245
250
|
return html `
|
|
246
|
-
<div class="action-buttons-row">
|
|
247
|
-
<div class="action-buttons-left">
|
|
251
|
+
<div class="action-buttons-row" part="actions">
|
|
252
|
+
<div class="action-buttons-left" part="actions-left">
|
|
248
253
|
${data.enableFileUpload ? renderFileUploadButton(data, handlers) : nothing}
|
|
249
254
|
${data.enableModuleSelection && data.moduleOptions.length > 0
|
|
250
255
|
? renderModuleSelector(data, handlers)
|
|
251
256
|
: nothing}
|
|
252
257
|
</div>
|
|
253
258
|
|
|
254
|
-
<div class="action-buttons-right">
|
|
259
|
+
<div class="action-buttons-right" part="actions-right">
|
|
255
260
|
${data.showAudioButton && !data.isQueryRunning ? html `
|
|
256
261
|
<!-- Speech-to-text: mic + keyboard indicator -->
|
|
257
262
|
<button
|
|
258
263
|
class="audio-mic-btn"
|
|
264
|
+
part="audio-mic-button audio-mic-transcribe"
|
|
259
265
|
title="${data.i18n.audio.recordSpeechLabel}"
|
|
260
266
|
?disabled=${data.disabled}
|
|
261
267
|
@click=${() => { var _a; return (_a = handlers.onAudioStart) === null || _a === void 0 ? void 0 : _a.call(handlers, 'transcribe'); }}
|
|
@@ -274,6 +280,7 @@ function renderActionButtons(data, handlers) {
|
|
|
274
280
|
<!-- Voice message: mic + waveform indicator -->
|
|
275
281
|
<button
|
|
276
282
|
class="audio-mic-btn"
|
|
283
|
+
part="audio-mic-button audio-mic-voice"
|
|
277
284
|
title="${data.i18n.audio.sendVoiceMessageLabel}"
|
|
278
285
|
?disabled=${data.disabled}
|
|
279
286
|
@click=${() => { var _a; return (_a = handlers.onAudioStart) === null || _a === void 0 ? void 0 : _a.call(handlers, 'message'); }}
|
|
@@ -319,7 +326,7 @@ export function renderInputBox(data, handlers) {
|
|
|
319
326
|
: nothing}
|
|
320
327
|
|
|
321
328
|
<!-- Input area -->
|
|
322
|
-
<div class="input-row">
|
|
329
|
+
<div class="input-row" part="input-row">
|
|
323
330
|
<div
|
|
324
331
|
class="input-box__input"
|
|
325
332
|
part="input"
|
|
@@ -20,12 +20,7 @@ export declare function renderMessage(message: ChatbotMessage, handlers: Message
|
|
|
20
20
|
* Renders bot typing indicator
|
|
21
21
|
*/
|
|
22
22
|
export declare function renderBotTypingIndicator(isTyping: boolean, loadingIndicator: ChatbotLoadingType, loadingText?: string): TemplateResult | typeof nothing;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export declare function renderEmptyState(i18n: ChatbotI18n): TemplateResult;
|
|
27
|
-
/**
|
|
28
|
-
* Renders messages container with all messages
|
|
29
|
-
*/
|
|
30
|
-
export declare function renderMessages(messages: ChatbotMessage[], suggestions: TemplateResult | typeof nothing, typingIndicator: TemplateResult | typeof nothing, messageHandlers: MessageTemplateHandlers, i18n: ChatbotI18n): TemplateResult;
|
|
23
|
+
export declare function renderEmptyState(i18n: ChatbotI18n, welcomeMessage?: string): TemplateResult;
|
|
24
|
+
export declare function renderThreadLoading(i18n: ChatbotI18n): TemplateResult;
|
|
25
|
+
export declare function renderMessages(messages: ChatbotMessage[], suggestions: TemplateResult | typeof nothing, typingIndicator: TemplateResult | typeof nothing, messageHandlers: MessageTemplateHandlers, i18n: ChatbotI18n, welcomeMessage?: string, isPendingThread?: boolean): TemplateResult;
|
|
31
26
|
//# sourceMappingURL=message.template.d.ts.map
|
|
@@ -68,14 +68,15 @@ export function renderMessage(message, handlers, i18n) {
|
|
|
68
68
|
introduction: !!message.introduction,
|
|
69
69
|
[message.sender]: true,
|
|
70
70
|
};
|
|
71
|
+
const role = message.sender;
|
|
71
72
|
return html `
|
|
72
73
|
<div
|
|
73
74
|
class="message ${classMap(messageClasses)}"
|
|
74
|
-
part
|
|
75
|
+
part=${`message message-${role}`}
|
|
75
76
|
data-sender="${message.sender}"
|
|
76
77
|
data-id="${message.id}"
|
|
77
78
|
>
|
|
78
|
-
<div class="message__content" part
|
|
79
|
+
<div class="message__content" part=${`message-content message-content-${role}`}>
|
|
79
80
|
${isError
|
|
80
81
|
? renderErrorMessage((_c = (_b = message.text) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : '')
|
|
81
82
|
: ((_d = message === null || message === void 0 ? void 0 : message.metadata) === null || _d === void 0 ? void 0 : _d.renderAsHtml)
|
|
@@ -144,6 +145,7 @@ export function renderMessage(message, handlers, i18n) {
|
|
|
144
145
|
size="small"
|
|
145
146
|
color="#9ca3af"
|
|
146
147
|
class="message__copy"
|
|
148
|
+
part="message-copy"
|
|
147
149
|
@click=${() => handlers.onCopy(message)}
|
|
148
150
|
@keydown=${(e) => handlers.onCopyKeydown(e, message)}
|
|
149
151
|
title="${i18n.messages.copyMessageLabel}"
|
|
@@ -177,43 +179,54 @@ export function renderBotTypingIndicator(isTyping, loadingIndicator, loadingText
|
|
|
177
179
|
return nothing;
|
|
178
180
|
const indicatorContent = loadingIndicator === ChatbotLoadingType.Dots
|
|
179
181
|
? html `
|
|
180
|
-
<div class="dots">
|
|
182
|
+
<div class="dots" part="typing-dots">
|
|
181
183
|
<span></span>
|
|
182
184
|
<span></span>
|
|
183
185
|
<span></span>
|
|
184
186
|
</div>
|
|
185
187
|
`
|
|
186
|
-
: html `<div class="spinner"></div>`;
|
|
188
|
+
: html `<div class="spinner" part="typing-spinner"></div>`;
|
|
187
189
|
return html `
|
|
188
190
|
<div class="message bot loading" part="typing-indicator">
|
|
189
|
-
<div class="message__content">
|
|
191
|
+
<div class="message__content" part="typing-content">
|
|
190
192
|
${indicatorContent}
|
|
191
|
-
${loadingText ? html `<span class="loading-text">${loadingText.split('').map((char, i) => html `<span class="loading-text__char" style="animation-delay:${i * 0.04}s">${char === ' ' ? '\u00A0' : char}</span>`)}</span>` : nothing}
|
|
193
|
+
${loadingText ? html `<span class="loading-text" part="typing-text">${loadingText.split('').map((char, i) => html `<span class="loading-text__char" style="animation-delay:${i * 0.04}s">${char === ' ' ? '\u00A0' : char}</span>`)}</span>` : nothing}
|
|
192
194
|
</div>
|
|
193
195
|
</div>
|
|
194
196
|
`;
|
|
195
197
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
*/
|
|
199
|
-
export function renderEmptyState(i18n) {
|
|
198
|
+
export function renderEmptyState(i18n, welcomeMessage) {
|
|
199
|
+
const heading = welcomeMessage !== null && welcomeMessage !== void 0 ? welcomeMessage : i18n.messages.startConversationLabel;
|
|
200
200
|
return html `
|
|
201
201
|
<div class="empty-state" part="empty-state">
|
|
202
202
|
<slot name="empty-state">
|
|
203
|
-
<div class="empty-state__content">
|
|
204
|
-
${
|
|
203
|
+
<div class="empty-state__content" part="empty-state-content">
|
|
204
|
+
${heading}
|
|
205
205
|
</div>
|
|
206
206
|
</slot>
|
|
207
207
|
</div>
|
|
208
208
|
`;
|
|
209
209
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
export function renderThreadLoading(i18n) {
|
|
211
|
+
return html `
|
|
212
|
+
<div class="empty-state empty-state--loading" part="empty-state thread-loading">
|
|
213
|
+
<slot name="thread-loading">
|
|
214
|
+
<div class="spinner" part="thread-loading-spinner"></div>
|
|
215
|
+
<div class="empty-state__content" part="empty-state-content">
|
|
216
|
+
${i18n.messages.loadingConversationLabel}
|
|
217
|
+
</div>
|
|
218
|
+
</slot>
|
|
219
|
+
</div>
|
|
220
|
+
`;
|
|
221
|
+
}
|
|
222
|
+
export function renderMessages(messages, suggestions, typingIndicator, messageHandlers, i18n, welcomeMessage, isPendingThread) {
|
|
214
223
|
return html `
|
|
215
224
|
<div class="messages" part="messages">
|
|
216
|
-
${messages.length === 0
|
|
225
|
+
${messages.length === 0
|
|
226
|
+
? isPendingThread
|
|
227
|
+
? renderThreadLoading(i18n)
|
|
228
|
+
: renderEmptyState(i18n, welcomeMessage)
|
|
229
|
+
: nothing}
|
|
217
230
|
${messages.map((message) => renderMessage(message, messageHandlers, i18n))}
|
|
218
231
|
${suggestions}
|
|
219
232
|
${typingIndicator}
|
|
@@ -26,6 +26,7 @@ function renderThreadItem(thread, data, handlers) {
|
|
|
26
26
|
${data.editingThreadId === thread.id && handlers.onRenameThread ? html `
|
|
27
27
|
<input
|
|
28
28
|
class="thread-item__rename-input"
|
|
29
|
+
part="thread-rename-input"
|
|
29
30
|
type="text"
|
|
30
31
|
.value=${thread.title || ''}
|
|
31
32
|
@click=${(e) => e.stopPropagation()}
|
|
@@ -52,9 +53,9 @@ function renderThreadItem(thread, data, handlers) {
|
|
|
52
53
|
}}
|
|
53
54
|
/>
|
|
54
55
|
` : html `
|
|
55
|
-
<div class="thread-item__title">${thread.title || data.i18n.threads.newChatTitle}</div>
|
|
56
|
+
<div class="thread-item__title" part="thread-title">${thread.title || data.i18n.threads.newChatTitle}</div>
|
|
56
57
|
`}
|
|
57
|
-
<div class="thread-item__actions">
|
|
58
|
+
<div class="thread-item__actions" part="thread-actions">
|
|
58
59
|
${handlers.onBookmarkThread && thread.bookmarked ? html `
|
|
59
60
|
<button
|
|
60
61
|
class="thread-item__action-btn thread-item__bookmark--active"
|
|
@@ -111,10 +112,10 @@ function renderThreadItem(thread, data, handlers) {
|
|
|
111
112
|
` : ''}
|
|
112
113
|
</div>
|
|
113
114
|
</div>
|
|
114
|
-
<div class="thread-item__preview">
|
|
115
|
+
<div class="thread-item__preview" part="thread-preview">
|
|
115
116
|
${previewText}
|
|
116
117
|
</div>
|
|
117
|
-
<div class="thread-item__timestamp">${formatTimestamp(thread.updatedAt)}</div>
|
|
118
|
+
<div class="thread-item__timestamp" part="thread-timestamp">${formatTimestamp(thread.updatedAt)}</div>
|
|
118
119
|
</div>
|
|
119
120
|
`;
|
|
120
121
|
}
|
|
@@ -126,14 +127,14 @@ export function renderThreadSidebar(data, handlers) {
|
|
|
126
127
|
const regularThreads = data.threads.filter(t => !t.bookmarked);
|
|
127
128
|
return html `
|
|
128
129
|
<div class="thread-sidebar" part="thread-sidebar">
|
|
129
|
-
<div class="thread-sidebar__header">
|
|
130
|
-
<h3>${data.i18n.threads.conversationsTitle}</h3>
|
|
130
|
+
<div class="thread-sidebar__header" part="thread-sidebar-header">
|
|
131
|
+
<h3 part="thread-sidebar-title">${data.i18n.threads.conversationsTitle}</h3>
|
|
131
132
|
</div>
|
|
132
133
|
|
|
133
|
-
<div class="thread-list">
|
|
134
|
+
<div class="thread-list" part="thread-list">
|
|
134
135
|
${bookmarkedThreads.length > 0 ? html `
|
|
135
|
-
<div class="thread-section" part="thread-section-bookmarks">
|
|
136
|
-
<div class="thread-section__label">
|
|
136
|
+
<div class="thread-section" part="thread-section thread-section-bookmarks">
|
|
137
|
+
<div class="thread-section__label" part="thread-section-label">
|
|
137
138
|
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>
|
|
138
139
|
${data.i18n.threads.bookmarksLabel}
|
|
139
140
|
</div>
|
|
@@ -142,11 +143,11 @@ export function renderThreadSidebar(data, handlers) {
|
|
|
142
143
|
` : nothing}
|
|
143
144
|
${regularThreads.length > 0 || bookmarkedThreads.length === 0 ? html `
|
|
144
145
|
${bookmarkedThreads.length > 0 ? html `
|
|
145
|
-
<div class="thread-section__label">${data.i18n.threads.allConversationsLabel}</div>
|
|
146
|
+
<div class="thread-section__label" part="thread-section-label">${data.i18n.threads.allConversationsLabel}</div>
|
|
146
147
|
` : nothing}
|
|
147
148
|
${repeat(regularThreads, t => t.id, t => renderThreadItem(t, data, handlers))}
|
|
148
149
|
${regularThreads.length === 0 && bookmarkedThreads.length === 0 ? html `
|
|
149
|
-
<p class="empty-msg">${data.i18n.threads.noConversationsLabel}</p>
|
|
150
|
+
<p class="empty-msg" part="thread-empty">${data.i18n.threads.noConversationsLabel}</p>
|
|
150
151
|
` : nothing}
|
|
151
152
|
` : nothing}
|
|
152
153
|
</div>
|
package/package.json
CHANGED
|
@@ -64,6 +64,11 @@
|
|
|
64
64
|
--nuraly-color-info-light: #e6f7ff;
|
|
65
65
|
--nuraly-color-info-dark: #0050b3;
|
|
66
66
|
|
|
67
|
+
--nuraly-color-user-bubble-bg: rgb(124, 58, 237);
|
|
68
|
+
--nuraly-color-user-bubble-fg: rgb(255, 255, 255);
|
|
69
|
+
--nuraly-color-bot-bubble-bg: transparent;
|
|
70
|
+
--nuraly-color-bot-bubble-fg: inherit;
|
|
71
|
+
|
|
67
72
|
--nuraly-color-background: #ffffff;
|
|
68
73
|
--nuraly-color-background-hover: #fafafa;
|
|
69
74
|
--nuraly-color-background-active: #f5f5f5;
|
|
@@ -85,6 +90,7 @@
|
|
|
85
90
|
--nuraly-color-border-danger: #ff4d4f;
|
|
86
91
|
--nuraly-color-border-success: #52c41a;
|
|
87
92
|
--nuraly-color-border-warning: #faad14;
|
|
93
|
+
--nuraly-color-divider: rgb(224, 224, 224);
|
|
88
94
|
|
|
89
95
|
--nuraly-border-radius-none: 0;
|
|
90
96
|
--nuraly-border-radius-xs: 2px;
|
|
@@ -201,6 +207,11 @@
|
|
|
201
207
|
--nuraly-color-info-light: #93c5fd;
|
|
202
208
|
--nuraly-color-info-dark: #1e40af;
|
|
203
209
|
|
|
210
|
+
--nuraly-color-user-bubble-bg: rgb(124, 58, 237);
|
|
211
|
+
--nuraly-color-user-bubble-fg: rgb(255, 255, 255);
|
|
212
|
+
--nuraly-color-bot-bubble-bg: transparent;
|
|
213
|
+
--nuraly-color-bot-bubble-fg: inherit;
|
|
214
|
+
|
|
204
215
|
--nuraly-color-background: #111827;
|
|
205
216
|
--nuraly-color-background-hover: #1f2937;
|
|
206
217
|
--nuraly-color-background-active: #374151;
|
|
@@ -222,6 +233,7 @@
|
|
|
222
233
|
--nuraly-color-border-danger: #f87171;
|
|
223
234
|
--nuraly-color-border-success: #34d399;
|
|
224
235
|
--nuraly-color-border-warning: #fbbf24;
|
|
236
|
+
--nuraly-color-divider: #374151;
|
|
225
237
|
|
|
226
238
|
--nuraly-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
227
239
|
--nuraly-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
|