@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.
Files changed (59) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +136 -0
  3. package/cdn/loader.js +146 -0
  4. package/custom-elements.json +2241 -0
  5. package/dist/components/index.d.ts +1 -0
  6. package/dist/components/index.js +1 -0
  7. package/dist/components/voip-widget/index.d.ts +18 -0
  8. package/dist/components/voip-widget/index.js +4 -0
  9. package/dist/components/voip-widget/voip-widget-contacts-tab.d.ts +14 -0
  10. package/dist/components/voip-widget/voip-widget-contacts-tab.js +45 -0
  11. package/dist/components/voip-widget/voip-widget-history-tab.d.ts +13 -0
  12. package/dist/components/voip-widget/voip-widget-history-tab.js +43 -0
  13. package/dist/components/voip-widget/voip-widget-launcher.d.ts +18 -0
  14. package/dist/components/voip-widget/voip-widget-launcher.js +100 -0
  15. package/dist/components/voip-widget/voip-widget-panel.d.ts +21 -0
  16. package/dist/components/voip-widget/voip-widget-panel.js +193 -0
  17. package/dist/components/voip-widget/voip-widget-phone-tab.d.ts +21 -0
  18. package/dist/components/voip-widget/voip-widget-phone-tab.js +187 -0
  19. package/dist/components/voip-widget/voip-widget-queue-tab.d.ts +14 -0
  20. package/dist/components/voip-widget/voip-widget-queue-tab.js +49 -0
  21. package/dist/components/voip-widget/voip-widget-settings-tab.d.ts +21 -0
  22. package/dist/components/voip-widget/voip-widget-settings-tab.js +135 -0
  23. package/dist/components/voip-widget/voip-widget.d.ts +142 -0
  24. package/dist/components/voip-widget/voip-widget.js +1329 -0
  25. package/dist/components/voip-widget/voip-widget.types.d.ts +22 -0
  26. package/dist/components/voip-widget/voip-widget.types.js +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.js +3 -0
  29. package/dist/lib/realtime.d.ts +1 -0
  30. package/dist/lib/realtime.js +1 -0
  31. package/dist/lib/sippet.d.ts +40 -0
  32. package/dist/lib/sippet.js +197 -0
  33. package/dist/lib/tailwindMixin.d.ts +6 -0
  34. package/dist/lib/tailwindMixin.js +24 -0
  35. package/dist/styles/tailwind.global.css +2 -0
  36. package/dist/styles/tailwind.global.css.js +1 -0
  37. package/package.json +126 -0
  38. package/react/SippetAIVoipWidget.d.ts +158 -0
  39. package/react/SippetAIVoipWidget.js +72 -0
  40. package/react/SippetAIVoipWidgetContactsTab.d.ts +67 -0
  41. package/react/SippetAIVoipWidgetContactsTab.js +29 -0
  42. package/react/SippetAIVoipWidgetHistoryTab.d.ts +55 -0
  43. package/react/SippetAIVoipWidgetHistoryTab.js +26 -0
  44. package/react/SippetAIVoipWidgetLauncher.d.ts +83 -0
  45. package/react/SippetAIVoipWidgetLauncher.js +41 -0
  46. package/react/SippetAIVoipWidgetPanel.d.ts +87 -0
  47. package/react/SippetAIVoipWidgetPanel.js +43 -0
  48. package/react/SippetAIVoipWidgetPhoneTab.d.ts +87 -0
  49. package/react/SippetAIVoipWidgetPhoneTab.js +43 -0
  50. package/react/SippetAIVoipWidgetQueueTab.d.ts +67 -0
  51. package/react/SippetAIVoipWidgetQueueTab.js +27 -0
  52. package/react/SippetAIVoipWidgetSettingsTab.d.ts +91 -0
  53. package/react/SippetAIVoipWidgetSettingsTab.js +47 -0
  54. package/react/index.d.ts +8 -0
  55. package/react/index.js +8 -0
  56. package/react/react-utils.js +67 -0
  57. package/types/custom-element-jsx.d.ts +956 -0
  58. package/types/custom-element-svelte.d.ts +264 -0
  59. package/types/custom-element-vuejs.d.ts +234 -0
