The Softphone
component is a comprehensive solution for call management within your React applications. It provides a rich and extensible interface for making and managing calls. Additionally, it includes options to customize the appearance and behavior of the component. You can see a live demo here.
- Call Management: Make calls and manage their status.
- Automatic Registration: Supports automatic user registration.
- Customizable Rendering: Customize how contacts are displayed.
- Various Events: Manage events such as call reception and status changes.
- Sidebar Integration: Includes configurable options for an interactive sidebar.
npm install @telaclaims-tech/softphone
- Node.js v16.16.0 - Required for running JavaScript applications.
- React v17.0.2 - Required for building user interfaces.
- MUI Material v5.15.15 - Provides Material Design UI components.
- Twilio Voice SDK v2.10.2 - Allows making and receiving phone calls directly in your apps.
- libphonenumber-js v1.10.60 - A library for parsing, formatting, and validating international phone numbers.
Below is a basic example of how to use the Softphone
component:
First need to use the SoftphoneProvider to wrap the Softphone component.
import { SoftphoneProvider } from "@telaclaims-tech/softphone";
function Main() {
return (
<SoftphoneProvider>
<App />
</SoftphoneProvider>
);
}
Then, you can use the Softphone
component and related hooks
in your application:
import Softphone from "@telaclaims-tech/softphone";
function App() {
const onFetchToken = async (identity) => {
// Fetch and return a Twilio token for the given identity.
};
return <Softphone contact={{ identity: "test" }} events={{ onFetchToken }} />;
}
This type represents the input structure required for contact-related operations in the Softphone component.
type ContactInput = ContactConstructorArgs | Contact;
This type represents the constructor arguments for creating a new contact.
type ContactConstructorArgs = {
identity: string;
id?: string;
label?: string;
isNew?: boolean;
status?: ContactStatus;
avatar?: string;
type?: "phone" | "identifier";
data?: Record<string, unknown>;
};
Properties:
-
identity
required
: The unique identifier for the contact used to communicate with Twilio and associated to the token. -
id
(default: uuidv4)
: Other unique identifier for the contact. -
label
(default: identity)
: The display name for the contact. -
isNew
(default: false)
: Indicates if the contact is new. display a New Icon in the contact list. -
status
("available" | "unavailable" | "unknown"(default))
: The status of the Device. -
avatar
(default: "/")
: The URL of the contact's avatar. -
type
("phone" | "identifier"(default))
: The type of contact. phone if the identity is a valid Phone Number. identifier otherwise. -
data
({})
: Additional data for the contact. Used in combination to theonRenderContact
to extend the contact view
This is a base class for the contact object. It represents a contact in the Softphone component. Exported to use.
const contact = new Contact(...ContactConstructorArgs);
or
const contact = Contact.buildContact(...ContactInput);
This type represents the settings for the Softphone component.
type SoftphoneSettings = {
contact: ContactInput;
autoRegister?: boolean;
events: Events;
callActions?: CallAction[];
};
Properties:
-
contact
required
: The registered contact. -
events
required
: The event handlers for the Softphone component. See theEvents
type for more details. -
autoRegister
(default: false)
: Automatically register the device on initialization. -
callActions
(optional)
: The call actions to display in the call view. (example buttons like hold and transfer).
This type represents the event handlers for the Softphone component. They are dispatched when specific events occur within the component.
type Events = {
onFetchToken: (identity: string, context: EventContext) => Promise<string>;
onChangeStatus?: (status: Status, context: EventContext) => void;
onIncomingCall?: (
call: Call,
context: EventContext
) => ContactInput | undefined;
onCallMessageReceived?: (message: string, context: EventContext) => void;
};
Properties:
-
onFetchToken
required
: Fetches the Twilio token for the given identity. -
onChangeStatus
(optional)
: Handles the status change event for the device(registered
,unregistered
). Triggered when the device status changes. -
onIncomingCall
(optional)
: Handles the incoming call event. Triggered when a call is received. -
onCallMessageReceived
(optional)
: Handles the call message received event. Triggered when a message is received from twilio using the Voice SDK Call Message Events during an active call.Currently, a default message 'CALL_CONNECTED' is displayed when the call connects to update the view.
This type represents the call actions to display in the call view.
type CallAction = {
id: string;
label: string;
onClick: (action: CallAction, call: Call) => void;
disabled: boolean;
loading: boolean;
icon: React.ReactNode;
};
Properties:
id
required
: The unique identifier for the action.label
required
: The label for the action.onClick
required
: Handles the click event on the action.disabled
required
: Indicates if the action is disabled.loading
required
: Indicates if the action is loading.icon
required
: The icon for the action.
This type represents the default call actions to display in the call view.
type DefaultCallActions = {
onClickLedIndicator?: (ledIndicator: boolean) => void | Promise<void>;
};
Properties:
onClickLedIndicator
(optional)
: Handles the click event on the led indicator. This function is called when the user clicks on the led indicator. Provide the led indicator value.
This type represents the context object for the event handlers in the Softphone component. It provides information about the current state of the component.
type EventContext = {
device?: Device;
call?: Call;
contact: Contact;
contactSelected?: Contact;
status: Status;
view: Views;
};
Properties:
-
device
(optional)
: The current Twilio device instance. -
call
(optional)
: The current Twilio call instance. -
contact
required
: The registered Contact. -
contactSelected
(optional)
: The contact selected. This contact selected could be selected by the user in the contact list, or the contact that is calling. Also using the functionslookupContact
ormakeCall
using the useSoftphone hook. -
status
required
: The current status of the device. -
view
required
: The current view of the Softphone component. Example:"ringing"
|"on-call"
|"incoming"
This type represents the handlers for the Softphone component.
type Handlers = {
onLookupContact?: (contactToLookup: string) => Promise<ContactInput[]>;
onClickMakeCallButton?: (contact: ContactInput) => void;
onRenderContact?: (contact: ContactInput) => React.ReactNode | undefined;
onRenderIncomingView?: (contact: ContactInput) => React.ReactNode | undefined;
};
Properties:
-
onLookupContact
(optional)
: Looks up a contact by the given identity. This function is called when the user type for a contact in the search contact input. Provide the input typed by the user and return the contacts that match the input. -
onClickMakeCallButton
(optional)
: Handles the click event on the make call button. This function is called when the user clicks on the make call button. Provide the contact selected by the user to make the call. -
onRenderContact
(optional)
: Renders the contact in thecontact
view. This function is called when the contact view is rendered. Provide the contact to render and return the JSX to render the contact. This is for customizing the contact view and extend the Contact selected. -
onRenderIncomingView
(optional)
: Renders the contact in theincoming
view. This function is called when the incoming view is rendered. Provide the contact to render and return the JSX to render the contact. This is for customizing the incoming view and extend the Contact selected.
The main difference between Events
and Handlers
is that Events
are dispatched when specific events occur within the internal state between Softphone
and Twilio SDK
events. These events do not have access to the current state of the component. To access the current state of the component, the context object provided in the Events
should be used. On the other hand, Handlers
are functions that are called when the user interacts with the component, and they do have access to the current state of the component.
The Softphone
component accepts the following props:
-
contact
ContactInput
: The contact to register with the Softphone component. -
events
Events
: The event handlers for the Softphone component. -
handlers
Handlers
: The handlers for the Softphone component. -
callActions
CallActions
: The call actions to display in the call view. (example buttons like hold and transfer). -
defaultCallActions
DefaultCallActions
: Like Call Action but these are by default, currently manage the led indicator action. -
autoRegister
(default: false)
: Automatically register the device on initialization. -
showStatus
(default: false)
: Show the status of the device in a bottom bar. -
styles
ContainerStyles
: Custom styles for the Softphone component. Styles that can be used arewidth
,height
, andminHeight
. -
sidebar
SideBarProps
: Extend the softphone with a sidebar. The sidebar is a component that can be used to display additional information or actions.
The SideBar
component is a component that can be used to display additional information or actions. It is a component that can be used to extend the Softphone component with additional information or actions.
This type represents the props for the SideBar component.
type SideBarProps = {
styles?: ContainerStyles;
options?: SideBarOption[];
onClickSideBarOption?: (option: SideBarOption) => void;
};
Properties:
-
styles
ContainerStyles
: Custom styles for the SideBar component. Styles that can be used arewidth
,height
, andminHeight
. -
options
SideBarOption[]
: The options to display in the SideBar component. -
onClickSideBarOption
(optional)
: Handles the click event on the SideBar option. This function is called when the user clicks on a SideBar option. Provide the option clicked by the user.
This type represents the options for the SideBar component.
type SideBarOption = {
id: string;
title: string;
position?: "top" | "bottom";
component: React.ReactNode;
panelComponent?: React.ReactNode;
};
Properties:
-
id
required
: The unique identifier for the option. -
title
required
: The title of the option. -
position
(default: "top")
: The position of the option in the SideBar component. -
component
required
: The option component to render. -
panelComponent
(optional)
: The panel component to render when the option is clicked.
The useSoftphone
hook provides access to the Softphone component's state and methods. It can be used to interact with the Softphone component programmatically.
import { useSoftphone } from "@telaclaims-tech/softphone";
function App() {
const {
isBusy,
currentCall,
registeredContact,
contactSelected,
updateCallAction,
displayOnCallView,
displayOnRingingView,
stopLedIndicator,
lookupContact,
makeCall } = useSoftphone();
return (
// ...
);
}
Properties:
-
isBusy
boolean
: Indicates if the Softphone component is busy. -
currentCall
Call
: The current call object. -
registeredContact
Contact
: The registered contact object. -
contactSelected
Contact
: The contact selected(contact on incoming call or the contact selected for an outgoing call). -
lookupContact
(contactToLookup: ContactInput): void
: Select a contact directly. -
makeCall
({ contact, params, }: { contact?: ContactInput; params?: Record<string, unknown>; }): void
: Start a call with the given contact using the params provided. -
updateCallAction
(action: CallAction): void
: Update the call action(update disable or loading state in callActions like hold button). -
displayOnCallView
(contact: ContactInput): void
: Display the on-call view with the given contact. -
displayOnRingingView
(contact: ContactInput): void
: Display the ringing view with the given contact. -
stopLedIndicator
(): void
: Stop the led indicator.
The useSideBar
hook provides access to the SideBar component's state and methods. It can be used to interact with the SideBar component programmatically.
import { useSideBar } from "@telaclaims-tech/softphone";
function App() {
const {
openSideBar } = useSideBar();
return (
// ...
);
}
Properties:
openSideBar
(optionId: string): void
: Open the SideBar with the given option id.
The utils
module provides utility functions for the Softphone component.
import { utils } from "@telaclaims-tech/softphone";
const { isPossiblePhoneNumber, isValidPhoneNumber, parsePhoneNumber } = utils;
These functions can be used to validate and parse phone numbers. (They are based on the libphonenumber-js
library)
The components
module provides various components that can be used.
LookupInput
: A component that displays a list of contacts.
onLookupContact
: (contactToLookup: string) => Promise<ContactInput[]>: Event handler for looking a matched list of contacts.onSelectContact
: (contact: ContactInput) => void;: Event handler for selecting a contact. Dispatch the selected contact event.
import { LookupInput } from "@telaclaims-tech/softphone";
function App() {
return (
<LookupInput
onLookupContact={onLookupContact}
onSelectContact={onSelectContact}
/>
);
}
ActionButton
: A component that displays an action button. Like the make call button.
icon
: React.ReactNode: The icon for the action button.active
: boolean: Indicates if the action button is active.loading
: boolean: Indicates if the action button is loading.disabled
: boolean: Indicates if the action button is disabled.extend Button props
import { ActionButton } from "@telaclaims-tech/softphone";
function App() {
return (
<ActionButton
icon={<PhoneForwardedIcon fontSize={"large"} />}
active
loading={loadingTransfer}
disabled={loadingTransfer}
color={"success"}
onClick={(e) => handleClickTransferButton(e, option)}
/>
);
}
ContactUI
: A component that displays a contact.
onRenderContact, contact
onRenderContact
: (contact: ContactInput) => React.ReactNode | undefined: Event handler for extend the rendering contact.contact
: ContactInput: The contact to display.
import { ContactUI } from "@telaclaims-tech/softphone";
function App() {
return <ContactUI onRenderContact={onRenderContact} contact={contact} />;
}