first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

21
node_modules/react-native-safe-area-context/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Th3rd Wave
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

19
node_modules/react-native-safe-area-context/README.md generated vendored Normal file
View File

@@ -0,0 +1,19 @@
![safearea](https://github.com/user-attachments/assets/d951efe6-4d25-4ff6-b654-7aaf4519829b)
### About
App & Flow is a Montreal-based React Native engineering and consulting studio. We partner with the worlds top companies and are recommended by [Expo](https://expo.dev/consultants). Need a hand? Lets build together. team@appandflow.com
# react-native-safe-area-context
[![npm](https://img.shields.io/npm/v/react-native-safe-area-context)](https://www.npmjs.com/package/react-native-safe-area-context) ![Supports Android, iOS, web, macOS and Windows](https://img.shields.io/badge/platforms-android%20%7C%20ios%20%7C%20web%20%7C%20macos%20%7C%20windows-lightgrey.svg) ![MIT License](https://img.shields.io/npm/l/react-native-safe-area-context.svg)
[![JavaScript tests](https://github.com/AppAndFlow/react-native-safe-area-context/workflows/JavaScript%20tests/badge.svg)](https://github.com/AppAndFlow/react-native-safe-area-context/actions/workflows/js.yml) [![iOS build](https://github.com/AppAndFlow/react-native-safe-area-context/workflows/iOS%20build/badge.svg)](https://github.com/AppAndFlow/react-native-safe-area-context/actions/workflows/ios.yml) [![Android build](https://github.com/AppAndFlow/react-native-safe-area-context/workflows/Android%20build/badge.svg)](https://github.com/AppAndFlow/react-native-safe-area-context/actions/workflows/android.yml)
A flexible way to handle safe area, also works on Android and Web!
## Documentation
Check out our [documentation site](https://appandflow.github.io/react-native-safe-area-context/).
## Contributing
See the [Contributing Guide](CONTRIBUTING.md)

View File

@@ -0,0 +1,124 @@
buildscript {
def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['RNSAC_kotlinVersion']
repositories {
mavenCentral()
google()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
classpath("com.android.tools.build:gradle:7.3.1")
classpath("com.diffplug.spotless:spotless-plugin-gradle:6.11.0")
}
}
if (project == rootProject) {
apply from: "spotless.gradle"
return
}
def getExtOrDefault(name, defaultValue) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : defaultValue
}
def isNewArchitectureEnabled() {
// To opt-in for the New Architecture, you can either:
// - Set `newArchEnabled` to true inside the `gradle.properties` file
// - Invoke gradle with `-newArchEnabled=true`
// - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}
android {
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
if (agpVersion.tokenize('.')[0].toInteger() >= 7) {
namespace "com.th3rdwave.safeareacontext"
buildFeatures {
buildConfig true
}
}
compileSdkVersion getExtOrDefault('compileSdkVersion', 30)
// Used to override the NDK path/version on internal CI or by allowing
// users to customize the NDK path/version from their root project (e.g. for M1 support)
if (rootProject.hasProperty("ndkPath")) {
ndkPath rootProject.ext.ndkPath
}
if (rootProject.hasProperty("ndkVersion")) {
ndkVersion rootProject.ext.ndkVersion
}
defaultConfig {
minSdkVersion getExtOrDefault('minSdkVersion', 16)
targetSdkVersion getExtOrDefault('targetSdkVersion', 28)
versionCode 1
versionName "1.0"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
ndk {
abiFilters (*reactNativeArchitectures())
}
}
lintOptions{
abortOnError false
}
packagingOptions {
// For some reason gradle only complains about the duplicated version of libreact_render libraries
// while there are more libraries copied in intermediates folder of the lib build directory, we exclude
// only the ones that make the build fail (ideally we should only include libsafeareacontext_modules but we
// are only allowed to specify exclude patterns)
exclude "**/libreact_render*.so"
}
sourceSets.main {
java {
if (isNewArchitectureEnabled()) {
srcDirs += [
"src/fabric/java",
"${project.buildDir}/generated/source/codegen/java"
]
} else {
srcDirs += [
"src/paper/java"
]
}
}
}
}
def reactNativeArchitectures() {
def value = project.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : [
"armeabi-v7a",
"x86",
"x86_64",
"arm64-v8a"
]
}
repositories {
google()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
mavenCentral()
}
def kotlin_version = getExtOrDefault('kotlinVersion', project.properties['RNSAC_kotlinVersion'])
dependencies {
implementation 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

View File

@@ -0,0 +1 @@
RNSAC_kotlinVersion=1.6.20

View File

@@ -0,0 +1,24 @@
apply plugin: 'com.diffplug.spotless'
allprojects {
repositories {
google()
mavenCentral()
}
}
spotless {
java {
target 'src/**/*.java'
googleJavaFormat()
}
kotlin {
target 'src/**/*.kt'
ktfmt()
}
groovyGradle {
target '*.gradle'
greclipse()
indentWithSpaces(4)
}
}

View File

@@ -0,0 +1,25 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.events.Event
internal class InsetsChangeEvent(
surfaceId: Int,
viewTag: Int,
private val mInsets: EdgeInsets,
private val mFrame: Rect
) : Event<InsetsChangeEvent>(surfaceId, viewTag) {
override fun getEventName() = EVENT_NAME
override fun getEventData(): WritableMap? {
val event = Arguments.createMap()
event.putMap("insets", edgeInsetsToJsMap(mInsets))
event.putMap("frame", rectToJsMap(mFrame))
return event
}
companion object {
const val EVENT_NAME = "topInsetsChange"
}
}

View File

@@ -0,0 +1,14 @@
package com.th3rdwave.safeareacontext
import android.content.Context
import android.view.View
import com.facebook.react.bridge.ReactContext
import com.facebook.react.uimanager.UIManagerHelper
fun getReactContext(view: View): ReactContext {
return UIManagerHelper.getReactContext(view)
}
fun getSurfaceId(context: Context): Int {
return UIManagerHelper.getSurfaceId(context)
}

View File

@@ -0,0 +1,5 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.th3rdwave.safeareacontext">
</manifest>

View File

@@ -0,0 +1,3 @@
package com.th3rdwave.safeareacontext
data class EdgeInsets(val top: Float, val right: Float, val bottom: Float, val left: Float)

View File

@@ -0,0 +1,3 @@
package com.th3rdwave.safeareacontext
data class Rect(val x: Float, val y: Float, val width: Float, val height: Float)

View File

@@ -0,0 +1,32 @@
package com.th3rdwave.safeareacontext
import android.view.View
import android.view.ViewGroup
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
@ReactModule(name = SafeAreaContextModule.NAME)
class SafeAreaContextModule(reactContext: ReactApplicationContext?) :
NativeSafeAreaContextSpec(reactContext) {
override fun getName(): String {
return NAME
}
public override fun getTypedExportedConstants(): Map<String, Any?> {
return mapOf("initialWindowMetrics" to getInitialWindowMetrics())
}
private fun getInitialWindowMetrics(): Map<String, Any>? {
val decorView = reactApplicationContext.currentActivity?.window?.decorView as ViewGroup?
val contentView = decorView?.findViewById<View>(android.R.id.content) ?: return null
val insets = getSafeAreaInsets(decorView)
val frame = getFrame(decorView, contentView)
return if (insets == null || frame == null) {
null
} else mapOf("insets" to edgeInsetsToJavaMap(insets), "frame" to rectToJavaMap(frame))
}
companion object {
const val NAME = "RNCSafeAreaContext"
}
}

View File

@@ -0,0 +1,41 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.BaseReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.module.model.ReactModuleInfo
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager
// Fool autolinking for older versions that do not support BaseReactPackage.
// public class SafeAreaContextPackage implements ReactPackage {
class SafeAreaContextPackage : BaseReactPackage() {
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
return when (name) {
SafeAreaContextModule.NAME -> SafeAreaContextModule(reactContext)
else -> null
}
}
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
val moduleList: Array<Class<out NativeModule?>> = arrayOf(SafeAreaContextModule::class.java)
val reactModuleInfoMap: MutableMap<String, ReactModuleInfo> = HashMap()
for (moduleClass in moduleList) {
val reactModule = moduleClass.getAnnotation(ReactModule::class.java) ?: continue
reactModuleInfoMap[reactModule.name] =
ReactModuleInfo(
reactModule.name,
moduleClass.name,
true,
reactModule.needsEagerInit,
reactModule.isCxxModule,
BuildConfig.IS_NEW_ARCHITECTURE_ENABLED)
}
return ReactModuleInfoProvider { reactModuleInfoMap }
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return listOf<ViewManager<*, *>>(SafeAreaProviderManager(), SafeAreaViewManager())
}
}

View File

@@ -0,0 +1,47 @@
package com.th3rdwave.safeareacontext
import android.content.Context
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.facebook.react.views.view.ReactViewGroup
typealias OnInsetsChangeHandler = (view: SafeAreaProvider, insets: EdgeInsets, frame: Rect) -> Unit
class SafeAreaProvider(context: Context?) :
ReactViewGroup(context), ViewTreeObserver.OnPreDrawListener {
private var mInsetsChangeHandler: OnInsetsChangeHandler? = null
private var mLastInsets: EdgeInsets? = null
private var mLastFrame: Rect? = null
private fun maybeUpdateInsets() {
val insetsChangeHandler = mInsetsChangeHandler ?: return
val edgeInsets = getSafeAreaInsets(this) ?: return
val frame = getFrame(rootView as ViewGroup, this) ?: return
if (mLastInsets != edgeInsets || mLastFrame != frame) {
insetsChangeHandler(this, edgeInsets, frame)
mLastInsets = edgeInsets
mLastFrame = frame
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewTreeObserver.addOnPreDrawListener(this)
maybeUpdateInsets()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
viewTreeObserver.removeOnPreDrawListener(this)
}
override fun onPreDraw(): Boolean {
maybeUpdateInsets()
return true
}
fun setOnInsetsChangeHandler(handler: OnInsetsChangeHandler?) {
mInsetsChangeHandler = handler
maybeUpdateInsets()
}
}

View File

@@ -0,0 +1,41 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.viewmanagers.RNCSafeAreaProviderManagerDelegate
import com.facebook.react.viewmanagers.RNCSafeAreaProviderManagerInterface
@ReactModule(name = SafeAreaProviderManager.REACT_CLASS)
class SafeAreaProviderManager :
ViewGroupManager<SafeAreaProvider>(), RNCSafeAreaProviderManagerInterface<SafeAreaProvider> {
private val mDelegate = RNCSafeAreaProviderManagerDelegate(this)
override fun getDelegate() = mDelegate
override fun getName() = REACT_CLASS
public override fun createViewInstance(context: ThemedReactContext) = SafeAreaProvider(context)
override fun getExportedCustomDirectEventTypeConstants() =
mutableMapOf(
InsetsChangeEvent.EVENT_NAME to mutableMapOf("registrationName" to "onInsetsChange"))
override fun addEventEmitters(reactContext: ThemedReactContext, view: SafeAreaProvider) {
super.addEventEmitters(reactContext, view)
view.setOnInsetsChangeHandler(::handleOnInsetsChange)
}
companion object {
const val REACT_CLASS = "RNCSafeAreaProvider"
}
}
private fun handleOnInsetsChange(view: SafeAreaProvider, insets: EdgeInsets, frame: Rect) {
val reactContext = view.context as ReactContext
val reactTag = view.id
UIManagerHelper.getEventDispatcherForReactTag(reactContext, reactTag)
?.dispatchEvent(InsetsChangeEvent(getSurfaceId(reactContext), reactTag, insets, frame))
}

View File

@@ -0,0 +1,102 @@
package com.th3rdwave.safeareacontext
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
import androidx.annotation.RequiresApi
import java.lang.IllegalArgumentException
import kotlin.math.max
import kotlin.math.min
@RequiresApi(Build.VERSION_CODES.R)
private fun getRootWindowInsetsCompatR(rootView: View): EdgeInsets? {
val insets =
rootView.rootWindowInsets?.getInsets(
WindowInsets.Type.statusBars() or
WindowInsets.Type.displayCutout() or
WindowInsets.Type.navigationBars() or
WindowInsets.Type.captionBar())
?: return null
return EdgeInsets(
top = insets.top.toFloat(),
right = insets.right.toFloat(),
bottom = insets.bottom.toFloat(),
left = insets.left.toFloat())
}
@RequiresApi(Build.VERSION_CODES.M)
@Suppress("DEPRECATION")
private fun getRootWindowInsetsCompatM(rootView: View): EdgeInsets? {
val insets = rootView.rootWindowInsets ?: return null
return EdgeInsets(
top = insets.systemWindowInsetTop.toFloat(),
right = insets.systemWindowInsetRight.toFloat(),
// System insets are more reliable to account for notches but the
// system inset for bottom includes the soft keyboard which we don't
// want to be consistent with iOS. Using the min value makes sure we
// never get the keyboard offset while still working with devices that
// hide the navigation bar.
bottom = min(insets.systemWindowInsetBottom, insets.stableInsetBottom).toFloat(),
left = insets.systemWindowInsetLeft.toFloat())
}
private fun getRootWindowInsetsCompatBase(rootView: View): EdgeInsets? {
val visibleRect = android.graphics.Rect()
rootView.getWindowVisibleDisplayFrame(visibleRect)
return EdgeInsets(
top = visibleRect.top.toFloat(),
right = (rootView.width - visibleRect.right).toFloat(),
bottom = (rootView.height - visibleRect.bottom).toFloat(),
left = visibleRect.left.toFloat())
}
private fun getRootWindowInsetsCompat(rootView: View): EdgeInsets? {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> getRootWindowInsetsCompatR(rootView)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> getRootWindowInsetsCompatM(rootView)
else -> getRootWindowInsetsCompatBase(rootView)
}
}
fun getSafeAreaInsets(view: View): EdgeInsets? {
// The view has not been layout yet.
if (view.height == 0) {
return null
}
val rootView = view.rootView
val windowInsets = getRootWindowInsetsCompat(rootView) ?: return null
// Calculate the part of the view that overlaps with window insets.
val windowWidth = rootView.width.toFloat()
val windowHeight = rootView.height.toFloat()
val visibleRect = android.graphics.Rect()
view.getGlobalVisibleRect(visibleRect)
return EdgeInsets(
top = max(windowInsets.top - visibleRect.top, 0f),
right = max(min(visibleRect.left + view.width - windowWidth, 0f) + windowInsets.right, 0f),
bottom = max(min(visibleRect.top + view.height - windowHeight, 0f) + windowInsets.bottom, 0f),
left = max(windowInsets.left - visibleRect.left, 0f))
}
fun getFrame(rootView: ViewGroup, view: View): Rect? {
// This can happen while the view gets unmounted.
if (view.parent == null) {
return null
}
val offset = android.graphics.Rect()
view.getDrawingRect(offset)
try {
rootView.offsetDescendantRectToMyCoords(view, offset)
} catch (ex: IllegalArgumentException) {
// This can throw if the view is not a descendant of rootView. This should not
// happen but avoid potential crashes.
ex.printStackTrace()
return null
}
return Rect(
x = offset.left.toFloat(),
y = offset.top.toFloat(),
width = view.width.toFloat(),
height = view.height.toFloat())
}

View File

@@ -0,0 +1,155 @@
package com.th3rdwave.safeareacontext
import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewTreeObserver
import com.facebook.react.bridge.Arguments
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.views.view.ReactViewGroup
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
private const val MAX_WAIT_TIME_NANO = 500000000L // 500ms
class SafeAreaView(context: Context?) :
ReactViewGroup(context), ViewTreeObserver.OnPreDrawListener {
private var mMode = SafeAreaViewMode.PADDING
private var mInsets: EdgeInsets? = null
private var mEdges: SafeAreaViewEdges? = null
private var mProviderView: View? = null
private var mStateWrapper: StateWrapper? = null
fun getStateWrapper(): StateWrapper? {
return mStateWrapper
}
fun setStateWrapper(stateWrapper: StateWrapper?) {
mStateWrapper = stateWrapper
}
private fun updateInsets() {
val insets = mInsets
if (insets != null) {
val edges =
mEdges
?: SafeAreaViewEdges(
SafeAreaViewEdgeModes.ADDITIVE,
SafeAreaViewEdgeModes.ADDITIVE,
SafeAreaViewEdgeModes.ADDITIVE,
SafeAreaViewEdgeModes.ADDITIVE)
val stateWrapper = getStateWrapper()
if (stateWrapper != null) {
val map = Arguments.createMap()
map.putMap("insets", edgeInsetsToJsMap(insets))
stateWrapper.updateState(map)
} else {
val localData = SafeAreaViewLocalData(insets = insets, mode = mMode, edges = edges)
val reactContext = getReactContext(this)
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
if (uiManager != null) {
uiManager.setViewLocalData(id, localData)
// Sadly there doesn't seem to be a way to properly dirty a yoga node from java, so if we
// are in
// the middle of a layout, we need to recompute it. There is also no way to know whether
// we
// are in the middle of a layout so always do it.
reactContext.runOnNativeModulesQueueThread {
uiManager.uiImplementation.dispatchViewUpdates(-1)
}
waitForReactLayout()
}
}
}
}
private fun waitForReactLayout() {
// Block the main thread until the native module thread is finished with
// its current tasks. To do this we use the done boolean as a lock and enqueue
// a task on the native modules thread. When the task runs we can unblock the
// main thread. This should be safe as long as the native modules thread
// does not block waiting on the main thread.
var done = false
val lock = ReentrantLock()
val condition = lock.newCondition()
val startTime = System.nanoTime()
var waitTime = 0L
getReactContext(this).runOnNativeModulesQueueThread {
lock.withLock {
if (!done) {
done = true
condition.signal()
}
}
}
lock.withLock {
while (!done && waitTime < MAX_WAIT_TIME_NANO) {
try {
condition.awaitNanos(MAX_WAIT_TIME_NANO)
} catch (ex: InterruptedException) {
// In case of an interrupt just give up waiting.
done = true
}
waitTime += System.nanoTime() - startTime
}
}
// Timed out waiting.
if (waitTime >= MAX_WAIT_TIME_NANO) {
Log.w("SafeAreaView", "Timed out waiting for layout.")
}
}
fun setMode(mode: SafeAreaViewMode) {
mMode = mode
updateInsets()
}
fun setEdges(edges: SafeAreaViewEdges) {
mEdges = edges
updateInsets()
}
private fun maybeUpdateInsets(): Boolean {
val providerView = mProviderView ?: return false
val edgeInsets = getSafeAreaInsets(providerView) ?: return false
if (mInsets != edgeInsets) {
mInsets = edgeInsets
updateInsets()
return true
}
return false
}
private fun findProvider(): View {
var current = parent
while (current != null) {
if (current is SafeAreaProvider) {
return current
}
current = current.parent
}
return this
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
mProviderView = findProvider()
mProviderView?.viewTreeObserver?.addOnPreDrawListener(this)
maybeUpdateInsets()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
mProviderView?.viewTreeObserver?.removeOnPreDrawListener(this)
mProviderView = null
}
override fun onPreDraw(): Boolean {
val didUpdate = maybeUpdateInsets()
if (didUpdate) {
requestLayout()
}
return !didUpdate
}
}

View File

@@ -0,0 +1,16 @@
package com.th3rdwave.safeareacontext
enum class SafeAreaViewEdgeModes {
OFF,
ADDITIVE,
MAXIMUM
}
data class SafeAreaViewEdges(
val top: SafeAreaViewEdgeModes,
val right: SafeAreaViewEdgeModes,
val bottom: SafeAreaViewEdgeModes,
val left: SafeAreaViewEdgeModes
)
class Safe

View File

@@ -0,0 +1,7 @@
package com.th3rdwave.safeareacontext
data class SafeAreaViewLocalData(
val insets: EdgeInsets,
val mode: SafeAreaViewMode,
val edges: SafeAreaViewEdges,
)

View File

@@ -0,0 +1,67 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ReactStylesDiffMap
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.views.view.ReactViewGroup
import com.facebook.react.views.view.ReactViewManager
@ReactModule(name = SafeAreaViewManager.REACT_CLASS)
class SafeAreaViewManager : ReactViewManager() {
override fun getName() = REACT_CLASS
override fun createViewInstance(context: ThemedReactContext) = SafeAreaView(context)
override fun createShadowNodeInstance() = SafeAreaViewShadowNode()
override fun getShadowNodeClass() = SafeAreaViewShadowNode::class.java
@ReactProp(name = "mode")
fun setMode(view: SafeAreaView, mode: String?) {
when (mode) {
"padding" -> {
view.setMode(SafeAreaViewMode.PADDING)
}
"margin" -> {
view.setMode(SafeAreaViewMode.MARGIN)
}
}
}
@ReactProp(name = "edges")
fun setEdges(view: SafeAreaView, propList: ReadableMap?) {
if (propList != null) {
view.setEdges(
SafeAreaViewEdges(
top = propList.getString("top")?.let { SafeAreaViewEdgeModes.valueOf(it.uppercase()) }
?: SafeAreaViewEdgeModes.OFF,
right =
propList.getString("right")?.let { SafeAreaViewEdgeModes.valueOf(it.uppercase()) }
?: SafeAreaViewEdgeModes.OFF,
bottom =
propList.getString("bottom")?.let {
SafeAreaViewEdgeModes.valueOf(it.uppercase())
}
?: SafeAreaViewEdgeModes.OFF,
left =
propList.getString("left")?.let { SafeAreaViewEdgeModes.valueOf(it.uppercase()) }
?: SafeAreaViewEdgeModes.OFF))
}
}
override fun updateState(
view: ReactViewGroup,
props: ReactStylesDiffMap?,
stateWrapper: StateWrapper?
): Any? {
(view as SafeAreaView).setStateWrapper(stateWrapper)
return null
}
companion object {
const val REACT_CLASS = "RNCSafeAreaView"
}
}

View File

@@ -0,0 +1,6 @@
package com.th3rdwave.safeareacontext
enum class SafeAreaViewMode {
PADDING,
MARGIN
}

View File

@@ -0,0 +1,170 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.Dynamic
import com.facebook.react.bridge.ReadableType
import com.facebook.react.uimanager.*
import com.facebook.react.uimanager.annotations.ReactPropGroup
import kotlin.math.max
class SafeAreaViewShadowNode : LayoutShadowNode() {
private var mLocalData: SafeAreaViewLocalData? = null
private val mPaddings: FloatArray = FloatArray(ViewProps.PADDING_MARGIN_SPACING_TYPES.size)
private val mMargins: FloatArray = FloatArray(ViewProps.PADDING_MARGIN_SPACING_TYPES.size)
private var mNeedsUpdate = false
init {
for (i in ViewProps.PADDING_MARGIN_SPACING_TYPES.indices) {
mPaddings[i] = Float.NaN
mMargins[i] = Float.NaN
}
}
private fun updateInsets() {
val localData = mLocalData ?: return
var top = 0f
var right = 0f
var bottom = 0f
var left = 0f
val meta = if (localData.mode == SafeAreaViewMode.PADDING) mPaddings else mMargins
val allEdges = meta[Spacing.ALL]
if (!java.lang.Float.isNaN(allEdges)) {
top = allEdges
right = allEdges
bottom = allEdges
left = allEdges
}
val verticalEdges = meta[Spacing.VERTICAL]
if (!java.lang.Float.isNaN(verticalEdges)) {
top = verticalEdges
bottom = verticalEdges
}
val horizontalEdges = meta[Spacing.HORIZONTAL]
if (!java.lang.Float.isNaN(horizontalEdges)) {
right = horizontalEdges
left = horizontalEdges
}
val topEdge = meta[Spacing.TOP]
if (!java.lang.Float.isNaN(topEdge)) {
top = topEdge
}
val rightEdge = meta[Spacing.RIGHT]
if (!java.lang.Float.isNaN(rightEdge)) {
right = rightEdge
}
val bottomEdge = meta[Spacing.BOTTOM]
if (!java.lang.Float.isNaN(bottomEdge)) {
bottom = bottomEdge
}
val leftEdge = meta[Spacing.LEFT]
if (!java.lang.Float.isNaN(leftEdge)) {
left = leftEdge
}
top = PixelUtil.toPixelFromDIP(top)
right = PixelUtil.toPixelFromDIP(right)
bottom = PixelUtil.toPixelFromDIP(bottom)
left = PixelUtil.toPixelFromDIP(left)
val edges = localData.edges
val insets = localData.insets
if (localData.mode == SafeAreaViewMode.PADDING) {
super.setPadding(Spacing.TOP, getEdgeValue(edges.top, insets.top, top))
super.setPadding(Spacing.RIGHT, getEdgeValue(edges.right, insets.right, right))
super.setPadding(Spacing.BOTTOM, getEdgeValue(edges.bottom, insets.bottom, bottom))
super.setPadding(Spacing.LEFT, getEdgeValue(edges.left, insets.left, left))
} else {
super.setMargin(Spacing.TOP, getEdgeValue(edges.top, insets.top, top))
super.setMargin(Spacing.RIGHT, getEdgeValue(edges.right, insets.right, right))
super.setMargin(Spacing.BOTTOM, getEdgeValue(edges.bottom, insets.bottom, bottom))
super.setMargin(Spacing.LEFT, getEdgeValue(edges.left, insets.left, left))
}
}
private fun getEdgeValue(
edgeMode: SafeAreaViewEdgeModes,
insetValue: Float,
edgeValue: Float
): Float {
if (edgeMode == SafeAreaViewEdgeModes.OFF) {
return edgeValue
} else if (edgeMode == SafeAreaViewEdgeModes.MAXIMUM) {
return max(insetValue, edgeValue)
} else {
return insetValue + edgeValue
}
}
private fun resetInsets(mode: SafeAreaViewMode) {
if (mode == SafeAreaViewMode.PADDING) {
super.setPadding(Spacing.TOP, mPaddings[Spacing.TOP])
super.setPadding(Spacing.RIGHT, mPaddings[Spacing.RIGHT])
super.setPadding(Spacing.BOTTOM, mPaddings[Spacing.BOTTOM])
super.setPadding(Spacing.LEFT, mPaddings[Spacing.LEFT])
} else {
super.setMargin(Spacing.TOP, mMargins[Spacing.TOP])
super.setMargin(Spacing.RIGHT, mMargins[Spacing.RIGHT])
super.setMargin(Spacing.BOTTOM, mMargins[Spacing.BOTTOM])
super.setMargin(Spacing.LEFT, mMargins[Spacing.LEFT])
}
markUpdated()
}
override fun onBeforeLayout(nativeViewHierarchyOptimizer: NativeViewHierarchyOptimizer) {
if (mNeedsUpdate) {
mNeedsUpdate = false
updateInsets()
}
}
override fun setLocalData(data: Any) {
if (data !is SafeAreaViewLocalData) {
return
}
val localData = mLocalData
if (localData != null && localData.mode != data.mode) {
resetInsets(localData.mode)
}
mLocalData = data
mNeedsUpdate = false
updateInsets()
}
// Names needs to reflect exact order in LayoutShadowNode.java
@ReactPropGroup(
names =
[
ViewProps.PADDING,
ViewProps.PADDING_VERTICAL,
ViewProps.PADDING_HORIZONTAL,
ViewProps.PADDING_START,
ViewProps.PADDING_END,
ViewProps.PADDING_TOP,
ViewProps.PADDING_BOTTOM,
ViewProps.PADDING_LEFT,
ViewProps.PADDING_RIGHT])
override fun setPaddings(index: Int, padding: Dynamic) {
val spacingType = ViewProps.PADDING_MARGIN_SPACING_TYPES[index]
mPaddings[spacingType] =
if (padding.type == ReadableType.Number) padding.asDouble().toFloat() else Float.NaN
super.setPaddings(index, padding)
mNeedsUpdate = true
}
@ReactPropGroup(
names =
[
ViewProps.MARGIN,
ViewProps.MARGIN_VERTICAL,
ViewProps.MARGIN_HORIZONTAL,
ViewProps.MARGIN_START,
ViewProps.MARGIN_END,
ViewProps.MARGIN_TOP,
ViewProps.MARGIN_BOTTOM,
ViewProps.MARGIN_LEFT,
ViewProps.MARGIN_RIGHT])
override fun setMargins(index: Int, margin: Dynamic) {
val spacingType = ViewProps.PADDING_MARGIN_SPACING_TYPES[index]
mMargins[spacingType] =
if (margin.type == ReadableType.Number) margin.asDouble().toFloat() else Float.NaN
super.setMargins(index, margin)
mNeedsUpdate = true
}
}

View File

@@ -0,0 +1,39 @@
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.PixelUtil
fun edgeInsetsToJsMap(insets: EdgeInsets): WritableMap {
val insetsMap = Arguments.createMap()
insetsMap.putDouble("top", PixelUtil.toDIPFromPixel(insets.top).toDouble())
insetsMap.putDouble("right", PixelUtil.toDIPFromPixel(insets.right).toDouble())
insetsMap.putDouble("bottom", PixelUtil.toDIPFromPixel(insets.bottom).toDouble())
insetsMap.putDouble("left", PixelUtil.toDIPFromPixel(insets.left).toDouble())
return insetsMap
}
fun edgeInsetsToJavaMap(insets: EdgeInsets): Map<String, Float> {
return mapOf(
"top" to PixelUtil.toDIPFromPixel(insets.top),
"right" to PixelUtil.toDIPFromPixel(insets.right),
"bottom" to PixelUtil.toDIPFromPixel(insets.bottom),
"left" to PixelUtil.toDIPFromPixel(insets.left))
}
fun rectToJsMap(rect: Rect): WritableMap {
val rectMap = Arguments.createMap()
rectMap.putDouble("x", PixelUtil.toDIPFromPixel(rect.x).toDouble())
rectMap.putDouble("y", PixelUtil.toDIPFromPixel(rect.y).toDouble())
rectMap.putDouble("width", PixelUtil.toDIPFromPixel(rect.width).toDouble())
rectMap.putDouble("height", PixelUtil.toDIPFromPixel(rect.height).toDouble())
return rectMap
}
fun rectToJavaMap(rect: Rect): Map<String, Float> {
return mapOf(
"x" to PixelUtil.toDIPFromPixel(rect.x),
"y" to PixelUtil.toDIPFromPixel(rect.y),
"width" to PixelUtil.toDIPFromPixel(rect.width),
"height" to PixelUtil.toDIPFromPixel(rect.height))
}

View File

@@ -0,0 +1,87 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(LIB_LITERAL safeareacontext)
set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL})
set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp)
set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni)
set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL})
file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS *.cpp ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp)
file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp)
add_library(
${LIB_TARGET_NAME}
SHARED
${LIB_CUSTOM_SRCS}
${LIB_CODEGEN_SRCS}
)
target_include_directories(
${LIB_TARGET_NAME}
PUBLIC
.
${LIB_COMMON_DIR}
${LIB_ANDROID_GENERATED_JNI_DIR}
${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
)
# https://github.com/react-native-community/discussions-and-proposals/discussions/816
# This if-then-else can be removed once this library does not support version below 0.76
if (REACTNATIVE_MERGED_SO)
target_link_libraries(
${LIB_TARGET_NAME}
fbjni
jsi
reactnative
)
else()
target_link_libraries(
${LIB_TARGET_NAME}
fbjni
folly_runtime
glog
jsi
react_codegen_rncore
react_debug
react_nativemodule_core
react_render_core
react_render_debug
react_render_graphics
react_render_mapbuffer
react_render_componentregistry
react_utils
rrc_view
turbomodulejsijni
yoga
)
endif()
target_include_directories(
${CMAKE_PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
target_compile_reactnative_options(${LIB_TARGET_NAME} PUBLIC)
else()
target_compile_options(
${LIB_TARGET_NAME}
PRIVATE
-fexceptions
-frtti
-std=c++20
-Wall
)
endif()
target_compile_options(
${LIB_TARGET_NAME}
PRIVATE
-Wpedantic
-Wno-gnu-zero-variadic-macro-arguments
-Wno-dollar-in-identifier-extension
)

View File

@@ -0,0 +1,17 @@
#pragma once
#include <ReactCommon/JavaTurboModule.h>
#include <ReactCommon/TurboModule.h>
#include <jsi/jsi.h>
#include <react/renderer/components/safeareacontext/RNCSafeAreaViewComponentDescriptor.h>
namespace facebook {
namespace react {
JSI_EXPORT
std::shared_ptr<TurboModule> safeareacontext_ModuleProvider(
const std::string &moduleName,
const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,31 @@
/**
* This code was generated by
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
* is regenerated.
*
* @generated by codegen project: GeneratePropsJavaDelegate.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
public class RNCSafeAreaProviderManagerDelegate<
T extends View,
U extends
BaseViewManager<T, ? extends LayoutShadowNode> & RNCSafeAreaProviderManagerInterface<T>>
extends BaseViewManagerDelegate<T, U> {
public RNCSafeAreaProviderManagerDelegate(U viewManager) {
super(viewManager);
}
@Override
public void setProperty(T view, String propName, @Nullable Object value) {
super.setProperty(view, propName, value);
}
}

View File

@@ -0,0 +1,16 @@
/**
* This code was generated by
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
* is regenerated.
*
* @generated by codegen project: GeneratePropsJavaInterface.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
public interface RNCSafeAreaProviderManagerInterface<T extends View> {
// No props
}

View File

@@ -0,0 +1,41 @@
/**
* This code was generated by
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
* is regenerated.
*
* @generated by codegen project: GeneratePropsJavaDelegate.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.BaseViewManager;
import com.facebook.react.uimanager.BaseViewManagerDelegate;
import com.facebook.react.uimanager.LayoutShadowNode;
public class RNCSafeAreaViewManagerDelegate<
T extends View,
U extends
BaseViewManager<T, ? extends LayoutShadowNode> & RNCSafeAreaViewManagerInterface<T>>
extends BaseViewManagerDelegate<T, U> {
public RNCSafeAreaViewManagerDelegate(U viewManager) {
super(viewManager);
}
@Override
public void setProperty(T view, String propName, @Nullable Object value) {
switch (propName) {
case "mode":
mViewManager.setMode(view, (String) value);
break;
case "edges":
mViewManager.setEdges(view, (ReadableMap) value);
break;
default:
super.setProperty(view, propName, value);
}
}
}

View File

@@ -0,0 +1,20 @@
/**
* This code was generated by
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
* is regenerated.
*
* @generated by codegen project: GeneratePropsJavaInterface.js
*/
package com.facebook.react.viewmanagers;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
public interface RNCSafeAreaViewManagerInterface<T extends View> {
void setMode(T view, @Nullable String value);
void setEdges(T view, @Nullable ReadableMap value);
}

View File

@@ -0,0 +1,29 @@
@file:Suppress("DEPRECATION")
package com.th3rdwave.safeareacontext
import com.facebook.react.bridge.Arguments
import com.facebook.react.uimanager.events.Event
import com.facebook.react.uimanager.events.RCTEventEmitter
internal class InsetsChangeEvent(
@Suppress("UNUSED_PARAMETER") surfaceId: Int,
viewTag: Int,
private val mInsets: EdgeInsets,
private val mFrame: Rect
// New ctor is only available in RN 0.65.
) : Event<InsetsChangeEvent>(viewTag) {
override fun getEventName() = EVENT_NAME
// TODO: Migrate to getEventData when dropping support for RN 0.64.
override fun dispatch(rctEventEmitter: RCTEventEmitter) {
val event = Arguments.createMap()
event.putMap("insets", edgeInsetsToJsMap(mInsets))
event.putMap("frame", rectToJsMap(mFrame))
rctEventEmitter.receiveEvent(viewTag, eventName, event)
}
companion object {
const val EVENT_NAME = "topInsetsChange"
}
}

View File

@@ -0,0 +1,56 @@
/**
* This code was generated by
* [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* <p>Do not edit this file as changes may cause incorrect behavior and will be lost once the code
* is regenerated.
*
* @generated by codegen project: GenerateModuleJavaSpec.js
* @nolint
*/
package com.th3rdwave.safeareacontext;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactModuleWithSpec;
import com.facebook.react.common.build.ReactBuildConfig;
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
public abstract class NativeSafeAreaContextSpec extends ReactContextBaseJavaModule
implements ReactModuleWithSpec, TurboModule {
public NativeSafeAreaContextSpec(ReactApplicationContext reactContext) {
super(reactContext);
}
protected abstract Map<String, Object> getTypedExportedConstants();
@Override
@DoNotStrip
public final @Nullable Map<String, Object> getConstants() {
Map<String, Object> constants = getTypedExportedConstants();
if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) {
Set<String> obligatoryFlowConstants = new HashSet<>();
Set<String> optionalFlowConstants = new HashSet<>(Arrays.asList("initialWindowMetrics"));
Set<String> undeclaredConstants = new HashSet<>(constants.keySet());
undeclaredConstants.removeAll(obligatoryFlowConstants);
undeclaredConstants.removeAll(optionalFlowConstants);
if (!undeclaredConstants.isEmpty()) {
throw new IllegalStateException(
String.format("Native Module Flow doesn't declare constants: %s", undeclaredConstants));
}
undeclaredConstants = obligatoryFlowConstants;
undeclaredConstants.removeAll(constants.keySet());
if (!undeclaredConstants.isEmpty()) {
throw new IllegalStateException(
String.format("Native Module doesn't fill in constants: %s", undeclaredConstants));
}
}
return constants;
}
}

View File

@@ -0,0 +1,20 @@
package com.th3rdwave.safeareacontext
import android.content.Context
import android.content.ContextWrapper
import android.view.View
import com.facebook.react.bridge.ReactContext
/** UIManagerHelper.getReactContext only exists in RN 0.63+ so vendor it here for a while. */
fun getReactContext(view: View): ReactContext {
var context = view.context
if (context !is ReactContext && context is ContextWrapper) {
context = context.baseContext
}
return context as ReactContext
}
/** UIManagerHelper.getSurfaceId only exists in RN 0.65+, surface id is only needed for new arch. */
fun getSurfaceId(@Suppress("UNUSED_PARAMETER") context: Context): Int {
return -1
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <react/renderer/components/safeareacontext/RNCSafeAreaViewShadowNode.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
namespace facebook {
namespace react {
/*
* Descriptor for <RNCSafeAreaView> component.
*/
class RNCSafeAreaViewComponentDescriptor final
: public ConcreteComponentDescriptor<RNCSafeAreaViewShadowNode> {
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
void adopt(ShadowNode &shadowNode) const override {
auto &concreteShadowNode =
static_cast<RNCSafeAreaViewShadowNode &>(shadowNode);
concreteShadowNode.adjustLayoutWithState();
ConcreteComponentDescriptor::adopt(shadowNode);
}
};
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,131 @@
#include "RNCSafeAreaViewShadowNode.h"
#include <react/renderer/components/view/conversions.h>
#include <react/renderer/core/LayoutContext.h>
#include <yoga/Yoga.h>
#include <algorithm>
namespace facebook {
namespace react {
using namespace yoga;
extern const char RNCSafeAreaViewComponentName[] = "RNCSafeAreaView";
inline Style::Length valueFromEdges(
Style::Length edge,
Style::Length axis,
Style::Length defaultValue) {
if (edge.isDefined()) {
return edge;
}
if (axis.isDefined()) {
return axis;
}
return defaultValue;
}
inline float
getEdgeValue(std::string edgeMode, float insetValue, float edgeValue) {
if (edgeMode == "off") {
return edgeValue;
} else if (edgeMode == "maximum") {
return fmax(insetValue, edgeValue);
} else {
return insetValue + edgeValue;
}
}
void RNCSafeAreaViewShadowNode::adjustLayoutWithState() {
ensureUnsealed();
auto &props = getConcreteProps();
auto state =
std::static_pointer_cast<const RNCSafeAreaViewShadowNode::ConcreteState>(
getState());
auto stateData = state->getData();
auto edges = props.edges;
// Get the current values for padding / margin. The only caveat here is that
// percent values are not supported. Also might need to add support for start
// / end.
Style::Length top, left, right, bottom;
if (props.mode == RNCSafeAreaViewMode::Padding) {
auto defaultPadding = props.yogaStyle.padding(Edge::All);
top = valueFromEdges(
props.yogaStyle.padding(Edge::Top),
props.yogaStyle.padding(Edge::Vertical),
defaultPadding);
left = valueFromEdges(
props.yogaStyle.padding(Edge::Left),
props.yogaStyle.padding(Edge::Horizontal),
defaultPadding);
bottom = valueFromEdges(
props.yogaStyle.padding(Edge::Bottom),
props.yogaStyle.padding(Edge::Vertical),
defaultPadding);
right = valueFromEdges(
props.yogaStyle.padding(Edge::Right),
props.yogaStyle.padding(Edge::Horizontal),
defaultPadding);
} else {
auto defaultMargin = props.yogaStyle.margin(Edge::All);
top = valueFromEdges(
props.yogaStyle.margin(Edge::Top),
props.yogaStyle.margin(Edge::Vertical),
defaultMargin);
left = valueFromEdges(
props.yogaStyle.margin(Edge::Left),
props.yogaStyle.margin(Edge::Horizontal),
defaultMargin);
bottom = valueFromEdges(
props.yogaStyle.margin(Edge::Bottom),
props.yogaStyle.margin(Edge::Vertical),
defaultMargin);
right = valueFromEdges(
props.yogaStyle.margin(Edge::Right),
props.yogaStyle.margin(Edge::Horizontal),
defaultMargin);
}
top = Style::Length::points(getEdgeValue(
edges.top, stateData.insets.top, top.value().unwrapOrDefault(0)));
left = Style::Length::points(getEdgeValue(
edges.left, stateData.insets.left, left.value().unwrapOrDefault(0)));
right = Style::Length::points(getEdgeValue(
edges.right, stateData.insets.right, right.value().unwrapOrDefault(0)));
bottom = Style::Length::points(getEdgeValue(
edges.bottom,
stateData.insets.bottom,
bottom.value().unwrapOrDefault(0)));
yoga::Style adjustedStyle = getConcreteProps().yogaStyle;
if (props.mode == RNCSafeAreaViewMode::Padding) {
adjustedStyle.setPadding(Edge::Top, top);
adjustedStyle.setPadding(Edge::Left, left);
adjustedStyle.setPadding(Edge::Right, right);
adjustedStyle.setPadding(Edge::Bottom, bottom);
} else {
adjustedStyle.setMargin(Edge::Top, top);
adjustedStyle.setMargin(Edge::Left, left);
adjustedStyle.setMargin(Edge::Right, right);
adjustedStyle.setMargin(Edge::Bottom, bottom);
}
auto currentStyle = yogaNode_.style();
if (adjustedStyle.padding(Edge::Top) != currentStyle.padding(Edge::Top) ||
adjustedStyle.padding(Edge::Left) != currentStyle.padding(Edge::Left) ||
adjustedStyle.padding(Edge::Right) != currentStyle.padding(Edge::Right) ||
adjustedStyle.padding(Edge::Bottom) !=
currentStyle.padding(Edge::Bottom) ||
adjustedStyle.margin(Edge::Top) != currentStyle.margin(Edge::Top) ||
adjustedStyle.margin(Edge::Left) != currentStyle.margin(Edge::Left) ||
adjustedStyle.margin(Edge::Right) != currentStyle.margin(Edge::Right) ||
adjustedStyle.margin(Edge::Bottom) != currentStyle.margin(Edge::Bottom)) {
yogaNode_.setStyle(adjustedStyle);
yogaNode_.setDirty(true);
}
}
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,30 @@
#pragma once
#include <jsi/jsi.h>
#include <react/renderer/components/safeareacontext/EventEmitters.h>
#include <react/renderer/components/safeareacontext/Props.h>
#include <react/renderer/components/safeareacontext/RNCSafeAreaViewState.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
JSI_EXPORT extern const char RNCSafeAreaViewComponentName[];
/*
* `ShadowNode` for <RNCSafeAreaView> component.
*/
class JSI_EXPORT RNCSafeAreaViewShadowNode final
: public ConcreteViewShadowNode<
RNCSafeAreaViewComponentName,
RNCSafeAreaViewProps,
ViewEventEmitter,
RNCSafeAreaViewState> {
using ConcreteViewShadowNode::ConcreteViewShadowNode;
public:
void adjustLayoutWithState();
};
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,23 @@
#include "RNCSafeAreaViewState.h"
namespace facebook {
namespace react {
#ifdef ANDROID
folly::dynamic RNCSafeAreaViewState::getDynamic() const {
folly::dynamic insetsValue = folly::dynamic::object();
insetsValue["top"] = insets.top;
insetsValue["left"] = insets.left;
insetsValue["bottom"] = insets.bottom;
insetsValue["right"] = insets.right;
folly::dynamic data = folly::dynamic::object();
data["insets"] = insetsValue;
return data;
}
#endif
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,56 @@
#pragma once
#include <react/renderer/components/safeareacontext/Props.h>
#include <react/renderer/graphics/RectangleEdges.h>
#include <vector>
#ifdef ANDROID
#include <folly/dynamic.h>
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#endif
namespace facebook {
namespace react {
#ifdef ANDROID
inline EdgeInsets edgeInsetsFromDynamic(const folly::dynamic &value) {
return EdgeInsets{
.left = (float)value["left"].getDouble(),
.top = (float)value["top"].getDouble(),
.right = (float)value["right"].getDouble(),
.bottom = (float)value["bottom"].getDouble(),
};
}
#endif
/*
* State for <RNCSafeAreaView> component.
*/
class JSI_EXPORT RNCSafeAreaViewState final {
public:
using Shared = std::shared_ptr<const RNCSafeAreaViewState>;
RNCSafeAreaViewState(){};
#ifdef ANDROID
RNCSafeAreaViewState(
RNCSafeAreaViewState const &previousState,
folly::dynamic data)
: insets(edgeInsetsFromDynamic(data["insets"])){};
#endif
EdgeInsets insets{};
#ifdef ANDROID
folly::dynamic getDynamic() const;
MapBuffer getMapBuffer() const {
return MapBufferBuilder::EMPTY();
};
#endif
};
} // namespace react
} // namespace facebook

View File

@@ -0,0 +1,17 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaProviderComponentView : RCTViewComponentView
extern NSString *const RNCSafeAreaDidChange;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,154 @@
#import "RNCSafeAreaProviderComponentView.h"
#import <react/renderer/components/safeareacontext/ComponentDescriptors.h>
#import <react/renderer/components/safeareacontext/EventEmitters.h>
#import <react/renderer/components/safeareacontext/Props.h>
#import <react/renderer/components/safeareacontext/RCTComponentViewHelpers.h>
#import <React/RCTFabricComponentsPlugins.h>
#import "RNCSafeAreaUtils.h"
using namespace facebook::react;
@interface RNCSafeAreaProviderComponentView () <RCTRNCSafeAreaProviderViewProtocol>
@end
@implementation RNCSafeAreaProviderComponentView {
UIEdgeInsets _currentSafeAreaInsets;
CGRect _currentFrame;
BOOL _initialInsetsSent;
BOOL _registeredNotifications;
}
// Needed because of this: https://github.com/facebook/react-native/pull/37274
+ (void)load
{
[super load];
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RNCSafeAreaProviderProps>();
_props = defaultProps;
}
return self;
}
#if !TARGET_OS_OSX
- (void)willMoveToSuperview:(UIView *)newSuperView
{
[super willMoveToSuperview:newSuperView];
if (newSuperView != nil && !_registeredNotifications) {
_registeredNotifications = YES;
[self registerNotifications];
}
}
#endif
- (void)registerNotifications
{
#if !TARGET_OS_TV && !TARGET_OS_OSX
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidShowNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidHideNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidChangeFrameNotification
object:nil];
#endif
}
- (void)safeAreaInsetsDidChange
{
[self invalidateSafeAreaInsets];
}
- (void)invalidateSafeAreaInsets
{
if (self.superview == nil) {
return;
}
// This gets called before the view size is set by react-native so
// make sure to wait so we don't set wrong insets to JS.
if (CGSizeEqualToSize(self.frame.size, CGSizeZero)) {
return;
}
UIEdgeInsets safeAreaInsets = self.safeAreaInsets;
CGRect frame = [self convertRect:self.bounds toView:RNCParentViewController(self).view];
if (_initialInsetsSent &&
#if TARGET_OS_IPHONE
UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#elif TARGET_OS_OSX
NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#endif
CGRectEqualToRect(frame, _currentFrame)) {
return;
}
_initialInsetsSent = YES;
_currentSafeAreaInsets = safeAreaInsets;
_currentFrame = frame;
[NSNotificationCenter.defaultCenter postNotificationName:RNCSafeAreaDidChange object:self userInfo:nil];
if (_eventEmitter) {
RNCSafeAreaProviderEventEmitter::OnInsetsChange event = {
.insets =
{
.top = safeAreaInsets.top,
.left = safeAreaInsets.left,
.bottom = safeAreaInsets.bottom,
.right = safeAreaInsets.right,
},
.frame =
{
.x = frame.origin.x,
.y = frame.origin.y,
.width = frame.size.width,
.height = frame.size.height,
},
};
std::static_pointer_cast<RNCSafeAreaProviderEventEmitter const>(_eventEmitter)->onInsetsChange(event);
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateSafeAreaInsets];
}
#pragma mark - RCTComponentViewProtocol
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNCSafeAreaProviderComponentDescriptor>();
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
_currentSafeAreaInsets = UIEdgeInsetsZero;
_currentFrame = CGRectZero;
_initialInsetsSent = NO;
[NSNotificationCenter.defaultCenter removeObserver:self];
_registeredNotifications = NO;
}
@end
Class<RCTComponentViewProtocol> RNCSafeAreaProviderCls(void)
{
return RNCSafeAreaProviderComponentView.class;
}

View File

@@ -0,0 +1,15 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import <React/RCTViewComponentView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaViewComponentView : RCTViewComponentView
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,175 @@
#import "RNCSafeAreaViewComponentView.h"
#import <react/renderer/components/safeareacontext/EventEmitters.h>
#import <react/renderer/components/safeareacontext/Props.h>
#import <react/renderer/components/safeareacontext/RCTComponentViewHelpers.h>
#import <react/renderer/components/safeareacontext/RNCSafeAreaViewComponentDescriptor.h>
#import <react/renderer/components/safeareacontext/RNCSafeAreaViewShadowNode.h>
#import <React/RCTConversions.h>
#import <React/RCTFabricComponentsPlugins.h>
#import "RNCSafeAreaProviderComponentView.h"
#import "RNCSafeAreaUtils.h"
using namespace facebook::react;
@interface RNCSafeAreaViewComponentView () <RCTRNCSafeAreaViewViewProtocol>
@end
@implementation RNCSafeAreaViewComponentView {
RNCSafeAreaViewShadowNode::ConcreteState::Shared _state;
UIEdgeInsets _currentSafeAreaInsets;
__weak UIView *_Nullable _providerView;
}
// Needed because of this: https://github.com/facebook/react-native/pull/37274
+ (void)load
{
[super load];
}
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RNCSafeAreaViewProps>();
_props = defaultProps;
}
return self;
}
- (NSString *)description
{
NSString *superDescription = [super description];
// Cutting the last `>` character.
if (superDescription.length > 0 && [superDescription characterAtIndex:superDescription.length - 1] == '>') {
superDescription = [superDescription substringToIndex:superDescription.length - 1];
}
#if TARGET_OS_IPHONE
NSString *providerViewSafeAreaInsetsString = NSStringFromUIEdgeInsets(_providerView.safeAreaInsets);
NSString *currentSafeAreaInsetsString = NSStringFromUIEdgeInsets(_currentSafeAreaInsets);
#elif TARGET_OS_OSX
NSString *providerViewSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_providerView.safeAreaInsets.top,
_providerView.safeAreaInsets.left,
_providerView.safeAreaInsets.bottom,
_providerView.safeAreaInsets.right];
NSString *currentSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_currentSafeAreaInsets.top,
_currentSafeAreaInsets.left,
_currentSafeAreaInsets.bottom,
_currentSafeAreaInsets.right];
#endif
return [NSString stringWithFormat:@"%@; RNCSafeAreaInsets = %@; appliedRNCSafeAreaInsets = %@>",
superDescription,
providerViewSafeAreaInsetsString,
currentSafeAreaInsetsString];
}
- (void)didMoveToWindow
{
UIView *previousProviderView = _providerView;
_providerView = [self findNearestProvider];
[self updateStateIfNecessary];
if (previousProviderView != _providerView) {
[NSNotificationCenter.defaultCenter removeObserver:self name:RNCSafeAreaDidChange object:previousProviderView];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(safeAreaProviderInsetsDidChange:)
name:RNCSafeAreaDidChange
object:_providerView];
}
}
- (void)safeAreaProviderInsetsDidChange:(NSNotification *)notification
{
[self updateStateIfNecessary];
}
- (void)updateStateIfNecessary
{
if (_providerView == nil) {
return;
}
#if TARGET_OS_IPHONE
UIEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#elif TARGET_OS_OSX
NSEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#endif
_currentSafeAreaInsets = safeAreaInsets;
[self updateState];
}
- (UIView *)findNearestProvider
{
UIView *current = self.superview;
while (current != nil) {
if ([current isKindOfClass:RNCSafeAreaProviderComponentView.class]) {
return current;
}
current = current.superview;
}
return self;
}
- (void)updateState
{
if (!_state) {
return;
}
_state->updateState(
[=](RNCSafeAreaViewShadowNode::ConcreteState::Data const &oldData)
-> RNCSafeAreaViewShadowNode::ConcreteState::SharedData {
auto newData = oldData;
newData.insets = RCTEdgeInsetsFromUIEdgeInsets(_currentSafeAreaInsets);
return std::make_shared<RNCSafeAreaViewShadowNode::ConcreteState::Data const>(newData);
});
}
#pragma mark - RCTComponentViewProtocol
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNCSafeAreaViewComponentDescriptor>();
}
- (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState
{
_state = std::static_pointer_cast<RNCSafeAreaViewShadowNode::ConcreteState const>(state);
}
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask
{
[super finalizeUpdates:updateMask];
[self updateStateIfNecessary];
}
- (void)prepareForRecycle
{
[super prepareForRecycle];
[NSNotificationCenter.defaultCenter removeObserver:self];
_state.reset();
_providerView = nil;
_currentSafeAreaInsets = UIEdgeInsetsZero;
}
@end
Class<RCTComponentViewProtocol> RNCSafeAreaViewCls(void)
{
return RNCSafeAreaViewComponentView.class;
}

View File

@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <React/RCTEventDispatcherProtocol.h>
@interface RNCOnInsetsChangeEvent : NSObject <RCTEvent>
- (instancetype)initWithEventName:(NSString *)eventName
reactTag:(NSNumber *)reactTag
insets:(UIEdgeInsets)insets
frame:(CGRect)frame
coalescingKey:(uint16_t)coalescingKey NS_DESIGNATED_INITIALIZER;
@end

View File

@@ -0,0 +1,79 @@
#import "RNCOnInsetsChangeEvent.h"
#import <React/RCTAssert.h>
@implementation RNCOnInsetsChangeEvent {
UIEdgeInsets _insets;
CGRect _frame;
uint16_t _coalescingKey;
}
@synthesize eventName = _eventName;
@synthesize viewTag = _viewTag;
- (instancetype)initWithEventName:(NSString *)eventName
reactTag:(NSNumber *)reactTag
insets:(UIEdgeInsets)insets
frame:(CGRect)frame
coalescingKey:(uint16_t)coalescingKey
{
RCTAssertParam(reactTag);
if ((self = [super init])) {
_eventName = [eventName copy];
_viewTag = reactTag;
_frame = frame;
_insets = insets;
_coalescingKey = coalescingKey;
}
return self;
}
RCT_NOT_IMPLEMENTED(-(instancetype)init)
- (uint16_t)coalescingKey
{
return _coalescingKey;
}
- (NSDictionary *)body
{
NSDictionary *body = @{
@"insets" : @{
@"top" : @(_insets.top),
@"right" : @(_insets.right),
@"bottom" : @(_insets.bottom),
@"left" : @(_insets.left),
},
@"frame" : @{
@"x" : @(_frame.origin.x),
@"y" : @(_frame.origin.y),
@"width" : @(_frame.size.width),
@"height" : @(_frame.size.height),
},
};
return body;
}
- (BOOL)canCoalesce
{
return YES;
}
- (RNCOnInsetsChangeEvent *)coalesceWithEvent:(RNCOnInsetsChangeEvent *)newEvent
{
return newEvent;
}
+ (NSString *)moduleDotMethod
{
return @"RCTEventEmitter.receiveEvent";
}
- (NSArray *)arguments
{
return @[ self.viewTag, RCTNormalizeInputEventName(self.eventName), [self body] ];
}
@end

View File

@@ -0,0 +1,9 @@
#import <React/RCTBridgeModule.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaContext : NSObject <RCTBridgeModule>
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,85 @@
#import "RNCSafeAreaContext.h"
#import <React/RCTUtils.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#ifdef RCT_NEW_ARCH_ENABLED
#import <safeareacontext/safeareacontext.h>
#endif
#ifdef RCT_NEW_ARCH_ENABLED
using namespace facebook::react;
@interface RNCSafeAreaContext () <NativeSafeAreaContextSpec>
@end
#endif
@implementation RNCSafeAreaContext
RCT_EXPORT_MODULE()
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
- (NSDictionary *)constantsToExport
{
return [self getConstants];
}
- (NSDictionary *)getConstants
{
__block NSDictionary *constants;
RCTUnsafeExecuteOnMainQueueSync(^{
#if TARGET_OS_IPHONE
UIWindow *window = RCTKeyWindow();
#elif TARGET_OS_OSX
NSWindow *window = RCTKeyWindow();
#endif
if (window == nil) {
constants = @{@"initialWindowMetrics" : [NSNull null]};
return;
}
#if TARGET_OS_IPHONE
UIEdgeInsets safeAreaInsets = window.safeAreaInsets;
#elif TARGET_OS_OSX
NSEdgeInsets safeAreaInsets = NSEdgeInsetsZero;
#endif
constants = @{
@"initialWindowMetrics" : @{
@"insets" : @{
@"top" : @(safeAreaInsets.top),
@"right" : @(safeAreaInsets.right),
@"bottom" : @(safeAreaInsets.bottom),
@"left" : @(safeAreaInsets.left),
},
@"frame" : @{
@"x" : @(window.frame.origin.x),
@"y" : @(window.frame.origin.y),
@"width" : @(window.frame.size.width),
@"height" : @(window.frame.size.height),
},
}
};
});
return constants;
}
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<TurboModule>)getTurboModule:(const ObjCTurboModule::InitParams &)params
{
return std::make_shared<NativeSafeAreaContextSpecJSI>(params);
}
#endif
@end

View File

@@ -0,0 +1,23 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaProvider : RCTView
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher NS_DESIGNATED_INITIALIZER;
// NOTE: currently these event props are only declared so we can export the
// event names to JS - we don't call the blocks directly because events
// need to be coalesced before sending, for performance reasons.
@property (nonatomic, copy) RCTBubblingEventBlock onInsetsChange;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,115 @@
#import "RNCSafeAreaProvider.h"
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUIManager.h>
#import <React/RCTUIManagerObserverCoordinator.h>
#import "RNCOnInsetsChangeEvent.h"
#import "RNCSafeAreaUtils.h"
@interface RNCSafeAreaProvider () <RCTUIManagerObserver>
@end
@implementation RNCSafeAreaProvider {
id<RCTEventDispatcherProtocol> _eventDispatcher;
UIEdgeInsets _currentSafeAreaInsets;
CGRect _currentFrame;
BOOL _initialInsetsSent;
}
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher
{
RCTAssertParam(eventDispatcher);
if ((self = [super initWithFrame:CGRectZero])) {
_eventDispatcher = eventDispatcher;
#if !TARGET_OS_TV && !TARGET_OS_OSX
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidShowNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidHideNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIKeyboardDidChangeFrameNotification
object:nil];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(invalidateSafeAreaInsets)
name:UIWindowDidBecomeVisibleNotification
object:nil];
#endif
}
return self;
}
- (void)safeAreaInsetsDidChange
{
[self invalidateSafeAreaInsets];
}
- (void)invalidateSafeAreaInsets
{
// This gets called before the view size is set by react-native so
// make sure to wait so we don't set wrong insets to JS.
if (CGSizeEqualToSize(self.frame.size, CGSizeZero)) {
return;
}
#if TARGET_OS_IPHONE
UIEdgeInsets safeAreaInsets = self.safeAreaInsets;
#elif TARGET_OS_OSX
NSEdgeInsets safeAreaInsets;
if (@available(macOS 11.0, *)) {
safeAreaInsets = self.safeAreaInsets;
} else {
safeAreaInsets = NSEdgeInsetsZero;
}
#endif
CGRect frame = [self convertRect:self.bounds toView:RNCParentViewController(self).view];
if (_initialInsetsSent &&
#if TARGET_OS_IPHONE
UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#elif TARGET_OS_OSX
NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale()) &&
#endif
CGRectEqualToRect(frame, _currentFrame)) {
return;
}
_initialInsetsSent = YES;
_currentSafeAreaInsets = safeAreaInsets;
_currentFrame = frame;
[NSNotificationCenter.defaultCenter postNotificationName:RNCSafeAreaDidChange object:self userInfo:nil];
RNCOnInsetsChangeEvent *onInsetsChangeEvent = [[RNCOnInsetsChangeEvent alloc] initWithEventName:@"onInsetsChange"
reactTag:self.reactTag
insets:safeAreaInsets
frame:frame
coalescingKey:0];
[_eventDispatcher sendEvent:onInsetsChangeEvent];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self invalidateSafeAreaInsets];
}
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
- (void)dealloc
{
[_eventDispatcher.bridge.uiManager.observerCoordinator removeObserver:self];
}
@end

