@ihoomanai/chat-widget 2.5.6 → 2.5.7
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/dist/index.cjs.js +59 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +59 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.umd.js +59 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/widget.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/types.ts +12 -0
- package/src/widget.ts +70 -0
package/package.json
CHANGED
package/src/types.ts
CHANGED
|
@@ -60,6 +60,18 @@ export interface BrandingConfig {
|
|
|
60
60
|
poweredBy?: boolean;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Preset question for quick access
|
|
65
|
+
*/
|
|
66
|
+
export interface PresetQuestion {
|
|
67
|
+
/** Unique identifier */
|
|
68
|
+
id: string;
|
|
69
|
+
/** Question text displayed to users */
|
|
70
|
+
text: string;
|
|
71
|
+
/** Optional emoji icon */
|
|
72
|
+
icon?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
/**
|
|
64
76
|
* Main widget configuration options
|
|
65
77
|
*/
|
package/src/widget.ts
CHANGED
|
@@ -111,6 +111,7 @@ interface WidgetElements {
|
|
|
111
111
|
historyList?: HTMLElement;
|
|
112
112
|
historyNewBtn?: HTMLButtonElement;
|
|
113
113
|
messages?: HTMLElement;
|
|
114
|
+
presetQuestions?: HTMLElement;
|
|
114
115
|
input?: HTMLTextAreaElement;
|
|
115
116
|
sendBtn?: HTMLButtonElement;
|
|
116
117
|
attachBtn?: HTMLButtonElement | null;
|
|
@@ -367,6 +368,11 @@ function generateStyles(): string {
|
|
|
367
368
|
.ihooman-history-preview { font-size: 13px; color: ${textColor}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
368
369
|
.ihooman-history-meta { font-size: 11px; color: ${mutedColor}; margin-top: 4px; display: flex; justify-content: space-between; }
|
|
369
370
|
.ihooman-history-empty { padding: 40px; text-align: center; color: ${mutedColor}; font-size: 14px; }
|
|
371
|
+
.ihooman-preset-questions { padding: 8px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderColor}; }
|
|
372
|
+
.ihooman-preset-questions:empty { display: none; }
|
|
373
|
+
.ihooman-preset-btn { display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px; border-radius: 16px; border: 1px solid ${borderColor}; background: ${isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.02)'}; color: ${textColor}; font-size: 12px; cursor: pointer; transition: all 0.2s; white-space: nowrap; }
|
|
374
|
+
.ihooman-preset-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}; border-color: ${primaryColor}; }
|
|
375
|
+
.ihooman-preset-btn .icon { font-size: 14px; }
|
|
370
376
|
@media (max-width: 480px) { .ihooman-window { width: calc(100vw - 20px); height: calc(100vh - 100px); left: 10px; right: 10px; bottom: 80px; max-height: none; } .ihooman-toggle { ${positionRight ? 'right: 16px' : 'left: 16px'}; bottom: 16px; } }
|
|
371
377
|
`;
|
|
372
378
|
}
|
|
@@ -415,6 +421,7 @@ function createWidget(): void {
|
|
|
415
421
|
<div class="ihooman-chat-view">
|
|
416
422
|
<div class="ihooman-status-bar"></div>
|
|
417
423
|
<div class="ihooman-messages" role="log" aria-live="polite"></div>
|
|
424
|
+
<div class="ihooman-preset-questions"></div>
|
|
418
425
|
<div class="ihooman-input-area">
|
|
419
426
|
<div class="ihooman-input-wrapper">
|
|
420
427
|
${config.enableFileUpload ? `<button class="ihooman-input-btn attach" title="Attach file">${icons.attach}</button><input type="file" class="ihooman-file-input">` : ''}
|
|
@@ -463,6 +470,7 @@ function createWidget(): void {
|
|
|
463
470
|
historyList: widget.querySelector('.ihooman-history-list') as HTMLElement,
|
|
464
471
|
historyNewBtn: widget.querySelector('.ihooman-history-new') as HTMLButtonElement,
|
|
465
472
|
messages: widget.querySelector('.ihooman-messages') as HTMLElement,
|
|
473
|
+
presetQuestions: widget.querySelector('.ihooman-preset-questions') as HTMLElement,
|
|
466
474
|
input: widget.querySelector('.ihooman-input') as HTMLTextAreaElement,
|
|
467
475
|
sendBtn: widget.querySelector('.ihooman-input-btn.send') as HTMLButtonElement,
|
|
468
476
|
attachBtn: widget.querySelector('.ihooman-input-btn.attach') as HTMLButtonElement | null,
|
|
@@ -479,6 +487,9 @@ function createWidget(): void {
|
|
|
479
487
|
|
|
480
488
|
// Set up event listeners
|
|
481
489
|
setupEventListeners();
|
|
490
|
+
|
|
491
|
+
// Render preset questions
|
|
492
|
+
renderPresetQuestions();
|
|
482
493
|
}
|
|
483
494
|
|
|
484
495
|
/**
|
|
@@ -619,6 +630,54 @@ function addMessage(content: string, sender: 'user' | 'bot' = 'bot', metadata: M
|
|
|
619
630
|
return message;
|
|
620
631
|
}
|
|
621
632
|
|
|
633
|
+
/**
|
|
634
|
+
* Render preset questions in the widget
|
|
635
|
+
*/
|
|
636
|
+
function renderPresetQuestions(): void {
|
|
637
|
+
if (!elements.presetQuestions || presetQuestions.length === 0) {
|
|
638
|
+
if (elements.presetQuestions) {
|
|
639
|
+
elements.presetQuestions.innerHTML = '';
|
|
640
|
+
}
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
elements.presetQuestions.innerHTML = presetQuestions.map(q => `
|
|
645
|
+
<button class="ihooman-preset-btn" data-question-id="${escapeHtml(q.id)}" data-question-text="${escapeHtml(q.text)}">
|
|
646
|
+
${q.icon ? `<span class="icon">${escapeHtml(q.icon)}</span>` : ''}
|
|
647
|
+
<span>${escapeHtml(q.text)}</span>
|
|
648
|
+
</button>
|
|
649
|
+
`).join('');
|
|
650
|
+
|
|
651
|
+
// Add click handlers
|
|
652
|
+
elements.presetQuestions.querySelectorAll('.ihooman-preset-btn').forEach(btn => {
|
|
653
|
+
btn.addEventListener('click', () => {
|
|
654
|
+
const questionText = (btn as HTMLElement).dataset.questionText;
|
|
655
|
+
if (questionText) {
|
|
656
|
+
handlePresetQuestionClick(questionText);
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Handle preset question click - send the question as a message
|
|
664
|
+
*/
|
|
665
|
+
function handlePresetQuestionClick(questionText: string): void {
|
|
666
|
+
// Add the question as a user message
|
|
667
|
+
addMessage(questionText, 'user');
|
|
668
|
+
|
|
669
|
+
// Show typing indicator
|
|
670
|
+
showTyping();
|
|
671
|
+
|
|
672
|
+
// Send to server
|
|
673
|
+
sendMessageToServer(questionText);
|
|
674
|
+
|
|
675
|
+
// Hide preset questions after first use (optional - can be removed if you want them to persist)
|
|
676
|
+
if (elements.presetQuestions) {
|
|
677
|
+
elements.presetQuestions.style.display = 'none';
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
622
681
|
/**
|
|
623
682
|
* Handle escalation action button clicks
|
|
624
683
|
*/
|
|
@@ -1618,6 +1677,11 @@ async function fetchWidgetConfig(widgetId: string, serverUrl: string): Promise<{
|
|
|
1618
1677
|
}
|
|
1619
1678
|
}
|
|
1620
1679
|
|
|
1680
|
+
/**
|
|
1681
|
+
* Preset questions from server config
|
|
1682
|
+
*/
|
|
1683
|
+
let presetQuestions: Array<{ id: string; text: string; icon?: string }> = [];
|
|
1684
|
+
|
|
1621
1685
|
/**
|
|
1622
1686
|
* Apply server configuration to local config
|
|
1623
1687
|
*/
|
|
@@ -1630,6 +1694,7 @@ function applyServerConfig(serverConfig: {
|
|
|
1630
1694
|
position: string;
|
|
1631
1695
|
behavior: Record<string, boolean>;
|
|
1632
1696
|
branding: Record<string, unknown>;
|
|
1697
|
+
presetQuestions?: Array<{ id: string; text: string; icon?: string }>;
|
|
1633
1698
|
}): void {
|
|
1634
1699
|
// Apply basic settings
|
|
1635
1700
|
config.title = serverConfig.title || config.title;
|
|
@@ -1664,6 +1729,11 @@ function applyServerConfig(serverConfig: {
|
|
|
1664
1729
|
config.avatarUrl = (serverConfig.branding.avatarUrl as string) || config.avatarUrl;
|
|
1665
1730
|
config.poweredBy = serverConfig.branding.poweredBy as boolean ?? config.poweredBy;
|
|
1666
1731
|
}
|
|
1732
|
+
|
|
1733
|
+
// Store preset questions
|
|
1734
|
+
if (serverConfig.presetQuestions && Array.isArray(serverConfig.presetQuestions)) {
|
|
1735
|
+
presetQuestions = serverConfig.presetQuestions;
|
|
1736
|
+
}
|
|
1667
1737
|
}
|
|
1668
1738
|
|
|
1669
1739
|
/**
|