diff --git a/packages/node_modules/@webex/webex-sign-in-page/package.json b/packages/node_modules/@webex/webex-sign-in-page/package.json deleted file mode 100644 index e12bb75d5..000000000 --- a/packages/node_modules/@webex/webex-sign-in-page/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@webex/webex-sign-in-page", - "description": "webex sign in page", - "main": "./dist/cjs/index.ts", - "src": "./src/index.ts", - "module": "./dist/es/index.ts", - "keywords": [], - "author": "devsupport@webex.com", - "license": "MIT", - "dependencies": { - "@formatjs/intl-pluralrules": "^1.5.4", - "@formatjs/intl-relativetimeformat": "^4.5.11", - "@momentum-ui/react-collaboration": "26.82.1" - }, - "repository": "https://github.com/webex/react-widgets", - "files": [ - "src", - "dist", - "cjs", - "es" - ], - "version": "0.50.0" -} - diff --git a/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.scss b/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.scss deleted file mode 100644 index a2279a6eb..000000000 --- a/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.scss +++ /dev/null @@ -1,142 +0,0 @@ -.sign-in-page { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding-top: 40px; -} - -.webex-message-container { - display: flex; - flex: 1; - flex-direction: column; - align-items: center; - height: calc(100vh - 25px)!important; - .icon { - background-image: none; - width: auto; - height: auto; - svg { - width: 200px; - height: 200px; - } - } - .message { - font-family: Inter; - font-size: 0.875rem !important; - font-weight: 450 !important; - font-family: Inter; - line-height: 1.375rem !important; - letter-spacing: -0.016rem; - text-align: center; - color: var(--mds-color-theme-text-primary-normal); - margin: 0.5rem 0rem 0rem; - } - .header { - font-family: Inter; - font-size: 0.875rem; - font-weight: 450; - line-height: 1.375rem; - letter-spacing: -0.016rem; - text-align: center; - } - .title { - font-family: Inter; - font-size: 1.625rem; - font-weight: 550; - line-height: 2.25rem; - letter-spacing: 0rem; - text-align: center; - - } -} - -.navigation-link { - width: 100%; - font-weight: 450; - font-size: 14px; - line-height: 14px; - position: fixed; - text-align: center; - color: var(--mds-color-theme-text-secondary-normal); - background-color: var(--mds-color-theme-background-gradient-primary); - margin: 0px; - bottom: 32px; - .webex-more-info { - color: var(--mds-color-theme-text-accent-normal); - } - .grant-consent { - color: var(--mds-color-theme-text-accent-normal); - } -} - -.webex-message-container__error { - .title { - margin-top: 50px; - } - .icon { - svg { - width: 200px; - height: 200px; - } - } -} - -.close1 { - button { - width: 15rem ; - height: 2rem ; - padding: 0.25rem 0.75rem 0.25rem 0.75rem !important; - border-radius: 1rem; - margin: 1.5rem auto 0.75rem; - } - span { - font-family: Inter; - font-size: 1rem; - font-weight: 550; - line-height: 1.5rem; - letter-spacing: -0.019rem; - margin: 0 auto; - color: var(--mds-color-theme-text-inverted-normal); -} -} -.close2 { - button { - width: 15rem; - height: 2rem !important; - padding: 0.25rem 0.75rem 0.25rem 0.75rem !important; - border-radius: 1rem; - border: 0.063rem solid var(--mds-color-theme-outline-button-normal); - margin: 0 auto 6.25rem; - background-color: var(--mds-color-theme-button-secondary-normal); - } - button:hover { - background-color: rgba(0, 0, 0, 0); - } - span { - font-weight: 550; - font-size: 0.875rem; - line-height: 1.375rem; - letter-spacing: -0.019rem; - color: var(--mds-color-theme-text-primary-normal); - margin: 0 auto; - } -} - -@media screen and (max-height: 444px) { - .sign-in-page__mobile{ - width: 100%; - height: 100%; - overflow-y: auto; - } - .webex-message-container__mobile { - width: 70%; - height: auto !important; - margin: 0 auto; - } -} -@media screen and (max-width: 335px) { - .sign-in-page__mobile{ - width:80%; - } - } \ No newline at end of file diff --git a/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.tsx b/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.tsx deleted file mode 100644 index 30de90efb..000000000 --- a/packages/node_modules/@webex/webex-sign-in-page/src/WebexSignInPage.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { ButtonPill } from "@momentum-ui/react-collaboration"; -import React, { ReactElement } from "react"; -import { useTranslation } from 'react-i18next'; -import './WebexSignInPage.scss'; - - -type IWebexSignInProps = { - signInImage: ReactElement; - signInTitle: string; - signInMessageStart: string; - signInMessageEnd: string; - signInButtonText: string; - footNote: ReactElement; - showSignInOrRetry: boolean; - signInDifferentAccountText?: string; - signInAction: (useDifferentAccount?: boolean) => void; - signingIn: boolean; - headerNoteStart?: string; - headerNoteEnd?: string; - email?: string; - clientType : string; -}; - -export const WebexSignInPage = ({ - signInImage, - signInTitle, - signInMessageStart, - signInMessageEnd, - signInButtonText, - footNote, - showSignInOrRetry, - signInDifferentAccountText, - signInAction, - headerNoteStart, - headerNoteEnd, - email, - signingIn, - clientType - }: IWebexSignInProps) => { - const { t } = useTranslation('WebexSpeedDials'); - return ( -
-
- {!signingIn && ( -
-
- { signInImage } -
-
-

{signInTitle}

- {signInMessageStart && ( -

{signInMessageStart}{email}{signInMessageEnd}

) - } - {headerNoteStart&& ( -
{headerNoteStart}{email}{headerNoteEnd}
- )} -
-
- signInAction(false)}> - { signInButtonText } - - {signInDifferentAccountText && ( -
- signInAction(true)}> - {signInDifferentAccountText} - -
- )} -
- {(clientType!=='desktop' && clientType!=='web') && footNote} -
- )} - {signingIn && ( -
{t('signIn.signingIn')}
- )} -
- {!signingIn && !(clientType!=='desktop' && clientType!=='web') && footNote} -
- ); - }; - - - diff --git a/packages/node_modules/@webex/webex-sign-in-page/src/index.ts b/packages/node_modules/@webex/webex-sign-in-page/src/index.ts deleted file mode 100644 index ef515e430..000000000 --- a/packages/node_modules/@webex/webex-sign-in-page/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '@webex/webex-sign-in-page/src/WebexSignInPage'; \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-call-history/README.md b/packages/node_modules/@webex/widget-call-history/README.md deleted file mode 100644 index d32d29b70..000000000 --- a/packages/node_modules/@webex/widget-call-history/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# webex-call-history - -[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) - -> This is a brief summary. - -- [Install](#install) -- [Usage](#usage) -- [Contribute](#contribute) -- [Maintainers](#maintainers) -- [License](#license) - -## Install - -```bash -$ -``` - -## Usage - -```js -import WebexCallHistory from './WebexCallHistory'; -``` - -## Maintainers - -This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/). - -## Contribute - -Pull requests welcome. Please see [CONTRIBUTING.md](https://github.com/webex/webex-calling-sdk/blob/master/CONTRIBUTING.md) for more details. - -## License - -© 2022 Cisco and/or its affiliates. All Rights Reserved. diff --git a/packages/node_modules/@webex/widget-call-history/package.json b/packages/node_modules/@webex/widget-call-history/package.json deleted file mode 100644 index a2e4877c3..000000000 --- a/packages/node_modules/@webex/widget-call-history/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@webex/widget-call-history", - "description": "widget call history", - "main": "./dist/cjs/index.ts", - "src": "./src/index.ts", - "module": "./dist/es/index.ts", - "keywords": [], - "author": "devsupport@webex.com", - "license": "MIT", - "dependencies": { - "@formatjs/intl-pluralrules": "^1.5.4", - "@formatjs/intl-relativetimeformat": "^4.5.11", - "@momentum-ui/react-collaboration": "26.82.1" - }, - "repository": "https://github.com/webex/react-widgets", - "files": [ - "src", - "dist", - "cjs", - "es" - ], - "version": "0.50.0" -} diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistory.stories.tsx b/packages/node_modules/@webex/widget-call-history/src/CallHistory.stories.tsx deleted file mode 100644 index a21659d06..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistory.stories.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React from 'react'; -import { faker } from '@faker-js/faker'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import { CallHistory } from './CallHistory'; - -export default { - title: 'Components/Call History/List', - component: CallHistory, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -const mockItems = [ - { - id: '1', - name: faker.name.findName(), - phoneNumber: '+16695441558', - startTime: new Date().toISOString(), - endTime: new Date().toISOString(), - direction: 'INCOMING', - disposition: 'CANCELLED', - }, - { - id: '2', - name: faker.name.findName(), - phoneNumber: '+15555555555', - startTime: '2022-04-20T21:21:16.186Z', - endTime: '2022-04-20T21:21:22.202Z', - direction: 'INCOMING', - disposition: 'MISSED', - }, - { - id: '3', - name: faker.name.findName(), - phoneNumber: '+15555555555', - startTime: '2022-04-23T21:21:16.186Z', - endTime: '2022-04-23T21:24:22.202Z', - direction: 'OUTGOING', - disposition: 'ANSWERED', - }, - { - id: '4', - name: faker.name.findName(), - phoneNumber: '+15555555555', - startTime: '2022-04-24T21:21:16.186Z', - endTime: '2022-04-24T21:29:32.202Z', - direction: 'INCOMING', - disposition: 'ANSWERED', - }, -]; - -export const Default = Template.bind({}); -Default.args = { - items: mockItems, -}; diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistory.styles.scss b/packages/node_modules/@webex/widget-call-history/src/CallHistory.styles.scss deleted file mode 100644 index d46ceda5a..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistory.styles.scss +++ /dev/null @@ -1,11 +0,0 @@ -/* Custom styles */ -$C: wxc-call-history; - -.#{$C} { - display: block; - - &__list { - width: 100%; - } - -} diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistory.tsx b/packages/node_modules/@webex/widget-call-history/src/CallHistory.tsx deleted file mode 100644 index ccf203cda..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistory.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { Flex, ListNext as List } from '@momentum-ui/react-collaboration'; -import React from 'react'; - -import './CallHistory.styles.scss'; -import { CallHistoryItem } from './CallHistoryItem'; -import { ICallHistoryItemProps } from './CallHistoryItem.types'; -import useWebexClasses from './hooks/useWebexClasses'; - -export type CallHistoryProps = { - items: ICallHistoryItemProps[]; - style?: React.CSSProperties; - onPress?: (item: ICallHistoryItemProps) => void; - selectedItem?: ICallHistoryItemProps; - extraCallHistoryItemProps?: ICallHistoryItemProps; - makeCall?: (address: string, isVideo?: boolean, label?: string) => void; - isLocaleGerman?: boolean; - dismissBagdeonClickRow?: () => void; -}; - -/** - * @description CallHistory component renders an array of call history items. - * @param {CallHistoryProps} obj - An object of CallHistoryProps - * @param {Array} obj.items An array of CallHistoryItems - * @param {Function} obj.onPress Handle when item is pressed - * @param {ICallHistoryItemProps} obj.selectedItem The selected call history item - * @param {Function} obj.onAudioCallPress Handle when audio call button is pressed - * @param {Function} obj.onVideoCallPress Handle when video call button is pressed - * @param {React.CSSProperties} obj.style Custom style for overriding this component's CSS - * @returns {React.Component} CallHistory component - */ -export const CallHistory = ({ - items, - style = undefined, - onPress = undefined, - selectedItem = undefined, - extraCallHistoryItemProps = undefined, - makeCall, - isLocaleGerman, - dismissBagdeonClickRow -}: CallHistoryProps) => { - const [cssClasses, sc] = useWebexClasses('call-history'); - - return ( - - {items && ( - - {items.map((item, index) => ( - { - if (onPress) { - onPress(item); - dismissBagdeonClickRow && dismissBagdeonClickRow() - } - }} - key={item.id} - id={item.id} - name={item.name} - isSelected={selectedItem?.id === item?.id} - phoneNumber={item.phoneNumber} - direction={item.direction} - disposition={item.disposition} - startTime={item.startTime} - endTime={item.endTime} - callbackAddress={item.callbackAddress} - durationSeconds={item.durationSeconds} - makeCall={makeCall} - callingSpecific={item.callingSpecific} - isLocaleGerman={isLocaleGerman} - dismissBagdeonClickRow={dismissBagdeonClickRow} - /> - ))} - - )} - - ); -}; diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.stories.tsx b/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.stories.tsx deleted file mode 100644 index 3965d4777..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.stories.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { faker } from '@faker-js/faker'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import { CallHistoryItem } from './CallHistoryItem'; - -export default { - title: 'Components/Call History/Item', - component: CallHistoryItem, - argTypes: { - direction: { - options: ['incoming', 'outgoing'], - control: { type: 'radio' }, - }, - disposition: { - options: ['answered', 'missed', 'cancelled'], - control: { type: 'radio' }, - }, - }, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Incoming = Template.bind({}); -Incoming.args = { - id: 'item1', - name: faker.name.findName(), - phoneNumber: '+12345678999', - startTime: '2022-06-20T19:00:00.000Z', - endTime: '2022-06-20T19:05:00.000Z', - direction: 'INCOMING', - disposition: 'ANSWERED', -}; - -export const Outgoing = Template.bind({}); -Outgoing.args = { - ...Incoming.args, - direction: 'OUTGOING', -}; - -export const Missed = Template.bind({}); -Missed.args = { - ...Incoming.args, - disposition: 'MISSED', -}; - -export const Selected = Template.bind({}); -Selected.args = { - ...Incoming.args, - endTime: '2022-06-20T19:05:12.000Z', - direction: 'OUTGOING', - isSelected: true, -}; diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.styles.scss b/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.styles.scss deleted file mode 100644 index cf045892a..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.styles.scss +++ /dev/null @@ -1,56 +0,0 @@ -@import "./styles/list-mixins"; - -/* wxc-call-history-item styles */ -$C: wxc-call-history-item; - -.#{$C} { - - @include list-squared; - @include list-bordered; - @include list-toggle-active(#{$C}__datetime, #{$C}__actions); - - &__phoneNumber, &__time { - @include list-sub-text; - } - - &__name { - @include list-primary-text; - } - - &__content-more { - visibility: hidden; - height: 0; - } - - &--is-missed { - .#{$C}__name, - .#{$C}__duration { - color: var(--theme-text-error-normal) - } - } - - &__content-wrap { - flex: 1; - } - - &__content { - align-items: center; - } - - &__direction { - flex: 1; - align-self: stretch; - @media only screen and (max-width: 600px) { - display: none; - } - } - - &__date { - @include list-primary-text; - text-transform: capitalize; - } - - &__datetime { - text-align: right; - } -} diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.tsx b/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.tsx deleted file mode 100644 index 94a6e3773..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { - AvatarNext as Avatar, - ButtonCircle, - Flex, ListItemBase, - ListItemBaseSection, - Text -} from '@momentum-ui/react-collaboration'; -import React from 'react'; - -import { useTranslation } from 'react-i18next'; -import './CallHistoryItem.styles.scss'; -import { ICallHistoryItemProps } from './CallHistoryItem.types'; -import useWebexClasses from './hooks/useWebexClasses'; -import { - removeBracketsAndContent, - titleCase -} from './utils/avatarInitials'; -import { - formatDate, - formatDateDDMMYYYY, - formatDateForAnnouncement, - formatDurationFromSeconds, - formatTime, - formatTimeToSupport24Hours -} from './utils/dateUtils'; -import { - formatDurationForAnnouncement, - formatPhoneNumberForAnnouncement -} from './utils/voiceOver'; - - -/** - * @description CallHistoryItem renders a individual call history item. - * @param {object} param An object parameter - * @param {string} param.id The id of the item - * @param {number} param.itemIndex The index of the item - * @param {string} param.name The name of the item - * @param {string} param.startTime The startTime of the item - * @param {string} param.endTime The endTime of the item - * @param {string} param.phoneNumber The phone number of the item - * @param {string} param.disposition The disposition of the item - * @param {string} param.direction The direction of the item - * @param {string} param.callbackAddress The address of the item call address - * @param {string} param.missedCallText The text for the missed call label - * @param {boolean} param.isSelected The selected state of the item - * @param {Function} param.onPress Handle when item is pressed - * @param {Function} param.onVideoCallPress Handle when item video call button is pressed - * @param param.audioCallLabel - * @param param.videoCallLabel - * @param {Function} param.onAudioCallPress Handle when item audio call button is pressed - * @returns {React.Component} A CallHistoryItem for rendering - */ -export const CallHistoryItem = ({ - id, - name, - itemIndex = undefined, - startTime, - endTime, - phoneNumber, - callbackAddress = undefined, - onPress = undefined, - direction = undefined, - disposition = undefined, - isSelected = false, - missedCallText = 'Missed call', - audioCallLabel = 'Make an audio call', - videoCallLabel = 'Make a video call', - durationSeconds, - makeCall, - callingSpecific = undefined, - isLocaleGerman, - dismissBagdeonClickRow -}: ICallHistoryItemProps) => { - const { t } = useTranslation('WebexCallHistory'); - const isMissed = disposition?.toLowerCase() === 'missed'; - const isOutgoing = direction?.toLowerCase() === 'outgoing'; - const duration = formatDurationFromSeconds(durationSeconds ? durationSeconds : 0); - const chTitle = name ? name : phoneNumber; - const chInitials = name ? removeBracketsAndContent(name) : removeBracketsAndContent(phoneNumber); - const recentCallsLabel = 'Recent calls' - - const [cssClasses, sc] = useWebexClasses('call-history-item', undefined, { - 'is-missed': isMissed, - 'is-outgoing': isOutgoing, - 'is-selected': isSelected as boolean, - }); - - const handleAudioPress = () => { - if (makeCall) { - makeCall(callbackAddress || id, false, recentCallsLabel); - } - if(dismissBagdeonClickRow) { - dismissBagdeonClickRow(); - } - }; - - const handleVideoPress = () => { - if (makeCall) { - makeCall(callbackAddress || id, true, recentCallsLabel); - } - if(dismissBagdeonClickRow) { - dismissBagdeonClickRow(); - } - }; - - return ( - - - - - - - -
- - {name} - -
- {!(callingSpecific && name) && -
- - {phoneNumber} - -
- } - {(callingSpecific && (name || phoneNumber)) && -
- - {callingSpecific} - -
- } -
- - {isOutgoing && ( - - - - - - - )} - {isMissed && ( - - {t('missedCallText')} - - )} - {!isMissed && ( - - {duration} - - )} - -
-
- - - - - - - - - - - - - - - - - {startTime && isLocaleGerman ? formatDateDDMMYYYY(startTime) : formatDate(startTime)} - - - {startTime && isLocaleGerman ? formatTimeToSupport24Hours(startTime) : formatTime(startTime)} - - - - -
- ); -}; \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.types.ts b/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.types.ts deleted file mode 100644 index ce4ce0777..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/CallHistoryItem.types.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface ICallHistoryItemProps { - id: string; - name: string; - phoneNumber: string; - startTime: string; - endTime: string; - direction?: string | 'INCOMING' | 'OUTGOING'; - disposition?: string; - isSelected?: boolean; - callbackAddress?: string; - missedCallText?: string; - onPress?: (e: unknown) => void; - itemIndex?: number; - audioCallLabel?: string; - videoCallLabel?: string; - durationSeconds?: number; - makeCall?: (address: string, isVideo?: boolean, label?: string) => void; - callingSpecific?: string; - isLocaleGerman?: boolean; - dismissBagdeonClickRow?: () => void; -} diff --git a/packages/node_modules/@webex/widget-call-history/src/NoHistory.tsx b/packages/node_modules/@webex/widget-call-history/src/NoHistory.tsx deleted file mode 100644 index b04e58af1..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/NoHistory.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { Flex, Text } from '@momentum-ui/react-collaboration'; -import useWebexClasses from './hooks/useWebexClasses'; - -type Props = { - message: string | undefined; -}; - -/** - * Banner for displaying empty call history. - * - * @param {string} message The message to display to the user - * @returns {React.Component} React component - */ -export const NoHistory = ({ message }: Props) => { - const [cssClasses, sc] = useWebexClasses('call-history-empty'); - return ( - -
- - - - - - - - - -
- - {message} - -
- ); -}; diff --git a/packages/node_modules/@webex/widget-call-history/src/contexts/AdapterContext.tsx b/packages/node_modules/@webex/widget-call-history/src/contexts/AdapterContext.tsx deleted file mode 100644 index 1e83df65e..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/contexts/AdapterContext.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { - ICallHistoryAdapter, - IMakeCallAdapter, - ISearchContactsAdapter, - ISpeedDialsAdapter, - IVoicemailAdapter, -} from '@webex/component-adapter-interfaces/dist/esm/src' -import React, { createContext } from 'react'; - -export interface IAdapterContext { - user?: unknown; - callHistoryAdapter?: ICallHistoryAdapter; - searchContactsAdapter?: ISearchContactsAdapter; - makeCallAdapter?: IMakeCallAdapter; - speedDialsAdapter?: ISpeedDialsAdapter; - voicemailAdapter?: IVoicemailAdapter; -} - -export const AdapterContext = createContext({}); - -export interface IAdapterProvider { - adapter: IAdapterContext; - children: React.ReactNode; -} - -/** - * - * @param root0 - * @param root0.adapter - * @param root0.children - */ -export const AdapterProvider = ({ adapter, children }: IAdapterProvider) => { - return ( - - {children} - - ); -}; diff --git a/packages/node_modules/@webex/widget-call-history/src/hooks/useMakeCall.ts b/packages/node_modules/@webex/widget-call-history/src/hooks/useMakeCall.ts deleted file mode 100644 index 22ef2cb49..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/hooks/useMakeCall.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { useCallback, useContext } from 'react'; -import { AdapterContext } from '../contexts/AdapterContext'; -import Logger from "../utils/Logger"; -export const useMakeCall = (webexCrosslaunchtoken: string) => { - const ctx = useContext(AdapterContext); - - const makeCall = useCallback( - (address: string, isVideo?: boolean) => { - return makeCrossLaunchCall(address, !!isVideo, webexCrosslaunchtoken); - }, - [makeCrossLaunchCall] - ); - - return [makeCall]; -}; - -export async function makeCrossLaunchCall(address: string, isAudio = false, webexCrosslaunchtoken: string) { - address = address.replace(/ /g, ""); - const url = `webextel://${address}`; - //const crossLaunchCallToken = await getCrossLaunchToken(); - const callUrl = new URL(url); - - // TODO: add check for mobile and if audio calls are enabled - callUrl.searchParams.append('jws', webexCrosslaunchtoken); - callUrl.searchParams.append('isAudio', String(!isAudio)); - Logger.info( - `Making ${isAudio ? 'audio' : 'video'} call to address ${address}` - ); - window.open(callUrl.href); -} diff --git a/packages/node_modules/@webex/widget-call-history/src/hooks/useWebexClasses.ts b/packages/node_modules/@webex/widget-call-history/src/hooks/useWebexClasses.ts deleted file mode 100644 index 0cd806520..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/hooks/useWebexClasses.ts +++ /dev/null @@ -1,48 +0,0 @@ -import classNames from 'classnames'; - -const WEBEX_COMPONENTS_CLASS_PREFIX = 'wxc'; - -/** - * Builds a string of css class names for webex components - * - * @param {string} classBaseName Component class base name - * @param {string} [userClassName] Custom CSS class to apply - * @param {object} otherClasses Other optional classes with prefix - * @returns {[string, Function]} Classes and a prefix function - */ -export default function useWebexClasses( - classBaseName: string, - userClassName?: string, - otherClasses?: { - [key: string]: string | boolean; - } -) { - const userClassNames = Array.isArray(userClassName) - ? userClassName - : [userClassName]; - - const cssClasses = classNames( - 'wxc', - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}`, - ...userClassNames, - { - ...Object.fromEntries( - Object.entries(otherClasses || {}).map(([key, val]) => [ - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}--${key}`, - val, - ]) - ), - } - ); - - const sc = (subclass: string, modifiers: string[] = []) => { - const n = `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}__${subclass}`; - - return classNames( - n, - modifiers.map((m) => `${n}--${m}`) - ); - }; - - return [cssClasses, sc] as const; -} diff --git a/packages/node_modules/@webex/widget-call-history/src/index.ts b/packages/node_modules/@webex/widget-call-history/src/index.ts deleted file mode 100644 index 4c0103b75..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from '@webex/widget-call-history/src/CallHistoryItem.types'; -export { CallHistoryItem } from '@webex/widget-call-history/src/CallHistoryItem'; -export { CallHistory } from '@webex/widget-call-history/src/CallHistory'; -export { NoHistory } from '@webex/widget-call-history/src/NoHistory'; diff --git a/packages/node_modules/@webex/widget-call-history/src/styles/index.scss b/packages/node_modules/@webex/widget-call-history/src/styles/index.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/node_modules/@webex/widget-call-history/src/styles/list-mixins.scss b/packages/node_modules/@webex/widget-call-history/src/styles/list-mixins.scss deleted file mode 100644 index 674be5e7c..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/styles/list-mixins.scss +++ /dev/null @@ -1,51 +0,0 @@ -@mixin list-bordered { - border-bottom: 1px solid var(--scrollbar-track-background, rgba(0, 0, 0, 0.1)); -} - -@mixin list-squared { - border-radius: 0 !important; -} - -@mixin list-avatar { - flex-shrink: 0; -} - -@mixin list-primary-text { - margin: 0; - padding: 0; - width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-sub-text { - color: var(--label-secondary-text); - width: 100%; - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-toggle-active($hideOnActiveClass, $showOnActiveClass) { - @include list-hide-on-active($hideOnActiveClass); - @include list-show-on-active($showOnActiveClass); -} - -@mixin list-hide-on-active($hideOnActiveClass) { - &:hover, - &:focus, - &.active { - .#{$hideOnActiveClass} { - display: none; - } - } -} - -@mixin list-show-on-active($showOnActiveClass) { - &:not(:hover):not(:focus):not(.active) { - .#{$showOnActiveClass} { - display: none; - } - } -} diff --git a/packages/node_modules/@webex/widget-call-history/src/utils/Logger.ts b/packages/node_modules/@webex/widget-call-history/src/utils/Logger.ts deleted file mode 100644 index a3838f979..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/utils/Logger.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - * @param error - */ -export function formatError(error: any) { - if (!error) { - return ''; - } - - if (error.stack) { - return `fileName: '${error.fileName}', name: '${error.name}' lineNumber:${error.lineNumber} columnNumber:${error.columnNumber} message:'${error.message}'.`; - } - - if (error.message) { - return error.message; - } - return JSON.stringify(error); - } - - /** - * - * @param text - * @param leadingCharactersToKeep - */ - export function concise(text = '', leadingCharactersToKeep = 32) { - if (text.length > leadingCharactersToKeep) { - return `${text.substring(0, leadingCharactersToKeep - 1)}...`; - } - return text; - // return text ? (text.length > leadingCharactersToKeep ? text.substring(0, leadingCharactersToKeep - 1) + '...' : text) : ''; - } - - export default class Logger { - static log(level: string, msg: string) { - console.log(`${new Date().toISOString()} [${level}] ${msg}\n`); - } - - static debug(msg: string) { - Logger.log('debug', msg); - } - - static info(msg: string) { - Logger.log('info', msg); - } - - static error(msg: string) { - Logger.log('error', msg); - } - } - \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-call-history/src/utils/avatarInitials.ts b/packages/node_modules/@webex/widget-call-history/src/utils/avatarInitials.ts deleted file mode 100644 index 971659ab8..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/utils/avatarInitials.ts +++ /dev/null @@ -1,33 +0,0 @@ -export function removeBracketsAndContent(str: string): string { - if (str?.match(/^[+\d]/)) { - return "#"; - } - const words = str?.replace(/ *\([^)]*\) */g, ' ').replace(/ *\(\S*/g, '').replace(/\)+/g, '').replace(/\s+/g, ' ').trim().split(' '); - const filteredWords = words?.filter(word => /^[a-zA-Z0-9]/.test(word)); - let initials = ''; - if (filteredWords?.length > 0) { - initials += filteredWords[0][0].toUpperCase(); - if (filteredWords?.length > 1) { - initials += filteredWords[filteredWords.length - 1][0].toUpperCase(); - } - } - if(initials?.length == 0 && str?.length > 0) { - initials += str[0]; - } - return initials; - - } - - export function titleCase(str: string) { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - const isEmail = emailRegex.test(str); - if (isEmail) { - return str; - } else { - var splitStr = str.toLowerCase().split(' '); - for (var i = 0; i < splitStr.length; i++) { - splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].substring(1); - } - return splitStr.join(' '); - } - } \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-call-history/src/utils/dateUtils.ts b/packages/node_modules/@webex/widget-call-history/src/utils/dateUtils.ts deleted file mode 100644 index f4279f4a6..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/utils/dateUtils.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { DateTime, Duration } from 'luxon'; - -/** - * @description Converts date string to DateTime object for use in other functions - * @param {string} date The date string to format - * @returns {DateTime} A DateTime object to be formatted - */ -function getDateTimeFromString(date: string): DateTime { - return DateTime.fromISO(date); -} - -/** - * @description Handle formatting the time for display. - * @param {string} date The date string to format - * @returns {string} A formatted time as in 3:00 PM - */ -export function formatTime(date: string) { - return getDateTimeFromString(date).toLocaleString({ - hour: 'numeric', - minute: '2-digit', - hour12: true, - }); -} - -/** - * @description Handle formatting the date for display. - * @param {string} date The date string to format - * @returns {string} A formatted date as in "Today", "Yesterday", or "1/1/22" - */ -export function formatDate(date: string) { - const d = getDateTimeFromString(date); - - if ( - d.toISODate() === DateTime.now().toISODate() || - d.toISODate() === DateTime.now().minus({ day: 1 }).toISODate() - ) { - return d.toRelativeCalendar({}); - } - - return d.toLocaleString({ - day: 'numeric', - month: 'numeric', - year: '2-digit', - }); -} - -/** - * @description Handle formatting the duration for display. - * @param {number} seconds Total duration in seconds - * @returns {string} A formatted duration for display "04:10" - */ -export function formatDuration(seconds: number) { - const dur = Duration.fromObject({ seconds: Math.trunc(seconds) }); - const shiftedDur = dur.shiftTo('hours', 'minutes', 'seconds').normalize(); - return shiftedDur.toFormat('hh:mm:ss'); -} - -/** - * @description Handle formatting the duration for display. - * @param {string} d1 The start time date string - * @param {string} d2 The end time date string - * @returns {string} A formatted duration for display "4m 10s" - */ -export function formatDurationFromDates(d1: string, d2: string) { - const dur = getDateTimeFromString(d2).diff(getDateTimeFromString(d1)); - const entries = Object.entries( - dur - .shiftTo('hours', 'minutes', 'seconds', 'milliseconds') - .normalize() - .toObject() - ).filter(([unit, amount]) => amount > 0 && unit !== 'milliseconds'); - const outputDur = Duration.fromObject( - entries.length === 0 ? { seconds: 0 } : Object.fromEntries(entries) - ); - return outputDur - .toHuman({ listStyle: 'narrow', unitDisplay: 'narrow' }) - .replace(/,/g, ''); -} - -export function formatDurationFromSeconds(seconds: number) { - const dur = Duration.fromObject({ seconds: Math.trunc(seconds) }); - const entries = Object.entries( - dur - .shiftTo('hours', 'minutes', 'seconds', 'milliseconds') - .normalize() - .toObject() - ).filter(([unit, amount]) => amount > 0 && unit !== 'milliseconds'); - const outputDur = Duration.fromObject( - entries.length === 0 ? { seconds: 0 } : Object.fromEntries(entries) - ); - return outputDur - .toHuman({ listStyle: 'narrow', unitDisplay: 'narrow' }) - .replace(/,/g, ''); -} - -/** - * @description Handle formatting the time for display 24hour format is required. - * @param {string} date The date string to format - * @returns {string} A formatted time as in 24hr format - */ -export function formatTimeToSupport24Hours(date: string) { - return getDateTimeFromString(date).toLocaleString({ - hour: 'numeric', - minute: '2-digit', - hour12: false - }); -} - -/** - * @description Handle formatting the date for display. - * @param {string} date The date string to format - * @returns {string} A formatted date as in "Today", "Yesterday", or "dd.mm.yyyy" - */ -export function formatDateDDMMYYYY(date: string) { - const d = getDateTimeFromString(date); - - if ( - d.toISODate() === DateTime.now().toISODate() || - d.toISODate() === DateTime.now().minus({ day: 1 }).toISODate() - ) { - return d.toRelativeCalendar({}); - } - - return d.toLocaleString({ - day: '2-digit', - month: '2-digit', - year: 'numeric', - }); -} - -/** - * @description Handle formatting the date for announce. - * @param {string} date The date string to format - * @returns {string} A announced date as in "Today", "Yesterday", or "june 10,2024" - */ -export const formatDateForAnnouncement = (date: string) => { - const dateValue = getDateTimeFromString(date); - - if ( - dateValue.toISODate() === DateTime.now().toISODate() || - dateValue.toISODate() === DateTime.now().minus({ days: 1 }).toISODate() - ) { - return dateValue.toRelativeCalendar({}); - } - - return dateValue.toLocaleString({ - month: 'long', // Use 'long' for full month name - day: 'numeric', - year: 'numeric', - }); - } diff --git a/packages/node_modules/@webex/widget-call-history/src/utils/voiceOver.ts b/packages/node_modules/@webex/widget-call-history/src/utils/voiceOver.ts deleted file mode 100644 index 73c5c071f..000000000 --- a/packages/node_modules/@webex/widget-call-history/src/utils/voiceOver.ts +++ /dev/null @@ -1,59 +0,0 @@ -export const formatDurationForAnnouncement = (seconds: number): string => { - const hours = Math.floor(seconds / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - const remainingSeconds = seconds % 60; - - const formattedHours = hours > 0 ? `${hours} hour${hours !== 1 ? 's' : ''}` : ''; - const formattedMinutes = minutes > 0 ? `${minutes} minute${minutes !== 1 ? 's' : ''}` : ''; - const formattedSeconds = `${remainingSeconds} second${remainingSeconds !== 1 ? 's' : ''}`; - - const formattedDuration = [formattedHours, formattedMinutes, formattedSeconds] - .filter(Boolean) // Remove empty strings - .join(' '); - - return `duration ${formattedDuration}`; - }; - - export const formatPhoneNumberForAnnouncement = (phoneNumber: string): string => { - if (phoneNumber?.match(/^\d|^\+/)) { - return phoneNumber?.split('').map((digit) => digit).join(' '); - } - return phoneNumber; - } - - export const formatVoiceMailTimeDurationForAnnouncement = (duration: number): string => { - const durationInSeconds = Math.floor(duration / 1000); - const formattedDuration = new Date(durationInSeconds * 1000).toISOString().substr(11, 8); // Format as "HH:mm:ss" - const [hours, minutes, seconds] = formattedDuration.split(':').map(Number); - let announcement = ''; - if (hours > 0) { - announcement += `${hours} hour${hours !== 1 ? 's' : ''} `; - } - - if (minutes > 0) { - announcement += `${minutes} minute${minutes !== 1 ? 's' : ''} `; - } - - if (seconds > 0) { - announcement += `${seconds} second${seconds !== 1 ? 's' : ''}`; - } - return `duration ${announcement}`; - }; - - export const formatSleekBarCurrTimeDurationForAnnouncement = (duration: number): string => { - - const durationInSeconds = duration / 1000; - const hours = Math.floor(durationInSeconds / 3600); - const minutes = Math.floor((durationInSeconds % 3600) / 60); - const seconds = Math.floor(durationInSeconds % 60); - const milliseconds = Math.floor((duration - seconds * 1000 - minutes * 60000 - hours * 3600000)); - - const parts = [ - hours > 0 ? `${hours} hour${hours !== 1 ? 's' : ''}` : '', - minutes > 0 ? `${minutes} minute${minutes !== 1 ? 's' : ''}` : '', - seconds > 0 ? `${seconds} second${seconds !== 1 ? 's' : ''}` : '', - milliseconds > 0 ? `${milliseconds} millisecond${milliseconds !== 1 ? 's' : ''}` : '', - ].filter(part => part !== ''); - - return parts.join(' '); - }; \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-call-history/tsconfig.json b/packages/node_modules/@webex/widget-call-history/tsconfig.json deleted file mode 100644 index ce5484b1b..000000000 --- a/packages/node_modules/@webex/widget-call-history/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react", - "experimentalDecorators": true, - "allowJs": true, - "lib": ["es6", "dom"], - "rootDir": "./src", - "module": "commonjs", - "target": "es5", - "sourceMap": true, - "moduleResolution": "node", - "noImplicitReturns": true, - "noImplicitThis": true, - "noImplicitAny": true, - "strictNullChecks": true, - "esModuleInterop": true, - }, - "include": [ - "packages/node_modules/@ciscospark/**/*", - "packages/node_modules/@webex/**/*", - "./src" - ], - "exclude": [ - "packages/node_modules/@ciscospark/**/dist/*", - "packages/node_modules/@webex/**/dist/*", - "packages/node_modules/@ciscospark/**/es/*", - "packages/node_modules/@webex/**/es/*", - "packages/node_modules/@ciscospark/**/cjs/*", - "packages/node_modules/@webex/**/cjs/*", - "node_modules/**/*", - "dist", - "rollup.calling-config.js", - ] -} diff --git a/packages/node_modules/@webex/widget-number-pad/package.json b/packages/node_modules/@webex/widget-number-pad/package.json deleted file mode 100644 index 1e7a2e9a6..000000000 --- a/packages/node_modules/@webex/widget-number-pad/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@webex/widget-number-pad", - "description": "widget number pad", - "main": "./dist/cjs/index.ts", - "src": "./src/index.ts", - "module": "./dist/es/index.ts", - "keywords": [], - "author": "devsupport@webex.com", - "license": "MIT", - "dependencies": { - "@formatjs/intl-pluralrules": "^1.5.4", - "@formatjs/intl-relativetimeformat": "^4.5.11", - "@momentum-ui/react-collaboration": "26.82.1" - }, - "repository": "https://github.com/webex/react-widgets", - "files": [ - "src", - "dist", - "cjs", - "es" - ], - "version": "0.50.0" -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.stories.tsx b/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.stories.tsx deleted file mode 100644 index a87ce4dac..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { CallButtons } from './CallButtons'; - -export default { - title: 'Components/CallButtons', - component: CallButtons, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = { - address: '1234567', -}; - -export const Disabled = Template.bind({}); -Disabled.args = { - disabled: true, -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.tsx b/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.tsx deleted file mode 100644 index e596f3ce1..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/CallButtons/CallButtons.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { - ButtonCircle, - Flex, - IconNext, - Text -} from '@momentum-ui/react-collaboration'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -type CallButtonsProps = { - address: string; - disabled?: boolean; - className?: string; - useMakeAudioCall?:() => void; - useMakeVideoCall?:() => void; -}; - -/** - * Video and audio call buttons - * - * @param {CallButtonsProps} props - * @param props.address address to call - * @param props.disabled denotes whether the call buttons should be disabled - * @returns {JSX.Element} React component - */ -export const CallButtons = ({ - address, - disabled = false, - className = undefined, - useMakeAudioCall = undefined, - useMakeVideoCall = undefined, -}: CallButtonsProps) => { - const isDisabled = disabled || !address; - - const { t } = useTranslation('WebexSearchContacts'); - - return ( - - - - - - {t('audio')} - - - - - - {t('video')} - - - ); -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.stories.tsx b/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.stories.tsx deleted file mode 100644 index 9d52b439c..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.stories.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { faker } from '@faker-js/faker'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import React from 'react'; - -import { IWebexIntContact } from '@webex/component-adapter-interfaces/dist/esm/src'; -import { ContactCard } from './ContactCard'; - -/** - * - */ -function createMockItem(): IWebexIntContact { - const name = faker.name.findName(); - return { - id: faker.datatype.uuid(), - name, - phoneNumbers: [ - { - type: 'home', - address: faker.phone.number('+1-###-###-####'), - }, - { - type: 'work', - address: faker.phone.number('+1-###-###-####'), - }, - ], - emailAddresses: [ - { - type: 'email', - address: faker.internet.email(name), - }, - ], - }; -} - -export default { - title: 'Components/ContactCard', - component: ContactCard, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = { - user: createMockItem(), -}; - -export const OneAddress = Template.bind({}); -const onAddressUser = createMockItem(); -onAddressUser.phoneNumbers = []; -OneAddress.args = { - user: onAddressUser, -}; - -export const NoAddresses = Template.bind({}); -const noAddressUser = createMockItem(); -noAddressUser.phoneNumbers = []; -noAddressUser.emailAddresses = []; -NoAddresses.args = { - user: noAddressUser, -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.styles.scss b/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.styles.scss deleted file mode 100644 index b8e0bdb93..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.styles.scss +++ /dev/null @@ -1,19 +0,0 @@ -$C: wxc-contact-card; - -.#{$C} { - - &__name { - margin-bottom: 0; - } - - &__select { - width: 280px; - - .md-select-selected-item-wrapper { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.tsx b/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.tsx deleted file mode 100644 index febe06b5c..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/ContactCard/ContactCard.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { - AvatarNext as Avatar, - Flex, - SelectNext as Select, - Text, -} from '@momentum-ui/react-collaboration'; -import { Item } from '@react-stately/collections'; -import { IWebexIntContact } from '@webex/component-adapter-interfaces/dist/esm/src'; -import React, { useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { removeBracketsAndContent } from '../../src/utils/avatarInitials'; -import { CallButtons } from "../CallButtons/CallButtons"; -import { useLazyLoadAvatarUrl } from '../hooks/useLazyLoadAvatarUrl'; -import useWebexClasses from '../hooks/useWebexClasses'; -import './ContactCard.styles.scss'; - - type Props = { - style?: React.CSSProperties; - user: IWebexIntContact; - noCallableAddressMessage?: string; - makeCall?: (address: string, isVideo?: boolean, label?: string) => void; - }; - - /** - * Description for this component. - * - * @param {Props} props Props for this component - * @param props.style optional styles to add - * @param props.user user to display call options for - * @param props.onSelect callback function to call when the selection is updated. It is called once at component mount with the default value - * @param props.noCallableAddressMessage message to display when there is no callable entry for a user - * @returns Contact card react component - */ - export const ContactCard = ({ - user, - style = undefined, - noCallableAddressMessage = 'No addresses found', - makeCall - }: Props) => { - const [cssClasses, sc] = useWebexClasses('contact-card'); - const [imageUrl] = useLazyLoadAvatarUrl(user.id, user.fetchAvatarUrl); - const { t } = useTranslation(); - const callables = useMemo( - () => [...user.phoneNumbers, ...user.emailAddresses], - [user] - ); - const chatLabel = '1:1 chat' - const [selectedAddress, setSelectedAddress] = useState(callables[0]?.address); - const callSelectElement = - callables.length > 1 ? ( - - ) : ( - callables[0]?.address ? ( - - {t('label.address.'+ callables[0]?.type) }: {callables[0]?.address} - - ) : ( - - {noCallableAddressMessage} - - ) - ); - - return ( - - - - {user.name} - - {callSelectElement} - makeCall && makeCall(selectedAddress, false, chatLabel)} - useMakeVideoCall={() => makeCall && makeCall(selectedAddress, true, chatLabel)} - /> - - ); - }; - \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.scss b/packages/node_modules/@webex/widget-number-pad/src/NumberPad.scss deleted file mode 100644 index 89f152dd5..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.scss +++ /dev/null @@ -1,7 +0,0 @@ -$C: wxc-number-pad; - -.#{$C} { - display: grid; - grid-template-columns: min-content min-content min-content; - grid-gap: 20px; -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.stories.tsx b/packages/node_modules/@webex/widget-number-pad/src/NumberPad.stories.tsx deleted file mode 100644 index dbbb094a8..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { NumberPad } from './NumberPad'; - -export default { - title: 'Components/NumberPad', - component: NumberPad, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = {}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.tsx b/packages/node_modules/@webex/widget-number-pad/src/NumberPad.tsx deleted file mode 100644 index b8796b026..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/NumberPad.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { ButtonDialpad } from '@momentum-ui/react-collaboration'; -import './NumberPad.scss'; -import useWebexClasses from './hooks/useWebexClasses'; -import { useGridFocus } from './hooks/useGridFocus'; -import { longPressDuration, longPressHandledValues } from './utils/WebexDialPad' -import { useTranslation } from 'react-i18next'; - -const dialPadButtonTexts = [ - { - value: '1', - letters: undefined, - }, - { - value: '2', - letters: 'ABC', - }, - { - value: '3', - letters: 'DEF', - }, - { - value: '4', - letters: 'GHI', - }, - { - value: '5', - letters: 'JKL', - }, - { - value: '6', - letters: 'MNO', - }, - { - value: '7', - letters: 'PQRS', - }, - { - value: '8', - letters: 'TUV', - }, - { - value: '9', - letters: 'WXYZ', - }, - { - value: '*', - letters: ',', - }, - { - value: '0', - letters: '+', - }, - { - value: '#', - letters: undefined, - }, -]; - -export interface INumPadProps { - onButtonPress: (value: string) => void; - disabled?: boolean; -} - -/** - * Number pad containing 0-9, #, and *. Also contains sub-lettering - * - * @param {INumPadProps} props props for the NumberPad element - * @param {Function} props.onButtonPress callback to be called whenever a button is pressed - * @returns {React.Component} React component - */ -export const NumberPad = ({ - onButtonPress, - disabled = false, -}: INumPadProps): JSX.Element => { - const [cssClasses] = useWebexClasses('number-pad'); - const childrenRef = useRef([]); - const { setFocused, keyboardProps } = - useGridFocus(childrenRef); - const numberPadRef = useRef(null); - const [isNumberPadFocused, setNumberPadFocused] = useState(false); - const [buttonPressStart, setButtonPressStart] = useState(0); - const NUMBER_PAD_FOCUSED = 'NumberPadFocused'; - const SEARCH_INPUT_FOCUSED = 'SearchInputFocused'; - const [timeoutID, setTimeoutID] = useState(); - const { t } = useTranslation(); - - const onPress = (value: string) => { - //Will pass the primary value of the dialpad button - //If button pressed is other than '0' or '*', - //If the button pressed is '0' or '*' but the duration of press is less than our predetermined duration of press to consider it as a long press. - if (!longPressHandledValues.includes(value) || (longPressHandledValues.includes(value) && (Date.now() - buttonPressStart) < longPressDuration)) { - timeoutID && clearTimeout(timeoutID); - onButtonPress(value); - } - } - - const onPressStart = (value: string, letters: string | undefined) => { - //Storing the exact time when the press starts - setButtonPressStart(Date.now()); - //Will set the timer for long press only for '0' and '*' buttons in dialpad - if (longPressHandledValues.includes(value)) { - let timer = setTimeout(() => { - // If the duration of press exceeds or is equal to our predetermined duration (duration after which we will consider a press as long press) - // will automatically set the search input value to secondary content of dialpad element i.e letters. - if ((Date.now() - buttonPressStart) >= longPressDuration) { - letters && onButtonPress(letters); - clearTimeout(timer); - } - }, longPressDuration); - setTimeoutID(timer); - } - } - - useEffect(() => { - const handleFocusIn = (event: FocusEvent) => { - if (numberPadRef.current?.contains(event.target as Node)) { - const focusedButtonValue = (event.target as HTMLButtonElement)?.textContent; - if (focusedButtonValue === '1') { - setNumberPadFocused(true); - localStorage.setItem(NUMBER_PAD_FOCUSED, JSON.stringify(true)); - window.dispatchEvent(new Event('storage')); - } else { - setNumberPadFocused(false); - localStorage.removeItem(NUMBER_PAD_FOCUSED); - } - } else { - setNumberPadFocused(false); - localStorage.removeItem(NUMBER_PAD_FOCUSED); - } - }; - - document.addEventListener('focusin', handleFocusIn); - - return () => { - document.removeEventListener('focusin', handleFocusIn); - }; - }, []); - - - useEffect(() => { - // handler object - const handleEvent = (event: KeyboardEvent) => { - if (numberPadRef.current?.contains(event.target as Node)) { - if (event.key === "Tab" && event.shiftKey) { - localStorage.setItem(SEARCH_INPUT_FOCUSED, JSON.stringify(true)); - window.dispatchEvent(new Event('storage')); - } else { - localStorage.removeItem(SEARCH_INPUT_FOCUSED); - } - } else { - localStorage.removeItem(SEARCH_INPUT_FOCUSED); - } - }; - - // register handler - window.addEventListener('keyup', handleEvent); - - // unregister handler - return () => { - window.removeEventListener('keyup', handleEvent); - }; - }, []); - - useEffect(() => { - return () => { - // Clear timeout on unmount to prevent memory leaks - if (timeoutID) { - clearTimeout(timeoutID); - } - }; - }, []); - - - return ( - // eslint-disable-next-line react/jsx-props-no-spreading -
- {dialPadButtonTexts.map(({ value, letters }, index) => ( - { - onPress(value) - }} - ref={(ref: HTMLButtonElement) => { - childrenRef.current[index] = ref; - }} - onFocus={() => { - setFocused(index); - setNumberPadFocused(true); - }} - onBlur={() => { - setFocused(undefined); - setNumberPadFocused(false); - }} - disabled={disabled} - onPressStart={() => { - onPressStart(value, letters) - }} - /> - ))} -
- ); -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.scss b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.scss deleted file mode 100644 index 0dcbab220..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.scss +++ /dev/null @@ -1,18 +0,0 @@ -$C: wxc-call-select-popover; - -.#{$C} { - - &__item { - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - &__item-type { - text-transform: capitalize; - - &:after { - content: "\00a0 "; - } - } -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.tsx b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.tsx deleted file mode 100644 index 85872c2d9..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/CallSelectPopover.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { - ListItemBase, - ListNext, - PopoverNext as Popover -} from '@momentum-ui/react-collaboration'; -import { IWebexIntCallableEntity } from '@webex/component-adapter-interfaces/dist/esm/src'; -import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; -import useWebexClasses from '../hooks/useWebexClasses'; -import './CallSelectPopover.scss'; -import './SearchContactsList.styles.scss'; - -interface ICallSelectPopoverProps { - callables: IWebexIntCallableEntity[]; - isVideo?: boolean; - children: React.ReactElement; - makeCall?: (address: string, isVideo?: boolean, label?: string) => void; - label?: string; - onHide?: () => void; - buttonRef?: React.RefObject; // Add buttonRef property -} - -export interface ICallSelectPopoverHandle { - hidePopover: () => void; -} - -/** - * - * @param {ICallSelectPopoverProps} props - * @param props.callables all callable addresses - * @param props.isVideo whether a call initialized from this popover will be a audio or video call - * @param props.children button that controls showing the popover - */ -export const CallSelectPopover = forwardRef< - ICallSelectPopoverHandle, - ICallSelectPopoverProps ->(({ callables, isVideo, children, makeCall, label, onHide, buttonRef }, ref) => { - const [cssClasses, sc] = useWebexClasses('call-select-popover'); - const [instance, setInstance] = useState(); - const channelLabel = 'channel'; - const searchPadLabel = 'searchpad'; - const channelMembersSearch = 'Search channel members'; - useImperativeHandle(ref, () => ({ - hidePopover() { - instance?.hide(); - }, - })); - - useEffect(() => { - const handleKeyPress = (event: KeyboardEvent) => { - if (event.key === 'Escape') { - console.log('Escape key pressed') - instance?.hide(); - } - }; - - const buttonElement = buttonRef?.current; - buttonElement?.addEventListener('keydown', handleKeyPress); - - return () => { - buttonElement?.removeEventListener('keydown', handleKeyPress); - }; - }, [instance]); - - useEffect(() => { - const handleListItemKeyPress = (event: KeyboardEvent) => { - if (event.key === 'Escape') { - event.stopPropagation(); // Stop event propagation - instance?.hide(); - } - }; - - const observer = new MutationObserver(() => { - const listItems = document.querySelectorAll('.md-modal-container-wrapper .md-list-item-base-wrapper'); - listItems.forEach(item => { - item.addEventListener('keydown', handleListItemKeyPress as EventListener); - }); - }); - - if (instance) { - observer.observe(document.body, { childList: true, subtree: true }); - } - - return () => { - observer.disconnect(); - }; - }, [instance, buttonRef]); - - const handleHide = () => { - if (onHide) { - onHide(); - } - }; - - if (callables.length === 1) { - return React.cloneElement(children, { - onPress: () => makeCall && makeCall(callables[0].address, isVideo, label == channelMembersSearch ? channelLabel : searchPadLabel), - }); - } - - return ( - - - {callables.map((item, callableIndex) => ( - makeCall && makeCall(item.address, isVideo, label == channelMembersSearch ? channelLabel : searchPadLabel)} - > -
- {item.type}: - {item.address} -
-
- ))} -
-
- ); -}); - -CallSelectPopover.defaultProps = { - isVideo: false, -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.scss b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.scss deleted file mode 100644 index 8ddabb39c..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.scss +++ /dev/null @@ -1,16 +0,0 @@ -$C: wxc-search-contacts-item; - -.#{$C} { - - &__actions { - display: none; - } - - &:hover, - &:focus, - &.active { - .#{$C}__actions { - display: inline-flex; - } - } -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.tsx b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.tsx deleted file mode 100644 index 35f9dd90e..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsItem.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { - AvatarNext, - ButtonCircle, - Flex, ListItemBase, - ListItemBaseSection -} from '@momentum-ui/react-collaboration'; -import { IWebexIntContact } from '@webex/component-adapter-interfaces/dist/esm/src'; -import React, { useCallback, useEffect, useRef } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useLazyLoadAvatarUrl } from '../hooks/useLazyLoadAvatarUrl'; -import useWebexClasses from '../hooks/useWebexClasses'; -import { removeBracketsAndContent } from '../utils/avatarInitials'; -import { - CallSelectPopover, - ICallSelectPopoverHandle -} from './CallSelectPopover'; -import './SearchContactsItem.scss'; - -type SearchContactsItemProps = { - user: IWebexIntContact; - index: number; - onPress?: (user: IWebexIntContact) => void; - isSelected?: boolean; - style?: React.CSSProperties; - makeCall?: (address: string, isVideo?: boolean, label?: string) => void; - label?: string -}; - -/** - * User object that appears in the search contacts list. On hover will show audio and video calling buttons. - * When clicking one of them, a dropdown appears with the possible call addresses if multiple exist. - * If the user only has one callable address, it will immediately call that one address. - * - * @param {SearchContactsItemProps} props - * @param props.style optional inline styles - * @param props.user user to show call options for - * @param props.index index within the list - * @param props.isSelected whether it is selected within the list - * @param props.onPress action to perform when the user list item is pressed - */ -export const SearchContactsItem = ({ - user, - index, - onPress = () => {}, - isSelected = false, - style = undefined, - makeCall, - label -}: SearchContactsItemProps) => { - const { t } = useTranslation('WebexSearchContacts'); - - const [imageUrl] = useLazyLoadAvatarUrl(user.id, user.fetchAvatarUrl); - - const filteredEmails = user.emailAddresses && user.emailAddresses.length > 0 ? user.emailAddresses.filter(email => email.address !== undefined && email.address !== null && email.address.trim() !== '') : user.emailAddresses; - const filteredphoneNumbers = user.phoneNumbers && user.phoneNumbers.length > 0 ? user.phoneNumbers.filter(number => number.address !== undefined && number.address !== null && number.address.trim() !== '') : user.phoneNumbers; - const callables = [...filteredphoneNumbers, ...filteredEmails]; - const hasNoAddress = callables.length === 0 ? true : false; - const [cssClasses, sc] = useWebexClasses('search-contacts-item'); - - const audioCallRef = useRef(null); - const videoCallRef = useRef(null); - const audioButtonRef = useRef(null); - const videoButtonRef = useRef(null); - - const onAudioCallButtonPress = useCallback(() => { - videoCallRef?.current?.hidePopover(); - onPress(user); - }, [videoCallRef, user, onPress]); - - const onVideoCallButtonPress = useCallback(() => { - audioCallRef?.current?.hidePopover(); - onPress(user); - }, [audioCallRef, user, onPress]); - - useEffect(() => { - if (!isSelected) { - videoCallRef?.current?.hidePopover(); - audioCallRef?.current?.hidePopover(); - } - }, [audioCallRef, videoCallRef, isSelected]); - - const handlePopoverHideForAudio = useCallback(() => { - audioButtonRef.current?.focus(); - }, []); - - const handlePopoverHideforVideo = useCallback(() => { - videoButtonRef.current?.focus(); - }, []); - - return ( - onPress(user)} - aria-label={`${(user.name)}, ${t('dialpadListFocusButton')}`} - > - - - - {user.name} - - - - - - - - - - - - - - - - - - - - ); -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsList.styles.scss b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsList.styles.scss deleted file mode 100644 index 40eb43be9..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsList.styles.scss +++ /dev/null @@ -1,30 +0,0 @@ -$C: wxc-search-contacts-list; - -.#{$C} { - - &--empty { - svg { - flex-shrink: 0; - } - - &__text.md-text-wrapper { - font-size: 14px; - color: var(--theme-text-secondary-normal); - } - } - - &__loading { - display: flex; - justify-content: center; - margin: 39px 0; - } - - &__source-header:first-letter { - text-transform: lowercase; - - &:first-letter { - text-transform: capitalize; - } - } - -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsListEmpty.tsx b/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsListEmpty.tsx deleted file mode 100644 index e39cb5b15..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/SearchContacts/SearchContactsListEmpty.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Flex, Text } from '@momentum-ui/react-collaboration'; -import React from 'react'; -import useWebexClasses from '../hooks/useWebexClasses'; - -type SearchContactsListEmptyProps = { - noContactsFoundMessage: string; - style?: React.CSSProperties; -}; - -/** - * - * @param root0 - * @param root0.noContactsFoundMessage - * @param root0.style - */ -export const SearchContactsListEmpty = ({ - noContactsFoundMessage, - style = undefined, -}: SearchContactsListEmptyProps) => { - const [cssClasses, sc] = useWebexClasses('search-contacts-list--empty'); - - return ( - - - - - - - - - - - - {noContactsFoundMessage} - - - ); -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/hooks/useGridFocus.ts b/packages/node_modules/@webex/widget-number-pad/src/hooks/useGridFocus.ts deleted file mode 100644 index f0dde7f8e..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/hooks/useGridFocus.ts +++ /dev/null @@ -1,53 +0,0 @@ -import React, { useCallback, useEffect, useState } from 'react'; -import { useKeyboard } from '@react-aria/interactions'; - -export const useGridFocus = ( - childrenRef: React.MutableRefObject -) => { - const [focused, setFocused] = useState(undefined); - useEffect(() => { - if (focused !== undefined && childrenRef?.current[focused]) { - childrenRef.current[focused].focus(); - } - }, [focused, childrenRef]); - - const updateFocusedState = useCallback( - (prevState: number | undefined, offset: number) => { - if (prevState === undefined) { - return undefined; - } - return ( - (childrenRef.current.length + prevState + offset) % - childrenRef.current.length - ); - }, - [childrenRef] - ); - - const { keyboardProps } = useKeyboard({ - onKeyDown: (e) => { - switch (e.key) { - case 'ArrowUp': - e.preventDefault(); - setFocused((prevState) => updateFocusedState(prevState, -3)); - break; - case 'ArrowLeft': - e.preventDefault(); - setFocused((prevState) => updateFocusedState(prevState, -1)); - break; - case 'ArrowDown': - e.preventDefault(); - setFocused((prevState) => updateFocusedState(prevState, 3)); - break; - case 'ArrowRight': - e.preventDefault(); - setFocused((prevState) => updateFocusedState(prevState, 1)); - break; - default: - break; - } - }, - }); - - return { focused, setFocused, keyboardProps }; -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/hooks/useLazyLoadAvatarUrl.ts b/packages/node_modules/@webex/widget-number-pad/src/hooks/useLazyLoadAvatarUrl.ts deleted file mode 100644 index 8fbb03893..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/hooks/useLazyLoadAvatarUrl.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; - -/** - * Handles the lazy loading of an avatar source url - * - * @param {string} userId user's id - * @param {() => Promise} fetchAvatarUrlFn function to call to fetch the avatar url - * @returns {[string | undefined]} array containing url of the avatar image - */ -export const useLazyLoadAvatarUrl = ( - userId: string, - fetchAvatarUrlFn?: () => Promise -) => { - const [imageUrl, setImageUrl] = useState(); - const fetchUserAvatar = useCallback(async () => { - if (!fetchAvatarUrlFn) return; - const url = await fetchAvatarUrlFn(); - setImageUrl(url); - }, [fetchAvatarUrlFn]); - useEffect(() => { - fetchUserAvatar(); - }, [userId, fetchUserAvatar]); - - return [imageUrl]; -}; diff --git a/packages/node_modules/@webex/widget-number-pad/src/hooks/useMakeCall.ts b/packages/node_modules/@webex/widget-number-pad/src/hooks/useMakeCall.ts deleted file mode 100644 index b703c6d8b..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/hooks/useMakeCall.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useCallback } from 'react'; -// import { AdapterContext } from '../contexts/AdapterContext'; -import Logger from "../utils/Logger"; -export const useMakeCall = (webexCrosslaunchtoken: string) => { - //const ctx = useContext(AdapterContext); - - const makeCall = useCallback( - (address: string, isVideo?: boolean) => { - return makeCrossLaunchCall(address, !!isVideo, webexCrosslaunchtoken); - }, - [makeCrossLaunchCall] - ); - - return [makeCall]; -}; - - -export async function makeCrossLaunchCall(address: string, isAudio = false, webexCrosslaunchtoken: string) { - address = address.replace(/ /g, ""); - const url = `webextel://${address}`; - //const crossLaunchCallToken = await getCrossLaunchToken(); - const callUrl = new URL(url); - - // TODO: add check for mobile and if audio calls are enabled - callUrl.searchParams.append('jws', webexCrosslaunchtoken); - callUrl.searchParams.append('isAudio', String(!isAudio)); - Logger.info( - `Making ${isAudio ? 'audio' : 'video'} call to address ${address}` - ); - window.open(callUrl.href); -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-number-pad/src/hooks/useWebexClasses.ts b/packages/node_modules/@webex/widget-number-pad/src/hooks/useWebexClasses.ts deleted file mode 100644 index 0cd806520..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/hooks/useWebexClasses.ts +++ /dev/null @@ -1,48 +0,0 @@ -import classNames from 'classnames'; - -const WEBEX_COMPONENTS_CLASS_PREFIX = 'wxc'; - -/** - * Builds a string of css class names for webex components - * - * @param {string} classBaseName Component class base name - * @param {string} [userClassName] Custom CSS class to apply - * @param {object} otherClasses Other optional classes with prefix - * @returns {[string, Function]} Classes and a prefix function - */ -export default function useWebexClasses( - classBaseName: string, - userClassName?: string, - otherClasses?: { - [key: string]: string | boolean; - } -) { - const userClassNames = Array.isArray(userClassName) - ? userClassName - : [userClassName]; - - const cssClasses = classNames( - 'wxc', - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}`, - ...userClassNames, - { - ...Object.fromEntries( - Object.entries(otherClasses || {}).map(([key, val]) => [ - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}--${key}`, - val, - ]) - ), - } - ); - - const sc = (subclass: string, modifiers: string[] = []) => { - const n = `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}__${subclass}`; - - return classNames( - n, - modifiers.map((m) => `${n}--${m}`) - ); - }; - - return [cssClasses, sc] as const; -} diff --git a/packages/node_modules/@webex/widget-number-pad/src/index.ts b/packages/node_modules/@webex/widget-number-pad/src/index.ts deleted file mode 100644 index 08f3d7e65..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { NumberPad } from '@webex/widget-number-pad/src/NumberPad'; -export {CallButtons} from '@webex/widget-number-pad/src/CallButtons/CallButtons'; -export {SearchContactsItem} from '@webex/widget-number-pad/src/SearchContacts/SearchContactsItem'; -export {SearchContactsListEmpty} from '@webex/widget-number-pad/src/SearchContacts/SearchContactsListEmpty'; -export {CallSelectPopover} from '@webex/widget-number-pad/src/SearchContacts/CallSelectPopover'; diff --git a/packages/node_modules/@webex/widget-number-pad/src/utils/Logger.ts b/packages/node_modules/@webex/widget-number-pad/src/utils/Logger.ts deleted file mode 100644 index a3838f979..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/utils/Logger.ts +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - * @param error - */ -export function formatError(error: any) { - if (!error) { - return ''; - } - - if (error.stack) { - return `fileName: '${error.fileName}', name: '${error.name}' lineNumber:${error.lineNumber} columnNumber:${error.columnNumber} message:'${error.message}'.`; - } - - if (error.message) { - return error.message; - } - return JSON.stringify(error); - } - - /** - * - * @param text - * @param leadingCharactersToKeep - */ - export function concise(text = '', leadingCharactersToKeep = 32) { - if (text.length > leadingCharactersToKeep) { - return `${text.substring(0, leadingCharactersToKeep - 1)}...`; - } - return text; - // return text ? (text.length > leadingCharactersToKeep ? text.substring(0, leadingCharactersToKeep - 1) + '...' : text) : ''; - } - - export default class Logger { - static log(level: string, msg: string) { - console.log(`${new Date().toISOString()} [${level}] ${msg}\n`); - } - - static debug(msg: string) { - Logger.log('debug', msg); - } - - static info(msg: string) { - Logger.log('info', msg); - } - - static error(msg: string) { - Logger.log('error', msg); - } - } - \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-number-pad/src/utils/WebexDialPad.ts b/packages/node_modules/@webex/widget-number-pad/src/utils/WebexDialPad.ts deleted file mode 100644 index 03513d9c6..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/utils/WebexDialPad.ts +++ /dev/null @@ -1,4 +0,0 @@ -//Duration at or after which a button press will be considered as long press -export const longPressDuration = 700; -//Dialpad buttons for which long press will be handled -export const longPressHandledValues = ['*', '0']; \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-number-pad/src/utils/avatarInitials.ts b/packages/node_modules/@webex/widget-number-pad/src/utils/avatarInitials.ts deleted file mode 100644 index 2b1dbb198..000000000 --- a/packages/node_modules/@webex/widget-number-pad/src/utils/avatarInitials.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function removeBracketsAndContent(str: string): string { - if (str?.match(/^[+\d]/)) { - return "#"; - } - const words = str?.replace(/ *\([^)]*\) */g, ' ').replace(/ *\(\S*/g, '').replace(/\)+/g, '').replace(/\s+/g, ' ').trim().split(' '); - const filteredWords = words?.filter(word => /^[a-zA-Z0-9]/.test(word)); - let initials = ''; - if (filteredWords?.length > 0) { - initials += filteredWords[0][0].toUpperCase(); - if (filteredWords?.length > 1) { - initials += filteredWords[filteredWords.length - 1][0].toUpperCase(); - } - } - if(initials?.length == 0 && str?.length > 0) { - initials += str[0]; - } - return initials; - - } diff --git a/packages/node_modules/@webex/widget-speed-dial/package.json b/packages/node_modules/@webex/widget-speed-dial/package.json deleted file mode 100644 index 398fc9eba..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@webex/widget-speed-dial", - "description": "widget speed dial", - "main": "./dist/cjs/index.ts", - "src": "./src/index.ts", - "module": "./dist/es/index.ts", - "keywords": [], - "author": "devsupport@webex.com", - "license": "MIT", - "dependencies": { - "@formatjs/intl-pluralrules": "^1.5.4", - "@formatjs/intl-relativetimeformat": "^4.5.11", - "@momentum-ui/react-collaboration": "26.82.1" - }, - "repository": "https://github.com/webex/react-widgets", - "files": [ - "src", - "dist", - "cjs", - "es" - ], - "version": "0.50.0" -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.stories.tsx b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.stories.tsx deleted file mode 100644 index 7570ebe5a..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-nocheck -import React from 'react'; -import { ComponentStory, ComponentMeta } from '@storybook/react'; - -import { GenericModal } from './GenericModal'; - -export default { - title: 'Components/GenericModal', - component: GenericModal, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = { - isOpen: false, -}; - -export const WithContent = (args) => ( - -); diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.styles.scss deleted file mode 100644 index 3a569a20d..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.styles.scss +++ /dev/null @@ -1,10 +0,0 @@ -$C: wxc-generic-modal; - -.#{$C} { - &__container { - align-items: unset; - } - .md-modal-container-wrapper { - border: 0.0625rem var(--modal-secondary-border-color) var(--modal-secondary-border-color) - } -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.test.tsx b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.test.tsx deleted file mode 100644 index 62c751348..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.test.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import TestRenderer from 'react-test-renderer'; - -import { GenericModal } from './GenericModal'; - -describe('GenericModal', () => { - test('should render - isOpen', () => { - const component = TestRenderer.create(); - - expect(component.toJSON()).toMatchSnapshot(); - }); - test('should render - isRound', () => { - const component = TestRenderer.create(); - - expect(component.toJSON()).toMatchSnapshot(); - }); -}); diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.tsx b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.tsx deleted file mode 100644 index 037a7f8f4..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/GenericModal.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import { ModalContainer, Overlay } from '@momentum-ui/react-collaboration'; - -import useWebexClasses from '../hooks/useWebexClasses'; -import './GenericModal.styles.scss'; - -type IGenericModalProps = { - isOpen?: boolean; - isRound?: boolean; - children?: React.ReactNode; - className?: string; -}; - -/** - * @description The summary of this component. - * @param {IGenericModalProps} props Component props - * @param {boolean} props.isOpen The open state - * @param {boolean} props.isRound The round edgets - * @param {React.ReactNode} props.children The children - * @param {string} props.className Custom class names - * @returns {React.Component} React component - */ -export const GenericModal = ({ - isOpen = false, - isRound = false, - children = undefined, - className = undefined, -}: IGenericModalProps) => { - const [cssClasses, sc] = useWebexClasses('generic-modal'); - return ( -
- {isOpen && ( - - - {children} - - - )} -
- ); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/README.md b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/README.md deleted file mode 100644 index ac9ac7dfc..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# generic-modal - -[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) - -> This is a brief summary. - - -- [Install](#install) -- [Usage](#usage) -- [Contribute](#contribute) -- [Maintainers](#maintainers) -- [License](#license) - -## Install - -```bash -$ -``` - -## Usage - -```js -import GenericModal from './GenericModal'; - -``` - -## Maintainers - -This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/). - -## Contribute - -Pull requests welcome. Please see [CONTRIBUTING.md](https://github.com/webex/webex-calling-sdk/blob/master/CONTRIBUTING.md) for more details. - -## License - -© 2022 Cisco and/or its affiliates. All Rights Reserved. \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/__snapshots__/GenericModal.test.tsx.snap b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/__snapshots__/GenericModal.test.tsx.snap deleted file mode 100644 index 635625bec..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/__snapshots__/GenericModal.test.tsx.snap +++ /dev/null @@ -1,41 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`GenericModal should render - isOpen 1`] = ` -
-
-
-
-
-`; - -exports[`GenericModal should render - isRound 1`] = ` -
-
-
-
-
-`; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/index.ts b/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/index.ts deleted file mode 100644 index ac649221c..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/GenericModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './GenericModal'; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/README.md b/packages/node_modules/@webex/widget-speed-dial/src/README.md deleted file mode 100644 index 20bc82119..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# speed-dials - -[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme) - -> This is a brief summary. - -- [Install](#install) -- [Usage](#usage) -- [Contribute](#contribute) -- [Maintainers](#maintainers) -- [License](#license) - -## Install - -```bash -$ -``` - -## Usage - -```js -import SpeedDials from './SpeedDials'; -``` - -## Maintainers - -This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/). - -## Contribute - -Pull requests welcome. Please see [CONTRIBUTING.md](https://github.com/webex/webex-calling-sdk/blob/master/CONTRIBUTING.md) for more details. - -## License - -© 2022 Cisco and/or its affiliates. All Rights Reserved. diff --git a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.stories.tsx b/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.stories.tsx deleted file mode 100644 index cc311e335..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { ScrubbingBar } from './ScrubbingBar'; - -export default { - title: 'Components/ScrubbingBar', - component: ScrubbingBar, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = {}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.styles.scss deleted file mode 100644 index 36a508efc..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.styles.scss +++ /dev/null @@ -1,47 +0,0 @@ -$C: wxc-voicemail-scrubbing-bar; - -.#{$C} { - $scrubber-thumb-size: 16px; - $track-radius: 5px; - - - flex-grow: 1; - - &__thumb { - width: $scrubber-thumb-size; - height: $scrubber-thumb-size; - border-radius: 100%; - background-color: var(--theme-background-solid-primary-normal); - border: 1px solid var(--theme-outline-primary-normal); - box-shadow: var(--md-globals-elevation-1); - cursor: pointer; - position: absolute; - top: 50%; - transform: translateY(-50%); - } - - &__track { - position: relative; - height: 2px; - - &::before { - content: ""; - position: absolute; - top: 50%; - transform: translateY(-50%); - width: 100%; - height: 100%; - border-radius: $track-radius; - background-color: var(--theme-control-inactive-normal); - } - } - - &__viewed { - position: absolute; - left: 0; - top: 0; - height: 100%; - border-radius: $track-radius; - background-color: var(--theme-control-active-normal); - } -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.tsx b/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.tsx deleted file mode 100644 index 6c6357a18..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/ScrubbingBar.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* eslint-disable react/jsx-props-no-spreading */ -/* eslint-disable react/destructuring-assignment */ -import { SliderState, SliderStateOptions, useSliderState } from 'react-stately'; - -import { - mergeProps, - useFocusRing, - useNumberFormatter, - useSlider, - useSliderThumb, - VisuallyHidden, -} from 'react-aria'; -import React, { MutableRefObject, useRef } from 'react'; -import useWebexClasses from './hooks/useWebexClasses'; -import './ScrubbingBar.styles.scss'; - -type IScrubbingBarThumbProps = { - state: SliderState; - index: number; - trackRef: MutableRefObject; - className?: string; -}; - -/** - * - * @param props - * @param props.state - * @param props.trackRef - * @param props.index - * @param props.className - */ -const ScrubbingBarThumb = ({ - state, - trackRef, - index, - className = undefined, -}: IScrubbingBarThumbProps) => { - const inputRef = useRef(null); - const { thumbProps, inputProps } = useSliderThumb( - { - index, - trackRef, - inputRef, - }, - state - ); - - const { focusProps, isFocusVisible } = useFocusRing(); - return ( -
- - - -
- ); -}; - -export interface IScrubbingBarProps - extends Partial> { - numberFormatOptions?: unknown; -} - -export const ScrubbingBar = ({ ...rest }: IScrubbingBarProps) => { - const [cssClasses, sc] = useWebexClasses( - 'voicemail-scrubbing-bar', - undefined, - { - disabled: !!rest.isDisabled, - } - ); - const trackRef = React.useRef(null); - const numberFormatted = useNumberFormatter(); - const state = useSliderState({ - numberFormatter: numberFormatted, - ...rest, - }); - const { groupProps, trackProps } = useSlider(rest, state, trackRef); - - return ( -
-
-
- -
-
- ); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDial.utils.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDial.utils.tsx deleted file mode 100644 index c014e30dd..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDial.utils.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { Message } from '@momentum-ui/react-collaboration/dist/esm/components/InputMessage/InputMessage.types'; -import { FieldError } from 'react-hook-form'; -import { IFormData, ISelectItems, PhoneType, PhoneValueTypes } from './SpeedDialForm.types'; - -/** - * Handles converting field error to message. - * - * @param {FieldError} e The field error message - * @returns {Message} The field error to message - */ -export function fieldErrorToMessage(e: FieldError): Message { - return { message: e.message as string, level: 'error' }; -} - -/** - * Phone Options is a list of phones for existing contact - * - * @param {IFormData} contact The contact phones to populate number select. - * @returns {Array} An array of phone nubmers to select. - */ -export const getPhoneOptions = (contact: IFormData) => { - const items = []; - - - - if (contact.emailAddresses) { - items.push({ - key: contact.emailAddresses[0].type, - value: PhoneValueTypes.MAIL+`: ${contact.emailAddresses[0].address}`, - }); - } - - if (contact.phoneNumbers) { - contact.phoneNumbers?.forEach((n: any) => { - if (n.type === PhoneType.WORK) { - items.push({ - key: n.type, - value: PhoneValueTypes.WORK +`: ${n.address}`, - }); - } - else if (n.type === PhoneType.MOBILE) { - items.push({ - key: n.type, - value: PhoneValueTypes.MOBILE+`: ${n.address}`, - }); - } - }); - } - return items; -}; - -/** - * Handles setting the correct properties on contact when creating new SpeedDial. - * - * @param {IFormData} data The speed dial contact - * @returns {IFormData} Returns contact with correct call types. - */ -export const setPhoneOptions = (data: IFormData) => { - const contact = { ...data }; - if (!contact.callType) { - contact.callType = PhoneType.HANDSET; - } - - if (contact.phoneNumbers) { - contact.phoneNumbers?.forEach((n: any) => { - if (n.type === PhoneType.WORK) { - contact.businessPhones = contact.businessPhones || [] - contact.businessPhones.push(n.address); - } - else if (n.type === PhoneType.MOBILE) { - contact.mobilePhone = n.address; - } - }); - } - return contact; -}; - -/** - * Get phone types for options select - * - * @param {array} types Array of strings - * @returns {ISelectItems[]} array of select option items. - */ -export const getPhoneTypeOptions = (types: string[]): ISelectItems[] => - [...types].map((type: string) => ({ - id: type.toLowerCase(), - value: type, - })); - -/** - * Handle abbriviating last name. - * - * @param {string} name The display - * @returns {string} Formatted first and last name. - */ -export function abbrDisplayName(name: string) { - if (name) { - const names: string[] = name.split(/\s+/); - const isNameContainsComma = names?.some(element => element.startsWith(',')); - if(isNameContainsComma) { - const [array1, array2] = processArray(names); - - const resultArray1 = array1.map(capitalizeFirstLetter); - const resultArray2 = convertToUpperCaseWithDot(array2); - - const resultString = resultArray1.concat(resultArray2).join(' '); - return resultString; - } - else { - if (names[1]) { - //Added condition to avoid adding undefined if don't have last name - names[1] = `${names[1].substr(0, 1)}.`; - } - return names.join(' '); - } - } -} - -function processArray(originalArray: string[]): [string[], string[]] { - const array1: string[] = []; - const array2: string[] = []; - - let foundComma = false; - let wordsAfterComma: string[] = []; - - for (const element of originalArray) { - if (element.startsWith(',')) { - foundComma = true; - wordsAfterComma = element.substring(1).split(' '); - } else if (!foundComma) { - array1.push(element); - } else { - wordsAfterComma.push(element); - } - } - - return [array1, wordsAfterComma]; -} - -function capitalizeFirstLetter(word: string): string { - return word.charAt(0).toUpperCase() + word.slice(1); -} - -function convertToUpperCaseWithDot(words: string[]): string[] { - return words.map(word => `${word.charAt(0).toUpperCase()}.`); -} - -export function removeCommaIfNeeded(inputString: string) { - const words = inputString?.split(' '); - const modifiedWords = words?.map(word => { - if (word.startsWith(',')) { - return word.slice(1); - } - return word; - }); - return modifiedWords.join(' '); -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.styles.scss deleted file mode 100644 index 230b66556..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.styles.scss +++ /dev/null @@ -1,38 +0,0 @@ -/* Custom styles */ - -$C: wxc-add-speed-dial; - -.#{$C} { - text-align: center; - position: absolute; - width: 100%; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - - &__add-dial { - background-color: var(--button-primary-background) !important; - margin: 1.5rem auto 0; - font-size: 1rem; - } - - &:hover { - background: var(--theme-background-solid-primary-normal); - color: var(--theme-text-primary-normal); - } - - &__add-text { - color: var(--tab-inactive-text); - } - h3 { - margin-top: 1.5rem; - margin-bottom: 0.3rem; - font-size: 1rem; - } - span { - font-size: 0.875rem; - } - .wxc-add-speed-dial__add-dial span { - color: var(--theme-text-inverted-normal); - } -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.tsx deleted file mode 100644 index e4466b166..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialAddBanner.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { useRef, forwardRef, useEffect, createRef } from 'react'; -import { ButtonPill } from '@momentum-ui/react-collaboration'; -import useWebexClasses from './hooks/useWebexClasses'; -import './SpeedDialAddBanner.styles.scss'; -import { useTranslation } from 'react-i18next'; - -export interface IAddSpeedDial { - addSpeedDial?: () => void; -} - -export const SpeedDialAddBanner = ({ addSpeedDial }: IAddSpeedDial) => { - const [cssClasses, sc] = useWebexClasses('add-speed-dial', undefined, {}); - const { t } = useTranslation('WebexSpeedDials'); - return ( - -
-
- - - - - - - - - -
-

{t('addSpeedBanner.dial.header')}

- {t('addSpeedBanner.desc.header')} - - {t('addSpeedBanner.add.header')} - -
- ) -} - - diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.styles.scss deleted file mode 100644 index fde68e5cd..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.styles.scss +++ /dev/null @@ -1,10 +0,0 @@ -$C: wxc-speed-dial-error-modal; - -.#{$C} { - align-items: unset; - border-radius: 6px; - - > * { - box-sizing: border-box; - } -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.tsx deleted file mode 100644 index cabcba97b..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialErrorModal.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { - ButtonCircle, - ButtonPill, - Flex, - Text -} from '@momentum-ui/react-collaboration'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - - import { GenericModal } from './GenericModal'; -import useWebexClasses from './hooks/useWebexClasses'; -import './SpeedDialErrorModal.styles.scss'; - - type ISpeedDialModalProps = { - headerText?: string; - isOpen?: boolean; - onCancel?: () => void; - children?: React.ReactNode; - errorNotification?: string; - removeSdFailureStorageEvents?: () => void; - refresh?: () => void; - }; - - /** - * When passed in a user, a fullscreen overlay will appear - * - * @param {ISpeedDialModalProps} props Component props - * @param {string} props.headerText Header title for modal - * @param {boolean} props.isOpen Open state of modal - * @param {Function} props.onCancel Callback function when cancel pressed - * @param {React.ReactNode} props.children The children - * @returns {React.Component} React component - */ - export const SpeedDialErrorModal = ({ - isOpen = true, - onCancel = undefined, - children = undefined, - errorNotification, - removeSdFailureStorageEvents, - refresh - }: ISpeedDialModalProps) => { - const [cssClasses, sc] = useWebexClasses('speed-dial-error-modal'); - const { t } = useTranslation('WebexSpeedDials'); - const onClose = () => { - if (onCancel && removeSdFailureStorageEvents && refresh) { - onCancel(); - removeSdFailureStorageEvents(); - refresh(); - } - } - return ( - - - - - - - - - - - {t('errorNotification.error')} - - {t('errorNotification.failureError', { errorNotification })} - - - {t('errorNotification.close')} - - - - - ); - }; - \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.styles.scss deleted file mode 100644 index 9d5045390..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.styles.scss +++ /dev/null @@ -1,155 +0,0 @@ -$C: wxc-speed-dial-form; - -.#{$C} { - flex: 1; - - #phone label, - #mail label { - visibility: hidden; - } - - &--isContact { - #phone label { - visibility: visible; - } - } - - &__preview { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 110px; - - .md-text-wrapper { - margin: 0; - padding: .5rem 0 0; - } - } - - &__footer { - display: flex; - padding: 1.5rem 0 1rem; - } - - - &__input-container { - margin-bottom: 1rem; - position: relative; - display: flex; - justify-content: normal; - align-items: normal; - flex-flow: row wrap; - flex-direction: column; - - &--row { - flex-direction: row; - - > :first-child { - margin-right: 1rem; - } - } - - &--required { - label:before { - content: '*'; - color: var(--theme-text-error-normal); - position: absolute; - left: 0; - } - } - - // For icon in select dropdown - .md-list-item-base-wrapper { - > div { - display: flex; - } - - .md-icon-wrapper { - margin-right: .5rem; - } - } - - .md-text-input-wrapper { - margin: 0; - flex: 1; - - label { - font-size: 14px; - } - } - - .md-select-wrapper { - align-self: stretch; - min-width: unset; - - label { - line-height: normal; - } - - .md-select-dropdown-input { - > span:first-of-type { - display: flex; - min-height: 24px; - } - } - } - - .type_prefrence { - .md-select-overlay { - li { - > div:first-of-type { - display: flex; - min-height: 24px; - svg { - margin-top: 0.33rem; - } - span { - margin-left: 0.5rem; - } - } - } - } - } - - label { - margin-bottom: 0.5rem; - margin-left: 0.75rem; - display: flex; - } - } - - .btn-margin-left { - margin-left: 0.5rem !important; - } -} - -.disablePhoneList { - display: flex; - width: 100%; -} - -.phoneTypeText { - width: 100%; -} - -.phoneTypeTextValue { - width: 85%; -} - -.inUseText { - display: none; - position: absolute; - right: 5%; -} - -.notUsed { - width: 100%; -} - -.md-select-overlay li:hover .inUseText { - display: inline-block; -} - - - diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.tsx deleted file mode 100644 index 0abc1da54..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.tsx +++ /dev/null @@ -1,811 +0,0 @@ -import { - ButtonPill, - Flex, - SelectNext as Select, - TextInput -} from '@momentum-ui/react-collaboration'; -import { Item } from '@react-stately/collections'; -import React, { useEffect, useRef, useState } from 'react'; -import { Controller, useForm } from 'react-hook-form'; -import { useTranslation } from 'react-i18next'; -import { v4 as uuid } from 'uuid'; -import { - fieldErrorToMessage, - getPhoneOptions, - setPhoneOptions -} from './SpeedDial.utils'; -import './SpeedDialForm.styles.scss'; -import { - IFormData, - ISelectItems, - ISpeedDialFormProps, - PhoneType -} from './SpeedDialForm.types'; -import useWebexClasses from './hooks/useWebexClasses'; - -/** - * The form for creating/editing a speed dial. - * - * @param {string} cancelText The text for the cancel button - * @param {string} addText The the text for the add button - * @param {object} data The form data to populate with - * @param {Function} onSubmit Callback function when form submit - * @param {Function} onCancel Callback function when form reset - * @param {boolean} isEdit If the speed dial item is being edited - * @param {boolean} isContact If the speed dial item is existing contact - * @returns {React.Component} SpeedDialForm component - */ -export const SpeedDialForm = ({ - cancelText = 'Cancel', - addText = 'Add', - data = { - id: 'l_'+ uuid(), - givenName: '', - surname: '', - displayName: '', - phone: '', - callType: PhoneType.HANDSET, - phoneType: 'work', - }, - onSubmit = undefined, - onCancel = undefined, - isEdit = false, - isContact = false, - searchText, - usedPhonesList = [], - inUseText = 'in use', - inUsePlaceHolder = 'All available numbers in use', - handleEnterKeyPress = undefined, - headerText -}: ISpeedDialFormProps) => { - const [cssClasses, sc] = useWebexClasses('speed-dial-form', undefined, { - isContact, - isEdit, - }); - const [formData, setFormData] = useState(data); - const { t } = useTranslation('WebexSpeedDials'); - const phoneOptions = getPhoneOptions(formData);// TODO get all types of phone option - const formInputRef = useRef(null); - const formSelectRef = useRef(null); - - if (!formData.phoneType) { - phoneOptions.find((element) => { - if(!(usedPhonesList.includes(element.key))) { - if (element.key === PhoneType.WORK) { - formData.phoneType = PhoneType.WORK - } else if (formData.phoneType != PhoneType.WORK) { - formData.phoneType = element.key; - } - } - }) - } - - // adding searched text - if(!formData.givenName) { - formData.givenName = searchText; - } - - //const phoneTypes: string[] = t('form.phoneTypes', { - // returnObjects: true, - // defaultValue: ['Work', 'Mobile', 'Email', 'Other', 'SIP'], - //}); - //const phoneTypeOptions = getPhoneTypeOptions(phoneTypes); - const phoneTypes: string[] = [ "work", "mobile", "mail", "other", "sip"]; - const phoneTypeOptions = [...phoneTypes].map((type: string) => ({ - id: type, - value: t('form.phoneTypes.'+ type), - })); - - const callTypeOptions: ISelectItems[] = t('form.callTypeOptions', { - returnObjects: true, - defaultValue: [ - { - id: PhoneType.HANDSET, - value: PhoneType.AUDIOCALL, - }, - { - id: PhoneType.VIDEO, - value: PhoneType.VIDEOCALL, - }, - ], - }); - - const processSubmit = (speedDialData: IFormData) => { - if (!speedDialData?.givenName && speedDialData.name) { - const names: string[] = speedDialData.name.split(/\s+/); - speedDialData.givenName = names[0] - //Added condition to avoid adding undefined if don't have last name - if (names[1]) { - // names[1] = `${names[1].substr(0, 1)}.`; - speedDialData.surname = names[1] - } - else { - speedDialData.surname = '' - } - } - - const displayName = `${speedDialData?.givenName} ${speedDialData?.surname ? ',' + speedDialData.surname : ''}`.trim(); - const currentCallAddress = speedDialData?.phone || speedDialData?.mail || speedDialData?.phoneNumbers && speedDialData?.phoneNumbers[0]?.address || speedDialData?.emailAddresses && speedDialData?.emailAddresses[0]?.address; - - //if (formData.phoneType === PhoneType.MAIL) { - // formData.phoneType = 'E' + formData.phoneType - //} - //else if (formData?.phoneType) { - // formData.phoneType = formData?.phoneType.charAt(0).toUpperCase() + formData.phoneType.slice(1); - //} - const phoneType = formData.phoneType; - delete speedDialData.phoneNumbers; - delete speedDialData.emailAddresses; - - const payload = setPhoneOptions({ - ...speedDialData, - displayName, - currentCallAddress, - phoneType - }); - - setFormData(payload); - if (onSubmit) { - onSubmit(payload); - } - }; - {/* Not in use */} - // const getDisplayName = () => { - // const name = formData?.displayName - // ? formData.displayName - // : `${formData?.givenName} ${formData?.surname}`; - // return name.trim(); - // }; - - const { control, handleSubmit, register, reset, formState, setFocus, setValue } = - useForm({ - defaultValues: { - ...data, - phone: formData.phoneType !== PhoneType.MAIL && formData.phoneType !== PhoneType.SIP ? data.currentCallAddress : "", - mail: formData.phoneType === PhoneType.MAIL ? data?.currentCallAddress : "", - sip: formData.phoneType === PhoneType.SIP ? data?.currentCallAddress : "", - }, - mode: 'onChange', - }); - - useEffect(() => { - // Set the initial value of the phoneType select field in the isContact template - if(isContact) { - const initialValue = formData?.phoneType || formData?.mobilePhone; - setValue('phone', initialValue); - } - }, [setValue, formData, isContact]); - - - useEffect(() => { - if (isEdit || ((!isContact && !isEdit))) { - if (formInputRef.current) { - formInputRef.current.focus(); - } - } else if (isContact) { - if (formSelectRef.current) { - formSelectRef.current.querySelector("button")?.focus(); - formSelectRef.current.querySelector("button")?.classList.add('md-focus-ring-wrapper'); - formSelectRef.current.querySelector("button")?.classList.add('children'); - } - } - - }, [isContact, isEdit]) - - - return ( -
- {/* Phone Select Input */} - {isContact && ( -
- ( - - )} - /> -
- )} - - {isEdit && ( - <> - {/* First Name */} -
- ( - { - // setAvatarName(e.currentTarget.value); - setFormData({ - ...formData, - givenName: e.currentTarget.value, - - }); - onChange(e); - }} - ref={formInputRef} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> -
- - {/* Last Name */} -
- ( - { - setFormData({ - ...formData, - surname: e.currentTarget.value, - }); - onChange(e); - }} - ref={ref} - /> - )} - /> -
- - {/* Phone Input */} -
- {/* Phone Type */} - ( - - )} - /> - {/* Phone - Number */} - {formData.phoneType !== PhoneType.MAIL && formData.phoneType !== PhoneType.SIP && ( - ( - { - setFormData({ - ...formData, - phone: e.currentTarget.value, - emailAddresses: "", - sip: "" - }); - setValue("mail", ""); - setValue("sip", ""); - onChange(e); - }} - ref={ref} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> - )} - - {/* Phone - Email */} - {formData.phoneType === PhoneType.MAIL && ( - ( - { - setFormData({ - ...formData, - emailAddresses: e.currentTarget.value, - phone:"", - sip:"" - }); - setValue("phone", ""); - setValue("sip", ""); - onChange(e); - }} - ref={ref} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> - )} - - {/* Phone - SIP */} - {formData.phoneType === PhoneType.SIP && ( - ( - { - setFormData({ - ...formData, - phone: "", - emailAddresses: "", - sip: e.currentTarget.value, - }); - setValue("mail", ""); - setValue("phone", ""); - onChange(e); - }} - ref={ref} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> - )} -
- - )} - - {!isEdit && !isContact && ( - <> - {/* First Name */} -
- ( - { - // setAvatarName(e.currentTarget.value); - setFormData({ - ...formData, - givenName: e.currentTarget.value, - }); - onChange(e); - }} - ref={formInputRef} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> -
- - {/* Last Name */} -
- ( - { - setFormData({ - ...formData, - surname: e.currentTarget.value, - }); - onChange(e); - }} - ref={ref} - /> - )} - /> -
- - {/* Phone Input */} -
- {/* Phone Type */} - ( - - )} - /> - {/* Phone - Number */} - {formData.phoneType !== PhoneType.MAIL && formData.phoneType !== PhoneType.SIP && ( - ( - { - setFormData({ - ...formData, - phone: e.currentTarget.value, - }); - onChange(e); - }} - ref={ref} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> - )} - - {/* Phone - Email */} - {formData.phoneType === PhoneType.MAIL && ( - ( - - )} - /> - )} - - {/* Phone - SIP */} - {formData.phoneType === PhoneType.SIP && ( - ( - { - setFormData({ - ...formData, - phone: e.currentTarget.value, - }); - onChange(e); - }} - ref={ref} - messageArr={ - fieldState.error - ? [fieldErrorToMessage(fieldState.error)] - : [] - } - /> - )} - /> - )} -
- - )} - - {/* Call Type */} -
- ( - - )} - /> -
- - {/* Cancel Submit Actions */} - {/* eslint-disable-next-line react/jsx-props-no-spreading */} - - {/* eslint-disable-next-line react/jsx-props-no-spreading */} - - - - { - if (onCancel) { - onCancel(); - } - reset(); - }} - onKeyDown={handleEnterKeyPress} - > - {cancelText} - - - {addText} - - -
- ); -}; - diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.types.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.types.tsx deleted file mode 100644 index cefb47f13..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialForm.types.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { ISpeedDialRecord } from '@webex/component-adapter-interfaces/dist/cjs/src'; -import React from 'react'; - -/** - * https://docs.microsoft.com/en-us/graph/api/resources/contact?view=graph-rest-1.0#properties - */ -export type IFormData = ISpeedDialRecord; - -export interface ISpeedDialFormProps { - cancelText?: string; - addText?: string; - data?: IFormData; - onSubmit?: (data: IFormData) => void; - onCancel?: () => void; - children?: React.ReactNode; - isContact?: boolean; - isEdit?: boolean; - searchText?: string; - usedPhonesList?: string[]; - inUseText?: string; - inUsePlaceHolder?: string; - handleEnterKeyPress?: (event: React.KeyboardEvent) => void; - headerText?: string; -} - -export interface ISelectItems { - id: string; - value: string; -} - -export enum PhoneType { - WORK = 'work', - MAIL = 'mail', - MOBILE = 'mobile', - HANDSET = 'handset', - VIDEO = 'video', - AUDIOCALL = 'Audio call', - VIDEOCALL = 'Video call', - EMAIL = 'email', - OTHER = 'other', - SIP = 'sip' -} - -export enum SpeedDialView{ - ADDVIEW = 'addView', - SEARCHVIEW = 'searchView', - EDITVIEW = 'editView', - LIST = 'list', - SEARCHADDVIEW = 'searchAddView', - ERRORVIEW = 'errorView' -} - -export enum PhoneValueTypes { - WORK = 'Work', - MOBILE = 'Mobile', - MAIL = 'Mail' -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.styles.scss deleted file mode 100644 index 309ba6f3f..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.styles.scss +++ /dev/null @@ -1,182 +0,0 @@ -$C: wxc-speed-dial-item; - -$name-color: var(--wxc-text-color, black); - -$speed-dial-list-item-background: var(--listitem-background, #ffffff); -$speed-dial-list-item-border: 1px solid var(--scrollbar-track-background, rgba(0, 0, 0, 0.07)); -$speed-dial-list-item-box-shadow: 0 0 4px rgb(0 0 0 / 10%); -$speed-dial-list-item-border-radius: 10px; - -$speed-dial-list-item__actions-border: 1px solid var(--scrollbar-track-background, #dedede); -$speed-dial-list-item__status-color: rgba(0, 0, 0, 0.6); - -$speed-dial-list-width: 500px; -$speed-dial-list-item-width: 105px; -$speed-dial-list-grid-gap: 0.5rem; -$speed-dial-list-grid-template: repeat( - auto-fit, - minmax(min(100% / 4, max(105px, 100% / 5)), 1fr) -); - -$speed-dial-min-width: 110px; -$speed-dial-min-height: 115px; - -.#{$C} { - user-select: none; - position: relative; - background: $speed-dial-list-item-background; - border-radius: $speed-dial-list-item-border-radius; - min-height: $speed-dial-min-height; - display: flex; - align-items: center; - cursor: pointer; - - &__action { - display: none; - } - - - &__drag-handle { - position: absolute; - right: 0; - top: 0; - width: 24px; - min-height: 30px; - display: flex; - text-align: center; - padding-top: .5rem; - } - - &__draggable { - height: 75px; - } - - &__drag-icon { - display: flex; - text-align: center; - visibility: hidden; - cursor: grab; - - svg { - height: 20px; - width: 20px; - } - } - - - &__actions { - border-radius: 50%; - width: 3rem !important; - height: 3rem !important; - color: var(--theme-text-primary-normal); - margin-bottom: .5rem; - position: relative; - } - - &:hover, &:focus, &:active { - .#{$C}__drag-icon { - visibility: visible; - } - - .#{$C}__drag-handle:not(:hover) + .#{$C}__actions { - .#{$C}__avatar { - opacity: 0.1; - } - - .#{$C}__action { - display: block; - position: absolute; - top: 50%; - left: 50%; - transform: translateX(-50%) translateY(-50%); - } - } - } - - &:hover, &--selected { - background: var(--theme-button-secondary-hover); - } - - &:active { - background: var(--theme-button-secondary-pressed); - - .#{$C}__avatar { - opacity: 0 !important; - } - } - - &:disabled { - background: var(--theme-button-secondary-disabled); - } - - &__content { - width: 100%; - } - - &__separator { - margin: .2rem .75rem; - - &:after { - border-color: var(--modal-primary-border-color); - } - } - - &__name { - padding: 0; - margin: 0; - white-space: nowrap; - text-overflow: ellipsis; - max-width: $speed-dial-list-item-width - 5px; - overflow: hidden; - } - - &__deletedName { - padding: 0; - margin-top: 2px; - white-space: nowrap; - text-overflow: ellipsis; - max-width: $speed-dial-list-item-width - 5px; - overflow: hidden; - } - - &__number, - &__status { - color: var(--label-secondary-text); - } - - &__menu ul { - padding-left: 0; - } -} - -.md-theme-darkWebex .wxc-sortable-item { - --theme-grabbing-background: #111111; -} - - -// Sortable item is outside theme provider -.wxc-sortable-item { - --theme-color-50: rgba(52, 146, 235, 1); - --theme-color-60: rgba(17, 112, 207, 1); - --theme-grabbing-background: #E3E3E3; - - .#{$C} { - background: var(--theme-grabbing-background) !important; - //box-shadow: var(--md-theme-globals-elevation-2, 0 0.5rem 1rem rgba(0, 0, 0, 0.2), 0 0 0.0625rem rgba(0, 0, 0, 0.11)); - border: 2px solid var(--theme-color-60); - box-shadow: 0 1px 6px -1px var(--theme-color-60); - } - - .#{$C}__drag-handle { - visibility: visible; - cursor: grabbing; - } - - .#{$C}__drag-icon { - visibility: visible; - color: var(--theme-color-60); - } -} - - - diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.tsx deleted file mode 100644 index 9ca995ed2..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialItem.tsx +++ /dev/null @@ -1,486 +0,0 @@ -// @ts-nocheck -import { - AvatarNext as Avatar, - Flex, - ListHeader, - MenuNext as Menu, - PopoverNext as Popover, - Text -} from '@momentum-ui/react-collaboration'; -import { Item, Section } from '@react-stately/collections'; -import { ISpeedDialRecord } from '@webex/component-adapter-interfaces/dist/cjs'; -import React, { useCallback, useRef, useEffect, useState, forwardRef, useImperativeHandle } from 'react'; -import { ContextMenu, ContextMenuTrigger } from 'react-contextmenu'; -import { useTranslation } from 'react-i18next'; - -import useWebexClasses from './hooks/useWebexClasses'; - -import { abbrDisplayName, removeCommaIfNeeded } from './SpeedDial.utils'; -import './SpeedDialItem.styles.scss'; -import { ISpeedDialItem } from './SpeedDials.types'; -import { removeBracketsAndContent } from './utils/avatarInitials'; - -export interface ISpeedDialProps { - id: string; - /** The audio call for speed dial for the item */ - isAudio?: boolean; - /** The avatar image for the item */ - item: ISpeedDialItem; - /** The index for reference */ - itemIndex?: number; - /** Triggered when speed dial item is pressed */ - onPress?: (item: ISpeedDialRecord) => void; - /** Triggered when audio call action is pressed */ - onAudioCallPress?: (item: ISpeedDialRecord) => void; - /** Triggered when video call action is pressed */ - onVideoCallPress?: (item: ISpeedDialRecord) => void; - /** Triggered when remove action is pressed */ - onRemovePress?: (id: string) => void; - /** Triggered when edit action is pressed */ - onEditPress?: (item: ISpeedDialRecord) => void; - - children?: React.ReactNode; - /** To handle reinitialization of aria label content after item has been rearranged */ - selectedNodeForRearange: Element | undefined; -} - -/** - * Speed Dial Item component renders individual entries. - * - * @param {ISpeedDialProps} obj The props for the component - * @param {number} obj.itemIndex The index of the speed dial - * @param {Function} obj.onVideoCallPress Handle when item video call button is pressed - * @param {Function} obj.onAudioCallPress Handle when item audio call button is pressed - * @param {Function} obj.onRemovePress Triggered when remove action is pressed - * @param {Function} obj.onEditPress Triggered when edit action is pressed - * @param {React.ReactNode} obj.children Drag handle component - * @returns {React.Component} A CallHistoryItem for rendering - */ -export const SpeedDialItem = forwardRef(({ - id, - item, - isAudio = false, - itemIndex = undefined, - onPress = undefined, - onAudioCallPress = undefined, - onVideoCallPress = undefined, - onEditPress = undefined, - onRemovePress = undefined, - children = undefined, -}: ISpeedDialProps, ref) => { - const [classes, sc] = useWebexClasses('speed-dial-item', undefined, {}); - const { t } = useTranslation('WebexSpeedDials'); - const actionBtnRef = useRef(); - const contextMenuId = `${id}-context-menu`; - const removeLabel = t('item.remove.label'); - const editLabel = t('item.edit.label'); - const audioCallLabel = t('item.audioCall.label'); - const videoCallLabel = t('item.videoCall.label'); - const outlookRemoveLabel = t('item.removeOutLook.label'); - const deleteOutlookUserLabel = t('item.deleteOutlookUser.label'); - const originalContactDeletedLabel = t('item.originalContactDeleted.label'); - const contextTriggerRef = useRef(null); - const submenuItemRef = useRef(null); - const contactRef = useRef(null); - const [isSubMenuVisible, setSubMenuVisible] = useState(false); - const [isContextMenuVisible, setIsContextMenuVisible] = useState(false); - const actionsRef = useRef(null); - const dragandDropActionRef = useRef(null); - - useImperativeHandle(ref, () => ({ - handleEnterKey: (e) => { - if(item?.isOutlookDeleted) { - if (onRemovePress) { - onRemovePress(item.id); - } - - } else { - if (onPress) { - onPress(item) - } - } - }, - handleContextMenuTrigger: (e) => { - if (contactRef.current) { - const position = { - isVisible: true, - x: contactRef.current.offsetLeft + 92, - y: item?.isOutlookDeleted ? contactRef.current.offsetTop + 91 : contactRef.current.offsetTop - 30, - }; - contextTriggerRef.current?.setState(position); - - // Prevent the default browser context menu - e.preventDefault(); - - if (submenuItemRef.current) { - setTimeout(() => { - submenuItemRef.current.focus(); - }, 20); // 20ms delay - } - } - }, - handleContextMenuClose: (e) => { - if (contactRef.current) { - contextTriggerRef.current?.setState({ - isVisible: false, - selectedItem: null, - forceSubMenuOpen: false, - }); - - // Prevent the default browser context menu - e.preventDefault(); - } - }, - setSubMenuVisible, - setIsContextMenuVisible, - triggerHoverEffect: () => { - let avatar: HTMLDivElement = actionsRef.current?.childNodes[0]; - let svg: HTMLDivElement = actionsRef.current?.childNodes[1]; - avatar.style.opacity = 0.1; - svg.style.display = "block"; - svg.style.position = "absolute"; - svg.style.top = "50%"; - svg.style.left = "50%"; - svg.style.transform = "translateX(-50%) translateY(-50%)"; - if(contactRef){ - contactRef.current.style.background = "var(--theme-button-inverted-hover)"; - } - if (item?.isOutlookDeleted) { - let p: HTMLParagraphElement = svg?.childNodes[0]; - p.style.marginTop = "1.875rem"; - p.style.color = "var(--mds-color-theme-text-accent-normal)"; - } - if (dragandDropActionRef.current) { - const svgElement: HTMLDivElement = dragandDropActionRef.current.querySelector('svg'); - if (svgElement) { - svgElement.style.visibility = 'visible'; - } - } - }, - removeHoverEffect: () => { - let avatar: HTMLDivElement = actionsRef.current?.childNodes[0]; - let svg: HTMLDivElement = actionsRef.current?.childNodes[1]; - avatar.style.opacity = ''; - svg.style.display = ''; - svg.style.position = ''; - svg.style.top = ""; - svg.style.left = ""; - svg.style.transform = ""; - if(contactRef){ - contactRef.current.style.background = ""; - } - if (item?.isOutlookDeleted) { - let p: HTMLParagraphElement = svg?.childNodes[0]; - p.style.marginTop = ""; - p.style.color = ""; - } - if (dragandDropActionRef.current) { - const svgElement: HTMLDivElement = dragandDropActionRef.current.querySelector('svg'); - if (svgElement) { - svgElement.style.visibility = ''; - svgElement.style.color = "" - } - } - } - })); - - const handleClick = useCallback(() => { - if (onPress) { - onPress(item); - } - }, [item, onPress]); - - const handleRemoveOutlookContactOnClick = useCallback(() => { - if (onRemovePress) { - onRemovePress(item.id); - } - }, [item, onRemovePress]); - - const handleAction = useCallback((key: React.Key) => { - // close the menu when an action is pressed - contextTriggerRef.current?.hideMenu({ keyCode: 27 }); - switch (key) { - case '.$remove': - if (onRemovePress) { - onRemovePress(item.id); - } - break; - case '.$edit': - if (onEditPress) { - onEditPress(item); - } - break; - case '.$audioCall': - if (onAudioCallPress) { - onAudioCallPress(item); - } - break; - case '.$videoCall': - if (onVideoCallPress) { - onVideoCallPress(item); - } - break; - default: - throw new Error('Cannot find action'); - } - }, []); - - useEffect(() => { - if (submenuItemRef.current) { - submenuItemRef.current.removeAttribute('aria-labelledby'); - const items = submenuItemRef.current.querySelectorAll('[aria-labelledby]'); - items.forEach(item => { - item.removeAttribute('aria-labelledby'); - }); - } - }, []); - - useEffect(() => { - const handleFocusOut = (event: FocusEvent) => { - if (isSubMenuVisible) { - contextTriggerRef.current?.setState({ - isVisible: false, - selectedItem: null, - forceSubMenuOpen: false - }); - }; - }; - - if (isSubMenuVisible) { - document.addEventListener('focusout', handleFocusOut); - contextTriggerRef.current?.setState({ - isVisible: false, - selectedItem: null, - forceSubMenuOpen: false - }); - } else { - document.removeEventListener('focusout', handleFocusOut); - contextTriggerRef.current?.setState({ - isVisible: false, - selectedItem: null, - forceSubMenuOpen: false - }); - } - - // Ensure that the event listener is removed when the component unmounts - return () => { - document.removeEventListener('focusout', handleFocusOut); - }; - }, [isSubMenuVisible]); - - return ( - <> - {!item?.isOutlookDeleted && - <> - -
{ - e.preventDefault(); - setIsContextMenuVisible(true); - actionBtnRef.current?.click(); - }} - ref={contactRef} - onClick={handleClick} - aria-label={`${abbrDisplayName(item?.displayName)}, ${t('form.phoneTypes.'+ item?.phoneType)}, ${t('addSpeedBanner.dial.header')}, ${t('voiceover.enterCall', {callType: isAudio ? t('item.audioCall.label') : t('item.videoCall.label')})}, ${t('voiceover.openContextMenu')}, ${t('voiceover.rearrangeItem')}`} - > - - {children && ( -
- {children} -
- )} - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */} -
- - - - - {isAudio && - // - - - - } - {!isAudio && - // - - - - } - -
- - - {abbrDisplayName(item?.displayName)} - - - {/* {item?.phoneType} */} - {t('form.phoneTypes.'+ item?.phoneType)} - - -
-
-
- {/* Context Menu Actions */} - -
{ - setSubMenuVisible(false); - }} - onBlur={() => { - setSubMenuVisible(true); - }} - > - -
- {audioCallLabel} - {videoCallLabel} -
-
} - > - {(!item || (item.id && item.id.startsWith('l_'))) && ( - {editLabel} - )} - {removeLabel} -
-
-
-
- - } - {item?.isOutlookDeleted && - - -
{ - e.preventDefault(); - setIsContextMenuVisible(true); - actionBtnRef.current?.click(); - }} - ref={contactRef} - aria-label={`${deleteOutlookUserLabel} ${t('voiceover.removeDeletedContact')} ${t('voiceover.openContextMenu')}`} - > - - {children && ( -
- {/* {children} */} -
- - - - - -
-
- )} - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */} -
- - - - - - - - - - - - - {outlookRemoveLabel} - - -
- - - {deleteOutlookUserLabel} - - -
-
-
- {/* Context Menu Actions */} - -
{ - setSubMenuVisible(false); - }} - onBlur={() => { - setSubMenuVisible(true); - }} > - -
- {removeLabel} -
-
-
-
-
- } - variant="small" - > -

{originalContactDeletedLabel}

- - } - - ); -}); diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.stories.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.stories.tsx deleted file mode 100644 index 2091b8161..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import { SpeedDialModal } from './SpeedDialModal'; - -export default { - title: 'Components/Speed Dials/Modal', - component: SpeedDialModal, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = {}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.styles.scss deleted file mode 100644 index ea6cc622f..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.styles.scss +++ /dev/null @@ -1,88 +0,0 @@ -$C: wxc-speed-dial-modal; - -.#{$C} { - align-items: unset; - border-radius: 6px; - - > * { - box-sizing: border-box; - } - - &__header { - display: flex; - flex-direction: column; - padding-left: .5rem; - - p, h3 { - padding: 0; - margin: 0; - } - - > div { - flex: 1; - width: 100%; - } - - &-text { - display: flex; - justify-content: space-between; - } - - .md-text-wrapper { - font-weight: normal; - } - - .header-text { - line-height: 1.975rem; - } - - .cancel-button { - height: 2rem; - width: 2rem; - } - - } - - &__subheader-text { - padding-top: 1rem; - padding-left: 0.625rem; - padding-bottom: 0.1rem; - } - - &__content { - max-width: 425px; - padding: 1.5rem 0.5rem 0.5rem; - } - - &__subheader-icon { - margin-left: 0.625rem !important; - margin-top: 0.188rem; - } - - &__footer { - display: flex; - padding: 1rem; - - button { - flex: 1; - - &:first-child { - margin-right: 0.75rem; - } - } - } - - &__tooltip { - background-color: #EDEDED !important; - border-radius: inherit !important; - border: 1px solid rgba(0, 0, 0, 0.2) !important; - box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.16), 0px 0px 1px rgba(0, 0, 0, 0.18) !important; - padding: 5px 8px !important; - height: auto !important; - p { - margin: 0; - font-size: 12px; - } - } - -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.tsx deleted file mode 100644 index 679824d43..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialModal.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { - ButtonCircle, - Flex, PopoverNext as Popover, Text -} from '@momentum-ui/react-collaboration'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { GenericModal } from './GenericModal'; -import useWebexClasses from './hooks/useWebexClasses'; -import './SpeedDialModal.styles.scss'; - -type ISpeedDialModalProps = { - headerText?: string; - isOpen?: boolean; - onCancel?: () => void; - children?: React.ReactNode; - handleEnterKeyPress?: (event: React.KeyboardEvent) => void; - isEdit?: boolean; -}; - -/** - * When passed in a user, a fullscreen overlay will appear - * - * @param {ISpeedDialModalProps} props Component props - * @param {string} props.headerText Header title for modal - * @param {boolean} props.isOpen Open state of modal - * @param {Function} props.onCancel Callback function when cancel pressed - * @param {React.ReactNode} props.children The children - * @returns {React.Component} React component - */ -export const SpeedDialModal = ({ - isOpen = true, - onCancel = undefined, - children = undefined, - headerText, - isEdit, - handleEnterKeyPress = undefined -}: ISpeedDialModalProps) => { - const [cssClasses, sc] = useWebexClasses('speed-dial-modal'); - const { t } = useTranslation('WebexSpeedDials'); - - return ( - - - - {t('webex.calling')} - - - - - - - - {headerText} - {/** No need this info toggletip as discussed with IVY **/} - {/* - - - -
- } - variant="small" - > -

{isEdit ? t('voiceover.editTextInfo') : t('addSpeedBanner.info.text')}

- */} - - -
{children}
- - ); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.styles.scss deleted file mode 100644 index 268f04731..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.styles.scss +++ /dev/null @@ -1,52 +0,0 @@ -$C: wxc-speed-dial-photo-input; - - -.#{$C} { - position: relative; - display: flex; - align-items: center; - justify-content: center; - - > * { - box-sizing: border-box; - } - - &__image-container { - position: relative; - } - - &__image { - border-radius: 50%; - width: 65px; - height: 65px; - } - - &__file { - display: none; - } - - &__button-container { - position: absolute; - right: 0; - bottom: 0; - background: white; - border-radius: 50%; - height: 36px; - width: 36px; - display: flex; - align-items: center; - justify-content: center; - transform: translate(8px, 8px); - } - - .md-button-circle-wrapper { - background-color: var(--videoSupport-controls-button-background) !important; - border-color: var(--button-secondary-text) !important; - color: var(--button-secondary-text) !important; - border-width: 2px; - svg { - fill: currentColor !important; - } - } - -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.tsx deleted file mode 100644 index 30b675ae4..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialPhotoInput.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React, { useState } from 'react'; -import { - AvatarNext, - ButtonCircle, - IconNext, -} from '@momentum-ui/react-collaboration'; - -import useWebexClasses from './hooks/useWebexClasses'; -import './SpeedDialPhotoInput.styles.scss'; - -type ISpeedDialPhotoInputProps = { - name: string; - title?: string; - src?: string; - className?: string; -}; - -const convertBase64 = (file: File) => { - return new Promise((resolve, reject) => { - const fileReader = new FileReader(); - fileReader.readAsDataURL(file); - fileReader.onload = () => { - resolve(fileReader.result); - }; - fileReader.onerror = (error) => { - reject(error); - }; - }); -}; - -/** - * The Speed Dial Photo input that handles previewing an avatar. - * - * @param {ISpeedDialPhotoInputProps} props Component props - * @param {string} props.title The title - * @param {string} props.name The file input name - * @param {string} props.className Custom class names - * @returns {React.Component} React component - */ -export const SpeedDialPhotoInput = ({ - name, - src = '', - title = undefined, - className = undefined, -}: ISpeedDialPhotoInputProps) => { - const [cssClasses, sc] = useWebexClasses('speed-dial-photo-input'); - - const [imageSrc, setImageSrc] = useState(src); - - const handleFileRead = async (event: React.ChangeEvent) => { - if (event.currentTarget.files) { - const file = event.currentTarget.files[0]; - const base64 = await convertBase64(file); - setImageSrc(base64 as string); - } - }; - - const fileRef = React.createRef(); - - return ( -
-
- {imageSrc && ( - Avatar - )} - {!imageSrc && } -
- { - fileRef.current?.click(); - }} - > - - -
-
- -
- ); -}; - -/* - - - - - - - - - - */ diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.styles.scss deleted file mode 100644 index 954213d0c..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.styles.scss +++ /dev/null @@ -1,52 +0,0 @@ -$C: wxc-speed-dial-search; - -$list-height: 200px; -$list-padding: .5rem; - -.#{$C} { - position: relative; - - &__popover { - align-items: unset; - - border-radius: 10px; - border: 1px solid var(--theme-background-secondary-normal); - box-shadow: var(--md-globals-elevation-2); - z-index: auto; - right: 0; - left: 0; - } - - &__list-container { - height: $list-height; - overflow-y: auto; - } - - &__popover-list { - padding: $list-padding - } - - &__item-header { - color: var(--label-secondary-text); - padding-left: .75rem; - - h3 { - font-weight: normal; - margin: $list-padding 0; - } - } - - &__create-label { - font-weight: bold; - } - - >* { - box-sizing: border-box; - } - - &__loading { - display: flex; - justify-content: center; - margin: 2.5rem auto; - } -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.tsx deleted file mode 100644 index 324f6f808..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDialSearch.tsx +++ /dev/null @@ -1,309 +0,0 @@ -import React, { useCallback, useReducer } from 'react'; -import { useTranslation } from 'react-i18next'; -import { - AvatarNext, - ContentSeparator, - IconNext, - ListHeader, - ListItemBase, - ListItemBaseSection, - ListNext as List, - SearchInput, - Text, - LoadingSpinner, -} from '@momentum-ui/react-collaboration'; -import { ISpeedDialRecord } from '@webex/component-adapter-interfaces/dist/cjs/src'; -import { useContactSearch } from './hooks/useContactSearch'; -import useWebexClasses from './hooks/useWebexClasses'; -import { ISpeedDialItem } from './SpeedDials.types'; -import { IWebexIntContact } from '@webex/component-adapter-interfaces/dist/cjs/src'; - -import './SpeedDialSearch.styles.scss'; - -type ISpeedDialSearchProps = { - /* Custom classname for component */ - className?: string; - items?: ISpeedDialRecord[]; - /* Triggered when search input changing */ - onSearch?: (value: string) => void; - /* Triggered when add button is pressed */ - onAdd?: (item: ISpeedDialItem) => void; - /* Triggered when search item is pressed */ - onPress?: (item: ISpeedDialItem) => void; -}; - -type State = { - searchValue: string; - items: ISpeedDialItem[]; - filteredItems: ISpeedDialItem[]; -}; - -enum ActionTypes { - FILTER_CONTACTS = 'FILTER_CONTACTS', -} - -type SearchAction = { - type: typeof ActionTypes.FILTER_CONTACTS; - payload: string; -}; - -type Actions = SearchAction; - -const initialState = { - searchValue: '', - items: [], - filteredItems: [], -}; - -/** - * Handles sanitizing user input. - * - * @param {string} str The input string - * @returns {string} THe input string sanitized - */ -function sanitizeString(str: string): string { - const s: string = str.replace(/[^a-z\dáéíóúñü .,_-]/gim, ''); - return s.trim(); -} - -/** - * Search component reducer - * - * @param {State} state The current state - * @param {Actions} action The action to perform - * @returns {State} The updated state - */ -function reducer(state: State, action: Actions): State { - const { type, payload } = action; - - const searchValue = sanitizeString(payload) as string; - - switch (type) { - case ActionTypes.FILTER_CONTACTS: - if (!payload) { - return { - ...state, - searchValue, - filteredItems: [], - }; - } - return { - ...state, - searchValue, - filteredItems: state.items.filter((item: ISpeedDialItem) => { - const regex = new RegExp(`${searchValue}`, 'ig'); - return item?.displayName.match(regex); - }), - }; - default: - throw new Error(); - } -} - -type ISpeedDialListItem = { - item: ISpeedDialItem; - className?: string; - onPress?: (item: ISpeedDialItem) => void; -}; -const SpeedDialListItem = ({ - item, - className = undefined, - onPress = undefined, -}: ISpeedDialListItem) => { - const handlePress = useCallback(() => { - if (onPress) { - onPress(item); - } - }, [item, onPress]); - return ( - - - {/* - add a newly type in component adpater interface then un comment the below one - - - - - {item?.name} - */} - - ); -}; - -/** - * Speed Dial search component. - * - * @param {ISpeedDialSearchProps} obj The props for the component - * @param {number} obj.items The index of the speed dial - * @param {string} obj.className The classname for componentn - * @param {Function} obj.onSearch Triggered when input is searched - * @param {Function} obj.onAdd Triggered when add button is pressed - * @param {Function} obj.onPress Triggered when search item is pressed - * @returns {React.Component} A Search component - * @class - */ -export const SpeedDialSearch = ({ - items = [], - className = undefined, - onSearch = undefined, - onAdd = undefined, - onPress = undefined, -}: ISpeedDialSearchProps) => { - const [cssClasses, sc] = useWebexClasses('speed-dial-search', className); - const { t } = useTranslation('WebexSpeedDials'); - - const [state, dispatch] = useReducer(reducer, { ...initialState, items }); - const [source, filteredContactResponse, isSearching] = useContactSearch(state.searchValue); - const filterArray = filteredContactResponse.items - - const searchContactsData = { - outlook: filterArray[source[0]], - directory: filterArray[source[1]] - }; - - - const createHeaderStr = t('search.labels.header', { - searchValue: state.searchValue, - }); - - const handleChange = (e: string) => { - if (onSearch) { - onSearch(e); - } - dispatch({ type: ActionTypes.FILTER_CONTACTS, payload: e }); - }; - - const handlePress = (item: ISpeedDialItem) => { - if (onPress) { - onPress(item); - } - }; - - const handleAdd = () => { - const newItem: ISpeedDialItem = { - id: '0', - displayName: state.searchValue, - }; - - if (onAdd) { - onAdd(newItem); - } - }; - - return ( -
- - - {state.searchValue && ( -
- {(isSearching && - )} - {!isSearching && ( -
    -
  • - - {/* Directory Contacts List */} - {searchContactsData?.directory?.length > 0 && ( - <> - - - - {t('search.labels.directory')} - - - - - {searchContactsData?.directory.map( - (item: IWebexIntContact | any) => ( - - ) - )} - - )} - {/* Outlook Contacts List */} - {searchContactsData?.outlook?.length > 0 && ( - <> - - - - {t('search.labels.outlook')} - - - - {searchContactsData?.outlook.map((item: IWebexIntContact | any) => ( - - ))} - - )} - -
  • - - {createHeaderStr && ( - - {createHeaderStr} - - )} - {/* Create speed dial action */} - - - {t('search.labels.create')} - - {` '${state.searchValue}'`} - - - - - - -
- )} -
- )} -
- ); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.styles.scss b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.styles.scss deleted file mode 100644 index 49a950f31..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.styles.scss +++ /dev/null @@ -1,54 +0,0 @@ -$C: wxc-speed-dial; - -$speed-dial-list-width: 500px; -$speed-dial-list-item-width: 110px; -$speed-dial-list-item-max-width: 125px; -$speed-dial-list-grid-gap: 0.35rem; -$speed-dial-list-grid-template: repeat(4, minmax($speed-dial-list-item-width, $speed-dial-list-item-max-width)); - -// Needed for the list item being dragged is attached to dom.body and css not scoped -ul, li { - list-style-type: none; -} - -.#{$C} { - overflow: hidden; - - &__list { - display: grid; - gap: $speed-dial-list-grid-gap; - grid-template-columns: $speed-dial-list-grid-template; - list-style: none; - margin: 0; - padding: 0; - } - - .react-contextmenu { - display: flex; - flex-direction: column; - position: relative; - width: fit-content; - list-style: none; - margin: 0; - border: 0.0625rem var(--modal-primary-border-style) var(--modal-primary-border-color); - min-width: 2.5rem; - padding: .2rem; - z-index: 1; - box-shadow: var(--md-globals-elevation-3); - background-color: var(--theme-background-solid-tertiary-normal); - border-radius: 10px; - - > li { - margin: 0; - padding: 0; - } - } - - &--grabbing, &--grabbing .wxc-sortable-item { - cursor: grabbing; - } - - &--grabbing .wxc-speed-dial-item { - pointer-events: none; - } -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.tsx deleted file mode 100644 index df4b675f3..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.tsx +++ /dev/null @@ -1,288 +0,0 @@ -import { ISpeedDialRecord } from '@webex/component-adapter-interfaces/dist/cjs/src'; -import { arrayMoveMutable } from 'array-move'; -import React, { useEffect, useRef, useState } from 'react'; - -import { - SortEnd, - SortEvent, - SortEventWithTag, - SortableContainer, - SortableElement, - SortableHandle, -} from 'react-sortable-hoc'; - -import { - Flex, Text -} from '@momentum-ui/react-collaboration'; -import { useTranslation } from 'react-i18next'; -import { SpeedDialAddBanner } from './SpeedDialAddBanner'; -import { ISpeedDialProps, SpeedDialItem } from './SpeedDialItem'; -import { ISpeedDialsListProps, ISpeedDialsProps } from './SpeedDials.types'; -import useWebexClasses from './hooks/useWebexClasses'; - -import './SpeedDials.styles.scss'; - -interface ChildHandles { - handleContextMenuTrigger: (e: KeyboardEvent) => void; - handleContextMenuClose: (e: KeyboardEvent) => void; - setSubMenuVisible: (visible: boolean) => void; // Add this line - handleEnterKey:(e:KeyboardEvent) => void; - setIsContextMenuVisible: (visible: boolean) => void; - triggerHoverEffect: () => void; - removeHoverEffect: () => void; -} - - -const DraggableIcon = () => ( -
- - - -
-); - -const DragHandle = SortableHandle(() => ); - -const SortableItem = SortableElement( - ({ - item, - isAudio, - onPress, - onAudioCallPress, - onVideoCallPress, - onRemovePress, - onEditPress, - selectedNodeForRearange - }: ISpeedDialProps) => { - const [isContactFocused, setIsContactFocused] = useState(false); - const childRef = useRef(null); - - useEffect(() => { - const handleShiftF10Press = (e: KeyboardEvent) => { - if (e.key === 'Enter' && isContactFocused) { - childRef.current?.handleEnterKey(e); - } else if (e.shiftKey && e.key === 'F10' && isContactFocused) { - childRef.current?.setIsContextMenuVisible(true); - childRef.current?.handleContextMenuTrigger(e); - } else if (e.key === 'Escape') { - childRef.current?.handleContextMenuClose(e); - childRef.current?.setIsContextMenuVisible(false); - } - else if ((e.shiftKey && e.key === 'Tab') || e.key === 'Tab'){ - childRef.current?.setIsContextMenuVisible(false); - } - }; - window.addEventListener('keydown', handleShiftF10Press); - - return () => { - window.removeEventListener('keydown', handleShiftF10Press); - }; - }, [isContactFocused]); - - const handleContextMenuTriggerFocus = () => { - setIsContactFocused(true); - childRef.current?.setSubMenuVisible(false); - childRef.current?.triggerHoverEffect(); - }; - - const handleContextMenuTriggerBlur = () => { - setIsContactFocused(false); - // To handle reinitialization of aria label content after item has been rearranged - selectedNodeForRearange && selectedNodeForRearange.removeAttribute('aria-label'); - childRef.current?.removeHoverEffect(); - }; - - - return ( -
  • - - - -
  • - - ) - } -); - -const SortableList = SortableContainer( - ({ - items = [], - onPress, - onVideoCallPress, - onAudioCallPress, - onEditPress, - onRemovePress, - className, - selectedNodeForRearange - }: { - items: ISpeedDialRecord[]; - onPress?: (item: ISpeedDialRecord) => void; - onVideoCallPress?: (item: ISpeedDialRecord) => void; - onAudioCallPress?: (item: ISpeedDialRecord) => void; - onEditPress?: (item: ISpeedDialRecord) => void; - onRemovePress?: (id: string) => void; - className: string; - selectedNodeForRearange: Element; - }) => ( -
      - {items && - items.map((item, index) => ( - - ))} -
    - ) -); - -/** - * @description This is the Speed Dials component - * @param {ISpeedDialsProps} obj - An object of props. - * @param {Array} obj.items An array of speed dial items - * @param {Function} obj.onSortEnd Function to call when sorting ends. - * @param {Function} obj.onEditPress Function to call when edit action is pressed. - * @param {Function} obj.onRemovePress Function to call when remove action is pressed. - * @param {Function} obj.onVideoCallPress Function to call when video call button pressed. - * @param {Function} obj.onAudioCallPress Function to call when audio call button pressed. - * @returns {React.Component} SpeedDials component - */ -export const SpeedDials = ({ - items = [], - onPress = undefined, - onAudioCallPress = undefined, - onVideoCallPress = undefined, - onEditPress = undefined, - onRemovePress = undefined, - onSortEnd: onSortEndCb = undefined, - onAddPress = undefined, - listError, -}: ISpeedDialsProps) => { - const [grabbing, setGrabbing] = useState(false); - const [classes, sc] = useWebexClasses('speed-dial', undefined, { - grabbing, - }); - const speedDialsRef = useRef(null); - const { t } = useTranslation('WebexSpeedDials'); - const [selectedNode, setSelectedNode] = useState(); - - const handleSortEnd = ({oldIndex, newIndex, nodes}: SortEnd) => { - setGrabbing(false); - // Move the item only if the position changed - if(oldIndex !== newIndex) { - arrayMoveMutable(items, oldIndex, newIndex); - if (onSortEndCb) { - onSortEndCb(items); - } - } - selectedNode && (selectedNode.ariaLabel = `${t('voiceover.contactNewPosition', { contactName: items[newIndex].displayName, newIndex: newIndex + 1, totalIndex: nodes.length })}`) - }; - - const handleShouldCancelStart = (event: SortEvent | SortEventWithTag): boolean => { - // This should be the class name you use for your sortable items - const sortableItemClassName = 'wxc-speed-dial-item__drag-handle'; - - // If the event is triggered by keyboard (e.g., spacebar), allow sorting to start - if (event.type === 'keydown') { - // Check if the correct key was pressed (e.g., spacebar) - if ((event as unknown as KeyboardEvent).key === ' ') { - return false; - } - } - - let target: HTMLElement | null = event.target as HTMLElement; - - while (target && target !== document.documentElement) { - if (target.classList.contains(sortableItemClassName)) { - return false; // Allow sorting to start because the target is a sortable item - } - target = target.parentElement; - } - - return true; // Cancel sorting by default if none of the conditions above are met - }; - - if (items.length > 0 && !listError) { - return ( -
    - setGrabbing(true)} - shouldCancelStart={handleShouldCancelStart} - onPress={onPress} - onVideoCallPress={onVideoCallPress} - onAudioCallPress={onAudioCallPress} - onEditPress={onEditPress} - onRemovePress={onRemovePress} - useDragHandle={grabbing} - items={items} - axis="xy" - className={sc('list')} - updateBeforeSortStart={({node, index}, event) => { - node.ariaLabel = `${t('voiceover.startRearranging', { contactName: items[index].displayName, numberType: items[index].phoneType })}, ${t('voiceover.adjustPosition')}, ${t('voiceover.stopRearranging')}, ${t('voiceover.currentPosition', { currentIndex: index+1, totalIndex: items.length })}`; - setSelectedNode(node); - }} - selectedNodeForRearange={selectedNode} - /> -
    - ); - } - else if(listError) { - return ( -
    -
    - - - - - - - - - -
    - - {t('errorNotification.error')} - - {t('errorNotification.listError')} -
    - ) - } - else { - return ( -
    - -
    - - ) - } -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.types.tsx b/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.types.tsx deleted file mode 100644 index 4f9425e01..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/SpeedDials.types.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { ISpeedDialRecord } from '@webex/component-adapter-interfaces/dist/cjs/src'; - -export interface ISpeedDialItem extends ISpeedDialRecord { - type?: string; -} - -export interface ISpeedDialEvents { - /** Handle when item is pressed */ - onPress?: (item: ISpeedDialRecord) => void; - /** Handle when item video call button is pressed */ - onVideoCallPress?: (item: ISpeedDialRecord) => void; - /** Handle when item audio call button is pressed */ - onAudioCallPress?: (item: ISpeedDialRecord) => void; - /** Handle when item edit button is pressed */ - onEditPress?: (item: ISpeedDialRecord) => void; - /** Handle when item remove button is pressed */ - onRemovePress?: (id: string) => void; - /** Handle when add speed dial btn is pressed */ - onAddPress?: () => void -} - -export interface ISpeedDialsProps extends ISpeedDialEvents { - items: ISpeedDialItem[] | undefined; - /** Handle when items sort ends */ - onSortEnd?: (items: ISpeedDialRecord[]) => void; - listError?: boolean; -} - -export interface ISpeedDialsListProps extends ISpeedDialEvents { - items: ISpeedDialItem[]; - className: string; - /** Handle when item is pressed */ - onClick?: (id: string) => void; - /** To handle reinitialization of aria label content after item has been rearranged */ - selectedNodeForRearange: Element | undefined; -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/contexts/AdapterContext.tsx b/packages/node_modules/@webex/widget-speed-dial/src/contexts/AdapterContext.tsx deleted file mode 100644 index 1e83df65e..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/contexts/AdapterContext.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { - ICallHistoryAdapter, - IMakeCallAdapter, - ISearchContactsAdapter, - ISpeedDialsAdapter, - IVoicemailAdapter, -} from '@webex/component-adapter-interfaces/dist/esm/src' -import React, { createContext } from 'react'; - -export interface IAdapterContext { - user?: unknown; - callHistoryAdapter?: ICallHistoryAdapter; - searchContactsAdapter?: ISearchContactsAdapter; - makeCallAdapter?: IMakeCallAdapter; - speedDialsAdapter?: ISpeedDialsAdapter; - voicemailAdapter?: IVoicemailAdapter; -} - -export const AdapterContext = createContext({}); - -export interface IAdapterProvider { - adapter: IAdapterContext; - children: React.ReactNode; -} - -/** - * - * @param root0 - * @param root0.adapter - * @param root0.children - */ -export const AdapterProvider = ({ adapter, children }: IAdapterProvider) => { - return ( - - {children} - - ); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useContactSearch.ts b/packages/node_modules/@webex/widget-speed-dial/src/hooks/useContactSearch.ts deleted file mode 100644 index 2761c6dbb..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useContactSearch.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { useCallback, useContext, useState } from 'react'; -import { ISearchContactsAdapterSearchResponse } from '@webex/component-adapter-interfaces/dist/cjs/src'; -import { AdapterContext } from '../contexts/AdapterContext'; -import { useDebouncedEffect } from './useDebouncedEffect'; -// import { Logger } from '@webex-int/logger'; - -export enum StatusCode{ - SUCCESS = 200 - } -/** - * Handles the searching of contacts, relaying the react state - * - * @param {string} searchText text to search for in contacts - * @returns {[ISearchContactsAdapterSearchResponse, boolean]} array containing search response and loading boolean respectively - */ -export const useContactSearch: ( - _: string -) => [string[], ISearchContactsAdapterSearchResponse, boolean] = ( - searchText: string -) => { - const [items, setItems] = useState({ - items: {}, - count: 0, - }); - const [searching, setSearching] = useState(false); - const ctx = useContext(AdapterContext); - - const sources = ctx?.searchContactsAdapter?.getSources() || []; - - const searchContacts = useCallback( - async (searchTextValue: string) => { - if (!ctx?.searchContactsAdapter) { - console.error('context does not contain field searchContactsAdapter'); - return; - } - setSearching(true); - try { - // Added condition to stop searching the empty field - if (searchTextValue) { - const data = await ctx.searchContactsAdapter.search({ - searchText: searchTextValue, - }); - setItems(data); - } - } catch (e) { - // Logger.error( - // `Contatc search error case: '${e}'.` - // ); - } finally { - setSearching(false); - } - }, - [ctx?.searchContactsAdapter] - ); - - useDebouncedEffect( - () => searchContacts(searchText), - [searchText, searchContacts], - StatusCode.SUCCESS, - () => setSearching(true) - ); - - return [sources, items, searching]; - }; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useDebouncedEffect.ts b/packages/node_modules/@webex/widget-speed-dial/src/hooks/useDebouncedEffect.ts deleted file mode 100644 index 25aa637ee..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useDebouncedEffect.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useEffect } from 'react'; - -export const useDebouncedEffect = ( - debouncedEffect: () => void, - deps: unknown[], - delay: number, - immediateEffect?: () => void -) => { - useEffect(() => { - if (immediateEffect) { - immediateEffect(); - } - const handler = setTimeout(() => debouncedEffect(), delay); - - return () => clearTimeout(handler); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [...(deps || []), delay]); -}; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useWebexClasses.ts b/packages/node_modules/@webex/widget-speed-dial/src/hooks/useWebexClasses.ts deleted file mode 100644 index 0cd806520..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/hooks/useWebexClasses.ts +++ /dev/null @@ -1,48 +0,0 @@ -import classNames from 'classnames'; - -const WEBEX_COMPONENTS_CLASS_PREFIX = 'wxc'; - -/** - * Builds a string of css class names for webex components - * - * @param {string} classBaseName Component class base name - * @param {string} [userClassName] Custom CSS class to apply - * @param {object} otherClasses Other optional classes with prefix - * @returns {[string, Function]} Classes and a prefix function - */ -export default function useWebexClasses( - classBaseName: string, - userClassName?: string, - otherClasses?: { - [key: string]: string | boolean; - } -) { - const userClassNames = Array.isArray(userClassName) - ? userClassName - : [userClassName]; - - const cssClasses = classNames( - 'wxc', - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}`, - ...userClassNames, - { - ...Object.fromEntries( - Object.entries(otherClasses || {}).map(([key, val]) => [ - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}--${key}`, - val, - ]) - ), - } - ); - - const sc = (subclass: string, modifiers: string[] = []) => { - const n = `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}__${subclass}`; - - return classNames( - n, - modifiers.map((m) => `${n}--${m}`) - ); - }; - - return [cssClasses, sc] as const; -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/index.ts b/packages/node_modules/@webex/widget-speed-dial/src/index.ts deleted file mode 100644 index 9c0c1f872..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { SpeedDials } from '@webex/widget-speed-dial/src/SpeedDials'; -export { SpeedDialItem } from '@webex/widget-speed-dial/src/SpeedDialItem'; -export { SpeedDialForm } from '@webex/widget-speed-dial/src/SpeedDialForm'; -export { SpeedDialSearch } from '@webex/widget-speed-dial/src/SpeedDialSearch'; -export { SpeedDialAddBanner } from '@webex/widget-speed-dial/src/SpeedDialAddBanner' -export * from '@webex/widget-speed-dial/src/SpeedDialForm.types'; -export * from '@webex/widget-speed-dial/src/SpeedDials.types'; diff --git a/packages/node_modules/@webex/widget-speed-dial/src/styles/index.scss b/packages/node_modules/@webex/widget-speed-dial/src/styles/index.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/node_modules/@webex/widget-speed-dial/src/styles/list-mixins.scss b/packages/node_modules/@webex/widget-speed-dial/src/styles/list-mixins.scss deleted file mode 100644 index 674be5e7c..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/styles/list-mixins.scss +++ /dev/null @@ -1,51 +0,0 @@ -@mixin list-bordered { - border-bottom: 1px solid var(--scrollbar-track-background, rgba(0, 0, 0, 0.1)); -} - -@mixin list-squared { - border-radius: 0 !important; -} - -@mixin list-avatar { - flex-shrink: 0; -} - -@mixin list-primary-text { - margin: 0; - padding: 0; - width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-sub-text { - color: var(--label-secondary-text); - width: 100%; - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-toggle-active($hideOnActiveClass, $showOnActiveClass) { - @include list-hide-on-active($hideOnActiveClass); - @include list-show-on-active($showOnActiveClass); -} - -@mixin list-hide-on-active($hideOnActiveClass) { - &:hover, - &:focus, - &.active { - .#{$hideOnActiveClass} { - display: none; - } - } -} - -@mixin list-show-on-active($showOnActiveClass) { - &:not(:hover):not(:focus):not(.active) { - .#{$showOnActiveClass} { - display: none; - } - } -} diff --git a/packages/node_modules/@webex/widget-speed-dial/src/utils/avatarInitials.ts b/packages/node_modules/@webex/widget-speed-dial/src/utils/avatarInitials.ts deleted file mode 100644 index 2b1dbb198..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/utils/avatarInitials.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function removeBracketsAndContent(str: string): string { - if (str?.match(/^[+\d]/)) { - return "#"; - } - const words = str?.replace(/ *\([^)]*\) */g, ' ').replace(/ *\(\S*/g, '').replace(/\)+/g, '').replace(/\s+/g, ' ').trim().split(' '); - const filteredWords = words?.filter(word => /^[a-zA-Z0-9]/.test(word)); - let initials = ''; - if (filteredWords?.length > 0) { - initials += filteredWords[0][0].toUpperCase(); - if (filteredWords?.length > 1) { - initials += filteredWords[filteredWords.length - 1][0].toUpperCase(); - } - } - if(initials?.length == 0 && str?.length > 0) { - initials += str[0]; - } - return initials; - - } diff --git a/packages/node_modules/@webex/widget-speed-dial/src/utils/dateUtils.ts b/packages/node_modules/@webex/widget-speed-dial/src/utils/dateUtils.ts deleted file mode 100644 index 598ede526..000000000 --- a/packages/node_modules/@webex/widget-speed-dial/src/utils/dateUtils.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { DateTime, Duration } from 'luxon'; - -/** - * @description Converts date string to DateTime object for use in other functions - * @param {string} date The date string to format - * @returns {DateTime} A DateTime object to be formatted - */ -function getDateTimeFromString(date: string): DateTime { - return DateTime.fromISO(date); -} - -/** - * @description Handle formatting the time for display. - * @param {string} date The date string to format - * @returns {string} A formatted time as in 3:00 PM - */ -export function formatTime(date: string) { - return getDateTimeFromString(date).toLocaleString({ - hour: 'numeric', - minute: '2-digit', - hour12: true, - }); -} - -/** - * @description Handle formatting the date for display. - * @param {string} date The date string to format - * @returns {string} A formatted date as in "Today", "Yesterday", or "1/1/22" - */ -export function formatDate(date: string) { - const d = getDateTimeFromString(date); - - if ( - d.toISODate() === DateTime.now().toISODate() || - d.toISODate() === DateTime.now().minus({ day: 1 }).toISODate() - ) { - return d.toRelativeCalendar({}); - } - - return d.toLocaleString({ - day: 'numeric', - month: 'numeric', - year: '2-digit', - }); -} - -/** - * @description Handle formatting the duration for display. - * @param {number} seconds Total duration in seconds - * @returns {string} A formatted duration for display "04:10" - */ -export function formatDuration(seconds: number) { - const dur = Duration.fromObject({ seconds: Math.trunc(seconds) }); - const shiftedDur = dur.shiftTo('hours', 'minutes', 'seconds').normalize(); - return shiftedDur.toFormat('hh:mm:ss'); -} - -/** - * @description Handle formatting the duration for display. - * @param {string} d1 The start time date string - * @param {string} d2 The end time date string - * @returns {string} A formatted duration for display "4m 10s" - */ -export function formatDurationFromDates(d1: string, d2: string) { - const dur = getDateTimeFromString(d2).diff(getDateTimeFromString(d1)); - const entries = Object.entries( - dur - .shiftTo('hours', 'minutes', 'seconds', 'milliseconds') - .normalize() - .toObject() - ).filter(([unit, amount]) => amount > 0 && unit !== 'milliseconds'); - const outputDur = Duration.fromObject( - entries.length === 0 ? { seconds: 0 } : Object.fromEntries(entries) - ); - return outputDur - .toHuman({ listStyle: 'narrow', unitDisplay: 'narrow' }) - .replace(/,/g, ''); -} diff --git a/packages/node_modules/@webex/widget-voice-mail/package.json b/packages/node_modules/@webex/widget-voice-mail/package.json deleted file mode 100644 index 68c90c832..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@webex/widget-voice-mail", - "description": "widget voice mail", - "main": "./dist/cjs/index.ts", - "src": "./src/index.ts", - "module": "./dist/es/index.ts", - "keywords": [], - "author": "devsupport@webex.com", - "license": "MIT", - "dependencies": { - "@formatjs/intl-pluralrules": "^1.5.4", - "@formatjs/intl-relativetimeformat": "^4.5.11", - "@momentum-ui/react-collaboration": "26.82.1" - }, - "repository": "https://github.com/webex/react-widgets", - "files": [ - "src", - "dist", - "cjs", - "es" - ], - "version": "0.50.0" -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.stories.tsx b/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.stories.tsx deleted file mode 100644 index cc311e335..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { ScrubbingBar } from './ScrubbingBar'; - -export default { - title: 'Components/ScrubbingBar', - component: ScrubbingBar, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ( - -); - -export const Default = Template.bind({}); -Default.args = {}; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.styles.scss b/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.styles.scss deleted file mode 100644 index 36a508efc..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.styles.scss +++ /dev/null @@ -1,47 +0,0 @@ -$C: wxc-voicemail-scrubbing-bar; - -.#{$C} { - $scrubber-thumb-size: 16px; - $track-radius: 5px; - - - flex-grow: 1; - - &__thumb { - width: $scrubber-thumb-size; - height: $scrubber-thumb-size; - border-radius: 100%; - background-color: var(--theme-background-solid-primary-normal); - border: 1px solid var(--theme-outline-primary-normal); - box-shadow: var(--md-globals-elevation-1); - cursor: pointer; - position: absolute; - top: 50%; - transform: translateY(-50%); - } - - &__track { - position: relative; - height: 2px; - - &::before { - content: ""; - position: absolute; - top: 50%; - transform: translateY(-50%); - width: 100%; - height: 100%; - border-radius: $track-radius; - background-color: var(--theme-control-inactive-normal); - } - } - - &__viewed { - position: absolute; - left: 0; - top: 0; - height: 100%; - border-radius: $track-radius; - background-color: var(--theme-control-active-normal); - } -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.tsx b/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.tsx deleted file mode 100644 index ae0eed13c..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/ScrubbingBar.tsx +++ /dev/null @@ -1,172 +0,0 @@ -/* eslint-disable react/jsx-props-no-spreading */ -/* eslint-disable react/destructuring-assignment */ -import { formatSleekBarCurrTimeDurationForAnnouncement, formatVoiceMailTimeDurationForAnnouncement } from '@webex/widget-call-history/src/utils/voiceOver'; - -import React, { KeyboardEvent, MutableRefObject, forwardRef, useEffect, useRef, useState } from 'react'; -import { - VisuallyHidden, - mergeProps, - useFocusRing, - useNumberFormatter, - useSlider, - useSliderThumb, -} from 'react-aria'; -import { useTranslation } from 'react-i18next'; -import { SliderState, SliderStateOptions, useSliderState } from 'react-stately'; -import './ScrubbingBar.styles.scss'; -import useWebexClasses from './hooks/useWebexClasses'; - -type IScrubbingBarThumbProps = { - state: SliderState; - index: number; - trackRef: MutableRefObject; - className?: string; - currTime?: number[]; -}; - -/** - * - * @param props - * @param props.state - * @param props.trackRef - * @param props.index - * @param props.className - */ -const ScrubbingBarThumb = forwardRef(({ - state, - trackRef, - index, - className = undefined, - currTime -}, ref) => { - const inputRef = useRef(null); - const [isFocused, setIsFocused] = useState(false); - const { thumbProps, inputProps } = useSliderThumb( - { - index, - trackRef, - inputRef, - }, - state - ); - - const { focusProps } = useFocusRing(); - const handleFocus = () => { - setIsFocused(true); - }; - - const handleBlur = () => { - setIsFocused(false); - }; - - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === 'Escape' && trackRef.current) { - trackRef.current.focus(); - } - }; - - return ( -
    { - thumbProps.onKeyDown?.(e); - handleKeyDown(e); - }} - role="slider" - aria-valuenow={currTime ? currTime[0] : 0} - aria-valuetext={currTime ? `${formatSleekBarCurrTimeDurationForAnnouncement(currTime[0] * 1000)}` : ""} - ref={ref} - > - - - -
    - ); -}); - -export interface IScrubbingBarProps - extends Partial> { - numberFormatOptions?: unknown; - duration?: number; - voicemailName?: string; - playButtonRef: React.RefObject; - pauseButtonRef: React.RefObject; - audioButtonRef: React.RefObject; - trackRef: React.RefObject; -} - -export const ScrubbingBar = ({ playButtonRef, pauseButtonRef, audioButtonRef, trackRef, ...rest }: IScrubbingBarProps) => { - const [cssClasses, sc] = useWebexClasses( - 'voicemail-scrubbing-bar', - undefined, - { - disabled: !!rest.isDisabled, - } - ); - const thumbRef = useRef(null); - const numberFormatted = useNumberFormatter(); - const state = useSliderState({ - numberFormatter: numberFormatted, - ...rest, - }); - const { groupProps, trackProps } = useSlider(rest, state, trackRef); - const { t } = useTranslation('WebexVoicemail'); - const { isFocusVisible, focusProps } = useFocusRing(); - - useEffect(() => { - if (trackRef.current) { - trackRef.current.focus(); - } - }, []); - - const handleTrackKeyDown = (event: KeyboardEvent) => { - if (event.key === 'Enter' && thumbRef.current) { - thumbRef.current.focus(); - } else if (event.key === 'ArrowRight' && audioButtonRef.current) { - event.preventDefault(); - event.stopPropagation(); - audioButtonRef.current.focus(); - } else if (event.key === 'ArrowLeft' && playButtonRef.current) { - event.preventDefault(); - event.stopPropagation(); - playButtonRef.current.focus(); - } - }; - - return ( -
    -
    -
    - -
    -
    - ); -}; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.styles.scss b/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.styles.scss deleted file mode 100644 index 812e5dfa8..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.styles.scss +++ /dev/null @@ -1,60 +0,0 @@ -@import "./styles/list-mixins.scss"; - -$C: wxc-voicemail-item; - -.#{$C} { - - @include list-squared; - @include list-bordered; - @include list-toggle-active(#{$C}__datetime, #{$C}__actions); - @include list-show-on-active(wxc-voicemail-scrubbing-bar); - @include list-show-on-active(wxc-voicemail-playback-controls__current-time); - - & > * { - display: grid; - grid-template-columns: min-content 1fr 1fr 1fr min-content; - grid-gap: 0.75rem; - align-items: center; - - & > * { - overflow: hidden; - } - } - - &__user-details { - overflow: hidden; - } - - &__avatar { - } - - &__phone, &__time { - @include list-sub-text; - } - - &__name, &__date { - @include list-primary-text; - text-transform: capitalize; - } - - &__meta { - text-align: right; - justify-self: flex-end; - } - - &__unread-bubble { - width: 12px; - height: 12px; - border-radius: 100%; - } - - &--unread { - .#{$C}__name, .#{$C}__date { - font-weight: 700; - } - - .#{$C}__unread-bubble { - background-color: var(--badge-background); - } - } -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.tsx b/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.tsx deleted file mode 100644 index 28bb9b332..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailItem.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import { - AvatarNext as Avatar, - ButtonCircle, - Flex, ListItemBase, - ListItemBaseSection, - Text -} from '@momentum-ui/react-collaboration'; -import { IWebexVoicemail } from '@webex/component-adapter-interfaces/dist/esm/src'; -import { formatPhoneNumberForAnnouncement, formatVoiceMailTimeDurationForAnnouncement } from '@webex/widget-call-history/src/utils/voiceOver'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import './VoicemailItem.styles.scss'; -import { VoicemailPlaybackControls } from './VoicemailPlaybackControls'; -import useWebexClasses from './hooks/useWebexClasses'; -import { removeBracketsAndContent } from './utils/avatarInitials'; -import { - formatDate, - formatDateDDMMYYYY, - formatDateForAnnouncement, - formatTime, - formatTimeToSupport24Hours -} from './utils/dateUtils'; - -export interface IVoicemailItemProps { - voicemail: IWebexVoicemail; - isSelected?: boolean; - onPress?: () => void; - onDelete?: () => void; - onRead?: () => void; - voicemailSrc: string; - voicemailSrcLoader?: boolean; - useMakeAudioCall?:() => void; - useMakeVideoCall?:() => void; - itemIndex?: number; - isLocaleGerman?: boolean; -} - -export const VoicemailItem = ({ - voicemail, - isSelected = false, - onPress = () => {}, - onDelete = undefined, - onRead = undefined, - voicemailSrc, - voicemailSrcLoader = false, - useMakeAudioCall = undefined, - useMakeVideoCall = undefined, - itemIndex = undefined, - isLocaleGerman -}: IVoicemailItemProps) => { - const { t } = useTranslation('WebexVoicemail'); - let [unread, setUnread] = useState(voicemail.unread); - const prevVoicemail = useRef(null); - const [cssClasses, sc] = useWebexClasses('voicemail-item', undefined, { - unread:voicemail.unread - }); - const [isAnnouncePlayOrPause, setIsAnnouncePlayOrPause] = useState(false); - const vmInitials = voicemail?.name ? removeBracketsAndContent(voicemail?.name) : removeBracketsAndContent(voicemail?.address); - const playOrPause = isAnnouncePlayOrPause ? t('pauseVoicemail') : t('playVoicemail'); - const formattedDate = formatDateForAnnouncement(voicemail.date); - const formattedTime = `${isLocaleGerman ? formatTimeToSupport24Hours(voicemail.date) : formatTime(voicemail.date)}`; - - const readVoicemail = useCallback(() => { - if (onRead) { - onRead(); - } - }, [onRead]); - - const onClick = () => { - // readVoicemail(); - onPress(); - }; - useEffect(() => { - if ( - prevVoicemail.current && - prevVoicemail.current.unread === false && - voicemail.unread === true - ) { - setUnread(true); - } - prevVoicemail.current = voicemail; - }, [voicemail]); - - useEffect(() => { - if(voicemailSrc) { - if(voicemail.unread) { - setUnread(false); - } - } - }, [voicemailSrc, voicemail.unread]); - - const playButtonRef = useRef(null); - const pauseButtonRef = useRef(null); - const audioButtonRef = useRef(null); - const videoButtonRef = useRef(null); - const trackRef = useRef(null); - - const handleAudioButtonKeyDown = (event: React.KeyboardEvent) => { - if (event.key === 'ArrowLeft' && trackRef.current) { - event.preventDefault(); - event.stopPropagation(); - trackRef.current.focus(); - } else if (event.key === 'ArrowRight' && videoButtonRef.current) { - event.preventDefault(); - event.stopPropagation(); - videoButtonRef.current.focus(); - } else if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { - //ListItemBase handle the focus movement for up and down arrow keys - const listItem = audioButtonRef.current?.closest('[role="listitem"]'); - if (listItem) { - const eventClone = new KeyboardEvent(event.type, { - key: event.key, - code: event.code, - location: event.location, - ctrlKey: event.ctrlKey, - shiftKey: event.shiftKey, - altKey: event.altKey, - metaKey: event.metaKey, - repeat: event.repeat, - bubbles: event.bubbles, - cancelable: event.cancelable, - keyCode: event.keyCode, - charCode: event.charCode, - which: event.which, - }); - listItem.dispatchEvent(eventClone); - } - } - }; - - return ( - - - - - - {voicemail.name} - - - {voicemail.address} - - - -
    - - - {isLocaleGerman ? formatDateDDMMYYYY(voicemail.date) : formatDate(voicemail.date)} - - - {isLocaleGerman ? formatTimeToSupport24Hours(voicemail.date) : formatTime(voicemail.date)} - - - - - - - - - - - - - - {onDelete && ( - - - - - - - )} - -
    -
    - - - ); -}; \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.styles.scss b/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.styles.scss deleted file mode 100644 index 9fdba97dd..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.styles.scss +++ /dev/null @@ -1,30 +0,0 @@ -$C: wxc-voicemail-playback-controls; - -.#{$C} { - &__play-icon { - margin-left: 1px; //fix off-centered play icon - } -} - -.vmLoader .md-loading-spinner-wrapper { - position: relative; - width: 23px; - right: 4.5px; -} - -.vmLoader .md-icon-wrapper { - align-items: center; - display: flex; - height: fit-content; - justify-content: center; - width: fit-content; -} - -.vmLoader .md-loading-spinner-wrapper .md-loading-spinner-arch { - position: absolute; - top: 0; - animation-name: spin-animation; - animation-duration: 0.75s; - animation-iteration-count: infinite; - animation-timing-function: linear; -} \ No newline at end of file diff --git a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.tsx b/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.tsx deleted file mode 100644 index 231ef2564..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/VoicemailPlaybackControls.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { - ButtonCircle, - Flex, - IconNext, - Text, -} from '@momentum-ui/react-collaboration'; -import React, { useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ScrubbingBar } from './ScrubbingBar'; -import './VoicemailItem.styles.scss'; -import './VoicemailPlaybackControls.styles.scss'; -import { useAudio } from './hooks/useAudio'; -import useWebexClasses from './hooks/useWebexClasses'; -import { formatDuration } from './utils/dateUtils'; - -export interface IVoicemailPlaybackControlsProps { - audioSrc: string; - onPlay?: () => void; - className?: string; - duration: number; - audioSrcLoader?: boolean; - focusPauseButton?: () => void; - setIsAnnouncePlayOrPause: React.Dispatch>; - voicemailName?: string; - playButtonRef: React.RefObject; - pauseButtonRef: React.RefObject; - audioButtonRef: React.RefObject; - trackRef: React.RefObject; -} - -export const VoicemailPlaybackControls = ({ - audioSrc, - onPlay = () => { }, - className = undefined, - duration, - audioSrcLoader = false, - setIsAnnouncePlayOrPause, - voicemailName, - playButtonRef, - pauseButtonRef, - audioButtonRef, - trackRef -}: IVoicemailPlaybackControlsProps) => { - const { t } = useTranslation('WebexVoicemail'); - const { curTime, playing, setPlaying, setClickedTime } = - useAudio(audioSrc, audioSrcLoader); - const playAudio = () => { - onPlay(); - setPlaying(true); - }; - const [cssClasses, sc] = useWebexClasses('voicemail-playback-controls'); - - useEffect(() => { - if (pauseButtonRef.current) { - pauseButtonRef?.current?.focus(); - } - }, [playing, audioSrcLoader, audioSrc]); - - useEffect(() => { - if (playing && audioSrc) { - setIsAnnouncePlayOrPause(true); - } else { - setIsAnnouncePlayOrPause(false); - } - }, [playing, audioSrc, setIsAnnouncePlayOrPause]); - - return ( - - {playing && audioSrc ? ( - { - setPlaying(false); - }} - data-testid="pause-button" - title={t('pauseVoicemail')} - ref={pauseButtonRef} - aria-label= {t('pauseVoicemail')} - > - - - ) : ( - - { (audioSrcLoader && audioSrc === '') ? ( -
    -
    - - - - -
    -
    - - - - -
    -
    -
    - ) : ( - - )} -
    - )} - - {formatDuration(curTime)} - setClickedTime(value)} - step={Math.min(duration / 1000, 0.1)} - voicemailName={voicemailName} - duration={duration} - playButtonRef={playButtonRef} - pauseButtonRef={pauseButtonRef} - audioButtonRef={audioButtonRef} - trackRef={trackRef} - /> - {formatDuration(duration / 1000)} -
    - ); -}; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/contexts/AdapterContext.tsx b/packages/node_modules/@webex/widget-voice-mail/src/contexts/AdapterContext.tsx deleted file mode 100644 index 1e83df65e..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/contexts/AdapterContext.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { - ICallHistoryAdapter, - IMakeCallAdapter, - ISearchContactsAdapter, - ISpeedDialsAdapter, - IVoicemailAdapter, -} from '@webex/component-adapter-interfaces/dist/esm/src' -import React, { createContext } from 'react'; - -export interface IAdapterContext { - user?: unknown; - callHistoryAdapter?: ICallHistoryAdapter; - searchContactsAdapter?: ISearchContactsAdapter; - makeCallAdapter?: IMakeCallAdapter; - speedDialsAdapter?: ISpeedDialsAdapter; - voicemailAdapter?: IVoicemailAdapter; -} - -export const AdapterContext = createContext({}); - -export interface IAdapterProvider { - adapter: IAdapterContext; - children: React.ReactNode; -} - -/** - * - * @param root0 - * @param root0.adapter - * @param root0.children - */ -export const AdapterProvider = ({ adapter, children }: IAdapterProvider) => { - return ( - - {children} - - ); -}; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useAudio.ts b/packages/node_modules/@webex/widget-voice-mail/src/hooks/useAudio.ts deleted file mode 100644 index 88920a7cf..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useAudio.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; - -export const useAudio = (url: string, audioSrcLoader: boolean) => { - const [audio] = useState(new Audio(url)); - const [duration, setDuration] = useState(0); - const [curTime, setCurTime] = useState(0); - const [playing, setPlaying] = useState(false); - - useEffect(() => { - const setAudioData = () => { - setDuration(audio.duration); - setCurTime(audio.currentTime); - }; - const setAudioTime = () => setCurTime(audio.currentTime); - const onEnded = () => { - setPlaying(false); - }; - - audio.addEventListener('loadeddata', setAudioData); - audio.addEventListener('timeupdate', setAudioTime); - audio.addEventListener('ended', onEnded); - - // effect cleanup - return () => { - audio.removeEventListener('loadeddata', setAudioData); - audio.removeEventListener('timeupdate', setAudioTime); - audio.removeEventListener('ended', onEnded); - }; - }, [playing, url, audioSrcLoader]); - - // React state listeners: update DOM on React state changes - useEffect(() => { - if (audioSrcLoader) { - if (playing && url) { - audio.src = url; - audio.pause(); - audio.load(); - audio.preload = 'auto' - audio.crossOrigin = "anonymous"; - audio.addEventListener("canplaythrough", () => { - url && audio.play(); - }) - } else { - audio.removeEventListener("canplaythrough", () => { - audio.pause(); - }); - audio.src = '' - } - } else { - audio.removeEventListener("canplaythrough", () => { - audio.pause(); - }); - audio.src = '' - setPlaying(false) - } - }, [playing, url, audio, setCurTime, audioSrcLoader]); - - const setClickedTime = useCallback( - (clickedTime: number) => { - if (clickedTime !== curTime) { - audio.currentTime = clickedTime; - setCurTime(clickedTime); - } - }, - [url, audio, setCurTime, curTime, audioSrcLoader] - ); - - return { audio, curTime, duration, playing, setPlaying, setClickedTime }; -}; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useMakeCall.ts b/packages/node_modules/@webex/widget-voice-mail/src/hooks/useMakeCall.ts deleted file mode 100644 index 64b83bb50..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useMakeCall.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useCallback, useContext } from 'react'; -import { AdapterContext } from '../contexts/AdapterContext'; - -export const useMakeCall = () => { - const ctx = useContext(AdapterContext); - - const makeCall = useCallback( - (address: string, isVideo?: boolean) => { - return makeCrossLaunchCall(address, !!isVideo); - }, - [makeCrossLaunchCall] - ); - - return [makeCall]; -}; - -export async function makeCrossLaunchCall(address: string, isAudio = false) { - console.debug( - `Making ${isAudio ? 'audio' : 'video'} call to address ${address}` - ); - const url = `webextel://${address}`; - const callUrl = new URL(url); - callUrl.searchParams.append('jws', ''); - callUrl.searchParams.append('isAudio', String(!isAudio)); - window.open(callUrl.href); -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useWebexClasses.ts b/packages/node_modules/@webex/widget-voice-mail/src/hooks/useWebexClasses.ts deleted file mode 100644 index 0cd806520..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/hooks/useWebexClasses.ts +++ /dev/null @@ -1,48 +0,0 @@ -import classNames from 'classnames'; - -const WEBEX_COMPONENTS_CLASS_PREFIX = 'wxc'; - -/** - * Builds a string of css class names for webex components - * - * @param {string} classBaseName Component class base name - * @param {string} [userClassName] Custom CSS class to apply - * @param {object} otherClasses Other optional classes with prefix - * @returns {[string, Function]} Classes and a prefix function - */ -export default function useWebexClasses( - classBaseName: string, - userClassName?: string, - otherClasses?: { - [key: string]: string | boolean; - } -) { - const userClassNames = Array.isArray(userClassName) - ? userClassName - : [userClassName]; - - const cssClasses = classNames( - 'wxc', - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}`, - ...userClassNames, - { - ...Object.fromEntries( - Object.entries(otherClasses || {}).map(([key, val]) => [ - `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}--${key}`, - val, - ]) - ), - } - ); - - const sc = (subclass: string, modifiers: string[] = []) => { - const n = `${WEBEX_COMPONENTS_CLASS_PREFIX}-${classBaseName}__${subclass}`; - - return classNames( - n, - modifiers.map((m) => `${n}--${m}`) - ); - }; - - return [cssClasses, sc] as const; -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/index.ts b/packages/node_modules/@webex/widget-voice-mail/src/index.ts deleted file mode 100644 index 99c0de85a..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export {VoicemailItem} from '@webex/widget-voice-mail/src/VoicemailItem'; -export {VoicemailPlaybackControls} from '@webex/widget-voice-mail/src/VoicemailPlaybackControls'; -export {ScrubbingBar}from '@webex/widget-voice-mail/src/ScrubbingBar'; diff --git a/packages/node_modules/@webex/widget-voice-mail/src/styles/index.scss b/packages/node_modules/@webex/widget-voice-mail/src/styles/index.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/node_modules/@webex/widget-voice-mail/src/styles/list-mixins.scss b/packages/node_modules/@webex/widget-voice-mail/src/styles/list-mixins.scss deleted file mode 100644 index 674be5e7c..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/styles/list-mixins.scss +++ /dev/null @@ -1,51 +0,0 @@ -@mixin list-bordered { - border-bottom: 1px solid var(--scrollbar-track-background, rgba(0, 0, 0, 0.1)); -} - -@mixin list-squared { - border-radius: 0 !important; -} - -@mixin list-avatar { - flex-shrink: 0; -} - -@mixin list-primary-text { - margin: 0; - padding: 0; - width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-sub-text { - color: var(--label-secondary-text); - width: 100%; - overflow-x: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -@mixin list-toggle-active($hideOnActiveClass, $showOnActiveClass) { - @include list-hide-on-active($hideOnActiveClass); - @include list-show-on-active($showOnActiveClass); -} - -@mixin list-hide-on-active($hideOnActiveClass) { - &:hover, - &:focus, - &.active { - .#{$hideOnActiveClass} { - display: none; - } - } -} - -@mixin list-show-on-active($showOnActiveClass) { - &:not(:hover):not(:focus):not(.active) { - .#{$showOnActiveClass} { - display: none; - } - } -} diff --git a/packages/node_modules/@webex/widget-voice-mail/src/utils/avatarInitials.ts b/packages/node_modules/@webex/widget-voice-mail/src/utils/avatarInitials.ts deleted file mode 100644 index 2b1dbb198..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/utils/avatarInitials.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function removeBracketsAndContent(str: string): string { - if (str?.match(/^[+\d]/)) { - return "#"; - } - const words = str?.replace(/ *\([^)]*\) */g, ' ').replace(/ *\(\S*/g, '').replace(/\)+/g, '').replace(/\s+/g, ' ').trim().split(' '); - const filteredWords = words?.filter(word => /^[a-zA-Z0-9]/.test(word)); - let initials = ''; - if (filteredWords?.length > 0) { - initials += filteredWords[0][0].toUpperCase(); - if (filteredWords?.length > 1) { - initials += filteredWords[filteredWords.length - 1][0].toUpperCase(); - } - } - if(initials?.length == 0 && str?.length > 0) { - initials += str[0]; - } - return initials; - - } diff --git a/packages/node_modules/@webex/widget-voice-mail/src/utils/dateUtils.ts b/packages/node_modules/@webex/widget-voice-mail/src/utils/dateUtils.ts deleted file mode 100644 index b41c1b344..000000000 --- a/packages/node_modules/@webex/widget-voice-mail/src/utils/dateUtils.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { DateTime, Duration } from 'luxon'; - -/** - * @description Converts date string to DateTime object for use in other functions - * @param {string} date The date string to format - * @returns {DateTime} A DateTime object to be formatted - */ -function getDateTimeFromString(date: string): DateTime { - return DateTime.fromISO(date); -} - -/** - * @description Handle formatting the time for display. - * @param {string} date The date string to format - * @returns {string} A formatted time as in 3:00 PM - */ -export function formatTime(date: string) { - return getDateTimeFromString(date).toLocaleString({ - hour: 'numeric', - minute: '2-digit', - hour12: true, - }); -} - -/** - * @description Handle formatting the date for display. - * @param {string} date The date string to format - * @returns {string} A formatted date as in "Today", "Yesterday", or "1/1/22" - */ -export function formatDate(date: string) { - const d = getDateTimeFromString(date); - - if ( - d.toISODate() === DateTime.now().toISODate() || - d.toISODate() === DateTime.now().minus({ day: 1 }).toISODate() - ) { - return d.toRelativeCalendar({}); - } - - return d.toLocaleString({ - day: 'numeric', - month: 'numeric', - year: '2-digit', - }); -} - -/** - * @description Handle formatting the duration for display. - * @param {number} seconds Total duration in seconds - * @returns {string} A formatted duration for display "04:10" - */ -export function formatDuration(seconds: number) { - const dur = Duration.fromObject({ seconds: Math.trunc(seconds) }); - const shiftedDur = dur.shiftTo('hours', 'minutes', 'seconds').normalize(); - return shiftedDur.toFormat('hh:mm:ss'); -} - -/** - * @description Handle formatting the duration for display. - * @param {string} d1 The start time date string - * @param {string} d2 The end time date string - * @returns {string} A formatted duration for display "4m 10s" - */ -export function formatDurationFromDates(d1: string, d2: string) { - const dur = getDateTimeFromString(d2).diff(getDateTimeFromString(d1)); - const entries = Object.entries( - dur - .shiftTo('hours', 'minutes', 'seconds', 'milliseconds') - .normalize() - .toObject() - ).filter(([unit, amount]) => amount > 0 && unit !== 'milliseconds'); - const outputDur = Duration.fromObject( - entries.length === 0 ? { seconds: 0 } : Object.fromEntries(entries) - ); - return outputDur - .toHuman({ listStyle: 'narrow', unitDisplay: 'narrow' }) - .replace(/,/g, ''); -} - -/** - * @description Handle formatting the time for display 24hour format is required. - * @param {string} date The date string to format - * @returns {string} A formatted time as in 24hr format - */ -export function formatTimeToSupport24Hours(date: string) { - return getDateTimeFromString(date).toLocaleString({ - hour: 'numeric', - minute: '2-digit', - hour12: false - }); -} - -/** - * @description Handle formatting the date for display. - * @param {string} date The date string to format - * @returns {string} A formatted date as in "Today", "Yesterday", or "dd.mm.yyyy" - */ -export function formatDateDDMMYYYY(date: string) { - const d = getDateTimeFromString(date); - - if ( - d.toISODate() === DateTime.now().toISODate() || - d.toISODate() === DateTime.now().minus({ day: 1 }).toISODate() - ) { - return d.toRelativeCalendar({}); - } - - return d.toLocaleString({ - day: '2-digit', - month: '2-digit', - year: 'numeric', - }); -} - -/** - * @description Handle formatting the date for announce. - * @param {string} date The date string to format - * @returns {string} A announced date as in "Today", "Yesterday", or "june 10,2024" - */ -export const formatDateForAnnouncement = (date: string) => { - const dateValue = getDateTimeFromString(date); - - if ( - dateValue.toISODate() === DateTime.now().toISODate() || - dateValue.toISODate() === DateTime.now().minus({ days: 1 }).toISODate() - ) { - return dateValue.toRelativeCalendar({}); - } - - return dateValue.toLocaleString({ - month: 'long', // Use 'long' for full month name - day: 'numeric', - year: 'numeric', - }); - }