View File

@@ -0,0 +1,9 @@
#import <React/RCTViewManager.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaProviderManager : RCTViewManager
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,20 @@
#import "RNCSafeAreaProviderManager.h"
#import "RNCSafeAreaProvider.h"
@implementation RNCSafeAreaProviderManager
RCT_EXPORT_MODULE(RNCSafeAreaProvider)
RCT_EXPORT_VIEW_PROPERTY(onInsetsChange, RCTDirectEventBlock)
#if TARGET_OS_IPHONE
- (UIView *)view
#elif TARGET_OS_OSX
- (NSView *)view
#endif
{
return [[RNCSafeAreaProvider alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
}
@end

View File

@@ -0,0 +1,9 @@
#import <React/RCTShadowView.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaShadowView : RCTShadowView
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,194 @@
#import "RNCSafeAreaShadowView.h"
#import <React/RCTAssert.h>
#include <math.h>
#import "RNCSafeAreaViewEdgeMode.h"
#import "RNCSafeAreaViewEdges.h"
#import "RNCSafeAreaViewLocalData.h"
#import "RNCSafeAreaViewMode.h"
// From RCTShadowView.m
typedef NS_ENUM(unsigned int, meta_prop_t) {
META_PROP_LEFT,
META_PROP_TOP,
META_PROP_RIGHT,
META_PROP_BOTTOM,
META_PROP_HORIZONTAL,
META_PROP_VERTICAL,
META_PROP_ALL,
META_PROP_COUNT,
};
@implementation RNCSafeAreaShadowView {
RNCSafeAreaViewLocalData *_localData;
bool _needsUpdate;
YGValue _paddingMetaProps[META_PROP_COUNT];
YGValue _marginMetaProps[META_PROP_COUNT];
}
- (instancetype)init
{
self = [super init];
if (self) {
_needsUpdate = false;
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
_paddingMetaProps[ii] = YGValueUndefined;
_marginMetaProps[ii] = YGValueUndefined;
}
}
return self;
}
- (void)extractEdges:(YGValue[])_metaProps
top:(CGFloat *)top
right:(CGFloat *)right
bottom:(CGFloat *)bottom
left:(CGFloat *)left
{
if (_metaProps[META_PROP_ALL].unit == YGUnitPoint) {
*top = _metaProps[META_PROP_ALL].value;
*right = _metaProps[META_PROP_ALL].value;
*bottom = _metaProps[META_PROP_ALL].value;
*left = _metaProps[META_PROP_ALL].value;
}
if (_metaProps[META_PROP_HORIZONTAL].unit == YGUnitPoint) {
*right = _metaProps[META_PROP_HORIZONTAL].value;
*left = _metaProps[META_PROP_HORIZONTAL].value;
}
if (_metaProps[META_PROP_VERTICAL].unit == YGUnitPoint) {
*top = _metaProps[META_PROP_VERTICAL].value;
*bottom = _metaProps[META_PROP_VERTICAL].value;
}
if (_metaProps[META_PROP_TOP].unit == YGUnitPoint) {
*top = _metaProps[META_PROP_TOP].value;
}
if (_metaProps[META_PROP_RIGHT].unit == YGUnitPoint) {
*right = _metaProps[META_PROP_RIGHT].value;
}
if (_metaProps[META_PROP_BOTTOM].unit == YGUnitPoint) {
*bottom = _metaProps[META_PROP_BOTTOM].value;
}
if (_metaProps[META_PROP_LEFT].unit == YGUnitPoint) {
*left = _metaProps[META_PROP_LEFT].value;
}
}
- (void)resetInsetsForMode:(RNCSafeAreaViewMode)mode
{
if (mode == RNCSafeAreaViewModePadding) {
super.paddingTop = _paddingMetaProps[META_PROP_TOP];
super.paddingRight = _paddingMetaProps[META_PROP_RIGHT];
super.paddingBottom = _paddingMetaProps[META_PROP_BOTTOM];
super.paddingLeft = _paddingMetaProps[META_PROP_LEFT];
} else if (mode == RNCSafeAreaViewModeMargin) {
super.marginTop = _marginMetaProps[META_PROP_TOP];
super.marginRight = _marginMetaProps[META_PROP_RIGHT];
super.marginBottom = _marginMetaProps[META_PROP_BOTTOM];
super.marginLeft = _marginMetaProps[META_PROP_LEFT];
}
}
- (void)updateInsets
{
if (_localData == nil) {
return;
}
UIEdgeInsets insets = _localData.insets;
RNCSafeAreaViewMode mode = _localData.mode;
RNCSafeAreaViewEdges edges = _localData.edges;
CGFloat top = 0;
CGFloat right = 0;
CGFloat bottom = 0;
CGFloat left = 0;
if (mode == RNCSafeAreaViewModePadding) {
[self extractEdges:_paddingMetaProps top:&top right:&right bottom:&bottom left:&left];
super.paddingTop = (YGValue){[self getEdgeValue:edges.top insetValue:insets.top edgeValue:top], YGUnitPoint};
super.paddingRight =
(YGValue){[self getEdgeValue:edges.right insetValue:insets.right edgeValue:right], YGUnitPoint};
super.paddingBottom =
(YGValue){[self getEdgeValue:edges.bottom insetValue:insets.bottom edgeValue:bottom], YGUnitPoint};
super.paddingLeft = (YGValue){[self getEdgeValue:edges.left insetValue:insets.left edgeValue:left], YGUnitPoint};
} else if (mode == RNCSafeAreaViewModeMargin) {
[self extractEdges:_marginMetaProps top:&top right:&right bottom:&bottom left:&left];
super.marginTop = (YGValue){[self getEdgeValue:edges.top insetValue:insets.top edgeValue:top], YGUnitPoint};
super.marginRight = (YGValue){[self getEdgeValue:edges.right insetValue:insets.right edgeValue:right], YGUnitPoint};
super.marginBottom =
(YGValue){[self getEdgeValue:edges.bottom insetValue:insets.bottom edgeValue:bottom], YGUnitPoint};
super.marginLeft = (YGValue){[self getEdgeValue:edges.left insetValue:insets.left edgeValue:left], YGUnitPoint};
}
}
- (CGFloat)getEdgeValue:(RNCSafeAreaViewEdgeMode)edgeMode insetValue:(CGFloat)insetValue edgeValue:(CGFloat)edgeValue
{
if (edgeMode == RNCSafeAreaViewEdgeModeOff) {
return edgeValue;
} else if (edgeMode == RNCSafeAreaViewEdgeModeMaximum) {
return MAX(insetValue, edgeValue);
} else {
return insetValue + edgeValue;
}
}
- (void)didSetProps:(NSArray<NSString *> *)changedProps
{
if (_needsUpdate) {
_needsUpdate = false;
[self updateInsets];
}
[super didSetProps:changedProps];
}
- (void)setLocalData:(RNCSafeAreaViewLocalData *)localData
{
RCTAssert(
[localData isKindOfClass:[RNCSafeAreaViewLocalData class]],
@"Local data object for `RCTRNCSafeAreaShadowView` must be `RCTRNCSafeAreaViewLocalData` instance.");
if (_localData != nil && _localData.mode != localData.mode) {
[self resetInsetsForMode:_localData.mode];
}
_localData = localData;
_needsUpdate = false;
[self updateInsets];
if (_localData.mode == RNCSafeAreaViewModePadding) {
[super didSetProps:@[ @"paddingTop", @"paddingRight", @"paddingBottom", @"paddingLeft" ]];
} else {
[super didSetProps:@[ @"marginTop", @"marginRight", @"marginBottom", @"marginLeft" ]];
}
}
#define SHADOW_VIEW_MARGIN_PADDING_PROP(edge, metaProp) \
-(void)setPadding##edge : (YGValue)value \
{ \
[super setPadding##edge:value]; \
_needsUpdate = true; \
_paddingMetaProps[META_PROP_##metaProp] = value; \
} \
-(void)setMargin##edge : (YGValue)value \
{ \
[super setMargin##edge:value]; \
_needsUpdate = true; \
_marginMetaProps[META_PROP_##metaProp] = value; \
}
SHADOW_VIEW_MARGIN_PADDING_PROP(, ALL);
SHADOW_VIEW_MARGIN_PADDING_PROP(Vertical, VERTICAL);
SHADOW_VIEW_MARGIN_PADDING_PROP(Horizontal, HORIZONTAL);
SHADOW_VIEW_MARGIN_PADDING_PROP(Top, TOP);
SHADOW_VIEW_MARGIN_PADDING_PROP(Right, RIGHT);
SHADOW_VIEW_MARGIN_PADDING_PROP(Bottom, BOTTOM);
SHADOW_VIEW_MARGIN_PADDING_PROP(Left, LEFT);
@end

View File

@@ -0,0 +1,23 @@
#import <React/RCTDefines.h>
#import <React/RCTView.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
typedef NSView UIView;
#endif
extern NSString *const RNCSafeAreaDidChange;
RCT_EXTERN BOOL
#if TARGET_OS_IPHONE
UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIEdgeInsets insets2, CGFloat threshold);
#elif TARGET_OS_OSX
NSEdgeInsetsEqualToEdgeInsetsWithThreshold(NSEdgeInsets insets1, NSEdgeInsets insets2, CGFloat threshold);
#endif
#if TARGET_OS_IPHONE
RCT_EXTERN UIViewController *RNCParentViewController(UIView *view);
#elif TARGET_OS_OSX
RCT_EXTERN NSViewController *RNCParentViewController(NSView *view);
#endif

View File

@@ -0,0 +1,41 @@
#import "RNCSafeAreaUtils.h"
#import <React/RCTUIManager.h>
NSString *const RNCSafeAreaDidChange = @"RNCSafeAreaDidChange";
#if TARGET_OS_IPHONE
BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIEdgeInsets insets2, CGFloat threshold)
#elif TARGET_OS_OSX
BOOL NSEdgeInsetsEqualToEdgeInsetsWithThreshold(NSEdgeInsets insets1, NSEdgeInsets insets2, CGFloat threshold)
#endif
{
return ABS(insets1.left - insets2.left) <= threshold && ABS(insets1.right - insets2.right) <= threshold &&
ABS(insets1.top - insets2.top) <= threshold && ABS(insets1.bottom - insets2.bottom) <= threshold;
}
#if TARGET_OS_IPHONE
UIViewController *RNCParentViewController(UIView *view)
{
UIResponder *responder = view.nextResponder;
while (responder != nil) {
if ([responder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)responder;
}
responder = responder.nextResponder;
}
return nil;
}
#elif TARGET_OS_OSX
NSViewController *RNCParentViewController(NSView *view)
{
NSResponder *responder = view.nextResponder;
while (responder != nil) {
if ([responder isKindOfClass:[NSViewController class]]) {
return (NSViewController *)responder;
}
responder = responder.nextResponder;
}
return nil;
}
#endif

View File

@@ -0,0 +1,25 @@
#import <React/RCTBridge.h>
#import <React/RCTView.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import "RNCSafeAreaViewEdges.h"
#import "RNCSafeAreaViewMode.h"
NS_ASSUME_NONNULL_BEGIN
@class RNCSafeAreaView;
@interface RNCSafeAreaView : RCTView
- (instancetype)initWithBridge:(RCTBridge *)bridge;
@property (nonatomic, assign) RNCSafeAreaViewMode mode;
@property (nonatomic, assign) RNCSafeAreaViewEdges edges;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,168 @@
#import "RNCSafeAreaView.h"
#import <React/RCTBridge.h>
#import <React/RCTUIManager.h>
#import "RNCSafeAreaProvider.h"
#import "RNCSafeAreaUtils.h"
#import "RNCSafeAreaViewEdges.h"
#import "RNCSafeAreaViewLocalData.h"
#import "RNCSafeAreaViewMode.h"
@implementation RNCSafeAreaView {
__weak RCTBridge *_bridge;
#if TARGET_OS_IPHONE
UIEdgeInsets _currentSafeAreaInsets;
#elif TARGET_OS_OSX
NSEdgeInsets _currentSafeAreaInsets;
#endif
RNCSafeAreaViewMode _mode;
RNCSafeAreaViewEdges _edges;
__weak RNCSafeAreaProvider *_Nullable _providerView;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if (self = [super initWithFrame:CGRectZero]) {
_bridge = bridge;
// Defaults
_mode = RNCSafeAreaViewModePadding;
_edges = RNCSafeAreaViewEdgesMake(
RNCSafeAreaViewEdgeModeOff, RNCSafeAreaViewEdgeModeOff, RNCSafeAreaViewEdgeModeOff, RNCSafeAreaViewEdgeModeOff);
}
return self;
}
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)decoder)
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
- (NSString *)description
{
NSString *superDescription = [super description];
// Cutting the last `>` character.
if (superDescription.length > 0 && [superDescription characterAtIndex:superDescription.length - 1] == '>') {
superDescription = [superDescription substringToIndex:superDescription.length - 1];
}
#if TARGET_OS_IPHONE
NSString *providerViewSafeAreaInsetsString = NSStringFromUIEdgeInsets(_providerView.safeAreaInsets);
NSString *currentSafeAreaInsetsString = NSStringFromUIEdgeInsets(_currentSafeAreaInsets);
#elif TARGET_OS_OSX
NSString *providerViewSafeAreaInsetsString;
NSString *currentSafeAreaInsetsString;
if (@available(macOS 11.0, *)) {
providerViewSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_providerView.safeAreaInsets.top,
_providerView.safeAreaInsets.left,
_providerView.safeAreaInsets.bottom,
_providerView.safeAreaInsets.right];
currentSafeAreaInsetsString = [NSString stringWithFormat:@"{%f,%f,%f,%f}",
_currentSafeAreaInsets.top,
_currentSafeAreaInsets.left,
_currentSafeAreaInsets.bottom,
_currentSafeAreaInsets.right];
} else {
providerViewSafeAreaInsetsString = @"{0.0,0.0,0.0,0.0}";
currentSafeAreaInsetsString = @"{0.0,0.0,0.0,0.0}";
}
#endif
return [NSString stringWithFormat:@"%@; RNCSafeAreaInsets = %@; appliedRNCSafeAreaInsets = %@>",
superDescription,
providerViewSafeAreaInsetsString,
currentSafeAreaInsetsString];
}
- (void)didMoveToWindow
{
#if TARGET_OS_IPHONE
UIView *previousProviderView = _providerView;
#elif TARGET_OS_OSX
NSView *previousProviderView = _providerView;
#endif
_providerView = [self findNearestProvider];
[self invalidateSafeAreaInsets];
if (previousProviderView != _providerView) {
if (previousProviderView != nil) {
[NSNotificationCenter.defaultCenter removeObserver:self name:RNCSafeAreaDidChange object:previousProviderView];
}
if (_providerView != nil) {
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(safeAreaProviderInsetsDidChange:)
name:RNCSafeAreaDidChange
object:_providerView];
}
}
}
- (void)safeAreaProviderInsetsDidChange:(NSNotification *)notification
{
[self invalidateSafeAreaInsets];
}
- (void)invalidateSafeAreaInsets
{
if (_providerView == nil) {
return;
}
#if TARGET_OS_IPHONE
UIEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#elif TARGET_OS_OSX
NSEdgeInsets safeAreaInsets = _providerView.safeAreaInsets;
if (NSEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) {
return;
}
#endif
_currentSafeAreaInsets = safeAreaInsets;
[self updateLocalData];
}
- (nullable RNCSafeAreaProvider *)findNearestProvider
{
#if TARGET_OS_IPHONE
UIView *current = self.reactSuperview;
#elif TARGET_OS_OSX
NSView *current = self.reactSuperview;
#endif
while (current != nil) {
if ([current isKindOfClass:RNCSafeAreaProvider.class]) {
return (RNCSafeAreaProvider *)current;
}
current = current.reactSuperview;
}
return nil;
}
- (void)updateLocalData
{
if (_providerView == nil) {
return;
}
RNCSafeAreaViewLocalData *localData = [[RNCSafeAreaViewLocalData alloc] initWithInsets:_currentSafeAreaInsets
mode:_mode
edges:_edges];
[_bridge.uiManager setLocalData:localData forView:self];
}
- (void)setMode:(RNCSafeAreaViewMode)mode
{
_mode = mode;
[self updateLocalData];
}
- (void)setEdges:(RNCSafeAreaViewEdges)edges
{
_edges = edges;
[self updateLocalData];
}
@end