package/LICENSE ADDED
@@ -0,0 +1,2 @@
1
+ COPYRIGHT (c) 2026 SIPPET TECHNOLOGIES VCC
2
+ ALL RIGHTS RESERVED
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # Sippet AI Operator Widget
2
+
3
+ A web component (with React wrappers) for embedding Sippet AI telephony controls in any app.
4
+ It provides a floating softphone UI, SIP/WebRTC call controls, queue handling, and light helpers
5
+ built on `@sippet-ai/sdk-js`.
6
+
7
+ ## What it does
8
+
9
+ - Renders a floating VoIP widget with phone, queue, contacts, history, and settings tabs.
10
+ - Connects to SIP and WebRTC (mic/speaker selection and permissions).
11
+ - Listens to queue entries and call history.
12
+ - Exposes a small JS API (`sippet`) to trigger calls and query queues/history.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @sippet-ai/operator-widget
18
+ ```
19
+
20
+ `@sippet-ai/sdk-js` is a dependency of the widget, so it will be installed automatically.
21
+
22
+ ## Quick start (Web Component)
23
+
24
+ ```html
25
+ <script type="module">
26
+ import '@sippet-ai/operator-widget';
27
+ </script>
28
+
29
+ <sippetai-voip-widget
30
+ api-key="YOUR_PUBLISHABLE_API_KEY"
31
+ sip-url="sip.sippet.ai"
32
+ sip-user="1001"
33
+ sip-password="1234"
34
+ sip-web-socket-url="wss://sip.sippet.ai:7443"
35
+ user-name="Agent"
36
+ user-email="agent@example.com"
37
+ ></sippetai-voip-widget>
38
+ ```
39
+
40
+ The widget renders a launcher button at the bottom-right of the page. Clicking it opens the panel.
41
+
42
+ ## React usage
43
+
44
+ ```tsx
45
+ import { SippetAIVoipWidget } from '@sippet-ai/operator-widget/react';
46
+
47
+ export function SupportWidget() {
48
+ return (
49
+ <SippetAIVoipWidget
50
+ apiKey="YOUR_PUBLISHABLE_API_KEY"
51
+ sipUrl="sip.sippet.ai"
52
+ sipUser="1001"
53
+ sipPassword="1234"
54
+ sipWebSocketUrl="wss://sip.sippet.ai:7443"
55
+ userName="Agent"
56
+ userEmail="agent@example.com"
57
+ />
58
+ );
59
+ }
60
+ ```
61
+
62
+ ## Configuration
63
+
64
+ - `api-key` (attribute) / `apiKey` (property). Required for contacts, history, queue polling, and realtime events.
65
+ - `api-origin` (attribute) / `apiOrigin` (property). Optional override for a self-hosted or local API origin.
66
+ - `sip-url`, `sip-user`, `sip-password`, `sip-web-socket-url`. Required for SIP calling.
67
+ - `user-name`, `user-email`. Displayed in the widget.
68
+
69
+ ## Methods & events
70
+
71
+ Methods are available on the DOM element instance via the `sippet` helper.
72
+
73
+ ```ts
74
+ import { sippet } from '@sippet-ai/operator-widget';
75
+
76
+ sippet.setApiKey('YOUR_PUBLISHABLE_API_KEY');
77
+ sippet.setApiOrigin('https://api.sippet.ai');
78
+
79
+ await sippet.call('+15551234567');
80
+ await sippet.answer();
81
+ await sippet.decline();
82
+ await sippet.hold();
83
+
84
+ const queue = await sippet.getQueue();
85
+ const activeCalls = await sippet.getActiveCalls();
86
+ const callDetails = await sippet.callDetails('CALL_UUID');
87
+ ```
88
+
89
+ If the widget element already has `api-key`, you can omit `sippet.setApiKey`.
90
+
91
+ ## Realtime events
92
+
93
+ ```ts
94
+ import { initSocket, joinEventsChannel } from '@sippet-ai/operator-widget';
95
+
96
+ initSocket({ publishableKey: 'YOUR_PUBLISHABLE_API_KEY' });
97
+
98
+ const channel = joinEventsChannel();
99
+
100
+ channel.on('incoming_call', payload => {
101
+ console.log('incoming_call', payload);
102
+ });
103
+ ```
104
+
105
+ Known event names:
106
+
107
+ - `incoming_call`
108
+ - `call_answered`
109
+ - `call_ended`
110
+ - `operator_status_change`
111
+ - `call_queue_entry_updated`
112
+ - `call_queue_entry_deleted`
113
+ - `call_participant_joined`
114
+ - `call_participant_left`
115
+ - `call_transcript_delta`
116
+ - `call_transcript_completed`
117
+
118
+ ## Permissions and runtime behavior
119
+
120
+ - Microphone access is required for calling; the widget prompts for audio permissions when opened.
121
+ - Speaker selection uses `setSinkId` when supported by the browser; some browsers require a user gesture.
122
+ - Queue entries are refreshed on realtime socket events and when the queue tab is opened (no polling loop).
123
+
124
+ ## Using `@sippet-ai/sdk-js` directly
125
+
126
+ If you need RPC calls outside the widget, use the SDK client directly:
127
+
128
+ ```ts
129
+ import { createClient } from '@sippet-ai/sdk-js';
130
+
131
+ const client = createClient({ apiKey: 'YOUR_PUBLISHABLE_API_KEY' });
132
+
133
+ const calls = await client.listCalls({
134
+ fields: ['id', 'callUuid', 'status'],
135
+ });
136
+ ```
package/cdn/loader.js ADDED
@@ -0,0 +1,146 @@
1
+
2
+ let observer;
3
+ let components = {
4
+ "sippetai-voip-widget-launcher": {
5
+ "importPath": "../dist/components/voip-widget/voip-widget-launcher.js",
6
+ "dependencies": []
7
+ },
8
+ "sippetai-voip-widget-panel": {
9
+ "importPath": "../dist/components/voip-widget/voip-widget-panel.js",
10
+ "dependencies": []
11
+ },
12
+ "sippetai-voip-widget-phone-tab": {
13
+ "importPath": "../dist/components/voip-widget/voip-widget-phone-tab.js",
14
+ "dependencies": []
15
+ },
16
+ "sippetai-voip-widget-queue-tab": {
17
+ "importPath": "../dist/components/voip-widget/voip-widget-queue-tab.js",
18
+ "dependencies": []
19
+ },
20
+ "sippetai-voip-widget-contacts-tab": {
21
+ "importPath": "../dist/components/voip-widget/voip-widget-contacts-tab.js",
22
+ "dependencies": []
23
+ },
24
+ "sippetai-voip-widget-history-tab": {
25
+ "importPath": "../dist/components/voip-widget/voip-widget-history-tab.js",
26
+ "dependencies": []
27
+ },
28
+ "sippetai-voip-widget-settings-tab": {
29
+ "importPath": "../dist/components/voip-widget/voip-widget-settings-tab.js",
30
+ "dependencies": []
31
+ },
32
+ "sippetai-voip-widget": {
33
+ "importPath": "../dist/components/voip-widget/voip-widget.js",
34
+ "dependencies": []
35
+ }
36
+ };
37
+ const eagerLoad = [];
38
+
39
+ /** Update the lazy-loader configuration at runtime */
40
+ export async function updateConfig(config) {
41
+ if (config.components) {
42
+ components = { ...components, ...config.components };
43
+ }
44
+
45
+ if(config.prefix || config.suffix) {
46
+ components = getScopedComponents(config.prefix, config.suffix);
47
+ }
48
+
49
+ if (config.rootElement) {
50
+ if (observer) {
51
+ observer.disconnect();
52
+ }
53
+ start(config.rootElement);
54
+ }
55
+
56
+ if (config.eagerLoad) {
57
+ await Promise.allSettled(eagerLoad?.map((tagName) => register(tagName)));
58
+ }
59
+ }
60
+
61
+ function getScopedComponents(prefix = "", suffix = "") {
62
+ const scopedComponents = {};
63
+ for (const [key, value] of Object.entries(components)) {
64
+ const newKey = prefix + key + suffix;
65
+ scopedComponents[newKey] = value;
66
+ }
67
+
68
+ return scopedComponents;
69
+ }
70
+
71
+ /** Load any undefined custom elements and load the components in the list */
72
+ async function load(root) {
73
+ const rootTagName = root instanceof Element ? root.tagName.toLowerCase() : "";
74
+ const tags = [...root.querySelectorAll(":not(:defined)")]?.map((el) =>
75
+ el.tagName.toLowerCase()
76
+ ) || [];
77
+ if (rootTagName.includes("-") && !customElements.get(rootTagName)) {
78
+ tags.push(rootTagName);
79
+ }
80
+ const tagsToRegister = [...new Set(tags)];
81
+ await Promise.allSettled(tagsToRegister?.map((tagName) => register(tagName)));
82
+ }
83
+
84
+ /** Register the component and any dependencies */
85
+ function register(tagName) {
86
+ const component = components[tagName];
87
+
88
+ if (customElements.get(tagName)) {
89
+
90
+ cleanUp(component, tagName);
91
+ return Promise.resolve();
92
+ }
93
+
94
+ if (!component) {
95
+
96
+ return Promise.resolve();
97
+ }
98
+
99
+ return new Promise((resolve, reject) => {
100
+ import(component.importPath)
101
+ .then(() => {
102
+
103
+ cleanUp(component, tagName);
104
+ resolve();
105
+ })
106
+ .catch(() => {
107
+ console.error(`Unable to load <${tagName}> from ${component.importPath}`);
108
+ reject();
109
+ });
110
+ });
111
+ }
112
+
113
+ /** Remove the component from the list of components to load */
114
+ function cleanUp(component, tagName) {
115
+ delete components[tagName];
116
+ component.dependencies?.forEach((dependency) => {
117
+ delete components[dependency];
118
+ });
119
+
120
+ if (!Object.keys(component).length) {
121
+ observer.disconnect();
122
+ }
123
+ }
124
+
125
+ /** Initialize the loader */
126
+ async function start(root = document.body) {
127
+
128
+ // Eager load any components that are not defined in the Custom Elements Manifest
129
+ await Promise.allSettled(eagerLoad?.map((tagName) => register(tagName)));
130
+
131
+ // Watch for any new elements that are added to the DOM
132
+ observer = new MutationObserver((mutations) => {
133
+ for (const { addedNodes } of mutations) {
134
+ for (const node of addedNodes) {
135
+ if (node.nodeType === Node.ELEMENT_NODE) {
136
+ load(node);
137
+ }
138
+ }
139
+ }
140
+ });
141
+
142
+ load(root);
143
+ observer.observe(root, { subtree: true, childList: true });
144
+ }
145
+
146
+ start();