Skip to content

Commit

Permalink
⭐️ Impl: ModalSheetView Native + JS Scaffolding
Browse files Browse the repository at this point in the history
  • Loading branch information
dominicstop committed Sep 25, 2024
1 parent f69e4cb commit df59ff8
Show file tree
Hide file tree
Showing 26 changed files with 376 additions and 136 deletions.
4 changes: 2 additions & 2 deletions example/ios/IosModalExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = ZC7A6XV8GR;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = IosModalExample/Info.plist;
Expand Down Expand Up @@ -499,7 +499,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 6;
CURRENT_PROJECT_VERSION = 8;
DEVELOPMENT_TEAM = ZC7A6XV8GR;
INFOPLIST_FILE = IosModalExample/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
2 changes: 1 addition & 1 deletion example/ios/IosModalExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>6</string>
<string>8</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
Expand Down
2 changes: 1 addition & 1 deletion example/ios/IosModalExampleTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>6</string>
<string>8</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// RNIModalView.h
// RNIModalSheetView.h
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
Expand All @@ -22,6 +22,6 @@
namespace react = facebook::react;
#endif

@interface RNIModalView : RNIBaseView
@interface RNIModalSheetView : RNIBaseView

@end
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//
// RNIModalView.mm
// RNIModalSheetView.mm
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
//

#import "RNIModalView.h"
#import "RNIModalSheetView.h"

#import "react-native-ios-modal/Swift.h"
#import <react-native-ios-utilities/RNIBaseView.h>
Expand All @@ -17,7 +17,7 @@
#import <react-native-ios-utilities/RNIObjcUtils.h>

#if RCT_NEW_ARCH_ENABLED
#include "RNIModalViewComponentDescriptor.h"
#include "RNIModalSheetViewComponentDescriptor.h"

#include <react-native-ios-utilities/RNIBaseViewState.h>
#include <react-native-ios-utilities/RNIBaseViewProps.h>
Expand All @@ -44,10 +44,10 @@
#endif


@interface RNIModalView () <
@interface RNIModalSheetView () <
RNIContentViewParentDelegate,
#ifdef RCT_NEW_ARCH_ENABLED
RCTRNIModalViewViewProtocol
RCTRNIModalSheetViewViewProtocol
#else
RCTInvalidating
#endif
Expand All @@ -56,7 +56,7 @@ @interface RNIModalView () <
}
@end