View File

@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
#import <React/RCTConvert.h>
typedef NS_ENUM(NSInteger, RNCSafeAreaViewEdgeMode) {
RNCSafeAreaViewEdgeModeOff,
RNCSafeAreaViewEdgeModeAdditive,
RNCSafeAreaViewEdgeModeMaximum
};
@interface RCTConvert (RNCSafeAreaViewEdgeMode)
+ (RNCSafeAreaViewEdgeMode)RNCSafeAreaViewEdgeMode:(nullable id)json;
@end

View File

@@ -0,0 +1,16 @@
#import "RNCSafeAreaViewEdgeMode.h"
#import <React/RCTConvert.h>
@implementation RCTConvert (RNCSafeAreaViewEdgeMode)
RCT_ENUM_CONVERTER(
RNCSafeAreaViewEdgeMode,
(@{
@"off" : @(RNCSafeAreaViewEdgeModeOff),
@"additive" : @(RNCSafeAreaViewEdgeModeAdditive),
@"maximum" : @(RNCSafeAreaViewEdgeModeMaximum),
}),
RNCSafeAreaViewEdgeModeOff,
integerValue);
@end

View File

@@ -0,0 +1,15 @@
#import <Foundation/Foundation.h>
#import "RNCSafeAreaViewEdgeMode.h"
typedef struct RNCSafeAreaViewEdges {
RNCSafeAreaViewEdgeMode top;
RNCSafeAreaViewEdgeMode right;
RNCSafeAreaViewEdgeMode bottom;
RNCSafeAreaViewEdgeMode left;
} RNCSafeAreaViewEdges;
RNCSafeAreaViewEdges RNCSafeAreaViewEdgesMake(
RNCSafeAreaViewEdgeMode top,
RNCSafeAreaViewEdgeMode right,
RNCSafeAreaViewEdgeMode bottom,
RNCSafeAreaViewEdgeMode left);

