import { FC, useMemo, RefObject, IframeHTMLAttributes } from 'react';
import { Platform, StyleSheet, View } from 'react-native';
import {
WebView,
WebViewProps as ReactNativeWebViewProps,
} from 'react-native-webview';
import { EmbedClientMessages } from '../models/EmbeddedMessageTypes';
import { tryResolveFullIframeUrl } from '../utils/urlResolution';
type WebViewProps = Omit<
ReactNativeWebViewProps,
| 'ref'
| 'onMessage'
| 'source'
| 'onFileDownload'
| 'onShouldStartLoadWithRequest'
>;
type IframeProps = Omit, 'ref' | 'src'>;
export type KomoWebViewProps = {
/**
* The URL of the embedded card experience.
* This can be obtained by querying the embed metadata endpoint.
*/
embedUrl?: string;
/**
* The URL of the authorization endpoint.
* This can be obtained by querying the embed metadata endpoint.
* If this is provided, the experience modal will first load the auth URL, and then redirect to the embed URL.
*/
embedAuthUrl?: string;
/**
* The passthrough parameters to add to the auth URL.
* These will be added to the auth URL as query parameters.
* For example, an auth0 session transfer token can be added to the auth URL as a passthrough parameter.
*/
authPassthroughParams?: URLSearchParams;
/**
* Prefill values for the form within the experience.
*/
formPrefillValues?: Record;
/**
* Extension data values for the experience.
*/
extensionDataValues?: Record;
/**
* Additional props for the iframe component.
* Only applies if the platform is web.
*/
iframeProps?: IframeProps;
/**
* Additional props for the react-native-webview component.
* Only applies if the platform is not web.
*/
webViewProps?: WebViewProps;
/**
* Callback for when a file download is requested.
* Only applies to iOS. See react-native-webview docs for more details.
*/
onFileDownload?: ReactNativeWebViewProps['onFileDownload'];
iframeRef?: RefObject;
webviewRef?: RefObject;
isLoading?: boolean;
onMessage: (data: EmbedClientMessages) => void;
};
export const KomoWebView: FC = ({
embedUrl,
embedAuthUrl,
authPassthroughParams,
formPrefillValues,
extensionDataValues,
iframeProps,
webViewProps,
onFileDownload,
iframeRef,
webviewRef,
isLoading,
onMessage,
}) => {
const iframeUrl = useMemo(
() =>
// Load the webview with the initial iframe url
tryResolveFullIframeUrl(
embedUrl,
embedAuthUrl,
authPassthroughParams,
formPrefillValues,
extensionDataValues
),
// We only want the initial iframe URL to be calculated once per modal open.
[]
);
return (
{Platform.OS === 'web' ? (
) : (
{
try {
const data = JSON.parse(e.nativeEvent.data);
onMessage(data);
} catch (error) {
console.error(error);
}
}}
onFileDownload={onFileDownload}
{...webViewProps}
style={[
styles.webview,
isLoading ? styles.iframeLoading : styles.iframeLoaded,
...(webViewProps?.style ? [webViewProps.style] : []),
]}
/>
)}
);
};
const styles = StyleSheet.create({
webviewContainer: {
width: '100%',
flex: 1,
},
webview: {
backgroundColor: 'transparent',
},
iframeLoading: {
opacity: 0,
},
iframeLoaded: {
opacity: 1,
},
});