@implementation RNIModalView {
@implementation RNIModalSheetView {
}

// MARK: - Init
Expand All @@ -71,7 +71,7 @@ - (void)initCommon {

+ (Class)viewDelegateClass
{
return [RNIModalViewDelegate class];
return [RNIModalSheetViewDelegate class];
}

// MARK: - Fabric
Expand All @@ -80,12 +80,12 @@ + (Class)viewDelegateClass
#if RCT_NEW_ARCH_ENABLED
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNIModalViewComponentDescriptor>();
return concreteComponentDescriptorProvider<RNIModalSheetViewComponentDescriptor>();
}

Class<RCTComponentViewProtocol> RNIModalViewCls(void)
Class<RCTComponentViewProtocol> RNIModalSheetViewCls(void)
{
return RNIModalView.class;
return RNIModalSheetView.class;
}
#else

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// RNIModalViewComponentDescriptor.h
// RNIModalSheetViewComponentDescriptor.h
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
Expand All @@ -8,7 +8,7 @@
#if __cplusplus
#pragma once

#include "RNIModalViewShadowNode.h"
#include "RNIModalSheetViewShadowNode.h"
#include "RNIBaseViewComponentDescriptor.h"

#include <react-native-ios-utilities/RNIBaseViewState.h>
Expand All @@ -17,8 +17,10 @@

namespace facebook::react {

class RNIModalViewComponentDescriptor final
: public RNIBaseViewComponentDescriptor<RNIModalViewShadowNode> {
class RNIModalSheetViewComponentDescriptor final : public RNIBaseViewComponentDescriptor<
RNIModalSheetViewShadowNode,
RNIModalSheetViewComponentName
> {

public:
using RNIBaseViewComponentDescriptor::RNIBaseViewComponentDescriptor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// RNIModalViewDelegate.swift
// RNIModalSheetViewDelegate.swift
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
Expand All @@ -9,10 +9,10 @@ import UIKit
import react_native_ios_utilities
import DGSwiftUtilities

@objc(RNIModalViewDelegate)
public final class RNIModalViewDelegate: UIView, RNIContentView {
@objc(RNIModalSheetViewDelegate)
public final class RNIModalSheetViewDelegate: UIView, RNIContentView {

public static var propKeyPathMap: Dictionary<String, PartialKeyPath<RNIModalViewDelegate>> {
public static var propKeyPathMap: Dictionary<String, PartialKeyPath<RNIModalSheetViewDelegate>> {
return [:];
};

Expand Down Expand Up @@ -81,9 +81,9 @@ public final class RNIModalViewDelegate: UIView, RNIContentView {
};
};

extension RNIModalViewDelegate: RNIContentViewDelegate {
extension RNIModalSheetViewDelegate: RNIContentViewDelegate {

public typealias KeyPathRoot = RNIModalViewDelegate;
public typealias KeyPathRoot = RNIModalSheetViewDelegate;

// MARK: Paper + Fabric
// --------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//
// RNIModalViewManager.m
// RNIModalSheetViewManager.m
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
//

#import "RNIModalView.h"
#import "RNIModalSheetView.h"
#import <objc/runtime.h>

#import "react-native-ios-utilities/RNIBaseViewUtils.h"
Expand All @@ -15,17 +15,17 @@
#import <React/RCTUIManager.h>


@interface RNIModalViewManager : RCTViewManager
@interface RNIModalSheetViewManager : RCTViewManager
@end

@implementation RNIModalViewManager
@implementation RNIModalSheetViewManager

RCT_EXPORT_MODULE(RNIModalView)
RCT_EXPORT_MODULE(RNIModalSheetView)

#ifndef RCT_NEW_ARCH_ENABLED
- (UIView *)view
{
return [[RNIModalView new] initWithBridge:self.bridge];
return [[RNIModalSheetView new] initWithBridge:self.bridge];
}
#endif

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// RNIModalViewShadowNode.h
// RNIModalSheetViewShadowNode.h
// react-native-ios-modal
//
// Created by Dominic Go on 6/6/24.
Expand All @@ -21,10 +21,10 @@

namespace facebook::react {

JSI_EXPORT extern const char RNIModalViewComponentName[] = "RNIModalView";
JSI_EXPORT extern const char RNIModalSheetViewComponentName[] = "RNIModalSheetView";

class JSI_EXPORT RNIModalViewShadowNode final : public RNIBaseViewShadowNode<
RNIModalViewComponentName,
class JSI_EXPORT RNIModalSheetViewShadowNode final : public RNIBaseViewShadowNode<
RNIModalSheetViewComponentName,
RNIBaseViewProps,
RNIBaseViewEventEmitter
> {
Expand Down
12 changes: 12 additions & 0 deletions src/components/ModalSheetView/ModalSheetContentMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { OnDidSetViewIDEventPayload } from 'react-native-ios-utilities';

export type ModalSheetContentEntry = {
didDetachFromOriginalParent: boolean;
};

export type ModalSheetContentMap =
Record<OnDidSetViewIDEventPayload['viewID'], ModalSheetContentEntry>;

export const DEFAULT_SHEET_CONTENT_ENTRY: ModalSheetContentEntry = Object.freeze({
didDetachFromOriginalParent: false,
});
56 changes: 56 additions & 0 deletions src/components/ModalSheetView/ModalSheetView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from 'react';
import { StyleSheet } from 'react-native';

import type { ModalSheetViewProps, ModalSheetViewRef } from './ModalSheetViewTypes';
import type { ModalSheetViewContentProps } from './ModalSheetViewContentTypes';
import type { ModalSheetContentMap } from './ModalSheetContentMap';

import { RNIModalSheetView, type RNIModalSheetViewRef } from '../../native_components/RNIModalSheetVIew';


export const ModalSheetView = React.forwardRef<
ModalSheetViewRef,
ModalSheetViewProps
>((props, ref) => {

const nativeRef = React.useRef<RNIModalSheetViewRef | null>();

const [
modalSheetContentMap,
setModalSheetContentMap
] = React.useState<ModalSheetContentMap>({});

React.useImperativeHandle(ref, () => ({
presentModal: async () => {
},
}));

const shouldEnableDebugBackgroundColors =
props.shouldEnableDebugBackgroundColors ?? false;

const children = React.Children.map(props.children, (child) => {
return React.cloneElement(
child as React.ReactElement<ModalSheetViewContentProps>,
{
modalSheetContentMap,
}
);
});

return (
<RNIModalSheetView
ref={ref => nativeRef.current = ref}
style={styles.nativeModalSheet}
>
{children}
</RNIModalSheetView>
);
});

const styles = StyleSheet.create({
nativeModalSheet: {
position: 'absolute',
pointerEvents: 'none',
opacity: 0,
},
});
77 changes: 77 additions & 0 deletions src/components/ModalSheetView/ModalSheetViewContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from 'react';
import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';

import { RNIWrapperView, type StateViewID } from 'react-native-ios-utilities';

import { DEFAULT_SHEET_CONTENT_ENTRY } from './ModalSheetContentMap';
import type { ModalSheetViewContentProps } from './ModalSheetViewContentTypes';

import { IS_USING_NEW_ARCH } from '../../constants/LibEnv';


export function ModalSheetViewContent(
props: React.PropsWithChildren<ModalSheetViewContentProps>
) {
const [viewID, setViewID] = React.useState<StateViewID>();

const wrapperStyle: StyleProp<ViewStyle> = [
props.shouldEnableDebugBackgroundColors && styles.wrapperViewDebug,
props.contentContainerStyle,
];

const detachedSubviewEntry =
(viewID != null ? props.modalSheetContentMap?.[viewID] : undefined )
?? DEFAULT_SHEET_CONTENT_ENTRY;

const didDetach =
(props.isParentDetached ?? false)
|| detachedSubviewEntry.didDetachFromOriginalParent;

return (
<RNIWrapperView
{...props}
style={[
...(IS_USING_NEW_ARCH
? wrapperStyle
: []
),
(didDetach
? styles.wrapperViewDetached
: styles.wrapperViewAttached
),
props.style,
]}
onDidSetViewID={(event) => {
props.onDidSetViewID?.(event);
setViewID(event.nativeEvent.viewID);

props.onDidSetViewID?.(event);
event.stopPropagation();
}}
>
{IS_USING_NEW_ARCH ? (
props.children
) : (
<View style={[
styles.innerWrapperContainerForPaper,
...wrapperStyle,
]}>
{props.children}
</View>
)}
</RNIWrapperView>
);
};

const styles = StyleSheet.create({
wrapperViewAttached: {
},
wrapperViewDetached: {
},
wrapperViewDebug: {
backgroundColor: 'rgba(255,0,255,0.3)',
},
innerWrapperContainerForPaper: {
flex: 1,
},
});
Loading

0 comments on commit df59ff8

Please sign in to comment.