View File

@@ -0,0 +1,36 @@
#import "RNCSafeAreaViewEdges.h"
#import <React/RCTConvert.h>
#import "RNCSafeAreaViewEdgeMode.h"
RNCSafeAreaViewEdges RNCSafeAreaViewEdgesMake(
RNCSafeAreaViewEdgeMode top,
RNCSafeAreaViewEdgeMode right,
RNCSafeAreaViewEdgeMode bottom,
RNCSafeAreaViewEdgeMode left)
{
RNCSafeAreaViewEdges edges;
edges.top = top;
edges.left = left;
edges.bottom = bottom;
edges.right = right;
return edges;
}
RNCSafeAreaViewEdges RNCSafeAreaViewEdgesMakeString(NSString *top, NSString *right, NSString *bottom, NSString *left)
{
RNCSafeAreaViewEdges edges;
edges.top = [RCTConvert RNCSafeAreaViewEdgeMode:top];
edges.right = [RCTConvert RNCSafeAreaViewEdgeMode:right];
edges.bottom = [RCTConvert RNCSafeAreaViewEdgeMode:bottom];
edges.left = [RCTConvert RNCSafeAreaViewEdgeMode:left];
return edges;
}
@implementation RCTConvert (RNCSafeAreaViewEdges)
RCT_CUSTOM_CONVERTER(
RNCSafeAreaViewEdges,
RNCSafeAreaViewEdges,
RNCSafeAreaViewEdgesMakeString(json[@"top"], json[@"right"], json[@"bottom"], json[@"left"]))
@end

