update: add minimal3 frame
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2015-present, Facebook, Inc.
|
||||
|
||||
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.
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
# React Native `MaskedView`
|
||||
|
||||
[![Build Status][build-badge]][build]
|
||||
[![Version][version-badge]][package]
|
||||
[![MIT License][license-badge]][license]
|
||||
[![Lean Core Badge][lean-core-badge]][lean-core-issue]
|
||||
|
||||
Provides a React component that renders a masked view.
|
||||
|
||||
## Platforms Supported
|
||||
|
||||
- [x] iOS
|
||||
- [x] Android
|
||||
- [ ] Web
|
||||
|
||||
## Getting Started
|
||||
|
||||
```sh
|
||||
yarn add @react-native-masked-view/masked-view
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install --save @react-native-masked-view/masked-view
|
||||
```
|
||||
|
||||
### Using React Native >= 0.60
|
||||
|
||||
Linking the package manually is not required anymore with [Autolinking](https://github.com/react-native-masked-view/cli/blob/master/docs/autolinking.md).
|
||||
|
||||
Remember to install the pod with:
|
||||
|
||||
```sh
|
||||
npx pod-install
|
||||
```
|
||||
|
||||
### Using React Native < 0.60
|
||||
|
||||
You then need to link the native parts of the library for the platforms you are using. The easiest way to link the library is using the CLI tool by running this command from the root of your project:
|
||||
|
||||
```sh
|
||||
react-native link @react-native-masked-view/masked-view
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import the `MaskedView` component from `@react-native-masked-view/masked-view` and use it like so:
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import MaskedView from '@react-native-masked-view/masked-view';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<MaskedView
|
||||
style={{ flex: 1, flexDirection: 'row', height: '100%' }}
|
||||
maskElement={
|
||||
<View
|
||||
style={{
|
||||
// Transparent background because mask is based off alpha channel.
|
||||
backgroundColor: 'transparent',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 60,
|
||||
color: 'black',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
>
|
||||
Basic Mask
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
>
|
||||
{/* Shows behind the mask, you can put anything here, such as an image */}
|
||||
<View style={{ flex: 1, height: '100%', backgroundColor: '#324376' }} />
|
||||
<View style={{ flex: 1, height: '100%', backgroundColor: '#F5DD90' }} />
|
||||
<View style={{ flex: 1, height: '100%', backgroundColor: '#F76C5E' }} />
|
||||
<View style={{ flex: 1, height: '100%', backgroundColor: '#e1e1e1' }} />
|
||||
</MaskedView>
|
||||
);
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
|
||||
The following image demonstrates that you can put almost anything behind the mask. The three examples shown are masked `<View>`, `<Text>`, and `<Image>`.
|
||||
|
||||
<div align="center"><img src="img/example.png" width="200"></img></div>
|
||||
|
||||
### Props
|
||||
|
||||
- [View props...](https://github.com/facebook/react-native-website/blob/master/docs/view.md#props)
|
||||
|
||||
- [`maskElement`](#maskelement)
|
||||
|
||||
- [`androidRenderingMode`](#androidrenderingmode)
|
||||
|
||||
### Reference
|
||||
|
||||
### `maskElement`
|
||||
|
||||
| Type | Required |
|
||||
| ------- | -------- |
|
||||
| element | Yes |
|
||||
|
||||
### `androidRenderingMode`
|
||||
|
||||
By default `hardware` rendering mode will be used for best performance, however if you need to animate your `maskElement` then you’ll need to switch to `software` to get your mask to update. This prop only affects Android.
|
||||
|
||||
| Type | Required | Default |
|
||||
| ---------------------- | -------- | ---------- |
|
||||
| `software`, `hardware` | No | `hardware` |
|
||||
|
||||
<!-- badges -->
|
||||
|
||||
[build-badge]: https://github.com/react-native-masked-view/masked-view/workflows/Build/badge.svg
|
||||
[build]: https://github.com/react-native-masked-view/masked-view/actions
|
||||
[version-badge]: https://img.shields.io/npm/v/@react-native-masked-view/masked-view.svg?style=flat-square
|
||||
[package]: https://www.npmjs.com/package/@react-native-masked-view/masked-view
|
||||
[license-badge]: https://img.shields.io/npm/l/@react-native-masked-view/masked-view.svg?style=flat-square
|
||||
[license]: https://opensource.org/licenses/MIT
|
||||
[lean-core-badge]: https://img.shields.io/badge/Lean%20Core-Extracted-brightgreen.svg?style=flat-square
|
||||
[lean-core-issue]: https://github.com/facebook/react-native/issues/23313
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
require 'json'
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "RNCMaskedView"
|
||||
s.version = package['version']
|
||||
s.summary = package['description']
|
||||
s.license = package['license']
|
||||
|
||||
s.authors = package['author']
|
||||
s.homepage = package['homepage']
|
||||
s.platforms = { :ios => "9.0", :tvos => "9.0" }
|
||||
|
||||
s.source = { :git => "https://github.com/react-native-masked-view/masked-view.git", :tag => "v#{s.version}" }
|
||||
s.source_files = "ios/**/*.{h,m}"
|
||||
|
||||
install_modules_dependencies(s)
|
||||
end
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
def safeExtGet(prop, fallback) {
|
||||
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||
}
|
||||
|
||||
buildscript {
|
||||
if (project == rootProject) {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger()
|
||||
def shouldUseNameSpace = agpVersion >= 7
|
||||
def PACKAGE_PROP = "package=\"org.reactnative.maskedview\""
|
||||
def manifestOutFile = file("${projectDir}/src/main/AndroidManifest.xml")
|
||||
def manifestContent = manifestOutFile.getText()
|
||||
if(shouldUseNameSpace){
|
||||
manifestContent = manifestContent.replaceAll(
|
||||
PACKAGE_PROP,
|
||||
''
|
||||
)
|
||||
} else {
|
||||
if(!manifestContent.contains("$PACKAGE_PROP")){
|
||||
manifestContent = manifestContent.replace(
|
||||
'<manifest',
|
||||
"<manifest $PACKAGE_PROP "
|
||||
)
|
||||
}
|
||||
}
|
||||
manifestContent.replaceAll(" ", " ")
|
||||
manifestOutFile.write(manifestContent)
|
||||
|
||||
android {
|
||||
compileSdkVersion safeExtGet('compileSdkVersion', 28)
|
||||
|
||||
if(shouldUseNameSpace){
|
||||
namespace = "org.reactnative.maskedview"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion safeExtGet('minSdkVersion', 16)
|
||||
targetSdkVersion safeExtGet('targetSdkVersion', 28)
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs = ['src/main/java']
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
warning 'InvalidPackage'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
maven { url "https://jitpack.io" }
|
||||
mavenCentral()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$rootDir/../node_modules/react-native/android"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.facebook.react:react-native:+'
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
<manifest package="org.reactnative.maskedview" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
</manifest>
|
||||
Generated
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Generated
Vendored
+112
@@ -0,0 +1,112 @@
|
||||
package org.reactnative.maskedview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.views.view.ReactViewGroup;
|
||||
|
||||
public class RNCMaskedView extends ReactViewGroup {
|
||||
private static final String TAG = "RNCMaskedView";
|
||||
|
||||
private Bitmap mBitmapMask = null;
|
||||
private boolean mBitmapMaskInvalidated = false;
|
||||
private Paint mPaint;
|
||||
private PorterDuffXfermode mPorterDuffXferMode;
|
||||
private int mRenderingMode = View.LAYER_TYPE_HARDWARE;
|
||||
|
||||
public RNCMaskedView(Context context) {
|
||||
super(context);
|
||||
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mPorterDuffXferMode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (mBitmapMaskInvalidated) {
|
||||
// redraw mask element to support animated elements
|
||||
updateBitmapMask();
|
||||
|
||||
mBitmapMaskInvalidated = false;
|
||||
}
|
||||
|
||||
// draw the mask
|
||||
if (mBitmapMask != null) {
|
||||
setLayerType(mRenderingMode, mPaint);
|
||||
mPaint.setXfermode(mPorterDuffXferMode);
|
||||
canvas.drawBitmap(mBitmapMask, 0, 0, mPaint);
|
||||
mPaint.setXfermode(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDescendantInvalidated(View child, View target) {
|
||||
super.onDescendantInvalidated(child, target);
|
||||
|
||||
if (!mBitmapMaskInvalidated) {
|
||||
View maskView = getChildAt(0);
|
||||
if (maskView != null) {
|
||||
if (maskView.equals(child)) {
|
||||
mBitmapMaskInvalidated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
|
||||
if (changed) {
|
||||
mBitmapMaskInvalidated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mBitmapMaskInvalidated = true;
|
||||
}
|
||||
|
||||
private void updateBitmapMask() {
|
||||
View maskView = getChildAt(0);
|
||||
if (maskView != null) {
|
||||
maskView.setVisibility(View.VISIBLE);
|
||||
if (this.mBitmapMask != null) {
|
||||
this.mBitmapMask.recycle();
|
||||
}
|
||||
this.mBitmapMask = getBitmapFromView(maskView);
|
||||
maskView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public static Bitmap getBitmapFromView(final View view) {
|
||||
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
|
||||
|
||||
if (view.getMeasuredWidth() <= 0 || view.getMeasuredHeight() <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
|
||||
view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
||||
|
||||
final Canvas canvas = new Canvas(bitmap);
|
||||
|
||||
view.draw(canvas);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void setRenderingMode(String renderingMode) {
|
||||
mRenderingMode = renderingMode.equals("software") ? View.LAYER_TYPE_SOFTWARE : View.LAYER_TYPE_HARDWARE;
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
package org.reactnative.maskedview;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.uimanager.SimpleViewManager;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RNCMaskedViewManager extends ViewGroupManager<RNCMaskedView> {
|
||||
private static final String REACT_CLASS = "RNCMaskedView";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RNCMaskedView createViewInstance(ThemedReactContext themedReactContext) {
|
||||
return new RNCMaskedView(themedReactContext);
|
||||
}
|
||||
|
||||
@ReactProp(name = "androidRenderingMode")
|
||||
public void setAndroidRenderingMode(RNCMaskedView view, @Nullable String renderingMode) {
|
||||
if (renderingMode != null) {
|
||||
view.setRenderingMode(renderingMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
package org.reactnative.maskedview;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RNCMaskedViewPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
|
||||
return Arrays.<ViewManager>asList(
|
||||
new RNCMaskedViewManager()
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import MaskedView from './js/MaskedView';
|
||||
|
||||
export default MaskedView;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTView.h>
|
||||
|
||||
@interface RNCMaskedView : RCTView
|
||||
|
||||
@end
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RNCMaskedView.h"
|
||||
|
||||
#import <React/UIView+React.h>
|
||||
|
||||
@implementation RNCMaskedView
|
||||
|
||||
- (void)didUpdateReactSubviews
|
||||
{
|
||||
// RNCMaskedView expects that the first subview rendered is the mask.
|
||||
UIView *maskView = [self.reactSubviews firstObject];
|
||||
self.maskView = maskView;
|
||||
|
||||
// Add the other subviews to the view hierarchy
|
||||
for (NSUInteger i = 1; i < self.reactSubviews.count; i++) {
|
||||
UIView *subview = [self.reactSubviews objectAtIndex:i];
|
||||
[self addSubview:subview];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)displayLayer:(CALayer *)layer
|
||||
{
|
||||
// RCTView uses displayLayer to do border rendering.
|
||||
// We don't need to do that in RNCMaskedView, so we
|
||||
// stub this method and override the default implementation.
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
Vendored
+265
@@ -0,0 +1,265 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2150303C220DFE9200FC1971 /* RNCMaskedViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 2150303B220DFE9200FC1971 /* RNCMaskedViewManager.m */; };
|
||||
B3E7B58A1CC2AC0600A0062D /* RNCMaskedView.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNCMaskedView.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 */
|
||||
134814201AA4EA6300B7C361 /* libRNCMaskedView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNCMaskedView.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2150303A220DFE9200FC1971 /* RNCMaskedViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCMaskedViewManager.h; sourceTree = "<group>"; };
|
||||
2150303B220DFE9200FC1971 /* RNCMaskedViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCMaskedViewManager.m; sourceTree = "<group>"; };
|
||||
B3E7B5881CC2AC0600A0062D /* RNCMaskedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNCMaskedView.h; sourceTree = "<group>"; };
|
||||
B3E7B5891CC2AC0600A0062D /* RNCMaskedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNCMaskedView.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
58B511D81A9E6C8500147676 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
134814211AA4EA7D00B7C361 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
134814201AA4EA6300B7C361 /* libRNCMaskedView.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
58B511D21A9E6C8500147676 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B3E7B5881CC2AC0600A0062D /* RNCMaskedView.h */,
|
||||
2150303A220DFE9200FC1971 /* RNCMaskedViewManager.h */,
|
||||
2150303B220DFE9200FC1971 /* RNCMaskedViewManager.m */,
|
||||
B3E7B5891CC2AC0600A0062D /* RNCMaskedView.m */,
|
||||
134814211AA4EA7D00B7C361 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
58B511DA1A9E6C8500147676 /* RNCMaskedView */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCMaskedView" */;
|
||||
buildPhases = (
|
||||
58B511D71A9E6C8500147676 /* Sources */,
|
||||
58B511D81A9E6C8500147676 /* Frameworks */,
|
||||
58B511D91A9E6C8500147676 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RNCMaskedView;
|
||||
productName = RCTDataManager;
|
||||
productReference = 134814201AA4EA6300B7C361 /* libRNCMaskedView.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
58B511D31A9E6C8500147676 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0830;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
58B511DA1A9E6C8500147676 = {
|
||||
CreatedOnToolsVersion = 6.1.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCMaskedView" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 58B511D21A9E6C8500147676;
|
||||
productRefGroup = 58B511D21A9E6C8500147676;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
58B511DA1A9E6C8500147676 /* RNCMaskedView */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
58B511D71A9E6C8500147676 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B3E7B58A1CC2AC0600A0062D /* RNCMaskedView.m in Sources */,
|
||||
2150303C220DFE9200FC1971 /* RNCMaskedViewManager.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
58B511ED1A9E6C8500147676 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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 = 8.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_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
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 = 8.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 = RNCMaskedView;
|
||||
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 = RNCMaskedView;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNCMaskedView" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511ED1A9E6C8500147676 /* Debug */,
|
||||
58B511EE1A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNCMaskedView" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
58B511F01A9E6C8500147676 /* Debug */,
|
||||
58B511F11A9E6C8500147676 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <React/RCTViewManager.h>
|
||||
|
||||
@interface RNCMaskedViewManager : RCTViewManager
|
||||
|
||||
@end
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RNCMaskedViewManager.h"
|
||||
|
||||
#import "RNCMaskedView.h"
|
||||
|
||||
@implementation RNCMaskedViewManager
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [RNCMaskedView new];
|
||||
}
|
||||
|
||||
@end
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet, requireNativeComponent } from 'react-native';
|
||||
|
||||
const RNCMaskedView = requireNativeComponent<any>('RNCMaskedView');
|
||||
|
||||
import type { MaskedViewProps } from './MaskedViewTypes';
|
||||
|
||||
/**
|
||||
* Renders the child view with a mask specified in the `maskElement` prop.
|
||||
*
|
||||
* ```
|
||||
* import React from 'react';
|
||||
* import { Text, View } from 'react-native';
|
||||
* import MaskedView from 'react-native-masked-view';
|
||||
*
|
||||
* class MyMaskedView extends React.Component {
|
||||
* render() {
|
||||
* return (
|
||||
* <MaskedView
|
||||
* style={{ flex: 1 }}
|
||||
* maskElement={
|
||||
* <View style={styles.maskContainerStyle}>
|
||||
* <Text style={styles.maskTextStyle}>
|
||||
* Basic Mask
|
||||
* </Text>
|
||||
* </View>
|
||||
* }
|
||||
* >
|
||||
* <View style={{ flex: 1, backgroundColor: 'blue' }} />
|
||||
* </MaskedView>
|
||||
* );
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The above example will render a view with a blue background that fills its
|
||||
* parent, and then mask that view with text that says "Basic Mask".
|
||||
*
|
||||
* The alpha channel of the view rendered by the `maskElement` prop determines how
|
||||
* much of the view's content and background shows through. Fully or partially
|
||||
* opaque pixels allow the underlying content to show through but fully
|
||||
* transparent pixels block that content.
|
||||
*
|
||||
*/
|
||||
export default class MaskedView extends React.Component<MaskedViewProps> {
|
||||
_hasWarnedInvalidRenderMask = false;
|
||||
|
||||
render(): React.Node {
|
||||
const { maskElement, children, ...otherViewProps } = this.props;
|
||||
|
||||
if (!React.isValidElement(maskElement)) {
|
||||
if (!this._hasWarnedInvalidRenderMask) {
|
||||
console.warn(
|
||||
'MaskedView: Invalid `maskElement` prop was passed to MaskedView. ' +
|
||||
'Expected a React Element. No mask will render.',
|
||||
);
|
||||
this._hasWarnedInvalidRenderMask = true;
|
||||
}
|
||||
return <View {...otherViewProps}>{children}</View>;
|
||||
}
|
||||
|
||||
return (
|
||||
<RNCMaskedView {...otherViewProps}>
|
||||
<View pointerEvents="none" style={StyleSheet.absoluteFill}>
|
||||
{maskElement}
|
||||
</View>
|
||||
{children}
|
||||
</RNCMaskedView>
|
||||
);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
function MaskedView({ maskElement, ...props }) {
|
||||
return React.createElement(View, props, maskElement);
|
||||
}
|
||||
|
||||
export default MaskedView;
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// @flow
|
||||
import { type Node } from 'react';
|
||||
import { type ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes';
|
||||
|
||||
export type MaskedViewProps = Partial<ViewProps> &
|
||||
$ReadOnly<{|
|
||||
children: Node,
|
||||
/**
|
||||
* Should be a React element to be rendered and applied as the
|
||||
* mask for the child element.
|
||||
*/
|
||||
maskElement: Node,
|
||||
/**
|
||||
* Opt into software rendering to enable animated masks.
|
||||
*/
|
||||
androidRenderingMode?: 'software' | 'hardware',
|
||||
|}>;
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "@react-native-masked-view/masked-view",
|
||||
"description": "React Native MaskedView component",
|
||||
"types": "./types/index.d.ts",
|
||||
"main": "index.js",
|
||||
"author": "Mike Nedosekin <crespo8800@gmail.com>",
|
||||
"license": "MIT",
|
||||
"version": "0.3.2",
|
||||
"homepage": "https://github.com/react-native-masked-view/masked-view#readme",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"react native",
|
||||
"masked-view",
|
||||
"masked view"
|
||||
],
|
||||
"scripts": {
|
||||
"test:flow": "flow check",
|
||||
"test:js": "echo 0",
|
||||
"test:lint": "eslint ./",
|
||||
"test:typescript": "tsc -noEmit",
|
||||
"test:prettier": "prettier --check './**/*.js'"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16",
|
||||
"react-native": ">=0.57"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"android",
|
||||
"ios",
|
||||
"js",
|
||||
"types",
|
||||
"RNCMaskedView.podspec"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@react-native/eslint-config": "^0.76.1",
|
||||
"@types/react-native": "^0.72.8",
|
||||
"eslint": "8",
|
||||
"eslint-plugin-ft-flow": "^3.0.11",
|
||||
"flow-bin": "^0.246.0",
|
||||
"prettier": "^3.3.3",
|
||||
"react-native": "0.75.3",
|
||||
"react-native-test-app": "^3.10.5",
|
||||
"typescript": "5.3.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/react-native-masked-view/masked-view.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/react-native-masked-view/masked-view/issues"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha256.c17d3797fb9a9115bf375e31bfd30058cac6bc9c3b8807a3d8cb2094794b51ca"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// CREDITS: These types are based on the original work made by all the people who contributed to @types/react-native
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactNative from 'react-native';
|
||||
|
||||
type Constructor<T> = new (...args: any[]) => T;
|
||||
|
||||
interface MaskedViewProps extends ReactNative.ViewProps {
|
||||
maskElement: React.ReactElement;
|
||||
androidRenderingMode?: 'software' | 'hardware';
|
||||
}
|
||||
/**
|
||||
* @see https://github.com/react-native-masked-view/masked-view
|
||||
*/
|
||||
declare class MaskedViewComponent extends React.Component<MaskedViewProps> {}
|
||||
declare const MaskedViewBase: Constructor<
|
||||
ReactNative.NativeMethods
|
||||
> &
|
||||
typeof MaskedViewComponent;
|
||||
export default class MaskedView extends MaskedViewBase {}
|
||||
Reference in New Issue
Block a user