@sippet-ai/operator-widget 0.0.12
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/LICENSE +2 -0
- package/README.md +136 -0
- package/cdn/loader.js +146 -0
- package/custom-elements.json +2241 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/voip-widget/index.d.ts +18 -0
- package/dist/components/voip-widget/index.js +4 -0
- package/dist/components/voip-widget/voip-widget-contacts-tab.d.ts +14 -0
- package/dist/components/voip-widget/voip-widget-contacts-tab.js +45 -0
- package/dist/components/voip-widget/voip-widget-history-tab.d.ts +13 -0
- package/dist/components/voip-widget/voip-widget-history-tab.js +43 -0
- package/dist/components/voip-widget/voip-widget-launcher.d.ts +18 -0
- package/dist/components/voip-widget/voip-widget-launcher.js +100 -0
- package/dist/components/voip-widget/voip-widget-panel.d.ts +21 -0
- package/dist/components/voip-widget/voip-widget-panel.js +193 -0
- package/dist/components/voip-widget/voip-widget-phone-tab.d.ts +21 -0
- package/dist/components/voip-widget/voip-widget-phone-tab.js +187 -0
- package/dist/components/voip-widget/voip-widget-queue-tab.d.ts +14 -0
- package/dist/components/voip-widget/voip-widget-queue-tab.js +49 -0
- package/dist/components/voip-widget/voip-widget-settings-tab.d.ts +21 -0
- package/dist/components/voip-widget/voip-widget-settings-tab.js +135 -0
- package/dist/components/voip-widget/voip-widget.d.ts +142 -0
- package/dist/components/voip-widget/voip-widget.js +1329 -0
- package/dist/components/voip-widget/voip-widget.types.d.ts +22 -0
- package/dist/components/voip-widget/voip-widget.types.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/lib/realtime.d.ts +1 -0
- package/dist/lib/realtime.js +1 -0
- package/dist/lib/sippet.d.ts +40 -0
- package/dist/lib/sippet.js +197 -0
- package/dist/lib/tailwindMixin.d.ts +6 -0
- package/dist/lib/tailwindMixin.js +24 -0
- package/dist/styles/tailwind.global.css +2 -0
- package/dist/styles/tailwind.global.css.js +1 -0
- package/package.json +126 -0
- package/react/SippetAIVoipWidget.d.ts +158 -0
- package/react/SippetAIVoipWidget.js +72 -0
- package/react/SippetAIVoipWidgetContactsTab.d.ts +67 -0
- package/react/SippetAIVoipWidgetContactsTab.js +29 -0
- package/react/SippetAIVoipWidgetHistoryTab.d.ts +55 -0
- package/react/SippetAIVoipWidgetHistoryTab.js +26 -0
- package/react/SippetAIVoipWidgetLauncher.d.ts +83 -0
- package/react/SippetAIVoipWidgetLauncher.js +41 -0
- package/react/SippetAIVoipWidgetPanel.d.ts +87 -0
- package/react/SippetAIVoipWidgetPanel.js +43 -0
- package/react/SippetAIVoipWidgetPhoneTab.d.ts +87 -0
- package/react/SippetAIVoipWidgetPhoneTab.js +43 -0
- package/react/SippetAIVoipWidgetQueueTab.d.ts +67 -0
- package/react/SippetAIVoipWidgetQueueTab.js +27 -0
- package/react/SippetAIVoipWidgetSettingsTab.d.ts +91 -0
- package/react/SippetAIVoipWidgetSettingsTab.js +47 -0
- package/react/index.d.ts +8 -0
- package/react/index.js +8 -0
- package/react/react-utils.js +67 -0
- package/types/custom-element-jsx.d.ts +956 -0
- package/types/custom-element-svelte.d.ts +264 -0
- package/types/custom-element-vuejs.d.ts +234 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { createIcons, Mic, MicOff, PhoneCall, PhoneOff, Repeat, Pause } from 'lucide';
|
|
10
|
+
import { TW } from '../../lib/tailwindMixin.js';
|
|
11
|
+
const TwLitElement = TW(LitElement);
|
|
12
|
+
export class SippetAIVoipWidgetPhoneTab extends TwLitElement {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.dialNumber = '';
|
|
16
|
+
this.sipStatus = 'idle';
|
|
17
|
+
this.callState = 'idle';
|
|
18
|
+
this.callSeconds = 0;
|
|
19
|
+
this.isMuted = false;
|
|
20
|
+
this.isHeld = false;
|
|
21
|
+
}
|
|
22
|
+
updated() {
|
|
23
|
+
createIcons({ icons: { PhoneCall, PhoneOff, Mic, MicOff, Repeat, Pause }, root: this.renderRoot });
|
|
24
|
+
}
|
|
25
|
+
emit(name, detail) {
|
|
26
|
+
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
27
|
+
}
|
|
28
|
+
playDtmfTone(digit) {
|
|
29
|
+
const frequencies = {
|
|
30
|
+
'1': [697, 1209],
|
|
31
|
+
'2': [697, 1336],
|
|
32
|
+
'3': [697, 1477],
|
|
33
|
+
'4': [770, 1209],
|
|
34
|
+
'5': [770, 1336],
|
|
35
|
+
'6': [770, 1477],
|
|
36
|
+
'7': [852, 1209],
|
|
37
|
+
'8': [852, 1336],
|
|
38
|
+
'9': [852, 1477],
|
|
39
|
+
'*': [941, 1209],
|
|
40
|
+
'0': [941, 1336],
|
|
41
|
+
'#': [941, 1477],
|
|
42
|
+
};
|
|
43
|
+
const tone = frequencies[digit];
|
|
44
|
+
if (!tone)
|
|
45
|
+
return;
|
|
46
|
+
const AudioContextCtor = window.AudioContext || window.webkitAudioContext;
|
|
47
|
+
if (!AudioContextCtor)
|
|
48
|
+
return;
|
|
49
|
+
const context = new AudioContextCtor();
|
|
50
|
+
const gain = context.createGain();
|
|
51
|
+
gain.gain.value = 0.08;
|
|
52
|
+
const osc1 = context.createOscillator();
|
|
53
|
+
const osc2 = context.createOscillator();
|
|
54
|
+
osc1.frequency.value = tone[0];
|
|
55
|
+
osc2.frequency.value = tone[1];
|
|
56
|
+
osc1.type = 'sine';
|
|
57
|
+
osc2.type = 'sine';
|
|
58
|
+
osc1.connect(gain);
|
|
59
|
+
osc2.connect(gain);
|
|
60
|
+
gain.connect(context.destination);
|
|
61
|
+
osc1.start();
|
|
62
|
+
osc2.start();
|
|
63
|
+
window.setTimeout(() => {
|
|
64
|
+
osc1.stop();
|
|
65
|
+
osc2.stop();
|
|
66
|
+
gain.disconnect();
|
|
67
|
+
context.close();
|
|
68
|
+
}, 140);
|
|
69
|
+
}
|
|
70
|
+
render() {
|
|
71
|
+
const isActive = this.callState === 'active' || this.callState === 'held';
|
|
72
|
+
const isOutgoing = this.callState === 'outgoing';
|
|
73
|
+
const minutes = Math.floor(this.callSeconds / 60)
|
|
74
|
+
.toString()
|
|
75
|
+
.padStart(2, '0');
|
|
76
|
+
const seconds = Math.floor(this.callSeconds % 60)
|
|
77
|
+
.toString()
|
|
78
|
+
.padStart(2, '0');
|
|
79
|
+
return html `
|
|
80
|
+
${isActive
|
|
81
|
+
? html `
|
|
82
|
+
<div class="mt-4 rounded-2xl border border-slate-200 bg-white p-3">
|
|
83
|
+
<div class="text-xs font-semibold uppercase tracking-wide text-slate-900">
|
|
84
|
+
Active call
|
|
85
|
+
</div>
|
|
86
|
+
<div class="text-lg font-semibold text-slate-900">${minutes}:${seconds}</div>
|
|
87
|
+
<div class="mt-3 grid grid-cols-2 gap-2">
|
|
88
|
+
<button
|
|
89
|
+
class="inline-flex items-center justify-center gap-2 rounded-xl voip-primary py-2 text-xs font-semibold transition-shadow"
|
|
90
|
+
@click=${() => this.emit('voip-hold')}
|
|
91
|
+
>
|
|
92
|
+
<i data-lucide="pause" class="h-4 w-4"></i>
|
|
93
|
+
${this.isHeld ? 'Resume' : 'Hold'}
|
|
94
|
+
</button>
|
|
95
|
+
<button
|
|
96
|
+
class="inline-flex items-center justify-center gap-2 rounded-xl voip-primary py-2 text-xs font-semibold transition-shadow"
|
|
97
|
+
@click=${() => this.emit('voip-mute')}
|
|
98
|
+
>
|
|
99
|
+
<i data-lucide=${this.isMuted ? 'mic-off' : 'mic'} class="h-4 w-4"></i>
|
|
100
|
+
${this.isMuted ? 'Unmute' : 'Mute'}
|
|
101
|
+
</button>
|
|
102
|
+
<button
|
|
103
|
+
class="inline-flex items-center justify-center gap-2 rounded-xl bg-slate-200 py-2 text-xs font-semibold text-slate-900"
|
|
104
|
+
@click=${() => this.emit('voip-transfer')}
|
|
105
|
+
>
|
|
106
|
+
<i data-lucide="repeat" class="h-4 w-4"></i>
|
|
107
|
+
Transfer
|
|
108
|
+
</button>
|
|
109
|
+
<button
|
|
110
|
+
class="inline-flex items-center justify-center gap-2 rounded-xl bg-red-700 py-2 text-xs font-semibold text-white"
|
|
111
|
+
@click=${() => this.emit('voip-hangup')}
|
|
112
|
+
>
|
|
113
|
+
<i data-lucide="phone-off" class="h-4 w-4"></i>
|
|
114
|
+
Hang up
|
|
115
|
+
</button>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
`
|
|
119
|
+
: html `
|
|
120
|
+
<input
|
|
121
|
+
class="mt-1 w-full rounded-2xl border border-slate-200 bg-white px-3 py-2 text-center text-sm text-slate-900"
|
|
122
|
+
type="text"
|
|
123
|
+
placeholder="Enter number"
|
|
124
|
+
.value=${this.dialNumber}
|
|
125
|
+
@input=${(event) => this.emit('voip-dial-change', {
|
|
126
|
+
value: event.target.value,
|
|
127
|
+
})}
|
|
128
|
+
/>
|
|
129
|
+
|
|
130
|
+
<div class="mt-3 grid grid-cols-3 gap-2">
|
|
131
|
+
${['1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '0', '#'].map((digit) => html `
|
|
132
|
+
<button
|
|
133
|
+
class="rounded-2xl border border-slate-200 bg-white py-3 text-sm font-semibold text-slate-900"
|
|
134
|
+
@click=${() => {
|
|
135
|
+
this.playDtmfTone(digit);
|
|
136
|
+
this.emit('voip-dial-digit', { digit });
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
${digit}
|
|
140
|
+
</button>
|
|
141
|
+
`)}
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
${isOutgoing
|
|
145
|
+
? html `
|
|
146
|
+
<button
|
|
147
|
+
class="mt-4 inline-flex w-full items-center justify-center gap-2 rounded-2xl bg-red-700 py-2 text-sm font-semibold text-white"
|
|
148
|
+
@click=${() => this.emit('voip-hangup')}
|
|
149
|
+
>
|
|
150
|
+
<i data-lucide="phone-off" class="h-4 w-4"></i>
|
|
151
|
+
Cancel
|
|
152
|
+
</button>
|
|
153
|
+
`
|
|
154
|
+
: html `
|
|
155
|
+
<button
|
|
156
|
+
class="mt-4 inline-flex w-full items-center justify-center gap-2 rounded-2xl voip-primary py-2 text-sm font-semibold transition-shadow"
|
|
157
|
+
@click=${() => this.emit('voip-call')}
|
|
158
|
+
>
|
|
159
|
+
<i data-lucide="phone-call" class="h-4 w-4"></i>
|
|
160
|
+
Call
|
|
161
|
+
</button>
|
|
162
|
+
`}
|
|
163
|
+
`}
|
|
164
|
+
`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
__decorate([
|
|
168
|
+
property({ type: String })
|
|
169
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "dialNumber", void 0);
|
|
170
|
+
__decorate([
|
|
171
|
+
property({ type: String })
|
|
172
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "sipStatus", void 0);
|
|
173
|
+
__decorate([
|
|
174
|
+
property({ type: String })
|
|
175
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "callState", void 0);
|
|
176
|
+
__decorate([
|
|
177
|
+
property({ type: Number })
|
|
178
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "callSeconds", void 0);
|
|
179
|
+
__decorate([
|
|
180
|
+
property({ type: Boolean })
|
|
181
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "isMuted", void 0);
|
|
182
|
+
__decorate([
|
|
183
|
+
property({ type: Boolean })
|
|
184
|
+
], SippetAIVoipWidgetPhoneTab.prototype, "isHeld", void 0);
|
|
185
|
+
if (!customElements.get('sippetai-voip-widget-phone-tab')) {
|
|
186
|
+
customElements.define('sippetai-voip-widget-phone-tab', SippetAIVoipWidgetPhoneTab);
|
|
187
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { QueuedCall } from './voip-widget.types.js';
|
|
3
|
+
declare const TwLitElement: typeof LitElement;
|
|
4
|
+
export declare class SippetAIVoipWidgetQueueTab extends TwLitElement {
|
|
5
|
+
queuedCalls: QueuedCall[];
|
|
6
|
+
private emit;
|
|
7
|
+
render(): import("lit").TemplateResult<1>;
|
|
8
|
+
}
|
|
9
|
+
declare global {
|
|
10
|
+
interface HTMLElementTagNameMap {
|
|
11
|
+
'sippetai-voip-widget-queue-tab': SippetAIVoipWidgetQueueTab;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { TW } from '../../lib/tailwindMixin.js';
|
|
10
|
+
const TwLitElement = TW(LitElement);
|
|
11
|
+
export class SippetAIVoipWidgetQueueTab extends TwLitElement {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
this.queuedCalls = [];
|
|
15
|
+
}
|
|
16
|
+
emit(name, detail) {
|
|
17
|
+
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
18
|
+
}
|
|
19
|
+
render() {
|
|
20
|
+
const queuedCalls = Array.isArray(this.queuedCalls) ? this.queuedCalls : [];
|
|
21
|
+
if (queuedCalls.length === 0) {
|
|
22
|
+
return html `<div class="py-6 text-center text-xs text-slate-900">No one is waiting.</div>`;
|
|
23
|
+
}
|
|
24
|
+
return html `
|
|
25
|
+
<div class="flex flex-col gap-2">
|
|
26
|
+
${queuedCalls.map((call) => html `
|
|
27
|
+
<div class="flex items-center justify-between gap-3 rounded-2xl bg-white px-3 py-2">
|
|
28
|
+
<div>
|
|
29
|
+
<div class="text-xs font-semibold text-slate-900">${call.name}</div>
|
|
30
|
+
<div class="text-[11px] text-slate-900">Waiting ${call.time}</div>
|
|
31
|
+
</div>
|
|
32
|
+
<button
|
|
33
|
+
class="rounded-xl voip-primary px-3 py-1 text-xs font-semibold transition-shadow"
|
|
34
|
+
@click=${() => this.emit('voip-queue-pickup', { id: call.id })}
|
|
35
|
+
>
|
|
36
|
+
Pick up
|
|
37
|
+
</button>
|
|
38
|
+
</div>
|
|
39
|
+
`)}
|
|
40
|
+
</div>
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
__decorate([
|
|
45
|
+
property({ type: Array })
|
|
46
|
+
], SippetAIVoipWidgetQueueTab.prototype, "queuedCalls", void 0);
|
|
47
|
+
if (!customElements.get('sippetai-voip-widget-queue-tab')) {
|
|
48
|
+
customElements.define('sippetai-voip-widget-queue-tab', SippetAIVoipWidgetQueueTab);
|
|
49
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { MediaDeviceOption, SipStatus } from './voip-widget.types.js';
|
|
3
|
+
declare const TwLitElement: typeof LitElement;
|
|
4
|
+
export declare class SippetAIVoipWidgetSettingsTab extends TwLitElement {
|
|
5
|
+
userEmail: string;
|
|
6
|
+
audioInputs: MediaDeviceOption[];
|
|
7
|
+
audioOutputs: MediaDeviceOption[];
|
|
8
|
+
selectedMicId: string;
|
|
9
|
+
selectedSpeakerId: string;
|
|
10
|
+
hasMediaPermission: boolean;
|
|
11
|
+
sipStatus: SipStatus;
|
|
12
|
+
updated(): void;
|
|
13
|
+
private emit;
|
|
14
|
+
render(): import("lit").TemplateResult<1>;
|
|
15
|
+
}
|
|
16
|
+
declare global {
|
|
17
|
+
interface HTMLElementTagNameMap {
|
|
18
|
+
'sippetai-voip-widget-settings-tab': SippetAIVoipWidgetSettingsTab;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { html, LitElement } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { createIcons, Mic, Speaker } from 'lucide';
|
|
10
|
+
import { TW } from '../../lib/tailwindMixin.js';
|
|
11
|
+
const TwLitElement = TW(LitElement);
|
|
12
|
+
export class SippetAIVoipWidgetSettingsTab extends TwLitElement {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.userEmail = '';
|
|
16
|
+
this.audioInputs = [];
|
|
17
|
+
this.audioOutputs = [];
|
|
18
|
+
this.selectedMicId = '';
|
|
19
|
+
this.selectedSpeakerId = '';
|
|
20
|
+
this.hasMediaPermission = false;
|
|
21
|
+
this.sipStatus = 'idle';
|
|
22
|
+
}
|
|
23
|
+
updated() {
|
|
24
|
+
createIcons({ icons: { Mic, Speaker }, root: this.renderRoot });
|
|
25
|
+
}
|
|
26
|
+
emit(name, detail) {
|
|
27
|
+
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
28
|
+
}
|
|
29
|
+
render() {
|
|
30
|
+
return html `
|
|
31
|
+
<div class="grid gap-3">
|
|
32
|
+
<div
|
|
33
|
+
class="rounded-2xl border border-slate-200 bg-white px-3 py-2 flex items-center gap-2"
|
|
34
|
+
>
|
|
35
|
+
<div
|
|
36
|
+
class="text-[10px] font-semibold uppercase tracking-wide text-slate-900"
|
|
37
|
+
>
|
|
38
|
+
SIP
|
|
39
|
+
</div>
|
|
40
|
+
<div
|
|
41
|
+
class="flex items-center gap-2 text-xs font-semibold text-slate-900"
|
|
42
|
+
>
|
|
43
|
+
<span
|
|
44
|
+
class=${`rounded-full px-2 py-0.5 text-[10px] font-semibold ${this.sipStatus === 'connected'
|
|
45
|
+
? 'bg-emerald-100 text-emerald-700'
|
|
46
|
+
: this.sipStatus === 'error'
|
|
47
|
+
? 'bg-red-100 text-red-700'
|
|
48
|
+
: 'bg-slate-200 text-slate-900'}`}
|
|
49
|
+
>
|
|
50
|
+
${this.sipStatus}
|
|
51
|
+
</span>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
<label class="grid gap-1 text-xs text-slate-900">
|
|
55
|
+
<span class="font-semibold text-slate-900">Email</span>
|
|
56
|
+
<input
|
|
57
|
+
class="w-full rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900"
|
|
58
|
+
type="email"
|
|
59
|
+
.value=${this.userEmail}
|
|
60
|
+
@input=${(event) => this.emit('voip-email-change', {
|
|
61
|
+
value: event.target.value,
|
|
62
|
+
})}
|
|
63
|
+
/>
|
|
64
|
+
</label>
|
|
65
|
+
|
|
66
|
+
${this.hasMediaPermission
|
|
67
|
+
? html ``
|
|
68
|
+
: html `
|
|
69
|
+
<button
|
|
70
|
+
class="rounded-2xl border border-slate-200 bg-white px-3 py-2 text-xs font-semibold text-slate-900"
|
|
71
|
+
@click=${() => this.emit('voip-request-permission')}
|
|
72
|
+
>
|
|
73
|
+
Enable device labels
|
|
74
|
+
</button>
|
|
75
|
+
`}
|
|
76
|
+
|
|
77
|
+
<label class="grid gap-1 text-xs text-slate-900">
|
|
78
|
+
<span class="flex items-center gap-2 font-semibold text-slate-900">
|
|
79
|
+
<i data-lucide="mic" class="h-4 w-4"></i>
|
|
80
|
+
Microphone
|
|
81
|
+
</span>
|
|
82
|
+
<select
|
|
83
|
+
class="w-full rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900"
|
|
84
|
+
.value=${this.selectedMicId}
|
|
85
|
+
@change=${(event) => this.emit('voip-mic-change', {
|
|
86
|
+
value: event.target.value,
|
|
87
|
+
})}
|
|
88
|
+
>
|
|
89
|
+
${this.audioInputs.map(device => html `<option value=${device.id}>${device.label}</option>`)}
|
|
90
|
+
</select>
|
|
91
|
+
</label>
|
|
92
|
+
|
|
93
|
+
<label class="grid gap-1 text-xs text-slate-900">
|
|
94
|
+
<span class="flex items-center gap-2 font-semibold text-slate-900">
|
|
95
|
+
<i data-lucide="speaker" class="h-4 w-4"></i>
|
|
96
|
+
Speaker
|
|
97
|
+
</span>
|
|
98
|
+
<select
|
|
99
|
+
class="w-full rounded-2xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900"
|
|
100
|
+
.value=${this.selectedSpeakerId}
|
|
101
|
+
@change=${(event) => this.emit('voip-speaker-change', {
|
|
102
|
+
value: event.target.value,
|
|
103
|
+
})}
|
|
104
|
+
>
|
|
105
|
+
${this.audioOutputs.map(device => html `<option value=${device.id}>${device.label}</option>`)}
|
|
106
|
+
</select>
|
|
107
|
+
</label>
|
|
108
|
+
</div>
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
__decorate([
|
|
113
|
+
property({ type: String })
|
|
114
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "userEmail", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
property({ type: Array })
|
|
117
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "audioInputs", void 0);
|
|
118
|
+
__decorate([
|
|
119
|
+
property({ type: Array })
|
|
120
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "audioOutputs", void 0);
|
|
121
|
+
__decorate([
|
|
122
|
+
property({ type: String })
|
|
123
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "selectedMicId", void 0);
|
|
124
|
+
__decorate([
|
|
125
|
+
property({ type: String })
|
|
126
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "selectedSpeakerId", void 0);
|
|
127
|
+
__decorate([
|
|
128
|
+
property({ type: Boolean })
|
|
129
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "hasMediaPermission", void 0);
|
|
130
|
+
__decorate([
|
|
131
|
+
property({ type: String })
|
|
132
|
+
], SippetAIVoipWidgetSettingsTab.prototype, "sipStatus", void 0);
|
|
133
|
+
if (!customElements.get('sippetai-voip-widget-settings-tab')) {
|
|
134
|
+
customElements.define('sippetai-voip-widget-settings-tab', SippetAIVoipWidgetSettingsTab);
|
|
135
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { Contact, HistoryEntry, QueuedCall, VoipTab } from './voip-widget.types.js';
|
|
3
|
+
import './voip-widget-launcher.js';
|
|
4
|
+
import './voip-widget-panel.js';
|
|
5
|
+
import './voip-widget-phone-tab.js';
|
|
6
|
+
import './voip-widget-queue-tab.js';
|
|
7
|
+
import './voip-widget-contacts-tab.js';
|
|
8
|
+
import './voip-widget-history-tab.js';
|
|
9
|
+
import './voip-widget-settings-tab.js';
|
|
10
|
+
declare const TwLitElement: typeof LitElement;
|
|
11
|
+
/**
|
|
12
|
+
* A VoIP widget web component allowing real-time telephony for Sippet AI integrations
|
|
13
|
+
*
|
|
14
|
+
* @tag sippetai-voip-widget
|
|
15
|
+
* @since 0.0.1
|
|
16
|
+
* @status experimental
|
|
17
|
+
*
|
|
18
|
+
**/
|
|
19
|
+
export declare class SippetAIVoipWidget extends TwLitElement {
|
|
20
|
+
apiKey: string;
|
|
21
|
+
sessionAuth: boolean;
|
|
22
|
+
apiOrigin: string;
|
|
23
|
+
sipUrl: string;
|
|
24
|
+
sipUser: string;
|
|
25
|
+
sipUserId: string;
|
|
26
|
+
sipPassword: string;
|
|
27
|
+
sipWebSocketUrl: string;
|
|
28
|
+
userName: string;
|
|
29
|
+
userEmail: string;
|
|
30
|
+
availability: string;
|
|
31
|
+
queueCount: number;
|
|
32
|
+
incomingCall: boolean;
|
|
33
|
+
incomingCallerName: string;
|
|
34
|
+
incomingFromQueue: boolean;
|
|
35
|
+
contacts: Contact[];
|
|
36
|
+
history: HistoryEntry[];
|
|
37
|
+
queuedCalls: QueuedCall[];
|
|
38
|
+
open: boolean;
|
|
39
|
+
activeTab: VoipTab;
|
|
40
|
+
private dialNumber;
|
|
41
|
+
private callState;
|
|
42
|
+
private sipStatus;
|
|
43
|
+
private callSeconds;
|
|
44
|
+
private isMuted;
|
|
45
|
+
private isHeld;
|
|
46
|
+
private dragOffsetX;
|
|
47
|
+
private dragOffsetY;
|
|
48
|
+
private dragX;
|
|
49
|
+
private dragY;
|
|
50
|
+
private audioInputs;
|
|
51
|
+
private audioOutputs;
|
|
52
|
+
private selectedMicId;
|
|
53
|
+
private selectedSpeakerId;
|
|
54
|
+
private hasMediaPermission;
|
|
55
|
+
private widgetLocked;
|
|
56
|
+
private remoteAudio?;
|
|
57
|
+
private simpleUser?;
|
|
58
|
+
private sipConfigKey;
|
|
59
|
+
private callTimer?;
|
|
60
|
+
private permissionStream?;
|
|
61
|
+
private queueSocket?;
|
|
62
|
+
private queueChannel?;
|
|
63
|
+
private queueChannelUpdateRef?;
|
|
64
|
+
private queueChannelDeleteRef?;
|
|
65
|
+
private sessionSipCredentialsIssued;
|
|
66
|
+
private sipCredentialExpiresAt?;
|
|
67
|
+
private sipCredentialRefreshTimer?;
|
|
68
|
+
private sipCredentialPromise?;
|
|
69
|
+
private widgetLockHeartbeat?;
|
|
70
|
+
private widgetLockPoller?;
|
|
71
|
+
private widgetTabId;
|
|
72
|
+
private get sipServer();
|
|
73
|
+
private ensureTabId;
|
|
74
|
+
private readWidgetLock;
|
|
75
|
+
private writeWidgetLock;
|
|
76
|
+
private releaseWidgetLock;
|
|
77
|
+
private startWidgetLockHeartbeat;
|
|
78
|
+
private stopWidgetLockHeartbeat;
|
|
79
|
+
private setWidgetLocked;
|
|
80
|
+
private syncWidgetLock;
|
|
81
|
+
private initWidgetLock;
|
|
82
|
+
private teardownWidgetLock;
|
|
83
|
+
private handleWidgetStorage;
|
|
84
|
+
private handleVisibilityChange;
|
|
85
|
+
private handlePageHide;
|
|
86
|
+
private configureSdkEndpoints;
|
|
87
|
+
private getRpcConfig;
|
|
88
|
+
private clearSipCredentialRefresh;
|
|
89
|
+
private scheduleSipCredentialRefresh;
|
|
90
|
+
private parseSipExpiry;
|
|
91
|
+
private isSipCredentialExpiringSoon;
|
|
92
|
+
private refreshSessionSipCredentials;
|
|
93
|
+
openPanel(tab?: VoipTab): void;
|
|
94
|
+
callNumber(phoneNumber: string): Promise<void>;
|
|
95
|
+
answerCall(): Promise<void>;
|
|
96
|
+
declineCall(): Promise<void>;
|
|
97
|
+
toggleHold(): Promise<void>;
|
|
98
|
+
transferTo(queue: string): void;
|
|
99
|
+
private refreshDevices;
|
|
100
|
+
private requestMediaPermission;
|
|
101
|
+
private applySpeakerSelection;
|
|
102
|
+
private setupSip;
|
|
103
|
+
private teardownSip;
|
|
104
|
+
firstUpdated(): void;
|
|
105
|
+
updated(changedProperties: Map<string, unknown>): void;
|
|
106
|
+
disconnectedCallback(): void;
|
|
107
|
+
private handleDeviceChange;
|
|
108
|
+
private handleToggleOpen;
|
|
109
|
+
private handleSelectTab;
|
|
110
|
+
private handleShowSettings;
|
|
111
|
+
private handleStartDrag;
|
|
112
|
+
private handleDrag;
|
|
113
|
+
private handleEndDrag;
|
|
114
|
+
private resolveDialTarget;
|
|
115
|
+
private handleCall;
|
|
116
|
+
private handleHangup;
|
|
117
|
+
private handleAccept;
|
|
118
|
+
private handleHold;
|
|
119
|
+
private handleDecline;
|
|
120
|
+
private handleMuteToggle;
|
|
121
|
+
private handleTransfer;
|
|
122
|
+
private emitCallState;
|
|
123
|
+
private setCallState;
|
|
124
|
+
private startCallTimer;
|
|
125
|
+
private stopCallTimer;
|
|
126
|
+
private stopPermissionStream;
|
|
127
|
+
private loadContacts;
|
|
128
|
+
private resolveHistoryName;
|
|
129
|
+
private formatHistoryTime;
|
|
130
|
+
private loadHistory;
|
|
131
|
+
private initQueueChannel;
|
|
132
|
+
private teardownQueueChannel;
|
|
133
|
+
private resetQueueChannel;
|
|
134
|
+
private handleQueueEntryEvent;
|
|
135
|
+
private formatQueueWaitTime;
|
|
136
|
+
private loadQueueEntries;
|
|
137
|
+
private acceptQueueEntry;
|
|
138
|
+
private resolveSipUserId;
|
|
139
|
+
private updateOperatorStatus;
|
|
140
|
+
render(): import("lit").TemplateResult<1>;
|
|
141
|
+
}
|
|
142
|
+
export default SippetAIVoipWidget;
|