View File

@@ -0,0 +1,29 @@
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#elif TARGET_OS_OSX
#import <AppKit/AppKit.h>
#endif
#import "RNCSafeAreaViewEdges.h"
#import "RNCSafeAreaViewMode.h"
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaViewLocalData : NSObject
#if TARGET_OS_IPHONE
- (instancetype)initWithInsets:(UIEdgeInsets)insets mode:(RNCSafeAreaViewMode)mode edges:(RNCSafeAreaViewEdges)edges;
@property (atomic, readonly) UIEdgeInsets insets;
#elif TARGET_OS_OSX
- (instancetype)initWithInsets:(NSEdgeInsets)insets mode:(RNCSafeAreaViewMode)mode edges:(RNCSafeAreaViewEdges)edges;
@property (atomic, readonly) NSEdgeInsets insets;
#endif
@property (atomic, readonly) RNCSafeAreaViewMode mode;
@property (atomic, readonly) RNCSafeAreaViewEdges edges;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,20 @@
#import "RNCSafeAreaViewLocalData.h"
@implementation RNCSafeAreaViewLocalData
#if TARGET_OS_IPHONE
- (instancetype)initWithInsets:(UIEdgeInsets)insets mode:(RNCSafeAreaViewMode)mode edges:(RNCSafeAreaViewEdges)edges
#elif TARGET_OS_OSX
- (instancetype)initWithInsets:(NSEdgeInsets)insets mode:(RNCSafeAreaViewMode)mode edges:(RNCSafeAreaViewEdges)edges
#endif
{
if (self = [super init]) {
_insets = insets;
_mode = mode;
_edges = edges;
}
return self;
}
@end

