call-control-sdk 1.0.0 → 2.1.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 +12 -22
- package/dist/index.d.mts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +1122 -0
- package/dist/index.mjs +1131 -0
- package/package.json +10 -21
- package/eslint.config.js +0 -23
- package/index.html +0 -13
- package/public/vite.svg +0 -1
- package/src/App.tsx +0 -47
- package/src/index.css +0 -23
- package/src/lib/components/CallControlPanel.tsx +0 -422
- package/src/lib/hooks/useDraggable.ts +0 -128
- package/src/lib/hooks/useSDKState.ts +0 -17
- package/src/lib/index.ts +0 -25
- package/src/lib/sdk-state.ts +0 -140
- package/src/lib/types.ts +0 -22
- package/src/main.tsx +0 -10
- package/src/vite-env.d.ts +0 -1
- package/tsconfig.app.json +0 -27
- package/tsconfig.json +0 -7
- package/tsconfig.lib.json +0 -23
- package/tsconfig.node.json +0 -25
- package/vite.config.ts +0 -47
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useState,
|
|
3
|
-
useRef,
|
|
4
|
-
useCallback,
|
|
5
|
-
type MouseEvent,
|
|
6
|
-
type TouchEvent,
|
|
7
|
-
} from "react";
|
|
8
|
-
|
|
9
|
-
interface Position {
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface UseDraggableReturn {
|
|
15
|
-
position: Position;
|
|
16
|
-
isDragging: boolean;
|
|
17
|
-
dragRef: React.RefObject<HTMLDivElement | null>;
|
|
18
|
-
handleMouseDown: (e: MouseEvent<HTMLDivElement>) => void;
|
|
19
|
-
handleTouchStart: (e: TouchEvent<HTMLDivElement>) => void;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function useDraggable(
|
|
23
|
-
initialPosition: Position,
|
|
24
|
-
onPositionChange?: (position: Position) => void
|
|
25
|
-
): UseDraggableReturn {
|
|
26
|
-
const [position, setPosition] = useState<Position>(initialPosition);
|
|
27
|
-
const [isDragging, setIsDragging] = useState(false);
|
|
28
|
-
const dragRef = useRef<HTMLDivElement>(null);
|
|
29
|
-
const dragStart = useRef<Position>({ x: 0, y: 0 });
|
|
30
|
-
const elementStart = useRef<Position>({ x: 0, y: 0 });
|
|
31
|
-
|
|
32
|
-
const updatePosition = useCallback(
|
|
33
|
-
(newPosition: Position) => {
|
|
34
|
-
// Constrain position to viewport bounds
|
|
35
|
-
const element = dragRef.current;
|
|
36
|
-
if (!element) return;
|
|
37
|
-
|
|
38
|
-
const rect = element.getBoundingClientRect();
|
|
39
|
-
const viewportWidth = window.innerWidth;
|
|
40
|
-
const viewportHeight = window.innerHeight;
|
|
41
|
-
|
|
42
|
-
const constrainedPosition = {
|
|
43
|
-
x: Math.max(0, Math.min(newPosition.x, viewportWidth - rect.width)),
|
|
44
|
-
y: Math.max(0, Math.min(newPosition.y, viewportHeight - rect.height)),
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
setPosition(constrainedPosition);
|
|
48
|
-
onPositionChange?.(constrainedPosition);
|
|
49
|
-
},
|
|
50
|
-
[onPositionChange]
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const handleStart = useCallback(
|
|
54
|
-
(clientX: number, clientY: number) => {
|
|
55
|
-
setIsDragging(true);
|
|
56
|
-
dragStart.current = { x: clientX, y: clientY };
|
|
57
|
-
elementStart.current = position;
|
|
58
|
-
|
|
59
|
-
const handleMove = (moveClientX: number, moveClientY: number) => {
|
|
60
|
-
const deltaX = moveClientX - dragStart.current.x;
|
|
61
|
-
const deltaY = moveClientY - dragStart.current.y;
|
|
62
|
-
|
|
63
|
-
const newPosition = {
|
|
64
|
-
x: elementStart.current.x + deltaX,
|
|
65
|
-
y: elementStart.current.y + deltaY,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
updatePosition(newPosition);
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const handleMouseMove = (e: globalThis.MouseEvent) => {
|
|
72
|
-
e.preventDefault();
|
|
73
|
-
handleMove(e.clientX, e.clientY);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const handleTouchMove = (e: globalThis.TouchEvent) => {
|
|
77
|
-
e.preventDefault();
|
|
78
|
-
const touch = e.touches[0];
|
|
79
|
-
if (touch) {
|
|
80
|
-
handleMove(touch.clientX, touch.clientY);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const handleEnd = () => {
|
|
85
|
-
setIsDragging(false);
|
|
86
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
87
|
-
document.removeEventListener("mouseup", handleEnd);
|
|
88
|
-
document.removeEventListener("touchmove", handleTouchMove);
|
|
89
|
-
document.removeEventListener("touchend", handleEnd);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
93
|
-
document.addEventListener("mouseup", handleEnd);
|
|
94
|
-
document.addEventListener("touchmove", handleTouchMove, {
|
|
95
|
-
passive: false,
|
|
96
|
-
});
|
|
97
|
-
document.addEventListener("touchend", handleEnd);
|
|
98
|
-
},
|
|
99
|
-
[position, updatePosition]
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
const handleMouseDown = useCallback(
|
|
103
|
-
(e: MouseEvent<HTMLDivElement>) => {
|
|
104
|
-
e.preventDefault();
|
|
105
|
-
handleStart(e.clientX, e.clientY);
|
|
106
|
-
},
|
|
107
|
-
[handleStart]
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const handleTouchStart = useCallback(
|
|
111
|
-
(e: TouchEvent<HTMLDivElement>) => {
|
|
112
|
-
e.preventDefault();
|
|
113
|
-
const touch = e.touches[0];
|
|
114
|
-
if (touch) {
|
|
115
|
-
handleStart(touch.clientX, touch.clientY);
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
[handleStart]
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
position,
|
|
123
|
-
isDragging,
|
|
124
|
-
dragRef,
|
|
125
|
-
handleMouseDown,
|
|
126
|
-
handleTouchStart,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from "react";
|
|
2
|
-
import { sdkStateManager } from "../sdk-state";
|
|
3
|
-
import type { SDKState } from "../types";
|
|
4
|
-
|
|
5
|
-
export function useSDKState(): SDKState {
|
|
6
|
-
const [state, setState] = useState<SDKState>(sdkStateManager.getState());
|
|
7
|
-
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
const unsubscribe = sdkStateManager.subscribe(() => {
|
|
10
|
-
setState(sdkStateManager.getState());
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
return unsubscribe;
|
|
14
|
-
}, []);
|
|
15
|
-
|
|
16
|
-
return state;
|
|
17
|
-
}
|
package/src/lib/index.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { sdkStateManager } from './sdk-state';
|
|
2
|
-
|
|
3
|
-
export { CallControlPanel } from './components/CallControlPanel';
|
|
4
|
-
export type { CallControlPanelProps, CallData, CallStatus } from './types';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Initialize the Call Control SDK with an API key
|
|
8
|
-
* @param sdkApiKey - The API key for SDK authentication
|
|
9
|
-
* @throws {Error} When API key is missing or invalid
|
|
10
|
-
*/
|
|
11
|
-
export function initCallSDK(sdkApiKey: string): void {
|
|
12
|
-
sdkStateManager.initialize(sdkApiKey);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Update call data (used by host application)
|
|
17
|
-
* @param data - Partial call data to update
|
|
18
|
-
*/
|
|
19
|
-
export function updateCallData(data: {
|
|
20
|
-
mobileNumber?: string;
|
|
21
|
-
callReferenceId?: string;
|
|
22
|
-
agentLoginId?: string;
|
|
23
|
-
}): void {
|
|
24
|
-
sdkStateManager.updateCallData(data);
|
|
25
|
-
}
|
package/src/lib/sdk-state.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import type { SDKState, CallData, CallStatus } from "./types";
|
|
2
|
-
|
|
3
|
-
class SDKStateManager {
|
|
4
|
-
private state: SDKState;
|
|
5
|
-
private listeners: Array<() => void> = [];
|
|
6
|
-
private readonly STORAGE_KEY = "call-control-sdk-state";
|
|
7
|
-
|
|
8
|
-
constructor() {
|
|
9
|
-
this.state = this.getInitialState();
|
|
10
|
-
this.loadFromStorage();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private getInitialState(): SDKState {
|
|
14
|
-
return {
|
|
15
|
-
apiKey: null,
|
|
16
|
-
isInitialized: false,
|
|
17
|
-
isHolding: false,
|
|
18
|
-
isMuted: false,
|
|
19
|
-
status: "idle",
|
|
20
|
-
callStartTime: null,
|
|
21
|
-
position: { x: 50, y: 50 },
|
|
22
|
-
callData: {
|
|
23
|
-
mobileNumber: "",
|
|
24
|
-
callReferenceId: "",
|
|
25
|
-
agentLoginId: "",
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private loadFromStorage(): void {
|
|
31
|
-
try {
|
|
32
|
-
const stored = localStorage.getItem(this.STORAGE_KEY);
|
|
33
|
-
if (stored) {
|
|
34
|
-
const parsedState = JSON.parse(stored);
|
|
35
|
-
// Only restore persistent data, not initialization state
|
|
36
|
-
this.state = {
|
|
37
|
-
...this.state,
|
|
38
|
-
isHolding: parsedState.isHolding || false,
|
|
39
|
-
isMuted: parsedState.isMuted || false,
|
|
40
|
-
status: parsedState.status || "idle",
|
|
41
|
-
position: parsedState.position || { x: 50, y: 50 },
|
|
42
|
-
callStartTime: parsedState.callStartTime || null,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
} catch (error) {
|
|
46
|
-
console.warn("Failed to load SDK state from localStorage:", error);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
private saveToStorage(): void {
|
|
51
|
-
try {
|
|
52
|
-
const persistentState = {
|
|
53
|
-
isHolding: this.state.isHolding,
|
|
54
|
-
isMuted: this.state.isMuted,
|
|
55
|
-
status: this.state.status,
|
|
56
|
-
position: this.state.position,
|
|
57
|
-
callStartTime: this.state.callStartTime,
|
|
58
|
-
};
|
|
59
|
-
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(persistentState));
|
|
60
|
-
} catch (error) {
|
|
61
|
-
console.warn("Failed to save SDK state to localStorage:", error);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private notifyListeners(): void {
|
|
66
|
-
this.listeners.forEach((listener) => listener());
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public initialize(apiKey: string): void {
|
|
70
|
-
if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
|
|
71
|
-
throw new Error("API key not available");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
this.state.apiKey = apiKey;
|
|
75
|
-
this.state.isInitialized = true;
|
|
76
|
-
this.notifyListeners();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public getState(): SDKState {
|
|
80
|
-
return { ...this.state };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public subscribe(listener: () => void): () => void {
|
|
84
|
-
this.listeners.push(listener);
|
|
85
|
-
return () => {
|
|
86
|
-
const index = this.listeners.indexOf(listener);
|
|
87
|
-
if (index > -1) {
|
|
88
|
-
this.listeners.splice(index, 1);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public setHolding(isHolding: boolean): void {
|
|
94
|
-
this.state.isHolding = isHolding;
|
|
95
|
-
this.saveToStorage();
|
|
96
|
-
this.notifyListeners();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
public setMuted(isMuted: boolean): void {
|
|
100
|
-
this.state.isMuted = isMuted;
|
|
101
|
-
this.saveToStorage();
|
|
102
|
-
this.notifyListeners();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
public setStatus(status: CallStatus): void {
|
|
106
|
-
this.state.status = status;
|
|
107
|
-
this.saveToStorage();
|
|
108
|
-
this.notifyListeners();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public setPosition(position: { x: number; y: number }): void {
|
|
112
|
-
this.state.position = position;
|
|
113
|
-
this.saveToStorage();
|
|
114
|
-
this.notifyListeners();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
public startCall(): void {
|
|
118
|
-
this.state.callStartTime = Date.now();
|
|
119
|
-
this.state.status = "ready";
|
|
120
|
-
this.saveToStorage();
|
|
121
|
-
this.notifyListeners();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
public endCall(): void {
|
|
125
|
-
this.state.callStartTime = null;
|
|
126
|
-
this.state.status = "idle";
|
|
127
|
-
this.state.isHolding = false;
|
|
128
|
-
this.state.isMuted = false;
|
|
129
|
-
this.saveToStorage();
|
|
130
|
-
this.notifyListeners();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
public updateCallData(data: Partial<CallData>): void {
|
|
134
|
-
this.state.callData = { ...this.state.callData, ...data };
|
|
135
|
-
this.notifyListeners();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Singleton instance
|
|
140
|
-
export const sdkStateManager = new SDKStateManager();
|
package/src/lib/types.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export interface CallData {
|
|
2
|
-
mobileNumber: string;
|
|
3
|
-
callReferenceId: string;
|
|
4
|
-
agentLoginId: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface CallControlPanelProps {
|
|
8
|
-
onDataChange?: (data: CallData) => void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type CallStatus = 'idle' | 'ready' | 'break';
|
|
12
|
-
|
|
13
|
-
export interface SDKState {
|
|
14
|
-
apiKey: string | null;
|
|
15
|
-
isInitialized: boolean;
|
|
16
|
-
isHolding: boolean;
|
|
17
|
-
isMuted: boolean;
|
|
18
|
-
status: CallStatus;
|
|
19
|
-
callStartTime: number | null;
|
|
20
|
-
position: { x: number; y: number };
|
|
21
|
-
callData: CallData;
|
|
22
|
-
}
|
package/src/main.tsx
DELETED
package/src/vite-env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
/// <reference types="vite/client" />
|
package/tsconfig.app.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"useDefineForClassFields": true,
|
|
6
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
/* Bundler mode */
|
|
11
|
-
"moduleResolution": "bundler",
|
|
12
|
-
"allowImportingTsExtensions": true,
|
|
13
|
-
"verbatimModuleSyntax": true,
|
|
14
|
-
"moduleDetection": "force",
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
"jsx": "react-jsx",
|
|
17
|
-
|
|
18
|
-
/* Linting */
|
|
19
|
-
"strict": true,
|
|
20
|
-
"noUnusedLocals": true,
|
|
21
|
-
"noUnusedParameters": true,
|
|
22
|
-
"erasableSyntaxOnly": true,
|
|
23
|
-
"noFallthroughCasesInSwitch": true,
|
|
24
|
-
"noUncheckedSideEffectImports": true
|
|
25
|
-
},
|
|
26
|
-
"include": ["src"]
|
|
27
|
-
}
|
package/tsconfig.json
DELETED
package/tsconfig.lib.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
"moduleResolution": "bundler",
|
|
9
|
-
"allowImportingTsExtensions": true,
|
|
10
|
-
"resolveJsonModule": true,
|
|
11
|
-
"isolatedModules": true,
|
|
12
|
-
"noEmit": true,
|
|
13
|
-
"jsx": "react-jsx",
|
|
14
|
-
"strict": true,
|
|
15
|
-
"noUnusedLocals": true,
|
|
16
|
-
"noUnusedParameters": true,
|
|
17
|
-
"noFallthroughCasesInSwitch": true,
|
|
18
|
-
"declaration": true,
|
|
19
|
-
"outDir": "./dist"
|
|
20
|
-
},
|
|
21
|
-
"include": ["src/lib/**/*"],
|
|
22
|
-
"exclude": ["src/main.tsx", "src/App.tsx", "**/*.test.*"]
|
|
23
|
-
}
|
package/tsconfig.node.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
-
"target": "ES2023",
|
|
5
|
-
"lib": ["ES2023"],
|
|
6
|
-
"module": "ESNext",
|
|
7
|
-
"skipLibCheck": true,
|
|
8
|
-
|
|
9
|
-
/* Bundler mode */
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"verbatimModuleSyntax": true,
|
|
13
|
-
"moduleDetection": "force",
|
|
14
|
-
"noEmit": true,
|
|
15
|
-
|
|
16
|
-
/* Linting */
|
|
17
|
-
"strict": true,
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"erasableSyntaxOnly": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true,
|
|
22
|
-
"noUncheckedSideEffectImports": true
|
|
23
|
-
},
|
|
24
|
-
"include": ["vite.config.ts"]
|
|
25
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vite";
|
|
2
|
-
import react from "@vitejs/plugin-react-swc";
|
|
3
|
-
import { resolve } from "path";
|
|
4
|
-
// https://vite.dev/config/
|
|
5
|
-
export default defineConfig(({ mode }) => {
|
|
6
|
-
if (mode === "lib") {
|
|
7
|
-
return {
|
|
8
|
-
plugins: [react()],
|
|
9
|
-
build: {
|
|
10
|
-
lib: {
|
|
11
|
-
entry: resolve(__dirname, "src/lib/index.ts"),
|
|
12
|
-
name: "ReactCallControlSDK",
|
|
13
|
-
formats: ["es", "umd"],
|
|
14
|
-
fileName: (format) => `index.${format}.js`,
|
|
15
|
-
},
|
|
16
|
-
rollupOptions: {
|
|
17
|
-
external: [
|
|
18
|
-
"react",
|
|
19
|
-
"react-dom",
|
|
20
|
-
"react/jsx-runtime",
|
|
21
|
-
"react/jsx-dev-runtime",
|
|
22
|
-
"@mui/material",
|
|
23
|
-
"@mui/icons-material",
|
|
24
|
-
"@emotion/react",
|
|
25
|
-
"@emotion/styled",
|
|
26
|
-
],
|
|
27
|
-
output: {
|
|
28
|
-
globals: {
|
|
29
|
-
react: "React",
|
|
30
|
-
"react-dom": "ReactDOM",
|
|
31
|
-
"react/jsx-runtime": "React",
|
|
32
|
-
"react/jsx-dev-runtime": "React",
|
|
33
|
-
"@mui/material": "MaterialUI",
|
|
34
|
-
"@mui/icons-material": "MaterialUIIcons",
|
|
35
|
-
"@emotion/react": "EmotionReact",
|
|
36
|
-
"@emotion/styled": "EmotionStyled",
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
plugins: [react()],
|
|
46
|
-
};
|
|
47
|
-
});
|