44/* @conditional -compile-remove(image-overlay) */
55import { DefaultButton , Icon , IconButton , Modal , Stack , mergeStyles } from '@fluentui/react' ;
66/* @conditional -compile-remove(image-overlay) */
7- import React , { useState } from 'react' ;
7+ import React , { SyntheticEvent , useState } from 'react' ;
88/* @conditional -compile-remove(image-overlay) */
99import {
1010 bodyContainer ,
@@ -25,11 +25,11 @@ import {
2525 titleStyle
2626} from './styles/ImageOverlay.style' ;
2727/* @conditional -compile-remove(image-overlay) */
28- import { FluentThemeProvider } from '../theming/FluentThemeProvider' ;
28+ import { useTheme } from '../theming/FluentThemeProvider' ;
2929/* @conditional -compile-remove(image-overlay) */
3030import { useLocale } from '../localization' ;
3131/* @conditional -compile-remove(image-overlay) */
32- import { imageOverlayTheme } from '../theming' ;
32+ import { ChatTheme } from '../theming' ;
3333
3434/* @conditional -compile-remove(image-overlay) */
3535/**
@@ -63,9 +63,13 @@ export interface ImageOverlayProps {
6363 */
6464 onDismiss : ( ) => void ;
6565 /**
66- * Optional callback called when the download button is clicked. If not provided, the download button will not be rendered .
66+ * Callback called when the download button is clicked.
6767 */
68- onDownloadButtonClicked ?: ( imageSrc : string ) => void ;
68+ onDownloadButtonClicked : ( imageSrc : string ) => void ;
69+ /**
70+ * Callback called when there's an error loading the image.
71+ */
72+ onError ?: ( event : SyntheticEvent < HTMLImageElement , Event > ) => void ;
6973}
7074/* @conditional -compile-remove(image-overlay) */
7175/**
@@ -90,50 +94,47 @@ export interface ImageOverlayStrings {
9094 * @beta
9195 */
9296export const ImageOverlay = ( props : ImageOverlayProps ) : JSX . Element => {
93- const { isOpen, imageSrc, title, titleIcon, altText, onDownloadButtonClicked, onDismiss } = props ;
97+ const { isOpen, imageSrc, title, titleIcon, altText, onDownloadButtonClicked, onDismiss, onError } = props ;
98+ const theme = useTheme ( ) as unknown as ChatTheme ;
9499
95100 /* @conditional -compile-remove(image-overlay) */
96101 const localeStrings = useLocale ( ) . strings . imageOverlay ;
97102
98103 const [ isImageLoaded , setIsImageLoaded ] = useState < boolean > ( true ) ;
99104
100- const imageStyle = isImageLoaded ? normalImageStyle : brokenImageStyle ( imageOverlayTheme ) ;
105+ const imageStyle = isImageLoaded ? normalImageStyle : brokenImageStyle ( theme ) ;
101106
102107 const renderHeaderBar = ( ) : JSX . Element => {
103108 return (
104109 < Stack className = { mergeStyles ( headerStyle ) } >
105110 < Stack className = { mergeStyles ( titleBarContainerStyle ) } >
106111 { titleIcon }
107- < Stack . Item className = { mergeStyles ( titleStyle ( imageOverlayTheme ) ) } aria-label = { title || 'Image' } >
112+ < Stack . Item className = { mergeStyles ( titleStyle ( theme ) ) } aria-label = { title || 'Image' } >
108113 { title }
109114 </ Stack . Item >
110115 </ Stack >
111116 < Stack className = { mergeStyles ( controlBarContainerStyle ) } >
112- { onDownloadButtonClicked && (
113- < DefaultButton
114- className = { mergeStyles ( downloadButtonStyle ) }
115- /* @conditional -compile-remove(image-overlay) */
116- text = { localeStrings . downloadButtonLabel }
117- onClick = { ( ) => onDownloadButtonClicked && onDownloadButtonClicked ( imageSrc ) }
118- onRenderIcon = { ( ) => < Icon iconName = { downloadIcon . iconName } className = { mergeStyles ( downloadIconStyle ) } /> }
119- aria-live = { 'polite' }
120- /* @conditional -compile-remove(image-overlay) */
121- aria-label = { localeStrings . downloadButtonLabel }
122- />
123- ) }
124- { onDownloadButtonClicked && (
125- < IconButton
126- iconProps = { downloadIcon }
127- className = { mergeStyles ( smallDownloadButtonContainerStyle ( imageOverlayTheme ) ) }
128- onClick = { ( ) => onDownloadButtonClicked && onDownloadButtonClicked ( imageSrc ) }
129- /* @conditional -compile-remove(image-overlay) */
130- aria-label = { localeStrings . downloadButtonLabel }
131- aria-live = { 'polite' }
132- />
133- ) }
117+ < DefaultButton
118+ className = { mergeStyles ( downloadButtonStyle ( theme ) ) }
119+ /* @conditional -compile-remove(image-overlay) */
120+ text = { localeStrings . downloadButtonLabel }
121+ onClick = { ( ) => onDownloadButtonClicked ( imageSrc ) }
122+ onRenderIcon = { ( ) => < Icon iconName = { downloadIcon . iconName } className = { mergeStyles ( downloadIconStyle ) } /> }
123+ aria-live = { 'polite' }
124+ /* @conditional -compile-remove(image-overlay) */
125+ aria-label = { localeStrings . downloadButtonLabel }
126+ />
127+ < IconButton
128+ iconProps = { downloadIcon }
129+ className = { mergeStyles ( smallDownloadButtonContainerStyle ( theme ) ) }
130+ onClick = { ( ) => onDownloadButtonClicked ( imageSrc ) }
131+ /* @conditional -compile-remove(image-overlay) */
132+ aria-label = { localeStrings . downloadButtonLabel }
133+ aria-live = { 'polite' }
134+ />
134135 < IconButton
135136 iconProps = { cancelIcon }
136- className = { mergeStyles ( closeButtonStyles ( imageOverlayTheme ) ) }
137+ className = { mergeStyles ( closeButtonStyles ( theme ) ) }
137138 onClick = { onDismiss }
138139 /* @conditional -compile-remove(image-overlay) */
139140 ariaLabel = { localeStrings . dismissButtonAriaLabel }
@@ -154,8 +155,9 @@ export const ImageOverlay = (props: ImageOverlayProps): JSX.Element => {
154155 alt = { altText || 'image' }
155156 aria-label = { 'image-overlay-main-image' }
156157 aria-live = { 'polite' }
157- onError = { ( ) => {
158+ onError = { ( event ) => {
158159 setIsImageLoaded ( false ) ;
160+ onError && onError ( event ) ;
159161 } }
160162 onClick = { ( event ) => event . stopPropagation ( ) }
161163 onDoubleClick = { ( event ) => {
@@ -168,18 +170,16 @@ export const ImageOverlay = (props: ImageOverlayProps): JSX.Element => {
168170 } ;
169171
170172 return (
171- < FluentThemeProvider fluentTheme = { imageOverlayTheme } >
172- < Modal
173- titleAriaId = { title }
174- isOpen = { isOpen }
175- onDismiss = { onDismiss }
176- overlay = { { styles : { ...overlayStyles ( imageOverlayTheme ) } } }
177- styles = { { main : focusTrapZoneStyle , scrollableContent : scrollableContentStyle } }
178- isDarkOverlay = { true }
179- >
180- { renderHeaderBar ( ) }
181- { renderBodyWithLightDismiss ( ) }
182- </ Modal >
183- </ FluentThemeProvider >
173+ < Modal
174+ titleAriaId = { title }
175+ isOpen = { isOpen }
176+ onDismiss = { onDismiss }
177+ overlay = { { styles : { ...overlayStyles ( theme ) } } }
178+ styles = { { main : focusTrapZoneStyle , scrollableContent : scrollableContentStyle } }
179+ isDarkOverlay = { true }
180+ >
181+ { renderHeaderBar ( ) }
182+ { renderBodyWithLightDismiss ( ) }
183+ </ Modal >
184184 ) ;
185185} ;
0 commit comments