View File

@@ -0,0 +1,9 @@
#import <React/RCTViewManager.h>
NS_ASSUME_NONNULL_BEGIN
@interface RNCSafeAreaViewManager : RCTViewManager
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,29 @@
#import "RNCSafeAreaViewManager.h"
#import "RNCSafeAreaShadowView.h"
#import "RNCSafeAreaView.h"
#import "RNCSafeAreaViewEdges.h"
#import "RNCSafeAreaViewMode.h"
@implementation RNCSafeAreaViewManager
RCT_EXPORT_MODULE(RNCSafeAreaView)
#if TARGET_OS_IPHONE
- (UIView *)view
#elif TARGET_OS_OSX
- (NSView *)view
#endif
{
return [[RNCSafeAreaView alloc] initWithBridge:self.bridge];
}
- (RNCSafeAreaShadowView *)shadowView
{
return [RNCSafeAreaShadowView new];
}
RCT_EXPORT_VIEW_PROPERTY(mode, RNCSafeAreaViewMode)
RCT_EXPORT_VIEW_PROPERTY(edges, RNCSafeAreaViewEdges)
@end

View File

@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, RNCSafeAreaViewMode) {
RNCSafeAreaViewModePadding,
RNCSafeAreaViewModeMargin,
RNCSafeAreaViewModeBorder,
};

View File

@@ -0,0 +1,15 @@
#import "RNCSafeAreaViewMode.h"
#import <React/RCTConvert.h>
@implementation RCTConvert (RNCSafeAreaView)
RCT_MULTI_ENUM_CONVERTER(
RNCSafeAreaViewMode,
(@{
@"padding" : @(RNCSafeAreaViewModePadding),
@"margin" : @(RNCSafeAreaViewModeMargin),
}),
RNCSafeAreaViewModePadding,
integerValue);
@end

View File

