зеркало из
1
0
Форкнуть 0

[JavaScript-loaders] Add loader path import on communication-react for JS Composite loader functions (#5106)

* Move loaders to external directory import

* Change files

* update API extractor to have a consolodated API for both paths for reviews

* fix exports definition

* add new api command

* Change files

* update API

* fix internal samples

* fix ci

* simplify complete api index

* update extractor to be by flavor

* Add new tests for checking adapter and react calls

* fix stable

* Add other composite tests

* test CI

* reverse test

* fix test import issue

* Update packages/communication-react/package.json

Co-authored-by: Porter Nan <jiangnanhello@live.com>
Signed-off-by: Donald McEachern <94866715+dmceachernmsft@users.noreply.github.com>

---------

Signed-off-by: Donald McEachern <94866715+dmceachernmsft@users.noreply.github.com>
Co-authored-by: Porter Nan <jiangnanhello@live.com>
This commit is contained in:
Donald McEachern 2024-09-11 13:09:21 -07:00 коммит произвёл GitHub
Родитель 538ab3865a
Коммит 12c5da8e79
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
17 изменённых файлов: 351 добавлений и 87 удалений

Просмотреть файл

@ -0,0 +1,9 @@
{
"type": "prerelease",
"area": "fix",
"workstream": "js-loaders",
"comment": "Add new sub package to communication react to import the loader functions",
"packageName": "@azure/communication-react",
"email": "dmceachern@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -0,0 +1,9 @@
{
"type": "prerelease",
"area": "feature",
"workstream": "js-loaders",
"comment": "Move loaders to external directory import",
"packageName": "@azure/communication-react",
"email": "dmceachern@microsoft.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -14,8 +14,8 @@
"preprocess": "cpx \"./src/**\" ./preprocessed && babel ./src --out-dir ../preprocessed --extensions \".ts,.tsx\" --keep-file-extension --config-file ./.babelrc.js --relative && rimraf ../preprocessed",
"prettier": "prettier --no-error-on-unmatched-pattern --write --config ../../.prettierrc --ignore-path=../../.prettierignore \"**/*.js\" \"**/*.jsx\" \"**/*.ts\" \"**/*.tsx\"",
"prettier:check": "prettier --no-error-on-unmatched-pattern --check --config ../../.prettierrc --ignore-path=../../.prettierignore \"**/*.js\" \"**/*.jsx\" \"**/*.ts\" \"**/*.tsx\"",
"test": "echo package only in alpha no test run",
"test:ci-coverage": "rushx _by-flavor \"rushx _test:by-flavor --coverage\"",
"test": "rushx _by-flavor \"rushx _test:by-flavor\"",
"test:ci-coverage": "echo package tested by composites",
"test:coverage": "rushx _by-flavor \"rushx _test:by-flavor --coverage --coverageReporters=lcov\"",
"lint": "eslint --max-warnings 0 \"*/**/*.{ts,tsx}\"",
"lint:fix": "rushx lint --fix --",

Просмотреть файл

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(composite-js-helpers) */
import { CallCompositeOptions } from '@internal/react-composites';
/* @conditional-compile-remove(composite-js-helpers) */
import { CallCompositeLoaderProps } from './callCompositeLoader';
jest.mock('@Internal/react-composites', () => {
return {
createAzureCommunicationCallAdapter: jest.fn().mockResolvedValue('mockAdapter'),
CallComposite: jest.fn().mockReturnValue('mockCallComposite')
};
});
const mockCreateRoot = jest.fn();
jest.mock('react-dom/client', () => {
return {
createRoot: jest.fn().mockReturnValue({ render: mockCreateRoot })
};
});
jest.mock('@azure/communication-common', () => {
return {
AzureCommunicationTokenCredential: jest.fn(),
CommunicationUserIdentifier: jest.fn(),
createIdentifierFromRawId: jest.fn().mockReturnValue('mockIdentifier')
};
});
const mockInitializeIcons = jest.fn();
jest.mock('@fluentui/react', () => {
return {
initializeIcons: mockInitializeIcons
};
});
describe('CallCompositeLoader tests', () => {
test('test to fulfill no empty test runners', () => {
expect(true).toBeTruthy();
});
/* @conditional-compile-remove(composite-js-helpers) */
test('loadCallComposite should call createAzureCommunicationCallAdapter and createRoot', async () => {
const mockAdapterArgs: CallCompositeLoaderProps = {
userId: 'userId',
token: 'token',
displayName: 'displayName',
locator: { groupId: 'groupId' },
options: { callingSounds: { callEnded: { url: 'test/url/ended' } } }
};
const mockHtmlElement = document.createElement('div');
const mockCompositeOptions: CallCompositeOptions = {};
const { loadCallComposite } = await import('./callCompositeLoader');
const { createAzureCommunicationCallAdapter } = await import('@internal/react-composites');
await loadCallComposite(mockAdapterArgs, mockHtmlElement, mockCompositeOptions);
expect(mockInitializeIcons).toHaveBeenCalled();
expect(createAzureCommunicationCallAdapter).toHaveBeenCalled();
expect(mockCreateRoot).toHaveBeenCalled();
});
});

Просмотреть файл

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(composite-js-helpers) */
import { CallWithChatCompositeOptions } from '@internal/react-composites';
/* @conditional-compile-remove(composite-js-helpers) */
import { CallWithChatCompositeLoaderProps } from './callWithChatCompositeLoader';
jest.mock('@Internal/react-composites', () => {
return {
createAzureCommunicationCallWithChatAdapter: jest.fn().mockResolvedValue('mockAdapter'),
CallWithChatComposite: jest.fn().mockReturnValue('mockCallComposite')
};
});
const mockCreateRoot = jest.fn();
jest.mock('react-dom/client', () => {
return {
createRoot: jest.fn().mockReturnValue({ render: mockCreateRoot })
};
});
jest.mock('@azure/communication-common', () => {
return {
AzureCommunicationTokenCredential: jest.fn(),
CommunicationUserIdentifier: jest.fn(),
createIdentifierFromRawId: jest.fn().mockReturnValue('mockIdentifier')
};
});
const mockInitializeIcons = jest.fn();
jest.mock('@fluentui/react', () => {
return {
initializeIcons: mockInitializeIcons
};
});
describe('CallWithChatCompositeLoader tests', () => {
test('test to fulfill no empty test runners', () => {
expect(true).toBeTruthy();
});
/* @conditional-compile-remove(composite-js-helpers) */
test('loadCallWithChatComposite should call createAzureCommunicationCallWithChatAdapter and createRoot', async () => {
const mockAdapterArgs: CallWithChatCompositeLoaderProps = {
userId: 'userId',
token: 'token',
endpoint: 'endpoint',
displayName: 'displayName',
locator: { callLocator: { groupId: 'groupId' }, chatThreadId: 'threadId' }
};
const mockHtmlElement = document.createElement('div');
const mockCompositeOptions: CallWithChatCompositeOptions = {
galleryOptions: { layout: 'floatingLocalVideo' }
};
const { loadCallWithChatComposite } = await import('./callWithChatCompositeLoader');
const { createAzureCommunicationCallWithChatAdapter } = await import('@internal/react-composites');
await loadCallWithChatComposite(mockAdapterArgs, mockHtmlElement, mockCompositeOptions);
expect(mockInitializeIcons).toHaveBeenCalled();
expect(createAzureCommunicationCallWithChatAdapter).toHaveBeenCalled();
expect(mockCreateRoot).toHaveBeenCalled();
});
});

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(composite-js-helpers) */
import { ChatCompositeOptions } from '@internal/react-composites';
/* @conditional-compile-remove(composite-js-helpers) */
import { ChatCompositeLoaderProps } from './chatCompositeLoader';
jest.mock('@Internal/react-composites', () => {
return {
createAzureCommunicationChatAdapter: jest.fn().mockResolvedValue('mockAdapter'),
ChatComposite: jest.fn().mockReturnValue('mockCallComposite')
};
});
const mockCreateRoot = jest.fn();
jest.mock('react-dom/client', () => {
return {
createRoot: jest.fn().mockReturnValue({ render: mockCreateRoot })
};
});
jest.mock('@azure/communication-common', () => {
return {
AzureCommunicationTokenCredential: jest.fn(),
CommunicationUserIdentifier: jest.fn(),
createIdentifierFromRawId: jest.fn().mockReturnValue('mockIdentifier')
};
});
const mockInitializeIcons = jest.fn();
jest.mock('@fluentui/react', () => {
return {
initializeIcons: mockInitializeIcons
};
});
describe('ChatCompositeLoader tests', () => {
test('test to fulfill no empty test runners', () => {
expect(true).toBeTruthy();
});
/* @conditional-compile-remove(composite-js-helpers) */
test('loadChatComposite should call createAzureCommunicationChatAdapter and createRoot', async () => {
const mockAdapterArgs: ChatCompositeLoaderProps = {
endpoint: 'endpoint',
token: 'token',
userId: 'userId',
displayName: 'displayName',
threadId: 'threadId'
};
const mockHtmlElement = document.createElement('div');
const mockCompositeOptions: ChatCompositeOptions = {
errorBar: true
};
const { loadChatComposite } = await import('./chatCompositeLoader');
const { createAzureCommunicationChatAdapter } = await import('@internal/react-composites');
await loadChatComposite(mockAdapterArgs, mockHtmlElement, mockCompositeOptions);
expect(mockInitializeIcons).toHaveBeenCalled();
expect(createAzureCommunicationChatAdapter).toHaveBeenCalled();
expect(mockCreateRoot).toHaveBeenCalled();
});
});

Просмотреть файл

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(composite-js-helpers) */
import { CallCompositeOptions } from '@internal/react-composites';
/* @conditional-compile-remove(composite-js-helpers) */
import { OutboundCallCompositeLoaderProps } from './outboundCallCompositeLoader';
jest.mock('@Internal/react-composites', () => {
return {
createAzureCommunicationCallAdapter: jest.fn().mockResolvedValue('mockAdapter'),
CallComposite: jest.fn().mockReturnValue('mockCallComposite')
};
});
const mockCreateRoot = jest.fn();
jest.mock('react-dom/client', () => {
return {
createRoot: jest.fn().mockReturnValue({ render: mockCreateRoot })
};
});
jest.mock('@azure/communication-common', () => {
return {
AzureCommunicationTokenCredential: jest.fn(),
CommunicationUserIdentifier: jest.fn(),
createIdentifierFromRawId: jest.fn().mockReturnValue('mockIdentifier')
};
});
const mockInitializeIcons = jest.fn();
jest.mock('@fluentui/react', () => {
return {
initializeIcons: mockInitializeIcons
};
});
describe('CallCompositeLoader tests', () => {
test('test to fulfill no empty test runners', () => {
expect(true).toBeTruthy();
});
/* @conditional-compile-remove(composite-js-helpers) */
test('loadCallComposite should call createAzureCommunicationCallAdapter and createRoot', async () => {
const mockAdapterArgs: OutboundCallCompositeLoaderProps = {
userId: 'userId',
token: 'token',
displayName: 'displayName',
targetCallees: [{ phoneNumber: '+14035556666' }],
options: { callingSounds: { callEnded: { url: 'test/url/ended' } } }
};
const mockHtmlElement = document.createElement('div');
const mockCompositeOptions: CallCompositeOptions = {};
const { loadOutboundCallComposite } = await import('./outboundCallCompositeLoader');
const { createAzureCommunicationCallAdapter } = await import('@internal/react-composites');
await loadOutboundCallComposite(mockAdapterArgs, mockHtmlElement, mockCompositeOptions);
expect(mockInitializeIcons).toHaveBeenCalled();
expect(createAzureCommunicationCallAdapter).toHaveBeenCalled();
expect(mockCreateRoot).toHaveBeenCalled();
});
});

Просмотреть файл

@ -0,0 +1,4 @@
{
"extends": "../../common/config/api-extractor/api-extractor.json",
"mainEntryPointFilePath": "<projectFolder>/dist/dist-esm/communication-react/src/api-summary.d.ts"
}

Просмотреть файл

@ -0,0 +1,4 @@
{
"extends": "../../common/config/api-extractor/api-extractor.stable.json",
"mainEntryPointFilePath": "<projectFolder>/dist/dist-esm/communication-react/src/api-summary.d.ts"
}

Просмотреть файл

@ -65,6 +65,17 @@
},
"main": "./dist/dist-cjs/communication-react/index.js",
"module": "./dist/dist-esm/communication-react/src/index.js",
"exports": {
".": {
"main": "./dist/dist-cjs/communication-react/index.js",
"module": "./dist/dist-esm/communication-react/src/index.js",
"types": "./dist/communication-react.d.ts"
},
"./javascript-loaders": {
"module": "./dist/dist-esm/communication-react/src/javascript-loaders.js",
"types": "./dist/dist-esm/communication-react/src/javascript-loaders.d.ts"
}
},
"scripts": {
"copy-original": "cpx \"../*/src/**\" ./preprocess-dist && renamer --find src --replace preprocessed ./preprocess-dist/**/*",
"preprocess": "babel ../*/src --out-dir ../preprocessed --extensions \".ts,.tsx\" --keep-file-extension --config-file ./.babelrc.js --relative && rimraf ../preprocessed",
@ -74,12 +85,14 @@
"build:cjs": "rollup -c --silent",
"build:esm": "npm run _if-preprocess && rushx copy-original && rushx preprocess && rushx copy-preprocess && tspc -project tsconfig.preprocess.json || (if-env COMMUNICATION_REACT_FLAVOR=beta && tspc)",
"build:watch": "",
"build:api": "rushx _api-extractor:complete:by-flavor",
"clean": "rimraf dist && rimraf ../**/preprocessed && rimraf ../**/preprocess-dist",
"test": "",
"test:ci-coverage": "",
"test:coverage": "",
"check-deps": "node scripts/verifyDependencies",
"api-extractor": "rushx _by-flavor \"rushx build:esm && rushx _api-extractor:by-flavor\"",
"api-extractor:complete": "rushx _by-flavor \"rushx build:esm && rushx api-extractor:complete:by-falvor\"",
"generate-doc": "api-documenter markdown -i temp -o docGen",
"prettier": "prettier --no-error-on-unmatched-pattern --write --config ../../.prettierrc --ignore-path=../../.prettierignore \"**/*.js\" \"**/*.jsx\" \"**/*.ts\" \"**/*.tsx\"",
"prettier:check": "prettier --no-error-on-unmatched-pattern --check --config ../../.prettierrc --ignore-path=../../.prettierignore \"**/*.js\" \"**/*.jsx\" \"**/*.ts\" \"**/*.tsx\"",
@ -92,6 +105,7 @@
"_if-preprocess": "if-env COMMUNICATION_REACT_FLAVOR=stable || if-env COMMUNICATION_REACT_FLAVOR=beta-release",
"_if-beta": "if-env COMMUNICATION_REACT_FLAVOR=beta || if-env COMMUNICATION_REACT_FLAVOR=beta-release",
"_api-extractor:by-flavor": "if-env COMMUNICATION_REACT_FLAVOR=stable && api-extractor run -c api-extractor.stable.json --local || (rushx _if-beta && api-extractor run --local)",
"_api-extractor:complete:by-flavor": "if-env COMMUNICATION_REACT_FLAVOR=stable && api-extractor run -c api-extractor-complete.stable.json --local || (rushx _if-beta && api-extractor run -c api-extractor-complete.json --local)",
"_build:by-flavor": "rushx clean && rushx build:esm && rushx build:cjs && rushx _api-extractor:by-flavor",
"_current-flavor": "echo You are running under COMMUNICATION_REACT_FLAVOR: && env-cmd -f ../../common/config/env/.env node -p process.env.COMMUNICATION_REACT_FLAVOR",
"_by-flavor": "rushx _current-flavor && env-cmd -f ../../common/config/env/.env --use-shell"
@ -109,6 +123,7 @@
"@internal/fake-backends": "1.19.0-beta.3",
"@internal/react-components": "1.19.0-beta.3",
"@internal/react-composites": "1.19.0-beta.3",
"@internal/acs-ui-javascript-loaders": "1.19.0-beta.3",
"@microsoft/api-documenter": "~7.25.9",
"@microsoft/api-extractor": "~7.47.4",
"@rollup/plugin-json": "^6.0.1",

Просмотреть файл

@ -726,15 +726,6 @@ export type CallCompositeIcons = {
StopAllSpotlightMenuButton?: JSX.Element;
};
// @beta
export type CallCompositeLoaderProps = {
userId: string;
token: string;
displayName: string;
locator: CallAdapterLocator;
options?: AzureCommunicationCallAdapterOptions;
};
// @public
export type CallCompositeOptions = {
errorBar?: boolean;
@ -1487,15 +1478,6 @@ export type CallWithChatCompositeIcons = {
StopAllSpotlightMenuButton?: JSX.Element;
};
// @beta
export type CallWithChatCompositeLoaderProps = {
userId: string;
token: string;
displayName: string;
endpoint: string;
locator: CallAndChatLocator;
};
// @public
export type CallWithChatCompositeOptions = {
callControls?: boolean | CallWithChatControlOptions;
@ -1920,15 +1902,6 @@ export type ChatCompositeIcons = {
SendBoxAttachFile?: JSX.Element;
};
// @beta
export type ChatCompositeLoaderProps = {
userId: string;
token: string;
displayName?: string;
endpoint: string;
threadId: string;
};
// @public
export type ChatCompositeOptions = {
errorBar?: boolean;
@ -3461,21 +3434,9 @@ export interface JumpToNewMessageButtonProps {
// @public
export const lightTheme: PartialTheme & CallingTheme;
// @beta
export const loadCallComposite: (adapterArgs: CallCompositeLoaderProps, htmlElement: HTMLElement | null, props?: CallCompositeOptions) => Promise<CallAdapter | undefined>;
// @beta
export const loadCallWithChatComposite: (args: CallWithChatCompositeLoaderProps, htmlElement: HTMLElement | null, props: CallWithChatCompositeOptions) => Promise<CallWithChatAdapter | undefined>;
// @beta
export const loadChatComposite: (args: ChatCompositeLoaderProps, htmlElement: HTMLElement | null, props: ChatCompositeOptions) => Promise<ChatAdapter | undefined>;
// @public
export type LoadingState = 'loading' | 'none';
// @beta
export const loadOutboundCallComposite: (adapterArgs: OutboundCallCompositeLoaderProps, htmlElement: HTMLElement | null, props?: CallCompositeOptions) => Promise<CallAdapter | undefined>;
// @public
export const LocalizationProvider: (props: LocalizationProviderProps) => JSX.Element;
@ -3989,15 +3950,6 @@ export interface OptionsDevice {
name: string;
}
// @beta
export type OutboundCallCompositeLoaderProps = {
userId: string;
token: string;
displayName: string;
targetCallees: string[] | StartCallIdentifier[];
options?: AzureCommunicationCallAdapterOptions;
};
// @public
export type OverflowGalleryPosition = 'horizontalBottom' | 'verticalRight' | 'horizontalTop';

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* This file is for the generate of the complete API of the package.
* This also includes the sub export of the javascript-loaders in the API.
* To use these exports the user will need to import the functions from
* '@azure/communication-react/javascript-loaders' instead of from the main entry point.
*
* This is to avoid having these new functions affect developers that are not using the current
* version of react that is needed to use these functions inside their react application. In this
* instance it is recommended that the developer use the react components and composites directly.
*/
/* @conditional-compile-remove(composite-js-helpers) */
export * from './javascript-loaders';
export * from './index';

Просмотреть файл

@ -28,21 +28,6 @@ export type {
AreParamEqual
} from '../../acs-ui-common/src';
/* @conditional-compile-remove(composite-js-helpers) */
export {
loadOutboundCallComposite,
loadCallComposite,
loadChatComposite,
loadCallWithChatComposite
} from '../../acs-ui-javascript-loaders/src';
/* @conditional-compile-remove(composite-js-helpers) */
export type {
OutboundCallCompositeLoaderProps,
CallCompositeLoaderProps,
ChatCompositeLoaderProps,
CallWithChatCompositeLoaderProps
} from '../../acs-ui-javascript-loaders/src';
// Not to export chat/calling specific hook from binding package
export type {
CallClientProviderProps,

Просмотреть файл

@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/* @conditional-compile-remove(composite-js-helpers) */
export {
loadOutboundCallComposite,
loadCallComposite,
loadChatComposite,
loadCallWithChatComposite
} from '../../acs-ui-javascript-loaders/src';
/* @conditional-compile-remove(composite-js-helpers) */
export type {
OutboundCallCompositeLoaderProps,
CallCompositeLoaderProps,
ChatCompositeLoaderProps,
CallWithChatCompositeLoaderProps
} from '../../acs-ui-javascript-loaders/src';

Просмотреть файл

@ -14,7 +14,8 @@ import SecondaryCustomButtonInjectionExampleText from '!!raw-loader!./snippets/S
<Meta of={CustomButtonInjectionStories} component={CustomButtonInjectionComponent} />
<script> { addCSS('#custom-button-injection-story button[aria-label="Custom"]{ border: 1px solid green; }') } </script>
<script> {addCSS('#custom-button-injection-story button[aria-label="Custom"]{ border: 1px solid green; }')} </script>
<script> {initializeIcons()} </script>
# Custom Button Injection
@ -39,7 +40,7 @@ Max number of buttons: '3'
<Canvas
of={CustomButtonInjectionStories.PrimaryCustomButtonInjectionDocsOnly}
source={{ code: PrimaryCustomButtonInjectionExampleText }}
layout='centered'
layout="centered"
/>
### Desktop: Secondary Main Bar
@ -49,7 +50,7 @@ Max number of buttons: '2'
<Canvas
of={CustomButtonInjectionStories.SecondaryCustomButtonInjectionDocsOnly}
source={{ code: SecondaryCustomButtonInjectionExampleText }}
layout='centered'
layout="centered"
/>
### Desktop: Overflow More Button
@ -59,7 +60,7 @@ Max number of buttons: '∞'
<Canvas
of={CustomButtonInjectionStories.OverflowCustomButtonInjectionDocsOnly}
source={{ code: OverflowCustomButtonInjectionExampleText }}
layout='centered'
layout="centered"
/>
### Mobile: Primary and Overflow Contextual Menu
@ -69,7 +70,7 @@ Max number of buttons in primary: '1' Max number of buttons in Contextual Menu:
<Canvas
of={CustomButtonInjectionStories.MobileCustomButtonInjectionDocsOnly}
source={{ code: MobileCustomButtonInjectionExampleText }}
layout='centered'
layout="centered"
/>
### Custom Button With State
@ -77,7 +78,7 @@ Max number of buttons in primary: '1' Max number of buttons in Contextual Menu:
<Canvas
of={CustomButtonInjectionStories.CustomButtonWithStateDocsOnly}
source={{ code: CustomButtonWithStateExampleText }}
layout='centered'
layout="centered"
/>
### Custom Button With Async loading State
@ -85,7 +86,7 @@ Max number of buttons in primary: '1' Max number of buttons in Contextual Menu:
<Canvas
of={CustomButtonInjectionStories.CustomButtonWithAsyncStateDocsOnly}
source={{ code: CustomButtonWithAsyncStateExampleText }}
layout='centered'
layout="centered"
/>
### Legacy Control Bar Custom Button Injection
@ -93,7 +94,7 @@ Max number of buttons in primary: '1' Max number of buttons in Contextual Menu:
<Canvas
of={CustomButtonInjectionStories.LegacyControlBarCustomButtonInjectionDocsOnly}
source={{ code: LegacyControlBarCustomButtonInjectionExampleText }}
layout='centered'
layout="centered"
/>
## Props

Просмотреть файл

@ -1,9 +1,9 @@
import React from 'react';
export const CustomButtonWithAsyncStateExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/CustomButtonWithAsyncStateExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -11,9 +11,9 @@ export const CustomButtonWithAsyncStateExample = (): JSX.Element => {
};
export const CustomButtonWithStateExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/CustomButtonWithStateExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -21,9 +21,9 @@ export const CustomButtonWithStateExample = (): JSX.Element => {
};
export const LegacyControlBarCustomButtonInjectionExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/LegacyControlBarCustomButtonInjectionExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -31,9 +31,9 @@ export const LegacyControlBarCustomButtonInjectionExample = (): JSX.Element => {
};
export const MobileCustomButtonInjectionExample = (): JSX.Element => {
return (
<img style={{ width: '100%', maxWidth: '20rem' }}
<img
style={{ width: '100%', maxWidth: '20rem' }}
src="images/custom-button-injection/MobileCustomButtonInjectionExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -41,9 +41,9 @@ export const MobileCustomButtonInjectionExample = (): JSX.Element => {
};
export const OverflowCustomButtonInjectionExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/OverflowCustomButtonInjectionExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -51,9 +51,9 @@ export const OverflowCustomButtonInjectionExample = (): JSX.Element => {
};
export const PrimaryCustomButtonInjectionExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/PrimaryCustomButtonInjectionExample.png"
alt="Call composite where all participants have their camera turned off"
/>
@ -61,9 +61,9 @@ export const PrimaryCustomButtonInjectionExample = (): JSX.Element => {
};
export const SecondaryCustomButtonInjectionExample = (): JSX.Element => {
return (
<img style={{ width: '100%' }}
<img
style={{ width: '100%' }}
src="images/custom-button-injection/SecondaryCustomButtonInjectionExample.png"
alt="Call composite where all participants have their camera turned off"
/>