Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@jkavuncuoglu/vue-softphone

jkavuncuoglu142MIT1.0.1

A provider independent Vue.js 2 softphone component

vue, vue2, softphone, amazon connect, twilio, 8x8, ring central, telephony

readme

Vue Softphone v2

npm version License: MIT

A provider-independent Vue.js 2 softphone component that works with multiple telephony providers including Amazon Connect, Twilio, and more. This component provides a modular and provider-agnostic call control panel, making future migrations between providers seamless and low-effort.

Features

  • 📞 Complete softphone UI with call controls
  • 🔄 Provider-independent architecture (Amazon Connect, Twilio)
  • 📱 Incoming and outgoing call handling
  • 🔀 Call transfer functionality (warm and cold)
  • 👥 Conference call support
  • 🔊 Audio controls (mute/unmute)
  • ⏸️ Call management (hold/resume)
  • 🔍 Built-in WebRTC diagnostics
  • 🎨 Customizable styling with TailwindCSS

Installation

NPM

npm install vue-softphone

Yarn

yarn add vue-softphone

Peer Dependencies

This component requires the following peer dependencies:

npm install vue@^2.6.0 @fortawesome/fontawesome-svg-core@^6.0.0 @fortawesome/free-solid-svg-icons@^6.0.0 @fortawesome/vue-fontawesome@^2.0.0

Basic Usage

Global Registration

import Vue from 'vue';
import VueSoftphone from 'vue-softphone';

Vue.use(VueSoftphone);

Local Registration

import { Softphone } from 'vue-softphone';

export default {
  components: {
    Softphone
  }
}

Template Usage

<template>
  <div>
    <Softphone 
      :phone-numbers="phoneNumbers"
      :transfer-numbers="transferNumbers"
      :show-ccp-popup-actions="true"
      :show-ccp-status-actions="true"
      @call-started="handleCallStarted"
      @call-ended="handleCallEnded"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      phoneNumbers: [
        { label: 'Main Office', number: '+15551234567' },
        { label: 'Support', number: '+15557654321' }
      ],
      transferNumbers: [
        { label: 'Sales Team', number: '+15559876543' },
        { label: 'Customer Service', number: '+15551234567' }
      ]
    }
  },
  methods: {
    handleCallStarted(callData) {
      console.log('Call started:', callData);
    },
    handleCallEnded(callData) {
      console.log('Call ended:', callData);
    }
  }
}
</script>

🧩 Architecture Overview

Components

Component Description
Softphone.vue Main component that integrates all sub-components and manages state
CallStatus.vue Shows agent connection/mute status
MainControlPanel.vue Core call control actions (Mute, Hang Up, Transfer)
IncomingCallActions.vue Accept/Decline buttons for inbound calls
OutgoingCallActions.vue Outbound call initiation interface
ConferenceCallActions.vue Manages conference call functionality
AdditionalNumbersModal.vue Modal for selecting phone numbers
CcpLoginModal.vue Handles login prompts for CCP providers
DiagnosticsModal.vue Displays diagnostic test results

Services Structure

Service Description
softphoneFactory.js Returns the correct provider service instance
providers/AmazonConnect/amazonConnectService.js Amazon Connect implementation
providers/AmazonConnect/agentService.js Manages agent lifecycle and state for Amazon Connect
providers/AmazonConnect/contactService.js Handles contact events for Amazon Connect
providers/Twilio/twilioService.js Twilio implementation
providers/Twilio/agentService.js Manages agent lifecycle and state for Twilio
providers/Twilio/contactService.js Handles contact events for Twilio
callUtils.js Shared helper functions
diagnostics/WebRTCDiagnosticsService.js Performs WebRTC diagnostic tests

Provider Configuration

Amazon Connect

// In your main.js or component
import { getSoftphoneService } from 'vue-softphone/src/services/softphoneFactory';

// Amazon Connect is the default provider
const softphoneService = getSoftphoneService('amazon-connect');