@@ -0,0 +1,358 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0C7844E127C02CEE001807FB /* RNCSafeAreaViewLocalData.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844D227C02CEE001807FB /* RNCSafeAreaViewLocalData.m */; };
0C7844E227C02CEE001807FB /* RNCSafeAreaViewMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844D327C02CEE001807FB /* RNCSafeAreaViewMode.m */; };
0C7844E327C02CEE001807FB /* RNCSafeAreaShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844D527C02CEE001807FB /* RNCSafeAreaShadowView.m */; };
0C7844E427C02CEE001807FB /* RNCSafeAreaProviderManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844D627C02CEE001807FB /* RNCSafeAreaProviderManager.m */; };
0C7844E527C02CEE001807FB /* RNCSafeAreaViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844D927C02CEE001807FB /* RNCSafeAreaViewManager.m */; };
0C7844E627C02CEE001807FB /* RNCSafeAreaViewEdges.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844DE27C02CEE001807FB /* RNCSafeAreaViewEdges.m */; };
0C7844E727C02CEE001807FB /* RNCSafeAreaUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844DF27C02CEE001807FB /* RNCSafeAreaUtils.m */; };
0C7844E827C02CEE001807FB /* RNCSafeAreaView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844E027C02CEE001807FB /* RNCSafeAreaView.m */; };
0C7844EF27C02D03001807FB /* RNCSafeAreaContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844EA27C02D03001807FB /* RNCSafeAreaContext.mm */; };
0C7844F027C02D03001807FB /* RNCSafeAreaProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844ED27C02D03001807FB /* RNCSafeAreaProvider.m */; };
AA53A9EE2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m in Sources */ = {isa = PBXBuildFile; fileRef = AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */; };
C923EDBC220C2C1A00D3100F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */; };
D697AA982D6F1D0A009C6433 /* RNCChangeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
58B511D91A9E6C8500147676 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0C7844D227C02CEE001807FB /* RNCSafeAreaViewLocalData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewLocalData.m; sourceTree = "<group>"; };
0C7844D327C02CEE001807FB /* RNCSafeAreaViewMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewMode.m; sourceTree = "<group>"; };
0C7844D427C02CEE001807FB /* RNCSafeAreaViewLocalData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewLocalData.h; sourceTree = "<group>"; };
0C7844D527C02CEE001807FB /* RNCSafeAreaShadowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaShadowView.m; sourceTree = "<group>"; };
0C7844D627C02CEE001807FB /* RNCSafeAreaProviderManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaProviderManager.m; sourceTree = "<group>"; };
0C7844D727C02CEE001807FB /* RNCSafeAreaShadowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaShadowView.h; sourceTree = "<group>"; };
0C7844D827C02CEE001807FB /* RNCSafeAreaView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaView.h; sourceTree = "<group>"; };
0C7844D927C02CEE001807FB /* RNCSafeAreaViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewManager.m; sourceTree = "<group>"; };
0C7844DA27C02CEE001807FB /* RNCSafeAreaViewEdges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewEdges.h; sourceTree = "<group>"; };
0C7844DB27C02CEE001807FB /* RNCSafeAreaUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaUtils.h; sourceTree = "<group>"; };
0C7844DC27C02CEE001807FB /* RNCSafeAreaViewMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewMode.h; sourceTree = "<group>"; };
0C7844DD27C02CEE001807FB /* RNCSafeAreaViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewManager.h; sourceTree = "<group>"; };
0C7844DE27C02CEE001807FB /* RNCSafeAreaViewEdges.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewEdges.m; sourceTree = "<group>"; };
0C7844DF27C02CEE001807FB /* RNCSafeAreaUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaUtils.m; sourceTree = "<group>"; };
0C7844E027C02CEE001807FB /* RNCSafeAreaView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaView.m; sourceTree = "<group>"; };
0C7844E927C02D03001807FB /* RNCSafeAreaContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaContext.h; sourceTree = "<group>"; };
0C7844EA27C02D03001807FB /* RNCSafeAreaContext.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RNCSafeAreaContext.mm; sourceTree = "<group>"; };
0C7844EB27C02D03001807FB /* RNCSafeAreaProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaProvider.h; sourceTree = "<group>"; };
0C7844EC27C02D03001807FB /* RNCSafeAreaProviderManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaProviderManager.h; sourceTree = "<group>"; };
0C7844ED27C02D03001807FB /* RNCSafeAreaProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaProvider.m; sourceTree = "<group>"; };
0C7844EE27C02D03001807FB /* Fabric */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fabric; sourceTree = "<group>"; };
134814201AA4EA6300B7C361 /* libRNCSafeAreaContext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCSafeAreaContext.a; sourceTree = BUILT_PRODUCTS_DIR; };
AA53A9EC2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewEdgeModes.h; sourceTree = "<group>"; };
AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewEdgeModes.m; sourceTree = "<group>"; };
C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
D697AA962D6F1CE5009C6433 /* RNCChangeEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCChangeEvent.h; sourceTree = "<group>"; };
D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCChangeEvent.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
58B511D81A9E6C8500147676 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C923EDBC220C2C1A00D3100F /* SystemConfiguration.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134814211AA4EA7D00B7C361 /* Products */ = {
isa = PBXGroup;
children = (
134814201AA4EA6300B7C361 /* libRNCSafeAreaContext.a */,
);
name = Products;
sourceTree = "<group>";
};
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */,
D697AA962D6F1CE5009C6433 /* RNCChangeEvent.h */,
AA53A9EC2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.h */,
AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */,
0C7844EE27C02D03001807FB /* Fabric */,
0C7844E927C02D03001807FB /* RNCSafeAreaContext.h */,
0C7844EA27C02D03001807FB /* RNCSafeAreaContext.mm */,
0C7844EB27C02D03001807FB /* RNCSafeAreaProvider.h */,
0C7844ED27C02D03001807FB /* RNCSafeAreaProvider.m */,
0C7844EC27C02D03001807FB /* RNCSafeAreaProviderManager.h */,
0C7844D627C02CEE001807FB /* RNCSafeAreaProviderManager.m */,
0C7844D727C02CEE001807FB /* RNCSafeAreaShadowView.h */,
0C7844D527C02CEE001807FB /* RNCSafeAreaShadowView.m */,
0C7844DB27C02CEE001807FB /* RNCSafeAreaUtils.h */,
0C7844DF27C02CEE001807FB /* RNCSafeAreaUtils.m */,
0C7844D827C02CEE001807FB /* RNCSafeAreaView.h */,
0C7844E027C02CEE001807FB /* RNCSafeAreaView.m */,
0C7844DA27C02CEE001807FB /* RNCSafeAreaViewEdges.h */,
0C7844DE27C02CEE001807FB /* RNCSafeAreaViewEdges.m */,
0C7844D427C02CEE001807FB /* RNCSafeAreaViewLocalData.h */,
0C7844D227C02CEE001807FB /* RNCSafeAreaViewLocalData.m */,
0C7844DD27C02CEE001807FB /* RNCSafeAreaViewManager.h */,
0C7844D927C02CEE001807FB /* RNCSafeAreaViewManager.m */,
0C7844DC27C02CEE001807FB /* RNCSafeAreaViewMode.h */,
0C7844D327C02CEE001807FB /* RNCSafeAreaViewMode.m */,
134814211AA4EA7D00B7C361 /* Products */,
C923EDBA220C2C1A00D3100F /* Frameworks */,
);
sourceTree = "<group>";
};
C923EDBA220C2C1A00D3100F /* Frameworks */ = {
isa = PBXGroup;
children = (
C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
58B511DA1A9E6C8500147676 /* RNCSafeAreaContext */ = {
isa = PBXNativeTarget;
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCSafeAreaContext" */;
buildPhases = (
58B511D71A9E6C8500147676 /* Sources */,
58B511D81A9E6C8500147676 /* Frameworks */,
58B511D91A9E6C8500147676 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = RNCSafeAreaContext;
productName = RCTDataManager;
productReference = 134814201AA4EA6300B7C361 /* libRNCSafeAreaContext.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
58B511D31A9E6C8500147676 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1030;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
58B511DA1A9E6C8500147676 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNSafeAreaContext" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 58B511D21A9E6C8500147676;
productRefGroup = 58B511D21A9E6C8500147676;
projectDirPath = "";
projectRoot = "";
targets = (
58B511DA1A9E6C8500147676 /* RNCSafeAreaContext */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
58B511D71A9E6C8500147676 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AA53A9EE2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m in Sources */,
0C7844E427C02CEE001807FB /* RNCSafeAreaProviderManager.m in Sources */,
0C7844E727C02CEE001807FB /* RNCSafeAreaUtils.m in Sources */,
0C7844E827C02CEE001807FB /* RNCSafeAreaView.m in Sources */,
0C7844E627C02CEE001807FB /* RNCSafeAreaViewEdges.m in Sources */,
0C7844E527C02CEE001807FB /* RNCSafeAreaViewManager.m in Sources */,
D697AA982D6F1D0A009C6433 /* RNCChangeEvent.m in Sources */,
0C7844EF27C02D03001807FB /* RNCSafeAreaContext.mm in Sources */,
0C7844E127C02CEE001807FB /* RNCSafeAreaViewLocalData.m in Sources */,
0C7844E227C02CEE001807FB /* RNCSafeAreaViewMode.m in Sources */,
0C7844F027C02D03001807FB /* RNCSafeAreaProvider.m in Sources */,
0C7844E327C02CEE001807FB /* RNCSafeAreaShadowView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
58B511ED1A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
58B511EE1A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
58B511F01A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
"$(SRCROOT)/../../react-native/React/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RNCSafeAreaContext;
SKIP_INSTALL = YES;
};
name = Debug;
};
58B511F11A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../../React/**",
"$(SRCROOT)/../../react-native/React/**",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RNCSafeAreaContext;
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNSafeAreaContext" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511ED1A9E6C8500147676 /* Debug */,
58B511EE1A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCSafeAreaContext" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511F01A9E6C8500147676 /* Debug */,
58B511F11A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
}

View File

@@ -0,0 +1,59 @@
import { jest } from '@jest/globals';
import React, { useContext } from 'react';
import type { Metrics } from '../src/SafeArea.types';
import type {
SafeAreaProviderProps,
SafeAreaInsetsContext,
SafeAreaFrameContext,
} from '../src/SafeAreaContext';
const MOCK_INITIAL_METRICS: Metrics = {
frame: {
width: 320,
height: 640,
x: 0,
y: 0,
},
insets: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
};
const RNSafeAreaContext = jest.requireActual<{
SafeAreaInsetsContext: typeof SafeAreaInsetsContext;
SafeAreaFrameContext: typeof SafeAreaFrameContext;
}>('react-native-safe-area-context');
export default {
...RNSafeAreaContext,
initialWindowMetrics: MOCK_INITIAL_METRICS,
useSafeAreaInsets: jest.fn(() => {
return (
useContext(RNSafeAreaContext.SafeAreaInsetsContext) ??
MOCK_INITIAL_METRICS.insets
);
}),
useSafeAreaFrame: jest.fn(() => {
return (
useContext(RNSafeAreaContext.SafeAreaFrameContext) ??
MOCK_INITIAL_METRICS.frame
);
}),
// Provide a simpler implementation with default values.
SafeAreaProvider: ({ children, initialMetrics }: SafeAreaProviderProps) => {
return (
<RNSafeAreaContext.SafeAreaFrameContext.Provider
value={initialMetrics?.frame ?? MOCK_INITIAL_METRICS.frame}
>
<RNSafeAreaContext.SafeAreaInsetsContext.Provider
value={initialMetrics?.insets ?? MOCK_INITIAL_METRICS.insets}
>
{children}
</RNSafeAreaContext.SafeAreaInsetsContext.Provider>
</RNSafeAreaContext.SafeAreaFrameContext.Provider>
);
},
};

View File

@@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CompatNativeSafeAreaProvider = CompatNativeSafeAreaProvider;
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function CompatNativeSafeAreaProvider({
children,
style,
onInsetsChange
}) {
const window = (0, _reactNative.useWindowDimensions)();
React.useEffect(() => {
const insets = {
top: 0,
bottom: 0,
left: 0,
right: 0
};
const frame = {
x: 0,
y: 0,
width: window.width,
height: window.height
};
// @ts-ignore: missing properties
onInsetsChange({
nativeEvent: {
insets,
frame
}
});
}, [onInsetsChange, window.height, window.width]);
return /*#__PURE__*/React.createElement(_reactNative.View, {
style: style
}, children);
}
//# sourceMappingURL=CompatNativeSafeAreaProvider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["React","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","CompatNativeSafeAreaProvider","children","style","onInsetsChange","window","useWindowDimensions","useEffect","insets","top","bottom","left","right","frame","x","y","width","height","nativeEvent","createElement","View"],"sourceRoot":"../../src","sources":["CompatNativeSafeAreaProvider.tsx"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAAyD,SAAAD,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAL,uBAAA,YAAAA,CAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAGlD,SAASkB,4BAA4BA,CAAC;EAC3CC,QAAQ;EACRC,KAAK;EACLC;AAC2B,CAAC,EAAE;EAC9B,MAAMC,MAAM,GAAG,IAAAC,gCAAmB,EAAC,CAAC;EACpC5B,KAAK,CAAC6B,SAAS,CAAC,MAAM;IACpB,MAAMC,MAAM,GAAG;MACbC,GAAG,EAAE,CAAC;MACNC,MAAM,EAAE,CAAC;MACTC,IAAI,EAAE,CAAC;MACPC,KAAK,EAAE;IACT,CAAC;IACD,MAAMC,KAAK,GAAG;MACZC,CAAC,EAAE,CAAC;MACJC,CAAC,EAAE,CAAC;MACJC,KAAK,EAAEX,MAAM,CAACW,KAAK;MACnBC,MAAM,EAAEZ,MAAM,CAACY;IACjB,CAAC;IACD;IACAb,cAAc,CAAC;MAAEc,WAAW,EAAE;QAAEV,MAAM;QAAEK;MAAM;IAAE,CAAC,CAAC;EACpD,CAAC,EAAE,CAACT,cAAc,EAAEC,MAAM,CAACY,MAAM,EAAEZ,MAAM,CAACW,KAAK,CAAC,CAAC;EACjD,oBAAOtC,KAAA,CAAAyC,aAAA,CAACtC,YAAA,CAAAuC,IAAI;IAACjB,KAAK,EAAEA;EAAM,GAAED,QAAe,CAAC;AAC9C","ignoreList":[]}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.initialWindowSafeAreaInsets = exports.initialWindowMetrics = void 0;
const initialWindowMetrics = exports.initialWindowMetrics = null;
/**
* @deprecated
*/
const initialWindowSafeAreaInsets = exports.initialWindowSafeAreaInsets = null;
//# sourceMappingURL=InitialWindow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["initialWindowMetrics","exports","initialWindowSafeAreaInsets"],"sourceRoot":"../../src","sources":["InitialWindow.ts"],"mappings":";;;;;;AAEO,MAAMA,oBAAoC,GAAAC,OAAA,CAAAD,oBAAA,GAAG,IAAI;;AAExD;AACA;AACA;AACO,MAAME,2BAA8C,GAAAD,OAAA,CAAAC,2BAAA,GAAG,IAAI","ignoreList":[]}

View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.initialWindowSafeAreaInsets = exports.initialWindowMetrics = void 0;
var _NativeSafeAreaContext = _interopRequireDefault(require("./specs/NativeSafeAreaContext"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const initialWindowMetrics = exports.initialWindowMetrics = _NativeSafeAreaContext.default?.getConstants?.()?.initialWindowMetrics ?? null;
/**
* @deprecated
*/
const initialWindowSafeAreaInsets = exports.initialWindowSafeAreaInsets = initialWindowMetrics?.insets;
//# sourceMappingURL=InitialWindow.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_NativeSafeAreaContext","_interopRequireDefault","require","e","__esModule","default","initialWindowMetrics","exports","NativeSafeAreaContext","getConstants","initialWindowSafeAreaInsets","insets"],"sourceRoot":"../../src","sources":["InitialWindow.native.ts"],"mappings":";;;;;;AACA,IAAAA,sBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAkE,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE3D,MAAMG,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,GAAIE,8BAAqB,EAAEC,YAAY,GAAG,CAAC,EACxEH,oBAAoB,IAAI,IAAuB;;AAEnD;AACA;AACA;AACO,MAAMI,2BAA2B,GAAAH,OAAA,CAAAG,2BAAA,GAAGJ,oBAAoB,EAAEK,MAAM","ignoreList":[]}

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NativeSafeAreaProvider", {
enumerable: true,
get: function () {
return _NativeSafeAreaProvider.default;
}
});
var _NativeSafeAreaProvider = _interopRequireDefault(require("./specs/NativeSafeAreaProvider"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
//# sourceMappingURL=NativeSafeAreaProvider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_NativeSafeAreaProvider","_interopRequireDefault","require","e","__esModule","default"],"sourceRoot":"../../src","sources":["NativeSafeAreaProvider.tsx"],"mappings":";;;;;;;;;;;AAAA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAoE,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA","ignoreList":[]}

View File

@@ -0,0 +1,133 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NativeSafeAreaProvider = NativeSafeAreaProvider;
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/* eslint-env browser */
/**
* TODO:
* Currently insets and frame are based on the window and are not
* relative to the provider view. This is inconsistent with iOS and Android.
* However in most cases if the provider view covers the screen this is not
* an issue.
*/
const CSSTransitions = {
WebkitTransition: 'webkitTransitionEnd',
Transition: 'transitionEnd',
MozTransition: 'transitionend',
MSTransition: 'msTransitionEnd',
OTransition: 'oTransitionEnd'
};
function NativeSafeAreaProvider({
children,
style,
onInsetsChange
}) {
React.useEffect(() => {
// Skip for SSR.
if (typeof document === 'undefined') {
return;
}
const element = createContextElement();
document.body.appendChild(element);
const onEnd = () => {
const {
paddingTop,
paddingBottom,
paddingLeft,
paddingRight
} = window.getComputedStyle(element);
const insets = {
top: paddingTop ? parseInt(paddingTop, 10) : 0,
bottom: paddingBottom ? parseInt(paddingBottom, 10) : 0,
left: paddingLeft ? parseInt(paddingLeft, 10) : 0,
right: paddingRight ? parseInt(paddingRight, 10) : 0
};
const frame = {
x: 0,
y: 0,
width: document.documentElement.offsetWidth,
height: document.documentElement.offsetHeight
};
// @ts-ignore: missing properties
onInsetsChange({
nativeEvent: {
insets,
frame
}
});
};
element.addEventListener(getSupportedTransitionEvent(), onEnd);
onEnd();
return () => {
document.body.removeChild(element);
element.removeEventListener(getSupportedTransitionEvent(), onEnd);
};
}, [onInsetsChange]);
return /*#__PURE__*/React.createElement(_reactNative.View, {
style: style
}, children);
}
let _supportedTransitionEvent = null;
function getSupportedTransitionEvent() {
if (_supportedTransitionEvent != null) {
return _supportedTransitionEvent;
}
const element = document.createElement('invalidtype');
_supportedTransitionEvent = CSSTransitions.Transition;
for (const key in CSSTransitions) {
if (element.style[key] !== undefined) {
_supportedTransitionEvent = CSSTransitions[key];
break;
}
}
return _supportedTransitionEvent;
}
let _supportedEnv = null;
function getSupportedEnv() {
if (_supportedEnv !== null) {
return _supportedEnv;
}
const {
CSS
} = window;
if (CSS && CSS.supports && CSS.supports('top: constant(safe-area-inset-top)')) {
_supportedEnv = 'constant';
} else {
_supportedEnv = 'env';
}
return _supportedEnv;
}
function getInset(side) {
return `${getSupportedEnv()}(safe-area-inset-${side})`;
}
function createContextElement() {
const element = document.createElement('div');
const {
style
} = element;
style.position = 'fixed';
style.left = '0';
style.top = '0';
style.width = '0';
style.height = '0';
style.zIndex = '-1';
style.overflow = 'hidden';
style.visibility = 'hidden';
// Bacon: Anything faster than this and the callback will be invoked too early with the wrong insets
style.transitionDuration = '0.05s';
style.transitionProperty = 'padding';
style.transitionDelay = '0s';
style.paddingTop = getInset('top');
style.paddingBottom = getInset('bottom');
style.paddingLeft = getInset('left');
style.paddingRight = getInset('right');
return element;
}
//# sourceMappingURL=NativeSafeAreaProvider.web.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NativeSafeAreaProvider", {
enumerable: true,
get: function () {
return _CompatNativeSafeAreaProvider.CompatNativeSafeAreaProvider;
}
});
var _CompatNativeSafeAreaProvider = require("./CompatNativeSafeAreaProvider");
//# sourceMappingURL=NativeSafeAreaProvider.windows.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_CompatNativeSafeAreaProvider","require"],"sourceRoot":"../../src","sources":["NativeSafeAreaProvider.windows.tsx"],"mappings":";;;;;;;;;;;AAAA,IAAAA,6BAAA,GAAAC,OAAA","ignoreList":[]}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=SafeArea.types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sourceRoot":"../../src","sources":["SafeArea.types.ts"],"mappings":"","ignoreList":[]}

View File

@@ -0,0 +1,145 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SafeAreaInsetsContext = exports.SafeAreaFrameContext = exports.SafeAreaContext = exports.SafeAreaConsumer = void 0;
exports.SafeAreaListener = SafeAreaListener;
exports.SafeAreaProvider = SafeAreaProvider;
exports.useSafeArea = useSafeArea;
exports.useSafeAreaFrame = useSafeAreaFrame;
exports.useSafeAreaInsets = useSafeAreaInsets;
exports.withSafeAreaInsets = withSafeAreaInsets;
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _NativeSafeAreaProvider = require("./NativeSafeAreaProvider");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const isDev = process.env.NODE_ENV !== 'production';
const SafeAreaInsetsContext = exports.SafeAreaInsetsContext = /*#__PURE__*/React.createContext(null);
if (isDev) {
SafeAreaInsetsContext.displayName = 'SafeAreaInsetsContext';
}
const SafeAreaFrameContext = exports.SafeAreaFrameContext = /*#__PURE__*/React.createContext(null);
if (isDev) {
SafeAreaFrameContext.displayName = 'SafeAreaFrameContext';
}
function SafeAreaProvider({
children,
initialMetrics,
initialSafeAreaInsets,
style,
...others
}) {
const parentInsets = useParentSafeAreaInsets();
const parentFrame = useParentSafeAreaFrame();
const [insets, setInsets] = React.useState(initialMetrics?.insets ?? initialSafeAreaInsets ?? parentInsets ?? null);
const [frame, setFrame] = React.useState(initialMetrics?.frame ?? parentFrame ?? {
// Backwards compat so we render anyway if we don't have frame.
x: 0,
y: 0,
width: _reactNative.Dimensions.get('window').width,
height: _reactNative.Dimensions.get('window').height
});
const onInsetsChange = React.useCallback(event => {
const {
nativeEvent: {
frame: nextFrame,
insets: nextInsets
}
} = event;
setFrame(curFrame => {
if (
// Backwards compat with old native code that won't send frame.
nextFrame && (nextFrame.height !== curFrame.height || nextFrame.width !== curFrame.width || nextFrame.x !== curFrame.x || nextFrame.y !== curFrame.y)) {
return nextFrame;
} else {
return curFrame;
}
});
setInsets(curInsets => {
if (!curInsets || nextInsets.bottom !== curInsets.bottom || nextInsets.left !== curInsets.left || nextInsets.right !== curInsets.right || nextInsets.top !== curInsets.top) {
return nextInsets;
} else {
return curInsets;
}
});
}, []);
return /*#__PURE__*/React.createElement(_NativeSafeAreaProvider.NativeSafeAreaProvider, _extends({
style: [styles.fill, style],
onInsetsChange: onInsetsChange
}, others), insets != null ? /*#__PURE__*/React.createElement(SafeAreaFrameContext.Provider, {
value: frame
}, /*#__PURE__*/React.createElement(SafeAreaInsetsContext.Provider, {
value: insets
}, children)) : null);
}
function SafeAreaListener({
onChange,
style,
children,
...others
}) {
return /*#__PURE__*/React.createElement(_NativeSafeAreaProvider.NativeSafeAreaProvider, _extends({}, others, {
style: [styles.fill, style],
onInsetsChange: e => {
onChange({
insets: e.nativeEvent.insets,
frame: e.nativeEvent.frame
});
}
}), children);
}
const styles = _reactNative.StyleSheet.create({
fill: {
flex: 1
}
});
function useParentSafeAreaInsets() {
return React.useContext(SafeAreaInsetsContext);
}
function useParentSafeAreaFrame() {
return React.useContext(SafeAreaFrameContext);
}
const NO_INSETS_ERROR = 'No safe area value available. Make sure you are rendering `<SafeAreaProvider>` at the top of your app.';
function useSafeAreaInsets() {
const insets = React.useContext(SafeAreaInsetsContext);
if (insets == null) {
throw new Error(NO_INSETS_ERROR);
}
return insets;
}
function useSafeAreaFrame() {
const frame = React.useContext(SafeAreaFrameContext);
if (frame == null) {
throw new Error(NO_INSETS_ERROR);
}
return frame;
}
function withSafeAreaInsets(WrappedComponent) {
return /*#__PURE__*/React.forwardRef((props, ref) => {
const insets = useSafeAreaInsets();
return /*#__PURE__*/React.createElement(WrappedComponent, _extends({}, props, {
insets: insets,
ref: ref
}));
});
}
/**
* @deprecated
*/
function useSafeArea() {
return useSafeAreaInsets();
}
/**
* @deprecated
*/
const SafeAreaConsumer = exports.SafeAreaConsumer = SafeAreaInsetsContext.Consumer;
/**
* @deprecated
*/
const SafeAreaContext = exports.SafeAreaContext = SafeAreaInsetsContext;
//# sourceMappingURL=SafeAreaContext.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SafeAreaView = void 0;
var _react = _interopRequireWildcard(require("react"));
var React = _react;
var _NativeSafeAreaView = _interopRequireDefault(require("./specs/NativeSafeAreaView"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const defaultEdges = {
top: 'additive',
left: 'additive',
bottom: 'additive',
right: 'additive'
};
const SafeAreaView = exports.SafeAreaView = /*#__PURE__*/React.forwardRef(({
edges,
...props
}, ref) => {
const nativeEdges = (0, _react.useMemo)(() => {
if (edges == null) {
return defaultEdges;
}
const edgesObj = Array.isArray(edges) ? edges.reduce((acc, edge) => {
acc[edge] = 'additive';
return acc;
}, {}) :
// ts has trouble with refining readonly arrays.
edges;
// make sure that we always pass all edges, required for fabric
const requiredEdges = {
top: edgesObj.top ?? 'off',
right: edgesObj.right ?? 'off',
bottom: edgesObj.bottom ?? 'off',
left: edgesObj.left ?? 'off'
};
return requiredEdges;
}, [edges]);
return /*#__PURE__*/React.createElement(_NativeSafeAreaView.default, _extends({}, props, {
edges: nativeEdges,
ref: ref
}));
});
//# sourceMappingURL=SafeAreaView.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_react","_interopRequireWildcard","require","React","_NativeSafeAreaView","_interopRequireDefault","e","__esModule","default","t","WeakMap","r","n","o","i","f","__proto__","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","defaultEdges","top","left","bottom","right","SafeAreaView","exports","forwardRef","edges","props","ref","nativeEdges","useMemo","edgesObj","Array","isArray","reduce","acc","edge","requiredEdges","createElement"],"sourceRoot":"../../src","sources":["SafeAreaView.tsx"],"mappings":"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","ignoreList":[]}

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SafeAreaView = void 0;
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _SafeAreaContext = require("./SafeAreaContext");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
const defaultEdges = {
top: 'additive',
left: 'additive',
bottom: 'additive',
right: 'additive'
};
function getEdgeValue(inset, current, mode) {
switch (mode) {
case 'off':
return current;
case 'maximum':
return Math.max(current, inset);
case 'additive':
default:
return current + inset;
}
}
const SafeAreaView = exports.SafeAreaView = /*#__PURE__*/React.forwardRef(({
style = {},
mode,
edges,
...rest
}, ref) => {
const insets = (0, _SafeAreaContext.useSafeAreaInsets)();
const edgesRecord = React.useMemo(() => {
if (edges == null) {
return defaultEdges;
}
return Array.isArray(edges) ? edges.reduce((acc, edge) => {
acc[edge] = 'additive';
return acc;
}, {}) :
// ts has trouble with refining readonly arrays.
edges;
}, [edges]);
const appliedStyle = React.useMemo(() => {
const flatStyle = _reactNative.StyleSheet.flatten(style);
if (mode === 'margin') {
const {
margin = 0,
marginVertical = margin,
marginHorizontal = margin,
marginTop = marginVertical,
marginRight = marginHorizontal,
marginBottom = marginVertical,
marginLeft = marginHorizontal
} = flatStyle;
const marginStyle = {
marginTop: getEdgeValue(insets.top, marginTop, edgesRecord.top),
marginRight: getEdgeValue(insets.right, marginRight, edgesRecord.right),
marginBottom: getEdgeValue(insets.bottom, marginBottom, edgesRecord.bottom),
marginLeft: getEdgeValue(insets.left, marginLeft, edgesRecord.left)
};
return [style, marginStyle];
} else {
const {
padding = 0,
paddingVertical = padding,
paddingHorizontal = padding,
paddingTop = paddingVertical,
paddingRight = paddingHorizontal,
paddingBottom = paddingVertical,
paddingLeft = paddingHorizontal
} = flatStyle;
const paddingStyle = {
paddingTop: getEdgeValue(insets.top, paddingTop, edgesRecord.top),
paddingRight: getEdgeValue(insets.right, paddingRight, edgesRecord.right),
paddingBottom: getEdgeValue(insets.bottom, paddingBottom, edgesRecord.bottom),
paddingLeft: getEdgeValue(insets.left, paddingLeft, edgesRecord.left)
};
return [style, paddingStyle];
}
}, [edgesRecord.bottom, edgesRecord.left, edgesRecord.right, edgesRecord.top, insets.bottom, insets.left, insets.right, insets.top, mode, style]);
return /*#__PURE__*/React.createElement(_reactNative.View, _extends({
style: appliedStyle
}, rest, {
ref: ref
}));
});
//# sourceMappingURL=SafeAreaView.web.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["React","_interopRequireWildcard","require","_reactNative","_SafeAreaContext","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","defaultEdges","top","left","bottom","right","getEdgeValue","inset","current","mode","Math","max","SafeAreaView","exports","forwardRef","style","edges","rest","ref","insets","useSafeAreaInsets","edgesRecord","useMemo","Array","isArray","reduce","acc","edge","appliedStyle","flatStyle","StyleSheet","flatten","margin","marginVertical","marginHorizontal","marginTop","marginRight","marginBottom","marginLeft","marginStyle","padding","paddingVertical","paddingHorizontal","paddingTop","paddingRight","paddingBottom","paddingLeft","paddingStyle","createElement","View"],"sourceRoot":"../../src","sources":["SafeAreaView.web.tsx"],"mappings":"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","ignoreList":[]}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.SafeAreaView = void 0;
var _reactNative = require("react-native");
const SafeAreaView = exports.SafeAreaView = _reactNative.View;
//# sourceMappingURL=SafeAreaView.windows.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_reactNative","require","SafeAreaView","exports","View"],"sourceRoot":"../../src","sources":["SafeAreaView.windows.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAGO,MAAMC,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAGE,iBAA6C","ignoreList":[]}

View File

@@ -0,0 +1,51 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _SafeAreaContext = require("./SafeAreaContext");
Object.keys(_SafeAreaContext).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _SafeAreaContext[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _SafeAreaContext[key];
}
});
});
var _SafeAreaView = require("./SafeAreaView");
Object.keys(_SafeAreaView).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _SafeAreaView[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _SafeAreaView[key];
}
});
});
var _InitialWindow = require("./InitialWindow");
Object.keys(_InitialWindow).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _InitialWindow[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _InitialWindow[key];
}
});
});
var _SafeArea = require("./SafeArea.types");
Object.keys(_SafeArea).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (key in exports && exports[key] === _SafeArea[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _SafeArea[key];
}
});
});
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["Object","defineProperty","exports","value","_SafeAreaContext","require","keys","forEach","key","enumerable","get","_SafeAreaView","_InitialWindow","_SafeArea"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";AAAA,YAAY;;AAACA,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAEb,IAAAC,gBAAA,GAAAC,OAAA;AAAAL,MAAA,CAAAM,IAAA,CAAAF,gBAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAN,OAAA,IAAAA,OAAA,CAAAM,GAAA,MAAAJ,gBAAA,CAAAI,GAAA;EAAAR,MAAA,CAAAC,cAAA,CAAAC,OAAA,EAAAM,GAAA;IAAAC,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAN,gBAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AACA,IAAAG,aAAA,GAAAN,OAAA;AAAAL,MAAA,CAAAM,IAAA,CAAAK,aAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAN,OAAA,IAAAA,OAAA,CAAAM,GAAA,MAAAG,aAAA,CAAAH,GAAA;EAAAR,MAAA,CAAAC,cAAA,CAAAC,OAAA,EAAAM,GAAA;IAAAC,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,aAAA,CAAAH,GAAA;IAAA;EAAA;AAAA;AACA,IAAAI,cAAA,GAAAP,OAAA;AAAAL,MAAA,CAAAM,IAAA,CAAAM,cAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAN,OAAA,IAAAA,OAAA,CAAAM,GAAA,MAAAI,cAAA,CAAAJ,GAAA;EAAAR,MAAA,CAAAC,cAAA,CAAAC,OAAA,EAAAM,GAAA;IAAAC,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAE,cAAA,CAAAJ,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,SAAA,GAAAR,OAAA;AAAAL,MAAA,CAAAM,IAAA,CAAAO,SAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAN,OAAA,IAAAA,OAAA,CAAAM,GAAA,MAAAK,SAAA,CAAAL,GAAA;EAAAR,MAAA,CAAAC,cAAA,CAAAC,OAAA,EAAAM,GAAA;IAAAC,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAG,SAAA,CAAAL,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _reactNative = require("react-native");
var _default = exports.default = _reactNative.TurboModuleRegistry.get('RNCSafeAreaContext');
//# sourceMappingURL=NativeSafeAreaContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","get"],"sourceRoot":"../../../src","sources":["specs/NativeSafeAreaContext.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAAgE,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAsBjDC,gCAAmB,CAACC,GAAG,CAAO,oBAAoB,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _codegenNativeComponent = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeComponent"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _codegenNativeComponent.default)('RNCSafeAreaProvider');
//# sourceMappingURL=NativeSafeAreaProvider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","e","__esModule","default","_default","exports","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/NativeSafeAreaProvider.ts"],"mappings":";;;;;;AAIA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA6F,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAsB9E,IAAAG,+BAAsB,EACnC,qBACF,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _codegenNativeComponent = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeComponent"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _codegenNativeComponent.default)('RNCSafeAreaView', {
interfaceOnly: true
});
//# sourceMappingURL=NativeSafeAreaView.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","e","__esModule","default","_default","exports","codegenNativeComponent","interfaceOnly"],"sourceRoot":"../../../src","sources":["specs/NativeSafeAreaView.ts"],"mappings":";;;;;;AAAA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA6F,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAc9E,IAAAG,+BAAsB,EAAc,iBAAiB,EAAE;EACpEC,aAAa,EAAE;AACjB,CAAC,CAAC","ignoreList":[]}

