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.
@@ -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
- }
@@ -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
@@ -1,10 +0,0 @@
1
- import { StrictMode } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
- import './index.css'
4
- import App from './App.tsx'
5
-
6
- createRoot(document.getElementById('root')!).render(
7
- <StrictMode>
8
- <App />
9
- </StrictMode>,
10
- )
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
@@ -1,7 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.app.json" },
5
- { "path": "./tsconfig.node.json" }
6
- ]
7
- }
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
- }
@@ -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
- });