// Initialize with your Amazon Connect configuration
softphoneService.initialize({
  container: document.getElementById('ccp-container'),
  ccpUrl: 'https://your-instance-name.awsapps.com/connect/ccp-v2/',
  onStatusChange: (status) => console.log(`Agent status: ${status}`),
  onIncomingCall: () => console.log('Incoming call'),
  onCallEnded: (contact) => console.log('Call ended')
});

Twilio

// In your main.js or component
import { getSoftphoneService } from 'vue-softphone/src/services/softphoneFactory';

// Specify Twilio as the provider
const softphoneService = getSoftphoneService('twilio');

// Initialize with your Twilio configuration
softphoneService.initialize({
  container: document.getElementById('twilio-container'),
  onStatusChange: (status) => console.log(`Agent status: ${status}`),
  onIncomingCall: () => console.log('Incoming call'),
  onCallEnded: (contact) => console.log('Call ended')
});

API Reference

Props

Prop Type Required Default Description
phoneNumbers Array Yes - Array of phone numbers for outgoing calls
transferNumbers Array Yes - Array of phone numbers for call transfers
showCcpPopupActions Boolean No true Show/hide CCP popup actions
showCcpStatusActions Boolean No true Show/hide CCP status actions

Events

Event Payload Description
call-started { contactId, patient_phone_number, status } Emitted when a call is started
call-ended { contactId, ccpLogs } Emitted when a call ends

Phone Number Format

Both phoneNumbers and transferNumbers should be arrays of objects with the following structure:

{
  label: 'Display Name',
  number: '+15551234567' // E.164 format recommended
}

Softphone Provider Interface

All provider implementations follow a common interface:

// Methods that all providers implement
interface ISoftphoneProviderService {
  initialize(options);
  placeCall(phoneNumber);
  hangUpCall();
  acceptIncomingCall();
  declineIncomingCall();
  transferCall(number, isWarmTransfer);
  endTransferCall(isAgentDisconnect);
  holdCall();
  resumeCall();
  mute();
  unmute();
  openLogin();
}

➕ Adding a New Provider

  1. Create a new service file in src/services/providers/YourProvider/ (e.g., zoomPhoneService.js)
  2. Implement the ISoftphoneProviderService interface methods
  3. Register the provider in softphoneFactory.js:
// softphoneFactory.js
import amazonConnectService from './providers/AmazonConnect/amazonConnectService';
import twilioService from './providers/Twilio/twilioService';
import zoomPhoneService from './providers/ZoomPhone/zoomPhoneService';

export function getSoftphoneService(provider = 'amazon-connect') {
    switch (provider) {
        case 'amazon-connect':
            return amazonConnectService;
        case 'twilio':
            return twilioService;
        case 'zoom-phone':
            return zoomPhoneService;
        default:
            throw new Error(`Unknown telephony provider: ${provider}`);
    }
}

🔍 Diagnostics

The component includes built-in WebRTC diagnostics that run automatically on initialization:

  • Microphone permissions check
  • Network connectivity test
  • WebRTC stability test
  • Network speed test

If any critical tests fail (microphone or WebRTC), a non-dismissible modal will be displayed to help the user resolve the issues.

🤝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin feature/my-new-feature
  5. Submit a pull request

🛠️ Development Setup

# Install dependencies
npm install

# Build for development
npm run build

# Run tests
npm test

🧪 Testing

The component includes comprehensive tests using Jest:

# Run all tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

💼 Author

Jeremy Kavuncuoglu jkavuncuoglu@outlook.com

💖 Support This Project

If you find this project useful, you can help keep it alive and growing! Your support allows me to:

  • Dedicate more time to development and maintenance
  • Cover hosting, tools, and other project costs
  • Build new features and improvements

Even a small contribution goes a long way. You can support the project in any of these ways:

Thank you for helping make this project better and accessible for everyone! 🚀