-
+
+
+
+
+
+
+
+
+
+
{showSpace && (
diff --git a/apps/react/app/globals.css b/apps/react/app/globals.css
index 0a2ce99d..2f62d7c9 100644
--- a/apps/react/app/globals.css
+++ b/apps/react/app/globals.css
@@ -110,7 +110,13 @@ a {
}
}
+.flatfile_iframe-wrapper,
+.flatfile_initIframe-wrapper {
+ top: 60px !important;
+ height: calc(100dvh - 60px) !important;
+}
-.flatfile_iframe-wrapper {
- top: 100px !important;
-}
\ No newline at end of file
+.flatfile_iFrameContainer,
+.flatfile_initIFrameContainer {
+ height: auto !important;
+}
diff --git a/apps/react/app/page.tsx b/apps/react/app/page.tsx
index f80d3d5e..5d7ea21c 100644
--- a/apps/react/app/page.tsx
+++ b/apps/react/app/page.tsx
@@ -6,7 +6,9 @@ import { FlatfileProvider } from '@flatfile/react'
export default function Home() {
const PUBLISHABLE_KEY = process.env.NEXT_PUBLIC_FLATFILE_PUBLISHABLE_KEY
- if (!PUBLISHABLE_KEY) return <>No Publishable Key Available>
+ if (!PUBLISHABLE_KEY) {
+ return <>No Publishable Key Available>
+ }
return (
void
+ setOnClose: (onClose: () => (undefined | (() => void))) => void,
setOpen: (open: boolean) => void
space?: CreateNewSpace | ReUseSpace
sessionSpace?: any
@@ -59,6 +61,8 @@ export const FlatfileContext = createContext({
environmentId: undefined,
apiUrl: '',
open: true,
+ onClose: undefined,
+ setOnClose: () => {},
setOpen: () => {},
space: undefined,
sessionSpace: undefined,
diff --git a/packages/react/src/components/FlatfileProvider.tsx b/packages/react/src/components/FlatfileProvider.tsx
index 7aa68248..52b71b2d 100644
--- a/packages/react/src/components/FlatfileProvider.tsx
+++ b/packages/react/src/components/FlatfileProvider.tsx
@@ -17,9 +17,15 @@ import { convertDatesToISO } from '../utils/convertDatesToISO'
import { createSpaceInternal } from '../utils/createSpaceInternal'
import { getSpace } from '../utils/getSpace'
import { EmbeddedIFrameWrapper } from './EmbeddedIFrameWrapper'
-import FlatfileContext, { DEFAULT_CREATE_SPACE } from './FlatfileContext'
+import FlatfileContext, {
+ DEFAULT_CREATE_SPACE,
+ FlatfileContextType,
+} from './FlatfileContext'
-import { attachStyleSheet } from '../utils/attachStyleSheet'
+import {
+ attachStyleSheet,
+ useAttachStyleSheet,
+} from '../utils/attachStyleSheet'
const configDefaults: IFrameTypes = {
preload: true,
@@ -41,6 +47,7 @@ export const FlatfileProvider: React.FC = ({
apiUrl = 'https://platform.flatfile.com/api',
config,
}) => {
+ useAttachStyleSheet(config?.styleSheetOptions)
const [internalAccessToken, setInternalAccessToken] = useState<
string | undefined | null
>(accessToken)
@@ -56,6 +63,8 @@ export const FlatfileProvider: React.FC = ({
space: Flatfile.SpaceConfig & { id?: string }
}>(DEFAULT_CREATE_SPACE)
+ const [onClose, setOnClose] = useState void)>()
+
const iframe = useRef(null)
const FLATFILE_PROVIDER_CONFIG = { ...config, ...configDefaults }
@@ -217,15 +226,9 @@ export const FlatfileProvider: React.FC = ({
}
// Works but only after the iframe is visible
}
- }
- const styleSheetRef = useRef(false)
- useEffect(() => {
- if (!styleSheetRef.current) {
- attachStyleSheet(config?.styleSheetOptions)
- styleSheetRef.current = true
- }
- }, [config?.styleSheetOptions, styleSheetRef])
+ onClose?.()
+ }
// Listen to the postMessage event from the created iFrame
useEffect(() => {
@@ -280,12 +283,14 @@ export const FlatfileProvider: React.FC = ({
}, [ready, open])
const providerValue = useMemo(
- () => ({
+ (): FlatfileContextType => ({
...(publishableKey ? { publishableKey } : {}),
...(internalAccessToken ? { accessToken: internalAccessToken } : {}),
apiUrl,
environmentId,
open,
+ onClose,
+ setOnClose,
setOpen,
sessionSpace,
setSessionSpace,
@@ -319,6 +324,8 @@ export const FlatfileProvider: React.FC = ({
ready,
iframe,
FLATFILE_PROVIDER_CONFIG,
+ onClose,
+ setOnClose,
]
)
diff --git a/packages/react/src/components/_tests_/FlatfileProvider.spec.tsx b/packages/react/src/components/_tests_/FlatfileProvider.spec.tsx
index c68e3a98..fd615cb1 100644
--- a/packages/react/src/components/_tests_/FlatfileProvider.spec.tsx
+++ b/packages/react/src/components/_tests_/FlatfileProvider.spec.tsx
@@ -13,6 +13,8 @@ export const FlatfileProviderValue: FlatfileContextType = {
apiUrl: '',
open: false,
setOpen: jest.fn(),
+ onClose: undefined,
+ setOnClose: jest.fn(),
setSessionSpace: jest.fn(),
listener: new FlatfileListener(),
setListener: jest.fn(),
diff --git a/packages/react/src/components/embeddedStyles.tsx b/packages/react/src/components/embeddedStyles.tsx
index b83dfb66..ab472415 100644
--- a/packages/react/src/components/embeddedStyles.tsx
+++ b/packages/react/src/components/embeddedStyles.tsx
@@ -17,16 +17,19 @@ export const getContainerStyles = (isModal: boolean): React.CSSProperties => {
return isModal
? {
backgroundColor: 'rgba(0, 0, 0, 0.1)',
+ boxSizing: 'border-box',
display: 'flex',
- height: 'calc(100vh - 40px)',
- width: 'calc(100% - 100px)',
+ height: '100dvh',
+ width: '100dvw',
+ left: '0',
+ top: '0',
padding: '50px',
position: 'fixed',
zIndex: '1000',
}
: {
- width: '100%',
height: '100%',
+ width: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
diff --git a/packages/react/src/components/style.scss b/packages/react/src/components/style.scss
index 0d49273a..580949c1 100644
--- a/packages/react/src/components/style.scss
+++ b/packages/react/src/components/style.scss
@@ -39,6 +39,7 @@
}
.flatfile_iframe-wrapper {
+ box-sizing: border-box;
color: var(--ff-text-color);
font-family: var(--ff-text-font);
font-size: var(--size-base);
@@ -46,6 +47,12 @@
margin: 0;
transition: opacity 0.25s ease-in-out;
}
+.flatfile_iframe-wrapper.flatfile_displayAsModal {
+ height: 100%;
+ height: 100vh;
+ width: 100%;
+ width: 100vw;
+}
.flatfile-close-button svg {
fill: lightgray;
width: 10px;
@@ -167,11 +174,11 @@
box-sizing: border-box;
display: block;
height: 100%;
- left: 0px;
+ left: 0;
overflow-y: auto;
- position: fixed;
- right: 0px;
+ position: absolute;
tab-size: 4;
+ top: 0;
width: 100%;
z-index: 1200;
}
diff --git a/packages/react/src/hooks/legacy/usePortal.tsx b/packages/react/src/hooks/legacy/usePortal.tsx
index 777628da..ef15f945 100644
--- a/packages/react/src/hooks/legacy/usePortal.tsx
+++ b/packages/react/src/hooks/legacy/usePortal.tsx
@@ -1,23 +1,24 @@
-import React, { JSX, useEffect, useState } from 'react'
-import DefaultError from '../../components/legacy/Error'
-import Space from '../../components/legacy/LegacySpace'
-import Spinner from '../../components/Spinner'
+// Bug where the default export function is not being used properly in some build tooling
+import { FlatfileClient } from '@flatfile/api'
import {
- State,
- JobHandler,
- SheetHandler,
createWorkbookFromSheet,
DefaultSubmitSettings,
+ JobHandler,
+ SheetHandler,
+ State,
} from '@flatfile/embedded-utils'
-import { initializeSpace } from '../../utils/initializeSpace'
-import { getSpace } from '../../utils/getSpace'
import { FlatfileRecord } from '@flatfile/hooks'
import { FlatfileEvent, FlatfileListener } from '@flatfile/listener'
import { recordHook } from '@flatfile/plugin-record-hook'
+import React, { JSX, useEffect, useState } from 'react'
+import DefaultError from '../../components/legacy/Error'
+import Space from '../../components/legacy/LegacySpace'
+import Spinner from '../../components/Spinner'
import { IReactSimpleOnboarding } from '../../types/IReactSimpleOnboarding'
+import { useAttachStyleSheet } from '../../utils/attachStyleSheet'
+import { getSpace } from '../../utils/getSpace'
+import { initializeSpace } from '../../utils/initializeSpace'
-// Bug where the default export function is not being used properly in some build tooling
-import { FlatfileClient } from '@flatfile/api'
const api = new FlatfileClient()
/**
* @deprecated - use FlatfileProvider and Space components instead
@@ -26,6 +27,7 @@ const api = new FlatfileClient()
export const usePortal = (
props: IReactSimpleOnboarding
): JSX.Element | null => {
+ useAttachStyleSheet()
const { errorTitle, loading: LoadingElement, apiUrl } = props
const [initError, setInitError] = useState()
const [state, setState] = useState({
diff --git a/packages/react/src/hooks/legacy/useSpace.tsx b/packages/react/src/hooks/legacy/useSpace.tsx
index 3fa351c3..bab7e1a5 100644
--- a/packages/react/src/hooks/legacy/useSpace.tsx
+++ b/packages/react/src/hooks/legacy/useSpace.tsx
@@ -1,17 +1,19 @@
+import { State } from '@flatfile/embedded-utils'
import React, { JSX, useEffect, useState } from 'react'
import DefaultError from '../../components/legacy/Error'
import Space from '../../components/legacy/LegacySpace'
import Spinner from '../../components/Spinner'
-import { State } from '@flatfile/embedded-utils'
-import { initializeSpace } from '../../utils/initializeSpace'
-import { getSpace } from '../../utils/getSpace'
import { IReactSpaceProps } from '../../types'
+import { useAttachStyleSheet } from '../../utils/attachStyleSheet'
+import { getSpace } from '../../utils/getSpace'
+import { initializeSpace } from '../../utils/initializeSpace'
/**
* @deprecated - use FlatfileProvider and Space components instead
* This hook is used to initialize a space and return the Space component
*/
export const useSpace = (props: IReactSpaceProps): JSX.Element | null => {
+ useAttachStyleSheet()
const {
error: ErrorElement,
errorTitle,
diff --git a/packages/react/src/hooks/legacy/useSpaceTrigger.tsx b/packages/react/src/hooks/legacy/useSpaceTrigger.tsx
index 712f17c8..36a6b5cb 100644
--- a/packages/react/src/hooks/legacy/useSpaceTrigger.tsx
+++ b/packages/react/src/hooks/legacy/useSpaceTrigger.tsx
@@ -1,11 +1,12 @@
+import { State } from '@flatfile/embedded-utils'
import React, { JSX, useState } from 'react'
import DefaultError from '../../components/legacy/Error'
import Space from '../../components/legacy/LegacySpace'
import Spinner from '../../components/Spinner'
-import { State } from '@flatfile/embedded-utils'
-import { initializeSpace } from '../../utils/initializeSpace'
-import { getSpace } from '../../utils/getSpace'
import { IReactSpaceProps } from '../../types'
+import { useAttachStyleSheet } from '../../utils/attachStyleSheet'
+import { getSpace } from '../../utils/getSpace'
+import { initializeSpace } from '../../utils/initializeSpace'
type IUseSpace = { OpenEmbed: () => Promise; Space: () => JSX.Element }
@@ -15,6 +16,7 @@ type IUseSpace = { OpenEmbed: () => Promise; Space: () => JSX.Element }
*/
export const initializeFlatfile = (props: IReactSpaceProps): IUseSpace => {
+ useAttachStyleSheet()
const { error: ErrorElement, errorTitle, loading: LoadingElement } = props
const [initError, setInitError] = useState()
const [loading, setLoading] = useState(false)
diff --git a/packages/react/src/hooks/useFlatfile.ts b/packages/react/src/hooks/useFlatfile.ts
index f54d6558..1f7fbf8b 100644
--- a/packages/react/src/hooks/useFlatfile.ts
+++ b/packages/react/src/hooks/useFlatfile.ts
@@ -1,31 +1,49 @@
-import { useContext } from 'react'
+import { useCallback, useContext, useEffect } from 'react'
import FlatfileContext from '../components/FlatfileContext'
import { ClosePortalOptions } from '../types'
-export const useFlatfile: () => {
+interface UseFlatfileOptions {
+ onClose?: () => void
+}
+
+export const useFlatfile: (useFlatfileOptions?: UseFlatfileOptions) => {
openPortal: () => void
closePortal: (options?: ClosePortalOptions) => void
open: boolean
setListener: (listener: any) => void
listener: any
-} = () => {
+} = (useFlatfileOptions: UseFlatfileOptions = {}) => {
const context = useContext(FlatfileContext)
if (!context) {
throw new Error('useFlatfile must be used within a FlatfileProvider')
}
+ const onCloseCallback = useCallback(
+ useFlatfileOptions.onClose ?? (() => {}),
+ [typeof useFlatfileOptions.onClose]
+ )
+
+ useEffect(() => {
+ if (context.onClose !== onCloseCallback) {
+ context.setOnClose(() => onCloseCallback)
+ }
+ }, [context.onClose, context.setOnClose, onCloseCallback])
+
const { open, setOpen, setListener, listener, apiUrl, resetSpace, ready } =
context
- const openPortal = () => {
+ const openPortal = useCallback(() => {
;(window as any).CROSSENV_FLATFILE_API_URL = apiUrl
setOpen(true)
- }
+ }, [setOpen, apiUrl])
- const closePortal = (options?: ClosePortalOptions) => {
- resetSpace(options)
- }
+ const closePortal = useCallback(
+ (options?: ClosePortalOptions) => {
+ resetSpace(options)
+ },
+ [resetSpace]
+ )
return {
openPortal,
diff --git a/packages/react/src/utils/attachStyleSheet.ts b/packages/react/src/utils/attachStyleSheet.ts
index bf141429..28186d72 100644
--- a/packages/react/src/utils/attachStyleSheet.ts
+++ b/packages/react/src/utils/attachStyleSheet.ts
@@ -1,6 +1,7 @@
import { styleInject } from '../utils/styleInject'
import stylesheet from '../components/style.scss'
+import { MutableRefObject } from 'react'
export type StyleSheetOptions = {
insertAt?: 'top'
nonce?: string
@@ -9,3 +10,12 @@ export type StyleSheetOptions = {
export function attachStyleSheet(options?: StyleSheetOptions) {
styleInject(stylesheet, options)
}
+
+const styleSheetAttachedRef: MutableRefObject = { current: false }
+
+export function useAttachStyleSheet(options?: StyleSheetOptions) {
+ if (!styleSheetAttachedRef.current) {
+ attachStyleSheet(options)
+ styleSheetAttachedRef.current = true
+ }
+}