diff --git a/packages/turbo/README.md b/packages/turbo/README.md index 2a20bf1b..972a9589 100644 --- a/packages/turbo/README.md +++ b/packages/turbo/README.md @@ -91,6 +91,12 @@ Enables pull to refresh functionality. Default value is `true`. Enables scrolling in the webview. Default value is `true`. +### `contentInset` + +The amount by which the web view content is inset from the edges of the scroll view. + +Note: available only on iOS. + ### `stradaComponents` `VisitableView` supports defining [Strada components](https://strada.hotwired.dev/) that receive and reply to messages from web components that are present on the page within one session. This prop accepts an array of Strada components that will be registered in the webview. diff --git a/packages/turbo/ios/RNVisitableView.swift b/packages/turbo/ios/RNVisitableView.swift index 29c274f2..f8392b5c 100644 --- a/packages/turbo/ios/RNVisitableView.swift +++ b/packages/turbo/ios/RNVisitableView.swift @@ -36,6 +36,11 @@ class RNVisitableView: UIView, RNSessionSubscriber { configureWebView() } } + @objc var contentInset: [String: CGFloat] = [:] { + didSet { + configureWebView() + } + } @objc var onMessage: RCTDirectEventBlock? @objc var onVisitProposal: RCTDirectEventBlock? @objc var onOpenExternalUrl: RCTDirectEventBlock? @@ -80,6 +85,10 @@ class RNVisitableView: UIView, RNSessionSubscriber { } webView!.scrollView.isScrollEnabled = scrollEnabled + webView!.scrollView.contentInset = UIEdgeInsets(top: contentInset["top"] ?? 0, + left: contentInset["left"] ?? 0, + bottom: contentInset["bottom"] ?? 0, + right: contentInset["right"] ?? 0) } override func willMove(toWindow newWindow: UIWindow?) { diff --git a/packages/turbo/ios/RNVisitableViewManager.m b/packages/turbo/ios/RNVisitableViewManager.m index c7f18cfe..d9042cb7 100644 --- a/packages/turbo/ios/RNVisitableViewManager.m +++ b/packages/turbo/ios/RNVisitableViewManager.m @@ -18,6 +18,7 @@ @interface RCT_EXTERN_MODULE(RNVisitableViewManager, NSObject) RCT_EXPORT_VIEW_PROPERTY(applicationNameForUserAgent, NSString) RCT_EXPORT_VIEW_PROPERTY(pullToRefreshEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(scrollEnabled, BOOL) + RCT_EXPORT_VIEW_PROPERTY(contentInset, NSDictionary) RCT_EXPORT_VIEW_PROPERTY(onVisitProposal, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onOpenExternalUrl, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock) diff --git a/packages/turbo/src/RNVisitableView.ts b/packages/turbo/src/RNVisitableView.ts index dd2144b3..c0da5be7 100644 --- a/packages/turbo/src/RNVisitableView.ts +++ b/packages/turbo/src/RNVisitableView.ts @@ -19,6 +19,7 @@ import type { OpenExternalUrlEvent, FormSubmissionEvent, ContentProcessDidTerminateEvent, + ContentInsetObject, } from './types'; // Interface should match RNVisitableView exported properties in native code @@ -28,6 +29,7 @@ export interface RNVisitableViewProps { applicationNameForUserAgent?: string; pullToRefreshEnabled: boolean; scrollEnabled: boolean; + contentInset: ContentInsetObject; onLoad?: (e: NativeSyntheticEvent) => void; onMessage?: (e: NativeSyntheticEvent) => void; onError?: (e: NativeSyntheticEvent) => void; diff --git a/packages/turbo/src/VisitableView.tsx b/packages/turbo/src/VisitableView.tsx index be82ceff..bcb8084e 100644 --- a/packages/turbo/src/VisitableView.tsx +++ b/packages/turbo/src/VisitableView.tsx @@ -40,6 +40,7 @@ import type { StradaComponent, FormSubmissionEvent, ContentProcessDidTerminateEvent, + ContentInsetObject, } from './types'; import { nextEventLoopTick } from './utils/nextEventLoopTick'; @@ -50,6 +51,7 @@ export interface Props { stradaComponents?: StradaComponent[]; pullToRefreshEnabled?: boolean; scrollEnabled?: boolean; + contentInset?: ContentInsetObject; renderLoading?: RenderLoading; renderError?: RenderError; onVisitProposal: (proposal: VisitProposal) => void; @@ -80,6 +82,7 @@ const VisitableView = React.forwardRef>( stradaComponents, pullToRefreshEnabled = true, scrollEnabled = true, + contentInset = { top: 0, left: 0, right: 0, bottom: 0 }, renderLoading, renderError, onLoad, @@ -217,6 +220,7 @@ const VisitableView = React.forwardRef>( applicationNameForUserAgent={resolvedApplicationNameForUserAgent} pullToRefreshEnabled={pullToRefreshEnabled} scrollEnabled={scrollEnabled} + contentInset={contentInset} onError={onErrorCombinedHandlers} onVisitProposal={handleVisitProposal} onMessage={handleOnMessage} diff --git a/packages/turbo/src/types.ts b/packages/turbo/src/types.ts index 6343cd75..3cfe0dbb 100644 --- a/packages/turbo/src/types.ts +++ b/packages/turbo/src/types.ts @@ -44,6 +44,13 @@ export enum SystemStatusCode { UNKNOWN = -4, } +export type ContentInsetObject = { + bottom?: number; + left?: number; + right?: number; + top?: number; +}; + export type StradaMessage = { component: string; event: string;