View File

@@ -0,0 +1,34 @@
import * as React from 'react';
import { useWindowDimensions, View } from 'react-native';
export function CompatNativeSafeAreaProvider({
children,
style,
onInsetsChange
}) {
const window = useWindowDimensions();
React.useEffect(() => {
const insets = {
top: 0,
bottom: 0,
left: 0,
right: 0
};
const frame = {
x: 0,
y: 0,
width: window.width,
height: window.height
};
// @ts-ignore: missing properties
onInsetsChange({
nativeEvent: {
insets,
frame
}
});
}, [onInsetsChange, window.height, window.width]);
return /*#__PURE__*/React.createElement(View, {
style: style
}, children);
}
//# sourceMappingURL=CompatNativeSafeAreaProvider.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["React","useWindowDimensions","View","CompatNativeSafeAreaProvider","children","style","onInsetsChange","window","useEffect","insets","top","bottom","left","right","frame","x","y","width","height","nativeEvent","createElement"],"sourceRoot":"../../src","sources":["CompatNativeSafeAreaProvider.tsx"],"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,mBAAmB,EAAEC,IAAI,QAAQ,cAAc;AAGxD,OAAO,SAASC,4BAA4BA,CAAC;EAC3CC,QAAQ;EACRC,KAAK;EACLC;AAC2B,CAAC,EAAE;EAC9B,MAAMC,MAAM,GAAGN,mBAAmB,CAAC,CAAC;EACpCD,KAAK,CAACQ,SAAS,CAAC,MAAM;IACpB,MAAMC,MAAM,GAAG;MACbC,GAAG,EAAE,CAAC;MACNC,MAAM,EAAE,CAAC;MACTC,IAAI,EAAE,CAAC;MACPC,KAAK,EAAE;IACT,CAAC;IACD,MAAMC,KAAK,GAAG;MACZC,CAAC,EAAE,CAAC;MACJC,CAAC,EAAE,CAAC;MACJC,KAAK,EAAEV,MAAM,CAACU,KAAK;MACnBC,MAAM,EAAEX,MAAM,CAACW;IACjB,CAAC;IACD;IACAZ,cAAc,CAAC;MAAEa,WAAW,EAAE;QAAEV,MAAM;QAAEK;MAAM;IAAE,CAAC,CAAC;EACpD,CAAC,EAAE,CAACR,cAAc,EAAEC,MAAM,CAACW,MAAM,EAAEX,MAAM,CAACU,KAAK,CAAC,CAAC;EACjD,oBAAOjB,KAAA,CAAAoB,aAAA,CAAClB,IAAI;IAACG,KAAK,EAAEA;EAAM,GAAED,QAAe,CAAC;AAC9C","ignoreList":[]}

View File

@@ -0,0 +1,7 @@
export const initialWindowMetrics = null;
/**
* @deprecated
*/
export const initialWindowSafeAreaInsets = null;
//# sourceMappingURL=InitialWindow.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["initialWindowMetrics","initialWindowSafeAreaInsets"],"sourceRoot":"../../src","sources":["InitialWindow.ts"],"mappings":"AAEA,OAAO,MAAMA,oBAAoC,GAAG,IAAI;;AAExD;AACA;AACA;AACA,OAAO,MAAMC,2BAA8C,GAAG,IAAI","ignoreList":[]}

Some files were not shown because too many files have changed in this diff Show More